[
  {
    "path": ".cursor/commands/opsx-apply.md",
    "content": "---\nname: /opsx-apply\nid: opsx-apply\ncategory: Workflow\ndescription: Implement tasks from an OpenSpec change (Experimental)\n---\n\nImplement tasks from an OpenSpec change.\n\n**Input**: Optionally specify a change name (e.g., `/opsx:apply add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **Select the change**\n\n   If a name is provided, use it. Otherwise:\n   - Infer from conversation context if the user mentioned a change\n   - Auto-select if only one active change exists\n   - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select\n\n   Always announce: \"Using change: <name>\" and how to override (e.g., `/opsx:apply <other>`).\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifact contains the tasks (typically \"tasks\" for spec-driven, check status for others)\n\n3. **Get apply instructions**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns:\n   - Context file paths (varies by schema)\n   - Progress (total, complete, remaining)\n   - Task list with status\n   - Dynamic instruction based on current state\n\n   **Handle states:**\n   - If `state: \"blocked\"` (missing artifacts): show message, suggest using `/opsx:continue`\n   - If `state: \"all_done\"`: congratulate, suggest archive\n   - Otherwise: proceed to implementation\n\n4. **Read context files**\n\n   Read the files listed in `contextFiles` from the apply instructions output.\n   The files depend on the schema being used:\n   - **spec-driven**: proposal, specs, design, tasks\n   - Other schemas: follow the contextFiles from CLI output\n\n5. **Show current progress**\n\n   Display:\n   - Schema being used\n   - Progress: \"N/M tasks complete\"\n   - Remaining tasks overview\n   - Dynamic instruction from CLI\n\n6. **Implement tasks (loop until done or blocked)**\n\n   For each pending task:\n   - Show which task is being worked on\n   - Make the code changes required\n   - Keep changes minimal and focused\n   - Mark task complete in the tasks file: `- [ ]` → `- [x]`\n   - Continue to next task\n\n   **Pause if:**\n   - Task is unclear → ask for clarification\n   - Implementation reveals a design issue → suggest updating artifacts\n   - Error or blocker encountered → report and wait for guidance\n   - User interrupts\n\n7. **On completion or pause, show status**\n\n   Display:\n   - Tasks completed this session\n   - Overall progress: \"N/M tasks complete\"\n   - If all done: suggest archive\n   - If paused: explain why and wait for guidance\n\n**Output During Implementation**\n\n```\n## Implementing: <change-name> (schema: <schema-name>)\n\nWorking on task 3/7: <task description>\n[...implementation happening...]\n✓ Task complete\n\nWorking on task 4/7: <task description>\n[...implementation happening...]\n✓ Task complete\n```\n\n**Output On Completion**\n\n```\n## Implementation Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 7/7 tasks complete ✓\n\n### Completed This Session\n- [x] Task 1\n- [x] Task 2\n...\n\nAll tasks complete! You can archive this change with `/opsx:archive`.\n```\n\n**Output On Pause (Issue Encountered)**\n\n```\n## Implementation Paused\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 4/7 tasks complete\n\n### Issue Encountered\n<description of the issue>\n\n**Options:**\n1. <option 1>\n2. <option 2>\n3. Other approach\n\nWhat would you like to do?\n```\n\n**Guardrails**\n- Keep going through tasks until done or blocked\n- Always read context files before starting (from the apply instructions output)\n- If task is ambiguous, pause and ask before implementing\n- If implementation reveals issues, pause and suggest artifact updates\n- Keep code changes minimal and scoped to each task\n- Update task checkbox immediately after completing each task\n- Pause on errors, blockers, or unclear requirements - don't guess\n- Use contextFiles from CLI output, don't assume specific file names\n\n**Fluid Workflow Integration**\n\nThis skill supports the \"actions on a change\" model:\n\n- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions\n- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly\n"
  },
  {
    "path": ".cursor/commands/opsx-archive.md",
    "content": "---\nname: /opsx-archive\nid: opsx-archive\ncategory: Workflow\ndescription: Archive a completed change in the experimental workflow\n---\n\nArchive a completed change in the experimental workflow.\n\n**Input**: Optionally specify a change name after `/opsx:archive` (e.g., `/opsx:archive add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show only active changes (not already archived).\n   Include the schema used for each change if available.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check artifact completion status**\n\n   Run `openspec status --change \"<name>\" --json` to check artifact completion.\n\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used\n   - `artifacts`: List of artifacts with their status (`done` or other)\n\n   **If any artifacts are not `done`:**\n   - Display warning listing incomplete artifacts\n   - Prompt user for confirmation to continue\n   - Proceed if user confirms\n\n3. **Check task completion status**\n\n   Read the tasks file (typically `tasks.md`) to check for incomplete tasks.\n\n   Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).\n\n   **If incomplete tasks found:**\n   - Display warning showing count of incomplete tasks\n   - Prompt user for confirmation to continue\n   - Proceed if user confirms\n\n   **If no tasks file exists:** Proceed without task-related warning.\n\n4. **Assess delta spec sync state**\n\n   Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.\n\n   **If delta specs exist:**\n   - Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`\n   - Determine what changes would be applied (adds, modifications, removals, renames)\n   - Show a combined summary before prompting\n\n   **Prompt options:**\n   - If changes needed: \"Sync now (recommended)\", \"Archive without syncing\"\n   - If already synced: \"Archive now\", \"Sync anyway\", \"Cancel\"\n\n   If user chooses sync, execute `/opsx:sync` logic. Proceed to archive regardless of choice.\n\n5. **Perform the archive**\n\n   Create the archive directory if it doesn't exist:\n   ```bash\n   mkdir -p openspec/changes/archive\n   ```\n\n   Generate target name using current date: `YYYY-MM-DD-<change-name>`\n\n   **Check if target already exists:**\n   - If yes: Fail with error, suggest renaming existing archive or using different date\n   - If no: Move the change directory to archive\n\n   ```bash\n   mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n   ```\n\n6. **Display summary**\n\n   Show archive completion summary including:\n   - Change name\n   - Schema that was used\n   - Archive location\n   - Spec sync status (synced / sync skipped / no delta specs)\n   - Note about any warnings (incomplete artifacts/tasks)\n\n**Output On Success**\n\n```\n## Archive Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** ✓ Synced to main specs\n\nAll artifacts complete. All tasks complete.\n```\n\n**Output On Success (No Delta Specs)**\n\n```\n## Archive Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** No delta specs\n\nAll artifacts complete. All tasks complete.\n```\n\n**Output On Success With Warnings**\n\n```\n## Archive Complete (with warnings)\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** Sync skipped (user chose to skip)\n\n**Warnings:**\n- Archived with 2 incomplete artifacts\n- Archived with 3 incomplete tasks\n- Delta spec sync was skipped (user chose to skip)\n\nReview the archive if this was not intentional.\n```\n\n**Output On Error (Archive Exists)**\n\n```\n## Archive Failed\n\n**Change:** <change-name>\n**Target:** openspec/changes/archive/YYYY-MM-DD-<name>/\n\nTarget archive directory already exists.\n\n**Options:**\n1. Rename the existing archive\n2. Delete the existing archive if it's a duplicate\n3. Wait until a different date to archive\n```\n\n**Guardrails**\n- Always prompt for change selection if not provided\n- Use artifact graph (openspec status --json) for completion checking\n- Don't block archive on warnings - just inform and confirm\n- Preserve .openspec.yaml when moving to archive (it moves with the directory)\n- Show clear summary of what happened\n- If sync is requested, use /opsx:sync approach (agent-driven)\n- If delta specs exist, always run the sync assessment and show the combined summary before prompting\n"
  },
  {
    "path": ".cursor/commands/opsx-bulk-archive.md",
    "content": "---\nname: /opsx-bulk-archive\nid: opsx-bulk-archive\ncategory: Workflow\ndescription: Archive multiple completed changes at once\n---\n\nArchive multiple completed changes in a single operation.\n\nThis skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented.\n\n**Input**: None required (prompts for selection)\n\n**Steps**\n\n1. **Get active changes**\n\n   Run `openspec list --json` to get all active changes.\n\n   If no active changes exist, inform user and stop.\n\n2. **Prompt for change selection**\n\n   Use **AskUserQuestion tool** with multi-select to let user choose changes:\n   - Show each change with its schema\n   - Include an option for \"All changes\"\n   - Allow any number of selections (1+ works, 2+ is the typical use case)\n\n   **IMPORTANT**: Do NOT auto-select. Always let the user choose.\n\n3. **Batch validation - gather status for all selected changes**\n\n   For each selected change, collect:\n\n   a. **Artifact status** - Run `openspec status --change \"<name>\" --json`\n      - Parse `schemaName` and `artifacts` list\n      - Note which artifacts are `done` vs other states\n\n   b. **Task completion** - Read `openspec/changes/<name>/tasks.md`\n      - Count `- [ ]` (incomplete) vs `- [x]` (complete)\n      - If no tasks file exists, note as \"No tasks\"\n\n   c. **Delta specs** - Check `openspec/changes/<name>/specs/` directory\n      - List which capability specs exist\n      - For each, extract requirement names (lines matching `### Requirement: <name>`)\n\n4. **Detect spec conflicts**\n\n   Build a map of `capability -> [changes that touch it]`:\n\n   ```\n   auth -> [change-a, change-b]  <- CONFLICT (2+ changes)\n   api  -> [change-c]            <- OK (only 1 change)\n   ```\n\n   A conflict exists when 2+ selected changes have delta specs for the same capability.\n\n5. **Resolve conflicts agentically**\n\n   **For each conflict**, investigate the codebase:\n\n   a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify\n\n   b. **Search the codebase** for implementation evidence:\n      - Look for code implementing requirements from each delta spec\n      - Check for related files, functions, or tests\n\n   c. **Determine resolution**:\n      - If only one change is actually implemented -> sync that one's specs\n      - If both implemented -> apply in chronological order (older first, newer overwrites)\n      - If neither implemented -> skip spec sync, warn user\n\n   d. **Record resolution** for each conflict:\n      - Which change's specs to apply\n      - In what order (if both)\n      - Rationale (what was found in codebase)\n\n6. **Show consolidated status table**\n\n   Display a table summarizing all changes:\n\n   ```\n   | Change               | Artifacts | Tasks | Specs   | Conflicts | Status |\n   |---------------------|-----------|-------|---------|-----------|--------|\n   | schema-management   | Done      | 5/5   | 2 delta | None      | Ready  |\n   | project-config      | Done      | 3/3   | 1 delta | None      | Ready  |\n   | add-oauth           | Done      | 4/4   | 1 delta | auth (!)  | Ready* |\n   | add-verify-skill    | 1 left    | 2/5   | None    | None      | Warn   |\n   ```\n\n   For conflicts, show the resolution:\n   ```\n   * Conflict resolution:\n     - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order)\n   ```\n\n   For incomplete changes, show warnings:\n   ```\n   Warnings:\n   - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks\n   ```\n\n7. **Confirm batch operation**\n\n   Use **AskUserQuestion tool** with a single confirmation:\n\n   - \"Archive N changes?\" with options based on status\n   - Options might include:\n     - \"Archive all N changes\"\n     - \"Archive only N ready changes (skip incomplete)\"\n     - \"Cancel\"\n\n   If there are incomplete changes, make clear they'll be archived with warnings.\n\n8. **Execute archive for each confirmed change**\n\n   Process changes in the determined order (respecting conflict resolution):\n\n   a. **Sync specs** if delta specs exist:\n      - Use the openspec-sync-specs approach (agent-driven intelligent merge)\n      - For conflicts, apply in resolved order\n      - Track if sync was done\n\n   b. **Perform the archive**:\n      ```bash\n      mkdir -p openspec/changes/archive\n      mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n      ```\n\n   c. **Track outcome** for each change:\n      - Success: archived successfully\n      - Failed: error during archive (record error)\n      - Skipped: user chose not to archive (if applicable)\n\n9. **Display summary**\n\n   Show final results:\n\n   ```\n   ## Bulk Archive Complete\n\n   Archived 3 changes:\n   - schema-management-cli -> archive/2026-01-19-schema-management-cli/\n   - project-config -> archive/2026-01-19-project-config/\n   - add-oauth -> archive/2026-01-19-add-oauth/\n\n   Skipped 1 change:\n   - add-verify-skill (user chose not to archive incomplete)\n\n   Spec sync summary:\n   - 4 delta specs synced to main specs\n   - 1 conflict resolved (auth: applied both in chronological order)\n   ```\n\n   If any failures:\n   ```\n   Failed 1 change:\n   - some-change: Archive directory already exists\n   ```\n\n**Conflict Resolution Examples**\n\nExample 1: Only one implemented\n```\nConflict: specs/auth/spec.md touched by [add-oauth, add-jwt]\n\nChecking add-oauth:\n- Delta adds \"OAuth Provider Integration\" requirement\n- Searching codebase... found src/auth/oauth.ts implementing OAuth flow\n\nChecking add-jwt:\n- Delta adds \"JWT Token Handling\" requirement\n- Searching codebase... no JWT implementation found\n\nResolution: Only add-oauth is implemented. Will sync add-oauth specs only.\n```\n\nExample 2: Both implemented\n```\nConflict: specs/api/spec.md touched by [add-rest-api, add-graphql]\n\nChecking add-rest-api (created 2026-01-10):\n- Delta adds \"REST Endpoints\" requirement\n- Searching codebase... found src/api/rest.ts\n\nChecking add-graphql (created 2026-01-15):\n- Delta adds \"GraphQL Schema\" requirement\n- Searching codebase... found src/api/graphql.ts\n\nResolution: Both implemented. Will apply add-rest-api specs first,\nthen add-graphql specs (chronological order, newer takes precedence).\n```\n\n**Output On Success**\n\n```\n## Bulk Archive Complete\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n- <change-2> -> archive/YYYY-MM-DD-<change-2>/\n\nSpec sync summary:\n- N delta specs synced to main specs\n- No conflicts (or: M conflicts resolved)\n```\n\n**Output On Partial Success**\n\n```\n## Bulk Archive Complete (partial)\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n\nSkipped M changes:\n- <change-2> (user chose not to archive incomplete)\n\nFailed K changes:\n- <change-3>: Archive directory already exists\n```\n\n**Output When No Changes**\n\n```\n## No Changes to Archive\n\nNo active changes found. Use `/opsx:new` to create a new change.\n```\n\n**Guardrails**\n- Allow any number of changes (1+ is fine, 2+ is the typical use case)\n- Always prompt for selection, never auto-select\n- Detect spec conflicts early and resolve by checking codebase\n- When both changes are implemented, apply specs in chronological order\n- Skip spec sync only when implementation is missing (warn user)\n- Show clear per-change status before confirming\n- Use single confirmation for entire batch\n- Track and report all outcomes (success/skip/fail)\n- Preserve .openspec.yaml when moving to archive\n- Archive directory target uses current date: YYYY-MM-DD-<name>\n- If archive target exists, fail that change but continue with others\n"
  },
  {
    "path": ".cursor/commands/opsx-continue.md",
    "content": "---\nname: /opsx-continue\nid: opsx-continue\ncategory: Workflow\ndescription: Continue working on a change - create the next artifact (Experimental)\n---\n\nContinue working on a change by creating the next artifact.\n\n**Input**: Optionally specify a change name after `/opsx:continue` (e.g., `/opsx:continue add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes sorted by most recently modified. Then use the **AskUserQuestion tool** to let the user select which change to work on.\n\n   Present the top 3-4 most recently modified changes as options, showing:\n   - Change name\n   - Schema (from `schema` field if present, otherwise \"spec-driven\")\n   - Status (e.g., \"0/5 tasks\", \"complete\", \"no tasks\")\n   - How recently it was modified (from `lastModified` field)\n\n   Mark the most recently modified change as \"(Recommended)\" since it's likely what the user wants to continue.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check current status**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand current state. The response includes:\n   - `schemaName`: The workflow schema being used (e.g., \"spec-driven\")\n   - `artifacts`: Array of artifacts with their status (\"done\", \"ready\", \"blocked\")\n   - `isComplete`: Boolean indicating if all artifacts are complete\n\n3. **Act based on status**:\n\n   ---\n\n   **If all artifacts are complete (`isComplete: true`)**:\n   - Congratulate the user\n   - Show final status including the schema used\n   - Suggest: \"All artifacts created! You can now implement this change with `/opsx:apply` or archive it with `/opsx:archive`.\"\n   - STOP\n\n   ---\n\n   **If artifacts are ready to create** (status shows artifacts with `status: \"ready\"`):\n   - Pick the FIRST artifact with `status: \"ready\"` from the status output\n   - Get its instructions:\n     ```bash\n     openspec instructions <artifact-id> --change \"<name>\" --json\n     ```\n   - Parse the JSON. The key fields are:\n     - `context`: Project background (constraints for you - do NOT include in output)\n     - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n     - `template`: The structure to use for your output file\n     - `instruction`: Schema-specific guidance\n     - `outputPath`: Where to write the artifact\n     - `dependencies`: Completed artifacts to read for context\n   - **Create the artifact file**:\n     - Read any completed dependency files for context\n     - Use `template` as the structure - fill in its sections\n     - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file\n     - Write to the output path specified in instructions\n   - Show what was created and what's now unlocked\n   - STOP after creating ONE artifact\n\n   ---\n\n   **If no artifacts are ready (all blocked)**:\n   - This shouldn't happen with a valid schema\n   - Show status and suggest checking for issues\n\n4. **After creating an artifact, show progress**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter each invocation, show:\n- Which artifact was created\n- Schema workflow being used\n- Current progress (N/M complete)\n- What artifacts are now unlocked\n- Prompt: \"Run `/opsx:continue` to create the next artifact\"\n\n**Artifact Creation Guidelines**\n\nThe artifact types and their purpose depend on the schema. Use the `instruction` field from the instructions output to understand what to create.\n\nCommon artifact patterns:\n\n**spec-driven schema** (proposal → specs → design → tasks):\n- **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact.\n  - The Capabilities section is critical - each capability listed will need a spec file.\n- **specs/<capability>/spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name).\n- **design.md**: Document technical decisions, architecture, and implementation approach.\n- **tasks.md**: Break down implementation into checkboxed tasks.\n\nFor other schemas, follow the `instruction` field from the CLI output.\n\n**Guardrails**\n- Create ONE artifact per invocation\n- Always read dependency artifacts before creating a new one\n- Never skip artifacts or create out of order\n- If context is unclear, ask the user before creating\n- Verify the artifact file exists after writing before marking progress\n- Use the schema's artifact sequence, don't assume specific artifact names\n- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file\n  - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact\n  - These guide what you write, but should never appear in the output\n"
  },
  {
    "path": ".cursor/commands/opsx-explore.md",
    "content": "---\nname: /opsx-explore\nid: opsx-explore\ncategory: Workflow\ndescription: \"Enter explore mode - think through ideas, investigate problems, clarify requirements\"\n---\n\nEnter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.\n\n**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first (e.g., start a change with `/opsx:new` or `/opsx:ff`). You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.\n\n**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.\n\n**Input**: The argument after `/opsx:explore` is whatever the user wants to think about. Could be:\n- A vague idea: \"real-time collaboration\"\n- A specific problem: \"the auth system is getting unwieldy\"\n- A change name: \"add-dark-mode\" (to explore in context of that change)\n- A comparison: \"postgres vs sqlite for this\"\n- Nothing (just enter explore mode)\n\n---\n\n## The Stance\n\n- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script\n- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.\n- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking\n- **Adaptive** - Follow interesting threads, pivot when new information emerges\n- **Patient** - Don't rush to conclusions, let the shape of the problem emerge\n- **Grounded** - Explore the actual codebase when relevant, don't just theorize\n\n---\n\n## What You Might Do\n\nDepending on what the user brings, you might:\n\n**Explore the problem space**\n- Ask clarifying questions that emerge from what they said\n- Challenge assumptions\n- Reframe the problem\n- Find analogies\n\n**Investigate the codebase**\n- Map existing architecture relevant to the discussion\n- Find integration points\n- Identify patterns already in use\n- Surface hidden complexity\n\n**Compare options**\n- Brainstorm multiple approaches\n- Build comparison tables\n- Sketch tradeoffs\n- Recommend a path (if asked)\n\n**Visualize**\n```\n┌─────────────────────────────────────────┐\n│     Use ASCII diagrams liberally        │\n├─────────────────────────────────────────┤\n│                                         │\n│   ┌────────┐         ┌────────┐        │\n│   │ State  │────────▶│ State  │        │\n│   │   A    │         │   B    │        │\n│   └────────┘         └────────┘        │\n│                                         │\n│   System diagrams, state machines,      │\n│   data flows, architecture sketches,    │\n│   dependency graphs, comparison tables  │\n│                                         │\n└─────────────────────────────────────────┘\n```\n\n**Surface risks and unknowns**\n- Identify what could go wrong\n- Find gaps in understanding\n- Suggest spikes or investigations\n\n---\n\n## OpenSpec Awareness\n\nYou have full context of the OpenSpec system. Use it naturally, don't force it.\n\n### Check for context\n\nAt the start, quickly check what exists:\n```bash\nopenspec list --json\n```\n\nThis tells you:\n- If there are active changes\n- Their names, schemas, and status\n- What the user might be working on\n\nIf the user mentioned a specific change name, read its artifacts for context.\n\n### When no change exists\n\nThink freely. When insights crystallize, you might offer:\n\n- \"This feels solid enough to start a change. Want me to create one?\"\n  → Can transition to `/opsx:new` or `/opsx:ff`\n- Or keep exploring - no pressure to formalize\n\n### When a change exists\n\nIf the user mentions a change or you detect one is relevant:\n\n1. **Read existing artifacts for context**\n   - `openspec/changes/<name>/proposal.md`\n   - `openspec/changes/<name>/design.md`\n   - `openspec/changes/<name>/tasks.md`\n   - etc.\n\n2. **Reference them naturally in conversation**\n   - \"Your design mentions using Redis, but we just realized SQLite fits better...\"\n   - \"The proposal scopes this to premium users, but we're now thinking everyone...\"\n\n3. **Offer to capture when decisions are made**\n\n   | Insight Type | Where to Capture |\n   |--------------|------------------|\n   | New requirement discovered | `specs/<capability>/spec.md` |\n   | Requirement changed | `specs/<capability>/spec.md` |\n   | Design decision made | `design.md` |\n   | Scope changed | `proposal.md` |\n   | New work identified | `tasks.md` |\n   | Assumption invalidated | Relevant artifact |\n\n   Example offers:\n   - \"That's a design decision. Capture it in design.md?\"\n   - \"This is a new requirement. Add it to specs?\"\n   - \"This changes scope. Update the proposal?\"\n\n4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.\n\n---\n\n## What You Don't Have To Do\n\n- Follow a script\n- Ask the same questions every time\n- Produce a specific artifact\n- Reach a conclusion\n- Stay on topic if a tangent is valuable\n- Be brief (this is thinking time)\n\n---\n\n## Ending Discovery\n\nThere's no required ending. Discovery might:\n\n- **Flow into action**: \"Ready to start? `/opsx:new` or `/opsx:ff`\"\n- **Result in artifact updates**: \"Updated design.md with these decisions\"\n- **Just provide clarity**: User has what they need, moves on\n- **Continue later**: \"We can pick this up anytime\"\n\nWhen things crystallize, you might offer a summary - but it's optional. Sometimes the thinking IS the value.\n\n---\n\n## Guardrails\n\n- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.\n- **Don't fake understanding** - If something is unclear, dig deeper\n- **Don't rush** - Discovery is thinking time, not task time\n- **Don't force structure** - Let patterns emerge naturally\n- **Don't auto-capture** - Offer to save insights, don't just do it\n- **Do visualize** - A good diagram is worth many paragraphs\n- **Do explore the codebase** - Ground discussions in reality\n- **Do question assumptions** - Including the user's and your own\n"
  },
  {
    "path": ".cursor/commands/opsx-ff.md",
    "content": "---\nname: /opsx-ff\nid: opsx-ff\ncategory: Workflow\ndescription: Create a change and generate all artifacts needed for implementation in one go\n---\n\nFast-forward through artifact creation - generate everything needed to start implementation.\n\n**Input**: The argument after `/opsx:ff` is the change name (kebab-case), OR a description of what the user wants to build.\n\n**Steps**\n\n1. **If no input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   This creates a scaffolded change at `openspec/changes/<name>/`.\n\n3. **Get the artifact build order**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to get:\n   - `applyRequires`: array of artifact IDs needed before implementation (e.g., `[\"tasks\"]`)\n   - `artifacts`: list of all artifacts with their status and dependencies\n\n4. **Create artifacts in sequence until apply-ready**\n\n   Use the **TodoWrite tool** to track progress through the artifacts.\n\n   Loop through artifacts in dependency order (artifacts with no pending dependencies first):\n\n   a. **For each artifact that is `ready` (dependencies satisfied)**:\n      - Get instructions:\n        ```bash\n        openspec instructions <artifact-id> --change \"<name>\" --json\n        ```\n      - The instructions JSON includes:\n        - `context`: Project background (constraints for you - do NOT include in output)\n        - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n        - `template`: The structure to use for your output file\n        - `instruction`: Schema-specific guidance for this artifact type\n        - `outputPath`: Where to write the artifact\n        - `dependencies`: Completed artifacts to read for context\n      - Read any completed dependency files for context\n      - Create the artifact file using `template` as the structure\n      - Apply `context` and `rules` as constraints - but do NOT copy them into the file\n      - Show brief progress: \"✓ Created <artifact-id>\"\n\n   b. **Continue until all `applyRequires` artifacts are complete**\n      - After creating each artifact, re-run `openspec status --change \"<name>\" --json`\n      - Check if every artifact ID in `applyRequires` has `status: \"done\"` in the artifacts array\n      - Stop when all `applyRequires` artifacts are done\n\n   c. **If an artifact requires user input** (unclear context):\n      - Use **AskUserQuestion tool** to clarify\n      - Then continue with creation\n\n5. **Show final status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter completing all artifacts, summarize:\n- Change name and location\n- List of artifacts created with brief descriptions\n- What's ready: \"All artifacts created! Ready for implementation.\"\n- Prompt: \"Run `/opsx:apply` to start implementing.\"\n\n**Artifact Creation Guidelines**\n\n- Follow the `instruction` field from `openspec instructions` for each artifact type\n- The schema defines what each artifact should contain - follow it\n- Read dependency artifacts for context before creating new ones\n- Use the `template` as a starting point, filling in based on context\n\n**Guardrails**\n- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)\n- Always read dependency artifacts before creating a new one\n- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum\n- If a change with that name already exists, ask if user wants to continue it or create a new one\n- Verify each artifact file exists after writing before proceeding to next\n"
  },
  {
    "path": ".cursor/commands/opsx-new.md",
    "content": "---\nname: /opsx-new\nid: opsx-new\ncategory: Workflow\ndescription: Start a new change using the experimental artifact workflow (OPSX)\n---\n\nStart a new change using the experimental artifact-driven approach.\n\n**Input**: The argument after `/opsx:new` is the change name (kebab-case), OR a description of what the user wants to build.\n\n**Steps**\n\n1. **If no input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Determine the workflow schema**\n\n   Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow.\n\n   **Use a different schema only if the user mentions:**\n   - A specific schema name → use `--schema <name>`\n   - \"show workflows\" or \"what workflows\" → run `openspec schemas --json` and let them choose\n\n   **Otherwise**: Omit `--schema` to use the default.\n\n3. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   Add `--schema <name>` only if the user requested a specific workflow.\n   This creates a scaffolded change at `openspec/changes/<name>/` with the selected schema.\n\n4. **Show the artifact status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n   This shows which artifacts need to be created and which are ready (dependencies satisfied).\n\n5. **Get instructions for the first artifact**\n   The first artifact depends on the schema. Check the status output to find the first artifact with status \"ready\".\n   ```bash\n   openspec instructions <first-artifact-id> --change \"<name>\"\n   ```\n   This outputs the template and context for creating the first artifact.\n\n6. **STOP and wait for user direction**\n\n**Output**\n\nAfter completing the steps, summarize:\n- Change name and location\n- Schema/workflow being used and its artifact sequence\n- Current status (0/N artifacts complete)\n- The template for the first artifact\n- Prompt: \"Ready to create the first artifact? Run `/opsx:continue` or just describe what this change is about and I'll draft it.\"\n\n**Guardrails**\n- Do NOT create any artifacts yet - just show the instructions\n- Do NOT advance beyond showing the first artifact template\n- If the name is invalid (not kebab-case), ask for a valid name\n- If a change with that name already exists, suggest using `/opsx:continue` instead\n- Pass --schema if using a non-default workflow\n"
  },
  {
    "path": ".cursor/commands/opsx-onboard.md",
    "content": "---\nname: /opsx-onboard\nid: opsx-onboard\ncategory: Workflow\ndescription: Guided onboarding - walk through a complete OpenSpec workflow cycle with narration\n---\n\nGuide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step.\n\n---\n\n## Preflight\n\nBefore starting, check if OpenSpec is initialized:\n\n```bash\nopenspec status --json 2>&1 || echo \"NOT_INITIALIZED\"\n```\n\n**If not initialized:**\n> OpenSpec isn't set up in this project yet. Run `openspec init` first, then come back to `/opsx:onboard`.\n\nStop here if not initialized.\n\n---\n\n## Phase 1: Welcome\n\nDisplay:\n\n```\n## Welcome to OpenSpec!\n\nI'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it.\n\n**What we'll do:**\n1. Pick a small, real task in your codebase\n2. Explore the problem briefly\n3. Create a change (the container for our work)\n4. Build the artifacts: proposal → specs → design → tasks\n5. Implement the tasks\n6. Archive the completed change\n\n**Time:** ~15-20 minutes\n\nLet's start by finding something to work on.\n```\n\n---\n\n## Phase 2: Task Selection\n\n### Codebase Analysis\n\nScan the codebase for small improvement opportunities. Look for:\n\n1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files\n2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch\n3. **Functions without tests** - Cross-reference `src/` with test directories\n4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`)\n5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code\n6. **Missing validation** - User input handlers without validation\n\nAlso check recent git activity:\n```bash\ngit log --oneline -10 2>/dev/null || echo \"No git history\"\n```\n\n### Present Suggestions\n\nFrom your analysis, present 3-4 specific suggestions:\n\n```\n## Task Suggestions\n\nBased on scanning your codebase, here are some good starter tasks:\n\n**1. [Most promising task]**\n   Location: `src/path/to/file.ts:42`\n   Scope: ~1-2 files, ~20-30 lines\n   Why it's good: [brief reason]\n\n**2. [Second task]**\n   Location: `src/another/file.ts`\n   Scope: ~1 file, ~15 lines\n   Why it's good: [brief reason]\n\n**3. [Third task]**\n   Location: [location]\n   Scope: [estimate]\n   Why it's good: [brief reason]\n\n**4. Something else?**\n   Tell me what you'd like to work on.\n\nWhich task interests you? (Pick a number or describe your own)\n```\n\n**If nothing found:** Fall back to asking what the user wants to build:\n> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix?\n\n### Scope Guardrail\n\nIf the user picks or describes something too large (major feature, multi-day work):\n\n```\nThat's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through.\n\nFor learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details.\n\n**Options:**\n1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]?\n2. **Pick something else** - One of the other suggestions, or a different small task?\n3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer.\n\nWhat would you prefer?\n```\n\nLet the user override if they insist—this is a soft guardrail.\n\n---\n\n## Phase 3: Explore Demo\n\nOnce a task is selected, briefly demonstrate explore mode:\n\n```\nBefore we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction.\n```\n\nSpend 1-2 minutes investigating the relevant code:\n- Read the file(s) involved\n- Draw a quick ASCII diagram if it helps\n- Note any considerations\n\n```\n## Quick Exploration\n\n[Your brief analysis—what you found, any considerations]\n\n┌─────────────────────────────────────────┐\n│   [Optional: ASCII diagram if helpful]  │\n└─────────────────────────────────────────┘\n\nExplore mode (`/opsx:explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem.\n\nNow let's create a change to hold our work.\n```\n\n**PAUSE** - Wait for user acknowledgment before proceeding.\n\n---\n\n## Phase 4: Create the Change\n\n**EXPLAIN:**\n```\n## Creating a Change\n\nA \"change\" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives in `openspec/changes/<name>/` and holds your artifacts—proposal, specs, design, tasks.\n\nLet me create one for our task.\n```\n\n**DO:** Create the change with a derived kebab-case name:\n```bash\nopenspec new change \"<derived-name>\"\n```\n\n**SHOW:**\n```\nCreated: `openspec/changes/<name>/`\n\nThe folder structure:\n```\nopenspec/changes/<name>/\n├── proposal.md    ← Why we're doing this (empty, we'll fill it)\n├── design.md      ← How we'll build it (empty)\n├── specs/         ← Detailed requirements (empty)\n└── tasks.md       ← Implementation checklist (empty)\n```\n\nNow let's fill in the first artifact—the proposal.\n```\n\n---\n\n## Phase 5: Proposal\n\n**EXPLAIN:**\n```\n## The Proposal\n\nThe proposal captures **why** we're making this change and **what** it involves at a high level. It's the \"elevator pitch\" for the work.\n\nI'll draft one based on our task.\n```\n\n**DO:** Draft the proposal content (don't save yet):\n\n```\nHere's a draft proposal:\n\n---\n\n## Why\n\n[1-2 sentences explaining the problem/opportunity]\n\n## What Changes\n\n[Bullet points of what will be different]\n\n## Capabilities\n\n### New Capabilities\n- `<capability-name>`: [brief description]\n\n### Modified Capabilities\n<!-- If modifying existing behavior -->\n\n## Impact\n\n- `src/path/to/file.ts`: [what changes]\n- [other files if applicable]\n\n---\n\nDoes this capture the intent? I can adjust before we save it.\n```\n\n**PAUSE** - Wait for user approval/feedback.\n\nAfter approval, save the proposal:\n```bash\nopenspec instructions proposal --change \"<name>\" --json\n```\nThen write the content to `openspec/changes/<name>/proposal.md`.\n\n```\nProposal saved. This is your \"why\" document—you can always come back and refine it as understanding evolves.\n\nNext up: specs.\n```\n\n---\n\n## Phase 6: Specs\n\n**EXPLAIN:**\n```\n## Specs\n\nSpecs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear.\n\nFor a small task like this, we might only need one spec file.\n```\n\n**DO:** Create the spec file:\n```bash\nmkdir -p openspec/changes/<name>/specs/<capability-name>\n```\n\nDraft the spec content:\n\n```\nHere's the spec:\n\n---\n\n## ADDED Requirements\n\n### Requirement: <Name>\n\n<Description of what the system should do>\n\n#### Scenario: <Scenario name>\n\n- **WHEN** <trigger condition>\n- **THEN** <expected outcome>\n- **AND** <additional outcome if needed>\n\n---\n\nThis format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases.\n```\n\nSave to `openspec/changes/<name>/specs/<capability>/spec.md`.\n\n---\n\n## Phase 7: Design\n\n**EXPLAIN:**\n```\n## Design\n\nThe design captures **how** we'll build it—technical decisions, tradeoffs, approach.\n\nFor small changes, this might be brief. That's fine—not every change needs deep design discussion.\n```\n\n**DO:** Draft design.md:\n\n```\nHere's the design:\n\n---\n\n## Context\n\n[Brief context about the current state]\n\n## Goals / Non-Goals\n\n**Goals:**\n- [What we're trying to achieve]\n\n**Non-Goals:**\n- [What's explicitly out of scope]\n\n## Decisions\n\n### Decision 1: [Key decision]\n\n[Explanation of approach and rationale]\n\n---\n\nFor a small task, this captures the key decisions without over-engineering.\n```\n\nSave to `openspec/changes/<name>/design.md`.\n\n---\n\n## Phase 8: Tasks\n\n**EXPLAIN:**\n```\n## Tasks\n\nFinally, we break the work into implementation tasks—checkboxes that drive the apply phase.\n\nThese should be small, clear, and in logical order.\n```\n\n**DO:** Generate tasks based on specs and design:\n\n```\nHere are the implementation tasks:\n\n---\n\n## 1. [Category or file]\n\n- [ ] 1.1 [Specific task]\n- [ ] 1.2 [Specific task]\n\n## 2. Verify\n\n- [ ] 2.1 [Verification step]\n\n---\n\nEach checkbox becomes a unit of work in the apply phase. Ready to implement?\n```\n\n**PAUSE** - Wait for user to confirm they're ready to implement.\n\nSave to `openspec/changes/<name>/tasks.md`.\n\n---\n\n## Phase 9: Apply (Implementation)\n\n**EXPLAIN:**\n```\n## Implementation\n\nNow we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach.\n```\n\n**DO:** For each task:\n\n1. Announce: \"Working on task N: [description]\"\n2. Implement the change in the codebase\n3. Reference specs/design naturally: \"The spec says X, so I'm doing Y\"\n4. Mark complete in tasks.md: `- [ ]` → `- [x]`\n5. Brief status: \"✓ Task N complete\"\n\nKeep narration light—don't over-explain every line of code.\n\nAfter all tasks:\n\n```\n## Implementation Complete\n\nAll tasks done:\n- [x] Task 1\n- [x] Task 2\n- [x] ...\n\nThe change is implemented! One more step—let's archive it.\n```\n\n---\n\n## Phase 10: Archive\n\n**EXPLAIN:**\n```\n## Archiving\n\nWhen a change is complete, we archive it. This moves it from `openspec/changes/` to `openspec/changes/archive/YYYY-MM-DD-<name>/`.\n\nArchived changes become your project's decision history—you can always find them later to understand why something was built a certain way.\n```\n\n**DO:**\n```bash\nopenspec archive \"<name>\"\n```\n\n**SHOW:**\n```\nArchived to: `openspec/changes/archive/YYYY-MM-DD-<name>/`\n\nThe change is now part of your project's history. The code is in your codebase, the decision record is preserved.\n```\n\n---\n\n## Phase 11: Recap & Next Steps\n\n```\n## Congratulations!\n\nYou just completed a full OpenSpec cycle:\n\n1. **Explore** - Thought through the problem\n2. **New** - Created a change container\n3. **Proposal** - Captured WHY\n4. **Specs** - Defined WHAT in detail\n5. **Design** - Decided HOW\n6. **Tasks** - Broke it into steps\n7. **Apply** - Implemented the work\n8. **Archive** - Preserved the record\n\nThis same rhythm works for any size change—a small fix or a major feature.\n\n---\n\n## Command Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems before/during work |\n| `/opsx:new` | Start a new change, step through artifacts |\n| `/opsx:ff` | Fast-forward: create all artifacts at once |\n| `/opsx:continue` | Continue working on an existing change |\n| `/opsx:apply` | Implement tasks from a change |\n| `/opsx:verify` | Verify implementation matches artifacts |\n| `/opsx:archive` | Archive a completed change |\n\n---\n\n## What's Next?\n\nTry `/opsx:new` or `/opsx:ff` on something you actually want to build. You've got the rhythm now!\n```\n\n---\n\n## Graceful Exit Handling\n\n### User wants to stop mid-way\n\nIf the user says they need to stop, want to pause, or seem disengaged:\n\n```\nNo problem! Your change is saved at `openspec/changes/<name>/`.\n\nTo pick up where we left off later:\n- `/opsx:continue <name>` - Resume artifact creation\n- `/opsx:apply <name>` - Jump to implementation (if tasks exist)\n\nThe work won't be lost. Come back whenever you're ready.\n```\n\nExit gracefully without pressure.\n\n### User just wants command reference\n\nIf the user says they just want to see the commands or skip the tutorial:\n\n```\n## OpenSpec Quick Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems (no code changes) |\n| `/opsx:new <name>` | Start a new change, step by step |\n| `/opsx:ff <name>` | Fast-forward: all artifacts at once |\n| `/opsx:continue <name>` | Continue an existing change |\n| `/opsx:apply <name>` | Implement tasks |\n| `/opsx:verify <name>` | Verify implementation |\n| `/opsx:archive <name>` | Archive when done |\n\nTry `/opsx:new` to start your first change, or `/opsx:ff` if you want to move fast.\n```\n\nExit gracefully.\n\n---\n\n## Guardrails\n\n- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive)\n- **Keep narration light** during implementation—teach without lecturing\n- **Don't skip phases** even if the change is small—the goal is teaching the workflow\n- **Pause for acknowledgment** at marked points, but don't over-pause\n- **Handle exits gracefully**—never pressure the user to continue\n- **Use real codebase tasks**—don't simulate or use fake examples\n- **Adjust scope gently**—guide toward smaller tasks but respect user choice\n"
  },
  {
    "path": ".cursor/commands/opsx-sync.md",
    "content": "---\nname: /opsx-sync\nid: opsx-sync\ncategory: Workflow\ndescription: Sync delta specs from a change to main specs\n---\n\nSync delta specs from a change to main specs.\n\nThis is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).\n\n**Input**: Optionally specify a change name after `/opsx:sync` (e.g., `/opsx:sync add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have delta specs (under `specs/` directory).\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Find delta specs**\n\n   Look for delta spec files in `openspec/changes/<name>/specs/*/spec.md`.\n\n   Each delta spec file contains sections like:\n   - `## ADDED Requirements` - New requirements to add\n   - `## MODIFIED Requirements` - Changes to existing requirements\n   - `## REMOVED Requirements` - Requirements to remove\n   - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)\n\n   If no delta specs found, inform user and stop.\n\n3. **For each delta spec, apply changes to main specs**\n\n   For each capability with a delta spec at `openspec/changes/<name>/specs/<capability>/spec.md`:\n\n   a. **Read the delta spec** to understand the intended changes\n\n   b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)\n\n   c. **Apply changes intelligently**:\n\n      **ADDED Requirements:**\n      - If requirement doesn't exist in main spec → add it\n      - If requirement already exists → update it to match (treat as implicit MODIFIED)\n\n      **MODIFIED Requirements:**\n      - Find the requirement in main spec\n      - Apply the changes - this can be:\n        - Adding new scenarios (don't need to copy existing ones)\n        - Modifying existing scenarios\n        - Changing the requirement description\n      - Preserve scenarios/content not mentioned in the delta\n\n      **REMOVED Requirements:**\n      - Remove the entire requirement block from main spec\n\n      **RENAMED Requirements:**\n      - Find the FROM requirement, rename to TO\n\n   d. **Create new main spec** if capability doesn't exist yet:\n      - Create `openspec/specs/<capability>/spec.md`\n      - Add Purpose section (can be brief, mark as TBD)\n      - Add Requirements section with the ADDED requirements\n\n4. **Show summary**\n\n   After applying all changes, summarize:\n   - Which capabilities were updated\n   - What changes were made (requirements added/modified/removed/renamed)\n\n**Delta Spec Format Reference**\n\n```markdown\n## ADDED Requirements\n\n### Requirement: New Feature\nThe system SHALL do something new.\n\n#### Scenario: Basic case\n- **WHEN** user does X\n- **THEN** system does Y\n\n## MODIFIED Requirements\n\n### Requirement: Existing Feature\n#### Scenario: New scenario to add\n- **WHEN** user does A\n- **THEN** system does B\n\n## REMOVED Requirements\n\n### Requirement: Deprecated Feature\n\n## RENAMED Requirements\n\n- FROM: `### Requirement: Old Name`\n- TO: `### Requirement: New Name`\n```\n\n**Key Principle: Intelligent Merging**\n\nUnlike programmatic merging, you can apply **partial updates**:\n- To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios\n- The delta represents *intent*, not a wholesale replacement\n- Use your judgment to merge changes sensibly\n\n**Output On Success**\n\n```\n## Specs Synced: <change-name>\n\nUpdated main specs:\n\n**<capability-1>**:\n- Added requirement: \"New Feature\"\n- Modified requirement: \"Existing Feature\" (added 1 scenario)\n\n**<capability-2>**:\n- Created new spec file\n- Added requirement: \"Another Feature\"\n\nMain specs are now updated. The change remains active - archive when implementation is complete.\n```\n\n**Guardrails**\n- Read both delta and main specs before making changes\n- Preserve existing content not mentioned in delta\n- If something is unclear, ask for clarification\n- Show what you're changing as you go\n- The operation should be idempotent - running twice should give same result\n"
  },
  {
    "path": ".cursor/commands/opsx-verify.md",
    "content": "---\nname: /opsx-verify\nid: opsx-verify\ncategory: Workflow\ndescription: Verify implementation matches change artifacts before archiving\n---\n\nVerify that an implementation matches the change artifacts (specs, tasks, design).\n\n**Input**: Optionally specify a change name after `/opsx:verify` (e.g., `/opsx:verify add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have implementation tasks (tasks artifact exists).\n   Include the schema used for each change if available.\n   Mark changes with incomplete tasks as \"(In Progress)\".\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifacts exist for this change\n\n3. **Get the change directory and load artifacts**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns the change directory and context files. Read all available artifacts from `contextFiles`.\n\n4. **Initialize verification report structure**\n\n   Create a report structure with three dimensions:\n   - **Completeness**: Track tasks and spec coverage\n   - **Correctness**: Track requirement implementation and scenario coverage\n   - **Coherence**: Track design adherence and pattern consistency\n\n   Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.\n\n5. **Verify Completeness**\n\n   **Task Completion**:\n   - If tasks.md exists in contextFiles, read it\n   - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete)\n   - Count complete vs total tasks\n   - If incomplete tasks exist:\n     - Add CRITICAL issue for each incomplete task\n     - Recommendation: \"Complete task: <description>\" or \"Mark as done if already implemented\"\n\n   **Spec Coverage**:\n   - If delta specs exist in `openspec/changes/<name>/specs/`:\n     - Extract all requirements (marked with \"### Requirement:\")\n     - For each requirement:\n       - Search codebase for keywords related to the requirement\n       - Assess if implementation likely exists\n     - If requirements appear unimplemented:\n       - Add CRITICAL issue: \"Requirement not found: <requirement name>\"\n       - Recommendation: \"Implement requirement X: <description>\"\n\n6. **Verify Correctness**\n\n   **Requirement Implementation Mapping**:\n   - For each requirement from delta specs:\n     - Search codebase for implementation evidence\n     - If found, note file paths and line ranges\n     - Assess if implementation matches requirement intent\n     - If divergence detected:\n       - Add WARNING: \"Implementation may diverge from spec: <details>\"\n       - Recommendation: \"Review <file>:<lines> against requirement X\"\n\n   **Scenario Coverage**:\n   - For each scenario in delta specs (marked with \"#### Scenario:\"):\n     - Check if conditions are handled in code\n     - Check if tests exist covering the scenario\n     - If scenario appears uncovered:\n       - Add WARNING: \"Scenario not covered: <scenario name>\"\n       - Recommendation: \"Add test or implementation for scenario: <description>\"\n\n7. **Verify Coherence**\n\n   **Design Adherence**:\n   - If design.md exists in contextFiles:\n     - Extract key decisions (look for sections like \"Decision:\", \"Approach:\", \"Architecture:\")\n     - Verify implementation follows those decisions\n     - If contradiction detected:\n       - Add WARNING: \"Design decision not followed: <decision>\"\n       - Recommendation: \"Update implementation or revise design.md to match reality\"\n   - If no design.md: Skip design adherence check, note \"No design.md to verify against\"\n\n   **Code Pattern Consistency**:\n   - Review new code for consistency with project patterns\n   - Check file naming, directory structure, coding style\n   - If significant deviations found:\n     - Add SUGGESTION: \"Code pattern deviation: <details>\"\n     - Recommendation: \"Consider following project pattern: <example>\"\n\n8. **Generate Verification Report**\n\n   **Summary Scorecard**:\n   ```\n   ## Verification Report: <change-name>\n\n   ### Summary\n   | Dimension    | Status           |\n   |--------------|------------------|\n   | Completeness | X/Y tasks, N reqs|\n   | Correctness  | M/N reqs covered |\n   | Coherence    | Followed/Issues  |\n   ```\n\n   **Issues by Priority**:\n\n   1. **CRITICAL** (Must fix before archive):\n      - Incomplete tasks\n      - Missing requirement implementations\n      - Each with specific, actionable recommendation\n\n   2. **WARNING** (Should fix):\n      - Spec/design divergences\n      - Missing scenario coverage\n      - Each with specific recommendation\n\n   3. **SUGGESTION** (Nice to fix):\n      - Pattern inconsistencies\n      - Minor improvements\n      - Each with specific recommendation\n\n   **Final Assessment**:\n   - If CRITICAL issues: \"X critical issue(s) found. Fix before archiving.\"\n   - If only warnings: \"No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements).\"\n   - If all clear: \"All checks passed. Ready for archive.\"\n\n**Verification Heuristics**\n\n- **Completeness**: Focus on objective checklist items (checkboxes, requirements list)\n- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty\n- **Coherence**: Look for glaring inconsistencies, don't nitpick style\n- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL\n- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable\n\n**Graceful Degradation**\n\n- If only tasks.md exists: verify task completion only, skip spec/design checks\n- If tasks + specs exist: verify completeness and correctness, skip design\n- If full artifacts: verify all three dimensions\n- Always note which checks were skipped and why\n\n**Output Format**\n\nUse clear markdown with:\n- Table for summary scorecard\n- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION)\n- Code references in format: `file.ts:123`\n- Specific, actionable recommendations\n- No vague suggestions like \"consider reviewing\"\n"
  },
  {
    "path": ".cursor/skills/openspec-apply-change/SKILL.md",
    "content": "zh---\nname: openspec-apply-change\ndescription: Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nImplement tasks from an OpenSpec change.\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **Select the change**\n\n   If a name is provided, use it. Otherwise:\n   - Infer from conversation context if the user mentioned a change\n   - Auto-select if only one active change exists\n   - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select\n\n   Always announce: \"Using change: <name>\" and how to override (e.g., `/opsx:apply <other>`).\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifact contains the tasks (typically \"tasks\" for spec-driven, check status for others)\n\n3. **Get apply instructions**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns:\n   - Context file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs)\n   - Progress (total, complete, remaining)\n   - Task list with status\n   - Dynamic instruction based on current state\n\n   **Handle states:**\n   - If `state: \"blocked\"` (missing artifacts): show message, suggest using openspec-continue-change\n   - If `state: \"all_done\"`: congratulate, suggest archive\n   - Otherwise: proceed to implementation\n\n4. **Read context files**\n\n   Read the files listed in `contextFiles` from the apply instructions output.\n   The files depend on the schema being used:\n   - **spec-driven**: proposal, specs, design, tasks\n   - Other schemas: follow the contextFiles from CLI output\n\n5. **Show current progress**\n\n   Display:\n   - Schema being used\n   - Progress: \"N/M tasks complete\"\n   - Remaining tasks overview\n   - Dynamic instruction from CLI\n\n6. **Implement tasks (loop until done or blocked)**\n\n   For each pending task:\n   - Show which task is being worked on\n   - Make the code changes required\n   - Keep changes minimal and focused\n   - Mark task complete in the tasks file: `- [ ]` → `- [x]`\n   - Continue to next task\n\n   **Pause if:**\n   - Task is unclear → ask for clarification\n   - Implementation reveals a design issue → suggest updating artifacts\n   - Error or blocker encountered → report and wait for guidance\n   - User interrupts\n\n7. **On completion or pause, show status**\n\n   Display:\n   - Tasks completed this session\n   - Overall progress: \"N/M tasks complete\"\n   - If all done: suggest archive\n   - If paused: explain why and wait for guidance\n\n**Output During Implementation**\n\n```\n## Implementing: <change-name> (schema: <schema-name>)\n\nWorking on task 3/7: <task description>\n[...implementation happening...]\n✓ Task complete\n\nWorking on task 4/7: <task description>\n[...implementation happening...]\n✓ Task complete\n```\n\n**Output On Completion**\n\n```\n## Implementation Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 7/7 tasks complete ✓\n\n### Completed This Session\n- [x] Task 1\n- [x] Task 2\n...\n\nAll tasks complete! Ready to archive this change.\n```\n\n**Output On Pause (Issue Encountered)**\n\n```\n## Implementation Paused\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 4/7 tasks complete\n\n### Issue Encountered\n<description of the issue>\n\n**Options:**\n1. <option 1>\n2. <option 2>\n3. Other approach\n\nWhat would you like to do?\n```\n\n**Guardrails**\n- Keep going through tasks until done or blocked\n- Always read context files before starting (from the apply instructions output)\n- If task is ambiguous, pause and ask before implementing\n- If implementation reveals issues, pause and suggest artifact updates\n- Keep code changes minimal and scoped to each task\n- Update task checkbox immediately after completing each task\n- Pause on errors, blockers, or unclear requirements - don't guess\n- Use contextFiles from CLI output, don't assume specific file names\n\n**Fluid Workflow Integration**\n\nThis skill supports the \"actions on a change\" model:\n\n- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions\n- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly\n"
  },
  {
    "path": ".cursor/skills/openspec-archive-change/SKILL.md",
    "content": "---\nname: openspec-archive-change\ndescription: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nArchive a completed change in the experimental workflow.\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show only active changes (not already archived).\n   Include the schema used for each change if available.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check artifact completion status**\n\n   Run `openspec status --change \"<name>\" --json` to check artifact completion.\n\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used\n   - `artifacts`: List of artifacts with their status (`done` or other)\n\n   **If any artifacts are not `done`:**\n   - Display warning listing incomplete artifacts\n   - Use **AskUserQuestion tool** to confirm user wants to proceed\n   - Proceed if user confirms\n\n3. **Check task completion status**\n\n   Read the tasks file (typically `tasks.md`) to check for incomplete tasks.\n\n   Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).\n\n   **If incomplete tasks found:**\n   - Display warning showing count of incomplete tasks\n   - Use **AskUserQuestion tool** to confirm user wants to proceed\n   - Proceed if user confirms\n\n   **If no tasks file exists:** Proceed without task-related warning.\n\n4. **Assess delta spec sync state**\n\n   Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.\n\n   **If delta specs exist:**\n   - Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`\n   - Determine what changes would be applied (adds, modifications, removals, renames)\n   - Show a combined summary before prompting\n\n   **Prompt options:**\n   - If changes needed: \"Sync now (recommended)\", \"Archive without syncing\"\n   - If already synced: \"Archive now\", \"Sync anyway\", \"Cancel\"\n\n   If user chooses sync, execute /opsx:sync logic (use the openspec-sync-specs skill). Proceed to archive regardless of choice.\n\n5. **Perform the archive**\n\n   Create the archive directory if it doesn't exist:\n   ```bash\n   mkdir -p openspec/changes/archive\n   ```\n\n   Generate target name using current date: `YYYY-MM-DD-<change-name>`\n\n   **Check if target already exists:**\n   - If yes: Fail with error, suggest renaming existing archive or using different date\n   - If no: Move the change directory to archive\n\n   ```bash\n   mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n   ```\n\n6. **Display summary**\n\n   Show archive completion summary including:\n   - Change name\n   - Schema that was used\n   - Archive location\n   - Whether specs were synced (if applicable)\n   - Note about any warnings (incomplete artifacts/tasks)\n\n**Output On Success**\n\n```\n## Archive Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** ✓ Synced to main specs (or \"No delta specs\" or \"Sync skipped\")\n\nAll artifacts complete. All tasks complete.\n```\n\n**Guardrails**\n- Always prompt for change selection if not provided\n- Use artifact graph (openspec status --json) for completion checking\n- Don't block archive on warnings - just inform and confirm\n- Preserve .openspec.yaml when moving to archive (it moves with the directory)\n- Show clear summary of what happened\n- If sync is requested, use openspec-sync-specs approach (agent-driven)\n- If delta specs exist, always run the sync assessment and show the combined summary before prompting\n"
  },
  {
    "path": ".cursor/skills/openspec-bulk-archive-change/SKILL.md",
    "content": "---\nname: openspec-bulk-archive-change\ndescription: Archive multiple completed changes at once. Use when archiving several parallel changes.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nArchive multiple completed changes in a single operation.\n\nThis skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented.\n\n**Input**: None required (prompts for selection)\n\n**Steps**\n\n1. **Get active changes**\n\n   Run `openspec list --json` to get all active changes.\n\n   If no active changes exist, inform user and stop.\n\n2. **Prompt for change selection**\n\n   Use **AskUserQuestion tool** with multi-select to let user choose changes:\n   - Show each change with its schema\n   - Include an option for \"All changes\"\n   - Allow any number of selections (1+ works, 2+ is the typical use case)\n\n   **IMPORTANT**: Do NOT auto-select. Always let the user choose.\n\n3. **Batch validation - gather status for all selected changes**\n\n   For each selected change, collect:\n\n   a. **Artifact status** - Run `openspec status --change \"<name>\" --json`\n      - Parse `schemaName` and `artifacts` list\n      - Note which artifacts are `done` vs other states\n\n   b. **Task completion** - Read `openspec/changes/<name>/tasks.md`\n      - Count `- [ ]` (incomplete) vs `- [x]` (complete)\n      - If no tasks file exists, note as \"No tasks\"\n\n   c. **Delta specs** - Check `openspec/changes/<name>/specs/` directory\n      - List which capability specs exist\n      - For each, extract requirement names (lines matching `### Requirement: <name>`)\n\n4. **Detect spec conflicts**\n\n   Build a map of `capability -> [changes that touch it]`:\n\n   ```\n   auth -> [change-a, change-b]  <- CONFLICT (2+ changes)\n   api  -> [change-c]            <- OK (only 1 change)\n   ```\n\n   A conflict exists when 2+ selected changes have delta specs for the same capability.\n\n5. **Resolve conflicts agentically**\n\n   **For each conflict**, investigate the codebase:\n\n   a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify\n\n   b. **Search the codebase** for implementation evidence:\n      - Look for code implementing requirements from each delta spec\n      - Check for related files, functions, or tests\n\n   c. **Determine resolution**:\n      - If only one change is actually implemented -> sync that one's specs\n      - If both implemented -> apply in chronological order (older first, newer overwrites)\n      - If neither implemented -> skip spec sync, warn user\n\n   d. **Record resolution** for each conflict:\n      - Which change's specs to apply\n      - In what order (if both)\n      - Rationale (what was found in codebase)\n\n6. **Show consolidated status table**\n\n   Display a table summarizing all changes:\n\n   ```\n   | Change               | Artifacts | Tasks | Specs   | Conflicts | Status |\n   |---------------------|-----------|-------|---------|-----------|--------|\n   | schema-management   | Done      | 5/5   | 2 delta | None      | Ready  |\n   | project-config      | Done      | 3/3   | 1 delta | None      | Ready  |\n   | add-oauth           | Done      | 4/4   | 1 delta | auth (!)  | Ready* |\n   | add-verify-skill    | 1 left    | 2/5   | None    | None      | Warn   |\n   ```\n\n   For conflicts, show the resolution:\n   ```\n   * Conflict resolution:\n     - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order)\n   ```\n\n   For incomplete changes, show warnings:\n   ```\n   Warnings:\n   - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks\n   ```\n\n7. **Confirm batch operation**\n\n   Use **AskUserQuestion tool** with a single confirmation:\n\n   - \"Archive N changes?\" with options based on status\n   - Options might include:\n     - \"Archive all N changes\"\n     - \"Archive only N ready changes (skip incomplete)\"\n     - \"Cancel\"\n\n   If there are incomplete changes, make clear they'll be archived with warnings.\n\n8. **Execute archive for each confirmed change**\n\n   Process changes in the determined order (respecting conflict resolution):\n\n   a. **Sync specs** if delta specs exist:\n      - Use the openspec-sync-specs approach (agent-driven intelligent merge)\n      - For conflicts, apply in resolved order\n      - Track if sync was done\n\n   b. **Perform the archive**:\n      ```bash\n      mkdir -p openspec/changes/archive\n      mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n      ```\n\n   c. **Track outcome** for each change:\n      - Success: archived successfully\n      - Failed: error during archive (record error)\n      - Skipped: user chose not to archive (if applicable)\n\n9. **Display summary**\n\n   Show final results:\n\n   ```\n   ## Bulk Archive Complete\n\n   Archived 3 changes:\n   - schema-management-cli -> archive/2026-01-19-schema-management-cli/\n   - project-config -> archive/2026-01-19-project-config/\n   - add-oauth -> archive/2026-01-19-add-oauth/\n\n   Skipped 1 change:\n   - add-verify-skill (user chose not to archive incomplete)\n\n   Spec sync summary:\n   - 4 delta specs synced to main specs\n   - 1 conflict resolved (auth: applied both in chronological order)\n   ```\n\n   If any failures:\n   ```\n   Failed 1 change:\n   - some-change: Archive directory already exists\n   ```\n\n**Conflict Resolution Examples**\n\nExample 1: Only one implemented\n```\nConflict: specs/auth/spec.md touched by [add-oauth, add-jwt]\n\nChecking add-oauth:\n- Delta adds \"OAuth Provider Integration\" requirement\n- Searching codebase... found src/auth/oauth.ts implementing OAuth flow\n\nChecking add-jwt:\n- Delta adds \"JWT Token Handling\" requirement\n- Searching codebase... no JWT implementation found\n\nResolution: Only add-oauth is implemented. Will sync add-oauth specs only.\n```\n\nExample 2: Both implemented\n```\nConflict: specs/api/spec.md touched by [add-rest-api, add-graphql]\n\nChecking add-rest-api (created 2026-01-10):\n- Delta adds \"REST Endpoints\" requirement\n- Searching codebase... found src/api/rest.ts\n\nChecking add-graphql (created 2026-01-15):\n- Delta adds \"GraphQL Schema\" requirement\n- Searching codebase... found src/api/graphql.ts\n\nResolution: Both implemented. Will apply add-rest-api specs first,\nthen add-graphql specs (chronological order, newer takes precedence).\n```\n\n**Output On Success**\n\n```\n## Bulk Archive Complete\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n- <change-2> -> archive/YYYY-MM-DD-<change-2>/\n\nSpec sync summary:\n- N delta specs synced to main specs\n- No conflicts (or: M conflicts resolved)\n```\n\n**Output On Partial Success**\n\n```\n## Bulk Archive Complete (partial)\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n\nSkipped M changes:\n- <change-2> (user chose not to archive incomplete)\n\nFailed K changes:\n- <change-3>: Archive directory already exists\n```\n\n**Output When No Changes**\n\n```\n## No Changes to Archive\n\nNo active changes found. Use `/opsx:new` to create a new change.\n```\n\n**Guardrails**\n- Allow any number of changes (1+ is fine, 2+ is the typical use case)\n- Always prompt for selection, never auto-select\n- Detect spec conflicts early and resolve by checking codebase\n- When both changes are implemented, apply specs in chronological order\n- Skip spec sync only when implementation is missing (warn user)\n- Show clear per-change status before confirming\n- Use single confirmation for entire batch\n- Track and report all outcomes (success/skip/fail)\n- Preserve .openspec.yaml when moving to archive\n- Archive directory target uses current date: YYYY-MM-DD-<name>\n- If archive target exists, fail that change but continue with others\n"
  },
  {
    "path": ".cursor/skills/openspec-continue-change/SKILL.md",
    "content": "---\nname: openspec-continue-change\ndescription: Continue working on an OpenSpec change by creating the next artifact. Use when the user wants to progress their change, create the next artifact, or continue their workflow.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nContinue working on a change by creating the next artifact.\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes sorted by most recently modified. Then use the **AskUserQuestion tool** to let the user select which change to work on.\n\n   Present the top 3-4 most recently modified changes as options, showing:\n   - Change name\n   - Schema (from `schema` field if present, otherwise \"spec-driven\")\n   - Status (e.g., \"0/5 tasks\", \"complete\", \"no tasks\")\n   - How recently it was modified (from `lastModified` field)\n\n   Mark the most recently modified change as \"(Recommended)\" since it's likely what the user wants to continue.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check current status**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand current state. The response includes:\n   - `schemaName`: The workflow schema being used (e.g., \"spec-driven\")\n   - `artifacts`: Array of artifacts with their status (\"done\", \"ready\", \"blocked\")\n   - `isComplete`: Boolean indicating if all artifacts are complete\n\n3. **Act based on status**:\n\n   ---\n\n   **If all artifacts are complete (`isComplete: true`)**:\n   - Congratulate the user\n   - Show final status including the schema used\n   - Suggest: \"All artifacts created! You can now implement this change or archive it.\"\n   - STOP\n\n   ---\n\n   **If artifacts are ready to create** (status shows artifacts with `status: \"ready\"`):\n   - Pick the FIRST artifact with `status: \"ready\"` from the status output\n   - Get its instructions:\n     ```bash\n     openspec instructions <artifact-id> --change \"<name>\" --json\n     ```\n   - Parse the JSON. The key fields are:\n     - `context`: Project background (constraints for you - do NOT include in output)\n     - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n     - `template`: The structure to use for your output file\n     - `instruction`: Schema-specific guidance\n     - `outputPath`: Where to write the artifact\n     - `dependencies`: Completed artifacts to read for context\n   - **Create the artifact file**:\n     - Read any completed dependency files for context\n     - Use `template` as the structure - fill in its sections\n     - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file\n     - Write to the output path specified in instructions\n   - Show what was created and what's now unlocked\n   - STOP after creating ONE artifact\n\n   ---\n\n   **If no artifacts are ready (all blocked)**:\n   - This shouldn't happen with a valid schema\n   - Show status and suggest checking for issues\n\n4. **After creating an artifact, show progress**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter each invocation, show:\n- Which artifact was created\n- Schema workflow being used\n- Current progress (N/M complete)\n- What artifacts are now unlocked\n- Prompt: \"Want to continue? Just ask me to continue or tell me what to do next.\"\n\n**Artifact Creation Guidelines**\n\nThe artifact types and their purpose depend on the schema. Use the `instruction` field from the instructions output to understand what to create.\n\nCommon artifact patterns:\n\n**spec-driven schema** (proposal → specs → design → tasks):\n- **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact.\n  - The Capabilities section is critical - each capability listed will need a spec file.\n- **specs/<capability>/spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name).\n- **design.md**: Document technical decisions, architecture, and implementation approach.\n- **tasks.md**: Break down implementation into checkboxed tasks.\n\nFor other schemas, follow the `instruction` field from the CLI output.\n\n**Guardrails**\n- Create ONE artifact per invocation\n- Always read dependency artifacts before creating a new one\n- Never skip artifacts or create out of order\n- If context is unclear, ask the user before creating\n- Verify the artifact file exists after writing before marking progress\n- Use the schema's artifact sequence, don't assume specific artifact names\n- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file\n  - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact\n  - These guide what you write, but should never appear in the output\n"
  },
  {
    "path": ".cursor/skills/openspec-explore/SKILL.md",
    "content": "---\nname: openspec-explore\ndescription: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nEnter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.\n\n**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first (e.g., start a change with `/opsx:new` or `/opsx:ff`). You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.\n\n**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.\n\n---\n\n## The Stance\n\n- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script\n- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.\n- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking\n- **Adaptive** - Follow interesting threads, pivot when new information emerges\n- **Patient** - Don't rush to conclusions, let the shape of the problem emerge\n- **Grounded** - Explore the actual codebase when relevant, don't just theorize\n\n---\n\n## What You Might Do\n\nDepending on what the user brings, you might:\n\n**Explore the problem space**\n- Ask clarifying questions that emerge from what they said\n- Challenge assumptions\n- Reframe the problem\n- Find analogies\n\n**Investigate the codebase**\n- Map existing architecture relevant to the discussion\n- Find integration points\n- Identify patterns already in use\n- Surface hidden complexity\n\n**Compare options**\n- Brainstorm multiple approaches\n- Build comparison tables\n- Sketch tradeoffs\n- Recommend a path (if asked)\n\n**Visualize**\n```\n┌─────────────────────────────────────────┐\n│     Use ASCII diagrams liberally        │\n├─────────────────────────────────────────┤\n│                                         │\n│   ┌────────┐         ┌────────┐        │\n│   │ State  │────────▶│ State  │        │\n│   │   A    │         │   B    │        │\n│   └────────┘         └────────┘        │\n│                                         │\n│   System diagrams, state machines,      │\n│   data flows, architecture sketches,    │\n│   dependency graphs, comparison tables  │\n│                                         │\n└─────────────────────────────────────────┘\n```\n\n**Surface risks and unknowns**\n- Identify what could go wrong\n- Find gaps in understanding\n- Suggest spikes or investigations\n\n---\n\n## OpenSpec Awareness\n\nYou have full context of the OpenSpec system. Use it naturally, don't force it.\n\n### Check for context\n\nAt the start, quickly check what exists:\n```bash\nopenspec list --json\n```\n\nThis tells you:\n- If there are active changes\n- Their names, schemas, and status\n- What the user might be working on\n\n### When no change exists\n\nThink freely. When insights crystallize, you might offer:\n\n- \"This feels solid enough to start a change. Want me to create one?\"\n  → Can transition to `/opsx:new` or `/opsx:ff`\n- Or keep exploring - no pressure to formalize\n\n### When a change exists\n\nIf the user mentions a change or you detect one is relevant:\n\n1. **Read existing artifacts for context**\n   - `openspec/changes/<name>/proposal.md`\n   - `openspec/changes/<name>/design.md`\n   - `openspec/changes/<name>/tasks.md`\n   - etc.\n\n2. **Reference them naturally in conversation**\n   - \"Your design mentions using Redis, but we just realized SQLite fits better...\"\n   - \"The proposal scopes this to premium users, but we're now thinking everyone...\"\n\n3. **Offer to capture when decisions are made**\n\n   | Insight Type | Where to Capture |\n   |--------------|------------------|\n   | New requirement discovered | `specs/<capability>/spec.md` |\n   | Requirement changed | `specs/<capability>/spec.md` |\n   | Design decision made | `design.md` |\n   | Scope changed | `proposal.md` |\n   | New work identified | `tasks.md` |\n   | Assumption invalidated | Relevant artifact |\n\n   Example offers:\n   - \"That's a design decision. Capture it in design.md?\"\n   - \"This is a new requirement. Add it to specs?\"\n   - \"This changes scope. Update the proposal?\"\n\n4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.\n\n---\n\n## What You Don't Have To Do\n\n- Follow a script\n- Ask the same questions every time\n- Produce a specific artifact\n- Reach a conclusion\n- Stay on topic if a tangent is valuable\n- Be brief (this is thinking time)\n\n---\n\n## Handling Different Entry Points\n\n**User brings a vague idea:**\n```\nUser: I'm thinking about adding real-time collaboration\n\nYou: Real-time collab is a big space. Let me think about this...\n\n      COLLABORATION SPECTRUM\n      ════════════════════════════════════════════\n\n      Awareness          Coordination         Sync\n          │                   │                 │\n          ▼                   ▼                 ▼\n      ┌────────┐         ┌────────┐        ┌────────┐\n      │Presence│         │Cursors │        │  CRDT  │\n      │  \"3    │         │ Multi  │        │Conflict│\n      │online\" │         │ select │        │  free  │\n      └────────┘         └────────┘        └────────┘\n          │                   │                 │\n       trivial            moderate           complex\n\n      Where's your head at?\n```\n\n**User brings a specific problem:**\n```\nUser: The auth system is a mess\n\nYou: [reads codebase]\n\n     ┌─────────────────────────────────────────────┐\n     │              CURRENT AUTH FLOW              │\n     └─────────────────────────────────────────────┘\n                        │\n          ┌─────────────┼─────────────┐\n          ▼             ▼             ▼\n     ┌─────────┐  ┌─────────┐  ┌─────────┐\n     │ Google  │  │  GitHub │  │  Email  │\n     │  OAuth  │  │  OAuth  │  │  Magic  │\n     └────┬────┘  └────┬────┘  └────┬────┘\n          │             │             │\n          └─────────────┼─────────────┘\n                        ▼\n                  ┌───────────┐\n                  │  Session  │\n                  └─────┬─────┘\n                        │\n                        ▼\n                  ┌───────────┐\n                  │   Perms   │\n                  └───────────┘\n\n     I see three tangles. Which one's burning?\n```\n\n**User is stuck mid-implementation:**\n```\nUser: /opsx:explore add-auth-system\n      The OAuth integration is more complex than expected\n\nYou: [reads change artifacts]\n\n     You're on task 4: \"Implement OAuth flow\"\n\n     Let me trace what's involved...\n\n     [draws diagram, explores options, suggests paths]\n\n     Want to update the design to reflect this?\n     Or add a spike task to investigate?\n```\n\n**User wants to compare options:**\n```\nUser: Should we use Postgres or SQLite?\n\nYou: Generic answer is boring. What's the context?\n\nUser: A CLI tool that tracks local dev environments\n\nYou: That changes everything.\n\n     ┌─────────────────────────────────────────────────┐\n     │         CLI TOOL DATA STORAGE                  │\n     └─────────────────────────────────────────────────┘\n\n     Key constraints:\n     • No daemon running\n     • Must work offline\n     • Single user\n\n                  SQLite          Postgres\n     Deployment   embedded ✓      needs server ✗\n     Offline      yes ✓           no ✗\n     Single file  yes ✓           no ✗\n\n     SQLite. Not even close.\n\n     Unless... is there a sync component?\n```\n\n---\n\n## Ending Discovery\n\nThere's no required ending. Discovery might:\n\n- **Flow into action**: \"Ready to start? /opsx:new or /opsx:ff\"\n- **Result in artifact updates**: \"Updated design.md with these decisions\"\n- **Just provide clarity**: User has what they need, moves on\n- **Continue later**: \"We can pick this up anytime\"\n\nWhen it feels like things are crystallizing, you might summarize:\n\n```\n## What We Figured Out\n\n**The problem**: [crystallized understanding]\n\n**The approach**: [if one emerged]\n\n**Open questions**: [if any remain]\n\n**Next steps** (if ready):\n- Create a change: /opsx:new <name>\n- Fast-forward to tasks: /opsx:ff <name>\n- Keep exploring: just keep talking\n```\n\nBut this summary is optional. Sometimes the thinking IS the value.\n\n---\n\n## Guardrails\n\n- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.\n- **Don't fake understanding** - If something is unclear, dig deeper\n- **Don't rush** - Discovery is thinking time, not task time\n- **Don't force structure** - Let patterns emerge naturally\n- **Don't auto-capture** - Offer to save insights, don't just do it\n- **Do visualize** - A good diagram is worth many paragraphs\n- **Do explore the codebase** - Ground discussions in reality\n- **Do question assumptions** - Including the user's and your own\n"
  },
  {
    "path": ".cursor/skills/openspec-ff-change/SKILL.md",
    "content": "---\nname: openspec-ff-change\ndescription: Fast-forward through OpenSpec artifact creation. Use when the user wants to quickly create all artifacts needed for implementation without stepping through each one individually.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nFast-forward through artifact creation - generate everything needed to start implementation in one go.\n\n**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.\n\n**Steps**\n\n1. **If no clear input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   This creates a scaffolded change at `openspec/changes/<name>/`.\n\n3. **Get the artifact build order**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to get:\n   - `applyRequires`: array of artifact IDs needed before implementation (e.g., `[\"tasks\"]`)\n   - `artifacts`: list of all artifacts with their status and dependencies\n\n4. **Create artifacts in sequence until apply-ready**\n\n   Use the **TodoWrite tool** to track progress through the artifacts.\n\n   Loop through artifacts in dependency order (artifacts with no pending dependencies first):\n\n   a. **For each artifact that is `ready` (dependencies satisfied)**:\n      - Get instructions:\n        ```bash\n        openspec instructions <artifact-id> --change \"<name>\" --json\n        ```\n      - The instructions JSON includes:\n        - `context`: Project background (constraints for you - do NOT include in output)\n        - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n        - `template`: The structure to use for your output file\n        - `instruction`: Schema-specific guidance for this artifact type\n        - `outputPath`: Where to write the artifact\n        - `dependencies`: Completed artifacts to read for context\n      - Read any completed dependency files for context\n      - Create the artifact file using `template` as the structure\n      - Apply `context` and `rules` as constraints - but do NOT copy them into the file\n      - Show brief progress: \"✓ Created <artifact-id>\"\n\n   b. **Continue until all `applyRequires` artifacts are complete**\n      - After creating each artifact, re-run `openspec status --change \"<name>\" --json`\n      - Check if every artifact ID in `applyRequires` has `status: \"done\"` in the artifacts array\n      - Stop when all `applyRequires` artifacts are done\n\n   c. **If an artifact requires user input** (unclear context):\n      - Use **AskUserQuestion tool** to clarify\n      - Then continue with creation\n\n5. **Show final status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter completing all artifacts, summarize:\n- Change name and location\n- List of artifacts created with brief descriptions\n- What's ready: \"All artifacts created! Ready for implementation.\"\n- Prompt: \"Run `/opsx:apply` or ask me to implement to start working on the tasks.\"\n\n**Artifact Creation Guidelines**\n\n- Follow the `instruction` field from `openspec instructions` for each artifact type\n- The schema defines what each artifact should contain - follow it\n- Read dependency artifacts for context before creating new ones\n- Use `template` as the structure for your output file - fill in its sections\n- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file\n  - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact\n  - These guide what you write, but should never appear in the output\n\n**Guardrails**\n- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)\n- Always read dependency artifacts before creating a new one\n- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum\n- If a change with that name already exists, suggest continuing that change instead\n- Verify each artifact file exists after writing before proceeding to next\n"
  },
  {
    "path": ".cursor/skills/openspec-new-change/SKILL.md",
    "content": "---\nname: openspec-new-change\ndescription: Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nStart a new change using the experimental artifact-driven approach.\n\n**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.\n\n**Steps**\n\n1. **If no clear input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Determine the workflow schema**\n\n   Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow.\n\n   **Use a different schema only if the user mentions:**\n   - A specific schema name → use `--schema <name>`\n   - \"show workflows\" or \"what workflows\" → run `openspec schemas --json` and let them choose\n\n   **Otherwise**: Omit `--schema` to use the default.\n\n3. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   Add `--schema <name>` only if the user requested a specific workflow.\n   This creates a scaffolded change at `openspec/changes/<name>/` with the selected schema.\n\n4. **Show the artifact status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n   This shows which artifacts need to be created and which are ready (dependencies satisfied).\n\n5. **Get instructions for the first artifact**\n   The first artifact depends on the schema (e.g., `proposal` for spec-driven).\n   Check the status output to find the first artifact with status \"ready\".\n   ```bash\n   openspec instructions <first-artifact-id> --change \"<name>\"\n   ```\n   This outputs the template and context for creating the first artifact.\n\n6. **STOP and wait for user direction**\n\n**Output**\n\nAfter completing the steps, summarize:\n- Change name and location\n- Schema/workflow being used and its artifact sequence\n- Current status (0/N artifacts complete)\n- The template for the first artifact\n- Prompt: \"Ready to create the first artifact? Just describe what this change is about and I'll draft it, or ask me to continue.\"\n\n**Guardrails**\n- Do NOT create any artifacts yet - just show the instructions\n- Do NOT advance beyond showing the first artifact template\n- If the name is invalid (not kebab-case), ask for a valid name\n- If a change with that name already exists, suggest continuing that change instead\n- Pass --schema if using a non-default workflow\n"
  },
  {
    "path": ".cursor/skills/openspec-onboard/SKILL.md",
    "content": "---\nname: openspec-onboard\ndescription: Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nGuide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step.\n\n---\n\n## Preflight\n\nBefore starting, check if OpenSpec is initialized:\n\n```bash\nopenspec status --json 2>&1 || echo \"NOT_INITIALIZED\"\n```\n\n**If not initialized:**\n> OpenSpec isn't set up in this project yet. Run `openspec init` first, then come back to `/opsx:onboard`.\n\nStop here if not initialized.\n\n---\n\n## Phase 1: Welcome\n\nDisplay:\n\n```\n## Welcome to OpenSpec!\n\nI'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it.\n\n**What we'll do:**\n1. Pick a small, real task in your codebase\n2. Explore the problem briefly\n3. Create a change (the container for our work)\n4. Build the artifacts: proposal → specs → design → tasks\n5. Implement the tasks\n6. Archive the completed change\n\n**Time:** ~15-20 minutes\n\nLet's start by finding something to work on.\n```\n\n---\n\n## Phase 2: Task Selection\n\n### Codebase Analysis\n\nScan the codebase for small improvement opportunities. Look for:\n\n1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files\n2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch\n3. **Functions without tests** - Cross-reference `src/` with test directories\n4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`)\n5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code\n6. **Missing validation** - User input handlers without validation\n\nAlso check recent git activity:\n```bash\ngit log --oneline -10 2>/dev/null || echo \"No git history\"\n```\n\n### Present Suggestions\n\nFrom your analysis, present 3-4 specific suggestions:\n\n```\n## Task Suggestions\n\nBased on scanning your codebase, here are some good starter tasks:\n\n**1. [Most promising task]**\n   Location: `src/path/to/file.ts:42`\n   Scope: ~1-2 files, ~20-30 lines\n   Why it's good: [brief reason]\n\n**2. [Second task]**\n   Location: `src/another/file.ts`\n   Scope: ~1 file, ~15 lines\n   Why it's good: [brief reason]\n\n**3. [Third task]**\n   Location: [location]\n   Scope: [estimate]\n   Why it's good: [brief reason]\n\n**4. Something else?**\n   Tell me what you'd like to work on.\n\nWhich task interests you? (Pick a number or describe your own)\n```\n\n**If nothing found:** Fall back to asking what the user wants to build:\n> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix?\n\n### Scope Guardrail\n\nIf the user picks or describes something too large (major feature, multi-day work):\n\n```\nThat's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through.\n\nFor learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details.\n\n**Options:**\n1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]?\n2. **Pick something else** - One of the other suggestions, or a different small task?\n3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer.\n\nWhat would you prefer?\n```\n\nLet the user override if they insist—this is a soft guardrail.\n\n---\n\n## Phase 3: Explore Demo\n\nOnce a task is selected, briefly demonstrate explore mode:\n\n```\nBefore we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction.\n```\n\nSpend 1-2 minutes investigating the relevant code:\n- Read the file(s) involved\n- Draw a quick ASCII diagram if it helps\n- Note any considerations\n\n```\n## Quick Exploration\n\n[Your brief analysis—what you found, any considerations]\n\n┌─────────────────────────────────────────┐\n│   [Optional: ASCII diagram if helpful]  │\n└─────────────────────────────────────────┘\n\nExplore mode (`/opsx:explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem.\n\nNow let's create a change to hold our work.\n```\n\n**PAUSE** - Wait for user acknowledgment before proceeding.\n\n---\n\n## Phase 4: Create the Change\n\n**EXPLAIN:**\n```\n## Creating a Change\n\nA \"change\" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives in `openspec/changes/<name>/` and holds your artifacts—proposal, specs, design, tasks.\n\nLet me create one for our task.\n```\n\n**DO:** Create the change with a derived kebab-case name:\n```bash\nopenspec new change \"<derived-name>\"\n```\n\n**SHOW:**\n```\nCreated: `openspec/changes/<name>/`\n\nThe folder structure:\n```\nopenspec/changes/<name>/\n├── proposal.md    ← Why we're doing this (empty, we'll fill it)\n├── design.md      ← How we'll build it (empty)\n├── specs/         ← Detailed requirements (empty)\n└── tasks.md       ← Implementation checklist (empty)\n```\n\nNow let's fill in the first artifact—the proposal.\n```\n\n---\n\n## Phase 5: Proposal\n\n**EXPLAIN:**\n```\n## The Proposal\n\nThe proposal captures **why** we're making this change and **what** it involves at a high level. It's the \"elevator pitch\" for the work.\n\nI'll draft one based on our task.\n```\n\n**DO:** Draft the proposal content (don't save yet):\n\n```\nHere's a draft proposal:\n\n---\n\n## Why\n\n[1-2 sentences explaining the problem/opportunity]\n\n## What Changes\n\n[Bullet points of what will be different]\n\n## Capabilities\n\n### New Capabilities\n- `<capability-name>`: [brief description]\n\n### Modified Capabilities\n<!-- If modifying existing behavior -->\n\n## Impact\n\n- `src/path/to/file.ts`: [what changes]\n- [other files if applicable]\n\n---\n\nDoes this capture the intent? I can adjust before we save it.\n```\n\n**PAUSE** - Wait for user approval/feedback.\n\nAfter approval, save the proposal:\n```bash\nopenspec instructions proposal --change \"<name>\" --json\n```\nThen write the content to `openspec/changes/<name>/proposal.md`.\n\n```\nProposal saved. This is your \"why\" document—you can always come back and refine it as understanding evolves.\n\nNext up: specs.\n```\n\n---\n\n## Phase 6: Specs\n\n**EXPLAIN:**\n```\n## Specs\n\nSpecs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear.\n\nFor a small task like this, we might only need one spec file.\n```\n\n**DO:** Create the spec file:\n```bash\nmkdir -p openspec/changes/<name>/specs/<capability-name>\n```\n\nDraft the spec content:\n\n```\nHere's the spec:\n\n---\n\n## ADDED Requirements\n\n### Requirement: <Name>\n\n<Description of what the system should do>\n\n#### Scenario: <Scenario name>\n\n- **WHEN** <trigger condition>\n- **THEN** <expected outcome>\n- **AND** <additional outcome if needed>\n\n---\n\nThis format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases.\n```\n\nSave to `openspec/changes/<name>/specs/<capability>/spec.md`.\n\n---\n\n## Phase 7: Design\n\n**EXPLAIN:**\n```\n## Design\n\nThe design captures **how** we'll build it—technical decisions, tradeoffs, approach.\n\nFor small changes, this might be brief. That's fine—not every change needs deep design discussion.\n```\n\n**DO:** Draft design.md:\n\n```\nHere's the design:\n\n---\n\n## Context\n\n[Brief context about the current state]\n\n## Goals / Non-Goals\n\n**Goals:**\n- [What we're trying to achieve]\n\n**Non-Goals:**\n- [What's explicitly out of scope]\n\n## Decisions\n\n### Decision 1: [Key decision]\n\n[Explanation of approach and rationale]\n\n---\n\nFor a small task, this captures the key decisions without over-engineering.\n```\n\nSave to `openspec/changes/<name>/design.md`.\n\n---\n\n## Phase 8: Tasks\n\n**EXPLAIN:**\n```\n## Tasks\n\nFinally, we break the work into implementation tasks—checkboxes that drive the apply phase.\n\nThese should be small, clear, and in logical order.\n```\n\n**DO:** Generate tasks based on specs and design:\n\n```\nHere are the implementation tasks:\n\n---\n\n## 1. [Category or file]\n\n- [ ] 1.1 [Specific task]\n- [ ] 1.2 [Specific task]\n\n## 2. Verify\n\n- [ ] 2.1 [Verification step]\n\n---\n\nEach checkbox becomes a unit of work in the apply phase. Ready to implement?\n```\n\n**PAUSE** - Wait for user to confirm they're ready to implement.\n\nSave to `openspec/changes/<name>/tasks.md`.\n\n---\n\n## Phase 9: Apply (Implementation)\n\n**EXPLAIN:**\n```\n## Implementation\n\nNow we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach.\n```\n\n**DO:** For each task:\n\n1. Announce: \"Working on task N: [description]\"\n2. Implement the change in the codebase\n3. Reference specs/design naturally: \"The spec says X, so I'm doing Y\"\n4. Mark complete in tasks.md: `- [ ]` → `- [x]`\n5. Brief status: \"✓ Task N complete\"\n\nKeep narration light—don't over-explain every line of code.\n\nAfter all tasks:\n\n```\n## Implementation Complete\n\nAll tasks done:\n- [x] Task 1\n- [x] Task 2\n- [x] ...\n\nThe change is implemented! One more step—let's archive it.\n```\n\n---\n\n## Phase 10: Archive\n\n**EXPLAIN:**\n```\n## Archiving\n\nWhen a change is complete, we archive it. This moves it from `openspec/changes/` to `openspec/changes/archive/YYYY-MM-DD-<name>/`.\n\nArchived changes become your project's decision history—you can always find them later to understand why something was built a certain way.\n```\n\n**DO:**\n```bash\nopenspec archive \"<name>\"\n```\n\n**SHOW:**\n```\nArchived to: `openspec/changes/archive/YYYY-MM-DD-<name>/`\n\nThe change is now part of your project's history. The code is in your codebase, the decision record is preserved.\n```\n\n---\n\n## Phase 11: Recap & Next Steps\n\n```\n## Congratulations!\n\nYou just completed a full OpenSpec cycle:\n\n1. **Explore** - Thought through the problem\n2. **New** - Created a change container\n3. **Proposal** - Captured WHY\n4. **Specs** - Defined WHAT in detail\n5. **Design** - Decided HOW\n6. **Tasks** - Broke it into steps\n7. **Apply** - Implemented the work\n8. **Archive** - Preserved the record\n\nThis same rhythm works for any size change—a small fix or a major feature.\n\n---\n\n## Command Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems before/during work |\n| `/opsx:new` | Start a new change, step through artifacts |\n| `/opsx:ff` | Fast-forward: create all artifacts at once |\n| `/opsx:continue` | Continue working on an existing change |\n| `/opsx:apply` | Implement tasks from a change |\n| `/opsx:verify` | Verify implementation matches artifacts |\n| `/opsx:archive` | Archive a completed change |\n\n---\n\n## What's Next?\n\nTry `/opsx:new` or `/opsx:ff` on something you actually want to build. You've got the rhythm now!\n```\n\n---\n\n## Graceful Exit Handling\n\n### User wants to stop mid-way\n\nIf the user says they need to stop, want to pause, or seem disengaged:\n\n```\nNo problem! Your change is saved at `openspec/changes/<name>/`.\n\nTo pick up where we left off later:\n- `/opsx:continue <name>` - Resume artifact creation\n- `/opsx:apply <name>` - Jump to implementation (if tasks exist)\n\nThe work won't be lost. Come back whenever you're ready.\n```\n\nExit gracefully without pressure.\n\n### User just wants command reference\n\nIf the user says they just want to see the commands or skip the tutorial:\n\n```\n## OpenSpec Quick Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems (no code changes) |\n| `/opsx:new <name>` | Start a new change, step by step |\n| `/opsx:ff <name>` | Fast-forward: all artifacts at once |\n| `/opsx:continue <name>` | Continue an existing change |\n| `/opsx:apply <name>` | Implement tasks |\n| `/opsx:verify <name>` | Verify implementation |\n| `/opsx:archive <name>` | Archive when done |\n\nTry `/opsx:new` to start your first change, or `/opsx:ff` if you want to move fast.\n```\n\nExit gracefully.\n\n---\n\n## Guardrails\n\n- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive)\n- **Keep narration light** during implementation—teach without lecturing\n- **Don't skip phases** even if the change is small—the goal is teaching the workflow\n- **Pause for acknowledgment** at marked points, but don't over-pause\n- **Handle exits gracefully**—never pressure the user to continue\n- **Use real codebase tasks**—don't simulate or use fake examples\n- **Adjust scope gently**—guide toward smaller tasks but respect user choice\n"
  },
  {
    "path": ".cursor/skills/openspec-sync-specs/SKILL.md",
    "content": "---\nname: openspec-sync-specs\ndescription: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nSync delta specs from a change to main specs.\n\nThis is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have delta specs (under `specs/` directory).\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Find delta specs**\n\n   Look for delta spec files in `openspec/changes/<name>/specs/*/spec.md`.\n\n   Each delta spec file contains sections like:\n   - `## ADDED Requirements` - New requirements to add\n   - `## MODIFIED Requirements` - Changes to existing requirements\n   - `## REMOVED Requirements` - Requirements to remove\n   - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)\n\n   If no delta specs found, inform user and stop.\n\n3. **For each delta spec, apply changes to main specs**\n\n   For each capability with a delta spec at `openspec/changes/<name>/specs/<capability>/spec.md`:\n\n   a. **Read the delta spec** to understand the intended changes\n\n   b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)\n\n   c. **Apply changes intelligently**:\n\n      **ADDED Requirements:**\n      - If requirement doesn't exist in main spec → add it\n      - If requirement already exists → update it to match (treat as implicit MODIFIED)\n\n      **MODIFIED Requirements:**\n      - Find the requirement in main spec\n      - Apply the changes - this can be:\n        - Adding new scenarios (don't need to copy existing ones)\n        - Modifying existing scenarios\n        - Changing the requirement description\n      - Preserve scenarios/content not mentioned in the delta\n\n      **REMOVED Requirements:**\n      - Remove the entire requirement block from main spec\n\n      **RENAMED Requirements:**\n      - Find the FROM requirement, rename to TO\n\n   d. **Create new main spec** if capability doesn't exist yet:\n      - Create `openspec/specs/<capability>/spec.md`\n      - Add Purpose section (can be brief, mark as TBD)\n      - Add Requirements section with the ADDED requirements\n\n4. **Show summary**\n\n   After applying all changes, summarize:\n   - Which capabilities were updated\n   - What changes were made (requirements added/modified/removed/renamed)\n\n**Delta Spec Format Reference**\n\n```markdown\n## ADDED Requirements\n\n### Requirement: New Feature\nThe system SHALL do something new.\n\n#### Scenario: Basic case\n- **WHEN** user does X\n- **THEN** system does Y\n\n## MODIFIED Requirements\n\n### Requirement: Existing Feature\n#### Scenario: New scenario to add\n- **WHEN** user does A\n- **THEN** system does B\n\n## REMOVED Requirements\n\n### Requirement: Deprecated Feature\n\n## RENAMED Requirements\n\n- FROM: `### Requirement: Old Name`\n- TO: `### Requirement: New Name`\n```\n\n**Key Principle: Intelligent Merging**\n\nUnlike programmatic merging, you can apply **partial updates**:\n- To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios\n- The delta represents *intent*, not a wholesale replacement\n- Use your judgment to merge changes sensibly\n\n**Output On Success**\n\n```\n## Specs Synced: <change-name>\n\nUpdated main specs:\n\n**<capability-1>**:\n- Added requirement: \"New Feature\"\n- Modified requirement: \"Existing Feature\" (added 1 scenario)\n\n**<capability-2>**:\n- Created new spec file\n- Added requirement: \"Another Feature\"\n\nMain specs are now updated. The change remains active - archive when implementation is complete.\n```\n\n**Guardrails**\n- Read both delta and main specs before making changes\n- Preserve existing content not mentioned in delta\n- If something is unclear, ask for clarification\n- Show what you're changing as you go\n- The operation should be idempotent - running twice should give same result\n"
  },
  {
    "path": ".cursor/skills/openspec-verify-change/SKILL.md",
    "content": "---\nname: openspec-verify-change\ndescription: Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nVerify that an implementation matches the change artifacts (specs, tasks, design).\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have implementation tasks (tasks artifact exists).\n   Include the schema used for each change if available.\n   Mark changes with incomplete tasks as \"(In Progress)\".\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifacts exist for this change\n\n3. **Get the change directory and load artifacts**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns the change directory and context files. Read all available artifacts from `contextFiles`.\n\n4. **Initialize verification report structure**\n\n   Create a report structure with three dimensions:\n   - **Completeness**: Track tasks and spec coverage\n   - **Correctness**: Track requirement implementation and scenario coverage\n   - **Coherence**: Track design adherence and pattern consistency\n\n   Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.\n\n5. **Verify Completeness**\n\n   **Task Completion**:\n   - If tasks.md exists in contextFiles, read it\n   - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete)\n   - Count complete vs total tasks\n   - If incomplete tasks exist:\n     - Add CRITICAL issue for each incomplete task\n     - Recommendation: \"Complete task: <description>\" or \"Mark as done if already implemented\"\n\n   **Spec Coverage**:\n   - If delta specs exist in `openspec/changes/<name>/specs/`:\n     - Extract all requirements (marked with \"### Requirement:\")\n     - For each requirement:\n       - Search codebase for keywords related to the requirement\n       - Assess if implementation likely exists\n     - If requirements appear unimplemented:\n       - Add CRITICAL issue: \"Requirement not found: <requirement name>\"\n       - Recommendation: \"Implement requirement X: <description>\"\n\n6. **Verify Correctness**\n\n   **Requirement Implementation Mapping**:\n   - For each requirement from delta specs:\n     - Search codebase for implementation evidence\n     - If found, note file paths and line ranges\n     - Assess if implementation matches requirement intent\n     - If divergence detected:\n       - Add WARNING: \"Implementation may diverge from spec: <details>\"\n       - Recommendation: \"Review <file>:<lines> against requirement X\"\n\n   **Scenario Coverage**:\n   - For each scenario in delta specs (marked with \"#### Scenario:\"):\n     - Check if conditions are handled in code\n     - Check if tests exist covering the scenario\n     - If scenario appears uncovered:\n       - Add WARNING: \"Scenario not covered: <scenario name>\"\n       - Recommendation: \"Add test or implementation for scenario: <description>\"\n\n7. **Verify Coherence**\n\n   **Design Adherence**:\n   - If design.md exists in contextFiles:\n     - Extract key decisions (look for sections like \"Decision:\", \"Approach:\", \"Architecture:\")\n     - Verify implementation follows those decisions\n     - If contradiction detected:\n       - Add WARNING: \"Design decision not followed: <decision>\"\n       - Recommendation: \"Update implementation or revise design.md to match reality\"\n   - If no design.md: Skip design adherence check, note \"No design.md to verify against\"\n\n   **Code Pattern Consistency**:\n   - Review new code for consistency with project patterns\n   - Check file naming, directory structure, coding style\n   - If significant deviations found:\n     - Add SUGGESTION: \"Code pattern deviation: <details>\"\n     - Recommendation: \"Consider following project pattern: <example>\"\n\n8. **Generate Verification Report**\n\n   **Summary Scorecard**:\n   ```\n   ## Verification Report: <change-name>\n\n   ### Summary\n   | Dimension    | Status           |\n   |--------------|------------------|\n   | Completeness | X/Y tasks, N reqs|\n   | Correctness  | M/N reqs covered |\n   | Coherence    | Followed/Issues  |\n   ```\n\n   **Issues by Priority**:\n\n   1. **CRITICAL** (Must fix before archive):\n      - Incomplete tasks\n      - Missing requirement implementations\n      - Each with specific, actionable recommendation\n\n   2. **WARNING** (Should fix):\n      - Spec/design divergences\n      - Missing scenario coverage\n      - Each with specific recommendation\n\n   3. **SUGGESTION** (Nice to fix):\n      - Pattern inconsistencies\n      - Minor improvements\n      - Each with specific recommendation\n\n   **Final Assessment**:\n   - If CRITICAL issues: \"X critical issue(s) found. Fix before archiving.\"\n   - If only warnings: \"No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements).\"\n   - If all clear: \"All checks passed. Ready for archive.\"\n\n**Verification Heuristics**\n\n- **Completeness**: Focus on objective checklist items (checkboxes, requirements list)\n- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty\n- **Coherence**: Look for glaring inconsistencies, don't nitpick style\n- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL\n- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable\n\n**Graceful Degradation**\n\n- If only tasks.md exists: verify task completion only, skip spec/design checks\n- If tasks + specs exist: verify completeness and correctness, skip design\n- If full artifacts: verify all three dimensions\n- Always note which checks were skipped and why\n\n**Output Format**\n\nUse clear markdown with:\n- Table for summary scorecard\n- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION)\n- Code references in format: `file.ts:123`\n- Specific, actionable recommendations\n- No vague suggestions like \"consider reviewing\"\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug report\ndescription: Create a report to help us improve\ntitle: \"[BUG] \"\nlabels: [\"bug\", \"triage\"]\nassignees: []\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n  - type: input\n    id: dbtype\n    attributes:\n      label: Database Type\n      description: What database are you using?\n      placeholder: e.g., MySQL, Oracle...\n    validations:\n      required: true\n  - type: input\n    id: dbversion\n    attributes:\n      label: Database Version\n      description: What version of the database are you using?\n      placeholder: e.g., MySQL 5.7, Oracle 12c...\n    validations:\n      required: true\n  - type: input\n    id: druid-version\n    attributes:\n      label: Druid Version\n      description: What version of Druid are you using?\n      placeholder: e.g., 1.2.22\n    validations:\n      required: true\n  - type: input\n    id: jdk-version\n    attributes:\n      label: JDK Version\n      description: What version of JDK are you using?\n      placeholder: e.g., OpenJDK 11\n    validations:\n      required: true\n  - type: textarea\n    id: error-sql\n    attributes:\n      label: Error SQL\n      description: Please provide the SQL that caused the error.\n      placeholder: SELECT * FROM your_table\n    validations:\n      required: true\n  - type: textarea\n    id: testcase-code\n    attributes:\n      label: Testcase Code\n      description: Please provide the testcase code that reproduces the issue.\n      placeholder: |\n        ```java\n        // Your testcase code here\n        ```\n    validations:\n      required: false\n  - type: textarea\n    id: stacktrace-info\n    attributes:\n      label: Stacktrace Info\n      description: Please provide the stacktrace information if applicable.\n      placeholder: |\n        ```java\n        // Your stacktrace here\n        ```\n    validations:\n      required: false\n  - type: textarea\n    id: error-info\n    attributes:\n      label: Error Info\n      description: Please provide any additional error information or logs.\n      placeholder: |\n        ```log\n        // Your error info or logs here\n        ```\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--\nplease follow the issue template below for bug reports and feature requests\nfor example, if you are reporting a bug, please provide the following information:\ndbtype: mysql\ndbversion: 5.7\nduird version: 1.2.22\njdk version: 17\nerror sql: select * from test\nerror info: error message\n-->\n**dbtype:** \n**dbversion:** \n**druid verion:**\n**jdk verion:**\n**error sql:**\n**testcase code:**\n**stacktrace info:**\n**error info:**\n---\n<!--\nThanks for taking the time to create an issue. Please read the following:\n\n- For bugs, specify affected versions and explain what you are trying to do.\n- For enhancements, provide context and describe the problem.\n\nIssue or Pull Request? Create only one, not both. GitHub treats them as the same.\nIf unsure, start with an issue, and if you submit a pull request later, the\nissue will be closed as superseded.\n-->\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "---\nname: Java CI\n\non:\n  push:\n    # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-excluding-paths\n    paths-ignore:\n      - 'docs/**'\n      - '**.md'\n  pull_request:\n    paths-ignore:\n      - 'docs/**'\n      - '**.md'\n\njobs:\n  test:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ ubuntu-latest ]\n        java: [ 8, 11, 17, 21 ]\n      fail-fast: false\n      max-parallel: 16\n    name: Test JDK ${{ matrix.java }}, ${{ matrix.os }}\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up JDK\n        uses: actions/setup-java@v4\n        with:\n          distribution: 'temurin'\n          java-version: ${{ matrix.java }}\n          cache: 'maven'\n      - name: Build with Maven if test jdk8\n        if: ${{ matrix.java == '8' || matrix.java == '11'}}\n        run: ./mvnw -Pgen-javadoc clean package -B\n      - name: Build with Maven if test jdk17\n        if: ${{ matrix.java == '17' || matrix.java == '21' }}\n        run: ./mvnw -Penable-for-jdk17+,gen-code-cov clean package -B\n      - name: \"Codecov if test jdk17\"\n        if: ${{ matrix.java == '17' }}\n        uses: codecov/codecov-action@v3.1.0\n        with:\n          files: ./core/target/site/jacoco/jacoco.xml,./druid-spring-boot-starter/target/site/jacoco/jacoco.xml,./druid-spring-boot-3-starter/target/site/jacoco/jacoco.xml\n"
  },
  {
    "path": ".gitignore",
    "content": "target\r\n.settings\r\n.project\r\n.classpath\r\n.DS_Store\r\n/1\r\n/derby.log\r\n/src/test/resources/pool_config\r\n/src/test/java/com/alibaba/druid/local_test\r\n/src/test/java/com/alibaba/druid/pool/mysql/\r\n# IntelliJ Idea\r\n.idea/\r\nout/\r\n*.ipr\r\n*.iws\r\n*.iml\r\n/bin\r\n/druid-inner-test\r\nhs_err_pid*.log\r\nreplay_pid*.log\r\n/core/derby.log\r\n/demo-db.mv.db\r\n/demo-db.trace.db\r\n\r\n.vscode\r\ndruid-spring-boot-3-starter/demo-db.mv.db\r\n/worktrees/\r\n.claude/worktrees/\n"
  },
  {
    "path": ".mvn/wrapper/MavenWrapperDownloader.java",
    "content": "/*\n * Copyright 2007-present the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport java.net.*;\nimport java.io.*;\nimport java.nio.channels.*;\nimport java.util.Properties;\n\npublic class MavenWrapperDownloader {\n    private static final String WRAPPER_VERSION = \"0.5.6\";\n    /**\n     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.\n     */\n    private static final String DEFAULT_DOWNLOAD_URL = \"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/\"\n        + WRAPPER_VERSION + \"/maven-wrapper-\" + WRAPPER_VERSION + \".jar\";\n\n    /**\n     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to\n     * use instead of the default one.\n     */\n    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =\n            \".mvn/wrapper/maven-wrapper.properties\";\n\n    /**\n     * Path where the maven-wrapper.jar will be saved to.\n     */\n    private static final String MAVEN_WRAPPER_JAR_PATH =\n            \".mvn/wrapper/maven-wrapper.jar\";\n\n    /**\n     * Name of the property which should be used to override the default download url for the wrapper.\n     */\n    private static final String PROPERTY_NAME_WRAPPER_URL = \"wrapperUrl\";\n\n    public static void main(String args[]) {\n        System.out.println(\"- Downloader started\");\n        File baseDirectory = new File(args[0]);\n        System.out.println(\"- Using base directory: \" + baseDirectory.getAbsolutePath());\n\n        // If the maven-wrapper.properties exists, read it and check if it contains a custom\n        // wrapperUrl parameter.\n        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);\n        String url = DEFAULT_DOWNLOAD_URL;\n        if(mavenWrapperPropertyFile.exists()) {\n            FileInputStream mavenWrapperPropertyFileInputStream = null;\n            try {\n                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);\n                Properties mavenWrapperProperties = new Properties();\n                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);\n                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);\n            } catch (IOException e) {\n                System.out.println(\"- ERROR loading '\" + MAVEN_WRAPPER_PROPERTIES_PATH + \"'\");\n            } finally {\n                try {\n                    if(mavenWrapperPropertyFileInputStream != null) {\n                        mavenWrapperPropertyFileInputStream.close();\n                    }\n                } catch (IOException e) {\n                    // Ignore ...\n                }\n            }\n        }\n        System.out.println(\"- Downloading from: \" + url);\n\n        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);\n        if(!outputFile.getParentFile().exists()) {\n            if(!outputFile.getParentFile().mkdirs()) {\n                System.out.println(\n                        \"- ERROR creating output directory '\" + outputFile.getParentFile().getAbsolutePath() + \"'\");\n            }\n        }\n        System.out.println(\"- Downloading to: \" + outputFile.getAbsolutePath());\n        try {\n            downloadFileFromURL(url, outputFile);\n            System.out.println(\"Done\");\n            System.exit(0);\n        } catch (Throwable e) {\n            System.out.println(\"- Error downloading\");\n            e.printStackTrace();\n            System.exit(1);\n        }\n    }\n\n    private static void downloadFileFromURL(String urlString, File destination) throws Exception {\n        if (System.getenv(\"MVNW_USERNAME\") != null && System.getenv(\"MVNW_PASSWORD\") != null) {\n            String username = System.getenv(\"MVNW_USERNAME\");\n            char[] password = System.getenv(\"MVNW_PASSWORD\").toCharArray();\n            Authenticator.setDefault(new Authenticator() {\n                @Override\n                protected PasswordAuthentication getPasswordAuthentication() {\n                    return new PasswordAuthentication(username, password);\n                }\n            });\n        }\n        URL website = new URL(urlString);\n        ReadableByteChannel rbc;\n        rbc = Channels.newChannel(website.openStream());\n        FileOutputStream fos = new FileOutputStream(destination);\n        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);\n        fos.close();\n        rbc.close();\n    }\n\n}\n"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "content": "distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip\nwrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar\n"
  },
  {
    "path": ".qoder/commands/opsx/apply.md",
    "content": "---\nname: OPSX: Apply\ndescription: Implement tasks from an OpenSpec change (Experimental)\ncategory: Workflow\ntags: [workflow, artifacts, experimental]\n---\n\nImplement tasks from an OpenSpec change.\n\n**Input**: Optionally specify a change name (e.g., `/opsx:apply add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **Select the change**\n\n   If a name is provided, use it. Otherwise:\n   - Infer from conversation context if the user mentioned a change\n   - Auto-select if only one active change exists\n   - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select\n\n   Always announce: \"Using change: <name>\" and how to override (e.g., `/opsx:apply <other>`).\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifact contains the tasks (typically \"tasks\" for spec-driven, check status for others)\n\n3. **Get apply instructions**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns:\n   - Context file paths (varies by schema)\n   - Progress (total, complete, remaining)\n   - Task list with status\n   - Dynamic instruction based on current state\n\n   **Handle states:**\n   - If `state: \"blocked\"` (missing artifacts): show message, suggest using `/opsx:continue`\n   - If `state: \"all_done\"`: congratulate, suggest archive\n   - Otherwise: proceed to implementation\n\n4. **Read context files**\n\n   Read the files listed in `contextFiles` from the apply instructions output.\n   The files depend on the schema being used:\n   - **spec-driven**: proposal, specs, design, tasks\n   - Other schemas: follow the contextFiles from CLI output\n\n5. **Show current progress**\n\n   Display:\n   - Schema being used\n   - Progress: \"N/M tasks complete\"\n   - Remaining tasks overview\n   - Dynamic instruction from CLI\n\n6. **Implement tasks (loop until done or blocked)**\n\n   For each pending task:\n   - Show which task is being worked on\n   - Make the code changes required\n   - Keep changes minimal and focused\n   - Mark task complete in the tasks file: `- [ ]` → `- [x]`\n   - Continue to next task\n\n   **Pause if:**\n   - Task is unclear → ask for clarification\n   - Implementation reveals a design issue → suggest updating artifacts\n   - Error or blocker encountered → report and wait for guidance\n   - User interrupts\n\n7. **On completion or pause, show status**\n\n   Display:\n   - Tasks completed this session\n   - Overall progress: \"N/M tasks complete\"\n   - If all done: suggest archive\n   - If paused: explain why and wait for guidance\n\n**Output During Implementation**\n\n```\n## Implementing: <change-name> (schema: <schema-name>)\n\nWorking on task 3/7: <task description>\n[...implementation happening...]\n✓ Task complete\n\nWorking on task 4/7: <task description>\n[...implementation happening...]\n✓ Task complete\n```\n\n**Output On Completion**\n\n```\n## Implementation Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 7/7 tasks complete ✓\n\n### Completed This Session\n- [x] Task 1\n- [x] Task 2\n...\n\nAll tasks complete! You can archive this change with `/opsx:archive`.\n```\n\n**Output On Pause (Issue Encountered)**\n\n```\n## Implementation Paused\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 4/7 tasks complete\n\n### Issue Encountered\n<description of the issue>\n\n**Options:**\n1. <option 1>\n2. <option 2>\n3. Other approach\n\nWhat would you like to do?\n```\n\n**Guardrails**\n- Keep going through tasks until done or blocked\n- Always read context files before starting (from the apply instructions output)\n- If task is ambiguous, pause and ask before implementing\n- If implementation reveals issues, pause and suggest artifact updates\n- Keep code changes minimal and scoped to each task\n- Update task checkbox immediately after completing each task\n- Pause on errors, blockers, or unclear requirements - don't guess\n- Use contextFiles from CLI output, don't assume specific file names\n\n**Fluid Workflow Integration**\n\nThis skill supports the \"actions on a change\" model:\n\n- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions\n- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly\n"
  },
  {
    "path": ".qoder/commands/opsx/archive.md",
    "content": "---\nname: OPSX: Archive\ndescription: Archive a completed change in the experimental workflow\ncategory: Workflow\ntags: [workflow, archive, experimental]\n---\n\nArchive a completed change in the experimental workflow.\n\n**Input**: Optionally specify a change name after `/opsx:archive` (e.g., `/opsx:archive add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show only active changes (not already archived).\n   Include the schema used for each change if available.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check artifact completion status**\n\n   Run `openspec status --change \"<name>\" --json` to check artifact completion.\n\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used\n   - `artifacts`: List of artifacts with their status (`done` or other)\n\n   **If any artifacts are not `done`:**\n   - Display warning listing incomplete artifacts\n   - Prompt user for confirmation to continue\n   - Proceed if user confirms\n\n3. **Check task completion status**\n\n   Read the tasks file (typically `tasks.md`) to check for incomplete tasks.\n\n   Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).\n\n   **If incomplete tasks found:**\n   - Display warning showing count of incomplete tasks\n   - Prompt user for confirmation to continue\n   - Proceed if user confirms\n\n   **If no tasks file exists:** Proceed without task-related warning.\n\n4. **Assess delta spec sync state**\n\n   Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.\n\n   **If delta specs exist:**\n   - Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`\n   - Determine what changes would be applied (adds, modifications, removals, renames)\n   - Show a combined summary before prompting\n\n   **Prompt options:**\n   - If changes needed: \"Sync now (recommended)\", \"Archive without syncing\"\n   - If already synced: \"Archive now\", \"Sync anyway\", \"Cancel\"\n\n   If user chooses sync, execute `/opsx:sync` logic. Proceed to archive regardless of choice.\n\n5. **Perform the archive**\n\n   Create the archive directory if it doesn't exist:\n   ```bash\n   mkdir -p openspec/changes/archive\n   ```\n\n   Generate target name using current date: `YYYY-MM-DD-<change-name>`\n\n   **Check if target already exists:**\n   - If yes: Fail with error, suggest renaming existing archive or using different date\n   - If no: Move the change directory to archive\n\n   ```bash\n   mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n   ```\n\n6. **Display summary**\n\n   Show archive completion summary including:\n   - Change name\n   - Schema that was used\n   - Archive location\n   - Spec sync status (synced / sync skipped / no delta specs)\n   - Note about any warnings (incomplete artifacts/tasks)\n\n**Output On Success**\n\n```\n## Archive Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** ✓ Synced to main specs\n\nAll artifacts complete. All tasks complete.\n```\n\n**Output On Success (No Delta Specs)**\n\n```\n## Archive Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** No delta specs\n\nAll artifacts complete. All tasks complete.\n```\n\n**Output On Success With Warnings**\n\n```\n## Archive Complete (with warnings)\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** Sync skipped (user chose to skip)\n\n**Warnings:**\n- Archived with 2 incomplete artifacts\n- Archived with 3 incomplete tasks\n- Delta spec sync was skipped (user chose to skip)\n\nReview the archive if this was not intentional.\n```\n\n**Output On Error (Archive Exists)**\n\n```\n## Archive Failed\n\n**Change:** <change-name>\n**Target:** openspec/changes/archive/YYYY-MM-DD-<name>/\n\nTarget archive directory already exists.\n\n**Options:**\n1. Rename the existing archive\n2. Delete the existing archive if it's a duplicate\n3. Wait until a different date to archive\n```\n\n**Guardrails**\n- Always prompt for change selection if not provided\n- Use artifact graph (openspec status --json) for completion checking\n- Don't block archive on warnings - just inform and confirm\n- Preserve .openspec.yaml when moving to archive (it moves with the directory)\n- Show clear summary of what happened\n- If sync is requested, use /opsx:sync approach (agent-driven)\n- If delta specs exist, always run the sync assessment and show the combined summary before prompting\n"
  },
  {
    "path": ".qoder/commands/opsx/bulk-archive.md",
    "content": "---\nname: OPSX: Bulk Archive\ndescription: Archive multiple completed changes at once\ncategory: Workflow\ntags: [workflow, archive, experimental, bulk]\n---\n\nArchive multiple completed changes in a single operation.\n\nThis skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented.\n\n**Input**: None required (prompts for selection)\n\n**Steps**\n\n1. **Get active changes**\n\n   Run `openspec list --json` to get all active changes.\n\n   If no active changes exist, inform user and stop.\n\n2. **Prompt for change selection**\n\n   Use **AskUserQuestion tool** with multi-select to let user choose changes:\n   - Show each change with its schema\n   - Include an option for \"All changes\"\n   - Allow any number of selections (1+ works, 2+ is the typical use case)\n\n   **IMPORTANT**: Do NOT auto-select. Always let the user choose.\n\n3. **Batch validation - gather status for all selected changes**\n\n   For each selected change, collect:\n\n   a. **Artifact status** - Run `openspec status --change \"<name>\" --json`\n      - Parse `schemaName` and `artifacts` list\n      - Note which artifacts are `done` vs other states\n\n   b. **Task completion** - Read `openspec/changes/<name>/tasks.md`\n      - Count `- [ ]` (incomplete) vs `- [x]` (complete)\n      - If no tasks file exists, note as \"No tasks\"\n\n   c. **Delta specs** - Check `openspec/changes/<name>/specs/` directory\n      - List which capability specs exist\n      - For each, extract requirement names (lines matching `### Requirement: <name>`)\n\n4. **Detect spec conflicts**\n\n   Build a map of `capability -> [changes that touch it]`:\n\n   ```\n   auth -> [change-a, change-b]  <- CONFLICT (2+ changes)\n   api  -> [change-c]            <- OK (only 1 change)\n   ```\n\n   A conflict exists when 2+ selected changes have delta specs for the same capability.\n\n5. **Resolve conflicts agentically**\n\n   **For each conflict**, investigate the codebase:\n\n   a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify\n\n   b. **Search the codebase** for implementation evidence:\n      - Look for code implementing requirements from each delta spec\n      - Check for related files, functions, or tests\n\n   c. **Determine resolution**:\n      - If only one change is actually implemented -> sync that one's specs\n      - If both implemented -> apply in chronological order (older first, newer overwrites)\n      - If neither implemented -> skip spec sync, warn user\n\n   d. **Record resolution** for each conflict:\n      - Which change's specs to apply\n      - In what order (if both)\n      - Rationale (what was found in codebase)\n\n6. **Show consolidated status table**\n\n   Display a table summarizing all changes:\n\n   ```\n   | Change               | Artifacts | Tasks | Specs   | Conflicts | Status |\n   |---------------------|-----------|-------|---------|-----------|--------|\n   | schema-management   | Done      | 5/5   | 2 delta | None      | Ready  |\n   | project-config      | Done      | 3/3   | 1 delta | None      | Ready  |\n   | add-oauth           | Done      | 4/4   | 1 delta | auth (!)  | Ready* |\n   | add-verify-skill    | 1 left    | 2/5   | None    | None      | Warn   |\n   ```\n\n   For conflicts, show the resolution:\n   ```\n   * Conflict resolution:\n     - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order)\n   ```\n\n   For incomplete changes, show warnings:\n   ```\n   Warnings:\n   - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks\n   ```\n\n7. **Confirm batch operation**\n\n   Use **AskUserQuestion tool** with a single confirmation:\n\n   - \"Archive N changes?\" with options based on status\n   - Options might include:\n     - \"Archive all N changes\"\n     - \"Archive only N ready changes (skip incomplete)\"\n     - \"Cancel\"\n\n   If there are incomplete changes, make clear they'll be archived with warnings.\n\n8. **Execute archive for each confirmed change**\n\n   Process changes in the determined order (respecting conflict resolution):\n\n   a. **Sync specs** if delta specs exist:\n      - Use the openspec-sync-specs approach (agent-driven intelligent merge)\n      - For conflicts, apply in resolved order\n      - Track if sync was done\n\n   b. **Perform the archive**:\n      ```bash\n      mkdir -p openspec/changes/archive\n      mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n      ```\n\n   c. **Track outcome** for each change:\n      - Success: archived successfully\n      - Failed: error during archive (record error)\n      - Skipped: user chose not to archive (if applicable)\n\n9. **Display summary**\n\n   Show final results:\n\n   ```\n   ## Bulk Archive Complete\n\n   Archived 3 changes:\n   - schema-management-cli -> archive/2026-01-19-schema-management-cli/\n   - project-config -> archive/2026-01-19-project-config/\n   - add-oauth -> archive/2026-01-19-add-oauth/\n\n   Skipped 1 change:\n   - add-verify-skill (user chose not to archive incomplete)\n\n   Spec sync summary:\n   - 4 delta specs synced to main specs\n   - 1 conflict resolved (auth: applied both in chronological order)\n   ```\n\n   If any failures:\n   ```\n   Failed 1 change:\n   - some-change: Archive directory already exists\n   ```\n\n**Conflict Resolution Examples**\n\nExample 1: Only one implemented\n```\nConflict: specs/auth/spec.md touched by [add-oauth, add-jwt]\n\nChecking add-oauth:\n- Delta adds \"OAuth Provider Integration\" requirement\n- Searching codebase... found src/auth/oauth.ts implementing OAuth flow\n\nChecking add-jwt:\n- Delta adds \"JWT Token Handling\" requirement\n- Searching codebase... no JWT implementation found\n\nResolution: Only add-oauth is implemented. Will sync add-oauth specs only.\n```\n\nExample 2: Both implemented\n```\nConflict: specs/api/spec.md touched by [add-rest-api, add-graphql]\n\nChecking add-rest-api (created 2026-01-10):\n- Delta adds \"REST Endpoints\" requirement\n- Searching codebase... found src/api/rest.ts\n\nChecking add-graphql (created 2026-01-15):\n- Delta adds \"GraphQL Schema\" requirement\n- Searching codebase... found src/api/graphql.ts\n\nResolution: Both implemented. Will apply add-rest-api specs first,\nthen add-graphql specs (chronological order, newer takes precedence).\n```\n\n**Output On Success**\n\n```\n## Bulk Archive Complete\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n- <change-2> -> archive/YYYY-MM-DD-<change-2>/\n\nSpec sync summary:\n- N delta specs synced to main specs\n- No conflicts (or: M conflicts resolved)\n```\n\n**Output On Partial Success**\n\n```\n## Bulk Archive Complete (partial)\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n\nSkipped M changes:\n- <change-2> (user chose not to archive incomplete)\n\nFailed K changes:\n- <change-3>: Archive directory already exists\n```\n\n**Output When No Changes**\n\n```\n## No Changes to Archive\n\nNo active changes found. Use `/opsx:new` to create a new change.\n```\n\n**Guardrails**\n- Allow any number of changes (1+ is fine, 2+ is the typical use case)\n- Always prompt for selection, never auto-select\n- Detect spec conflicts early and resolve by checking codebase\n- When both changes are implemented, apply specs in chronological order\n- Skip spec sync only when implementation is missing (warn user)\n- Show clear per-change status before confirming\n- Use single confirmation for entire batch\n- Track and report all outcomes (success/skip/fail)\n- Preserve .openspec.yaml when moving to archive\n- Archive directory target uses current date: YYYY-MM-DD-<name>\n- If archive target exists, fail that change but continue with others\n"
  },
  {
    "path": ".qoder/commands/opsx/continue.md",
    "content": "---\nname: OPSX: Continue\ndescription: Continue working on a change - create the next artifact (Experimental)\ncategory: Workflow\ntags: [workflow, artifacts, experimental]\n---\n\nContinue working on a change by creating the next artifact.\n\n**Input**: Optionally specify a change name after `/opsx:continue` (e.g., `/opsx:continue add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes sorted by most recently modified. Then use the **AskUserQuestion tool** to let the user select which change to work on.\n\n   Present the top 3-4 most recently modified changes as options, showing:\n   - Change name\n   - Schema (from `schema` field if present, otherwise \"spec-driven\")\n   - Status (e.g., \"0/5 tasks\", \"complete\", \"no tasks\")\n   - How recently it was modified (from `lastModified` field)\n\n   Mark the most recently modified change as \"(Recommended)\" since it's likely what the user wants to continue.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check current status**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand current state. The response includes:\n   - `schemaName`: The workflow schema being used (e.g., \"spec-driven\")\n   - `artifacts`: Array of artifacts with their status (\"done\", \"ready\", \"blocked\")\n   - `isComplete`: Boolean indicating if all artifacts are complete\n\n3. **Act based on status**:\n\n   ---\n\n   **If all artifacts are complete (`isComplete: true`)**:\n   - Congratulate the user\n   - Show final status including the schema used\n   - Suggest: \"All artifacts created! You can now implement this change with `/opsx:apply` or archive it with `/opsx:archive`.\"\n   - STOP\n\n   ---\n\n   **If artifacts are ready to create** (status shows artifacts with `status: \"ready\"`):\n   - Pick the FIRST artifact with `status: \"ready\"` from the status output\n   - Get its instructions:\n     ```bash\n     openspec instructions <artifact-id> --change \"<name>\" --json\n     ```\n   - Parse the JSON. The key fields are:\n     - `context`: Project background (constraints for you - do NOT include in output)\n     - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n     - `template`: The structure to use for your output file\n     - `instruction`: Schema-specific guidance\n     - `outputPath`: Where to write the artifact\n     - `dependencies`: Completed artifacts to read for context\n   - **Create the artifact file**:\n     - Read any completed dependency files for context\n     - Use `template` as the structure - fill in its sections\n     - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file\n     - Write to the output path specified in instructions\n   - Show what was created and what's now unlocked\n   - STOP after creating ONE artifact\n\n   ---\n\n   **If no artifacts are ready (all blocked)**:\n   - This shouldn't happen with a valid schema\n   - Show status and suggest checking for issues\n\n4. **After creating an artifact, show progress**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter each invocation, show:\n- Which artifact was created\n- Schema workflow being used\n- Current progress (N/M complete)\n- What artifacts are now unlocked\n- Prompt: \"Run `/opsx:continue` to create the next artifact\"\n\n**Artifact Creation Guidelines**\n\nThe artifact types and their purpose depend on the schema. Use the `instruction` field from the instructions output to understand what to create.\n\nCommon artifact patterns:\n\n**spec-driven schema** (proposal → specs → design → tasks):\n- **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact.\n  - The Capabilities section is critical - each capability listed will need a spec file.\n- **specs/<capability>/spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name).\n- **design.md**: Document technical decisions, architecture, and implementation approach.\n- **tasks.md**: Break down implementation into checkboxed tasks.\n\nFor other schemas, follow the `instruction` field from the CLI output.\n\n**Guardrails**\n- Create ONE artifact per invocation\n- Always read dependency artifacts before creating a new one\n- Never skip artifacts or create out of order\n- If context is unclear, ask the user before creating\n- Verify the artifact file exists after writing before marking progress\n- Use the schema's artifact sequence, don't assume specific artifact names\n- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file\n  - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact\n  - These guide what you write, but should never appear in the output\n"
  },
  {
    "path": ".qoder/commands/opsx/explore.md",
    "content": "---\nname: OPSX: Explore\ndescription: Enter explore mode - think through ideas, investigate problems, clarify requirements\ncategory: Workflow\ntags: [workflow, explore, experimental, thinking]\n---\n\nEnter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.\n\n**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first (e.g., start a change with `/opsx:new` or `/opsx:ff`). You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.\n\n**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.\n\n**Input**: The argument after `/opsx:explore` is whatever the user wants to think about. Could be:\n- A vague idea: \"real-time collaboration\"\n- A specific problem: \"the auth system is getting unwieldy\"\n- A change name: \"add-dark-mode\" (to explore in context of that change)\n- A comparison: \"postgres vs sqlite for this\"\n- Nothing (just enter explore mode)\n\n---\n\n## The Stance\n\n- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script\n- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.\n- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking\n- **Adaptive** - Follow interesting threads, pivot when new information emerges\n- **Patient** - Don't rush to conclusions, let the shape of the problem emerge\n- **Grounded** - Explore the actual codebase when relevant, don't just theorize\n\n---\n\n## What You Might Do\n\nDepending on what the user brings, you might:\n\n**Explore the problem space**\n- Ask clarifying questions that emerge from what they said\n- Challenge assumptions\n- Reframe the problem\n- Find analogies\n\n**Investigate the codebase**\n- Map existing architecture relevant to the discussion\n- Find integration points\n- Identify patterns already in use\n- Surface hidden complexity\n\n**Compare options**\n- Brainstorm multiple approaches\n- Build comparison tables\n- Sketch tradeoffs\n- Recommend a path (if asked)\n\n**Visualize**\n```\n┌─────────────────────────────────────────┐\n│     Use ASCII diagrams liberally        │\n├─────────────────────────────────────────┤\n│                                         │\n│   ┌────────┐         ┌────────┐        │\n│   │ State  │────────▶│ State  │        │\n│   │   A    │         │   B    │        │\n│   └────────┘         └────────┘        │\n│                                         │\n│   System diagrams, state machines,      │\n│   data flows, architecture sketches,    │\n│   dependency graphs, comparison tables  │\n│                                         │\n└─────────────────────────────────────────┘\n```\n\n**Surface risks and unknowns**\n- Identify what could go wrong\n- Find gaps in understanding\n- Suggest spikes or investigations\n\n---\n\n## OpenSpec Awareness\n\nYou have full context of the OpenSpec system. Use it naturally, don't force it.\n\n### Check for context\n\nAt the start, quickly check what exists:\n```bash\nopenspec list --json\n```\n\nThis tells you:\n- If there are active changes\n- Their names, schemas, and status\n- What the user might be working on\n\nIf the user mentioned a specific change name, read its artifacts for context.\n\n### When no change exists\n\nThink freely. When insights crystallize, you might offer:\n\n- \"This feels solid enough to start a change. Want me to create one?\"\n  → Can transition to `/opsx:new` or `/opsx:ff`\n- Or keep exploring - no pressure to formalize\n\n### When a change exists\n\nIf the user mentions a change or you detect one is relevant:\n\n1. **Read existing artifacts for context**\n   - `openspec/changes/<name>/proposal.md`\n   - `openspec/changes/<name>/design.md`\n   - `openspec/changes/<name>/tasks.md`\n   - etc.\n\n2. **Reference them naturally in conversation**\n   - \"Your design mentions using Redis, but we just realized SQLite fits better...\"\n   - \"The proposal scopes this to premium users, but we're now thinking everyone...\"\n\n3. **Offer to capture when decisions are made**\n\n   | Insight Type | Where to Capture |\n   |--------------|------------------|\n   | New requirement discovered | `specs/<capability>/spec.md` |\n   | Requirement changed | `specs/<capability>/spec.md` |\n   | Design decision made | `design.md` |\n   | Scope changed | `proposal.md` |\n   | New work identified | `tasks.md` |\n   | Assumption invalidated | Relevant artifact |\n\n   Example offers:\n   - \"That's a design decision. Capture it in design.md?\"\n   - \"This is a new requirement. Add it to specs?\"\n   - \"This changes scope. Update the proposal?\"\n\n4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.\n\n---\n\n## What You Don't Have To Do\n\n- Follow a script\n- Ask the same questions every time\n- Produce a specific artifact\n- Reach a conclusion\n- Stay on topic if a tangent is valuable\n- Be brief (this is thinking time)\n\n---\n\n## Ending Discovery\n\nThere's no required ending. Discovery might:\n\n- **Flow into action**: \"Ready to start? `/opsx:new` or `/opsx:ff`\"\n- **Result in artifact updates**: \"Updated design.md with these decisions\"\n- **Just provide clarity**: User has what they need, moves on\n- **Continue later**: \"We can pick this up anytime\"\n\nWhen things crystallize, you might offer a summary - but it's optional. Sometimes the thinking IS the value.\n\n---\n\n## Guardrails\n\n- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.\n- **Don't fake understanding** - If something is unclear, dig deeper\n- **Don't rush** - Discovery is thinking time, not task time\n- **Don't force structure** - Let patterns emerge naturally\n- **Don't auto-capture** - Offer to save insights, don't just do it\n- **Do visualize** - A good diagram is worth many paragraphs\n- **Do explore the codebase** - Ground discussions in reality\n- **Do question assumptions** - Including the user's and your own\n"
  },
  {
    "path": ".qoder/commands/opsx/ff.md",
    "content": "---\nname: OPSX: Fast Forward\ndescription: Create a change and generate all artifacts needed for implementation in one go\ncategory: Workflow\ntags: [workflow, artifacts, experimental]\n---\n\nFast-forward through artifact creation - generate everything needed to start implementation.\n\n**Input**: The argument after `/opsx:ff` is the change name (kebab-case), OR a description of what the user wants to build.\n\n**Steps**\n\n1. **If no input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   This creates a scaffolded change at `openspec/changes/<name>/`.\n\n3. **Get the artifact build order**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to get:\n   - `applyRequires`: array of artifact IDs needed before implementation (e.g., `[\"tasks\"]`)\n   - `artifacts`: list of all artifacts with their status and dependencies\n\n4. **Create artifacts in sequence until apply-ready**\n\n   Use the **TodoWrite tool** to track progress through the artifacts.\n\n   Loop through artifacts in dependency order (artifacts with no pending dependencies first):\n\n   a. **For each artifact that is `ready` (dependencies satisfied)**:\n      - Get instructions:\n        ```bash\n        openspec instructions <artifact-id> --change \"<name>\" --json\n        ```\n      - The instructions JSON includes:\n        - `context`: Project background (constraints for you - do NOT include in output)\n        - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n        - `template`: The structure to use for your output file\n        - `instruction`: Schema-specific guidance for this artifact type\n        - `outputPath`: Where to write the artifact\n        - `dependencies`: Completed artifacts to read for context\n      - Read any completed dependency files for context\n      - Create the artifact file using `template` as the structure\n      - Apply `context` and `rules` as constraints - but do NOT copy them into the file\n      - Show brief progress: \"✓ Created <artifact-id>\"\n\n   b. **Continue until all `applyRequires` artifacts are complete**\n      - After creating each artifact, re-run `openspec status --change \"<name>\" --json`\n      - Check if every artifact ID in `applyRequires` has `status: \"done\"` in the artifacts array\n      - Stop when all `applyRequires` artifacts are done\n\n   c. **If an artifact requires user input** (unclear context):\n      - Use **AskUserQuestion tool** to clarify\n      - Then continue with creation\n\n5. **Show final status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter completing all artifacts, summarize:\n- Change name and location\n- List of artifacts created with brief descriptions\n- What's ready: \"All artifacts created! Ready for implementation.\"\n- Prompt: \"Run `/opsx:apply` to start implementing.\"\n\n**Artifact Creation Guidelines**\n\n- Follow the `instruction` field from `openspec instructions` for each artifact type\n- The schema defines what each artifact should contain - follow it\n- Read dependency artifacts for context before creating new ones\n- Use the `template` as a starting point, filling in based on context\n\n**Guardrails**\n- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)\n- Always read dependency artifacts before creating a new one\n- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum\n- If a change with that name already exists, ask if user wants to continue it or create a new one\n- Verify each artifact file exists after writing before proceeding to next\n"
  },
  {
    "path": ".qoder/commands/opsx/new.md",
    "content": "---\nname: OPSX: New\ndescription: Start a new change using the experimental artifact workflow (OPSX)\ncategory: Workflow\ntags: [workflow, artifacts, experimental]\n---\n\nStart a new change using the experimental artifact-driven approach.\n\n**Input**: The argument after `/opsx:new` is the change name (kebab-case), OR a description of what the user wants to build.\n\n**Steps**\n\n1. **If no input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Determine the workflow schema**\n\n   Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow.\n\n   **Use a different schema only if the user mentions:**\n   - A specific schema name → use `--schema <name>`\n   - \"show workflows\" or \"what workflows\" → run `openspec schemas --json` and let them choose\n\n   **Otherwise**: Omit `--schema` to use the default.\n\n3. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   Add `--schema <name>` only if the user requested a specific workflow.\n   This creates a scaffolded change at `openspec/changes/<name>/` with the selected schema.\n\n4. **Show the artifact status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n   This shows which artifacts need to be created and which are ready (dependencies satisfied).\n\n5. **Get instructions for the first artifact**\n   The first artifact depends on the schema. Check the status output to find the first artifact with status \"ready\".\n   ```bash\n   openspec instructions <first-artifact-id> --change \"<name>\"\n   ```\n   This outputs the template and context for creating the first artifact.\n\n6. **STOP and wait for user direction**\n\n**Output**\n\nAfter completing the steps, summarize:\n- Change name and location\n- Schema/workflow being used and its artifact sequence\n- Current status (0/N artifacts complete)\n- The template for the first artifact\n- Prompt: \"Ready to create the first artifact? Run `/opsx:continue` or just describe what this change is about and I'll draft it.\"\n\n**Guardrails**\n- Do NOT create any artifacts yet - just show the instructions\n- Do NOT advance beyond showing the first artifact template\n- If the name is invalid (not kebab-case), ask for a valid name\n- If a change with that name already exists, suggest using `/opsx:continue` instead\n- Pass --schema if using a non-default workflow\n"
  },
  {
    "path": ".qoder/commands/opsx/onboard.md",
    "content": "---\nname: OPSX: Onboard\ndescription: Guided onboarding - walk through a complete OpenSpec workflow cycle with narration\ncategory: Workflow\ntags: [workflow, onboarding, tutorial, learning]\n---\n\nGuide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step.\n\n---\n\n## Preflight\n\nBefore starting, check if OpenSpec is initialized:\n\n```bash\nopenspec status --json 2>&1 || echo \"NOT_INITIALIZED\"\n```\n\n**If not initialized:**\n> OpenSpec isn't set up in this project yet. Run `openspec init` first, then come back to `/opsx:onboard`.\n\nStop here if not initialized.\n\n---\n\n## Phase 1: Welcome\n\nDisplay:\n\n```\n## Welcome to OpenSpec!\n\nI'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it.\n\n**What we'll do:**\n1. Pick a small, real task in your codebase\n2. Explore the problem briefly\n3. Create a change (the container for our work)\n4. Build the artifacts: proposal → specs → design → tasks\n5. Implement the tasks\n6. Archive the completed change\n\n**Time:** ~15-20 minutes\n\nLet's start by finding something to work on.\n```\n\n---\n\n## Phase 2: Task Selection\n\n### Codebase Analysis\n\nScan the codebase for small improvement opportunities. Look for:\n\n1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files\n2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch\n3. **Functions without tests** - Cross-reference `src/` with test directories\n4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`)\n5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code\n6. **Missing validation** - User input handlers without validation\n\nAlso check recent git activity:\n```bash\ngit log --oneline -10 2>/dev/null || echo \"No git history\"\n```\n\n### Present Suggestions\n\nFrom your analysis, present 3-4 specific suggestions:\n\n```\n## Task Suggestions\n\nBased on scanning your codebase, here are some good starter tasks:\n\n**1. [Most promising task]**\n   Location: `src/path/to/file.ts:42`\n   Scope: ~1-2 files, ~20-30 lines\n   Why it's good: [brief reason]\n\n**2. [Second task]**\n   Location: `src/another/file.ts`\n   Scope: ~1 file, ~15 lines\n   Why it's good: [brief reason]\n\n**3. [Third task]**\n   Location: [location]\n   Scope: [estimate]\n   Why it's good: [brief reason]\n\n**4. Something else?**\n   Tell me what you'd like to work on.\n\nWhich task interests you? (Pick a number or describe your own)\n```\n\n**If nothing found:** Fall back to asking what the user wants to build:\n> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix?\n\n### Scope Guardrail\n\nIf the user picks or describes something too large (major feature, multi-day work):\n\n```\nThat's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through.\n\nFor learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details.\n\n**Options:**\n1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]?\n2. **Pick something else** - One of the other suggestions, or a different small task?\n3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer.\n\nWhat would you prefer?\n```\n\nLet the user override if they insist—this is a soft guardrail.\n\n---\n\n## Phase 3: Explore Demo\n\nOnce a task is selected, briefly demonstrate explore mode:\n\n```\nBefore we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction.\n```\n\nSpend 1-2 minutes investigating the relevant code:\n- Read the file(s) involved\n- Draw a quick ASCII diagram if it helps\n- Note any considerations\n\n```\n## Quick Exploration\n\n[Your brief analysis—what you found, any considerations]\n\n┌─────────────────────────────────────────┐\n│   [Optional: ASCII diagram if helpful]  │\n└─────────────────────────────────────────┘\n\nExplore mode (`/opsx:explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem.\n\nNow let's create a change to hold our work.\n```\n\n**PAUSE** - Wait for user acknowledgment before proceeding.\n\n---\n\n## Phase 4: Create the Change\n\n**EXPLAIN:**\n```\n## Creating a Change\n\nA \"change\" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives in `openspec/changes/<name>/` and holds your artifacts—proposal, specs, design, tasks.\n\nLet me create one for our task.\n```\n\n**DO:** Create the change with a derived kebab-case name:\n```bash\nopenspec new change \"<derived-name>\"\n```\n\n**SHOW:**\n```\nCreated: `openspec/changes/<name>/`\n\nThe folder structure:\n```\nopenspec/changes/<name>/\n├── proposal.md    ← Why we're doing this (empty, we'll fill it)\n├── design.md      ← How we'll build it (empty)\n├── specs/         ← Detailed requirements (empty)\n└── tasks.md       ← Implementation checklist (empty)\n```\n\nNow let's fill in the first artifact—the proposal.\n```\n\n---\n\n## Phase 5: Proposal\n\n**EXPLAIN:**\n```\n## The Proposal\n\nThe proposal captures **why** we're making this change and **what** it involves at a high level. It's the \"elevator pitch\" for the work.\n\nI'll draft one based on our task.\n```\n\n**DO:** Draft the proposal content (don't save yet):\n\n```\nHere's a draft proposal:\n\n---\n\n## Why\n\n[1-2 sentences explaining the problem/opportunity]\n\n## What Changes\n\n[Bullet points of what will be different]\n\n## Capabilities\n\n### New Capabilities\n- `<capability-name>`: [brief description]\n\n### Modified Capabilities\n<!-- If modifying existing behavior -->\n\n## Impact\n\n- `src/path/to/file.ts`: [what changes]\n- [other files if applicable]\n\n---\n\nDoes this capture the intent? I can adjust before we save it.\n```\n\n**PAUSE** - Wait for user approval/feedback.\n\nAfter approval, save the proposal:\n```bash\nopenspec instructions proposal --change \"<name>\" --json\n```\nThen write the content to `openspec/changes/<name>/proposal.md`.\n\n```\nProposal saved. This is your \"why\" document—you can always come back and refine it as understanding evolves.\n\nNext up: specs.\n```\n\n---\n\n## Phase 6: Specs\n\n**EXPLAIN:**\n```\n## Specs\n\nSpecs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear.\n\nFor a small task like this, we might only need one spec file.\n```\n\n**DO:** Create the spec file:\n```bash\nmkdir -p openspec/changes/<name>/specs/<capability-name>\n```\n\nDraft the spec content:\n\n```\nHere's the spec:\n\n---\n\n## ADDED Requirements\n\n### Requirement: <Name>\n\n<Description of what the system should do>\n\n#### Scenario: <Scenario name>\n\n- **WHEN** <trigger condition>\n- **THEN** <expected outcome>\n- **AND** <additional outcome if needed>\n\n---\n\nThis format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases.\n```\n\nSave to `openspec/changes/<name>/specs/<capability>/spec.md`.\n\n---\n\n## Phase 7: Design\n\n**EXPLAIN:**\n```\n## Design\n\nThe design captures **how** we'll build it—technical decisions, tradeoffs, approach.\n\nFor small changes, this might be brief. That's fine—not every change needs deep design discussion.\n```\n\n**DO:** Draft design.md:\n\n```\nHere's the design:\n\n---\n\n## Context\n\n[Brief context about the current state]\n\n## Goals / Non-Goals\n\n**Goals:**\n- [What we're trying to achieve]\n\n**Non-Goals:**\n- [What's explicitly out of scope]\n\n## Decisions\n\n### Decision 1: [Key decision]\n\n[Explanation of approach and rationale]\n\n---\n\nFor a small task, this captures the key decisions without over-engineering.\n```\n\nSave to `openspec/changes/<name>/design.md`.\n\n---\n\n## Phase 8: Tasks\n\n**EXPLAIN:**\n```\n## Tasks\n\nFinally, we break the work into implementation tasks—checkboxes that drive the apply phase.\n\nThese should be small, clear, and in logical order.\n```\n\n**DO:** Generate tasks based on specs and design:\n\n```\nHere are the implementation tasks:\n\n---\n\n## 1. [Category or file]\n\n- [ ] 1.1 [Specific task]\n- [ ] 1.2 [Specific task]\n\n## 2. Verify\n\n- [ ] 2.1 [Verification step]\n\n---\n\nEach checkbox becomes a unit of work in the apply phase. Ready to implement?\n```\n\n**PAUSE** - Wait for user to confirm they're ready to implement.\n\nSave to `openspec/changes/<name>/tasks.md`.\n\n---\n\n## Phase 9: Apply (Implementation)\n\n**EXPLAIN:**\n```\n## Implementation\n\nNow we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach.\n```\n\n**DO:** For each task:\n\n1. Announce: \"Working on task N: [description]\"\n2. Implement the change in the codebase\n3. Reference specs/design naturally: \"The spec says X, so I'm doing Y\"\n4. Mark complete in tasks.md: `- [ ]` → `- [x]`\n5. Brief status: \"✓ Task N complete\"\n\nKeep narration light—don't over-explain every line of code.\n\nAfter all tasks:\n\n```\n## Implementation Complete\n\nAll tasks done:\n- [x] Task 1\n- [x] Task 2\n- [x] ...\n\nThe change is implemented! One more step—let's archive it.\n```\n\n---\n\n## Phase 10: Archive\n\n**EXPLAIN:**\n```\n## Archiving\n\nWhen a change is complete, we archive it. This moves it from `openspec/changes/` to `openspec/changes/archive/YYYY-MM-DD-<name>/`.\n\nArchived changes become your project's decision history—you can always find them later to understand why something was built a certain way.\n```\n\n**DO:**\n```bash\nopenspec archive \"<name>\"\n```\n\n**SHOW:**\n```\nArchived to: `openspec/changes/archive/YYYY-MM-DD-<name>/`\n\nThe change is now part of your project's history. The code is in your codebase, the decision record is preserved.\n```\n\n---\n\n## Phase 11: Recap & Next Steps\n\n```\n## Congratulations!\n\nYou just completed a full OpenSpec cycle:\n\n1. **Explore** - Thought through the problem\n2. **New** - Created a change container\n3. **Proposal** - Captured WHY\n4. **Specs** - Defined WHAT in detail\n5. **Design** - Decided HOW\n6. **Tasks** - Broke it into steps\n7. **Apply** - Implemented the work\n8. **Archive** - Preserved the record\n\nThis same rhythm works for any size change—a small fix or a major feature.\n\n---\n\n## Command Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems before/during work |\n| `/opsx:new` | Start a new change, step through artifacts |\n| `/opsx:ff` | Fast-forward: create all artifacts at once |\n| `/opsx:continue` | Continue working on an existing change |\n| `/opsx:apply` | Implement tasks from a change |\n| `/opsx:verify` | Verify implementation matches artifacts |\n| `/opsx:archive` | Archive a completed change |\n\n---\n\n## What's Next?\n\nTry `/opsx:new` or `/opsx:ff` on something you actually want to build. You've got the rhythm now!\n```\n\n---\n\n## Graceful Exit Handling\n\n### User wants to stop mid-way\n\nIf the user says they need to stop, want to pause, or seem disengaged:\n\n```\nNo problem! Your change is saved at `openspec/changes/<name>/`.\n\nTo pick up where we left off later:\n- `/opsx:continue <name>` - Resume artifact creation\n- `/opsx:apply <name>` - Jump to implementation (if tasks exist)\n\nThe work won't be lost. Come back whenever you're ready.\n```\n\nExit gracefully without pressure.\n\n### User just wants command reference\n\nIf the user says they just want to see the commands or skip the tutorial:\n\n```\n## OpenSpec Quick Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems (no code changes) |\n| `/opsx:new <name>` | Start a new change, step by step |\n| `/opsx:ff <name>` | Fast-forward: all artifacts at once |\n| `/opsx:continue <name>` | Continue an existing change |\n| `/opsx:apply <name>` | Implement tasks |\n| `/opsx:verify <name>` | Verify implementation |\n| `/opsx:archive <name>` | Archive when done |\n\nTry `/opsx:new` to start your first change, or `/opsx:ff` if you want to move fast.\n```\n\nExit gracefully.\n\n---\n\n## Guardrails\n\n- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive)\n- **Keep narration light** during implementation—teach without lecturing\n- **Don't skip phases** even if the change is small—the goal is teaching the workflow\n- **Pause for acknowledgment** at marked points, but don't over-pause\n- **Handle exits gracefully**—never pressure the user to continue\n- **Use real codebase tasks**—don't simulate or use fake examples\n- **Adjust scope gently**—guide toward smaller tasks but respect user choice\n"
  },
  {
    "path": ".qoder/commands/opsx/sync.md",
    "content": "---\nname: OPSX: Sync\ndescription: Sync delta specs from a change to main specs\ncategory: Workflow\ntags: [workflow, specs, experimental]\n---\n\nSync delta specs from a change to main specs.\n\nThis is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).\n\n**Input**: Optionally specify a change name after `/opsx:sync` (e.g., `/opsx:sync add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have delta specs (under `specs/` directory).\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Find delta specs**\n\n   Look for delta spec files in `openspec/changes/<name>/specs/*/spec.md`.\n\n   Each delta spec file contains sections like:\n   - `## ADDED Requirements` - New requirements to add\n   - `## MODIFIED Requirements` - Changes to existing requirements\n   - `## REMOVED Requirements` - Requirements to remove\n   - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)\n\n   If no delta specs found, inform user and stop.\n\n3. **For each delta spec, apply changes to main specs**\n\n   For each capability with a delta spec at `openspec/changes/<name>/specs/<capability>/spec.md`:\n\n   a. **Read the delta spec** to understand the intended changes\n\n   b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)\n\n   c. **Apply changes intelligently**:\n\n      **ADDED Requirements:**\n      - If requirement doesn't exist in main spec → add it\n      - If requirement already exists → update it to match (treat as implicit MODIFIED)\n\n      **MODIFIED Requirements:**\n      - Find the requirement in main spec\n      - Apply the changes - this can be:\n        - Adding new scenarios (don't need to copy existing ones)\n        - Modifying existing scenarios\n        - Changing the requirement description\n      - Preserve scenarios/content not mentioned in the delta\n\n      **REMOVED Requirements:**\n      - Remove the entire requirement block from main spec\n\n      **RENAMED Requirements:**\n      - Find the FROM requirement, rename to TO\n\n   d. **Create new main spec** if capability doesn't exist yet:\n      - Create `openspec/specs/<capability>/spec.md`\n      - Add Purpose section (can be brief, mark as TBD)\n      - Add Requirements section with the ADDED requirements\n\n4. **Show summary**\n\n   After applying all changes, summarize:\n   - Which capabilities were updated\n   - What changes were made (requirements added/modified/removed/renamed)\n\n**Delta Spec Format Reference**\n\n```markdown\n## ADDED Requirements\n\n### Requirement: New Feature\nThe system SHALL do something new.\n\n#### Scenario: Basic case\n- **WHEN** user does X\n- **THEN** system does Y\n\n## MODIFIED Requirements\n\n### Requirement: Existing Feature\n#### Scenario: New scenario to add\n- **WHEN** user does A\n- **THEN** system does B\n\n## REMOVED Requirements\n\n### Requirement: Deprecated Feature\n\n## RENAMED Requirements\n\n- FROM: `### Requirement: Old Name`\n- TO: `### Requirement: New Name`\n```\n\n**Key Principle: Intelligent Merging**\n\nUnlike programmatic merging, you can apply **partial updates**:\n- To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios\n- The delta represents *intent*, not a wholesale replacement\n- Use your judgment to merge changes sensibly\n\n**Output On Success**\n\n```\n## Specs Synced: <change-name>\n\nUpdated main specs:\n\n**<capability-1>**:\n- Added requirement: \"New Feature\"\n- Modified requirement: \"Existing Feature\" (added 1 scenario)\n\n**<capability-2>**:\n- Created new spec file\n- Added requirement: \"Another Feature\"\n\nMain specs are now updated. The change remains active - archive when implementation is complete.\n```\n\n**Guardrails**\n- Read both delta and main specs before making changes\n- Preserve existing content not mentioned in delta\n- If something is unclear, ask for clarification\n- Show what you're changing as you go\n- The operation should be idempotent - running twice should give same result\n"
  },
  {
    "path": ".qoder/commands/opsx/verify.md",
    "content": "---\nname: OPSX: Verify\ndescription: Verify implementation matches change artifacts before archiving\ncategory: Workflow\ntags: [workflow, verify, experimental]\n---\n\nVerify that an implementation matches the change artifacts (specs, tasks, design).\n\n**Input**: Optionally specify a change name after `/opsx:verify` (e.g., `/opsx:verify add-auth`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have implementation tasks (tasks artifact exists).\n   Include the schema used for each change if available.\n   Mark changes with incomplete tasks as \"(In Progress)\".\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifacts exist for this change\n\n3. **Get the change directory and load artifacts**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns the change directory and context files. Read all available artifacts from `contextFiles`.\n\n4. **Initialize verification report structure**\n\n   Create a report structure with three dimensions:\n   - **Completeness**: Track tasks and spec coverage\n   - **Correctness**: Track requirement implementation and scenario coverage\n   - **Coherence**: Track design adherence and pattern consistency\n\n   Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.\n\n5. **Verify Completeness**\n\n   **Task Completion**:\n   - If tasks.md exists in contextFiles, read it\n   - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete)\n   - Count complete vs total tasks\n   - If incomplete tasks exist:\n     - Add CRITICAL issue for each incomplete task\n     - Recommendation: \"Complete task: <description>\" or \"Mark as done if already implemented\"\n\n   **Spec Coverage**:\n   - If delta specs exist in `openspec/changes/<name>/specs/`:\n     - Extract all requirements (marked with \"### Requirement:\")\n     - For each requirement:\n       - Search codebase for keywords related to the requirement\n       - Assess if implementation likely exists\n     - If requirements appear unimplemented:\n       - Add CRITICAL issue: \"Requirement not found: <requirement name>\"\n       - Recommendation: \"Implement requirement X: <description>\"\n\n6. **Verify Correctness**\n\n   **Requirement Implementation Mapping**:\n   - For each requirement from delta specs:\n     - Search codebase for implementation evidence\n     - If found, note file paths and line ranges\n     - Assess if implementation matches requirement intent\n     - If divergence detected:\n       - Add WARNING: \"Implementation may diverge from spec: <details>\"\n       - Recommendation: \"Review <file>:<lines> against requirement X\"\n\n   **Scenario Coverage**:\n   - For each scenario in delta specs (marked with \"#### Scenario:\"):\n     - Check if conditions are handled in code\n     - Check if tests exist covering the scenario\n     - If scenario appears uncovered:\n       - Add WARNING: \"Scenario not covered: <scenario name>\"\n       - Recommendation: \"Add test or implementation for scenario: <description>\"\n\n7. **Verify Coherence**\n\n   **Design Adherence**:\n   - If design.md exists in contextFiles:\n     - Extract key decisions (look for sections like \"Decision:\", \"Approach:\", \"Architecture:\")\n     - Verify implementation follows those decisions\n     - If contradiction detected:\n       - Add WARNING: \"Design decision not followed: <decision>\"\n       - Recommendation: \"Update implementation or revise design.md to match reality\"\n   - If no design.md: Skip design adherence check, note \"No design.md to verify against\"\n\n   **Code Pattern Consistency**:\n   - Review new code for consistency with project patterns\n   - Check file naming, directory structure, coding style\n   - If significant deviations found:\n     - Add SUGGESTION: \"Code pattern deviation: <details>\"\n     - Recommendation: \"Consider following project pattern: <example>\"\n\n8. **Generate Verification Report**\n\n   **Summary Scorecard**:\n   ```\n   ## Verification Report: <change-name>\n\n   ### Summary\n   | Dimension    | Status           |\n   |--------------|------------------|\n   | Completeness | X/Y tasks, N reqs|\n   | Correctness  | M/N reqs covered |\n   | Coherence    | Followed/Issues  |\n   ```\n\n   **Issues by Priority**:\n\n   1. **CRITICAL** (Must fix before archive):\n      - Incomplete tasks\n      - Missing requirement implementations\n      - Each with specific, actionable recommendation\n\n   2. **WARNING** (Should fix):\n      - Spec/design divergences\n      - Missing scenario coverage\n      - Each with specific recommendation\n\n   3. **SUGGESTION** (Nice to fix):\n      - Pattern inconsistencies\n      - Minor improvements\n      - Each with specific recommendation\n\n   **Final Assessment**:\n   - If CRITICAL issues: \"X critical issue(s) found. Fix before archiving.\"\n   - If only warnings: \"No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements).\"\n   - If all clear: \"All checks passed. Ready for archive.\"\n\n**Verification Heuristics**\n\n- **Completeness**: Focus on objective checklist items (checkboxes, requirements list)\n- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty\n- **Coherence**: Look for glaring inconsistencies, don't nitpick style\n- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL\n- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable\n\n**Graceful Degradation**\n\n- If only tasks.md exists: verify task completion only, skip spec/design checks\n- If tasks + specs exist: verify completeness and correctness, skip design\n- If full artifacts: verify all three dimensions\n- Always note which checks were skipped and why\n\n**Output Format**\n\nUse clear markdown with:\n- Table for summary scorecard\n- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION)\n- Code references in format: `file.ts:123`\n- Specific, actionable recommendations\n- No vague suggestions like \"consider reviewing\"\n"
  },
  {
    "path": ".qoder/skills/openspec-apply-change/SKILL.md",
    "content": "---\nname: openspec-apply-change\ndescription: Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nImplement tasks from an OpenSpec change.\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **Select the change**\n\n   If a name is provided, use it. Otherwise:\n   - Infer from conversation context if the user mentioned a change\n   - Auto-select if only one active change exists\n   - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select\n\n   Always announce: \"Using change: <name>\" and how to override (e.g., `/opsx:apply <other>`).\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifact contains the tasks (typically \"tasks\" for spec-driven, check status for others)\n\n3. **Get apply instructions**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns:\n   - Context file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs)\n   - Progress (total, complete, remaining)\n   - Task list with status\n   - Dynamic instruction based on current state\n\n   **Handle states:**\n   - If `state: \"blocked\"` (missing artifacts): show message, suggest using openspec-continue-change\n   - If `state: \"all_done\"`: congratulate, suggest archive\n   - Otherwise: proceed to implementation\n\n4. **Read context files**\n\n   Read the files listed in `contextFiles` from the apply instructions output.\n   The files depend on the schema being used:\n   - **spec-driven**: proposal, specs, design, tasks\n   - Other schemas: follow the contextFiles from CLI output\n\n5. **Show current progress**\n\n   Display:\n   - Schema being used\n   - Progress: \"N/M tasks complete\"\n   - Remaining tasks overview\n   - Dynamic instruction from CLI\n\n6. **Implement tasks (loop until done or blocked)**\n\n   For each pending task:\n   - Show which task is being worked on\n   - Make the code changes required\n   - Keep changes minimal and focused\n   - Mark task complete in the tasks file: `- [ ]` → `- [x]`\n   - Continue to next task\n\n   **Pause if:**\n   - Task is unclear → ask for clarification\n   - Implementation reveals a design issue → suggest updating artifacts\n   - Error or blocker encountered → report and wait for guidance\n   - User interrupts\n\n7. **On completion or pause, show status**\n\n   Display:\n   - Tasks completed this session\n   - Overall progress: \"N/M tasks complete\"\n   - If all done: suggest archive\n   - If paused: explain why and wait for guidance\n\n**Output During Implementation**\n\n```\n## Implementing: <change-name> (schema: <schema-name>)\n\nWorking on task 3/7: <task description>\n[...implementation happening...]\n✓ Task complete\n\nWorking on task 4/7: <task description>\n[...implementation happening...]\n✓ Task complete\n```\n\n**Output On Completion**\n\n```\n## Implementation Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 7/7 tasks complete ✓\n\n### Completed This Session\n- [x] Task 1\n- [x] Task 2\n...\n\nAll tasks complete! Ready to archive this change.\n```\n\n**Output On Pause (Issue Encountered)**\n\n```\n## Implementation Paused\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Progress:** 4/7 tasks complete\n\n### Issue Encountered\n<description of the issue>\n\n**Options:**\n1. <option 1>\n2. <option 2>\n3. Other approach\n\nWhat would you like to do?\n```\n\n**Guardrails**\n- Keep going through tasks until done or blocked\n- Always read context files before starting (from the apply instructions output)\n- If task is ambiguous, pause and ask before implementing\n- If implementation reveals issues, pause and suggest artifact updates\n- Keep code changes minimal and scoped to each task\n- Update task checkbox immediately after completing each task\n- Pause on errors, blockers, or unclear requirements - don't guess\n- Use contextFiles from CLI output, don't assume specific file names\n\n**Fluid Workflow Integration**\n\nThis skill supports the \"actions on a change\" model:\n\n- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions\n- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly\n"
  },
  {
    "path": ".qoder/skills/openspec-archive-change/SKILL.md",
    "content": "---\nname: openspec-archive-change\ndescription: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nArchive a completed change in the experimental workflow.\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show only active changes (not already archived).\n   Include the schema used for each change if available.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check artifact completion status**\n\n   Run `openspec status --change \"<name>\" --json` to check artifact completion.\n\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used\n   - `artifacts`: List of artifacts with their status (`done` or other)\n\n   **If any artifacts are not `done`:**\n   - Display warning listing incomplete artifacts\n   - Use **AskUserQuestion tool** to confirm user wants to proceed\n   - Proceed if user confirms\n\n3. **Check task completion status**\n\n   Read the tasks file (typically `tasks.md`) to check for incomplete tasks.\n\n   Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).\n\n   **If incomplete tasks found:**\n   - Display warning showing count of incomplete tasks\n   - Use **AskUserQuestion tool** to confirm user wants to proceed\n   - Proceed if user confirms\n\n   **If no tasks file exists:** Proceed without task-related warning.\n\n4. **Assess delta spec sync state**\n\n   Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.\n\n   **If delta specs exist:**\n   - Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`\n   - Determine what changes would be applied (adds, modifications, removals, renames)\n   - Show a combined summary before prompting\n\n   **Prompt options:**\n   - If changes needed: \"Sync now (recommended)\", \"Archive without syncing\"\n   - If already synced: \"Archive now\", \"Sync anyway\", \"Cancel\"\n\n   If user chooses sync, execute /opsx:sync logic (use the openspec-sync-specs skill). Proceed to archive regardless of choice.\n\n5. **Perform the archive**\n\n   Create the archive directory if it doesn't exist:\n   ```bash\n   mkdir -p openspec/changes/archive\n   ```\n\n   Generate target name using current date: `YYYY-MM-DD-<change-name>`\n\n   **Check if target already exists:**\n   - If yes: Fail with error, suggest renaming existing archive or using different date\n   - If no: Move the change directory to archive\n\n   ```bash\n   mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n   ```\n\n6. **Display summary**\n\n   Show archive completion summary including:\n   - Change name\n   - Schema that was used\n   - Archive location\n   - Whether specs were synced (if applicable)\n   - Note about any warnings (incomplete artifacts/tasks)\n\n**Output On Success**\n\n```\n## Archive Complete\n\n**Change:** <change-name>\n**Schema:** <schema-name>\n**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/\n**Specs:** ✓ Synced to main specs (or \"No delta specs\" or \"Sync skipped\")\n\nAll artifacts complete. All tasks complete.\n```\n\n**Guardrails**\n- Always prompt for change selection if not provided\n- Use artifact graph (openspec status --json) for completion checking\n- Don't block archive on warnings - just inform and confirm\n- Preserve .openspec.yaml when moving to archive (it moves with the directory)\n- Show clear summary of what happened\n- If sync is requested, use openspec-sync-specs approach (agent-driven)\n- If delta specs exist, always run the sync assessment and show the combined summary before prompting\n"
  },
  {
    "path": ".qoder/skills/openspec-bulk-archive-change/SKILL.md",
    "content": "---\nname: openspec-bulk-archive-change\ndescription: Archive multiple completed changes at once. Use when archiving several parallel changes.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nArchive multiple completed changes in a single operation.\n\nThis skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented.\n\n**Input**: None required (prompts for selection)\n\n**Steps**\n\n1. **Get active changes**\n\n   Run `openspec list --json` to get all active changes.\n\n   If no active changes exist, inform user and stop.\n\n2. **Prompt for change selection**\n\n   Use **AskUserQuestion tool** with multi-select to let user choose changes:\n   - Show each change with its schema\n   - Include an option for \"All changes\"\n   - Allow any number of selections (1+ works, 2+ is the typical use case)\n\n   **IMPORTANT**: Do NOT auto-select. Always let the user choose.\n\n3. **Batch validation - gather status for all selected changes**\n\n   For each selected change, collect:\n\n   a. **Artifact status** - Run `openspec status --change \"<name>\" --json`\n      - Parse `schemaName` and `artifacts` list\n      - Note which artifacts are `done` vs other states\n\n   b. **Task completion** - Read `openspec/changes/<name>/tasks.md`\n      - Count `- [ ]` (incomplete) vs `- [x]` (complete)\n      - If no tasks file exists, note as \"No tasks\"\n\n   c. **Delta specs** - Check `openspec/changes/<name>/specs/` directory\n      - List which capability specs exist\n      - For each, extract requirement names (lines matching `### Requirement: <name>`)\n\n4. **Detect spec conflicts**\n\n   Build a map of `capability -> [changes that touch it]`:\n\n   ```\n   auth -> [change-a, change-b]  <- CONFLICT (2+ changes)\n   api  -> [change-c]            <- OK (only 1 change)\n   ```\n\n   A conflict exists when 2+ selected changes have delta specs for the same capability.\n\n5. **Resolve conflicts agentically**\n\n   **For each conflict**, investigate the codebase:\n\n   a. **Read the delta specs** from each conflicting change to understand what each claims to add/modify\n\n   b. **Search the codebase** for implementation evidence:\n      - Look for code implementing requirements from each delta spec\n      - Check for related files, functions, or tests\n\n   c. **Determine resolution**:\n      - If only one change is actually implemented -> sync that one's specs\n      - If both implemented -> apply in chronological order (older first, newer overwrites)\n      - If neither implemented -> skip spec sync, warn user\n\n   d. **Record resolution** for each conflict:\n      - Which change's specs to apply\n      - In what order (if both)\n      - Rationale (what was found in codebase)\n\n6. **Show consolidated status table**\n\n   Display a table summarizing all changes:\n\n   ```\n   | Change               | Artifacts | Tasks | Specs   | Conflicts | Status |\n   |---------------------|-----------|-------|---------|-----------|--------|\n   | schema-management   | Done      | 5/5   | 2 delta | None      | Ready  |\n   | project-config      | Done      | 3/3   | 1 delta | None      | Ready  |\n   | add-oauth           | Done      | 4/4   | 1 delta | auth (!)  | Ready* |\n   | add-verify-skill    | 1 left    | 2/5   | None    | None      | Warn   |\n   ```\n\n   For conflicts, show the resolution:\n   ```\n   * Conflict resolution:\n     - auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order)\n   ```\n\n   For incomplete changes, show warnings:\n   ```\n   Warnings:\n   - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks\n   ```\n\n7. **Confirm batch operation**\n\n   Use **AskUserQuestion tool** with a single confirmation:\n\n   - \"Archive N changes?\" with options based on status\n   - Options might include:\n     - \"Archive all N changes\"\n     - \"Archive only N ready changes (skip incomplete)\"\n     - \"Cancel\"\n\n   If there are incomplete changes, make clear they'll be archived with warnings.\n\n8. **Execute archive for each confirmed change**\n\n   Process changes in the determined order (respecting conflict resolution):\n\n   a. **Sync specs** if delta specs exist:\n      - Use the openspec-sync-specs approach (agent-driven intelligent merge)\n      - For conflicts, apply in resolved order\n      - Track if sync was done\n\n   b. **Perform the archive**:\n      ```bash\n      mkdir -p openspec/changes/archive\n      mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>\n      ```\n\n   c. **Track outcome** for each change:\n      - Success: archived successfully\n      - Failed: error during archive (record error)\n      - Skipped: user chose not to archive (if applicable)\n\n9. **Display summary**\n\n   Show final results:\n\n   ```\n   ## Bulk Archive Complete\n\n   Archived 3 changes:\n   - schema-management-cli -> archive/2026-01-19-schema-management-cli/\n   - project-config -> archive/2026-01-19-project-config/\n   - add-oauth -> archive/2026-01-19-add-oauth/\n\n   Skipped 1 change:\n   - add-verify-skill (user chose not to archive incomplete)\n\n   Spec sync summary:\n   - 4 delta specs synced to main specs\n   - 1 conflict resolved (auth: applied both in chronological order)\n   ```\n\n   If any failures:\n   ```\n   Failed 1 change:\n   - some-change: Archive directory already exists\n   ```\n\n**Conflict Resolution Examples**\n\nExample 1: Only one implemented\n```\nConflict: specs/auth/spec.md touched by [add-oauth, add-jwt]\n\nChecking add-oauth:\n- Delta adds \"OAuth Provider Integration\" requirement\n- Searching codebase... found src/auth/oauth.ts implementing OAuth flow\n\nChecking add-jwt:\n- Delta adds \"JWT Token Handling\" requirement\n- Searching codebase... no JWT implementation found\n\nResolution: Only add-oauth is implemented. Will sync add-oauth specs only.\n```\n\nExample 2: Both implemented\n```\nConflict: specs/api/spec.md touched by [add-rest-api, add-graphql]\n\nChecking add-rest-api (created 2026-01-10):\n- Delta adds \"REST Endpoints\" requirement\n- Searching codebase... found src/api/rest.ts\n\nChecking add-graphql (created 2026-01-15):\n- Delta adds \"GraphQL Schema\" requirement\n- Searching codebase... found src/api/graphql.ts\n\nResolution: Both implemented. Will apply add-rest-api specs first,\nthen add-graphql specs (chronological order, newer takes precedence).\n```\n\n**Output On Success**\n\n```\n## Bulk Archive Complete\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n- <change-2> -> archive/YYYY-MM-DD-<change-2>/\n\nSpec sync summary:\n- N delta specs synced to main specs\n- No conflicts (or: M conflicts resolved)\n```\n\n**Output On Partial Success**\n\n```\n## Bulk Archive Complete (partial)\n\nArchived N changes:\n- <change-1> -> archive/YYYY-MM-DD-<change-1>/\n\nSkipped M changes:\n- <change-2> (user chose not to archive incomplete)\n\nFailed K changes:\n- <change-3>: Archive directory already exists\n```\n\n**Output When No Changes**\n\n```\n## No Changes to Archive\n\nNo active changes found. Use `/opsx:new` to create a new change.\n```\n\n**Guardrails**\n- Allow any number of changes (1+ is fine, 2+ is the typical use case)\n- Always prompt for selection, never auto-select\n- Detect spec conflicts early and resolve by checking codebase\n- When both changes are implemented, apply specs in chronological order\n- Skip spec sync only when implementation is missing (warn user)\n- Show clear per-change status before confirming\n- Use single confirmation for entire batch\n- Track and report all outcomes (success/skip/fail)\n- Preserve .openspec.yaml when moving to archive\n- Archive directory target uses current date: YYYY-MM-DD-<name>\n- If archive target exists, fail that change but continue with others\n"
  },
  {
    "path": ".qoder/skills/openspec-continue-change/SKILL.md",
    "content": "---\nname: openspec-continue-change\ndescription: Continue working on an OpenSpec change by creating the next artifact. Use when the user wants to progress their change, create the next artifact, or continue their workflow.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nContinue working on a change by creating the next artifact.\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes sorted by most recently modified. Then use the **AskUserQuestion tool** to let the user select which change to work on.\n\n   Present the top 3-4 most recently modified changes as options, showing:\n   - Change name\n   - Schema (from `schema` field if present, otherwise \"spec-driven\")\n   - Status (e.g., \"0/5 tasks\", \"complete\", \"no tasks\")\n   - How recently it was modified (from `lastModified` field)\n\n   Mark the most recently modified change as \"(Recommended)\" since it's likely what the user wants to continue.\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check current status**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand current state. The response includes:\n   - `schemaName`: The workflow schema being used (e.g., \"spec-driven\")\n   - `artifacts`: Array of artifacts with their status (\"done\", \"ready\", \"blocked\")\n   - `isComplete`: Boolean indicating if all artifacts are complete\n\n3. **Act based on status**:\n\n   ---\n\n   **If all artifacts are complete (`isComplete: true`)**:\n   - Congratulate the user\n   - Show final status including the schema used\n   - Suggest: \"All artifacts created! You can now implement this change or archive it.\"\n   - STOP\n\n   ---\n\n   **If artifacts are ready to create** (status shows artifacts with `status: \"ready\"`):\n   - Pick the FIRST artifact with `status: \"ready\"` from the status output\n   - Get its instructions:\n     ```bash\n     openspec instructions <artifact-id> --change \"<name>\" --json\n     ```\n   - Parse the JSON. The key fields are:\n     - `context`: Project background (constraints for you - do NOT include in output)\n     - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n     - `template`: The structure to use for your output file\n     - `instruction`: Schema-specific guidance\n     - `outputPath`: Where to write the artifact\n     - `dependencies`: Completed artifacts to read for context\n   - **Create the artifact file**:\n     - Read any completed dependency files for context\n     - Use `template` as the structure - fill in its sections\n     - Apply `context` and `rules` as constraints when writing - but do NOT copy them into the file\n     - Write to the output path specified in instructions\n   - Show what was created and what's now unlocked\n   - STOP after creating ONE artifact\n\n   ---\n\n   **If no artifacts are ready (all blocked)**:\n   - This shouldn't happen with a valid schema\n   - Show status and suggest checking for issues\n\n4. **After creating an artifact, show progress**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter each invocation, show:\n- Which artifact was created\n- Schema workflow being used\n- Current progress (N/M complete)\n- What artifacts are now unlocked\n- Prompt: \"Want to continue? Just ask me to continue or tell me what to do next.\"\n\n**Artifact Creation Guidelines**\n\nThe artifact types and their purpose depend on the schema. Use the `instruction` field from the instructions output to understand what to create.\n\nCommon artifact patterns:\n\n**spec-driven schema** (proposal → specs → design → tasks):\n- **proposal.md**: Ask user about the change if not clear. Fill in Why, What Changes, Capabilities, Impact.\n  - The Capabilities section is critical - each capability listed will need a spec file.\n- **specs/<capability>/spec.md**: Create one spec per capability listed in the proposal's Capabilities section (use the capability name, not the change name).\n- **design.md**: Document technical decisions, architecture, and implementation approach.\n- **tasks.md**: Break down implementation into checkboxed tasks.\n\nFor other schemas, follow the `instruction` field from the CLI output.\n\n**Guardrails**\n- Create ONE artifact per invocation\n- Always read dependency artifacts before creating a new one\n- Never skip artifacts or create out of order\n- If context is unclear, ask the user before creating\n- Verify the artifact file exists after writing before marking progress\n- Use the schema's artifact sequence, don't assume specific artifact names\n- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file\n  - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact\n  - These guide what you write, but should never appear in the output\n"
  },
  {
    "path": ".qoder/skills/openspec-explore/SKILL.md",
    "content": "---\nname: openspec-explore\ndescription: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nEnter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.\n\n**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first (e.g., start a change with `/opsx:new` or `/opsx:ff`). You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.\n\n**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.\n\n---\n\n## The Stance\n\n- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script\n- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.\n- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking\n- **Adaptive** - Follow interesting threads, pivot when new information emerges\n- **Patient** - Don't rush to conclusions, let the shape of the problem emerge\n- **Grounded** - Explore the actual codebase when relevant, don't just theorize\n\n---\n\n## What You Might Do\n\nDepending on what the user brings, you might:\n\n**Explore the problem space**\n- Ask clarifying questions that emerge from what they said\n- Challenge assumptions\n- Reframe the problem\n- Find analogies\n\n**Investigate the codebase**\n- Map existing architecture relevant to the discussion\n- Find integration points\n- Identify patterns already in use\n- Surface hidden complexity\n\n**Compare options**\n- Brainstorm multiple approaches\n- Build comparison tables\n- Sketch tradeoffs\n- Recommend a path (if asked)\n\n**Visualize**\n```\n┌─────────────────────────────────────────┐\n│     Use ASCII diagrams liberally        │\n├─────────────────────────────────────────┤\n│                                         │\n│   ┌────────┐         ┌────────┐        │\n│   │ State  │────────▶│ State  │        │\n│   │   A    │         │   B    │        │\n│   └────────┘         └────────┘        │\n│                                         │\n│   System diagrams, state machines,      │\n│   data flows, architecture sketches,    │\n│   dependency graphs, comparison tables  │\n│                                         │\n└─────────────────────────────────────────┘\n```\n\n**Surface risks and unknowns**\n- Identify what could go wrong\n- Find gaps in understanding\n- Suggest spikes or investigations\n\n---\n\n## OpenSpec Awareness\n\nYou have full context of the OpenSpec system. Use it naturally, don't force it.\n\n### Check for context\n\nAt the start, quickly check what exists:\n```bash\nopenspec list --json\n```\n\nThis tells you:\n- If there are active changes\n- Their names, schemas, and status\n- What the user might be working on\n\n### When no change exists\n\nThink freely. When insights crystallize, you might offer:\n\n- \"This feels solid enough to start a change. Want me to create one?\"\n  → Can transition to `/opsx:new` or `/opsx:ff`\n- Or keep exploring - no pressure to formalize\n\n### When a change exists\n\nIf the user mentions a change or you detect one is relevant:\n\n1. **Read existing artifacts for context**\n   - `openspec/changes/<name>/proposal.md`\n   - `openspec/changes/<name>/design.md`\n   - `openspec/changes/<name>/tasks.md`\n   - etc.\n\n2. **Reference them naturally in conversation**\n   - \"Your design mentions using Redis, but we just realized SQLite fits better...\"\n   - \"The proposal scopes this to premium users, but we're now thinking everyone...\"\n\n3. **Offer to capture when decisions are made**\n\n   | Insight Type | Where to Capture |\n   |--------------|------------------|\n   | New requirement discovered | `specs/<capability>/spec.md` |\n   | Requirement changed | `specs/<capability>/spec.md` |\n   | Design decision made | `design.md` |\n   | Scope changed | `proposal.md` |\n   | New work identified | `tasks.md` |\n   | Assumption invalidated | Relevant artifact |\n\n   Example offers:\n   - \"That's a design decision. Capture it in design.md?\"\n   - \"This is a new requirement. Add it to specs?\"\n   - \"This changes scope. Update the proposal?\"\n\n4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.\n\n---\n\n## What You Don't Have To Do\n\n- Follow a script\n- Ask the same questions every time\n- Produce a specific artifact\n- Reach a conclusion\n- Stay on topic if a tangent is valuable\n- Be brief (this is thinking time)\n\n---\n\n## Handling Different Entry Points\n\n**User brings a vague idea:**\n```\nUser: I'm thinking about adding real-time collaboration\n\nYou: Real-time collab is a big space. Let me think about this...\n\n      COLLABORATION SPECTRUM\n      ════════════════════════════════════════════\n\n      Awareness          Coordination         Sync\n          │                   │                 │\n          ▼                   ▼                 ▼\n      ┌────────┐         ┌────────┐        ┌────────┐\n      │Presence│         │Cursors │        │  CRDT  │\n      │  \"3    │         │ Multi  │        │Conflict│\n      │online\" │         │ select │        │  free  │\n      └────────┘         └────────┘        └────────┘\n          │                   │                 │\n       trivial            moderate           complex\n\n      Where's your head at?\n```\n\n**User brings a specific problem:**\n```\nUser: The auth system is a mess\n\nYou: [reads codebase]\n\n     ┌─────────────────────────────────────────────┐\n     │              CURRENT AUTH FLOW              │\n     └─────────────────────────────────────────────┘\n                        │\n          ┌─────────────┼─────────────┐\n          ▼             ▼             ▼\n     ┌─────────┐  ┌─────────┐  ┌─────────┐\n     │ Google  │  │  GitHub │  │  Email  │\n     │  OAuth  │  │  OAuth  │  │  Magic  │\n     └────┬────┘  └────┬────┘  └────┬────┘\n          │             │             │\n          └─────────────┼─────────────┘\n                        ▼\n                  ┌───────────┐\n                  │  Session  │\n                  └─────┬─────┘\n                        │\n                        ▼\n                  ┌───────────┐\n                  │   Perms   │\n                  └───────────┘\n\n     I see three tangles. Which one's burning?\n```\n\n**User is stuck mid-implementation:**\n```\nUser: /opsx:explore add-auth-system\n      The OAuth integration is more complex than expected\n\nYou: [reads change artifacts]\n\n     You're on task 4: \"Implement OAuth flow\"\n\n     Let me trace what's involved...\n\n     [draws diagram, explores options, suggests paths]\n\n     Want to update the design to reflect this?\n     Or add a spike task to investigate?\n```\n\n**User wants to compare options:**\n```\nUser: Should we use Postgres or SQLite?\n\nYou: Generic answer is boring. What's the context?\n\nUser: A CLI tool that tracks local dev environments\n\nYou: That changes everything.\n\n     ┌─────────────────────────────────────────────────┐\n     │         CLI TOOL DATA STORAGE                  │\n     └─────────────────────────────────────────────────┘\n\n     Key constraints:\n     • No daemon running\n     • Must work offline\n     • Single user\n\n                  SQLite          Postgres\n     Deployment   embedded ✓      needs server ✗\n     Offline      yes ✓           no ✗\n     Single file  yes ✓           no ✗\n\n     SQLite. Not even close.\n\n     Unless... is there a sync component?\n```\n\n---\n\n## Ending Discovery\n\nThere's no required ending. Discovery might:\n\n- **Flow into action**: \"Ready to start? /opsx:new or /opsx:ff\"\n- **Result in artifact updates**: \"Updated design.md with these decisions\"\n- **Just provide clarity**: User has what they need, moves on\n- **Continue later**: \"We can pick this up anytime\"\n\nWhen it feels like things are crystallizing, you might summarize:\n\n```\n## What We Figured Out\n\n**The problem**: [crystallized understanding]\n\n**The approach**: [if one emerged]\n\n**Open questions**: [if any remain]\n\n**Next steps** (if ready):\n- Create a change: /opsx:new <name>\n- Fast-forward to tasks: /opsx:ff <name>\n- Keep exploring: just keep talking\n```\n\nBut this summary is optional. Sometimes the thinking IS the value.\n\n---\n\n## Guardrails\n\n- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.\n- **Don't fake understanding** - If something is unclear, dig deeper\n- **Don't rush** - Discovery is thinking time, not task time\n- **Don't force structure** - Let patterns emerge naturally\n- **Don't auto-capture** - Offer to save insights, don't just do it\n- **Do visualize** - A good diagram is worth many paragraphs\n- **Do explore the codebase** - Ground discussions in reality\n- **Do question assumptions** - Including the user's and your own\n"
  },
  {
    "path": ".qoder/skills/openspec-ff-change/SKILL.md",
    "content": "---\nname: openspec-ff-change\ndescription: Fast-forward through OpenSpec artifact creation. Use when the user wants to quickly create all artifacts needed for implementation without stepping through each one individually.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nFast-forward through artifact creation - generate everything needed to start implementation in one go.\n\n**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.\n\n**Steps**\n\n1. **If no clear input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   This creates a scaffolded change at `openspec/changes/<name>/`.\n\n3. **Get the artifact build order**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to get:\n   - `applyRequires`: array of artifact IDs needed before implementation (e.g., `[\"tasks\"]`)\n   - `artifacts`: list of all artifacts with their status and dependencies\n\n4. **Create artifacts in sequence until apply-ready**\n\n   Use the **TodoWrite tool** to track progress through the artifacts.\n\n   Loop through artifacts in dependency order (artifacts with no pending dependencies first):\n\n   a. **For each artifact that is `ready` (dependencies satisfied)**:\n      - Get instructions:\n        ```bash\n        openspec instructions <artifact-id> --change \"<name>\" --json\n        ```\n      - The instructions JSON includes:\n        - `context`: Project background (constraints for you - do NOT include in output)\n        - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)\n        - `template`: The structure to use for your output file\n        - `instruction`: Schema-specific guidance for this artifact type\n        - `outputPath`: Where to write the artifact\n        - `dependencies`: Completed artifacts to read for context\n      - Read any completed dependency files for context\n      - Create the artifact file using `template` as the structure\n      - Apply `context` and `rules` as constraints - but do NOT copy them into the file\n      - Show brief progress: \"✓ Created <artifact-id>\"\n\n   b. **Continue until all `applyRequires` artifacts are complete**\n      - After creating each artifact, re-run `openspec status --change \"<name>\" --json`\n      - Check if every artifact ID in `applyRequires` has `status: \"done\"` in the artifacts array\n      - Stop when all `applyRequires` artifacts are done\n\n   c. **If an artifact requires user input** (unclear context):\n      - Use **AskUserQuestion tool** to clarify\n      - Then continue with creation\n\n5. **Show final status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n\n**Output**\n\nAfter completing all artifacts, summarize:\n- Change name and location\n- List of artifacts created with brief descriptions\n- What's ready: \"All artifacts created! Ready for implementation.\"\n- Prompt: \"Run `/opsx:apply` or ask me to implement to start working on the tasks.\"\n\n**Artifact Creation Guidelines**\n\n- Follow the `instruction` field from `openspec instructions` for each artifact type\n- The schema defines what each artifact should contain - follow it\n- Read dependency artifacts for context before creating new ones\n- Use `template` as the structure for your output file - fill in its sections\n- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file\n  - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact\n  - These guide what you write, but should never appear in the output\n\n**Guardrails**\n- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)\n- Always read dependency artifacts before creating a new one\n- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum\n- If a change with that name already exists, suggest continuing that change instead\n- Verify each artifact file exists after writing before proceeding to next\n"
  },
  {
    "path": ".qoder/skills/openspec-new-change/SKILL.md",
    "content": "---\nname: openspec-new-change\ndescription: Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nStart a new change using the experimental artifact-driven approach.\n\n**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.\n\n**Steps**\n\n1. **If no clear input provided, ask what they want to build**\n\n   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:\n   > \"What change do you want to work on? Describe what you want to build or fix.\"\n\n   From their description, derive a kebab-case name (e.g., \"add user authentication\" → `add-user-auth`).\n\n   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.\n\n2. **Determine the workflow schema**\n\n   Use the default schema (omit `--schema`) unless the user explicitly requests a different workflow.\n\n   **Use a different schema only if the user mentions:**\n   - A specific schema name → use `--schema <name>`\n   - \"show workflows\" or \"what workflows\" → run `openspec schemas --json` and let them choose\n\n   **Otherwise**: Omit `--schema` to use the default.\n\n3. **Create the change directory**\n   ```bash\n   openspec new change \"<name>\"\n   ```\n   Add `--schema <name>` only if the user requested a specific workflow.\n   This creates a scaffolded change at `openspec/changes/<name>/` with the selected schema.\n\n4. **Show the artifact status**\n   ```bash\n   openspec status --change \"<name>\"\n   ```\n   This shows which artifacts need to be created and which are ready (dependencies satisfied).\n\n5. **Get instructions for the first artifact**\n   The first artifact depends on the schema (e.g., `proposal` for spec-driven).\n   Check the status output to find the first artifact with status \"ready\".\n   ```bash\n   openspec instructions <first-artifact-id> --change \"<name>\"\n   ```\n   This outputs the template and context for creating the first artifact.\n\n6. **STOP and wait for user direction**\n\n**Output**\n\nAfter completing the steps, summarize:\n- Change name and location\n- Schema/workflow being used and its artifact sequence\n- Current status (0/N artifacts complete)\n- The template for the first artifact\n- Prompt: \"Ready to create the first artifact? Just describe what this change is about and I'll draft it, or ask me to continue.\"\n\n**Guardrails**\n- Do NOT create any artifacts yet - just show the instructions\n- Do NOT advance beyond showing the first artifact template\n- If the name is invalid (not kebab-case), ask for a valid name\n- If a change with that name already exists, suggest continuing that change instead\n- Pass --schema if using a non-default workflow\n"
  },
  {
    "path": ".qoder/skills/openspec-onboard/SKILL.md",
    "content": "---\nname: openspec-onboard\ndescription: Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nGuide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step.\n\n---\n\n## Preflight\n\nBefore starting, check if OpenSpec is initialized:\n\n```bash\nopenspec status --json 2>&1 || echo \"NOT_INITIALIZED\"\n```\n\n**If not initialized:**\n> OpenSpec isn't set up in this project yet. Run `openspec init` first, then come back to `/opsx:onboard`.\n\nStop here if not initialized.\n\n---\n\n## Phase 1: Welcome\n\nDisplay:\n\n```\n## Welcome to OpenSpec!\n\nI'll walk you through a complete change cycle—from idea to implementation—using a real task in your codebase. Along the way, you'll learn the workflow by doing it.\n\n**What we'll do:**\n1. Pick a small, real task in your codebase\n2. Explore the problem briefly\n3. Create a change (the container for our work)\n4. Build the artifacts: proposal → specs → design → tasks\n5. Implement the tasks\n6. Archive the completed change\n\n**Time:** ~15-20 minutes\n\nLet's start by finding something to work on.\n```\n\n---\n\n## Phase 2: Task Selection\n\n### Codebase Analysis\n\nScan the codebase for small improvement opportunities. Look for:\n\n1. **TODO/FIXME comments** - Search for `TODO`, `FIXME`, `HACK`, `XXX` in code files\n2. **Missing error handling** - `catch` blocks that swallow errors, risky operations without try-catch\n3. **Functions without tests** - Cross-reference `src/` with test directories\n4. **Type issues** - `any` types in TypeScript files (`: any`, `as any`)\n5. **Debug artifacts** - `console.log`, `console.debug`, `debugger` statements in non-debug code\n6. **Missing validation** - User input handlers without validation\n\nAlso check recent git activity:\n```bash\ngit log --oneline -10 2>/dev/null || echo \"No git history\"\n```\n\n### Present Suggestions\n\nFrom your analysis, present 3-4 specific suggestions:\n\n```\n## Task Suggestions\n\nBased on scanning your codebase, here are some good starter tasks:\n\n**1. [Most promising task]**\n   Location: `src/path/to/file.ts:42`\n   Scope: ~1-2 files, ~20-30 lines\n   Why it's good: [brief reason]\n\n**2. [Second task]**\n   Location: `src/another/file.ts`\n   Scope: ~1 file, ~15 lines\n   Why it's good: [brief reason]\n\n**3. [Third task]**\n   Location: [location]\n   Scope: [estimate]\n   Why it's good: [brief reason]\n\n**4. Something else?**\n   Tell me what you'd like to work on.\n\nWhich task interests you? (Pick a number or describe your own)\n```\n\n**If nothing found:** Fall back to asking what the user wants to build:\n> I didn't find obvious quick wins in your codebase. What's something small you've been meaning to add or fix?\n\n### Scope Guardrail\n\nIf the user picks or describes something too large (major feature, multi-day work):\n\n```\nThat's a valuable task, but it's probably larger than ideal for your first OpenSpec run-through.\n\nFor learning the workflow, smaller is better—it lets you see the full cycle without getting stuck in implementation details.\n\n**Options:**\n1. **Slice it smaller** - What's the smallest useful piece of [their task]? Maybe just [specific slice]?\n2. **Pick something else** - One of the other suggestions, or a different small task?\n3. **Do it anyway** - If you really want to tackle this, we can. Just know it'll take longer.\n\nWhat would you prefer?\n```\n\nLet the user override if they insist—this is a soft guardrail.\n\n---\n\n## Phase 3: Explore Demo\n\nOnce a task is selected, briefly demonstrate explore mode:\n\n```\nBefore we create a change, let me quickly show you **explore mode**—it's how you think through problems before committing to a direction.\n```\n\nSpend 1-2 minutes investigating the relevant code:\n- Read the file(s) involved\n- Draw a quick ASCII diagram if it helps\n- Note any considerations\n\n```\n## Quick Exploration\n\n[Your brief analysis—what you found, any considerations]\n\n┌─────────────────────────────────────────┐\n│   [Optional: ASCII diagram if helpful]  │\n└─────────────────────────────────────────┘\n\nExplore mode (`/opsx:explore`) is for this kind of thinking—investigating before implementing. You can use it anytime you need to think through a problem.\n\nNow let's create a change to hold our work.\n```\n\n**PAUSE** - Wait for user acknowledgment before proceeding.\n\n---\n\n## Phase 4: Create the Change\n\n**EXPLAIN:**\n```\n## Creating a Change\n\nA \"change\" in OpenSpec is a container for all the thinking and planning around a piece of work. It lives in `openspec/changes/<name>/` and holds your artifacts—proposal, specs, design, tasks.\n\nLet me create one for our task.\n```\n\n**DO:** Create the change with a derived kebab-case name:\n```bash\nopenspec new change \"<derived-name>\"\n```\n\n**SHOW:**\n```\nCreated: `openspec/changes/<name>/`\n\nThe folder structure:\n```\nopenspec/changes/<name>/\n├── proposal.md    ← Why we're doing this (empty, we'll fill it)\n├── design.md      ← How we'll build it (empty)\n├── specs/         ← Detailed requirements (empty)\n└── tasks.md       ← Implementation checklist (empty)\n```\n\nNow let's fill in the first artifact—the proposal.\n```\n\n---\n\n## Phase 5: Proposal\n\n**EXPLAIN:**\n```\n## The Proposal\n\nThe proposal captures **why** we're making this change and **what** it involves at a high level. It's the \"elevator pitch\" for the work.\n\nI'll draft one based on our task.\n```\n\n**DO:** Draft the proposal content (don't save yet):\n\n```\nHere's a draft proposal:\n\n---\n\n## Why\n\n[1-2 sentences explaining the problem/opportunity]\n\n## What Changes\n\n[Bullet points of what will be different]\n\n## Capabilities\n\n### New Capabilities\n- `<capability-name>`: [brief description]\n\n### Modified Capabilities\n<!-- If modifying existing behavior -->\n\n## Impact\n\n- `src/path/to/file.ts`: [what changes]\n- [other files if applicable]\n\n---\n\nDoes this capture the intent? I can adjust before we save it.\n```\n\n**PAUSE** - Wait for user approval/feedback.\n\nAfter approval, save the proposal:\n```bash\nopenspec instructions proposal --change \"<name>\" --json\n```\nThen write the content to `openspec/changes/<name>/proposal.md`.\n\n```\nProposal saved. This is your \"why\" document—you can always come back and refine it as understanding evolves.\n\nNext up: specs.\n```\n\n---\n\n## Phase 6: Specs\n\n**EXPLAIN:**\n```\n## Specs\n\nSpecs define **what** we're building in precise, testable terms. They use a requirement/scenario format that makes expected behavior crystal clear.\n\nFor a small task like this, we might only need one spec file.\n```\n\n**DO:** Create the spec file:\n```bash\nmkdir -p openspec/changes/<name>/specs/<capability-name>\n```\n\nDraft the spec content:\n\n```\nHere's the spec:\n\n---\n\n## ADDED Requirements\n\n### Requirement: <Name>\n\n<Description of what the system should do>\n\n#### Scenario: <Scenario name>\n\n- **WHEN** <trigger condition>\n- **THEN** <expected outcome>\n- **AND** <additional outcome if needed>\n\n---\n\nThis format—WHEN/THEN/AND—makes requirements testable. You can literally read them as test cases.\n```\n\nSave to `openspec/changes/<name>/specs/<capability>/spec.md`.\n\n---\n\n## Phase 7: Design\n\n**EXPLAIN:**\n```\n## Design\n\nThe design captures **how** we'll build it—technical decisions, tradeoffs, approach.\n\nFor small changes, this might be brief. That's fine—not every change needs deep design discussion.\n```\n\n**DO:** Draft design.md:\n\n```\nHere's the design:\n\n---\n\n## Context\n\n[Brief context about the current state]\n\n## Goals / Non-Goals\n\n**Goals:**\n- [What we're trying to achieve]\n\n**Non-Goals:**\n- [What's explicitly out of scope]\n\n## Decisions\n\n### Decision 1: [Key decision]\n\n[Explanation of approach and rationale]\n\n---\n\nFor a small task, this captures the key decisions without over-engineering.\n```\n\nSave to `openspec/changes/<name>/design.md`.\n\n---\n\n## Phase 8: Tasks\n\n**EXPLAIN:**\n```\n## Tasks\n\nFinally, we break the work into implementation tasks—checkboxes that drive the apply phase.\n\nThese should be small, clear, and in logical order.\n```\n\n**DO:** Generate tasks based on specs and design:\n\n```\nHere are the implementation tasks:\n\n---\n\n## 1. [Category or file]\n\n- [ ] 1.1 [Specific task]\n- [ ] 1.2 [Specific task]\n\n## 2. Verify\n\n- [ ] 2.1 [Verification step]\n\n---\n\nEach checkbox becomes a unit of work in the apply phase. Ready to implement?\n```\n\n**PAUSE** - Wait for user to confirm they're ready to implement.\n\nSave to `openspec/changes/<name>/tasks.md`.\n\n---\n\n## Phase 9: Apply (Implementation)\n\n**EXPLAIN:**\n```\n## Implementation\n\nNow we implement each task, checking them off as we go. I'll announce each one and occasionally note how the specs/design informed the approach.\n```\n\n**DO:** For each task:\n\n1. Announce: \"Working on task N: [description]\"\n2. Implement the change in the codebase\n3. Reference specs/design naturally: \"The spec says X, so I'm doing Y\"\n4. Mark complete in tasks.md: `- [ ]` → `- [x]`\n5. Brief status: \"✓ Task N complete\"\n\nKeep narration light—don't over-explain every line of code.\n\nAfter all tasks:\n\n```\n## Implementation Complete\n\nAll tasks done:\n- [x] Task 1\n- [x] Task 2\n- [x] ...\n\nThe change is implemented! One more step—let's archive it.\n```\n\n---\n\n## Phase 10: Archive\n\n**EXPLAIN:**\n```\n## Archiving\n\nWhen a change is complete, we archive it. This moves it from `openspec/changes/` to `openspec/changes/archive/YYYY-MM-DD-<name>/`.\n\nArchived changes become your project's decision history—you can always find them later to understand why something was built a certain way.\n```\n\n**DO:**\n```bash\nopenspec archive \"<name>\"\n```\n\n**SHOW:**\n```\nArchived to: `openspec/changes/archive/YYYY-MM-DD-<name>/`\n\nThe change is now part of your project's history. The code is in your codebase, the decision record is preserved.\n```\n\n---\n\n## Phase 11: Recap & Next Steps\n\n```\n## Congratulations!\n\nYou just completed a full OpenSpec cycle:\n\n1. **Explore** - Thought through the problem\n2. **New** - Created a change container\n3. **Proposal** - Captured WHY\n4. **Specs** - Defined WHAT in detail\n5. **Design** - Decided HOW\n6. **Tasks** - Broke it into steps\n7. **Apply** - Implemented the work\n8. **Archive** - Preserved the record\n\nThis same rhythm works for any size change—a small fix or a major feature.\n\n---\n\n## Command Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems before/during work |\n| `/opsx:new` | Start a new change, step through artifacts |\n| `/opsx:ff` | Fast-forward: create all artifacts at once |\n| `/opsx:continue` | Continue working on an existing change |\n| `/opsx:apply` | Implement tasks from a change |\n| `/opsx:verify` | Verify implementation matches artifacts |\n| `/opsx:archive` | Archive a completed change |\n\n---\n\n## What's Next?\n\nTry `/opsx:new` or `/opsx:ff` on something you actually want to build. You've got the rhythm now!\n```\n\n---\n\n## Graceful Exit Handling\n\n### User wants to stop mid-way\n\nIf the user says they need to stop, want to pause, or seem disengaged:\n\n```\nNo problem! Your change is saved at `openspec/changes/<name>/`.\n\nTo pick up where we left off later:\n- `/opsx:continue <name>` - Resume artifact creation\n- `/opsx:apply <name>` - Jump to implementation (if tasks exist)\n\nThe work won't be lost. Come back whenever you're ready.\n```\n\nExit gracefully without pressure.\n\n### User just wants command reference\n\nIf the user says they just want to see the commands or skip the tutorial:\n\n```\n## OpenSpec Quick Reference\n\n| Command | What it does |\n|---------|--------------|\n| `/opsx:explore` | Think through problems (no code changes) |\n| `/opsx:new <name>` | Start a new change, step by step |\n| `/opsx:ff <name>` | Fast-forward: all artifacts at once |\n| `/opsx:continue <name>` | Continue an existing change |\n| `/opsx:apply <name>` | Implement tasks |\n| `/opsx:verify <name>` | Verify implementation |\n| `/opsx:archive <name>` | Archive when done |\n\nTry `/opsx:new` to start your first change, or `/opsx:ff` if you want to move fast.\n```\n\nExit gracefully.\n\n---\n\n## Guardrails\n\n- **Follow the EXPLAIN → DO → SHOW → PAUSE pattern** at key transitions (after explore, after proposal draft, after tasks, after archive)\n- **Keep narration light** during implementation—teach without lecturing\n- **Don't skip phases** even if the change is small—the goal is teaching the workflow\n- **Pause for acknowledgment** at marked points, but don't over-pause\n- **Handle exits gracefully**—never pressure the user to continue\n- **Use real codebase tasks**—don't simulate or use fake examples\n- **Adjust scope gently**—guide toward smaller tasks but respect user choice\n"
  },
  {
    "path": ".qoder/skills/openspec-sync-specs/SKILL.md",
    "content": "---\nname: openspec-sync-specs\ndescription: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nSync delta specs from a change to main specs.\n\nThis is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have delta specs (under `specs/` directory).\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Find delta specs**\n\n   Look for delta spec files in `openspec/changes/<name>/specs/*/spec.md`.\n\n   Each delta spec file contains sections like:\n   - `## ADDED Requirements` - New requirements to add\n   - `## MODIFIED Requirements` - Changes to existing requirements\n   - `## REMOVED Requirements` - Requirements to remove\n   - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)\n\n   If no delta specs found, inform user and stop.\n\n3. **For each delta spec, apply changes to main specs**\n\n   For each capability with a delta spec at `openspec/changes/<name>/specs/<capability>/spec.md`:\n\n   a. **Read the delta spec** to understand the intended changes\n\n   b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)\n\n   c. **Apply changes intelligently**:\n\n      **ADDED Requirements:**\n      - If requirement doesn't exist in main spec → add it\n      - If requirement already exists → update it to match (treat as implicit MODIFIED)\n\n      **MODIFIED Requirements:**\n      - Find the requirement in main spec\n      - Apply the changes - this can be:\n        - Adding new scenarios (don't need to copy existing ones)\n        - Modifying existing scenarios\n        - Changing the requirement description\n      - Preserve scenarios/content not mentioned in the delta\n\n      **REMOVED Requirements:**\n      - Remove the entire requirement block from main spec\n\n      **RENAMED Requirements:**\n      - Find the FROM requirement, rename to TO\n\n   d. **Create new main spec** if capability doesn't exist yet:\n      - Create `openspec/specs/<capability>/spec.md`\n      - Add Purpose section (can be brief, mark as TBD)\n      - Add Requirements section with the ADDED requirements\n\n4. **Show summary**\n\n   After applying all changes, summarize:\n   - Which capabilities were updated\n   - What changes were made (requirements added/modified/removed/renamed)\n\n**Delta Spec Format Reference**\n\n```markdown\n## ADDED Requirements\n\n### Requirement: New Feature\nThe system SHALL do something new.\n\n#### Scenario: Basic case\n- **WHEN** user does X\n- **THEN** system does Y\n\n## MODIFIED Requirements\n\n### Requirement: Existing Feature\n#### Scenario: New scenario to add\n- **WHEN** user does A\n- **THEN** system does B\n\n## REMOVED Requirements\n\n### Requirement: Deprecated Feature\n\n## RENAMED Requirements\n\n- FROM: `### Requirement: Old Name`\n- TO: `### Requirement: New Name`\n```\n\n**Key Principle: Intelligent Merging**\n\nUnlike programmatic merging, you can apply **partial updates**:\n- To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios\n- The delta represents *intent*, not a wholesale replacement\n- Use your judgment to merge changes sensibly\n\n**Output On Success**\n\n```\n## Specs Synced: <change-name>\n\nUpdated main specs:\n\n**<capability-1>**:\n- Added requirement: \"New Feature\"\n- Modified requirement: \"Existing Feature\" (added 1 scenario)\n\n**<capability-2>**:\n- Created new spec file\n- Added requirement: \"Another Feature\"\n\nMain specs are now updated. The change remains active - archive when implementation is complete.\n```\n\n**Guardrails**\n- Read both delta and main specs before making changes\n- Preserve existing content not mentioned in delta\n- If something is unclear, ask for clarification\n- Show what you're changing as you go\n- The operation should be idempotent - running twice should give same result\n"
  },
  {
    "path": ".qoder/skills/openspec-verify-change/SKILL.md",
    "content": "---\nname: openspec-verify-change\ndescription: Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving.\nlicense: MIT\ncompatibility: Requires openspec CLI.\nmetadata:\n  author: openspec\n  version: \"1.0\"\n  generatedBy: \"1.1.1\"\n---\n\nVerify that an implementation matches the change artifacts (specs, tasks, design).\n\n**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.\n\n**Steps**\n\n1. **If no change name provided, prompt for selection**\n\n   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.\n\n   Show changes that have implementation tasks (tasks artifact exists).\n   Include the schema used for each change if available.\n   Mark changes with incomplete tasks as \"(In Progress)\".\n\n   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.\n\n2. **Check status to understand the schema**\n   ```bash\n   openspec status --change \"<name>\" --json\n   ```\n   Parse the JSON to understand:\n   - `schemaName`: The workflow being used (e.g., \"spec-driven\")\n   - Which artifacts exist for this change\n\n3. **Get the change directory and load artifacts**\n\n   ```bash\n   openspec instructions apply --change \"<name>\" --json\n   ```\n\n   This returns the change directory and context files. Read all available artifacts from `contextFiles`.\n\n4. **Initialize verification report structure**\n\n   Create a report structure with three dimensions:\n   - **Completeness**: Track tasks and spec coverage\n   - **Correctness**: Track requirement implementation and scenario coverage\n   - **Coherence**: Track design adherence and pattern consistency\n\n   Each dimension can have CRITICAL, WARNING, or SUGGESTION issues.\n\n5. **Verify Completeness**\n\n   **Task Completion**:\n   - If tasks.md exists in contextFiles, read it\n   - Parse checkboxes: `- [ ]` (incomplete) vs `- [x]` (complete)\n   - Count complete vs total tasks\n   - If incomplete tasks exist:\n     - Add CRITICAL issue for each incomplete task\n     - Recommendation: \"Complete task: <description>\" or \"Mark as done if already implemented\"\n\n   **Spec Coverage**:\n   - If delta specs exist in `openspec/changes/<name>/specs/`:\n     - Extract all requirements (marked with \"### Requirement:\")\n     - For each requirement:\n       - Search codebase for keywords related to the requirement\n       - Assess if implementation likely exists\n     - If requirements appear unimplemented:\n       - Add CRITICAL issue: \"Requirement not found: <requirement name>\"\n       - Recommendation: \"Implement requirement X: <description>\"\n\n6. **Verify Correctness**\n\n   **Requirement Implementation Mapping**:\n   - For each requirement from delta specs:\n     - Search codebase for implementation evidence\n     - If found, note file paths and line ranges\n     - Assess if implementation matches requirement intent\n     - If divergence detected:\n       - Add WARNING: \"Implementation may diverge from spec: <details>\"\n       - Recommendation: \"Review <file>:<lines> against requirement X\"\n\n   **Scenario Coverage**:\n   - For each scenario in delta specs (marked with \"#### Scenario:\"):\n     - Check if conditions are handled in code\n     - Check if tests exist covering the scenario\n     - If scenario appears uncovered:\n       - Add WARNING: \"Scenario not covered: <scenario name>\"\n       - Recommendation: \"Add test or implementation for scenario: <description>\"\n\n7. **Verify Coherence**\n\n   **Design Adherence**:\n   - If design.md exists in contextFiles:\n     - Extract key decisions (look for sections like \"Decision:\", \"Approach:\", \"Architecture:\")\n     - Verify implementation follows those decisions\n     - If contradiction detected:\n       - Add WARNING: \"Design decision not followed: <decision>\"\n       - Recommendation: \"Update implementation or revise design.md to match reality\"\n   - If no design.md: Skip design adherence check, note \"No design.md to verify against\"\n\n   **Code Pattern Consistency**:\n   - Review new code for consistency with project patterns\n   - Check file naming, directory structure, coding style\n   - If significant deviations found:\n     - Add SUGGESTION: \"Code pattern deviation: <details>\"\n     - Recommendation: \"Consider following project pattern: <example>\"\n\n8. **Generate Verification Report**\n\n   **Summary Scorecard**:\n   ```\n   ## Verification Report: <change-name>\n\n   ### Summary\n   | Dimension    | Status           |\n   |--------------|------------------|\n   | Completeness | X/Y tasks, N reqs|\n   | Correctness  | M/N reqs covered |\n   | Coherence    | Followed/Issues  |\n   ```\n\n   **Issues by Priority**:\n\n   1. **CRITICAL** (Must fix before archive):\n      - Incomplete tasks\n      - Missing requirement implementations\n      - Each with specific, actionable recommendation\n\n   2. **WARNING** (Should fix):\n      - Spec/design divergences\n      - Missing scenario coverage\n      - Each with specific recommendation\n\n   3. **SUGGESTION** (Nice to fix):\n      - Pattern inconsistencies\n      - Minor improvements\n      - Each with specific recommendation\n\n   **Final Assessment**:\n   - If CRITICAL issues: \"X critical issue(s) found. Fix before archiving.\"\n   - If only warnings: \"No critical issues. Y warning(s) to consider. Ready for archive (with noted improvements).\"\n   - If all clear: \"All checks passed. Ready for archive.\"\n\n**Verification Heuristics**\n\n- **Completeness**: Focus on objective checklist items (checkboxes, requirements list)\n- **Correctness**: Use keyword search, file path analysis, reasonable inference - don't require perfect certainty\n- **Coherence**: Look for glaring inconsistencies, don't nitpick style\n- **False Positives**: When uncertain, prefer SUGGESTION over WARNING, WARNING over CRITICAL\n- **Actionability**: Every issue must have a specific recommendation with file/line references where applicable\n\n**Graceful Degradation**\n\n- If only tasks.md exists: verify task completion only, skip spec/design checks\n- If tasks + specs exist: verify completeness and correctness, skip design\n- If full artifacts: verify all three dimensions\n- Always note which checks were skipped and why\n\n**Output Format**\n\nUse clear markdown with:\n- Table for summary scorecard\n- Grouped lists for issues (CRITICAL/WARNING/SUGGESTION)\n- Code references in format: `file.ts:123`\n- Specific, actionable recommendations\n- No vague suggestions like \"consider reviewing\"\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: java\njdk:\n  - oraclejdk8\nbefore_install:\n  - pip install --user codecov\nafter_success:\n  - codecov\nbranches:\n  except:\n    - appveyor\n\ncache:\n  directories:\n  - $HOME/.m2\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# AGENTS.md — Druid Project Context\n\n## Project Overview\n\nDruid is Alibaba's open-source high-performance JDBC connection pool and SQL parser for Java. Version: 1.2.29-SNAPSHOT.\n\n## Build & Test\n\n```bash\nmvn clean install              # Full build with tests\nmvn test -pl core              # Core module tests only\nmvn test -pl core -Dtest=<TestClass>  # Single test class\n```\n\n**Requirements:** Java 8+ JDK, Apache Maven 3.6+\n\n## Project Structure\n\n- `core/` — Main library: connection pool, SQL parser, filter chain, wall security, monitoring\n- `druid-spring-boot-starter/` — Spring Boot 2.x auto-configuration\n- `druid-spring-boot-3-starter/` — Spring Boot 3.x auto-configuration\n- `druid-spring-boot-4-starter/` — Spring Boot 4.x auto-configuration\n- `druid-admin/` — Cluster monitoring admin\n- `druid-wrapper/` — Wrapper utilities\n- `openspec/` — Architecture specs and change documentation\n\n## Key Source Paths\n\n- `core/src/main/java/com/alibaba/druid/pool/` — Connection pool (`DruidDataSource`)\n- `core/src/main/java/com/alibaba/druid/sql/dialect/` — 30 SQL dialect parsers\n- `core/src/main/java/com/alibaba/druid/sql/parser/` — Core parser infrastructure\n- `core/src/main/java/com/alibaba/druid/sql/ast/` — AST node classes\n- `core/src/main/java/com/alibaba/druid/filter/` — Filter chain implementations\n- `core/src/main/java/com/alibaba/druid/wall/` — SQL firewall (WallFilter)\n- `core/src/main/java/com/alibaba/druid/stat/` — Monitoring statistics\n\n## Testing Conventions\n\n- Tests are in `core/src/test/java/com/alibaba/druid/bvt/` (Black-box Verification Test)\n- SQL dialect tests use resource files: `core/src/test/resources/bvt/parser/<dialect>/*.txt`\n- Testing framework: JUnit 5 (migrated from JUnit 4)\n- Surefire pattern: `**/bvt/**/*.java`\n\n## SQL Dialect Pattern\n\nEach dialect in `sql/dialect/<name>/` follows this structure:\n- `<Name>Lexer` — Lexical analyzer\n- `<Name>ExprParser` — Expression parser\n- `<Name>StatementParser` — Statement parser\n- `<Name>OutputVisitor` — SQL output visitor\n- `<Name>ASTVisitor` — AST visitor interface\n- `<Name>SchemaStatVisitor` — Schema statistics visitor\n- Config: `META-INF/druid/parser/<name>/dialect.properties` and `builtin_datatypes`\n\n## Code Style\n\n- Java 8 compatible (source level 8)\n- Checkstyle enforced: `src/checkstyle/druid-checks.xml`\n- Visitor pattern for AST traversal\n- Filter-Chain (Chain of Responsibility) for JDBC interception\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Druid | 贡献指南\n\n[English](#english) | [中文](#中文)\n\n---\n\n## English\n\nThank you for your interest in contributing to Druid! This guide will help you get started.\n\n### Code of Conduct\n\nPlease be respectful and constructive in all interactions. We are committed to providing a welcoming and inclusive experience for everyone.\n\n### How to Contribute\n\n#### Reporting Bugs\n\n1. Search [existing issues](https://github.com/alibaba/druid/issues) to check if the bug has already been reported\n2. If not, [create a new issue](https://github.com/alibaba/druid/issues/new) with:\n   - A clear, descriptive title\n   - Steps to reproduce the problem\n   - Expected behavior vs actual behavior\n   - Druid version, Java version, and database type\n   - Relevant logs or stack traces\n\n#### Suggesting Features\n\nOpen a [GitHub Issue](https://github.com/alibaba/druid/issues/new) describing:\n- The use case and motivation\n- Expected behavior\n- Example code or configuration (if applicable)\n\n#### Submitting Code Changes\n\n1. **Fork** the repository and create your branch from `master`\n2. **Write code** following our conventions (see below)\n3. **Add tests** for any new functionality\n4. **Run the test suite** to verify nothing is broken\n5. **Submit a Pull Request** with a clear description\n\n### Development Setup\n\n#### Prerequisites\n\n- Java 8+ JDK\n- Apache Maven 3.6+\n- Git\n\n#### Building\n\n```bash\ngit clone https://github.com/alibaba/druid.git\ncd druid\nmvn clean install\n```\n\n#### Running Tests\n\n```bash\n# Run all tests\nmvn test\n\n# Run tests for a specific module\nmvn test -pl core\n\n# Run a specific test class\nmvn test -pl core -Dtest=com.alibaba.druid.bvt.sql.mysql.MySqlSelectTest\n```\n\n### Code Conventions\n\n- **Language:** Java 8+ compatible\n- **Style:** Follow the project's Checkstyle rules (`src/checkstyle/druid-checks.xml`)\n- **Testing:** All new features must include tests in the corresponding `bvt` (Black-box Verification Test) package\n- **SQL Dialect Tests:** Use the resource-driven test pattern with `.txt` files in `core/src/test/resources/bvt/parser/<dialect>/`\n\n### Project Structure\n\n```\ncore/src/main/java/com/alibaba/druid/\n├── pool/            # Connection pool implementation\n├── sql/\n│   ├── ast/         # SQL AST node classes\n│   ├── dialect/     # Dialect-specific parsers and visitors\n│   ├── parser/      # Core parser infrastructure\n│   └── visitor/     # AST visitor interfaces\n├── filter/          # Filter-Chain implementations\n├── stat/            # Monitoring and statistics\n├── wall/            # SQL firewall (WallFilter)\n└── util/            # Utility classes\n```\n\n### Adding a New SQL Dialect\n\nIf you want to add support for a new database dialect:\n\n1. Create the dialect package: `sql/dialect/<name>/`\n2. Implement these classes:\n   - `<Name>Lexer` - Lexical analyzer with dialect-specific keywords\n   - `<Name>ExprParser` - Expression parser\n   - `<Name>StatementParser` - Statement parser\n   - `<Name>SelectParser` - SELECT statement parser (if needed)\n   - `<Name>OutputVisitor` - SQL output/generation visitor\n   - `<Name>ASTVisitor` - AST visitor interface\n   - `<Name>SchemaStatVisitor` - Schema statistics visitor\n3. Register the dialect in `SQLParserUtils` and `SQLUtils`\n4. Add dialect configuration in `META-INF/druid/parser/<name>/`:\n   - `dialect.properties` - Quote characters and other settings\n   - `builtin_datatypes` - Supported data types\n5. Add comprehensive tests\n\n### Pull Request Guidelines\n\n- Keep PRs focused — one feature or fix per PR\n- Include tests for new functionality\n- Update documentation if behavior changes\n- Write clear commit messages in English\n- Reference related issues in the PR description\n\n### Review Process\n\n1. A maintainer will review your PR\n2. Address any requested changes\n3. Once approved, your PR will be merged\n\n---\n\n## 中文\n\n感谢你对 Druid 项目的关注！本指南将帮助你快速参与到项目开发中。\n\n### 行为准则\n\n请在所有交流中保持尊重和建设性态度。\n\n### 如何贡献\n\n#### 报告 Bug\n\n1. 先搜索[已有 Issue](https://github.com/alibaba/druid/issues)，确认是否已被报告\n2. 如果没有，[创建新 Issue](https://github.com/alibaba/druid/issues/new)，包含：\n   - 清晰的标题\n   - 复现步骤\n   - 期望行为与实际行为\n   - Druid 版本、Java 版本、数据库类型\n   - 相关日志或堆栈信息\n\n#### 建议新功能\n\n提交 [GitHub Issue](https://github.com/alibaba/druid/issues/new)，描述：\n- 使用场景和动机\n- 期望的行为\n- 示例代码或配置（如适用）\n\n#### 提交代码\n\n1. **Fork** 仓库，基于 `master` 创建分支\n2. 按照代码规范**编写代码**\n3. 为新功能**添加测试**\n4. **运行测试**确保没有破坏现有功能\n5. **提交 Pull Request**，附上清晰的描述\n\n### 开发环境\n\n#### 前提条件\n\n- Java 8+ JDK\n- Apache Maven 3.6+\n- Git\n\n#### 构建\n\n```bash\ngit clone https://github.com/alibaba/druid.git\ncd druid\nmvn clean install\n```\n\n#### 运行测试\n\n```bash\n# 运行所有测试\nmvn test\n\n# 运行特定模块的测试\nmvn test -pl core\n\n# 运行特定测试类\nmvn test -pl core -Dtest=com.alibaba.druid.bvt.sql.mysql.MySqlSelectTest\n```\n\n### 代码规范\n\n- **语言：** 兼容 Java 8+\n- **风格：** 遵循项目的 Checkstyle 规则（`src/checkstyle/druid-checks.xml`）\n- **测试：** 所有新功能必须在 `bvt`（黑盒验证测试）包中添加对应测试\n- **SQL 方言测试：** 使用 `core/src/test/resources/bvt/parser/<dialect>/` 下的 `.txt` 资源驱动测试\n\n### 添加新的 SQL 方言\n\n如果要添加新的数据库方言支持：\n\n1. 创建方言包：`sql/dialect/<name>/`\n2. 实现以下类：\n   - `<Name>Lexer` - 词法分析器（含方言特有关键字）\n   - `<Name>ExprParser` - 表达式解析器\n   - `<Name>StatementParser` - 语句解析器\n   - `<Name>SelectParser` - SELECT 解析器（如需要）\n   - `<Name>OutputVisitor` - SQL 输出访问者\n   - `<Name>ASTVisitor` - AST 访问者接口\n   - `<Name>SchemaStatVisitor` - Schema 统计访问者\n3. 在 `SQLParserUtils` 和 `SQLUtils` 中注册方言\n4. 在 `META-INF/druid/parser/<name>/` 添加配置：\n   - `dialect.properties` - 引号字符等设置\n   - `builtin_datatypes` - 支持的数据类型\n5. 添加完整的测试用例\n\n### Pull Request 规范\n\n- 保持 PR 聚焦 — 每个 PR 只包含一个功能或修复\n- 新功能必须包含测试\n- 行为变更需更新文档\n- 使用英文编写清晰的 commit message\n- 在 PR 描述中引用相关 Issue\n\n### 审核流程\n\n1. 维护者将审核你的 PR\n2. 根据反馈进行修改\n3. 审核通过后合并\n"
  },
  {
    "path": "NOTICE",
    "content": "Alibaba Druid\nCopyright 1999-2021 Alibaba Group Holding Ltd.\n"
  },
  {
    "path": "QWEN.md",
    "content": "# Qwen Code Context for Druid Project\n\nThis document provides essential context for Qwen Code to understand and assist with the Druid project.\n\n## Project Overview\n\nThis is a **Java** project. Druid is a high-performance, scalable JDBC connection pool implementation for Java applications. It's designed to provide efficient database connection management and includes features for monitoring and statistics.\n\nKey aspects:\n- **Main Technology:** Java, built with Maven.\n- **Core Functionality:** JDBC Connection Pooling (`DruidDataSource`).\n- **Additional Features:** SQL monitoring, statistics, and security features like SQL firewall (`WallFilter`).\n- **Integration:** Provides Spring Boot starters for easy integration (`druid-spring-boot-starter`, `druid-spring-boot-3-starter`).\n\n## Project Structure\n\n- `pom.xml`: Root Maven project file. Defines parent POM, manages modules, dependencies, and build profiles.\n- `core/`: Contains the main Druid library source code.\n    - `core/pom.xml`: Maven configuration for the core library.\n    - `core/src/main/java/com/alibaba/druid/`: Main source code for the Druid library.\n        - `pool/`: Core connection pooling logic (e.g., `DruidDataSource`).\n        - `sql/`: SQL parsing and analysis.\n        - `stat/`: Statistics collection and management.\n        - `wall/`: SQL firewall/filtering logic.\n        - `filter/`: Extensible filter mechanism for connections/statements.\n- `druid-spring-boot-starter/`: Spring Boot Starter for integrating Druid into Spring Boot 2.x applications.\n- `druid-spring-boot-3-starter/`: Spring Boot Starter for integrating Druid into Spring Boot 3.x applications.\n- `druid-demo-petclinic/`: A demo application, likely based on Spring PetClinic, showcasing Druid usage.\n- `doc/`: Documentation files.\n- `README.md`: General project introduction and quick start guide.\n\n## Building and Running\n\n- **Prerequisites:** Java 8+ JDK, Apache Maven.\n- **Build Command:** `mvn clean install` (from the project root). This compiles the code, runs tests, and packages the artifacts (JARs).\n- **Run Demo:** Navigate to `druid-demo-petclinic` and follow its specific instructions (likely `mvn spring-boot:run`).\n\n## Development Conventions\n\n- **Build Tool:** Apache Maven is used for dependency management and building.\n- **Language:** Java.\n- **Testing:** Unit and integration tests are likely located within `src/test` directories of respective modules (e.g., `core/src/test`). The `pom.xml` configures the `maven-surefire-plugin` to run tests.\n- **Code Style:** Checkstyle is configured (see `pom.xml` and `src/checkstyle/druid-checks.xml`) to enforce coding standards.\n- **Modularization:** The project is a multi-module Maven project, separating the core library from Spring Boot integration modules.\n- **Versioning:** Version information is managed in the root `pom.xml` and reflected in `core/src/main/java/com/alibaba/druid/VERSION.java`."
  },
  {
    "path": "README.md",
    "content": "# Alibaba Druid\r\n\r\n[![Java CI](https://img.shields.io/github/actions/workflow/status/alibaba/druid/ci.yaml?branch=master&logo=github&logoColor=white)](https://github.com/alibaba/druid/actions/workflows/ci.yaml)\r\n[![Codecov](https://img.shields.io/codecov/c/github/alibaba/druid/master?logo=codecov&logoColor=white)](https://codecov.io/gh/alibaba/druid/branch/master)\r\n[![Maven Central](https://img.shields.io/maven-central/v/com.alibaba/druid?logo=apache-maven&logoColor=white)](https://search.maven.org/artifact/com.alibaba/druid)\r\n[![Last SNAPSHOT](https://img.shields.io/nexus/snapshots/https/oss.sonatype.org/com.alibaba/druid?label=latest%20snapshot)](https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/druid/)\r\n[![GitHub release](https://img.shields.io/github/release/alibaba/druid)](https://github.com/alibaba/druid/releases)\r\n[![License](https://img.shields.io/github/license/alibaba/druid?color=4D7A97&logo=apache)](https://www.apache.org/licenses/LICENSE-2.0.html)\r\n\r\n[English](README_EN.md) | 中文\r\n\r\n---\r\n\r\n**Druid** 是阿里巴巴开源的高性能数据库连接池和 SQL 解析器。它将 JDBC 连接池、SQL 解析分析、安全防护和监控统计深度整合为一体，是 Java 生态中功能最全面的数据库中间件之一。\r\n\r\n## 核心特性\r\n\r\n| 功能领域 | 说明 |\r\n|---------|------|\r\n| **JDBC 连接池** | 高性能、可监控的连接池实现 `DruidDataSource`，支持物理连接预热、PSCache、KeepAlive 等高级特性 |\r\n| **SQL 解析器** | 支持 30 种 SQL 方言的完整解析器，生成 AST 抽象语法树，支持 SQL 格式化、改写和分析 |\r\n| **SQL 防火墙** | 基于 AST 的 `WallFilter` SQL 安全防护，可拦截 SQL 注入、危险操作等 |\r\n| **监控统计** | 内置 `StatFilter` 实时采集 SQL 执行统计、连接池状态，提供 Web 监控页面 |\r\n| **Filter 扩展** | 可插拔的 Filter-Chain 架构，支持日志、加密、统计等扩展 |\r\n| **Spring Boot 集成** | 提供 Spring Boot 2.x / 3.x / 4.x Starter，开箱即用 |\r\n| **高可用** | `HighAvailableDataSource` 支持多数据源负载均衡、健康检查和故障切换 |\r\n\r\n## 快速开始\r\n\r\n### Maven 依赖\r\n\r\n```xml\r\n<dependency>\r\n    <groupId>com.alibaba</groupId>\r\n    <artifactId>druid</artifactId>\r\n    <version>1.2.24</version>\r\n</dependency>\r\n```\r\n\r\n### Spring Boot 项目（推荐）\r\n\r\n根据 Spring Boot 版本选择对应 Starter：\r\n\r\n| Spring Boot 版本 | Starter |\r\n|-----------------|---------|\r\n| 2.x | `druid-spring-boot-starter` |\r\n| 3.x | `druid-spring-boot-3-starter` |\r\n| 4.x | `druid-spring-boot-4-starter` |\r\n\r\n```xml\r\n<!-- Spring Boot 3.x 示例 -->\r\n<dependency>\r\n    <groupId>com.alibaba</groupId>\r\n    <artifactId>druid-spring-boot-3-starter</artifactId>\r\n    <version>1.2.24</version>\r\n</dependency>\r\n```\r\n\r\n```yaml\r\n# application.yml\r\nspring:\r\n  datasource:\r\n    url: jdbc:mysql://localhost:3306/mydb\r\n    username: root\r\n    password: password\r\n    druid:\r\n      initial-size: 5\r\n      max-active: 20\r\n      min-idle: 5\r\n      max-wait: 60000\r\n      # 启用 Filter\r\n      filter:\r\n        stat:\r\n          enabled: true\r\n          log-slow-sql: true\r\n          slow-sql-millis: 2000\r\n        wall:\r\n          enabled: true\r\n```\r\n\r\n### 直接使用 DruidDataSource\r\n\r\n```java\r\nDruidDataSource dataSource = new DruidDataSource();\r\ndataSource.setUrl(\"jdbc:mysql://localhost:3306/mydb\");\r\ndataSource.setUsername(\"root\");\r\ndataSource.setPassword(\"password\");\r\ndataSource.setInitialSize(5);\r\ndataSource.setMaxActive(20);\r\ndataSource.setMinIdle(5);\r\ndataSource.init();\r\n\r\n// 使用连接\r\ntry (Connection conn = dataSource.getConnection()) {\r\n    // 执行 SQL\r\n}\r\n```\r\n\r\n### SQL 解析器\r\n\r\n```java\r\n// 解析 SQL\r\nString sql = \"SELECT id, name FROM users WHERE age > 18 ORDER BY name\";\r\nList<SQLStatement> stmts = SQLUtils.parseStatements(sql, DbType.mysql);\r\n\r\n// 格式化 SQL\r\nString formatted = SQLUtils.format(sql, DbType.mysql);\r\n\r\n// 获取表信息\r\nSchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\r\nstmts.get(0).accept(visitor);\r\nSystem.out.println(\"Tables: \" + visitor.getTables());\r\nSystem.out.println(\"Columns: \" + visitor.getColumns());\r\n```\r\n\r\n## 项目模块\r\n\r\n```\r\ndruid/\r\n├── core/                           # 核心库（连接池、SQL 解析、安全、监控）\r\n├── druid-spring-boot-starter/      # Spring Boot 2.x 自动配置\r\n├── druid-spring-boot-3-starter/    # Spring Boot 3.x 自动配置\r\n├── druid-spring-boot-4-starter/    # Spring Boot 4.x 自动配置\r\n├── druid-wrapper/                  # 包装工具\r\n├── druid-admin/                    # 集群监控管理端\r\n└── doc/                            # 文档\r\n```\r\n\r\n## SQL 方言支持\r\n\r\nDruid SQL 解析器支持 30 种数据库方言，每种方言都提供完整的 Lexer、Parser、AST 和 Visitor 实现：\r\n\r\n| 分类 | 支持的数据库 |\r\n|------|------------|\r\n| **主流关系型** | MySQL, PostgreSQL, Oracle, SQL Server, DB2, H2, Informix |\r\n| **国产数据库** | 达梦 (DM), Oscar, GaussDB |\r\n| **分析型/MPP** | ClickHouse, Doris, StarRocks, Teradata, Redshift |\r\n| **云原生/数仓** | BigQuery, Snowflake, Synapse, Hologres, ODPS (MaxCompute) |\r\n| **计算引擎** | Hive, Spark, Presto, Impala, Athena, Blink, Databricks |\r\n| **其他** | Phoenix, SuperSQL, Transact-SQL |\r\n\r\n## 文档\r\n\r\n| 文档 | 说明 |\r\n|------|------|\r\n| [架构概览](doc/architecture.md) | 整体架构设计与核心组件交互 |\r\n| [连接池指南](doc/connection-pool-guide.md) | DruidDataSource 配置、调优与最佳实践 |\r\n| [SQL 解析器指南](doc/sql-parser-guide.md) | SQL 解析、格式化、改写与方言扩展 |\r\n| [SQL 方言支持](doc/sql-dialect-support.md) | 完整方言支持矩阵与各方言特性 |\r\n| [Filter 机制](doc/filter-guide.md) | Filter-Chain 架构与自定义 Filter 开发 |\r\n| [SQL 防火墙](doc/wall-security-guide.md) | WallFilter 配置与 SQL 安全防护 |\r\n| [监控统计](doc/monitoring-guide.md) | StatFilter 与 Web 监控页面 |\r\n| [高可用数据源](doc/ha-datasource.md) | HighAvailableDataSource 配置与使用 |\r\n| [Spring Boot 集成](druid-spring-boot-starter/README.md) | Spring Boot Starter 配置指南 |\r\n| [Wiki (中文)](https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) | 常见问题与进阶文档 |\r\n| [Wiki (English)](https://github.com/alibaba/druid/wiki/FAQ) | FAQ and documentation |\r\n\r\n## 从源码构建\r\n\r\n```bash\r\ngit clone https://github.com/alibaba/druid.git\r\ncd druid\r\nmvn clean install\r\n```\r\n\r\n**要求：** Java 8+ JDK，Apache Maven 3.6+\r\n\r\n## 贡献\r\n\r\n欢迎参与 Druid 项目！请阅读 [贡献指南](CONTRIBUTING.md) 了解如何参与开发。\r\n\r\n## 安全漏洞\r\n\r\n请勿通过公开 Issue 报告安全漏洞。详见 [安全策略](SECURITY.md)。\r\n\r\n## 相关阿里云产品\r\n\r\n* [DataWorks 数据集成](https://help.aliyun.com/document_detail/137663.html)\r\n\r\n## License\r\n\r\nDruid 基于 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html) 开源。\r\n"
  },
  {
    "path": "README_EN.md",
    "content": "# Alibaba Druid\n\n[![Java CI](https://img.shields.io/github/actions/workflow/status/alibaba/druid/ci.yaml?branch=master&logo=github&logoColor=white)](https://github.com/alibaba/druid/actions/workflows/ci.yaml)\n[![Codecov](https://img.shields.io/codecov/c/github/alibaba/druid/master?logo=codecov&logoColor=white)](https://codecov.io/gh/alibaba/druid/branch/master)\n[![Maven Central](https://img.shields.io/maven-central/v/com.alibaba/druid?logo=apache-maven&logoColor=white)](https://search.maven.org/artifact/com.alibaba/druid)\n[![Last SNAPSHOT](https://img.shields.io/nexus/snapshots/https/oss.sonatype.org/com.alibaba/druid?label=latest%20snapshot)](https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/druid/)\n[![GitHub release](https://img.shields.io/github/release/alibaba/druid)](https://github.com/alibaba/druid/releases)\n[![License](https://img.shields.io/github/license/alibaba/druid?color=4D7A97&logo=apache)](https://www.apache.org/licenses/LICENSE-2.0.html)\n\nEnglish | [中文](README.md)\n\n---\n\n**Druid** is a high-performance database connection pool and SQL parser open-sourced by Alibaba. It deeply integrates JDBC connection pooling, SQL parsing and analysis, security protection, and monitoring statistics into one package, making it one of the most comprehensive database middleware solutions in the Java ecosystem.\n\n## Key Features\n\n| Capability | Description |\n|-----------|-------------|\n| **JDBC Connection Pool** | High-performance, monitorable pool implementation `DruidDataSource` with connection warm-up, PSCache, KeepAlive and more |\n| **SQL Parser** | Full parser for 30 SQL dialects, generating AST (Abstract Syntax Tree) with support for formatting, rewriting and analysis |\n| **SQL Firewall** | AST-based `WallFilter` for SQL injection protection, blocking dangerous operations |\n| **Monitoring & Stats** | Built-in `StatFilter` for real-time SQL execution statistics, connection pool status, and Web monitoring console |\n| **Filter Extension** | Pluggable Filter-Chain architecture supporting logging, encryption, statistics and custom extensions |\n| **Spring Boot Integration** | Starters for Spring Boot 2.x / 3.x / 4.x with auto-configuration |\n| **High Availability** | `HighAvailableDataSource` supporting multi-datasource load balancing, health checks and failover |\n\n## Quick Start\n\n### Maven Dependency\n\n```xml\n<dependency>\n    <groupId>com.alibaba</groupId>\n    <artifactId>druid</artifactId>\n    <version>1.2.24</version>\n</dependency>\n```\n\n### Spring Boot (Recommended)\n\nChoose the starter matching your Spring Boot version:\n\n| Spring Boot Version | Starter |\n|-------------------|---------|\n| 2.x | `druid-spring-boot-starter` |\n| 3.x | `druid-spring-boot-3-starter` |\n| 4.x | `druid-spring-boot-4-starter` |\n\n```xml\n<!-- Spring Boot 3.x example -->\n<dependency>\n    <groupId>com.alibaba</groupId>\n    <artifactId>druid-spring-boot-3-starter</artifactId>\n    <version>1.2.24</version>\n</dependency>\n```\n\n```yaml\n# application.yml\nspring:\n  datasource:\n    url: jdbc:mysql://localhost:3306/mydb\n    username: root\n    password: password\n    druid:\n      initial-size: 5\n      max-active: 20\n      min-idle: 5\n      max-wait: 60000\n      filter:\n        stat:\n          enabled: true\n          log-slow-sql: true\n          slow-sql-millis: 2000\n        wall:\n          enabled: true\n```\n\n### Direct DruidDataSource Usage\n\n```java\nDruidDataSource dataSource = new DruidDataSource();\ndataSource.setUrl(\"jdbc:mysql://localhost:3306/mydb\");\ndataSource.setUsername(\"root\");\ndataSource.setPassword(\"password\");\ndataSource.setInitialSize(5);\ndataSource.setMaxActive(20);\ndataSource.setMinIdle(5);\ndataSource.init();\n\ntry (Connection conn = dataSource.getConnection()) {\n    // execute SQL\n}\n```\n\n### SQL Parser\n\n```java\n// Parse SQL\nString sql = \"SELECT id, name FROM users WHERE age > 18 ORDER BY name\";\nList<SQLStatement> stmts = SQLUtils.parseStatements(sql, DbType.mysql);\n\n// Format SQL\nString formatted = SQLUtils.format(sql, DbType.mysql);\n\n// Extract schema information\nSchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\nstmts.get(0).accept(visitor);\nSystem.out.println(\"Tables: \" + visitor.getTables());\nSystem.out.println(\"Columns: \" + visitor.getColumns());\n```\n\n## Project Modules\n\n```\ndruid/\n├── core/                           # Core library (pool, SQL parser, security, monitoring)\n├── druid-spring-boot-starter/      # Spring Boot 2.x auto-configuration\n├── druid-spring-boot-3-starter/    # Spring Boot 3.x auto-configuration\n├── druid-spring-boot-4-starter/    # Spring Boot 4.x auto-configuration\n├── druid-wrapper/                  # Wrapper utilities\n├── druid-admin/                    # Cluster monitoring admin\n└── doc/                            # Documentation\n```\n\n## SQL Dialect Support\n\nThe Druid SQL parser supports 30 database dialects, each with full Lexer, Parser, AST and Visitor implementations:\n\n| Category | Supported Databases |\n|----------|-------------------|\n| **Major RDBMS** | MySQL, PostgreSQL, Oracle, SQL Server, DB2, H2, Informix |\n| **Chinese Databases** | Dameng (DM), Oscar, GaussDB |\n| **Analytical / MPP** | ClickHouse, Doris, StarRocks, Teradata, Redshift |\n| **Cloud / Data Warehouse** | BigQuery, Snowflake, Synapse, Hologres, ODPS (MaxCompute) |\n| **Compute Engines** | Hive, Spark, Presto, Impala, Athena, Blink, Databricks |\n| **Other** | Phoenix, SuperSQL, Transact-SQL |\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Architecture Overview](doc/architecture.md) | System architecture and core component interactions |\n| [Connection Pool Guide](doc/connection-pool-guide.md) | DruidDataSource configuration, tuning and best practices |\n| [SQL Parser Guide](doc/sql-parser-guide.md) | SQL parsing, formatting, rewriting and dialect extensions |\n| [SQL Dialect Support](doc/sql-dialect-support.md) | Complete dialect support matrix and per-dialect features |\n| [Filter Mechanism](doc/filter-guide.md) | Filter-Chain architecture and custom Filter development |\n| [SQL Firewall](doc/wall-security-guide.md) | WallFilter configuration and SQL security |\n| [Monitoring & Statistics](doc/monitoring-guide.md) | StatFilter and Web monitoring console |\n| [High Availability](doc/ha-datasource.md) | HighAvailableDataSource configuration and usage |\n| [Spring Boot Integration](druid-spring-boot-starter/README_EN.md) | Spring Boot Starter configuration guide |\n| [Wiki](https://github.com/alibaba/druid/wiki/FAQ) | FAQ and additional documentation |\n\n## Building from Source\n\n```bash\ngit clone https://github.com/alibaba/druid.git\ncd druid\nmvn clean install\n```\n\n**Requirements:** Java 8+ JDK, Apache Maven 3.6+\n\n## Contributing\n\nContributions are welcome! Please read the [Contributing Guide](CONTRIBUTING.md) for details.\n\n## Security\n\nPlease do not report security vulnerabilities through public issues. See [Security Policy](SECURITY.md).\n\n## License\n\nDruid is open-sourced under [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# 漏洞奖励计划 \n## 报告\n如果您认为自己在本程序中发现了任何安全（技术）漏洞，欢迎您通过 https://security.alibaba.com 向我们提交漏洞报告。\n如果您报告任何安全漏洞，请注意您可能包含以下信息（合格报告）：\n* git程序URL地址，运行的环境\n* 包含必要屏幕截图的详细说明\n* 重现漏洞的步骤以及修复漏洞的建议。\n* 其他有用信息\n\n## 处理\nASRC（Alibaba Security Response Center阿里安全响应中心）将尽快审核并回复您的提交内容，并在我们努力修复您提交的漏洞时随时通知您。如有必要，我们可能会与您联系以获取更多信息。\n\n\n## 条款和条件\n1. 仅接受技术漏洞并对其进行评级\n2. 出于安全原因，上报者同意与ASRC合作完成他/她提交的漏洞，不向任何第三方透露任何漏洞信息\n3. 如果不止一个人报告相同的安全漏洞，奖励将给予完成合格报告的第一个人\n4. 为了保护程序的用户，请在修复之前不要直接提交git的issue，也不要在社区讨论任何漏洞信息\n5. 所有奖励和声誉积分将提供给仅向ASRC提交其安全漏洞的上报者\n6. 安全漏洞奖励的解释权利归ASRC所有\n\n## 收集范围\n我们的主要收集漏洞类别是：\n* 服务器端请求伪造（SSRF）\n* SQL注入\n* 拒绝服务攻击\n* 远程执行代码（RCE）\n* XML外部实体攻击（XXE）\n* 访问控制问题（不安全的直接对象参考问题等）\n* 敏感目录遍历问题\n* 本地文件读取（LFD）\n* 敏感信息泄露（密钥，Cookie，Session等）\n\n## 奖励\n* 可直接导致严重问题的每个漏洞奖励7000元人民币\n* 存在限制及需要一定特殊环境下才能利用的问题将给予700-5600元人民币不等的奖励，比如需要用户主动点击才会触发的问题或需要admin权限\n* 只有在指定环境下才可以运行的利用将有可能被收纳但不给予奖励，或直接被忽略，比如只在fastjson+linux特定版本才会出现的问题\n\n## 不在收集范围的报告\n* 影响过时浏览器或平台用户的漏洞\n* Self-XSS\n* 会话固定\n* 内容欺骗\n* 缺少cookie标记\n* 混合内容警告\n* SSL / TLS问题\n* Clickjacking \n* 基于Flash的漏洞\n* 反射文件下载攻击（RFD）\n* 物理或社会工程攻击\n* 未验证自动化工具或扫描仪的结果\n* 登录/注销/未认证/低影响CSRF\n* 需要MITM或物理访问用户设备的攻击\n* 与网络协议或行业标准相关的问题\n* 不能用于直接攻击的错误信息泄露\n* 缺少与安全相关的HTTP标头等\n\n\n\n\n\n# Vulnerability Reward Program\n## Reporting\nIf you believe you have found any security (technical) vulnerability in the Program, you are welcomed to submit a vulnerability report to us at https://security.alibaba.com \nIn case of reporting any security vulnerability, please be noted that you may including following information (Qualified Reporting):\n* The git program URL and running version \n* A detailed description with necessary screenshots\n* Steps to reappearance the vulnerability and your advice to fix it\n* Other useful information\n\n\n## Processing\nASRC (Alibaba Security Response Center) will review and respond as quickly as possible to your submission, and keep you informed as we work to fix the vulnerability you submitted. We may contact you for further information if necessary.\n\n\n## Terms and Conditions\n1. ONLY technical vulnerabilities will be accepted and rated.\n2. With regarding to security reasons, reporters agree to cooperate with ASRC exclusively on the vulnerability he/she submitted and not disclose any information of vulnerability to any third-parties.\n3. In the case that more than one person report the same security vulnerability, the reward will be given to the first person who accomplish a Qualified Reporting.\n4. To protect users of the program, please do not directly submit issue on github or discuss anything with the community \n5. All Rewards and Reputation Credits are given to the reporters who submit his/her security vulnerabilities ONLY to ASRC.\n6. All rights for the security vulnerability rewards are reserved by ASRC.\n\n## Scope of Collecting\nThe main categories of vulnerabilities that we are sincerely looking for are:\n* Server-Side Request Forgery (SSRF)\n* SQL Injection\n* Denial of Service Attack\n* Remote Code Execution (RCE)\n* XML External Entity Attacks (XXE)\n* Access Control Issues (Insecure Direct Object Reference issues, etc.)\n* Directory Traversal Issues\n* Local File Disclosure (LFD)\n* Sensitive Information Leakage (Key, Cookie, Session etc.)\n\n## Reward\n* $1,000 for one valid report\n* $100-$800 for Vuls which is limited. For example, Vuls that need user interactions or administrator authority\n* Vuls which only work on the special version will be accepted but no reward, or directly rejected. For example, Vul runs only on a special linux version\n\n## Ineligible Reports\n* Vulnerabilities affecting users of outdated browsers or platforms\n* \"Self\" XSS\n* Session fixation\n* Content Spoofing\n* Missing cookie flags\n* Mixed content warnings\n* SSL/TLS best practices\n* Clickjacking/UI redressing\n* Flash-based vulnerabilities\n* Reflected file download attacks (RFD)\n* Physical or social engineering attacks\n* Unverified Results of automated tools or scanners\n* Login/logout/unauthenticated/low-impact CSRF\n* Attacks requiring MITM or physical access to a user's device\n* Issues related to networking protocols or industry standards\n* Error information disclosure that cannot be used to make a direct attack\n* Missing security-related HTTP headers which do not lead directly to a vulnerability\n\n\n"
  },
  {
    "path": "codecov.yml",
    "content": "comment:\r\n  behavior: default\r\n  layout: reach,diff,flags,files,footer\r\n  require_changes: false\r\n"
  },
  {
    "path": "core/.gitignore",
    "content": "/target\n/src/test/java/com/alibaba/druid/bvt/inc/\n/src/test/resources/bvt/inc/\n"
  },
  {
    "path": "core/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\t\t xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<parent>\n\t\t<groupId>com.alibaba</groupId>\n\t\t<artifactId>druid-parent</artifactId>\n\t\t<version>1.2.29-SNAPSHOT</version>\n\t\t<relativePath>../pom.xml</relativePath>\n\t</parent>\n\t<artifactId>druid</artifactId>\n\t<packaging>jar</packaging>\n\t<name>druid</name>\n\t<description>A JDBC datasource implementation.</description>\n\t<url>https://github.com/alibaba/druid</url>\n\t<inceptionYear>2013</inceptionYear>\n\n\t<properties>\n\t\t<spring.version>4.3.20.RELEASE</spring.version>\n\t\t<junit-jupiter.version>5.11.4</junit-jupiter.version>\n\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<jdk.version>1.8</jdk.version>\n\t</properties>\n\n\t<developers>\n\t\t<developer>\n\t\t\t<id>wenshao</id>\n\t\t\t<name>wenshao</name>\n\t\t\t<email>szujobs@hotmail.com</email>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>kiki</id>\n\t\t\t<name>kiki</name>\n\t\t\t<email>little.fierydragon@gmail.com</email>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<id>yako</id>\n\t\t\t<name>yako</name>\n\t\t\t<email>yakolyh@gmail.com</email>\n\t\t</developer>\n\t</developers>\n\n\t<licenses>\n\t\t<license>\n\t\t\t<name>Apache 2</name>\n\t\t\t<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>\n\t\t\t<distribution>repo</distribution>\n\t\t\t<comments>A business-friendly OSS license</comments>\n\t\t</license>\n\t</licenses>\n\t<scm>\n\t\t<url>https://github.com/alibaba/druid</url>\n\t\t<connection>scm:git:https://git@github.com/alibaba/druid.git</connection>\n\t</scm>\n\n\t<organization>\n\t\t<name>Alibaba Group</name>\n\t\t<url>https://github.com/alibaba</url>\n\t</organization>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<includes>\n\t\t\t\t\t\t<include>**/bvt/**/*.java</include>\n\t\t\t\t\t</includes>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-sources</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar-no-fork</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t\t<configuration>\n\t\t\t\t\t<attach>true</attach>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>sql-tests</id>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t<include>**/bvt/sql/**/*.java</include>\n\t\t\t\t\t\t\t\t<include>**/bvt/filter/wall/**/*.java</include>\n\t\t\t\t\t\t\t\t<include>**/bvt/bug/**/*.java</include>\n\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\t\t<profile>\n\t\t\t<id>non-sql-tests</id>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-surefire-plugin</artifactId>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<includes>\n\t\t\t\t\t\t\t\t<include>**/bvt/**/*.java</include>\n\t\t\t\t\t\t\t</includes>\n\t\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t\t<exclude>**/bvt/sql/**/*.java</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/bvt/filter/wall/**/*.java</exclude>\n\t\t\t\t\t\t\t\t<exclude>**/bvt/bug/**/*.java</exclude>\n\t\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\t</profiles>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>simple-jndi</groupId>\n\t\t\t<artifactId>simple-jndi</artifactId>\n\t\t\t<version>0.11.4.1</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>javax.transaction</groupId>\n\t\t\t<artifactId>jta</artifactId>\n\t\t\t<version>1.1</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>javax.servlet</groupId>\n\t\t\t<artifactId>javax.servlet-api</artifactId>\n\t\t\t<version>3.1.0</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>commons-logging</groupId>\n\t\t\t<artifactId>commons-logging</artifactId>\n\t\t\t<version>1.2</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>jakarta.servlet</groupId>\n\t\t\t<artifactId>jakarta.servlet-api</artifactId>\n\t\t\t<version>5.0.0</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-core</artifactId>\n\t\t\t<version>${spring.version}</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-beans</artifactId>\n\t\t\t<version>${spring.version}</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-orm</artifactId>\n\t\t\t<version>${spring.version}</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-webmvc</artifactId>\n\t\t\t<version>${spring.version}</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-ibatis</artifactId>\n\t\t\t<version>2.0.8</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis</groupId>\n\t\t\t<artifactId>mybatis</artifactId>\n\t\t\t<version>3.4.0</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.mybatis</groupId>\n\t\t\t<artifactId>mybatis-spring</artifactId>\n\t\t\t<version>1.3.0</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>log4j</groupId>\n\t\t\t<artifactId>log4j</artifactId>\n\t\t\t<version>1.2.17</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-api</artifactId>\n\t\t\t<version>1.7.9</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.slf4j</groupId>\n\t\t\t<artifactId>slf4j-log4j12</artifactId>\n\t\t\t<version>1.7.9</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.logging.log4j</groupId>\n\t\t\t<artifactId>log4j-api</artifactId>\n\t\t\t<version>2.13.2</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.logging.log4j</groupId>\n\t\t\t<artifactId>log4j-core</artifactId>\n\t\t\t<version>2.17.0</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.mysql</groupId>\n\t\t\t<artifactId>mysql-connector-j</artifactId>\n\t\t\t<version>8.0.33</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>net.sourceforge.jtds</groupId>\n\t\t\t<artifactId>jtds</artifactId>\n\t\t\t<version>1.3.0</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.postgresql</groupId>\n\t\t\t<artifactId>postgresql</artifactId>\n\t\t\t<version>42.2.18</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.oracle.ojdbc</groupId>\n\t\t\t<artifactId>ojdbc8</artifactId>\n\t\t\t<version>19.3.0.0</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.oceanbase</groupId>\n\t\t\t<artifactId>oceanbase-client</artifactId>\n\t\t\t<version>2.4.12</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.dameng</groupId>\n\t\t\t<artifactId>DmJdbcDriver18</artifactId>\n\t\t\t<version>8.1.3.62</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.kylin</groupId>\n\t\t\t<artifactId>kylin-jdbc</artifactId>\n\t\t\t<version>2.0.0</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>io.trino</groupId>\n\t\t\t<artifactId>trino-jdbc</artifactId>\n\t\t\t<version>352</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.quartz-scheduler</groupId>\n\t\t\t<artifactId>quartz</artifactId>\n\t\t\t<version>2.3.2</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.ibatis</groupId>\n\t\t\t<artifactId>ibatis-sqlmap</artifactId>\n\t\t\t<version>2.3.4.726</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.h2database</groupId>\n\t\t\t<artifactId>h2</artifactId>\n\t\t\t<version>1.4.199</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.hibernate</groupId>\n\t\t\t<artifactId>hibernate-core</artifactId>\n\t\t\t<version>5.6.9.Final</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.hibernate</groupId>\n\t\t\t<artifactId>hibernate-c3p0</artifactId>\n\t\t\t<version>5.6.9.Final</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.aliyun.odps</groupId>\n\t\t\t<artifactId>odps-sdk-udf</artifactId>\n\t\t\t<version>0.43.3-public</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>javax.validation</groupId>\n\t\t\t\t\t<artifactId>validation-api</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.calcite</groupId>\n\t\t\t<artifactId>calcite-core</artifactId>\n\t\t\t<version>1.26.0</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<exclusions>\n\t\t\t\t<exclusion>\n\t\t\t\t\t<groupId>com.google.guava</groupId>\n\t\t\t\t\t<artifactId>guava</artifactId>\n\t\t\t\t</exclusion>\n\t\t\t</exclusions>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.google.guava</groupId>\n\t\t\t<artifactId>guava</artifactId>\n\t\t\t<version>30.1-jre</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba</groupId>\n\t\t\t<artifactId>dubbo</artifactId>\n\t\t\t<version>2.5.3</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.curator</groupId>\n\t\t\t<artifactId>curator-recipes</artifactId>\n\t\t\t<version>4.2.0</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>com.alibaba.fastjson2</groupId>\n\t\t\t<artifactId>fastjson2</artifactId>\n\t\t\t<version>2.0.29</version>\n\t\t\t<scope>provided</scope>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>ru.yandex.clickhouse</groupId>\n\t\t\t<artifactId>clickhouse-jdbc</artifactId>\n\t\t\t<version>0.2.4</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\n\t\t<!--\n\t\t\ttest dependences\n\t\t-->\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework</groupId>\n\t\t\t<artifactId>spring-test</artifactId>\n\t\t\t<version>${spring.version}</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.aliyun.odps</groupId>\n\t\t\t<artifactId>odps-jdbc</artifactId>\n\t\t\t<version>3.4.2</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.junit.jupiter</groupId>\n\t\t\t<artifactId>junit-jupiter</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.junit.vintage</groupId>\n\t\t\t<artifactId>junit-vintage-engine</artifactId>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.hamcrest</groupId>\n\t\t\t<artifactId>hamcrest</artifactId>\n\t\t\t<version>2.2</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.derby</groupId>\n\t\t\t<artifactId>derby</artifactId>\n\t\t\t<version>10.12.1.1</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>commons-dbcp</groupId>\n\t\t\t<artifactId>commons-dbcp</artifactId>\n\t\t\t<version>1.4</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.apache.commons</groupId>\n\t\t\t<artifactId>commons-dbcp2</artifactId>\n\t\t\t<version>2.5.0</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.jolbox</groupId>\n\t\t\t<artifactId>bonecp</artifactId>\n\t\t\t<version>0.8.0.RELEASE</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.jolbox</groupId>\n\t\t\t<artifactId>bonecp-spring</artifactId>\n\t\t\t<version>0.8.0.RELEASE</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>c3p0</groupId>\n\t\t\t<artifactId>c3p0</artifactId>\n\t\t\t<version>0.9.1.2</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.tomcat</groupId>\n\t\t\t<artifactId>tomcat-jdbc</artifactId>\n\t\t\t<version>8.0.32</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.nutz</groupId>\n\t\t\t<artifactId>nutz</artifactId>\n\t\t\t<version>1.r.55</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.javasimon</groupId>\n\t\t\t<artifactId>javasimon-spring</artifactId>\n\t\t\t<version>4.1.1</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.javasimon</groupId>\n\t\t\t<artifactId>javasimon-jdbc41</artifactId>\n\t\t\t<version>4.1.1</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.javasimon</groupId>\n\t\t\t<artifactId>javasimon-javaee</artifactId>\n\t\t\t<version>4.1.1</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.calcite</groupId>\n\t\t\t<artifactId>calcite-druid</artifactId>\n\t\t\t<version>1.26.0</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>commons-dbutils</groupId>\n\t\t\t<artifactId>commons-dbutils</artifactId>\n\t\t\t<version>1.6</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.antlr</groupId>\n\t\t\t<artifactId>antlr4</artifactId>\n\t\t\t<version>4.11.1</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.openjdk.jmh</groupId>\n\t\t\t<artifactId>jmh-core</artifactId>\n\t\t\t<version>${jmh.version}</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.openjdk.jmh</groupId>\n\t\t\t<artifactId>jmh-generator-annprocess</artifactId>\n\t\t\t<version>${jmh.version}</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.mariadb.jdbc</groupId>\n\t\t\t<artifactId>mariadb-java-client</artifactId>\n\t\t\t<version>2.4.0</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.apache.curator</groupId>\n\t\t\t<artifactId>curator-test</artifactId>\n\t\t\t<version>4.2.0</version>\n\t\t\t<scope>test</scope>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.github.housepower</groupId>\n\t\t\t<artifactId>clickhouse-native-jdbc-shaded</artifactId>\n\t\t\t<version>2.5.6</version>\n\t\t\t<scope>provided</scope>\n\t\t</dependency>\n\t</dependencies>\n</project>\n"
  },
  {
    "path": "core/src/main/java/META-INF/MANIFEST.MF",
    "content": "Manifest-Version: 1.0\nClass-Path: \n\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/Constants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\npublic interface Constants {\n    public static final String DRUID_STAT_SQL_MAX_SIZE = \"druid.stat.sql.MaxSize\";\n\n    public static final String DRUID_TIME_BETWEEN_LOG_STATS_MILLIS = \"druid.timeBetweenLogStatsMillis\";\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/DbType.java",
    "content": "package com.alibaba.druid;\n\nimport com.alibaba.druid.util.FnvHash;\n\npublic enum DbType {\n    other(1 << 0),\n    jtds(1 << 1),\n    hsql(1 << 2),\n    db2(1 << 3),\n    postgresql(1 << 4),\n\n    sqlserver(1 << 5),\n    oracle(1 << 6),\n    mysql(1 << 7),\n    mariadb(1 << 8),\n    derby(1 << 9),\n\n    hive(1 << 10),\n    h2(1 << 11),\n    dm(1 << 12), // dm.jdbc.driver.DmDriver\n    kingbase(1 << 13),\n    gbase(1 << 14),\n\n    oceanbase(1 << 15),\n    informix(1 << 16),\n    odps(1 << 17),\n    teradata(1 << 18),\n    phoenix(1 << 19),\n\n    edb(1 << 20),\n    kylin(1 << 21), // org.apache.kylin.jdbc.Driver\n    sqlite(1 << 22),\n    ads(1 << 23),\n    presto(1 << 24),\n\n    elastic_search(1 << 25), // com.alibaba.xdriver.elastic.jdbc.ElasticDriver\n    hbase(1 << 26),\n    drds(1 << 27),\n\n    clickhouse(1 << 28),\n    blink(1 << 29),\n\n    @Deprecated\n    antspark(1 << 30),\n\n    spark(1 << 30),\n    oceanbase_oracle(1 << 31),\n    /**\n     * Alibaba Cloud PolarDB-Oracle 1.0\n     */\n    polardb(1L << 32),\n\n    ali_oracle(1L << 33),\n    mock(1L << 34),\n    sybase(1L << 35),\n    highgo(1L << 36),\n    /**\n     * 非常成熟的开源mpp数据库\n     */\n    greenplum(1L << 37),\n    /**\n     * 华为的mpp数据库\n     */\n    gaussdb(1L << 38),\n\n    trino(1L << 39),\n\n    oscar(1L << 40),\n\n    tidb(1L << 41),\n\n    tydb(1L << 42),\n\n    starrocks(1L << 43),\n\n    goldendb(1L << 44),\n\n    snowflake(1L << 45),\n\n    redshift(1L << 46),\n\n    hologres(1L << 47),\n\n    bigquery(1L << 48),\n\n    impala(1L << 49),\n\n    doris(1L << 50),\n\n    lealone(1L << 51),\n\n    athena(1L << 52),\n\n    polardbx(1L << 53),\n    supersql(1L << 54),\n    databricks(1L << 55),\n    adb_mysql(1L << 56),\n    /**\n     * Alibaba Cloud PolarDB-Oracle 2.0\n     */\n    polardb2(1L << 57),\n    synapse(1L << 58),\n    duckdb(1L << 59),\n\n    ingres(0),\n    cloudscape(0),\n    timesten(0),\n    as400(0),\n    sapdb(0),\n    kdb(0),\n    log4jdbc(0),\n    xugu(0),\n    firebirdsql(0),\n    JSQLConnect(0),\n    JTurbo(0),\n    interbase(0),\n    pointbase(0),\n    edbc(0),\n    mimer(0),\n    taosdata(0),\n    sundb(0);\n\n    public final long mask;\n    public final long hashCode64;\n\n    private DbType(long mask) {\n        this.mask = mask;\n        this.hashCode64 = FnvHash.hashCode64(name());\n    }\n\n    public static long of(DbType... types) {\n        long value = 0;\n\n        for (DbType type : types) {\n            value |= type.mask;\n        }\n\n        return value;\n    }\n\n    public static DbType of(String name) {\n        if (name == null || name.isEmpty()) {\n            return null;\n        }\n\n        if (\"aliyun_ads\".equalsIgnoreCase(name)) {\n            return ads;\n        }\n\n        if (\"maxcompute\".equalsIgnoreCase(name)) {\n            return odps;\n        }\n\n        try {\n            return valueOf(name);\n        } catch (Exception e) {\n            return null;\n        }\n    }\n\n    public static boolean isPostgreSQLDbStyle(DbType dbType) {\n        return dbType == DbType.postgresql || dbType == DbType.edb || dbType == DbType.greenplum || dbType == DbType.hologres;\n    }\n    public final boolean equals(String other) {\n        return this == of(other);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/DruidRuntimeException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\npublic class DruidRuntimeException extends RuntimeException {\n    private static final long serialVersionUID = 1L;\n\n    public DruidRuntimeException() {\n        super();\n    }\n\n    public DruidRuntimeException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public DruidRuntimeException(String message) {\n        super(message);\n    }\n\n    public DruidRuntimeException(Throwable cause) {\n        super(cause);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/FastsqlColumnAmbiguousException.java",
    "content": "package com.alibaba.druid;\n\npublic class FastsqlColumnAmbiguousException extends FastsqlException {\n    public FastsqlColumnAmbiguousException() {\n    }\n\n    public FastsqlColumnAmbiguousException(String msg) {\n        super(msg);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/FastsqlException.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\npublic class FastsqlException extends RuntimeException {\n    private static final long serialVersionUID = 1L;\n\n    public FastsqlException() {\n        super();\n    }\n\n    public FastsqlException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n    public FastsqlException(String message) {\n        super(message);\n    }\n\n    public FastsqlException(Throwable cause) {\n        super(cause);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/TransactionTimeoutException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport java.sql.SQLException;\n\npublic class TransactionTimeoutException extends SQLException {\n    private static final long serialVersionUID = 1L;\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/VERSION.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\npublic final class VERSION {\n    public static final int MajorVersion = 1;\n    public static final int MinorVersion = 2;\n    public static final int RevisionVersion = 29;\n\n    public static String getVersionNumber() {\n        return VERSION.MajorVersion + \".\" + VERSION.MinorVersion + \".\" + VERSION.RevisionVersion;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/AutoLoad.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * @author sandzhang [sandzhagntoo@gmail.com]\n */\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface AutoLoad {\n    boolean value() default true;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/Filter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.*;\n\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface Filter extends Wrapper {\n    void init(DataSourceProxy dataSource);\n\n    void destroy();\n\n    void configFromProperties(Properties properties);\n\n    boolean isWrapperFor(java.lang.Class<?> iface);\n\n    <T> T unwrap(java.lang.Class<T> iface);\n\n    ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException;\n\n    StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException;\n\n    CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException;\n\n    String connection_nativeSQL(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException;\n\n    void connection_setAutoCommit(FilterChain chain, ConnectionProxy connection, boolean autoCommit)\n            throws SQLException;\n\n    boolean connection_getAutoCommit(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_commit(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_rollback(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_close(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    boolean connection_isClosed(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    DatabaseMetaData connection_getMetaData(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_setReadOnly(FilterChain chain, ConnectionProxy connection, boolean readOnly) throws SQLException;\n\n    boolean connection_isReadOnly(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_setCatalog(FilterChain chain, ConnectionProxy connection, String catalog) throws SQLException;\n\n    String connection_getCatalog(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_setTransactionIsolation(FilterChain chain, ConnectionProxy connection, int level)\n            throws SQLException;\n\n    int connection_getTransactionIsolation(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    SQLWarning connection_getWarnings(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_clearWarnings(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection, int resultSetType,\n                                              int resultSetConcurrency) throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql,\n                                                       int resultSetType, int resultSetConcurrency) throws SQLException;\n\n    CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                  int resultSetType, int resultSetConcurrency) throws SQLException;\n\n    java.util.Map<String, Class<?>> connection_getTypeMap(FilterChain chain, ConnectionProxy connection)\n            throws SQLException;\n\n    void connection_setTypeMap(FilterChain chain, ConnectionProxy connection, java.util.Map<String, Class<?>> map)\n            throws SQLException;\n\n    void connection_setHoldability(FilterChain chain, ConnectionProxy connection, int holdability) throws SQLException;\n\n    int connection_getHoldability(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    Savepoint connection_setSavepoint(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    Savepoint connection_setSavepoint(FilterChain chain, ConnectionProxy connection, String name) throws SQLException;\n\n    void connection_rollback(FilterChain chain, ConnectionProxy connection, Savepoint savepoint) throws SQLException;\n\n    void connection_releaseSavepoint(FilterChain chain, ConnectionProxy connection, Savepoint savepoint)\n            throws SQLException;\n\n    StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection, int resultSetType,\n                                              int resultSetConcurrency, int resultSetHoldability) throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql,\n                                                       int resultSetType, int resultSetConcurrency,\n                                                       int resultSetHoldability) throws SQLException;\n\n    CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                  int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n            throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql,\n                                                       int autoGeneratedKeys) throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql,\n                                                       int[] columnIndexes) throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql,\n                                                       String[] columnNames) throws SQLException;\n\n    Clob connection_createClob(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    Blob connection_createBlob(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    NClob connection_createNClob(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    SQLXML connection_createSQLXML(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    boolean connection_isValid(FilterChain chain, ConnectionProxy connection, int timeout) throws SQLException;\n\n    void connection_setClientInfo(FilterChain chain, ConnectionProxy connection, String name, String value)\n            throws SQLClientInfoException;\n\n    void connection_setClientInfo(FilterChain chain, ConnectionProxy connection, Properties properties)\n            throws SQLClientInfoException;\n\n    String connection_getClientInfo(FilterChain chain, ConnectionProxy connection, String name) throws SQLException;\n\n    Properties connection_getClientInfo(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    Array connection_createArrayOf(FilterChain chain, ConnectionProxy connection, String typeName, Object[] elements)\n            throws SQLException;\n\n    Struct connection_createStruct(FilterChain chain, ConnectionProxy connection, String typeName, Object[] attributes)\n            throws SQLException;\n\n    String connection_getSchema(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    void connection_setSchema(FilterChain chain, ConnectionProxy connection, String schema) throws SQLException;\n\n    void connection_abort(FilterChain chain, ConnectionProxy connection, Executor executor) throws SQLException;\n\n    void connection_setNetworkTimeout(FilterChain chain,\n                                      ConnectionProxy connection,\n                                      Executor executor,\n                                      int milliseconds) throws SQLException;\n\n    int connection_getNetworkTimeout(FilterChain chain, ConnectionProxy connection) throws SQLException;\n\n    // ///////////////\n    boolean resultSet_next(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_wasNull(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    String resultSet_getString(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    boolean resultSet_getBoolean(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    byte resultSet_getByte(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    short resultSet_getShort(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    int resultSet_getInt(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    long resultSet_getLong(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    float resultSet_getFloat(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    double resultSet_getDouble(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy resultSet, int columnIndex, int scale)\n            throws SQLException;\n\n    byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Date resultSet_getDate(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Time resultSet_getTime(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.io.InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException;\n\n    java.io.InputStream resultSet_getUnicodeStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException;\n\n    java.io.InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException;\n\n    String resultSet_getString(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    boolean resultSet_getBoolean(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    byte resultSet_getByte(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    short resultSet_getShort(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    int resultSet_getInt(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    long resultSet_getLong(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    float resultSet_getFloat(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    double resultSet_getDouble(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy resultSet, String columnLabel, int scale)\n            throws SQLException;\n\n    byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    java.io.InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    java.io.InputStream resultSet_getUnicodeStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    java.io.InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    SQLWarning resultSet_getWarnings(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_clearWarnings(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    String resultSet_getCursorName(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    ResultSetMetaData resultSet_getMetaData(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    Object resultSet_getObject(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    <T> T resultSet_getObject(FilterChain chain,\n                              ResultSetProxy resultSet,\n                              int columnIndex,\n                              Class<T> type) throws SQLException;\n\n    Object resultSet_getObject(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    <T> T resultSet_getObject(FilterChain chain,\n                              ResultSetProxy resultSet,\n                              String columnLabel,\n                              Class<T> type) throws SQLException;\n\n    int resultSet_findColumn(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.io.Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException;\n\n    java.io.Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    boolean resultSet_isBeforeFirst(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isAfterLast(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isFirst(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isLast(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_beforeFirst(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_afterLast(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_first(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_last(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    int resultSet_getRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_absolute(FilterChain chain, ResultSetProxy resultSet, int row) throws SQLException;\n\n    boolean resultSet_relative(FilterChain chain, ResultSetProxy resultSet, int rows) throws SQLException;\n\n    boolean resultSet_previous(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_setFetchDirection(FilterChain chain, ResultSetProxy resultSet, int direction) throws SQLException;\n\n    int resultSet_getFetchDirection(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_setFetchSize(FilterChain chain, ResultSetProxy resultSet, int rows) throws SQLException;\n\n    int resultSet_getFetchSize(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    int resultSet_getType(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    int resultSet_getConcurrency(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_rowUpdated(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_rowInserted(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_rowDeleted(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_updateNull(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    void resultSet_updateBoolean(FilterChain chain, ResultSetProxy resultSet, int columnIndex, boolean x)\n            throws SQLException;\n\n    void resultSet_updateByte(FilterChain chain, ResultSetProxy resultSet, int columnIndex, byte x) throws SQLException;\n\n    void resultSet_updateShort(FilterChain chain, ResultSetProxy resultSet, int columnIndex, short x)\n            throws SQLException;\n\n    void resultSet_updateInt(FilterChain chain, ResultSetProxy resultSet, int columnIndex, int x) throws SQLException;\n\n    void resultSet_updateLong(FilterChain chain, ResultSetProxy resultSet, int columnIndex, long x) throws SQLException;\n\n    void resultSet_updateFloat(FilterChain chain, ResultSetProxy resultSet, int columnIndex, float x)\n            throws SQLException;\n\n    void resultSet_updateDouble(FilterChain chain, ResultSetProxy resultSet, int columnIndex, double x)\n            throws SQLException;\n\n    void resultSet_updateBigDecimal(FilterChain chain, ResultSetProxy resultSet, int columnIndex, BigDecimal x)\n            throws SQLException;\n\n    void resultSet_updateString(FilterChain chain, ResultSetProxy resultSet, int columnIndex, String x)\n            throws SQLException;\n\n    void resultSet_updateBytes(FilterChain chain, ResultSetProxy resultSet, int columnIndex, byte[] x)\n            throws SQLException;\n\n    void resultSet_updateDate(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Date x)\n            throws SQLException;\n\n    void resultSet_updateTime(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Time x)\n            throws SQLException;\n\n    void resultSet_updateTimestamp(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Timestamp x)\n            throws SQLException;\n\n    void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                     java.io.InputStream x, int length) throws SQLException;\n\n    void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                      java.io.InputStream x, int length) throws SQLException;\n\n    void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                         java.io.Reader x, int length) throws SQLException;\n\n    void resultSet_updateObject(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Object x,\n                                int scaleOrLength) throws SQLException;\n\n    void resultSet_updateObject(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Object x)\n            throws SQLException;\n\n    void resultSet_updateNull(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateBoolean(FilterChain chain, ResultSetProxy resultSet, String columnLabel, boolean x)\n            throws SQLException;\n\n    void resultSet_updateByte(FilterChain chain, ResultSetProxy resultSet, String columnLabel, byte x)\n            throws SQLException;\n\n    void resultSet_updateShort(FilterChain chain, ResultSetProxy resultSet, String columnLabel, short x)\n            throws SQLException;\n\n    void resultSet_updateInt(FilterChain chain, ResultSetProxy resultSet, String columnLabel, int x)\n            throws SQLException;\n\n    void resultSet_updateLong(FilterChain chain, ResultSetProxy resultSet, String columnLabel, long x)\n            throws SQLException;\n\n    void resultSet_updateFloat(FilterChain chain, ResultSetProxy resultSet, String columnLabel, float x)\n            throws SQLException;\n\n    void resultSet_updateDouble(FilterChain chain, ResultSetProxy resultSet, String columnLabel, double x)\n            throws SQLException;\n\n    void resultSet_updateBigDecimal(FilterChain chain, ResultSetProxy resultSet, String columnLabel, BigDecimal x)\n            throws SQLException;\n\n    void resultSet_updateString(FilterChain chain, ResultSetProxy resultSet, String columnLabel, String x)\n            throws SQLException;\n\n    void resultSet_updateBytes(FilterChain chain, ResultSetProxy resultSet, String columnLabel, byte[] x)\n            throws SQLException;\n\n    void resultSet_updateDate(FilterChain chain, ResultSetProxy resultSet, String columnLabel, java.sql.Date x)\n            throws SQLException;\n\n    void resultSet_updateTime(FilterChain chain, ResultSetProxy resultSet, String columnLabel, java.sql.Time x)\n            throws SQLException;\n\n    void resultSet_updateTimestamp(FilterChain chain,\n                                   ResultSetProxy resultSet,\n                                   String columnLabel,\n                                   java.sql.Timestamp x)\n            throws SQLException;\n\n    void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                     java.io.InputStream x, int length) throws SQLException;\n\n    void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                      java.io.InputStream x, int length) throws SQLException;\n\n    void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                         java.io.Reader reader, int length) throws SQLException;\n\n    void resultSet_updateObject(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Object x,\n                                int scaleOrLength) throws SQLException;\n\n    void resultSet_updateObject(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Object x)\n            throws SQLException;\n\n    void resultSet_insertRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_updateRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_deleteRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_refreshRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_cancelRowUpdates(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_moveToInsertRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_moveToCurrentRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    Statement resultSet_getStatement(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    Object resultSet_getObject(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                               java.util.Map<String, Class<?>> map) throws SQLException;\n\n    Ref resultSet_getRef(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Blob resultSet_getBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Array resultSet_getArray(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Object resultSet_getObject(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                               java.util.Map<String, Class<?>> map) throws SQLException;\n\n    Ref resultSet_getRef(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    Blob resultSet_getBlob(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    Array resultSet_getArray(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Calendar cal)\n            throws SQLException;\n\n    java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Calendar cal)\n            throws SQLException;\n\n    java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Calendar cal)\n            throws SQLException;\n\n    java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Calendar cal)\n            throws SQLException;\n\n    java.sql.Timestamp resultSet_getTimestamp(FilterChain chain,\n                                              ResultSetProxy resultSet,\n                                              int columnIndex,\n                                              Calendar cal)\n            throws SQLException;\n\n    java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                              Calendar cal) throws SQLException;\n\n    java.net.URL resultSet_getURL(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.net.URL resultSet_getURL(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateRef(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Ref x)\n            throws SQLException;\n\n    void resultSet_updateRef(FilterChain chain, ResultSetProxy resultSet, String columnLabel, java.sql.Ref x)\n            throws SQLException;\n\n    void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Blob x)\n            throws SQLException;\n\n    void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, java.sql.Blob x)\n            throws SQLException;\n\n    void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Clob x)\n            throws SQLException;\n\n    void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, java.sql.Clob x)\n            throws SQLException;\n\n    void resultSet_updateArray(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Array x)\n            throws SQLException;\n\n    void resultSet_updateArray(FilterChain chain, ResultSetProxy resultSet, String columnLabel, java.sql.Array x)\n            throws SQLException;\n\n    RowId resultSet_getRowId(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    RowId resultSet_getRowId(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateRowId(FilterChain chain, ResultSetProxy resultSet, int columnIndex, RowId x)\n            throws SQLException;\n\n    void resultSet_updateRowId(FilterChain chain, ResultSetProxy resultSet, String columnLabel, RowId x)\n            throws SQLException;\n\n    int resultSet_getHoldability(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isClosed(FilterChain chain, ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_updateNString(FilterChain chain, ResultSetProxy resultSet, int columnIndex, String nString)\n            throws SQLException;\n\n    void resultSet_updateNString(FilterChain chain, ResultSetProxy resultSet, String columnLabel, String nString)\n            throws SQLException;\n\n    void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, NClob nClob)\n            throws SQLException;\n\n    void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, NClob nClob)\n            throws SQLException;\n\n    NClob resultSet_getNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    NClob resultSet_getNClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    SQLXML resultSet_getSQLXML(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    SQLXML resultSet_getSQLXML(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateSQLXML(FilterChain chain, ResultSetProxy resultSet, int columnIndex, SQLXML xmlObject)\n            throws SQLException;\n\n    void resultSet_updateSQLXML(FilterChain chain, ResultSetProxy resultSet, String columnLabel, SQLXML xmlObject)\n            throws SQLException;\n\n    String resultSet_getNString(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    String resultSet_getNString(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.io.Reader resultSet_getNCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException;\n\n    java.io.Reader resultSet_getNCharacterStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException;\n\n    void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                          java.io.Reader x, long length) throws SQLException;\n\n    void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                          java.io.Reader reader, long length) throws SQLException;\n\n    void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                     java.io.InputStream x, long length) throws SQLException;\n\n    void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                      java.io.InputStream x, long length) throws SQLException;\n\n    void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                         java.io.Reader x, long length) throws SQLException;\n\n    void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                     java.io.InputStream x, long length) throws SQLException;\n\n    void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                      java.io.InputStream x, long length) throws SQLException;\n\n    void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                         Reader reader, long length) throws SQLException;\n\n    void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, InputStream inputStream,\n                              long length) throws SQLException;\n\n    void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, InputStream inputStream,\n                              long length) throws SQLException;\n\n    void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader, long length)\n            throws SQLException;\n\n    void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Reader reader,\n                              long length) throws SQLException;\n\n    void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader, long length)\n            throws SQLException;\n\n    void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Reader reader,\n                               long length) throws SQLException;\n\n    void resultSet_updateNCharacterStream(FilterChain chain,\n                                          ResultSetProxy resultSet,\n                                          int columnIndex,\n                                          java.io.Reader x)\n            throws SQLException;\n\n    void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                          java.io.Reader reader) throws SQLException;\n\n    void resultSet_updateAsciiStream(FilterChain chain,\n                                     ResultSetProxy resultSet,\n                                     int columnIndex,\n                                     java.io.InputStream x)\n            throws SQLException;\n\n    void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                      java.io.InputStream x) throws SQLException;\n\n    void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.io.Reader x)\n            throws SQLException;\n\n    void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                     java.io.InputStream x) throws SQLException;\n\n    void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                      java.io.InputStream x) throws SQLException;\n\n    void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, String columnLabel,\n                                         java.io.Reader reader) throws SQLException;\n\n    void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, InputStream inputStream)\n            throws SQLException;\n\n    void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, InputStream inputStream)\n            throws SQLException;\n\n    void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader)\n            throws SQLException;\n\n    void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Reader reader)\n            throws SQLException;\n\n    void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader)\n            throws SQLException;\n\n    void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel, Reader reader)\n            throws SQLException;\n\n    // / statement\n\n    ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql) throws SQLException;\n\n    int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException;\n\n    void statement_close(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    int statement_getMaxFieldSize(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_setMaxFieldSize(FilterChain chain, StatementProxy statement, int max) throws SQLException;\n\n    int statement_getMaxRows(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_setMaxRows(FilterChain chain, StatementProxy statement, int max) throws SQLException;\n\n    void statement_setEscapeProcessing(FilterChain chain, StatementProxy statement, boolean enable) throws SQLException;\n\n    int statement_getQueryTimeout(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_setQueryTimeout(FilterChain chain, StatementProxy statement, int seconds) throws SQLException;\n\n    void statement_cancel(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    SQLWarning statement_getWarnings(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_clearWarnings(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_setCursorName(FilterChain chain, StatementProxy statement, String name) throws SQLException;\n\n    boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException;\n\n    ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    int statement_getUpdateCount(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    boolean statement_getMoreResults(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_setFetchDirection(FilterChain chain, StatementProxy statement, int direction) throws SQLException;\n\n    int statement_getFetchDirection(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_setFetchSize(FilterChain chain, StatementProxy statement, int rows) throws SQLException;\n\n    int statement_getFetchSize(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    int statement_getResultSetConcurrency(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    int statement_getResultSetType(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException;\n\n    void statement_clearBatch(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    int[] statement_executeBatch(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    Connection statement_getConnection(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    boolean statement_getMoreResults(FilterChain chain, StatementProxy statement, int current) throws SQLException;\n\n    ResultSetProxy statement_getGeneratedKeys(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException;\n\n    int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException;\n\n    int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException;\n\n    boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException;\n\n    boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException;\n\n    boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException;\n\n    int statement_getResultSetHoldability(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    boolean statement_isClosed(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    void statement_setPoolable(FilterChain chain, StatementProxy statement, boolean poolable) throws SQLException;\n\n    boolean statement_isPoolable(FilterChain chain, StatementProxy statement) throws SQLException;\n\n    // ///\n\n    ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException;\n\n    int preparedStatement_executeUpdate(FilterChain chain, PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setNull(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, int sqlType)\n            throws SQLException;\n\n    void preparedStatement_setBoolean(FilterChain chain,\n                                      PreparedStatementProxy statement,\n                                      int parameterIndex,\n                                      boolean x)\n            throws SQLException;\n\n    void preparedStatement_setByte(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, byte x)\n            throws SQLException;\n\n    void preparedStatement_setShort(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, short x)\n            throws SQLException;\n\n    void preparedStatement_setInt(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, int x)\n            throws SQLException;\n\n    void preparedStatement_setLong(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, long x)\n            throws SQLException;\n\n    void preparedStatement_setFloat(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, float x)\n            throws SQLException;\n\n    void preparedStatement_setDouble(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, double x)\n            throws SQLException;\n\n    void preparedStatement_setBigDecimal(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                         BigDecimal x) throws SQLException;\n\n    void preparedStatement_setString(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, String x)\n            throws SQLException;\n\n    void preparedStatement_setBytes(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, byte[] x)\n            throws SQLException;\n\n    void preparedStatement_setDate(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   java.sql.Date x) throws SQLException;\n\n    void preparedStatement_setTime(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   java.sql.Time x) throws SQLException;\n\n    void preparedStatement_setTimestamp(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                        java.sql.Timestamp x) throws SQLException;\n\n    void preparedStatement_setAsciiStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          java.io.InputStream x, int length) throws SQLException;\n\n    void preparedStatement_setUnicodeStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            java.io.InputStream x, int length) throws SQLException;\n\n    void preparedStatement_setBinaryStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           java.io.InputStream x, int length) throws SQLException;\n\n    void preparedStatement_clearParameters(FilterChain chain, PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Object x,\n                                     int targetSqlType) throws SQLException;\n\n    void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Object x)\n            throws SQLException;\n\n    boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_addBatch(FilterChain chain, PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                              java.io.Reader reader, int length) throws SQLException;\n\n    void preparedStatement_setRef(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Ref x)\n            throws SQLException;\n\n    void preparedStatement_setBlob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Blob x)\n            throws SQLException;\n\n    void preparedStatement_setClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Clob x)\n            throws SQLException;\n\n    void preparedStatement_setArray(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Array x)\n            throws SQLException;\n\n    ResultSetMetaData preparedStatement_getMetaData(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException;\n\n    void preparedStatement_setDate(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   java.sql.Date x, Calendar cal) throws SQLException;\n\n    void preparedStatement_setTime(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   java.sql.Time x, Calendar cal) throws SQLException;\n\n    void preparedStatement_setTimestamp(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                        java.sql.Timestamp x, Calendar cal) throws SQLException;\n\n    void preparedStatement_setNull(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   int sqlType, String typeName) throws SQLException;\n\n    void preparedStatement_setURL(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                  java.net.URL x) throws SQLException;\n\n    ParameterMetaData preparedStatement_getParameterMetaData(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException;\n\n    void preparedStatement_setRowId(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, RowId x)\n            throws SQLException;\n\n    void preparedStatement_setNString(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                      String value) throws SQLException;\n\n    void preparedStatement_setNCharacterStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                               Reader value, long length) throws SQLException;\n\n    void preparedStatement_setNClob(FilterChain chain,\n                                    PreparedStatementProxy statement,\n                                    int parameterIndex,\n                                    NClob value)\n            throws SQLException;\n\n    void preparedStatement_setClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   Reader reader, long length) throws SQLException;\n\n    void preparedStatement_setBlob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   InputStream inputStream, long length) throws SQLException;\n\n    void preparedStatement_setNClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                    Reader reader, long length) throws SQLException;\n\n    void preparedStatement_setSQLXML(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                     SQLXML xmlObject) throws SQLException;\n\n    void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Object x,\n                                     int targetSqlType, int scaleOrLength) throws SQLException;\n\n    void preparedStatement_setAsciiStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          java.io.InputStream x, long length) throws SQLException;\n\n    void preparedStatement_setBinaryStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           java.io.InputStream x, long length) throws SQLException;\n\n    void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                              java.io.Reader reader, long length) throws SQLException;\n\n    void preparedStatement_setAsciiStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          java.io.InputStream x) throws SQLException;\n\n    void preparedStatement_setBinaryStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           java.io.InputStream x) throws SQLException;\n\n    void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                              java.io.Reader reader) throws SQLException;\n\n    void preparedStatement_setNCharacterStream(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                               Reader value) throws SQLException;\n\n    void preparedStatement_setClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   Reader reader) throws SQLException;\n\n    void preparedStatement_setBlob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                   InputStream inputStream) throws SQLException;\n\n    void preparedStatement_setNClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                    Reader reader) throws SQLException;\n\n    // ///////////////////////////////////\n\n    void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                int parameterIndex, int sqlType) throws SQLException;\n\n    void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                int parameterIndex, int sqlType, int scale) throws SQLException;\n\n    boolean callableStatement_wasNull(FilterChain chain, CallableStatementProxy statement) throws SQLException;\n\n    String callableStatement_getString(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    boolean callableStatement_getBoolean(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    byte callableStatement_getByte(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    short callableStatement_getShort(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    int callableStatement_getInt(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    long callableStatement_getLong(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    float callableStatement_getFloat(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    double callableStatement_getDouble(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    BigDecimal callableStatement_getBigDecimal(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                               int scale) throws SQLException;\n\n    byte[] callableStatement_getBytes(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                      int parameterIndex) throws SQLException;\n\n    Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    BigDecimal callableStatement_getBigDecimal(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                       java.util.Map<String, Class<?>> map) throws SQLException;\n\n    Ref callableStatement_getRef(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    Array callableStatement_getArray(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                            Calendar cal) throws SQLException;\n\n    java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                            Calendar cal) throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                      int parameterIndex, Calendar cal) throws SQLException;\n\n    void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                int parameterIndex, int sqlType, String typeName) throws SQLException;\n\n    void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                String parameterName, int sqlType) throws SQLException;\n\n    void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                String parameterName, int sqlType, int scale) throws SQLException;\n\n    void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                String parameterName, int sqlType, String typeName) throws SQLException;\n\n    java.net.URL callableStatement_getURL(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    void callableStatement_setURL(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                  java.net.URL val) throws SQLException;\n\n    void callableStatement_setNull(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   int sqlType) throws SQLException;\n\n    void callableStatement_setBoolean(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                      boolean x) throws SQLException;\n\n    void callableStatement_setByte(FilterChain chain, CallableStatementProxy statement, String parameterName, byte x)\n            throws SQLException;\n\n    void callableStatement_setShort(FilterChain chain, CallableStatementProxy statement, String parameterName, short x)\n            throws SQLException;\n\n    void callableStatement_setInt(FilterChain chain, CallableStatementProxy statement, String parameterName, int x)\n            throws SQLException;\n\n    void callableStatement_setLong(FilterChain chain, CallableStatementProxy statement, String parameterName, long x)\n            throws SQLException;\n\n    void callableStatement_setFloat(FilterChain chain, CallableStatementProxy statement, String parameterName, float x)\n            throws SQLException;\n\n    void callableStatement_setDouble(FilterChain chain,\n                                     CallableStatementProxy statement,\n                                     String parameterName,\n                                     double x)\n            throws SQLException;\n\n    void callableStatement_setBigDecimal(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                         BigDecimal x) throws SQLException;\n\n    void callableStatement_setString(FilterChain chain,\n                                     CallableStatementProxy statement,\n                                     String parameterName,\n                                     String x)\n            throws SQLException;\n\n    void callableStatement_setBytes(FilterChain chain, CallableStatementProxy statement, String parameterName, byte[] x)\n            throws SQLException;\n\n    void callableStatement_setDate(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   java.sql.Date x) throws SQLException;\n\n    void callableStatement_setTime(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   java.sql.Time x) throws SQLException;\n\n    void callableStatement_setTimestamp(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                        java.sql.Timestamp x) throws SQLException;\n\n    void callableStatement_setAsciiStream(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          java.io.InputStream x, int length) throws SQLException;\n\n    void callableStatement_setBinaryStream(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           java.io.InputStream x, int length) throws SQLException;\n\n    void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                     Object x, int targetSqlType, int scale) throws SQLException;\n\n    void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                     Object x, int targetSqlType) throws SQLException;\n\n    void callableStatement_setObject(FilterChain chain,\n                                     CallableStatementProxy statement,\n                                     String parameterName,\n                                     Object x)\n            throws SQLException;\n\n    void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                              String parameterName, java.io.Reader reader, int length)\n            throws SQLException;\n\n    void callableStatement_setDate(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   java.sql.Date x, Calendar cal) throws SQLException;\n\n    void callableStatement_setTime(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   java.sql.Time x, Calendar cal) throws SQLException;\n\n    void callableStatement_setTimestamp(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                        java.sql.Timestamp x, Calendar cal) throws SQLException;\n\n    void callableStatement_setNull(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   int sqlType, String typeName) throws SQLException;\n\n    String callableStatement_getString(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    boolean callableStatement_getBoolean(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    byte callableStatement_getByte(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    short callableStatement_getShort(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    int callableStatement_getInt(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    long callableStatement_getLong(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    float callableStatement_getFloat(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    double callableStatement_getDouble(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    byte[] callableStatement_getBytes(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                      String parameterName) throws SQLException;\n\n    Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    BigDecimal callableStatement_getBigDecimal(FilterChain chain,\n                                               CallableStatementProxy statement,\n                                               String parameterName)\n            throws SQLException;\n\n    Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                       java.util.Map<String, Class<?>> map) throws SQLException;\n\n    Ref callableStatement_getRef(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    Array callableStatement_getArray(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Calendar cal) throws SQLException;\n\n    java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Calendar cal) throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                      String parameterName, Calendar cal) throws SQLException;\n\n    java.net.URL callableStatement_getURL(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    RowId callableStatement_getRowId(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    RowId callableStatement_getRowId(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    void callableStatement_setRowId(FilterChain chain, CallableStatementProxy statement, String parameterName, RowId x)\n            throws SQLException;\n\n    void callableStatement_setNString(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                      String value) throws SQLException;\n\n    void callableStatement_setNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                               String parameterName, Reader value, long length) throws SQLException;\n\n    void callableStatement_setNClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                    NClob value) throws SQLException;\n\n    void callableStatement_setClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   Reader reader, long length) throws SQLException;\n\n    void callableStatement_setBlob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   InputStream inputStream, long length) throws SQLException;\n\n    void callableStatement_setNClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                    Reader reader, long length) throws SQLException;\n\n    NClob callableStatement_getNClob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    NClob callableStatement_getNClob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    void callableStatement_setSQLXML(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                     SQLXML xmlObject) throws SQLException;\n\n    SQLXML callableStatement_getSQLXML(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    SQLXML callableStatement_getSQLXML(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    String callableStatement_getNString(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    String callableStatement_getNString(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    java.io.Reader callableStatement_getNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                         int parameterIndex) throws SQLException;\n\n    java.io.Reader callableStatement_getNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                         String parameterName) throws SQLException;\n\n    java.io.Reader callableStatement_getCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                        int parameterIndex) throws SQLException;\n\n    java.io.Reader callableStatement_getCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                        String parameterName) throws SQLException;\n\n    void callableStatement_setBlob(FilterChain chain, CallableStatementProxy statement, String parameterName, Blob x)\n            throws SQLException;\n\n    void callableStatement_setClob(FilterChain chain, CallableStatementProxy statement, String parameterName, Clob x)\n            throws SQLException;\n\n    void callableStatement_setAsciiStream(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          java.io.InputStream x, long length) throws SQLException;\n\n    void callableStatement_setBinaryStream(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           java.io.InputStream x, long length) throws SQLException;\n\n    void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                              String parameterName, java.io.Reader reader, long length)\n            throws SQLException;\n\n    void callableStatement_setAsciiStream(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          java.io.InputStream x) throws SQLException;\n\n    void callableStatement_setBinaryStream(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           java.io.InputStream x) throws SQLException;\n\n    void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                              String parameterName, java.io.Reader reader) throws SQLException;\n\n    void callableStatement_setNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                               String parameterName, Reader value) throws SQLException;\n\n    void callableStatement_setClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   Reader reader) throws SQLException;\n\n    void callableStatement_setBlob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                   InputStream inputStream) throws SQLException;\n\n    void callableStatement_setNClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                    Reader reader) throws SQLException;\n\n    <T> T unwrap(FilterChain chain, Wrapper wrapper, java.lang.Class<T> iface) throws java.sql.SQLException;\n\n    boolean isWrapperFor(FilterChain chain, Wrapper wrapper, java.lang.Class<?> iface) throws java.sql.SQLException;\n\n    void clob_free(FilterChain chain, ClobProxy wrapper) throws SQLException;\n\n    InputStream clob_getAsciiStream(FilterChain chain, ClobProxy wrapper) throws SQLException;\n\n    Reader clob_getCharacterStream(FilterChain chain, ClobProxy wrapper) throws SQLException;\n\n    Reader clob_getCharacterStream(FilterChain chain, ClobProxy wrapper, long pos, long length) throws SQLException;\n\n    String clob_getSubString(FilterChain chain, ClobProxy wrapper, long pos, int length) throws SQLException;\n\n    long clob_length(FilterChain chain, ClobProxy wrapper) throws SQLException;\n\n    long clob_position(FilterChain chain, ClobProxy wrapper, String searchstr, long start) throws SQLException;\n\n    long clob_position(FilterChain chain, ClobProxy wrapper, Clob searchstr, long start) throws SQLException;\n\n    OutputStream clob_setAsciiStream(FilterChain chain, ClobProxy wrapper, long pos) throws SQLException;\n\n    Writer clob_setCharacterStream(FilterChain chain, ClobProxy wrapper, long pos) throws SQLException;\n\n    int clob_setString(FilterChain chain, ClobProxy wrapper, long pos, String str) throws SQLException;\n\n    int clob_setString(FilterChain chain, ClobProxy wrapper, long pos, String str, int offset, int len)\n            throws SQLException;\n\n    void clob_truncate(FilterChain chain, ClobProxy wrapper, long len) throws SQLException;\n\n    void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection connection) throws SQLException;\n\n    DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource, long maxWaitMillis)\n            throws SQLException;\n\n    // /////////////////\n    int resultSetMetaData_getColumnCount(FilterChain chain, ResultSetMetaDataProxy metaData) throws SQLException;\n\n    boolean resultSetMetaData_isAutoIncrement(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    boolean resultSetMetaData_isCaseSensitive(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    boolean resultSetMetaData_isSearchable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    boolean resultSetMetaData_isCurrency(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    int resultSetMetaData_isNullable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    boolean resultSetMetaData_isSigned(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    int resultSetMetaData_getColumnDisplaySize(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    String resultSetMetaData_getColumnLabel(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    String resultSetMetaData_getColumnName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    String resultSetMetaData_getSchemaName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    int resultSetMetaData_getPrecision(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    int resultSetMetaData_getScale(FilterChain chain, ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getTableName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    String resultSetMetaData_getCatalogName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    int resultSetMetaData_getColumnType(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    String resultSetMetaData_getColumnTypeName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    boolean resultSetMetaData_isReadOnly(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    boolean resultSetMetaData_isWritable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    boolean resultSetMetaData_isDefinitelyWritable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n    String resultSetMetaData_getColumnClassName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException;\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/FilterAdapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.*;\n\nimport javax.management.NotificationBroadcasterSupport;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\n/**\n * 提供JdbcFilter的基本实现，使得实现一个JdbcFilter更容易。\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic abstract class FilterAdapter extends NotificationBroadcasterSupport implements Filter {\n    @Override\n    public void init(DataSourceProxy dataSource) {\n    }\n\n    @Override\n    public void destroy() {\n    }\n\n    public void configFromProperties(Properties properties) {\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) {\n        return iface == this.getClass();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) {\n        if (iface == this.getClass()) {\n            return (T) this;\n        }\n        return null;\n    }\n\n    @Override\n    public Array callableStatement_getArray(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getArray(statement, parameterIndex);\n    }\n\n    @Override\n    public Array callableStatement_getArray(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getArray(statement, parameterName);\n    }\n\n    @Override\n    public BigDecimal callableStatement_getBigDecimal(FilterChain chain, CallableStatementProxy statement,\n                                                      int parameterIndex) throws SQLException {\n        return chain.callableStatement_getBigDecimal(statement, parameterIndex);\n    }\n\n    @Override\n    public BigDecimal callableStatement_getBigDecimal(FilterChain chain, CallableStatementProxy statement,\n                                                      int parameterIndex, int scale) throws SQLException {\n        return chain.callableStatement_getBigDecimal(statement, parameterIndex, scale);\n    }\n\n    @Override\n    public BigDecimal callableStatement_getBigDecimal(FilterChain chain, CallableStatementProxy statement,\n                                                      String parameterName) throws SQLException {\n        return chain.callableStatement_getBigDecimal(statement, parameterName);\n    }\n\n    @Override\n    public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getBlob(statement, parameterIndex);\n    }\n\n    @Override\n    public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getBlob(statement, parameterName);\n    }\n\n    @Override\n    public boolean callableStatement_getBoolean(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getBoolean(statement, parameterIndex);\n    }\n\n    @Override\n    public boolean callableStatement_getBoolean(FilterChain chain, CallableStatementProxy statement,\n                                                String parameterName) throws SQLException {\n        return chain.callableStatement_getBoolean(statement, parameterName);\n    }\n\n    @Override\n    public byte callableStatement_getByte(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getByte(statement, parameterIndex);\n    }\n\n    @Override\n    public byte callableStatement_getByte(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getByte(statement, parameterName);\n    }\n\n    @Override\n    public byte[] callableStatement_getBytes(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getBytes(statement, parameterIndex);\n    }\n\n    @Override\n    public byte[] callableStatement_getBytes(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getBytes(statement, parameterName);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                               int parameterIndex) throws SQLException {\n        return chain.callableStatement_getCharacterStream(statement, parameterIndex);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                               String parameterName) throws SQLException {\n        return chain.callableStatement_getCharacterStream(statement, parameterName);\n    }\n\n    @Override\n    public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getClob(statement, parameterIndex);\n    }\n\n    @Override\n    public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getClob(statement, parameterName);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement,\n                                                   int parameterIndex) throws SQLException {\n        return chain.callableStatement_getDate(statement, parameterIndex);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement,\n                                                   int parameterIndex, Calendar cal) throws SQLException {\n        return chain.callableStatement_getDate(statement, parameterIndex, cal);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement,\n                                                   String parameterName) throws SQLException {\n        return chain.callableStatement_getDate(statement, parameterName);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(FilterChain chain, CallableStatementProxy statement,\n                                                   String parameterName, Calendar cal) throws SQLException {\n        return chain.callableStatement_getDate(statement, parameterName, cal);\n    }\n\n    @Override\n    public double callableStatement_getDouble(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getDouble(statement, parameterIndex);\n    }\n\n    @Override\n    public double callableStatement_getDouble(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getDouble(statement, parameterName);\n    }\n\n    @Override\n    public float callableStatement_getFloat(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getFloat(statement, parameterIndex);\n    }\n\n    @Override\n    public float callableStatement_getFloat(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getFloat(statement, parameterName);\n    }\n\n    @Override\n    public int callableStatement_getInt(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getInt(statement, parameterIndex);\n    }\n\n    @Override\n    public int callableStatement_getInt(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getInt(statement, parameterName);\n    }\n\n    @Override\n    public long callableStatement_getLong(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getLong(statement, parameterIndex);\n    }\n\n    @Override\n    public long callableStatement_getLong(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getLong(statement, parameterName);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                                int parameterIndex) throws SQLException {\n        return chain.callableStatement_getNCharacterStream(statement, parameterIndex);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                                String parameterName) throws SQLException {\n        return chain.callableStatement_getNCharacterStream(statement, parameterName);\n    }\n\n    @Override\n    public NClob callableStatement_getNClob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getNClob(statement, parameterIndex);\n    }\n\n    @Override\n    public NClob callableStatement_getNClob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getNClob(statement, parameterName);\n    }\n\n    @Override\n    public String callableStatement_getNString(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getNString(statement, parameterIndex);\n    }\n\n    @Override\n    public String callableStatement_getNString(FilterChain chain,\n                                               CallableStatementProxy statement,\n                                               String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getNString(statement, parameterName);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getObject(statement, parameterIndex);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n        return chain.callableStatement_getObject(statement, parameterIndex, map);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getObject(statement, parameterName);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement,\n                                              String parameterName, java.util.Map<String, Class<?>> map)\n            throws SQLException {\n        return chain.callableStatement_getObject(statement, parameterName, map);\n    }\n\n    @Override\n    public Ref callableStatement_getRef(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getRef(statement, parameterIndex);\n    }\n\n    @Override\n    public Ref callableStatement_getRef(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getRef(statement, parameterName);\n    }\n\n    @Override\n    public RowId callableStatement_getRowId(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getRowId(statement, parameterIndex);\n    }\n\n    @Override\n    public RowId callableStatement_getRowId(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getRowId(statement, parameterName);\n    }\n\n    @Override\n    public short callableStatement_getShort(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getShort(statement, parameterIndex);\n    }\n\n    @Override\n    public short callableStatement_getShort(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getShort(statement, parameterName);\n    }\n\n    @Override\n    public SQLXML callableStatement_getSQLXML(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getSQLXML(statement, parameterIndex);\n    }\n\n    @Override\n    public SQLXML callableStatement_getSQLXML(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getSQLXML(statement, parameterName);\n    }\n\n    @Override\n    public String callableStatement_getString(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getString(statement, parameterIndex);\n    }\n\n    @Override\n    public String callableStatement_getString(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        return chain.callableStatement_getString(statement, parameterName);\n    }\n\n    @Override\n    public java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement,\n                                                   int parameterIndex) throws SQLException {\n        return chain.callableStatement_getTime(statement, parameterIndex);\n    }\n\n    // //////////////////////////////\n\n    @Override\n    public java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement,\n                                                   int parameterIndex, Calendar cal) throws SQLException {\n        return chain.callableStatement_getTime(statement, parameterIndex, cal);\n    }\n\n    @Override\n    public java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement,\n                                                   String parameterName) throws SQLException {\n        return chain.callableStatement_getTime(statement, parameterName);\n    }\n\n    @Override\n    public java.sql.Time callableStatement_getTime(FilterChain chain, CallableStatementProxy statement,\n                                                   String parameterName, Calendar cal) throws SQLException {\n        return chain.callableStatement_getTime(statement, parameterName, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                             int parameterIndex) throws SQLException {\n        return chain.callableStatement_getTimestamp(statement, parameterIndex);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                             int parameterIndex, Calendar cal) throws SQLException {\n        return chain.callableStatement_getTimestamp(statement, parameterIndex, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                             String parameterName) throws SQLException {\n        return chain.callableStatement_getTimestamp(statement, parameterName);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                                             String parameterName, Calendar cal) throws SQLException {\n        return chain.callableStatement_getTimestamp(statement, parameterName, cal);\n    }\n\n    @Override\n    public java.net.URL callableStatement_getURL(FilterChain chain,\n                                                 CallableStatementProxy statement,\n                                                 int parameterIndex)\n            throws SQLException {\n        return chain.callableStatement_getURL(statement, parameterIndex);\n    }\n\n    @Override\n    public java.net.URL callableStatement_getURL(FilterChain chain, CallableStatementProxy statement,\n                                                 String parameterName) throws SQLException {\n        return chain.callableStatement_getURL(statement, parameterName);\n    }\n\n    // ///////////////\n    @Override\n    public void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                       int parameterIndex, int sqlType) throws SQLException {\n        chain.callableStatement_registerOutParameter(statement, parameterIndex, sqlType);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                       int parameterIndex, int sqlType, int scale) throws SQLException {\n        chain.callableStatement_registerOutParameter(statement, parameterIndex, sqlType, scale);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                       int parameterIndex, int sqlType, String typeName)\n            throws SQLException {\n        chain.callableStatement_registerOutParameter(statement, parameterIndex, sqlType, typeName);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                       String parameterName, int sqlType) throws SQLException {\n        chain.callableStatement_registerOutParameter(statement, parameterName, sqlType);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                       String parameterName, int sqlType, int scale)\n            throws SQLException {\n        chain.callableStatement_registerOutParameter(statement, parameterName, sqlType, scale);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(FilterChain chain, CallableStatementProxy statement,\n                                                       String parameterName, int sqlType, String typeName)\n            throws SQLException {\n        chain.callableStatement_registerOutParameter(statement, parameterName, sqlType, typeName);\n    }\n\n    @Override\n    public void callableStatement_setAsciiStream(FilterChain chain, CallableStatementProxy statement,\n                                                 String parameterName, java.io.InputStream x) throws SQLException {\n        chain.callableStatement_setAsciiStream(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setAsciiStream(FilterChain chain, CallableStatementProxy statement,\n                                                 String parameterName, java.io.InputStream x, int length)\n            throws SQLException {\n        chain.callableStatement_setAsciiStream(statement, parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setAsciiStream(FilterChain chain, CallableStatementProxy statement,\n                                                 String parameterName, java.io.InputStream x, long length)\n            throws SQLException {\n        chain.callableStatement_setAsciiStream(statement, parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setBigDecimal(FilterChain chain, CallableStatementProxy statement,\n                                                String parameterName, BigDecimal x) throws SQLException {\n        chain.callableStatement_setBigDecimal(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setBinaryStream(FilterChain chain, CallableStatementProxy statement,\n                                                  String parameterName, java.io.InputStream x) throws SQLException {\n        chain.callableStatement_setBinaryStream(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setBinaryStream(FilterChain chain, CallableStatementProxy statement,\n                                                  String parameterName, java.io.InputStream x, int length)\n            throws SQLException {\n        chain.callableStatement_setBinaryStream(statement, parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setBinaryStream(FilterChain chain, CallableStatementProxy statement,\n                                                  String parameterName, java.io.InputStream x, long length)\n            throws SQLException {\n        chain.callableStatement_setBinaryStream(statement, parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setBlob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          Blob x) throws SQLException {\n        chain.callableStatement_setBlob(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setBlob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          InputStream inputStream) throws SQLException {\n        chain.callableStatement_setBlob(statement, parameterName, inputStream);\n    }\n\n    @Override\n    public void callableStatement_setBlob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          InputStream inputStream, long length) throws SQLException {\n        chain.callableStatement_setBlob(statement, parameterName, inputStream, length);\n    }\n\n    @Override\n    public void callableStatement_setBoolean(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                             boolean x) throws SQLException {\n        chain.callableStatement_setBoolean(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setByte(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          byte x) throws SQLException {\n        chain.callableStatement_setByte(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setBytes(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           byte[] x) throws SQLException {\n        chain.callableStatement_setBytes(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                     String parameterName, java.io.Reader reader) throws SQLException {\n        chain.callableStatement_setCharacterStream(statement, parameterName, reader);\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                     String parameterName, java.io.Reader reader, int length)\n            throws SQLException {\n        chain.callableStatement_setCharacterStream(statement, parameterName, reader, length);\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                     String parameterName, java.io.Reader reader, long length)\n            throws SQLException {\n        chain.callableStatement_setCharacterStream(statement, parameterName, reader, length);\n    }\n\n    @Override\n    public void callableStatement_setClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          Clob x) throws SQLException {\n        chain.callableStatement_setClob(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          Reader reader) throws SQLException {\n        chain.callableStatement_setClob(statement, parameterName, reader);\n    }\n\n    @Override\n    public void callableStatement_setClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          Reader reader, long length) throws SQLException {\n        chain.callableStatement_setClob(statement, parameterName, reader, length);\n    }\n\n    @Override\n    public void callableStatement_setDate(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          java.sql.Date x) throws SQLException {\n        chain.callableStatement_setDate(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setDate(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          java.sql.Date x, Calendar cal) throws SQLException {\n        chain.callableStatement_setDate(statement, parameterName, x, cal);\n    }\n\n    @Override\n    public void callableStatement_setDouble(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            double x) throws SQLException {\n        chain.callableStatement_setDouble(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setFloat(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           float x) throws SQLException {\n        chain.callableStatement_setFloat(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setInt(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                         int x) throws SQLException {\n        chain.callableStatement_setInt(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setLong(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          long x) throws SQLException {\n        chain.callableStatement_setLong(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                      String parameterName, Reader value) throws SQLException {\n        chain.callableStatement_setNCharacterStream(statement, parameterName, value);\n    }\n\n    @Override\n    public void callableStatement_setNCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                      String parameterName, Reader value, long length)\n            throws SQLException {\n        chain.callableStatement_setNCharacterStream(statement, parameterName, value, length);\n    }\n\n    @Override\n    public void callableStatement_setNClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           NClob value) throws SQLException {\n        chain.callableStatement_setNClob(statement, parameterName, value);\n    }\n\n    @Override\n    public void callableStatement_setNClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           Reader reader) throws SQLException {\n        chain.callableStatement_setNClob(statement, parameterName, reader);\n    }\n\n    @Override\n    public void callableStatement_setNClob(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           Reader reader, long length) throws SQLException {\n        chain.callableStatement_setNClob(statement, parameterName, reader, length);\n    }\n\n    @Override\n    public void callableStatement_setNString(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                             String value) throws SQLException {\n        chain.callableStatement_setNString(statement, parameterName, value);\n    }\n\n    @Override\n    public void callableStatement_setNull(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          int sqlType) throws SQLException {\n        chain.callableStatement_setNull(statement, parameterName, sqlType);\n    }\n\n    @Override\n    public void callableStatement_setNull(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          int sqlType, String typeName) throws SQLException {\n        chain.callableStatement_setNull(statement, parameterName, sqlType, typeName);\n    }\n\n    @Override\n    public void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Object x) throws SQLException {\n        chain.callableStatement_setObject(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Object x, int targetSqlType) throws SQLException {\n        chain.callableStatement_setObject(statement, parameterName, x, targetSqlType);\n    }\n\n    @Override\n    public void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Object x, int targetSqlType, int scale) throws SQLException {\n        chain.callableStatement_setObject(statement, parameterName, x, targetSqlType, scale);\n    }\n\n    @Override\n    public void callableStatement_setRowId(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           RowId x) throws SQLException {\n        chain.callableStatement_setRowId(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setShort(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                           short x) throws SQLException {\n        chain.callableStatement_setShort(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setSQLXML(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            SQLXML xmlObject) throws SQLException {\n        chain.callableStatement_setSQLXML(statement, parameterName, xmlObject);\n    }\n\n    @Override\n    public void callableStatement_setString(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            String x) throws SQLException {\n        chain.callableStatement_setString(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setTime(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          java.sql.Time x) throws SQLException {\n        chain.callableStatement_setTime(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setTime(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                          java.sql.Time x, Calendar cal) throws SQLException {\n        chain.callableStatement_setTime(statement, parameterName, x, cal);\n    }\n\n    @Override\n    public void callableStatement_setTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                               String parameterName, java.sql.Timestamp x) throws SQLException {\n        chain.callableStatement_setTimestamp(statement, parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setTimestamp(FilterChain chain, CallableStatementProxy statement,\n                                               String parameterName, java.sql.Timestamp x, Calendar cal)\n            throws SQLException {\n        chain.callableStatement_setTimestamp(statement, parameterName, x, cal);\n    }\n\n    @Override\n    public void callableStatement_setURL(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                         java.net.URL val) throws SQLException {\n        chain.callableStatement_setURL(statement, parameterName, val);\n    }\n\n    @Override\n    public boolean callableStatement_wasNull(FilterChain chain, CallableStatementProxy statement) throws SQLException {\n        return chain.callableStatement_wasNull(statement);\n    }\n\n    @Override\n    public void connection_clearWarnings(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        chain.connection_clearWarnings(connection);\n    }\n\n    @Override\n    public void connection_close(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        chain.connection_close(connection);\n    }\n\n    @Override\n    public void connection_commit(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        chain.connection_commit(connection);\n    }\n\n    @Override\n    public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n        return chain.connection_connect(info);\n    }\n\n    @Override\n    public Array connection_createArrayOf(FilterChain chain, ConnectionProxy connection, String typeName,\n                                          Object[] elements) throws SQLException {\n        return chain.connection_createArrayOf(connection, typeName, elements);\n    }\n\n    @Override\n    public Blob connection_createBlob(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_createBlob(connection);\n    }\n\n    @Override\n    public Clob connection_createClob(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_createClob(connection);\n    }\n\n    @Override\n    public NClob connection_createNClob(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_createNClob(connection);\n    }\n\n    @Override\n    public SQLXML connection_createSQLXML(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_createSQLXML(connection);\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(FilterChain chain,\n                                                     ConnectionProxy connection) throws SQLException {\n        return chain.connection_createStatement(connection);\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection, int resultSetType,\n                                                     int resultSetConcurrency) throws SQLException {\n        return chain.connection_createStatement(connection, resultSetType, resultSetConcurrency);\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection, int resultSetType,\n                                                     int resultSetConcurrency, int resultSetHoldability)\n            throws SQLException {\n        return chain.connection_createStatement(connection, resultSetType, resultSetConcurrency, resultSetHoldability);\n    }\n\n    @Override\n    public Struct connection_createStruct(FilterChain chain, ConnectionProxy connection, String typeName,\n                                          Object[] attributes) throws SQLException {\n        return chain.connection_createStruct(connection, typeName, attributes);\n    }\n\n    @Override\n    public boolean connection_getAutoCommit(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getAutoCommit(connection);\n    }\n\n    @Override\n    public String connection_getCatalog(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getCatalog(connection);\n    }\n\n    @Override\n    public Properties connection_getClientInfo(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getClientInfo(connection);\n    }\n\n    @Override\n    public String connection_getClientInfo(FilterChain chain, ConnectionProxy connection, String name)\n            throws SQLException {\n        return chain.connection_getClientInfo(connection, name);\n    }\n\n    @Override\n    public int connection_getHoldability(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getHoldability(connection);\n    }\n\n    @Override\n    public DatabaseMetaData connection_getMetaData(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getMetaData(connection);\n    }\n\n    @Override\n    public int connection_getTransactionIsolation(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getTransactionIsolation(connection);\n    }\n\n    @Override\n    public Map<String, Class<?>> connection_getTypeMap(FilterChain chain, ConnectionProxy connection)\n            throws SQLException {\n        return chain.connection_getTypeMap(connection);\n    }\n\n    @Override\n    public SQLWarning connection_getWarnings(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getWarnings(connection);\n    }\n\n    @Override\n    public boolean connection_isClosed(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_isClosed(connection);\n    }\n\n    @Override\n    public boolean connection_isReadOnly(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_isReadOnly(connection);\n    }\n\n    @Override\n    public boolean connection_isValid(FilterChain chain, ConnectionProxy connection, int timeout) throws SQLException {\n        return chain.connection_isValid(connection, timeout);\n    }\n\n    @Override\n    public String connection_nativeSQL(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException {\n        return chain.connection_nativeSQL(connection, sql);\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        return chain.connection_prepareCall(connection, sql);\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency);\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency,\n                                                         int resultSetHoldability) throws SQLException {\n        return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        return chain.connection_prepareStatement(connection, sql);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int autoGeneratedKeys) throws SQLException {\n        return chain.connection_prepareStatement(connection, sql, autoGeneratedKeys);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency,\n                                                              int resultSetHoldability) throws SQLException {\n        return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency,\n                resultSetHoldability);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int[] columnIndexes) throws SQLException {\n        return chain.connection_prepareStatement(connection, sql, columnIndexes);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, String[] columnNames) throws SQLException {\n        return chain.connection_prepareStatement(connection, sql, columnNames);\n    }\n\n    @Override\n    public void connection_releaseSavepoint(FilterChain chain, ConnectionProxy connection, Savepoint savepoint)\n            throws SQLException {\n        chain.connection_releaseSavepoint(connection, savepoint);\n    }\n\n    @Override\n    public void connection_rollback(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        chain.connection_rollback(connection);\n    }\n\n    @Override\n    public void connection_rollback(FilterChain chain, ConnectionProxy connection, Savepoint savepoint)\n            throws SQLException {\n        chain.connection_rollback(connection, savepoint);\n    }\n\n    @Override\n    public void connection_setAutoCommit(FilterChain chain, ConnectionProxy connection, boolean autoCommit)\n            throws SQLException {\n        chain.connection_setAutoCommit(connection, autoCommit);\n    }\n\n    @Override\n    public void connection_setCatalog(FilterChain chain, ConnectionProxy connection, String catalog)\n            throws SQLException {\n        chain.connection_setCatalog(connection, catalog);\n    }\n\n    @Override\n    public void connection_setClientInfo(FilterChain chain, ConnectionProxy connection, Properties properties)\n            throws SQLClientInfoException {\n        chain.connection_setClientInfo(connection, properties);\n    }\n\n    @Override\n    public void connection_setClientInfo(FilterChain chain, ConnectionProxy connection, String name, String value)\n            throws SQLClientInfoException {\n        chain.connection_setClientInfo(connection, name, value);\n    }\n\n    @Override\n    public void connection_setHoldability(FilterChain chain, ConnectionProxy connection, int holdability)\n            throws SQLException {\n        chain.connection_setHoldability(connection, holdability);\n    }\n\n    @Override\n    public void connection_setReadOnly(FilterChain chain, ConnectionProxy connection, boolean readOnly)\n            throws SQLException {\n        chain.connection_setReadOnly(connection, readOnly);\n    }\n\n    @Override\n    public Savepoint connection_setSavepoint(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_setSavepoint(connection);\n    }\n\n    @Override\n    public Savepoint connection_setSavepoint(FilterChain chain, ConnectionProxy connection, String name)\n            throws SQLException {\n        return chain.connection_setSavepoint(connection, name);\n    }\n\n    @Override\n    public void connection_setTransactionIsolation(FilterChain chain, ConnectionProxy connection, int level)\n            throws SQLException {\n        chain.connection_setTransactionIsolation(connection, level);\n    }\n\n    @Override\n    public void connection_setTypeMap(FilterChain chain, ConnectionProxy connection, Map<String, Class<?>> map)\n            throws SQLException {\n        chain.connection_setTypeMap(connection, map);\n    }\n\n    @Override\n    public String connection_getSchema(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getSchema(connection);\n    }\n\n    @Override\n    public void connection_setSchema(FilterChain chain, ConnectionProxy connection, String schema) throws SQLException {\n        chain.connection_setSchema(connection, schema);\n    }\n\n    public void connection_abort(FilterChain chain, ConnectionProxy connection, Executor executor) throws SQLException {\n        chain.connection_abort(connection, executor);\n    }\n\n    public void connection_setNetworkTimeout(FilterChain chain,\n                                             ConnectionProxy connection,\n                                             Executor executor,\n                                             int milliseconds) throws SQLException {\n        chain.connection_setNetworkTimeout(connection, executor, milliseconds);\n    }\n\n    public int connection_getNetworkTimeout(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        return chain.connection_getNetworkTimeout(connection);\n    }\n\n    @Override\n    public boolean isWrapperFor(FilterChain chain, Wrapper wrapper, Class<?> iface) throws SQLException {\n        return chain.isWrapperFor(wrapper, iface);\n    }\n\n    @Override\n    public void preparedStatement_addBatch(FilterChain chain, PreparedStatementProxy statement) throws SQLException {\n        chain.preparedStatement_addBatch(statement);\n    }\n\n    @Override\n    public void preparedStatement_clearParameters(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException {\n        chain.preparedStatement_clearParameters(statement);\n    }\n\n    @Override\n    public boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement) throws SQLException {\n        return chain.preparedStatement_execute(statement);\n    }\n\n    @Override\n    public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException {\n        return chain.preparedStatement_executeQuery(statement);\n    }\n\n    @Override\n    public int preparedStatement_executeUpdate(FilterChain chain,\n                                               PreparedStatementProxy statement) throws SQLException {\n        return chain.preparedStatement_executeUpdate(statement);\n    }\n\n    @Override\n    public ResultSetMetaData preparedStatement_getMetaData(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException {\n        return chain.preparedStatement_getMetaData(statement);\n    }\n\n    @Override\n    public ParameterMetaData preparedStatement_getParameterMetaData(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException {\n        return chain.preparedStatement_getParameterMetaData(statement);\n    }\n\n    @Override\n    public void preparedStatement_setArray(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           Array x) throws SQLException {\n        chain.preparedStatement_setArray(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setAsciiStream(FilterChain chain, PreparedStatementProxy statement,\n                                                 int parameterIndex, java.io.InputStream x) throws SQLException {\n        chain.preparedStatement_setAsciiStream(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setAsciiStream(FilterChain chain, PreparedStatementProxy statement,\n                                                 int parameterIndex, java.io.InputStream x, int length)\n            throws SQLException {\n        chain.preparedStatement_setAsciiStream(statement, parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setAsciiStream(FilterChain chain, PreparedStatementProxy statement,\n                                                 int parameterIndex, java.io.InputStream x, long length)\n            throws SQLException {\n        chain.preparedStatement_setAsciiStream(statement, parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setBigDecimal(FilterChain chain, PreparedStatementProxy statement,\n                                                int parameterIndex, BigDecimal x) throws SQLException {\n        chain.preparedStatement_setBigDecimal(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBinaryStream(FilterChain chain, PreparedStatementProxy statement,\n                                                  int parameterIndex, java.io.InputStream x) throws SQLException {\n        chain.preparedStatement_setBinaryStream(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBinaryStream(FilterChain chain, PreparedStatementProxy statement,\n                                                  int parameterIndex, java.io.InputStream x, int length)\n            throws SQLException {\n        chain.preparedStatement_setBinaryStream(statement, parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setBinaryStream(FilterChain chain, PreparedStatementProxy statement,\n                                                  int parameterIndex, java.io.InputStream x, long length)\n            throws SQLException {\n        chain.preparedStatement_setBinaryStream(statement, parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setBlob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          Blob x) throws SQLException {\n        chain.preparedStatement_setBlob(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBlob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          InputStream inputStream) throws SQLException {\n        chain.preparedStatement_setBlob(statement, parameterIndex, inputStream);\n    }\n\n    @Override\n    public void preparedStatement_setBlob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          InputStream inputStream, long length) throws SQLException {\n        chain.preparedStatement_setBlob(statement, parameterIndex, inputStream, length);\n    }\n\n    @Override\n    public void preparedStatement_setBoolean(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                             boolean x) throws SQLException {\n        chain.preparedStatement_setBoolean(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setByte(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          byte x) throws SQLException {\n        chain.preparedStatement_setByte(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBytes(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           byte[] x) throws SQLException {\n        chain.preparedStatement_setBytes(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                     int parameterIndex, java.io.Reader reader) throws SQLException {\n        chain.preparedStatement_setCharacterStream(statement, parameterIndex, reader);\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                     int parameterIndex, java.io.Reader reader, int length)\n            throws SQLException {\n        chain.preparedStatement_setCharacterStream(statement, parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                     int parameterIndex, java.io.Reader reader, long length)\n            throws SQLException {\n        chain.preparedStatement_setCharacterStream(statement, parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          Clob x) throws SQLException {\n        chain.preparedStatement_setClob(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          Reader reader) throws SQLException {\n        chain.preparedStatement_setClob(statement, parameterIndex, reader);\n    }\n\n    @Override\n    public void preparedStatement_setClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          Reader reader, long length) throws SQLException {\n        chain.preparedStatement_setClob(statement, parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setDate(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          java.sql.Date x) throws SQLException {\n        chain.preparedStatement_setDate(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setDate(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          java.sql.Date x, Calendar cal) throws SQLException {\n        chain.preparedStatement_setDate(statement, parameterIndex, x, cal);\n    }\n\n    @Override\n    public void preparedStatement_setDouble(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            double x) throws SQLException {\n        chain.preparedStatement_setDouble(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setFloat(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           float x) throws SQLException {\n        chain.preparedStatement_setFloat(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setInt(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, int x)\n            throws SQLException {\n        chain.preparedStatement_setInt(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setLong(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          long x) throws SQLException {\n        chain.preparedStatement_setLong(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setNCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                      int parameterIndex, Reader value) throws SQLException {\n        chain.preparedStatement_setNCharacterStream(statement, parameterIndex, value);\n    }\n\n    @Override\n    public void preparedStatement_setNCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                      int parameterIndex, Reader value, long length)\n            throws SQLException {\n        chain.preparedStatement_setNCharacterStream(statement, parameterIndex, value, length);\n    }\n\n    @Override\n    public void preparedStatement_setNClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           NClob value) throws SQLException {\n        chain.preparedStatement_setNClob(statement, parameterIndex, value);\n    }\n\n    @Override\n    public void preparedStatement_setNClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           Reader reader) throws SQLException {\n        chain.preparedStatement_setNClob(statement, parameterIndex, reader);\n    }\n\n    @Override\n    public void preparedStatement_setNClob(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           Reader reader, long length) throws SQLException {\n        chain.preparedStatement_setNClob(statement, parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setNString(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                             String value) throws SQLException {\n        chain.preparedStatement_setNString(statement, parameterIndex, value);\n    }\n\n    @Override\n    public void preparedStatement_setNull(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          int sqlType) throws SQLException {\n        chain.preparedStatement_setNull(statement, parameterIndex, sqlType);\n    }\n\n    @Override\n    public void preparedStatement_setNull(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          int sqlType, String typeName) throws SQLException {\n        chain.preparedStatement_setNull(statement, parameterIndex, sqlType, typeName);\n    }\n\n    @Override\n    public void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            Object x) throws SQLException {\n        chain.preparedStatement_setObject(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            Object x, int targetSqlType) throws SQLException {\n        chain.preparedStatement_setObject(statement, parameterIndex, x, targetSqlType);\n    }\n\n    @Override\n    public void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            Object x, int targetSqlType, int scaleOrLength) throws SQLException {\n        chain.preparedStatement_setObject(statement, parameterIndex, x, targetSqlType, scaleOrLength);\n    }\n\n    @Override\n    public void preparedStatement_setRef(FilterChain chain, PreparedStatementProxy statement, int parameterIndex, Ref x)\n            throws SQLException {\n        chain.preparedStatement_setRef(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setRowId(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           RowId x) throws SQLException {\n        chain.preparedStatement_setRowId(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setShort(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                           short x) throws SQLException {\n        chain.preparedStatement_setShort(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setSQLXML(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            SQLXML xmlObject) throws SQLException {\n        chain.preparedStatement_setSQLXML(statement, parameterIndex, xmlObject);\n    }\n\n    @Override\n    public void preparedStatement_setString(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            String x) throws SQLException {\n        chain.preparedStatement_setString(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setTime(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          java.sql.Time x) throws SQLException {\n        chain.preparedStatement_setTime(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setTime(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                          java.sql.Time x, Calendar cal) throws SQLException {\n        chain.preparedStatement_setTime(statement, parameterIndex, x, cal);\n    }\n\n    @Override\n    public void preparedStatement_setTimestamp(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                               java.sql.Timestamp x) throws SQLException {\n        chain.preparedStatement_setTimestamp(statement, parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setTimestamp(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                               java.sql.Timestamp x, Calendar cal) throws SQLException {\n        chain.preparedStatement_setTimestamp(statement, parameterIndex, x, cal);\n    }\n\n    @Override\n    public void preparedStatement_setUnicodeStream(FilterChain chain, PreparedStatementProxy statement,\n                                                   int parameterIndex, java.io.InputStream x, int length)\n            throws SQLException {\n        chain.preparedStatement_setUnicodeStream(statement, parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setURL(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                         java.net.URL x) throws SQLException {\n        chain.preparedStatement_setURL(statement, parameterIndex, x);\n    }\n\n    @Override\n    public boolean resultSet_absolute(FilterChain chain, ResultSetProxy result, int row) throws SQLException {\n        return chain.resultSet_absolute(result, row);\n    }\n\n    @Override\n    public void resultSet_afterLast(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_afterLast(resultSet);\n    }\n\n    @Override\n    public void resultSet_beforeFirst(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_beforeFirst(resultSet);\n    }\n\n    @Override\n    public void resultSet_cancelRowUpdates(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_cancelRowUpdates(resultSet);\n    }\n\n    @Override\n    public void resultSet_clearWarnings(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_clearWarnings(resultSet);\n    }\n\n    @Override\n    public void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_close(resultSet);\n    }\n\n    @Override\n    public void resultSet_deleteRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_deleteRow(resultSet);\n    }\n\n    @Override\n    public int resultSet_findColumn(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_findColumn(result, columnLabel);\n    }\n\n    @Override\n    public boolean resultSet_first(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_first(resultSet);\n    }\n\n    @Override\n    public Array resultSet_getArray(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getArray(result, columnIndex);\n    }\n\n    @Override\n    public Array resultSet_getArray(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getArray(result, columnLabel);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getAsciiStream(result, columnIndex);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getAsciiStream(result, columnLabel);\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getBigDecimal(result, columnIndex);\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy result, int columnIndex, int scale)\n            throws SQLException {\n        return chain.resultSet_getBigDecimal(result, columnIndex, scale);\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getBigDecimal(result, columnLabel);\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy result, String columnLabel, int scale)\n            throws SQLException {\n        return chain.resultSet_getBigDecimal(result, columnLabel, scale);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getBinaryStream(result, columnIndex);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getBinaryStream(result, columnLabel);\n    }\n\n    @Override\n    public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getBlob(result, columnIndex);\n    }\n\n    @Override\n    public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getBlob(result, columnLabel);\n    }\n\n    @Override\n    public boolean resultSet_getBoolean(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getBoolean(result, columnIndex);\n    }\n\n    @Override\n    public boolean resultSet_getBoolean(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getBoolean(result, columnLabel);\n    }\n\n    @Override\n    public byte resultSet_getByte(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getByte(result, columnIndex);\n    }\n\n    @Override\n    public byte resultSet_getByte(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getByte(result, columnLabel);\n    }\n\n    @Override\n    public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getBytes(result, columnIndex);\n    }\n\n    @Override\n    public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getBytes(result, columnLabel);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getCharacterStream(result, columnIndex);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getCharacterStream(result, columnLabel);\n    }\n\n    @Override\n    public Clob resultSet_getClob(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getClob(result, columnIndex);\n    }\n\n    @Override\n    public Clob resultSet_getClob(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getClob(result, columnLabel);\n    }\n\n    @Override\n    public int resultSet_getConcurrency(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getConcurrency(resultSet);\n    }\n\n    @Override\n    public String resultSet_getCursorName(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getCursorName(resultSet);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getDate(result, columnIndex);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy result, int columnIndex, Calendar cal)\n            throws SQLException {\n        return chain.resultSet_getDate(result, columnIndex, cal);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getDate(result, columnLabel);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy result, String columnLabel, Calendar cal)\n            throws SQLException {\n        return chain.resultSet_getDate(result, columnLabel, cal);\n    }\n\n    @Override\n    public double resultSet_getDouble(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getDouble(result, columnIndex);\n    }\n\n    @Override\n    public double resultSet_getDouble(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        return chain.resultSet_getDouble(result, columnLabel);\n    }\n\n    @Override\n    public int resultSet_getFetchDirection(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getFetchDirection(resultSet);\n    }\n\n    @Override\n    public int resultSet_getFetchSize(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getFetchSize(resultSet);\n    }\n\n    @Override\n    public float resultSet_getFloat(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getFloat(result, columnIndex);\n    }\n\n    @Override\n    public float resultSet_getFloat(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getFloat(result, columnLabel);\n    }\n\n    @Override\n    public int resultSet_getHoldability(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getHoldability(resultSet);\n    }\n\n    @Override\n    public int resultSet_getInt(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getInt(result, columnIndex);\n    }\n\n    @Override\n    public int resultSet_getInt(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getInt(result, columnLabel);\n    }\n\n    @Override\n    public long resultSet_getLong(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getLong(result, columnIndex);\n    }\n\n    @Override\n    public long resultSet_getLong(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getLong(result, columnLabel);\n    }\n\n    @Override\n    public ResultSetMetaData resultSet_getMetaData(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getMetaData(resultSet);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getNCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getNCharacterStream(result, columnIndex);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getNCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getNCharacterStream(result, columnLabel);\n    }\n\n    @Override\n    public NClob resultSet_getNClob(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getNClob(result, columnIndex);\n    }\n\n    @Override\n    public NClob resultSet_getNClob(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getNClob(result, columnLabel);\n    }\n\n    @Override\n    public String resultSet_getNString(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getNString(result, columnIndex);\n    }\n\n    @Override\n    public String resultSet_getNString(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getNString(result, columnLabel);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getObject(result, columnIndex);\n    }\n\n    @Override\n    public <T> T resultSet_getObject(FilterChain chain,\n                                     ResultSetProxy result,\n                                     int columnIndex,\n                                     Class<T> type) throws SQLException {\n        return chain.resultSet_getObject(result, columnIndex, type);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                      java.util.Map<String, Class<?>> map) throws SQLException {\n        return chain.resultSet_getObject(result, columnIndex, map);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        return chain.resultSet_getObject(result, columnLabel);\n    }\n\n    @Override\n    public <T> T resultSet_getObject(FilterChain chain,\n                                     ResultSetProxy result,\n                                     String columnLabel,\n                                     Class<T> type) throws SQLException {\n        return chain.resultSet_getObject(result, columnLabel, type);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                      java.util.Map<String, Class<?>> map) throws SQLException {\n        return chain.resultSet_getObject(result, columnLabel, map);\n    }\n\n    @Override\n    public Ref resultSet_getRef(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getRef(result, columnIndex);\n    }\n\n    @Override\n    public Ref resultSet_getRef(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getRef(result, columnLabel);\n    }\n\n    @Override\n    public int resultSet_getRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getRow(resultSet);\n    }\n\n    // ////////////////\n\n    @Override\n    public RowId resultSet_getRowId(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getRowId(result, columnIndex);\n    }\n\n    @Override\n    public RowId resultSet_getRowId(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getRowId(result, columnLabel);\n    }\n\n    @Override\n    public short resultSet_getShort(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getShort(result, columnIndex);\n    }\n\n    @Override\n    public short resultSet_getShort(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return chain.resultSet_getShort(result, columnLabel);\n    }\n\n    @Override\n    public SQLXML resultSet_getSQLXML(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getSQLXML(result, columnIndex);\n    }\n\n    @Override\n    public SQLXML resultSet_getSQLXML(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        return chain.resultSet_getSQLXML(result, columnLabel);\n    }\n\n    @Override\n    public Statement resultSet_getStatement(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getStatement(resultSet);\n    }\n\n    @Override\n    public String resultSet_getString(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return chain.resultSet_getString(result, columnIndex);\n    }\n\n    @Override\n    public String resultSet_getString(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        return chain.resultSet_getString(result, columnLabel);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getTime(result, columnIndex);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy result, int columnIndex, Calendar cal)\n            throws SQLException {\n        return chain.resultSet_getTime(result, columnIndex, cal);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getTime(result, columnLabel);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy result, String columnLabel, Calendar cal)\n            throws SQLException {\n        return chain.resultSet_getTime(result, columnLabel, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getTimestamp(result, columnIndex);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                                     Calendar cal) throws SQLException {\n        return chain.resultSet_getTimestamp(result, columnIndex, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getTimestamp(result, columnLabel);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                                     Calendar cal) throws SQLException {\n        return chain.resultSet_getTimestamp(result, columnLabel, cal);\n    }\n\n    @Override\n    public int resultSet_getType(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getType(resultSet);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getUnicodeStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getUnicodeStream(result, columnIndex);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getUnicodeStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getUnicodeStream(result, columnLabel);\n    }\n\n    @Override\n    public java.net.URL resultSet_getURL(FilterChain chain,\n                                         ResultSetProxy result,\n                                         int columnIndex) throws SQLException {\n        return chain.resultSet_getURL(result, columnIndex);\n    }\n\n    @Override\n    public java.net.URL resultSet_getURL(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        return chain.resultSet_getURL(result, columnLabel);\n    }\n\n    @Override\n    public SQLWarning resultSet_getWarnings(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_getWarnings(resultSet);\n    }\n\n    @Override\n    public void resultSet_insertRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_insertRow(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_isAfterLast(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_isAfterLast(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_isBeforeFirst(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_isBeforeFirst(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_isClosed(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_isClosed(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_isFirst(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_isFirst(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_isLast(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_isLast(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_last(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_last(resultSet);\n    }\n\n    @Override\n    public void resultSet_moveToCurrentRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_moveToCurrentRow(resultSet);\n    }\n\n    @Override\n    public void resultSet_moveToInsertRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_moveToInsertRow(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_next(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_next(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_previous(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_previous(resultSet);\n    }\n\n    @Override\n    public void resultSet_refreshRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_refreshRow(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_relative(FilterChain chain, ResultSetProxy result, int rows) throws SQLException {\n        return chain.resultSet_relative(result, rows);\n    }\n\n    @Override\n    public boolean resultSet_rowDeleted(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_rowDeleted(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_rowInserted(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_rowInserted(resultSet);\n    }\n\n    @Override\n    public boolean resultSet_rowUpdated(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_rowUpdated(resultSet);\n    }\n\n    @Override\n    public void resultSet_setFetchDirection(FilterChain chain, ResultSetProxy result, int direction)\n            throws SQLException {\n        chain.resultSet_setFetchDirection(result, direction);\n    }\n\n    @Override\n    public void resultSet_setFetchSize(FilterChain chain, ResultSetProxy result, int rows) throws SQLException {\n        chain.resultSet_setFetchSize(result, rows);\n    }\n\n    @Override\n    public void resultSet_updateArray(FilterChain chain, ResultSetProxy result, int columnIndex, java.sql.Array x)\n            throws SQLException {\n        chain.resultSet_updateArray(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateArray(FilterChain chain, ResultSetProxy result, String columnLabel, java.sql.Array x)\n            throws SQLException {\n        chain.resultSet_updateArray(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                            java.io.InputStream x) throws SQLException {\n        chain.resultSet_updateAsciiStream(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                            java.io.InputStream x, int length) throws SQLException {\n        chain.resultSet_updateAsciiStream(result, columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                            java.io.InputStream x, long length) throws SQLException {\n        chain.resultSet_updateAsciiStream(result, columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                            java.io.InputStream x) throws SQLException {\n        chain.resultSet_updateAsciiStream(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                            java.io.InputStream x, int length) throws SQLException {\n        chain.resultSet_updateAsciiStream(result, columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                            java.io.InputStream x, long length) throws SQLException {\n        chain.resultSet_updateAsciiStream(result, columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBigDecimal(FilterChain chain, ResultSetProxy result, int columnIndex, BigDecimal x)\n            throws SQLException {\n        chain.resultSet_updateBigDecimal(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBigDecimal(FilterChain chain, ResultSetProxy result, String columnLabel, BigDecimal x)\n            throws SQLException {\n        chain.resultSet_updateBigDecimal(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                             java.io.InputStream x) throws SQLException {\n        chain.resultSet_updateBinaryStream(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                             java.io.InputStream x, int length) throws SQLException {\n        chain.resultSet_updateBinaryStream(result, columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                             java.io.InputStream x, long length) throws SQLException {\n        chain.resultSet_updateBinaryStream(result, columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                             java.io.InputStream x) throws SQLException {\n        chain.resultSet_updateBinaryStream(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                             java.io.InputStream x, int length) throws SQLException {\n        chain.resultSet_updateBinaryStream(result, columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                             java.io.InputStream x, long length) throws SQLException {\n        chain.resultSet_updateBinaryStream(result, columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy result, int columnIndex, InputStream inputStream)\n            throws SQLException {\n        chain.resultSet_updateBlob(result, columnIndex, inputStream);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                     InputStream inputStream, long length) throws SQLException {\n        chain.resultSet_updateBlob(result, columnIndex, inputStream, length);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy result, int columnIndex, java.sql.Blob x)\n            throws SQLException {\n        chain.resultSet_updateBlob(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                     InputStream inputStream) throws SQLException {\n        chain.resultSet_updateBlob(result, columnLabel, inputStream);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                     InputStream inputStream, long length) throws SQLException {\n        chain.resultSet_updateBlob(result, columnLabel, inputStream, length);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy result, String columnLabel, java.sql.Blob x)\n            throws SQLException {\n        chain.resultSet_updateBlob(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBoolean(FilterChain chain, ResultSetProxy result, int columnIndex, boolean x)\n            throws SQLException {\n        chain.resultSet_updateBoolean(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBoolean(FilterChain chain, ResultSetProxy result, String columnLabel, boolean x)\n            throws SQLException {\n        chain.resultSet_updateBoolean(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateByte(FilterChain chain, ResultSetProxy result, int columnIndex, byte x)\n            throws SQLException {\n        chain.resultSet_updateByte(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateByte(FilterChain chain, ResultSetProxy result, String columnLabel, byte x)\n            throws SQLException {\n        chain.resultSet_updateByte(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBytes(FilterChain chain, ResultSetProxy result, int columnIndex, byte[] x)\n            throws SQLException {\n        chain.resultSet_updateBytes(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBytes(FilterChain chain, ResultSetProxy result, String columnLabel, byte[] x)\n            throws SQLException {\n        chain.resultSet_updateBytes(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                                java.io.Reader x) throws SQLException {\n        chain.resultSet_updateCharacterStream(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                                java.io.Reader x, int length) throws SQLException {\n        chain.resultSet_updateCharacterStream(result, columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                                java.io.Reader x, long length) throws SQLException {\n        chain.resultSet_updateCharacterStream(result, columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                                java.io.Reader reader) throws SQLException {\n        chain.resultSet_updateCharacterStream(result, columnLabel, reader);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                                java.io.Reader reader, int length) throws SQLException {\n        chain.resultSet_updateCharacterStream(result, columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                                java.io.Reader reader, long length) throws SQLException {\n        chain.resultSet_updateCharacterStream(result, columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy result, int columnIndex, java.sql.Clob x)\n            throws SQLException {\n        chain.resultSet_updateClob(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy result, int columnIndex, Reader reader)\n            throws SQLException {\n        chain.resultSet_updateClob(result, columnIndex, reader);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy result, int columnIndex, Reader reader,\n                                     long length) throws SQLException {\n        chain.resultSet_updateClob(result, columnIndex, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy result, String columnLabel, java.sql.Clob x)\n            throws SQLException {\n        chain.resultSet_updateClob(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy result, String columnLabel, Reader reader)\n            throws SQLException {\n        chain.resultSet_updateClob(result, columnLabel, reader);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy result, String columnLabel, Reader reader,\n                                     long length) throws SQLException {\n        chain.resultSet_updateClob(result, columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateDate(FilterChain chain, ResultSetProxy result, int columnIndex, java.sql.Date x)\n            throws SQLException {\n        chain.resultSet_updateDate(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateDate(FilterChain chain, ResultSetProxy result, String columnLabel, java.sql.Date x)\n            throws SQLException {\n        chain.resultSet_updateDate(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateDouble(FilterChain chain, ResultSetProxy result, int columnIndex, double x)\n            throws SQLException {\n        chain.resultSet_updateDouble(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateDouble(FilterChain chain, ResultSetProxy result, String columnLabel, double x)\n            throws SQLException {\n        chain.resultSet_updateDouble(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateFloat(FilterChain chain, ResultSetProxy result, int columnIndex, float x)\n            throws SQLException {\n        chain.resultSet_updateFloat(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateFloat(FilterChain chain, ResultSetProxy result, String columnLabel, float x)\n            throws SQLException {\n        chain.resultSet_updateFloat(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateInt(FilterChain chain, ResultSetProxy result, int columnIndex, int x)\n            throws SQLException {\n        chain.resultSet_updateInt(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateInt(FilterChain chain, ResultSetProxy result, String columnLabel, int x)\n            throws SQLException {\n        chain.resultSet_updateInt(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateLong(FilterChain chain, ResultSetProxy result, int columnIndex, long x)\n            throws SQLException {\n        chain.resultSet_updateLong(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateLong(FilterChain chain, ResultSetProxy result, String columnLabel, long x)\n            throws SQLException {\n        chain.resultSet_updateLong(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                                 java.io.Reader x) throws SQLException {\n        chain.resultSet_updateNCharacterStream(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                                 java.io.Reader x, long length) throws SQLException {\n        chain.resultSet_updateNCharacterStream(result, columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                                 java.io.Reader reader) throws SQLException {\n        chain.resultSet_updateNCharacterStream(result, columnLabel, reader);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                                 java.io.Reader reader, long length) throws SQLException {\n        chain.resultSet_updateNCharacterStream(result, columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy result, int columnIndex, NClob nClob)\n            throws SQLException {\n        chain.resultSet_updateNClob(result, columnIndex, nClob);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy result, int columnIndex, Reader reader)\n            throws SQLException {\n        chain.resultSet_updateNClob(result, columnIndex, reader);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy result, int columnIndex, Reader reader,\n                                      long length) throws SQLException {\n        chain.resultSet_updateNClob(result, columnIndex, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy result, String columnLabel, NClob nClob)\n            throws SQLException {\n        chain.resultSet_updateNClob(result, columnLabel, nClob);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy result, String columnLabel, Reader reader)\n            throws SQLException {\n        chain.resultSet_updateNClob(result, columnLabel, reader);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy result, String columnLabel, Reader reader,\n                                      long length) throws SQLException {\n        chain.resultSet_updateNClob(result, columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateNString(FilterChain chain, ResultSetProxy result, int columnIndex, String nString)\n            throws SQLException {\n        chain.resultSet_updateNString(result, columnIndex, nString);\n    }\n\n    @Override\n    public void resultSet_updateNString(FilterChain chain, ResultSetProxy result, String columnLabel, String nString)\n            throws SQLException {\n        chain.resultSet_updateNString(result, columnLabel, nString);\n    }\n\n    @Override\n    public void resultSet_updateNull(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        chain.resultSet_updateNull(result, columnIndex);\n    }\n\n    @Override\n    public void resultSet_updateNull(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        chain.resultSet_updateNull(result, columnLabel);\n    }\n\n    @Override\n    public void resultSet_updateObject(FilterChain chain, ResultSetProxy result, int columnIndex, Object x)\n            throws SQLException {\n        chain.resultSet_updateObject(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateObject(FilterChain chain, ResultSetProxy result, int columnIndex, Object x,\n                                       int scaleOrLength) throws SQLException {\n        chain.resultSet_updateObject(result, columnIndex, x, scaleOrLength);\n    }\n\n    @Override\n    public void resultSet_updateObject(FilterChain chain, ResultSetProxy result, String columnLabel, Object x)\n            throws SQLException {\n        chain.resultSet_updateObject(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateObject(FilterChain chain, ResultSetProxy result, String columnLabel, Object x,\n                                       int scaleOrLength) throws SQLException {\n        chain.resultSet_updateObject(result, columnLabel, x, scaleOrLength);\n    }\n\n    @Override\n    public void resultSet_updateRef(FilterChain chain, ResultSetProxy result, int columnIndex, java.sql.Ref x)\n            throws SQLException {\n        chain.resultSet_updateRef(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateRef(FilterChain chain, ResultSetProxy result, String columnLabel, java.sql.Ref x)\n            throws SQLException {\n        chain.resultSet_updateRef(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateRow(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_updateRow(resultSet);\n    }\n\n    @Override\n    public void resultSet_updateRowId(FilterChain chain, ResultSetProxy result, int columnIndex, RowId x)\n            throws SQLException {\n        chain.resultSet_updateRowId(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateRowId(FilterChain chain, ResultSetProxy result, String columnLabel, RowId x)\n            throws SQLException {\n        chain.resultSet_updateRowId(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateShort(FilterChain chain, ResultSetProxy result, int columnIndex, short x)\n            throws SQLException {\n        chain.resultSet_updateShort(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateShort(FilterChain chain, ResultSetProxy result, String columnLabel, short x)\n            throws SQLException {\n        chain.resultSet_updateShort(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateSQLXML(FilterChain chain, ResultSetProxy result, int columnIndex, SQLXML xmlObject)\n            throws SQLException {\n        chain.resultSet_updateSQLXML(result, columnIndex, xmlObject);\n    }\n\n    @Override\n    public void resultSet_updateSQLXML(FilterChain chain, ResultSetProxy result, String columnLabel, SQLXML xmlObject)\n            throws SQLException {\n        chain.resultSet_updateSQLXML(result, columnLabel, xmlObject);\n    }\n\n    @Override\n    public void resultSet_updateString(FilterChain chain, ResultSetProxy result, int columnIndex, String x)\n            throws SQLException {\n        chain.resultSet_updateString(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateString(FilterChain chain, ResultSetProxy result, String columnLabel, String x)\n            throws SQLException {\n        chain.resultSet_updateString(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateTime(FilterChain chain, ResultSetProxy result, int columnIndex, java.sql.Time x)\n            throws SQLException {\n        chain.resultSet_updateTime(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateTime(FilterChain chain, ResultSetProxy result, String columnLabel, java.sql.Time x)\n            throws SQLException {\n        chain.resultSet_updateTime(result, columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateTimestamp(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                          java.sql.Timestamp x) throws SQLException {\n        chain.resultSet_updateTimestamp(result, columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateTimestamp(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                          java.sql.Timestamp x) throws SQLException {\n        chain.resultSet_updateTimestamp(result, columnLabel, x);\n    }\n\n    @Override\n    public boolean resultSet_wasNull(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return chain.resultSet_wasNull(resultSet);\n    }\n\n    @Override\n    public void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        chain.statement_addBatch(statement, sql);\n    }\n\n    @Override\n    public void statement_cancel(FilterChain chain, StatementProxy statement) throws SQLException {\n        chain.statement_cancel(statement);\n    }\n\n    @Override\n    public void statement_clearBatch(FilterChain chain, StatementProxy statement) throws SQLException {\n        chain.statement_clearBatch(statement);\n    }\n\n    @Override\n    public void statement_close(FilterChain chain, StatementProxy statement) throws SQLException {\n        chain.statement_close(statement);\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        return chain.statement_execute(statement, sql);\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        return chain.statement_execute(statement, sql, autoGeneratedKeys);\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        return chain.statement_execute(statement, sql, columnIndexes);\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        return chain.statement_execute(statement, sql, columnNames);\n    }\n\n    @Override\n    public int[] statement_executeBatch(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_executeBatch(statement);\n    }\n\n    // /////////////////////////////\n    @Override\n    public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)\n            throws SQLException {\n        return chain.statement_executeQuery(statement, sql);\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        return chain.statement_executeUpdate(statement, sql);\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        return chain.statement_executeUpdate(statement, sql, autoGeneratedKeys);\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        return chain.statement_executeUpdate(statement, sql, columnIndexes);\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        return chain.statement_executeUpdate(statement, sql, columnNames);\n    }\n\n    @Override\n    public Connection statement_getConnection(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getConnection(statement);\n    }\n\n    @Override\n    public int statement_getFetchDirection(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getFetchDirection(statement);\n    }\n\n    @Override\n    public int statement_getFetchSize(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getFetchSize(statement);\n    }\n\n    @Override\n    public ResultSetProxy statement_getGeneratedKeys(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getGeneratedKeys(statement);\n    }\n\n    @Override\n    public int statement_getMaxFieldSize(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getMaxFieldSize(statement);\n    }\n\n    @Override\n    public int statement_getMaxRows(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getMaxRows(statement);\n    }\n\n    @Override\n    public boolean statement_getMoreResults(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getMoreResults(statement);\n    }\n\n    @Override\n    public boolean statement_getMoreResults(FilterChain chain, StatementProxy statement, int current)\n            throws SQLException {\n        return chain.statement_getMoreResults(statement, current);\n    }\n\n    @Override\n    public int statement_getQueryTimeout(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getQueryTimeout(statement);\n    }\n\n    @Override\n    public void statement_setQueryTimeout(FilterChain chain,\n                                          StatementProxy statement,\n                                          int seconds) throws SQLException {\n        chain.statement_setQueryTimeout(statement, seconds);\n    }\n\n    @Override\n    public ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getResultSet(statement);\n    }\n\n    @Override\n    public int statement_getResultSetConcurrency(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getResultSetConcurrency(statement);\n    }\n\n    @Override\n    public int statement_getResultSetHoldability(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getResultSetHoldability(statement);\n    }\n\n    @Override\n    public int statement_getResultSetType(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getResultSetType(statement);\n    }\n\n    @Override\n    public int statement_getUpdateCount(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getUpdateCount(statement);\n    }\n\n    @Override\n    public SQLWarning statement_getWarnings(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_getWarnings(statement);\n    }\n\n    @Override\n    public void statement_clearWarnings(FilterChain chain, StatementProxy statement) throws SQLException {\n        chain.statement_clearWarnings(statement);\n    }\n\n    @Override\n    public boolean statement_isClosed(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_isClosed(statement);\n    }\n\n    @Override\n    public boolean statement_isPoolable(FilterChain chain, StatementProxy statement) throws SQLException {\n        return chain.statement_isPoolable(statement);\n    }\n\n    @Override\n    public void statement_setCursorName(FilterChain chain, StatementProxy statement, String name) throws SQLException {\n        chain.statement_setCursorName(statement, name);\n    }\n\n    @Override\n    public void statement_setEscapeProcessing(FilterChain chain, StatementProxy statement, boolean enable)\n            throws SQLException {\n        chain.statement_setEscapeProcessing(statement, enable);\n    }\n\n    @Override\n    public void statement_setFetchDirection(FilterChain chain, StatementProxy statement, int direction)\n            throws SQLException {\n        chain.statement_setFetchDirection(statement, direction);\n    }\n\n    @Override\n    public void statement_setFetchSize(FilterChain chain, StatementProxy statement, int rows) throws SQLException {\n        chain.statement_setFetchSize(statement, rows);\n    }\n\n    @Override\n    public void statement_setMaxFieldSize(FilterChain chain, StatementProxy statement, int max) throws SQLException {\n        chain.statement_setMaxFieldSize(statement, max);\n    }\n\n    @Override\n    public void statement_setMaxRows(FilterChain chain, StatementProxy statement, int max) throws SQLException {\n        chain.statement_setMaxRows(statement, max);\n    }\n\n    @Override\n    public void statement_setPoolable(FilterChain chain, StatementProxy statement, boolean poolable)\n            throws SQLException {\n        chain.statement_setPoolable(statement, poolable);\n    }\n\n    @Override\n    public <T> T unwrap(FilterChain chain, Wrapper wrapper, Class<T> iface) throws SQLException {\n        return chain.unwrap(wrapper, iface);\n    }\n\n    @Override\n    public long clob_length(FilterChain chain, ClobProxy wrapper) throws SQLException {\n        return chain.clob_length(wrapper);\n    }\n\n    @Override\n    public String clob_getSubString(FilterChain chain, ClobProxy wrapper, long pos, int length) throws SQLException {\n        return chain.clob_getSubString(wrapper, pos, length);\n    }\n\n    @Override\n    public java.io.Reader clob_getCharacterStream(FilterChain chain, ClobProxy wrapper) throws SQLException {\n        return chain.clob_getCharacterStream(wrapper);\n    }\n\n    @Override\n    public java.io.InputStream clob_getAsciiStream(FilterChain chain, ClobProxy wrapper) throws SQLException {\n        return chain.clob_getAsciiStream(wrapper);\n    }\n\n    @Override\n    public long clob_position(FilterChain chain, ClobProxy wrapper, String searchstr, long start) throws SQLException {\n        return chain.clob_position(wrapper, searchstr, start);\n    }\n\n    @Override\n    public long clob_position(FilterChain chain, ClobProxy wrapper, Clob searchstr, long start) throws SQLException {\n        return chain.clob_position(wrapper, searchstr, start);\n    }\n\n    @Override\n    public int clob_setString(FilterChain chain, ClobProxy wrapper, long pos, String str) throws SQLException {\n        return chain.clob_setString(wrapper, pos, str);\n    }\n\n    @Override\n    public int clob_setString(FilterChain chain, ClobProxy wrapper, long pos, String str, int offset, int len)\n            throws SQLException {\n        return chain.clob_setString(wrapper, pos, str, offset, len);\n    }\n\n    @Override\n    public java.io.OutputStream clob_setAsciiStream(FilterChain chain,\n                                                    ClobProxy wrapper,\n                                                    long pos) throws SQLException {\n        return chain.clob_setAsciiStream(wrapper, pos);\n    }\n\n    @Override\n    public java.io.Writer clob_setCharacterStream(FilterChain chain, ClobProxy wrapper, long pos) throws SQLException {\n        return chain.clob_setCharacterStream(wrapper, pos);\n    }\n\n    @Override\n    public void clob_truncate(FilterChain chain, ClobProxy wrapper, long len) throws SQLException {\n        chain.clob_truncate(wrapper, len);\n    }\n\n    @Override\n    public void clob_free(FilterChain chain, ClobProxy wrapper) throws SQLException {\n        chain.clob_free(wrapper);\n    }\n\n    @Override\n    public Reader clob_getCharacterStream(FilterChain chain, ClobProxy wrapper, long pos, long length)\n            throws SQLException {\n        return chain.clob_getCharacterStream(wrapper, pos, length);\n    }\n\n    // ///////////////////\n\n    @Override\n    public void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection connection) throws SQLException {\n        chain.dataSource_recycle(connection);\n    }\n\n    @Override\n    public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource,\n                                                          long maxWaitMillis) throws SQLException {\n        return chain.dataSource_connect(dataSource, maxWaitMillis);\n    }\n\n    // ///////////////\n\n    @Override\n    public int resultSetMetaData_getColumnCount(FilterChain chain,\n                                                ResultSetMetaDataProxy metaData) throws SQLException {\n        return chain.resultSetMetaData_getColumnCount(metaData);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isAutoIncrement(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isAutoIncrement(metaData, column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isCaseSensitive(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isCaseSensitive(metaData, column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isSearchable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isSearchable(metaData, column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isCurrency(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isCurrency(metaData, column);\n    }\n\n    @Override\n    public int resultSetMetaData_isNullable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isNullable(metaData, column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isSigned(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isSigned(metaData, column);\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnDisplaySize(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnDisplaySize(metaData, column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnLabel(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnLabel(metaData, column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnName(metaData, column);\n    }\n\n    @Override\n    public String resultSetMetaData_getSchemaName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getSchemaName(metaData, column);\n    }\n\n    @Override\n    public int resultSetMetaData_getPrecision(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getPrecision(metaData, column);\n    }\n\n    @Override\n    public int resultSetMetaData_getScale(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getScale(metaData, column);\n    }\n\n    @Override\n    public String resultSetMetaData_getTableName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getTableName(metaData, column);\n    }\n\n    @Override\n    public String resultSetMetaData_getCatalogName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getCatalogName(metaData, column);\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnType(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnType(metaData, column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnTypeName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnTypeName(metaData, column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isReadOnly(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isReadOnly(metaData, column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isWritable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isWritable(metaData, column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isDefinitelyWritable(FilterChain chain,\n                                                          ResultSetMetaDataProxy metaData,\n                                                          int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isDefinitelyWritable(metaData, column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnClassName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnClassName(metaData, column);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/FilterChain.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.*;\n\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface FilterChain {\n    DataSourceProxy getDataSource();\n\n    int getFilterSize();\n\n    int getPos();\n\n    FilterChain cloneChain();\n\n    <T> T unwrap(Wrapper wrapper, java.lang.Class<T> iface) throws java.sql.SQLException;\n\n    boolean isWrapperFor(Wrapper wrapper, java.lang.Class<?> iface) throws java.sql.SQLException;\n\n    ConnectionProxy connection_connect(Properties info) throws SQLException;\n\n    StatementProxy connection_createStatement(ConnectionProxy connection) throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(ConnectionProxy connection, String sql) throws SQLException;\n\n    CallableStatementProxy connection_prepareCall(ConnectionProxy connection, String sql) throws SQLException;\n\n    String connection_nativeSQL(ConnectionProxy connection, String sql) throws SQLException;\n\n    void connection_setAutoCommit(ConnectionProxy connection, boolean autoCommit) throws SQLException;\n\n    boolean connection_getAutoCommit(ConnectionProxy connection) throws SQLException;\n\n    void connection_commit(ConnectionProxy connection) throws SQLException;\n\n    void connection_rollback(ConnectionProxy connection) throws SQLException;\n\n    void connection_close(ConnectionProxy connection) throws SQLException;\n\n    boolean connection_isClosed(ConnectionProxy connection) throws SQLException;\n\n    DatabaseMetaData connection_getMetaData(ConnectionProxy connection) throws SQLException;\n\n    void connection_setReadOnly(ConnectionProxy connection, boolean readOnly) throws SQLException;\n\n    boolean connection_isReadOnly(ConnectionProxy connection) throws SQLException;\n\n    void connection_setCatalog(ConnectionProxy connection, String catalog) throws SQLException;\n\n    String connection_getCatalog(ConnectionProxy connection) throws SQLException;\n\n    void connection_setTransactionIsolation(ConnectionProxy connection, int level) throws SQLException;\n\n    int connection_getTransactionIsolation(ConnectionProxy connection) throws SQLException;\n\n    SQLWarning connection_getWarnings(ConnectionProxy connection) throws SQLException;\n\n    void connection_clearWarnings(ConnectionProxy connection) throws SQLException;\n\n    StatementProxy connection_createStatement(ConnectionProxy connection, int resultSetType, int resultSetConcurrency)\n            throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(ConnectionProxy connection, String sql, int resultSetType,\n                                                       int resultSetConcurrency) throws SQLException;\n\n    CallableStatementProxy connection_prepareCall(ConnectionProxy connection, String sql, int resultSetType,\n                                                  int resultSetConcurrency) throws SQLException;\n\n    java.util.Map<String, Class<?>> connection_getTypeMap(ConnectionProxy connection) throws SQLException;\n\n    void connection_setTypeMap(ConnectionProxy connection, java.util.Map<String, Class<?>> map) throws SQLException;\n\n    void connection_setHoldability(ConnectionProxy connection, int holdability) throws SQLException;\n\n    int connection_getHoldability(ConnectionProxy connection) throws SQLException;\n\n    Savepoint connection_setSavepoint(ConnectionProxy connection) throws SQLException;\n\n    Savepoint connection_setSavepoint(ConnectionProxy connection, String name) throws SQLException;\n\n    void connection_rollback(ConnectionProxy connection, Savepoint savepoint) throws SQLException;\n\n    void connection_releaseSavepoint(ConnectionProxy connection, Savepoint savepoint) throws SQLException;\n\n    StatementProxy connection_createStatement(ConnectionProxy connection, int resultSetType, int resultSetConcurrency,\n                                              int resultSetHoldability) throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(ConnectionProxy connection, String sql, int resultSetType,\n                                                       int resultSetConcurrency, int resultSetHoldability)\n            throws SQLException;\n\n    CallableStatementProxy connection_prepareCall(ConnectionProxy connection, String sql, int resultSetType,\n                                                  int resultSetConcurrency, int resultSetHoldability)\n            throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(ConnectionProxy connection, String sql, int autoGeneratedKeys)\n            throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(ConnectionProxy connection, String sql, int[] columnIndexes)\n            throws SQLException;\n\n    PreparedStatementProxy connection_prepareStatement(ConnectionProxy connection, String sql, String[] columnNames)\n            throws SQLException;\n\n    Clob connection_createClob(ConnectionProxy connection) throws SQLException;\n\n    Blob connection_createBlob(ConnectionProxy connection) throws SQLException;\n\n    NClob connection_createNClob(ConnectionProxy connection) throws SQLException;\n\n    SQLXML connection_createSQLXML(ConnectionProxy connection) throws SQLException;\n\n    boolean connection_isValid(ConnectionProxy connection, int timeout) throws SQLException;\n\n    void connection_setClientInfo(ConnectionProxy connection, String name, String value) throws SQLClientInfoException;\n\n    void connection_setClientInfo(ConnectionProxy connection, Properties properties) throws SQLClientInfoException;\n\n    String connection_getClientInfo(ConnectionProxy connection, String name) throws SQLException;\n\n    Properties connection_getClientInfo(ConnectionProxy connection) throws SQLException;\n\n    Array connection_createArrayOf(ConnectionProxy connection, String typeName, Object[] elements) throws SQLException;\n\n    Struct connection_createStruct(ConnectionProxy connection, String typeName, Object[] attributes)\n            throws SQLException;\n\n    String connection_getSchema(ConnectionProxy connection) throws SQLException;\n\n    void connection_setSchema(ConnectionProxy connection, String schema) throws SQLException;\n\n    void connection_abort(ConnectionProxy connection, Executor executor) throws SQLException;\n\n    void connection_setNetworkTimeout(ConnectionProxy connection,\n                                      Executor executor,\n                                      int milliseconds) throws SQLException;\n\n    int connection_getNetworkTimeout(ConnectionProxy connection) throws SQLException;\n    // ---------\n\n    // ///////////////\n    boolean resultSet_next(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_close(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_wasNull(ResultSetProxy resultSet) throws SQLException;\n\n    String resultSet_getString(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    boolean resultSet_getBoolean(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    byte resultSet_getByte(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    short resultSet_getShort(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    int resultSet_getInt(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    long resultSet_getLong(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    float resultSet_getFloat(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    double resultSet_getDouble(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(ResultSetProxy resultSet, int columnIndex, int scale) throws SQLException;\n\n    byte[] resultSet_getBytes(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.sql.Date resultSet_getDate(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.sql.Time resultSet_getTime(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.io.InputStream resultSet_getAsciiStream(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.io.InputStream resultSet_getUnicodeStream(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.io.InputStream resultSet_getBinaryStream(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    String resultSet_getString(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    boolean resultSet_getBoolean(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    byte resultSet_getByte(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    short resultSet_getShort(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    int resultSet_getInt(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    long resultSet_getLong(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    float resultSet_getFloat(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    double resultSet_getDouble(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(ResultSetProxy resultSet, String columnLabel, int scale) throws SQLException;\n\n    byte[] resultSet_getBytes(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.sql.Date resultSet_getDate(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.sql.Time resultSet_getTime(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.io.InputStream resultSet_getAsciiStream(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.io.InputStream resultSet_getUnicodeStream(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.io.InputStream resultSet_getBinaryStream(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    SQLWarning resultSet_getWarnings(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_clearWarnings(ResultSetProxy resultSet) throws SQLException;\n\n    String resultSet_getCursorName(ResultSetProxy resultSet) throws SQLException;\n\n    ResultSetMetaData resultSet_getMetaData(ResultSetProxy resultSet) throws SQLException;\n\n    Object resultSet_getObject(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    <T> T resultSet_getObject(ResultSetProxy resultSet, int columnIndex, Class<T> type) throws SQLException;\n\n    Object resultSet_getObject(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    <T> T resultSet_getObject(ResultSetProxy resultSet, String columnLabel, Class<T> type) throws SQLException;\n\n    int resultSet_findColumn(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.io.Reader resultSet_getCharacterStream(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.io.Reader resultSet_getCharacterStream(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    BigDecimal resultSet_getBigDecimal(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    boolean resultSet_isBeforeFirst(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isAfterLast(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isFirst(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isLast(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_beforeFirst(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_afterLast(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_first(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_last(ResultSetProxy resultSet) throws SQLException;\n\n    int resultSet_getRow(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_absolute(ResultSetProxy resultSet, int row) throws SQLException;\n\n    boolean resultSet_relative(ResultSetProxy resultSet, int rows) throws SQLException;\n\n    boolean resultSet_previous(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_setFetchDirection(ResultSetProxy resultSet, int direction) throws SQLException;\n\n    int resultSet_getFetchDirection(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_setFetchSize(ResultSetProxy resultSet, int rows) throws SQLException;\n\n    int resultSet_getFetchSize(ResultSetProxy resultSet) throws SQLException;\n\n    int resultSet_getType(ResultSetProxy resultSet) throws SQLException;\n\n    int resultSet_getConcurrency(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_rowUpdated(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_rowInserted(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_rowDeleted(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_updateNull(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    void resultSet_updateBoolean(ResultSetProxy resultSet, int columnIndex, boolean x) throws SQLException;\n\n    void resultSet_updateByte(ResultSetProxy resultSet, int columnIndex, byte x) throws SQLException;\n\n    void resultSet_updateShort(ResultSetProxy resultSet, int columnIndex, short x) throws SQLException;\n\n    void resultSet_updateInt(ResultSetProxy resultSet, int columnIndex, int x) throws SQLException;\n\n    void resultSet_updateLong(ResultSetProxy resultSet, int columnIndex, long x) throws SQLException;\n\n    void resultSet_updateFloat(ResultSetProxy resultSet, int columnIndex, float x) throws SQLException;\n\n    void resultSet_updateDouble(ResultSetProxy resultSet, int columnIndex, double x) throws SQLException;\n\n    void resultSet_updateBigDecimal(ResultSetProxy resultSet, int columnIndex, BigDecimal x) throws SQLException;\n\n    void resultSet_updateString(ResultSetProxy resultSet, int columnIndex, String x) throws SQLException;\n\n    void resultSet_updateBytes(ResultSetProxy resultSet, int columnIndex, byte[] x) throws SQLException;\n\n    void resultSet_updateDate(ResultSetProxy resultSet, int columnIndex, java.sql.Date x) throws SQLException;\n\n    void resultSet_updateTime(ResultSetProxy resultSet, int columnIndex, java.sql.Time x) throws SQLException;\n\n    void resultSet_updateTimestamp(ResultSetProxy resultSet, int columnIndex, java.sql.Timestamp x) throws SQLException;\n\n    void resultSet_updateAsciiStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x, int length)\n            throws SQLException;\n\n    void resultSet_updateBinaryStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x, int length)\n            throws SQLException;\n\n    void resultSet_updateCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x, int length)\n            throws SQLException;\n\n    void resultSet_updateObject(ResultSetProxy resultSet, int columnIndex, Object x, int scaleOrLength)\n            throws SQLException;\n\n    void resultSet_updateObject(ResultSetProxy resultSet, int columnIndex, Object x) throws SQLException;\n\n    void resultSet_updateNull(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateBoolean(ResultSetProxy resultSet, String columnLabel, boolean x) throws SQLException;\n\n    void resultSet_updateByte(ResultSetProxy resultSet, String columnLabel, byte x) throws SQLException;\n\n    void resultSet_updateShort(ResultSetProxy resultSet, String columnLabel, short x) throws SQLException;\n\n    void resultSet_updateInt(ResultSetProxy resultSet, String columnLabel, int x) throws SQLException;\n\n    void resultSet_updateLong(ResultSetProxy resultSet, String columnLabel, long x) throws SQLException;\n\n    void resultSet_updateFloat(ResultSetProxy resultSet, String columnLabel, float x) throws SQLException;\n\n    void resultSet_updateDouble(ResultSetProxy resultSet, String columnLabel, double x) throws SQLException;\n\n    void resultSet_updateBigDecimal(ResultSetProxy resultSet, String columnLabel, BigDecimal x) throws SQLException;\n\n    void resultSet_updateString(ResultSetProxy resultSet, String columnLabel, String x) throws SQLException;\n\n    void resultSet_updateBytes(ResultSetProxy resultSet, String columnLabel, byte[] x) throws SQLException;\n\n    void resultSet_updateDate(ResultSetProxy resultSet, String columnLabel, java.sql.Date x) throws SQLException;\n\n    void resultSet_updateTime(ResultSetProxy resultSet, String columnLabel, java.sql.Time x) throws SQLException;\n\n    void resultSet_updateTimestamp(ResultSetProxy resultSet, String columnLabel, java.sql.Timestamp x)\n            throws SQLException;\n\n    void resultSet_updateAsciiStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x, int length)\n            throws SQLException;\n\n    void resultSet_updateBinaryStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x, int length)\n            throws SQLException;\n\n    void resultSet_updateCharacterStream(ResultSetProxy resultSet,\n                                         String columnLabel,\n                                         java.io.Reader reader,\n                                         int length)\n            throws SQLException;\n\n    void resultSet_updateObject(ResultSetProxy resultSet, String columnLabel, Object x, int scaleOrLength)\n            throws SQLException;\n\n    void resultSet_updateObject(ResultSetProxy resultSet, String columnLabel, Object x) throws SQLException;\n\n    void resultSet_insertRow(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_updateRow(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_deleteRow(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_refreshRow(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_cancelRowUpdates(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_moveToInsertRow(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_moveToCurrentRow(ResultSetProxy resultSet) throws SQLException;\n\n    Statement resultSet_getStatement(ResultSetProxy resultSet) throws SQLException;\n\n    Object resultSet_getObject(ResultSetProxy resultSet, int columnIndex, java.util.Map<String, Class<?>> map)\n            throws SQLException;\n\n    Ref resultSet_getRef(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Blob resultSet_getBlob(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Clob resultSet_getClob(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Array resultSet_getArray(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    Object resultSet_getObject(ResultSetProxy resultSet, String columnLabel, java.util.Map<String, Class<?>> map)\n            throws SQLException;\n\n    Ref resultSet_getRef(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    Blob resultSet_getBlob(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    Clob resultSet_getClob(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    Array resultSet_getArray(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.sql.Date resultSet_getDate(ResultSetProxy resultSet, int columnIndex, Calendar cal) throws SQLException;\n\n    java.sql.Date resultSet_getDate(ResultSetProxy resultSet, String columnLabel, Calendar cal) throws SQLException;\n\n    java.sql.Time resultSet_getTime(ResultSetProxy resultSet, int columnIndex, Calendar cal) throws SQLException;\n\n    java.sql.Time resultSet_getTime(ResultSetProxy resultSet, String columnLabel, Calendar cal) throws SQLException;\n\n    java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy resultSet, int columnIndex, Calendar cal)\n            throws SQLException;\n\n    java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy resultSet, String columnLabel, Calendar cal)\n            throws SQLException;\n\n    java.net.URL resultSet_getURL(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.net.URL resultSet_getURL(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateRef(ResultSetProxy resultSet, int columnIndex, java.sql.Ref x) throws SQLException;\n\n    void resultSet_updateRef(ResultSetProxy resultSet, String columnLabel, java.sql.Ref x) throws SQLException;\n\n    void resultSet_updateBlob(ResultSetProxy resultSet, int columnIndex, java.sql.Blob x) throws SQLException;\n\n    void resultSet_updateBlob(ResultSetProxy resultSet, String columnLabel, java.sql.Blob x) throws SQLException;\n\n    void resultSet_updateClob(ResultSetProxy resultSet, int columnIndex, java.sql.Clob x) throws SQLException;\n\n    void resultSet_updateClob(ResultSetProxy resultSet, String columnLabel, java.sql.Clob x) throws SQLException;\n\n    void resultSet_updateArray(ResultSetProxy resultSet, int columnIndex, java.sql.Array x) throws SQLException;\n\n    void resultSet_updateArray(ResultSetProxy resultSet, String columnLabel, java.sql.Array x) throws SQLException;\n\n    RowId resultSet_getRowId(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    RowId resultSet_getRowId(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateRowId(ResultSetProxy resultSet, int columnIndex, RowId x) throws SQLException;\n\n    void resultSet_updateRowId(ResultSetProxy resultSet, String columnLabel, RowId x) throws SQLException;\n\n    int resultSet_getHoldability(ResultSetProxy resultSet) throws SQLException;\n\n    boolean resultSet_isClosed(ResultSetProxy resultSet) throws SQLException;\n\n    void resultSet_updateNString(ResultSetProxy resultSet, int columnIndex, String nString) throws SQLException;\n\n    void resultSet_updateNString(ResultSetProxy resultSet, String columnLabel, String nString) throws SQLException;\n\n    void resultSet_updateNClob(ResultSetProxy resultSet, int columnIndex, NClob nClob) throws SQLException;\n\n    void resultSet_updateNClob(ResultSetProxy resultSet, String columnLabel, NClob nClob) throws SQLException;\n\n    NClob resultSet_getNClob(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    NClob resultSet_getNClob(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    SQLXML resultSet_getSQLXML(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    SQLXML resultSet_getSQLXML(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateSQLXML(ResultSetProxy resultSet, int columnIndex, SQLXML xmlObject) throws SQLException;\n\n    void resultSet_updateSQLXML(ResultSetProxy resultSet, String columnLabel, SQLXML xmlObject) throws SQLException;\n\n    String resultSet_getNString(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    String resultSet_getNString(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    java.io.Reader resultSet_getNCharacterStream(ResultSetProxy resultSet, int columnIndex) throws SQLException;\n\n    java.io.Reader resultSet_getNCharacterStream(ResultSetProxy resultSet, String columnLabel) throws SQLException;\n\n    void resultSet_updateNCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x, long length)\n            throws SQLException;\n\n    void resultSet_updateNCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader,\n                                          long length) throws SQLException;\n\n    void resultSet_updateAsciiStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x, long length)\n            throws SQLException;\n\n    void resultSet_updateBinaryStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x, long length)\n            throws SQLException;\n\n    void resultSet_updateCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x, long length)\n            throws SQLException;\n\n    void resultSet_updateAsciiStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x, long length)\n            throws SQLException;\n\n    void resultSet_updateBinaryStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x, long length)\n            throws SQLException;\n\n    void resultSet_updateCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader,\n                                         long length) throws SQLException;\n\n    void resultSet_updateBlob(ResultSetProxy resultSet, int columnIndex, InputStream inputStream, long length)\n            throws SQLException;\n\n    void resultSet_updateBlob(ResultSetProxy resultSet, String columnLabel, InputStream inputStream, long length)\n            throws SQLException;\n\n    void resultSet_updateClob(ResultSetProxy resultSet, int columnIndex, Reader reader, long length)\n            throws SQLException;\n\n    void resultSet_updateClob(ResultSetProxy resultSet, String columnLabel, Reader reader, long length)\n            throws SQLException;\n\n    void resultSet_updateNClob(ResultSetProxy resultSet, int columnIndex, Reader reader, long length)\n            throws SQLException;\n\n    void resultSet_updateNClob(ResultSetProxy resultSet, String columnLabel, Reader reader, long length)\n            throws SQLException;\n\n    void resultSet_updateNCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x)\n            throws SQLException;\n\n    void resultSet_updateNCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader)\n            throws SQLException;\n\n    void resultSet_updateAsciiStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x)\n            throws SQLException;\n\n    void resultSet_updateBinaryStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x)\n            throws SQLException;\n\n    void resultSet_updateCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x)\n            throws SQLException;\n\n    void resultSet_updateAsciiStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x)\n            throws SQLException;\n\n    void resultSet_updateBinaryStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x)\n            throws SQLException;\n\n    void resultSet_updateCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader)\n            throws SQLException;\n\n    void resultSet_updateBlob(ResultSetProxy resultSet, int columnIndex, InputStream inputStream) throws SQLException;\n\n    void resultSet_updateBlob(ResultSetProxy resultSet, String columnLabel, InputStream inputStream)\n            throws SQLException;\n\n    void resultSet_updateClob(ResultSetProxy resultSet, int columnIndex, Reader reader) throws SQLException;\n\n    void resultSet_updateClob(ResultSetProxy resultSet, String columnLabel, Reader reader) throws SQLException;\n\n    void resultSet_updateNClob(ResultSetProxy resultSet, int columnIndex, Reader reader) throws SQLException;\n\n    void resultSet_updateNClob(ResultSetProxy resultSet, String columnLabel, Reader reader) throws SQLException;\n\n    // ////////////////////////////////////\n\n    ResultSetProxy statement_executeQuery(StatementProxy statement, String sql) throws SQLException;\n\n    int statement_executeUpdate(StatementProxy statement, String sql) throws SQLException;\n\n    void statement_close(StatementProxy statement) throws SQLException;\n\n    int statement_getMaxFieldSize(StatementProxy statement) throws SQLException;\n\n    void statement_setMaxFieldSize(StatementProxy statement, int max) throws SQLException;\n\n    int statement_getMaxRows(StatementProxy statement) throws SQLException;\n\n    void statement_setMaxRows(StatementProxy statement, int max) throws SQLException;\n\n    void statement_setEscapeProcessing(StatementProxy statement, boolean enable) throws SQLException;\n\n    int statement_getQueryTimeout(StatementProxy statement) throws SQLException;\n\n    void statement_setQueryTimeout(StatementProxy statement, int seconds) throws SQLException;\n\n    void statement_cancel(StatementProxy statement) throws SQLException;\n\n    SQLWarning statement_getWarnings(StatementProxy statement) throws SQLException;\n\n    void statement_clearWarnings(StatementProxy statement) throws SQLException;\n\n    void statement_setCursorName(StatementProxy statement, String name) throws SQLException;\n\n    boolean statement_execute(StatementProxy statement, String sql) throws SQLException;\n\n    ResultSetProxy statement_getResultSet(StatementProxy statement) throws SQLException;\n\n    int statement_getUpdateCount(StatementProxy statement) throws SQLException;\n\n    boolean statement_getMoreResults(StatementProxy statement) throws SQLException;\n\n    void statement_setFetchDirection(StatementProxy statement, int direction) throws SQLException;\n\n    int statement_getFetchDirection(StatementProxy statement) throws SQLException;\n\n    void statement_setFetchSize(StatementProxy statement, int rows) throws SQLException;\n\n    int statement_getFetchSize(StatementProxy statement) throws SQLException;\n\n    int statement_getResultSetConcurrency(StatementProxy statement) throws SQLException;\n\n    int statement_getResultSetType(StatementProxy statement) throws SQLException;\n\n    void statement_addBatch(StatementProxy statement, String sql) throws SQLException;\n\n    void statement_clearBatch(StatementProxy statement) throws SQLException;\n\n    int[] statement_executeBatch(StatementProxy statement) throws SQLException;\n\n    Connection statement_getConnection(StatementProxy statement) throws SQLException;\n\n    boolean statement_getMoreResults(StatementProxy statement, int current) throws SQLException;\n\n    ResultSetProxy statement_getGeneratedKeys(StatementProxy statement) throws SQLException;\n\n    int statement_executeUpdate(StatementProxy statement, String sql, int autoGeneratedKeys) throws SQLException;\n\n    int statement_executeUpdate(StatementProxy statement, String sql, int[] columnIndexes) throws SQLException;\n\n    int statement_executeUpdate(StatementProxy statement, String sql, String[] columnNames) throws SQLException;\n\n    boolean statement_execute(StatementProxy statement, String sql, int autoGeneratedKeys) throws SQLException;\n\n    boolean statement_execute(StatementProxy statement, String sql, int[] columnIndexes) throws SQLException;\n\n    boolean statement_execute(StatementProxy statement, String sql, String[] columnNames) throws SQLException;\n\n    int statement_getResultSetHoldability(StatementProxy statement) throws SQLException;\n\n    boolean statement_isClosed(StatementProxy statement) throws SQLException;\n\n    void statement_setPoolable(StatementProxy statement, boolean poolable) throws SQLException;\n\n    boolean statement_isPoolable(StatementProxy statement) throws SQLException;\n\n    // ////////////////////\n\n    ResultSetProxy preparedStatement_executeQuery(PreparedStatementProxy statement) throws SQLException;\n\n    int preparedStatement_executeUpdate(PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setNull(PreparedStatementProxy statement, int parameterIndex, int sqlType)\n            throws SQLException;\n\n    void preparedStatement_setBoolean(PreparedStatementProxy statement, int parameterIndex, boolean x)\n            throws SQLException;\n\n    void preparedStatement_setByte(PreparedStatementProxy statement, int parameterIndex, byte x) throws SQLException;\n\n    void preparedStatement_setShort(PreparedStatementProxy statement, int parameterIndex, short x) throws SQLException;\n\n    void preparedStatement_setInt(PreparedStatementProxy statement, int parameterIndex, int x) throws SQLException;\n\n    void preparedStatement_setLong(PreparedStatementProxy statement, int parameterIndex, long x) throws SQLException;\n\n    void preparedStatement_setFloat(PreparedStatementProxy statement, int parameterIndex, float x) throws SQLException;\n\n    void preparedStatement_setDouble(PreparedStatementProxy statement, int parameterIndex, double x)\n            throws SQLException;\n\n    void preparedStatement_setBigDecimal(PreparedStatementProxy statement, int parameterIndex, BigDecimal x)\n            throws SQLException;\n\n    void preparedStatement_setString(PreparedStatementProxy statement, int parameterIndex, String x)\n            throws SQLException;\n\n    void preparedStatement_setBytes(PreparedStatementProxy statement, int parameterIndex, byte[] x) throws SQLException;\n\n    void preparedStatement_setDate(PreparedStatementProxy statement, int parameterIndex, java.sql.Date x)\n            throws SQLException;\n\n    void preparedStatement_setTime(PreparedStatementProxy statement, int parameterIndex, java.sql.Time x)\n            throws SQLException;\n\n    void preparedStatement_setTimestamp(PreparedStatementProxy statement, int parameterIndex, java.sql.Timestamp x)\n            throws SQLException;\n\n    void preparedStatement_setAsciiStream(PreparedStatementProxy statement, int parameterIndex, java.io.InputStream x,\n                                          int length) throws SQLException;\n\n    void preparedStatement_setUnicodeStream(PreparedStatementProxy statement, int parameterIndex,\n                                            java.io.InputStream x, int length) throws SQLException;\n\n    void preparedStatement_setBinaryStream(PreparedStatementProxy statement, int parameterIndex, java.io.InputStream x,\n                                           int length) throws SQLException;\n\n    void preparedStatement_clearParameters(PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setObject(PreparedStatementProxy statement, int parameterIndex, Object x, int targetSqlType)\n            throws SQLException;\n\n    void preparedStatement_setObject(PreparedStatementProxy statement, int parameterIndex, Object x)\n            throws SQLException;\n\n    boolean preparedStatement_execute(PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_addBatch(PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setCharacterStream(PreparedStatementProxy statement, int parameterIndex,\n                                              java.io.Reader reader, int length) throws SQLException;\n\n    void preparedStatement_setRef(PreparedStatementProxy statement, int parameterIndex, Ref x) throws SQLException;\n\n    void preparedStatement_setBlob(PreparedStatementProxy statement, int parameterIndex, Blob x) throws SQLException;\n\n    void preparedStatement_setClob(PreparedStatementProxy statement, int parameterIndex, Clob x) throws SQLException;\n\n    void preparedStatement_setArray(PreparedStatementProxy statement, int parameterIndex, Array x) throws SQLException;\n\n    ResultSetMetaData preparedStatement_getMetaData(PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setDate(PreparedStatementProxy statement, int parameterIndex, java.sql.Date x, Calendar cal)\n            throws SQLException;\n\n    void preparedStatement_setTime(PreparedStatementProxy statement, int parameterIndex, java.sql.Time x, Calendar cal)\n            throws SQLException;\n\n    void preparedStatement_setTimestamp(PreparedStatementProxy statement, int parameterIndex, java.sql.Timestamp x,\n                                        Calendar cal) throws SQLException;\n\n    void preparedStatement_setNull(PreparedStatementProxy statement, int parameterIndex, int sqlType, String typeName)\n            throws SQLException;\n\n    void preparedStatement_setURL(PreparedStatementProxy statement, int parameterIndex, java.net.URL x)\n            throws SQLException;\n\n    ParameterMetaData preparedStatement_getParameterMetaData(PreparedStatementProxy statement) throws SQLException;\n\n    void preparedStatement_setRowId(PreparedStatementProxy statement, int parameterIndex, RowId x) throws SQLException;\n\n    void preparedStatement_setNString(PreparedStatementProxy statement, int parameterIndex, String value)\n            throws SQLException;\n\n    void preparedStatement_setNCharacterStream(PreparedStatementProxy statement, int parameterIndex, Reader value,\n                                               long length) throws SQLException;\n\n    void preparedStatement_setNClob(PreparedStatementProxy statement, int parameterIndex, NClob value)\n            throws SQLException;\n\n    void preparedStatement_setClob(PreparedStatementProxy statement, int parameterIndex, Reader reader, long length)\n            throws SQLException;\n\n    void preparedStatement_setBlob(PreparedStatementProxy statement, int parameterIndex, InputStream inputStream,\n                                   long length) throws SQLException;\n\n    void preparedStatement_setNClob(PreparedStatementProxy statement, int parameterIndex, Reader reader, long length)\n            throws SQLException;\n\n    void preparedStatement_setSQLXML(PreparedStatementProxy statement, int parameterIndex, SQLXML xmlObject)\n            throws SQLException;\n\n    void preparedStatement_setObject(PreparedStatementProxy statement, int parameterIndex, Object x, int targetSqlType,\n                                     int scaleOrLength) throws SQLException;\n\n    void preparedStatement_setAsciiStream(PreparedStatementProxy statement, int parameterIndex, java.io.InputStream x,\n                                          long length) throws SQLException;\n\n    void preparedStatement_setBinaryStream(PreparedStatementProxy statement, int parameterIndex, java.io.InputStream x,\n                                           long length) throws SQLException;\n\n    void preparedStatement_setCharacterStream(PreparedStatementProxy statement, int parameterIndex,\n                                              java.io.Reader reader, long length) throws SQLException;\n\n    void preparedStatement_setAsciiStream(PreparedStatementProxy statement, int parameterIndex, java.io.InputStream x)\n            throws SQLException;\n\n    void preparedStatement_setBinaryStream(PreparedStatementProxy statement, int parameterIndex, java.io.InputStream x)\n            throws SQLException;\n\n    void preparedStatement_setCharacterStream(PreparedStatementProxy statement, int parameterIndex,\n                                              java.io.Reader reader) throws SQLException;\n\n    void preparedStatement_setNCharacterStream(PreparedStatementProxy statement, int parameterIndex, Reader value)\n            throws SQLException;\n\n    void preparedStatement_setClob(PreparedStatementProxy statement, int parameterIndex, Reader reader)\n            throws SQLException;\n\n    void preparedStatement_setBlob(PreparedStatementProxy statement, int parameterIndex, InputStream inputStream)\n            throws SQLException;\n\n    void preparedStatement_setNClob(PreparedStatementProxy statement, int parameterIndex, Reader reader)\n            throws SQLException;\n\n    // /////////////////////////////\n\n    void callableStatement_registerOutParameter(CallableStatementProxy statement, int parameterIndex, int sqlType)\n            throws SQLException;\n\n    void callableStatement_registerOutParameter(CallableStatementProxy statement, int parameterIndex, int sqlType,\n                                                int scale) throws SQLException;\n\n    boolean callableStatement_wasNull(CallableStatementProxy statement) throws SQLException;\n\n    String callableStatement_getString(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    boolean callableStatement_getBoolean(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    byte callableStatement_getByte(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    short callableStatement_getShort(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    int callableStatement_getInt(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    long callableStatement_getLong(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    float callableStatement_getFloat(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    double callableStatement_getDouble(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    BigDecimal callableStatement_getBigDecimal(CallableStatementProxy statement, int parameterIndex, int scale)\n            throws SQLException;\n\n    byte[] callableStatement_getBytes(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    java.sql.Date callableStatement_getDate(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    java.sql.Time callableStatement_getTime(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    Object callableStatement_getObject(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    BigDecimal callableStatement_getBigDecimal(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    Object callableStatement_getObject(CallableStatementProxy statement, int parameterIndex,\n                                       java.util.Map<String, Class<?>> map) throws SQLException;\n\n    Ref callableStatement_getRef(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    Blob callableStatement_getBlob(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    Clob callableStatement_getClob(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    Array callableStatement_getArray(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    java.sql.Date callableStatement_getDate(CallableStatementProxy statement, int parameterIndex, Calendar cal)\n            throws SQLException;\n\n    java.sql.Time callableStatement_getTime(CallableStatementProxy statement, int parameterIndex, Calendar cal)\n            throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement,\n                                                      int parameterIndex,\n                                                      Calendar cal)\n            throws SQLException;\n\n    void callableStatement_registerOutParameter(CallableStatementProxy statement, int parameterIndex, int sqlType,\n                                                String typeName) throws SQLException;\n\n    void callableStatement_registerOutParameter(CallableStatementProxy statement, String parameterName, int sqlType)\n            throws SQLException;\n\n    void callableStatement_registerOutParameter(CallableStatementProxy statement, String parameterName, int sqlType,\n                                                int scale) throws SQLException;\n\n    void callableStatement_registerOutParameter(CallableStatementProxy statement, String parameterName, int sqlType,\n                                                String typeName) throws SQLException;\n\n    java.net.URL callableStatement_getURL(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    void callableStatement_setURL(CallableStatementProxy statement, String parameterName, java.net.URL val)\n            throws SQLException;\n\n    void callableStatement_setNull(CallableStatementProxy statement, String parameterName, int sqlType)\n            throws SQLException;\n\n    void callableStatement_setBoolean(CallableStatementProxy statement, String parameterName, boolean x)\n            throws SQLException;\n\n    void callableStatement_setByte(CallableStatementProxy statement, String parameterName, byte x) throws SQLException;\n\n    void callableStatement_setShort(CallableStatementProxy statement, String parameterName, short x)\n            throws SQLException;\n\n    void callableStatement_setInt(CallableStatementProxy statement, String parameterName, int x) throws SQLException;\n\n    void callableStatement_setLong(CallableStatementProxy statement, String parameterName, long x) throws SQLException;\n\n    void callableStatement_setFloat(CallableStatementProxy statement, String parameterName, float x)\n            throws SQLException;\n\n    void callableStatement_setDouble(CallableStatementProxy statement, String parameterName, double x)\n            throws SQLException;\n\n    void callableStatement_setBigDecimal(CallableStatementProxy statement, String parameterName, BigDecimal x)\n            throws SQLException;\n\n    void callableStatement_setString(CallableStatementProxy statement, String parameterName, String x)\n            throws SQLException;\n\n    void callableStatement_setBytes(CallableStatementProxy statement, String parameterName, byte[] x)\n            throws SQLException;\n\n    void callableStatement_setDate(CallableStatementProxy statement, String parameterName, java.sql.Date x)\n            throws SQLException;\n\n    void callableStatement_setTime(CallableStatementProxy statement, String parameterName, java.sql.Time x)\n            throws SQLException;\n\n    void callableStatement_setTimestamp(CallableStatementProxy statement, String parameterName, java.sql.Timestamp x)\n            throws SQLException;\n\n    void callableStatement_setAsciiStream(CallableStatementProxy statement, String parameterName,\n                                          java.io.InputStream x, int length) throws SQLException;\n\n    void callableStatement_setBinaryStream(CallableStatementProxy statement, String parameterName,\n                                           java.io.InputStream x, int length) throws SQLException;\n\n    void callableStatement_setObject(CallableStatementProxy statement, String parameterName, Object x,\n                                     int targetSqlType, int scale) throws SQLException;\n\n    void callableStatement_setObject(CallableStatementProxy statement,\n                                     String parameterName,\n                                     Object x,\n                                     int targetSqlType)\n            throws SQLException;\n\n    void callableStatement_setObject(CallableStatementProxy statement, String parameterName, Object x)\n            throws SQLException;\n\n    void callableStatement_setCharacterStream(CallableStatementProxy statement, String parameterName,\n                                              java.io.Reader reader, int length) throws SQLException;\n\n    void callableStatement_setDate(CallableStatementProxy statement,\n                                   String parameterName,\n                                   java.sql.Date x,\n                                   Calendar cal)\n            throws SQLException;\n\n    void callableStatement_setTime(CallableStatementProxy statement,\n                                   String parameterName,\n                                   java.sql.Time x,\n                                   Calendar cal)\n            throws SQLException;\n\n    void callableStatement_setTimestamp(CallableStatementProxy statement, String parameterName, java.sql.Timestamp x,\n                                        Calendar cal) throws SQLException;\n\n    void callableStatement_setNull(CallableStatementProxy statement, String parameterName, int sqlType, String typeName)\n            throws SQLException;\n\n    String callableStatement_getString(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    boolean callableStatement_getBoolean(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    byte callableStatement_getByte(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    short callableStatement_getShort(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    int callableStatement_getInt(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    long callableStatement_getLong(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    float callableStatement_getFloat(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    double callableStatement_getDouble(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    byte[] callableStatement_getBytes(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    java.sql.Date callableStatement_getDate(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    java.sql.Time callableStatement_getTime(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    Object callableStatement_getObject(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    BigDecimal callableStatement_getBigDecimal(CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    Object callableStatement_getObject(CallableStatementProxy statement, String parameterName,\n                                       java.util.Map<String, Class<?>> map) throws SQLException;\n\n    Ref callableStatement_getRef(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    Blob callableStatement_getBlob(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    Clob callableStatement_getClob(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    Array callableStatement_getArray(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    java.sql.Date callableStatement_getDate(CallableStatementProxy statement, String parameterName, Calendar cal)\n            throws SQLException;\n\n    java.sql.Time callableStatement_getTime(CallableStatementProxy statement, String parameterName, Calendar cal)\n            throws SQLException;\n\n    java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement, String parameterName,\n                                                      Calendar cal) throws SQLException;\n\n    java.net.URL callableStatement_getURL(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    RowId callableStatement_getRowId(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    RowId callableStatement_getRowId(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    void callableStatement_setRowId(CallableStatementProxy statement, String parameterName, RowId x)\n            throws SQLException;\n\n    void callableStatement_setNString(CallableStatementProxy statement, String parameterName, String value)\n            throws SQLException;\n\n    void callableStatement_setNCharacterStream(CallableStatementProxy statement, String parameterName, Reader value,\n                                               long length) throws SQLException;\n\n    void callableStatement_setNClob(CallableStatementProxy statement, String parameterName, NClob value)\n            throws SQLException;\n\n    void callableStatement_setClob(CallableStatementProxy statement, String parameterName, Reader reader, long length)\n            throws SQLException;\n\n    void callableStatement_setBlob(CallableStatementProxy statement, String parameterName, InputStream inputStream,\n                                   long length) throws SQLException;\n\n    void callableStatement_setNClob(CallableStatementProxy statement, String parameterName, Reader reader, long length)\n            throws SQLException;\n\n    NClob callableStatement_getNClob(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    NClob callableStatement_getNClob(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    void callableStatement_setSQLXML(CallableStatementProxy statement, String parameterName, SQLXML xmlObject)\n            throws SQLException;\n\n    SQLXML callableStatement_getSQLXML(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    SQLXML callableStatement_getSQLXML(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    String callableStatement_getNString(CallableStatementProxy statement, int parameterIndex) throws SQLException;\n\n    String callableStatement_getNString(CallableStatementProxy statement, String parameterName) throws SQLException;\n\n    java.io.Reader callableStatement_getNCharacterStream(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    java.io.Reader callableStatement_getNCharacterStream(CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    java.io.Reader callableStatement_getCharacterStream(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException;\n\n    java.io.Reader callableStatement_getCharacterStream(CallableStatementProxy statement, String parameterName)\n            throws SQLException;\n\n    void callableStatement_setBlob(CallableStatementProxy statement, String parameterName, Blob x) throws SQLException;\n\n    void callableStatement_setClob(CallableStatementProxy statement, String parameterName, Clob x) throws SQLException;\n\n    void callableStatement_setAsciiStream(CallableStatementProxy statement, String parameterName,\n                                          java.io.InputStream x, long length) throws SQLException;\n\n    void callableStatement_setBinaryStream(CallableStatementProxy statement, String parameterName,\n                                           java.io.InputStream x, long length) throws SQLException;\n\n    void callableStatement_setCharacterStream(CallableStatementProxy statement, String parameterName,\n                                              java.io.Reader reader, long length) throws SQLException;\n\n    void callableStatement_setAsciiStream(CallableStatementProxy statement, String parameterName, java.io.InputStream x)\n            throws SQLException;\n\n    void callableStatement_setBinaryStream(CallableStatementProxy statement,\n                                           String parameterName,\n                                           java.io.InputStream x)\n            throws SQLException;\n\n    void callableStatement_setCharacterStream(CallableStatementProxy statement, String parameterName,\n                                              java.io.Reader reader) throws SQLException;\n\n    void callableStatement_setNCharacterStream(CallableStatementProxy statement, String parameterName, Reader value)\n            throws SQLException;\n\n    void callableStatement_setClob(CallableStatementProxy statement, String parameterName, Reader reader)\n            throws SQLException;\n\n    void callableStatement_setBlob(CallableStatementProxy statement, String parameterName, InputStream inputStream)\n            throws SQLException;\n\n    void callableStatement_setNClob(CallableStatementProxy statement, String parameterName, Reader reader)\n            throws SQLException;\n\n    void clob_free(ClobProxy wrapper) throws SQLException;\n\n    InputStream clob_getAsciiStream(ClobProxy wrapper) throws SQLException;\n\n    Reader clob_getCharacterStream(ClobProxy wrapper) throws SQLException;\n\n    Reader clob_getCharacterStream(ClobProxy wrapper, long pos, long length) throws SQLException;\n\n    String clob_getSubString(ClobProxy wrapper, long pos, int length) throws SQLException;\n\n    long clob_length(ClobProxy wrapper) throws SQLException;\n\n    long clob_position(ClobProxy wrapper, String searchstr, long start) throws SQLException;\n\n    long clob_position(ClobProxy wrapper, Clob searchstr, long start) throws SQLException;\n\n    OutputStream clob_setAsciiStream(ClobProxy wrapper, long pos) throws SQLException;\n\n    Writer clob_setCharacterStream(ClobProxy wrapper, long pos) throws SQLException;\n\n    int clob_setString(ClobProxy wrapper, long pos, String str) throws SQLException;\n\n    int clob_setString(ClobProxy wrapper, long pos, String str, int offset, int len) throws SQLException;\n\n    void clob_truncate(ClobProxy wrapper, long len) throws SQLException;\n\n    // ////\n\n    void dataSource_recycle(DruidPooledConnection connection) throws SQLException;\n\n    DruidPooledConnection dataSource_connect(DruidDataSource dataSource, long maxWaitMillis) throws SQLException;\n\n    // //////////\n    int resultSetMetaData_getColumnCount(ResultSetMetaDataProxy metaData) throws SQLException;\n\n    boolean resultSetMetaData_isAutoIncrement(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    boolean resultSetMetaData_isCaseSensitive(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    boolean resultSetMetaData_isSearchable(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    boolean resultSetMetaData_isCurrency(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    int resultSetMetaData_isNullable(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    boolean resultSetMetaData_isSigned(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    int resultSetMetaData_getColumnDisplaySize(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getColumnLabel(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getColumnName(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getSchemaName(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    int resultSetMetaData_getPrecision(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    int resultSetMetaData_getScale(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getTableName(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getCatalogName(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    int resultSetMetaData_getColumnType(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getColumnTypeName(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    boolean resultSetMetaData_isReadOnly(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    boolean resultSetMetaData_isWritable(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    boolean resultSetMetaData_isDefinitelyWritable(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n\n    String resultSetMetaData_getColumnClassName(ResultSetMetaDataProxy metaData, int column) throws SQLException;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/FilterChainImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidStatementConnection;\nimport com.alibaba.druid.proxy.jdbc.*;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class FilterChainImpl implements FilterChain {\n    protected int pos;\n\n    private final DataSourceProxy dataSource;\n\n    private final int filterSize;\n\n    public FilterChainImpl(DataSourceProxy dataSource) {\n        this.dataSource = dataSource;\n        this.filterSize = getFilters().size();\n    }\n\n    public FilterChainImpl(DataSourceProxy dataSource, int pos) {\n        this.dataSource = dataSource;\n        this.pos = pos;\n        this.filterSize = getFilters().size();\n    }\n\n    public int getFilterSize() {\n        return filterSize;\n    }\n\n    public int getPos() {\n        return pos;\n    }\n\n    public void reset() {\n        pos = 0;\n    }\n\n    @Override\n    public FilterChain cloneChain() {\n        return new FilterChainImpl(dataSource, pos);\n    }\n\n    public DataSourceProxy getDataSource() {\n        return dataSource;\n    }\n\n    @Override\n    public boolean isWrapperFor(Wrapper wrapper, Class<?> iface) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .isWrapperFor(this, wrapper, iface);\n        }\n\n        if (wrapper instanceof DruidStatementConnection) {\n            if (iface.isInstance(((DruidStatementConnection) wrapper).getConnection())) {\n                return true;\n            }\n        }\n\n        // // if driver is for jdbc 3.0\n        if (iface.isInstance(wrapper)) {\n            return true;\n        }\n\n        return wrapper.isWrapperFor(iface);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Wrapper wrapper, Class<T> iface) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .unwrap(this, wrapper, iface);\n        }\n\n        if (iface == null) {\n            return null;\n        }\n\n        if (wrapper instanceof DruidStatementConnection) {\n            Connection conn = ((DruidStatementConnection) wrapper).getConnection();\n            if (iface.isAssignableFrom(conn.getClass())) {\n                return (T) conn;\n            }\n        }\n\n        // if driver is for jdbc 3.0\n        if (iface.isAssignableFrom(wrapper.getClass())) {\n            return (T) wrapper;\n        }\n\n        return wrapper.unwrap(iface);\n    }\n\n    public ConnectionProxy connection_connect(Properties info) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_connect(this, info);\n        }\n\n        Driver driver = dataSource.getRawDriver();\n        String url = dataSource.getRawJdbcUrl();\n\n        Connection nativeConnection = driver.connect(url, info);\n\n        if (nativeConnection == null) {\n            return null;\n        }\n\n        Statement stmt = nativeConnection.createStatement();\n        Connection conn = new DruidStatementConnection(nativeConnection, stmt);\n        return new ConnectionProxyImpl(dataSource, conn, info, dataSource.createConnectionId());\n    }\n\n    @Override\n    public void connection_clearWarnings(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_clearWarnings(this, connection);\n            return;\n        }\n\n        connection.getRawObject()\n                .clearWarnings();\n    }\n\n    @Override\n    public void connection_close(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_close(this, connection);\n            return;\n        }\n\n        connection.getRawObject()\n                .close();\n        connection.clearAttributes();\n    }\n\n    @Override\n    public void connection_commit(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_commit(this, connection);\n            return;\n        }\n\n        connection.getRawObject()\n                .commit();\n    }\n\n    @Override\n    public Array connection_createArrayOf(ConnectionProxy connection, String typeName, Object[] elements)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createArrayOf(this, connection, typeName, elements);\n        }\n\n        return connection.getRawObject()\n                .createArrayOf(typeName, elements);\n\n    }\n\n    @Override\n    public Blob connection_createBlob(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createBlob(this, connection);\n        }\n\n        return connection.getRawObject()\n                .createBlob();\n    }\n\n    @Override\n    public Clob connection_createClob(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createClob(this, connection);\n        }\n\n        return wrap(\n                connection,\n                connection\n                        .getRawObject()\n                        .createClob()\n        );\n    }\n\n    @Override\n    public NClob connection_createNClob(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createNClob(this, connection);\n        }\n\n        return wrap(\n                connection,\n                connection\n                        .getRawObject()\n                        .createNClob()\n        );\n    }\n\n    @Override\n    public SQLXML connection_createSQLXML(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createSQLXML(this, connection);\n        }\n\n        return connection.getRawObject()\n                .createSQLXML();\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createStatement(this, connection);\n        }\n\n        Statement statement = connection.getRawObject()\n                .createStatement();\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new StatementProxyImpl(\n                connection,\n                statement,\n                dataSource.createStatementId()\n        );\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(\n            ConnectionProxy connection,\n            int resultSetType,\n            int resultSetConcurrency) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createStatement(this, connection, resultSetType, resultSetConcurrency);\n        }\n\n        Statement statement = connection.getRawObject()\n                .createStatement(resultSetType, resultSetConcurrency);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new StatementProxyImpl(connection, statement, dataSource.createStatementId());\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(\n            ConnectionProxy connection,\n            int resultSetType,\n            int resultSetConcurrency,\n            int resultSetHoldability) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createStatement(this, connection, resultSetType, resultSetConcurrency, resultSetHoldability);\n        }\n\n        Statement statement = connection.getRawObject()\n                .createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);\n        if (statement == null) {\n            return null;\n        }\n        return new StatementProxyImpl(\n                connection,\n                statement,\n                dataSource.createStatementId());\n    }\n\n    @Override\n    public Struct connection_createStruct(\n            ConnectionProxy connection,\n            String typeName,\n            Object[] attributes) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_createStruct(this, connection, typeName, attributes);\n        }\n\n        return connection.getRawObject()\n                .createStruct(typeName, attributes);\n    }\n\n    @Override\n    public boolean connection_getAutoCommit(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getAutoCommit(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getAutoCommit();\n    }\n\n    @Override\n    public String connection_getCatalog(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getCatalog(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getCatalog();\n    }\n\n    @Override\n    public Properties connection_getClientInfo(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getClientInfo(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getClientInfo();\n    }\n\n    @Override\n    public String connection_getClientInfo(ConnectionProxy connection, String name) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getClientInfo(this, connection, name);\n        }\n\n        return connection.getRawObject()\n                .getClientInfo(name);\n    }\n\n    public List<Filter> getFilters() {\n        return dataSource.getProxyFilters();\n    }\n\n    @Override\n    public int connection_getHoldability(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getHoldability(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getHoldability();\n    }\n\n    @Override\n    public DatabaseMetaData connection_getMetaData(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getMetaData(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getMetaData();\n    }\n\n    @Override\n    public int connection_getTransactionIsolation(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getTransactionIsolation(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getTransactionIsolation();\n    }\n\n    @Override\n    public Map<String, Class<?>> connection_getTypeMap(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getTypeMap(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getTypeMap();\n    }\n\n    @Override\n    public SQLWarning connection_getWarnings(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getWarnings(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getWarnings();\n    }\n\n    @Override\n    public boolean connection_isClosed(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_isClosed(this, connection);\n        }\n\n        return connection.getRawObject()\n                .isClosed();\n    }\n\n    @Override\n    public boolean connection_isReadOnly(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_isReadOnly(this, connection);\n        }\n\n        return connection.getRawObject()\n                .isReadOnly();\n    }\n\n    @Override\n    public boolean connection_isValid(ConnectionProxy connection, int timeout) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_isValid(this, connection, timeout);\n        }\n\n        return connection.getRawObject()\n                .isValid(timeout);\n    }\n\n    @Override\n    public String connection_nativeSQL(ConnectionProxy connection, String sql) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_nativeSQL(this, connection, sql);\n        }\n\n        return connection.getRawObject()\n                .nativeSQL(sql);\n    }\n\n    private Filter nextFilter() {\n        return getFilters()\n                .get(pos++);\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(ConnectionProxy connection, String sql) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareCall(this, connection, sql);\n        }\n\n        CallableStatement statement = connection.getRawObject()\n                .prepareCall(sql);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new CallableStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(\n            ConnectionProxy connection,\n            String sql,\n            int resultSetType,\n            int resultSetConcurrency) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareCall(this, connection, sql, resultSetType, resultSetConcurrency);\n        }\n\n        CallableStatement statement = connection.getRawObject()\n                .prepareCall(sql, resultSetType, resultSetConcurrency);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new CallableStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(\n            ConnectionProxy connection,\n            String sql,\n            int resultSetType,\n            int resultSetConcurrency,\n            int resultSetHoldability) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareCall(\n                            this,\n                            connection,\n                            sql,\n                            resultSetType,\n                            resultSetConcurrency,\n                            resultSetHoldability\n                    );\n        }\n\n        CallableStatement statement = connection.getRawObject()\n                .prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new CallableStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(\n            ConnectionProxy connection,\n            String sql) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareStatement(this, connection, sql);\n        }\n\n        PreparedStatement statement = connection.getRawObject()\n                .prepareStatement(sql);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new PreparedStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(\n            ConnectionProxy connection,\n            String sql,\n            int autoGeneratedKeys) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareStatement(this, connection, sql, autoGeneratedKeys);\n        }\n\n        PreparedStatement statement = connection.getRawObject().prepareStatement(sql, autoGeneratedKeys);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new PreparedStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(\n            ConnectionProxy connection,\n            String sql,\n            int resultSetType,\n            int resultSetConcurrency) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareStatement(this, connection, sql, resultSetType, resultSetConcurrency);\n        }\n\n        PreparedStatement statement\n                = connection.getRawObject()\n                .prepareStatement(sql, resultSetType, resultSetConcurrency);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new PreparedStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(\n            ConnectionProxy connection,\n            String sql,\n            int resultSetType,\n            int resultSetConcurrency,\n            int resultSetHoldability) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareStatement(this, connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n        }\n\n        PreparedStatement statement = connection.getRawObject()\n                .prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new PreparedStatementProxyImpl(\n                connection,\n                statement,\n                sql,\n                dataSource.createStatementId()\n        );\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(\n            ConnectionProxy connection,\n            String sql,\n            int[] columnIndexes) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareStatement(this, connection, sql, columnIndexes);\n        }\n\n        PreparedStatement statement = connection.getRawObject()\n                .prepareStatement(sql, columnIndexes);\n\n        if (statement == null) {\n            return null;\n        }\n\n        return new PreparedStatementProxyImpl(\n                connection,\n                statement,\n                sql,\n                dataSource.createStatementId()\n        );\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(ConnectionProxy connection, String sql,\n                                                              String[] columnNames) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_prepareStatement(this, connection, sql, columnNames);\n        }\n\n        PreparedStatement statement = connection.getRawObject()\n                .prepareStatement(sql, columnNames);\n        if (statement == null) {\n            return null;\n        }\n\n        return new PreparedStatementProxyImpl(connection, statement, sql, dataSource.createStatementId());\n    }\n\n    @Override\n    public void connection_releaseSavepoint(ConnectionProxy connection, Savepoint savepoint) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_releaseSavepoint(this, connection, savepoint);\n            return;\n        }\n\n        connection.getRawObject()\n                .releaseSavepoint(savepoint);\n    }\n\n    @Override\n    public void connection_rollback(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_rollback(this, connection);\n            return;\n        }\n\n        connection.getRawObject()\n                .rollback();\n    }\n\n    @Override\n    public void connection_rollback(ConnectionProxy connection, Savepoint savepoint) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_rollback(this, connection, savepoint);\n            return;\n        }\n\n        connection.getRawObject()\n                .rollback(savepoint);\n    }\n\n    @Override\n    public void connection_setAutoCommit(ConnectionProxy connection, boolean autoCommit) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setAutoCommit(this, connection, autoCommit);\n            return;\n        }\n\n        connection.getRawObject()\n                .setAutoCommit(autoCommit);\n    }\n\n    @Override\n    public void connection_setCatalog(ConnectionProxy connection, String catalog) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setCatalog(this, connection, catalog);\n            return;\n        }\n\n        connection.getRawObject()\n                .setCatalog(catalog);\n    }\n\n    @Override\n    public void connection_setClientInfo(\n            ConnectionProxy connection,\n            Properties properties) throws SQLClientInfoException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setClientInfo(this, connection, properties);\n            return;\n        }\n\n        connection.getRawObject()\n                .setClientInfo(properties);\n    }\n\n    @Override\n    public void connection_setClientInfo(\n            ConnectionProxy connection,\n            String name, String value) throws SQLClientInfoException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setClientInfo(this, connection, name, value);\n            return;\n        }\n\n        connection.getRawObject()\n                .setClientInfo(name, value);\n    }\n\n    @Override\n    public void connection_setHoldability(ConnectionProxy connection, int holdability) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setHoldability(this, connection, holdability);\n            return;\n        }\n\n        connection.getRawObject()\n                .setHoldability(holdability);\n    }\n\n    @Override\n    public void connection_setReadOnly(ConnectionProxy connection, boolean readOnly) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setReadOnly(this, connection, readOnly);\n            return;\n        }\n\n        connection.getRawObject()\n                .setReadOnly(readOnly);\n    }\n\n    @Override\n    public Savepoint connection_setSavepoint(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_setSavepoint(this, connection);\n        }\n\n        return connection.getRawObject()\n                .setSavepoint();\n    }\n\n    @Override\n    public Savepoint connection_setSavepoint(ConnectionProxy connection, String name) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_setSavepoint(this, connection, name);\n        }\n\n        return connection.getRawObject()\n                .setSavepoint(name);\n    }\n\n    @Override\n    public void connection_setTransactionIsolation(ConnectionProxy connection, int level) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setTransactionIsolation(this, connection, level);\n            return;\n        }\n\n        connection.getRawObject()\n                .setTransactionIsolation(level);\n    }\n\n    @Override\n    public void connection_setTypeMap(ConnectionProxy connection, Map<String, Class<?>> map) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setTypeMap(this, connection, map);\n            return;\n        }\n\n        connection.getRawObject()\n                .setTypeMap(map);\n    }\n\n    @Override\n    public String connection_getSchema(ConnectionProxy connection) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getSchema(this, connection);\n        }\n\n        return connection.getRawObject()\n                .getSchema();\n    }\n\n    @Override\n    public void connection_setSchema(ConnectionProxy connection, String schema) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setSchema(this, connection, schema);\n            return;\n        }\n\n        connection.getRawObject()\n                .setSchema(schema);\n    }\n\n    public void connection_abort(ConnectionProxy conn, Executor executor) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_abort(this, conn, executor);\n            return;\n        }\n\n        conn.getRawObject()\n                .abort(executor);\n    }\n\n    public void connection_setNetworkTimeout(ConnectionProxy conn,\n                                             Executor executor,\n                                             int milliseconds) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .connection_setNetworkTimeout(this, conn, executor, milliseconds);\n            return;\n        }\n\n        conn.getRawObject()\n                .setNetworkTimeout(executor, milliseconds);\n    }\n\n    public int connection_getNetworkTimeout(ConnectionProxy conn) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .connection_getNetworkTimeout(this, conn);\n        }\n\n        return conn.getRawObject().getNetworkTimeout();\n    }\n\n    // ///////////////////////////////////////\n\n    @Override\n    public boolean resultSet_next(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_next(this, rs);\n        }\n\n        return rs\n                .getResultSetRaw().next();\n    }\n\n    @Override\n    public void resultSet_close(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .resultSet_close(this, rs);\n            return;\n        }\n\n        rs.getResultSetRaw()\n                .close();\n        rs.clearAttributes();\n    }\n\n    @Override\n    public boolean resultSet_wasNull(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_wasNull(this, rs);\n        }\n\n        return rs.getResultSetRaw().wasNull();\n    }\n\n    @Override\n    public String resultSet_getString(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getString(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getString(columnIndex);\n    }\n\n    @Override\n    public boolean resultSet_getBoolean(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBoolean(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getBoolean(columnIndex);\n    }\n\n    @Override\n    public byte resultSet_getByte(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getByte(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getByte(columnIndex);\n    }\n\n    @Override\n    public short resultSet_getShort(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getShort(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getShort(columnIndex);\n    }\n\n    @Override\n    public int resultSet_getInt(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getInt(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getInt(columnIndex);\n    }\n\n    @Override\n    public long resultSet_getLong(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getLong(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getLong(columnIndex);\n    }\n\n    @Override\n    public float resultSet_getFloat(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getFloat(this, resultSet, columnIndex);\n        }\n\n        return resultSet.getResultSetRaw()\n                .getFloat(columnIndex);\n    }\n\n    @Override\n    public double resultSet_getDouble(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getDouble(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getDouble(columnIndex);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public BigDecimal resultSet_getBigDecimal(ResultSetProxy rs, int columnIndex, int scale) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBigDecimal(this, rs, columnIndex, scale);\n        }\n\n        return rs.getResultSetRaw()\n                .getBigDecimal(columnIndex, scale);\n    }\n\n    @Override\n    public byte[] resultSet_getBytes(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBytes(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getBytes(columnIndex);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getDate(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getDate(columnIndex);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getTime(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getTime(columnIndex);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getTimestamp(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getTimestamp(columnIndex);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getAsciiStream(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getAsciiStream(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getAsciiStream(columnIndex);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public java.io.InputStream resultSet_getUnicodeStream(ResultSetProxy rs, int columnIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getUnicodeStream(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getUnicodeStream(columnIndex);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getBinaryStream(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBinaryStream(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getBinaryStream(columnIndex);\n    }\n\n    @Override\n    public String resultSet_getString(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getString(this, rs, columnLabel);\n        }\n        return rs.getResultSetRaw()\n                .getString(columnLabel);\n    }\n\n    @Override\n    public boolean resultSet_getBoolean(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBoolean(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getBoolean(columnLabel);\n    }\n\n    @Override\n    public byte resultSet_getByte(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getByte(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getByte(columnLabel);\n    }\n\n    @Override\n    public short resultSet_getShort(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getShort(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getShort(columnLabel);\n    }\n\n    @Override\n    public int resultSet_getInt(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getInt(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getInt(columnLabel);\n    }\n\n    @Override\n    public long resultSet_getLong(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getLong(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getLong(columnLabel);\n    }\n\n    @Override\n    public float resultSet_getFloat(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getFloat(this, rs, columnLabel);\n        }\n        return rs.getResultSetRaw()\n                .getFloat(columnLabel);\n    }\n\n    @Override\n    public double resultSet_getDouble(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getDouble(this, rs, columnLabel);\n        }\n        return rs.getResultSetRaw()\n                .getDouble(columnLabel);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public BigDecimal resultSet_getBigDecimal(ResultSetProxy rs, String columnLabel, int scale) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBigDecimal(this, rs, columnLabel, scale);\n        }\n\n        return rs.getResultSetRaw()\n                .getBigDecimal(columnLabel, scale);\n    }\n\n    @Override\n    public byte[] resultSet_getBytes(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBytes(this, rs, columnLabel);\n        }\n        return rs.getResultSetRaw().getBytes(columnLabel);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getDate(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getDate(columnLabel);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getTime(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getTime(columnLabel);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getTimestamp(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getTimestamp(columnLabel);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getAsciiStream(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getAsciiStream(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getAsciiStream(columnLabel);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public java.io.InputStream resultSet_getUnicodeStream(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getUnicodeStream(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getUnicodeStream(columnLabel);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getBinaryStream(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBinaryStream(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getBinaryStream(columnLabel);\n    }\n\n    @Override\n    public SQLWarning resultSet_getWarnings(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getWarnings(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .getWarnings();\n    }\n\n    @Override\n    public void resultSet_clearWarnings(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .resultSet_clearWarnings(this, rs);\n            return;\n        }\n\n        rs.getResultSetRaw()\n                .clearWarnings();\n    }\n\n    @Override\n    public String resultSet_getCursorName(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getCursorName(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .getCursorName();\n    }\n\n    @Override\n    public ResultSetMetaData resultSet_getMetaData(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getMetaData(this, rs);\n        }\n\n        ResultSetMetaData metaData = rs.getResultSetRaw()\n                .getMetaData();\n        if (metaData == null) {\n            return null;\n        }\n\n        return new ResultSetMetaDataProxyImpl(metaData, dataSource.createMetaDataId(), rs);\n    }\n\n    @Override\n    public Object resultSet_getObject(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getObject(this, rs, columnIndex);\n        }\n\n        Object obj = rs.getResultSetRaw().getObject(columnIndex);\n\n        if (obj instanceof ResultSet) {\n            StatementProxy statement = rs.getStatementProxy();\n            return new ResultSetProxyImpl(\n                    statement,\n                    (ResultSet) obj,\n                    dataSource.createResultSetId(),\n                    statement.getLastExecuteSql()\n            );\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(\n                    rs.getStatementProxy(), (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public <T> T resultSet_getObject(ResultSetProxy rs, int columnIndex, Class<T> type) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getObject(this, rs, columnIndex, type);\n        }\n\n        Object obj = rs.getResultSetRaw().getObject(columnIndex, type);\n\n        if (obj instanceof ResultSet) {\n            StatementProxy statement = rs.getStatementProxy();\n            return (T) new ResultSetProxyImpl(\n                    statement,\n                    (ResultSet) obj,\n                    dataSource.createResultSetId(),\n                    statement.getLastExecuteSql()\n            );\n        }\n\n        if (obj instanceof Clob) {\n            return (T) wrap(\n                    rs.getStatementProxy(), (Clob) obj);\n        }\n\n        return (T) obj;\n    }\n\n    @Override\n    public Object resultSet_getObject(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getObject(this, rs, columnLabel);\n        }\n\n        Object obj = rs.getResultSetRaw()\n                .getObject(columnLabel);\n\n        if (obj instanceof ResultSet) {\n            StatementProxy stmt = rs.getStatementProxy();\n            return new ResultSetProxyImpl(\n                    stmt,\n                    (ResultSet) obj,\n                    dataSource.createResultSetId(),\n                    stmt.getLastExecuteSql()\n            );\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(rs.getStatementProxy(), (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public <T> T resultSet_getObject(ResultSetProxy rs, String columnLabel, Class<T> type) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getObject(this, rs, columnLabel, type);\n        }\n\n        T obj = rs.getResultSetRaw()\n                .getObject(columnLabel, type);\n\n        if (obj instanceof ResultSet) {\n            StatementProxy stmt = rs.getStatementProxy();\n            return (T) new ResultSetProxyImpl(\n                    stmt,\n                    (ResultSet) obj,\n                    dataSource.createResultSetId(),\n                    stmt.getLastExecuteSql()\n            );\n        }\n\n        if (obj instanceof Clob) {\n            return (T) wrap(rs.getStatementProxy(), (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public int resultSet_findColumn(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_findColumn(this, rs, columnLabel);\n        }\n        return rs.getResultSetRaw()\n                .findColumn(columnLabel);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getCharacterStream(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getCharacterStream(this, rs, columnIndex);\n        }\n        return rs.getResultSetRaw()\n                .getCharacterStream(columnIndex);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getCharacterStream(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getCharacterStream(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getCharacterStream(columnLabel);\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBigDecimal(this, rs, columnIndex);\n        }\n\n        return rs.getResultSetRaw()\n                .getBigDecimal(columnIndex);\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(ResultSetProxy rs, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getBigDecimal(this, rs, columnLabel);\n        }\n\n        return rs.getResultSetRaw()\n                .getBigDecimal(columnLabel);\n    }\n\n    @Override\n    public boolean resultSet_isBeforeFirst(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_isBeforeFirst(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .isBeforeFirst();\n    }\n\n    @Override\n    public boolean resultSet_isAfterLast(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_isAfterLast(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .isAfterLast();\n    }\n\n    @Override\n    public boolean resultSet_isFirst(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_isFirst(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .isFirst();\n    }\n\n    @Override\n    public boolean resultSet_isLast(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_isLast(this, rs);\n        }\n        return rs.getResultSetRaw()\n                .isLast();\n    }\n\n    @Override\n    public void resultSet_beforeFirst(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .resultSet_beforeFirst(this, rs);\n            return;\n        }\n        rs.getResultSetRaw()\n                .beforeFirst();\n    }\n\n    @Override\n    public void resultSet_afterLast(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .resultSet_afterLast(this, rs);\n            return;\n        }\n\n        rs.getResultSetRaw()\n                .afterLast();\n    }\n\n    @Override\n    public boolean resultSet_first(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_first(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .first();\n    }\n\n    @Override\n    public boolean resultSet_last(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_last(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .last();\n    }\n\n    @Override\n    public int resultSet_getRow(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getRow(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .getRow();\n    }\n\n    @Override\n    public boolean resultSet_absolute(ResultSetProxy rs, int row) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_absolute(this, rs, row);\n        }\n\n        return rs.getResultSetRaw()\n                .absolute(row);\n    }\n\n    @Override\n    public boolean resultSet_relative(ResultSetProxy rs, int rows) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_relative(this, rs, rows);\n        }\n        return rs.getResultSetRaw().relative(rows);\n    }\n\n    @Override\n    public boolean resultSet_previous(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_previous(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .previous();\n    }\n\n    @Override\n    public void resultSet_setFetchDirection(ResultSetProxy rs, int direction) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .resultSet_setFetchDirection(this, rs, direction);\n            return;\n        }\n\n        rs.getResultSetRaw()\n                .setFetchDirection(direction);\n    }\n\n    @Override\n    public int resultSet_getFetchDirection(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getFetchDirection(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .getFetchDirection();\n    }\n\n    @Override\n    public void resultSet_setFetchSize(ResultSetProxy rs, int rows) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .resultSet_setFetchSize(this, rs, rows);\n            return;\n        }\n\n        rs.getResultSetRaw()\n                .setFetchSize(rows);\n    }\n\n    @Override\n    public int resultSet_getFetchSize(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getFetchSize(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .getFetchSize();\n    }\n\n    @Override\n    public int resultSet_getType(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getType(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .getType();\n    }\n\n    @Override\n    public int resultSet_getConcurrency(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_getConcurrency(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .getConcurrency();\n    }\n\n    @Override\n    public boolean resultSet_rowUpdated(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_rowUpdated(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .rowUpdated();\n    }\n\n    @Override\n    public boolean resultSet_rowInserted(ResultSetProxy rs) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_rowInserted(this, rs);\n        }\n\n        return rs.getResultSetRaw()\n                .rowInserted();\n    }\n\n    @Override\n    public boolean resultSet_rowDeleted(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSet_rowDeleted(this, resultSet);\n        }\n\n        return resultSet.getResultSetRaw()\n                .rowDeleted();\n    }\n\n    @Override\n    public void resultSet_updateNull(ResultSetProxy rs, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNull(this, rs, columnIndex);\n            return;\n\n        }\n\n        rs.getResultSetRaw()\n                .updateNull(columnIndex);\n    }\n\n    @Override\n    public void resultSet_updateBoolean(ResultSetProxy rs, int columnIndex, boolean x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter()\n                    .resultSet_updateBoolean(this, rs, columnIndex, x);\n            return;\n        }\n        rs.getResultSetRaw()\n                .updateBoolean(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateByte(ResultSetProxy resultSet, int columnIndex, byte x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateByte(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateByte(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateShort(ResultSetProxy resultSet, int columnIndex, short x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateShort(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateShort(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateInt(ResultSetProxy resultSet, int columnIndex, int x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateInt(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateInt(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateLong(ResultSetProxy resultSet, int columnIndex, long x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateLong(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateLong(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateFloat(ResultSetProxy resultSet, int columnIndex, float x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateFloat(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateFloat(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateDouble(ResultSetProxy resultSet, int columnIndex, double x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateDouble(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateDouble(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBigDecimal(ResultSetProxy resultSet,\n                                           int columnIndex,\n                                           BigDecimal x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBigDecimal(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBigDecimal(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateString(ResultSetProxy resultSet, int columnIndex, String x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateString(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateString(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBytes(ResultSetProxy resultSet, int columnIndex, byte[] x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBytes(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBytes(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateDate(ResultSetProxy resultSet, int columnIndex, java.sql.Date x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateDate(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateDate(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateTime(ResultSetProxy resultSet, int columnIndex, java.sql.Time x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateTime(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateTime(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateTimestamp(ResultSetProxy resultSet, int columnIndex, java.sql.Timestamp x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateTimestamp(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateTimestamp(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(ResultSetProxy resultSet,\n                                            int columnIndex,\n                                            java.io.InputStream x,\n                                            int length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateAsciiStream(this, resultSet, columnIndex, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateAsciiStream(columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x,\n                                             int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBinaryStream(this, resultSet, columnIndex, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBinaryStream(columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x, int length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateCharacterStream(this, resultSet, columnIndex, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateCharacterStream(columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateObject(ResultSetProxy resultSet, int columnIndex, Object x, int scaleOrLength)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateObject(this, resultSet, columnIndex, x, scaleOrLength);\n            return;\n        }\n        resultSet.getResultSetRaw().updateObject(columnIndex, x, scaleOrLength);\n    }\n\n    @Override\n    public void resultSet_updateObject(ResultSetProxy resultSet, int columnIndex, Object x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateObject(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateNull(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNull(this, resultSet, columnLabel);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNull(columnLabel);\n    }\n\n    @Override\n    public void resultSet_updateBoolean(ResultSetProxy resultSet, String columnLabel, boolean x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBoolean(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBoolean(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateByte(ResultSetProxy resultSet, String columnLabel, byte x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateByte(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateByte(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateShort(ResultSetProxy resultSet, String columnLabel, short x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateShort(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateShort(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateInt(ResultSetProxy resultSet, String columnLabel, int x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateInt(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateInt(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateLong(ResultSetProxy resultSet, String columnLabel, long x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateLong(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateLong(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateFloat(ResultSetProxy resultSet, String columnLabel, float x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateFloat(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateFloat(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateDouble(ResultSetProxy resultSet, String columnLabel, double x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateDouble(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateDouble(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBigDecimal(ResultSetProxy resultSet, String columnLabel, BigDecimal x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBigDecimal(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBigDecimal(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateString(ResultSetProxy resultSet, String columnLabel, String x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateString(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateString(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBytes(ResultSetProxy resultSet, String columnLabel, byte[] x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBytes(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBytes(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateDate(ResultSetProxy resultSet,\n                                     String columnLabel,\n                                     java.sql.Date x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateDate(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateDate(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateTime(ResultSetProxy resultSet,\n                                     String columnLabel,\n                                     java.sql.Time x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateTime(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateTime(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateTimestamp(ResultSetProxy resultSet, String columnLabel, java.sql.Timestamp x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateTimestamp(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateTimestamp(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x,\n                                            int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateAsciiStream(this, resultSet, columnLabel, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateAsciiStream(columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x,\n                                             int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBinaryStream(this, resultSet, columnLabel, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBinaryStream(columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader,\n                                                int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateCharacterStream(this, resultSet, columnLabel, reader, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateCharacterStream(columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateObject(ResultSetProxy resultSet, String columnLabel, Object x, int scaleOrLength)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateObject(this, resultSet, columnLabel, x, scaleOrLength);\n            return;\n        }\n        resultSet.getResultSetRaw().updateObject(columnLabel, x, scaleOrLength);\n    }\n\n    @Override\n    public void resultSet_updateObject(ResultSetProxy resultSet, String columnLabel, Object x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateObject(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_insertRow(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_insertRow(this, resultSet);\n            return;\n        }\n        resultSet.getResultSetRaw().insertRow();\n    }\n\n    @Override\n    public void resultSet_updateRow(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateRow(this, resultSet);\n            return;\n        }\n        resultSet.getResultSetRaw().updateRow();\n    }\n\n    @Override\n    public void resultSet_deleteRow(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_deleteRow(this, resultSet);\n            return;\n        }\n        resultSet.getResultSetRaw().deleteRow();\n    }\n\n    @Override\n    public void resultSet_refreshRow(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_refreshRow(this, resultSet);\n            return;\n        }\n        resultSet.getResultSetRaw().refreshRow();\n    }\n\n    @Override\n    public void resultSet_cancelRowUpdates(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_cancelRowUpdates(this, resultSet);\n            return;\n        }\n        resultSet.getResultSetRaw().cancelRowUpdates();\n    }\n\n    @Override\n    public void resultSet_moveToInsertRow(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_moveToInsertRow(this, resultSet);\n            return;\n        }\n        resultSet.getResultSetRaw().moveToInsertRow();\n    }\n\n    @Override\n    public void resultSet_moveToCurrentRow(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_moveToCurrentRow(this, resultSet);\n            return;\n        }\n        resultSet.getResultSetRaw().moveToCurrentRow();\n    }\n\n    @Override\n    public Statement resultSet_getStatement(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getStatement(this, resultSet);\n        }\n        return resultSet.getResultSetRaw().getStatement();\n    }\n\n    @Override\n    public Object resultSet_getObject(ResultSetProxy resultSet, int columnIndex, java.util.Map<String, Class<?>> map)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getObject(this, resultSet, columnIndex, map);\n        }\n\n        Object obj = resultSet.getResultSetRaw().getObject(columnIndex, map);\n\n        if (obj instanceof ResultSet) {\n            StatementProxy statement = resultSet.getStatementProxy();\n            return new ResultSetProxyImpl(statement, (ResultSet) obj, dataSource.createResultSetId(),\n                    statement.getLastExecuteSql());\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(resultSet.getStatementProxy(), (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Ref resultSet_getRef(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getRef(this, resultSet, columnIndex);\n        }\n        return resultSet.getResultSetRaw().getRef(columnIndex);\n    }\n\n    @Override\n    public Blob resultSet_getBlob(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getBlob(this, resultSet, columnIndex);\n        }\n        return resultSet.getResultSetRaw().getBlob(columnIndex);\n    }\n\n    @Override\n    public Clob resultSet_getClob(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getClob(this, resultSet, columnIndex);\n        }\n\n        Clob clob = resultSet.getResultSetRaw().getClob(columnIndex);\n\n        return wrap(resultSet.getStatementProxy(), clob);\n    }\n\n    @Override\n    public Array resultSet_getArray(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getArray(this, resultSet, columnIndex);\n        }\n\n        Array rawArray = resultSet.getResultSetRaw().getArray(columnIndex);\n\n        return rawArray;\n    }\n\n    @Override\n    public Object resultSet_getObject(ResultSetProxy resultSet, String columnLabel, java.util.Map<String, Class<?>> map)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getObject(this, resultSet, columnLabel, map);\n        }\n\n        Object obj = resultSet.getResultSetRaw().getObject(columnLabel, map);\n\n        if (obj instanceof ResultSet) {\n            StatementProxy statement = resultSet.getStatementProxy();\n            return new ResultSetProxyImpl(statement, (ResultSet) obj, dataSource.createResultSetId(),\n                    statement.getLastExecuteSql());\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(resultSet.getStatementProxy(), (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Ref resultSet_getRef(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getRef(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getRef(columnLabel);\n    }\n\n    @Override\n    public Blob resultSet_getBlob(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getBlob(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getBlob(columnLabel);\n    }\n\n    @Override\n    public Clob resultSet_getClob(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getClob(this, resultSet, columnLabel);\n        }\n\n        Clob clob = resultSet.getResultSetRaw().getClob(columnLabel);\n\n        return wrap(resultSet.getStatementProxy(), clob);\n    }\n\n    @Override\n    public Array resultSet_getArray(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getArray(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getArray(columnLabel);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(ResultSetProxy resultSet,\n                                           int columnIndex,\n                                           Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getDate(this, resultSet, columnIndex, cal);\n        }\n        return resultSet.getResultSetRaw().getDate(columnIndex, cal);\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(ResultSetProxy resultSet, String columnLabel, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getDate(this, resultSet, columnLabel, cal);\n        }\n        return resultSet.getResultSetRaw().getDate(columnLabel, cal);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(ResultSetProxy resultSet,\n                                           int columnIndex,\n                                           Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getTime(this, resultSet, columnIndex, cal);\n        }\n        return resultSet.getResultSetRaw().getTime(columnIndex, cal);\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(ResultSetProxy resultSet, String columnLabel, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getTime(this, resultSet, columnLabel, cal);\n        }\n        return resultSet.getResultSetRaw().getTime(columnLabel, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy resultSet, int columnIndex, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getTimestamp(this, resultSet, columnIndex, cal);\n        }\n        return resultSet.getResultSetRaw().getTimestamp(columnIndex, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(ResultSetProxy resultSet, String columnLabel, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getTimestamp(this, resultSet, columnLabel, cal);\n        }\n        return resultSet.getResultSetRaw().getTimestamp(columnLabel, cal);\n    }\n\n    @Override\n    public java.net.URL resultSet_getURL(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getURL(this, resultSet, columnIndex);\n        }\n        return resultSet.getResultSetRaw().getURL(columnIndex);\n    }\n\n    @Override\n    public java.net.URL resultSet_getURL(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getURL(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getURL(columnLabel);\n    }\n\n    @Override\n    public void resultSet_updateRef(ResultSetProxy resultSet, int columnIndex, java.sql.Ref x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateRef(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateRef(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateRef(ResultSetProxy resultSet, String columnLabel, java.sql.Ref x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateRef(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateRef(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBlob(ResultSetProxy resultSet, int columnIndex, Blob x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBlob(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBlob(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBlob(ResultSetProxy resultSet, String columnLabel, Blob x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBlob(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBlob(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateClob(ResultSetProxy resultSet, int columnIndex, Clob x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateClob(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateClob(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateClob(ResultSetProxy resultSet, String columnLabel, Clob x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateClob(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateClob(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateArray(ResultSetProxy resultSet, int columnIndex, java.sql.Array x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateArray(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateArray(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateArray(ResultSetProxy resultSet, String columnLabel, java.sql.Array x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateArray(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateArray(columnLabel, x);\n    }\n\n    @Override\n    public RowId resultSet_getRowId(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getRowId(this, resultSet, columnIndex);\n        }\n        return resultSet.getResultSetRaw().getRowId(columnIndex);\n    }\n\n    @Override\n    public RowId resultSet_getRowId(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getRowId(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getRowId(columnLabel);\n    }\n\n    @Override\n    public void resultSet_updateRowId(ResultSetProxy resultSet, int columnIndex, RowId x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateRowId(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateRowId(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateRowId(ResultSetProxy resultSet, String columnLabel, RowId x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateRowId(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateRowId(columnLabel, x);\n    }\n\n    @Override\n    public int resultSet_getHoldability(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getHoldability(this, resultSet);\n        }\n        return resultSet.getResultSetRaw().getHoldability();\n    }\n\n    @Override\n    public boolean resultSet_isClosed(ResultSetProxy resultSet) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_isClosed(this, resultSet);\n        }\n        return resultSet.getResultSetRaw().isClosed();\n    }\n\n    @Override\n    public void resultSet_updateNString(ResultSetProxy resultSet, int columnIndex, String x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNString(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNString(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateNString(ResultSetProxy resultSet, String columnLabel, String nString)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNString(this, resultSet, columnLabel, nString);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNString(columnLabel, nString);\n    }\n\n    @Override\n    public void resultSet_updateNClob(ResultSetProxy resultSet, int columnIndex, NClob x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNClob(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNClob(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateNClob(ResultSetProxy resultSet, String columnLabel, NClob x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNClob(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw()\n                .updateNClob(columnLabel, x);\n    }\n\n    @Override\n    public NClob resultSet_getNClob(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getNClob(this, resultSet, columnIndex);\n        }\n\n        NClob nclob = resultSet.getResultSetRaw().getNClob(columnIndex);\n\n        return wrap(resultSet.getStatementProxy().getConnectionProxy(), nclob);\n    }\n\n    @Override\n    public NClob resultSet_getNClob(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getNClob(this, resultSet, columnLabel);\n        }\n\n        NClob nclob = resultSet.getResultSetRaw()\n                .getNClob(columnLabel);\n\n        return wrap(resultSet.getStatementProxy().getConnectionProxy(), nclob);\n    }\n\n    @Override\n    public SQLXML resultSet_getSQLXML(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getSQLXML(this, resultSet, columnIndex);\n        }\n\n        return resultSet.getResultSetRaw().getSQLXML(columnIndex);\n    }\n\n    @Override\n    public SQLXML resultSet_getSQLXML(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getSQLXML(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getSQLXML(columnLabel);\n    }\n\n    @Override\n    public void resultSet_updateSQLXML(ResultSetProxy resultSet,\n                                       int columnIndex,\n                                       SQLXML xmlObject) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateSQLXML(this, resultSet, columnIndex, xmlObject);\n            return;\n        }\n        resultSet.getResultSetRaw().updateSQLXML(columnIndex, xmlObject);\n    }\n\n    @Override\n    public void resultSet_updateSQLXML(ResultSetProxy resultSet, String columnLabel, SQLXML xmlObject)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateSQLXML(this, resultSet, columnLabel, xmlObject);\n            return;\n        }\n        resultSet.getResultSetRaw().updateSQLXML(columnLabel, xmlObject);\n    }\n\n    @Override\n    public String resultSet_getNString(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getNString(this, resultSet, columnIndex);\n        }\n        return resultSet.getResultSetRaw().getNString(columnIndex);\n    }\n\n    @Override\n    public String resultSet_getNString(ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getNString(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getNString(columnLabel);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getNCharacterStream(ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getNCharacterStream(this, resultSet, columnIndex);\n        }\n        return resultSet.getResultSetRaw().getNCharacterStream(columnIndex);\n    }\n\n    @Override\n    public java.io.Reader resultSet_getNCharacterStream(ResultSetProxy resultSet, String columnLabel)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSet_getNCharacterStream(this, resultSet, columnLabel);\n        }\n        return resultSet.getResultSetRaw().getNCharacterStream(columnLabel);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x,\n                                                 long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNCharacterStream(this, resultSet, columnIndex, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNCharacterStream(columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader,\n                                                 long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNCharacterStream(this, resultSet, columnLabel, reader, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNCharacterStream(columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x,\n                                            long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateAsciiStream(this, resultSet, columnIndex, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateAsciiStream(columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x,\n                                             long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBinaryStream(this, resultSet, columnIndex, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBinaryStream(columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(ResultSetProxy resultSet,\n                                                int columnIndex,\n                                                java.io.Reader x,\n                                                long length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateCharacterStream(this, resultSet, columnIndex, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateCharacterStream(columnIndex, x, length);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x,\n                                            long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateAsciiStream(this, resultSet, columnLabel, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateAsciiStream(columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x,\n                                             long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBinaryStream(this, resultSet, columnLabel, x, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBinaryStream(columnLabel, x, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader,\n                                                long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateCharacterStream(this, resultSet, columnLabel, reader, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateCharacterStream(columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateBlob(ResultSetProxy resultSet, int columnIndex, InputStream inputStream, long length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBlob(this, resultSet, columnIndex, inputStream, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBlob(columnIndex, inputStream, length);\n    }\n\n    @Override\n    public void resultSet_updateBlob(ResultSetProxy resultSet, String columnLabel, InputStream inputStream, long length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBlob(this, resultSet, columnLabel, inputStream, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBlob(columnLabel, inputStream, length);\n    }\n\n    @Override\n    public void resultSet_updateClob(ResultSetProxy resultSet, int columnIndex, Reader reader, long length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateClob(this, resultSet, columnIndex, reader, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateClob(columnIndex, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateClob(ResultSetProxy resultSet, String columnLabel, Reader reader, long length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateClob(this, resultSet, columnLabel, reader, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateClob(columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateNClob(ResultSetProxy resultSet, int columnIndex, Reader reader, long length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNClob(this, resultSet, columnIndex, reader, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNClob(columnIndex, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateNClob(ResultSetProxy resultSet, String columnLabel, Reader reader, long length)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNClob(this, resultSet, columnLabel, reader, length);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNClob(columnLabel, reader, length);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNCharacterStream(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNCharacterStream(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNCharacterStream(this, resultSet, columnLabel, reader);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNCharacterStream(columnLabel, reader);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateAsciiStream(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateAsciiStream(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(ResultSetProxy resultSet, int columnIndex, java.io.InputStream x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBinaryStream(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBinaryStream(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(ResultSetProxy resultSet, int columnIndex, java.io.Reader x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateCharacterStream(this, resultSet, columnIndex, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateCharacterStream(columnIndex, x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateAsciiStream(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateAsciiStream(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(ResultSetProxy resultSet, String columnLabel, java.io.InputStream x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBinaryStream(this, resultSet, columnLabel, x);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBinaryStream(columnLabel, x);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(ResultSetProxy resultSet, String columnLabel, java.io.Reader reader)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateCharacterStream(this, resultSet, columnLabel, reader);\n            return;\n        }\n        resultSet.getResultSetRaw().updateCharacterStream(columnLabel, reader);\n    }\n\n    @Override\n    public void resultSet_updateBlob(ResultSetProxy resultSet, int columnIndex, InputStream inputStream)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBlob(this, resultSet, columnIndex, inputStream);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBlob(columnIndex, inputStream);\n    }\n\n    @Override\n    public void resultSet_updateBlob(ResultSetProxy resultSet, String columnLabel, InputStream inputStream)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateBlob(this, resultSet, columnLabel, inputStream);\n            return;\n        }\n        resultSet.getResultSetRaw().updateBlob(columnLabel, inputStream);\n    }\n\n    @Override\n    public void resultSet_updateClob(ResultSetProxy resultSet, int columnIndex, Reader reader) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateClob(this, resultSet, columnIndex, reader);\n            return;\n        }\n        resultSet.getResultSetRaw().updateClob(columnIndex, reader);\n    }\n\n    @Override\n    public void resultSet_updateClob(ResultSetProxy resultSet, String columnLabel, Reader reader) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateClob(this, resultSet, columnLabel, reader);\n            return;\n        }\n        resultSet.getResultSetRaw().updateClob(columnLabel, reader);\n    }\n\n    @Override\n    public void resultSet_updateNClob(ResultSetProxy resultSet, int columnIndex, Reader reader) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNClob(this, resultSet, columnIndex, reader);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNClob(columnIndex, reader);\n    }\n\n    @Override\n    public void resultSet_updateNClob(ResultSetProxy resultSet, String columnLabel, Reader reader) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().resultSet_updateNClob(this, resultSet, columnLabel, reader);\n            return;\n        }\n        resultSet.getResultSetRaw().updateNClob(columnLabel, reader);\n    }\n\n    // //////////////////////////////////////// statement\n    @Override\n    public ResultSetProxy statement_executeQuery(StatementProxy statement, String sql) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_executeQuery(this, statement, sql);\n        }\n\n        ResultSet resultSet = statement.getRawObject().executeQuery(sql);\n\n        if (resultSet == null) {\n            return null;\n        }\n\n        return new ResultSetProxyImpl(statement, resultSet, dataSource.createResultSetId(),\n                statement.getLastExecuteSql());\n    }\n\n    @Override\n    public int statement_executeUpdate(StatementProxy statement, String sql) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_executeUpdate(this, statement, sql);\n        }\n        return statement.getRawObject().executeUpdate(sql);\n    }\n\n    @Override\n    public void statement_close(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_close(this, statement);\n            return;\n        }\n        statement.getRawObject().close();\n    }\n\n    @Override\n    public int statement_getMaxFieldSize(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getMaxFieldSize(this, statement);\n        }\n        return statement.getRawObject().getMaxFieldSize();\n    }\n\n    @Override\n    public void statement_setMaxFieldSize(StatementProxy statement, int max) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setMaxFieldSize(this, statement, max);\n            return;\n        }\n        statement.getRawObject().setMaxFieldSize(max);\n    }\n\n    @Override\n    public int statement_getMaxRows(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getMaxRows(this, statement);\n        }\n        return statement.getRawObject().getMaxRows();\n    }\n\n    @Override\n    public void statement_setMaxRows(StatementProxy statement, int max) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setMaxRows(this, statement, max);\n            return;\n        }\n        statement.getRawObject().setMaxRows(max);\n    }\n\n    @Override\n    public void statement_setEscapeProcessing(StatementProxy statement, boolean enable) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setEscapeProcessing(this, statement, enable);\n            return;\n        }\n        statement.getRawObject().setEscapeProcessing(enable);\n    }\n\n    @Override\n    public int statement_getQueryTimeout(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getQueryTimeout(this, statement);\n        }\n        return statement.getRawObject().getQueryTimeout();\n    }\n\n    @Override\n    public void statement_setQueryTimeout(StatementProxy statement, int seconds) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setQueryTimeout(this, statement, seconds);\n            return;\n        }\n        statement.getRawObject().setQueryTimeout(seconds);\n    }\n\n    @Override\n    public void statement_cancel(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_cancel(this, statement);\n            return;\n        }\n        statement.getRawObject().cancel();\n    }\n\n    @Override\n    public SQLWarning statement_getWarnings(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getWarnings(this, statement);\n        }\n        return statement.getRawObject().getWarnings();\n    }\n\n    @Override\n    public void statement_clearWarnings(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_clearWarnings(this, statement);\n            return;\n        }\n        statement.getRawObject().clearWarnings();\n    }\n\n    @Override\n    public void statement_setCursorName(StatementProxy statement, String name) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setCursorName(this, statement, name);\n            return;\n        }\n        statement.getRawObject().setCursorName(name);\n    }\n\n    @Override\n    public boolean statement_execute(StatementProxy statement, String sql) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_execute(this, statement, sql);\n        }\n        return statement.getRawObject().execute(sql);\n    }\n\n    @Override\n    public ResultSetProxy statement_getResultSet(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getResultSet(this, statement);\n        }\n\n        ResultSet resultSet = statement.getRawObject().getResultSet();\n\n        if (resultSet == null) {\n            return null;\n        }\n\n        return new ResultSetProxyImpl(statement, resultSet, dataSource.createResultSetId(),\n                statement.getLastExecuteSql());\n    }\n\n    @Override\n    public int statement_getUpdateCount(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getUpdateCount(this, statement);\n        }\n        return statement.getRawObject().getUpdateCount();\n    }\n\n    @Override\n    public boolean statement_getMoreResults(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getMoreResults(this, statement);\n        }\n        return statement.getRawObject().getMoreResults();\n    }\n\n    @Override\n    public void statement_setFetchDirection(StatementProxy statement, int direction) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setFetchDirection(this, statement, direction);\n            return;\n        }\n        statement.getRawObject().setFetchDirection(direction);\n    }\n\n    @Override\n    public int statement_getFetchDirection(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getFetchDirection(this, statement);\n        }\n        return statement.getRawObject().getFetchDirection();\n    }\n\n    @Override\n    public void statement_setFetchSize(StatementProxy statement, int rows) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setFetchSize(this, statement, rows);\n            return;\n        }\n        statement.getRawObject().setFetchSize(rows);\n    }\n\n    @Override\n    public int statement_getFetchSize(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getFetchSize(this, statement);\n        }\n        return statement.getRawObject().getFetchSize();\n    }\n\n    @Override\n    public int statement_getResultSetConcurrency(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getResultSetConcurrency(this, statement);\n        }\n        return statement.getRawObject().getResultSetConcurrency();\n    }\n\n    @Override\n    public int statement_getResultSetType(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getResultSetType(this, statement);\n        }\n        return statement.getRawObject().getResultSetType();\n    }\n\n    @Override\n    public void statement_addBatch(StatementProxy statement, String sql) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_addBatch(this, statement, sql);\n            return;\n        }\n        statement.getRawObject().addBatch(sql);\n    }\n\n    @Override\n    public void statement_clearBatch(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_clearBatch(this, statement);\n            return;\n        }\n        statement.getRawObject().clearBatch();\n    }\n\n    @Override\n    public int[] statement_executeBatch(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_executeBatch(this, statement);\n        }\n        return statement.getRawObject().executeBatch();\n    }\n\n    @Override\n    public Connection statement_getConnection(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getConnection(this, statement);\n        }\n        return statement.getRawObject().getConnection();\n    }\n\n    @Override\n    public boolean statement_getMoreResults(StatementProxy statement, int current) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getMoreResults(this, statement, current);\n        }\n        return statement.getRawObject().getMoreResults(current);\n    }\n\n    @Override\n    public ResultSetProxy statement_getGeneratedKeys(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getGeneratedKeys(this, statement);\n        }\n\n        ResultSet resultSet = statement.getRawObject().getGeneratedKeys();\n        if (resultSet == null) {\n            return null;\n        }\n        return new ResultSetProxyImpl(statement, resultSet, dataSource.createResultSetId(),\n                statement.getLastExecuteSql());\n    }\n\n    @Override\n    public int statement_executeUpdate(StatementProxy statement,\n                                       String sql,\n                                       int autoGeneratedKeys) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_executeUpdate(this, statement, sql, autoGeneratedKeys);\n        }\n        return statement.getRawObject().executeUpdate(sql, autoGeneratedKeys);\n    }\n\n    @Override\n    public int statement_executeUpdate(StatementProxy statement, String sql, int[] columnIndexes) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_executeUpdate(this, statement, sql, columnIndexes);\n        }\n        return statement.getRawObject().executeUpdate(sql, columnIndexes);\n    }\n\n    @Override\n    public int statement_executeUpdate(StatementProxy statement, String sql, String[] columnNames) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_executeUpdate(this, statement, sql, columnNames);\n        }\n        return statement.getRawObject().executeUpdate(sql, columnNames);\n    }\n\n    @Override\n    public boolean statement_execute(StatementProxy statement, String sql, int autoGeneratedKeys) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_execute(this, statement, sql, autoGeneratedKeys);\n        }\n        return statement.getRawObject().execute(sql, autoGeneratedKeys);\n    }\n\n    @Override\n    public boolean statement_execute(StatementProxy statement, String sql, int[] columnIndexes) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_execute(this, statement, sql, columnIndexes);\n        }\n        return statement.getRawObject().execute(sql, columnIndexes);\n    }\n\n    @Override\n    public boolean statement_execute(StatementProxy statement, String sql, String[] columnNames) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_execute(this, statement, sql, columnNames);\n        }\n        return statement.getRawObject().execute(sql, columnNames);\n    }\n\n    @Override\n    public int statement_getResultSetHoldability(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_getResultSetHoldability(this, statement);\n        }\n        return statement.getRawObject().getResultSetHoldability();\n    }\n\n    @Override\n    public boolean statement_isClosed(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_isClosed(this, statement);\n        }\n        return statement.getRawObject().isClosed();\n    }\n\n    @Override\n    public void statement_setPoolable(StatementProxy statement, boolean poolable) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().statement_setPoolable(this, statement, poolable);\n            return;\n        }\n        statement.getRawObject().setPoolable(poolable);\n    }\n\n    @Override\n    public boolean statement_isPoolable(StatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().statement_isPoolable(this, statement);\n        }\n        return statement.getRawObject().isPoolable();\n    }\n\n    // ////////////////\n\n    @Override\n    public ResultSetProxy preparedStatement_executeQuery(PreparedStatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().preparedStatement_executeQuery(this, statement);\n        }\n\n        ResultSet resultSet = statement.getRawObject().executeQuery();\n        if (resultSet == null) {\n            return null;\n        }\n        return new ResultSetProxyImpl(statement, resultSet, dataSource.createResultSetId(),\n                statement.getLastExecuteSql());\n    }\n\n    @Override\n    public int preparedStatement_executeUpdate(PreparedStatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().preparedStatement_executeUpdate(this, statement);\n        }\n        return statement.getRawObject().executeUpdate();\n    }\n\n    @Override\n    public void preparedStatement_setNull(PreparedStatementProxy statement, int parameterIndex, int sqlType)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNull(this, statement, parameterIndex, sqlType);\n            return;\n        }\n        statement.getRawObject().setNull(parameterIndex, sqlType);\n    }\n\n    @Override\n    public void preparedStatement_setBoolean(PreparedStatementProxy statement, int parameterIndex, boolean x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBoolean(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setBoolean(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setByte(PreparedStatementProxy statement, int parameterIndex, byte x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setByte(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setByte(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setShort(PreparedStatementProxy statement, int parameterIndex, short x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setShort(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setShort(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setInt(PreparedStatementProxy statement, int parameterIndex, int x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setInt(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setInt(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setLong(PreparedStatementProxy statement, int parameterIndex, long x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setLong(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setLong(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setFloat(PreparedStatementProxy statement, int parameterIndex, float x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setFloat(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setFloat(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setDouble(PreparedStatementProxy statement, int parameterIndex, double x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setDouble(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setDouble(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBigDecimal(PreparedStatementProxy statement, int parameterIndex, BigDecimal x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBigDecimal(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setBigDecimal(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setString(PreparedStatementProxy statement, int parameterIndex, String x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setString(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setString(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBytes(PreparedStatementProxy statement, int parameterIndex, byte[] x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBytes(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setBytes(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setDate(PreparedStatementProxy statement, int parameterIndex, java.sql.Date x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setDate(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setDate(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setTime(PreparedStatementProxy statement, int parameterIndex, java.sql.Time x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setTime(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setTime(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setTimestamp(PreparedStatementProxy statement, int parameterIndex,\n                                               java.sql.Timestamp x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setTimestamp(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setTimestamp(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setAsciiStream(PreparedStatementProxy statement, int parameterIndex,\n                                                 java.io.InputStream x, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setAsciiStream(this, statement, parameterIndex, x, length);\n            return;\n        }\n        statement.getRawObject().setAsciiStream(parameterIndex, x, length);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public void preparedStatement_setUnicodeStream(PreparedStatementProxy statement, int parameterIndex,\n                                                   java.io.InputStream x, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setUnicodeStream(this, statement, parameterIndex, x, length);\n            return;\n        }\n        statement.getRawObject().setUnicodeStream(parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setBinaryStream(PreparedStatementProxy statement, int parameterIndex,\n                                                  java.io.InputStream x, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBinaryStream(this, statement, parameterIndex, x, length);\n            return;\n        }\n        statement.getRawObject().setBinaryStream(parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_clearParameters(PreparedStatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_clearParameters(this, statement);\n            return;\n        }\n        statement.getRawObject().clearParameters();\n    }\n\n    @Override\n    public void preparedStatement_setObject(PreparedStatementProxy statement, int parameterIndex, Object x,\n                                            int targetSqlType) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setObject(this, statement, parameterIndex, x, targetSqlType);\n            return;\n        }\n        statement.getRawObject().setObject(parameterIndex, x, targetSqlType);\n    }\n\n    @Override\n    public void preparedStatement_setObject(PreparedStatementProxy statement, int parameterIndex, Object x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setObject(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setObject(parameterIndex, x);\n    }\n\n    @Override\n    public boolean preparedStatement_execute(PreparedStatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().preparedStatement_execute(this, statement);\n        }\n        return statement.getRawObject().execute();\n    }\n\n    @Override\n    public void preparedStatement_addBatch(PreparedStatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_addBatch(this, statement);\n            return;\n        }\n        statement.getRawObject().addBatch();\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(PreparedStatementProxy statement, int parameterIndex,\n                                                     java.io.Reader reader, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setCharacterStream(this, statement, parameterIndex, reader, length);\n            return;\n        }\n        statement.getRawObject().setCharacterStream(parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setRef(PreparedStatementProxy statement, int parameterIndex, Ref x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setRef(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setRef(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBlob(PreparedStatementProxy statement, int parameterIndex, Blob x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBlob(this, statement, parameterIndex, x);\n            return;\n        }\n\n        statement.getRawObject()\n                .setBlob(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setClob(PreparedStatementProxy statement, int parameterIndex, Clob x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setClob(this, statement, parameterIndex, x);\n            return;\n        }\n\n        if (x instanceof ClobProxy) {\n            x = ((ClobProxy) x).getRawClob();\n        }\n\n        statement.getRawObject()\n                .setClob(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setArray(PreparedStatementProxy statement, int parameterIndex, Array x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setArray(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setArray(parameterIndex, x);\n    }\n\n    @Override\n    public ResultSetMetaData preparedStatement_getMetaData(PreparedStatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().preparedStatement_getMetaData(this, statement);\n        }\n        return statement.getRawObject().getMetaData();\n    }\n\n    @Override\n    public void preparedStatement_setDate(PreparedStatementProxy statement, int parameterIndex, java.sql.Date x,\n                                          Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setDate(this, statement, parameterIndex, x, cal);\n            return;\n        }\n        statement.getRawObject().setDate(parameterIndex, x, cal);\n    }\n\n    @Override\n    public void preparedStatement_setTime(PreparedStatementProxy statement, int parameterIndex, java.sql.Time x,\n                                          Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setTime(this, statement, parameterIndex, x, cal);\n            return;\n        }\n        statement.getRawObject().setTime(parameterIndex, x, cal);\n    }\n\n    @Override\n    public void preparedStatement_setTimestamp(PreparedStatementProxy statement, int parameterIndex,\n                                               java.sql.Timestamp x, Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setTimestamp(this, statement, parameterIndex, x, cal);\n            return;\n        }\n        statement.getRawObject().setTimestamp(parameterIndex, x, cal);\n    }\n\n    @Override\n    public void preparedStatement_setNull(PreparedStatementProxy statement, int parameterIndex, int sqlType,\n                                          String typeName) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNull(this, statement, parameterIndex, sqlType, typeName);\n            return;\n        }\n        statement.getRawObject().setNull(parameterIndex, sqlType, typeName);\n    }\n\n    @Override\n    public void preparedStatement_setURL(PreparedStatementProxy statement, int parameterIndex, java.net.URL x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setURL(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setURL(parameterIndex, x);\n    }\n\n    @Override\n    public ParameterMetaData preparedStatement_getParameterMetaData(PreparedStatementProxy statement)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().preparedStatement_getParameterMetaData(this, statement);\n        }\n        return statement.getRawObject().getParameterMetaData();\n    }\n\n    @Override\n    public void preparedStatement_setRowId(PreparedStatementProxy statement, int parameterIndex, RowId x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setRowId(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setRowId(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setNString(PreparedStatementProxy statement, int parameterIndex, String value)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNString(this, statement, parameterIndex, value);\n            return;\n        }\n        statement.getRawObject().setNString(parameterIndex, value);\n    }\n\n    @Override\n    public void preparedStatement_setNCharacterStream(PreparedStatementProxy statement, int parameterIndex,\n                                                      Reader value, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNCharacterStream(this, statement, parameterIndex, value, length);\n            return;\n        }\n        statement.getRawObject().setNCharacterStream(parameterIndex, value, length);\n    }\n\n    @Override\n    public void preparedStatement_setNClob(PreparedStatementProxy statement, int parameterIndex, NClob x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNClob(this, statement, parameterIndex, x);\n            return;\n        }\n\n        if (x instanceof NClobProxy) {\n            x = ((NClobProxy) x).getRawNClob();\n        }\n\n        statement.getRawObject()\n                .setNClob(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setClob(PreparedStatementProxy statement, int parameterIndex, Reader reader,\n                                          long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setClob(this, statement, parameterIndex, reader, length);\n            return;\n        }\n        statement.getRawObject().setClob(parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setBlob(PreparedStatementProxy statement, int parameterIndex,\n                                          InputStream inputStream, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBlob(this, statement, parameterIndex, inputStream, length);\n            return;\n        }\n        statement.getRawObject().setBlob(parameterIndex, inputStream, length);\n    }\n\n    @Override\n    public void preparedStatement_setNClob(PreparedStatementProxy statement, int parameterIndex, Reader reader,\n                                           long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNClob(this, statement, parameterIndex, reader, length);\n            return;\n        }\n        statement.getRawObject().setNClob(parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setSQLXML(PreparedStatementProxy statement, int parameterIndex, SQLXML xmlObject)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setSQLXML(this, statement, parameterIndex, xmlObject);\n            return;\n        }\n        statement.getRawObject().setSQLXML(parameterIndex, xmlObject);\n    }\n\n    @Override\n    public void preparedStatement_setObject(PreparedStatementProxy statement, int parameterIndex, Object x,\n                                            int targetSqlType, int scaleOrLength) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setObject(this, statement, parameterIndex, x, targetSqlType, scaleOrLength);\n            return;\n        }\n        statement.getRawObject().setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n    }\n\n    @Override\n    public void preparedStatement_setAsciiStream(PreparedStatementProxy statement, int parameterIndex,\n                                                 java.io.InputStream x, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setAsciiStream(this, statement, parameterIndex, x, length);\n            return;\n        }\n        statement.getRawObject().setAsciiStream(parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setBinaryStream(PreparedStatementProxy statement, int parameterIndex,\n                                                  java.io.InputStream x, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBinaryStream(this, statement, parameterIndex, x, length);\n            return;\n        }\n        statement.getRawObject().setBinaryStream(parameterIndex, x, length);\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(PreparedStatementProxy statement, int parameterIndex,\n                                                     java.io.Reader reader, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setCharacterStream(this, statement, parameterIndex, reader, length);\n            return;\n        }\n        statement.getRawObject().setCharacterStream(parameterIndex, reader, length);\n    }\n\n    @Override\n    public void preparedStatement_setAsciiStream(PreparedStatementProxy statement, int parameterIndex,\n                                                 java.io.InputStream x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setAsciiStream(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setAsciiStream(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setBinaryStream(PreparedStatementProxy statement, int parameterIndex,\n                                                  java.io.InputStream x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBinaryStream(this, statement, parameterIndex, x);\n            return;\n        }\n        statement.getRawObject().setBinaryStream(parameterIndex, x);\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(PreparedStatementProxy statement, int parameterIndex,\n                                                     java.io.Reader reader) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setCharacterStream(this, statement, parameterIndex, reader);\n            return;\n        }\n        statement.getRawObject().setCharacterStream(parameterIndex, reader);\n    }\n\n    @Override\n    public void preparedStatement_setNCharacterStream(PreparedStatementProxy statement,\n                                                      int parameterIndex,\n                                                      Reader value)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNCharacterStream(this, statement, parameterIndex, value);\n            return;\n        }\n        statement.getRawObject().setNCharacterStream(parameterIndex, value);\n    }\n\n    @Override\n    public void preparedStatement_setClob(PreparedStatementProxy statement, int parameterIndex, Reader reader)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setClob(this, statement, parameterIndex, reader);\n            return;\n        }\n        statement.getRawObject().setClob(parameterIndex, reader);\n    }\n\n    @Override\n    public void preparedStatement_setBlob(PreparedStatementProxy statement, int parameterIndex, InputStream inputStream)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setBlob(this, statement, parameterIndex, inputStream);\n            return;\n        }\n        statement.getRawObject().setBlob(parameterIndex, inputStream);\n    }\n\n    @Override\n    public void preparedStatement_setNClob(PreparedStatementProxy statement, int parameterIndex, Reader reader)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().preparedStatement_setNClob(this, statement, parameterIndex, reader);\n            return;\n        }\n        statement.getRawObject().setNClob(parameterIndex, reader);\n    }\n\n    // /////////////////////////////////////\n\n    @Override\n    public void callableStatement_registerOutParameter(CallableStatementProxy statement,\n                                                       int parameterIndex,\n                                                       int sqlType)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_registerOutParameter(this, statement, parameterIndex, sqlType);\n            return;\n        }\n        statement.getRawObject().registerOutParameter(parameterIndex, sqlType);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(CallableStatementProxy statement, int parameterIndex,\n                                                       int sqlType, int scale) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_registerOutParameter(this, statement, parameterIndex, sqlType, scale);\n            return;\n        }\n        statement.getRawObject().registerOutParameter(parameterIndex, sqlType, scale);\n    }\n\n    @Override\n    public boolean callableStatement_wasNull(CallableStatementProxy statement) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_wasNull(this, statement);\n        }\n        return statement.getRawObject().wasNull();\n    }\n\n    @Override\n    public String callableStatement_getString(CallableStatementProxy statement,\n                                              int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getString(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getString(parameterIndex);\n    }\n\n    @Override\n    public boolean callableStatement_getBoolean(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBoolean(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getBoolean(parameterIndex);\n    }\n\n    @Override\n    public byte callableStatement_getByte(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getByte(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getByte(parameterIndex);\n    }\n\n    @Override\n    public short callableStatement_getShort(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getShort(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getShort(parameterIndex);\n    }\n\n    @Override\n    public int callableStatement_getInt(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getInt(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getInt(parameterIndex);\n    }\n\n    @Override\n    public long callableStatement_getLong(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getLong(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getLong(parameterIndex);\n    }\n\n    @Override\n    public float callableStatement_getFloat(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getFloat(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getFloat(parameterIndex);\n    }\n\n    @Override\n    public double callableStatement_getDouble(CallableStatementProxy statement,\n                                              int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getDouble(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getDouble(parameterIndex);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public BigDecimal callableStatement_getBigDecimal(CallableStatementProxy statement, int parameterIndex, int scale)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBigDecimal(this, statement, parameterIndex, scale);\n        }\n        return statement.getRawObject().getBigDecimal(parameterIndex, scale);\n    }\n\n    @Override\n    public byte[] callableStatement_getBytes(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBytes(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getBytes(parameterIndex);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getDate(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getDate(parameterIndex);\n    }\n\n    @Override\n    public java.sql.Time callableStatement_getTime(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTime(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getTime(parameterIndex);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTimestamp(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getTimestamp(parameterIndex);\n    }\n\n    @Override\n    public Object callableStatement_getObject(CallableStatementProxy statement,\n                                              int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getObject(this, statement, parameterIndex);\n        }\n\n        Object obj = statement.getRawObject().getObject(parameterIndex);\n\n        if (obj instanceof ResultSet) {\n            return new ResultSetProxyImpl(statement, (ResultSet) obj, dataSource.createResultSetId(),\n                    statement.getLastExecuteSql());\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(statement, (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(CallableStatementProxy statement, int parameterIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getObject(this, statement, parameterIndex, map);\n        }\n\n        Object obj = statement.getRawObject().getObject(parameterIndex, map);\n\n        if (obj instanceof ResultSet) {\n            return new ResultSetProxyImpl(statement, (ResultSet) obj, dataSource.createResultSetId(),\n                    statement.getLastExecuteSql());\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(statement, (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getObject(this, statement, parameterName);\n        }\n\n        Object obj = statement.getRawObject().getObject(parameterName);\n\n        if (obj instanceof ResultSet) {\n            return new ResultSetProxyImpl(statement, (ResultSet) obj, dataSource.createResultSetId(),\n                    statement.getLastExecuteSql());\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(statement, (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(CallableStatementProxy statement, String parameterName,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getObject(this, statement, parameterName, map);\n        }\n\n        Object obj = statement.getRawObject().getObject(parameterName, map);\n\n        if (obj instanceof ResultSet) {\n            return new ResultSetProxyImpl(statement, (ResultSet) obj, dataSource.createResultSetId(),\n                    statement.getLastExecuteSql());\n        }\n\n        if (obj instanceof Clob) {\n            return wrap(statement, (Clob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public BigDecimal callableStatement_getBigDecimal(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBigDecimal(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getBigDecimal(parameterIndex);\n    }\n\n    @Override\n    public Ref callableStatement_getRef(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getRef(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getRef(parameterIndex);\n    }\n\n    @Override\n    public Blob callableStatement_getBlob(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBlob(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getBlob(parameterIndex);\n    }\n\n    @Override\n    public Clob callableStatement_getClob(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getClob(this, statement, parameterIndex);\n        }\n\n        Clob clob = statement.getRawObject()\n                .getClob(parameterIndex);\n\n        return wrap(statement, clob);\n    }\n\n    @Override\n    public Array callableStatement_getArray(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getArray(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getArray(parameterIndex);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(CallableStatementProxy statement, int parameterIndex, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getDate(this, statement, parameterIndex, cal);\n        }\n        return statement.getRawObject().getDate(parameterIndex, cal);\n    }\n\n    @Override\n    public java.sql.Time callableStatement_getTime(CallableStatementProxy statement, int parameterIndex, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTime(this, statement, parameterIndex, cal);\n        }\n        return statement.getRawObject().getTime(parameterIndex, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement, int parameterIndex,\n                                                             Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTimestamp(this, statement, parameterIndex, cal);\n        }\n        return statement.getRawObject().getTimestamp(parameterIndex, cal);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(CallableStatementProxy statement, int parameterIndex,\n                                                       int sqlType, String typeName) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_registerOutParameter(this, statement, parameterIndex, sqlType, typeName);\n            return;\n        }\n        statement.getRawObject().registerOutParameter(parameterIndex, sqlType, typeName);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(CallableStatementProxy statement, String parameterName,\n                                                       int sqlType) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_registerOutParameter(this, statement, parameterName, sqlType);\n            return;\n        }\n        statement.getRawObject().registerOutParameter(parameterName, sqlType);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(CallableStatementProxy statement, String parameterName,\n                                                       int sqlType, int scale) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_registerOutParameter(this, statement, parameterName, sqlType, scale);\n            return;\n        }\n        statement.getRawObject().registerOutParameter(parameterName, sqlType, scale);\n    }\n\n    @Override\n    public void callableStatement_registerOutParameter(CallableStatementProxy statement, String parameterName,\n                                                       int sqlType, String typeName) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_registerOutParameter(this, statement, parameterName, sqlType, typeName);\n            return;\n        }\n        statement.getRawObject().registerOutParameter(parameterName, sqlType, typeName);\n    }\n\n    @Override\n    public java.net.URL callableStatement_getURL(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getURL(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getURL(parameterIndex);\n    }\n\n    @Override\n    public void callableStatement_setURL(CallableStatementProxy statement, String parameterName, java.net.URL val)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setURL(this, statement, parameterName, val);\n            return;\n        }\n        statement.getRawObject().setURL(parameterName, val);\n    }\n\n    @Override\n    public void callableStatement_setNull(CallableStatementProxy statement, String parameterName, int sqlType)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNull(this, statement, parameterName, sqlType);\n            return;\n        }\n        statement.getRawObject().setNull(parameterName, sqlType);\n    }\n\n    @Override\n    public void callableStatement_setBoolean(CallableStatementProxy statement, String parameterName, boolean x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBoolean(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setBoolean(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setByte(CallableStatementProxy statement, String parameterName, byte x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setByte(this, statement, parameterName, x);\n        }\n        statement.getRawObject().setByte(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setShort(CallableStatementProxy statement, String parameterName, short x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setShort(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setShort(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setInt(CallableStatementProxy statement, String parameterName, int x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setInt(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setInt(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setLong(CallableStatementProxy statement, String parameterName, long x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setLong(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setLong(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setFloat(CallableStatementProxy statement, String parameterName, float x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setFloat(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setFloat(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setDouble(CallableStatementProxy statement, String parameterName, double x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setDouble(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setDouble(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setBigDecimal(CallableStatementProxy statement, String parameterName, BigDecimal x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBigDecimal(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setBigDecimal(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setString(CallableStatementProxy statement, String parameterName, String x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setString(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setString(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setBytes(CallableStatementProxy statement, String parameterName, byte[] x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBytes(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setBytes(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setDate(CallableStatementProxy statement, String parameterName, java.sql.Date x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setDate(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setDate(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setTime(CallableStatementProxy statement, String parameterName, java.sql.Time x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setTime(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setTime(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setTimestamp(CallableStatementProxy statement, String parameterName,\n                                               java.sql.Timestamp x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setTimestamp(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setTimestamp(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setAsciiStream(CallableStatementProxy statement, String parameterName,\n                                                 java.io.InputStream x, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setAsciiStream(this, statement, parameterName, x, length);\n            return;\n        }\n        statement.getRawObject().setAsciiStream(parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setBinaryStream(CallableStatementProxy statement, String parameterName,\n                                                  java.io.InputStream x, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBinaryStream(this, statement, parameterName, x, length);\n            return;\n        }\n        statement.getRawObject().setBinaryStream(parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setObject(CallableStatementProxy statement, String parameterName, Object x,\n                                            int targetSqlType, int scale) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setObject(this, statement, parameterName, x, targetSqlType, scale);\n            return;\n        }\n        statement.getRawObject().setObject(parameterName, x, targetSqlType, scale);\n    }\n\n    @Override\n    public void callableStatement_setObject(CallableStatementProxy statement, String parameterName, Object x,\n                                            int targetSqlType) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setObject(this, statement, parameterName, x, targetSqlType);\n            return;\n        }\n        statement.getRawObject().setObject(parameterName, x, targetSqlType);\n    }\n\n    @Override\n    public void callableStatement_setObject(CallableStatementProxy statement, String parameterName, Object x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setObject(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setObject(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(CallableStatementProxy statement, String parameterName,\n                                                     java.io.Reader reader, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setCharacterStream(this, statement, parameterName, reader, length);\n            return;\n        }\n        statement.getRawObject().setCharacterStream(parameterName, reader, length);\n    }\n\n    @Override\n    public void callableStatement_setDate(CallableStatementProxy statement, String parameterName, java.sql.Date x,\n                                          Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setDate(this, statement, parameterName, x, cal);\n            return;\n        }\n        statement.getRawObject().setDate(parameterName, x, cal);\n    }\n\n    @Override\n    public void callableStatement_setTime(CallableStatementProxy statement, String parameterName, java.sql.Time x,\n                                          Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setTime(this, statement, parameterName, x, cal);\n            return;\n        }\n        statement.getRawObject().setTime(parameterName, x, cal);\n    }\n\n    @Override\n    public void callableStatement_setTimestamp(CallableStatementProxy statement, String parameterName,\n                                               java.sql.Timestamp x, Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setTimestamp(this, statement, parameterName, x, cal);\n            return;\n        }\n        statement.getRawObject().setTimestamp(parameterName, x, cal);\n    }\n\n    @Override\n    public void callableStatement_setNull(CallableStatementProxy statement, String parameterName, int sqlType,\n                                          String typeName) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNull(this, statement, parameterName, sqlType, typeName);\n            return;\n        }\n        statement.getRawObject().setNull(parameterName, sqlType, typeName);\n    }\n\n    @Override\n    public String callableStatement_getString(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getString(this, statement, parameterName);\n        }\n        return statement.getRawObject().getString(parameterName);\n    }\n\n    @Override\n    public boolean callableStatement_getBoolean(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBoolean(this, statement, parameterName);\n        }\n        return statement.getRawObject().getBoolean(parameterName);\n    }\n\n    @Override\n    public byte callableStatement_getByte(CallableStatementProxy statement, String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getByte(this, statement, parameterName);\n        }\n        return statement.getRawObject().getByte(parameterName);\n    }\n\n    @Override\n    public short callableStatement_getShort(CallableStatementProxy statement,\n                                            String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getShort(this, statement, parameterName);\n        }\n        return statement.getRawObject().getShort(parameterName);\n    }\n\n    @Override\n    public int callableStatement_getInt(CallableStatementProxy statement, String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getInt(this, statement, parameterName);\n        }\n        return statement.getRawObject().getInt(parameterName);\n    }\n\n    @Override\n    public long callableStatement_getLong(CallableStatementProxy statement, String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getLong(this, statement, parameterName);\n        }\n        return statement.getRawObject().getLong(parameterName);\n    }\n\n    @Override\n    public float callableStatement_getFloat(CallableStatementProxy statement,\n                                            String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getFloat(this, statement, parameterName);\n        }\n        return statement.getRawObject().getFloat(parameterName);\n    }\n\n    @Override\n    public double callableStatement_getDouble(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getDouble(this, statement, parameterName);\n        }\n        return statement.getRawObject().getDouble(parameterName);\n    }\n\n    @Override\n    public byte[] callableStatement_getBytes(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBytes(this, statement, parameterName);\n        }\n        return statement.getRawObject().getBytes(parameterName);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getDate(this, statement, parameterName);\n        }\n        return statement.getRawObject().getDate(parameterName);\n    }\n\n    @Override\n    public java.sql.Time callableStatement_getTime(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTime(this, statement, parameterName);\n        }\n        return statement.getRawObject().getTime(parameterName);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTimestamp(this, statement, parameterName);\n        }\n        return statement.getRawObject().getTimestamp(parameterName);\n    }\n\n    @Override\n    public BigDecimal callableStatement_getBigDecimal(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBigDecimal(this, statement, parameterName);\n        }\n        return statement.getRawObject().getBigDecimal(parameterName);\n    }\n\n    @Override\n    public Ref callableStatement_getRef(CallableStatementProxy statement, String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getRef(this, statement, parameterName);\n        }\n        return statement.getRawObject().getRef(parameterName);\n    }\n\n    @Override\n    public Blob callableStatement_getBlob(CallableStatementProxy statement, String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getBlob(this, statement, parameterName);\n        }\n        return statement.getRawObject().getBlob(parameterName);\n    }\n\n    @Override\n    public Clob callableStatement_getClob(CallableStatementProxy statement, String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getClob(this, statement, parameterName);\n        }\n\n        Clob clob = statement.getRawObject()\n                .getClob(parameterName);\n\n        return wrap(statement, clob);\n    }\n\n    @Override\n    public Array callableStatement_getArray(CallableStatementProxy statement,\n                                            String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getArray(this, statement, parameterName);\n        }\n        return statement.getRawObject().getArray(parameterName);\n    }\n\n    @Override\n    public java.sql.Date callableStatement_getDate(CallableStatementProxy statement, String parameterName, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getDate(this, statement, parameterName, cal);\n        }\n        return statement.getRawObject().getDate(parameterName, cal);\n    }\n\n    @Override\n    public java.sql.Time callableStatement_getTime(CallableStatementProxy statement, String parameterName, Calendar cal)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTime(this, statement, parameterName, cal);\n        }\n        return statement.getRawObject().getTime(parameterName, cal);\n    }\n\n    @Override\n    public java.sql.Timestamp callableStatement_getTimestamp(CallableStatementProxy statement, String parameterName,\n                                                             Calendar cal) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getTimestamp(this, statement, parameterName, cal);\n        }\n        return statement.getRawObject().getTimestamp(parameterName, cal);\n    }\n\n    @Override\n    public java.net.URL callableStatement_getURL(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getURL(this, statement, parameterName);\n        }\n        return statement.getRawObject().getURL(parameterName);\n    }\n\n    @Override\n    public RowId callableStatement_getRowId(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getRowId(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getRowId(parameterIndex);\n    }\n\n    @Override\n    public RowId callableStatement_getRowId(CallableStatementProxy statement,\n                                            String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getRowId(this, statement, parameterName);\n        }\n        return statement.getRawObject().getRowId(parameterName);\n    }\n\n    @Override\n    public void callableStatement_setRowId(CallableStatementProxy statement, String parameterName, RowId x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setRowId(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setRowId(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setNString(CallableStatementProxy statement, String parameterName, String value)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNString(this, statement, parameterName, value);\n            return;\n        }\n        statement.getRawObject().setNString(parameterName, value);\n    }\n\n    @Override\n    public void callableStatement_setNCharacterStream(CallableStatementProxy statement, String parameterName,\n                                                      Reader value, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNCharacterStream(this, statement, parameterName, value, length);\n            return;\n        }\n        statement.getRawObject().setNCharacterStream(parameterName, value, length);\n    }\n\n    @Override\n    public void callableStatement_setNClob(CallableStatementProxy statement, String parameterName, NClob x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNClob(this, statement, parameterName, x);\n            return;\n        }\n\n        if (x instanceof NClobProxy) {\n            x = ((NClobProxy) x).getRawNClob();\n        }\n\n        statement.getRawObject()\n                .setNClob(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setClob(CallableStatementProxy statement, String parameterName, Reader reader,\n                                          long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setClob(this, statement, parameterName, reader, length);\n            return;\n        }\n        statement.getRawObject().setClob(parameterName, reader, length);\n    }\n\n    @Override\n    public void callableStatement_setBlob(CallableStatementProxy statement, String parameterName,\n                                          InputStream inputStream, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBlob(this, statement, parameterName, inputStream, length);\n            return;\n        }\n        statement.getRawObject().setBlob(parameterName, inputStream, length);\n    }\n\n    @Override\n    public void callableStatement_setNClob(CallableStatementProxy statement, String parameterName, Reader reader,\n                                           long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNClob(this, statement, parameterName, reader, length);\n            return;\n        }\n        statement.getRawObject().setNClob(parameterName, reader, length);\n    }\n\n    @Override\n    public NClob callableStatement_getNClob(CallableStatementProxy statement, int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getNClob(this, statement, parameterIndex);\n        }\n\n        NClob nclob = statement.getRawObject()\n                .getNClob(parameterIndex);\n\n        return wrap(statement.getConnectionProxy(), nclob);\n    }\n\n    @Override\n    public NClob callableStatement_getNClob(CallableStatementProxy statement,\n                                            String parameterName) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getNClob(this, statement, parameterName);\n        }\n\n        NClob nclob = statement.getRawObject()\n                .getNClob(parameterName);\n\n        return wrap(statement.getConnectionProxy(), nclob);\n    }\n\n    @Override\n    public void callableStatement_setSQLXML(CallableStatementProxy statement, String parameterName, SQLXML xmlObject)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setSQLXML(this, statement, parameterName, xmlObject);\n            return;\n        }\n        statement.getRawObject().setSQLXML(parameterName, xmlObject);\n    }\n\n    @Override\n    public SQLXML callableStatement_getSQLXML(CallableStatementProxy statement,\n                                              int parameterIndex) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getSQLXML(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getSQLXML(parameterIndex);\n    }\n\n    @Override\n    public SQLXML callableStatement_getSQLXML(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getSQLXML(this, statement, parameterName);\n        }\n        return statement.getRawObject().getSQLXML(parameterName);\n    }\n\n    @Override\n    public String callableStatement_getNString(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getNString(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getNString(parameterIndex);\n    }\n\n    @Override\n    public String callableStatement_getNString(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getNString(this, statement, parameterName);\n        }\n        return statement.getRawObject().getNString(parameterName);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getNCharacterStream(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getNCharacterStream(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getNCharacterStream(parameterIndex);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getNCharacterStream(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getNCharacterStream(this, statement, parameterName);\n        }\n        return statement.getRawObject().getNCharacterStream(parameterName);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getCharacterStream(CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getCharacterStream(this, statement, parameterIndex);\n        }\n        return statement.getRawObject().getCharacterStream(parameterIndex);\n    }\n\n    @Override\n    public java.io.Reader callableStatement_getCharacterStream(CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().callableStatement_getCharacterStream(this, statement, parameterName);\n        }\n        return statement.getRawObject().getCharacterStream(parameterName);\n    }\n\n    @Override\n    public void callableStatement_setBlob(CallableStatementProxy statement, String parameterName, Blob x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBlob(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setBlob(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setClob(CallableStatementProxy statement, String parameterName, Clob x)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setClob(this, statement, parameterName, x);\n            return;\n        }\n\n        if (x instanceof ClobProxy) {\n            x = ((ClobProxy) x).getRawClob();\n        }\n\n        statement.getRawObject()\n                .setClob(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setAsciiStream(CallableStatementProxy statement, String parameterName,\n                                                 java.io.InputStream x, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setAsciiStream(this, statement, parameterName, x, length);\n            return;\n        }\n        statement.getRawObject().setAsciiStream(parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setBinaryStream(CallableStatementProxy statement, String parameterName,\n                                                  java.io.InputStream x, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBinaryStream(this, statement, parameterName, x, length);\n            return;\n        }\n        statement.getRawObject().setBinaryStream(parameterName, x, length);\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(CallableStatementProxy statement, String parameterName,\n                                                     java.io.Reader reader, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setCharacterStream(this, statement, parameterName, reader, length);\n            return;\n        }\n        statement.getRawObject().setCharacterStream(parameterName, reader, length);\n    }\n\n    @Override\n    public void callableStatement_setAsciiStream(CallableStatementProxy statement, String parameterName,\n                                                 java.io.InputStream x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setAsciiStream(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setAsciiStream(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setBinaryStream(CallableStatementProxy statement, String parameterName,\n                                                  java.io.InputStream x) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBinaryStream(this, statement, parameterName, x);\n            return;\n        }\n        statement.getRawObject().setBinaryStream(parameterName, x);\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(CallableStatementProxy statement, String parameterName,\n                                                     java.io.Reader reader) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setCharacterStream(this, statement, parameterName, reader);\n            return;\n        }\n        statement.getRawObject().setCharacterStream(parameterName, reader);\n    }\n\n    @Override\n    public void callableStatement_setNCharacterStream(CallableStatementProxy statement, String parameterName,\n                                                      Reader value) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNCharacterStream(this, statement, parameterName, value);\n            return;\n        }\n        statement.getRawObject().setNCharacterStream(parameterName, value);\n    }\n\n    @Override\n    public void callableStatement_setClob(CallableStatementProxy statement, String parameterName, Reader reader)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setClob(this, statement, parameterName, reader);\n            return;\n        }\n        statement.getRawObject().setClob(parameterName, reader);\n    }\n\n    @Override\n    public void callableStatement_setBlob(CallableStatementProxy statement, String parameterName,\n                                          InputStream inputStream) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setBlob(this, statement, parameterName, inputStream);\n            return;\n        }\n        statement.getRawObject().setBlob(parameterName, inputStream);\n    }\n\n    @Override\n    public void callableStatement_setNClob(CallableStatementProxy statement, String parameterName, Reader reader)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().callableStatement_setNClob(this, statement, parameterName, reader);\n            return;\n        }\n        statement.getRawObject().setNClob(parameterName, reader);\n    }\n\n    @Override\n    public long clob_length(ClobProxy clob) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_length(this, clob);\n        }\n        return clob.getRawClob().length();\n    }\n\n    @Override\n    public String clob_getSubString(ClobProxy clob, long pos, int length) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_getSubString(this, clob, pos, length);\n        }\n        return clob.getRawClob().getSubString(pos, length);\n    }\n\n    @Override\n    public java.io.Reader clob_getCharacterStream(ClobProxy clob) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_getCharacterStream(this, clob);\n        }\n        return clob.getRawClob().getCharacterStream();\n    }\n\n    @Override\n    public java.io.InputStream clob_getAsciiStream(ClobProxy clob) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_getAsciiStream(this, clob);\n        }\n        return clob.getRawClob().getAsciiStream();\n    }\n\n    @Override\n    public long clob_position(ClobProxy clob, String searchstr, long start) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_position(this, clob, searchstr, start);\n        }\n        return clob.getRawClob().position(searchstr, start);\n    }\n\n    @Override\n    public long clob_position(ClobProxy clob, Clob searchstr, long start) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_position(this, clob, searchstr, start);\n        }\n        return clob.getRawClob().position(searchstr, start);\n    }\n\n    @Override\n    public int clob_setString(ClobProxy clob, long pos, String str) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_setString(this, clob, pos, str);\n        }\n        return clob.getRawClob().setString(pos, str);\n    }\n\n    @Override\n    public int clob_setString(ClobProxy clob, long pos, String str, int offset, int len) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_setString(this, clob, pos, str, offset, len);\n        }\n        return clob.getRawClob().setString(pos, str, offset, len);\n    }\n\n    @Override\n    public java.io.OutputStream clob_setAsciiStream(ClobProxy clob, long pos) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_setAsciiStream(this, clob, pos);\n        }\n        return clob.getRawClob().setAsciiStream(pos);\n    }\n\n    @Override\n    public java.io.Writer clob_setCharacterStream(ClobProxy clob, long pos) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_setCharacterStream(this, clob, pos);\n        }\n        return clob.getRawClob().setCharacterStream(pos);\n    }\n\n    @Override\n    public void clob_truncate(ClobProxy clob, long len) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().clob_truncate(this, clob, len);\n            return;\n        }\n        clob.getRawClob().truncate(len);\n    }\n\n    @Override\n    public void clob_free(ClobProxy clob) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().clob_free(this, clob);\n            return;\n        }\n        clob.getRawClob().free();\n    }\n\n    @Override\n    public Reader clob_getCharacterStream(ClobProxy clob, long pos, long length) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().clob_getCharacterStream(this, clob, pos, length);\n        }\n        return clob.getRawClob().getCharacterStream(pos, length);\n    }\n\n    // ////////////\n\n    public ClobProxy wrap(ConnectionProxy conn, Clob clob) {\n        if (clob == null) {\n            return null;\n        }\n\n        if (clob instanceof NClob) {\n            return wrap(conn, (NClob) clob);\n        }\n\n        return new ClobProxyImpl(dataSource, conn, clob);\n    }\n\n    public NClobProxy wrap(ConnectionProxy conn, NClob clob) {\n        if (clob == null) {\n            return null;\n        }\n\n        return new NClobProxyImpl(dataSource, conn, clob);\n    }\n\n    public ClobProxy wrap(StatementProxy stmt, Clob clob) {\n        if (clob == null) {\n            return null;\n        }\n\n        if (clob instanceof NClob) {\n            return wrap(stmt, (NClob) clob);\n        }\n\n        return new ClobProxyImpl(dataSource, stmt.getConnectionProxy(), clob);\n    }\n\n    public NClobProxy wrap(StatementProxy stmt, NClob nclob) {\n        if (nclob == null) {\n            return null;\n        }\n\n        return new NClobProxyImpl(dataSource, stmt.getConnectionProxy(), nclob);\n    }\n\n    @Override\n    public void dataSource_recycle(DruidPooledConnection connection) throws SQLException {\n        if (this.pos < filterSize) {\n            nextFilter().dataSource_releaseConnection(this, connection);\n            return;\n        }\n\n        connection.recycle();\n    }\n\n    @Override\n    public DruidPooledConnection dataSource_connect(DruidDataSource dataSource,\n                                                    long maxWaitMillis) throws SQLException {\n        if (this.pos < filterSize) {\n            DruidPooledConnection conn = nextFilter().dataSource_getConnection(this, dataSource, maxWaitMillis);\n            return conn;\n        }\n\n        return dataSource.getConnectionDirect(maxWaitMillis);\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnCount(ResultSetMetaDataProxy metaData) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_getColumnCount(this, metaData);\n        }\n\n        return metaData.getResultSetMetaDataRaw().getColumnCount();\n    }\n\n    @Override\n    public boolean resultSetMetaData_isAutoIncrement(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_isAutoIncrement(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().isAutoIncrement(column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isCaseSensitive(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_isCaseSensitive(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().isCaseSensitive(column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isSearchable(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_isSearchable(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().isSearchable(column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isCurrency(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_isCurrency(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().isCurrency(column);\n    }\n\n    @Override\n    public int resultSetMetaData_isNullable(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_isNullable(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().isNullable(column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isSigned(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_isSigned(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().isSigned(column);\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnDisplaySize(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_getColumnDisplaySize(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().getColumnDisplaySize(column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnLabel(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_getColumnLabel(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().getColumnLabel(column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnName(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_getColumnName(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().getColumnName(column);\n    }\n\n    @Override\n    public String resultSetMetaData_getSchemaName(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_getSchemaName(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw().getSchemaName(column);\n    }\n\n    @Override\n    public int resultSetMetaData_getPrecision(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter().resultSetMetaData_getPrecision(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .getPrecision(column);\n    }\n\n    @Override\n    public int resultSetMetaData_getScale(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_getScale(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .getScale(column);\n    }\n\n    @Override\n    public String resultSetMetaData_getTableName(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_getTableName(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .getTableName(column);\n    }\n\n    @Override\n    public String resultSetMetaData_getCatalogName(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_getCatalogName(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .getCatalogName(column);\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnType(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_getColumnType(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .getColumnType(column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnTypeName(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_getColumnTypeName(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .getColumnTypeName(column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isReadOnly(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_isReadOnly(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .isReadOnly(column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isWritable(ResultSetMetaDataProxy metaData, int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_isWritable(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .isWritable(column);\n    }\n\n    @Override\n    public boolean resultSetMetaData_isDefinitelyWritable(ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_isDefinitelyWritable(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .isDefinitelyWritable(column);\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnClassName(ResultSetMetaDataProxy metaData,\n                                                       int column) throws SQLException {\n        if (this.pos < filterSize) {\n            return nextFilter()\n                    .resultSetMetaData_getColumnClassName(this, metaData, column);\n        }\n\n        return metaData.getResultSetMetaDataRaw()\n                .getColumnClassName(column);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/FilterEventAdapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter;\n\nimport com.alibaba.druid.proxy.jdbc.*;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic abstract class FilterEventAdapter extends FilterAdapter {\n    public FilterEventAdapter() {\n    }\n\n    public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n        connection_connectBefore(chain, info);\n\n        ConnectionProxy connection = super.connection_connect(chain, info);\n\n        connection_connectAfter(connection);\n\n        return connection;\n    }\n\n    public void connection_connectBefore(FilterChain chain, Properties info) {\n    }\n\n    public void connection_connectAfter(ConnectionProxy connection) {\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(FilterChain chain,\n                                                     ConnectionProxy connection) throws SQLException {\n        StatementProxy statement = super.connection_createStatement(chain, connection);\n\n        statementCreateAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection, int resultSetType,\n                                                     int resultSetConcurrency) throws SQLException {\n        StatementProxy statement = super.connection_createStatement(chain, connection, resultSetType,\n                resultSetConcurrency);\n\n        statementCreateAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public StatementProxy connection_createStatement(FilterChain chain, ConnectionProxy connection, int resultSetType,\n                                                     int resultSetConcurrency, int resultSetHoldability)\n            throws SQLException {\n        StatementProxy statement = super.connection_createStatement(chain, connection, resultSetType,\n                resultSetConcurrency, resultSetHoldability);\n\n        statementCreateAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        CallableStatementProxy statement = super.connection_prepareCall(chain, connection, sql);\n\n        statementPrepareCallAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        CallableStatementProxy statement = super.connection_prepareCall(chain, connection, sql, resultSetType,\n                resultSetConcurrency);\n\n        statementPrepareCallAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency,\n                                                         int resultSetHoldability) throws SQLException {\n        CallableStatementProxy statement = super.connection_prepareCall(chain, connection, sql, resultSetType,\n                resultSetConcurrency, resultSetHoldability);\n\n        statementPrepareCallAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        PreparedStatementProxy statement = super.connection_prepareStatement(chain, connection, sql);\n\n        statementPrepareAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int autoGeneratedKeys) throws SQLException {\n        PreparedStatementProxy statement = super.connection_prepareStatement(chain, connection, sql, autoGeneratedKeys);\n\n        statementPrepareAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        PreparedStatementProxy statement = super.connection_prepareStatement(chain, connection, sql, resultSetType,\n                resultSetConcurrency);\n\n        statementPrepareAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency,\n                                                              int resultSetHoldability) throws SQLException {\n        PreparedStatementProxy statement = super.connection_prepareStatement(chain, connection, sql, resultSetType,\n                resultSetConcurrency, resultSetHoldability);\n\n        statementPrepareAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int[] columnIndexes) throws SQLException {\n        PreparedStatementProxy statement = super.connection_prepareStatement(chain, connection, sql, columnIndexes);\n\n        statementPrepareAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, String[] columnNames) throws SQLException {\n        PreparedStatementProxy statement = super.connection_prepareStatement(chain, connection, sql, columnNames);\n\n        statementPrepareAfter(statement);\n\n        return statement;\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        statementExecuteBefore(statement, sql);\n\n        try {\n            boolean firstResult = super.statement_execute(chain, statement, sql);\n\n            statementExecuteAfter(statement, sql, firstResult);\n\n            return firstResult;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        statementExecuteBefore(statement, sql);\n\n        try {\n            boolean firstResult = super.statement_execute(chain, statement, sql, autoGeneratedKeys);\n\n            this.statementExecuteAfter(statement, sql, firstResult);\n\n            return firstResult;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        statementExecuteBefore(statement, sql);\n\n        try {\n            boolean firstResult = super.statement_execute(chain, statement, sql, columnIndexes);\n\n            this.statementExecuteAfter(statement, sql, firstResult);\n\n            return firstResult;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        statementExecuteBefore(statement, sql);\n\n        try {\n            boolean firstResult = super.statement_execute(chain, statement, sql, columnNames);\n\n            this.statementExecuteAfter(statement, sql, firstResult);\n\n            return firstResult;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public int[] statement_executeBatch(FilterChain chain, StatementProxy statement) throws SQLException {\n        statementExecuteBatchBefore(statement);\n\n        try {\n            int[] result = super.statement_executeBatch(chain, statement);\n\n            statementExecuteBatchAfter(statement, result);\n\n            return result;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, statement.getBatchSql(), error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, statement.getBatchSql(), error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, statement.getBatchSql(), error);\n            throw error;\n        }\n    }\n\n    @Override\n    public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)\n            throws SQLException {\n        statementExecuteQueryBefore(statement, sql);\n\n        try {\n            ResultSetProxy resultSet = super.statement_executeQuery(chain, statement, sql);\n\n            if (resultSet != null) {\n                statementExecuteQueryAfter(statement, sql, resultSet);\n                resultSetOpenAfter(resultSet);\n            }\n\n            return resultSet;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        statementExecuteUpdateBefore(statement, sql);\n\n        try {\n            int updateCount = super.statement_executeUpdate(chain, statement, sql);\n\n            statementExecuteUpdateAfter(statement, sql, updateCount);\n\n            return updateCount;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        statementExecuteUpdateBefore(statement, sql);\n\n        try {\n            int updateCount = super.statement_executeUpdate(chain, statement, sql, autoGeneratedKeys);\n\n            statementExecuteUpdateAfter(statement, sql, updateCount);\n\n            return updateCount;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        statementExecuteUpdateBefore(statement, sql);\n\n        try {\n            int updateCount = super.statement_executeUpdate(chain, statement, sql, columnIndexes);\n\n            statementExecuteUpdateAfter(statement, sql, updateCount);\n\n            return updateCount;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        statementExecuteUpdateBefore(statement, sql);\n\n        try {\n            int updateCount = super.statement_executeUpdate(chain, statement, sql, columnNames);\n\n            statementExecuteUpdateAfter(statement, sql, updateCount);\n\n            return updateCount;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, sql, error);\n            throw error;\n        }\n    }\n\n    @Override\n    public ResultSetProxy statement_getGeneratedKeys(FilterChain chain, StatementProxy statement) throws SQLException {\n        ResultSetProxy resultSet = super.statement_getGeneratedKeys(chain, statement);\n\n        if (resultSet != null) {\n            resultSetOpenAfter(resultSet);\n        }\n\n        return resultSet;\n    }\n\n    @Override\n    public ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException {\n        ResultSetProxy resultSet = super.statement_getResultSet(chain, statement);\n\n        if (resultSet != null) {\n            resultSetOpenAfter(resultSet);\n        }\n\n        return resultSet;\n    }\n\n    @Override\n    public boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement) throws SQLException {\n        try {\n            statementExecuteBefore(statement, statement.getSql());\n\n            boolean firstResult = chain.preparedStatement_execute(statement);\n\n            this.statementExecuteAfter(statement, statement.getSql(), firstResult);\n\n            return firstResult;\n\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        }\n\n    }\n\n    @Override\n    public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException {\n        try {\n            statementExecuteQueryBefore(statement, statement.getSql());\n\n            ResultSetProxy resultSet = chain.preparedStatement_executeQuery(statement);\n\n            if (resultSet != null) {\n                statementExecuteQueryAfter(statement, statement.getSql(), resultSet);\n\n                resultSetOpenAfter(resultSet);\n            }\n\n            return resultSet;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        }\n    }\n\n    @Override\n    public int preparedStatement_executeUpdate(FilterChain chain,\n                                               PreparedStatementProxy statement) throws SQLException {\n        try {\n            statementExecuteUpdateBefore(statement, statement.getSql());\n\n            int updateCount = super.preparedStatement_executeUpdate(chain, statement);\n\n            statementExecuteUpdateAfter(statement, statement.getSql(), updateCount);\n\n            return updateCount;\n        } catch (SQLException error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        } catch (RuntimeException error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        } catch (Error error) {\n            statement_executeErrorAfter(statement, statement.getSql(), error);\n            throw error;\n        }\n    }\n\n    protected void statementCreateAfter(StatementProxy statement) {\n    }\n\n    protected void statementPrepareAfter(PreparedStatementProxy statement) {\n    }\n\n    protected void statementPrepareCallAfter(CallableStatementProxy statement) {\n    }\n\n    protected void resultSetOpenAfter(ResultSetProxy resultSet) {\n    }\n\n    protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) {\n    }\n\n    protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) {\n    }\n\n    protected void statementExecuteQueryBefore(StatementProxy statement, String sql) {\n    }\n\n    protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {\n    }\n\n    protected void statementExecuteBefore(StatementProxy statement, String sql) {\n    }\n\n    protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) {\n    }\n\n    protected void statementExecuteBatchBefore(StatementProxy statement) {\n    }\n\n    protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) {\n    }\n\n    protected void statement_executeErrorAfter(StatementProxy statement, String sql, Throwable error) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/FilterManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\nimport java.sql.SQLException;\nimport java.util.Enumeration;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.ConcurrentHashMap;\n\npublic class FilterManager {\n    private static final Log LOG = LogFactory.getLog(FilterManager.class);\n\n    private static final ConcurrentHashMap<String, String> aliasMap = new ConcurrentHashMap<String, String>(16, 0.75f, 1);\n\n    static {\n        try {\n            Properties filterProperties = loadFilterConfig();\n            for (Map.Entry<Object, Object> entry : filterProperties.entrySet()) {\n                String key = (String) entry.getKey();\n                if (key.startsWith(\"druid.filters.\")) {\n                    String name = key.substring(\"druid.filters.\".length());\n                    aliasMap.put(name, (String) entry.getValue());\n                }\n            }\n        } catch (Throwable e) {\n            LOG.error(\"load filter config error\", e);\n        }\n    }\n\n    public static final String getFilter(String alias) {\n        if (alias == null) {\n            return null;\n        }\n\n        String filter = aliasMap.get(alias);\n\n        if (filter == null && alias.length() < 128) {\n            filter = alias;\n        }\n\n        return filter;\n    }\n\n    public static Properties loadFilterConfig() throws IOException {\n        Properties filterProperties = new Properties();\n\n        loadFilterConfig(filterProperties, ClassLoader.getSystemClassLoader());\n        loadFilterConfig(filterProperties, FilterManager.class.getClassLoader());\n        loadFilterConfig(filterProperties, Thread.currentThread().getContextClassLoader());\n\n        return filterProperties;\n    }\n\n    private static void loadFilterConfig(Properties filterProperties, ClassLoader classLoader) throws IOException {\n        if (classLoader == null) {\n            return;\n        }\n\n        for (Enumeration<URL> e = classLoader.getResources(\"META-INF/druid-filter.properties\"); e.hasMoreElements(); ) {\n            URL url = e.nextElement();\n\n            Properties property = new Properties();\n\n            InputStream is = null;\n            try {\n                is = url.openStream();\n                property.load(is);\n            } finally {\n                JdbcUtils.close(is);\n            }\n\n            filterProperties.putAll(property);\n        }\n    }\n\n    public static void loadFilter(List<Filter> filters, String filterName) throws SQLException {\n        if (filterName.length() == 0) {\n            return;\n        }\n\n        String filterClassNames = getFilter(filterName);\n\n        if (filterClassNames != null) {\n            for (String filterClassName : filterClassNames.split(\",\")) {\n                if (existsFilter(filters, filterClassName)) {\n                    continue;\n                }\n\n                Class<?> filterClass = Utils.loadClass(filterClassName);\n\n                if (filterClass == null) {\n                    LOG.error(\"load filter error, filter not found : \" + filterClassName);\n                    continue;\n                }\n\n                Filter filter;\n\n                try {\n                    filter = (Filter) filterClass.newInstance();\n                } catch (ClassCastException e) {\n                    LOG.error(\"load filter error.\", e);\n                    continue;\n                } catch (NoSuchFieldError e) {\n                    LOG.error(\"load filter error.\", e);\n                    continue;\n                } catch (InstantiationException e) {\n                    throw new SQLException(\"load managed jdbc driver event listener error. \" + filterName, e);\n                } catch (IllegalAccessException e) {\n                    throw new SQLException(\"load managed jdbc driver event listener error. \" + filterName, e);\n                } catch (RuntimeException e) {\n                    throw new SQLException(\"load managed jdbc driver event listener error. \" + filterName, e);\n                }\n\n                filters.add(filter);\n            }\n\n            return;\n        }\n\n        if (existsFilter(filters, filterName)) {\n            return;\n        }\n\n        Class<?> filterClass = Utils.loadClass(filterName);\n        if (filterClass == null) {\n            LOG.error(\"load filter error, filter not found : \" + filterName);\n            return;\n        }\n\n        try {\n            Filter filter = (Filter) filterClass.newInstance();\n            filters.add(filter);\n        } catch (Exception e) {\n            throw new SQLException(\"load managed jdbc driver event listener error. \" + filterName, e);\n        }\n    }\n\n    private static boolean existsFilter(List<Filter> filterList, String filterClassName) {\n        for (Filter filter : filterList) {\n            String itemFilterClassName = filter.getClass().getName();\n            if (itemFilterClassName.equalsIgnoreCase(filterClassName)) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.config;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.InputStream;\nimport java.net.URL;\nimport java.security.PublicKey;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\n/**\n * <pre>\n * 这个类主要是负责两个事情：解密和下载远程的配置文件\n * [解密]\n *\n * DruidDataSource dataSource = new DruidDataSource();\n * //dataSource.setXXX 其他设置\n * //下面两步很重要\n * //启用config filter\n * dataSource.setFilters(\"config\");\n * //使用RSA解密(使用默认密钥）\n * dataSource.setConnectionProperties(\"config.decrypt=true\");\n * dataSource.setPassword(\"加密的密文\");\n *\n * [远程配置文件]\n * DruidDataSource dataSource = new DruidDataSource();\n * //下面两步很重要\n * //启用config filter\n * dataSource.setFilters(\"config\");\n * //使用RSA解密(使用默认密钥）\n * dataSource.setConnectionProperties(\"config.file=http://localhost:8080/remote.propreties;\");\n *\n * [Spring的配置解密]\n *\n * &lt;bean id=\"dataSource\" class=\"com.alibaba.druid.pool.DruidDataSource\" init-method=\"init\" destroy-method=\"close\"&gt;\n *     &lt;property name=\"password\" value=\"加密的密文\" /&gt;\n *     &lt;!-- 其他的属性设置 --&gt;\n *     &lt;property name=\"filters\" value=\"config\" /&gt;\n *     &lt;property name=\"connectionProperties\" value=\"config.decrypt=true\" /&gt;\n * &lt;/bean&gt;\n *\n * [Spring的配置远程配置文件]\n *\n * &lt;bean id=\"dataSource\" class=\"com.alibaba.druid.pool.DruidDataSource\" init-method=\"init\" destroy-method=\"close\"&gt;\n *     &lt;property name=\"filters\" value=\"config\" /&gt;\n *     &lt;property name=\"connectionProperties\" value=\"config.file=http://localhost:8080/remote.propreties; /&gt;\n * &lt;/bean&gt;\n *\n * [使用系统属性配置远程文件]\n * java -Ddruid.config.file=file:///home/test/my.properties ...\n *\n * 远程配置文件格式:\n * 1. 其他的属性KEY请查看 @see com.alibaba.druid.pool.DruidDataSourceFactory\n * 2. config filter 相关设置:\n * #远程文件路径\n * config.file=http://xxxxx(http://开头或者file:开头)\n *\n * #RSA解密, Key不指定, 使用默认的\n * config.decrypt=true\n * config.decrypt.key=密钥字符串\n * config.decrypt.keyFile=密钥文件路径\n * config.decrypt.x509File=证书路径\n *\n * </pre>\n *\n * @author Jonas Yang\n */\npublic class ConfigFilter extends FilterAdapter {\n    private static final Log LOG = LogFactory.getLog(ConfigFilter.class);\n\n    public static final String CONFIG_FILE = \"config.file\";\n    public static final String CONFIG_DECRYPT = \"config.decrypt\";\n    public static final String CONFIG_KEY = \"config.decrypt.key\";\n\n    public static final String SYS_PROP_CONFIG_FILE = \"druid.config.file\";\n    public static final String SYS_PROP_CONFIG_DECRYPT = \"druid.config.decrypt\";\n    public static final String SYS_PROP_CONFIG_KEY = \"druid.config.decrypt.key\";\n\n    public ConfigFilter() {\n    }\n\n    public void init(DataSourceProxy dataSourceProxy) {\n        if (!(dataSourceProxy instanceof DruidDataSource)) {\n            throw new IllegalArgumentException(\"ConfigLoader only support DruidDataSource\");\n        }\n\n        DruidDataSource dataSource = (DruidDataSource) dataSourceProxy;\n        Properties connectionProperties = dataSource.getConnectProperties();\n\n        Properties configFileProperties = loadPropertyFromConfigFile(connectionProperties);\n\n        // 判断是否需要解密，如果需要就进行解密行动\n        boolean decrypt = isDecrypt(connectionProperties, configFileProperties);\n\n        if (configFileProperties == null) {\n            if (decrypt) {\n                decrypt(dataSource, null);\n            }\n            return;\n        }\n\n        if (decrypt) {\n            decrypt(dataSource, configFileProperties);\n        }\n\n        try {\n            DruidDataSourceFactory.config(dataSource, configFileProperties);\n        } catch (SQLException e) {\n            throw new IllegalArgumentException(\"Config DataSource error.\", e);\n        }\n    }\n\n    public boolean isDecrypt(Properties connectionProperties, Properties configFileProperties) {\n        String decrypterId = connectionProperties.getProperty(CONFIG_DECRYPT);\n        if (decrypterId == null || decrypterId.length() == 0) {\n            if (configFileProperties != null) {\n                decrypterId = configFileProperties.getProperty(CONFIG_DECRYPT);\n            }\n        }\n\n        if (decrypterId == null || decrypterId.length() == 0) {\n            decrypterId = System.getProperty(SYS_PROP_CONFIG_DECRYPT);\n        }\n\n        return Boolean.valueOf(decrypterId);\n    }\n\n    Properties loadPropertyFromConfigFile(Properties connectionProperties) {\n        String configFile = connectionProperties.getProperty(CONFIG_FILE);\n\n        if (configFile == null) {\n            configFile = System.getProperty(SYS_PROP_CONFIG_FILE);\n        }\n\n        if (configFile != null && configFile.length() > 0) {\n            if (LOG.isInfoEnabled()) {\n                LOG.info(\"DruidDataSource Config File load from : \" + configFile);\n            }\n\n            Properties info = loadConfig(configFile);\n\n            if (info == null) {\n                throw new IllegalArgumentException(\n                        \"Cannot load remote config file from the [config.file=\" + configFile + \"].\");\n            }\n\n            return info;\n        }\n\n        return null;\n    }\n\n    public void decrypt(DruidDataSource dataSource, Properties info) {\n        try {\n            String encryptedPassword = null;\n            if (info != null) {\n                encryptedPassword = info.getProperty(DruidDataSourceFactory.PROP_PASSWORD);\n            }\n\n            if (encryptedPassword == null || encryptedPassword.length() == 0) {\n                encryptedPassword = dataSource.getConnectProperties().getProperty(DruidDataSourceFactory.PROP_PASSWORD);\n            }\n\n            if (encryptedPassword == null || encryptedPassword.length() == 0) {\n                encryptedPassword = dataSource.getPassword();\n            }\n\n            PublicKey publicKey = getPublicKey(dataSource.getConnectProperties(), info);\n\n            String passwordPlainText = ConfigTools.decrypt(publicKey, encryptedPassword);\n\n            if (info != null) {\n                info.setProperty(DruidDataSourceFactory.PROP_PASSWORD, passwordPlainText);\n            } else {\n                dataSource.setPassword(passwordPlainText);\n            }\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\"Failed to decrypt.\", e);\n        }\n    }\n\n    public PublicKey getPublicKey(Properties connectionProperties, Properties configFileProperties) {\n        String key = null;\n        if (configFileProperties != null) {\n            key = configFileProperties.getProperty(CONFIG_KEY);\n        }\n\n        if (StringUtils.isEmpty(key) && connectionProperties != null) {\n            key = connectionProperties.getProperty(CONFIG_KEY);\n        }\n\n        if (StringUtils.isEmpty(key)) {\n            key = System.getProperty(SYS_PROP_CONFIG_KEY);\n        }\n\n        return ConfigTools.getPublicKey(key);\n    }\n\n    public Properties loadConfig(String filePath) {\n        Properties properties = new Properties();\n\n        InputStream inStream = null;\n        try {\n            boolean xml = false;\n            if (filePath.startsWith(\"file://\")) {\n                filePath = filePath.substring(\"file://\".length());\n                inStream = getFileAsStream(filePath);\n                xml = filePath.endsWith(\".xml\");\n            } else if (filePath.startsWith(\"http://\") || filePath.startsWith(\"https://\")) {\n                URL url = new URL(filePath);\n                inStream = url.openStream();\n                xml = url.getPath().endsWith(\".xml\");\n            } else if (filePath.startsWith(\"classpath:\")) {\n                String resourcePath = filePath.substring(\"classpath:\".length());\n                inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath);\n                // 在classpath下应该也可以配置xml文件吧？\n                xml = resourcePath.endsWith(\".xml\");\n            } else {\n                inStream = getFileAsStream(filePath);\n                xml = filePath.endsWith(\".xml\");\n            }\n\n            if (inStream == null) {\n                LOG.error(\"load config file error, file : \" + filePath);\n                return null;\n            }\n\n            if (xml) {\n                properties.loadFromXML(inStream);\n            } else {\n                properties.load(inStream);\n            }\n\n            return properties;\n        } catch (Exception ex) {\n            LOG.error(\"load config file error, file : \" + filePath, ex);\n            return null;\n        } finally {\n            JdbcUtils.close(inStream);\n        }\n    }\n\n    private InputStream getFileAsStream(String filePath) throws FileNotFoundException {\n        InputStream inStream = null;\n        File file = new File(filePath);\n        if (file.exists()) {\n            inStream = new FileInputStream(file);\n        } else {\n            inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);\n        }\n        return inStream;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/config/ConfigTools.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.config;\n\nimport com.alibaba.druid.util.Base64;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport javax.crypto.Cipher;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.FileInputStream;\nimport java.security.*;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateFactory;\nimport java.security.interfaces.RSAPrivateKey;\nimport java.security.interfaces.RSAPublicKey;\nimport java.security.spec.PKCS8EncodedKeySpec;\nimport java.security.spec.RSAPrivateKeySpec;\nimport java.security.spec.RSAPublicKeySpec;\nimport java.security.spec.X509EncodedKeySpec;\n\n@Deprecated\npublic class ConfigTools {\n    @Deprecated\n    private static final String DEFAULT_PRIVATE_KEY_STRING = \"MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAocbCrurZGbC5GArEHKlAfDSZi7gFBnd4yxOt0rwTqKBFzGyhtQLu5PRKjEiOXVa95aeIIBJ6OhC2f8FjqFUpawIDAQABAkAPejKaBYHrwUqUEEOe8lpnB6lBAsQIUFnQI/vXU4MV+MhIzW0BLVZCiarIQqUXeOhThVWXKFt8GxCykrrUsQ6BAiEA4vMVxEHBovz1di3aozzFvSMdsjTcYRRo82hS5Ru2/OECIQC2fAPoXixVTVY7bNMeuxCP4954ZkXp7fEPDINCjcQDywIgcc8XLkkPcs3Jxk7uYofaXaPbg39wuJpEmzPIxi3k0OECIGubmdpOnin3HuCP/bbjbJLNNoUdGiEmFL5hDI4UdwAdAiEAtcAwbm08bKN7pwwvyqaCBC//VnEWaq39DCzxr+Z2EIk=\";\n    @Deprecated\n    public static final String DEFAULT_PUBLIC_KEY_STRING = \"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHGwq7q2RmwuRgKxBypQHw0mYu4BQZ3eMsTrdK8E6igRcxsobUC7uT0SoxIjl1WveWniCASejoQtn/BY6hVKWsCAwEAAQ==\";\n\n    public static void main(String[] args) throws Exception {\n        String password = args[0];\n        String[] arr = genKeyPair(512);\n        System.out.println(\"privateKey:\" + arr[0]);\n        System.out.println(\"publicKey:\" + arr[1]);\n        System.out.println(\"password:\" + encrypt(arr[0], password));\n    }\n\n    public static String decrypt(String cipherText) throws Exception {\n        return decrypt((String) null, cipherText);\n    }\n\n    public static String decrypt(String publicKeyText, String cipherText)\n            throws Exception {\n        PublicKey publicKey = getPublicKey(publicKeyText);\n\n        return decrypt(publicKey, cipherText);\n    }\n\n    public static PublicKey getPublicKeyByX509(String x509File) {\n        if (x509File == null || x509File.length() == 0) {\n            return ConfigTools.getPublicKey(null);\n        }\n\n        FileInputStream in = null;\n        try {\n            in = new FileInputStream(x509File);\n\n            CertificateFactory factory = CertificateFactory\n                    .getInstance(\"X.509\");\n            Certificate cer = factory.generateCertificate(in);\n            return cer.getPublicKey();\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\"Failed to get public key\", e);\n        } finally {\n            JdbcUtils.close(in);\n        }\n    }\n\n    public static PublicKey getPublicKey(String publicKeyText) {\n        if (publicKeyText == null || publicKeyText.length() == 0) {\n            publicKeyText = ConfigTools.DEFAULT_PUBLIC_KEY_STRING;\n        }\n\n        try {\n            byte[] publicKeyBytes = Base64.base64ToByteArray(publicKeyText);\n            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(\n                    publicKeyBytes);\n\n            KeyFactory keyFactory = KeyFactory.getInstance(\"RSA\", \"SunRsaSign\");\n            return keyFactory.generatePublic(x509KeySpec);\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\"Failed to get public key\", e);\n        }\n    }\n\n    public static PublicKey getPublicKeyByPublicKeyFile(String publicKeyFile) {\n        if (publicKeyFile == null || publicKeyFile.length() == 0) {\n            return ConfigTools.getPublicKey(null);\n        }\n\n        FileInputStream in = null;\n        try {\n            in = new FileInputStream(publicKeyFile);\n            ByteArrayOutputStream out = new ByteArrayOutputStream();\n            int len = 0;\n            byte[] b = new byte[512 / 8];\n            while ((len = in.read(b)) != -1) {\n                out.write(b, 0, len);\n            }\n\n            byte[] publicKeyBytes = out.toByteArray();\n            X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);\n            KeyFactory factory = KeyFactory.getInstance(\"RSA\", \"SunRsaSign\");\n            return factory.generatePublic(spec);\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\"Failed to get public key\", e);\n        } finally {\n            JdbcUtils.close(in);\n        }\n    }\n\n    public static String decrypt(PublicKey publicKey, String cipherText)\n            throws Exception {\n        Cipher cipher = Cipher.getInstance(\"RSA/ECB/PKCS1Padding\");\n        try {\n            cipher.init(Cipher.DECRYPT_MODE, publicKey);\n        } catch (InvalidKeyException e) {\n            // 因为 IBM JDK 不支持私钥加密, 公钥解密, 所以要反转公私钥\n            // 也就是说对于解密, 可以通过公钥的参数伪造一个私钥对象欺骗 IBM JDK\n            RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;\n            RSAPrivateKeySpec spec = new RSAPrivateKeySpec(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());\n            Key fakePrivateKey = KeyFactory.getInstance(\"RSA\").generatePrivate(spec);\n            cipher = Cipher.getInstance(\"RSA\"); //It is a stateful object. so we need to get new one.\n            cipher.init(Cipher.DECRYPT_MODE, fakePrivateKey);\n        }\n\n        if (cipherText == null || cipherText.length() == 0) {\n            return cipherText;\n        }\n\n        byte[] cipherBytes = Base64.base64ToByteArray(cipherText);\n        byte[] plainBytes = cipher.doFinal(cipherBytes);\n\n        return new String(plainBytes);\n    }\n\n    public static String encrypt(String plainText) throws Exception {\n        return encrypt((String) null, plainText);\n    }\n\n    public static String encrypt(String key, String plainText) throws Exception {\n        if (key == null) {\n            key = DEFAULT_PRIVATE_KEY_STRING;\n        }\n\n        byte[] keyBytes = Base64.base64ToByteArray(key);\n        return encrypt(keyBytes, plainText);\n    }\n\n    public static String encrypt(byte[] keyBytes, String plainText)\n            throws Exception {\n        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);\n        KeyFactory factory = KeyFactory.getInstance(\"RSA\", \"SunRsaSign\");\n        PrivateKey privateKey = factory.generatePrivate(spec);\n        Cipher cipher = Cipher.getInstance(\"RSA/ECB/PKCS1Padding\");\n        try {\n            cipher.init(Cipher.ENCRYPT_MODE, privateKey);\n        } catch (InvalidKeyException e) {\n            //For IBM JDK, 原因请看解密方法中的说明\n            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;\n            RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(rsaPrivateKey.getModulus(), rsaPrivateKey.getPrivateExponent());\n            Key fakePublicKey = KeyFactory.getInstance(\"RSA\").generatePublic(publicKeySpec);\n            cipher = Cipher.getInstance(\"RSA\");\n            cipher.init(Cipher.ENCRYPT_MODE, fakePublicKey);\n        }\n\n        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(\"UTF-8\"));\n        String encryptedString = Base64.byteArrayToBase64(encryptedBytes);\n\n        return encryptedString;\n    }\n\n    public static byte[][] genKeyPairBytes(int keySize)\n            throws NoSuchAlgorithmException, NoSuchProviderException {\n        byte[][] keyPairBytes = new byte[2][];\n\n        KeyPairGenerator gen = KeyPairGenerator.getInstance(\"RSA\", \"SunRsaSign\");\n        gen.initialize(keySize, new SecureRandom());\n        KeyPair pair = gen.generateKeyPair();\n\n        keyPairBytes[0] = pair.getPrivate().getEncoded();\n        keyPairBytes[1] = pair.getPublic().getEncoded();\n\n        return keyPairBytes;\n    }\n\n    public static String[] genKeyPair(int keySize)\n            throws NoSuchAlgorithmException, NoSuchProviderException {\n        byte[][] keyPairBytes = genKeyPairBytes(keySize);\n        String[] keyPairs = new String[2];\n\n        keyPairs[0] = Base64.byteArrayToBase64(keyPairBytes[0]);\n        keyPairs[1] = Base64.byteArrayToBase64(keyPairBytes[1]);\n\n        return keyPairs;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/encoding/CharsetConvert.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.encoding;\n\nimport java.io.UnsupportedEncodingException;\n\n/**\n * 字符编码转换器\n *\n * @author xianmao.hexm 2007-3-5 09:51:33\n */\npublic class CharsetConvert {\n    private final String clientEncoding;\n\n    private final String serverEncoding;\n\n    private final boolean enable;\n\n    public CharsetConvert(String clientEncoding, String serverEncoding) {\n        this.clientEncoding = clientEncoding;\n        this.serverEncoding = serverEncoding;\n        this.enable = clientEncoding != null && serverEncoding != null && !clientEncoding.equalsIgnoreCase(serverEncoding);\n    }\n\n    /**\n     * Encodes the specified string using the specified client and server encodings, if enabled.\n     * If encoding is not enabled or the input string is empty, the original string is returned unchanged.\n     *\n     * @param s the string to be encoded\n     * @return the encoded string, or the original string if encoding is not enabled or the input string is empty\n     * @throws UnsupportedEncodingException if the specified encoding is not supported\n     */\n    public String encode(String s) throws UnsupportedEncodingException {\n        if (enable && !isEmpty(s)) {\n            s = new String(s.getBytes(clientEncoding), serverEncoding);\n        }\n        return s;\n    }\n\n    /**\n     * Decodes the specified string using the specified server and client encodings, if enabled.\n     * If decoding is not enabled or the input string is empty, the original string is returned unchanged.\n     *\n     * @param s the string to be decoded\n     * @return the decoded string, or the original string if decoding is not enabled or the input string is empty\n     * @throws UnsupportedEncodingException if the specified encoding is not supported\n     */\n    public String decode(String s) throws UnsupportedEncodingException {\n        if (enable && !isEmpty(s)) {\n            s = new String(s.getBytes(serverEncoding), clientEncoding);\n        }\n        return s;\n    }\n\n    /**\n     * Determines whether the specified string is null or empty.\n     *\n     * @param s the string to be checked\n     * @return true if the specified string is null or empty, false otherwise\n     */\n    public boolean isEmpty(String s) {\n        return s == null || s.isEmpty();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/encoding/CharsetParameter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.encoding;\n\n/**\n * 已过期,后续版本考虑直接下线该代码. {@link EncodingConvertFilter}\n */\n@Deprecated\npublic class CharsetParameter {\n    /**\n     * {@link EncodingConvertFilter#CLIENT_ENCODING_KEY}\n     */\n    public static final String CLIENTENCODINGKEY = \"clientEncoding\";\n\n    /**\n     * {@link EncodingConvertFilter#SERVER_ENCODING_KEY}\n     */\n    public static final String SERVERENCODINGKEY = \"serverEncoding\";\n\n    // 数据库客户端编码\n    private String clientEncoding;\n\n    // 数据库服务器端编码\n    private String serverEncoding;\n\n    public String getClientEncoding() {\n        return clientEncoding;\n    }\n\n    public void setClientEncoding(String clientEncoding) {\n        this.clientEncoding = clientEncoding;\n    }\n\n    public String getServerEncoding() {\n        return serverEncoding;\n    }\n\n    public void setServerEncoding(String serverEncoding) {\n        this.serverEncoding = serverEncoding;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/encoding/EncodingConvertFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.encoding;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.proxy.jdbc.*;\nimport com.alibaba.druid.util.Utils;\n\nimport java.io.Reader;\nimport java.io.StringReader;\nimport java.io.UnsupportedEncodingException;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.sql.Types;\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class EncodingConvertFilter extends FilterAdapter {\n    public static final String ATTR_CHARSET_CONVERTER = \"ali.charset.converter\";\n\n    public static final String CLIENT_ENCODING_KEY = \"clientEncoding\";\n\n    public static final String SERVER_ENCODING_KEY = \"serverEncoding\";\n\n    @Override\n    public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n        ConnectionProxy conn = chain.connection_connect(info);\n\n        String clientEncoding = info.getProperty(CLIENT_ENCODING_KEY);\n        String serverEncoding = info.getProperty(SERVER_ENCODING_KEY);\n\n        conn.putAttribute(ATTR_CHARSET_CONVERTER, new CharsetConvert(clientEncoding, serverEncoding));\n\n        return conn;\n    }\n\n    @Override\n    public String resultSet_getString(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        String value = super.resultSet_getString(chain, result, columnIndex);\n        return decode(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    @Override\n    public String resultSet_getString(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        String value = super.resultSet_getString(chain, result, columnLabel);\n        return decode(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        ResultSet rawResultSet = result.getResultSetRaw();\n        ResultSetMetaData metadata = rawResultSet.getMetaData();\n        int columnType = metadata.getColumnType(columnIndex);\n\n        Object value = null;\n        switch (columnType) {\n            case Types.CHAR:\n            case Types.CLOB:\n            case Types.LONGVARCHAR:\n            case Types.VARCHAR:\n                value = super.resultSet_getString(chain, result, columnIndex);\n                break;\n            default:\n                value = super.resultSet_getObject(chain, result, columnIndex);\n        }\n\n        return decodeObject(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    @Override\n    public <T> T resultSet_getObject(FilterChain chain,\n                                     ResultSetProxy result,\n                                     int columnIndex,\n                                     Class<T> type) throws SQLException {\n        ResultSet rawResultSet = result.getResultSetRaw();\n        ResultSetMetaData metadata = rawResultSet.getMetaData();\n        int columnType = metadata.getColumnType(columnIndex);\n\n        Object value = null;\n        switch (columnType) {\n            case Types.CHAR:\n            case Types.CLOB:\n            case Types.LONGVARCHAR:\n            case Types.VARCHAR:\n                value = super.resultSet_getString(chain, result, columnIndex);\n                break;\n            default:\n                value = super.resultSet_getObject(chain, result, columnIndex, type);\n        }\n\n        return (T) decodeObject(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                      java.util.Map<String, Class<?>> map) throws SQLException {\n        ResultSet rawResultSet = result.getResultSetRaw();\n        ResultSetMetaData metadata = rawResultSet.getMetaData();\n        int columnType = metadata.getColumnType(columnIndex);\n\n        Object value = null;\n        switch (columnType) {\n            case Types.CHAR:\n            case Types.CLOB:\n            case Types.LONGVARCHAR:\n            case Types.VARCHAR:\n                value = super.resultSet_getString(chain, result, columnIndex);\n                break;\n            default:\n                value = super.resultSet_getObject(chain, result, columnIndex, map);\n        }\n\n        return decodeObject(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        ResultSet rawResultSet = result.getResultSetRaw();\n        ResultSetMetaData metadata = rawResultSet.getMetaData();\n        int columnIndex = rawResultSet.findColumn(columnLabel);\n        int columnType = metadata.getColumnType(columnIndex);\n\n        Object value = null;\n        switch (columnType) {\n            case Types.CHAR:\n            case Types.CLOB:\n            case Types.LONGVARCHAR:\n            case Types.VARCHAR:\n                value = super.resultSet_getString(chain, result, columnLabel);\n                break;\n            default:\n                value = super.resultSet_getObject(chain, result, columnLabel);\n        }\n        return decodeObject(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    @Override\n    public <T> T resultSet_getObject(FilterChain chain,\n                                     ResultSetProxy result,\n                                     String columnLabel,\n                                     Class<T> type) throws SQLException {\n        ResultSet rawResultSet = result.getResultSetRaw();\n        ResultSetMetaData metadata = rawResultSet.getMetaData();\n        int columnIndex = rawResultSet.findColumn(columnLabel);\n        int columnType = metadata.getColumnType(columnIndex);\n\n        Object value = null;\n        switch (columnType) {\n            case Types.CHAR:\n            case Types.CLOB:\n            case Types.LONGVARCHAR:\n            case Types.VARCHAR:\n                value = super.resultSet_getString(chain, result, columnLabel);\n                break;\n            default:\n                value = super.resultSet_getObject(chain, result, columnLabel, type);\n        }\n        return (T) decodeObject(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                      java.util.Map<String, Class<?>> map) throws SQLException {\n        ResultSet rawResultSet = result.getResultSetRaw();\n        ResultSetMetaData metadata = rawResultSet.getMetaData();\n        int columnIndex = rawResultSet.findColumn(columnLabel);\n        int columnType = metadata.getColumnType(columnIndex);\n\n        Object value = null;\n        switch (columnType) {\n            case Types.CHAR:\n                value = super.resultSet_getString(chain, result, columnLabel);\n                break;\n            case Types.CLOB:\n                value = super.resultSet_getString(chain, result, columnLabel);\n                break;\n            case Types.LONGVARCHAR:\n                value = super.resultSet_getString(chain, result, columnLabel);\n                break;\n            case Types.VARCHAR:\n                value = super.resultSet_getString(chain, result, columnLabel);\n                break;\n            default:\n                value = super.resultSet_getObject(chain, result, columnLabel, map);\n        }\n\n        return decodeObject(result.getStatementProxy().getConnectionProxy(), value);\n    }\n\n    // ///////////\n\n    public Object decodeObject(ConnectionProxy connection, Object object) throws SQLException {\n        if (object instanceof String) {\n            return decode(connection, (String) object);\n        }\n\n        if (object instanceof Reader) {\n            Reader reader = (Reader) object;\n            String text = Utils.read(reader);\n            return new StringReader(decode(connection, text));\n        }\n\n        return object;\n    }\n\n    public Object decodeObject(CallableStatementProxy stmt, Object object) throws SQLException {\n        if (object instanceof String) {\n            return decode(stmt.getConnectionProxy(), (String) object);\n        }\n\n        if (object instanceof Reader) {\n            Reader reader = (Reader) object;\n            String text = Utils.read(reader);\n            return new StringReader(decode(stmt.getConnectionProxy(), text));\n        }\n\n        return object;\n    }\n\n    public String encode(ConnectionProxy connection, String s) throws SQLException {\n        try {\n            CharsetConvert charsetConvert = (CharsetConvert) connection.getAttribute(ATTR_CHARSET_CONVERTER);\n\n            return charsetConvert.encode(s);\n        } catch (UnsupportedEncodingException e) {\n            throw new SQLException(e.getMessage(), e);\n        }\n    }\n\n    public String decode(ConnectionProxy connection, String s) throws SQLException {\n        try {\n            CharsetConvert charsetConvert = (CharsetConvert) connection.getAttribute(ATTR_CHARSET_CONVERTER);\n            return charsetConvert.decode(s);\n        } catch (UnsupportedEncodingException e) {\n            throw new SQLException(e.getMessage(), e);\n        }\n    }\n\n    // //////////////// Connection\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        return super.connection_prepareStatement(chain, connection, encode(connection, sql));\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int autoGeneratedKeys) throws SQLException {\n        return super.connection_prepareStatement(chain, connection, encode(connection, sql), autoGeneratedKeys);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        return super.connection_prepareStatement(chain, connection, encode(connection, sql), resultSetType,\n                resultSetConcurrency);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency,\n                                                              int resultSetHoldability) throws SQLException {\n        return super.connection_prepareStatement(chain, connection, encode(connection, sql), resultSetType,\n                resultSetConcurrency, resultSetHoldability);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int[] columnIndexes) throws SQLException {\n        return super.connection_prepareStatement(chain, connection, encode(connection, sql), columnIndexes);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, String[] columnNames) throws SQLException {\n        return super.connection_prepareStatement(chain, connection, encode(connection, sql), columnNames);\n    }\n\n    // / precall\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        return super.connection_prepareCall(chain, connection, encode(connection, sql));\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        return super.connection_prepareCall(chain, connection, encode(connection, sql), resultSetType,\n                resultSetConcurrency);\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency,\n                                                         int resultSetHoldability) throws SQLException {\n        return super.connection_prepareCall(chain, connection, encode(connection, sql), resultSetType,\n                resultSetConcurrency, resultSetHoldability);\n    }\n\n    // nativeSQL\n\n    @Override\n    public String connection_nativeSQL(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException {\n        String encodedSql = encode(connection, sql);\n        return super.connection_nativeSQL(chain, connection, encodedSql);\n    }\n\n    // ////////////// statement\n\n    @Override\n    public void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        super.statement_addBatch(chain, statement, encode(statement.getConnectionProxy(), sql));\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        return super.statement_execute(chain, statement, encode(statement.getConnectionProxy(), sql));\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        return super.statement_execute(chain, statement, encode(statement.getConnectionProxy(), sql), autoGeneratedKeys);\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        return super.statement_execute(chain, statement, encode(statement.getConnectionProxy(), sql), columnIndexes);\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        return super.statement_execute(chain, statement, encode(statement.getConnectionProxy(), sql), columnNames);\n    }\n\n    @Override\n    public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)\n            throws SQLException {\n        return super.statement_executeQuery(chain, statement, encode(statement.getConnectionProxy(), sql));\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        return super.statement_executeUpdate(chain, statement, encode(statement.getConnectionProxy(), sql));\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        return super.statement_executeUpdate(chain, statement, encode(statement.getConnectionProxy(), sql),\n                autoGeneratedKeys);\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        return super.statement_executeUpdate(chain, statement, encode(statement.getConnectionProxy(), sql),\n                columnIndexes);\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        return super.statement_executeUpdate(chain, statement, encode(statement.getConnectionProxy(), sql), columnNames);\n    }\n\n    // ========== preparedStatement\n\n    @Override\n    public void preparedStatement_setString(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            String x) throws SQLException {\n        super.preparedStatement_setString(chain, statement, parameterIndex, encode(statement.getConnectionProxy(), x));\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                     int parameterIndex, java.io.Reader reader) throws SQLException {\n        String text = Utils.read(reader);\n        String encodedText = encode(statement.getConnectionProxy(), text);\n        super.preparedStatement_setCharacterStream(chain, statement, parameterIndex, new StringReader(encodedText));\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                     int parameterIndex, java.io.Reader reader, int length)\n            throws SQLException {\n        String text = Utils.read(reader, length);\n        String encodedText = encode(statement.getConnectionProxy(), text);\n        super.preparedStatement_setCharacterStream(chain, statement, parameterIndex, new StringReader(encodedText),\n                encodedText.length());\n    }\n\n    @Override\n    public void preparedStatement_setCharacterStream(FilterChain chain, PreparedStatementProxy statement,\n                                                     int parameterIndex, java.io.Reader reader, long length)\n            throws SQLException {\n        String text = Utils.read(reader, (int) length);\n        String encodedText = encode(statement.getConnectionProxy(), text);\n        super.preparedStatement_setCharacterStream(chain, statement, parameterIndex, new StringReader(encodedText),\n                encodedText.length());\n    }\n\n    @Override\n    public void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            Object x) throws SQLException {\n        if (x instanceof String) {\n            String encodedText = encode(statement.getConnectionProxy(), (String) x);\n            super.preparedStatement_setObject(chain, statement, parameterIndex, encodedText);\n        } else if (x instanceof Reader) {\n            String text = Utils.read((Reader) x);\n            String encodedText = encode(statement.getConnectionProxy(), text);\n            super.preparedStatement_setObject(chain, statement, parameterIndex, new StringReader(encodedText));\n        } else {\n            super.preparedStatement_setObject(chain, statement, parameterIndex, x);\n        }\n    }\n\n    @Override\n    public void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            Object x, int targetSqlType) throws SQLException {\n        if (x instanceof String) {\n            String encodedText = encode(statement.getConnectionProxy(), (String) x);\n            super.preparedStatement_setObject(chain, statement, parameterIndex, encodedText, targetSqlType);\n        } else if (x instanceof Reader) {\n            String text = Utils.read((Reader) x);\n            String encodedText = encode(statement.getConnectionProxy(), text);\n            super.preparedStatement_setObject(chain, statement, parameterIndex, new StringReader(encodedText),\n                    targetSqlType);\n        } else {\n            super.preparedStatement_setObject(chain, statement, parameterIndex, x, targetSqlType);\n        }\n    }\n\n    @Override\n    public void preparedStatement_setObject(FilterChain chain, PreparedStatementProxy statement, int parameterIndex,\n                                            Object x, int targetSqlType, int scaleOrLength) throws SQLException {\n        if (x instanceof String) {\n            String encodedText = encode(statement.getConnectionProxy(), (String) x);\n            super.preparedStatement_setObject(chain, statement, parameterIndex, encodedText, targetSqlType,\n                    scaleOrLength);\n        } else if (x instanceof Reader) {\n            String text = Utils.read((Reader) x);\n            String encodedText = encode(statement.getConnectionProxy(), text);\n            super.preparedStatement_setObject(chain, statement, parameterIndex, new StringReader(encodedText),\n                    targetSqlType, scaleOrLength);\n        } else {\n            super.preparedStatement_setObject(chain, statement, parameterIndex, x, targetSqlType, scaleOrLength);\n        }\n    }\n\n    // //////////\n\n    @Override\n    public long clob_position(FilterChain chain, ClobProxy wrapper, String searchstr, long start) throws SQLException {\n        return chain.clob_position(wrapper, encode(wrapper.getConnectionWrapper(), searchstr), start);\n    }\n\n    @Override\n    public String clob_getSubString(FilterChain chain, ClobProxy wrapper, long pos, int length) throws SQLException {\n        String text = super.clob_getSubString(chain, wrapper, pos, length);\n        return decode(wrapper.getConnectionWrapper(), text);\n    }\n\n    @Override\n    public java.io.Reader clob_getCharacterStream(FilterChain chain, ClobProxy wrapper) throws SQLException {\n        Reader reader = super.clob_getCharacterStream(chain, wrapper);\n        String text = Utils.read(reader);\n        return new StringReader(decode(wrapper.getConnectionWrapper(), text));\n    }\n\n    @Override\n    public Reader clob_getCharacterStream(FilterChain chain, ClobProxy wrapper, long pos, long length)\n            throws SQLException {\n        Reader reader = super.clob_getCharacterStream(chain, wrapper, pos, length);\n        String text = Utils.read(reader);\n        return new StringReader(decode(wrapper.getConnectionWrapper(), text));\n    }\n\n    @Override\n    public int clob_setString(FilterChain chain, ClobProxy wrapper, long pos, String str) throws SQLException {\n        return chain.clob_setString(wrapper, pos, encode(wrapper.getConnectionWrapper(), str));\n    }\n\n    @Override\n    public int clob_setString(FilterChain chain, ClobProxy wrapper, long pos, String str, int offset, int len)\n            throws SQLException {\n        return chain.clob_setString(wrapper, pos, encode(wrapper.getConnectionWrapper(), str), offset, len);\n    }\n\n    // ///////////// callableStatement_\n\n    @Override\n    public void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                     String parameterName, java.io.Reader reader) throws SQLException {\n        String text = Utils.read(reader);\n        Reader encodeReader = new StringReader(encode(statement.getConnectionProxy(), text));\n        super.callableStatement_setCharacterStream(chain, statement, parameterName, encodeReader);\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                     String parameterName, java.io.Reader reader, int length)\n            throws SQLException {\n        String text = Utils.read(reader, length);\n        String encodeText = encode(statement.getConnectionProxy(), text);\n        Reader encodeReader = new StringReader(encodeText);\n        super.callableStatement_setCharacterStream(chain, statement, parameterName, encodeReader, encodeText.length());\n    }\n\n    @Override\n    public void callableStatement_setCharacterStream(FilterChain chain, CallableStatementProxy statement,\n                                                     String parameterName, java.io.Reader reader, long length)\n            throws SQLException {\n        String text = Utils.read(reader, (int) length);\n        String encodeText = encode(statement.getConnectionProxy(), text);\n        Reader encodeReader = new StringReader(encodeText);\n        super.callableStatement_setCharacterStream(chain, statement, parameterName, encodeReader,\n                (long) encodeText.length());\n    }\n\n    @Override\n    public void callableStatement_setString(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            String x) throws SQLException {\n        super.callableStatement_setString(chain, statement, parameterName, encode(statement.getConnectionProxy(), x));\n    }\n\n    @Override\n    public void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Object x) throws SQLException {\n        if (x instanceof String) {\n            String encodedText = encode(statement.getConnectionProxy(), (String) x);\n            super.callableStatement_setObject(chain, statement, parameterName, encodedText);\n        } else if (x instanceof Reader) {\n            String text = Utils.read((Reader) x);\n            String encodedText = encode(statement.getConnectionProxy(), text);\n            super.callableStatement_setObject(chain, statement, parameterName, new StringReader(encodedText));\n        } else {\n            super.callableStatement_setObject(chain, statement, parameterName, x);\n        }\n    }\n\n    @Override\n    public void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Object x, int targetSqlType) throws SQLException {\n        if (x instanceof String) {\n            String encodedText = encode(statement.getConnectionProxy(), (String) x);\n            super.callableStatement_setObject(chain, statement, parameterName, encodedText, targetSqlType);\n        } else if (x instanceof Reader) {\n            String text = Utils.read((Reader) x);\n            String encodedText = encode(statement.getConnectionProxy(), text);\n            super.callableStatement_setObject(chain, statement, parameterName, new StringReader(encodedText),\n                    targetSqlType);\n        } else {\n            super.callableStatement_setObject(chain, statement, parameterName, x, targetSqlType);\n        }\n    }\n\n    @Override\n    public void callableStatement_setObject(FilterChain chain, CallableStatementProxy statement, String parameterName,\n                                            Object x, int targetSqlType, int scale) throws SQLException {\n        if (x instanceof String) {\n            String encodedText = encode(statement.getConnectionProxy(), (String) x);\n            super.callableStatement_setObject(chain, statement, parameterName, encodedText, targetSqlType, scale);\n        } else if (x instanceof Reader) {\n            String text = Utils.read((Reader) x);\n            String encodedText = encode(statement.getConnectionProxy(), text);\n            super.callableStatement_setObject(chain, statement, parameterName, new StringReader(encodedText),\n                    targetSqlType, scale);\n        } else {\n            super.callableStatement_setObject(chain, statement, parameterName, x, targetSqlType, scale);\n        }\n    }\n\n    @Override\n    public String callableStatement_getString(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        String value = super.callableStatement_getString(chain, statement, parameterIndex);\n        return decode(statement.getConnectionProxy(), value);\n    }\n\n    @Override\n    public String callableStatement_getString(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        String value = super.callableStatement_getString(chain, statement, parameterName);\n        return decode(statement.getConnectionProxy(), value);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        Object value = chain.callableStatement_getObject(statement, parameterIndex);\n        return decodeObject(statement, value);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n        Object value = chain.callableStatement_getObject(statement, parameterIndex, map);\n        return decodeObject(statement, value);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        Object value = chain.callableStatement_getObject(statement, parameterName);\n        return decodeObject(statement, value);\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement,\n                                              String parameterName, java.util.Map<String, Class<?>> map)\n            throws SQLException {\n        Object value = chain.callableStatement_getObject(statement, parameterName, map);\n        return decodeObject(statement, value);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/CommonsLogFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.apache.commons.logging.impl.Log4JLogger;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class CommonsLogFilter extends LogFilter {\n    private Log dataSourceLogger = LogFactory.getLog(dataSourceLoggerName);\n    private Log connectionLogger = LogFactory.getLog(connectionLoggerName);\n    private Log statementLogger = LogFactory.getLog(statementLoggerName);\n    private Log resultSetLogger = LogFactory.getLog(resultSetLoggerName);\n\n    public void setDataSourceLogger(Log dataSourceLogger) {\n        this.dataSourceLogger = dataSourceLogger;\n        if (dataSourceLogger instanceof Log4JLogger) {\n            this.dataSourceLoggerName = ((Log4JLogger) dataSourceLogger).getLogger().getName();\n        }\n    }\n\n    @Override\n    public String getDataSourceLoggerName() {\n        return dataSourceLoggerName;\n    }\n\n    @Override\n    public void setDataSourceLoggerName(String dataSourceLoggerName) {\n        this.dataSourceLoggerName = dataSourceLoggerName;\n        dataSourceLogger = LogFactory.getLog(dataSourceLoggerName);\n    }\n\n    @Override\n    public String getConnectionLoggerName() {\n        return connectionLoggerName;\n    }\n\n    @Override\n    public void setConnectionLoggerName(String connectionLoggerName) {\n        this.connectionLoggerName = connectionLoggerName;\n        connectionLogger = LogFactory.getLog(connectionLoggerName);\n    }\n\n    public void setConnectionLogger(Log connectionLogger) {\n        this.connectionLogger = connectionLogger;\n        if (connectionLogger instanceof Log4JLogger) {\n            this.connectionLoggerName = ((Log4JLogger) connectionLogger).getLogger().getName();\n        }\n    }\n\n    @Override\n    public String getStatementLoggerName() {\n        return statementLoggerName;\n    }\n\n    @Override\n    public void setStatementLoggerName(String statementLoggerName) {\n        this.statementLoggerName = statementLoggerName;\n        statementLogger = LogFactory.getLog(statementLoggerName);\n    }\n\n    public void setStatementLogger(Log statementLogger) {\n        this.statementLogger = statementLogger;\n        if (statementLogger instanceof Log4JLogger) {\n            this.statementLoggerName = ((Log4JLogger) statementLogger).getLogger().getName();\n        }\n    }\n\n    @Override\n    public String getResultSetLoggerName() {\n        return resultSetLoggerName;\n    }\n\n    @Override\n    public void setResultSetLoggerName(String resultSetLoggerName) {\n        this.resultSetLoggerName = resultSetLoggerName;\n        resultSetLogger = LogFactory.getLog(resultSetLoggerName);\n    }\n\n    public void setResultSetLogger(Log resultSetLogger) {\n        this.resultSetLogger = resultSetLogger;\n        if (resultSetLogger instanceof Log4JLogger) {\n            this.resultSetLoggerName = ((Log4JLogger) resultSetLogger).getLogger().getName();\n        }\n    }\n\n    @Override\n    public boolean isDataSourceLogEnabled() {\n        return dataSourceLogger.isDebugEnabled() && super.isDataSourceLogEnabled();\n    }\n\n    public boolean isConnectionLogErrorEnabled() {\n        return connectionLogger.isErrorEnabled() && super.isConnectionLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isConnectionLogEnabled() {\n        return connectionLogger.isDebugEnabled() && super.isConnectionLogEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogEnabled() {\n        return statementLogger.isDebugEnabled() && super.isStatementLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogEnabled() {\n        return resultSetLogger.isDebugEnabled() && super.isResultSetLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogErrorEnabled() {\n        return resultSetLogger.isErrorEnabled() && super.isResultSetLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogErrorEnabled() {\n        return statementLogger.isErrorEnabled() && super.isStatementLogErrorEnabled();\n    }\n\n    @Override\n    protected void connectionLog(String message) {\n        connectionLogger.debug(message);\n    }\n\n    @Override\n    protected void statementLog(String message) {\n        statementLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLog(String message) {\n        resultSetLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLogError(String message, Throwable error) {\n        resultSetLogger.error(message, error);\n    }\n\n    @Override\n    protected void statementLogError(String message, Throwable error) {\n        statementLogger.error(message, error);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/CommonsLogFilterMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface CommonsLogFilterMBean extends LogFilterMBean {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/Log4j2Filter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class Log4j2Filter extends LogFilter implements Log4j2FilterMBean {\n    private Logger dataSourceLogger = LogManager.getLogger(dataSourceLoggerName);\n    private Logger connectionLogger = LogManager.getLogger(connectionLoggerName);\n    private Logger statementLogger = LogManager.getLogger(statementLoggerName);\n    private Logger resultSetLogger = LogManager.getLogger(resultSetLoggerName);\n\n    @Override\n    public String getDataSourceLoggerName() {\n        return dataSourceLoggerName;\n    }\n\n    @Override\n    public void setDataSourceLoggerName(String dataSourceLoggerName) {\n        this.dataSourceLoggerName = dataSourceLoggerName;\n        dataSourceLogger = LogManager.getLogger(dataSourceLoggerName);\n    }\n\n    public void setDataSourceLogger(Logger dataSourceLogger) {\n        this.dataSourceLogger = dataSourceLogger;\n        this.dataSourceLoggerName = dataSourceLogger.getName();\n    }\n\n    @Override\n    public String getConnectionLoggerName() {\n        return connectionLoggerName;\n    }\n\n    @Override\n    public void setConnectionLoggerName(String connectionLoggerName) {\n        this.connectionLoggerName = connectionLoggerName;\n        connectionLogger = LogManager.getLogger(connectionLoggerName);\n    }\n\n    public void setConnectionLogger(Logger connectionLogger) {\n        this.connectionLogger = connectionLogger;\n        this.connectionLoggerName = connectionLogger.getName();\n    }\n\n    @Override\n    public String getStatementLoggerName() {\n        return statementLoggerName;\n    }\n\n    @Override\n    public void setStatementLoggerName(String statementLoggerName) {\n        this.statementLoggerName = statementLoggerName;\n        statementLogger = LogManager.getLogger(statementLoggerName);\n    }\n\n    public void setStatementLogger(Logger statementLogger) {\n        this.statementLogger = statementLogger;\n        this.statementLoggerName = statementLogger.getName();\n    }\n\n    @Override\n    public String getResultSetLoggerName() {\n        return resultSetLoggerName;\n    }\n\n    @Override\n    public void setResultSetLoggerName(String resultSetLoggerName) {\n        this.resultSetLoggerName = resultSetLoggerName;\n        resultSetLogger = LogManager.getLogger(resultSetLoggerName);\n    }\n\n    public void setResultSetLogger(Logger resultSetLogger) {\n        this.resultSetLogger = resultSetLogger;\n        this.resultSetLoggerName = resultSetLogger.getName();\n    }\n\n    @Override\n    public boolean isConnectionLogErrorEnabled() {\n        return connectionLogger.isErrorEnabled() && super.isConnectionLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isDataSourceLogEnabled() {\n        return dataSourceLogger.isDebugEnabled() && super.isDataSourceLogEnabled();\n    }\n\n    @Override\n    public boolean isConnectionLogEnabled() {\n        return connectionLogger.isDebugEnabled() && super.isConnectionLogEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogEnabled() {\n        return statementLogger.isDebugEnabled() && super.isStatementLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogEnabled() {\n        return resultSetLogger.isDebugEnabled() && super.isResultSetLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogErrorEnabled() {\n        return resultSetLogger.isErrorEnabled() && super.isResultSetLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogErrorEnabled() {\n        return statementLogger.isErrorEnabled() && super.isStatementLogErrorEnabled();\n    }\n\n    @Override\n    protected void connectionLog(String message) {\n        connectionLogger.debug(message);\n    }\n\n    @Override\n    protected void statementLog(String message) {\n        statementLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLog(String message) {\n        resultSetLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLogError(String message, Throwable error) {\n        resultSetLogger.error(message, error);\n    }\n\n    @Override\n    protected void statementLogError(String message, Throwable error) {\n        statementLogger.error(message, error);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/Log4j2FilterMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\npublic interface Log4j2FilterMBean extends LogFilterMBean {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/Log4jFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\nimport org.apache.log4j.Level;\nimport org.apache.log4j.Logger;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class Log4jFilter extends LogFilter implements Log4jFilterMBean {\n    private Logger dataSourceLogger = Logger.getLogger(dataSourceLoggerName);\n    private Logger connectionLogger = Logger.getLogger(connectionLoggerName);\n    private Logger statementLogger = Logger.getLogger(statementLoggerName);\n    private Logger resultSetLogger = Logger.getLogger(resultSetLoggerName);\n\n    @Override\n    public String getDataSourceLoggerName() {\n        return dataSourceLoggerName;\n    }\n\n    @Override\n    public void setDataSourceLoggerName(String dataSourceLoggerName) {\n        this.dataSourceLoggerName = dataSourceLoggerName;\n        dataSourceLogger = Logger.getLogger(dataSourceLoggerName);\n    }\n\n    public void setDataSourceLogger(Logger dataSourceLogger) {\n        this.dataSourceLogger = dataSourceLogger;\n        this.dataSourceLoggerName = dataSourceLogger.getName();\n    }\n\n    @Override\n    public String getConnectionLoggerName() {\n        return connectionLoggerName;\n    }\n\n    @Override\n    public void setConnectionLoggerName(String connectionLoggerName) {\n        this.connectionLoggerName = connectionLoggerName;\n        connectionLogger = Logger.getLogger(connectionLoggerName);\n    }\n\n    public void setConnectionLogger(Logger connectionLogger) {\n        this.connectionLogger = connectionLogger;\n        this.connectionLoggerName = connectionLogger.getName();\n    }\n\n    @Override\n    public String getStatementLoggerName() {\n        return statementLoggerName;\n    }\n\n    @Override\n    public void setStatementLoggerName(String statementLoggerName) {\n        this.statementLoggerName = statementLoggerName;\n        statementLogger = Logger.getLogger(statementLoggerName);\n    }\n\n    public void setStatementLogger(Logger statementLogger) {\n        this.statementLogger = statementLogger;\n        this.statementLoggerName = statementLogger.getName();\n    }\n\n    @Override\n    public String getResultSetLoggerName() {\n        return resultSetLoggerName;\n    }\n\n    @Override\n    public void setResultSetLoggerName(String resultSetLoggerName) {\n        this.resultSetLoggerName = resultSetLoggerName;\n        resultSetLogger = Logger.getLogger(resultSetLoggerName);\n    }\n\n    public void setResultSetLogger(Logger resultSetLogger) {\n        this.resultSetLogger = resultSetLogger;\n        this.resultSetLoggerName = resultSetLogger.getName();\n    }\n\n    @Override\n    public boolean isConnectionLogErrorEnabled() {\n        return connectionLogger.isEnabledFor(Level.ERROR) && super.isConnectionLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isDataSourceLogEnabled() {\n        return dataSourceLogger.isDebugEnabled() && super.isDataSourceLogEnabled();\n    }\n\n    @Override\n    public boolean isConnectionLogEnabled() {\n        return connectionLogger.isDebugEnabled() && super.isConnectionLogEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogEnabled() {\n        return statementLogger.isDebugEnabled() && super.isStatementLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogEnabled() {\n        return resultSetLogger.isDebugEnabled() && super.isResultSetLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogErrorEnabled() {\n        return resultSetLogger.isEnabledFor(Level.ERROR) && super.isResultSetLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogErrorEnabled() {\n        return statementLogger.isEnabledFor(Level.ERROR) && super.isStatementLogErrorEnabled();\n    }\n\n    @Override\n    protected void connectionLog(String message) {\n        connectionLogger.debug(message);\n    }\n\n    @Override\n    protected void statementLog(String message) {\n        statementLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLog(String message) {\n        resultSetLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLogError(String message, Throwable error) {\n        resultSetLogger.error(message, error);\n    }\n\n    @Override\n    protected void statementLogError(String message, Throwable error) {\n        statementLogger.error(message, error);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/Log4jFilterMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface Log4jFilterMBean extends LogFilterMBean {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.filter.FilterEventAdapter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.*;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.SQLUtils.FormatOption;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.MySqlUtils;\n\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic abstract class LogFilter extends FilterEventAdapter implements LogFilterMBean {\n    protected String dataSourceLoggerName = \"druid.sql.DataSource\";\n    protected String connectionLoggerName = \"druid.sql.Connection\";\n    protected String statementLoggerName = \"druid.sql.Statement\";\n    protected String resultSetLoggerName = \"druid.sql.ResultSet\";\n\n    private boolean connectionConnectBeforeLogEnable = true;\n    private boolean connectionConnectAfterLogEnable = true;\n    private boolean connectionCommitAfterLogEnable = true;\n    private boolean connectionRollbackAfterLogEnable = true;\n    private boolean connectionCloseAfterLogEnable = true;\n\n    private boolean statementCreateAfterLogEnable = true;\n    private boolean statementPrepareAfterLogEnable = true;\n    private boolean statementPrepareCallAfterLogEnable = true;\n\n    private boolean statementExecuteAfterLogEnable = true;\n    private boolean statementExecuteQueryAfterLogEnable = true;\n    private boolean statementExecuteUpdateAfterLogEnable = true;\n    private boolean statementExecuteBatchAfterLogEnable = true;\n    private boolean statementExecutableSqlLogEnable;\n\n    private boolean statementCloseAfterLogEnable = true;\n\n    private boolean statementParameterClearLogEnable = true;\n    private boolean statementParameterSetLogEnable = true;\n\n    private boolean resultSetNextAfterLogEnable = true;\n    private boolean resultSetOpenAfterLogEnable = true;\n    private boolean resultSetCloseAfterLogEnable = true;\n\n    private boolean dataSourceLogEnabled = true;\n    private boolean connectionLogEnabled = true;\n    private boolean connectionLogErrorEnabled = true;\n    private boolean statementLogEnabled = true;\n    private boolean statementLogErrorEnabled = true;\n    private boolean resultSetLogEnabled = true;\n    private boolean resultSetLogErrorEnabled = true;\n\n    private FormatOption statementSqlFormatOption = new FormatOption(false, true);\n    private boolean statementLogSqlPrettyFormat;\n\n    protected DataSourceProxy dataSource;\n\n    public LogFilter() {\n        this(System.getProperties());\n    }\n\n    public LogFilter(final Properties properties) {\n        configFromProperties(properties);\n    }\n\n    public void configFromProperties(Properties properties) {\n        if (properties == null) {\n            return;\n        }\n\n        {\n            String prop = properties.getProperty(\"druid.log.conn\");\n            if (\"false\".equals(prop)) {\n                connectionLogEnabled = false;\n            } else if (\"true\".equals(prop)) {\n                connectionLogEnabled = true;\n            }\n        }\n        {\n            String prop = properties.getProperty(\"druid.log.stmt\");\n            if (\"false\".equals(prop)) {\n                statementLogEnabled = false;\n            } else if (\"true\".equals(prop)) {\n                statementLogEnabled = true;\n            }\n        }\n        {\n            String prop = properties.getProperty(\"druid.log.rs\");\n            if (\"false\".equals(prop)) {\n                resultSetLogEnabled = false;\n            } else if (\"true\".equals(prop)) {\n                resultSetLogEnabled = true;\n            }\n        }\n        {\n            String prop = properties.getProperty(\"druid.log.stmt.executableSql\");\n            if (\"true\".equals(prop)) {\n                statementExecutableSqlLogEnable = true;\n            } else if (\"false\".equals(prop)) {\n                statementExecutableSqlLogEnable = false;\n            }\n        }\n        {\n            String prop = properties.getProperty(\"druid.log.conn.logError\");\n            if (\"false\".equals(prop)) {\n                connectionLogErrorEnabled = false;\n            } else if (\"true\".equals(prop)) {\n                connectionLogErrorEnabled = true;\n            }\n        }\n        {\n            String prop = properties.getProperty(\"druid.log.stmt.logError\");\n            if (\"false\".equals(prop)) {\n                statementLogErrorEnabled = false;\n            } else if (\"true\".equals(prop)) {\n                statementLogErrorEnabled = true;\n            }\n        }\n        {\n            String prop = properties.getProperty(\"druid.log.rs.logError\");\n            if (\"false\".equals(prop)) {\n                resultSetLogErrorEnabled = false;\n            } else if (\"true\".equals(prop)) {\n                resultSetLogErrorEnabled = true;\n            }\n        }\n    }\n\n    private DbType dbType;\n    @Override\n    public void init(DataSourceProxy dataSource) {\n        this.dataSource = dataSource;\n        dbType = DbType.of(dataSource.getDbType());\n        configFromProperties(dataSource.getConnectProperties());\n        //configFromProperties(System.getProperties());\n    }\n\n    public boolean isConnectionLogErrorEnabled() {\n        return connectionLogErrorEnabled;\n    }\n\n    public boolean isResultSetCloseAfterLogEnabled() {\n        return isResultSetLogEnabled() && resultSetCloseAfterLogEnable;\n    }\n\n    public void setResultSetCloseAfterLogEnabled(boolean resultSetCloseAfterLogEnable) {\n        this.resultSetCloseAfterLogEnable = resultSetCloseAfterLogEnable;\n    }\n\n    public void setConnectionLogErrorEnabled(boolean connectionLogErrorEnabled) {\n        this.connectionLogErrorEnabled = connectionLogErrorEnabled;\n    }\n\n    public boolean isResultSetLogErrorEnabled() {\n        return resultSetLogErrorEnabled;\n    }\n\n    public void setResultSetLogErrorEnabled(boolean resultSetLogErrorEnabled) {\n        this.resultSetLogErrorEnabled = resultSetLogErrorEnabled;\n    }\n\n    public boolean isConnectionConnectBeforeLogEnabled() {\n        return isConnectionLogEnabled() && connectionConnectBeforeLogEnable;\n    }\n\n    public void setConnectionConnectBeforeLogEnabled(boolean beforeConnectionConnectLogEnable) {\n        this.connectionConnectBeforeLogEnable = beforeConnectionConnectLogEnable;\n    }\n\n    public boolean isConnectionCloseAfterLogEnabled() {\n        return isConnectionLogEnabled() && connectionCloseAfterLogEnable;\n    }\n\n    public boolean isConnectionRollbackAfterLogEnabled() {\n        return isConnectionLogEnabled() && connectionRollbackAfterLogEnable;\n    }\n\n    public void setConnectionRollbackAfterLogEnabled(boolean connectionRollbackAfterLogEnable) {\n        this.connectionRollbackAfterLogEnable = connectionRollbackAfterLogEnable;\n    }\n\n    public void setConnectionCloseAfterLogEnabled(boolean afterConnectionCloseLogEnable) {\n        this.connectionCloseAfterLogEnable = afterConnectionCloseLogEnable;\n    }\n\n    public boolean isConnectionCommitAfterLogEnabled() {\n        return isConnectionLogEnabled() && connectionCommitAfterLogEnable;\n    }\n\n    public void setConnectionCommitAfterLogEnabled(boolean afterConnectionCommitLogEnable) {\n        this.connectionCommitAfterLogEnable = afterConnectionCommitLogEnable;\n    }\n\n    public boolean isConnectionConnectAfterLogEnabled() {\n        return isConnectionLogEnabled() && connectionConnectAfterLogEnable;\n    }\n\n    public void setConnectionConnectAfterLogEnabled(boolean afterConnectionConnectLogEnable) {\n        this.connectionConnectAfterLogEnable = afterConnectionConnectLogEnable;\n    }\n\n    public boolean isResultSetNextAfterLogEnabled() {\n        return isResultSetLogEnabled() && resultSetNextAfterLogEnable;\n    }\n\n    public void setResultSetNextAfterLogEnabled(boolean afterResultSetNextLogEnable) {\n        this.resultSetNextAfterLogEnable = afterResultSetNextLogEnable;\n    }\n\n    public boolean isResultSetOpenAfterLogEnabled() {\n        return isResultSetLogEnabled() && resultSetOpenAfterLogEnable;\n    }\n\n    public void setResultSetOpenAfterLogEnabled(boolean afterResultSetOpenLogEnable) {\n        this.resultSetOpenAfterLogEnable = afterResultSetOpenLogEnable;\n    }\n\n    public boolean isStatementCloseAfterLogEnabled() {\n        return isStatementLogEnabled() && statementCloseAfterLogEnable;\n    }\n\n    public void setStatementCloseAfterLogEnabled(boolean afterStatementCloseLogEnable) {\n        this.statementCloseAfterLogEnable = afterStatementCloseLogEnable;\n    }\n\n    public boolean isStatementCreateAfterLogEnabled() {\n        return isStatementLogEnabled() && statementCreateAfterLogEnable;\n    }\n\n    public void setStatementCreateAfterLogEnabled(boolean afterStatementCreateLogEnable) {\n        this.statementCreateAfterLogEnable = afterStatementCreateLogEnable;\n    }\n\n    public boolean isStatementExecuteBatchAfterLogEnabled() {\n        return isStatementLogEnabled() && statementExecuteBatchAfterLogEnable;\n    }\n\n    public void setStatementExecuteBatchAfterLogEnabled(boolean afterStatementExecuteBatchLogEnable) {\n        this.statementExecuteBatchAfterLogEnable = afterStatementExecuteBatchLogEnable;\n    }\n\n    public boolean isStatementExecuteAfterLogEnabled() {\n        return isStatementLogEnabled() && statementExecuteAfterLogEnable;\n    }\n\n    public void setStatementExecuteAfterLogEnabled(boolean afterStatementExecuteLogEnable) {\n        this.statementExecuteAfterLogEnable = afterStatementExecuteLogEnable;\n    }\n\n    public boolean isStatementExecuteQueryAfterLogEnabled() {\n        return isStatementLogEnabled() && statementExecuteQueryAfterLogEnable;\n    }\n\n    public void setStatementExecuteQueryAfterLogEnabled(boolean afterStatementExecuteQueryLogEnable) {\n        this.statementExecuteQueryAfterLogEnable = afterStatementExecuteQueryLogEnable;\n    }\n\n    public boolean isStatementExecuteUpdateAfterLogEnabled() {\n        return isStatementLogEnabled() && statementExecuteUpdateAfterLogEnable;\n    }\n\n    public void setStatementExecuteUpdateAfterLogEnabled(boolean afterStatementExecuteUpdateLogEnable) {\n        this.statementExecuteUpdateAfterLogEnable = afterStatementExecuteUpdateLogEnable;\n    }\n\n    public boolean isStatementExecutableSqlLogEnable() {\n        return statementExecutableSqlLogEnable;\n    }\n\n    public void setStatementExecutableSqlLogEnable(boolean statementExecutableSqlLogEnable) {\n        this.statementExecutableSqlLogEnable = statementExecutableSqlLogEnable;\n    }\n\n    public boolean isStatementPrepareCallAfterLogEnabled() {\n        return isStatementLogEnabled() && statementPrepareCallAfterLogEnable;\n    }\n\n    public void setStatementPrepareCallAfterLogEnabled(boolean afterStatementPrepareCallLogEnable) {\n        this.statementPrepareCallAfterLogEnable = afterStatementPrepareCallLogEnable;\n    }\n\n    public boolean isStatementPrepareAfterLogEnabled() {\n        return isStatementLogEnabled() && statementPrepareAfterLogEnable;\n    }\n\n    public void setStatementPrepareAfterLogEnabled(boolean afterStatementPrepareLogEnable) {\n        this.statementPrepareAfterLogEnable = afterStatementPrepareLogEnable;\n    }\n\n    public boolean isDataSourceLogEnabled() {\n        return dataSourceLogEnabled;\n    }\n\n    public void setDataSourceLogEnabled(boolean dataSourceLogEnabled) {\n        this.dataSourceLogEnabled = dataSourceLogEnabled;\n    }\n\n    public boolean isConnectionLogEnabled() {\n        return connectionLogEnabled;\n    }\n\n    public void setConnectionLogEnabled(boolean connectionLogEnabled) {\n        this.connectionLogEnabled = connectionLogEnabled;\n    }\n\n    public boolean isStatementLogEnabled() {\n        return statementLogEnabled;\n    }\n\n    public void setStatementLogEnabled(boolean statementLogEnabled) {\n        this.statementLogEnabled = statementLogEnabled;\n    }\n\n    public boolean isStatementLogErrorEnabled() {\n        return statementLogErrorEnabled;\n    }\n\n    public void setStatementLogErrorEnabled(boolean statementLogErrorEnabled) {\n        this.statementLogErrorEnabled = statementLogErrorEnabled;\n    }\n\n    public boolean isResultSetLogEnabled() {\n        return resultSetLogEnabled;\n    }\n\n    public void setResultSetLogEnabled(boolean resultSetLogEnabled) {\n        this.resultSetLogEnabled = resultSetLogEnabled;\n    }\n\n    public boolean isStatementParameterSetLogEnabled() {\n        return isStatementLogEnabled() && statementParameterSetLogEnable;\n    }\n\n    public void setStatementParameterSetLogEnabled(boolean statementParameterSetLogEnable) {\n        this.statementParameterSetLogEnable = statementParameterSetLogEnable;\n    }\n\n    public boolean isStatementParameterClearLogEnable() {\n        return isStatementLogEnabled() && statementParameterClearLogEnable;\n    }\n\n    public void setStatementParameterClearLogEnable(boolean statementParameterClearLogEnable) {\n        this.statementParameterClearLogEnable = statementParameterClearLogEnable;\n    }\n\n    public FormatOption getStatementSqlFormatOption() {\n        return this.statementSqlFormatOption;\n    }\n\n    public void setStatementSqlFormatOption(FormatOption formatOption) {\n        this.statementSqlFormatOption = formatOption;\n    }\n\n    public boolean isStatementSqlPrettyFormat() {\n        return this.statementLogSqlPrettyFormat;\n    }\n\n    public void setStatementSqlPrettyFormat(boolean statementSqlPrettyFormat) {\n        this.statementLogSqlPrettyFormat = statementSqlPrettyFormat;\n    }\n\n    protected abstract void connectionLog(String message);\n\n    protected abstract void statementLog(String message);\n\n    protected abstract void statementLogError(String message, Throwable error);\n\n    protected abstract void resultSetLog(String message);\n\n    protected abstract void resultSetLogError(String message, Throwable error);\n\n    public void connection_connectAfter(ConnectionProxy connection) {\n        if (connection == null) {\n            return;\n        }\n\n        if (connectionConnectAfterLogEnable && isConnectionLogEnabled()) {\n            StringBuilder msg = new StringBuilder(34)\n                    .append(\"{conn-\")\n                    .append(connection.getId());\n\n            Connection impl = connection.getRawObject();\n            if (DbType.mysql.equals(dbType)) {\n                Long procId = MySqlUtils.getId(impl);\n                if (procId != null) {\n                    msg.append(\",procId-\").append(procId);\n                }\n            }\n\n            msg.append(\"} connected\");\n            connectionLog(msg.toString());\n        }\n    }\n\n    @Override\n    public Savepoint connection_setSavepoint(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        Savepoint savepoint = chain.connection_setSavepoint(connection);\n\n        if (isConnectionLogEnabled()) {\n            connectionLog(\"{conn-\" + connection.getId() + \"} setSavepoint-\" + savepointToString(savepoint));\n        }\n\n        return savepoint;\n    }\n\n    @Override\n    public Savepoint connection_setSavepoint(FilterChain chain, ConnectionProxy connection, String name)\n            throws SQLException {\n        Savepoint savepoint = chain.connection_setSavepoint(connection, name);\n\n        if (isConnectionLogEnabled()) {\n            connectionLog(\"{conn-\" + connection.getId() + \"} setSavepoint-\" + name);\n        }\n\n        return savepoint;\n    }\n\n    @Override\n    public void connection_rollback(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        super.connection_rollback(chain, connection);\n\n        if (connectionRollbackAfterLogEnable && isConnectionLogEnabled()) {\n            connectionLog(\"{conn \" + connection.getId() + \"} rollback\");\n        }\n    }\n\n    @Override\n    public void connection_rollback(FilterChain chain, ConnectionProxy connection, Savepoint savePoint)\n            throws SQLException {\n        super.connection_rollback(chain, connection, savePoint);\n\n        if (connectionRollbackAfterLogEnable && isConnectionLogEnabled()) {\n            connectionLog(\"{conn \" + connection.getId() + \"} rollback -> \" + savepointToString(savePoint));\n        }\n    }\n\n    @Override\n    public void connection_commit(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        super.connection_commit(chain, connection);\n\n        if (connectionCommitAfterLogEnable && isConnectionLogEnabled()) {\n            connectionLog(\"{conn-\" + connection.getId() + \"} committed\");\n        }\n    }\n\n    @Override\n    public void connection_setAutoCommit(FilterChain chain, ConnectionProxy connection, boolean autoCommit)\n            throws SQLException {\n        if (isConnectionLogEnabled()) {\n            connectionLog(\"{conn-\" + connection.getId() + \"} setAutoCommit \" + autoCommit);\n        }\n        chain.connection_setAutoCommit(connection, autoCommit);\n    }\n\n    @Override\n    public void connection_close(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        super.connection_close(chain, connection);\n\n        if (connectionCloseAfterLogEnable && isConnectionLogEnabled()) {\n            connectionLog(\"{conn-\" + connection.getId() + \"} closed\");\n        }\n    }\n\n    @Override\n    public void statement_close(FilterChain chain, StatementProxy statement) throws SQLException {\n        super.statement_close(chain, statement);\n\n        if (statementCloseAfterLogEnable && isStatementLogEnabled()) {\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement) + \"} closed\");\n        }\n    }\n\n    @Override\n    protected void statementExecuteBefore(StatementProxy statement, String sql) {\n        statement.setLastExecuteStartNano();\n        if (statement instanceof PreparedStatementProxy) {\n            logParameter((PreparedStatementProxy) statement);\n        }\n    }\n\n    @Override\n    protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) {\n        logExecutableSql(statement, sql);\n\n        if (statementExecuteAfterLogEnable && isStatementLogEnabled()) {\n            statement.setLastExecuteTimeNano();\n            double nanos = statement.getLastExecuteTimeNano();\n            double millis = nanos / (1000 * 1000);\n\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement) + \"} executed. \"\n                    + millis + \" millis. \" + sql);\n        }\n    }\n\n    @Override\n    protected void statementExecuteBatchBefore(StatementProxy statement) {\n        statement.setLastExecuteStartNano();\n    }\n\n    @Override\n    protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) {\n        String sql;\n        if (statement instanceof PreparedStatementProxy) {\n            sql = ((PreparedStatementProxy) statement).getSql();\n        } else {\n            sql = statement.getBatchSql();\n        }\n\n        logExecutableSql(statement, sql);\n\n        if (statementExecuteBatchAfterLogEnable && isStatementLogEnabled()) {\n            statement.setLastExecuteTimeNano();\n            double nanos = statement.getLastExecuteTimeNano();\n            double millis = nanos / (1000 * 1000);\n\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement)\n                    + \"} batch executed. \" + millis + \" millis. \" + sql);\n        }\n    }\n\n    @Override\n    protected void statementExecuteQueryBefore(StatementProxy statement, String sql) {\n        statement.setLastExecuteStartNano();\n        if (statement instanceof PreparedStatementProxy) {\n            logParameter((PreparedStatementProxy) statement);\n        }\n    }\n\n    @Override\n    protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {\n        logExecutableSql(statement, sql);\n\n        if (statementExecuteQueryAfterLogEnable && isStatementLogEnabled()) {\n            statement.setLastExecuteTimeNano();\n            double nanos = statement.getLastExecuteTimeNano();\n            double millis = nanos / (1000 * 1000);\n\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement) + \", rs-\"\n                    + resultSet.getId() + \"} query executed. \" + millis + \" millis. \" + sql);\n        }\n    }\n\n    @Override\n    protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) {\n        statement.setLastExecuteStartNano();\n        if (statement instanceof PreparedStatementProxy) {\n            logParameter((PreparedStatementProxy) statement);\n        }\n    }\n\n    @Override\n    protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) {\n        logExecutableSql(statement, sql);\n\n        if (statementExecuteUpdateAfterLogEnable && isStatementLogEnabled()) {\n            statement.setLastExecuteTimeNano();\n            double nanos = statement.getLastExecuteTimeNano();\n            double millis = nanos / (1000 * 1000);\n\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement)\n                    + \"} update executed. effort \" + updateCount + \". \" + millis + \" millis. \" + sql);\n        }\n    }\n\n    private void logExecutableSql(StatementProxy statement, String sql) {\n        if ((!isStatementExecutableSqlLogEnable()) || !isStatementLogEnabled()) {\n            return;\n        }\n\n        int parametersSize = statement.getParametersSize();\n        if (parametersSize == 0) {\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement) + \"} executed. \"\n                    + sql);\n            return;\n        }\n\n        List<Object> parameters = new ArrayList<Object>(parametersSize);\n        for (int i = 0; i < parametersSize; ++i) {\n            JdbcParameter jdbcParam = statement.getParameter(i);\n            parameters.add(jdbcParam != null\n                    ? jdbcParam.getValue()\n                    : null);\n        }\n\n        DbType dbType = DbType.of(statement.getConnectionProxy().getDirectDataSource().getDbType());\n        String formattedSql = SQLUtils.format(sql, dbType, parameters, this.statementSqlFormatOption);\n        statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement) + \"} executed. \"\n                + formattedSql);\n    }\n\n    @Override\n    public void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_close(resultSet);\n\n        if (isResultSetCloseAfterLogEnabled()) {\n            StringBuilder buf = new StringBuilder();\n            buf.append(\"{conn-\");\n            buf.append(resultSet.getStatementProxy().getConnectionProxy().getId());\n            buf.append(\", \");\n            buf.append(stmtId(resultSet));\n            buf.append(\", rs-\");\n            buf.append(resultSet.getId());\n            buf.append(\"} closed\");\n            resultSetLog(buf.toString());\n        }\n    }\n\n    @Override\n    public boolean resultSet_next(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        boolean moreRows = super.resultSet_next(chain, resultSet);\n\n        if (moreRows) {\n            if (resultSetNextAfterLogEnable && isResultSetLogEnabled()) {\n                try {\n                    StringBuilder buf = new StringBuilder();\n                    buf.append(\"{conn-\");\n                    buf.append(resultSet.getStatementProxy().getConnectionProxy().getId());\n                    buf.append(\", \");\n                    buf.append(stmtId(resultSet));\n                    buf.append(\", rs-\");\n                    buf.append(resultSet.getId());\n                    buf.append(\"}\");\n                    buf.append(\" Result: [\");\n\n                    ResultSetMetaData meta = resultSet.getMetaData();\n                    for (int i = 0, size = meta.getColumnCount(); i < size; ++i) {\n                        if (i != 0) {\n                            buf.append(\", \");\n                        }\n                        int columnIndex = i + 1;\n                        int type = meta.getColumnType(columnIndex);\n\n                        Object value;\n                        if (type == Types.TIMESTAMP) {\n                            value = resultSet.getTimestamp(columnIndex);\n                        } else if (type == Types.BLOB) {\n                            value = \"<BLOB>\";\n                        } else if (type == Types.CLOB) {\n                            value = \"<CLOB>\";\n                        } else if (type == Types.NCLOB) {\n                            value = \"<NCLOB>\";\n                        } else if (type == Types.BINARY) {\n                            value = \"<BINARY>\";\n                        } else {\n                            value = resultSet.getObject(columnIndex);\n                        }\n                        buf.append(value);\n                    }\n\n                    buf.append(\"]\");\n\n                    resultSetLog(buf.toString());\n                } catch (SQLException ex) {\n                    resultSetLogError(\"logging error\", ex);\n                }\n            }\n        }\n\n        return moreRows;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterIndex);\n\n        if (obj instanceof ResultSetProxy) {\n            resultSetOpenAfter((ResultSetProxy) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterIndex, map);\n\n        if (obj instanceof ResultSetProxy) {\n            resultSetOpenAfter((ResultSetProxy) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterName);\n\n        if (obj instanceof ResultSetProxy) {\n            resultSetOpenAfter((ResultSetProxy) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement,\n                                              String parameterName, java.util.Map<String, Class<?>> map)\n            throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterName, map);\n\n        if (obj instanceof ResultSetProxy) {\n            resultSetOpenAfter((ResultSetProxy) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    protected void resultSetOpenAfter(ResultSetProxy resultSet) {\n        if (resultSetOpenAfterLogEnable && isResultSetLogEnabled()) {\n            try {\n                StringBuilder buf = new StringBuilder();\n                buf.append(\"{conn-\");\n                buf.append(resultSet.getStatementProxy().getConnectionProxy().getId());\n                buf.append(\", \");\n                buf.append(stmtId(resultSet));\n                buf.append(\", rs-\");\n                buf.append(resultSet.getId());\n                buf.append(\"}\");\n\n                String resultId = buf.toString();\n                resultSetLog(resultId + \" open\");\n\n                buf.append(\" Header: [\");\n\n                ResultSetMetaData meta = resultSet.getMetaData();\n                for (int i = 0, size = meta.getColumnCount(); i < size; ++i) {\n                    if (i != 0) {\n                        buf.append(\", \");\n                    }\n                    buf.append(meta.getColumnName(i + 1));\n                }\n                buf.append(\"]\");\n\n                resultSetLog(buf.toString());\n            } catch (SQLException ex) {\n                resultSetLogError(\"logging error\", ex);\n            }\n        }\n    }\n\n    protected void statementCreateAfter(StatementProxy statement) {\n        if (statementCreateAfterLogEnable && isStatementLogEnabled()) {\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", stmt-\" + statement.getId()\n                    + \"} created\");\n        }\n    }\n\n    protected void statementPrepareAfter(PreparedStatementProxy statement) {\n        if (statementPrepareAfterLogEnable && isStatementLogEnabled()) {\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", pstmt-\" + statement.getId()\n                    + \"} created. \" + statement.getSql());\n        }\n    }\n\n    protected void statementPrepareCallAfter(CallableStatementProxy statement) {\n        if (statementPrepareCallAfterLogEnable && isStatementLogEnabled()) {\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", cstmt-\" + statement.getId()\n                    + \"} created. \" + statement.getSql());\n        }\n    }\n\n    @Override\n    protected void statement_executeErrorAfter(StatementProxy statement, String sql, Throwable error) {\n        if (this.isStatementLogErrorEnabled()) {\n            if (!isStatementExecutableSqlLogEnable()) {\n                statementLogError(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement)\n                        + \"} execute error. \" + sql, error);\n            } else {\n                int parametersSize = statement.getParametersSize();\n                if (parametersSize > 0) {\n                    List<Object> parameters = new ArrayList<Object>(parametersSize);\n                    for (int i = 0; i < parametersSize; ++i) {\n                        JdbcParameter jdbcParam = statement.getParameter(i);\n                        parameters.add(jdbcParam != null\n                                ? jdbcParam.getValue()\n                                : null);\n                    }\n                    DbType dbType = DbType.of(statement.getConnectionProxy().getDirectDataSource().getDbType());\n                    String formattedSql = SQLUtils.format(sql, dbType, parameters, this.statementSqlFormatOption);\n                    statementLogError(\"{conn-\" + statement.getConnectionProxy().getId()\n                                    + \", \" + stmtId(statement)\n                                    + \"} execute error. \" + formattedSql,\n                            error\n                    );\n                } else {\n                    statementLogError(\"{conn-\" + statement.getConnectionProxy().getId() + \", \" + stmtId(statement)\n                            + \"} execute error. \" + sql, error);\n                }\n            }\n        }\n    }\n\n    private String stmtId(ResultSetProxy resultSet) {\n        return stmtId(resultSet.getStatementProxy());\n    }\n\n    private String stmtId(StatementProxy statement) {\n        StringBuilder buf = new StringBuilder();\n        if (statement instanceof CallableStatementProxy) {\n            buf.append(\"cstmt-\");\n        } else if (statement instanceof PreparedStatementProxy) {\n            buf.append(\"pstmt-\");\n        } else {\n            buf.append(\"stmt-\");\n        }\n        buf.append(statement.getId());\n\n        return buf.toString();\n    }\n\n    protected void logParameter(PreparedStatementProxy statement) {\n        if (isStatementParameterSetLogEnabled()) {\n            {\n                StringBuilder buf = new StringBuilder();\n                buf.append(\"{conn-\");\n                buf.append(statement.getConnectionProxy().getId());\n                buf.append(\", \");\n                buf.append(stmtId(statement));\n                buf.append(\"}\");\n                buf.append(\" Parameters : [\");\n\n                for (int i = 0, parametersSize = statement.getParametersSize(); i < parametersSize; ++i) {\n                    JdbcParameter parameter = statement.getParameter(i);\n                    if (i != 0) {\n                        buf.append(\", \");\n                    }\n                    if (parameter == null) {\n                        continue;\n                    }\n\n                    int sqlType = parameter.getSqlType();\n                    Object value = parameter.getValue();\n                    switch (sqlType) {\n                        case Types.NULL:\n                            buf.append(\"NULL\");\n                            break;\n                        default:\n                            buf.append(String.valueOf(value));\n                            break;\n                    }\n                }\n                buf.append(\"]\");\n                statementLog(buf.toString());\n            }\n            {\n                StringBuilder buf = new StringBuilder();\n                buf.append(\"{conn-\");\n                buf.append(statement.getConnectionProxy().getId());\n                buf.append(\", \");\n                buf.append(stmtId(statement));\n                buf.append(\"}\");\n                buf.append(\" Types : [\");\n                for (int i = 0, parametersSize = statement.getParametersSize(); i < parametersSize; ++i) {\n                    JdbcParameter parameter = statement.getParameter(i);\n                    if (i != 0) {\n                        buf.append(\", \");\n                    }\n                    if (parameter == null) {\n                        continue;\n                    }\n                    int sqlType = parameter.getSqlType();\n                    buf.append(JdbcUtils.getTypeName(sqlType));\n                }\n                buf.append(\"]\");\n                statementLog(buf.toString());\n            }\n        }\n    }\n\n    @Override\n    public void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection conn) throws SQLException {\n        long connectionId = -1;\n\n        if (conn.getConnectionHolder() != null) {\n            ConnectionProxy connection = (ConnectionProxy) conn.getConnectionHolder().getConnection();\n            connectionId = connection.getId();\n        }\n\n        chain.dataSource_recycle(conn);\n\n        if (connectionCloseAfterLogEnable && isConnectionLogEnabled()) {\n            connectionLog(\"{conn-\" + connectionId + \"} pool-recycle\");\n        }\n    }\n\n    @Override\n    public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource,\n                                                          long maxWaitMillis) throws SQLException {\n        DruidPooledConnection conn = chain.dataSource_connect(dataSource, maxWaitMillis);\n\n        ConnectionProxy connection = (ConnectionProxy) conn.getConnectionHolder().getConnection();\n\n        if (connectionConnectAfterLogEnable && isConnectionLogEnabled()) {\n            connectionLog(\"{conn-\" + connection.getId() + \"} pool-connect\");\n        }\n\n        return conn;\n    }\n\n    @Override\n    public void preparedStatement_clearParameters(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException {\n        if (isStatementParameterClearLogEnable()) {\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", pstmt-\" + statement.getId()\n                    + \"} clearParameters. \");\n        }\n        chain.preparedStatement_clearParameters(statement);\n    }\n\n    @Override\n    public void statement_clearBatch(FilterChain chain, StatementProxy statement)\n            throws SQLException {\n        if (isStatementParameterClearLogEnable()) {\n            statementLog(\"{conn-\" + statement.getConnectionProxy().getId() + \", stmt-\" + statement.getId()\n                    + \"} clearBatch. \");\n        }\n        chain.statement_clearBatch(statement);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) {\n        return iface == this.getClass() || iface == LogFilter.class;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) {\n        if (iface == this.getClass() || iface == LogFilter.class) {\n            return (T) this;\n        }\n        return null;\n    }\n\n    protected String savepointToString(Savepoint savePoint) {\n        String savePointString = null;\n        try {\n            savePointString = savePoint.getSavepointName();\n        } catch (SQLException e) {\n            try {\n                savePointString = String.valueOf(savePoint.getSavepointId());\n            } catch (SQLException e1) {\n                savePointString = savePoint.toString();\n            }\n        }\n        return savePointString;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/LogFilterMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\nimport com.alibaba.druid.sql.SQLUtils.FormatOption;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface LogFilterMBean {\n    String getDataSourceLoggerName();\n\n    void setDataSourceLoggerName(String loggerName);\n\n    boolean isDataSourceLogEnabled();\n\n    void setDataSourceLogEnabled(boolean dataSourceLogEnabled);\n\n    // //////////////\n\n    String getConnectionLoggerName();\n\n    void setConnectionLoggerName(String loggerName);\n\n    boolean isConnectionLogEnabled();\n\n    void setConnectionLogEnabled(boolean connectionLogEnabled);\n\n    boolean isConnectionLogErrorEnabled();\n\n    void setConnectionLogErrorEnabled(boolean connectionLogErrorEnabled);\n\n    boolean isConnectionConnectBeforeLogEnabled();\n\n    void setConnectionConnectBeforeLogEnabled(boolean beforeConnectionConnectLogEnable);\n\n    boolean isConnectionConnectAfterLogEnabled();\n\n    void setConnectionConnectAfterLogEnabled(boolean afterConnectionConnectLogEnable);\n\n    boolean isConnectionCloseAfterLogEnabled();\n\n    void setConnectionCloseAfterLogEnabled(boolean afterConnectionCloseLogEnable);\n\n    boolean isConnectionCommitAfterLogEnabled();\n\n    void setConnectionCommitAfterLogEnabled(boolean afterConnectionCommitLogEnable);\n\n    // ////////////\n\n    String getStatementLoggerName();\n\n    void setStatementLoggerName(String loggerName);\n\n    boolean isStatementLogEnabled();\n\n    void setStatementLogEnabled(boolean statementLogEnabled);\n\n    boolean isStatementCloseAfterLogEnabled();\n\n    void setStatementCloseAfterLogEnabled(boolean afterStatementCloseLogEnable);\n\n    boolean isStatementCreateAfterLogEnabled();\n\n    void setStatementCreateAfterLogEnabled(boolean afterStatementCreateLogEnable);\n\n    boolean isStatementExecuteBatchAfterLogEnabled();\n\n    void setStatementExecuteBatchAfterLogEnabled(boolean afterStatementExecuteBatchLogEnable);\n\n    boolean isStatementExecuteAfterLogEnabled();\n\n    void setStatementExecuteAfterLogEnabled(boolean afterStatementExecuteLogEnable);\n\n    boolean isStatementExecuteQueryAfterLogEnabled();\n\n    void setStatementExecuteQueryAfterLogEnabled(boolean afterStatementExecuteQueryLogEnable);\n\n    boolean isStatementExecuteUpdateAfterLogEnabled();\n\n    void setStatementExecuteUpdateAfterLogEnabled(boolean afterStatementExecuteUpdateLogEnable);\n\n    boolean isStatementPrepareCallAfterLogEnabled();\n\n    void setStatementPrepareCallAfterLogEnabled(boolean afterStatementPrepareCallLogEnable);\n\n    boolean isStatementPrepareAfterLogEnabled();\n\n    void setStatementPrepareAfterLogEnabled(boolean afterStatementPrepareLogEnable);\n\n    boolean isStatementLogErrorEnabled();\n\n    void setStatementLogErrorEnabled(boolean statementLogErrorEnabled);\n\n    boolean isStatementParameterSetLogEnabled();\n\n    void setStatementParameterSetLogEnabled(boolean statementParameterSetLogEnable);\n\n    // //////////////\n\n    String getResultSetLoggerName();\n\n    void setResultSetLoggerName(String loggerName);\n\n    boolean isResultSetLogEnabled();\n\n    void setResultSetLogEnabled(boolean resultSetLogEnabled);\n\n    boolean isResultSetNextAfterLogEnabled();\n\n    void setResultSetNextAfterLogEnabled(boolean afterResultSetNextLogEnable);\n\n    boolean isResultSetOpenAfterLogEnabled();\n\n    void setResultSetOpenAfterLogEnabled(boolean afterResultSetOpenLogEnable);\n\n    boolean isResultSetLogErrorEnabled();\n\n    void setResultSetLogErrorEnabled(boolean resultSetLogErrorEnabled);\n\n    boolean isResultSetCloseAfterLogEnabled();\n\n    void setResultSetCloseAfterLogEnabled(boolean resultSetCloseAfterLogEnable);\n\n    FormatOption getStatementSqlFormatOption();\n\n    void setStatementSqlFormatOption(FormatOption formatOption);\n\n    boolean isStatementSqlPrettyFormat();\n\n    void setStatementSqlPrettyFormat(boolean statementSqlPrettyFormat);\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/logging/Slf4jLogFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.logging;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Properties;\n\npublic class Slf4jLogFilter extends LogFilter {\n    private Logger dataSourceLogger = LoggerFactory.getLogger(dataSourceLoggerName);\n    private Logger connectionLogger = LoggerFactory.getLogger(connectionLoggerName);\n    private Logger statementLogger = LoggerFactory.getLogger(statementLoggerName);\n    private Logger resultSetLogger = LoggerFactory.getLogger(resultSetLoggerName);\n\n    public Slf4jLogFilter(final Properties properties) {\n        super(properties);\n    }\n\n    public Slf4jLogFilter() {\n    }\n\n    @Override\n    public String getDataSourceLoggerName() {\n        return dataSourceLoggerName;\n    }\n\n    @Override\n    public void setDataSourceLoggerName(String dataSourceLoggerName) {\n        this.dataSourceLoggerName = dataSourceLoggerName;\n        dataSourceLogger = LoggerFactory.getLogger(dataSourceLoggerName);\n    }\n\n    public void setDataSourceLogger(Logger dataSourceLogger) {\n        this.dataSourceLogger = dataSourceLogger;\n        this.dataSourceLoggerName = dataSourceLogger.getName();\n    }\n\n    @Override\n    public String getConnectionLoggerName() {\n        return connectionLoggerName;\n    }\n\n    @Override\n    public void setConnectionLoggerName(String connectionLoggerName) {\n        this.connectionLoggerName = connectionLoggerName;\n        connectionLogger = LoggerFactory.getLogger(connectionLoggerName);\n    }\n\n    public void setConnectionLogger(Logger connectionLogger) {\n        this.connectionLogger = connectionLogger;\n        this.connectionLoggerName = connectionLogger.getName();\n    }\n\n    @Override\n    public String getStatementLoggerName() {\n        return statementLoggerName;\n    }\n\n    @Override\n    public void setStatementLoggerName(String statementLoggerName) {\n        this.statementLoggerName = statementLoggerName;\n        statementLogger = LoggerFactory.getLogger(statementLoggerName);\n    }\n\n    public void setStatementLogger(Logger statementLogger) {\n        this.statementLogger = statementLogger;\n        this.statementLoggerName = statementLogger.getName();\n    }\n\n    @Override\n    public String getResultSetLoggerName() {\n        return resultSetLoggerName;\n    }\n\n    @Override\n    public void setResultSetLoggerName(String resultSetLoggerName) {\n        this.resultSetLoggerName = resultSetLoggerName;\n        resultSetLogger = LoggerFactory.getLogger(resultSetLoggerName);\n    }\n\n    public void setResultSetLogger(Logger resultSetLogger) {\n        this.resultSetLogger = resultSetLogger;\n        this.resultSetLoggerName = resultSetLogger.getName();\n    }\n\n    @Override\n    public boolean isConnectionLogErrorEnabled() {\n        return connectionLogger.isErrorEnabled() && super.isConnectionLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isDataSourceLogEnabled() {\n        return dataSourceLogger.isDebugEnabled() && super.isDataSourceLogEnabled();\n    }\n\n    @Override\n    public boolean isConnectionLogEnabled() {\n        return connectionLogger.isDebugEnabled() && super.isConnectionLogEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogEnabled() {\n        return statementLogger.isDebugEnabled() && super.isStatementLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogEnabled() {\n        return resultSetLogger.isDebugEnabled() && super.isResultSetLogEnabled();\n    }\n\n    @Override\n    public boolean isResultSetLogErrorEnabled() {\n        return resultSetLogger.isErrorEnabled() && super.isResultSetLogErrorEnabled();\n    }\n\n    @Override\n    public boolean isStatementLogErrorEnabled() {\n        return statementLogger.isErrorEnabled() && super.isStatementLogErrorEnabled();\n    }\n\n    @Override\n    protected void connectionLog(String message) {\n        connectionLogger.debug(message);\n    }\n\n    @Override\n    protected void statementLog(String message) {\n        statementLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLog(String message) {\n        resultSetLogger.debug(message);\n    }\n\n    @Override\n    protected void resultSetLogError(String message, Throwable error) {\n        resultSetLogger.error(message, error);\n    }\n\n    @Override\n    protected void statementLogError(String message, Throwable error) {\n        statementLogger.error(message, error);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/mysql8datetime/MySQL8DateTimeResultSetMetaData.java",
    "content": "package com.alibaba.druid.filter.mysql8datetime;\n\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.time.LocalDateTime;\n\n/**\n * 针对mysql jdbc 8.0.23及以上版本，通过该方法控制将对象类型转换成原来的类型\n * @author lizongbo\n * @see <a href=\"https://dev.mysql.com/doc/relnotes/connector-j/8.0/en/news-8-0-24.html\">...</a>\n */\npublic class MySQL8DateTimeResultSetMetaData implements ResultSetMetaData {\n    private ResultSetMetaData resultSetMetaData;\n\n    public MySQL8DateTimeResultSetMetaData(ResultSetMetaData resultSetMetaData) {\n        super();\n        this.resultSetMetaData = resultSetMetaData;\n    }\n\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        return resultSetMetaData.unwrap(iface);\n    }\n\n    @Override\n    public int getColumnCount() throws SQLException {\n        return resultSetMetaData.getColumnCount();\n    }\n\n    @Override\n    public boolean isAutoIncrement(int column) throws SQLException {\n        return resultSetMetaData.isAutoIncrement(column);\n    }\n\n    @Override\n    public boolean isCaseSensitive(int column) throws SQLException {\n        return resultSetMetaData.isCaseSensitive(column);\n    }\n\n    @Override\n    public boolean isSearchable(int column) throws SQLException {\n        return resultSetMetaData.isSearchable(column);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return resultSetMetaData.isWrapperFor(iface);\n    }\n\n    @Override\n    public boolean isCurrency(int column) throws SQLException {\n        return resultSetMetaData.isCurrency(column);\n    }\n\n    @Override\n    public int isNullable(int column) throws SQLException {\n        return resultSetMetaData.isNullable(column);\n    }\n\n    @Override\n    public boolean isSigned(int column) throws SQLException {\n        return resultSetMetaData.isSigned(column);\n    }\n\n    @Override\n    public int getColumnDisplaySize(int column) throws SQLException {\n        return resultSetMetaData.getColumnDisplaySize(column);\n    }\n\n    @Override\n    public String getColumnLabel(int column) throws SQLException {\n        return resultSetMetaData.getColumnLabel(column);\n    }\n\n    @Override\n    public String getColumnName(int column) throws SQLException {\n        return resultSetMetaData.getColumnName(column);\n    }\n\n    @Override\n    public String getSchemaName(int column) throws SQLException {\n        return resultSetMetaData.getSchemaName(column);\n    }\n\n    @Override\n    public int getPrecision(int column) throws SQLException {\n        return resultSetMetaData.getPrecision(column);\n    }\n\n    @Override\n    public int getScale(int column) throws SQLException {\n        return resultSetMetaData.getScale(column);\n    }\n\n    @Override\n    public String getTableName(int column) throws SQLException {\n        return resultSetMetaData.getTableName(column);\n    }\n\n    @Override\n    public String getCatalogName(int column) throws SQLException {\n        return resultSetMetaData.getCatalogName(column);\n    }\n\n    @Override\n    public int getColumnType(int column) throws SQLException {\n        return resultSetMetaData.getColumnType(column);\n    }\n\n    @Override\n    public String getColumnTypeName(int column) throws SQLException {\n        return resultSetMetaData.getColumnTypeName(column);\n    }\n\n    @Override\n    public boolean isReadOnly(int column) throws SQLException {\n        return resultSetMetaData.isReadOnly(column);\n    }\n\n    @Override\n    public boolean isWritable(int column) throws SQLException {\n        return resultSetMetaData.isWritable(column);\n    }\n\n    @Override\n    public boolean isDefinitelyWritable(int column) throws SQLException {\n        return resultSetMetaData.isDefinitelyWritable(column);\n    }\n\n    /**\n     * 针对8.0.24版本开始，如果把mysql DATETIME映射回Timestamp，就需要把javaClass的类型也改回去\n     * 相关类在com.mysql.cj.MysqlType 中\n     * 旧版本jdbc为\n     *  DATETIME(\"DATETIME\", Types.TIMESTAMP, Timestamp.class, 0, MysqlType.IS_NOT_DECIMAL, 26L, \"[(fsp)]\"),\n     *  8.0.24及以上版本jdbc实现改为\n     * DATETIME(\"DATETIME\", Types.TIMESTAMP, LocalDateTime.class, 0, MysqlType.IS_NOT_DECIMAL, 26L, \"[(fsp)]\"),\n     * @param column 列的索引位\n     * @return 列名称\n     * @see java.sql.ResultSetMetaData#getColumnClassName(int)\n     * @throws SQLException 如果发生数据库访问错误\n     */\n    @Override\n    public String getColumnClassName(int column) throws SQLException {\n        String className = resultSetMetaData.getColumnClassName(column);\n        if (LocalDateTime.class.getName().equals(className)) {\n            return Timestamp.class.getName();\n        }\n        return className;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/mysql8datetime/MySQL8DateTimeSqlTypeFilter.java",
    "content": "package com.alibaba.druid.filter.mysql8datetime;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\n\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.time.LocalDateTime;\n\n/**\n * 针对mysql jdbc 8.0.23及以上版本，如果调用方没有使用orm框架，而是直接调用ResultSet的getObject方法，则针对DATETIME类型的字段，得到的对象从TimeStamp类型变成了LocalDateTime类型，导致调用方出现类型转换异常\n * 通过Filter控制将对象类型转换成原来的类型\n *\n * @author lizongbo\n * @see <a href=\"https://dev.mysql.com/doc/relnotes/connector-j/8.0/en/news-8-0-23.html\">MySQL 8.0.23 更新说明</a>\n */\npublic class MySQL8DateTimeSqlTypeFilter extends FilterAdapter {\n    /**\n     * 针对mysql jdbc 8.0.23及以上版本，通过该方法控制将对象类型转换成原来的类型\n     *\n     * @param chain  chain the FilterChain object that represents the filter chain\n     * @param result the ResultSetProxy object that represents the result set\n     * @param columnIndex the index of the column to retrieve\n     * @return an Object holding the column value, or {@code null} if the value is SQL NULL\n     * @throws SQLException if a database access error occurs or the columnIndex is invalid\n     * @see java.sql.ResultSet#getObject(int)\n     */\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        return getObjectReplaceLocalDateTime(super.resultSet_getObject(chain, result, columnIndex));\n    }\n\n    /**\n     * 针对mysql jdbc 8.0.23及以上版本，通过该方法控制将对象类型转换成原来的类型\n     *\n     * @param chain   chain the FilterChain object that represents the filter chain\n     * @param result  the ResultSetProxy object that represents the result set\n     * @param columnLabel the label of the column to retrieve\n     * @return an Object holding the column value, or {@code null} if the value is SQL NULL\n     * @throws SQLException if a database access error occurs or the columnLabel is invalid\n     * @see java.sql.ResultSet#getObject(String)\n     */\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        return getObjectReplaceLocalDateTime(super.resultSet_getObject(chain, result, columnLabel));\n    }\n\n    /**\n     * Replaces a LocalDateTime object with its equivalent Timestamp object.\n     * If the input object is not an instance of LocalDateTime, it is returned as is.\n     * This method is specifically designed to handle cases where upgrading to MySQL JDBC 8.0.23 or above\n     * requires converting LocalDateTime objects back to the older compatible type.\n     *\n     * @param obj the object to be checked and possibly replaced\n     * @return the replaced object if it is a LocalDateTime, or the original object otherwise\n     */\n    public static Object getObjectReplaceLocalDateTime(Object obj) {\n        if (!(obj instanceof LocalDateTime)) {\n            return obj;\n        }\n        // 针对升级到了mysql jdbc 8.0.23以上的情况，转换回老的兼容类型\n        return Timestamp.valueOf((LocalDateTime) obj);\n    }\n\n    /**\n     * Retrieves the metadata for the result set, including information about the columns and their properties.\n     * This method wraps the original result set metadata with a custom implementation that handles MySQL 8.0.23 or above\n     * compatibility for LocalDateTime objects.\n     *\n     * @param chain the FilterChain object that represents the filter chain\n     * @param resultSet the ResultSetProxy object that represents the result set\n     * @return a ResultSetMetaData object containing the metadata for the result set\n     * @throws SQLException if a database access error occurs\n     */\n    @Override\n    public ResultSetMetaData resultSet_getMetaData(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        return new MySQL8DateTimeResultSetMetaData(chain.resultSet_getMetaData(resultSet));\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/stat/MergeStatFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.stat;\n\npublic class MergeStatFilter extends StatFilter {\n    public MergeStatFilter() {\n        super.setMergeSql(true);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) {\n        return iface == MergeStatFilter.class || iface == StatFilter.class;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) {\n        if (iface == MergeStatFilter.class || iface == StatFilter.class) {\n            return (T) this;\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.stat;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.VERSION;\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.filter.FilterEventAdapter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.*;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.alibaba.druid.stat.*;\nimport com.alibaba.druid.support.json.JSONWriter;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.support.profile.Profiler;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.sql.*;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.LocalTime;\nimport java.util.Date;\nimport java.util.Properties;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class StatFilter extends FilterEventAdapter implements StatFilterMBean {\n    private static final Log LOG = LogFactory.getLog(StatFilter.class);\n\n    private static final String SYS_PROP_LOG_SLOW_SQL = \"druid.stat.logSlowSql\";\n    private static final String SYS_PROP_SLOW_SQL_MILLIS = \"druid.stat.slowSqlMillis\";\n    private static final String SYS_PROP_SLOW_SQL_LOG_LEVEL = \"druid.stat.slowSqlLogLevel\";\n    private static final String SYS_PROP_MERGE_SQL = \"druid.stat.mergeSql\";\n\n    public static final String ATTR_NAME_CONNECTION_STAT = \"stat.conn\";\n    public static final String ATTR_TRANSACTION = \"stat.tx\";\n\n    private final Lock lock = new ReentrantLock();\n\n    // protected JdbcDataSourceStat dataSourceStat;\n\n    @Deprecated\n    protected final JdbcStatementStat statementStat = JdbcStatManager.getInstance().getStatementStat();\n\n    @Deprecated\n    protected final JdbcResultSetStat resultSetStat = JdbcStatManager.getInstance().getResultSetStat();\n\n    private boolean connectionStackTraceEnable;\n\n    // 3 seconds is slow sql\n    protected long slowSqlMillis = 3 * 1000;\n\n    protected boolean logSlowSql;\n\n    protected String slowSqlLogLevel = \"ERROR\";\n\n    private DbType dbType;\n\n    private boolean mergeSql;\n\n    public StatFilter() {\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public void setDbType(String dbType) {\n        this.dbType = DbType.of(dbType);\n    }\n\n    @Override\n    public long getSlowSqlMillis() {\n        return slowSqlMillis;\n    }\n\n    @Override\n    public void setSlowSqlMillis(long slowSqlMillis) {\n        this.slowSqlMillis = slowSqlMillis;\n    }\n\n    @Override\n    public boolean isLogSlowSql() {\n        return logSlowSql;\n    }\n\n    @Override\n    public void setLogSlowSql(boolean logSlowSql) {\n        this.logSlowSql = logSlowSql;\n    }\n\n    public boolean isConnectionStackTraceEnable() {\n        return connectionStackTraceEnable;\n    }\n\n    public void setConnectionStackTraceEnable(boolean connectionStackTraceEnable) {\n        this.connectionStackTraceEnable = connectionStackTraceEnable;\n    }\n\n    @Override\n    public boolean isMergeSql() {\n        return mergeSql;\n    }\n\n    @Override\n    public void setMergeSql(boolean mergeSql) {\n        this.mergeSql = mergeSql;\n    }\n\n    public String getSlowSqlLogLevel() {\n        return slowSqlLogLevel;\n    }\n\n    public void setSlowSqlLogLevel(String slowSqlLogLevel) {\n        this.slowSqlLogLevel = slowSqlLogLevel;\n    }\n\n    @Deprecated\n    public String mergeSql(String sql) {\n        return this.mergeSql(sql, dbType);\n    }\n\n    @Override\n    public String mergeSql(String sql, String dbType) {\n        return mergeSql(sql, DbType.of(dbType));\n    }\n\n    public String mergeSql(String sql, DbType dbType) {\n        if (!mergeSql) {\n            return sql;\n        }\n\n        try {\n            sql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType, null, null, null);\n        } catch (Exception e) {\n            LOG.error(\"merge sql error, dbType \" + dbType + \", druid-\" + VERSION.getVersionNumber() + \", sql : \" + sql, e);\n        }\n\n        return sql;\n    }\n\n    @Override\n    public void init(DataSourceProxy dataSource) {\n        lock.lock();\n        try {\n            if (this.dbType == null) {\n                this.dbType = DbType.of(dataSource.getDbType());\n            }\n\n            configFromProperties(dataSource.getConnectProperties());\n            configFromProperties(System.getProperties());\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n        if (properties == null) {\n            return;\n        }\n\n        {\n            String property = properties.getProperty(SYS_PROP_MERGE_SQL);\n            if (\"true\".equals(property)) {\n                this.mergeSql = true;\n            } else if (\"false\".equals(property)) {\n                this.mergeSql = false;\n            }\n        }\n\n        {\n            String property = properties.getProperty(SYS_PROP_SLOW_SQL_MILLIS);\n            if (property != null && property.trim().length() > 0) {\n                property = property.trim();\n                try {\n                    this.slowSqlMillis = Long.parseLong(property);\n                } catch (Exception e) {\n                    LOG.error(\"property 'druid.stat.slowSqlMillis' format error\");\n                }\n            }\n        }\n\n        {\n            String property = properties.getProperty(SYS_PROP_LOG_SLOW_SQL);\n            if (\"true\".equals(property)) {\n                this.logSlowSql = true;\n            } else if (\"false\".equals(property)) {\n                this.logSlowSql = false;\n            }\n        }\n\n        {\n            String property = properties.getProperty(SYS_PROP_SLOW_SQL_LOG_LEVEL);\n            if (\"error\".equalsIgnoreCase(property)) {\n                this.slowSqlLogLevel = \"ERROR\";\n            } else if (\"warn\".equalsIgnoreCase(property)) {\n                this.slowSqlLogLevel = \"WARN\";\n            } else if (\"info\".equalsIgnoreCase(property)) {\n                this.slowSqlLogLevel = \"INFO\";\n            } else if (\"debug\".equalsIgnoreCase(property)) {\n                this.slowSqlLogLevel = \"DEBUG\";\n            }\n        }\n    }\n\n    @Override\n    public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n        ConnectionProxy connection = null;\n\n        long startNano = System.nanoTime();\n        long startTime = System.currentTimeMillis();\n\n        long nanoSpan;\n\n        JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();\n        dataSourceStat.getConnectionStat().beforeConnect();\n        try {\n            connection = chain.connection_connect(info);\n            nanoSpan = System.nanoTime() - startNano;\n        } catch (SQLException ex) {\n            dataSourceStat.getConnectionStat().connectError(ex);\n            throw ex;\n        }\n        dataSourceStat.getConnectionStat().afterConnected(nanoSpan);\n\n        if (connection != null) {\n            JdbcConnectionStat.Entry statEntry = getConnectionInfo(connection);\n\n            dataSourceStat.getConnections().put(connection.getId(), statEntry);\n\n            long nowNano = System.nanoTime();\n            long nowTime = System.currentTimeMillis();\n\n            statEntry.setConnectTime(new Date(startTime));\n            statEntry.setConnectTimespanNano(nanoSpan);\n            statEntry.setEstablishNano(nowNano);\n            statEntry.setEstablishTime(nowTime);\n            statEntry.setConnectStackTrace(new Exception());\n\n            dataSourceStat.getConnectionStat().setActiveCount(dataSourceStat.getConnections().size());\n        }\n\n        return connection;\n    }\n\n    @Override\n    public void connection_close(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        if (connection.getCloseCount() == 0) {\n            long nowNano = System.nanoTime();\n\n            JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();\n            dataSourceStat.getConnectionStat().incrementConnectionCloseCount();\n\n            JdbcConnectionStat.Entry connectionInfo = getConnectionInfo(connection);\n\n            long aliveNanoSpan = nowNano - connectionInfo.getEstablishNano();\n\n            JdbcConnectionStat.Entry existsConnection = dataSourceStat.getConnections().remove(connection.getId());\n            if (existsConnection != null) {\n                dataSourceStat.getConnectionStat().afterClose(aliveNanoSpan);\n            }\n        }\n\n        chain.connection_close(connection);\n        // duplicate close, C3P0等连接池，在某些情况下会关闭连接多次。\n    }\n\n    @Override\n    public void connection_commit(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        chain.connection_commit(connection);\n\n        JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();\n        dataSourceStat.getConnectionStat().incrementConnectionCommitCount();\n        StatFilterContext.getInstance().commit();\n    }\n\n    @Override\n    public void connection_rollback(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        chain.connection_rollback(connection);\n\n        JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();\n        dataSourceStat.getConnectionStat().incrementConnectionRollbackCount();\n        StatFilterContext.getInstance().rollback();\n    }\n\n    @Override\n    public void connection_rollback(FilterChain chain, ConnectionProxy connection, Savepoint savepoint)\n            throws SQLException {\n        chain.connection_rollback(connection, savepoint);\n\n        JdbcDataSourceStat dataSourceStat = connection.getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getConnectionStat().incrementConnectionRollbackCount();\n    }\n\n    @Override\n    public void statementCreateAfter(StatementProxy statement) {\n        JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getStatementStat().incrementCreateCounter();\n\n        super.statementCreateAfter(statement);\n    }\n\n    @Override\n    public void statementPrepareCallAfter(CallableStatementProxy statement) {\n        JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getStatementStat().incrementPrepareCallCount();\n\n        JdbcSqlStat sqlStat = createSqlStat(statement, statement.getSql());\n        statement.setSqlStat(sqlStat);\n    }\n\n    @Override\n    public void statementPrepareAfter(PreparedStatementProxy statement) {\n        JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getStatementStat().incrementPrepareCounter();\n        JdbcSqlStat sqlStat = createSqlStat(statement, statement.getSql());\n        statement.setSqlStat(sqlStat);\n    }\n\n    @Override\n    public void statement_close(FilterChain chain, StatementProxy statement) throws SQLException {\n        chain.statement_close(statement);\n\n        JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();\n        dataSourceStat.getStatementStat().incrementStatementCloseCounter();\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        if (context != null) {\n            context.setName(null);\n            context.setFile(null);\n            context.setSql(null);\n        }\n    }\n\n    @Override\n    protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) {\n        internalBeforeStatementExecute(statement, sql);\n    }\n\n    @Override\n    protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) {\n        internalAfterStatementExecute(statement, false, updateCount);\n    }\n\n    @Override\n    protected void statementExecuteQueryBefore(StatementProxy statement, String sql) {\n        internalBeforeStatementExecute(statement, sql);\n    }\n\n    @Override\n    protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {\n        internalAfterStatementExecute(statement, true);\n    }\n\n    @Override\n    protected void statementExecuteBefore(StatementProxy statement, String sql) {\n        internalBeforeStatementExecute(statement, sql);\n    }\n\n    @Override\n    protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) {\n        internalAfterStatementExecute(statement, firstResult);\n    }\n\n    @Override\n    protected void statementExecuteBatchBefore(StatementProxy statement) {\n        final String sql = statement.getBatchSql();\n\n        final int batchSize = statement.getBatchSqlList().size();\n        JdbcSqlStat sqlStat = statement.getSqlStat();\n        if (sqlStat == null || sqlStat.isRemoved()) {\n            sqlStat = createSqlStat(statement, sql);\n            statement.setSqlStat(sqlStat);\n        }\n\n        if (sqlStat != null) {\n            sqlStat.addExecuteBatchCount(batchSize);\n        }\n\n        internalBeforeStatementExecute(statement, sql);\n\n    }\n\n    @Override\n    protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) {\n        internalAfterStatementExecute(statement, false, result);\n\n    }\n\n    private final void internalBeforeStatementExecute(StatementProxy statement, String sql) {\n        JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getStatementStat().beforeExecute();\n\n        final ConnectionProxy connection = statement.getConnectionProxy();\n        final JdbcConnectionStat.Entry connectionCounter = getConnectionInfo(connection);\n\n        statement.setLastExecuteStartNano();\n\n        connectionCounter.setLastSql(sql);\n\n        if (connectionStackTraceEnable) {\n            connectionCounter.setLastStatementStatckTrace(new Exception());\n        }\n\n        // //////////SQL\n\n        JdbcSqlStat sqlStat = statement.getSqlStat();\n        if (sqlStat == null || sqlStat.isRemoved() || !sqlStat.getSql().equals(sql)) {\n            sqlStat = createSqlStat(statement, sql);\n            statement.setSqlStat(sqlStat);\n        }\n\n        JdbcStatContext statContext = JdbcStatManager.getInstance().getStatContext();\n        if (statContext != null) {\n            sqlStat.setName(statContext.getName());\n            sqlStat.setFile(statContext.getFile());\n        }\n\n        boolean inTransaction = false;\n        try {\n            inTransaction = !statement.getConnectionProxy().getAutoCommit();\n        } catch (SQLException e) {\n            LOG.error(\"getAutoCommit error\", e);\n        }\n\n        if (sqlStat != null) {\n            sqlStat.setExecuteLastStartTime(System.currentTimeMillis());\n            sqlStat.incrementRunningCount();\n\n            if (inTransaction) {\n                sqlStat.incrementInTransactionCount();\n            }\n        }\n\n        StatFilterContext.getInstance().executeBefore(sql, inTransaction);\n\n        String mergedSql;\n        if (sqlStat != null) {\n            mergedSql = sqlStat.getSql();\n        } else {\n            mergedSql = sql;\n        }\n        Profiler.enter(mergedSql, Profiler.PROFILE_TYPE_SQL);\n    }\n\n    private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult,\n                                                     int... updateCountArray) {\n        final long nowNano = System.nanoTime();\n        final long nanos = nowNano - statement.getLastExecuteStartNano();\n\n        JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getStatementStat().afterExecute(nanos);\n\n        final JdbcSqlStat sqlStat = statement.getSqlStat();\n\n        if (sqlStat != null) {\n            sqlStat.incrementExecuteSuccessCount();\n\n            sqlStat.decrementRunningCount();\n            sqlStat.addExecuteTime(statement.getLastExecuteType(), firstResult, nanos);\n            statement.setLastExecuteTimeNano(nanos);\n            if ((!firstResult) && statement.getLastExecuteType() == StatementExecuteType.Execute) {\n                try {\n                    int updateCount = statement.getUpdateCount();\n                    sqlStat.addUpdateCount(updateCount);\n                } catch (SQLException e) {\n                    LOG.error(\"getUpdateCount error\", e);\n                }\n            } else {\n                for (int updateCount : updateCountArray) {\n                    sqlStat.addUpdateCount(updateCount);\n                    sqlStat.addFetchRowCount(0);\n                    StatFilterContext.getInstance().addUpdateCount(updateCount);\n                }\n            }\n\n            long millis = nanos / (1000 * 1000);\n            if (millis >= slowSqlMillis) {\n                String slowParameters = buildSlowParameters(statement);\n                sqlStat.setLastSlowParameters(slowParameters);\n\n                String lastExecSql = statement.getLastExecuteSql();\n                if (logSlowSql) {\n                    String msg = \"slow sql \" + millis + \" millis. \" + lastExecSql + \" \" + slowParameters;\n                    switch (slowSqlLogLevel) {\n                        case \"WARN\":\n                            LOG.warn(msg);\n                            break;\n                        case \"INFO\":\n                            LOG.info(msg);\n                            break;\n                        case \"DEBUG\":\n                            LOG.debug(msg);\n                            break;\n                        default:\n                            LOG.error(msg);\n                    }\n                }\n\n                handleSlowSql(statement);\n            }\n        }\n\n        String sql = statement.getLastExecuteSql();\n        StatFilterContext.getInstance().executeAfter(sql, nanos, null);\n\n        Profiler.release(nanos);\n    }\n\n    protected void handleSlowSql(StatementProxy statementProxy) {\n    }\n\n    @Override\n    protected void statement_executeErrorAfter(StatementProxy statement, String sql, Throwable error) {\n        ConnectionProxy connection = statement.getConnectionProxy();\n        JdbcConnectionStat.Entry connectionCounter = getConnectionInfo(connection);\n\n        long nanos = System.nanoTime() - statement.getLastExecuteStartNano();\n\n        JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getStatementStat().error(error);\n        dataSourceStat.getStatementStat().afterExecute(nanos);\n\n        connectionCounter.error(error);\n\n        // SQL\n        JdbcSqlStat sqlStat = statement.getSqlStat();\n\n        if (sqlStat != null) {\n            sqlStat.decrementRunningCount();\n            sqlStat.error(error);\n            sqlStat.addExecuteTime(statement.getLastExecuteType(), statement.isFirstResultSet(), nanos);\n            statement.setLastExecuteTimeNano(nanos);\n        }\n\n        StatFilterContext.getInstance().executeAfter(sql, nanos, error);\n        Profiler.release(nanos);\n    }\n\n    protected String buildSlowParameters(StatementProxy statement) {\n        JSONWriter out = new JSONWriter();\n\n        out.writeArrayStart();\n        for (int i = 0, parametersSize = statement.getParametersSize(); i < parametersSize; ++i) {\n            JdbcParameter parameter = statement.getParameter(i);\n            if (i != 0) {\n                out.writeComma();\n            }\n            if (parameter == null) {\n                continue;\n            }\n\n            Object value = parameter.getValue();\n            if (value == null) {\n                out.writeNull();\n            } else if (value instanceof String) {\n                String text = (String) value;\n                if (text.length() > 100) {\n                    out.writeString(text.substring(0, 97) + \"...\");\n                } else {\n                    out.writeString(text);\n                }\n            } else if (value instanceof Number) {\n                out.writeObject(value);\n            } else if (value instanceof java.util.Date) {\n                out.writeObject(value);\n            } else if (value instanceof Boolean) {\n                out.writeObject(value);\n            } else if (value instanceof LocalDate) {\n                out.writeObject(value);\n            } else if (value instanceof LocalTime) {\n                out.writeObject(value);\n            } else if (value instanceof LocalDateTime) {\n                out.writeObject(value);\n            } else if (value instanceof InputStream) {\n                out.writeString(\"<InputStream>\");\n            } else if (value instanceof NClob) {\n                out.writeString(\"<NClob>\");\n            } else if (value instanceof Clob) {\n                out.writeString(\"<Clob>\");\n            } else if (value instanceof Blob) {\n                out.writeString(\"<Blob>\");\n            } else {\n                out.writeString('<' + value.getClass().getName() + '>');\n            }\n        }\n        out.writeArrayEnd();\n\n        return out.toString();\n    }\n\n    @Override\n    protected void resultSetOpenAfter(ResultSetProxy resultSet) {\n        JdbcDataSourceStat dataSourceStat = resultSet.getStatementProxy().getConnectionProxy().getDirectDataSource().getDataSourceStat();\n        dataSourceStat.getResultSetStat().beforeOpen();\n\n        resultSet.setConstructNano();\n\n        StatFilterContext.getInstance().resultSet_open();\n    }\n\n    @Override\n    public void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        long nanos = System.nanoTime() - resultSet.getConstructNano();\n\n        int fetchRowCount = resultSet.getFetchRowCount();\n\n        JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();\n        dataSourceStat.getResultSetStat().afterClose(nanos);\n        dataSourceStat.getResultSetStat().addFetchRowCount(fetchRowCount);\n        dataSourceStat.getResultSetStat().incrementCloseCounter();\n\n        StatFilterContext.getInstance().addFetchRowCount(fetchRowCount);\n\n        String sql = resultSet.getSql();\n        if (sql != null) {\n            JdbcSqlStat sqlStat = resultSet.getSqlStat();\n            if (sqlStat != null && resultSet.getCloseCount() == 0) {\n                sqlStat.addFetchRowCount(fetchRowCount);\n                long stmtExecuteNano = resultSet.getStatementProxy().getLastExecuteTimeNano();\n                sqlStat.addResultSetHoldTimeNano(stmtExecuteNano, nanos);\n                if (resultSet.getReadStringLength() > 0) {\n                    sqlStat.addStringReadLength(resultSet.getReadStringLength());\n                }\n                if (resultSet.getReadBytesLength() > 0) {\n                    sqlStat.addReadBytesLength(resultSet.getReadBytesLength());\n                }\n                if (resultSet.getOpenInputStreamCount() > 0) {\n                    sqlStat.addInputStreamOpenCount(resultSet.getOpenInputStreamCount());\n                }\n                if (resultSet.getOpenReaderCount() > 0) {\n                    sqlStat.addReaderOpenCount(resultSet.getOpenReaderCount());\n                }\n            }\n        }\n\n        chain.resultSet_close(resultSet);\n\n        StatFilterContext.getInstance().resultSet_close(nanos);\n    }\n\n    public JdbcConnectionStat.Entry getConnectionInfo(ConnectionProxy connection) {\n        JdbcConnectionStat.Entry counter = (JdbcConnectionStat.Entry) connection.getAttribute(ATTR_NAME_CONNECTION_STAT);\n\n        if (counter == null) {\n            String dataSourceName = connection.getDirectDataSource().getName();\n            counter = new JdbcConnectionStat.Entry(dataSourceName, connection.getId());\n            connection.putAttribute(ATTR_NAME_CONNECTION_STAT, counter);\n        }\n\n        return counter;\n    }\n\n    public JdbcSqlStat createSqlStat(StatementProxy statement, String sql) {\n        DataSourceProxy dataSource = statement.getConnectionProxy().getDirectDataSource();\n        JdbcDataSourceStat dataSourceStat = dataSource.getDataSourceStat();\n\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        String contextSql = context != null ? context.getSql() : null;\n        if (contextSql != null && contextSql.length() > 0) {\n            return dataSourceStat.createSqlStat(contextSql);\n        } else {\n            DbType dbType = this.dbType;\n\n            if (dbType == null) {\n                dbType = DbType.of(dataSource.getDbType());\n            }\n\n            sql = mergeSql(sql, dbType);\n            return dataSourceStat.createSqlStat(sql);\n        }\n    }\n\n    public static StatFilter getStatFilter(DataSourceProxy dataSource) {\n        for (Filter filter : dataSource.getProxyFilters()) {\n            if (filter instanceof StatFilter) {\n                return (StatFilter) filter;\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    public void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection conn) throws SQLException {\n        chain.dataSource_recycle(conn);\n\n        long nanos = System.nanoTime() - conn.getConnectedTimeNano();\n\n        long millis = nanos / (1000L * 1000L);\n\n        JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat();\n        dataSourceStat.getConnectionHoldHistogram().record(millis);\n\n        StatFilterContext.getInstance().pool_connection_close(nanos);\n    }\n\n    @Override\n    public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource,\n                                                          long maxWaitMillis) throws SQLException {\n        DruidPooledConnection conn = chain.dataSource_connect(dataSource, maxWaitMillis);\n\n        if (conn != null) {\n            conn.setConnectedTimeNano();\n\n            StatFilterContext.getInstance().pool_connection_open();\n        }\n\n        return conn;\n    }\n\n    @Override\n    public Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        Clob clob = chain.resultSet_getClob(resultSet, columnIndex);\n\n        if (clob != null) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), resultSet, (ClobProxy) clob);\n        }\n\n        return clob;\n    }\n\n    @Override\n    public Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException {\n        Clob clob = chain.resultSet_getClob(resultSet, columnLabel);\n\n        if (clob != null) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), resultSet, (ClobProxy) clob);\n        }\n\n        return clob;\n    }\n\n    @Override\n    public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        Blob blob = chain.callableStatement_getBlob(statement, parameterIndex);\n\n        if (blob != null) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, blob);\n        }\n\n        return blob;\n    }\n\n    @Override\n    public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        Blob blob = chain.callableStatement_getBlob(statement, parameterName);\n\n        if (blob != null) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, blob);\n        }\n\n        return blob;\n    }\n\n    @Override\n    public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        Blob blob = chain.resultSet_getBlob(result, columnIndex);\n\n        if (blob != null) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, blob);\n        }\n\n        return blob;\n    }\n\n    @Override\n    public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        Blob blob = chain.resultSet_getBlob(result, columnLabel);\n\n        if (blob != null) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, blob);\n        }\n\n        return blob;\n    }\n\n    @Override\n    public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        Clob clob = chain.callableStatement_getClob(statement, parameterIndex);\n\n        if (clob != null) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) clob);\n        }\n\n        return clob;\n    }\n\n    @Override\n    public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        Clob clob = chain.callableStatement_getClob(statement, parameterName);\n\n        if (clob != null) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) clob);\n        }\n\n        return clob;\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        Object obj = chain.resultSet_getObject(result, columnIndex);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj);\n        } else if (obj instanceof String) {\n            result.addReadStringLength(((String) obj).length());\n        }\n\n        return obj;\n    }\n\n    @Override\n    public <T> T resultSet_getObject(FilterChain chain,\n                                     ResultSetProxy result,\n                                     int columnIndex,\n                                     Class<T> type) throws SQLException {\n        T obj = chain.resultSet_getObject(result, columnIndex, type);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj);\n        } else if (obj instanceof String) {\n            result.addReadStringLength(((String) obj).length());\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                      java.util.Map<String, Class<?>> map) throws SQLException {\n        Object obj = chain.resultSet_getObject(result, columnIndex, map);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj);\n        } else if (obj instanceof String) {\n            result.addReadStringLength(((String) obj).length());\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        Object obj = chain.resultSet_getObject(result, columnLabel);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj);\n        } else if (obj instanceof String) {\n            result.addReadStringLength(((String) obj).length());\n        }\n\n        return obj;\n    }\n\n    @Override\n    public <T> T resultSet_getObject(FilterChain chain,\n                                     ResultSetProxy result,\n                                     String columnLabel,\n                                     Class<T> type) throws SQLException {\n        T obj = chain.resultSet_getObject(result, columnLabel, type);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj);\n        } else if (obj instanceof String) {\n            result.addReadStringLength(((String) obj).length());\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel,\n                                      java.util.Map<String, Class<?>> map) throws SQLException {\n        Object obj = chain.resultSet_getObject(result, columnLabel, map);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj);\n        } else if (obj instanceof String) {\n            result.addReadStringLength(((String) obj).length());\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex)\n            throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterIndex);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterIndex, map);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName)\n            throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterName);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj);\n        }\n\n        return obj;\n    }\n\n    @Override\n    public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement,\n                                              String parameterName, java.util.Map<String, Class<?>> map)\n            throws SQLException {\n        Object obj = chain.callableStatement_getObject(statement, parameterName, map);\n\n        if (obj instanceof Clob) {\n            clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj);\n        } else if (obj instanceof Blob) {\n            blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj);\n        }\n\n        return obj;\n    }\n\n    private void blobOpenAfter(JdbcDataSourceStat dataSourceStat, ResultSetProxy rs, Blob blob) {\n        blobOpenAfter(dataSourceStat, rs.getStatementProxy(), blob);\n    }\n\n    private void clobOpenAfter(JdbcDataSourceStat dataSourceStat, ResultSetProxy rs, ClobProxy clob) {\n        clobOpenAfter(dataSourceStat, rs.getStatementProxy(), clob);\n    }\n\n    private void blobOpenAfter(JdbcDataSourceStat dataSourceStat, StatementProxy stmt, Blob blob) {\n        dataSourceStat.incrementBlobOpenCount();\n\n        if (stmt != null) {\n            JdbcSqlStat sqlStat = stmt.getSqlStat();\n            if (sqlStat != null) {\n                sqlStat.incrementBlobOpenCount();\n            }\n        }\n\n        StatFilterContext.getInstance().blob_open();\n    }\n\n    private void clobOpenAfter(JdbcDataSourceStat dataSourceStat, StatementProxy stmt, ClobProxy clob) {\n        dataSourceStat.incrementClobOpenCount();\n\n        if (stmt != null) {\n            JdbcSqlStat sqlStat = stmt.getSqlStat();\n            if (sqlStat != null) {\n                sqlStat.incrementClobOpenCount();\n            }\n        }\n\n        StatFilterContext.getInstance().clob_open();\n    }\n\n    @Override\n    public String resultSet_getString(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        String value = chain.resultSet_getString(result, columnIndex);\n\n        if (value != null) {\n            result.addReadStringLength(value.length());\n        }\n\n        return value;\n    }\n\n    @Override\n    public String resultSet_getString(FilterChain chain,\n                                      ResultSetProxy result,\n                                      String columnLabel) throws SQLException {\n        String value = chain.resultSet_getString(result, columnLabel);\n\n        if (value != null) {\n            result.addReadStringLength(value.length());\n        }\n\n        return value;\n    }\n\n    @Override\n    public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException {\n        byte[] value = chain.resultSet_getBytes(result, columnIndex);\n\n        if (value != null) {\n            result.addReadBytesLength(value.length);\n        }\n\n        return value;\n    }\n\n    @Override\n    public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException {\n        byte[] value = chain.resultSet_getBytes(result, columnLabel);\n\n        if (value != null) {\n            result.addReadBytesLength(value.length);\n        }\n\n        return value;\n    }\n\n    @Override\n    public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        InputStream input = chain.resultSet_getBinaryStream(result, columnIndex);\n\n        if (input != null) {\n            result.incrementOpenInputStreamCount();\n        }\n\n        return input;\n    }\n\n    @Override\n    public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        InputStream input = chain.resultSet_getBinaryStream(result, columnLabel);\n\n        if (input != null) {\n            result.incrementOpenInputStreamCount();\n        }\n\n        return input;\n    }\n\n    @Override\n    public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        InputStream input = chain.resultSet_getAsciiStream(result, columnIndex);\n\n        if (input != null) {\n            result.incrementOpenInputStreamCount();\n        }\n\n        return input;\n    }\n\n    @Override\n    public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        InputStream input = chain.resultSet_getAsciiStream(result, columnLabel);\n\n        if (input != null) {\n            result.incrementOpenInputStreamCount();\n        }\n\n        return input;\n    }\n\n    @Override\n    public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n            throws SQLException {\n        Reader reader = chain.resultSet_getCharacterStream(result, columnIndex);\n\n        if (reader != null) {\n            result.incrementOpenReaderCount();\n        }\n\n        return reader;\n    }\n\n    @Override\n    public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n            throws SQLException {\n        Reader reader = chain.resultSet_getCharacterStream(result, columnLabel);\n\n        if (reader != null) {\n            result.incrementOpenReaderCount();\n        }\n\n        return reader;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/stat/StatFilterContext.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.stat;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\npublic class StatFilterContext {\n    private List<StatFilterContextListener> listeners = new CopyOnWriteArrayList<StatFilterContextListener>();\n\n    private static final StatFilterContext instance = new StatFilterContext();\n\n    public static final StatFilterContext getInstance() {\n        return instance;\n    }\n\n    public void addContextListener(StatFilterContextListener listener) {\n        this.listeners.add(listener);\n    }\n\n    public boolean removeContextListener(StatFilterContextListener listener) {\n        return listeners.remove(listener);\n    }\n\n    public List<StatFilterContextListener> getListeners() {\n        return listeners;\n    }\n\n    public void addUpdateCount(int updateCount) {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.addUpdateCount(updateCount);\n        }\n    }\n\n    public void addFetchRowCount(int fetchRowCount) {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.addFetchRowCount(fetchRowCount);\n        }\n    }\n\n    public void executeBefore(String sql, boolean inTransaction) {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.executeBefore(sql, inTransaction);\n        }\n    }\n\n    public void executeAfter(String sql, long nanoSpan, Throwable error) {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.executeAfter(sql, nanoSpan, error);\n        }\n    }\n\n    public void commit() {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.commit();\n        }\n    }\n\n    public void rollback() {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.rollback();\n        }\n    }\n\n    public void pool_connection_open() {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.pool_connect();\n        }\n    }\n\n    public void pool_connection_close(long nanos) {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.pool_close(nanos);\n        }\n    }\n\n    public void physical_connection_connect() {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.physical_connection_connect();\n        }\n    }\n\n    public void physical_connection_close(long nanos) {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.physical_connection_close(nanos);\n        }\n    }\n\n    public void resultSet_open() {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.resultSet_open();\n        }\n    }\n\n    public void resultSet_close(long nanos) {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.resultSet_close(nanos);\n        }\n    }\n\n    public void clob_open() {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.clob_open();\n        }\n    }\n\n    public void blob_open() {\n        for (int i = 0; i < listeners.size(); ++i) {\n            StatFilterContextListener listener = listeners.get(i);\n            listener.blob_open();\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/stat/StatFilterContextListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.stat;\n\npublic interface StatFilterContextListener {\n    void addUpdateCount(int updateCount);\n\n    void addFetchRowCount(int fetchRowCount);\n\n    void executeBefore(String sql, boolean inTransaction);\n\n    void executeAfter(String sql, long nanoSpan, Throwable error);\n\n    void commit();\n\n    void rollback();\n\n    void pool_connect();\n\n    void pool_close(long nanos);\n\n    void physical_connection_connect();\n\n    void physical_connection_close(long nanos);\n\n    void resultSet_open();\n\n    void resultSet_close(long nanos);\n\n    void clob_open();\n\n    void blob_open();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/stat/StatFilterContextListenerAdapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.stat;\n\npublic class StatFilterContextListenerAdapter implements StatFilterContextListener {\n    @Override\n    public void addUpdateCount(int updateCount) {\n    }\n\n    @Override\n    public void addFetchRowCount(int fetchRowCount) {\n    }\n\n    @Override\n    public void executeBefore(String sql, boolean inTransaction) {\n    }\n\n    @Override\n    public void executeAfter(String sql, long nanoSpan, Throwable error) {\n    }\n\n    @Override\n    public void commit() {\n    }\n\n    @Override\n    public void rollback() {\n    }\n\n    @Override\n    public void pool_connect() {\n    }\n\n    @Override\n    public void pool_close(long nanos) {\n    }\n\n    @Override\n    public void physical_connection_connect() {\n    }\n\n    @Override\n    public void physical_connection_close(long nanos) {\n    }\n\n    @Override\n    public void resultSet_open() {\n    }\n\n    @Override\n    public void resultSet_close(long nanos) {\n    }\n\n    @Override\n    public void clob_open() {\n    }\n\n    @Override\n    public void blob_open() {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/filter/stat/StatFilterMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.filter.stat;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface StatFilterMBean {\n    boolean isMergeSql();\n\n    void setMergeSql(boolean mergeSql);\n\n    boolean isLogSlowSql();\n\n    void setLogSlowSql(boolean logSlowSql);\n\n    String mergeSql(String sql, String dbType);\n\n    long getSlowSqlMillis();\n\n    void setSlowSqlMillis(long slowSqlMillis);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockArray.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.Array;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Map;\n\npublic class MockArray implements Array {\n    private int baseType;\n\n    public MockArray() {\n    }\n\n    @Override\n    public String getBaseTypeName() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public int getBaseType() throws SQLException {\n        return baseType;\n    }\n\n    @Override\n    public Object getArray() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Object getArray(Map<String, Class<?>> map) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Object getArray(long index, int count) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public ResultSet getResultSet() throws SQLException {\n        return new MockResultSet(null);\n    }\n\n    @Override\n    public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {\n        return new MockResultSet(null);\n    }\n\n    @Override\n    public ResultSet getResultSet(long index, int count) throws SQLException {\n        return new MockResultSet(null);\n    }\n\n    @Override\n    public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map) throws SQLException {\n        return new MockResultSet(null);\n    }\n\n    @Override\n    public void free() throws SQLException {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockBlob.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.sql.Blob;\nimport java.sql.SQLException;\n\npublic class MockBlob implements Blob {\n    private final ByteArrayOutputStream out = new ByteArrayOutputStream();\n\n    @Override\n    public long length() throws SQLException {\n        return out.size();\n    }\n\n    @Override\n    public byte[] getBytes(long pos, int length) throws SQLException {\n        byte[] bytes = new byte[length];\n        byte[] outBytes = out.toByteArray();\n        System.arraycopy(outBytes, (int) (pos - 1), bytes, 0, length);\n        return bytes;\n    }\n\n    @Override\n    public InputStream getBinaryStream() throws SQLException {\n        return new ByteArrayInputStream(out.toByteArray());\n    }\n\n    @Override\n    public long position(byte[] pattern, long start) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public long position(Blob pattern, long start) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public int setBytes(long pos, byte[] bytes) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public OutputStream setBinaryStream(long pos) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public void truncate(long len) throws SQLException {\n    }\n\n    @Override\n    public void free() throws SQLException {\n    }\n\n    @Override\n    public InputStream getBinaryStream(long pos, long length) throws SQLException {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockCallableStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.List;\nimport java.util.Map;\n\npublic class MockCallableStatement extends MockPreparedStatement implements CallableStatement {\n    private final List<Object> outParameters = new ArrayList<Object>();\n    private boolean wasNull;\n\n    public MockCallableStatement(MockConnection conn, String sql) {\n        super(conn, sql);\n    }\n\n    public List<Object> getOutParameters() {\n        return outParameters;\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {\n        if (parameterIndex < 1) {\n            throw new SQLException();\n        }\n\n        if (outParameters.size() >= parameterIndex - 1) {\n            outParameters.add(null);\n        } else {\n            throw new SQLException();\n        }\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {\n        registerOutParameter(parameterIndex, sqlType);\n    }\n\n    @Override\n    public boolean wasNull() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return wasNull;\n    }\n\n    @Override\n    public String getString(int columnIndex) throws SQLException {\n        return (String) getObject(columnIndex);\n    }\n\n    @Override\n    public boolean getBoolean(int columnIndex) throws SQLException {\n        Object obj = getObject(columnIndex);\n\n        if (obj == null) {\n            return false;\n        }\n\n        return ((Boolean) obj).booleanValue();\n    }\n\n    @Override\n    public byte getByte(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.byteValue();\n    }\n\n    @Override\n    public short getShort(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.shortValue();\n    }\n\n    @Override\n    public int getInt(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.intValue();\n    }\n\n    @Override\n    public long getLong(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.longValue();\n    }\n\n    @Override\n    public float getFloat(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.floatValue();\n    }\n\n    @Override\n    public double getDouble(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.doubleValue();\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {\n        return (BigDecimal) getObject(columnIndex);\n    }\n\n    @Override\n    public byte[] getBytes(int columnIndex) throws SQLException {\n        return (byte[]) getObject(columnIndex);\n    }\n\n    @Override\n    public Date getDate(int columnIndex) throws SQLException {\n        return (Date) getObject(columnIndex);\n    }\n\n    @Override\n    public Time getTime(int columnIndex) throws SQLException {\n        return (Time) getObject(columnIndex);\n    }\n\n    @Override\n    public Timestamp getTimestamp(int columnIndex) throws SQLException {\n        return (Timestamp) getObject(columnIndex);\n    }\n\n    @Override\n    public String getString(String columnLabel) throws SQLException {\n        return getString(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public boolean getBoolean(String columnLabel) throws SQLException {\n        return getBoolean(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public byte getByte(String columnLabel) throws SQLException {\n        return getByte(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public short getShort(String columnLabel) throws SQLException {\n        return getShort(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public int getInt(String columnLabel) throws SQLException {\n        return getInt(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public long getLong(String columnLabel) throws SQLException {\n        return getLong(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public float getFloat(String columnLabel) throws SQLException {\n        return getFloat(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public double getDouble(String columnLabel) throws SQLException {\n        return getDouble(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public byte[] getBytes(String columnLabel) throws SQLException {\n        return getBytes(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public Date getDate(String columnLabel) throws SQLException {\n        return getDate(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public Time getTime(String columnLabel) throws SQLException {\n        return getTime(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public Timestamp getTimestamp(String columnLabel) throws SQLException {\n        return getTimestamp(Integer.parseInt(columnLabel));\n    }\n\n    @Override\n    public Object getObject(int parameterIndex) throws SQLException {\n        Object obj = outParameters.get(parameterIndex - 1);\n\n        wasNull = (obj == null);\n\n        return obj;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {\n        return (BigDecimal) getObject(parameterIndex);\n    }\n\n    @Override\n    public Object getObject(int parameterIndex, Map<String, Class<?>> map) throws SQLException {\n        return getObject(parameterIndex);\n    }\n\n    @Override\n    public Ref getRef(int parameterIndex) throws SQLException {\n        return (Ref) getObject(parameterIndex);\n    }\n\n    @Override\n    public Blob getBlob(int parameterIndex) throws SQLException {\n        return (Blob) getObject(parameterIndex);\n    }\n\n    @Override\n    public Clob getClob(int parameterIndex) throws SQLException {\n        return (Clob) getObject(parameterIndex);\n    }\n\n    @Override\n    public Array getArray(int parameterIndex) throws SQLException {\n        return (Array) getObject(parameterIndex);\n    }\n\n    @Override\n    public Date getDate(int parameterIndex, Calendar cal) throws SQLException {\n        return (Date) getObject(parameterIndex);\n    }\n\n    @Override\n    public Time getTime(int parameterIndex, Calendar cal) throws SQLException {\n        return (Time) getObject(parameterIndex);\n    }\n\n    @Override\n    public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {\n        return (Timestamp) getObject(parameterIndex);\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {\n        registerOutParameter(parameterIndex, sqlType);\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType) throws SQLException {\n        registerOutParameter(Integer.parseInt(parameterName), sqlType);\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {\n        registerOutParameter(parameterName, sqlType);\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {\n        registerOutParameter(parameterName, sqlType);\n    }\n\n    @Override\n    public URL getURL(int parameterIndex) throws SQLException {\n        return (URL) getObject(parameterIndex);\n    }\n\n    @Override\n    public void setURL(String parameterName, URL x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNull(String parameterName, int sqlType) throws SQLException {\n        setObject(parameterName, null);\n    }\n\n    @Override\n    public void setBoolean(String parameterName, boolean x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setByte(String parameterName, byte x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setShort(String parameterName, short x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setInt(String parameterName, int x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setLong(String parameterName, long x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setFloat(String parameterName, float x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setDouble(String parameterName, double x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setString(String parameterName, String x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setBytes(String parameterName, byte[] x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setDate(String parameterName, Date x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setTime(String parameterName, Time x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setTimestamp(String parameterName, Timestamp x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x) throws SQLException {\n        setObject(Integer.parseInt(parameterName), x);\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, Reader x, int length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setDate(String parameterName, Date x, Calendar cal) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setTime(String parameterName, Time x, Calendar cal) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {\n        setObject(parameterName, null);\n    }\n\n    @Override\n    public Object getObject(String parameterName) throws SQLException {\n        return getObject(Integer.parseInt(parameterName));\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String parameterName) throws SQLException {\n        return getBigDecimal(Integer.parseInt(parameterName));\n    }\n\n    @Override\n    public Object getObject(String parameterName, Map<String, Class<?>> map) throws SQLException {\n        return getObject(parameterName);\n    }\n\n    @Override\n    public Ref getRef(String parameterName) throws SQLException {\n        return (Ref) getObject(parameterName);\n    }\n\n    @Override\n    public Blob getBlob(String parameterName) throws SQLException {\n        return (Blob) getObject(parameterName);\n    }\n\n    @Override\n    public Clob getClob(String parameterName) throws SQLException {\n        return (Clob) getObject(parameterName);\n    }\n\n    @Override\n    public Array getArray(String parameterName) throws SQLException {\n        return (Array) getObject(parameterName);\n    }\n\n    @Override\n    public Date getDate(String parameterName, Calendar cal) throws SQLException {\n        return (Date) getObject(parameterName);\n    }\n\n    @Override\n    public Time getTime(String parameterName, Calendar cal) throws SQLException {\n        return (Time) getObject(parameterName);\n    }\n\n    @Override\n    public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {\n        return (Timestamp) getObject(parameterName);\n    }\n\n    @Override\n    public URL getURL(String parameterName) throws SQLException {\n        return (URL) getObject(parameterName);\n    }\n\n    @Override\n    public RowId getRowId(int parameterIndex) throws SQLException {\n        return (RowId) getObject(parameterIndex);\n    }\n\n    @Override\n    public RowId getRowId(String parameterName) throws SQLException {\n        return (RowId) getObject(parameterName);\n    }\n\n    @Override\n    public void setRowId(String parameterName, RowId x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNString(String parameterName, String x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNCharacterStream(String parameterName, Reader x, long length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNClob(String parameterName, NClob x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setClob(String parameterName, Reader x, long length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setBlob(String parameterName, InputStream x, long length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNClob(String parameterName, Reader x, long length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public NClob getNClob(int parameterIndex) throws SQLException {\n        return (NClob) getObject(parameterIndex);\n    }\n\n    @Override\n    public NClob getNClob(String parameterName) throws SQLException {\n        return (NClob) getObject(parameterName);\n    }\n\n    @Override\n    public void setSQLXML(String parameterName, SQLXML x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public SQLXML getSQLXML(int parameterIndex) throws SQLException {\n        return (SQLXML) getObject(parameterIndex);\n    }\n\n    @Override\n    public SQLXML getSQLXML(String parameterName) throws SQLException {\n        return (SQLXML) getObject(parameterName);\n    }\n\n    @Override\n    public String getNString(int parameterIndex) throws SQLException {\n        return (String) getObject(parameterIndex);\n    }\n\n    @Override\n    public String getNString(String parameterName) throws SQLException {\n        return (String) getObject(parameterName);\n    }\n\n    @Override\n    public Reader getNCharacterStream(int parameterIndex) throws SQLException {\n        return (Reader) getObject(parameterIndex);\n    }\n\n    @Override\n    public Reader getNCharacterStream(String parameterName) throws SQLException {\n        return (Reader) getObject(parameterName);\n    }\n\n    @Override\n    public Reader getCharacterStream(int parameterIndex) throws SQLException {\n        return (Reader) getObject(parameterIndex);\n    }\n\n    @Override\n    public Reader getCharacterStream(String parameterName) throws SQLException {\n        return (Reader) getObject(parameterName);\n    }\n\n    @Override\n    public void setBlob(String parameterName, Blob x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setClob(String parameterName, Clob x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, Reader x, long length) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, InputStream x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, InputStream x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, Reader x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNCharacterStream(String parameterName, Reader x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setClob(String parameterName, Reader x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setBlob(String parameterName, InputStream x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    @Override\n    public void setNClob(String parameterName, Reader x) throws SQLException {\n        setObject(parameterName, x);\n    }\n\n    public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public <T> T getObject(String parameterName, Class<T> type) throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockClob.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.io.*;\nimport java.sql.Clob;\nimport java.sql.SQLException;\n\npublic class MockClob implements Clob {\n    private byte[] bytes;\n    private ByteArrayOutputStream out = new ByteArrayOutputStream();\n\n    public MockClob() {\n        this(new byte[0]);\n    }\n\n    public MockClob(byte[] bytes) {\n        this.bytes = bytes;\n    }\n\n    @Override\n    public long length() throws SQLException {\n        return bytes.length;\n    }\n\n    @Override\n    public String getSubString(long pos, int length) throws SQLException {\n        return new String(bytes, (int) (pos - 1), length);\n    }\n\n    @Override\n    public Reader getCharacterStream() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public InputStream getAsciiStream() throws SQLException {\n        return new ByteArrayInputStream(bytes);\n    }\n\n    @Override\n    public long position(String searchstr, long start) throws SQLException {\n        if (bytes.length == 0) {\n            return 0;\n        }\n\n        return new String(bytes).indexOf(searchstr);\n    }\n\n    @Override\n    public long position(Clob searchstr, long start) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public int setString(long pos, String str) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public int setString(long pos, String str, int offset, int len) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public OutputStream setAsciiStream(long pos) throws SQLException {\n        return out;\n    }\n\n    @Override\n    public Writer setCharacterStream(long pos) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public void truncate(long len) throws SQLException {\n    }\n\n    @Override\n    public void free() throws SQLException {\n    }\n\n    @Override\n    public Reader getCharacterStream(long pos, long length) throws SQLException {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockConnection.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport com.alibaba.druid.util.jdbc.ConnectionBase;\n\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\npublic class MockConnection extends ConnectionBase implements Connection {\n    // private static final Log LOG = LogFactory.getLog(MockConnection.class);\n\n    private boolean closed;\n\n    private MockDriver driver;\n    private int savepointIdSeed;\n    private List<Savepoint> savepoints = new ArrayList<Savepoint>();\n\n    private long id;\n\n    private final long createdTimeMillis = System.currentTimeMillis();\n    private long lastActiveTimeMillis = System.currentTimeMillis();\n    private int networkTimeout;\n\n    private SQLException error;\n\n    private String lastSql;\n\n    public MockConnection() {\n        this(null, null, null);\n    }\n\n    public MockConnection(MockDriver driver, String url, Properties connectProperties) {\n        super(url, connectProperties);\n\n        this.driver = driver;\n\n        if (driver != null) {\n            this.id = driver.generateConnectionId();\n        }\n    }\n\n    public String getLastSql() {\n        return lastSql;\n    }\n\n    public void setLastSql(String lastSql) {\n        this.lastSql = lastSql;\n    }\n\n    public SQLException getError() {\n        return error;\n    }\n\n    public void setError(SQLException error) {\n        this.error = error;\n    }\n\n    public List<Savepoint> getSavepoints() {\n        return savepoints;\n    }\n\n    public long getLastActiveTimeMillis() {\n        return lastActiveTimeMillis;\n    }\n\n    public void setLastActiveTimeMillis(long lastActiveTimeMillis) {\n        this.lastActiveTimeMillis = lastActiveTimeMillis;\n    }\n\n    public long getCreatedTimeMillis() {\n        return createdTimeMillis;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public MockDriver getDriver() {\n        return driver;\n    }\n\n    public void setDriver(MockDriver driver) {\n        this.driver = driver;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface.isInstance(this)) {\n            return (T) this;\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return iface.isInstance(this);\n    }\n\n    @Override\n    public Statement createStatement() throws SQLException {\n        checkState();\n\n        return createMockStatement();\n    }\n\n    private MockStatement createMockStatement() {\n        if (driver != null) {\n            return driver.createMockStatement(this);\n        }\n        return new MockStatement(this);\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql) throws SQLException {\n        checkState();\n\n        return createMockPreparedStatement(sql);\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql) throws SQLException {\n        checkState();\n\n        return createMockCallableStatement(sql);\n    }\n\n    @Override\n    public String nativeSQL(String sql) throws SQLException {\n        checkState();\n\n        return sql;\n    }\n\n    @Override\n    public void setAutoCommit(boolean autoCommit) throws SQLException {\n        checkState();\n\n        super.setAutoCommit(autoCommit);\n    }\n\n    @Override\n    public void commit() throws SQLException {\n        checkState();\n    }\n\n    @Override\n    public void rollback() throws SQLException {\n        checkState();\n\n        this.savepoints.clear();\n    }\n\n    @Override\n    public void close() throws SQLException {\n        if (!closed) {\n            closed = true;\n            if (driver != null) {\n                driver.afterConnectionClose(this);\n            }\n        }\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        return closed;\n    }\n\n    @Override\n    public DatabaseMetaData getMetaData() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {\n        checkState();\n\n        MockStatement stmt = createMockStatement();\n\n        stmt.setResultSetType(resultSetType);\n        stmt.setResultSetConcurrency(resultSetConcurrency);\n\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        checkState();\n\n        MockPreparedStatement stmt = createMockPreparedStatement(sql);\n\n        stmt.setResultSetType(resultSetType);\n        stmt.setResultSetConcurrency(resultSetConcurrency);\n\n        return stmt;\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\n        checkState();\n\n        MockCallableStatement stmt = createMockCallableStatement(sql);\n\n        stmt.setResultSetType(resultSetType);\n        stmt.setResultSetConcurrency(resultSetConcurrency);\n\n        return stmt;\n    }\n\n    @Override\n    public Map<String, Class<?>> getTypeMap() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {\n    }\n\n    @Override\n    public Savepoint setSavepoint() throws SQLException {\n        checkState();\n\n        MockSavepoint savepoint = new MockSavepoint();\n        savepoint.setSavepointId(this.savepointIdSeed++);\n        this.savepoints.add(savepoint);\n\n        return savepoint;\n    }\n\n    @Override\n    public Savepoint setSavepoint(String name) throws SQLException {\n        checkState();\n\n        MockSavepoint savepoint = new MockSavepoint();\n        savepoint.setSavepointId(this.savepointIdSeed++);\n        savepoint.setSavepointName(name);\n        this.savepoints.add(savepoint);\n\n        return savepoint;\n    }\n\n    public void checkState() throws SQLException {\n        if (error != null) {\n            throw error;\n        }\n\n        if (closed) {\n            throw new MockConnectionClosedException();\n        }\n    }\n\n    @Override\n    public void rollback(Savepoint savepoint) throws SQLException {\n        checkState();\n\n        int index = this.savepoints.indexOf(savepoint);\n        if (index == -1) {\n            throw new SQLException(\"savepoint not contained\");\n        }\n        for (int i = savepoints.size() - 1; i >= index; --i) {\n            savepoints.remove(i);\n        }\n    }\n\n    @Override\n    public void releaseSavepoint(Savepoint savepoint) throws SQLException {\n        checkState();\n\n        if (savepoint == null) {\n            throw new SQLException(\"argument is null\");\n        }\n\n        int index = this.savepoints.indexOf(savepoint);\n        if (index == -1) {\n            throw new SQLException(\"savepoint not contained\");\n        }\n        savepoints.remove(savepoint);\n    }\n\n    @Override\n    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n            throws SQLException {\n        checkState();\n\n        MockStatement stmt = createMockStatement();\n\n        stmt.setResultSetType(resultSetType);\n        stmt.setResultSetConcurrency(resultSetConcurrency);\n        stmt.setResultSetHoldability(resultSetHoldability);\n\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,\n                                              int resultSetHoldability) throws SQLException {\n        checkState();\n\n        MockPreparedStatement stmt = createMockPreparedStatement(sql);\n\n        stmt.setResultSetType(resultSetType);\n        stmt.setResultSetConcurrency(resultSetConcurrency);\n        stmt.setResultSetHoldability(resultSetHoldability);\n\n        return stmt;\n    }\n\n    private MockPreparedStatement createMockPreparedStatement(String sql) {\n        if (driver != null) {\n            return driver.createMockPreparedStatement(this, sql);\n        }\n        return new MockPreparedStatement(this, sql);\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,\n                                         int resultSetHoldability) throws SQLException {\n        checkState();\n\n        MockCallableStatement stmt = createMockCallableStatement(sql);\n\n        stmt.setResultSetType(resultSetType);\n        stmt.setResultSetConcurrency(resultSetConcurrency);\n        stmt.setResultSetHoldability(resultSetHoldability);\n\n        return stmt;\n    }\n\n    private MockCallableStatement createMockCallableStatement(String sql) {\n        if (driver != null) {\n            return driver.createMockCallableStatement(this, sql);\n        }\n        return new MockCallableStatement(this, sql);\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {\n        checkState();\n\n        return createMockPreparedStatement(sql);\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {\n        checkState();\n\n        return createMockPreparedStatement(sql);\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {\n        checkState();\n\n        return createMockPreparedStatement(sql);\n    }\n\n    @Override\n    public Clob createClob() throws SQLException {\n        if (driver != null) {\n            return driver.createClob(this);\n        }\n\n        return new MockClob();\n    }\n\n    @Override\n    public Blob createBlob() throws SQLException {\n        if (driver != null) {\n            return driver.createBlob(this);\n        }\n\n        return new MockBlob();\n    }\n\n    @Override\n    public NClob createNClob() throws SQLException {\n        if (driver != null) {\n            return driver.createNClob(this);\n        }\n\n        return new MockNClob();\n    }\n\n    @Override\n    public SQLXML createSQLXML() throws SQLException {\n        if (driver != null) {\n            return driver.createSQLXML(this);\n        }\n\n        return new MockSQLXML();\n    }\n\n    @Override\n    public boolean isValid(int timeout) throws SQLException {\n        return false;\n    }\n\n    @Override\n    public void setClientInfo(String name, String value) throws SQLClientInfoException {\n    }\n\n    @Override\n    public void setClientInfo(Properties properties) throws SQLClientInfoException {\n    }\n\n    @Override\n    public String getClientInfo(String name) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Properties getClientInfo() throws SQLException {\n        return new Properties();\n    }\n\n    @Override\n    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {\n        return new MockArray();\n    }\n\n    @Override\n    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {\n        return new MockStruct();\n    }\n\n    public void setSchema(String schema) throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public String getSchema() throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public void abort(Executor executor) throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {\n        this.networkTimeout = milliseconds;\n    }\n\n    public int getNetworkTimeout() throws SQLException {\n        return networkTimeout;\n    }\n\n    @Override\n    public void setReadOnly(boolean readOnly) throws SQLException {\n        checkState();\n        super.setReadOnly(readOnly);\n    }\n\n    public void handleSleep() {\n        if (getConnectProperties() != null) {\n            Object propertyValue = getConnectProperties().get(\"executeSleep\");\n\n            if (propertyValue != null) {\n                long millis = Long.parseLong(propertyValue.toString());\n                try {\n                    Thread.sleep(millis);\n                } catch (InterruptedException e) {\n                    // skip\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockConnectionClosedException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.SQLException;\n\npublic class MockConnectionClosedException extends SQLException {\n    private static final long serialVersionUID = 1L;\n\n    public MockConnectionClosedException() {\n        super();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockDriver.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport com.alibaba.druid.mock.handler.MockExecuteHandler;\nimport com.alibaba.druid.mock.handler.MySqlMockExecuteHandlerImpl;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\n\nimport java.lang.management.ManagementFactory;\nimport java.sql.*;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.logging.Logger;\n\npublic class MockDriver implements Driver, MockDriverMBean {\n    private static Log LOG;\n\n    public static final MockExecuteHandler DEFAULT_HANDLER = new MySqlMockExecuteHandlerImpl();\n\n    private String prefix = \"jdbc:fake:\";\n    private String mockPrefix = \"jdbc:mock:\";\n\n    private MockExecuteHandler executeHandler = DEFAULT_HANDLER;\n\n    public static final MockDriver instance = new MockDriver();\n\n    private final AtomicLong connectCount = new AtomicLong();\n    private final AtomicLong connectionCloseCount = new AtomicLong();\n\n    private final AtomicLong connectionIdSeed = new AtomicLong(1000L);\n\n    private final List<MockConnection> connections = new CopyOnWriteArrayList<MockConnection>();\n\n    private long idleTimeCount = 1000 * 60 * 3;\n\n    private boolean logExecuteQueryEnable = true;\n\n    private static final String MBEAN_NAME = \"com.alibaba.druid:type=MockDriver\";\n\n    static {\n        registerDriver(instance);\n    }\n\n    public boolean isLogExecuteQueryEnable() {\n        return logExecuteQueryEnable;\n    }\n\n    private static Log getLog() {\n        if (LOG == null) {\n            LOG = LogFactory.getLog(MockDriver.class);\n        }\n\n        return LOG;\n    }\n\n    public void setLogExecuteQueryEnable(boolean logExecuteQueryEnable) {\n        this.logExecuteQueryEnable = logExecuteQueryEnable;\n    }\n\n    public long getIdleTimeCount() {\n        return idleTimeCount;\n    }\n\n    public void setIdleTimeCount(long idleTimeCount) {\n        this.idleTimeCount = idleTimeCount;\n    }\n\n    public long generateConnectionId() {\n        return connectionIdSeed.incrementAndGet();\n    }\n\n    public void closeAllConnections() throws SQLException {\n        for (int i = 0, size = this.connections.size(); i < size; ++i) {\n            Connection conn = this.connections.get(size - i - 1);\n            conn.close();\n        }\n    }\n\n    public int getConnectionsSize() {\n        return this.connections.size();\n    }\n\n    public List<MockConnection> getConnections() {\n        return connections;\n    }\n\n    protected void incrementConnectionCloseCount() {\n        connectionCloseCount.incrementAndGet();\n    }\n\n    public long getConnectionCloseCount() {\n        return connectionCloseCount.get();\n    }\n\n    protected void afterConnectionClose(MockConnection conn) {\n        connectionCloseCount.incrementAndGet();\n\n        connections.remove(conn);\n\n        if (getLog().isDebugEnabled()) {\n            getLog().debug(\"conn-\" + conn.getId() + \" close\");\n        }\n    }\n\n    public static boolean registerDriver(Driver driver) {\n        try {\n            DriverManager.registerDriver(driver);\n\n            try {\n                MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n\n                ObjectName objectName = new ObjectName(MBEAN_NAME);\n                if (!mbeanServer.isRegistered(objectName)) {\n                    mbeanServer.registerMBean(instance, objectName);\n                }\n            } catch (Exception ex) {\n                getLog().warn(\"register druid-driver mbean error\", ex);\n            }\n\n            return true;\n        } catch (Exception e) {\n            getLog().error(\"registerDriver error\", e);\n        }\n\n        return false;\n    }\n\n    public MockExecuteHandler getExecuteHandler() {\n        return executeHandler;\n    }\n\n    public void setExecuteHandler(MockExecuteHandler executeHandler) {\n        this.executeHandler = executeHandler;\n    }\n\n    @Override\n    public Connection connect(String url, Properties info) throws SQLException {\n        if (!acceptsURL(url)) {\n            return null;\n        }\n\n        if (info != null) {\n            Object val = info.get(\"connectSleep\");\n            if (val != null) {\n                long millis = Long.parseLong(val.toString());\n                try {\n                    Thread.sleep(millis);\n                } catch (InterruptedException e) {\n                    // skip\n                }\n            }\n        }\n\n        MockConnection conn = createMockConnection(this, url, info);\n\n        if (getLog().isDebugEnabled()) {\n            getLog().debug(\"connect, url \" + url + \", id \" + conn.getId());\n        }\n\n        if (url == null) {\n            connectCount.incrementAndGet();\n            connections.add(conn);\n            return conn;\n        }\n\n        if (url.startsWith(prefix)) {\n            String catalog = url.substring(prefix.length());\n            conn.setCatalog(catalog);\n\n            connectCount.incrementAndGet();\n            connections.add(conn);\n            return conn;\n        }\n\n        if (url.startsWith(mockPrefix)) {\n            String catalog = url.substring(mockPrefix.length());\n            conn.setCatalog(catalog);\n\n            connectCount.incrementAndGet();\n            connections.add(conn);\n            return conn;\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean acceptsURL(String url) throws SQLException {\n        if (url == null) {\n            return false;\n        }\n\n        return url.startsWith(prefix) || url.startsWith(mockPrefix);\n    }\n\n    @Override\n    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public int getMajorVersion() {\n        return 0;\n    }\n\n    @Override\n    public int getMinorVersion() {\n        return 0;\n    }\n\n    @Override\n    public boolean jdbcCompliant() {\n        return true;\n    }\n\n    public MockResultSet createMockResultSet(MockStatementBase stmt) {\n        return new MockResultSet(stmt);\n    }\n\n    public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n        if (logExecuteQueryEnable && getLog().isDebugEnabled()) {\n            getLog().debug(\"executeQuery \" + sql);\n        }\n\n        MockConnection conn = stmt.getConnection();\n\n        long idleTimeMillis = System.currentTimeMillis() - conn.getLastActiveTimeMillis();\n        if (idleTimeMillis >= this.idleTimeCount) {\n            throw new SQLException(\"connection is idle time count\");\n        }\n\n        conn.setLastActiveTimeMillis(System.currentTimeMillis());\n\n        handleSleep(conn);\n\n        if (\"SELECT value FROM _int_1000_\".equalsIgnoreCase(sql)) {\n            MockResultSet rs = createMockResultSet(stmt);\n\n            for (int i = 0; i < 1000; ++i) {\n                rs.getRows().add(new Object[]{i});\n            }\n\n            return rs;\n        }\n\n        return this.executeHandler.executeQuery(stmt, sql);\n    }\n\n    public void handleSleep(MockConnection conn) {\n        if (conn != null) {\n            conn.handleSleep();\n        }\n    }\n\n    public ResultSet createResultSet(MockPreparedStatement stmt) {\n        MockResultSet rs = new MockResultSet(stmt);\n\n        String sql = stmt.getSql();\n\n        if (\"SELECT 1\".equalsIgnoreCase(sql)) {\n            rs.getRows().add(new Object[]{1});\n        } else if (\"SELECT NOW()\".equalsIgnoreCase(sql)) {\n            rs.getRows().add(new Object[]{new java.sql.Timestamp(System.currentTimeMillis())});\n        } else if (\"SELECT ?\".equalsIgnoreCase(sql)) {\n            rs.getRows().add(new Object[]{stmt.getParameters().get(0)});\n        }\n\n        return rs;\n    }\n\n    protected Clob createClob(MockConnection conn) throws SQLException {\n        return new MockClob();\n    }\n\n    protected Blob createBlob(MockConnection conn) throws SQLException {\n        return new MockBlob();\n    }\n\n    protected NClob createNClob(MockConnection conn) throws SQLException {\n        return new MockNClob();\n    }\n\n    protected SQLXML createSQLXML(MockConnection conn) throws SQLException {\n        return new MockSQLXML();\n    }\n\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public MockConnection createMockConnection(MockDriver driver, String url, Properties connectProperties) {\n        return new MockConnection(this, url, connectProperties);\n    }\n\n    public MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql) {\n        return new MockPreparedStatement(conn, sql);\n    }\n\n    public MockStatement createMockStatement(MockConnection conn) {\n        return new MockStatement(conn);\n    }\n\n    public MockCallableStatement createMockCallableStatement(MockConnection conn, String sql) {\n        return new MockCallableStatement(conn, sql);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockDriverMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.SQLException;\n\npublic interface MockDriverMBean {\n    long getConnectionCloseCount();\n\n    int getMajorVersion();\n\n    int getMinorVersion();\n\n    boolean jdbcCompliant();\n\n    boolean acceptsURL(String url) throws SQLException;\n\n    boolean isLogExecuteQueryEnable();\n\n    void setLogExecuteQueryEnable(boolean logExecuteQueryEnable);\n\n    long getIdleTimeCount();\n\n    void setIdleTimeCount(long idleTimeCount);\n\n    void closeAllConnections() throws SQLException;\n\n    int getConnectionsSize();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockNClob.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.NClob;\n\npublic class MockNClob extends MockClob implements NClob {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockParameterMetaData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.ParameterMetaData;\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MockParameterMetaData implements ParameterMetaData {\n    public MockParameterMetaData() {\n    }\n\n    private final List<Parameter> parameters = new ArrayList<Parameter>();\n\n    public List<Parameter> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return false;\n    }\n\n    @Override\n    public int getParameterCount() throws SQLException {\n        return parameters.size();\n    }\n\n    @Override\n    public int isNullable(int param) throws SQLException {\n        return parameters.get(param - 1).getNullable();\n    }\n\n    @Override\n    public boolean isSigned(int param) throws SQLException {\n        return parameters.get(param - 1).isSigned();\n    }\n\n    @Override\n    public int getPrecision(int param) throws SQLException {\n        return parameters.get(param - 1).getPrecision();\n    }\n\n    @Override\n    public int getScale(int param) throws SQLException {\n        return parameters.get(param - 1).getScale();\n    }\n\n    @Override\n    public int getParameterType(int param) throws SQLException {\n        return parameters.get(param - 1).getType();\n    }\n\n    @Override\n    public String getParameterTypeName(int param) throws SQLException {\n        return parameters.get(param - 1).getTypeName();\n    }\n\n    @Override\n    public String getParameterClassName(int param) throws SQLException {\n        return parameters.get(param - 1).getClassName();\n    }\n\n    @Override\n    public int getParameterMode(int param) throws SQLException {\n        return parameters.get(param - 1).getMode();\n    }\n\n    public static class Parameter {\n        private int nullable;\n        private boolean signed;\n        private int mode;\n        private String className;\n        private int type;\n        private String typeName;\n        private int scale;\n        private int precision;\n\n        public int getType() {\n            return type;\n        }\n\n        public void setType(int type) {\n            this.type = type;\n        }\n\n        public int getNullable() {\n            return nullable;\n        }\n\n        public void setNullable(int nullable) {\n            this.nullable = nullable;\n        }\n\n        public boolean isSigned() {\n            return signed;\n        }\n\n        public void setSigned(boolean signed) {\n            this.signed = signed;\n        }\n\n        public int getMode() {\n            return mode;\n        }\n\n        public void setMode(int mode) {\n            this.mode = mode;\n        }\n\n        public String getClassName() {\n            return className;\n        }\n\n        public void setClassName(String className) {\n            this.className = className;\n        }\n\n        public String getTypeName() {\n            return typeName;\n        }\n\n        public void setTypeName(String typeName) {\n            this.typeName = typeName;\n        }\n\n        public int getScale() {\n            return scale;\n        }\n\n        public void setScale(int scale) {\n            this.scale = scale;\n        }\n\n        public int getPrecision() {\n            return precision;\n        }\n\n        public void setPrecision(int precision) {\n            this.precision = precision;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockPreparedStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport com.alibaba.druid.util.jdbc.PreparedStatementBase;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\npublic class MockPreparedStatement extends PreparedStatementBase implements MockStatementBase, PreparedStatement {\n    private final String sql;\n\n    public MockPreparedStatement(MockConnection conn, String sql) {\n        super(conn);\n        this.sql = sql;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public MockConnection getConnection() throws SQLException {\n        return (MockConnection) super.getConnection();\n    }\n\n    @Override\n    public ResultSet executeQuery() throws SQLException {\n        checkOpen();\n\n        MockConnection conn = getConnection();\n\n        if (conn != null && conn.getDriver() != null) {\n            return conn.getDriver().executeQuery(this, sql);\n        }\n\n        if (conn != null) {\n            conn.handleSleep();\n\n            return conn.getDriver().createMockResultSet(this);\n        }\n\n        return new MockResultSet(this);\n    }\n\n    @Override\n    public int executeUpdate() throws SQLException {\n        checkOpen();\n\n        if (getConnection() != null) {\n            getConnection().handleSleep();\n        }\n\n        return 0;\n    }\n\n    @Override\n    public boolean execute() throws SQLException {\n        checkOpen();\n\n        if (getConnection() != null) {\n            getConnection().handleSleep();\n        }\n\n        return false;\n    }\n\n    @Override\n    public ResultSet getResultSet() throws SQLException {\n        checkOpen();\n\n        if (resultSet == null) {\n            resultSet = this.getConnection().getDriver().createResultSet(this);\n        }\n\n        return resultSet;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockRef.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.Ref;\nimport java.sql.SQLException;\nimport java.util.Map;\n\npublic class MockRef implements Ref {\n    private String baseTypeName;\n    private Object object;\n\n    public void setBaseTypeName(String baseTypeName) {\n        this.baseTypeName = baseTypeName;\n    }\n\n    @Override\n    public String getBaseTypeName() throws SQLException {\n        return baseTypeName;\n    }\n\n    @Override\n    public Object getObject(Map<String, Class<?>> map) throws SQLException {\n        return object;\n    }\n\n    @Override\n    public Object getObject() throws SQLException {\n        return object;\n    }\n\n    @Override\n    public void setObject(Object value) throws SQLException {\n        this.object = value;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockResultSet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport com.alibaba.druid.util.jdbc.ResultSetBase;\n\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MockResultSet extends ResultSetBase implements ResultSet {\n    private int rowIndex = -1;\n    private List<Object[]> rows;\n\n    public MockResultSet(Statement statement) {\n        this(statement, new ArrayList<Object[]>());\n    }\n\n    public MockResultSet(Statement statement, List<Object[]> rows) {\n        super(statement);\n        this.rows = rows;\n        super.metaData = new MockResultSetMetaData();\n    }\n\n    public List<Object[]> getRows() {\n        return rows;\n    }\n\n    @Override\n    public synchronized boolean next() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        if (rowIndex < rows.size() - 1) {\n            rowIndex++;\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n\n        return (MockResultSetMetaData) metaData;\n    }\n\n    public MockResultSetMetaData getMockMetaData() throws SQLException {\n        return (MockResultSetMetaData) metaData;\n    }\n\n    public Object getObjectInternal(int columnIndex) {\n        Object[] row = rows.get(rowIndex);\n        Object obj = row[columnIndex - 1];\n        return obj;\n    }\n\n    @Override\n    public synchronized boolean previous() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        if (rowIndex >= 0) {\n            rowIndex--;\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public void updateObject(int columnIndex, Object x) throws SQLException {\n        Object[] row = rows.get(rowIndex);\n        row[columnIndex - 1] = x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockResultSetMetaData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport com.alibaba.druid.util.jdbc.ResultSetMetaDataBase;\n\nimport java.sql.ResultSetMetaData;\n\npublic class MockResultSetMetaData extends ResultSetMetaDataBase implements ResultSetMetaData {\n    public MockResultSetMetaData() {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockRowId.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.RowId;\n\npublic class MockRowId implements RowId {\n    private byte[] bytes;\n\n    public MockRowId() {\n    }\n\n    public MockRowId(byte[] bytes) {\n        this.bytes = bytes;\n    }\n\n    @Override\n    public byte[] getBytes() {\n        return bytes;\n    }\n\n    public void setBytes(byte[] bytes) {\n        this.bytes = bytes;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockSQLXML.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport javax.xml.transform.Result;\nimport javax.xml.transform.Source;\n\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.sql.SQLException;\nimport java.sql.SQLXML;\n\npublic class MockSQLXML implements SQLXML {\n    @Override\n    public void free() throws SQLException {\n    }\n\n    @Override\n    public InputStream getBinaryStream() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public OutputStream setBinaryStream() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Reader getCharacterStream() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Writer setCharacterStream() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public String getString() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public void setString(String value) throws SQLException {\n    }\n\n    @Override\n    public <T extends Source> T getSource(Class<T> sourceClass) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public <T extends Result> T setResult(Class<T> resultClass) throws SQLException {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockSavepoint.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.Savepoint;\n\npublic class MockSavepoint implements Savepoint {\n    private int savepointId;\n    private String savepointName;\n\n    public int getSavepointId() {\n        return savepointId;\n    }\n\n    public void setSavepointId(int savepointId) {\n        this.savepointId = savepointId;\n    }\n\n    public String getSavepointName() {\n        return savepointName;\n    }\n\n    public void setSavepointName(String savepointName) {\n        this.savepointName = savepointName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport com.alibaba.druid.util.jdbc.StatementBase;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MockStatement extends StatementBase implements MockStatementBase, Statement {\n    public static final String ERROR_SQL = \"THROW ERROR\";\n\n    protected MockConnection mockConnection;\n\n    public MockStatement(Connection connection) {\n        super(connection);\n\n        if (connection instanceof MockConnection) {\n            mockConnection = (MockConnection) connection;\n        }\n    }\n\n    protected void checkOpen() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        if (this.mockConnection != null) {\n            mockConnection.checkState();\n        }\n    }\n\n    public MockConnection getConnection() {\n        return mockConnection;\n    }\n\n    public void setFakeConnection(MockConnection fakeConnection) {\n        this.mockConnection = fakeConnection;\n        this.setConnection(fakeConnection);\n    }\n\n    @Override\n    public ResultSet executeQuery(String sql) throws SQLException {\n        checkOpen();\n\n        if (mockConnection != null && mockConnection.getDriver() != null) {\n            return mockConnection.getDriver().executeQuery(this, sql);\n        }\n\n        List<Object[]> mockRows = new ArrayList<>();\n        mockRows.add(new Object[1]);\n        return new MockResultSet(this, mockRows);\n    }\n\n    @Override\n    public int executeUpdate(String sql) throws SQLException {\n        checkOpen();\n\n        if (mockConnection != null) {\n            mockConnection.handleSleep();\n        }\n\n        return 0;\n    }\n\n    @Override\n    public boolean execute(String sql) throws SQLException {\n        checkOpen();\n\n        if (ERROR_SQL.equals(sql)) {\n            throw new SQLException();\n        }\n\n        if (mockConnection != null) {\n            mockConnection.setLastSql(sql);\n            mockConnection.handleSleep();\n        }\n\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockStatementBase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\npublic interface MockStatementBase extends Statement {\n    MockConnection getConnection() throws SQLException;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/MockStruct.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock;\n\nimport java.sql.SQLException;\nimport java.sql.Struct;\nimport java.util.Map;\n\npublic class MockStruct implements Struct {\n    @Override\n    public String getSQLTypeName() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Object[] getAttributes() throws SQLException {\n        return null;\n    }\n\n    @Override\n    public Object[] getAttributes(Map<String, Class<?>> map) throws SQLException {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/handler/MockExecuteHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock.handler;\n\nimport com.alibaba.druid.mock.MockStatementBase;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\npublic interface MockExecuteHandler {\n    ResultSet executeQuery(MockStatementBase statement, String sql) throws SQLException;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/mock/handler/MySqlMockExecuteHandlerImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.mock.handler;\n\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.mock.MockResultSetMetaData;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.jdbc.ResultSetMetaDataBase.ColumnMetaData;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.sql.Types;\nimport java.util.List;\n\npublic class MySqlMockExecuteHandlerImpl implements MockExecuteHandler {\n    @Override\n    public ResultSet executeQuery(MockStatementBase statement, String sql) throws SQLException {\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        if (stmtList.size() > 1) {\n            throw new SQLException(\"not support multi-statment. \" + sql);\n        }\n\n        if (stmtList.isEmpty()) {\n            throw new SQLException(\"executeQueryError : \" + sql);\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n\n        if (stmt instanceof CobarShowStatus) {\n            return showStatus(statement);\n        }\n\n        if (!(stmt instanceof SQLSelectStatement)) {\n            throw new SQLException(\"executeQueryError : \" + sql);\n        }\n\n        SQLSelect select = ((SQLSelectStatement) stmt).getSelect();\n        SQLSelectQuery query = select.getQuery();\n\n        if (query instanceof SQLSelectQueryBlock) {\n            return executeQuery(statement, (SQLSelectQueryBlock) query);\n        }\n\n        throw new SQLException(\"TODO\");\n    }\n\n    public ResultSet executeQuery(MockStatementBase statement, SQLSelectQueryBlock query) throws SQLException {\n        SQLTableSource from = query.getFrom();\n\n        if (from instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) from).getExpr();\n\n            if (expr instanceof SQLIdentifierExpr) {\n                String ident = ((SQLIdentifierExpr) expr).getName();\n                if (\"dual\".equalsIgnoreCase(ident)) {\n                    return executeQueryFromDual(statement, query);\n                }\n            }\n            throw new SQLException(\"TODO : \" + query);\n        } else if (from == null) {\n            return executeQueryFromDual(statement, query);\n        } else {\n            throw new SQLException(\"TODO\");\n        }\n    }\n\n    public ResultSet showStatus(MockStatementBase statement) throws SQLException {\n        MockResultSet rs = new MockResultSet(statement);\n        MockResultSetMetaData metaData = rs.getMockMetaData();\n\n        Object[] row = new Object[]{\"on\"};\n\n        ColumnMetaData column = new ColumnMetaData();\n        column.setColumnType(Types.NVARCHAR);\n        metaData.getColumns().add(column);\n\n        rs.getRows().add(row);\n\n        return rs;\n    }\n\n    public ResultSet executeQueryFromDual(MockStatementBase statement, SQLSelectQueryBlock query) throws SQLException {\n        MockResultSet rs = statement.getConnection().getDriver().createMockResultSet(statement);\n        MockResultSetMetaData metaData = rs.getMockMetaData();\n\n        Object[] row = new Object[query.getSelectList().size()];\n\n        for (int i = 0, size = query.getSelectList().size(); i < size; ++i) {\n            ColumnMetaData column = new ColumnMetaData();\n            SQLSelectItem item = query.getSelectList().get(i);\n            SQLExpr expr = item.getExpr();\n\n            if (expr instanceof SQLIntegerExpr) {\n                row[i] = ((SQLNumericLiteralExpr) expr).getNumber();\n                column.setColumnType(Types.INTEGER);\n            } else if (expr instanceof SQLNumberExpr) {\n                row[i] = ((SQLNumericLiteralExpr) expr).getNumber();\n                column.setColumnType(Types.DECIMAL);\n            } else if (expr instanceof SQLCharExpr) {\n                row[i] = ((SQLCharExpr) expr).getText();\n                column.setColumnType(Types.VARCHAR);\n            } else if (expr instanceof SQLNCharExpr) {\n                row[i] = ((SQLNCharExpr) expr).getText();\n                column.setColumnType(Types.NVARCHAR);\n            } else if (expr instanceof SQLBooleanExpr) {\n                row[i] = ((SQLBooleanExpr) expr).getBooleanValue();\n                column.setColumnType(Types.NVARCHAR);\n            } else if (expr instanceof SQLNullExpr) {\n                row[i] = null;\n            } else if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;\n\n                if (\"NOW\".equalsIgnoreCase(methodInvokeExpr.getMethodName())) {\n                    row[i] = new Timestamp(System.currentTimeMillis());\n                } else {\n                    throw new SQLException(\"TODO\");\n                }\n            } else if (expr instanceof SQLVariantRefExpr) {\n                SQLVariantRefExpr varExpr = (SQLVariantRefExpr) expr;\n                int varIndex = varExpr.getIndex();\n                if (statement instanceof MockPreparedStatement) {\n                    MockPreparedStatement mockPstmt = (MockPreparedStatement) statement;\n                    row[i] = mockPstmt.getParameters().get(varIndex);\n                } else {\n                    row[i] = null;\n                }\n            } else {\n                row[i] = null;\n            }\n\n            metaData.getColumns().add(column);\n        }\n\n        rs.getRows().add(row);\n\n        return rs;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DataSourceClosedException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.SQLException;\n\npublic class DataSourceClosedException extends SQLException {\n    private static final long serialVersionUID = 1L;\n\n    public DataSourceClosedException(String reason) {\n        super(reason);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DataSourceDisableException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.SQLException;\n\npublic class DataSourceDisableException extends SQLException {\n    private static final long serialVersionUID = 1L;\n\n    public DataSourceDisableException() {\n        super();\n    }\n\n    public DataSourceDisableException(String reason) {\n        super(reason);\n    }\n\n    public DataSourceDisableException(Throwable cause) {\n        super(cause);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DataSourceNotAvailableException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.SQLException;\n\npublic class DataSourceNotAvailableException extends SQLException {\n    private static final long serialVersionUID = 1L;\n\n    public DataSourceNotAvailableException(Throwable cause) {\n        super(cause);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.DruidRuntimeException;\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.filter.FilterManager;\nimport com.alibaba.druid.pool.vendor.NullExceptionSorter;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.proxy.jdbc.TransactionInfo;\nimport com.alibaba.druid.stat.DataSourceMonitorable;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.*;\n\nimport javax.management.JMException;\nimport javax.management.ObjectName;\nimport javax.management.openmbean.CompositeDataSupport;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.PasswordCallback;\nimport javax.sql.DataSource;\n\nimport java.io.PrintWriter;\nimport java.io.Serializable;\nimport java.sql.*;\nimport java.util.*;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\nimport java.util.concurrent.atomic.AtomicReferenceFieldUpdater;\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.logging.Logger;\n\nimport static com.alibaba.druid.util.JdbcConstants.POSTGRESQL_DRIVER;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n * @author ljw [ljw2083@alibaba-inc.com]\n */\npublic abstract class DruidAbstractDataSource extends WrapperAdapter implements DruidAbstractDataSourceMBean, DataSource,\n    DataSourceProxy, Serializable, DataSourceMonitorable {\n    private static final long serialVersionUID = 1L;\n    private static final Log LOG = LogFactory.getLog(DruidAbstractDataSource.class);\n\n    public static final int DEFAULT_INITIAL_SIZE = 0;\n    public static final int DEFAULT_MAX_ACTIVE_SIZE = 8;\n    public static final int DEFAULT_MAX_IDLE = 8;\n    public static final int DEFAULT_MIN_IDLE = 0;\n    public static final int DEFAULT_MAX_WAIT = -1;\n    public static final String DEFAULT_VALIDATION_QUERY = null;                                                //\n    public static final boolean DEFAULT_TEST_ON_BORROW = false;\n    public static final boolean DEFAULT_TEST_ON_RETURN = false;\n    public static final boolean DEFAULT_WHILE_IDLE = true;\n    public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 60 * 1000L;\n    public static final long DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS = 500;\n    public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;\n    public static final int DEFAULT_TIME_CONNECT_TIMEOUT_MILLIS = 10_000;\n    public static final int DEFAULT_TIME_SOCKET_TIMEOUT_MILLIS = 10_000;\n\n    public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;\n    public static final long DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 60L * 7;\n    public static final long DEFAULT_PHY_TIMEOUT_MILLIS = -1;\n\n    protected volatile boolean defaultAutoCommit = true;\n    protected volatile Boolean defaultReadOnly;\n    protected volatile Integer defaultTransactionIsolation;\n    protected volatile String defaultCatalog;\n\n    protected String name;\n\n    protected volatile String username;\n    protected volatile String password;\n    protected volatile String jdbcUrl;\n    protected volatile String driverClass;\n    protected volatile ClassLoader driverClassLoader;\n    protected volatile Properties connectProperties = new Properties();\n\n    protected volatile PasswordCallback passwordCallback;\n    protected volatile NameCallback userCallback;\n\n    protected volatile int initialSize = DEFAULT_INITIAL_SIZE;\n    protected volatile int maxActive = DEFAULT_MAX_ACTIVE_SIZE;\n    protected volatile int minIdle = DEFAULT_MIN_IDLE;\n    protected volatile int maxIdle = DEFAULT_MAX_IDLE;\n    protected volatile long maxWait = DEFAULT_MAX_WAIT;\n    protected int notFullTimeoutRetryCount;\n\n    protected volatile String validationQuery = DEFAULT_VALIDATION_QUERY;\n    protected volatile int validationQueryTimeout = -1;\n    protected volatile boolean testOnBorrow = DEFAULT_TEST_ON_BORROW;\n    protected volatile boolean testOnReturn = DEFAULT_TEST_ON_RETURN;\n    protected volatile boolean testWhileIdle = DEFAULT_WHILE_IDLE;\n    protected volatile boolean poolPreparedStatements;\n    protected volatile boolean sharePreparedStatements;\n    protected volatile int maxPoolPreparedStatementPerConnectionSize = 10;\n\n    protected volatile boolean inited;\n    protected volatile boolean initExceptionThrow = true;\n\n    protected PrintWriter logWriter = new PrintWriter(System.out);\n\n    protected List<Filter> filters = new CopyOnWriteArrayList<Filter>();\n    private boolean clearFiltersEnable = true;\n    protected volatile ExceptionSorter exceptionSorter;\n\n    protected Driver driver;\n\n    protected volatile int connectTimeout; // milliSeconds\n    protected volatile int socketTimeout; // milliSeconds\n    private volatile String connectTimeoutStr;\n    private volatile String socketTimeoutStr;\n\n    protected volatile int queryTimeout; // seconds\n    protected volatile int transactionQueryTimeout; // seconds\n\n    protected long createTimespan;\n\n    protected volatile int maxWaitThreadCount = -1;\n    protected volatile boolean accessToUnderlyingConnectionAllowed = true;\n\n    protected volatile long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;\n    protected volatile int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;\n    protected volatile long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;\n    protected volatile long maxEvictableIdleTimeMillis = DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS;\n    protected volatile long keepAliveBetweenTimeMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS * 2;\n    protected volatile long phyTimeoutMillis = DEFAULT_PHY_TIMEOUT_MILLIS;\n    protected volatile long phyMaxUseCount = -1;\n\n    protected volatile boolean removeAbandoned;\n    protected volatile long removeAbandonedTimeoutMillis = 300 * 1000;\n    protected volatile boolean logAbandoned;\n\n    protected volatile int maxOpenPreparedStatements = -1;\n\n    protected volatile List<String> connectionInitSqls;\n\n    protected volatile String dbTypeName;\n\n    protected volatile long timeBetweenConnectErrorMillis = DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS;\n\n    protected volatile ValidConnectionChecker validConnectionChecker;\n\n    protected volatile boolean usePingMethod;\n\n    protected final Map<DruidPooledConnection, Object> activeConnections = new IdentityHashMap<DruidPooledConnection, Object>();\n    protected static final Object PRESENT = new Object();\n\n    protected long id;\n\n    protected int connectionErrorRetryAttempts = 1;\n    protected boolean breakAfterAcquireFailure;\n    protected long transactionThresholdMillis;\n\n    protected final java.util.Date createdTime = new java.util.Date();\n    protected java.util.Date initedTime;\n    protected volatile long errorCount;\n    protected volatile long dupCloseCount;\n    protected volatile long startTransactionCount;\n    protected volatile long commitCount;\n    protected volatile long rollbackCount;\n    protected volatile long cachedPreparedStatementHitCount;\n    protected volatile long preparedStatementCount;\n    protected volatile long closedPreparedStatementCount;\n    protected volatile long cachedPreparedStatementCount;\n    protected volatile long cachedPreparedStatementDeleteCount;\n    protected volatile long cachedPreparedStatementMissCount;\n    protected volatile long userPasswordVersion;\n\n    private volatile FilterChainImpl filterChain;\n\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource>\n            errorCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"errorCount\"),\n            dupCloseCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"dupCloseCount\"),\n            startTransactionCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"startTransactionCount\"),\n            commitCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"commitCount\"),\n            rollbackCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"rollbackCount\"),\n            cachedPreparedStatementHitCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"cachedPreparedStatementHitCount\"),\n            preparedStatementCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"preparedStatementCount\"),\n            closedPreparedStatementCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"closedPreparedStatementCount\"),\n            cachedPreparedStatementCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"cachedPreparedStatementCount\"),\n            cachedPreparedStatementDeleteCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"cachedPreparedStatementDeleteCount\"),\n            cachedPreparedStatementMissCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"cachedPreparedStatementMissCount\"),\n            userPasswordVersionUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"userPasswordVersion\");\n    protected static final AtomicReferenceFieldUpdater<DruidAbstractDataSource, FilterChainImpl> filterChainUpdater\n            = AtomicReferenceFieldUpdater.newUpdater(DruidAbstractDataSource.class, FilterChainImpl.class, \"filterChain\");\n\n    protected final Histogram transactionHistogram = new Histogram(1,\n            10,\n            100,\n            1000,\n            10 * 1000,\n            100 * 1000);\n\n    private boolean dupCloseLogEnable;\n\n    private ObjectName objectName;\n\n    protected volatile long executeCount;\n    protected volatile long executeQueryCount;\n    protected volatile long executeUpdateCount;\n    protected volatile long executeBatchCount;\n\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> executeQueryCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"executeQueryCount\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> executeUpdateCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"executeUpdateCount\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> executeBatchCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"executeBatchCount\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> executeCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"executeCount\");\n\n    protected volatile Throwable createError;\n    protected volatile Throwable lastError;\n    protected volatile long lastErrorTimeMillis;\n    protected volatile Throwable lastCreateError;\n    protected volatile long lastCreateErrorTimeMillis;\n    protected volatile long lastCreateStartTimeMillis;\n\n    protected boolean isOracle;\n    protected boolean isMySql;\n    protected boolean useOracleImplicitCache = true;\n\n    protected ReentrantLock lock;\n    protected Condition notEmpty;\n    protected Condition empty;\n\n    protected ReentrantLock activeConnectionLock = new ReentrantLock();\n\n    protected volatile int createErrorCount;\n    protected volatile int creatingCount;\n    protected volatile int directCreateCount;\n    protected volatile long createCount;\n    protected volatile long destroyCount;\n    protected volatile long createStartNanos;\n\n    static final AtomicIntegerFieldUpdater<DruidAbstractDataSource> createErrorCountUpdater = AtomicIntegerFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"createErrorCount\");\n    static final AtomicIntegerFieldUpdater<DruidAbstractDataSource> creatingCountUpdater = AtomicIntegerFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"creatingCount\");\n    static final AtomicIntegerFieldUpdater<DruidAbstractDataSource> directCreateCountUpdater = AtomicIntegerFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"directCreateCount\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> createCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"createCount\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> destroyCountUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"destroyCount\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> createStartNanosUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"createStartNanos\");\n\n    private boolean useLocalSessionState = true;\n    private boolean keepConnectionUnderlyingTransactionIsolation;\n\n    protected long timeBetweenLogStatsMillis;\n    protected DruidDataSourceStatLogger statLogger = new DruidDataSourceStatLoggerImpl();\n\n    protected boolean asyncCloseConnectionEnable;\n    protected int maxCreateTaskCount = 3;\n    protected boolean failFast;\n    protected volatile int failContinuous;\n    protected volatile long failContinuousTimeMillis;\n    protected ScheduledExecutorService destroyScheduler;\n    protected ScheduledExecutorService createScheduler;\n    protected Executor netTimeoutExecutor;\n    protected volatile boolean netTimeoutError;\n\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> failContinuousTimeMillisUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"failContinuousTimeMillis\");\n    static final AtomicIntegerFieldUpdater<DruidAbstractDataSource> failContinuousUpdater = AtomicIntegerFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"failContinuous\");\n\n    protected boolean initVariants;\n    protected boolean initGlobalVariants;\n    protected volatile boolean onFatalError;\n    protected volatile int onFatalErrorMaxActive;\n    protected volatile int fatalErrorCount;\n    protected volatile int fatalErrorCountLastShrink;\n    protected volatile long lastFatalErrorTimeMillis;\n    protected volatile String lastFatalErrorSql;\n    protected volatile Throwable lastFatalError;\n    protected volatile Throwable keepAliveError;\n\n    /**\n     * Constructs a new DruidAbstractDataSource with a specified lock fairness setting.\n     *\n     * @param lockFair a boolean value indicating whether the lock should be fair or not\n     */\n    public DruidAbstractDataSource(boolean lockFair) {\n        lock = new ReentrantLock(lockFair);\n        notEmpty = lock.newCondition();\n        empty = lock.newCondition();\n    }\n\n    protected FilterChainImpl createChain() {\n        FilterChainImpl chain = filterChainUpdater.getAndSet(this, null);\n        if (chain == null) {\n            chain = new FilterChainImpl(this);\n        }\n        return chain;\n    }\n\n    protected void recycleFilterChain(FilterChainImpl chain) {\n        chain.reset();\n        filterChainUpdater.lazySet(this, chain);\n    }\n\n    public boolean isUseLocalSessionState() {\n        return useLocalSessionState;\n    }\n\n    public void setUseLocalSessionState(boolean useLocalSessionState) {\n        this.useLocalSessionState = useLocalSessionState;\n    }\n\n    public boolean isKeepConnectionUnderlyingTransactionIsolation() {\n        return keepConnectionUnderlyingTransactionIsolation;\n    }\n\n    public void setKeepConnectionUnderlyingTransactionIsolation(boolean keepConnectionUnderlyingTransactionIsolation) {\n        this.keepConnectionUnderlyingTransactionIsolation = keepConnectionUnderlyingTransactionIsolation;\n    }\n\n    public DruidDataSourceStatLogger getStatLogger() {\n        return statLogger;\n    }\n\n    public void setStatLoggerClassName(String className) {\n        Class<?> clazz;\n        try {\n            clazz = Class.forName(className);\n            DruidDataSourceStatLogger statLogger = (DruidDataSourceStatLogger) clazz.newInstance();\n            this.setStatLogger(statLogger);\n        } catch (Exception e) {\n            throw new IllegalArgumentException(className, e);\n        }\n    }\n\n    public void setStatLogger(DruidDataSourceStatLogger statLogger) {\n        this.statLogger = statLogger;\n    }\n\n    public long getTimeBetweenLogStatsMillis() {\n        return timeBetweenLogStatsMillis;\n    }\n\n    public void setTimeBetweenLogStatsMillis(long timeBetweenLogStatsMillis) {\n        this.timeBetweenLogStatsMillis = timeBetweenLogStatsMillis;\n    }\n\n    public boolean isOracle() {\n        return isOracle;\n    }\n\n    public void setOracle(boolean isOracle) {\n        if (inited) {\n            throw new IllegalStateException();\n        }\n        this.isOracle = isOracle;\n    }\n\n    public boolean isUseUnfairLock() {\n        return !lock.isFair();\n    }\n\n    public void setUseUnfairLock(boolean useUnfairLock) {\n        if (lock.isFair() == !useUnfairLock) {\n            return;\n        }\n\n        if (!this.inited) {\n            final ReentrantLock lock = this.lock;\n            lock.lock();\n            try {\n                if (!this.inited) {\n                    this.lock = new ReentrantLock(!useUnfairLock);\n                    this.notEmpty = this.lock.newCondition();\n                    this.empty = this.lock.newCondition();\n                }\n            } finally {\n                lock.unlock();\n            }\n        }\n    }\n\n    public boolean isUseOracleImplicitCache() {\n        return useOracleImplicitCache;\n    }\n\n    public void setUseOracleImplicitCache(boolean useOracleImplicitCache) {\n        if (this.useOracleImplicitCache != useOracleImplicitCache) {\n            this.useOracleImplicitCache = useOracleImplicitCache;\n            boolean isOracleDriver10 = isOracle() && this.driver != null && this.driver.getMajorVersion() == 10;\n\n            if (isOracleDriver10 && useOracleImplicitCache) {\n                this.getConnectProperties().setProperty(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\", \"true\");\n            } else {\n                this.getConnectProperties().remove(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\");\n            }\n        }\n    }\n\n    public Throwable getLastCreateError() {\n        return lastCreateError;\n    }\n\n    public Throwable getLastError() {\n        return this.lastError;\n    }\n\n    public long getLastErrorTimeMillis() {\n        return lastErrorTimeMillis;\n    }\n\n    public java.util.Date getLastErrorTime() {\n        return lastErrorTimeMillis <= 0 ? null : new java.util.Date(lastErrorTimeMillis);\n    }\n\n    public long getLastCreateErrorTimeMillis() {\n        return lastCreateErrorTimeMillis;\n    }\n\n    public java.util.Date getLastCreateErrorTime() {\n        return lastCreateErrorTimeMillis <= 0 ? null : new java.util.Date(lastCreateErrorTimeMillis);\n    }\n\n    public int getTransactionQueryTimeout() {\n        return transactionQueryTimeout <= 0 ? queryTimeout : transactionQueryTimeout;\n    }\n\n    public void setTransactionQueryTimeout(int transactionQueryTimeout) {\n        this.transactionQueryTimeout = transactionQueryTimeout;\n    }\n\n    public long getExecuteCount() {\n        return executeCount + executeQueryCount + executeUpdateCount + executeBatchCount;\n    }\n\n    public long getExecuteUpdateCount() {\n        return executeUpdateCount;\n    }\n\n    public long getExecuteQueryCount() {\n        return executeQueryCount;\n    }\n\n    public long getExecuteBatchCount() {\n        return executeBatchCount;\n    }\n\n    public long getAndResetExecuteCount() {\n        return executeCountUpdater.getAndSet(this, 0)\n                + executeQueryCountUpdater.getAndSet(this, 0)\n                + executeUpdateCountUpdater.getAndSet(this, 0)\n                + executeBatchCountUpdater.getAndSet(this, 0);\n    }\n\n    public long getExecuteCount2() {\n        return executeCount;\n    }\n\n    public void incrementExecuteCount() {\n        this.executeCountUpdater.incrementAndGet(this);\n    }\n\n    public void incrementExecuteUpdateCount() {\n        this.executeUpdateCount++;\n    }\n\n    public void incrementExecuteQueryCount() {\n        this.executeQueryCount++;\n    }\n\n    public void incrementExecuteBatchCount() {\n        this.executeBatchCount++;\n    }\n\n    public boolean isDupCloseLogEnable() {\n        return dupCloseLogEnable;\n    }\n\n    public void setDupCloseLogEnable(boolean dupCloseLogEnable) {\n        this.dupCloseLogEnable = dupCloseLogEnable;\n    }\n\n    public ObjectName getObjectName() {\n        return objectName;\n    }\n\n    public void setObjectName(ObjectName objectName) {\n        this.objectName = objectName;\n    }\n\n    public Histogram getTransactionHistogram() {\n        return transactionHistogram;\n    }\n\n    public void incrementCachedPreparedStatementCount() {\n        cachedPreparedStatementCountUpdater.incrementAndGet(this);\n    }\n\n    public void decrementCachedPreparedStatementCount() {\n        cachedPreparedStatementCountUpdater.decrementAndGet(this);\n    }\n\n    public void incrementCachedPreparedStatementDeleteCount() {\n        cachedPreparedStatementDeleteCountUpdater.incrementAndGet(this);\n    }\n\n    public void incrementCachedPreparedStatementMissCount() {\n        cachedPreparedStatementMissCountUpdater.incrementAndGet(this);\n    }\n\n    protected void incrementUserPasswordVersion() {\n        userPasswordVersionUpdater.incrementAndGet(this);\n    }\n\n    protected long getUserPasswordVersion() {\n        return userPasswordVersionUpdater.get(this);\n    }\n\n    public long getCachedPreparedStatementMissCount() {\n        return cachedPreparedStatementMissCount;\n    }\n\n    public long getCachedPreparedStatementAccessCount() {\n        return cachedPreparedStatementMissCount + cachedPreparedStatementHitCount;\n    }\n\n    public long getCachedPreparedStatementDeleteCount() {\n        return cachedPreparedStatementDeleteCount;\n    }\n\n    public long getCachedPreparedStatementCount() {\n        return cachedPreparedStatementCount;\n    }\n\n    public void incrementClosedPreparedStatementCount() {\n        closedPreparedStatementCountUpdater.incrementAndGet(this);\n    }\n\n    public long getClosedPreparedStatementCount() {\n        return closedPreparedStatementCount;\n    }\n\n    public void incrementPreparedStatementCount() {\n        preparedStatementCountUpdater.incrementAndGet(this);\n    }\n\n    public long getPreparedStatementCount() {\n        return preparedStatementCount;\n    }\n\n    public void incrementCachedPreparedStatementHitCount() {\n        cachedPreparedStatementHitCountUpdater.incrementAndGet(this);\n    }\n\n    public long getCachedPreparedStatementHitCount() {\n        return cachedPreparedStatementHitCount;\n    }\n\n    public long getTransactionThresholdMillis() {\n        return transactionThresholdMillis;\n    }\n\n    public void setTransactionThresholdMillis(long transactionThresholdMillis) {\n        this.transactionThresholdMillis = transactionThresholdMillis;\n    }\n\n    public abstract void logTransaction(TransactionInfo info);\n\n    public long[] getTransactionHistogramValues() {\n        return transactionHistogram.toArray();\n    }\n\n    public long[] getTransactionHistogramRanges() {\n        return transactionHistogram.getRanges();\n    }\n\n    public long getCommitCount() {\n        return commitCount;\n    }\n\n    public void incrementCommitCount() {\n        commitCountUpdater.incrementAndGet(this);\n    }\n\n    public long getRollbackCount() {\n        return rollbackCount;\n    }\n\n    public void incrementRollbackCount() {\n        rollbackCountUpdater.incrementAndGet(this);\n    }\n\n    public long getStartTransactionCount() {\n        return startTransactionCount;\n    }\n\n    public void incrementStartTransactionCount() {\n        startTransactionCountUpdater.incrementAndGet(this);\n    }\n\n    public boolean isBreakAfterAcquireFailure() {\n        return breakAfterAcquireFailure;\n    }\n\n    public void setBreakAfterAcquireFailure(boolean breakAfterAcquireFailure) {\n        this.breakAfterAcquireFailure = breakAfterAcquireFailure;\n    }\n\n    public int getConnectionErrorRetryAttempts() {\n        return connectionErrorRetryAttempts;\n    }\n\n    public void setConnectionErrorRetryAttempts(int connectionErrorRetryAttempts) {\n        this.connectionErrorRetryAttempts = connectionErrorRetryAttempts;\n    }\n\n    public long getDupCloseCount() {\n        return dupCloseCount;\n    }\n\n    public int getMaxPoolPreparedStatementPerConnectionSize() {\n        return maxPoolPreparedStatementPerConnectionSize;\n    }\n\n    public void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize) {\n        this.poolPreparedStatements = maxPoolPreparedStatementPerConnectionSize > 0;\n        this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;\n    }\n\n    public boolean isSharePreparedStatements() {\n        return sharePreparedStatements;\n    }\n\n    public void setSharePreparedStatements(boolean sharePreparedStatements) {\n        this.sharePreparedStatements = sharePreparedStatements;\n    }\n\n    public void incrementDupCloseCount() {\n        dupCloseCountUpdater.incrementAndGet(this);\n    }\n\n    public ValidConnectionChecker getValidConnectionChecker() {\n        return validConnectionChecker;\n    }\n\n    public void setValidConnectionChecker(ValidConnectionChecker validConnectionChecker) {\n        this.validConnectionChecker = validConnectionChecker;\n    }\n\n    public boolean isUsePingMethod() {\n        return usePingMethod;\n    }\n\n    public void setUsePingMethod(boolean usePingMethod) {\n        this.usePingMethod = usePingMethod;\n    }\n\n    public String getValidConnectionCheckerClassName() {\n        return validConnectionChecker == null ? null : validConnectionChecker.getClass().getName();\n    }\n\n    public void setValidConnectionCheckerClassName(String validConnectionCheckerClass) throws Exception {\n        Class<?> clazz = Utils.loadClass(validConnectionCheckerClass);\n        ValidConnectionChecker validConnectionChecker;\n        if (clazz != null) {\n            validConnectionChecker = (ValidConnectionChecker) clazz.newInstance();\n            this.validConnectionChecker = validConnectionChecker;\n        } else {\n            if (LOG.isErrorEnabled()) {\n                LOG.error(\"load validConnectionCheckerClass[\"\n                        + validConnectionCheckerClass + \"] error, and use JDBC4ValidConnectionChecker.\");\n            }\n            this.validConnectionChecker = new JDBC4ValidConnectionChecker();\n        }\n    }\n\n    public String getDbType() {\n        return dbTypeName;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbTypeName = dbType == null ? null : dbType.name();\n    }\n\n    public void setDbType(String dbType) {\n        this.dbTypeName = dbType;\n    }\n\n    public void addConnectionProperty(String name, String value) {\n        if (StringUtils.equals(connectProperties.getProperty(name), value)) {\n            return;\n        }\n\n        if (inited) {\n            throw new UnsupportedOperationException();\n        }\n\n        connectProperties.put(name, value);\n    }\n\n    public Collection<String> getConnectionInitSqls() {\n        return connectionInitSqls == null ? Collections.emptyList() : connectionInitSqls;\n    }\n\n    public void setConnectionInitSqls(Collection<? extends Object> connectionInitSqls) {\n        if ((connectionInitSqls != null) && (connectionInitSqls.size() > 0)) {\n            ArrayList<String> newVal = null;\n            for (Object o : connectionInitSqls) {\n                if (o == null) {\n                    continue;\n                }\n\n                String s = o.toString();\n                s = s.trim();\n                if (s.length() == 0) {\n                    continue;\n                }\n\n                if (newVal == null) {\n                    newVal = new ArrayList<String>();\n                }\n                newVal.add(s);\n            }\n            this.connectionInitSqls = newVal;\n        } else {\n            this.connectionInitSqls = null;\n        }\n    }\n\n    public long getTimeBetweenConnectErrorMillis() {\n        return timeBetweenConnectErrorMillis;\n    }\n\n    public void setTimeBetweenConnectErrorMillis(long timeBetweenConnectErrorMillis) {\n        this.timeBetweenConnectErrorMillis = timeBetweenConnectErrorMillis;\n    }\n\n    public int getMaxOpenPreparedStatements() {\n        return maxPoolPreparedStatementPerConnectionSize;\n    }\n\n    public void setMaxOpenPreparedStatements(int maxOpenPreparedStatements) {\n        this.setMaxPoolPreparedStatementPerConnectionSize(maxOpenPreparedStatements);\n    }\n\n    public boolean isLogAbandoned() {\n        return logAbandoned;\n    }\n\n    public void setLogAbandoned(boolean logAbandoned) {\n        this.logAbandoned = logAbandoned;\n    }\n\n    public int getRemoveAbandonedTimeout() {\n        return (int) (removeAbandonedTimeoutMillis / 1000);\n    }\n\n    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {\n        this.removeAbandonedTimeoutMillis = (long) removeAbandonedTimeout * 1000;\n    }\n\n    public void setRemoveAbandonedTimeoutMillis(long removeAbandonedTimeoutMillis) {\n        this.removeAbandonedTimeoutMillis = removeAbandonedTimeoutMillis;\n    }\n\n    public long getRemoveAbandonedTimeoutMillis() {\n        return removeAbandonedTimeoutMillis;\n    }\n\n    public boolean isRemoveAbandoned() {\n        return removeAbandoned;\n    }\n\n    public void setRemoveAbandoned(boolean removeAbandoned) {\n        this.removeAbandoned = removeAbandoned;\n    }\n\n    public long getMinEvictableIdleTimeMillis() {\n        return minEvictableIdleTimeMillis;\n    }\n\n    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {\n        if (minEvictableIdleTimeMillis < 1000 * 30) {\n            LOG.error(\"minEvictableIdleTimeMillis should be greater than 30000\");\n        }\n        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;\n    }\n\n    public long getKeepAliveBetweenTimeMillis() {\n        return keepAliveBetweenTimeMillis;\n    }\n\n    public void setKeepAliveBetweenTimeMillis(long keepAliveBetweenTimeMillis) {\n        if (keepAliveBetweenTimeMillis < 1000 * 30) {\n            LOG.error(\"keepAliveBetweenTimeMillis should be greater than 30000\");\n        }\n        this.keepAliveBetweenTimeMillis = keepAliveBetweenTimeMillis;\n    }\n\n    public long getMaxEvictableIdleTimeMillis() {\n        return maxEvictableIdleTimeMillis;\n    }\n\n    public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {\n        if (maxEvictableIdleTimeMillis < 1000 * 30) {\n            LOG.error(\"maxEvictableIdleTimeMillis should be greater than 30000\");\n        }\n\n        if (inited && maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {\n            throw new IllegalArgumentException(\"maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis\");\n        }\n\n        this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;\n    }\n\n    public long getPhyTimeoutMillis() {\n        return phyTimeoutMillis;\n    }\n\n    public void setPhyTimeoutMillis(long phyTimeoutMillis) {\n        this.phyTimeoutMillis = phyTimeoutMillis;\n    }\n\n    public long getPhyMaxUseCount() {\n        return phyMaxUseCount;\n    }\n\n    public void setPhyMaxUseCount(long phyMaxUseCount) {\n        this.phyMaxUseCount = phyMaxUseCount;\n    }\n\n    public int getNumTestsPerEvictionRun() {\n        return numTestsPerEvictionRun;\n    }\n\n    /**\n     * @param numTestsPerEvictionRun number of tests per eviction run\n     */\n    @Deprecated\n    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {\n        this.numTestsPerEvictionRun = numTestsPerEvictionRun;\n    }\n\n    public long getTimeBetweenEvictionRunsMillis() {\n        return timeBetweenEvictionRunsMillis;\n    }\n\n    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {\n        if (timeBetweenEvictionRunsMillis <= 0) {\n            throw new IllegalArgumentException(\"timeBetweenEvictionRunsMillis must > 0\");\n        }\n\n        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;\n    }\n\n    public int getMaxWaitThreadCount() {\n        return maxWaitThreadCount;\n    }\n\n    public void setMaxWaitThreadCount(int maxWaithThreadCount) {\n        this.maxWaitThreadCount = maxWaithThreadCount;\n    }\n\n    public String getValidationQuery() {\n        return validationQuery;\n    }\n\n    public void setValidationQuery(String validationQuery) {\n        this.validationQuery = validationQuery;\n    }\n\n    public int getValidationQueryTimeout() {\n        return validationQueryTimeout;\n    }\n\n    public void setValidationQueryTimeout(int validationQueryTimeout) {\n        if (validationQueryTimeout < 0 && DbType.of(dbTypeName) == DbType.sqlserver) {\n            LOG.error(\"validationQueryTimeout should be >= 0\");\n        }\n        this.validationQueryTimeout = validationQueryTimeout;\n    }\n\n    public boolean isAccessToUnderlyingConnectionAllowed() {\n        return accessToUnderlyingConnectionAllowed;\n    }\n\n    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {\n        this.accessToUnderlyingConnectionAllowed = accessToUnderlyingConnectionAllowed;\n    }\n\n    public boolean isTestOnBorrow() {\n        return testOnBorrow;\n    }\n\n    public void setTestOnBorrow(boolean testOnBorrow) {\n        this.testOnBorrow = testOnBorrow;\n    }\n\n    public boolean isTestOnReturn() {\n        return testOnReturn;\n    }\n\n    public void setTestOnReturn(boolean testOnReturn) {\n        this.testOnReturn = testOnReturn;\n    }\n\n    public boolean isTestWhileIdle() {\n        return testWhileIdle;\n    }\n\n    public void setTestWhileIdle(boolean testWhileIdle) {\n        this.testWhileIdle = testWhileIdle;\n    }\n\n    public boolean isDefaultAutoCommit() {\n        return defaultAutoCommit;\n    }\n\n    public void setDefaultAutoCommit(boolean defaultAutoCommit) {\n        this.defaultAutoCommit = defaultAutoCommit;\n    }\n\n    public Boolean getDefaultReadOnly() {\n        return defaultReadOnly;\n    }\n\n    public void setDefaultReadOnly(Boolean defaultReadOnly) {\n        this.defaultReadOnly = defaultReadOnly;\n    }\n\n    public Integer getDefaultTransactionIsolation() {\n        return defaultTransactionIsolation;\n    }\n\n    public void setDefaultTransactionIsolation(Integer defaultTransactionIsolation) {\n        this.defaultTransactionIsolation = defaultTransactionIsolation;\n    }\n\n    public String getDefaultCatalog() {\n        return defaultCatalog;\n    }\n\n    public void setDefaultCatalog(String defaultCatalog) {\n        this.defaultCatalog = defaultCatalog;\n    }\n\n    public PasswordCallback getPasswordCallback() {\n        return passwordCallback;\n    }\n\n    public void setPasswordCallback(PasswordCallback passwordCallback) {\n        this.passwordCallback = passwordCallback;\n    }\n\n    public void setPasswordCallbackClassName(String passwordCallbackClassName) throws Exception {\n        Class<?> clazz = Utils.loadClass(passwordCallbackClassName);\n        if (clazz != null) {\n            this.passwordCallback = (PasswordCallback) clazz.newInstance();\n        } else {\n            LOG.error(\"load passwordCallback error : \" + passwordCallbackClassName);\n            this.passwordCallback = null;\n        }\n    }\n\n    public NameCallback getUserCallback() {\n        return userCallback;\n    }\n\n    public void setUserCallback(NameCallback userCallback) {\n        this.userCallback = userCallback;\n    }\n\n    public boolean isInitVariants() {\n        return initVariants;\n    }\n\n    public void setInitVariants(boolean initVariants) {\n        this.initVariants = initVariants;\n    }\n\n    public boolean isInitGlobalVariants() {\n        return initGlobalVariants;\n    }\n\n    public void setInitGlobalVariants(boolean initGlobalVariants) {\n        this.initGlobalVariants = initGlobalVariants;\n    }\n\n    /**\n     * Retrieves the number of seconds the driver will wait for a <code>Statement</code> object to execute. If the limit\n     * is exceeded, a <code>SQLException</code> is thrown.\n     *\n     * @return the current query timeout limit in seconds; zero means there is no limit\n     * <code>Statement</code>\n     * @see #setQueryTimeout\n     */\n    public int getQueryTimeout() {\n        return queryTimeout;\n    }\n\n    /**\n     * Sets the number of seconds the driver will wait for a <code>Statement</code> object to execute to the given\n     * number of seconds. If the limit is exceeded, an <code>SQLException</code> is thrown. A JDBC driver must apply\n     * this limit to the <code>execute</code>, <code>executeQuery</code> and <code>executeUpdate</code> methods. JDBC\n     * driver implementations may also apply this limit to <code>ResultSet</code> methods (consult your driver vendor\n     * documentation for details).\n     *\n     * @param seconds the new query timeout limit in seconds; zero means there is no limit\n     * @see #getQueryTimeout\n     */\n    public void setQueryTimeout(int seconds) {\n        this.queryTimeout = seconds;\n    }\n\n    /**\n     * @since 1.2.12\n     */\n    public int getConnectTimeout() {\n        return connectTimeout;\n    }\n\n    /**\n     * @since 1.2.12\n     */\n    public void setConnectTimeout(int milliSeconds) {\n        this.connectTimeout = milliSeconds;\n        this.connectTimeoutStr = null;\n    }\n\n    protected void setConnectTimeout(String milliSeconds) {\n        try {\n            this.connectTimeout = Integer.parseInt(milliSeconds);\n        } catch (Exception ignored) {\n            // ignored\n        }\n        this.connectTimeoutStr = null;\n    }\n\n    /**\n     * @since 1.2.12\n     */\n    public int getSocketTimeout() {\n        return socketTimeout;\n    }\n\n    /**\n     * @since 1.2.12\n     */\n    public void setSocketTimeout(int milliSeconds) {\n        this.socketTimeout = milliSeconds;\n        this.socketTimeoutStr = null;\n    }\n\n    protected void setSocketTimeout(String milliSeconds) {\n        try {\n            this.socketTimeout = Integer.parseInt(milliSeconds);\n        } catch (Exception ignored) {\n            // ignored\n        }\n        this.socketTimeoutStr = null;\n    }\n\n    public String getName() {\n        if (name != null) {\n            return name;\n        }\n        return \"DataSource-\" + System.identityHashCode(this);\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public boolean isPoolPreparedStatements() {\n        return poolPreparedStatements;\n    }\n\n    public abstract void setPoolPreparedStatements(boolean value);\n\n    public long getMaxWait() {\n        return maxWait;\n    }\n\n    public void setMaxWait(long maxWaitMillis) {\n        if (maxWaitMillis == this.maxWait) {\n            return;\n        }\n\n        if (inited) {\n            LOG.error(\"maxWait changed : \" + this.maxWait + \" -> \" + maxWaitMillis);\n        }\n\n        this.maxWait = maxWaitMillis;\n    }\n\n    public int getNotFullTimeoutRetryCount() {\n        return notFullTimeoutRetryCount;\n    }\n\n    public void setNotFullTimeoutRetryCount(int notFullTimeoutRetryCount) {\n        this.notFullTimeoutRetryCount = notFullTimeoutRetryCount;\n    }\n\n    public int getMinIdle() {\n        return minIdle;\n    }\n\n    public void setMinIdle(int value) {\n        if (value == this.minIdle) {\n            return;\n        }\n\n        if (inited && value > this.maxActive) {\n            throw new IllegalArgumentException(\"minIdle greater than maxActive, \" + maxActive + \" must >= \" + this.minIdle);\n        }\n\n        if (minIdle < 0) {\n            throw new IllegalArgumentException(\"minIdle must >= 0\");\n        }\n\n        this.minIdle = value;\n    }\n\n    public int getMaxIdle() {\n        return maxIdle;\n    }\n\n    @Deprecated\n    public void setMaxIdle(int maxIdle) {\n        LOG.error(\"maxIdle is deprecated\");\n        this.maxIdle = maxIdle;\n    }\n\n    public int getInitialSize() {\n        return initialSize;\n    }\n\n    public void setInitialSize(int initialSize) {\n        if (this.initialSize == initialSize) {\n            return;\n        }\n\n        if (inited) {\n            throw new UnsupportedOperationException();\n        }\n\n        this.initialSize = initialSize;\n    }\n\n    public long getCreateErrorCount() {\n        return createErrorCount;\n    }\n\n    public int getMaxActive() {\n        return maxActive;\n    }\n\n    public abstract void setMaxActive(int maxActive);\n\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        if (StringUtils.equals(this.username, username)) {\n            return;\n        }\n\n        if (inited) {\n            throw new UnsupportedOperationException();\n        }\n\n        this.username = username;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        if (StringUtils.equals(this.password, password)) {\n            return;\n        }\n\n        if (inited) {\n            LOG.info(\"password changed\");\n        }\n\n        this.password = password;\n    }\n\n    public Properties getConnectProperties() {\n        return connectProperties;\n    }\n\n    public abstract void setConnectProperties(Properties properties);\n\n    public void setConnectionProperties(String connectionProperties) {\n        if (connectionProperties == null || connectionProperties.trim().length() == 0) {\n            setConnectProperties(null);\n            return;\n        }\n\n        String[] entries = connectionProperties.split(\";\");\n        Properties properties = new Properties();\n        for (int i = 0; i < entries.length; i++) {\n            String entry = entries[i];\n            if (entry.length() > 0) {\n                int index = entry.indexOf('=');\n                if (index > 0) {\n                    String name = entry.substring(0, index);\n                    String value = entry.substring(index + 1);\n                    properties.setProperty(name, value);\n                } else {\n                    // no value is empty string which is how java.util.Properties works\n                    properties.setProperty(entry, \"\");\n                }\n            }\n        }\n\n        setConnectProperties(properties);\n    }\n\n    public String getUrl() {\n        return jdbcUrl;\n    }\n\n    public String getRawJdbcUrl() {\n        return jdbcUrl;\n    }\n\n    public void setUrl(String jdbcUrl) {\n        if (StringUtils.equals(this.jdbcUrl, jdbcUrl)) {\n            return;\n        }\n\n        if (inited) {\n            throw new UnsupportedOperationException();\n        }\n\n        if (jdbcUrl != null) {\n            jdbcUrl = jdbcUrl.trim();\n        }\n\n        this.jdbcUrl = jdbcUrl;\n\n        // if (jdbcUrl.startsWith(ConfigFilter.URL_PREFIX)) {\n        // this.filters.add(new ConfigFilter());\n        // }\n    }\n\n    public String getDriverClassName() {\n        return driverClass;\n    }\n\n    public void setDriverClassName(String driverClass) {\n        if (driverClass != null && driverClass.length() > 256) {\n            throw new IllegalArgumentException(\"driverClassName length > 256.\");\n        }\n\n        if (JdbcConstants.ORACLE_DRIVER2.equalsIgnoreCase(driverClass)) {\n            driverClass = \"oracle.jdbc.OracleDriver\";\n            LOG.warn(\"oracle.jdbc.driver.OracleDriver is deprecated.Having use oracle.jdbc.OracleDriver.\");\n        }\n\n        if (inited) {\n            if (StringUtils.equals(this.driverClass, driverClass)) {\n                return;\n            }\n\n            throw new UnsupportedOperationException();\n        }\n\n        this.driverClass = driverClass;\n    }\n\n    public ClassLoader getDriverClassLoader() {\n        return driverClassLoader;\n    }\n\n    public void setDriverClassLoader(ClassLoader driverClassLoader) {\n        this.driverClassLoader = driverClassLoader;\n    }\n\n    @Override\n    public PrintWriter getLogWriter() {\n        return logWriter;\n    }\n\n    @Override\n    public void setLogWriter(PrintWriter out) throws SQLException {\n        this.logWriter = out;\n    }\n\n    @Override\n    public void setLoginTimeout(int seconds) {\n        DriverManager.setLoginTimeout(seconds);\n    }\n\n    @Override\n    public int getLoginTimeout() {\n        return DriverManager.getLoginTimeout();\n    }\n\n    public Driver getDriver() {\n        return driver;\n    }\n\n    public void setDriver(Driver driver) {\n        this.driver = driver;\n    }\n\n    public int getDriverMajorVersion() {\n        if (this.driver == null) {\n            return -1;\n        }\n\n        return this.driver.getMajorVersion();\n    }\n\n    public int getDriverMinorVersion() {\n        if (this.driver == null) {\n            return -1;\n        }\n\n        return this.driver.getMinorVersion();\n    }\n\n    public ExceptionSorter getExceptionSorter() {\n        return exceptionSorter;\n    }\n\n    public String getExceptionSorterClassName() {\n        if (exceptionSorter == null) {\n            return null;\n        }\n\n        return exceptionSorter.getClass().getName();\n    }\n\n    public void setExceptionSorter(ExceptionSorter exceptionSoter) {\n        this.exceptionSorter = exceptionSoter;\n    }\n\n    // 兼容JBOSS\n    public void setExceptionSorterClassName(String exceptionSorter) throws Exception {\n        this.setExceptionSorter(exceptionSorter);\n    }\n\n    public void setExceptionSorter(String exceptionSorter) throws SQLException {\n        if (exceptionSorter == null) {\n            this.exceptionSorter = NullExceptionSorter.getInstance();\n            return;\n        }\n\n        exceptionSorter = exceptionSorter.trim();\n        if (exceptionSorter.length() == 0) {\n            this.exceptionSorter = NullExceptionSorter.getInstance();\n            return;\n        }\n\n        Class<?> clazz = Utils.loadClass(exceptionSorter);\n        if (clazz == null) {\n            LOG.error(\"load exceptionSorter error : \" + exceptionSorter);\n        } else {\n            try {\n                this.exceptionSorter = (ExceptionSorter) clazz.newInstance();\n            } catch (Exception ex) {\n                throw new SQLException(\"create exceptionSorter error\", ex);\n            }\n        }\n    }\n\n    @Override\n    public List<Filter> getProxyFilters() {\n        return filters;\n    }\n\n    public void setProxyFilters(List<Filter> filters) {\n        if (filters != null) {\n            this.filters.addAll(filters);\n        }\n    }\n\n    public String[] getFilterClasses() {\n        List<Filter> filterConfigList = getProxyFilters();\n\n        List<String> classes = new ArrayList<String>();\n        for (Filter filter : filterConfigList) {\n            classes.add(filter.getClass().getName());\n        }\n\n        return classes.toArray(new String[classes.size()]);\n    }\n\n    public void setFilters(String filters) throws SQLException {\n        if (filters != null && filters.startsWith(\"!\")) {\n            filters = filters.substring(1);\n            this.clearFilters();\n        }\n        this.addFilters(filters);\n    }\n\n    public void addFilters(String filters) throws SQLException {\n        if (filters == null || filters.length() == 0) {\n            return;\n        }\n\n        String[] filterArray = filters.split(\"\\\\,\");\n\n        for (String item : filterArray) {\n            FilterManager.loadFilter(this.filters, item.trim());\n        }\n    }\n\n    public void clearFilters() {\n        if (!isClearFiltersEnable()) {\n            return;\n        }\n        this.filters.clear();\n    }\n\n    public void validateConnection(Connection conn) throws SQLException {\n        String query = getValidationQuery();\n        if (conn.isClosed()) {\n            throw new SQLException(\"validateConnection: connection closed\");\n        }\n\n        if (validConnectionChecker != null) {\n            boolean result;\n            Exception error = null;\n            try {\n                result = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);\n\n                if (conn instanceof ConnectionProxyImpl) {\n                    ((ConnectionProxyImpl) conn).setLastValidateTimeMillis(System.currentTimeMillis());\n                }\n                if (result && onFatalError) {\n                    lock.lock();\n                    try {\n                        if (onFatalError) {\n                            onFatalError = false;\n                        }\n                    } finally {\n                        lock.unlock();\n                    }\n                }\n            } catch (SQLException ex) {\n                throw ex;\n            } catch (Exception ex) {\n                result = false;\n                error = ex;\n            }\n\n            if (!result) {\n                SQLException sqlError = error != null ? //\n                        new SQLException(\"validateConnection false\", error) //\n                        : new SQLException(\"validateConnection false\");\n                throw sqlError;\n            }\n            return;\n        }\n\n        if (null != query) {\n            boolean valid;\n            try {\n                valid = ValidConnectionCheckerAdapter.execValidQuery(conn, query, validationQueryTimeout);\n            } catch (SQLException ex) {\n                throw ex;\n            } catch (Exception ex) {\n                throw new SQLException(\"validationQuery failed\", ex);\n            } finally {\n                if (conn instanceof ConnectionProxyImpl) {\n                    ((ConnectionProxyImpl) conn).setLastValidateTimeMillis(System.currentTimeMillis());\n                }\n            }\n\n            if (!valid) {\n                throw new SQLException(\"validationQuery didn't return a row\");\n            }\n\n            if (onFatalError) {\n                lock.lock();\n                try {\n                    if (onFatalError) {\n                        onFatalError = false;\n                    }\n                } finally {\n                    lock.unlock();\n                }\n            }\n        }\n    }\n\n    /**\n     * @deprecated\n     */\n    protected boolean testConnectionInternal(Connection conn) {\n        return testConnectionInternal(null, conn);\n    }\n\n    protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn) {\n        String sqlFile = JdbcSqlStat.getContextSqlFile();\n        String sqlName = JdbcSqlStat.getContextSqlName();\n\n        if (sqlFile != null) {\n            JdbcSqlStat.setContextSqlFile(null);\n        }\n        if (sqlName != null) {\n            JdbcSqlStat.setContextSqlName(null);\n        }\n        try {\n            if (validConnectionChecker != null) {\n                // mysql-connector-java will throw Exception if the connection is broken.\n                boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);\n                long currentTimeMillis = System.currentTimeMillis();\n                if (holder != null) {\n                    holder.lastValidTimeMillis = currentTimeMillis;\n                    holder.lastExecTimeMillis = currentTimeMillis;\n                }\n                if (conn instanceof ConnectionProxyImpl) {\n                    ((ConnectionProxyImpl) conn).setLastValidateTimeMillis(currentTimeMillis);\n                }\n\n                if (valid && onFatalError) {\n                    lock.lock();\n                    try {\n                        if (onFatalError) {\n                            onFatalError = false;\n                        }\n                    } finally {\n                        lock.unlock();\n                    }\n                }\n\n                return valid;\n            }\n\n            if (conn.isClosed()) {\n                return false;\n            }\n\n            if (null == validationQuery) {\n                return true;\n            }\n\n            boolean valid;\n            try {\n                valid = ValidConnectionCheckerAdapter.execValidQuery(conn, validationQuery, validationQueryTimeout);\n            } finally {\n                if (conn instanceof ConnectionProxyImpl) {\n                    ((ConnectionProxyImpl) conn).setLastValidateTimeMillis(System.currentTimeMillis());\n                }\n            }\n\n            if (valid && onFatalError) {\n                lock.lock();\n                try {\n                    if (onFatalError) {\n                        onFatalError = false;\n                    }\n                } finally {\n                    lock.unlock();\n                }\n            }\n\n            return valid;\n        } catch (Throwable ex) {\n            // skip\n            return false;\n        } finally {\n            if (sqlFile != null) {\n                JdbcSqlStat.setContextSqlFile(sqlFile);\n            }\n            if (sqlName != null) {\n                JdbcSqlStat.setContextSqlName(sqlName);\n            }\n        }\n    }\n\n    public Set<DruidPooledConnection> getActiveConnections() {\n        activeConnectionLock.lock();\n        try {\n            return new HashSet<DruidPooledConnection>(this.activeConnections.keySet());\n        } finally {\n            activeConnectionLock.unlock();\n        }\n    }\n\n    public List<String> getActiveConnectionStackTrace() {\n        List<String> list = new ArrayList<String>();\n\n        for (DruidPooledConnection conn : this.getActiveConnections()) {\n            list.add(Utils.toString(conn.getConnectStackTrace()));\n        }\n\n        return list;\n    }\n\n    public long getCreateTimespanNano() {\n        return createTimespan;\n    }\n\n    public long getCreateTimespanMillis() {\n        return createTimespan / (1000 * 1000);\n    }\n\n    @Override\n    public Driver getRawDriver() {\n        return driver;\n    }\n\n    public boolean isClearFiltersEnable() {\n        return clearFiltersEnable;\n    }\n\n    public void setClearFiltersEnable(boolean clearFiltersEnable) {\n        this.clearFiltersEnable = clearFiltersEnable;\n    }\n\n    protected volatile long connectionIdSeed = 10000L;\n    protected volatile long statementIdSeed = 20000L;\n    protected volatile long resultSetIdSeed = 50000L;\n    protected volatile long transactionIdSeed = 60000L;\n    protected volatile long metaDataIdSeed = 80000L;\n\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> connectionIdSeedUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"connectionIdSeed\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> statementIdSeedUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"statementIdSeed\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> resultSetIdSeedUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"resultSetIdSeed\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> transactionIdSeedUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"transactionIdSeed\");\n    static final AtomicLongFieldUpdater<DruidAbstractDataSource> metaDataIdSeedUpdater = AtomicLongFieldUpdater.newUpdater(DruidAbstractDataSource.class, \"metaDataIdSeed\");\n\n    public long createConnectionId() {\n        return connectionIdSeedUpdater.incrementAndGet(this);\n    }\n\n    public long createStatementId() {\n        return statementIdSeedUpdater.getAndIncrement(this);\n    }\n\n    public long createMetaDataId() {\n        return metaDataIdSeedUpdater.getAndIncrement(this);\n    }\n\n    public long createResultSetId() {\n        return resultSetIdSeedUpdater.getAndIncrement(this);\n    }\n\n    @Override\n    public long createTransactionId() {\n        return transactionIdSeedUpdater.getAndIncrement(this);\n    }\n\n    void initStatement(DruidPooledConnection conn, Statement stmt) throws SQLException {\n        boolean transaction = !conn.getConnectionHolder().underlyingAutoCommit;\n\n        int queryTimeout = transaction ? getTransactionQueryTimeout() : getQueryTimeout();\n\n        if (queryTimeout > 0) {\n            stmt.setQueryTimeout(queryTimeout);\n        }\n    }\n\n    public void handleConnectionException(DruidPooledConnection conn, Throwable t) throws SQLException {\n        handleConnectionException(conn, t, null);\n    }\n\n    public abstract void handleConnectionException(\n            DruidPooledConnection conn,\n            Throwable t,\n            String sql\n    ) throws SQLException;\n\n    protected abstract void recycle(DruidPooledConnection pooledConnection) throws SQLException;\n\n    public Connection createPhysicalConnection(String url, Properties info) throws SQLException {\n        Connection conn;\n        if (getProxyFilters().isEmpty()) {\n            Connection rawConn = getDriver().connect(url, info);\n            Statement stmt = rawConn.createStatement();\n            conn = new DruidStatementConnection(rawConn, stmt);\n        } else {\n            FilterChainImpl filterChain = createChain();\n            conn = filterChain.connection_connect(info);\n            recycleFilterChain(filterChain);\n        }\n\n        createCountUpdater.incrementAndGet(this);\n\n        return conn;\n    }\n\n    public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {\n        String url = this.getUrl();\n        Properties connectProperties = getConnectProperties();\n\n        String user;\n        if (getUserCallback() != null) {\n            user = getUserCallback().getName();\n        } else {\n            user = getUsername();\n        }\n\n        String password = getPassword();\n        PasswordCallback passwordCallback = getPasswordCallback();\n\n        if (passwordCallback != null) {\n            if (passwordCallback instanceof DruidPasswordCallback) {\n                DruidPasswordCallback druidPasswordCallback = (DruidPasswordCallback) passwordCallback;\n\n                druidPasswordCallback.setUrl(url);\n                druidPasswordCallback.setProperties(connectProperties);\n            }\n\n            char[] chars = passwordCallback.getPassword();\n            if (chars != null) {\n                password = new String(chars);\n            }\n        }\n\n        Properties physicalConnectProperties = new Properties();\n        if (connectProperties != null) {\n            physicalConnectProperties.putAll(connectProperties);\n        }\n\n        if (user != null && user.length() != 0) {\n            physicalConnectProperties.put(\"user\", user);\n        }\n\n        if (password != null && password.length() != 0) {\n            physicalConnectProperties.put(\"password\", password);\n        }\n\n        if (connectTimeout > 0) {\n            if (isMySql) {\n                if (connectTimeoutStr == null) {\n                    connectTimeoutStr = Integer.toString(connectTimeout);\n                }\n                physicalConnectProperties.put(\"connectTimeout\", connectTimeoutStr);\n            } else if (isOracle) {\n                if (connectTimeoutStr == null) {\n                    connectTimeoutStr = Integer.toString(connectTimeout);\n                }\n                physicalConnectProperties.put(\"oracle.net.CONNECT_TIMEOUT\", connectTimeoutStr);\n            } else if (driver != null && POSTGRESQL_DRIVER.equals(driver.getClass().getName())) {\n                // see https://github.com/pgjdbc/pgjdbc/blob/2b90ad04696324d107b65b085df4b1db8f6c162d/README.md\n                if (connectTimeoutStr == null) {\n                    connectTimeoutStr = Long.toString(TimeUnit.MILLISECONDS.toSeconds(connectTimeout));\n                }\n                physicalConnectProperties.put(\"loginTimeout\", connectTimeoutStr);\n                physicalConnectProperties.put(\"connectTimeout\", connectTimeoutStr);\n            } else if (dbTypeName != null && DbType.sqlserver.name().equals(dbTypeName)) {\n                // see https://learn.microsoft.com/en-us/sql/connect/jdbc/setting-the-connection-properties?view=sql-server-ver16\n                if (connectTimeoutStr == null) {\n                    connectTimeoutStr = Long.toString(TimeUnit.MILLISECONDS.toSeconds(connectTimeout));\n                }\n                physicalConnectProperties.put(\"loginTimeout\", connectTimeoutStr);\n            }\n        }\n\n        if (socketTimeout > 0) {\n            if (isOracle) {\n                // https://docs.oracle.com/cd/E21454_01/html/821-2594/cnfg_oracle-env_r.html\n                if (socketTimeoutStr == null) {\n                    socketTimeoutStr = Integer.toString(socketTimeout);\n                }\n                // oracle.jdbc.ReadTimeout for jdbc versions >=10.1.0.5\n                physicalConnectProperties.put(\"oracle.jdbc.ReadTimeout\", socketTimeoutStr);\n                // oracle.net.READ_TIMEOUT for jdbc versions < 10.1.0.5\n                physicalConnectProperties.put(\"oracle.net.READ_TIMEOUT\", socketTimeoutStr);\n            } else if (driver != null && POSTGRESQL_DRIVER.equals(driver.getClass().getName())) {\n                if (socketTimeoutStr == null) {\n                    socketTimeoutStr = Long.toString(TimeUnit.MILLISECONDS.toSeconds(socketTimeout));\n                }\n                physicalConnectProperties.put(\"socketTimeout\", socketTimeoutStr);\n            } else if (dbTypeName != null && DbType.sqlserver.name().equals(dbTypeName)) {\n                // As SQLServer-jdbc-driver 6.1.2 can use this, see https://github.com/microsoft/mssql-jdbc/wiki/SocketTimeout\n                if (socketTimeoutStr == null) {\n                    socketTimeoutStr = Integer.toString(socketTimeout);\n                }\n                physicalConnectProperties.put(\"socketTimeout\", socketTimeoutStr);\n            }\n        }\n\n        Connection conn = null;\n\n        long connectStartNanos = System.nanoTime();\n        long connectedNanos, initedNanos, validatedNanos;\n\n        Map<String, Object> variables = initVariants\n                ? new HashMap<String, Object>()\n                : null;\n        Map<String, Object> globalVariables = initGlobalVariants\n                ? new HashMap<String, Object>()\n                : null;\n\n        createStartNanosUpdater.set(this, connectStartNanos);\n        creatingCountUpdater.incrementAndGet(this);\n        try {\n            conn = createPhysicalConnection(url, physicalConnectProperties);\n            connectedNanos = System.nanoTime();\n\n            if (conn == null) {\n                throw new SQLException(\"connect error, url \" + url + \", driverClass \" + this.driverClass);\n            }\n\n            initPhysicalConnection(conn, variables, globalVariables);\n            initedNanos = System.nanoTime();\n\n            boolean skipSocketTimeout = \"odps\".equals(dbTypeName);\n            if (socketTimeout > 0 && !netTimeoutError && !skipSocketTimeout) {\n                try {\n                    // As SQLServer-jdbc-driver 6.1.7 can use this, see https://github.com/microsoft/mssql-jdbc/wiki/SocketTimeout\n                    conn.setNetworkTimeout(netTimeoutExecutor, socketTimeout); // here is milliseconds defined by JDBC\n                } catch (SQLFeatureNotSupportedException | AbstractMethodError e) {\n                    netTimeoutError = true;\n                } catch (Exception ignored) {\n                    // ignored\n                }\n            }\n\n            // call initSqls after completing socketTimeout setting.\n            if (!initSqls(conn, variables, globalVariables)) {\n                // if no SQL has been executed yet.\n                validateConnection(conn);\n            }\n            validatedNanos = System.nanoTime();\n\n            setFailContinuous(false);\n            setCreateError(null);\n        } catch (SQLException ex) {\n            setCreateError(ex);\n            JdbcUtils.close(conn);\n            throw ex;\n        } catch (RuntimeException ex) {\n            setCreateError(ex);\n            JdbcUtils.close(conn);\n            throw ex;\n        } catch (Error ex) {\n            createErrorCountUpdater.incrementAndGet(this);\n            setCreateError(ex);\n            JdbcUtils.close(conn);\n            throw ex;\n        } finally {\n            long nano = System.nanoTime() - connectStartNanos;\n            createTimespan += nano;\n            creatingCountUpdater.decrementAndGet(this);\n        }\n\n        return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos, variables, globalVariables);\n    }\n\n    protected void setCreateError(Throwable ex) {\n        if (ex == null) {\n            lock.lock();\n            try {\n                if (createError != null) {\n                    createError = null;\n                }\n            } finally {\n                lock.unlock();\n            }\n            return;\n        }\n\n        createErrorCountUpdater.incrementAndGet(this);\n        long now = System.currentTimeMillis();\n        lock.lock();\n        try {\n            createError = ex;\n            lastCreateError = ex;\n            lastCreateErrorTimeMillis = now;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public boolean isFailContinuous() {\n        return failContinuousUpdater.get(this) == 1;\n    }\n\n    protected void setFailContinuous(boolean fail) {\n        if (fail) {\n            failContinuousTimeMillisUpdater.set(this, System.currentTimeMillis());\n        } else {\n            failContinuousTimeMillisUpdater.set(this, 0L);\n        }\n\n        boolean currentState = failContinuousUpdater.get(this) == 1;\n        if (currentState == fail) {\n            return;\n        }\n\n        if (fail) {\n            failContinuousUpdater.set(this, 1);\n            if (LOG.isInfoEnabled()) {\n                LOG.info(\"{dataSource-\" + this.getID() + \"} failContinuous is true\");\n            }\n        } else {\n            failContinuousUpdater.set(this, 0);\n            if (LOG.isInfoEnabled()) {\n                LOG.info(\"{dataSource-\" + this.getID() + \"} failContinuous is false\");\n            }\n        }\n    }\n\n    public void initPhysicalConnection(Connection conn) throws SQLException {\n        initPhysicalConnection(conn, null, null);\n    }\n\n    public void initPhysicalConnection(Connection conn,\n                                       Map<String, Object> variables,\n                                       Map<String, Object> globalVariables) throws SQLException {\n        boolean skipAutoCommit = \"odps\".equals(dbTypeName);\n\n        if ((!skipAutoCommit) && conn.getAutoCommit() != defaultAutoCommit) {\n            conn.setAutoCommit(defaultAutoCommit);\n        }\n\n        if (defaultReadOnly != null) {\n            if (conn.isReadOnly() != defaultReadOnly) {\n                conn.setReadOnly(defaultReadOnly);\n            }\n        }\n\n        if (getDefaultTransactionIsolation() != null) {\n            if (conn.getTransactionIsolation() != getDefaultTransactionIsolation().intValue()) {\n                conn.setTransactionIsolation(getDefaultTransactionIsolation());\n            }\n        }\n\n        if (getDefaultCatalog() != null && getDefaultCatalog().length() != 0) {\n            conn.setCatalog(getDefaultCatalog());\n        }\n    }\n\n    private boolean initSqls(Connection conn,\n            Map<String, Object> variables,\n            Map<String, Object> globalVariables) throws SQLException {\n        boolean checked = false;\n        Collection<String> initSqls = getConnectionInitSqls();\n        if (initSqls.isEmpty()\n                && variables == null\n                && globalVariables == null) {\n            return checked;\n        }\n\n        // using raw connection to skip all filters.\n        Connection rawConn;\n        if (conn instanceof ConnectionProxyImpl) {\n            rawConn = ((ConnectionProxyImpl) conn).getConnectionRaw();\n        } else {\n            rawConn = conn;\n        }\n        Statement stmt = ((DruidStatementConnection) rawConn).getStatement();\n        for (String sql : initSqls) {\n            if (StringUtils.isEmpty(sql)) {\n                continue;\n            }\n\n            stmt.execute(sql);\n            checked = true;\n        }\n\n        DbType dbType = DbType.of(this.dbTypeName);\n        if (JdbcUtils.isMysqlDbType(dbType)) {\n            if (variables != null) {\n                ResultSet rs = null;\n                try {\n                    rs = stmt.executeQuery(\"show variables\");\n                    while (rs.next()) {\n                        String name = rs.getString(1);\n                        Object value = rs.getObject(2);\n                        variables.put(name, value);\n                    }\n                } finally {\n                    JdbcUtils.close(rs);\n                }\n                checked = true;\n            }\n\n            if (globalVariables != null) {\n                ResultSet rs = null;\n                try {\n                    rs = stmt.executeQuery(\"show global variables\");\n                    while (rs.next()) {\n                        String name = rs.getString(1);\n                        Object value = rs.getObject(2);\n                        globalVariables.put(name, value);\n                    }\n                } finally {\n                    JdbcUtils.close(rs);\n                }\n                checked = true;\n            }\n        }\n\n        return checked;\n    }\n\n    public abstract int getActivePeak();\n\n    @Override\n    public CompositeDataSupport getCompositeData() throws JMException {\n        Map<String, Object> map = new HashMap<String, Object>();\n        map.put(\"ID\", getID());\n        map.put(\"URL\", this.getUrl());\n        map.put(\"Name\", this.getName());\n        map.put(\"FilterClasses\", getFilterClasses());\n        map.put(\"CreatedTime\", getCreatedTime());\n\n        map.put(\"RawDriverClassName\", getDriverClassName());\n        map.put(\"RawUrl\", getUrl());\n        map.put(\"RawDriverMajorVersion\", getRawDriverMajorVersion());\n        map.put(\"RawDriverMinorVersion\", getRawDriverMinorVersion());\n        map.put(\"Properties\", getProperties());\n\n        // 0 - 4\n        map.put(\"ConnectionActiveCount\", (long) getActiveCount());\n        map.put(\"ConnectionActiveCountMax\", getActivePeak());\n        map.put(\"ConnectionCloseCount\", getCloseCount());\n        map.put(\"ConnectionCommitCount\", getCommitCount());\n        map.put(\"ConnectionRollbackCount\", getRollbackCount());\n\n        // 5 - 9\n        map.put(\"ConnectionConnectErrorCount\", this.getCreateCount());\n        if (createError != null) {\n            map.put(\"ConnectionConnectErrorLastTime\", getLastCreateErrorTime());\n            map.put(\"ConnectionConnectErrorLastMessage\", createError.getMessage());\n            map.put(\"ConnectionConnectErrorLastStackTrace\", Utils.getStackTrace(createError));\n        } else {\n            map.put(\"ConnectionConnectErrorLastTime\", null);\n            map.put(\"ConnectionConnectErrorLastMessage\", null);\n            map.put(\"ConnectionConnectErrorLastStackTrace\", null);\n        }\n\n        // 35 - 39\n        map.put(\"ConnectionConnectCount\", this.getConnectCount());\n        if (createError != null) {\n            map.put(\"ConnectionErrorLastMessage\", createError.getMessage());\n            map.put(\"ConnectionErrorLastStackTrace\", Utils.getStackTrace(createError));\n        } else {\n            map.put(\"ConnectionErrorLastMessage\", null);\n            map.put(\"ConnectionErrorLastStackTrace\", null);\n        }\n\n        fillStatDataToMap(getDataSourceStat(), map);\n        return new CompositeDataSupport(JdbcStatManager.getDataSourceCompositeType(), map);\n    }\n\n    public static void fillStatDataToMap(final JdbcDataSourceStat stat, final Map<String, Object> map) {\n        map.put(\"ConnectionConnectLastTime\", stat.getConnectionStat().getConnectLastTime());\n        // 10 - 14\n        map.put(\"StatementCreateCount\", stat.getStatementStat().getCreateCount());\n        map.put(\"StatementPrepareCount\", stat.getStatementStat().getPrepareCount());\n        map.put(\"StatementPreCallCount\", stat.getStatementStat().getPrepareCallCount());\n        map.put(\"StatementExecuteCount\", stat.getStatementStat().getExecuteCount());\n        map.put(\"StatementRunningCount\", stat.getStatementStat().getRunningCount());\n\n        // 15 - 19\n        map.put(\"StatementConcurrentMax\", stat.getStatementStat().getConcurrentMax());\n        map.put(\"StatementCloseCount\", stat.getStatementStat().getCloseCount());\n        map.put(\"StatementErrorCount\", stat.getStatementStat().getErrorCount());\n        map.put(\"StatementLastErrorTime\", null);\n        map.put(\"StatementLastErrorMessage\", null);\n\n        // 20 - 24\n        map.put(\"StatementLastErrorStackTrace\", null);\n        map.put(\"StatementExecuteMillisTotal\", stat.getStatementStat().getMillisTotal());\n        map.put(\"StatementExecuteLastTime\", stat.getStatementStat().getExecuteLastTime());\n        map.put(\"ConnectionConnectingCount\", stat.getConnectionStat().getConnectingCount());\n        map.put(\"ResultSetCloseCount\", stat.getResultSetStat().getCloseCount());\n\n        // 25 - 29\n        map.put(\"ResultSetOpenCount\", stat.getResultSetStat().getOpenCount());\n        map.put(\"ResultSetOpenningCount\", stat.getResultSetStat().getOpeningCount());\n        map.put(\"ResultSetOpenningMax\", stat.getResultSetStat().getOpeningMax());\n        map.put(\"ResultSetFetchRowCount\", stat.getResultSetStat().getFetchRowCount());\n        map.put(\"ResultSetLastOpenTime\", stat.getResultSetStat().getLastOpenTime());\n\n        // 30 - 34\n        map.put(\"ResultSetErrorCount\", stat.getResultSetStat().getErrorCount());\n        map.put(\"ResultSetOpenningMillisTotal\", stat.getResultSetStat().getAliveMillisTotal());\n        map.put(\"ResultSetLastErrorTime\", stat.getResultSetStat().getLastErrorTime());\n        map.put(\"ResultSetLastErrorMessage\", null);\n        map.put(\"ResultSetLastErrorStackTrace\", null);\n\n        map.put(\"ConnectionConnectMillisTotal\", stat.getConnectionStat().getConnectMillis());\n        map.put(\"ConnectionConnectingCountMax\", stat.getConnectionStat().getConnectingMax());\n\n        // 40 - 44\n        map.put(\"ConnectionConnectMillisMax\", stat.getConnectionStat().getConnectMillisMax());\n        map.put(\"ConnectionErrorLastTime\", stat.getConnectionStat().getErrorLastTime());\n        map.put(\"ConnectionAliveMillisMax\", stat.getConnectionConnectAliveMillisMax());\n        map.put(\"ConnectionAliveMillisMin\", stat.getConnectionConnectAliveMillisMin());\n\n        map.put(\"ConnectionHistogram\", stat.getConnectionHistogramValues());\n        map.put(\"StatementHistogram\", stat.getStatementStat().getHistogramValues());\n    }\n\n    public long getID() {\n        return this.id;\n    }\n\n    @Override\n    public long getDataSourceId() {\n        return getID();\n    }\n    public java.util.Date getCreatedTime() {\n        return createdTime;\n    }\n\n    public abstract int getRawDriverMajorVersion();\n\n    public abstract int getRawDriverMinorVersion();\n\n    public abstract String getProperties();\n\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public void closePreapredStatement(PreparedStatementHolder stmtHolder) {\n        if (stmtHolder == null) {\n            return;\n        }\n        closedPreparedStatementCountUpdater.incrementAndGet(this);\n        decrementCachedPreparedStatementCount();\n        incrementCachedPreparedStatementDeleteCount();\n\n        JdbcUtils.close(stmtHolder.statement);\n    }\n\n    protected void cloneTo(DruidAbstractDataSource to) {\n        to.defaultAutoCommit = this.defaultAutoCommit;\n        to.defaultReadOnly = this.defaultReadOnly;\n        to.defaultTransactionIsolation = this.defaultTransactionIsolation;\n        to.defaultCatalog = this.defaultCatalog;\n        to.name = this.name;\n        to.username = this.username;\n        to.password = this.password;\n        to.jdbcUrl = this.jdbcUrl;\n        to.driverClass = this.driverClass;\n        to.connectProperties = this.connectProperties;\n        to.passwordCallback = this.passwordCallback;\n        to.userCallback = this.userCallback;\n        to.initialSize = this.initialSize;\n        to.maxActive = this.maxActive;\n        to.minIdle = this.minIdle;\n        to.maxIdle = this.maxIdle;\n        to.maxWait = this.maxWait;\n        to.validationQuery = this.validationQuery;\n        to.validationQueryTimeout = this.validationQueryTimeout;\n        to.testOnBorrow = this.testOnBorrow;\n        to.testOnReturn = this.testOnReturn;\n        to.testWhileIdle = this.testWhileIdle;\n        to.poolPreparedStatements = this.poolPreparedStatements;\n        to.sharePreparedStatements = this.sharePreparedStatements;\n        to.maxPoolPreparedStatementPerConnectionSize = this.maxPoolPreparedStatementPerConnectionSize;\n        to.logWriter = this.logWriter;\n        if (this.filters != null) {\n            to.filters = new ArrayList<>(this.filters);\n        }\n        to.exceptionSorter = this.exceptionSorter;\n        to.driver = this.driver;\n        to.queryTimeout = this.queryTimeout;\n        to.transactionQueryTimeout = this.transactionQueryTimeout;\n        to.accessToUnderlyingConnectionAllowed = this.accessToUnderlyingConnectionAllowed;\n        to.timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;\n        to.numTestsPerEvictionRun = this.numTestsPerEvictionRun;\n        to.minEvictableIdleTimeMillis = this.minEvictableIdleTimeMillis;\n        to.removeAbandoned = this.removeAbandoned;\n        to.removeAbandonedTimeoutMillis = this.removeAbandonedTimeoutMillis;\n        to.logAbandoned = this.logAbandoned;\n        to.maxOpenPreparedStatements = this.maxOpenPreparedStatements;\n        if (connectionInitSqls != null) {\n            to.connectionInitSqls = new ArrayList<String>(this.connectionInitSqls);\n        }\n        to.dbTypeName = this.dbTypeName;\n        to.timeBetweenConnectErrorMillis = this.timeBetweenConnectErrorMillis;\n        to.validConnectionChecker = this.validConnectionChecker;\n        to.connectionErrorRetryAttempts = this.connectionErrorRetryAttempts;\n        to.breakAfterAcquireFailure = this.breakAfterAcquireFailure;\n        to.transactionThresholdMillis = this.transactionThresholdMillis;\n        to.dupCloseLogEnable = this.dupCloseLogEnable;\n        to.isOracle = this.isOracle;\n        to.useOracleImplicitCache = this.useOracleImplicitCache;\n        to.asyncCloseConnectionEnable = this.asyncCloseConnectionEnable;\n        to.createScheduler = this.createScheduler;\n        to.destroyScheduler = this.destroyScheduler;\n        to.socketTimeout = this.socketTimeout;\n        to.connectTimeout = this.connectTimeout;\n        to.socketTimeoutStr = this.socketTimeoutStr;\n        to.connectTimeoutStr = this.connectTimeoutStr;\n    }\n\n    /**\n     * @param realConnection\n     * @return true if new connection has been requested during the execution.\n     */\n    public abstract boolean discardConnection(Connection realConnection);\n\n    public boolean discardConnection(DruidConnectionHolder holder) {\n        return discardConnection(holder.getConnection());\n    }\n\n    public boolean isAsyncCloseConnectionEnable() {\n        if (isRemoveAbandoned()) {\n            return true;\n        }\n        return asyncCloseConnectionEnable;\n    }\n\n    public void setAsyncCloseConnectionEnable(boolean asyncCloseConnectionEnable) {\n        this.asyncCloseConnectionEnable = asyncCloseConnectionEnable;\n    }\n\n    public ScheduledExecutorService getCreateScheduler() {\n        return createScheduler;\n    }\n\n    public void setCreateScheduler(ScheduledExecutorService createScheduler) {\n        if (isInited()) {\n            throw new DruidRuntimeException(\"dataSource inited.\");\n        }\n        this.createScheduler = createScheduler;\n    }\n\n    public ScheduledExecutorService getDestroyScheduler() {\n        return destroyScheduler;\n    }\n\n    public void setDestroyScheduler(ScheduledExecutorService destroyScheduler) {\n        if (isInited()) {\n            throw new DruidRuntimeException(\"dataSource inited.\");\n        }\n        this.destroyScheduler = destroyScheduler;\n    }\n\n    public boolean isInited() {\n        return this.inited;\n    }\n\n    public int getMaxCreateTaskCount() {\n        return maxCreateTaskCount;\n    }\n\n    public void setMaxCreateTaskCount(int maxCreateTaskCount) {\n        if (maxCreateTaskCount < 1) {\n            throw new IllegalArgumentException();\n        }\n\n        this.maxCreateTaskCount = maxCreateTaskCount;\n    }\n\n    public boolean isFailFast() {\n        return failFast;\n    }\n\n    public void setFailFast(boolean failFast) {\n        this.failFast = failFast;\n    }\n\n    public int getOnFatalErrorMaxActive() {\n        return onFatalErrorMaxActive;\n    }\n\n    public void setOnFatalErrorMaxActive(int onFatalErrorMaxActive) {\n        this.onFatalErrorMaxActive = onFatalErrorMaxActive;\n    }\n\n    public boolean isOnFatalError() {\n        return onFatalError;\n    }\n\n    /**\n     * @since 1.1.11\n     */\n    public boolean isInitExceptionThrow() {\n        return initExceptionThrow;\n    }\n\n    /**\n     * @since 1.1.11\n     */\n    public void setInitExceptionThrow(boolean initExceptionThrow) {\n        this.initExceptionThrow = initExceptionThrow;\n    }\n\n    public static class PhysicalConnectionInfo {\n        private Connection connection;\n        private long connectStartNanos;\n        private long connectedNanos;\n        private long initedNanos;\n        private long validatedNanos;\n        private Map<String, Object> vairiables;\n        private Map<String, Object> globalVairiables;\n\n        long createTaskId;\n\n        public PhysicalConnectionInfo(\n                Connection connection,\n                long connectStartNanos,\n                long connectedNanos,\n                long initedNanos,\n                long validatedNanos\n        ) {\n            this(connection, connectStartNanos, connectedNanos, initedNanos, validatedNanos, null, null);\n        }\n\n        public PhysicalConnectionInfo(\n                Connection connection,\n                long connectStartNanos,\n                long connectedNanos,\n                long initedNanos,\n                long validatedNanos,\n                Map<String, Object> vairiables,\n                Map<String, Object> globalVairiables\n        ) {\n            this.connection = connection;\n\n            this.connectStartNanos = connectStartNanos;\n            this.connectedNanos = connectedNanos;\n            this.initedNanos = initedNanos;\n            this.validatedNanos = validatedNanos;\n            this.vairiables = vairiables;\n            this.globalVairiables = globalVairiables;\n        }\n\n        public Connection getPhysicalConnection() {\n            return connection;\n        }\n\n        public long getConnectStartNanos() {\n            return connectStartNanos;\n        }\n\n        public long getConnectedNanos() {\n            return connectedNanos;\n        }\n\n        public long getInitedNanos() {\n            return initedNanos;\n        }\n\n        public long getValidatedNanos() {\n            return validatedNanos;\n        }\n\n        public long getConnectNanoSpan() {\n            return connectedNanos - connectStartNanos;\n        }\n\n        public Map<String, Object> getVairiables() {\n            return vairiables;\n        }\n\n        public Map<String, Object> getGlobalVairiables() {\n            return globalVairiables;\n        }\n    }\n\n    class SynchronousExecutor implements Executor {\n        @Override\n        public void execute(Runnable command) {\n            try {\n                command.run();\n            } catch (AbstractMethodError error) {\n                netTimeoutError = true;\n            } catch (Exception ignored) {\n                if (LOG.isDebugEnabled()) {\n                    LOG.debug(\"failed to execute command \" + command);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSourceMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.util.Date;\nimport java.util.List;\n\npublic interface DruidAbstractDataSourceMBean {\n    int getLoginTimeout();\n\n    String getDbType();\n\n    String getName();\n\n    int getInitialSize();\n\n    String getUsername();\n\n    String getUrl();\n\n    String getDriverClassName();\n\n    long getConnectCount();\n\n    long getCloseCount();\n\n    long getConnectErrorCount();\n\n    int getPoolingCount();\n\n    long getRecycleCount();\n\n    int getActiveCount();\n\n    long getCreateCount();\n\n    long getDestroyCount();\n\n    long getCreateTimespanMillis();\n\n    long getCommitCount();\n\n    long getRollbackCount();\n\n    long getStartTransactionCount();\n\n    int getQueryTimeout();\n\n    int getTransactionQueryTimeout();\n\n    String getValidationQuery();\n\n    int getValidationQueryTimeout();\n\n    int getMaxWaitThreadCount();\n\n    long getTimeBetweenEvictionRunsMillis();\n\n    long getMinEvictableIdleTimeMillis();\n\n    boolean isRemoveAbandoned();\n\n    long getRemoveAbandonedTimeoutMillis();\n\n    List<String> getActiveConnectionStackTrace();\n\n    List<String> getFilterClassNames();\n\n    boolean isTestOnBorrow();\n\n    void setTestOnBorrow(boolean testOnBorrow);\n\n    boolean isTestOnReturn();\n\n    boolean isTestWhileIdle();\n\n    void setTestWhileIdle(boolean testWhileIdle);\n\n    boolean isDefaultAutoCommit();\n\n    Boolean getDefaultReadOnly();\n\n    Integer getDefaultTransactionIsolation();\n\n    String getDefaultCatalog();\n\n    boolean isPoolPreparedStatements();\n\n    boolean isSharePreparedStatements();\n\n    long getMaxWait();\n\n    int getMinIdle();\n\n    int getMaxIdle();\n\n    long getCreateErrorCount();\n\n    int getMaxActive();\n\n    void setMaxActive(int maxActive);\n\n    long getTimeBetweenConnectErrorMillis();\n\n    int getMaxOpenPreparedStatements();\n\n    long getRemoveAbandonedCount();\n\n    boolean isLogAbandoned();\n\n    void setLogAbandoned(boolean logAbandoned);\n\n    long getDupCloseCount();\n\n    boolean isBreakAfterAcquireFailure();\n\n    int getConnectionErrorRetryAttempts();\n\n    int getMaxPoolPreparedStatementPerConnectionSize();\n\n    void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize);\n\n    String getProperties();\n\n    int getRawDriverMinorVersion();\n\n    int getRawDriverMajorVersion();\n\n    Date getCreatedTime();\n\n    String getValidConnectionCheckerClassName();\n\n    long[] getTransactionHistogramValues();\n\n    void setTransactionThresholdMillis(long transactionThresholdMillis);\n\n    long getTransactionThresholdMillis();\n\n    long getPreparedStatementCount();\n\n    long getClosedPreparedStatementCount();\n\n    long getCachedPreparedStatementCount();\n\n    long getCachedPreparedStatementDeleteCount();\n\n    long getCachedPreparedStatementAccessCount();\n\n    long getCachedPreparedStatementMissCount();\n\n    long getCachedPreparedStatementHitCount();\n\n    boolean isUseOracleImplicitCache();\n\n    void setUseOracleImplicitCache(boolean useOracleImplicitCache);\n\n    int getDriverMajorVersion();\n\n    int getDriverMinorVersion();\n\n    String getExceptionSorterClassName();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.pool.DruidAbstractDataSource.PhysicalConnectionInfo;\nimport com.alibaba.druid.proxy.jdbc.WrapperProxy;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.StatementEventListener;\n\nimport java.lang.reflect.Field;\nimport java.net.Socket;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.sql.Statement;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic final class DruidConnectionHolder {\n    private static final Log LOG = LogFactory.getLog(DruidConnectionHolder.class);\n\n    static volatile boolean ORACLE_SOCKET_FIELD_ERROR;\n    static volatile Field ORACLE_FIELD_NET;\n    static volatile Field ORACLE_FIELD_S_ATTS;\n    static volatile Field ORACLE_FIELD_NT;\n    static volatile Field ORACLE_FIELD_SOCKET;\n\n    public static boolean holdabilityUnsupported;\n\n    protected final DruidAbstractDataSource dataSource;\n    protected final long connectionId;\n    protected final Connection conn;\n    protected final List<ConnectionEventListener> connectionEventListeners = new CopyOnWriteArrayList<ConnectionEventListener>();\n    protected final List<StatementEventListener> statementEventListeners = new CopyOnWriteArrayList<StatementEventListener>();\n    protected final long connectTimeMillis;\n    protected volatile long lastActiveTimeMillis;\n    protected volatile long lastExecTimeMillis;\n    protected volatile long lastKeepTimeMillis;\n    protected volatile long lastValidTimeMillis;\n    protected long useCount;\n    private long keepAliveCheckCount;\n    private long lastNotEmptyWaitNanos;\n    private final long createNanoSpan;\n    protected PreparedStatementPool statementPool;\n    protected final List<Statement> statementTrace = new ArrayList<Statement>(2);\n    protected final boolean defaultReadOnly;\n    protected final int defaultHoldability;\n    protected final int defaultTransactionIsolation;\n    protected final boolean defaultAutoCommit;\n    protected boolean underlyingReadOnly;\n    protected int underlyingHoldability;\n    protected int underlyingTransactionIsolation;\n    protected boolean underlyingAutoCommit;\n    protected volatile boolean discard;\n    protected volatile boolean active;\n    protected final Map<String, Object> variables;\n    protected final Map<String, Object> globalVariables;\n    final ReentrantLock lock = new ReentrantLock();\n    protected String initSchema;\n    protected Socket socket;\n    protected final long userPasswordVersion;\n\n    volatile FilterChainImpl filterChain;\n\n    public DruidConnectionHolder(DruidAbstractDataSource dataSource, PhysicalConnectionInfo pyConnectInfo)\n            throws SQLException {\n        this(\n                dataSource,\n                pyConnectInfo.getPhysicalConnection(),\n                pyConnectInfo.getConnectNanoSpan(),\n                pyConnectInfo.getVairiables(),\n                pyConnectInfo.getGlobalVairiables()\n        );\n    }\n\n    public DruidConnectionHolder(DruidAbstractDataSource dataSource, Connection conn, long connectNanoSpan)\n            throws SQLException {\n        this(dataSource, conn, connectNanoSpan, null, null);\n    }\n\n    public DruidConnectionHolder(\n            DruidAbstractDataSource dataSource,\n            Connection conn,\n            long connectNanoSpan,\n            Map<String, Object> variables,\n            Map<String, Object> globalVariables\n    ) throws SQLException {\n        this.dataSource = dataSource;\n        this.conn = conn;\n        this.createNanoSpan = connectNanoSpan;\n        this.variables = variables;\n        this.globalVariables = globalVariables;\n        this.userPasswordVersion = dataSource.getUserPasswordVersion();\n\n        this.connectTimeMillis = System.currentTimeMillis();\n        this.lastActiveTimeMillis = connectTimeMillis;\n        this.lastExecTimeMillis = connectTimeMillis;\n\n        this.underlyingAutoCommit = conn.getAutoCommit();\n\n        if (conn instanceof WrapperProxy) {\n            this.connectionId = ((WrapperProxy) conn).getId();\n        } else {\n            this.connectionId = dataSource.createConnectionId();\n        }\n\n        Class<? extends Connection> conClass = conn.getClass();\n        String connClassName = conClass.getName();\n        if ((!ORACLE_SOCKET_FIELD_ERROR) && connClassName.equals(\"oracle.jdbc.driver.T4CConnection\")) {\n            try {\n                if (ORACLE_FIELD_NET == null) {\n                    Field field = conClass.getDeclaredField(\"net\");\n                    field.setAccessible(true);\n                    ORACLE_FIELD_NET = field;\n                }\n                Object net = ORACLE_FIELD_NET.get(conn);\n\n                if (ORACLE_FIELD_S_ATTS == null) {\n                    // NSProtocol\n                    Field field = net.getClass().getSuperclass().getDeclaredField(\"sAtts\");\n                    field.setAccessible(true);\n                    ORACLE_FIELD_S_ATTS = field;\n                }\n\n                Object sAtts = ORACLE_FIELD_S_ATTS.get(net);\n\n                if (ORACLE_FIELD_NT == null) {\n                    Field field = sAtts.getClass().getDeclaredField(\"nt\");\n                    field.setAccessible(true);\n                    ORACLE_FIELD_NT = field;\n                }\n\n                Object nt = ORACLE_FIELD_NT.get(sAtts);\n\n                if (ORACLE_FIELD_SOCKET == null) {\n                    Field field = nt.getClass().getDeclaredField(\"socket\");\n                    field.setAccessible(true);\n                    ORACLE_FIELD_SOCKET = field;\n                }\n\n                socket = (Socket) ORACLE_FIELD_SOCKET.get(nt);\n            } catch (Throwable ignored) {\n                ORACLE_SOCKET_FIELD_ERROR = true;\n                // ignored\n            }\n        }\n\n        {\n            boolean initUnderlyHoldability = !holdabilityUnsupported;\n            DbType dbType = DbType.of(dataSource.dbTypeName);\n            if (dbType == DbType.sybase //\n                    || dbType == DbType.db2 //\n                    || dbType == DbType.hive //\n                    || dbType == DbType.odps //\n                    || dbType == DbType.duckdb //\n            ) {\n                initUnderlyHoldability = false;\n            }\n            if (initUnderlyHoldability) {\n                try {\n                    this.underlyingHoldability = conn.getHoldability();\n                } catch (UnsupportedOperationException e) {\n                    holdabilityUnsupported = true;\n                    LOG.warn(\"getHoldability unsupported\", e);\n                } catch (SQLFeatureNotSupportedException e) {\n                    holdabilityUnsupported = true;\n                    LOG.warn(\"getHoldability unsupported\", e);\n                } catch (SQLException e) {\n                    // bug fixed for hive jdbc-driver\n                    if (\"Method not supported\".equals(e.getMessage())) {\n                        holdabilityUnsupported = true;\n                    }\n                    LOG.warn(\"getHoldability error\", e);\n                }\n            }\n        }\n\n        this.underlyingReadOnly = conn.isReadOnly();\n        try {\n            this.underlyingTransactionIsolation = conn.getTransactionIsolation();\n        } catch (SQLException e) {\n            // compartible for alibaba corba\n            if (\"HY000\".equals(e.getSQLState())\n                    || \"com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException\".equals(e.getClass().getName())) {\n                // skip\n            } else {\n                throw e;\n            }\n        }\n\n        this.defaultHoldability = underlyingHoldability;\n        this.defaultTransactionIsolation = underlyingTransactionIsolation;\n        this.defaultAutoCommit = underlyingAutoCommit;\n        this.defaultReadOnly = underlyingReadOnly;\n    }\n\n    protected FilterChainImpl createChain() {\n        FilterChainImpl chain = this.filterChain;\n        if (chain == null) {\n            chain = new FilterChainImpl(dataSource);\n        } else {\n            this.filterChain = null;\n        }\n\n        return chain;\n    }\n\n    protected void recycleFilterChain(FilterChainImpl chain) {\n        chain.reset();\n        this.filterChain = chain;\n    }\n\n    public long getConnectTimeMillis() {\n        return connectTimeMillis;\n    }\n\n    public boolean isUnderlyingReadOnly() {\n        return underlyingReadOnly;\n    }\n\n    public void setUnderlyingReadOnly(boolean underlyingReadOnly) {\n        this.underlyingReadOnly = underlyingReadOnly;\n    }\n\n    public int getUnderlyingHoldability() {\n        return underlyingHoldability;\n    }\n\n    public void setUnderlyingHoldability(int underlyingHoldability) {\n        this.underlyingHoldability = underlyingHoldability;\n    }\n\n    public int getUnderlyingTransactionIsolation() {\n        return underlyingTransactionIsolation;\n    }\n\n    public void setUnderlyingTransactionIsolation(int underlyingTransactionIsolation) {\n        this.underlyingTransactionIsolation = underlyingTransactionIsolation;\n    }\n\n    public boolean isUnderlyingAutoCommit() {\n        return underlyingAutoCommit;\n    }\n\n    public void setUnderlyingAutoCommit(boolean underlyingAutoCommit) {\n        this.underlyingAutoCommit = underlyingAutoCommit;\n    }\n\n    public long getLastActiveTimeMillis() {\n        return lastActiveTimeMillis;\n    }\n\n    public void setLastActiveTimeMillis(long lastActiveMillis) {\n        this.lastActiveTimeMillis = lastActiveMillis;\n    }\n\n    public long getLastExecTimeMillis() {\n        return lastExecTimeMillis;\n    }\n\n    public void setLastExecTimeMillis(long lastExecTimeMillis) {\n        this.lastExecTimeMillis = lastExecTimeMillis;\n    }\n\n    public void addTrace(DruidPooledStatement stmt) {\n        lock.lock();\n        try {\n            statementTrace.add(stmt);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void removeTrace(DruidPooledStatement stmt) {\n        lock.lock();\n        try {\n            statementTrace.remove(stmt);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public List<ConnectionEventListener> getConnectionEventListeners() {\n        return connectionEventListeners;\n    }\n\n    public List<StatementEventListener> getStatementEventListeners() {\n        return statementEventListeners;\n    }\n\n    public PreparedStatementPool getStatementPool() {\n        if (statementPool == null) {\n            statementPool = new PreparedStatementPool(this);\n        }\n        return statementPool;\n    }\n\n    public PreparedStatementPool getStatementPoolDirect() {\n        return statementPool;\n    }\n\n    public void clearStatementCache() {\n        if (this.statementPool == null) {\n            return;\n        }\n        this.statementPool.clear();\n    }\n\n    public DruidAbstractDataSource getDataSource() {\n        return dataSource;\n    }\n\n    public boolean isPoolPreparedStatements() {\n        return dataSource.isPoolPreparedStatements();\n    }\n\n    public Connection getConnection() {\n        return conn;\n    }\n\n    public long getTimeMillis() {\n        return connectTimeMillis;\n    }\n\n    public long getUseCount() {\n        return useCount;\n    }\n\n    public long getConnectionId() {\n        return connectionId;\n    }\n\n    public void incrementUseCount() {\n        useCount++;\n    }\n\n    public long getKeepAliveCheckCount() {\n        return keepAliveCheckCount;\n    }\n\n    public void incrementKeepAliveCheckCount() {\n        keepAliveCheckCount++;\n    }\n\n    public void reset() throws SQLException {\n        // reset default settings\n        if (underlyingReadOnly != defaultReadOnly) {\n            conn.setReadOnly(defaultReadOnly);\n            underlyingReadOnly = defaultReadOnly;\n        }\n\n        if (underlyingHoldability != defaultHoldability) {\n            conn.setHoldability(defaultHoldability);\n            underlyingHoldability = defaultHoldability;\n        }\n\n        if (!dataSource.isKeepConnectionUnderlyingTransactionIsolation()\n                && underlyingTransactionIsolation != defaultTransactionIsolation) {\n            conn.setTransactionIsolation(defaultTransactionIsolation);\n            underlyingTransactionIsolation = defaultTransactionIsolation;\n        }\n\n        if (underlyingAutoCommit != defaultAutoCommit) {\n            conn.setAutoCommit(defaultAutoCommit);\n            underlyingAutoCommit = defaultAutoCommit;\n        }\n\n        if (!connectionEventListeners.isEmpty()) {\n            connectionEventListeners.clear();\n        }\n        if (!statementEventListeners.isEmpty()) {\n            statementEventListeners.clear();\n        }\n\n        lock.lock();\n        try {\n            if (!statementTrace.isEmpty()) {\n                Object[] items = statementTrace.toArray();\n                for (int i = 0; i < items.length; i++) {\n                    Object item = items[i];\n                    Statement stmt = (Statement) item;\n                    JdbcUtils.close(stmt);\n                }\n\n                statementTrace.clear();\n            }\n        } finally {\n            lock.unlock();\n        }\n\n        conn.clearWarnings();\n    }\n\n    public boolean isDiscard() {\n        return discard;\n    }\n\n    public void setDiscard(boolean discard) {\n        this.discard = discard;\n    }\n\n    public long getCreateNanoSpan() {\n        return createNanoSpan;\n    }\n\n    public long getLastNotEmptyWaitNanos() {\n        return lastNotEmptyWaitNanos;\n    }\n\n    protected void setLastNotEmptyWaitNanos(long lastNotEmptyWaitNanos) {\n        this.lastNotEmptyWaitNanos = lastNotEmptyWaitNanos;\n    }\n\n    public String toString() {\n        StringBuilder buf = new StringBuilder();\n\n        buf.append(\"{ID:\");\n        buf.append(System.identityHashCode(conn));\n        buf.append(\", ConnectTime:\\\"\");\n        buf.append(Utils.toString(new Date(this.connectTimeMillis)));\n\n        buf.append(\"\\\", UseCount:\");\n        buf.append(useCount);\n\n        if (lastActiveTimeMillis > 0) {\n            buf.append(\", LastActiveTime:\\\"\");\n            buf.append(Utils.toString(new Date(lastActiveTimeMillis)));\n            buf.append(\"\\\"\");\n        }\n\n        if (lastKeepTimeMillis > 0) {\n            buf.append(\", LastKeepTimeMillis:\\\"\");\n            buf.append(Utils.toString(new Date(lastKeepTimeMillis)));\n            buf.append(\"\\\"\");\n        }\n\n        if (statementPool != null && statementPool.getMap().size() > 0) {\n            buf.append(\"\\\", CachedStatementCount:\");\n            buf.append(statementPool.getMap().size());\n        }\n\n        buf.append(\"}\");\n\n        return buf.toString();\n    }\n\n    public long getUserPasswordVersion() {\n        return userPasswordVersion;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.DruidRuntimeException;\nimport com.alibaba.druid.TransactionTimeoutException;\nimport com.alibaba.druid.VERSION;\nimport com.alibaba.druid.filter.AutoLoad;\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\nimport com.alibaba.druid.pool.vendor.*;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.TransactionInfo;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.stat.JdbcSqlStatValue;\nimport com.alibaba.druid.support.clickhouse.BalancedClickhouseDriver;\nimport com.alibaba.druid.support.clickhouse.BalancedClickhouseDriverNative;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.*;\nimport com.alibaba.druid.wall.WallFilter;\nimport com.alibaba.druid.wall.WallProviderStatValue;\n\nimport javax.management.JMException;\nimport javax.management.MBeanRegistration;\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\nimport javax.naming.NamingException;\nimport javax.naming.Reference;\nimport javax.naming.Referenceable;\nimport javax.naming.StringRefAddr;\nimport javax.sql.ConnectionEvent;\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.ConnectionPoolDataSource;\nimport javax.sql.PooledConnection;\n\nimport java.io.Closeable;\nimport java.net.Socket;\nimport java.security.AccessController;\nimport java.security.PrivilegedAction;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.sql.Statement;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * @author ljw [ljw2083@alibaba-inc.com]\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSource extends DruidAbstractDataSource\n        implements DruidDataSourceMBean, ManagedDataSource, Referenceable, Closeable, Cloneable, ConnectionPoolDataSource, MBeanRegistration {\n    private static final Log LOG = LogFactory.getLog(DruidDataSource.class);\n    private static final long serialVersionUID = 1L;\n    // stats\n    private volatile long recycleErrorCount;\n    private volatile long discardErrorCount;\n    private volatile Throwable discardErrorLast;\n    private long connectCount;\n    private long closeCount;\n    private volatile long connectErrorCount;\n    private long recycleCount;\n    private long removeAbandonedCount;\n    private long notEmptyWaitCount;\n    private long notEmptySignalCount;\n    private long notEmptyWaitNanos;\n    private int keepAliveCheckCount;\n    private int activePeak;\n    private long activePeakTime;\n    private int poolingPeak;\n    private long poolingPeakTime;\n    private volatile int keepAliveCheckErrorCount;\n    private volatile Throwable keepAliveCheckErrorLast;\n    // store\n    private volatile DruidConnectionHolder[] connections;\n    private int poolingCount;\n    private int activeCount;\n    private volatile int createDirectCount;\n    private volatile long discardCount;\n    private int notEmptyWaitThreadCount;\n    private int notEmptyWaitThreadPeak;\n    //\n    private DruidConnectionHolder[] evictConnections;\n    private DruidConnectionHolder[] keepAliveConnections;\n    // for clean connection old references.\n    private volatile DruidConnectionHolder[] nullConnections;\n\n    // threads\n    private volatile ScheduledFuture<?> destroySchedulerFuture;\n    private DestroyTask destroyTask;\n\n    private final Map<CreateConnectionTask, Future<?>> createSchedulerFutures = new ConcurrentHashMap<>(16);\n    private CreateConnectionThread createConnectionThread;\n    private DestroyConnectionThread destroyConnectionThread;\n    private LogStatsThread logStatsThread;\n    private int createTaskCount;\n\n    private volatile long createTaskIdSeed = 1L;\n    private long[] createTasks;\n\n    private volatile boolean enable = true;\n\n    private boolean resetStatEnable = true;\n    private volatile long resetCount;\n\n    private String initStackTrace;\n\n    private volatile boolean closing;\n    private volatile boolean closed;\n    private long closeTimeMillis = -1L;\n\n    protected JdbcDataSourceStat dataSourceStat;\n\n    private boolean useGlobalDataSourceStat;\n    private boolean mbeanRegistered;\n    private boolean logDifferentThread = true;\n    private volatile boolean keepAlive;\n    private boolean asyncInit;\n    protected boolean killWhenSocketReadTimeout;\n    protected boolean checkExecuteTime;\n\n    private static List<Filter> autoFilters;\n    private boolean loadSpifilterSkip;\n    private volatile DataSourceDisableException disableException;\n\n    protected static final AtomicLongFieldUpdater<DruidDataSource> recycleErrorCountUpdater\n            = AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, \"recycleErrorCount\");\n    protected static final AtomicLongFieldUpdater<DruidDataSource> connectErrorCountUpdater\n            = AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, \"connectErrorCount\");\n    protected static final AtomicLongFieldUpdater<DruidDataSource> resetCountUpdater\n            = AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, \"resetCount\");\n    protected static final AtomicLongFieldUpdater<DruidDataSource> createTaskIdSeedUpdater\n            = AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, \"createTaskIdSeed\");\n    protected static final AtomicLongFieldUpdater<DruidDataSource> discardErrorCountUpdater\n            = AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, \"discardErrorCount\");\n    protected static final AtomicIntegerFieldUpdater<DruidDataSource> keepAliveCheckErrorCountUpdater\n            = AtomicIntegerFieldUpdater.newUpdater(DruidDataSource.class, \"keepAliveCheckErrorCount\");\n    protected static final AtomicIntegerFieldUpdater<DruidDataSource> createDirectCountUpdater\n            = AtomicIntegerFieldUpdater.newUpdater(DruidDataSource.class, \"createDirectCount\");\n\n    public DruidDataSource() {\n        this(false);\n    }\n\n    public DruidDataSource(boolean fairLock) {\n        super(fairLock);\n\n        configFromPropeties(System.getProperties());\n    }\n\n    public boolean isAsyncInit() {\n        return asyncInit;\n    }\n\n    public void setAsyncInit(boolean asyncInit) {\n        this.asyncInit = asyncInit;\n    }\n\n    @Deprecated\n    public void configFromPropety(Properties properties) {\n        configFromPropeties(properties);\n    }\n\n    @Deprecated\n    public void configFromPropeties(Properties properties) {\n        configFromProperties(properties);\n    }\n\n    /**\n     * support config after init\n     */\n    public void configFromProperties(Properties properties) {\n        boolean init;\n        lock.lock();\n        try {\n            init = this.inited;\n        } finally {\n            lock.unlock();\n        }\n        if (init) {\n            configFromPropertiesAfterInit(properties);\n        } else {\n            DruidDataSourceUtils.configFromProperties(this, properties);\n        }\n    }\n\n    private void configFromPropertiesAfterInit(Properties properties) {\n        String url = properties.getProperty(\"druid.url\");\n        if (url != null) {\n            url = url.trim();\n        }\n\n        String username = properties.getProperty(\"druid.username\");\n        if (username != null) {\n            username = username.trim();\n        }\n\n        String password = properties.getProperty(\"druid.password\");\n\n        Properties connectProperties = new Properties();\n\n        final String connectUrl;\n        final boolean urlUserPasswordChanged;\n        lock.lock();\n        try {\n            urlUserPasswordChanged = (url != null && !this.jdbcUrl.equals(url))\n                    || (username != null && !username.equals(this.username))\n                    || (password != null && !password.equals(this.password));\n\n            String connectUser = username != null ? username : this.username;\n            if (username != null) {\n                connectProperties.put(\"user\", connectUser);\n            }\n\n            String connectPassword = password != null ? password : this.password;\n            if (connectPassword != null) {\n                connectProperties.put(\"password\", connectPassword);\n            }\n            connectUrl = url != null ? url : this.jdbcUrl;\n        } finally {\n            lock.unlock();\n        }\n\n        if (urlUserPasswordChanged) {\n            Connection conn = null;\n            try {\n                conn = getDriver().connect(connectUrl, connectProperties);\n                LOG.info(\"check connection info success\");\n                // ignore\n            } catch (SQLException e) {\n                throw new DruidRuntimeException(\"check connection info failed\", e);\n            } finally {\n                JdbcUtils.close(conn);\n            }\n        }\n\n        lock.lock();\n        try {\n            if (urlUserPasswordChanged) {\n                if (url != null && !url.equals(this.jdbcUrl)) {\n                    this.jdbcUrl = url; // direct set url, ignore init check\n                    LOG.info(\"jdbcUrl changed\");\n                }\n\n                if (username != null && !username.equals(this.username)) {\n                    this.username = username; // direct set, ignore init check\n                    LOG.info(\"username changed\");\n                }\n\n                if (password != null && !password.equals(this.password)) {\n                    this.password = password; // direct set, ignore init check\n                    LOG.info(\"password changed\");\n                }\n                incrementUserPasswordVersion();\n            }\n\n            {\n                Integer initialSize = DruidDataSourceUtils.getPropertyInt(properties, \"druid.initialSize\");\n                if (initialSize != null) {\n                    this.initialSize = initialSize;\n                }\n            }\n\n            Integer maxActive = DruidDataSourceUtils.getPropertyInt(properties, \"druid.maxActive\");\n            Integer minIdle = DruidDataSourceUtils.getPropertyInt(properties, \"druid.minIdle\");\n            if (maxActive != null || minIdle != null) {\n                int compareMaxActive = maxActive != null ? maxActive.intValue() : this.maxActive;\n                int compareMinIdle = minIdle != null ? minIdle.intValue() : this.minIdle;\n                if (compareMaxActive < compareMinIdle) {\n                    throw new IllegalArgumentException(\"maxActive less than minIdle, \" + compareMaxActive + \" < \" + compareMinIdle);\n                }\n            }\n            if (maxActive != null) {\n                this.maxActive = maxActive;\n            }\n            if (minIdle != null) {\n                this.minIdle = minIdle;\n            }\n\n            DruidDataSourceUtils.configFromProperties(this, properties);\n        } finally {\n            lock.unlock();\n        }\n\n        int replaceCount = 0;\n        // replace older version urlUserPassword Connection\n        while ((hasOlderVersionUrlUserPasswordConnection())) {\n            try {\n                PhysicalConnectionInfo phyConnInfo = createPhysicalConnection();\n\n                boolean result = false;\n                lock.lock();\n                try {\n                    for (int i = poolingCount - 1; i >= 0; i--) {\n                        if (connections[i].getUserPasswordVersion() < userPasswordVersion) {\n                            connections[i] = new DruidConnectionHolder(DruidDataSource.this, phyConnInfo);\n                            result = true;\n                            replaceCount++;\n                            break;\n                        }\n                    }\n                } finally {\n                    lock.unlock();\n                }\n\n                if (!result) {\n                    JdbcUtils.close(phyConnInfo.getPhysicalConnection());\n                    LOG.info(\"replace older version urlUserPassword failed.\");\n                    break;\n                }\n            } catch (SQLException e) {\n                LOG.error(\"fill init connection error\", e);\n            }\n        }\n\n        if (replaceCount > 0) {\n            LOG.info(\"replace older version urlUserPassword Connection : \" + replaceCount);\n        }\n\n        while ((isLowWaterLevel())) {\n            try {\n                PhysicalConnectionInfo physicalConnection = createPhysicalConnection();\n\n                boolean result = put(physicalConnection);\n                if (!result) {\n                    JdbcUtils.close(physicalConnection.getPhysicalConnection());\n                    LOG.info(\"put physical connection to pool failed.\");\n                }\n            } catch (SQLException e) {\n                LOG.error(\"fill init connection error\", e);\n            }\n        }\n    }\n\n    private boolean hasOlderVersionUrlUserPasswordConnection() {\n        lock.lock();\n        try {\n            long userPasswordVersion = this.userPasswordVersion;\n            for (int i = 0; i < poolingCount; i++) {\n                if (connections[i].getUserPasswordVersion() < userPasswordVersion) {\n                    return true;\n                }\n            }\n        } finally {\n            lock.unlock();\n        }\n        return false;\n    }\n\n    private boolean isLowWaterLevel() {\n        lock.lock();\n        try {\n            return activeCount + poolingCount < minIdle;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public boolean isKillWhenSocketReadTimeout() {\n        return killWhenSocketReadTimeout;\n    }\n\n    public void setKillWhenSocketReadTimeout(boolean killWhenSocketTimeOut) {\n        this.killWhenSocketReadTimeout = killWhenSocketTimeOut;\n    }\n\n    public boolean isUseGlobalDataSourceStat() {\n        return useGlobalDataSourceStat;\n    }\n\n    public void setUseGlobalDataSourceStat(boolean useGlobalDataSourceStat) {\n        this.useGlobalDataSourceStat = useGlobalDataSourceStat;\n    }\n\n    public boolean isKeepAlive() {\n        return keepAlive;\n    }\n\n    public void setKeepAlive(boolean keepAlive) {\n        this.keepAlive = keepAlive;\n    }\n\n    public String getInitStackTrace() {\n        return initStackTrace;\n    }\n\n    public boolean isResetStatEnable() {\n        return resetStatEnable;\n    }\n\n    public void setResetStatEnable(boolean resetStatEnable) {\n        this.resetStatEnable = resetStatEnable;\n        if (dataSourceStat != null) {\n            dataSourceStat.setResetStatEnable(resetStatEnable);\n        }\n    }\n\n    public long getDiscardCount() {\n        return discardCount;\n    }\n\n    public void restart() throws SQLException {\n        this.restart(null);\n    }\n\n    public void restart(Properties properties) throws SQLException {\n        lock.lock();\n        try {\n            if (activeCount > 0) {\n                throw new SQLException(\"can not restart, activeCount not zero. \" + activeCount);\n            }\n            if (LOG.isInfoEnabled()) {\n                LOG.info(\"{dataSource-\" + this.getID() + \"} restart\");\n            }\n\n            this.close();\n            this.resetStat();\n            this.inited = false;\n            this.enable = true;\n            this.closed = false;\n\n            if (properties != null) {\n                DruidDataSourceUtils.configFromProperties(this, properties);\n            }\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void resetStat() {\n        if (!isResetStatEnable()) {\n            return;\n        }\n\n        lock.lock();\n        try {\n            connectCount = 0;\n            closeCount = 0;\n            discardCount = 0;\n            recycleCount = 0;\n            createCount = 0L;\n            directCreateCount = 0;\n            destroyCount = 0L;\n            removeAbandonedCount = 0;\n            notEmptyWaitCount = 0;\n            notEmptySignalCount = 0L;\n            notEmptyWaitNanos = 0;\n\n            activePeak = activeCount;\n            activePeakTime = 0;\n            poolingPeak = 0;\n            createTimespan = 0;\n            lastError = null;\n            lastErrorTimeMillis = 0;\n            lastCreateError = null;\n            lastCreateErrorTimeMillis = 0;\n        } finally {\n            lock.unlock();\n        }\n\n        connectErrorCountUpdater.set(this, 0);\n        errorCountUpdater.set(this, 0);\n        commitCountUpdater.set(this, 0);\n        rollbackCountUpdater.set(this, 0);\n        startTransactionCountUpdater.set(this, 0);\n        cachedPreparedStatementHitCountUpdater.set(this, 0);\n        closedPreparedStatementCountUpdater.set(this, 0);\n        preparedStatementCountUpdater.set(this, 0);\n        transactionHistogram.reset();\n        cachedPreparedStatementDeleteCountUpdater.set(this, 0);\n        recycleErrorCountUpdater.set(this, 0);\n\n        resetCountUpdater.incrementAndGet(this);\n    }\n\n    public long getResetCount() {\n        return this.resetCount;\n    }\n\n    public boolean isEnable() {\n        return enable;\n    }\n\n    public void setEnable(boolean enable) {\n        lock.lock();\n        try {\n            this.enable = enable;\n            if (!enable) {\n                notEmpty.signalAll();\n                notEmptySignalCount++;\n            }\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void setPoolPreparedStatements(boolean value) {\n        setPoolPreparedStatements0(value);\n    }\n\n    private void setPoolPreparedStatements0(boolean value) {\n        if (this.poolPreparedStatements == value) {\n            return;\n        }\n\n        this.poolPreparedStatements = value;\n\n        if (!inited) {\n            return;\n        }\n\n        if (LOG.isInfoEnabled()) {\n            LOG.info(\"set poolPreparedStatements \" + this.poolPreparedStatements + \" -> \" + value);\n        }\n\n        if (!value) {\n            lock.lock();\n            try {\n                for (int i = 0; i < poolingCount; ++i) {\n                    DruidConnectionHolder connection = connections[i];\n\n                    for (PreparedStatementHolder holder : connection.getStatementPool().getMap().values()) {\n                        closePreapredStatement(holder);\n                    }\n\n                    connection.getStatementPool().getMap().clear();\n                }\n            } finally {\n                lock.unlock();\n            }\n        }\n    }\n\n    public void setMaxActive(int maxActive) {\n        if (this.maxActive == maxActive) {\n            return;\n        }\n\n        if (maxActive == 0) {\n            throw new IllegalArgumentException(\"maxActive can't not set zero\");\n        }\n\n        if (!inited) {\n            this.maxActive = maxActive;\n            return;\n        }\n\n        if (maxActive < this.minIdle) {\n            throw new IllegalArgumentException(\"maxActive less than minIdle, \" + maxActive + \" < \" + this.minIdle);\n        }\n\n        if (LOG.isInfoEnabled()) {\n            LOG.info(\"maxActive changed : \" + this.maxActive + \" -> \" + maxActive);\n        }\n\n        lock.lock();\n        try {\n            int allCount = this.poolingCount + this.activeCount;\n\n            if (maxActive > allCount) {\n                this.connections = Arrays.copyOf(this.connections, maxActive);\n                evictConnections = new DruidConnectionHolder[maxActive];\n                keepAliveConnections = new DruidConnectionHolder[maxActive];\n                nullConnections = new DruidConnectionHolder[maxActive];\n            } else {\n                this.connections = Arrays.copyOf(this.connections, allCount);\n                evictConnections = new DruidConnectionHolder[allCount];\n                keepAliveConnections = new DruidConnectionHolder[allCount];\n                nullConnections = new DruidConnectionHolder[allCount];\n            }\n\n            this.maxActive = maxActive;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public void setConnectProperties(Properties properties) {\n        if (properties == null) {\n            properties = new Properties();\n        }\n\n        boolean equals;\n        if (properties.size() == this.connectProperties.size()) {\n            equals = true;\n            for (Map.Entry entry : properties.entrySet()) {\n                if (\n                    !Objects.equals(\n                        this.connectProperties.get(entry.getKey()),\n                        entry.getValue()\n                    )\n                ) {\n                    equals = false;\n                    break;\n                }\n            }\n        } else {\n            equals = false;\n        }\n\n        if (!equals) {\n            if (inited && LOG.isInfoEnabled()) {\n                LOG.info(\"connectProperties changed : \" + this.connectProperties + \" -> \" + properties);\n            }\n\n            configFromPropeties(properties);\n\n            for (Filter filter : this.filters) {\n                filter.configFromProperties(properties);\n            }\n\n            if (exceptionSorter != null) {\n                exceptionSorter.configFromProperties(properties);\n            }\n\n            if (validConnectionChecker != null) {\n                validConnectionChecker.configFromProperties(properties);\n            }\n\n            if (statLogger != null) {\n                statLogger.configFromProperties(properties);\n            }\n        }\n\n        this.connectProperties = properties;\n    }\n\n    public void init() throws SQLException {\n        if (inited) {\n            return;\n        }\n\n        // bug fixed for dead lock, for issue #2980\n        DruidDriver.getInstance();\n\n        final ReentrantLock lock = this.lock;\n        try {\n            lock.lockInterruptibly();\n        } catch (InterruptedException e) {\n            throw new SQLException(\"interrupt\", e);\n        }\n\n        boolean init = false;\n        try {\n            if (inited) {\n                return;\n            }\n\n            initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());\n\n            this.id = DruidDriver.createDataSourceId();\n            if (this.id > 1) {\n                long delta = (this.id - 1) * 100000;\n                connectionIdSeedUpdater.addAndGet(this, delta);\n                statementIdSeedUpdater.addAndGet(this, delta);\n                resultSetIdSeedUpdater.addAndGet(this, delta);\n                transactionIdSeedUpdater.addAndGet(this, delta);\n            }\n\n            if (this.jdbcUrl != null) {\n                this.jdbcUrl = this.jdbcUrl.trim();\n                initFromWrapDriverUrl();\n            }\n            initTimeoutsFromUrlOrProperties();\n\n            for (Filter filter : filters) {\n                filter.init(this);\n            }\n\n            if (this.dbTypeName == null || this.dbTypeName.length() == 0) {\n                this.dbTypeName = JdbcUtils.getDbType(jdbcUrl, null);\n            }\n\n            DbType dbType = DbType.of(this.dbTypeName);\n            if (JdbcUtils.isMysqlDbType(dbType)) {\n                boolean cacheServerConfigurationSet = false;\n                if (this.connectProperties.containsKey(\"cacheServerConfiguration\")) {\n                    cacheServerConfigurationSet = true;\n                } else if (this.jdbcUrl.indexOf(\"cacheServerConfiguration\") != -1) {\n                    cacheServerConfigurationSet = true;\n                }\n                if (cacheServerConfigurationSet) {\n                    this.connectProperties.put(\"cacheServerConfiguration\", \"true\");\n                }\n            }\n\n            if (maxActive <= 0) {\n                throw new IllegalArgumentException(\"illegal maxActive \" + maxActive);\n            }\n\n            if (maxActive < minIdle) {\n                throw new IllegalArgumentException(\"illegal maxActive \" + maxActive);\n            }\n\n            if (getInitialSize() > maxActive) {\n                throw new IllegalArgumentException(\"illegal initialSize \" + this.initialSize + \", maxActive \" + maxActive);\n            }\n\n            if (timeBetweenLogStatsMillis > 0 && useGlobalDataSourceStat) {\n                throw new IllegalArgumentException(\"timeBetweenLogStatsMillis not support useGlobalDataSourceStat=true\");\n            }\n\n            if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {\n                throw new SQLException(\"maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis\");\n            }\n\n            if (keepAlive && keepAliveBetweenTimeMillis <= timeBetweenEvictionRunsMillis) {\n                throw new SQLException(\"keepAliveBetweenTimeMillis must be greater than timeBetweenEvictionRunsMillis\");\n            }\n\n            if (this.driverClass != null) {\n                this.driverClass = driverClass.trim();\n            }\n\n            initFromSPIServiceLoader();\n\n            resolveDriver();\n\n            initCheck();\n\n            this.netTimeoutExecutor = new SynchronousExecutor();\n\n            initExceptionSorter();\n            initValidConnectionChecker();\n            validationQueryCheck();\n\n            if (isUseGlobalDataSourceStat()) {\n                dataSourceStat = JdbcDataSourceStat.getGlobal();\n                if (dataSourceStat == null) {\n                    dataSourceStat = new JdbcDataSourceStat(\"Global\", \"Global\", this.dbTypeName);\n                    JdbcDataSourceStat.setGlobal(dataSourceStat);\n                }\n                if (dataSourceStat.getDbType() == null) {\n                    dataSourceStat.setDbType(this.dbTypeName);\n                }\n            } else {\n                dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbTypeName, this.connectProperties);\n            }\n            dataSourceStat.setResetStatEnable(this.resetStatEnable);\n\n            connections = new DruidConnectionHolder[maxActive];\n            evictConnections = new DruidConnectionHolder[maxActive];\n            keepAliveConnections = new DruidConnectionHolder[maxActive];\n            nullConnections = new DruidConnectionHolder[maxActive];\n\n            SQLException connectError = null;\n\n            if (createScheduler != null && asyncInit) {\n                for (int i = 0; i < initialSize; ++i) {\n                    submitCreateTask(true);\n                }\n            } else if (!asyncInit) {\n                // init connections\n                while (poolingCount < initialSize) {\n                    try {\n                        PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();\n                        DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);\n                        connections[poolingCount++] = holder;\n                    } catch (SQLException ex) {\n                        LOG.error(\"init datasource error, url: \" + this.getUrl(), ex);\n                        if (initExceptionThrow) {\n                            connectError = ex;\n                            break;\n                        } else {\n                            Thread.sleep(3000);\n                        }\n                    }\n                }\n\n                if (poolingCount > 0) {\n                    poolingPeak = poolingCount;\n                    poolingPeakTime = System.currentTimeMillis();\n                }\n            }\n\n            createAndLogThread();\n            createAndStartCreatorThread();\n            createAndStartDestroyThread();\n\n            // await threads initedLatch to support dataSource restart.\n            if (createConnectionThread != null) {\n                createConnectionThread.getInitedLatch().await();\n            }\n            if (destroyConnectionThread != null) {\n                destroyConnectionThread.getInitedLatch().await();\n            }\n\n            init = true;\n\n            initedTime = new Date();\n            registerMbean();\n\n            if (connectError != null && poolingCount == 0) {\n                throw connectError;\n            }\n\n            if (keepAlive) {\n                if (createScheduler != null) {\n                    // async fill to minIdle\n                    for (int i = 0; i < minIdle - initialSize; ++i) {\n                        submitCreateTask(true);\n                    }\n                } else {\n                    empty.signal();\n                }\n            }\n\n        } catch (SQLException e) {\n            LOG.error(\"{dataSource-\" + this.getID() + \"} init error\", e);\n            throw e;\n        } catch (InterruptedException e) {\n            throw new SQLException(e.getMessage(), e);\n        } catch (RuntimeException e) {\n            LOG.error(\"{dataSource-\" + this.getID() + \"} init error\", e);\n            throw e;\n        } catch (Error e) {\n            LOG.error(\"{dataSource-\" + this.getID() + \"} init error\", e);\n            throw e;\n\n        } finally {\n            inited = true;\n            lock.unlock();\n\n            if (init && LOG.isInfoEnabled()) {\n                String msg = \"{dataSource-\" + this.getID();\n\n                if (this.name != null && !this.name.isEmpty()) {\n                    msg += \",\";\n                    msg += this.name;\n                }\n\n                msg += \"} inited\";\n\n                LOG.info(msg);\n            }\n        }\n    }\n\n    private void initTimeoutsFromUrlOrProperties() {\n        // createPhysicalConnection will set the corresponding parameters based on dbType.\n        if (jdbcUrl != null && (jdbcUrl.indexOf(\"connectTimeout=\") != -1 || jdbcUrl.indexOf(\"socketTimeout=\") != -1)) {\n            String[] items = jdbcUrl.split(\"(\\\\?|&)\");\n            for (int i = 0; i < items.length; i++) {\n                String item = items[i];\n                if (item.startsWith(\"connectTimeout=\")) {\n                    String strVal = item.substring(\"connectTimeout=\".length());\n                    setConnectTimeout(strVal);\n                } else if (item.startsWith(\"socketTimeout=\")) {\n                    String strVal = item.substring(\"socketTimeout=\".length());\n                    setSocketTimeout(strVal);\n                }\n            }\n        }\n\n        Object propertyConnectTimeout = connectProperties.get(\"connectTimeout\");\n        if (propertyConnectTimeout instanceof String) {\n            setConnectTimeout((String) propertyConnectTimeout);\n        } else if (propertyConnectTimeout instanceof Number) {\n            setConnectTimeout(((Number) propertyConnectTimeout).intValue());\n        }\n\n        Object propertySocketTimeout = connectProperties.get(\"socketTimeout\");\n        if (propertySocketTimeout instanceof String) {\n            setSocketTimeout((String) propertySocketTimeout);\n        } else if (propertySocketTimeout instanceof Number) {\n            setSocketTimeout(((Number) propertySocketTimeout).intValue());\n        }\n    }\n\n    /**\n     * Issue 5192,Issue 5457\n     * @see <a href=\"https://dev.mysql.com/doc/connector-j/8.1/en/connector-j-reference-jdbc-url-format.html\">MySQL Connection URL Syntax</a>\n     * @see <a href=\"https://mariadb.com/kb/en/about-mariadb-connector-j/\">About MariaDB Connector/J</a>\n     * @param jdbcUrl\n     * @return\n     */\n    private static boolean isMysqlOrMariaDBUrl(String jdbcUrl) {\n        return jdbcUrl.startsWith(\"jdbc:mysql://\") || jdbcUrl.startsWith(\"jdbc:mysql:loadbalance://\")\n            || jdbcUrl.startsWith(\"jdbc:mysql:replication://\") || jdbcUrl.startsWith(\"jdbc:mariadb://\")\n            || jdbcUrl.startsWith(\"jdbc:mariadb:loadbalance://\") || jdbcUrl.startsWith(\"jdbc:mariadb:replication://\");\n    }\n\n    private void submitCreateTask(boolean initTask) {\n        createTaskCount++;\n        CreateConnectionTask task = new CreateConnectionTask(initTask);\n        if (createTasks == null) {\n            createTasks = new long[8];\n        }\n\n        boolean putted = false;\n        for (int i = 0; i < createTasks.length; ++i) {\n            if (createTasks[i] == 0) {\n                createTasks[i] = task.taskId;\n                putted = true;\n                break;\n            }\n        }\n        if (!putted) {\n            long[] array = new long[createTasks.length * 3 / 2];\n            System.arraycopy(createTasks, 0, array, 0, createTasks.length);\n            array[createTasks.length] = task.taskId;\n            createTasks = array;\n        }\n\n        this.createSchedulerFutures.put(task, createScheduler.submit(task));\n    }\n\n    private boolean clearCreateTask(long taskId) {\n        if (createTasks == null) {\n            return false;\n        }\n\n        if (taskId == 0) {\n            return false;\n        }\n\n        for (int i = 0; i < createTasks.length; i++) {\n            if (createTasks[i] == taskId) {\n                createTasks[i] = 0;\n                createTaskCount--;\n\n                if (createTaskCount < 0) {\n                    createTaskCount = 0;\n                }\n\n                if (createTaskCount == 0 && createTasks.length > 8) {\n                    createTasks = new long[8];\n                }\n                return true;\n            }\n        }\n\n        if (LOG.isWarnEnabled()) {\n            LOG.warn(\"clear create task failed : \" + taskId);\n        }\n\n        return false;\n    }\n\n    private void createAndLogThread() {\n        if (this.timeBetweenLogStatsMillis <= 0) {\n            return;\n        }\n\n        String threadName = \"Druid-ConnectionPool-Log-\" + System.identityHashCode(this);\n        logStatsThread = new LogStatsThread(threadName);\n        logStatsThread.start();\n\n        this.resetStatEnable = false;\n    }\n\n    protected void createAndStartDestroyThread() {\n        destroyTask = new DestroyTask();\n\n        if (destroyScheduler != null) {\n            long period = timeBetweenEvictionRunsMillis;\n            if (period <= 0) {\n                period = 1000;\n            }\n            destroySchedulerFuture = destroyScheduler.scheduleAtFixedRate(destroyTask, period, period,\n                    TimeUnit.MILLISECONDS);\n            return;\n        }\n\n        String threadName = \"Druid-ConnectionPool-Destroy-\" + System.identityHashCode(this);\n        destroyConnectionThread = new DestroyConnectionThread(threadName);\n        destroyConnectionThread.start();\n    }\n\n    protected void createAndStartCreatorThread() {\n        if (createScheduler == null) {\n            String threadName = \"Druid-ConnectionPool-Create-\" + System.identityHashCode(this);\n            createConnectionThread = new CreateConnectionThread(threadName);\n            createConnectionThread.start();\n        }\n    }\n\n    /**\n     * load filters from SPI ServiceLoader\n     *\n     * @see ServiceLoader\n     */\n    private void initFromSPIServiceLoader() {\n        if (loadSpifilterSkip) {\n            return;\n        }\n\n        if (autoFilters == null) {\n            List<Filter> filters = new ArrayList<Filter>();\n            ServiceLoader<Filter> autoFilterLoader = ServiceLoader.load(Filter.class);\n\n            for (Filter filter : autoFilterLoader) {\n                AutoLoad autoLoad = filter.getClass().getAnnotation(AutoLoad.class);\n                if (autoLoad != null && autoLoad.value()) {\n                    filters.add(filter);\n                }\n            }\n            autoFilters = filters;\n        }\n\n        for (Filter filter : autoFilters) {\n            if (LOG.isInfoEnabled()) {\n                LOG.info(\"load filter from spi :\" + filter.getClass().getName());\n            }\n            addFilter(filter);\n        }\n    }\n\n    private void initFromWrapDriverUrl() throws SQLException {\n        if (!jdbcUrl.startsWith(DruidDriver.DEFAULT_PREFIX)) {\n            return;\n        }\n\n        DataSourceProxyConfig config = DruidDriver.parseConfig(jdbcUrl, null);\n        this.driverClass = config.getRawDriverClassName();\n\n        LOG.error(\"error url : '\" + sanitizedUrl(jdbcUrl) + \"', it should be : '\" + config.getRawUrl() + \"'\");\n\n        this.jdbcUrl = config.getRawUrl();\n        if (this.name == null) {\n            this.name = config.getName();\n        }\n\n        for (Filter filter : config.getFilters()) {\n            addFilter(filter);\n        }\n    }\n\n    /**\n     * 会去重复\n     *\n     * @param filter\n     */\n    private void addFilter(Filter filter) {\n        boolean exists = false;\n        for (Filter initedFilter : this.filters) {\n            if (initedFilter.getClass() == filter.getClass()) {\n                exists = true;\n                break;\n            }\n        }\n\n        if (!exists) {\n            filter.init(this);\n            this.filters.add(filter);\n        }\n\n    }\n\n    private void validationQueryCheck() {\n        if (!(testOnBorrow || testOnReturn || testWhileIdle)) {\n            return;\n        }\n\n        if (this.validConnectionChecker != null) {\n            return;\n        }\n\n        if (this.validationQuery != null && this.validationQuery.length() > 0) {\n            return;\n        }\n\n        if (\"odps\".equals(dbTypeName)) {\n            return;\n        }\n\n        String errorMessage = \"\";\n\n        if (testOnBorrow) {\n            errorMessage += \"testOnBorrow is true, \";\n        }\n\n        if (testOnReturn) {\n            errorMessage += \"testOnReturn is true, \";\n        }\n\n        if (testWhileIdle) {\n            errorMessage += \"testWhileIdle is true, \";\n        }\n\n        LOG.error(errorMessage + \"validationQuery not set\");\n    }\n\n    protected void resolveDriver() throws SQLException {\n        if (this.driver == null) {\n            if (this.driverClass == null || this.driverClass.isEmpty()) {\n                this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl);\n            }\n\n            if (MockDriver.class.getName().equals(driverClass)) {\n                driver = MockDriver.instance;\n            } else if (\"com.alibaba.druid.support.clickhouse.BalancedClickhouseDriver\".equals(driverClass)) {\n                Properties info = new Properties();\n                info.put(\"user\", username);\n                info.put(\"password\", password);\n                info.putAll(connectProperties);\n                driver = new BalancedClickhouseDriver(jdbcUrl, info);\n            } else if (\"com.alibaba.druid.support.clickhouse.BalancedClickhouseDriverNative\".equals(driverClass)) {\n                Properties info = new Properties();\n                info.put(\"user\", username);\n                info.put(\"password\", password);\n                info.putAll(connectProperties);\n                driver = new BalancedClickhouseDriverNative(jdbcUrl, info);\n            } else {\n                if (jdbcUrl == null && (driverClass == null || driverClass.length() == 0)) {\n                    throw new SQLException(\"url not set\");\n                }\n                driver = JdbcUtils.createDriver(driverClassLoader, driverClass);\n            }\n        } else {\n            if (this.driverClass == null) {\n                this.driverClass = driver.getClass().getName();\n            }\n        }\n    }\n\n    protected void initCheck() throws SQLException {\n        DbType dbType = DbType.of(this.dbTypeName);\n\n        if (dbType == DbType.oracle) {\n            isOracle = true;\n\n            if (driver.getMajorVersion() < 10) {\n                throw new SQLException(\"not support oracle driver \" + driver.getMajorVersion() + \".\"\n                        + driver.getMinorVersion());\n            }\n\n            if (driver.getMajorVersion() == 10 && isUseOracleImplicitCache()) {\n                this.getConnectProperties().setProperty(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\", \"true\");\n            }\n\n            oracleValidationQueryCheck();\n        } else if (dbType == DbType.db2) {\n            db2ValidationQueryCheck();\n        } else if (dbType == DbType.mysql\n                || JdbcUtils.MYSQL_DRIVER.equals(this.driverClass)\n                || JdbcUtils.MYSQL_DRIVER_6.equals(this.driverClass)\n                || JdbcUtils.MYSQL_DRIVER_603.equals(this.driverClass)\n                || JdbcUtils.GOLDENDB_DRIVER.equals(this.driverClass)\n                || JdbcUtils.GBASE8S_DRIVER.equals(this.driverClass)\n                || JdbcUtils.POLARDBX_DRIVER.equals(this.driverClass)\n        ) {\n            isMySql = true;\n        }\n\n        if (removeAbandoned) {\n            LOG.warn(\"removeAbandoned is true, not use in production.\");\n        }\n    }\n\n    private void oracleValidationQueryCheck() {\n        if (validationQuery == null) {\n            return;\n        }\n        if (validationQuery.length() == 0) {\n            return;\n        }\n\n        SQLStatementParser sqlStmtParser = SQLParserUtils.createSQLStatementParser(validationQuery, this.dbTypeName);\n        List<SQLStatement> stmtList = sqlStmtParser.parseStatementList();\n\n        if (stmtList.size() != 1) {\n            return;\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n        if (!(stmt instanceof SQLSelectStatement)) {\n            return;\n        }\n\n        SQLSelectQuery query = ((SQLSelectStatement) stmt).getSelect().getQuery();\n        if (query instanceof SQLSelectQueryBlock) {\n            if (((SQLSelectQueryBlock) query).getFrom() == null) {\n                LOG.error(\"invalid oracle validationQuery. \" + validationQuery + \", may should be : \" + validationQuery\n                        + \" FROM DUAL\");\n            }\n        }\n    }\n\n    private void db2ValidationQueryCheck() {\n        if (validationQuery == null) {\n            return;\n        }\n        if (validationQuery.length() == 0) {\n            return;\n        }\n\n        SQLStatementParser sqlStmtParser = SQLParserUtils.createSQLStatementParser(validationQuery, this.dbTypeName);\n        List<SQLStatement> stmtList = sqlStmtParser.parseStatementList();\n\n        if (stmtList.size() != 1) {\n            return;\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n        if (!(stmt instanceof SQLSelectStatement)) {\n            return;\n        }\n\n        SQLSelectQuery query = ((SQLSelectStatement) stmt).getSelect().getQuery();\n        if (query instanceof SQLSelectQueryBlock) {\n            if (((SQLSelectQueryBlock) query).getFrom() == null) {\n                LOG.error(\"invalid db2 validationQuery. \" + validationQuery + \", may should be : \" + validationQuery\n                        + \" FROM SYSDUMMY\");\n            }\n        }\n    }\n\n    private void initValidConnectionChecker() {\n        if (this.validConnectionChecker != null) {\n            return;\n        }\n\n        String realDriverClassName = driver.getClass().getName();\n        if (JdbcUtils.isMySqlDriver(realDriverClassName)) {\n            this.validConnectionChecker = new MySqlValidConnectionChecker();\n\n        } else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)\n                || realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {\n            this.validConnectionChecker = new OracleValidConnectionChecker();\n\n        } else if (realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER)\n                || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4)\n                || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_JTDS)) {\n            this.validConnectionChecker = new MSSQLValidConnectionChecker();\n\n        } else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)\n                || realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)\n                || realDriverClassName.equals(JdbcConstants.OPENGAUSS_DRIVER)\n                || realDriverClassName.equals(JdbcConstants.POLARDB_DRIVER)\n                || realDriverClassName.equals(JdbcConstants.POLARDB2_DRIVER)) {\n            this.validConnectionChecker = new PGValidConnectionChecker();\n        } else if (realDriverClassName.equals(JdbcConstants.OCEANBASE_DRIVER)\n                || (realDriverClassName.equals(JdbcConstants.OCEANBASE_DRIVER2))) {\n            DbType dbType = DbType.of(this.dbTypeName);\n            this.validConnectionChecker = new OceanBaseValidConnectionChecker(dbType);\n        }\n\n    }\n\n    private void initExceptionSorter() {\n        if (exceptionSorter instanceof NullExceptionSorter) {\n            if (driver instanceof MockDriver) {\n                return;\n            }\n        } else if (this.exceptionSorter != null) {\n            return;\n        }\n\n        for (Class<?> driverClass = driver.getClass(); ; ) {\n            String realDriverClassName = driverClass.getName();\n            if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) //\n                    || realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)\n                    || realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_603)) {\n                this.exceptionSorter = new MySqlExceptionSorter();\n                this.isMySql = true;\n            } else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)\n                    || realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {\n                this.exceptionSorter = new OracleExceptionSorter();\n            } else if (realDriverClassName.equals(JdbcConstants.OCEANBASE_DRIVER)) { // 写一个真实的 TestCase\n                if (JdbcUtils.OCEANBASE_ORACLE.name().equalsIgnoreCase(dbTypeName)) {\n                    this.exceptionSorter = new OceanBaseOracleExceptionSorter();\n                } else {\n                    this.exceptionSorter = new MySqlExceptionSorter();\n                }\n            } else if (realDriverClassName.equals(\"com.informix.jdbc.IfxDriver\")) {\n                this.exceptionSorter = new InformixExceptionSorter();\n\n            } else if (realDriverClassName.equals(\"com.sybase.jdbc2.jdbc.SybDriver\")) {\n                this.exceptionSorter = new SybaseExceptionSorter();\n\n            } else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)\n                    || realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)\n                    || realDriverClassName.equals(JdbcConstants.POLARDB_DRIVER)\n                    || realDriverClassName.equals(JdbcConstants.POLARDB2_DRIVER)) {\n                this.exceptionSorter = new PGExceptionSorter();\n\n            } else if (realDriverClassName.equals(\"com.alibaba.druid.mock.MockDriver\")) {\n                this.exceptionSorter = new MockExceptionSorter();\n            } else if (realDriverClassName.contains(\"DB2\")) {\n                this.exceptionSorter = new DB2ExceptionSorter();\n            } else if (realDriverClassName.equals(JdbcConstants.GOLDENDB_DRIVER)) {\n                this.exceptionSorter = new MySqlExceptionSorter();\n                this.isMySql = true;\n            } else if (realDriverClassName.equals(JdbcConstants.POLARDBX_DRIVER)) {\n                this.exceptionSorter = new MySqlExceptionSorter();\n                this.isMySql = true;\n            } else {\n                Class<?> superClass = driverClass.getSuperclass();\n                if (superClass != null && superClass != Object.class) {\n                    driverClass = superClass;\n                    continue;\n                }\n            }\n\n            break;\n        }\n    }\n\n    @Override\n    public DruidPooledConnection getConnection() throws SQLException {\n        return getConnection(maxWait);\n    }\n\n    public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {\n        if (jdbcUrl == null || jdbcUrl.isEmpty()) {\n            LOG.warn(\"getConnection but jdbcUrl is not set,jdbcUrl=\" + jdbcUrl + \",username=\" + username);\n            return null;\n        }\n        init();\n\n        final int filtersSize = filters.size();\n        if (filtersSize > 0) {\n            FilterChainImpl filterChain = createChain();\n            try {\n                return filterChain.dataSource_connect(this, maxWaitMillis);\n            } finally {\n                recycleFilterChain(filterChain);\n            }\n        } else {\n            return getConnectionDirect(maxWaitMillis);\n        }\n    }\n\n    @Override\n    public PooledConnection getPooledConnection() throws SQLException {\n        return getConnection(maxWait);\n    }\n\n    @Override\n    public PooledConnection getPooledConnection(String user, String password) throws SQLException {\n        throw new UnsupportedOperationException(\"Not supported by DruidDataSource\");\n    }\n\n    public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {\n        int notFullTimeoutRetryCnt = 0;\n        for (; ; ) {\n            // handle notFullTimeoutRetry\n            DruidPooledConnection poolableConnection;\n            try {\n                poolableConnection = getConnectionInternal(maxWaitMillis);\n            } catch (GetConnectionTimeoutException ex) {\n                if (notFullTimeoutRetryCnt < this.notFullTimeoutRetryCount && !isFull()) {\n                    notFullTimeoutRetryCnt++;\n                    if (LOG.isWarnEnabled()) {\n                        LOG.warn(\"get connection timeout retry : \" + notFullTimeoutRetryCnt);\n                    }\n                    continue;\n                }\n                throw ex;\n            }\n\n            if (testOnBorrow) {\n                boolean validated = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);\n                if (!validated) {\n                    if (LOG.isDebugEnabled()) {\n                        LOG.debug(\"skip not validated connection.\");\n                    }\n\n                    discardConnection(poolableConnection.holder);\n                    continue;\n                }\n            } else {\n                if (poolableConnection.conn.isClosed()) {\n                    discardConnection(poolableConnection.holder); // 传入null，避免重复关闭\n                    continue;\n                }\n\n                if (testWhileIdle) {\n                    final DruidConnectionHolder holder = poolableConnection.holder;\n                    long currentTimeMillis = System.currentTimeMillis();\n                    long lastActiveTimeMillis = holder.lastActiveTimeMillis;\n                    long lastExecTimeMillis = holder.lastExecTimeMillis;\n                    long lastKeepTimeMillis = holder.lastKeepTimeMillis;\n\n                    if (checkExecuteTime\n                            && lastExecTimeMillis != lastActiveTimeMillis) {\n                        lastActiveTimeMillis = lastExecTimeMillis;\n                    }\n\n                    if (lastKeepTimeMillis > lastActiveTimeMillis) {\n                        lastActiveTimeMillis = lastKeepTimeMillis;\n                    }\n\n                    long idleMillis = currentTimeMillis - lastActiveTimeMillis;\n\n                    if (idleMillis >= timeBetweenEvictionRunsMillis\n                            || idleMillis < 0 // unexcepted branch\n                    ) {\n                        boolean validated = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);\n                        if (!validated) {\n                            if (LOG.isDebugEnabled()) {\n                                LOG.debug(\"skip not validated connection.\");\n                            }\n\n                            discardConnection(poolableConnection.holder);\n                            continue;\n                        }\n                    }\n                }\n            }\n\n            if (removeAbandoned) {\n                StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();\n                poolableConnection.connectStackTrace = stackTrace;\n                poolableConnection.setConnectedTimeNano();\n                poolableConnection.traceEnable = true;\n\n                activeConnectionLock.lock();\n                try {\n                    activeConnections.put(poolableConnection, PRESENT);\n                } finally {\n                    activeConnectionLock.unlock();\n                }\n            }\n\n            if (!this.defaultAutoCommit) {\n                poolableConnection.setAutoCommit(false);\n            }\n\n            return poolableConnection;\n        }\n    }\n\n    /**\n     * 抛弃连接，不进行回收，而是抛弃\n     *\n     * @param conn the connection to be discarded\n     * @return a boolean indicating whether the empty signal was called\n     * @deprecated\n     */\n    @Override\n    public boolean discardConnection(Connection conn) {\n        boolean emptySignalCalled = false;\n        if (conn == null) {\n            return emptySignalCalled;\n        }\n\n        try {\n            if (!conn.isClosed()) {\n                conn.close();\n            }\n        } catch (SQLRecoverableException ignored) {\n            discardErrorCountUpdater.incrementAndGet(this);\n            // ignored\n        } catch (Throwable e) {\n            discardErrorCountUpdater.incrementAndGet(this);\n\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"discard to close connection error\", e);\n            }\n        }\n\n        lock.lock();\n        try {\n            activeCount--;\n            discardCount++;\n\n            int fillCount = minIdle - (activeCount + poolingCount + createTaskCount);\n            if (fillCount > 0) {\n                emptySignalCalled = true;\n                emptySignal(fillCount);\n            }\n        } finally {\n            lock.unlock();\n        }\n        return emptySignalCalled;\n    }\n\n    @Override\n    public boolean discardConnection(DruidConnectionHolder holder) {\n        boolean emptySignalCalled = false;\n        if (holder == null) {\n            return emptySignalCalled;\n        }\n\n        Connection conn = holder.getConnection();\n        if (conn != null) {\n            JdbcUtils.close(conn);\n        }\n\n        Socket socket = holder.socket;\n        if (socket != null) {\n            JdbcUtils.close(socket);\n        }\n\n        lock.lock();\n        try {\n            if (holder.discard) {\n                return emptySignalCalled;\n            }\n\n            if (holder.active) {\n                activeCount--;\n                holder.active = false;\n            }\n            discardCount++;\n\n            holder.discard = true;\n\n            int fillCount = minIdle - (activeCount + poolingCount + createTaskCount);\n            if (fillCount > 0) {\n                emptySignalCalled = true;\n                emptySignal(fillCount);\n            }\n        } finally {\n            lock.unlock();\n        }\n        return emptySignalCalled;\n    }\n\n    private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {\n        if (closed) {\n            connectErrorCountUpdater.incrementAndGet(this);\n            throw new DataSourceClosedException(\"dataSource already closed at \" + new Date(closeTimeMillis));\n        }\n\n        if (!enable) {\n            connectErrorCountUpdater.incrementAndGet(this);\n\n            if (disableException != null) {\n                throw disableException;\n            }\n\n            throw new DataSourceDisableException();\n        }\n\n        final int maxWaitThreadCount = this.maxWaitThreadCount;\n\n        DruidConnectionHolder holder;\n\n        long startTime = System.currentTimeMillis();  //进入循环等待之前，先记录开始尝试获取连接的时间\n        final long expiredTime = startTime + maxWait;\n        for (boolean createDirect = false; ; ) {\n            if (createDirect) {\n                try {\n                    createStartNanosUpdater.set(this, System.nanoTime());\n                    if (creatingCountUpdater.compareAndSet(this, 0, 1)) {\n                        PhysicalConnectionInfo pyConnInfo = DruidDataSource.this.createPhysicalConnection();\n                        holder = new DruidConnectionHolder(this, pyConnInfo);\n\n                        creatingCountUpdater.decrementAndGet(this);\n                        directCreateCountUpdater.incrementAndGet(this);\n\n                        if (LOG.isDebugEnabled()) {\n                            LOG.debug(\"conn-direct_create \");\n                        }\n\n                        final Lock lock = this.lock;\n                        lock.lock();\n                        try {\n                            if (activeCount + poolingCount < maxActive) {\n                                activeCount++;\n                                holder.active = true;\n                                if (activeCount > activePeak) {\n                                    activePeak = activeCount;\n                                    activePeakTime = System.currentTimeMillis();\n                                }\n                                break;\n                            }\n                        } finally {\n                            lock.unlock();\n                        }\n\n                        JdbcUtils.close(pyConnInfo.getPhysicalConnection());\n                    }\n                } finally {\n                    createDirect = false;\n                    createDirectCountUpdater.decrementAndGet(this);\n                }\n            }\n\n            final ReentrantLock lock = this.lock;\n            try {\n                lock.lockInterruptibly();\n            } catch (InterruptedException e) {\n                connectErrorCountUpdater.incrementAndGet(this);\n                throw new SQLException(\"interrupt\", e);\n            }\n\n            try {\n                if (maxWaitThreadCount > 0\n                        && notEmptyWaitThreadCount > maxWaitThreadCount) {\n                    connectErrorCountUpdater.incrementAndGet(this);\n                    throw new SQLException(\"maxWaitThreadCount \" + maxWaitThreadCount + \", current wait Thread count \"\n                            + lock.getQueueLength());\n                }\n\n                if (onFatalError\n                        && onFatalErrorMaxActive > 0\n                        && activeCount >= onFatalErrorMaxActive) {\n                    connectErrorCountUpdater.incrementAndGet(this);\n\n                    StringBuilder errorMsg = new StringBuilder();\n                    errorMsg.append(\"onFatalError, activeCount \")\n                            .append(activeCount)\n                            .append(\", onFatalErrorMaxActive \")\n                            .append(onFatalErrorMaxActive);\n\n                    if (lastFatalErrorTimeMillis > 0) {\n                        errorMsg.append(\", time '\")\n                                .append(StringUtils.formatDateTime19(\n                                        lastFatalErrorTimeMillis, TimeZone.getDefault()))\n                                .append(\"'\");\n                    }\n\n                    if (lastFatalErrorSql != null) {\n                        errorMsg.append(\", sql \\n\")\n                                .append(lastFatalErrorSql);\n                    }\n\n                    throw new SQLException(\n                            errorMsg.toString(), lastFatalError);\n                }\n\n                connectCount++;\n\n                if (createScheduler != null\n                        && poolingCount == 0\n                        && activeCount < maxActive\n                        && createDirectCountUpdater.get(this) == 0\n                        && creatingCountUpdater.get(this) == 0\n                        && createScheduler instanceof ScheduledThreadPoolExecutor) {\n                    ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) createScheduler;\n                    if (executor.getQueue().size() > 0) {\n                        if (maxWait > 0 && System.currentTimeMillis() - startTime >= maxWait) {\n                            holder = null;\n                            break;\n                        }\n                        createDirect = true;\n                        createDirectCountUpdater.incrementAndGet(this);\n                        continue;\n                    }\n                }\n\n                if (maxWait > 0) {\n                    if (System.currentTimeMillis() < expiredTime) {\n                        holder = pollLast(startTime, expiredTime);\n                    } else {\n                        holder = null;\n                        break;\n                    }\n                } else {\n                    holder = takeLast(startTime);\n                }\n\n                if (holder != null) {\n                    if (holder.discard) {\n                        holder = null;\n                        if (maxWait > 0 && System.currentTimeMillis() >= expiredTime) {\n                            break;\n                        }\n                        continue;\n                    }\n\n                    activeCount++;\n                    holder.active = true;\n                    if (activeCount > activePeak) {\n                        activePeak = activeCount;\n                        activePeakTime = System.currentTimeMillis();\n                    }\n                }\n            } catch (InterruptedException e) {\n                connectErrorCountUpdater.incrementAndGet(this);\n                throw new SQLException(e.getMessage(), e);\n            } catch (SQLException e) {\n                connectErrorCountUpdater.incrementAndGet(this);\n                throw e;\n            } finally {\n                lock.unlock();\n            }\n\n            break;\n        }\n\n        if (holder == null) {\n            long waitMillis = System.currentTimeMillis() - startTime;\n\n            final long activeCount;\n            final long maxActive;\n            final long creatingCount;\n            final long createStartNanos;\n            final long createErrorCount;\n            final Throwable createError;\n            try {\n                lock.lock();\n                activeCount = this.activeCount;\n                maxActive = this.maxActive;\n                creatingCount = this.creatingCount;\n                createStartNanos = this.createStartNanos;\n                createErrorCount = this.createErrorCount;\n                createError = this.createError;\n            } finally {\n                lock.unlock();\n            }\n\n            StringBuilder buf = new StringBuilder(128);\n            buf.append(\"wait millis \")\n                    .append(waitMillis)\n                    .append(\", active \").append(activeCount)\n                    .append(\", maxActive \").append(maxActive)\n                    .append(\", creating \").append(creatingCount);\n\n            if (creatingCount > 0 && createStartNanos > 0) {\n                long createElapseMillis = (System.nanoTime() - createStartNanos) / (1000 * 1000);\n                if (createElapseMillis > 0) {\n                    buf.append(\", createElapseMillis \").append(createElapseMillis);\n                }\n            }\n\n            if (createErrorCount > 0) {\n                buf.append(\", createErrorCount \").append(createErrorCount);\n            }\n\n            List<JdbcSqlStatValue> sqlList = this.getDataSourceStat().getRuningSqlList();\n            for (int i = 0; i < sqlList.size(); ++i) {\n                if (i != 0) {\n                    buf.append('\\n');\n                } else {\n                    buf.append(\", \");\n                }\n                JdbcSqlStatValue sql = sqlList.get(i);\n                buf.append(\"runningSqlCount \").append(sql.getRunningCount());\n                buf.append(\" : \");\n                buf.append(sql.getSql());\n            }\n\n            String errorMessage = buf.toString();\n\n            if (createError != null) {\n                throw new GetConnectionTimeoutException(errorMessage, createError);\n            } else {\n                throw new GetConnectionTimeoutException(errorMessage);\n            }\n        }\n\n        holder.incrementUseCount();\n\n        return new DruidPooledConnection(holder);\n    }\n\n    public void handleConnectionException(\n            DruidPooledConnection pooledConnection,\n            Throwable t,\n            String sql\n    ) throws SQLException {\n        final DruidConnectionHolder holder = pooledConnection.getConnectionHolder();\n        if (holder == null) {\n            return;\n        }\n\n        errorCountUpdater.incrementAndGet(this);\n        lastError = t;\n        lastErrorTimeMillis = System.currentTimeMillis();\n\n        if (t instanceof SQLException) {\n            SQLException sqlEx = (SQLException) t;\n\n            // broadcastConnectionError\n            ConnectionEvent event = new ConnectionEvent(pooledConnection, sqlEx);\n            for (ConnectionEventListener eventListener : holder.getConnectionEventListeners()) {\n                eventListener.connectionErrorOccurred(event);\n            }\n\n            // exceptionSorter.isExceptionFatal\n            if (exceptionSorter != null && exceptionSorter.isExceptionFatal(sqlEx)) {\n                handleFatalError(pooledConnection, sqlEx, sql);\n            }\n\n            throw sqlEx;\n        } else {\n            throw new SQLException(\"Error\", t);\n        }\n    }\n\n    protected final void handleFatalError(\n            DruidPooledConnection conn,\n            SQLException error,\n            String sql\n    ) throws SQLException {\n        final DruidConnectionHolder holder = conn.holder;\n\n        if (conn.isTraceEnable()) {\n            activeConnectionLock.lock();\n            try {\n                if (conn.isTraceEnable()) {\n                    activeConnections.remove(conn);\n                    conn.setTraceEnable(false);\n                }\n            } finally {\n                activeConnectionLock.unlock();\n            }\n        }\n\n        long lastErrorTimeMillis = this.lastErrorTimeMillis;\n        if (lastErrorTimeMillis == 0) {\n            lastErrorTimeMillis = System.currentTimeMillis();\n        }\n\n        if (sql != null && sql.length() > 1024) {\n            sql = sql.substring(0, 1024);\n        }\n\n        boolean requireDiscard = false;\n        // using dataSourceLock when holder dataSource isn't null because shrink used it to access fatal error variables.\n        boolean hasHolderDataSource = (holder != null && holder.getDataSource() != null);\n        ReentrantLock fatalErrorCountLock = hasHolderDataSource ? holder.getDataSource().lock : conn.lock;\n        fatalErrorCountLock.lock();\n        try {\n            if ((!conn.closed) && !conn.disable) {\n                conn.disable(error);\n                requireDiscard = true;\n            }\n\n            lastFatalErrorTimeMillis = lastErrorTimeMillis;\n            fatalErrorCount++;\n            if (fatalErrorCount - fatalErrorCountLastShrink > onFatalErrorMaxActive) {\n                // increase fatalErrorCountLastShrink to avoid that emptySignal would be called again by shrink.\n                fatalErrorCountLastShrink++;\n                onFatalError = true;\n            } else {\n                onFatalError = false;\n            }\n            lastFatalError = error;\n            lastFatalErrorSql = sql;\n        } finally {\n            fatalErrorCountLock.unlock();\n        }\n\n        boolean emptySignalCalled = false;\n        if (requireDiscard) {\n            if (holder != null && holder.statementTrace != null) {\n                holder.lock.lock();\n                try {\n                    for (Statement stmt : holder.statementTrace) {\n                        JdbcUtils.close(stmt);\n                    }\n                } finally {\n                    holder.lock.unlock();\n                }\n            }\n\n            // decrease activeCount first to make sure the following emptySignal should be called successfully.\n            emptySignalCalled = this.discardConnection(holder);\n        }\n\n        // holder.\n        LOG.error(\"{conn-\" + (holder != null ? holder.getConnectionId() : \"null\") + \"} discard\", error);\n\n        if (!emptySignalCalled && onFatalError && hasHolderDataSource) {\n            fatalErrorCountLock.lock();\n            try {\n                emptySignal();\n            } finally {\n                fatalErrorCountLock.unlock();\n            }\n        }\n    }\n\n    /**\n     * 回收连接\n     */\n    protected void recycle(DruidPooledConnection pooledConnection) throws SQLException {\n        final DruidConnectionHolder holder = pooledConnection.holder;\n\n        if (holder == null) {\n            LOG.warn(\"connectionHolder is null\");\n            return;\n        }\n\n        boolean asyncCloseConnectionEnable = this.removeAbandoned || this.asyncCloseConnectionEnable;\n        boolean isSameThread = pooledConnection.ownerThread == Thread.currentThread();\n\n        if (logDifferentThread //\n                && (!asyncCloseConnectionEnable) //\n                && !isSameThread\n        ) {\n            LOG.warn(\"get/close not same thread\");\n        }\n\n        final Connection physicalConnection = holder.conn;\n\n        if (pooledConnection.traceEnable) {\n            Object oldInfo = null;\n            activeConnectionLock.lock();\n            try {\n                if (pooledConnection.traceEnable) {\n                    oldInfo = activeConnections.remove(pooledConnection);\n                    pooledConnection.traceEnable = false;\n                }\n            } finally {\n                activeConnectionLock.unlock();\n            }\n            if (oldInfo == null) {\n                if (LOG.isWarnEnabled()) {\n                    LOG.warn(\"remove abandoned failed. activeConnections.size \" + activeConnections.size());\n                }\n            }\n        }\n\n        final boolean isAutoCommit = holder.underlyingAutoCommit;\n        final boolean isReadOnly = holder.underlyingReadOnly;\n        final boolean testOnReturn = this.testOnReturn;\n\n        try {\n            // check need to rollback?\n            if ((!isAutoCommit) && (!isReadOnly)) {\n                pooledConnection.rollback();\n            }\n\n            // reset holder, restore default settings, clear warnings\n            if (!isSameThread) {\n                final ReentrantLock lock = pooledConnection.lock;\n                lock.lock();\n                try {\n                    holder.reset();\n                } finally {\n                    lock.unlock();\n                }\n            } else {\n                holder.reset();\n            }\n\n            if (holder.discard) {\n                return;\n            }\n\n            if ((phyMaxUseCount > 0 && holder.useCount >= phyMaxUseCount)\n                    || holder.userPasswordVersion < getUserPasswordVersion()) {\n                discardConnection(holder);\n                return;\n            }\n\n            if (physicalConnection.isClosed()) {\n                lock.lock();\n                try {\n                    if (holder.active) {\n                        activeCount--;\n                        holder.active = false;\n                    }\n                    closeCount++;\n                } finally {\n                    lock.unlock();\n                }\n                return;\n            }\n\n            if (testOnReturn) {\n                boolean validated = testConnectionInternal(holder, physicalConnection);\n                if (!validated) {\n                    JdbcUtils.close(physicalConnection);\n\n                    destroyCountUpdater.incrementAndGet(this);\n\n                    lock.lock();\n                    try {\n                        if (holder.active) {\n                            activeCount--;\n                            holder.active = false;\n                        }\n                        closeCount++;\n                    } finally {\n                        lock.unlock();\n                    }\n                    return;\n                }\n            }\n            if (holder.initSchema != null) {\n                holder.conn.setSchema(holder.initSchema);\n                holder.initSchema = null;\n            }\n\n            if (!enable) {\n                discardConnection(holder);\n                return;\n            }\n\n            boolean result;\n            final long currentTimeMillis = System.currentTimeMillis();\n\n            if (phyTimeoutMillis > 0) {\n                long phyConnectTimeMillis = currentTimeMillis - holder.connectTimeMillis;\n                if (phyConnectTimeMillis > phyTimeoutMillis) {\n                    discardConnection(holder);\n                    return;\n                }\n            }\n\n            boolean full = false;\n            lock.lock();\n            try {\n                if (holder.active) {\n                    activeCount--;\n                    holder.active = false;\n                }\n                closeCount++;\n\n                result = putLast(holder, currentTimeMillis);\n                recycleCount++;\n                if (!result) {\n                    full = poolingCount + activeCount >= maxActive;\n                }\n            } finally {\n                lock.unlock();\n            }\n\n            if (!result) {\n                JdbcUtils.close(holder.conn);\n                String msg = \"connection recycle failed.\";\n                if (full) {\n                    msg += \" pool is full\";\n                }\n                LOG.info(msg);\n            }\n        } catch (Throwable e) {\n            holder.clearStatementCache();\n\n            if (!holder.discard) {\n                discardConnection(holder);\n                holder.discard = true;\n            }\n\n            LOG.error(\"recycle error\", e);\n            recycleErrorCountUpdater.incrementAndGet(this);\n        }\n    }\n\n    public long getRecycleErrorCount() {\n        return recycleErrorCount;\n    }\n\n    public void clearStatementCache() throws SQLException {\n        lock.lock();\n        try {\n            for (int i = 0; i < poolingCount; ++i) {\n                DruidConnectionHolder conn = connections[i];\n\n                if (conn.statementPool != null) {\n                    conn.statementPool.clear();\n                }\n            }\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    /**\n     * close datasource\n     */\n    public void close() {\n        if (LOG.isInfoEnabled()) {\n            LOG.info(\"{dataSource-\" + this.getID() + \"} closing ...\");\n        }\n\n        lock.lock();\n        try {\n            if (this.closed) {\n                return;\n            }\n\n            if (!this.inited) {\n                return;\n            }\n\n            this.closing = true;\n\n            if (logStatsThread != null) {\n                logStatsThread.interrupt();\n            }\n\n            if (createConnectionThread != null) {\n                createConnectionThread.interrupt();\n            }\n\n            if (destroyConnectionThread != null) {\n                destroyConnectionThread.interrupt();\n            }\n\n            for (Future<?> createSchedulerFuture : createSchedulerFutures.values()) {\n                createSchedulerFuture.cancel(true);\n            }\n\n            if (destroySchedulerFuture != null) {\n                destroySchedulerFuture.cancel(true);\n            }\n\n            for (int i = 0; i < poolingCount; ++i) {\n                DruidConnectionHolder connHolder = connections[i];\n\n                for (PreparedStatementHolder stmtHolder : connHolder.getStatementPool().getMap().values()) {\n                    connHolder.getStatementPool().closeRemovedStatement(stmtHolder);\n                }\n                connHolder.getStatementPool().getMap().clear();\n\n                Connection physicalConnection = connHolder.getConnection();\n                try {\n                    physicalConnection.close();\n                } catch (Exception ex) {\n                    LOG.warn(\"close connection error\", ex);\n                }\n                connections[i] = null;\n                destroyCountUpdater.incrementAndGet(this);\n            }\n            poolingCount = 0;\n            unregisterMbean();\n\n            enable = false;\n            notEmpty.signalAll();\n            notEmptySignalCount++;\n\n            this.closed = true;\n            this.closeTimeMillis = System.currentTimeMillis();\n\n            disableException = new DataSourceDisableException();\n\n            for (Filter filter : filters) {\n                filter.destroy();\n            }\n        } finally {\n            this.closing = false;\n            lock.unlock();\n        }\n\n        if (LOG.isInfoEnabled()) {\n            LOG.info(\"{dataSource-\" + this.getID() + \"} closed\");\n        }\n    }\n\n    public void registerMbean() {\n        if (!mbeanRegistered) {\n            AccessController.doPrivileged(new PrivilegedAction<Object>() {\n                @Override\n                public Object run() {\n                    ObjectName objectName = DruidDataSourceStatManager.addDataSource(DruidDataSource.this,\n                            DruidDataSource.this.name);\n\n                    DruidDataSource.this.setObjectName(objectName);\n                    DruidDataSource.this.mbeanRegistered = true;\n\n                    return null;\n                }\n            });\n        }\n    }\n\n    public void unregisterMbean() {\n        if (mbeanRegistered) {\n            AccessController.doPrivileged(new PrivilegedAction<Object>() {\n                @Override\n                public Object run() {\n                    DruidDataSourceStatManager.removeDataSource(DruidDataSource.this);\n                    DruidDataSource.this.mbeanRegistered = false;\n                    return null;\n                }\n            });\n        }\n    }\n\n    public boolean isMbeanRegistered() {\n        return mbeanRegistered;\n    }\n\n    boolean putLast(DruidConnectionHolder e, long lastActiveTimeMillis) {\n        if (activeCount + poolingCount >= maxActive || e.discard || this.closed || this.closing) {\n            return false;\n        }\n\n        e.lastActiveTimeMillis = lastActiveTimeMillis;\n        connections[poolingCount] = e;\n        incrementPoolingCount();\n\n        if (poolingCount > poolingPeak) {\n            poolingPeak = poolingCount;\n            poolingPeakTime = lastActiveTimeMillis;\n        }\n\n        notEmpty.signal();\n        notEmptySignalCount++;\n\n        return true;\n    }\n\n    private DruidConnectionHolder takeLast(long startTime) throws InterruptedException, SQLException {\n        return pollLast(startTime, 0);\n    }\n\n    private DruidConnectionHolder pollLast(long startTime, long expiredTime) throws InterruptedException, SQLException {\n        try {\n            long awaitStartTime;\n            long estimate = 0;\n            while (poolingCount == 0) {\n                // send signal to CreateThread create connection\n                emptySignal();\n\n                if (failFast && isFailContinuous()) {\n                    throw new DataSourceNotAvailableException(createError);\n                }\n\n                awaitStartTime = System.currentTimeMillis();\n                if (expiredTime != 0) {\n                    estimate = expiredTime - awaitStartTime;\n                    if (estimate <= 0) {\n                        return null;\n                    }\n                }\n\n                notEmptyWaitThreadCount++;\n                if (notEmptyWaitThreadCount > notEmptyWaitThreadPeak) {\n                    notEmptyWaitThreadPeak = notEmptyWaitThreadCount;\n                }\n                try {\n                    // signal by recycle or creator\n                    if (estimate == 0) {\n                        notEmpty.await();\n                    } else {\n                        notEmpty.await(estimate, TimeUnit.MILLISECONDS);\n                    }\n                } finally {\n                    notEmptyWaitThreadCount--;\n                    notEmptyWaitCount++;\n                    notEmptyWaitNanos += TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis() - awaitStartTime);\n                }\n\n                if (!enable) {\n                    connectErrorCountUpdater.incrementAndGet(this);\n                    if (disableException != null) {\n                        throw disableException;\n                    }\n\n                    throw new DataSourceDisableException();\n                }\n\n            }\n        } catch (InterruptedException ie) {\n            notEmpty.signal(); // propagate to non-interrupted thread\n            notEmptySignalCount++;\n            throw ie;\n        }\n\n        decrementPoolingCount();\n        DruidConnectionHolder last = connections[poolingCount];\n        connections[poolingCount] = null;\n\n        long waitNanos = System.currentTimeMillis() - startTime;\n        last.setLastNotEmptyWaitNanos(waitNanos);\n\n        return last;\n    }\n\n    private final void decrementPoolingCount() {\n        poolingCount--;\n    }\n\n    private final void incrementPoolingCount() {\n        poolingCount++;\n    }\n\n    @Override\n    public Connection getConnection(String username, String password) throws SQLException {\n        if (this.username == null\n                && this.password == null\n                && username != null\n                && password != null) {\n            this.username = username;\n            this.password = password;\n\n            return getConnection();\n        }\n\n        if (!StringUtils.equals(username, this.username)) {\n            throw new UnsupportedOperationException(\"Not supported by DruidDataSource\");\n        }\n\n        if (!StringUtils.equals(password, this.password)) {\n            throw new UnsupportedOperationException(\"Not supported by DruidDataSource\");\n        }\n\n        return getConnection();\n    }\n\n    public long getCreateCount() {\n        lock.lock();\n        try {\n            return createCount;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public long getDestroyCount() {\n        lock.lock();\n        try {\n            return destroyCount;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public long getConnectCount() {\n        lock.lock();\n        try {\n            return connectCount;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public long getCloseCount() {\n        return closeCount;\n    }\n\n    public long getConnectErrorCount() {\n        return connectErrorCountUpdater.get(this);\n    }\n\n    @Override\n    public int getPoolingCount() {\n        lock.lock();\n        try {\n            return poolingCount;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public int getPoolingPeak() {\n        lock.lock();\n        try {\n            return poolingPeak;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public Date getPoolingPeakTime() {\n        if (poolingPeakTime <= 0) {\n            return null;\n        }\n\n        return new Date(poolingPeakTime);\n    }\n\n    public long getRecycleCount() {\n        return recycleCount;\n    }\n\n    public int getActiveCount() {\n        lock.lock();\n        try {\n            return activeCount;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void logStats() {\n        final DruidDataSourceStatLogger statLogger = this.statLogger;\n        if (statLogger == null) {\n            return;\n        }\n\n        DruidDataSourceStatValue statValue = getStatValueAndReset();\n\n        statLogger.log(statValue);\n    }\n\n    public DruidDataSourceStatValue getStatValueAndReset() {\n        DruidDataSourceStatValue value = new DruidDataSourceStatValue();\n\n        lock.lock();\n        try {\n            value.setPoolingCount(this.poolingCount);\n            value.setPoolingPeak(this.poolingPeak);\n            value.setPoolingPeakTime(this.poolingPeakTime);\n\n            value.setActiveCount(this.activeCount);\n            value.setActivePeak(this.activePeak);\n            value.setActivePeakTime(this.activePeakTime);\n\n            value.setConnectCount(this.connectCount);\n            value.setCloseCount(this.closeCount);\n            value.setWaitThreadCount(lock.getWaitQueueLength(notEmpty));\n            value.setNotEmptyWaitCount(this.notEmptyWaitCount);\n            value.setNotEmptyWaitNanos(this.notEmptyWaitNanos);\n            value.setKeepAliveCheckCount(this.keepAliveCheckCount);\n\n            // reset\n            this.poolingPeak = 0;\n            this.poolingPeakTime = 0;\n            this.activePeak = 0;\n            this.activePeakTime = 0;\n            this.connectCount = 0;\n            this.closeCount = 0;\n            this.keepAliveCheckCount = 0;\n\n            this.notEmptyWaitCount = 0;\n            this.notEmptyWaitNanos = 0;\n        } finally {\n            lock.unlock();\n        }\n\n        value.setName(this.getName());\n        value.setDbType(this.dbTypeName);\n        value.setDriverClassName(this.getDriverClassName());\n\n        value.setUrl(this.getUrl());\n        value.setUserName(this.getUsername());\n        value.setFilterClassNames(this.getFilterClassNames());\n\n        value.setInitialSize(this.getInitialSize());\n        value.setMinIdle(this.getMinIdle());\n        value.setMaxActive(this.getMaxActive());\n\n        value.setQueryTimeout(this.getQueryTimeout());\n        value.setTransactionQueryTimeout(this.getTransactionQueryTimeout());\n        value.setLoginTimeout(this.getLoginTimeout());\n        value.setValidConnectionCheckerClassName(this.getValidConnectionCheckerClassName());\n        value.setExceptionSorterClassName(this.getExceptionSorterClassName());\n\n        value.setTestOnBorrow(this.testOnBorrow);\n        value.setTestOnReturn(this.testOnReturn);\n        value.setTestWhileIdle(this.testWhileIdle);\n\n        value.setDefaultAutoCommit(this.isDefaultAutoCommit());\n\n        if (defaultReadOnly != null) {\n            value.setDefaultReadOnly(defaultReadOnly);\n        }\n        value.setDefaultTransactionIsolation(this.getDefaultTransactionIsolation());\n\n        value.setLogicConnectErrorCount(connectErrorCountUpdater.getAndSet(this, 0));\n\n        value.setPhysicalConnectCount(createCountUpdater.getAndSet(this, 0));\n        value.setPhysicalCloseCount(destroyCountUpdater.getAndSet(this, 0));\n        value.setPhysicalConnectErrorCount(createErrorCountUpdater.getAndSet(this, 0));\n\n        value.setExecuteCount(this.getAndResetExecuteCount());\n        value.setErrorCount(errorCountUpdater.getAndSet(this, 0));\n        value.setCommitCount(commitCountUpdater.getAndSet(this, 0));\n        value.setRollbackCount(rollbackCountUpdater.getAndSet(this, 0));\n\n        value.setPstmtCacheHitCount(cachedPreparedStatementHitCountUpdater.getAndSet(this, 0));\n        value.setPstmtCacheMissCount(cachedPreparedStatementMissCountUpdater.getAndSet(this, 0));\n\n        value.setStartTransactionCount(startTransactionCountUpdater.getAndSet(this, 0));\n        value.setTransactionHistogram(this.getTransactionHistogram().toArrayAndReset());\n\n        value.setConnectionHoldTimeHistogram(this.getDataSourceStat().getConnectionHoldHistogram().toArrayAndReset());\n        value.setRemoveAbandoned(this.isRemoveAbandoned());\n        value.setClobOpenCount(this.getDataSourceStat().getClobOpenCountAndReset());\n        value.setBlobOpenCount(this.getDataSourceStat().getBlobOpenCountAndReset());\n\n        value.setSqlSkipCount(this.getDataSourceStat().getSkipSqlCountAndReset());\n        value.setSqlList(this.getDataSourceStat().getSqlStatMapAndReset());\n\n        return value;\n    }\n\n    public long getRemoveAbandonedCount() {\n        return removeAbandonedCount;\n    }\n\n    protected boolean put(PhysicalConnectionInfo physicalConnectionInfo) {\n        DruidConnectionHolder holder;\n        try {\n            holder = new DruidConnectionHolder(DruidDataSource.this, physicalConnectionInfo);\n        } catch (SQLException ex) {\n            lock.lock();\n            try {\n                if (createScheduler != null) {\n                    clearCreateTask(physicalConnectionInfo.createTaskId);\n                }\n            } finally {\n                lock.unlock();\n            }\n            LOG.error(\"create connection holder error\", ex);\n            return false;\n        }\n\n        return put(holder, physicalConnectionInfo.createTaskId, false);\n    }\n\n    private boolean put(DruidConnectionHolder holder, long createTaskId, boolean checkExists) {\n        lock.lock();\n        try {\n            if (this.closing || this.closed) {\n                return false;\n            }\n\n            if (activeCount + poolingCount >= maxActive) {\n                if (createScheduler != null) {\n                    clearCreateTask(createTaskId);\n                }\n                return false;\n            }\n\n            if (checkExists) {\n                for (int i = 0; i < poolingCount; i++) {\n                    if (connections[i] == holder) {\n                        return false;\n                    }\n                }\n            }\n\n            connections[poolingCount] = holder;\n            incrementPoolingCount();\n\n            if (poolingCount > poolingPeak) {\n                poolingPeak = poolingCount;\n                poolingPeakTime = System.currentTimeMillis();\n            }\n\n            notEmpty.signal();\n            notEmptySignalCount++;\n\n            if (createScheduler != null) {\n                clearCreateTask(createTaskId);\n\n                if (poolingCount + createTaskCount < notEmptyWaitThreadCount) {\n                    emptySignal();\n                }\n            }\n        } finally {\n            lock.unlock();\n        }\n        return true;\n    }\n\n    public class CreateConnectionTask implements Runnable {\n        private int errorCount;\n        private boolean initTask;\n        private final long taskId;\n\n        public CreateConnectionTask() {\n            taskId = createTaskIdSeedUpdater.getAndIncrement(DruidDataSource.this);\n        }\n\n        public CreateConnectionTask(boolean initTask) {\n            taskId = createTaskIdSeedUpdater.getAndIncrement(DruidDataSource.this);\n            this.initTask = initTask;\n        }\n\n        @Override\n        public void run() {\n            runInternal();\n        }\n\n        private void runInternal() {\n            for (; ; ) {\n                // addLast\n                lock.lock();\n                try {\n                    if (closed || closing) {\n                        clearCreateTask(taskId);\n                        return;\n                    }\n\n                    boolean emptyWait = createError == null || poolingCount != 0;\n\n                    if (emptyWait) {\n                        // 必须存在线程等待，才创建连接\n                        if (poolingCount >= notEmptyWaitThreadCount //\n                                && (!(keepAlive && activeCount + poolingCount < minIdle)) // 在keepAlive场景不能放弃创建\n                                && (!initTask) // 线程池初始化时的任务不能放弃创建\n                                && !isFailContinuous() // failContinuous时不能放弃创建，否则会无法创建线程\n                                && !isOnFatalError() // onFatalError时不能放弃创建，否则会无法创建线程\n                        ) {\n                            clearCreateTask(taskId);\n                            return;\n                        }\n                    }\n\n                    // 防止创建超过maxActive数量的连接\n                    if (activeCount + poolingCount >= maxActive) {\n                        clearCreateTask(taskId);\n                        return;\n                    }\n                } finally {\n                    lock.unlock();\n                }\n\n                PhysicalConnectionInfo physicalConnection = null;\n\n                try {\n                    physicalConnection = createPhysicalConnection();\n                } catch (OutOfMemoryError e) {\n                    LOG.error(\"create connection OutOfMemoryError, out memory. \", e);\n\n                    errorCount++;\n                    if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {\n                        // fail over retry attempts\n                        setFailContinuous(true);\n                        if (failFast) {\n                            lock.lock();\n                            try {\n                                notEmpty.signalAll();\n                            } finally {\n                                lock.unlock();\n                            }\n                        }\n\n                        if (breakAfterAcquireFailure || closing || closed) {\n                            lock.lock();\n                            try {\n                                clearCreateTask(taskId);\n                            } finally {\n                                lock.unlock();\n                            }\n                            return;\n                        }\n\n                        // reset errorCount\n                        this.errorCount = 0;\n                        createSchedulerFutures.put(this,\n                                createScheduler.schedule(this, timeBetweenConnectErrorMillis, TimeUnit.MILLISECONDS));\n                        return;\n                    }\n                } catch (SQLException e) {\n                    LOG.error(\"create connection SQLException, url: \" + sanitizedUrl(jdbcUrl), e);\n\n                    errorCount++;\n                    if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {\n                        // fail over retry attempts\n                        setFailContinuous(true);\n                        if (failFast) {\n                            lock.lock();\n                            try {\n                                notEmpty.signalAll();\n                            } finally {\n                                lock.unlock();\n                            }\n                        }\n\n                        if (breakAfterAcquireFailure || closing || closed) {\n                            lock.lock();\n                            try {\n                                clearCreateTask(taskId);\n                            } finally {\n                                lock.unlock();\n                            }\n                            return;\n                        }\n\n                        // reset errorCount\n                        this.errorCount = 0;\n                        createSchedulerFutures.put(this,\n                                createScheduler.schedule(this, timeBetweenConnectErrorMillis, TimeUnit.MILLISECONDS));\n                        return;\n                    }\n                } catch (RuntimeException e) {\n                    LOG.error(\"create connection RuntimeException\", e);\n                    // unknown fatal exception\n                    setFailContinuous(true);\n                    continue;\n                } catch (Error e) {\n                    lock.lock();\n                    try {\n                        clearCreateTask(taskId);\n                    } finally {\n                        lock.unlock();\n                    }\n                    LOG.error(\"create connection Error\", e);\n                    // unknown fatal exception\n                    setFailContinuous(true);\n                    break;\n                } catch (Throwable e) {\n                    lock.lock();\n                    try {\n                        clearCreateTask(taskId);\n                    } finally {\n                        lock.unlock();\n                    }\n\n                    LOG.error(\"create connection unexpected error.\", e);\n                    break;\n                }\n\n                if (physicalConnection == null) {\n                    continue;\n                }\n\n                physicalConnection.createTaskId = taskId;\n                boolean result = put(physicalConnection);\n                if (!result) {\n                    JdbcUtils.close(physicalConnection.getPhysicalConnection());\n                    LOG.info(\"put physical connection to pool failed.\");\n                }\n                break;\n            }\n        }\n    }\n\n    public class CreateConnectionThread extends Thread {\n        private final CountDownLatch initedLatch = new CountDownLatch(1);\n\n        public CreateConnectionThread(String name) {\n            super(name);\n            this.setDaemon(true);\n        }\n\n        public CountDownLatch getInitedLatch() {\n            return initedLatch;\n        }\n\n        public void run() {\n            initedLatch.countDown();\n\n            long lastDiscardCount = 0;\n            int errorCount = 0;\n            while (!closing && !closed && !Thread.currentThread().isInterrupted()) {\n                // addLast\n                try {\n                    lock.lockInterruptibly();\n                } catch (InterruptedException e2) {\n                    break;\n                }\n\n                long discardCount = DruidDataSource.this.discardCount;\n                boolean discardChanged = discardCount - lastDiscardCount > 0;\n                lastDiscardCount = discardCount;\n\n                try {\n                    boolean emptyWait = createError == null\n                            || poolingCount != 0\n                            || discardChanged;\n\n                    if (emptyWait\n                            && asyncInit && createCount < initialSize) {\n                        emptyWait = false;\n                    }\n\n                    if (emptyWait) {\n                        // 必须存在线程等待，才创建连接\n                        if (poolingCount >= notEmptyWaitThreadCount //\n                                && (!(keepAlive && activeCount + poolingCount < minIdle))\n                                && !isFailContinuous()\n                        ) {\n                            empty.await();\n                        }\n                    }\n\n                    // 防止创建超过maxActive数量的连接\n                    if (activeCount + poolingCount >= maxActive) {\n                        empty.await();\n                        continue;\n                    }\n                } catch (InterruptedException e) {\n                    lastCreateError = e;\n                    lastErrorTimeMillis = System.currentTimeMillis();\n\n                    if ((!closing) && (!closed)) {\n                        LOG.error(\"create connection thread interrupted, url: \" + sanitizedUrl(jdbcUrl), e);\n                    }\n                    break;\n                } finally {\n                    lock.unlock();\n                }\n\n                PhysicalConnectionInfo connection = null;\n\n                try {\n                    connection = createPhysicalConnection();\n                } catch (SQLException e) {\n                    LOG.error(\"create connection SQLException, url: \" + sanitizedUrl(jdbcUrl) + \", errorCode \" + e.getErrorCode()\n                        + \", state \" + e.getSQLState(), e);\n\n                    errorCount++;\n                    if (errorCount > connectionErrorRetryAttempts && timeBetweenConnectErrorMillis > 0) {\n                        // fail over retry attempts\n                        setFailContinuous(true);\n                        if (failFast) {\n                            lock.lock();\n                            try {\n                                notEmpty.signalAll();\n                            } finally {\n                                lock.unlock();\n                            }\n                        }\n\n                        if (breakAfterAcquireFailure || closing || closed) {\n                            break;\n                        }\n\n                        try {\n                            Thread.sleep(timeBetweenConnectErrorMillis);\n                        } catch (InterruptedException interruptEx) {\n                            break;\n                        }\n                    }\n                } catch (RuntimeException e) {\n                    LOG.error(\"create connection RuntimeException\", e);\n                    setFailContinuous(true);\n                    continue;\n                } catch (Error e) {\n                    LOG.error(\"create connection Error\", e);\n                    break;\n                }\n\n                if (connection == null) {\n                    continue;\n                }\n\n                boolean result = put(connection);\n                if (!result) {\n                    JdbcUtils.close(connection.getPhysicalConnection());\n                    LOG.info(\"put physical connection to pool failed.\");\n                }\n\n                // reset errorCount\n                errorCount = 0;\n            }\n        }\n    }\n\n    public class DestroyConnectionThread extends Thread {\n        private final CountDownLatch initedLatch = new CountDownLatch(1);\n\n        public DestroyConnectionThread(String name) {\n            super(name);\n            this.setDaemon(true);\n        }\n\n        public CountDownLatch getInitedLatch() {\n            return initedLatch;\n        }\n\n        public void run() {\n            initedLatch.countDown();\n\n            for (; !Thread.currentThread().isInterrupted(); ) {\n                // 从前面开始删除\n                try {\n                    if (closed || closing) {\n                        break;\n                    }\n\n                    if (timeBetweenEvictionRunsMillis > 0) {\n                        Thread.sleep(timeBetweenEvictionRunsMillis);\n                    } else {\n                        Thread.sleep(1000);\n                    }\n\n                    if (Thread.interrupted()) {\n                        break;\n                    }\n\n                    destroyTask.run();\n                } catch (InterruptedException e) {\n                    break;\n                }\n            }\n        }\n\n    }\n\n    public class DestroyTask implements Runnable {\n        public DestroyTask() {\n        }\n\n        @Override\n        public void run() {\n            shrink(true, keepAlive);\n\n            if (isRemoveAbandoned()) {\n                removeAbandoned();\n            }\n        }\n\n    }\n\n    public class LogStatsThread extends Thread {\n        public LogStatsThread(String name) {\n            super(name);\n            this.setDaemon(true);\n        }\n\n        public void run() {\n            try {\n                for (; ; ) {\n                    try {\n                        logStats();\n                    } catch (Exception e) {\n                        LOG.error(\"logStats error\", e);\n                    }\n\n                    Thread.sleep(timeBetweenLogStatsMillis);\n                }\n            } catch (InterruptedException e) {\n                // skip\n            }\n        }\n    }\n\n    public int removeAbandoned() {\n        int removeCount = 0;\n\n        if (activeConnections.size() == 0) {\n            return removeCount;\n        }\n\n        long currrentNanos = System.nanoTime();\n\n        List<DruidPooledConnection> abandonedList = new ArrayList<DruidPooledConnection>();\n\n        activeConnectionLock.lock();\n        try {\n            Iterator<DruidPooledConnection> iter = activeConnections.keySet().iterator();\n\n            for (; iter.hasNext(); ) {\n                DruidPooledConnection pooledConnection = iter.next();\n\n                if (pooledConnection.isRunning()) {\n                    continue;\n                }\n\n                long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000);\n\n                if (timeMillis >= removeAbandonedTimeoutMillis) {\n                    iter.remove();\n                    pooledConnection.setTraceEnable(false);\n                    abandonedList.add(pooledConnection);\n                }\n            }\n        } finally {\n            activeConnectionLock.unlock();\n        }\n\n        if (abandonedList.size() > 0) {\n            for (DruidPooledConnection pooledConnection : abandonedList) {\n                final ReentrantLock lock = pooledConnection.lock;\n                lock.lock();\n                try {\n                    if (pooledConnection.isDisable()) {\n                        continue;\n                    }\n                } finally {\n                    lock.unlock();\n                }\n\n                JdbcUtils.close(pooledConnection);\n                pooledConnection.abandond();\n                removeAbandonedCount++;\n                removeCount++;\n\n                if (isLogAbandoned()) {\n                    StringBuilder buf = new StringBuilder();\n                    buf.append(\"abandon connection, owner thread: \");\n                    buf.append(pooledConnection.getOwnerThread().getName());\n                    buf.append(\", connected at : \");\n                    buf.append(pooledConnection.getConnectedTimeMillis());\n                    buf.append(\", open stackTrace\\n\");\n\n                    StackTraceElement[] trace = pooledConnection.getConnectStackTrace();\n                    for (int i = 0; i < trace.length; i++) {\n                        buf.append(\"\\tat \");\n                        buf.append(trace[i].toString());\n                        buf.append(\"\\n\");\n                    }\n\n                    buf.append(\"ownerThread current state is \")\n                            .append(pooledConnection.getOwnerThread().getState())\n                            .append(\", current stackTrace\\n\");\n                    trace = pooledConnection.getOwnerThread().getStackTrace();\n                    for (int i = 0; i < trace.length; i++) {\n                        buf.append(\"\\tat \");\n                        buf.append(trace[i].toString());\n                        buf.append(\"\\n\");\n                    }\n\n                    LOG.error(buf.toString());\n                }\n            }\n        }\n\n        return removeCount;\n    }\n\n    /**\n     * Instance key\n     */\n    protected String instanceKey;\n\n    public Reference getReference() throws NamingException {\n        final String className = getClass().getName();\n        final String factoryName = className + \"Factory\"; // XXX: not robust\n        Reference ref = new Reference(className, factoryName, null);\n        ref.add(new StringRefAddr(\"instanceKey\", instanceKey));\n        ref.add(new StringRefAddr(\"url\", this.getUrl()));\n        ref.add(new StringRefAddr(\"username\", this.getUsername()));\n        ref.add(new StringRefAddr(\"password\", this.getPassword()));\n        // TODO ADD OTHER PROPERTIES\n        return ref;\n    }\n\n    @Override\n    public List<String> getFilterClassNames() {\n        List<String> names = new ArrayList<String>();\n        for (Filter filter : filters) {\n            names.add(filter.getClass().getName());\n        }\n        return names;\n    }\n\n    public int getRawDriverMajorVersion() {\n        int version = -1;\n        if (this.driver != null) {\n            version = driver.getMajorVersion();\n        }\n        return version;\n    }\n\n    public int getRawDriverMinorVersion() {\n        int version = -1;\n        if (this.driver != null) {\n            version = driver.getMinorVersion();\n        }\n        return version;\n    }\n\n    public String getProperties() {\n        Properties properties = new Properties();\n        properties.putAll(connectProperties);\n        if (properties.containsKey(\"password\")) {\n            properties.put(\"password\", \"******\");\n        }\n        return properties.toString();\n    }\n\n    @Override\n    public void shrink() {\n        shrink(false, false);\n    }\n\n    public void shrink(boolean checkTime) {\n        shrink(checkTime, keepAlive);\n    }\n\n    public void shrink(boolean checkTime, boolean keepAlive) {\n        if (poolingCount == 0) {\n            return;\n        }\n\n        final Lock lock = this.lock;\n        try {\n            lock.lockInterruptibly();\n        } catch (InterruptedException e) {\n            return;\n        }\n\n        boolean needFill = false;\n        int evictCount = 0;\n        int keepAliveCount = 0;\n        int fatalErrorIncrement = fatalErrorCount - fatalErrorCountLastShrink;\n        fatalErrorCountLastShrink = fatalErrorCount;\n\n        try {\n            if (!inited) {\n                return;\n            }\n\n            final int checkCount = poolingCount - minIdle;\n            final long currentTimeMillis = System.currentTimeMillis();\n            // remaining is the position of the next connection should be retained in the pool.\n            int remaining = 0;\n            int i = 0;\n            for (; i < poolingCount; ++i) {\n                DruidConnectionHolder connection = connections[i];\n\n                if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis)) {\n                    keepAliveConnections[keepAliveCount++] = connection;\n                    continue;\n                }\n\n                if (checkTime) {\n                    if (phyTimeoutMillis > 0) {\n                        long phyConnectTimeMillis = currentTimeMillis - connection.connectTimeMillis;\n                        if (phyConnectTimeMillis > phyTimeoutMillis) {\n                            evictConnections[evictCount++] = connection;\n                            continue;\n                        }\n                    }\n\n                    long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis;\n\n                    if (idleMillis < minEvictableIdleTimeMillis\n                            && idleMillis < keepAliveBetweenTimeMillis) {\n                        break;\n                    }\n\n                    if (idleMillis >= minEvictableIdleTimeMillis) {\n                        if (i < checkCount) {\n                            evictConnections[evictCount++] = connection;\n                            continue;\n                        } else if (idleMillis > maxEvictableIdleTimeMillis) {\n                            evictConnections[evictCount++] = connection;\n                            continue;\n                        }\n                    }\n\n                    if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis\n                            && currentTimeMillis - connection.lastKeepTimeMillis >= keepAliveBetweenTimeMillis) {\n                        keepAliveConnections[keepAliveCount++] = connection;\n                    } else {\n                        if (i != remaining) {\n                            // move the connection to the new position for retaining it in the pool.\n                            connections[remaining] = connection;\n                        }\n                        remaining++;\n                    }\n                } else {\n                    if (i < checkCount) {\n                        evictConnections[evictCount++] = connection;\n                    } else {\n                        break;\n                    }\n                }\n            }\n\n            // shrink connections by HotSpot intrinsic function _arraycopy for performance optimization.\n            int removeCount = evictCount + keepAliveCount;\n            if (removeCount > poolingCount) {\n                removeCount = poolingCount;\n            }\n            if (removeCount > 0) {\n                int breakedCount = poolingCount - i;\n                if (breakedCount > 0) {\n                    // retains the connections that start at the break position.\n                    System.arraycopy(connections, i, connections, remaining, breakedCount);\n                    remaining += breakedCount;\n                }\n                // clean the old references of the connections that have been moved forward to the new positions.\n                System.arraycopy(nullConnections, 0, connections, remaining, removeCount);\n                poolingCount -= removeCount;\n            }\n            keepAliveCheckCount += keepAliveCount;\n\n            if (keepAlive && poolingCount + activeCount < minIdle) {\n                needFill = true;\n            }\n        } finally {\n            lock.unlock();\n        }\n\n        if (evictCount > 0) {\n            for (int i = 0; i < evictCount; ++i) {\n                DruidConnectionHolder item = evictConnections[i];\n                Connection connection = item.getConnection();\n                JdbcUtils.close(connection);\n                destroyCountUpdater.incrementAndGet(this);\n            }\n            // use HotSpot intrinsic function _arraycopy for performance optimization.\n            System.arraycopy(nullConnections, 0, evictConnections, 0, evictConnections.length);\n        }\n\n        if (keepAliveCount > 0) {\n            // keep order\n            for (int i = keepAliveCount - 1; i >= 0; --i) {\n                DruidConnectionHolder holder = keepAliveConnections[i];\n                Connection connection = holder.getConnection();\n                holder.incrementKeepAliveCheckCount();\n\n                boolean validate = false;\n                try {\n                    this.validateConnection(connection);\n                    validate = true;\n                } catch (Throwable error) {\n                    keepAliveCheckErrorLast = error;\n                    keepAliveCheckErrorCountUpdater.incrementAndGet(this);\n                    if (LOG.isDebugEnabled()) {\n                        LOG.debug(\"keepAliveErr\", error);\n                    }\n                }\n\n                boolean discard = !validate;\n                if (validate) {\n                    holder.lastKeepTimeMillis = System.currentTimeMillis();\n                    boolean putOk = put(holder, 0L, true);\n                    if (!putOk) {\n                        discard = true;\n                    }\n                }\n\n                if (discard) {\n                    try {\n                        connection.close();\n                    } catch (Exception error) {\n                        discardErrorLast = error;\n                        discardErrorCountUpdater.incrementAndGet(DruidDataSource.this);\n                        if (LOG.isErrorEnabled()) {\n                            LOG.error(\"discard connection error\", error);\n                        }\n                    }\n\n                    if (holder.socket != null) {\n                        try {\n                            holder.socket.close();\n                        } catch (Exception error) {\n                            discardErrorLast = error;\n                            discardErrorCountUpdater.incrementAndGet(DruidDataSource.this);\n                            if (LOG.isErrorEnabled()) {\n                                LOG.error(\"discard connection error\", error);\n                            }\n                        }\n                    }\n\n                    lock.lock();\n                    try {\n                        holder.discard = true;\n                        discardCount++;\n\n                        if (activeCount + poolingCount + createTaskCount < minIdle) {\n                            needFill = true;\n                        }\n                    } finally {\n                        lock.unlock();\n                    }\n                }\n            }\n            this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount);\n            // use HotSpot intrinsic function _arraycopy for performance optimization.\n            System.arraycopy(nullConnections, 0, keepAliveConnections, 0, keepAliveConnections.length);\n        }\n\n        if (needFill) {\n            lock.lock();\n            try {\n                int fillCount = minIdle - (activeCount + poolingCount + createTaskCount);\n                if (fillCount > 0) {\n                    emptySignal(fillCount);\n                }\n            } finally {\n                lock.unlock();\n            }\n        } else if (fatalErrorIncrement > 0) {\n            lock.lock();\n            try {\n                emptySignal();\n            } finally {\n                lock.unlock();\n            }\n        }\n    }\n\n    public int getWaitThreadCount() {\n        lock.lock();\n        try {\n            return lock.getWaitQueueLength(notEmpty);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public long getNotEmptyWaitCount() {\n        return notEmptyWaitCount;\n    }\n\n    public int getNotEmptyWaitThreadCount() {\n        lock.lock();\n        try {\n            return notEmptyWaitThreadCount;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public int getNotEmptyWaitThreadPeak() {\n        lock.lock();\n        try {\n            return notEmptyWaitThreadPeak;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public long getNotEmptySignalCount() {\n        return notEmptySignalCount;\n    }\n\n    public long getNotEmptyWaitMillis() {\n        return notEmptyWaitNanos / (1000 * 1000);\n    }\n\n    public long getNotEmptyWaitNanos() {\n        return notEmptyWaitNanos;\n    }\n\n    public int getLockQueueLength() {\n        return lock.getQueueLength();\n    }\n\n    public int getActivePeak() {\n        return activePeak;\n    }\n\n    public Date getActivePeakTime() {\n        if (activePeakTime <= 0) {\n            return null;\n        }\n\n        return new Date(activePeakTime);\n    }\n\n    public String dump() {\n        lock.lock();\n        try {\n            return this.toString();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public long getErrorCount() {\n        return this.errorCount;\n    }\n\n    public String toString() {\n        StringBuilder buf = new StringBuilder();\n\n        buf.append(\"{\");\n\n        buf.append(\"\\n\\tCreateTime:\\\"\");\n        buf.append(Utils.toString(getCreatedTime()));\n        buf.append(\"\\\"\");\n\n        buf.append(\",\\n\\tActiveCount:\");\n        buf.append(getActiveCount());\n\n        buf.append(\",\\n\\tPoolingCount:\");\n        buf.append(getPoolingCount());\n\n        buf.append(\",\\n\\tCreateCount:\");\n        buf.append(getCreateCount());\n\n        buf.append(\",\\n\\tDestroyCount:\");\n        buf.append(getDestroyCount());\n\n        buf.append(\",\\n\\tCloseCount:\");\n        buf.append(getCloseCount());\n\n        buf.append(\",\\n\\tConnectCount:\");\n        buf.append(getConnectCount());\n\n        buf.append(\",\\n\\tConnections:[\");\n        for (int i = 0; i < poolingCount; ++i) {\n            DruidConnectionHolder conn = connections[i];\n            if (conn != null) {\n                if (i != 0) {\n                    buf.append(\",\");\n                }\n                buf.append(\"\\n\\t\\t\");\n                buf.append(conn.toString());\n            }\n        }\n        buf.append(\"\\n\\t]\");\n\n        buf.append(\"\\n}\");\n\n        if (this.isPoolPreparedStatements()) {\n            buf.append(\"\\n\\n[\");\n            for (int i = 0; i < poolingCount; ++i) {\n                DruidConnectionHolder conn = connections[i];\n                if (conn != null) {\n                    if (i != 0) {\n                        buf.append(\",\");\n                    }\n                    buf.append(\"\\n\\t{\\n\\tID:\");\n                    buf.append(System.identityHashCode(conn.getConnection()));\n                    PreparedStatementPool pool = conn.getStatementPool();\n\n                    buf.append(\", \\n\\tpoolStatements:[\");\n\n                    int entryIndex = 0;\n                    try {\n                        for (Map.Entry<PreparedStatementKey, PreparedStatementHolder> entry : pool.getMap().entrySet()) {\n                            if (entryIndex != 0) {\n                                buf.append(\",\");\n                            }\n                            buf.append(\"\\n\\t\\t{hitCount:\");\n                            buf.append(entry.getValue().getHitCount());\n                            buf.append(\",sql:\\\"\");\n                            buf.append(entry.getKey().getSql());\n                            buf.append(\"\\\"\");\n                            buf.append(\"\\t}\");\n\n                            entryIndex++;\n                        }\n                    } catch (ConcurrentModificationException e) {\n                        // skip ..\n                    }\n\n                    buf.append(\"\\n\\t\\t]\");\n\n                    buf.append(\"\\n\\t}\");\n                }\n            }\n            buf.append(\"\\n]\");\n        }\n\n        return buf.toString();\n    }\n\n    public List<Map<String, Object>> getPoolingConnectionInfo() {\n        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();\n        lock.lock();\n        try {\n            for (int i = 0; i < poolingCount; ++i) {\n                DruidConnectionHolder connHolder = connections[i];\n                Connection conn = connHolder.getConnection();\n\n                Map<String, Object> map = new LinkedHashMap<String, Object>();\n                map.put(\"id\", System.identityHashCode(conn));\n                map.put(\"connectionId\", connHolder.getConnectionId());\n                map.put(\"useCount\", connHolder.getUseCount());\n                if (connHolder.lastActiveTimeMillis > 0) {\n                    map.put(\"lastActiveTime\", new Date(connHolder.lastActiveTimeMillis));\n                }\n                if (connHolder.lastKeepTimeMillis > 0) {\n                    map.put(\"lastKeepTimeMillis\", new Date(connHolder.lastKeepTimeMillis));\n                }\n                map.put(\"connectTime\", new Date(connHolder.getTimeMillis()));\n                map.put(\"holdability\", connHolder.getUnderlyingHoldability());\n                map.put(\"transactionIsolation\", connHolder.getUnderlyingTransactionIsolation());\n                map.put(\"autoCommit\", connHolder.underlyingAutoCommit);\n                map.put(\"readoOnly\", connHolder.isUnderlyingReadOnly());\n\n                if (connHolder.isPoolPreparedStatements()) {\n                    List<Map<String, Object>> stmtCache = new ArrayList<Map<String, Object>>();\n                    PreparedStatementPool stmtPool = connHolder.getStatementPool();\n                    for (PreparedStatementHolder stmtHolder : stmtPool.getMap().values()) {\n                        Map<String, Object> stmtInfo = new LinkedHashMap<String, Object>();\n\n                        stmtInfo.put(\"sql\", stmtHolder.key.getSql());\n                        stmtInfo.put(\"defaultRowPrefetch\", stmtHolder.getDefaultRowPrefetch());\n                        stmtInfo.put(\"rowPrefetch\", stmtHolder.getRowPrefetch());\n                        stmtInfo.put(\"hitCount\", stmtHolder.getHitCount());\n\n                        stmtCache.add(stmtInfo);\n                    }\n\n                    map.put(\"pscache\", stmtCache);\n                }\n                map.put(\"keepAliveCheckCount\", connHolder.getKeepAliveCheckCount());\n\n                list.add(map);\n            }\n        } finally {\n            lock.unlock();\n        }\n        return list;\n    }\n\n    public void logTransaction(TransactionInfo info) {\n        long transactionMillis = info.getEndTimeMillis() - info.getStartTimeMillis();\n        if (transactionThresholdMillis > 0 && transactionMillis > transactionThresholdMillis) {\n            StringBuilder buf = new StringBuilder();\n            buf.append(\"long time transaction, take \");\n            buf.append(transactionMillis);\n            buf.append(\" ms : \");\n            for (String sql : info.getSqlList()) {\n                buf.append(sql);\n                buf.append(\";\");\n            }\n            LOG.error(buf.toString(), new TransactionTimeoutException());\n        }\n    }\n\n    @Override\n    public String getVersion() {\n        return VERSION.getVersionNumber();\n    }\n\n    @Override\n    public JdbcDataSourceStat getDataSourceStat() {\n        return dataSourceStat;\n    }\n\n    public Object clone() {\n        return cloneDruidDataSource();\n    }\n\n    public DruidDataSource cloneDruidDataSource() {\n        DruidDataSource x = new DruidDataSource();\n\n        cloneTo(x);\n\n        return x;\n    }\n\n    public Map<String, Object> getStatDataForMBean() {\n        try {\n            Map<String, Object> map = new HashMap<String, Object>();\n\n            // 0 - 4\n            map.put(\"Name\", this.getName());\n            map.put(\"URL\", this.getUrl());\n            map.put(\"CreateCount\", this.getCreateCount());\n            map.put(\"DestroyCount\", this.getDestroyCount());\n            map.put(\"ConnectCount\", this.getConnectCount());\n\n            // 5 - 9\n            map.put(\"CloseCount\", this.getCloseCount());\n            map.put(\"ActiveCount\", this.getActiveCount());\n            map.put(\"PoolingCount\", this.getPoolingCount());\n            map.put(\"LockQueueLength\", this.getLockQueueLength());\n            map.put(\"WaitThreadCount\", this.getNotEmptyWaitThreadCount());\n\n            // 10 - 14\n            map.put(\"InitialSize\", this.getInitialSize());\n            map.put(\"MaxActive\", this.getMaxActive());\n            map.put(\"MinIdle\", this.getMinIdle());\n            map.put(\"PoolPreparedStatements\", this.isPoolPreparedStatements());\n            map.put(\"TestOnBorrow\", this.isTestOnBorrow());\n\n            // 15 - 19\n            map.put(\"TestOnReturn\", this.isTestOnReturn());\n            map.put(\"MinEvictableIdleTimeMillis\", this.minEvictableIdleTimeMillis);\n            map.put(\"ConnectErrorCount\", this.getConnectErrorCount());\n            map.put(\"CreateTimespanMillis\", this.getCreateTimespanMillis());\n            map.put(\"DbType\", this.dbTypeName);\n\n            // 20 - 24\n            map.put(\"ValidationQuery\", this.getValidationQuery());\n            map.put(\"ValidationQueryTimeout\", this.getValidationQueryTimeout());\n            map.put(\"DriverClassName\", this.getDriverClassName());\n            map.put(\"Username\", this.getUsername());\n            map.put(\"RemoveAbandonedCount\", this.getRemoveAbandonedCount());\n\n            // 25 - 29\n            map.put(\"NotEmptyWaitCount\", this.getNotEmptyWaitCount());\n            map.put(\"NotEmptyWaitNanos\", this.getNotEmptyWaitNanos());\n            map.put(\"ErrorCount\", this.getErrorCount());\n            map.put(\"ReusePreparedStatementCount\", this.getCachedPreparedStatementHitCount());\n            map.put(\"StartTransactionCount\", this.getStartTransactionCount());\n\n            // 30 - 34\n            map.put(\"CommitCount\", this.getCommitCount());\n            map.put(\"RollbackCount\", this.getRollbackCount());\n            map.put(\"LastError\", JMXUtils.getErrorCompositeData(this.getLastError()));\n            map.put(\"LastCreateError\", JMXUtils.getErrorCompositeData(this.getLastCreateError()));\n            map.put(\"PreparedStatementCacheDeleteCount\", this.getCachedPreparedStatementDeleteCount());\n\n            // 35 - 39\n            map.put(\"PreparedStatementCacheAccessCount\", this.getCachedPreparedStatementAccessCount());\n            map.put(\"PreparedStatementCacheMissCount\", this.getCachedPreparedStatementMissCount());\n            map.put(\"PreparedStatementCacheHitCount\", this.getCachedPreparedStatementHitCount());\n            map.put(\"PreparedStatementCacheCurrentCount\", this.getCachedPreparedStatementCount());\n            map.put(\"Version\", this.getVersion());\n\n            // 40 -\n            map.put(\"LastErrorTime\", this.getLastErrorTime());\n            map.put(\"LastCreateErrorTime\", this.getLastCreateErrorTime());\n            map.put(\"CreateErrorCount\", this.getCreateErrorCount());\n            map.put(\"DiscardCount\", this.getDiscardCount());\n            map.put(\"ExecuteQueryCount\", this.getExecuteQueryCount());\n\n            map.put(\"ExecuteUpdateCount\", this.getExecuteUpdateCount());\n            map.put(\"InitStackTrace\", this.getInitStackTrace());\n\n            return map;\n        } catch (JMException ex) {\n            throw new IllegalStateException(\"getStatData error\", ex);\n        }\n    }\n\n    public Map<String, Object> getStatData() {\n        final int activeCount;\n        final int activePeak;\n        final Date activePeakTime;\n\n        final int poolingCount;\n        final int poolingPeak;\n        final Date poolingPeakTime;\n\n        final long connectCount;\n        final long closeCount;\n\n        lock.lock();\n        try {\n            poolingCount = this.poolingCount;\n            poolingPeak = this.poolingPeak;\n            poolingPeakTime = this.getPoolingPeakTime();\n\n            activeCount = this.activeCount;\n            activePeak = this.activePeak;\n            activePeakTime = this.getActivePeakTime();\n\n            connectCount = this.connectCount;\n            closeCount = this.closeCount;\n        } finally {\n            lock.unlock();\n        }\n        Map<String, Object> dataMap = new LinkedHashMap<String, Object>();\n\n        dataMap.put(\"Identity\", System.identityHashCode(this));\n        dataMap.put(\"Name\", this.getName());\n        dataMap.put(\"DbType\", this.dbTypeName);\n        dataMap.put(\"DriverClassName\", this.getDriverClassName());\n\n        dataMap.put(\"URL\", this.getUrl());\n        dataMap.put(\"UserName\", this.getUsername());\n        dataMap.put(\"FilterClassNames\", this.getFilterClassNames());\n\n        dataMap.put(\"WaitThreadCount\", this.getWaitThreadCount());\n        dataMap.put(\"NotEmptyWaitCount\", this.getNotEmptyWaitCount());\n        dataMap.put(\"NotEmptyWaitMillis\", this.getNotEmptyWaitMillis());\n\n        dataMap.put(\"PoolingCount\", poolingCount);\n        dataMap.put(\"PoolingPeak\", poolingPeak);\n        dataMap.put(\"PoolingPeakTime\", poolingPeakTime);\n\n        dataMap.put(\"ActiveCount\", activeCount);\n        dataMap.put(\"ActivePeak\", activePeak);\n        dataMap.put(\"ActivePeakTime\", activePeakTime);\n\n        dataMap.put(\"InitialSize\", this.getInitialSize());\n        dataMap.put(\"MinIdle\", this.getMinIdle());\n        dataMap.put(\"MaxActive\", this.getMaxActive());\n\n        dataMap.put(\"QueryTimeout\", this.getQueryTimeout());\n        dataMap.put(\"TransactionQueryTimeout\", this.getTransactionQueryTimeout());\n        dataMap.put(\"LoginTimeout\", this.getLoginTimeout());\n        dataMap.put(\"ValidConnectionCheckerClassName\", this.getValidConnectionCheckerClassName());\n        dataMap.put(\"ExceptionSorterClassName\", this.getExceptionSorterClassName());\n\n        dataMap.put(\"TestOnBorrow\", this.isTestOnBorrow());\n        dataMap.put(\"TestOnReturn\", this.isTestOnReturn());\n        dataMap.put(\"TestWhileIdle\", this.isTestWhileIdle());\n\n        dataMap.put(\"DefaultAutoCommit\", this.isDefaultAutoCommit());\n        dataMap.put(\"DefaultReadOnly\", this.getDefaultReadOnly());\n        dataMap.put(\"DefaultTransactionIsolation\", this.getDefaultTransactionIsolation());\n\n        dataMap.put(\"LogicConnectCount\", connectCount);\n        dataMap.put(\"LogicCloseCount\", closeCount);\n        dataMap.put(\"LogicConnectErrorCount\", this.getConnectErrorCount());\n\n        dataMap.put(\"PhysicalConnectCount\", this.getCreateCount());\n        dataMap.put(\"PhysicalCloseCount\", this.getDestroyCount());\n        dataMap.put(\"PhysicalConnectErrorCount\", this.getCreateErrorCount());\n\n        dataMap.put(\"DiscardCount\", this.getDiscardCount());\n\n        dataMap.put(\"ExecuteCount\", this.getExecuteCount());\n        dataMap.put(\"ExecuteUpdateCount\", this.getExecuteUpdateCount());\n        dataMap.put(\"ExecuteQueryCount\", this.getExecuteQueryCount());\n        dataMap.put(\"ExecuteBatchCount\", this.getExecuteBatchCount());\n        dataMap.put(\"ErrorCount\", this.getErrorCount());\n        dataMap.put(\"CommitCount\", this.getCommitCount());\n        dataMap.put(\"RollbackCount\", this.getRollbackCount());\n\n        dataMap.put(\"PSCacheAccessCount\", this.getCachedPreparedStatementAccessCount());\n        dataMap.put(\"PSCacheHitCount\", this.getCachedPreparedStatementHitCount());\n        dataMap.put(\"PSCacheMissCount\", this.getCachedPreparedStatementMissCount());\n\n        dataMap.put(\"StartTransactionCount\", this.getStartTransactionCount());\n        dataMap.put(\"TransactionHistogram\", this.getTransactionHistogramValues());\n\n        dataMap.put(\"ConnectionHoldTimeHistogram\", this.getDataSourceStat().getConnectionHoldHistogram().toArray());\n        dataMap.put(\"RemoveAbandoned\", this.isRemoveAbandoned());\n        dataMap.put(\"ClobOpenCount\", this.getDataSourceStat().getClobOpenCount());\n        dataMap.put(\"BlobOpenCount\", this.getDataSourceStat().getBlobOpenCount());\n        dataMap.put(\"KeepAliveCheckCount\", this.getDataSourceStat().getKeepAliveCheckCount());\n\n        dataMap.put(\"KeepAlive\", this.isKeepAlive());\n        dataMap.put(\"FailFast\", this.isFailFast());\n        dataMap.put(\"MaxWait\", this.getMaxWait());\n        dataMap.put(\"MaxWaitThreadCount\", this.getMaxWaitThreadCount());\n        dataMap.put(\"PoolPreparedStatements\", this.isPoolPreparedStatements());\n        dataMap.put(\"MaxPoolPreparedStatementPerConnectionSize\", this.getMaxPoolPreparedStatementPerConnectionSize());\n        dataMap.put(\"MinEvictableIdleTimeMillis\", this.minEvictableIdleTimeMillis);\n        dataMap.put(\"MaxEvictableIdleTimeMillis\", this.maxEvictableIdleTimeMillis);\n\n        dataMap.put(\"LogDifferentThread\", isLogDifferentThread());\n        dataMap.put(\"RecycleErrorCount\", getRecycleErrorCount());\n        dataMap.put(\"PreparedStatementOpenCount\", getPreparedStatementCount());\n        dataMap.put(\"PreparedStatementClosedCount\", getClosedPreparedStatementCount());\n\n        dataMap.put(\"UseUnfairLock\", isUseUnfairLock());\n        dataMap.put(\"InitGlobalVariants\", isInitGlobalVariants());\n        dataMap.put(\"InitVariants\", isInitVariants());\n        return dataMap;\n    }\n\n    public JdbcSqlStat getSqlStat(int sqlId) {\n        return this.getDataSourceStat().getSqlStat(sqlId);\n    }\n\n    public JdbcSqlStat getSqlStat(long sqlId) {\n        return this.getDataSourceStat().getSqlStat(sqlId);\n    }\n\n    public Map<String, JdbcSqlStat> getSqlStatMap() {\n        return this.getDataSourceStat().getSqlStatMap();\n    }\n\n    public Map<String, Object> getWallStatMap() {\n        WallProviderStatValue wallStatValue = getWallStatValue(false);\n\n        if (wallStatValue != null) {\n            return wallStatValue.toMap();\n        }\n\n        return null;\n    }\n\n    public WallProviderStatValue getWallStatValue(boolean reset) {\n        for (Filter filter : this.filters) {\n            if (filter instanceof WallFilter) {\n                WallFilter wallFilter = (WallFilter) filter;\n                return wallFilter.getProvider().getStatValue(reset);\n            }\n        }\n\n        return null;\n    }\n\n    public Lock getLock() {\n        return lock;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) {\n        for (Filter filter : this.filters) {\n            if (filter.isWrapperFor(iface)) {\n                return true;\n            }\n        }\n\n        if (this.statLogger != null\n                && (this.statLogger.getClass() == iface || DruidDataSourceStatLogger.class == iface)) {\n            return true;\n        }\n\n        return super.isWrapperFor(iface);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) {\n        for (Filter filter : this.filters) {\n            if (filter.isWrapperFor(iface)) {\n                return (T) filter;\n            }\n        }\n\n        if (this.statLogger != null\n                && (this.statLogger.getClass() == iface || DruidDataSourceStatLogger.class == iface)) {\n            return (T) statLogger;\n        }\n\n        return super.unwrap(iface);\n    }\n\n    public boolean isLogDifferentThread() {\n        return logDifferentThread;\n    }\n\n    public void setLogDifferentThread(boolean logDifferentThread) {\n        this.logDifferentThread = logDifferentThread;\n    }\n\n    public DruidPooledConnection tryGetConnection() throws SQLException {\n        if (poolingCount == 0) {\n            return null;\n        }\n        return getConnection();\n    }\n\n    @Override\n    public int fill() throws SQLException {\n        return this.fill(this.maxActive);\n    }\n\n    @Override\n    public int fill(int toCount) throws SQLException {\n        if (closed) {\n            throw new DataSourceClosedException(\"dataSource already closed at \" + new Date(closeTimeMillis));\n        }\n\n        if (toCount < 0) {\n            throw new IllegalArgumentException(\"toCount can't not be less than zero\");\n        }\n\n        init();\n\n        if (toCount > this.maxActive) {\n            toCount = this.maxActive;\n        }\n\n        int fillCount = 0;\n        for (; ; ) {\n            try {\n                lock.lockInterruptibly();\n            } catch (InterruptedException e) {\n                connectErrorCountUpdater.incrementAndGet(this);\n                throw new SQLException(\"interrupt\", e);\n            }\n\n            boolean fillable = this.isFillable(toCount);\n\n            lock.unlock();\n\n            if (!fillable) {\n                break;\n            }\n\n            DruidConnectionHolder holder;\n            try {\n                PhysicalConnectionInfo pyConnInfo = createPhysicalConnection();\n                holder = new DruidConnectionHolder(this, pyConnInfo);\n            } catch (SQLException e) {\n                LOG.error(\"fill connection error, url: \" + sanitizedUrl(this.jdbcUrl), e);\n                connectErrorCountUpdater.incrementAndGet(this);\n                throw e;\n            }\n\n            try {\n                lock.lockInterruptibly();\n            } catch (InterruptedException e) {\n                connectErrorCountUpdater.incrementAndGet(this);\n                throw new SQLException(\"interrupt\", e);\n            }\n\n            boolean result;\n            try {\n                if (!this.isFillable(toCount)) {\n                    JdbcUtils.close(holder.getConnection());\n                    LOG.info(\"fill connections skip.\");\n                    break;\n                }\n                result = this.putLast(holder, System.currentTimeMillis());\n                fillCount++;\n            } finally {\n                lock.unlock();\n            }\n\n            if (!result) {\n                JdbcUtils.close(holder.getConnection());\n                LOG.info(\"connection fill failed.\");\n            }\n        }\n\n        if (LOG.isInfoEnabled()) {\n            LOG.info(\"fill \" + fillCount + \" connections\");\n        }\n\n        return fillCount;\n    }\n\n    static String sanitizedUrl(String url) {\n        if (url == null) {\n            return null;\n        }\n        for (String pwdKeyNamesInMysql : new String[]{\n            \"password=\", \"password1=\", \"password2=\", \"password3=\",\n            \"trustCertificateKeyStorePassword=\",\n            \"clientCertificateKeyStorePassword=\",\n        }) {\n            if (url.contains(pwdKeyNamesInMysql)) {\n                url = url.replaceAll(\"([?&;]\" + pwdKeyNamesInMysql + \")[^&#;]*(.*)\", \"$1<masked>$2\");\n            }\n        }\n        return url;\n    }\n\n    private boolean isFillable(int toCount) {\n        int currentCount = this.poolingCount + this.activeCount;\n        return currentCount < toCount && currentCount < this.maxActive;\n    }\n\n    public boolean isFull() {\n        lock.lock();\n        try {\n            return this.poolingCount + this.activeCount >= this.maxActive;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private void emptySignal() {\n        emptySignal(1);\n    }\n\n    private void emptySignal(int fillCount) {\n        if (createScheduler == null) {\n            if (activeCount + poolingCount >= maxActive) {\n                return;\n            }\n            empty.signal();\n            return;\n        }\n\n        for (int i = 0; i < fillCount; i++) {\n            if (activeCount + poolingCount + createTaskCount >= maxActive) {\n                return;\n            }\n\n            if (createTaskCount >= maxCreateTaskCount) {\n                return;\n            }\n\n            submitCreateTask(false);\n        }\n    }\n\n    @Override\n    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {\n        if (server != null) {\n            try {\n                if (server.isRegistered(name)) {\n                    server.unregisterMBean(name);\n                }\n            } catch (Exception ex) {\n                LOG.warn(\"DruidDataSource preRegister error\", ex);\n            }\n        }\n        return name;\n    }\n\n    @Override\n    public void postRegister(Boolean registrationDone) {\n    }\n\n    @Override\n    public void preDeregister() throws Exception {\n    }\n\n    @Override\n    public void postDeregister() {\n    }\n\n    public boolean isClosed() {\n        return this.closed;\n    }\n\n    public boolean isCheckExecuteTime() {\n        return checkExecuteTime;\n    }\n\n    public void setCheckExecuteTime(boolean checkExecuteTime) {\n        this.checkExecuteTime = checkExecuteTime;\n    }\n\n    public boolean isLoadSpifilterSkip() {\n        return loadSpifilterSkip;\n    }\n\n    public void setLoadSpifilterSkip(boolean loadSpifilterSkip) {\n        this.loadSpifilterSkip = loadSpifilterSkip;\n    }\n\n    public void forEach(Connection conn) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceC3P0Adapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.filter.Filter;\n\nimport javax.sql.DataSource;\n\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.Driver;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.logging.Logger;\n\npublic class DruidDataSourceC3P0Adapter implements DataSource, DruidDataSourceC3P0AdapterMBean {\n    private DruidDataSource dataSource;\n\n    public DruidDataSourceC3P0Adapter() {\n        dataSource = new DruidDataSource();\n\n        // setDefault\n        dataSource.setInitialSize(3);\n        acquireIncrement = 3;\n        dataSource.setTimeBetweenConnectErrorMillis(1000);\n        dataSource.setDefaultAutoCommit(true);\n        dataSource.setLogAbandoned(false);\n        dataSource.setMaxActive(15);\n        dataSource.setMinIdle(3);\n        dataSource.setTestOnReturn(false);\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @Override\n    public PrintWriter getLogWriter() throws SQLException {\n        return dataSource.getLogWriter();\n    }\n\n    @Override\n    public void setLogWriter(PrintWriter out) throws SQLException {\n        dataSource.setLogWriter(out);\n    }\n\n    @Override\n    public void setLoginTimeout(int seconds) throws SQLException {\n        dataSource.setLoginTimeout(seconds);\n    }\n\n    @Override\n    public int getLoginTimeout() throws SQLException {\n        return dataSource.getLoginTimeout();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == DruidDataSourceC3P0Adapter.class) {\n            return (T) this;\n        }\n\n        return dataSource.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == DruidDataSourceC3P0Adapter.class) {\n            return true;\n        }\n\n        return dataSource.isWrapperFor(iface);\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        return dataSource.getConnection();\n    }\n\n    @Override\n    public Connection getConnection(String username, String password) throws SQLException {\n        return dataSource.getConnection(username, password);\n    }\n\n    public String getDriverClass() {\n        return dataSource.getDriverClassName();\n    }\n\n    public void setDriverClass(String driverClass) {\n        dataSource.setDriverClassName(driverClass);\n    }\n\n    public String getJdbcUrl() {\n        return dataSource.getUrl();\n    }\n\n    public Driver getDriver() {\n        return dataSource.getDriver();\n    }\n\n    public void setDriver(Driver driver) {\n        dataSource.setDriver(driver);\n    }\n\n    public void setJdbcUrl(String jdbcUrl) {\n        dataSource.setUrl(jdbcUrl);\n    }\n\n    public Properties getProperties() {\n        return dataSource.getConnectProperties();\n    }\n\n    public void setProperties(Properties properties) {\n        dataSource.setConnectProperties(properties);\n    }\n\n    public String getUser() {\n        return dataSource.getUsername();\n    }\n\n    public void setUser(String user) {\n        dataSource.setUsername(user);\n    }\n\n    public String getPassword() {\n        return dataSource.getPassword();\n    }\n\n    public void setPassword(String password) {\n        dataSource.setPassword(password);\n    }\n\n    public int getCheckoutTimeout() {\n        return (int) dataSource.getMaxWait();\n    }\n\n    public void setCheckoutTimeout(int checkoutTimeout) {\n        dataSource.setMaxWait(checkoutTimeout);\n    }\n\n    public boolean isAutoCommitOnClose() {\n        return dataSource.isDefaultAutoCommit();\n    }\n\n    public void setAutoCommitOnClose(boolean autoCommitOnClose) {\n        this.dataSource.setDefaultAutoCommit(autoCommitOnClose);\n    }\n\n    public int getIdleConnectionTestPeriod() {\n        return (int) (dataSource.getTimeBetweenEvictionRunsMillis() / 1000);\n    }\n\n    public void setIdleConnectionTestPeriod(int idleConnectionTestPeriod) {\n        long timeBetweenEvictionRunsMillis = ((long) idleConnectionTestPeriod) * 1000L;\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setKeepAliveBetweenTimeMillis(timeBetweenEvictionRunsMillis * 2);\n    }\n\n    public int getInitialPoolSize() {\n        return dataSource.getInitialSize();\n    }\n\n    public void setInitialPoolSize(int initialPoolSize) {\n        dataSource.setInitialSize(initialPoolSize);\n    }\n\n    public int getMaxIdleTime() {\n        return (int) dataSource.getMinEvictableIdleTimeMillis() / 1000;\n    }\n\n    public void setMaxIdleTime(int maxIdleTime) {\n        dataSource.setMinEvictableIdleTimeMillis(((long) maxIdleTime) * 1000L);\n    }\n\n    public int getMaxPoolSize() {\n        return dataSource.getMaxActive();\n    }\n\n    public void setMaxPoolSize(int maxPoolSize) {\n        dataSource.setMaxActive(maxPoolSize);\n    }\n\n    public int getMinPoolSize() {\n        return dataSource.getMinIdle();\n    }\n\n    public void setMinPoolSize(int minPoolSize) {\n        dataSource.setMinIdle(minPoolSize);\n    }\n\n    public boolean isTestConnectionOnCheckout() {\n        return dataSource.isTestOnBorrow();\n    }\n\n    public void setTestConnectionOnCheckout(boolean testConnectionOnCheckout) {\n        dataSource.setTestOnBorrow(testConnectionOnCheckout);\n    }\n\n    public boolean isTestConnectionOnCheckin() {\n        return dataSource.isTestOnReturn();\n    }\n\n    public void setTestConnectionOnCheckin(boolean testConnectionOnCheckin) {\n        dataSource.setTestOnReturn(testConnectionOnCheckin);\n    }\n\n    public String getPreferredTestQuery() {\n        return dataSource.getValidationQuery();\n    }\n\n    public void setPreferredTestQuery(String preferredTestQuery) {\n        dataSource.setValidationQuery(preferredTestQuery);\n    }\n\n    public void setFilters(String filters) throws SQLException {\n        dataSource.setFilters(filters);\n    }\n\n    public List<Filter> getProxyFilters() {\n        return dataSource.getProxyFilters();\n    }\n\n    public void setProxyFilters(List<Filter> filters) {\n        dataSource.setProxyFilters(filters);\n    }\n\n    public String getDataSourceName() {\n        return dataSource.getName();\n    }\n\n    public int getNumConnections() {\n        return dataSource.getActiveCount() + dataSource.getPoolingCount();\n    }\n\n    public int getNumIdleConnections() {\n        return dataSource.getPoolingCount();\n    }\n\n    public int getNumBusyConnections() {\n        return dataSource.getActiveCount();\n    }\n\n    public int getNumUnclosedOrphanedConnections() {\n        return 0;\n    }\n\n    public int getNumConnectionsDefaultUser() {\n        return getNumConnections();\n    }\n\n    public int getNumIdleConnectionsDefaultUser() {\n        return getNumIdleConnections();\n    }\n\n    public int getNumBusyConnectionsDefaultUser() {\n        return getNumBusyConnections();\n    }\n\n    public int getMaxStatementsPerConnection() {\n        return dataSource.getMaxPoolPreparedStatementPerConnectionSize();\n    }\n\n    public void setMaxStatementsPerConnection(int maxStatementsPerConnection) {\n        dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxStatementsPerConnection);\n    }\n\n    public int getMaxStatements() {\n        return dataSource.getMaxOpenPreparedStatements();\n    }\n\n    public void setMaxStatements(int maxStatements) {\n        dataSource.setMaxOpenPreparedStatements(maxStatements);\n    }\n\n    public int getUnreturnedConnectionTimeout() {\n        return dataSource.getRemoveAbandonedTimeout();\n    }\n\n    public void setUnreturnedConnectionTimeout(int unreturnedConnectionTimeout) {\n        dataSource.setRemoveAbandonedTimeout(unreturnedConnectionTimeout);\n    }\n\n    public boolean isDebugUnreturnedConnectionStackTraces() {\n        return dataSource.isLogAbandoned();\n    }\n\n    public void setDebugUnreturnedConnectionStackTraces(boolean debugUnreturnedConnectionStackTraces) {\n        dataSource.setLogAbandoned(debugUnreturnedConnectionStackTraces);\n    }\n\n    public int getAcquireRetryAttempts() {\n        return dataSource.getConnectionErrorRetryAttempts();\n    }\n\n    public void setAcquireRetryAttempts(int acquireRetryAttempts) {\n        dataSource.setConnectionErrorRetryAttempts(acquireRetryAttempts);\n    }\n\n    public int getAcquireRetryDelay() {\n        return (int) dataSource.getTimeBetweenConnectErrorMillis();\n    }\n\n    public void setAcquireRetryDelay(int acquireRetryDelay) {\n        dataSource.setTimeBetweenConnectErrorMillis(acquireRetryDelay);\n    }\n\n    public boolean isBreakAfterAcquireFailure() {\n        return dataSource.isBreakAfterAcquireFailure();\n    }\n\n    public void setBreakAfterAcquireFailure(boolean breakAfterAcquireFailure) {\n        dataSource.setBreakAfterAcquireFailure(breakAfterAcquireFailure);\n    }\n\n    // /////////////////\n\n    @Override\n    public boolean isEnable() {\n        return dataSource.isEnable();\n    }\n\n    @Override\n    public void shrink() {\n        dataSource.shrink();\n    }\n\n    @Override\n    public int getWaitThreadCount() {\n        return dataSource.getWaitThreadCount();\n    }\n\n    @Override\n    public int getLockQueueLength() {\n        return dataSource.getLockQueueLength();\n    }\n\n    @Override\n    public void close() {\n        dataSource.close();\n    }\n\n    // ///////////////\n\n    private String overrideDefaultUser;\n    private String overrideDefaultPassword;\n    private int propertyCycle;\n    private boolean usesTraditionalReflectiveProxies;\n    private String userOverridesAsString;\n    private int maxAdministrativeTaskTime;\n    private int maxIdleTimeExcessConnections;\n    private int maxConnectionAge;\n    private String connectionCustomizerClassName;\n    private String factoryClassLocation;\n    private int acquireIncrement = 1;\n\n    private String connectionTesterClassName;\n    private String automaticTestTable;\n\n    public String getConnectionTesterClassName() {\n        return connectionTesterClassName;\n    }\n\n    public void setConnectionTesterClassName(String connectionTesterClassName) {\n        this.connectionTesterClassName = connectionTesterClassName;\n    }\n\n    public String getAutomaticTestTable() {\n        return automaticTestTable;\n    }\n\n    public void setAutomaticTestTable(String automaticTestTable) {\n        this.automaticTestTable = automaticTestTable;\n    }\n\n    private boolean forceIgnoreUnresolvedTransactions;\n\n    public boolean isForceIgnoreUnresolvedTransactions() {\n        return forceIgnoreUnresolvedTransactions;\n    }\n\n    public void setForceIgnoreUnresolvedTransactions(boolean forceIgnoreUnresolvedTransactions) {\n        this.forceIgnoreUnresolvedTransactions = forceIgnoreUnresolvedTransactions;\n    }\n\n    public boolean isUsesTraditionalReflectiveProxies() {\n        return usesTraditionalReflectiveProxies;\n    }\n\n    public void setUsesTraditionalReflectiveProxies(boolean usesTraditionalReflectiveProxies) {\n        this.usesTraditionalReflectiveProxies = usesTraditionalReflectiveProxies;\n    }\n\n    public String getUserOverridesAsString() {\n        return userOverridesAsString;\n    }\n\n    public void setUserOverridesAsString(String userOverridesAsString) {\n        this.userOverridesAsString = userOverridesAsString;\n    }\n\n    public int getMaxAdministrativeTaskTime() {\n        return maxAdministrativeTaskTime;\n    }\n\n    public void setMaxAdministrativeTaskTime(int maxAdministrativeTaskTime) {\n        this.maxAdministrativeTaskTime = maxAdministrativeTaskTime;\n    }\n\n    public int getMaxIdleTimeExcessConnections() {\n        return maxIdleTimeExcessConnections;\n    }\n\n    public void setMaxIdleTimeExcessConnections(int maxIdleTimeExcessConnections) {\n        this.maxIdleTimeExcessConnections = maxIdleTimeExcessConnections;\n    }\n\n    public int getMaxConnectionAge() {\n        return maxConnectionAge;\n    }\n\n    public void setMaxConnectionAge(int maxConnectionAge) {\n        this.maxConnectionAge = maxConnectionAge;\n    }\n\n    public String getConnectionCustomizerClassName() {\n        return connectionCustomizerClassName;\n    }\n\n    public void setConnectionCustomizerClassName(String connectionCustomizerClassName) {\n        this.connectionCustomizerClassName = connectionCustomizerClassName;\n    }\n\n    public String getFactoryClassLocation() {\n        return factoryClassLocation;\n    }\n\n    public void setFactoryClassLocation(String factoryClassLocation) {\n        this.factoryClassLocation = factoryClassLocation;\n    }\n\n    public int getAcquireIncrement() {\n        return acquireIncrement;\n    }\n\n    public void setAcquireIncrement(int acquireIncrement) {\n        this.acquireIncrement = acquireIncrement;\n    }\n\n    public String getOverrideDefaultUser() {\n        return overrideDefaultUser;\n    }\n\n    public void setOverrideDefaultUser(String overrideDefaultUser) {\n        this.overrideDefaultUser = overrideDefaultUser;\n    }\n\n    public String getOverrideDefaultPassword() {\n        return overrideDefaultPassword;\n    }\n\n    public void setOverrideDefaultPassword(String overrideDefaultPassword) {\n        this.overrideDefaultPassword = overrideDefaultPassword;\n    }\n\n    public int getPropertyCycle() {\n        return propertyCycle;\n    }\n\n    public void setPropertyCycle(int propertyCycle) {\n        this.propertyCycle = propertyCycle;\n    }\n\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        return dataSource.getParentLogger();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceC3P0AdapterMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.util.Properties;\n\npublic interface DruidDataSourceC3P0AdapterMBean {\n    String getDriverClass();\n\n    String getJdbcUrl();\n\n    Properties getProperties();\n\n    String getUser();\n\n    int getCheckoutTimeout();\n\n    boolean isAutoCommitOnClose();\n\n    int getIdleConnectionTestPeriod();\n\n    int getInitialPoolSize();\n\n    int getMaxIdleTime();\n\n    int getMaxPoolSize();\n\n    int getMinPoolSize();\n\n    boolean isTestConnectionOnCheckout();\n\n    boolean isTestConnectionOnCheckin();\n\n    String getPreferredTestQuery();\n\n    int getNumIdleConnections();\n\n    int getNumConnections();\n\n    String getDataSourceName();\n\n    int getNumBusyConnections();\n\n    // //////////\n\n    boolean isEnable();\n\n    void shrink();\n\n    String toString();\n\n    int getWaitThreadCount();\n\n    int getLockQueueLength();\n\n    void close();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.naming.Context;\nimport javax.naming.Name;\nimport javax.naming.RefAddr;\nimport javax.naming.Reference;\nimport javax.naming.spi.ObjectFactory;\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.*;\n\npublic class DruidDataSourceFactory implements ObjectFactory {\n    private static final Log LOG = LogFactory.getLog(DruidDataSourceFactory.class);\n\n    static final int UNKNOWN_TRANSACTIONISOLATION = -1;\n\n    public static final String PROP_DEFAULTAUTOCOMMIT = \"defaultAutoCommit\";\n    public static final String PROP_DEFAULTREADONLY = \"defaultReadOnly\";\n    public static final String PROP_DEFAULTTRANSACTIONISOLATION = \"defaultTransactionIsolation\";\n    public static final String PROP_DEFAULTCATALOG = \"defaultCatalog\";\n    public static final String PROP_DRIVERCLASSNAME = \"driverClassName\";\n    public static final String PROP_MAXACTIVE = \"maxActive\";\n    public static final String PROP_MAXIDLE = \"maxIdle\";\n    public static final String PROP_MINIDLE = \"minIdle\";\n    public static final String PROP_INITIALSIZE = \"initialSize\";\n    public static final String PROP_MAXWAIT = \"maxWait\";\n    public static final String PROP_TESTONBORROW = \"testOnBorrow\";\n    public static final String PROP_TESTONRETURN = \"testOnReturn\";\n    public static final String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = \"timeBetweenEvictionRunsMillis\";\n    public static final String PROP_NUMTESTSPEREVICTIONRUN = \"numTestsPerEvictionRun\";\n    public static final String PROP_MINEVICTABLEIDLETIMEMILLIS = \"minEvictableIdleTimeMillis\";\n    public static final String PROP_MAXEVICTABLEIDLETIMEMILLIS = \"maxEvictableIdleTimeMillis\";\n    public static final String PROP_PHY_TIMEOUT_MILLIS = \"phyTimeoutMillis\";\n    public static final String PROP_TESTWHILEIDLE = \"testWhileIdle\";\n    public static final String PROP_PASSWORD = \"password\";\n    public static final String PROP_URL = \"url\";\n    public static final String PROP_USERNAME = \"username\";\n    public static final String PROP_VALIDATIONQUERY = \"validationQuery\";\n    public static final String PROP_VALIDATIONQUERY_TIMEOUT = \"validationQueryTimeout\";\n    public static final String PROP_INITCONNECTIONSQLS = \"initConnectionSqls\";\n    public static final String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = \"accessToUnderlyingConnectionAllowed\";\n    public static final String PROP_REMOVEABANDONED = \"removeAbandoned\";\n    public static final String PROP_REMOVEABANDONEDTIMEOUT = \"removeAbandonedTimeout\";\n    public static final String PROP_LOGABANDONED = \"logAbandoned\";\n    public static final String PROP_POOLPREPAREDSTATEMENTS = \"poolPreparedStatements\";\n    public static final String PROP_MAXOPENPREPAREDSTATEMENTS = \"maxOpenPreparedStatements\";\n    public static final String PROP_CONNECTIONPROPERTIES = \"connectionProperties\";\n    public static final String PROP_FILTERS = \"filters\";\n    public static final String PROP_EXCEPTION_SORTER = \"exceptionSorter\";\n    public static final String PROP_EXCEPTION_SORTER_CLASS_NAME = \"exception-sorter-class-name\";\n    public static final String PROP_NAME = \"name\";\n    public static final String PROP_INIT = \"init\";\n\n    public static final String PROP_CONNECT_TIMEOUT = \"connectTimeout\";\n    public static final String PROP_SOCKET_TIMEOUT = \"socketTimeout\";\n    private static final String[] ALL_PROPERTIES = {\n            PROP_DEFAULTAUTOCOMMIT,\n            PROP_DEFAULTREADONLY,\n            PROP_DEFAULTTRANSACTIONISOLATION,\n            PROP_DEFAULTCATALOG,\n            PROP_DRIVERCLASSNAME,\n            PROP_MAXACTIVE,\n            PROP_MAXIDLE,\n            PROP_MINIDLE,\n            PROP_INITIALSIZE,\n            PROP_MAXWAIT,\n            PROP_TESTONBORROW,\n            PROP_TESTONRETURN,\n            PROP_TIMEBETWEENEVICTIONRUNSMILLIS,\n            PROP_NUMTESTSPEREVICTIONRUN,\n            PROP_MINEVICTABLEIDLETIMEMILLIS,\n            PROP_MAXEVICTABLEIDLETIMEMILLIS,\n            PROP_TESTWHILEIDLE,\n            PROP_PASSWORD,\n            PROP_FILTERS,\n            PROP_URL,\n            PROP_USERNAME,\n            PROP_VALIDATIONQUERY,\n            PROP_VALIDATIONQUERY_TIMEOUT,\n            PROP_INITCONNECTIONSQLS,\n            PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,\n            PROP_REMOVEABANDONED,\n            PROP_REMOVEABANDONEDTIMEOUT,\n            PROP_LOGABANDONED,\n            PROP_POOLPREPAREDSTATEMENTS,\n            PROP_MAXOPENPREPAREDSTATEMENTS,\n            PROP_CONNECTIONPROPERTIES,\n            PROP_EXCEPTION_SORTER,\n            PROP_EXCEPTION_SORTER_CLASS_NAME,\n            PROP_INIT,\n            PROP_NAME,\n            PROP_CONNECT_TIMEOUT,\n            PROP_SOCKET_TIMEOUT,\n\n            \"druid.timeBetweenLogStatsMillis\",\n            \"druid.stat.sql.MaxSize\",\n            \"druid.clearFiltersEnable\",\n            \"druid.resetStatEnable\", //\n            \"druid.notFullTimeoutRetryCount\", //\n            \"druid.maxWaitThreadCount\", //\n            \"druid.failFast\", //\n            \"druid.phyTimeoutMillis\", //\n            \"druid.wall.tenantColumn\", //\n            \"druid.wall.updateAllow\", //\n            \"druid.wall.deleteAllow\", //\n            \"druid.wall.insertAllow\", //\n            \"druid.wall.selelctAllow\", //\n            \"druid.wall.multiStatementAllow\", //\n    };\n\n    @Override\n    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)\n            throws Exception {\n        // We only know how to deal with <code>javax.naming.Reference</code>s\n        // that specify a class name of \"javax.sql.DataSource\"\n        if ((obj == null) || !(obj instanceof Reference)) {\n            return null;\n        }\n        Reference ref = (Reference) obj;\n\n        if ((!\"javax.sql.DataSource\".equals(ref.getClassName())) //\n                && (!\"com.alibaba.druid.pool.DruidDataSource\".equals(ref.getClassName())) //\n        ) {\n            return null;\n        }\n\n        Properties properties = new Properties();\n        for (int i = 0; i < ALL_PROPERTIES.length; i++) {\n            String propertyName = ALL_PROPERTIES[i];\n            RefAddr ra = ref.get(propertyName);\n            if (ra != null) {\n                String propertyValue = ra.getContent().toString();\n                properties.setProperty(propertyName, propertyValue);\n            }\n        }\n\n        return createDataSourceInternal(properties);\n    }\n\n    protected DataSource createDataSourceInternal(Properties properties) throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        config(dataSource, properties);\n        return dataSource;\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public static DataSource createDataSource(Properties properties) throws Exception {\n        return createDataSource((Map) properties);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public static DataSource createDataSource(Map properties) throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        config(dataSource, properties);\n        return dataSource;\n    }\n\n    @SuppressWarnings({\"deprecation\", \"rawtypes\"})\n    public static void config(DruidDataSource dataSource, Map<?, ?> properties) throws SQLException {\n        String value = null;\n\n        value = (String) properties.get(PROP_NAME);\n        if (value != null) {\n            dataSource.setName(value);\n        }\n\n        value = (String) properties.get(PROP_DEFAULTAUTOCOMMIT);\n        if (value != null) {\n            dataSource.setDefaultAutoCommit(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_DEFAULTREADONLY);\n        if (value != null) {\n            dataSource.setDefaultReadOnly(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_DEFAULTTRANSACTIONISOLATION);\n        if (value != null) {\n            int level = UNKNOWN_TRANSACTIONISOLATION;\n            if (\"NONE\".equalsIgnoreCase(value)) {\n                level = Connection.TRANSACTION_NONE;\n            } else if (\"READ_COMMITTED\".equalsIgnoreCase(value)) {\n                level = Connection.TRANSACTION_READ_COMMITTED;\n            } else if (\"READ_UNCOMMITTED\".equalsIgnoreCase(value)) {\n                level = Connection.TRANSACTION_READ_UNCOMMITTED;\n            } else if (\"REPEATABLE_READ\".equalsIgnoreCase(value)) {\n                level = Connection.TRANSACTION_REPEATABLE_READ;\n            } else if (\"SERIALIZABLE\".equalsIgnoreCase(value)) {\n                level = Connection.TRANSACTION_SERIALIZABLE;\n            } else {\n                try {\n                    level = Integer.parseInt(value);\n                } catch (NumberFormatException e) {\n                    LOG.error(\"Could not parse defaultTransactionIsolation: \" + value);\n                    LOG.error(\"WARNING: defaultTransactionIsolation not set\");\n                    LOG.error(\"using default value of database driver\");\n                    level = UNKNOWN_TRANSACTIONISOLATION;\n                }\n            }\n            dataSource.setDefaultTransactionIsolation(level);\n        }\n\n        value = (String) properties.get(PROP_DEFAULTCATALOG);\n        if (value != null) {\n            dataSource.setDefaultCatalog(value);\n        }\n\n        value = (String) properties.get(PROP_DRIVERCLASSNAME);\n        if (value != null) {\n            dataSource.setDriverClassName(value);\n        }\n\n        value = (String) properties.get(PROP_MAXACTIVE);\n        if (value != null) {\n            dataSource.setMaxActive(Integer.parseInt(value));\n        }\n\n        value = (String) properties.get(PROP_MAXIDLE);\n        if (value != null) {\n            dataSource.setMaxIdle(Integer.parseInt(value));\n        }\n\n        value = (String) properties.get(PROP_MINIDLE);\n        if (value != null) {\n            dataSource.setMinIdle(Integer.parseInt(value));\n        }\n\n        value = (String) properties.get(PROP_INITIALSIZE);\n        if (value != null) {\n            dataSource.setInitialSize(Integer.parseInt(value));\n        }\n\n        value = (String) properties.get(PROP_MAXWAIT);\n        if (value != null) {\n            dataSource.setMaxWait(Long.parseLong(value));\n        }\n\n        value = (String) properties.get(PROP_TESTONBORROW);\n        if (value != null) {\n            dataSource.setTestOnBorrow(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_TESTONRETURN);\n        if (value != null) {\n            dataSource.setTestOnReturn(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_TIMEBETWEENEVICTIONRUNSMILLIS);\n        if (value != null) {\n            dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(value));\n        }\n\n        value = (String) properties.get(PROP_NUMTESTSPEREVICTIONRUN);\n        if (value != null) {\n            dataSource.setNumTestsPerEvictionRun(Integer.parseInt(value));\n        }\n\n        value = (String) properties.get(PROP_MINEVICTABLEIDLETIMEMILLIS);\n        if (value != null) {\n            dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(value));\n        }\n\n        value = (String) properties.get(PROP_MAXEVICTABLEIDLETIMEMILLIS);\n        if (value != null) {\n            dataSource.setMaxEvictableIdleTimeMillis(Long.parseLong(value));\n        }\n\n        value = (String) properties.get(PROP_PHY_TIMEOUT_MILLIS);\n        if (value != null) {\n            dataSource.setPhyTimeoutMillis(Long.parseLong(value));\n        }\n\n        value = (String) properties.get(PROP_TESTWHILEIDLE);\n        if (value != null) {\n            dataSource.setTestWhileIdle(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_PASSWORD);\n        if (value != null) {\n            dataSource.setPassword(value);\n        }\n\n        value = (String) properties.get(PROP_URL);\n        if (value != null) {\n            dataSource.setUrl(value);\n        }\n\n        value = (String) properties.get(PROP_USERNAME);\n        if (value != null) {\n            dataSource.setUsername(value);\n        }\n\n        value = (String) properties.get(PROP_VALIDATIONQUERY);\n        if (value != null) {\n            dataSource.setValidationQuery(value);\n        }\n\n        value = (String) properties.get(PROP_VALIDATIONQUERY_TIMEOUT);\n        if (value != null) {\n            dataSource.setValidationQueryTimeout(Integer.parseInt(value));\n        }\n\n        value = (String) properties.get(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED);\n        if (value != null) {\n            dataSource.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_REMOVEABANDONED);\n        if (value != null) {\n            dataSource.setRemoveAbandoned(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_REMOVEABANDONEDTIMEOUT);\n        if (value != null) {\n            dataSource.setRemoveAbandonedTimeout(Integer.parseInt(value));\n        }\n\n        value = (String) properties.get(PROP_LOGABANDONED);\n        if (value != null) {\n            dataSource.setLogAbandoned(Boolean.valueOf(value).booleanValue());\n        }\n\n        value = (String) properties.get(PROP_POOLPREPAREDSTATEMENTS);\n        if (value != null) {\n            boolean poolPreparedStatements = Boolean.valueOf(value).booleanValue();\n            dataSource.setPoolPreparedStatements(poolPreparedStatements);\n\n            if (poolPreparedStatements) {\n                value = (String) properties.get(PROP_MAXOPENPREPAREDSTATEMENTS);\n                if (value != null) {\n                    dataSource.setMaxOpenPreparedStatements(Integer.parseInt(value));\n                }\n            }\n        }\n\n        value = (String) properties.get(PROP_FILTERS);\n        if (value != null) {\n            dataSource.setFilters(value);\n        }\n\n        value = (String) properties.get(PROP_EXCEPTION_SORTER);\n        if (value != null) {\n            dataSource.setExceptionSorter(value);\n        }\n\n        value = (String) properties.get(PROP_EXCEPTION_SORTER_CLASS_NAME);\n        if (value != null) {\n            dataSource.setExceptionSorter(value);\n        }\n\n        value = (String) properties.get(PROP_INITCONNECTIONSQLS);\n        if (value != null) {\n            StringTokenizer tokenizer = new StringTokenizer(value, \";\");\n            dataSource.setConnectionInitSqls(Collections.list(tokenizer));\n        }\n\n        value = (String) properties.get(PROP_CONNECTIONPROPERTIES);\n        if (value != null) {\n            dataSource.setConnectionProperties(value);\n        }\n        value = (String) properties.get(PROP_SOCKET_TIMEOUT);\n        if (value != null) {\n            dataSource.setSocketTimeout(Integer.parseInt(value));\n        }\n        value = (String) properties.get(PROP_CONNECT_TIMEOUT);\n        if (value != null) {\n            dataSource.setConnectTimeout(Integer.parseInt(value));\n        }\n\n        {\n            Properties dataSourceProperties = null;\n            for (Map.Entry entry : properties.entrySet()) {\n                String entryKey = (String) entry.getKey();\n                if (entryKey.startsWith(\"druid.\")) {\n                    if (dataSourceProperties == null) {\n                        dataSourceProperties = new Properties();\n                    }\n\n                    String entryValue = (String) entry.getValue();\n                    dataSourceProperties.put(entryKey, entryValue);\n                }\n            }\n            if (dataSourceProperties != null) {\n                dataSource.configFromPropeties(dataSourceProperties);\n            }\n        }\n\n        value = (String) properties.get(PROP_INIT);\n        if (\"true\".equals(value)) {\n            dataSource.init();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport javax.management.ObjectName;\n\nimport java.sql.SQLException;\nimport java.util.Date;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface DruidDataSourceMBean extends DruidAbstractDataSourceMBean {\n    long getResetCount();\n\n    boolean isEnable();\n\n    String getUrl();\n\n    void shrink();\n\n    int removeAbandoned();\n\n    String dump();\n\n    int getWaitThreadCount();\n\n    int getLockQueueLength();\n\n    long getNotEmptyWaitCount();\n\n    int getNotEmptyWaitThreadCount();\n\n    long getNotEmptySignalCount();\n\n    long getNotEmptyWaitMillis();\n\n    long getNotEmptyWaitNanos();\n\n    void resetStat();\n\n    boolean isResetStatEnable();\n\n    void setResetStatEnable(boolean resetStatEnable);\n\n    String getVersion();\n\n    void setPoolPreparedStatements(boolean poolPreparedStatements);\n\n    int getActivePeak();\n\n    int getPoolingPeak();\n\n    Date getActivePeakTime();\n\n    Date getPoolingPeakTime();\n\n    long getErrorCount();\n\n    ObjectName getObjectName();\n\n    void clearStatementCache() throws SQLException;\n\n    long getDiscardCount();\n\n    void setStatLoggerClassName(String className);\n\n    long getTimeBetweenLogStatsMillis();\n\n    void setTimeBetweenLogStatsMillis(long timeBetweenLogStatsMillis);\n\n    void setConnectionProperties(String connectionProperties);\n\n    int fill() throws SQLException;\n\n    int fill(int toCount) throws SQLException;\n\n    boolean isUseGlobalDataSourceStat();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLogger.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n * @since 0.2.19\n */\npublic interface DruidDataSourceStatLogger {\n    void log(DruidDataSourceStatValue statValue);\n\n    /**\n     * @param properties the properties to be used for configuration\n     * @since 0.2.21\n     */\n    void configFromProperties(Properties properties);\n\n    void setLogger(Log logger);\n\n    void setLoggerName(String loggerName);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerAdapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n * @since 0.2.21\n */\npublic class DruidDataSourceStatLoggerAdapter implements DruidDataSourceStatLogger {\n    @Override\n    public void log(DruidDataSourceStatValue statValue) {\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n\n    @Override\n    public void setLogger(Log logger) {\n    }\n\n    @Override\n    public void setLoggerName(String loggerName) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.stat.JdbcSqlStatValue;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.rtrim;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n * @since 0.2.19\n */\npublic class DruidDataSourceStatLoggerImpl extends DruidDataSourceStatLoggerAdapter {\n    private static Log LOG = LogFactory.getLog(DruidDataSourceStatLoggerImpl.class);\n\n    private Log logger = LOG;\n\n    public DruidDataSourceStatLoggerImpl() {\n        this.configFromProperties(System.getProperties());\n    }\n\n    /**\n     * @since 0.2.21\n     */\n    @Override\n    public void configFromProperties(Properties properties) {\n        if (properties == null) {\n            return;\n        }\n\n        String property = properties.getProperty(\"druid.stat.loggerName\");\n        if (property != null && property.length() > 0) {\n            setLoggerName(property);\n        }\n    }\n\n    public Log getLogger() {\n        return logger;\n    }\n\n    @Override\n    public void setLoggerName(String loggerName) {\n        logger = LogFactory.getLog(loggerName);\n    }\n\n    @Override\n    public void setLogger(Log logger) {\n        if (logger == null) {\n            throw new IllegalArgumentException(\"logger can not be null\");\n        }\n        this.logger = logger;\n    }\n\n    public boolean isLogEnable() {\n        return logger.isInfoEnabled();\n    }\n\n    public void log(String value) {\n        logger.info(value);\n    }\n\n    @Override\n    public void log(DruidDataSourceStatValue statValue) {\n        if (!isLogEnable()) {\n            return;\n        }\n        Map<String, Object> map = new LinkedHashMap<String, Object>();\n\n        map.put(\"url\", statValue.url);\n        map.put(\"dbType\", statValue.getDbType());\n        map.put(\"name\", statValue.getName());\n        map.put(\"activeCount\", statValue.getActiveCount());\n\n        if (statValue.getActivePeak() > 0) {\n            map.put(\"activePeak\", statValue.getActivePeak());\n            map.put(\"activePeakTime\", statValue.getActivePeakTime());\n        }\n        map.put(\"poolingCount\", statValue.getPoolingCount());\n        if (statValue.getPoolingPeak() > 0) {\n            map.put(\"poolingPeak\", statValue.getPoolingPeak());\n            map.put(\"poolingPeakTime\", statValue.getPoolingPeakTime());\n        }\n        map.put(\"connectCount\", statValue.getConnectCount());\n        map.put(\"closeCount\", statValue.getCloseCount());\n\n        if (statValue.getWaitThreadCount() > 0) {\n            map.put(\"waitThreadCount\", statValue.getWaitThreadCount());\n        }\n\n        if (statValue.getNotEmptyWaitCount() > 0) {\n            map.put(\"notEmptyWaitCount\", statValue.getNotEmptyWaitCount());\n        }\n\n        if (statValue.getNotEmptyWaitMillis() > 0) {\n            map.put(\"notEmptyWaitMillis\", statValue.getNotEmptyWaitMillis());\n        }\n\n        if (statValue.getLogicConnectErrorCount() > 0) {\n            map.put(\"logicConnectErrorCount\", statValue.getLogicConnectErrorCount());\n        }\n\n        if (statValue.getPhysicalConnectCount() > 0) {\n            map.put(\"physicalConnectCount\", statValue.getPhysicalConnectCount());\n        }\n\n        if (statValue.getPhysicalCloseCount() > 0) {\n            map.put(\"physicalCloseCount\", statValue.getPhysicalCloseCount());\n        }\n\n        if (statValue.getPhysicalConnectErrorCount() > 0) {\n            map.put(\"physicalConnectErrorCount\", statValue.getPhysicalConnectErrorCount());\n        }\n\n        if (statValue.getExecuteCount() > 0) {\n            map.put(\"executeCount\", statValue.getExecuteCount());\n        }\n\n        if (statValue.getErrorCount() > 0) {\n            map.put(\"errorCount\", statValue.getErrorCount());\n        }\n\n        if (statValue.getCommitCount() > 0) {\n            map.put(\"commitCount\", statValue.getCommitCount());\n        }\n\n        if (statValue.getRollbackCount() > 0) {\n            map.put(\"rollbackCount\", statValue.getRollbackCount());\n        }\n\n        if (statValue.getPstmtCacheHitCount() > 0) {\n            map.put(\"pstmtCacheHitCount\", statValue.getPstmtCacheHitCount());\n        }\n\n        if (statValue.getPstmtCacheMissCount() > 0) {\n            map.put(\"pstmtCacheMissCount\", statValue.getPstmtCacheMissCount());\n        }\n\n        if (statValue.getStartTransactionCount() > 0) {\n            map.put(\"startTransactionCount\", statValue.getStartTransactionCount());\n            map.put(\"transactionHistogram\", rtrim(statValue.getTransactionHistogram()));\n        }\n\n        if (statValue.getConnectCount() > 0) {\n            map.put(\"connectionHoldTimeHistogram\", rtrim(statValue.getConnectionHoldTimeHistogram()));\n        }\n\n        if (statValue.getClobOpenCount() > 0) {\n            map.put(\"clobOpenCount\", statValue.getClobOpenCount());\n        }\n\n        if (statValue.getBlobOpenCount() > 0) {\n            map.put(\"blobOpenCount\", statValue.getBlobOpenCount());\n        }\n\n        if (statValue.getSqlSkipCount() > 0) {\n            map.put(\"sqlSkipCount\", statValue.getSqlSkipCount());\n        }\n\n        ArrayList<Map<String, Object>> sqlList = new ArrayList<Map<String, Object>>();\n        if (statValue.sqlList.size() > 0) {\n            for (JdbcSqlStatValue sqlStat : statValue.getSqlList()) {\n                Map<String, Object> sqlStatMap = new LinkedHashMap<String, Object>();\n                sqlStatMap.put(\"sql\", sqlStat.getSql());\n\n                if (sqlStat.getExecuteCount() > 0) {\n                    sqlStatMap.put(\"executeCount\", sqlStat.getExecuteCount());\n                    sqlStatMap.put(\"executeMillisMax\", sqlStat.getExecuteMillisMax());\n                    sqlStatMap.put(\"executeMillisTotal\", sqlStat.getExecuteMillisTotal());\n\n                    sqlStatMap.put(\"executeHistogram\", rtrim(sqlStat.getExecuteHistogram()));\n                    sqlStatMap.put(\"executeAndResultHoldHistogram\", rtrim(sqlStat.getExecuteAndResultHoldHistogram()));\n                }\n\n                long executeErrorCount = sqlStat.getExecuteErrorCount();\n                if (executeErrorCount > 0) {\n                    sqlStatMap.put(\"executeErrorCount\", executeErrorCount);\n                }\n\n                int runningCount = sqlStat.getRunningCount();\n                if (runningCount > 0) {\n                    sqlStatMap.put(\"runningCount\", runningCount);\n                }\n\n                int concurrentMax = sqlStat.getConcurrentMax();\n                if (concurrentMax > 0) {\n                    sqlStatMap.put(\"concurrentMax\", concurrentMax);\n                }\n\n                if (sqlStat.getFetchRowCount() > 0) {\n                    sqlStatMap.put(\"fetchRowCount\", sqlStat.getFetchRowCount());\n                    sqlStatMap.put(\"fetchRowCountMax\", sqlStat.getFetchRowCountMax());\n                    sqlStatMap.put(\"fetchRowHistogram\", rtrim(sqlStat.getFetchRowHistogram()));\n                }\n\n                if (sqlStat.getUpdateCount() > 0) {\n                    sqlStatMap.put(\"updateCount\", sqlStat.getUpdateCount());\n                    sqlStatMap.put(\"updateCountMax\", sqlStat.getUpdateCountMax());\n                    sqlStatMap.put(\"updateHistogram\", rtrim(sqlStat.getUpdateHistogram()));\n                }\n\n                if (sqlStat.getInTransactionCount() > 0) {\n                    sqlStatMap.put(\"inTransactionCount\", sqlStat.getInTransactionCount());\n                }\n\n                if (sqlStat.getClobOpenCount() > 0) {\n                    sqlStatMap.put(\"clobOpenCount\", sqlStat.getClobOpenCount());\n                }\n\n                if (sqlStat.getBlobOpenCount() > 0) {\n                    sqlStatMap.put(\"blobOpenCount\", sqlStat.getBlobOpenCount());\n                }\n\n                sqlList.add(sqlStatMap);\n            }\n\n            map.put(\"sqlList\", sqlList);\n        }\n\n        if (statValue.getKeepAliveCheckCount() > 0) {\n            map.put(\"keepAliveCheckCount\", statValue.getKeepAliveCheckCount());\n        }\n\n        String text = JSONUtils.toJSONString(map);\n\n        log(text);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.stat.JdbcSqlStatValue;\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\n\nimport java.util.Date;\nimport java.util.List;\n\n@MTable(name = \"druid_datasource\")\npublic class DruidDataSourceStatValue {\n    @MField(groupBy = true, aggregate = AggregateType.None)\n    protected String name;\n\n    @MField(aggregate = AggregateType.None)\n    protected String dbType;\n\n    @MField(aggregate = AggregateType.None)\n    protected String driverClassName;\n\n    protected String url;\n    protected String userName;\n    protected List<String> filterClassNames;\n    protected boolean removeAbandoned;\n\n    protected int initialSize;\n    protected int minIdle;\n    protected int maxActive;\n    protected int queryTimeout;\n    protected int transactionQueryTimeout;\n    protected int loginTimeout;\n    protected String validConnectionCheckerClassName;\n    protected String exceptionSorterClassName;\n    protected boolean testOnBorrow;\n    protected boolean testOnReturn;\n    protected boolean testWhileIdle;\n    protected boolean defaultAutoCommit;\n    protected boolean defaultReadOnly;\n    protected Integer defaultTransactionIsolation;\n\n    @MField(aggregate = AggregateType.Last)\n    protected int activeCount;\n\n    @MField(aggregate = AggregateType.Max)\n    protected int activePeak;\n\n    @MField(aggregate = AggregateType.Max)\n    protected long activePeakTime;\n\n    @MField(aggregate = AggregateType.Last)\n    protected int poolingCount;\n\n    @MField(aggregate = AggregateType.Max)\n    protected int poolingPeak;\n\n    @MField(aggregate = AggregateType.Max)\n    protected long poolingPeakTime;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long connectCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long closeCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long waitThreadCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long notEmptyWaitCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long notEmptyWaitNanos;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long logicConnectErrorCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long physicalConnectCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long physicalCloseCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long physicalConnectErrorCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long executeCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long errorCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long commitCount;\n    @MField(aggregate = AggregateType.Sum)\n    protected long rollbackCount;\n    @MField(aggregate = AggregateType.Sum)\n    protected long pstmtCacheHitCount;\n    @MField(aggregate = AggregateType.Sum)\n    protected long pstmtCacheMissCount;\n    @MField(aggregate = AggregateType.Sum)\n    protected long startTransactionCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long keepAliveCheckCount;\n\n    // protected long[] transactionHistogram;\n    protected long[] connectionHoldTimeHistogram;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long txn_0_1;\n    @MField(aggregate = AggregateType.Sum)\n    protected long txn_1_10;\n    @MField(aggregate = AggregateType.Sum)\n    protected long txn_10_100;\n    @MField(aggregate = AggregateType.Sum)\n    protected long txn_100_1000;\n    @MField(aggregate = AggregateType.Sum)\n    protected long txn_1000_10000;\n    @MField(aggregate = AggregateType.Sum)\n    protected long txn_10000_100000;\n    @MField(aggregate = AggregateType.Sum)\n    protected long txn_more;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long clobOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long blobOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long sqlSkipCount;\n\n    protected List<JdbcSqlStatValue> sqlList;\n\n    public Date getPoolingPeakTime() {\n        if (poolingPeakTime <= 0) {\n            return null;\n        }\n\n        return new Date(poolingPeakTime);\n    }\n\n    public long getSqlSkipCount() {\n        return sqlSkipCount;\n    }\n\n    public void setSqlSkipCount(long sqlSkipCount) {\n        this.sqlSkipCount = sqlSkipCount;\n    }\n\n    public Date getActivePeakTime() {\n        if (activePeakTime <= 0) {\n            return null;\n        }\n\n        return new Date(activePeakTime);\n    }\n\n    public long getNotEmptyWaitMillis() {\n        return notEmptyWaitNanos / (1000 * 1000);\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(String dbType) {\n        this.dbType = dbType;\n    }\n\n    public String getDriverClassName() {\n        return driverClassName;\n    }\n\n    public void setDriverClassName(String driverClassName) {\n        this.driverClassName = driverClassName;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public String getUserName() {\n        return userName;\n    }\n\n    public void setUserName(String userName) {\n        this.userName = userName;\n    }\n\n    public List<String> getFilterClassNames() {\n        return filterClassNames;\n    }\n\n    public void setFilterClassNames(List<String> filterClassNames) {\n        this.filterClassNames = filterClassNames;\n    }\n\n    public boolean isRemoveAbandoned() {\n        return removeAbandoned;\n    }\n\n    public void setRemoveAbandoned(boolean removeAbandoned) {\n        this.removeAbandoned = removeAbandoned;\n    }\n\n    public int getInitialSize() {\n        return initialSize;\n    }\n\n    public void setInitialSize(int initialSize) {\n        this.initialSize = initialSize;\n    }\n\n    public int getMinIdle() {\n        return minIdle;\n    }\n\n    public void setMinIdle(int minIdle) {\n        this.minIdle = minIdle;\n    }\n\n    public int getMaxActive() {\n        return maxActive;\n    }\n\n    public void setMaxActive(int maxActive) {\n        this.maxActive = maxActive;\n    }\n\n    public int getQueryTimeout() {\n        return queryTimeout;\n    }\n\n    public void setQueryTimeout(int queryTimeout) {\n        this.queryTimeout = queryTimeout;\n    }\n\n    public int getTransactionQueryTimeout() {\n        return transactionQueryTimeout;\n    }\n\n    public void setTransactionQueryTimeout(int transactionQueryTimeout) {\n        this.transactionQueryTimeout = transactionQueryTimeout;\n    }\n\n    public int getLoginTimeout() {\n        return loginTimeout;\n    }\n\n    public void setLoginTimeout(int loginTimeout) {\n        this.loginTimeout = loginTimeout;\n    }\n\n    public String getValidConnectionCheckerClassName() {\n        return validConnectionCheckerClassName;\n    }\n\n    public void setValidConnectionCheckerClassName(String validConnectionCheckerClassName) {\n        this.validConnectionCheckerClassName = validConnectionCheckerClassName;\n    }\n\n    public String getExceptionSorterClassName() {\n        return exceptionSorterClassName;\n    }\n\n    public void setExceptionSorterClassName(String exceptionSorterClassName) {\n        this.exceptionSorterClassName = exceptionSorterClassName;\n    }\n\n    public boolean isTestOnBorrow() {\n        return testOnBorrow;\n    }\n\n    public void setTestOnBorrow(boolean testOnBorrow) {\n        this.testOnBorrow = testOnBorrow;\n    }\n\n    public boolean isTestOnReturn() {\n        return testOnReturn;\n    }\n\n    public void setTestOnReturn(boolean testOnReturn) {\n        this.testOnReturn = testOnReturn;\n    }\n\n    public boolean isTestWhileIdle() {\n        return testWhileIdle;\n    }\n\n    public void setTestWhileIdle(boolean testWhileIdle) {\n        this.testWhileIdle = testWhileIdle;\n    }\n\n    public boolean isDefaultAutoCommit() {\n        return defaultAutoCommit;\n    }\n\n    public void setDefaultAutoCommit(boolean defaultAutoCommit) {\n        this.defaultAutoCommit = defaultAutoCommit;\n    }\n\n    public boolean isDefaultReadOnly() {\n        return defaultReadOnly;\n    }\n\n    public void setDefaultReadOnly(boolean defaultReadOnly) {\n        this.defaultReadOnly = defaultReadOnly;\n    }\n\n    public Integer getDefaultTransactionIsolation() {\n        return defaultTransactionIsolation;\n    }\n\n    public void setDefaultTransactionIsolation(Integer defaultTransactionIsolation) {\n        this.defaultTransactionIsolation = defaultTransactionIsolation;\n    }\n\n    public int getActiveCount() {\n        return activeCount;\n    }\n\n    public void setActiveCount(int activeCount) {\n        this.activeCount = activeCount;\n    }\n\n    public int getActivePeak() {\n        return activePeak;\n    }\n\n    public void setActivePeak(int activePeak) {\n        this.activePeak = activePeak;\n    }\n\n    public int getPoolingCount() {\n        return poolingCount;\n    }\n\n    public void setPoolingCount(int poolingCount) {\n        this.poolingCount = poolingCount;\n    }\n\n    public int getPoolingPeak() {\n        return poolingPeak;\n    }\n\n    public void setPoolingPeak(int poolingPeak) {\n        this.poolingPeak = poolingPeak;\n    }\n\n    public long getConnectCount() {\n        return connectCount;\n    }\n\n    public void setConnectCount(long connectCount) {\n        this.connectCount = connectCount;\n    }\n\n    public long getCloseCount() {\n        return closeCount;\n    }\n\n    public void setCloseCount(long closeCount) {\n        this.closeCount = closeCount;\n    }\n\n    public long getWaitThreadCount() {\n        return waitThreadCount;\n    }\n\n    public void setWaitThreadCount(long waitThreadCount) {\n        this.waitThreadCount = waitThreadCount;\n    }\n\n    public long getNotEmptyWaitCount() {\n        return notEmptyWaitCount;\n    }\n\n    public void setNotEmptyWaitCount(long notEmptyWaitCount) {\n        this.notEmptyWaitCount = notEmptyWaitCount;\n    }\n\n    public long getNotEmptyWaitNanos() {\n        return notEmptyWaitNanos;\n    }\n\n    public void setNotEmptyWaitNanos(long notEmptyWaitNanos) {\n        this.notEmptyWaitNanos = notEmptyWaitNanos;\n    }\n\n    public long getLogicConnectErrorCount() {\n        return logicConnectErrorCount;\n    }\n\n    public void setLogicConnectErrorCount(long logicConnectErrorCount) {\n        this.logicConnectErrorCount = logicConnectErrorCount;\n    }\n\n    public long getPhysicalConnectCount() {\n        return physicalConnectCount;\n    }\n\n    public void setPhysicalConnectCount(long physicalConnectCount) {\n        this.physicalConnectCount = physicalConnectCount;\n    }\n\n    public long getPhysicalCloseCount() {\n        return physicalCloseCount;\n    }\n\n    public void setPhysicalCloseCount(long physicalCloseCount) {\n        this.physicalCloseCount = physicalCloseCount;\n    }\n\n    public long getPhysicalConnectErrorCount() {\n        return physicalConnectErrorCount;\n    }\n\n    public void setPhysicalConnectErrorCount(long physicalConnectErrorCount) {\n        this.physicalConnectErrorCount = physicalConnectErrorCount;\n    }\n\n    public long getExecuteCount() {\n        return executeCount;\n    }\n\n    public void setExecuteCount(long executeCount) {\n        this.executeCount = executeCount;\n    }\n\n    public long getErrorCount() {\n        return errorCount;\n    }\n\n    public void setErrorCount(long errorCount) {\n        this.errorCount = errorCount;\n    }\n\n    public long getCommitCount() {\n        return commitCount;\n    }\n\n    public void setCommitCount(long commitCount) {\n        this.commitCount = commitCount;\n    }\n\n    public long getRollbackCount() {\n        return rollbackCount;\n    }\n\n    public void setRollbackCount(long rollbackCount) {\n        this.rollbackCount = rollbackCount;\n    }\n\n    public long getPstmtCacheHitCount() {\n        return pstmtCacheHitCount;\n    }\n\n    public void setPstmtCacheHitCount(long pstmtCacheHitCount) {\n        this.pstmtCacheHitCount = pstmtCacheHitCount;\n    }\n\n    public long getPstmtCacheMissCount() {\n        return pstmtCacheMissCount;\n    }\n\n    public void setPstmtCacheMissCount(long pstmtCacheMissCount) {\n        this.pstmtCacheMissCount = pstmtCacheMissCount;\n    }\n\n    public long getStartTransactionCount() {\n        return startTransactionCount;\n    }\n\n    public void setStartTransactionCount(long startTransactionCount) {\n        this.startTransactionCount = startTransactionCount;\n    }\n\n    public long[] getTransactionHistogram() {\n        return new long[]{\n                txn_0_1, // txn_0_1\n                txn_1_10,\n                txn_10_100,\n                txn_100_1000,\n                txn_1000_10000,\n                txn_10000_100000,\n                txn_more, //\n        };\n    }\n\n    public void setTransactionHistogram(long[] values) {\n        txn_0_1 = values[0];\n        txn_1_10 = values[1];\n        txn_10_100 = values[2];\n        txn_100_1000 = values[3];\n        txn_1000_10000 = values[4];\n        txn_10000_100000 = values[5];\n        txn_more = values[6];\n    }\n\n    public long[] getConnectionHoldTimeHistogram() {\n        return connectionHoldTimeHistogram;\n    }\n\n    public void setConnectionHoldTimeHistogram(long[] connectionHoldTimeHistogram) {\n        this.connectionHoldTimeHistogram = connectionHoldTimeHistogram;\n    }\n\n    public long getClobOpenCount() {\n        return clobOpenCount;\n    }\n\n    public void setClobOpenCount(long clobOpenCount) {\n        this.clobOpenCount = clobOpenCount;\n    }\n\n    public long getBlobOpenCount() {\n        return blobOpenCount;\n    }\n\n    public void setBlobOpenCount(long blobOpenCount) {\n        this.blobOpenCount = blobOpenCount;\n    }\n\n    public List<JdbcSqlStatValue> getSqlList() {\n        return sqlList;\n    }\n\n    public void setSqlList(List<JdbcSqlStatValue> sqlList) {\n        this.sqlList = sqlList;\n    }\n\n    public void setActivePeakTime(long activePeakTime) {\n        this.activePeakTime = activePeakTime;\n    }\n\n    public void setPoolingPeakTime(long poolingPeakTime) {\n        this.poolingPeakTime = poolingPeakTime;\n    }\n\n    public long getKeepAliveCheckCount() {\n        return keepAliveCheckCount;\n    }\n\n    public void setKeepAliveCheckCount(long keepAliveCheckCount) {\n        this.keepAliveCheckCount = keepAliveCheckCount;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidPooledCallableStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxy;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.Calendar;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidPooledCallableStatement extends DruidPooledPreparedStatement implements CallableStatement {\n    private CallableStatement stmt;\n\n    public DruidPooledCallableStatement(DruidPooledConnection conn,\n                                        PreparedStatementHolder holder) throws SQLException {\n        super(conn, holder);\n        this.stmt = (CallableStatement) holder.statement;\n    }\n\n    public CallableStatement getCallableStatementRaw() {\n        return stmt;\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {\n        try {\n            stmt.registerOutParameter(parameterIndex, sqlType);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {\n        try {\n            stmt.registerOutParameter(parameterIndex, sqlType, scale);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean wasNull() throws SQLException {\n        try {\n            return stmt.wasNull();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getString(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getString(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean getBoolean(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getBoolean(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte getByte(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getByte(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public short getShort(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getShort(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getInt(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getInt(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public long getLong(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getLong(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public float getFloat(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getFloat(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public double getDouble(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getDouble(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    @Deprecated\n    public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {\n        try {\n            return stmt.getBigDecimal(parameterIndex, scale);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte[] getBytes(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getBytes(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getDate(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getTime(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getTimestamp(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Object getObject(int parameterIndex) throws SQLException {\n        try {\n            Object obj = stmt.getObject(parameterIndex);\n            return wrapObject(obj);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    private Object wrapObject(Object obj) {\n        if (obj instanceof ResultSet) {\n            ResultSet rs = (ResultSet) obj;\n\n            DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);\n            addResultSetTrace(poolableResultSet);\n\n            obj = poolableResultSet;\n        }\n\n        return obj;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getBigDecimal(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Object getObject(int parameterIndex, java.util.Map<String, Class<?>> map) throws SQLException {\n        try {\n            Object obj = stmt.getObject(parameterIndex, map);\n            return wrapObject(obj);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Ref getRef(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getRef(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Blob getBlob(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getBlob(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Clob getClob(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getClob(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Array getArray(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getArray(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(int parameterIndex, Calendar cal) throws SQLException {\n        try {\n            return stmt.getDate(parameterIndex, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(int parameterIndex, Calendar cal) throws SQLException {\n        try {\n            return stmt.getTime(parameterIndex, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {\n        try {\n            return stmt.getTimestamp(parameterIndex, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {\n        try {\n            stmt.registerOutParameter(parameterIndex, sqlType, typeName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType) throws SQLException {\n        try {\n            stmt.registerOutParameter(parameterName, sqlType);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {\n        try {\n            stmt.registerOutParameter(parameterName, sqlType, scale);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {\n        try {\n            stmt.registerOutParameter(parameterName, sqlType, typeName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.net.URL getURL(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getURL(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setURL(String parameterName, java.net.URL val) throws SQLException {\n        try {\n            stmt.setURL(parameterName, val);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNull(String parameterName, int sqlType) throws SQLException {\n        try {\n            stmt.setNull(parameterName, sqlType);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBoolean(String parameterName, boolean x) throws SQLException {\n        try {\n            stmt.setBoolean(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setByte(String parameterName, byte x) throws SQLException {\n        try {\n            stmt.setByte(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setShort(String parameterName, short x) throws SQLException {\n        try {\n            stmt.setShort(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setInt(String parameterName, int x) throws SQLException {\n        try {\n            stmt.setInt(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setLong(String parameterName, long x) throws SQLException {\n        try {\n            stmt.setLong(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setFloat(String parameterName, float x) throws SQLException {\n        try {\n            stmt.setFloat(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setDouble(String parameterName, double x) throws SQLException {\n        try {\n            stmt.setDouble(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {\n        try {\n            stmt.setBigDecimal(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setString(String parameterName, String x) throws SQLException {\n        try {\n            stmt.setString(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBytes(String parameterName, byte[] x) throws SQLException {\n        try {\n            stmt.setBytes(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setDate(String parameterName, java.sql.Date x) throws SQLException {\n        try {\n            stmt.setDate(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTime(String parameterName, java.sql.Time x) throws SQLException {\n        try {\n            stmt.setTime(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTimestamp(String parameterName, java.sql.Timestamp x) throws SQLException {\n        try {\n            stmt.setTimestamp(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, java.io.InputStream x, int length) throws SQLException {\n        try {\n            stmt.setAsciiStream(parameterName, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, java.io.InputStream x, int length) throws SQLException {\n        try {\n            stmt.setBinaryStream(parameterName, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {\n        try {\n            stmt.setObject(parameterName, x, targetSqlType, scale);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {\n        try {\n            stmt.setObject(parameterName, x, targetSqlType);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x) throws SQLException {\n        try {\n            stmt.setObject(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, java.io.Reader reader, int length) throws SQLException {\n        try {\n            stmt.setCharacterStream(parameterName, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setDate(String parameterName, java.sql.Date x, Calendar cal) throws SQLException {\n        try {\n            stmt.setDate(parameterName, x, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTime(String parameterName, java.sql.Time x, Calendar cal) throws SQLException {\n        try {\n            stmt.setTime(parameterName, x, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal) throws SQLException {\n        try {\n            stmt.setTimestamp(parameterName, x, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {\n        try {\n            stmt.setNull(parameterName, sqlType, typeName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getString(String parameterName) throws SQLException {\n        try {\n            return stmt.getString(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean getBoolean(String parameterName) throws SQLException {\n        try {\n            return stmt.getBoolean(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte getByte(String parameterName) throws SQLException {\n        try {\n            return stmt.getByte(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public short getShort(String parameterName) throws SQLException {\n        try {\n            return stmt.getShort(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getInt(String parameterName) throws SQLException {\n        try {\n            return stmt.getInt(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public long getLong(String parameterName) throws SQLException {\n        try {\n            return stmt.getLong(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public float getFloat(String parameterName) throws SQLException {\n        try {\n            return stmt.getFloat(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public double getDouble(String parameterName) throws SQLException {\n        try {\n            return stmt.getDouble(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte[] getBytes(String parameterName) throws SQLException {\n        try {\n            return stmt.getBytes(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(String parameterName) throws SQLException {\n        try {\n            return stmt.getDate(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(String parameterName) throws SQLException {\n        try {\n            return stmt.getTime(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(String parameterName) throws SQLException {\n        try {\n            return stmt.getTimestamp(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Object getObject(String parameterName) throws SQLException {\n        try {\n            Object obj = stmt.getObject(parameterName);\n            return wrapObject(obj);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String parameterName) throws SQLException {\n        try {\n            return stmt.getBigDecimal(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Object getObject(String parameterName, java.util.Map<String, Class<?>> map) throws SQLException {\n        try {\n            Object obj = stmt.getObject(parameterName, map);\n            return wrapObject(obj);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Ref getRef(String parameterName) throws SQLException {\n        try {\n            return stmt.getRef(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Blob getBlob(String parameterName) throws SQLException {\n        try {\n            return stmt.getBlob(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Clob getClob(String parameterName) throws SQLException {\n        try {\n            return stmt.getClob(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Array getArray(String parameterName) throws SQLException {\n        try {\n            return stmt.getArray(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(String parameterName, Calendar cal) throws SQLException {\n        try {\n            return stmt.getDate(parameterName, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(String parameterName, Calendar cal) throws SQLException {\n        try {\n            return stmt.getTime(parameterName, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {\n        try {\n            return stmt.getTimestamp(parameterName, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.net.URL getURL(String parameterName) throws SQLException {\n        try {\n            return stmt.getURL(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public RowId getRowId(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getRowId(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public RowId getRowId(String parameterName) throws SQLException {\n        try {\n            return stmt.getRowId(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setRowId(String parameterName, RowId x) throws SQLException {\n        try {\n            stmt.setRowId(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNString(String parameterName, String value) throws SQLException {\n        try {\n            stmt.setNString(parameterName, value);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {\n        try {\n            stmt.setNCharacterStream(parameterName, value, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNClob(String parameterName, NClob value) throws SQLException {\n        try {\n            stmt.setNClob(parameterName, value);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setClob(String parameterName, Reader reader, long length) throws SQLException {\n        try {\n            stmt.setClob(parameterName, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {\n        try {\n            stmt.setBlob(parameterName, inputStream, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNClob(String parameterName, Reader reader, long length) throws SQLException {\n        try {\n            stmt.setNClob(parameterName, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public NClob getNClob(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getNClob(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public NClob getNClob(String parameterName) throws SQLException {\n        try {\n            return stmt.getNClob(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {\n        try {\n            stmt.setSQLXML(parameterName, xmlObject);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public SQLXML getSQLXML(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getSQLXML(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public SQLXML getSQLXML(String parameterName) throws SQLException {\n        try {\n            return stmt.getSQLXML(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getNString(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getNString(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getNString(String parameterName) throws SQLException {\n        try {\n            return stmt.getNString(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getNCharacterStream(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getNCharacterStream(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getNCharacterStream(String parameterName) throws SQLException {\n        try {\n            return stmt.getNCharacterStream(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getCharacterStream(int parameterIndex) throws SQLException {\n        try {\n            return stmt.getCharacterStream(parameterIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getCharacterStream(String parameterName) throws SQLException {\n        try {\n            return stmt.getCharacterStream(parameterName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBlob(String parameterName, Blob x) throws SQLException {\n        try {\n            stmt.setBlob(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setClob(String parameterName, Clob x) throws SQLException {\n        try {\n            stmt.setClob(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, java.io.InputStream x, long length) throws SQLException {\n        try {\n            stmt.setAsciiStream(parameterName, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, java.io.InputStream x, long length) throws SQLException {\n        try {\n            stmt.setBinaryStream(parameterName, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, java.io.Reader reader, long length) throws SQLException {\n        try {\n            stmt.setCharacterStream(parameterName, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, java.io.InputStream x) throws SQLException {\n        try {\n            stmt.setAsciiStream(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, java.io.InputStream x) throws SQLException {\n        try {\n            stmt.setBinaryStream(parameterName, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, java.io.Reader reader) throws SQLException {\n        try {\n            stmt.setCharacterStream(parameterName, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNCharacterStream(String parameterName, Reader value) throws SQLException {\n        try {\n            stmt.setNCharacterStream(parameterName, value);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setClob(String parameterName, Reader reader) throws SQLException {\n        try {\n            stmt.setClob(parameterName, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBlob(String parameterName, InputStream inputStream) throws SQLException {\n        try {\n            stmt.setBlob(parameterName, inputStream);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNClob(String parameterName, Reader reader) throws SQLException {\n        try {\n            stmt.setNClob(parameterName, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException {\n        return stmt.getObject(parameterIndex, type);\n    }\n\n    public <T> T getObject(String parameterName, Class<T> type) throws SQLException {\n        return stmt.getObject(parameterName, type);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == CallableStatement.class || iface == PreparedStatement.class) {\n            if (stmt instanceof CallableStatementProxy) {\n                return stmt.unwrap(iface);\n            }\n            return (T) stmt;\n        }\n\n        return super.unwrap(iface);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\nimport com.alibaba.druid.pool.PreparedStatementPool.MethodType;\nimport com.alibaba.druid.proxy.jdbc.TransactionInfo;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport javax.sql.ConnectionEvent;\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.StatementEventListener;\n\nimport java.sql.*;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidPooledConnection extends PoolableWrapper implements javax.sql.PooledConnection, Connection {\n    private static final Log LOG = LogFactory.getLog(DruidPooledConnection.class);\n    public static final int MAX_RECORD_SQL_COUNT = 10;\n    protected Connection conn;\n    protected volatile DruidConnectionHolder holder;\n    protected TransactionInfo transactionInfo;\n    private final boolean dupCloseLogEnable;\n    protected volatile boolean traceEnable;\n    protected volatile boolean disable;\n    protected volatile boolean closed;\n    static AtomicIntegerFieldUpdater CLOSING_UPDATER = AtomicIntegerFieldUpdater.newUpdater(DruidPooledConnection.class, \"closing\");\n    protected final Thread ownerThread;\n    private long connectedTimeMillis;\n    private long connectedTimeNano;\n    private volatile boolean running;\n    private volatile boolean abandoned;\n    protected StackTraceElement[] connectStackTrace;\n    protected Throwable disableError;\n    final ReentrantLock lock;\n    protected volatile int closing;\n    protected FilterChain filterChain;\n\n    public DruidPooledConnection(DruidConnectionHolder holder) {\n        super(holder.getConnection());\n\n        this.conn = holder.getConnection();\n        this.holder = holder;\n        this.lock = holder.lock;\n        dupCloseLogEnable = holder.getDataSource().isDupCloseLogEnable();\n        ownerThread = Thread.currentThread();\n        connectedTimeMillis = System.currentTimeMillis();\n    }\n\n    public long getConnectedTimeMillis() {\n        return connectedTimeMillis;\n    }\n\n    public Thread getOwnerThread() {\n        return ownerThread;\n    }\n\n    public StackTraceElement[] getConnectStackTrace() {\n        return connectStackTrace;\n    }\n\n    public void setConnectStackTrace(StackTraceElement[] connectStackTrace) {\n        this.connectStackTrace = connectStackTrace;\n    }\n\n    public long getConnectedTimeNano() {\n        return connectedTimeNano;\n    }\n\n    public void setConnectedTimeNano() {\n        if (connectedTimeNano <= 0) {\n            this.setConnectedTimeNano(System.nanoTime());\n        }\n    }\n\n    public void setConnectedTimeNano(long connectedTimeNano) {\n        this.connectedTimeNano = connectedTimeNano;\n    }\n\n    public boolean isTraceEnable() {\n        return traceEnable;\n    }\n\n    public void setTraceEnable(boolean traceEnable) {\n        this.traceEnable = traceEnable;\n    }\n\n    public SQLException handleException(Throwable t) throws SQLException {\n        return handleException(t, null);\n    }\n\n    public SQLException handleException(Throwable t, String sql) throws SQLException {\n        final DruidConnectionHolder holder = this.holder;\n\n        //\n        if (holder != null) {\n            DruidAbstractDataSource dataSource = holder.getDataSource();\n            dataSource.handleConnectionException(this, t, sql);\n        }\n\n        if (t instanceof SQLException) {\n            throw (SQLException) t;\n        }\n\n        throw new SQLException(\"Error\", t);\n    }\n\n    public boolean isOracle() {\n        return holder.getDataSource().isOracle();\n    }\n\n    public void closePoolableStatement(DruidPooledPreparedStatement stmt) throws SQLException {\n        PreparedStatement rawStatement = stmt.stmt;\n\n        final DruidConnectionHolder holder = this.holder;\n        if (holder == null) {\n            return;\n        }\n\n        if (stmt.pooled) {\n            try {\n                rawStatement.clearParameters();\n            } catch (SQLException ex) {\n                this.handleException(ex, null);\n                if (rawStatement.getConnection().isClosed()) {\n                    return;\n                }\n\n                LOG.error(\"clear parameter error\", ex);\n            }\n\n            try {\n                rawStatement.clearBatch();\n            } catch (SQLException ex) {\n                this.handleException(ex, null);\n                if (rawStatement.getConnection().isClosed()) {\n                    return;\n                }\n\n                LOG.error(\"clear batch error\", ex);\n            }\n        }\n\n        PreparedStatementHolder stmtHolder = stmt.holder;\n        stmtHolder.inUseCount--;\n        if (stmt.pooled && holder.dataSource.poolPreparedStatements && stmt.exceptionCount == 0) {\n            holder.getStatementPool().put(stmtHolder);\n\n            stmt.clearResultSet();\n            holder.removeTrace(stmt);\n\n            stmtHolder.setFetchRowPeak(stmt.getFetchRowPeak());\n\n            stmt.setClosed(true); // soft set close\n        } else if (stmt.pooled && holder.dataSource.poolPreparedStatements) {\n            // the PreparedStatement threw an exception\n            stmt.clearResultSet();\n            holder.removeTrace(stmt);\n\n            holder.getStatementPool()\n                    .remove(stmtHolder);\n        } else {\n            try {\n                //Connection behind the statement may be in invalid state, which will throw a SQLException.\n                //In this case, the exception is desired to be properly handled to remove the unusable connection from the pool.\n                stmt.closeInternal();\n            } catch (SQLException ex) {\n                this.handleException(ex, null);\n                throw ex;\n            } finally {\n                holder.dataSource.incrementClosedPreparedStatementCount();\n            }\n        }\n    }\n\n    public DruidConnectionHolder getConnectionHolder() {\n        return holder;\n    }\n\n    @Override\n    public Connection getConnection() {\n        if (!holder.underlyingAutoCommit) {\n            createTransactionInfo();\n        }\n\n        return conn;\n    }\n\n    public void disable() {\n        disable(null);\n    }\n\n    public void disable(Throwable error) {\n        if (this.holder != null) {\n            this.holder.clearStatementCache();\n        }\n\n        this.traceEnable = false;\n        this.holder = null;\n        this.transactionInfo = null;\n        this.disable = true;\n        this.disableError = error;\n    }\n\n    public boolean isDisable() {\n        return disable;\n    }\n\n    @Override\n    public void close() throws SQLException {\n        if (this.disable) {\n            return;\n        }\n\n        DruidConnectionHolder holder = this.holder;\n        if (holder == null) {\n            if (dupCloseLogEnable) {\n                LOG.error(\"dup close\");\n            }\n            return;\n        }\n\n        DruidAbstractDataSource dataSource = holder.getDataSource();\n        boolean isSameThread = this.ownerThread == Thread.currentThread();\n\n        if (!isSameThread) {\n            dataSource.setAsyncCloseConnectionEnable(true);\n        }\n\n        if (dataSource.removeAbandoned || dataSource.asyncCloseConnectionEnable) {\n            syncClose();\n            return;\n        }\n\n        if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {\n            return;\n        }\n\n        try {\n            for (int i = 0; i < holder.connectionEventListeners.size(); i++) {\n                ConnectionEventListener listener = holder.connectionEventListeners.get(i);\n                listener.connectionClosed(new ConnectionEvent(this));\n            }\n\n            List<Filter> filters = dataSource.filters;\n            int filtersSize = filters.size();\n            if (filtersSize > 0) {\n                FilterChainImpl filterChain = holder.createChain();\n                try {\n                    filterChain.dataSource_recycle(this);\n                } finally {\n                    holder.recycleFilterChain(filterChain);\n                }\n            } else {\n                recycle();\n            }\n        } finally {\n            CLOSING_UPDATER.set(this, 0);\n        }\n\n        this.disable = true;\n    }\n\n    public void syncClose() throws SQLException {\n        lock.lock();\n        try {\n            if (this.disable || CLOSING_UPDATER.get(this) != 0) {\n                return;\n            }\n\n            DruidConnectionHolder holder = this.holder;\n            if (holder == null) {\n                if (dupCloseLogEnable) {\n                    LOG.error(\"dup close\");\n                }\n                return;\n            }\n\n            if (!CLOSING_UPDATER.compareAndSet(this, 0, 1)) {\n                return;\n            }\n\n            for (ConnectionEventListener listener : holder.connectionEventListeners) {\n                listener.connectionClosed(new ConnectionEvent(this));\n            }\n\n            DruidAbstractDataSource dataSource = holder.getDataSource();\n            List<Filter> filters = dataSource.getProxyFilters();\n            if (filters.size() > 0) {\n                FilterChainImpl filterChain = new FilterChainImpl(dataSource);\n                filterChain.dataSource_recycle(this);\n            } else {\n                recycle();\n            }\n\n            this.disable = true;\n        } finally {\n            CLOSING_UPDATER.set(this, 0);\n            lock.unlock();\n        }\n    }\n\n    public void recycle() throws SQLException {\n        if (this.disable) {\n            return;\n        }\n\n        DruidConnectionHolder holder = this.holder;\n        if (holder == null) {\n            if (dupCloseLogEnable) {\n                LOG.error(\"dup close\");\n            }\n            return;\n        }\n\n        if (!this.abandoned) {\n            holder.dataSource.recycle(this);\n        }\n\n        this.holder = null;\n        conn = null;\n        transactionInfo = null;\n        closed = true;\n    }\n\n    // ////////////////////\n\n    @Override\n    public PreparedStatement prepareStatement(String sql) throws SQLException {\n        checkState();\n\n        PreparedStatementHolder stmtHolder = null;\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M1);\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    private void initStatement(PreparedStatementHolder stmtHolder) throws SQLException {\n        stmtHolder.incrementInUseCount();\n        holder.getDataSource().initStatement(this, stmtHolder.statement);\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        checkState();\n\n        PreparedStatementHolder stmtHolder = null;\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M2, resultSetType,\n                resultSetConcurrency);\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, resultSetType,\n                        resultSetConcurrency));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,\n                                              int resultSetHoldability) throws SQLException {\n        checkState();\n\n        PreparedStatementHolder stmtHolder = null;\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M3, resultSetType,\n                resultSetConcurrency, resultSetHoldability);\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, resultSetType,\n                        resultSetConcurrency,\n                        resultSetHoldability));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {\n        checkState();\n\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M4, columnIndexes);\n        PreparedStatementHolder stmtHolder = null;\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, columnIndexes));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {\n        checkState();\n\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M5, columnNames);\n        PreparedStatementHolder stmtHolder = null;\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, columnNames));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {\n        checkState();\n\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M6, autoGeneratedKeys);\n        PreparedStatementHolder stmtHolder = null;\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql, autoGeneratedKeys));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    // ////////////////////\n\n    @Override\n    public CallableStatement prepareCall(String sql) throws SQLException {\n        checkState();\n\n        PreparedStatementHolder stmtHolder = null;\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.Precall_1);\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareCall(sql));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledCallableStatement rtnVal = new DruidPooledCallableStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,\n                                         int resultSetHoldability) throws SQLException {\n        checkState();\n\n        PreparedStatementHolder stmtHolder = null;\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.Precall_2, resultSetType,\n                resultSetConcurrency, resultSetHoldability);\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key, conn.prepareCall(sql, resultSetType,\n                        resultSetConcurrency,\n                        resultSetHoldability));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledCallableStatement rtnVal = new DruidPooledCallableStatement(this, stmtHolder);\n\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\n        checkState();\n\n        PreparedStatementHolder stmtHolder = null;\n        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.Precall_3, resultSetType,\n                resultSetConcurrency);\n\n        boolean poolPreparedStatements = holder.isPoolPreparedStatements();\n\n        if (poolPreparedStatements) {\n            stmtHolder = holder.getStatementPool().get(key);\n        }\n\n        if (stmtHolder == null) {\n            try {\n                stmtHolder = new PreparedStatementHolder(key,\n                        conn.prepareCall(sql, resultSetType, resultSetConcurrency));\n                holder.getDataSource().incrementPreparedStatementCount();\n            } catch (SQLException ex) {\n                handleException(ex, sql);\n            }\n        }\n\n        initStatement(stmtHolder);\n\n        DruidPooledCallableStatement rtnVal = new DruidPooledCallableStatement(this, stmtHolder);\n        holder.addTrace(rtnVal);\n\n        return rtnVal;\n    }\n\n    // ////////////////////\n\n    @Override\n    public Statement createStatement() throws SQLException {\n        checkState();\n\n        Statement stmt = null;\n        try {\n            stmt = conn.createStatement();\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n\n        holder.dataSource.initStatement(this, stmt);\n\n        DruidPooledStatement poolableStatement = new DruidPooledStatement(this, stmt);\n        holder.addTrace(poolableStatement);\n\n        return poolableStatement;\n    }\n\n    @Override\n    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)\n            throws SQLException {\n        checkState();\n\n        Statement stmt = null;\n        try {\n            stmt = conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n\n        holder.dataSource.initStatement(this, stmt);\n\n        DruidPooledStatement poolableStatement = new DruidPooledStatement(this, stmt);\n        holder.addTrace(poolableStatement);\n\n        return poolableStatement;\n    }\n\n    @Override\n    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {\n        checkState();\n\n        Statement stmt = null;\n        try {\n            stmt = conn.createStatement(resultSetType, resultSetConcurrency);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n\n        holder.dataSource.initStatement(this, stmt);\n\n        DruidPooledStatement poolableStatement = new DruidPooledStatement(this, stmt);\n        holder.addTrace(poolableStatement);\n\n        return poolableStatement;\n    }\n\n    @Override\n    public String nativeSQL(String sql) throws SQLException {\n        checkState();\n\n        return conn.nativeSQL(sql);\n    }\n\n    @Override\n    public void setAutoCommit(boolean autoCommit) throws SQLException {\n        checkState();\n\n        boolean useLocalSessionState = holder.getDataSource().isUseLocalSessionState();\n\n        if (useLocalSessionState) {\n            if (autoCommit == holder.underlyingAutoCommit) {\n                return;\n            }\n        }\n\n        try {\n            conn.setAutoCommit(autoCommit);\n            holder.setUnderlyingAutoCommit(autoCommit);\n            holder.setLastExecTimeMillis(System.currentTimeMillis());\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n    }\n\n    protected void transactionRecord(String sql) throws SQLException {\n        if (holder != null) {\n            holder.setLastExecTimeMillis(System.currentTimeMillis());\n        }\n\n        if (transactionInfo == null && (!conn.getAutoCommit())) {\n            DruidAbstractDataSource dataSource = holder.getDataSource();\n            dataSource.incrementStartTransactionCount();\n            transactionInfo = new TransactionInfo(dataSource.createTransactionId());\n        }\n\n        if (transactionInfo != null) {\n            List<String> sqlList = transactionInfo.getSqlList();\n            if (sqlList.size() < MAX_RECORD_SQL_COUNT) {\n                sqlList.add(sql);\n            }\n        }\n    }\n\n    @Override\n    public boolean getAutoCommit() throws SQLException {\n        checkState();\n\n        return conn.getAutoCommit();\n    }\n\n    @Override\n    public void commit() throws SQLException {\n        checkState();\n\n        DruidAbstractDataSource dataSource = holder.getDataSource();\n        dataSource.incrementCommitCount();\n\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        } finally {\n            handleEndTransaction(dataSource, null);\n        }\n    }\n\n    public TransactionInfo getTransactionInfo() {\n        return transactionInfo;\n    }\n\n    protected void createTransactionInfo() {\n        DruidAbstractDataSource dataSource = holder.getDataSource();\n        dataSource.incrementStartTransactionCount();\n        transactionInfo = new TransactionInfo(dataSource.createTransactionId());\n    }\n\n    @Override\n    public void rollback() throws SQLException {\n        if (transactionInfo == null) {\n            return;\n        }\n\n        if (holder == null) {\n            return;\n        }\n\n        DruidAbstractDataSource dataSource = holder.getDataSource();\n        dataSource.incrementRollbackCount();\n\n        try {\n            conn.rollback();\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        } finally {\n            handleEndTransaction(dataSource, null);\n        }\n    }\n\n    @Override\n    public Savepoint setSavepoint(String name) throws SQLException {\n        checkState();\n\n        try {\n            return conn.setSavepoint(name);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n            return null; // never arrive\n        }\n    }\n\n    @Override\n    public void rollback(Savepoint savepoint) throws SQLException {\n        if (holder == null) {\n            return;\n        }\n\n        DruidAbstractDataSource dataSource = holder.getDataSource();\n        dataSource.incrementRollbackCount();\n\n        try {\n            conn.rollback(savepoint);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        } finally {\n            handleEndTransaction(dataSource, savepoint);\n        }\n    }\n\n    private void handleEndTransaction(DruidAbstractDataSource dataSource, Savepoint savepoint) {\n        if (transactionInfo != null && savepoint == null) {\n            transactionInfo.setEndTimeMillis();\n\n            long transactionMillis = transactionInfo.getEndTimeMillis() - transactionInfo.getStartTimeMillis();\n            dataSource.getTransactionHistogram().record(transactionMillis);\n\n            dataSource.logTransaction(transactionInfo);\n\n            transactionInfo = null;\n        }\n    }\n\n    @Override\n    public void releaseSavepoint(Savepoint savepoint) throws SQLException {\n        checkState();\n        try {\n            conn.releaseSavepoint(savepoint);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n    }\n\n    @Override\n    public Clob createClob() throws SQLException {\n        checkState();\n\n        try {\n            return conn.createClob();\n        } catch (SQLException ex) {\n            handleException(ex, null);\n            return null; // never arrive\n        }\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        return holder == null || closed || disable;\n    }\n\n    public boolean isAbandonded() {\n        return this.abandoned;\n    }\n\n    @Override\n    public DatabaseMetaData getMetaData() throws SQLException {\n        checkState();\n\n        if (!holder.underlyingAutoCommit) {\n            createTransactionInfo();\n        }\n\n        return conn.getMetaData();\n    }\n\n    @Override\n    public void setReadOnly(boolean readOnly) throws SQLException {\n        checkState();\n\n        boolean useLocalSessionState = holder.getDataSource().isUseLocalSessionState();\n        if (useLocalSessionState) {\n            if (readOnly == holder.isUnderlyingReadOnly()) {\n                return;\n            }\n        }\n\n        try {\n            conn.setReadOnly(readOnly);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n\n        holder.setUnderlyingReadOnly(readOnly);\n    }\n\n    @Override\n    public boolean isReadOnly() throws SQLException {\n        checkState();\n\n        return conn.isReadOnly();\n    }\n\n    @Override\n    public void setCatalog(String catalog) throws SQLException {\n        checkState();\n\n        try {\n            conn.setCatalog(catalog);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n    }\n\n    @Override\n    public String getCatalog() throws SQLException {\n        checkState();\n\n        return conn.getCatalog();\n    }\n\n    @Override\n    public void setTransactionIsolation(int level) throws SQLException {\n        checkState();\n\n        boolean useLocalSessionState = holder.getDataSource().isUseLocalSessionState();\n        if (useLocalSessionState) {\n            if (level == holder.getUnderlyingTransactionIsolation()) {\n                return;\n            }\n        }\n\n        try {\n            conn.setTransactionIsolation(level);\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n        holder.setUnderlyingTransactionIsolation(level);\n    }\n\n    @Override\n    public int getTransactionIsolation() throws SQLException {\n        checkState();\n\n        return holder.getUnderlyingTransactionIsolation();\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        checkState();\n\n        return conn.getWarnings();\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        checkState();\n        try {\n            conn.clearWarnings();\n        } catch (SQLException ex) {\n            handleException(ex, null);\n        }\n    }\n\n    @Override\n    public Map<String, Class<?>> getTypeMap() throws SQLException {\n        checkState();\n\n        return conn.getTypeMap();\n    }\n\n    @Override\n    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {\n        checkState();\n\n        conn.setTypeMap(map);\n    }\n\n    @Override\n    public void setHoldability(int holdability) throws SQLException {\n        checkState();\n\n        boolean useLocalSessionState = holder.getDataSource().isUseLocalSessionState();\n        if (useLocalSessionState) {\n            if (holdability == holder.getUnderlyingHoldability()) {\n                return;\n            }\n        }\n\n        conn.setHoldability(holdability);\n        holder.setUnderlyingHoldability(holdability);\n    }\n\n    @Override\n    public int getHoldability() throws SQLException {\n        checkState();\n\n        if (!holder.underlyingAutoCommit) {\n            createTransactionInfo();\n        }\n\n        return conn.getHoldability();\n    }\n\n    @Override\n    public Savepoint setSavepoint() throws SQLException {\n        checkState();\n\n        try {\n            return conn.setSavepoint();\n        } catch (SQLException ex) {\n            handleException(ex, null);\n            return null;\n        }\n    }\n\n    @Override\n    public Blob createBlob() throws SQLException {\n        checkState();\n\n        return conn.createBlob();\n    }\n\n    @Override\n    public NClob createNClob() throws SQLException {\n        checkState();\n\n        return conn.createNClob();\n    }\n\n    @Override\n    public SQLXML createSQLXML() throws SQLException {\n        checkState();\n\n        return conn.createSQLXML();\n    }\n\n    @Override\n    public boolean isValid(int timeout) throws SQLException {\n        checkState();\n\n        return conn.isValid(timeout);\n    }\n\n    @Override\n    public void setClientInfo(String name, String value) throws SQLClientInfoException {\n        if (holder == null) {\n            throw new SQLClientInfoException();\n        }\n\n        conn.setClientInfo(name, value);\n    }\n\n    @Override\n    public void setClientInfo(Properties properties) throws SQLClientInfoException {\n        if (holder == null) {\n            throw new SQLClientInfoException();\n        }\n\n        conn.setClientInfo(properties);\n    }\n\n    @Override\n    public String getClientInfo(String name) throws SQLException {\n        checkState();\n\n        return conn.getClientInfo(name);\n    }\n\n    @Override\n    public Properties getClientInfo() throws SQLException {\n        checkState();\n\n        return conn.getClientInfo();\n    }\n\n    @Override\n    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {\n        checkState();\n\n        return conn.createArrayOf(typeName, elements);\n    }\n\n    @Override\n    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {\n        checkState();\n\n        return conn.createStruct(typeName, attributes);\n    }\n\n    @Override\n    public void addConnectionEventListener(ConnectionEventListener listener) {\n        if (holder == null) {\n            throw new IllegalStateException();\n        }\n\n        holder.getConnectionEventListeners().add(listener);\n    }\n\n    @Override\n    public void removeConnectionEventListener(ConnectionEventListener listener) {\n        if (holder == null) {\n            throw new IllegalStateException();\n        }\n\n        holder.getConnectionEventListeners().remove(listener);\n    }\n\n    @Override\n    public void addStatementEventListener(StatementEventListener listener) {\n        if (holder == null) {\n            throw new IllegalStateException();\n        }\n\n        holder.getStatementEventListeners().add(listener);\n    }\n\n    @Override\n    public void removeStatementEventListener(StatementEventListener listener) {\n        if (holder == null) {\n            throw new IllegalStateException();\n        }\n\n        holder.getStatementEventListeners().remove(listener);\n    }\n\n    public Throwable getDisableError() {\n        return disableError;\n    }\n\n    public void checkState() throws SQLException {\n        final boolean asyncCloseEnabled;\n        if (holder != null) {\n            asyncCloseEnabled = holder.dataSource.isAsyncCloseConnectionEnable();\n        } else {\n            asyncCloseEnabled = false;\n        }\n\n        if (asyncCloseEnabled) {\n            lock.lock();\n            try {\n                checkStateInternal();\n            } finally {\n                lock.unlock();\n            }\n        } else {\n            checkStateInternal();\n        }\n    }\n\n    private void checkStateInternal() throws SQLException {\n        if (closed) {\n            if (disableError != null) {\n                throw new SQLException(\"connection closed\", disableError);\n            } else {\n                throw new SQLException(\"connection closed\");\n            }\n        }\n\n        if (disable) {\n            if (disableError != null) {\n                throw new SQLException(\"connection disabled\", disableError);\n            } else {\n                throw new SQLException(\"connection disabled\");\n            }\n        }\n\n        if (holder == null) {\n            if (disableError != null) {\n                throw new SQLException(\"connection holder is null\", disableError);\n            } else {\n                throw new SQLException(\"connection holder is null\");\n            }\n        }\n    }\n\n    public String toString() {\n        if (conn != null) {\n            return conn.toString();\n        } else {\n            return \"closed-conn-\" + System.identityHashCode(this);\n        }\n    }\n\n    public void setSchema(String schema) throws SQLException {\n        if (JdbcUtils.isMysqlDbType(holder.dataSource.getDbType())) {\n            if (holder.initSchema == null) {\n                holder.initSchema = conn.getSchema();\n            }\n            conn.setSchema(schema);\n            if (holder.statementPool != null) {\n                holder.clearStatementCache();\n            }\n            return;\n        }\n        conn.setSchema(schema);\n    }\n\n    public String getSchema() throws SQLException {\n        return conn.getSchema();\n    }\n\n    public void abort(Executor executor) throws SQLException {\n        conn.abort(executor);\n    }\n\n    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {\n        conn.setNetworkTimeout(executor, milliseconds);\n    }\n\n    public int getNetworkTimeout() throws SQLException {\n        return conn.getNetworkTimeout();\n    }\n\n    final void beforeExecute() {\n        final DruidConnectionHolder holder = this.holder;\n        if (holder != null && holder.dataSource.removeAbandoned) {\n            running = true;\n        }\n    }\n\n    final void afterExecute() {\n        final DruidConnectionHolder holder = this.holder;\n        if (holder != null) {\n            DruidAbstractDataSource dataSource = holder.dataSource;\n            if (dataSource.removeAbandoned) {\n                running = false;\n                holder.lastActiveTimeMillis = System.currentTimeMillis();\n            }\n            dataSource.onFatalError = false;\n        }\n    }\n\n    boolean isRunning() {\n        return running;\n    }\n\n    public void abandond() {\n        this.abandoned = true;\n    }\n\n    /**\n     * @since 1.0.17\n     */\n    public long getPhysicalConnectNanoSpan() {\n        return this.holder.getCreateNanoSpan();\n    }\n\n    /**\n     * @since 1.0.17\n     */\n    public long getPhysicalConnectionUsedCount() {\n        return this.holder.getUseCount();\n    }\n\n    /**\n     * @since 1.0.17\n     */\n    public long getConnectNotEmptyWaitNanos() {\n        return this.holder.getLastNotEmptyWaitNanos();\n    }\n\n    /**\n     * @since 1.0.28\n     */\n    public Map<String, Object> getVariables() {\n        return this.holder.variables;\n    }\n\n    /**\n     * @since 1.0.28\n     */\n    public Map<String, Object> getGloablVariables() {\n        return this.holder.globalVariables;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidPooledPreparedStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.pool.PreparedStatementPool.MethodType;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.OracleUtils;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.Arrays;\nimport java.util.Calendar;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidPooledPreparedStatement extends DruidPooledStatement implements PreparedStatement {\n    private static final Log LOG = LogFactory.getLog(DruidPooledPreparedStatement.class);\n\n    protected final PreparedStatementHolder holder;\n    protected final PreparedStatement stmt;\n    private final String sql;\n\n    private int defaultMaxFieldSize;\n    private int defaultMaxRows;\n    private int defaultQueryTimeout;\n    private int defaultFetchDirection;\n    private int defaultFetchSize;\n    private int currentMaxFieldSize;\n    private int currentMaxRows;\n    private int currentQueryTimeout;\n    private int currentFetchDirection;\n    private int currentFetchSize;\n\n    protected boolean pooled;\n\n    public DruidPooledPreparedStatement(DruidPooledConnection conn,\n                                        PreparedStatementHolder holder) throws SQLException {\n        super(conn, holder.statement);\n        this.stmt = holder.statement;\n        this.holder = holder;\n        this.sql = holder.key.sql;\n\n        pooled = conn.getConnectionHolder().isPoolPreparedStatements();\n        // Remember the defaults\n\n        if (pooled) {\n            try {\n                defaultMaxFieldSize = stmt.getMaxFieldSize();\n            } catch (SQLException e) {\n                LOG.error(\"getMaxFieldSize error\", e);\n            }\n\n            try {\n                defaultMaxRows = stmt.getMaxRows();\n            } catch (SQLException e) {\n                LOG.error(\"getMaxRows error\", e);\n            }\n\n            try {\n                defaultQueryTimeout = stmt.getQueryTimeout();\n            } catch (SQLException e) {\n                LOG.error(\"getMaxRows error\", e);\n            }\n\n            try {\n                defaultFetchDirection = stmt.getFetchDirection();\n            } catch (SQLException e) {\n                LOG.error(\"getFetchDirection error\", e);\n            }\n\n            try {\n                defaultFetchSize = stmt.getFetchSize();\n            } catch (SQLException e) {\n                LOG.error(\"getFetchSize error\", e);\n            }\n        }\n\n        currentMaxFieldSize = defaultMaxFieldSize;\n        currentMaxRows = defaultMaxRows;\n        currentQueryTimeout = defaultQueryTimeout;\n        currentFetchDirection = defaultFetchDirection;\n        currentFetchSize = defaultFetchSize;\n    }\n\n    public PreparedStatementHolder getPreparedStatementHolder() {\n        return holder;\n    }\n\n    public int getHitCount() {\n        return holder.getHitCount();\n    }\n\n    public void setFetchSize(int rows) throws SQLException {\n        currentFetchSize = rows;\n        super.setFetchSize(rows);\n    }\n\n    public void setFetchDirection(int direction) throws SQLException {\n        currentFetchDirection = direction;\n        super.setFetchDirection(direction);\n    }\n\n    public void setMaxFieldSize(int max) throws SQLException {\n        currentMaxFieldSize = max;\n        super.setMaxFieldSize(max);\n    }\n\n    public void setMaxRows(int max) throws SQLException {\n        currentMaxRows = max;\n        super.setMaxRows(max);\n    }\n\n    public void setQueryTimeout(int seconds) throws SQLException {\n        currentQueryTimeout = seconds;\n        super.setQueryTimeout(seconds);\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public PreparedStatementKey getKey() {\n        return holder.key;\n    }\n\n    public PreparedStatement getRawPreparedStatement() {\n        return stmt;\n    }\n\n    public PreparedStatement getRawStatement() {\n        return stmt;\n    }\n\n    @Override\n    public void close() throws SQLException {\n        if (closed) {\n            return;\n        }\n\n        boolean connectionClosed = conn.holder == null || conn.closed || conn.disable;\n        // Reset the defaults\n        if (pooled && !connectionClosed) {\n            try {\n                if (defaultMaxFieldSize != currentMaxFieldSize) {\n                    stmt.setMaxFieldSize(defaultMaxFieldSize);\n                    currentMaxFieldSize = defaultMaxFieldSize;\n                }\n                if (defaultMaxRows != currentMaxRows) {\n                    stmt.setMaxRows(defaultMaxRows);\n                    currentMaxRows = defaultMaxRows;\n                }\n                if (defaultQueryTimeout != currentQueryTimeout) {\n                    stmt.setQueryTimeout(defaultQueryTimeout);\n                    currentQueryTimeout = defaultQueryTimeout;\n                }\n                if (defaultFetchDirection != currentFetchDirection) {\n                    stmt.setFetchDirection(defaultFetchDirection);\n                    currentFetchDirection = defaultFetchDirection;\n                }\n                if (defaultFetchSize != currentFetchSize) {\n                    stmt.setFetchSize(defaultFetchSize);\n                    currentFetchSize = defaultFetchSize;\n                }\n            } catch (Exception e) {\n                this.conn.handleException(e, null);\n            }\n        }\n\n        conn.closePoolableStatement(this);\n    }\n\n    public boolean isPooled() {\n        return pooled;\n    }\n\n    void closeInternal() throws SQLException {\n        super.close();\n    }\n\n    void setClosed(boolean value) {\n        this.closed = value;\n    }\n\n    @Override\n    public ResultSet executeQuery() throws SQLException {\n        checkOpen();\n\n        incrementExecuteQueryCount();\n        transactionRecord(sql);\n\n        oracleSetRowPrefetch();\n\n        conn.beforeExecute();\n        try {\n            ResultSet rs = stmt.executeQuery();\n\n            if (rs == null) {\n                return null;\n            }\n\n            DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);\n            addResultSetTrace(poolableResultSet);\n\n            return poolableResultSet;\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public int executeUpdate() throws SQLException {\n        checkOpen();\n\n        incrementExecuteUpdateCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.executeUpdate();\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public void setNull(int parameterIndex, int sqlType) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNull(parameterIndex, sqlType);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBoolean(int parameterIndex, boolean x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBoolean(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setByte(int parameterIndex, byte x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setByte(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setShort(int parameterIndex, short x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setShort(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setInt(int parameterIndex, int x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setInt(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setLong(int parameterIndex, long x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setLong(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setFloat(int parameterIndex, float x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setFloat(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setDouble(int parameterIndex, double x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setDouble(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBigDecimal(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setString(int parameterIndex, String x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setString(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBytes(int parameterIndex, byte[] x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBytes(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setDate(int parameterIndex, Date x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setDate(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTime(int parameterIndex, Time x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setTime(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setTimestamp(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setAsciiStream(parameterIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    @Deprecated\n    public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setUnicodeStream(parameterIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBinaryStream(parameterIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void clearParameters() throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.clearParameters();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setObject(parameterIndex, x, targetSqlType);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setObject(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean execute() throws SQLException {\n        checkOpen();\n\n        incrementExecuteCount();\n        transactionRecord(sql);\n\n        oracleSetRowPrefetch();\n\n        conn.beforeExecute();\n        try {\n            return stmt.execute();\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    protected void oracleSetRowPrefetch() throws SQLException {\n        if (!conn.holder.dataSource.isOracle) {\n            return;\n        }\n\n        if (holder.hitCount == 0) {\n            return;\n        }\n\n        int fetchRowPeak = holder.fetchRowPeak;\n\n        if (fetchRowPeak < 0) {\n            return;\n        }\n\n        if (holder.getDefaultRowPrefetch() == -1) {\n            int defaultRowPretch = OracleUtils.getRowPrefetch(this);\n            if (defaultRowPretch != holder.getDefaultRowPrefetch()) {\n                holder.setDefaultRowPrefetch(defaultRowPretch);\n                holder.setRowPrefetch(defaultRowPretch);\n            }\n        }\n\n        int rowPrefetch;\n\n        if (fetchRowPeak <= 1) {\n            rowPrefetch = 2;\n        } else if (fetchRowPeak > holder.getDefaultRowPrefetch()) {\n            rowPrefetch = holder.getDefaultRowPrefetch();\n        } else {\n            rowPrefetch = fetchRowPeak + 1;\n        }\n\n        if (rowPrefetch != holder.getRowPrefetch()) {\n            OracleUtils.setRowPrefetch(this, rowPrefetch);\n            holder.setRowPrefetch(rowPrefetch);\n        }\n    }\n\n    @Override\n    public void addBatch() throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.addBatch();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    public int[] executeBatch() throws SQLException {\n        checkOpen();\n\n        incrementExecuteBatchCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.executeBatch();\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setCharacterStream(parameterIndex, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setRef(int parameterIndex, Ref x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setRef(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, Blob x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBlob(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Clob x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setClob(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setArray(int parameterIndex, Array x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setArray(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException {\n        checkOpen();\n\n        if (!conn.holder.isUnderlyingAutoCommit()) {\n            conn.createTransactionInfo();\n        }\n\n        try {\n            return stmt.getMetaData();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setDate(parameterIndex, x, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setTime(parameterIndex, x, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setTimestamp(parameterIndex, x, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNull(parameterIndex, sqlType, typeName);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setURL(int parameterIndex, URL x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setURL(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public ParameterMetaData getParameterMetaData() throws SQLException {\n        checkOpen();\n\n        if (!conn.holder.isUnderlyingAutoCommit()) {\n            conn.createTransactionInfo();\n        }\n\n        try {\n            return stmt.getParameterMetaData();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setRowId(int parameterIndex, RowId x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setRowId(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNString(int parameterIndex, String value) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNString(parameterIndex, value);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNCharacterStream(parameterIndex, value, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, NClob value) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNClob(parameterIndex, value);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setClob(parameterIndex, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBlob(parameterIndex, inputStream, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNClob(parameterIndex, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setSQLXML(parameterIndex, xmlObject);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setAsciiStream(parameterIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBinaryStream(parameterIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setCharacterStream(parameterIndex, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setAsciiStream(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBinaryStream(parameterIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setCharacterStream(parameterIndex, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNCharacterStream(parameterIndex, value);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Reader reader) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setClob(parameterIndex, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setBlob(parameterIndex, inputStream);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, Reader reader) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setNClob(parameterIndex, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    public static class PreparedStatementKey {\n        protected final String sql;\n        protected final String catalog;\n\n        protected final MethodType methodType;\n\n        public final int resultSetType;\n        public final int resultSetConcurrency;\n        public final int resultSetHoldability;\n        public final int autoGeneratedKeys;\n        private final int[] columnIndexes;\n        private final String[] columnNames;\n\n        public PreparedStatementKey(String sql, String catalog, MethodType methodType) throws SQLException {\n            this(sql, catalog, methodType, 0, 0, 0, 0, null, null);\n        }\n\n        public PreparedStatementKey(String sql, String catalog, MethodType methodType, int resultSetType,\n                                    int resultSetConcurrency) throws SQLException {\n            this(sql, catalog, methodType, resultSetType, resultSetConcurrency, 0, 0, null, null);\n        }\n\n        public PreparedStatementKey(String sql, String catalog, MethodType methodType, int resultSetType,\n                                    int resultSetConcurrency, int resultSetHoldability) throws SQLException {\n            this(sql, catalog, methodType, resultSetType, resultSetConcurrency, resultSetHoldability, 0, null, null);\n        }\n\n        public PreparedStatementKey(String sql, String catalog, MethodType methodType, int autoGeneratedKeys)\n                throws SQLException {\n            this(sql, catalog, methodType, 0, 0, 0, autoGeneratedKeys, null, null);\n        }\n\n        public PreparedStatementKey(String sql, String catalog, MethodType methodType, int[] columnIndexes)\n                throws SQLException {\n            this(sql, catalog, methodType, 0, 0, 0, 0, columnIndexes, null);\n        }\n\n        public PreparedStatementKey(String sql, String catalog, MethodType methodType, String[] columnNames)\n                throws SQLException {\n            this(sql, catalog, methodType, 0, 0, 0, 0, null, columnNames);\n        }\n\n        public PreparedStatementKey(String sql, String catalog, MethodType methodType, int resultSetType,\n                                    int resultSetConcurrency, int resultSetHoldability, int autoGeneratedKeys,\n                                    int[] columnIndexes, String[] columnNames) throws SQLException {\n            if (sql == null) {\n                throw new SQLException(\"sql is null\");\n            }\n\n            this.sql = sql;\n            this.catalog = catalog;\n            this.methodType = methodType;\n            this.resultSetType = resultSetType;\n            this.resultSetConcurrency = resultSetConcurrency;\n            this.resultSetHoldability = resultSetHoldability;\n            this.autoGeneratedKeys = autoGeneratedKeys;\n            this.columnIndexes = columnIndexes;\n            this.columnNames = columnNames;\n        }\n\n        public int getResultSetType() {\n            return resultSetType;\n        }\n\n        public int getResultSetConcurrency() {\n            return resultSetConcurrency;\n        }\n\n        public int getResultSetHoldability() {\n            return resultSetHoldability;\n        }\n\n        @Override\n        public boolean equals(Object object) {\n            if (!(object instanceof PreparedStatementKey)) {\n                return false;\n            }\n\n            PreparedStatementKey that = (PreparedStatementKey) object;\n\n            if (!this.sql.equals(that.sql)) {\n                return false;\n            }\n\n            if (this.catalog == null) {\n                if (that.catalog != null) {\n                    return false;\n                }\n            } else {\n                if (!this.catalog.equals(that.catalog)) {\n                    return false;\n                }\n            }\n\n            if (this.methodType != that.methodType) {\n                return false;\n            }\n\n            if (this.resultSetType != that.resultSetType) {\n                return false;\n            }\n\n            if (this.resultSetConcurrency != that.resultSetConcurrency) {\n                return false;\n            }\n\n            if (this.resultSetHoldability != that.resultSetHoldability) {\n                return false;\n            }\n\n            if (this.autoGeneratedKeys != that.autoGeneratedKeys) {\n                return false;\n            }\n\n            if (!Arrays.equals(columnIndexes, that.columnIndexes)) {\n                return false;\n            }\n\n            if (!Arrays.equals(columnNames, that.columnNames)) {\n                return false;\n            }\n\n            return true;\n        }\n\n        public int hashCode() {\n            final int prime = 31;\n            int result = 1;\n\n            result = prime * result + ((sql == null) ? 0 : sql.hashCode());\n            result = prime * result + ((catalog == null) ? 0 : catalog.hashCode());\n            result = prime * result + ((methodType == null) ? 0 : methodType.hashCode());\n\n            result = prime * result + resultSetConcurrency;\n            result = prime * result + resultSetHoldability;\n            result = prime * result + resultSetType;\n\n            result = prime * result + autoGeneratedKeys;\n\n            result = prime * result + Arrays.hashCode(columnIndexes);\n            result = prime * result + Arrays.hashCode(columnNames);\n\n            return result;\n        }\n\n        public String getSql() {\n            return sql;\n        }\n\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == PreparedStatementHolder.class) {\n            return true;\n        }\n\n        return super.isWrapperFor(iface);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == PreparedStatementHolder.class) {\n            return (T) holder;\n        }\n        return super.unwrap(iface);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidPooledResultSet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.Calendar;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic final class DruidPooledResultSet extends PoolableWrapper implements ResultSet {\n    private final ResultSet rs;\n    private final DruidPooledStatement stmt;\n    protected boolean closed;\n\n    protected int cursorIndex;\n    protected int fetchRowCount;\n\n    public DruidPooledResultSet(DruidPooledStatement stmt, ResultSet rs) {\n        super(rs);\n        this.stmt = stmt;\n        this.rs = rs;\n    }\n\n    protected SQLException checkException(Throwable error) throws SQLException {\n        return stmt.checkException(error);\n    }\n\n    public DruidPooledStatement getPoolableStatement() {\n        return stmt;\n    }\n\n    public ResultSet getRawResultSet() {\n        return rs;\n    }\n\n    @Override\n    public boolean next() throws SQLException {\n        try {\n            boolean moreRows = rs.next();\n\n            if (moreRows) {\n                cursorIndex++;\n                if (cursorIndex > fetchRowCount) {\n                    fetchRowCount = cursorIndex;\n                }\n            }\n            return moreRows;\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void close() throws SQLException {\n        try {\n            this.closed = true;\n            rs.close();\n\n            stmt.recordFetchRowCount(fetchRowCount);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    public int getFetchRowCount() {\n        return fetchRowCount;\n    }\n\n    @Override\n    public boolean wasNull() throws SQLException {\n        try {\n            return rs.wasNull();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getString(int columnIndex) throws SQLException {\n        try {\n            return rs.getString(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean getBoolean(int columnIndex) throws SQLException {\n        try {\n            return rs.getBoolean(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte getByte(int columnIndex) throws SQLException {\n        try {\n            return rs.getByte(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public short getShort(int columnIndex) throws SQLException {\n        try {\n            return rs.getShort(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getInt(int columnIndex) throws SQLException {\n        try {\n            return rs.getInt(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public long getLong(int columnIndex) throws SQLException {\n        try {\n            return rs.getLong(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public float getFloat(int columnIndex) throws SQLException {\n        try {\n            return rs.getFloat(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public double getDouble(int columnIndex) throws SQLException {\n        try {\n            return rs.getDouble(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    @Deprecated\n    public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {\n        try {\n            return rs.getBigDecimal(columnIndex, scale);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte[] getBytes(int columnIndex) throws SQLException {\n        try {\n            return rs.getBytes(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(int columnIndex) throws SQLException {\n        try {\n            return rs.getDate(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(int columnIndex) throws SQLException {\n        try {\n            return rs.getTime(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {\n        try {\n            return rs.getTimestamp(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {\n        try {\n            return rs.getAsciiStream(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    @Deprecated\n    public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {\n        try {\n            return rs.getUnicodeStream(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {\n        try {\n            return rs.getBinaryStream(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getString(String columnLabel) throws SQLException {\n        try {\n            return rs.getString(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean getBoolean(String columnLabel) throws SQLException {\n        try {\n            return rs.getBoolean(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte getByte(String columnLabel) throws SQLException {\n        try {\n            return rs.getByte(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public short getShort(String columnLabel) throws SQLException {\n        try {\n            return rs.getShort(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getInt(String columnLabel) throws SQLException {\n        try {\n            return rs.getInt(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public long getLong(String columnLabel) throws SQLException {\n        try {\n            return rs.getLong(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public float getFloat(String columnLabel) throws SQLException {\n        try {\n            return rs.getFloat(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public double getDouble(String columnLabel) throws SQLException {\n        try {\n            return rs.getDouble(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    @Deprecated\n    public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {\n        try {\n            return rs.getBigDecimal(columnLabel, scale);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public byte[] getBytes(String columnLabel) throws SQLException {\n        try {\n            return rs.getBytes(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(String columnLabel) throws SQLException {\n        try {\n            return rs.getDate(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(String columnLabel) throws SQLException {\n        try {\n            return rs.getTime(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(String columnLabel) throws SQLException {\n        try {\n            return rs.getTimestamp(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.InputStream getAsciiStream(String columnLabel) throws SQLException {\n        try {\n            return rs.getAsciiStream(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    @Deprecated\n    public java.io.InputStream getUnicodeStream(String columnLabel) throws SQLException {\n        try {\n            return rs.getUnicodeStream(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.InputStream getBinaryStream(String columnLabel) throws SQLException {\n        try {\n            return rs.getBinaryStream(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        try {\n            return rs.getWarnings();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        try {\n            rs.clearWarnings();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getCursorName() throws SQLException {\n        try {\n            return rs.getCursorName();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException {\n        try {\n            return rs.getMetaData();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Object getObject(int columnIndex) throws SQLException {\n        try {\n            return rs.getObject(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Object getObject(String columnLabel) throws SQLException {\n        try {\n            return rs.getObject(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int findColumn(String columnLabel) throws SQLException {\n        try {\n            return rs.findColumn(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getCharacterStream(int columnIndex) throws SQLException {\n        try {\n            return rs.getCharacterStream(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getCharacterStream(String columnLabel) throws SQLException {\n        try {\n            return rs.getCharacterStream(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {\n        try {\n            return rs.getBigDecimal(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String columnLabel) throws SQLException {\n        try {\n            return rs.getBigDecimal(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean isBeforeFirst() throws SQLException {\n        try {\n            return rs.isBeforeFirst();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean isAfterLast() throws SQLException {\n        try {\n            return rs.isAfterLast();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean isFirst() throws SQLException {\n        try {\n            return rs.isFirst();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean isLast() throws SQLException {\n        try {\n            return rs.isLast();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void beforeFirst() throws SQLException {\n        try {\n            rs.beforeFirst();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void afterLast() throws SQLException {\n        try {\n            rs.afterLast();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean first() throws SQLException {\n        try {\n            return rs.first();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean last() throws SQLException {\n        try {\n            return rs.last();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getRow() throws SQLException {\n        try {\n            return rs.getRow();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean absolute(int row) throws SQLException {\n        try {\n            return rs.absolute(row);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean relative(int rows) throws SQLException {\n        try {\n            return rs.relative(rows);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean previous() throws SQLException {\n        try {\n            boolean moreRows = rs.previous();\n\n            if (moreRows) {\n                cursorIndex--;\n            }\n\n            return moreRows;\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setFetchDirection(int direction) throws SQLException {\n        try {\n            rs.setFetchDirection(direction);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getFetchDirection() throws SQLException {\n        try {\n            return rs.getFetchDirection();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setFetchSize(int rows) throws SQLException {\n        try {\n            rs.setFetchSize(rows);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getFetchSize() throws SQLException {\n        try {\n            return rs.getFetchSize();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getType() throws SQLException {\n        try {\n            return rs.getType();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getConcurrency() throws SQLException {\n        try {\n            return rs.getConcurrency();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean rowUpdated() throws SQLException {\n        try {\n            return rs.rowUpdated();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean rowInserted() throws SQLException {\n        try {\n            return rs.rowInserted();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean rowDeleted() throws SQLException {\n        try {\n            return rs.rowDeleted();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNull(int columnIndex) throws SQLException {\n        try {\n            rs.updateNull(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBoolean(int columnIndex, boolean x) throws SQLException {\n        try {\n            rs.updateBoolean(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateByte(int columnIndex, byte x) throws SQLException {\n        try {\n            rs.updateByte(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateShort(int columnIndex, short x) throws SQLException {\n        try {\n            rs.updateShort(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateInt(int columnIndex, int x) throws SQLException {\n        try {\n            rs.updateInt(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateLong(int columnIndex, long x) throws SQLException {\n        try {\n            rs.updateLong(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateFloat(int columnIndex, float x) throws SQLException {\n        try {\n            rs.updateFloat(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateDouble(int columnIndex, double x) throws SQLException {\n        try {\n            rs.updateDouble(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {\n        try {\n            rs.updateBigDecimal(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateString(int columnIndex, String x) throws SQLException {\n        try {\n            rs.updateString(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBytes(int columnIndex, byte[] x) throws SQLException {\n        try {\n            rs.updateBytes(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {\n        try {\n            rs.updateDate(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {\n        try {\n            rs.updateTime(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {\n        try {\n            rs.updateTimestamp(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {\n        try {\n            rs.updateAsciiStream(columnIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {\n        try {\n            rs.updateBinaryStream(columnIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {\n        try {\n            rs.updateCharacterStream(columnIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {\n        try {\n            rs.updateObject(columnIndex, x, scaleOrLength);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateObject(int columnIndex, Object x) throws SQLException {\n        try {\n            rs.updateObject(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNull(String columnLabel) throws SQLException {\n        try {\n            rs.updateNull(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBoolean(String columnLabel, boolean x) throws SQLException {\n        try {\n            rs.updateBoolean(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateByte(String columnLabel, byte x) throws SQLException {\n        try {\n            rs.updateByte(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateShort(String columnLabel, short x) throws SQLException {\n        try {\n            rs.updateShort(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateInt(String columnLabel, int x) throws SQLException {\n        try {\n            rs.updateInt(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateLong(String columnLabel, long x) throws SQLException {\n        try {\n            rs.updateLong(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateFloat(String columnLabel, float x) throws SQLException {\n        try {\n            rs.updateFloat(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateDouble(String columnLabel, double x) throws SQLException {\n        try {\n            rs.updateDouble(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {\n        try {\n            rs.updateBigDecimal(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateString(String columnLabel, String x) throws SQLException {\n        try {\n            rs.updateString(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBytes(String columnLabel, byte[] x) throws SQLException {\n        try {\n            rs.updateBytes(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateDate(String columnLabel, java.sql.Date x) throws SQLException {\n        try {\n            rs.updateDate(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateTime(String columnLabel, java.sql.Time x) throws SQLException {\n        try {\n            rs.updateTime(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateTimestamp(String columnLabel, java.sql.Timestamp x) throws SQLException {\n        try {\n            rs.updateTimestamp(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, java.io.InputStream x, int length) throws SQLException {\n        try {\n            rs.updateAsciiStream(columnLabel, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, java.io.InputStream x, int length) throws SQLException {\n        try {\n            rs.updateBinaryStream(columnLabel, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, java.io.Reader reader, int length) throws SQLException {\n        try {\n            rs.updateCharacterStream(columnLabel, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {\n        try {\n            rs.updateObject(columnLabel, x, scaleOrLength);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateObject(String columnLabel, Object x) throws SQLException {\n        try {\n            rs.updateObject(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void insertRow() throws SQLException {\n        try {\n            rs.insertRow();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateRow() throws SQLException {\n        try {\n            rs.updateRow();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void deleteRow() throws SQLException {\n        try {\n            rs.deleteRow();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void refreshRow() throws SQLException {\n        try {\n            rs.refreshRow();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void cancelRowUpdates() throws SQLException {\n        try {\n            rs.cancelRowUpdates();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void moveToInsertRow() throws SQLException {\n        try {\n            rs.moveToInsertRow();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void moveToCurrentRow() throws SQLException {\n        try {\n            rs.moveToCurrentRow();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Statement getStatement() {\n        return stmt;\n    }\n\n    @Override\n    public Object getObject(int columnIndex, java.util.Map<String, Class<?>> map) throws SQLException {\n        try {\n            return rs.getObject(columnIndex, map);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Ref getRef(int columnIndex) throws SQLException {\n        try {\n            return rs.getRef(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Blob getBlob(int columnIndex) throws SQLException {\n        try {\n            return rs.getBlob(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Clob getClob(int columnIndex) throws SQLException {\n        try {\n            return rs.getClob(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Array getArray(int columnIndex) throws SQLException {\n        try {\n            return rs.getArray(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Object getObject(String columnLabel, java.util.Map<String, Class<?>> map) throws SQLException {\n        try {\n            return rs.getObject(columnLabel, map);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Ref getRef(String columnLabel) throws SQLException {\n        try {\n            return rs.getRef(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Blob getBlob(String columnLabel) throws SQLException {\n        try {\n            return rs.getBlob(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Clob getClob(String columnLabel) throws SQLException {\n        try {\n            return rs.getClob(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public Array getArray(String columnLabel) throws SQLException {\n        try {\n            return rs.getArray(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {\n        try {\n            return rs.getDate(columnIndex, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Date getDate(String columnLabel, Calendar cal) throws SQLException {\n        try {\n            return rs.getDate(columnLabel, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {\n        try {\n            return rs.getTime(columnIndex, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Time getTime(String columnLabel, Calendar cal) throws SQLException {\n        try {\n            return rs.getTime(columnLabel, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {\n        try {\n            return rs.getTimestamp(columnIndex, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {\n        try {\n            return rs.getTimestamp(columnLabel, cal);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.net.URL getURL(int columnIndex) throws SQLException {\n        try {\n            return rs.getURL(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.net.URL getURL(String columnLabel) throws SQLException {\n        try {\n            return rs.getURL(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateRef(int columnIndex, java.sql.Ref x) throws SQLException {\n        try {\n            rs.updateRef(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateRef(String columnLabel, java.sql.Ref x) throws SQLException {\n        try {\n            rs.updateRef(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, java.sql.Blob x) throws SQLException {\n        try {\n            rs.updateBlob(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, java.sql.Blob x) throws SQLException {\n        try {\n            rs.updateBlob(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateClob(int columnIndex, java.sql.Clob x) throws SQLException {\n        try {\n            rs.updateClob(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateClob(String columnLabel, java.sql.Clob x) throws SQLException {\n        try {\n            rs.updateClob(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateArray(int columnIndex, java.sql.Array x) throws SQLException {\n        try {\n            rs.updateArray(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateArray(String columnLabel, java.sql.Array x) throws SQLException {\n        try {\n            rs.updateArray(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public RowId getRowId(int columnIndex) throws SQLException {\n        try {\n            return rs.getRowId(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public RowId getRowId(String columnLabel) throws SQLException {\n        try {\n            return rs.getRowId(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateRowId(int columnIndex, RowId x) throws SQLException {\n        try {\n            rs.updateRowId(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateRowId(String columnLabel, RowId x) throws SQLException {\n        try {\n            rs.updateRowId(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int getHoldability() throws SQLException {\n        try {\n            return rs.getHoldability();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        return this.closed;\n    }\n\n    @Override\n    public void updateNString(int columnIndex, String nString) throws SQLException {\n        try {\n            rs.updateNString(columnIndex, nString);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNString(String columnLabel, String nString) throws SQLException {\n        try {\n            rs.updateNString(columnLabel, nString);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, NClob nClob) throws SQLException {\n        try {\n            rs.updateNClob(columnIndex, nClob);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, NClob nClob) throws SQLException {\n        try {\n            rs.updateNClob(columnLabel, nClob);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public NClob getNClob(int columnIndex) throws SQLException {\n        try {\n            return rs.getNClob(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public NClob getNClob(String columnLabel) throws SQLException {\n        try {\n            return rs.getNClob(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public SQLXML getSQLXML(int columnIndex) throws SQLException {\n        try {\n            return rs.getSQLXML(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public SQLXML getSQLXML(String columnLabel) throws SQLException {\n        try {\n            return rs.getSQLXML(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {\n        try {\n            rs.updateSQLXML(columnIndex, xmlObject);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {\n        try {\n            rs.updateSQLXML(columnLabel, xmlObject);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getNString(int columnIndex) throws SQLException {\n        try {\n            return rs.getNString(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public String getNString(String columnLabel) throws SQLException {\n        try {\n            return rs.getNString(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {\n        try {\n            return rs.getNCharacterStream(columnIndex);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public java.io.Reader getNCharacterStream(String columnLabel) throws SQLException {\n        try {\n            return rs.getNCharacterStream(columnLabel);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNCharacterStream(int columnIndex, java.io.Reader x, long length) throws SQLException {\n        try {\n            rs.updateNCharacterStream(columnIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNCharacterStream(String columnLabel, java.io.Reader reader, long length) throws SQLException {\n        try {\n            rs.updateNCharacterStream(columnLabel, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, java.io.InputStream x, long length) throws SQLException {\n        try {\n            rs.updateAsciiStream(columnIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, java.io.InputStream x, long length) throws SQLException {\n        try {\n            rs.updateBinaryStream(columnIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, java.io.Reader x, long length) throws SQLException {\n        try {\n            rs.updateCharacterStream(columnIndex, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, java.io.InputStream x, long length) throws SQLException {\n        try {\n            rs.updateAsciiStream(columnLabel, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, java.io.InputStream x, long length) throws SQLException {\n        try {\n            rs.updateBinaryStream(columnLabel, x, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, java.io.Reader reader, long length) throws SQLException {\n        try {\n            rs.updateCharacterStream(columnLabel, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {\n        try {\n            rs.updateBlob(columnIndex, inputStream, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {\n        try {\n            rs.updateBlob(columnLabel, inputStream, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {\n        try {\n            rs.updateClob(columnIndex, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {\n        try {\n            rs.updateClob(columnLabel, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {\n        try {\n            rs.updateNClob(columnIndex, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {\n        try {\n            rs.updateNClob(columnLabel, reader, length);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNCharacterStream(int columnIndex, java.io.Reader x) throws SQLException {\n        try {\n            rs.updateNCharacterStream(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNCharacterStream(String columnLabel, java.io.Reader reader) throws SQLException {\n        try {\n            rs.updateNCharacterStream(columnLabel, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, java.io.InputStream x) throws SQLException {\n        try {\n            rs.updateAsciiStream(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, java.io.InputStream x) throws SQLException {\n        try {\n            rs.updateBinaryStream(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, java.io.Reader x) throws SQLException {\n        try {\n            rs.updateCharacterStream(columnIndex, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, java.io.InputStream x) throws SQLException {\n        try {\n            rs.updateAsciiStream(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, java.io.InputStream x) throws SQLException {\n        try {\n            rs.updateBinaryStream(columnLabel, x);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, java.io.Reader reader) throws SQLException {\n        try {\n            rs.updateCharacterStream(columnLabel, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {\n        try {\n            rs.updateBlob(columnIndex, inputStream);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {\n        try {\n            rs.updateBlob(columnLabel, inputStream);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Reader reader) throws SQLException {\n        try {\n            rs.updateClob(columnIndex, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Reader reader) throws SQLException {\n        try {\n            rs.updateClob(columnLabel, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, Reader reader) throws SQLException {\n        try {\n            rs.updateNClob(columnIndex, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, Reader reader) throws SQLException {\n        try {\n            rs.updateNClob(columnLabel, reader);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {\n        try {\n            return rs.getObject(columnIndex, type);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {\n        try {\n            return rs.getObject(columnLabel, type);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.VERSION;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.MySqlUtils;\n\nimport java.net.SocketTimeoutException;\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidPooledStatement extends PoolableWrapper implements Statement {\n    private static final Log LOG = LogFactory.getLog(DruidPooledStatement.class);\n\n    private final Statement stmt;\n    protected DruidPooledConnection conn;\n    protected List<ResultSet> resultSetTrace;\n    protected boolean closed;\n    protected int fetchRowPeak = -1;\n    protected int exceptionCount;\n\n    public DruidPooledStatement(DruidPooledConnection conn, Statement stmt) {\n        super(stmt);\n\n        this.conn = conn;\n        this.stmt = stmt;\n    }\n\n    protected void addResultSetTrace(ResultSet resultSet) {\n        if (resultSetTrace == null) {\n            resultSetTrace = new ArrayList<ResultSet>(1);\n        } else if (resultSetTrace.size() > 0) {\n            int lastIndex = resultSetTrace.size() - 1;\n            ResultSet lastResultSet = resultSetTrace.get(lastIndex);\n            try {\n                if (lastResultSet.isClosed()) {\n                    resultSetTrace.set(lastIndex, resultSet);\n                    return;\n                }\n            } catch (SQLException ex) {\n                // skip\n            }\n        }\n\n        resultSetTrace.add(resultSet);\n    }\n\n    protected void recordFetchRowCount(int fetchRowCount) {\n        if (fetchRowPeak < fetchRowCount) {\n            fetchRowPeak = fetchRowCount;\n        }\n    }\n\n    public int getFetchRowPeak() {\n        return fetchRowPeak;\n    }\n\n    protected SQLException checkException(Throwable error) throws SQLException {\n        String sql = null;\n        if (this instanceof DruidPooledPreparedStatement) {\n            sql = ((DruidPooledPreparedStatement) this).getSql();\n        }\n\n        handleSocketTimeout(error);\n\n        exceptionCount++;\n        return conn.handleException(error, sql);\n    }\n\n    protected SQLException checkException(Throwable error, String sql) throws SQLException {\n        handleSocketTimeout(error);\n\n        exceptionCount++;\n        return conn.handleException(error, sql);\n    }\n\n    protected void handleSocketTimeout(Throwable error) throws SQLException {\n        if (this.conn == null\n                || this.conn.transactionInfo != null\n                || this.conn.holder == null) {\n            return;\n        }\n\n        DruidDataSource dataSource = null;\n\n        final DruidConnectionHolder holder = this.conn.holder;\n        if (holder.dataSource instanceof DruidDataSource) {\n            dataSource = (DruidDataSource) holder.dataSource;\n        }\n        if (dataSource == null) {\n            return;\n        }\n\n        if (!dataSource.killWhenSocketReadTimeout) {\n            return;\n        }\n\n        SQLException sqlException = null;\n        if (error instanceof SQLException) {\n            sqlException = (SQLException) error;\n        }\n\n        if (sqlException == null) {\n            return;\n        }\n\n        Throwable cause = error.getCause();\n        boolean socketReadTimeout = cause instanceof SocketTimeoutException\n                && \"Read timed out\".equals(cause.getMessage());\n        if (!socketReadTimeout) {\n            return;\n        }\n\n        if (!JdbcUtils.isMysqlDbType(dataSource.dbTypeName)) {\n            return;\n        }\n\n        String killQuery = MySqlUtils.buildKillQuerySql(this.conn.getConnection(), (SQLException) error);\n\n        if (killQuery == null) {\n            return;\n        }\n\n        DruidPooledConnection killQueryConn = null;\n        Statement killQueryStmt = null;\n\n        try {\n            killQueryConn = dataSource.getConnection(1000);\n            if (killQueryConn == null) {\n                return;\n            }\n\n            killQueryStmt = killQueryConn.createStatement();\n            killQueryStmt.execute(killQuery);\n\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(killQuery + \" success.\");\n            }\n        } catch (Exception ex) {\n            LOG.warn(killQuery + \" error.\", ex);\n        } finally {\n            JdbcUtils.close(killQueryStmt);\n            JdbcUtils.close(killQueryConn);\n        }\n    }\n\n    public DruidPooledConnection getPoolableConnection() {\n        return conn;\n    }\n\n    public Statement getStatement() {\n        return stmt;\n    }\n\n    protected void checkOpen() throws SQLException {\n        if (closed) {\n            Throwable disableError = null;\n            if (this.conn != null) {\n                disableError = this.conn.getDisableError();\n            }\n\n            if (disableError != null) {\n                throw new SQLException(\"statement is closed\", disableError);\n            } else {\n                throw new SQLException(\"statement is closed\");\n            }\n        }\n    }\n\n    protected void clearResultSet() {\n        if (resultSetTrace == null) {\n            return;\n        }\n\n        for (ResultSet rs : resultSetTrace) {\n            try {\n                if (!rs.isClosed()) {\n                    rs.close();\n                }\n            } catch (SQLException ex) {\n                LOG.error(\"clearResultSet error\", ex);\n            }\n        }\n        resultSetTrace.clear();\n    }\n\n    public void incrementExecuteCount() {\n        final DruidPooledConnection conn = this.getPoolableConnection();\n        if (conn == null) {\n            return;\n        }\n\n        final DruidConnectionHolder holder = conn.getConnectionHolder();\n        if (holder == null) {\n            return;\n        }\n\n        final DruidAbstractDataSource dataSource = holder.getDataSource();\n        if (dataSource == null) {\n            return;\n        }\n\n        dataSource.incrementExecuteCount();\n    }\n\n    public void incrementExecuteBatchCount() {\n        final DruidPooledConnection conn = this.getPoolableConnection();\n        if (conn == null) {\n            return;\n        }\n\n        final DruidConnectionHolder holder = conn.getConnectionHolder();\n        if (holder == null) {\n            return;\n        }\n\n        if (holder.getDataSource() == null) {\n            return;\n        }\n\n        final DruidAbstractDataSource dataSource = holder.getDataSource();\n        if (dataSource == null) {\n            return;\n        }\n\n        dataSource.incrementExecuteBatchCount();\n    }\n\n    public void incrementExecuteUpdateCount() {\n        final DruidPooledConnection conn = this.getPoolableConnection();\n        if (conn == null) {\n            return;\n        }\n\n        final DruidConnectionHolder holder = conn.getConnectionHolder();\n        if (holder == null) {\n            return;\n        }\n\n        final DruidAbstractDataSource dataSource = holder.getDataSource();\n        if (dataSource == null) {\n            return;\n        }\n\n        dataSource.incrementExecuteUpdateCount();\n    }\n\n    public void incrementExecuteQueryCount() {\n        final DruidPooledConnection conn = this.conn;\n        if (conn == null) {\n            return;\n        }\n\n        final DruidConnectionHolder holder = conn.holder;\n        if (holder == null) {\n            return;\n        }\n\n        final DruidAbstractDataSource dataSource = holder.dataSource;\n        if (dataSource == null) {\n            return;\n        }\n\n        dataSource.executeQueryCount++;\n    }\n\n    protected void transactionRecord(String sql) throws SQLException {\n        conn.transactionRecord(sql);\n    }\n\n    @Override\n    public final ResultSet executeQuery(String sql) throws SQLException {\n        checkOpen();\n\n        incrementExecuteQueryCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            ResultSet rs = stmt.executeQuery(sql);\n\n            if (rs == null) {\n                return rs;\n            }\n\n            DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);\n            addResultSetTrace(poolableResultSet);\n\n            return poolableResultSet;\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public final int executeUpdate(String sql) throws SQLException {\n        checkOpen();\n\n        incrementExecuteUpdateCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.executeUpdate(sql);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    protected final void errorCheck(Throwable t) {\n        String errorClassName = t.getClass().getName();\n        if (errorClassName.endsWith(\".CommunicationsException\")\n                && conn.holder != null\n                && conn.holder.dataSource.testWhileIdle) {\n            DruidConnectionHolder holder = conn.holder;\n            DruidAbstractDataSource dataSource = holder.dataSource;\n\n            long currentTimeMillis = System.currentTimeMillis();\n            long lastActiveTimeMillis = holder.lastActiveTimeMillis;\n\n            if (lastActiveTimeMillis < holder.lastKeepTimeMillis) {\n                lastActiveTimeMillis = holder.lastKeepTimeMillis;\n            }\n\n            long idleMillis = currentTimeMillis - lastActiveTimeMillis;\n            long lastValidIdleMillis = currentTimeMillis - holder.lastActiveTimeMillis;\n\n            String errorMsg = \"CommunicationsException, druid version \" + VERSION.getVersionNumber()\n                    + \", jdbcUrl : \" + dataSource.jdbcUrl\n                    + \", testWhileIdle \" + dataSource.testWhileIdle\n                    + \", idle millis \" + idleMillis\n                    + \", minIdle \" + dataSource.minIdle\n                    + \", poolingCount \" + dataSource.getPoolingCount()\n                    + \", timeBetweenEvictionRunsMillis \" + dataSource.timeBetweenEvictionRunsMillis\n                    + \", lastValidIdleMillis \" + lastValidIdleMillis\n                    + \", driver \" + dataSource.driver.getClass().getName();\n\n            if (dataSource.exceptionSorter != null) {\n                errorMsg += \", exceptionSorter \" + dataSource.exceptionSorter.getClass().getName();\n            }\n\n            LOG.error(errorMsg);\n        }\n    }\n\n    @Override\n    public final int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n        checkOpen();\n\n        incrementExecuteUpdateCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.executeUpdate(sql, autoGeneratedKeys);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public final int executeUpdate(String sql, int[] columnIndexes) throws SQLException {\n        checkOpen();\n\n        incrementExecuteUpdateCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.executeUpdate(sql, columnIndexes);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public final int executeUpdate(String sql, String[] columnNames) throws SQLException {\n        checkOpen();\n\n        incrementExecuteUpdateCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.executeUpdate(sql, columnNames);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public final boolean execute(String sql, int autoGeneratedKeys) throws SQLException {\n        checkOpen();\n\n        incrementExecuteCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.execute(sql, autoGeneratedKeys);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public final boolean execute(String sql, int[] columnIndexes) throws SQLException {\n        checkOpen();\n\n        incrementExecuteCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.execute(sql, columnIndexes);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public final boolean execute(String sql, String[] columnNames) throws SQLException {\n        checkOpen();\n\n        incrementExecuteCount();\n        transactionRecord(sql);\n\n        conn.beforeExecute();\n        try {\n            return stmt.execute(sql, columnNames);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public int getMaxFieldSize() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getMaxFieldSize();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void close() throws SQLException {\n        if (this.closed) {\n            return;\n        }\n\n        clearResultSet();\n        if (stmt != null) {\n            stmt.close();\n        }\n        this.closed = true;\n\n        DruidConnectionHolder connHolder = conn.getConnectionHolder();\n        if (connHolder != null) {\n            connHolder.removeTrace(this);\n        }\n    }\n\n    @Override\n    public void setMaxFieldSize(int max) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setMaxFieldSize(max);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getMaxRows() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getMaxRows();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setMaxRows(int max) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setMaxRows(max);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final void setEscapeProcessing(boolean enable) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setEscapeProcessing(enable);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getQueryTimeout() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getQueryTimeout();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setQueryTimeout(int seconds) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setQueryTimeout(seconds);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final void cancel() throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.cancel();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final SQLWarning getWarnings() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getWarnings();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final void clearWarnings() throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.clearWarnings();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final void setCursorName(String name) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setCursorName(name);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final boolean execute(String sql) throws SQLException {\n        checkOpen();\n\n        incrementExecuteCount();\n        transactionRecord(sql);\n\n        try {\n            return stmt.execute(sql);\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t, sql);\n        }\n    }\n\n    @Override\n    public final ResultSet getResultSet() throws SQLException {\n        checkOpen();\n\n        try {\n            ResultSet rs = stmt.getResultSet();\n            if (rs == null) {\n                return null;\n            }\n\n            DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);\n            addResultSetTrace(poolableResultSet);\n\n            return poolableResultSet;\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getUpdateCount() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getUpdateCount();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final boolean getMoreResults() throws SQLException {\n        checkOpen();\n\n        try {\n            boolean moreResults = stmt.getMoreResults();\n\n            if (resultSetTrace != null && resultSetTrace.size() > 0) {\n                ResultSet lastResultSet = resultSetTrace.get(resultSetTrace.size() - 1);\n                if (lastResultSet instanceof DruidPooledResultSet) {\n                    DruidPooledResultSet pooledResultSet = ((DruidPooledResultSet) lastResultSet);\n                    pooledResultSet.closed = true;\n                }\n            }\n\n            return moreResults;\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setFetchDirection(int direction) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setFetchDirection(direction);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getFetchDirection() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getFetchDirection();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public void setFetchSize(int rows) throws SQLException {\n        checkOpen();\n\n        try {\n            stmt.setFetchSize(rows);\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getFetchSize() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getFetchSize();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getResultSetConcurrency() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getResultSetConcurrency();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getResultSetType() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getResultSetType();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final void addBatch(String sql) throws SQLException {\n        checkOpen();\n\n        transactionRecord(sql);\n\n        try {\n            stmt.addBatch(sql);\n        } catch (Throwable t) {\n            throw checkException(t, sql);\n        }\n    }\n\n    @Override\n    public final void clearBatch() throws SQLException {\n        if (closed) {\n            return;\n        }\n\n        try {\n            stmt.clearBatch();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public int[] executeBatch() throws SQLException {\n        checkOpen();\n\n        incrementExecuteBatchCount();\n\n        conn.beforeExecute();\n        try {\n            return stmt.executeBatch();\n        } catch (Throwable t) {\n            errorCheck(t);\n\n            throw checkException(t);\n        } finally {\n            conn.afterExecute();\n        }\n    }\n\n    @Override\n    public final Connection getConnection() throws SQLException {\n        checkOpen();\n\n        return conn;\n    }\n\n    @Override\n    public final boolean getMoreResults(int current) throws SQLException {\n        checkOpen();\n\n        try {\n            boolean results = stmt.getMoreResults(current);\n\n            if (resultSetTrace != null && resultSetTrace.size() > 0) {\n                ResultSet lastResultSet = resultSetTrace.get(resultSetTrace.size() - 1);\n                if (lastResultSet instanceof DruidPooledResultSet) {\n                    DruidPooledResultSet pooledResultSet = ((DruidPooledResultSet) lastResultSet);\n                    pooledResultSet.closed = true;\n                }\n            }\n\n            return results;\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final ResultSet getGeneratedKeys() throws SQLException {\n        checkOpen();\n\n        try {\n            ResultSet rs = stmt.getGeneratedKeys();\n\n            DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs);\n\n            addResultSetTrace(poolableResultSet);\n\n            return poolableResultSet;\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final int getResultSetHoldability() throws SQLException {\n        checkOpen();\n\n        try {\n            return stmt.getResultSetHoldability();\n        } catch (Throwable t) {\n            throw checkException(t);\n        }\n    }\n\n    @Override\n    public final boolean isClosed() throws SQLException {\n        return closed;\n    }\n\n    @Override\n    public final void setPoolable(boolean poolable) throws SQLException {\n        if (poolable) {\n            return;\n        }\n\n        throw new SQLException(\"not support\");\n    }\n\n    @Override\n    public final boolean isPoolable() throws SQLException {\n        return false;\n    }\n\n    public String toString() {\n        return stmt.toString();\n    }\n\n    public void closeOnCompletion() throws SQLException {\n        stmt.closeOnCompletion();\n    }\n\n    public boolean isCloseOnCompletion() throws SQLException {\n        return stmt.isCloseOnCompletion();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/DruidStatementConnection.java",
    "content": "/*\r\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n *      http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\npackage com.alibaba.druid.pool;\r\n\r\nimport java.sql.Array;\r\nimport java.sql.Blob;\r\nimport java.sql.CallableStatement;\r\nimport java.sql.Clob;\r\nimport java.sql.Connection;\r\nimport java.sql.DatabaseMetaData;\r\nimport java.sql.NClob;\r\nimport java.sql.PreparedStatement;\r\nimport java.sql.SQLClientInfoException;\r\nimport java.sql.SQLException;\r\nimport java.sql.SQLWarning;\r\nimport java.sql.SQLXML;\r\nimport java.sql.Savepoint;\r\nimport java.sql.Statement;\r\nimport java.sql.Struct;\r\nimport java.util.Map;\r\nimport java.util.Properties;\r\nimport java.util.concurrent.Executor;\r\n\r\n/**\r\n * @author zrlw [zrlw@sina.com]\r\n */\r\npublic class DruidStatementConnection implements Connection {\r\n    protected final Connection conn;\r\n    protected final Statement statement;\r\n\r\n    public DruidStatementConnection(Connection conn, Statement statement) {\r\n        this.conn = conn;\r\n        this.statement = statement;\r\n    }\r\n\r\n    public Connection getConnection() {\r\n        return conn;\r\n    }\r\n\r\n    public Statement getStatement() {\r\n        return statement;\r\n    }\r\n\r\n    @Override\r\n    public <T> T unwrap(Class<T> iface) throws SQLException {\r\n        return conn.unwrap(iface);\r\n    }\r\n\r\n    @Override\r\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\r\n        return conn.isWrapperFor(iface);\r\n    }\r\n\r\n    @Override\r\n    public Statement createStatement() throws SQLException {\r\n        return conn.createStatement();\r\n    }\r\n\r\n    @Override\r\n    public PreparedStatement prepareStatement(String sql) throws SQLException {\r\n        return conn.prepareStatement(sql);\r\n    }\r\n\r\n    @Override\r\n    public CallableStatement prepareCall(String sql) throws SQLException {\r\n        return conn.prepareCall(sql);\r\n    }\r\n\r\n    @Override\r\n    public String nativeSQL(String sql) throws SQLException {\r\n        return conn.nativeSQL(sql);\r\n    }\r\n\r\n    @Override\r\n    public void setAutoCommit(boolean autoCommit) throws SQLException {\r\n        conn.setAutoCommit(autoCommit);\r\n    }\r\n\r\n    @Override\r\n    public boolean getAutoCommit() throws SQLException {\r\n        return conn.getAutoCommit();\r\n    }\r\n\r\n    @Override\r\n    public void commit() throws SQLException {\r\n        conn.commit();\r\n    }\r\n\r\n    @Override\r\n    public void rollback() throws SQLException {\r\n        conn.rollback();\r\n    }\r\n\r\n    @Override\r\n    public void close() throws SQLException {\r\n        statement.close();\r\n        conn.close();\r\n    }\r\n\r\n    @Override\r\n    public boolean isClosed() throws SQLException {\r\n        return conn.isClosed();\r\n    }\r\n\r\n    @Override\r\n    public DatabaseMetaData getMetaData() throws SQLException {\r\n        return conn.getMetaData();\r\n    }\r\n\r\n    @Override\r\n    public void setReadOnly(boolean readOnly) throws SQLException {\r\n        conn.setReadOnly(readOnly);\r\n    }\r\n\r\n    @Override\r\n    public boolean isReadOnly() throws SQLException {\r\n        return conn.isReadOnly();\r\n    }\r\n\r\n    @Override\r\n    public void setCatalog(String catalog) throws SQLException {\r\n        conn.setCatalog(catalog);\r\n    }\r\n\r\n    @Override\r\n    public String getCatalog() throws SQLException {\r\n         return conn.getCatalog();\r\n    }\r\n\r\n    @Override\r\n    public void setTransactionIsolation(int level) throws SQLException {\r\n        conn.setTransactionIsolation(level);\r\n    }\r\n\r\n    @Override\r\n    public int getTransactionIsolation() throws SQLException {\r\n        return conn.getTransactionIsolation();\r\n    }\r\n\r\n    @Override\r\n    public SQLWarning getWarnings() throws SQLException {\r\n        return conn.getWarnings();\r\n    }\r\n\r\n    @Override\r\n    public void clearWarnings() throws SQLException {\r\n        conn.clearWarnings();\r\n    }\r\n\r\n    @Override\r\n    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {\r\n        return conn.createStatement(resultSetType, resultSetConcurrency);\r\n    }\r\n\r\n    @Override\r\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)\r\n            throws SQLException {\r\n        return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);\r\n    }\r\n\r\n    @Override\r\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\r\n        return conn.prepareCall(sql, resultSetType, resultSetConcurrency);\r\n    }\r\n\r\n    @Override\r\n    public Map<String, Class<?>> getTypeMap() throws SQLException {\r\n        return conn.getTypeMap();\r\n    }\r\n\r\n    @Override\r\n    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {\r\n        conn.setTypeMap(map);\r\n    }\r\n\r\n    @Override\r\n    public void setHoldability(int holdability) throws SQLException {\r\n        conn.setHoldability(holdability);\r\n    }\r\n\r\n    @Override\r\n    public int getHoldability() throws SQLException {\r\n        return conn.getHoldability();\r\n    }\r\n\r\n    @Override\r\n    public Savepoint setSavepoint() throws SQLException {\r\n        return conn.setSavepoint();\r\n    }\r\n\r\n    @Override\r\n    public Savepoint setSavepoint(String name) throws SQLException {\r\n        return conn.setSavepoint(name);\r\n    }\r\n\r\n    @Override\r\n    public void rollback(Savepoint savepoint) throws SQLException {\r\n        conn.rollback(savepoint);\r\n    }\r\n\r\n    @Override\r\n    public void releaseSavepoint(Savepoint savepoint) throws SQLException {\r\n        conn.releaseSavepoint(savepoint);\r\n    }\r\n\r\n    @Override\r\n    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)\r\n            throws SQLException {\r\n        return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);\r\n    }\r\n\r\n    @Override\r\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,\r\n            int resultSetHoldability) throws SQLException {\r\n        return conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\r\n    }\r\n\r\n    @Override\r\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,\r\n            int resultSetHoldability) throws SQLException {\r\n        return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\r\n    }\r\n\r\n    @Override\r\n    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {\r\n        return conn.prepareStatement(sql, autoGeneratedKeys);\r\n    }\r\n\r\n    @Override\r\n    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {\r\n        return conn.prepareStatement(sql, columnIndexes);\r\n    }\r\n\r\n    @Override\r\n    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {\r\n        return conn.prepareStatement(sql, columnNames);\r\n    }\r\n\r\n    @Override\r\n    public Clob createClob() throws SQLException {\r\n        return conn.createClob();\r\n    }\r\n\r\n    @Override\r\n    public Blob createBlob() throws SQLException {\r\n        return conn.createBlob();\r\n    }\r\n\r\n    @Override\r\n    public NClob createNClob() throws SQLException {\r\n        return conn.createNClob();\r\n    }\r\n\r\n    @Override\r\n    public SQLXML createSQLXML() throws SQLException {\r\n        return conn.createSQLXML();\r\n    }\r\n\r\n    @Override\r\n    public boolean isValid(int timeout) throws SQLException {\r\n        return conn.isValid(timeout);\r\n    }\r\n\r\n    @Override\r\n    public void setClientInfo(String name, String value) throws SQLClientInfoException {\r\n        conn.setClientInfo(name, value);\r\n    }\r\n\r\n    @Override\r\n    public void setClientInfo(Properties properties) throws SQLClientInfoException {\r\n        conn.setClientInfo(properties);\r\n    }\r\n\r\n    @Override\r\n    public String getClientInfo(String name) throws SQLException {\r\n        return conn.getClientInfo(name);\r\n    }\r\n\r\n    @Override\r\n    public Properties getClientInfo() throws SQLException {\r\n        return conn.getClientInfo();\r\n    }\r\n\r\n    @Override\r\n    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {\r\n        return conn.createArrayOf(typeName, elements);\r\n    }\r\n\r\n    @Override\r\n    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {\r\n        return conn.createStruct(typeName, attributes);\r\n    }\r\n\r\n    @Override\r\n    public void setSchema(String schema) throws SQLException {\r\n        conn.setSchema(schema);\r\n        \r\n    }\r\n\r\n    @Override\r\n    public String getSchema() throws SQLException {\r\n        return conn.getSchema();\r\n    }\r\n\r\n    @Override\r\n    public void abort(Executor executor) throws SQLException {\r\n        statement.close();\r\n        conn.abort(executor);\r\n    }\r\n\r\n    @Override\r\n    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {\r\n        conn.setNetworkTimeout(executor, milliseconds);\r\n    }\r\n\r\n    @Override\r\n    public int getNetworkTimeout() throws SQLException {\r\n        return conn.getNetworkTimeout();\r\n    }\r\n}\r\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\n/**\n * An interface to allow for exception evaluation.\n */\npublic interface ExceptionSorter {\n    /**\n     * Returns true or false whether or not the exception is fatal.\n     *\n     * @param e the exception\n     * @return true or false if the exception is fatal.\n     */\n    boolean isExceptionFatal(SQLException e);\n\n    void configFromProperties(Properties properties);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/GetConnectionTimeoutException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.SQLException;\n\npublic class GetConnectionTimeoutException extends SQLException {\n    private static final long serialVersionUID = 1L;\n\n    public GetConnectionTimeoutException(String reason) {\n        super(reason);\n    }\n\n    public GetConnectionTimeoutException(String message, Throwable cause) {\n        super(message, cause);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/JDBC4ValidConnectionChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\n/**\n * Common ValidConnectionChecker for JDBC4 to use Connection.isValid.\n *\n * Author : kimmking(kimmking@apache.org)\n * create 2023/3/4 16:48\n * Since 1.2.17\n */\npublic class JDBC4ValidConnectionChecker implements ValidConnectionChecker {\n    @Override\n    public boolean isValidConnection(Connection c, String query, int validationQueryTimeout) throws Exception {\n        Connection conn = c;\n        if (conn instanceof DruidPooledConnection) {\n            conn = ((DruidPooledConnection) conn).getConnection();\n        }\n        return conn.isValid(validationQueryTimeout);\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ManagedDataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport javax.management.ObjectName;\nimport javax.sql.DataSource;\n\npublic interface ManagedDataSource extends DataSource {\n    boolean isEnable();\n\n    void setEnable(boolean value);\n\n    ObjectName getObjectName();\n\n    void setObjectName(ObjectName objectName);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/PoolableWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.proxy.jdbc.WrapperProxy;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Wrapper;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class PoolableWrapper implements Wrapper {\n    private final Wrapper wrapper;\n\n    public PoolableWrapper(Wrapper wraaper) {\n        this.wrapper = wraaper;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (null == wrapper) {\n            //Best to log error.\n            return false;\n        }\n\n        if (iface == null) {\n            return false;\n        }\n\n        if (wrapper instanceof DruidStatementConnection) {\n            if (iface.isInstance(((DruidStatementConnection) wrapper).getConnection())) {\n                return true;\n            }\n        }\n\n        if (iface == wrapper.getClass()) {\n            return true;\n        }\n\n        if (iface == this.getClass()) {\n            return true;\n        }\n\n        if (!(wrapper instanceof WrapperProxy)) {\n            if (iface.isInstance(wrapper)) {\n                return true;\n            }\n        }\n\n        return wrapper.isWrapperFor(iface);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (null == wrapper) {\n            //Best to log error.\n            return null;\n        }\n\n        if (iface == null) {\n            return null;\n        }\n\n        if (wrapper instanceof DruidStatementConnection) {\n            Connection conn = ((DruidStatementConnection) wrapper).getConnection();\n            if (iface.isAssignableFrom(conn.getClass())) {\n                return (T) conn;\n            }\n        }\n\n        if (iface == wrapper.getClass()) {\n            return (T) wrapper;\n        }\n\n        if (iface == this.getClass()) {\n            return (T) this;\n        }\n\n        if (!(wrapper instanceof WrapperProxy)) {\n            if (iface.isInstance(wrapper)) {\n                return (T) wrapper;\n            }\n        }\n\n        return wrapper.unwrap(iface);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/PreparedStatementHolder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\n\nimport java.sql.PreparedStatement;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic final class PreparedStatementHolder {\n    public final PreparedStatementKey key;\n    public final PreparedStatement statement;\n    protected int hitCount;\n\n    protected int fetchRowPeak = -1;\n\n    private int defaultRowPrefetch = -1;\n    private int rowPrefetch = -1;\n\n    private boolean enterOracleImplicitCache;\n\n    protected int inUseCount;\n    private boolean pooling;\n\n    public PreparedStatementHolder(PreparedStatementKey key, PreparedStatement stmt) {\n        this.key = key;\n        this.statement = stmt;\n    }\n\n    public boolean isEnterOracleImplicitCache() {\n        return enterOracleImplicitCache;\n    }\n\n    public void setEnterOracleImplicitCache(boolean enterOracleImplicitCache) {\n        this.enterOracleImplicitCache = enterOracleImplicitCache;\n    }\n\n    public int getDefaultRowPrefetch() {\n        return defaultRowPrefetch;\n    }\n\n    public void setDefaultRowPrefetch(int defaultRowPrefetch) {\n        this.defaultRowPrefetch = defaultRowPrefetch;\n    }\n\n    public int getRowPrefetch() {\n        return rowPrefetch;\n    }\n\n    public void setRowPrefetch(int rowPrefetch) {\n        this.rowPrefetch = rowPrefetch;\n    }\n\n    public int getFetchRowPeak() {\n        return fetchRowPeak;\n    }\n\n    public void setFetchRowPeak(int fetchRowPeak) {\n        if (fetchRowPeak > this.fetchRowPeak) {\n            this.fetchRowPeak = fetchRowPeak;\n        }\n    }\n\n    public void incrementHitCount() {\n        hitCount++;\n    }\n\n    public int getHitCount() {\n        return hitCount;\n    }\n\n    public boolean isInUse() {\n        return inUseCount > 0;\n    }\n\n    public void incrementInUseCount() {\n        inUseCount++;\n    }\n\n    public void decrementInUseCount() {\n        inUseCount--;\n    }\n\n    public int getInUseCount() {\n        return inUseCount;\n    }\n\n    public boolean isPooling() {\n        return pooling;\n    }\n\n    public void setPooling(boolean pooling) {\n        this.pooling = pooling;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/PreparedStatementPool.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.OracleUtils;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class PreparedStatementPool {\n    private static final Log LOG = LogFactory.getLog(PreparedStatementPool.class);\n\n    private final LRUCache map;\n    private final DruidAbstractDataSource dataSource;\n\n    public PreparedStatementPool(DruidConnectionHolder holder) {\n        this.dataSource = holder.getDataSource();\n        int initCapacity = holder.getDataSource().getMaxPoolPreparedStatementPerConnectionSize();\n        if (initCapacity <= 0) {\n            initCapacity = 16;\n        }\n        map = new LRUCache(initCapacity);\n    }\n\n    public static enum MethodType {\n        M1, M2, M3, M4, M5, M6, Precall_1, Precall_2, Precall_3\n    }\n\n    public PreparedStatementHolder get(PreparedStatementKey key) throws SQLException {\n        PreparedStatementHolder holder = map.get(key);\n\n        if (holder != null) {\n            if (holder.isInUse() && (!dataSource.isSharePreparedStatements())) {\n                return null;\n            }\n\n            holder.incrementHitCount();\n            dataSource.incrementCachedPreparedStatementHitCount();\n            if (holder.isEnterOracleImplicitCache()) {\n                OracleUtils.exitImplicitCacheToActive(holder.statement);\n            }\n        } else {\n            dataSource.incrementCachedPreparedStatementMissCount();\n        }\n\n        return holder;\n    }\n\n    public void remove(PreparedStatementHolder stmtHolder) throws SQLException {\n        if (stmtHolder == null) {\n            return;\n        }\n        map.remove(stmtHolder.key);\n        closeRemovedStatement(stmtHolder);\n    }\n\n    public void put(PreparedStatementHolder stmtHolder) throws SQLException {\n        PreparedStatement stmt = stmtHolder.statement;\n\n        if (stmt == null) {\n            return;\n        }\n\n        if (dataSource.isOracle() && dataSource.isUseOracleImplicitCache()) {\n            OracleUtils.enterImplicitCache(stmt);\n            stmtHolder.setEnterOracleImplicitCache(true);\n        } else {\n            stmtHolder.setEnterOracleImplicitCache(false);\n        }\n\n        PreparedStatementHolder oldStmtHolder = map.put(stmtHolder.key, stmtHolder);\n\n        if (oldStmtHolder == stmtHolder) {\n            return;\n        }\n\n        if (oldStmtHolder != null) {\n            oldStmtHolder.setPooling(false);\n            closeRemovedStatement(oldStmtHolder);\n        } else {\n            if (stmtHolder.getHitCount() == 0) {\n                dataSource.incrementCachedPreparedStatementCount();\n            }\n        }\n\n        stmtHolder.setPooling(true);\n\n        if (LOG.isDebugEnabled()) {\n            String message = null;\n            if (stmtHolder.statement instanceof PreparedStatementProxy) {\n                PreparedStatementProxy stmtProxy = (PreparedStatementProxy) stmtHolder.statement;\n                if (stmtProxy instanceof CallableStatementProxy) {\n                    message = \"{conn-\" + stmtProxy.getConnectionProxy().getId() + \", cstmt-\" + stmtProxy.getId()\n                            + \"} enter cache\";\n                } else {\n                    message = \"{conn-\" + stmtProxy.getConnectionProxy().getId() + \", pstmt-\" + stmtProxy.getId()\n                            + \"} enter cache\";\n                }\n            } else {\n                message = \"stmt enter cache\";\n            }\n\n            LOG.debug(message);\n        }\n    }\n\n    public void clear() {\n        Iterator<Entry<PreparedStatementKey, PreparedStatementHolder>> iter = map.entrySet().iterator();\n        while (iter.hasNext()) {\n            Entry<PreparedStatementKey, PreparedStatementHolder> entry = iter.next();\n\n            closeRemovedStatement(entry.getValue());\n\n            iter.remove();\n        }\n    }\n\n    public void closeRemovedStatement(PreparedStatementHolder holder) {\n        if (LOG.isDebugEnabled()) {\n            String message = null;\n            if (holder.statement instanceof PreparedStatementProxy) {\n                PreparedStatementProxy stmtProxy = (PreparedStatementProxy) holder.statement;\n                if (stmtProxy instanceof CallableStatementProxy) {\n                    message = \"{conn-\" + stmtProxy.getConnectionProxy().getId() + \", cstmt-\" + stmtProxy.getId()\n                            + \"} exit cache\";\n                } else {\n                    message = \"{conn-\" + stmtProxy.getConnectionProxy().getId() + \", pstmt-\" + stmtProxy.getId()\n                            + \"} exit cache\";\n                }\n            } else {\n                message = \"stmt exit cache\";\n            }\n\n            LOG.debug(message);\n        }\n\n        holder.setPooling(false);\n        if (holder.isInUse()) {\n            return;\n        }\n\n        if (holder.isEnterOracleImplicitCache()) {\n            try {\n                OracleUtils.exitImplicitCacheToClose(holder.statement);\n            } catch (Exception ex) {\n                LOG.error(\"exitImplicitCacheToClose error\", ex);\n            }\n        }\n        dataSource.closePreapredStatement(holder);\n    }\n\n    public Map<PreparedStatementKey, PreparedStatementHolder> getMap() {\n        return map;\n    }\n\n    public int size() {\n        return this.map.size();\n    }\n\n    public class LRUCache extends LinkedHashMap<PreparedStatementKey, PreparedStatementHolder> {\n        private static final long serialVersionUID = 1L;\n\n        public LRUCache(int maxSize) {\n            super(maxSize, 0.75f, true);\n        }\n\n        protected boolean removeEldestEntry(Entry<PreparedStatementKey, PreparedStatementHolder> eldest) {\n            boolean remove = (size() > dataSource.getMaxPoolPreparedStatementPerConnectionSize());\n\n            if (remove) {\n                closeRemovedStatement(eldest.getValue());\n            }\n\n            return remove;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ValidConnectionChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\npublic interface ValidConnectionChecker {\n    boolean isValidConnection(Connection c, String query, int validationQueryTimeout) throws Exception;\n\n    /**\n     * @param properties the properties to be used for configuration\n     * @since 0.2.21\n     */\n    void configFromProperties(Properties properties);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ValidConnectionCheckerAdapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n * @since 0.2.21\n */\npublic class ValidConnectionCheckerAdapter implements ValidConnectionChecker {\n    @Override\n    public boolean isValidConnection(Connection conn, String query, int validationQueryTimeout) throws Exception {\n        if (StringUtils.isEmpty(query)) {\n            return true;\n        }\n        return execValidQuery(conn, query, validationQueryTimeout);\n    }\n\n    public static boolean execValidQuery(Connection conn, String query, int validationQueryTimeout) throws Exception {\n        // using raw connection for createStatement to speed up validation by skipping all filters.\n        Connection rawConn;\n        if (conn instanceof DruidPooledConnection) {\n            conn = ((DruidPooledConnection) conn).getConnection();\n        }\n        if (conn instanceof ConnectionProxyImpl) {\n            rawConn = ((ConnectionProxyImpl) conn).getConnectionRaw();\n        } else {\n            rawConn = conn;\n        }\n\n        Statement stmt = null;\n        boolean isDruidStatementConnection;\n        if (rawConn instanceof DruidStatementConnection) {\n            stmt = ((DruidStatementConnection) rawConn).getStatement();\n            isDruidStatementConnection = true;\n        } else {\n            isDruidStatementConnection = false;\n        }\n        ResultSet rs = null;\n        try {\n            if (!isDruidStatementConnection) {\n                stmt = rawConn.createStatement();\n            }\n            if (validationQueryTimeout > 0) {\n                stmt.setQueryTimeout(validationQueryTimeout);\n            }\n            rs = stmt.executeQuery(query);\n            return rs.next();\n        } finally {\n            JdbcUtils.close(rs);\n            if (!isDruidStatementConnection) {\n                JdbcUtils.close(stmt);\n            }\n        }\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/WrapperAdapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool;\n\nimport java.sql.Wrapper;\n\npublic class WrapperAdapter implements Wrapper {\n    public WrapperAdapter() {\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) {\n        return iface != null && iface.isInstance(this);\n\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) {\n        if (iface == null) {\n            return null;\n        }\n\n        if (iface.isInstance(this)) {\n            return (T) this;\n        }\n\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/DataSourceCreator.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha;\n\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.SQLException;\n\n/**\n * An utility class to create DruidDataSource dynamically.\n *\n * @author DigitalSonic\n */\npublic class DataSourceCreator {\n    public static DruidDataSource create(String name, String url, String username, String password,\n                                         HighAvailableDataSource haDataSource) throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setName(name + \"-\" + System.identityHashCode(dataSource));\n        dataSource.setUrl(url);\n        dataSource.setUsername(username);\n        dataSource.setPassword(password);\n\n        dataSource.setDriverClassName(haDataSource.getDriverClassName());\n        dataSource.setConnectProperties(haDataSource.getConnectProperties());\n        dataSource.setConnectionProperties(haDataSource.getConnectionProperties());\n\n        dataSource.setInitialSize(haDataSource.getInitialSize());\n        dataSource.setMaxActive(haDataSource.getMaxActive());\n        dataSource.setMinIdle(haDataSource.getMinIdle());\n        dataSource.setMaxWait(haDataSource.getMaxWait());\n\n        dataSource.setValidationQuery(haDataSource.getValidationQuery());\n        dataSource.setValidationQueryTimeout(haDataSource.getValidationQueryTimeout());\n        dataSource.setTestOnBorrow(haDataSource.isTestOnBorrow());\n        dataSource.setTestOnReturn(haDataSource.isTestOnReturn());\n        dataSource.setTestWhileIdle(haDataSource.isTestWhileIdle());\n\n        dataSource.setPoolPreparedStatements(haDataSource.isPoolPreparedStatements());\n        dataSource.setSharePreparedStatements(haDataSource.isSharePreparedStatements());\n        dataSource.setMaxPoolPreparedStatementPerConnectionSize(\n                haDataSource.getMaxPoolPreparedStatementPerConnectionSize());\n\n        dataSource.setQueryTimeout(haDataSource.getQueryTimeout());\n        dataSource.setTransactionQueryTimeout(haDataSource.getTransactionQueryTimeout());\n\n        dataSource.setTimeBetweenEvictionRunsMillis(haDataSource.getTimeBetweenEvictionRunsMillis());\n        dataSource.setMinEvictableIdleTimeMillis(haDataSource.getMinEvictableIdleTimeMillis());\n        dataSource.setMaxEvictableIdleTimeMillis(haDataSource.getMaxEvictableIdleTimeMillis());\n        dataSource.setPhyTimeoutMillis(haDataSource.getPhyTimeoutMillis());\n        dataSource.setTimeBetweenConnectErrorMillis(haDataSource.getTimeBetweenConnectErrorMillis());\n\n        dataSource.setRemoveAbandoned(haDataSource.isRemoveAbandoned());\n        dataSource.setRemoveAbandonedTimeoutMillis(haDataSource.getRemoveAbandonedTimeoutMillis());\n        dataSource.setLogAbandoned(haDataSource.isLogAbandoned());\n\n        dataSource.setProxyFilters(haDataSource.getProxyFilters());\n        dataSource.setFilters(haDataSource.getFilters());\n        dataSource.setLogWriter(haDataSource.getLogWriter());\n\n        dataSource.init();\n\n        return dataSource;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/HighAvailableDataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.pool.DruidAbstractDataSource;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.WrapperAdapter;\nimport com.alibaba.druid.pool.ha.node.FileNodeListener;\nimport com.alibaba.druid.pool.ha.node.NodeListener;\nimport com.alibaba.druid.pool.ha.node.PoolUpdater;\nimport com.alibaba.druid.pool.ha.selector.DataSourceSelector;\nimport com.alibaba.druid.pool.ha.selector.DataSourceSelectorEnum;\nimport com.alibaba.druid.pool.ha.selector.DataSourceSelectorFactory;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.sql.DataSource;\n\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.logging.Logger;\n\n/**\n * DataSource class which contains multiple DataSource objects.\n *\n * @author DigitalSonic\n */\npublic class HighAvailableDataSource extends WrapperAdapter implements DataSource {\n    private static final Log LOG = LogFactory.getLog(HighAvailableDataSource.class);\n    private static final String DEFAULT_DATA_SOURCE_FILE = \"ha-datasource.properties\";\n\n    // Properties copied from DruidAbstractDataSource BEGIN\n    private String driverClassName;\n    private Properties connectProperties = new Properties();\n    private String connectionProperties;\n\n    private int initialSize = DruidAbstractDataSource.DEFAULT_INITIAL_SIZE;\n    private int maxActive = DruidAbstractDataSource.DEFAULT_MAX_ACTIVE_SIZE;\n    private int minIdle = DruidAbstractDataSource.DEFAULT_MIN_IDLE;\n    private long maxWait = DruidAbstractDataSource.DEFAULT_MAX_WAIT;\n\n    private String validationQuery = DruidAbstractDataSource.DEFAULT_VALIDATION_QUERY;\n    private int validationQueryTimeout = -1;\n    private boolean testOnBorrow = DruidAbstractDataSource.DEFAULT_TEST_ON_BORROW;\n    private boolean testOnReturn = DruidAbstractDataSource.DEFAULT_TEST_ON_RETURN;\n    private boolean testWhileIdle = DruidAbstractDataSource.DEFAULT_WHILE_IDLE;\n\n    private boolean poolPreparedStatements;\n    private boolean sharePreparedStatements;\n    private int maxPoolPreparedStatementPerConnectionSize = 10;\n\n    private int queryTimeout;\n    private int transactionQueryTimeout;\n\n    private long timeBetweenEvictionRunsMillis = DruidAbstractDataSource.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;\n    private long minEvictableIdleTimeMillis = DruidAbstractDataSource.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;\n    private long maxEvictableIdleTimeMillis = DruidAbstractDataSource.DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS;\n    private long phyTimeoutMillis = DruidAbstractDataSource.DEFAULT_PHY_TIMEOUT_MILLIS;\n    private long timeBetweenConnectErrorMillis = DruidAbstractDataSource.DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS;\n\n    private boolean removeAbandoned;\n    private long removeAbandonedTimeoutMillis = 300 * 1000;\n    private boolean logAbandoned;\n\n    private String filters;\n    private List<Filter> proxyFilters = new CopyOnWriteArrayList<Filter>();\n    private PrintWriter logWriter = new PrintWriter(System.out);\n    // Properties copied from DruidAbstractDataSource END\n\n    private Map<String, DataSource> dataSourceMap = new ConcurrentHashMap<String, DataSource>();\n    private Set<String> blacklist = new CopyOnWriteArraySet<String>();\n    private DataSourceSelector selector;\n    private String dataSourceFile = DEFAULT_DATA_SOURCE_FILE;\n    private String propertyPrefix = \"\";\n    private int poolPurgeIntervalSeconds = PoolUpdater.DEFAULT_INTERVAL;\n    private boolean allowEmptyPoolWhenUpdate;\n\n    private volatile boolean inited;\n\n    private PoolUpdater poolUpdater = new PoolUpdater(this);\n    private NodeListener nodeListener;\n\n    public void init() {\n        if (inited) {\n            return;\n        }\n        synchronized (this) {\n            if (inited) {\n                return;\n            }\n            if (dataSourceMap == null || dataSourceMap.isEmpty()) {\n                poolUpdater.setIntervalSeconds(poolPurgeIntervalSeconds);\n                poolUpdater.setAllowEmptyPool(allowEmptyPoolWhenUpdate);\n                poolUpdater.init();\n                createNodeMap();\n            }\n            if (selector == null) {\n                setSelector(DataSourceSelectorEnum.RANDOM.getName());\n            }\n            if (dataSourceMap == null || dataSourceMap.isEmpty()) {\n                LOG.warn(\"There is NO DataSource available!!! Please check your configuration.\");\n            }\n            inited = true;\n        }\n    }\n\n    public void close() {\n        destroy();\n    }\n\n    public void destroy() {\n        if (nodeListener != null) {\n            nodeListener.destroy();\n        }\n        if (poolUpdater != null) {\n            poolUpdater.destroy();\n        }\n        if (selector != null) {\n            selector.destroy();\n        }\n        if (dataSourceMap == null || dataSourceMap.isEmpty()) {\n            return;\n        }\n        for (DataSource dataSource : dataSourceMap.values()) {\n            if (dataSource instanceof DruidDataSource) {\n                ((DruidDataSource) dataSource).close();\n            }\n        }\n    }\n\n    public void setTargetDataSource(String targetName) {\n        selector.setTarget(targetName);\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        init();\n        DataSource dataSource = selector.get();\n        if (dataSource == null) {\n            LOG.warn(\"Can NOT obtain DataSource, return null.\");\n            return null;\n        }\n        return dataSource.getConnection();\n    }\n\n    public String getDataSourceFile() {\n        return dataSourceFile;\n    }\n\n    public void setDataSourceFile(String dataSourceFile) {\n        this.dataSourceFile = dataSourceFile;\n    }\n\n    public String getPropertyPrefix() {\n        return propertyPrefix;\n    }\n\n    public void setPropertyPrefix(String propertyPrefix) {\n        this.propertyPrefix = propertyPrefix;\n    }\n\n    public void setDataSourceMap(Map<String, DataSource> dataSourceMap) {\n        if (dataSourceMap != null) {\n            this.dataSourceMap = dataSourceMap;\n        }\n    }\n\n    public Map<String, DataSource> getDataSourceMap() {\n        return dataSourceMap;\n    }\n\n    public Map<String, DataSource> getAvailableDataSourceMap() {\n        Map<String, DataSource> map = new ConcurrentHashMap<String, DataSource>(this.dataSourceMap);\n        for (String n : blacklist) {\n            map.remove(n);\n        }\n        return map;\n    }\n\n    public void addBlackList(String name) {\n        if (dataSourceMap.containsKey(name)) {\n            blacklist.add(name);\n        } else {\n            LOG.info(\"Key \" + name + \" is NOT existed, ignore it.\");\n        }\n    }\n\n    public void removeBlackList(String name) {\n        blacklist.remove(name);\n    }\n\n    public boolean isInBlackList(String name) {\n        return blacklist.contains(name);\n    }\n\n    public void setSelector(String name) {\n        DataSourceSelector selector = DataSourceSelectorFactory.getSelector(name, this);\n        if (selector != null) {\n            selector.init();\n            setDataSourceSelector(selector);\n        }\n    }\n\n    public String getSelector() {\n        return selector == null ? null : selector.getName();\n    }\n\n    @Override\n    public Connection getConnection(String username, String password) throws SQLException {\n        throw new UnsupportedOperationException(\"Not supported by HighAvailableDataSource.\");\n    }\n\n    @Override\n    public void setLoginTimeout(int seconds) {\n        DriverManager.setLoginTimeout(seconds);\n    }\n\n    @Override\n    public int getLoginTimeout() {\n        return DriverManager.getLoginTimeout();\n    }\n\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public void setConnectionProperties(String connectionProperties) {\n        this.connectionProperties = connectionProperties;\n\n        // COPIED FROM DruidAbstractDataSource.setConnectionProperties()\n\n        if (connectionProperties == null || connectionProperties.trim().length() == 0) {\n            setConnectProperties(null);\n            return;\n        }\n\n        String[] entries = connectionProperties.split(\";\");\n        Properties properties = new Properties();\n        for (int i = 0; i < entries.length; i++) {\n            String entry = entries[i];\n            if (entry.length() > 0) {\n                int index = entry.indexOf('=');\n                if (index > 0) {\n                    String name = entry.substring(0, index);\n                    String value = entry.substring(index + 1);\n                    properties.setProperty(name, value);\n                } else {\n                    // no value is empty string which is how java.util.Properties works\n                    properties.setProperty(entry, \"\");\n                }\n            }\n        }\n\n        setConnectProperties(properties);\n    }\n\n    public void setConnectProperties(Properties connectProperties) {\n        if (connectProperties == null) {\n            connectProperties = new Properties();\n        }\n\n        if (this.connectProperties != null) {\n            this.connectProperties.putAll(connectProperties);\n        } else {\n            this.connectProperties = connectProperties;\n        }\n    }\n\n    private void createNodeMap() {\n        if (nodeListener == null) {\n            // Compatible with the old version.\n            // Create a FileNodeListener to watch the dataSourceFile.\n            FileNodeListener listener = new FileNodeListener();\n            listener.setFile(dataSourceFile);\n            listener.setPrefix(propertyPrefix);\n            nodeListener = listener;\n        }\n        nodeListener.setObserver(poolUpdater);\n        nodeListener.init();\n        nodeListener.update(); // Do update in the current Thread at the startup\n    }\n\n    public boolean isAllowEmptyPoolWhenUpdate() {\n        return allowEmptyPoolWhenUpdate;\n    }\n\n    public void setAllowEmptyPoolWhenUpdate(boolean allowEmptyPoolWhenUpdate) {\n        this.allowEmptyPoolWhenUpdate = allowEmptyPoolWhenUpdate;\n    }\n\n    // Getters & Setters\n\n    public int getPoolPurgeIntervalSeconds() {\n        return poolPurgeIntervalSeconds;\n    }\n\n    public void setPoolPurgeIntervalSeconds(int poolPurgeIntervalSeconds) {\n        this.poolPurgeIntervalSeconds = poolPurgeIntervalSeconds;\n    }\n\n    public NodeListener getNodeListener() {\n        return nodeListener;\n    }\n\n    public void setNodeListener(NodeListener nodeListener) {\n        this.nodeListener = nodeListener;\n    }\n\n    public DataSourceSelector getDataSourceSelector() {\n        return this.selector;\n    }\n\n    public void setDataSourceSelector(DataSourceSelector dataSourceSelector) {\n        this.selector = dataSourceSelector;\n    }\n\n    @Override\n    public PrintWriter getLogWriter() throws SQLException {\n        return logWriter;\n    }\n\n    @Override\n    public void setLogWriter(PrintWriter out) throws SQLException {\n        this.logWriter = out;\n    }\n\n    public String getDriverClassName() {\n        return driverClassName;\n    }\n\n    public void setDriverClassName(String driverClassName) {\n        this.driverClassName = driverClassName;\n    }\n\n    public Properties getConnectProperties() {\n        return connectProperties;\n    }\n\n    public int getInitialSize() {\n        return initialSize;\n    }\n\n    public void setInitialSize(int initialSize) {\n        this.initialSize = initialSize;\n    }\n\n    public int getMaxActive() {\n        return maxActive;\n    }\n\n    public void setMaxActive(int maxActive) {\n        this.maxActive = maxActive;\n    }\n\n    public int getMinIdle() {\n        return minIdle;\n    }\n\n    public void setMinIdle(int minIdle) {\n        this.minIdle = minIdle;\n    }\n\n    public long getMaxWait() {\n        return maxWait;\n    }\n\n    public void setMaxWait(long maxWait) {\n        this.maxWait = maxWait;\n    }\n\n    public String getValidationQuery() {\n        return validationQuery;\n    }\n\n    public void setValidationQuery(String validationQuery) {\n        this.validationQuery = validationQuery;\n    }\n\n    public int getValidationQueryTimeout() {\n        return validationQueryTimeout;\n    }\n\n    public void setValidationQueryTimeout(int validationQueryTimeout) {\n        this.validationQueryTimeout = validationQueryTimeout;\n    }\n\n    public boolean isTestOnBorrow() {\n        return testOnBorrow;\n    }\n\n    public void setTestOnBorrow(boolean testOnBorrow) {\n        this.testOnBorrow = testOnBorrow;\n    }\n\n    public boolean isTestOnReturn() {\n        return testOnReturn;\n    }\n\n    public void setTestOnReturn(boolean testOnReturn) {\n        this.testOnReturn = testOnReturn;\n    }\n\n    public boolean isTestWhileIdle() {\n        return testWhileIdle;\n    }\n\n    public void setTestWhileIdle(boolean testWhileIdle) {\n        this.testWhileIdle = testWhileIdle;\n    }\n\n    public boolean isPoolPreparedStatements() {\n        return poolPreparedStatements;\n    }\n\n    public void setPoolPreparedStatements(boolean poolPreparedStatements) {\n        this.poolPreparedStatements = poolPreparedStatements;\n    }\n\n    public boolean isSharePreparedStatements() {\n        return sharePreparedStatements;\n    }\n\n    public void setSharePreparedStatements(boolean sharePreparedStatements) {\n        this.sharePreparedStatements = sharePreparedStatements;\n    }\n\n    public int getMaxPoolPreparedStatementPerConnectionSize() {\n        return maxPoolPreparedStatementPerConnectionSize;\n    }\n\n    public void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize) {\n        this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;\n    }\n\n    public int getQueryTimeout() {\n        return queryTimeout;\n    }\n\n    public void setQueryTimeout(int queryTimeout) {\n        this.queryTimeout = queryTimeout;\n    }\n\n    public int getTransactionQueryTimeout() {\n        return transactionQueryTimeout;\n    }\n\n    public void setTransactionQueryTimeout(int transactionQueryTimeout) {\n        this.transactionQueryTimeout = transactionQueryTimeout;\n    }\n\n    public long getTimeBetweenEvictionRunsMillis() {\n        return timeBetweenEvictionRunsMillis;\n    }\n\n    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {\n        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;\n    }\n\n    public long getMinEvictableIdleTimeMillis() {\n        return minEvictableIdleTimeMillis;\n    }\n\n    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {\n        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;\n    }\n\n    public long getMaxEvictableIdleTimeMillis() {\n        return maxEvictableIdleTimeMillis;\n    }\n\n    public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {\n        this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;\n    }\n\n    public long getPhyTimeoutMillis() {\n        return phyTimeoutMillis;\n    }\n\n    public void setPhyTimeoutMillis(long phyTimeoutMillis) {\n        this.phyTimeoutMillis = phyTimeoutMillis;\n    }\n\n    public long getTimeBetweenConnectErrorMillis() {\n        return timeBetweenConnectErrorMillis;\n    }\n\n    public void setTimeBetweenConnectErrorMillis(long timeBetweenConnectErrorMillis) {\n        this.timeBetweenConnectErrorMillis = timeBetweenConnectErrorMillis;\n    }\n\n    public boolean isRemoveAbandoned() {\n        return removeAbandoned;\n    }\n\n    public void setRemoveAbandoned(boolean removeAbandoned) {\n        this.removeAbandoned = removeAbandoned;\n    }\n\n    public long getRemoveAbandonedTimeoutMillis() {\n        return removeAbandonedTimeoutMillis;\n    }\n\n    public void setRemoveAbandonedTimeoutMillis(long removeAbandonedTimeoutMillis) {\n        this.removeAbandonedTimeoutMillis = removeAbandonedTimeoutMillis;\n    }\n\n    public boolean isLogAbandoned() {\n        return logAbandoned;\n    }\n\n    public void setLogAbandoned(boolean logAbandoned) {\n        this.logAbandoned = logAbandoned;\n    }\n\n    public String getConnectionProperties() {\n        return connectionProperties;\n    }\n\n    public String getFilters() {\n        return filters;\n    }\n\n    public void setFilters(String filters) {\n        this.filters = filters;\n    }\n\n    public List<Filter> getProxyFilters() {\n        return proxyFilters;\n    }\n\n    public void setProxyFilters(List<Filter> proxyFilters) {\n        this.proxyFilters = proxyFilters;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/PropertiesUtils.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.InputStream;\nimport java.util.*;\n\n/**\n * Utilities for Properties.\n *\n * @author DigitalSonic\n */\npublic class PropertiesUtils {\n    private static final Log LOG = LogFactory.getLog(PropertiesUtils.class);\n\n    /**\n     * Load properties from the given file into Properties.\n     */\n    public static Properties loadProperties(String file) {\n        Properties properties = new Properties();\n        if (file == null) {\n            return properties;\n        }\n\n        InputStream is = null;\n        try {\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"Trying to load \" + file + \" from FileSystem.\");\n            }\n            is = new FileInputStream(file);\n        } catch (FileNotFoundException e) {\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"Trying to load \" + file + \" from Classpath.\");\n            }\n            try {\n                is = PropertiesUtils.class.getResourceAsStream(file);\n            } catch (Exception ex) {\n                LOG.warn(\"Can not load resource \" + file, ex);\n            }\n        }\n        if (is != null) {\n            try {\n                properties.load(is);\n            } catch (Exception e) {\n                LOG.error(\"Exception occurred while loading \" + file, e);\n            } finally {\n                try {\n                    is.close();\n                } catch (Exception e) {\n                    LOG.debug(\"Can not close Inputstream.\", e);\n                }\n            }\n        } else {\n            LOG.warn(\"File \" + file + \" can't be loaded!\");\n        }\n\n        return properties;\n    }\n\n    /**\n     * Pick the name of a JDBC url. Such as xxx.url, xxx is the name.\n     */\n    public static List<String> loadNameList(Properties properties, String propertyPrefix) {\n        List<String> nameList = new ArrayList<String>();\n\n        Set<String> names = new HashSet<String>();\n        for (String n : properties.stringPropertyNames()) {\n            if (propertyPrefix != null && !propertyPrefix.isEmpty()\n                    && !n.startsWith(propertyPrefix)) {\n                continue;\n            }\n            if (n.endsWith(\".url\")) {\n                names.add(n.split(\"\\\\.url\")[0]);\n            }\n        }\n        if (!names.isEmpty()) {\n            nameList.addAll(names);\n        }\n        return nameList;\n    }\n\n    public static Properties filterPrefix(Properties properties, String prefix) {\n        if (properties == null || prefix == null || prefix.isEmpty()) {\n            return properties;\n        }\n        Properties result = new Properties();\n        for (String n : properties.stringPropertyNames()) {\n            if (n.startsWith(prefix)) {\n                result.setProperty(n, properties.getProperty(n));\n            }\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/FileNodeListener.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\nimport com.alibaba.druid.pool.ha.PropertiesUtils;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * A NodeList that monitors the change of a file.\n *\n * @author DigitalSonic\n */\npublic class FileNodeListener extends NodeListener {\n    private static final Log LOG = LogFactory.getLog(FileNodeListener.class);\n\n    private Lock lock = new ReentrantLock();\n    private String file;\n    private int intervalSeconds = 60;\n    private ScheduledExecutorService executor;\n\n    /**\n     * Start a Scheduler to check the specified file.\n     *\n     * @see #setIntervalSeconds(int)\n     * @see #update()\n     */\n    @Override\n    public void init() {\n        super.init();\n        if (intervalSeconds <= 0) {\n            intervalSeconds = 60;\n        }\n        executor = Executors.newScheduledThreadPool(1);\n        executor.scheduleAtFixedRate(new Runnable() {\n            @Override\n            public void run() {\n                if (LOG.isDebugEnabled()) {\n                    LOG.debug(\"Checking file \" + file + \" every \" + intervalSeconds + \"s.\");\n                }\n                if (!lock.tryLock()) {\n                    LOG.info(\"Can not acquire the lock, skip this time.\");\n                    return;\n                }\n                try {\n                    update();\n                } catch (Exception e) {\n                    LOG.error(\"Can NOT update the node list.\", e);\n                } finally {\n                    lock.unlock();\n                }\n            }\n        }, intervalSeconds, intervalSeconds, TimeUnit.SECONDS);\n    }\n\n    /**\n     * Load the properties file and diff with the stored Properties.\n     *\n     * @return A List of the modification\n     */\n    @Override\n    public List<NodeEvent> refresh() {\n        Properties originalProperties = PropertiesUtils.loadProperties(file);\n        List<String> nameList = PropertiesUtils.loadNameList(originalProperties, getPrefix());\n        Properties properties = new Properties();\n        for (String n : nameList) {\n            String url = originalProperties.getProperty(n + \".url\");\n            String username = originalProperties.getProperty(n + \".username\");\n            String password = originalProperties.getProperty(n + \".password\");\n            if (url == null || url.isEmpty()) {\n                LOG.warn(n + \".url is EMPTY! IGNORE!\");\n                continue;\n            } else {\n                properties.setProperty(n + \".url\", url);\n            }\n            if (username == null || username.isEmpty()) {\n                if (LOG.isDebugEnabled()) {\n                    LOG.debug(n + \".username is EMPTY. Maybe you should check the config.\");\n                }\n            } else {\n                properties.setProperty(n + \".username\", username);\n            }\n            if (password == null || password.isEmpty()) {\n                if (LOG.isDebugEnabled()) {\n                    LOG.debug(n + \".password is EMPTY. Maybe you should check the config.\");\n                }\n            } else {\n                properties.setProperty(n + \".password\", password);\n            }\n        }\n\n        List<NodeEvent> events = NodeEvent.getEventsByDiffProperties(getProperties(), properties);\n        if (events != null && !events.isEmpty()) {\n            LOG.info(events.size() + \" different(s) detected.\");\n            setProperties(properties);\n        }\n        return events;\n    }\n\n    /**\n     * Close the ScheduledExecutorService.\n     */\n    @Override\n    public void destroy() {\n        if (executor == null || executor.isShutdown()) {\n            return;\n        }\n        try {\n            executor.shutdown();\n        } catch (Exception e) {\n            LOG.error(\"Can NOT shutdown the ScheduledExecutorService.\", e);\n        }\n    }\n\n    public int getIntervalSeconds() {\n        return intervalSeconds;\n    }\n\n    public void setIntervalSeconds(int intervalSeconds) {\n        this.intervalSeconds = intervalSeconds;\n    }\n\n    public String getFile() {\n        return file;\n    }\n\n    public void setFile(String file) {\n        this.file = file;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/NodeEvent.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\nimport com.alibaba.druid.pool.ha.PropertiesUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\n\n/**\n * Define the detail of a node update event.\n *\n * @author DigitalSonic\n */\npublic class NodeEvent {\n    private NodeEventTypeEnum type;\n    private String nodeName;\n    private String url;\n    private String username;\n    private String password;\n\n    /**\n     * Diff the given two Properties.\n     *\n     * @return A List of AddEvent and DelEvent\n     */\n    public static List<NodeEvent> getEventsByDiffProperties(Properties previous, Properties next) {\n        List<String> prevNames = PropertiesUtils.loadNameList(previous, \"\");\n        List<String> nextNames = PropertiesUtils.loadNameList(next, \"\");\n\n        List<String> namesToAdd = new ArrayList<String>();\n        List<String> namesToDel = new ArrayList<String>();\n        for (String n : prevNames) {\n            if (n != null && !n.trim().isEmpty() && !nextNames.contains(n)) {\n                namesToDel.add(n);\n            }\n        }\n        for (String n : nextNames) {\n            if (n != null && !n.trim().isEmpty() && !prevNames.contains(n)) {\n                namesToAdd.add(n);\n            }\n        }\n\n        List<NodeEvent> list = new ArrayList<NodeEvent>();\n        list.addAll(generateEvents(next, namesToAdd, NodeEventTypeEnum.ADD));\n        list.addAll(generateEvents(previous, namesToDel, NodeEventTypeEnum.DELETE));\n\n        return list;\n    }\n\n    public static List<NodeEvent> generateEvents(Properties properties, List<String> names, NodeEventTypeEnum type) {\n        List<NodeEvent> list = new ArrayList<NodeEvent>();\n        for (String n : names) {\n            NodeEvent event = new NodeEvent();\n            event.setType(type);\n            event.setNodeName(n);\n            event.setUrl(properties.getProperty(n + \".url\"));\n            event.setUsername(properties.getProperty(n + \".username\"));\n            event.setPassword(properties.getProperty(n + \".password\"));\n            list.add(event);\n        }\n        return list;\n    }\n\n    @Override\n    public String toString() {\n        String str = \"NodeEvent{\" +\n                \"type=\" + type +\n                \", nodeName='\" + nodeName + '\\'' +\n                \", url='\" + url + '\\'' +\n                \", username='\" + username + '\\'';\n        if (password != null) {\n            str += \", password.length=\" + password.length();\n        }\n        str += '}';\n        return str;\n    }\n\n    public NodeEventTypeEnum getType() {\n        return type;\n    }\n\n    public void setType(NodeEventTypeEnum type) {\n        this.type = type;\n    }\n\n    public String getNodeName() {\n        return nodeName;\n    }\n\n    public void setNodeName(String nodeName) {\n        this.nodeName = nodeName;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        this.username = username;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/NodeEventTypeEnum.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\n/**\n * Enum that specifies the type of a NodeEvent.\n *\n * @author DigitalSonic\n */\npublic enum NodeEventTypeEnum {\n    ADD, DELETE\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/NodeListener.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\nimport com.alibaba.druid.DruidRuntimeException;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.*;\n\n/**\n * This abstract class defines a listener to monitor the change of DataSource nodes.\n *\n * @author DigitalSonic\n * @see Observable\n */\npublic abstract class NodeListener extends Observable {\n    private static final Log LOG = LogFactory.getLog(NodeListener.class);\n\n    private String prefix = \"\";\n    private Properties properties = new Properties();\n    private Date lastUpdateTime;\n    private Observer observer;\n\n    /**\n     * The method implements the detail update logic.\n     */\n    public abstract List<NodeEvent> refresh();\n\n    /**\n     * Do some cleanup.\n     */\n    public abstract void destroy();\n\n    /**\n     * Add the given PoolUpdater as the Observer.\n     *\n     * @see #setObserver(Observer)\n     */\n    public void init() {\n        if (observer == null) {\n            throw new DruidRuntimeException(\"No Observer(such as PoolUpdater) specified.\");\n        }\n        this.addObserver(observer);\n    }\n\n    /**\n     * Fire the refresh() method and notify the Observer.\n     *\n     * @see #refresh()\n     * @see #update(List)\n     */\n    public void update() {\n        update(refresh());\n    }\n\n    /**\n     * Notify the Observer.\n     */\n    public void update(List<NodeEvent> events) {\n        if (events != null && !events.isEmpty()) {\n            this.lastUpdateTime = new Date();\n            NodeEvent[] arr = new NodeEvent[events.size()];\n            for (int i = 0; i < events.size(); i++) {\n                arr[i] = events.get(i);\n            }\n            this.setChanged();\n            this.notifyObservers(arr);\n        }\n    }\n\n    public Observer getObserver() {\n        return observer;\n    }\n\n    public void setObserver(Observer observer) {\n        this.observer = observer;\n    }\n\n    public Date getLastUpdateTime() {\n        return lastUpdateTime;\n    }\n\n    public void setLastUpdateTime(Date lastUpdateTime) {\n        this.lastUpdateTime = lastUpdateTime;\n    }\n\n    public Properties getProperties() {\n        return properties;\n    }\n\n    public void setProperties(Properties properties) {\n        this.properties = properties;\n    }\n\n    public String getPrefix() {\n        return prefix;\n    }\n\n    public void setPrefix(String prefix) {\n        this.prefix = prefix;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/PoolUpdater.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ha.DataSourceCreator;\nimport com.alibaba.druid.pool.ha.HighAvailableDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport javax.sql.DataSource;\n\nimport java.util.*;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * Update the DataSource Connection Pool when notified.\n *\n * @author DigitalSonic\n */\npublic class PoolUpdater implements Observer {\n    public static final int DEFAULT_INTERVAL = 60;\n    private static final Log LOG = LogFactory.getLog(PoolUpdater.class);\n    private Set<String> nodesToDel = new CopyOnWriteArraySet<String>();\n    private HighAvailableDataSource highAvailableDataSource;\n\n    private Lock lock = new ReentrantLock();\n    private ScheduledExecutorService executor;\n    private int intervalSeconds = DEFAULT_INTERVAL;\n    private volatile boolean inited;\n    private boolean allowEmptyPool;\n\n    public boolean isInited() {\n        return inited;\n    }\n\n    public PoolUpdater(HighAvailableDataSource highAvailableDataSource) {\n        setHighAvailableDataSource(highAvailableDataSource);\n    }\n\n    /**\n     * Create a ScheduledExecutorService to remove unused DataSources.\n     */\n    public void init() {\n        if (inited) {\n            return;\n        }\n        synchronized (this) {\n            if (inited) {\n                return;\n            }\n            if (intervalSeconds < 10) {\n                LOG.warn(\"CAUTION: Purge interval has been set to \" + intervalSeconds\n                        + \". This value should NOT be too small.\");\n            }\n            if (intervalSeconds <= 0) {\n                intervalSeconds = DEFAULT_INTERVAL;\n            }\n            executor = Executors.newScheduledThreadPool(1);\n            executor.scheduleAtFixedRate(new Runnable() {\n                @Override\n                public void run() {\n                    if (LOG.isDebugEnabled()) {\n                        LOG.debug(\"Purging the DataSource Pool every \" + intervalSeconds + \"s.\");\n                    }\n                    try {\n                        removeDataSources();\n                    } catch (Exception e) {\n                        LOG.error(\"Exception occurred while removing DataSources.\", e);\n                    }\n                }\n            }, intervalSeconds, intervalSeconds, TimeUnit.SECONDS);\n\n            inited = true;\n        }\n    }\n\n    public void destroy() {\n        if (executor == null || executor.isShutdown()) {\n            return;\n        }\n        try {\n            executor.shutdown();\n        } catch (Exception e) {\n            LOG.error(\"Can NOT shutdown the ScheduledExecutorService.\", e);\n        }\n    }\n\n    /**\n     * Process the given NodeEvent[]. Maybe add / delete some nodes.\n     */\n    @Override\n    public void update(Observable o, Object arg) {\n        if (!(o instanceof NodeListener)) {\n            return;\n        }\n        if (arg == null || !(arg instanceof NodeEvent[])) {\n            return;\n        }\n        NodeEvent[] events = (NodeEvent[]) arg;\n\n        if (events.length <= 0) {\n            return;\n        }\n\n        LOG.info(\"Waiting for Lock to start processing NodeEvents.\");\n        lock.lock();\n        try {\n            LOG.info(\"Start processing the NodeEvent[\" + events.length + \"].\");\n            for (NodeEvent e : events) {\n                if (e.getType() == NodeEventTypeEnum.ADD) {\n                    addNode(e);\n                } else if (e.getType() == NodeEventTypeEnum.DELETE) {\n                    deleteNode(e);\n                }\n            }\n        } catch (Exception e) {\n            LOG.error(\"Exception occurred while updating Pool.\", e);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    /**\n     * Remove unused DataSources.\n     */\n    public void removeDataSources() {\n        if (nodesToDel == null || nodesToDel.isEmpty()) {\n            return;\n        }\n\n        lock.lock();\n        try {\n            Map<String, DataSource> map = highAvailableDataSource.getDataSourceMap();\n            Set<String> copySet = new HashSet<String>(nodesToDel);\n            for (String nodeName : copySet) {\n                LOG.info(\"Start removing Node \" + nodeName + \".\");\n                if (!map.containsKey(nodeName)) {\n                    LOG.info(\"Node \" + nodeName + \" is NOT existed in the map.\");\n                    cancelBlacklistNode(nodeName);\n                    continue;\n                }\n                DataSource ds = map.get(nodeName);\n                if (ds instanceof DruidDataSource) {\n                    DruidDataSource dds = (DruidDataSource) ds;\n                    int activeCount = dds.getActiveCount(); // CAUTION, activeCount MAYBE changed!\n                    if (activeCount > 0) {\n                        LOG.warn(\"Node \" + nodeName + \" is still running [activeCount=\" + activeCount\n                                + \"], try next time.\");\n                        continue;\n                    } else {\n                        LOG.info(\"Close Node \" + nodeName + \" and remove it.\");\n                        try {\n                            dds.close();\n                        } catch (Exception e) {\n                            LOG.error(\"Exception occurred while closing Node \" + nodeName\n                                    + \", just remove it.\", e);\n                        }\n                    }\n                }\n                map.remove(nodeName); // Remove the node directly if it is NOT a DruidDataSource.\n                cancelBlacklistNode(nodeName);\n            }\n        } catch (Exception e) {\n            LOG.error(\"Exception occurred while removing DataSources.\", e);\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    protected void addNode(NodeEvent event) {\n        String nodeName = event.getNodeName();\n        String url = event.getUrl();\n        String username = event.getUsername();\n        String password = event.getPassword();\n\n        Map<String, DataSource> map = highAvailableDataSource.getDataSourceMap();\n        if (nodeName == null || nodeName.isEmpty()) {\n            return;\n        }\n        LOG.info(\"Adding Node \" + nodeName + \"[url: \" + url + \", username: \" + username + \"].\");\n        if (map.containsKey(nodeName)) {\n            cancelBlacklistNode(nodeName);\n            return;\n        }\n        DruidDataSource dataSource = null;\n        try {\n            dataSource = DataSourceCreator.create(nodeName, url, username,\n                    password, this.highAvailableDataSource);\n            map.put(nodeName, dataSource);\n            LOG.info(\"Creating Node \" + nodeName + \"[url: \" + url + \", username: \" + username + \"].\");\n        } catch (Exception e) {\n            LOG.error(\"Can NOT create DataSource \" + nodeName + \". IGNORE IT.\", e);\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    protected void deleteNode(NodeEvent event) {\n        String nodeName = event.getNodeName();\n        Map<String, DataSource> map = highAvailableDataSource.getDataSourceMap();\n        if (nodeName == null || nodeName.isEmpty() || !map.containsKey(nodeName)) {\n            return;\n        }\n        map = highAvailableDataSource.getAvailableDataSourceMap();\n        if (!allowEmptyPool && map.size() == 1 && map.containsKey(nodeName)) {\n            LOG.warn(nodeName + \" is the only DataSource left, don't remove it.\");\n            return;\n        }\n        blacklistNode(nodeName);\n    }\n\n    private void cancelBlacklistNode(String nodeName) {\n        LOG.info(\"Cancel the deletion of Node \" + nodeName + \".\");\n        nodesToDel.remove(nodeName);\n        highAvailableDataSource.removeBlackList(nodeName);\n    }\n\n    private void blacklistNode(String nodeName) {\n        LOG.info(\"Deleting Node \" + nodeName + \", just add it into blacklist.\");\n        nodesToDel.add(nodeName);\n        highAvailableDataSource.addBlackList(nodeName);\n    }\n\n    public HighAvailableDataSource getHighAvailableDataSource() {\n        return highAvailableDataSource;\n    }\n\n    public void setHighAvailableDataSource(HighAvailableDataSource highAvailableDataSource) {\n        this.highAvailableDataSource = highAvailableDataSource;\n    }\n\n    public Set<String> getNodesToDel() {\n        return nodesToDel;\n    }\n\n    public int getIntervalSeconds() {\n        return intervalSeconds;\n    }\n\n    public void setIntervalSeconds(int intervalSeconds) {\n        this.intervalSeconds = intervalSeconds;\n    }\n\n    public boolean isAllowEmptyPool() {\n        return allowEmptyPool;\n    }\n\n    public void setAllowEmptyPool(boolean allowEmptyPool) {\n        this.allowEmptyPool = allowEmptyPool;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/ZookeeperNodeInfo.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\n/**\n * The information that will be added to an ephemeral node.\n *\n * @author DigitalSonic\n */\npublic class ZookeeperNodeInfo {\n    private String prefix = \"\";\n    private String host;\n    private Integer port;\n    /**\n     * Database can be the following ones:\n     * 1. Database in MySQL and PostgreSQL JDBC URL\n     * 2. ServiceName or SID in Oracle JDBC URL\n     * etc.\n     */\n    private String database;\n    private String username;\n    private String password;\n\n    public void setPrefix(String prefix) {\n        if (prefix != null && !prefix.trim().isEmpty()) {\n            this.prefix = prefix;\n            if (!prefix.endsWith(\".\")) {\n                this.prefix = prefix + \".\";\n            }\n        }\n    }\n\n    public String getPrefix() {\n        return prefix;\n    }\n\n    public String getHost() {\n        return host;\n    }\n\n    public void setHost(String host) {\n        this.host = host;\n    }\n\n    public Integer getPort() {\n        return port;\n    }\n\n    public void setPort(Integer port) {\n        this.port = port;\n    }\n\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        this.username = username;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public String getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(String database) {\n        this.database = database;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/ZookeeperNodeListener.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\nimport com.alibaba.druid.DruidRuntimeException;\nimport com.alibaba.druid.pool.ha.PropertiesUtils;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.StringUtils;\nimport org.apache.curator.framework.CuratorFramework;\nimport org.apache.curator.framework.CuratorFrameworkFactory;\nimport org.apache.curator.framework.recipes.cache.ChildData;\nimport org.apache.curator.framework.recipes.cache.PathChildrenCache;\nimport org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;\nimport org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;\nimport org.apache.curator.retry.RetryForever;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * A NodeListener that watches a Zookeeper Path.\n * e.g.\n * Path to watch:\n * <pre>\n * + ha-druid-datasources\n * |---- NodeA\n * |---- NodeB\n * </pre>\n * <p>\n * The Data of NodeA (in Java properties format):\n * <pre>\n * foo.host=xxx.xxx.xxx.xxx\n * foo.port=3308\n * foo.username=foo\n * foo.password=foo_password\n *\n * bar.host=xxx.xxx.xxx.xxx\n * bar.port=3309\n * bar.username=bar\n * bar.password=bar_password\n * bar.database=bar_database\n * </pre>\n *\n * @author DigitalSonic\n */\npublic class ZookeeperNodeListener extends NodeListener {\n    private static final Log LOG = LogFactory.getLog(ZookeeperNodeListener.class);\n    private final Lock lock = new ReentrantLock();\n    private String zkConnectString;\n    private String path = \"/ha-druid-datasources\";\n    private boolean privateZkClient; // Should I close the client?\n    private PathChildrenCache cache;\n    private CuratorFramework client;\n    /**\n     * URL Template, e.g.\n     * jdbc:mysql://${host}:${port}/${database}?useUnicode=true\n     * ${host}, ${port} and ${database} will be replaced by values in ZK\n     * ${host} can also be #{host} and #host#\n     */\n    private String urlTemplate;\n\n    /**\n     * Init a PathChildrenCache to watch the given path.\n     */\n    @Override\n    public void init() {\n        checkParameters();\n        super.init();\n        if (client == null) {\n            client = CuratorFrameworkFactory.builder()\n                    .canBeReadOnly(true)\n                    .connectionTimeoutMs(5000)\n                    .connectString(zkConnectString)\n                    .retryPolicy(new RetryForever(10000))\n                    .sessionTimeoutMs(30000)\n                    .build();\n            client.start();\n            privateZkClient = true;\n        }\n        cache = new PathChildrenCache(client, path, true);\n        cache.getListenable().addListener(new PathChildrenCacheListener() {\n            @Override\n            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {\n                try {\n                    LOG.info(\"Receive an event: \" + event.getType());\n                    lock.lock();\n                    PathChildrenCacheEvent.Type eventType = event.getType();\n                    switch (eventType) {\n                        case CHILD_REMOVED:\n                            updateSingleNode(event, NodeEventTypeEnum.DELETE);\n                            break;\n                        case CHILD_ADDED:\n                            updateSingleNode(event, NodeEventTypeEnum.ADD);\n                            break;\n                        case CONNECTION_RECONNECTED:\n                            refreshAllNodes();\n                            break;\n                        default:\n                            // CHILD_UPDATED\n                            // INITIALIZED\n                            // CONNECTION_LOST\n                            // CONNECTION_SUSPENDED\n                            LOG.info(\"Received a PathChildrenCacheEvent, IGNORE it: \" + event);\n                    }\n                } finally {\n                    lock.unlock();\n                    LOG.info(\"Finish the processing of event: \" + event.getType());\n                }\n            }\n        });\n        try {\n            // Use BUILD_INITIAL_CACHE to force build cache in the current Thread.\n            // We don't use POST_INITIALIZED_EVENT, so there's no INITIALIZED event.\n            cache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);\n        } catch (Exception e) {\n            LOG.error(\"Can't start PathChildrenCache\", e);\n        }\n    }\n\n    /**\n     * Close PathChildrenCache and CuratorFramework.\n     */\n    @Override\n    public void destroy() {\n        if (cache != null) {\n            try {\n                cache.close();\n            } catch (IOException e) {\n                LOG.error(\"IOException occurred while closing PathChildrenCache.\", e);\n            }\n        }\n        if (client != null && privateZkClient) {\n            client.close();\n        }\n    }\n\n    /**\n     * Build Properties from PathChildrenCache.\n     * Should be called after init().\n     *\n     * @see #getPropertiesFromCache()\n     */\n    @Override\n    public List<NodeEvent> refresh() {\n        lock.lock();\n        try {\n            Properties properties = getPropertiesFromCache();\n            List<NodeEvent> events = NodeEvent.getEventsByDiffProperties(getProperties(), properties);\n            if (events != null && !events.isEmpty()) {\n                setProperties(properties);\n            }\n            return events;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private void checkParameters() {\n        if (client == null && StringUtils.isEmpty(zkConnectString)) {\n            throw new DruidRuntimeException(\"ZK Client is NULL, Please set the zkConnectString.\");\n        }\n        if (StringUtils.isEmpty(path)) {\n            throw new DruidRuntimeException(\"Please set the ZooKeeper node path.\");\n        }\n        if (StringUtils.isEmpty(urlTemplate)) {\n            throw new DruidRuntimeException(\"Please set the urlTemplate.\");\n        }\n    }\n\n    private void updateSingleNode(PathChildrenCacheEvent event, NodeEventTypeEnum type) {\n        ChildData data = event.getData();\n        String nodeName = getNodeName(data);\n        List<String> names = new ArrayList<String>();\n        names.add(getPrefix() + \".\" + nodeName);\n        Properties properties = getPropertiesFromChildData(data);\n        List<NodeEvent> events = NodeEvent.generateEvents(properties, names, type);\n\n        if (events.isEmpty()) {\n            return;\n        }\n        if (type == NodeEventTypeEnum.ADD) {\n            getProperties().putAll(properties);\n        } else {\n            for (String n : properties.stringPropertyNames()) {\n                getProperties().remove(n);\n            }\n        }\n        super.update(events);\n    }\n\n    private void refreshAllNodes() {\n        try {\n            if (client.checkExists().forPath(path) == null) {\n                LOG.warn(\"PATH[\" + path + \"] is NOT existed, can NOT refresh nodes.\");\n                return;\n            }\n            cache.rebuild();\n            Properties properties = getPropertiesFromCache();\n            List<NodeEvent> events = NodeEvent.getEventsByDiffProperties(getProperties(), properties);\n            if (events != null && !events.isEmpty()) {\n                setProperties(properties);\n                super.update(events);\n            }\n        } catch (Exception e) {\n            LOG.error(\"Can NOT refresh Cache Nodes.\", e);\n        }\n    }\n\n    private Properties getPropertiesFromCache() {\n        List<ChildData> data = cache.getCurrentData();\n        Properties properties = new Properties();\n        for (ChildData c : data) {\n            properties.putAll(getPropertiesFromChildData(c));\n        }\n        return properties;\n    }\n\n    private Properties getPropertiesFromChildData(ChildData data) {\n        String dataPrefix = getPrefix();\n        Properties properties = new Properties();\n        if (data == null) {\n            return properties;\n        }\n        String nodeName = getNodeName(data);\n        String str = new String(data.getData());\n        Properties full = new Properties();\n        try {\n            full.load(new StringReader(str));\n        } catch (IOException e) {\n            LOG.error(\"Can't load Properties from String. \" + str, e);\n        }\n        Properties filtered = PropertiesUtils.filterPrefix(full, dataPrefix);\n        for (String n : filtered.stringPropertyNames()) {\n            properties.setProperty(\n                    n.replaceFirst(dataPrefix, dataPrefix + \"\\\\.\" + nodeName),\n                    filtered.getProperty(n));\n        }\n        if (!properties.containsKey(dataPrefix + \".\" + nodeName + \".url\")) {\n            properties.setProperty(dataPrefix + \".\" + nodeName + \".url\", formatUrl(filtered));\n        }\n        return properties;\n    }\n\n    private String formatUrl(Properties properties) {\n        String url = urlTemplate;\n        String dataPrefix = getPrefix();\n        if (properties.containsKey(dataPrefix + \".host\")) {\n            url = url.replace(\"${host}\", properties.getProperty(dataPrefix + \".host\"));\n            url = url.replace(\"#{host}\", properties.getProperty(dataPrefix + \".host\"));\n            url = url.replace(\"#host#\", properties.getProperty(dataPrefix + \".host\"));\n        }\n        if (properties.containsKey(dataPrefix + \".port\")) {\n            url = url.replace(\"${port}\", properties.getProperty(dataPrefix + \".port\"));\n            url = url.replace(\"#{port}\", properties.getProperty(dataPrefix + \".port\"));\n            url = url.replace(\"#port#\", properties.getProperty(dataPrefix + \".port\"));\n        }\n        if (properties.containsKey(dataPrefix + \".database\")) {\n            url = url.replace(\"${database}\", properties.getProperty(dataPrefix + \".database\"));\n            url = url.replace(\"#{database}\", properties.getProperty(dataPrefix + \".database\"));\n            url = url.replace(\"#database#\", properties.getProperty(dataPrefix + \".database\"));\n        }\n        return url;\n    }\n\n    private String getNodeName(ChildData data) {\n        String eventZkPath = data.getPath();\n        if (eventZkPath.startsWith(path + \"/\")) {\n            return eventZkPath.substring(path.length() + 1);\n        } else {\n            return eventZkPath;\n        }\n    }\n\n    public void setClient(CuratorFramework client) {\n        if (client != null) {\n            this.client = client;\n            privateZkClient = false;\n        }\n    }\n\n    public CuratorFramework getClient() {\n        return client;\n    }\n\n    public String getZkConnectString() {\n        return zkConnectString;\n    }\n\n    public void setZkConnectString(String zkConnectString) {\n        this.zkConnectString = zkConnectString;\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public String getUrlTemplate() {\n        return urlTemplate;\n    }\n\n    public void setUrlTemplate(String urlTemplate) {\n        this.urlTemplate = urlTemplate;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/node/ZookeeperNodeRegister.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.node;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport org.apache.curator.framework.CuratorFramework;\nimport org.apache.curator.framework.CuratorFrameworkFactory;\nimport org.apache.curator.framework.recipes.nodes.GroupMember;\nimport org.apache.curator.retry.RetryForever;\n\nimport java.io.IOException;\nimport java.io.StringWriter;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * A register which is used to register a node to an ephemeral node.\n *\n * @author DigitalSonic\n */\npublic class ZookeeperNodeRegister {\n    private static final Log LOG = LogFactory.getLog(ZookeeperNodeRegister.class);\n    private final Lock lock = new ReentrantLock();\n    private String zkConnectString;\n    private String path = \"/ha-druid-datasources\";\n    private CuratorFramework client;\n    private GroupMember member;\n    private boolean privateZkClient; // Should I close the client?\n\n    /**\n     * Init a CuratorFramework if there's no CuratorFramework provided.\n     */\n    public void init() {\n        if (client == null) {\n            client = CuratorFrameworkFactory.builder()\n                    .connectionTimeoutMs(5000)\n                    .connectString(zkConnectString)\n                    .retryPolicy(new RetryForever(10000))\n                    .sessionTimeoutMs(30000)\n                    .build();\n            client.start();\n            privateZkClient = true;\n        }\n    }\n\n    /**\n     * Register a Node which has a Properties as the payload.\n     * <pre>\n     * CAUTION: only one node can be registered,\n     *          if you want to register another one,\n     *          call deregister first\n     * </pre>\n     *\n     * @param payload The information used to generate the payload Properties\n     * @return true, register successfully; false, skip the registeration\n     */\n    public boolean register(String nodeId, List<ZookeeperNodeInfo> payload) {\n        if (payload == null || payload.isEmpty()) {\n            return false;\n        }\n        lock.lock();\n        try {\n            createPathIfNotExisted();\n            if (member != null) {\n                LOG.warn(\"GroupMember has already registered. Please deregister first.\");\n                return false;\n            }\n            String payloadString = getPropertiesString(payload);\n            member = new GroupMember(client, path, nodeId, payloadString.getBytes());\n            member.start();\n            LOG.info(\"Register Node[\" + nodeId + \"] in path[\" + path + \"].\");\n            return true;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    /**\n     * Close the current GroupMember.\n     */\n    public void deregister() {\n        if (member != null) {\n            member.close();\n            member = null;\n        }\n        if (client != null && privateZkClient) {\n            client.close();\n        }\n    }\n\n    /**\n     * @see #deregister()\n     */\n    public void destroy() {\n        deregister();\n    }\n\n    private void createPathIfNotExisted() {\n        try {\n            if (client.checkExists().forPath(path) == null) {\n                LOG.info(\"Path[\" + path + \"] is NOT existed, create it.\");\n                client.create().creatingParentsIfNeeded().forPath(path);\n            }\n        } catch (Exception e) {\n            LOG.error(\"Can NOT check the path.\", e);\n        }\n    }\n\n    private String getPropertiesString(List<ZookeeperNodeInfo> payload) {\n        Properties properties = new Properties();\n        for (ZookeeperNodeInfo n : payload) {\n            if (n.getHost() != null) {\n                properties.setProperty(n.getPrefix() + \"host\", n.getHost());\n            }\n            if (n.getPort() != null) {\n                properties.setProperty(n.getPrefix() + \"port\", n.getPort().toString());\n            }\n            if (n.getDatabase() != null) {\n                properties.setProperty(n.getPrefix() + \"database\", n.getDatabase());\n            }\n            if (n.getUsername() != null) {\n                properties.setProperty(n.getPrefix() + \"username\", n.getUsername());\n            }\n            if (n.getPassword() != null) {\n                properties.setProperty(n.getPrefix() + \"password\", n.getPassword());\n            }\n        }\n        StringWriter sw = new StringWriter();\n        try {\n            properties.store(sw, \"\");\n        } catch (IOException e) {\n            LOG.error(\"Why Properties.store goes wrong?\", e);\n        }\n        return sw.toString();\n    }\n\n    public void setClient(CuratorFramework client) {\n        if (client != null) {\n            this.client = client;\n            privateZkClient = false;\n        }\n    }\n\n    public CuratorFramework getClient() {\n        return client;\n    }\n\n    public String getZkConnectString() {\n        return zkConnectString;\n    }\n\n    public void setZkConnectString(String zkConnectString) {\n        this.zkConnectString = zkConnectString;\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/DataSourceSelector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport javax.sql.DataSource;\n\n/**\n * Interface for those selector to implement.\n * e.g. Random and Named\n *\n * @author DigitalSonic\n */\npublic interface DataSourceSelector {\n    /**\n     * Return a DataSource according to the implemention.\n     */\n    DataSource get();\n\n    /**\n     * Set the target DataSource name to return.\n     * Wether to use this or not, it's decided by the implemention.\n     */\n    void setTarget(String name);\n\n    /**\n     * Return the name of this DataSourceSelector.\n     * e.g. byName\n     */\n    String getName();\n\n    /**\n     * Init the DataSourceSelector before use it.\n     */\n    void init();\n\n    /**\n     * Destroy the DataSourceSelector, maybe interrupt the Thread.\n     */\n    void destroy();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/DataSourceSelectorEnum.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.pool.ha.HighAvailableDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\n/**\n * An enum holding the names and classes of DataSourceSelector.\n *\n * @author DigitalSonic\n */\npublic enum DataSourceSelectorEnum {\n    BY_NAME(\"byName\", NamedDataSourceSelector.class),\n    RANDOM(\"random\", RandomDataSourceSelector.class),\n    STICKY_RANDOM(\"stickyRandom\", StickyRandomDataSourceSelector.class);\n\n    private static final Log LOG = LogFactory.getLog(DataSourceSelectorEnum.class);\n    private String name;\n    private Class<? extends DataSourceSelector> clazz;\n\n    DataSourceSelectorEnum(String name, Class<? extends DataSourceSelector> clazz) {\n        this.name = name;\n        this.clazz = clazz;\n    }\n\n    /**\n     * Create a new instance of the DataSourceSelector represented by this enum.\n     *\n     * @return null if dataSource is not given or exception occurred while creating new instance\n     */\n    public DataSourceSelector newInstance(HighAvailableDataSource dataSource) {\n        if (dataSource == null) {\n            LOG.warn(\"You should provide an instance of HighAvailableDataSource!\");\n            return null;\n        }\n\n        DataSourceSelector selector = null;\n        try {\n            selector = clazz.getDeclaredConstructor(HighAvailableDataSource.class).newInstance(dataSource);\n        } catch (Exception e) {\n            LOG.error(\"Can not create new instance of \" + clazz.getName(), e);\n        }\n        return selector;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public Class<? extends DataSourceSelector> getClazz() {\n        return clazz;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/DataSourceSelectorFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.pool.ha.HighAvailableDataSource;\n\n/**\n * A Factory pattern for DataSourceSelector.\n *\n * @author DigitalSonic\n */\npublic class DataSourceSelectorFactory {\n    /**\n     * Get a new instance of the given selector name.\n     *\n     * @return null if the given name do not represent a DataSourceSelector\n     */\n    public static DataSourceSelector getSelector(String name, HighAvailableDataSource highAvailableDataSource) {\n        for (DataSourceSelectorEnum e : DataSourceSelectorEnum.values()) {\n            if (e.getName().equalsIgnoreCase(name)) {\n                return e.newInstance(highAvailableDataSource);\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/NamedDataSourceSelector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.pool.ha.HighAvailableDataSource;\n\nimport javax.sql.DataSource;\n\nimport java.util.Map;\n\n/**\n * Use the given name in ThreadLocal variable to choose DataSource.\n *\n * @author DigitalSonic\n */\npublic class NamedDataSourceSelector implements DataSourceSelector {\n    public static final String DEFAULT_NAME = \"default\";\n    private HighAvailableDataSource highAvailableDataSource;\n    private ThreadLocal<String> targetDataSourceName = new ThreadLocal<String>();\n    private String defaultName = DEFAULT_NAME;\n\n    public NamedDataSourceSelector(HighAvailableDataSource highAvailableDataSource) {\n        this.highAvailableDataSource = highAvailableDataSource;\n    }\n\n    @Override\n    public void init() {\n    }\n\n    @Override\n    public void destroy() {\n    }\n\n    @Override\n    public String getName() {\n        return DataSourceSelectorEnum.BY_NAME.getName();\n    }\n\n    @Override\n    public DataSource get() {\n        if (highAvailableDataSource == null) {\n            return null;\n        }\n\n        Map<String, DataSource> dataSourceMap = highAvailableDataSource.getAvailableDataSourceMap();\n        if (dataSourceMap == null || dataSourceMap.isEmpty()) {\n            return null;\n        }\n        if (dataSourceMap.size() == 1) {\n            for (DataSource v : dataSourceMap.values()) {\n                return v;\n            }\n        }\n        String name = getTarget();\n        if (name == null) {\n            if (dataSourceMap.get(getDefaultName()) != null) {\n                return dataSourceMap.get(getDefaultName());\n            }\n        } else {\n            return dataSourceMap.get(name);\n        }\n        return null;\n    }\n\n    @Override\n    public void setTarget(String name) {\n        targetDataSourceName.set(name);\n    }\n\n    public String getTarget() {\n        return targetDataSourceName.get();\n    }\n\n    public void resetDataSourceName() {\n        targetDataSourceName.remove();\n    }\n\n    public String getDefaultName() {\n        return defaultName;\n    }\n\n    public void setDefaultName(String defaultName) {\n        this.defaultName = defaultName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/RandomDataSourceRecoverThread.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\n\n/**\n * A Thread trying to test if DataSource in blacklist has been recovered.\n *\n * @author DigitalSonic\n */\npublic class RandomDataSourceRecoverThread implements Runnable {\n    public static final int DEFAULT_RECOVER_INTERVAL_SECONDS = 120;\n    private static final Log LOG = LogFactory.getLog(RandomDataSourceRecoverThread.class);\n\n    private RandomDataSourceSelector selector;\n    private int recoverIntervalSeconds = DEFAULT_RECOVER_INTERVAL_SECONDS;\n    private int validationSleepSeconds;\n\n    public RandomDataSourceRecoverThread(RandomDataSourceSelector selector) {\n        this.selector = selector;\n    }\n\n    @Override\n    public void run() {\n        while (true) {\n            if (selector != null && selector.getBlacklist() != null\n                    && !selector.getBlacklist().isEmpty()) {\n                LOG.info(selector.getBlacklist().size() + \" DataSource in blacklist.\");\n                for (DataSource dataSource : selector.getBlacklist()) {\n                    if (!(dataSource instanceof DruidDataSource)) {\n                        continue;\n                    }\n                    tryOneDataSource((DruidDataSource) dataSource);\n                }\n            } else if (selector == null) {\n                break;\n            }\n            sleep();\n        }\n    }\n\n    private void tryOneDataSource(DruidDataSource dataSource) {\n        if (dataSource == null) {\n            return;\n        }\n        Connection connection = null;\n        try {\n            connection = dataSource.getConnection();\n            sleepBeforeValidation();\n            dataSource.validateConnection(connection);\n            LOG.info(dataSource.getName() + \" is available now.\");\n            selector.removeBlacklist(dataSource);\n        } catch (Exception e) {\n            LOG.warn(\"DataSource[\" + dataSource.getName() + \"] is still unavailable. Exception: \"\n                    + e.getMessage());\n        } finally {\n            JdbcUtils.close(connection);\n        }\n    }\n\n    private void sleepBeforeValidation() {\n        if (validationSleepSeconds > 0) {\n            try {\n                if (LOG.isDebugEnabled()) {\n                    LOG.debug(\"Sleep \" + validationSleepSeconds + \" second(s) before validation.\");\n                }\n                Thread.sleep(validationSleepSeconds * 1000L);\n            } catch (InterruptedException e) {\n                // ignore\n            }\n        }\n    }\n\n    private void sleep() {\n        try {\n            Thread.sleep(recoverIntervalSeconds * 1000L);\n        } catch (InterruptedException e) {\n            // ignore\n        }\n    }\n\n    public int getRecoverIntervalSeconds() {\n        return recoverIntervalSeconds;\n    }\n\n    public void setRecoverIntervalSeconds(int recoverIntervalSeconds) {\n        this.recoverIntervalSeconds = recoverIntervalSeconds;\n    }\n\n    public int getValidationSleepSeconds() {\n        return validationSleepSeconds;\n    }\n\n    public void setValidationSleepSeconds(int validationSleepSeconds) {\n        this.validationSleepSeconds = validationSleepSeconds;\n    }\n\n    public RandomDataSourceSelector getSelector() {\n        return selector;\n    }\n\n    public void setSelector(RandomDataSourceSelector selector) {\n        this.selector = selector;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/RandomDataSourceSelector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ha.HighAvailableDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.sql.DataSource;\n\nimport java.util.*;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\n/**\n * A selector which uses java.util.Random to choose DataSource.\n *\n * @author DigitalSonic\n */\npublic class RandomDataSourceSelector implements DataSourceSelector {\n    private static final String PROP_PREFIX = \"druid.ha.random.\";\n    public static final String PROP_CHECKING_INTERVAL = PROP_PREFIX + \"checkingIntervalSeconds\";\n    public static final String PROP_RECOVERY_INTERVAL = PROP_PREFIX + \"recoveryIntervalSeconds\";\n    public static final String PROP_VALIDATION_SLEEP = PROP_PREFIX + \"validationSleepSeconds\";\n    public static final String PROP_BLACKLIST_THRESHOLD = PROP_PREFIX + \"blacklistThreshold\";\n\n    private static final Log LOG = LogFactory.getLog(RandomDataSourceSelector.class);\n\n    private Random random = new Random();\n    private List<DataSource> blacklist = new CopyOnWriteArrayList<DataSource>();\n    private HighAvailableDataSource highAvailableDataSource;\n    private RandomDataSourceValidateThread validateThread;\n    private RandomDataSourceRecoverThread recoverThread;\n    private Thread runningValidateThread;\n    private Thread runningRecoverThread;\n\n    private int checkingIntervalSeconds = RandomDataSourceValidateThread.DEFAULT_CHECKING_INTERVAL_SECONDS;\n    private int recoveryIntervalSeconds = RandomDataSourceRecoverThread.DEFAULT_RECOVER_INTERVAL_SECONDS;\n    private int validationSleepSeconds;\n    private int blacklistThreshold = RandomDataSourceValidateThread.DEFAULT_BLACKLIST_THRESHOLD;\n\n    public RandomDataSourceSelector(HighAvailableDataSource highAvailableDataSource) {\n        this.highAvailableDataSource = highAvailableDataSource;\n    }\n\n    @Override\n    public void init() {\n        if (highAvailableDataSource == null) {\n            LOG.warn(\"highAvailableDataSource is NULL!\");\n            return;\n        }\n        if (!highAvailableDataSource.isTestOnBorrow() && !highAvailableDataSource.isTestOnReturn()) {\n            loadProperties();\n            initThreads();\n        } else {\n            LOG.info(\"testOnBorrow or testOnReturn has been set to true, ignore validateThread\");\n        }\n    }\n\n    /**\n     * Interrupt Threads if needed.\n     */\n    @Override\n    public void destroy() {\n        if (runningValidateThread != null) {\n            runningValidateThread.interrupt();\n            validateThread.setSelector(null);\n        }\n        if (runningRecoverThread != null) {\n            runningRecoverThread.interrupt();\n            recoverThread.setSelector(null);\n        }\n    }\n\n    @Override\n    public String getName() {\n        return DataSourceSelectorEnum.RANDOM.getName();\n    }\n\n    @Override\n    public DataSource get() {\n        Map<String, DataSource> dataSourceMap = getDataSourceMap();\n        if (dataSourceMap == null || dataSourceMap.isEmpty()) {\n            return null;\n        }\n\n        Collection<DataSource> targetDataSourceSet = removeBlackList(dataSourceMap);\n        removeBusyDataSource(targetDataSourceSet);\n        DataSource dataSource = getRandomDataSource(targetDataSourceSet);\n        return dataSource;\n    }\n\n    @Override\n    public void setTarget(String name) {\n        // do nothing\n    }\n\n    public Map<String, DataSource> getFullDataSourceMap() {\n        if (highAvailableDataSource != null) {\n            return highAvailableDataSource.getDataSourceMap();\n        }\n        return new HashMap<String, DataSource>();\n    }\n\n    public Map<String, DataSource> getDataSourceMap() {\n        if (highAvailableDataSource != null) {\n            return highAvailableDataSource.getAvailableDataSourceMap();\n        }\n        return new HashMap<String, DataSource>();\n    }\n\n    public List<DataSource> getBlacklist() {\n        return blacklist;\n    }\n\n    public boolean containInBlacklist(DataSource dataSource) {\n        return dataSource != null && blacklist.contains(dataSource);\n    }\n\n    public void addBlacklist(DataSource dataSource) {\n        if (dataSource != null && !blacklist.contains(dataSource)) {\n            blacklist.add(dataSource);\n            if (dataSource instanceof DruidDataSource) {\n                ((DruidDataSource) dataSource).setTestOnReturn(true);\n            }\n        }\n    }\n\n    public void removeBlacklist(DataSource dataSource) {\n        if (containInBlacklist(dataSource)) {\n            blacklist.remove(dataSource);\n            if (dataSource instanceof DruidDataSource) {\n                ((DruidDataSource) dataSource).setTestOnReturn(highAvailableDataSource.isTestOnReturn());\n            }\n        }\n    }\n\n    private void loadProperties() {\n        checkingIntervalSeconds = loadInteger(PROP_CHECKING_INTERVAL, checkingIntervalSeconds);\n        recoveryIntervalSeconds = loadInteger(PROP_RECOVERY_INTERVAL, recoveryIntervalSeconds);\n        validationSleepSeconds = loadInteger(PROP_VALIDATION_SLEEP, validationSleepSeconds);\n        blacklistThreshold = loadInteger(PROP_BLACKLIST_THRESHOLD, blacklistThreshold);\n    }\n\n    private int loadInteger(String name, int defaultValue) {\n        if (name == null) {\n            return defaultValue;\n        }\n\n        Properties properties = highAvailableDataSource.getConnectProperties();\n        int value = defaultValue;\n        try {\n            if (properties.containsKey(name)) {\n                value = Integer.parseInt(properties.getProperty(name));\n            }\n        } catch (Exception e) {\n            LOG.error(\"Exception occurred while parsing \" + name, e);\n        }\n        return value;\n    }\n\n    private void initThreads() {\n        if (validateThread == null) {\n            validateThread = new RandomDataSourceValidateThread(this);\n            validateThread.setCheckingIntervalSeconds(checkingIntervalSeconds);\n            validateThread.setValidationSleepSeconds(validationSleepSeconds);\n            validateThread.setBlacklistThreshold(blacklistThreshold);\n        } else {\n            validateThread.setSelector(this);\n        }\n        if (runningValidateThread != null) {\n            runningValidateThread.interrupt();\n        }\n        runningValidateThread = new Thread(validateThread, \"RandomDataSourceSelector-validate-thread\");\n        runningValidateThread.start();\n\n        if (recoverThread == null) {\n            recoverThread = new RandomDataSourceRecoverThread(this);\n            recoverThread.setRecoverIntervalSeconds(recoveryIntervalSeconds);\n            recoverThread.setValidationSleepSeconds(validationSleepSeconds);\n        } else {\n            recoverThread.setSelector(this);\n        }\n        if (runningRecoverThread != null) {\n            runningRecoverThread.interrupt();\n        }\n        runningRecoverThread = new Thread(recoverThread, \"RandomDataSourceSelector-recover-thread\");\n        runningRecoverThread.start();\n    }\n\n    private Collection<DataSource> removeBlackList(Map<String, DataSource> dataSourceMap) {\n        Collection<DataSource> dataSourceSet;\n        if (blacklist == null || blacklist.isEmpty() || blacklist.size() >= dataSourceMap.size()) {\n            dataSourceSet = dataSourceMap.values();\n        } else {\n            dataSourceSet = new HashSet<DataSource>(dataSourceMap.values());\n            for (DataSource b : blacklist) {\n                dataSourceSet.remove(b);\n            }\n            LOG.info(blacklist.size() + \" Blacklist DataSource removed, return \"\n                    + dataSourceSet.size() + \" DataSource(s).\");\n        }\n        return dataSourceSet;\n    }\n\n    private void removeBusyDataSource(Collection<DataSource> dataSourceSet) {\n        Collection<DataSource> busyDataSourceSet = new HashSet<DataSource>();\n        for (DataSource ds : dataSourceSet) {\n            if (ds instanceof DruidDataSource && ((DruidDataSource) ds).getPoolingCount() <= 0) {\n                busyDataSourceSet.add(ds);\n            }\n        }\n        if (!busyDataSourceSet.isEmpty() && busyDataSourceSet.size() < dataSourceSet.size()) {\n            LOG.info(\"Busy DataSouces: \" + busyDataSourceSet.size() + \"/\" + dataSourceSet.size());\n            for (DataSource ds : busyDataSourceSet) {\n                dataSourceSet.remove(ds);\n            }\n        }\n    }\n\n    private DataSource getRandomDataSource(Collection<DataSource> dataSourceSet) {\n        DataSource[] dataSources = dataSourceSet.toArray(new DataSource[]{});\n        if (dataSources != null && dataSources.length > 0) {\n            return dataSources[random.nextInt(dataSourceSet.size())];\n        }\n        return null;\n    }\n\n    public HighAvailableDataSource getHighAvailableDataSource() {\n        return highAvailableDataSource;\n    }\n\n    public RandomDataSourceValidateThread getValidateThread() {\n        return validateThread;\n    }\n\n    public void setValidateThread(RandomDataSourceValidateThread validateThread) {\n        this.validateThread = validateThread;\n    }\n\n    public RandomDataSourceRecoverThread getRecoverThread() {\n        return recoverThread;\n    }\n\n    public void setRecoverThread(RandomDataSourceRecoverThread recoverThread) {\n        this.recoverThread = recoverThread;\n    }\n\n    public int getCheckingIntervalSeconds() {\n        return checkingIntervalSeconds;\n    }\n\n    public void setCheckingIntervalSeconds(int checkingIntervalSeconds) {\n        this.checkingIntervalSeconds = checkingIntervalSeconds;\n    }\n\n    public int getRecoveryIntervalSeconds() {\n        return recoveryIntervalSeconds;\n    }\n\n    public void setRecoveryIntervalSeconds(int recoveryIntervalSeconds) {\n        this.recoveryIntervalSeconds = recoveryIntervalSeconds;\n    }\n\n    public int getValidationSleepSeconds() {\n        return validationSleepSeconds;\n    }\n\n    public void setValidationSleepSeconds(int validationSleepSeconds) {\n        this.validationSleepSeconds = validationSleepSeconds;\n    }\n\n    public int getBlacklistThreshold() {\n        return blacklistThreshold;\n    }\n\n    public void setBlacklistThreshold(int blacklistThreshold) {\n        this.blacklistThreshold = blacklistThreshold;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/RandomDataSourceValidateFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.filter.FilterEventAdapter;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\n\n/**\n * A Druid Filter that records the last success execute time.\n *\n * @author DigitalSonic\n */\npublic class RandomDataSourceValidateFilter extends FilterEventAdapter {\n    protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) {\n        recordTime(statement);\n    }\n\n    protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) {\n        recordTime(statement);\n    }\n\n    protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) {\n        recordTime(statement);\n    }\n\n    protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) {\n        recordTime(statement);\n    }\n\n    private void recordTime(StatementProxy statement) {\n        ConnectionProxy conn = statement.getConnectionProxy();\n        if (conn != null) {\n            DataSourceProxy dataSource = conn.getDirectDataSource();\n            RandomDataSourceValidateThread.logSuccessTime(dataSource);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/RandomDataSourceValidateThread.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.StringUtils;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.Driver;\nimport java.util.*;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * A Thread trying to test all DataSource provided by HADataSource.\n * If a DataSource failed this test for 3 times (default value), it will be put into a blacklist.\n *\n * @author DigitalSonic\n */\npublic class RandomDataSourceValidateThread implements Runnable {\n    public static final int DEFAULT_CHECKING_INTERVAL_SECONDS = 10;\n    public static final int DEFAULT_BLACKLIST_THRESHOLD = 3;\n\n    private static final Log LOG = LogFactory.getLog(RandomDataSourceValidateThread.class);\n    private static Map<String, Long> successTimes = new ConcurrentHashMap<String, Long>();\n\n    private int checkingIntervalSeconds = DEFAULT_CHECKING_INTERVAL_SECONDS; // This value should NOT be too small.\n    private int validationSleepSeconds;\n    private int blacklistThreshold = DEFAULT_BLACKLIST_THRESHOLD;\n    private RandomDataSourceSelector selector;\n    private ExecutorService checkExecutor = Executors.newFixedThreadPool(5);\n    private Map<String, Integer> errorCounts = new ConcurrentHashMap<String, Integer>();\n    private Map<String, Long> lastCheckTimes = new ConcurrentHashMap<String, Long>();\n\n    /**\n     * Provide a static method to record the last success time of a DataSource\n     */\n    public static void logSuccessTime(DataSourceProxy dataSource) {\n        if (dataSource != null && !StringUtils.isEmpty(dataSource.getName())) {\n            String name = dataSource.getName();\n            long time = System.currentTimeMillis();\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"Log successTime [\" + time + \"] for \" + name);\n            }\n            successTimes.put(name, time);\n        }\n    }\n\n    public RandomDataSourceValidateThread(RandomDataSourceSelector selector) {\n        if (LOG.isDebugEnabled()) {\n            LOG.debug(\"Create a RandomDataSourceValidateThread, hashCode=\" + this.hashCode());\n        }\n        this.selector = selector;\n    }\n\n    @Override\n    public void run() {\n        while (true) {\n            if (selector != null) {\n                checkAllDataSources();\n                maintainBlacklist();\n                cleanup();\n            } else {\n                break;\n            }\n            sleepForNextValidation();\n        }\n    }\n\n    private void sleepForNextValidation() {\n        int errorCountBelowThreshold = 0;\n\n        for (int count : errorCounts.values()) {\n            if (count > 0 && count < blacklistThreshold && count > errorCountBelowThreshold) {\n                errorCountBelowThreshold = count;\n            }\n        }\n\n        int newSleepSeconds = checkingIntervalSeconds / (errorCountBelowThreshold + 1);\n        if (newSleepSeconds < 1) {\n            newSleepSeconds = 1;\n        }\n        try {\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"[RandomDataSourceValidateThread@\" + hashCode() + \"] Sleep \" + newSleepSeconds\n                        + \" second(s) until next checking.\");\n            }\n            Thread.sleep(newSleepSeconds * 1000L);\n        } catch (InterruptedException e) {\n            // ignore\n        }\n    }\n\n    private void cleanup() {\n        Map<String, DataSource> dataSourceMap = selector.getFullDataSourceMap();\n        Set<String> dataSources = new HashSet<String>();\n        for (DataSource ds : dataSourceMap.values()) {\n            if (ds instanceof DruidDataSource) {\n                dataSources.add(((DruidDataSource) ds).getName());\n            }\n        }\n        cleanupMap(successTimes, dataSources);\n        cleanupMap(errorCounts, dataSources);\n        cleanupMap(lastCheckTimes, dataSources);\n    }\n\n    private void cleanupMap(Map<String, ?> mapToClean, Set<String> keys) {\n        Set<String> keysToRemove = new HashSet<String>();\n        for (String k : mapToClean.keySet()) {\n            if (!keys.contains(k)) {\n                keysToRemove.add(k);\n            }\n        }\n        for (String k : keysToRemove) {\n            mapToClean.remove(k);\n        }\n    }\n\n    private void maintainBlacklist() {\n        Map<String, DataSource> dataSourceMap = selector.getFullDataSourceMap();\n        for (String name : errorCounts.keySet()) {\n            Integer count = errorCounts.get(name);\n            DataSource dataSource = dataSourceMap.get(name);\n            if (dataSource == null) {\n                for (DataSource ds : dataSourceMap.values()) {\n                    if (ds instanceof DruidDataSource\n                            && name.equals(((DruidDataSource) ds).getName())) {\n                        dataSource = ds;\n                    }\n                }\n            }\n            if (count == null || count <= 0) {\n                selector.removeBlacklist(dataSource);\n            } else if (count != null && count >= blacklistThreshold\n                    && !selector.containInBlacklist(dataSource)) {\n                LOG.warn(\"Adding \" + name + \" to blacklist.\");\n                selector.addBlacklist(dataSource);\n            }\n        }\n    }\n\n    private void checkAllDataSources() {\n        Map<String, DataSource> dataSourceMap = selector.getFullDataSourceMap();\n        List<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();\n        LOG.debug(\"Checking all DataSource(s).\");\n        for (final Map.Entry<String, DataSource> e : dataSourceMap.entrySet()) {\n            if (!(e.getValue() instanceof DruidDataSource)) {\n                continue;\n            }\n\n            if (selector.containInBlacklist(e.getValue())) {\n                if (LOG.isDebugEnabled()) {\n                    LOG.debug(e.getKey() + \" is already in blacklist, skip.\");\n                }\n                continue;\n            }\n\n            tasks.add(new Callable<Boolean>() {\n                @Override\n                public Boolean call() {\n                    DruidDataSource dataSource = (DruidDataSource) e.getValue();\n                    String name = dataSource.getName();\n\n                    if (isSkipChecking(dataSource)) {\n                        if (LOG.isDebugEnabled()) {\n                            LOG.debug(\"Skip checking DataSource[\" + name + \"] this time.\");\n                        }\n                        return true;\n                    }\n\n                    if (LOG.isDebugEnabled()) {\n                        LOG.debug(\"Start checking \" + name + \".\");\n                    }\n                    boolean flag = check(dataSource);\n\n                    if (flag) {\n                        logSuccessTime(dataSource);\n                        errorCounts.put(name, 0);\n                    } else {\n                        if (!errorCounts.containsKey(name)) {\n                            errorCounts.put(name, 0);\n                        }\n                        int count = errorCounts.get(name);\n                        errorCounts.put(name, count + 1);\n                    }\n                    lastCheckTimes.put(name, System.currentTimeMillis());\n\n                    return flag;\n                }\n            });\n        }\n        try {\n            checkExecutor.invokeAll(tasks);\n        } catch (Exception e) {\n            LOG.warn(\"Exception occurred while checking DataSource.\", e);\n        }\n    }\n\n    private boolean isSkipChecking(DruidDataSource dataSource) {\n        String name = dataSource.getName();\n        Long lastSuccessTime = successTimes.get(dataSource.getName());\n        Long lastCheckTime = lastCheckTimes.get(dataSource.getName());\n        long currentTime = System.currentTimeMillis();\n        if (LOG.isDebugEnabled()) {\n            LOG.debug(\"DataSource=\" + name + \", lastSuccessTime=\" + lastSuccessTime\n                    + \", lastCheckTime=\" + lastCheckTime + \", currentTime=\" + currentTime);\n        }\n        return lastSuccessTime != null && lastCheckTime != null\n                && (currentTime - lastSuccessTime) <= checkingIntervalSeconds * 1000L\n                && (currentTime - lastCheckTime) <= checkingIntervalSeconds * 1000L * 5\n                && (!errorCounts.containsKey(name) || errorCounts.get(name) < 1);\n    }\n\n    private boolean check(DruidDataSource dataSource) {\n        boolean result = true;\n        String name = dataSource.getName();\n        Driver driver = dataSource.getRawDriver();\n        Properties info = new Properties(dataSource.getConnectProperties());\n        String username = dataSource.getUsername();\n        String password = dataSource.getPassword();\n        String url = dataSource.getUrl(); // We can't use rawUrl here, because the schema maybe set in url.\n        Connection conn = null;\n\n        if (info.getProperty(\"user\") == null && username != null) {\n            info.setProperty(\"user\", username);\n        }\n        if (info.getProperty(\"password\") == null && password != null) {\n            info.setProperty(\"password\", password);\n        }\n        try {\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"[RandomDataSourceValidateThread@\" + this.hashCode() + \"] Validating \" + name + \" every \" + checkingIntervalSeconds + \" seconds.\");\n            }\n            conn = driver.connect(url, info);\n            sleepBeforeValidation();\n            dataSource.validateConnection(conn);\n        } catch (Exception e) {\n            LOG.warn(\"Validation FAILED for \" + name + \" with url [\" + url + \"] and username [\"\n                    + info.getProperty(\"user\") + \"]. Exception: \" + e.getMessage());\n            result = false;\n        } finally {\n            JdbcUtils.close(conn);\n        }\n\n        return result;\n    }\n\n    private void sleepBeforeValidation() {\n        if (validationSleepSeconds <= 0) {\n            return;\n        }\n        try {\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"Sleep \" + validationSleepSeconds + \" second(s) before validation.\");\n            }\n            Thread.sleep(validationSleepSeconds * 1000L);\n        } catch (InterruptedException e) {\n            // ignore\n        }\n    }\n\n    public int getCheckingIntervalSeconds() {\n        return checkingIntervalSeconds;\n    }\n\n    public void setCheckingIntervalSeconds(int checkingIntervalSeconds) {\n        this.checkingIntervalSeconds = checkingIntervalSeconds;\n    }\n\n    public int getValidationSleepSeconds() {\n        return validationSleepSeconds;\n    }\n\n    public void setValidationSleepSeconds(int validationSleepSeconds) {\n        this.validationSleepSeconds = validationSleepSeconds;\n    }\n\n    public int getBlacklistThreshold() {\n        return blacklistThreshold;\n    }\n\n    public void setBlacklistThreshold(int blacklistThreshold) {\n        this.blacklistThreshold = blacklistThreshold;\n    }\n\n    public RandomDataSourceSelector getSelector() {\n        return selector;\n    }\n\n    public void setSelector(RandomDataSourceSelector selector) {\n        this.selector = selector;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/StickyDataSourceHolder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport javax.sql.DataSource;\n\n/**\n * A class holding DataSource reference and retrieving time.\n *\n * @author DigitalSonic\n */\npublic class StickyDataSourceHolder {\n    private long retrievingTime = System.currentTimeMillis();\n    private DataSource dataSource;\n\n    public StickyDataSourceHolder() {\n    }\n\n    public StickyDataSourceHolder(DataSource dataSource) {\n        this.dataSource = dataSource;\n    }\n\n    public boolean isValid() {\n        return retrievingTime > 0 && dataSource != null;\n    }\n\n    public long getRetrievingTime() {\n        return retrievingTime;\n    }\n\n    public void setRetrievingTime(long retrievingTime) {\n        this.retrievingTime = retrievingTime;\n    }\n\n    public DataSource getDataSource() {\n        return dataSource;\n    }\n\n    public void setDataSource(DataSource dataSource) {\n        this.dataSource = dataSource;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/ha/selector/StickyRandomDataSourceSelector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.ha.selector;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ha.HighAvailableDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.sql.DataSource;\n\n/**\n * An extend selector based on RandomDataSourceSelector which can stick a DataSource to a Thread in a while.\n *\n * @author DigitalSonic\n * @see RandomDataSourceSelector\n * @see StickyDataSourceHolder\n */\npublic class StickyRandomDataSourceSelector extends RandomDataSourceSelector {\n    private static final Log LOG = LogFactory.getLog(StickyRandomDataSourceSelector.class);\n\n    private ThreadLocal<StickyDataSourceHolder> holders = new ThreadLocal<StickyDataSourceHolder>();\n\n    private int expireSeconds = 5;\n\n    public StickyRandomDataSourceSelector(HighAvailableDataSource highAvailableDataSource) {\n        super(highAvailableDataSource);\n    }\n\n    @Override\n    public String getName() {\n        return DataSourceSelectorEnum.STICKY_RANDOM.getName();\n    }\n\n    @Override\n    public DataSource get() {\n        StickyDataSourceHolder holder = holders.get();\n        if (holder != null && isAvailable(holder)) {\n            if (LOG.isDebugEnabled()) {\n                LOG.debug(\"Return the sticky DataSource \" + holder.getDataSource().toString() + \" directly.\");\n            }\n            return holder.getDataSource();\n        }\n        LOG.debug(\"Return a random DataSource.\");\n        DataSource dataSource = super.get();\n        holder = new StickyDataSourceHolder(dataSource);\n        holders.remove();\n        holders.set(holder);\n        return dataSource;\n    }\n\n    private boolean isAvailable(StickyDataSourceHolder holder) {\n        boolean flag = isValid(holder) && !isExpired(holder);\n        if (flag && holder.getDataSource() instanceof DruidDataSource) {\n            flag = ((DruidDataSource) holder.getDataSource()).getPoolingCount() > 0;\n        }\n        return flag;\n    }\n\n    private boolean isValid(StickyDataSourceHolder holder) {\n        boolean flag = holder.isValid() && !getBlacklist().contains(holder.getDataSource());\n        if (!(holder.getDataSource() instanceof DruidDataSource) || !flag) {\n            return flag;\n        }\n        DruidDataSource dataSource = (DruidDataSource) holder.getDataSource();\n        return flag && dataSource.getActiveCount() < dataSource.getMaxActive();\n    }\n\n    private boolean isExpired(StickyDataSourceHolder holder) {\n        return System.currentTimeMillis() - holder.getRetrievingTime() > expireSeconds * 1000L;\n    }\n\n    public int getExpireSeconds() {\n        return expireSeconds;\n    }\n\n    public void setExpireSeconds(int expireSeconds) {\n        this.expireSeconds = expireSeconds;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/AbstractOracleExceptionSorter.java",
    "content": "package com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.HashSet;\nimport java.util.Properties;\nimport java.util.Set;\n\n/**\n * oracle exception sorter abstract\n */\npublic abstract class AbstractOracleExceptionSorter implements ExceptionSorter {\n    private static final Log LOG = LogFactory.getLog(AbstractOracleExceptionSorter.class);\n    protected Set<Integer> fatalErrorCodes = new HashSet<Integer>();\n\n    @Override\n    public void configFromProperties(Properties properties) {\n        if (properties == null) {\n            return;\n        }\n        String property = properties.getProperty(\"druid.oracle.fatalErrorCodes\");\n        if (property != null) {\n            String[] items = property.split(\"\\\\,\");\n            for (String item : items) {\n                if (item != null && item.length() > 0) {\n                    try {\n                        int code = Integer.parseInt(item);\n                        fatalErrorCodes.add(code);\n                    } catch (NumberFormatException e) {\n                        LOG.error(\"parse druid.oracle.fatalErrorCodes error\", e);\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/DB2ExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\n\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.util.Properties;\n\npublic class DB2ExceptionSorter implements ExceptionSorter {\n    @Override\n    public boolean isExceptionFatal(SQLException e) {\n        if (e instanceof SQLRecoverableException) {\n            return true;\n        }\n\n        String sqlState = e.getSQLState();\n        if (sqlState != null && sqlState.startsWith(\"08\")) { // Connection Exception\n            return true;\n        }\n\n        int errorCode = e.getErrorCode();\n        switch (errorCode) {\n            case -512: // STATEMENT REFERENCE TO REMOTE OBJECT IS INVALID\n            case -514: // THE CURSOR IS NOT IN A PREPARED STATE\n            case -516: // THE DESCRIBE STATEMENT DOES NOT SPECIFY A PREPARED STATEMENT\n            case -518: // THE EXECUTE STATEMENT DOES NOT IDENTIFY A VALID PREPARED STATEMENT\n            case -525: // THE SQL STATEMENT CANNOT BE EXECUTED BECAUSE IT WAS IN ERROR AT BIND TIME FOR SECTION = sectno\n                // PACKAGE = pkgname CONSISTENCY TOKEN = contoken\n            case -909: // THE OBJECT HAS BEEN DELETED OR ALTERED\n            case -918: // THE SQL STATEMENT CANNOT BE EXECUTED BECAUSE A CONNECTION HAS BEEN LOST\n            case -924: // DB2 CONNECTION INTERNAL ERROR, function-code,return-code,reason-code\n                return true;\n            default:\n                break;\n        }\n        return false;\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/InformixExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\n\nimport java.io.Serializable;\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.util.Properties;\n\npublic class InformixExceptionSorter implements ExceptionSorter, Serializable {\n    private static final long serialVersionUID = -5175884111768095263L;\n\n    public boolean isExceptionFatal(SQLException e) {\n        if (e instanceof SQLRecoverableException) {\n            return true;\n        }\n\n        switch (e.getErrorCode()) {\n            case -710: // Table has been dropped, altered or renamed JBAS-3120\n            case -79716: // System or internal error\n            case -79730: // Connection noit established\n            case -79734: // INFORMIXSERVER has to be specified\n            case -79735: // Can't instantiate protocol\n            case -79736: // No connection/statement established yet\n            case -79756: // Invalid connection URL\n            case -79757: // Invalid subprotocol\n            case -79758: // Invalid IP address\n            case -79759: // Invalid port nnumber\n            case -79760: // Invalid database name\n            case -79788: // User name must be specified\n            case -79811: // Connection without user/password not supported\n            case -79812: // User/password does not match with datasource\n            case -79836: // Proxy error: no database connection\n            case -79837: // Proxy error: IO error\n            case -79879: // Unexpected exception\n\n                return true;\n        }\n\n        return false;\n    }\n\n    public void configFromProperties(Properties properties) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/MSSQLValidConnectionChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ValidConnectionChecker;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.io.Serializable;\nimport java.sql.Connection;\n\n/**\n * A MSSQLValidConnectionChecker.\n */\npublic class MSSQLValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker, Serializable {\n    private static final long serialVersionUID = 1L;\n    private static final String DEFAULT_VALIDATION_QUERY = \"SELECT 1\";\n\n    public MSSQLValidConnectionChecker() {\n    }\n\n    public boolean isValidConnection(final Connection conn,\n                                     String validateQuery,\n                                     int validationQueryTimeout) throws Exception {\n        if (conn.isClosed()) {\n            return false;\n        }\n\n        if (StringUtils.isEmpty(validateQuery)) {\n            validateQuery = DEFAULT_VALIDATION_QUERY;\n        }\n\n        return ValidConnectionCheckerAdapter.execValidQuery(conn, validateQuery, validationQueryTimeout);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/MockExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.mock.MockConnectionClosedException;\nimport com.alibaba.druid.pool.ExceptionSorter;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\npublic class MockExceptionSorter implements ExceptionSorter {\n    private static final MockExceptionSorter instance = new MockExceptionSorter();\n\n    public static final MockExceptionSorter getInstance() {\n        return instance;\n    }\n\n    @Override\n    public boolean isExceptionFatal(SQLException e) {\n        return e instanceof MockConnectionClosedException;\n    }\n\n    public void configFromProperties(Properties properties) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/MySqlExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\n\nimport java.net.SocketTimeoutException;\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.util.Properties;\n\npublic class MySqlExceptionSorter implements ExceptionSorter {\n    @Override\n    public boolean isExceptionFatal(SQLException e) {\n        if (e instanceof SQLRecoverableException) {\n            return true;\n        }\n\n        final String sqlState = e.getSQLState();\n        final int errorCode = e.getErrorCode();\n\n        if (sqlState != null && sqlState.startsWith(\"08\")) {\n            return true;\n        }\n\n        switch (errorCode) {\n            // Communications Errors\n            case 1040: // ER_CON_COUNT_ERROR\n            case 1042: // ER_BAD_HOST_ERROR\n            case 1043: // ER_HANDSHAKE_ERROR\n            case 1047: // ER_UNKNOWN_COM_ERROR\n            case 1081: // ER_IPSOCK_ERROR\n            case 1129: // ER_HOST_IS_BLOCKED\n            case 1130: // ER_HOST_NOT_PRIVILEGED\n                // Authentication Errors\n            case 1045: // ER_ACCESS_DENIED_ERROR\n                // Resource errors\n            case 1004: // ER_CANT_CREATE_FILE\n            case 1005: // ER_CANT_CREATE_TABLE\n            case 1015: // ER_CANT_LOCK\n            case 1021: // ER_DISK_FULL\n            case 1041: // ER_OUT_OF_RESOURCES\n                // Out-of-memory errors\n            case 1037: // ER_OUTOFMEMORY\n            case 1038: // ER_OUT_OF_SORTMEMORY\n                // Access denied\n            case 1142: // ER_TABLEACCESS_DENIED_ERROR\n            case 1227: // ER_SPECIFIC_ACCESS_DENIED_ERROR\n\n            case 1023: // ER_ERROR_ON_CLOSE\n\n            case 1290: // ER_OPTION_PREVENTS_STATEMENT\n                return true;\n            default:\n                break;\n        }\n\n        // for oceanbase\n        if (errorCode >= -9000 && errorCode <= -8000) {\n            return true;\n        }\n\n        String className = e.getClass().getName();\n        if (className.endsWith(\".CommunicationsException\")) {\n            return true;\n        }\n\n        String message = e.getMessage();\n        if (message != null && message.length() > 0) {\n            if (message.startsWith(\"Streaming result set com.mysql.jdbc.RowDataDynamic\")\n                    && message.endsWith(\"is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.\")) {\n                return true;\n            }\n\n            final String errorText = message.toUpperCase();\n\n            if ((errorCode == 0 && (errorText.contains(\"COMMUNICATIONS LINK FAILURE\")) //\n                    || errorText.contains(\"COULD NOT CREATE CONNECTION\")) //\n                    || errorText.contains(\"NO DATASOURCE\") //\n                    || errorText.contains(\"NO ALIVE DATASOURCE\")) {\n                return true;\n            }\n        }\n\n        Throwable cause = e.getCause();\n        for (int i = 0; i < 5 && cause != null; ++i) {\n            if (cause instanceof SocketTimeoutException) {\n                return true;\n            }\n\n            className = cause.getClass().getName();\n            if (className.endsWith(\".CommunicationsException\")) {\n                return true;\n            }\n\n            cause = cause.getCause();\n        }\n\n        return false;\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/MySqlValidConnectionChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ValidConnectionChecker;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.io.Serializable;\nimport java.sql.Connection;\nimport java.util.Properties;\n\npublic class MySqlValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker, Serializable {\n    public static final int DEFAULT_VALIDATION_QUERY_TIMEOUT = 1;\n    /**\n     * @see <a href=\"https://dev.mysql.com/doc/connectors/en/connector-j-usagenotes-j2ee-concepts-connection-pooling.html\">Connection Pooling with Connector/J</a>\n     * <p>\n     * specify a validation query in your connection pool that starts with {@literal /}* ping *{@literal /}.\n     * Note that the syntax must be exactly as specified. This will cause the driver send a ping to the server\n     * and return a dummy lightweight result set. When using a ReplicationConnection or LoadBalancedConnection,\n     * the ping will be sent across all active connections.\n     */\n    public static final String DEFAULT_VALIDATION_QUERY = \"/* ping */ SELECT 1\";\n\n    private static final long serialVersionUID = 1L;\n    private static final Log LOG = LogFactory.getLog(MySqlValidConnectionChecker.class);\n\n    /** using ping SQL by default */\n    private boolean usePingMethod = true;\n\n    public MySqlValidConnectionChecker() {\n        configFromProperties(System.getProperties());\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n        if (properties == null) {\n            return;\n        }\n\n        String property = properties.getProperty(\"druid.mysql.usePingMethod\");\n        if (\"true\".equals(property)) {\n            setUsePingMethod(true);\n        } else if (\"false\".equals(property)) {\n            setUsePingMethod(false);\n        }\n    }\n\n    public boolean isUsePingMethod() {\n        return usePingMethod;\n    }\n\n    public void setUsePingMethod(boolean usePingMethod) {\n        this.usePingMethod = usePingMethod;\n    }\n\n    public boolean isValidConnection(Connection conn,\n                                     String validateQuery,\n                                     int validationQueryTimeout) throws Exception {\n        if (conn.isClosed()) {\n            return false;\n        }\n\n        if (usePingMethod || StringUtils.isEmpty(validateQuery)) {\n            validateQuery = DEFAULT_VALIDATION_QUERY;\n        }\n\n        return ValidConnectionCheckerAdapter.execValidQuery(conn, validateQuery, validationQueryTimeout);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/NullExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\npublic class NullExceptionSorter implements ExceptionSorter {\n    private static final NullExceptionSorter instance = new NullExceptionSorter();\n\n    public static final NullExceptionSorter getInstance() {\n        return instance;\n    }\n\n    @Override\n    public boolean isExceptionFatal(SQLException e) {\n        return false;\n    }\n\n    public void configFromProperties(Properties properties) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/OceanBaseOracleExceptionSorter.java",
    "content": "package com.alibaba.druid.pool.vendor;\n\nimport java.io.Serializable;\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.util.Set;\n\npublic class OceanBaseOracleExceptionSorter extends AbstractOracleExceptionSorter implements Serializable {\n    private static final long serialVersionUID = -9146226891418913175L;\n\n    public OceanBaseOracleExceptionSorter() {\n        configFromProperties(System.getProperties());\n    }\n\n    public Set<Integer> getFatalErrorCodes() {\n        return fatalErrorCodes;\n    }\n\n    public void setFatalErrorCodes(Set<Integer> fatalErrorCodes) {\n        this.fatalErrorCodes = fatalErrorCodes;\n    }\n\n    @Override\n    public boolean isExceptionFatal(SQLException e) {\n        if (e instanceof SQLRecoverableException) {\n            return true;\n        }\n        final String sqlState = e.getSQLState();\n        final int error_code = Math.abs(e.getErrorCode()); // I can't remember if the errors are negative or positive.\n        if (sqlState != null && sqlState.startsWith(\"08\")) {\n            return true;\n        }\n        switch (error_code) {\n            case 28: // your session has been killed\n            case 600: // Internal oracle error\n            case 1012: // not logged on\n            case 1014: // Oracle shutdown in progress\n            case 1033: // Oracle initialization or shutdown in progress\n            case 1034: // Oracle not available\n            case 1035: // ORACLE only available to users with RESTRICTED SESSION privilege\n            case 1089: // immediate shutdown in progress - no operations are permitted\n            case 1090: // shutdown in progress - connection is not permitted\n            case 1092: // ORACLE instance terminated. Disconnection forced\n            case 1094: // ALTER DATABASE CLOSE in progress. Connections not permitted\n            case 2396: // exceeded maximum idle time, please connect again\n            case 3106: // fatal two-task communication protocol error\n            case 3111: // break received on communication channel\n            case 3113: // end-of-file on communication channel\n            case 3114: // not connected to ORACLE\n            case 3134: // Connections to this server version are no longer supported.\n            case 3135: // connection lost contact\n            case 3136: // inbound connection timed out\n            case 3138: // Connection terminated due to security policy violation\n            case 3142: // Connection was lost for the specified session and serial number. This is either due to session\n                // being killed or network problems.\n            case 3143: // Connection was lost for the specified process ID and thread ID. This is either due to session\n                // being killed or network problems.\n            case 3144: // Connection was lost for the specified process ID. This is either due to session being killed\n                // or network problems.\n            case 3145: // I/O streaming direction error\n            case 3149: // Invalid Oracle error code, Cause: An invalid Oracle error code was received by the server.\n            case 6801: // TLI Driver: listen for SPX server reconnect failed\n            case 6802: // TLI Driver: could not open the /etc/netware/yellowpages file\n            case 6805: // TLI Driver: could not send datagram SAP packet for SPX\n            case 9918: // Unable to get user privileges from SQL*Net\n            case 9920: // Unable to get sensitivity label from connection\n            case 9921: // Unable to get information label from connection\n                // TTC(Two-Task Common) ERROR CODE\n            case 17001: // Internal Error\n            case 17002: // Io exception\n            case 17008: // Closed Connection\n            case 17009: // Closed Statement\n            case 17024: // No data read\n            case 17089: // internal error\n            case 17409: // invalid buffer length\n            case 17401: // Protocol violation\n            case 17410: // No more data to read from socket\n            case 17416: // FATAl\n            case 17438: // Internal - Unexpected value\n            case 17442: // Refcursor value is invalid\n            case 25407: // connection terminated\n            case 25408: // can not safely replay call\n            case 25409: // failover happened during the network operation,cannot continue\n            case 25425: // connection lost during rollback\n            case 29276: // transfer timeout\n            case 30676: // socket read or write failed\n                return true;\n            default:\n                if (error_code >= 12100 && error_code <= 12299) { // TNS issues\n                    return true;\n                }\n                break;\n        }\n        final String error_text = (e.getMessage()).toUpperCase();\n        // Exclude oracle user defined error codes (20000 through 20999) from consideration when looking for\n        // certain strings.\n        if ((error_code < 20000 || error_code >= 21000)) {\n            if ((error_text.contains(\"SOCKET\")) // for control socket error\n                    || (error_text.contains(\"套接字\")) // for control socket error\n                    || (error_text.contains(\"CONNECTION HAS ALREADY BEEN CLOSED\")) //\n                    || (error_text.contains(\"BROKEN PIPE\")) //\n                    || (error_text.contains(\"管道已结束\")) //\n            ) {\n                return true;\n            }\n        }\n        if (error_text.indexOf(\"COMMUNICATIONS LINK FAILURE\") > -1\n                || error_text.indexOf(\"COULD NOT CREATE CONNECTION\") > -1\n                || error_text.indexOf(\"ACCESS DENIED FOR USER\") > -1\n                || error_text.indexOf(\"NO DATASOURCE\") > -1\n                || error_text.indexOf(\"NO ALIVE DATASOURCE\") > -1) {\n            // errorCode忽略并且异常信息为连接出错\n            return true;\n        }\n\n        return fatalErrorCodes.contains(error_code);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/OceanBaseValidConnectionChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.pool.ValidConnectionChecker;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.sql.Connection;\n\npublic class OceanBaseValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker {\n    private String commonValidateQuery = \"SELECT 'x' FROM DUAL\";\n    /**\n     * MySQL:\n     * specify a validation query in your connection pool that starts with {@literal /}* ping *{@literal /}.\n     * Note that the syntax must be exactly as specified. This will cause the driver send a ping to the server\n     * and return a dummy lightweight result set. When using a ReplicationConnection or LoadBalancedConnection,\n     * the ping will be sent across all active connections.\n     */\n    private String mysqlValidateQuery = \"/* ping */ SELECT 1\";\n    private DbType dbType;\n\n    public OceanBaseValidConnectionChecker() {\n        configFromProperties(System.getProperties());\n        dbType = null;\n    }\n\n    public OceanBaseValidConnectionChecker(DbType dbType) {\n        this.dbType = dbType;\n        configFromProperties(System.getProperties());\n    }\n\n    public boolean isValidConnection(final Connection conn,\n                                     String validateQuery,\n                                     int validationQueryTimeout) throws Exception {\n        if (conn.isClosed()) {\n            return false;\n        }\n\n        if (StringUtils.isEmpty(validateQuery)) {\n            if (DbType.mysql.equals(dbType)) {\n                validateQuery = mysqlValidateQuery;\n            } else {\n                validateQuery = commonValidateQuery;\n            }\n        }\n\n        return ValidConnectionCheckerAdapter.execValidQuery(conn, validateQuery, validationQueryTimeout);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/OracleExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport java.io.Serializable;\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.util.Set;\n\n/**\n * Implementation of ExceptionSorter for Oracle.\n */\npublic class OracleExceptionSorter extends AbstractOracleExceptionSorter implements Serializable {\n    private static final long serialVersionUID = -9146226891418913174L;\n\n    public OracleExceptionSorter() {\n        configFromProperties(System.getProperties());\n    }\n\n    public Set<Integer> getFatalErrorCodes() {\n        return fatalErrorCodes;\n    }\n\n    public void setFatalErrorCodes(Set<Integer> fatalErrorCodes) {\n        this.fatalErrorCodes = fatalErrorCodes;\n    }\n\n    public boolean isExceptionFatal(final SQLException e) {\n        if (e instanceof SQLRecoverableException) {\n            return true;\n        }\n\n        final int error_code = Math.abs(e.getErrorCode()); // I can't remember if the errors are negative or positive.\n\n        switch (error_code) {\n            case 28: // your session has been killed\n            case 600: // Internal oracle error\n            case 1012: // not logged on\n            case 1014: // Oracle shutdown in progress\n            case 1033: // Oracle initialization or shutdown in progress\n            case 1034: // Oracle not available\n            case 1035: // ORACLE only available to users with RESTRICTED SESSION privilege\n            case 1089: // immediate shutdown in progress - no operations are permitted\n            case 1090: // shutdown in progress - connection is not permitted\n            case 1092: // ORACLE instance terminated. Disconnection forced\n            case 1094: // ALTER DATABASE CLOSE in progress. Connections not permitted\n            case 2396: // exceeded maximum idle time, please connect again\n            case 3106: // fatal two-task communication protocol error\n            case 3111: // break received on communication channel\n            case 3113: // end-of-file on communication channel\n            case 3114: // not connected to ORACLE\n\n            case 3134: // Connections to this server version are no longer supported.\n            case 3135: // connection lost contact\n            case 3136: // inbound connection timed out\n            case 3138: // Connection terminated due to security policy violation\n            case 3142: // Connection was lost for the specified session and serial number. This is either due to session\n                // being killed or network problems.\n            case 3143: // Connection was lost for the specified process ID and thread ID. This is either due to session\n                // being killed or network problems.\n            case 3144: // Connection was lost for the specified process ID. This is either due to session being killed\n                // or network problems.\n            case 3145: // I/O streaming direction error\n            case 3149: // Invalid Oracle error code, Cause: An invalid Oracle error code was received by the server.\n\n            case 6801: // TLI Driver: listen for SPX server reconnect failed\n            case 6802: // TLI Driver: could not open the /etc/netware/yellowpages file\n            case 6805: // TLI Driver: could not send datagram SAP packet for SPX\n            case 9918: // Unable to get user privileges from SQL*Net\n            case 9920: // Unable to get sensitivity label from connection\n            case 9921: // Unable to get information label from connection\n\n                // TTC(Two-Task Common) ERROR CODE\n            case 17001: // Internal Error\n            case 17002: // Io exception\n            case 17008: // Closed Connection\n            case 17009: // Closed Statement\n            case 17024: // No data read\n            case 17089: // internal error\n            case 17409: // invalid buffer length\n            case 17401: // Protocol violation\n            case 17410: // No more data to read from socket\n            case 17416: // FATAl\n            case 17438: // Internal - Unexpected value\n            case 17442: // Refcursor value is invalid\n\n            case 25407: // connection terminated\n            case 25408: // can not safely replay call\n            case 25409: // failover happened during the network operation,cannot continue\n            case 25425: // connection lost during rollback\n            case 29276: // transfer timeout\n            case 30676: // socket read or write failed\n                return true;\n            default:\n                if (error_code >= 12100 && error_code <= 12299) { // TNS issues\n                    return true;\n                }\n                break;\n        }\n\n        final String error_text = (e.getMessage()).toUpperCase();\n\n        // Exclude oracle user defined error codes (20000 through 20999) from consideration when looking for\n        // certain strings.\n\n        if ((error_code < 20000 || error_code >= 21000)) {\n            if ((error_text.contains(\"SOCKET\")) // for control socket error\n                    || (error_text.contains(\"套接字\")) // for control socket error\n                    || (error_text.contains(\"CONNECTION HAS ALREADY BEEN CLOSED\")) //\n                    || (error_text.contains(\"BROKEN PIPE\")) //\n                    || (error_text.contains(\"管道已结束\")) //\n            ) {\n                return true;\n            }\n\n        }\n\n        return fatalErrorCodes.contains(error_code);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/OracleValidConnectionChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ValidConnectionChecker;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.io.Serializable;\nimport java.sql.Connection;\nimport java.util.Properties;\n\npublic class OracleValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker, Serializable {\n    private static final long serialVersionUID = -2227528634302168877L;\n\n    private int timeout = 1;\n\n    private String defaultValidateQuery = \"SELECT 'x' FROM DUAL\";\n\n    public OracleValidConnectionChecker() {\n        configFromProperties(System.getProperties());\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n        if (properties == null) {\n            return;\n        }\n\n        String property = properties.getProperty(\"druid.oracle.pingTimeout\");\n        if (property != null && property.length() > 0) {\n            int value = Integer.parseInt(property);\n            setTimeout(value);\n        }\n    }\n\n    public void setTimeout(int seconds) {\n        this.timeout = seconds;\n    }\n\n    public boolean isValidConnection(Connection conn,\n                                     String validateQuery,\n                                     int validationQueryTimeout) throws Exception {\n        if (conn.isClosed()) {\n            return false;\n        }\n\n        if (StringUtils.isEmpty(validateQuery)) {\n            validateQuery = this.defaultValidateQuery;\n        }\n\n        int queryTimeout = validationQueryTimeout <= 0 ? timeout : validationQueryTimeout;\n\n        return ValidConnectionCheckerAdapter.execValidQuery(conn, validateQuery, queryTimeout);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/PGExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\n\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.util.Properties;\n\npublic class PGExceptionSorter implements ExceptionSorter {\n    @Override\n    public boolean isExceptionFatal(SQLException e) {\n        if (e instanceof SQLRecoverableException) {\n            return true;\n        }\n\n        String sqlState = e.getSQLState();\n        if (sqlState == null) {\n            return false;\n        }\n\n        // org.postgresql.util.PSQLState\n        if (sqlState.startsWith(\"08\")) {\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/PGValidConnectionChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ValidConnectionChecker;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.io.Serializable;\nimport java.sql.Connection;\n\npublic class PGValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker, Serializable {\n    private static final long serialVersionUID = -2227528634302168877L;\n\n    private String defaultValidateQuery = \"SELECT 'x'\";\n\n    public PGValidConnectionChecker() {\n        configFromProperties(System.getProperties());\n    }\n\n    /**\n     * pgsql Driver 9.0以及以下版本不支持setQueryTimeout，可通过设置validationQueryTimeout小于0兼容低版本\n     */\n    public boolean isValidConnection(Connection conn,\n                                     String validateQuery,\n                                     int validationQueryTimeout) throws Exception {\n        if (conn.isClosed()) {\n            return false;\n        }\n\n        if (StringUtils.isEmpty(validateQuery)) {\n            validateQuery = this.defaultValidateQuery;\n        }\n\n        return ValidConnectionCheckerAdapter.execValidQuery(conn, validateQuery, validationQueryTimeout);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/PhoenixExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\npublic class PhoenixExceptionSorter implements ExceptionSorter {\n    private static final Log LOG = LogFactory.getLog(OracleExceptionSorter.class);\n\n    /**\n     * 解决phoenix 的错误 --Connection is null or closed\n     *\n     * @param e the exception\n     * @return a boolean indicating whether the SQLException is fatal\n     */\n    @Override\n    public boolean isExceptionFatal(SQLException e) {\n        if (e.getMessage().contains(\"Connection is null or closed\")) {\n            LOG.error(\"剔除phoenix不可用的连接\", e);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/vendor/SybaseExceptionSorter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.vendor;\n\nimport com.alibaba.druid.pool.ExceptionSorter;\n\nimport java.io.Serializable;\nimport java.sql.SQLException;\nimport java.sql.SQLRecoverableException;\nimport java.util.Properties;\n\npublic class SybaseExceptionSorter implements ExceptionSorter, Serializable {\n    private static final long serialVersionUID = 2742592563671255116L;\n\n    public SybaseExceptionSorter() {\n        this.configFromProperties(System.getProperties());\n    }\n\n    public boolean isExceptionFatal(SQLException e) {\n        if (e instanceof SQLRecoverableException) {\n            return true;\n        }\n\n        boolean result = false;\n\n        String errorText = e.getMessage();\n        if (errorText == null) {\n            return false;\n        }\n        errorText = errorText.toUpperCase();\n\n        if ((errorText.contains(\"JZ0C0\")) || // ERR_CONNECTION_DEAD\n                (errorText.contains(\"JZ0C1\")) // ERR_IOE_KILLED_CONNECTION\n        ) {\n            result = true;\n        }\n\n        return result;\n    }\n\n    public void configFromProperties(Properties properties) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/xa/DruidPooledXAConnection.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.xa;\n\nimport com.alibaba.druid.pool.DruidPooledConnection;\n\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.StatementEventListener;\nimport javax.sql.XAConnection;\nimport javax.transaction.xa.XAResource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\npublic class DruidPooledXAConnection implements XAConnection {\n    private DruidPooledConnection pooledConnection;\n    private XAConnection xaConnection;\n\n    public DruidPooledXAConnection(DruidPooledConnection pooledConnection, XAConnection xaConnection) {\n        this.pooledConnection = pooledConnection;\n        this.xaConnection = xaConnection;\n\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        return pooledConnection;\n    }\n\n    @Override\n    public void close() throws SQLException {\n        pooledConnection.close();\n    }\n\n    @Override\n    public void addConnectionEventListener(ConnectionEventListener listener) {\n        pooledConnection.addConnectionEventListener(listener);\n    }\n\n    @Override\n    public void removeConnectionEventListener(ConnectionEventListener listener) {\n        pooledConnection.removeConnectionEventListener(listener);\n    }\n\n    @Override\n    public void addStatementEventListener(StatementEventListener listener) {\n        pooledConnection.addStatementEventListener(listener);\n    }\n\n    @Override\n    public void removeStatementEventListener(StatementEventListener listener) {\n        pooledConnection.removeStatementEventListener(listener);\n    }\n\n    @Override\n    public XAResource getXAResource() throws SQLException {\n        return xaConnection.getXAResource();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/xa/DruidXADataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.xa;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.*;\nimport com.oceanbase.jdbc.OceanBaseConnection;\nimport com.oceanbase.jdbc.OceanBaseXaConnection;\nimport dm.jdbc.driver.DmdbXAConnection;\n\nimport javax.sql.XAConnection;\nimport javax.sql.XADataSource;\nimport javax.transaction.xa.XAException;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\npublic class DruidXADataSource extends DruidDataSource implements XADataSource {\n    private static final Log LOG = LogFactory.getLog(DruidXADataSource.class);\n\n    private static final long serialVersionUID = 1L;\n\n    private Object h2Factory;\n\n    @Override\n    public XAConnection getXAConnection() throws SQLException {\n        DruidPooledConnection conn = this.getConnection();\n\n        Connection physicalConn = conn.unwrap(Connection.class);\n\n        XAConnection rawXAConnection = createPhysicalXAConnection(physicalConn);\n\n        return new DruidPooledXAConnection(conn, rawXAConnection);\n    }\n\n    protected void initCheck() throws SQLException {\n        super.initCheck();\n\n        DbType dbType = DbType.of(this.dbTypeName);\n        if (JdbcUtils.H2.equals(dbType)) {\n            h2Factory = H2Utils.createJdbcDataSourceFactory();\n        }\n    }\n\n    private XAConnection createPhysicalXAConnection(Connection physicalConn) throws SQLException {\n        DbType dbType = DbType.of(this.dbTypeName);\n\n        if (dbType == null) {\n            throw new SQLException(\"xa not support dbType : \" + this.dbTypeName);\n        }\n\n        switch (dbType) {\n            case oracle:\n                try {\n                    return OracleUtils.OracleXAConnection(physicalConn);\n                } catch (XAException xae) {\n                    LOG.error(\"create xaConnection error\", xae);\n                    return null;\n                }\n            case mysql:\n            case mariadb:\n                return MySqlUtils.createXAConnection(driver, physicalConn);\n            case postgresql:\n                return PGUtils.createXAConnection(physicalConn);\n            case h2:\n                return H2Utils.createXAConnection(h2Factory, physicalConn);\n            case jtds:\n                return new JtdsXAConnection(physicalConn);\n            case dm:\n                return new DmdbXAConnection(physicalConn);\n            case oceanbase:\n            case oceanbase_oracle:\n                return new OceanBaseXaConnection((OceanBaseConnection) physicalConn);\n            default:\n                throw new SQLException(\"xa not support dbType : \" + this.dbTypeName);\n\n        }\n    }\n\n    @Override\n    public XAConnection getXAConnection(String user, String password) throws SQLException {\n        throw new UnsupportedOperationException(\"Not supported by DruidDataSource\");\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/xa/JtdsXAConnection.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.xa;\n\nimport com.alibaba.druid.util.JdbcUtils;\nimport net.sourceforge.jtds.jdbc.XASupport;\n\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.StatementEventListener;\nimport javax.sql.XAConnection;\nimport javax.transaction.xa.XAResource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\npublic class JtdsXAConnection implements XAConnection {\n    private Connection connection;\n\n    private final XAResource resource;\n    private final int xaConnectionId;\n\n    public JtdsXAConnection(Connection connection) throws SQLException {\n        this.resource = new JtdsXAResource(this, connection);\n        this.connection = connection;\n        this.xaConnectionId = XASupport.xa_open(connection);\n    }\n\n    int getXAConnectionID() {\n        return this.xaConnectionId;\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        return connection;\n    }\n\n    @Override\n    public void close() throws SQLException {\n        try {\n            XASupport.xa_close(connection, xaConnectionId);\n        } catch (SQLException e) {\n            // Ignore close errors\n        }\n\n        JdbcUtils.close(connection);\n    }\n\n    @Override\n    public void addConnectionEventListener(ConnectionEventListener listener) {\n    }\n\n    @Override\n    public void removeConnectionEventListener(ConnectionEventListener listener) {\n    }\n\n    @Override\n    public void addStatementEventListener(StatementEventListener listener) {\n    }\n\n    @Override\n    public void removeStatementEventListener(StatementEventListener listener) {\n    }\n\n    @Override\n    public XAResource getXAResource() throws SQLException {\n        return resource;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/pool/xa/JtdsXAResource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.pool.xa;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport net.sourceforge.jtds.jdbc.XASupport;\n\nimport javax.transaction.xa.XAException;\nimport javax.transaction.xa.XAResource;\nimport javax.transaction.xa.Xid;\n\nimport java.lang.reflect.Method;\nimport java.sql.Connection;\n\npublic class JtdsXAResource implements XAResource {\n    private static final Log LOG = LogFactory.getLog(JtdsXAResource.class);\n\n    private final Connection connection;\n    private final JtdsXAConnection xaConnection;\n    private String rmHost;\n\n    private static Method method;\n\n    public JtdsXAResource(JtdsXAConnection xaConnection, Connection connection) {\n        this.xaConnection = xaConnection;\n        this.connection = connection;\n\n        if (method == null) {\n            try {\n                method = connection.getClass().getMethod(\"getRmHost\");\n            } catch (Exception e) {\n                LOG.error(\"getRmHost method error\", e);\n            }\n        }\n\n        if (method != null) {\n            try {\n                rmHost = (String) method.invoke(connection);\n            } catch (Exception e) {\n                LOG.error(\"getRmHost error\", e);\n            }\n        }\n    }\n\n    protected JtdsXAConnection getResourceManager() {\n        return xaConnection;\n    }\n\n    protected String getRmHost() {\n        return this.rmHost;\n    }\n\n    @Override\n    public void commit(Xid xid, boolean commit) throws XAException {\n        XASupport.xa_commit(connection, xaConnection.getXAConnectionID(), xid, commit);\n    }\n\n    @Override\n    public void end(Xid xid, int flags) throws XAException {\n        XASupport.xa_end(connection, xaConnection.getXAConnectionID(), xid, flags);\n    }\n\n    @Override\n    public void forget(Xid xid) throws XAException {\n        XASupport.xa_forget(connection, xaConnection.getXAConnectionID(), xid);\n    }\n\n    @Override\n    public int getTransactionTimeout() throws XAException {\n        return 0;\n    }\n\n    @Override\n    public boolean isSameRM(XAResource xares) throws XAException {\n        if (xares instanceof JtdsXAResource) {\n            if (((JtdsXAResource) xares).getRmHost().equals(this.rmHost)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public int prepare(Xid xid) throws XAException {\n        return XASupport.xa_prepare(connection, xaConnection.getXAConnectionID(), xid);\n    }\n\n    @Override\n    public Xid[] recover(int flags) throws XAException {\n        return XASupport.xa_recover(connection, xaConnection.getXAConnectionID(), flags);\n    }\n\n    @Override\n    public void rollback(Xid xid) throws XAException {\n        XASupport.xa_rollback(connection, xaConnection.getXAConnectionID(), xid);\n    }\n\n    @Override\n    public boolean setTransactionTimeout(int seconds) throws XAException {\n        return false;\n    }\n\n    @Override\n    public void start(Xid xid, int flags) throws XAException {\n        XASupport.xa_start(connection, xaConnection.getXAConnectionID(), xid, flags);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/DruidDriver.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy;\n\nimport com.alibaba.druid.VERSION;\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterManager;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JMXUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\n\nimport java.lang.management.ManagementFactory;\nimport java.security.AccessController;\nimport java.security.PrivilegedAction;\nimport java.sql.*;\nimport java.util.Properties;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.logging.Logger;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDriver implements Driver, DruidDriverMBean {\n    private static Log LOG; // lazy init\n\n    private static final DruidDriver instance = new DruidDriver();\n\n    private static final ConcurrentMap<String, DataSourceProxyImpl> proxyDataSources = new ConcurrentHashMap<String, DataSourceProxyImpl>(16, 0.75f, 1);\n    private static final AtomicInteger dataSourceIdSeed = new AtomicInteger(0);\n    private static final AtomicInteger sqlStatIdSeed = new AtomicInteger(0);\n\n    public static final String DEFAULT_PREFIX = \"jdbc:wrap-jdbc:\";\n    public static final String DRIVER_PREFIX = \"driver=\";\n    public static final String PASSWORD_CALLBACK_PREFIX = \"passwordCallback=\";\n    public static final String NAME_PREFIX = \"name=\";\n    public static final String JMX_PREFIX = \"jmx=\";\n    public static final String FILTERS_PREFIX = \"filters=\";\n\n    private final AtomicLong connectCount = new AtomicLong(0);\n\n    private String acceptPrefix = DEFAULT_PREFIX;\n\n    private int majorVersion = 4;\n\n    private int minorVersion;\n\n    private static final String MBEAN_NAME = \"com.alibaba.druid:type=DruidDriver\";\n\n    static {\n        AccessController.doPrivileged(new PrivilegedAction<Object>() {\n            @Override\n            public Object run() {\n                registerDriver(instance);\n                return null;\n            }\n        });\n    }\n\n    public static boolean registerDriver(Driver driver) {\n        try {\n            DriverManager.registerDriver(driver);\n\n            try {\n                MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n\n                ObjectName objectName = new ObjectName(MBEAN_NAME);\n                if (!mbeanServer.isRegistered(objectName)) {\n                    mbeanServer.registerMBean(instance, objectName);\n                }\n            } catch (Throwable ex) {\n                if (LOG == null) {\n                    LOG = LogFactory.getLog(DruidDriver.class);\n                }\n                LOG.warn(\"register druid-driver mbean error\", ex);\n            }\n\n            return true;\n        } catch (Exception e) {\n            if (LOG == null) {\n                LOG = LogFactory.getLog(DruidDriver.class);\n            }\n\n            LOG.error(\"registerDriver error\", e);\n        }\n\n        return false;\n    }\n\n    public DruidDriver() {\n    }\n\n    public static DruidDriver getInstance() {\n        return instance;\n    }\n\n    public static int createDataSourceId() {\n        return dataSourceIdSeed.incrementAndGet();\n    }\n\n    public static int createSqlStatId() {\n        return sqlStatIdSeed.incrementAndGet();\n    }\n\n    @Override\n    public boolean acceptsURL(String url) throws SQLException {\n        if (url == null) {\n            return false;\n        }\n\n        if (url.startsWith(acceptPrefix)) {\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public Connection connect(String url, Properties info) throws SQLException {\n        if (!acceptsURL(url)) {\n            return null;\n        }\n\n        connectCount.incrementAndGet();\n\n        DataSourceProxyImpl dataSource = getDataSource(url, info);\n\n        return dataSource.connect(info);\n    }\n\n    /**\n     * 参数定义： com.alibaba.druid.log.LogFilter=filter com.alibaba.druid.log.LogFilter.p1=prop-value\n     * com.alibaba.druid.log.LogFilter.p2=prop-value\n     *\n     * @param url\n     * @return\n     * @throws SQLException\n     */\n    public static DataSourceProxyImpl getDataSource(String url, Properties info) throws SQLException {\n        DataSourceProxyImpl dataSource = proxyDataSources.get(url);\n\n        if (dataSource == null) {\n            DataSourceProxyConfig config = parseConfig(url, info);\n\n            Driver rawDriver = createDriver(config.getRawDriverClassName());\n\n            DataSourceProxyImpl newDataSource = new DataSourceProxyImpl(rawDriver, config);\n\n            {\n                String property = System.getProperty(\"druid.filters\");\n                if (property != null && property.length() > 0) {\n                    for (String filterItem : property.split(\",\")) {\n                        FilterManager.loadFilter(config.getFilters(), filterItem);\n                    }\n                }\n            }\n            {\n                int dataSourceId = createDataSourceId();\n                newDataSource.setId(dataSourceId);\n\n                for (Filter filter : config.getFilters()) {\n                    filter.init(newDataSource);\n                }\n            }\n\n            DataSourceProxy oldDataSource = proxyDataSources.putIfAbsent(url, newDataSource);\n            if (oldDataSource == null) {\n                if (config.isJmxOption()) {\n                    JMXUtils.register(\"com.alibaba.druid:type=JdbcStat\", JdbcStatManager.getInstance());\n                }\n            }\n\n            dataSource = proxyDataSources.get(url);\n        }\n        return dataSource;\n    }\n\n    public static DataSourceProxyConfig parseConfig(String url, Properties info) throws SQLException {\n        String restUrl = url.substring(DEFAULT_PREFIX.length());\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        int colonPos = -1;\n        while ((colonPos = restUrl.indexOf(\":\")) != -1)\n        {\n            if (restUrl.startsWith(\"jdbc:\")) {\n                break;\n            }\n            if (restUrl.indexOf(\"=\") == -1) {\n                break;\n            }\n            String fragmentText = restUrl.substring(0, colonPos);\n            int equalPos = fragmentText.indexOf(\"=\");\n            if (equalPos == -1)\n            {\n                continue;\n            }\n            String key = fragmentText.substring(0, equalPos + 1);\n            String value = fragmentText.substring(equalPos + 1);\n            if (StringUtils.equalsIgnoreCase(key, DRIVER_PREFIX))\n            {\n                config.setRawDriverClassName(value.trim());\n            }\n            else if (StringUtils.equalsIgnoreCase(key, FILTERS_PREFIX))\n            {\n                for (String filterItem : value.split(\",\")) {\n                    FilterManager.loadFilter(config.getFilters(), filterItem);\n                }\n            }\n            else if (StringUtils.equalsIgnoreCase(key, NAME_PREFIX))\n            {\n                config.setName(value);\n            }\n            else if (StringUtils.equalsIgnoreCase(key, JMX_PREFIX))\n            {\n                config.setJmxOption(value);\n            }\n            restUrl = restUrl.substring(colonPos + 1);\n        }\n        config.setRawUrl(restUrl);\n        if (config.getRawDriverClassName() == null || config.getRawDriverClassName().isEmpty()) {\n            String rawDriverClassname = JdbcUtils.getDriverClassName(restUrl);\n            config.setRawDriverClassName(rawDriverClassname);\n        }\n        config.setUrl(url);\n        return config;\n    }\n\n    public static Driver createDriver(final String className) throws SQLException {\n        Class<?> rawDriverClass = Utils.loadClass(className);\n\n        if (rawDriverClass == null) {\n            throw new SQLException(\"jdbc-driver's class not found. '\" + className + \"'\");\n        }\n\n        Driver rawDriver;\n        try {\n            rawDriver = (Driver) rawDriverClass.newInstance();\n        } catch (InstantiationException e) {\n            throw new SQLException(\"create driver instance error, driver className '\" + className + \"'\", e);\n        } catch (IllegalAccessException e) {\n            throw new SQLException(\"create driver instance error, driver className '\" + className + \"'\", e);\n        }\n\n        return rawDriver;\n    }\n\n    @Override\n    public int getMajorVersion() {\n        return this.majorVersion;\n    }\n\n    @Override\n    public int getMinorVersion() {\n        return this.minorVersion;\n    }\n\n    @Override\n    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {\n        DataSourceProxyImpl dataSource = getDataSource(url, info);\n        return dataSource.getRawDriver().getPropertyInfo(dataSource.getConfig().getRawUrl(), info);\n    }\n\n    @Override\n    public boolean jdbcCompliant() {\n        return true;\n    }\n\n    @Override\n    public long getConnectCount() {\n        return connectCount.get();\n    }\n\n    public String getAcceptPrefix() {\n        return acceptPrefix;\n    }\n\n    @Override\n    public String[] getDataSourceUrls() {\n        return proxyDataSources.keySet().toArray(new String[proxyDataSources.size()]);\n    }\n\n    public static ConcurrentMap<String, DataSourceProxyImpl> getProxyDataSources() {\n        return proxyDataSources;\n    }\n\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    @Override\n    public void resetStat() {\n        connectCount.set(0);\n    }\n\n    @Override\n    public String getDruidVersion() {\n        return VERSION.getVersionNumber();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/DruidDriverMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface DruidDriverMBean {\n    String getDruidVersion();\n\n    long getConnectCount();\n\n    void resetStat();\n\n    String getAcceptPrefix();\n\n    boolean jdbcCompliant();\n\n    int getMinorVersion();\n\n    int getMajorVersion();\n\n    String[] getDataSourceUrls();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/CallableStatementProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.CallableStatement;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface CallableStatementProxy extends CallableStatement, PreparedStatementProxy {\n    CallableStatement getRawObject();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/CallableStatementProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.Calendar;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class CallableStatementProxyImpl extends PreparedStatementProxyImpl implements CallableStatementProxy {\n    private final CallableStatement statement;\n\n    public CallableStatementProxyImpl(ConnectionProxy connection, CallableStatement statement, String sql, long id) {\n        super(connection, statement, sql, id);\n        this.statement = statement;\n    }\n\n    public CallableStatement getRawObject() {\n        return this.statement;\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_registerOutParameter(this, parameterIndex, sqlType);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_registerOutParameter(this, parameterIndex, sqlType, scale);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public boolean wasNull() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean wasNull = chain.callableStatement_wasNull(this);\n        recycleFilterChain(chain);\n        return wasNull;\n    }\n\n    @Override\n    public String getString(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.callableStatement_getString(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean getBoolean(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.callableStatement_getBoolean(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public byte getByte(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte value = chain.callableStatement_getByte(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public short getShort(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        short value = chain.callableStatement_getShort(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getInt(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.callableStatement_getInt(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public long getLong(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        long value = chain.callableStatement_getLong(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public float getFloat(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        float value = chain.callableStatement_getFloat(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public double getDouble(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        double value = chain.callableStatement_getDouble(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {\n        FilterChainImpl chain = createChain();\n        BigDecimal decimal = chain.callableStatement_getBigDecimal(this, parameterIndex, scale);\n        recycleFilterChain(chain);\n        return decimal;\n    }\n\n    @Override\n    public byte[] getBytes(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte[] bytes = chain.callableStatement_getBytes(this, parameterIndex);\n        recycleFilterChain(chain);\n        return bytes;\n    }\n\n    @Override\n    public java.sql.Date getDate(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date value = chain.callableStatement_getDate(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public java.sql.Time getTime(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time value = chain.callableStatement_getTime(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp value = chain.callableStatement_getTimestamp(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Object getObject(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.callableStatement_getObject(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        BigDecimal decimal = chain.callableStatement_getBigDecimal(this, parameterIndex);\n        recycleFilterChain(chain);\n        return decimal;\n    }\n\n    @Override\n    public Object getObject(int parameterIndex, java.util.Map<String, Class<?>> map) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.callableStatement_getObject(this, parameterIndex, map);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Ref getRef(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Ref value = chain.callableStatement_getRef(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Blob getBlob(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Blob value = chain.callableStatement_getBlob(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Clob getClob(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Clob value = chain.callableStatement_getClob(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Array getArray(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Array value = chain.callableStatement_getArray(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public java.sql.Date getDate(int parameterIndex, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date date = chain.callableStatement_getDate(this, parameterIndex, cal);\n        recycleFilterChain(chain);\n        return date;\n    }\n\n    @Override\n    public java.sql.Time getTime(int parameterIndex, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time time = chain.callableStatement_getTime(this, parameterIndex, cal);\n        recycleFilterChain(chain);\n        return time;\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp timestamp = chain.callableStatement_getTimestamp(this, parameterIndex, cal);\n        recycleFilterChain(chain);\n        return timestamp;\n    }\n\n    @Override\n    public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_registerOutParameter(this, parameterIndex, sqlType, typeName);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_registerOutParameter(this, parameterName, sqlType);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_registerOutParameter(this, parameterName, sqlType, scale);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_registerOutParameter(this, parameterName, sqlType, typeName);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public java.net.URL getURL(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        URL url = chain.callableStatement_getURL(this, parameterIndex);\n        recycleFilterChain(chain);\n        return url;\n    }\n\n    @Override\n    public void setURL(String parameterName, java.net.URL val) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setURL(this, parameterName, val);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNull(String parameterName, int sqlType) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNull(this, parameterName, sqlType);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBoolean(String parameterName, boolean x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBoolean(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setByte(String parameterName, byte x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setByte(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setShort(String parameterName, short x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setShort(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setInt(String parameterName, int x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setInt(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setLong(String parameterName, long x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setLong(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setFloat(String parameterName, float x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setFloat(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setDouble(String parameterName, double x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setDouble(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBigDecimal(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setString(String parameterName, String x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setString(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBytes(String parameterName, byte[] x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBytes(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setDate(String parameterName, java.sql.Date x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setDate(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTime(String parameterName, java.sql.Time x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setTime(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTimestamp(String parameterName, java.sql.Timestamp x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setTimestamp(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, java.io.InputStream x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setAsciiStream(this, parameterName, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, java.io.InputStream x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBinaryStream(this, parameterName, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setObject(this, parameterName, x, targetSqlType, scale);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setObject(this, parameterName, x, targetSqlType);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setObject(String parameterName, Object x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setObject(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, java.io.Reader reader, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setCharacterStream(this, parameterName, reader, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setDate(String parameterName, java.sql.Date x, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setDate(this, parameterName, x, cal);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTime(String parameterName, java.sql.Time x, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setTime(this, parameterName, x, cal);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setTimestamp(this, parameterName, x, cal);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNull(this, parameterName, sqlType, typeName);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public String getString(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.callableStatement_getString(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean getBoolean(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.callableStatement_getBoolean(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public byte getByte(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte value = chain.callableStatement_getByte(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public short getShort(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        short value = chain.callableStatement_getShort(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getInt(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.callableStatement_getInt(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public long getLong(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        long value = chain.callableStatement_getLong(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public float getFloat(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        float value = chain.callableStatement_getFloat(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public double getDouble(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        double value = chain.callableStatement_getDouble(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public byte[] getBytes(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte[] value = chain.callableStatement_getBytes(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public java.sql.Date getDate(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date date = chain.callableStatement_getDate(this, parameterName);\n        recycleFilterChain(chain);\n        return date;\n    }\n\n    @Override\n    public java.sql.Time getTime(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time time = chain.callableStatement_getTime(this, parameterName);\n        recycleFilterChain(chain);\n        return time;\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp timestamp = chain.callableStatement_getTimestamp(this, parameterName);\n        recycleFilterChain(chain);\n        return timestamp;\n    }\n\n    @Override\n    public Object getObject(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.callableStatement_getObject(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        BigDecimal decimal = chain.callableStatement_getBigDecimal(this, parameterName);\n        recycleFilterChain(chain);\n        return decimal;\n    }\n\n    @Override\n    public Object getObject(String parameterName, java.util.Map<String, Class<?>> map) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.callableStatement_getObject(this, parameterName, map);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Ref getRef(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Ref value = chain.callableStatement_getRef(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Blob getBlob(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Blob value = chain.callableStatement_getBlob(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Clob getClob(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Clob clob = chain.callableStatement_getClob(this, parameterName);\n        recycleFilterChain(chain);\n        return clob;\n    }\n\n    @Override\n    public Array getArray(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Array array = chain.callableStatement_getArray(this, parameterName);\n        recycleFilterChain(chain);\n        return array;\n    }\n\n    @Override\n    public java.sql.Date getDate(String parameterName, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date date = chain.callableStatement_getDate(this, parameterName, cal);\n        recycleFilterChain(chain);\n        return date;\n    }\n\n    @Override\n    public java.sql.Time getTime(String parameterName, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time time = chain.callableStatement_getTime(this, parameterName, cal);\n        recycleFilterChain(chain);\n        return time;\n    }\n\n    @Override\n    public java.sql.Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp timestamp = chain.callableStatement_getTimestamp(this, parameterName, cal);\n        recycleFilterChain(chain);\n        return timestamp;\n    }\n\n    @Override\n    public java.net.URL getURL(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        URL url = chain.callableStatement_getURL(this, parameterName);\n        recycleFilterChain(chain);\n        return url;\n    }\n\n    @Override\n    public RowId getRowId(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        RowId rowId = chain.callableStatement_getRowId(this, parameterIndex);\n        recycleFilterChain(chain);\n        return rowId;\n    }\n\n    @Override\n    public RowId getRowId(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        RowId rowId = chain.callableStatement_getRowId(this, parameterName);\n        recycleFilterChain(chain);\n        return rowId;\n    }\n\n    @Override\n    public void setRowId(String parameterName, RowId x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setRowId(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNString(String parameterName, String value) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNString(this, parameterName, value);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNCharacterStream(this, parameterName, value, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNClob(String parameterName, NClob value) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNClob(this, parameterName, value);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClob(String parameterName, Reader reader, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setClob(this, parameterName, reader, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBlob(this, parameterName, inputStream, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNClob(String parameterName, Reader reader, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNClob(this, parameterName, reader, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public NClob getNClob(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        NClob value = chain.callableStatement_getNClob(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public NClob getNClob(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        NClob value = chain.callableStatement_getNClob(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setSQLXML(this, parameterName, xmlObject);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public SQLXML getSQLXML(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLXML value = chain.callableStatement_getSQLXML(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public SQLXML getSQLXML(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLXML value = chain.callableStatement_getSQLXML(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getNString(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.callableStatement_getNString(this, parameterIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getNString(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.callableStatement_getNString(this, parameterName);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public java.io.Reader getNCharacterStream(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader reader = chain.callableStatement_getNCharacterStream(this, parameterIndex);\n        recycleFilterChain(chain);\n        return reader;\n    }\n\n    @Override\n    public java.io.Reader getNCharacterStream(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader reader = chain.callableStatement_getNCharacterStream(this, parameterName);\n        recycleFilterChain(chain);\n        return reader;\n    }\n\n    @Override\n    public java.io.Reader getCharacterStream(int parameterIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader reader = chain.callableStatement_getCharacterStream(this, parameterIndex);\n        recycleFilterChain(chain);\n        return reader;\n    }\n\n    @Override\n    public java.io.Reader getCharacterStream(String parameterName) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader reader = chain.callableStatement_getCharacterStream(this, parameterName);\n        recycleFilterChain(chain);\n        return reader;\n    }\n\n    @Override\n    public void setBlob(String parameterName, Blob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBlob(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClob(String parameterName, Clob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setClob(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, java.io.InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setAsciiStream(this, parameterName, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, java.io.InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBinaryStream(this, parameterName, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, java.io.Reader reader, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setCharacterStream(this, parameterName, reader, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setAsciiStream(String parameterName, java.io.InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setAsciiStream(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBinaryStream(String parameterName, java.io.InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBinaryStream(this, parameterName, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setCharacterStream(String parameterName, java.io.Reader reader) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setCharacterStream(this, parameterName, reader);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNCharacterStream(String parameterName, Reader value) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNCharacterStream(this, parameterName, value);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClob(String parameterName, Reader reader) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setClob(this, parameterName, reader);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBlob(String parameterName, InputStream inputStream) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setBlob(this, parameterName, inputStream);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNClob(String parameterName, Reader reader) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.callableStatement_setNClob(this, parameterName, reader);\n        recycleFilterChain(chain);\n    }\n\n    public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException {\n        return statement.getObject(parameterIndex, type);\n    }\n\n    public <T> T getObject(String parameterName, Class<T> type) throws SQLException {\n        return statement.getObject(parameterName, type);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == PreparedStatement.class || iface == CallableStatement.class) {\n            return (T) statement;\n        }\n\n        return super.unwrap(iface);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ClobProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Clob;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface ClobProxy extends Clob {\n    ConnectionProxy getConnectionWrapper();\n\n    Clob getRawClob();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ClobProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.filter.FilterChainImpl;\n\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.sql.Clob;\nimport java.sql.SQLException;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class ClobProxyImpl implements ClobProxy {\n    protected final Clob clob;\n    protected final ConnectionProxy connection;\n\n    protected final DataSourceProxy dataSource;\n\n    public ClobProxyImpl(DataSourceProxy dataSource, ConnectionProxy connection, Clob clob) {\n        if (clob == null) {\n            throw new IllegalArgumentException(\"clob is null\");\n        }\n\n        this.dataSource = dataSource;\n        this.connection = connection;\n        this.clob = clob;\n    }\n\n    public FilterChain createChain() {\n        return new FilterChainImpl(dataSource);\n    }\n\n    public ConnectionProxy getConnectionWrapper() {\n        return this.connection;\n    }\n\n    @Override\n    public Clob getRawClob() {\n        return clob;\n    }\n\n    @Override\n    public void free() throws SQLException {\n        createChain().clob_free(this);\n    }\n\n    @Override\n    public InputStream getAsciiStream() throws SQLException {\n        return createChain().clob_getAsciiStream(this);\n    }\n\n    @Override\n    public Reader getCharacterStream() throws SQLException {\n        return createChain().clob_getCharacterStream(this);\n    }\n\n    @Override\n    public Reader getCharacterStream(long pos, long length) throws SQLException {\n        return createChain().clob_getCharacterStream(this, pos, length);\n    }\n\n    @Override\n    public String getSubString(long pos, int length) throws SQLException {\n        return createChain().clob_getSubString(this, pos, length);\n    }\n\n    @Override\n    public long length() throws SQLException {\n        return createChain().clob_length(this);\n    }\n\n    @Override\n    public long position(String searchstr, long start) throws SQLException {\n        return createChain().clob_position(this, searchstr, start);\n    }\n\n    @Override\n    public long position(Clob searchstr, long start) throws SQLException {\n        return createChain().clob_position(this, searchstr, start);\n    }\n\n    @Override\n    public OutputStream setAsciiStream(long pos) throws SQLException {\n        return createChain().clob_setAsciiStream(this, pos);\n    }\n\n    @Override\n    public Writer setCharacterStream(long pos) throws SQLException {\n        return createChain().clob_setCharacterStream(this, pos);\n    }\n\n    @Override\n    public int setString(long pos, String str) throws SQLException {\n        return createChain().clob_setString(this, pos, str);\n    }\n\n    @Override\n    public int setString(long pos, String str, int offset, int len) throws SQLException {\n        return createChain().clob_setString(this, pos, str, offset, len);\n    }\n\n    @Override\n    public void truncate(long len) throws SQLException {\n        createChain().clob_truncate(this, len);\n    }\n\n    public String toString() {\n        return clob.toString();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ConnectionProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Connection;\nimport java.util.Date;\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface ConnectionProxy extends Connection, WrapperProxy {\n    Connection getRawObject();\n\n    Properties getProperties();\n\n    DataSourceProxy getDirectDataSource();\n\n    Date getConnectedTime();\n\n    TransactionInfo getTransactionInfo();\n\n    int getCloseCount();\n\n    long getLastValidateTimeMillis();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ConnectionProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.filter.stat.StatFilter;\n\nimport java.sql.*;\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class ConnectionProxyImpl extends WrapperProxyImpl implements ConnectionProxy {\n    private final Connection connection;\n\n    private final DataSourceProxy dataSource;\n\n    private final Properties properties;\n\n    private final long connectedTime;\n\n    private TransactionInfo transactionInfo;\n\n    private int closeCount;\n\n    private FilterChainImpl filterChain;\n\n    private long lastValidateTimeMillis;\n\n    public ConnectionProxyImpl(DataSourceProxy dataSource, Connection connection, Properties properties, long id) {\n        super(connection, id);\n        this.dataSource = dataSource;\n        this.connection = connection;\n        this.properties = properties;\n        this.connectedTime = System.currentTimeMillis();\n    }\n\n    public Date getConnectedTime() {\n        return new Date(connectedTime);\n    }\n\n    public Properties getProperties() {\n        return properties;\n    }\n\n    public Connection getConnectionRaw() {\n        return connection;\n    }\n\n    public Connection getRawObject() {\n        return connection;\n    }\n\n    public DataSourceProxy getDirectDataSource() {\n        return this.dataSource;\n    }\n\n    public FilterChainImpl createChain() {\n        FilterChainImpl chain = this.filterChain;\n        if (chain == null) {\n            chain = new FilterChainImpl(dataSource);\n        } else {\n            this.filterChain = null;\n        }\n\n        return chain;\n    }\n\n    public void recycleFilterChain(FilterChainImpl chain) {\n        chain.reset();\n        this.filterChain = chain;\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_clearWarnings(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void close() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_close(this);\n        closeCount++;\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void commit() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_commit(this);\n\n        if (transactionInfo != null) {\n            transactionInfo.setEndTimeMillis();\n        }\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Array value = chain.connection_createArrayOf(this, typeName, elements);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Blob createBlob() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Blob value = chain.connection_createBlob(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Clob createClob() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Clob value = chain.connection_createClob(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public NClob createNClob() throws SQLException {\n        FilterChainImpl chain = createChain();\n        NClob value = chain.connection_createNClob(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public SQLXML createSQLXML() throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLXML value = chain.connection_createSQLXML(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Statement createStatement() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Statement stmt = chain.connection_createStatement(this);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public Statement createStatement(int resultSetType, //\n                                     int resultSetConcurrency //\n    ) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Statement stmt = chain.connection_createStatement(this, resultSetType, resultSetConcurrency);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public Statement createStatement(int resultSetType, //\n                                     int resultSetConcurrency, //\n                                     int resultSetHoldability //\n    ) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Statement stmt = chain.connection_createStatement(this, resultSetType, resultSetConcurrency,\n                resultSetHoldability);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Struct value = chain.connection_createStruct(this, typeName, attributes);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean getAutoCommit() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.connection_getAutoCommit(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getCatalog() throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.connection_getCatalog(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Properties getClientInfo() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Properties value = chain.connection_getClientInfo(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getClientInfo(String name) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.connection_getClientInfo(this, name);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getHoldability() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.connection_getHoldability(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public DatabaseMetaData getMetaData() throws SQLException {\n        FilterChainImpl chain = createChain();\n        DatabaseMetaData value = chain.connection_getMetaData(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getTransactionIsolation() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.connection_getTransactionIsolation(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Map<String, Class<?>> getTypeMap() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Map<String, Class<?>> value = chain.connection_getTypeMap(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLWarning value = chain.connection_getWarnings(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.connection_isClosed(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isReadOnly() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.connection_isReadOnly(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isValid(int timeout) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.connection_isValid(this, timeout);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String nativeSQL(String sql) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.connection_nativeSQL(this, sql);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql) throws SQLException {\n        FilterChainImpl chain = createChain();\n        CallableStatement stmt = chain.connection_prepareCall(this, sql);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {\n        FilterChainImpl chain = createChain();\n        CallableStatement stmt = chain.connection_prepareCall(this, sql, resultSetType, resultSetConcurrency);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,\n                                         int resultSetHoldability) throws SQLException {\n        FilterChainImpl chain = createChain();\n        CallableStatement stmt = chain.connection_prepareCall(this, sql, resultSetType, resultSetConcurrency,\n                resultSetHoldability);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql) throws SQLException {\n        FilterChainImpl chain = createChain();\n        PreparedStatement stmt = chain.connection_prepareStatement(this, sql);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {\n        FilterChainImpl chain = createChain();\n        PreparedStatement stmt = chain.connection_prepareStatement(this, sql, autoGeneratedKeys);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {\n        FilterChainImpl chain = createChain();\n        PreparedStatement stmt = chain.connection_prepareStatement(this, sql, columnIndexes);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {\n        FilterChainImpl chain = createChain();\n        PreparedStatement stmt = chain.connection_prepareStatement(this, sql, columnNames);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        FilterChainImpl chain = createChain();\n        PreparedStatement stmt = chain.connection_prepareStatement(this, sql, resultSetType, resultSetConcurrency);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,\n                                              int resultSetHoldability) throws SQLException {\n        FilterChainImpl chain = createChain();\n        PreparedStatement stmt = chain.connection_prepareStatement(this, sql, resultSetType, resultSetConcurrency,\n                resultSetHoldability);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public void releaseSavepoint(Savepoint savepoint) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_releaseSavepoint(this, savepoint);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void rollback() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_rollback(this);\n        recycleFilterChain(chain);\n        if (transactionInfo != null) {\n            transactionInfo.setEndTimeMillis();\n        }\n    }\n\n    @Override\n    public void rollback(Savepoint savepoint) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_rollback(this, savepoint);\n        recycleFilterChain(chain);\n        if (transactionInfo != null) {\n            transactionInfo.setEndTimeMillis();\n        }\n    }\n\n    @Override\n    public void setAutoCommit(boolean autoCommit) throws SQLException {\n        if (!autoCommit) {\n            if (transactionInfo == null) {\n                long transactionId = this.dataSource.createTransactionId();\n                transactionInfo = new TransactionInfo(transactionId);\n                this.putAttribute(StatFilter.ATTR_TRANSACTION, transactionInfo); // compatible for druid 0.1.18\n            }\n        } else {\n            transactionInfo = null;\n        }\n\n        FilterChainImpl chain = createChain();\n        chain.connection_setAutoCommit(this, autoCommit);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setCatalog(String catalog) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setCatalog(this, catalog);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClientInfo(Properties properties) throws SQLClientInfoException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setClientInfo(this, properties);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClientInfo(String name, String value) throws SQLClientInfoException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setClientInfo(this, name, value);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setHoldability(int holdability) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setHoldability(this, holdability);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setReadOnly(boolean readOnly) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setReadOnly(this, readOnly);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public Savepoint setSavepoint() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Savepoint savepoint = chain.connection_setSavepoint(this);\n        recycleFilterChain(chain);\n        return savepoint;\n    }\n\n    @Override\n    public Savepoint setSavepoint(String name) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Savepoint savepoint = chain.connection_setSavepoint(this, name);\n        recycleFilterChain(chain);\n        return savepoint;\n    }\n\n    @Override\n    public void setTransactionIsolation(int level) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setTransactionIsolation(this, level);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setTypeMap(this, map);\n        recycleFilterChain(chain);\n    }\n\n    public void setSchema(String schema) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setSchema(this, schema);\n        recycleFilterChain(chain);\n    }\n\n    public String getSchema() throws SQLException {\n        FilterChainImpl chain = createChain();\n        String schema = chain.connection_getSchema(this);\n        recycleFilterChain(chain);\n        return schema;\n    }\n\n    public void abort(Executor executor) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_abort(this, executor);\n        recycleFilterChain(chain);\n    }\n\n    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.connection_setNetworkTimeout(this, executor, milliseconds);\n        recycleFilterChain(chain);\n    }\n\n    public int getNetworkTimeout() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int networkTimeout = chain.connection_getNetworkTimeout(this);\n        recycleFilterChain(chain);\n        return networkTimeout;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == this.getClass() || iface == ConnectionProxy.class) {\n            return (T) this;\n        }\n\n        return super.unwrap(iface);\n    }\n\n    @Override\n    public TransactionInfo getTransactionInfo() {\n        return transactionInfo;\n    }\n\n    @Override\n    public int getCloseCount() {\n        return closeCount;\n    }\n\n    @Override\n    public long getLastValidateTimeMillis() {\n        return lastValidateTimeMillis;\n    }\n\n    public void setLastValidateTimeMillis(long lastValidateTimeMillis) {\n        this.lastValidateTimeMillis = lastValidateTimeMillis;\n    }\n\n    @Override\n    public String toString() {\n        return \"ConnectionProxyImpl{\" +\n            \"connectedTime=\" + new java.sql.Timestamp(connectedTime) +\n            \", closeCount=\" + closeCount +\n            \", lastValidateTimeMillis=\" + new java.sql.Timestamp(lastValidateTimeMillis) +\n            '}';\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\n\nimport java.sql.Driver;\nimport java.util.List;\nimport java.util.Properties;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface DataSourceProxy {\n    JdbcDataSourceStat getDataSourceStat();\n\n    long getDataSourceId();\n    String getName();\n\n    String getDbType();\n\n    Driver getRawDriver();\n\n    String getUrl();\n\n    String getRawJdbcUrl();\n\n    List<Filter> getProxyFilters();\n\n    long createConnectionId();\n\n    long createStatementId();\n\n    long createResultSetId();\n\n    long createMetaDataId();\n\n    long createTransactionId();\n\n    Properties getConnectProperties();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxyConfig.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.Filter;\n\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.PasswordCallback;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DataSourceProxyConfig {\n    private String rawUrl;\n    private String url;\n    private String rawDriverClassName;\n    private String name;\n    private boolean jmx;\n\n    private PasswordCallback passwordCallback;\n    private NameCallback userCallback;\n    private final List<Filter> filters = new ArrayList<Filter>();\n\n    public DataSourceProxyConfig() {\n    }\n\n    public boolean isJmxOption() {\n        return jmx;\n    }\n\n    public void setJmxOption(boolean jmx) {\n        this.jmx = jmx;\n    }\n\n    public void setJmxOption(String jmx) {\n        this.jmx = Boolean.parseBoolean(jmx);\n    }\n\n    public PasswordCallback getPasswordCallback() {\n        return passwordCallback;\n    }\n\n    public void setPasswordCallback(PasswordCallback passwordCallback) {\n        this.passwordCallback = passwordCallback;\n    }\n\n    public NameCallback getUserCallback() {\n        return userCallback;\n    }\n\n    public void setUserCallback(NameCallback userCallback) {\n        this.userCallback = userCallback;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public List<Filter> getFilters() {\n        return filters;\n    }\n\n    public String getRawUrl() {\n        return rawUrl;\n    }\n\n    public void setRawUrl(String rawUrl) {\n        this.rawUrl = rawUrl;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public String getRawDriverClassName() {\n        return rawDriverClassName;\n    }\n\n    public void setRawDriverClassName(String driverClassName) {\n        this.rawDriverClassName = driverClassName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.CompositeDataSupport;\nimport javax.security.auth.callback.NameCallback;\nimport javax.security.auth.callback.PasswordCallback;\n\nimport java.sql.Driver;\nimport java.sql.SQLException;\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DataSourceProxyImpl implements DataSourceProxy, DataSourceProxyImplMBean {\n    private final Driver rawDriver;\n\n    private final DataSourceProxyConfig config;\n\n    private long id;\n\n    private final long createdTimeMillis = System.currentTimeMillis();\n\n    private Properties properties;\n\n    private String dbType;\n\n    private final AtomicLong connectionIdSeed = new AtomicLong(10000);\n    private final AtomicLong statementIdSeed = new AtomicLong(20000);\n    private final AtomicLong resultSetIdSeed = new AtomicLong(50000);\n    private final AtomicLong metaDataIdSeed = new AtomicLong(100000);\n    private final AtomicLong transactionIdSeed = new AtomicLong(0);\n\n    private final JdbcDataSourceStat dataSourceStat;\n\n    public DataSourceProxyImpl(Driver rawDriver, DataSourceProxyConfig config) {\n        super();\n        this.rawDriver = rawDriver;\n        this.config = config;\n        this.dbType = JdbcUtils.getDbType(config.getRawUrl(), config.getRawDriverClassName());\n        this.dataSourceStat = new JdbcDataSourceStat(config.getName(), config.getUrl(), dbType);\n    }\n\n    public String getDbType() {\n        return dbType;\n    }\n\n    public Driver getRawDriver() {\n        return this.rawDriver;\n    }\n\n    public String getRawUrl() {\n        return config.getRawUrl();\n    }\n\n    public ConnectionProxy connect(Properties info) throws SQLException {\n        this.properties = info;\n\n        PasswordCallback passwordCallback = this.config.getPasswordCallback();\n\n        if (passwordCallback != null) {\n            char[] chars = passwordCallback.getPassword();\n            String password = new String(chars);\n            info.put(\"password\", password);\n        }\n\n        NameCallback userCallback = this.config.getUserCallback();\n        if (userCallback != null) {\n            String user = userCallback.getName();\n            info.put(\"user\", user);\n        }\n\n        FilterChain chain = new FilterChainImpl(this);\n        return chain.connection_connect(info);\n    }\n\n    public DataSourceProxyConfig getConfig() {\n        return config;\n    }\n\n    public long getDataSourceId() {\n        return getId();\n    }\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    @Override\n    public String getName() {\n        return this.config.getName();\n    }\n\n    @Override\n    public String getUrl() {\n        return config.getUrl();\n    }\n\n    public List<Filter> getProxyFilters() {\n        return config.getFilters();\n    }\n\n    @Override\n    public String[] getFilterClasses() {\n        List<Filter> filterConfigList = config.getFilters();\n\n        List<String> classes = new ArrayList<String>();\n        for (Filter filter : filterConfigList) {\n            classes.add(filter.getClass().getName());\n        }\n\n        return classes.toArray(new String[classes.size()]);\n    }\n\n    @Override\n    public String getRawDriverClassName() {\n        return config.getRawDriverClassName();\n    }\n\n    @Override\n    public Date getCreatedTime() {\n        return new Date(createdTimeMillis);\n    }\n\n    @Override\n    public int getRawDriverMajorVersion() {\n        return rawDriver.getMajorVersion();\n    }\n\n    @Override\n    public int getRawDriverMinorVersion() {\n        return rawDriver.getMinorVersion();\n    }\n\n    public String getDataSourceMBeanDomain() {\n        String name = this.config.getName();\n        if (name != null && name.length() != 0) {\n            return name;\n        }\n\n        return \"java.sql.dataSource_\" + System.identityHashCode(this);\n    }\n\n    public String getProperties() {\n        if (this.properties == null) {\n            return null;\n        }\n\n        Properties properties = new Properties(this.properties);\n        if (properties.contains(\"password\")) {\n            properties.put(\"password\", \"******\");\n        }\n        return properties.toString();\n    }\n\n    public Properties getConnectProperties() {\n        return properties;\n    }\n\n    public CompositeDataSupport getCompositeData() throws JMException {\n        JdbcDataSourceStat stat = this.getDataSourceStat();\n\n        Map<String, Object> map = new HashMap<String, Object>();\n\n        map.put(\"ID\", id);\n        map.put(\"URL\", this.getUrl());\n        map.put(\"Name\", this.getName());\n        map.put(\"FilterClasses\", getFilterClasses());\n        map.put(\"CreatedTime\", getCreatedTime());\n\n        map.put(\"RawDriverClassName\", getRawDriverClassName());\n        map.put(\"RawUrl\", getRawUrl());\n        map.put(\"RawDriverMajorVersion\", getRawDriverMajorVersion());\n        map.put(\"RawDriverMinorVersion\", getRawDriverMinorVersion());\n        map.put(\"Properties\", getProperties());\n\n        if (stat != null) {\n            map.put(\"ConnectionActiveCount\", stat.getConnectionActiveCount());\n            map.put(\"ConnectionActiveCountMax\", stat.getConnectionStat().getActiveMax());\n            map.put(\"ConnectionCloseCount\", stat.getConnectionStat().getCloseCount());\n            map.put(\"ConnectionCommitCount\", stat.getConnectionStat().getCommitCount());\n            map.put(\"ConnectionRollbackCount\", stat.getConnectionStat().getRollbackCount());\n\n            map.put(\"ConnectionConnectLastTime\", stat.getConnectionStat().getConnectLastTime());\n            map.put(\"ConnectionConnectErrorCount\", stat.getConnectionStat().getConnectErrorCount());\n            Throwable lastConnectionConnectError = stat.getConnectionStat().getConnectErrorLast();\n            if (lastConnectionConnectError != null) {\n                map.put(\"ConnectionConnectErrorLastTime\", stat.getConnectionStat().getErrorLastTime());\n                map.put(\"ConnectionConnectErrorLastMessage\", lastConnectionConnectError.getMessage());\n                map.put(\"ConnectionConnectErrorLastStackTrace\", Utils.getStackTrace(lastConnectionConnectError));\n            } else {\n                map.put(\"ConnectionConnectErrorLastTime\", null);\n                map.put(\"ConnectionConnectErrorLastMessage\", null);\n                map.put(\"ConnectionConnectErrorLastStackTrace\", null);\n            }\n\n            map.put(\"StatementCreateCount\", stat.getStatementStat().getCreateCount());\n            map.put(\"StatementPrepareCount\", stat.getStatementStat().getPrepareCount());\n            map.put(\"StatementPreCallCount\", stat.getStatementStat().getPrepareCallCount());\n            map.put(\"StatementExecuteCount\", stat.getStatementStat().getExecuteCount());\n            map.put(\"StatementRunningCount\", stat.getStatementStat().getRunningCount());\n\n            map.put(\"StatementConcurrentMax\", stat.getStatementStat().getConcurrentMax());\n            map.put(\"StatementCloseCount\", stat.getStatementStat().getCloseCount());\n            map.put(\"StatementErrorCount\", stat.getStatementStat().getErrorCount());\n            Throwable lastStatementError = stat.getStatementStat().getLastException();\n            if (lastStatementError != null) {\n                map.put(\"StatementLastErrorTime\", stat.getStatementStat().getLastErrorTime());\n                map.put(\"StatementLastErrorMessage\", lastStatementError.getMessage());\n\n                map.put(\"StatementLastErrorStackTrace\", Utils.getStackTrace(lastStatementError));\n            } else {\n                map.put(\"StatementLastErrorTime\", null);\n                map.put(\"StatementLastErrorMessage\", null);\n\n                map.put(\"StatementLastErrorStackTrace\", null);\n            }\n            map.put(\"StatementExecuteMillisTotal\", stat.getStatementStat().getMillisTotal());\n            map.put(\"StatementExecuteLastTime\", stat.getStatementStat().getExecuteLastTime());\n            map.put(\"ConnectionConnectingCount\", stat.getConnectionStat().getConnectingCount());\n            map.put(\"ResultSetCloseCount\", stat.getResultSetStat().getCloseCount());\n\n            map.put(\"ResultSetOpenCount\", stat.getResultSetStat().getOpenCount());\n            map.put(\"ResultSetOpenningCount\", stat.getResultSetStat().getOpeningCount());\n            map.put(\"ResultSetOpenningMax\", stat.getResultSetStat().getOpeningMax());\n            map.put(\"ResultSetFetchRowCount\", stat.getResultSetStat().getFetchRowCount());\n            map.put(\"ResultSetLastOpenTime\", stat.getResultSetStat().getLastOpenTime());\n\n            map.put(\"ResultSetErrorCount\", stat.getResultSetStat().getErrorCount());\n            map.put(\"ResultSetOpenningMillisTotal\", stat.getResultSetStat().getAliveMillisTotal());\n            map.put(\"ResultSetLastErrorTime\", stat.getResultSetStat().getLastErrorTime());\n            Throwable lastResultSetError = stat.getResultSetStat().getLastError();\n            if (lastResultSetError != null) {\n                map.put(\"ResultSetLastErrorMessage\", lastResultSetError.getMessage());\n                map.put(\"ResultSetLastErrorStackTrace\", Utils.getStackTrace(lastResultSetError));\n            } else {\n                map.put(\"ResultSetLastErrorMessage\", null);\n                map.put(\"ResultSetLastErrorStackTrace\", null);\n            }\n\n            map.put(\"ConnectionConnectCount\", stat.getConnectionStat().getConnectCount());\n            Throwable lastConnectionError = stat.getConnectionStat().getErrorLast();\n            if (lastConnectionError != null) {\n                map.put(\"ConnectionErrorLastMessage\", lastConnectionError.getMessage());\n                map.put(\"ConnectionErrorLastStackTrace\", Utils.getStackTrace(lastConnectionError));\n            } else {\n                map.put(\"ConnectionErrorLastMessage\", null);\n                map.put(\"ConnectionErrorLastStackTrace\", null);\n            }\n            map.put(\"ConnectionConnectMillisTotal\", stat.getConnectionStat().getConnectMillis());\n            map.put(\"ConnectionConnectingCountMax\", stat.getConnectionStat().getConnectingMax());\n\n            map.put(\"ConnectionConnectMillisMax\", stat.getConnectionStat().getConnectMillisMax());\n            map.put(\"ConnectionErrorLastTime\", stat.getConnectionStat().getErrorLastTime());\n            map.put(\"ConnectionAliveMillisMax\", stat.getConnectionConnectAliveMillisMax());\n            map.put(\"ConnectionAliveMillisMin\", stat.getConnectionConnectAliveMillisMin());\n\n            map.put(\"ConnectionHistogram\", stat.getConnectionHistogramValues());\n            map.put(\"StatementHistogram\", stat.getStatementStat().getHistogramValues());\n        } else {\n            map.put(\"ConnectionActiveCount\", null);\n            map.put(\"ConnectionActiveCountMax\", null);\n            map.put(\"ConnectionCloseCount\", null);\n            map.put(\"ConnectionCommitCount\", null);\n            map.put(\"ConnectionRollbackCount\", null);\n\n            map.put(\"ConnectionConnectLastTime\", null);\n            map.put(\"ConnectionConnectErrorCount\", null);\n            map.put(\"ConnectionConnectErrorLastTime\", null);\n            map.put(\"ConnectionConnectErrorLastMessage\", null);\n            map.put(\"ConnectionConnectErrorLastStackTrace\", null);\n\n            map.put(\"StatementCreateCount\", null);\n            map.put(\"StatementPrepareCount\", null);\n            map.put(\"StatementPreCallCount\", null);\n            map.put(\"StatementExecuteCount\", null);\n            map.put(\"StatementRunningCount\", null);\n\n            map.put(\"StatementConcurrentMax\", null);\n            map.put(\"StatementCloseCount\", null);\n            map.put(\"StatementErrorCount\", null);\n            map.put(\"StatementLastErrorTime\", null);\n            map.put(\"StatementLastErrorMessage\", null);\n\n            map.put(\"StatementLastErrorStackTrace\", null);\n            map.put(\"StatementExecuteMillisTotal\", null);\n            map.put(\"ConnectionConnectingCount\", null);\n            map.put(\"StatementExecuteLastTime\", null);\n            map.put(\"ResultSetCloseCount\", null);\n\n            map.put(\"ResultSetOpenCount\", null);\n            map.put(\"ResultSetOpenningCount\", null);\n            map.put(\"ResultSetOpenningMax\", null);\n            map.put(\"ResultSetFetchRowCount\", null);\n            map.put(\"ResultSetLastOpenTime\", null);\n\n            map.put(\"ResultSetErrorCount\", null);\n            map.put(\"ResultSetOpenningMillisTotal\", null);\n            map.put(\"ResultSetLastErrorTime\", null);\n            map.put(\"ResultSetLastErrorMessage\", null);\n            map.put(\"ResultSetLastErrorStackTrace\", null);\n\n            map.put(\"ConnectionConnectCount\", null);\n            map.put(\"ConnectionErrorLastMessage\", null);\n            map.put(\"ConnectionErrorLastStackTrace\", null);\n            map.put(\"ConnectionConnectMillisTotal\", null);\n            map.put(\"ConnectionConnectingCountMax\", null);\n\n            map.put(\"ConnectionConnectMillisMax\", null);\n            map.put(\"ConnectionErrorLastTime\", null);\n            map.put(\"ConnectionAliveMillisMax\", null);\n            map.put(\"ConnectionAliveMillisMin\", null);\n\n            map.put(\"ConnectionHistogram\", new long[0]);\n            map.put(\"StatementHistogram\", new long[0]);\n        }\n\n        return new CompositeDataSupport(JdbcStatManager.getDataSourceCompositeType(), map);\n    }\n\n    @Override\n    public String getRawJdbcUrl() {\n        return config.getRawUrl();\n    }\n\n    public long createConnectionId() {\n        return connectionIdSeed.incrementAndGet();\n    }\n\n    public long createStatementId() {\n        return statementIdSeed.getAndIncrement();\n    }\n\n    public long createResultSetId() {\n        return resultSetIdSeed.getAndIncrement();\n    }\n\n    public long createMetaDataId() {\n        return metaDataIdSeed.getAndIncrement();\n    }\n\n    @Override\n    public long createTransactionId() {\n        return transactionIdSeed.getAndIncrement();\n    }\n\n    public JdbcDataSourceStat getDataSourceStat() {\n        return dataSourceStat;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxyImplMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.util.Date;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface DataSourceProxyImplMBean {\n    String getName();\n\n    String getUrl();\n\n    String getRawUrl();\n\n    Date getCreatedTime();\n\n    String getRawDriverClassName();\n\n    String[] getFilterClasses();\n\n    int getRawDriverMajorVersion();\n\n    int getRawDriverMinorVersion();\n\n    String getProperties();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/DatabaseMetaDataProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.*;\n\n/**\n * Created by wenshao on 26/05/2017.\n */\npublic class DatabaseMetaDataProxyImpl implements DatabaseMetaData {\n    private DatabaseMetaData metaData;\n\n    public DatabaseMetaDataProxyImpl(DatabaseMetaData metaData) {\n        this.metaData = metaData;\n    }\n\n    @Override\n    public boolean allProceduresAreCallable() throws SQLException {\n        return metaData.allProceduresAreCallable();\n    }\n\n    @Override\n    public boolean allTablesAreSelectable() throws SQLException {\n        return metaData.allTablesAreSelectable();\n    }\n\n    @Override\n    public String getURL() throws SQLException {\n        return metaData.getURL();\n    }\n\n    @Override\n    public String getUserName() throws SQLException {\n        return metaData.getUserName();\n    }\n\n    @Override\n    public boolean isReadOnly() throws SQLException {\n        return metaData.isReadOnly();\n    }\n\n    @Override\n    public boolean nullsAreSortedHigh() throws SQLException {\n        return metaData.nullsAreSortedHigh();\n    }\n\n    @Override\n    public boolean nullsAreSortedLow() throws SQLException {\n        return metaData.nullsAreSortedLow();\n    }\n\n    @Override\n    public boolean nullsAreSortedAtStart() throws SQLException {\n        return metaData.nullsAreSortedAtStart();\n    }\n\n    @Override\n    public boolean nullsAreSortedAtEnd() throws SQLException {\n        return metaData.nullsAreSortedAtEnd();\n    }\n\n    @Override\n    public String getDatabaseProductName() throws SQLException {\n        return metaData.getDatabaseProductName();\n    }\n\n    @Override\n    public String getDatabaseProductVersion() throws SQLException {\n        return metaData.getDatabaseProductVersion();\n    }\n\n    @Override\n    public String getDriverName() throws SQLException {\n        return metaData.getDriverName();\n    }\n\n    @Override\n    public String getDriverVersion() throws SQLException {\n        return metaData.getDriverVersion();\n    }\n\n    @Override\n    public int getDriverMajorVersion() {\n        return metaData.getDriverMajorVersion();\n    }\n\n    @Override\n    public int getDriverMinorVersion() {\n        return metaData.getDriverMinorVersion();\n    }\n\n    @Override\n    public boolean usesLocalFiles() throws SQLException {\n        return metaData.usesLocalFiles();\n    }\n\n    @Override\n    public boolean usesLocalFilePerTable() throws SQLException {\n        return metaData.usesLocalFilePerTable();\n    }\n\n    @Override\n    public boolean supportsMixedCaseIdentifiers() throws SQLException {\n        return metaData.supportsMixedCaseIdentifiers();\n    }\n\n    @Override\n    public boolean storesUpperCaseIdentifiers() throws SQLException {\n        return metaData.storesUpperCaseIdentifiers();\n    }\n\n    @Override\n    public boolean storesLowerCaseIdentifiers() throws SQLException {\n        return metaData.storesMixedCaseIdentifiers();\n    }\n\n    @Override\n    public boolean storesMixedCaseIdentifiers() throws SQLException {\n        return metaData.supportsMixedCaseIdentifiers();\n    }\n\n    @Override\n    public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {\n        return metaData.supportsMixedCaseQuotedIdentifiers();\n    }\n\n    @Override\n    public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {\n        return metaData.storesUpperCaseIdentifiers();\n    }\n\n    @Override\n    public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {\n        return metaData.storesLowerCaseQuotedIdentifiers();\n    }\n\n    @Override\n    public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {\n        return metaData.storesMixedCaseQuotedIdentifiers();\n    }\n\n    @Override\n    public String getIdentifierQuoteString() throws SQLException {\n        return metaData.getIdentifierQuoteString();\n    }\n\n    @Override\n    public String getSQLKeywords() throws SQLException {\n        return metaData.getSQLKeywords();\n    }\n\n    @Override\n    public String getNumericFunctions() throws SQLException {\n        return metaData.getNumericFunctions();\n    }\n\n    @Override\n    public String getStringFunctions() throws SQLException {\n        return metaData.getStringFunctions();\n    }\n\n    @Override\n    public String getSystemFunctions() throws SQLException {\n        return metaData.getSystemFunctions();\n    }\n\n    @Override\n    public String getTimeDateFunctions() throws SQLException {\n        return metaData.getTimeDateFunctions();\n    }\n\n    @Override\n    public String getSearchStringEscape() throws SQLException {\n        return metaData.getSearchStringEscape();\n    }\n\n    @Override\n    public String getExtraNameCharacters() throws SQLException {\n        return metaData.getExtraNameCharacters();\n    }\n\n    @Override\n    public boolean supportsAlterTableWithAddColumn() throws SQLException {\n        return metaData.supportsAlterTableWithAddColumn();\n    }\n\n    @Override\n    public boolean supportsAlterTableWithDropColumn() throws SQLException {\n        return metaData.supportsAlterTableWithDropColumn();\n    }\n\n    @Override\n    public boolean supportsColumnAliasing() throws SQLException {\n        return metaData.supportsColumnAliasing();\n    }\n\n    @Override\n    public boolean nullPlusNonNullIsNull() throws SQLException {\n        return metaData.nullPlusNonNullIsNull();\n    }\n\n    @Override\n    public boolean supportsConvert() throws SQLException {\n        return metaData.supportsConvert();\n    }\n\n    @Override\n    public boolean supportsConvert(int fromType, int toType) throws SQLException {\n        return metaData.supportsConvert(fromType, toType);\n    }\n\n    @Override\n    public boolean supportsTableCorrelationNames() throws SQLException {\n        return metaData.supportsTableCorrelationNames();\n    }\n\n    @Override\n    public boolean supportsDifferentTableCorrelationNames() throws SQLException {\n        return metaData.supportsDifferentTableCorrelationNames();\n    }\n\n    @Override\n    public boolean supportsExpressionsInOrderBy() throws SQLException {\n        return metaData.supportsExpressionsInOrderBy();\n    }\n\n    @Override\n    public boolean supportsOrderByUnrelated() throws SQLException {\n        return metaData.supportsOrderByUnrelated();\n    }\n\n    @Override\n    public boolean supportsGroupBy() throws SQLException {\n        return metaData.supportsGroupBy();\n    }\n\n    @Override\n    public boolean supportsGroupByUnrelated() throws SQLException {\n        return metaData.supportsGroupByUnrelated();\n    }\n\n    @Override\n    public boolean supportsGroupByBeyondSelect() throws SQLException {\n        return metaData.supportsGroupByBeyondSelect();\n    }\n\n    @Override\n    public boolean supportsLikeEscapeClause() throws SQLException {\n        return metaData.supportsLikeEscapeClause();\n    }\n\n    @Override\n    public boolean supportsMultipleResultSets() throws SQLException {\n        return metaData.supportsMultipleResultSets();\n    }\n\n    @Override\n    public boolean supportsMultipleTransactions() throws SQLException {\n        return metaData.supportsMultipleTransactions();\n    }\n\n    @Override\n    public boolean supportsNonNullableColumns() throws SQLException {\n        return metaData.supportsNonNullableColumns();\n    }\n\n    @Override\n    public boolean supportsMinimumSQLGrammar() throws SQLException {\n        return metaData.supportsMinimumSQLGrammar();\n    }\n\n    @Override\n    public boolean supportsCoreSQLGrammar() throws SQLException {\n        return metaData.supportsCoreSQLGrammar();\n    }\n\n    @Override\n    public boolean supportsExtendedSQLGrammar() throws SQLException {\n        return metaData.supportsExtendedSQLGrammar();\n    }\n\n    @Override\n    public boolean supportsANSI92EntryLevelSQL() throws SQLException {\n        return metaData.supportsANSI92EntryLevelSQL();\n    }\n\n    @Override\n    public boolean supportsANSI92IntermediateSQL() throws SQLException {\n        return metaData.supportsANSI92IntermediateSQL();\n    }\n\n    @Override\n    public boolean supportsANSI92FullSQL() throws SQLException {\n        return metaData.supportsANSI92FullSQL();\n    }\n\n    @Override\n    public boolean supportsIntegrityEnhancementFacility() throws SQLException {\n        return metaData.supportsIntegrityEnhancementFacility();\n    }\n\n    @Override\n    public boolean supportsOuterJoins() throws SQLException {\n        return metaData.supportsOuterJoins();\n    }\n\n    @Override\n    public boolean supportsFullOuterJoins() throws SQLException {\n        return metaData.supportsFullOuterJoins();\n    }\n\n    @Override\n    public boolean supportsLimitedOuterJoins() throws SQLException {\n        return metaData.supportsLimitedOuterJoins();\n    }\n\n    @Override\n    public String getSchemaTerm() throws SQLException {\n        return metaData.getSchemaTerm();\n    }\n\n    @Override\n    public String getProcedureTerm() throws SQLException {\n        return metaData.getProcedureTerm();\n    }\n\n    @Override\n    public String getCatalogTerm() throws SQLException {\n        return metaData.getCatalogTerm();\n    }\n\n    @Override\n    public boolean isCatalogAtStart() throws SQLException {\n        return metaData.isCatalogAtStart();\n    }\n\n    @Override\n    public String getCatalogSeparator() throws SQLException {\n        return metaData.getCatalogSeparator();\n    }\n\n    @Override\n    public boolean supportsSchemasInDataManipulation() throws SQLException {\n        return metaData.supportsSchemasInDataManipulation();\n    }\n\n    @Override\n    public boolean supportsSchemasInProcedureCalls() throws SQLException {\n        return metaData.supportsSchemasInProcedureCalls();\n    }\n\n    @Override\n    public boolean supportsSchemasInTableDefinitions() throws SQLException {\n        return metaData.supportsSchemasInTableDefinitions();\n    }\n\n    @Override\n    public boolean supportsSchemasInIndexDefinitions() throws SQLException {\n        return metaData.supportsSchemasInIndexDefinitions();\n    }\n\n    @Override\n    public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {\n        return metaData.supportsSchemasInPrivilegeDefinitions();\n    }\n\n    @Override\n    public boolean supportsCatalogsInDataManipulation() throws SQLException {\n        return metaData.supportsCatalogsInDataManipulation();\n    }\n\n    @Override\n    public boolean supportsCatalogsInProcedureCalls() throws SQLException {\n        return metaData.supportsCatalogsInProcedureCalls();\n    }\n\n    @Override\n    public boolean supportsCatalogsInTableDefinitions() throws SQLException {\n        return metaData.supportsCatalogsInTableDefinitions();\n    }\n\n    @Override\n    public boolean supportsCatalogsInIndexDefinitions() throws SQLException {\n        return metaData.supportsCatalogsInIndexDefinitions();\n    }\n\n    @Override\n    public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {\n        return metaData.supportsCatalogsInPrivilegeDefinitions();\n    }\n\n    @Override\n    public boolean supportsPositionedDelete() throws SQLException {\n        return metaData.supportsPositionedDelete();\n    }\n\n    @Override\n    public boolean supportsPositionedUpdate() throws SQLException {\n        return metaData.supportsPositionedUpdate();\n    }\n\n    @Override\n    public boolean supportsSelectForUpdate() throws SQLException {\n        return metaData.supportsSelectForUpdate();\n    }\n\n    @Override\n    public boolean supportsStoredProcedures() throws SQLException {\n        return metaData.supportsStoredProcedures();\n    }\n\n    @Override\n    public boolean supportsSubqueriesInComparisons() throws SQLException {\n        return metaData.supportsSubqueriesInComparisons();\n    }\n\n    @Override\n    public boolean supportsSubqueriesInExists() throws SQLException {\n        return metaData.supportsSubqueriesInExists();\n    }\n\n    @Override\n    public boolean supportsSubqueriesInIns() throws SQLException {\n        return metaData.supportsSubqueriesInIns();\n    }\n\n    @Override\n    public boolean supportsSubqueriesInQuantifieds() throws SQLException {\n        return metaData.supportsSubqueriesInQuantifieds();\n    }\n\n    @Override\n    public boolean supportsCorrelatedSubqueries() throws SQLException {\n        return metaData.supportsCorrelatedSubqueries();\n    }\n\n    @Override\n    public boolean supportsUnion() throws SQLException {\n        return metaData.supportsUnion();\n    }\n\n    @Override\n    public boolean supportsUnionAll() throws SQLException {\n        return metaData.supportsUnionAll();\n    }\n\n    @Override\n    public boolean supportsOpenCursorsAcrossCommit() throws SQLException {\n        return metaData.supportsOpenCursorsAcrossCommit();\n    }\n\n    @Override\n    public boolean supportsOpenCursorsAcrossRollback() throws SQLException {\n        return metaData.supportsOpenCursorsAcrossRollback();\n    }\n\n    @Override\n    public boolean supportsOpenStatementsAcrossCommit() throws SQLException {\n        return metaData.supportsOpenStatementsAcrossCommit();\n    }\n\n    @Override\n    public boolean supportsOpenStatementsAcrossRollback() throws SQLException {\n        return metaData.supportsOpenStatementsAcrossRollback();\n    }\n\n    @Override\n    public int getMaxBinaryLiteralLength() throws SQLException {\n        return metaData.getMaxBinaryLiteralLength();\n    }\n\n    @Override\n    public int getMaxCharLiteralLength() throws SQLException {\n        return metaData.getMaxCharLiteralLength();\n    }\n\n    @Override\n    public int getMaxColumnNameLength() throws SQLException {\n        return metaData.getMaxColumnNameLength();\n    }\n\n    @Override\n    public int getMaxColumnsInGroupBy() throws SQLException {\n        return metaData.getMaxColumnsInGroupBy();\n    }\n\n    @Override\n    public int getMaxColumnsInIndex() throws SQLException {\n        return metaData.getMaxColumnsInIndex();\n    }\n\n    @Override\n    public int getMaxColumnsInOrderBy() throws SQLException {\n        return metaData.getMaxColumnsInOrderBy();\n    }\n\n    @Override\n    public int getMaxColumnsInSelect() throws SQLException {\n        return metaData.getMaxColumnsInSelect();\n    }\n\n    @Override\n    public int getMaxColumnsInTable() throws SQLException {\n        return metaData.getMaxColumnsInTable();\n    }\n\n    @Override\n    public int getMaxConnections() throws SQLException {\n        return metaData.getMaxConnections();\n    }\n\n    @Override\n    public int getMaxCursorNameLength() throws SQLException {\n        return metaData.getMaxCursorNameLength();\n    }\n\n    @Override\n    public int getMaxIndexLength() throws SQLException {\n        return metaData.getMaxIndexLength();\n    }\n\n    @Override\n    public int getMaxSchemaNameLength() throws SQLException {\n        return metaData.getMaxSchemaNameLength();\n    }\n\n    @Override\n    public int getMaxProcedureNameLength() throws SQLException {\n        return metaData.getMaxProcedureNameLength();\n    }\n\n    @Override\n    public int getMaxCatalogNameLength() throws SQLException {\n        return metaData.getMaxCatalogNameLength();\n    }\n\n    @Override\n    public int getMaxRowSize() throws SQLException {\n        return metaData.getMaxRowSize();\n    }\n\n    @Override\n    public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {\n        return metaData.doesMaxRowSizeIncludeBlobs();\n    }\n\n    @Override\n    public int getMaxStatementLength() throws SQLException {\n        return metaData.getMaxStatementLength();\n    }\n\n    @Override\n    public int getMaxStatements() throws SQLException {\n        return metaData.getMaxStatements();\n    }\n\n    @Override\n    public int getMaxTableNameLength() throws SQLException {\n        return metaData.getMaxTableNameLength();\n    }\n\n    @Override\n    public int getMaxTablesInSelect() throws SQLException {\n        return metaData.getMaxTablesInSelect();\n    }\n\n    @Override\n    public int getMaxUserNameLength() throws SQLException {\n        return metaData.getMaxUserNameLength();\n    }\n\n    @Override\n    public int getDefaultTransactionIsolation() throws SQLException {\n        return metaData.getDefaultTransactionIsolation();\n    }\n\n    @Override\n    public boolean supportsTransactions() throws SQLException {\n        return metaData.supportsTransactions();\n    }\n\n    @Override\n    public boolean supportsTransactionIsolationLevel(int level) throws SQLException {\n        return metaData.supportsTransactionIsolationLevel(level);\n    }\n\n    @Override\n    public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {\n        return metaData.supportsDataDefinitionAndDataManipulationTransactions();\n    }\n\n    @Override\n    public boolean supportsDataManipulationTransactionsOnly() throws SQLException {\n        return metaData.supportsDataManipulationTransactionsOnly();\n    }\n\n    @Override\n    public boolean dataDefinitionCausesTransactionCommit() throws SQLException {\n        return metaData.dataDefinitionCausesTransactionCommit();\n    }\n\n    @Override\n    public boolean dataDefinitionIgnoredInTransactions() throws SQLException {\n        return metaData.dataDefinitionIgnoredInTransactions();\n    }\n\n    @Override\n    public ResultSet getProcedures(String catalog,\n                                   String schemaPattern,\n                                   String procedureNamePattern) throws SQLException {\n        return metaData.getProcedures(catalog, schemaPattern, procedureNamePattern);\n    }\n\n    @Override\n    public ResultSet getProcedureColumns(String catalog,\n                                         String schemaPattern,\n                                         String procedureNamePattern,\n                                         String columnNamePattern) throws SQLException {\n        return metaData.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern);\n    }\n\n    @Override\n    public ResultSet getTables(String catalog,\n                               String schemaPattern,\n                               String tableNamePattern,\n                               String[] types) throws SQLException {\n        return metaData.getTables(catalog, schemaPattern, tableNamePattern, types);\n    }\n\n    @Override\n    public ResultSet getSchemas() throws SQLException {\n        return metaData.getSchemas();\n    }\n\n    @Override\n    public ResultSet getCatalogs() throws SQLException {\n        return metaData.getCatalogs();\n    }\n\n    @Override\n    public ResultSet getTableTypes() throws SQLException {\n        return metaData.getTableTypes();\n    }\n\n    @Override\n    public ResultSet getColumns(String catalog,\n                                String schemaPattern,\n                                String tableNamePattern,\n                                String columnNamePattern) throws SQLException {\n        return metaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n    }\n\n    @Override\n    public ResultSet getColumnPrivileges(String catalog,\n                                         String schema,\n                                         String table,\n                                         String columnNamePattern) throws SQLException {\n        return metaData.getColumnPrivileges(catalog, schema, table, columnNamePattern);\n    }\n\n    @Override\n    public ResultSet getTablePrivileges(String catalog,\n                                        String schemaPattern,\n                                        String tableNamePattern) throws SQLException {\n        return metaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern);\n    }\n\n    @Override\n    public ResultSet getBestRowIdentifier(String catalog,\n                                          String schema,\n                                          String table,\n                                          int scope,\n                                          boolean nullable) throws SQLException {\n        return metaData.getBestRowIdentifier(catalog, schema, table, scope, nullable);\n    }\n\n    @Override\n    public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {\n        return metaData.getVersionColumns(catalog, schema, table);\n    }\n\n    @Override\n    public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {\n        return metaData.getPrimaryKeys(catalog, schema, table);\n    }\n\n    @Override\n    public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {\n        return metaData.getImportedKeys(catalog, schema, table);\n    }\n\n    @Override\n    public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {\n        return metaData.getExportedKeys(catalog, schema, table);\n    }\n\n    @Override\n    public ResultSet getCrossReference(String parentCatalog,\n                                       String parentSchema,\n                                       String parentTable,\n                                       String foreignCatalog,\n                                       String foreignSchema,\n                                       String foreignTable) throws SQLException {\n        return metaData.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable);\n    }\n\n    @Override\n    public ResultSet getTypeInfo() throws SQLException {\n        return metaData.getTypeInfo();\n    }\n\n    @Override\n    public ResultSet getIndexInfo(String catalog,\n                                  String schema,\n                                  String table,\n                                  boolean unique,\n                                  boolean approximate) throws SQLException {\n        return metaData.getIndexInfo(catalog, schema, table, unique, approximate);\n    }\n\n    @Override\n    public boolean supportsResultSetType(int type) throws SQLException {\n        return metaData.supportsResultSetType(type);\n    }\n\n    @Override\n    public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {\n        return metaData.supportsResultSetConcurrency(type, concurrency);\n    }\n\n    @Override\n    public boolean ownUpdatesAreVisible(int type) throws SQLException {\n        return metaData.ownUpdatesAreVisible(type);\n    }\n\n    @Override\n    public boolean ownDeletesAreVisible(int type) throws SQLException {\n        return metaData.ownDeletesAreVisible(type);\n    }\n\n    @Override\n    public boolean ownInsertsAreVisible(int type) throws SQLException {\n        return metaData.ownInsertsAreVisible(type);\n    }\n\n    @Override\n    public boolean othersUpdatesAreVisible(int type) throws SQLException {\n        return metaData.othersUpdatesAreVisible(type);\n    }\n\n    @Override\n    public boolean othersDeletesAreVisible(int type) throws SQLException {\n        return metaData.othersDeletesAreVisible(type);\n    }\n\n    @Override\n    public boolean othersInsertsAreVisible(int type) throws SQLException {\n        return metaData.othersInsertsAreVisible(type);\n    }\n\n    @Override\n    public boolean updatesAreDetected(int type) throws SQLException {\n        return metaData.updatesAreDetected(type);\n    }\n\n    @Override\n    public boolean deletesAreDetected(int type) throws SQLException {\n        return metaData.deletesAreDetected(type);\n    }\n\n    @Override\n    public boolean insertsAreDetected(int type) throws SQLException {\n        return metaData.insertsAreDetected(type);\n    }\n\n    @Override\n    public boolean supportsBatchUpdates() throws SQLException {\n        return metaData.supportsBatchUpdates();\n    }\n\n    @Override\n    public ResultSet getUDTs(String catalog,\n                             String schemaPattern,\n                             String typeNamePattern,\n                             int[] types) throws SQLException {\n        return metaData.getUDTs(catalog, schemaPattern, typeNamePattern, types);\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        return metaData.getConnection();\n    }\n\n    @Override\n    public boolean supportsSavepoints() throws SQLException {\n        return metaData.supportsSavepoints();\n    }\n\n    @Override\n    public boolean supportsNamedParameters() throws SQLException {\n        return metaData.supportsNamedParameters();\n    }\n\n    @Override\n    public boolean supportsMultipleOpenResults() throws SQLException {\n        return metaData.supportsMultipleOpenResults();\n    }\n\n    @Override\n    public boolean supportsGetGeneratedKeys() throws SQLException {\n        return metaData.supportsGetGeneratedKeys();\n    }\n\n    @Override\n    public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {\n        return metaData.getSuperTypes(catalog, schemaPattern, typeNamePattern);\n    }\n\n    @Override\n    public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {\n        return metaData.getSuperTypes(catalog, schemaPattern, tableNamePattern);\n    }\n\n    @Override\n    public ResultSet getAttributes(String catalog,\n                                   String schemaPattern,\n                                   String typeNamePattern,\n                                   String attributeNamePattern) throws SQLException {\n        return metaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern);\n    }\n\n    @Override\n    public boolean supportsResultSetHoldability(int holdability) throws SQLException {\n        return metaData.supportsResultSetHoldability(holdability);\n    }\n\n    @Override\n    public int getResultSetHoldability() throws SQLException {\n        return metaData.getResultSetHoldability();\n    }\n\n    @Override\n    public int getDatabaseMajorVersion() throws SQLException {\n        return metaData.getDatabaseMajorVersion();\n    }\n\n    @Override\n    public int getDatabaseMinorVersion() throws SQLException {\n        return metaData.getDatabaseMinorVersion();\n    }\n\n    @Override\n    public int getJDBCMajorVersion() throws SQLException {\n        return metaData.getJDBCMajorVersion();\n    }\n\n    @Override\n    public int getJDBCMinorVersion() throws SQLException {\n        return metaData.getJDBCMinorVersion();\n    }\n\n    @Override\n    public int getSQLStateType() throws SQLException {\n        return metaData.getSQLStateType();\n    }\n\n    @Override\n    public boolean locatorsUpdateCopy() throws SQLException {\n        return metaData.locatorsUpdateCopy();\n    }\n\n    @Override\n    public boolean supportsStatementPooling() throws SQLException {\n        return metaData.supportsStatementPooling();\n    }\n\n    @Override\n    public RowIdLifetime getRowIdLifetime() throws SQLException {\n        return metaData.getRowIdLifetime();\n    }\n\n    @Override\n    public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {\n        return metaData.getSchemas(catalog, schemaPattern);\n    }\n\n    @Override\n    public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {\n        return metaData.supportsStoredFunctionsUsingCallSyntax();\n    }\n\n    @Override\n    public boolean autoCommitFailureClosesAllResultSets() throws SQLException {\n        return metaData.autoCommitFailureClosesAllResultSets();\n    }\n\n    @Override\n    public ResultSet getClientInfoProperties() throws SQLException {\n        return metaData.getClientInfoProperties();\n    }\n\n    @Override\n    public ResultSet getFunctions(String catalog,\n                                  String schemaPattern,\n                                  String functionNamePattern) throws SQLException {\n        return metaData.getFunctions(catalog, schemaPattern, functionNamePattern);\n    }\n\n    @Override\n    public ResultSet getFunctionColumns(String catalog,\n                                        String schemaPattern,\n                                        String functionNamePattern,\n                                        String columnNamePattern) throws SQLException {\n        return metaData.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern);\n    }\n\n    public ResultSet getPseudoColumns(String catalog,\n                                      String schemaPattern,\n                                      String tableNamePattern,\n                                      String columnNamePattern) throws SQLException {\n        return metaData.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n    }\n\n    public boolean generatedKeyAlwaysReturned() throws SQLException {\n        return metaData.generatedKeyAlwaysReturned();\n    }\n\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        return metaData.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return metaData.isWrapperFor(iface);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.util.Calendar;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface JdbcParameter {\n    public static final int BinaryInputStream = 10001;\n    public static final int AsciiInputStream = 10002;\n    public static final int CharacterInputStream = 10003;\n    public static final int NCharacterInputStream = 10004;\n    public static final int URL = 10005;\n\n    public static interface TYPE {\n        public static final int BinaryInputStream = 10001;\n        public static final int AsciiInputStream = 10002;\n        public static final int CharacterInputStream = 10003;\n        public static final int NCharacterInputStream = 10004;\n        public static final int URL = 10005;\n        public static final int UnicodeStream = 10006;\n        public static final int BYTES = 10007;\n\n    }\n\n    Object getValue();\n\n    long getLength();\n\n    Calendar getCalendar();\n\n    int getSqlType();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterDate.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Types;\nimport java.util.Calendar;\nimport java.util.Date;\n\npublic final class JdbcParameterDate implements JdbcParameter {\n    private final Date value;\n\n    public JdbcParameterDate(Date value) {\n        this.value = value;\n    }\n\n    @Override\n    public Object getValue() {\n        return value;\n    }\n\n    @Override\n    public long getLength() {\n        return 0;\n    }\n\n    @Override\n    public Calendar getCalendar() {\n        return null;\n    }\n\n    @Override\n    public int getSqlType() {\n        return Types.DATE;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterDecimal.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.math.BigDecimal;\nimport java.sql.Types;\nimport java.util.Calendar;\n\npublic final class JdbcParameterDecimal implements JdbcParameter {\n    private final BigDecimal value;\n\n    public static JdbcParameterDecimal NULL = new JdbcParameterDecimal(null);\n    public static JdbcParameterDecimal ZERO = new JdbcParameterDecimal(BigDecimal.ZERO);\n    public static JdbcParameterDecimal TEN = new JdbcParameterDecimal(BigDecimal.TEN);\n\n    private JdbcParameterDecimal(BigDecimal value) {\n        this.value = value;\n    }\n\n    public static JdbcParameterDecimal valueOf(BigDecimal x) {\n        if (x == null) {\n            return NULL;\n        }\n\n        if (0 == (x.compareTo(BigDecimal.ZERO))) {\n            return ZERO;\n        }\n\n        if (0 == (x.compareTo(BigDecimal.TEN))) {\n            return TEN;\n        }\n\n        return new JdbcParameterDecimal(x);\n    }\n\n    @Override\n    public Object getValue() {\n        return value;\n    }\n\n    @Override\n    public long getLength() {\n        return 0;\n    }\n\n    @Override\n    public Calendar getCalendar() {\n        return null;\n    }\n\n    @Override\n    public int getSqlType() {\n        return Types.DECIMAL;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.util.Calendar;\n\npublic final class JdbcParameterImpl implements JdbcParameter {\n    private final int sqlType;\n    private final Object value;\n    private final long length;\n    private final Calendar calendar;\n    private final int scaleOrLength;\n\n    public JdbcParameterImpl(int sqlType, Object value, long length, Calendar calendar, int scaleOrLength) {\n        this.sqlType = sqlType;\n        this.value = value;\n        this.length = length;\n        this.calendar = calendar;\n        this.scaleOrLength = scaleOrLength;\n    }\n\n    public JdbcParameterImpl(int sqlType, Object value, long length, Calendar calendar) {\n        this(sqlType, value, -1, null, -1);\n    }\n\n    public JdbcParameterImpl(int sqlType, Object value) {\n        this(sqlType, value, -1, null);\n    }\n\n    public JdbcParameterImpl(int sqlType, Object value, long length) {\n        this(sqlType, value, length, null);\n    }\n\n    public JdbcParameterImpl(int sqlType, Object value, Calendar calendar) {\n        this(sqlType, value, -1, calendar);\n    }\n\n    public int getScaleOrLength() {\n        return scaleOrLength;\n    }\n\n    public Object getValue() {\n        return value;\n    }\n\n    public long getLength() {\n        return length;\n    }\n\n    public Calendar getCalendar() {\n        return calendar;\n    }\n\n    public int getSqlType() {\n        return sqlType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterInt.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Types;\nimport java.util.Calendar;\n\npublic final class JdbcParameterInt implements JdbcParameter {\n    private static JdbcParameterInt[] cache;\n\n    static {\n        int cacheSize = 127;\n        cache = new JdbcParameterInt[cacheSize];\n        for (int i = 0; i < cache.length; ++i) {\n            cache[i] = new JdbcParameterInt(i);\n        }\n    }\n\n    private final int value;\n\n    private JdbcParameterInt(int value) {\n        this.value = value;\n    }\n\n    public static JdbcParameterInt valueOf(int value) {\n        if (value >= 0 && value < cache.length) {\n            return cache[value];\n        }\n\n        return new JdbcParameterInt(value);\n    }\n\n    @Override\n    public Object getValue() {\n        return value;\n    }\n\n    @Override\n    public long getLength() {\n        return 0;\n    }\n\n    @Override\n    public Calendar getCalendar() {\n        return null;\n    }\n\n    @Override\n    public int getSqlType() {\n        return Types.INTEGER;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterLong.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Types;\nimport java.util.Calendar;\n\npublic final class JdbcParameterLong implements JdbcParameter {\n    private static JdbcParameterLong[] cache;\n\n    static {\n        int cacheSize = 127;\n        cache = new JdbcParameterLong[cacheSize];\n        for (int i = 0; i < cache.length; ++i) {\n            cache[i] = new JdbcParameterLong(i);\n        }\n    }\n\n    private final long value;\n\n    private JdbcParameterLong(long value) {\n        this.value = value;\n    }\n\n    public static JdbcParameterLong valueOf(long value) {\n        if (value >= 0 && value < cache.length) {\n            return cache[(int) value];\n        }\n\n        return new JdbcParameterLong(value);\n    }\n\n    @Override\n    public Object getValue() {\n        return value;\n    }\n\n    @Override\n    public long getLength() {\n        return 0;\n    }\n\n    @Override\n    public Calendar getCalendar() {\n        return null;\n    }\n\n    @Override\n    public int getSqlType() {\n        return Types.BIGINT;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterNull.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Types;\nimport java.util.Calendar;\n\npublic final class JdbcParameterNull implements JdbcParameter {\n    private final int sqlType;\n\n    public static final JdbcParameterNull CHAR = new JdbcParameterNull(Types.CHAR);\n    public static final JdbcParameterNull VARCHAR = new JdbcParameterNull(Types.VARCHAR);\n    public static final JdbcParameterNull NVARCHAR = new JdbcParameterNull(Types.NVARCHAR);\n\n    public static final JdbcParameterNull BINARY = new JdbcParameterNull(Types.BINARY);\n    public static final JdbcParameterNull VARBINARY = new JdbcParameterNull(Types.VARBINARY);\n\n    public static final JdbcParameterNull TINYINT = new JdbcParameterNull(Types.TINYINT);\n    public static final JdbcParameterNull SMALLINT = new JdbcParameterNull(Types.SMALLINT);\n    public static final JdbcParameterNull INTEGER = new JdbcParameterNull(Types.INTEGER);\n    public static final JdbcParameterNull BIGINT = new JdbcParameterNull(Types.BIGINT);\n\n    public static final JdbcParameterNull DECIMAL = new JdbcParameterNull(Types.DECIMAL);\n    public static final JdbcParameterNull NUMERIC = new JdbcParameterNull(Types.NUMERIC);\n    public static final JdbcParameterNull FLOAT = new JdbcParameterNull(Types.FLOAT);\n    public static final JdbcParameterNull DOUBLE = new JdbcParameterNull(Types.DOUBLE);\n\n    public static final JdbcParameterNull NULL = new JdbcParameterNull(Types.NULL);\n\n    public static final JdbcParameterNull DATE = new JdbcParameterNull(Types.DATE);\n    public static final JdbcParameterNull TIME = new JdbcParameterNull(Types.TIME);\n    public static final JdbcParameterNull TIMESTAMP = new JdbcParameterNull(Types.TIMESTAMP);\n\n    private JdbcParameterNull(int sqlType) {\n        this.sqlType = sqlType;\n    }\n\n    @Override\n    public Object getValue() {\n        return null;\n    }\n\n    @Override\n    public long getLength() {\n        return 0;\n    }\n\n    @Override\n    public Calendar getCalendar() {\n        return null;\n    }\n\n    @Override\n    public int getSqlType() {\n        return sqlType;\n    }\n\n    public static JdbcParameterNull valueOf(int sqlType) {\n        switch (sqlType) {\n            case Types.TINYINT:\n                return INTEGER;\n            case Types.SMALLINT:\n                return SMALLINT;\n            case Types.INTEGER:\n                return INTEGER;\n            case Types.BIGINT:\n                return BIGINT;\n\n            case Types.DECIMAL:\n                return DECIMAL;\n            case Types.NUMERIC:\n                return NUMERIC;\n            case Types.FLOAT:\n                return FLOAT;\n            case Types.DOUBLE:\n                return DOUBLE;\n\n            case Types.CHAR:\n                return CHAR;\n            case Types.VARCHAR:\n                return VARCHAR;\n            case Types.NVARCHAR:\n                return NVARCHAR;\n\n            case Types.BINARY:\n                return BINARY;\n            case Types.VARBINARY:\n                return VARBINARY;\n\n            case Types.TIME:\n                return TIME;\n            case Types.DATE:\n                return DATE;\n            case Types.TIMESTAMP:\n                return TIMESTAMP;\n\n            case Types.NULL:\n                return NULL;\n\n            default:\n                return new JdbcParameterNull(sqlType);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterString.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Types;\nimport java.util.Calendar;\n\npublic final class JdbcParameterString implements JdbcParameter {\n    private final String value;\n\n    public static final JdbcParameterString empty = new JdbcParameterString(\"\");\n\n    public JdbcParameterString(String value) {\n        this.value = value;\n    }\n\n    @Override\n    public Object getValue() {\n        return value;\n    }\n\n    @Override\n    public long getLength() {\n        return 0;\n    }\n\n    @Override\n    public Calendar getCalendar() {\n        return null;\n    }\n\n    @Override\n    public int getSqlType() {\n        return Types.VARCHAR;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/JdbcParameterTimestamp.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Timestamp;\nimport java.sql.Types;\nimport java.util.Calendar;\n\npublic final class JdbcParameterTimestamp implements JdbcParameter {\n    private final Timestamp value;\n\n    public JdbcParameterTimestamp(Timestamp value) {\n        this.value = value;\n    }\n\n    @Override\n    public Object getValue() {\n        return value;\n    }\n\n    @Override\n    public long getLength() {\n        return 0;\n    }\n\n    @Override\n    public Calendar getCalendar() {\n        return null;\n    }\n\n    @Override\n    public int getSqlType() {\n        return Types.TIMESTAMP;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/NClobProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.NClob;\n\npublic interface NClobProxy extends ClobProxy, NClob {\n    NClob getRawNClob();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/NClobProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.NClob;\n\npublic class NClobProxyImpl extends ClobProxyImpl implements NClobProxy {\n    private final NClob nclob;\n\n    public NClobProxyImpl(DataSourceProxy dataSource, ConnectionProxy connection, NClob clob) {\n        super(dataSource, connection, clob);\n        this.nclob = clob;\n    }\n\n    @Override\n    public NClob getRawNClob() {\n        return nclob;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.PreparedStatement;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface PreparedStatementProxy extends PreparedStatement, StatementProxy {\n    String getSql();\n\n    PreparedStatement getRawObject();\n\n    Map<Integer, JdbcParameter> getParameters();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.proxy.jdbc.JdbcParameter.TYPE;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class PreparedStatementProxyImpl extends StatementProxyImpl implements PreparedStatementProxy {\n    private PreparedStatement statement;\n    protected final String sql;\n    private JdbcParameter[] parameters;\n    private int parametersSize;\n    private Map<Integer, JdbcParameter> paramMap;\n\n    public PreparedStatementProxyImpl(ConnectionProxy connection, PreparedStatement statement, String sql, long id) {\n        super(connection, statement, id);\n        this.statement = statement;\n        this.sql = sql;\n\n        char quote = 0;\n        int paramCount = 0;\n        for (int i = 0; i < sql.length(); ++i) {\n            char ch = sql.charAt(i);\n\n            if (ch == '\\'') {\n                if (quote == 0) {\n                    quote = ch;\n                } else if (quote == '\\'') {\n                    quote = 0;\n                }\n            } else if (ch == '\"') {\n                if (quote == 0) {\n                    quote = ch;\n                } else if (quote == '\"') {\n                    quote = 0;\n                }\n            }\n\n            if (quote == 0 && ch == '?') {\n                paramCount++;\n            }\n        }\n\n        parameters = new JdbcParameter[paramCount];\n    }\n\n    public Map<Integer, JdbcParameter> getParameters() {\n        if (paramMap == null) {\n            paramMap = new HashMap<Integer, JdbcParameter>(parametersSize);\n            for (int i = 0; i < parametersSize; ++i) {\n                paramMap.put(i, parameters[i]);\n            }\n        }\n\n        return paramMap;\n    }\n\n    protected void setStatement(PreparedStatement statement) {\n        super.statement = statement;\n        this.statement = statement;\n    }\n\n    public void setParameter(int jdbcIndex, JdbcParameter parameter) {\n        int index = jdbcIndex - 1;\n\n        if (jdbcIndex > parametersSize) {\n            parametersSize = jdbcIndex;\n        }\n        if (parametersSize >= parameters.length) {\n            int oldCapacity = parameters.length;\n            int newCapacity = oldCapacity + (oldCapacity >> 1);\n            if (newCapacity <= 4) {\n                newCapacity = 4;\n            }\n\n            parameters = Arrays.copyOf(parameters, newCapacity);\n        }\n        parameters[index] = parameter;\n\n        if (paramMap != null) {\n            paramMap = null;\n        }\n    }\n\n    public int getParametersSize() {\n        return parametersSize;\n    }\n\n    public JdbcParameter getParameter(int i) {\n        if (i > parametersSize) {\n            return null;\n        }\n        return this.parameters[i];\n    }\n\n    public String getSql() {\n        return this.sql;\n    }\n\n    public PreparedStatement getRawObject() {\n        return this.statement;\n    }\n\n    @Override\n    public void addBatch() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_addBatch(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void clearParameters() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_clearParameters(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public String getBatchSql() {\n        return this.sql;\n    }\n\n    @Override\n    public boolean execute() throws SQLException {\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.Execute;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        firstResultSet = chain.preparedStatement_execute(this);\n        recycleFilterChain(chain);\n        return firstResultSet;\n    }\n\n    @Override\n    public ResultSet executeQuery() throws SQLException {\n        firstResultSet = true;\n\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.ExecuteQuery;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        try {\n            return chain.preparedStatement_executeQuery(this);\n        } finally {\n            recycleFilterChain(chain);\n        }\n    }\n\n    @Override\n    public int executeUpdate() throws SQLException {\n        firstResultSet = false;\n\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.ExecuteUpdate;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        updateCount = chain.preparedStatement_executeUpdate(this);\n        recycleFilterChain(chain);\n        return updateCount;\n    }\n\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException {\n        FilterChainImpl chain = createChain();\n        try {\n            return chain.preparedStatement_getMetaData(this);\n        } finally {\n            recycleFilterChain(chain);\n        }\n    }\n\n    @Override\n    public ParameterMetaData getParameterMetaData() throws SQLException {\n        FilterChainImpl chain = createChain();\n        try {\n            return chain.preparedStatement_getParameterMetaData(this);\n        } finally {\n            recycleFilterChain(chain);\n        }\n    }\n\n    @Override\n    public void setArray(int parameterIndex, Array x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.ARRAY, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setArray(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {\n        setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.AsciiInputStream, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setAsciiStream(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.AsciiInputStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setAsciiStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {\n        setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.AsciiInputStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setAsciiStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {\n        setParameter(parameterIndex, createParameter(x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBigDecimal(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {\n        setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.BinaryInputStream, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBinaryStream(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.BinaryInputStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBinaryStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {\n        setParameter(parameterIndex, createParameter(JdbcParameter.TYPE.BinaryInputStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBinaryStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, Blob x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.BLOB, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBlob(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, InputStream x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.BLOB, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBlob(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, InputStream x, long length) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.BLOB, x, length));\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBlob(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBoolean(int parameterIndex, boolean x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.BOOLEAN, x));\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBoolean(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setByte(int parameterIndex, byte x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.TINYINT, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setByte(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setBytes(int parameterIndex, byte[] x) throws SQLException {\n        setParameter(parameterIndex, createParameter(TYPE.BYTES, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setBytes(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader x) throws SQLException {\n        setParameter(parameterIndex, createParameter(TYPE.CharacterInputStream, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setCharacterStream(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader x, int length) throws SQLException {\n        setParameter(parameterIndex, createParameter(TYPE.CharacterInputStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setCharacterStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader x, long length) throws SQLException {\n        setParameter(parameterIndex, createParameter(TYPE.CharacterInputStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setCharacterStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Clob x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.CLOB, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setClob(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Reader x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.CLOB, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setClob(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Reader x, long length) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.CLOB, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setClob(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setDate(int parameterIndex, Date x) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParameter(x)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setDate(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParameter(Types.DATE, x, cal)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setDate(this, parameterIndex, x, cal);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setDouble(int parameterIndex, double x) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParameter(Types.DOUBLE, x)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setDouble(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setFloat(int parameterIndex, float x) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParameter(Types.FLOAT, x)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setFloat(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setInt(int parameterIndex, int x) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParemeter(x)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setInt(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setLong(int parameterIndex, long x) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParameter(x)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setLong(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader x) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParameter(TYPE.NCharacterInputStream, x)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNCharacterStream(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader x, long length) throws SQLException {\n        setParameter(parameterIndex, createParameter(TYPE.NCharacterInputStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNCharacterStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, NClob x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.NCLOB, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNClob(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, Reader x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.NCLOB, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNClob(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, Reader x, long length) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.NCLOB, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNClob(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNString(int parameterIndex, String x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.NVARCHAR, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNString(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNull(int parameterIndex, int sqlType) throws SQLException {\n        setParameter(parameterIndex, createParameterNull(sqlType));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNull(this, parameterIndex, sqlType);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {\n        setParameter(parameterIndex, createParameterNull(sqlType));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setNull(this, parameterIndex, sqlType, typeName);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x) throws SQLException {\n        setObjectParameter(parameterIndex, x);\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setObject(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    private void setObjectParameter(int parameterIndex, Object x) {\n        if (x == null) {\n            setParameter(parameterIndex, createParameterNull(Types.OTHER));\n            return;\n        }\n\n        Class<?> clazz = x.getClass();\n        if (clazz == Byte.class) {\n            setParameter(parameterIndex, createParameter(Types.TINYINT, x));\n            return;\n        }\n\n        if (clazz == Short.class) {\n            setParameter(parameterIndex, createParameter(Types.SMALLINT, x));\n            return;\n        }\n\n        if (clazz == Integer.class) {\n            setParameter(parameterIndex, createParemeter((Integer) x));\n            return;\n        }\n\n        if (clazz == Long.class) {\n            setParameter(parameterIndex, createParameter((Long) x));\n            return;\n        }\n\n        if (clazz == String.class) {\n            setParameter(parameterIndex, createParameter((String) x));\n            return;\n        }\n\n        if (clazz == BigDecimal.class) {\n            setParameter(parameterIndex, createParameter((BigDecimal) x));\n            return;\n        }\n\n        if (clazz == Float.class) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.FLOAT, x));\n            return;\n        }\n\n        if (clazz == Double.class) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.DOUBLE, x));\n            return;\n        }\n\n        if (clazz == java.sql.Date.class || clazz == java.util.Date.class) {\n            setParameter(parameterIndex, createParameter((java.util.Date) x));\n            return;\n        }\n\n        if (clazz == java.sql.Timestamp.class) {\n            setParameter(parameterIndex, createParameter((java.sql.Timestamp) x));\n            return;\n        }\n\n        if (clazz == java.sql.Time.class) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.TIME, x));\n            return;\n        }\n\n        if (clazz == Boolean.class) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.BOOLEAN, x));\n            return;\n        }\n\n        if (clazz == byte[].class) {\n            setParameter(parameterIndex, new JdbcParameterImpl(TYPE.BYTES, x));\n            return;\n        }\n\n        if (x instanceof InputStream) {\n            setParameter(parameterIndex, new JdbcParameterImpl(JdbcParameter.TYPE.BinaryInputStream, x));\n            return;\n        }\n\n        if (x instanceof Reader) {\n            setParameter(parameterIndex, new JdbcParameterImpl(JdbcParameter.TYPE.CharacterInputStream, x));\n            return;\n        }\n\n        if (x instanceof NClob) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.NCLOB, x));\n            return;\n        }\n\n        if (x instanceof Clob) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.CLOB, x));\n            return;\n        }\n\n        if (x instanceof Blob) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.BLOB, x));\n            return;\n        }\n\n        String className = x.getClass().getName();\n\n        if (className.equals(\"java.time.LocalTime\")) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.TIME, x));\n            return;\n        }\n\n        if (className.equals(\"java.time.LocalDate\")) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.DATE, x));\n            return;\n        }\n\n        if (className.equals(\"java.time.LocalDateTime\")) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.TIMESTAMP, x));\n            return;\n        }\n\n        if (className.equals(\"java.time.ZonedDateTime\")) {\n            setParameter(parameterIndex, new JdbcParameterImpl(Types.TIMESTAMP, x));\n            return;\n        }\n\n        setParameter(parameterIndex, createParameter(Types.OTHER, null));\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {\n        setParameter(parameterIndex, createParameter(targetSqlType, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setObject(this, parameterIndex, x, targetSqlType);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {\n        setParameter(parameterIndex, createParameter(x, targetSqlType, scaleOrLength));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setObject(this, parameterIndex, x, targetSqlType, scaleOrLength);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setRef(int parameterIndex, Ref x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.REF, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setRef(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setRowId(int parameterIndex, RowId x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.ROWID, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setRowId(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setSQLXML(int parameterIndex, SQLXML x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.SQLXML, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setSQLXML(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setShort(int parameterIndex, short x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.SMALLINT, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setShort(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setString(int parameterIndex, String x) throws SQLException {\n        setParameter(\n                parameterIndex,\n                createParameter(x)\n        );\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setString(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTime(int parameterIndex, Time x) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.TIME, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setTime(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.TIME, x, cal));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setTime(this, parameterIndex, x, cal);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {\n        setParameter(parameterIndex, createParameter(x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setTimestamp(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {\n        setParameter(parameterIndex, createParameter(Types.TIMESTAMP, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setTimestamp(this, parameterIndex, x, cal);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setURL(int parameterIndex, URL x) throws SQLException {\n        setParameter(parameterIndex, createParameter(TYPE.URL, x));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setURL(this, parameterIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        setParameter(parameterIndex, createParameter(TYPE.UnicodeStream, x, length));\n\n        FilterChainImpl chain = createChain();\n        chain.preparedStatement_setUnicodeStream(this, parameterIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public String getLastExecuteSql() {\n        return this.sql;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == PreparedStatementProxy.class) {\n            return (T) this;\n        }\n\n        return super.unwrap(iface);\n    }\n\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == PreparedStatementProxy.class) {\n            return true;\n        }\n\n        return super.isWrapperFor(iface);\n    }\n\n    private JdbcParameter createParemeter(int x) {\n        return JdbcParameterInt.valueOf(x);\n    }\n\n    private JdbcParameter createParameter(long x) {\n        return JdbcParameterLong.valueOf(x);\n    }\n\n    private JdbcParameter createParameterNull(int sqlType) {\n        return JdbcParameterNull.valueOf(sqlType);\n\n    }\n\n    private JdbcParameter createParameter(java.util.Date x) {\n        if (x == null) {\n            return JdbcParameterNull.DATE;\n        }\n\n        return new JdbcParameterDate(x);\n    }\n\n    private JdbcParameter createParameter(BigDecimal x) {\n        if (x == null) {\n            return JdbcParameterNull.DECIMAL;\n        }\n\n        return JdbcParameterDecimal.valueOf(x);\n    }\n\n    private JdbcParameter createParameter(String x) {\n        if (x == null) {\n            return JdbcParameterNull.VARCHAR;\n        }\n\n        if (x.length() == 0) {\n            return JdbcParameterString.empty;\n        }\n\n        return new JdbcParameterString(x);\n    }\n\n    private JdbcParameter createParameter(Timestamp x) {\n        if (x == null) {\n            return JdbcParameterNull.TIMESTAMP;\n        }\n\n        return new JdbcParameterTimestamp(x);\n    }\n\n    private JdbcParameter createParameter(Object x, int sqlType, int scaleOrLength) {\n        if (x == null) {\n            return JdbcParameterNull.valueOf(sqlType);\n        }\n\n        return new JdbcParameterImpl(sqlType, x, -1, null, scaleOrLength);\n    }\n\n    private JdbcParameter createParameter(int sqlType, Object value, long length) {\n        if (value == null) {\n            return JdbcParameterNull.valueOf(sqlType);\n        }\n\n        return new JdbcParameterImpl(sqlType, value, length);\n    }\n\n    private JdbcParameter createParameter(int sqlType, Object value) {\n        if (value == null) {\n            return JdbcParameterNull.valueOf(sqlType);\n        }\n\n        return new JdbcParameterImpl(sqlType, value);\n    }\n\n    public JdbcParameter createParameter(int sqlType, Object value, Calendar calendar) {\n        if (value == null) {\n            return JdbcParameterNull.valueOf(sqlType);\n        }\n\n        return new JdbcParameterImpl(sqlType, value, calendar);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetMetaDataProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.ResultSetMetaData;\n\n/**\n * @author kiki\n */\npublic interface ResultSetMetaDataProxy extends ResultSetMetaData, WrapperProxy {\n    ResultSetMetaData getResultSetMetaDataRaw();\n\n    ResultSetProxy getResultSetProxy();\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetMetaDataProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\n\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\n\n/**\n * @author kiki\n */\npublic class ResultSetMetaDataProxyImpl extends WrapperProxyImpl implements ResultSetMetaDataProxy {\n    private final ResultSetMetaData metaData;\n    private final ResultSetProxy resultSet;\n\n    private FilterChainImpl filterChain;\n\n    public ResultSetMetaDataProxyImpl(ResultSetMetaData metaData, long id, ResultSetProxy resultSet) {\n        super(metaData, id);\n        this.metaData = metaData;\n        this.resultSet = resultSet;\n    }\n\n    @Override\n    public int getColumnCount() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSetMetaData_getColumnCount(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isAutoIncrement(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isAutoIncrement(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isCaseSensitive(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isCaseSensitive(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isSearchable(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isSearchable(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isCurrency(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isCurrency(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int isNullable(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSetMetaData_isNullable(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isSigned(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isSigned(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getColumnDisplaySize(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSetMetaData_getColumnDisplaySize(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getColumnLabel(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSetMetaData_getColumnLabel(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getColumnName(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSetMetaData_getColumnName(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getSchemaName(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSetMetaData_getSchemaName(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getPrecision(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSetMetaData_getPrecision(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getScale(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSetMetaData_getScale(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getTableName(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSetMetaData_getTableName(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getCatalogName(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSetMetaData_getCatalogName(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getColumnType(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSetMetaData_getColumnType(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getColumnTypeName(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSetMetaData_getColumnTypeName(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isReadOnly(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isReadOnly(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isWritable(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isWritable(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isDefinitelyWritable(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSetMetaData_isDefinitelyWritable(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getColumnClassName(int column) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSetMetaData_getColumnClassName(this, column);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    public FilterChainImpl createChain() {\n        FilterChainImpl chain = this.filterChain;\n        if (chain == null) {\n            chain = new FilterChainImpl(this.resultSet.getStatementProxy().getConnectionProxy().getDirectDataSource());\n        } else {\n            this.filterChain = null;\n        }\n\n        return chain;\n    }\n\n    public void recycleFilterChain(FilterChainImpl chain) {\n        chain.reset();\n        this.filterChain = chain;\n    }\n\n    @Override\n    public ResultSetProxy getResultSetProxy() {\n        return this.resultSet;\n    }\n\n    @Override\n    public ResultSetMetaData getResultSetMetaDataRaw() {\n        return this.metaData;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.stat.JdbcSqlStat;\n\nimport java.sql.ResultSet;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface ResultSetProxy extends ResultSet, WrapperProxy {\n    ResultSet getResultSetRaw();\n\n    StatementProxy getStatementProxy();\n\n    String getSql();\n\n    JdbcSqlStat getSqlStat();\n\n    int getCursorIndex();\n\n    int getFetchRowCount();\n\n    long getConstructNano();\n\n    void setConstructNano(long constructNano);\n\n    void setConstructNano();\n\n    int getCloseCount();\n\n    void addReadStringLength(int length);\n\n    long getReadStringLength();\n\n    void addReadBytesLength(int length);\n\n    long getReadBytesLength();\n\n    void incrementOpenInputStreamCount();\n\n    int getOpenInputStreamCount();\n\n    void incrementOpenReaderCount();\n\n    int getOpenReaderCount();\n\n    int getPhysicalColumn(int logicColumn);\n\n    int getLogicColumn(int physicalColumn);\n\n    List<Integer> getHiddenColumns();\n\n    int getHiddenColumnCount();\n\n    void setLogicColumnMap(Map<Integer, Integer> logicColumnMap);\n\n    void setPhysicalColumnMap(Map<Integer, Integer> physicalColumnMap);\n\n    void setHiddenColumns(List<Integer> hiddenColumns);\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.stat.JdbcSqlStat;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class ResultSetProxyImpl extends WrapperProxyImpl implements ResultSetProxy {\n    private final ResultSet resultSet;\n    private final StatementProxy statement;\n    private final String sql;\n\n    protected int cursorIndex;\n    protected int fetchRowCount;\n    protected long constructNano;\n    protected final JdbcSqlStat sqlStat;\n    private int closeCount;\n\n    private long readStringLength;\n    private long readBytesLength;\n\n    private int openInputStreamCount;\n    private int openReaderCount;\n\n    private Map<Integer, Integer> logicColumnMap;\n    private Map<Integer, Integer> physicalColumnMap;\n    private List<Integer> hiddenColumns;\n\n    private FilterChainImpl filterChain;\n\n    public ResultSetProxyImpl(StatementProxy statement, ResultSet resultSet, long id, String sql) {\n        super(resultSet, id);\n        this.statement = statement;\n        this.resultSet = resultSet;\n        this.sql = sql;\n        sqlStat = this.statement.getSqlStat();\n    }\n\n    public long getConstructNano() {\n        return constructNano;\n    }\n\n    public void setConstructNano(long constructNano) {\n        this.constructNano = constructNano;\n    }\n\n    public void setConstructNano() {\n        if (this.constructNano <= 0) {\n            this.constructNano = System.nanoTime();\n        }\n    }\n\n    public int getCursorIndex() {\n        return cursorIndex;\n    }\n\n    public int getFetchRowCount() {\n        return fetchRowCount;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public JdbcSqlStat getSqlStat() {\n        return sqlStat;\n    }\n\n    public ResultSet getResultSetRaw() {\n        return resultSet;\n    }\n\n    public StatementProxy getStatementProxy() {\n        return this.statement;\n    }\n\n    public FilterChainImpl createChain() {\n        FilterChainImpl chain = this.filterChain;\n        if (chain == null) {\n            chain = new FilterChainImpl(this.statement.getConnectionProxy().getDirectDataSource());\n        } else {\n            this.filterChain = null;\n        }\n\n        return chain;\n    }\n\n    public void recycleFilterChain(FilterChainImpl chain) {\n        chain.reset();\n        this.filterChain = chain;\n    }\n\n    @Override\n    public boolean absolute(int row) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_absolute(this, row);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public void afterLast() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_afterLast(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void beforeFirst() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_beforeFirst(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void cancelRowUpdates() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_cancelRowUpdates(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_clearWarnings(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void close() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_close(this);\n        closeCount++;\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void deleteRow() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_deleteRow(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public int findColumn(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_findColumn(this, columnLabel);\n        recycleFilterChain(chain);\n\n        return value;\n    }\n\n    @Override\n    public boolean first() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_first(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Array getArray(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Array value = chain.resultSet_getArray(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Array getArray(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Array value = chain.resultSet_getArray(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public InputStream getAsciiStream(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        InputStream value = chain.resultSet_getAsciiStream(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public InputStream getAsciiStream(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        InputStream value = chain.resultSet_getAsciiStream(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        BigDecimal value = chain.resultSet_getBigDecimal(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        BigDecimal value = chain.resultSet_getBigDecimal(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {\n        FilterChainImpl chain = createChain();\n        BigDecimal value = chain.resultSet_getBigDecimal(this, columnIndex, scale);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {\n        FilterChainImpl chain = createChain();\n        BigDecimal value = chain.resultSet_getBigDecimal(this, columnLabel, scale);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public InputStream getBinaryStream(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        InputStream value = chain.resultSet_getBinaryStream(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public InputStream getBinaryStream(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        InputStream value = chain.resultSet_getBinaryStream(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Blob getBlob(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Blob value = chain.resultSet_getBlob(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Blob getBlob(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Blob value = chain.resultSet_getBlob(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean getBoolean(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_getBoolean(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean getBoolean(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_getBoolean(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public byte getByte(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte value = chain.resultSet_getByte(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public byte getByte(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte value = chain.resultSet_getByte(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public byte[] getBytes(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte[] value = chain.resultSet_getBytes(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public byte[] getBytes(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        byte[] value = chain.resultSet_getBytes(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Reader getCharacterStream(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader value = chain.resultSet_getCharacterStream(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Reader getCharacterStream(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader value = chain.resultSet_getCharacterStream(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Clob getClob(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Clob value = chain.resultSet_getClob(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Clob getClob(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Clob value = chain.resultSet_getClob(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getConcurrency() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getConcurrency(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getCursorName() throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSet_getCursorName(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Date getDate(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date value = chain.resultSet_getDate(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Date getDate(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date value = chain.resultSet_getDate(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Date getDate(int columnIndex, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date value = chain.resultSet_getDate(this, columnIndex, cal);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Date getDate(String columnLabel, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Date value = chain.resultSet_getDate(this, columnLabel, cal);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public double getDouble(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        double value = chain.resultSet_getDouble(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public double getDouble(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        double value = chain.resultSet_getDouble(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getFetchDirection() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getFetchDirection(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getFetchSize() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getFetchSize(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public float getFloat(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        float value = chain.resultSet_getFloat(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public float getFloat(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        float value = chain.resultSet_getFloat(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getHoldability() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getHoldability(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getInt(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getInt(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getInt(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getInt(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public long getLong(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        long value = chain.resultSet_getLong(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public long getLong(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        long value = chain.resultSet_getLong(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException {\n        FilterChainImpl chain = createChain();\n        ResultSetMetaData value = chain.resultSet_getMetaData(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Reader getNCharacterStream(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader value = chain.resultSet_getNCharacterStream(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Reader getNCharacterStream(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Reader value = chain.resultSet_getNCharacterStream(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public NClob getNClob(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        NClob value = chain.resultSet_getNClob(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public NClob getNClob(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        NClob value = chain.resultSet_getNClob(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getNString(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSet_getNString(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getNString(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSet_getNString(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Object getObject(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.resultSet_getObject(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Object getObject(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.resultSet_getObject(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.resultSet_getObject(this, columnIndex, map);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Object value = chain.resultSet_getObject(this, columnLabel, map);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Ref getRef(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Ref value = chain.resultSet_getRef(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Ref getRef(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Ref value = chain.resultSet_getRef(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getRow() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getRow(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public RowId getRowId(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        RowId value = chain.resultSet_getRowId(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public RowId getRowId(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        RowId value = chain.resultSet_getRowId(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public SQLXML getSQLXML(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLXML value = chain.resultSet_getSQLXML(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public SQLXML getSQLXML(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLXML value = chain.resultSet_getSQLXML(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public short getShort(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        short value = chain.resultSet_getShort(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public short getShort(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        short value = chain.resultSet_getShort(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Statement getStatement() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Statement stmt = chain.resultSet_getStatement(this);\n        recycleFilterChain(chain);\n        return stmt;\n    }\n\n    @Override\n    public String getString(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSet_getString(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public String getString(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        String value = chain.resultSet_getString(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Time getTime(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time value = chain.resultSet_getTime(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Time getTime(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time value = chain.resultSet_getTime(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Time getTime(int columnIndex, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time value = chain.resultSet_getTime(this, columnIndex, cal);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Time getTime(String columnLabel, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Time value = chain.resultSet_getTime(this, columnLabel, cal);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Timestamp getTimestamp(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp value = chain.resultSet_getTimestamp(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Timestamp getTimestamp(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp value = chain.resultSet_getTimestamp(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp value = chain.resultSet_getTimestamp(this, columnIndex, cal);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {\n        FilterChainImpl chain = createChain();\n        Timestamp value = chain.resultSet_getTimestamp(this, columnLabel, cal);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getType() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.resultSet_getType(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public URL getURL(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        URL value = chain.resultSet_getURL(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public URL getURL(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        URL value = chain.resultSet_getURL(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public InputStream getUnicodeStream(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        InputStream value = chain.resultSet_getUnicodeStream(this, columnIndex);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public InputStream getUnicodeStream(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        InputStream value = chain.resultSet_getUnicodeStream(this, columnLabel);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLWarning value = chain.resultSet_getWarnings(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public void insertRow() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_insertRow(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public boolean isAfterLast() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_isAfterLast(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isBeforeFirst() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_isBeforeFirst(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_isClosed(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isFirst() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_isFirst(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isLast() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_isLast(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean last() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_last(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public void moveToCurrentRow() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_moveToCurrentRow(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void moveToInsertRow() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_moveToInsertRow(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public boolean next() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean moreRows = chain.resultSet_next(this);\n\n        if (moreRows) {\n            cursorIndex++;\n            if (cursorIndex > fetchRowCount) {\n                fetchRowCount = cursorIndex;\n            }\n        }\n\n        recycleFilterChain(chain);\n        return moreRows;\n    }\n\n    @Override\n    public boolean previous() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean moreRows = chain.resultSet_previous(this);\n\n        if (moreRows) {\n            cursorIndex--;\n        }\n\n        recycleFilterChain(chain);\n        return moreRows;\n    }\n\n    @Override\n    public void refreshRow() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_refreshRow(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public boolean relative(int rows) throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_relative(this, rows);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean rowDeleted() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_rowDeleted(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean rowInserted() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_rowInserted(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean rowUpdated() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.resultSet_rowUpdated(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public void setFetchDirection(int direction) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_setFetchDirection(this, direction);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setFetchSize(int rows) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_setFetchSize(this, rows);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateArray(int columnIndex, Array x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateArray(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateArray(String columnLabel, Array x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateArray(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateAsciiStream(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateAsciiStream(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateAsciiStream(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateAsciiStream(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateAsciiStream(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateAsciiStream(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBigDecimal(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBigDecimal(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBinaryStream(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBinaryStream(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBinaryStream(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBinaryStream(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBinaryStream(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBinaryStream(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, Blob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBlob(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, Blob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBlob(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBlob(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, InputStream x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBlob(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBlob(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, InputStream x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBlob(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBoolean(int columnIndex, boolean x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBoolean(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBoolean(String columnLabel, boolean x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBoolean(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateByte(int columnIndex, byte x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateByte(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateByte(String columnLabel, byte x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateByte(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBytes(int columnIndex, byte[] x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBytes(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateBytes(String columnLabel, byte[] x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateBytes(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateCharacterStream(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateCharacterStream(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateCharacterStream(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader x, int length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateCharacterStream(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateCharacterStream(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateCharacterStream(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Clob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateClob(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Clob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateClob(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateClob(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateClob(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateClob(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateClob(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateDate(int columnIndex, Date x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateDate(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateDate(String columnLabel, Date x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateDate(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateDouble(int columnIndex, double x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateDouble(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateDouble(String columnLabel, double x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateDouble(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateFloat(int columnIndex, float x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateFloat(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateFloat(String columnLabel, float x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateFloat(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateInt(int columnIndex, int x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateInt(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateInt(String columnLabel, int x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateInt(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateLong(int columnIndex, long x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateLong(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateLong(String columnLabel, long x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateLong(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNCharacterStream(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNCharacterStream(String columnLabel, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNCharacterStream(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNCharacterStream(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNCharacterStream(String columnLabel, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNCharacterStream(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, NClob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNClob(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, NClob x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNClob(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNClob(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, Reader x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNClob(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNClob(this, columnIndex, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, Reader x, long length) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNClob(this, columnLabel, x, length);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNString(int columnIndex, String x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNString(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNString(String columnLabel, String x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNString(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNull(int columnIndex) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNull(this, columnIndex);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateNull(String columnLabel) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateNull(this, columnLabel);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateObject(int columnIndex, Object x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateObject(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateObject(String columnLabel, Object x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateObject(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateObject(this, columnIndex, x, scaleOrLength);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateObject(this, columnLabel, x, scaleOrLength);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateRef(int columnIndex, Ref x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateRef(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateRef(String columnLabel, Ref x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateRef(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateRow() throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateRow(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateRowId(int columnIndex, RowId x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateRowId(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateRowId(String columnLabel, RowId x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateRowId(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateSQLXML(int columnIndex, SQLXML x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateSQLXML(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateSQLXML(String columnLabel, SQLXML x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateSQLXML(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateShort(int columnIndex, short x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateShort(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateShort(String columnLabel, short x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateShort(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateString(int columnIndex, String x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateString(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateString(String columnLabel, String x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateString(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateTime(int columnIndex, Time x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateTime(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateTime(String columnLabel, Time x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateTime(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateTimestamp(this, columnIndex, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.resultSet_updateTimestamp(this, columnLabel, x);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public boolean wasNull() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean result = chain.resultSet_wasNull(this);\n\n        recycleFilterChain(chain);\n        return result;\n    }\n\n    @Override\n    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {\n        FilterChainImpl chain = createChain();\n        T value = chain.resultSet_getObject(this, columnIndex, type);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {\n        FilterChainImpl chain = createChain();\n        T value = chain.resultSet_getObject(this, columnLabel, type);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    public int getCloseCount() {\n        return closeCount;\n    }\n\n    @Override\n    public void addReadStringLength(int length) {\n        this.readStringLength += length;\n    }\n\n    @Override\n    public long getReadStringLength() {\n        return readStringLength;\n    }\n\n    @Override\n    public void addReadBytesLength(int length) {\n        this.readBytesLength += length;\n    }\n\n    @Override\n    public long getReadBytesLength() {\n        return readBytesLength;\n    }\n\n    @Override\n    public void incrementOpenInputStreamCount() {\n        openInputStreamCount++;\n    }\n\n    @Override\n    public int getOpenInputStreamCount() {\n        return openInputStreamCount;\n    }\n\n    @Override\n    public void incrementOpenReaderCount() {\n        openReaderCount++;\n    }\n\n    @Override\n    public int getOpenReaderCount() {\n        return openReaderCount;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == ResultSetProxy.class || iface == ResultSetProxyImpl.class) {\n            return (T) this;\n        }\n\n        return super.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == ResultSetProxy.class || iface == ResultSetProxyImpl.class) {\n            return true;\n        }\n\n        return super.isWrapperFor(iface);\n    }\n\n    @Override\n    public int getPhysicalColumn(int logicColumn) {\n        if (logicColumnMap == null) {\n            return logicColumn;\n        }\n        Integer physical = logicColumnMap.get(logicColumn);\n        if (physical == null) {\n            throw new IllegalArgumentException(\"Invalid column index: \" + logicColumn);\n        }\n        return physical;\n    }\n\n    @Override\n    public int getLogicColumn(int physicalColumn) {\n        if (physicalColumnMap == null) {\n            return physicalColumn;\n        }\n        Integer logical = physicalColumnMap.get(physicalColumn);\n        if (logical == null) {\n            throw new IllegalArgumentException(\"Invalid column index: \" + physicalColumn);\n        }\n        return logical;\n    }\n\n    @Override\n    public int getHiddenColumnCount() {\n        if (hiddenColumns == null) {\n            return 0;\n        }\n        return hiddenColumns.size();\n    }\n\n    @Override\n    public List<Integer> getHiddenColumns() {\n        return this.hiddenColumns;\n    }\n\n    @Override\n    public void setLogicColumnMap(Map<Integer, Integer> logicColumnMap) {\n        this.logicColumnMap = logicColumnMap;\n    }\n\n    @Override\n    public void setPhysicalColumnMap(Map<Integer, Integer> physicalColumnMap) {\n        this.physicalColumnMap = physicalColumnMap;\n    }\n\n    @Override\n    public void setHiddenColumns(List<Integer> hiddenColumns) {\n        this.hiddenColumns = hiddenColumns;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/StatementExecuteType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\npublic enum StatementExecuteType {\n    Execute,\n    ExecuteBatch,\n    ExecuteQuery,\n    ExecuteUpdate\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.stat.JdbcSqlStat;\n\nimport java.sql.Statement;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface StatementProxy extends Statement, WrapperProxy {\n    ConnectionProxy getConnectionProxy();\n\n    Statement getRawObject();\n\n    List<String> getBatchSqlList();\n\n    String getBatchSql();\n\n    JdbcSqlStat getSqlStat();\n\n    StatementExecuteType getLastExecuteType();\n\n    void setSqlStat(JdbcSqlStat sqlStat);\n\n    String getLastExecuteSql();\n\n    long getLastExecuteStartNano();\n\n    void setLastExecuteStartNano(long lastExecuteStartNano);\n\n    void setLastExecuteStartNano();\n\n    long getLastExecuteTimeNano();\n\n    void setLastExecuteTimeNano(long nano);\n\n    void setLastExecuteTimeNano();\n\n    Map<Integer, JdbcParameter> getParameters();\n\n    int getParametersSize();\n\n    JdbcParameter getParameter(int i);\n\n    boolean isFirstResultSet();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.stat.JdbcSqlStat;\n\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class StatementProxyImpl extends WrapperProxyImpl implements StatementProxy {\n    private final ConnectionProxy connection;\n    protected Statement statement;\n    protected String lastExecuteSql;\n    protected long lastExecuteStartNano;\n    protected long lastExecuteTimeNano;\n    protected JdbcSqlStat sqlStat;\n    protected boolean firstResultSet;\n    protected ArrayList<String> batchSqlList;\n    protected StatementExecuteType lastExecuteType;\n    protected Integer updateCount;\n    private FilterChainImpl filterChain;\n\n    public StatementProxyImpl(ConnectionProxy connection, Statement statement, long id) {\n        super(statement, id);\n        this.connection = connection;\n        this.statement = statement;\n    }\n\n    public ConnectionProxy getConnectionProxy() {\n        return connection;\n    }\n\n    public Statement getRawObject() {\n        return this.statement;\n    }\n\n    public final FilterChainImpl createChain() {\n        FilterChainImpl chain = this.filterChain;\n        if (chain == null) {\n            chain = new FilterChainImpl(this.getConnectionProxy().getDirectDataSource());\n        } else {\n            this.filterChain = null;\n        }\n\n        return chain;\n    }\n\n    public final void recycleFilterChain(FilterChainImpl chain) {\n        chain.reset();\n        this.filterChain = chain;\n    }\n\n    @Override\n    public void addBatch(String sql) throws SQLException {\n        if (batchSqlList == null) {\n            batchSqlList = new ArrayList<String>();\n        }\n\n        FilterChainImpl chain = createChain();\n        chain.statement_addBatch(this, sql);\n        recycleFilterChain(chain);\n        batchSqlList.add(sql);\n    }\n\n    @Override\n    public void cancel() throws SQLException {\n        if (this.statement == null) {\n            return;\n        }\n\n        FilterChainImpl chain = createChain();\n        chain.statement_cancel(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void clearBatch() throws SQLException {\n        if (this.statement == null) {\n            return;\n        }\n\n        if (batchSqlList == null) {\n            batchSqlList = new ArrayList<String>();\n        }\n\n        FilterChainImpl chain = createChain();\n        chain.statement_clearBatch(this);\n        recycleFilterChain(chain);\n        batchSqlList.clear();\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        if (this.statement == null) {\n            return;\n        }\n\n        FilterChainImpl chain = createChain();\n        chain.statement_clearWarnings(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void close() throws SQLException {\n        if (this.statement == null) {\n            return;\n        }\n\n        FilterChainImpl chain = createChain();\n        chain.statement_close(this);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public boolean execute(String sql) throws SQLException {\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.Execute;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        firstResultSet = chain.statement_execute(this, sql);\n        recycleFilterChain(chain);\n        return firstResultSet;\n    }\n\n    @Override\n    public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.Execute;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        firstResultSet = chain.statement_execute(this, sql, autoGeneratedKeys);\n        recycleFilterChain(chain);\n        return firstResultSet;\n    }\n\n    @Override\n    public boolean execute(String sql, int[] columnIndexes) throws SQLException {\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.Execute;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        firstResultSet = chain.statement_execute(this, sql, columnIndexes);\n        recycleFilterChain(chain);\n        return firstResultSet;\n    }\n\n    @Override\n    public boolean execute(String sql, String[] columnNames) throws SQLException {\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.Execute;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        firstResultSet = chain.statement_execute(this, sql, columnNames);\n        recycleFilterChain(chain);\n        return firstResultSet;\n    }\n\n    @Override\n    public int[] executeBatch() throws SQLException {\n        firstResultSet = false;\n        lastExecuteType = StatementExecuteType.ExecuteBatch;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        int[] updateCounts = chain.statement_executeBatch(this);\n        recycleFilterChain(chain);\n        if (updateCounts != null && updateCounts.length == 1) {\n            updateCount = updateCounts[0];\n        }\n\n        return updateCounts;\n    }\n\n    @Override\n    public ResultSet executeQuery(String sql) throws SQLException {\n        firstResultSet = true;\n        updateCount = null;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.ExecuteQuery;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        ResultSet resultSet = chain.statement_executeQuery(this, sql);\n        recycleFilterChain(chain);\n        return resultSet;\n    }\n\n    @Override\n    public int executeUpdate(String sql) throws SQLException {\n        firstResultSet = false;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.ExecuteUpdate;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        updateCount = chain.statement_executeUpdate(this, sql);\n        recycleFilterChain(chain);\n        return updateCount;\n    }\n\n    @Override\n    public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n        firstResultSet = false;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.ExecuteUpdate;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        updateCount = chain.statement_executeUpdate(this, sql, autoGeneratedKeys);\n        recycleFilterChain(chain);\n        return updateCount;\n    }\n\n    @Override\n    public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {\n        firstResultSet = false;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.ExecuteUpdate;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        updateCount = chain.statement_executeUpdate(this, sql, columnIndexes);\n        recycleFilterChain(chain);\n        return updateCount;\n    }\n\n    @Override\n    public int executeUpdate(String sql, String[] columnNames) throws SQLException {\n        firstResultSet = false;\n        lastExecuteSql = sql;\n        lastExecuteType = StatementExecuteType.ExecuteUpdate;\n        lastExecuteStartNano = -1L;\n        lastExecuteTimeNano = -1L;\n\n        FilterChainImpl chain = createChain();\n        updateCount = chain.statement_executeUpdate(this, sql, columnNames);\n        recycleFilterChain(chain);\n        return updateCount;\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        FilterChainImpl chain = createChain();\n        Connection conn = chain.statement_getConnection(this);\n        recycleFilterChain(chain);\n        return conn;\n    }\n\n    @Override\n    public int getFetchDirection() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getFetchDirection(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getFetchSize() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getFetchSize(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public ResultSet getGeneratedKeys() throws SQLException {\n        FilterChainImpl chain = createChain();\n        ResultSet value = chain.statement_getGeneratedKeys(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getMaxFieldSize() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getMaxFieldSize(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getMaxRows() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getMaxRows(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean getMoreResults() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.statement_getMoreResults(this);\n        updateCount = null;\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean getMoreResults(int current) throws SQLException {\n        updateCount = null;\n        FilterChainImpl chain = createChain();\n        boolean value = chain.statement_getMoreResults(this, current);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getQueryTimeout() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getQueryTimeout(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public ResultSet getResultSet() throws SQLException {\n        FilterChainImpl chain = createChain();\n        ResultSet value = chain.statement_getResultSet(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getResultSetConcurrency() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getResultSetConcurrency(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getResultSetHoldability() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getResultSetHoldability(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public int getResultSetType() throws SQLException {\n        FilterChainImpl chain = createChain();\n        int value = chain.statement_getResultSetType(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    // bug fixed for oracle\n    @Override\n    public int getUpdateCount() throws SQLException {\n        if (updateCount == null) {\n            FilterChainImpl chain = createChain();\n            updateCount = chain.statement_getUpdateCount(this);\n            recycleFilterChain(chain);\n        }\n        return updateCount;\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        FilterChainImpl chain = createChain();\n        SQLWarning value = chain.statement_getWarnings(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.statement_isClosed(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public boolean isPoolable() throws SQLException {\n        FilterChainImpl chain = createChain();\n        boolean value = chain.statement_isPoolable(this);\n        recycleFilterChain(chain);\n        return value;\n    }\n\n    @Override\n    public void setCursorName(String name) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setCursorName(this, name);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setEscapeProcessing(boolean enable) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setEscapeProcessing(this, enable);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setFetchDirection(int direction) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setFetchDirection(this, direction);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setFetchSize(int rows) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setFetchSize(this, rows);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setMaxFieldSize(int max) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setMaxFieldSize(this, max);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setMaxRows(int max) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setMaxRows(this, max);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setPoolable(boolean poolable) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setPoolable(this, poolable);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public void setQueryTimeout(int seconds) throws SQLException {\n        FilterChainImpl chain = createChain();\n        chain.statement_setQueryTimeout(this, seconds);\n        recycleFilterChain(chain);\n    }\n\n    @Override\n    public List<String> getBatchSqlList() {\n        if (batchSqlList == null) {\n            batchSqlList = new ArrayList<String>();\n        }\n\n        return batchSqlList;\n    }\n\n    @Override\n    public String getBatchSql() {\n        List<String> sqlList = getBatchSqlList();\n        StringBuilder buf = new StringBuilder();\n        for (String item : sqlList) {\n            if (buf.length() > 0) {\n                buf.append(\"\\n;\\n\");\n            }\n            buf.append(item);\n        }\n        return buf.toString();\n    }\n\n    public String getLastExecuteSql() {\n        return lastExecuteSql;\n    }\n\n    public void closeOnCompletion() throws SQLException {\n        statement.closeOnCompletion();\n    }\n\n    public boolean isCloseOnCompletion() throws SQLException {\n        return statement.isCloseOnCompletion();\n    }\n\n    @Override\n    public Map<Integer, JdbcParameter> getParameters() {\n        return Collections.emptyMap();\n    }\n\n    public JdbcSqlStat getSqlStat() {\n        return sqlStat;\n    }\n\n    public void setSqlStat(JdbcSqlStat sqlStat) {\n        this.sqlStat = sqlStat;\n    }\n\n    public long getLastExecuteTimeNano() {\n        return lastExecuteTimeNano;\n    }\n\n    public void setLastExecuteTimeNano(long lastExecuteTimeNano) {\n        this.lastExecuteTimeNano = lastExecuteTimeNano;\n    }\n\n    public void setLastExecuteTimeNano() {\n        if (this.lastExecuteTimeNano <= 0 && this.lastExecuteStartNano > 0) {\n            this.lastExecuteTimeNano = System.nanoTime() - this.lastExecuteStartNano;\n        }\n    }\n\n    public long getLastExecuteStartNano() {\n        return lastExecuteStartNano;\n    }\n\n    public void setLastExecuteStartNano(long lastExecuteStartNano) {\n        this.lastExecuteStartNano = lastExecuteStartNano;\n        this.lastExecuteTimeNano = -1L;\n    }\n\n    public void setLastExecuteStartNano() {\n        if (lastExecuteStartNano <= 0) {\n            setLastExecuteStartNano(System.nanoTime());\n        }\n    }\n\n    public StatementExecuteType getLastExecuteType() {\n        return lastExecuteType;\n    }\n\n    public boolean isFirstResultSet() {\n        return firstResultSet;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == StatementProxy.class) {\n            return (T) this;\n        }\n\n        return super.unwrap(iface);\n    }\n\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == StatementProxy.class) {\n            return true;\n        }\n\n        return super.isWrapperFor(iface);\n    }\n\n    @Override\n    public int getParametersSize() {\n        return 0;\n    }\n\n    @Override\n    public JdbcParameter getParameter(int i) {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/TransactionInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\n// compatible for druid 0.1.19\npublic class TransactionInfo extends com.alibaba.druid.util.TransactionInfo {\n    public TransactionInfo(long id) {\n        super(id);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/WrapperProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport java.sql.Wrapper;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface WrapperProxy extends Wrapper {\n    long getId();\n\n    Object getRawObject();\n\n    int getAttributesSize();\n\n    void clearAttributes();\n\n    Map<String, Object> getAttributes();\n\n    Object getAttribute(String key);\n\n    void putAttribute(String key, Object value);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/proxy/jdbc/WrapperProxyImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.proxy.jdbc;\n\nimport com.alibaba.druid.filter.FilterChain;\n\nimport java.sql.SQLException;\nimport java.sql.Wrapper;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic abstract class WrapperProxyImpl implements WrapperProxy {\n    private final Wrapper raw;\n\n    private final long id;\n\n    private Map<String, Object> attributes; // 不需要线程安全\n\n    public WrapperProxyImpl(Wrapper wrapper, long id) {\n        this.raw = wrapper;\n        this.id = id;\n    }\n\n    public long getId() {\n        return this.id;\n    }\n\n    public Object getRawObject() {\n        return raw;\n    }\n\n    public abstract FilterChain createChain();\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == null) {\n            return false;\n        }\n\n        if (iface == this.getClass()) {\n            return true;\n        }\n\n        FilterChain chain = createChain();\n        return chain.isWrapperFor(raw, iface);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == null) {\n            return null;\n        }\n\n        if (iface == this.getClass()) {\n            return (T) this;\n        }\n\n        return createChain().unwrap(raw, iface);\n    }\n\n    public int getAttributesSize() {\n        if (attributes == null) {\n            return 0;\n        }\n\n        return attributes.size();\n    }\n\n    public void clearAttributes() {\n        if (this.attributes == null) {\n            return;\n        }\n\n        this.attributes.clear();\n    }\n\n    public Map<String, Object> getAttributes() {\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(4);\n        }\n        return this.attributes;\n    }\n\n    public void putAttribute(String key, Object value) {\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(4);\n        }\n        this.attributes.put(key, value);\n    }\n\n    public Object getAttribute(String key) {\n        if (attributes == null) {\n            return null;\n        }\n\n        return this.attributes.get(key);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/PagerUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.FastsqlException;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.util.List;\n\npublic class PagerUtils {\n    public static String count(String sql, DbType dbType) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (stmtList.size() != 1) {\n            throw new IllegalArgumentException(\"sql not support count : \" + sql);\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n\n        if (!(stmt instanceof SQLSelectStatement)) {\n            throw new IllegalArgumentException(\"sql not support count : \" + sql);\n        }\n\n        SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;\n        return count(selectStmt.getSelect(), dbType);\n    }\n\n    public static String limit(String sql, DbType dbType, int offset, int count) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (stmtList.size() != 1) {\n            throw new IllegalArgumentException(\"sql not support count : \" + sql);\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n\n        if (!(stmt instanceof SQLSelectStatement)) {\n            throw new IllegalArgumentException(\"sql not support count : \" + sql);\n        }\n\n        SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;\n\n        return limit(selectStmt.getSelect(), dbType, offset, count);\n    }\n\n    public static String limit(String sql, DbType dbType, int offset, int count, boolean check) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (stmtList.size() != 1) {\n            throw new IllegalArgumentException(\"sql not support count : \" + sql);\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n\n        if (!(stmt instanceof SQLSelectStatement)) {\n            throw new IllegalArgumentException(\"sql not support count : \" + sql);\n        }\n\n        SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;\n\n        limit(selectStmt.getSelect(), dbType, offset, count, check);\n\n        return selectStmt.toString();\n    }\n\n    public static String limit(SQLSelect select, DbType dbType, int offset, int count) {\n        limit(select, dbType, offset, count, false);\n\n        return SQLUtils.toSQLString(select, dbType);\n    }\n\n    public static boolean limit(SQLSelect select, DbType dbType, int offset, int count, boolean check) {\n        SQLSelectQuery query = select.getQuery();\n\n        switch (dbType) {\n            case oracle:\n                return limitOracle(select, dbType, offset, count, check);\n            case db2:\n                return limitDB2(select, dbType, offset, count, check);\n            case sqlserver:\n            case jtds:\n                return limitSQLServer(select, dbType, offset, count, check);\n            default:\n                if (query instanceof SQLSelectQueryBlock) {\n                    return limitQueryBlock(select, dbType, offset, count, check);\n                } else if (query instanceof SQLUnionQuery) {\n                    return limitUnion((SQLUnionQuery) query, dbType, offset, count, check);\n                }\n                throw new UnsupportedOperationException();\n        }\n    }\n\n    private static boolean limitUnion(SQLUnionQuery queryBlock, DbType dbType, int offset, int count, boolean check) {\n        SQLLimit limit = queryBlock.getLimit();\n        if (limit != null) {\n            if (offset >= 0) {\n                limit.setOffset(new SQLIntegerExpr(offset));\n            }\n\n            if (check && limit.getRowCount() instanceof SQLNumericLiteralExpr) {\n                int rowCount = ((SQLNumericLiteralExpr) limit.getRowCount()).getNumber().intValue();\n                if (rowCount <= count && offset <= 0) {\n                    return false;\n                }\n            } else if (check && limit.getRowCount() instanceof SQLVariantRefExpr) {\n                return false;\n            }\n\n            limit.setRowCount(new SQLIntegerExpr(count));\n        }\n\n        if (limit == null) {\n            limit = new SQLLimit();\n            if (offset > 0) {\n                limit.setOffset(new SQLIntegerExpr(offset));\n            }\n            limit.setRowCount(new SQLIntegerExpr(count));\n            queryBlock.setLimit(limit);\n        }\n\n        return true;\n    }\n\n    private static boolean limitQueryBlock(SQLSelect select, DbType dbType, int offset, int count, boolean check) {\n        SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) select.getQuery();\n\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        switch (dbType) {\n            case mysql:\n            case mariadb:\n            case tidb:\n            case h2:\n            case lealone:\n            case ads:\n            case clickhouse:\n            case polardbx:\n                return limitMySqlQueryBlock(queryBlock, dbType, offset, count, check);\n            case postgresql:\n            case greenplum:\n            case edb:\n            case hive:\n            case odps:\n            case presto:\n            case supersql:\n                return limitSQLQueryBlock(queryBlock, dbType, offset, count, check);\n            case oracle:\n            case oceanbase_oracle:\n            case polardb2:\n                return limitOracle(select, dbType, offset, count, check);\n            default:\n                throw new UnsupportedOperationException();\n        }\n    }\n\n    private static boolean limitSQLQueryBlock(SQLSelectQueryBlock queryBlock,\n                                              DbType dbType,\n                                              int offset,\n                                              int count,\n                                              boolean check) {\n        SQLLimit limit = queryBlock.getLimit();\n        if (limit != null) {\n            if (offset >= 0) {\n                limit.setOffset(new SQLIntegerExpr(offset));\n            }\n\n            if (check && limit.getRowCount() instanceof SQLNumericLiteralExpr) {\n                int rowCount = ((SQLNumericLiteralExpr) limit.getRowCount()).getNumber().intValue();\n                if (rowCount <= count && offset <= 0) {\n                    return false;\n                }\n            }\n\n            limit.setRowCount(new SQLIntegerExpr(count));\n        }\n\n        limit = new SQLLimit();\n        if (offset > 0) {\n            limit.setOffset(new SQLIntegerExpr(offset));\n        }\n        limit.setRowCount(new SQLIntegerExpr(count));\n        queryBlock.setLimit(limit);\n        return true;\n    }\n\n    private static boolean limitDB2(SQLSelect select, DbType dbType, int offset, int count, boolean check) {\n        SQLSelectQuery query = select.getQuery();\n\n        SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr(\"ROWNUM\"),\n                SQLBinaryOperator.GreaterThan,\n                new SQLNumberExpr(offset),\n                DbType.db2);\n        SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr(\"ROWNUM\"),\n                SQLBinaryOperator.LessThanOrEqual,\n                new SQLNumberExpr(count + offset),\n                DbType.db2);\n        SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq, DbType.db2);\n\n        if (query instanceof SQLSelectQueryBlock) {\n            DB2SelectQueryBlock queryBlock = (DB2SelectQueryBlock) query;\n            if (offset <= 0) {\n                SQLExpr first = queryBlock.getFirst();\n                if (check && first != null && first instanceof SQLNumericLiteralExpr) {\n                    int rowCount = ((SQLNumericLiteralExpr) first).getNumber().intValue();\n                    if (rowCount < count) {\n                        return false;\n                    }\n                }\n                queryBlock.setFirst(new SQLIntegerExpr(count));\n                return true;\n            }\n\n            SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(\"ROW_NUMBER\");\n            SQLOrderBy orderBy = select.getOrderBy();\n\n            if (orderBy == null && select.getQuery() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock selectQueryBlcok = (SQLSelectQueryBlock) select.getQuery();\n                orderBy = selectQueryBlcok.getOrderBy();\n                selectQueryBlcok.setOrderBy(null);\n            } else {\n                select.setOrderBy(null);\n            }\n\n            aggregateExpr.setOver(new SQLOver(orderBy));\n\n            queryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, \"ROWNUM\"));\n\n            DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock();\n            countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));\n\n            countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), \"XX\"));\n\n            countQueryBlock.setWhere(pageCondition);\n\n            select.setQuery(countQueryBlock);\n\n            return true;\n        }\n\n        DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock();\n        countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr(\"XX\"), \"*\")));\n        SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(\"ROW_NUMBER\");\n        SQLOrderBy orderBy = select.getOrderBy();\n        aggregateExpr.setOver(new SQLOver(orderBy));\n        select.setOrderBy(null);\n        countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, \"ROWNUM\"));\n\n        countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), \"XX\"));\n\n        if (offset <= 0) {\n            select.setQuery(countQueryBlock);\n            return true;\n        }\n\n        DB2SelectQueryBlock offsetQueryBlock = new DB2SelectQueryBlock();\n        offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));\n        offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), \"XXX\"));\n        offsetQueryBlock.setWhere(pageCondition);\n\n        select.setQuery(offsetQueryBlock);\n\n        return true;\n    }\n\n    private static boolean limitSQLServer(SQLSelect select, DbType dbType, int offset, int count, boolean check) {\n        SQLSelectQuery query = select.getQuery();\n\n        SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr(\"ROWNUM\"),\n                SQLBinaryOperator.GreaterThan,\n                new SQLNumberExpr(offset),\n                DbType.sqlserver);\n        SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr(\"ROWNUM\"),\n                SQLBinaryOperator.LessThanOrEqual,\n                new SQLNumberExpr(count + offset),\n                DbType.sqlserver);\n        SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq,\n                DbType.sqlserver);\n\n        if (query instanceof SQLSelectQueryBlock) {\n            SQLServerSelectQueryBlock queryBlock = (SQLServerSelectQueryBlock) query;\n            if (offset <= 0) {\n                SQLTop top = queryBlock.getTop();\n                if (check && top != null && !top.isPercent() && top.getExpr() instanceof SQLNumericLiteralExpr) {\n                    int rowCount = ((SQLNumericLiteralExpr) top.getExpr()).getNumber().intValue();\n                    if (rowCount <= count) {\n                        return false;\n                    }\n                }\n                queryBlock.setTop(new SQLTop(new SQLNumberExpr(count)));\n                return true;\n            }\n\n            SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(\"ROW_NUMBER\");\n            SQLOrderBy orderBy = select.getOrderBy();\n            if (orderBy != null) {\n                aggregateExpr.setOver(new SQLOver(orderBy));\n                select.setOrderBy(null);\n            } else if (queryBlock.getOrderBy() != null) {\n                aggregateExpr.setOver(new SQLOver(queryBlock.getOrderBy()));\n                queryBlock.setOrderBy(null);\n            }\n\n            queryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, \"ROWNUM\"));\n\n            SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock();\n            countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));\n\n            countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), \"XX\"));\n\n            countQueryBlock.setWhere(pageCondition);\n\n            select.setQuery(countQueryBlock);\n\n            return true;\n        }\n\n        SQLServerSelectQueryBlock countQueryBlock = new SQLServerSelectQueryBlock();\n        countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr(\"XX\"), \"*\")));\n\n        countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), \"XX\"));\n\n        if (offset <= 0) {\n            countQueryBlock.setTop(new SQLTop(new SQLNumberExpr(count)));\n\n            select.setQuery(countQueryBlock);\n            return true;\n        }\n\n        SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(\"ROW_NUMBER\");\n        SQLOrderBy orderBy = select.getOrderBy();\n        aggregateExpr.setOver(new SQLOver(orderBy));\n        select.setOrderBy(null);\n        countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, \"ROWNUM\"));\n\n        SQLServerSelectQueryBlock offsetQueryBlock = new SQLServerSelectQueryBlock();\n        offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));\n        offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), \"XXX\"));\n        offsetQueryBlock.setWhere(pageCondition);\n\n        select.setQuery(offsetQueryBlock);\n\n        return true;\n    }\n\n    private static boolean limitOracle(SQLSelect select, DbType dbType, int offset, int count, boolean check) {\n        SQLSelectQuery query = select.getQuery();\n\n        if (query instanceof SQLSelectQueryBlock) {\n            OracleSelectQueryBlock queryBlock = (OracleSelectQueryBlock) query;\n            SQLOrderBy orderBy = select.getOrderBy();\n            if (orderBy == null && queryBlock.getOrderBy() != null) {\n                orderBy = queryBlock.getOrderBy();\n            }\n\n            if (queryBlock.getGroupBy() == null\n                    && orderBy == null && offset <= 0) {\n                SQLExpr where = queryBlock.getWhere();\n                if (check && where instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr binaryOpWhere = (SQLBinaryOpExpr) where;\n                    if (binaryOpWhere.getOperator() == SQLBinaryOperator.LessThanOrEqual) {\n                        SQLExpr left = binaryOpWhere.getLeft();\n                        SQLExpr right = binaryOpWhere.getRight();\n                        if (left instanceof SQLIdentifierExpr\n                                && ((SQLIdentifierExpr) left).getName().equalsIgnoreCase(\"ROWNUM\")\n                                && right instanceof SQLNumericLiteralExpr) {\n                            int rowCount = ((SQLNumericLiteralExpr) right).getNumber().intValue();\n                            if (rowCount <= count) {\n                                return false;\n                            }\n                        }\n                    }\n                }\n\n                SQLExpr condition = new SQLBinaryOpExpr(new SQLIdentifierExpr(\"ROWNUM\"),\n                        SQLBinaryOperator.LessThanOrEqual,\n                        new SQLNumberExpr(count),\n                        DbType.oracle);\n                if (queryBlock.getWhere() == null) {\n                    queryBlock.setWhere(condition);\n                } else {\n                    queryBlock.setWhere(new SQLBinaryOpExpr(queryBlock.getWhere(),\n                            SQLBinaryOperator.BooleanAnd,\n                            condition,\n                            DbType.oracle));\n                }\n\n                return true;\n            }\n        }\n\n        OracleSelectQueryBlock countQueryBlock = new OracleSelectQueryBlock();\n        countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr(\"XX\"), \"*\")));\n        countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLIdentifierExpr(\"ROWNUM\"), \"RN\"));\n\n        countQueryBlock.setFrom(new SQLSubqueryTableSource(select.clone(), \"XX\"));\n        countQueryBlock.setWhere(new SQLBinaryOpExpr(new SQLIdentifierExpr(\"ROWNUM\"),\n                SQLBinaryOperator.LessThanOrEqual,\n                new SQLNumberExpr(count + offset),\n                DbType.oracle));\n\n        select.setOrderBy(null);\n        if (offset <= 0) {\n            select.setQuery(countQueryBlock);\n            return true;\n        }\n\n        OracleSelectQueryBlock offsetQueryBlock = new OracleSelectQueryBlock();\n        offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));\n        offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), \"XXX\"));\n        offsetQueryBlock.setWhere(new SQLBinaryOpExpr(new SQLIdentifierExpr(\"RN\"),\n                SQLBinaryOperator.GreaterThan,\n                new SQLNumberExpr(offset),\n                DbType.oracle));\n\n        select.setQuery(offsetQueryBlock);\n        return true;\n    }\n\n    private static boolean limitMySqlQueryBlock(SQLSelectQueryBlock queryBlock,\n                                                DbType dbType,\n                                                int offset,\n                                                int count,\n                                                boolean check) {\n        SQLLimit limit = queryBlock.getLimit();\n        if (limit != null) {\n            if (offset >= 0) {\n                limit.setOffset(new SQLIntegerExpr(offset));\n            }\n\n            if (check && limit.getRowCount() instanceof SQLNumericLiteralExpr) {\n                int rowCount = ((SQLNumericLiteralExpr) limit.getRowCount()).getNumber().intValue();\n                if (rowCount <= count && offset <= 0) {\n                    return false;\n                }\n            } else if (check && limit.getRowCount() instanceof SQLVariantRefExpr) {\n                return false;\n            }\n\n            limit.setRowCount(new SQLIntegerExpr(count));\n        }\n\n        if (limit == null) {\n            limit = new SQLLimit();\n            if (offset > 0) {\n                limit.setOffset(new SQLIntegerExpr(offset));\n            }\n            limit.setRowCount(new SQLIntegerExpr(count));\n            queryBlock.setLimit(limit);\n        }\n\n        return true;\n    }\n\n    private static String count(SQLSelect select, DbType dbType) {\n        if (select.getOrderBy() != null) {\n            select.setOrderBy(null);\n        }\n\n        SQLSelectQuery query = select.getQuery();\n        clearOrderBy(query);\n\n        if (query instanceof SQLSelectQueryBlock) {\n            SQLSelectItem countItem = createCountItem(dbType);\n\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n            List<SQLSelectItem> selectList = queryBlock.getSelectList();\n\n            if (queryBlock.getGroupBy() != null\n                    && queryBlock.getGroupBy().getItems().size() > 0) {\n                if (queryBlock.getSelectList().size() == 1\n                        && queryBlock.getSelectList().get(0).getExpr() instanceof SQLAllColumnExpr\n                ) {\n                    queryBlock.getSelectList().clear();\n                    queryBlock.getSelectList().add(new SQLSelectItem(new SQLIntegerExpr(1)));\n                }\n                return createCountUseSubQuery(select, dbType);\n            }\n\n            int option = queryBlock.getDistionOption();\n            if (option == SQLSetQuantifier.DISTINCT\n                    && selectList.size() >= 1) {\n                SQLAggregateExpr countExpr = new SQLAggregateExpr(\"COUNT\", SQLAggregateOption.DISTINCT);\n                for (int i = 0; i < selectList.size(); ++i) {\n                    countExpr.addArgument(selectList.get(i).getExpr());\n                }\n                selectList.clear();\n                queryBlock.setDistionOption(0);\n                queryBlock.addSelectItem(countExpr);\n            } else {\n                selectList.clear();\n                selectList.add(countItem);\n            }\n            return SQLUtils.toSQLString(select, dbType);\n        } else if (query instanceof SQLUnionQuery) {\n            return createCountUseSubQuery(select, dbType);\n        }\n\n        throw new IllegalStateException();\n    }\n\n    private static String createCountUseSubQuery(SQLSelect select, DbType dbType) {\n        SQLSelectQueryBlock countSelectQuery = createQueryBlock(dbType);\n\n        SQLSelectItem countItem = createCountItem(dbType);\n        countSelectQuery.getSelectList().add(countItem);\n\n        SQLSubqueryTableSource fromSubquery = new SQLSubqueryTableSource(select);\n        fromSubquery.setAlias(\"ALIAS_COUNT\");\n        countSelectQuery.setFrom(fromSubquery);\n\n        SQLSelect countSelect = new SQLSelect(countSelectQuery);\n        SQLSelectStatement countStmt = new SQLSelectStatement(countSelect, dbType);\n\n        return SQLUtils.toSQLString(countStmt, dbType);\n    }\n\n    private static SQLSelectQueryBlock createQueryBlock(DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        switch (dbType) {\n            case mysql:\n            case mariadb:\n            case tidb:\n            case ads:\n            case polardbx:\n                return new MySqlSelectQueryBlock();\n            case oracle:\n            case polardb2:\n                return new OracleSelectQueryBlock();\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGSelectQueryBlock();\n            case sqlserver:\n            case jtds:\n                return new SQLServerSelectQueryBlock();\n            case db2:\n                return new DB2SelectQueryBlock();\n            case odps:\n                return new OdpsSelectQueryBlock();\n            default:\n                return new SQLSelectQueryBlock(dbType);\n        }\n    }\n\n    private static SQLSelectItem createCountItem(DbType dbType) {\n        SQLAggregateExpr countExpr = new SQLAggregateExpr(\"COUNT\");\n\n        countExpr.addArgument(new SQLAllColumnExpr());\n\n        SQLSelectItem countItem = new SQLSelectItem(countExpr);\n        return countItem;\n    }\n\n    private static void clearOrderBy(SQLSelectQuery query) {\n        if (query instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n            if (queryBlock.getOrderBy() != null) {\n                queryBlock.setOrderBy(null);\n            }\n            return;\n        }\n\n        if (query instanceof SQLUnionQuery) {\n            SQLUnionQuery union = (SQLUnionQuery) query;\n            if (union.getOrderBy() != null) {\n                union.setOrderBy(null);\n            }\n            clearOrderBy(union.getLeft());\n            clearOrderBy(union.getRight());\n        }\n    }\n\n    /**\n     * Retrieves the limit value from the provided SQL query string based on the specified database type.\n     *\n     * @param sql    the SQL query string\n     * @param dbType the database type for parsing the SQL query\n     * @return the limit value extracted from the SQL query, or -1 if the query does not have a valid limit clause\n     */\n    public static int getLimit(String sql, DbType dbType) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (stmtList.size() != 1) {\n            return -1;\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n\n        if (stmt instanceof SQLSelectStatement) {\n            SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;\n            SQLSelectQuery query = selectStmt.getSelect().getQuery();\n            if (query instanceof SQLSelectQueryBlock) {\n                if (query instanceof MySqlSelectQueryBlock) {\n                    SQLLimit limit = ((MySqlSelectQueryBlock) query).getLimit();\n\n                    if (limit == null) {\n                        return -1;\n                    }\n\n                    SQLExpr rowCountExpr = limit.getRowCount();\n\n                    if (rowCountExpr instanceof SQLNumericLiteralExpr) {\n                        int rowCount = ((SQLNumericLiteralExpr) rowCountExpr).getNumber().intValue();\n                        return rowCount;\n                    }\n\n                    return Integer.MAX_VALUE;\n                }\n\n                if (query instanceof OdpsSelectQueryBlock) {\n                    SQLLimit limit = ((OdpsSelectQueryBlock) query).getLimit();\n                    SQLExpr rowCountExpr = limit != null ? limit.getRowCount() : null;\n\n                    if (rowCountExpr instanceof SQLNumericLiteralExpr) {\n                        int rowCount = ((SQLNumericLiteralExpr) rowCountExpr).getNumber().intValue();\n                        return rowCount;\n                    }\n\n                    return Integer.MAX_VALUE;\n                }\n\n                return -1;\n            }\n        }\n\n        return -1;\n    }\n\n    public static boolean hasUnorderedLimit(String sql, DbType dbType) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (JdbcUtils.isMysqlDbType(dbType)) {\n            MySqlUnorderedLimitDetectVisitor visitor = new MySqlUnorderedLimitDetectVisitor();\n\n            for (SQLStatement stmt : stmtList) {\n                stmt.accept(visitor);\n            }\n\n            return visitor.unorderedLimitCount > 0;\n        }\n\n        if (DbType.oracle == dbType) {\n            OracleUnorderedLimitDetectVisitor visitor = new OracleUnorderedLimitDetectVisitor();\n\n            for (SQLStatement stmt : stmtList) {\n                stmt.accept(visitor);\n            }\n\n            return visitor.unorderedLimitCount > 0;\n        }\n\n        throw new FastsqlException(\"not supported. dbType : \" + dbType);\n    }\n\n    private static class MySqlUnorderedLimitDetectVisitor extends MySqlASTVisitorAdapter {\n        public int unorderedLimitCount;\n\n        @Override\n        public boolean visit(MySqlSelectQueryBlock x) {\n            SQLOrderBy orderBy = x.getOrderBy();\n            SQLLimit limit = x.getLimit();\n\n            if (limit != null && (orderBy == null || orderBy.getItems().isEmpty())) {\n                boolean subQueryHasOrderBy = false;\n                SQLTableSource from = x.getFrom();\n                if (from instanceof SQLSubqueryTableSource) {\n                    SQLSubqueryTableSource subqueryTabSrc = (SQLSubqueryTableSource) from;\n                    SQLSelect select = subqueryTabSrc.getSelect();\n                    if (select.getQuery() instanceof SQLSelectQueryBlock) {\n                        SQLSelectQueryBlock subquery = (SQLSelectQueryBlock) select.getQuery();\n                        if (subquery.getOrderBy() != null && subquery.getOrderBy().getItems().size() > 0) {\n                            subQueryHasOrderBy = true;\n                        }\n                    }\n                }\n\n                if (!subQueryHasOrderBy) {\n                    unorderedLimitCount++;\n                }\n            }\n            return true;\n        }\n    }\n\n    private static class OracleUnorderedLimitDetectVisitor extends OracleASTVisitorAdapter {\n        public int unorderedLimitCount;\n\n        @Override\n        public boolean visit(SQLBinaryOpExpr x) {\n            SQLExpr left = x.getLeft();\n            SQLExpr right = x.getRight();\n\n            boolean rownum = false;\n            if (left instanceof SQLIdentifierExpr\n                    && ((SQLIdentifierExpr) left).getName().equalsIgnoreCase(\"ROWNUM\")\n                    && right instanceof SQLLiteralExpr) {\n                rownum = true;\n            } else if (right instanceof SQLIdentifierExpr\n                    && ((SQLIdentifierExpr) right).getName().equalsIgnoreCase(\"ROWNUM\")\n                    && left instanceof SQLLiteralExpr) {\n                rownum = true;\n            }\n\n            OracleSelectQueryBlock selectQuery = null;\n            if (rownum) {\n                for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n                    if (parent instanceof SQLSelectQuery) {\n                        if (parent instanceof OracleSelectQueryBlock) {\n                            OracleSelectQueryBlock queryBlock = (OracleSelectQueryBlock) parent;\n                            SQLTableSource from = queryBlock.getFrom();\n                            if (from instanceof SQLExprTableSource) {\n                                selectQuery = queryBlock;\n                            } else if (from instanceof SQLSubqueryTableSource) {\n                                SQLSelect subSelect = ((SQLSubqueryTableSource) from).getSelect();\n                                if (subSelect.getQuery() instanceof OracleSelectQueryBlock) {\n                                    selectQuery = (OracleSelectQueryBlock) subSelect.getQuery();\n                                }\n                            }\n                        }\n                        break;\n                    }\n                }\n            }\n\n            if (selectQuery != null) {\n                SQLOrderBy orderBy = selectQuery.getOrderBy();\n\n                SQLObject parent = selectQuery.getParent();\n                if (orderBy == null && parent instanceof SQLSelect) {\n                    SQLSelect select = (SQLSelect) parent;\n                    orderBy = select.getOrderBy();\n                }\n\n                if (orderBy == null || orderBy.getItems().isEmpty()) {\n                    unorderedLimitCount++;\n                }\n            }\n\n            return true;\n        }\n\n        @Override\n        public boolean visit(OracleSelectQueryBlock queryBlock) {\n            boolean isExprTableSrc = queryBlock.getFrom() instanceof SQLExprTableSource;\n\n            if (!isExprTableSrc) {\n                return true;\n            }\n\n            boolean rownum = false;\n            for (SQLSelectItem item : queryBlock.getSelectList()) {\n                SQLExpr itemExpr = item.getExpr();\n                if (itemExpr instanceof SQLIdentifierExpr) {\n                    if (((SQLIdentifierExpr) itemExpr).getName().equalsIgnoreCase(\"ROWNUM\")) {\n                        rownum = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!rownum) {\n                return true;\n            }\n\n            SQLObject parent = queryBlock.getParent();\n            if (!(parent instanceof SQLSelect)) {\n                return true;\n            }\n\n            SQLSelect select = (SQLSelect) parent;\n\n            if (select.getOrderBy() == null || select.getOrderBy().getItems().isEmpty()) {\n                unorderedLimitCount++;\n            }\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/SQLDialect.java",
    "content": "package com.alibaba.druid.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.Utils;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * @since 1.2.25\n */\npublic class SQLDialect {\n    private static final Map<DbType, SQLDialect> DIALECTS = new ConcurrentHashMap<>();\n\n    private int quoteChars;\n    private final DbType dbType;\n    private final Keyword keywords;\n    private final Keyword aliasKeyword;\n    private final Keyword builtInFunctions;\n    private final Keyword builtInTables;\n    private final Keyword builtInDataTypes;\n\n    private SQLDialect(\n            DbType dbType,\n            List<Quote> quotes,\n            Keyword keywords,\n            Keyword aliasKeyword,\n            Keyword builtInDataTypes,\n            Keyword builtInFunctions,\n            Keyword builtInTables\n    ) {\n        this.dbType = dbType;\n        this.keywords = keywords;\n        this.aliasKeyword = aliasKeyword;\n        this.builtInDataTypes = builtInDataTypes;\n        this.builtInFunctions = builtInFunctions;\n        this.builtInTables = builtInTables;\n        this.quoteChars = DEFAULT_QUOTE_INT;\n        for (Quote quote : quotes) {\n            quoteChars = Quote.register(quoteChars, quote);\n        }\n    }\n\n    public static final int DEFAULT_QUOTE_INT = 0;\n    public void dumpBuiltInDataTypes(Collection<String> dataTypes) {\n        builtInDataTypes.dumpNames(dataTypes);\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public int getQuoteChars() {\n        return quoteChars;\n    }\n\n    public boolean isKeyword(String name) {\n        return keywords.contains(name);\n    }\n\n    public boolean isAliasKeyword(String name) {\n        return aliasKeyword.contains(name);\n    }\n\n    public boolean isBuiltInDataType(String name) {\n        return builtInDataTypes.contains(name);\n    }\n\n    public boolean isBuiltInFunction(String name) {\n        return builtInFunctions.contains(name);\n    }\n\n    public boolean isBuiltInTable(String name) {\n        return builtInTables.contains(name);\n    }\n\n    public static SQLDialect of(DbType dbType) {\n        if (dbType == null) {\n            return null;\n        }\n        return DIALECTS.computeIfAbsent(dbType, SQLDialect::create);\n    }\n\n    private static SQLDialect create(DbType dbType) {\n        String dir = \"META-INF/druid/parser/\".concat(dbType.name().toLowerCase());\n        Properties props = Utils.loadProperties(dir.concat(\"/dialect.properties\"));\n\n        List<Quote> quoteChars = new ArrayList<>();\n        {\n            String quotes = props.getProperty(\"quote\");\n            if (quotes != null) {\n                for (String quote : quotes.split(\",\")) {\n                    if (quote != null && quote.length() == 1) {\n                        if (Quote.of(quote.charAt(0)) != null) {\n                            quoteChars.add(Quote.of(quote.charAt(0)));\n                        }\n                    }\n                }\n            }\n        }\n        if (quoteChars.isEmpty()) {\n            quoteChars.add(Quote.DOUBLE_QUOTE);\n        }\n        return new SQLDialect(\n                dbType,\n                quoteChars,\n                new Keyword(\n                        Utils.readLines(dir.concat(\"/keywords\"))),\n                new Keyword(\n                        Utils.readLines(dir.concat(\"/alias_keywords\"))),\n                new Keyword(\n                        Utils.readLines(dir.concat(\"/builtin_datatypes\"))),\n                new Keyword(\n                        Utils.readLines(dir.concat(\"/builtin_functions\"))),\n                new Keyword(\n                        Utils.readLines(dir.concat(\"/builtin_tables\")))\n        );\n    }\n\n    private static final class Keyword {\n        private final long[] hashes;\n        private final String[] names;\n\n        public Keyword(List<String> reservedKeywords) {\n            Map<Long, String> map = new TreeMap<>();\n            for (String keyword : reservedKeywords) {\n                long hash = FnvHash.fnv1a_64_lower(keyword);\n                map.put(hash, keyword);\n            }\n\n            int index = 0;\n            long[] hashes = new long[map.size()];\n            String[] names = new String[map.size()];\n            for (Map.Entry<Long, String> entry : map.entrySet()) {\n                hashes[index] = entry.getKey();\n                names[index] = entry.getValue();\n                index++;\n            }\n            this.hashes = hashes;\n            this.names = names;\n        }\n\n        public boolean contains(String keyword) {\n            long hash = FnvHash.fnv1a_64_lower(keyword);\n            return Arrays.binarySearch(hashes, hash) >= 0;\n        }\n\n        public void dumpNames(Collection<String> names) {\n            names.addAll(Arrays.asList(this.names));\n        }\n    }\n\n    public enum Quote {\n        SINGLE_QUOTE('\\''),\n        DOUBLE_QUOTE('\"'),\n        BACK_QUOTE('`'),\n        BRACKETS_QUOTE('[');\n        public final int mask;\n        public final char sign;\n        private Quote(char sign) {\n            this.mask = 1 << ordinal();\n            this.sign = sign;\n        }\n\n        public static int register(int features, Quote quote) {\n            return features | quote.mask;\n        }\n\n        public static Quote of(char sign) {\n            if (sign == '[') {\n                return BRACKETS_QUOTE;\n            } else if (sign == '\\'') {\n                return SINGLE_QUOTE;\n            } else if (sign == '\"') {\n                return DOUBLE_QUOTE;\n            } else if (sign == '`') {\n                return BACK_QUOTE;\n            }\n            return null;\n        }\n        public static boolean isValidQuota(int features, Quote quote) {\n            if (quote == null) {\n                return false;\n            }\n            return (features & quote.mask) != 0;\n        }\n\n        public static char getQuote(int features) {\n            if ((features & Quote.BACK_QUOTE.mask) != 0) {\n                return Quote.BACK_QUOTE.sign;\n            } else if ((features & Quote.SINGLE_QUOTE.mask) != 0) {\n                return Quote.SINGLE_QUOTE.sign;\n            } else if ((features & Quote.DOUBLE_QUOTE.mask) != 0) {\n                return Quote.DOUBLE_QUOTE.sign;\n            } else if ((features & Quote.BRACKETS_QUOTE.mask) != 0) {\n                return Quote.BRACKETS_QUOTE.sign;\n            }\n            return ' ';\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/SQLUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.athena.visitor.AthenaOutputVisitor;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryOutputVisitor;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQuerySchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.blink.vsitor.BlinkOutputVisitor;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKOutputVisitor;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKStatVisitor;\nimport com.alibaba.druid.sql.dialect.databricks.visitor.DatabricksOutputASTVisitor;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmOutputVisitor;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.doris.visitor.DorisOutputVisitor;\nimport com.alibaba.druid.sql.dialect.gaussdb.visitor.GaussDbOutputVisitor;\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2OutputVisitor;\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2SchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveOutputVisitor;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.hologres.visitor.HologresOutputVisitor;\nimport com.alibaba.druid.sql.dialect.impala.visitor.ImpalaOutputVisitor;\nimport com.alibaba.druid.sql.dialect.informix.visitor.InformixOutputVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsOutputVisitor;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleWithSubqueryEntry;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleToMySqlOutputVisitor;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarOutputVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoOutputVisitor;\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftOutputVisitor;\nimport com.alibaba.druid.sql.dialect.spark.visitor.SparkOutputASTVisitor;\nimport com.alibaba.druid.sql.dialect.spark.visitor.SparkSchemaStatASTVisitor;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteOutputVisitor;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.starrocks.visitor.StarRocksOutputVisitor;\nimport com.alibaba.druid.sql.dialect.supersql.visitor.SuperSqlOutputVisitor;\nimport com.alibaba.druid.sql.dialect.synapse.visitor.SynapseOutputVisitor;\nimport com.alibaba.druid.sql.dialect.teradata.visitor.TDOutputVisitor;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.*;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.*;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TimeZone;\nimport java.util.function.Consumer;\nimport java.util.function.Predicate;\n\npublic class SQLUtils {\n    private static final SQLParserFeature[] FORMAT_DEFAULT_FEATURES = {\n            SQLParserFeature.KeepComments,\n            SQLParserFeature.EnableSQLBinaryOpExprGroup\n    };\n\n    public static FormatOption DEFAULT_FORMAT_OPTION = new FormatOption(true, true);\n    public static FormatOption DEFAULT_LCASE_FORMAT_OPTION\n            = new FormatOption(false, true);\n\n    private static final Log LOG = LogFactory.getLog(SQLUtils.class);\n\n    public static String toSQLString(SQLObject sqlObject, String dbType) {\n        return toSQLString(sqlObject, DbType.valueOf(dbType));\n    }\n\n    public static String toSQLString(SQLObject sqlObject, DbType dbType) {\n        return toSQLString(sqlObject, dbType, null, null);\n    }\n\n    public static String toSQLString(SQLObject sqlObject, DbType dbType, FormatOption option) {\n        return toSQLString(sqlObject, dbType, option, null);\n    }\n\n    public static String toSQLString(SQLObject sqlObject,\n                                     DbType dbType,\n                                     FormatOption option,\n                                     VisitorFeature... features) {\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = createOutputVisitor(out, dbType);\n\n        if (option == null) {\n            option = DEFAULT_FORMAT_OPTION;\n        }\n\n        visitor.setUppCase(option.isUppCase());\n        visitor.setPrettyFormat(option.isPrettyFormat());\n        visitor.setParameterized(option.isParameterized());\n\n        int featuresValue = option.features;\n        if (features != null) {\n            for (VisitorFeature feature : features) {\n                visitor.config(feature, true);\n                featuresValue |= feature.mask;\n            }\n        }\n\n        visitor.setFeatures(featuresValue);\n\n        sqlObject.accept(visitor);\n\n        String sql = out.toString();\n        return sql;\n    }\n\n    public static String toSQLString(SQLObject obj) {\n        if (obj instanceof SQLStatement) {\n            SQLStatement stmt = (SQLStatement) obj;\n            return toSQLString(stmt, stmt.getDbType());\n        }\n\n        if (obj instanceof MySqlObject) {\n            return toMySqlString(obj);\n        }\n\n        StringBuilder out = new StringBuilder();\n        obj.accept(new SQLASTOutputVisitor(out));\n\n        String sql = out.toString();\n        return sql;\n    }\n\n    public static String toOdpsString(SQLObject sqlObject) {\n        return toOdpsString(sqlObject, null);\n    }\n\n    public static String toHiveString(SQLObject sqlObject) {\n        return toSQLString(sqlObject, DbType.odps);\n    }\n\n    public static String toOdpsString(SQLObject sqlObject, FormatOption option) {\n        return toSQLString(sqlObject, DbType.odps, option);\n    }\n\n    public static String toAntsparkString(SQLObject sqlObject) {\n        return toAntsparkString(sqlObject, null);\n    }\n\n    public static String toAntsparkString(SQLObject sqlObject, FormatOption option) {\n        return toSQLString(sqlObject, DbType.spark, option);\n    }\n\n    public static String toMySqlString(SQLObject sqlObject) {\n        return toMySqlString(sqlObject, (FormatOption) null);\n    }\n\n    public static String toMySqlStringIfNotNull(SQLObject sqlObject, String defaultStr) {\n        if (sqlObject == null) {\n            return defaultStr;\n        }\n\n        return toMySqlString(sqlObject, (FormatOption) null);\n    }\n\n    public static String toMySqlString(SQLObject sqlObject, VisitorFeature... features) {\n        return toMySqlString(sqlObject, new FormatOption(features));\n    }\n\n    public static String toNormalizeMysqlString(SQLObject sqlObject) {\n        if (sqlObject != null) {\n            return SQLUtils.normalize(toSQLString(sqlObject, DbType.mysql));\n        }\n        return null;\n    }\n\n    public static String toMySqlString(SQLObject sqlObject, FormatOption option) {\n        return toSQLString(sqlObject, DbType.mysql, option);\n    }\n\n    public static SQLExpr toMySqlExpr(String sql) {\n        return toSQLExpr(sql, DbType.mysql);\n    }\n\n    public static String formatMySql(String sql) {\n        return format(sql, DbType.mysql);\n    }\n\n    public static String formatMySql(String sql, FormatOption option) {\n        return format(sql, DbType.mysql, option);\n    }\n\n    public static String formatOracle(String sql) {\n        return format(sql, DbType.oracle);\n    }\n\n    public static String formatOracle(String sql, FormatOption option) {\n        return format(sql, DbType.oracle, option);\n    }\n\n    public static String formatOdps(String sql) {\n        return format(sql, DbType.odps);\n    }\n\n    public static String formatPresto(String sql) {\n        return formatPresto(sql, null);\n    }\n\n    public static String formatPresto(String sql, FormatOption option) {\n        SQLParserFeature[] features = {SQLParserFeature.KeepComments,\n                SQLParserFeature.EnableSQLBinaryOpExprGroup,\n                SQLParserFeature.KeepNameQuotes};\n        return format(sql, DbType.mysql, null, option, features);\n    }\n\n    public static String formatHive(String sql) {\n        return format(sql, DbType.hive);\n    }\n\n    public static String formatOdps(String sql, FormatOption option) {\n        return format(sql, DbType.odps, option);\n    }\n\n    public static String formatHive(String sql, FormatOption option) {\n        return format(sql, DbType.hive, option);\n    }\n\n    public static String formatSQLServer(String sql) {\n        return format(sql, DbType.sqlserver);\n    }\n\n    public static String toOracleString(SQLObject sqlObject) {\n        return toOracleString(sqlObject, null);\n    }\n\n    public static String toOracleString(SQLObject sqlObject, FormatOption option) {\n        return toSQLString(sqlObject, DbType.oracle, option);\n    }\n\n    public static String toPGString(SQLObject sqlObject) {\n        return toPGString(sqlObject, null);\n    }\n\n    public static String toPGString(SQLObject sqlObject, FormatOption option) {\n        return toSQLString(sqlObject, DbType.postgresql, option);\n    }\n\n    public static String toDB2String(SQLObject sqlObject) {\n        return toDB2String(sqlObject, null);\n    }\n\n    public static String toDB2String(SQLObject sqlObject, FormatOption option) {\n        return toSQLString(sqlObject, DbType.db2, option);\n    }\n\n    public static String toSQLServerString(SQLObject sqlObject) {\n        return toSQLServerString(sqlObject, null);\n    }\n\n    public static String toSQLServerString(SQLObject sqlObject, FormatOption option) {\n        return toSQLString(sqlObject, DbType.sqlserver, option);\n    }\n\n    public static String formatPGSql(String sql, FormatOption option) {\n        return format(sql, DbType.postgresql, option);\n    }\n\n    public static SQLExpr toSQLExpr(String sql, DbType dbType) {\n        SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType);\n        SQLExpr expr = parser.expr();\n\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"illegal sql expr : \" + sql + \", \" + parser.getLexer().info());\n        }\n\n        return expr;\n    }\n\n    public static SQLExpr toSQLExpr(String sql, DbType dbType, SQLParserFeature... features) {\n        SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType, features);\n        SQLExpr expr = parser.expr();\n\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"illegal sql expr : \" + sql + \", \" + parser.getLexer().info());\n        }\n\n        return expr;\n    }\n\n    public static SQLSelectOrderByItem toOrderByItem(String sql, DbType dbType) {\n        SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType);\n        SQLSelectOrderByItem orderByItem = parser.parseSelectOrderByItem();\n\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"illegal sql expr : \" + sql + \", \" + parser.getLexer().info());\n        }\n\n        return orderByItem;\n    }\n\n    public static SQLUpdateSetItem toUpdateSetItem(String sql, DbType dbType) {\n        SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType);\n        SQLUpdateSetItem updateSetItem = parser.parseUpdateSetItem();\n\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"illegal sql expr : \" + sql + \", \" + parser.getLexer().info());\n        }\n\n        return updateSetItem;\n    }\n\n    public static SQLSelectItem toSelectItem(String sql, DbType dbType) {\n        SQLExprParser parser = SQLParserUtils.createExprParser(sql, dbType);\n        SQLSelectItem selectItem = parser.parseSelectItem();\n\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"illegal sql expr : \" + sql + \", \" + parser.getLexer().info());\n        }\n\n        return selectItem;\n    }\n\n    public static List<SQLStatement> toStatementList(String sql, DbType dbType) {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n        return parser.parseStatementList();\n    }\n\n    public static SQLExpr toSQLExpr(String sql) {\n        return toSQLExpr(sql, null);\n    }\n\n    public static String format(String sql, String dbType) {\n        return format(sql, DbType.of(dbType));\n    }\n\n    public static String format(String sql, DbType dbType) {\n        return format(sql, dbType, null, null);\n    }\n\n    public static String format(String sql, DbType dbType, FormatOption option) {\n        return format(sql, dbType, null, option);\n    }\n\n    public static String format(String sql, DbType dbType, List<Object> parameters) {\n        return format(sql, dbType, parameters, null);\n    }\n\n    public static String format(String sql, DbType dbType, List<Object> parameters, FormatOption option) {\n        return format(sql, dbType, parameters, option, FORMAT_DEFAULT_FEATURES);\n    }\n\n    public static String format(String sql, DbType dbType, List<Object> parameters, FormatOption option,\n                                SQLParserFeature[] features) {\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, features);\n            List<SQLStatement> statementList = parser.parseStatementList();\n            return toSQLString(statementList, dbType, parameters, option);\n        } catch (ParserException ex) {\n            LOG.warn(\"rowFormat error\", ex);\n            return sql;\n        }\n    }\n\n    public static String toSQLString(List<SQLStatement> statementList, DbType dbType) {\n        return toSQLString(statementList, dbType, (List<Object>) null);\n    }\n\n    public static String toSQLString(List<SQLStatement> statementList, DbType dbType, FormatOption option) {\n        return toSQLString(statementList, dbType, null, option);\n    }\n\n    public static String toSQLString(List<SQLStatement> statementList, DbType dbType, List<Object> parameters) {\n        return toSQLString(statementList, dbType, parameters, null);\n    }\n\n    public static String toSQLString(\n            List<SQLStatement> statementList,\n            DbType dbType,\n            List<Object> parameters,\n            FormatOption option\n    ) {\n        return toSQLString(statementList, dbType, parameters, option, null);\n    }\n\n    public static String toSQLString(List<SQLStatement> statementList, DbType dbType, SQLASTOutputVisitor visitor) {\n        return toSQLString(statementList, dbType, (List<Object>) null, null, visitor);\n    }\n\n    public static String toSQLString(\n            List<SQLStatement> statementList,\n            DbType dbType,\n            List<Object> parameters,\n            FormatOption option,\n            Map<String, String> tableMapping\n    ) {\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = createFormatOutputVisitor(out, statementList, dbType);\n        if (option == null) {\n            option = DEFAULT_FORMAT_OPTION;\n        }\n        visitor.setFeatures(option.features);\n        return toSQLString(statementList, dbType, parameters, tableMapping, visitor);\n    }\n\n    public static String toSQLString(\n            List<SQLStatement> statementList,\n            DbType dbType,\n            List<Object> parameters,\n            Map<String, String> tableMapping,\n            SQLASTOutputVisitor visitor\n    ) {\n        if (parameters != null) {\n            visitor.setInputParameters(parameters);\n        }\n\n        if (tableMapping != null) {\n            visitor.setTableMapping(tableMapping);\n        }\n\n        boolean printStmtSeperator;\n        if (DbType.sqlserver == dbType) {\n            printStmtSeperator = false;\n        } else {\n            printStmtSeperator = DbType.oracle != dbType;\n        }\n\n        for (int i = 0, size = statementList.size(); i < size; i++) {\n            SQLStatement stmt = statementList.get(i);\n\n            if (i > 0) {\n                SQLStatement preStmt = statementList.get(i - 1);\n                if (printStmtSeperator && !preStmt.isAfterSemi()) {\n                    visitor.print(\";\");\n                }\n\n                List<String> comments = preStmt.getAfterCommentsDirect();\n                if (comments != null) {\n                    for (int j = 0; j < comments.size(); ++j) {\n                        String comment = comments.get(j);\n                        if (j != 0) {\n                            visitor.println();\n                        }\n                        visitor.printComment(comment);\n                    }\n                }\n\n                if (printStmtSeperator) {\n                    visitor.println();\n                }\n\n                if (!(stmt instanceof SQLSetStatement)) {\n                    visitor.println();\n                }\n            }\n\n//            {\n//                List<String> comments = stmt.getBeforeCommentsDirect();\n//                if (comments != null){\n//                    for(String comment : comments) {\n//                        visitor.printComment(comment);\n//                        visitor.println();\n//                    }\n//                }\n//            }\n            stmt.accept(visitor);\n\n            if (i == size - 1) {\n                List<String> comments = stmt.getAfterCommentsDirect();\n                if (comments != null) {\n                    for (int j = 0; j < comments.size(); ++j) {\n                        String comment = comments.get(j);\n                        if (j != 0) {\n                            visitor.println();\n                        }\n                        visitor.printComment(comment);\n                    }\n                }\n            }\n        }\n\n        return visitor.toString();\n    }\n\n    public static SQLASTOutputVisitor createOutputVisitor(StringBuilder out, DbType dbType) {\n        return createFormatOutputVisitor(out, null, dbType);\n    }\n\n    public static SQLASTOutputVisitor createFormatOutputVisitor(\n            StringBuilder out,\n            List<SQLStatement> statementList,\n            DbType dbType\n    ) {\n        if (dbType == null) {\n            if (statementList != null && statementList.size() > 0) {\n                dbType = statementList.get(0).getDbType();\n            }\n\n            if (dbType == null) {\n                dbType = DbType.other;\n            }\n        }\n\n        switch (dbType) {\n            case oracle:\n            case oceanbase_oracle:\n            case polardb2:\n                if (statementList == null || statementList.size() == 1) {\n                    return new OracleOutputVisitor(out, false);\n                } else {\n                    return new OracleOutputVisitor(out, true);\n                }\n            case mysql:\n            case mariadb:\n            case tidb:\n            case polardbx:\n                return new MySqlOutputVisitor(out);\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGOutputVisitor(out);\n            case gaussdb:\n                return new GaussDbOutputVisitor(out);\n            case hologres:\n                return new HologresOutputVisitor(out);\n            case redshift:\n                return new RedshiftOutputVisitor(out);\n            case sqlserver:\n            case jtds:\n                return new SQLServerOutputVisitor(out);\n            case synapse:\n                return new SynapseOutputVisitor(out);\n            case db2:\n                return new DB2OutputVisitor(out);\n            case odps:\n                return new OdpsOutputVisitor(out);\n            case h2:\n            case lealone:\n                return new H2OutputVisitor(out);\n            case informix:\n                return new InformixOutputVisitor(out);\n            case hive:\n                return new HiveOutputVisitor(out);\n            case blink:\n                return new BlinkOutputVisitor(out);\n            case spark:\n                return new SparkOutputASTVisitor(out);\n            case databricks:\n                return new DatabricksOutputASTVisitor(out);\n            case presto:\n            case trino:\n                return new PrestoOutputVisitor(out);\n            case supersql:\n                return new SuperSqlOutputVisitor(out);\n            case athena:\n                return new AthenaOutputVisitor(out);\n            case clickhouse:\n                return new CKOutputVisitor(out);\n            case oscar:\n                return new OscarOutputVisitor(out);\n            case dm:\n                return new DmOutputVisitor(out);\n            case starrocks:\n                return new StarRocksOutputVisitor(out);\n            case bigquery:\n                return new BigQueryOutputVisitor(out);\n            case impala:\n                return new ImpalaOutputVisitor(out);\n            case doris:\n                return new DorisOutputVisitor(out);\n            case teradata:\n                return new TDOutputVisitor(out);\n            case sqlite:\n                return new SQLiteOutputVisitor(out);\n            default:\n                return new SQLASTOutputVisitor(out, dbType);\n        }\n    }\n\n    @Deprecated\n    public static SchemaStatVisitor createSchemaStatVisitor(List<SQLStatement> statementList, DbType dbType) {\n        return createSchemaStatVisitor(dbType);\n    }\n\n    public static SchemaStatVisitor createSchemaStatVisitor(DbType dbType) {\n        return createSchemaStatVisitor((SchemaRepository) null, dbType);\n    }\n\n    public static SchemaStatVisitor createSchemaStatVisitor(SchemaRepository repository) {\n        return createSchemaStatVisitor(repository, repository.getDbType());\n    }\n\n    public static SchemaStatVisitor createSchemaStatVisitor(SchemaRepository repository, DbType dbType) {\n        if (repository == null) {\n            repository = new SchemaRepository(dbType);\n        }\n\n        if (dbType == null) {\n            return new SchemaStatVisitor(repository);\n        }\n\n        switch (dbType) {\n            case oracle:\n                return new OracleSchemaStatVisitor(repository);\n            case mysql:\n            case mariadb:\n            case tidb:\n            case elastic_search:\n            case polardbx:\n                return new MySqlSchemaStatVisitor(repository);\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGSchemaStatVisitor(repository);\n            case sqlserver:\n            case jtds:\n                return new SQLServerSchemaStatVisitor(repository);\n            case synapse:\n                return new SQLServerSchemaStatVisitor(repository);\n            case db2:\n                return new DB2SchemaStatVisitor(repository);\n            case odps:\n                return new OdpsSchemaStatVisitor(repository);\n            case h2:\n            case lealone:\n                return new H2SchemaStatVisitor(repository);\n            case hive:\n                return new HiveSchemaStatVisitor(repository);\n            case spark:\n                return new SparkSchemaStatASTVisitor(repository);\n            case clickhouse:\n                return new CKStatVisitor(repository);\n            case bigquery:\n                return new BigQuerySchemaStatVisitor(repository);\n            case dm:\n                return new DmSchemaStatVisitor(repository);\n            case sqlite:\n                return new SQLiteSchemaStatVisitor(repository);\n            default:\n                return new SchemaStatVisitor(repository);\n        }\n    }\n\n    public static List<SQLStatement> parseStatements(String sql, String dbType, SQLParserFeature... features) {\n        return parseStatements(sql, DbType.of(dbType), features);\n    }\n\n    public static List<SQLStatement> parseStatements(String sql, DbType dbType, SQLParserFeature... features) {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, features);\n        List<SQLStatement> stmtList = new ArrayList<SQLStatement>();\n        parser.parseStatementList(stmtList, -1, null);\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"syntax error : \" + parser.getLexer().info());\n        }\n        return stmtList;\n    }\n\n    public static List<SQLStatement> parseStatements(String sql, DbType dbType, boolean keepComments) {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, keepComments);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"syntax error. \" + sql);\n        }\n        return stmtList;\n    }\n\n    public static List<SQLStatement> parseStatements(String sql, String dbType) {\n        return parseStatements(sql, dbType, new SQLParserFeature[0]);\n    }\n\n    public static List<SQLStatement> parseStatements(String sql, DbType dbType) {\n        return parseStatements(sql, dbType, new SQLParserFeature[0]);\n    }\n\n    public static SQLStatement parseSingleStatement(String sql, DbType dbType, boolean keepComments) {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, keepComments);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        if (stmtList.size() > 1) {\n            throw new ParserException(\"multi-statement be found.\");\n        }\n\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"syntax error. \" + sql);\n        }\n        return stmtList.get(0);\n    }\n\n    public static SQLStatement parseSingleStatement(String sql, String dbType, SQLParserFeature... features) {\n        return parseSingleStatement(sql, DbType.of(dbType), features);\n    }\n\n    public static SQLStatement parseSingleStatement(String sql, DbType dbType, SQLParserFeature... features) {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, features);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        if (stmtList.size() > 1) {\n            throw new ParserException(\"multi-statement be found.\");\n        }\n\n        if (parser.getLexer().token() != Token.EOF) {\n            throw new ParserException(\"syntax error. \" + sql);\n        }\n        return stmtList.get(0);\n    }\n\n    public static SQLStatement parseSingleMysqlStatement(String sql) {\n        return parseSingleStatement(sql, DbType.mysql, false);\n    }\n\n    /**\n     * @param columnName\n     * @param tableAlias\n     * @param pattern    if pattern is null,it will be set {%Y-%m-%d %H:%i:%s} as mysql default value and set {yyyy-mm-dd\n     *                   hh24:mi:ss} as oracle default value\n     * @param dbType     {@link DbType} if dbType is null ,it will be set the mysql as a default value\n     * @author owenludong.lud\n     */\n    public static String buildToDate(String columnName, String tableAlias, String pattern, DbType dbType) {\n        StringBuilder sql = new StringBuilder();\n        if (StringUtils.isEmpty(columnName)) {\n            return \"\";\n        }\n        if (dbType == null) {\n            dbType = DbType.mysql;\n        }\n        String formatMethod = \"\";\n        if (JdbcUtils.isMysqlDbType(dbType)) {\n            formatMethod = \"STR_TO_DATE\";\n            if (StringUtils.isEmpty(pattern)) {\n                pattern = \"%Y-%m-%d %H:%i:%s\";\n            }\n        } else if (DbType.oracle == dbType) {\n            formatMethod = \"TO_DATE\";\n            if (StringUtils.isEmpty(pattern)) {\n                pattern = \"yyyy-mm-dd hh24:mi:ss\";\n            }\n        } else {\n            return \"\";\n            // expand date's handle method for other database\n        }\n        sql.append(formatMethod).append(\"(\");\n        if (!StringUtils.isEmpty(tableAlias)) {\n            sql.append(tableAlias).append(\".\");\n        }\n        sql.append(columnName).append(\",\");\n        sql.append(\"'\");\n        sql.append(pattern);\n        sql.append(\"')\");\n        return sql.toString();\n    }\n\n    public static List<SQLExpr> split(SQLBinaryOpExpr x) {\n        return SQLBinaryOpExpr.split(x);\n    }\n\n    public static String translateOracleToMySql(String sql) {\n        List<SQLStatement> stmtList = toStatementList(sql, DbType.oracle);\n\n        StringBuilder out = new StringBuilder();\n        OracleToMySqlOutputVisitor visitor = new OracleToMySqlOutputVisitor(out, false);\n        for (int i = 0; i < stmtList.size(); ++i) {\n            stmtList.get(i).accept(visitor);\n        }\n\n        String mysqlSql = out.toString();\n        return mysqlSql;\n\n    }\n\n    public static String addCondition(String sql, String condition, DbType dbType) {\n        String result = addCondition(sql, condition, SQLBinaryOperator.BooleanAnd, false, dbType);\n        return result;\n    }\n\n    public static String addCondition(String sql, String condition, SQLBinaryOperator op, boolean left, DbType dbType) {\n        if (sql == null) {\n            throw new IllegalArgumentException(\"sql is null\");\n        }\n\n        if (condition == null) {\n            return sql;\n        }\n\n        if (op == null) {\n            op = SQLBinaryOperator.BooleanAnd;\n        }\n\n        if (op != SQLBinaryOperator.BooleanAnd //\n                && op != SQLBinaryOperator.BooleanOr) {\n            throw new IllegalArgumentException(\"add condition not support : \" + op);\n        }\n\n        List<SQLStatement> stmtList = parseStatements(sql, dbType);\n\n        if (stmtList.isEmpty()) {\n            throw new IllegalArgumentException(\"not support empty-statement :\" + sql);\n        }\n\n        if (stmtList.size() > 1) {\n            throw new IllegalArgumentException(\"not support multi-statement :\" + sql);\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n\n        SQLExpr conditionExpr = toSQLExpr(condition, dbType);\n\n        addCondition(stmt, op, conditionExpr, left);\n\n        return toSQLString(stmt, dbType);\n    }\n\n    public static void addCondition(SQLStatement stmt, SQLBinaryOperator op, SQLExpr condition, boolean left) {\n        if (stmt instanceof SQLSelectStatement) {\n            SQLSelectQuery query = ((SQLSelectStatement) stmt).getSelect().getQuery();\n            if (query instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n                SQLExpr newCondition = buildCondition(op, condition, left, queryBlock.getWhere());\n                queryBlock.setWhere(newCondition);\n            } else {\n                throw new IllegalArgumentException(\"add condition not support \" + stmt.getClass().getName());\n            }\n\n            return;\n        }\n\n        if (stmt instanceof SQLDeleteStatement) {\n            SQLDeleteStatement delete = (SQLDeleteStatement) stmt;\n\n            SQLExpr newCondition = buildCondition(op, condition, left, delete.getWhere());\n            delete.setWhere(newCondition);\n\n            return;\n        }\n\n        if (stmt instanceof SQLUpdateStatement) {\n            SQLUpdateStatement update = (SQLUpdateStatement) stmt;\n\n            SQLExpr newCondition = buildCondition(op, condition, left, update.getWhere());\n            update.setWhere(newCondition);\n\n            return;\n        }\n\n        throw new IllegalArgumentException(\"add condition not support \" + stmt.getClass().getName());\n    }\n\n    public static SQLExpr buildCondition(SQLBinaryOperator op, SQLExpr condition, boolean left, SQLExpr where) {\n        if (where == null) {\n            return condition;\n        }\n\n        SQLBinaryOpExpr newCondition;\n        if (left) {\n            newCondition = new SQLBinaryOpExpr(condition, op, where);\n        } else {\n            newCondition = new SQLBinaryOpExpr(where, op, condition);\n        }\n        return newCondition;\n    }\n\n    public static String addSelectItem(String selectSql, String expr, String alias, DbType dbType) {\n        return addSelectItem(selectSql, expr, alias, false, dbType);\n    }\n\n    public static void acceptBooleanOr(String sql, DbType dbType, Consumer<SQLBinaryOpExprGroup> consumer) {\n        acceptBinaryOpExprGroup(sql, dbType, consumer, e -> e.getOperator() == SQLBinaryOperator.BooleanOr);\n    }\n\n    public static void acceptBinaryOpExprGroup(String sql,\n                                               DbType dbType,\n                                               Consumer<SQLBinaryOpExprGroup> consumer,\n                                               Predicate<SQLBinaryOpExprGroup> filter) {\n        if (sql == null || sql.isEmpty()) {\n            return;\n        }\n\n        List<SQLStatement> stmtList = new ArrayList<>();\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableMultiUnion, SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n            parser.parseStatementList(stmtList, -1, null);\n        } catch (Exception ignored) {\n            return;\n        }\n\n        SQLASTVisitor visitor;\n        switch (dbType) {\n            case odps:\n                visitor = new OdpsASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLBinaryOpExprGroup x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return super.visit(x);\n                    }\n                };\n                break;\n            default:\n                visitor = new SQLASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLBinaryOpExprGroup x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return super.visit(x);\n                    }\n                };\n                break;\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n    }\n\n    public static void acceptBinaryOpExpr(String sql,\n                                          DbType dbType,\n                                          Consumer<SQLBinaryOpExpr> consumer,\n                                          Predicate<SQLBinaryOpExpr> filter) {\n        if (sql == null || sql.isEmpty()) {\n            return;\n        }\n\n        List<SQLStatement> stmtList = new ArrayList<>();\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableMultiUnion, SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n            parser.parseStatementList(stmtList, -1, null);\n        } catch (Exception ignored) {\n            return;\n        }\n\n        SQLASTVisitor visitor;\n        switch (dbType) {\n            case odps:\n                visitor = new OdpsASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLBinaryOpExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return super.visit(x);\n                    }\n                };\n                break;\n            default:\n                visitor = new SQLASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLBinaryOpExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return super.visit(x);\n                    }\n                };\n                break;\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n    }\n\n    public static void acceptTableSource(String sql,\n                                         DbType dbType,\n                                         Consumer<SQLTableSource> consumer,\n                                         Predicate<SQLTableSource> filter) {\n        if (sql == null || sql.isEmpty()) {\n            return;\n        }\n\n        List<SQLStatement> stmtList = new ArrayList<>();\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableMultiUnion, SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n            parser.parseStatementList(stmtList, -1, null);\n        } catch (Exception ignored) {\n            return;\n        }\n\n        SQLASTVisitor visitor;\n        switch (dbType) {\n            case odps:\n                visitor = new OdpsASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLExprTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLJoinTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLSubqueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnionQueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLValuesTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnnestTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLWithSubqueryClause.Entry x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLLateralViewTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLAdhocTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            case mysql:\n                visitor = new MySqlASTVisitorAdapter() {\n                    public boolean visit(SQLExprTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLJoinTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLSubqueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnionQueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLValuesTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnnestTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLWithSubqueryClause.Entry x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLLateralViewTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLAdhocTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(MySqlUpdateTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            case oracle:\n                visitor = new OracleASTVisitorAdapter() {\n                    public boolean visit(SQLExprTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLSubqueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLJoinTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnionQueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLValuesTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnnestTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLWithSubqueryClause.Entry x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLLateralViewTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLAdhocTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(OracleSelectTableReference x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(OracleWithSubqueryEntry x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(OracleSelectSubqueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            default:\n                visitor = new SQLASTVisitorAdapter() {\n                    public boolean visit(SQLExprTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLJoinTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLSubqueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLValuesTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnnestTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLUnionQueryTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLWithSubqueryClause.Entry x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLLateralViewTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLAdhocTableSource x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n    }\n\n    public static void acceptSelectQueryBlock(String sql,\n                                              DbType dbType,\n                                              Consumer<SQLSelectQueryBlock> consumer,\n                                              Predicate<SQLSelectQueryBlock> filter) {\n        if (sql == null || sql.isEmpty()) {\n            return;\n        }\n\n        List<SQLStatement> stmtList = new ArrayList<>();\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableMultiUnion, SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n            parser.parseStatementList(stmtList, -1, null);\n        } catch (Exception ignored) {\n            return;\n        }\n\n        SQLASTVisitor visitor;\n        switch (dbType) {\n            case odps:\n                visitor = new OdpsASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLSelectQueryBlock x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(OdpsSelectQueryBlock x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            case mysql:\n                visitor = new MySqlASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLSelectQueryBlock x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(MySqlSelectQueryBlock x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            default:\n                visitor = new SQLASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLSelectQueryBlock x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n    }\n\n    public static void acceptAggregateFunction(String sql,\n                                               DbType dbType,\n                                               Consumer<SQLAggregateExpr> consumer,\n                                               Predicate<SQLAggregateExpr> filter) {\n        if (sql == null || sql.isEmpty()) {\n            return;\n        }\n\n        List<SQLStatement> stmtList = new ArrayList<>();\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableMultiUnion, SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n            parser.parseStatementList(stmtList, -1, null);\n        } catch (Exception ignored) {\n            return;\n        }\n\n        SQLASTVisitor visitor;\n        switch (dbType) {\n            case odps:\n                visitor = new OdpsASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            case mysql:\n                visitor = new MySqlASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            case oracle:\n                visitor = new OracleASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            default:\n                visitor = new SQLASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n    }\n\n    public static void acceptFunction(String sql,\n                                      DbType dbType,\n                                      Consumer<SQLMethodInvokeExpr> consumer,\n                                      Predicate<SQLMethodInvokeExpr> filter) {\n        if (sql == null || sql.isEmpty()) {\n            return;\n        }\n\n        List<SQLStatement> stmtList = new ArrayList<>();\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableMultiUnion, SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n            parser.parseStatementList(stmtList, -1, null);\n        } catch (Exception ignored) {\n            return;\n        }\n\n        SQLASTVisitor visitor;\n        switch (dbType) {\n            case odps:\n                visitor = new OdpsASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLMethodInvokeExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            case mysql:\n                visitor = new MySqlASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLMethodInvokeExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            case oracle:\n                visitor = new OracleASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLMethodInvokeExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n            default:\n                visitor = new SQLASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLAggregateExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n\n                    @Override\n                    public boolean visit(SQLMethodInvokeExpr x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n    }\n\n    public static void acceptInsertInto(String sql,\n                                        DbType dbType,\n                                        Consumer<SQLInsertInto> consumer,\n                                        Predicate<SQLInsertInto> filter) {\n        if (sql == null || sql.isEmpty()) {\n            return;\n        }\n\n        List<SQLStatement> stmtList = new ArrayList<>();\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableMultiUnion, SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n            parser.parseStatementList(stmtList, -1, null);\n        } catch (Exception ignored) {\n            return;\n        }\n\n        SQLASTVisitor visitor;\n        switch (dbType) {\n            case odps:\n                visitor = new OdpsASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLSelectStatement x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(SQLCreateTableStatement x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(OdpsCreateTableStatement x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(SQLSelectQueryBlock x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(OdpsSelectQueryBlock x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(SQLInsertStatement x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(HiveInsertStatement x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(HiveInsert x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return false;\n                    }\n                };\n                break;\n            case hive:\n                visitor = new HiveASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLSelectStatement x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(SQLCreateTableStatement x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(SQLInsertStatement x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(HiveInsertStatement x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(HiveInsert x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return false;\n                    }\n                };\n                break;\n            default:\n                visitor = new SQLASTVisitorAdapter() {\n                    @Override\n                    public boolean visit(SQLSelectStatement x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(SQLCreateTableStatement x) {\n                        return false;\n                    }\n\n                    @Override\n                    public boolean visit(SQLInsertStatement x) {\n                        if (filter == null || filter.test(x)) {\n                            consumer.accept(x);\n                        }\n                        return true;\n                    }\n                };\n                break;\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n    }\n\n    public static String addSelectItem(String selectSql, String expr, String alias, boolean first, DbType dbType) {\n        List<SQLStatement> stmtList = parseStatements(selectSql, dbType);\n\n        if (stmtList.isEmpty()) {\n            throw new IllegalArgumentException(\"not support empty-statement :\" + selectSql);\n        }\n\n        if (stmtList.size() > 1) {\n            throw new IllegalArgumentException(\"not support multi-statement :\" + selectSql);\n        }\n\n        SQLStatement stmt = stmtList.get(0);\n\n        SQLExpr columnExpr = toSQLExpr(expr, dbType);\n\n        addSelectItem(stmt, columnExpr, alias, first);\n\n        return toSQLString(stmt, dbType);\n    }\n\n    public static void addSelectItem(SQLStatement stmt, SQLExpr expr, String alias, boolean first) {\n        if (expr == null) {\n            return;\n        }\n\n        if (stmt instanceof SQLSelectStatement) {\n            SQLSelectQuery query = ((SQLSelectStatement) stmt).getSelect().getQuery();\n            if (query instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n                addSelectItem(queryBlock, expr, alias, first);\n            } else {\n                throw new IllegalArgumentException(\"add condition not support \" + stmt.getClass().getName());\n            }\n\n            return;\n        }\n\n        throw new IllegalArgumentException(\"add selectItem not support \" + stmt.getClass().getName());\n    }\n\n    public static void addSelectItem(SQLSelectQueryBlock queryBlock, SQLExpr expr, String alias, boolean first) {\n        SQLSelectItem selectItem = new SQLSelectItem(expr, alias);\n        queryBlock.getSelectList().add(selectItem);\n        selectItem.setParent(selectItem);\n    }\n\n    public static class FormatOption {\n        private int features = VisitorFeature.of(\n                VisitorFeature.OutputUCase,\n                VisitorFeature.OutputPrettyFormat\n        );\n\n        public FormatOption() {\n        }\n\n        public FormatOption(VisitorFeature... features) {\n            this.features = VisitorFeature.of(features);\n        }\n\n        public FormatOption(boolean ucase) {\n            this(ucase, true);\n        }\n\n        public FormatOption(boolean ucase, boolean prettyFormat) {\n            this(ucase, prettyFormat, false);\n        }\n\n        public FormatOption(boolean ucase, boolean prettyFormat, boolean parameterized) {\n            this.features = VisitorFeature.config(this.features, VisitorFeature.OutputUCase, ucase);\n            this.features = VisitorFeature.config(this.features, VisitorFeature.OutputPrettyFormat, prettyFormat);\n            this.features = VisitorFeature.config(this.features, VisitorFeature.OutputParameterized, parameterized);\n        }\n\n        public boolean isDesensitize() {\n            return isEnabled(VisitorFeature.OutputDesensitize);\n        }\n\n        public void setDesensitize(boolean val) {\n            config(VisitorFeature.OutputDesensitize, val);\n        }\n\n        public boolean isUppCase() {\n            return isEnabled(VisitorFeature.OutputUCase);\n        }\n\n        public void setUppCase(boolean val) {\n            config(VisitorFeature.OutputUCase, val);\n        }\n\n        public boolean isPrettyFormat() {\n            return isEnabled(VisitorFeature.OutputPrettyFormat);\n        }\n\n        public void setPrettyFormat(boolean prettyFormat) {\n            config(VisitorFeature.OutputPrettyFormat, prettyFormat);\n        }\n\n        public boolean isParameterized() {\n            return isEnabled(VisitorFeature.OutputParameterized);\n        }\n\n        public void setParameterized(boolean parameterized) {\n            config(VisitorFeature.OutputParameterized, parameterized);\n        }\n\n        public void config(VisitorFeature feature, boolean state) {\n            features = VisitorFeature.config(features, feature, state);\n        }\n\n        public void configTo(SQLASTOutputVisitor v) {\n            v.setFeatures(features);\n        }\n\n        public final boolean isEnabled(VisitorFeature feature) {\n            return VisitorFeature.isEnabled(this.features, feature);\n        }\n    }\n\n    public static String refactor(String sql, DbType dbType, Map<String, String> tableMapping) {\n        List<SQLStatement> stmtList = parseStatements(sql, dbType);\n        return SQLUtils.toSQLString(stmtList, dbType, null, null, tableMapping);\n    }\n\n    public static long hash(String sql, DbType dbType) {\n        Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n\n        StringBuilder buf = new StringBuilder(sql.length());\n\n        for (; ; ) {\n            lexer.nextToken();\n\n            Token token = lexer.token();\n            if (token == Token.EOF) {\n                break;\n            }\n\n            if (token == Token.ERROR) {\n                return Utils.fnv_64(sql);\n            }\n\n            if (buf.length() != 0) {\n                // skip\n            }\n        }\n\n        return buf.hashCode();\n    }\n\n    public static SQLExpr not(SQLExpr expr) {\n        if (expr instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr;\n            SQLBinaryOperator op = binaryOpExpr.getOperator();\n\n            SQLBinaryOperator notOp = null;\n\n            switch (op) {\n                case Equality:\n                    notOp = SQLBinaryOperator.LessThanOrGreater;\n                    break;\n                case LessThanOrEqualOrGreaterThan:\n                    notOp = SQLBinaryOperator.Equality;\n                    break;\n                case LessThan:\n                    notOp = SQLBinaryOperator.GreaterThanOrEqual;\n                    break;\n                case LessThanOrEqual:\n                    notOp = SQLBinaryOperator.GreaterThan;\n                    break;\n                case GreaterThan:\n                    notOp = SQLBinaryOperator.LessThanOrEqual;\n                    break;\n                case GreaterThanOrEqual:\n                    notOp = SQLBinaryOperator.LessThan;\n                    break;\n                case Is:\n                    notOp = SQLBinaryOperator.IsNot;\n                    break;\n                case IsNot:\n                    notOp = SQLBinaryOperator.Is;\n                    break;\n                default:\n                    break;\n            }\n\n            if (notOp != null) {\n                return new SQLBinaryOpExpr(binaryOpExpr.getLeft(), notOp, binaryOpExpr.getRight());\n            }\n        }\n\n        if (expr instanceof SQLInListExpr) {\n            SQLInListExpr inListExpr = (SQLInListExpr) expr;\n\n            SQLInListExpr newInListExpr = new SQLInListExpr(inListExpr);\n            newInListExpr.getTargetList().addAll(inListExpr.getTargetList());\n            newInListExpr.setNot(!inListExpr.isNot());\n            return newInListExpr;\n        }\n\n        return new SQLUnaryExpr(SQLUnaryOperator.Not, expr);\n    }\n\n    public static String normalize(String name) {\n        return normalize(name, null);\n    }\n\n    public static String normalize(String name, boolean isTrimmed) {\n        return _normalize(name, null, false, isTrimmed);\n    }\n\n    public static String normalize(String name, DbType dbType) {\n        return _normalize(name, dbType, false);\n    }\n\n    private static String _normalize(String name, DbType dbType, boolean isForced) {\n        return _normalize(name, dbType, isForced, true);\n    }\n\n    private static String _normalize(String name, DbType dbType, boolean isForced, boolean isTrimmed) {\n        if (name == null) {\n            return null;\n        }\n\n        if (name.length() > 2) {\n            char c0 = name.charAt(0);\n            char x0 = name.charAt(name.length() - 1);\n            if ((c0 == '[' && x0 == ']') || (c0 == '\"' && x0 == '\"') || (c0 == '`' && x0 == '`') || (c0 == '\\'' && x0 == '\\'')) {\n                String normalizeName = name.substring(1, name.length() - 1);\n\n                if (isTrimmed) {\n                    normalizeName = normalizeName.trim();\n                }\n\n                int dotIndex = normalizeName.indexOf('.');\n                if (dotIndex > 0) {\n                    if (c0 == '`') {\n                        normalizeName = normalizeName.replaceAll(\"`\\\\.`\", \".\");\n                    }\n                }\n\n                if (!isForced) {\n                    if (DbType.oracle == dbType) {\n                        if (OracleUtils.isKeyword(normalizeName)) {\n                            return name;\n                        }\n                    } else if (JdbcUtils.isMysqlDbType(dbType)) {\n                        if (MySqlUtils.isKeyword(normalizeName)) {\n                            return name;\n                        }\n                    } else if (DbType.postgresql == dbType || DbType.db2 == dbType) {\n                        if (PGUtils.isKeyword(normalizeName)) {\n                            return name;\n                        }\n                    }\n                }\n\n                return normalizeName;\n            }\n        }\n\n        return name;\n    }\n\n    public static String forcedNormalize(String name, DbType dbType) {\n        return _normalize(name, dbType, true);\n    }\n\n    public static boolean nameEquals(SQLName a, SQLName b) {\n        if (a == b) {\n            return true;\n        }\n\n        if (a == null || b == null) {\n            return false;\n        }\n\n        return a.nameHashCode64() == b.nameHashCode64();\n    }\n\n    public static boolean nameEquals(String a, String b) {\n        if (a == b) {\n            return true;\n        }\n\n        if (a == null || b == null) {\n            return false;\n        }\n\n        if (a.equalsIgnoreCase(b)) {\n            return true;\n        }\n\n        String normalize_a = normalize(a);\n        String normalize_b = normalize(b);\n\n        return normalize_a.equalsIgnoreCase(normalize_b);\n    }\n\n    public static boolean isValue(SQLExpr expr) {\n        if (expr instanceof SQLLiteralExpr) {\n            return true;\n        }\n\n        if (expr instanceof SQLVariantRefExpr) {\n            return true;\n        }\n\n        if (expr instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr;\n            SQLBinaryOperator op = binaryOpExpr.getOperator();\n            if (op == SQLBinaryOperator.Add\n                    || op == SQLBinaryOperator.Subtract\n                    || op == SQLBinaryOperator.Multiply) {\n                return isValue(binaryOpExpr.getLeft())\n                        && isValue(binaryOpExpr.getRight());\n            }\n        }\n\n        return false;\n    }\n\n    public static boolean replaceInParent(SQLDataType expr, SQLDataType target) {\n        SQLObject parent = expr.getParent();\n        if (parent instanceof SQLColumnDefinition) {\n            ((SQLColumnDefinition) parent).setDataType(target);\n        } else if (parent instanceof SQLCastExpr) {\n            ((SQLCastExpr) parent).setDataType(target);\n        } else {\n            return false;\n        }\n        return true;\n    }\n\n    public static boolean replaceInParent(SQLExpr expr, SQLExpr target) {\n        if (expr == null) {\n            return false;\n        }\n\n        SQLObject parent = expr.getParent();\n\n        if (parent instanceof SQLReplaceable) {\n            return ((SQLReplaceable) parent).replace(expr, target);\n        }\n\n        return false;\n    }\n\n    public static boolean replaceInParent(SQLSelect cmp, SQLSelect dest) {\n        SQLObject parent = cmp.getParent();\n        if (parent instanceof SQLSelectStatement) {\n            ((SQLSelectStatement) parent).setSelect(dest);\n            return true;\n        } else if (parent instanceof SQLSubqueryTableSource) {\n            ((SQLSubqueryTableSource) parent).setSelect(dest);\n            return true;\n        } else if (parent instanceof SQLInsertStatement) {\n            ((SQLInsertStatement) parent).setQuery(dest);\n            return true;\n        }\n        return false;\n    }\n\n    public static boolean replaceInParent(SQLTableSource cmp, SQLTableSource dest) {\n        if (cmp == null) {\n            return false;\n        }\n\n        SQLObject parent = cmp.getParent();\n\n        if (parent instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;\n            if (queryBlock.getFrom() == cmp) {\n                queryBlock.setFrom(dest);\n                return true;\n            }\n        }\n\n        if (parent instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) parent;\n            return join.replace(cmp, dest);\n        }\n\n        return false;\n    }\n\n    public static boolean replaceInParent(SQLSelectQuery cmp, SQLSelectQuery dest) {\n        if (cmp == null) {\n            return false;\n        }\n\n        SQLObject parent = cmp.getParent();\n        if (parent == null) {\n            return false;\n        }\n\n        if (parent instanceof SQLUnionQuery) {\n            return ((SQLUnionQuery) parent).replace(cmp, dest);\n        }\n\n        if (parent instanceof SQLSelect) {\n            return ((SQLSelect) parent).replace(cmp, dest);\n        }\n        return false;\n    }\n\n    public static boolean replaceInParent(SQLStatement cmp, SQLStatement dest) {\n        if (cmp == null) {\n            return false;\n        }\n\n        SQLObject parent = cmp.getParent();\n        if (parent == null) {\n            return false;\n        }\n\n        if (parent instanceof SQLBlockStatement) {\n            return ((SQLBlockStatement) parent).replace(cmp, dest);\n        }\n\n        return false;\n    }\n\n    public static String desensitizeTable(String tableName) {\n        if (tableName == null) {\n            return null;\n        }\n\n        tableName = normalize(tableName);\n        long hash = FnvHash.hashCode64(tableName);\n        return Utils.hex_t(hash);\n    }\n\n    /**\n     * 重新排序建表语句，解决建表语句的依赖关系\n     *\n     * @param sql\n     * @param dbType\n     */\n    public static String sort(String sql, DbType dbType) {\n        List stmtList = SQLUtils.parseStatements(sql, DbType.oracle);\n        SQLCreateTableStatement.sort(stmtList);\n        return SQLUtils.toSQLString(stmtList, dbType);\n    }\n\n    /**\n     * @param query\n     * @param dbType\n     * @return 0：sql.toString, 1:\n     */\n    public static Object[] clearLimit(String query, DbType dbType) {\n        List stmtList = SQLUtils.parseStatements(query, dbType);\n\n        SQLLimit limit = null;\n\n        SQLStatement statement = (SQLStatement) stmtList.get(0);\n\n        if (statement instanceof SQLSelectStatement) {\n            SQLSelectStatement selectStatement = (SQLSelectStatement) statement;\n\n            if (selectStatement.getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n                limit = clearLimit(selectStatement.getSelect().getQueryBlock());\n            }\n        }\n\n        if (statement instanceof SQLDumpStatement) {\n            SQLDumpStatement dumpStatement = (SQLDumpStatement) statement;\n\n            if (dumpStatement.getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n                limit = clearLimit(dumpStatement.getSelect().getQueryBlock());\n            }\n        }\n\n        if (statement instanceof MySqlSelectIntoStatement) {\n            MySqlSelectIntoStatement sqlSelectIntoStatement = (MySqlSelectIntoStatement) statement;\n            limit = clearLimit(sqlSelectIntoStatement.getSelect().getQueryBlock());\n        }\n\n        if (statement instanceof MySqlInsertStatement) {\n            MySqlInsertStatement insertStatement = (MySqlInsertStatement) statement;\n            limit = clearLimit(insertStatement.getQuery().getQueryBlock());\n        }\n\n        String sql = SQLUtils.toSQLString(stmtList, dbType);\n        return new Object[]{sql, limit};\n    }\n\n    private static SQLLimit clearLimit(SQLSelectQueryBlock queryBlock) {\n        if (queryBlock == null) {\n            return null;\n        }\n\n        SQLLimit limit = queryBlock.getLimit();\n        queryBlock.setLimit(null);\n        return limit;\n    }\n\n    public static SQLLimit getLimit(SQLStatement statement, DbType dbType) {\n        if (statement instanceof SQLSelectStatement) {\n            SQLSelectQueryBlock queryBlock = ((SQLSelectStatement) statement).getSelect().getQueryBlock();\n            return queryBlock == null ? null : queryBlock.getLimit();\n        } else if (statement instanceof SQLDumpStatement) {\n            SQLSelectQueryBlock queryBlock = ((SQLDumpStatement) statement).getSelect().getQueryBlock();\n            return queryBlock == null ? null : queryBlock.getLimit();\n        } else if (statement instanceof MySqlSelectIntoStatement) {\n            SQLSelectQueryBlock queryBlock = ((MySqlSelectIntoStatement) statement).getSelect().getQueryBlock();\n            return queryBlock == null ? null : queryBlock.getLimit();\n        } else if (statement instanceof MySqlInsertStatement) {\n            SQLSelect select = ((MySqlInsertStatement) statement).getQuery();\n\n            if (select == null) {\n                return null;\n            }\n\n            if (select.getQuery() instanceof SQLUnionQuery) {\n                return ((SQLUnionQuery) select.getQuery()).getLimit();\n            } else {\n                return select.getQueryBlock().getLimit();\n            }\n\n        } else {\n            return null;\n        }\n    }\n\n    public static SQLLimit getLimit(String query, DbType dbType) {\n        List stmtList = SQLUtils.parseStatements(query, dbType);\n        SQLStatement statement = (SQLStatement) stmtList.get(0);\n        return getLimit(statement, dbType);\n    }\n\n    public static String convertTimeZone(String sql, TimeZone from, TimeZone to) {\n        SQLStatement statement = parseSingleMysqlStatement(sql);\n        statement.accept(new TimeZoneVisitor(from, to));\n        return statement.toString();\n    }\n\n    public static SQLStatement convertTimeZone(SQLStatement stmt, TimeZone from, TimeZone to) {\n        stmt.accept(new TimeZoneVisitor(from, to));\n        return stmt;\n    }\n\n    public static List<SQLInsertStatement> splitInsertValues(DbType dbType, String insertSql, int size) {\n        SQLStatement statement = SQLUtils.parseStatements(insertSql, dbType, false).get(0);\n        if (!(statement instanceof SQLInsertStatement)) {\n            throw new IllegalArgumentException(\"The SQL must be insert statement.\");\n        }\n\n        List<SQLInsertStatement> insertLists = new ArrayList<SQLInsertStatement>();\n\n        SQLInsertStatement insertStatement = (SQLInsertStatement) statement;\n\n        List<SQLInsertStatement.ValuesClause> valuesList = insertStatement.getValuesList();\n\n        int totalSize = valuesList.size();\n        if (totalSize <= size) {\n            insertLists.add(insertStatement);\n        } else {\n            SQLInsertStatement insertTemplate = new SQLInsertStatement();\n\n            insertStatement.cloneTo(insertTemplate);\n            insertTemplate.getValuesList().clear();\n\n            int batchCount = 0;\n            if (totalSize % size == 0) {\n                batchCount = totalSize / size;\n            } else {\n                batchCount = (totalSize / size) + 1;\n            }\n            for (int i = 0; i < batchCount; i++) {\n                SQLInsertStatement subInsertStatement = new SQLInsertStatement();\n                insertTemplate.cloneTo(subInsertStatement);\n\n                int fromIndex = i * size;\n                int toIndex = (fromIndex + size) > totalSize ? totalSize : fromIndex + size;\n                List<SQLInsertStatement.ValuesClause> subValuesList = valuesList.subList(fromIndex, toIndex);\n                subInsertStatement.getValuesList().addAll(subValuesList);\n\n                insertLists.add(subInsertStatement);\n            }\n        }\n\n        return insertLists;\n    }\n\n    public static boolean isQuoteChar(char c) {\n        return c == '`' || c == '\\'' || c == '\"';\n    }\n\n    public static String removeQuote(String str) {\n        return str.replace(\"`\", \"\").replace(\"'\", \"\").replace(\"\\\"\", \"\");\n    }\n\n    /**\n     * TokenInfo class to hold token, its corresponding string value, and position\n     */\n    public static class TokenInfo {\n        private final Token token;\n        private final String stringVal;\n        private final int pos;\n\n        public TokenInfo(Token token, String stringVal, int pos) {\n            this.token = token;\n            this.stringVal = stringVal;\n            this.pos = pos;\n        }\n\n        public Token getToken() {\n            return token;\n        }\n\n        public String getStringVal() {\n            return stringVal;\n        }\n\n        public int getPos() {\n            return pos;\n        }\n\n        @Override\n        public String toString() {\n            if (stringVal == null) {\n                return token + \"@\" + pos;\n            }\n            return token + \"(\" + stringVal + \")@\" + pos;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            TokenInfo tokenInfo = (TokenInfo) o;\n            if (token != tokenInfo.token) {\n                return false;\n            }\n            if (pos != tokenInfo.pos) {\n                return false;\n            }\n            return stringVal != null ? stringVal.equals(tokenInfo.stringVal) : tokenInfo.stringVal == null;\n        }\n\n        @Override\n        public int hashCode() {\n            int result = token != null ? token.hashCode() : 0;\n            result = 31 * result + (stringVal != null ? stringVal.hashCode() : 0);\n            result = 31 * result + pos;\n            return result;\n        }\n    }\n\n    /**\n     * Get all tokens from SQL parsing based on dialect type, including their string values\n     *\n     * @param sql    SQL statement to parse\n     * @param dbType Database type (dialect)\n     * @return List of TokenInfo objects containing token and corresponding stringVal pairs (excluding comments)\n     */\n    public static List<TokenInfo> getAllTokens(String sql, DbType dbType) {\n        return getAllTokens(sql, dbType, false);\n    }\n\n    /**\n     * Get all tokens from SQL parsing based on dialect type, including their string values\n     *\n     * @param sql    SQL statement to parse\n     * @param dbType Database type (dialect)\n     * @param keepComments Whether to keep comment tokens (LINE_COMMENT, MULTI_LINE_COMMENT, HINT)\n     * @return List of TokenInfo objects containing token and corresponding stringVal pairs\n     */\n    public static List<TokenInfo> getAllTokens(String sql, DbType dbType, boolean keepComments) {\n        if (sql == null || sql.isEmpty()) {\n            return new ArrayList<TokenInfo>();\n        }\n\n        List<TokenInfo> tokens = new ArrayList<TokenInfo>();\n        Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n\n        // Configure lexer to keep or skip comments\n        lexer.config(SQLParserFeature.SkipComments, !keepComments);\n        lexer.config(SQLParserFeature.KeepComments, keepComments);\n\n        for (; ; ) {\n            lexer.nextToken();\n            Token token = lexer.token();\n\n            // Filter out comment tokens if keepComments is false\n            if (!keepComments && (token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT || token == Token.HINT)) {\n                continue;\n            }\n\n            // Create and add token info\n            tokens.add(createTokenInfo(token, lexer));\n\n            // Exit on EOF or ERROR\n            if (token == Token.EOF || token == Token.ERROR) {\n                break;\n            }\n        }\n\n        return tokens;\n    }\n\n    /**\n     * Create a TokenInfo object from the current lexer state\n     */\n    private static TokenInfo createTokenInfo(Token token, Lexer lexer) {\n        int pos = lexer.pos();\n        String stringVal;\n\n        // Get stringVal - use numberString() for numeric literals, stringVal() for others\n        if (token == Token.LITERAL_INT || token == Token.LITERAL_FLOAT || token == Token.LITERAL_HEX) {\n            stringVal = lexer.numberString();\n        } else {\n            stringVal = lexer.stringVal();\n        }\n\n        // Create a defensive copy to prevent mutation\n        if (stringVal != null) {\n            stringVal = new String(stringVal.toCharArray());\n        }\n\n        return new TokenInfo(token, stringVal, pos);\n    }\n\n    /**\n     * Get all tokens from SQL parsing based on dialect type (overloaded method with String dbType)\n     *\n     * @param sql    SQL statement to parse\n     * @param dbType Database type string (will be converted to DbType)\n     * @return List of TokenInfo objects containing token and corresponding stringVal pairs\n     */\n    public static List<TokenInfo> getAllTokens(String sql, String dbType) {\n        return getAllTokens(sql, DbType.of(dbType), false);\n    }\n\n    /**\n     * Get all tokens from SQL parsing based on dialect type (overloaded method with String dbType)\n     *\n     * @param sql    SQL statement to parse\n     * @param dbType Database type string (will be converted to DbType)\n     * @param keepComments Whether to keep comment tokens (LINE_COMMENT, MULTI_LINE_COMMENT, HINT)\n     * @return List of TokenInfo objects containing token and corresponding stringVal pairs\n     */\n    public static List<TokenInfo> getAllTokens(String sql, String dbType, boolean keepComments) {\n        return getAllTokens(sql, DbType.of(dbType), keepComments);\n    }\n\n    /**\n     * Calculate Levenshtein distance between two SQL statements based on their token sequences.\n     * For IDENTIFIER, PROPERTY, and LITERAL_INT tokens, the stringVal must also match for tokens to be considered equal.\n     *\n     * @param sql1 First SQL statement\n     * @param dbType1 Database type for first SQL\n     * @param sql2 Second SQL statement\n     * @param dbType2 Database type for second SQL\n     * @return Levenshtein distance between the two token sequences\n     */\n    public static int calculateTokenLevenshteinDistance(String sql1, DbType dbType1, String sql2, DbType dbType2) {\n        // Step 1: Parse both SQLs and get their token lists\n        List<TokenInfo> tokens1 = getAllTokens(sql1, dbType1);\n        List<TokenInfo> tokens2 = getAllTokens(sql2, dbType2);\n\n        // Step 2: Calculate Levenshtein distance based on tokens\n        return calculateLevenshteinDistance(tokens1, tokens2);\n    }\n\n    /**\n     * Calculate Levenshtein distance between two token sequences\n     */\n    private static int calculateLevenshteinDistance(List<TokenInfo> tokens1, List<TokenInfo> tokens2) {\n        int len1 = tokens1.size();\n        int len2 = tokens2.size();\n\n        // Create DP matrix\n        int[][] dp = new int[len1 + 1][len2 + 1];\n\n        // Initialize base cases\n        for (int i = 0; i <= len1; i++) {\n            dp[i][0] = i;\n        }\n        for (int j = 0; j <= len2; j++) {\n            dp[0][j] = j;\n        }\n\n        // Fill DP matrix\n        for (int i = 1; i <= len1; i++) {\n            for (int j = 1; j <= len2; j++) {\n                TokenInfo tokenInfo1 = tokens1.get(i - 1);\n                TokenInfo tokenInfo2 = tokens2.get(j - 1);\n\n                int cost;\n                if (areTokensEqual(tokenInfo1, tokenInfo2)) {\n                    cost = 0; // Tokens are equal\n                } else {\n                    cost = 1; // Tokens are different\n                }\n\n                dp[i][j] = Math.min(\n                        Math.min(\n                                dp[i - 1][j] + 1,      // Deletion\n                                dp[i][j - 1] + 1       // Insertion\n                        ),\n                        dp[i - 1][j - 1] + cost        // Substitution\n                );\n            }\n        }\n\n        return dp[len1][len2];\n    }\n\n    /**\n     * Check if two tokens are equal.\n     * For IDENTIFIER, PROPERTY, and LITERAL_INT tokens, stringVal must also match.\n     */\n    private static boolean areTokensEqual(\n            TokenInfo tokenInfo1,\n            TokenInfo tokenInfo2\n    ) {\n        // First check if token types are the same\n        if (tokenInfo1.getToken() != tokenInfo2.getToken()) {\n            return false;\n        }\n\n        // For IDENTIFIER, PROPERTY, and LITERAL_INT tokens, check stringVal\n        if (tokenInfo1.getToken() == Token.IDENTIFIER\n                || tokenInfo1.getToken() == Token.LITERAL_INT\n                || tokenInfo1.getToken() == Token.LITERAL_FLOAT\n                || tokenInfo1.getToken() == Token.LITERAL_CHARS\n                || tokenInfo1.getToken() == Token.LITERAL_NCHARS\n                || tokenInfo1.getToken() == Token.LITERAL_HEX) {\n            String stringVal1 = tokenInfo1.getStringVal();\n            String stringVal2 = tokenInfo2.getStringVal();\n\n            // Both should have string values\n            if (stringVal1 == null && stringVal2 == null) {\n                return true;\n            }\n            if (stringVal1 == null || stringVal2 == null) {\n                return false;\n            }\n\n            return stringVal1.equals(stringVal2);\n        }\n\n        // For other token types, just matching the token type is enough\n        return true;\n    }\n\n    /**\n     * Helper class to hold token sequence and string value map\n     */\n    static class TimeZoneVisitor extends SQLASTVisitorAdapter {\n        private TimeZone from;\n        private TimeZone to;\n\n        public TimeZoneVisitor(TimeZone from, TimeZone to) {\n            this.from = from;\n            this.to = to;\n        }\n\n        public boolean visit(SQLTimestampExpr x) {\n            SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n            String newTime = format.format(x.getDate(from));\n\n            x.setValue(newTime);\n\n            return true;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/AutoIncrementType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\npublic enum AutoIncrementType {\n    GROUP(\"GROUP\"), SIMPLE(\"SIMPLE\"),\n    SIMPLE_CACHE(\"SIMPLE WITH CACHE\"), TIME(\"TIME\");\n\n    private final String keyword;\n\n    public String getKeyword() {\n        return this.keyword;\n    }\n\n    private AutoIncrementType(String keyword) {\n        this.keyword = keyword;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/ClusteringType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\npublic enum ClusteringType {\n    Range,\n    Hash\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/DistributedByType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\npublic enum DistributedByType {\n    Hash,\n    Random\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLAdhocTableSource.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSourceImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAdhocTableSource extends SQLTableSourceImpl {\n    private SQLCreateTableStatement definition;\n\n    public SQLAdhocTableSource(SQLCreateTableStatement definition) {\n        setDefinition(definition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, definition);\n            super.accept0(v);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLCreateTableStatement getDefinition() {\n        return definition;\n    }\n\n    public void setDefinition(SQLCreateTableStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.definition = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLAnnIndex.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAnnIndex extends SQLObjectImpl {\n    private int indexType;\n    private int rtIndexType;\n    private Distance distance;\n\n    public SQLAnnIndex clone() {\n        SQLAnnIndex x = new SQLAnnIndex();\n        x.indexType = indexType;\n        x.rtIndexType = rtIndexType;\n        x.distance = distance;\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n\n    public void setIndexType(String type) {\n        this.indexType = IndexType.of(type);\n    }\n\n    public void setIndexType(IndexType indexType, boolean state) {\n        if (state) {\n            this.indexType |= indexType.mask;\n        } else {\n            this.indexType &= ~indexType.mask;\n        }\n    }\n\n    public void setRtIndexType(IndexType indexType, boolean state) {\n        if (state) {\n            this.rtIndexType |= indexType.mask;\n        } else {\n            this.rtIndexType &= ~indexType.mask;\n        }\n    }\n\n    public void setRtIndexType(String type) {\n        this.rtIndexType = IndexType.of(type);\n    }\n\n    public int getIndexType() {\n        return indexType;\n    }\n\n    public int getRtIndexType() {\n        return rtIndexType;\n    }\n\n    public Distance getDistance() {\n        return distance;\n    }\n\n    public void setDistance(Distance distance) {\n        this.distance = distance;\n    }\n\n    public void setDistance(String distance) {\n        if (distance == null) {\n            this.distance = null;\n            return;\n        }\n\n        if (distance.equalsIgnoreCase(\"Hamming\")) {\n            this.distance = Distance.Hamming;\n        } else if (distance.equalsIgnoreCase(\"SquaredEuclidean\")) {\n            this.distance = Distance.SquaredEuclidean;\n        } else if (distance.equalsIgnoreCase(\"DotProduct\")) {\n            this.distance = Distance.DotProduct;\n        }\n    }\n\n    public static enum IndexType {\n        Flat(1), FastIndex(2);\n\n        public final int mask;\n\n        IndexType(int ordinal) {\n            mask = (1 << ordinal);\n        }\n\n        private static int of(String type) {\n            if (type == null || type.length() == 0) {\n                return 0;\n            }\n\n            int v = 0;\n            String[] items = type.split(\",\");\n            for (String item : items) {\n                if (item.trim().equalsIgnoreCase(\"Flat\")) {\n                    v |= Flat.mask;\n                } else if (item.trim().equalsIgnoreCase(\"FastIndex\")\n                        || item.trim().equalsIgnoreCase(\"FAST_INDEX\")) {\n                    v |= FastIndex.mask;\n                }\n            }\n            return v;\n        }\n    }\n\n    public enum Distance {\n        Hamming,\n        SquaredEuclidean,\n        DotProduct // desc\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLArgument.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * Created by wenshao on 29/05/2017.\n */\npublic class SQLArgument extends SQLObjectImpl {\n    private SQLParameter.ParameterType type;\n    private SQLExpr expr;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public SQLArgument clone() {\n        SQLArgument x = new SQLArgument();\n\n        x.type = type;\n\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n\n        return x;\n    }\n\n    public SQLParameter.ParameterType getType() {\n        return type;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setType(SQLParameter.ParameterType type) {\n        this.type = type;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLArrayDataType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.sql.Types;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLArrayDataType extends SQLObjectImpl implements SQLDataType {\n    public static final SQLArrayDataType ARRYA_CHAR = new SQLArrayDataType(SQLCharExpr.DATA_TYPE);\n\n    private DbType dbType;\n    private SQLDataType componentType;\n    private boolean usedForCast;\n    private List<SQLExpr> arguments = new ArrayList<SQLExpr>();\n    public SQLArrayDataType() {\n    }\n\n    public SQLArrayDataType(SQLDataType componentType) {\n        setComponentType(componentType);\n    }\n\n    public SQLArrayDataType(SQLDataType componentType, DbType dbType) {\n        this.dbType = dbType;\n        setComponentType(componentType);\n    }\n\n    @Override\n    public String getName() {\n        return \"ARRAY\";\n    }\n\n    @Override\n    public long nameHashCode64() {\n        return FnvHash.Constants.ARRAY;\n    }\n\n    @Override\n    public void setName(String name) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public List<SQLExpr> getArguments() {\n        return arguments;\n    }\n\n    @Override\n    public Boolean getWithTimeZone() {\n        return null;\n    }\n\n    @Override\n    public void setWithTimeZone(Boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    public boolean isUsedForCast() {\n        return usedForCast;\n    }\n\n    public void setUsedForCast(boolean usedForCast) {\n        this.usedForCast = usedForCast;\n    }\n\n    @Override\n    public boolean isWithLocalTimeZone() {\n        return false;\n    }\n\n    @Override\n    public void setWithLocalTimeZone(boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, componentType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLArrayDataType clone() {\n        SQLArrayDataType x = new SQLArrayDataType();\n        if (componentType != null) {\n            x.setComponentType(componentType.clone());\n        }\n        x.dbType = dbType;\n\n        for (SQLExpr arg : arguments) {\n            SQLExpr item = arg.clone();\n            item.setParent(x);\n            x.arguments.add(item);\n        }\n        return x;\n    }\n\n    public SQLDataType getComponentType() {\n        return componentType;\n    }\n\n    public void setComponentType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.componentType = x;\n    }\n\n    public int jdbcType() {\n        return Types.ARRAY;\n    }\n\n    @Override\n    public boolean isInt() {\n        return false;\n    }\n\n    @Override\n    public boolean isNumberic() {\n        return false;\n    }\n\n    @Override\n    public boolean isString() {\n        return false;\n    }\n\n    @Override\n    public boolean hasKeyLength() {\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLCommentHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCommentHint extends SQLObjectImpl implements SQLHint {\n    private String text;\n\n    public SQLCommentHint() {\n    }\n\n    public SQLCommentHint(String text) {\n        this.text = text;\n    }\n\n    public String getText() {\n        return this.text;\n    }\n\n    public void setText(String text) {\n        this.text = text;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLCommentHint clone() {\n        return new SQLCommentHint(text);\n    }\n\n    public String toString() {\n        return \"/*\" + text + \"*/\";\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLComputeIncrementalStatsStatement.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLComputeIncrementalStatsStatement extends SQLStatementImpl {\n    private SQLExpr name;\n    private SQLExpr partition;\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getPartition() {\n        return partition;\n    }\n\n    public void setPartition(SQLExpr partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partition = partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n            acceptChild(v, partition);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLCurrentTimeExpr.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Objects;\n\npublic class SQLCurrentTimeExpr extends SQLExprImpl {\n    private final Type type;\n    private String timeZone;\n\n    public SQLCurrentTimeExpr(Type type) {\n        if (type == null) {\n            throw new NullPointerException();\n        }\n\n        this.type = type;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public String getTimeZone() {\n        return timeZone;\n    }\n\n    public void setTimeZone(String timeZone) {\n        this.timeZone = timeZone;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLCurrentTimeExpr that = (SQLCurrentTimeExpr) o;\n\n        if (type != that.type) {\n            return false;\n        }\n        return Objects.equals(timeZone, that.timeZone);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = type.hashCode();\n        result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);\n        return result;\n    }\n\n    public SQLCurrentTimeExpr clone() {\n        SQLCurrentTimeExpr x = new SQLCurrentTimeExpr(type);\n        x.setTimeZone(timeZone);\n        return x;\n    }\n\n    public static enum Type {\n        CURRENT_TIME(\"CURRENT_TIME\"),\n        CURRENT_DATE(\"CURRENT_DATE\"),\n        CURDATE(\"CURDATE\"),\n        CURTIME(\"CURTIME\"),\n        CURRENT_TIMESTAMP(\"CURRENT_TIMESTAMP\"),\n        LOCALTIME(\"LOCALTIME\"),\n        LOCALTIMESTAMP(\"LOCALTIMESTAMP\"),\n        SYSDATE(\"SYSDATE\");\n\n        public final String name;\n        public final String nameLCase;\n\n        Type(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLCurrentUserExpr.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCurrentUserExpr extends SQLExprImpl {\n    public SQLCurrentUserExpr() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (o == null) {\n            return false;\n        }\n\n        if (this == o) {\n            return true;\n        }\n\n        return getClass() == o.getClass();\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    public SQLCurrentUserExpr clone() {\n        return new SQLCurrentUserExpr();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\n\nimport java.util.List;\n\npublic interface SQLDataType extends SQLObject {\n    String getName();\n\n    long nameHashCode64();\n\n    void setName(String name);\n\n    List<SQLExpr> getArguments();\n\n    Boolean getWithTimeZone();\n\n    void setWithTimeZone(Boolean value);\n\n    boolean isWithLocalTimeZone();\n\n    void setWithLocalTimeZone(boolean value);\n\n    SQLDataType clone();\n\n    void setDbType(DbType dbType);\n\n    DbType getDbType();\n\n    int jdbcType();\n\n    interface Constants {\n        String CHAR = \"CHAR\";\n        String NCHAR = \"NCHAR\";\n        String VARCHAR = \"VARCHAR\";\n        String VARBINARY = \"VARBINARY\";\n        String DATE = \"DATE\";\n        String DATETIME = \"DATETIME\";\n        String TIME = \"TIME\";\n        String TIMESTAMP = \"TIMESTAMP\";\n        String TIMESTAMP_NTZ = \"TIMESTAMP_NTZ\";\n        String XML = \"XML\";\n\n        String DECIMAL = \"DECIMAL\";\n        String NUMBER = \"NUMBER\";\n        String REAL = \"REAL\";\n        String DOUBLE_PRECISION = \"DOUBLE PRECISION\";\n        String DOUBLE = \"DOUBLE\";\n\n        String TINYINT = \"TINYINT\";\n        String SMALLINT = \"SMALLINT\";\n        String INT = \"INT\";\n        String BIGINT = \"BIGINT\";\n        String TEXT = \"TEXT\";\n        String BYTEA = \"BYTEA\";\n        String BOOLEAN = \"BOOLEAN\";\n\n        String FLOAT = \"FLOAT\";\n        String JSON = \"JSON\";\n    }\n\n    boolean isInt();\n\n    boolean isNumberic();\n\n    public boolean isString();\n\n    public boolean hasKeyLength();\n\n    static SQLDataType of(String name) {\n        return new SQLDataTypeImpl(name);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLListExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.sql.Types;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDataTypeImpl extends SQLObjectImpl\n        implements SQLDataType, SQLDbTypedObject, SQLReplaceable {\n    private String name;\n    private long nameHashCode64;\n    protected final List<SQLExpr> arguments = new ArrayList<SQLExpr>();\n\n    protected SQLListExpr enumList;\n\n    private Boolean withTimeZone;\n    private boolean withLocalTimeZone;\n    private DbType dbType;\n\n    private boolean unsigned;\n    private boolean zerofill;\n\n    // for oracle\n    private SQLExpr indexBy;\n\n    public SQLDataTypeImpl() {\n    }\n\n    public SQLDataTypeImpl(String name) {\n        this.name = name;\n    }\n\n    public SQLDataTypeImpl(String name, int precision) {\n        this(name);\n        addArgument(new SQLIntegerExpr(precision));\n    }\n\n    public SQLDataTypeImpl(String name, SQLExpr arg) {\n        this(name);\n        addArgument(arg);\n    }\n\n    public SQLDataTypeImpl(String name, SQLListExpr enumList) {\n        this(name);\n        setEnumList(enumList);\n    }\n\n    public SQLDataTypeImpl(String name, int precision, int scale) {\n        this(name);\n        addArgument(new SQLIntegerExpr(precision));\n        addArgument(new SQLIntegerExpr(scale));\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < arguments.size(); i++) {\n                SQLExpr arg = arguments.get(i);\n                if (arg != null) {\n                    arg.accept(visitor);\n                }\n            }\n        }\n        if (enumList != null) {\n            visitor.visit(enumList);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public long nameHashCode64() {\n        if (nameHashCode64 == 0) {\n            nameHashCode64 = FnvHash.hashCode64(name);\n        }\n        return nameHashCode64;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n        nameHashCode64 = 0L;\n    }\n\n    public SQLListExpr getEnumList() {\n        return enumList;\n    }\n\n    public void setEnumList(SQLListExpr enumList) {\n        this.enumList = enumList;\n    }\n\n    public List<SQLExpr> getArguments() {\n        return this.arguments;\n    }\n\n    public void addArgument(SQLExpr argument) {\n        if (argument != null) {\n            argument.setParent(this);\n        }\n        this.arguments.add(argument);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLDataTypeImpl dataType = (SQLDataTypeImpl) o;\n\n        if (name != null ? !name.equals(dataType.name) : dataType.name != null) {\n            return false;\n        }\n        if (enumList != null ? !enumList.equals(dataType.enumList) : dataType.enumList != null) {\n            return false;\n        }\n        if (!arguments.equals(dataType.arguments)) {\n            return false;\n        }\n        return withTimeZone != null ? withTimeZone.equals(dataType.withTimeZone) : dataType.withTimeZone == null;\n    }\n\n    @Override\n    public int hashCode() {\n        long value = nameHashCode64();\n        return (int) (value ^ (value >>> 32));\n    }\n\n    @Override\n    public Boolean getWithTimeZone() {\n        return withTimeZone;\n    }\n\n    public void setWithTimeZone(Boolean withTimeZone) {\n        this.withTimeZone = withTimeZone;\n    }\n\n    public boolean isWithLocalTimeZone() {\n        return withLocalTimeZone;\n    }\n\n    public void setWithLocalTimeZone(boolean withLocalTimeZone) {\n        this.withLocalTimeZone = withLocalTimeZone;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    @Override\n    public int jdbcType() {\n        long nameNash = nameHashCode64();\n\n        if (nameNash == FnvHash.Constants.TINYINT) {\n            return Types.TINYINT;\n        }\n\n        if (nameNash == FnvHash.Constants.SMALLINT) {\n            return Types.SMALLINT;\n        }\n\n        if (nameNash == FnvHash.Constants.INT || nameNash == FnvHash.Constants.INTEGER) {\n            return Types.INTEGER;\n        }\n\n        if (nameNash == FnvHash.Constants.BIGINT) {\n            return Types.BIGINT;\n        }\n\n        if (nameNash == FnvHash.Constants.DECIMAL) {\n            return Types.DECIMAL;\n        }\n\n        if (nameNash == FnvHash.Constants.FLOAT) {\n            return Types.FLOAT;\n        }\n\n        if (nameNash == FnvHash.Constants.REAL) {\n            return Types.REAL;\n        }\n\n        if (nameNash == FnvHash.Constants.DOUBLE) {\n            return Types.DOUBLE;\n        }\n\n        if (nameNash == FnvHash.Constants.NUMBER || nameNash == FnvHash.Constants.NUMERIC) {\n            return Types.NUMERIC;\n        }\n\n        if (nameNash == FnvHash.Constants.BOOLEAN) {\n            return Types.BOOLEAN;\n        }\n\n        if (nameNash == FnvHash.Constants.DATE || nameNash == FnvHash.Constants.NEWDATE) {\n            return Types.DATE;\n        }\n\n        if (nameNash == FnvHash.Constants.DATETIME || nameNash == FnvHash.Constants.TIMESTAMP) {\n            return Types.TIMESTAMP;\n        }\n\n        if (nameNash == FnvHash.Constants.TIME) {\n            return Types.TIME;\n        }\n\n        if (nameNash == FnvHash.Constants.BLOB) {\n            return Types.BLOB;\n        }\n\n        if (nameNash == FnvHash.Constants.ROWID) {\n            return Types.ROWID;\n        }\n\n        if (nameNash == FnvHash.Constants.REF) {\n            return Types.REF;\n        }\n\n        if (nameNash == FnvHash.Constants.TINYINT || nameNash == FnvHash.Constants.TINY) {\n            return Types.TINYINT;\n        }\n\n        if (nameNash == FnvHash.Constants.SMALLINT || nameNash == FnvHash.Constants.SHORT) {\n            return Types.SMALLINT;\n        }\n\n        if (nameNash == FnvHash.Constants.INT\n                || nameNash == FnvHash.Constants.INT24\n                || nameNash == FnvHash.Constants.INTEGER) {\n            return Types.INTEGER;\n        }\n\n        if (nameNash == FnvHash.Constants.NUMBER || nameNash == FnvHash.Constants.NUMERIC) {\n            return Types.NUMERIC;\n        }\n\n        if (nameNash == FnvHash.Constants.BOOLEAN) {\n            return Types.BOOLEAN;\n        }\n\n        if (nameNash == FnvHash.Constants.DATE\n                || nameNash == FnvHash.Constants.YEAR\n                || nameNash == FnvHash.Constants.NEWDATE) {\n            return Types.DATE;\n        }\n\n        if (nameNash == FnvHash.Constants.DATETIME || nameNash == FnvHash.Constants.TIMESTAMP) {\n            return Types.TIMESTAMP;\n        }\n\n        if (nameNash == FnvHash.Constants.TIME) {\n            return Types.TIME;\n        }\n\n        if (nameNash == FnvHash.Constants.TINYBLOB) {\n            return Types.VARBINARY;\n        }\n\n        if (nameNash == FnvHash.Constants.BLOB) {\n            return Types.BLOB;\n        }\n\n        if (nameNash == FnvHash.Constants.LONGBLOB) {\n            return Types.LONGVARBINARY;\n        }\n\n        if (nameNash == FnvHash.Constants.ROWID) {\n            return Types.ROWID;\n        }\n\n        if (nameNash == FnvHash.Constants.REF) {\n            return Types.REF;\n        }\n\n        if (nameNash == FnvHash.Constants.BINARY || nameNash == FnvHash.Constants.GEOMETRY) {\n            return Types.BINARY;\n        }\n\n        if (nameNash == FnvHash.Constants.SQLXML) {\n            return Types.SQLXML;\n        }\n\n        if (nameNash == FnvHash.Constants.BIT) {\n            return Types.BIT;\n        }\n\n        if (nameNash == FnvHash.Constants.NCHAR) {\n            return Types.NCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.CHAR\n                || nameNash == FnvHash.Constants.ENUM\n                || nameNash == FnvHash.Constants.SET\n                || nameNash == FnvHash.Constants.JSON) {\n            return Types.CHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.VARCHAR\n                || nameNash == FnvHash.Constants.VARCHAR2\n                || nameNash == FnvHash.Constants.STRING) {\n            return Types.VARCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.NVARCHAR || nameNash == FnvHash.Constants.NVARCHAR2) {\n            return Types.NVARCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.CLOB\n                || nameNash == FnvHash.Constants.TEXT\n                || nameNash == FnvHash.Constants.TINYTEXT\n                || nameNash == FnvHash.Constants.MEDIUMTEXT\n                || nameNash == FnvHash.Constants.LONGTEXT) {\n            return Types.CLOB;\n        }\n\n        if (nameNash == FnvHash.Constants.NCLOB) {\n            return Types.NCLOB;\n        }\n\n        if (nameNash == FnvHash.Constants.TINYBLOB) {\n            return Types.VARBINARY;\n        }\n\n        if (nameNash == FnvHash.Constants.LONGBLOB) {\n            return Types.LONGVARBINARY;\n        }\n\n        if (nameNash == FnvHash.Constants.BINARY || nameNash == FnvHash.Constants.GEOMETRY) {\n            return Types.BINARY;\n        }\n\n        if (nameNash == FnvHash.Constants.SQLXML) {\n            return Types.SQLXML;\n        }\n\n        //\n\n        if (nameNash == FnvHash.Constants.NCHAR) {\n            return Types.NCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.CHAR || nameNash == FnvHash.Constants.JSON) {\n            return Types.CHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.VARCHAR\n                || nameNash == FnvHash.Constants.VARCHAR2\n                || nameNash == FnvHash.Constants.STRING) {\n            return Types.VARCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.NVARCHAR || nameNash == FnvHash.Constants.NVARCHAR2) {\n            return Types.NVARCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.CLOB\n                || nameNash == FnvHash.Constants.TEXT\n                || nameNash == FnvHash.Constants.TINYTEXT\n                || nameNash == FnvHash.Constants.MEDIUMTEXT\n                || nameNash == FnvHash.Constants.LONGTEXT) {\n            return Types.CLOB;\n        }\n\n        if (nameNash == FnvHash.Constants.NCLOB) {\n            return Types.NCLOB;\n        }\n\n        return 0;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLDataTypeImpl clone() {\n        SQLDataTypeImpl x = new SQLDataTypeImpl();\n\n        cloneTo(x);\n\n        return x;\n    }\n\n    public void cloneTo(SQLDataTypeImpl x) {\n        x.dbType = dbType;\n        x.name = name;\n        x.nameHashCode64 = nameHashCode64;\n\n        for (SQLExpr arg : arguments) {\n            x.addArgument(arg.clone());\n        }\n\n        x.withTimeZone = withTimeZone;\n        x.withLocalTimeZone = withLocalTimeZone;\n        x.zerofill = zerofill;\n        x.unsigned = unsigned;\n\n        if (indexBy != null) {\n            x.setIndexBy(indexBy.clone());\n        }\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, dbType);\n    }\n\n    public boolean isUnsigned() {\n        return unsigned;\n    }\n\n    public void setUnsigned(boolean unsigned) {\n        this.unsigned = unsigned;\n    }\n\n    public boolean isZerofill() {\n        return zerofill;\n    }\n\n    public void setZerofill(boolean zerofill) {\n        this.zerofill = zerofill;\n    }\n\n    public SQLExpr getIndexBy() {\n        return indexBy;\n    }\n\n    public void setIndexBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.indexBy = x;\n    }\n\n    public boolean isInt() {\n        long hashCode64 = nameHashCode64();\n\n        return hashCode64 == FnvHash.Constants.BIGINT\n            || hashCode64 == FnvHash.Constants.INT\n            || hashCode64 == FnvHash.Constants.INT4\n            || hashCode64 == FnvHash.Constants.INT24\n            || hashCode64 == FnvHash.Constants.SMALLINT\n            || hashCode64 == FnvHash.Constants.MEDIUMINT\n            || hashCode64 == FnvHash.Constants.TINYINT\n            || hashCode64 == FnvHash.Constants.INTEGER;\n    }\n\n    public boolean isNumberic() {\n        long hashCode64 = nameHashCode64();\n\n        return hashCode64 == FnvHash.Constants.REAL\n                || hashCode64 == FnvHash.Constants.FLOAT\n                || hashCode64 == FnvHash.Constants.DOUBLE\n                || hashCode64 == FnvHash.Constants.DOUBLE_PRECISION\n                || hashCode64 == FnvHash.Constants.NUMBER\n                || hashCode64 == FnvHash.Constants.DECIMAL;\n    }\n\n    public boolean isString() {\n        long hashCode64 = nameHashCode64();\n\n        return hashCode64 == FnvHash.Constants.VARCHAR\n                || hashCode64 == FnvHash.Constants.VARCHAR2\n                || hashCode64 == FnvHash.Constants.CHAR\n                || hashCode64 == FnvHash.Constants.NCHAR\n                || hashCode64 == FnvHash.Constants.NVARCHAR\n                || hashCode64 == FnvHash.Constants.NVARCHAR2\n                || hashCode64 == FnvHash.Constants.TEXT\n                || hashCode64 == FnvHash.Constants.TINYTEXT\n                || hashCode64 == FnvHash.Constants.MEDIUMTEXT\n                || hashCode64 == FnvHash.Constants.LONGTEXT\n                || hashCode64 == FnvHash.Constants.CLOB\n                || hashCode64 == FnvHash.Constants.NCLOB\n                || hashCode64 == FnvHash.Constants.MULTIVALUE\n                || hashCode64 == FnvHash.Constants.STRING;\n    }\n\n    @Override\n    public boolean hasKeyLength() {\n        long hashCode64 = nameHashCode64();\n\n        return hashCode64 == FnvHash.Constants.VARCHAR\n                || hashCode64 == FnvHash.Constants.VARCHAR2\n                || hashCode64 == FnvHash.Constants.CHAR\n                || hashCode64 == FnvHash.Constants.NCHAR\n                || hashCode64 == FnvHash.Constants.NVARCHAR\n                || hashCode64 == FnvHash.Constants.NVARCHAR2\n                || hashCode64 == FnvHash.Constants.TEXT\n                || hashCode64 == FnvHash.Constants.TINYTEXT\n                || hashCode64 == FnvHash.Constants.MEDIUMTEXT\n                || hashCode64 == FnvHash.Constants.LONGTEXT\n                || hashCode64 == FnvHash.Constants.CLOB\n                || hashCode64 == FnvHash.Constants.NCLOB\n                || hashCode64 == FnvHash.Constants.MULTIVALUE\n                || hashCode64 == FnvHash.Constants.STRING\n                || hashCode64 == FnvHash.Constants.BLOB\n                || hashCode64 == FnvHash.Constants.TINYBLOB\n                || hashCode64 == FnvHash.Constants.LONGBLOB\n                || hashCode64 == FnvHash.Constants.BINARY\n                || hashCode64 == FnvHash.Constants.VARBINARY;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < arguments.size(); i++) {\n            if (arguments.get(i) == expr) {\n                target.setParent(this);\n                arguments.set(i, target);\n                return true;\n            }\n        }\n        if (indexBy == expr) {\n            target.setParent(this);\n            indexBy = target;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLDataTypeRefExpr.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLDataTypeRefExpr extends SQLExprImpl {\n    private SQLDataType dataType;\n\n    public SQLDataTypeRefExpr(SQLDataType dataType) {\n        this.dataType = dataType;\n    }\n\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    public void setDataType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.dataType = x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLDataTypeRefExpr that = (SQLDataTypeRefExpr) o;\n\n        return dataType != null ? dataType.equals(that.dataType) : that.dataType == null;\n    }\n\n    @Override\n    public int hashCode() {\n        return dataType != null ? dataType.hashCode() : 0;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, dataType);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public SQLExpr clone() {\n        return new SQLDataTypeRefExpr(\n                dataType == null\n                        ? null\n                        : dataType.clone());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLDbTypedObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\n\npublic interface SQLDbTypedObject extends SQLObject {\n    DbType getDbType();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLDeclareItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDeclareItem extends SQLObjectImpl implements SQLObjectWithDataType, SQLReplaceable {\n    protected Type type;\n\n    protected SQLName name;\n\n    protected SQLDataType dataType;\n\n    protected SQLExpr value;\n\n    protected List<SQLTableElement> tableElementList = new ArrayList<SQLTableElement>();\n\n    protected transient SQLObject resolvedObject;\n\n    public SQLDeclareItem() {\n    }\n\n    public SQLDeclareItem(SQLName name, SQLDataType dataType) {\n        this.setName(name);\n        this.setDataType(dataType);\n    }\n\n    public SQLDeclareItem(SQLName name, SQLDataType dataType, SQLExpr value) {\n        this.setName(name);\n        this.setDataType(dataType);\n        this.setValue(value);\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        if (value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.name);\n            acceptChild(visitor, this.dataType);\n            acceptChild(visitor, this.value);\n            acceptChild(visitor, this.tableElementList);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    public void setDataType(SQLDataType dataType) {\n        if (dataType != null) {\n            dataType.setParent(this);\n        }\n        this.dataType = dataType;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.value = value;\n    }\n\n    public List<SQLTableElement> getTableElementList() {\n        return tableElementList;\n    }\n\n    public void setTableElementList(List<SQLTableElement> tableElementList) {\n        this.tableElementList = tableElementList;\n    }\n\n    public enum Type {\n        TABLE, LOCAL, CURSOR;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public void setType(Type type) {\n        this.type = type;\n    }\n\n    public SQLObject getResolvedObject() {\n        return resolvedObject;\n    }\n\n    public void setResolvedObject(SQLObject resolvedObject) {\n        this.resolvedObject = resolvedObject;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport java.util.List;\n\npublic interface SQLExpr extends SQLObject, Cloneable {\n    SQLExpr clone();\n\n    SQLDataType computeDataType();\n\n    List<SQLObject> getChildren();\n\n    SQLCommentHint getHint();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLExprComparor.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport java.util.Comparator;\n\npublic class SQLExprComparor implements Comparator<SQLExpr> {\n    public static final SQLExprComparor instance = new SQLExprComparor();\n\n    @Override\n    public int compare(SQLExpr a, SQLExpr b) {\n        return compareTo(a, b);\n    }\n\n    public static int compareTo(SQLExpr a, SQLExpr b) {\n        if (a == null && b == null) {\n            return 0;\n        }\n\n        if (a == null) {\n            return -1;\n        }\n\n        if (b == null) {\n            return 1;\n        }\n\n        if (a.getClass() == b.getClass() && a instanceof Comparable) {\n            return ((Comparable) a).compareTo(b);\n        }\n\n        return a.getClass().getName().compareTo(b.getClass().getName());\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport java.util.List;\n\npublic abstract class SQLExprImpl extends SQLObjectImpl implements SQLExpr {\n    protected boolean parenthesized;\n    protected int parenthesizedCount;\n    public SQLExprImpl() {\n    }\n\n    public boolean isParenthesized() {\n        return parenthesized;\n    }\n\n    public void setParenthesized(boolean parenthesized) {\n        this.parenthesized = parenthesized;\n        if (parenthesized) {\n            parenthesizedCount++;\n        } else {\n            parenthesizedCount--;\n        }\n    }\n\n    public int getParenthesizedCount() {\n        return parenthesizedCount;\n    }\n\n    public void setParenthesizedCount(int parenthesizedCount) {\n        this.parenthesizedCount = parenthesizedCount;\n    }\n\n    public void increaseParenthesizedCount() {\n        this.parenthesizedCount++;\n    }\n\n    public abstract boolean equals(Object o);\n\n    public abstract int hashCode();\n\n    public abstract SQLExpr clone();\n\n    protected void cloneTo(SQLExprImpl x) {\n        super.cloneTo(x);\n        x.parenthesized = this.parenthesized;\n        x.parenthesizedCount = this.parenthesizedCount;\n    }\n\n    public SQLDataType computeDataType() {\n        return null;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\npublic interface SQLHint extends SQLObject {\n    SQLHint clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLIndex.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\n\nimport java.util.List;\n\npublic interface SQLIndex extends SQLObject {\n    List<SQLName> getCovering();\n\n    List<SQLSelectOrderByItem> getColumns();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLIndexDefinition.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-04 11:27\n */\npublic class SQLIndexDefinition extends SQLObjectImpl implements SQLIndex {\n    // for polardb-x partition manage\n    protected SQLPartitionBy partitioning;\n    /**\n     * [CONSTRAINT [symbol]] [GLOBAL|LOCAL] [FULLTEXT|SPATIAL|UNIQUE|PRIMARY] [INDEX|KEY]\n     * [index_name] [index_type] (key_part,...) [COVERING (col_name,...)] [index_option] ...\n     */\n\n    private boolean hasConstraint;\n    private SQLName symbol;\n    private boolean global;\n    private boolean local;\n    private String type;\n    private boolean hashMapType; //for ads\n    private boolean hashType; //for ads\n    private boolean index;\n    private boolean key;\n    private SQLName name;\n    private SQLTableSource table;\n    private List<SQLSelectOrderByItem> columns = new ArrayList<SQLSelectOrderByItem>();\n    private SQLIndexOptions options;\n\n    // DRDS\n    private SQLExpr dbPartitionBy;\n    private SQLExpr tbPartitionBy;\n    private SQLExpr tbPartitions;\n    private List<SQLName> covering = new ArrayList<SQLName>();\n\n    // For fulltext index when create table.\n    private SQLName analyzerName;\n    private SQLName indexAnalyzerName;\n    private SQLName queryAnalyzerName;\n    private SQLName withDicName;\n\n    // Compatible layer.\n    private List<SQLAssignItem> compatibleOptions = new ArrayList<SQLAssignItem>();\n\n    public boolean hasConstraint() {\n        return hasConstraint;\n    }\n\n    public void setHasConstraint(boolean hasConstraint) {\n        this.hasConstraint = hasConstraint;\n    }\n\n    public SQLName getSymbol() {\n        return symbol;\n    }\n\n    public void setSymbol(SQLName symbol) {\n        if (symbol != null) {\n            if (getParent() != null) {\n                symbol.setParent(getParent());\n            } else {\n                symbol.setParent(this);\n            }\n        }\n        this.symbol = symbol;\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public boolean isHashMapType() {\n        return hashMapType;\n    }\n\n    public void setHashMapType(boolean hashMapType) {\n        this.hashMapType = hashMapType;\n    }\n\n    public boolean isHashType() {\n        return hashType;\n    }\n\n    public void setHashType(boolean hashType) {\n        this.hashType = hashType;\n    }\n\n    public boolean isIndex() {\n        return index;\n    }\n\n    public void setIndex(boolean index) {\n        this.index = index;\n    }\n\n    public boolean isKey() {\n        return key;\n    }\n\n    public void setKey(boolean key) {\n        this.key = key;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            if (getParent() != null) {\n                name.setParent(getParent());\n            } else {\n                name.setParent(this);\n            }\n        }\n        this.name = name;\n    }\n\n    public SQLTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLTableSource table) {\n        if (table != null) {\n            if (getParent() != null) {\n                table.setParent(getParent());\n            } else {\n                table.setParent(this);\n            }\n        }\n        this.table = table;\n    }\n\n    @Override\n    public List<SQLSelectOrderByItem> getColumns() {\n        return columns;\n    }\n\n    public void setColumns(List<SQLSelectOrderByItem> columns) {\n        this.columns = columns;\n    }\n\n    public boolean hasOptions() {\n        return options != null;\n    }\n\n    public SQLIndexOptions getOptions() {\n        if (null == options) {\n            options = new SQLIndexOptions();\n            options.setParent(this);\n        }\n        return options;\n    }\n\n    public SQLExpr getDbPartitionBy() {\n        return dbPartitionBy;\n    }\n\n    public void setDbPartitionBy(SQLExpr dbPartitionBy) {\n        if (dbPartitionBy != null) {\n            if (getParent() != null) {\n                dbPartitionBy.setParent(getParent());\n            } else {\n                dbPartitionBy.setParent(this);\n            }\n        }\n        this.dbPartitionBy = dbPartitionBy;\n    }\n\n    public SQLExpr getTbPartitionBy() {\n        return tbPartitionBy;\n    }\n\n    public void setTbPartitionBy(SQLExpr tbPartitionBy) {\n        if (tbPartitionBy != null) {\n            if (getParent() != null) {\n                tbPartitionBy.setParent(getParent());\n            } else {\n                tbPartitionBy.setParent(this);\n            }\n        }\n        this.tbPartitionBy = tbPartitionBy;\n    }\n\n    public SQLExpr getTbPartitions() {\n        return tbPartitions;\n    }\n\n    public void setTbPartitions(SQLExpr tbPartitions) {\n        if (tbPartitions != null) {\n            if (getParent() != null) {\n                tbPartitions.setParent(getParent());\n            } else {\n                tbPartitions.setParent(this);\n            }\n        }\n        this.tbPartitions = tbPartitions;\n    }\n\n    @Override\n    public List<SQLName> getCovering() {\n        return covering;\n    }\n\n    public void setCovering(List<SQLName> covering) {\n        this.covering = covering;\n    }\n\n    public SQLName getAnalyzerName() {\n        return analyzerName;\n    }\n\n    public void setAnalyzerName(SQLName analyzerName) {\n        if (analyzerName != null) {\n            if (getParent() != null) {\n                analyzerName.setParent(getParent());\n            } else {\n                analyzerName.setParent(this);\n            }\n        }\n        this.analyzerName = analyzerName;\n    }\n\n    public SQLName getIndexAnalyzerName() {\n        return indexAnalyzerName;\n    }\n\n    public void setIndexAnalyzerName(SQLName indexAnalyzerName) {\n        if (indexAnalyzerName != null) {\n            if (getParent() != null) {\n                indexAnalyzerName.setParent(getParent());\n            } else {\n                indexAnalyzerName.setParent(this);\n            }\n        }\n        this.indexAnalyzerName = indexAnalyzerName;\n    }\n\n    public SQLName getQueryAnalyzerName() {\n        return queryAnalyzerName;\n    }\n\n    public void setQueryAnalyzerName(SQLName queryAnalyzerName) {\n        if (queryAnalyzerName != null) {\n            if (getParent() != null) {\n                queryAnalyzerName.setParent(getParent());\n            } else {\n                queryAnalyzerName.setParent(this);\n            }\n        }\n        this.queryAnalyzerName = queryAnalyzerName;\n    }\n\n    public SQLName getWithDicName() {\n        return withDicName;\n    }\n\n    public void setWithDicName(SQLName withDicName) {\n        if (withDicName != null) {\n            if (getParent() != null) {\n                withDicName.setParent(getParent());\n            } else {\n                withDicName.setParent(this);\n            }\n        }\n        this.withDicName = withDicName;\n    }\n\n    public SQLPartitionBy getPartitioning() {\n        return partitioning;\n    }\n\n    public void setPartitioning(SQLPartitionBy partitioning) {\n        this.partitioning = partitioning;\n    }\n\n    public List<SQLAssignItem> getCompatibleOptions() {\n        return compatibleOptions;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (name != null) {\n                name.accept(visitor);\n            }\n\n            for (final SQLSelectOrderByItem item : columns) {\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n            for (final SQLName item : covering) {\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public void cloneTo(SQLIndexDefinition definition) {\n        SQLObject parent;\n        if (definition.getParent() != null) {\n            parent = definition.getParent();\n        } else {\n            parent = definition;\n        }\n        definition.hasConstraint = hasConstraint;\n        if (symbol != null) {\n            definition.symbol = symbol.clone();\n            definition.symbol.setParent(parent);\n        }\n        definition.global = global;\n        definition.local = local;\n        definition.type = type;\n        definition.hashMapType = hashMapType;\n        definition.index = index;\n        definition.key = key;\n        if (name != null) {\n            definition.name = name.clone();\n            definition.name.setParent(parent);\n        }\n        if (table != null) {\n            definition.table = table.clone();\n            definition.table.setParent(parent);\n        }\n        for (SQLSelectOrderByItem item : columns) {\n            SQLSelectOrderByItem item1 = item.clone();\n            item1.setParent(parent);\n            definition.columns.add(item1);\n        }\n        if (options != null) {\n            options.cloneTo(definition.getOptions());\n        }\n        if (dbPartitionBy != null) {\n            definition.dbPartitionBy = dbPartitionBy.clone();\n            definition.dbPartitionBy.setParent(parent);\n        }\n        if (tbPartitionBy != null) {\n            definition.tbPartitionBy = tbPartitionBy.clone();\n            definition.tbPartitionBy.setParent(parent);\n        }\n        if (tbPartitions != null) {\n            definition.tbPartitions = tbPartitions.clone();\n            definition.tbPartitions.setParent(parent);\n        }\n        if (partitioning != null) {\n            definition.partitioning = partitioning.clone();\n            definition.partitioning.setParent(parent);\n        }\n        for (SQLName name : covering) {\n            SQLName name1 = name.clone();\n            name1.setParent(parent);\n            definition.covering.add(name1);\n        }\n        if (analyzerName != null) {\n            definition.analyzerName = analyzerName.clone();\n            definition.analyzerName.setParent(parent);\n        }\n        if (indexAnalyzerName != null) {\n            definition.indexAnalyzerName = indexAnalyzerName.clone();\n            definition.indexAnalyzerName.setParent(parent);\n        }\n        if (withDicName != null) {\n            definition.withDicName = withDicName.clone();\n            definition.withDicName.setParent(parent);\n        }\n        if (queryAnalyzerName != null) {\n            definition.queryAnalyzerName = queryAnalyzerName.clone();\n            definition.queryAnalyzerName.setParent(parent);\n        }\n        for (SQLAssignItem item : compatibleOptions) {\n            SQLAssignItem item2 = item.clone();\n            item2.setParent(parent);\n            definition.compatibleOptions.add(item2);\n        }\n    }\n\n    //\n    // Function for compatibility.\n    //\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        if (getParent() != null) {\n            assignItem.setParent(getParent());\n        } else {\n            assignItem.setParent(this);\n        }\n        getCompatibleOptions().add(assignItem);\n    }\n\n    public SQLExpr getOption(String name) {\n        if (name == null) {\n            return null;\n        }\n\n        return getOption(\n                FnvHash.hashCode64(name));\n    }\n\n    public SQLExpr getOption(long hash64) {\n        // Search in compatible list first.\n        for (SQLAssignItem item : compatibleOptions) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        // Now search in new options.\n        if (null == options) {\n            return null;\n        }\n\n        if (hash64 == FnvHash.Constants.KEY_BLOCK_SIZE) {\n            return options.getKeyBlockSize();\n        } else if (hash64 == FnvHash.Constants.ALGORITHM) {\n            if (options.getAlgorithm() != null) {\n                return new SQLIdentifierExpr(options.getAlgorithm());\n            }\n            return null;\n        } else if (hash64 == FnvHash.hashCode64(\"LOCK\")) {\n            if (options.getLock() != null) {\n                return new SQLIdentifierExpr(options.getLock());\n            }\n            return null;\n        }\n\n        for (SQLAssignItem item : options.getOtherOptions()) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public String getDistanceMeasure() {\n        SQLExpr expr = getOption(FnvHash.Constants.DISTANCEMEASURE);\n        if (expr == null) {\n            return null;\n        }\n\n        return expr.toString();\n    }\n\n    public String getAlgorithm() {\n        if (options != null && options.getAlgorithm() != null) {\n            return options.getAlgorithm();\n        }\n\n        SQLExpr expr = getOption(FnvHash.Constants.ALGORITHM);\n        if (expr == null) {\n            return null;\n        }\n\n        return expr.toString();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLIndexOptions.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-04 11:48\n */\npublic class SQLIndexOptions extends SQLObjectImpl {\n    private String indexType; // Using btree/hash\n    private SQLExpr keyBlockSize;\n    private String parserName;\n    private SQLExpr comment;\n    private String algorithm;\n    private String lock;\n    private boolean invisible;\n    private boolean visible;\n    private boolean global;\n    private boolean local;\n    private List<SQLAssignItem> otherOptions = new ArrayList<SQLAssignItem>();\n\n    public SQLIndexOptions() {\n    }\n\n    public String getIndexType() {\n        return indexType;\n    }\n\n    public void setIndexType(String indexType) {\n        this.indexType = indexType;\n    }\n\n    public SQLExpr getKeyBlockSize() {\n        return keyBlockSize;\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public void setKeyBlockSize(SQLExpr keyBlockSize) {\n        if (keyBlockSize != null) {\n            if (getParent() != null && getParent().getParent() != null) {\n                keyBlockSize.setParent(getParent().getParent());\n            } else {\n                keyBlockSize.setParent(this);\n            }\n        }\n        this.keyBlockSize = keyBlockSize;\n\n        // Old parser code put it in options list.\n        if (keyBlockSize != null && getParent() != null && getParent() instanceof SQLIndexDefinition) {\n            SQLIndexDefinition parent = (SQLIndexDefinition) getParent();\n            SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"KEY_BLOCK_SIZE\"), keyBlockSize);\n            if (getParent() != null && getParent().getParent() != null) {\n                assignItem.setParent(getParent().getParent());\n            } else {\n                assignItem.setParent(this);\n            }\n            parent.getCompatibleOptions().add(assignItem);\n        }\n    }\n\n    public String getParserName() {\n        return parserName;\n    }\n\n    public void setParserName(String parserName) {\n        this.parserName = parserName;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            if (getParent() != null && getParent().getParent() != null) {\n                comment.setParent(getParent().getParent());\n            } else {\n                comment.setParent(this);\n            }\n        }\n        this.comment = comment;\n    }\n\n    public String getAlgorithm() {\n        return algorithm;\n    }\n\n    public void setAlgorithm(String algorithm) {\n        this.algorithm = algorithm;\n\n        // Old parser code put it in options list.\n        if (algorithm != null && getParent() != null && getParent() instanceof SQLIndexDefinition) {\n            SQLIndexDefinition parent = (SQLIndexDefinition) getParent();\n            SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"ALGORITHM\"), new SQLIdentifierExpr(algorithm));\n            if (getParent() != null && getParent().getParent() != null) {\n                assignItem.setParent(getParent().getParent());\n            } else {\n                assignItem.setParent(this);\n            }\n            parent.getCompatibleOptions().add(assignItem);\n        }\n    }\n\n    public String getLock() {\n        return lock;\n    }\n\n    public void setLock(String lock) {\n        this.lock = lock;\n\n        // Old parser code put it in options list.\n        if (lock != null && getParent() != null && getParent() instanceof SQLIndexDefinition) {\n            SQLIndexDefinition parent = (SQLIndexDefinition) getParent();\n            SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"LOCK\"), new SQLIdentifierExpr(lock));\n            if (getParent() != null && getParent().getParent() != null) {\n                assignItem.setParent(getParent().getParent());\n            } else {\n                assignItem.setParent(this);\n            }\n            parent.getCompatibleOptions().add(assignItem);\n        }\n    }\n\n    public boolean isInvisible() {\n        return invisible;\n    }\n\n    public void setInvisible(boolean invisible) {\n        this.invisible = invisible;\n    }\n\n    public boolean isVisible() {\n        return visible;\n    }\n\n    public void setVisible(boolean visible) {\n        this.visible = visible;\n    }\n\n    public List<SQLAssignItem> getOtherOptions() {\n        return otherOptions;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public void cloneTo(SQLIndexOptions options) {\n        SQLObject parent;\n        if (options.getParent() != null && options.getParent().getParent() != null) {\n            parent = options.getParent().getParent();\n        } else {\n            parent = options;\n        }\n        options.indexType = indexType;\n        if (keyBlockSize != null) {\n            options.keyBlockSize = keyBlockSize.clone();\n            options.keyBlockSize.setParent(parent);\n        }\n        options.parserName = parserName;\n        if (comment != null) {\n            options.comment = comment.clone();\n            options.comment.setParent(parent);\n        }\n        options.algorithm = algorithm;\n        options.lock = lock;\n        for (SQLAssignItem item : otherOptions) {\n            SQLAssignItem item1 = item.clone();\n            item1.setParent(parent);\n            options.otherOptions.add(item1);\n        }\n\n        options.invisible = invisible;\n\n        options.global = global;\n        options.local = local;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLJSONValueExpr.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLJSONValueExpr extends SQLExprImpl {\n    private SQLExpr json;\n    private SQLExpr path;\n\n    @Override\n    public boolean equals(Object o) {\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n    }\n\n    @Override\n    public SQLExpr clone() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLKeep.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic final class SQLKeep extends SQLObjectImpl {\n    protected DenseRank denseRank;\n\n    protected SQLOrderBy orderBy;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.orderBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public DenseRank getDenseRank() {\n        return denseRank;\n    }\n\n    public void setDenseRank(DenseRank denseRank) {\n        this.denseRank = denseRank;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        if (orderBy != null) {\n            orderBy.setParent(this);\n        }\n        this.orderBy = orderBy;\n    }\n\n    public SQLKeep clone() {\n        SQLKeep x = new SQLKeep();\n\n        x.denseRank = denseRank;\n\n        if (orderBy != null) {\n            x.setOrderBy(orderBy.clone());\n        }\n\n        return x;\n    }\n\n    public static enum DenseRank {\n        FIRST,\n        LAST\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLLimit.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic final class SQLLimit extends SQLObjectImpl implements SQLReplaceable {\n    private SQLExpr rowCount;\n    private SQLExpr offset;\n    private List<SQLExpr> by;\n\n    private boolean offsetClause;\n\n    public SQLLimit() {\n    }\n\n    public SQLLimit(int rowCount) {\n        this.setRowCount(new SQLIntegerExpr(rowCount));\n    }\n\n    public SQLLimit(SQLExpr rowCount) {\n        this.setRowCount(rowCount);\n    }\n\n    public SQLLimit(SQLExpr offset, SQLExpr rowCount) {\n        this.setOffset(offset);\n        this.setRowCount(rowCount);\n    }\n\n    public SQLExpr getRowCount() {\n        return rowCount;\n    }\n\n    public void setRowCount(SQLExpr rowCount) {\n        if (rowCount != null) {\n            rowCount.setParent(this);\n        }\n        this.rowCount = rowCount;\n    }\n\n    public void setRowCount(int rowCount) {\n        this.setRowCount(new SQLIntegerExpr(rowCount));\n    }\n\n    public SQLExpr getOffset() {\n        return offset;\n    }\n\n    public void setOffset(int offset) {\n        this.setOffset(new SQLIntegerExpr(offset));\n    }\n\n    public void setOffset(SQLExpr offset) {\n        if (offset != null) {\n            offset.setParent(this);\n        }\n        this.offset = offset;\n    }\n\n    public boolean isOffsetClause() {\n        return offsetClause;\n    }\n\n    public void setOffsetClause(boolean offsetClause) {\n        this.offsetClause = offsetClause;\n    }\n\n    public void merge(SQLLimit other) {\n        if (other == null) {\n            return;\n        }\n\n        if (other.offset != null) {\n            if (this.offset == null) {\n                this.offset = other.offset.clone();\n            }\n        }\n\n        if (other.rowCount != null) {\n            if (this.rowCount == null) {\n                this.rowCount = other.rowCount.clone();\n            }\n        }\n\n        if (other.by != null) {\n            for (SQLExpr item : other.by) {\n                addBy(item.clone());\n            }\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (offset != null) {\n                offset.accept(visitor);\n            }\n\n            if (rowCount != null) {\n                rowCount.accept(visitor);\n            }\n\n            if (by != null) {\n                for (SQLExpr item : by) {\n                    item.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLLimit clone() {\n        SQLLimit x = new SQLLimit();\n\n        if (offset != null) {\n            x.setOffset(offset.clone());\n        }\n\n        if (rowCount != null) {\n            x.setRowCount(rowCount.clone());\n        }\n\n        if (by != null) {\n            for (SQLExpr item : by) {\n                x.addBy(item);\n            }\n        }\n\n        if (attributes != null) {\n            x.attributes = (HashMap) ((HashMap) attributes).clone();\n        }\n\n        return x;\n    }\n\n    public void addBy(SQLExpr item) {\n        if (item == null) {\n            return;\n        }\n\n        if (by == null) {\n            by = new ArrayList<>(1);\n        }\n        by.add(item);\n        item.setParent(this);\n    }\n\n    public List<SQLExpr> getBy() {\n        return by;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (rowCount == expr) {\n            setRowCount(target);\n            return true;\n        }\n\n        if (offset == expr) {\n            setOffset(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLLimit limit = (SQLLimit) o;\n\n        if (rowCount != null ? !rowCount.equals(limit.rowCount) : limit.rowCount != null) {\n            return false;\n        }\n        return offset != null ? offset.equals(limit.offset) : limit.offset == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = rowCount != null ? rowCount.hashCode() : 0;\n        result = 31 * result + (offset != null ? offset.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLMapDataType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.sql.Types;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLMapDataType extends SQLObjectImpl implements SQLDataType {\n    public static final SQLMapDataType MAP_CHAR_CHAR = new SQLMapDataType(SQLCharExpr.DATA_TYPE, SQLCharExpr.DATA_TYPE);\n\n    private DbType dbType;\n    private SQLDataType keyType;\n    private SQLDataType valueType;\n\n    public SQLMapDataType() {\n    }\n\n    public SQLMapDataType(SQLDataType keyType, SQLDataType valueType) {\n        this.setKeyType(keyType);\n        this.setValueType(valueType);\n    }\n\n    public SQLMapDataType(SQLDataType keyType, SQLDataType valueType, DbType dbType) {\n        this.setKeyType(keyType);\n        this.setValueType(valueType);\n        this.dbType = dbType;\n    }\n\n    @Override\n    public String getName() {\n        return \"MAP\";\n    }\n\n    @Override\n    public long nameHashCode64() {\n        return FnvHash.Constants.MAP;\n    }\n\n    @Override\n    public void setName(String name) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public List<SQLExpr> getArguments() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Boolean getWithTimeZone() {\n        return null;\n    }\n\n    @Override\n    public void setWithTimeZone(Boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public boolean isWithLocalTimeZone() {\n        return false;\n    }\n\n    @Override\n    public void setWithLocalTimeZone(boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, keyType);\n            acceptChild(visitor, valueType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLMapDataType clone() {\n        SQLMapDataType x = new SQLMapDataType();\n        x.dbType = dbType;\n\n        if (keyType != null) {\n            x.setKeyType(keyType.clone());\n        }\n\n        if (valueType != null) {\n            x.setValueType(valueType.clone());\n        }\n\n        return x;\n    }\n\n    public SQLDataType getKeyType() {\n        return keyType;\n    }\n\n    public void setKeyType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.keyType = x;\n    }\n\n    public SQLDataType getValueType() {\n        return valueType;\n    }\n\n    public void setValueType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.valueType = x;\n    }\n\n    public int jdbcType() {\n        return Types.OTHER;\n    }\n\n    @Override\n    public boolean isInt() {\n        return false;\n    }\n\n    @Override\n    public boolean isNumberic() {\n        return false;\n    }\n\n    @Override\n    public boolean isString() {\n        return false;\n    }\n\n    @Override\n    public boolean hasKeyLength() {\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLName.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\n\npublic interface SQLName extends SQLExpr {\n    String getSimpleName();\n\n    SQLName clone();\n\n    long nameHashCode64();\n\n    long hashCode64();\n\n    SQLColumnDefinition getResolvedColumn();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface SQLObject {\n    default int getSourceColumn() {\n        return 0;\n    }\n\n    default int getSourceLine() {\n        return 0;\n    }\n\n    default void setSource(int column, int line) {\n    }\n\n    void accept(SQLASTVisitor visitor);\n\n    SQLObject clone();\n\n    SQLObject getParent();\n    SQLObject getParent(int level);\n\n    void setParent(SQLObject parent);\n\n    Map<String, Object> getAttributes();\n\n    boolean containsAttribute(String name);\n\n    Object getAttribute(String name);\n\n    void putAttribute(String name, Object value);\n\n    Map<String, Object> getAttributesDirect();\n\n    void output(StringBuilder buf);\n\n    void addBeforeComment(String comment);\n\n    void addBeforeComment(List<String> comments);\n\n    List<String> getBeforeCommentsDirect();\n\n    void addAfterComment(String comment);\n\n    void addAfterComment(List<String> comments);\n\n    List<String> getAfterCommentsDirect();\n\n    boolean hasBeforeComment();\n\n    boolean hasAfterComment();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic abstract class SQLObjectImpl implements SQLObject {\n    protected SQLObject parent;\n    protected Map<String, Object> attributes;\n    protected SQLCommentHint hint;\n\n    protected int sourceLine;\n    protected int sourceColumn;\n\n    public SQLObjectImpl() {\n    }\n\n    protected void cloneTo(SQLObjectImpl x) {\n        x.parent = this.parent;\n        if (this.attributes != null) {\n            x.attributes = new HashMap<>(attributes);\n        }\n        x.sourceLine = this.sourceLine;\n        x.sourceColumn = this.sourceColumn;\n    }\n\n    public final void accept(SQLASTVisitor visitor) {\n        if (visitor == null) {\n            throw new IllegalArgumentException();\n        }\n\n        visitor.preVisit(this);\n\n        accept0(visitor);\n\n        visitor.postVisit(this);\n    }\n\n    protected abstract void accept0(SQLASTVisitor v);\n\n    protected final void acceptChild(SQLASTVisitor visitor, List<? extends SQLObject> children) {\n        if (children == null) {\n            return;\n        }\n\n        for (int i = 0; i < children.size(); i++) {\n            acceptChild(visitor, children.get(i));\n        }\n    }\n\n    protected final void acceptChild(SQLASTVisitor visitor, SQLObject child) {\n        if (child == null) {\n            return;\n        }\n\n        child.accept(visitor);\n    }\n\n    public void output(StringBuilder buf) {\n        DbType dbType = null;\n        if (this instanceof OracleSQLObject) {\n            dbType = DbType.oracle;\n        } else if (this instanceof MySqlObject) {\n            dbType = DbType.mysql;\n        } else if (this instanceof PGSQLObject) {\n            dbType = DbType.postgresql;\n        } else if (this instanceof SQLServerObject) {\n            dbType = DbType.sqlserver;\n        } else if (this instanceof SQLDbTypedObject) {\n            dbType = ((SQLDbTypedObject) this).getDbType();\n        }\n\n        accept(\n                SQLUtils.createOutputVisitor(buf, dbType)\n        );\n    }\n\n    public String toString() {\n        StringBuilder buf = new StringBuilder();\n        output(buf);\n        return buf.toString();\n    }\n\n    public SQLObject getParent() {\n        return parent;\n    }\n    public SQLObject getParent(int level) {\n        if (level <= 0) {\n            throw new IllegalArgumentException(\"Get parent level should be greater than 0.\");\n        }\n        SQLObject parent = this;\n        while (level-- > 0) {\n            if (parent == null) {\n                return null;\n            }\n            parent = parent.getParent();\n        }\n        return parent;\n    }\n\n    public void setParent(SQLObject parent) {\n        this.parent = parent;\n    }\n\n    public Map<String, Object> getAttributes() {\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(1);\n        }\n\n        return attributes;\n    }\n\n    public Object getAttribute(String name) {\n        if (attributes == null) {\n            return null;\n        }\n\n        return attributes.get(name);\n    }\n\n    public boolean containsAttribute(String name) {\n        if (attributes == null) {\n            return false;\n        }\n\n        return attributes.containsKey(name);\n    }\n\n    public void putAttribute(String name, Object value) {\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(1);\n        }\n\n        attributes.put(name, value);\n    }\n\n    public Map<String, Object> getAttributesDirect() {\n        return attributes;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public void addBeforeComment(String comment) {\n        if (comment == null) {\n            return;\n        }\n\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(1);\n        }\n\n        List<String> comments = (List<String>) attributes.get(\"rowFormat.before_comment\");\n        if (comments == null) {\n            comments = new ArrayList<String>(2);\n            attributes.put(\"rowFormat.before_comment\", comments);\n        }\n\n        comments.add(comment);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public void addBeforeComment(List<String> comments) {\n        if (comments == null) {\n            return;\n        }\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(1);\n        }\n\n        List<String> attrComments = (List<String>) attributes.get(\"rowFormat.before_comment\");\n        if (attrComments == null) {\n            attributes.put(\"rowFormat.before_comment\", comments);\n        } else {\n            attrComments.addAll(comments);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public List<String> getBeforeCommentsDirect() {\n        if (attributes == null) {\n            return null;\n        }\n\n        return (List<String>) attributes.get(\"rowFormat.before_comment\");\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public void addAfterComment(String comment) {\n        if (comment == null) {\n            return;\n        }\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(1);\n        }\n\n        List<String> comments = (List<String>) attributes.get(\"rowFormat.after_comment\");\n        if (comments == null) {\n            comments = new ArrayList<String>(2);\n            attributes.put(\"rowFormat.after_comment\", comments);\n        }\n\n        comments.add(comment);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public void addAfterComment(List<String> comments) {\n        if (comments == null) {\n            return;\n        }\n\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(1);\n        }\n\n        List<String> attrComments = (List<String>) attributes.get(\"rowFormat.after_comment\");\n        if (attrComments == null) {\n            attributes.put(\"rowFormat.after_comment\", comments);\n        } else {\n            attrComments.addAll(comments);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public List<String> getAfterCommentsDirect() {\n        if (attributes == null) {\n            return null;\n        }\n\n        return (List<String>) attributes.get(\"rowFormat.after_comment\");\n    }\n\n    public boolean hasBeforeComment() {\n        if (attributes == null) {\n            return false;\n        }\n\n        List<String> comments = (List<String>) attributes.get(\"rowFormat.before_comment\");\n\n        if (comments == null) {\n            return false;\n        }\n\n        return !comments.isEmpty();\n    }\n\n    public boolean hasAfterComment() {\n        if (attributes == null) {\n            return false;\n        }\n\n        List<String> comments = (List<String>) attributes.get(\"rowFormat.after_comment\");\n        if (comments == null) {\n            return false;\n        }\n\n        return !comments.isEmpty();\n    }\n\n    public SQLObject clone() {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n\n    public SQLDataType computeDataType() {\n        return null;\n    }\n\n    public int getSourceLine() {\n        return sourceLine;\n    }\n\n    public void setSourceLine(int sourceLine) {\n        this.sourceLine = sourceLine;\n    }\n\n    public int getSourceColumn() {\n        return sourceColumn;\n    }\n\n    public void setSource(int line, int column) {\n        this.sourceLine = line;\n        this.sourceColumn = column;\n    }\n\n    public SQLCommentHint getHint() {\n        return hint;\n    }\n\n    public void setHint(SQLCommentHint hint) {\n        this.hint = hint;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLObjectWithDataType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\npublic interface SQLObjectWithDataType extends SQLObject {\n    SQLDataType getDataType();\n\n    void setDataType(SQLDataType dataType);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLOrderBy.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class SQLOrderBy extends SQLObjectImpl implements SQLReplaceable {\n    protected final List<SQLSelectOrderByItem> items = new ArrayList<SQLSelectOrderByItem>();\n\n    // for postgres\n    private boolean siblings;\n\n    public SQLOrderBy() {\n    }\n\n    public SQLOrderBy(SQLExpr expr) {\n        SQLSelectOrderByItem item = new SQLSelectOrderByItem(expr);\n        addItem(item);\n    }\n\n    public SQLOrderBy(SQLExpr expr, SQLOrderingSpecification type) {\n        SQLSelectOrderByItem item = new SQLSelectOrderByItem(expr, type);\n        addItem(item);\n    }\n\n    public void addItem(SQLSelectOrderByItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public void addItem(SQLExpr item) {\n        addItem(new SQLSelectOrderByItem(item));\n    }\n\n    public List<SQLSelectOrderByItem> getItems() {\n        return this.items;\n    }\n\n    public boolean isSiblings() {\n        return this.siblings;\n    }\n\n    public void setSiblings(boolean siblings) {\n        this.siblings = siblings;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            for (int i = 0; i < this.items.size(); i++) {\n                final SQLSelectOrderByItem item = this.items.get(i);\n                item.accept(v);\n            }\n        }\n\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLOrderBy order = (SQLOrderBy) o;\n\n        if (siblings != order.siblings) {\n            return false;\n        }\n        return items.equals(order.items);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = items.hashCode();\n        result = 31 * result + (siblings ? 1 : 0);\n        return result;\n    }\n\n    public void addItem(SQLExpr expr, SQLOrderingSpecification type) {\n        SQLSelectOrderByItem item = createItem();\n        item.setExpr(expr);\n        item.setType(type);\n        addItem(item);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (SQLSelectOrderByItem item : items) {\n            if (item.replace(expr, target)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    protected SQLSelectOrderByItem createItem() {\n        return new SQLSelectOrderByItem();\n    }\n\n    public SQLOrderBy clone() {\n        SQLOrderBy x = new SQLOrderBy();\n\n        for (SQLSelectOrderByItem item : items) {\n            SQLSelectOrderByItem item1 = item.clone();\n            item1.setParent(x);\n            x.items.add(item1);\n        }\n\n        x.siblings = siblings;\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLOrderingSpecification.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\npublic enum SQLOrderingSpecification {\n    ASC(\"ASC\"), DESC(\"DESC\");\n\n    public final String name;\n    public final String nameLCase;\n\n    private SQLOrderingSpecification(String name) {\n        this.name = name;\n        this.nameLCase = name.toLowerCase();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLOver.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npublic class SQLOver extends SQLObjectImpl implements SQLReplaceable {\n    protected final List<SQLExpr> partitionBy = new ArrayList<SQLExpr>();\n    protected SQLOrderBy orderBy;\n    protected SQLOrderBy distributeBy;\n    protected SQLOrderBy sortBy;\n    protected SQLOrderBy clusterBy;\n\n    // for db2\n    protected SQLName of;\n\n    protected WindowingType windowingType;\n\n    protected boolean windowingPreceding;\n    protected boolean windowingFollowing;\n\n    protected SQLExpr windowingBetweenBegin;\n    protected WindowingBound windowingBetweenBeginBound;\n\n    protected SQLExpr windowingBetweenEnd;\n    protected WindowingBound windowingBetweenEndBound;\n\n    protected boolean excludeCurrentRow;\n\n    public SQLOver() {\n    }\n\n    public SQLOver(SQLOrderBy orderBy) {\n        this.setOrderBy(orderBy);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (partitionBy != null) {\n                for (SQLExpr item : partitionBy) {\n                    if (item != null) {\n                        item.accept(visitor);\n                    }\n                }\n            }\n\n            if (orderBy != null) {\n                orderBy.accept(visitor);\n            }\n\n            if (distributeBy != null) {\n                distributeBy.accept(visitor);\n            }\n\n            if (sortBy != null) {\n                sortBy.accept(visitor);\n            }\n\n            if (clusterBy != null) {\n                clusterBy.accept(visitor);\n            }\n\n            if (of != null) {\n                of.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.orderBy = x;\n    }\n\n    public SQLOrderBy getClusterBy() {\n        return clusterBy;\n    }\n\n    public void setClusterBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.clusterBy = x;\n    }\n\n    public SQLOrderBy getDistributeBy() {\n        return distributeBy;\n    }\n\n    public void setDistributeBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.distributeBy = x;\n    }\n\n    public SQLOrderBy getSortBy() {\n        return sortBy;\n    }\n\n    public void setSortBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.sortBy = x;\n    }\n\n    public SQLName getOf() {\n        return of;\n    }\n\n    public void setOf(SQLName of) {\n        if (of != null) {\n            of.setParent(this);\n        }\n        this.of = of;\n    }\n\n    public List<SQLExpr> getPartitionBy() {\n        return partitionBy;\n    }\n\n    public WindowingType getWindowingType() {\n        return windowingType;\n    }\n\n    public void setWindowingType(WindowingType windowingType) {\n        this.windowingType = windowingType;\n    }\n\n    public boolean isWindowingPreceding() {\n        return windowingPreceding;\n    }\n\n    public void setWindowingPreceding(boolean windowingPreceding) {\n        this.windowingPreceding = windowingPreceding;\n    }\n\n    public SQLExpr getWindowingBetweenBegin() {\n        return windowingBetweenBegin;\n    }\n\n    public void setWindowingBetweenBegin(SQLExpr windowingBetweenBegin) {\n        this.windowingBetweenBegin = windowingBetweenBegin;\n    }\n\n    public SQLExpr getWindowingBetweenEnd() {\n        return windowingBetweenEnd;\n    }\n\n    public void setWindowingBetweenEnd(SQLExpr windowingBetweenEnd) {\n        this.windowingBetweenEnd = windowingBetweenEnd;\n    }\n\n    public boolean isWindowingBetweenEndPreceding() {\n        return windowingBetweenEndBound == WindowingBound.PRECEDING;\n    }\n\n    public boolean isWindowingBetweenEndFollowing() {\n        return windowingBetweenEndBound == WindowingBound.FOLLOWING;\n    }\n\n    public WindowingBound getWindowingBetweenBeginBound() {\n        return windowingBetweenBeginBound;\n    }\n\n    public void setWindowingBetweenBeginBound(WindowingBound windowingBetweenBeginBound) {\n        this.windowingBetweenBeginBound = windowingBetweenBeginBound;\n    }\n\n    public WindowingBound getWindowingBetweenEndBound() {\n        return windowingBetweenEndBound;\n    }\n\n    public void setWindowingBetweenEndBound(WindowingBound windowingBetweenEndBound) {\n        this.windowingBetweenEndBound = windowingBetweenEndBound;\n    }\n\n    public boolean isExcludeCurrentRow() {\n        return excludeCurrentRow;\n    }\n\n    public void setExcludeCurrentRow(boolean excludeCurrentRow) {\n        this.excludeCurrentRow = excludeCurrentRow;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLOver sqlOver = (SQLOver) o;\n\n        if (windowingPreceding != sqlOver.windowingPreceding) {\n            return false;\n        }\n        if (windowingFollowing != sqlOver.windowingFollowing) {\n            return false;\n        }\n        if (!partitionBy.equals(sqlOver.partitionBy)) {\n            return false;\n        }\n        if (orderBy != null ? !orderBy.equals(sqlOver.orderBy) : sqlOver.orderBy != null) {\n            return false;\n        }\n        if (of != null ? !of.equals(sqlOver.of) : sqlOver.of != null) {\n            return false;\n        }\n        if (windowingType != sqlOver.windowingType) {\n            return false;\n        }\n        if (windowingBetweenBegin != null ? !windowingBetweenBegin.equals(sqlOver.windowingBetweenBegin) : sqlOver.windowingBetweenBegin != null) {\n            return false;\n        }\n        if (windowingBetweenBeginBound != sqlOver.windowingBetweenBeginBound) {\n            return false;\n        }\n        if (windowingBetweenEnd != null ? !windowingBetweenEnd.equals(sqlOver.windowingBetweenEnd) : sqlOver.windowingBetweenEnd != null) {\n            return false;\n        }\n        return windowingBetweenEndBound == sqlOver.windowingBetweenEndBound;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = partitionBy != null ? partitionBy.hashCode() : 0;\n        result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);\n        result = 31 * result + (of != null ? of.hashCode() : 0);\n        result = 31 * result + (windowingType != null ? windowingType.hashCode() : 0);\n        result = 31 * result + (windowingPreceding ? 1 : 0);\n        result = 31 * result + (windowingFollowing ? 1 : 0);\n        result = 31 * result + (windowingBetweenBegin != null ? windowingBetweenBegin.hashCode() : 0);\n        result = 31 * result + (windowingBetweenBeginBound != null ? windowingBetweenBeginBound.hashCode() : 0);\n        result = 31 * result + (windowingBetweenEnd != null ? windowingBetweenEnd.hashCode() : 0);\n        result = 31 * result + (windowingBetweenEndBound != null ? windowingBetweenEndBound.hashCode() : 0);\n        return result;\n    }\n\n    public void cloneTo(SQLOver x) {\n        for (SQLExpr item : partitionBy) {\n            SQLExpr item1 = item.clone();\n            item1.setParent(x);\n            x.partitionBy.add(item1);\n        }\n\n        if (orderBy != null) {\n            x.setOrderBy(orderBy.clone());\n        }\n\n        if (of != null) {\n            x.setOf(of.clone());\n        }\n\n        x.windowingType = windowingType;\n        x.windowingPreceding = windowingPreceding;\n        x.windowingFollowing = windowingFollowing;\n\n        if (windowingBetweenBegin != null) {\n            x.setWindowingBetweenBegin(windowingBetweenBegin.clone());\n        }\n        x.windowingBetweenBeginBound = windowingBetweenBeginBound;\n        x.windowingBetweenEndBound = windowingBetweenEndBound;\n\n        if (windowingBetweenEnd != null) {\n            x.setWindowingBetweenEnd(windowingBetweenEnd.clone());\n        }\n    }\n\n    public SQLOver clone() {\n        SQLOver x = new SQLOver();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (windowingBetweenBegin == expr) {\n            setWindowingBetweenBegin(target);\n            return true;\n        }\n\n        if (windowingBetweenEnd == expr) {\n            setWindowingBetweenEnd(target);\n            return true;\n        }\n\n        for (int i = 0; i < partitionBy.size(); i++) {\n            if (partitionBy.get(i) == expr) {\n                partitionBy.set(i, target);\n                target.setParent(this);\n            }\n        }\n\n        return false;\n    }\n\n    public static enum WindowingType {\n        ROWS(\"ROWS\"), RANGE(\"RANGE\");\n\n        public final String name;\n        public final String nameLCase;\n\n        private WindowingType(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n    }\n\n    public static enum WindowingBound {\n        UNBOUNDED_PRECEDING(\"UNBOUNDED PRECEDING\"),\n        PRECEDING(\"PRECEDING\"),\n        CURRENT_ROW(\"CURRENT ROW\"),\n        FOLLOWING(\"FOLLOWING\"),\n        UNBOUNDED_FOLLOWING(\"UNBOUNDED FOLLOWING\");\n\n        public final String name;\n        public final String nameLCase;\n\n        private WindowingBound(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLParameter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class SQLParameter extends SQLObjectImpl implements SQLObjectWithDataType {\n    private SQLName name;\n    private SQLDataType dataType;\n    private SQLExpr defaultValue;\n    private ParameterType paramType;\n    private boolean noCopy;\n    private boolean constant;\n    private boolean isNotNull;\n    private SQLName cursorName;\n    private final List<SQLParameter> cursorParameters = new ArrayList<>();\n    private boolean order;\n    private boolean map;\n    private boolean member;\n\n    public SQLParameter() {\n    }\n\n    public SQLParameter(SQLName name, SQLDataType dataType) {\n        this.setName(name);\n        this.setDataType(dataType);\n    }\n\n    public SQLParameter(SQLName name, SQLDataType dataType, SQLExpr defaultValue) {\n        this.setName(name);\n        this.setDataType(dataType);\n        this.setDefaultValue(defaultValue);\n    }\n\n    public SQLDataType computeDataType() {\n        return dataType;\n    }\n\n    public SQLExpr getDefaultValue() {\n        return defaultValue;\n    }\n\n    public void setDefaultValue(SQLExpr deaultValue) {\n        if (deaultValue != null) {\n            deaultValue.setParent(this);\n        }\n        this.defaultValue = deaultValue;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    public void setDataType(SQLDataType dataType) {\n        if (dataType != null) {\n            dataType.setParent(this);\n        }\n        this.dataType = dataType;\n    }\n\n    public ParameterType getParamType() {\n        return paramType;\n    }\n\n    public void setParamType(ParameterType paramType) {\n        this.paramType = paramType;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, dataType);\n            acceptChild(visitor, defaultValue);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void setNotNull(boolean isNotNull) {\n        this.isNotNull = isNotNull;\n    }\n\n    public boolean isNotNull() {\n        return this.isNotNull;\n    }\n\n    public static enum ParameterType {\n        DEFAULT,\n        IN, // in\n        OUT, // out\n        INOUT// inout\n    }\n\n    public boolean isNoCopy() {\n        return noCopy;\n    }\n\n    public void setNoCopy(boolean noCopy) {\n        this.noCopy = noCopy;\n    }\n\n    public boolean isConstant() {\n        return constant;\n    }\n\n    public void setConstant(boolean constant) {\n        this.constant = constant;\n    }\n\n    public List<SQLParameter> getCursorParameters() {\n        return cursorParameters;\n    }\n\n    public SQLName getCursorName() {\n        return cursorName;\n    }\n\n    public void setCursorName(SQLName cursorName) {\n        if (cursorName != null) {\n            cursorName.setParent(this);\n        }\n        this.cursorName = cursorName;\n    }\n\n    public SQLParameter clone() {\n        SQLParameter x = new SQLParameter();\n        if (name != null) {\n            x.setName(name.clone());\n        }\n        if (dataType != null) {\n            x.setDataType(dataType.clone());\n        }\n        if (defaultValue != null) {\n            x.setDefaultValue(defaultValue.clone());\n        }\n        x.paramType = paramType;\n        x.noCopy = noCopy;\n        x.constant = constant;\n        x.order = order;\n        x.map = map;\n        if (cursorName != null) {\n            x.setCursorName(cursorName.clone());\n        }\n        for (SQLParameter p : cursorParameters) {\n            SQLParameter p2 = p.clone();\n            p2.setParent(x);\n            x.cursorParameters.add(p2);\n        }\n        return x;\n    }\n\n    public boolean isOrder() {\n        return order;\n    }\n\n    public void setOrder(boolean order) {\n        this.order = order;\n    }\n\n    public boolean isMap() {\n        return map;\n    }\n\n    public void setMap(boolean map) {\n        this.map = map;\n    }\n\n    public boolean isMember() {\n        return member;\n    }\n\n    public void setMember(boolean member) {\n        this.member = member;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartition.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class SQLPartition extends SQLObjectImpl {\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public SQLPartition clone() {\n        throw new UnsupportedOperationException();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionBatch.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPartitionBatch extends SQLPartition {\n    private SQLExpr start;\n    private SQLExpr end;\n    private SQLExpr every;\n\n    public SQLExpr getStart() {\n        return start;\n    }\n\n    public void setStart(SQLExpr start) {\n        this.start = start;\n    }\n\n    public SQLExpr getEnd() {\n        return end;\n    }\n\n    public void setEnd(SQLExpr end) {\n        this.end = end;\n    }\n\n    public SQLExpr getEvery() {\n        return every;\n    }\n\n    public void setEvery(SQLExpr every) {\n        this.every = every;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, start);\n            acceptChild(v, end);\n            acceptChild(v, every);\n        }\n        v.endVisit(this);\n    }\n    @Override\n    public SQLPartitionBatch clone() {\n        SQLPartitionBatch sqlPartitionBatch = new SQLPartitionBatch();\n        sqlPartitionBatch.setStart(start);\n        sqlPartitionBatch.setEnd(end);\n        sqlPartitionBatch.setEvery(every);\n        sqlPartitionBatch.setParent(parent);\n        return sqlPartitionBatch;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionBy.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class SQLPartitionBy extends SQLObjectImpl {\n    protected SQLSubPartitionBy subPartitionBy;\n    protected SQLExpr partitionsCount;\n    protected boolean linear;\n    protected List<SQLPartition> partitions = new ArrayList<>();\n    protected List<SQLName> storeIn = new ArrayList<SQLName>();\n    protected List<SQLExpr> columns = new ArrayList<SQLExpr>();\n    protected Boolean auto;\n    protected Boolean logical;\n\n    protected SQLIntegerExpr lifeCycle;\n\n    public List<SQLPartition> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLPartition partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    public SQLSubPartitionBy getSubPartitionBy() {\n        return subPartitionBy;\n    }\n\n    public void setSubPartitionBy(SQLSubPartitionBy subPartitionBy) {\n        if (subPartitionBy != null) {\n            subPartitionBy.setParent(this);\n        }\n        this.subPartitionBy = subPartitionBy;\n    }\n\n    public SQLExpr getPartitionsCount() {\n        return partitionsCount;\n    }\n\n    public void setPartitionsCount(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partitionsCount = x;\n    }\n\n    public void setPartitionsCount(int partitionsCount) {\n        this.partitionsCount = new SQLIntegerExpr(partitionsCount);\n    }\n\n    public boolean isLinear() {\n        return linear;\n    }\n\n    public void setLinear(boolean linear) {\n        this.linear = linear;\n    }\n\n    public List<SQLName> getStoreIn() {\n        return storeIn;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLExpr column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public Boolean getAuto() {\n        return this.auto;\n    }\n\n    public void setAuto(Boolean auto) {\n        this.auto = auto;\n    }\n\n    public Boolean getLogical() {\n        return logical;\n    }\n\n    public void setLogical(Boolean logical) {\n        this.logical = logical;\n    }\n\n    public void cloneTo(SQLPartitionBy x) {\n        if (subPartitionBy != null) {\n            x.setSubPartitionBy(subPartitionBy.clone());\n        }\n        if (partitionsCount != null) {\n            x.setPartitionsCount(partitionsCount.clone());\n        }\n        x.linear = linear;\n        for (SQLPartition p : partitions) {\n            SQLPartition p2 = p.clone();\n            p2.setParent(x);\n            x.partitions.add(p2);\n        }\n        for (SQLName name : storeIn) {\n            SQLName name2 = name.clone();\n            name2.setParent(x);\n            x.storeIn.add(name2);\n        }\n\n        x.lifeCycle = lifeCycle;\n    }\n\n    public boolean isPartitionByColumn(long columnNameHashCode64) {\n        for (SQLExpr column : columns) {\n            if (column instanceof SQLIdentifierExpr\n                    && ((SQLIdentifierExpr) column)\n                    .nameHashCode64() == columnNameHashCode64) {\n                return true;\n            }\n        }\n\n        if (subPartitionBy != null) {\n            return subPartitionBy.isPartitionByColumn(columnNameHashCode64);\n        }\n        return false;\n    }\n\n    public SQLIntegerExpr getLifeCycle() {\n        return lifeCycle;\n    }\n\n    public void setLifeCycle(SQLIntegerExpr x) {\n        this.lifeCycle = x;\n    }\n\n    public abstract SQLPartitionBy clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionByHash.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPartitionByHash extends SQLPartitionBy {\n    // for aliyun ads\n    protected boolean key;\n    protected boolean unique;\n\n    public boolean isKey() {\n        return key;\n    }\n\n    public void setKey(boolean key) {\n        this.key = key;\n    }\n\n    public boolean isUnique() {\n        return unique;\n    }\n\n    public void setUnique(boolean unique) {\n        this.unique = unique;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, partitionsCount);\n            acceptChild(visitor, getPartitions());\n            acceptChild(visitor, subPartitionBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLPartitionByHash clone() {\n        SQLPartitionByHash x = new SQLPartitionByHash();\n\n        cloneTo(x);\n\n        x.key = key;\n        x.unique = unique;\n\n        for (SQLExpr column : columns) {\n            SQLExpr c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n        return x;\n    }\n\n    public void cloneTo(SQLPartitionByHash x) {\n        super.cloneTo(x);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionByList.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPartitionByList extends SQLPartitionBy {\n    protected PartitionByListType type;\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, partitionsCount);\n            acceptChild(visitor, getPartitions());\n            acceptChild(visitor, subPartitionBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public PartitionByListType getType() {\n        return type;\n    }\n\n    public void setType(PartitionByListType type) {\n        this.type = type;\n    }\n\n    public SQLPartitionByList clone() {\n        SQLPartitionByList x = new SQLPartitionByList();\n\n        this.cloneTo(x);\n\n        for (SQLExpr column : columns) {\n            SQLExpr c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n        return x;\n    }\n\n    public void cloneTo(SQLPartitionByList x) {\n        super.cloneTo(x);\n    }\n    public enum PartitionByListType {\n        LIST_EXPRESSION,\n        LIST_COLUMNS,\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionByRange.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPartitionByRange extends SQLPartitionBy {\n    protected SQLExpr interval;\n    protected boolean isColumns;\n    protected SQLExpr startWith;\n    protected SQLIntegerExpr expireAfter;\n    protected SQLIntegerExpr preAllocate;\n    protected SQLExpr pivotDateExpr;\n    protected boolean disableSchedule;\n\n    public SQLPartitionByRange() {\n    }\n\n    public SQLExpr getInterval() {\n        return interval;\n    }\n\n    public void setInterval(SQLExpr interval) {\n        if (interval != null) {\n            interval.setParent(this);\n        }\n\n        this.interval = interval;\n    }\n\n    public SQLExpr getStartWith() {\n        return this.startWith;\n    }\n\n    public void setStartWith(final SQLExpr startWith) {\n        if (startWith != null) {\n            startWith.setParent(this);\n        }\n\n        this.startWith = startWith;\n    }\n\n    public SQLIntegerExpr getExpireAfter() {\n        return this.expireAfter;\n    }\n\n    public void setExpireAfter(final SQLIntegerExpr expireAfter) {\n        if (expireAfter != null) {\n            expireAfter.setParent(this);\n        }\n        this.expireAfter = expireAfter;\n    }\n\n    public SQLIntegerExpr getPreAllocate() {\n        return this.preAllocate;\n    }\n\n    public void setPreAllocate(final SQLIntegerExpr preAllocate) {\n        if (preAllocate != null) {\n            preAllocate.setParent(this);\n        }\n        this.preAllocate = preAllocate;\n    }\n\n    public SQLExpr getPivotDateExpr() {\n        return this.pivotDateExpr;\n    }\n\n    public void setPivotDateExpr(final SQLExpr pivotDateExpr) {\n        if (pivotDateExpr != null) {\n            pivotDateExpr.setParent(this);\n        }\n        this.pivotDateExpr = pivotDateExpr;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, interval);\n            acceptChild(visitor, expireAfter);\n            acceptChild(visitor, preAllocate);\n            acceptChild(visitor, pivotDateExpr);\n            acceptChild(visitor, columns);\n            acceptChild(visitor, storeIn);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, subPartitionBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLPartitionByRange clone() {\n        SQLPartitionByRange x = new SQLPartitionByRange();\n\n        this.cloneTo(x);\n\n        if (interval != null) {\n            x.setInterval(interval.clone());\n        }\n\n        if (startWith != null) {\n            x.setStartWith(startWith.clone());\n        }\n\n        if (expireAfter != null) {\n            x.setExpireAfter(expireAfter.clone());\n        }\n\n        for (SQLExpr column : columns) {\n            SQLExpr c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n        x.setColumns(this.isColumns);\n        x.setDisableSchedule(this.disableSchedule);\n\n        return x;\n    }\n\n    public void cloneTo(SQLPartitionByRange x) {\n        super.cloneTo(x);\n    }\n\n    public boolean isColumns() {\n        return isColumns;\n    }\n\n    public void setColumns(boolean columns) {\n        isColumns = columns;\n    }\n\n    public boolean isDisableSchedule() {\n        return this.disableSchedule;\n    }\n\n    public void setDisableSchedule(final boolean disableSchedule) {\n        this.disableSchedule = disableSchedule;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionByValue.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPartitionByValue extends SQLPartitionBy {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, storeIn);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, subPartitionBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLPartitionByValue clone() {\n        SQLPartitionByValue x = new SQLPartitionByValue();\n\n        cloneTo(x);\n\n        for (SQLExpr column : columns) {\n            SQLExpr c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n        return x;\n    }\n\n    public void cloneTo(SQLPartitionByValue x) {\n        super.cloneTo(x);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionOf.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\n/**\n * @author lizongbo\n */\npublic class SQLPartitionOf extends SQLObjectImpl {\n    protected SQLExprTableSource parentTable;\n    private boolean useDefault;\n    private SQLName columnName;\n    private SQLName constraintName;\n    private SQLExpr checkExpr;\n    private SQLExpr defaultExpr;\n    private List<SQLExpr> forValuesFrom;\n    private List<SQLExpr> forValuesTo;\n    private List<SQLExpr> forValuesIn;\n\n    private SQLExpr forValuesModulus;\n\n    private SQLExpr forValuesRemainder;\n\n    public SQLExprTableSource getParentTable() {\n        return parentTable;\n    }\n\n    public void setParentTable(SQLExprTableSource parentTable) {\n        this.parentTable = parentTable;\n    }\n\n    public boolean isUseDefault() {\n        return useDefault;\n    }\n\n    public void setUseDefault(boolean useDefault) {\n        this.useDefault = useDefault;\n    }\n\n    public List<SQLExpr> getForValuesFrom() {\n        return forValuesFrom;\n    }\n\n    public void setForValuesFrom(List<SQLExpr> forValuesFrom) {\n        this.forValuesFrom = forValuesFrom;\n    }\n\n    public List<SQLExpr> getForValuesTo() {\n        return forValuesTo;\n    }\n\n    public void setForValuesTo(List<SQLExpr> forValuesTo) {\n        this.forValuesTo = forValuesTo;\n    }\n\n    public List<SQLExpr> getForValuesIn() {\n        return forValuesIn;\n    }\n\n    public void setForValuesIn(List<SQLExpr> forValuesIn) {\n        this.forValuesIn = forValuesIn;\n    }\n\n    public SQLName getColumnName() {\n        return columnName;\n    }\n\n    public void setColumnName(SQLName columnName) {\n        this.columnName = columnName;\n    }\n\n    public SQLName getConstraintName() {\n        return constraintName;\n    }\n\n    public void setConstraintName(SQLName constraintName) {\n        this.constraintName = constraintName;\n    }\n\n    public SQLExpr getCheckExpr() {\n        return checkExpr;\n    }\n\n    public void setCheckExpr(SQLExpr checkExpr) {\n        this.checkExpr = checkExpr;\n    }\n\n    public SQLExpr getDefaultExpr() {\n        return defaultExpr;\n    }\n\n    public void setDefaultExpr(SQLExpr defaultExpr) {\n        this.defaultExpr = defaultExpr;\n    }\n\n    public SQLExpr getForValuesModulus() {\n        return forValuesModulus;\n    }\n\n    public void setForValuesModulus(SQLExpr forValuesModulus) {\n        this.forValuesModulus = forValuesModulus;\n    }\n\n    public SQLExpr getForValuesRemainder() {\n        return forValuesRemainder;\n    }\n\n    public void setForValuesRemainder(SQLExpr forValuesRemainder) {\n        this.forValuesRemainder = forValuesRemainder;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, parentTable);\n            if (columnName != null) {\n                acceptChild(v, columnName);\n            }\n            if (constraintName != null) {\n                acceptChild(v, constraintName);\n            }\n            if (checkExpr != null) {\n                acceptChild(v, checkExpr);\n            }\n            if (defaultExpr != null) {\n                acceptChild(v, defaultExpr);\n            }\n            if (forValuesFrom != null) {\n                acceptChild(v, forValuesFrom);\n            }\n            if (forValuesTo != null) {\n                acceptChild(v, forValuesTo);\n            }\n            if (forValuesIn != null) {\n                acceptChild(v, forValuesIn);\n            }\n            if (forValuesModulus != null) {\n                acceptChild(v, forValuesModulus);\n            }\n            if (forValuesRemainder != null) {\n                acceptChild(v, forValuesRemainder);\n            }\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionSingle.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLPartitionSingle extends SQLPartition {\n    protected SQLName name;\n\n    protected SQLExpr subPartitionsCount;\n    protected List<SQLSubPartition> subPartitions = new ArrayList<>();\n\n    protected SQLPartitionValue values;\n    protected SQLName tablespace;\n    protected SQLExpr locality;\n\n    public SQLExpr getLocality() {\n        return locality;\n    }\n\n    public void setLocality(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.locality = x;\n    }\n\n    public SQLName getTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(SQLName tablespace) {\n        this.tablespace = tablespace;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getSubPartitionsCount() {\n        return subPartitionsCount;\n    }\n\n    public void setSubPartitionsCount(SQLExpr subPartitionsCount) {\n        if (subPartitionsCount != null) {\n            subPartitionsCount.setParent(this);\n        }\n        this.subPartitionsCount = subPartitionsCount;\n    }\n\n    public SQLPartitionValue getValues() {\n        return values;\n    }\n\n    public void setValues(SQLPartitionValue values) {\n        if (values != null) {\n            values.setParent(this);\n        }\n        this.values = values;\n    }\n\n    public List<SQLSubPartition> getSubPartitions() {\n        return subPartitions;\n    }\n\n    public void addSubPartition(SQLSubPartition partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.subPartitions.add(partition);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, values);\n            acceptChild(visitor, subPartitionsCount);\n            acceptChild(visitor, subPartitions);\n            acceptChild(visitor, tablespace);\n            acceptChild(visitor, locality);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public SQLPartitionSingle clone() {\n        SQLPartitionSingle x = new SQLPartitionSingle();\n\n        if (name != null) {\n            x.setName(name.clone());\n        }\n\n        if (subPartitionsCount != null) {\n            x.setSubPartitionsCount(subPartitionsCount.clone());\n        }\n\n        for (SQLSubPartition p : subPartitions) {\n            SQLSubPartition p2 = p.clone();\n            p2.setParent(x);\n            x.subPartitions.add(p2);\n        }\n\n        if (values != null) {\n            x.setValues(values.clone());\n        }\n\n        if (locality != null) {\n            x.setLocality(locality.clone());\n        }\n\n        if (tablespace != null) {\n            x.setTablespace(tablespace.clone());\n        }\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionSpec.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLPartitionSpec extends SQLObjectImpl implements Cloneable {\n    private List<Item> items = new ArrayList<Item>();\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, items);\n        }\n        v.endVisit(this);\n    }\n\n    public void addItem(Item item) {\n        item.setParent(this);\n        items.add(item);\n    }\n\n    public List<Item> getItems() {\n        return items;\n    }\n\n    public SQLPartitionSpec clone() {\n        SQLPartitionSpec x = new SQLPartitionSpec();\n\n        for (Item item : items) {\n            x.addItem(item.clone());\n        }\n\n        return x;\n    }\n\n    public static class Item extends SQLObjectImpl implements Cloneable {\n        private SQLName column;\n        private SQLExpr value;\n\n        @Override\n        protected void accept0(SQLASTVisitor v) {\n            if (v.visit(this)) {\n                acceptChild(v, column);\n                acceptChild(v, value);\n            }\n            v.endVisit(this);\n        }\n\n        public Item clone() {\n            Item x = new Item();\n\n            if (column != null) {\n                x.setColumn(column.clone());\n            }\n\n            if (value != null) {\n                x.setValue(value.clone());\n            }\n\n            return x;\n        }\n\n        public SQLName getColumn() {\n            return column;\n        }\n\n        public void setColumn(SQLName column) {\n            this.column = column;\n        }\n\n        public SQLExpr getValue() {\n            return value;\n        }\n\n        public void setValue(SQLExpr value) {\n            this.value = value;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPartitionValue.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributesImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLPartitionValue extends OracleSegmentAttributesImpl {\n    protected Operator operator;\n    protected final List<SQLExpr> items = new ArrayList<SQLExpr>();\n\n    public SQLPartitionValue() {\n    }\n\n    public SQLPartitionValue(Operator operator) {\n        super();\n        this.operator = operator;\n    }\n\n    public List<SQLExpr> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLExpr item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public Operator getOperator() {\n        return operator;\n    }\n\n    public enum Operator {\n        LessThan,\n        LessThanEqual,\n        Equal,\n        In,\n        List,\n        StartEndEvery,\n        FixedRange\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getItems());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLPartitionValue clone() {\n        SQLPartitionValue x = new SQLPartitionValue(operator);\n\n        for (SQLExpr item : items) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLPivot.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLPivot extends SQLObjectImpl {\n    protected boolean xml;\n    protected final List<SQLSelectItem> items = new ArrayList<SQLSelectItem>();\n    protected final List<SQLExpr> pivotFor = new ArrayList<>();\n    protected final List<SQLSelectItem> pivotIn = new ArrayList<>();\n\n    public List<SQLExpr> getPivotFor() {\n        return pivotFor;\n    }\n\n    public List<SQLSelectItem> getPivotIn() {\n        return pivotIn;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, this.items);\n            acceptChild(v, this.pivotFor);\n            acceptChild(v, this.pivotIn);\n        }\n        v.endVisit(this);\n    }\n\n    public List<SQLSelectItem> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLSelectItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public boolean isXml() {\n        return xml;\n    }\n\n    public void setXml(boolean xml) {\n        this.xml = xml;\n    }\n\n    @Override\n    public SQLPivot clone() {\n        SQLPivot x = new SQLPivot();\n\n        x.setXml(this.xml);\n\n        for (SQLSelectItem e : this.items) {\n            SQLSelectItem e2 = e.clone();\n            e2.setParent(x);\n            x.getItems().add(e2);\n        }\n\n        for (SQLExpr e : this.pivotFor) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.getPivotFor().add(e2);\n        }\n\n        for (SQLSelectItem e : this.pivotIn) {\n            SQLSelectItem e2 = e.clone();\n            e2.setParent(x);\n            x.getPivotIn().add(e2);\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLRecordDataType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLRecordDataType extends SQLDataTypeImpl implements SQLDataType {\n    private final List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();\n\n    public List<SQLColumnDefinition> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLColumnDefinition column) {\n        column.setParent(this);\n        this.columns.add(column);\n    }\n\n    public SQLRecordDataType clone() {\n        SQLRecordDataType x = new SQLRecordDataType();\n        cloneTo(x);\n\n        for (SQLColumnDefinition c : columns) {\n            SQLColumnDefinition c2 = c.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n        return x;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.columns);\n        }\n\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLReplaceable.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\n/**\n * Created by wenshao on 06/06/2017.\n */\npublic interface SQLReplaceable {\n    boolean replace(SQLExpr expr, SQLExpr target);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLResetStatement.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLResetStatement extends SQLStatementImpl {\n    private List<String> options = new ArrayList<String>();\n\n    public List<String> getOptions() {\n        return options;\n    }\n\n    public void setOptions(List<String> options) {\n        this.options = options;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLRowDataType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStructDataType.Field;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.sql.Types;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLRowDataType extends SQLObjectImpl implements SQLDataType {\n    private DbType dbType;\n    private List<Field> fields = new ArrayList<Field>();\n\n    public SQLRowDataType() {\n    }\n\n    public SQLRowDataType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public String getName() {\n        return \"ROW\";\n    }\n\n    @Override\n    public long nameHashCode64() {\n        return FnvHash.Constants.ROW;\n    }\n\n    @Override\n    public void setName(String name) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public List<SQLExpr> getArguments() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Boolean getWithTimeZone() {\n        return null;\n    }\n\n    @Override\n    public void setWithTimeZone(Boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public boolean isWithLocalTimeZone() {\n        return false;\n    }\n\n    @Override\n    public void setWithLocalTimeZone(boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, fields);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLRowDataType clone() {\n        SQLRowDataType x = new SQLRowDataType(dbType);\n\n        for (Field field : fields) {\n            x.addField(field.getName(), field.getDataType().clone());\n        }\n\n        return x;\n    }\n\n    public List<Field> getFields() {\n        return fields;\n    }\n\n    public Field addField(SQLName name, SQLDataType dataType) {\n        Field field = new Field(name, dataType);\n        field.setParent(this);\n        fields.add(field);\n        return field;\n    }\n\n    public int jdbcType() {\n        return Types.STRUCT;\n    }\n\n    @Override\n    public boolean isInt() {\n        return false;\n    }\n\n    @Override\n    public boolean isNumberic() {\n        return false;\n    }\n\n    @Override\n    public boolean isString() {\n        return false;\n    }\n\n    @Override\n    public boolean hasKeyLength() {\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLSetQuantifier.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\npublic interface SQLSetQuantifier {\n    // SQL 92\n    public static final int ALL = 1;\n    public static final int DISTINCT = 2;\n\n    public static final int UNIQUE = 3;\n    public static final int DISTINCTROW = 4;\n    public static final int ALL_EXCEPT = 5;\n    public static final int STRAIGHT_JOIN = 6;\n\n    // <SetQuantifier>\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\n\nimport java.util.List;\n\npublic interface SQLStatement extends SQLObject, SQLDbTypedObject {\n    DbType getDbType();\n\n    boolean isAfterSemi();\n\n    void setAfterSemi(boolean afterSemi);\n\n    SQLStatement clone();\n\n    List<SQLObject> getChildren();\n\n    List<SQLCommentHint> getHeadHintsDirect();\n\n    void setHeadHints(List<SQLCommentHint> headHints);\n\n    String toString();\n\n    String toString(VisitorFeature... features);\n\n    String toLowerCaseString();\n\n    String toParameterizedString();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLStatementImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\n\nimport java.util.List;\n\npublic abstract class SQLStatementImpl extends SQLObjectImpl implements SQLStatement {\n    protected DbType dbType;\n    protected boolean afterSemi;\n    protected List<SQLCommentHint> headHints;\n\n    public SQLStatementImpl() {\n    }\n\n    public SQLStatementImpl(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, dbType);\n    }\n\n    public String toString(VisitorFeature... features) {\n        return SQLUtils.toSQLString(this, dbType, null, features);\n    }\n\n    public String toLowerCaseString() {\n        return SQLUtils.toSQLString(this, dbType, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n    }\n\n    public String toUnformattedString() {\n        return SQLUtils.toSQLString(this, dbType, new SQLUtils.FormatOption(true, false));\n    }\n\n    public String toParameterizedString() {\n        return ParameterizedOutputVisitorUtils.parameterize(this, dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n\n    public List<SQLObject> getChildren() {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n\n    public boolean isAfterSemi() {\n        return afterSemi;\n    }\n\n    public void setAfterSemi(boolean afterSemi) {\n        this.afterSemi = afterSemi;\n    }\n\n    public SQLStatement clone() {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n\n    protected void cloneTo(SQLStatementImpl x) {\n        super.cloneTo(x);\n        x.dbType = dbType;\n        x.afterSemi = afterSemi;\n        x.headHints = headHints;\n    }\n\n    public List<SQLCommentHint> getHeadHintsDirect() {\n        return headHints;\n    }\n\n    public void setHeadHints(List<SQLCommentHint> headHints) {\n        this.headHints = headHints;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLStructDataType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.sql.Types;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLStructDataType extends SQLObjectImpl implements SQLDataType {\n    private DbType dbType;\n    private List<Field> fields = new ArrayList<Field>();\n\n    public SQLStructDataType() {\n    }\n\n    public SQLStructDataType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public String getName() {\n        return \"STRUCT\";\n    }\n\n    @Override\n    public long nameHashCode64() {\n        return FnvHash.Constants.STRUCT;\n    }\n\n    @Override\n    public void setName(String name) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public List<SQLExpr> getArguments() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Boolean getWithTimeZone() {\n        return null;\n    }\n\n    @Override\n    public void setWithTimeZone(Boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public boolean isWithLocalTimeZone() {\n        return false;\n    }\n\n    @Override\n    public void setWithLocalTimeZone(boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, fields);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLStructDataType clone() {\n        SQLStructDataType x = new SQLStructDataType(dbType);\n\n        for (Field field : fields) {\n            x.addField(field.name, field.dataType.clone());\n        }\n\n        return x;\n    }\n\n    public List<Field> getFields() {\n        return fields;\n    }\n\n    public Field addField(SQLName name, SQLDataType dataType) {\n        Field field = new Field(name, dataType);\n        field.setParent(this);\n        fields.add(field);\n        return field;\n    }\n\n    public int jdbcType() {\n        return Types.STRUCT;\n    }\n\n    @Override\n    public boolean isInt() {\n        return false;\n    }\n\n    @Override\n    public boolean isNumberic() {\n        return false;\n    }\n\n    @Override\n    public boolean isString() {\n        return false;\n    }\n\n    @Override\n    public boolean hasKeyLength() {\n        return false;\n    }\n\n    public static class Field extends SQLObjectImpl {\n        private SQLName name;\n        private SQLDataType dataType;\n        private final List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n        private String comment;\n        private List<SQLColumnConstraint> constraints = new ArrayList<>();\n\n        public Field(SQLName name, SQLDataType dataType) {\n            setName(name);\n            setDataType(dataType);\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, name);\n                acceptChild(visitor, dataType);\n                acceptChild(visitor, constraints);\n            }\n            visitor.endVisit(this);\n        }\n\n        public SQLName getName() {\n            return name;\n        }\n\n        public void setName(SQLName x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.name = x;\n        }\n\n        public List<SQLAssignItem> getOptions() {\n            return options;\n        }\n\n        public SQLDataType getDataType() {\n            return dataType;\n        }\n\n        public void setDataType(SQLDataType x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.dataType = x;\n        }\n\n        public String getComment() {\n            return comment;\n        }\n\n        public void setComment(String comment) {\n            this.comment = comment;\n        }\n\n        public void addConstraint(SQLColumnConstraint constraint) {\n            if (constraint != null) {\n                constraint.setParent(this);\n            }\n            this.constraints.add(constraint);\n        }\n\n        public List<SQLColumnConstraint> getConstraints() {\n            return constraints;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLSubPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributesImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLSubPartition extends OracleSegmentAttributesImpl {\n    protected SQLName name;\n    protected SQLPartitionValue values;\n    protected SQLName tableSpace;\n\n    // for mysql\n    protected SQLExpr dataDirectory;\n    protected SQLExpr indexDirectory;\n    protected SQLExpr maxRows;\n    protected SQLExpr minRows;\n    protected SQLExpr engine;\n    protected SQLExpr comment;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLPartitionValue getValues() {\n        return values;\n    }\n\n    public void setValues(SQLPartitionValue values) {\n        if (values != null) {\n            values.setParent(this);\n        }\n        this.values = values;\n    }\n\n    public SQLName getTableSpace() {\n        return tableSpace;\n    }\n\n    public void setTableSpace(SQLName tableSpace) {\n        if (tableSpace != null) {\n            tableSpace.setParent(this);\n        }\n        this.tableSpace = tableSpace;\n    }\n\n    public SQLExpr getDataDirectory() {\n        return dataDirectory;\n    }\n\n    public void setDataDirectory(SQLExpr dataDirectory) {\n        this.dataDirectory = dataDirectory;\n    }\n\n    public SQLExpr getIndexDirectory() {\n        return indexDirectory;\n    }\n\n    public void setIndexDirectory(SQLExpr indexDirectory) {\n        this.indexDirectory = indexDirectory;\n    }\n\n    public SQLExpr getMaxRows() {\n        return maxRows;\n    }\n\n    public void setMaxRows(SQLExpr maxRows) {\n        this.maxRows = maxRows;\n    }\n\n    public SQLExpr getMinRows() {\n        return minRows;\n    }\n\n    public void setMinRows(SQLExpr minRows) {\n        this.minRows = minRows;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr engine) {\n        this.engine = engine;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        this.comment = comment;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, tableSpace);\n            acceptChild(visitor, values);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLSubPartition clone() {\n        SQLSubPartition x = new SQLSubPartition();\n\n        if (name != null) {\n            x.setName(name.clone());\n        }\n\n        if (values != null) {\n            x.setValues(values.clone());\n        }\n\n        if (tableSpace != null) {\n            x.setTableSpace(tableSpace.clone());\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLSubPartitionBy.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class SQLSubPartitionBy extends SQLObjectImpl {\n    protected SQLExpr subPartitionsCount;\n    protected boolean linear;\n    protected List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n    protected List<SQLSubPartition> subPartitionTemplate = new ArrayList<SQLSubPartition>();\n\n    protected SQLIntegerExpr lifecycle;\n\n    public SQLExpr getSubPartitionsCount() {\n        return subPartitionsCount;\n    }\n\n    public void setSubPartitionsCount(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.subPartitionsCount = x;\n    }\n\n    public boolean isLinear() {\n        return linear;\n    }\n\n    public void setLinear(boolean linear) {\n        this.linear = linear;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public List<SQLSubPartition> getSubPartitionTemplate() {\n        return subPartitionTemplate;\n    }\n\n    public void cloneTo(SQLSubPartitionBy x) {\n        if (subPartitionsCount != null) {\n            x.setSubPartitionsCount(subPartitionsCount.clone());\n        }\n        x.linear = linear;\n        for (SQLAssignItem option : options) {\n            SQLAssignItem option2 = option.clone();\n            option2.setParent(x);\n            x.options.add(option2);\n        }\n\n        for (SQLSubPartition p : subPartitionTemplate) {\n            SQLSubPartition p2 = p.clone();\n            p2.setParent(x);\n            x.subPartitionTemplate.add(p2);\n        }\n\n        x.lifecycle = lifecycle;\n    }\n\n    public SQLIntegerExpr getLifecycle() {\n        return lifecycle;\n    }\n\n    public void setLifecycle(SQLIntegerExpr lifecycle) {\n        this.lifecycle = lifecycle;\n    }\n\n    public boolean isPartitionByColumn(long columnNameHashCode64) {\n        return false;\n    }\n\n    public abstract SQLSubPartitionBy clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLSubPartitionByHash.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLSubPartitionByHash extends SQLSubPartitionBy {\n    protected SQLExpr expr;\n\n    // for aliyun ads\n    private boolean key;\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n            acceptChild(visitor, subPartitionsCount);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isKey() {\n        return key;\n    }\n\n    public void setKey(boolean key) {\n        this.key = key;\n    }\n\n    public SQLSubPartitionByHash clone() {\n        SQLSubPartitionByHash x = new SQLSubPartitionByHash();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.key = key;\n        return x;\n    }\n\n    public boolean isPartitionByColumn(long columnNameHashCode64) {\n        return expr instanceof SQLName\n                && ((SQLName) expr).nameHashCode64() == columnNameHashCode64;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLSubPartitionByList.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLSubPartitionByList extends SQLSubPartitionBy {\n    protected SQLName column;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, column);\n            acceptChild(visitor, subPartitionsCount);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLName column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.column = column;\n    }\n\n    public SQLSubPartitionByList clone() {\n        SQLSubPartitionByList x = new SQLSubPartitionByList();\n        if (column != null) {\n            x.setColumn(column.clone());\n        }\n        return x;\n    }\n\n    public boolean isPartitionByColumn(long columnNameHashCode64) {\n        return column != null\n                && column.nameHashCode64() == columnNameHashCode64;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLSubPartitionByRange.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLSubPartitionByRange extends SQLSubPartitionBy {\n    private List<SQLExpr> columns = new ArrayList<SQLExpr>();\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, columns);\n            acceptChild(v, subPartitionsCount);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLSubPartitionByRange clone() {\n        SQLSubPartitionByRange x = new SQLSubPartitionByRange();\n\n        for (SQLExpr column : columns) {\n            SQLExpr c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n        return x;\n    }\n\n    public boolean isPartitionByColumn(long columnNameHashCode64) {\n        for (SQLExpr column : columns) {\n            if (column instanceof SQLIdentifierExpr\n                    && ((SQLIdentifierExpr) column).nameHashCode64() == columnNameHashCode64) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLTableDataType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.sql.Types;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLTableDataType extends SQLObjectImpl implements SQLDataType {\n    private DbType dbType;\n    private List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();\n\n    public SQLTableDataType() {\n    }\n\n    public SQLTableDataType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public String getName() {\n        return \"TABLE\";\n    }\n\n    @Override\n    public void setName(String name) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public long nameHashCode64() {\n        return FnvHash.Constants.TABLE;\n    }\n\n    @Override\n    public List<SQLExpr> getArguments() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Boolean getWithTimeZone() {\n        return null;\n    }\n\n    @Override\n    public void setWithTimeZone(Boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public boolean isWithLocalTimeZone() {\n        return false;\n    }\n\n    @Override\n    public void setWithLocalTimeZone(boolean value) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    @Override\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLTableDataType clone() {\n        SQLTableDataType x = new SQLTableDataType(dbType);\n\n        for (SQLColumnDefinition item : columns) {\n            SQLColumnDefinition item2 = item.clone();\n            item2.setParent(x);\n            x.columns.add(item2);\n        }\n\n        return x;\n    }\n\n    public List<SQLColumnDefinition> getColumns() {\n        return columns;\n    }\n\n    public int jdbcType() {\n        return Types.STRUCT;\n    }\n\n    @Override\n    public boolean isInt() {\n        return false;\n    }\n\n    @Override\n    public boolean isNumberic() {\n        return false;\n    }\n\n    @Override\n    public boolean isString() {\n        return false;\n    }\n\n    @Override\n    public boolean hasKeyLength() {\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLTop.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLTop extends SQLObjectImpl implements SQLReplaceable {\n    private SQLExpr expr;\n    private boolean percent;\n    private boolean withTies;\n    private boolean parentheses;\n\n    public SQLTop() {}\n    public SQLTop(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public void setExpr(int expr) {\n        this.setExpr(new SQLIntegerExpr(expr));\n    }\n\n    public boolean isPercent() {\n        return percent;\n    }\n\n    public void setPercent(boolean percent) {\n        this.percent = percent;\n    }\n\n    public boolean isWithTies() {\n        return withTies;\n    }\n\n    public void setWithTies(boolean withTies) {\n        this.withTies = withTies;\n    }\n\n    public boolean isParentheses() {\n        return parentheses;\n    }\n\n    public void setParentheses(boolean parentheses) {\n        this.parentheses = parentheses;\n    }\n\n    public SQLTop clone() {\n        SQLTop x = new SQLTop();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.withTies = withTies;\n        x.percent = percent;\n        x.parentheses = parentheses;\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, this.expr);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == this.expr) {\n            this.expr = target;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLUnionDataType.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLUnionDataType extends SQLDataTypeImpl {\n    private final List<SQLDataType> items = new ArrayList<SQLDataType>();\n\n    @Override\n    public String getName() {\n        return \"UNIONTYPE\";\n    }\n\n    public List<SQLDataType> getItems() {\n        return items;\n    }\n\n    public void add(SQLDataType item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        items.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, items);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLUnionDataType clone() {\n        SQLUnionDataType x = new SQLUnionDataType();\n\n        for (SQLDataType item : items) {\n            x.add(item.clone());\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLUnpivot.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLUnpivot extends SQLObjectImpl {\n    protected NullsIncludeType nullsIncludeType;\n    protected List<SQLExpr> items = new ArrayList<>();\n    protected final List<SQLExpr> pivotFor = new ArrayList<>();\n    protected final List<SQLSelectItem> pivotIn = new ArrayList<>();\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, this.items);\n            acceptChild(v, this.pivotFor);\n            acceptChild(v, this.pivotIn);\n        }\n        v.endVisit(this);\n    }\n\n    public NullsIncludeType getNullsIncludeType() {\n        return nullsIncludeType;\n    }\n\n    public void setNullsIncludeType(NullsIncludeType nullsIncludeType) {\n        this.nullsIncludeType = nullsIncludeType;\n    }\n\n    public List<SQLExpr> getPivotFor() {\n        return pivotFor;\n    }\n\n    public List<SQLSelectItem> getPivotIn() {\n        return pivotIn;\n    }\n\n    public List<SQLExpr> getItems() {\n        return this.items;\n    }\n\n    public void addItem(SQLExpr item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public SQLUnpivot clone() {\n        SQLUnpivot x = new SQLUnpivot();\n\n        x.setNullsIncludeType(nullsIncludeType);\n\n        for (SQLExpr e : this.items) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.getItems().add(e2);\n        }\n\n        for (SQLExpr e : this.pivotFor) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.getPivotFor().add(e2);\n        }\n\n        for (SQLSelectItem e : this.pivotIn) {\n            SQLSelectItem e2 = e.clone();\n            e2.setParent(x);\n            x.getPivotIn().add(e2);\n        }\n\n        return x;\n    }\n\n    public static enum NullsIncludeType {\n        INCLUDE_NULLS, EXCLUDE_NULLS;\n\n        public static String toString(SQLUnpivot.NullsIncludeType type, boolean ucase) {\n            if (INCLUDE_NULLS.equals(type)) {\n                return ucase ? \"INCLUDE NULLS\" : \"include nulls\";\n            }\n            if (EXCLUDE_NULLS.equals(type)) {\n                return ucase ? \"EXCLUDE NULLS\" : \"exclude nulls\";\n            }\n\n            throw new IllegalArgumentException();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLWindow.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLWindow extends SQLObjectImpl {\n    private SQLName name;\n    private SQLOver over;\n\n    public SQLWindow(SQLName name, SQLOver over) {\n        this.setName(name);\n        this.setOver(over);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLOver getOver() {\n        return over;\n    }\n\n    public void setOver(SQLOver x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.over = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n            acceptChild(v, over);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/SQLZOrderBy.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class SQLZOrderBy extends SQLObjectImpl implements SQLReplaceable {\n    protected final List<SQLSelectOrderByItem> items = new ArrayList<SQLSelectOrderByItem>();\n\n    // for postgres\n    private boolean sibings;\n\n    public SQLZOrderBy() {\n    }\n\n    public SQLZOrderBy(SQLExpr expr) {\n        SQLSelectOrderByItem item = new SQLSelectOrderByItem(expr);\n        addItem(item);\n    }\n\n    public SQLZOrderBy(SQLExpr expr, SQLOrderingSpecification type) {\n        SQLSelectOrderByItem item = new SQLSelectOrderByItem(expr, type);\n        addItem(item);\n    }\n\n    public void addItem(SQLSelectOrderByItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public void addItem(SQLExpr item) {\n        addItem(new SQLSelectOrderByItem(item));\n    }\n\n    public List<SQLSelectOrderByItem> getItems() {\n        return this.items;\n    }\n\n    public boolean isSibings() {\n        return this.sibings;\n    }\n\n    public void setSibings(boolean sibings) {\n        this.sibings = sibings;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            for (int i = 0; i < this.items.size(); i++) {\n                final SQLSelectOrderByItem item = this.items.get(i);\n                item.accept(v);\n            }\n        }\n\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLZOrderBy order = (SQLZOrderBy) o;\n\n        if (sibings != order.sibings) {\n            return false;\n        }\n        return items.equals(order.items);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = items.hashCode();\n        result = 31 * result + (sibings ? 1 : 0);\n        return result;\n    }\n\n    public void addItem(SQLExpr expr, SQLOrderingSpecification type) {\n        SQLSelectOrderByItem item = createItem();\n        item.setExpr(expr);\n        item.setType(type);\n        addItem(item);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (SQLSelectOrderByItem item : items) {\n            if (item.replace(expr, target)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    protected SQLSelectOrderByItem createItem() {\n        return new SQLSelectOrderByItem();\n    }\n\n    public SQLZOrderBy clone() {\n        SQLZOrderBy x = new SQLZOrderBy();\n\n        for (SQLSelectOrderByItem item : items) {\n            SQLSelectOrderByItem item1 = item.clone();\n            item1.setParent(x);\n            x.items.add(item1);\n        }\n\n        x.sibings = sibings;\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/TDDLHint.java",
    "content": "package com.alibaba.druid.sql.ast;\n\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class TDDLHint extends SQLCommentHint {\n    private List<Function> functions = new ArrayList<Function>();\n    private String json;\n    private Type type = Type.Unknown;\n\n    public List<Function> getFunctions() {\n        return functions;\n    }\n\n    public TDDLHint(String text) {\n        super(text);\n\n        MySqlExprParser hintParser = new MySqlExprParser(text, SQLParserFeature.TDDLHint);\n        Lexer lexer = hintParser.getLexer();\n        if (lexer.token() == Token.PLUS || lexer.token() == Token.BANG) {\n            lexer.nextToken();\n        }\n\n        if (!lexer.identifierEquals(FnvHash.Constants.TDDL)) {\n            // error tddl hint\n            return;\n        }\n\n        lexer.nextToken();\n\n        switch (lexer.token()) {\n            case COLON:\n                lexer.nextToken();\n                break;\n            case LPAREN:\n                int rp = text.lastIndexOf(')');\n                if (rp != -1) {\n                    json = text.substring(lexer.pos(), rp);\n                    type = Type.JSON;\n                }\n                return;\n            default:\n                return;\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.AND) {\n                lexer.nextToken();\n            }\n\n            String name = lexer.stringVal();\n            long hash = lexer.hashLCase();\n\n            if (lexer.identifierEquals(FnvHash.Constants.NODE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.IN) {\n                    lexer.nextToken();\n                    name = \"NODE_IN\";\n                } else if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                    name = \"NODE_IN\";\n                    SQLExpr value = hintParser.primary();\n                    Function function = new Function(name);\n                    Argument argument = new Argument(null, value);\n                    function.getArguments().add(argument);\n                    functions.add(function);\n\n                    if (lexer.token() == Token.EOF) {\n                        break;\n                    }\n\n                    continue;\n                }\n            } else if (hash == FnvHash.Constants.SCAN || hash == FnvHash.Constants.DEFER) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                    SQLExpr value = hintParser.primary();\n                    Function function = new Function(name);\n                    Argument argument = new Argument(null, value);\n                    function.getArguments().add(argument);\n                    functions.add(function);\n\n                    if (lexer.token() == Token.EOF) {\n                        break;\n                    }\n\n                    continue;\n                } else if (lexer.token() == Token.EOF) {\n                    Function function = new Function(name);\n                    functions.add(function);\n                    break;\n                }\n            } else if (hash == FnvHash.Constants.SQL_DELAY_CUTOFF\n                    || hash == FnvHash.Constants.SOCKET_TIMEOUT\n                    || hash == FnvHash.Constants.UNDO_LOG_LIMIT\n                    || hash == FnvHash.Constants.FORBID_EXECUTE_DML_ALL) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                    SQLExpr value = hintParser.primary();\n                    Function function = new Function(name);\n                    Argument argument = new Argument(null, value);\n                    function.getArguments().add(argument);\n                    functions.add(function);\n\n                    if (lexer.token() == Token.EOF) {\n                        break;\n                    }\n\n                    continue;\n                }\n            } else {\n                lexer.nextToken();\n            }\n\n            // /!TDDL:table_name.partition_key=value [and table_name1.partition_key=value1]*/\n            // =>\n            // /!TDDL:partitions('table_name.partition_key=value','table_name1.partition_key=value1')*/\n            if (lexer.token() == Token.DOT) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"partition_key\")) {\n                    String table = name;\n                    lexer.nextToken();\n                    hintParser.accept(Token.EQ);\n                    SQLExpr value = hintParser.primary();\n\n                    Function function = new Function(\"PARTITIONS\");\n                    functions.add(function);\n\n                    function.getArguments().add(new Argument(new SQLPropertyExpr(name, \"partition_key\"), value));\n\n                    while (lexer.token() == Token.AND) {\n                        lexer.nextToken();\n                        SQLExpr key = hintParser.primary();\n                        hintParser.accept(Token.EQ);\n                        value = hintParser.primary();\n\n                        function.getArguments().add(new Argument(key, value));\n                    }\n\n                    if (lexer.token() == Token.EOF) {\n                        break;\n                    }\n                } else {\n                    return; // skip\n                }\n            } else if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n                // For other KV.\n                SQLExpr value = hintParser.primary();\n                Function function = new Function(name);\n                Argument argument = new Argument(null, value);\n                function.getArguments().add(argument);\n                functions.add(function);\n\n                if (lexer.token() == Token.EOF) {\n                    break;\n                }\n\n                continue;\n            }\n\n            Function function = new Function(name);\n\n            functions.add(function);\n\n            if (hash == FnvHash.Constants.MASTER) {\n                if (lexer.token() == Token.EOF) {\n                    break;\n                } else if (lexer.token() == Token.BAR) {\n                    lexer.nextToken();\n                    continue;\n                }\n            }\n\n            if (hash == FnvHash.Constants.SLAVE) {\n                if (lexer.token() == Token.EOF) {\n                    break;\n                } else if (lexer.token() == Token.AND) {\n                    lexer.nextToken();\n                    continue;\n                }\n            }\n\n            if (lexer.token() == Token.AND) {\n                continue;\n            }\n\n            hintParser.accept(Token.LPAREN);\n\n            if (lexer.token() != Token.RPAREN) {\n                for (; ; ) {\n                    Lexer.SavePoint mark = lexer.mark();\n\n                    SQLExpr value = null;\n\n                    String keyVal = lexer.stringVal();\n                    long keyHash = lexer.hashLCase();\n\n                    lexer.nextToken();\n\n                    SQLIdentifierExpr key = new SQLIdentifierExpr(keyVal, keyHash);\n\n                    if (lexer.token() == Token.EQ) {\n                        hintParser.accept(Token.EQ);\n\n                        if (lexer.token() == Token.LITERAL_ALIAS) {\n                            String stringVal = lexer.stringVal();\n                            stringVal = stringVal.substring(1, stringVal.length() - 1);\n                            value = new SQLCharExpr(stringVal);\n                            value = hintParser.exprRest(value);\n\n                            lexer.nextToken();\n                        } else {\n                            value = hintParser.expr();\n                        }\n                    }\n\n                    //为了处理 add_ms(t.pk, true) 的情况；\n                    if (value == null) {\n                        lexer.reset(mark);\n                        key = null;\n                        value = hintParser.expr();\n                    }\n\n                    Argument argument = new Argument(key, value);\n                    function.getArguments().add(argument);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n\n                    if (lexer.token() == Token.RPAREN) {\n                        lexer.nextToken();\n                        break;\n                    }\n                }\n            } else {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.AND) {\n                continue;\n            }\n\n            if (hash == FnvHash.Constants.MASTER && lexer.token() == Token.BAR) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.EOF) {\n                break;\n            }\n        }\n\n        if (functions.size() > 0) {\n            type = Type.Function;\n        }\n    }\n\n    public String getJson() {\n        return json;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public static class Function {\n        private final String name;\n        private final List<Argument> arguments = new ArrayList<Argument>();\n\n        public Function(String name) {\n            this.name = name;\n        }\n\n        public String getName() {\n            return name;\n        }\n\n        public List<Argument> getArguments() {\n            return arguments;\n        }\n    }\n\n    public static class Argument {\n        private final SQLExpr name;\n        private final SQLExpr value;\n\n        public Argument(SQLExpr name, SQLExpr value) {\n            this.name = name;\n            this.value = value;\n        }\n\n        public SQLExpr getName() {\n            return name;\n        }\n\n        public SQLExpr getValue() {\n            return value;\n        }\n    }\n\n    public static enum Type {\n        Function,\n        JSON,\n        Unknown\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLAggregateExpr extends SQLMethodInvokeExpr implements Serializable, SQLReplaceable {\n    private static final long serialVersionUID = 1L;\n\n    protected SQLAggregateOption option;\n\n    protected SQLKeep keep;\n    protected SQLExpr filter;\n    protected SQLOver over;\n    protected SQLName overRef;\n    protected SQLOrderBy orderBy;\n    protected SQLExpr limit;\n    protected boolean withinGroup;\n\n    // For BigQuery scenario.\n    protected boolean ignoreNulls;\n\n    // For BigQuery scenario.\n    protected boolean respectNulls;\n\n    public SQLAggregateExpr(String methodName) {\n        this.methodName = methodName;\n        this.ignoreNulls = false;\n        this.respectNulls = false;\n    }\n\n    public SQLAggregateExpr(String methodName, SQLAggregateOption option) {\n        this.methodName = methodName;\n        this.option = option;\n        this.ignoreNulls = false;\n        this.respectNulls = false;\n    }\n\n    public SQLAggregateExpr(String methodName, SQLAggregateOption option, SQLExpr... arguments) {\n        this.methodName = methodName;\n        this.option = option;\n        this.ignoreNulls = false;\n        this.respectNulls = false;\n        if (arguments != null) {\n            for (SQLExpr argument : arguments) {\n                if (argument != null) {\n                    addArgument(argument);\n                }\n            }\n        }\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.orderBy = x;\n    }\n\n    public SQLExpr getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.limit = x;\n    }\n\n    public SQLAggregateOption getOption() {\n        return this.option;\n    }\n\n    public void setOption(SQLAggregateOption option) {\n        this.option = option;\n    }\n\n    public boolean isDistinct() {\n        return option == SQLAggregateOption.DISTINCT;\n    }\n\n    public SQLOver getOver() {\n        return over;\n    }\n\n    public void setOver(SQLOver x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.over = x;\n    }\n\n    public SQLName getOverRef() {\n        return overRef;\n    }\n\n    public void setOverRef(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.overRef = x;\n    }\n\n    public SQLKeep getKeep() {\n        return keep;\n    }\n\n    public void setKeep(SQLKeep keep) {\n        if (keep != null) {\n            keep.setParent(this);\n        }\n        this.keep = keep;\n    }\n\n    public boolean isWithinGroup() {\n        return withinGroup;\n    }\n\n    public void setWithinGroup(boolean withinGroup) {\n        this.withinGroup = withinGroup;\n    }\n\n    //为了兼容之前的逻辑\n    @Deprecated\n    public SQLOrderBy getWithinGroup() {\n        return orderBy;\n    }\n\n    public boolean isIgnoreNulls() {\n        return this.ignoreNulls;\n    }\n\n    public boolean getIgnoreNulls() {\n        return this.ignoreNulls;\n    }\n\n    public boolean isRespectNulls() {\n        return this.respectNulls;\n    }\n\n    public void setIgnoreNulls(boolean ignoreNulls) {\n        this.ignoreNulls = ignoreNulls;\n    }\n\n    public void setRespectNulls(boolean respectNulls) {\n        this.respectNulls = respectNulls;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            if (this.owner != null) {\n                this.owner.accept(v);\n            }\n\n            for (SQLExpr arg : this.arguments) {\n                if (arg != null) {\n                    arg.accept(v);\n                }\n            }\n\n            if (this.keep != null) {\n                this.keep.accept(v);\n            }\n\n            if (this.filter != null) {\n                this.filter.accept(v);\n            }\n\n            if (this.over != null) {\n                this.over.accept(v);\n            }\n\n            if (this.overRef != null) {\n                this.overRef.accept(v);\n            }\n            acceptChild(v, orderBy);\n            acceptChild(v, limit);\n        }\n\n        v.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.addAll(this.arguments);\n        if (keep != null) {\n            children.add(this.keep);\n        }\n        if (over != null) {\n            children.add(over);\n        }\n        if (orderBy != null) {\n            children.add(orderBy);\n        }\n        return children;\n    }\n\n    public SQLExpr getFilter() {\n        return filter;\n    }\n\n    public void setFilter(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.filter = x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        SQLAggregateExpr that = (SQLAggregateExpr) o;\n\n        if (option != that.option) {\n            return false;\n        }\n        if (keep != null ? !keep.equals(that.keep) : that.keep != null) {\n            return false;\n        }\n        if (filter != null ? !filter.equals(that.filter) : that.filter != null) {\n            return false;\n        }\n        if (over != null ? !over.equals(that.over) : that.over != null) {\n            return false;\n        }\n        if (overRef != null ? !overRef.equals(that.overRef) : that.overRef != null) {\n            return false;\n        }\n        if (orderBy != null ? !orderBy.equals(that.orderBy) : that.orderBy != null) {\n            return false;\n        }\n        return ignoreNulls == that.ignoreNulls && respectNulls == that.respectNulls;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = super.hashCode();\n        result = 31 * result + (option != null ? option.hashCode() : 0);\n        result = 31 * result + (keep != null ? keep.hashCode() : 0);\n        result = 31 * result + (filter != null ? filter.hashCode() : 0);\n        result = 31 * result + (over != null ? over.hashCode() : 0);\n        result = 31 * result + (overRef != null ? overRef.hashCode() : 0);\n        result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);\n        return result;\n    }\n\n    public SQLAggregateExpr clone() {\n        SQLAggregateExpr x = new SQLAggregateExpr(methodName);\n\n        x.option = option;\n\n        for (SQLExpr arg : arguments) {\n            x.addArgument(arg.clone());\n        }\n\n        if (keep != null) {\n            x.setKeep(keep.clone());\n        }\n\n        if (over != null) {\n            x.setOver(over.clone());\n        }\n\n        if (overRef != null) {\n            x.setOverRef(overRef.clone());\n        }\n\n        if (orderBy != null) {\n            x.setOrderBy(orderBy.clone());\n        }\n\n        // 修复listagg wthin group语句转换错误的问题\n        // https://github.com/alibaba/druid/issues/5930\n        x.setWithinGroup(withinGroup);\n\n        x.ignoreNulls = ignoreNulls;\n\n        if (attributes != null) {\n            for (Map.Entry<String, Object> entry : attributes.entrySet()) {\n                String key = entry.getKey();\n                Object value = entry.getValue();\n                if (value instanceof SQLObject) {\n                    value = ((SQLObject) value).clone();\n                }\n                x.putAttribute(key, value);\n            }\n        }\n\n        return x;\n    }\n\n    public SQLDataType computeDataType() {\n        if (resolvedReturnDataType != null) {\n            return resolvedReturnDataType;\n        }\n\n        long hash = methodNameHashCode64();\n\n        if (hash == FnvHash.Constants.COUNT\n                || hash == FnvHash.Constants.ROW_NUMBER) {\n            return SQLIntegerExpr.DATA_TYPE;\n        }\n\n        if (arguments.size() > 0) {\n            SQLDataType dataType = arguments.get(0)\n                    .computeDataType();\n            if (dataType != null\n                    && (dataType.nameHashCode64() != FnvHash.Constants.BOOLEAN)) {\n                return dataType;\n            }\n        }\n\n        if (hash == FnvHash.Constants.SUM) {\n            return SQLNumberExpr.DATA_TYPE_DOUBLE;\n        }\n\n        if (hash == FnvHash.Constants.WM_CONCAT\n                || hash == FnvHash.Constants.GROUP_CONCAT) {\n            return SQLCharExpr.DATA_TYPE;\n        }\n\n        return null;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (target == null) {\n            return false;\n        }\n\n        for (int i = 0; i < arguments.size(); ++i) {\n            if (arguments.get(i) == expr) {\n                arguments.set(i, target);\n                target.setParent(this);\n                return true;\n            }\n        }\n\n        if (overRef == expr) {\n            setOverRef((SQLName) target);\n            return true;\n        }\n\n        if (filter != null) {\n            filter = target;\n            target.setParent(this);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateOption.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\npublic enum SQLAggregateOption {\n    DISTINCT,\n    ALL,\n    UNIQUE,\n    DEDUPLICATION // just for nut\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAliasedExpr.java",
    "content": "package com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Objects;\n\npublic class SQLAliasedExpr extends SQLExprImpl implements SQLReplaceable {\n    protected SQLExpr expr;\n    protected String alias;\n\n    public SQLAliasedExpr() {\n        this(null, null);\n    }\n\n    public SQLAliasedExpr(SQLExpr expr) {\n        this(expr, null);\n    }\n\n    public SQLAliasedExpr(SQLExpr expr, String alias) {\n        this.setExpr(expr);\n        this.alias = alias;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            if (expr != null) {\n                expr.accept(v);\n            }\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public String computeAlias() {\n        String alias = this.getAlias();\n        if (alias == null) {\n            if (expr instanceof SQLIdentifierExpr) {\n                alias = ((SQLIdentifierExpr) expr).getName();\n            } else if (expr instanceof SQLPropertyExpr) {\n                alias = ((SQLPropertyExpr) expr).getName();\n            }\n        }\n\n        return SQLUtils.normalize(alias);\n    }\n\n    public SQLDataType computeDataType() {\n        if (expr == null) {\n            return null;\n        }\n\n        return expr.computeDataType();\n    }\n\n    public String getAlias() {\n        return this.alias;\n    }\n\n    public String getAlias2() {\n        if (this.alias == null || this.alias.length() == 0) {\n            return alias;\n        }\n\n        char first = alias.charAt(0);\n        if (first == '\"' || first == '\\'') {\n            char[] chars = new char[alias.length() - 2];\n            int len = 0;\n            for (int i = 1; i < alias.length() - 1; ++i) {\n                char ch = alias.charAt(i);\n                if (ch == '\\\\') {\n                    ++i;\n                    ch = alias.charAt(i);\n                }\n                chars[len++] = ch;\n            }\n            return new String(chars, 0, len);\n        }\n\n        return alias;\n    }\n\n    public void setAlias(String alias) {\n        this.alias = alias;\n    }\n\n    public SQLAliasedExpr clone() {\n        SQLAliasedExpr x = new SQLAliasedExpr();\n        cloneTo(x);\n        return x;\n    }\n\n    protected void cloneTo(SQLAliasedExpr x) {\n        super.cloneTo(x);\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.setAlias(alias);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLAliasedExpr that = (SQLAliasedExpr) o;\n\n        if (!Objects.equals(expr, that.expr)) {\n            return false;\n        }\n        return Objects.equals(alias, that.alias);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = expr != null ? expr.hashCode() : 0;\n        result = 31 * result + (alias != null ? alias.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAllColumnExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLAllColumnExpr extends SQLExprImpl implements SQLName {\n    private transient SQLTableSource resolvedTableSource;\n\n    private SQLExpr owner;\n    private List<SQLExpr> except;\n    private static final String name = \"*\";\n    private final List<SQLAliasedExpr> replace = new ArrayList<SQLAliasedExpr>();\n\n    public SQLAllColumnExpr() {\n    }\n\n    public void output(StringBuilder buf) {\n        if (owner != null) {\n            owner.output(buf);\n            buf.append('.');\n        }\n        buf.append(name);\n    }\n\n    public SQLExpr getOwner() {\n        return owner;\n    }\n\n    public void setOwner(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.owner = x;\n    }\n\n    public List<SQLExpr> getExcept() {\n        return except;\n    }\n\n    public List<SQLAliasedExpr> getReplace() {\n        return replace;\n    }\n\n    public void setExcept(List<SQLExpr> except) {\n        this.except = except;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public int hashCode() {\n        return 0;\n    }\n\n    public boolean equals(Object o) {\n        return o instanceof SQLAllColumnExpr;\n    }\n\n    @Override\n    public String getSimpleName() {\n        return name;\n    }\n\n    public SQLAllColumnExpr clone() {\n        SQLAllColumnExpr x = new SQLAllColumnExpr();\n        x.setOwner(owner);\n\n        x.resolvedTableSource = resolvedTableSource;\n        return x;\n    }\n\n    @Override\n    public long nameHashCode64() {\n        return 0;\n    }\n\n    @Override\n    public long hashCode64() {\n        return 0;\n    }\n\n    @Override\n    public SQLColumnDefinition getResolvedColumn() {\n        return null;\n    }\n\n    public SQLTableSource getResolvedTableSource() {\n        return resolvedTableSource;\n    }\n\n    public void setResolvedTableSource(SQLTableSource resolvedTableSource) {\n        this.resolvedTableSource = resolvedTableSource;\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAllExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLAllExpr extends SQLExprImpl {\n    public SQLSelect subQuery;\n\n    public SQLAllExpr() {\n    }\n\n    public SQLAllExpr(SQLSelect select) {\n        setSubQuery(select);\n    }\n\n    public SQLAllExpr clone() {\n        SQLAllExpr x = new SQLAllExpr();\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n        return x;\n    }\n\n    public SQLSelect getSubQuery() {\n        return this.subQuery;\n    }\n\n    public void setSubQuery(SQLSelect subQuery) {\n        if (subQuery != null) {\n            subQuery.setParent(this);\n        }\n        this.subQuery = subQuery;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.subQuery != null) {\n                this.subQuery.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.subQuery);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((subQuery == null) ? 0 : subQuery.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLAllExpr other = (SQLAllExpr) obj;\n        if (subQuery == null) {\n            if (other.subQuery != null) {\n                return false;\n            }\n        } else if (!subQuery.equals(other.subQuery)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAnyExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLAnyExpr extends SQLExprImpl {\n    public SQLSelect subQuery;\n\n    public SQLAnyExpr() {\n    }\n\n    public SQLAnyExpr(SQLSelect select) {\n        setSubQuery(select);\n    }\n\n    public SQLAnyExpr clone() {\n        SQLAnyExpr x = new SQLAnyExpr();\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n        return x;\n    }\n\n    public SQLSelect getSubQuery() {\n        return this.subQuery;\n    }\n\n    public void setSubQuery(SQLSelect x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.subQuery = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.subQuery != null) {\n                this.subQuery.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.subQuery);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((subQuery == null) ? 0 : subQuery.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLAnyExpr other = (SQLAnyExpr) obj;\n        if (subQuery == null) {\n            if (other.subQuery != null) {\n                return false;\n            }\n        } else if (!subQuery.equals(other.subQuery)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLDataType computeDataType() {\n        if (subQuery == null) {\n            return null;\n        }\n\n        SQLSelectQueryBlock queryBlock = subQuery.getFirstQueryBlock();\n        if (queryBlock == null) {\n            return null;\n        }\n\n        List<SQLSelectItem> selectList = queryBlock.getSelectList();\n        if (selectList.size() == 1) {\n            return selectList.get(0).computeDataType();\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLArrayExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLArrayExpr extends SQLExprImpl implements SQLReplaceable {\n    private SQLExpr expr;\n    private SQLDataType dataType;\n    private List<SQLExpr> values = new ArrayList<SQLExpr>();\n\n    public SQLArrayExpr() {\n    }\n\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    public void setDataType(SQLDataType dataType) {\n        if (dataType != null) {\n            dataType.setParent(this);\n        }\n        this.dataType = dataType;\n    }\n\n    public SQLArrayExpr clone() {\n        SQLArrayExpr x = new SQLArrayExpr();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        if (dataType != null) {\n            x.setDataType(dataType.clone());\n        }\n        for (SQLExpr value : values) {\n            SQLExpr value2 = value.clone();\n            value2.setParent(x);\n            x.values.add(value2);\n        }\n        return x;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    public List<SQLExpr> getValues() {\n        return values;\n    }\n\n    public void addValue(SQLExpr value) {\n        value.setParent(this);\n        this.values.add(value);\n    }\n\n    public void setValues(List<SQLExpr> values) {\n        this.values = values;\n        if (values != null) {\n            for (SQLExpr value : values) {\n                value.setParent(this);\n            }\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n            acceptChild(visitor, dataType);\n            acceptChild(visitor, values);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.add(this.expr);\n        if (this.dataType != null) {\n            children.add(this.dataType);\n        }\n        children.addAll(this.values);\n        return children;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        result = prime * result + ((values == null) ? 0 : values.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLArrayExpr other = (SQLArrayExpr) obj;\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        if (values == null) {\n            if (other.values != null) {\n                return false;\n            }\n        } else if (!values.equals(other.values)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n        }\n        for (int i = 0; i < values.size(); i++) {\n            if (values.get(i) == expr) {\n                target.setParent(this);\n                values.set(i, target);\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAtTimeZoneExpr.java",
    "content": "package com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Objects;\n\npublic class SQLAtTimeZoneExpr extends SQLExprImpl {\n    private SQLExpr expr;\n    private SQLExpr timeZone;\n\n    public SQLAtTimeZoneExpr() {\n    }\n\n    public SQLAtTimeZoneExpr(SQLExpr expr, SQLExpr timeZone) {\n        this.expr = expr;\n        this.timeZone = timeZone;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n            acceptChild(visitor, timeZone);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public SQLExpr getTimeZone() {\n        return timeZone;\n    }\n\n    public void setTimeZone(SQLExpr timeZone) {\n        if (timeZone != null) {\n            timeZone.setParent(this);\n        }\n        this.timeZone = timeZone;\n    }\n\n    public SQLAtTimeZoneExpr clone() {\n        SQLAtTimeZoneExpr x = new SQLAtTimeZoneExpr();\n\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n\n        if (timeZone != null) {\n            x.setTimeZone(timeZone.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLAtTimeZoneExpr that = (SQLAtTimeZoneExpr) o;\n        return Objects.equals(expr, that.expr) && Objects.equals(timeZone, that.timeZone);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = Objects.hashCode(expr);\n        result = 31 * result + Objects.hashCode(timeZone);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBetweenExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class SQLBetweenExpr extends SQLExprImpl implements SQLReplaceable, Serializable {\n    private static final long serialVersionUID = 1L;\n    public SQLExpr testExpr;\n    private boolean not;\n    public SQLExpr beginExpr;\n    public SQLExpr endExpr;\n    public SQLBetweenExpr() {\n    }\n\n    public SQLBetweenExpr clone() {\n        SQLBetweenExpr x = new SQLBetweenExpr();\n        if (testExpr != null) {\n            x.setTestExpr(testExpr.clone());\n        }\n        x.not = not;\n        if (beginExpr != null) {\n            x.setBeginExpr(beginExpr.clone());\n        }\n        if (endExpr != null) {\n            x.setEndExpr(endExpr.clone());\n        }\n        x.setParenthesized(parenthesized);\n        return x;\n    }\n\n    public SQLBetweenExpr(SQLExpr testExpr, SQLExpr beginExpr, SQLExpr endExpr) {\n        setTestExpr(testExpr);\n        setBeginExpr(beginExpr);\n        setEndExpr(endExpr);\n    }\n\n    public SQLBetweenExpr(SQLExpr testExpr, boolean not, SQLExpr beginExpr, SQLExpr endExpr) {\n        this(testExpr, beginExpr, endExpr);\n        this.not = not;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.testExpr != null) {\n                this.testExpr.accept(visitor);\n            }\n\n            if (this.beginExpr != null) {\n                this.beginExpr.accept(visitor);\n            }\n\n            if (this.endExpr != null) {\n                this.endExpr.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Arrays.<SQLObject>asList(this.testExpr, beginExpr, this.endExpr);\n    }\n\n    public SQLExpr getTestExpr() {\n        return this.testExpr;\n    }\n\n    public void setTestExpr(SQLExpr testExpr) {\n        if (testExpr != null) {\n            testExpr.setParent(this);\n        }\n        this.testExpr = testExpr;\n    }\n\n    public boolean isNot() {\n        return this.not;\n    }\n\n    public void setNot(boolean not) {\n        this.not = not;\n    }\n\n    public SQLExpr getBeginExpr() {\n        return this.beginExpr;\n    }\n\n    public void setBeginExpr(SQLExpr beginExpr) {\n        if (beginExpr != null) {\n            beginExpr.setParent(this);\n        }\n        this.beginExpr = beginExpr;\n    }\n\n    public SQLExpr getEndExpr() {\n        return this.endExpr;\n    }\n\n    public void setEndExpr(SQLExpr endExpr) {\n        if (endExpr != null) {\n            endExpr.setParent(this);\n        }\n        this.endExpr = endExpr;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((beginExpr == null) ? 0 : beginExpr.hashCode());\n        result = prime * result + ((endExpr == null) ? 0 : endExpr.hashCode());\n        result = prime * result + (not ? 1231 : 1237);\n        result = prime * result + ((testExpr == null) ? 0 : testExpr.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLBetweenExpr other = (SQLBetweenExpr) obj;\n        if (beginExpr == null) {\n            if (other.beginExpr != null) {\n                return false;\n            }\n        } else if (!beginExpr.equals(other.beginExpr)) {\n            return false;\n        }\n        if (endExpr == null) {\n            if (other.endExpr != null) {\n                return false;\n            }\n        } else if (!endExpr.equals(other.endExpr)) {\n            return false;\n        }\n        if (not != other.not) {\n            return false;\n        }\n        if (testExpr == null) {\n            if (other.testExpr != null) {\n                return false;\n            }\n        } else if (!testExpr.equals(other.testExpr)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public SQLDataType computeDataType() {\n        return SQLBooleanExpr.DATA_TYPE;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == testExpr) {\n            setTestExpr(target);\n            return true;\n        }\n\n        if (expr == beginExpr) {\n            setBeginExpr(target);\n            return true;\n        }\n\n        if (expr == endExpr) {\n            setEndExpr(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBigIntExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLBigIntExpr extends SQLNumericLiteralExpr implements SQLValuableExpr {\n    public SQLBigIntExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.BIGINT));\n    }\n\n    public SQLBigIntExpr(Long value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLBigIntExpr(String value) {\n        this();\n        this.value = Long.valueOf(value);\n    }\n\n    public SQLBigIntExpr clone() {\n        return new SQLBigIntExpr(getValue());\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Number getNumber() {\n        return getValue();\n    }\n\n    @Override\n    public Long getValue() {\n        return (Long) value;\n    }\n\n    public void setValue(Long value) {\n        this.value = value;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLBigIntExpr other = (SQLBigIntExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            value = null;\n            return;\n        }\n\n        this.setValue(((Long) number));\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.Utils;\n\nimport java.math.BigInteger;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLBinaryExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValuableExpr {\n    private String text;\n\n    private transient Number val;\n\n    public SQLBinaryExpr() {\n    }\n\n    public SQLBinaryExpr(String value) {\n        super();\n        this.text = value;\n    }\n\n    public String getText() {\n        return text;\n    }\n\n    public Number getValue() {\n        if (text == null) {\n            return null;\n        }\n\n        if (val == null) {\n            long[] words = new long[text.length() / 64 + 1];\n            for (int i = text.length() - 1; i >= 0; --i) {\n                char ch = text.charAt(i);\n                if (ch == '1') {\n                    int wordIndex = i >> 6;\n                    words[wordIndex] |= (1L << (text.length() - 1 - i));\n                }\n            }\n\n            if (words.length == 1) {\n                val = words[0];\n            } else {\n                byte[] bytes = new byte[words.length * 8];\n\n                for (int i = 0; i < words.length; ++i) {\n                    Utils.putLong(bytes, (words.length - 1 - i) * 8, words[i]);\n                }\n\n                val = new BigInteger(bytes);\n            }\n        }\n\n        return val;\n    }\n\n    public void setValue(String value) {\n        this.text = value;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(\"b'\");\n        buf.append(text);\n        buf.append('\\'');\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((text == null) ? 0 : text.hashCode());\n        return result;\n    }\n\n    public SQLBinaryExpr clone() {\n        return new SQLBinaryExpr(text);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLBinaryExpr other = (SQLBinaryExpr) obj;\n        if (text == null) {\n            if (other.text != null) {\n                return false;\n            }\n        } else if (!text.equals(other.text)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.ParameterizedVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.Utils;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Serializable, SQLDbTypedObject, Comparable<SQLBinaryOpExpr> {\n    private static final long serialVersionUID = 1L;\n    protected SQLExpr left;\n    protected SQLExpr right;\n    protected SQLBinaryOperator operator;\n    protected DbType dbType;\n\n    // only for parameterized output\n    protected transient List<SQLObject> mergedList;\n\n    public SQLBinaryOpExpr() {\n    }\n\n    public SQLBinaryOpExpr(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLBinaryOpExpr(SQLExpr left, SQLBinaryOperator operator, SQLExpr right) {\n        if (left != null) {\n            left.setParent(this);\n        }\n        if (right != null) {\n            right.setParent(this);\n        }\n\n        this.left = left;\n        this.right = right;\n        this.operator = operator;\n\n        if (dbType == null) {\n            if (left instanceof SQLBinaryOpExpr) {\n                dbType = ((SQLBinaryOpExpr) left).dbType;\n            }\n        }\n\n        if (dbType == null) {\n            if (right instanceof SQLBinaryOpExpr) {\n                dbType = ((SQLBinaryOpExpr) right).dbType;\n            }\n        }\n    }\n\n    public SQLBinaryOpExpr(SQLExpr left, SQLBinaryOperator operator, SQLExpr right, DbType dbType) {\n        if (left != null) {\n            left.setParent(this);\n        }\n        if (right != null) {\n            right.setParent(this);\n        }\n\n        this.left = left;\n        this.right = right;\n        this.operator = operator;\n\n        if (dbType == null) {\n            if (left instanceof SQLBinaryOpExpr) {\n                dbType = ((SQLBinaryOpExpr) left).dbType;\n            }\n        }\n\n        if (dbType == null) {\n            if (right instanceof SQLBinaryOpExpr) {\n                dbType = ((SQLBinaryOpExpr) right).dbType;\n            }\n        }\n\n        this.dbType = dbType;\n    }\n\n    public SQLBinaryOpExpr(SQLExpr left, SQLExpr right, SQLBinaryOperator operator) {\n        if (left != null) {\n            left.setParent(this);\n        }\n        if (right != null) {\n            right.setParent(this);\n        }\n        this.left = left;\n        this.right = right;\n        this.operator = operator;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLExpr getLeft() {\n        return this.left;\n    }\n\n    public void setLeft(SQLExpr left) {\n        if (left != null) {\n            left.setParent(this);\n        }\n        this.left = left;\n    }\n\n    public SQLExpr getRight() {\n        return this.right;\n    }\n\n    public void setRight(SQLExpr right) {\n        if (right != null) {\n            right.setParent(this);\n        }\n        this.right = right;\n    }\n\n    public SQLBinaryOperator getOperator() {\n        return this.operator;\n    }\n\n    public void setOperator(SQLBinaryOperator operator) {\n        this.operator = operator;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (left != null) {\n                left.accept(visitor);\n            }\n            if (right != null) {\n                right.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Arrays.asList(this.left, this.right);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((left == null) ? 0 : left.hashCode());\n        result = prime * result + ((operator == null) ? 0 : operator.hashCode());\n        result = prime * result + ((right == null) ? 0 : right.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (!(obj instanceof SQLBinaryOpExpr)) {\n            return false;\n        }\n\n        return equals((SQLBinaryOpExpr) obj);\n    }\n\n    public boolean equals(SQLBinaryOpExpr other) {\n        return operator == other.operator\n                && SQLExprUtils.equals(left, other.left)\n                && SQLExprUtils.equals(right, other.right);\n    }\n\n    public boolean equalsIgoreOrder(SQLBinaryOpExpr other) {\n        if (this == other) {\n            return true;\n        }\n        if (other == null) {\n            return false;\n        }\n\n        if (operator != other.operator) {\n            return false;\n        }\n\n        return (Utils.equals(this.left, other.left)\n                && Utils.equals(this.right, other.right))\n                || (Utils.equals(this.left, other.right)\n                && Utils.equals(this.right, other.left));\n    }\n\n    protected void cloneTo(SQLBinaryOpExpr x) {\n        super.cloneTo(x);\n        if (left != null) {\n            x.setLeft(left.clone());\n        }\n        if (right != null) {\n            x.setRight(right.clone());\n        }\n        x.operator = operator;\n        x.dbType = dbType;\n        x.parenthesized = parenthesized;\n\n        if (hint != null) {\n            x.hint = hint.clone();\n        }\n        x.setParenthesized(parenthesized);\n    }\n\n    public SQLBinaryOpExpr clone() {\n        SQLBinaryOpExpr x = new SQLBinaryOpExpr();\n        cloneTo(x);\n        return x;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, getDbType());\n    }\n\n    public static SQLExpr combine(List<? extends SQLExpr> items, SQLBinaryOperator op) {\n        if (items == null || op == null) {\n            return null;\n        }\n\n        int size = items.size();\n        if (size == 0) {\n            return null;\n        }\n\n        if (size == 1) {\n            return items.get(0);\n        }\n\n        SQLBinaryOpExpr expr = new SQLBinaryOpExpr(items.get(0), op, items.get(1));\n\n        for (int i = 2; i < size; ++i) {\n            SQLExpr item = items.get(i);\n            expr = new SQLBinaryOpExpr(expr, op, item);\n        }\n\n        return expr;\n    }\n\n    public static List<SQLExpr> split(SQLBinaryOpExpr x) {\n        return split(x, x.getOperator());\n    }\n\n    public static List<SQLExpr> split(SQLExpr x, SQLBinaryOperator op) {\n        if (x instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) x;\n            if (group.getOperator() == op) {\n                return new ArrayList<SQLExpr>(group.getItems());\n            }\n        } else if (x instanceof SQLBinaryOpExpr) {\n            return split((SQLBinaryOpExpr) x, op);\n        }\n\n        List<SQLExpr> list = new ArrayList<SQLExpr>(1);\n        list.add(x);\n        return list;\n    }\n\n    public static List<SQLExpr> split(SQLBinaryOpExpr x, SQLBinaryOperator op) {\n        if (x.getOperator() != op) {\n            List<SQLExpr> groupList = new ArrayList<SQLExpr>(1);\n            groupList.add(x);\n            return groupList;\n        }\n\n        List<SQLExpr> groupList = new ArrayList<SQLExpr>();\n        split(groupList, x, op);\n        return groupList;\n    }\n\n    public static void split(List<SQLExpr> outList, SQLExpr expr, SQLBinaryOperator op) {\n        if (expr == null) {\n            return;\n        }\n\n        if (!(expr instanceof SQLBinaryOpExpr)) {\n            outList.add(expr);\n            return;\n        }\n\n        SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) expr;\n\n        if (binaryExpr.getOperator() != op) {\n            outList.add(binaryExpr);\n            return;\n        }\n\n        List<SQLExpr> rightList = new ArrayList<SQLExpr>();\n        rightList.add(binaryExpr.getRight());\n        for (SQLExpr left = binaryExpr.getLeft(); ; ) {\n            if (left instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr leftBinary = (SQLBinaryOpExpr) left;\n                if (leftBinary.operator == op) {\n                    left = ((SQLBinaryOpExpr) leftBinary).getLeft();\n                    rightList.add(leftBinary.getRight());\n                } else {\n                    outList.add(leftBinary);\n                    break;\n                }\n            } else {\n                outList.add(left);\n                break;\n            }\n        }\n\n        for (int i = rightList.size() - 1; i >= 0; --i) {\n            SQLExpr right = rightList.get(i);\n\n            if (right instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr binaryRight = (SQLBinaryOpExpr) right;\n                if (binaryRight.operator == op) {\n                    {\n                        SQLExpr rightLeft = binaryRight.getLeft();\n                        if (rightLeft instanceof SQLBinaryOpExpr) {\n                            SQLBinaryOpExpr rightLeftBinary = (SQLBinaryOpExpr) rightLeft;\n                            if (rightLeftBinary.operator == op) {\n                                split(outList, rightLeftBinary, op);\n                            } else {\n                                outList.add(rightLeftBinary);\n                            }\n                        } else {\n                            outList.add(rightLeft);\n                        }\n                    }\n                    {\n                        SQLExpr rightRight = binaryRight.getRight();\n                        if (rightRight instanceof SQLBinaryOpExpr) {\n                            SQLBinaryOpExpr rightRightBinary = (SQLBinaryOpExpr) rightRight;\n                            if (rightRightBinary.operator == op) {\n                                split(outList, rightRightBinary, op);\n                            } else {\n                                outList.add(rightRightBinary);\n                            }\n                        } else {\n                            outList.add(rightRight);\n                        }\n                    }\n                } else {\n                    outList.add(binaryRight);\n                }\n            } else {\n                outList.add(right);\n            }\n        }\n    }\n\n    public static SQLExpr and(SQLExpr a, SQLExpr b) {\n        if (a == null) {\n            return b;\n        }\n\n        if (b == null) {\n            return a;\n        }\n\n        if (a instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) a;\n            if (group.getOperator() == SQLBinaryOperator.BooleanAnd) {\n                group.add(b);\n                return group;\n            } else if (group.getOperator() == SQLBinaryOperator.BooleanOr && group.getItems().size() == 1) {\n                a = group.getItems().get(0).clone();\n            }\n        }\n\n        if (b instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr bb = (SQLBinaryOpExpr) b;\n            if (bb.operator == SQLBinaryOperator.BooleanAnd) {\n                return and(and(a, bb.left), bb.right);\n            }\n        } else if (b instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) b;\n            if (group.getOperator() == SQLBinaryOperator.BooleanOr && group.getItems().size() == 1) {\n                b = group.getItems().get(0).clone();\n            }\n        }\n\n        if (a instanceof SQLBinaryOpExpr\n                && b instanceof SQLBinaryOpExprGroup\n                && ((SQLBinaryOpExprGroup) b).getOperator() == SQLBinaryOperator.BooleanAnd) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) b;\n            group.add(0, a);\n            return group;\n        }\n\n        return new SQLBinaryOpExpr(a, SQLBinaryOperator.BooleanAnd, b);\n    }\n\n    public static SQLExpr and(SQLExpr a, SQLExpr b, SQLExpr c) {\n        return and(and(a, b), c);\n    }\n\n    public static SQLExpr or(SQLExpr a, SQLExpr b) {\n        if (a == null) {\n            return b;\n        }\n\n        if (b == null) {\n            return a;\n        }\n\n        if (a instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) a;\n            if (group.getOperator() == SQLBinaryOperator.BooleanOr) {\n                group.add(b);\n                return group;\n            }\n        }\n\n        if (b instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr bb = (SQLBinaryOpExpr) b;\n            if (bb.operator == SQLBinaryOperator.BooleanOr) {\n                return or(or(a, bb.left), bb.right);\n            }\n        }\n\n        return new SQLBinaryOpExpr(a, SQLBinaryOperator.BooleanOr, b);\n    }\n\n    public static SQLExpr or(List<? extends SQLExpr> list) {\n        if (list.isEmpty()) {\n            return null;\n        }\n        SQLExpr first = list.get(0);\n        for (int i = 1; i < list.size(); i++) {\n            first = or(first, list.get(i));\n        }\n        return first;\n    }\n\n    public static SQLExpr andIfNotExists(SQLExpr a, SQLExpr b) {\n        if (a == null) {\n            return b;\n        }\n\n        if (b == null) {\n            return a;\n        }\n\n        List<SQLExpr> groupListA = new ArrayList<SQLExpr>();\n        List<SQLExpr> groupListB = new ArrayList<SQLExpr>();\n        split(groupListA, a, SQLBinaryOperator.BooleanAnd);\n        split(groupListB, b, SQLBinaryOperator.BooleanAnd);\n\n        for (SQLExpr itemB : groupListB) {\n            boolean exist = false;\n            for (SQLExpr itemA : groupListA) {\n                if (itemA.equals(itemB)) {\n                    exist = true;\n                } else if (itemA instanceof SQLBinaryOpExpr\n                        && itemB instanceof SQLBinaryOpExpr) {\n                    if (((SQLBinaryOpExpr) itemA).equalsIgoreOrder((SQLBinaryOpExpr) itemB)) {\n                        exist = true;\n                    }\n                }\n            }\n            if (!exist) {\n                groupListA.add(itemB);\n            }\n        }\n        return combine(groupListA, SQLBinaryOperator.BooleanAnd);\n    }\n\n    public static SQLBinaryOpExpr isNotNull(SQLExpr expr) {\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.IsNot, new SQLNullExpr());\n    }\n\n    public static SQLBinaryOpExpr isNull(SQLExpr expr) {\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, new SQLNullExpr());\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        SQLObject parent = getParent();\n\n        if (left == expr) {\n            if (target == null) {\n                if (parent instanceof SQLReplaceable) {\n                    return ((SQLReplaceable) parent).replace(this, right);\n                } else {\n                    return false;\n                }\n            }\n            this.setLeft(target);\n            return true;\n        }\n\n        if (right == expr) {\n            if (target == null) {\n                if (parent instanceof SQLReplaceable) {\n                    return ((SQLReplaceable) parent).replace(this, left);\n                } else {\n                    return false;\n                }\n            }\n            this.setRight(target);\n            return true;\n        }\n\n        if (left instanceof SQLBinaryOpExpr) {\n            final SQLBinaryOperator operator = ((SQLBinaryOpExpr) left).getOperator();\n            if (operator == SQLBinaryOperator.BooleanAnd) {\n                if (((SQLBinaryOpExpr) left).replace(expr, target)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public SQLExpr other(SQLExpr x) {\n        if (x == left) {\n            return right;\n        }\n\n        if (x == right) {\n            return left;\n        }\n\n        return null;\n    }\n\n    public boolean contains(SQLExpr item) {\n        if (item instanceof SQLBinaryOpExpr) {\n            if (this.equalsIgoreOrder((SQLBinaryOpExpr) item)) {\n                return true;\n            }\n\n            return left.equals(item) || right.equals(item);\n        }\n\n        return false;\n    }\n\n    public SQLDataType computeDataType() {\n        if (operator == null) {\n            return null;\n        }\n\n        if (operator.isRelational()) {\n            return SQLBooleanExpr.DATA_TYPE;\n        }\n\n        SQLDataType leftDataType = null, rightDataType = null;\n        if (left != null) {\n            leftDataType = left.computeDataType();\n        }\n        if (right != null) {\n            rightDataType = right.computeDataType();\n        }\n\n        switch (operator) {\n            case Concat:\n                if (leftDataType != null) {\n                    return leftDataType;\n                }\n                if (rightDataType != null) {\n                    return rightDataType;\n                }\n                return SQLCharExpr.DATA_TYPE;\n            case BooleanXor:\n            case Modulus:\n            case Mod:\n            case DIV:\n            case Divide:\n                if (leftDataType != null) {\n                    return leftDataType;\n                }\n                if (rightDataType != null) {\n                    return rightDataType;\n                }\n                return null;\n            case Subtract:\n            case Add:\n            case Multiply:\n                if (leftDataType != null) {\n                    if (rightDataType != null) {\n                        if (leftDataType.nameHashCode64() == FnvHash.Constants.BIGINT\n                                && rightDataType.nameHashCode64() == FnvHash.Constants.NUMBER) {\n                            return rightDataType;\n                        }\n\n                        if (leftDataType.isInt()\n                                && rightDataType.nameHashCode64() == FnvHash.Constants.INTERVAL) {\n                            return rightDataType;\n                        }\n\n                        if ((leftDataType.nameHashCode64() == FnvHash.Constants.DATE\n                                || leftDataType.nameHashCode64() == FnvHash.Constants.DATETIME\n                                || leftDataType.nameHashCode64() == FnvHash.Constants.TIMESTAMP)\n                                && (\n                                rightDataType.nameHashCode64() == FnvHash.Constants.DATE\n                                        || rightDataType.nameHashCode64() == FnvHash.Constants.DATETIME\n                                        || rightDataType.nameHashCode64() == FnvHash.Constants.TIMESTAMP\n                        )) {\n                            return new SQLDataTypeImpl(\"BIGING\");\n                        }\n\n                        if ((leftDataType.isString() && !rightDataType.isString())\n                                || (!leftDataType.isString() && rightDataType.isString())) {\n                            return null;\n                        }\n                    }\n\n                    return leftDataType;\n                }\n                return null;\n            default:\n                return null;\n        }\n    }\n\n    public boolean conditionContainsTable(String alias) {\n        if (left == null || right == null) {\n            return false;\n        }\n\n        if (left instanceof SQLPropertyExpr) {\n            if (((SQLPropertyExpr) left).matchOwner(alias)) {\n                return true;\n            }\n        } else if (left instanceof SQLBinaryOpExpr) {\n            if (((SQLBinaryOpExpr) left).conditionContainsTable(alias)) {\n                return true;\n            }\n        }\n\n        if (right instanceof SQLPropertyExpr) {\n            if (((SQLPropertyExpr) right).matchOwner(alias)) {\n                return true;\n            }\n        } else if (right instanceof SQLBinaryOpExpr) {\n            return ((SQLBinaryOpExpr) right).conditionContainsTable(alias);\n        }\n\n        return false;\n    }\n\n    public boolean conditionContainsColumn(String column) {\n        if (left == null || right == null) {\n            return false;\n        }\n\n        if (left instanceof SQLIdentifierExpr) {\n            if (((SQLIdentifierExpr) left).nameEquals(column)) {\n                return true;\n            }\n        } else if (right instanceof SQLIdentifierExpr) {\n            if (((SQLIdentifierExpr) right).nameEquals(column)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Merges the given SQLBinaryOpExpr with its parent using a parameterized visitor.\n     *\n     * @param v the parameterized visitor used for merging\n     * @param x the SQLBinaryOpExpr to be merged\n     * @return the merged SQLBinaryOpExpr\n     */\n    public static SQLBinaryOpExpr merge(ParameterizedVisitor v, SQLBinaryOpExpr x) {\n        SQLObject parent = x.parent;\n\n        for (; ; ) {\n            if (x.right instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr rightBinary = (SQLBinaryOpExpr) x.right;\n                if (x.left instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr leftBinaryExpr = (SQLBinaryOpExpr) x.left;\n                    if (SQLExprUtils.equals(leftBinaryExpr.right, rightBinary)) {\n                        x = leftBinaryExpr;\n                        v.incrementReplaceCunt();\n                        continue;\n                    }\n                }\n                SQLExpr mergedRight = merge(v, rightBinary);\n                if (mergedRight != x.right) {\n                    x = new SQLBinaryOpExpr(x.left, x.operator, mergedRight);\n                    v.incrementReplaceCunt();\n                }\n\n                x.setParent(parent);\n            }\n\n            break;\n        }\n\n        if (x.left instanceof SQLBinaryOpExpr) {\n            SQLExpr mergedLeft = merge(v, (SQLBinaryOpExpr) x.left);\n            if (mergedLeft != x.left) {\n                SQLBinaryOpExpr tmp = new SQLBinaryOpExpr(mergedLeft, x.operator, x.right);\n                tmp.setParent(parent);\n                x = tmp;\n                v.incrementReplaceCunt();\n            }\n        }\n\n        // ID = ? OR ID = ? => ID = ?\n        if (x.operator == SQLBinaryOperator.BooleanOr && !v.isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeInList)) {\n            if ((x.left instanceof SQLBinaryOpExpr) && (x.right instanceof SQLBinaryOpExpr)) {\n                SQLBinaryOpExpr leftBinary = (SQLBinaryOpExpr) x.left;\n                SQLBinaryOpExpr rightBinary = (SQLBinaryOpExpr) x.right;\n\n                if (mergeEqual(leftBinary, rightBinary)) {\n                    v.incrementReplaceCunt();\n                    leftBinary.setParent(x.parent);\n                    leftBinary.addMergedItem(rightBinary);\n                    return leftBinary;\n                }\n\n                if (SQLExprUtils.isLiteralExpr(leftBinary.left) //\n                        && leftBinary.operator == SQLBinaryOperator.BooleanOr) {\n                    if (mergeEqual(leftBinary.right, x.right)) {\n                        v.incrementReplaceCunt();\n                        leftBinary.addMergedItem(rightBinary);\n                        return leftBinary;\n                    }\n                }\n            }\n        }\n\n        return x;\n    }\n\n    /**\n     * Adds the given SQLBinaryOpExpr to the merged list.\n     *\n     * @param item the SQLBinaryOpExpr to be added\n     */\n    private void addMergedItem(SQLBinaryOpExpr item) {\n        if (mergedList == null) {\n            mergedList = new ArrayList<SQLObject>();\n        }\n        mergedList.add(item);\n    }\n\n    /**\n     * Retrieves the merged list of SQLObjects.\n     *\n     * @return the merged list of SQLObjects\n     */\n    public List<SQLObject> getMergedList() {\n        return mergedList;\n    }\n\n    /**\n     * Determines whether two SQL expressions can be merged based on equality.\n     *\n     * @param a the first SQL expression to compare\n     * @param b the second SQL expression to compare\n     * @return true if the two expressions are equal and can be merged; otherwise false\n     */\n    private static boolean mergeEqual(SQLExpr a, SQLExpr b) {\n        if (!(a instanceof SQLBinaryOpExpr)) {\n            return false;\n        }\n        if (!(b instanceof SQLBinaryOpExpr)) {\n            return false;\n        }\n\n        SQLBinaryOpExpr binaryA = (SQLBinaryOpExpr) a;\n        SQLBinaryOpExpr binaryB = (SQLBinaryOpExpr) b;\n\n        if (binaryA.operator != SQLBinaryOperator.Equality) {\n            return false;\n        }\n\n        if (binaryB.operator != SQLBinaryOperator.Equality) {\n            return false;\n        }\n\n        if (!(binaryA.right instanceof SQLLiteralExpr || binaryA.right instanceof SQLVariantRefExpr)) {\n            return false;\n        }\n\n        if (!(binaryB.right instanceof SQLLiteralExpr || binaryB.right instanceof SQLVariantRefExpr)) {\n            return false;\n        }\n\n        return binaryA.left.equals(binaryB.left);\n    }\n\n    public static boolean isOr(SQLExpr x) {\n        return x instanceof SQLBinaryOpExpr\n                && ((SQLBinaryOpExpr) x).getOperator() == SQLBinaryOperator.BooleanOr;\n    }\n\n    public static boolean isAnd(SQLExpr x) {\n        return x instanceof SQLBinaryOpExpr\n                && ((SQLBinaryOpExpr) x).getOperator() == SQLBinaryOperator.BooleanAnd;\n    }\n\n    public boolean isLeftNameAndRightLiteral() {\n        return left instanceof SQLName\n                && right instanceof SQLLiteralExpr;\n    }\n\n    public boolean isLeftFunctionAndRightLiteral() {\n        return left instanceof SQLMethodInvokeExpr\n                && right instanceof SQLLiteralExpr;\n    }\n\n    public boolean isNameAndLiteral() {\n        return (left instanceof SQLLiteralExpr\n                && right instanceof SQLName)\n                || (left instanceof SQLName\n                && right instanceof SQLLiteralExpr);\n    }\n\n    public boolean isBothName() {\n        return left instanceof SQLName\n                && right instanceof SQLName;\n    }\n\n    @Override\n    public int compareTo(SQLBinaryOpExpr o) {\n        int leftResult = SQLExprComparor.compareTo(left, o.left);\n        if (leftResult != 0) {\n            return leftResult;\n        }\n\n        int opResult = this.operator.compareTo(o.operator);\n        if (opResult != 0) {\n            return opResult;\n        }\n\n        int rightResult = SQLExprComparor.compareTo(right, o.right);\n        if (rightResult != 0) {\n            return rightResult;\n        }\n\n        return 0;\n    }\n\n    public boolean isLeftLiteralAndRightName() {\n        return right instanceof SQLName\n                && left instanceof SQLLiteralExpr;\n    }\n\n    public static SQLBinaryOpExpr conditionEq(String column, String value) {\n        return new SQLBinaryOpExpr(\n                SQLUtils.toSQLExpr(column),\n                SQLBinaryOperator.Equality, new SQLCharExpr(value)\n        );\n    }\n\n    public static SQLBinaryOpExpr conditionEq(String column, int value) {\n        return new SQLBinaryOpExpr(\n                SQLUtils.toSQLExpr(column),\n                SQLBinaryOperator.Equality,\n                new SQLIntegerExpr(value)\n        );\n    }\n\n    public static SQLBinaryOpExpr conditionLike(String column, String value) {\n        return new SQLBinaryOpExpr(\n                SQLUtils.toSQLExpr(column),\n                SQLBinaryOperator.Like,\n                new SQLCharExpr(value)\n        );\n    }\n\n    public static SQLBinaryOpExpr conditionLike(String column, SQLExpr value) {\n        return new SQLBinaryOpExpr(\n                SQLUtils.toSQLExpr(column),\n                SQLBinaryOperator.Like,\n                value\n        );\n    }\n\n    public static SQLBinaryOpExpr eq(SQLExpr a, SQLExpr b) {\n        return new SQLBinaryOpExpr(a, SQLBinaryOperator.Equality, b);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExprGroup.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class SQLBinaryOpExprGroup extends SQLExprImpl implements SQLReplaceable {\n    private final SQLBinaryOperator operator;\n    private final List<SQLExpr> items = new ArrayList<SQLExpr>();\n    private DbType dbType;\n\n    public SQLBinaryOpExprGroup(SQLBinaryOperator operator) {\n        this.operator = operator;\n    }\n\n    public SQLBinaryOpExprGroup(SQLBinaryOperator operator, DbType dbType) {\n        this.operator = operator;\n        this.dbType = dbType;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLBinaryOpExprGroup that = (SQLBinaryOpExprGroup) o;\n\n        if (operator != that.operator) {\n            return false;\n        }\n        return items.equals(that.items);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = operator != null ? operator.hashCode() : 0;\n        result = 31 * result + items.hashCode();\n        return result;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < this.items.size(); i++) {\n                SQLExpr item = this.items.get(i);\n                item.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public SQLExpr clone() {\n        SQLBinaryOpExprGroup x = new SQLBinaryOpExprGroup(operator);\n\n        for (SQLExpr item : items) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(this);\n            x.items.add(item2);\n        }\n\n        return x;\n    }\n\n    @Override\n    public List getChildren() {\n        return items;\n    }\n\n    public void add(SQLExpr item) {\n        add(items.size(), item);\n    }\n\n    public void add(int index, SQLExpr item) {\n        if (item instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) item;\n            if (binaryOpExpr.getOperator() == operator) {\n                add(binaryOpExpr.getLeft());\n                add(binaryOpExpr.getRight());\n                return;\n            }\n        } else if (item instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) item;\n            if (group.operator == this.operator) {\n                for (SQLExpr sqlExpr : group.getItems()) {\n                    add(sqlExpr);\n                }\n                return;\n            }\n        }\n\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(index, item);\n    }\n\n    public List<SQLExpr> getItems() {\n        return this.items;\n    }\n\n    public SQLBinaryOperator getOperator() {\n        return operator;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, dbType);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        boolean replaced = false;\n        for (int i = 0; i < items.size(); i++) {\n            if (items.get(i) == expr) {\n                if (target == null) {\n                    items.remove(i);\n                } else {\n                    if (target instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) target).getOperator() == operator) {\n                        items.remove(i);\n                        List<SQLExpr> list = SQLBinaryOpExpr.split(target, operator);\n                        for (int j = 0; j < list.size(); j++) {\n                            SQLExpr o = list.get(j);\n                            o.setParent(this);\n                            items.add(i + j, o);\n                        }\n                    } else {\n                        target.setParent(this);\n                        items.set(i, target);\n                    }\n                }\n                replaced = true;\n            }\n        }\n\n        if (items.size() == 1 && replaced) {\n            SQLUtils.replaceInParent(this, items.get(0));\n        }\n\n        if (items.isEmpty()) {\n            SQLUtils.replaceInParent(this, null);\n        }\n\n        return replaced;\n    }\n\n    public void optimize() {\n        List<Integer> dupIndexList = null;\n\n        Set<SQLExpr> itemSet = new LinkedHashSet<SQLExpr>();\n        for (int i = 0; i < items.size(); i++) {\n            if (!itemSet.add(items.get(i))) {\n                if (dupIndexList == null) {\n                    dupIndexList = new ArrayList<Integer>();\n                }\n                dupIndexList.add(i);\n            }\n        }\n\n        if (dupIndexList != null) {\n            for (int i = dupIndexList.size() - 1; i >= 0; i--) {\n                int index = dupIndexList.get(i);\n                items.remove(index);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\n/**\n * 二元操作符\n *\n * @author wenshao 2011-5-20 下午12:32:02\n */\npublic enum SQLBinaryOperator {\n    Union(\"UNION\", 0),\n    COLLATE(\"COLLATE\", 20),\n    BitwiseXor(\"^\", 50),\n    BitwiseXorEQ(\"^=\", 110),\n\n    Multiply(\"*\", 60),\n    Divide(\"/\", 60),\n    DIV(\"DIV\", 60), // mysql integer division\n    Modulus(\"%\", 60),\n    Mod(\"MOD\", 60),\n\n    Add(\"+\", 70),\n    Subtract(\"-\", 70),\n\n    SubGt(\"->\", 20),\n    SubGtGt(\"->>\", 20),\n    PoundGt(\"#>\", 20),\n    PoundGtGt(\"#>>\", 20),\n    QuesQues(\"??\", 20),\n    QuesBar(\"?|\", 20),\n    QuesQuesBar(\"??|\", 20),\n    QuesAmp(\"?&\", 20),\n\n    LeftShift(\"<<\", 80),\n    LeftShiftUnsigned(\"<<<\", 80),\n    RightShift(\">>\", 80),\n    RightShiftUnsigned(\">>>\", 80),\n\n    BitwiseAnd(\"&\", 90),\n    BitwiseOr(\"|\", 100),\n\n    GreaterThan(\">\", 110),\n    GreaterThanOrEqual(\">=\", 110),\n    Is(\"IS\", 110),\n    LessThan(\"<\", 110),\n    LessThanOrEqual(\"<=\", 110),\n    LessThanOrEqualOrGreaterThan(\"<=>\", 110),\n    LessThanOrGreater(\"<>\", 110),\n\n    IsDistinctFrom(\"IS DISTINCT FROM\", 110),\n    IsNotDistinctFrom(\"IS NOT DISTINCT FROM\", 110),\n\n    Like(\"LIKE\", 110),\n    SoudsLike(\"SOUNDS LIKE\", 110),\n    NotLike(\"NOT LIKE\", 110),\n\n    ILike(\"ILIKE\", 110),\n    NotILike(\"NOT ILIKE\", 110),\n    AT_AT(\"@@\", 110), // postgresql textsearch\n    SIMILAR_TO(\"SIMILAR TO\", 110),\n    POSIX_Regular_Match(\"~\", 110),\n    POSIX_Regular_Match_Insensitive(\"~*\", 110),\n    POSIX_Regular_Not_Match(\"!~\", 110),\n    POSIX_Regular_Not_Match_POSIX_Regular_Match_Insensitive(\"!~*\", 110),\n    Array_Contains(\"@>\", 110),\n    Array_ContainedBy(\"<@\", 110),\n    SAME_AS(\"~=\", 110),\n    JSONContains(\"?\", 110),\n\n    RLike(\"RLIKE\", 110),\n    NotRLike(\"NOT RLIKE\", 110),\n\n    NotEqual(\"!=\", 110),\n    NotLessThan(\"!<\", 110),\n    NotGreaterThan(\"!>\", 110),\n    IsNot(\"IS NOT\", 110),\n    Escape(\"ESCAPE\", 110),\n    RegExp(\"REGEXP\", 110),\n    NotRegExp(\"NOT REGEXP\", 110),\n    Equality(\"=\", 110),\n    EqEq(\"==\", 110),\n\n    BitwiseNot(\"!\", 130),\n    Concat(\"||\", 140),\n\n    BooleanAnd(\"AND\", 140),\n    BooleanXor(\"XOR\", 150),\n    BooleanOr(\"OR\", 160),\n    Assignment(\":=\", 169),\n    Blank(\"\", 170),\n\n    PG_And(\"&&\", 140),\n    PG_ST_DISTANCE(\"<->\", 20);\n\n    public static int getPriority(SQLBinaryOperator operator) {\n        return 0;\n    }\n\n    public final String name;\n    public final String nameLCase;\n    public final int priority;\n\n    SQLBinaryOperator(String name, int priority) {\n        this.name = name;\n        this.nameLCase = name.toLowerCase();\n        this.priority = priority;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public int getPriority() {\n        return this.priority;\n    }\n\n    public boolean isRelational() {\n        switch (this) {\n            case Equality:\n            case Like:\n            case SoudsLike:\n            case NotEqual:\n            case GreaterThan:\n            case GreaterThanOrEqual:\n            case LessThan:\n            case LessThanOrEqual:\n            case LessThanOrGreater:\n            case NotLike:\n            case NotLessThan:\n            case NotGreaterThan:\n            case RLike:\n            case NotRLike:\n            case RegExp:\n            case NotRegExp:\n            case Is:\n            case IsNot:\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public boolean isLogical() {\n        return this == BooleanAnd || this == BooleanOr || this == BooleanXor;\n    }\n\n    public boolean isArithmetic() {\n        switch (this) {\n            case Add:\n            case Subtract:\n            case Multiply:\n            case Divide:\n            case DIV:\n            case Modulus:\n            case Mod:\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public static SQLBinaryOperator from(String str) {\n        if (str == null) {\n            return null;\n        }\n\n        for (SQLBinaryOperator value : values()) {\n            if (value.name.equals(str)) {\n                return value;\n            }\n        }\n\n        return valueOf(str);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBooleanExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLBooleanExpr extends SQLTypeExpr {\n    public static final SQLDataType DATA_TYPE = new SQLDataTypeImpl(SQLDataType.Constants.BOOLEAN);\n\n    private boolean value;\n\n    public SQLBooleanExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.BOOLEAN));\n    }\n\n    public SQLBooleanExpr(boolean value) {\n        this();\n        this.value = value;\n    }\n\n    public boolean getBooleanValue() {\n        return getValue();\n    }\n\n    public Boolean getValue() {\n        return (Boolean) value;\n    }\n\n    public void setValue(boolean value) {\n        this.value = value;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(getValue() ? \"true\" : \"false\");\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + (getValue() ? 1231 : 1237);\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLBooleanExpr other = (SQLBooleanExpr) obj;\n        if (value != other.value) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLBooleanExpr clone() {\n        return new SQLBooleanExpr(getValue());\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.emptyList();\n    }\n\n    public static enum Type {\n        ON_OFF\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCaseExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCaseExpr extends SQLExprImpl implements SQLReplaceable, Serializable {\n    private static final long serialVersionUID = 1L;\n    private final List<Item> items = new ArrayList<Item>();\n    private SQLExpr valueExpr;\n    private SQLExpr elseExpr;\n\n    public SQLCaseExpr() {\n    }\n\n    public SQLExpr getValueExpr() {\n        return this.valueExpr;\n    }\n\n    public void setValueExpr(SQLExpr valueExpr) {\n        if (valueExpr != null) {\n            valueExpr.setParent(this);\n        }\n        this.valueExpr = valueExpr;\n    }\n\n    public SQLExpr getElseExpr() {\n        return this.elseExpr;\n    }\n\n    public void setElseExpr(SQLExpr elseExpr) {\n        if (elseExpr != null) {\n            elseExpr.setParent(this);\n        }\n        this.elseExpr = elseExpr;\n    }\n\n    public List<Item> getItems() {\n        return this.items;\n    }\n\n    public void addItem(Item item) {\n        if (item != null) {\n            item.setParent(this);\n            this.items.add(item);\n        }\n    }\n\n    public void addItem(SQLExpr condition, SQLExpr value) {\n        this.addItem(new Item(condition, value));\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (valueExpr != null) {\n                valueExpr.accept(visitor);\n            }\n\n            for (Item item : this.items) {\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n\n            if (elseExpr != null) {\n                elseExpr.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (valueExpr != null) {\n            children.add(this.valueExpr);\n        }\n        children.addAll(this.items);\n        if (elseExpr != null) {\n            children.add(this.elseExpr);\n        }\n        return children;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (valueExpr == expr) {\n            setValueExpr(target);\n            return true;\n        }\n\n        if (elseExpr == expr) {\n            setElseExpr(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public static class Item extends SQLObjectImpl implements SQLReplaceable, Serializable {\n        private static final long serialVersionUID = 1L;\n        private SQLExpr conditionExpr;\n        private SQLExpr valueExpr;\n\n        public Item() {\n        }\n\n        public Item(SQLExpr conditionExpr, SQLExpr valueExpr) {\n            setConditionExpr(conditionExpr);\n            setValueExpr(valueExpr);\n        }\n\n        public SQLExpr getConditionExpr() {\n            return this.conditionExpr;\n        }\n\n        public void setConditionExpr(SQLExpr conditionExpr) {\n            if (conditionExpr != null) {\n                conditionExpr.setParent(this);\n            }\n            this.conditionExpr = conditionExpr;\n        }\n\n        public SQLExpr getValueExpr() {\n            return this.valueExpr;\n        }\n\n        public void setValueExpr(SQLExpr valueExpr) {\n            if (valueExpr != null) {\n                valueExpr.setParent(this);\n            }\n            this.valueExpr = valueExpr;\n        }\n\n        protected void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                if (this.conditionExpr != null) {\n                    this.conditionExpr.accept(visitor);\n                }\n\n                if (valueExpr != null) {\n                    valueExpr.accept(visitor);\n                }\n            }\n            visitor.endVisit(this);\n        }\n\n        @Override\n        public int hashCode() {\n            final int prime = 31;\n            int result = 1;\n            result = prime * result + ((conditionExpr == null) ? 0 : conditionExpr.hashCode());\n            result = prime * result + ((valueExpr == null) ? 0 : valueExpr.hashCode());\n            return result;\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            if (this == obj) {\n                return true;\n            }\n            if (obj == null) {\n                return false;\n            }\n            if (getClass() != obj.getClass()) {\n                return false;\n            }\n            Item other = (Item) obj;\n            if (conditionExpr == null) {\n                if (other.conditionExpr != null) {\n                    return false;\n                }\n            } else if (!conditionExpr.equals(other.conditionExpr)) {\n                return false;\n            }\n            if (valueExpr == null) {\n                if (other.valueExpr != null) {\n                    return false;\n                }\n            } else if (!valueExpr.equals(other.valueExpr)) {\n                return false;\n            }\n            return true;\n        }\n\n        public Item clone() {\n            Item x = new Item();\n            if (conditionExpr != null) {\n                x.setConditionExpr(conditionExpr.clone());\n            }\n            if (valueExpr != null) {\n                x.setValueExpr(valueExpr.clone());\n            }\n            return x;\n        }\n\n        @Override\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            if (valueExpr == expr) {\n                setValueExpr(target);\n                return true;\n            }\n\n            if (conditionExpr == expr) {\n                setConditionExpr(target);\n                return true;\n            }\n\n            return false;\n        }\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((elseExpr == null) ? 0 : elseExpr.hashCode());\n        result = prime * result + items.hashCode();\n        result = prime * result + ((valueExpr == null) ? 0 : valueExpr.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLCaseExpr other = (SQLCaseExpr) obj;\n        if (elseExpr == null) {\n            if (other.elseExpr != null) {\n                return false;\n            }\n        } else if (!elseExpr.equals(other.elseExpr)) {\n            return false;\n        }\n        if (!items.equals(other.items)) {\n            return false;\n        }\n        if (valueExpr == null) {\n            if (other.valueExpr != null) {\n                return false;\n            }\n        } else if (!valueExpr.equals(other.valueExpr)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLCaseExpr clone() {\n        SQLCaseExpr x = new SQLCaseExpr();\n\n        for (Item item : items) {\n            x.addItem(item.clone());\n        }\n\n        if (valueExpr != null) {\n            x.setValueExpr(valueExpr.clone());\n        }\n\n        if (elseExpr != null) {\n            x.setElseExpr(elseExpr.clone());\n        }\n\n        return x;\n    }\n\n    public SQLDataType computeDataType() {\n        for (Item item : items) {\n            SQLExpr expr = item.getValueExpr();\n            if (expr != null) {\n                SQLDataType dataType = expr.computeDataType();\n                if (dataType != null) {\n                    return dataType;\n                }\n            }\n        }\n\n        if (elseExpr != null) {\n            return elseExpr.computeDataType();\n        }\n\n        return null;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, (DbType) null);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCaseStatement extends SQLStatementImpl implements Serializable {\n    private final List<Item> items = new ArrayList<Item>();\n    private SQLExpr valueExpr;\n    private List<SQLStatement> elseStatements = new ArrayList<SQLStatement>();\n\n    public SQLCaseStatement() {\n    }\n\n    public SQLExpr getValueExpr() {\n        return this.valueExpr;\n    }\n\n    public void setValueExpr(SQLExpr valueExpr) {\n        if (valueExpr != null) {\n            valueExpr.setParent(this);\n        }\n        this.valueExpr = valueExpr;\n    }\n\n    public List<SQLStatement> getElseStatements() {\n        return elseStatements;\n    }\n\n    public List<Item> getItems() {\n        return this.items;\n    }\n\n    public void addItem(Item item) {\n        if (item != null) {\n            item.setParent(this);\n            this.items.add(item);\n        }\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.valueExpr != null) {\n                this.valueExpr.accept(visitor);\n            }\n\n            if (this.items != null) {\n                for (Item item : this.items) {\n                    if (item != null) {\n                        item.accept(visitor);\n                    }\n                }\n            }\n\n            if (this.elseStatements != null) {\n                for (SQLStatement item : this.elseStatements) {\n                    if (item != null) {\n                        item.accept(visitor);\n                    }\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (valueExpr != null) {\n            children.add(valueExpr);\n        }\n        children.addAll(this.items);\n        children.addAll(this.elseStatements);\n        return children;\n    }\n\n    public static class Item extends SQLObjectImpl implements Serializable {\n        private static final long serialVersionUID = 1L;\n        private SQLExpr conditionExpr;\n        private SQLStatement statement;\n\n        public Item() {\n        }\n\n        public Item(SQLExpr conditionExpr, SQLStatement statement) {\n            setConditionExpr(conditionExpr);\n            setStatement(statement);\n        }\n\n        public SQLExpr getConditionExpr() {\n            return this.conditionExpr;\n        }\n\n        public void setConditionExpr(SQLExpr conditionExpr) {\n            if (conditionExpr != null) {\n                conditionExpr.setParent(this);\n            }\n            this.conditionExpr = conditionExpr;\n        }\n\n        public SQLStatement getStatement() {\n            return this.statement;\n        }\n\n        public void setStatement(SQLStatement statement) {\n            if (statement != null) {\n                statement.setParent(this);\n            }\n            this.statement = statement;\n        }\n\n        protected void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                if (this.conditionExpr != null) {\n                    this.conditionExpr.accept(visitor);\n                }\n\n                if (this.statement != null) {\n                    this.statement.accept(visitor);\n                }\n            }\n            visitor.endVisit(this);\n        }\n\n        @Override\n        public int hashCode() {\n            final int prime = 31;\n            int result = 1;\n            result = prime * result + ((conditionExpr == null) ? 0 : conditionExpr.hashCode());\n            result = prime * result + ((statement == null) ? 0 : statement.hashCode());\n            return result;\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            if (this == obj) {\n                return true;\n            }\n            if (obj == null) {\n                return false;\n            }\n            if (getClass() != obj.getClass()) {\n                return false;\n            }\n            Item other = (Item) obj;\n            if (conditionExpr == null) {\n                if (other.conditionExpr != null) {\n                    return false;\n                }\n            } else if (!conditionExpr.equals(other.conditionExpr)) {\n                return false;\n            }\n            if (statement == null) {\n                if (other.statement != null) {\n                    return false;\n                }\n            } else if (!statement.equals(other.statement)) {\n                return false;\n            }\n            return true;\n        }\n\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLCaseStatement that = (SQLCaseStatement) o;\n\n        if (!items.equals(that.items)) {\n            return false;\n        }\n        if (valueExpr != null ? !valueExpr.equals(that.valueExpr) : that.valueExpr != null) {\n            return false;\n        }\n        return elseStatements != null ? elseStatements.equals(that.elseStatements) : that.elseStatements == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = items.hashCode();\n        result = 31 * result + (valueExpr != null ? valueExpr.hashCode() : 0);\n        result = 31 * result + (elseStatements != null ? elseStatements.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCastExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class SQLCastExpr extends SQLExprImpl implements SQLObjectWithDataType, SQLReplaceable {\n    protected boolean isTry;\n    protected SQLExpr expr;\n    protected SQLDataType dataType;\n    protected SQLExpr format;\n\n    public SQLCastExpr() {\n    }\n\n    public SQLCastExpr(SQLExpr expr, SQLDataType dataType) {\n        setExpr(expr);\n        setDataType(dataType);\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public SQLExpr getFormat() {\n        return format;\n    }\n\n    public void setFormat(SQLExpr format) {\n        if (format != null) {\n            format.setParent(this);\n        }\n        this.format = format;\n    }\n\n    public SQLDataType getDataType() {\n        return this.dataType;\n    }\n\n    public long dateTypeHashCode() {\n        if (this.dataType == null) {\n            return 0;\n        }\n\n        return this.dataType.nameHashCode64();\n    }\n\n    public void setDataType(SQLDataType dataType) {\n        if (dataType != null) {\n            dataType.setParent(this);\n        }\n        this.dataType = dataType;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.expr != null) {\n                this.expr.accept(visitor);\n            }\n\n            if (this.dataType != null) {\n                this.dataType.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Arrays.asList(this.expr, this.dataType);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLCastExpr castExpr = (SQLCastExpr) o;\n\n        if (isTry != castExpr.isTry) {\n            return false;\n        }\n        if (expr != null ? !expr.equals(castExpr.expr) : castExpr.expr != null) {\n            return false;\n        }\n        return dataType != null ? dataType.equals(castExpr.dataType) : castExpr.dataType == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = (isTry ? 1 : 0);\n        result = 31 * result + (expr != null ? expr.hashCode() : 0);\n        result = 31 * result + (dataType != null ? dataType.hashCode() : 0);\n        return result;\n    }\n\n    public SQLDataType computeDataType() {\n        return dataType;\n    }\n\n    public SQLCastExpr clone() {\n        SQLCastExpr x = new SQLCastExpr();\n        x.isTry = isTry;\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        if (dataType != null) {\n            x.setDataType(dataType.clone());\n        }\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n\n    public boolean isTry() {\n        return isTry;\n    }\n\n    public void setTry(boolean aTry) {\n        isTry = aTry;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCharExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLCharExpr extends SQLTextLiteralExpr implements SQLValuableExpr, Comparable<SQLCharExpr> {\n    public static final SQLDataType DATA_TYPE = new SQLCharacterDataType(\"char\");\n\n    protected String collate;\n\n    public SQLCharExpr() {\n    }\n\n    public SQLCharExpr(String text) {\n        this.text = text;\n    }\n\n    public SQLCharExpr(String text, SQLObject parent) {\n        this.text = text;\n        this.parent = parent;\n    }\n\n    public String getCollate() {\n        return collate;\n    }\n\n    public void setCollate(String collate) {\n        this.collate = collate;\n    }\n\n    public void output(StringBuilder buf) {\n        this.accept(new SQLASTOutputVisitor(buf));\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public Object getValue() {\n        return this.text;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this);\n    }\n\n    public SQLCharExpr clone() {\n        SQLCharExpr expr = new SQLCharExpr(this.text);\n        expr.setCollate(collate);\n        return expr;\n    }\n\n    public SQLDataType computeDataType() {\n        return DATA_TYPE;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    public SQLDateExpr toDate() {\n        return new SQLDateExpr(this.text);\n    }\n\n    public SQLDateTimeExpr toDateTime() {\n        return new SQLDateTimeExpr(this.text);\n    }\n\n    public SQLTimestampExpr toTimestamp() {\n        String text = this.text;\n        if (text.length() == 10) {\n            text += \" 00:00:00\";\n        }\n        return new SQLTimestampExpr(text);\n    }\n\n    @Override\n    public int compareTo(SQLCharExpr o) {\n        return this.text.compareTo(o.text);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLContainsExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class SQLContainsExpr extends SQLExprImpl implements SQLReplaceable, Serializable {\n    private static final long serialVersionUID = 1L;\n    private boolean not;\n    private SQLExpr expr;\n    private List<SQLExpr> targetList = new ArrayList<SQLExpr>();\n\n    public SQLContainsExpr() {\n    }\n\n    public SQLContainsExpr(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public SQLContainsExpr(SQLExpr expr, boolean not) {\n        this.setExpr(expr);\n        this.not = not;\n    }\n\n    public SQLContainsExpr clone() {\n        SQLContainsExpr x = new SQLContainsExpr();\n        x.not = not;\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        for (SQLExpr e : targetList) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.targetList.add(e2);\n        }\n        return x;\n    }\n\n    public boolean isNot() {\n        return this.not;\n    }\n\n    public void setNot(boolean not) {\n        this.not = not;\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n\n        this.expr = expr;\n    }\n\n    public List<SQLExpr> getTargetList() {\n        return this.targetList;\n    }\n\n    public void setTargetList(List<SQLExpr> targetList) {\n        this.targetList = targetList;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.expr != null) {\n                this.expr.accept(visitor);\n            }\n\n            if (this.targetList != null) {\n                for (SQLExpr item : this.targetList) {\n                    if (item != null) {\n                        item.accept(visitor);\n                    }\n                }\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (this.expr != null) {\n            children.add(this.expr);\n        }\n        children.addAll(this.targetList);\n        return children;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        result = prime * result + (not ? 1231 : 1237);\n        result = prime * result + ((targetList == null) ? 0 : targetList.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLContainsExpr other = (SQLContainsExpr) obj;\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        if (not != other.not) {\n            return false;\n        }\n        if (targetList == null) {\n            if (other.targetList != null) {\n                return false;\n            }\n        } else if (!targetList.equals(other.targetList)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLDataType computeDataType() {\n        return SQLBooleanExpr.DATA_TYPE;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        for (int i = 0; i < targetList.size(); i++) {\n            if (targetList.get(i) == expr) {\n                targetList.set(i, target);\n                target.setParent(this);\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCurrentOfCursorExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLCurrentOfCursorExpr extends SQLExprImpl implements SQLReplaceable {\n    private SQLName cursorName;\n\n    public SQLCurrentOfCursorExpr() {\n    }\n\n    public SQLCurrentOfCursorExpr(SQLName cursorName) {\n        this.cursorName = cursorName;\n    }\n\n    public SQLCurrentOfCursorExpr clone() {\n        SQLCurrentOfCursorExpr x = new SQLCurrentOfCursorExpr();\n        if (cursorName != null) {\n            x.setCursorName(cursorName.clone());\n        }\n        return x;\n    }\n\n    public SQLName getCursorName() {\n        return cursorName;\n    }\n\n    public void setCursorName(SQLName cursorName) {\n        if (cursorName != null) {\n            cursorName.setParent(this);\n        }\n        this.cursorName = cursorName;\n    }\n\n    @Override\n    public void output(StringBuilder buf) {\n        buf.append(\"CURRENT OF \");\n        cursorName.output(buf);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (cursorName != null) {\n                cursorName.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.cursorName);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((cursorName == null) ? 0 : cursorName.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLCurrentOfCursorExpr other = (SQLCurrentOfCursorExpr) obj;\n        if (cursorName == null) {\n            if (other.cursorName != null) {\n                return false;\n            }\n        } else if (!cursorName.equals(other.cursorName)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.cursorName == expr) {\n            setCursorName((SQLName) target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.MySqlUtils;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\n\npublic class SQLDateExpr extends SQLDateTypeExpr {\n    public static final SQLDataType DATA_TYPE = new SQLDataTypeImpl(SQLDataType.Constants.DATE);\n\n    public SQLDateExpr() {\n        super(DATA_TYPE);\n    }\n\n    @Override\n    public SQLDateExpr clone() {\n        SQLDateExpr x = new SQLDateExpr();\n        x.value = this.value;\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.dataType);\n        }\n        visitor.endVisit(this);\n    }\n    public SQLDateExpr(String literal) {\n        this();\n        this.setValue(literal);\n    }\n\n    public SQLDateExpr(Date literal) {\n        this();\n        this.setValue(literal);\n    }\n\n    public SQLDateExpr(Date literal, TimeZone timeZone) {\n        this();\n        this.setValue(literal, timeZone);\n    }\n\n    public void setValue(String literal) {\n        this.value = literal;\n    }\n\n    public void setValue(Date x) {\n        setValue(x, null);\n    }\n\n    public void setValue(Date x, TimeZone timeZone) {\n        if (x == null) {\n            this.value = null;\n            return;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        if (timeZone != null) {\n            format.setTimeZone(timeZone);\n        }\n        String text = format.format(x);\n        setValue(text);\n    }\n\n    public Date getDate() {\n        return getDate(null);\n    }\n\n    public Date getDate(TimeZone timeZone) {\n        return MySqlUtils.parseDate(getValue(), timeZone);\n    }\n\n    public boolean addDay(int delta) {\n        if (value == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        try {\n            Date date = format.parse(value.toString());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.DAY_OF_MONTH, delta);\n            String result_chars = format.format(calendar.getTime());\n            setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public boolean addMonth(int delta) {\n        if (value == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        try {\n            Date date = format.parse(value.toString());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.MONTH, delta);\n            String result_chars = format.format(calendar.getTime());\n            setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public boolean addYear(int delta) {\n        if (value == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        try {\n            Date date = format.parse(value.toString());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.YEAR, delta);\n            String result_chars = format.format(calendar.getTime());\n            setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    @Override\n    public String getValue() {\n        return (String) value;\n    }\n\n    public static boolean check(String str) {\n        final int len;\n        if (str == null || (len = str.length()) < 8) {\n            return false;\n        }\n\n        final char c0 = str.charAt(0);\n        final char c1 = str.charAt(1);\n        final char c2 = str.charAt(2);\n        final char c3 = str.charAt(3);\n        final char c4 = str.charAt(4);\n        final char c5 = str.charAt(5);\n        final char c6 = str.charAt(6);\n        final char c7 = str.charAt(7);\n\n        if (c0 < '1' | c0 > '9') {\n            return false;\n        }\n        if (c1 < '0' | c1 > '9') {\n            return false;\n        }\n        if (c2 < '0' | c2 > '9') {\n            return false;\n        }\n        if (c3 < '0' | c3 > '9') {\n            return false;\n        }\n\n        int year = (c0 - '0') * 1000 + (c1 - '0') * 100 + (c2 - '0') * 10 + (c3 - '0');\n        if (year < 1000) {\n            return false;\n        }\n\n        if (c4 != '-') {\n            return false;\n        }\n\n        if (c5 < '0' | c5 > '9') {\n            return false;\n        }\n\n        int month, day;\n        if (c6 == '-') {\n            month = (c5 - '0');\n\n            if (c7 < '0' | c7 > '9') {\n                return false;\n            }\n\n            if (len == 8) {\n                day = c7 - '0';\n            } else if (len == 9) {\n                final char c8 = str.charAt(8);\n                if (c8 < '0' | c8 > '9') {\n                    return false;\n                }\n                day = (c7 - '0') * 10 + (c8 - '0');\n            } else {\n                return false;\n            }\n        } else if (c6 < '0' | c6 > '9') {\n            return false;\n        } else {\n            month = (c5 - '0') * 10 + (c6 - '0');\n\n            if (c7 != '-') {\n                return false;\n            }\n\n            if (len == 9) {\n                final char c8 = str.charAt(8);\n                if (c8 < '0' | c8 > '9') {\n                    return false;\n                }\n                day = c8 - '0';\n            } else if (len == 10) {\n                final char c8 = str.charAt(8);\n                final char c9 = str.charAt(9);\n                if (c8 < '0' | c8 > '9') {\n                    return false;\n                }\n                if (c9 < '0' | c9 > '9') {\n                    return false;\n                }\n                day = (c8 - '0') * 10 + (c9 - '0');\n            } else {\n                return false;\n            }\n        }\n\n        if (month < 1) {\n            return false;\n        }\n\n        if (day < 1) {\n            return false;\n        }\n\n        switch (month) {\n            case 1:\n            case 3:\n            case 5:\n            case 7:\n            case 8:\n            case 10:\n            case 12:\n                if (day > 31) {\n                    return false;\n                }\n                return true;\n            case 2:\n                if (day > 29) {\n                    return false;\n                }\n                return true;\n            case 4:\n            case 6:\n            case 9:\n            case 11:\n                if (day > 30) {\n                    return false;\n                }\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public static String format(Calendar calendar) {\n        if (calendar == null) {\n            return null;\n        }\n\n        int year = calendar.get(Calendar.YEAR);\n        int month = calendar.get(Calendar.MONTH) + 1;\n        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);\n\n        char[] chars = new char[10];\n        chars[0] = (char) (year / 1000 + '0');\n        chars[1] = (char) ((year / 100) % 10 + '0');\n        chars[2] = (char) ((year / 10) % 10 + '0');\n        chars[3] = (char) (year % 10 + '0');\n        chars[4] = '-';\n        chars[5] = (char) (month / 10 + '0');\n        chars[6] = (char) (month % 10 + '0');\n        chars[7] = '-';\n        chars[8] = (char) (dayOfMonth / 10 + '0');\n        chars[9] = (char) (dayOfMonth % 10 + '0');\n\n        return new String(chars);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateTimeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.TimeZone;\n\npublic class SQLDateTimeExpr extends SQLDateTypeExpr {\n    public SQLDateTimeExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.DATETIME));\n    }\n\n    public SQLDateTimeExpr(Date now, TimeZone timeZone) {\n        this();\n        setValue(now, timeZone);\n    }\n\n    public void setValue(Date x, TimeZone timeZone) {\n        if (x == null) {\n            this.value = null;\n            return;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        if (timeZone != null) {\n            format.setTimeZone(timeZone);\n        }\n        String text = format.format(x);\n        setValue(text);\n    }\n\n    public SQLDateTimeExpr(String literal) {\n        this();\n        this.setValue(literal);\n    }\n\n    public void setValue(String literal) {\n        value = literal;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.dataType);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public String getValue() {\n        return (String) value;\n    }\n\n    public SQLDateTimeExpr clone() {\n        SQLDateTimeExpr x = new SQLDateTimeExpr();\n        x.value = this.value;\n\n        return x;\n    }\n\n    public static long supportDbTypes = DbType.of(\n            DbType.mysql,\n            DbType.oracle,\n            DbType.presto,\n            DbType.trino,\n            DbType.postgresql,\n            DbType.mariadb,\n            DbType.tidb,\n            DbType.polardbx\n    );\n\n    public static boolean isSupport(DbType dbType) {\n        return (dbType.mask & supportDbTypes) != 0;\n    }\n\n    public static boolean check(String str) {\n        if (str == null || str.length() != 8) {\n            return false;\n        }\n\n        if (str.charAt(2) != ':' && str.charAt(5) != ':') {\n            return false;\n        }\n\n        char c0 = str.charAt(0);\n        char c1 = str.charAt(1);\n        char c3 = str.charAt(3);\n        char c4 = str.charAt(4);\n        char c6 = str.charAt(6);\n        char c7 = str.charAt(7);\n\n        if (c0 < '0' || c0 > '9') {\n            return false;\n        }\n        if (c1 < '0' || c1 > '9') {\n            return false;\n        }\n        if (c3 < '0' || c3 > '9') {\n            return false;\n        }\n        if (c4 < '0' || c4 > '9') {\n            return false;\n        }\n        if (c6 < '0' || c6 > '9') {\n            return false;\n        }\n        if (c7 < '0' || c7 > '9') {\n            return false;\n        }\n\n        int HH = (c0 - '0') * 10 + (c1 - '0');\n        int mm = (c3 - '0') * 10 + (c4 - '0');\n        int ss = (c6 - '0') * 10 + (c7 - '0');\n\n        if (HH > 24 || mm > 60 || ss > 60) {\n            return false;\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateTypeExpr.java",
    "content": "package com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\n\npublic abstract class SQLDateTypeExpr extends SQLTypeExpr {\n    public SQLDateTypeExpr(SQLDataType sqlDataType) {\n        super(sqlDataType);\n    }\n\n    @Override\n    public abstract Object getValue();\n\n    @Override\n    public abstract SQLTypeExpr clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDbLinkExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLDbLinkExpr extends SQLExprImpl implements SQLName, SQLExpr, SQLReplaceable {\n    private SQLExpr expr;\n    private String dbLink;\n\n    private long dbLinkHashCode64;\n    private long hashCode64;\n\n    public SQLDbLinkExpr() {\n    }\n\n    public String getSimpleName() {\n        return dbLink;\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    public String getDbLink() {\n        return this.dbLink;\n    }\n\n    public void setDbLink(String dbLink) {\n        this.dbLink = dbLink;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.expr);\n    }\n\n    @Override\n    public int hashCode() {\n        long value = hashCode64();\n        return (int) (value ^ (value >>> 32));\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLDbLinkExpr other = (SQLDbLinkExpr) obj;\n        return this.hashCode64() == other.hashCode64();\n    }\n\n    public SQLDbLinkExpr clone() {\n        SQLDbLinkExpr x = new SQLDbLinkExpr();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.dbLink = dbLink;\n        return x;\n    }\n\n    public long nameHashCode64() {\n        if (dbLinkHashCode64 == 0\n                && dbLink != null) {\n            dbLinkHashCode64 = FnvHash.hashCode64(dbLink);\n        }\n        return dbLinkHashCode64;\n    }\n\n    @Override\n    public long hashCode64() {\n        if (hashCode64 == 0) {\n            long hash;\n            if (expr instanceof SQLName) {\n                hash = ((SQLName) expr).hashCode64();\n\n                hash ^= '@';\n                hash *= FnvHash.PRIME;\n            } else if (expr == null) {\n                hash = FnvHash.BASIC;\n            } else {\n                hash = FnvHash.fnv1a_64_lower(expr.toString());\n\n                hash ^= '@';\n                hash *= FnvHash.PRIME;\n            }\n            hash = FnvHash.hashCode64(hash, dbLink);\n            hashCode64 = hash;\n        }\n\n        return hashCode64;\n    }\n\n    @Override\n    public SQLColumnDefinition getResolvedColumn() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDecimalExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.math.BigDecimal;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLDecimalExpr extends SQLNumericLiteralExpr implements SQLValuableExpr, Comparable<SQLDecimalExpr> {\n    public SQLDecimalExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.DECIMAL));\n    }\n\n    public SQLDecimalExpr(BigDecimal value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLDecimalExpr(String value) {\n        this();\n        this.value = new BigDecimal(value);\n    }\n\n    public SQLDecimalExpr clone() {\n        return new SQLDecimalExpr(getValue());\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Number getNumber() {\n        return getValue();\n    }\n\n    public BigDecimal getValue() {\n        return (BigDecimal) value;\n    }\n\n    public void setValue(BigDecimal value) {\n        this.value = value;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLDecimalExpr other = (SQLDecimalExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            this.value = null;\n            return;\n        }\n\n        this.setValue(((BigDecimal) number));\n    }\n\n    @Override\n    public int compareTo(SQLDecimalExpr o) {\n        return getValue().compareTo(o.getValue());\n    }\n\n    public SQLDecimalExpr negative() {\n        return new SQLDecimalExpr(getValue().negate());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDefaultExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLDefaultExpr extends SQLExprImpl implements SQLLiteralExpr {\n    @Override\n    public boolean equals(Object o) {\n        return o instanceof SQLDefaultExpr;\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String toString() {\n        return \"DEFAULT\";\n    }\n\n    public SQLDefaultExpr clone() {\n        return new SQLDefaultExpr();\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDoubleExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLDoubleExpr extends SQLNumericLiteralExpr implements SQLValuableExpr, Comparable<SQLDoubleExpr> {\n    private double value;\n\n    public SQLDoubleExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.DOUBLE));\n    }\n\n    public SQLDoubleExpr(String value) {\n        this();\n        this.value = Double.parseDouble(value);\n    }\n\n    public SQLDoubleExpr(double value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLDoubleExpr clone() {\n        return new SQLDoubleExpr(value);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Double getNumber() {\n        return value;\n    }\n\n    public Double getValue() {\n        return value;\n    }\n\n    public void setValue(double value) {\n        this.value = value;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLDoubleExpr that = (SQLDoubleExpr) o;\n\n        return Double.compare(that.value, value) == 0;\n    }\n\n    @Override\n    public int hashCode() {\n        long temp = Double.doubleToLongBits(value);\n        return (int) (temp ^ (temp >>> 32));\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            this.setValue(Double.NaN);\n            return;\n        }\n\n        this.setValue(number.doubleValue());\n    }\n\n    @Override\n    public int compareTo(SQLDoubleExpr o) {\n        return Double.compare(value, o.value);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExistsExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLExistsExpr extends SQLExprImpl implements Serializable {\n    private static final long serialVersionUID = 1L;\n    public boolean not;\n    public SQLSelect subQuery;\n\n    public SQLExistsExpr() {\n    }\n\n    public SQLExistsExpr(SQLSelect subQuery) {\n        this.setSubQuery(subQuery);\n    }\n\n    public SQLExistsExpr(SQLSelect subQuery, boolean not) {\n        this.setSubQuery(subQuery);\n        this.not = not;\n    }\n\n    public boolean isNot() {\n        return this.not;\n    }\n\n    public void setNot(boolean not) {\n        this.not = not;\n    }\n\n    public SQLSelect getSubQuery() {\n        return this.subQuery;\n    }\n\n    public void setSubQuery(SQLSelect subQuery) {\n        if (subQuery != null) {\n            subQuery.setParent(this);\n        }\n        this.subQuery = subQuery;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.subQuery != null) {\n                this.subQuery.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.singletonList(this.subQuery);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + (not ? 1231 : 1237);\n        result = prime * result + ((subQuery == null) ? 0 : subQuery.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLExistsExpr other = (SQLExistsExpr) obj;\n        if (not != other.not) {\n            return false;\n        }\n        if (subQuery == null) {\n            if (other.subQuery != null) {\n                return false;\n            }\n        } else if (!subQuery.equals(other.subQuery)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLExistsExpr clone() {\n        SQLExistsExpr x = new SQLExistsExpr();\n\n        x.not = not;\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExprUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.FastsqlException;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.parser.ParserException;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.sql.Types;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.TimeZone;\n\npublic class SQLExprUtils {\n    public static boolean equals(SQLExpr a, SQLExpr b) {\n        if (a == b) {\n            return true;\n        }\n\n        if (a == null || b == null) {\n            return false;\n        }\n\n        Class<?> clazz_a = a.getClass();\n        Class<?> clazz_b = b.getClass();\n\n        if (clazz_a == SQLPropertyExpr.class && clazz_b == SQLIdentifierExpr.class) {\n            return ((SQLPropertyExpr) a).equals((SQLIdentifierExpr) b);\n        }\n\n        if (clazz_b == SQLPropertyExpr.class && clazz_a == SQLIdentifierExpr.class) {\n            return ((SQLPropertyExpr) b).equals((SQLIdentifierExpr) a);\n        }\n\n        if (clazz_a != clazz_b) {\n            return false;\n        }\n\n        if (clazz_a == SQLIdentifierExpr.class) {\n            SQLIdentifierExpr x_a = (SQLIdentifierExpr) a;\n            SQLIdentifierExpr x_b = (SQLIdentifierExpr) b;\n            return x_a.hashCode() == x_b.hashCode();\n        }\n\n        if (clazz_a == SQLBinaryOpExpr.class) {\n            SQLBinaryOpExpr x_a = (SQLBinaryOpExpr) a;\n            SQLBinaryOpExpr x_b = (SQLBinaryOpExpr) b;\n            return x_a.equals(x_b);\n        }\n\n        return a.equals(b);\n    }\n\n    public static boolean isLiteralExpr(SQLExpr expr) {\n        if (expr instanceof SQLLiteralExpr) {\n            return true;\n        }\n\n        if (expr instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binary = (SQLBinaryOpExpr) expr;\n            return isLiteralExpr(binary.left) && isLiteralExpr(binary.right);\n        }\n\n        return false;\n    }\n\n    public static SQLExpr fromJavaObject(Object o) {\n        return fromJavaObject(o, null);\n    }\n\n    public static SQLExpr fromJavaObject(Object o, TimeZone timeZone) {\n        if (o == null) {\n            return new SQLNullExpr();\n        }\n\n        if (o instanceof String) {\n            return new SQLCharExpr((String) o);\n        }\n\n        if (o instanceof BigDecimal) {\n            return new SQLDecimalExpr((BigDecimal) o);\n        }\n\n        if (o instanceof Byte || o instanceof Short || o instanceof Integer || o instanceof Long || o instanceof BigInteger) {\n            return new SQLIntegerExpr((Number) o);\n        }\n\n        if (o instanceof Number) {\n            return new SQLNumberExpr((Number) o);\n        }\n\n        if (o instanceof Date) {\n            return new SQLTimestampExpr((Date) o, timeZone);\n        }\n\n        throw new ParserException(\"not support class : \" + o.getClass());\n    }\n\n    public static SQLInListExpr conditionIn(String column, List<Object> values, TimeZone timeZone) {\n        SQLInListExpr in = new SQLInListExpr();\n        in.setExpr(\n                SQLUtils.toSQLExpr(column));\n\n        for (Object value : values) {\n            in.addTarget(\n                    fromJavaObject(value, timeZone));\n        }\n        return in;\n    }\n\n    public static String quote(String str, DbType dbType, char quote) {\n        SQLExpr expr;\n        if (quote == '`') {\n            expr = new SQLIdentifierExpr(str);\n        } else if (quote == '\"') {\n            if (dbType == DbType.oracle || dbType == DbType.presto || dbType == DbType.trino || dbType == DbType.supersql) {\n                expr = new SQLIdentifierExpr(str);\n            } else {\n                expr = new SQLCharExpr(str);\n            }\n        } else if (quote == '\\'') {\n            expr = new SQLCharExpr(str);\n        } else {\n            throw new FastsqlException(\"quote not support\");\n        }\n\n        return SQLUtils.toSQLString(expr, dbType);\n    }\n\n    public static SQLDataType createDataTypeFromJdbc(DbType dbType, int jdbType, Integer precision, Integer scale) {\n        SQLDataType dataType = null;\n\n        switch (jdbType) {\n            case Types.INTEGER:\n                if (dbType == null) {\n                    return new SQLDataTypeImpl(\"integer\");\n                }\n\n                switch (dbType) {\n                    case mysql:\n                        return new SQLDataTypeImpl(\"int\");\n                    default:\n                        break;\n                }\n                break;\n            case Types.VARCHAR:\n                switch (dbType) {\n                    case mysql:\n                        return new SQLDataTypeImpl(\"varchar\");\n                    default:\n                        break;\n                }\n                break;\n            default:\n                break;\n        }\n\n        if (dataType != null) {\n            if (dbType != null) {\n                dataType.setDbType(dbType);\n            }\n\n            return dataType;\n        }\n        throw new FastsqlException(\"type \" + jdbType + \" not support\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExtractExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLExtractExpr extends SQLExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n    private SQLIntervalUnit unit;\n\n    public SQLExtractExpr() {\n    }\n\n    public SQLExtractExpr clone() {\n        SQLExtractExpr x = new SQLExtractExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        x.unit = unit;\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.value = value;\n    }\n\n    public SQLIntervalUnit getUnit() {\n        return unit;\n    }\n\n    public void setUnit(SQLIntervalUnit unit) {\n        this.unit = unit;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.value != null) {\n                this.value.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((unit == null) ? 0 : unit.hashCode());\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (!(obj instanceof SQLExtractExpr)) {\n            return false;\n        }\n        SQLExtractExpr other = (SQLExtractExpr) obj;\n        if (unit != other.unit) {\n            return false;\n        }\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLDataType computeDataType() {\n        return SQLIntegerExpr.DATA_TYPE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLFlashbackExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Created by wenshao on 14/06/2017.\n */\npublic class SQLFlashbackExpr extends SQLExprImpl implements SQLReplaceable {\n    private Type type;\n    private SQLExpr expr;\n\n    public SQLFlashbackExpr() {\n    }\n\n    public SQLFlashbackExpr(Type type, SQLExpr expr) {\n        this.type = type;\n        this.setExpr(expr);\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public void setType(Type type) {\n        this.type = type;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr((SQLName) target);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.expr != null) {\n                this.expr.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(expr);\n    }\n\n    public SQLFlashbackExpr clone() {\n        SQLFlashbackExpr x = new SQLFlashbackExpr();\n        x.type = this.type;\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        return x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLFlashbackExpr that = (SQLFlashbackExpr) o;\n\n        if (type != that.type) {\n            return false;\n        }\n        return expr != null ? expr.equals(that.expr) : that.expr == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = type != null ? type.hashCode() : 0;\n        result = 31 * result + (expr != null ? expr.hashCode() : 0);\n        return result;\n    }\n\n    public static enum Type {\n        SCN, TIMESTAMP\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLFloatExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLFloatExpr extends SQLNumericLiteralExpr implements SQLValuableExpr, Comparable<SQLFloatExpr> {\n    private float value;\n\n    public SQLFloatExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.FLOAT));\n    }\n\n    public SQLFloatExpr(String value) {\n        this();\n        this.value = Float.parseFloat(value);\n    }\n\n    public SQLFloatExpr(float value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLFloatExpr clone() {\n        return new SQLFloatExpr(value);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Float getNumber() {\n        return value;\n    }\n\n    public Float getValue() {\n        return value;\n    }\n\n    public void setValue(float value) {\n        this.value = value;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLFloatExpr that = (SQLFloatExpr) o;\n\n        return Double.compare(that.value, value) == 0;\n    }\n\n    @Override\n    public int hashCode() {\n        long temp = Double.doubleToLongBits(value);\n        return (int) (temp ^ (temp >>> 32));\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            this.setValue(Float.NaN);\n            return;\n        }\n\n        this.setValue(number.floatValue());\n    }\n\n    @Override\n    public int compareTo(SQLFloatExpr o) {\n        return Float.compare(value, o.value);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLGroupingSetExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLGroupingSetExpr extends SQLExprImpl implements SQLReplaceable {\n    private final List<SQLExpr> parameters = new ArrayList<SQLExpr>();\n\n    public SQLGroupingSetExpr clone() {\n        SQLGroupingSetExpr x = new SQLGroupingSetExpr();\n        for (SQLExpr p : parameters) {\n            SQLExpr p2 = p.clone();\n            p2.setParent(x);\n            x.parameters.add(p2);\n        }\n        return x;\n    }\n\n    public List<SQLExpr> getParameters() {\n        return parameters;\n    }\n\n    public void addParameter(SQLExpr parameter) {\n        if (parameter != null) {\n            parameter.setParent(this);\n        }\n        this.parameters.add(parameter);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return this.parameters;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + parameters.hashCode();\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (!(obj instanceof SQLGroupingSetExpr)) {\n            return false;\n        }\n        SQLGroupingSetExpr other = (SQLGroupingSetExpr) obj;\n        if (!parameters.equals(other.parameters)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < parameters.size(); i++) {\n            if (parameters.get(i) == expr) {\n                target.setParent(this);\n                parameters.set(i, target);\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLHexExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.HexBin;\n\nimport java.nio.charset.StandardCharsets;\n\npublic class SQLHexExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValuableExpr {\n    private final String hex;\n\n    public SQLHexExpr(String hex) {\n        this.hex = hex;\n    }\n\n    public String getHex() {\n        return hex;\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(\"0x\");\n        buf.append(this.hex);\n\n        String charset = (String) getAttribute(\"USING\");\n        if (charset != null) {\n            buf.append(\" USING \");\n            buf.append(charset);\n        }\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((hex == null) ? 0 : hex.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLHexExpr other = (SQLHexExpr) obj;\n        if (hex == null) {\n            if (other.hex != null) {\n                return false;\n            }\n        } else if (!hex.equals(other.hex)) {\n            return false;\n        }\n        return true;\n    }\n\n    public byte[] toBytes() {\n        return HexBin.decode(this.hex);\n    }\n\n    public SQLHexExpr clone() {\n        return new SQLHexExpr(hex);\n    }\n\n    public byte[] getValue() {\n        return toBytes();\n    }\n\n    public SQLCharExpr toCharExpr() {\n        byte[] bytes = toBytes();\n        if (bytes == null) {\n            return null;\n        }\n        String str = new String(bytes, StandardCharsets.UTF_8);\n        return new SQLCharExpr(str);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLIdentifierExpr extends SQLExprImpl implements SQLName, Comparable<SQLIdentifierExpr> {\n    protected String name;\n    protected long hashCode64;\n\n    private SQLObject resolvedColumn;\n    private SQLObject resolvedOwnerObject;\n\n    protected String collate;\n\n    public SQLIdentifierExpr() {\n    }\n\n    public SQLIdentifierExpr(String name) {\n        this.name = name;\n    }\n\n    public SQLIdentifierExpr(String name, long hash_lower) {\n        this.name = name;\n        this.hashCode64 = hash_lower;\n    }\n\n    public String getSimpleName() {\n        return name;\n    }\n\n    public String getLowerName() {\n        if (name == null) {\n            return null;\n        }\n\n        return name.toLowerCase();\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n        this.hashCode64 = 0L;\n\n        if (parent instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) parent;\n            propertyExpr.computeHashCode64();\n        }\n    }\n\n    public String getCollate() {\n        return collate;\n    }\n\n    public void setCollate(String collate) {\n        this.collate = collate;\n    }\n\n    public long nameHashCode64() {\n        return hashCode64();\n    }\n\n    @Override\n    public long hashCode64() {\n        if (hashCode64 == 0\n                && name != null) {\n            if (collate != null) {\n                hashCode64 = FnvHash.hashCode64(name + collate);\n            } else {\n                hashCode64 = FnvHash.hashCode64(name);\n            }\n        }\n        return hashCode64;\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(this.name);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        long value = hashCode64();\n        return (int) (value ^ (value >>> 32));\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (obj instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) obj).equals(this);\n        }\n\n        if (!(obj instanceof SQLIdentifierExpr)) {\n            return false;\n        }\n\n        SQLIdentifierExpr other = (SQLIdentifierExpr) obj;\n        return this.hashCode64() == other.hashCode64();\n    }\n\n    public String toString() {\n        return this.name;\n    }\n\n    public SQLIdentifierExpr clone() {\n        SQLIdentifierExpr x = new SQLIdentifierExpr(this.name, hashCode64);\n        x.resolvedColumn = resolvedColumn;\n        x.resolvedOwnerObject = resolvedOwnerObject;\n\n        if (hint != null) {\n            x.hint = hint.clone();\n        }\n        x.collate = collate;\n        return x;\n    }\n\n    public SQLIdentifierExpr simplify() {\n        String normalized = SQLUtils.normalize(name);\n        if (normalized != name) {\n            return new SQLIdentifierExpr(normalized, hashCode64);\n        }\n        return this;\n    }\n\n    public String normalizedName() {\n        return SQLUtils.normalize(name);\n    }\n\n    public SQLColumnDefinition getResolvedColumn() {\n        if (resolvedColumn instanceof SQLColumnDefinition) {\n            return (SQLColumnDefinition) resolvedColumn;\n        }\n\n        if (resolvedColumn instanceof SQLSelectItem) {\n            SQLSelectItem selectItem = (SQLSelectItem) resolvedColumn;\n            final SQLExpr expr = selectItem.getExpr();\n            if (expr instanceof SQLIdentifierExpr && expr != this) {\n                return ((SQLIdentifierExpr) expr).getResolvedColumn();\n            } else if (expr instanceof SQLPropertyExpr) {\n                return ((SQLPropertyExpr) expr).getResolvedColumn();\n            }\n        }\n\n        return null;\n    }\n\n    public SQLSelectItem getResolvedSelectItem() {\n        if (resolvedColumn instanceof SQLSelectItem) {\n            return (SQLSelectItem) resolvedColumn;\n        }\n\n        return null;\n    }\n\n    public SQLObject getResolvedColumnObject() {\n        return resolvedColumn;\n    }\n\n    public void setResolvedColumn(SQLColumnDefinition resolvedColumn) {\n        this.resolvedColumn = resolvedColumn;\n    }\n\n    public void setResolvedColumn(SQLObject resolvedColumn) {\n        this.resolvedColumn = resolvedColumn;\n    }\n\n    public void setResolvedColumn(SQLSelectItem selectItem) {\n        this.resolvedColumn = selectItem;\n    }\n\n    public SQLTableSource getResolvedTableSource() {\n        if (resolvedOwnerObject instanceof SQLTableSource) {\n            return (SQLTableSource) resolvedOwnerObject;\n        }\n\n        return null;\n    }\n\n    public void setResolvedTableSource(SQLTableSource resolvedTableSource) {\n        this.resolvedOwnerObject = resolvedTableSource;\n    }\n\n    public SQLObject getResolvedOwnerObject() {\n        return resolvedOwnerObject;\n    }\n\n    public void setResolvedOwnerObject(SQLObject resolvedOwnerObject) {\n        this.resolvedOwnerObject = resolvedOwnerObject;\n    }\n\n    public SQLParameter getResolvedParameter() {\n        if (resolvedColumn instanceof SQLParameter) {\n            return (SQLParameter) this.resolvedColumn;\n        }\n        return null;\n    }\n\n    public void setResolvedParameter(SQLParameter resolvedParameter) {\n        this.resolvedColumn = resolvedParameter;\n    }\n\n    public SQLDeclareItem getResolvedDeclareItem() {\n        if (resolvedColumn instanceof SQLDeclareItem) {\n            return (SQLDeclareItem) this.resolvedColumn;\n        }\n        return null;\n    }\n\n    public void setResolvedDeclareItem(SQLDeclareItem resolvedDeclareItem) {\n        this.resolvedColumn = resolvedDeclareItem;\n    }\n\n    public SQLDataType computeDataType() {\n        SQLColumnDefinition resolvedColumn = getResolvedColumn();\n        if (resolvedColumn != null) {\n            return resolvedColumn.getDataType();\n        }\n\n        if (this.resolvedColumn instanceof SQLSelectItem) {\n            if (((SQLSelectItem) this.resolvedColumn).getExpr() != this) {\n                return ((SQLSelectItem) this.resolvedColumn).computeDataType();\n            }\n            return null;\n        }\n\n        SQLSelectQueryBlock queryBlock = null;\n        if (resolvedOwnerObject instanceof SQLSubqueryTableSource) {\n            SQLSelect select = ((SQLSubqueryTableSource) resolvedOwnerObject).getSelect();\n            queryBlock = select.getFirstQueryBlock();\n        } else if (resolvedOwnerObject instanceof SQLUnionQueryTableSource) {\n            SQLUnionQuery union = ((SQLUnionQueryTableSource) resolvedOwnerObject).getUnion();\n            queryBlock = union.getFirstQueryBlock();\n        } else if (resolvedOwnerObject instanceof SQLWithSubqueryClause.Entry) {\n            queryBlock = ((SQLWithSubqueryClause.Entry) resolvedOwnerObject)\n                    .getSubQuery()\n                    .getFirstQueryBlock();\n        }\n\n        if (queryBlock != null) {\n            SQLSelectItem selectItem = queryBlock.findSelectItem(nameHashCode64());\n            if (selectItem != null) {\n                return selectItem.computeDataType();\n            }\n        }\n\n        for (SQLObject parent = this.parent; parent != null; parent = parent.getParent()) {\n            if (parent instanceof SQLCreateFunctionStatement) {\n                SQLCreateFunctionStatement createFunction = (SQLCreateFunctionStatement) parent;\n                SQLParameter parameter = createFunction.getParameter(this.name);\n                return parameter != null ? parameter.computeDataType() : null;\n            }\n        }\n\n        return null;\n    }\n\n    public boolean nameEquals(String name) {\n        return SQLUtils.nameEquals(this.name, name);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    public static boolean matchIgnoreCase(SQLExpr expr, String name) {\n        if (!(expr instanceof SQLIdentifierExpr)) {\n            return false;\n        }\n        SQLIdentifierExpr ident = (SQLIdentifierExpr) expr;\n        return ident.getName().equalsIgnoreCase(name);\n    }\n\n    @Override\n    public int compareTo(SQLIdentifierExpr o) {\n        return this.normalizedName()\n                .compareTo(\n                        o.normalizedName());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInListExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLInListExpr extends SQLExprImpl implements SQLReplaceable, Serializable {\n    private static final long serialVersionUID = 1L;\n    private boolean not;\n    private SQLExpr expr;\n    private List<SQLExpr> targetList = new ArrayList<SQLExpr>();\n\n    //for ads query hint\n    protected SQLCommentHint hint;\n\n    public SQLInListExpr() {\n    }\n\n    public SQLInListExpr(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public SQLInListExpr(String expr, String... values) {\n        this.setExpr(\n                SQLUtils.toSQLExpr(expr));\n\n        for (String value : values) {\n            targetList.add(new SQLCharExpr(value));\n        }\n    }\n\n    public SQLInListExpr(SQLExpr expr, boolean not) {\n        this.setExpr(expr);\n        this.not = not;\n    }\n\n    public SQLInListExpr clone() {\n        SQLInListExpr x = new SQLInListExpr();\n        x.not = not;\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        for (SQLExpr e : targetList) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.targetList.add(e2);\n        }\n        return x;\n    }\n\n    public boolean isNot() {\n        return this.not;\n    }\n\n    public void setNot(boolean not) {\n        this.not = not;\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n\n        this.expr = expr;\n    }\n\n    public void addTarget(SQLExpr x) {\n        x.setParent(this);\n        targetList.add(x);\n    }\n\n    public void addTarget(int index, SQLExpr x) {\n        x.setParent(this);\n        targetList.add(index, x);\n    }\n\n    public List<SQLExpr> getTargetList() {\n        return this.targetList;\n    }\n\n    public boolean sortTargetList() {\n        if (targetList.size() < 2) {\n            return true;\n        }\n\n        Class<?> firstClass = targetList.get(0).getClass();\n        for (int i = 1; i < targetList.size(); i++) {\n            if (targetList.get(i).getClass() != firstClass) {\n                return false;\n            }\n        }\n\n        if (!Comparable.class.isAssignableFrom(firstClass)) {\n            return false;\n        }\n\n        Collections.sort((List) targetList);\n        return true;\n    }\n\n    public void setTargetList(List<SQLExpr> targetList) {\n        this.targetList = targetList;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (expr != null) {\n                expr.accept(visitor);\n            }\n\n            if (targetList != null) {\n                for (SQLExpr item : targetList) {\n                    if (item != null) {\n                        item.accept(visitor);\n                    }\n                }\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (this.expr != null) {\n            children.add(this.expr);\n        }\n        children.addAll(this.targetList);\n        return children;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        result = prime * result + (not ? 1231 : 1237);\n        result = prime * result + ((targetList == null) ? 0 : targetList.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLInListExpr other = (SQLInListExpr) obj;\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        if (not != other.not) {\n            return false;\n        }\n        if (targetList == null) {\n            if (other.targetList != null) {\n                return false;\n            }\n        } else if (!targetList.equals(other.targetList)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLDataType computeDataType() {\n        return SQLBooleanExpr.DATA_TYPE;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        for (int i = targetList.size() - 1; i >= 0; i--) {\n            if (targetList.get(i) == expr) {\n                if (target == null) {\n                    targetList.remove(i);\n                } else {\n                    targetList.set(i, target);\n                    target.setParent(this);\n                }\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public SQLCommentHint getHint() {\n        return hint;\n    }\n\n    public void setHint(SQLCommentHint hint) {\n        this.hint = hint;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLInSubQueryExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class SQLInSubQueryExpr extends SQLExprImpl implements Serializable, SQLReplaceable {\n    private static final long serialVersionUID = 1L;\n    private boolean not;\n    private SQLExpr expr;\n\n    public SQLSelect subQuery;\n\n    // for ads query hint\n    public SQLCommentHint hint;\n\n    // for clickhouse\n    private boolean global;\n\n    public SQLInSubQueryExpr() {\n    }\n\n    public SQLInSubQueryExpr(SQLSelect select) {\n        setSubQuery(select);\n    }\n\n    public SQLInSubQueryExpr(SQLExpr expr, SQLSelectQueryBlock queryBlock) {\n        setExpr(expr);\n        setSubQuery(new SQLSelect(queryBlock));\n    }\n\n    public SQLInSubQueryExpr clone() {\n        SQLInSubQueryExpr x = new SQLInSubQueryExpr();\n        x.not = not;\n        x.global = global;\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n        return x;\n    }\n\n    public boolean isNot() {\n        return not;\n    }\n\n    public void setNot(boolean not) {\n        this.not = not;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public SQLSelect getSubQuery() {\n        return this.subQuery;\n    }\n\n    public void setSubQuery(SQLSelect x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.subQuery = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.expr != null) {\n                this.expr.accept(visitor);\n            }\n\n            if (this.subQuery != null) {\n                this.subQuery.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Arrays.<SQLObject>asList(this.expr, this.subQuery);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        result = prime * result + (not ? 1231 : 1237);\n        result = prime * result + (global ? 1231 : 1237);\n        result = prime * result + ((subQuery == null) ? 0 : subQuery.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLInSubQueryExpr other = (SQLInSubQueryExpr) obj;\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        if (not != other.not) {\n            return false;\n        }\n        if (global != other.global) {\n            return false;\n        }\n        if (subQuery == null) {\n            if (other.subQuery != null) {\n                return false;\n            }\n        } else if (!subQuery.equals(other.subQuery)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLDataType computeDataType() {\n        return SQLBooleanExpr.DATA_TYPE;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n\n    public SQLCommentHint getHint() {\n        return hint;\n    }\n\n    public void setHint(SQLCommentHint hint) {\n        this.hint = hint;\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntegerExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.FastsqlException;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\n\npublic class SQLIntegerExpr extends SQLNumericLiteralExpr implements Comparable<SQLIntegerExpr> {\n    public static final SQLDataType DATA_TYPE = new SQLDataTypeImpl(\"bigint\");\n\n    private Number number;\n    private String type;\n\n    public SQLIntegerExpr(Number number) {\n        this();\n        this.number = number;\n    }\n\n    public SQLIntegerExpr(Number number, SQLObject parent) {\n        this();\n        this.number = number;\n        this.parent = parent;\n    }\n\n    public SQLIntegerExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.INT));\n    }\n\n    public Number getNumber() {\n        return this.number;\n    }\n\n    public void setNumber(Number number) {\n        this.number = number;\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(this.number.toString());\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((number == null) ? 0 : number.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLIntegerExpr other = (SQLIntegerExpr) obj;\n        if (number == null) {\n            if (other.number != null) {\n                return false;\n            }\n        } else if (!number.equals(other.number)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public Object getValue() {\n        return this.number;\n    }\n\n    public SQLIntegerExpr clone() {\n        return new SQLIntegerExpr(this.number);\n    }\n\n    public SQLDataType computeDataType() {\n        return DATA_TYPE;\n    }\n\n    public void decrement() {\n        if (number instanceof Integer) {\n            number = Integer.valueOf((Integer) number.intValue() - 1);\n        } else if (number instanceof Long) {\n            number = Long.valueOf((Long) number.longValue() - 1);\n        } else {\n            throw new FastsqlException(\"decrement not support.\");\n        }\n    }\n\n    public static boolean isZero(SQLExpr expr) {\n        if (expr instanceof SQLIntegerExpr) {\n            Number number = ((SQLIntegerExpr) expr).getNumber();\n            return number != null && number.intValue() == 0;\n        }\n        return false;\n    }\n\n    public static SQLIntegerExpr substract(SQLIntegerExpr a, SQLIntegerExpr b) {\n        int val = a.number.intValue() - b.number.intValue();\n        return new SQLIntegerExpr(val);\n    }\n\n    public static SQLIntegerExpr least(SQLIntegerExpr a, SQLIntegerExpr b) {\n        if (a == null) {\n            return b;\n        }\n\n        if (a.number.intValue() <= b.number.intValue()) {\n            return a;\n        }\n\n        return b;\n    }\n\n    public static SQLIntegerExpr greatst(SQLIntegerExpr a, SQLIntegerExpr b) {\n        if (a.number.intValue() >= b.number.intValue()) {\n            return a;\n        }\n\n        return b;\n    }\n\n    public static SQLIntegerExpr ofIntOrLong(long value) {\n        if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {\n            return new SQLIntegerExpr((int) value);\n        }\n\n        return new SQLIntegerExpr(value);\n    }\n\n    public static SQLIntegerExpr add(long a, long b) {\n        long r = a + b;\n\n        if (a > 0 && b > 0 && r <= 0) {\n            return new SQLIntegerExpr(BigInteger.valueOf(a).add(BigInteger.valueOf(b)));\n        }\n\n        return new SQLIntegerExpr(r);\n    }\n\n    @Override\n    public int compareTo(SQLIntegerExpr o) {\n        if (this.number instanceof Integer && o.number instanceof Integer) {\n            return ((Integer) this.number).compareTo((Integer) o.number);\n        }\n\n        if (this.number instanceof Long && o.number instanceof Long) {\n            return ((Long) this.number).compareTo((Long) o.number);\n        }\n\n        if (this.number instanceof BigDecimal && o.number instanceof BigDecimal) {\n            return ((BigDecimal) this.number).compareTo((BigDecimal) o.number);\n        }\n\n        if (this.number instanceof Float && o.number instanceof Float) {\n            return ((Float) this.number).compareTo((Float) o.number);\n        }\n\n        if (this.number instanceof Double && o.number instanceof Double) {\n            return ((Double) this.number).compareTo((Double) o.number);\n        }\n\n        return -1;\n    }\n\n    public SQLIntegerExpr negative() {\n        Number number = this.number;\n        if (number instanceof Integer) {\n            number = -number.intValue();\n        } else if (number instanceof Long) {\n            number = -number.longValue();\n        } else if (number instanceof BigInteger) {\n            number = ((BigInteger) number).negate();\n        } else {\n            throw new UnsupportedOperationException();\n        }\n        return new SQLIntegerExpr(number);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntervalExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLIntervalExpr extends SQLExprImpl implements SQLReplaceable {\n    public static final SQLDataType DATA_TYPE = new SQLDataTypeImpl(\"interval\");\n\n    private SQLExpr value;\n    private SQLIntervalUnit unit;\n\n    public SQLIntervalExpr() {\n    }\n\n    public SQLIntervalExpr(SQLExpr value, SQLIntervalUnit unit) {\n        setValue(value);\n        this.unit = unit;\n    }\n\n    public SQLIntervalExpr clone() {\n        SQLIntervalExpr x = new SQLIntervalExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        x.unit = unit;\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n        return false;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.value = x;\n    }\n\n    public SQLIntervalUnit getUnit() {\n        return unit;\n    }\n\n    public void setUnit(SQLIntervalUnit unit) {\n        this.unit = unit;\n    }\n\n    @Override\n    public void output(StringBuilder buf) {\n        buf.append(\"INTERVAL \");\n        value.output(buf);\n        if (unit != null) {\n            buf.append(' ');\n            buf.append(unit.name());\n        }\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.value != null) {\n                this.value.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((unit == null) ? 0 : unit.hashCode());\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLIntervalExpr other = (SQLIntervalExpr) obj;\n        if (unit != other.unit) {\n            return false;\n        }\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLDataType computeDataType() {\n        return DATA_TYPE;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntervalUnit.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport java.util.Calendar;\n\npublic enum SQLIntervalUnit {\n    YEAR,\n    YEAR_MONTH,\n    QUARTER,\n    MONTH,\n    WEEK,\n    DAY,\n    DAY_HOUR,\n    DAY_MINUTE,\n    DAY_SECOND,\n    DAY_MICROSECOND,\n    HOUR,\n    HOUR_MINUTE,\n    HOUR_SECOND,\n    HOUR_MICROSECOND,\n    MINUTE,\n    MINUTE_SECOND,\n    MINUTE_MICROSECOND,\n    SECOND,\n    SECOND_MICROSECOND,\n    MICROSECOND,\n    MILLISECOND,\n    DAY_OF_WEEK,\n    DOW,\n    DAY_OF_MONTH,\n    DAY_OF_YEAR,\n    YEAR_OF_WEEK,\n    YOW,\n    TIMEZONE_HOUR,\n    TIMEZONE_MINUTE,\n    DOY,\n    YEAR_TO_MONTH(\"YEAR TO MONTH\");\n\n    public final String name;\n    public final String nameLCase;\n\n    SQLIntervalUnit(String name) {\n        this.name = name;\n        this.nameLCase = name.toLowerCase();\n    }\n\n    SQLIntervalUnit() {\n        this.name = name();\n        this.nameLCase = name.toLowerCase();\n    }\n\n    public static boolean add(Calendar calendar, int intervalInt, SQLIntervalUnit unit) {\n        switch (unit) {\n            case YEAR:\n                calendar.add(Calendar.YEAR, intervalInt);\n                return true;\n            case MONTH:\n                calendar.add(Calendar.MONTH, intervalInt);\n                return true;\n            case WEEK:\n                calendar.add(Calendar.WEEK_OF_MONTH, intervalInt);\n                return true;\n            case DAY:\n                calendar.add(Calendar.DAY_OF_MONTH, intervalInt);\n                return true;\n            case HOUR:\n                calendar.add(Calendar.HOUR_OF_DAY, intervalInt);\n                return true;\n            case MINUTE:\n                calendar.add(Calendar.MINUTE, intervalInt);\n                return true;\n            case SECOND:\n                calendar.add(Calendar.SECOND, intervalInt);\n                return true;\n            case MICROSECOND:\n                calendar.add(Calendar.MILLISECOND, intervalInt);\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public boolean isDateTime() {\n        switch (this) {\n            case HOUR:\n            case MINUTE:\n            case SECOND:\n            case MICROSECOND:\n            case MILLISECOND:\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public static SQLIntervalUnit of(String str) {\n        if (str == null || str.isEmpty()) {\n            return null;\n        }\n\n        str = str.toUpperCase();\n        switch (str) {\n            case \"YEARS\":\n                return YEAR;\n            case \"MONTHS\":\n                return MONTH;\n            case \"WEEKS\":\n                return WEEK;\n            case \"DAYS\":\n                return DAY;\n            case \"HOURS\":\n                return HOUR;\n            case \"MINUTES\":\n                return MINUTE;\n            case \"SECONDS\":\n                return SECOND;\n            case \"MILLISECONDS\":\n                return MILLISECOND;\n            case \"MICROSECOND\":\n                return MICROSECOND;\n            default:\n                break;\n        }\n\n        for (SQLIntervalUnit value : values()) {\n            if (value.name().equals(str)) {\n                return value;\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLJSONExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLJSONExpr extends SQLTypeExpr {\n    public SQLJSONExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.JSON));\n    }\n\n    public SQLJSONExpr(String value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLJSONExpr clone() {\n        SQLJSONExpr x = new SQLJSONExpr(getValue());\n        return x;\n    }\n\n    public String getValue() {\n        return (String) value;\n    }\n\n    public void setValue(String literal) {\n        this.value = literal;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLJSONExpr that = (SQLJSONExpr) o;\n\n        return value != null ? value.equals(that.value) : that.value == null;\n    }\n\n    @Override\n    public int hashCode() {\n        return value != null ? value.hashCode() : 0;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, (DbType) null);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLListExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLListExpr extends SQLExprImpl implements SQLReplaceable {\n    private final List<SQLExpr> items;\n\n    public SQLListExpr() {\n        items = new ArrayList<SQLExpr>();\n    }\n\n    public SQLListExpr(SQLExpr... items) {\n        this.items = new ArrayList<SQLExpr>(items.length);\n        for (SQLExpr item : items) {\n            item.setParent(this);\n            this.items.add(item);\n        }\n    }\n\n    public SQLListExpr(List<SQLExpr> items) {\n        this.items = new ArrayList<>(items.size());\n        for (SQLExpr item : items) {\n            item.setParent(this);\n            this.items.add(item);\n        }\n    }\n\n    public List<SQLExpr> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLExpr item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < items.size(); i++) {\n                SQLExpr item = items.get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + items.hashCode();\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLListExpr other = (SQLListExpr) obj;\n        if (!items.equals(other.items)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLListExpr clone() {\n        SQLListExpr x = new SQLListExpr();\n        for (SQLExpr item : items) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n        return x;\n    }\n\n    public List getChildren() {\n        return this.items;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < items.size(); i++) {\n            if (items.get(i) == expr) {\n                target.setParent(this);\n                items.set(i, target);\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLLiteralExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\n\npublic interface SQLLiteralExpr extends SQLExpr {\n    SQLLiteralExpr clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMatchAgainstExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLMatchAgainstExpr extends SQLExprImpl implements SQLReplaceable {\n    private List<SQLExpr> columns = new ArrayList<SQLExpr>();\n    private SQLExpr against;\n    private SearchModifier searchModifier;\n\n    public SQLMatchAgainstExpr() {\n    }\n\n    public SQLMatchAgainstExpr clone() {\n        SQLMatchAgainstExpr x = new SQLMatchAgainstExpr();\n        for (SQLExpr column : columns) {\n            SQLExpr column2 = column.clone();\n            column2.setParent(x);\n            x.columns.add(column2);\n        }\n        if (against != null) {\n            x.setAgainst(against.clone());\n        }\n        x.searchModifier = searchModifier;\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.against == expr) {\n            setAgainst(target);\n            return true;\n        }\n\n        for (int i = 0; i < columns.size(); i++) {\n            if (columns.get(i) == expr) {\n                target.setParent(this);\n                columns.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void setColumns(List<SQLExpr> columns) {\n        this.columns = columns;\n    }\n\n    public SQLExpr getAgainst() {\n        return against;\n    }\n\n    public void setAgainst(SQLExpr against) {\n        if (against != null) {\n            against.setParent(this);\n        }\n        this.against = against;\n    }\n\n    public SearchModifier getSearchModifier() {\n        return searchModifier;\n    }\n\n    public void setSearchModifier(SearchModifier searchModifier) {\n        this.searchModifier = searchModifier;\n    }\n\n    public static enum SearchModifier {\n        IN_BOOLEAN_MODE(\"IN BOOLEAN MODE\"),\n        IN_NATURAL_LANGUAGE_MODE(\"IN NATURAL LANGUAGE MODE\"),\n        IN_NATURAL_LANGUAGE_MODE_WITH_QUERY_EXPANSION(\"IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION\"),\n        WITH_QUERY_EXPANSION(\"WITH QUERY EXPANSION\");\n\n        public final String name;\n        public final String nameLCase;\n\n        SearchModifier() {\n            this(null);\n        }\n\n        SearchModifier(String name) {\n            this.name = name;\n            this.nameLCase = name == null ? null : name.toLowerCase();\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            if (columns != null) {\n                for (SQLExpr column : this.columns) {\n                    if (column != null) {\n                        column.accept(v);\n                    }\n                }\n            }\n\n            if (this.against != null) {\n                against.accept(v);\n            }\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.addAll(this.columns);\n        children.add(this.against);\n        return children;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((against == null) ? 0 : against.hashCode());\n        result = prime * result + ((columns == null) ? 0 : columns.hashCode());\n        result = prime * result + ((searchModifier == null) ? 0 : searchModifier.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLMatchAgainstExpr other = (SQLMatchAgainstExpr) obj;\n        if (against == null) {\n            if (other.against != null) {\n                return false;\n            }\n        } else if (!against.equals(other.against)) {\n            return false;\n        }\n        if (columns == null) {\n            if (other.columns != null) {\n                return false;\n            }\n        } else if (!columns.equals(other.columns)) {\n            return false;\n        }\n        if (searchModifier != other.searchModifier) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, Serializable {\n    private static final long serialVersionUID = 1L;\n    private boolean removeBrackets;\n\n    protected final List<SQLExpr> arguments = new ArrayList<SQLExpr>();\n    protected String methodName;\n    protected long methodNameHashCode64;\n    protected long hashCode64;\n    protected SQLExpr owner;\n    protected SQLExpr from;\n    protected SQLExpr using;\n    protected SQLExpr hasFor;\n    protected String trimOption;\n    protected transient SQLDataType resolvedReturnDataType;\n\n    public SQLMethodInvokeExpr() {\n        this.removeBrackets = false;\n    }\n\n    public SQLMethodInvokeExpr(String methodName) {\n        this.methodName = methodName;\n        this.removeBrackets = false;\n    }\n\n    public SQLMethodInvokeExpr(SQLIdentifierExpr methodName) {\n        this.methodName = methodName.name;\n        this.methodNameHashCode64 = methodName.hashCode64;\n        this.setSource(methodName.getSourceLine(), methodName.getSourceColumn());\n        this.removeBrackets = false;\n    }\n\n    public SQLMethodInvokeExpr(String methodName, long methodNameHashCode64) {\n        this.methodName = methodName;\n        this.methodNameHashCode64 = methodNameHashCode64;\n        this.removeBrackets = false;\n    }\n\n    public SQLMethodInvokeExpr(String methodName, SQLExpr owner) {\n        this.methodName = methodName;\n        setOwner(owner);\n        this.removeBrackets = false;\n    }\n\n    public SQLMethodInvokeExpr(String methodName, SQLExpr owner, SQLExpr... params) {\n        this.methodName = methodName;\n        setOwner(owner);\n        for (SQLExpr param : params) {\n            this.addArgument(param);\n        }\n        this.removeBrackets = false;\n    }\n\n    public SQLMethodInvokeExpr(String methodName, SQLExpr owner, List<SQLExpr> params) {\n        this.methodName = methodName;\n        setOwner(owner);\n        for (SQLExpr param : params) {\n            this.addArgument(param);\n        }\n        this.removeBrackets = false;\n    }\n\n    public long methodNameHashCode64() {\n        if (methodNameHashCode64 == 0\n                && methodName != null) {\n            methodNameHashCode64 = FnvHash.hashCode64(methodName);\n        }\n        return methodNameHashCode64;\n    }\n\n    public long hashCode64() {\n        if (hashCode64 == 0) {\n            computeHashCode64();\n        }\n\n        return hashCode64;\n    }\n\n    protected void computeHashCode64() {\n        long hash;\n        if (owner instanceof SQLName) {\n            hash = ((SQLName) owner).hashCode64();\n\n            hash ^= '.';\n            hash *= FnvHash.PRIME;\n        } else if (owner == null) {\n            hash = FnvHash.BASIC;\n        } else {\n            hash = FnvHash.fnv1a_64_lower(owner.toString());\n\n            hash ^= '.';\n            hash *= FnvHash.PRIME;\n        }\n        hash = FnvHash.hashCode64(hash, methodName);\n        hashCode64 = hash;\n    }\n\n    public String getMethodName() {\n        return this.methodName;\n    }\n\n    public void setMethodName(String methodName) {\n        this.methodName = methodName;\n        this.methodNameHashCode64 = 0L;\n    }\n\n    /**\n     * instead of getArguments\n     *\n     * @deprecated\n     */\n    public List<SQLExpr> getParameters() {\n        return this.arguments;\n    }\n\n    public List<SQLExpr> getArguments() {\n        return this.arguments;\n    }\n\n    public void setArgument(int i, SQLExpr arg) {\n        if (arg != null) {\n            arg.setParent(this);\n        }\n        this.arguments.set(i, arg);\n    }\n\n    public SQLExpr getArgument(int i) {\n        if (i >= 0 && i < this.arguments.size()) {\n            return this.arguments.get(i);\n        }\n        return null;\n    }\n\n    /**\n     * deprecated, instead of addArgument\n     *\n     * @deprecated\n     */\n    public void addParameter(SQLExpr param) {\n        if (param != null) {\n            param.setParent(this);\n        }\n        this.arguments.add(param);\n    }\n\n    public void addArgument(SQLExpr arg) {\n        if (arg != null) {\n            arg.setParent(this);\n        }\n        this.arguments.add(arg);\n    }\n\n    public void addArguments(List<SQLExpr> args) {\n        for (SQLExpr arg : args) {\n            addArgument(arg);\n        }\n    }\n\n    public SQLExpr getOwner() {\n        return this.owner;\n    }\n\n    public void setOwner(SQLExpr owner) {\n        if (owner != null) {\n            owner.setParent(this);\n        }\n        this.owner = owner;\n    }\n\n    public SQLExpr getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.from = x;\n    }\n\n    public void output(StringBuilder buf) {\n        if (this.owner != null) {\n            this.owner.output(buf);\n            buf.append(\".\");\n        }\n\n        if (this.content != null) {\n            this.content.output(buf);\n            buf.append(' ');\n        }\n        buf.append(this.methodName);\n        buf.append(\"(\");\n        for (int i = 0, size = this.arguments.size(); i < size; ++i) {\n            if (i != 0) {\n                buf.append(\", \");\n            }\n\n            this.arguments.get(i).output(buf);\n        }\n        if (this.as != null) {\n            buf.append(' ');\n            this.as.output(buf);\n        }\n        buf.append(\")\");\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.content != null) {\n                acceptChild(visitor, this.content);\n            }\n            if (this.owner != null) {\n                this.owner.accept(visitor);\n            }\n\n            for (SQLExpr arg : this.arguments) {\n                if (arg != null) {\n                    arg.accept(visitor);\n                }\n            }\n\n            if (this.from != null) {\n                this.from.accept(visitor);\n            }\n\n            if (this.using != null) {\n                this.using.accept(visitor);\n            }\n\n            if (this.hasFor != null) {\n                this.hasFor.accept(visitor);\n            }\n            if (this.as != null) {\n                acceptChild(visitor, this.as);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public List getChildren() {\n        if (this.owner == null) {\n            return this.arguments;\n        }\n\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.add(owner);\n        children.addAll(this.arguments);\n        return children;\n    }\n\n    protected void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.content != null) {\n                acceptChild(visitor, this.content);\n            }\n            if (this.owner != null) {\n                this.owner.accept(visitor);\n            }\n\n            for (SQLExpr arg : this.arguments) {\n                if (arg != null) {\n                    arg.accept(visitor);\n                }\n            }\n\n            if (this.from != null) {\n                this.from.accept(visitor);\n            }\n\n            if (this.using != null) {\n                this.using.accept(visitor);\n            }\n\n            if (this.hasFor != null) {\n                this.hasFor.accept(visitor);\n            }\n            if (this.as != null) {\n                acceptChild(visitor, this.as);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLMethodInvokeExpr that = (SQLMethodInvokeExpr) o;\n\n        if (methodNameHashCode64() != that.methodNameHashCode64()) {\n            return false;\n        }\n        if (owner != null ? !owner.equals(that.owner) : that.owner != null) {\n            return false;\n        }\n        if (content != null ? !content.equals(that.content) : that.content != null) {\n            return false;\n        }\n        if (as != null ? !as.equals(that.as) : that.as != null) {\n            return false;\n        }\n        if (!arguments.equals(that.arguments)) {\n            return false;\n        }\n        return from != null ? from.equals(that.from) : that.from == null;\n\n    }\n\n    @Override\n    public int hashCode() {\n        int result = (int) (methodNameHashCode64() ^ (methodNameHashCode64() >>> 32));\n        result = 31 * result + (owner != null ? owner.hashCode() : 0);\n        result = 31 * result + arguments.hashCode();\n        result = 31 * result + (from != null ? from.hashCode() : 0);\n        return result;\n    }\n\n    public SQLMethodInvokeExpr clone() {\n        SQLMethodInvokeExpr x = new SQLMethodInvokeExpr();\n        cloneTo(x);\n        return x;\n    }\n\n    public void cloneTo(SQLMethodInvokeExpr x) {\n        super.cloneTo(x);\n        x.methodName = methodName;\n\n        if (owner != null) {\n            x.setOwner(owner.clone());\n        }\n\n        if (content != null) {\n            x.setContent(content);\n        }\n        for (SQLExpr arg : arguments) {\n            x.addArgument(arg.clone());\n        }\n\n        if (from != null) {\n            x.setFrom(from.clone());\n        }\n\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n\n        if (trimOption != null) {\n            x.setTrimOption(trimOption);\n        }\n\n        if (attributes != null) {\n            for (Map.Entry<String, Object> entry : attributes.entrySet()) {\n                String key = entry.getKey();\n                Object value = entry.getValue();\n                if (value instanceof SQLObject) {\n                    value = ((SQLObject) value).clone();\n                }\n                x.putAttribute(key, value);\n            }\n        }\n        x.setRemoveBrackets(removeBrackets);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (target == null) {\n            return false;\n        }\n\n        for (int i = 0; i < arguments.size(); ++i) {\n            if (arguments.get(i) == expr) {\n                arguments.set(i, target);\n                target.setParent(this);\n                return true;\n            }\n        }\n\n        if (from == expr) {\n            setFrom(target);\n            return true;\n        }\n\n        if (using == expr) {\n            setUsing(target);\n            return true;\n        }\n\n        if (hasFor == expr) {\n            setFor(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean match(String owner, String function) {\n        if (function == null) {\n            return false;\n        }\n\n        if (!SQLUtils.nameEquals(function, methodName)) {\n            return false;\n        }\n\n        if (owner == null && this.owner == null) {\n            return true;\n        }\n\n        if (owner == null || this.owner == null) {\n            return false;\n        }\n\n        if (this.owner instanceof SQLIdentifierExpr) {\n            return SQLUtils.nameEquals(((SQLIdentifierExpr) this.owner).name, owner);\n        }\n\n        return false;\n    }\n\n    public SQLDataType computeDataType() {\n        if (resolvedReturnDataType != null) {\n            return resolvedReturnDataType;\n        }\n\n        long nameHash = this.methodNameHashCode64();\n        if (nameHash == FnvHash.Constants.TO_DATE\n                || nameHash == FnvHash.Constants.ADD_MONTHS\n        ) {\n            return resolvedReturnDataType = SQLDateExpr.DATA_TYPE;\n        }\n        if (nameHash == FnvHash.Constants.DATE_PARSE) {\n            return resolvedReturnDataType = SQLTimestampExpr.DATA_TYPE;\n        }\n        if (nameHash == FnvHash.Constants.CURRENT_TIME\n                || nameHash == FnvHash.Constants.CURTIME) {\n            return resolvedReturnDataType = SQLTimeExpr.DATA_TYPE;\n        }\n\n        if (nameHash == FnvHash.Constants.BIT_COUNT\n                || nameHash == FnvHash.Constants.ROW_NUMBER) {\n            return resolvedReturnDataType = new SQLDataTypeImpl(\"BIGINT\");\n        }\n\n        if (arguments.size() == 1) {\n            if (nameHash == FnvHash.Constants.TRUNC) {\n                return resolvedReturnDataType = arguments.get(0).computeDataType();\n            }\n        } else if (arguments.size() == 2) {\n            SQLExpr param0 = arguments.get(0);\n            SQLExpr param1 = arguments.get(1);\n\n            if (nameHash == FnvHash.Constants.ROUND) {\n                SQLDataType dataType = param0.computeDataType();\n                if (dataType != null) {\n                    return dataType;\n                }\n            } else if (nameHash == FnvHash.Constants.NVL\n                    || nameHash == FnvHash.Constants.IFNULL\n                    || nameHash == FnvHash.Constants.ISNULL\n                    || nameHash == FnvHash.Constants.COALESCE) {\n                SQLDataType dataType = param0.computeDataType();\n                if (dataType != null) {\n                    return dataType;\n                }\n\n                return param1.computeDataType();\n            }\n\n            if (nameHash == FnvHash.Constants.MOD) {\n                return resolvedReturnDataType = SQLIntegerExpr.DATA_TYPE;\n            }\n        }\n\n//        if (nameHash == FnvHash.Constants.ROUND) {\n//            return resolvedReturnDataType = SQLDecimalExpr.DATA_TYPE;\n//        }\n\n        if (nameHash == FnvHash.Constants.STDDEV_SAMP) {\n            return resolvedReturnDataType = SQLNumberExpr.DATA_TYPE_DOUBLE;\n        }\n\n        if (nameHash == FnvHash.Constants.CONCAT\n                || nameHash == FnvHash.Constants.SUBSTR\n                || nameHash == FnvHash.Constants.SUBSTRING) {\n            return resolvedReturnDataType = SQLCharExpr.DATA_TYPE;\n        }\n\n        if (nameHash == FnvHash.Constants.YEAR\n                || nameHash == FnvHash.Constants.MONTH\n                || nameHash == FnvHash.Constants.DAY\n                || nameHash == FnvHash.Constants.HOUR\n                || nameHash == FnvHash.Constants.MINUTE\n                || nameHash == FnvHash.Constants.SECOND\n                || nameHash == FnvHash.Constants.PERIOD_ADD\n                || nameHash == FnvHash.Constants.PERIOD_DIFF\n        ) {\n            return resolvedReturnDataType = new SQLDataTypeImpl(\"INT\");\n        }\n\n        if (nameHash == FnvHash.Constants.GROUPING) {\n            return resolvedReturnDataType = new SQLDataTypeImpl(\"INT\");\n        }\n\n        if (nameHash == FnvHash.Constants.JSON_EXTRACT_SCALAR\n                || nameHash == FnvHash.Constants.FORMAT_DATETIME\n                || nameHash == FnvHash.Constants.DATE_FORMAT\n        ) {\n            return resolvedReturnDataType = SQLCharExpr.DATA_TYPE;\n        }\n\n        if (nameHash == FnvHash.Constants.DATE_ADD\n                || nameHash == FnvHash.Constants.DATE_SUB\n                || nameHash == FnvHash.Constants.DATE\n                || nameHash == FnvHash.Constants.STR_TO_DATE\n                || nameHash == FnvHash.Constants.CURRENT_DATE) {\n            return resolvedReturnDataType = SQLDateExpr.DATA_TYPE;\n        }\n\n        if (nameHash == FnvHash.Constants.UNIX_TIMESTAMP) {\n            return resolvedReturnDataType = SQLIntegerExpr.DATA_TYPE;\n        }\n\n        if (nameHash == FnvHash.Constants.TIME) {\n            return resolvedReturnDataType = new SQLDataTypeImpl(\"VARCHAR\");\n        }\n\n        if (nameHash == FnvHash.Constants.SYSDATE\n                || nameHash == FnvHash.Constants.CURRENT_TIMESTAMP\n                || nameHash == FnvHash.Constants.SYSTIMESTAMP) {\n            return resolvedReturnDataType = SQLTimestampExpr.DATA_TYPE;\n        }\n\n        return null;\n    }\n\n    public SQLExpr getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.using = x;\n    }\n\n    public SQLExpr getFor() {\n        return hasFor;\n    }\n\n    public void setFor(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.hasFor = x;\n    }\n\n    public String getTrimOption() {\n        return trimOption;\n    }\n\n    public void setTrimOption(String trimOption) {\n        this.trimOption = trimOption;\n    }\n\n    public SQLDataType getResolvedReturnDataType() {\n        return resolvedReturnDataType;\n    }\n\n    public void setResolvedReturnDataType(SQLDataType resolvedReturnDataType) {\n        this.resolvedReturnDataType = resolvedReturnDataType;\n    }\n\n    private SQLExpr as;\n    private SQLExpr content;\n\n    public SQLExpr getAs() {\n        return as;\n    }\n\n    public void setAs(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.as = x;\n     }\n\n    public SQLExpr getContent() {\n        return content;\n    }\n\n    public void setContent(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.content = x;\n    }\n\n    public boolean isRemoveBrackets() {\n        return removeBrackets;\n    }\n\n    public void setRemoveBrackets(boolean removeBrackets) {\n        this.removeBrackets = removeBrackets;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNCharExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLNCharExpr extends SQLTextLiteralExpr {\n    private static SQLDataType defaultDataType = new SQLCharacterDataType(\"nvarchar\");\n\n    public SQLNCharExpr() {\n    }\n\n    public SQLNCharExpr(String text) {\n        this.text = text;\n    }\n\n    public SQLNCharExpr(String text, SQLObject parent) {\n        this.text = text;\n        this.parent = parent;\n    }\n\n    public void output(StringBuilder buf) {\n        if ((this.text == null) || (this.text.length() == 0)) {\n            buf.append(\"NULL\");\n            return;\n        }\n\n        buf.append(\"N'\");\n        buf.append(this.text.replaceAll(\"'\", \"''\"));\n        buf.append(\"'\");\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLNCharExpr clone() {\n        return new SQLNCharExpr(text);\n    }\n\n    public SQLDataType computeDataType() {\n        return defaultDataType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNotExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLNotExpr extends SQLExprImpl implements Serializable, SQLReplaceable {\n    private static final long serialVersionUID = 1L;\n    public SQLExpr expr;\n\n    public SQLNotExpr() {\n    }\n\n    public SQLNotExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    @Override\n    public void output(StringBuilder buf) {\n        buf.append(\" NOT \");\n        this.expr.output(buf);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.expr != null) {\n                this.expr.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.singletonList(this.expr);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLNotExpr other = (SQLNotExpr) obj;\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLNotExpr clone() {\n        SQLNotExpr x = new SQLNotExpr();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        return x;\n    }\n\n    public SQLDataType computeDataType() {\n        return SQLBooleanExpr.DATA_TYPE;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNullExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE_NULL;\n\npublic final class SQLNullExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValuableExpr {\n    public SQLNullExpr() {\n    }\n\n    public SQLNullExpr(SQLObject parent) {\n        this.parent = parent;\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(\"NULL\");\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public int hashCode() {\n        return 0;\n    }\n\n    public boolean equals(Object o) {\n        return o instanceof SQLNullExpr;\n    }\n\n    @Override\n    public Object getValue() {\n        return EVAL_VALUE_NULL;\n    }\n\n    public SQLNullExpr clone() {\n        return new SQLNullExpr();\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.Utils;\n\nimport java.math.BigDecimal;\n\npublic class SQLNumberExpr extends SQLNumericLiteralExpr implements SQLValuableExpr {\n    public static final SQLDataType DATA_TYPE_NUMBER = new SQLDataTypeImpl(\"number\");\n\n    public static final SQLDataType DATA_TYPE_DOUBLE = new SQLDataTypeImpl(\"double\");\n    public static final SQLDataType DATA_TYPE_BIGINT = SQLIntegerExpr.DATA_TYPE;\n\n    private char[] chars;\n\n    public SQLNumberExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.NUMBER));\n    }\n\n    public SQLNumberExpr(Number number) {\n        this();\n        this.value = number;\n    }\n\n    public SQLNumberExpr(char[] chars, SQLObject parent) {\n        this();\n        this.chars = chars;\n        this.parent = parent;\n    }\n\n    public SQLNumberExpr(char[] chars) {\n        this();\n        this.chars = chars;\n    }\n\n    public Number getNumber() {\n        if (chars != null && value == null) {\n            boolean exp = false;\n            for (int i = 0; i < chars.length; i++) {\n                char ch = chars[i];\n                if (ch == 'e' || ch == 'E') {\n                    exp = true;\n                }\n            }\n            if (exp) {\n                this.value = Double.parseDouble(new String(chars));\n            } else {\n                this.value = new BigDecimal(chars);\n            }\n        }\n        return getValue();\n    }\n\n    public Number getValue() {\n        return (Number) value;\n    }\n\n    public void setNumber(Number number) {\n        this.value = number;\n        this.chars = null;\n    }\n\n    public void output(StringBuilder buf) {\n        if (chars != null) {\n            buf.append(chars);\n        } else {\n            buf.append(this.value.toString());\n        }\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        Number number = getNumber();\n        if (number == null) {\n            return 0;\n        }\n\n        return number.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (chars != null && value == null) {\n            this.value = new BigDecimal(chars);\n        }\n\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n\n        SQLNumberExpr other = (SQLNumberExpr) obj;\n        return Utils.equals(getNumber(), other.getNumber());\n    }\n\n    public SQLNumberExpr clone() {\n        SQLNumberExpr x = new SQLNumberExpr();\n        x.chars = chars;\n        x.value = value;\n        return x;\n    }\n\n    public SQLDataType computeDataType() {\n        return DATA_TYPE_NUMBER;\n    }\n\n    public static boolean isZero(SQLExpr x) {\n        if (x instanceof SQLNumberExpr) {\n            Number number = ((SQLNumberExpr) x).getNumber();\n            if (number instanceof Integer) {\n                return number.intValue() == 0;\n            } else if (number instanceof Long) {\n                return number.longValue() == 0L;\n            }\n        }\n\n        return false;\n    }\n\n    public static boolean isOne(SQLExpr x) {\n        if (x instanceof SQLNumberExpr) {\n            Number number = ((SQLNumberExpr) x).getNumber();\n            if (number instanceof Integer) {\n                return number.intValue() == 1;\n            } else if (number instanceof Long) {\n                return number.longValue() == 1L;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumericLiteralExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic abstract class SQLNumericLiteralExpr extends SQLTypeExpr {\n    public SQLNumericLiteralExpr(SQLDataType sqlDataType) {\n        super(sqlDataType);\n    }\n\n    public abstract Number getNumber();\n\n    public abstract void setNumber(Number number);\n\n    public abstract SQLNumericLiteralExpr clone();\n\n    @Override\n    public List getChildren() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLParametricMethodInvokeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Ver\u001b[Ision 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLParametricMethodInvokeExpr extends SQLMethodInvokeExpr {\n    private static final long serialVersionUID = 1L;\n\n    protected final List<SQLExpr> secondArguments = new ArrayList<>();\n\n    public SQLParametricMethodInvokeExpr() {\n    }\n\n    public SQLParametricMethodInvokeExpr(String methodName) {\n        super(methodName);\n    }\n\n    public SQLParametricMethodInvokeExpr(String methodName, long methodNameHashCode64) {\n        super(methodName, methodNameHashCode64);\n    }\n\n    public SQLParametricMethodInvokeExpr(String methodName, SQLExpr owner) {\n        super(methodName, owner);\n    }\n\n    public SQLParametricMethodInvokeExpr(String methodName, SQLExpr owner, SQLExpr... params) {\n        super(methodName, owner, params);\n    }\n\n    public SQLParametricMethodInvokeExpr(String methodName, SQLExpr owner, List<SQLExpr> params) {\n        super(methodName, owner, params);\n    }\n\n    @Override\n    public SQLParametricMethodInvokeExpr clone() {\n        SQLParametricMethodInvokeExpr x = new SQLParametricMethodInvokeExpr();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public void cloneTo(SQLMethodInvokeExpr x) {\n        super.cloneTo(x);\n        for (SQLExpr arg : secondArguments) {\n            ((SQLParametricMethodInvokeExpr) x).addSecondArgument(arg.clone());\n        }\n    }\n\n    public List<SQLExpr> getSecondArguments() {\n        return secondArguments;\n    }\n\n    public void addSecondArgument(SQLExpr arg) {\n        if (arg != null) {\n            arg.setParent(this);\n        }\n        this.secondArguments.add(arg);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPatternExpr.java",
    "content": "package com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPatternExpr extends SQLExprImpl {\n    private String prefix;\n    private SQLExpr expr;\n    private String suffix;\n\n    public SQLPatternExpr() {\n        this.prefix = \"{{\";\n        this.suffix = \"}}\";\n    }\n\n    public SQLPatternExpr(SQLExpr expr) {\n        this.prefix = \"{{\";\n        this.suffix = \"}}\";\n        this.expr = expr;\n    }\n\n    public String getPrefix() {\n        return prefix;\n    }\n\n    public void setPrefix(String prefix) {\n        this.prefix = prefix;\n    }\n\n    public String getSuffix() {\n        return suffix;\n    }\n\n    public void setSuffix(String suffix) {\n        this.suffix = suffix;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLPatternExpr other = (SQLPatternExpr) obj;\n        if (!prefix.equals(other.prefix)) {\n            return false;\n        }\n        if (!suffix.equals(other.suffix)) {\n            return false;\n        }\n        return expr.equals(other.expr);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode())\n                + prefix.hashCode() + suffix.hashCode();\n        return result;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLASTOutputVisitor) {\n            SQLASTOutputVisitor visitor = (SQLASTOutputVisitor) v;\n            visitor.print(prefix);\n            visitor.print(\" \");\n            expr.accept(visitor);\n            visitor.print(\" \");\n            visitor.print(suffix);\n        }\n    }\n\n    @Override\n    public SQLExpr clone() {\n        SQLPatternExpr x = new SQLPatternExpr();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.prefix = prefix;\n        x.suffix = suffix;\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\n\npublic class SQLPropertyExpr extends SQLExprImpl implements SQLName, SQLReplaceable, Comparable<SQLPropertyExpr> {\n    protected SQLExpr owner;\n    private String splitString;\n    protected String name;\n\n    protected long nameHashCod64;\n    protected long hashCode64;\n\n    protected SQLObject resolvedColumn;\n    protected SQLObject resolvedOwnerObject;\n\n    public SQLPropertyExpr(String owner2, String owner, String name) {\n        this(new SQLPropertyExpr(owner2, owner), name);\n    }\n\n    public SQLPropertyExpr(String owner, String name) {\n        this(new SQLIdentifierExpr(owner), name);\n    }\n\n    public SQLPropertyExpr(SQLExpr owner, String name) {\n        setOwner(owner);\n        this.name = name;\n    }\n\n    public SQLPropertyExpr(SQLExpr owner, String name, long nameHashCod64) {\n        setOwner(owner);\n        this.name = name;\n        this.nameHashCod64 = nameHashCod64;\n    }\n\n    public SQLPropertyExpr() {\n    }\n\n    public String getSimpleName() {\n        return name;\n    }\n\n    public SQLExpr getOwner() {\n        return this.owner;\n    }\n\n    public String getSplitString() {\n        return splitString;\n    }\n\n    public void setSplitString(String splitString) {\n        this.splitString = splitString;\n    }\n\n    @Deprecated\n    public String getOwnernName() {\n        if (owner instanceof SQLName) {\n            return ((SQLName) owner).toString();\n        }\n\n        return null;\n    }\n\n    public String getOwnerName() {\n        if (owner instanceof SQLName) {\n            return ((SQLName) owner).toString();\n        }\n\n        return null;\n    }\n\n    public void setOwner(SQLExpr owner) {\n        if (owner != null) {\n            owner.setParent(this);\n        }\n\n        if (parent instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) parent;\n            propertyExpr.computeHashCode64();\n        }\n\n        this.owner = owner;\n        this.hashCode64 = 0;\n    }\n\n    protected void computeHashCode64() {\n        long hash;\n        if (owner instanceof SQLName) {\n            hash = ((SQLName) owner).hashCode64();\n\n            hash ^= '.';\n            hash *= FnvHash.PRIME;\n        } else if (owner == null) {\n            hash = FnvHash.BASIC;\n        } else {\n            hash = FnvHash.fnv1a_64_lower(owner.toString());\n\n            hash ^= '.';\n            hash *= FnvHash.PRIME;\n        }\n        if (splitString != null) {\n            hash = FnvHash.hashCode64(hash, splitString);\n        }\n        hash = FnvHash.hashCode64(hash, name);\n        hashCode64 = hash;\n    }\n\n    public void setOwner(String owner) {\n        if (owner == null) {\n            this.owner = null;\n            return;\n        }\n\n        if (owner.indexOf('.') != -1) {\n            SQLExpr ownerExpr = SQLUtils.toSQLExpr(owner);\n            this.setOwner(ownerExpr);\n        } else {\n            this.setOwner(new SQLIdentifierExpr(owner));\n        }\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n        this.hashCode64 = 0;\n        this.nameHashCod64 = 0;\n\n        if (parent instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) parent;\n            propertyExpr.computeHashCode64();\n        }\n    }\n\n    public void output(StringBuilder buf) {\n        this.owner.output(buf);\n        buf.append(\".\");\n        buf.append(this.name);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.owner != null) {\n                this.owner.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.singletonList(this.owner);\n    }\n\n    @Override\n    public int hashCode() {\n        long hash = hashCode64();\n        return (int) (hash ^ (hash >>> 32));\n    }\n\n    public long hashCode64() {\n        if (hashCode64 == 0) {\n            computeHashCode64();\n        }\n\n        return hashCode64;\n    }\n\n    public boolean equals(SQLIdentifierExpr other) {\n        if (other == null) {\n            return false;\n        }\n\n        if (this.nameHashCode64() != other.nameHashCode64()) {\n            return false;\n        }\n\n        return resolvedOwnerObject != null\n                && resolvedOwnerObject == other.getResolvedOwnerObject()\n                && resolvedColumn != null\n                && resolvedColumn == other.getResolvedColumn();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (!(obj instanceof SQLPropertyExpr)) {\n            return false;\n        }\n\n        SQLPropertyExpr other = (SQLPropertyExpr) obj;\n        if (this.nameHashCode64() != other.nameHashCode64()) {\n            return false;\n        }\n\n        if (!Objects.equals(this.splitString, other.splitString)) {\n            return false;\n        }\n        if (owner == null) {\n            if (other.owner != null) {\n                return false;\n            }\n        } else if (!owner.equals(other.owner)) {\n            return false;\n        }\n\n        return true;\n    }\n\n    public SQLPropertyExpr clone() {\n        SQLExpr owner_x = null;\n        if (owner != null) {\n            owner_x = owner.clone();\n        }\n\n        SQLPropertyExpr x = new SQLPropertyExpr(owner_x, name, nameHashCod64);\n\n        x.hashCode64 = hashCode64;\n        x.resolvedColumn = resolvedColumn;\n        x.resolvedOwnerObject = resolvedOwnerObject;\n\n        return x;\n    }\n\n    public boolean matchOwner(String alias) {\n        if (owner instanceof SQLIdentifierExpr) {\n            return ((SQLIdentifierExpr) owner).getName().equalsIgnoreCase(alias);\n        }\n\n        return false;\n    }\n\n    public long nameHashCode64() {\n        if (nameHashCod64 == 0\n                && name != null) {\n            nameHashCod64 = FnvHash.hashCode64(name);\n        }\n        return nameHashCod64;\n    }\n\n    public String normalizedName() {\n        String ownerName;\n        if (owner instanceof SQLIdentifierExpr) {\n            ownerName = ((SQLIdentifierExpr) owner).normalizedName();\n        } else if (owner instanceof SQLPropertyExpr) {\n            ownerName = ((SQLPropertyExpr) owner).normalizedName();\n        } else {\n            ownerName = owner.toString();\n        }\n\n        return ownerName + '.' + SQLUtils.normalize(name);\n    }\n\n    public SQLColumnDefinition getResolvedColumn() {\n        if (resolvedColumn instanceof SQLColumnDefinition) {\n            return (SQLColumnDefinition) resolvedColumn;\n        }\n\n        if (resolvedColumn instanceof SQLSelectItem) {\n            SQLSelectItem selectItem = (SQLSelectItem) resolvedColumn;\n            final SQLExpr expr = selectItem.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                return ((SQLIdentifierExpr) expr).getResolvedColumn();\n            } else if (expr instanceof SQLPropertyExpr && expr != this) {\n                return ((SQLPropertyExpr) expr).getResolvedColumn();\n            }\n        }\n\n        return null;\n    }\n\n    public void setResolvedColumn(SQLColumnDefinition resolvedColumn) {\n        this.resolvedColumn = resolvedColumn;\n    }\n\n    public void setResolvedColumn(SQLSelectItem resolvedColumn) {\n        this.resolvedColumn = resolvedColumn;\n    }\n\n    public SQLTableSource getResolvedTableSource() {\n        if (resolvedOwnerObject instanceof SQLTableSource) {\n            return (SQLTableSource) resolvedOwnerObject;\n        }\n\n        return null;\n    }\n\n    public void setResolvedTableSource(SQLTableSource resolvedTableSource) {\n        this.resolvedOwnerObject = resolvedTableSource;\n    }\n\n    public void setResolvedProcedure(SQLCreateProcedureStatement stmt) {\n        this.resolvedOwnerObject = stmt;\n    }\n\n    public void setResolvedOwnerObject(SQLObject resolvedOwnerObject) {\n        this.resolvedOwnerObject = resolvedOwnerObject;\n    }\n\n    public SQLCreateProcedureStatement getResolvedProcudure() {\n        if (this.resolvedOwnerObject instanceof SQLCreateProcedureStatement) {\n            return (SQLCreateProcedureStatement) this.resolvedOwnerObject;\n        }\n\n        return null;\n    }\n\n    public SQLObject getResolvedOwnerObject() {\n        return resolvedOwnerObject;\n    }\n\n    public SQLDataType computeDataType() {\n        if (resolvedColumn instanceof SQLColumnDefinition) {\n            return ((SQLColumnDefinition) resolvedColumn).getDataType();\n        }\n\n        if (resolvedColumn instanceof SQLSelectItem) {\n            if (((SQLSelectItem) resolvedColumn).getExpr() != this) {\n                return ((SQLSelectItem) resolvedColumn).computeDataType();\n            }\n            return null;\n        }\n\n        if (resolvedOwnerObject == null) {\n            return null;\n        }\n\n        if (resolvedOwnerObject instanceof SQLSubqueryTableSource) {\n            SQLSelect select = ((SQLSubqueryTableSource) resolvedOwnerObject).getSelect();\n            SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();\n            if (queryBlock == null) {\n                return null;\n            }\n            SQLSelectItem selectItem = queryBlock.findSelectItem(nameHashCode64());\n            if (selectItem != null) {\n                return selectItem.computeDataType();\n            }\n        } else if (resolvedOwnerObject instanceof SQLUnionQueryTableSource) {\n            SQLSelectQueryBlock queryBlock = ((SQLUnionQueryTableSource) resolvedOwnerObject).getUnion().getFirstQueryBlock();\n            if (queryBlock == null) {\n                return null;\n            }\n            SQLSelectItem selectItem = queryBlock.findSelectItem(nameHashCode64());\n            if (selectItem != null) {\n                return selectItem.computeDataType();\n            }\n        } else if (resolvedOwnerObject instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) resolvedOwnerObject).getExpr();\n            if (expr instanceof SQLName) {\n                String referencedTableName = ((SQLName) expr).getSimpleName();\n\n                SQLSelect select = null;\n                for (SQLObject parent = resolvedOwnerObject.getParent(); parent != null; parent = parent.getParent()) {\n                    if (parent instanceof SQLSelect) {\n                        select = (SQLSelect) parent;\n                        break;\n                    }\n                }\n                if (select != null) {\n                    SQLWithSubqueryClause.Entry queryEntry = select.findWithSubQueryEntry(referencedTableName);\n                    if (queryEntry != null) {\n                        SQLSelectQueryBlock firstQueryBlock = queryEntry.getSubQuery().getFirstQueryBlock();\n                        if (firstQueryBlock != null) {\n                            return firstQueryBlock.findSelectItemAndComputeDataType(this.name);\n                        }\n                        // ignore\n                    }\n\n                    for (SQLObject parent = select.getParent(); parent != null; parent = parent.getParent()) {\n                        if (parent instanceof SQLSelect) {\n                            queryEntry = ((SQLSelect) parent).findWithSubQueryEntry(referencedTableName);\n                            if (queryEntry != null) {\n                                return queryEntry.getSubQuery().findSelectItemAndComputeDataType(this.name);\n                            }\n                            break;\n                        }\n                    }\n                }\n                // skip\n            }\n        }\n\n        return null;\n    }\n\n    public boolean nameEquals(String name) {\n        return SQLUtils.nameEquals(this.name, name);\n    }\n\n    public SQLPropertyExpr simplify() {\n        String normalizedName = SQLUtils.normalize(name);\n        SQLExpr normalizedOwner = this.owner;\n        if (normalizedOwner instanceof SQLIdentifierExpr) {\n            normalizedOwner = ((SQLIdentifierExpr) normalizedOwner).simplify();\n        }\n\n        if (normalizedName != name || normalizedOwner != owner) {\n            return new SQLPropertyExpr(normalizedOwner, normalizedName, hashCode64);\n        }\n\n        return this;\n    }\n\n    public String toString() {\n        if (owner == null) {\n            return this.name;\n        }\n\n        if (splitString == null) {\n            return owner.toString() + '.' + name;\n        } else {\n            return owner.toString() + splitString + name;\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == owner) {\n            setOwner(target);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public int compareTo(SQLPropertyExpr o) {\n        int r = SQLExprComparor.compareTo(owner, o.owner);\n        if (r != 0) {\n            return r;\n        }\n\n        return name.compareTo(o.name);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLQueryExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLQueryExpr extends SQLExprImpl implements Serializable {\n    private static final long serialVersionUID = 1L;\n    public SQLSelect subQuery;\n\n    public SQLQueryExpr() {\n    }\n\n    public SQLQueryExpr(SQLSelect select) {\n        setSubQuery(select);\n    }\n\n    public SQLSelect getSubQuery() {\n        return this.subQuery;\n    }\n\n    public void setSubQuery(SQLSelect subQuery) {\n        if (subQuery != null) {\n            subQuery.setParent(this);\n        }\n        this.subQuery = subQuery;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.subQuery != null) {\n                this.subQuery.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(subQuery);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((subQuery == null) ? 0 : subQuery.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLQueryExpr other = (SQLQueryExpr) obj;\n        if (subQuery == null) {\n            if (other.subQuery != null) {\n                return false;\n            }\n        } else if (!subQuery.equals(other.subQuery)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLQueryExpr clone() {\n        SQLQueryExpr x = new SQLQueryExpr();\n\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n        x.parenthesized = this.parenthesized;\n\n        return x;\n    }\n\n    public SQLDataType computeDataType() {\n        if (subQuery == null) {\n            return null;\n        }\n\n        SQLSelectQueryBlock queryBlock = subQuery.getFirstQueryBlock();\n        if (queryBlock == null) {\n            return null;\n        }\n\n        List<SQLSelectItem> selectList = queryBlock.getSelectList();\n        if (selectList.size() == 1) {\n            return selectList.get(0).computeDataType();\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLRealExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLRealExpr extends SQLNumericLiteralExpr implements SQLValuableExpr {\n    public SQLRealExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.REAL));\n    }\n\n    public SQLRealExpr(float value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLRealExpr(String value) {\n        this();\n        this.value = Float.valueOf(value);\n    }\n\n    public SQLRealExpr clone() {\n        return new SQLRealExpr(getValue());\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Number getNumber() {\n        return getValue();\n    }\n\n    public Float getValue() {\n        return (Float) value;\n    }\n\n    public void setValue(Float value) {\n        this.value = value;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public void setValue(float value) {\n        this.value = value;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLRealExpr that = (SQLRealExpr) o;\n\n        return Float.compare(that.getValue(), getValue()) == 0;\n    }\n\n    @Override\n    public int hashCode() {\n        return (getValue() != +0.0f ? Float.floatToIntBits(getValue()) : 0);\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            value = null;\n            return;\n        }\n\n        this.setValue(number.floatValue());\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSequenceExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLSequenceExpr extends SQLExprImpl implements SQLReplaceable {\n    private SQLName sequence;\n    private Function function;\n\n    public SQLSequenceExpr() {\n    }\n\n    public SQLSequenceExpr(SQLName sequence, Function function) {\n        this.sequence = sequence;\n        this.function = function;\n    }\n\n    public SQLSequenceExpr clone() {\n        SQLSequenceExpr x = new SQLSequenceExpr();\n        if (sequence != null) {\n            x.setSequence(sequence.clone());\n        }\n        x.function = function;\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.sequence != null) {\n                this.sequence.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.sequence == expr) {\n            setSequence((SQLName) target);\n            return true;\n        }\n        return false;\n    }\n\n    public static enum Function {\n        NextVal(\"NEXTVAL\"), CurrVal(\"CURRVAL\"), PrevVal(\"PREVVAL\");\n\n        public final String name;\n        public final String nameLCase;\n\n        private Function(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(sequence);\n    }\n\n    public SQLName getSequence() {\n        return sequence;\n    }\n\n    public void setSequence(SQLName sequence) {\n        this.sequence = sequence;\n    }\n\n    public Function getFunction() {\n        return function;\n    }\n\n    public void setFunction(Function function) {\n        this.function = function;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((function == null) ? 0 : function.hashCode());\n        result = prime * result + ((sequence == null) ? 0 : sequence.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLSequenceExpr other = (SQLSequenceExpr) obj;\n        if (function != other.function) {\n            return false;\n        }\n        if (sequence == null) {\n            if (other.sequence != null) {\n                return false;\n            }\n        } else if (!sequence.equals(other.sequence)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSizeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.math.BigDecimal;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLSizeExpr extends SQLExprImpl {\n    private SQLExpr value;\n    private Unit unit;\n\n    public SQLSizeExpr() {\n    }\n\n    public SQLSizeExpr(String value, char unit) {\n        this.unit = Unit.valueOf(Character.toString(unit).toUpperCase());\n        if (value.indexOf('.') == -1) {\n            this.value = new SQLIntegerExpr(Integer.parseInt(value));\n        } else {\n            this.value = new SQLNumberExpr(new BigDecimal(value));\n        }\n    }\n\n    public SQLSizeExpr(SQLExpr value, Unit unit) {\n        super();\n        this.value = value;\n        this.unit = unit;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.value != null) {\n                this.value.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    public Unit getUnit() {\n        return unit;\n    }\n\n    public void setUnit(Unit unit) {\n        this.unit = unit;\n    }\n\n    public static enum Unit {\n        B, K, M, G, T, P, E\n    }\n\n    public SQLSizeExpr clone() {\n        SQLSizeExpr x = new SQLSizeExpr();\n\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        x.unit = unit;\n\n        return x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLSizeExpr that = (SQLSizeExpr) o;\n\n        if (value != null ? !value.equals(that.value) : that.value != null) {\n            return false;\n        }\n        return unit == that.unit;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = value != null ? value.hashCode() : 0;\n        result = 31 * result + (unit != null ? unit.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSmallIntExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLSmallIntExpr extends SQLNumericLiteralExpr implements SQLValuableExpr {\n    public SQLSmallIntExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.SMALLINT));\n    }\n\n    public SQLSmallIntExpr(short value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLSmallIntExpr(String value) {\n        this();\n        if (value.startsWith(\"--\")) {\n            value = value.substring(2);\n        }\n        this.value = Short.valueOf(value);\n    }\n\n    public SQLSmallIntExpr clone() {\n        return new SQLSmallIntExpr(getValue());\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Number getNumber() {\n        return getValue();\n    }\n\n    @Override\n    public Short getValue() {\n        return (Short) value;\n    }\n\n    public void setValue(Short value) {\n        this.value = value;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLSmallIntExpr other = (SQLSmallIntExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            value = null;\n            return;\n        }\n\n        this.setValue(((Short) number));\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLSomeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic final class SQLSomeExpr extends SQLExprImpl {\n    public SQLSelect subQuery;\n\n    public SQLSomeExpr() {\n    }\n\n    public SQLSomeExpr(SQLSelect select) {\n        this.setSubQuery(select);\n    }\n\n    public SQLSomeExpr clone() {\n        SQLSomeExpr x = new SQLSomeExpr();\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n        return x;\n    }\n\n    public SQLSelect getSubQuery() {\n        return this.subQuery;\n    }\n\n    public void setSubQuery(SQLSelect subQuery) {\n        if (subQuery != null) {\n            subQuery.setParent(this);\n        }\n        this.subQuery = subQuery;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.subQuery != null) {\n                this.subQuery.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((subQuery == null) ? 0 : subQuery.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLSomeExpr other = (SQLSomeExpr) obj;\n        if (subQuery == null) {\n            if (other.subQuery != null) {\n                return false;\n            }\n        } else if (!subQuery.equals(other.subQuery)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLDataType computeDataType() {\n        if (subQuery == null) {\n            return null;\n        }\n\n        SQLSelectQueryBlock queryBlock = subQuery.getFirstQueryBlock();\n        if (queryBlock == null) {\n            return null;\n        }\n\n        List<SQLSelectItem> selectList = queryBlock.getSelectList();\n        if (selectList.size() == 1) {\n            return selectList.get(0).computeDataType();\n        }\n\n        return null;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.subQuery);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLStructExpr.java",
    "content": "package com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStructDataType;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLStructExpr extends SQLExprImpl implements SQLReplaceable {\n    private SQLStructDataType dataType;\n    private final List<SQLAliasedExpr> items = new ArrayList<>();\n\n    public SQLStructDataType getDataType() {\n        return dataType;\n    }\n\n    public void setDataType(SQLStructDataType x) {\n        x.setParent(this);\n        this.dataType = x;\n    }\n\n    public void addItem(SQLAliasedExpr item) {\n        item.setParent(this);\n        items.add(item);\n    }\n\n    public void addItem(SQLExpr item, String alias) {\n        items.add(\n                new SQLAliasedExpr(item, alias));\n    }\n\n    public List<SQLAliasedExpr> getItems() {\n        return items;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, items);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public SQLStructExpr clone() {\n        SQLStructExpr x = new SQLStructExpr();\n       cloneTo(x);\n        return x;\n    }\n\n    protected void cloneTo(SQLStructExpr x) {\n        if (this.dataType != null) {\n            x.dataType = this.dataType.clone();\n        }\n        for (SQLAliasedExpr item : items) {\n            x.addItem(item.clone());\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < items.size(); i++) {\n            if (items.get(i) == expr) {\n                target.setParent(this);\n                items.set(i, (SQLAliasedExpr) target);\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTextLiteralExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic abstract class SQLTextLiteralExpr extends SQLExprImpl implements SQLLiteralExpr {\n    protected String text;\n\n    public SQLTextLiteralExpr() {\n    }\n\n    public SQLTextLiteralExpr(String text) {\n        this.text = text;\n    }\n\n    public String getText() {\n        return this.text;\n    }\n\n    public void setText(String text) {\n        this.text = text;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((text == null) ? 0 : text.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLTextLiteralExpr other = (SQLTextLiteralExpr) obj;\n        if (text == null) {\n            if (other.text != null) {\n                return false;\n            }\n        } else if (!text.equals(other.text)) {\n            return false;\n        }\n        return true;\n    }\n\n    public abstract SQLTextLiteralExpr clone();\n\n    @Override\n    public List getChildren() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTimeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.TimeZone;\n\npublic class SQLTimeExpr extends SQLDateTypeExpr {\n    public static final SQLDataType DATA_TYPE = new SQLDataTypeImpl(SQLDataType.Constants.TIME);\n\n    private SQLExpr literal;\n\n    public SQLTimeExpr() {\n        super(DATA_TYPE);\n    }\n\n    public SQLTimeExpr(Date now, TimeZone timeZone) {\n        this();\n        setValue(now, timeZone);\n    }\n\n    public void setValue(Date x, TimeZone timeZone) {\n        if (x == null) {\n            this.value = null;\n            return;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"HH:mm:ss\");\n        if (timeZone != null) {\n            format.setTimeZone(timeZone);\n        }\n        String text = format.format(x);\n        setValue(text);\n    }\n\n    public SQLTimeExpr(String literal) {\n        this();\n        this.setValue(literal);\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.dataType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLTimeExpr clone() {\n        SQLTimeExpr x = new SQLTimeExpr();\n        x.value = this.value;\n\n        return x;\n    }\n\n    @Override\n    public String getValue() {\n        return (String) value;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    public static long supportDbTypes = DbType.of(\n            DbType.mysql,\n            DbType.oracle,\n            DbType.presto,\n            DbType.trino,\n            DbType.supersql,\n            DbType.postgresql,\n            DbType.mariadb,\n            DbType.tidb,\n            DbType.polardbx\n    );\n\n    public static boolean isSupport(DbType dbType) {\n        return (dbType.mask & supportDbTypes) != 0;\n    }\n\n    public static boolean check(String str) {\n        if (str == null || str.length() != 8) {\n            return false;\n        }\n\n        if (str.charAt(2) != ':' && str.charAt(5) != ':') {\n            return false;\n        }\n\n        char c0 = str.charAt(0);\n        char c1 = str.charAt(1);\n        char c3 = str.charAt(3);\n        char c4 = str.charAt(4);\n        char c6 = str.charAt(6);\n        char c7 = str.charAt(7);\n\n        if (c0 < '0' || c0 > '9') {\n            return false;\n        }\n        if (c1 < '0' || c1 > '9') {\n            return false;\n        }\n        if (c3 < '0' || c3 > '9') {\n            return false;\n        }\n        if (c4 < '0' || c4 > '9') {\n            return false;\n        }\n        if (c6 < '0' || c6 > '9') {\n            return false;\n        }\n        if (c7 < '0' || c7 > '9') {\n            return false;\n        }\n\n        int HH = (c0 - '0') * 10 + (c1 - '0');\n        int mm = (c3 - '0') * 10 + (c4 - '0');\n        int ss = (c6 - '0') * 10 + (c7 - '0');\n\n        if (HH > 24 || mm > 60 || ss > 60) {\n            return false;\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTimestampExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.MySqlUtils;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\n\npublic class SQLTimestampExpr extends SQLDateTypeExpr {\n    public static final SQLDataType DATA_TYPE = new SQLDataTypeImpl(SQLDataType.Constants.TIMESTAMP);\n\n    protected String literal;\n    protected String timeZone;\n    protected boolean withTimeZone;\n\n    public SQLTimestampExpr() {\n        super(DATA_TYPE);\n    }\n\n    public SQLTimestampExpr(String value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLTimestampExpr(Date date) {\n        this();\n        setValue(date);\n    }\n\n    public SQLTimestampExpr(Date date, TimeZone timeZone) {\n        this();\n        setValue(date, timeZone);\n    }\n\n    @Override\n    public String getValue() {\n        return (String) value;\n    }\n\n    public SQLTimestampExpr clone() {\n        SQLTimestampExpr x = new SQLTimestampExpr();\n        x.value = value;\n        x.timeZone = timeZone;\n        x.withTimeZone = withTimeZone;\n        return x;\n    }\n\n    public Date getDate(TimeZone timeZone) {\n        if (getValue() == null || getValue().isEmpty()) {\n            return null;\n        }\n\n        return MySqlUtils.parseDate(getValue(), timeZone);\n    }\n\n    public boolean addDay(int delta) {\n        if (getValue() == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        try {\n            Date date = format.parse(getValue());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.DAY_OF_MONTH, delta);\n            String result_chars = format.format(calendar.getTime());\n            this.setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public boolean addMonth(int delta) {\n        if (getValue() == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        try {\n            Date date = format.parse(getValue());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.MONTH, delta);\n            String result_chars = format.format(calendar.getTime());\n            this.setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public boolean addHour(int delta) {\n        if (getValue() == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        try {\n            Date date = format.parse(getValue());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.HOUR_OF_DAY, delta);\n            String result_chars = format.format(calendar.getTime());\n            this.setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public boolean addMiniute(int delta) {\n        if (getValue() == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        try {\n            Date date = format.parse(getValue());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.MINUTE, delta);\n            String result_chars = format.format(calendar.getTime());\n            this.setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public void setValue(Date x) {\n        setValue(x, null);\n    }\n\n    public void setValue(Date x, TimeZone timeZone) {\n        if (x == null) {\n            this.value = null;\n            return;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        if (timeZone != null) {\n            format.setTimeZone(timeZone);\n        }\n        this.value = format.format(x);\n    }\n\n    public String getTimeZone() {\n        return this.timeZone;\n    }\n\n    public void setTimeZone(String timeZone) {\n        this.timeZone = timeZone;\n    }\n\n    public boolean isWithTimeZone() {\n        return withTimeZone;\n    }\n\n    public void setWithTimeZone(boolean withTimeZone) {\n        this.withTimeZone = withTimeZone;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        result = prime * result + ((timeZone == null) ? 0 : timeZone.hashCode());\n        result = prime * result + (withTimeZone ? 1231 : 1237);\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLTimestampExpr other = (SQLTimestampExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        if (timeZone == null) {\n            if (other.timeZone != null) {\n                return false;\n            }\n        } else if (!timeZone.equals(other.timeZone)) {\n            return false;\n        }\n        if (withTimeZone != other.withTimeZone) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.dataType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, (DbType) null);\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.emptyList();\n    }\n\n    public static boolean check(String str) {\n        final int len;\n        if (str == null || (len = str.length()) < 14 || len > 23) {\n            return false;\n        }\n\n        final char c0 = str.charAt(0);\n        final char c1 = str.charAt(1);\n        final char c2 = str.charAt(2);\n        final char c3 = str.charAt(3);\n        final char c4 = str.charAt(4);\n        final char c5 = str.charAt(5);\n        final char c6 = str.charAt(6);\n        final char c7 = str.charAt(7);\n        final char c8 = str.charAt(8);\n        final char c9 = str.charAt(9);\n        final char c10 = str.charAt(10);\n\n        // check year\n        if (c0 < '1' | c0 > '9') {\n            return false;\n        }\n        if (c1 < '0' | c1 > '9') {\n            return false;\n        }\n        if (c2 < '0' | c2 > '9') {\n            return false;\n        }\n        if (c3 < '0' | c3 > '9') {\n            return false;\n        }\n\n        int year = (c0 - '0') * 1000 + (c1 - '0') * 100 + (c2 - '0') * 10 + (c3 - '0');\n        if (year < 1000) {\n            return false;\n        }\n\n        if (c4 != '-') {\n            return false;\n        }\n\n        final int month, day;\n        char M0 = 0, M1 = 0, d0 = 0, d1 = 0;\n        if (c8 == ' ') {\n            if (c6 != '-') {\n                return false;\n            }\n\n            M1 = c5;\n            d1 = c7;\n        } else if (c9 == ' ') {\n            if (c6 == '-') {\n                M1 = c5;\n                d0 = c7;\n                d1 = c8;\n            } else if (c7 == '-') {\n                M0 = c5;\n                M1 = c6;\n                d1 = c8;\n            } else {\n                return false;\n            }\n        } else if (c10 == ' ') {\n            if (c7 != '-') {\n                return false;\n            }\n\n            M0 = c5;\n            M1 = c6;\n            d0 = c8;\n            d1 = c9;\n        } else {\n            return false;\n        }\n\n        if (M0 == 0) {\n            if (M1 < '0' || M1 > '9') {\n                return false;\n            }\n            month = M1 - '0';\n        } else {\n            if (M0 != '0' && M0 != '1') {\n                return false;\n            }\n            if (M1 < '0' || M1 > '9') {\n                return false;\n            }\n            month = (M0 - '0') * 10 + M1 - '0';\n        }\n\n        if (d0 == 0) {\n            if (d1 < '0' || d1 > '9') {\n                return false;\n            }\n            day = d1 - '0';\n        } else {\n            if (d0 < '0' || d0 > '9') {\n                return false;\n            }\n            if (d1 < '0' || d1 > '9') {\n                return false;\n            }\n            day = (d0 - '0') * 10 + d1 - '0';\n        }\n\n        if (month < 1) {\n            return false;\n        }\n\n        if (day < 1) {\n            return false;\n        }\n\n        switch (month) {\n            case 1:\n            case 3:\n            case 5:\n            case 7:\n            case 8:\n            case 10:\n            case 12:\n                if (day > 31) {\n                    return false;\n                }\n                break;\n            case 2:\n                if (day > 29) {\n                    return false;\n                }\n                break;\n            case 4:\n            case 6:\n            case 9:\n            case 11:\n                if (day > 30) {\n                    return false;\n                }\n                break;\n            default:\n                break;\n        }\n\n        int index = len - 1;\n        if (str.charAt(index) == '0' && str.charAt(index - 1) == '.') {\n            index -= 2;\n        }\n        final char x0 = str.charAt(index--);\n        final char x1 = str.charAt(index--);\n        final char x2 = str.charAt(index--);\n        final char x3 = str.charAt(index--);\n        final char x4 = str.charAt(index--);\n        final char x5 = str.charAt(index--);\n        final char x6 = str.charAt(index--);\n        final char x7 = str.charAt(index--);\n        final char x8 = str.charAt(index--);\n        final char x9 = str.charAt(index--);\n        final char x10 = str.charAt(index--);\n        final char x11 = str.charAt(index--);\n        final char x12 = str.charAt(index--);\n\n        final char h0, h1, m0, m1, s0, s1;\n\n        if (x5 == ' ') {\n            if (x1 != ':' || x3 != ':') {\n                return false;\n            }\n            s0 = 0;\n            s1 = x0;\n            m0 = 0;\n            m1 = x2;\n            h0 = 0;\n            h1 = x4;\n        } else if (x6 == ' ') {\n            if (x1 == ':') {\n                s0 = 0;\n                s1 = x0;\n\n                if (x3 == ':') {\n                    m0 = 0;\n                    m1 = x2;\n                    h1 = x4;\n                    h0 = x5;\n                } else if (x4 == ':') {\n                    m0 = x2;\n                    m1 = x3;\n                    h0 = 0;\n                    h1 = x5;\n                } else {\n                    return false;\n                }\n            } else if (x2 == ':') {\n                s0 = x0;\n                s1 = x1;\n\n                if (x4 != ':') {\n                    return false;\n                }\n\n                m0 = 0;\n                m1 = x3;\n                h0 = 0;\n                h1 = x5;\n            } else {\n                return false;\n            }\n        } else if (x7 == ' ') {\n            if (x1 == ':') {\n                s0 = 0;\n                s1 = x0;\n\n                if (x4 != ':') {\n                    return false;\n                }\n                m1 = x2;\n                m0 = x3;\n                h1 = x5;\n                h0 = x6;\n            } else if (x2 == ':') {\n                s0 = x0;\n                s1 = x1;\n\n                if (x4 == ':') {\n                    m0 = 0;\n                    m1 = x3;\n                    h1 = x5;\n                    h0 = x6;\n                } else if (x5 == ':') {\n                    m1 = x3;\n                    m0 = x4;\n                    h0 = 0;\n                    h1 = x6;\n                } else {\n                    return false;\n                }\n            } else {\n                return false;\n            }\n        } else if (x8 == ' ') {\n            if (x2 != ':' || x5 != ':') {\n                return false;\n            }\n            s1 = x0;\n            s0 = x1;\n            m1 = x3;\n            m0 = x4;\n            h1 = x6;\n            h0 = x7;\n        } else if (x12 == ' ') {\n            if (x3 != '.' || x6 != ':' || x9 != ':') {\n                return false;\n            }\n            s1 = x4;\n            s0 = x5;\n            m1 = x7;\n            m0 = x8;\n            h1 = x10;\n            h0 = x11;\n\n            int S2 = x0;\n            int S1 = x1;\n            int S0 = x2;\n\n            if (S0 < '0' || S0 > '9') {\n                return false;\n            }\n\n            if (S1 < '0' || S1 > '9') {\n                return false;\n            }\n\n            if (S2 < '0' || S2 > '9') {\n                return false;\n            }\n        } else {\n            return false;\n        }\n\n        if (h0 == 0) {\n            if (h1 < '0' || h1 > '9') {\n                return false;\n            }\n        } else {\n            if (h0 < '0' || h0 > '2') {\n                return false;\n            }\n            if (h1 < '0' || h1 > '9') {\n                return false;\n            }\n\n            int hour = (h0 - '0') * 10 + (h1 - '0');\n            if (hour > 24) {\n                return false;\n            }\n        }\n\n        if (m0 == 0) {\n            if (m1 < '0' || m1 > '9') {\n                return false;\n            }\n        } else {\n            if (m0 < '0' || m0 > '6') {\n                return false;\n            }\n            if (m1 < '0' || m1 > '9') {\n                return false;\n            }\n\n            int minute = (m0 - '0') * 10 + (m1 - '0');\n            if (minute > 60) {\n                return false;\n            }\n        }\n\n        if (s0 == 0) {\n            if (s1 < '0' || s1 > '9') {\n                return false;\n            }\n        } else {\n            if (s0 < '0' || s0 > '6') {\n                return false;\n            }\n            if (s1 < '0' || s1 > '9') {\n                return false;\n            }\n\n            int second = (s0 - '0') * 10 + (s1 - '0');\n            if (second > 60) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    public static SQLTimestampExpr of(String str) {\n        return new SQLTimestampExpr(str);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTimestampNTZExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.MySqlUtils;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\n\npublic class SQLTimestampNTZExpr extends SQLDateTypeExpr {\n    public SQLTimestampNTZExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.TIMESTAMP_NTZ));\n    }\n\n    public SQLTimestampNTZExpr(String literal) {\n        this();\n        this.setValue(literal);\n    }\n\n    public SQLTimestampNTZExpr(Date literal) {\n        this();\n        this.setValue(literal);\n    }\n\n    public SQLTimestampNTZExpr(Date literal, TimeZone timeZone) {\n        this();\n        this.setValue(literal, timeZone);\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public void setValue(Date x) {\n        setValue(x, null);\n    }\n\n    public void setValue(Date x, TimeZone timeZone) {\n        if (x == null) {\n            this.value = null;\n            return;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        if (timeZone != null) {\n            format.setTimeZone(timeZone);\n        }\n        String text = format.format(x);\n        setValue(text);\n    }\n\n    public Date getDate() {\n        return getDate(null);\n    }\n\n    public Date getDate(TimeZone timeZone) {\n        return MySqlUtils.parseDate(getValue(), timeZone);\n    }\n\n    public boolean addDay(int delta) {\n        if (value == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        try {\n            Date date = format.parse(getValue());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.DAY_OF_MONTH, delta);\n            String result_chars = format.format(calendar.getTime());\n            setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public boolean addMonth(int delta) {\n        if (value == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        try {\n            Date date = format.parse(getValue());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.MONTH, delta);\n            String result_chars = format.format(calendar.getTime());\n            setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    public boolean addYear(int delta) {\n        if (value == null) {\n            return false;\n        }\n\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd\");\n        try {\n            Date date = format.parse(value.toString());\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(date);\n            calendar.add(Calendar.YEAR, delta);\n            String result_chars = format.format(calendar.getTime());\n            setValue(result_chars);\n            return true;\n        } catch (ParseException e) {\n            // skip\n        }\n\n        return false;\n    }\n\n    @Override\n    public String getValue() {\n        return (String) value;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLTimestampNTZExpr other = (SQLTimestampNTZExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    public SQLTimestampNTZExpr clone() {\n        SQLTimestampNTZExpr x = new SQLTimestampNTZExpr();\n        x.value = this.value;\n        return x;\n    }\n\n    public static boolean check(String str) {\n        final int len;\n        if (str == null || (len = str.length()) < 8) {\n            return false;\n        }\n\n        final char c0 = str.charAt(0);\n        final char c1 = str.charAt(1);\n        final char c2 = str.charAt(2);\n        final char c3 = str.charAt(3);\n        final char c4 = str.charAt(4);\n        final char c5 = str.charAt(5);\n        final char c6 = str.charAt(6);\n        final char c7 = str.charAt(7);\n\n        if (c0 < '1' | c0 > '9') {\n            return false;\n        }\n        if (c1 < '0' | c1 > '9') {\n            return false;\n        }\n        if (c2 < '0' | c2 > '9') {\n            return false;\n        }\n        if (c3 < '0' | c3 > '9') {\n            return false;\n        }\n\n        int year = (c0 - '0') * 1000 + (c1 - '0') * 100 + (c2 - '0') * 10 + (c3 - '0');\n        if (year < 1000) {\n            return false;\n        }\n\n        if (c4 != '-') {\n            return false;\n        }\n\n        if (c5 < '0' | c5 > '9') {\n            return false;\n        }\n\n        int month, day;\n        if (c6 == '-') {\n            month = (c5 - '0');\n\n            if (c7 < '0' | c7 > '9') {\n                return false;\n            }\n\n            if (len == 8) {\n                day = c7 - '0';\n            } else if (len == 9) {\n                final char c8 = str.charAt(8);\n                if (c8 < '0' | c8 > '9') {\n                    return false;\n                }\n                day = (c7 - '0') * 10 + (c8 - '0');\n            } else {\n                return false;\n            }\n        } else if (c6 < '0' | c6 > '9') {\n            return false;\n        } else {\n            month = (c5 - '0') * 10 + (c6 - '0');\n\n            if (c7 != '-') {\n                return false;\n            }\n\n            if (len == 9) {\n                final char c8 = str.charAt(8);\n                if (c8 < '0' | c8 > '9') {\n                    return false;\n                }\n                day = c8 - '0';\n            } else if (len == 10) {\n                final char c8 = str.charAt(8);\n                final char c9 = str.charAt(9);\n                if (c8 < '0' | c8 > '9') {\n                    return false;\n                }\n                if (c9 < '0' | c9 > '9') {\n                    return false;\n                }\n                day = (c8 - '0') * 10 + (c9 - '0');\n            } else {\n                return false;\n            }\n        }\n\n        if (month < 1) {\n            return false;\n        }\n\n        if (day < 1) {\n            return false;\n        }\n\n        switch (month) {\n            case 1:\n            case 3:\n            case 5:\n            case 7:\n            case 8:\n            case 10:\n            case 12:\n                if (day > 31) {\n                    return false;\n                }\n                return true;\n            case 2:\n                if (day > 29) {\n                    return false;\n                }\n                return true;\n            case 4:\n            case 6:\n            case 9:\n            case 11:\n                if (day > 30) {\n                    return false;\n                }\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public static String format(Calendar calendar) {\n        if (calendar == null) {\n            return null;\n        }\n\n        int year = calendar.get(Calendar.YEAR);\n        int month = calendar.get(Calendar.MONTH) + 1;\n        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);\n\n        char[] chars = new char[10];\n        chars[0] = (char) (year / 1000 + '0');\n        chars[1] = (char) ((year / 100) % 10 + '0');\n        chars[2] = (char) ((year / 10) % 10 + '0');\n        chars[3] = (char) (year % 10 + '0');\n        chars[4] = '-';\n        chars[5] = (char) (month / 10 + '0');\n        chars[6] = (char) (month % 10 + '0');\n        chars[7] = '-';\n        chars[8] = (char) (dayOfMonth / 10 + '0');\n        chars[9] = (char) (dayOfMonth % 10 + '0');\n\n        return new String(chars);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTinyIntExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLTinyIntExpr extends SQLNumericLiteralExpr implements SQLValuableExpr {\n    public SQLTinyIntExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.TINYINT));\n    }\n\n    public SQLTinyIntExpr(Byte value) {\n        this();\n        this.value = value;\n    }\n\n    public SQLTinyIntExpr(String value) {\n        this();\n        if (value.startsWith(\"--\")) {\n            value = value.substring(2);\n        }\n        this.value = Byte.valueOf(value);\n    }\n\n    public SQLTinyIntExpr clone() {\n        return new SQLTinyIntExpr(getValue());\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Number getNumber() {\n        return getValue();\n    }\n\n    @Override\n    public Byte getValue() {\n        return (Byte) value;\n    }\n\n    public void setValue(Byte value) {\n        this.value = value;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLTinyIntExpr other = (SQLTinyIntExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            this.value = null;\n            return;\n        }\n\n        this.setValue(((Byte) number));\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTypeExpr.java",
    "content": "package com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic abstract class SQLTypeExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValuableExpr, SQLReplaceable {\n    protected SQLDataType dataType;\n    protected Object value;\n\n    public SQLTypeExpr(SQLDataType sqlDataType) {\n        if (sqlDataType != null) {\n            sqlDataType.setParent(this);\n        }\n        this.dataType = sqlDataType;\n    }\n\n    public void setValue(Object value) {\n        this.value = value;\n        if (value instanceof SQLExpr) {\n            ((SQLExpr) value).setParent(this);\n        }\n    }\n\n    public void setDataType(SQLDataType dataType) {\n        if (dataType != null) {\n            dataType.setParent(this);\n        }\n        this.dataType = dataType;\n    }\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    @Override\n    public abstract Object getValue();\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n    @Override\n    public SQLDataType computeDataType() {\n        return dataType;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.dataType);\n            if (this.value instanceof SQLExpr) {\n                acceptChild(visitor, (SQLExpr) this.value);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == this.dataType && target instanceof SQLDataType) {\n            setDataType((SQLDataType) target);\n            return true;\n        }\n        if (this.value instanceof SQLExpr && expr == this.value) {\n            this.setValue(target);\n            return true;\n        }\n        return false;\n    }\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLTypeExpr other = (SQLTypeExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public abstract SQLTypeExpr clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.io.Serializable;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLUnaryExpr extends SQLExprImpl implements Serializable, SQLReplaceable {\n    private static final long serialVersionUID = 1L;\n    private SQLExpr expr;\n    private SQLUnaryOperator operator;\n\n    public SQLUnaryExpr() {\n    }\n\n    public SQLUnaryExpr(SQLUnaryOperator operator, SQLExpr expr) {\n        this.operator = operator;\n        this.setExpr(expr);\n    }\n\n    public SQLUnaryExpr clone() {\n        SQLUnaryExpr x = new SQLUnaryExpr();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.operator = operator;\n        x.parenthesized = parenthesized;\n        return x;\n    }\n\n    public SQLUnaryOperator getOperator() {\n        return operator;\n    }\n\n    public void setOperator(SQLUnaryOperator operator) {\n        this.operator = operator;\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.expr != null) {\n                this.expr.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.expr);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        result = prime * result + ((operator == null) ? 0 : operator.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLUnaryExpr other = (SQLUnaryExpr) obj;\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        if (operator != other.operator) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n\n    public SQLDataType computeDataType() {\n        switch (operator) {\n            case Plus:\n            case Negative:\n            case Compl:\n            case Not:\n                return expr.computeDataType();\n            default:\n                return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\npublic enum SQLUnaryOperator {\n    Plus(\"+\"),\n    Negative(\"-\"),\n    Not(\"!\"),\n    Compl(\"~\"),\n    Prior(\"PRIOR\"),\n    ConnectByRoot(\"CONNECT BY\"),\n    BINARY(\"BINARY\"),\n    RAW(\"RAW\"),\n    NOT(\"NOT\"),\n    // Number of points in path or polygon\n    Pound(\"#\");\n\n    public final String name;\n\n    SQLUnaryOperator(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLValuableExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\n\npublic interface SQLValuableExpr extends SQLExpr {\n    Object getValue();\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLValuesExpr.java",
    "content": "package com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLValuesExpr extends SQLExprImpl implements SQLReplaceable {\n    private List<SQLListExpr> values = new ArrayList<SQLListExpr>();\n\n    public List<SQLListExpr> getValues() {\n        return values;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, values);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLValuesExpr that = (SQLValuesExpr) o;\n\n        return values.equals(that.values);\n    }\n\n    @Override\n    public int hashCode() {\n        return values.hashCode();\n    }\n\n    @Override\n    public SQLExpr clone() {\n        SQLValuesExpr x = new SQLValuesExpr();\n\n        for (SQLListExpr value : values) {\n            SQLListExpr value2 = value.clone();\n            value2.setParent(x);\n            x.values.add(value2);\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < values.size(); i++) {\n            if (values.get(i) == expr) {\n                target.setParent(this);\n                values.set(i, (SQLListExpr) target);\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public List getChildren() {\n        return values;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLVariantRefExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLVariantRefExpr extends SQLExprImpl {\n    private String name;\n\n    private boolean global;\n    private boolean session;\n    private boolean templateParameter;\n    private boolean hasPrefixComma;\n\n    private int index = -1;\n\n    public SQLVariantRefExpr(String name) {\n        this.name = name;\n        if (name.startsWith(\"${\") && name.endsWith(\"}\")) {\n            this.templateParameter = true;\n        } else {\n            this.templateParameter = false;\n        }\n        this.hasPrefixComma = true;\n    }\n\n    public SQLVariantRefExpr(String name, SQLObject parent) {\n        this.name = name;\n        this.parent = parent;\n        if (name.startsWith(\"${\") && name.endsWith(\"}\")) {\n            this.templateParameter = true;\n        } else {\n            this.templateParameter = false;\n        }\n        this.hasPrefixComma = true;\n    }\n\n    public SQLVariantRefExpr(String name, boolean global) {\n        this(name, global, false);\n    }\n\n    public SQLVariantRefExpr(String name, boolean global, boolean session) {\n        this.name = name;\n        this.global = global;\n        this.session = session;\n    }\n\n    public SQLVariantRefExpr() {\n    }\n\n    public int getIndex() {\n        return index;\n    }\n\n    public void setIndex(int index) {\n        this.index = index;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public boolean isTemplateParameter() {\n        return templateParameter;\n    }\n\n    public void setTemplateParameter(boolean templateParameter) {\n        this.templateParameter = templateParameter;\n    }\n\n    public boolean isHasPrefixComma() {\n        return hasPrefixComma;\n    }\n\n    public void setHasPrefixComma(boolean hasPrefixComma) {\n        this.hasPrefixComma = hasPrefixComma;\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(this.name);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((name == null) ? 0 : name.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (!(obj instanceof SQLVariantRefExpr)) {\n            return false;\n        }\n        SQLVariantRefExpr other = (SQLVariantRefExpr) obj;\n        if (name == null) {\n            if (other.name != null) {\n                return false;\n            }\n        } else if (!name.equals(other.name)) {\n            return false;\n        }\n        return true;\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n\n    public boolean isSession() {\n        return session;\n    }\n\n    public void setSession(boolean session) {\n        this.session = session;\n    }\n\n    public SQLVariantRefExpr clone() {\n        SQLVariantRefExpr var = new SQLVariantRefExpr(name, global, session);\n\n        if (attributes != null) {\n            var.attributes = new HashMap<String, Object>(attributes.size());\n            for (Map.Entry<String, Object> entry : attributes.entrySet()) {\n                String k = entry.getKey();\n                Object v = entry.getValue();\n\n                if (v instanceof SQLObject) {\n                    var.attributes.put(k, ((SQLObject) v).clone());\n                } else {\n                    var.attributes.put(k, v);\n                }\n            }\n        }\n\n        var.index = index;\n        return var;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterCharacter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterCharacter extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr characterSet;\n    private SQLExpr collate;\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, characterSet);\n            acceptChild(visitor, collate);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getCharacterSet() {\n        return characterSet;\n    }\n\n    public void setCharacterSet(SQLExpr characterSet) {\n        this.characterSet = characterSet;\n    }\n\n    public SQLExpr getCollate() {\n        return collate;\n    }\n\n    public void setCollate(SQLExpr collate) {\n        this.collate = collate;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterDatabaseItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\n\npublic interface SQLAlterDatabaseItem extends SQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterDatabaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLAlterDatabaseStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n    private boolean upgradeDataDirectoryName;\n    private SQLAlterCharacter character;\n\n    private SQLAlterDatabaseItem item;\n\n    private List<SQLAssignItem> properties = new ArrayList<SQLAssignItem>();\n\n    public SQLAlterDatabaseStatement() {\n    }\n\n    public SQLAlterDatabaseStatement(DbType dbType) {\n        this.setDbType(dbType);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLAlterCharacter getCharacter() {\n        return character;\n    }\n\n    public void setCharacter(SQLAlterCharacter character) {\n        if (character != null) {\n            character.setParent(this);\n        }\n        this.character = character;\n    }\n\n    public boolean isUpgradeDataDirectoryName() {\n        return upgradeDataDirectoryName;\n    }\n\n    public void setUpgradeDataDirectoryName(boolean upgradeDataDirectoryName) {\n        this.upgradeDataDirectoryName = upgradeDataDirectoryName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLAlterDatabaseItem getItem() {\n        return item;\n    }\n\n    public void setItem(SQLAlterDatabaseItem item) {\n        this.item = item;\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(name);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterFunctionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterFunctionStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    private boolean debug;\n    private boolean reuseSettings;\n\n    private SQLExpr comment;\n    private boolean languageSql;\n    private boolean containsSql;\n    private SQLExpr sqlSecurity;\n\n    public boolean isDebug() {\n        return debug;\n    }\n\n    public void setDebug(boolean debug) {\n        this.debug = debug;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public boolean isReuseSettings() {\n        return reuseSettings;\n    }\n\n    public void setReuseSettings(boolean x) {\n        this.reuseSettings = x;\n    }\n\n    public boolean isLanguageSql() {\n        return languageSql;\n    }\n\n    public void setLanguageSql(boolean languageSql) {\n        this.languageSql = languageSql;\n    }\n\n    public boolean isContainsSql() {\n        return containsSql;\n    }\n\n    public void setContainsSql(boolean containsSql) {\n        this.containsSql = containsSql;\n    }\n\n    public SQLExpr getSqlSecurity() {\n        return sqlSecurity;\n    }\n\n    public void setSqlSecurity(SQLExpr sqlSecurity) {\n        if (sqlSecurity != null) {\n            sqlSecurity.setParent(this);\n        }\n        this.sqlSecurity = sqlSecurity;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, comment);\n            acceptChild(visitor, sqlSecurity);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.FUNCTION;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterIndexStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterIndexStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n    private SQLName renameTo;\n    private SQLExprTableSource table;\n    private boolean compile;\n    private Boolean enable;\n    protected boolean unusable;\n    private Boolean monitoringUsage;\n    private Rebuild rebuild;\n    private SQLExpr parallel;\n    private List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>();\n    protected SQLPartitionBy dbPartitionBy;\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, renameTo);\n            acceptChild(visitor, table);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, rebuild);\n            acceptChild(visitor, parallel);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getRenameTo() {\n        return renameTo;\n    }\n\n    public void setRenameTo(SQLName renameTo) {\n        this.renameTo = renameTo;\n    }\n\n    public SQLExpr getParallel() {\n        return parallel;\n    }\n\n    public void setParallel(SQLExpr parallel) {\n        this.parallel = parallel;\n    }\n\n    public Boolean getMonitoringUsage() {\n        return monitoringUsage;\n    }\n\n    public void setMonitoringUsage(Boolean monitoringUsage) {\n        this.monitoringUsage = monitoringUsage;\n    }\n\n    public Rebuild getRebuild() {\n        return rebuild;\n    }\n\n    public void setRebuild(Rebuild rebuild) {\n        this.rebuild = rebuild;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public boolean isUnusable() {\n        return unusable;\n    }\n\n    public void setUnusable(boolean unusable) {\n        this.unusable = unusable;\n    }\n\n    public static class Rebuild extends SQLObjectImpl {\n        private SQLObject option;\n\n        public SQLObject getOption() {\n            return option;\n        }\n\n        public void setOption(SQLObject option) {\n            this.option = option;\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, option);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName x) {\n        setTable(new SQLExprTableSource(x));\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public SQLPartitionBy getDbPartitionBy() {\n        return dbPartitionBy;\n    }\n\n    public void setDbPartitionBy(SQLPartitionBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.dbPartitionBy = x;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.INDEX;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterMaterializedViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterMaterializedViewStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    private boolean refreshFast;\n    private boolean refreshComplete;\n    private boolean refreshForce;\n    private boolean refreshOnCommit;\n    private boolean refreshOnDemand;\n    private boolean refreshStartWith;\n    private boolean refreshNext;\n    private final List<SQLExpr> partitions = new ArrayList<SQLExpr>(); // odps\n\n    private Boolean enableQueryRewrite;\n\n    private SQLExpr startWith;\n    private SQLExpr next;\n\n    // for ADB\n    protected boolean refreshOnOverWrite;\n    private boolean rebuild;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public boolean isRefresh() {\n        return refreshFast || refreshComplete || refreshForce || refreshOnDemand || refreshOnCommit || refreshStartWith || refreshNext || refreshOnOverWrite;\n    }\n\n    public boolean isRefreshFast() {\n        return refreshFast;\n    }\n\n    public void setRefreshFast(boolean refreshFast) {\n        this.refreshFast = refreshFast;\n    }\n\n    public boolean isRefreshComplete() {\n        return refreshComplete;\n    }\n\n    public void setRefreshComplete(boolean refreshComplete) {\n        this.refreshComplete = refreshComplete;\n    }\n\n    public boolean isRefreshForce() {\n        return refreshForce;\n    }\n\n    public void setRefreshForce(boolean refreshForce) {\n        this.refreshForce = refreshForce;\n    }\n\n    public boolean isRefreshOnCommit() {\n        return refreshOnCommit;\n    }\n\n    public void setRefreshOnCommit(boolean refreshOnCommit) {\n        this.refreshOnCommit = refreshOnCommit;\n    }\n\n    public boolean isRefreshOnDemand() {\n        return refreshOnDemand;\n    }\n\n    public void setRefreshOnDemand(boolean refreshOnDemand) {\n        this.refreshOnDemand = refreshOnDemand;\n    }\n\n    public boolean isRefreshOnOverWrite() {\n        return refreshOnOverWrite;\n    }\n\n    public void setRefreshOnOverWrite(boolean refreshOnOverWrite) {\n        this.refreshOnOverWrite = refreshOnOverWrite;\n    }\n\n    public boolean isRefreshStartWith() {\n        return refreshStartWith;\n    }\n\n    public void setRefreshStartWith(boolean refreshStartWith) {\n        this.refreshStartWith = refreshStartWith;\n    }\n\n    public boolean isRefreshNext() {\n        return refreshNext;\n    }\n\n    public void setRefreshNext(boolean refreshNext) {\n        this.refreshNext = refreshNext;\n    }\n\n    public Boolean getEnableQueryRewrite() {\n        return enableQueryRewrite;\n    }\n\n    public void setEnableQueryRewrite(Boolean enableQueryRewrite) {\n        this.enableQueryRewrite = enableQueryRewrite;\n    }\n\n    public SQLExpr getStartWith() {\n        return startWith;\n    }\n\n    public void setStartWith(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.startWith = x;\n    }\n\n    public SQLExpr getNext() {\n        return next;\n    }\n\n    public void setNext(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.next = x;\n    }\n\n    public boolean isRebuild() {\n        return rebuild;\n    }\n\n    public void setRebuild(boolean rebuild) {\n        this.rebuild = rebuild;\n    }\n\n    public List<SQLExpr> getPartitions() {\n        return partitions;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, startWith);\n            acceptChild(visitor, next);\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.MATERIALIZED_VIEW;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterOutlineStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterOutlineStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLExpr name;\n\n    private boolean resync;\n    private boolean disable;\n    private boolean enable;\n\n    public SQLAlterOutlineStatement() {\n    }\n\n    public SQLAlterOutlineStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public boolean isResync() {\n        return resync;\n    }\n\n    public void setResync(boolean resync) {\n        this.resync = resync;\n    }\n\n    public boolean isDisable() {\n        return disable;\n    }\n\n    public void setDisable(boolean disable) {\n        this.disable = disable;\n    }\n\n    public boolean isEnable() {\n        return enable;\n    }\n\n    public void setEnable(boolean enable) {\n        this.enable = enable;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterProcedureStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterProcedureStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLExpr name;\n\n    private boolean compile;\n    private boolean reuseSettings;\n\n    private SQLExpr comment;\n    private boolean languageSql;\n    private boolean containsSql;\n    private SQLExpr sqlSecurity;\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        this.name = name;\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n    public boolean isReuseSettings() {\n        return reuseSettings;\n    }\n\n    public void setReuseSettings(boolean reuseSettings) {\n        this.reuseSettings = reuseSettings;\n    }\n\n    public boolean isLanguageSql() {\n        return languageSql;\n    }\n\n    public void setLanguageSql(boolean languageSql) {\n        this.languageSql = languageSql;\n    }\n\n    public boolean isContainsSql() {\n        return containsSql;\n    }\n\n    public void setContainsSql(boolean containsSql) {\n        this.containsSql = containsSql;\n    }\n\n    public SQLExpr getSqlSecurity() {\n        return sqlSecurity;\n    }\n\n    public void setSqlSecurity(SQLExpr sqlSecurity) {\n        if (sqlSecurity != null) {\n            sqlSecurity.setParent(this);\n        }\n        this.sqlSecurity = sqlSecurity;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.PROCEDURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterSequenceStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterSequenceStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    private Boolean withCache;\n    private SQLExpr startWith;\n    private SQLExpr incrementBy;\n    private SQLExpr minValue;\n    private SQLExpr maxValue;\n    private boolean noMaxValue;\n    private boolean noMinValue;\n\n    private Boolean cycle;\n    private Boolean cache;\n    private SQLExpr cacheValue;\n\n    private boolean restart;\n    private SQLExpr restartWith;\n\n    private Boolean order;\n\n    private boolean changeToSimple;\n    private boolean changeToGroup;\n    private boolean changeToTime;\n\n    public SQLAlterSequenceStatement() {\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, startWith);\n            acceptChild(visitor, incrementBy);\n            acceptChild(visitor, minValue);\n            acceptChild(visitor, maxValue);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        if (startWith != null) {\n            children.add(startWith);\n        }\n        if (incrementBy != null) {\n            children.add(incrementBy);\n        }\n        if (minValue != null) {\n            children.add(minValue);\n        }\n        if (maxValue != null) {\n            children.add(maxValue);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public SQLExpr getStartWith() {\n        return startWith;\n    }\n\n    public void setStartWith(SQLExpr startWith) {\n        this.startWith = startWith;\n    }\n\n    public SQLExpr getIncrementBy() {\n        return incrementBy;\n    }\n\n    public void setIncrementBy(SQLExpr incrementBy) {\n        this.incrementBy = incrementBy;\n    }\n\n    public SQLExpr getMaxValue() {\n        return maxValue;\n    }\n\n    public void setMaxValue(SQLExpr maxValue) {\n        this.maxValue = maxValue;\n    }\n\n    public Boolean getCycle() {\n        return cycle;\n    }\n\n    public void setCycle(Boolean cycle) {\n        this.cycle = cycle;\n    }\n\n    public Boolean getCache() {\n        return cache;\n    }\n\n    public void setCache(Boolean cache) {\n        this.cache = cache;\n    }\n\n    public Boolean getWithCache() {\n        return withCache;\n    }\n\n    public void setWithCache(Boolean withCache) {\n        this.withCache = withCache;\n    }\n\n    public Boolean getOrder() {\n        return order;\n    }\n\n    public void setOrder(Boolean order) {\n        this.order = order;\n    }\n\n    public SQLExpr getMinValue() {\n        return minValue;\n    }\n\n    public void setMinValue(SQLExpr minValue) {\n        this.minValue = minValue;\n    }\n\n    public boolean isNoMaxValue() {\n        return noMaxValue;\n    }\n\n    public void setNoMaxValue(boolean noMaxValue) {\n        this.noMaxValue = noMaxValue;\n    }\n\n    public boolean isNoMinValue() {\n        return noMinValue;\n    }\n\n    public void setNoMinValue(boolean noMinValue) {\n        this.noMinValue = noMinValue;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public SQLExpr getCacheValue() {\n        return cacheValue;\n    }\n\n    public void setCacheValue(SQLExpr cacheValue) {\n        if (cacheValue != null) {\n            cacheValue.setParent(this);\n        }\n        this.cacheValue = cacheValue;\n    }\n\n    public boolean isChangeToSimple() {\n        return changeToSimple;\n    }\n\n    public void setChangeToSimple(boolean changeToSimple) {\n        this.changeToSimple = changeToSimple;\n    }\n\n    public boolean isChangeToGroup() {\n        return changeToGroup;\n    }\n\n    public void setChangeToGroup(boolean changeToGroup) {\n        this.changeToGroup = changeToGroup;\n    }\n\n    public boolean isChangeToTime() {\n        return changeToTime;\n    }\n\n    public void setChangeToTime(boolean changeToTime) {\n        this.changeToTime = changeToTime;\n    }\n\n    public boolean isRestart() {\n        return restart;\n    }\n\n    public void setRestart(boolean restart) {\n        this.restart = restart;\n    }\n\n    public SQLExpr getRestartWith() {\n        return restartWith;\n    }\n\n    public void setRestartWith(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.restartWith = x;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.SEQUENCE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\npublic interface SQLAlterStatement extends SQLDDLStatement {\n    default DDLObjectType getDDLObjectType() {\n        return DDLObjectType.OTHER;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterSystemGetConfigStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterSystemGetConfigStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterSystemSetConfigStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterSystemSetConfigStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void addOption(SQLAssignItem item) {\n        item.setParent(this);\n        this.options.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, options);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAddClusteringKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableAddClusteringKey extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName name;\n    private final List<SQLName> columns = new ArrayList<SQLName>();\n\n    public SQLAlterTableAddClusteringKey() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (name != null) {\n                name.accept(visitor);\n            }\n            for (SQLName column : columns) {\n                column.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAddColumn.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableAddColumn extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();\n\n    // for mysql\n    private SQLName firstColumn;\n    private SQLName afterColumn;\n    private boolean first;\n    private Boolean restrict;\n    private boolean cascade;\n    private boolean ifNotExists;\n\n    public SQLAlterTableAddColumn() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public List<SQLColumnDefinition> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLColumnDefinition column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public SQLName getFirstColumn() {\n        return firstColumn;\n    }\n\n    public void setFirstColumn(SQLName first) {\n        this.firstColumn = first;\n    }\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public void setFirst(boolean first) {\n        this.first = first;\n    }\n\n    public SQLName getAfterColumn() {\n        return afterColumn;\n    }\n\n    public void setAfterColumn(SQLName after) {\n        this.afterColumn = after;\n    }\n\n    public Boolean getRestrict() {\n        return restrict;\n    }\n\n    public boolean isRestrict() {\n        if (restrict == null) {\n            return !cascade;\n        }\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAddConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableAddConstraint extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLConstraint constraint;\n    private boolean withNoCheck;\n\n    private boolean noInherit;\n    private boolean notValid;\n    public SQLAlterTableAddConstraint() {\n    }\n\n    public SQLAlterTableAddConstraint(SQLConstraint constraint) {\n        this.setConstraint(constraint);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, constraint);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLConstraint getConstraint() {\n        return constraint;\n    }\n\n    public void setConstraint(SQLConstraint constraint) {\n        if (constraint != null) {\n            constraint.setParent(this);\n        }\n        this.constraint = constraint;\n    }\n\n    public boolean isWithNoCheck() {\n        return withNoCheck;\n    }\n\n    public void setWithNoCheck(boolean withNoCheck) {\n        this.withNoCheck = withNoCheck;\n    }\n\n    public boolean isNoInherit() {\n        return noInherit;\n    }\n\n    public void setNoInherit(boolean noInherit) {\n        this.noInherit = noInherit;\n    }\n\n    public boolean isNotValid() {\n        return notValid;\n    }\n\n    public void setNotValid(boolean notValid) {\n        this.notValid = notValid;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAddExtPartition.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExtPartition;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * @author shicai.xsc 2018-9-13\n * @since 5.0.0.0\n */\npublic class SQLAlterTableAddExtPartition extends SQLObjectImpl implements SQLAlterTableItem, MySqlObject {\n    private MySqlExtPartition extPartition;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public void setExPartition(MySqlExtPartition x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.extPartition = x;\n    }\n\n    public MySqlExtPartition getExtPartition() {\n        return extPartition;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAddIndex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class SQLAlterTableAddIndex extends SQLObjectImpl implements SQLAlterTableItem, SQLIndex {\n    private SQLIndexDefinition indexDefinition = new SQLIndexDefinition();\n\n    public SQLAlterTableAddIndex() {\n        indexDefinition.setParent(this);\n    }\n\n    public SQLIndexDefinition getIndexDefinition() {\n        return indexDefinition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (indexDefinition.getName() != null) {\n                indexDefinition.getName().accept(visitor);\n            }\n\n            for (int i = 0; i < getColumns().size(); i++) {\n                final SQLSelectOrderByItem item = getColumns().get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n            for (int i = 0; i < getCovering().size(); i++) {\n                final SQLName item = getCovering().get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isUnique() {\n        return indexDefinition.getType() != null && indexDefinition.getType().equalsIgnoreCase(\"UNIQUE\");\n    }\n\n    public void setUnique(boolean unique) {\n        indexDefinition.setType(\"UNIQUE\");\n    }\n\n    public List<SQLSelectOrderByItem> getItems() {\n        return indexDefinition.getColumns();\n    }\n\n    public void addItem(SQLSelectOrderByItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        indexDefinition.getColumns().add(item);\n    }\n\n    public SQLName getName() {\n        return indexDefinition.getName();\n    }\n\n    public void setName(SQLName name) {\n        indexDefinition.setName(name);\n    }\n\n    public String getType() {\n        return indexDefinition.getType();\n    }\n\n    public void setType(String type) {\n        indexDefinition.setType(type);\n    }\n\n    public String getUsing() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getIndexType();\n        }\n        return null;\n    }\n\n    public void setUsing(String using) {\n        indexDefinition.getOptions().setIndexType(using);\n    }\n\n    public boolean isKey() {\n        return indexDefinition.isKey();\n    }\n\n    public void setKey(boolean key) {\n        indexDefinition.setKey(key);\n    }\n\n    public void cloneTo(MySqlTableIndex x) {\n        indexDefinition.cloneTo(x.getIndexDefinition());\n    }\n\n    public void cloneTo(MySqlKey x) {\n        indexDefinition.cloneTo(x.getIndexDefinition());\n    }\n\n    public SQLExpr getComment() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getComment();\n        }\n        return null;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        indexDefinition.getOptions().setComment(comment);\n    }\n\n    public SQLExpr getKeyBlockSize() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getKeyBlockSize();\n        }\n        return null;\n    }\n\n    public void setKeyBlockSize(SQLExpr keyBlockSize) {\n        indexDefinition.getOptions().setKeyBlockSize(keyBlockSize);\n    }\n\n    public String getParserName() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getParserName();\n        }\n        return null;\n    }\n\n    public void setParserName(String parserName) {\n        indexDefinition.getOptions().setParserName(parserName);\n    }\n\n    public boolean isHashMapType() {\n        return indexDefinition.isHashMapType();\n    }\n\n    public void setHashMapType(boolean hashMapType) {\n        indexDefinition.setHashMapType(hashMapType);\n    }\n\n    protected SQLExpr getOption(long hash64) {\n        return indexDefinition.getOption(hash64);\n    }\n\n    public String getDistanceMeasure() {\n        return indexDefinition.getDistanceMeasure();\n    }\n\n    public String getAlgorithm() {\n        return indexDefinition.getAlgorithm();\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        indexDefinition.addOption(name, value);\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return indexDefinition.getCompatibleOptions();\n    }\n\n    public boolean isGlobal() {\n        return indexDefinition.isGlobal();\n    }\n\n    public void setGlobal(boolean global) {\n        indexDefinition.setGlobal(global);\n    }\n\n    public SQLExpr getDbPartitionBy() {\n        return indexDefinition.getDbPartitionBy();\n    }\n\n    public void setDbPartitionBy(SQLExpr x) {\n        indexDefinition.setDbPartitionBy(x);\n    }\n\n    public SQLExpr getTablePartitionBy() {\n        return indexDefinition.getTbPartitionBy();\n    }\n\n    public void setTablePartitionBy(SQLExpr x) {\n        indexDefinition.setTbPartitionBy(x);\n    }\n\n    public SQLExpr getTablePartitions() {\n        return indexDefinition.getTbPartitions();\n    }\n\n    public void setTablePartitions(SQLExpr x) {\n        indexDefinition.setTbPartitions(x);\n    }\n\n    @Override\n    public List<SQLName> getCovering() {\n        return indexDefinition.getCovering();\n    }\n\n    @Override\n    public List<SQLSelectOrderByItem> getColumns() {\n        return indexDefinition.getColumns();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAddPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableAddPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private boolean ifNotExists;\n    private final List<SQLObject> partitions = new ArrayList<SQLObject>(4);\n    private SQLExpr partitionCount;\n    private SQLExpr location; // hive\n\n    public List<SQLObject> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLObject x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partitions.add(x);\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public SQLExpr getPartitionCount() {\n        return partitionCount;\n    }\n\n    public void setPartitionCount(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partitionCount = x;\n    }\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public void setLocation(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.location = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, partitionCount);\n            acceptChild(visitor, location);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAddSupplemental.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableAddSupplemental extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLTableElement element;\n\n    public SQLAlterTableAddSupplemental() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, element);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLTableElement getElement() {\n        return element;\n    }\n\n    public void setElement(SQLTableElement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.element = x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAlterColumn.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableAlterColumn extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName originColumn;\n    private SQLColumnDefinition column;\n    private boolean setNotNull;\n    private boolean dropNotNull;\n    private SQLExpr setDefault;\n    private boolean dropDefault;\n    private boolean first;\n    private SQLName after;\n    private SQLDataType dataType;\n    private boolean toFirst;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, column);\n            acceptChild(visitor, setDefault);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLColumnDefinition getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLColumnDefinition column) {\n        this.column = column;\n        column.setParent(this);\n    }\n\n    public boolean isSetNotNull() {\n        return setNotNull;\n    }\n\n    public void setSetNotNull(boolean setNotNull) {\n        this.setNotNull = setNotNull;\n    }\n\n    public boolean isDropNotNull() {\n        return dropNotNull;\n    }\n\n    public void setDropNotNull(boolean dropNotNull) {\n        this.dropNotNull = dropNotNull;\n    }\n\n    public SQLExpr getSetDefault() {\n        return setDefault;\n    }\n\n    public void setSetDefault(SQLExpr setDefault) {\n        this.setDefault = setDefault;\n    }\n\n    public boolean isDropDefault() {\n        return dropDefault;\n    }\n\n    public void setDropDefault(boolean dropDefault) {\n        this.dropDefault = dropDefault;\n    }\n\n    public SQLName getOriginColumn() {\n        return originColumn;\n    }\n\n    public void setOriginColumn(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.originColumn = x;\n    }\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public void setFirst(boolean x) {\n        this.first = x;\n    }\n\n    public SQLName getAfter() {\n        return after;\n    }\n\n    public void setAfter(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.after = x;\n    }\n\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    public void setDataType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.dataType = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAlterIndex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class SQLAlterTableAlterIndex extends SQLObjectImpl implements SQLAlterTableItem, SQLIndex {\n    private SQLIndexDefinition indexDefinition = new SQLIndexDefinition();\n\n    public SQLAlterTableAlterIndex() {\n        indexDefinition.setParent(this);\n    }\n\n    public SQLIndexDefinition getIndexDefinition() {\n        return indexDefinition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (indexDefinition.getName() != null) {\n                indexDefinition.getName().accept(visitor);\n            }\n\n            for (int i = 0; i < getColumns().size(); i++) {\n                final SQLSelectOrderByItem item = getColumns().get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n            for (int i = 0; i < getCovering().size(); i++) {\n                final SQLName item = getCovering().get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isUnique() {\n        return indexDefinition.getType() != null && indexDefinition.getType().equalsIgnoreCase(\"UNIQUE\");\n    }\n\n    public void setUnique(boolean unique) {\n        indexDefinition.setType(\"UNIQUE\");\n    }\n\n    public List<SQLSelectOrderByItem> getItems() {\n        return indexDefinition.getColumns();\n    }\n\n    public void addItem(SQLSelectOrderByItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        indexDefinition.getColumns().add(item);\n    }\n\n    public SQLName getName() {\n        return indexDefinition.getName();\n    }\n\n    public void setName(SQLName name) {\n        indexDefinition.setName(name);\n    }\n\n    public String getType() {\n        return indexDefinition.getType();\n    }\n\n    public void setType(String type) {\n        indexDefinition.setType(type);\n    }\n\n    public String getUsing() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getIndexType();\n        }\n        return null;\n    }\n\n    public void setUsing(String using) {\n        indexDefinition.getOptions().setIndexType(using);\n    }\n\n    public boolean isKey() {\n        return indexDefinition.isKey();\n    }\n\n    public void setKey(boolean key) {\n        indexDefinition.setKey(key);\n    }\n\n    public void cloneTo(MySqlTableIndex x) {\n        indexDefinition.cloneTo(x.getIndexDefinition());\n    }\n\n    public void cloneTo(MySqlKey x) {\n        indexDefinition.cloneTo(x.getIndexDefinition());\n    }\n\n    public SQLExpr getComment() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getComment();\n        }\n        return null;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        indexDefinition.getOptions().setComment(comment);\n    }\n\n    public SQLExpr getKeyBlockSize() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getKeyBlockSize();\n        }\n        return null;\n    }\n\n    public void setKeyBlockSize(SQLExpr keyBlockSize) {\n        indexDefinition.getOptions().setKeyBlockSize(keyBlockSize);\n    }\n\n    public String getParserName() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getParserName();\n        }\n        return null;\n    }\n\n    public void setParserName(String parserName) {\n        indexDefinition.getOptions().setParserName(parserName);\n    }\n\n    public boolean isHashMapType() {\n        return indexDefinition.isHashMapType();\n    }\n\n    public void setHashMapType(boolean hashMapType) {\n        indexDefinition.setHashMapType(hashMapType);\n    }\n\n    protected SQLExpr getOption(long hash64) {\n        return indexDefinition.getOption(hash64);\n    }\n\n    public String getDistanceMeasure() {\n        return indexDefinition.getDistanceMeasure();\n    }\n\n    public String getAlgorithm() {\n        return indexDefinition.getAlgorithm();\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        indexDefinition.addOption(name, value);\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return indexDefinition.getCompatibleOptions();\n    }\n\n    public boolean isGlobal() {\n        return indexDefinition.isGlobal();\n    }\n\n    public void setGlobal(boolean global) {\n        indexDefinition.setGlobal(global);\n    }\n\n    public SQLExpr getDbPartitionBy() {\n        return indexDefinition.getDbPartitionBy();\n    }\n\n    public void setDbPartitionBy(SQLExpr x) {\n        indexDefinition.setDbPartitionBy(x);\n    }\n\n    public SQLExpr getTablePartitionBy() {\n        return indexDefinition.getTbPartitionBy();\n    }\n\n    public void setTablePartitionBy(SQLExpr x) {\n        indexDefinition.setTbPartitionBy(x);\n    }\n\n    public SQLExpr getTablePartitions() {\n        return indexDefinition.getTbPartitions();\n    }\n\n    public void setTablePartitions(SQLExpr x) {\n        indexDefinition.setTbPartitions(x);\n    }\n\n    @Override\n    public List<SQLName> getCovering() {\n        return indexDefinition.getCovering();\n    }\n\n    @Override\n    public List<SQLSelectOrderByItem> getColumns() {\n        return indexDefinition.getColumns();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAnalyzePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableAnalyzePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableArchive.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableArchive extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partition);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableArchivePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableArchivePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLAssignItem partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableAttachPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableAttachPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    protected SQLName partitionName;\n\n    protected boolean defaultFlag;\n\n    public SQLName getPartitionName() {\n        return partitionName;\n    }\n\n    public void setPartitionName(SQLName partitionName) {\n        this.partitionName = partitionName;\n    }\n\n    public boolean isDefaultFlag() {\n        return defaultFlag;\n    }\n\n    public void setDefaultFlag(boolean defaultFlag) {\n        this.defaultFlag = defaultFlag;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.partitionName);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableBlockSize.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableBlockSize extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLIntegerExpr size;\n\n    public SQLAlterTableBlockSize() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, size);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLIntegerExpr getSize() {\n        return size;\n    }\n\n    public void setSize(SQLIntegerExpr size) {\n        if (size != null) {\n            size.setParent(this);\n        }\n        this.size = size;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableChangeOwner.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableChangeOwner extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n    private SQLName owner;\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLName getOwner() {\n        return owner;\n    }\n\n    public void setOwner(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.owner = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableCheckPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableCheckPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableCoalescePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableCoalescePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr count;\n\n    public SQLExpr getCount() {\n        return count;\n    }\n\n    public void setCount(SQLExpr count) {\n        if (count != null) {\n            count.setParent(this);\n        }\n        this.count = count;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, count);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableCompression.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableCompression extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLCharExpr name;\n\n    public SQLAlterTableCompression() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLCharExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLCharExpr name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableConvertCharSet.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableConvertCharSet extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr charset;\n    private SQLExpr collate;\n\n    public SQLAlterTableConvertCharSet() {\n    }\n\n    public SQLExpr getCharset() {\n        return charset;\n    }\n\n    public void setCharset(SQLExpr charset) {\n        if (charset != null) {\n            charset.setParent(this);\n        }\n        this.charset = charset;\n    }\n\n    public SQLExpr getCollate() {\n        return collate;\n    }\n\n    public void setCollate(SQLExpr collate) {\n        if (collate != null) {\n            collate.setParent(this);\n        }\n        this.collate = collate;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, charset);\n            acceptChild(visitor, collate);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDeleteByCondition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDeleteByCondition extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr where;\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n        if (where != null) {\n            this.where.setParent(this);\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDetachPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDetachPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    protected SQLName partitionName;\n\n    protected boolean concurrently;\n    protected boolean finalize;\n\n    public SQLName getPartitionName() {\n        return partitionName;\n    }\n\n    public void setPartitionName(SQLName partitionName) {\n        this.partitionName = partitionName;\n    }\n\n    public boolean isConcurrently() {\n        return concurrently;\n    }\n\n    public void setConcurrently(boolean concurrently) {\n        this.concurrently = concurrently;\n    }\n\n    public boolean isFinalize() {\n        return finalize;\n    }\n\n    public void setFinalize(boolean finalize) {\n        this.finalize = finalize;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.partitionName);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDisableConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDisableConstraint extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName constraintName;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.constraintName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getConstraintName() {\n        return constraintName;\n    }\n\n    public void setConstraintName(SQLName constraintName) {\n        this.constraintName = constraintName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDisableKeys.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDisableKeys extends SQLObjectImpl implements SQLAlterTableItem {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDisableLifecycle.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableDisableLifecycle extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partition);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDiscardPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableDiscardPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    private boolean tablespace;\n\n    public SQLAlterTableDiscardPartition() {\n    }\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(boolean tablespace) {\n        this.tablespace = tablespace;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropCheck.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDropCheck extends SQLObjectImpl implements SQLAlterTableItem {\n    private boolean ifExists;\n    private SQLName checkName;\n\n    protected boolean cascade;\n    protected boolean restrict;\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.checkName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getCheckName() {\n        return checkName;\n    }\n\n    public void setCheckName(SQLName checkName) {\n        this.checkName = checkName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropClusteringKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDropClusteringKey extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName keyName;\n\n    public SQLName getKeyName() {\n        return keyName;\n    }\n\n    public void setKeyName(SQLName keyName) {\n        this.keyName = keyName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, keyName);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropColumnItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableDropColumnItem extends SQLObjectImpl implements SQLAlterTableItem {\n    private boolean ifExists;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n\n    private boolean restrict;\n    private boolean cascade;\n\n    public SQLAlterTableDropColumnItem() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLName column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDropConstraint extends SQLObjectImpl implements SQLAlterTableItem {\n    private boolean ifExists;\n    private SQLName constraintName;\n\n    protected boolean cascade;\n    protected boolean restrict;\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.constraintName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getConstraintName() {\n        return constraintName;\n    }\n\n    public void setConstraintName(SQLName constraintName) {\n        this.constraintName = constraintName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropExtPartition.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExtPartition;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * @author shicai.xsc 2018/9/17 上午10:35\n * @since 5.0.0.0\n */\npublic class SQLAlterTableDropExtPartition extends SQLObjectImpl implements SQLAlterTableItem, MySqlObject {\n    private MySqlExtPartition extPartition;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public void setExPartition(MySqlExtPartition x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.extPartition = x;\n    }\n\n    public MySqlExtPartition getExtPartition() {\n        return extPartition;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropForeignKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDropForeignKey extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName indexName;\n\n    public SQLName getIndexName() {\n        return indexName;\n    }\n\n    public void setIndexName(SQLName indexName) {\n        this.indexName = indexName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, indexName);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropIndex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDropIndex extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName indexName;\n\n    public SQLName getIndexName() {\n        return indexName;\n    }\n\n    public void setIndexName(SQLName indexName) {\n        this.indexName = indexName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, indexName);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDropKey extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName keyName;\n\n    public SQLName getKeyName() {\n        return keyName;\n    }\n\n    public void setKeyName(SQLName keyName) {\n        this.keyName = keyName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, keyName);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableDropPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private boolean ifExists;\n    private boolean purge;\n    private final List<SQLExpr> partitions = new ArrayList<SQLExpr>(4);\n\n    public List<SQLExpr> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLExpr partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isPurge() {\n        return purge;\n    }\n\n    public void setPurge(boolean purge) {\n        this.purge = purge;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropPrimaryKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableDropPrimaryKey extends SQLObjectImpl implements SQLAlterTableItem {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropSubpartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableDropSubpartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private List<SQLIntegerExpr> partitionIds = new ArrayList<SQLIntegerExpr>();\n    private List<SQLIntegerExpr> subpartitionIds = new ArrayList<SQLIntegerExpr>();\n\n    public SQLAlterTableDropSubpartition() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitionIds);\n            acceptChild(visitor, subpartitionIds);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLIntegerExpr> getPartitionIds() {\n        return partitionIds;\n    }\n\n    public void setPartitionIds(List<SQLIntegerExpr> partitionIds) {\n        this.partitionIds = partitionIds;\n    }\n\n    public List<SQLIntegerExpr> getSubpartitionIds() {\n        return subpartitionIds;\n    }\n\n    public void setSubpartitionIds(List<SQLIntegerExpr> subpartitionIds) {\n        this.subpartitionIds = subpartitionIds;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableEnableConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableEnableConstraint extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName constraintName;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.constraintName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getConstraintName() {\n        return constraintName;\n    }\n\n    public void setConstraintName(SQLName constraintName) {\n        this.constraintName = constraintName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableEnableKeys.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableEnableKeys extends SQLObjectImpl implements SQLAlterTableItem {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableEnableLifecycle.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableEnableLifecycle extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partition);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableExchangePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableExchangePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private List<SQLExpr> partitions = new ArrayList<SQLExpr>();\n    private SQLExprTableSource table;\n    private Boolean validation;\n\n    public SQLAlterTableExchangePartition() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, table);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLExpr> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partitions.add(x);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName x) {\n        setTable(new SQLExprTableSource(x));\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public void setValidation(boolean validation) {\n        this.validation = validation;\n    }\n\n    public Boolean getValidation() {\n        return validation;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableGroupStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    private List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n\n    public SQLAlterTableGroupStatement() {\n    }\n\n    public SQLAlterTableGroupStatement(DbType dbType) {\n        this.setDbType(dbType);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableImportPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableImportPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    private boolean tablespace;\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(boolean tablespace) {\n        this.tablespace = tablespace;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\n\npublic interface SQLAlterTableItem extends SQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableMergePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.SQLPartitionSpec;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableMergePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLPartitionSpec> partitions = new ArrayList<SQLPartitionSpec>(4);\n    private boolean ifExists;\n    private SQLPartitionSpec overwritePartition;\n    private boolean purge;\n\n    public List<SQLPartitionSpec> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLPartitionSpec x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partitions.add(x);\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLPartitionSpec getOverwritePartition() {\n        return overwritePartition;\n    }\n\n    public void setOverwritePartition(SQLPartitionSpec x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.overwritePartition = x;\n    }\n\n    public boolean isPurge() {\n        return purge;\n    }\n\n    public void setPurge(boolean purge) {\n        this.purge = purge;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableModifyClusteredBy.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableModifyClusteredBy extends SQLObjectImpl implements SQLAlterTableItem {\n    private List<SQLName> clusterColumns = new ArrayList<SQLName>();\n\n    public List<SQLName> getClusterColumns() {\n        return clusterColumns;\n    }\n\n    public void addClusterColumn(SQLName name) {\n        this.clusterColumns.add(name);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, clusterColumns);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableOptimizePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableOptimizePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTablePartition.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2019 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author gouzhiwen\n * @version : SQLAlterTablePartition.java, v 0.1 2019年11月14日 21:50 gouzhiwen Exp $\n */\npublic class SQLAlterTablePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partition);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTablePartitionCount.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTablePartitionCount extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLIntegerExpr count;\n\n    public SQLAlterTablePartitionCount() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, count);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLIntegerExpr getCount() {\n        return count;\n    }\n\n    public void setCount(SQLIntegerExpr count) {\n        if (count != null) {\n            count.setParent(this);\n        }\n        this.count = count;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTablePartitionLifecycle.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTablePartitionLifecycle extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLIntegerExpr lifecycle;\n\n    public SQLAlterTablePartitionLifecycle() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, lifecycle);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLIntegerExpr getLifecycle() {\n        return lifecycle;\n    }\n\n    public void setLifecycle(SQLIntegerExpr lifecycle) {\n        if (lifecycle != null) {\n            lifecycle.setParent(this);\n        }\n        this.lifecycle = lifecycle;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTablePartitionSetProperties.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2019 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author gouzhiwen\n * @version : SQLAlterTablePartition.java, v 0.1 2019年11月14日 21:50 gouzhiwen Exp $\n */\npublic class SQLAlterTablePartitionSetProperties extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n    private final List<SQLAssignItem> partitionProperties = new ArrayList<SQLAssignItem>(4);\n    private SQLExpr location;\n\n    public List<SQLAssignItem> getPartitionProperties() {\n        return partitionProperties;\n    }\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public void setLocation(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.location = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partition);\n            acceptChild(visitor, partitionProperties);\n            acceptChild(visitor, location);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableReOrganizePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableReOrganizePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> names = new ArrayList<SQLName>();\n\n    private final List<SQLObject> partitions = new ArrayList<SQLObject>(4);\n\n    public List<SQLObject> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLObject partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    public List<SQLName> getNames() {\n        return names;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRebuildPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableRebuildPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRecoverPartitions.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableRecoverPartitions extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRename.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableRename extends SQLObjectImpl implements SQLAlterTableItem {\n    protected SQLExprTableSource to;\n\n    public SQLAlterTableRename() {\n    }\n\n    public SQLAlterTableRename(SQLExpr to) {\n        this.setTo(to);\n    }\n\n    public SQLExprTableSource getTo() {\n        return to;\n    }\n\n    public SQLName getToName() {\n        if (to == null) {\n            return null;\n        }\n\n        SQLExpr expr = to.expr;\n\n        if (expr instanceof SQLName) {\n            return (SQLName) expr;\n        }\n\n        return null;\n    }\n\n    public void setTo(SQLExprTableSource to) {\n        if (to != null) {\n            to.setParent(this);\n        }\n        this.to = to;\n    }\n\n    public void setTo(SQLExpr to) {\n        this.setTo(new SQLExprTableSource(to));\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, to);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRenameColumn.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableRenameColumn extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName column;\n    private SQLName to;\n\n    public SQLAlterTableRenameColumn() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, column);\n            acceptChild(visitor, to);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLName column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.column = column;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName to) {\n        if (to != null) {\n            to.setParent(this);\n        }\n        this.to = to;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRenameConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableRenameConstraint extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName constraint;\n    private SQLName to;\n\n    public SQLAlterTableRenameConstraint() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, constraint);\n            acceptChild(visitor, to);\n        }\n        visitor.endVisit(this);\n    }\n    public SQLName getConstraint() {\n        return constraint;\n    }\n\n    public void setConstraint(SQLName constraint) {\n        if (constraint != null) {\n            constraint.setParent(this);\n        }\n        this.constraint = constraint;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName to) {\n        if (to != null) {\n            to.setParent(this);\n        }\n        this.to = to;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRenameIndex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableRenameIndex extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName name;\n    private SQLName to;\n\n    public SQLAlterTableRenameIndex(SQLName name, SQLName to) {\n        this.setName(name);\n        this.setTo(to);\n    }\n\n    public SQLAlterTableRenameIndex() {\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, to);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRenamePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableRenamePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private boolean ifNotExists;\n\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n    private final List<SQLAssignItem> to = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public List<SQLAssignItem> getTo() {\n        return to;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partition);\n            acceptChild(visitor, to);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRepairPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableRepairPartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableReplaceColumn.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableReplaceColumn extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();\n\n    // for mysql\n    private SQLName firstColumn;\n    private SQLName afterColumn;\n\n    private boolean first;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLColumnDefinition> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLColumnDefinition column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public SQLName getFirstColumn() {\n        return firstColumn;\n    }\n\n    public void setFirstColumn(SQLName first) {\n        this.firstColumn = first;\n    }\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public void setFirst(boolean first) {\n        this.first = first;\n    }\n\n    public SQLName getAfterColumn() {\n        return afterColumn;\n    }\n\n    public void setAfterColumn(SQLName after) {\n        this.afterColumn = after;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetComment.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableSetComment extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr comment;\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, comment);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetFileFormat.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableSetFileFormat extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr value;\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, value);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.value = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetLifecycle.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableSetLifecycle extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr lifecycle;\n\n    public SQLExpr getLifecycle() {\n        return lifecycle;\n    }\n\n    public void setLifecycle(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.lifecycle = comment;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, lifecycle);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetLocation.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableSetLocation extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr location;\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public void setLocation(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.location = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, location);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetOption.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableSetOption extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> options = new ArrayList<>();\n    private SQLName on;\n\n    public SQLAlterTableSetOption() {\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void addOption(SQLAssignItem item) {\n        item.setParent(this);\n        this.options.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, options);\n            acceptChild(visitor, on);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getOn() {\n        return on;\n    }\n\n    public void setOn(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.on = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetSchema.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableSetSchema extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr schemaName;\n\n    public SQLExpr getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLExpr schemaName) {\n        if (schemaName != null) {\n            schemaName.setParent(this);\n        }\n        this.schemaName = schemaName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, schemaName);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetSerde.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableSetSerde extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr serde;\n    private List<SQLAssignItem> serdeProperties = new ArrayList<>();\n\n    public SQLExpr getSerde() {\n        return serde;\n    }\n\n    public void setSerde(SQLExpr serde) {\n        if (serde != null) {\n            serde.setParent(this);\n        }\n        this.serde = serde;\n    }\n\n    public List<SQLAssignItem> getSerdeProperties() {\n        return serdeProperties;\n    }\n\n    public void addSerdeProperties(SQLAssignItem item) {\n        item.setParent(this);\n        this.serdeProperties.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, serde);\n            acceptChild(visitor, serdeProperties);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetSerdeProperties.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableSetSerdeProperties extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> serdeProperties = new ArrayList<>();\n    private SQLName on;\n\n    public SQLAlterTableSetSerdeProperties() {\n    }\n\n    public List<SQLAssignItem> getSerdeProperties() {\n        return serdeProperties;\n    }\n\n    public void addSerdeProperties(SQLAssignItem item) {\n        item.setParent(this);\n        this.serdeProperties.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, serdeProperties);\n            acceptChild(visitor, on);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getOn() {\n        return on;\n    }\n\n    public void setOn(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.on = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSetTableSpace.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableSetTableSpace extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLExpr tableSpaceName;\n\n    public SQLExpr getTableSpaceName() {\n        return tableSpaceName;\n    }\n\n    public void setTableSpaceName(SQLExpr tableSpaceName) {\n        if (tableSpaceName != null) {\n            tableSpaceName.setParent(this);\n        }\n        this.tableSpaceName = tableSpaceName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSpaceName);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLStatement, SQLAlterStatement {\n    private boolean only;\n    private SQLExprTableSource tableSource;\n    private List<SQLAlterTableItem> items = new ArrayList<SQLAlterTableItem>();\n\n    // for mysql\n    private boolean ignore;\n    private boolean online;\n    private boolean offline;\n\n    private boolean updateGlobalIndexes;\n    private boolean invalidateGlobalIndexes;\n\n    private boolean removePatiting;\n    private boolean upgradePatiting;\n    private List<SQLAssignItem> tableOptions = new ArrayList<>();\n    private List<SQLName> unsetTableOptions = new ArrayList<>();\n    private SQLPartitionBy partition;\n\n    // odps\n    private boolean mergeSmallFiles;\n    protected boolean range;\n    protected final List<SQLSelectOrderByItem> clusteredBy = new ArrayList<SQLSelectOrderByItem>();\n    protected final List<SQLSelectOrderByItem> sortedBy = new ArrayList<SQLSelectOrderByItem>();\n    protected int buckets;\n    protected int shards;\n\n    private boolean ifExists;\n    private boolean notClustered;\n\n    // clickhouse\n    private SQLName on;\n\n    public SQLAlterTableStatement() {\n    }\n\n    public SQLAlterTableStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public boolean isOnly() {\n        return only;\n    }\n\n    public void setOnly(boolean only) {\n        this.only = only;\n    }\n\n    public boolean isIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(boolean ignore) {\n        this.ignore = ignore;\n    }\n\n    public boolean isOnline() {\n        return online;\n    }\n\n    public void setOnline(boolean online) {\n        this.online = online;\n    }\n\n    public boolean isOffline() {\n        return offline;\n    }\n\n    public void setOffline(boolean offline) {\n        this.offline = offline;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isRemovePatiting() {\n        return removePatiting;\n    }\n\n    public void setRemovePatiting(boolean removePatiting) {\n        this.removePatiting = removePatiting;\n    }\n\n    public boolean isUpgradePatiting() {\n        return upgradePatiting;\n    }\n\n    public void setUpgradePatiting(boolean upgradePatiting) {\n        this.upgradePatiting = upgradePatiting;\n    }\n\n    public boolean isUpdateGlobalIndexes() {\n        return updateGlobalIndexes;\n    }\n\n    public void setUpdateGlobalIndexes(boolean updateGlobalIndexes) {\n        this.updateGlobalIndexes = updateGlobalIndexes;\n    }\n\n    public boolean isInvalidateGlobalIndexes() {\n        return invalidateGlobalIndexes;\n    }\n\n    public void setInvalidateGlobalIndexes(boolean invalidateGlobalIndexes) {\n        this.invalidateGlobalIndexes = invalidateGlobalIndexes;\n    }\n\n    public boolean isMergeSmallFiles() {\n        return mergeSmallFiles;\n    }\n\n    public void setMergeSmallFiles(boolean mergeSmallFiles) {\n        this.mergeSmallFiles = mergeSmallFiles;\n    }\n\n    public List<SQLAlterTableItem> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLAlterTableItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        this.tableSource = tableSource;\n    }\n\n    public void setTableSource(SQLExpr table) {\n        this.setTableSource(new SQLExprTableSource(table));\n    }\n\n    public SQLName getName() {\n        if (getTableSource() == null) {\n            return null;\n        }\n        return (SQLName) getTableSource().getExpr();\n    }\n\n    public long nameHashCode64() {\n        if (getTableSource() == null) {\n            return 0L;\n        }\n        return ((SQLName) getTableSource().getExpr()).nameHashCode64();\n    }\n\n    public void setName(SQLName name) {\n        this.setTableSource(new SQLExprTableSource(name));\n    }\n\n    public List<SQLAssignItem> getTableOptions() {\n        return tableOptions;\n    }\n\n    public List<SQLName> getUnsetTableOptions() {\n        return unsetTableOptions;\n    }\n\n    public SQLPartitionBy getPartition() {\n        return partition;\n    }\n\n    public void setPartition(SQLPartitionBy partition) {\n        this.partition = partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getTableSource());\n            acceptChild(visitor, getItems());\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (tableSource != null) {\n            children.add(tableSource);\n        }\n        children.addAll(this.items);\n        return children;\n    }\n\n    public String getTableName() {\n        if (tableSource == null) {\n            return null;\n        }\n        SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr();\n        if (expr instanceof SQLIdentifierExpr) {\n            return ((SQLIdentifierExpr) expr).getName();\n        } else if (expr instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) expr).getName();\n        }\n\n        return null;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public void setItems(List<SQLAlterTableItem> items) {\n        this.items = items;\n    }\n\n    public boolean isRange() {\n        return range;\n    }\n\n    public void setRange(boolean range) {\n        this.range = range;\n    }\n\n    public List<SQLSelectOrderByItem> getClusteredBy() {\n        return clusteredBy;\n    }\n\n    public void addClusteredByItem(SQLSelectOrderByItem item) {\n        item.setParent(this);\n        this.clusteredBy.add(item);\n    }\n\n    public List<SQLSelectOrderByItem> getSortedBy() {\n        return sortedBy;\n    }\n\n    public void addSortedByItem(SQLSelectOrderByItem item) {\n        item.setParent(this);\n        this.sortedBy.add(item);\n    }\n\n    public int getBuckets() {\n        return buckets;\n    }\n\n    public void setBuckets(int buckets) {\n        this.buckets = buckets;\n    }\n\n    public int getShards() {\n        return shards;\n    }\n\n    public void setShards(int shards) {\n        this.shards = shards;\n    }\n\n    public boolean isNotClustered() {\n        return notClustered;\n    }\n\n    public void setNotClustered(boolean notClustered) {\n        this.notClustered = notClustered;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TABLE;\n    }\n\n    public SQLName getOn() {\n        return on;\n    }\n\n    public void setOn(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.on = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSubpartitionAvailablePartitionNum.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableSubpartitionAvailablePartitionNum extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLIntegerExpr number;\n\n    public SQLIntegerExpr getNumber() {\n        return number;\n    }\n\n    public void setNumber(SQLIntegerExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.number = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, number);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableSubpartitionLifecycle.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableSubpartitionLifecycle extends SQLObjectImpl implements SQLAlterTableItem {\n    private List<SQLIntegerExpr> partitionIds = new ArrayList<SQLIntegerExpr>();\n    private List<SQLIntegerExpr> subpartitionLifeCycle = new ArrayList<SQLIntegerExpr>();\n\n    public SQLAlterTableSubpartitionLifecycle() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitionIds);\n            acceptChild(visitor, subpartitionLifeCycle);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLIntegerExpr> getPartitionIds() {\n        return partitionIds;\n    }\n\n    public void setPartitionIds(List<SQLIntegerExpr> partitionIds) {\n        this.partitionIds = partitionIds;\n    }\n\n    public List<SQLIntegerExpr> getSubpartitionLifeCycle() {\n        return subpartitionLifeCycle;\n    }\n\n    public void setSubpartitionLifeCycle(List<SQLIntegerExpr> subpartitionLifeCycle) {\n        this.subpartitionLifeCycle = subpartitionLifeCycle;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableTouch.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableTouch extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableTruncatePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableTruncatePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLName> partitions = new ArrayList<SQLName>(4);\n    private final List<SQLExpr> partitionValues = new ArrayList<>(4);\n\n    public List<SQLName> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartitionValue(SQLExpr partitionValue) {\n        if (partitionValue != null) {\n            partitionValue.setParent(this);\n        }\n        this.partitionValues.add(partitionValue);\n    }\n    public List<SQLExpr> getPartitionValues() {\n        return partitionValues;\n    }\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableUnarchivePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterTableUnarchivePartition extends SQLObjectImpl implements SQLAlterTableItem {\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>(4);\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLAssignItem partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableValidateConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterTableValidateConstraint extends SQLObjectImpl implements SQLAlterTableItem {\n    private SQLName constraintName;\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.constraintName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getConstraintName() {\n        return constraintName;\n    }\n\n    public void setConstraintName(SQLName constraintName) {\n        this.constraintName = constraintName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTypeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLAlterTypeStatement extends SQLStatementImpl {\n    private SQLName name;\n\n    private boolean compile;\n    private boolean debug;\n    private boolean body;\n    private boolean reuseSettings;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n    public boolean isDebug() {\n        return debug;\n    }\n\n    public void setDebug(boolean debug) {\n        this.debug = debug;\n    }\n\n    public boolean isBody() {\n        return body;\n    }\n\n    public void setBody(boolean body) {\n        this.body = body;\n    }\n\n    public boolean isReuseSettings() {\n        return reuseSettings;\n    }\n\n    public void setReuseSettings(boolean reuseSettings) {\n        this.reuseSettings = reuseSettings;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.name);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterViewRenameStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLAlterViewRenameStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n    private SQLName to;\n\n    private SQLName changeOwnerTo;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n\n    public SQLName getChangeOwnerTo() {\n        return changeOwnerTo;\n    }\n\n    public void setChangeOwnerTo(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.changeOwnerTo = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, to);\n            acceptChild(visitor, changeOwnerTo);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAlterViewStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private boolean force;\n    // protected SQLName   name;\n    protected SQLSelect subQuery;\n    protected boolean ifNotExists;\n\n    protected String algorithm;\n    protected SQLName definer;\n    protected String sqlSecurity;\n\n    protected SQLExprTableSource tableSource;\n\n    protected final List<SQLTableElement> columns = new ArrayList<>();\n    protected final List<SQLAssignItem> options = new ArrayList<>();\n    protected final List<SQLName> unsetOptions = new ArrayList<>();\n\n    private boolean withCheckOption;\n    private boolean withCascaded;\n    private boolean withLocal;\n    private boolean withReadOnly;\n\n    private SQLLiteralExpr comment;\n\n    public SQLAlterViewStatement() {\n    }\n\n    public SQLAlterViewStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public String computeName() {\n        if (tableSource == null) {\n            return null;\n        }\n\n        SQLExpr expr = tableSource.getExpr();\n        if (expr instanceof SQLName) {\n            String name = ((SQLName) expr).getSimpleName();\n            return SQLUtils.normalize(name);\n        }\n\n        return null;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public SQLName getName() {\n        if (tableSource == null) {\n            return null;\n        }\n\n        return (SQLName) tableSource.getExpr();\n    }\n\n    public void setName(SQLName name) {\n        this.setTableSource(new SQLExprTableSource(name));\n    }\n\n    public void setName(String name) {\n        this.setName(new SQLIdentifierExpr(name));\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public boolean isWithCheckOption() {\n        return withCheckOption;\n    }\n\n    public void setWithCheckOption(boolean withCheckOption) {\n        this.withCheckOption = withCheckOption;\n    }\n\n    public boolean isWithCascaded() {\n        return withCascaded;\n    }\n\n    public void setWithCascaded(boolean withCascaded) {\n        this.withCascaded = withCascaded;\n    }\n\n    public boolean isWithLocal() {\n        return withLocal;\n    }\n\n    public void setWithLocal(boolean withLocal) {\n        this.withLocal = withLocal;\n    }\n\n    public boolean isWithReadOnly() {\n        return withReadOnly;\n    }\n\n    public void setWithReadOnly(boolean withReadOnly) {\n        this.withReadOnly = withReadOnly;\n    }\n\n    public SQLSelect getSubQuery() {\n        return subQuery;\n    }\n\n    public void setSubQuery(SQLSelect subQuery) {\n        if (subQuery != null) {\n            subQuery.setParent(this);\n        }\n        this.subQuery = subQuery;\n    }\n\n    public List<SQLTableElement> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLTableElement column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public SQLLiteralExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLLiteralExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public String getAlgorithm() {\n        return algorithm;\n    }\n\n    public void setAlgorithm(String algorithm) {\n        this.algorithm = algorithm;\n    }\n\n    public SQLName getDefiner() {\n        return definer;\n    }\n\n    public void setDefiner(SQLName definer) {\n        if (definer != null) {\n            definer.setParent(this);\n        }\n        this.definer = definer;\n    }\n\n    public String getSqlSecurity() {\n        return sqlSecurity;\n    }\n\n    public void setSqlSecurity(String sqlSecurity) {\n        this.sqlSecurity = sqlSecurity;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.tableSource);\n            acceptChild(visitor, this.columns);\n            acceptChild(visitor, this.comment);\n            acceptChild(visitor, this.subQuery);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (tableSource != null) {\n            children.add(tableSource);\n        }\n        children.addAll(this.columns);\n        if (comment != null) {\n            children.add(comment);\n        }\n        if (subQuery != null) {\n            children.add(subQuery);\n        }\n        return children;\n    }\n\n    public SQLAlterViewStatement clone() {\n        SQLAlterViewStatement x = new SQLAlterViewStatement();\n\n        x.force = force;\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n        x.ifNotExists = ifNotExists;\n\n        x.algorithm = algorithm;\n        if (definer != null) {\n            x.setDefiner(definer.clone());\n        }\n        x.sqlSecurity = sqlSecurity;\n        if (tableSource != null) {\n            x.setTableSource(tableSource.clone());\n        }\n        for (SQLTableElement column : columns) {\n            SQLTableElement column2 = column.clone();\n            column2.setParent(x);\n            x.columns.add(column2);\n        }\n        x.withCheckOption = withCheckOption;\n        x.withCascaded = withCascaded;\n        x.withLocal = withLocal;\n        x.withReadOnly = withReadOnly;\n\n        if (comment != null) {\n            x.setComment(comment.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.VIEW;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public List<SQLName> getUnsetOptions() {\n        return unsetOptions;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAnalyzeTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLAnalyzeTableStatement extends SQLStatementImpl {\n    protected final List<SQLExprTableSource> tableSources = new ArrayList<SQLExprTableSource>();\n\n    private SQLPartitionRef partition;\n    private boolean forColums;\n    private List<SQLName> columns = new ArrayList<>();\n    private boolean cacheMetadata;\n    private boolean noscan;\n    private boolean computeStatistics;\n\n    private SQLIdentifierExpr adbSchema; // for ADB\n    private List<SQLIdentifierExpr> adbColumns = new ArrayList<SQLIdentifierExpr>(); // for ADB\n    private List<SQLIdentifierExpr> adbColumnsGroup = new ArrayList<SQLIdentifierExpr>(); // for ADB\n    private SQLExpr adbWhere; // for ADB\n\n    public SQLAnalyzeTableStatement() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, tableSources);\n            this.acceptChild(visitor, partition);\n            this.acceptChild(visitor, columns);\n            this.acceptChild(visitor, adbSchema);\n            this.acceptChild(visitor, adbColumns);\n            this.acceptChild(visitor, adbColumnsGroup);\n            this.acceptChild(visitor, adbWhere);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLExprTableSource> getTables() {\n        return tableSources;\n    }\n\n    public SQLExprTableSource getTable() {\n        if (tableSources.isEmpty()) {\n            return null;\n        }\n\n        if (tableSources.size() == 1) {\n            return tableSources.get(0);\n        }\n\n        throw new UnsupportedOperationException();\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(this);\n        }\n\n        if (tableSources.isEmpty()) {\n            if (table == null) {\n                return;\n            }\n\n            tableSources.add(table);\n            return;\n        }\n\n        if (tableSources.size() == 1) {\n            if (table == null) {\n                this.tableSources.remove(0);\n            } else {\n                tableSources.set(0, table);\n            }\n            return;\n        }\n\n        throw new UnsupportedOperationException();\n    }\n\n    public SQLIdentifierExpr getAdbSchema() {\n        return adbSchema;\n    }\n\n    public void setAdbSchema(SQLIdentifierExpr adbSchema) {\n        this.adbSchema = adbSchema;\n    }\n\n    public List<SQLIdentifierExpr> getAdbColumns() {\n        return adbColumns;\n    }\n\n    public void setAdbColumns(List<SQLIdentifierExpr> adbColumns) {\n        this.adbColumns = adbColumns;\n    }\n\n    public List<SQLIdentifierExpr> getAdbColumnsGroup() {\n        return adbColumnsGroup;\n    }\n\n    public void setAdbColumnsGroup(List<SQLIdentifierExpr> adbColumnsGroup) {\n        this.adbColumnsGroup = adbColumnsGroup;\n    }\n\n    public SQLExpr getAdbWhere() {\n        return adbWhere;\n    }\n\n    public void setAdbWhere(SQLExpr adbWhere) {\n        this.adbWhere = adbWhere;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public SQLPartitionRef getPartition() {\n        return partition;\n    }\n\n    public void setPartition(SQLPartitionRef x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partition = x;\n    }\n\n    public boolean isForColums() {\n        return forColums;\n    }\n\n    public void setForColums(boolean forColums) {\n        this.forColums = forColums;\n    }\n\n    public boolean isCacheMetadata() {\n        return cacheMetadata;\n    }\n\n    public void setCacheMetadata(boolean cacheMetadata) {\n        this.cacheMetadata = cacheMetadata;\n    }\n\n    public boolean isNoscan() {\n        return noscan;\n    }\n\n    public void setNoscan(boolean noscan) {\n        this.noscan = noscan;\n    }\n\n    public boolean isComputeStatistics() {\n        return computeStatistics;\n    }\n\n    public void setComputeStatistics(boolean computeStatistics) {\n        this.computeStatistics = computeStatistics;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLArchiveTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLArchiveTableStatement extends SQLStatementImpl {\n    private SQLName table;\n\n    private SQLName type;\n    private List<SQLIntegerExpr> spIdList = new ArrayList<SQLIntegerExpr>();\n    private List<SQLIntegerExpr> pIdList = new ArrayList<SQLIntegerExpr>();\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.table);\n            acceptChild(visitor, this.type);\n\n            acceptChild(visitor, spIdList);\n            acceptChild(visitor, pIdList);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName table) {\n        if (table != null) {\n            table.setParent(this);\n        }\n        this.table = table;\n    }\n\n    public SQLName getType() {\n        return type;\n    }\n\n    public void setType(SQLName type) {\n        if (type != null) {\n            type.setParent(this);\n        }\n        this.type = type;\n    }\n\n    public List<SQLIntegerExpr> getSpIdList() {\n        return spIdList;\n    }\n\n    public List<SQLIntegerExpr> getpIdList() {\n        return pIdList;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAssignItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class SQLAssignItem extends SQLExprImpl implements SQLReplaceable {\n    private SQLExpr target;\n    private SQLExpr value;\n\n    public SQLAssignItem() {\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLAssignItem that = (SQLAssignItem) o;\n\n        if (target != null ? !target.equals(that.target) : that.target != null) {\n            return false;\n        }\n        return value != null ? value.equals(that.value) : that.value == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = target != null ? target.hashCode() : 0;\n        result = 31 * result + (value != null ? value.hashCode() : 0);\n        return result;\n    }\n\n    public SQLAssignItem(SQLExpr target, SQLExpr value) {\n        setTarget(target);\n        setValue(value);\n    }\n\n    public SQLAssignItem clone() {\n        SQLAssignItem x = new SQLAssignItem();\n        if (target != null) {\n            x.setTarget(target.clone());\n        }\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return null;\n    }\n\n    public SQLExpr getTarget() {\n        return target;\n    }\n\n    public void setTarget(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.target = x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.value = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.target);\n            acceptChild(visitor, this.value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.target == expr) {\n            setTarget(target);\n            return true;\n        }\n\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBackupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLBackupStatement extends SQLStatementImpl {\n    private SQLName type;\n    private SQLName action;\n    private List<SQLCharExpr> properties = new ArrayList<SQLCharExpr>();\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.type);\n            acceptChild(visitor, this.action);\n\n            acceptChild(visitor, properties);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getType() {\n        return type;\n    }\n\n    public void setType(SQLName type) {\n        this.type = type;\n    }\n\n    public SQLName getAction() {\n        return action;\n    }\n\n    public void setAction(SQLName action) {\n        this.action = action;\n    }\n\n    public List<SQLCharExpr> getProperties() {\n        return properties;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBeginStatement.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://docs.pingcap.com/tidb/stable/sql-statement-begin\">BEGIN | TiDB SQL Statement Reference</a>\n */\npublic class SQLBeginStatement extends SQLStatementImpl implements SQLReplaceable {\n    //tidb\n    private SQLName tidbTxnMode;\n\n    public SQLBeginStatement() {\n    }\n\n    public SQLBeginStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLName getTidbTxnMode() {\n        return tidbTxnMode;\n    }\n\n    public void setTidbTxnMode(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.tidbTxnMode = x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tidbTxnMode);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.tidbTxnMode == expr) {\n            setTidbTxnMode((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.singletonList(tidbTxnMode);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBlockStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLBlockStatement extends SQLStatementImpl {\n    private boolean isDollarQuoted;\n    private String dollarQuoteTagName;\n    private String labelName;\n    private String endLabel;\n    private List<SQLParameter> parameters = new ArrayList<SQLParameter>();\n    private List<SQLStatement> statementList = new ArrayList<SQLStatement>();\n    public SQLStatement exception;\n    private boolean endOfCommit;\n    private boolean haveBeginEnd;\n    private String language;\n\n    public SQLBlockStatement() {\n        haveBeginEnd = true;\n    }\n\n    public List<SQLStatement> getStatementList() {\n        return statementList;\n    }\n\n    public void setStatementList(List<SQLStatement> statementList) {\n        this.statementList = statementList;\n    }\n\n    public boolean isDollarQuoted() {\n        return isDollarQuoted;\n    }\n\n    public void setIsDollarQuoted(boolean isDollarQuoted) {\n        this.isDollarQuoted = isDollarQuoted;\n    }\n\n    public String getDollarQuoteTagName() {\n        return dollarQuoteTagName;\n    }\n\n    public void setDollarQuoteTagName(String dollarQuoteTagName) {\n        this.dollarQuoteTagName = dollarQuoteTagName;\n    }\n\n    public String getLanguage() {\n        return language;\n    }\n\n    public void setLanguage(String language) {\n        this.language = language;\n    }\n\n    public String getLabelName() {\n        return labelName;\n    }\n\n    public void setLabelName(String labelName) {\n        this.labelName = labelName;\n    }\n\n    public boolean isHaveBeginEnd() {\n        return haveBeginEnd;\n    }\n\n    public void setHaveBeginEnd(boolean haveBeginEnd) {\n        this.haveBeginEnd = haveBeginEnd;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, parameters);\n            acceptChild(visitor, statementList);\n            acceptChild(visitor, exception);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<SQLParameter> parameters) {\n        this.parameters = parameters;\n    }\n\n    public SQLStatement getException() {\n        return exception;\n    }\n\n    public void setException(SQLStatement exception) {\n        if (exception != null) {\n            exception.setParent(this);\n        }\n        this.exception = exception;\n    }\n\n    public String getEndLabel() {\n        return endLabel;\n    }\n\n    public void setEndLabel(String endLabel) {\n        this.endLabel = endLabel;\n    }\n\n    public SQLBlockStatement clone() {\n        SQLBlockStatement x = new SQLBlockStatement();\n        x.labelName = labelName;\n        x.endLabel = endLabel;\n\n        for (SQLParameter p : parameters) {\n            SQLParameter p2 = p.clone();\n            p2.setParent(x);\n            x.parameters.add(p2);\n        }\n\n        for (SQLStatement stmt : statementList) {\n            SQLStatement stmt2 = stmt.clone();\n            stmt2.setParent(x);\n            x.statementList.add(stmt2);\n        }\n\n        if (exception != null) {\n            x.setException(exception.clone());\n        }\n\n        return x;\n    }\n\n    public SQLParameter findParameter(long hash) {\n        for (SQLParameter param : this.parameters) {\n            if (param.getName().nameHashCode64() == hash) {\n                return param;\n            }\n        }\n\n        return null;\n    }\n\n    public boolean isEndOfCommit() {\n        return endOfCommit;\n    }\n\n    public void setEndOfCommit(boolean value) {\n        this.endOfCommit = value;\n    }\n\n    public boolean replace(SQLStatement cmp, SQLStatement target) {\n        for (int i = 0; i < statementList.size(); i++) {\n            if (statementList.get(i) == cmp) {\n                statementList.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBreakStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLBreakStatement extends SQLStatementImpl {\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLBuildTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLBuildTableStatement extends SQLStatementImpl {\n    private SQLName table;\n    private SQLIntegerExpr version;\n    private boolean withSplit;\n    private boolean force;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.table);\n            acceptChild(visitor, this.version);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName table) {\n        this.table = table;\n    }\n\n    public SQLIntegerExpr getVersion() {\n        return version;\n    }\n\n    public void setVersion(SQLIntegerExpr version) {\n        this.version = version;\n    }\n\n    public boolean isWithSplit() {\n        return withSplit;\n    }\n\n    public void setWithSplit(boolean withSplit) {\n        this.withSplit = withSplit;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCallStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCallStatement extends SQLStatementImpl {\n    private boolean brace;\n\n    private SQLVariantRefExpr outParameter;\n\n    private SQLName procedureName;\n\n    private final List<SQLExpr> parameters = new ArrayList<SQLExpr>();\n\n    public SQLCallStatement() {\n    }\n\n    public SQLCallStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLVariantRefExpr getOutParameter() {\n        return outParameter;\n    }\n\n    public void setOutParameter(SQLVariantRefExpr outParameter) {\n        this.outParameter = outParameter;\n    }\n\n    public SQLName getProcedureName() {\n        return procedureName;\n    }\n\n    public void setProcedureName(SQLName procedureName) {\n        this.procedureName = procedureName;\n    }\n\n    public List<SQLExpr> getParameters() {\n        return parameters;\n    }\n\n    public boolean isBrace() {\n        return brace;\n    }\n\n    public void setBrace(boolean brace) {\n        this.brace = brace;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.outParameter);\n            acceptChild(visitor, this.procedureName);\n            acceptChild(visitor, this.parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.add(outParameter);\n        children.add(procedureName);\n        children.addAll(parameters);\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCancelJobStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCancelJobStatement extends SQLStatementImpl {\n    private SQLName jobName;\n    private boolean isImport;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.jobName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getJobName() {\n        return jobName;\n    }\n\n    public void setJobName(SQLName jobName) {\n        this.jobName = jobName;\n    }\n\n    public boolean isImport() {\n        return isImport;\n    }\n\n    public void setImport(boolean anImport) {\n        isImport = anImport;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCharacterDataType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.sql.Types;\nimport java.util.List;\n\npublic class SQLCharacterDataType extends SQLDataTypeImpl {\n    private String charSetName;\n    private String collate;\n\n    private String charType;\n    private boolean hasBinary;\n\n    public List<SQLCommentHint> hints;\n\n    public static final String CHAR_TYPE_BYTE = \"BYTE\";\n    public static final String CHAR_TYPE_CHAR = \"CHAR\";\n\n    public SQLCharacterDataType(String name) {\n        super(name);\n    }\n\n    public SQLCharacterDataType(String name, int precision) {\n        super(name, precision);\n    }\n\n    public String getCharSetName() {\n        return charSetName;\n    }\n\n    public void setCharSetName(String charSetName) {\n        this.charSetName = charSetName;\n    }\n\n    public boolean isHasBinary() {\n        return hasBinary;\n    }\n\n    public void setHasBinary(boolean hasBinary) {\n        this.hasBinary = hasBinary;\n    }\n\n    public String getCollate() {\n        return collate;\n    }\n\n    public void setCollate(String collate) {\n        this.collate = collate;\n    }\n\n    public String getCharType() {\n        return charType;\n    }\n\n    public void setCharType(String charType) {\n        this.charType = charType;\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public int getLength() {\n        if (this.arguments.size() == 1) {\n            SQLExpr arg = this.arguments.get(0);\n            if (arg instanceof SQLIntegerExpr) {\n                return ((SQLIntegerExpr) arg).getNumber().intValue();\n            }\n        }\n\n        return -1;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < arguments.size(); i++) {\n                SQLExpr arg = arguments.get(i);\n                if (arg != null) {\n                    arg.accept(visitor);\n                }\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public SQLCharacterDataType clone() {\n        SQLCharacterDataType x = new SQLCharacterDataType(getName());\n\n        super.cloneTo(x);\n\n        x.charSetName = charSetName;\n        x.collate = collate;\n        x.charType = charType;\n        x.hasBinary = hasBinary;\n\n        return x;\n    }\n\n    @Override\n    public String toString() {\n        return SQLUtils.toSQLString(this);\n    }\n\n    public int jdbcType() {\n        long nameNash = nameHashCode64();\n\n        if (nameNash == FnvHash.Constants.NCHAR) {\n            return Types.NCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.CHAR || nameNash == FnvHash.Constants.JSON) {\n            return Types.CHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.VARCHAR\n                || nameNash == FnvHash.Constants.VARCHAR2\n                || nameNash == FnvHash.Constants.STRING) {\n            return Types.VARCHAR;\n        }\n\n        if (nameNash == FnvHash.Constants.NVARCHAR || nameNash == FnvHash.Constants.NVARCHAR2) {\n            return Types.NVARCHAR;\n        }\n\n        return Types.OTHER;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCheck.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCheck extends SQLConstraintImpl implements SQLTableElement, SQLTableConstraint, SQLReplaceable {\n    private SQLExpr expr;\n    private Boolean enforced;\n\n    public SQLCheck() {\n    }\n\n    public SQLCheck(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (getName() != null) {\n                getName().accept(visitor);\n            }\n\n            if (expr != null) {\n                expr.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public void cloneTo(SQLCheck x) {\n        super.cloneTo(x);\n\n        if (expr != null) {\n            x.expr = expr.clone();\n        }\n\n        x.enforced = enforced;\n    }\n\n    public SQLCheck clone() {\n        SQLCheck x = new SQLCheck();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        if (getName() == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        if (getComment() == expr) {\n            setComment(target);\n            return true;\n        }\n        return false;\n    }\n\n    public Boolean getEnforced() {\n        return enforced;\n    }\n\n    public void setEnforced(Boolean enforced) {\n        this.enforced = enforced;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCloneTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCloneTableStatement extends SQLStatementImpl {\n    protected SQLExprTableSource from;\n\n    protected List<SQLAssignItem> partitions = new ArrayList<>();\n\n    protected SQLExprTableSource to;\n\n    protected boolean ifExistsOverwrite;\n    protected boolean ifExistsIgnore;\n\n    public SQLCloneTableStatement() {\n    }\n\n    public SQLCloneTableStatement(SQLExpr to) {\n        this.setTo(to);\n    }\n\n    public SQLExprTableSource getTo() {\n        return to;\n    }\n\n    public void setTo(SQLExprTableSource to) {\n        if (to != null) {\n            to.setParent(this);\n        }\n        this.to = to;\n    }\n\n    public void setTo(SQLExpr to) {\n        this.setTo(new SQLExprTableSource(to));\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public SQLName getToName() {\n        if (to == null) {\n            return null;\n        }\n\n        SQLExpr expr = to.expr;\n\n        if (expr instanceof SQLName) {\n            return (SQLName) expr;\n        }\n\n        return null;\n    }\n\n    public SQLExprTableSource getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.from = x;\n    }\n\n    public void setFrom(SQLName x) {\n        this.setFrom(new SQLExprTableSource(x));\n    }\n\n    public boolean isIfExistsOverwrite() {\n        return ifExistsOverwrite;\n    }\n\n    public void setIfExistsOverwrite(boolean ifExistsOverwrite) {\n        this.ifExistsOverwrite = ifExistsOverwrite;\n    }\n\n    public boolean isIfExistsIgnore() {\n        return ifExistsIgnore;\n    }\n\n    public void setIfExistsIgnore(boolean ifExistsIgnore) {\n        this.ifExistsIgnore = ifExistsIgnore;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, from);\n            acceptChild(visitor, to);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCloseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * MySql cursor close statement\n *\n * @author zz [455910092@qq.com]\n */\npublic class SQLCloseStatement extends SQLStatementImpl {\n    //cursor name\n    private SQLName cursorName;\n\n    public SQLName getCursorName() {\n        return cursorName;\n    }\n\n    public void setCursorName(String cursorName) {\n        setCursorName(new SQLIdentifierExpr(cursorName));\n    }\n\n    public void setCursorName(SQLName cursorName) {\n        if (cursorName != null) {\n            cursorName.setParent(this);\n        }\n        this.cursorName = cursorName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, cursorName);\n        }\n        visitor.endVisit(this);\n\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnCheck.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLColumnCheck extends SQLConstraintImpl implements SQLColumnConstraint, SQLReplaceable {\n    private SQLExpr expr;\n    protected Boolean enforced;\n\n    public SQLColumnCheck() {\n    }\n\n    public SQLColumnCheck(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public Boolean getEnforced() {\n        return enforced;\n    }\n\n    public void setEnforced(Boolean enforced) {\n        this.enforced = enforced;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getExpr());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLColumnCheck clone() {\n        SQLColumnCheck x = new SQLColumnCheck();\n\n        super.cloneTo(x);\n\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        if (getName() == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        if (getComment() == expr) {\n            setComment(target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\npublic interface SQLColumnConstraint extends SQLConstraint, SQLTableElement {\n    SQLColumnConstraint clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefault.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLColumnDefault extends SQLConstraintImpl implements SQLColumnConstraint, SQLReplaceable {\n    private SQLExpr defaultExpr;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getDefaultExpr());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLColumnDefault clone() {\n        SQLColumnDefault x = new SQLColumnDefault();\n\n        super.cloneTo(x);\n\n        if (defaultExpr != null) {\n            x.setDefaultExpr(defaultExpr.clone());\n        }\n\n        return x;\n    }\n\n    public void setDefaultExpr(SQLExpr defaultExpr) {\n        this.defaultExpr = defaultExpr;\n    }\n\n    public SQLExpr getDefaultExpr() {\n        return defaultExpr;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.defaultExpr == expr) {\n            setDefaultExpr(target);\n            return true;\n        }\n\n        if (getName() == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        if (getComment() == expr) {\n            setComment(target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.sql.Types;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement, SQLObjectWithDataType, SQLReplaceable, SQLDbTypedObject {\n    protected DbType dbType;\n\n    protected boolean ifNotExists;\n    protected SQLName name;\n    protected SQLDataType dataType;\n    protected SQLExpr defaultExpr;\n    protected final List<SQLColumnConstraint> constraints = new ArrayList<SQLColumnConstraint>(0);\n    protected boolean disableNovalidate;\n    protected SQLExpr comment;\n\n    protected Boolean enable;\n    protected Boolean validate;\n    protected Boolean rely;\n\n    // for mysql\n    protected boolean autoIncrement;\n    protected SQLExpr onUpdate;\n    protected SQLExpr format;\n    protected SQLExpr storage;\n    protected SQLExpr charsetExpr;\n    protected SQLExpr collateExpr;\n    protected SQLExpr asExpr;\n    protected boolean stored;\n    protected boolean virtual;\n    protected boolean visible;\n    protected AutoIncrementType sequenceType;\n    protected boolean preSort; // for ads\n    protected int preSortOrder; // for ads\n    protected Identity identity;\n\n    // for ads\n    protected SQLExpr generatedAlwaysAs;\n    protected SQLExpr delimiter; // for ads\n    protected SQLExpr delimiterTokenizer; // for ads3.0 multivalue\n    protected SQLExpr nlpTokenizer; // for ads3.0 multivalue\n    protected SQLExpr valueType; // for ads3.0 multivalue\n    protected boolean disableIndex; //for ads\n    protected SQLExpr jsonIndexAttrsExpr;    // for ads\n    protected SQLAnnIndex annIndex;\n    private SQLExpr unitCount;\n    private SQLExpr unitIndex;\n    private SQLExpr step;\n    private SQLExpr encode;\n    private SQLExpr compression;\n    protected SQLCharExpr aggType; // for starrocks\n    protected SQLCharExpr bitmap; // for starrocks\n    protected SQLCharExpr indexComment; // for starrocks\n\n    // for aliyun data lake anlytics\n    private List<SQLAssignItem> mappedBy;\n    private List<SQLAssignItem> colProperties;\n\n    protected SQLIntegerExpr blockSize; // for impala for kudu\n\n    private boolean generateByDefault;\n\n    public SQLCharExpr getIndexComment() {\n        return indexComment;\n    }\n\n    public void setIndexComment(SQLCharExpr indexComment) {\n        this.indexComment = indexComment;\n    }\n\n    public SQLCharExpr getBitmap() {\n        return bitmap;\n    }\n\n    public void setBitmap(SQLCharExpr bitmap) {\n        this.bitmap = bitmap;\n    }\n\n    public SQLCharExpr getAggType() {\n        return aggType;\n    }\n\n    public void setAggType(SQLCharExpr aggType) {\n        this.aggType = aggType;\n    }\n\n    public SQLColumnDefinition() {\n    }\n\n    public SQLColumnDefinition(SQLName name) {\n        this.setName(name);\n    }\n\n    public SQLColumnDefinition(String name, SQLDataType dataType) {\n        setName(name);\n        setDataType(dataType);\n    }\n\n    public Identity getIdentity() {\n        return identity;\n    }\n\n    // for sqlserver\n    public void setIdentity(Identity identity) {\n        if (identity != null) {\n            identity.setParent(this);\n        }\n        this.identity = identity;\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public Boolean getValidate() {\n        return validate;\n    }\n\n    public void setValidate(Boolean validate) {\n        this.validate = validate;\n    }\n\n    public Boolean getRely() {\n        return rely;\n    }\n\n    public void setRely(Boolean rely) {\n        this.rely = rely;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public String getColumnName() {\n        if (name == null) {\n            return null;\n        }\n\n        return name.getSimpleName();\n    }\n\n    public long nameHashCode64() {\n        if (name == null) {\n            return 0;\n        }\n\n        return name.hashCode64();\n    }\n\n    public String getNameAsString() {\n        if (name == null) {\n            return null;\n        }\n\n        return name.toString();\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public void setName(String name) {\n        this.setName(new SQLIdentifierExpr(name));\n    }\n\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    public int jdbcType() {\n        if (dataType == null) {\n            return Types.OTHER;\n        }\n\n        return dataType.jdbcType();\n    }\n\n    public void setDataType(SQLDataType dataType) {\n        if (dataType != null) {\n            dataType.setParent(this);\n        }\n        this.dataType = dataType;\n    }\n\n    public SQLExpr getDefaultExpr() {\n        return defaultExpr;\n    }\n\n    public void setDefaultExpr(SQLExpr defaultExpr) {\n        if (defaultExpr != null) {\n            defaultExpr.setParent(this);\n        }\n        this.defaultExpr = defaultExpr;\n    }\n\n    public List<SQLColumnConstraint> getConstraints() {\n        return constraints;\n    }\n\n    public boolean isPrimaryKey() {\n        for (SQLColumnConstraint constraint : constraints) {\n            if (constraint instanceof SQLColumnPrimaryKey) {\n                return true;\n            }\n        }\n\n        if (parent instanceof SQLCreateTableStatement) {\n            return ((SQLCreateTableStatement) parent)\n                    .isPrimaryColumn(\n                            nameHashCode64());\n        }\n\n        return false;\n    }\n\n    public boolean isOnlyPrimaryKey() {\n        for (SQLColumnConstraint constraint : constraints) {\n            if (constraint instanceof SQLColumnPrimaryKey) {\n                return true;\n            }\n        }\n\n        if (parent instanceof SQLCreateTableStatement) {\n            return ((SQLCreateTableStatement) parent)\n                    .isPrimaryColumn(\n                            nameHashCode64());\n        }\n\n        return false;\n    }\n\n    public boolean isPartitionBy() {\n        if (!(parent instanceof SQLCreateTableStatement)) {\n            return false;\n        }\n\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) parent;\n        final SQLPartitionBy partitioning = stmt.getPartitioning();\n        if (partitioning == null) {\n            return false;\n        }\n\n        if (name == null) {\n            return false;\n        }\n\n        return partitioning.isPartitionByColumn(\n                nameHashCode64());\n    }\n\n    public void addConstraint(SQLColumnConstraint constraint) {\n        if (constraint != null) {\n            constraint.setParent(this);\n        }\n        this.constraints.add(constraint);\n    }\n\n    public boolean isDisableNovalidate() {\n        return disableNovalidate;\n    }\n\n    public void setDisableNovalidate(boolean disableNovalidate) {\n        this.disableNovalidate = disableNovalidate;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, name);\n            this.acceptChild(visitor, dataType);\n            this.acceptChild(visitor, defaultExpr);\n            this.acceptChild(visitor, constraints);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(String comment) {\n        SQLCharExpr expr;\n        if (comment == null) {\n            expr = null;\n        } else {\n            expr = new SQLCharExpr(comment);\n        }\n        this.setComment(expr);\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public boolean isVirtual() {\n        return virtual;\n    }\n\n    public void setVirtual(boolean virtual) {\n        this.virtual = virtual;\n    }\n\n    public boolean isStored() {\n        return stored;\n    }\n\n    public void setStored(boolean stored) {\n        this.stored = stored;\n    }\n\n    public SQLExpr getCharsetExpr() {\n        return charsetExpr;\n    }\n\n    public void setCharsetExpr(SQLExpr charsetExpr) {\n        if (charsetExpr != null) {\n            charsetExpr.setParent(this);\n        }\n        this.charsetExpr = charsetExpr;\n    }\n\n    public SQLExpr getCollateExpr() {\n        return collateExpr;\n    }\n\n    public void setCollateExpr(SQLExpr x) {\n        if (charsetExpr != null) {\n            charsetExpr.setParent(this);\n        }\n        this.collateExpr = x;\n    }\n\n    public SQLExpr getAsExpr() {\n        return asExpr;\n    }\n\n    public void setAsExpr(SQLExpr asExpr) {\n        if (charsetExpr != null) {\n            charsetExpr.setParent(this);\n        }\n        this.asExpr = asExpr;\n    }\n\n    public boolean isAutoIncrement() {\n        return autoIncrement;\n    }\n\n    public void setAutoIncrement(boolean autoIncrement) {\n        this.autoIncrement = autoIncrement;\n    }\n\n    public SQLExpr getOnUpdate() {\n        return onUpdate;\n    }\n\n    public void setOnUpdate(SQLExpr onUpdate) {\n        this.onUpdate = onUpdate;\n    }\n\n    public SQLExpr getFormat() {\n        return format;\n    }\n\n    public void setFormat(SQLExpr format) {\n        this.format = format;\n    }\n\n    public SQLExpr getStorage() {\n        return storage;\n    }\n\n    public void setStorage(SQLExpr storage) {\n        this.storage = storage;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (defaultExpr == expr) {\n            setDefaultExpr(target);\n            return true;\n        }\n\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        if (comment == expr) {\n            setComment(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public void setUnitCount(SQLExpr unitCount) {\n        if (unitCount != null) {\n            unitCount.setParent(this);\n        }\n        this.unitCount = unitCount;\n    }\n\n    public boolean isGenerateByDefault() {\n        return generateByDefault;\n    }\n\n    public void setGenerateByDefault(boolean generateByDefault) {\n        this.generateByDefault = generateByDefault;\n    }\n\n    public static class Identity extends SQLObjectImpl implements SQLExpr{\n        private Integer seed;\n        private Integer increment;\n\n        private boolean notForReplication;\n        private boolean cycle;\n\n        private Integer minValue;\n        private Integer maxValue;\n\n        public Identity() {\n        }\n\n        public Integer getSeed() {\n            return seed;\n        }\n\n        public void setSeed(Integer seed) {\n            this.seed = seed;\n        }\n\n        public Integer getIncrement() {\n            return increment;\n        }\n\n        public void setIncrement(Integer increment) {\n            this.increment = increment;\n        }\n\n        public boolean isCycle() {\n            return cycle;\n        }\n\n        public void setCycle(boolean cycle) {\n            this.cycle = cycle;\n        }\n\n        public Integer getMinValue() {\n            return minValue;\n        }\n\n        public void setMinValue(Integer minValue) {\n            this.minValue = minValue;\n        }\n\n        public Integer getMaxValue() {\n            return maxValue;\n        }\n\n        public void setMaxValue(Integer maxValue) {\n            this.maxValue = maxValue;\n        }\n\n        public boolean isNotForReplication() {\n            return notForReplication;\n        }\n\n        public void setNotForReplication(boolean notForReplication) {\n            this.notForReplication = notForReplication;\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor visitor) {\n            visitor.visit(this);\n            visitor.endVisit(this);\n        }\n\n        public Identity clone() {\n            Identity x = new Identity();\n            x.seed = seed;\n            x.increment = increment;\n            x.cycle = cycle;\n            x.minValue = minValue;\n            x.maxValue = maxValue;\n            x.notForReplication = notForReplication;\n            return x;\n        }\n\n        @Override\n        public List<SQLObject> getChildren() {\n            return null;\n        }\n    }\n\n    public String computeAlias() {\n        String alias = null;\n\n        if (name instanceof SQLIdentifierExpr) {\n            alias = ((SQLIdentifierExpr) name).getName();\n        } else if (name instanceof SQLPropertyExpr) {\n            alias = ((SQLPropertyExpr) name).getName();\n        }\n\n        return SQLUtils.normalize(alias);\n    }\n\n    public SQLColumnDefinition clone() {\n        SQLColumnDefinition x = new SQLColumnDefinition();\n        x.setDbType(dbType);\n\n        if (name != null) {\n            x.setName(name.clone());\n        }\n\n        if (dataType != null) {\n            x.setDataType(dataType.clone());\n        }\n\n        if (defaultExpr != null) {\n            x.setDefaultExpr(defaultExpr.clone());\n        }\n\n        for (SQLColumnConstraint item : constraints) {\n            SQLColumnConstraint itemCloned = item.clone();\n            itemCloned.setParent(x);\n            x.constraints.add(itemCloned);\n        }\n\n        if (comment != null) {\n            x.setComment(comment.clone());\n        }\n\n        x.enable = enable;\n        x.validate = validate;\n        x.rely = rely;\n\n        x.autoIncrement = autoIncrement;\n\n        if (onUpdate != null) {\n            x.setOnUpdate(onUpdate.clone());\n        }\n\n        if (format != null) {\n            x.setFormat(format.clone());\n        }\n\n        if (storage != null) {\n            x.setStorage(storage.clone());\n        }\n\n        if (charsetExpr != null) {\n            x.setCharsetExpr(charsetExpr.clone());\n        }\n\n        if (collateExpr != null) {\n            x.setCollateExpr(collateExpr.clone());\n        }\n\n        if (asExpr != null) {\n            x.setAsExpr(asExpr.clone());\n        }\n\n        x.stored = stored;\n        x.virtual = virtual;\n\n        if (identity != null) {\n            x.setIdentity(identity.clone());\n        }\n\n        if (delimiter != null) {\n            x.setDelimiter(delimiter.clone());\n        }\n\n        if (valueType != null) {\n            x.setValueType(valueType.clone());\n        }\n\n        if (nlpTokenizer != null) {\n            x.setNplTokenizer(nlpTokenizer.clone());\n        }\n\n        x.preSort = preSort;\n        x.preSortOrder = preSortOrder;\n\n        if (jsonIndexAttrsExpr != null) {\n            x.setJsonIndexAttrsExpr(jsonIndexAttrsExpr.clone());\n        }\n\n        if (annIndex != null) {\n            x.setAnnIndex(annIndex.clone());\n        }\n\n        if (mappedBy != null) {\n            for (SQLAssignItem item : mappedBy) {\n                SQLAssignItem item2 = item.clone();\n                item2.setParent(this);\n                if (x.mappedBy == null) {\n                    x.mappedBy = new ArrayList<SQLAssignItem>();\n                }\n                x.mappedBy.add(item2);\n            }\n        }\n\n        if (colProperties != null) {\n            for (SQLAssignItem item : colProperties) {\n                SQLAssignItem item2 = item.clone();\n                item2.setParent(this);\n                if (x.colProperties == null) {\n                    x.colProperties = new ArrayList<SQLAssignItem>();\n                }\n                x.colProperties.add(item2);\n            }\n        }\n\n        return x;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public void simplify() {\n        enable = null;\n        validate = null;\n        rely = null;\n\n        if (this.name instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) this.name;\n            String columnName = identExpr.getName();\n            String normalized = SQLUtils.normalize(columnName, dbType);\n            if (normalized != columnName) {\n                this.setName(normalized);\n            }\n        }\n    }\n\n    @Deprecated\n    public boolean containsNotNullConstaint() {\n        return containsNotNullConstraint();\n    }\n    public boolean containsNotNullConstraint() {\n        for (SQLColumnConstraint constraint : this.constraints) {\n            if (constraint instanceof SQLNotNullConstraint) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public SQLExpr getGeneratedAlwaysAs() {\n        return generatedAlwaysAs;\n    }\n\n    public void setGeneratedAlwaysAs(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.generatedAlwaysAs = x;\n    }\n\n    public boolean isVisible() {\n        return visible;\n    }\n\n    public void setVisible(boolean visible) {\n        this.visible = visible;\n    }\n\n    public SQLExpr getDelimiter() {\n        return delimiter;\n    }\n\n    public boolean isDisableIndex() {\n        return disableIndex;\n    }\n\n    public void setDisableIndex(boolean disableIndex) {\n        this.disableIndex = disableIndex;\n    }\n\n    public void setDelimiter(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.delimiter = x;\n    }\n\n    public SQLExpr getDelimiterTokenizer() {\n        return delimiterTokenizer;\n    }\n\n    public void setDelimiterTokenizer(SQLExpr delimiterTokenizer) {\n        this.delimiterTokenizer = delimiterTokenizer;\n    }\n\n    public SQLExpr getNlpTokenizer() {\n        return nlpTokenizer;\n    }\n\n    public void setNlpTokenizer(SQLExpr nlpTokenizer) {\n        this.nlpTokenizer = nlpTokenizer;\n    }\n\n    public SQLExpr getValueType() {\n        return valueType;\n    }\n\n    public void setValueType(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.valueType = x;\n    }\n\n    public boolean isPreSort() {\n        return preSort;\n    }\n\n    public void setPreSort(boolean preSort) {\n        this.preSort = preSort;\n    }\n\n    public int getPreSortOrder() {\n        return preSortOrder;\n    }\n\n    public void setPreSortOrder(int preSortOrder) {\n        this.preSortOrder = preSortOrder;\n    }\n\n    public SQLExpr getJsonIndexAttrsExpr() {\n        return jsonIndexAttrsExpr;\n    }\n\n    public void setJsonIndexAttrsExpr(SQLExpr jsonIndexAttrsExpr) {\n        this.jsonIndexAttrsExpr = jsonIndexAttrsExpr;\n    }\n\n    public SQLAnnIndex getAnnIndex() {\n        return annIndex;\n    }\n\n    public void setAnnIndex(SQLAnnIndex x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.annIndex = x;\n    }\n\n    public AutoIncrementType getSequenceType() {\n        return sequenceType;\n    }\n\n    public void setSequenceType(AutoIncrementType sequenceType) {\n        this.sequenceType = sequenceType;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, dbType);\n    }\n\n    public SQLExpr getUnitCount() {\n        return unitCount;\n    }\n\n    public SQLExpr getUnitIndex() {\n        return unitIndex;\n    }\n\n    public void setUnitIndex(SQLExpr unitIndex) {\n        if (unitIndex != null) {\n            unitIndex.setParent(this);\n        }\n        this.unitIndex = unitIndex;\n    }\n\n    public SQLExpr getNplTokenizer() {\n        return nlpTokenizer;\n    }\n\n    public void setNplTokenizer(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.nlpTokenizer = x;\n    }\n\n    public SQLExpr getStep() {\n        return step;\n    }\n\n    public void setStep(SQLExpr step) {\n        if (step != null) {\n            step.setParent(this);\n        }\n        this.step = step;\n    }\n\n    public List<SQLAssignItem> getMappedBy() {\n        if (mappedBy == null) {\n            mappedBy = new ArrayList<SQLAssignItem>();\n        }\n        return mappedBy;\n    }\n\n    public List<SQLAssignItem> getMappedByDirect() {\n        return mappedBy;\n    }\n\n    public List<SQLAssignItem> getColProperties() {\n        if (colProperties == null) {\n            colProperties = new ArrayList<SQLAssignItem>();\n        }\n        return colProperties;\n    }\n\n    public SQLExpr getEncode() {\n        return encode;\n    }\n\n    public void setEncode(SQLExpr encode) {\n        this.encode = encode;\n    }\n\n    public SQLExpr getCompression() {\n        return compression;\n    }\n\n    public void setCompression(SQLExpr compression) {\n        this.compression = compression;\n    }\n\n    public void setBlockSize(SQLIntegerExpr blockSize) {\n        this.blockSize = blockSize;\n    }\n\n    public SQLIntegerExpr getBlockSize() {\n        return blockSize;\n    }\n\n    public List<SQLAssignItem> getColPropertiesDirect() {\n        return colProperties;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnPrimaryKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLColumnPrimaryKey extends SQLConstraintImpl implements SQLColumnConstraint {\n    private boolean notEnforced;\n    public SQLColumnPrimaryKey() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLColumnPrimaryKey clone() {\n        SQLColumnPrimaryKey x = new SQLColumnPrimaryKey();\n\n        super.cloneTo(x);\n\n        return x;\n    }\n\n    public boolean isNotEnforced() {\n        return notEnforced;\n    }\n\n    public void setNotEnforced(boolean notEnforced) {\n        this.notEnforced = notEnforced;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnReference.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLColumnReference extends SQLConstraintImpl implements SQLColumnConstraint {\n    private SQLName table;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n\n    private SQLForeignKeyImpl.Match referenceMatch;\n    protected SQLForeignKeyImpl.Option onUpdate;\n    protected SQLForeignKeyImpl.Option onDelete;\n    private boolean notEnforced;\n\n    public SQLColumnReference() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName table) {\n        this.table = table;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void setColumns(List<SQLName> columns) {\n        this.columns = columns;\n    }\n\n    public SQLColumnReference clone() {\n        SQLColumnReference x = new SQLColumnReference();\n\n        super.cloneTo(x);\n\n        if (table != null) {\n            x.setTable(table.clone());\n        }\n\n        for (SQLName column : columns) {\n            SQLName columnCloned = column.clone();\n            columnCloned.setParent(x);\n            x.columns.add(columnCloned);\n        }\n\n        x.referenceMatch = referenceMatch;\n        x.onUpdate = onUpdate;\n        x.onDelete = onDelete;\n\n        return x;\n    }\n\n    public SQLForeignKeyImpl.Match getReferenceMatch() {\n        return referenceMatch;\n    }\n\n    public void setReferenceMatch(SQLForeignKeyImpl.Match referenceMatch) {\n        this.referenceMatch = referenceMatch;\n    }\n\n    public SQLForeignKeyImpl.Option getOnUpdate() {\n        return onUpdate;\n    }\n\n    public void setOnUpdate(SQLForeignKeyImpl.Option onUpdate) {\n        this.onUpdate = onUpdate;\n    }\n\n    public SQLForeignKeyImpl.Option getOnDelete() {\n        return onDelete;\n    }\n\n    public void setOnDelete(SQLForeignKeyImpl.Option onDelete) {\n        this.onDelete = onDelete;\n    }\n\n    public boolean isNotEnforced() {\n        return notEnforced;\n    }\n\n    public void setNotEnforced(boolean notEnforced) {\n        this.notEnforced = notEnforced;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnUniqueKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLColumnUniqueKey extends SQLConstraintImpl implements SQLColumnConstraint, SQLReplaceable {\n    public SQLColumnUniqueKey() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLColumnUniqueKey clone() {\n        SQLColumnUniqueKey x = new SQLColumnUniqueKey();\n        super.cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCommentStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCommentStatement extends SQLStatementImpl {\n    public static enum Type {\n        TABLE, COLUMN, INDEX, VIEW\n    }\n\n    private SQLExprTableSource on;\n    private Type type;\n    private SQLExpr comment;\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        this.comment = comment;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public void setType(Type type) {\n        this.type = type;\n    }\n\n    public SQLExprTableSource getOn() {\n        return on;\n    }\n\n    public void setOn(SQLExprTableSource on) {\n        if (on != null) {\n            on.setParent(this);\n        }\n        this.on = on;\n    }\n\n    public void setOn(SQLName on) {\n        this.setOn(new SQLExprTableSource(on));\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, on);\n            acceptChild(visitor, comment);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (on != null) {\n            children.add(on);\n        }\n        if (comment != null) {\n            children.add(comment);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCommitStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCommitStatement extends SQLStatementImpl {\n    // oracle\n    private boolean write;\n    private Boolean wait;\n    private Boolean immediate;\n\n    // mysql\n    private boolean work;\n    private Boolean chain;\n    private Boolean release;\n\n    // sql server\n    private SQLExpr transactionName;\n    private SQLExpr delayedDurability;\n\n    public SQLCommitStatement() {\n    }\n\n    public SQLCommitStatement clone() {\n        SQLCommitStatement x = new SQLCommitStatement();\n        x.write = write;\n        x.wait = wait;\n        x.immediate = immediate;\n        x.work = work;\n        x.chain = chain;\n        x.release = release;\n\n        if (transactionName != null) {\n            x.setTransactionName(transactionName.clone());\n        }\n        if (delayedDurability != null) {\n            x.setDelayedDurability(delayedDurability.clone());\n        }\n        return x;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (transactionName != null) {\n                transactionName.accept(visitor);\n            }\n\n            if (delayedDurability != null) {\n                delayedDurability.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    // oracle\n    public boolean isWrite() {\n        return write;\n    }\n\n    public void setWrite(boolean write) {\n        this.write = write;\n    }\n\n    public Boolean getWait() {\n        return wait;\n    }\n\n    public void setWait(Boolean wait) {\n        this.wait = wait;\n    }\n\n    public Boolean getImmediate() {\n        return immediate;\n    }\n\n    public void setImmediate(Boolean immediate) {\n        this.immediate = immediate;\n    }\n\n    // mysql\n    public Boolean getChain() {\n        return chain;\n    }\n\n    public void setChain(Boolean chain) {\n        this.chain = chain;\n    }\n\n    public Boolean getRelease() {\n        return release;\n    }\n\n    public void setRelease(Boolean release) {\n        this.release = release;\n    }\n\n    public boolean isWork() {\n        return work;\n    }\n\n    public void setWork(boolean work) {\n        this.work = work;\n    }\n\n    // sql server\n    public SQLExpr getTransactionName() {\n        return transactionName;\n    }\n\n    public void setTransactionName(SQLExpr transactionName) {\n        if (transactionName != null) {\n            transactionName.setParent(this);\n        }\n        this.transactionName = transactionName;\n    }\n\n    public SQLExpr getDelayedDurability() {\n        return delayedDurability;\n    }\n\n    public void setDelayedDurability(SQLExpr delayedDurability) {\n        if (delayedDurability != null) {\n            delayedDurability.setParent(this);\n        }\n        this.delayedDurability = delayedDurability;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCommitTransactionStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCommitTransactionStatement extends SQLStatementImpl {\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\n\npublic interface SQLConstraint extends SQLObject {\n    SQLName getName();\n\n    void setName(SQLName value);\n\n    SQLExpr getComment();\n\n    void setComment(SQLExpr x);\n\n    void simplify();\n\n    default void setHasConstraint(boolean hasConstraint) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLConstraintImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\n\nimport java.util.List;\n\npublic abstract class SQLConstraintImpl extends SQLObjectImpl implements SQLConstraint, SQLDbTypedObject {\n    protected DbType dbType;\n    private SQLName name;\n    protected Boolean enable;\n    protected Boolean validate;\n    protected Boolean rely;\n    private SQLExpr comment;\n\n    public List<SQLCommentHint> hints;\n\n    public SQLConstraintImpl() {\n    }\n\n    public void cloneTo(SQLConstraintImpl x) {\n        if (getName() != null) {\n            x.setName(getName().clone());\n        }\n\n        x.enable = enable;\n        x.validate = validate;\n        x.rely = rely;\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public void setName(String name) {\n        this.setName(new SQLIdentifierExpr(name));\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public void cloneTo(SQLConstraint x) {\n        if (getName() != null) {\n            x.setName(getName().clone());\n        }\n    }\n\n    public Boolean getValidate() {\n        return validate;\n    }\n\n    public void setValidate(Boolean validate) {\n        this.validate = validate;\n    }\n\n    public Boolean getRely() {\n        return rely;\n    }\n\n    public void setRely(Boolean rely) {\n        this.rely = rely;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.comment = x;\n    }\n\n    public void simplify() {\n        if (getName() instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) getName();\n            String columnName = identExpr.getName();\n\n            String normalized = SQLUtils.normalize(columnName, dbType);\n            if (columnName != normalized) {\n                this.setName(normalized);\n            }\n        }\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (getName() == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        if (getComment() == expr) {\n            setComment(target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLContinueStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLContinueStatement extends SQLStatementImpl {\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCopyFromStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCopyFromStatement extends SQLStatementImpl {\n    private SQLExprTableSource table;\n    private final List<SQLName> columns = new ArrayList<SQLName>();\n    private SQLExpr from;\n    private SQLExpr accessKeyId;\n    private SQLExpr accessKeySecret;\n    private final List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>();\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, table);\n            acceptChild(v, columns);\n            acceptChild(v, partitions);\n            acceptChild(v, from);\n            acceptChild(v, options);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public SQLExpr getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.from = x;\n    }\n\n    public SQLExpr getAccessKeyId() {\n        return accessKeyId;\n    }\n\n    public void setAccessKeyId(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.accessKeyId = x;\n    }\n\n    public SQLExpr getAccessKeySecret() {\n        return accessKeySecret;\n    }\n\n    public void setAccessKeySecret(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.accessKeySecret = x;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCostStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCostStatement extends SQLStatementImpl {\n    protected SQLStatement statement;\n\n    public SQLStatement getStatement() {\n        return statement;\n    }\n\n    public void setStatement(SQLStatement statement) {\n        if (statement != null) {\n            statement.setParent(this);\n        }\n\n        this.statement = statement;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statement);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateDatabaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLCreateDatabaseStatement extends SQLStatementImpl implements SQLCreateStatement {\n    protected SQLName name;\n    protected String characterSet;\n    protected String collate;\n    protected List<SQLCommentHint> hints;\n    protected boolean ifNotExists;\n    protected SQLExpr comment;\n    protected SQLExpr location; // hive\n    protected final List<SQLAssignItem> dbProperties = new ArrayList<SQLAssignItem>();\n    protected Map<String, SQLExpr> options = new HashMap<String, SQLExpr>(); // for ads\n    protected String user;\n\n    protected SQLExpr password; // drds\n    protected final List<SQLAssignItem> storedOn = new ArrayList<SQLAssignItem>(); // drds\n    protected final List<List<SQLAssignItem>> storedBy = new ArrayList<List<SQLAssignItem>>(); // drds stored by\n    protected SQLExpr storedAs;  // drds\n    protected SQLExpr storedIn;  // drds\n\n    //adb\n    protected boolean physical;\n\n    public SQLCreateDatabaseStatement() {\n    }\n\n    public SQLCreateDatabaseStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public String getCharacterSet() {\n        return characterSet;\n    }\n\n    public void setCharacterSet(String characterSet) {\n        this.characterSet = characterSet;\n    }\n\n    public String getCollate() {\n        return collate;\n    }\n\n    public void setCollate(String collate) {\n        this.collate = collate;\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public String getUser() {\n        return user;\n    }\n\n    public void setUser(String user) {\n        this.user = user;\n    }\n\n    public void setComment(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.comment = x;\n    }\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public Map<String, SQLExpr> getOptions() {\n        return options;\n    }\n\n    public void setLocation(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.location = x;\n    }\n\n    public List<SQLAssignItem> getDbProperties() {\n        return dbProperties;\n    }\n\n    public void setOptions(Map<String, SQLExpr> options) {\n        this.options = options;\n    }\n\n    public List<SQLAssignItem> getStoredOn() {\n        return storedOn;\n    }\n\n    public List<List<SQLAssignItem>> getStoredBy() {\n        return storedBy;\n    }\n\n    public SQLExpr getStoredAs() {\n        return storedAs;\n    }\n\n    public void setStoredAs(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedAs = x;\n    }\n\n    public SQLExpr getStoredIn() {\n        return storedIn;\n    }\n\n    public void setStoredIn(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedIn = x;\n    }\n\n    public SQLExpr getPassword() {\n        return password;\n    }\n\n    public void setPassword(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.password = x;\n    }\n\n    public String getDatabaseName() {\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLName) {\n            return ((SQLName) name).getSimpleName();\n        }\n\n        return null;\n    }\n\n    public void setDatabase(String database) {\n        SQLExpr expr = SQLUtils.toSQLExpr(database);\n\n        if (expr instanceof SQLIdentifierExpr && name instanceof SQLPropertyExpr) {\n            ((SQLPropertyExpr) this.name).setName(database);\n            return;\n        }\n\n        expr.setParent(this);\n        this.name = (SQLName) expr;\n    }\n\n    public String getServer() {\n        if (name instanceof SQLPropertyExpr) {\n            SQLExpr owner = ((SQLPropertyExpr) name).getOwner();\n            if (owner instanceof SQLIdentifierExpr) {\n                return ((SQLIdentifierExpr) owner).getName();\n            }\n\n            if (owner instanceof SQLPropertyExpr) {\n                return ((SQLPropertyExpr) owner).getName();\n            }\n        }\n\n        return null;\n    }\n\n    public boolean setServer(String server) {\n        if (name == null) {\n            return false;\n        }\n\n        if (name instanceof SQLIdentifierExpr) {\n            SQLPropertyExpr propertyExpr = new SQLPropertyExpr(new SQLIdentifierExpr(server), ((SQLIdentifierExpr) name).getName());\n            propertyExpr.setParent(this);\n            name = propertyExpr;\n            return true;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) name;\n            SQLExpr owner = propertyExpr.getOwner();\n            if (owner instanceof SQLIdentifierExpr) {\n                propertyExpr.setOwner(new SQLIdentifierExpr(server));\n                return true;\n            } else if (owner instanceof SQLPropertyExpr) {\n                ((SQLPropertyExpr) owner).setName(server);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public boolean isPhysical() {\n        return physical;\n    }\n\n    public void setPhysical(boolean physical) {\n        this.physical = physical;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.DATABASE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateFunctionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 23/05/2017.\n */\npublic class SQLCreateFunctionStatement extends SQLStatementImpl implements SQLCreateStatement, SQLObjectWithDataType {\n    protected SQLName definer;\n\n    protected boolean create = true;\n    protected boolean orReplace;\n    protected SQLName name;\n    protected SQLStatement block;\n    protected List<SQLParameter> parameters = new ArrayList<>();\n    protected List<SQLAssignItem> options = new ArrayList<>();\n\n    // for oracle\n    private String javaCallSpec;\n\n    private SQLName authid;\n\n    SQLDataType returnDataType;\n\n    // for mysql\n\n    private String comment;\n    private boolean deterministic;\n    private boolean parallelEnable;\n    private boolean aggregate;\n    private SQLName using;\n    private boolean pipelined;\n    private boolean resultCache;\n    private String wrappedSource;\n    private String language;\n    private boolean temporary;\n    protected boolean ifNotExists;\n\n    public SQLCreateFunctionStatement() {\n    }\n\n    public SQLCreateFunctionStatement clone() {\n        SQLCreateFunctionStatement x = new SQLCreateFunctionStatement();\n\n        if (definer != null) {\n            x.setDefiner(definer.clone());\n        }\n        x.create = create;\n        x.orReplace = orReplace;\n        if (name != null) {\n            x.setName(name.clone());\n        }\n        if (block != null) {\n            x.setBlock(block.clone());\n        }\n        for (SQLParameter p : parameters) {\n            SQLParameter p2 = p.clone();\n            p2.setParent(x);\n            x.parameters.add(p2);\n        }\n        x.javaCallSpec = javaCallSpec;\n        if (authid != null) {\n            x.setAuthid(authid.clone());\n        }\n        if (returnDataType != null) {\n            x.setReturnDataType(returnDataType.clone());\n        }\n        x.comment = comment;\n        x.deterministic = deterministic;\n        x.pipelined = pipelined;\n        x.language = language;\n\n        return x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, definer);\n            acceptChild(visitor, name);\n            acceptChild(visitor, parameters);\n            acceptChild(visitor, returnDataType);\n            acceptChild(visitor, block);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    public SQLParameter getParameter(String name) {\n        if (name == null) {\n            return null;\n        }\n        for (SQLParameter parameter : parameters) {\n            if (name.equals(parameter.getName().getSimpleName())) {\n                return parameter;\n            }\n        }\n        return null;\n    }\n\n    public void setParameters(List<SQLParameter> parameters) {\n        this.parameters = parameters;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLStatement getBlock() {\n        return block;\n    }\n\n    public void setBlock(SQLStatement block) {\n        if (block != null) {\n            block.setParent(this);\n        }\n        this.block = block;\n    }\n\n    public SQLName getAuthid() {\n        return authid;\n    }\n\n    public void setAuthid(SQLName authid) {\n        if (authid != null) {\n            authid.setParent(this);\n        }\n        this.authid = authid;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public String getLanguage() {\n        return language;\n    }\n\n    public void setLanguage(String language) {\n        this.language = language;\n    }\n\n    public boolean isOrReplace() {\n        return orReplace;\n    }\n\n    public void setOrReplace(boolean orReplace) {\n        this.orReplace = orReplace;\n    }\n\n    public SQLName getDefiner() {\n        return definer;\n    }\n\n    public void setDefiner(SQLName definer) {\n        this.definer = definer;\n    }\n\n    public boolean isCreate() {\n        return create;\n    }\n\n    public void setCreate(boolean create) {\n        this.create = create;\n    }\n\n    public String getJavaCallSpec() {\n        return javaCallSpec;\n    }\n\n    public void setJavaCallSpec(String javaCallSpec) {\n        this.javaCallSpec = javaCallSpec;\n    }\n\n    public SQLDataType getReturnDataType() {\n        return returnDataType;\n    }\n\n    public void setReturnDataType(SQLDataType returnDataType) {\n        if (returnDataType != null) {\n            returnDataType.setParent(this);\n        }\n        this.returnDataType = returnDataType;\n    }\n\n    public String getComment() {\n        return comment;\n    }\n\n    public void setComment(String comment) {\n        this.comment = comment;\n    }\n\n    public boolean isDeterministic() {\n        return deterministic;\n    }\n\n    public void setDeterministic(boolean deterministic) {\n        this.deterministic = deterministic;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    @Override\n    public SQLDataType getDataType() {\n        return returnDataType;\n    }\n\n    @Override\n    public void setDataType(SQLDataType dataType) {\n        this.setReturnDataType(dataType);\n    }\n\n    public boolean isParallelEnable() {\n        return parallelEnable;\n    }\n\n    public void setParallelEnable(boolean parallel_enable) {\n        this.parallelEnable = parallel_enable;\n    }\n\n    public boolean isAggregate() {\n        return aggregate;\n    }\n\n    public void setAggregate(boolean aggregate) {\n        this.aggregate = aggregate;\n    }\n\n    public SQLName getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLName using) {\n        this.using = using;\n    }\n\n    public boolean isPipelined() {\n        return pipelined;\n    }\n\n    public void setPipelined(boolean pipelined) {\n        this.pipelined = pipelined;\n    }\n\n    public boolean isResultCache() {\n        return resultCache;\n    }\n\n    public void setResultCache(boolean resultCache) {\n        this.resultCache = resultCache;\n    }\n\n    public String getWrappedSource() {\n        return wrappedSource;\n    }\n\n    public void setWrappedSource(String wrappedSource) {\n        this.wrappedSource = wrappedSource;\n    }\n\n    public boolean isTemporary() {\n        return temporary;\n    }\n\n    public void setTemporary(boolean temporary) {\n        this.temporary = temporary;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCreateIndexStatement extends SQLStatementImpl implements SQLCreateStatement, SQLIndex {\n    private SQLIndexDefinition indexDefinition = new SQLIndexDefinition();\n\n    private boolean concurrently; // for pg\n    protected SQLName tablespace; // for oracle\n    protected boolean deferedRebuild;\n    protected SQLTableSource in;\n    protected SQLExternalRecordFormat rowFormat;\n    protected SQLName storedAs;\n    protected List<SQLAssignItem> properties = new ArrayList<SQLAssignItem>();\n    protected List<SQLAssignItem> tableProperties = new ArrayList<SQLAssignItem>();\n    protected boolean storing;\n    protected boolean ifNotExists;\n\n    public SQLCreateIndexStatement() {\n        indexDefinition.setParent(this);\n    }\n\n    public SQLCreateIndexStatement(DbType dbType) {\n        super(dbType);\n        indexDefinition.setParent(this);\n    }\n\n    public SQLIndexDefinition getIndexDefinition() {\n        return indexDefinition;\n    }\n\n    public SQLTableSource getTable() {\n        return indexDefinition.getTable();\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public void setTable(SQLTableSource table) {\n        indexDefinition.setTable(table);\n    }\n\n    public String getTableName() {\n        if (indexDefinition.getTable() instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) indexDefinition.getTable()).getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                return ((SQLIdentifierExpr) expr).getName();\n            } else if (expr instanceof SQLPropertyExpr) {\n                return ((SQLPropertyExpr) expr).getName();\n            }\n        }\n\n        return null;\n    }\n\n    public List<SQLSelectOrderByItem> getItems() {\n        return indexDefinition.getColumns();\n    }\n\n    public void addItem(SQLSelectOrderByItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        indexDefinition.getColumns().add(item);\n    }\n\n    public SQLName getName() {\n        return indexDefinition.getName();\n    }\n\n    public void setName(SQLName name) {\n        indexDefinition.setName(name);\n    }\n\n    public String getType() {\n        return indexDefinition.getType();\n    }\n\n    public void setType(String type) {\n        indexDefinition.setType(type);\n    }\n\n    public String getUsing() {\n        return indexDefinition.hasOptions() ? indexDefinition.getOptions().getIndexType() : null;\n    }\n\n    public void setUsing(String using) {\n        indexDefinition.getOptions().setIndexType(using);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, indexDefinition.getName());\n            acceptChild(visitor, indexDefinition.getTable());\n            acceptChild(visitor, indexDefinition.getColumns());\n            acceptChild(visitor, tablespace);\n            acceptChild(visitor, in);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (indexDefinition.getName() != null) {\n            children.add(indexDefinition.getName());\n        }\n\n        if (indexDefinition.getTable() != null) {\n            children.add(indexDefinition.getTable());\n        }\n\n        children.addAll(indexDefinition.getColumns());\n        return children;\n    }\n\n    public String getSchema() {\n        SQLName name = null;\n        if (indexDefinition.getTable() instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) indexDefinition.getTable()).getExpr();\n            if (expr instanceof SQLName) {\n                name = (SQLName) expr;\n            }\n        }\n\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public SQLCreateIndexStatement clone() {\n        SQLCreateIndexStatement x = new SQLCreateIndexStatement();\n        indexDefinition.cloneTo(x.indexDefinition);\n        x.setIfNotExists(ifNotExists);\n        return x;\n    }\n\n    public SQLExpr getComment() {\n        return indexDefinition.hasOptions() ? indexDefinition.getOptions().getComment() : null;\n    }\n\n    public void setComment(SQLExpr x) {\n        indexDefinition.getOptions().setComment(x);\n    }\n\n    public SQLName getTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.tablespace = x;\n    }\n\n    public boolean isConcurrently() {\n        return concurrently;\n    }\n\n    public void setConcurrently(boolean concurrently) {\n        this.concurrently = concurrently;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return indexDefinition.getCompatibleOptions();\n    }\n\n    public boolean isDeferedRebuild() {\n        return deferedRebuild;\n    }\n\n    public void setDeferedRebuild(boolean deferedRebuild) {\n        this.deferedRebuild = deferedRebuild;\n    }\n\n    public SQLTableSource getIn() {\n        return in;\n    }\n\n    public void setIn(SQLName x) {\n        if (x == null) {\n            this.in = null;\n            return;\n        }\n        setIn(new SQLExprTableSource(x));\n    }\n\n    public void setIn(SQLTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.in = x;\n    }\n\n    public SQLName getStoredAs() {\n        return storedAs;\n    }\n\n    public void setStoredAs(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedAs = x;\n    }\n\n    public SQLExternalRecordFormat getRowFormat() {\n        return rowFormat;\n    }\n\n    public void setRowFormat(SQLExternalRecordFormat x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.rowFormat = x;\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n\n    public List<SQLAssignItem> getTableProperties() {\n        return tableProperties;\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        // Add both with same object.\n        indexDefinition.getOptions().getOtherOptions().add(assignItem);\n        indexDefinition.getCompatibleOptions().add(assignItem);\n    }\n\n    public boolean isGlobal() {\n        return indexDefinition.isGlobal();\n    }\n\n    public void setGlobal(boolean global) {\n        indexDefinition.setGlobal(global);\n    }\n\n    public boolean isLocal() {\n        return indexDefinition.isLocal();\n    }\n\n    public void setLocal(boolean local) {\n        indexDefinition.setLocal(local);\n    }\n\n    public SQLExpr getDbPartitionBy() {\n        return indexDefinition.getDbPartitionBy();\n    }\n\n    public void setDbPartitionBy(SQLExpr x) {\n        indexDefinition.setDbPartitionBy(x);\n    }\n\n    public SQLExpr getTablePartitions() {\n        return indexDefinition.getTbPartitions();\n    }\n\n    public void setTablePartitions(SQLExpr x) {\n        indexDefinition.setTbPartitions(x);\n    }\n\n    public SQLExpr getTablePartitionBy() {\n        return indexDefinition.getTbPartitionBy();\n    }\n\n    public void setTablePartitionBy(SQLExpr x) {\n        indexDefinition.setTbPartitionBy(x);\n    }\n\n    public boolean isStoring() {\n        return storing;\n    }\n\n    public void setStoring(boolean storing) {\n        this.storing = storing;\n    }\n\n    @Override\n    public List<SQLName> getCovering() {\n        return indexDefinition.getCovering();\n    }\n\n    @Override\n    public List<SQLSelectOrderByItem> getColumns() {\n        return indexDefinition.getColumns();\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.INDEX;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateMaterializedViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 30/06/2017.\n */\npublic class SQLCreateMaterializedViewStatement extends SQLStatementImpl implements OracleSegmentAttributes, SQLCreateStatement, SQLReplaceable {\n    protected SQLExpr lifyCycle;\n    private SQLName name;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n    private boolean ifNotExists;\n\n    private boolean refreshFast;\n    private boolean refreshComplete;\n    private boolean refreshForce;\n    private boolean refreshOnCommit;\n    private boolean refreshOnDemand;\n    private boolean refreshStartWith;\n    private boolean refreshNext;\n\n    private boolean buildImmediate;\n    private boolean buildDeferred;\n\n    private SQLSelect query;\n\n    // oracle\n    private Integer pctfree;\n    private Integer pctused;\n    private Integer initrans;\n\n    private Integer maxtrans;\n    private Integer pctincrease;\n    private Integer freeLists;\n    private Boolean compress;\n    private Integer compressLevel;\n    private boolean compressForOltp;\n    private Integer pctthreshold;\n\n    private Boolean logging;\n    private Boolean cache;\n\n    protected SQLName tablespace;\n    protected SQLObject storage;\n\n    private Boolean parallel;\n    private Integer parallelValue;\n\n    private Boolean enableQueryRewrite;\n\n    private SQLPartitionBy partitionBy;\n    private SQLExpr startWith;\n    private SQLExpr next;\n\n    private boolean withRowId;\n\n    // for ADB\n    protected boolean refreshOnOverWrite;\n    protected List<SQLTableElement> tableElementList = new ArrayList<SQLTableElement>();\n    protected SQLName distributedByType;\n    protected List<SQLName> distributedBy = new ArrayList<SQLName>();\n    protected final List<SQLAssignItem> tableOptions = new ArrayList<SQLAssignItem>();\n    protected SQLExpr comment;\n    private List<SQLName> partitionedOn = new ArrayList<SQLName>();\n\n    protected SQLName to;\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName to) {\n        if (to != null) {\n            to.setParent(this);\n        }\n        this.to = to;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public SQLSelect getQuery() {\n        return query;\n    }\n\n    public void setQuery(SQLSelect query) {\n        if (query != null) {\n            query.setParent(this);\n        }\n        this.query = query;\n    }\n\n    public boolean isBuildImmediate() {\n        return buildImmediate;\n    }\n\n    public void setBuildImmediate(boolean buildImmediate) {\n        this.buildImmediate = buildImmediate;\n    }\n\n    public boolean isBuildDeferred() {\n        return buildDeferred;\n    }\n\n    public void setBuildDeferred(boolean buildDeferred) {\n        this.buildDeferred = buildDeferred;\n    }\n\n    public boolean isRefresh() {\n        return this.refreshFast || refreshComplete || refreshForce || refreshOnDemand || refreshOnCommit || refreshStartWith || refreshNext;\n    }\n\n    public boolean isRefreshFast() {\n        return refreshFast;\n    }\n\n    public void setRefreshFast(boolean refreshFast) {\n        this.refreshFast = refreshFast;\n    }\n\n    public boolean isRefreshComplete() {\n        return refreshComplete;\n    }\n\n    public void setRefreshComplete(boolean refreshComplete) {\n        this.refreshComplete = refreshComplete;\n    }\n\n    public boolean isRefreshForce() {\n        return refreshForce;\n    }\n\n    public void setRefreshForce(boolean refreshForce) {\n        this.refreshForce = refreshForce;\n    }\n\n    public boolean isRefreshOnCommit() {\n        return refreshOnCommit;\n    }\n\n    public void setRefreshOnCommit(boolean refreshOnCommit) {\n        this.refreshOnCommit = refreshOnCommit;\n    }\n\n    public boolean isRefreshOnDemand() {\n        return refreshOnDemand;\n    }\n\n    public void setRefreshOnDemand(boolean refreshOnDemand) {\n        this.refreshOnDemand = refreshOnDemand;\n    }\n\n    public boolean isRefreshOnOverWrite() {\n        return refreshOnOverWrite;\n    }\n\n    public void setRefreshOnOverWrite(boolean refreshOnOverWrite) {\n        this.refreshOnOverWrite = refreshOnOverWrite;\n    }\n\n    public boolean isRefreshStartWith() {\n        return refreshStartWith;\n    }\n\n    public void setRefreshStartWith(boolean refreshStartWith) {\n        this.refreshStartWith = refreshStartWith;\n    }\n\n    public boolean isRefreshNext() {\n        return refreshNext;\n    }\n\n    public void setRefreshNext(boolean refreshNext) {\n        this.refreshNext = refreshNext;\n    }\n\n    public Integer getPctfree() {\n        return pctfree;\n    }\n\n    public void setPctfree(Integer pctfree) {\n        this.pctfree = pctfree;\n    }\n\n    public Integer getPctused() {\n        return pctused;\n    }\n\n    public void setPctused(Integer pctused) {\n        this.pctused = pctused;\n    }\n\n    public Integer getInitrans() {\n        return initrans;\n    }\n\n    public void setInitrans(Integer initrans) {\n        this.initrans = initrans;\n    }\n\n    public Integer getMaxtrans() {\n        return maxtrans;\n    }\n\n    public void setMaxtrans(Integer maxtrans) {\n        this.maxtrans = maxtrans;\n    }\n\n    public Integer getPctincrease() {\n        return pctincrease;\n    }\n\n    public void setPctincrease(Integer pctincrease) {\n        this.pctincrease = pctincrease;\n    }\n\n    public Integer getFreeLists() {\n        return freeLists;\n    }\n\n    public void setFreeLists(Integer freeLists) {\n        this.freeLists = freeLists;\n    }\n\n    public Boolean getCompress() {\n        return compress;\n    }\n\n    public void setCompress(Boolean compress) {\n        this.compress = compress;\n    }\n\n    public Integer getCompressLevel() {\n        return compressLevel;\n    }\n\n    public void setCompressLevel(Integer compressLevel) {\n        this.compressLevel = compressLevel;\n    }\n\n    public boolean isCompressForOltp() {\n        return compressForOltp;\n    }\n\n    public void setCompressForOltp(boolean compressForOltp) {\n        this.compressForOltp = compressForOltp;\n    }\n\n    public Integer getPctthreshold() {\n        return pctthreshold;\n    }\n\n    public void setPctthreshold(Integer pctthreshold) {\n        this.pctthreshold = pctthreshold;\n    }\n\n    public Boolean getLogging() {\n        return logging;\n    }\n\n    public void setLogging(Boolean logging) {\n        this.logging = logging;\n    }\n\n    public SQLName getTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(SQLName tablespace) {\n        if (tablespace != null) {\n            tablespace.setParent(this);\n        }\n        this.tablespace = tablespace;\n    }\n\n    public SQLObject getStorage() {\n        return storage;\n    }\n\n    public void setStorage(SQLObject storage) {\n        if (storage != null) {\n            storage.setParent(this);\n        }\n        this.storage = storage;\n    }\n\n    public Boolean getParallel() {\n        return parallel;\n    }\n\n    public void setParallel(Boolean parallel) {\n        this.parallel = parallel;\n    }\n\n    public Integer getParallelValue() {\n        return parallelValue;\n    }\n\n    public void setParallelValue(Integer parallelValue) {\n        this.parallelValue = parallelValue;\n    }\n\n    public Boolean getEnableQueryRewrite() {\n        return enableQueryRewrite;\n    }\n\n    public void setEnableQueryRewrite(Boolean enableQueryRewrite) {\n        this.enableQueryRewrite = enableQueryRewrite;\n    }\n\n    public Boolean getCache() {\n        return cache;\n    }\n\n    public void setCache(Boolean cache) {\n        this.cache = cache;\n    }\n\n    public SQLPartitionBy getPartitionBy() {\n        return partitionBy;\n    }\n\n    public List<SQLTableElement> getTableElementList() {\n        return tableElementList;\n    }\n\n    public List<SQLName> getDistributedBy() {\n        return distributedBy;\n    }\n\n    public SQLName getDistributedByType() {\n        return distributedByType;\n    }\n\n    public void setDistributedByType(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.distributedByType = x;\n    }\n\n    public SQLExpr getStartWith() {\n        return startWith;\n    }\n\n    public void setStartWith(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.startWith = x;\n    }\n\n    public SQLExpr getNext() {\n        return next;\n    }\n\n    public void setNext(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.next = x;\n    }\n\n    public void setPartitionBy(SQLPartitionBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partitionBy = x;\n    }\n\n    public boolean isWithRowId() {\n        return withRowId;\n    }\n\n    public void setWithRowId(boolean withRowId) {\n        this.withRowId = withRowId;\n    }\n\n    public List<SQLName> getPartitionedOn() {\n        return partitionedOn;\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        tableOptions.add(assignItem);\n    }\n\n    public List<SQLAssignItem> getTableOptions() {\n        return tableOptions;\n    }\n\n    public SQLExpr getOption(String name) {\n        if (name == null) {\n            return null;\n        }\n\n        long hash64 = FnvHash.hashCode64(name);\n\n        for (SQLAssignItem item : tableOptions) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.comment = x;\n    }\n\n    public SQLExpr getLifyCycle() {\n        return lifyCycle;\n    }\n\n    public void setLifyCycle(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.lifyCycle = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, columns);\n            acceptChild(visitor, partitionBy);\n            acceptChild(visitor, query);\n            acceptChild(visitor, tableElementList);\n            acceptChild(visitor, distributedBy);\n            acceptChild(visitor, distributedByType);\n            acceptChild(visitor, startWith);\n            acceptChild(visitor, next);\n            acceptChild(visitor, tableOptions);\n            acceptChild(visitor, comment);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == name) {\n            setName((SQLName) target);\n            return true;\n        }\n        if (expr == next) {\n            setNext(target);\n            return true;\n        }\n        if (expr == startWith) {\n            setStartWith(target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateOutlineStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCreateOutlineStatement extends SQLStatementImpl {\n    private SQLName name;\n    private SQLExpr where;\n\n    private SQLStatement on;\n    private SQLStatement to;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLStatement getOn() {\n        return on;\n    }\n\n    public void setOn(SQLStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.on = x;\n    }\n\n    public SQLStatement getTo() {\n        return to;\n    }\n\n    public void setTo(SQLStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n            acceptChild(v, where);\n            acceptChild(v, on);\n            acceptChild(v, to);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateProcedureStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCreateProcedureStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName definer;\n\n    private boolean create = true;\n    private boolean orReplace;\n    private SQLName name;\n    private SQLStatement block;\n    private List<SQLParameter> parameters = new ArrayList<SQLParameter>();\n\n    // for oracle\n    private String javaCallSpec;\n\n    private SQLName authid;\n\n    // for mysql\n    private boolean deterministic;\n    private boolean containsSql;\n    private boolean noSql;\n    private boolean readSqlData;\n    private boolean modifiesSqlData;\n    private boolean languageSql;\n\n    private String wrappedSource;\n\n    private SQLCharExpr comment;\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, definer);\n            acceptChild(visitor, name);\n            acceptChild(visitor, parameters);\n            acceptChild(visitor, block);\n            acceptChild(visitor, comment);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<SQLParameter> parameters) {\n        this.parameters = parameters;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public SQLStatement getBlock() {\n        return block;\n    }\n\n    public void setBlock(SQLStatement block) {\n        if (block != null) {\n            block.setParent(this);\n        }\n        this.block = block;\n    }\n\n    public SQLName getAuthid() {\n        return authid;\n    }\n\n    public void setAuthid(SQLName authid) {\n        if (authid != null) {\n            authid.setParent(this);\n        }\n        this.authid = authid;\n    }\n\n    public boolean isOrReplace() {\n        return orReplace;\n    }\n\n    public void setOrReplace(boolean orReplace) {\n        this.orReplace = orReplace;\n    }\n\n    public SQLName getDefiner() {\n        return definer;\n    }\n\n    public void setDefiner(SQLName definer) {\n        this.definer = definer;\n    }\n\n    public boolean isCreate() {\n        return create;\n    }\n\n    public void setCreate(boolean create) {\n        this.create = create;\n    }\n\n    public String getJavaCallSpec() {\n        return javaCallSpec;\n    }\n\n    public void setJavaCallSpec(String javaCallSpec) {\n        this.javaCallSpec = javaCallSpec;\n    }\n\n    public boolean isDeterministic() {\n        return deterministic;\n    }\n\n    public void setDeterministic(boolean deterministic) {\n        this.deterministic = deterministic;\n    }\n\n    public boolean isContainsSql() {\n        return containsSql;\n    }\n\n    public void setContainsSql(boolean containsSql) {\n        this.containsSql = containsSql;\n    }\n\n    public boolean isNoSql() {\n        return noSql;\n    }\n\n    public void setNoSql(boolean noSql) {\n        this.noSql = noSql;\n    }\n\n    public boolean isReadSqlData() {\n        return readSqlData;\n    }\n\n    public void setReadSqlData(boolean readSqlData) {\n        this.readSqlData = readSqlData;\n    }\n\n    public boolean isModifiesSqlData() {\n        return modifiesSqlData;\n    }\n\n    public void setModifiesSqlData(boolean modifiesSqlData) {\n        this.modifiesSqlData = modifiesSqlData;\n    }\n\n    public SQLParameter findParameter(long hash) {\n        for (SQLParameter param : this.parameters) {\n            if (param.getName().nameHashCode64() == hash) {\n                return param;\n            }\n        }\n\n        return null;\n    }\n\n    public boolean isLanguageSql() {\n        return languageSql;\n    }\n\n    public void setLanguageSql(boolean languageSql) {\n        this.languageSql = languageSql;\n    }\n\n    public SQLCharExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLCharExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public String getWrappedSource() {\n        return wrappedSource;\n    }\n\n    public void setWrappedSource(String wrappedSource) {\n        this.wrappedSource = wrappedSource;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateRoleStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCreateRoleStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n    protected boolean ifNotExists;\n\n    public SQLCreateRoleStatement() {\n    }\n\n    public SQLCreateRoleStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.ROLE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateSequenceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 16/9/14.\n */\npublic class SQLCreateSequenceStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n\n    private SQLExpr startWith;\n    private SQLExpr incrementBy;\n    private SQLExpr minValue;\n    private SQLExpr maxValue;\n    private boolean noMaxValue;\n    private boolean noMinValue;\n    private Boolean withCache;\n    private Boolean cycle;\n    private Boolean cache;\n    private SQLExpr cacheValue;\n    private Boolean order;\n\n    // for drds\n    private boolean simple;\n    private boolean group;\n    private boolean time;\n\n    private SQLExpr unitCount;\n    private SQLExpr unitIndex;\n\n    private SQLExpr step;\n\n    public SQLCreateSequenceStatement() {\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, startWith);\n            acceptChild(visitor, incrementBy);\n            acceptChild(visitor, minValue);\n            acceptChild(visitor, maxValue);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        if (startWith != null) {\n            children.add(startWith);\n        }\n        if (incrementBy != null) {\n            children.add(incrementBy);\n        }\n        if (minValue != null) {\n            children.add(minValue);\n        }\n        if (maxValue != null) {\n            children.add(maxValue);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public SQLExpr getStartWith() {\n        return startWith;\n    }\n\n    public void setStartWith(SQLExpr startWith) {\n        this.startWith = startWith;\n    }\n\n    public SQLExpr getIncrementBy() {\n        return incrementBy;\n    }\n\n    public void setIncrementBy(SQLExpr incrementBy) {\n        this.incrementBy = incrementBy;\n    }\n\n    public SQLExpr getMaxValue() {\n        return maxValue;\n    }\n\n    public void setMaxValue(SQLExpr maxValue) {\n        this.maxValue = maxValue;\n    }\n\n    public Boolean getCycle() {\n        return cycle;\n    }\n\n    public void setCycle(Boolean cycle) {\n        this.cycle = cycle;\n    }\n\n    public Boolean getCache() {\n        return cache;\n    }\n\n    public void setCache(Boolean cache) {\n        this.cache = cache;\n    }\n\n    public Boolean getOrder() {\n        return order;\n    }\n\n    public void setOrder(Boolean order) {\n        this.order = order;\n    }\n\n    public SQLExpr getMinValue() {\n        return minValue;\n    }\n\n    public void setMinValue(SQLExpr minValue) {\n        this.minValue = minValue;\n    }\n\n    public boolean isNoMaxValue() {\n        return noMaxValue;\n    }\n\n    public void setNoMaxValue(boolean noMaxValue) {\n        this.noMaxValue = noMaxValue;\n    }\n\n    public boolean isNoMinValue() {\n        return noMinValue;\n    }\n\n    public void setNoMinValue(boolean noMinValue) {\n        this.noMinValue = noMinValue;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public SQLExpr getCacheValue() {\n        return cacheValue;\n    }\n\n    public void setCacheValue(SQLExpr cacheValue) {\n        if (cacheValue != null) {\n            cacheValue.setParent(this);\n        }\n        this.cacheValue = cacheValue;\n    }\n\n    public boolean isSimple() {\n        return simple;\n    }\n\n    public void setSimple(boolean simple) {\n        this.simple = simple;\n    }\n\n    public boolean isGroup() {\n        return group;\n    }\n\n    public void setGroup(boolean group) {\n        this.group = group;\n    }\n\n    public SQLExpr getUnitCount() {\n        return unitCount;\n    }\n\n    public void setUnitCount(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.unitCount = x;\n    }\n\n    public SQLExpr getUnitIndex() {\n        return unitIndex;\n    }\n\n    public void setUnitIndex(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.unitIndex = x;\n    }\n\n    public boolean isTime() {\n        return time;\n    }\n\n    public void setTime(boolean time) {\n        this.time = time;\n    }\n\n    public Boolean getWithCache() {\n        return withCache;\n    }\n\n    public void setWithCache(Boolean withCache) {\n        this.withCache = withCache;\n    }\n\n    public SQLExpr getStep() {\n        return step;\n    }\n\n    public void setStep(SQLExpr step) {\n        if (step != null) {\n            step.setParent(this);\n        }\n        this.step = step;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.SEQUENCE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\n\npublic interface SQLCreateStatement extends SQLDDLStatement {\n    default SQLName getName() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCreateTableGroupStatement extends SQLStatementImpl implements SQLCreateStatement {\n    protected SQLName name;\n    protected boolean ifNotExists;\n    protected SQLExpr partitionNum;\n\n    public SQLCreateTableGroupStatement() {\n    }\n\n    public SQLCreateTableGroupStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public String getSchemaName() {\n        if (name instanceof SQLPropertyExpr) {\n            return SQLUtils.toMySqlString(((SQLPropertyExpr) name).getOwner());\n        }\n        return null;\n    }\n\n    public void setSchemaName(String name) {\n        if (name != null) {\n            this.name = new SQLPropertyExpr(name, getTableGroupName());\n        }\n    }\n\n    public String getTableGroupName() {\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getName();\n        } else if (name instanceof SQLIdentifierExpr) {\n            return ((SQLIdentifierExpr) name).getName();\n        } else if (name instanceof SQLCharExpr) {\n            return ((SQLCharExpr) name).getText();\n        }\n        return null;\n    }\n\n    public SQLExpr getPartitionNum() {\n        return partitionNum;\n    }\n\n    public void setPartitionNum(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.partitionNum = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSynonymStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.ListDG;\nimport com.alibaba.druid.util.lang.Consumer;\n\nimport java.math.BigDecimal;\nimport java.util.*;\n\npublic class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLStatement, SQLCreateStatement {\n    protected int features;\n    protected SQLExprTableSource tableSource;\n    protected List<SQLTableElement> tableElementList = new ArrayList<SQLTableElement>();\n\n    // for postgresql\n    protected SQLExprTableSource inherits;\n    protected SQLSelect select;\n    protected SQLExpr comment;\n    protected SQLExprTableSource like;\n\n    protected Boolean compress;\n    protected Boolean logging;\n\n    protected SQLName tablespace;\n    protected SQLPartitionBy partitionBy;\n    protected SQLPartitionOf partitionOf;\n    protected SQLPartitionBy localPartitioning;\n    protected SQLUnique unique;\n    protected SQLExpr storedAs;\n    protected SQLExpr storedBy;\n    protected SQLExpr location;\n    protected SQLExpr engine;\n    protected SQLOrderBy orderBy;\n\n    protected boolean onCommitPreserveRows;\n    protected boolean onCommitDeleteRows;\n\n    // for odps & hive\n    protected SQLExternalRecordFormat rowFormat;\n    protected final List<SQLColumnDefinition> partitionColumns = new ArrayList<SQLColumnDefinition>(2);\n    protected ClusteringType clusteringType;\n    protected final List<SQLSelectOrderByItem> clusteredBy = new ArrayList<SQLSelectOrderByItem>();\n    protected final List<SQLSelectOrderByItem> sortedBy = new ArrayList<SQLSelectOrderByItem>();\n    protected boolean isAutoBucket;\n    protected int buckets;\n    protected int shards;\n    protected final List<SQLAssignItem> tableOptions = new ArrayList<SQLAssignItem>();\n//    protected final List<SQLAssignItem> tblProperties = new ArrayList<SQLAssignItem>();\n\n    protected boolean replace;\n    protected boolean ignore;\n    protected boolean single; // polardbx\n\n    protected SQLExpr lifeCycle;\n\n    public SQLCreateTableStatement() {\n        isAutoBucket = false;\n    }\n\n    public SQLCreateTableStatement(DbType dbType) {\n        super(dbType);\n        isAutoBucket = false;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        this.acceptChild(v, tableSource);\n        this.acceptChild(v, tableElementList);\n        this.acceptChild(v, inherits);\n        this.acceptChild(v, select);\n        this.acceptChild(v, comment);\n        this.acceptChild(v, like);\n\n        this.acceptChild(v, tablespace);\n        this.acceptChild(v, partitionBy);\n        this.acceptChild(v, localPartitioning);\n        this.acceptChild(v, storedAs);\n        this.acceptChild(v, storedBy);\n        this.acceptChild(v, location);\n        this.acceptChild(v, unique);\n\n        this.acceptChild(v, partitionColumns);\n        this.acceptChild(v, clusteredBy);\n        this.acceptChild(v, sortedBy);\n        this.acceptChild(v, tableOptions);\n//        this.acceptChild(v, tblProperties);\n        this.acceptChild(v, lifeCycle);\n    }\n\n    public boolean isAutoBucket() {\n        return isAutoBucket;\n    }\n\n    public void setAutoBucket(boolean autoBucket) {\n        isAutoBucket = autoBucket;\n    }\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.engine = x;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        if (orderBy != null) {\n            orderBy.setParent(this);\n        }\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public SQLName getName() {\n        if (tableSource == null) {\n            return null;\n        }\n\n        return (SQLName) tableSource.getExpr();\n    }\n\n    public String getTableName() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n        return name.getSimpleName();\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public void setSchema(String name) {\n        if (this.tableSource == null) {\n            return;\n        }\n        tableSource.setSchema(name);\n    }\n\n    public void setName(SQLName name) {\n        this.setTableSource(new SQLExprTableSource(name));\n    }\n\n    public void setName(String name) {\n        this.setName(new SQLIdentifierExpr(name));\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public void setTableName(String tableName) {\n        SQLExpr name = SQLUtils.toSQLExpr(tableName, dbType);\n        setTableSource(new SQLExprTableSource(name));\n    }\n\n    public void config(Feature feature) {\n        config(feature, true);\n    }\n\n    public boolean isEnabled(Feature feature) {\n        return feature.isEnabled(this.features);\n    }\n\n    public void config(Feature feature, boolean state) {\n        this.features = feature.config(this.features, state);\n    }\n\n    public boolean isTemporary() {\n        return Feature.Temporary.isEnabled(features);\n    }\n\n    public void setTemporary(boolean value) {\n        this.features = Feature.Temporary.config(features, value);\n    }\n\n    public List<SQLTableElement> getTableElementList() {\n        return tableElementList;\n    }\n\n    public SQLColumnDefinition getColumn(String columnName) {\n        long hashCode64 = FnvHash.hashCode64(columnName);\n\n        for (SQLTableElement e : tableElementList) {\n            if (e instanceof SQLColumnDefinition) {\n                SQLColumnDefinition column = (SQLColumnDefinition) e;\n                if (column.nameHashCode64() == hashCode64) {\n                    return column;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public List<SQLColumnDefinition> getColumnDefinitions() {\n        ArrayList<SQLColumnDefinition> column = new ArrayList<SQLColumnDefinition>();\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof SQLColumnDefinition) {\n                column.add((SQLColumnDefinition) element);\n            }\n        }\n        return column;\n    }\n\n    public List<String> getColumnNames(boolean normalized) {\n        List<String> columnNames = new ArrayList<String>();\n        for (SQLColumnDefinition definition : getColumnDefinitions()) {\n            String columnName = (definition.getColumnName());\n            if (normalized) {\n                columnName = SQLUtils.normalize(columnName);\n            }\n            columnNames.add(columnName);\n        }\n\n        return columnNames;\n    }\n\n    public List<String> getColumnComments() {\n        List<String> comments = new ArrayList<String>();\n        for (SQLColumnDefinition definition : getColumnDefinitions()) {\n            comments.add(((SQLCharExpr) definition.getComment()).getText());\n        }\n        return comments;\n    }\n\n    public List<String> getPrimaryKeyNames() {\n        List<String> keys = new ArrayList<String>();\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof MySqlPrimaryKey) {\n                List<SQLSelectOrderByItem> columns = ((MySqlPrimaryKey) element).getColumns();\n                for (SQLSelectOrderByItem column : columns) {\n                    keys.add(SQLUtils.normalize(column.getExpr().toString()));\n                }\n            }\n        }\n        return keys;\n    }\n\n    public void addColumn(String columnName, String dataType) {\n        SQLColumnDefinition column = new SQLColumnDefinition();\n        column.setName(columnName);\n        column.setDataType(\n                SQLParserUtils.createExprParser(dataType, dbType).parseDataType()\n        );\n        addColumn(column);\n    }\n\n    public void addColumn(String name, SQLDataType dataType) {\n        addColumn(new SQLColumnDefinition(name, dataType));\n    }\n\n    public void addColumn(SQLColumnDefinition column) {\n        if (column == null) {\n            throw new IllegalArgumentException();\n        }\n        column.setParent(this);\n        tableElementList.add(column);\n    }\n\n    public boolean isIfNotExists() {\n        return Feature.IfNotExists.isEnabled(features);\n    }\n\n    public void setIfNotExists(boolean value) {\n        this.features = Feature.IfNotExists.config(this.features, value);\n    }\n\n    public SQLExprTableSource getInherits() {\n        return inherits;\n    }\n\n    public void setInherits(SQLExprTableSource inherits) {\n        if (inherits != null) {\n            inherits.setParent(this);\n        }\n        this.inherits = inherits;\n    }\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect select) {\n        if (select != null) {\n            select.setParent(this);\n        }\n        this.select = select;\n    }\n\n    public SQLUnique getUnique() {\n        return unique;\n    }\n\n    public void setUnique(SQLUnique unique) {\n        if (unique != null) {\n            unique.setParent(this);\n        }\n        this.unique = unique;\n    }\n\n    public SQLExprTableSource getLike() {\n        return like;\n    }\n\n    public void setLike(SQLName like) {\n        this.setLike(new SQLExprTableSource(like));\n    }\n\n    public void setLike(SQLExprTableSource like) {\n        if (like != null) {\n            like.setParent(this);\n        }\n        this.like = like;\n    }\n\n    public Boolean getCompress() {\n        return compress;\n    }\n\n    public void setCompress(Boolean compress) {\n        this.compress = compress;\n    }\n\n    public Boolean getLogging() {\n        return logging;\n    }\n\n    public void setLogging(Boolean logging) {\n        this.logging = logging;\n    }\n\n    public SQLName getTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.tablespace = x;\n    }\n\n    public SQLPartitionBy getPartitioning() {\n        return partitionBy;\n    }\n\n    public SQLPartitionBy getLocalPartitioning() {\n        return this.localPartitioning;\n    }\n\n    public void setPartitionBy(SQLPartitionBy partitionBy) {\n        if (partitionBy != null) {\n            partitionBy.setParent(this);\n        }\n\n        this.partitionBy = partitionBy;\n    }\n\n    public SQLPartitionOf getPartitionOf() {\n        return partitionOf;\n    }\n\n    public void setPartitionOf(SQLPartitionOf partitionOf) {\n        if (partitionOf != null) {\n            partitionOf.setParent(this);\n        }\n        this.partitionOf = partitionOf;\n    }\n    public void setLocalPartitioning(SQLPartitionBy localPartitioning) {\n        if (localPartitioning != null) {\n            localPartitioning.setParent(this);\n        }\n\n        this.localPartitioning = localPartitioning;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.add(tableSource);\n        children.addAll(tableElementList);\n        if (inherits != null) {\n            children.add(inherits);\n        }\n        if (select != null) {\n            children.add(select);\n        }\n        return children;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public void addBodyBeforeComment(List<String> comments) {\n        if (attributes == null) {\n            attributes = new HashMap<String, Object>(1);\n        }\n\n        List<String> attrComments = (List<String>) attributes.get(\"rowFormat.body_before_comment\");\n        if (attrComments == null) {\n            attributes.put(\"rowFormat.body_before_comment\", comments);\n        } else {\n            attrComments.addAll(comments);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public List<String> getBodyBeforeCommentsDirect() {\n        if (attributes == null) {\n            return null;\n        }\n\n        return (List<String>) attributes.get(\"rowFormat.body_before_comment\");\n    }\n\n    public boolean hasBodyBeforeComment() {\n        List<String> comments = getBodyBeforeCommentsDirect();\n        if (comments == null) {\n            return false;\n        }\n\n        return !comments.isEmpty();\n    }\n\n    public String computeName() {\n        if (tableSource == null) {\n            return null;\n        }\n\n        SQLExpr expr = tableSource.getExpr();\n        if (expr instanceof SQLName) {\n            String name = ((SQLName) expr).getSimpleName();\n            return SQLUtils.normalize(name);\n        }\n\n        return null;\n    }\n\n    public boolean containsColumn(String columName) {\n        return findColumn(columName) != null;\n    }\n\n    public SQLColumnDefinition findColumn(String columName) {\n        if (columName == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(columName);\n        return findColumn(hash);\n    }\n\n    public SQLColumnDefinition findColumn(long columName_hash) {\n        for (SQLTableElement element : tableElementList) {\n            if (element instanceof SQLColumnDefinition) {\n                SQLColumnDefinition column = (SQLColumnDefinition) element;\n                if (column.nameHashCode64() == columName_hash) {\n                    return column;\n                }\n            }\n        }\n\n        for (SQLColumnDefinition column : partitionColumns) {\n            if (column.nameHashCode64() == columName_hash) {\n                return column;\n            }\n        }\n\n        return null;\n    }\n\n    public boolean isPrimaryColumn(String columnName) {\n        SQLPrimaryKey pk = this.findPrimaryKey();\n\n        if (pk != null && pk.containsColumn(columnName)) {\n            return true;\n        }\n\n        for (SQLColumnDefinition element : this.getColumnDefinitions()) {\n            for (SQLColumnConstraint constraint : element.constraints) {\n                if (constraint instanceof SQLColumnPrimaryKey\n                        && SQLUtils.normalize(element.getColumnName()).equalsIgnoreCase(SQLUtils.normalize(columnName))) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public boolean isPrimaryColumn(long columnNameHash) {\n        SQLPrimaryKey pk = this.findPrimaryKey();\n        if (pk == null) {\n            return false;\n        }\n\n        return pk.containsColumn(columnNameHash);\n    }\n\n    public boolean isOnlyPrimaryKey(long columnNameHash) {\n        SQLPrimaryKey pk = this.findPrimaryKey();\n        if (pk == null) {\n            return false;\n        }\n\n        return pk.containsColumn(columnNameHash) && pk.getColumns().size() == 1;\n    }\n\n    /**\n     * only for show columns\n     */\n    public boolean isMUL(String columnName) {\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof MySqlUnique) {\n                MySqlUnique unique = (MySqlUnique) element;\n\n                SQLExpr column = unique.getColumns().get(0).getExpr();\n                if (column instanceof SQLIdentifierExpr\n                        && SQLUtils.nameEquals(columnName, ((SQLIdentifierExpr) column).getName())) {\n                    return unique.getColumns().size() > 1;\n                } else if (column instanceof SQLMethodInvokeExpr\n                        && SQLUtils.nameEquals(((SQLMethodInvokeExpr) column).getMethodName(), columnName)) {\n                    return true;\n                }\n            } else if (element instanceof MySqlKey) {\n                MySqlKey unique = (MySqlKey) element;\n\n                SQLExpr column = unique.getColumns().get(0).getExpr();\n                if (column instanceof SQLIdentifierExpr\n                        && SQLUtils.nameEquals(columnName, ((SQLIdentifierExpr) column).getName())) {\n                    return true;\n                } else if (column instanceof SQLMethodInvokeExpr\n                        && SQLUtils.nameEquals(((SQLMethodInvokeExpr) column).getMethodName(), columnName)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    /**\n     * only for show columns\n     */\n    public boolean isUNI(String columnName) {\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof MySqlUnique) {\n                MySqlUnique unique = (MySqlUnique) element;\n\n                if (unique.getColumns().isEmpty()) {\n                    continue;\n                }\n\n                SQLExpr column = unique.getColumns().get(0).getExpr();\n                if (column instanceof SQLIdentifierExpr\n                        && SQLUtils.nameEquals(columnName, ((SQLIdentifierExpr) column).getName())) {\n                    return unique.getColumns().size() == 1;\n                } else if (column instanceof SQLMethodInvokeExpr\n                        && SQLUtils.nameEquals(((SQLMethodInvokeExpr) column).getMethodName(), columnName)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public MySqlUnique findUnique(String columnName) {\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof MySqlUnique) {\n                MySqlUnique unique = (MySqlUnique) element;\n\n                if (unique.containsColumn(columnName)) {\n                    return unique;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public SQLTableElement findIndex(String columnName) {\n        for (SQLTableElement element : tableElementList) {\n            if (element instanceof SQLUniqueConstraint) {\n                SQLUniqueConstraint unique = (SQLUniqueConstraint) element;\n                for (SQLSelectOrderByItem item : unique.getColumns()) {\n                    SQLExpr columnExpr = item.getExpr();\n                    if (columnExpr instanceof SQLIdentifierExpr) {\n                        String keyColumName = ((SQLIdentifierExpr) columnExpr).getName();\n                        keyColumName = SQLUtils.normalize(keyColumName);\n                        if (keyColumName.equalsIgnoreCase(columnName)) {\n                            return element;\n                        }\n                    }\n                }\n\n            } else if (element instanceof MySqlTableIndex) {\n                List<SQLSelectOrderByItem> indexColumns = ((MySqlTableIndex) element).getColumns();\n                for (SQLSelectOrderByItem orderByItem : indexColumns) {\n                    SQLExpr columnExpr = orderByItem.getExpr();\n                    if (columnExpr instanceof SQLIdentifierExpr) {\n                        String keyColumName = ((SQLIdentifierExpr) columnExpr).getName();\n                        keyColumName = SQLUtils.normalize(keyColumName);\n                        if (keyColumName.equalsIgnoreCase(columnName)) {\n                            return element;\n                        }\n                    }\n                }\n            }\n\n        }\n\n        return null;\n    }\n\n    public void forEachColumn(Consumer<SQLColumnDefinition> columnConsumer) {\n        if (columnConsumer == null) {\n            return;\n        }\n\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof SQLColumnDefinition) {\n                columnConsumer.accept((SQLColumnDefinition) element);\n            }\n        }\n    }\n\n    public SQLPrimaryKey findPrimaryKey() {\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof SQLPrimaryKey) {\n                return (SQLPrimaryKey) element;\n            }\n        }\n\n        return null;\n    }\n\n    public List<SQLForeignKeyConstraint> findForeignKey() {\n        List<SQLForeignKeyConstraint> fkList = new ArrayList<SQLForeignKeyConstraint>();\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof SQLForeignKeyConstraint) {\n                fkList.add((SQLForeignKeyConstraint) element);\n            }\n        }\n        return fkList;\n    }\n\n    public boolean hashForeignKey() {\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof SQLForeignKeyConstraint) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public boolean isReferenced(SQLName tableName) {\n        if (tableName == null) {\n            return false;\n        }\n\n        return isReferenced(tableName.getSimpleName());\n    }\n\n    public boolean isReferenced(String tableName) {\n        if (tableName == null) {\n            return false;\n        }\n\n        tableName = SQLUtils.normalize(tableName);\n\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof SQLForeignKeyConstraint) {\n                SQLForeignKeyConstraint fk = (SQLForeignKeyConstraint) element;\n                String refTableName = fk.getReferencedTableName().getSimpleName();\n\n                if (SQLUtils.nameEquals(tableName, refTableName)) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public SQLAlterTableStatement foreignKeyToAlterTable() {\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement();\n        for (int i = this.tableElementList.size() - 1; i >= 0; --i) {\n            SQLTableElement element = this.tableElementList.get(i);\n            if (element instanceof SQLForeignKeyConstraint) {\n                SQLForeignKeyConstraint fk = (SQLForeignKeyConstraint) element;\n                this.tableElementList.remove(i);\n                stmt.addItem(new SQLAlterTableAddConstraint(fk));\n            }\n        }\n\n        if (stmt.getItems().isEmpty()) {\n            return null;\n        }\n\n        stmt.setDbType(getDbType());\n        stmt.setTableSource(this.tableSource.clone());\n\n        Collections.reverse(stmt.getItems());\n\n        return stmt;\n    }\n\n    public static void sort(List<SQLStatement> stmtList) {\n        Map<String, SQLCreateTableStatement> tables = new HashMap<String, SQLCreateTableStatement>();\n        Map<String, List<SQLCreateTableStatement>> referencedTables = new HashMap<String, List<SQLCreateTableStatement>>();\n\n        for (SQLStatement stmt : stmtList) {\n            if (stmt instanceof SQLCreateTableStatement) {\n                SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) stmt;\n                String tableName = createTableStmt.getName().getSimpleName();\n                tableName = SQLUtils.normalize(tableName).toLowerCase();\n                tables.put(tableName, createTableStmt);\n            }\n        }\n\n        List<ListDG.Edge> edges = new ArrayList<ListDG.Edge>();\n\n        for (SQLCreateTableStatement stmt : tables.values()) {\n            for (SQLTableElement element : stmt.getTableElementList()) {\n                if (element instanceof SQLForeignKeyConstraint) {\n                    SQLForeignKeyConstraint fk = (SQLForeignKeyConstraint) element;\n                    String refTableName = fk.getReferencedTableName().getSimpleName();\n                    refTableName = SQLUtils.normalize(refTableName).toLowerCase();\n\n                    SQLCreateTableStatement refTable = tables.get(refTableName);\n                    if (refTable != null) {\n                        edges.add(new ListDG.Edge(stmt, refTable));\n                    }\n\n                    List<SQLCreateTableStatement> referencedList = referencedTables.get(refTableName);\n                    if (referencedList == null) {\n                        referencedList = new ArrayList<SQLCreateTableStatement>();\n                        referencedTables.put(refTableName, referencedList);\n                    }\n                    referencedList.add(stmt);\n                }\n            }\n        }\n\n        for (SQLStatement stmt : stmtList) {\n            if (stmt instanceof OracleCreateSynonymStatement) {\n                OracleCreateSynonymStatement createSynonym = (OracleCreateSynonymStatement) stmt;\n                SQLName object = createSynonym.getObject();\n                String refTableName = object.getSimpleName();\n                SQLCreateTableStatement refTable = tables.get(refTableName);\n                if (refTable != null) {\n                    edges.add(new ListDG.Edge(stmt, refTable));\n                }\n            }\n        }\n\n        ListDG dg = new ListDG(stmtList, edges);\n\n        SQLStatement[] tops = new SQLStatement[stmtList.size()];\n        if (dg.topologicalSort(tops)) {\n            for (int i = 0, size = stmtList.size(); i < size; ++i) {\n                stmtList.set(i, tops[size - i - 1]);\n            }\n            return;\n        }\n\n        List<SQLAlterTableStatement> alterList = new ArrayList<SQLAlterTableStatement>();\n\n        for (int i = edges.size() - 1; i >= 0; --i) {\n            ListDG.Edge edge = edges.get(i);\n            SQLCreateTableStatement from = (SQLCreateTableStatement) edge.from;\n            String fromTableName = from.getName().getSimpleName();\n            fromTableName = SQLUtils.normalize(fromTableName).toLowerCase();\n            if (referencedTables.containsKey(fromTableName)) {\n                edges.remove(i);\n\n                Arrays.fill(tops, null);\n                tops = new SQLStatement[stmtList.size()];\n\n                dg = new ListDG(stmtList, edges);\n                if (dg.topologicalSort(tops)) {\n                    for (int j = 0, size = stmtList.size(); j < size; ++j) {\n                        SQLStatement stmt = tops[size - j - 1];\n                        stmtList.set(j, stmt);\n                    }\n\n                    SQLAlterTableStatement alter = from.foreignKeyToAlterTable();\n                    alterList.add(alter);\n\n                    stmtList.add(alter);\n                    return;\n                }\n                edges.add(i, edge);\n            }\n        }\n\n        for (int i = edges.size() - 1; i >= 0; --i) {\n            ListDG.Edge edge = edges.get(i);\n            SQLCreateTableStatement from = (SQLCreateTableStatement) edge.from;\n            String fromTableName = from.getName().getSimpleName();\n            fromTableName = SQLUtils.normalize(fromTableName).toLowerCase();\n            if (referencedTables.containsKey(fromTableName)) {\n                SQLAlterTableStatement alter = from.foreignKeyToAlterTable();\n\n                edges.remove(i);\n                if (alter != null) {\n                    alterList.add(alter);\n                }\n\n                Arrays.fill(tops, null);\n                tops = new SQLStatement[stmtList.size()];\n\n                dg = new ListDG(stmtList, edges);\n                if (dg.topologicalSort(tops)) {\n                    for (int j = 0, size = stmtList.size(); j < size; ++j) {\n                        SQLStatement stmt = tops[size - j - 1];\n                        stmtList.set(j, stmt);\n                    }\n\n                    stmtList.addAll(alterList);\n                    return;\n                }\n            }\n        }\n    }\n\n    public void simplify() {\n        SQLName name = getName();\n        if (name instanceof SQLPropertyExpr) {\n            String tableName = ((SQLPropertyExpr) name).getName();\n            tableName = SQLUtils.normalize(tableName);\n\n            String normalized = SQLUtils.normalize(tableName, dbType);\n            if (tableName != normalized) {\n                this.setName(normalized);\n                name = getName();\n            }\n        }\n\n        if (name instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) name;\n            String tableName = identExpr.getName();\n            String normalized = SQLUtils.normalize(tableName, dbType);\n            if (normalized != tableName) {\n                setName(normalized);\n            }\n        }\n\n        for (SQLTableElement element : this.tableElementList) {\n            if (element instanceof SQLColumnDefinition) {\n                SQLColumnDefinition column = (SQLColumnDefinition) element;\n                column.simplify();\n            } else if (element instanceof SQLConstraint) {\n                ((SQLConstraint) element).simplify();\n            }\n        }\n    }\n\n    public boolean apply(SQLDropIndexStatement x) {\n        long indexNameHashCode64 = x.getIndexName().nameHashCode64();\n\n        for (int i = tableElementList.size() - 1; i >= 0; i--) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLUniqueConstraint) {\n                SQLUniqueConstraint unique = (SQLUniqueConstraint) e;\n                if (unique.getName() != null && unique.getName().nameHashCode64() == indexNameHashCode64) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n\n            } else if (e instanceof MySqlTableIndex) {\n                MySqlTableIndex tableIndex = (MySqlTableIndex) e;\n                if (SQLUtils.nameEquals(tableIndex.getName(), x.getIndexName())) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public boolean apply(SQLCommentStatement x) {\n        SQLName on = x.getOn().getName();\n        SQLExpr comment = x.getComment();\n        if (comment == null) {\n            return false;\n        }\n\n        SQLCommentStatement.Type type = x.getType();\n        if (type == SQLCommentStatement.Type.TABLE) {\n            if (!SQLUtils.nameEquals(getName(), on)) {\n                return false;\n            }\n\n            setComment(comment.clone());\n\n            return true;\n        } else if (type == SQLCommentStatement.Type.COLUMN) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) on;\n            if (!SQLUtils.nameEquals(getName(), (SQLName) propertyExpr.getOwner())) {\n                return false;\n            }\n\n            SQLColumnDefinition column\n                    = this.findColumn(\n                    propertyExpr.nameHashCode64());\n\n            if (column != null) {\n                column.setComment(comment.clone());\n            }\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean apply(SQLAlterTableStatement alter) {\n        if (!SQLUtils.nameEquals(alter.getName(), this.getName())) {\n            return false;\n        }\n\n        int applyCount = 0;\n        for (SQLAlterTableItem item : alter.getItems()) {\n            if (alterApply(item)) {\n                applyCount++;\n            }\n        }\n\n        return applyCount > 0;\n    }\n\n    protected boolean alterApply(SQLAlterTableItem item) {\n        if (item instanceof SQLAlterTableDropColumnItem) {\n            return apply((SQLAlterTableDropColumnItem) item);\n\n        } else if (item instanceof SQLAlterTableAddColumn) {\n            return apply((SQLAlterTableAddColumn) item);\n\n        } else if (item instanceof SQLAlterTableAddConstraint) {\n            return apply((SQLAlterTableAddConstraint) item);\n\n        } else if (item instanceof SQLAlterTableDropPrimaryKey) {\n            return apply((SQLAlterTableDropPrimaryKey) item);\n\n        } else if (item instanceof SQLAlterTableDropIndex) {\n            return apply((SQLAlterTableDropIndex) item);\n\n        } else if (item instanceof SQLAlterTableDropConstraint) {\n            return apply((SQLAlterTableDropConstraint) item);\n        } else if (item instanceof SQLAlterTableDropCheck) {\n            return apply((SQLAlterTableDropCheck) item);\n\n        } else if (item instanceof SQLAlterTableDropKey) {\n            return apply((SQLAlterTableDropKey) item);\n\n        } else if (item instanceof SQLAlterTableDropForeignKey) {\n            return apply((SQLAlterTableDropForeignKey) item);\n\n        } else if (item instanceof SQLAlterTableRename) {\n            return apply((SQLAlterTableRename) item);\n\n        } else if (item instanceof SQLAlterTableRenameColumn) {\n            return apply((SQLAlterTableRenameColumn) item);\n\n        } else if (item instanceof SQLAlterTableAddIndex) {\n            return apply((SQLAlterTableAddIndex) item);\n        } else if (item instanceof SQLAlterTableTruncatePartition) {\n            return apply((SQLAlterTableTruncatePartition) item);\n        }\n\n        return false;\n    }\n\n    // SQLAlterTableRenameColumn\n\n    private boolean apply(SQLAlterTableRenameColumn item) {\n        int columnIndex = columnIndexOf(item.getColumn());\n        if (columnIndex == -1) {\n            return false;\n        }\n\n        SQLColumnDefinition column = (SQLColumnDefinition) tableElementList.get(columnIndex);\n        column.setName(item.getTo().clone());\n\n        return true;\n    }\n\n    public boolean renameColumn(String colummName, String newColumnName) {\n        if (colummName == null || newColumnName == null || newColumnName.length() == 0) {\n            return false;\n        }\n\n        int columnIndex = columnIndexOf(new SQLIdentifierExpr(colummName));\n        if (columnIndex == -1) {\n            return false;\n        }\n\n        SQLColumnDefinition column = (SQLColumnDefinition) tableElementList.get(columnIndex);\n        column.setName(new SQLIdentifierExpr(newColumnName));\n\n        return true;\n    }\n\n    private boolean apply(SQLAlterTableRename item) {\n        SQLName name = item.getToName();\n        if (name == null) {\n            return false;\n        }\n\n        this.setName(name.clone());\n\n        return true;\n    }\n\n    private boolean apply(SQLAlterTableDropForeignKey item) {\n        for (int i = tableElementList.size() - 1; i >= 0; i--) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLForeignKeyConstraint) {\n                SQLForeignKeyConstraint fk = (SQLForeignKeyConstraint) e;\n                if (SQLUtils.nameEquals(fk.getName(), item.getIndexName())) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private boolean apply(SQLAlterTableDropKey item) {\n        for (int i = tableElementList.size() - 1; i >= 0; i--) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLUniqueConstraint) {\n                SQLUniqueConstraint unique = (SQLUniqueConstraint) e;\n                if (SQLUtils.nameEquals(unique.getName(), item.getKeyName())) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private boolean apply(SQLAlterTableDropConstraint item) {\n        for (int i = tableElementList.size() - 1; i >= 0; i--) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLConstraint) {\n                SQLConstraint constraint = (SQLConstraint) e;\n                if (SQLUtils.nameEquals(constraint.getName(), item.getConstraintName())) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n    private boolean apply(SQLAlterTableDropCheck item) {\n        for (int i = tableElementList.size() - 1; i >= 0; i--) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLConstraint) {\n                SQLConstraint constraint = (SQLConstraint) e;\n                if (SQLUtils.nameEquals(constraint.getName(), item.getCheckName())) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private boolean apply(SQLAlterTableDropIndex item) {\n        for (int i = tableElementList.size() - 1; i >= 0; i--) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLUniqueConstraint) {\n                SQLUniqueConstraint unique = (SQLUniqueConstraint) e;\n                if (SQLUtils.nameEquals(unique.getName(), item.getIndexName())) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n\n            } else if (e instanceof MySqlTableIndex) {\n                MySqlTableIndex tableIndex = (MySqlTableIndex) e;\n                if (SQLUtils.nameEquals(tableIndex.getName(), item.getIndexName())) {\n                    tableElementList.remove(i);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private boolean apply(SQLAlterTableDropPrimaryKey item) {\n        for (int i = tableElementList.size() - 1; i >= 0; i--) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLPrimaryKey) {\n                tableElementList.remove(i);\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private boolean apply(SQLAlterTableAddConstraint item) {\n        SQLName name = item.getConstraint().getName();\n        if (name != null) {\n            long nameHashCode = name.nameHashCode64();\n            for (int i = tableElementList.size() - 1; i >= 0; i--) {\n                SQLTableElement e = tableElementList.get(i);\n                if (e instanceof SQLConstraint) {\n                    SQLName name1 = ((SQLConstraint) e).getName();\n                    if (name1 != null && name1.nameHashCode64() == nameHashCode) {\n                        return false;\n                    }\n                }\n            }\n        }\n        tableElementList.add((SQLTableElement) item.getConstraint());\n        return true;\n    }\n\n    private boolean apply(SQLAlterTableDropColumnItem item) {\n        for (SQLName column : item.getColumns()) {\n            String columnName = column.getSimpleName();\n            for (int i = tableElementList.size() - 1; i >= 0; --i) {\n                SQLTableElement e = tableElementList.get(i);\n                if (e instanceof SQLColumnDefinition) {\n                    if (SQLUtils.nameEquals(columnName, ((SQLColumnDefinition) e).getName().getSimpleName())) {\n                        tableElementList.remove(i);\n                    }\n                }\n            }\n\n            for (int i = tableElementList.size() - 1; i >= 0; --i) {\n                SQLTableElement e = tableElementList.get(i);\n                if (e instanceof SQLUnique) {\n                    SQLUnique unique = (SQLUnique) e;\n                    unique.applyDropColumn(column);\n                    if (unique.getColumns().isEmpty()) {\n                        tableElementList.remove(i);\n                    }\n                } else if (e instanceof MySqlTableIndex) {\n                    MySqlTableIndex index = (MySqlTableIndex) e;\n                    index.applyDropColumn(column);\n                    if (index.getColumns().isEmpty()) {\n                        tableElementList.remove(i);\n                    }\n                }\n            }\n        }\n\n        return true;\n    }\n\n    protected boolean apply(SQLAlterTableTruncatePartition item) {\n        return false;\n    }\n    protected boolean apply(SQLAlterTableAddIndex item) {\n        return false;\n    }\n\n    private boolean apply(SQLAlterTableAddColumn item) {\n        int startIndex = tableElementList.size();\n        if (item.isFirst()) {\n            startIndex = 0;\n        }\n\n        int afterIndex = columnIndexOf(item.getAfterColumn());\n        if (afterIndex != -1) {\n            startIndex = afterIndex + 1;\n        }\n\n        int beforeIndex = columnIndexOf(item.getFirstColumn());\n        if (beforeIndex != -1) {\n            startIndex = beforeIndex;\n        }\n\n        for (int i = 0; i < item.getColumns().size(); i++) {\n            SQLColumnDefinition column = item.getColumns().get(i);\n\n            int matchIndex = -1;\n            for (int j = 0; j < tableElementList.size(); j++) {\n                SQLTableElement element = tableElementList.get(j);\n\n                if (element instanceof SQLColumnDefinition) {\n                    if (column.nameHashCode64() == (((SQLColumnDefinition) element)).nameHashCode64()) {\n                        matchIndex = j;\n                        break;\n                    }\n                }\n            }\n\n            if (matchIndex != -1) {\n                return false;\n            }\n\n            tableElementList.add(i + startIndex, column);\n\n            column.setParent(this);\n        }\n\n        return true;\n    }\n\n    protected int columnIndexOf(SQLName column) {\n        if (column == null) {\n            return -1;\n        }\n\n        String columnName = column.getSimpleName();\n        for (int i = tableElementList.size() - 1; i >= 0; --i) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof SQLColumnDefinition) {\n                if (SQLUtils.nameEquals(columnName, ((SQLColumnDefinition) e).getName().getSimpleName())) {\n                    return i;\n                }\n            }\n        }\n\n        return -1;\n    }\n\n    public void cloneTo(SQLCreateTableStatement x) {\n        x.features = features;\n\n        if (tableSource != null) {\n            x.setTableSource(tableSource.clone());\n        }\n\n        for (SQLTableElement e : tableElementList) {\n            SQLTableElement e2 = e.clone();\n            e2.setParent(x);\n            x.tableElementList.add(e2);\n        }\n\n        for (SQLColumnDefinition e : partitionColumns) {\n            SQLColumnDefinition e2 = e.clone();\n            e2.setParent(x);\n            x.partitionColumns.add(e2);\n        }\n\n        if (inherits != null) {\n            x.setInherits(inherits.clone());\n        }\n\n        if (select != null) {\n            x.setSelect(select.clone());\n        }\n\n        if (comment != null) {\n            x.setComment(comment.clone());\n        }\n\n        if (partitionBy != null) {\n            x.setPartitionBy(partitionBy.clone());\n        }\n\n        if (like != null) {\n            x.setLike(like.clone());\n        }\n\n        x.compress = compress;\n        x.logging = logging;\n\n        if (tablespace != null) {\n            x.setTablespace(tablespace.clone());\n        }\n\n        if (partitionBy != null) {\n            x.setPartitionBy(partitionBy.clone());\n        }\n\n        if (localPartitioning != null) {\n            x.setLocalPartitioning(localPartitioning.clone());\n        }\n\n        if (storedAs != null) {\n            x.setStoredAs(storedAs.clone());\n        }\n        if (storedBy != null) {\n            x.setStoredBy(storedBy.clone());\n        }\n\n        if (lifeCycle != null) {\n            x.setLifeCycle(lifeCycle.clone());\n        }\n\n        if (location != null) {\n            x.setLocation(location.clone());\n        }\n\n        x.onCommitPreserveRows = onCommitPreserveRows;\n        x.onCommitDeleteRows = onCommitDeleteRows;\n\n        for (SQLAssignItem item : this.tableOptions) {\n            SQLAssignItem item2 = item.clone();\n            item2.setParent(item);\n            x.tableOptions.add(item2);\n        }\n\n//        for (SQLAssignItem item : this.tblProperties) {\n//            SQLAssignItem item2 = item.clone();\n//            item2.setParent(item);\n//            x.tblProperties.add(item2);\n//        }\n\n        if (rowFormat != null) {\n            x.setRowFormat(rowFormat.clone());\n        }\n\n        if (clusteringType != null) {\n            x.setClusteringType(clusteringType);\n        }\n\n        for (SQLSelectOrderByItem e : clusteredBy) {\n            SQLSelectOrderByItem e2 = e.clone();\n            e2.setParent(x);\n            x.clusteredBy.add(e2);\n        }\n\n        for (SQLSelectOrderByItem e : sortedBy) {\n            SQLSelectOrderByItem e2 = e.clone();\n            e2.setParent(x);\n            x.sortedBy.add(e2);\n        }\n\n        x.buckets = buckets;\n        x.shards = shards;\n        x.afterSemi = afterSemi;\n\n    }\n\n    public boolean isReplace() {\n        return replace;\n    }\n\n    public void setReplace(boolean replace) {\n        this.ignore = false;\n        this.replace = replace;\n    }\n\n    public boolean isIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(boolean ignore) {\n        this.replace = false;\n        this.ignore = ignore;\n    }\n\n    public boolean isSingle() {\n        return single;\n    }\n\n    public void setSingle(boolean single) {\n        this.single = single;\n    }\n\n    public SQLExpr getStoredAs() {\n        return storedAs;\n    }\n\n    public void setStoredAs(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedAs = x;\n    }\n\n    public SQLExpr getStoredBy() {\n        return storedBy;\n    }\n\n    public void setStoredBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedBy = x;\n    }\n\n    public SQLCreateTableStatement clone() {\n        SQLCreateTableStatement x = new SQLCreateTableStatement(dbType);\n        cloneTo(x);\n        return x;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, dbType);\n    }\n\n    public boolean isOnCommitPreserveRows() {\n        return onCommitPreserveRows;\n    }\n\n    public void setOnCommitPreserveRows(boolean onCommitPreserveRows) {\n        this.onCommitPreserveRows = onCommitPreserveRows;\n    }\n\n    // for odps & hive\n    public boolean isExternal() {\n        return Feature.External.isEnabled(features);\n    }\n\n    public void setExternal(boolean external) {\n        this.features = Feature.External.config(this.features, external);\n    }\n\n    public ClusteringType getClusteringType() {\n        return clusteringType;\n    }\n\n    public void setClusteringType(ClusteringType clusteringType) {\n        this.clusteringType = clusteringType;\n    }\n\n    public List<SQLSelectOrderByItem> getClusteredBy() {\n        return clusteredBy;\n    }\n\n    public void addClusteredByItem(SQLSelectOrderByItem item) {\n        item.setParent(this);\n        this.clusteredBy.add(item);\n    }\n\n    public List<SQLSelectOrderByItem> getSortedBy() {\n        return sortedBy;\n    }\n\n    public void addSortedByItem(SQLSelectOrderByItem item) {\n        item.setParent(this);\n        this.sortedBy.add(item);\n    }\n\n    public int getBuckets() {\n        return buckets;\n    }\n\n    public void setBuckets(int buckets) {\n        this.buckets = buckets;\n    }\n\n    public int getShards() {\n        return shards;\n    }\n\n    public void setShards(int shards) {\n        this.shards = shards;\n    }\n\n    public List<SQLColumnDefinition> getPartitionColumns() {\n        return partitionColumns;\n    }\n\n    public void addPartitionColumn(SQLColumnDefinition column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.partitionColumns.add(column);\n    }\n\n    public List<SQLAssignItem> getTableOptions() {\n        return tableOptions;\n    }\n\n    @Deprecated\n    public List<SQLAssignItem> getTblProperties() {\n        return tableOptions;\n    }\n\n    @Deprecated\n    public void addTblProperty(String name, SQLExpr value) {\n        addOption(name, value);\n    }\n\n    public SQLExternalRecordFormat getRowFormat() {\n        return rowFormat;\n    }\n\n    public void setRowFormat(SQLExternalRecordFormat x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.rowFormat = x;\n    }\n\n    public boolean isDimension() {\n        return Feature.Dimension.isEnabled(features);\n    }\n\n    public void setDimension(boolean dimension) {\n        this.features = Feature.Dimension.config(features, dimension);\n    }\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public void setLocation(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.location = x;\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        tableOptions.add(assignItem);\n    }\n\n    public SQLExpr getOption(String name) {\n        if (name == null) {\n            return null;\n        }\n\n        long hash64 = FnvHash.hashCode64(name);\n\n        for (SQLAssignItem item : tableOptions) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public boolean removeOption(String name) {\n        if (name == null) {\n            return false;\n        }\n\n        long hash64 = FnvHash.hashCode64(name);\n\n        for (int i = tableOptions.size() - 1; i >= 0; i--) {\n            SQLAssignItem item = tableOptions.get(i);\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    tableOptions.remove(i);\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public SQLExpr getTblProperty(String name) {\n        if (name == null) {\n            return null;\n        }\n\n        long hash64 = FnvHash.hashCode64(name);\n\n        for (SQLAssignItem item : tableOptions) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public Object getOptionValue(String name) {\n        SQLExpr option = getOption(name);\n        if (option instanceof SQLValuableExpr) {\n            return ((SQLValuableExpr) option).getValue();\n        }\n\n        return null;\n    }\n\n    public Object getTblPropertyValue(String name) {\n        SQLExpr option = getTblProperty(name);\n        if (option instanceof SQLValuableExpr) {\n            return ((SQLValuableExpr) option).getValue();\n        }\n\n        return null;\n    }\n\n    public Object getOptionOrTblPropertyValue(String name) {\n        SQLExpr option = getTblProperty(name);\n\n        if (option == null) {\n            option = getOption(name);\n        }\n        if (option instanceof SQLValuableExpr) {\n            return ((SQLValuableExpr) option).getValue();\n        }\n\n        return null;\n    }\n\n    public String getCatalog() {\n        return null;\n    }\n\n    public boolean containsDuplicateColumnNames() {\n        return containsDuplicateColumnNames(false);\n    }\n\n    public boolean containsDuplicateColumnNames(boolean throwException) {\n        Map<Long, SQLTableElement> columnMap = new HashMap<Long, SQLTableElement>();\n\n        for (SQLTableElement item : tableElementList) {\n            if (item instanceof SQLColumnDefinition) {\n                SQLName columnName = ((SQLColumnDefinition) item).getName();\n                long nameHashCode64 = columnName.nameHashCode64();\n                SQLTableElement old = columnMap.put(nameHashCode64, item);\n                if (old != null) {\n                    if (throwException) {\n                        throw new ParserException(\"Table contains duplicate column names : \"\n                                + SQLUtils.normalize(columnName.getSimpleName()));\n                    }\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TABLE;\n    }\n\n    public SQLExpr getLifeCycle() {\n        return lifeCycle;\n    }\n\n    public void setLifeCycle(SQLExpr x) {\n        if (x instanceof SQLNumberExpr) {\n            Number number = ((SQLNumberExpr) x).getNumber();\n            if (number instanceof BigDecimal) {\n                x = new SQLIntegerExpr(((BigDecimal) number).intValueExact());\n            }\n        }\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.lifeCycle = x;\n    }\n\n    public enum Feature {\n        Temporary(1),\n        Global(1 << 1),\n        Local(1 << 2),\n        OrReplace(1 << 3),\n        IfNotExists(1 << 4),\n        External(1 << 5),\n        Transactional(1 << 6),\n        Shadow(1 << 7),\n        Dimension(1 << 8),\n        Set(1 << 9),\n        MultiSet(1 << 10),\n        Volatile(1 << 11),\n        Unlogged(1 << 12);\n        public final int mask;\n\n        Feature(int mask) {\n            this.mask = mask;\n        }\n\n        public boolean isEnabled(long features) {\n            return (features & mask) != 0;\n        }\n\n        public int config(int features, boolean state) {\n            if (state) {\n                features |= this.mask;\n            } else {\n                features &= ~this.mask;\n            }\n\n            return features;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTriggerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCreateTriggerStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n    private boolean orReplace;\n    private TriggerType triggerType;\n\n    private SQLName definer;\n\n    private boolean update;\n    private boolean delete;\n    private boolean insert;\n\n    private SQLExprTableSource on;\n\n    private boolean forEachRow;\n\n    private List<SQLName> updateOfColumns = new ArrayList<SQLName>();\n\n    private SQLExpr when;\n    private SQLStatement body;\n\n    private String executeType;\n\n    private SQLExpr executeFunc;\n\n    public SQLCreateTriggerStatement() {\n    }\n\n    public SQLCreateTriggerStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, updateOfColumns);\n            acceptChild(visitor, on);\n            acceptChild(visitor, when);\n            acceptChild(visitor, body);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        children.addAll(updateOfColumns);\n        if (on != null) {\n            children.add(on);\n        }\n        if (when != null) {\n            children.add(when);\n        }\n        if (body != null) {\n            children.add(body);\n        }\n        return children;\n    }\n\n    public SQLExprTableSource getOn() {\n        return on;\n    }\n\n    public void setOn(SQLName on) {\n        this.setOn(new SQLExprTableSource(on));\n    }\n\n    public void setOn(SQLExprTableSource on) {\n        if (on != null) {\n            on.setParent(this);\n        }\n        this.on = on;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLStatement getBody() {\n        return body;\n    }\n\n    public void setBody(SQLStatement body) {\n        if (body != null) {\n            body.setParent(this);\n        }\n        this.body = body;\n    }\n\n    public boolean isOrReplace() {\n        return orReplace;\n    }\n\n    public void setOrReplace(boolean orReplace) {\n        this.orReplace = orReplace;\n    }\n\n    public TriggerType getTriggerType() {\n        return triggerType;\n    }\n\n    public void setTriggerType(TriggerType triggerType) {\n        this.triggerType = triggerType;\n    }\n\n    public List<TriggerEvent> getTriggerEvents() {\n        return null;\n    }\n\n    public boolean isForEachRow() {\n        return forEachRow;\n    }\n\n    public void setForEachRow(boolean forEachRow) {\n        this.forEachRow = forEachRow;\n    }\n\n    public String getExecuteType() {\n        return executeType;\n    }\n\n    public void setExecuteType(String executeType) {\n        this.executeType = executeType;\n    }\n\n    public SQLExpr getExecuteFunc() {\n        return executeFunc;\n    }\n\n    public void setExecuteFunc(SQLExpr executeFunc) {\n        this.executeFunc = executeFunc;\n    }\n\n    public List<SQLName> getUpdateOfColumns() {\n        return updateOfColumns;\n    }\n\n    public SQLExpr getWhen() {\n        return when;\n    }\n\n    public void setWhen(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.when = x;\n    }\n\n    public boolean isUpdate() {\n        return update;\n    }\n\n    public void setUpdate(boolean update) {\n        this.update = update;\n    }\n\n    public boolean isDelete() {\n        return delete;\n    }\n\n    public void setDelete(boolean delete) {\n        this.delete = delete;\n    }\n\n    public boolean isInsert() {\n        return insert;\n    }\n\n    public void setInsert(boolean insert) {\n        this.insert = insert;\n    }\n\n    public SQLName getDefiner() {\n        return definer;\n    }\n\n    public void setDefiner(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.definer = x;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TRIGGER;\n    }\n\n    public static enum TriggerType {\n        BEFORE, AFTER, INSTEAD_OF\n    }\n\n    public static enum TriggerEvent {\n        INSERT, UPDATE, DELETE\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateUserStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLCreateUserStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName user;\n    private SQLExpr password;\n    private boolean postgresqlWith;\n    private boolean postgresqlEncrypted;\n    // oracle\n    private SQLName defaultTableSpace;\n\n    public SQLCreateUserStatement() {\n    }\n\n    public SQLName getUser() {\n        return user;\n    }\n\n    public void setUser(SQLName user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.user = user;\n    }\n\n    public boolean isPostgresqlWith() {\n        return postgresqlWith;\n    }\n\n    public void setPostgresqlWith(boolean postgresqlWith) {\n        this.postgresqlWith = postgresqlWith;\n    }\n\n    public boolean isPostgresqlEncrypted() {\n        return postgresqlEncrypted;\n    }\n\n    public void setPostgresqlEncrypted(boolean postgresqlEncrypted) {\n        this.postgresqlEncrypted = postgresqlEncrypted;\n    }\n\n    public SQLExpr getPassword() {\n        return password;\n    }\n\n    public void setPassword(SQLExpr password) {\n        if (password != null) {\n            password.setParent(this);\n        }\n        this.password = password;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, user);\n            acceptChild(visitor, password);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.USER;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLCreateViewStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private boolean orReplace;\n    private boolean force;\n    private boolean temporary;\n    // protected SQLName   name;\n    protected SQLSelect subQuery;\n    protected boolean ifNotExists;\n\n    protected String algorithm;\n    protected SQLName definer;\n    protected String sqlSecurity;\n\n    protected SQLExprTableSource tableSource;\n\n    protected final List<SQLTableElement> columns = new ArrayList<SQLTableElement>();\n\n    private boolean withCheckOption;\n    private boolean withCascaded;\n    private boolean withLocal;\n    private boolean withReadOnly;\n    private boolean global;\n\n    private SQLLiteralExpr comment;\n\n    private SQLVariantRefExpr returns; // odps\n    private SQLTableDataType returnsDataType; // odps\n\n    // clickhouse\n    protected boolean onCluster;\n    private SQLName to;\n\n    // bigquery\n    protected List<SQLAssignItem> options = new ArrayList<>();\n\n    private SQLBlockStatement script;\n\n    public SQLCreateViewStatement() {\n    }\n\n    public SQLCreateViewStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n\n    public String computeName() {\n        if (tableSource == null) {\n            return null;\n        }\n\n        SQLExpr expr = tableSource.getExpr();\n        if (expr instanceof SQLName) {\n            String name = ((SQLName) expr).getSimpleName();\n            return SQLUtils.normalize(name);\n        }\n\n        return null;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public boolean isOrReplace() {\n        return orReplace;\n    }\n\n    public void setOrReplace(boolean orReplace) {\n        this.orReplace = orReplace;\n    }\n\n    public SQLName getName() {\n        if (tableSource == null) {\n            return null;\n        }\n\n        return (SQLName) tableSource.getExpr();\n    }\n\n    public void setName(SQLName name) {\n        this.setTableSource(new SQLExprTableSource(name));\n    }\n\n    public void setName(String name) {\n        this.setName(new SQLIdentifierExpr(name));\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public boolean isWithCheckOption() {\n        return withCheckOption;\n    }\n\n    public void setWithCheckOption(boolean withCheckOption) {\n        this.withCheckOption = withCheckOption;\n    }\n\n    public boolean isWithCascaded() {\n        return withCascaded;\n    }\n\n    public void setWithCascaded(boolean withCascaded) {\n        this.withCascaded = withCascaded;\n    }\n\n    public boolean isWithLocal() {\n        return withLocal;\n    }\n\n    public void setWithLocal(boolean withLocal) {\n        this.withLocal = withLocal;\n    }\n\n    public boolean isWithReadOnly() {\n        return withReadOnly;\n    }\n\n    public void setWithReadOnly(boolean withReadOnly) {\n        this.withReadOnly = withReadOnly;\n    }\n\n    public SQLSelect getSubQuery() {\n        return subQuery;\n    }\n\n    public void setSubQuery(SQLSelect subQuery) {\n        if (subQuery != null) {\n            subQuery.setParent(this);\n        }\n        this.subQuery = subQuery;\n    }\n\n    public List<SQLTableElement> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLTableElement column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public SQLLiteralExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLLiteralExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public String getAlgorithm() {\n        return algorithm;\n    }\n\n    public void setAlgorithm(String algorithm) {\n        this.algorithm = algorithm;\n    }\n\n    public SQLName getDefiner() {\n        return definer;\n    }\n\n    public void setDefiner(SQLName definer) {\n        if (definer != null) {\n            definer.setParent(this);\n        }\n        this.definer = definer;\n    }\n\n    public String getSqlSecurity() {\n        return sqlSecurity;\n    }\n\n    public void setSqlSecurity(String sqlSecurity) {\n        this.sqlSecurity = sqlSecurity;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n\n    public boolean isTemporary() {\n        return temporary;\n    }\n\n    public void setTemporary(boolean temporary) {\n        this.temporary = temporary;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (tableSource != null) {\n                tableSource.accept(visitor);\n            }\n\n            for (int i = 0; i < columns.size(); i++) {\n                final SQLTableElement column = columns.get(i);\n                if (column != null) {\n                    column.accept(visitor);\n                }\n            }\n\n            if (comment != null) {\n                comment.accept(visitor);\n            }\n\n            if (subQuery != null) {\n                subQuery.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (tableSource != null) {\n            children.add(tableSource);\n        }\n        children.addAll(this.columns);\n        if (comment != null) {\n            children.add(comment);\n        }\n        if (subQuery != null) {\n            children.add(subQuery);\n        }\n        return children;\n    }\n\n    public static enum Level {\n        CASCADED, LOCAL\n    }\n\n    public static class Column extends SQLObjectImpl {\n        private SQLExpr expr;\n        private SQLCharExpr comment;\n\n        public SQLExpr getExpr() {\n            return expr;\n        }\n\n        public void setExpr(SQLExpr expr) {\n            if (expr != null) {\n                expr.setParent(this);\n            }\n            this.expr = expr;\n        }\n\n        public SQLCharExpr getComment() {\n            return comment;\n        }\n\n        public void setComment(SQLCharExpr comment) {\n            if (comment != null) {\n                comment.setParent(this);\n            }\n            this.comment = comment;\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, expr);\n                acceptChild(visitor, comment);\n            }\n        }\n    }\n\n    public boolean isOnCluster() {\n        return onCluster;\n    }\n\n    public void setOnCluster(boolean onCluster) {\n        this.onCluster = onCluster;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n\n    public SQLVariantRefExpr getReturns() {\n        return returns;\n    }\n\n    public void setReturns(SQLVariantRefExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.returns = x;\n    }\n\n    public SQLTableDataType getReturnsDataType() {\n        return returnsDataType;\n    }\n\n    public void\n    setReturnsDataType(SQLTableDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.returnsDataType = x;\n    }\n\n    public SQLBlockStatement getScript() {\n        return script;\n    }\n\n    public void setScript(SQLBlockStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.script = x;\n    }\n\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.VIEW;\n    }\n\n    public SQLCreateViewStatement clone() {\n        SQLCreateViewStatement x = new SQLCreateViewStatement();\n\n        x.orReplace = orReplace;\n        x.force = force;\n        if (subQuery != null) {\n            x.setSubQuery(subQuery.clone());\n        }\n        x.ifNotExists = ifNotExists;\n\n        x.algorithm = algorithm;\n        if (definer != null) {\n            x.setDefiner(definer.clone());\n        }\n        x.sqlSecurity = sqlSecurity;\n        if (tableSource != null) {\n            x.setTableSource(tableSource.clone());\n        }\n        for (SQLTableElement column : columns) {\n            SQLTableElement column2 = column.clone();\n            column2.setParent(x);\n            x.columns.add(column2);\n        }\n        x.withCheckOption = withCheckOption;\n        x.withCascaded = withCascaded;\n        x.withLocal = withLocal;\n        x.withReadOnly = withReadOnly;\n        x.global = global;\n\n        if (comment != null) {\n            x.setComment(comment.clone());\n        }\n\n        x.onCluster = onCluster;\n        if (x.to != null) {\n            to = x.to.clone();\n        }\n\n        if (x.returns != null) {\n            returns = x.returns.clone();\n        }\n\n        if (x.returnsDataType != null) {\n            returnsDataType = x.returnsDataType.clone();\n        }\n\n        return x;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDDLStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\npublic interface SQLDDLStatement extends SQLStatement {\n    default DDLObjectType getDDLObjectType() {\n        return DDLObjectType.OTHER;\n    }\n\n    enum DDLObjectType {\n        DATABASE,\n        TABLE,\n        VIEW,\n        MATERIALIZED_VIEW,\n        TABLE_SPACE,\n        TABLE_GROUP,\n        FUNCTION,\n        TRIGGER,\n        USER,\n        ROLE,\n        SEQUENCE,\n        INDEX,\n        PROCEDURE,\n        TYPE,\n        OTHER\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeclareStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDeclareStatement extends SQLStatementImpl {\n    protected List<SQLDeclareItem> items = new ArrayList<SQLDeclareItem>();\n\n    public SQLDeclareStatement() {\n    }\n\n    public SQLDeclareStatement(SQLName name, SQLDataType dataType) {\n        this.addItem(new SQLDeclareItem(name, dataType));\n    }\n\n    public SQLDeclareStatement(SQLName name, SQLDataType dataType, SQLExpr value) {\n        this.addItem(new SQLDeclareItem(name, dataType, value));\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, items);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLDeclareItem> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLDeclareItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDefault.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLDefault extends SQLConstraintImpl implements SQLTableElement, SQLTableConstraint, SQLReplaceable {\n    private SQLExpr expr;\n    private SQLExpr column;\n    private boolean withValues;\n\n    public SQLDefault() {\n    }\n\n    public SQLDefault(SQLExpr expr, SQLExpr column) {\n        this.setExpr(expr);\n        this.setColumn(column);\n    }\n\n    public SQLExpr getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLExpr column) {\n        this.column = column;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (getName() != null) {\n                getName().accept(visitor);\n            }\n\n            if (expr != null) {\n                expr.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public void cloneTo(SQLDefault x) {\n        super.cloneTo(x);\n\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n\n        if (column != null) {\n            x.setColumn(column.clone());\n        }\n\n        x.setWithValues(x.isWithValues());\n    }\n\n    public SQLDefault clone() {\n        SQLDefault x = new SQLDefault();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        if (getName() == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        if (getComment() == expr) {\n            setComment(target);\n            return true;\n        }\n        return false;\n    }\n\n    public boolean isWithValues() {\n        return withValues;\n    }\n\n    public void setWithValues(boolean withValues) {\n        this.withValues = withValues;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDeleteStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExprGroup;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDeleteStatement extends SQLStatementImpl implements SQLReplaceable {\n    protected SQLWithSubqueryClause with;\n\n    protected SQLTableSource tableSource;\n    protected SQLExpr where;\n    protected SQLTableSource from;\n    protected SQLTableSource using;\n\n    protected boolean only;\n\n    public SQLDeleteStatement() {\n    }\n\n    public SQLDeleteStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    protected void cloneTo(SQLDeleteStatement x) {\n        if (headHints != null) {\n            for (SQLCommentHint h : headHints) {\n                SQLCommentHint h2 = h.clone();\n                h2.setParent(x);\n                x.headHints.add(h2);\n            }\n        }\n\n        if (with != null) {\n            x.setWith(with.clone());\n        }\n\n        if (tableSource != null) {\n            x.setTableSource(tableSource.clone());\n        }\n        if (where != null) {\n            x.setWhere(where.clone());\n        }\n        if (from != null) {\n            x.setFrom(from.clone());\n        }\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n        x.only = only;\n    }\n\n    public SQLDeleteStatement clone() {\n        SQLDeleteStatement x = new SQLDeleteStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    public SQLTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public SQLExprTableSource getExprTableSource() {\n        return (SQLExprTableSource) getTableSource();\n    }\n\n    public void setTableSource(SQLExpr expr) {\n        this.setTableSource(new SQLExprTableSource(expr));\n    }\n\n    public void setTableSource(SQLTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public SQLName getTableName() {\n        if (this.tableSource instanceof SQLExprTableSource) {\n            SQLExprTableSource exprTableSource = (SQLExprTableSource) this.tableSource;\n            return (SQLName) exprTableSource.getExpr();\n        }\n\n        if (tableSource instanceof SQLSubqueryTableSource) {\n            SQLSelectQuery selectQuery = ((SQLSubqueryTableSource) tableSource).getSelect().getQuery();\n            if (selectQuery instanceof SQLSelectQueryBlock) {\n                SQLTableSource subQueryTableSource = ((SQLSelectQueryBlock) selectQuery).getFrom();\n                if (subQueryTableSource instanceof SQLExprTableSource) {\n                    SQLExpr subQueryTableSourceExpr = ((SQLExprTableSource) subQueryTableSource).getExpr();\n                    return (SQLName) subQueryTableSourceExpr;\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.setTableSource(new SQLExprTableSource(tableName));\n    }\n\n    public void setTableName(String name) {\n        setTableName(new SQLIdentifierExpr(name));\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        if (where != null) {\n            where.setParent(this);\n        }\n        this.where = where;\n    }\n\n    public String getAlias() {\n        return this.tableSource.getAlias();\n    }\n\n    public void setAlias(String alias) {\n        this.tableSource.setAlias(alias);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (with != null) {\n                with.accept(visitor);\n            }\n\n            if (tableSource != null) {\n                tableSource.accept(visitor);\n            }\n\n            if (where != null) {\n                where.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (with != null) {\n            children.add(with);\n        }\n        children.add(tableSource);\n        if (where != null) {\n            children.add(where);\n        }\n        return children;\n    }\n\n    public SQLTableSource getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLTableSource from) {\n        if (from != null) {\n            from.setParent(this);\n        }\n        this.from = from;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (where == expr) {\n            setWhere(target);\n            return true;\n        }\n        return false;\n    }\n\n    public boolean isOnly() {\n        return only;\n    }\n\n    public void setOnly(boolean only) {\n        this.only = only;\n    }\n\n    public SQLTableSource getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLTableSource using) {\n        this.using = using;\n    }\n\n    public SQLWithSubqueryClause getWith() {\n        return with;\n    }\n\n    public void setWith(SQLWithSubqueryClause with) {\n        if (with != null) {\n            with.setParent(this);\n        }\n        this.with = with;\n    }\n\n    public void addCondition(String conditionSql) {\n        if (conditionSql == null || conditionSql.length() == 0) {\n            return;\n        }\n\n        SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);\n        addCondition(condition);\n    }\n\n    public void addCondition(SQLExpr expr) {\n        if (expr == null) {\n            return;\n        }\n\n        this.setWhere(SQLBinaryOpExpr.and(where, expr));\n    }\n\n    public boolean removeCondition(String conditionSql) {\n        if (conditionSql == null || conditionSql.length() == 0) {\n            return false;\n        }\n\n        SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);\n\n        return removeCondition(condition);\n    }\n\n    public boolean removeCondition(SQLExpr condition) {\n        if (condition == null) {\n            return false;\n        }\n\n        if (where instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) where;\n\n            int removedCount = 0;\n            List<SQLExpr> items = group.getItems();\n            for (int i = items.size() - 1; i >= 0; i--) {\n                if (items.get(i).equals(condition)) {\n                    items.remove(i);\n                    removedCount++;\n                }\n            }\n            if (items.isEmpty()) {\n                where = null;\n            }\n\n            return removedCount > 0;\n        }\n\n        if (where instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpWhere = (SQLBinaryOpExpr) where;\n            SQLBinaryOperator operator = binaryOpWhere.getOperator();\n            if (operator == SQLBinaryOperator.BooleanAnd || operator == SQLBinaryOperator.BooleanOr) {\n                List<SQLExpr> items = SQLBinaryOpExpr.split(binaryOpWhere);\n\n                int removedCount = 0;\n                for (int i = items.size() - 1; i >= 0; i--) {\n                    SQLExpr item = items.get(i);\n                    if (item.equals(condition)) {\n                        if (SQLUtils.replaceInParent(item, null)) {\n                            removedCount++;\n                        }\n                    }\n                }\n\n                return removedCount > 0;\n            }\n        }\n\n        if (condition.equals(where)) {\n            where = null;\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean addWhere(SQLExpr where) {\n        if (where == null) {\n            return false;\n        }\n\n        this.addCondition(where);\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDescribeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class SQLDescribeStatement extends SQLStatementImpl implements SQLReplaceable {\n    protected SQLName object;\n    protected SQLName column;\n    protected boolean extended;\n    protected boolean formatted;\n\n    // for odps\n    protected SQLObjectType objectType;\n    protected List<SQLExpr> partition = new ArrayList<SQLExpr>();\n\n    public SQLName getObject() {\n        return object;\n    }\n\n    public void setObject(SQLName object) {\n        this.object = object;\n    }\n\n    public SQLName getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLName column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.column = column;\n    }\n\n    public List<SQLExpr> getPartition() {\n        return partition;\n    }\n\n    public void setPartition(List<SQLExpr> partition) {\n        this.partition = partition;\n    }\n\n    public SQLObjectType getObjectType() {\n        return objectType;\n    }\n\n    public void setObjectType(SQLObjectType objectType) {\n        this.objectType = objectType;\n    }\n\n    public boolean isExtended() {\n        return extended;\n    }\n\n    public void setExtended(boolean extended) {\n        this.extended = extended;\n    }\n\n    public boolean isFormatted() {\n        return formatted;\n    }\n\n    public void setFormatted(boolean formatted) {\n        this.formatted = formatted;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, object);\n            acceptChild(visitor, column);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Arrays.<SQLObject>asList(this.object, column);\n\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (object == expr) {\n            setObject((SQLName) target);\n            return true;\n        }\n\n        if (column == expr) {\n            setColumn((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropCatalogStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropCatalogStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n    private boolean external;\n\n    public SQLDropCatalogStatement() {\n    }\n\n    public SQLDropCatalogStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isExternal() {\n        return external;\n    }\n\n    public void setExternal(boolean external) {\n        this.external = external;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropDatabaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropDatabaseStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLExpr database;\n    private boolean ifExists;\n    private Boolean restrict;\n    private boolean cascade;\n\n    //adb\n    private boolean physical;\n\n    public SQLDropDatabaseStatement() {\n    }\n\n    public SQLDropDatabaseStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return (SQLName) database;\n    }\n\n    public String getDatabaseName() {\n        if (database == null) {\n            return null;\n        }\n\n        if (database instanceof SQLName) {\n            return ((SQLName) database).getSimpleName();\n        }\n\n        return null;\n    }\n\n    public SQLExpr getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLExpr database) {\n        if (database != null) {\n            database.setParent(this);\n        }\n        this.database = database;\n    }\n\n    public void setDatabase(String database) {\n        SQLExpr expr = SQLUtils.toSQLExpr(database);\n\n        if (expr instanceof SQLIdentifierExpr && this.database instanceof SQLPropertyExpr) {\n            ((SQLPropertyExpr) this.database).setName(database);\n            return;\n        }\n\n        expr.setParent(this);\n        this.database = expr;\n    }\n\n    public String getServer() {\n        if (database instanceof SQLPropertyExpr) {\n            SQLExpr owner = ((SQLPropertyExpr) database).getOwner();\n            if (owner instanceof SQLIdentifierExpr) {\n                return ((SQLIdentifierExpr) owner).getName();\n            }\n\n            if (owner instanceof SQLPropertyExpr) {\n                return ((SQLPropertyExpr) owner).getName();\n            }\n        }\n\n        return null;\n    }\n\n    public boolean setServer(String server) {\n        if (database == null) {\n            return false;\n        }\n\n        if (database instanceof SQLIdentifierExpr) {\n            SQLPropertyExpr propertyExpr = new SQLPropertyExpr(new SQLIdentifierExpr(server), ((SQLIdentifierExpr) database).getName());\n            propertyExpr.setParent(this);\n            database = propertyExpr;\n            return true;\n        }\n\n        if (database instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) database;\n            SQLExpr owner = propertyExpr.getOwner();\n            if (owner instanceof SQLIdentifierExpr) {\n                propertyExpr.setOwner(new SQLIdentifierExpr(server));\n                return true;\n            } else if (owner instanceof SQLPropertyExpr) {\n                ((SQLPropertyExpr) owner).setName(server);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (database != null) {\n            children.add(database);\n        }\n        return children;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (database == expr) {\n            setDatabase(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public Boolean getRestrict() {\n        return restrict;\n    }\n\n    public boolean isRestrict() {\n        if (restrict == null) {\n            return !cascade;\n        }\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isPhysical() {\n        return physical;\n    }\n\n    public void setPhysical(boolean physical) {\n        this.physical = physical;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.DATABASE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropEventStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropEventStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropEventStatement() {\n    }\n\n    public SQLDropEventStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropFunctionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class SQLDropFunctionStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n    protected List<SQLParameter> parameters;\n    private boolean temporary;\n\n    public SQLDropFunctionStatement() {\n    }\n\n    public SQLDropFunctionStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<SQLParameter> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean isTemporary() {\n        return temporary;\n    }\n\n    public void setTemporary(boolean temporary) {\n        this.temporary = temporary;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropIndexStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropIndexStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName indexName;\n    private SQLExprTableSource tableName;\n\n    private SQLExpr algorithm;\n    private SQLExpr lockOption;\n    private boolean ifExists;\n\n    public SQLDropIndexStatement() {\n    }\n\n    public SQLDropIndexStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLName getIndexName() {\n        return indexName;\n    }\n\n    public void setIndexName(SQLName indexName) {\n        this.indexName = indexName;\n    }\n\n    public SQLExprTableSource getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.setTableName(new SQLExprTableSource(tableName));\n    }\n\n    public void setTableName(SQLExprTableSource tableName) {\n        this.tableName = tableName;\n    }\n\n    public SQLExpr getAlgorithm() {\n        return algorithm;\n    }\n\n    public void setAlgorithm(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.algorithm = x;\n    }\n\n    public SQLExpr getLockOption() {\n        return lockOption;\n    }\n\n    public void setLockOption(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.lockOption = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, indexName);\n            acceptChild(visitor, tableName);\n            acceptChild(visitor, algorithm);\n            acceptChild(visitor, lockOption);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (indexName != null) {\n            children.add(indexName);\n        }\n        if (tableName != null) {\n            children.add(tableName);\n        }\n        return children;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (indexName == expr) {\n            setIndexName((SQLName) target);\n            return true;\n        }\n\n        if (algorithm == expr) {\n            setAlgorithm(target);\n            return true;\n        }\n\n        if (lockOption == expr) {\n            setLockOption(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.INDEX;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropLogFileGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropLogFileGroupStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n    private SQLExpr engine;\n\n    public SQLDropLogFileGroupStatement() {\n    }\n\n    public SQLDropLogFileGroupStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, engine);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.engine = x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropMaterializedViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropMaterializedViewStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropMaterializedViewStatement() {\n    }\n\n    public SQLDropMaterializedViewStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropOfflineModelStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropOfflineModelStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    protected SQLName name;\n    protected boolean ifExists;\n\n    public SQLDropOfflineModelStatement() {\n    }\n\n    public SQLDropOfflineModelStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public String getTableGroupName() {\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLName) {\n            return name.getSimpleName();\n        }\n\n        return null;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifNotExists) {\n        this.ifExists = ifNotExists;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropOutlineStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropOutlineStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropOutlineStatement() {\n    }\n\n    public SQLDropOutlineStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropProcedureStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLDropProcedureStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropProcedureStatement() {\n    }\n\n    public SQLDropProcedureStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.PROCEDURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropResourceGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropResourceGroupStatement\n        extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropResourceGroupStatement() {\n    }\n\n    public SQLDropResourceGroupStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropResourceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropResourceStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropResourceStatement() {\n    }\n\n    public SQLDropResourceStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropRoleStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropRoleStatement extends SQLStatementImpl implements SQLCreateStatement, SQLReplaceable {\n    private SQLName name;\n    protected boolean ifNotExists;\n\n    public SQLDropRoleStatement() {\n    }\n\n    public SQLDropRoleStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.ROLE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropSequenceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropSequenceStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropSequenceStatement() {\n    }\n\n    public SQLDropSequenceStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.SEQUENCE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropServerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropServerStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropServerStatement() {\n    }\n\n    public SQLDropServerStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\n\npublic interface SQLDropStatement extends SQLDDLStatement {\n    default SQLName getName() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropSynonymStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropSynonymStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n    private boolean isPublic;\n    private boolean force;\n\n    public SQLDropSynonymStatement() {\n    }\n\n    public SQLDropSynonymStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public String getSchema() {\n        SQLName name = getName();\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n\n        return null;\n    }\n\n    public boolean isPublic() {\n        return isPublic;\n    }\n\n    public void setPublic(boolean aPublic) {\n        isPublic = aPublic;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTableGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropTableGroupStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    protected SQLName name;\n    protected boolean ifExists;\n\n    public SQLDropTableGroupStatement() {\n    }\n\n    public SQLDropTableGroupStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public String getTableGroupName() {\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLName) {\n            return name.getSimpleName();\n        }\n\n        return null;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifNotExists) {\n        this.ifExists = ifNotExists;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TABLE_GROUP;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTableSpaceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLDropTableSpaceStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n    private SQLExpr engine;\n\n    public SQLDropTableSpaceStatement() {\n    }\n\n    public SQLDropTableSpaceStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public String getTableSpaceName() {\n        if (name == null) {\n            return null;\n        }\n\n        if (name instanceof SQLName) {\n            return name.getSimpleName();\n        }\n\n        return null;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.engine = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TABLE_SPACE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\n\npublic class SQLDropTableStatement extends SQLStatementImpl implements SQLDropStatement {\n    private List<SQLCommentHint> hints;\n\n    protected List<SQLExprTableSource> tableSources = new ArrayList<>();\n    protected boolean purge;\n    protected boolean cascade;\n    protected boolean restrict;\n    protected boolean ifExists;\n    private boolean temporary;\n    private boolean external;\n    private boolean isDropPartition;\n    private SQLExpr where;\n\n    public SQLDropTableStatement() {\n    }\n\n    public SQLDropTableStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLDropTableStatement(SQLName name, DbType dbType) {\n        this(new SQLExprTableSource(name), dbType);\n    }\n\n    public SQLDropTableStatement(SQLName name) {\n        this(name, null);\n    }\n\n    public SQLDropTableStatement(SQLExprTableSource tableSource) {\n        this(tableSource, null);\n    }\n\n    public SQLDropTableStatement(SQLExprTableSource tableSource, DbType dbType) {\n        this(dbType);\n        this.tableSources.add(tableSource);\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void addPartition(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSources.add(tableSource);\n    }\n\n    public void setName(SQLName name) {\n        this.addTableSource(new SQLExprTableSource(name));\n    }\n\n    public void addTableSource(String name) {\n        this.addTableSource(new SQLIdentifierExpr(name));\n    }\n\n    public void addTableSource(SQLName name) {\n        this.addTableSource(new SQLExprTableSource(name));\n    }\n\n    public void addTableSource(SQLExprTableSource tableSource) {\n        tableSources.add(tableSource);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, tableSources);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return this.tableSources;\n    }\n\n    public boolean isPurge() {\n        return purge;\n    }\n\n    public void setPurge(boolean purge) {\n        this.purge = purge;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    public boolean isTemporary() {\n        return temporary;\n    }\n\n    public void setTemporary(boolean temporary) {\n        this.temporary = temporary;\n    }\n\n    public boolean isExternal() {\n        return external;\n    }\n\n    public void setExternal(boolean external) {\n        this.external = external;\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public boolean isDropPartition() {\n        return isDropPartition;\n    }\n\n    public void setDropPartition(boolean dropPartition) {\n        isDropPartition = dropPartition;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TABLE;\n    }\n\n    public SQLName getName() {\n        if (tableSources.size() == 1) {\n            SQLExprTableSource dataSource0 = tableSources.get(0);\n            return dataSource0.getName();\n        }\n        return null;\n    }\n\n    protected void cloneTo(SQLDropTableStatement x) {\n        if (hints != null) {\n            x.hints = new ArrayList<>(hints);\n        }\n        tableSources.forEach(e -> x.addTableSource(e.clone()));\n        x.purge = purge;\n        x.cascade = cascade;\n        x.restrict = restrict;\n        x.ifExists = ifExists;\n        x.temporary = temporary;\n        x.external = external;\n        x.isDropPartition = isDropPartition;\n        if (where != null) {\n            x.where = where.clone();\n        }\n    }\n\n    public SQLDropTableStatement clone() {\n        SQLDropTableStatement x = new SQLDropTableStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLDropTableStatement that = (SQLDropTableStatement) o;\n        return purge == that.purge\n                && cascade == that.cascade\n                && restrict == that.restrict\n                && ifExists == that.ifExists\n                && temporary == that.temporary\n                && external == that.external\n                && isDropPartition == that.isDropPartition\n                && Objects.equals(hints, that.hints)\n                && Objects.equals(tableSources, that.tableSources)\n                && Objects.equals(where, that.where);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = Objects.hashCode(hints);\n        result = 31 * result + Objects.hashCode(tableSources);\n        result = 31 * result + Boolean.hashCode(purge);\n        result = 31 * result + Boolean.hashCode(cascade);\n        result = 31 * result + Boolean.hashCode(restrict);\n        result = 31 * result + Boolean.hashCode(ifExists);\n        result = 31 * result + Boolean.hashCode(temporary);\n        result = 31 * result + Boolean.hashCode(external);\n        result = 31 * result + Boolean.hashCode(isDropPartition);\n        result = 31 * result + Objects.hashCode(where);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTriggerStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\n/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropTriggerStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropTriggerStatement() {\n    }\n\n    public SQLDropTriggerStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TRIGGER;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTypeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropTypeStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean ifExists;\n\n    public SQLDropTypeStatement() {\n    }\n\n    public SQLDropTypeStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.TYPE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropUserStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropUserStatement extends SQLStatementImpl implements SQLDropStatement, SQLReplaceable {\n    private List<SQLExpr> users = new ArrayList<SQLExpr>(2);\n\n    protected boolean ifExists;\n\n    protected boolean cascade;\n\n    public SQLDropUserStatement() {\n    }\n\n    public SQLDropUserStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public List<SQLExpr> getUsers() {\n        return users;\n    }\n\n    public void addUser(SQLExpr user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.users.add(user);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, users);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return users;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < users.size(); i++) {\n            if (users.get(i) == expr) {\n                target.setParent(this);\n                users.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.USER;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLDropViewStatement extends SQLStatementImpl implements SQLDropStatement {\n    protected List<SQLExprTableSource> tableSources = new ArrayList<SQLExprTableSource>();\n\n    protected boolean cascade;\n    protected boolean restrict;\n    protected boolean ifExists;\n\n    public SQLDropViewStatement() {\n    }\n\n    public SQLDropViewStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLDropViewStatement(SQLName name) {\n        this(new SQLExprTableSource(name));\n    }\n\n    public SQLDropViewStatement(SQLExprTableSource tableSource) {\n        this.tableSources.add(tableSource);\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void addPartition(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSources.add(tableSource);\n    }\n\n    public void setName(SQLName name) {\n        this.addTableSource(new SQLExprTableSource(name));\n    }\n\n    public void addTableSource(SQLName name) {\n        this.addTableSource(new SQLExprTableSource(name));\n    }\n\n    public void addTableSource(SQLExprTableSource tableSource) {\n        tableSources.add(tableSource);\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < tableSources.size(); i++) {\n                SQLExprTableSource item = tableSources.get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    @Override\n    public List getChildren() {\n        return tableSources;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.VIEW;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLDumpStatement extends SQLStatementImpl {\n    private boolean overwrite;\n    private SQLExprTableSource into;\n    private SQLSelect select;\n\n    public SQLDumpStatement() {\n    }\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.select = x;\n    }\n\n    public SQLExprTableSource getInto() {\n        return into;\n    }\n\n    public void setInto(SQLExpr x) {\n        if (x == null) {\n            return;\n        }\n\n        setInto(new SQLExprTableSource(x));\n    }\n\n    public void setInto(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.into = x;\n    }\n\n    public boolean isOverwrite() {\n        return overwrite;\n    }\n\n    public void setOverwrite(boolean overwrite) {\n        this.overwrite = overwrite;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (into != null) {\n                into.accept(visitor);\n            }\n\n            if (select != null) {\n                select.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLErrorLoggingClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLErrorLoggingClause extends SQLObjectImpl {\n    private SQLName into;\n    private SQLExpr simpleExpression;\n    private SQLExpr limit;\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, into);\n            acceptChild(visitor, simpleExpression);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getInto() {\n        return into;\n    }\n\n    public void setInto(SQLName into) {\n        this.into = into;\n    }\n\n    public SQLExpr getSimpleExpression() {\n        return simpleExpression;\n    }\n\n    public void setSimpleExpression(SQLExpr simpleExpression) {\n        this.simpleExpression = simpleExpression;\n    }\n\n    public SQLExpr getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLExpr limit) {\n        this.limit = limit;\n    }\n\n    public SQLErrorLoggingClause clone() {\n        SQLErrorLoggingClause x = new SQLErrorLoggingClause();\n        if (into != null) {\n            x.setInto(into.clone());\n        }\n        if (simpleExpression != null) {\n            x.setSimpleExpression(simpleExpression.clone());\n        }\n        if (limit != null) {\n            x.setLimit(limit.clone());\n        }\n        return x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExceptionStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLExceptionStatement extends SQLStatementImpl {\n    // TODO: merge with OracleExceptionStatement\n    private List<Item> items = new ArrayList<>();\n\n    public List<Item> getItems() {\n        return items;\n    }\n\n    public void addItem(Item item) {\n        if (item != null) {\n            item.setParent(this);\n            this.items.add(item);\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, items);\n        }\n        v.endVisit(this);\n    }\n\n    public static class Item extends SQLObjectImpl {\n        private SQLExpr when;\n        private List<SQLStatement> statements = new ArrayList<SQLStatement>();\n\n        public SQLExpr getWhen() {\n            return when;\n        }\n\n        public void setWhen(SQLExpr when) {\n            this.when = when;\n        }\n\n        public List<SQLStatement> getStatements() {\n            return statements;\n        }\n\n        public void setStatement(SQLStatement statement) {\n            if (statement != null) {\n                statement.setParent(this);\n                this.statements.add(statement);\n            }\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, when);\n                acceptChild(visitor, statements);\n            }\n            visitor.endVisit(this);\n        }\n\n        public Item clone() {\n            Item x = new Item();\n            if (when != null) {\n                x.setWhen(when.clone());\n            }\n            for (SQLStatement stmt : statements) {\n                SQLStatement stmt2 = stmt.clone();\n                stmt2.setParent(x);\n                x.statements.add(stmt2);\n            }\n            return x;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExecuteImmediateStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class SQLExecuteImmediateStatement extends SQLStatementImpl {\n    protected SQLExpr dynamicSql;\n\n    protected final List<SQLExpr> into = new ArrayList<>();\n\n    public SQLExpr getDynamicSql() {\n        return dynamicSql;\n    }\n\n    public void setDynamicSql(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.dynamicSql = x;\n    }\n\n    public void setDynamicSql(String dynamicSql) {\n        this.setDynamicSql(new SQLCharExpr(dynamicSql));\n    }\n\n    public List<SQLExpr> getInto() {\n        return into;\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        acceptChild(v, dynamicSql);\n        acceptChild(v, into);\n    }\n\n    protected void cloneTo(SQLExecuteImmediateStatement x) {\n        super.cloneTo(x);\n        if (dynamicSql != null) {\n            x.setDynamicSql(dynamicSql.clone());\n        }\n        for (SQLExpr e : into) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.into.add(e2);\n        }\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExplainAnalyzeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLExplainAnalyzeStatement extends SQLStatementImpl {\n    protected SQLSelect select;\n\n    public SQLExplainAnalyzeStatement() {\n    }\n\n    public SQLExplainAnalyzeStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, select);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (select != null) {\n            children.add(select);\n        }\n        return children;\n    }\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect select) {\n        this.select = select;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExplainStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLExplainStatement extends SQLStatementImpl {\n    protected String type;\n    protected String format;\n    protected boolean extended;\n    protected boolean dependency;\n    protected boolean authorization;\n    protected boolean optimizer;\n    protected SQLStatement statement;\n    protected List<SQLCommentHint> hints;\n    protected boolean parenthesis;\n\n    public SQLExplainStatement() {\n    }\n\n    public SQLExplainStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLStatement getStatement() {\n        return statement;\n    }\n\n    public void setStatement(SQLStatement statement) {\n        if (statement != null) {\n            statement.setParent(this);\n        }\n        this.statement = statement;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statement);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (statement != null) {\n            children.add(statement);\n        }\n        return children;\n    }\n\n    public boolean isExtended() {\n        return extended;\n    }\n\n    public void setExtended(boolean extended) {\n        this.extended = extended;\n    }\n\n    public boolean isDependency() {\n        return dependency;\n    }\n\n    public void setDependency(boolean dependency) {\n        this.dependency = dependency;\n    }\n\n    public boolean isAuthorization() {\n        return authorization;\n    }\n\n    public void setAuthorization(boolean authorization) {\n        this.authorization = authorization;\n    }\n\n    public boolean isOptimizer() {\n        return optimizer;\n    }\n\n    public void setOptimizer(boolean optimizer) {\n        this.optimizer = optimizer;\n    }\n\n    public String getFormat() {\n        return format;\n    }\n\n    public void setFormat(String format) {\n        this.format = format;\n    }\n\n    public boolean isParenthesis() {\n        return parenthesis;\n    }\n\n    public void setParenthesis(boolean parenthesis) {\n        this.parenthesis = parenthesis;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExportDatabaseStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLExportDatabaseStatement extends SQLStatementImpl {\n    private SQLName db;\n    private boolean realtime;\n\n    public SQLName getDb() {\n        return db;\n    }\n\n    public void setDb(SQLName db) {\n        this.db = db;\n    }\n\n    public boolean isRealtime() {\n        return realtime;\n    }\n\n    public void setRealtime(boolean realtime) {\n        this.realtime = realtime;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, db);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExportTableStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLExportTableStatement extends SQLStatementImpl {\n    private SQLExprTableSource table;\n    private List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>();\n    private SQLExpr to;\n    private SQLExpr forReplication;\n\n    public SQLExportTableStatement() {\n        dbType = DbType.hive;\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    public SQLExpr getTo() {\n        return to;\n    }\n\n    public void setTo(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n\n    public SQLExpr getForReplication() {\n        return forReplication;\n    }\n\n    public void setForReplication(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.forReplication = x;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, table);\n            acceptChild(v, partition);\n            acceptChild(v, to);\n            acceptChild(v, forReplication);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLExprHint extends SQLObjectImpl implements SQLHint {\n    private SQLExpr expr;\n\n    public SQLExprHint() {\n    }\n\n    public SQLExprHint(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n\n        this.expr = expr;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprHint clone() {\n        SQLExprHint x = new SQLExprHint();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLExprStatement extends SQLStatementImpl implements SQLReplaceable {\n    private SQLExpr expr;\n\n    public SQLExprStatement() {\n    }\n\n    public SQLExprStatement(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n\n    public SQLExprStatement clone() {\n        SQLExprStatement x = new SQLExprStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    protected void cloneTo(SQLExprStatement x) {\n        super.cloneTo(x);\n        if (x.getExpr() != null) {\n            x.setExpr(x.getExpr().clone());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExprTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.repository.SchemaObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLExprTableSource extends SQLTableSourceImpl implements SQLReplaceable {\n    protected SQLExpr expr;\n    protected List<SQLName> partitions;\n    protected SQLTableSampling sampling;\n    protected SchemaObject schemaObject;\n\n    protected List<SQLName> columns;\n    protected boolean lateral;\n\n    public SQLExprTableSource() {\n    }\n\n    public SQLExprTableSource(String tableName) {\n        this(SQLUtils.toSQLExpr(tableName), null);\n    }\n\n    public SQLExprTableSource(SQLExpr expr) {\n        this(expr, null);\n    }\n\n    public SQLExprTableSource(SQLExpr expr, String alias) {\n        this.setExpr(expr);\n        this.setAlias(alias);\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    public void setExpr(String name) {\n        this.setExpr(new SQLIdentifierExpr(name));\n    }\n\n    public boolean isLateral() {\n        return lateral;\n    }\n\n    public void setLateral(boolean lateral) {\n        this.lateral = lateral;\n    }\n\n    public SQLTableSampling getSampling() {\n        return sampling;\n    }\n\n    public void setSampling(SQLTableSampling x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.sampling = x;\n    }\n\n    public SQLName getName() {\n        if (expr instanceof SQLName) {\n            return (SQLName) expr;\n        }\n        return null;\n    }\n\n    public String getTableName(boolean normalize) {\n        String tableName = getTableName();\n        if (normalize) {\n            return SQLUtils.normalize(tableName);\n        }\n        return tableName;\n    }\n\n    public String getTableName() {\n        if (expr == null) {\n            return null;\n        }\n\n        if (expr instanceof SQLIdentifierExpr) {\n            return ((SQLIdentifierExpr) expr).getName();\n        }\n\n        if (expr instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) expr).getSimpleName();\n        }\n\n        return null;\n    }\n\n    public String getSchema() {\n        if (expr == null) {\n            return null;\n        }\n\n        if (expr instanceof SQLPropertyExpr) {\n            SQLExpr owner = ((SQLPropertyExpr) expr).getOwner();\n            if (owner instanceof SQLIdentifierExpr) {\n                return ((SQLIdentifierExpr) owner).getName();\n            }\n\n            if (owner instanceof SQLPropertyExpr) {\n                return ((SQLPropertyExpr) owner).getSimpleName();\n            }\n\n            if (owner instanceof SQLAllColumnExpr) {\n                return \"*\";\n            }\n\n            return null;\n        }\n\n        return null;\n    }\n\n    public String getCatalog() {\n        if (expr instanceof SQLPropertyExpr) {\n            SQLExpr owner = ((SQLPropertyExpr) expr).getOwner();\n\n            if (owner instanceof SQLPropertyExpr) {\n                SQLExpr catalogExpr = ((SQLPropertyExpr) owner).getOwner();\n                if (catalogExpr instanceof SQLIdentifierExpr) {\n                    return ((SQLIdentifierExpr) catalogExpr).getName();\n                }\n            }\n\n            return null;\n        }\n\n        return null;\n    }\n\n    public boolean setCatalog(String catalog) {\n        if (expr instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n            SQLExpr owner = propertyExpr.getOwner();\n            if (owner instanceof SQLIdentifierExpr) {\n                if (catalog == null) {\n                    return false;\n                }\n\n                propertyExpr.setOwner(\n                        new SQLPropertyExpr(\n                                catalog,\n                                ((SQLIdentifierExpr) owner).getName()\n                        )\n                );\n                return true;\n            } else if (owner instanceof SQLPropertyExpr) {\n                SQLPropertyExpr propertyOwner = (SQLPropertyExpr) owner;\n                final SQLExpr propertyOwnerOwner = propertyOwner.getOwner();\n                if (propertyOwnerOwner instanceof SQLIdentifierExpr) {\n                    if (catalog == null) {\n                        propertyExpr.setOwner(((SQLIdentifierExpr) propertyOwnerOwner).getName());\n                    } else {\n                        propertyOwner.setOwner(\n                                new SQLIdentifierExpr(catalog));\n                    }\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public void setCatalog(String catalog, String schema) {\n        if (catalog == null) {\n            throw new IllegalArgumentException(\"catalog is null.\");\n        }\n\n        if (schema == null) {\n            throw new IllegalArgumentException(\"schema is null.\");\n        }\n\n        setSchema(schema);\n        setCatalog(catalog);\n    }\n\n    public void setSchema(String schema) {\n        if (expr instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n            if (StringUtils.isEmpty(schema)) {\n                this.setExpr(new SQLIdentifierExpr(propertyExpr.getName()));\n            } else {\n                propertyExpr.setOwner(schema);\n            }\n        } else {\n            if (StringUtils.isEmpty(schema)) {\n                return;\n            }\n\n            String ident = ((SQLIdentifierExpr) expr).getName();\n            this.setExpr(new SQLPropertyExpr(schema, ident));\n        }\n    }\n\n    public void setSimpleName(String name) {\n        if (StringUtils.isEmpty(name)) {\n            throw new IllegalArgumentException(\"schema is empty.\");\n        }\n        if (expr == null) {\n            expr = new SQLIdentifierExpr(name);\n        } else if (expr instanceof SQLPropertyExpr) {\n            ((SQLPropertyExpr) expr).setName(name);\n        } else {\n            expr = new SQLIdentifierExpr(name);\n        }\n    }\n\n    public List<SQLName> getPartitions() {\n        if (this.partitions == null) {\n            this.partitions = new ArrayList<SQLName>(2);\n        }\n\n        return partitions;\n    }\n\n    public int getPartitionSize() {\n        if (this.partitions == null) {\n            return 0;\n        }\n        return this.partitions.size();\n    }\n\n    public void addPartition(SQLName partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n\n        if (this.partitions == null) {\n            this.partitions = new ArrayList<SQLName>(2);\n        }\n        this.partitions.add(partition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n            acceptChild(visitor, sampling);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, columns);\n            super.accept0(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    public String computeAlias() {\n        String alias = this.getAlias();\n\n        if (alias == null) {\n            if (expr instanceof SQLName) {\n                alias = ((SQLName) expr).getSimpleName();\n            }\n        }\n\n        return SQLUtils.normalize(alias);\n    }\n\n    public SQLExprTableSource clone() {\n        SQLExprTableSource x = new SQLExprTableSource();\n        cloneTo(x);\n        return x;\n    }\n\n    public void cloneTo(SQLExprTableSource x) {\n        x.alias = alias;\n        x.lateral = lateral;\n\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n\n        if (hints != null) {\n            for (SQLHint p : hints) {\n                SQLHint p1 = p.clone();\n                x.getHints().add(p1);\n            }\n        }\n        if (partitions != null) {\n            for (SQLName p : partitions) {\n                SQLName p1 = p.clone();\n                x.addPartition(p1);\n            }\n        }\n\n        if (schemaObject != null) {\n            x.setSchemaObject(schemaObject);\n        }\n\n        if (columns != null) {\n            x.columns = new ArrayList<SQLName>(columns.size());\n\n            for (SQLName column : columns) {\n                SQLName clonedColumn = column.clone();\n                clonedColumn.setParent(x);\n                x.columns.add(clonedColumn);\n            }\n        }\n    }\n\n    public List<SQLName> getColumns() {\n        if (columns == null) {\n            columns = new ArrayList<SQLName>(2);\n        }\n        return columns;\n    }\n\n    public List<SQLName> getColumnsDirect() {\n        return columns;\n    }\n\n    public SchemaObject getSchemaObject() {\n        return schemaObject;\n    }\n\n    public void setSchemaObject(SchemaObject schemaObject) {\n        this.schemaObject = schemaObject;\n    }\n\n    public boolean containsAlias(String alias) {\n        long hashCode64 = FnvHash.hashCode64(alias);\n\n        return containsAlias(hashCode64);\n    }\n\n    public boolean containsAlias(long aliasHash) {\n        if (this.aliasHashCode64() == aliasHash) {\n            return true;\n        }\n\n        if (expr instanceof SQLPropertyExpr) {\n            long exprNameHash = ((SQLPropertyExpr) expr).hashCode64();\n            if (exprNameHash == aliasHash) {\n                return true;\n            }\n        }\n\n        if (expr instanceof SQLName) {\n            long exprNameHash = ((SQLName) expr).nameHashCode64();\n            return exprNameHash == aliasHash;\n        }\n\n        return false;\n    }\n\n    public SQLColumnDefinition findColumn(String columnName) {\n        if (columnName == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(columnName);\n        return findColumn(hash);\n    }\n\n    public SQLColumnDefinition findColumn(long columnNameHash) {\n        SQLObject object = resolveColum(columnNameHash);\n        if (object instanceof SQLColumnDefinition) {\n            return (SQLColumnDefinition) object;\n        }\n        return null;\n    }\n\n    public SQLObject resolveColumn(long columnNameHash) {\n        if (schemaObject != null) {\n            SQLStatement stmt = schemaObject.getStatement();\n            if (stmt instanceof SQLCreateTableStatement) {\n                SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) stmt;\n                return createTableStmt.findColumn(columnNameHash);\n            }\n        }\n\n        SQLObject resolvedOwnerObject = null;\n        if (expr instanceof SQLIdentifierExpr) {\n            resolvedOwnerObject = ((SQLIdentifierExpr) expr).getResolvedOwnerObject();\n        }\n\n        if (resolvedOwnerObject == null) {\n            return resolvedOwnerObject;\n        }\n\n        if (resolvedOwnerObject instanceof SQLWithSubqueryClause.Entry) {\n            final SQLSelect subQuery = ((SQLWithSubqueryClause.Entry) resolvedOwnerObject)\n                    .getSubQuery();\n            if (subQuery == null) {\n                return null;\n            }\n\n            final SQLSelectQueryBlock firstQueryBlock = subQuery.getFirstQueryBlock();\n            if (firstQueryBlock == null) {\n                return null;\n            }\n\n            SQLSelectItem selectItem = firstQueryBlock.findSelectItem(columnNameHash);\n            if (selectItem != null) {\n                return selectItem;\n            }\n        }\n        return null;\n    }\n\n    public SQLTableSource findTableSourceWithColumn(String columnName) {\n        if (columnName == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(columnName);\n        return findTableSourceWithColumn(hash, columnName, 0);\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnName_hash, String name, int option) {\n        if (schemaObject != null) {\n            SQLStatement stmt = schemaObject.getStatement();\n            if (stmt instanceof SQLCreateTableStatement) {\n                SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) stmt;\n                if (createTableStmt.findColumn(columnName_hash) != null) {\n                    return this;\n                }\n            }\n        }\n\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLTableSource tableSource = ((SQLIdentifierExpr) expr).getResolvedTableSource();\n            if (tableSource != null) {\n                return this;\n            }\n        }\n\n        return null;\n    }\n\n    public SQLTableSource findTableSource(long alias_hash) {\n        if (alias_hash == 0) {\n            return null;\n        }\n\n        if (aliasHashCode64() == alias_hash) {\n            return this;\n        }\n\n        if (expr instanceof SQLName) {\n            long exprNameHash = ((SQLName) expr).nameHashCode64();\n            if (exprNameHash == alias_hash) {\n                return this;\n            }\n        }\n\n        if (expr instanceof SQLPropertyExpr) {\n            long hash = ((SQLPropertyExpr) expr).hashCode64();\n            if (hash == alias_hash) {\n                return this;\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == this.expr) {\n            this.setExpr(target);\n            return true;\n        }\n\n        if (partitions != null) {\n            for (int i = 0; i < partitions.size(); i++) {\n                if (partitions.get(i) == expr) {\n                    target.setParent(this);\n                    partitions.set(i, (SQLName) target);\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public long aliasHashCode64() {\n        if (alias != null) {\n            if (aliasHashCode64 == 0) {\n                aliasHashCode64 = FnvHash.hashCode64(alias);\n            }\n            return aliasHashCode64;\n        }\n\n        if (expr instanceof SQLName) {\n            return ((SQLName) expr).nameHashCode64();\n        }\n\n        return 0;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        SQLExprTableSource that = (SQLExprTableSource) o;\n\n        if (expr != null ? !expr.equals(that.expr) : that.expr != null) {\n            return false;\n        }\n        if (partitions != null ? !partitions.equals(that.partitions) : that.partitions != null) {\n            return false;\n        }\n        if (sampling != null ? !sampling.equals(that.sampling) : that.sampling != null) {\n            return false;\n        }\n        if (schemaObject != null ? !schemaObject.equals(that.schemaObject) : that.schemaObject != null) {\n            return false;\n        }\n        return columns != null ? columns.equals(that.columns) : that.columns == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = super.hashCode();\n        result = 31 * result + (expr != null ? expr.hashCode() : 0);\n        result = 31 * result + (partitions != null ? partitions.hashCode() : 0);\n        result = 31 * result + (sampling != null ? sampling.hashCode() : 0);\n        result = 31 * result + (schemaObject != null ? schemaObject.hashCode() : 0);\n        result = 31 * result + (columns != null ? columns.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExternalRecordFormat.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLExternalRecordFormat extends SQLObjectImpl {\n    private SQLExpr delimitedBy;\n    private SQLExpr terminatedBy;\n    private SQLExpr escapedBy;\n    private SQLExpr collectionItemsTerminatedBy;\n    private SQLExpr mapKeysTerminatedBy;\n    private SQLExpr linesTerminatedBy;\n    private SQLExpr nullDefinedAs;\n    private SQLExpr serde;\n\n    private Boolean logfile;\n    private Boolean badfile;\n    private boolean ltrim;\n    private boolean missingFieldValuesAreNull;\n    private boolean rejectRowsWithAllNullFields;\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, delimitedBy);\n            acceptChild(visitor, terminatedBy);\n            acceptChild(visitor, escapedBy);\n            acceptChild(visitor, collectionItemsTerminatedBy);\n            acceptChild(visitor, mapKeysTerminatedBy);\n            acceptChild(visitor, linesTerminatedBy);\n            acceptChild(visitor, nullDefinedAs);\n            acceptChild(visitor, serde);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getDelimitedBy() {\n        return delimitedBy;\n    }\n\n    public void setDelimitedBy(SQLExpr delimitedBy) {\n        if (delimitedBy != null) {\n            delimitedBy.setParent(this);\n        }\n        this.delimitedBy = delimitedBy;\n    }\n\n    public SQLExpr getTerminatedBy() {\n        return terminatedBy;\n    }\n\n    public void setTerminatedBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.terminatedBy = x;\n    }\n\n    public SQLExpr getSerde() {\n        return serde;\n    }\n\n    public void setSerde(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.serde = x;\n    }\n\n    public SQLExpr getMapKeysTerminatedBy() {\n        return mapKeysTerminatedBy;\n    }\n\n    public void setMapKeysTerminatedBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        mapKeysTerminatedBy = x;\n    }\n\n    public SQLExpr getCollectionItemsTerminatedBy() {\n        return collectionItemsTerminatedBy;\n    }\n\n    public void setCollectionItemsTerminatedBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.collectionItemsTerminatedBy = x;\n    }\n\n    public SQLExpr getEscapedBy() {\n        return escapedBy;\n    }\n\n    public void setEscapedBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.escapedBy = x;\n    }\n\n    public SQLExpr getLinesTerminatedBy() {\n        return linesTerminatedBy;\n    }\n\n    public void setLinesTerminatedBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.linesTerminatedBy = x;\n    }\n\n    public SQLExpr getNullDefinedAs() {\n        return nullDefinedAs;\n    }\n\n    public void setNullDefinedAs(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.nullDefinedAs = x;\n    }\n\n    public Boolean getLogfile() {\n        return logfile;\n    }\n\n    public void setLogfile(Boolean logfile) {\n        this.logfile = logfile;\n    }\n\n    public Boolean getBadfile() {\n        return badfile;\n    }\n\n    public void setBadfile(Boolean badfile) {\n        this.badfile = badfile;\n    }\n\n    public boolean isLtrim() {\n        return ltrim;\n    }\n\n    public void setLtrim(boolean ltrim) {\n        this.ltrim = ltrim;\n    }\n\n    public boolean isRejectRowsWithAllNullFields() {\n        return rejectRowsWithAllNullFields;\n    }\n\n    public void setRejectRowsWithAllNullFields(boolean rejectRowsWithAllNullFields) {\n        this.rejectRowsWithAllNullFields = rejectRowsWithAllNullFields;\n    }\n\n    public boolean isMissingFieldValuesAreNull() {\n        return missingFieldValuesAreNull;\n    }\n\n    public void setMissingFieldValuesAreNull(boolean missingFieldValuesAreNull) {\n        this.missingFieldValuesAreNull = missingFieldValuesAreNull;\n    }\n\n    public SQLExternalRecordFormat clone() {\n        SQLExternalRecordFormat x = new SQLExternalRecordFormat();\n\n        if (delimitedBy != null) {\n            x.setDelimitedBy(delimitedBy.clone());\n        }\n\n        if (escapedBy != null) {\n            x.setEscapedBy(escapedBy.clone());\n        }\n\n        if (collectionItemsTerminatedBy != null) {\n            x.setCollectionItemsTerminatedBy(collectionItemsTerminatedBy.clone());\n        }\n\n        if (mapKeysTerminatedBy != null) {\n            x.setMapKeysTerminatedBy(mapKeysTerminatedBy.clone());\n        }\n\n        if (linesTerminatedBy != null) {\n            x.setLinesTerminatedBy(linesTerminatedBy.clone());\n        }\n\n        if (nullDefinedAs != null) {\n            x.setNullDefinedAs(nullDefinedAs.clone());\n        }\n\n        if (serde != null) {\n            x.setSerde(serde.clone());\n        }\n\n        x.logfile = logfile;\n        x.badfile = badfile;\n        x.ltrim = ltrim;\n        x.missingFieldValuesAreNull = missingFieldValuesAreNull;\n        x.rejectRowsWithAllNullFields = rejectRowsWithAllNullFields;\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLFetchStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLFetchStatement extends SQLStatementImpl implements SQLReplaceable {\n    private SQLName cursorName;\n    private boolean bulkCollect;\n    private List<SQLExpr> into = new ArrayList<SQLExpr>();\n    private SQLLimit limit;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, cursorName);\n            acceptChild(visitor, into);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getCursorName() {\n        return cursorName;\n    }\n\n    public void setCursorName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.cursorName = x;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.limit = x;\n    }\n\n    public List<SQLExpr> getInto() {\n        return into;\n    }\n\n    public void setInto(List<SQLExpr> into) {\n        this.into = into;\n    }\n\n    public boolean isBulkCollect() {\n        return bulkCollect;\n    }\n\n    public void setBulkCollect(boolean bulkCollect) {\n        this.bulkCollect = bulkCollect;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (cursorName == expr) {\n            setCursorName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLForStatement extends SQLStatementImpl {\n    protected SQLName index;\n    protected boolean isReverse;\n    protected SQLExpr range;\n\n    protected List<SQLStatement> statements = new ArrayList<SQLStatement>();\n\n    public SQLForStatement() {\n    }\n\n    public SQLName getIndex() {\n        return index;\n    }\n\n    public void setIndex(SQLName index) {\n        this.index = index;\n    }\n\n    public void setReverse(boolean isReverse) {\n        this.isReverse = isReverse;\n    }\n\n    public boolean isReverse() {\n        return isReverse;\n    }\n\n    public SQLExpr getRange() {\n        return range;\n    }\n\n    public void setRange(SQLExpr range) {\n        if (range != null) {\n            range.setParent(this);\n        }\n        this.range = range;\n    }\n\n    public List<SQLStatement> getStatements() {\n        return statements;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, index);\n            acceptChild(v, range);\n            acceptChild(v, statements);\n        }\n        v.endVisit(this);\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\n\nimport java.util.List;\n\npublic interface SQLForeignKeyConstraint extends SQLConstraint, SQLTableElement, SQLTableConstraint {\n    List<SQLName> getReferencingColumns();\n\n    SQLExprTableSource getReferencedTable();\n\n    SQLName getReferencedTableName();\n\n    void setReferencedTableName(SQLName value);\n\n    List<SQLName> getReferencedColumns();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLForeignKeyImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLForeignKeyImpl extends SQLConstraintImpl implements SQLForeignKeyConstraint {\n    private SQLExprTableSource referencedTable;\n    private List<SQLName> referencingColumns = new ArrayList<SQLName>();\n    private List<SQLName> referencedColumns = new ArrayList<SQLName>();\n    private boolean onDeleteCascade;\n    private boolean onDeleteSetNull;\n    private boolean disableNovalidate;\n\n    private boolean hasConstraint;\n    private boolean notEnforced;\n\n    public SQLForeignKeyImpl() {\n    }\n\n    public boolean isHasConstraint() {\n        return hasConstraint;\n    }\n\n    public void setHasConstraint(boolean hasConstraint) {\n        this.hasConstraint = hasConstraint;\n    }\n\n    @Override\n    public List<SQLName> getReferencingColumns() {\n        return referencingColumns;\n    }\n\n    @Override\n    public SQLExprTableSource getReferencedTable() {\n        return referencedTable;\n    }\n\n    @Override\n    public SQLName getReferencedTableName() {\n        if (referencedTable == null) {\n            return null;\n        }\n        return referencedTable.getName();\n    }\n\n    @Override\n    public void setReferencedTableName(SQLName value) {\n        if (value == null) {\n            this.referencedTable = null;\n            return;\n        }\n        this.setReferencedTable(new SQLExprTableSource(value));\n    }\n\n    public void setReferencedTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.referencedTable = x;\n    }\n\n    @Override\n    public List<SQLName> getReferencedColumns() {\n        return referencedColumns;\n    }\n\n    public boolean isOnDeleteCascade() {\n        return onDeleteCascade;\n    }\n\n    public void setOnDeleteCascade(boolean onDeleteCascade) {\n        this.onDeleteCascade = onDeleteCascade;\n    }\n\n    public boolean isOnDeleteSetNull() {\n        return onDeleteSetNull;\n    }\n\n    public void setOnDeleteSetNull(boolean onDeleteSetNull) {\n        this.onDeleteSetNull = onDeleteSetNull;\n    }\n\n    public boolean isDisableNovalidate() {\n        return disableNovalidate;\n    }\n\n    public void setDisableNovalidate(boolean disableNovalidate) {\n        this.disableNovalidate = disableNovalidate;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getReferencedTableName());\n            acceptChild(visitor, this.getReferencingColumns());\n            acceptChild(visitor, this.getReferencedColumns());\n        }\n        visitor.endVisit(this);\n    }\n\n    public void cloneTo(SQLForeignKeyImpl x) {\n        super.cloneTo(x);\n\n        if (referencedTable != null) {\n            x.setReferencedTable(referencedTable.clone());\n        }\n\n        for (SQLName column : referencingColumns) {\n            SQLName columnClone = column.clone();\n            columnClone.setParent(x);\n            x.getReferencingColumns().add(columnClone);\n        }\n\n        for (SQLName column : referencedColumns) {\n            SQLName columnClone = column.clone();\n            columnClone.setParent(x);\n            x.getReferencedColumns().add(columnClone);\n        }\n    }\n\n    public SQLForeignKeyImpl clone() {\n        SQLForeignKeyImpl x = new SQLForeignKeyImpl();\n        cloneTo(x);\n        return x;\n    }\n\n    public boolean isNotEnforced() {\n        return notEnforced;\n    }\n\n    public void setNotEnforced(boolean notEnforced) {\n        this.notEnforced = notEnforced;\n    }\n\n    public static enum Match {\n        FULL(\"FULL\"), PARTIAL(\"PARTIAL\"), SIMPLE(\"SIMPLE\");\n\n        public final String name;\n        public final String nameLCase;\n\n        Match(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n    }\n\n    public static enum On {\n        DELETE(\"DELETE\"),\n        UPDATE(\"UPDATE\");\n\n        public final String name;\n        public final String nameLCase;\n\n        On(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n    }\n\n    public static enum Option {\n        RESTRICT(\"RESTRICT\"), CASCADE(\"CASCADE\"), SET_NULL(\"SET NULL\"), NO_ACTION(\"NO ACTION\"), SET_DEFAULT(\"SET DEFAULT\");\n\n        public final String name;\n        public final String nameLCase;\n\n        Option(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n\n        public String getText() {\n            return name;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLGeneratedTableSource.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLGeneratedTableSource extends SQLTableSourceImpl\n        implements SQLReplaceable {\n    private final List<SQLExpr> items = new ArrayList<SQLExpr>();\n    protected List<SQLName> columns = new ArrayList<SQLName>();\n    private SQLIdentifierExpr methodName;\n\n    public List<SQLExpr> getItems() {\n        return items;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, methodName);\n            acceptChild(v, columns);\n            acceptChild(v, items);\n            super.accept0(v);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < items.size(); i++) {\n            if (items.get(i) == expr) {\n                target.setParent(this);\n                items.set(i, target);\n                return true;\n            }\n        }\n        if (target instanceof SQLName) {\n            SQLName targetName = (SQLName) target;\n            for (int i = 0; i < columns.size(); i++) {\n                if (columns.get(i) == expr) {\n                    target.setParent(this);\n                    columns.set(i, targetName);\n                    return true;\n                }\n            }\n        }\n        if (target instanceof SQLIdentifierExpr) {\n            if (methodName == expr) {\n                target.setParent(this);\n                methodName = (SQLIdentifierExpr) target;\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public SQLIdentifierExpr getMethodName() {\n        return methodName;\n    }\n\n    public void setMethodName(SQLIdentifierExpr methodName) {\n        this.methodName = methodName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLGetDiagnosticsStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLGetDiagnosticsStatement extends SQLStatementImpl implements SQLReplaceable {\n    private SQLExpr expr;\n\n    public SQLGetDiagnosticsStatement() {\n    }\n\n    public SQLGetDiagnosticsStatement(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n        visitor.endVisit(this);\n\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        setExpr(target);\n        return this.expr == expr;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLGrantStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLGrantStatement extends SQLPrivilegeStatement {\n    // mysql\n    private SQLExpr maxQueriesPerHour;\n    private SQLExpr maxUpdatesPerHour;\n    private SQLExpr maxConnectionsPerHour;\n    private SQLExpr maxUserConnections;\n\n    private boolean adminOption;\n\n    private SQLExpr identifiedBy;\n    private String identifiedByPassword;\n\n    private boolean withGrantOption;\n\n    public SQLGrantStatement() {\n    }\n\n    public SQLGrantStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.privileges);\n            acceptChild(visitor, resource);\n            acceptChild(visitor, users);\n            acceptChild(visitor, identifiedBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.addAll(privileges);\n        if (resource != null) {\n            children.add(resource);\n        }\n        if (users != null) {\n            children.addAll(users);\n        }\n        if (identifiedBy != null) {\n            children.add(identifiedBy);\n        }\n        return children;\n    }\n\n    public SQLObjectType getResourceType() {\n        return resourceType;\n    }\n\n    public void setResourceType(SQLObjectType resourceType) {\n        this.resourceType = resourceType;\n    }\n\n    public SQLExpr getMaxQueriesPerHour() {\n        return maxQueriesPerHour;\n    }\n\n    public void setMaxQueriesPerHour(SQLExpr maxQueriesPerHour) {\n        this.maxQueriesPerHour = maxQueriesPerHour;\n    }\n\n    public SQLExpr getMaxUpdatesPerHour() {\n        return maxUpdatesPerHour;\n    }\n\n    public void setMaxUpdatesPerHour(SQLExpr maxUpdatesPerHour) {\n        this.maxUpdatesPerHour = maxUpdatesPerHour;\n    }\n\n    public SQLExpr getMaxConnectionsPerHour() {\n        return maxConnectionsPerHour;\n    }\n\n    public void setMaxConnectionsPerHour(SQLExpr maxConnectionsPerHour) {\n        this.maxConnectionsPerHour = maxConnectionsPerHour;\n    }\n\n    public SQLExpr getMaxUserConnections() {\n        return maxUserConnections;\n    }\n\n    public void setMaxUserConnections(SQLExpr maxUserConnections) {\n        this.maxUserConnections = maxUserConnections;\n    }\n\n    public boolean isAdminOption() {\n        return adminOption;\n    }\n\n    public void setAdminOption(boolean adminOption) {\n        this.adminOption = adminOption;\n    }\n\n    public SQLExpr getIdentifiedBy() {\n        return identifiedBy;\n    }\n\n    public void setIdentifiedBy(SQLExpr identifiedBy) {\n        this.identifiedBy = identifiedBy;\n    }\n\n    public String getIdentifiedByPassword() {\n        return identifiedByPassword;\n    }\n\n    public void setIdentifiedByPassword(String identifiedByPassword) {\n        this.identifiedByPassword = identifiedByPassword;\n    }\n\n    public boolean getWithGrantOption() {\n        return withGrantOption;\n    }\n\n    public void setWithGrantOption(boolean withGrantOption) {\n        this.withGrantOption = withGrantOption;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLIfStatement extends SQLStatementImpl implements SQLReplaceable {\n    private SQLExpr condition;\n    private List<SQLStatement> statements = new ArrayList<SQLStatement>();\n    private List<ElseIf> elseIfList = new ArrayList<ElseIf>();\n    private Else elseItem;\n\n    public SQLIfStatement clone() {\n        SQLIfStatement x = new SQLIfStatement();\n\n        for (SQLStatement stmt : statements) {\n            SQLStatement stmt2 = stmt.clone();\n            stmt2.setParent(x);\n            x.statements.add(stmt2);\n        }\n        for (ElseIf o : elseIfList) {\n            ElseIf o2 = o.clone();\n            o2.setParent(x);\n            x.elseIfList.add(o2);\n        }\n        if (elseItem != null) {\n            x.setElseItem(elseItem.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (condition != null) {\n                condition.accept(visitor);\n            }\n\n            for (int i = 0; i < statements.size(); i++) {\n                statements.get(i)\n                        .accept(visitor);\n            }\n\n            for (int i = 0; i < elseIfList.size(); i++) {\n                elseIfList.get(i)\n                        .accept(visitor);\n            }\n\n            if (elseItem != null) {\n                elseItem.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getCondition() {\n        return condition;\n    }\n\n    public void setCondition(SQLExpr condition) {\n        if (condition != null) {\n            condition.setParent(this);\n        }\n        this.condition = condition;\n    }\n\n    public List<SQLStatement> getStatements() {\n        return statements;\n    }\n\n    public void addStatement(SQLStatement statement) {\n        if (statement != null) {\n            statement.setParent(this);\n        }\n        this.statements.add(statement);\n    }\n\n    public List<ElseIf> getElseIfList() {\n        return elseIfList;\n    }\n\n    public Else getElseItem() {\n        return elseItem;\n    }\n\n    public void setElseItem(Else elseItem) {\n        if (elseItem != null) {\n            elseItem.setParent(this);\n        }\n        this.elseItem = elseItem;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (condition == expr) {\n            setCondition(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public static class ElseIf extends SQLObjectImpl implements SQLReplaceable {\n        private SQLExpr condition;\n        private List<SQLStatement> statements = new ArrayList<SQLStatement>();\n        private boolean isConcatenated;\n\n        public boolean isConcatenated() {\n            return isConcatenated;\n        }\n\n        public void setConcatenated(boolean isConcatenated) {\n            this.isConcatenated = isConcatenated;\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, condition);\n                acceptChild(visitor, statements);\n            }\n            visitor.endVisit(this);\n        }\n\n        public List<SQLStatement> getStatements() {\n            return statements;\n        }\n\n        public void setStatements(List<SQLStatement> statements) {\n            this.statements = statements;\n        }\n\n        public SQLExpr getCondition() {\n            return condition;\n        }\n\n        public void setCondition(SQLExpr condition) {\n            if (condition != null) {\n                condition.setParent(this);\n            }\n            this.condition = condition;\n        }\n\n        @Override\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            if (condition == expr) {\n                setCondition(target);\n                return true;\n            }\n\n            return false;\n        }\n\n        public ElseIf clone() {\n            ElseIf x = new ElseIf();\n\n            if (condition != null) {\n                x.setCondition(condition.clone());\n            }\n            for (SQLStatement stmt : statements) {\n                SQLStatement stmt2 = stmt.clone();\n                stmt2.setParent(x);\n                x.statements.add(stmt2);\n            }\n\n            return x;\n        }\n    }\n\n    public static class Else extends SQLObjectImpl {\n        private List<SQLStatement> statements = new ArrayList<SQLStatement>();\n\n        @Override\n        public void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, statements);\n            }\n            visitor.endVisit(this);\n        }\n\n        public List<SQLStatement> getStatements() {\n            return statements;\n        }\n\n        public void setStatements(List<SQLStatement> statements) {\n            this.statements = statements;\n        }\n\n        public Else clone() {\n            Else x = new Else();\n            for (SQLStatement stmt : statements) {\n                SQLStatement stmt2 = stmt.clone();\n                stmt2.setParent(x);\n                x.statements.add(stmt2);\n            }\n            return x;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLImportDatabaseStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLImportDatabaseStatement extends SQLStatementImpl {\n    private SQLName db;\n    private SQLName status;\n\n    public SQLName getDb() {\n        return db;\n    }\n\n    public void setDb(SQLName db) {\n        this.db = db;\n    }\n\n    public SQLName getStatus() {\n        return status;\n    }\n\n    public void setStatus(SQLName status) {\n        this.status = status;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, db);\n            acceptChild(v, status);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLImportTableStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLImportTableStatement extends SQLStatementImpl {\n    private boolean extenal;\n    private SQLExprTableSource table;\n    private List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>();\n    private SQLExpr from;\n    private SQLExpr location;\n    // for ads\n    private SQLIntegerExpr version;\n    private boolean usingBuild;\n\n    public SQLImportTableStatement() {\n        dbType = DbType.hive;\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    public SQLExpr getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.from = x;\n    }\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public void setLocation(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.location = x;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, table);\n            acceptChild(v, partition);\n            acceptChild(v, from);\n            acceptChild(v, location);\n            acceptChild(v, version);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLIntegerExpr getVersion() {\n        return version;\n    }\n\n    public void setVersion(SQLIntegerExpr version) {\n        this.version = version;\n    }\n\n    public boolean isUsingBuild() {\n        return usingBuild;\n    }\n\n    public void setUsingBuild(boolean usingBuild) {\n        this.usingBuild = usingBuild;\n    }\n\n    public boolean isExtenal() {\n        return extenal;\n    }\n\n    public void setExtenal(boolean extenal) {\n        this.extenal = extenal;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertInto.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class SQLInsertInto extends SQLStatementImpl implements SQLReplaceable {\n    protected List<String> insertBeforeComments;\n\n    protected SQLExprTableSource tableSource;\n    protected final List<SQLExpr> columns = new ArrayList<SQLExpr>();\n    protected transient String columnsString;\n    protected transient long columnsStringHash;\n    protected SQLSelect query;\n    protected final List<ValuesClause> valuesList = new ArrayList<ValuesClause>();\n    protected boolean overwrite;\n    protected List<SQLAssignItem> partitions;\n\n    public SQLInsertInto() {\n    }\n\n    public void cloneTo(SQLInsertInto x) {\n        if (tableSource != null) {\n            x.setTableSource(tableSource.clone());\n        }\n        for (SQLExpr column : columns) {\n            SQLExpr column2 = column.clone();\n            column2.setParent(x);\n            x.columns.add(column2);\n        }\n        if (query != null) {\n            x.setQuery(query.clone());\n        }\n        for (ValuesClause v : valuesList) {\n            ValuesClause v2 = v.clone();\n            v2.setParent(x);\n            x.valuesList.add(v2);\n        }\n\n        if (hint != null) {\n            x.setHint(hint.clone());\n        }\n\n        x.overwrite = overwrite;\n        if (partitions != null) {\n            for (SQLAssignItem item : partitions) {\n                x.addPartition(item.clone());\n            }\n        }\n    }\n\n    public void addInsertBeforeComment(List<String> comments) {\n        if (insertBeforeComments == null) {\n            insertBeforeComments = new ArrayList<>();\n        }\n\n        insertBeforeComments.addAll(comments);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public List<String> getInsertBeforeCommentsDirect() {\n        return insertBeforeComments;\n    }\n\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < columns.size(); i++) {\n            if (columns.get(i) == expr) {\n                target.setParent(this);\n                columns.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public SQLCommentHint getHint() {\n        return hint;\n    }\n\n    public void setHint(SQLCommentHint x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.hint = x;\n    }\n\n    public abstract SQLInsertInto clone();\n\n    public String getAlias() {\n        return tableSource.getAlias();\n    }\n\n    public void setAlias(String alias) {\n        this.tableSource.setAlias(alias);\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public SQLName getTableName() {\n        return (SQLName) tableSource.getExpr();\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.setTableSource(new SQLExprTableSource(tableName));\n    }\n\n    public void setTableSource(SQLName tableName) {\n        this.setTableSource(new SQLExprTableSource(tableName));\n    }\n\n    public SQLSelect getQuery() {\n        return query;\n    }\n\n    public void setQuery(SQLSelectQuery query) {\n        this.setQuery(new SQLSelect(query));\n    }\n\n    public void setQuery(SQLSelect query) {\n        if (query != null) {\n            query.setParent(this);\n        }\n        this.query = query;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLExpr column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public ValuesClause getValues() {\n        if (valuesList.isEmpty()) {\n            return null;\n        }\n        return valuesList.get(0);\n    }\n\n    public void setValues(ValuesClause values) {\n        if (valuesList.isEmpty()) {\n            valuesList.add(values);\n        } else {\n            valuesList.set(0, values);\n        }\n    }\n\n    public List<ValuesClause> getValuesList() {\n        return valuesList;\n    }\n\n    public void addValueCause(ValuesClause valueClause) {\n        if (valueClause != null) {\n            valueClause.setParent(this);\n        }\n        valuesList.add(valueClause);\n    }\n\n    public String getColumnsString() {\n        return columnsString;\n    }\n\n    public long getColumnsStringHash() {\n        return columnsStringHash;\n    }\n\n    public void setColumnsString(String columnsString, long columnsStringHash) {\n        this.columnsString = columnsString;\n        this.columnsStringHash = columnsStringHash;\n    }\n\n    public boolean isOverwrite() {\n        return overwrite;\n    }\n\n    public void setOverwrite(boolean overwrite) {\n        this.overwrite = overwrite;\n    }\n\n    public void addPartition(SQLAssignItem partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n\n        if (partitions == null) {\n            partitions = new ArrayList<SQLAssignItem>();\n        }\n\n        this.partitions.add(partition);\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLInsertStatement extends SQLInsertInto implements SQLStatement {\n    protected SQLWithSubqueryClause with;\n    protected boolean upsert; // for phoenix\n\n    public SQLInsertStatement() {\n    }\n\n    public void cloneTo(SQLInsertStatement x) {\n        super.cloneTo(x);\n        x.dbType = dbType;\n        x.upsert = upsert;\n        x.afterSemi = afterSemi;\n\n        if (with != null) {\n            x.setWith(with.clone());\n        }\n    }\n\n    public SQLInsertStatement clone() {\n        SQLInsertStatement x = new SQLInsertStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, with);\n            this.acceptChild(visitor, tableSource);\n            this.acceptChild(visitor, columns);\n            this.acceptChild(visitor, valuesList);\n            this.acceptChild(visitor, query);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n\n        children.add(tableSource);\n        children.addAll(this.columns);\n        children.addAll(this.valuesList);\n        if (query != null) {\n            children.add(query);\n        }\n\n        return children;\n    }\n\n    public boolean isUpsert() {\n        return upsert;\n    }\n\n    public void setUpsert(boolean upsert) {\n        this.upsert = upsert;\n    }\n\n    public static class ValuesClause extends SQLObjectImpl implements SQLReplaceable {\n        private final List values;\n        private transient String originalString;\n        private transient int replaceCount;\n\n        public ValuesClause() {\n            this(new ArrayList<SQLExpr>());\n        }\n\n        public ValuesClause clone() {\n            ValuesClause x = new ValuesClause(new ArrayList<SQLExpr>(this.values.size()));\n            for (Object v : values) {\n                x.addValue(v);\n            }\n            return x;\n        }\n\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            for (int i = 0; i < values.size(); i++) {\n                if (values.get(i) == expr) {\n                    target.setParent(this);\n                    values.set(i, target);\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        public ValuesClause(List<SQLExpr> values) {\n            this.values = values;\n            for (int i = 0; i < values.size(); ++i) {\n                values.get(i).setParent(this);\n            }\n        }\n\n        public ValuesClause(List values, SQLObject parent) {\n            this.values = values;\n            for (int i = 0; i < values.size(); ++i) {\n                Object val = values.get(i);\n                if (val instanceof SQLObject) {\n                    ((SQLObject) val).setParent(this);\n                }\n            }\n            this.parent = parent;\n        }\n\n        public void addValue(Object value) {\n            if (value instanceof SQLObject) {\n                ((SQLObject) value).setParent(this);\n            }\n            values.add(value);\n        }\n\n        public void addValue(SQLExpr value) {\n            value.setParent(this);\n            values.add(value);\n        }\n\n        public List<SQLExpr> getValues() {\n            return values;\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                for (int i = 0; i < values.size(); i++) {\n                    Object item = values.get(i);\n                    if (item instanceof SQLObject) {\n                        SQLObject value = (SQLObject) item;\n                        value.accept(visitor);\n                    }\n                }\n            }\n\n            visitor.endVisit(this);\n        }\n\n        public String getOriginalString() {\n            return originalString;\n        }\n\n        public void setOriginalString(String originalString) {\n            this.originalString = originalString;\n        }\n\n        public int getReplaceCount() {\n            return replaceCount;\n        }\n\n        public void incrementReplaceCount() {\n            this.replaceCount++;\n        }\n    }\n\n    @Override\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public boolean isAfterSemi() {\n        return afterSemi;\n    }\n\n    @Override\n    public void setAfterSemi(boolean afterSemi) {\n        this.afterSemi = afterSemi;\n    }\n\n    public SQLWithSubqueryClause getWith() {\n        return with;\n    }\n\n    public void setWith(SQLWithSubqueryClause with) {\n        if (with != null) {\n            with.setParent(this);\n        }\n        this.with = with;\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(this, dbType);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLJoinTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.FastsqlColumnAmbiguousException;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.repository.SchemaResolveVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplaceable {\n    protected SQLTableSource left;\n    protected JoinType joinType;\n    protected SQLTableSource right;\n    protected SQLExpr condition;\n    protected final List<SQLExpr> using = new ArrayList<SQLExpr>();\n    protected boolean natural;\n    protected UDJ udj; // for maxcompute\n    protected boolean asof; // for clickhouse\n    protected boolean global; // for clickhouse\n\n    public SQLJoinTableSource(String alias) {\n        super(alias);\n    }\n\n    public SQLJoinTableSource() {\n    }\n\n    public SQLJoinTableSource(SQLTableSource left, JoinType joinType, SQLTableSource right, SQLExpr condition) {\n        this.setLeft(left);\n        this.setJoinType(joinType);\n        this.setRight(right);\n        this.setCondition(condition);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, left);\n            acceptChild(visitor, right);\n            acceptChild(visitor, condition);\n            acceptChild(visitor, using);\n            acceptChild(visitor, udj);\n            super.accept0(visitor);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public UDJ getUdj() {\n        return udj;\n    }\n\n    public void setUdj(UDJ x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.udj = x;\n    }\n\n    public boolean isAsof() {\n        return asof;\n    }\n\n    public void setAsof(boolean asof) {\n        this.asof = asof;\n    }\n\n    public JoinType getJoinType() {\n        return this.joinType;\n    }\n\n    public void setJoinType(JoinType joinType) {\n        this.joinType = joinType;\n    }\n\n    public void setImplicitJoinToCross() {\n        if (joinType == JoinType.COMMA) {\n            joinType = JoinType.CROSS_JOIN;\n        }\n        if (left instanceof SQLJoinTableSource) {\n            ((SQLJoinTableSource) left).setImplicitJoinToCross();\n        }\n\n        if (right instanceof SQLJoinTableSource) {\n            ((SQLJoinTableSource) right).setImplicitJoinToCross();\n        }\n    }\n\n    public SQLTableSource getLeft() {\n        return this.left;\n    }\n\n    public void setLeft(SQLTableSource left) {\n        if (left != null) {\n            left.setParent(this);\n        }\n        this.left = left;\n    }\n\n    public void setLeft(String tableName, String alias) {\n        SQLExprTableSource tableSource;\n        if (tableName == null || tableName.length() == 0) {\n            tableSource = null;\n        } else {\n            tableSource = new SQLExprTableSource(new SQLIdentifierExpr(tableName), alias);\n        }\n        this.setLeft(tableSource);\n    }\n\n    public void setRight(String tableName, String alias) {\n        SQLExprTableSource tableSource;\n        if (tableName == null || tableName.length() == 0) {\n            tableSource = null;\n        } else {\n            tableSource = new SQLExprTableSource(new SQLIdentifierExpr(tableName), alias);\n        }\n        this.setRight(tableSource);\n    }\n\n    public SQLTableSource getRight() {\n        return this.right;\n    }\n\n    public void setRight(SQLTableSource right) {\n        if (right != null) {\n            right.setParent(this);\n        }\n        this.right = right;\n    }\n\n    public SQLExpr getCondition() {\n        return this.condition;\n    }\n\n    public void setCondition(SQLExpr condition) {\n        if (condition != null) {\n            condition.setParent(this);\n        }\n        this.condition = condition;\n    }\n\n    public void addCondition(SQLExpr condition) {\n        if (this.condition == null) {\n            this.condition = condition;\n            setImplicitJoinToCross();\n            return;\n        }\n\n        this.condition = SQLBinaryOpExpr.and(this.condition, condition);\n    }\n\n    public void addConditionnIfAbsent(SQLExpr condition) {\n        if (this.containsCondition(condition)) {\n            return;\n        }\n        this.condition = SQLBinaryOpExpr.and(this.condition, condition);\n    }\n\n    public boolean containsCondition(SQLExpr condition) {\n        if (this.condition == null) {\n            return false;\n        }\n\n        if (this.condition.equals(condition)) {\n            return false;\n        }\n\n        if (this.condition instanceof SQLBinaryOpExpr) {\n            return ((SQLBinaryOpExpr) this.condition).contains(condition);\n        }\n\n        return false;\n    }\n\n    public List<SQLExpr> getUsing() {\n        return this.using;\n    }\n\n    public boolean isNatural() {\n        return natural;\n    }\n\n    public void setNatural(boolean natural) {\n        this.natural = natural;\n    }\n\n    public void output(StringBuilder buf) {\n        this.left.output(buf);\n        buf.append(' ');\n        buf.append(JoinType.toString(this.joinType));\n        buf.append(' ');\n        this.right.output(buf);\n\n        if (this.condition != null) {\n            buf.append(\" ON \");\n            this.condition.output(buf);\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (condition == expr) {\n            setCondition(target);\n            return true;\n        }\n\n        for (int i = 0; i < using.size(); i++) {\n            if (using.get(i) == expr) {\n                target.setParent(this);\n                using.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public boolean replace(SQLTableSource cmp, SQLTableSource target) {\n        if (left == cmp) {\n            if (target == null) {\n                SQLUtils.replaceInParent(this, right);\n            } else {\n                setLeft(target);\n            }\n            return true;\n        } else if (right == cmp) {\n            if (target == null) {\n                SQLUtils.replaceInParent(this, left);\n            } else {\n                setRight(target);\n            }\n            return true;\n        }\n\n        return false;\n    }\n\n    public static enum JoinType {\n        COMMA(\",\"),\n        JOIN(\"JOIN\"),\n        INNER_JOIN(\"INNER JOIN\"),\n        CROSS_JOIN(\"CROSS JOIN\"),\n        NATURAL_JOIN(\"NATURAL JOIN\"),\n        NATURAL_CROSS_JOIN(\"NATURAL CROSS JOIN\"),\n        NATURAL_LEFT_JOIN(\"NATURAL LEFT JOIN\"),\n        NATURAL_RIGHT_JOIN(\"NATURAL RIGHT JOIN\"),\n        NATURAL_INNER_JOIN(\"NATURAL INNER JOIN\"),\n        LEFT_OUTER_JOIN(\"LEFT JOIN\"),\n        LEFT_SEMI_JOIN(\"LEFT SEMI JOIN\"),\n        LEFT_ANTI_JOIN(\"LEFT ANTI JOIN\"),\n        ARRAY_JOIN(\"ARRAY JOIN\"),\n        LEFT_ARRAY_JOIN(\"LEFT ARRAY JOIN\"),\n        RIGHT_OUTER_JOIN(\"RIGHT JOIN\"),\n        FULL_OUTER_JOIN(\"FULL JOIN\"),\n        STRAIGHT_JOIN(\"STRAIGHT_JOIN\"),\n        OUTER_APPLY(\"OUTER APPLY\"),\n        CROSS_APPLY(\"CROSS APPLY\");\n\n        public final String name;\n        public final String nameLCase;\n\n        JoinType(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n\n        public static String toString(JoinType joinType) {\n            return joinType.name;\n        }\n    }\n\n    public void cloneTo(SQLJoinTableSource x) {\n        x.alias = alias;\n\n        if (left != null) {\n            x.setLeft(left.clone());\n        }\n\n        x.joinType = joinType;\n\n        if (right != null) {\n            x.setRight(right.clone());\n        }\n\n        if (condition != null) {\n            x.setCondition(condition.clone());\n        }\n\n        for (SQLExpr item : using) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(x);\n            x.using.add(item2);\n        }\n\n        x.natural = natural;\n        x.asof = asof;\n\n        if (udj != null) {\n            x.udj = udj.clone();\n        }\n    }\n\n    public SQLJoinTableSource clone() {\n        SQLJoinTableSource x = new SQLJoinTableSource();\n        cloneTo(x);\n        return x;\n    }\n\n    public void reverse() {\n        SQLTableSource temp = left;\n        left = right;\n        right = temp;\n\n        if (left instanceof SQLJoinTableSource) {\n            ((SQLJoinTableSource) left).reverse();\n        }\n\n        if (right instanceof SQLJoinTableSource) {\n            ((SQLJoinTableSource) right).reverse();\n        }\n\n    }\n\n    /**\n     * a inner_join (b inner_join c) -&lt; a inner_join b innre_join c\n     */\n    public void rearrangement() {\n        if (joinType != JoinType.COMMA && joinType != JoinType.INNER_JOIN) {\n            return;\n        }\n        if (right instanceof SQLJoinTableSource) {\n            SQLJoinTableSource rightJoin = (SQLJoinTableSource) right;\n\n            if (rightJoin.joinType != JoinType.COMMA && rightJoin.joinType != JoinType.INNER_JOIN) {\n                return;\n            }\n\n            SQLTableSource a = left;\n            SQLTableSource b = rightJoin.getLeft();\n            SQLTableSource c = rightJoin.getRight();\n            SQLExpr on_ab = condition;\n            SQLExpr on_bc = rightJoin.condition;\n\n            setLeft(rightJoin);\n            rightJoin.setLeft(a);\n            rightJoin.setRight(b);\n\n            boolean on_ab_match = false;\n            if (on_ab instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr on_ab_binaryOpExpr = (SQLBinaryOpExpr) on_ab;\n                if (on_ab_binaryOpExpr.getLeft() instanceof SQLPropertyExpr\n                        && on_ab_binaryOpExpr.getRight() instanceof SQLPropertyExpr) {\n                    String leftOwnerName = ((SQLPropertyExpr) on_ab_binaryOpExpr.getLeft()).getOwnernName();\n                    String rightOwnerName = ((SQLPropertyExpr) on_ab_binaryOpExpr.getRight()).getOwnernName();\n\n                    if (rightJoin.containsAlias(leftOwnerName) && rightJoin.containsAlias(rightOwnerName)) {\n                        on_ab_match = true;\n                    }\n                }\n            }\n\n            if (on_ab_match) {\n                rightJoin.setCondition(on_ab);\n            } else {\n                rightJoin.setCondition(null);\n                on_bc = SQLBinaryOpExpr.and(on_bc, on_ab);\n            }\n\n            setRight(c);\n            setCondition(on_bc);\n        }\n    }\n\n    public boolean contains(SQLTableSource tableSource, SQLExpr condition) {\n        if (right.equals(tableSource)) {\n            if (this.condition == condition) {\n                return true;\n            }\n\n            return this.condition != null && this.condition.equals(condition);\n        }\n\n        if (left instanceof SQLJoinTableSource) {\n            SQLJoinTableSource joinLeft = (SQLJoinTableSource) left;\n\n            if (tableSource instanceof SQLJoinTableSource) {\n                SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n\n                if (join.right.equals(right) && this.condition.equals(condition) && joinLeft.right.equals(join.left)) {\n                    return true;\n                }\n            }\n\n            return joinLeft.contains(tableSource, condition);\n        }\n\n        return false;\n    }\n\n    public boolean contains(SQLTableSource tableSource, SQLExpr condition, JoinType joinType) {\n        if (right.equals(tableSource)) {\n            if (this.condition == condition) {\n                return true;\n            }\n\n            return this.condition != null && this.condition.equals(condition) && this.joinType == joinType;\n        }\n\n        if (left instanceof SQLJoinTableSource) {\n            SQLJoinTableSource joinLeft = (SQLJoinTableSource) left;\n\n            if (tableSource instanceof SQLJoinTableSource) {\n                SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n\n                if (join.right.equals(right)\n                        && this.condition != null && this.condition.equals(join.condition)\n                        && joinLeft.right.equals(join.left)\n                        && this.joinType == join.joinType\n                        && joinLeft.condition != null && joinLeft.condition.equals(condition)\n                        && joinLeft.joinType == joinType) {\n                    return true;\n                }\n            }\n\n            return joinLeft.contains(tableSource, condition, joinType);\n        }\n\n        return false;\n    }\n\n    public SQLJoinTableSource findJoin(SQLTableSource tableSource, JoinType joinType) {\n        if (right.equals(tableSource)) {\n            if (this.joinType == joinType) {\n                return this;\n            }\n            return null;\n        }\n\n        if (left instanceof SQLJoinTableSource) {\n            return ((SQLJoinTableSource) left).findJoin(tableSource, joinType);\n        }\n\n        return null;\n    }\n\n    public boolean containsAlias(String alias) {\n        if (SQLUtils.nameEquals(this.alias, alias)) {\n            return true;\n        }\n\n        if (left != null && left.containsAlias(alias)) {\n            return true;\n        }\n\n        if (right != null && right.containsAlias(alias)) {\n            return true;\n        }\n\n        return false;\n    }\n\n    public SQLColumnDefinition findColumn(String columnName) {\n        long hash = FnvHash.hashCode64(columnName);\n        return findColumn(hash);\n    }\n\n    public SQLColumnDefinition findColumn(long columnNameHash) {\n        SQLObject column = resolveColum(columnNameHash);\n        if (column instanceof SQLColumnDefinition) {\n            return (SQLColumnDefinition) column;\n        }\n\n        return null;\n    }\n\n    public SQLObject resolveColumn(long columnNameHash) {\n        if (left != null) {\n            SQLObject column = left.resolveColum(columnNameHash);\n            if (column != null) {\n                return column;\n            }\n        }\n\n        if (right != null) {\n            return right.resolveColum(columnNameHash);\n        }\n\n        return null;\n    }\n\n    @Override\n    public SQLTableSource findTableSourceWithColumn(String columnName) {\n        long hash = FnvHash.hashCode64(columnName);\n        return findTableSourceWithColumn(hash, columnName, 0);\n    }\n\n    public SQLJoinTableSource findTableSourceWithColumn(SQLName a, SQLName b) {\n        if (left.findTableSourceWithColumn(a) != null\n                && right.findTableSourceWithColumn(b) != null) {\n            return this;\n        }\n\n        if (right.findTableSourceWithColumn(a) != null\n                && left.findTableSourceWithColumn(b) != null) {\n            return this;\n        }\n\n        if (left instanceof SQLJoinTableSource) {\n            return ((SQLJoinTableSource) left).findTableSourceWithColumn(a, b);\n        }\n\n        if (right instanceof SQLJoinTableSource) {\n            return ((SQLJoinTableSource) right).findTableSourceWithColumn(a, b);\n        }\n\n        return null;\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnNameHash, String name, int option) {\n        SQLTableSource leftMatch = null;\n        if (left != null) {\n            leftMatch = left.findTableSourceWithColumn(columnNameHash, name, option);\n        }\n\n        boolean checkColumnAmbiguous = (option & SchemaResolveVisitor.Option.CheckColumnAmbiguous.mask) != 0;\n        if (leftMatch != null && !checkColumnAmbiguous) {\n            return leftMatch;\n        }\n\n        SQLTableSource rightMatch = null;\n        if (right != null) {\n            rightMatch = right.findTableSourceWithColumn(columnNameHash, name, option);\n        }\n\n        if (leftMatch == null) {\n            return rightMatch;\n        }\n\n        if (rightMatch == null) {\n            return leftMatch;\n        }\n\n        if (name != null) {\n            String msg = \"Column '\" + name + \"' is ambiguous\";\n            throw new FastsqlColumnAmbiguousException(msg);\n        }\n        throw new FastsqlColumnAmbiguousException();\n    }\n\n    public boolean match(String alias_a, String alias_b) {\n        if (left == null || right == null) {\n            return false;\n        }\n\n        if (left.containsAlias(alias_a)\n                && right.containsAlias(alias_b)) {\n            return true;\n        }\n\n        return right.containsAlias(alias_a)\n                && left.containsAlias(alias_b);\n    }\n\n    public boolean conditionContainsTable(String alias) {\n        if (condition == null) {\n            return false;\n        }\n\n        if (condition instanceof SQLBinaryOpExpr) {\n            return ((SQLBinaryOpExpr) condition).conditionContainsTable(alias);\n        }\n\n        return false;\n    }\n\n    public SQLJoinTableSource join(SQLTableSource right, JoinType joinType, SQLExpr condition) {\n        SQLJoinTableSource joined = new SQLJoinTableSource(this, joinType, right, condition);\n        return joined;\n    }\n\n    public SQLTableSource findTableSource(long alias_hash) {\n        if (alias_hash == 0) {\n            return null;\n        }\n\n        if (aliasHashCode64() == alias_hash) {\n            return this;\n        }\n\n        SQLTableSource result = left.findTableSource(alias_hash);\n        if (result != null) {\n            return result;\n        }\n\n        return right.findTableSource(alias_hash);\n    }\n\n    public SQLTableSource other(SQLTableSource x) {\n        if (left == x) {\n            return right;\n        }\n\n        if (right == x) {\n            return left;\n        }\n\n        return null;\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = left != null ? left.hashCode() : 0;\n        result = 31 * result + (joinType != null ? joinType.hashCode() : 0);\n        result = 31 * result + (right != null ? right.hashCode() : 0);\n        result = 31 * result + (condition != null ? condition.hashCode() : 0);\n        result = 31 * result + using.hashCode();\n        result = 31 * result + (natural ? 1 : 0);\n        result = 31 * result + (global ? 1 : 0);\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        SQLJoinTableSource that = (SQLJoinTableSource) o;\n\n        if (natural != that.natural) {\n            return false;\n        }\n        if (asof != that.asof) {\n            return false;\n        }\n        if (global != that.global) {\n            return false;\n        }\n        if (left != null ? !left.equals(that.left) : that.left != null) {\n            return false;\n        }\n        if (joinType != that.joinType) {\n            return false;\n        }\n        if (right != null ? !right.equals(that.right) : that.right != null) {\n            return false;\n        }\n        if (condition != null ? !condition.equals(that.condition) : that.condition != null) {\n            return false;\n        }\n        if (using != null ? !using.equals(that.using) : that.using != null) {\n            return false;\n        }\n        return udj != null ? udj.equals(that.udj) : that.udj == null;\n    }\n\n    public void splitTo(List<SQLTableSource> outTableSources, JoinType joinType) {\n        if (joinType == this.joinType) {\n            if (left instanceof SQLJoinTableSource) {\n                ((SQLJoinTableSource) left).splitTo(outTableSources, joinType);\n            } else {\n                outTableSources.add(left);\n            }\n\n            if (right instanceof SQLJoinTableSource) {\n                ((SQLJoinTableSource) right).splitTo(outTableSources, joinType);\n            } else {\n                outTableSources.add(right);\n            }\n        } else {\n            outTableSources.add(this);\n        }\n    }\n\n    public static class UDJ extends SQLObjectImpl {\n        protected SQLExpr function;\n        protected final List<SQLExpr> arguments = new ArrayList<SQLExpr>();\n        protected String alias;\n        protected final List<SQLName> columns = new ArrayList<SQLName>();\n        protected List<SQLSelectOrderByItem> sortBy = new ArrayList<SQLSelectOrderByItem>();\n        protected List<SQLAssignItem> properties = new ArrayList<SQLAssignItem>();\n\n        public UDJ() {\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor v) {\n            if (v.visit(this)) {\n                acceptChild(v, arguments);\n                acceptChild(v, columns);\n            }\n            v.endVisit(this);\n        }\n\n        public List<SQLSelectOrderByItem> getSortBy() {\n            return sortBy;\n        }\n\n        public UDJ(SQLExpr function) {\n            this.function = function;\n        }\n\n        public UDJ clone() {\n            UDJ x = new UDJ();\n            x.function = function.clone();\n            for (SQLExpr arg : arguments) {\n                SQLExpr t = arg.clone();\n                t.setParent(x);\n                x.arguments.add(t);\n            }\n            x.alias = alias;\n            for (SQLName column : columns) {\n                SQLName t = column.clone();\n                t.setParent(x);\n                x.columns.add(t);\n            }\n\n            for (SQLAssignItem property : properties) {\n                SQLAssignItem c = property.clone();\n                c.setParent(x);\n                x.properties.add(c);\n            }\n            return x;\n        }\n\n        public SQLExpr getFunction() {\n            return function;\n        }\n\n        public void setFunction(SQLExpr function) {\n            this.function = function;\n        }\n\n        public List<SQLExpr> getArguments() {\n            return arguments;\n        }\n\n        public List<SQLName> getColumns() {\n            return columns;\n        }\n\n        public String getAlias() {\n            return alias;\n        }\n\n        public void setAlias(String alias) {\n            this.alias = alias;\n        }\n\n        public List<SQLAssignItem> getProperties() {\n            return properties;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLateralViewTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLLateralViewTableSource extends SQLTableSourceImpl {\n    private SQLTableSource tableSource;\n    private boolean outer;\n\n    private SQLMethodInvokeExpr method;\n\n    private List<SQLName> columns = new ArrayList<SQLName>(2);\n\n    private SQLExpr on; // odps\n\n    public SQLLateralViewTableSource() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, method);\n            acceptChild(visitor, columns);\n            super.accept0(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public SQLMethodInvokeExpr getMethod() {\n        return method;\n    }\n\n    public void setMethod(SQLMethodInvokeExpr method) {\n        if (method != null) {\n            method.setParent(this);\n        }\n        this.method = method;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void setColumns(List<SQLName> columns) {\n        this.columns = columns;\n    }\n\n    public SQLTableSource findTableSource(long alias_hash) {\n        long hash = this.aliasHashCode64();\n        if (hash != 0 && hash == alias_hash) {\n            return this;\n        }\n\n        for (SQLName column : columns) {\n            if (column.nameHashCode64() == alias_hash) {\n                return this;\n            }\n        }\n\n        if (tableSource != null) {\n            return tableSource.findTableSource(alias_hash);\n        }\n\n        return null;\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnNameHash, String columnName, int option) {\n        for (SQLName column : columns) {\n            if (column.nameHashCode64() == columnNameHash) {\n                return this;\n            }\n        }\n\n        if (tableSource != null) {\n            return tableSource.findTableSourceWithColumn(columnNameHash, columnName, option);\n        }\n        return null;\n    }\n\n    @Override\n    public SQLLateralViewTableSource clone() {\n        SQLLateralViewTableSource x = new SQLLateralViewTableSource();\n\n        x.setAlias(this.alias);\n        x.outer = outer;\n\n        if (this.tableSource != null) {\n            x.setTableSource(this.tableSource.clone());\n        }\n\n        if (this.method != null) {\n            x.setMethod(this.method.clone());\n        }\n\n        for (SQLName column : this.columns) {\n            SQLName e2 = column.clone();\n            e2.setParent(x);\n            x.getColumns().add(e2);\n        }\n\n        if (this.flashback != null) {\n            x.setFlashback(this.flashback.clone());\n        }\n\n        if (this.hints != null) {\n            for (SQLHint e : this.hints) {\n                SQLHint e2 = e.clone();\n                e2.setParent(x);\n                x.getHints().add(e2);\n            }\n        }\n\n        return x;\n    }\n\n    public boolean isOuter() {\n        return outer;\n    }\n\n    public void setOuter(boolean outer) {\n        this.outer = outer;\n    }\n\n    public SQLExpr getOn() {\n        return on;\n    }\n\n    public void setOn(SQLExpr on) {\n        this.on = on;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLeaveStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLLeaveStatement extends SQLStatementImpl {\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLockTableStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\npublic interface SQLLockTableStatement extends SQLStatement {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLLoopStatement extends SQLStatementImpl {\n    private String labelName;\n\n    private final List<SQLStatement> statements = new ArrayList<SQLStatement>();\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statements);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLStatement> getStatements() {\n        return statements;\n    }\n\n    public String getLabelName() {\n        return labelName;\n    }\n\n    public void setLabelName(String labelName) {\n        this.labelName = labelName;\n    }\n\n    public void addStatement(SQLStatement stmt) {\n        if (stmt != null) {\n            stmt.setParent(this);\n        }\n        statements.add(stmt);\n    }\n\n    @Override\n    public List getChildren() {\n        return statements;\n    }\n\n    @Override\n    public SQLLoopStatement clone() {\n        SQLLoopStatement x = new SQLLoopStatement();\n\n        x.setLabelName(this.labelName);\n\n        x.setAfterSemi(this.afterSemi);\n\n        x.setDbType(this.dbType);\n\n        for (SQLStatement item : statements) {\n            SQLStatement item2 = item.clone();\n            item2.setParent(x);\n            x.statements.add(item2);\n        }\n\n        if (this.headHints != null) {\n            List<SQLCommentHint> headHintsClone = new ArrayList<SQLCommentHint>(this.headHints.size());\n            for (SQLCommentHint hint : headHints) {\n                SQLCommentHint h2 = hint.clone();\n                h2.setParent(x);\n                headHintsClone.add(h2);\n            }\n            x.setHeadHints(headHintsClone);\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLMergeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLMergeStatement extends SQLStatementImpl {\n    private final List<SQLHint> hints = new ArrayList<>();\n\n    private SQLTableSource into;\n    private SQLTableSource using;\n    private SQLExpr on;\n    private List<When> whens = new ArrayList<>();\n    private SQLErrorLoggingClause errorLoggingClause;\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, into);\n            acceptChild(visitor, using);\n            acceptChild(visitor, on);\n            acceptChild(visitor, whens);\n            acceptChild(visitor, errorLoggingClause);\n        }\n        visitor.endVisit(this);\n    }\n\n    public String getAlias() {\n        return into.getAlias();\n    }\n\n    public SQLTableSource getInto() {\n        return into;\n    }\n\n    public void setInto(SQLName into) {\n        this.setInto(new SQLExprTableSource(into));\n    }\n\n    public void setInto(SQLTableSource into) {\n        if (into != null) {\n            into.setParent(this);\n        }\n        this.into = into;\n    }\n\n    public SQLTableSource getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLTableSource using) {\n        if (using != null) {\n            using.setParent(this);\n        }\n        this.using = using;\n    }\n\n    public SQLExpr getOn() {\n        return on;\n    }\n\n    public void setOn(SQLExpr on) {\n        if (on != null) {\n            on.setParent(this);\n        }\n        this.on = on;\n    }\n\n    public void addWhen(When when) {\n        when.setParent(this);\n        this.whens.add(when);\n    }\n\n    public List<When> getWhens() {\n        return whens;\n    }\n\n    public SQLErrorLoggingClause getErrorLoggingClause() {\n        return errorLoggingClause;\n    }\n\n    public void setErrorLoggingClause(SQLErrorLoggingClause errorLoggingClause) {\n        this.errorLoggingClause = errorLoggingClause;\n    }\n\n    public List<SQLHint> getHints() {\n        return hints;\n    }\n\n    public static class WhenUpdate extends When {\n        private final List<SQLUpdateSetItem> items = new ArrayList<>();\n        public List<SQLUpdateSetItem> getItems() {\n            return items;\n        }\n\n        public WhenUpdate() {\n        }\n\n        public WhenUpdate(boolean not, SQLName by, SQLExpr where) {\n            super(not, by, where);\n        }\n\n        public void addItem(SQLUpdateSetItem item) {\n            if (item != null) {\n                item.setParent(this);\n            }\n            this.items.add(item);\n        }\n\n        public SQLUpdateSetItem findItemByColumn(SQLExpr column) {\n            if (column == null) {\n                return null;\n            }\n            for (SQLUpdateSetItem item : items) {\n                if (item.getColumn().equals(column)) {\n                    return item;\n                }\n            }\n            return null;\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor v) {\n            if (v.visit(this)) {\n                acceptChild(v, by);\n                acceptChild(v, items);\n                acceptChild(v, where);\n            }\n            v.endVisit(this);\n        }\n\n        protected void cloneTo(WhenUpdate x) {\n            super.cloneTo(x);\n            for (SQLUpdateSetItem item : items) {\n                x.addItem(item.clone());\n            }\n        }\n\n        public WhenUpdate cloneTo() {\n            WhenUpdate x = new WhenUpdate();\n            cloneTo(x);\n            return x;\n        }\n\n        @Override\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            boolean isSuccess = false;\n            if (expr instanceof SQLUpdateSetItem && target instanceof SQLUpdateSetItem) {\n                for (int i = 0; i < items.size(); i++) {\n                    if (items.get(i) == expr) {\n                        target.setParent(this);\n                        items.set(i, (SQLUpdateSetItem) target);\n                        isSuccess = true;\n                    }\n                }\n            }\n            return isSuccess || super.replace(expr, target);\n        }\n    }\n\n    public static class WhenInsert extends When {\n        private boolean insertRow;\n        private List<SQLExpr> columns = new ArrayList<SQLExpr>();\n        private List<SQLExpr> values = new ArrayList<SQLExpr>();\n\n        public WhenInsert() {\n        }\n\n        public WhenInsert(boolean not, SQLName by, SQLExpr where) {\n            super(not, by, where);\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor v) {\n            if (v.visit(this)) {\n                acceptChild(v, by);\n                acceptChild(v, where);\n                acceptChild(v, columns);\n                acceptChild(v, values);\n            }\n            v.endVisit(this);\n        }\n\n        public List<SQLExpr> getColumns() {\n            return columns;\n        }\n\n        public void addColumn(SQLExpr column) {\n            column.setParent(this);\n            columns.add(column);\n        }\n\n        public void addValue(SQLExpr value) {\n            value.setParent(this);\n            values.add(value);\n        }\n\n        public void setColumns(List<SQLExpr> columns) {\n            this.columns = columns;\n        }\n\n        public boolean isInsertRow() {\n            return insertRow;\n        }\n\n        public void setInsertRow(boolean insertRow) {\n            this.insertRow = insertRow;\n        }\n\n        public List<SQLExpr> getValues() {\n            return values;\n        }\n\n        public void setValues(List<SQLExpr> values) {\n            this.values = values;\n        }\n\n        protected void cloneTo(WhenInsert x) {\n            super.cloneTo(x);\n            for (SQLExpr column : columns) {\n                x.addColumn(column.clone());\n            }\n            for (SQLExpr value : values) {\n                x.addValue(value.clone());\n            }\n        }\n\n        public WhenInsert cloneTo() {\n            WhenInsert x = new WhenInsert();\n            cloneTo(x);\n            return x;\n        }\n\n        @Override\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            boolean isSuccess = false;\n            for (int i = 0; i < columns.size(); i++) {\n                if (columns.get(i) == expr) {\n                    target.setParent(this);\n                    columns.set(i, target);\n                    isSuccess = true;\n                }\n            }\n\n            for (int i = 0; i < values.size(); i++) {\n                if (values.get(i) == expr) {\n                    target.setParent(this);\n                    values.set(i, target);\n                    isSuccess = true;\n                }\n            }\n            return isSuccess || super.replace(expr, target);\n        }\n    }\n\n    public static class WhenDoNothing extends When {\n        public WhenDoNothing() {\n        }\n\n        public WhenDoNothing(boolean not, SQLName by, SQLExpr where) {\n            super(not, by, where);\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor v) {\n            if (v.visit(this)) {\n                acceptChild(v, by);\n                acceptChild(v, where);\n            }\n            v.endVisit(this);\n        }\n\n        public WhenDoNothing cloneTo() {\n            WhenDoNothing x = new WhenDoNothing();\n            cloneTo(x);\n            return x;\n        }\n    }\n\n    public static class WhenDelete extends When {\n        public WhenDelete() {\n        }\n\n        public WhenDelete(boolean not, SQLName by, SQLExpr where) {\n            super(not, by, where);\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor v) {\n            if (v.visit(this)) {\n                acceptChild(v, by);\n                acceptChild(v, where);\n            }\n            v.endVisit(this);\n        }\n\n        public WhenDelete cloneTo() {\n            WhenDelete x = new WhenDelete();\n            cloneTo(x);\n            return x;\n        }\n    }\n\n    public abstract static class When extends SQLObjectImpl implements SQLReplaceable {\n        protected boolean not;\n        protected SQLName by;\n        protected SQLExpr where;\n\n        public When() {\n        }\n\n        public When(boolean not, SQLName by, SQLExpr where) {\n            this.not = not;\n            if (by != null) {\n                by.setParent(this);\n            }\n            this.by = by;\n            if (where != null) {\n                where.setParent(this);\n            }\n            this.where = where;\n        }\n\n        protected void cloneTo(When x) {\n            x.not = this.not;\n            if (by != null) {\n                x.setBy(by.clone());\n            }\n            if (where != null) {\n                x.setWhere(where.clone());\n            }\n        }\n\n        public boolean isNot() {\n            return not;\n        }\n\n        public void setNot(boolean not) {\n            this.not = not;\n        }\n\n        public SQLName getBy() {\n            return by;\n        }\n\n        public void setBy(SQLName x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.by = x;\n        }\n\n        public SQLExpr getWhere() {\n            return where;\n        }\n\n        public void setWhere(SQLExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.where = x;\n        }\n\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            if (this.where == expr) {\n                target.setParent(this);\n                this.where = target;\n                return true;\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNotNullConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLNotNullConstraint extends SQLConstraintImpl implements SQLColumnConstraint {\n    public SQLNotNullConstraint() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLNotNullConstraint clone() {\n        SQLNotNullConstraint x = new SQLNotNullConstraint();\n        super.cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLNullConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLNullConstraint extends SQLConstraintImpl implements SQLColumnConstraint {\n    public SQLNullConstraint() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLNullConstraint clone() {\n        SQLNullConstraint x = new SQLNullConstraint();\n        super.cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLObjectType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\npublic enum SQLObjectType {\n    TABLE(\"TABLE\"),\n    FUNCTION(\"FUNCTION\"),\n    PROCEDURE(\"PROCEDURE\"),\n    USER(\"USER\"),\n    DATABASE(\"DATABASE\"),\n    SCHEMA(\"SCHEMA\"),\n    ROLE(\"ROLE\"),\n    PROJECT(\"PROJECT\"),\n    PACKAGE(\"PACKAGE\"),\n    RESOURCE(\"RESOURCE\"),\n    INSTANCE(\"INSTANCE\"),\n    JOB(\"JOB\"),\n    VOLUME(\"VOLUME\"),\n    OfflineModel(\"OFFLINEMODEL\"),\n    SYSTEM(\"SYSTEM\"),\n    GLOBAL(\"GLOBAL\"),\n    // for odps\n    XFLOW(\"XFLOW\");\n\n    public final String name;\n    public final String nameLCase;\n\n    SQLObjectType(String name) {\n        this.name = name;\n        this.nameLCase = name.toLowerCase();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLOpenStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class SQLOpenStatement extends SQLStatementImpl {\n    //cursor name\n    private SQLName cursorName;\n\n    private final List<SQLExpr> columns = new ArrayList<SQLExpr>();\n\n    private SQLExpr forExpr;\n\n    private final List<SQLExpr> using = new ArrayList<SQLExpr>();\n\n    public SQLOpenStatement() {\n    }\n\n    public SQLName getCursorName() {\n        return cursorName;\n    }\n\n    public void setCursorName(String cursorName) {\n        setCursorName(new SQLIdentifierExpr(cursorName));\n    }\n\n    public void setCursorName(SQLName cursorName) {\n        if (cursorName != null) {\n            cursorName.setParent(this);\n        }\n        this.cursorName = cursorName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, cursorName);\n            acceptChild(visitor, forExpr);\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getFor() {\n        return forExpr;\n    }\n\n    public void setFor(SQLExpr forExpr) {\n        if (forExpr != null) {\n            forExpr.setParent(this);\n        }\n        this.forExpr = forExpr;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public List<SQLExpr> getUsing() {\n        return using;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLOptimizeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLOptimizeStatement extends SQLStatementImpl {\n    protected final List<SQLExprTableSource> tableSources = new ArrayList<SQLExprTableSource>();\n    protected SQLName cluster;\n\n    boolean isFinal;\n    boolean deduplicate;\n    SQLExpr deduplicateBy;\n\n    public boolean isFinal() {\n        return isFinal;\n    }\n\n    public void setFinal(boolean isFinal) {\n        this.isFinal = isFinal;\n    }\n\n    public boolean isDeduplicate() {\n        return deduplicate;\n    }\n\n    public void setDeduplicate(boolean deduplicate) {\n        this.deduplicate = deduplicate;\n    }\n\n    public SQLExpr getDeduplicateBy() {\n        return deduplicateBy;\n    }\n\n    public void setDeduplicateBy(SQLExpr deduplicateBy) {\n        this.deduplicateBy = deduplicateBy;\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void addTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSources.add(tableSource);\n    }\n\n    public SQLName getCluster() {\n        return cluster;\n    }\n\n    public void setCluster(SQLName cluster) {\n        this.cluster = cluster;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSources);\n            acceptChild(visitor, cluster);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPartitionRef.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLPartitionRef extends SQLObjectImpl {\n    private List<Item> items = new ArrayList<Item>();\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, items);\n        }\n        v.endVisit(this);\n    }\n\n    public List<Item> getItems() {\n        return items;\n    }\n\n    public void addItem(Item item) {\n        item.setParent(this);\n        items.add(item);\n    }\n\n    public void addItem(SQLIdentifierExpr name, SQLExpr value) {\n        Item item = new Item();\n        item.setColumnName(name);\n        item.setValue(value);\n        item.setParent(this);\n        this.items.add(item);\n    }\n\n    public static class Item extends SQLObjectImpl {\n        private SQLIdentifierExpr columnName;\n        private SQLExpr value;\n        private SQLBinaryOperator operator;\n\n        public Item() {\n        }\n\n        public Item(SQLIdentifierExpr columnName) {\n            setColumnName(columnName);\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor v) {\n        }\n\n        public SQLIdentifierExpr getColumnName() {\n            return columnName;\n        }\n\n        public void setColumnName(SQLIdentifierExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.columnName = x;\n        }\n\n        public SQLExpr getValue() {\n            return value;\n        }\n\n        public void setValue(SQLExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.value = x;\n        }\n\n        public SQLBinaryOperator getOperator() {\n            return operator;\n        }\n\n        public void setOperator(SQLBinaryOperator operator) {\n            this.operator = operator;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrimaryKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\npublic interface SQLPrimaryKey extends SQLUniqueConstraint, SQLTableElement {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrimaryKeyImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPrimaryKeyImpl extends SQLUnique implements SQLPrimaryKey, SQLTableConstraint {\n    protected boolean disableNovalidate;\n    protected boolean clustered; // sql server\n    protected boolean notEnforced; // bigquery\n\n    public SQLPrimaryKeyImpl() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getColumns());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLPrimaryKeyImpl clone() {\n        SQLPrimaryKeyImpl x = new SQLPrimaryKeyImpl();\n        cloneTo(x);\n        return x;\n    }\n\n    public void cloneTo(SQLPrimaryKeyImpl x) {\n        super.cloneTo(x);\n        x.disableNovalidate = disableNovalidate;\n        x.clustered = clustered;\n    }\n\n    public boolean isDisableNovalidate() {\n        return disableNovalidate;\n    }\n\n    public void setDisableNovalidate(boolean disableNovalidate) {\n        this.disableNovalidate = disableNovalidate;\n    }\n\n    public boolean isClustered() {\n        return clustered;\n    }\n\n    public void setClustered(boolean clustered) {\n        this.clustered = clustered;\n    }\n\n    public boolean isNotEnforced() {\n        return notEnforced;\n    }\n\n    public void setNotEnforced(boolean notEnforced) {\n        this.notEnforced = notEnforced;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrivilegeItem.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLPrivilegeItem extends SQLObjectImpl {\n    private SQLExpr action;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n\n    public SQLExpr getAction() {\n        return action;\n    }\n\n    public void setAction(SQLExpr action) {\n        this.action = action;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, action);\n            acceptChild(v, this.columns);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrivilegeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class SQLPrivilegeStatement extends SQLStatementImpl {\n    protected final List<SQLPrivilegeItem> privileges = new ArrayList<SQLPrivilegeItem>();\n    protected List<SQLExpr> users = new ArrayList<SQLExpr>();\n    protected SQLObject resource;\n\n    // mysql\n    protected SQLObjectType resourceType;\n\n    public SQLPrivilegeStatement() {\n    }\n\n    public SQLPrivilegeStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public List<SQLExpr> getUsers() {\n        return users;\n    }\n\n    public void addUser(SQLExpr user) {\n        if (user == null) {\n            return;\n        }\n        user.setParent(this);\n        this.users.add(user);\n    }\n\n    public void setUsers(List<SQLExpr> users) {\n        this.users = users;\n    }\n\n    public SQLObject getResource() {\n        return resource;\n    }\n\n    public void setResource(SQLObject x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.resource = x;\n    }\n\n    public void setResource(SQLExpr resource) {\n        if (resource != null) {\n            resource.setParent(this);\n        }\n        this.resource = resource;\n    }\n\n    public List<SQLPrivilegeItem> getPrivileges() {\n        return privileges;\n    }\n\n    public SQLObjectType getResourceType() {\n        return resourceType;\n    }\n\n    public void setResourceType(SQLObjectType x) {\n        this.resourceType = x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPurgeLogsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPurgeLogsStatement extends SQLStatementImpl implements SQLDropStatement {\n    private boolean binary;\n    private boolean master;\n    private boolean all;\n\n    private SQLExpr to;\n    private SQLExpr before;\n\n    public SQLPurgeLogsStatement() {\n    }\n\n    public SQLPurgeLogsStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, to);\n            acceptChild(visitor, before);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getTo() {\n        return to;\n    }\n\n    public void setTo(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n\n    public SQLExpr getBefore() {\n        return before;\n    }\n\n    public void setBefore(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.before = x;\n    }\n\n    public boolean isBinary() {\n        return binary;\n    }\n\n    public void setBinary(boolean binary) {\n        this.binary = binary;\n    }\n\n    public boolean isMaster() {\n        return master;\n    }\n\n    public void setMaster(boolean master) {\n        this.master = master;\n    }\n\n    public boolean isAll() {\n        return all;\n    }\n\n    public void setAll(boolean all) {\n        this.all = all;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPurgeRecyclebinStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPurgeRecyclebinStatement extends SQLStatementImpl implements SQLDropStatement {\n    public SQLPurgeRecyclebinStatement() {\n    }\n\n    public SQLPurgeRecyclebinStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPurgeTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPurgeTableStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLExprTableSource table;\n    private boolean all;\n    private int count;\n\n    public SQLPurgeTableStatement() {\n    }\n\n    public SQLPurgeTableStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, table);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName x) {\n        if (x == null) {\n            this.table = null;\n            return;\n        }\n\n        setTable(new SQLExprTableSource(x));\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public int getCount() {\n        return count;\n    }\n\n    public void setCount(int count) {\n        this.count = count;\n    }\n\n    public boolean isAll() {\n        return all;\n    }\n\n    public void setAll(boolean all) {\n        this.all = all;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPurgeTemporaryOutputStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLPurgeTemporaryOutputStatement extends SQLStatementImpl implements SQLDropStatement {\n    private SQLName name;\n\n    public SQLPurgeTemporaryOutputStatement() {\n    }\n\n    public SQLPurgeTemporaryOutputStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRaiseStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLRaiseStatement extends SQLStatementImpl {\n    private SQLExpr message;\n\n    public SQLExpr getMessage() {\n        return message;\n    }\n\n    public void setMessage(SQLExpr message) {\n        this.message = message;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, message);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        if (message != null) {\n            return Collections.<SQLObject>singletonList(message);\n        }\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRefreshMaterializedViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLRefreshMaterializedViewStatement extends SQLStatementImpl {\n    private SQLExpr name;\n\n    private boolean concurrently;\n\n    private boolean withNoData;\n\n    private boolean withData;\n\n    public SQLRefreshMaterializedViewStatement() {\n        this.setConcurrently(false);\n        this.setWithData(false);\n        this.setWithNoData(false);\n    }\n\n    public SQLRefreshMaterializedViewStatement(DbType dbType) {\n        super(dbType);\n        this.setConcurrently(false);\n        this.setWithData(false);\n        this.setWithNoData(false);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public boolean isConcurrently() {\n        return concurrently;\n    }\n\n    public void setConcurrently(boolean concurrently) {\n        this.concurrently = concurrently;\n    }\n\n    public boolean isWithNoData() {\n        return withNoData;\n    }\n\n    public void setWithNoData(boolean withNoData) {\n        this.withNoData = withNoData;\n    }\n\n    public void setWithData(boolean withData) {\n        this.withData = withData;\n    }\n\n    public boolean isWithData() {\n        return withData;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRefreshTableStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLRefreshTableStatement extends SQLStatementImpl {\n    private SQLExpr name;\n    private List<SQLAssignItem> partitions;\n    public SQLRefreshTableStatement() {\n        partitions = new ArrayList<>();\n    }\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, partitions);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public void setPartitions(List<SQLAssignItem> partitions) {\n        this.partitions = partitions;\n    }\n\n    public void addPartition(SQLAssignItem partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReleaseSavePointStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLReleaseSavePointStatement extends SQLStatementImpl {\n    private SQLExpr name;\n\n    public SQLReleaseSavePointStatement() {\n    }\n\n    public SQLReleaseSavePointStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        this.name = name;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRenameUserStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLRenameUserStatement extends SQLStatementImpl {\n    private SQLName name;\n    private SQLName to;\n\n    public SQLRenameUserStatement() {\n        dbType = DbType.mysql;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n            acceptChild(v, to);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName to) {\n        this.to = to;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReplaceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLReplaceStatement extends SQLStatementImpl {\n    protected boolean lowPriority;\n    protected boolean delayed;\n\n    protected SQLExprTableSource tableSource;\n    protected final List<SQLExpr> columns = new ArrayList<SQLExpr>();\n    protected List<SQLInsertStatement.ValuesClause> valuesList = new ArrayList<SQLInsertStatement.ValuesClause>();\n    protected SQLQueryExpr query;\n\n    protected List<SQLCommentHint> hints;\n    protected List<SQLAssignItem> partitions;\n\n    public SQLName getTableName() {\n        if (tableSource == null) {\n            return null;\n        }\n\n        return (SQLName) tableSource.getExpr();\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.setTableSource(new SQLExprTableSource(tableName));\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLExpr column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public boolean isLowPriority() {\n        return lowPriority;\n    }\n\n    public void setLowPriority(boolean lowPriority) {\n        this.lowPriority = lowPriority;\n    }\n\n    public boolean isDelayed() {\n        return delayed;\n    }\n\n    public void setDelayed(boolean delayed) {\n        this.delayed = delayed;\n    }\n\n    public SQLQueryExpr getQuery() {\n        return query;\n    }\n\n    public void setQuery(SQLQueryExpr query) {\n        if (query != null) {\n            query.setParent(this);\n        }\n        this.query = query;\n    }\n\n    public List<SQLInsertStatement.ValuesClause> getValuesList() {\n        return valuesList;\n    }\n\n    @Override\n    public SQLStatement clone() {\n        SQLReplaceStatement x = new SQLReplaceStatement();\n        x.setDbType(this.dbType);\n\n        if (headHints != null) {\n            for (SQLCommentHint h : headHints) {\n                SQLCommentHint clone = h.clone();\n                clone.setParent(x);\n                x.headHints.add(clone);\n            }\n        }\n\n        if (hints != null && !hints.isEmpty()) {\n            for (SQLCommentHint h : hints) {\n                SQLCommentHint clone = h.clone();\n                clone.setParent(x);\n                x.getHints().add(clone);\n            }\n        }\n\n        x.lowPriority = this.lowPriority;\n        x.delayed = this.delayed;\n\n        if (this.tableSource != null) {\n            x.tableSource = this.tableSource.clone();\n        }\n\n        for (SQLInsertStatement.ValuesClause clause : valuesList) {\n            x.getValuesList().add(clause.clone());\n        }\n\n        for (SQLExpr column : columns) {\n            x.addColumn(column.clone());\n        }\n\n        if (query != null) {\n            x.query = this.query.clone();\n        }\n\n        if (partitions != null) {\n            for (SQLAssignItem partition : partitions) {\n                x.addPartition(partition.clone());\n            }\n        }\n\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, columns);\n            acceptChild(visitor, valuesList);\n            acceptChild(visitor, query);\n        }\n        visitor.endVisit(this);\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n\n        return hints.size();\n    }\n\n    public List<SQLCommentHint> getHints() {\n        if (hints == null) {\n            hints = new ArrayList<SQLCommentHint>(2);\n        }\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public void addPartition(SQLAssignItem partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n\n        if (partitions == null) {\n            partitions = new ArrayList<SQLAssignItem>();\n        }\n\n        this.partitions.add(partition);\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRestoreStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLRestoreStatement extends SQLStatementImpl {\n    private SQLName type;\n    private List<SQLCharExpr> properties = new ArrayList<SQLCharExpr>();\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.type);\n\n            acceptChild(visitor, properties);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getType() {\n        return type;\n    }\n\n    public void setType(SQLName type) {\n        this.type = type;\n    }\n\n    public List<SQLCharExpr> getProperties() {\n        return properties;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLReturnStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLReturnStatement extends SQLStatementImpl implements SQLReplaceable {\n    private SQLExpr expr;\n\n    public SQLReturnStatement() {\n    }\n\n    public SQLReturnStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLReturnStatement clone() {\n        SQLReturnStatement x = new SQLReturnStatement();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        return x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.expr);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRevokeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLRevokeStatement extends SQLPrivilegeStatement {\n    private boolean grantOption;\n\n    public SQLRevokeStatement() {\n    }\n\n    public SQLRevokeStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, resource);\n            acceptChild(visitor, users);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isGrantOption() {\n        return grantOption;\n    }\n\n    public void setGrantOption(boolean grantOption) {\n        this.grantOption = grantOption;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRollbackStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLRollbackStatement extends SQLStatementImpl {\n    private SQLName to;\n\n    // for mysql\n    private Boolean chain;\n    private Boolean release;\n    private SQLExpr force;\n\n    public SQLRollbackStatement() {\n    }\n\n    public SQLRollbackStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, to);\n\n            acceptChild(visitor, force);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (to != null) {\n            children.add(to);\n        }\n        if (force != null) {\n            children.add(force);\n        }\n        return children;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName to) {\n        this.to = to;\n    }\n\n    public Boolean getChain() {\n        return chain;\n    }\n\n    public void setChain(Boolean chain) {\n        this.chain = chain;\n    }\n\n    public Boolean getRelease() {\n        return release;\n    }\n\n    public void setRelease(Boolean release) {\n        this.release = release;\n    }\n\n    public SQLExpr getForce() {\n        return force;\n    }\n\n    public void setForce(SQLExpr force) {\n        this.force = force;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLRollbackTransactionStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLRollbackTransactionStatement extends SQLStatementImpl {\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSavePointStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLSavePointStatement extends SQLStatementImpl {\n    private SQLExpr name;\n\n    public SQLSavePointStatement() {\n    }\n\n    public SQLSavePointStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        this.name = name;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLScriptCommitStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLScriptCommitStatement extends SQLStatementImpl {\n    public SQLScriptCommitStatement() {\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelect.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLSelect extends SQLObjectImpl implements SQLDbTypedObject {\n    protected SQLWithSubqueryClause withSubQuery;\n    protected SQLSelectQuery query;\n    protected SQLOrderBy orderBy;\n    protected SQLLimit limit;\n\n    protected List<SQLHint> hints;\n\n    protected SQLObject restriction;\n\n    protected boolean forBrowse;\n    protected List<String> forXmlOptions;\n    protected SQLExpr xmlPath;\n\n    protected SQLExpr rowCount;\n    protected SQLExpr offset;\n\n    private SQLHint headHint;\n\n    public SQLSelect() {\n    }\n\n    public List<SQLHint> getHints() {\n        if (hints == null) {\n            hints = new ArrayList<SQLHint>(2);\n        }\n        return hints;\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n        return hints.size();\n    }\n\n    public SQLSelect(SQLSelectQuery query) {\n        this.setQuery(query);\n    }\n\n    public SQLWithSubqueryClause getWithSubQuery() {\n        return withSubQuery;\n    }\n\n    public SQLWithSubqueryClause.Entry findWithSubQueryEntry(String alias) {\n        return withSubQuery == null ? null : withSubQuery.findEntry(alias);\n    }\n\n    public SQLDataType findSelectItemAndComputeDataType(String ident) {\n        if (ident == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(ident);\n        return findSelectItemAndComputeDataType(hash);\n    }\n\n    public SQLDataType findSelectItemAndComputeDataType(long identHash) {\n        SQLSelectQueryBlock queryBlock = getFirstQueryBlock();\n        return queryBlock != null ? queryBlock.findSelectItemAndComputeDataType(identHash) : null;\n    }\n\n    public void setWithSubQuery(SQLWithSubqueryClause x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.withSubQuery = x;\n    }\n\n    public SQLSelectQuery getQuery() {\n        return this.query;\n    }\n\n    public void setQuery(SQLSelectQuery query) {\n        if (query != null) {\n            query.setParent(this);\n        }\n        this.query = query;\n    }\n\n    public SQLSelectQueryBlock getQueryBlock() {\n        if (query instanceof SQLSelectQueryBlock) {\n            return (SQLSelectQueryBlock) query;\n        }\n\n        return null;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return this.orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        if (orderBy != null) {\n            orderBy.setParent(this);\n        }\n        this.orderBy = orderBy;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            if (withSubQuery != null) {\n                withSubQuery.accept0(v);\n            }\n\n            if (this.query != null) {\n                this.query.accept(v);\n            }\n\n            if (this.restriction != null) {\n                this.restriction.accept(v);\n            }\n\n            if (this.orderBy != null) {\n                this.orderBy.accept(v);\n            }\n\n            if (this.hints != null) {\n                for (SQLHint hint : hints) {\n                    hint.accept(v);\n                }\n            }\n\n            if (this.offset != null) {\n                this.offset.accept(v);\n            }\n\n            if (this.rowCount != null) {\n                this.rowCount.accept(v);\n            }\n\n            if (this.headHint != null) {\n                this.headHint.accept(v);\n            }\n        }\n\n        v.endVisit(this);\n    }\n\n    public DbType getDbType() {\n        DbType dbType = null;\n\n        SQLObject parent = this.getParent();\n        if (parent instanceof SQLStatement) {\n            dbType = ((SQLStatement) parent).getDbType();\n        }\n\n        if (dbType == null && parent instanceof OracleSQLObject) {\n            dbType = DbType.oracle;\n        }\n\n        if (dbType == null && query instanceof SQLSelectQueryBlock) {\n            dbType = ((SQLSelectQueryBlock) query).dbType;\n        }\n\n        return dbType;\n    }\n\n    public SQLSelect clone() {\n        SQLSelect x = new SQLSelect();\n\n        if (withSubQuery != null) {\n            x.withSubQuery = withSubQuery.clone();\n        }\n\n        if (query != null) {\n            x.setQuery(query.clone());\n        }\n\n        if (orderBy != null) {\n            x.setOrderBy(this.orderBy.clone());\n        }\n        if (restriction != null) {\n            x.setRestriction(restriction.clone());\n        }\n\n        if (this.hints != null) {\n            for (SQLHint hint : this.hints) {\n                x.getHints().add(hint);\n            }\n        }\n\n        x.forBrowse = forBrowse;\n\n        if (forXmlOptions != null) {\n            x.forXmlOptions = new ArrayList<String>(forXmlOptions);\n        }\n\n        if (xmlPath != null) {\n            x.setXmlPath(xmlPath.clone());\n        }\n\n        if (rowCount != null) {\n            x.setRowCount(rowCount.clone());\n        }\n\n        if (offset != null) {\n            x.setOffset(offset.clone());\n        }\n\n        if (headHint != null) {\n            x.setHeadHint(headHint.clone());\n        }\n\n        return x;\n    }\n\n    public boolean isSimple() {\n        return withSubQuery == null\n                && (hints == null || hints.isEmpty())\n                && restriction == null\n                && (!forBrowse)\n                && (forXmlOptions == null || forXmlOptions.isEmpty())\n                && xmlPath == null\n                && rowCount == null\n                && offset == null;\n    }\n\n    public SQLObject getRestriction() {\n        return this.restriction;\n    }\n\n    public void setRestriction(SQLObject restriction) {\n        if (restriction != null) {\n            restriction.setParent(this);\n        }\n        this.restriction = restriction;\n    }\n\n    public boolean isForBrowse() {\n        return forBrowse;\n    }\n\n    public void setForBrowse(boolean forBrowse) {\n        this.forBrowse = forBrowse;\n    }\n\n    public List<String> getForXmlOptions() {\n        if (forXmlOptions == null) {\n            forXmlOptions = new ArrayList<String>(4);\n        }\n\n        return forXmlOptions;\n    }\n\n    public int getForXmlOptionsSize() {\n        if (forXmlOptions == null) {\n            return 0;\n        }\n        return forXmlOptions.size();\n    }\n\n    public SQLExpr getRowCount() {\n        return rowCount;\n    }\n\n    public void setRowCount(SQLExpr rowCount) {\n        if (rowCount != null) {\n            rowCount.setParent(this);\n        }\n\n        this.rowCount = rowCount;\n    }\n\n    public SQLHint getHeadHint() {\n        return headHint;\n    }\n\n    public void setHeadHint(SQLHint headHint) {\n        this.headHint = headHint;\n    }\n\n    public SQLExpr getOffset() {\n        return offset;\n    }\n\n    public void setOffset(SQLExpr offset) {\n        if (offset != null) {\n            offset.setParent(this);\n        }\n        this.offset = offset;\n    }\n\n    public SQLExpr getXmlPath() {\n        return xmlPath;\n    }\n\n    public void setXmlPath(SQLExpr xmlPath) {\n        if (xmlPath != null) {\n            xmlPath.setParent(this);\n        }\n        this.xmlPath = xmlPath;\n    }\n\n    public List<String> computeSelecteListAlias() {\n        SQLSelectQueryBlock firstQuery = getFirstQueryBlock();\n        if (firstQuery != null) {\n            return firstQuery.computeSelecteListAlias();\n        }\n\n        return Collections.emptyList();\n    }\n\n    public SQLSelectQueryBlock getFirstQueryBlock() {\n        if (query instanceof SQLSelectQueryBlock) {\n            return (SQLSelectQueryBlock) query;\n        }\n\n        if (query instanceof SQLUnionQuery) {\n            SQLUnionQuery union = (SQLUnionQuery) query;\n            while (union.getLeft() instanceof SQLUnionQuery) {\n                union = (SQLUnionQuery) union.getLeft();\n            }\n            return union.getFirstQueryBlock();\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLSelect sqlSelect = (SQLSelect) o;\n\n        if (forBrowse != sqlSelect.forBrowse) {\n            return false;\n        }\n        if (withSubQuery != null ? !withSubQuery.equals(sqlSelect.withSubQuery) : sqlSelect.withSubQuery != null) {\n            return false;\n        }\n        if (query != null ? !query.equals(sqlSelect.query) : sqlSelect.query != null) {\n            return false;\n        }\n        if (orderBy != null ? !orderBy.equals(sqlSelect.orderBy) : sqlSelect.orderBy != null) {\n            return false;\n        }\n        if (limit != null ? !limit.equals(sqlSelect.limit) : sqlSelect.limit != null) {\n            return false;\n        }\n        if (hints != null ? !hints.equals(sqlSelect.hints) : sqlSelect.hints != null) {\n            return false;\n        }\n        if (restriction != null ? !restriction.equals(sqlSelect.restriction) : sqlSelect.restriction != null) {\n            return false;\n        }\n        if (forXmlOptions != null ? !forXmlOptions.equals(sqlSelect.forXmlOptions) : sqlSelect.forXmlOptions != null) {\n            return false;\n        }\n        if (xmlPath != null ? !xmlPath.equals(sqlSelect.xmlPath) : sqlSelect.xmlPath != null) {\n            return false;\n        }\n        if (rowCount != null ? !rowCount.equals(sqlSelect.rowCount) : sqlSelect.rowCount != null) {\n            return false;\n        }\n        if (offset != null ? !offset.equals(sqlSelect.offset) : sqlSelect.offset != null) {\n            return false;\n        }\n        return headHint != null ? headHint.equals(sqlSelect.headHint) : sqlSelect.headHint == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = withSubQuery != null ? withSubQuery.hashCode() : 0;\n        result = 31 * result + (query != null ? query.hashCode() : 0);\n        result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);\n        result = 31 * result + (limit != null ? limit.hashCode() : 0);\n        result = 31 * result + (hints != null ? hints.hashCode() : 0);\n        result = 31 * result + (restriction != null ? restriction.hashCode() : 0);\n        result = 31 * result + (forBrowse ? 1 : 0);\n        result = 31 * result + (forXmlOptions != null ? forXmlOptions.hashCode() : 0);\n        result = 31 * result + (xmlPath != null ? xmlPath.hashCode() : 0);\n        result = 31 * result + (rowCount != null ? rowCount.hashCode() : 0);\n        result = 31 * result + (offset != null ? offset.hashCode() : 0);\n        result = 31 * result + (headHint != null ? headHint.hashCode() : 0);\n        return result;\n    }\n\n    public boolean addWhere(SQLExpr where) {\n        if (where == null) {\n            return false;\n        }\n\n        if (query instanceof SQLSelectQueryBlock) {\n            ((SQLSelectQueryBlock) query).addWhere(where);\n            return true;\n        }\n\n        if (query instanceof SQLUnionQuery) {\n            SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock(getDbType());\n            queryBlock.setFrom(new SQLSelect(query), \"u\");\n            queryBlock.addSelectItem(new SQLAllColumnExpr());\n            queryBlock.setParent(queryBlock);\n            query = queryBlock;\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean replace(SQLSelectQuery cmp, SQLSelectQuery target) {\n        if (cmp == query) {\n            setQuery(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.limit = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectGroupByClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLSelectGroupByClause extends SQLObjectImpl implements SQLReplaceable {\n    private final List<SQLExpr> items = new ArrayList<SQLExpr>();\n    private SQLExpr having;\n    private boolean withRollUp;\n    private boolean withCube;\n\n    private boolean distinct;\n    private boolean paren;\n\n    public SQLSelectGroupByClause() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < this.items.size(); i++) {\n                SQLExpr item = items.get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n\n            if (having != null) {\n                having.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public boolean isDistinct() {\n        return distinct;\n    }\n\n    public void setDistinct(boolean distinct) {\n        this.distinct = distinct;\n    }\n\n    public boolean isWithRollUp() {\n        return withRollUp;\n    }\n\n    public void setWithRollUp(boolean withRollUp) {\n        this.withRollUp = withRollUp;\n    }\n\n    public boolean isWithCube() {\n        return withCube;\n    }\n\n    public void setWithCube(boolean withCube) {\n        this.withCube = withCube;\n    }\n\n    public SQLExpr getHaving() {\n        return this.having;\n    }\n\n    public void setHaving(SQLExpr having) {\n        if (having != null) {\n            having.setParent(this);\n        }\n\n        this.having = having;\n    }\n\n    public void addHaving(SQLExpr condition) {\n        if (condition == null) {\n            return;\n        }\n\n        if (having == null) {\n            having = condition;\n        } else {\n            having = SQLBinaryOpExpr.and(having, condition);\n        }\n    }\n\n    public List<SQLExpr> getItems() {\n        return this.items;\n    }\n\n    public void setItem(int index, SQLExpr expr) {\n        expr.setParent(this);\n        this.items.set(index, expr);\n    }\n\n    public boolean containsItem(SQLExpr item) {\n        return this.items.contains(item);\n    }\n\n    public void addItem(SQLExpr sqlExpr) {\n        if (sqlExpr != null) {\n            sqlExpr.setParent(this);\n            this.items.add(sqlExpr);\n        }\n    }\n\n    public void addItem(int index, SQLExpr sqlExpr) {\n        if (sqlExpr != null) {\n            sqlExpr.setParent(this);\n            this.items.add(index, sqlExpr);\n        }\n    }\n\n    public SQLSelectGroupByClause clone() {\n        SQLSelectGroupByClause x = new SQLSelectGroupByClause();\n        for (SQLExpr item : items) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n        if (having != null) {\n            x.setHaving(having.clone());\n        }\n        x.withRollUp = withRollUp;\n        x.withCube = withCube;\n        x.distinct = distinct;\n        x.paren = paren;\n        if (hint != null) {\n            x.setHint(hint.clone());\n        }\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == having) {\n            setHaving(target);\n            return true;\n        }\n\n        for (int i = items.size() - 1; i >= 0; i--) {\n            if (items.get(i) == expr) {\n                if (target instanceof SQLIntegerExpr) {\n                    items.remove(i);\n                } else {\n                    items.set(i, target);\n                }\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public SQLCommentHint getHint() {\n        return hint;\n    }\n\n    public void setHint(SQLCommentHint hint) {\n        this.hint = hint;\n    }\n\n    public boolean isParen() {\n        return paren;\n    }\n\n    public void setParen(boolean paren) {\n        this.paren = paren;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLSelectGroupByClause that = (SQLSelectGroupByClause) o;\n\n        if (withRollUp != that.withRollUp) {\n            return false;\n        }\n        if (withCube != that.withCube) {\n            return false;\n        }\n        if (distinct != that.distinct) {\n            return false;\n        }\n        if (paren != that.paren) {\n            return false;\n        }\n        if (items != null ? !items.equals(that.items) : that.items != null) {\n            return false;\n        }\n        if (having != null ? !having.equals(that.having) : that.having != null) {\n            return false;\n        }\n        return hint != null ? hint.equals(that.hint) : that.hint == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = items != null ? items.hashCode() : 0;\n        result = 31 * result + (having != null ? having.hashCode() : 0);\n        result = 31 * result + (withRollUp ? 1 : 0);\n        result = 31 * result + (withCube ? 1 : 0);\n        result = 31 * result + (distinct ? 1 : 0);\n        result = 31 * result + (paren ? 1 : 0);\n        result = 31 * result + (hint != null ? hint.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLSelectItem extends SQLAliasedExpr implements SQLReplaceable {\n    protected boolean connectByRoot;\n    protected transient long aliasHashCode64;\n    protected List<String> aliasList;\n\n    public SQLSelectItem() {\n    }\n\n    public SQLSelectItem(SQLExpr expr) {\n        this(expr, null);\n    }\n\n    public SQLSelectItem(int value) {\n        this(new SQLIntegerExpr(value), null);\n    }\n\n    public SQLSelectItem(SQLExpr expr, String alias) {\n        this.expr = expr;\n        this.alias = alias;\n\n        if (expr != null) {\n            expr.setParent(this);\n        }\n    }\n\n    public SQLSelectItem(SQLExpr expr, String alias, boolean connectByRoot) {\n        this.connectByRoot = connectByRoot;\n        this.expr = expr;\n        this.alias = alias;\n\n        if (expr != null) {\n            expr.setParent(this);\n        }\n    }\n\n    public SQLSelectItem(SQLExpr expr, List<String> aliasList, boolean connectByRoot) {\n        this.connectByRoot = connectByRoot;\n        this.expr = expr;\n        this.aliasList = aliasList;\n\n        if (expr != null) {\n            expr.setParent(this);\n        }\n    }\n\n    public void output(StringBuilder buf) {\n        if (this.connectByRoot) {\n            buf.append(\" CONNECT_BY_ROOT \");\n        }\n        this.expr.output(buf);\n        if ((this.alias != null) && (this.alias.length() != 0)) {\n            buf.append(\" AS \");\n            buf.append(this.alias);\n        }\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            if (expr != null) {\n                expr.accept(v);\n            }\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLSelectItem that = (SQLSelectItem) o;\n\n        if (connectByRoot != that.connectByRoot) {\n            return false;\n        }\n        if (alias_hash() != that.alias_hash()) {\n            return false;\n        }\n        if (expr != null ? !expr.equals(that.expr) : that.expr != null) {\n            return false;\n        }\n\n        return aliasList != null\n                ? aliasList.equals(that.aliasList)\n                : that.aliasList == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = expr != null ? expr.hashCode() : 0;\n        result = 31 * result + (alias != null ? alias.hashCode() : 0);\n        result = 31 * result + (connectByRoot ? 1 : 0);\n        result = 31 * result + (int) (alias_hash() ^ (alias_hash() >>> 32));\n        result = 31 * result + (aliasList != null ? aliasList.hashCode() : 0);\n        return result;\n    }\n\n    public boolean isConnectByRoot() {\n        return connectByRoot;\n    }\n\n    public void setConnectByRoot(boolean connectByRoot) {\n        this.connectByRoot = connectByRoot;\n    }\n\n    public SQLSelectItem clone() {\n        SQLSelectItem x = new SQLSelectItem();\n        cloneTo(x);\n        return x;\n    }\n\n    protected void cloneTo(SQLSelectItem x) {\n        super.cloneTo(x);\n        x.connectByRoot = connectByRoot;\n        if (aliasList != null) {\n            x.aliasList = new ArrayList<String>(aliasList);\n        }\n    }\n\n    public boolean match(String alias) {\n        if (alias == null) {\n            return false;\n        }\n\n        long hash = FnvHash.hashCode64(alias);\n        return match(hash);\n    }\n\n    public long alias_hash() {\n        if (this.aliasHashCode64 == 0) {\n            this.aliasHashCode64 = FnvHash.hashCode64(alias);\n        }\n        return aliasHashCode64;\n    }\n\n    public boolean match(long alias_hash) {\n        long hash = alias_hash();\n\n        if (hash == alias_hash) {\n            return true;\n        }\n\n        if (expr instanceof SQLAllColumnExpr) {\n            SQLTableSource resolvedTableSource = ((SQLAllColumnExpr) expr).getResolvedTableSource();\n            if (resolvedTableSource != null\n                    && resolvedTableSource.findColumn(alias_hash) != null) {\n                return true;\n            }\n            return false;\n        }\n\n        if (expr instanceof SQLIdentifierExpr) {\n            return ((SQLIdentifierExpr) expr).nameHashCode64() == alias_hash;\n        }\n\n        if (expr instanceof SQLPropertyExpr) {\n            String ident = ((SQLPropertyExpr) expr).getName();\n            if (\"*\".equals(ident)) {\n                SQLTableSource resolvedTableSource = ((SQLPropertyExpr) expr).getResolvedTableSource();\n                if (resolvedTableSource == null) {\n                    return false;\n                }\n\n                boolean isParentTableSource = false;\n                if (resolvedTableSource instanceof SQLSubqueryTableSource) {\n                    for (SQLObject parent = this.getParent(); parent != null; parent = parent.getParent()) {\n                        if (parent == resolvedTableSource) {\n                            isParentTableSource = true;\n                            break;\n                        }\n                    }\n                }\n\n                return (!isParentTableSource)\n                        && resolvedTableSource.findColumn(alias_hash) != null;\n            }\n\n            return alias == null && ((SQLPropertyExpr) expr).nameHashCode64() == alias_hash;\n        }\n\n        return false;\n    }\n\n    public List<String> getAliasList() {\n        return aliasList;\n    }\n\n    public String toString() {\n        DbType dbType = null;\n        if (parent instanceof OracleSQLObject) {\n            dbType = DbType.oracle;\n        }\n        return SQLUtils.toSQLString(this, dbType);\n    }\n\n    public boolean isUDTFSelectItem() {\n        return aliasList != null && aliasList.size() > 0;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectOrderByItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic final class SQLSelectOrderByItem extends SQLExprImpl implements SQLReplaceable {\n    protected SQLExpr expr;\n    protected String collate;\n    protected SQLExpr opclass;\n\n    protected SQLOrderingSpecification type;\n    protected NullsOrderType nullsOrderType;\n\n    protected transient SQLSelectItem resolvedSelectItem;\n\n    public SQLSelectOrderByItem() {\n    }\n\n    public SQLSelectOrderByItem(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public SQLSelectOrderByItem(SQLExpr expr, SQLOrderingSpecification type) {\n        this.setExpr(expr);\n        this.type = type;\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public String getCollate() {\n        return collate;\n    }\n\n    public void setCollate(String collate) {\n        this.collate = collate;\n    }\n\n    public SQLExpr getOpclass() {\n        return opclass;\n    }\n\n    public void setOpclass(SQLExpr opclass) {\n        this.opclass = opclass;\n    }\n\n    public SQLOrderingSpecification getType() {\n        return this.type;\n    }\n\n    public void setType(SQLOrderingSpecification type) {\n        this.type = type;\n    }\n\n    public NullsOrderType getNullsOrderType() {\n        return this.nullsOrderType;\n    }\n\n    public void setNullsOrderType(NullsOrderType nullsOrderType) {\n        this.nullsOrderType = nullsOrderType;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            if (expr != null) {\n                expr.accept(v);\n            }\n        }\n\n        v.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((collate == null) ? 0 : collate.hashCode());\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        result = prime * result + ((type == null) ? 0 : type.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        SQLSelectOrderByItem other = (SQLSelectOrderByItem) obj;\n        if (collate == null) {\n            if (other.collate != null) {\n                return false;\n            }\n        } else if (!collate.equals(other.collate)) {\n            return false;\n        }\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        if (type != other.type) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            if (target instanceof SQLIntegerExpr && parent instanceof SQLOrderBy) {\n                ((SQLOrderBy) parent).getItems().remove(this);\n            }\n            this.setExpr(target);\n            return true;\n        }\n        return false;\n    }\n\n    public static enum NullsOrderType {\n        NullsFirst, NullsLast;\n\n        public String toFormalString() {\n            if (NullsFirst.equals(this)) {\n                return \"NULLS FIRST\";\n            }\n\n            if (NullsLast.equals(this)) {\n                return \"NULLS LAST\";\n            }\n\n            throw new IllegalArgumentException();\n        }\n    }\n\n    public SQLSelectOrderByItem clone() {\n        SQLSelectOrderByItem x = new SQLSelectOrderByItem();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.collate = collate;\n        x.type = type;\n        x.nullsOrderType = nullsOrderType;\n        return x;\n    }\n\n    public SQLSelectItem getResolvedSelectItem() {\n        return resolvedSelectItem;\n    }\n\n    public void setResolvedSelectItem(SQLSelectItem resolvedSelectItem) {\n        this.resolvedSelectItem = resolvedSelectItem;\n    }\n\n    public boolean isClusterBy() {\n        if (parent instanceof SQLCreateTableStatement) {\n            List<SQLSelectOrderByItem> clusteredBy = ((SQLCreateTableStatement) parent).getClusteredBy();\n            return clusteredBy.indexOf(this) != -1;\n        }\n\n        if (parent instanceof SQLSelectQueryBlock) {\n            List<SQLSelectOrderByItem> clusterBy = ((SQLSelectQueryBlock) parent).getClusterByDirect();\n            return clusterBy != null && clusterBy.indexOf(this) != -1;\n        }\n\n        return false;\n    }\n\n    public boolean isSortBy() {\n        if (parent instanceof SQLCreateTableStatement) {\n            List<SQLSelectOrderByItem> sortedBy = ((SQLCreateTableStatement) parent).getSortedBy();\n            return sortedBy.indexOf(this) != -1;\n        }\n\n        if (parent instanceof SQLSelectQueryBlock) {\n            List<SQLSelectOrderByItem> sortedBy = ((SQLSelectQueryBlock) parent).getSortByDirect();\n            return sortedBy != null && sortedBy.indexOf(this) != -1;\n        }\n\n        return false;\n    }\n\n    public boolean isDistributeBy() {\n        if (parent instanceof SQLSelectQueryBlock) {\n            List<SQLSelectOrderByItem> distributeBy = ((SQLSelectQueryBlock) parent).getDistributeBy();\n            return distributeBy.indexOf(this) != -1;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQuery.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\n\npublic interface SQLSelectQuery extends SQLObject {\n    boolean isParenthesized();\n\n    void setParenthesized(boolean parenthesized);\n\n    SQLSelectQuery clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBase.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\n\npublic abstract class SQLSelectQueryBase extends SQLObjectImpl implements SQLSelectQuery {\n    protected boolean parenthesized;\n\n    @Override\n    public boolean isParenthesized() {\n        return parenthesized;\n    }\n\n    @Override\n    public void setParenthesized(boolean parenthesized) {\n        this.parenthesized = parenthesized;\n    }\n\n    public abstract SQLSelectQueryBase clone();\n\n    protected void cloneTo(SQLSelectQueryBase x) {\n        x.setParenthesized(this.parenthesized);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsUDTFSQLSelectItem;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.TreeSet;\n\npublic class SQLSelectQueryBlock extends SQLSelectQueryBase implements SQLReplaceable, SQLDbTypedObject {\n    // for bigquery\n    protected SQLWithSubqueryClause with;\n\n    protected int distionOption;\n    protected final List<SQLSelectItem> selectList = new ArrayList<SQLSelectItem>();\n\n    protected SQLTableSource from;\n    protected List<String> commentsAfterFrom;\n\n    protected SQLExprTableSource into;\n    protected SQLExpr where;\n\n    // for oracle & oceanbase\n    protected SQLExpr startWith;\n    protected SQLExpr connectBy;\n    protected boolean prior;\n    protected boolean noCycle;\n    protected SQLOrderBy orderBySiblings;\n\n    protected SQLSelectGroupByClause groupBy;\n    protected List<SQLWindow> windows;\n    protected SQLExpr qualify;\n    protected SQLOrderBy orderBy;\n    protected boolean forUpdate;\n    protected boolean noWait;\n    protected boolean skipLocked;\n    protected boolean forShare;\n    protected SQLExpr waitTime;\n    protected SQLLimit limit;\n\n    // for oracle\n    protected List<SQLExpr> forUpdateOf;\n    protected List<SQLSelectOrderByItem> distributeBy;\n    protected List<SQLSelectOrderByItem> sortBy;\n    protected List<SQLSelectOrderByItem> clusterBy;\n\n    protected String cachedSelectList; // optimized for SelectListCache\n    protected long cachedSelectListHash; // optimized for SelectListCache\n\n    protected DbType dbType;\n    protected List<SQLCommentHint> hints;\n\n    public SQLSelectQueryBlock() {\n    }\n\n    public SQLSelectQueryBlock(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLExprTableSource getInto() {\n        return into;\n    }\n\n    public void setInto(SQLExpr into) {\n        this.setInto(new SQLExprTableSource(into));\n    }\n\n    public void setInto(SQLExprTableSource into) {\n        if (into != null) {\n            into.setParent(this);\n        }\n        this.into = into;\n    }\n\n    public SQLSelectGroupByClause getGroupBy() {\n        return this.groupBy;\n    }\n\n    public void setGroupBy(SQLSelectGroupByClause x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.groupBy = x;\n    }\n\n    public List<SQLWindow> getWindows() {\n        return windows;\n    }\n\n    public void addWindow(SQLWindow x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        if (windows == null) {\n            windows = new ArrayList<SQLWindow>(4);\n        }\n        this.windows.add(x);\n    }\n\n    public SQLExpr getQualify() {\n        return qualify;\n    }\n\n    public void setQualify(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.qualify = x;\n    }\n\n    public SQLExpr getWhere() {\n        return this.where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    public void addWhere(SQLExpr condition) {\n        if (condition == null) {\n            return;\n        }\n\n        if (where == null) {\n            condition.setParent(this);\n            where = condition;\n            return;\n        }\n\n        List<SQLExpr> items = SQLBinaryOpExpr.split(where, SQLBinaryOperator.BooleanAnd);\n        for (SQLExpr item : items) {\n            if (condition.equals(item)) {\n                return;\n            }\n\n            if (condition instanceof SQLInListExpr) {\n                SQLInListExpr inListExpr = (SQLInListExpr) condition;\n\n                if (item instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr binaryOpItem = (SQLBinaryOpExpr) item;\n                    SQLExpr left = binaryOpItem.getLeft();\n                    SQLExpr right = binaryOpItem.getRight();\n                    if (inListExpr.getExpr().equals(left)\n                            && binaryOpItem.getOperator() == SQLBinaryOperator.Equality\n                            && !(right instanceof SQLNullExpr)\n                    ) {\n                        if (inListExpr.getTargetList().contains(right)) {\n                            return;\n                        }\n\n                        SQLUtils.replaceInParent(item, new SQLBooleanExpr(false));\n                        return;\n                    }\n                } else {\n                    if (item instanceof SQLInListExpr) {\n                        SQLInListExpr inListItem = (SQLInListExpr) item;\n                        if (inListExpr.getExpr().equals(inListItem.getExpr())) {\n                            TreeSet<SQLExpr> set = new TreeSet<SQLExpr>();\n                            for (SQLExpr itemItem : inListItem.getTargetList()) {\n                                set.add(itemItem);\n                            }\n\n                            List<SQLExpr> andList = new ArrayList<SQLExpr>();\n                            for (SQLExpr exprItem : inListExpr.getTargetList()) {\n                                if (set.contains(exprItem)) {\n                                    andList.add(exprItem.clone());\n                                }\n                            }\n\n                            if (andList.isEmpty()) {\n                                SQLUtils.replaceInParent(item, new SQLBooleanExpr(false));\n                                return;\n                            }\n\n                            inListItem.getTargetList().clear();\n                            for (SQLExpr val : andList) {\n                                inListItem.addTarget(val);\n                            }\n                            return;\n                        }\n                    }\n                }\n            }\n        }\n\n        where = SQLBinaryOpExpr.and(this.where, condition);\n        where.setParent(this);\n    }\n\n    public void addWhereForDynamicFilter(SQLExpr condition) {\n        if (condition == null) {\n            return;\n        }\n\n        if (where == null) {\n            condition.setParent(this);\n            where = condition;\n            return;\n        }\n\n        if ((where instanceof SQLBinaryOpExpr\n                || where instanceof SQLBinaryOpExprGroup)) {\n            List<SQLExpr> items = SQLBinaryOpExpr.split(where, SQLBinaryOperator.BooleanAnd);\n            for (SQLExpr item : items) {\n                if (condition.equals(item)) {\n                    return;\n                }\n\n                if (condition instanceof SQLInListExpr) {\n                    SQLInListExpr inListExpr = (SQLInListExpr) condition;\n\n                    if (item instanceof SQLBinaryOpExpr) {\n                        SQLBinaryOpExpr binaryOpItem = (SQLBinaryOpExpr) item;\n                        SQLExpr left = binaryOpItem.getLeft();\n                        SQLExpr right = binaryOpItem.getRight();\n                        if (inListExpr.getExpr().equals(left)) {\n                            if (inListExpr.getTargetList().contains(right)) {\n                                replace(item, inListExpr);\n                            } else {\n                                SQLInListExpr inListExpr2 = inListExpr.clone();\n                                inListExpr2.addTarget(right.clone());\n                                replace(item, inListExpr2);\n                            }\n                            return;\n                        }\n                    } else {\n                        if (item instanceof SQLInListExpr) {\n                            SQLInListExpr inListItem = (SQLInListExpr) item;\n                            if (inListExpr.getExpr().equals(inListItem.getExpr())) {\n                                TreeSet<SQLExpr> set = new TreeSet<SQLExpr>();\n                                for (SQLExpr itemItem : inListItem.getTargetList()) {\n                                    set.add(itemItem);\n                                }\n                                for (SQLExpr exprItem : inListExpr.getTargetList()) {\n                                    if (!set.contains(exprItem)) {\n                                        inListItem.addTarget(exprItem.clone());\n                                    }\n                                }\n                                return;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        where = SQLBinaryOpExpr.and(this.where, condition);\n        where.setParent(this);\n\n    }\n\n    public void whereOr(SQLExpr condition) {\n        if (condition == null) {\n            return;\n        }\n\n        if (where == null) {\n            condition.setParent(this);\n            where = condition;\n        } else if (SQLBinaryOpExpr.isOr(where) || SQLBinaryOpExpr.isOr(condition)) {\n            SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanOr, dbType);\n            group.add(where);\n            group.add(condition);\n            group.setParent(this);\n            where = group;\n        } else {\n            where = SQLBinaryOpExpr.or(where, condition);\n            where.setParent(this);\n        }\n    }\n\n    public void addHaving(SQLExpr condition) {\n        if (condition == null) {\n            return;\n        }\n\n        if (groupBy == null) {\n            groupBy = new SQLSelectGroupByClause();\n        }\n\n        groupBy.addHaving(condition);\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        if (orderBy != null) {\n            orderBy.setParent(this);\n        }\n\n        this.orderBy = orderBy;\n    }\n\n    public void addOrderBy(SQLOrderBy orderBy) {\n        if (orderBy == null) {\n            return;\n        }\n\n        if (this.orderBy == null) {\n            setOrderBy(orderBy);\n            return;\n        }\n\n        for (SQLSelectOrderByItem item : orderBy.getItems()) {\n            this.orderBy.addItem(item.clone());\n        }\n    }\n\n    public void addOrderBy(SQLSelectOrderByItem orderByItem) {\n        if (orderByItem == null) {\n            return;\n        }\n\n        if (this.orderBy == null) {\n            orderBy = new SQLOrderBy();\n            orderBy.setParent(this);\n        }\n\n        orderBy.addItem(orderByItem);\n    }\n\n    public boolean containsOrderBy(SQLSelectOrderByItem orderByItem) {\n        if (orderByItem == null || this.orderBy == null) {\n            return false;\n        }\n\n        if (this.orderBy.getItems().contains(orderByItem)) {\n            return true;\n        }\n\n        SQLExpr expr = orderByItem.getExpr();\n\n        int index = 0;\n        for (int i = 0; i < selectList.size(); i++) {\n            SQLSelectItem selectItem = selectList.get(i);\n            if (selectItem.getExpr().equals(expr)) {\n                index = i + 1;\n                break;\n            }\n        }\n\n        if (index > 0) {\n            for (SQLSelectOrderByItem selectOrderByItem : orderBy.getItems()) {\n                final SQLExpr orderByItemExpr = selectOrderByItem.getExpr();\n                if (orderByItemExpr instanceof SQLIntegerExpr && ((SQLIntegerExpr) orderByItemExpr).getNumber().intValue() == index) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public void addOrderBy(SQLExpr orderBy, SQLOrderingSpecification type) {\n        if (orderBy == null) {\n            return;\n        }\n\n        if (this.orderBy == null) {\n            setOrderBy(new SQLOrderBy(orderBy, type));\n            return;\n        }\n\n        this.orderBy.addItem(orderBy, type);\n    }\n\n    public void addOrderBy(SQLExpr orderBy) {\n        if (orderBy == null) {\n            return;\n        }\n\n        if (this.orderBy == null) {\n            setOrderBy(new SQLOrderBy(orderBy));\n            return;\n        }\n\n        this.orderBy.addItem(orderBy);\n    }\n\n    public SQLOrderBy getOrderBySiblings() {\n        return orderBySiblings;\n    }\n\n    public void setOrderBySiblings(SQLOrderBy orderBySiblings) {\n        if (orderBySiblings != null) {\n            orderBySiblings.setParent(this);\n        }\n        this.orderBySiblings = orderBySiblings;\n    }\n\n    public int getDistionOption() {\n        return this.distionOption;\n    }\n\n    public void setDistionOption(int distionOption) {\n        this.distionOption = distionOption;\n    }\n\n    public void setDistinct() {\n        this.distionOption = SQLSetQuantifier.DISTINCT;\n    }\n\n    public boolean isDistinct() {\n        return this.distionOption == SQLSetQuantifier.DISTINCT;\n    }\n\n    public void setDistinct(boolean distinct) {\n        if (distinct) {\n            this.distionOption = SQLSetQuantifier.DISTINCT;\n        } else {\n            if (this.distionOption == SQLSetQuantifier.DISTINCT) {\n                this.distionOption = 0;\n            }\n        }\n    }\n\n    public List<SQLSelectItem> getSelectList() {\n        return this.selectList;\n    }\n\n    public SQLSelectItem getSelectItem(int i) {\n        return this.selectList.get(i);\n    }\n\n    public void addSelectItem(SQLSelectItem item) {\n        this.selectList.add(item);\n        item.setParent(this);\n    }\n\n    public SQLSelectItem addSelectItem(SQLExpr expr) {\n        SQLSelectItem item = new SQLSelectItem(expr);\n        this.addSelectItem(item);\n        return item;\n    }\n\n    public void addSelectItem(String selectItemExpr, String alias) {\n        SQLExpr expr = SQLUtils.toSQLExpr(selectItemExpr, dbType);\n        this.addSelectItem(new SQLSelectItem(expr, alias));\n    }\n\n    public void addSelectItem(SQLExpr expr, String alias) {\n        this.addSelectItem(new SQLSelectItem(expr, alias));\n    }\n\n    private static class AggregationStatVisitor extends SQLASTVisitorAdapter {\n        private boolean aggregation;\n\n        public boolean visit(SQLAggregateExpr x) {\n            aggregation = true;\n            return false;\n        }\n    }\n\n    public boolean hasSelectAggregation() {\n        AggregationStatVisitor v = new AggregationStatVisitor();\n        for (SQLSelectItem item : selectList) {\n            SQLExpr expr = item.getExpr();\n            expr.accept(v);\n        }\n        return v.aggregation;\n    }\n\n    public SQLTableSource getFrom() {\n        return this.from;\n    }\n\n    public void setFrom(SQLExpr from) {\n        setFrom(new SQLExprTableSource(from));\n    }\n\n    public void setFrom(SQLTableSource from) {\n        if (from != null) {\n            from.setParent(this);\n        }\n        this.from = from;\n    }\n    public void setFrom(SQLSelectQueryBlock queryBlock, String alias) {\n        if (queryBlock == null) {\n            this.from = null;\n            return;\n        }\n\n        this.setFrom(new SQLSelect(queryBlock), alias);\n    }\n\n    public List<String> getCommentsAfterFrom() {\n        return commentsAfterFrom;\n    }\n\n    public void setCommentsAfterFrom(List<String> commentsAfterFrom) {\n        this.commentsAfterFrom = commentsAfterFrom;\n    }\n\n    public void setFrom(SQLSelect select, String alias) {\n        if (select == null) {\n            this.from = null;\n            return;\n        }\n\n        SQLSubqueryTableSource from = new SQLSubqueryTableSource(select);\n        from.setAlias(alias);\n        this.setFrom(from);\n    }\n\n    public void setFrom(String tableName, String alias) {\n        SQLExprTableSource from;\n        if (tableName == null || tableName.length() == 0) {\n            from = null;\n        } else {\n            SQLExpr expr = SQLUtils.toSQLExpr(tableName);\n            from = new SQLExprTableSource(expr, alias);\n        }\n        this.setFrom(from);\n    }\n\n    public boolean isForUpdate() {\n        return forUpdate;\n    }\n\n    public void setForUpdate(boolean forUpdate) {\n        this.forUpdate = forUpdate;\n    }\n\n    public boolean isNoWait() {\n        return noWait;\n    }\n\n    public void setNoWait(boolean noWait) {\n        this.noWait = noWait;\n    }\n\n    public boolean isSkipLocked() {\n        return skipLocked;\n    }\n\n    public void setSkipLocked(boolean skipLocked) {\n        this.skipLocked = skipLocked;\n    }\n\n    public boolean isForShare() {\n        return forShare;\n    }\n\n    public void setForShare(boolean forShare) {\n        this.forShare = forShare;\n    }\n\n    public SQLExpr getWaitTime() {\n        return waitTime;\n    }\n\n    public void setWaitTime(SQLExpr waitTime) {\n        if (waitTime != null) {\n            waitTime.setParent(this);\n        }\n        this.waitTime = waitTime;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        if (limit != null) {\n            limit.setParent(this);\n        }\n        this.limit = limit;\n    }\n\n    public void mergeLimit(SQLLimit limit) {\n        if (this.limit == null) {\n            this.limit = limit.clone();\n            return;\n        }\n\n        this.limit.merge(limit);\n    }\n\n    public SQLExpr getFirst() {\n        if (limit == null) {\n            return null;\n        }\n\n        return limit.getRowCount();\n    }\n\n    public void setFirst(SQLExpr first) {\n        if (limit == null) {\n            limit = new SQLLimit();\n        }\n        this.limit.setRowCount(first);\n    }\n\n    public SQLExpr getOffset() {\n        if (limit == null) {\n            return null;\n        }\n\n        return limit.getOffset();\n    }\n\n    public void setOffset(SQLExpr offset) {\n        if (limit == null) {\n            limit = new SQLLimit();\n        }\n        this.limit.setOffset(offset);\n    }\n\n    public boolean isPrior() {\n        return prior;\n    }\n\n    public void setPrior(boolean prior) {\n        this.prior = prior;\n    }\n\n    public SQLExpr getStartWith() {\n        return this.startWith;\n    }\n\n    public void setStartWith(SQLExpr startWith) {\n        if (startWith != null) {\n            startWith.setParent(this);\n        }\n        this.startWith = startWith;\n    }\n\n    public SQLExpr getConnectBy() {\n        return this.connectBy;\n    }\n\n    public void setConnectBy(SQLExpr connectBy) {\n        if (connectBy != null) {\n            connectBy.setParent(this);\n        }\n        this.connectBy = connectBy;\n    }\n\n    public boolean isNoCycle() {\n        return this.noCycle;\n    }\n\n    public void setNoCycle(boolean noCycle) {\n        this.noCycle = noCycle;\n    }\n\n    public List<SQLSelectOrderByItem> getDistributeBy() {\n        if (distributeBy == null) {\n            distributeBy = new ArrayList<SQLSelectOrderByItem>();\n        }\n\n        return distributeBy;\n    }\n\n    public List<SQLSelectOrderByItem> getDistributeByDirect() {\n        return distributeBy;\n    }\n\n    public void addDistributeBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        } else {\n            return;\n        }\n\n        if (distributeBy == null) {\n            distributeBy = new ArrayList<SQLSelectOrderByItem>();\n        }\n        distributeBy.add(new SQLSelectOrderByItem(x));\n    }\n\n    public void addDistributeBy(SQLSelectOrderByItem item) {\n        if (distributeBy == null) {\n            distributeBy = new ArrayList<SQLSelectOrderByItem>();\n        }\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.distributeBy.add(item);\n    }\n\n    public List<SQLSelectOrderByItem> getSortBy() {\n        if (sortBy == null) {\n            sortBy = new ArrayList<SQLSelectOrderByItem>();\n        }\n        return sortBy;\n    }\n\n    public List<SQLSelectOrderByItem> getSortByDirect() {\n        return sortBy;\n    }\n\n    public void addSortBy(SQLSelectOrderByItem item) {\n        if (sortBy == null) {\n            sortBy = new ArrayList<SQLSelectOrderByItem>();\n        }\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.sortBy.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        if (with != null) {\n            with.accept(v);\n        }\n\n        for (int i = 0; i < this.selectList.size(); i++) {\n            SQLSelectItem item = this.selectList.get(i);\n            if (item != null) {\n                item.accept(v);\n            }\n        }\n\n        if (this.from != null) {\n            this.from.accept(v);\n        }\n\n        if (this.windows != null) {\n            for (int i = 0; i < windows.size(); i++) {\n                SQLWindow item = windows.get(i);\n                item.accept(v);\n            }\n        }\n\n        if (this.into != null) {\n            this.into.accept(v);\n        }\n\n        if (this.where != null) {\n            this.where.accept(v);\n        }\n\n        if (this.startWith != null) {\n            this.startWith.accept(v);\n        }\n\n        if (this.connectBy != null) {\n            this.connectBy.accept(v);\n        }\n\n        if (this.groupBy != null) {\n            this.groupBy.accept(v);\n        }\n\n        if (this.qualify != null) {\n            this.qualify.accept(v);\n        }\n\n        if (this.orderBy != null) {\n            this.orderBy.accept(v);\n        }\n\n        if (this.distributeBy != null) {\n            for (int i = 0; i < distributeBy.size(); i++) {\n                SQLSelectOrderByItem item = distributeBy.get(i);\n                item.accept(v);\n            }\n        }\n\n        if (this.sortBy != null) {\n            for (int i = 0; i < sortBy.size(); i++) {\n                SQLSelectOrderByItem item = sortBy.get(i);\n                item.accept(v);\n            }\n        }\n\n        if (this.waitTime != null) {\n            this.waitTime.accept(v);\n        }\n\n        if (this.limit != null) {\n            this.limit.accept(v);\n        }\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLSelectQueryBlock that = (SQLSelectQueryBlock) o;\n\n        if (distionOption != that.distionOption) {\n            return false;\n        }\n        if (prior != that.prior) {\n            return false;\n        }\n        if (noCycle != that.noCycle) {\n            return false;\n        }\n        if (parenthesized != that.parenthesized) {\n            return false;\n        }\n        if (forUpdate != that.forUpdate) {\n            return false;\n        }\n        if (noWait != that.noWait) {\n            return false;\n        }\n        if (cachedSelectListHash != that.cachedSelectListHash) {\n            return false;\n        }\n        if (selectList != null ? !selectList.equals(that.selectList) : that.selectList != null) {\n            return false;\n        }\n        if (from != null ? !from.equals(that.from) : that.from != null) {\n            return false;\n        }\n        if (into != null ? !into.equals(that.into) : that.into != null) {\n            return false;\n        }\n        if (where != null ? !where.equals(that.where) : that.where != null) {\n            return false;\n        }\n        if (startWith != null ? !startWith.equals(that.startWith) : that.startWith != null) {\n            return false;\n        }\n        if (connectBy != null ? !connectBy.equals(that.connectBy) : that.connectBy != null) {\n            return false;\n        }\n        if (orderBySiblings != null ? !orderBySiblings.equals(that.orderBySiblings) : that.orderBySiblings != null) {\n            return false;\n        }\n        if (groupBy != null ? !groupBy.equals(that.groupBy) : that.groupBy != null) {\n            return false;\n        }\n        if (orderBy != null ? !orderBy.equals(that.orderBy) : that.orderBy != null) {\n            return false;\n        }\n        if (waitTime != null ? !waitTime.equals(that.waitTime) : that.waitTime != null) {\n            return false;\n        }\n        if (limit != null ? !limit.equals(that.limit) : that.limit != null) {\n            return false;\n        }\n        if (forUpdateOf != null ? !forUpdateOf.equals(that.forUpdateOf) : that.forUpdateOf != null) {\n            return false;\n        }\n        if (distributeBy != null ? !distributeBy.equals(that.distributeBy) : that.distributeBy != null) {\n            return false;\n        }\n        if (sortBy != null ? !sortBy.equals(that.sortBy) : that.sortBy != null) {\n            return false;\n        }\n        if (cachedSelectList != null ? !cachedSelectList.equals(that.cachedSelectList) : that.cachedSelectList != null) {\n            return false;\n        }\n        if (dbType != that.dbType) {\n            return false;\n        }\n        return hints != null ? hints.equals(that.hints) : that.hints == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = distionOption;\n        result = 31 * result + (selectList != null ? selectList.hashCode() : 0);\n        result = 31 * result + (from != null ? from.hashCode() : 0);\n        result = 31 * result + (into != null ? into.hashCode() : 0);\n        result = 31 * result + (where != null ? where.hashCode() : 0);\n        result = 31 * result + (startWith != null ? startWith.hashCode() : 0);\n        result = 31 * result + (connectBy != null ? connectBy.hashCode() : 0);\n        result = 31 * result + (prior ? 1 : 0);\n        result = 31 * result + (noCycle ? 1 : 0);\n        result = 31 * result + (orderBySiblings != null ? orderBySiblings.hashCode() : 0);\n        result = 31 * result + (groupBy != null ? groupBy.hashCode() : 0);\n        result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);\n        result = 31 * result + (parenthesized ? 1 : 0);\n        result = 31 * result + (forUpdate ? 1 : 0);\n        result = 31 * result + (noWait ? 1 : 0);\n        result = 31 * result + (waitTime != null ? waitTime.hashCode() : 0);\n        result = 31 * result + (limit != null ? limit.hashCode() : 0);\n        result = 31 * result + (forUpdateOf != null ? forUpdateOf.hashCode() : 0);\n        result = 31 * result + (distributeBy != null ? distributeBy.hashCode() : 0);\n        result = 31 * result + (sortBy != null ? sortBy.hashCode() : 0);\n        result = 31 * result + (cachedSelectList != null ? cachedSelectList.hashCode() : 0);\n        result = 31 * result + (int) (cachedSelectListHash ^ (cachedSelectListHash >>> 32));\n        result = 31 * result + (dbType != null ? dbType.hashCode() : 0);\n        result = 31 * result + (hints != null ? hints.hashCode() : 0);\n        return result;\n    }\n\n    public boolean equalsForMergeJoin(SQLSelectQueryBlock that) {\n        if (this == that) {\n            return true;\n        }\n        if (that == null) {\n            return false;\n        }\n\n        if (into != null || limit != null || groupBy != null) {\n            return false;\n        }\n\n        if (distionOption != that.distionOption) {\n            return false;\n        }\n        if (prior != that.prior) {\n            return false;\n        }\n        if (noCycle != that.noCycle) {\n            return false;\n        }\n        if (parenthesized != that.parenthesized) {\n            return false;\n        }\n        if (forUpdate != that.forUpdate) {\n            return false;\n        }\n        if (noWait != that.noWait) {\n            return false;\n        }\n        if (cachedSelectListHash != that.cachedSelectListHash) {\n            return false;\n        }\n        if (selectList != null ? !selectList.equals(that.selectList) : that.selectList != null) {\n            return false;\n        }\n        if (from != null ? !from.equals(that.from) : that.from != null) {\n            return false;\n        }\n        if (into != null ? !into.equals(that.into) : that.into != null) {\n            return false;\n        }\n//        if (where != null ? !where.equals(that.where) : that.where != null) return false;\n        if (startWith != null ? !startWith.equals(that.startWith) : that.startWith != null) {\n            return false;\n        }\n        if (connectBy != null ? !connectBy.equals(that.connectBy) : that.connectBy != null) {\n            return false;\n        }\n        if (orderBySiblings != null ? !orderBySiblings.equals(that.orderBySiblings) : that.orderBySiblings != null) {\n            return false;\n        }\n        if (groupBy != null ? !groupBy.equals(that.groupBy) : that.groupBy != null) {\n            return false;\n        }\n        if (orderBy != null ? !orderBy.equals(that.orderBy) : that.orderBy != null) {\n            return false;\n        }\n        if (waitTime != null ? !waitTime.equals(that.waitTime) : that.waitTime != null) {\n            return false;\n        }\n        if (limit != null ? !limit.equals(that.limit) : that.limit != null) {\n            return false;\n        }\n        if (forUpdateOf != null ? !forUpdateOf.equals(that.forUpdateOf) : that.forUpdateOf != null) {\n            return false;\n        }\n        if (distributeBy != null ? !distributeBy.equals(that.distributeBy) : that.distributeBy != null) {\n            return false;\n        }\n        if (sortBy != null ? !sortBy.equals(that.sortBy) : that.sortBy != null) {\n            return false;\n        }\n        if (cachedSelectList != null ? !cachedSelectList.equals(that.cachedSelectList) : that.cachedSelectList != null) {\n            return false;\n        }\n        return dbType == that.dbType;\n    }\n\n    public SQLSelectQueryBlock clone() {\n        SQLSelectQueryBlock x = new SQLSelectQueryBlock(dbType);\n        cloneTo(x);\n        return x;\n    }\n\n    public List<SQLExpr> getForUpdateOf() {\n        if (forUpdateOf == null) {\n            forUpdateOf = new ArrayList<SQLExpr>(1);\n        }\n        return forUpdateOf;\n    }\n\n    public int getForUpdateOfSize() {\n        if (forUpdateOf == null) {\n            return 0;\n        }\n\n        return forUpdateOf.size();\n    }\n\n    public void cloneSelectListTo(SQLSelectQueryBlock x) {\n        x.distionOption = distionOption;\n        for (SQLSelectItem item : this.selectList) {\n            SQLSelectItem item2 = item.clone();\n            item2.setParent(x);\n            x.selectList.add(item2);\n        }\n    }\n\n    public void cloneTo(SQLSelectQueryBlock x) {\n        x.parenthesized = parenthesized;\n        x.distionOption = distionOption;\n\n        if (with != null) {\n            x.setWith(with.clone());\n        }\n\n        if (x.selectList.size() > 0) {\n            x.selectList.clear();\n        }\n\n        if (hints != null) {\n            for (SQLCommentHint hint : hints) {\n                SQLCommentHint hint1 = hint.clone();\n                hint1.setParent(x);\n                x.getHints().add(hint1);\n            }\n        }\n\n        for (SQLSelectItem item : this.selectList) {\n            x.addSelectItem(item.clone());\n        }\n\n        if (from != null) {\n            x.setFrom(from.clone());\n        }\n\n        if (into != null) {\n            x.setInto(into.clone());\n        }\n\n        if (where != null) {\n            x.setWhere(where.clone());\n        }\n\n        if (startWith != null) {\n            x.setStartWith(startWith.clone());\n        }\n\n        if (connectBy != null) {\n            x.setConnectBy(connectBy.clone());\n        }\n\n        x.prior = prior;\n        x.noCycle = noCycle;\n\n        if (orderBySiblings != null) {\n            x.setOrderBySiblings(orderBySiblings.clone());\n        }\n\n        if (groupBy != null) {\n            x.setGroupBy(groupBy.clone());\n        }\n\n        if (qualify != null) {\n            x.setQualify(qualify.clone());\n        }\n\n        if (orderBy != null) {\n            x.setOrderBy(orderBy.clone());\n        }\n\n        if (distributeBy != null) {\n            if (x.distributeBy == null) {\n                x.distributeBy = new ArrayList<SQLSelectOrderByItem>();\n            }\n\n            for (int i = 0; i < distributeBy.size(); i++) {\n                SQLSelectOrderByItem item = distributeBy.get(i).clone();\n                item.setParent(x);\n                x.distributeBy.add(item);\n            }\n        }\n\n        if (sortBy != null) {\n            if (x.sortBy == null) {\n                x.sortBy = new ArrayList<SQLSelectOrderByItem>();\n            }\n\n            for (int i = 0; i < sortBy.size(); i++) {\n                SQLSelectOrderByItem item = sortBy.get(i).clone();\n                item.setParent(x);\n                x.sortBy.add(item);\n            }\n        }\n\n        if (clusterBy != null) {\n            if (x.clusterBy == null) {\n                x.clusterBy = new ArrayList<SQLSelectOrderByItem>();\n            }\n\n            for (int i = 0; i < clusterBy.size(); i++) {\n                SQLSelectOrderByItem item = clusterBy.get(i).clone();\n                item.setParent(x);\n                x.clusterBy.add(item);\n            }\n        }\n\n        x.parenthesized = parenthesized;\n        x.forUpdate = forUpdate;\n        x.noWait = noWait;\n        x.skipLocked = skipLocked;\n        x.forShare = forShare;\n        if (waitTime != null) {\n            x.setWaitTime(waitTime.clone());\n        }\n\n        if (limit != null) {\n            x.setLimit(limit.clone());\n        }\n    }\n\n    public SQLTableSource findTableSource(String alias) {\n        if (from == null) {\n            return null;\n        }\n        return from.findTableSource(alias);\n    }\n\n    public SQLTableSource findTableSourceWithColumn(String column) {\n        if (from == null) {\n            return null;\n        }\n        return from.findTableSourceWithColumn(column);\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnHash) {\n        if (from == null) {\n            return null;\n        }\n\n        SQLTableSource tableSource = from.findTableSourceWithColumn(columnHash);\n\n        if (tableSource == null && from instanceof SQLExprTableSource) {\n            SQLSelectItem selectItem = this.findSelectItem(columnHash);\n            if (selectItem != null\n                    && selectItem.getExpr() instanceof SQLName\n                    && ((SQLName) selectItem.getExpr()).nameHashCode64() == columnHash) {\n                tableSource = from;\n            }\n        }\n\n        return tableSource;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        boolean isReplaced = false;\n        if (where == expr) {\n            setWhere(target);\n            isReplaced = true;\n        }\n\n        if (startWith == expr) {\n            setStartWith(target);\n            isReplaced = true;\n        }\n\n        if (connectBy == expr) {\n            setConnectBy(target);\n            isReplaced = true;\n        }\n\n        if (with == expr) {\n            setWith((SQLWithSubqueryClause) target);\n            isReplaced = true;\n        }\n\n        if (from == expr) {\n            setFrom((SQLTableSource) target);\n            isReplaced = true;\n        }\n\n        if (into == expr && target instanceof SQLExprTableSource) {\n            setInto((SQLExprTableSource) target);\n            isReplaced = true;\n        }\n\n        if (qualify == expr) {\n            setQualify(target);\n            isReplaced = true;\n        }\n\n        if (waitTime == expr) {\n            setWaitTime(target);\n            isReplaced = true;\n        }\n\n        if (expr instanceof SQLSelectItem && target instanceof SQLSelectItem) {\n            isReplaced = isReplaced || replaceList(selectList, (SQLSelectItem) expr, (SQLSelectItem) target);\n        }\n\n        if (expr instanceof SQLSelectOrderByItem && target instanceof SQLSelectOrderByItem) {\n            isReplaced = isReplaced || replaceList(distributeBy, (SQLSelectOrderByItem) expr, (SQLSelectOrderByItem) target)\n                || replaceList(sortBy, (SQLSelectOrderByItem) expr, (SQLSelectOrderByItem) target)\n                || replaceList(clusterBy, (SQLSelectOrderByItem) expr, (SQLSelectOrderByItem) target);\n        }\n\n        isReplaced = isReplaced || replaceList(forUpdateOf, expr, target);\n        return isReplaced;\n    }\n\n    protected <T extends SQLObject> boolean replaceList(List<T> exprList, T expr, T target) {\n        boolean isReplaced = false;\n        if (exprList == null) {\n            return isReplaced;\n        }\n        for (int i = 0; i < exprList.size(); i++) {\n            if (exprList.get(i) == expr) {\n                target.setParent(this);\n                exprList.set(i, target);\n                isReplaced = true;\n            }\n        }\n        return isReplaced;\n    }\n\n    public SQLSelectItem findSelectItem(String ident) {\n        if (ident == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(ident);\n        return findSelectItem(hash);\n    }\n\n    public SQLDataType findSelectItemAndComputeDataType(String ident) {\n        if (ident == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(ident);\n        return findSelectItemAndComputeDataType(hash);\n    }\n\n    public SQLDataType findSelectItemAndComputeDataType(long identHash) {\n        SQLSelectItem selectItem = findSelectItem(identHash);\n        if (selectItem != null) {\n            return selectItem.computeDataType();\n        }\n\n        if (hasAllColumnSelectItem()) {\n            if (from instanceof SQLSubqueryTableSource) {\n                SQLSelectQueryBlock firstQueryBlock = ((SQLSubqueryTableSource) from).getSelect().getFirstQueryBlock();\n                if (firstQueryBlock != null) {\n                    return firstQueryBlock.findSelectItemAndComputeDataType(identHash);\n                }\n            } else if (from instanceof SQLExprTableSource\n                    && ((SQLExprTableSource) from).getExpr() instanceof SQLIdentifierExpr\n            ) {\n                for (SQLObject parent = this.parent; parent != null; parent = parent.getParent()) {\n                    if (parent instanceof SQLSelect) {\n                        SQLWithSubqueryClause.Entry queryEntry = ((SQLSelect) parent).findWithSubQueryEntry(((SQLIdentifierExpr) ((SQLExprTableSource) from).getExpr()).getName());\n                        if (queryEntry != null) {\n                            return queryEntry.getSubQuery().findSelectItemAndComputeDataType(identHash);\n                        }\n                    }\n                }\n            }\n        }\n        return null;\n    }\n\n    public boolean hasAllColumnSelectItem() {\n        for (SQLSelectItem selectItem : selectList) {\n            if (selectItem.getExpr() instanceof SQLAllColumnExpr) {\n                SQLAllColumnExpr expr = (SQLAllColumnExpr) selectItem.getExpr();\n                SQLExpr owner = expr.getOwner();\n                if (owner == null) {\n                    return true;\n                }\n                if (owner instanceof SQLIdentifierExpr\n                        && from != null\n                        && ((SQLIdentifierExpr) owner).getName().equals(from.computeAlias())) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public SQLSelectItem findSelectItem(long identHash) {\n        for (SQLSelectItem item : this.selectList) {\n            if (item.match(identHash)) {\n                return item;\n            }\n        }\n\n        if (from == null) {\n            return null;\n        }\n\n        if (selectList.size() == 1\n                && selectList.get(0).getExpr() instanceof SQLAllColumnExpr) {\n            SQLTableSource matchedTableSource = from.findTableSourceWithColumn(identHash);\n            if (matchedTableSource != null) {\n                return selectList.get(0);\n            }\n        }\n\n        SQLSelectItem ownerAllItem = null;\n        for (SQLSelectItem item : this.selectList) {\n            SQLExpr itemExpr = item.getExpr();\n//            if (itemExpr instanceof SQLAllColumnExpr && !(from instanceof SQLJoinTableSource)) {\n//                if (ownerAllItem != null) {\n//                    return null; // dup *\n//                }\n//                ownerAllItem = item;\n//                continue;\n//            }\n\n            if (itemExpr instanceof SQLPropertyExpr\n                    && ((SQLPropertyExpr) itemExpr).getName().equals(\"*\")\n            ) {\n                if (ownerAllItem != null) {\n                    return null; // dup *\n                }\n                ownerAllItem = item;\n            }\n        }\n\n        if (ownerAllItem != null) {\n            return ownerAllItem;\n        }\n\n        return null;\n    }\n\n    public boolean selectItemHasAllColumn() {\n        return selectItemHasAllColumn(true);\n    }\n\n    public boolean selectItemHasAllColumn(boolean recursive) {\n        for (SQLSelectItem item : this.selectList) {\n            SQLExpr expr = item.getExpr();\n\n            boolean allColumn = expr instanceof SQLAllColumnExpr\n                    || (expr instanceof SQLPropertyExpr && ((SQLPropertyExpr) expr).getName().equals(\"*\"));\n\n            if (allColumn) {\n                if (recursive && from instanceof SQLSubqueryTableSource) {\n                    SQLSelect subSelect = ((SQLSubqueryTableSource) from).select;\n                    SQLSelectQueryBlock queryBlock = subSelect.getQueryBlock();\n                    if (queryBlock != null) {\n                        return queryBlock.selectItemHasAllColumn();\n                    }\n                }\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public SQLSelectItem findAllColumnSelectItem() {\n        SQLSelectItem allColumnItem = null;\n        for (SQLSelectItem item : this.selectList) {\n            SQLExpr expr = item.getExpr();\n\n            boolean allColumn = expr instanceof SQLAllColumnExpr\n                    || (expr instanceof SQLPropertyExpr && ((SQLPropertyExpr) expr).getName().equals(\"*\"));\n\n            if (allColumnItem != null) {\n                return null; // duplicateAllColumn\n            }\n            allColumnItem = item;\n        }\n\n        return allColumnItem;\n    }\n\n    public SQLColumnDefinition findColumn(String columnName) {\n        if (from == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(columnName);\n        return from.findColumn(hash);\n    }\n\n    public SQLColumnDefinition findColumn(long columnNameHash) {\n        SQLObject object = resolveColum(columnNameHash);\n        if (object instanceof SQLColumnDefinition) {\n            return (SQLColumnDefinition) object;\n        } else if (object instanceof SQLSelectItem) {\n            SQLExpr expr = ((SQLSelectItem) object).getExpr();\n            if (expr instanceof SQLName) {\n                return ((SQLName) expr).getResolvedColumn();\n            }\n        }\n        return null;\n    }\n\n    public SQLObject resolveColum(long columnNameHash) {\n        final SQLSelectItem selectItem = findSelectItem(columnNameHash);\n        if (selectItem != null) {\n            SQLExpr selectItemExpr = selectItem.getExpr();\n            if (selectItemExpr instanceof SQLAllColumnExpr) {\n                SQLObject resolveColumn = from.resolveColum(columnNameHash);\n                if (resolveColumn != null) {\n                    return resolveColumn;\n                }\n            } else if (selectItemExpr instanceof SQLPropertyExpr\n                    && ((SQLPropertyExpr) selectItemExpr).getName().equals(\"*\")) {\n                SQLTableSource resolvedTableSource = ((SQLPropertyExpr) selectItemExpr).getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLSubqueryTableSource) {\n                    boolean isParentTableSource = false;\n                    for (SQLObject parent = this.getParent(); parent != null; parent = parent.getParent()) {\n                        if (parent == resolvedTableSource) {\n                            isParentTableSource = true;\n                            break;\n                        }\n                    }\n\n                    if (isParentTableSource) {\n                        return null;\n                    }\n\n                    SQLObject resolveColumn = resolvedTableSource.resolveColum(columnNameHash);\n                    if (resolveColumn != null) {\n                        return resolveColumn;\n                    }\n                }\n            }\n\n            return selectItem;\n        }\n\n        if (from != null) {\n            return from.resolveColum(columnNameHash);\n        } else {\n            return null;\n        }\n    }\n\n    public void addCondition(String conditionSql) {\n        if (conditionSql == null || conditionSql.length() == 0) {\n            return;\n        }\n\n        SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);\n        addCondition(condition);\n    }\n\n    public void addCondition(SQLExpr expr) {\n        if (expr == null) {\n            return;\n        }\n\n        this.setWhere(SQLBinaryOpExpr.and(where, expr));\n    }\n\n    public boolean removeCondition(String conditionSql) {\n        if (conditionSql == null || conditionSql.length() == 0) {\n            return false;\n        }\n\n        SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);\n\n        return removeCondition(condition);\n    }\n\n    public boolean removeCondition(SQLExpr condition) {\n        if (condition == null) {\n            return false;\n        }\n\n        if (where instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) where;\n\n            int removedCount = 0;\n            List<SQLExpr> items = group.getItems();\n            for (int i = items.size() - 1; i >= 0; i--) {\n                SQLExpr item = items.get(i);\n                if (item.equals(condition)) {\n                    items.remove(i);\n                    removedCount++;\n                }\n            }\n            if (items.isEmpty()) {\n                where = null;\n            }\n\n            return removedCount > 0;\n        }\n\n        if (where instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpWhere = (SQLBinaryOpExpr) where;\n            SQLBinaryOperator operator = binaryOpWhere.getOperator();\n            if (operator == SQLBinaryOperator.BooleanAnd || operator == SQLBinaryOperator.BooleanOr) {\n                List<SQLExpr> items = SQLBinaryOpExpr.split(binaryOpWhere);\n\n                int removedCount = 0;\n                for (int i = items.size() - 1; i >= 0; i--) {\n                    SQLExpr item = items.get(i);\n                    if (item.equals(condition)) {\n                        if (SQLUtils.replaceInParent(item, null)) {\n                            removedCount++;\n                        }\n                    }\n                }\n\n                return removedCount > 0;\n            }\n        }\n\n        if (condition.equals(where)) {\n            where = null;\n            return true;\n        }\n\n        return false;\n    }\n\n    public void limit(int rowCount, int offset) {\n        SQLLimit limit = new SQLLimit();\n        limit.setRowCount(new SQLIntegerExpr(rowCount));\n        if (offset > 0) {\n            limit.setOffset(new SQLIntegerExpr(offset));\n        }\n\n        setLimit(limit);\n    }\n\n    public String getCachedSelectList() {\n        return cachedSelectList;\n    }\n\n    public void setCachedSelectList(String cachedSelectList, long cachedSelectListHash) {\n        this.cachedSelectList = cachedSelectList;\n        this.cachedSelectListHash = cachedSelectListHash;\n    }\n\n    public long getCachedSelectListHash() {\n        return cachedSelectListHash;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public List<SQLCommentHint> getHintsDirect() {\n        return hints;\n    }\n\n    public List<SQLCommentHint> getHints() {\n        if (hints == null) {\n            hints = new ArrayList<SQLCommentHint>(2);\n        }\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n\n        return hints.size();\n    }\n\n    public boolean replaceInParent(SQLSelectQuery x) {\n        if (parent instanceof SQLSelect) {\n            ((SQLSelect) parent).setQuery(x);\n            return true;\n        }\n\n        if (parent instanceof SQLUnionQuery) {\n            SQLUnionQuery union = (SQLUnionQuery) parent;\n            return union.replace(this, x);\n        }\n\n        return false;\n    }\n\n    public List<SQLSelectOrderByItem> getClusterBy() {\n        if (clusterBy == null) {\n            clusterBy = new ArrayList<SQLSelectOrderByItem>();\n        }\n\n        return clusterBy;\n    }\n\n    public List<SQLSelectOrderByItem> getClusterByDirect() {\n        return clusterBy;\n    }\n\n    public void addClusterBy(SQLSelectOrderByItem item) {\n        if (clusterBy == null) {\n            clusterBy = new ArrayList<SQLSelectOrderByItem>();\n        }\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.clusterBy.add(item);\n    }\n\n    public List<String> computeSelecteListAlias() {\n        List<String> aliasList = new ArrayList<String>();\n\n        for (SQLSelectItem item : this.selectList) {\n            if (item instanceof OdpsUDTFSQLSelectItem) {\n                aliasList.addAll(((OdpsUDTFSQLSelectItem) item).getAliasList());\n            } else {\n                SQLExpr expr = item.getExpr();\n                if (expr instanceof SQLAllColumnExpr) {\n                    // TODO\n                } else if (expr instanceof SQLPropertyExpr && ((SQLPropertyExpr) expr).getName().equals(\"*\")) {\n                    // TODO\n                } else {\n                    aliasList.add(item.computeAlias());\n                }\n            }\n        }\n\n        return aliasList;\n    }\n\n    public List<SQLTableSource> getMappJoinTableSources() {\n        if (hints == null) {\n            return Collections.emptyList();\n        }\n\n        List<SQLTableSource> tableSources = null;\n        for (SQLCommentHint hint : hints) {\n            String text = hint.getText();\n            if (text.startsWith(\"+\")) {\n                SQLExpr hintExpr = SQLUtils.toSQLExpr(text.substring(1), dbType);\n                if (hintExpr instanceof SQLMethodInvokeExpr) {\n                    SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) hintExpr;\n                    if (func.methodNameHashCode64() == FnvHash.Constants.MAPJOIN) {\n                        for (SQLExpr arg : func.getArguments()) {\n                            SQLIdentifierExpr tablename = (SQLIdentifierExpr) arg;\n                            SQLTableSource tableSource = findTableSource(tablename.getName());\n                            if (tableSources == null) {\n                                tableSources = new ArrayList<SQLTableSource>(2);\n                            }\n                            tableSources.add(tableSource);\n                        }\n                    }\n                }\n            }\n        }\n\n        if (tableSources == null) {\n            return Collections.emptyList();\n        }\n\n        return tableSources;\n    }\n\n    public boolean clearMapJoinHint() {\n        if (hints == null) {\n            return false;\n        }\n\n        int removeCount = 0;\n        for (int i = hints.size() - 1; i >= 0; i--) {\n            SQLCommentHint hint = hints.get(i);\n            String text = hint.getText();\n            if (text.startsWith(\"+\")) {\n                SQLExpr hintExpr = SQLUtils.toSQLExpr(text.substring(1), dbType);\n                if (hintExpr instanceof SQLMethodInvokeExpr) {\n                    SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) hintExpr;\n                    if (func.methodNameHashCode64() == FnvHash.Constants.MAPJOIN) {\n                        hints.remove(i);\n                        removeCount++;\n                    }\n                }\n            }\n        }\n        return removeCount > 0;\n    }\n\n    public SQLWithSubqueryClause getWith() {\n        return with;\n    }\n\n    public void setWith(SQLWithSubqueryClause x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.with = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLSelectStatement extends SQLStatementImpl {\n    protected SQLSelect select;\n\n    public SQLSelectStatement() {\n    }\n\n    public SQLSelectStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLSelectStatement(SQLSelect select) {\n        this.setSelect(select);\n    }\n\n    public SQLSelectStatement(SQLSelect select, DbType dbType) {\n        this(dbType);\n        this.setSelect(select);\n    }\n\n    public SQLSelect getSelect() {\n        return this.select;\n    }\n\n    public void setSelect(SQLSelect select) {\n        if (select != null) {\n            select.setParent(this);\n        }\n        this.select = select;\n    }\n\n    public void output(StringBuilder buf) {\n        this.select.output(buf);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.select != null) {\n                this.select.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLSelectStatement clone() {\n        SQLSelectStatement x = new SQLSelectStatement();\n        x.dbType = dbType;\n        x.afterSemi = afterSemi;\n        if (select != null) {\n            x.setSelect(select.clone());\n        }\n        if (headHints != null) {\n            for (SQLCommentHint h : headHints) {\n                SQLCommentHint h2 = h.clone();\n                h2.setParent(x);\n                if (x.headHints == null) {\n                    x.headHints = new ArrayList<SQLCommentHint>(headHints.size());\n                }\n                x.headHints.add(h2);\n            }\n        }\n        return x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(select);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLSelectStatement that = (SQLSelectStatement) o;\n\n        return select != null ? select.equals(that.select) : that.select == null;\n    }\n\n    @Override\n    public int hashCode() {\n        return select != null ? select.hashCode() : 0;\n    }\n\n    public List<String> computeSelecteListAlias() {\n        return select.computeSelecteListAlias();\n    }\n\n    public boolean addWhere(SQLExpr where) {\n        return select.addWhere(where);\n    }\n\n    public void addBeforeComment(String comment) {\n        if (headHints == null && attributes == null && select.hints == null && select.getBeforeCommentsDirect() == null) {\n            SQLSelectQueryBlock queryBlock = select.getQueryBlock();\n            List<String> queryBlockBeforeComments = queryBlock.getBeforeCommentsDirect();\n            if (queryBlockBeforeComments != null) {\n                queryBlockBeforeComments.add(comment);\n                return;\n            }\n        }\n        super.addBeforeComment(comment);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSetStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLSetStatement extends SQLStatementImpl {\n    private Option option;\n\n    private List<SQLAssignItem> items = new ArrayList<SQLAssignItem>();\n\n    private List<SQLCommentHint> hints;\n\n    private boolean useSet;\n\n    SQLStatement maridbSetForStatement;\n\n    public SQLSetStatement() {\n    }\n\n    public SQLSetStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLSetStatement(SQLExpr target, SQLExpr value) {\n        this(target, value, null);\n    }\n\n    public SQLSetStatement(SQLExpr target, SQLExpr value, DbType dbType) {\n        super(dbType);\n        SQLAssignItem item = new SQLAssignItem(target, value);\n        item.setParent(this);\n        this.items.add(item);\n    }\n\n    public static SQLSetStatement plus(SQLName target) {\n        SQLExpr value = new SQLBinaryOpExpr(target.clone(), SQLBinaryOperator.Add, new SQLIntegerExpr(1));\n        return new SQLSetStatement(target, value);\n    }\n\n    public List<SQLAssignItem> getItems() {\n        return items;\n    }\n\n    public void setItems(List<SQLAssignItem> items) {\n        this.items = items;\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public Option getOption() {\n        return option;\n    }\n\n    public void setOption(Option option) {\n        this.option = option;\n    }\n\n    public boolean isUseSet() {\n        return useSet;\n    }\n\n    public void setUseSet(boolean useSet) {\n        this.useSet = useSet;\n    }\n\n    public void set(SQLExpr target, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(target, value);\n        assignItem.setParent(this);\n        this.items.add(assignItem);\n    }\n\n    public SQLStatement getMaridbSetForStatement() {\n        return maridbSetForStatement;\n    }\n\n    public void setMaridbSetForStatement(SQLStatement maridbSetForStatement) {\n        this.maridbSetForStatement = maridbSetForStatement;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.items);\n            acceptChild(visitor, this.hints);\n            if (maridbSetForStatement != null) {\n                maridbSetForStatement.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(\"SET \");\n\n        for (int i = 0; i < items.size(); ++i) {\n            if (i != 0) {\n                buf.append(\", \");\n            }\n\n            SQLAssignItem item = items.get(i);\n            item.output(buf);\n        }\n    }\n\n    public SQLSetStatement clone() {\n        SQLSetStatement x = new SQLSetStatement();\n        for (SQLAssignItem item : items) {\n            SQLAssignItem item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n        if (hints != null) {\n            for (SQLCommentHint hint : hints) {\n                SQLCommentHint h2 = hint.clone();\n                h2.setParent(x);\n                x.hints.add(h2);\n            }\n        }\n        return x;\n    }\n\n    public List getChildren() {\n        return this.items;\n    }\n\n    public static enum Option {\n        IDENTITY_INSERT,\n        PASSWORD, // mysql\n        GLOBAL,\n        SESSION,\n        LOCAL,\n        PROJECT\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowACLStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowACLStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    protected SQLExprTableSource table;\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (table != null) {\n                table.accept(visitor);\n            }\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (table != null) {\n            return table.replace(expr, target);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowCatalogsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowCatalogsStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    protected SQLExpr like;\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.like = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (like != null) {\n                like.accept(visitor);\n            }\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (like == expr) {\n            setLike(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowColumnsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLShowColumnsStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    private boolean full;\n\n    private SQLName table;\n    private SQLName database;\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public SQLName getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName table) {\n        if (table instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propExpr = (SQLPropertyExpr) table;\n            this.setDatabase((SQLName) propExpr.getOwner());\n            this.table = new SQLIdentifierExpr(propExpr.getName());\n            return;\n        }\n        this.table = table;\n    }\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName database) {\n        this.database = database;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, table);\n            acceptChild(visitor, database);\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (table != null) {\n            children.add(table);\n        }\n        if (database != null) {\n            children.add(database);\n        }\n        if (like != null) {\n            children.add(like);\n        }\n        if (where != null) {\n            children.add(where);\n        }\n        return children;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (table == expr) {\n            setTable((SQLName) target);\n            return true;\n        }\n\n        if (database == expr) {\n            setDatabase((SQLName) target);\n            return true;\n        }\n\n        if (like == expr) {\n            setLike(target);\n            return true;\n        }\n\n        if (where == expr) {\n            setWhere(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowCreateMaterializedViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLShowCreateMaterializedViewStatement extends SQLStatementImpl implements SQLShowStatement {\n    private SQLExpr name;\n\n    public SQLShowCreateMaterializedViewStatement() {\n    }\n\n    public SQLShowCreateMaterializedViewStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowCreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowCreateTableStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    private SQLName name;\n    private boolean all;\n\n    private SQLName likeMapping; // for DLA\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, likeMapping);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLName getLikeMapping() {\n        return likeMapping;\n    }\n\n    public void setLikeMapping(SQLName likeMapping) {\n        this.likeMapping = likeMapping;\n    }\n\n    public boolean isAll() {\n        return all;\n    }\n\n    public void setAll(boolean all) {\n        this.all = all;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n        if (likeMapping == expr) {\n            setLikeMapping((SQLName) target);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowCreateViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowCreateViewStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    private SQLName name;\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName functionName) {\n        this.name = functionName;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (name == expr) {\n            setName((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowDatabasesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowDatabasesStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    private boolean physical;\n    private boolean full;\n\n    private SQLName database;\n    private SQLExpr like;\n    private SQLExpr where;\n\n    private boolean extra;\n\n    public SQLShowDatabasesStatement() {\n    }\n\n    public boolean isPhysical() {\n        return physical;\n    }\n\n    public void setPhysical(boolean physical) {\n        this.physical = physical;\n    }\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName database) {\n        this.database = database;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isExtra() {\n        return extra;\n    }\n\n    public void setExtra(boolean extra) {\n        this.extra = extra;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (database == expr) {\n            setDatabase((SQLName) target);\n            return true;\n        }\n\n        if (like == expr) {\n            setLike(target);\n            return true;\n        }\n\n        if (where == expr) {\n            setWhere(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowErrorsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowErrorsStatement extends SQLStatementImpl implements SQLShowStatement {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowFunctionsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowFunctionsStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    protected SQLExpr like;\n    private SQLName kind;\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.like = x;\n    }\n\n    public SQLName getKind() {\n        return kind;\n    }\n\n    public void setKind(SQLName kind) {\n        this.kind = kind;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (like != null) {\n                like.accept(visitor);\n            }\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (like == expr) {\n            setLike(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowGrantsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowGrantsStatement extends SQLStatementImpl implements SQLShowStatement {\n    protected SQLExpr user;\n    protected SQLExpr on;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, user);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getUser() {\n        return user;\n    }\n\n    public void setUser(SQLExpr user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.user = user;\n    }\n\n    public SQLExpr getOn() {\n        return on;\n    }\n\n    public void setOn(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.on = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowHistoryStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLShowHistoryStatement extends SQLStatementImpl implements SQLShowStatement {\n    protected SQLExprTableSource table;\n    private boolean tables;\n    private List<SQLAssignItem> properties = new ArrayList<>();\n    private List<SQLAssignItem> partitions = new ArrayList<>();\n\n    public SQLShowHistoryStatement() {\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (table != null) {\n                table.accept(visitor);\n            }\n        }\n    }\n\n    public boolean isTables() {\n        return tables;\n    }\n\n    public void setTables(boolean tables) {\n        this.tables = tables;\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowIndexesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class SQLShowIndexesStatement extends SQLStatementImpl implements SQLShowStatement {\n    private SQLExprTableSource table;\n    private List<SQLCommentHint> hints;\n    private SQLExpr where;\n    private String type;\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLName table) {\n        setTable(new SQLExprTableSource(table));\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        this.table = table;\n    }\n\n    public SQLName getDatabase() {\n        SQLExpr expr = table.getExpr();\n        if (expr instanceof SQLPropertyExpr) {\n            return (SQLName) ((SQLPropertyExpr) expr).getOwner();\n        }\n        return null;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public void setDatabase(String database) {\n        table.setSchema(database);\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, table);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowMaterializedViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLShowMaterializedViewStatement extends SQLStatementImpl implements SQLShowStatement {\n    private SQLExpr name;\n    private SQLCharExpr like;\n\n    public SQLShowMaterializedViewStatement() {\n    }\n\n    public SQLShowMaterializedViewStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, like);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLCharExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.like = x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n            children.add(like);\n        }\n        return children;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowOutlinesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowOutlinesStatement extends SQLStatementImpl implements SQLShowStatement {\n    private SQLExpr where;\n    private SQLOrderBy orderBy;\n    private SQLLimit limit;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.orderBy = x;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.limit = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowPackagesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowPackagesStatement extends SQLStatementImpl implements SQLShowStatement {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowPartitionsStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLShowPartitionsStmt extends SQLStatementImpl implements SQLShowStatement {\n    private SQLExprTableSource tableSource;\n\n    private List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>();\n\n    private SQLExpr where;\n\n    public SQLShowPartitionsStmt() {\n        super(DbType.odps);\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExpr table) {\n        if (table == null) {\n            return;\n        }\n\n        setTableSource(new SQLExprTableSource(table));\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        this.tableSource = tableSource;\n    }\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, partition);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowProcessListStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowProcessListStatement extends SQLStatementImpl implements SQLShowStatement {\n    protected boolean mpp;\n    private SQLExpr where;\n    private SQLOrderBy orderBy;\n    private SQLLimit limit;\n    private boolean full;\n\n    public boolean isMpp() {\n        return mpp;\n    }\n\n    public void setMpp(boolean mpp) {\n        this.mpp = mpp;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.orderBy = x;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.limit = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowQueryTaskStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowQueryTaskStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    private boolean full;\n    private SQLExpr where;\n    private SQLOrderBy orderBy;\n    private SQLLimit limit;\n    private SQLExpr user;\n\n    public SQLShowQueryTaskStatement() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n            acceptChild(visitor, user);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    public SQLExpr getUser() {\n        return user;\n    }\n\n    public SQLExpr getFor() {\n        return user;\n    }\n\n    public void setUser(SQLExpr user) {\n        this.user = user;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.orderBy = x;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.limit = x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (where == expr) {\n            setWhere(target);\n            return true;\n        }\n\n        if (user == expr) {\n            setUser(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowRecylebinStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowRecylebinStatement extends SQLStatementImpl implements SQLShowStatement {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowRoleStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowRoleStatement extends SQLStatementImpl implements SQLShowStatement {\n    private SQLName grant;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, grant);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getGrant() {\n        return grant;\n    }\n\n    public void setGrant(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.grant = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowRolesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowRolesStatement extends SQLStatementImpl implements SQLShowStatement {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowSessionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowSessionStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    protected SQLExpr like;\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.like = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (like != null) {\n                like.accept(visitor);\n            }\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (like == expr) {\n            setLike(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\npublic interface SQLShowStatement extends SQLStatement {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowStatisticListStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLShowStatisticListStmt extends SQLStatementImpl implements SQLShowStatement {\n    private SQLExprTableSource tableSource;\n    private boolean full;\n\n    public SQLShowStatisticListStmt() {\n        super(DbType.odps);\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        this.tableSource = tableSource;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSource);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.tableSource);\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowStatisticStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLShowStatisticStmt extends SQLStatementImpl implements SQLShowStatement {\n    private SQLExprTableSource tableSource;\n    private boolean full;\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>(4);\n    private final List<SQLName> columns = new ArrayList<>();\n\n    public SQLShowStatisticStmt() {\n        super(DbType.odps);\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        this.tableSource = tableSource;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSource);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.tableSource);\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public void addPartition(SQLAssignItem partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partitions.add(partition);\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowTableGroupsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowTableGroupsStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    protected SQLName database;\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName database) {\n        if (database != null) {\n            database.setParent(this);\n        }\n\n        this.database = database;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (database == expr) {\n            setDatabase((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowTablesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowTablesStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    private boolean extended;\n    protected SQLName database;\n    protected SQLExpr like;\n\n    // for mysql\n    protected boolean full;\n    protected SQLExpr where;\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public SQLName getFrom() {\n        return database;\n    }\n\n    public void setDatabase(SQLName database) {\n        if (database != null) {\n            database.setParent(this);\n        }\n\n        this.database = database;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        if (like != null) {\n            like.setParent(this);\n        }\n\n        this.like = like;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n            acceptChild(visitor, like);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (database == expr) {\n            setDatabase((SQLName) target);\n            return true;\n        }\n\n        if (like == expr) {\n            setLike(target);\n            return true;\n        }\n\n        if (where == expr) {\n            setWhere(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean isExtended() {\n        return extended;\n    }\n\n    public void setExtended(boolean extended) {\n        this.extended = extended;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowUsersStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowUsersStatement extends SQLStatementImpl implements SQLShowStatement {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowVariantsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowVariantsStatement extends SQLStatementImpl implements SQLShowStatement {\n    private boolean global;\n    private boolean session;\n\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n\n    public boolean isSession() {\n        return session;\n    }\n\n    public void setSession(boolean session) {\n        this.session = session;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowViewsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLShowViewsStatement extends SQLStatementImpl implements SQLShowStatement, SQLReplaceable {\n    protected SQLName database;\n    protected SQLExpr like;\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.database = x;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.like = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n            acceptChild(visitor, like);\n        }\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (database == expr) {\n            setDatabase((SQLName) target);\n            return true;\n        }\n\n        if (like == expr) {\n            setLike(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLStartTransactionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLStartTransactionStatement extends SQLStatementImpl {\n    private boolean consistentSnapshot;\n\n    private boolean begin;\n    private boolean work;\n    private SQLExpr name;\n\n    private List<SQLCommentHint> hints;\n\n    private IsolationLevel isolationLevel;\n    private boolean readOnly;\n\n    public SQLStartTransactionStatement() {\n    }\n\n    public SQLStartTransactionStatement(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public boolean isConsistentSnapshot() {\n        return consistentSnapshot;\n    }\n\n    public void setConsistentSnapshot(boolean consistentSnapshot) {\n        this.consistentSnapshot = consistentSnapshot;\n    }\n\n    public boolean isBegin() {\n        return begin;\n    }\n\n    public void setBegin(boolean begin) {\n        this.begin = begin;\n    }\n\n    public boolean isWork() {\n        return work;\n    }\n\n    public void setWork(boolean work) {\n        this.work = work;\n    }\n\n    public SQLStartTransactionStatement.IsolationLevel getIsolationLevel() {\n        return isolationLevel;\n    }\n\n    public void setIsolationLevel(SQLStartTransactionStatement.IsolationLevel isolationLevel) {\n        this.isolationLevel = isolationLevel;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        if (name != null) {\n            return Collections.<SQLObject>singletonList(name);\n        }\n        return Collections.emptyList();\n    }\n\n    public boolean isReadOnly() {\n        return readOnly;\n    }\n\n    public void setReadOnly(boolean readOnly) {\n        this.readOnly = readOnly;\n    }\n\n    public static enum IsolationLevel {\n        SERIALIZABLE(\"SERIALIZABLE\"),\n        REPEATABLE_READ(\"REPEATABLE READ\"),\n        READ_COMMITTED(\"READ COMMITTED\"),\n        READ_UNCOMMITTED(\"READ UNCOMMITTED\");\n\n        private final String text;\n\n        IsolationLevel(String text) {\n            this.text = text;\n        }\n\n        public String getText() {\n            return text;\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubmitJobStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLSubmitJobStatement extends SQLStatementImpl {\n    private boolean await;\n    private SQLStatement statment;\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statment);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        ArrayList<SQLObject> children = new ArrayList<SQLObject>();\n        children.add(statment);\n        return children;\n    }\n\n    public boolean isAwait() {\n        return await;\n    }\n\n    public void setAwait(boolean await) {\n        this.await = await;\n    }\n\n    public SQLStatement getStatment() {\n        return statment;\n    }\n\n    public void setStatment(SQLStatement statment) {\n        this.statment = statment;\n    }\n\n    public SQLSubmitJobStatement clone() {\n        SQLSubmitJobStatement x = new SQLSubmitJobStatement();\n\n        if (statment != null) {\n            x.setStatment(statment.clone());\n        }\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSubqueryTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLSubqueryTableSource extends SQLTableSourceImpl {\n    protected SQLSelect select;\n    protected boolean lateral;\n    protected List<SQLName> columns = new ArrayList<SQLName>();\n\n    public SQLSubqueryTableSource() {\n    }\n\n    public SQLSubqueryTableSource(String alias) {\n        super(alias);\n    }\n\n    public SQLSubqueryTableSource(SQLSelect select, String alias) {\n        super(alias);\n        this.setSelect(select);\n    }\n\n    public SQLSubqueryTableSource(SQLSelect select) {\n        this.setSelect(select);\n    }\n\n    public SQLSubqueryTableSource(SQLSelectQuery query) {\n        this(new SQLSelect(query));\n    }\n\n    public SQLSubqueryTableSource(SQLSelectQuery query, String alias) {\n        this(new SQLSelect(query), alias);\n    }\n\n    public boolean isLateral() {\n        return lateral;\n    }\n\n    public void setLateral(boolean lateral) {\n        this.lateral = lateral;\n    }\n\n    public SQLSelect getSelect() {\n        return this.select;\n    }\n\n    public void setSelect(SQLSelect x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.select = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.select);\n            super.accept0(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLObject resolveColumn(long columnNameHash) {\n        if (select != null) {\n            SQLSelectQueryBlock queryBlock = select.getQueryBlock();\n            if (queryBlock != null) {\n                return queryBlock.findSelectItem(columnNameHash);\n            }\n        }\n        return null;\n    }\n\n    public void cloneTo(SQLSubqueryTableSource x) {\n        x.alias = alias;\n        x.lateral = lateral;\n\n        if (select != null) {\n            x.select = select.clone();\n            x.select.setParent(x);\n        }\n\n        for (SQLName column : columns) {\n            SQLName c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n    }\n\n    public SQLSubqueryTableSource clone() {\n        SQLSubqueryTableSource x = new SQLSubqueryTableSource();\n        cloneTo(x);\n        return x;\n    }\n\n    public SQLTableSource findTableSourceWithColumn(String columnName) {\n        if (select == null) {\n            return null;\n        }\n\n        SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();\n        if (queryBlock == null) {\n            return null;\n        }\n\n        if (queryBlock.findSelectItem(columnName) != null) {\n            return this;\n        }\n\n        return null;\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnNameHash, String columnName, int option) {\n        if (select == null) {\n            return null;\n        }\n\n        SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();\n        if (queryBlock == null) {\n            return null;\n        }\n\n        if (queryBlock.findSelectItem(columnNameHash) != null) {\n            return this;\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLSubqueryTableSource that = (SQLSubqueryTableSource) o;\n\n        return select != null ? select.equals(that.select) : that.select == null;\n    }\n\n    @Override\n    public int hashCode() {\n        return select != null ? select.hashCode() : 0;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLName column) {\n        column.setParent(this);\n        this.columns.add(column);\n    }\n\n    public SQLColumnDefinition findColumn(long columnNameHash) {\n        SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();\n        if (queryBlock != null) {\n            return queryBlock.findColumn(columnNameHash);\n        } else {\n            if (select.getQuery() instanceof SQLUnionQuery && ((SQLUnionQuery) select.getQuery()).getFirstQueryBlock() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock left = ((SQLUnionQuery) select.getQuery()).getFirstQueryBlock();\n                return ((SQLSelectQueryBlock) left).findColumn(columnNameHash);\n            }\n        }\n        return null;\n    }\n\n    public SQLColumnDefinition findColumn(String columnName) {\n        SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();\n        if (queryBlock != null) {\n            return queryBlock.findColumn(columnName);\n        } else {\n            if (select.getQuery() instanceof SQLUnionQuery && ((SQLUnionQuery) select.getQuery()).getFirstQueryBlock() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock left = ((SQLUnionQuery) select.getQuery()).getFirstQueryBlock();\n                return ((SQLSelectQueryBlock) left).findColumn(columnName);\n            }\n        }\n        return null;\n    }\n\n    public static SQLSubqueryTableSource fixParenthesized(SQLSubqueryTableSource rightTableSourceTmp) {\n        if (rightTableSourceTmp.getSelect() != null && rightTableSourceTmp.getSelect().getQuery() != null && rightTableSourceTmp.getSelect()\n            .getQuery().isParenthesized()) {\n            rightTableSourceTmp.getSelect().getQuery().setParenthesized(false);\n        }\n        return rightTableSourceTmp;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSyncMetaStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLSyncMetaStatement extends SQLStatementImpl {\n    private Boolean restrict;\n    private Boolean ignore;\n\n    private SQLName from;\n    private SQLExpr like;\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, from);\n            acceptChild(v, like);\n        }\n        v.endVisit(this);\n    }\n\n    public Boolean getRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(Boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    public Boolean getIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(Boolean ignore) {\n        this.ignore = ignore;\n    }\n\n    public SQLName getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLName from) {\n        this.from = from;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\npublic interface SQLTableConstraint extends SQLConstraint, SQLTableElement {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableElement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\n\npublic interface SQLTableElement extends SQLObject {\n    SQLTableElement clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableLike.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLTableLike extends SQLObjectImpl implements SQLTableElement {\n    private SQLExprTableSource table;\n    private boolean includeProperties;\n    private boolean includeDistribution;\n    private boolean excludeProperties;\n    private boolean excludeDistribution;\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, table);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLTableLike clone() {\n        SQLTableLike x = new SQLTableLike();\n        if (table != null) {\n            x.setTable(table.clone());\n        }\n\n        return x;\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public boolean isIncludeProperties() {\n        return includeProperties;\n    }\n\n    public void setIncludeProperties(boolean includeProperties) {\n        this.includeProperties = includeProperties;\n    }\n\n    public boolean isExcludeProperties() {\n        return excludeProperties;\n    }\n\n    public void setExcludeProperties(boolean excludeProperties) {\n        this.excludeProperties = excludeProperties;\n    }\n\n    public boolean isIncludeDistribution() {\n        return includeDistribution;\n    }\n\n    public void setIncludeDistribution(boolean includeDistribution) {\n        this.includeDistribution = includeDistribution;\n    }\n\n    public boolean isExcludeDistribution() {\n        return excludeDistribution;\n    }\n\n    public void setExcludeDistribution(boolean excludeDistribution) {\n        this.excludeDistribution = excludeDistribution;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSampling.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLTableSampling extends SQLObjectImpl implements SQLReplaceable {\n    private SQLExpr bucket;\n    private SQLExpr outOf;\n    private SQLExpr on;\n    private SQLExpr percent;\n    private SQLExpr rows;\n    private SQLExpr byteLength;\n\n    private boolean bernoulli;\n    private boolean system;\n\n    public SQLTableSampling clone() {\n        SQLTableSampling x = new SQLTableSampling();\n\n        if (bucket != null) {\n            x.setBucket(bucket.clone());\n        }\n\n        if (outOf != null) {\n            x.setOutOf(outOf.clone());\n        }\n\n        if (on != null) {\n            x.setOn(on.clone());\n        }\n\n        if (percent != null) {\n            x.setPercent(percent.clone());\n        }\n\n        if (rows != null) {\n            x.setRows(rows.clone());\n        }\n\n        if (byteLength != null) {\n            x.setByteLength(byteLength.clone());\n        }\n\n        x.bernoulli = bernoulli;\n        x.system = system;\n        return x;\n    }\n\n    public SQLExpr getBucket() {\n        return bucket;\n    }\n\n    public void setBucket(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.bucket = x;\n    }\n\n    public SQLExpr getOutOf() {\n        return outOf;\n    }\n\n    public void setOutOf(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.outOf = x;\n    }\n\n    public SQLExpr getOn() {\n        return on;\n    }\n\n    public void setOn(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.on = x;\n    }\n\n    public SQLExpr getPercent() {\n        return percent;\n    }\n\n    public void setPercent(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.percent = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, bucket);\n            acceptChild(v, outOf);\n            acceptChild(v, on);\n            acceptChild(v, percent);\n            acceptChild(v, byteLength);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (bucket == expr) {\n            setBucket(target);\n            return true;\n        }\n\n        if (outOf == expr) {\n            setOutOf(target);\n            return true;\n        }\n\n        if (on == expr) {\n            setOn(target);\n            return true;\n        }\n\n        if (percent == expr) {\n            setPercent(target);\n            return true;\n        }\n\n        if (byteLength == expr) {\n            setByteLength(target);\n            return true;\n        }\n        return false;\n    }\n\n    public SQLExpr getByteLength() {\n        return byteLength;\n    }\n\n    public void setByteLength(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.byteLength = x;\n    }\n\n    public SQLExpr getRows() {\n        return rows;\n    }\n\n    public void setRows(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.rows = x;\n    }\n\n    public boolean isBernoulli() {\n        return bernoulli;\n    }\n\n    public void setBernoulli(boolean bernoulli) {\n        this.bernoulli = bernoulli;\n    }\n\n    public boolean isSystem() {\n        return system;\n    }\n\n    public void setSystem(boolean system) {\n        this.system = system;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\n\nimport java.util.List;\n\npublic interface SQLTableSource extends SQLObject {\n    String getAlias();\n\n    long aliasHashCode64();\n\n    void setAlias(String alias);\n\n    List<SQLHint> getHints();\n\n    SQLTableSource clone();\n\n    String computeAlias();\n\n    boolean containsAlias(String alias);\n\n    SQLExpr getFlashback();\n\n    void setFlashback(SQLExpr flashback);\n\n    SQLColumnDefinition findColumn(String columnName);\n\n    SQLColumnDefinition findColumn(long columnNameHash);\n\n    @Deprecated\n    default SQLObject resolveColum(long columnNameHash) {\n        return resolveColumn(columnNameHash);\n    }\n\n    SQLObject resolveColumn(long columnNameHash);\n\n    SQLTableSource findTableSourceWithColumn(String columnName);\n\n    SQLTableSource findTableSourceWithColumn(long columnName_hash);\n\n    SQLTableSource findTableSourceWithColumn(SQLName columnName);\n\n    SQLTableSource findTableSourceWithColumn(long columnName_hash, String name, int option);\n\n    SQLTableSource findTableSource(String alias);\n\n    SQLTableSource findTableSource(long alias_hash);\n\n    SQLPivot getPivot();\n\n    void setPivot(SQLPivot pivot);\n\n    SQLUnpivot getUnpivot();\n\n    void setUnpivot(SQLUnpivot x);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTableSourceImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class SQLTableSourceImpl extends SQLObjectImpl implements SQLTableSource {\n    protected boolean needAsTokenForAlias;\n    protected String alias;\n    protected List<SQLHint> hints;\n    protected SQLExpr flashback;\n    protected long aliasHashCode64;\n    protected SQLPivot pivot;\n    protected SQLUnpivot unpivot;\n\n    public SQLTableSourceImpl() {\n    }\n\n    public SQLTableSourceImpl(String alias) {\n        this.alias = alias;\n    }\n\n    public boolean isNeedAsTokenForAlias() {\n        return needAsTokenForAlias;\n    }\n\n    public void setNeedAsTokenForAlias(boolean needAsTokenForAlias) {\n        this.needAsTokenForAlias = needAsTokenForAlias;\n    }\n\n    public String getAlias() {\n        return this.alias;\n    }\n\n    public String getAlias2() {\n        if (this.alias == null || this.alias.length() == 0) {\n            return alias;\n        }\n\n        char first = alias.charAt(0);\n        if (first == '\"' || first == '\\'') {\n            char[] chars = new char[alias.length() - 2];\n            int len = 0;\n            for (int i = 1; i < alias.length() - 1; ++i) {\n                char ch = alias.charAt(i);\n                if (ch == '\\\\') {\n                    ++i;\n                    ch = alias.charAt(i);\n                }\n                chars[len++] = ch;\n            }\n            return new String(chars, 0, len);\n        }\n\n        return alias;\n    }\n\n    public void setAlias(String alias) {\n        this.alias = alias;\n        this.aliasHashCode64 = 0L;\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n\n        return hints.size();\n    }\n\n    public List<SQLHint> getHints() {\n        if (hints == null) {\n            hints = new ArrayList<SQLHint>(2);\n        }\n        return hints;\n    }\n\n    public void setHints(List<SQLHint> hints) {\n        this.hints = hints;\n    }\n\n    public SQLTableSource clone() {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n\n    public String computeAlias() {\n        return alias;\n    }\n\n    public SQLExpr getFlashback() {\n        return flashback;\n    }\n\n    public void setFlashback(SQLExpr flashback) {\n        if (flashback != null) {\n            flashback.setParent(this);\n        }\n        this.flashback = flashback;\n    }\n\n    public boolean containsAlias(String alias) {\n        if (SQLUtils.nameEquals(this.alias, alias)) {\n            return true;\n        }\n\n        return false;\n    }\n\n    public long aliasHashCode64() {\n        if (aliasHashCode64 == 0\n                && alias != null) {\n            aliasHashCode64 = FnvHash.hashCode64(alias);\n        }\n        return aliasHashCode64;\n    }\n\n    public SQLColumnDefinition findColumn(String columnName) {\n        if (columnName == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(columnName);\n        return findColumn(hash);\n    }\n\n    public SQLColumnDefinition findColumn(long columnNameHash) {\n        return null;\n    }\n\n    public SQLObject resolveColumn(long columnNameHash) {\n        return findColumn(columnNameHash);\n    }\n\n    public SQLTableSource findTableSourceWithColumn(String columnName) {\n        if (columnName == null) {\n            return null;\n        }\n\n        long hash = FnvHash.hashCode64(columnName);\n        return findTableSourceWithColumn(hash, columnName, 0);\n    }\n\n    public SQLTableSource findTableSourceWithColumn(SQLName columnName) {\n        if (columnName instanceof SQLIdentifierExpr) {\n            return findTableSourceWithColumn(\n                    columnName.nameHashCode64(), columnName.getSimpleName(), 0);\n        }\n\n        if (columnName instanceof SQLPropertyExpr) {\n            SQLExpr owner = ((SQLPropertyExpr) columnName).getOwner();\n            if (owner instanceof SQLIdentifierExpr) {\n                return findTableSource(((SQLIdentifierExpr) owner).nameHashCode64());\n            }\n        }\n\n        return null;\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnNameHash) {\n        return findTableSourceWithColumn(columnNameHash, null, 0);\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnNameHash, String columnName, int option) {\n        return null;\n    }\n\n    public SQLTableSource findTableSource(String alias) {\n        long hash = FnvHash.hashCode64(alias);\n        return findTableSource(hash);\n    }\n\n    public SQLTableSource findTableSource(long alias_hash) {\n        long hash = this.aliasHashCode64();\n        if (hash != 0 && hash == alias_hash) {\n            return this;\n        }\n        return null;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLTableSourceImpl that = (SQLTableSourceImpl) o;\n\n        if (aliasHashCode64() != that.aliasHashCode64()) {\n            return false;\n        }\n        if (hints != null ? !hints.equals(that.hints) : that.hints != null) {\n            return false;\n        }\n        return flashback != null ? flashback.equals(that.flashback) : that.flashback == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = (hints != null ? hints.hashCode() : 0);\n        result = 31 * result + (flashback != null ? flashback.hashCode() : 0);\n        result = 31 * result + (int) (aliasHashCode64() ^ (aliasHashCode64() >>> 32));\n        return result;\n    }\n\n    @Override\n    public SQLPivot getPivot() {\n        return pivot;\n    }\n\n    @Override\n    public void setPivot(SQLPivot x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.pivot = x;\n    }\n\n    public SQLUnpivot getUnpivot() {\n        return unpivot;\n    }\n\n    public void setUnpivot(SQLUnpivot x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.unpivot = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.flashback);\n            acceptChild(visitor, this.pivot);\n            acceptChild(visitor, this.unpivot);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLTruncateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLTruncateStatement extends SQLStatementImpl {\n    protected List<SQLExprTableSource> tableSources = new ArrayList<SQLExprTableSource>(2);\n    private boolean purgeSnapshotLog;\n    private boolean only;\n    private Boolean restartIdentity;\n    private Boolean cascade;\n\n    // db2\n    private boolean dropStorage;\n    private boolean reuseStorage;\n    private boolean immediate;\n    private boolean ignoreDeleteTriggers;\n    private boolean restrictWhenDeleteTriggers;\n    private boolean continueIdentity;\n    protected boolean ifExists;\n    protected List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>();\n\n    // adb\n    protected boolean partitionAll;\n    protected List<SQLIntegerExpr> partitionsForADB = new ArrayList<SQLIntegerExpr>();\n\n    public SQLTruncateStatement() {\n    }\n\n    public SQLTruncateStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void setTableSources(List<SQLExprTableSource> tableSources) {\n        this.tableSources = tableSources;\n    }\n\n    public void addTableSource(SQLName name) {\n        SQLExprTableSource tableSource = new SQLExprTableSource(name);\n        tableSource.setParent(this);\n        this.tableSources.add(tableSource);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSources);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isPurgeSnapshotLog() {\n        return purgeSnapshotLog;\n    }\n\n    public void setPurgeSnapshotLog(boolean purgeSnapshotLog) {\n        this.purgeSnapshotLog = purgeSnapshotLog;\n    }\n\n    public boolean isOnly() {\n        return only;\n    }\n\n    public void setOnly(boolean only) {\n        this.only = only;\n    }\n\n    public Boolean getRestartIdentity() {\n        return restartIdentity;\n    }\n\n    public void setRestartIdentity(Boolean restartIdentity) {\n        this.restartIdentity = restartIdentity;\n    }\n\n    public Boolean getCascade() {\n        return cascade;\n    }\n\n    public void setCascade(Boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isDropStorage() {\n        return dropStorage;\n    }\n\n    public void setDropStorage(boolean dropStorage) {\n        this.dropStorage = dropStorage;\n    }\n\n    public boolean isReuseStorage() {\n        return reuseStorage;\n    }\n\n    public void setReuseStorage(boolean reuseStorage) {\n        this.reuseStorage = reuseStorage;\n    }\n\n    public boolean isImmediate() {\n        return immediate;\n    }\n\n    public void setImmediate(boolean immediate) {\n        this.immediate = immediate;\n    }\n\n    public boolean isIgnoreDeleteTriggers() {\n        return ignoreDeleteTriggers;\n    }\n\n    public void setIgnoreDeleteTriggers(boolean ignoreDeleteTriggers) {\n        this.ignoreDeleteTriggers = ignoreDeleteTriggers;\n    }\n\n    public boolean isRestrictWhenDeleteTriggers() {\n        return restrictWhenDeleteTriggers;\n    }\n\n    public void setRestrictWhenDeleteTriggers(boolean restrictWhenDeleteTriggers) {\n        this.restrictWhenDeleteTriggers = restrictWhenDeleteTriggers;\n    }\n\n    public boolean isContinueIdentity() {\n        return continueIdentity;\n    }\n\n    public void setContinueIdentity(boolean continueIdentity) {\n        this.continueIdentity = continueIdentity;\n    }\n\n    @Override\n    public List getChildren() {\n        return tableSources;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public boolean isPartitionAll() {\n        return partitionAll;\n    }\n\n    public void setPartitionAll(boolean partitionAll) {\n        this.partitionAll = partitionAll;\n    }\n\n    public List<SQLIntegerExpr> getPartitionsForADB() {\n        return partitionsForADB;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionOperator.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\npublic enum SQLUnionOperator {\n    UNION(\"UNION\"),\n    UNION_ALL(\"UNION ALL\"),\n    MINUS(\"MINUS\"),\n    MINUS_DISTINCT(\"MINUS DISTINCT\"),\n    MINUS_ALL(\"MINUS ALL\"),\n    EXCEPT(\"EXCEPT\"),\n    EXCEPT_ALL(\"EXCEPT ALL\"),\n    EXCEPT_DISTINCT(\"EXCEPT DISTINCT\"),\n    INTERSECT(\"INTERSECT\"),\n    INTERSECT_ALL(\"INTERSECT ALL\"),\n    INTERSECT_DISTINCT(\"INTERSECT DISTINCT\"),\n    DISTINCT(\"UNION DISTINCT\");\n\n    public final String name;\n    public final String nameLCase;\n\n    private SQLUnionOperator(String name) {\n        this.name = name;\n        this.nameLCase = name.toLowerCase();\n    }\n\n    public String toString() {\n        return name;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLDbTypedObject;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.*;\n\npublic class SQLUnionQuery extends SQLSelectQueryBase implements SQLDbTypedObject {\n    protected SQLWithSubqueryClause with;\n    private List<SQLSelectQuery> relations = new ArrayList<SQLSelectQuery>();\n    private SQLUnionOperator operator = SQLUnionOperator.UNION;\n    private SQLOrderBy orderBy;\n\n    private SQLLimit limit;\n    private DbType dbType;\n\n    public SQLUnionOperator getOperator() {\n        return operator;\n    }\n\n    public void setOperator(SQLUnionOperator operator) {\n        this.operator = operator;\n    }\n\n    public SQLUnionQuery() {\n    }\n\n    public SQLUnionQuery(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLUnionQuery(SQLSelectQuery left, SQLUnionOperator operator, SQLSelectQuery right) {\n        this.setLeft(left);\n        this.operator = operator;\n        this.setRight(right);\n    }\n\n    public List<SQLSelectQuery> getRelations() {\n        return relations;\n    }\n\n    public boolean isEmpty() {\n        return relations.isEmpty();\n    }\n\n    public void addRelation(SQLSelectQuery relation) {\n        if (relation != null) {\n            relation.setParent(this);\n        }\n\n        relations.add(relation);\n    }\n\n    public SQLSelectQuery getLeft() {\n        if (relations.isEmpty()) {\n            return null;\n        }\n        return relations.get(0);\n    }\n\n    public void setLeft(SQLSelectQuery left) {\n        if (left != null) {\n            left.setParent(this);\n        }\n\n        if (relations.isEmpty()) {\n            relations.add(left);\n        } else if (relations.size() <= 2) {\n            relations.set(0, left);\n        } else {\n            throw new UnsupportedOperationException(\"multi-union\");\n        }\n    }\n\n    public SQLSelectQuery getRight() {\n        if (relations.size() < 2) {\n            return null;\n        }\n        if (relations.size() == 2) {\n            return relations.get(1);\n        }\n\n        throw new UnsupportedOperationException(\"multi-union\");\n    }\n\n    public void setRight(SQLSelectQuery right) {\n        if (right != null) {\n            right.setParent(this);\n        }\n\n        if (relations.isEmpty()) {\n            relations.add(null);\n        }\n\n        if (relations.size() == 1) {\n            relations.add(right);\n        } else if (relations.size() == 2) {\n            relations.set(1, right);\n        } else {\n            throw new UnsupportedOperationException(\"multi-union\");\n        }\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        if (orderBy != null) {\n            orderBy.setParent(this);\n        }\n        this.orderBy = orderBy;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (with != null) {\n                with.accept(visitor);\n            }\n\n            for (SQLSelectQuery relation : relations) {\n                relation.accept(visitor);\n            }\n\n            if (orderBy != null) {\n                orderBy.accept(visitor);\n            }\n\n            if (limit != null) {\n                limit.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        if (limit != null) {\n            limit.setParent(this);\n        }\n        this.limit = limit;\n    }\n\n    public SQLUnionQuery clone() {\n        SQLUnionQuery x = new SQLUnionQuery();\n\n        x.parenthesized = parenthesized;\n        if (with != null) {\n            x.setWith(with.clone());\n        }\n\n        for (SQLSelectQuery relation : relations) {\n            SQLSelectQuery r = relation.clone();\n            r.setParent(x);\n            x.relations.add(r);\n        }\n\n        x.operator = operator;\n\n        if (orderBy != null) {\n            x.setOrderBy(orderBy.clone());\n        }\n\n        if (limit != null) {\n            x.setLimit(limit.clone());\n        }\n\n        x.dbType = dbType;\n\n        return x;\n    }\n\n    public SQLSelectQueryBlock getFirstQueryBlock() {\n        SQLSelectQuery left = getLeft();\n\n        if (left instanceof SQLSelectQueryBlock) {\n            return (SQLSelectQueryBlock) left;\n        }\n\n        if (left instanceof SQLUnionQuery) {\n            return ((SQLUnionQuery) left).getFirstQueryBlock();\n        }\n\n        return null;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public boolean replace(SQLSelectQuery cmp, SQLSelectQuery target) {\n        for (int i = 0; i < relations.size(); i++) {\n            SQLSelectQuery r = relations.get(i);\n            if (r == cmp) {\n                if (cmp != null) {\n                    cmp.setParent(this);\n                }\n                relations.set(i, cmp);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public List<SQLSelectQuery> getChildren() {\n        boolean bracket = this.parenthesized && !(parent instanceof SQLUnionQueryTableSource);\n\n        if (relations.size() > 2) {\n            return relations;\n        }\n\n        SQLSelectQuery left = getLeft();\n        SQLSelectQuery right = getRight();\n\n        if ((!bracket)\n                && left instanceof SQLUnionQuery\n                && ((SQLUnionQuery) left).getOperator() == operator\n                && !right.isParenthesized()\n                && orderBy == null) {\n            SQLUnionQuery leftUnion = (SQLUnionQuery) left;\n\n            ArrayList<SQLSelectQuery> rights = new ArrayList<SQLSelectQuery>();\n            rights.add(right);\n\n            for (; ; ) {\n                SQLSelectQuery leftLeft = leftUnion.getLeft();\n                SQLSelectQuery leftRight = leftUnion.getRight();\n\n                if ((!leftUnion.isParenthesized())\n                        && leftUnion.getOrderBy() == null\n                        && (!leftLeft.isParenthesized())\n                        && (!leftRight.isParenthesized())\n                        && leftLeft instanceof SQLUnionQuery\n                        && ((SQLUnionQuery) leftLeft).getOperator() == operator) {\n                    rights.add(leftRight);\n                    leftUnion = (SQLUnionQuery) leftLeft;\n                    continue;\n                } else {\n                    rights.add(leftRight);\n                    rights.add(leftLeft);\n                }\n                break;\n            }\n            Collections.reverse(rights);\n\n            return rights;\n        }\n\n        return Arrays.asList(left, right);\n    }\n\n    public SQLWithSubqueryClause getWith() {\n        return with;\n    }\n\n    public void setWith(SQLWithSubqueryClause x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.with = x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLUnionQuery that = (SQLUnionQuery) o;\n\n        if (parenthesized != that.parenthesized) {\n            return false;\n        }\n        if (!Objects.equals(with, that.with)) {\n            return false;\n        }\n        if (!Objects.equals(relations, that.relations)) {\n            return false;\n        }\n        if (operator != that.operator) {\n            return false;\n        }\n        if (!Objects.equals(orderBy, that.orderBy)) {\n            return false;\n        }\n        if (!Objects.equals(limit, that.limit)) {\n            return false;\n        }\n        return dbType == that.dbType;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = (parenthesized ? 1 : 0);\n        result = 31 * result + (with != null ? with.hashCode() : 0);\n        result = 31 * result + (relations != null ? relations.hashCode() : 0);\n        result = 31 * result + (operator != null ? operator.hashCode() : 0);\n        result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);\n        result = 31 * result + (limit != null ? limit.hashCode() : 0);\n        result = 31 * result + (dbType != null ? dbType.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQueryTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLUnionQueryTableSource extends SQLTableSourceImpl {\n    private SQLUnionQuery union;\n    protected List<SQLName> columns = new ArrayList<SQLName>();\n\n    public SQLUnionQueryTableSource() {\n    }\n\n    public SQLUnionQueryTableSource(String alias) {\n        super(alias);\n    }\n\n    public SQLUnionQueryTableSource(SQLUnionQuery union, String alias) {\n        super(alias);\n        this.setUnion(union);\n    }\n\n    public SQLUnionQueryTableSource(SQLUnionQuery union) {\n        this.setUnion(union);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, union);\n            acceptChild(visitor, columns);\n            super.accept0(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(\"(\");\n        this.union.output(buf);\n        buf.append(\")\");\n    }\n\n    public SQLUnionQuery getUnion() {\n        return union;\n    }\n\n    public void setUnion(SQLUnionQuery union) {\n        if (union != null) {\n            union.setParent(this);\n        }\n        this.union = union;\n    }\n\n    @Override\n    public SQLUnionQueryTableSource clone() {\n        SQLUnionQueryTableSource x = new SQLUnionQueryTableSource(this.union.clone(), alias);\n\n        if (this.flashback != null) {\n            x.setFlashback(this.flashback.clone());\n        }\n\n        if (this.hints != null) {\n            for (SQLHint e : this.hints) {\n                SQLHint e2 = e.clone();\n                e2.setParent(x);\n                x.getHints().add(e2);\n            }\n        }\n\n        return x;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        SQLUnionQueryTableSource that = (SQLUnionQueryTableSource) o;\n\n        if (union != null ? !union.equals(that.union) : that.union != null) {\n            return false;\n        }\n        return columns != null ? columns.equals(that.columns) : that.columns == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = super.hashCode();\n        result = 31 * result + (union != null ? union.hashCode() : 0);\n        result = 31 * result + (columns != null ? columns.hashCode() : 0);\n        return result;\n    }\n\n    public SQLTableSource findTableSourceWithColumn(long columnNameHash, String columnName, int option) {\n        if (union == null) {\n            return null;\n        }\n\n        final SQLSelectQueryBlock firstQueryBlock = union.getFirstQueryBlock();\n        if (firstQueryBlock != null) {\n            final SQLSelectItem selectItem = firstQueryBlock.findSelectItem(columnNameHash);\n            if (selectItem != null) {\n                return this;\n            }\n        }\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLIndexDefinition;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint, SQLTableElement {\n    protected final SQLIndexDefinition indexDefinition = new SQLIndexDefinition();\n\n    protected boolean disableNovalidate;\n    public SQLUnique() {\n        indexDefinition.setParent(this);\n    }\n\n    // Override name and comment in constraint impl.\n    @Override\n    public SQLName getName() {\n        return indexDefinition.getName();\n    }\n\n    @Override\n    public void setName(SQLName name) {\n        indexDefinition.setName(name);\n    }\n\n    @Override\n    public void setName(String name) {\n        this.setName(new SQLIdentifierExpr(name));\n    }\n\n    public boolean isDisableNovalidate() {\n        return disableNovalidate;\n    }\n\n    public void setDisableNovalidate(boolean disableNovalidate) {\n        this.disableNovalidate = disableNovalidate;\n    }\n\n    @Override\n    public SQLExpr getComment() {\n        if (indexDefinition.hasOptions()) {\n            return indexDefinition.getOptions().getComment();\n        }\n        return null;\n    }\n\n    @Override\n    public void setComment(SQLExpr x) {\n        indexDefinition.getOptions().setComment(x);\n    }\n\n    public SQLIndexDefinition getIndexDefinition() {\n        return indexDefinition;\n    }\n\n    public List<SQLSelectOrderByItem> getColumns() {\n        return indexDefinition.getColumns();\n    }\n\n    public void addColumn(SQLExpr column) {\n        if (column == null) {\n            return;\n        }\n\n        addColumn(new SQLSelectOrderByItem(column));\n    }\n\n    public void addColumn(SQLSelectOrderByItem column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        indexDefinition.getColumns().add(column);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getName());\n            acceptChild(visitor, getColumns());\n            acceptChild(visitor, getCovering());\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean containsColumn(String column) {\n        for (SQLSelectOrderByItem item : getColumns()) {\n            SQLExpr expr = item.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                if (SQLUtils.nameEquals(((SQLIdentifierExpr) expr).getName(), column)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public boolean containsColumn(long columnNameHash) {\n        for (SQLSelectOrderByItem item : getColumns()) {\n            SQLExpr expr = item.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) expr).nameHashCode64() == columnNameHash) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public void cloneTo(SQLUnique x) {\n        super.cloneTo(x);\n\n        indexDefinition.cloneTo(x.indexDefinition);\n    }\n\n    public SQLUnique clone() {\n        SQLUnique x = new SQLUnique();\n        cloneTo(x);\n        return x;\n    }\n\n    public void simplify() {\n        super.simplify();\n\n        for (SQLSelectOrderByItem item : getColumns()) {\n            SQLExpr column = item.getExpr();\n            if (column instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) column;\n                String columnName = identExpr.getName();\n                String normalized = SQLUtils.normalize(columnName, dbType);\n                if (normalized != columnName) {\n                    item.setExpr(new SQLIdentifierExpr(columnName));\n                }\n            }\n        }\n    }\n\n    public boolean applyColumnRename(SQLName columnName, SQLColumnDefinition to) {\n        for (SQLSelectOrderByItem orderByItem : getColumns()) {\n            SQLExpr expr = orderByItem.getExpr();\n            if (expr instanceof SQLName\n                    && SQLUtils.nameEquals((SQLName) expr, columnName)) {\n                orderByItem.setExpr(to.getName().clone());\n                return true;\n            }\n\n            if (expr instanceof SQLMethodInvokeExpr\n                    && SQLUtils.nameEquals(((SQLMethodInvokeExpr) expr).getMethodName(), columnName.getSimpleName())) {\n                // More complex when with key length.\n                if (1 == ((SQLMethodInvokeExpr) expr).getArguments().size() &&\n                        ((SQLMethodInvokeExpr) expr).getArguments().get(0) instanceof SQLIntegerExpr) {\n                    if (to.getDataType().hasKeyLength() &&\n                            1 == to.getDataType().getArguments().size() &&\n                            to.getDataType().getArguments().get(0) instanceof SQLIntegerExpr) {\n                        int newKeyLength = ((SQLIntegerExpr) to.getDataType().getArguments().get(0)).getNumber().intValue();\n                        int oldKeyLength = ((SQLIntegerExpr) ((SQLMethodInvokeExpr) expr).getArguments().get(0)).getNumber().intValue();\n                        if (newKeyLength > oldKeyLength) {\n                            // Change name and keep key length.\n                            ((SQLMethodInvokeExpr) expr).setMethodName(to.getName().getSimpleName());\n                            return true;\n                        }\n                    }\n                    // Remove key length.\n                    orderByItem.setExpr(to.getName().clone());\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public boolean applyDropColumn(SQLName columnName) {\n        for (int i = getColumns().size() - 1; i >= 0; i--) {\n            SQLExpr expr = getColumns().get(i).getExpr();\n            if (expr instanceof SQLName\n                    && SQLUtils.nameEquals((SQLName) expr, columnName)) {\n                getColumns().remove(i);\n                return true;\n            }\n\n            if (expr instanceof SQLMethodInvokeExpr\n                    && SQLUtils.nameEquals(((SQLMethodInvokeExpr) expr).getMethodName(), columnName.getSimpleName())) {\n                getColumns().remove(i);\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public List<SQLName> getCovering() {\n        return indexDefinition.getCovering();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport java.util.List;\n\npublic interface SQLUniqueConstraint extends SQLConstraint {\n    List<SQLSelectOrderByItem> getColumns();\n\n    boolean containsColumn(String column);\n\n    boolean containsColumn(long columnNameHash);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnnestTableSource.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLUnnestTableSource extends SQLTableSourceImpl\n        implements SQLReplaceable {\n    private final List<SQLExpr> items = new ArrayList<SQLExpr>();\n    protected List<SQLName> columns = new ArrayList<SQLName>();\n    private boolean ordinality;\n    private SQLExpr offset;\n\n    public SQLUnnestTableSource() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, items);\n            acceptChild(v, columns);\n            acceptChild(v, offset);\n            super.accept0(v);\n        }\n        v.endVisit(this);\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLName column) {\n        column.setParent(this);\n        this.columns.add(column);\n    }\n\n    public boolean isOrdinality() {\n        return ordinality;\n    }\n\n    public void setOrdinality(boolean ordinality) {\n        this.ordinality = ordinality;\n    }\n\n    public List<SQLExpr> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLExpr item) {\n        item.setParent(this);\n        this.items.add(item);\n    }\n\n    public void setItem(int i, SQLExpr item) {\n        this.items.set(i, item);\n    }\n\n    public SQLExpr getOffset() {\n        return offset;\n    }\n\n    public void setOffset(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.offset = x;\n    }\n\n    public SQLUnnestTableSource clone() {\n        SQLUnnestTableSource x = new SQLUnnestTableSource();\n\n        for (SQLExpr item : items) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n\n        for (SQLName column : columns) {\n            SQLName c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n        x.alias = alias;\n\n        if (offset != null) {\n            x.setOffset(offset);\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < items.size(); i++) {\n            if (items.get(i) == expr) {\n                target.setParent(this);\n                items.set(i, target);\n                return true;\n            }\n        }\n\n        if (target instanceof SQLName) {\n            SQLName targetName = (SQLName) target;\n            for (int i = 0; i < columns.size(); i++) {\n                if (columns.get(i) == expr) {\n                    target.setParent(this);\n                    columns.set(i, targetName);\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateSetItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLUpdateSetItem extends SQLObjectImpl implements SQLReplaceable {\n    private SQLExpr column;\n    private SQLExpr value;\n\n    public SQLUpdateSetItem() {\n    }\n\n    public SQLUpdateSetItem(SQLExpr column, SQLExpr value) {\n        this.setColumn(column);\n        this.setValue(value);\n    }\n\n    public SQLExpr getColumn() {\n        return column;\n    }\n\n    public void cloneTo(SQLUpdateSetItem x) {\n        if (column != null) {\n            x.column = column.clone();\n            x.column.setParent(x);\n        }\n        if (value != null) {\n            x.value = value.clone();\n            x.value.setParent(x);\n        }\n    }\n\n    @Override\n    public SQLUpdateSetItem clone() {\n        SQLUpdateSetItem x = new SQLUpdateSetItem();\n        cloneTo(x);\n        return x;\n    }\n\n    public void setColumn(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.column = x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.value = value;\n    }\n\n    public void output(StringBuilder buf) {\n        column.output(buf);\n        buf.append(\" = \");\n        value.output(buf);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (column != null) {\n                column.accept(visitor);\n            }\n\n            if (value != null) {\n                value.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public boolean columnMatch(String column) {\n        if (this.column instanceof SQLIdentifierExpr) {\n            return ((SQLIdentifierExpr) this.column).nameEquals(column);\n        } else if (this.column instanceof SQLPropertyExpr) {\n            ((SQLPropertyExpr) this.column).nameEquals(column);\n        }\n        return false;\n    }\n\n    public boolean columnMatch(long columnHash) {\n        if (this.column instanceof SQLName) {\n            return ((SQLName) this.column).nameHashCode64() == columnHash;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (expr == this.column) {\n            this.setColumn(target);\n            return true;\n        }\n\n        if (expr == this.value) {\n            setValue(target);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLUpdateSetItem that = (SQLUpdateSetItem) o;\n\n        if (column != null ? !column.equals(that.column) : that.column != null) {\n            return false;\n        }\n        return value != null ? value.equals(that.value) : that.value == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = column != null ? column.hashCode() : 0;\n        result = 31 * result + (value != null ? value.hashCode() : 0);\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUpdateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExprGroup;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLUpdateStatement extends SQLStatementImpl implements SQLReplaceable {\n    protected SQLWithSubqueryClause with; // for pg\n\n    protected final List<SQLUpdateSetItem> items = new ArrayList<SQLUpdateSetItem>();\n    protected SQLExpr where;\n    protected SQLLimit limit;\n    protected SQLTableSource from;\n\n    protected SQLTableSource tableSource;\n    protected List<SQLExpr> returning;\n\n    protected List<SQLAssignItem> partitions;\n\n    // for mysql\n    protected SQLOrderBy orderBy;\n\n    public SQLUpdateStatement() {\n    }\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        if (limit != null) {\n            limit.setParent(this);\n        }\n        this.limit = limit;\n    }\n    public void cloneTo(SQLUpdateStatement x) {\n        x.dbType = dbType;\n        x.afterSemi = afterSemi;\n\n        if (with != null) {\n            x.setWith(with.clone());\n            x.with.setParent(x);\n        }\n\n        if (where != null) {\n            x.where = where.clone();\n            x.where.setParent(x);\n        }\n        if (tableSource != null) {\n            x.setTableSource(tableSource.clone());\n            x.tableSource.setParent(x);\n        }\n\n        for (SQLUpdateSetItem item : items) {\n            SQLUpdateSetItem clone = item.clone();\n            clone.setParent(x);\n            x.getItems().add(clone);\n        }\n\n        if (returning != null) {\n            for (SQLExpr item : returning) {\n                SQLExpr clone = item.clone();\n                clone.setParent(x);\n                x.getReturning().add(clone);\n            }\n        }\n\n        if (orderBy != null) {\n            x.orderBy = orderBy.clone();\n            x.orderBy.setParent(x);\n        }\n    }\n\n    public SQLUpdateStatement clone() {\n        SQLUpdateStatement x = new SQLUpdateStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    public SQLUpdateStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExpr expr) {\n        this.setTableSource(new SQLExprTableSource(expr));\n    }\n\n    public void setTableSource(SQLTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public SQLName getTableName() {\n        return this.getTableName(false);\n    }\n\n    public SQLName getTableName(boolean lastFlag) {\n        if (tableSource instanceof SQLExprTableSource) {\n            return ((SQLExprTableSource) tableSource).getName();\n        }\n\n        if (tableSource instanceof SQLJoinTableSource) {\n            SQLTableSource left = ((SQLJoinTableSource) tableSource).getLeft();\n            if (left instanceof SQLExprTableSource) {\n                return ((SQLExprTableSource) left).getName();\n            } else if (lastFlag && left instanceof SQLJoinTableSource) {\n                return getLastTableName(left);\n            }\n        }\n        return null;\n    }\n\n    private SQLName getLastTableName(SQLTableSource tableSource) {\n        SQLTableSource left = ((SQLJoinTableSource) tableSource).getLeft();\n        if (left instanceof SQLExprTableSource) {\n            return ((SQLExprTableSource) left).getName();\n        } else if (left instanceof SQLJoinTableSource) {\n            return getLastTableName(left);\n        }\n        return null;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public void setPartitions(List<SQLAssignItem> partitions) {\n        this.partitions = partitions;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        if (where != null) {\n            where.setParent(this);\n        }\n        this.where = where;\n    }\n\n    public List<SQLUpdateSetItem> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLUpdateSetItem item) {\n        this.items.add(item);\n        item.setParent(this);\n    }\n\n    public List<SQLExpr> getReturning() {\n        if (returning == null) {\n            returning = new ArrayList<SQLExpr>(2);\n        }\n\n        return returning;\n    }\n\n    public SQLTableSource getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLTableSource from) {\n        if (from != null) {\n            from.setParent(this);\n        }\n        this.from = from;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor visitor) {\n        if (with != null) {\n            with.accept(visitor);\n        }\n\n        if (tableSource != null) {\n            tableSource.accept(visitor);\n        }\n\n        if (from != null) {\n            from.accept(visitor);\n        }\n\n        for (int i = 0; i < items.size(); i++) {\n            SQLUpdateSetItem item = items.get(i);\n            if (item != null) {\n                item.accept(visitor);\n            }\n        }\n\n        if (where != null) {\n            where.accept(visitor);\n        }\n\n        if (orderBy != null) {\n            orderBy.accept(visitor);\n        }\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (tableSource != null) {\n            children.add(tableSource);\n        }\n        if (from != null) {\n            children.add(from);\n        }\n        children.addAll(this.items);\n        if (where != null) {\n            children.add(where);\n        }\n        if (orderBy != null) {\n            children.add(orderBy);\n        }\n        return children;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (where == expr) {\n            setWhere(target);\n            return true;\n        }\n\n        if (returning != null) {\n            for (int i = 0; i < returning.size(); i++) {\n                if (returning.get(i) == expr) {\n                    target.setParent(this);\n                    returning.set(i, target);\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        if (orderBy != null) {\n            orderBy.setParent(this);\n        }\n        this.orderBy = orderBy;\n    }\n\n    public SQLWithSubqueryClause getWith() {\n        return with;\n    }\n\n    public void setWith(SQLWithSubqueryClause with) {\n        if (with != null) {\n            with.setParent(this);\n        }\n        this.with = with;\n    }\n\n    public void addCondition(String conditionSql) {\n        if (conditionSql == null || conditionSql.length() == 0) {\n            return;\n        }\n\n        SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);\n        addCondition(condition);\n    }\n\n    public void addCondition(SQLExpr expr) {\n        if (expr == null) {\n            return;\n        }\n\n        this.setWhere(SQLBinaryOpExpr.and(where, expr));\n    }\n\n    public boolean removeCondition(String conditionSql) {\n        if (conditionSql == null || conditionSql.length() == 0) {\n            return false;\n        }\n\n        SQLExpr condition = SQLUtils.toSQLExpr(conditionSql, dbType);\n\n        return removeCondition(condition);\n    }\n\n    public boolean removeCondition(SQLExpr condition) {\n        if (condition == null) {\n            return false;\n        }\n\n        if (where instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) where;\n\n            int removedCount = 0;\n            List<SQLExpr> items = group.getItems();\n            for (int i = items.size() - 1; i >= 0; i--) {\n                if (items.get(i).equals(condition)) {\n                    items.remove(i);\n                    removedCount++;\n                }\n            }\n            if (items.isEmpty()) {\n                where = null;\n            }\n\n            return removedCount > 0;\n        }\n\n        if (where instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpWhere = (SQLBinaryOpExpr) where;\n            SQLBinaryOperator operator = binaryOpWhere.getOperator();\n            if (operator == SQLBinaryOperator.BooleanAnd || operator == SQLBinaryOperator.BooleanOr) {\n                List<SQLExpr> items = SQLBinaryOpExpr.split(binaryOpWhere);\n\n                int removedCount = 0;\n                for (int i = items.size() - 1; i >= 0; i--) {\n                    SQLExpr item = items.get(i);\n                    if (item.equals(condition)) {\n                        if (SQLUtils.replaceInParent(item, null)) {\n                            removedCount++;\n                        }\n                    }\n                }\n\n                return removedCount > 0;\n            }\n        }\n\n        if (condition.equals(where)) {\n            where = null;\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLUpdateStatement that = (SQLUpdateStatement) o;\n\n        if (with != null ? !with.equals(that.with) : that.with != null) {\n            return false;\n        }\n        if (!items.equals(that.items)) {\n            return false;\n        }\n        if (where != null ? !where.equals(that.where) : that.where != null) {\n            return false;\n        }\n        if (from != null ? !from.equals(that.from) : that.from != null) {\n            return false;\n        }\n        if (tableSource != null ? !tableSource.equals(that.tableSource) : that.tableSource != null) {\n            return false;\n        }\n        if (returning != null ? !returning.equals(that.returning) : that.returning != null) {\n            return false;\n        }\n        return orderBy != null ? orderBy.equals(that.orderBy) : that.orderBy == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = with != null ? with.hashCode() : 0;\n        result = 31 * result + items.hashCode();\n        result = 31 * result + (where != null ? where.hashCode() : 0);\n        result = 31 * result + (from != null ? from.hashCode() : 0);\n        result = 31 * result + (tableSource != null ? tableSource.hashCode() : 0);\n        result = 31 * result + (returning != null ? returning.hashCode() : 0);\n        result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);\n        return result;\n    }\n\n    public boolean addWhere(SQLExpr where) {\n        if (where == null) {\n            return false;\n        }\n\n        this.addCondition(where);\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLUseStatement extends SQLStatementImpl implements SQLReplaceable {\n    private SQLName database;\n\n    public SQLUseStatement() {\n    }\n\n    public SQLUseStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.database = x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.database == expr) {\n            setDatabase((SQLName) target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(database);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLValuesQuery.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLListExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLValuesQuery extends SQLSelectQueryBase {\n    private List<SQLExpr> values = new ArrayList<SQLExpr>();\n\n    public List<SQLExpr> getValues() {\n        return values;\n    }\n\n    public void addValue(SQLListExpr value) {\n        value.setParent(this);\n        values.add(value);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, values);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLValuesQuery clone() {\n        SQLValuesQuery x = new SQLValuesQuery();\n        x.parenthesized = parenthesized;\n\n        for (int i = 0; i < values.size(); ++i) {\n            SQLExpr value = values.get(i).clone();\n            value.setParent(x);\n            x.values.add(value);\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLValuesTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLListExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 23/02/2017.\n */\npublic class SQLValuesTableSource extends SQLTableSourceImpl implements SQLSelectQuery, SQLReplaceable {\n    private boolean parenthesized;\n    private List<SQLListExpr> values = new ArrayList<SQLListExpr>();\n    private List<SQLName> columns = new ArrayList<SQLName>();\n\n    public SQLValuesTableSource() {\n    }\n\n    public List<SQLListExpr> getValues() {\n        return values;\n    }\n\n    public void addValue(SQLListExpr row) {\n        if (row == null) {\n            return;\n        }\n\n        row.setParent(this);\n        values.add(row);\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLName column) {\n        column.setParent(this);\n        columns.add(column);\n    }\n\n    public void addColumn(String column) {\n        addColumn(new SQLIdentifierExpr(column));\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, values);\n            acceptChild(visitor, columns);\n            super.accept0(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean isParenthesized() {\n        return parenthesized;\n    }\n\n    @Override\n    public void setParenthesized(boolean paren) {\n        this.parenthesized = paren;\n    }\n\n    @Override\n    public SQLValuesTableSource clone() {\n        SQLValuesTableSource x = new SQLValuesTableSource();\n\n        x.setAlias(this.alias);\n\n        for (SQLListExpr e : this.values) {\n            SQLListExpr e2 = e.clone();\n            e2.setParent(x);\n            x.getValues().add(e2);\n        }\n\n        for (SQLName e : this.columns) {\n            SQLName e2 = e.clone();\n            e2.setParent(x);\n            x.getColumns().add(e2);\n        }\n\n        if (this.flashback != null) {\n            x.setFlashback(this.flashback.clone());\n        }\n\n        if (this.hints != null) {\n            for (SQLHint e : this.hints) {\n                SQLHint e2 = e.clone();\n                e2.setParent(x);\n                x.getHints().add(e2);\n            }\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < values.size(); i++) {\n            if (values.get(i) == expr) {\n                target.setParent(this);\n                values.set(i, (SQLListExpr) expr);\n                return true;\n            }\n        }\n\n        for (int i = 0; i < columns.size(); i++) {\n            if (columns.get(i) == expr) {\n                target.setParent(this);\n                columns.set(i, (SQLName) expr);\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhileStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class SQLWhileStatement extends SQLStatementImpl implements SQLReplaceable {\n    //while expr\n    private SQLExpr condition;\n    private List<SQLStatement> statements = new ArrayList<SQLStatement>();\n    //while label name\n    private String labelName;\n\n    public String getLabelName() {\n        return labelName;\n    }\n\n    public void setLabelName(String labelName) {\n        this.labelName = labelName;\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, condition);\n            acceptChild(visitor, statements);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.add(condition);\n        children.addAll(this.statements);\n        return children;\n    }\n\n    public List<SQLStatement> getStatements() {\n        return statements;\n    }\n\n    public void setStatements(List<SQLStatement> statements) {\n        this.statements = statements;\n    }\n\n    public SQLExpr getCondition() {\n        return condition;\n    }\n\n    public void setCondition(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.condition = x;\n    }\n\n    public SQLWhileStatement clone() {\n        SQLWhileStatement x = new SQLWhileStatement();\n\n        if (condition != null) {\n            x.setCondition(condition.clone());\n        }\n        for (SQLStatement stmt : statements) {\n            SQLStatement stmt2 = stmt.clone();\n            stmt2.setParent(x);\n            x.statements.add(stmt2);\n        }\n        x.labelName = labelName;\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (condition == expr) {\n            setCondition(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWhoamiStatement.java",
    "content": "package com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLWhoamiStatement extends SQLStatementImpl {\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/ast/statement/SQLWithSubqueryClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLWithSubqueryClause extends SQLObjectImpl {\n    private Boolean recursive;\n    private final List<Entry> entries = new ArrayList<Entry>();\n\n    protected void cloneTo(SQLWithSubqueryClause x) {\n        super.cloneTo(x);\n        x.recursive = recursive;\n\n        for (Entry entry : entries) {\n            Entry entry2 = entry.clone();\n            entry2.setParent(x);\n            x.entries.add(entry2);\n        }\n    }\n\n    public SQLWithSubqueryClause clone() {\n        SQLWithSubqueryClause x = new SQLWithSubqueryClause();\n        cloneTo(x);\n        return x;\n    }\n\n    public List<Entry> getEntries() {\n        return entries;\n    }\n\n    public Entry findEntry(String alias) {\n        if (alias == null) {\n            return null;\n        }\n        for (Entry entry : entries) {\n            if (alias.equals(entry.getAlias())) {\n                return entry;\n            }\n        }\n        return null;\n    }\n\n    public void addEntry(Entry entry) {\n        if (entry != null) {\n            entry.setParent(this);\n        }\n        this.entries.add(entry);\n    }\n\n    public Boolean getRecursive() {\n        return recursive;\n    }\n\n    public void setRecursive(Boolean recursive) {\n        this.recursive = recursive;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < entries.size(); i++) {\n                Entry entry = entries.get(i);\n                if (entry != null) {\n                    entry.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public static class Entry extends SQLTableSourceImpl implements SQLReplaceable {\n        protected final List<SQLName> columns = new ArrayList<SQLName>();\n        protected SQLSelect subQuery;\n        protected SQLStatement returningStatement;\n        protected SQLExpr expr;\n        protected boolean prefixAlias;\n\n        public Entry() {\n        }\n\n        public Entry(String alias, SQLSelect select) {\n            this.setAlias(alias);\n            this.setSubQuery(select);\n        }\n\n        public Entry(String alias, SQLExpr expr) {\n            this.setAlias(alias);\n            this.setExpr(expr);\n        }\n\n        public void cloneTo(Entry x) {\n            for (SQLName column : columns) {\n                SQLName column2 = column.clone();\n                column2.setParent(x);\n                x.columns.add(column2);\n            }\n\n            if (subQuery != null) {\n                x.setSubQuery(subQuery.clone());\n            }\n\n            if (returningStatement != null) {\n                setReturningStatement(returningStatement.clone());\n            }\n\n            x.alias = alias;\n            x.expr = expr;\n            x.prefixAlias = prefixAlias;\n        }\n\n        public SQLObject resolveColumn(long columnNameHash) {\n            if (subQuery != null) {\n                SQLSelectQueryBlock queryBlock = subQuery.getQueryBlock();\n                if (queryBlock != null) {\n                    return queryBlock.findSelectItem(columnNameHash);\n                }\n            }\n            return null;\n        }\n\n        @Override\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            if (flashback == expr) {\n                setFlashback(target);\n                return true;\n            }\n\n            for (int i = 0; i < columns.size(); i++) {\n                if (columns.get(i) == expr) {\n                    target.setParent(this);\n                    columns.set(i, (SQLName) expr);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public Entry clone() {\n            Entry x = new Entry();\n            cloneTo(x);\n            return x;\n        }\n\n        public SQLExpr getExpr() {\n            return expr;\n        }\n\n        public void setExpr(SQLExpr expr) {\n            this.expr = expr;\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                for (int i = 0; i < columns.size(); i++) {\n                    SQLExpr column = columns.get(i);\n                    if (column != null) {\n                        column.accept(visitor);\n                    }\n                }\n\n                if (subQuery != null) {\n                    subQuery.accept(visitor);\n                }\n\n                if (returningStatement != null) {\n                    returningStatement.accept(visitor);\n                }\n\n                if (expr != null) {\n                    expr.accept(visitor);\n                }\n            }\n            visitor.endVisit(this);\n        }\n\n        public SQLSelect getSubQuery() {\n            return subQuery;\n        }\n\n        public void setSubQuery(SQLSelect subQuery) {\n            if (subQuery != null) {\n                subQuery.setParent(this);\n            }\n            this.subQuery = subQuery;\n        }\n\n        public SQLStatement getReturningStatement() {\n            return returningStatement;\n        }\n\n        public void setReturningStatement(SQLStatement returningStatement) {\n            if (returningStatement != null) {\n                returningStatement.setParent(this);\n            }\n            this.returningStatement = returningStatement;\n        }\n\n        public List<SQLName> getColumns() {\n            return columns;\n        }\n\n        public SQLTableSource findTableSourceWithColumn(long columnNameHash, String columnName, int option) {\n            for (SQLName column : columns) {\n                if (column.nameHashCode64() == columnNameHash) {\n                    return this;\n                }\n            }\n\n            if (subQuery != null) {\n                SQLSelectQueryBlock queryBlock = subQuery.getFirstQueryBlock();\n                if (queryBlock != null) {\n                    if (queryBlock.findSelectItem(columnNameHash) != null) {\n                        return this;\n                    }\n                }\n            }\n            return null;\n        }\n\n        public boolean isPrefixAlias() {\n            return prefixAlias;\n        }\n\n        public void setPrefixAlias(boolean prefixAlias) {\n            this.prefixAlias = prefixAlias;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            if (!super.equals(o)) {\n                return false;\n            }\n\n            Entry entry = (Entry) o;\n\n            if (!columns.equals(entry.columns)) {\n                return false;\n            }\n            if (subQuery != null ? !subQuery.equals(entry.subQuery) : entry.subQuery != null) {\n                return false;\n            }\n            return returningStatement != null ? returningStatement.equals(entry.returningStatement) : entry.returningStatement == null;\n        }\n\n        @Override\n        public int hashCode() {\n            int result = super.hashCode();\n            result = 31 * result + (columns != null ? columns.hashCode() : 0);\n            result = 31 * result + (subQuery != null ? subQuery.hashCode() : 0);\n            result = 31 * result + (returningStatement != null ? returningStatement.hashCode() : 0);\n            return result;\n        }\n    }\n\n    public Entry findEntry(long alias_hash) {\n        if (alias_hash == 0) {\n            return null;\n        }\n\n        for (Entry entry : entries) {\n            if (entry.aliasHashCode64() == alias_hash) {\n                return entry;\n            }\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        SQLWithSubqueryClause that = (SQLWithSubqueryClause) o;\n\n        if (recursive != null ? !recursive.equals(that.recursive) : that.recursive != null) {\n            return false;\n        }\n        return entries.equals(that.entries);\n    }\n\n    @Override\n    public int hashCode() {\n        int result = recursive != null ? recursive.hashCode() : 0;\n        result = 31 * result + entries.hashCode();\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/SQLBuilder.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.druid.sql.builder;\n\npublic interface SQLBuilder {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/SQLBuilderFactory.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.builder.impl.SQLDeleteBuilderImpl;\nimport com.alibaba.druid.sql.builder.impl.SQLSelectBuilderImpl;\nimport com.alibaba.druid.sql.builder.impl.SQLUpdateBuilderImpl;\n\npublic class SQLBuilderFactory {\n    public static SQLSelectBuilder createSelectSQLBuilder(DbType dbType) {\n        return new SQLSelectBuilderImpl(dbType);\n    }\n\n    public static SQLSelectBuilder createSelectSQLBuilder(String sql, DbType dbType) {\n        return new SQLSelectBuilderImpl(sql, dbType);\n    }\n\n    public static SQLDeleteBuilder createDeleteBuilder(DbType dbType) {\n        return new SQLDeleteBuilderImpl(dbType);\n    }\n\n    public static SQLDeleteBuilder createDeleteBuilder(String sql, DbType dbType) {\n        return new SQLDeleteBuilderImpl(sql, dbType);\n    }\n\n    public static SQLUpdateBuilder createUpdateBuilder(DbType dbType) {\n        return new SQLUpdateBuilderImpl(dbType);\n    }\n\n    public static SQLUpdateBuilder createUpdateBuilder(String sql, DbType dbType) {\n        return new SQLUpdateBuilderImpl(sql, dbType);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/SQLDeleteBuilder.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder;\n\npublic interface SQLDeleteBuilder {\n    SQLDeleteBuilder from(String table);\n\n    SQLDeleteBuilder from(String table, String alias);\n\n    SQLDeleteBuilder limit(int rowCount);\n\n    SQLDeleteBuilder limit(int rowCount, int offset);\n\n    SQLDeleteBuilder where(String sql);\n\n    SQLDeleteBuilder whereAnd(String sql);\n\n    SQLDeleteBuilder whereOr(String sql);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/SQLFunctionBuilder.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\n\n/**\n * Created by wenshao on 09/07/2017.\n */\npublic class SQLFunctionBuilder {\n    private final DbType dbType;\n\n    public SQLFunctionBuilder(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    // for character function\n    public SQLMethodInvokeExpr length(SQLExpr expr) {\n        return new SQLMethodInvokeExpr(\"length\", null, expr);\n    }\n\n    public SQLMethodInvokeExpr lower(SQLExpr expr) {\n        return new SQLMethodInvokeExpr(\"lower\", null, expr);\n    }\n\n    public SQLMethodInvokeExpr upper(SQLExpr expr) {\n        return new SQLMethodInvokeExpr(\"upper\", null, expr);\n    }\n\n    public SQLMethodInvokeExpr substr(SQLExpr expr) {\n        return new SQLMethodInvokeExpr(\"substr\", null, expr);\n    }\n\n    public SQLMethodInvokeExpr ltrim(SQLExpr expr) {\n        return new SQLMethodInvokeExpr(\"ltrim\", null, expr);\n    }\n\n    public SQLMethodInvokeExpr rtrim(SQLExpr expr) {\n        return new SQLMethodInvokeExpr(\"rtrim\", null, expr);\n    }\n\n    public SQLMethodInvokeExpr trim(SQLExpr expr) {\n        return new SQLMethodInvokeExpr(\"trim\", null, expr);\n    }\n\n    public SQLMethodInvokeExpr ifnull(SQLExpr expr1, SQLExpr expr2) {\n        switch (dbType) {\n            case ads:\n            case presto:\n            case trino:\n            case odps:\n            case supersql:\n                return new SQLMethodInvokeExpr(\"coalesce\", null, expr1, expr2);\n            case oracle:\n                return new SQLMethodInvokeExpr(\"nvl\", null, expr1, expr2);\n            case sqlserver:\n                return new SQLMethodInvokeExpr(\"isnull\", null, expr1, expr2);\n            default:\n                return new SQLMethodInvokeExpr(\"ifnull\", null, expr1, expr2);\n        }\n    }\n\n    public static final SQLFunctionBuilder Oracle = new SQLFunctionBuilder(DbType.oracle);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/SQLSelectBuilder.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\n\npublic interface SQLSelectBuilder {\n    SQLSelectStatement getSQLSelectStatement();\n\n    SQLSelectBuilder select(String... column);\n\n    SQLSelectBuilder selectWithAlias(String column, String alias);\n\n    SQLSelectBuilder from(String table);\n\n    SQLSelectBuilder from(String table, String alias);\n\n    SQLSelectBuilder orderBy(String... columns);\n\n    SQLSelectBuilder groupBy(String expr);\n\n    SQLSelectBuilder having(String expr);\n\n    SQLSelectBuilder into(String expr);\n\n    SQLSelectBuilder limit(int rowCount);\n\n    SQLSelectBuilder limit(int rowCount, int offset);\n\n    SQLSelectBuilder where(String sql);\n\n    SQLSelectBuilder whereAnd(String sql);\n\n    SQLSelectBuilder whereOr(String sql);\n\n    String toString();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/SQLUpdateBuilder.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder;\n\npublic interface SQLUpdateBuilder {\n    SQLUpdateBuilder from(String table);\n\n    SQLUpdateBuilder from(String table, String alias);\n\n    SQLUpdateBuilder limit(int rowCount);\n\n    SQLUpdateBuilder limit(int rowCount, int offset);\n\n    SQLUpdateBuilder where(String sql);\n\n    SQLUpdateBuilder whereAnd(String sql);\n\n    SQLUpdateBuilder whereOr(String sql);\n\n    SQLUpdateBuilder set(String... items);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/UpdateBuilder.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder;\n\npublic interface UpdateBuilder {\n    UpdateBuilder from(String table);\n\n    UpdateBuilder from(String table, String alias);\n\n    UpdateBuilder limit(int rowCount);\n\n    UpdateBuilder limit(int rowCount, int offset);\n\n    UpdateBuilder where(String sql);\n\n    UpdateBuilder whereAnd(String sql);\n\n    UpdateBuilder whereOr(String sql);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/impl/SQLBuilderImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder.impl;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.builder.SQLBuilder;\n\npublic class SQLBuilderImpl implements SQLBuilder {\n    public static SQLExpr toSQLExpr(Object obj, DbType dbType) {\n        if (obj == null) {\n            return new SQLNullExpr();\n        }\n\n        if (obj instanceof Integer) {\n            return new SQLIntegerExpr((Integer) obj);\n        }\n\n        if (obj instanceof Number) {\n            return new SQLNumberExpr((Number) obj);\n        }\n\n        if (obj instanceof String) {\n            return new SQLCharExpr((String) obj);\n        }\n\n        if (obj instanceof Boolean) {\n            return new SQLBooleanExpr((Boolean) obj);\n        }\n\n        throw new IllegalArgumentException(\"not support : \" + obj.getClass().getName());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/impl/SQLDeleteBuilderImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder.impl;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.builder.SQLDeleteBuilder;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement;\n\nimport java.util.List;\n\npublic class SQLDeleteBuilderImpl implements SQLDeleteBuilder {\n    private SQLDeleteStatement stmt;\n    private DbType dbType;\n\n    public SQLDeleteBuilderImpl(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLDeleteBuilderImpl(String sql, DbType dbType) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (stmtList.isEmpty()) {\n            throw new IllegalArgumentException(\"not support empty-statement :\" + sql);\n        }\n\n        if (stmtList.size() > 1) {\n            throw new IllegalArgumentException(\"not support multi-statement :\" + sql);\n        }\n\n        SQLDeleteStatement stmt = (SQLDeleteStatement) stmtList.get(0);\n        this.stmt = stmt;\n        this.dbType = dbType;\n    }\n\n    public SQLDeleteBuilderImpl(SQLDeleteStatement stmt, DbType dbType) {\n        this.stmt = stmt;\n        this.dbType = dbType;\n    }\n\n    @Override\n    public SQLDeleteBuilderImpl limit(int rowCount) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public SQLDeleteBuilderImpl limit(int rowCount, int offset) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public SQLDeleteBuilder from(String table) {\n        return from(table, null);\n    }\n\n    @Override\n    public SQLDeleteBuilder from(String table, String alias) {\n        SQLDeleteStatement delete = getSQLDeleteStatement();\n        SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);\n        delete.setTableSource(from);\n        return this;\n    }\n\n    @Override\n    public SQLDeleteBuilder where(String expr) {\n        SQLDeleteStatement delete = getSQLDeleteStatement();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        delete.setWhere(exprObj);\n\n        return this;\n    }\n\n    @Override\n    public SQLDeleteBuilder whereAnd(String expr) {\n        SQLDeleteStatement delete = getSQLDeleteStatement();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false, delete.getWhere());\n        delete.setWhere(newCondition);\n\n        return this;\n    }\n\n    @Override\n    public SQLDeleteBuilder whereOr(String expr) {\n        SQLDeleteStatement delete = getSQLDeleteStatement();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false, delete.getWhere());\n        delete.setWhere(newCondition);\n\n        return this;\n    }\n\n    public SQLDeleteStatement getSQLDeleteStatement() {\n        if (stmt == null) {\n            stmt = createSQLDeleteStatement();\n        }\n        return stmt;\n    }\n\n    public SQLDeleteStatement createSQLDeleteStatement() {\n        switch (dbType) {\n            case oracle:\n                return new OracleDeleteStatement();\n            case mysql:\n            case mariadb:\n            case tidb:\n            case polardbx:\n                return new MySqlDeleteStatement();\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGDeleteStatement();\n            default:\n                return new SQLDeleteStatement();\n        }\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(stmt, dbType);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder.impl;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.builder.SQLSelectBuilder;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\n\nimport java.util.List;\n\npublic class SQLSelectBuilderImpl implements SQLSelectBuilder {\n    private SQLSelectStatement stmt;\n    private DbType dbType;\n\n    public SQLSelectBuilderImpl(DbType dbType) {\n        this(new SQLSelectStatement(), dbType);\n    }\n\n    public SQLSelectBuilderImpl(String sql, DbType dbType) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (stmtList.isEmpty()) {\n            throw new IllegalArgumentException(\"not support empty-statement :\" + sql);\n        }\n\n        if (stmtList.size() > 1) {\n            throw new IllegalArgumentException(\"not support multi-statement :\" + sql);\n        }\n\n        SQLSelectStatement stmt = (SQLSelectStatement) stmtList.get(0);\n        this.stmt = stmt;\n        this.dbType = dbType;\n    }\n\n    public SQLSelectBuilderImpl(SQLSelectStatement stmt, DbType dbType) {\n        this.stmt = stmt;\n        this.dbType = dbType;\n    }\n\n    public SQLSelect getSQLSelect() {\n        if (stmt.getSelect() == null) {\n            stmt.setSelect(createSelect());\n        }\n        return stmt.getSelect();\n    }\n\n    @Override\n    public SQLSelectStatement getSQLSelectStatement() {\n        return stmt;\n    }\n\n    public SQLSelectBuilderImpl select(String... columns) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n\n        for (String column : columns) {\n            SQLSelectItem selectItem = SQLUtils.toSelectItem(column, dbType);\n            queryBlock.addSelectItem(selectItem);\n        }\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl selectWithAlias(String column, String alias) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n\n        SQLExpr columnExpr = SQLUtils.toSQLExpr(column, dbType);\n        SQLSelectItem selectItem = new SQLSelectItem(columnExpr, alias);\n        queryBlock.addSelectItem(selectItem);\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl from(String table) {\n        return from(table, null);\n    }\n\n    @Override\n    public SQLSelectBuilderImpl from(String table, String alias) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n        SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);\n        queryBlock.setFrom(from);\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl orderBy(String... columns) {\n        SQLSelect select = this.getSQLSelect();\n\n        SQLOrderBy orderBy = select.getOrderBy();\n        if (orderBy == null) {\n            orderBy = createOrderBy();\n            select.setOrderBy(orderBy);\n        }\n\n        for (String column : columns) {\n            SQLSelectOrderByItem orderByItem = SQLUtils.toOrderByItem(column, dbType);\n            orderBy.addItem(orderByItem);\n        }\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl groupBy(String expr) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n\n        SQLSelectGroupByClause groupBy = queryBlock.getGroupBy();\n        if (groupBy == null) {\n            groupBy = createGroupBy();\n            queryBlock.setGroupBy(groupBy);\n        }\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        groupBy.addItem(exprObj);\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl having(String expr) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n\n        SQLSelectGroupByClause groupBy = queryBlock.getGroupBy();\n        if (groupBy == null) {\n            groupBy = createGroupBy();\n            queryBlock.setGroupBy(groupBy);\n        }\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        groupBy.setHaving(exprObj);\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl into(String expr) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        queryBlock.setInto(exprObj);\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl where(String expr) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        queryBlock.setWhere(exprObj);\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl whereAnd(String expr) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n        queryBlock.addWhere(SQLUtils.toSQLExpr(expr, dbType));\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl whereOr(String expr) {\n        SQLSelectQueryBlock queryBlock = getQueryBlock();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false,\n                queryBlock.getWhere());\n        queryBlock.setWhere(newCondition);\n\n        return this;\n    }\n\n    @Override\n    public SQLSelectBuilderImpl limit(int rowCount) {\n        return limit(rowCount, 0);\n    }\n\n    @Override\n    public SQLSelectBuilderImpl limit(int rowCount, int offset) {\n        getQueryBlock()\n                .limit(rowCount, offset);\n        return this;\n    }\n\n    protected SQLSelectQueryBlock getQueryBlock() {\n        SQLSelect select = getSQLSelect();\n        SQLSelectQuery query = select.getQuery();\n        if (query == null) {\n            query = SQLParserUtils.createSelectQueryBlock(dbType);\n            select.setQuery(query);\n        }\n\n        if (!(query instanceof SQLSelectQueryBlock)) {\n            throw new IllegalStateException(\"not support from, class : \" + query.getClass().getName());\n        }\n\n        SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n        return queryBlock;\n    }\n\n    protected SQLSelect createSelect() {\n        return new SQLSelect();\n    }\n\n    protected SQLSelectQuery createSelectQueryBlock() {\n        return SQLParserUtils.createSelectQueryBlock(dbType);\n    }\n\n    protected SQLOrderBy createOrderBy() {\n        return new SQLOrderBy();\n    }\n\n    protected SQLSelectGroupByClause createGroupBy() {\n        return new SQLSelectGroupByClause();\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(stmt, dbType);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/builder/impl/SQLUpdateBuilderImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.builder.impl;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.builder.SQLUpdateBuilder;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLUpdateBuilderImpl extends SQLBuilderImpl implements SQLUpdateBuilder {\n    private SQLUpdateStatement stmt;\n    private DbType dbType;\n\n    public SQLUpdateBuilderImpl(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public SQLUpdateBuilderImpl(String sql, DbType dbType) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        if (stmtList.isEmpty()) {\n            throw new IllegalArgumentException(\"not support empty-statement :\" + sql);\n        }\n\n        if (stmtList.size() > 1) {\n            throw new IllegalArgumentException(\"not support multi-statement :\" + sql);\n        }\n\n        SQLUpdateStatement stmt = (SQLUpdateStatement) stmtList.get(0);\n        this.stmt = stmt;\n        this.dbType = dbType;\n    }\n\n    public SQLUpdateBuilderImpl(SQLUpdateStatement stmt, DbType dbType) {\n        this.stmt = stmt;\n        this.dbType = dbType;\n    }\n\n    @Override\n    public SQLUpdateBuilderImpl limit(int rowCount) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public SQLUpdateBuilderImpl limit(int rowCount, int offset) {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public SQLUpdateBuilderImpl from(String table) {\n        return from(table, null);\n    }\n\n    @Override\n    public SQLUpdateBuilderImpl from(String table, String alias) {\n        SQLUpdateStatement update = getSQLUpdateStatement();\n        SQLExprTableSource from = new SQLExprTableSource(new SQLIdentifierExpr(table), alias);\n        update.setTableSource(from);\n        return this;\n    }\n\n    @Override\n    public SQLUpdateBuilderImpl where(String expr) {\n        SQLUpdateStatement update = getSQLUpdateStatement();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        update.setWhere(exprObj);\n\n        return this;\n    }\n\n    @Override\n    public SQLUpdateBuilderImpl whereAnd(String expr) {\n        SQLUpdateStatement update = getSQLUpdateStatement();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false, update.getWhere());\n        update.setWhere(newCondition);\n\n        return this;\n    }\n\n    @Override\n    public SQLUpdateBuilderImpl whereOr(String expr) {\n        SQLUpdateStatement update = getSQLUpdateStatement();\n\n        SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);\n        SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanOr, exprObj, false, update.getWhere());\n        update.setWhere(newCondition);\n\n        return this;\n    }\n\n    public SQLUpdateBuilderImpl set(String... items) {\n        SQLUpdateStatement update = getSQLUpdateStatement();\n        for (String item : items) {\n            SQLUpdateSetItem updateSetItem = SQLUtils.toUpdateSetItem(item, dbType);\n            update.addItem(updateSetItem);\n        }\n\n        return this;\n    }\n\n    public SQLUpdateBuilderImpl setValue(Map<String, Object> values) {\n        for (Map.Entry<String, Object> entry : values.entrySet()) {\n            setValue(entry.getKey(), entry.getValue());\n        }\n\n        return this;\n    }\n\n    public SQLUpdateBuilderImpl setValue(String column, Object value) {\n        SQLUpdateStatement update = getSQLUpdateStatement();\n\n        SQLExpr columnExpr = SQLUtils.toSQLExpr(column, dbType);\n        SQLExpr valueExpr = toSQLExpr(value, dbType);\n\n        SQLUpdateSetItem item = new SQLUpdateSetItem();\n        item.setColumn(columnExpr);\n        item.setValue(valueExpr);\n        update.addItem(item);\n\n        return this;\n    }\n\n    public SQLUpdateStatement getSQLUpdateStatement() {\n        if (stmt == null) {\n            stmt = createSQLUpdateStatement();\n        }\n        return stmt;\n    }\n\n    public SQLUpdateStatement createSQLUpdateStatement() {\n        switch (dbType) {\n            case mysql:\n            case mariadb:\n            case tidb:\n            case polardbx:\n                return new MySqlUpdateStatement();\n            case oracle:\n                return new OracleUpdateStatement();\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGUpdateStatement();\n            case sqlserver:\n                return new SQLServerUpdateStatement();\n            default:\n                return new SQLUpdateStatement();\n        }\n    }\n\n    public String toString() {\n        return SQLUtils.toSQLString(stmt, dbType);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/Athena.java",
    "content": "package com.alibaba.druid.sql.dialect.athena;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Athena {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.athena);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/ast/AthenaObject.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.athena.visitor.AthenaASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface AthenaObject extends SQLObject {\n    void accept0(AthenaASTVisitor visitor);\n\n    @Override\n    default void accept(SQLASTVisitor visitor) {\n        if (visitor instanceof AthenaASTVisitor) {\n            accept0((AthenaASTVisitor) visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/ast/stmt/AthenaCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.athena.ast.AthenaObject;\nimport com.alibaba.druid.sql.dialect.athena.visitor.AthenaASTVisitor;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoCreateTableStatement;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class AthenaCreateTableStatement extends PrestoCreateTableStatement implements AthenaObject {\n    protected Map<String, SQLObject> serdeProperties = new LinkedHashMap<String, SQLObject>();\n\n    @Override\n    public void accept0(AthenaASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            visitor.endVisit(this);\n        }\n    }\n\n    public Map<String, SQLObject> getSerdeProperties() {\n        return serdeProperties;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/parser/AthenaCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.dialect.athena.ast.stmt.AthenaCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInputOutputFormat;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoCreateTableParser;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class AthenaCreateTableParser extends PrestoCreateTableParser {\n    public AthenaCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    @Override\n    protected void createTableBefore(SQLCreateTableStatement stmt) {\n        acceptIdentifier(FnvHash.Constants.EXTERNAL);\n        stmt.setExternal(true);\n    }\n    @Override\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.nextIf(Token.PARTITIONED)) {\n            accept(Token.BY);\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                if (lexer.token() != Token.IDENTIFIER) {\n                    throw new ParserException(\"expect identifier. \" + lexer.info());\n                }\n\n                SQLColumnDefinition column = this.exprParser.parseColumn();\n                stmt.addPartitionColumn(column);\n\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    column.addAfterComment(lexer.readAndResetComments());\n                }\n\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        column.addAfterComment(lexer.readAndResetComments());\n                    }\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.CLUSTERED)) {\n            accept(Token.BY);\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                stmt.addClusteredByItem(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.ROW\n                || lexer.identifierEquals(FnvHash.Constants.ROW)) {\n            parseRowFormat(stmt);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n            lexer.nextToken();\n\n            accept(Token.AS);\n\n            if (lexer.identifierEquals(FnvHash.Constants.INPUTFORMAT)) {\n                HiveInputOutputFormat format = new HiveInputOutputFormat();\n                lexer.nextToken();\n                format.setInput(this.exprParser.primary());\n\n                if (lexer.identifierEquals(FnvHash.Constants.OUTPUTFORMAT)) {\n                    lexer.nextToken();\n                    format.setOutput(this.exprParser.primary());\n                }\n                stmt.setStoredAs(format);\n            } else {\n                SQLName name = this.exprParser.name();\n                stmt.setStoredAs(name);\n            }\n        }\n        parseCreateTableWithSerderPropertie(stmt);\n        if (lexer.identifierEquals(FnvHash.Constants.LOCATION)) {\n            lexer.nextToken();\n            SQLExpr location = this.exprParser.primary();\n            stmt.setLocation(location);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, false);\n            accept(Token.RPAREN);\n        }\n    }\n\n    protected void parseRowFormat(SQLCreateTableStatement stmt) {\n        SQLExternalRecordFormat format = this.getExprParser().parseRowFormat();\n        stmt.setRowFormat(format);\n    }\n\n    protected void parseCreateTableWithSerderPropertie(SQLCreateTableStatement stmt) {\n        if (stmt instanceof AthenaCreateTableStatement) {\n            AthenaCreateTableStatement athenaStmt = (AthenaCreateTableStatement) stmt;\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"SERDEPROPERTIES\");\n\n                accept(Token.LPAREN);\n\n                for (; ; ) {\n                    String key = lexer.stringVal();\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    SQLExpr value = this.exprParser.primary();\n                    athenaStmt.getSerdeProperties().put(key, value);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n\n                accept(Token.RPAREN);\n            }\n        }\n    }\n\n    @Override\n    protected AthenaCreateTableStatement newCreateStatement() {\n        return new AthenaCreateTableStatement();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/parser/AthenaExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoExprParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class AthenaExprParser extends PrestoExprParser {\n    public AthenaExprParser(String sql, SQLParserFeature... features) {\n        this(new AthenaLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public AthenaExprParser(Lexer lexer) {\n        super(lexer, DbType.athena);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/parser/AthenaLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoLexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class AthenaLexer extends PrestoLexer {\n    public AthenaLexer(String input, SQLParserFeature... features) {\n        super(input, DbType.athena, features);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/parser/AthenaSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.parser;\n\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\n\npublic class AthenaSelectParser extends PrestoSelectParser {\n    public AthenaSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    @Override\n    protected SQLExprParser createExprParser() {\n    return new AthenaExprParser(this.lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/parser/AthenaStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.parser;\n\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoStatementParser;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class AthenaStatementParser extends PrestoStatementParser {\n    public AthenaStatementParser(String sql, SQLParserFeature... features) {\n        super(new AthenaExprParser(sql, features));\n    }\n\n    @Override\n    public AthenaSelectParser createSQLSelectParser() {\n        return new AthenaSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new AthenaCreateTableParser(this.exprParser);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/visitor/AthenaASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.visitor;\n\nimport com.alibaba.druid.sql.dialect.athena.ast.stmt.AthenaCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\n\npublic interface AthenaASTVisitor extends PrestoASTVisitor {\n    default boolean visit(AthenaCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(AthenaCreateTableStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/athena/visitor/AthenaOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.athena.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.athena.Athena;\nimport com.alibaba.druid.sql.dialect.athena.ast.stmt.AthenaCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoOutputVisitor;\n\npublic class AthenaOutputVisitor extends PrestoOutputVisitor implements AthenaASTVisitor {\n    public AthenaOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.athena, Athena.DIALECT);\n    }\n\n    public AthenaOutputVisitor(StringBuilder appender, boolean parameterized) {\n    super(appender, DbType.athena, Athena.DIALECT, parameterized);\n    }\n\n    protected void printCreateTable(SQLCreateTableStatement x, boolean printSelect) {\n        printCreateTable((AthenaCreateTableStatement) x, printSelect);\n    }\n    protected void printCreateTable(AthenaCreateTableStatement x, boolean printSelect) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        printCreateTableFeatures(x);\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        printTableSourceExpr(x.getTableSource().getExpr());\n        printCreateTableAfterName(x);\n        printTableElements(x.getTableElementList());\n        printComment(x.getComment());\n        printPartitionedBy(x);\n        printClusteredBy(x);\n        printIntoBuckets(x.getBuckets());\n        printRowFormat(x);\n        printStoredAs(x);\n        printSerdeProperties(x.getSerdeProperties());\n        printLocation(x);\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        print0(ucase ? \"TBLPROPERTIES (\" : \"tblproperties (\");\n        incrementIndent();\n        println();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/BQ.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class BQ {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.bigquery);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryAssertStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class BigQueryAssertStatement extends SQLStatementImpl implements BigQueryObject{\n    private SQLExpr expr;\n    private SQLCharExpr as;\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.expr = x;\n    }\n\n    public SQLCharExpr getAs() {\n        return as;\n    }\n\n    public void setAs(SQLCharExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.as = x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(BigQueryVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, expr);\n            acceptChild(v, as);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryCharExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class BigQueryCharExpr extends SQLCharExpr implements SQLExpr, BigQueryObject {\n    private String prefix;\n    private boolean space;\n    private boolean isAlias;\n\n    public BigQueryCharExpr() {\n    }\n\n    public boolean hasPrefix() {\n        return prefix != null;\n    }\n\n    public void setPrefix(String prefix) {\n        this.prefix = prefix;\n    }\n\n    public String getPrefix() {\n        return prefix;\n    }\n\n    public boolean isSpace() {\n        return space;\n    }\n\n    public void setSpace(boolean space) {\n        this.space = space;\n    }\n\n    public boolean isAlias() {\n        return isAlias;\n    }\n\n    public void setAlias(boolean alias) {\n        isAlias = alias;\n    }\n\n    public BigQueryCharExpr(String text, String prefix) {\n        this(text, prefix, false, false);\n    }\n\n    public BigQueryCharExpr(String text, String prefix, boolean space, boolean isAlias) {\n        this.prefix = prefix;\n        this.text = text;\n        this.space = space;\n        this.isAlias = isAlias;\n    }\n\n    public void accept0(BigQueryVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            this.accept0((BigQueryVisitor) v);\n            return;\n        }\n        v.visit(this);\n        v.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public BigQueryCharExpr clone() {\n        BigQueryCharExpr clone = new BigQueryCharExpr();\n        clone.setPrefix(this.prefix);\n        clone.setText(this.text);\n        clone.setSpace(this.space);\n        clone.setAlias(this.isAlias);\n        return clone;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryCreateModelStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class BigQueryCreateModelStatement extends SQLStatementImpl implements BigQueryObject {\n    private boolean ifNotExists;\n    private boolean replace;\n\n    private SQLName name;\n    private final List<SQLAssignItem> options = new ArrayList<>();\n    private SQLStatement trainingData;\n    private SQLStatement customHoliday;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public boolean isReplace() {\n        return replace;\n    }\n\n    public void setReplace(boolean replace) {\n        this.replace = replace;\n    }\n\n    public SQLStatement getTrainingData() {\n        return trainingData;\n    }\n\n    public void setTrainingData(SQLStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.trainingData = x;\n    }\n\n    public SQLStatement getCustomHoliday() {\n        return customHoliday;\n    }\n\n    public void setCustomHoliday(SQLStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.customHoliday = x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(BigQueryVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class BigQueryCreateTableStatement\n        extends SQLCreateTableStatement {\n    protected final List<SQLExpr> partitionBy = new ArrayList<>();\n    private SQLExpr collate;\n\n    public List<SQLExpr> getPartitionBy() {\n        return partitionBy;\n    }\n\n    public BigQueryCreateTableStatement clone() {\n        BigQueryCreateTableStatement x = new BigQueryCreateTableStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    protected void cloneTo(BigQueryCreateTableStatement x) {\n        super.cloneTo(x);\n        for (SQLExpr item : partitionBy) {\n            SQLExpr cloned = item.clone();\n            cloned.setParent(x);\n            x.partitionBy.add(cloned);\n        }\n    }\n\n    public SQLExpr getCollate() {\n        return collate;\n    }\n\n    public void setCollate(SQLExpr collate) {\n        this.collate = collate;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryExecuteImmediateStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLAliasedExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExecuteImmediateStatement;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class BigQueryExecuteImmediateStatement\n        extends SQLExecuteImmediateStatement {\n    private final List<SQLAliasedExpr> using = new ArrayList<>();\n\n    public List<SQLAliasedExpr> getUsing() {\n        return using;\n    }\n\n    public void addUsing(SQLExpr x) {\n        x.setParent(this);\n        using.add(new SQLAliasedExpr(x));\n    }\n\n    public void addUsing(SQLExpr x, String alias) {\n        x.setParent(this);\n        using.add(new SQLAliasedExpr(x, alias));\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    public void accept0(BigQueryVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        super.acceptChild(v);\n        acceptChild(v, using);\n    }\n\n    protected BigQueryExecuteImmediateStatement cloneTo(BigQueryExecuteImmediateStatement x) {\n        super.cloneTo(x);\n        for (SQLAliasedExpr item : using) {\n            SQLAliasedExpr item2 = item.clone();\n            item2.setParent(x);\n            x.using.add(item2);\n        }\n        return x;\n    }\n\n    public BigQueryExecuteImmediateStatement clone() {\n        BigQueryExecuteImmediateStatement x = new BigQueryExecuteImmediateStatement();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryExportDataStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class BigQueryExportDataStatement extends SQLStatementImpl implements BigQueryObject {\n    private SQLExprTableSource connection;\n    private final List<SQLAssignItem> options = new ArrayList<>();\n    private SQLStatement asSelect;\n\n    public BigQueryExportDataStatement() {\n        dbType = DbType.bigquery;\n    }\n\n    public SQLExprTableSource getConnection() {\n        return connection;\n    }\n\n    public void setConnection(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.connection = x;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public SQLStatement getAsSelect() {\n        return asSelect;\n    }\n\n    public void setAsSelect(SQLStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.asSelect = x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(BigQueryVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, connection);\n            acceptChild(v, options);\n            acceptChild(v, asSelect);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryModelExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class BigQueryModelExpr extends SQLExprImpl implements BigQueryObject {\n    private SQLName name;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(BigQueryVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public SQLExpr clone() {\n        return null;\n    }\n\n    public void acceptChild(SQLASTVisitor v) {\n        acceptChild(v, name);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryObject.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface BigQueryObject extends SQLObject {\n    default void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        }\n    }\n\n    void accept0(BigQueryVisitor v);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQuerySelectQueryBlock.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\n\npublic class BigQuerySelectQueryBlock extends SQLSelectQueryBlock\n        implements BigQueryObject{\n    protected boolean asStruct;\n    private DifferentialPrivacy differentialPrivacy;\n\n    public DifferentialPrivacy getDifferentialPrivacy() {\n        return differentialPrivacy;\n    }\n\n    public void setDifferentialPrivacy(DifferentialPrivacy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.differentialPrivacy = x;\n    }\n\n    public boolean isAsStruct() {\n        return asStruct;\n    }\n\n    public void setAsStruct(boolean asStruct) {\n        this.asStruct = asStruct;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(BigQueryVisitor v) {\n        super.accept0(v);\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        if (differentialPrivacy != null) {\n            differentialPrivacy.accept(v);\n        }\n        super.acceptChild(v);\n    }\n\n    public static class DifferentialPrivacy\n            extends SQLObjectImpl implements BigQueryObject {\n        private final List<SQLAssignItem> options = new ArrayList<>();\n\n        @Override\n        public boolean equals(Object object) {\n            if (this == object) {\n                return true;\n            }\n            if (object == null || getClass() != object.getClass()) {\n                return false;\n            }\n\n            DifferentialPrivacy that = (DifferentialPrivacy) object;\n            return options.equals(that.options);\n        }\n\n        public List<SQLAssignItem> getOptions() {\n            return options;\n        }\n\n        @Override\n        public int hashCode() {\n            return Objects.hash(options);\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor v) {\n            if (v instanceof BigQueryVisitor) {\n                accept0((BigQueryVisitor) v);\n            }\n        }\n\n        @Override\n        public void accept0(BigQueryVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, options);\n            }\n            visitor.endVisit(this);\n        }\n\n        @Override\n        public DifferentialPrivacy clone() {\n            DifferentialPrivacy x = new DifferentialPrivacy();\n            for (SQLAssignItem option : options) {\n                SQLAssignItem cloned = option.clone();\n                x.options.add(cloned);\n            }\n            return x;\n        }\n    }\n\n    public BigQuerySelectQueryBlock clone() {\n        BigQuerySelectQueryBlock x = new BigQuerySelectQueryBlock();\n        cloneTo(x);\n        x.asStruct = this.asStruct;\n        if (differentialPrivacy != null) {\n            x.differentialPrivacy = this.differentialPrivacy.clone();\n        }\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/ast/BigQueryTableExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class BigQueryTableExpr extends SQLExprImpl implements BigQueryObject {\n    private SQLName name;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof BigQueryVisitor) {\n            accept0((BigQueryVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(BigQueryVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public SQLExpr clone() {\n        return null;\n    }\n\n    public void acceptChild(SQLASTVisitor v) {\n        acceptChild(v, name);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryCreateTableStatement;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class BigQueryCreateTableParser extends SQLCreateTableParser {\n    public BigQueryCreateTableParser(String sql) {\n        super(new BigQueryExprParser(sql));\n    }\n\n    public BigQueryCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    protected SQLCreateTableStatement newCreateStatement() {\n        return new BigQueryCreateTableStatement();\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new BigQuerySelectParser(this.exprParser, selectListCache);\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement x) {\n        BigQueryCreateTableStatement stmt = (BigQueryCreateTableStatement) x;\n        for (;;) {\n            if (lexer.nextIf(Token.DEFAULT)) {\n                acceptIdentifier(\"COLLATE\");\n                SQLExpr collate = exprParser.expr();\n                stmt.setCollate(collate);\n            }\n\n            if (lexer.nextIf(Token.PARTITION)) {\n                accept(Token.BY);\n\n                this.exprParser.exprList(stmt.getPartitionBy(), stmt);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"CLUSTER\")) {\n                accept(Token.BY);\n                for (;;) {\n                    SQLSelectOrderByItem item = exprParser.parseSelectOrderByItem();\n                    item.setParent(stmt);\n                    stmt.getClusteredBy().add(item);\n                    if (lexer.nextIf(Token.COMMA)) {\n                        continue;\n                    }\n                    break;\n                }\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"OPTIONS\")) {\n                exprParser.parseAssignItem(stmt.getTableOptions(), stmt);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"CLONE\")) {\n                stmt.setLike(exprParser.name());\n                continue;\n            }\n\n            if (lexer.nextIf(Token.COMMENT)) {\n                SQLExpr comment = this.exprParser.expr();\n                stmt.setComment(comment);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextIf(Token.EQ);\n                stmt.setLifeCycle(this.exprParser.primary());\n\n                continue;\n            }\n\n            if (lexer.nextIf(Token.AS)) {\n                stmt.setSelect(\n                        this.createSQLSelectParser().select()\n                );\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        if (lexer.nextIfIdentifier(\"TEMPORARY\") || lexer.nextIfIdentifier(\"TEMP\")) {\n            createTable.setTemporary(true);\n        } else if (lexer.nextIfIdentifier(FnvHash.Constants.EXTERNAL)) {\n            createTable.setExternal(true);\n        }\n\n        if (lexer.nextIf(Token.OR)) {\n            accept(Token.REPLACE);\n            createTable.config(SQLCreateTableStatement.Feature.OrReplace);\n        }\n\n        if (lexer.nextIfIdentifier(\"TEMPORARY\") || lexer.nextIfIdentifier(\"TEMP\")) {\n            createTable.setTemporary(true);\n        }\n    }\n\n    @Override\n    protected SQLSelect createTableQueryRest() {\n        return new BigQuerySelectParser(this.exprParser, selectListCache).select();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.bigquery.BQ;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryCharExpr;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryModelExpr;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryTableExpr;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\nimport static com.alibaba.druid.util.FnvHash.fnv1a_64_lower;\n\npublic class BigQueryExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"ANY_VALUE\",\n                \"ARRAY_AGG\",\n                \"ARRAY_CONCAT_AGG\",\n                \"AVG\",\n                \"BIT_AND\",\n                \"BIT_OR\",\n                \"BIT_XOR\",\n                \"COUNT\",\n                \"COUNTIF\",\n                \"FIRST_VALUE\",\n                \"GROUPING\",\n                \"LAST_VALUE\",\n                \"LAG\",\n                \"LEAD\",\n                \"LOGICAL_AND\",\n                \"LOGICAL_OR\",\n                \"MAX\",\n                \"MAX_BY\",\n                \"MIN\",\n                \"MIN_BY\",\n                \"STRING_AGG\",\n                \"SUM\",\n                \"APPROX_QUANTILES\"\n        };\n        AGGREGATE_FUNCTIONS_CODES = fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    {\n        dbType = DbType.bigquery;\n    }\n\n    public BigQueryExprParser(String sql) {\n        this(new BigQueryLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public BigQueryExprParser(String sql, SQLParserFeature... features) {\n        this(new BigQueryLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public BigQueryExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    static final long SAFE_CAST = fnv1a_64_lower(\"SAFE_CAST\");\n\n    protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) {\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            long hashCode64 = identifierExpr.hashCode64();\n            if (hashCode64 == FnvHash.Constants.STRUCT && acceptLPAREN) {\n                SQLStructExpr struct = struct();\n                if (lexer.isKeepSourceLocation()) {\n                    struct.setSource(identifierExpr.getSourceLine(), identifierExpr.getSourceColumn());\n                }\n                return struct;\n            }\n\n            if (hashCode64 == SAFE_CAST && acceptLPAREN) {\n                SQLCastExpr castExpr = new SQLCastExpr();\n                lexer.nextToken();\n                castExpr.setExpr(\n                        expr());\n                castExpr.setTry(true);\n                accept(Token.AS);\n                castExpr.setDataType(\n                        parseDataType()\n                );\n                castExpr = parseCastFormat(castExpr);\n                accept(Token.RPAREN);\n                return castExpr;\n            }\n\n            String ident = identifierExpr.getName();\n            if (ident.length() > 3 && ident.charAt(0) == '`' && ident.charAt(ident.length() - 1) == '`' && ident.indexOf('.') != -1) {\n                expr = topPropertyExpr(ident);\n            }\n        }\n        return super.methodRest(expr, acceptLPAREN);\n    }\n\n    protected SQLExpr parseSelectItemRest(String ident, long hash_lower) {\n        if (ident.length() > 3\n                && ident.charAt(0) == '`'\n                && ident.charAt(ident.length() - 1) == '`'\n                && ident.indexOf('.') != -1\n        ) {\n            return topPropertyExpr(ident);\n        }\n        if (hash_lower == FnvHash.Constants.ARRAY && lexer.token() == Token.LT) {\n            return parseArrayExpr(ident);\n        }\n        return null;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.nextIfIdentifier(FnvHash.Constants.OPTIONS)) {\n            parseAssignItem(column.getColProperties(), column);\n        }\n\n        return super.parseColumnRest(column);\n    }\n\n    protected SQLStructDataType parseDataTypeStruct() {\n        acceptIdentifier(\"STRUCT\");\n        return parseDataTypeStruct0();\n    }\n\n    protected SQLStructDataType parseDataTypeStruct0() {\n        SQLStructDataType struct = new SQLStructDataType(dbType);\n        accept(Token.LT);\n        for (; ; ) {\n            SQLName name;\n            String str = lexer.stringVal();\n            if (BQ.DIALECT.isBuiltInDataType(str)) {\n                Lexer.SavePoint mark = lexer.markOut();\n                lexer.nextToken();\n                String tokenName = lexer.token() == Token.IDENTIFIER ? lexer.stringVal() : lexer.token().name;\n                if (tokenName != null\n                        && Character.isLetter(tokenName.charAt(0))\n                        && BQ.DIALECT.isBuiltInDataType(lexer.stringVal())\n                ) {\n                    name = new SQLIdentifierExpr(str);\n                } else {\n                    lexer.reset(mark);\n                    name = null;\n                }\n            } else {\n                name = new SQLIdentifierExpr(str);\n                lexer.nextToken();\n            }\n\n            SQLDataType dataType = this.parseDataType();\n            SQLStructDataType.Field field = struct.addField(name, dataType);\n            parseFieldConstraints(field);\n            if (lexer.nextIfIdentifier(FnvHash.Constants.OPTIONS)) {\n                parseAssignItem(field.getOptions(), field);\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        if (lexer.token() == Token.GTGTGT) {\n            lexer.setToken(Token.GTGT);\n        } else if (lexer.token() == Token.GTGT) {\n            lexer.setToken(Token.GT);\n        } else {\n            accept(Token.GT);\n        }\n        return struct;\n    }\n\n    private void parseFieldConstraints(SQLStructDataType.Field field) {\n        switch (lexer.token()) {\n            case DEFAULT:\n                field.addConstraint(parseColumnDefault());\n                break;\n            case NOT: {\n                lexer.nextToken();\n                accept(Token.NULL);\n                SQLNotNullConstraint notNull = new SQLNotNullConstraint();\n                field.addConstraint(notNull);\n                break;\n            }\n            case PRIMARY:\n                SQLColumnPrimaryKey pk = new SQLColumnPrimaryKey();\n                lexer.nextToken();\n                accept(Token.KEY);\n                accept(Token.NOT);\n                acceptIdentifier(\"ENFORCED\");\n                pk.setNotEnforced(true);\n                field.addConstraint(pk);\n                break;\n            case REFERENCES:\n                SQLColumnReference ref = parseReference();\n                accept(Token.NOT);\n                acceptIdentifier(\"ENFORCED\");\n                ref.setNotEnforced(true);\n                field.addConstraint(ref);\n                break;\n            default:\n                break;\n        }\n    }\n\n    private SQLColumnDefault parseColumnDefault() {\n        SQLColumnDefault columnDefault = new SQLColumnDefault();\n        accept(Token.DEFAULT);\n        if (lexer.token() == Token.LPAREN) {\n            while (lexer.token() == Token.LPAREN) {\n                accept(Token.LPAREN);\n            }\n\n            columnDefault.setDefaultExpr(this.primary());\n\n            while (lexer.token() == Token.RPAREN) {\n                accept(Token.RPAREN);\n            }\n        } else {\n            columnDefault.setDefaultExpr(this.primary());\n        }\n        return columnDefault;\n    }\n\n    public void parsePrimaryKeyRest(SQLPrimaryKeyImpl primaryKey) {\n        accept(Token.NOT);\n        acceptIdentifier(\"ENFORCED\");\n        primaryKey.setNotEnforced(true);\n        super.parsePrimaryKeyRest(primaryKey);\n    }\n\n    @Override\n    protected void parseForeignKeyRest(SQLForeignKeyImpl foreignKey) {\n        accept(Token.NOT);\n        acceptIdentifier(\"ENFORCED\");\n        foreignKey.setNotEnforced(true);\n        super.parseForeignKeyRest(foreignKey);\n    }\n\n    public SQLExpr primary() {\n        if (lexer.nextIf(Token.DOT)) {\n            String name = lexer.stringVal();\n            SQLExpr expr = new SQLPropertyExpr((SQLExpr) null, name);\n            lexer.nextToken();\n            if (lexer.nextIf(Token.DOT)) {\n                expr = dotRest(expr);\n            }\n            return primaryRest(expr);\n        }\n\n        if (lexer.token() == Token.WITH) {\n            return primaryRest(\n                    parseQueryExpr()\n            );\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.MODEL)) {\n            Lexer.SavePoint mark = lexer.markOut();\n            lexer.nextToken();\n            if (lexer.token() == Token.IDENTIFIER) {\n                BigQueryModelExpr model = new BigQueryModelExpr();\n                model.setName(\n                        name()\n                );\n                return model;\n            } else {\n                lexer.reset(mark);\n            }\n        }\n        if (lexer.token() == Token.TABLE) {\n            Lexer.SavePoint mark = lexer.markOut();\n            lexer.nextToken();\n            if (lexer.token() == Token.IDENTIFIER) {\n                BigQueryTableExpr model = new BigQueryTableExpr();\n                model.setName(\n                        name()\n                );\n                return model;\n            } else {\n                lexer.reset(mark);\n            }\n        }\n        return super.primary();\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            String ident = identifierExpr.getName();\n            if (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS) {\n                boolean isAlias = lexer.token() == Token.LITERAL_ALIAS;\n                boolean isSpace;\n                if (ident.equalsIgnoreCase(\"b\") || ident.equalsIgnoreCase(\"r\")) {\n                    isSpace = false;\n                } else if (ident.equalsIgnoreCase(\"json\")) {\n                    isSpace = true;\n                } else {\n                    throw new ParserException(\"Not supported prefix: \" + ident + \" for bigquery\");\n                }\n                String charValue = lexer.stringVal();\n                lexer.nextToken();\n                expr = new BigQueryCharExpr(charValue, ident, isSpace, isAlias);\n            }\n        }\n\n        Lexer.SavePoint savePoint = lexer.markOut();\n        if (lexer.identifierEquals(FnvHash.Constants.AT)) {\n            lexer.nextToken();\n            if (lexer.nextIfIdentifier(FnvHash.Constants.TIME)) {\n                acceptIdentifier(\"ZONE\");\n                SQLExpr timeZone = primary();\n                expr = new SQLAtTimeZoneExpr(expr, timeZone);\n            } else {\n                lexer.reset(savePoint);\n            }\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    public SQLDataType parseDataType(boolean restrict) {\n        if (lexer.nextIf(Token.ANY)) {\n            acceptIdentifier(\"TYPE\");\n            return new SQLDataTypeImpl(\"ANY TYPE\");\n        }\n        return super.parseDataType(restrict);\n    }\n\n    protected SQLExpr dotRest(SQLExpr expr) {\n        return super.dotRest(expr);\n    }\n\n    public SQLSelectParser createSelectParser() {\n        return new BigQuerySelectParser(this, null);\n    }\n\n    public SQLExpr exprRest(SQLExpr expr) {\n        if (lexer.token() == Token.LT && expr instanceof SQLIdentifierExpr && ((SQLIdentifierExpr) expr).nameEquals(\"STRUCT\")) {\n            SQLStructExpr structExpr = new SQLStructExpr();\n            structExpr.setDataType(\n                    parseDataTypeStruct0()\n            );\n            accept(Token.LPAREN);\n            aliasedItems(structExpr.getItems(), structExpr);\n            accept(Token.RPAREN);\n            expr = structExpr;\n        }\n        return super.exprRest(expr);\n    }\n\n    protected String nameCommon() {\n        String identName = lexer.stringVal();\n        lexer.nextToken();\n        return identName;\n    }\n\n    @Override\n    protected SQLCastExpr parseCastFormat(SQLCastExpr cast) {\n        if (lexer.nextIfIdentifier(\"FORMAT\")) {\n            cast.setFormat(\n                    this.expr()\n            );\n        }\n        return cast;\n    }\n\n    protected SQLExpr primaryIdentifierRest(long hash_lower, String ident) {\n        if (ident.length() > 3 && ident.charAt(0) == '`' && ident.charAt(ident.length() - 1) == '`' && ident.indexOf('.') != -1) {\n            return topPropertyExpr(ident);\n        }\n        return super.primaryIdentifierRest(hash_lower, ident);\n    }\n\n    public SQLName nameRest(SQLName name) {\n        if (name instanceof SQLIdentifierExpr) {\n            String ident = ((SQLIdentifierExpr) name).getName();\n            if (ident.length() > 3 && ident.charAt(0) == '`' && ident.charAt(ident.length() - 1) == '`' && ident.indexOf('.') != -1) {\n                return topPropertyExpr(ident);\n            }\n        }\n        return super.nameRest(name);\n    }\n\n    @Override\n    protected SQLExpr primaryCommon(SQLExpr sqlExpr) {\n        sqlExpr = new SQLIdentifierExpr(lexer.stringVal());\n        lexer.nextToken();\n        return sqlExpr;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;\n\npublic class BigQueryLexer extends Lexer {\n    static final Keywords BIGQUERY_KEYWORDS;\n    static final DialectFeature BIGQUERY_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    SQLDateExpr,\n                    GroupByAll,\n                    InRestSpecificOperation\n            ),\n            null\n    );\n    static {\n        Map<String, Token> map = new HashMap<String, Token>();\n\n        //        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"ALL\", Token.ALL);\n        map.put(\"AND\", Token.AND);\n        map.put(\"ANY\", Token.ANY);\n        map.put(\"ALTER\", Token.ALTER);\n        //        map.put(\"ARRAY\", Token.ARRAY);\n        map.put(\"AS\", Token.AS);\n        map.put(\"ASC\", Token.ASC);\n        map.put(\"BETWEEN\", Token.BETWEEN);\n        map.put(\"BY\", Token.BY);\n        map.put(\"CASE\", Token.CASE);\n        map.put(\"CAST\", Token.CAST);\n        map.put(\"COLUMN\", Token.COLUMN);\n        map.put(\"CONTAINS\", Token.CONTAINS);\n        map.put(\"CREATE\", Token.CREATE);\n        map.put(\"CROSS\", Token.CROSS);\n        map.put(\"CURRENT\", Token.CURRENT);\n        map.put(\"DECLARE\", Token.DECLARE);\n        map.put(\"DEFAULT\", Token.DEFAULT);\n        map.put(\"DESC\", Token.DESC);\n        map.put(\"DISTINCT\", Token.DISTINCT);\n        map.put(\"DELETE\", Token.DELETE);\n        map.put(\"DROP\", Token.DROP);\n        map.put(\"DO\", Token.DO);\n        map.put(\"ELSE\", Token.ELSE);\n        map.put(\"END\", Token.END);\n        map.put(\"ESCAPE\", Token.ESCAPE);\n        map.put(\"EXCEPT\", Token.EXCEPT);\n        map.put(\"EXISTS\", Token.EXISTS);\n        map.put(\"EXTRACT\", Token.EXTRACT);\n        map.put(\"FUNCTION\", Token.FUNCTION);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FOR\", Token.FOR);\n        map.put(\"FOREIGN\", Token.FOREIGN);\n        map.put(\"FROM\", Token.FROM);\n        map.put(\"FULL\", Token.FULL);\n        map.put(\"GROUP\", Token.GROUP);\n        map.put(\"HAVING\", Token.HAVING);\n        map.put(\"INSERT\", Token.INSERT);\n        map.put(\"IF\", Token.IF);\n        map.put(\"IN\", Token.IN);\n        map.put(\"INNER\", Token.INNER);\n        map.put(\"INTERSECT\", Token.INTERSECT);\n        map.put(\"INTERVAL\", Token.INTERVAL);\n        map.put(\"INTO\", Token.INTO);\n        map.put(\"IS\", Token.IS);\n        map.put(\"JOIN\", Token.JOIN);\n        map.put(\"KEY\", Token.KEY);\n        map.put(\"LATERAL\", Token.LATERAL);\n        map.put(\"LEFT\", Token.LEFT);\n        map.put(\"LIKE\", Token.LIKE);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"NEW\", Token.NEW);\n        map.put(\"NOT\", Token.NOT);\n        map.put(\"NULL\", Token.NULL);\n        map.put(\"OF\", Token.OF);\n        map.put(\"ON\", Token.ON);\n        map.put(\"OR\", Token.OR);\n        map.put(\"ORDER\", Token.ORDER);\n        map.put(\"OUTER\", Token.OUTER);\n        map.put(\"OVER\", Token.OVER);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"PRIMARY\", Token.PRIMARY);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n        map.put(\"RECURSIVE\", Token.RECURSIVE);\n        map.put(\"REFERENCES\", Token.REFERENCES);\n        map.put(\"REPLACE\", Token.REPLACE);\n        map.put(\"RIGHT\", Token.RIGHT);\n        map.put(\"ROWS\", Token.ROWS);\n        map.put(\"SELECT\", Token.SELECT);\n        map.put(\"SET\", Token.SET);\n        map.put(\"SOME\", Token.SOME);\n        map.put(\"THEN\", Token.THEN);\n        map.put(\"TO\", Token.TO);\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"UPDATE\", Token.UPDATE);\n        map.put(\"UNION\", Token.UNION);\n        map.put(\"USING\", Token.USING);\n        map.put(\"VALUES\", Token.VALUES);\n        map.put(\"WHEN\", Token.WHEN);\n        map.put(\"WHERE\", Token.WHERE);\n        map.put(\"WINDOW\", Token.WINDOW);\n        map.put(\"WITH\", Token.WITH);\n        map.put(\"WHILE\", Token.WHILE);\n        map.put(\"LOOP\", Token.LOOP);\n        map.put(\"LEAVE\", Token.LEAVE);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"VIEW\", Token.VIEW);\n        map.put(\"TRUNCATE\", Token.TRUNCATE);\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"TABLE\", Token.TABLE);\n        map.put(\"EXCEPTION\", Token.EXCEPTION);\n        map.put(\"RAISE\", Token.RAISE);\n        map.put(\"ELSEIF\", Token.ELSEIF);\n        map.put(\"SCHEMA\", Token.SCHEMA);\n        map.put(\"PROCEDURE\", Token.PROCEDURE);\n        map.put(\"DATABASE\", Token.DATABASE);\n\n        BIGQUERY_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return BIGQUERY_KEYWORDS;\n    }\n\n    public BigQueryLexer(String input, SQLParserFeature... features) {\n        super(input);\n        dbType = DbType.bigquery;\n        this.skipComment = true;\n        this.keepComments = true;\n        this.features |= SQLParserFeature.SupportUnicodeCodePoint.mask;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    public final void nextTokenFullName() {\n        nextToken();\n    }\n\n    @Override\n    public boolean nextIf(Token token) {\n        if (this.token == token) {\n            boolean setFeature = token == Token.DELETE\n                    || token == Token.FROM\n                    || token == Token.INTO\n                    || token == Token.JOIN;\n            if (setFeature) {\n                dialectFeature.configFeature(DialectFeature.LexerFeature.ScanSubAsIdentifier);\n            }\n            nextToken();\n            if (setFeature) {\n                dialectFeature.configFeature(DialectFeature.LexerFeature.ScanSubAsIdentifier, false);\n            }\n            return true;\n        }\n        return false;\n    }\n\n    public final void scanIdentifier() {\n        scanIdentifier0();\n    }\n\n    protected void scanAlias() {\n        if (pos + 2 < text.length()\n                && text.charAt(pos + 1) == '\"'\n                && text.charAt(pos + 2) == '\"'\n        ) {\n            for (int i = pos + 3; i < text.length(); i++) {\n                char c = text.charAt(i);\n                if (c == '\"'\n                        && i + 2 < text.length()\n                        && text.charAt(i + 1) == '\"'\n                        && text.charAt(i + 2) == '\"'\n                ) {\n                    stringVal = text.substring(pos + 3, i);\n                    token = Token.LITERAL_TEXT_BLOCK;\n                    pos = i + 2;\n                    scanChar();\n                    return;\n                }\n            }\n        }\n\n        {\n            boolean hasSpecial = false;\n            int startIndex = pos + 1;\n            int endIndex = -1; // text.indexOf('\\'', startIndex);\n            for (int i = startIndex; i < text.length(); ++i) {\n                final char ch = text.charAt(i);\n                if (ch == '\\\\') {\n                    hasSpecial = true;\n                    continue;\n                }\n                if (ch == '\"') {\n                    endIndex = i;\n                    break;\n                }\n            }\n\n            if (endIndex == -1) {\n                throw new ParserException(\"unclosed str. \" + info());\n            }\n\n            String stringVal;\n            if (token == Token.AS) {\n                stringVal = text.substring(pos, endIndex + 1);\n            } else {\n                if (startIndex == endIndex) {\n                    stringVal = \"\";\n                } else {\n                    stringVal = text.substring(startIndex, endIndex);\n                }\n            }\n\n            if (!hasSpecial) {\n                this.stringVal = stringVal;\n                int pos = endIndex + 1;\n                char ch = charAt(pos);\n                if (ch != '\"') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = LITERAL_CHARS;\n                    return;\n                }\n            }\n        }\n\n        mark = pos;\n        boolean hasSpecial = false;\n        Token preToken = this.token;\n\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                switch (ch) {\n                    case '\\'':\n                        putChar('\\'');\n                        break;\n                    case '\"':\n                        putChar('\"');\n                        break;\n                    case '\\\\':\n                        putChar('\\\\');\n                        break;\n                    default:\n                        putChar('\\\\');\n                        putChar(ch);\n                        break;\n                }\n\n                continue;\n            }\n\n            if (ch == '\"') {\n                scanChar();\n                if (ch != '\"') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\"');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            if (preToken == Token.AS) {\n                stringVal = subString(mark, bufPos + 2);\n            } else {\n                stringVal = subString(mark + 1, bufPos);\n            }\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = BIGQUERY_FEATURE;\n    }\n\n    @Override\n    public void scanSharp() {\n        scanComment();\n    }\n\n    @Override\n    public void scanComment() {\n        if ((ch == '/' && charAt(pos + 1) == '/')\n                || (ch == '-' && charAt(pos + 1) == '-')\n                || (ch == '#')) {\n            scanSingleLineComment();\n        } else if (ch == '/' && charAt(pos + 1) == '*') {\n            scanMultiLineComment();\n        } else {\n            throw new IllegalStateException();\n        }\n    }\n\n    @Override\n    protected void scanString() {\n        if (pos + 2 < text.length()\n                && text.charAt(pos + 1) == '\\''\n                && text.charAt(pos + 2) == '\\''\n        ) {\n            for (int i = pos + 3; i < text.length(); i++) {\n                char c = text.charAt(i);\n                if (c == '\\''\n                        && i + 2 < text.length()\n                        && text.charAt(i + 1) == '\\''\n                        && text.charAt(i + 2) == '\\''\n                ) {\n                    stringVal = text.substring(pos + 3, i);\n                    token = Token.LITERAL_TEXT_BLOCK;\n                    pos = i + 2;\n                    scanChar();\n                    return;\n                }\n            }\n        }\n\n        {\n            boolean hasSpecial = false;\n            int startIndex = pos + 1;\n            int endIndex = -1; // text.indexOf('\\'', startIndex);\n            for (int i = startIndex; i < text.length(); ++i) {\n                final char ch = text.charAt(i);\n                if (ch == '\\\\') {\n                    hasSpecial = true;\n                    continue;\n                }\n                if (ch == '\\'') {\n                    endIndex = i;\n                    break;\n                }\n            }\n\n            if (endIndex == -1) {\n                throw new ParserException(\"unclosed str. \" + info());\n            }\n\n            String stringVal;\n            if (token == Token.AS) {\n                stringVal = text.substring(pos, endIndex + 1);\n            } else {\n                if (startIndex == endIndex) {\n                    stringVal = \"\";\n                } else {\n                    stringVal = text.substring(startIndex, endIndex);\n                }\n            }\n            // hasSpecial = stringVal.indexOf('\\\\') != -1;\n\n            if (!hasSpecial) {\n                this.stringVal = stringVal;\n                int pos = endIndex + 1;\n                char ch = charAt(pos);\n                if (ch != '\\'') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = LITERAL_CHARS;\n                    return;\n                }\n            }\n        }\n\n        mark = pos;\n        boolean hasSpecial = false;\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                switch (ch) {\n                    case '\\'':\n                        putChar('\\'');\n                        break;\n                    case '\"':\n                        putChar('\"');\n                        break;\n                    case '\\\\':\n                        putChar('\\\\');\n                        break;\n                    default:\n                        putChar('\\\\');\n                        putChar(ch);\n                        break;\n                }\n\n                continue;\n            }\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQuerySelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQuerySelectQueryBlock;\nimport com.alibaba.druid.sql.parser.*;\n\npublic class BigQuerySelectParser extends SQLSelectParser {\n    public BigQuerySelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.bigquery;\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new BigQueryExprParser(lexer);\n    }\n\n    @Override\n    protected BigQuerySelectQueryBlock createSelectQueryBlock() {\n        return new BigQuerySelectQueryBlock();\n    }\n\n    protected void querySelectListBefore(SQLSelectQueryBlock x) {\n        if (lexer.nextIf(Token.DISTINCT)) {\n            x.setDistinct();\n        }\n        if (lexer.nextIf(Token.AS)) {\n            acceptIdentifier(\"STRUCT\");\n            ((BigQuerySelectQueryBlock) x).setAsStruct(true);\n        }\n        if (lexer.nextIf(Token.WITH)) {\n            acceptIdentifier(\"DIFFERENTIAL_PRIVACY\");\n            acceptIdentifier(\"OPTIONS\");\n            BigQuerySelectQueryBlock.DifferentialPrivacy clause = new BigQuerySelectQueryBlock.DifferentialPrivacy();\n            exprParser.parseAssignItem(clause.getOptions(), clause);\n            ((BigQuerySelectQueryBlock) x).setDifferentialPrivacy(clause);\n        }\n    }\n\n    protected boolean parseSelectListFromError() {\n        return false;\n    }\n\n    protected String tableAlias(boolean must) {\n        Token tok = lexer.token();\n        if (tok == Token.TABLE || tok == Token.UPDATE) {\n            String alias = lexer.stringVal();\n            lexer.nextToken();\n            return alias;\n        }\n        return super.tableAlias(must);\n    }\n\n    protected void queryBefore(SQLSelectQueryBlock x) {\n        if (lexer.token() == Token.WITH) {\n            BigQuerySelectQueryBlock queryBlock = (BigQuerySelectQueryBlock) x;\n            queryBlock.setWith(\n                    this.parseWith()\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.parser;\n\nimport com.alibaba.druid.sql.ast.SQLDeclareItem;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryAssertStatement;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryCreateModelStatement;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryExecuteImmediateStatement;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryExportDataStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class BigQueryStatementParser extends SQLStatementParser {\n    public BigQueryStatementParser(String sql) {\n        super(new BigQueryExprParser(sql));\n    }\n\n    public BigQueryStatementParser(String sql, SQLParserFeature... features) {\n        super(new BigQueryExprParser(sql, features));\n    }\n\n    public BigQueryStatementParser(Lexer lexer) {\n        super(new BigQueryExprParser(lexer));\n    }\n\n    public BigQuerySelectParser createSQLSelectParser() {\n        return new BigQuerySelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new BigQueryCreateTableParser(this.exprParser);\n    }\n\n    @Override\n    public void parseCreateTableSupportSchema() {\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n    }\n\n    @Override\n    public SQLStatement parseCreateDatabase() {\n        SQLStatement stmt = super.parseCreateDatabase();\n        if (stmt instanceof SQLCreateDatabaseStatement) {\n            SQLCreateDatabaseStatement createDb = (SQLCreateDatabaseStatement) stmt;\n            if (lexer.nextIfIdentifier(FnvHash.Constants.OPTIONS)) {\n                accept(Token.LPAREN);\n                for (;;) {\n                    SQLAssignItem item = this.exprParser.parseAssignItem(true, createDb);\n                    item.setParent(createDb);\n                    createDb.getOptions().put(\n                            item.getTarget().toString(),\n                            item.getValue()\n                    );\n                    if (lexer.nextIf(Token.COMMA)) {\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n        }\n        return stmt;\n    }\n\n    @Override\n    public SQLCreateProcedureStatement parseCreateProcedure() {\n        SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement();\n        stmt.setDbType(dbType);\n\n        accept(Token.CREATE);\n        if (lexer.nextIf(Token.OR)) {\n            accept(Token.REPLACE);\n            stmt.setOrReplace(true);\n        }\n\n        accept(Token.PROCEDURE);\n\n        stmt.setName(this.exprParser.name());\n\n        parameters(stmt.getParameters(), stmt);\n\n        SQLStatement block;\n        if (lexer.token() == Token.BEGIN) {\n            block = this.parseBlock();\n        } else {\n            block = this.parseStatement();\n        }\n\n        stmt.setBlock(block);\n\n        return stmt;\n    }\n\n    @Override\n    public SQLCreateFunctionStatement parseCreateFunction() {\n        SQLCreateFunctionStatement createFunction = new SQLCreateFunctionStatement();\n        accept(Token.CREATE);\n        if (lexer.nextIf(Token.OR)) {\n            accept(Token.REPLACE);\n            createFunction.setOrReplace(true);\n        }\n        if (lexer.nextIfIdentifier(\"TEMP\")\n                || lexer.nextIfIdentifier(FnvHash.Constants.TEMPORARY)) {\n            createFunction.setTemporary(true);\n        }\n        accept(Token.FUNCTION);\n        if (lexer.nextIf(Token.IF)) {\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            createFunction.setIfNotExists(true);\n        }\n        createFunction.setName(\n                this.exprParser.name());\n\n        parameters(createFunction.getParameters(), createFunction);\n        if (lexer.nextIfIdentifier(FnvHash.Constants.RETURNS)) {\n            createFunction.setReturnDataType(\n                    this.exprParser.parseDataType()\n            );\n        }\n\n        for (;;) {\n            if (lexer.nextIfIdentifier(\"LANGUAGE\")) {\n                createFunction.setLanguage(\n                        lexer.stringVal()\n                );\n                accept(Token.IDENTIFIER);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(FnvHash.Constants.OPTIONS)) {\n                exprParser.parseAssignItem(createFunction.getOptions(), createFunction);\n                continue;\n            }\n\n            if (lexer.nextIf(Token.AS)) {\n                if (lexer.nextIf(Token.LPAREN)) {\n                    createFunction.setBlock(\n                            new SQLExprStatement(\n                                    this.exprParser.expr()));\n                    accept(Token.RPAREN);\n                } else {\n                    lexer.nextIfIdentifier(\"R\");\n                    String script = lexer.stringVal();\n                    if (script.startsWith(\"\\\"\") && script.endsWith(\"\\\"\")) {\n                        script = script.substring(1, script.length() - 1);\n                    }\n                    createFunction.setWrappedSource(\n                            script\n                    );\n                    if (lexer.token() == Token.LITERAL_TEXT_BLOCK || lexer.token() == Token.LITERAL_CHARS) {\n                        lexer.nextToken();\n                    } else {\n                        setErrorEndPos(lexer.pos());\n                        printError(lexer.token());\n                    }\n                }\n                continue;\n            }\n\n            break;\n        }\n\n        if (lexer.nextIf(Token.SEMI)) {\n            createFunction.setAfterSemi(true);\n        }\n        return createFunction;\n    }\n\n    public SQLStatement parseDeclare() {\n        accept(Token.DECLARE);\n        SQLDeclareStatement declareStatement = new SQLDeclareStatement();\n        for (; ; ) {\n            SQLDeclareItem item = new SQLDeclareItem();\n            item.setName(exprParser.name());\n            declareStatement.addItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n            } else if (lexer.token() != Token.EOF) {\n                item.setDataType(exprParser.parseDataType());\n                if (lexer.nextIf(Token.DEFAULT)) {\n                    item.setValue(exprParser.expr());\n                }\n                break;\n            } else {\n                throw new ParserException(\"TODO. \" + lexer.info());\n            }\n        }\n        return declareStatement;\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.identifierEquals(\"ASSERT\")) {\n            statementList.add(parseAssert());\n            return true;\n        }\n        if (lexer.token() == Token.BEGIN) {\n            statementList.add(parseBlock());\n            return true;\n        }\n        if (lexer.token() == Token.RAISE) {\n            statementList.add(parseRaise());\n            return true;\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.EXPORT)) {\n            statementList.add(parseExportData());\n            return true;\n        }\n        return false;\n    }\n\n    protected SQLStatement parseExportData() {\n        acceptIdentifier(\"EXPORT\");\n        acceptIdentifier(\"DATA\");\n\n        BigQueryExportDataStatement stmt = new BigQueryExportDataStatement();\n\n        if (lexer.nextIf(Token.WITH)) {\n            acceptIdentifier(\"CONNECTION\");\n            SQLExprTableSource connection = new SQLExprTableSource(this.exprParser.name());\n            stmt.setConnection(connection);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.OPTIONS)) {\n            exprParser.parseAssignItem(stmt.getOptions(), stmt);\n        }\n\n        if (lexer.nextIf(Token.AS)) {\n            accept(Token.LPAREN);\n            SQLSelect select = createSQLSelectParser().select();\n            SQLSelectStatement selectStmt = new SQLSelectStatement(select, dbType);\n            stmt.setAsSelect(selectStmt);\n            accept(Token.RPAREN);\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseExecute() {\n        acceptIdentifier(FnvHash.Constants.EXECUTE);\n        acceptIdentifier(\"IMMEDIATE\");\n\n        BigQueryExecuteImmediateStatement stmt = new BigQueryExecuteImmediateStatement();\n        stmt.setDynamicSql(\n                this.exprParser.expr()\n        );\n        if (lexer.nextIf(Token.INTO)) {\n            this.exprParser.exprList(stmt.getInto(), stmt);\n        }\n        if (lexer.nextIf(Token.USING)) {\n            for (;;) {\n                SQLExpr expr = this.exprParser.expr();\n                String alias = null;\n                if (lexer.nextIf(Token.AS)) {\n                    alias = lexer.stringVal();\n                    lexer.nextToken();\n                }\n                stmt.addUsing(expr, alias);\n                if (lexer.nextIf(Token.COMMA)) {\n                    continue;\n                }\n                break;\n            }\n        }\n        return stmt;\n    }\n\n    public SQLStatement parseRaise() {\n        accept(Token.RAISE);\n        SQLRaiseStatement sqlRaiseStatement = new SQLRaiseStatement();\n        if (lexer.nextIf(Token.USING)) {\n            acceptIdentifier(\"MESSAGE\");\n            accept(Token.EQ);\n            sqlRaiseStatement.setMessage(exprParser.expr());\n        }\n\n        return sqlRaiseStatement;\n    }\n\n    protected SQLStatement parseAssert() {\n        acceptIdentifier(\"ASSERT\");\n        BigQueryAssertStatement stmt = new BigQueryAssertStatement();\n        stmt.setExpr(\n                exprParser.expr()\n        );\n        if (lexer.nextIf(Token.AS)) {\n            SQLExpr asExpr = exprParser.primary();\n            if (asExpr instanceof SQLCharExpr) {\n                stmt.setAs((SQLCharExpr) asExpr);\n            } else {\n                throw new ParserException(\"syntax error, expect string literal after AS, actual \" + asExpr.getClass().getSimpleName() + \". \" + lexer.info());\n            }\n        }\n        return stmt;\n    }\n\n    public SQLDeleteStatement parseDeleteStatement() {\n        SQLDeleteStatement deleteStatement = new SQLDeleteStatement(getDbType());\n\n        accept(Token.DELETE);\n        lexer.nextIf(Token.FROM);\n\n        SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n        deleteStatement.setTableSource(tableSource);\n\n        if (lexer.nextIf(Token.WHERE)) {\n            SQLExpr where = this.exprParser.expr();\n            deleteStatement.setWhere(where);\n        }\n\n        return deleteStatement;\n    }\n\n    @Override\n    protected void mergeBeforeName() {\n        this.lexer.nextIf(Token.INTO);\n    }\n\n    public SQLStatement parseBlock() {\n        accept(Token.BEGIN);\n        if (lexer.identifierEquals(\"TRANSACTION\") || lexer.identifierEquals(\"TRAN\")) {\n            lexer.nextToken();\n            SQLStartTransactionStatement startTrans = new SQLStartTransactionStatement(dbType);\n            if (lexer.token() == Token.IDENTIFIER) {\n                SQLName name = this.exprParser.name();\n                startTrans.setName(name);\n            }\n            return startTrans;\n        }\n        SQLBlockStatement block = new SQLBlockStatement();\n        parseStatementList(block.getStatementList(), -1, block);\n        if (lexer.token() == Token.EXCEPTION) {\n            block.setException(parseException());\n        }\n        accept(Token.END);\n        return block;\n    }\n\n    protected void createViewAs(SQLCreateViewStatement createView) {\n        if (lexer.nextIfIdentifier(FnvHash.Constants.OPTIONS)) {\n            exprParser.parseAssignItem(createView.getOptions(), createView);\n        }\n        super.createViewAs(createView);\n    }\n\n    @Override\n    protected SQLStatement parseCreateModel() {\n        accept(Token.CREATE);\n        acceptIdentifier(\"MODEL\");\n\n        BigQueryCreateModelStatement stmt = new BigQueryCreateModelStatement();\n        if (lexer.nextIf(Token.IF)) {\n           accept(Token.NOT);\n           accept(Token.EXISTS);\n           stmt.setIfNotExists(true);\n        } else if (lexer.nextIf(Token.OR)) {\n            accept(Token.REPLACE);\n            stmt.setReplace(true);\n        }\n        stmt.setName(\n                exprParser.name()\n        );\n\n        if (lexer.nextIfIdentifier(\"OPTIONS\")) {\n            exprParser.parseAssignItem(stmt.getOptions(), stmt);\n        }\n\n        if (lexer.nextIf(Token.AS)) {\n            accept(Token.LPAREN);\n            acceptIdentifier(\"TRAINING_DATA\");\n            accept(Token.AS);\n            accept(Token.LPAREN);\n            stmt.setTrainingData(\n                    parseStatement0()\n            );\n            accept(Token.RPAREN);\n\n            accept(Token.COMMA);\n            acceptIdentifier(\"CUSTOM_HOLIDAY\");\n            accept(Token.AS);\n            accept(Token.LPAREN);\n            stmt.setCustomHoliday(\n                    parseStatement0()\n            );\n            accept(Token.RPAREN);\n            accept(Token.RPAREN);\n        }\n\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQueryASTVisitorAdapter.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class BigQueryASTVisitorAdapter extends SQLASTVisitorAdapter implements BigQueryVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQueryOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.bigquery.BQ;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class BigQueryOutputVisitor extends SQLASTOutputVisitor\n        implements BigQueryVisitor {\n    public BigQueryOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.bigquery, BQ.DIALECT);\n    }\n\n    public BigQueryOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.bigquery, BQ.DIALECT, parameterized);\n    }\n\n    protected void printPartitionedBy(SQLCreateTableStatement x) {\n        List<SQLExpr> partitionBy;\n        if (!(x instanceof BigQueryCreateTableStatement)) {\n            return;\n        } else {\n            partitionBy = ((BigQueryCreateTableStatement) x).getPartitionBy();\n        }\n        if (partitionBy.isEmpty()) {\n            return;\n        }\n        println();\n        print0(ucase ? \"PARTITION BY \" : \"partition by \");\n        printAndAccept(((BigQueryCreateTableStatement) x).getPartitionBy(), \",\");\n    }\n\n    protected void printPartitionedByColumn(SQLColumnDefinition column) {\n        String function = (String) column.getName().getAttribute(\"function\");\n        if (function != null) {\n            print0(function);\n            print('(');\n        }\n        column.accept(this);\n        if (function != null) {\n            print(')');\n        }\n    }\n\n    protected void printCreateTableLike(SQLCreateTableStatement x) {\n        SQLExprTableSource like = x.getLike();\n        if (like == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"CLONE \" : \"clone \");\n        like.accept(this);\n    }\n\n    public boolean visit(BigQuerySelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    protected void printSelectListBefore(SQLSelectQueryBlock x) {\n        if (x instanceof BigQuerySelectQueryBlock) {\n            printSelectListBefore((BigQuerySelectQueryBlock) x);\n            return;\n        }\n\n        super.printSelectListBefore(x);\n    }\n\n    protected void printSelectListBefore(BigQuerySelectQueryBlock x) {\n        if (x.isAsStruct()) {\n            print0(ucase ? \" AS STRUCT\" : \" as struct\");\n        }\n\n        BigQuerySelectQueryBlock.DifferentialPrivacy privacy = x.getDifferentialPrivacy();\n        if (privacy != null) {\n            incrementIndent();\n            println();\n            privacy.accept(this);\n            decrementIndent();\n        } else {\n            print(' ');\n        }\n    }\n\n    public boolean visit(BigQuerySelectQueryBlock.DifferentialPrivacy x) {\n        print0(ucase ? \"WITH DIFFERENTIAL_PRIVACY\" : \"with differential_privacy\");\n        println();\n        print0(ucase ? \"OPTIONS (\" : \"options (\");\n        printAndAccept(x.getOptions(), \",\");\n        print(')');\n        println();\n        return false;\n    }\n\n    protected void printColumnProperties(SQLColumnDefinition x) {\n        List<SQLAssignItem> colProperties = x.getColPropertiesDirect();\n        if (colProperties == null || colProperties.isEmpty()) {\n            return;\n        }\n        print0(ucase ? \" OPTIONS (\" : \" options (\");\n        printAndAccept(colProperties, \", \");\n        print0(ucase ? \")\" : \")\");\n    }\n\n    @Override\n    public boolean visit(SQLStructDataType.Field x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            name.accept(this);\n            print(' ');\n        }\n        SQLDataType dataType = x.getDataType();\n\n        if (dataType != null) {\n            dataType.accept(this);\n        }\n\n        if (!x.getConstraints().isEmpty()) {\n            print(' ');\n            printAndAccept(x.getConstraints(), \",\");\n        }\n\n        if (!x.getOptions().isEmpty()) {\n            print(' ');\n            print0(ucase ? \"OPTIONS (\" : \"options (\");\n            printAndAccept(x.getOptions(), \",\");\n            print0(ucase ? \")\" : \")\");\n        }\n        return false;\n    }\n\n    protected void printClusteredBy(SQLCreateTableStatement x) {\n        List<SQLSelectOrderByItem> clusteredBy = x.getClusteredBy();\n        if (clusteredBy.isEmpty()) {\n            return;\n        }\n        println();\n        print0(ucase ? \"CLUSTER BY \" : \"cluster by \");\n        printAndAccept(clusteredBy, \",\");\n    }\n\n    @Override\n    protected void printCreateFunctionBody(SQLCreateFunctionStatement x) {\n        printCreateFunctionReturns(x);\n\n        String language = x.getLanguage();\n        if (language != null) {\n            println();\n            print0(ucase ? \"LANGUAGE \" : \"language \");\n            print0(language);\n        }\n        List<SQLAssignItem> options = x.getOptions();\n        printOptions(options);\n\n        String wrappedSource = x.getWrappedSource();\n        if (wrappedSource != null) {\n            println();\n            print0(\"AS \\\"\\\"\\\"\");\n            print0(wrappedSource);\n            print0(\"\\\"\\\"\\\"\");\n        } else {\n            SQLStatement block = x.getBlock();\n            if (block != null) {\n                println();\n                print0(ucase ? \"AS (\" : \"as (\");\n                block.accept(this);\n                print(')');\n            }\n        }\n    }\n\n    protected void printOptions(List<SQLAssignItem> options) {\n        if (!options.isEmpty()) {\n            println();\n            print0(ucase ? \"OPTIONS (\" : \"options (\");\n            printAndAccept(options, \",\");\n            print(')');\n        }\n    }\n\n    protected void printCreateFunctionReturns(SQLCreateFunctionStatement x) {\n        SQLDataType returnDataType = x.getReturnDataType();\n        if (returnDataType == null) {\n            return;\n        }\n        println();\n        print(ucase ? \"RETURNS \" : \"returns \");\n        returnDataType.accept(this);\n    }\n\n    protected void printFetchFirst(SQLSelectQueryBlock x) {\n        SQLLimit limit = x.getLimit();\n        if (limit == null) {\n            return;\n        }\n        println();\n        limit.accept(this);\n    }\n\n    protected void printLifeCycle(SQLExpr lifeCycle) {\n        if (lifeCycle == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"LIFECYCLE = \" : \"lifecycle = \");\n        lifeCycle.accept(this);\n    }\n\n    public boolean visit(BigQueryAssertStatement x) {\n        print0(ucase ? \"ASSERT \" : \"assert \");\n        x.getExpr().accept(this);\n        SQLCharExpr as = x.getAs();\n        if (as != null) {\n            println();\n            print0(ucase ? \"AS \" : \"as \");\n            as.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLCastExpr x) {\n        tryPrintLparen(x);\n        if (x.isTry()) {\n            print0(ucase ? \"SAFE_CAST(\" : \"safe_cast(\");\n        } else {\n            print0(ucase ? \"CAST(\" : \"cast(\");\n        }\n        x.getExpr().accept(this);\n        print0(ucase ? \" AS \" : \" as \");\n        x.getDataType().accept(this);\n\n        SQLExpr format = x.getFormat();\n        if (format != null) {\n            print0(ucase ? \" FORMAT \" : \" format \");\n            format.accept(this);\n        }\n\n        print0(\")\");\n        tryPrintRparen(x);\n        return false;\n    }\n\n    protected void printTableOption(SQLExpr name, SQLExpr value, int index) {\n        if (index != 0) {\n            print(\",\");\n            println();\n        }\n        String key = name.toString();\n        print0(key);\n        print0(\" = \");\n        value.accept(this);\n    }\n\n    protected void printCollate(SQLCreateTableStatement x) {\n        if (x instanceof BigQueryCreateTableStatement) {\n            BigQueryCreateTableStatement bigQueryCreateTableStatement = (BigQueryCreateTableStatement) x;\n            if (bigQueryCreateTableStatement.getCollate() != null) {\n                println();\n                print0(ucase ? \"DEFAULT COLLATE \" : \"default collate \");\n                bigQueryCreateTableStatement.getCollate().accept(this);\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLAtTimeZoneExpr x) {\n        x.getExpr().accept(this);\n        SQLExpr timeZone = x.getTimeZone();\n        print0(ucase ? \" AT TIME ZONE \" : \" at time zone \");\n        timeZone.accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAggregateExpr x) {\n        boolean parameterized = this.parameterized;\n        if (x.methodNameHashCode64() == FnvHash.Constants.GROUP_CONCAT) {\n            this.parameterized = false;\n        }\n        if (x.methodNameHashCode64() == FnvHash.Constants.COUNT) {\n            List<SQLExpr> arguments = x.getArguments();\n            if (arguments.size() == 1) {\n                SQLExpr arg0 = arguments.get(0);\n                if (arg0 instanceof SQLLiteralExpr) {\n                    this.parameterized = false;\n                }\n            }\n        }\n\n        if (x.getOwner() != null) {\n            printExpr(x.getOwner());\n            print(\".\");\n        }\n\n        String methodName = x.getMethodName();\n        print0(ucase ? methodName : methodName.toLowerCase());\n        print('(');\n\n        SQLAggregateOption option = x.getOption();\n        if (option != null) {\n            print0(option.toString());\n            print(' ');\n        }\n\n        List<SQLExpr> arguments = x.getArguments();\n        for (int i = 0, size = arguments.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            printExpr(arguments.get(i), false);\n        }\n\n        if (x.isIgnoreNulls()) {\n            print0(ucase ? \" IGNORE NULLS\" : \" ignore nulls\");\n        }\n\n        if (x.isRespectNulls()) {\n            print0(ucase ? \" RESPECT NULLS\" : \" respect nulls\");\n        }\n\n        visitAggregateRest(x);\n\n        print(')');\n\n        SQLKeep keep = x.getKeep();\n        if (keep != null) {\n            print(' ');\n            visit(keep);\n        }\n\n        SQLOver over = x.getOver();\n        if (over != null) {\n            print0(ucase ? \" OVER \" : \" over \");\n            over.accept(this);\n        }\n\n        final SQLName overRef = x.getOverRef();\n        if (overRef != null) {\n            print0(ucase ? \" OVER \" : \" over \");\n            overRef.accept(this);\n        }\n\n        final SQLExpr filter = x.getFilter();\n        if (filter != null) {\n            print0(ucase ? \" FILTER (WHERE \" : \" filter (where \");\n            printExpr(filter);\n            print(')');\n        }\n\n        this.parameterized = parameterized;\n        return false;\n    }\n\n    public boolean visit(BigQueryCharExpr x) {\n        if (x.hasPrefix()) {\n            print0(x.getPrefix());\n        }\n        if (x.isSpace()) {\n            print0(\" \");\n        }\n        if (!x.isAlias()) {\n            print(\"'\");\n        }\n        print(x.getText());\n        if (!x.isAlias()) {\n            print(\"'\");\n        }\n        return false;\n    }\n\n    protected void printName0(String text) {\n        if (text.length() > 1\n                && text.charAt(0) != '`'\n                && text.indexOf('-') != -1\n        ) {\n            appender.append('`');\n            appender.append(text);\n            appender.append('`');\n            return;\n        }\n        super.printName0(text);\n    }\n\n    protected void printCreateViewAs(SQLCreateViewStatement x) {\n        printOptions(x.getOptions());\n        super.printCreateViewAs(x);\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement x) {\n        print0(ucase ? \"IF \" : \"if \");\n        x.getCondition().accept(this);\n        this.indentCount++;\n        println();\n        print0(ucase ? \"THEN\" : \"then\");\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n\n        for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) {\n            println();\n            elseIf.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            x.getElseItem().accept(this);\n        }\n        println();\n        print0(ucase ? \"END IF\" : \"end if\");\n        return false;\n    }\n\n    public boolean visit(BigQueryExecuteImmediateStatement x) {\n        super.visit(x);\n        List<SQLAliasedExpr> using = x.getUsing();\n        if (!using.isEmpty()) {\n            print0(ucase ? \" USING \" : \" using \");\n            printAndAccept(using, \", \");\n        }\n        return false;\n    }\n\n    public boolean visit(BigQueryCreateModelStatement x) {\n        print0(ucase ? \" CREATE \" : \" create \");\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        if (x.isReplace()) {\n            print0(ucase ? \"OR REPLACE \" : \"or replace \");\n        }\n        print0(ucase ? \"MODEL \" : \"model \");\n        x.getName().accept(this);\n        println();\n\n        incrementIndent();\n        println(ucase ? \"OPTIONS (\" : \"options (\");\n        printlnAndAccept(x.getOptions(), \",\");\n        decrementIndent();\n        println();\n        println(')');\n\n        print0(ucase ? \"AS (\" : \"as (\");\n        incrementIndent();\n        println();\n\n        incrementIndent();\n        println(ucase ? \"TRAINING_DATA AS (\" : \"training_data AS (\");\n        x.getTrainingData().accept(this);\n        decrementIndent();\n        println();\n\n        println(\"),\");\n        incrementIndent();\n        println(ucase ? \"CUSTOM_HOLIDAY AS (\" : \"custom_holiday AS (\");\n        x.getCustomHoliday().accept(this);\n        decrementIndent();\n        println();\n        decrementIndent();\n        println(\")\");\n        print0(')');\n        return false;\n    }\n\n    public boolean visit(BigQueryModelExpr x) {\n        print0(ucase ? \"MODEL \" : \"model \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    public boolean visit(BigQueryTableExpr x) {\n        print0(ucase ? \"TABLE \" : \"table \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateProcedureStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE PROCEDURE \" : \"create or replace procedure \");\n        } else {\n            print0(ucase ? \"CREATE PROCEDURE \" : \"create procedure \");\n        }\n        x.getName().accept(this);\n\n        int paramSize = x.getParameters().size();\n        if (paramSize > 0) {\n            print0(\" (\");\n            this.indentCount++;\n            println();\n            for (int i = 0; i < paramSize; ++i) {\n                if (i != 0) {\n                    print(',');\n                    println();\n                }\n                x.getParameters().get(i).accept(this);\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        SQLStatement block = x.getBlock();\n        if (block != null) {\n            println();\n            block.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(BigQueryExportDataStatement x) {\n        print0(ucase ? \"EXPORT DATA\" : \"export data\");\n\n        SQLExprTableSource connection = x.getConnection();\n        if (connection != null) {\n            print0(ucase ? \" WITH CONNECTION \" : \" with connection \");\n            connection.accept(this);\n        }\n\n        println();\n        print0(ucase ? \"OPTIONS (\" : \"options (\");\n        printAndAccept(x.getOptions(), \",\");\n        print(')');\n\n        SQLStatement asSelect = x.getAsSelect();\n        if (asSelect != null) {\n            println();\n            print0(ucase ? \"AS (\" : \"as (\");\n            asSelect.accept(this);\n            print(')');\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQuerySchemaStatVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\npublic class BigQuerySchemaStatVisitor extends SchemaStatVisitor implements BigQueryVisitor {\n    public BigQuerySchemaStatVisitor() {\n        super(DbType.bigquery);\n    }\n\n    public BigQuerySchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQueryVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.bigquery.visitor;\n\nimport com.alibaba.druid.sql.dialect.bigquery.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface BigQueryVisitor extends SQLASTVisitor {\n    default boolean visit(BigQuerySelectQueryBlock x) {\n        return true;\n    }\n\n    default void endVisit(BigQuerySelectQueryBlock x) {\n    }\n\n    default boolean visit(BigQuerySelectQueryBlock.DifferentialPrivacy x) {\n        return true;\n    }\n\n    default void endVisit(BigQuerySelectQueryBlock.DifferentialPrivacy x) {\n    }\n\n    default boolean visit(BigQueryAssertStatement x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryAssertStatement x) {\n    }\n\n    default boolean visit(BigQueryCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryCreateTableStatement x) {\n    }\n\n    default boolean visit(BigQueryCharExpr x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryCharExpr x) {\n    }\n\n    default boolean visit(BigQueryExecuteImmediateStatement x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryExecuteImmediateStatement x) {\n    }\n\n    default boolean visit(BigQueryCreateModelStatement x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryCreateModelStatement x) {\n    }\n\n    default boolean visit(BigQueryModelExpr x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryModelExpr x) {\n    }\n\n    default boolean visit(BigQueryTableExpr x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryTableExpr x) {\n    }\n\n    default boolean visit(BigQueryExportDataStatement x) {\n        return true;\n    }\n\n    default void endVisit(BigQueryExportDataStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/Blink.java",
    "content": "package com.alibaba.druid.sql.dialect.blink;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Blink {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.blink);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/ast/BlinkCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.blink.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\n\npublic class BlinkCreateTableStatement extends SQLCreateTableStatement {\n    private SQLExpr periodFor;\n\n    public BlinkCreateTableStatement() {\n        dbType = DbType.blink;\n    }\n\n    public SQLExpr getPeriodFor() {\n        return periodFor;\n    }\n\n    public void setPeriodFor(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.periodFor = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/parser/BlinkCreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.blink.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLTableConstraint;\nimport com.alibaba.druid.sql.dialect.blink.ast.BlinkCreateTableStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class BlinkCreateTableParser extends SQLCreateTableParser {\n    public BlinkCreateTableParser(String sql) {\n        super(new BlinkExprParser(sql));\n    }\n\n    public BlinkCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        BlinkCreateTableStatement stmt = new BlinkCreateTableStatement();\n\n        accept(Token.CREATE);\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.EXTERNAL)) {\n            stmt.setExternal(true);\n        }\n\n        accept(Token.TABLE);\n\n        if (lexer.token() == Token.IF || lexer.identifierEquals(\"IF\")) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        accept(Token.LPAREN);\n\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            stmt.addBodyBeforeComment(lexer.readAndResetComments());\n        }\n\n        for_:\n        for (; ; ) {\n            SQLColumnDefinition column = null;\n            switch (lexer.token()) {\n                case IDENTIFIER:\n                case KEY:\n                    column = this.exprParser.parseColumn();\n                    column.setParent(stmt);\n                    stmt.getTableElementList().add(column);\n                    break;\n                case PRIMARY:\n                    SQLTableConstraint constraint = this.parseConstraint();\n                    constraint.setParent(stmt);\n                    stmt.getTableElementList().add(constraint);\n                    break;\n                case PERIOD:\n                    lexer.nextToken();\n                    accept(Token.FOR);\n                    SQLExpr periodFor = this.exprParser.primary();\n                    stmt.setPeriodFor(periodFor);\n                    break for_;\n                default:\n                    throw new ParserException(\"expect identifier. \" + lexer.info());\n            }\n\n//        } else if (lexer.token() == Token.CONSTRAINT //\n//                || lexer.token() == Token.PRIMARY //\n//                || lexer.token() == Token.UNIQUE) {\n//            SQLTableConstraint constraint = this.parseConstraint();\n//            constraint.setParent(stmt);\n//            stmt.getTableElementList().add(constraint);\n//        }\n\n            if (lexer.isKeepComments() && lexer.hasComment() && column != null) {\n                column.addAfterComment(lexer.readAndResetComments());\n            }\n\n            if (!(lexer.token() == (Token.COMMA))) {\n                break;\n            } else {\n                lexer.nextToken();\n\n                if (lexer.isKeepComments() && lexer.hasComment() && column != null) {\n                    column.addAfterComment(lexer.readAndResetComments());\n                }\n            }\n        }\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            stmt.setComment(this.exprParser.primary());\n        }\n\n        if (stmt.getClusteredBy().size() > 0 || stmt.getSortedBy().size() > 0) {\n            accept(Token.INTO);\n            if (lexer.token() == Token.LITERAL_INT) {\n                stmt.setBuckets(lexer.integerValue().intValue());\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"into buckets must be integer. \" + lexer.info());\n            }\n            acceptIdentifier(\"BUCKETS\");\n        }\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, true);\n            accept(Token.RPAREN);\n        }\n\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/parser/BlinkExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.blink.parser;\n\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class BlinkExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\", \"ROW_NUMBER\",\n                \"ROWNUMBER\"};\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public BlinkExprParser(String sql) {\n        this(new BlinkLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public BlinkExprParser(String sql, SQLParserFeature... features) {\n        this(new BlinkLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public BlinkExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/parser/BlinkLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.blink.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class BlinkLexer extends Lexer {\n    static final Keywords BLINK_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"IF\", Token.IF);\n        map.put(\"PERIOD\", Token.PERIOD);\n\n        BLINK_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return BLINK_KEYWORDS;\n    }\n\n    public BlinkLexer(String input) {\n        super(input);\n        dbType = DbType.blink;\n    }\n\n    public BlinkLexer(String input, SQLParserFeature... features) {\n        super(input);\n        dbType = DbType.blink;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/parser/BlinkStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.blink.parser;\n\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\n\npublic class BlinkStatementParser extends SQLStatementParser {\n    public BlinkStatementParser(String sql) {\n        super(new BlinkExprParser(sql));\n    }\n\n    public BlinkStatementParser(String sql, SQLParserFeature... features) {\n        super(new BlinkExprParser(sql, features));\n    }\n\n    public BlinkStatementParser(Lexer lexer) {\n        super(new BlinkExprParser(lexer));\n    }\n//\n//    public H2SelectParser createSQLSelectParser() {\n//        return new H2SelectParser(this.exprParser, selectListCache);\n//    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new BlinkCreateTableParser(this.exprParser);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/vsitor/BlinkOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.blink.vsitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.blink.Blink;\nimport com.alibaba.druid.sql.dialect.blink.ast.BlinkCreateTableStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\nimport java.util.List;\n\npublic class BlinkOutputVisitor extends SQLASTOutputVisitor implements BlinkVisitor {\n    public BlinkOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.blink, Blink.DIALECT);\n    }\n\n    public BlinkOutputVisitor(StringBuilder appender, DbType dbType) {\n        super(appender, dbType);\n    }\n\n    public BlinkOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.blink, parameterized);\n    }\n\n    @Override\n    public boolean visit(BlinkCreateTableStatement x) {\n        super.visit((SQLCreateTableStatement) x);\n        return false;\n    }\n\n    protected void printTableElements(List<SQLTableElement> tableElementList) {\n        int size = tableElementList.size();\n        if (size == 0) {\n            return;\n        }\n\n        BlinkCreateTableStatement stmt = (BlinkCreateTableStatement) tableElementList.get(0).getParent();\n\n        print0(\" (\");\n\n        this.indentCount++;\n        println();\n        for (int i = 0; i < size; ++i) {\n            SQLTableElement element = tableElementList.get(i);\n            element.accept(this);\n\n            if (i != size - 1) {\n                print(',');\n            }\n            if (this.isPrettyFormat() && element.hasAfterComment()) {\n                print(' ');\n                printlnComment(element.getAfterCommentsDirect());\n            }\n\n            if (i != size - 1) {\n                println();\n            }\n        }\n\n        if (stmt.getPeriodFor() != null) {\n            print(',');\n            println();\n            print0(ucase ? \"PERIOD FOR \" : \"period for \");\n            stmt.getPeriodFor().accept(this);\n        }\n        this.indentCount--;\n        println();\n        print(')');\n    }\n\n    @Override\n    public void endVisit(BlinkCreateTableStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/blink/vsitor/BlinkVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.blink.vsitor;\n\nimport com.alibaba.druid.sql.dialect.blink.ast.BlinkCreateTableStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface BlinkVisitor extends SQLASTVisitor {\n    boolean visit(BlinkCreateTableStatement x);\n\n    void endVisit(BlinkCreateTableStatement x);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/CK.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class CK {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.clickhouse);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/CKAlterTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\n\npublic abstract class CKAlterTableStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLName tableName;\n\n    private SQLName clusterName;\n\n    public CKAlterTableStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLName getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.tableName = tableName;\n    }\n\n    public SQLName getClusterName() {\n        return clusterName;\n    }\n\n    public void setClusterName(SQLName clusterName) {\n        this.clusterName = clusterName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/CKAlterTableUpdateStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CKAlterTableUpdateStatement extends CKAlterTableStatement {\n    protected final List<SQLUpdateSetItem> items = new ArrayList<SQLUpdateSetItem>();\n    private SQLName partitionId;\n    protected SQLExpr where;\n\n    public CKAlterTableUpdateStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public List<SQLUpdateSetItem> getItems() {\n        return items;\n    }\n\n    public SQLName getPartitionId() {\n        return partitionId;\n    }\n\n    public void setPartitionId(SQLName partitionId) {\n        this.partitionId = partitionId;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof CKASTVisitor) {\n            CKASTVisitor vv = (CKASTVisitor) v;\n            if (vv.visit(this)) {\n                acceptChild(vv, this.getTableName());\n                acceptChild(vv, this.getClusterName());\n                acceptChild(vv, this.getItems());\n                acceptChild(vv, this.getWhere());\n            }\n            vv.endVisit(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/CKCreateMaterializedViewStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateMaterializedViewStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CKCreateMaterializedViewStatement extends SQLCreateMaterializedViewStatement {\n    private String onCluster;\n    private SQLExpr engine;\n    private SQLExpr ckPartitionBy;\n    private SQLExpr primaryKey;\n    private SQLOrderBy orderBy;\n    private final List<SQLAssignItem> settings = new ArrayList<SQLAssignItem>();\n    private boolean populate;\n\n    public CKCreateMaterializedViewStatement() {\n        super.dbType = DbType.clickhouse;\n    }\n\n    public String getOnCluster() {\n        return onCluster;\n    }\n\n    public void setOnCluster(String onCluster) {\n        this.onCluster = onCluster;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.engine = x;\n    }\n\n    public SQLExpr getCkPartitionBy() {\n        return ckPartitionBy;\n    }\n\n    public void setCkPartitionBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.ckPartitionBy = x;\n    }\n\n    public SQLExpr getPrimaryKey() {\n        return primaryKey;\n    }\n\n    public void setPrimaryKey(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.primaryKey = x;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.orderBy = x;\n    }\n\n    public List<SQLAssignItem> getSettings() {\n        return settings;\n    }\n\n    public boolean isPopulate() {\n        return populate;\n    }\n\n    public void setPopulate(boolean populate) {\n        this.populate = populate;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof CKASTVisitor) {\n            CKASTVisitor ckVisitor = (CKASTVisitor) visitor;\n            if (ckVisitor.visit(this)) {\n                acceptChild(visitor, getName());\n                acceptChild(visitor, getTo());\n                acceptChild(visitor, engine);\n                acceptChild(visitor, ckPartitionBy);\n                acceptChild(visitor, primaryKey);\n                acceptChild(visitor, orderBy);\n                acceptChild(visitor, settings);\n                acceptChild(visitor, getQuery());\n            }\n            ckVisitor.endVisit(this);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/CKCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CKCreateTableStatement extends SQLCreateTableStatement {\n    protected final List<SQLAssignItem> settings = new ArrayList<SQLAssignItem>();\n    private SQLPrimaryKey primaryKey;\n    private SQLExpr sampleBy;\n\n    private SQLExpr ttl;\n    private String onClusterName;\n\n    public CKCreateTableStatement() {\n        super(DbType.clickhouse);\n    }\n\n    public SQLExpr getSampleBy() {\n        return sampleBy;\n    }\n\n    public void setSampleBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.sampleBy = x;\n    }\n\n    public List<SQLAssignItem> getSettings() {\n        return settings;\n    }\n\n    public SQLPrimaryKey getPrimaryKey() {\n        return primaryKey;\n    }\n\n    public void setPrimaryKey(SQLPrimaryKey primaryKey) {\n        if (primaryKey != null) {\n            primaryKey.setParent(this);\n        }\n        this.primaryKey = primaryKey;\n    }\n\n    public SQLExpr getTtl() {\n        return ttl;\n    }\n\n    public void setTtl(SQLExpr ttl) {\n        if (ttl != null) {\n            ttl.setParent(this);\n        }\n        this.ttl = ttl;\n    }\n\n    public String getOnClusterName() {\n        return onClusterName;\n    }\n\n    public void setOnClusterName(String onClusterName) {\n        this.onClusterName = onClusterName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof CKASTVisitor) {\n            CKASTVisitor vv = (CKASTVisitor) v;\n            if (vv.visit(this)) {\n                acceptChild(vv);\n            }\n            vv.endVisit(this);\n            return;\n        }\n\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/CKDropTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class CKDropTableStatement extends SQLDropTableStatement {\n    private String onClusterName;\n\n    public CKDropTableStatement() {\n        super(DbType.clickhouse);\n    }\n\n    public CKDropTableStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public String getOnClusterName() {\n        return onClusterName;\n    }\n\n    public void setOnClusterName(String onClusterName) {\n        this.onClusterName = onClusterName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof CKASTVisitor) {\n            CKASTVisitor vv = (CKASTVisitor) v;\n            if (vv.visit(this)) {\n                acceptChild(vv, tableSources);\n            }\n            vv.endVisit(this);\n            return;\n        }\n\n        super.accept0(v);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/CKSelectQueryBlock.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CKSelectQueryBlock extends SQLSelectQueryBlock {\n    {\n        dbType = DbType.clickhouse;\n    }\n\n    private SQLExpr preWhere;\n    private SQLExpr sample;\n    private SQLExpr format;\n    private boolean isFinal;\n    private boolean withTotals;\n    private boolean withFill;\n    private boolean withTies;\n    private List<SQLAssignItem> settings = new ArrayList<>();\n\n    public SQLExpr getPreWhere() {\n        return preWhere;\n    }\n\n    public void setPreWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.preWhere = x;\n    }\n\n    public SQLExpr getSample() {\n        return sample;\n    }\n\n    public void setSample(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.sample = x;\n    }\n\n    public SQLExpr getFormat() {\n        return format;\n    }\n\n    public void setFormat(SQLExpr format) {\n        this.format = format;\n    }\n\n    public List<SQLAssignItem> getSettings() {\n        return settings;\n    }\n\n    public void setSettings(List<SQLAssignItem> x) {\n        this.settings = x;\n    }\n\n    public boolean isFinal() {\n        return isFinal;\n    }\n    public void setFinal(boolean aFinal) {\n        isFinal = aFinal;\n    }\n\n    public boolean isWithTotals() {\n        return withTotals;\n    }\n\n    public void setWithTotals(boolean withTotals) {\n        this.withTotals = withTotals;\n    }\n\n    public boolean isWithFill() {\n        return withFill;\n    }\n\n    public void setWithFill(boolean withFill) {\n        this.withFill = withFill;\n    }\n\n    public boolean isWithTies() {\n        return withTies;\n    }\n\n    public void setWithTies(boolean withTies) {\n        this.withTies = withTies;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/ClickhouseColumnCodec.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class ClickhouseColumnCodec extends ClickhouseColumnConstraint {\n    private SQLExpr expr;\n    public ClickhouseColumnCodec() {\n        super();\n    }\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof CKASTVisitor) {\n            CKASTVisitor vv = (CKASTVisitor) v;\n            if (vv.visit(this)) {\n                acceptChild(vv, expr);\n            }\n            vv.endVisit(this);\n        }\n    }\n\n    @Override\n    public ClickhouseColumnCodec clone() {\n        ClickhouseColumnCodec clickhouseColumnCodec = new ClickhouseColumnCodec();\n        super.cloneTo(clickhouseColumnCodec);\n        clickhouseColumnCodec.setExpr(expr.clone());\n        return clickhouseColumnCodec;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/ClickhouseColumnConstraint.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLConstraintImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class ClickhouseColumnConstraint extends SQLConstraintImpl implements SQLColumnConstraint {\n    public ClickhouseColumnConstraint() {\n        dbType = DbType.clickhouse;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor v) {}\n\n    @Override\n    public ClickhouseColumnConstraint clone() {\n        ClickhouseColumnConstraint clickhouseColumnConstraint = new ClickhouseColumnConstraint();\n        cloneTo(clickhouseColumnConstraint);\n        return clickhouseColumnConstraint;\n    }\n\n    public void cloneTo(ClickhouseColumnConstraint x) {\n        super.cloneTo(x);\n        x.dbType = dbType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/ast/ClickhouseColumnTTL.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class ClickhouseColumnTTL extends ClickhouseColumnConstraint{\n    private SQLExpr expr;\n\n    public ClickhouseColumnTTL() {\n        super();\n    }\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof CKASTVisitor) {\n            CKASTVisitor vv = (CKASTVisitor) v;\n            if (vv.visit(this)) {\n                acceptChild(vv, expr);\n            }\n            vv.endVisit(this);\n        }\n    }\n\n    public ClickhouseColumnTTL clone() {\n        ClickhouseColumnTTL clickhouseColumnTTL = new ClickhouseColumnTTL();\n        super.cloneTo(clickhouseColumnTTL);\n        clickhouseColumnTTL.setExpr(expr.clone());\n        return clickhouseColumnTTL;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/parser/CKCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionByList;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKCreateTableStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class CKCreateTableParser extends SQLCreateTableParser {\n    public CKCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    protected SQLCreateTableStatement newCreateStatement() {\n        return new CKCreateTableStatement();\n    }\n\n    @Override\n    public SQLPartitionBy parsePartitionBy() {\n        lexer.nextToken();\n        accept(Token.BY);\n        SQLPartitionByList sqlPartitionBy = new SQLPartitionByList();\n        sqlPartitionBy.setType(SQLPartitionByList.PartitionByListType.LIST_EXPRESSION);\n        boolean hasParen = false;\n        if (lexer.nextIf(Token.LPAREN)) {\n            hasParen = true;\n        }\n        for (; ; ) {\n            sqlPartitionBy.addColumn(this.exprParser.expr());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        if (hasParen) {\n            accept(Token.RPAREN);\n        }\n\n        return sqlPartitionBy;\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        CKCreateTableStatement ckStmt = (CKCreateTableStatement) stmt;\n        if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            ckStmt.setEngine(\n                    this.exprParser.expr()\n            );\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            ckStmt.setPartitionBy(parsePartitionBy());\n        }\n\n        if (lexer.token() == Token.ORDER) {\n            SQLOrderBy orderBy = this.exprParser.parseOrderBy();\n            ckStmt.setOrderBy(orderBy);\n        }\n\n        if (lexer.token() == Token.PRIMARY) {\n            SQLPrimaryKey sqlPrimaryKey = this.exprParser.parsePrimaryKey();\n            ckStmt.setPrimaryKey(sqlPrimaryKey);\n        }\n\n        if (lexer.identifierEquals(\"SAMPLE\")) {\n            lexer.nextToken();\n            accept(Token.BY);\n            SQLExpr expr = this.exprParser.expr();\n            ckStmt.setSampleBy(expr);\n        }\n\n        if (lexer.token() == Token.TTL) {\n            lexer.nextToken();\n            SQLExpr expr = this.exprParser.expr();\n            ckStmt.setTtl(expr);\n        }\n\n        if (lexer.token() == Token.SETTINGS) {\n            lexer.nextToken();\n            for (; ; ) {\n                SQLAssignItem item = this.exprParser.parseAssignItem();\n                item.setParent(ckStmt);\n                ckStmt.getSettings().add(item);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n        }\n\n        if (lexer.nextIf(Token.COMMENT)) {\n            ckStmt.setComment(this.exprParser.expr());\n        }\n    }\n\n    @Override\n    protected void createTableAfterName(SQLCreateTableStatement createTable) {\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            acceptIdentifier(\"CLUSTER\");\n            // 支持 IDENTIFIER 或 DEFAULT 关键字作为 cluster 名称\n            if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.DEFAULT) {\n                String clusterName = lexer.stringVal();\n                CKCreateTableStatement ckStmt = (CKCreateTableStatement) createTable;\n                ckStmt.setOnClusterName(clusterName);\n                lexer.nextToken();\n            } else {\n                setErrorEndPos(lexer.pos());\n                throw new ParserException(\"syntax error, expect IDENTIFIER, actual \" + lexer.token() + \", \" + lexer.info());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/parser/CKExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.clickhouse.parser;\n\nimport com.alibaba.druid.sql.ast.SQLArrayDataType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStructDataType;\nimport com.alibaba.druid.sql.ast.expr.SQLArrayExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.ClickhouseColumnCodec;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.ClickhouseColumnTTL;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.LPAREN;\nimport static com.alibaba.druid.sql.parser.Token.RPAREN;\n\npublic class CKExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n    private static final List<String> NESTED_DATA_TYPE;\n\n    static {\n        String[] strings = {\"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\", \"ROW_NUMBER\",\n                \"ROWNUMBER\"};\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n        NESTED_DATA_TYPE = Arrays.asList(\"array\", \"tuple\", \"nullable\", \"lowcardinality\", \"variant\");\n    }\n\n    public CKExprParser(String sql) {\n        this(new CKLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public CKExprParser(String sql, SQLParserFeature... features) {\n        this(new CKLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public CKExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n        this.nestedDataType = NESTED_DATA_TYPE;\n    }\n\n    protected SQLExpr parseAliasExpr(String alias) {\n        String chars = alias.substring(1, alias.length() - 1);\n        return new SQLCharExpr(chars);\n    }\n\n    public SQLExpr primary() {\n        if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            return primaryRest(array);\n        }\n        return super.primary();\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            array.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            return primaryRest(array);\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    @Override\n    protected SQLColumnDefinition parseColumnSpecific(SQLColumnDefinition column) {\n        switch (lexer.token()) {\n            case CODEC: {\n                lexer.nextToken();\n                accept(LPAREN);\n                SQLExpr codecExpr = expr();\n                accept(RPAREN);\n                ClickhouseColumnCodec sqlColumnCodec = new ClickhouseColumnCodec();\n                sqlColumnCodec.setExpr(codecExpr);\n                column.addConstraint(sqlColumnCodec);\n                return parseColumnRest(column);\n                }\n            case TTL: {\n                lexer.nextToken();\n                ClickhouseColumnTTL clickhouseColumnTTL = new ClickhouseColumnTTL();\n                clickhouseColumnTTL.setExpr(expr());\n                column.addConstraint(clickhouseColumnTTL);\n                return parseColumnRest(column);\n            }\n            default:\n                return column;\n        }\n    }\n\n    @Override\n    protected SQLExpr primaryDefaultRest() {\n        return new SQLIdentifierExpr(lexer.stringVal());\n    }\n\n    @Override\n    protected SQLDataType parseDataTypeNested() {\n        lexer.nextToken();\n        accept(Token.LPAREN);\n\n        SQLStructDataType struct = new SQLStructDataType(dbType);\n\n        for (; ; ) {\n            SQLName name;\n            switch (lexer.token()) {\n                case GROUP:\n                case ORDER:\n                case FROM:\n                case TO:\n                    name = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                    break;\n                default:\n                    name = this.name();\n                    break;\n            }\n\n            SQLDataType dataType = this.parseDataType();\n            SQLStructDataType.Field field = struct.addField(name, dataType);\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                SQLCharExpr chars = (SQLCharExpr) this.primary();\n                field.setComment(chars.getText());\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        accept(Token.RPAREN);\n\n        return struct;\n    }\n\n    @Override\n    protected SQLArrayDataType parseArrayDataType() {\n        lexer.nextToken();\n        accept(Token.LPAREN);\n        SQLDataType itemType = parseDataType();\n        SQLArrayDataType array = new SQLArrayDataType(itemType, dbType);\n        accept(Token.RPAREN);\n        return array;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/parser/CKLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.DialectFeature;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\n\npublic class CKLexer extends Lexer {\n    static final Keywords CK_KEYWORDS;\n    static final DialectFeature CK_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    AsofJoin,\n                    GlobalJoin,\n                    JoinRightTableAlias,\n                    ParseLimitBy,\n                    TableAliasAsof\n            ),\n            null\n    );\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"IF\", Token.IF);\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"ALL\", Token.ALL);\n        map.put(\"GLOBAL\", Token.GLOBAL);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"ILIKE\", Token.ILIKE);\n        map.put(\"PREWHERE\", Token.PREWHERE);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n        map.put(\"FORMAT\", Token.FORMAT);\n        map.put(\"SETTINGS\", Token.SETTINGS);\n        map.put(\"FINAL\", Token.FINAL);\n        map.put(\"TTL\", Token.TTL);\n        map.put(\"CODEC\", Token.CODEC);\n        map.remove(\"ANY\");\n\n        CK_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return CK_KEYWORDS;\n    }\n\n    public CKLexer(String input, SQLParserFeature... features) {\n        super(input, DbType.clickhouse);\n        this.skipComment = true;\n        this.keepComments = true;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = CK_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/parser/CKSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class CKSelectParser\n        extends SQLSelectParser {\n    public CKSelectParser(Lexer lexer) {\n        super(lexer);\n    }\n\n    public CKSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLWithSubqueryClause parseWith() {\n        SQLWithSubqueryClause withQueryClause = new SQLWithSubqueryClause();\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            withQueryClause.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        accept(Token.WITH);\n\n        if (lexer.token() == Token.RECURSIVE || lexer.identifierEquals(FnvHash.Constants.RECURSIVE)) {\n            lexer.nextToken();\n            withQueryClause.setRecursive(true);\n        }\n\n        for (; ; ) {\n            SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry();\n            entry.setParent(withQueryClause);\n            SQLExpr sqlExpr = exprParser.expr();\n\n            if (sqlExpr instanceof SQLIdentifierExpr) {\n                String alias = ((SQLIdentifierExpr) sqlExpr).getName();\n                accept(Token.AS);\n                accept(Token.LPAREN);\n                entry.setSubQuery(select());\n                entry.setPrefixAlias(true);\n                entry.setAlias(alias);\n                accept(Token.RPAREN);\n            } else {\n                entry.setExpr(sqlExpr);\n                accept(Token.AS);\n                String alias = this.lexer.stringVal();\n                lexer.nextToken();\n                entry.setPrefixAlias(false);\n                entry.setAlias(alias);\n            }\n\n            withQueryClause.addEntry(entry);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        return withQueryClause;\n    }\n\n    @Override\n    protected SQLSelectQueryBlock createSelectQueryBlock() {\n        return new CKSelectQueryBlock();\n    }\n\n    @Override\n    public void parseWhere(SQLSelectQueryBlock queryBlock) {\n        if (lexer.nextIf(Token.PREWHERE)) {\n            SQLExpr preWhere = exprParser.expr();\n            ((CKSelectQueryBlock) queryBlock).setPreWhere(preWhere);\n        }\n        super.parseWhere(queryBlock);\n    }\n\n    @Override\n    public void parseFrom(SQLSelectQueryBlock queryBlock) {\n        List<String> comments = null;\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            comments = lexer.readAndResetComments();\n        }\n\n        if (lexer.nextIf(Token.FROM)) {\n            SQLTableSource from = parseTableSource();\n\n            if (comments != null) {\n                from.addBeforeComment(comments);\n            }\n\n            queryBlock.setFrom(from);\n        } else {\n            if (comments != null) {\n                queryBlock.addAfterComment(comments);\n            }\n        }\n\n        if (lexer.nextIf(Token.FINAL)) {\n            if (queryBlock instanceof CKSelectQueryBlock) {\n                ((CKSelectQueryBlock) queryBlock).setFinal(true);\n            }\n        }\n    }\n\n    @Override\n    protected void afterParseFetchClause(SQLSelectQueryBlock queryBlock) {\n        if (queryBlock instanceof CKSelectQueryBlock) {\n            CKSelectQueryBlock ckSelectQueryBlock = (CKSelectQueryBlock) queryBlock;\n            if (lexer.token() == Token.SETTINGS) {\n                lexer.nextToken();\n                for (; ; ) {\n                    SQLAssignItem item = this.exprParser.parseAssignItem();\n                    ckSelectQueryBlock.getSettings().add(item);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n            }\n\n            if (lexer.token() == Token.FORMAT) {\n                lexer.nextToken();\n                ckSelectQueryBlock.setFormat(expr());\n            }\n        }\n    }\n\n    @Override\n    protected void afterParseLimitClause(SQLSelectQueryBlock queryBlock) {\n        if (queryBlock instanceof CKSelectQueryBlock) {\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"TIES\");\n                ((CKSelectQueryBlock) queryBlock).setWithTies(true);\n            }\n        }\n    }\n\n    @Override\n    protected void parseOrderByWith(SQLSelectGroupByClause groupBy, SQLSelectQueryBlock queryBlock) {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.CUBE)) {\n            lexer.nextToken();\n            groupBy.setWithCube(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.ROLLUP)) {\n            lexer.nextToken();\n            groupBy.setWithRollUp(true);\n        } else if (lexer.identifierEquals(\"TOTALS\")) {\n            lexer.nextToken();\n            ((CKSelectQueryBlock) queryBlock).setWithTotals(true);\n        } else {\n            lexer.reset(mark);\n        }\n    }\n\n    @Override\n    protected void parseAfterOrderBy(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"FILL\");\n            ((CKSelectQueryBlock) queryBlock).setWithFill(true);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/parser/CKStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKAlterTableUpdateStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKCreateMaterializedViewStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKDropTableStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport static com.alibaba.druid.sql.parser.Token.ALTER;\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;\nimport static com.alibaba.druid.sql.parser.Token.ON;\nimport static com.alibaba.druid.sql.parser.Token.TABLE;\nimport static com.alibaba.druid.sql.parser.Token.TO;\n\npublic class CKStatementParser extends SQLStatementParser {\n    public CKStatementParser(String sql) {\n        super(new CKExprParser(sql));\n    }\n\n    public CKStatementParser(String sql, SQLParserFeature... features) {\n        super(new CKExprParser(sql, features));\n    }\n\n    public CKStatementParser(Lexer lexer) {\n        super(new CKExprParser(lexer));\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new CKSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLWithSubqueryClause parseWithQuery() {\n        return this.createSQLSelectParser().parseWith();\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new CKCreateTableParser(this.exprParser);\n    }\n\n    protected SQLAlterStatement alterTable() {\n        Lexer.SavePoint mark = lexer.mark();\n        accept(ALTER);\n        accept(TABLE);\n\n        SQLName tableName = this.exprParser.name();\n        SQLName clusterName = null;\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            acceptIdentifier(\"CLUSTER\");\n            clusterName = this.exprParser.name();\n        }\n\n        if (lexer.token() == Token.UPDATE) {\n            CKAlterTableUpdateStatement stmt = new CKAlterTableUpdateStatement(getDbType());\n            stmt.setTableName(tableName);\n            stmt.setClusterName(clusterName);\n            lexer.nextToken();\n            for (; ; ) {\n                SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n                stmt.getItems().add(item);\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                }\n                lexer.nextToken();\n            }\n            SQLName partitionId = null;\n            if (lexer.token() == Token.IN) {\n                lexer.nextToken();\n                accept(Token.PARTITION);\n                partitionId = this.exprParser.name();\n            }\n            stmt.setPartitionId(partitionId);\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        lexer.reset(mark);\n        return super.alterTable();\n    }\n\n    @Override\n    protected SQLAlterStatement alterTableAfterName(SQLAlterTableStatement stmt) {\n        if (lexer.token() == ON) {\n            lexer.nextToken();\n            acceptIdentifier(\"CLUSTER\");\n            stmt.setOn(this.exprParser.name());\n        }\n        return super.alterTableAfterName(stmt);\n    }\n\n    @Override\n    public void parseCreateViewAfterName(SQLCreateViewStatement createView) {\n        if (dbType == DbType.clickhouse) {\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                acceptIdentifier(\"CLUSTER\");\n                createView.setOnCluster(true);\n            }\n\n            if (lexer.token() == LITERAL_CHARS) {\n                SQLName to = this.exprParser.name();\n                createView.setTo(to);\n            } else if (lexer.token() == TO) {\n                lexer.nextToken();\n                SQLName to = this.exprParser.name();\n                createView.setTo(to);\n            }\n        }\n    }\n    public void parseCreateViewAtDataType(SQLColumnDefinition column, SQLName expr) {\n        column.setDataType(this.exprParser.parseDataType());\n    }\n\n    @Override\n    protected SQLDropTableStatement parseDropTable(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        // 创建 ClickHouse 特定的 DROP TABLE 语句\n        CKDropTableStatement stmt = new CKDropTableStatement(getDbType());\n\n        if (lexer.identifierEquals(FnvHash.Constants.TEMPORARY)) {\n            lexer.nextToken();\n            stmt.setTemporary(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            lexer.nextToken();\n            stmt.setExternal(true);\n        }\n\n        accept(Token.TABLE);\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        for (; ; ) {\n            SQLName name = this.exprParser.name();\n            SQLExprTableSource tab = new SQLExprTableSource(name);\n            stmt.addPartition(tab);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        // 调用扩展点方法\n        parseDropTableAfterName(stmt);\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseCreateMaterializedView() {\n        accept(Token.CREATE);\n        acceptIdentifier(\"MATERIALIZED\");\n        accept(Token.VIEW);\n\n        CKCreateMaterializedViewStatement stmt = new CKCreateMaterializedViewStatement();\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            acceptIdentifier(\"CLUSTER\");\n            stmt.setOnCluster(this.exprParser.name().getSimpleName());\n        }\n\n        if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n            stmt.setTo(this.exprParser.name());\n        }\n\n        if (lexer.identifierEquals(\"ENGINE\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            stmt.setEngine(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.BY);\n            stmt.setCkPartitionBy(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.PRIMARY) {\n            lexer.nextToken();\n            accept(Token.KEY);\n            stmt.setPrimaryKey(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.ORDER) {\n            stmt.setOrderBy(this.exprParser.parseOrderBy());\n        }\n\n        if (lexer.identifierEquals(\"SETTINGS\")) {\n            lexer.nextToken();\n            for (;;) {\n                stmt.getSettings().add(this.exprParser.parseAssignItem());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        if (lexer.identifierEquals(\"POPULATE\")) {\n            lexer.nextToken();\n            stmt.setPopulate(true);\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN || lexer.token() == Token.WITH) {\n            stmt.setQuery(createSQLSelectParser().select());\n        }\n\n        return stmt;\n    }\n\n    @Override\n    protected void parseDropTableAfterName(SQLDropTableStatement stmt) {\n        // 支持 ON CLUSTER 语法\n        if (stmt instanceof CKDropTableStatement && lexer.token() == Token.ON) {\n            lexer.nextToken();\n            acceptIdentifier(\"CLUSTER\");\n            // 支持 IDENTIFIER 或 DEFAULT 关键字作为 cluster 名称\n            if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.DEFAULT) {\n                String clusterName = lexer.stringVal();\n                ((CKDropTableStatement) stmt).setOnClusterName(clusterName);\n                lexer.nextToken();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/visitor/CKASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.visitor;\n\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKAlterTableUpdateStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKCreateMaterializedViewStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKDropTableStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.ClickhouseColumnCodec;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.ClickhouseColumnTTL;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface CKASTVisitor extends SQLASTVisitor {\n    default boolean visit(CKCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(CKCreateTableStatement x) {\n    }\n\n    default boolean visit(CKSelectQueryBlock x) {\n        return true;\n    }\n\n    default void endVisit(CKSelectQueryBlock x) {\n    }\n\n    default boolean visit(CKAlterTableUpdateStatement x) {\n        return true;\n    }\n\n    default void endVisit(CKAlterTableUpdateStatement x) {\n    }\n\n    default boolean visit(ClickhouseColumnCodec x) {\n        return true;\n    }\n\n    default void endVisit(ClickhouseColumnCodec x) {\n    }\n\n    default boolean visit(ClickhouseColumnTTL x) {\n        return true;\n    }\n\n    default void endVisit(ClickhouseColumnTTL x) {\n    }\n\n    default boolean visit(CKDropTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(CKDropTableStatement x) {\n    }\n\n    default boolean visit(CKCreateMaterializedViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(CKCreateMaterializedViewStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/visitor/CKExportParameterVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.clickhouse.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLInListExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CKExportParameterVisitor extends CKOutputVisitor implements ExportParameterVisitor {\n    /**\n     * true= if require parameterized sql output\n     */\n    private final boolean requireParameterizedOutput;\n\n    public CKExportParameterVisitor(final List<Object> parameters,\n                                    final StringBuilder appender,\n                                    final boolean wantParameterizedOutput) {\n        super(appender, true);\n        this.parameters = parameters;\n        this.requireParameterizedOutput = wantParameterizedOutput;\n    }\n\n    public CKExportParameterVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public CKExportParameterVisitor(final List<Object> parameters) {\n        this(parameters, new StringBuilder(), false);\n    }\n\n    public CKExportParameterVisitor(final StringBuilder appender) {\n        this(new ArrayList<Object>(), appender, true);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public boolean visit(SQLSelectItem x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOrderBy x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelectGroupByClause x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getArguments());\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/visitor/CKOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.clickhouse.CK;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKAlterTableUpdateStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKCreateMaterializedViewStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKDropTableStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.ClickhouseColumnCodec;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.ClickhouseColumnTTL;\nimport com.alibaba.druid.sql.parser.CharTypes;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.List;\n\npublic class CKOutputVisitor extends SQLASTOutputVisitor implements CKASTVisitor {\n    public CKOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.clickhouse, CK.DIALECT);\n    }\n\n    public CKOutputVisitor(StringBuilder appender, DbType dbType) {\n        super(appender, dbType);\n    }\n\n    public CKOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.clickhouse, CK.DIALECT, parameterized);\n    }\n\n    @Override\n    public boolean visit(SQLWithSubqueryClause.Entry x) {\n        if (x.isPrefixAlias()) {\n            print0(x.getAlias());\n            print(' ');\n            print0(ucase ? \"AS \" : \"as \");\n            printWithExpr(x);\n        } else {\n            printWithExpr(x);\n            print(' ');\n            print0(ucase ? \"AS \" : \"as \");\n            print0(x.getAlias());\n        }\n\n        return false;\n    }\n\n    private void printWithExpr(SQLWithSubqueryClause.Entry x) {\n        if (x.getExpr() != null) {\n            x.getExpr().accept(this);\n        } else if (x.getSubQuery() != null) {\n            print('(');\n            println();\n            SQLSelect query = x.getSubQuery();\n            if (query != null) {\n                query.accept(this);\n            } else {\n                x.getReturningStatement().accept(this);\n            }\n            println();\n            print(')');\n        }\n    }\n\n    public boolean visit(SQLStructDataType x) {\n        print0(ucase ? \"NESTED (\" : \"nested (\");\n        incrementIndent();\n        println();\n        printlnAndAccept(x.getFields(), \",\");\n        decrementIndent();\n        println();\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLStructDataType.Field x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            name.accept(this);\n        }\n        SQLDataType dataType = x.getDataType();\n\n        if (dataType != null) {\n            print(' ');\n            dataType.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByList x) {\n        if (x.getColumns().size() == 1) {\n            x.getColumns().get(0).accept(this);\n        } else {\n            print('(');\n            printAndAccept(x.getColumns(), \", \");\n            print0(\")\");\n        }\n\n        printPartitionsCountAndSubPartitions(x);\n\n        printSQLPartitions(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    protected void printCreateTable(SQLCreateTableStatement x, boolean printSelect) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        printCreateTableFeatures(x);\n\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printTableSourceExpr(\n                x.getTableSource()\n                        .getExpr());\n\n        printCreateTableAfterName(x);\n        printTableElements(x.getTableElementList());\n        printPartitionedBy(x);\n        printClusteredBy(x);\n        printCreateTableLike(x);\n\n        printSelectAs(x, printSelect);\n    }\n    @Override\n    public boolean visit(CKCreateTableStatement x) {\n        super.visit((SQLCreateTableStatement) x);\n\n//        SQLPartitionBy partitionBy = x.getPartitioning();\n//        if (partitionBy != null) {\n//            println();\n//            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n//            partitionBy.accept(this);\n//        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            orderBy.accept(this);\n        }\n\n        SQLPrimaryKey primaryKey = x.getPrimaryKey();\n        if (primaryKey != null) {\n            println();\n            primaryKey.accept(this);\n        }\n\n        SQLExpr sampleBy = x.getSampleBy();\n        if (sampleBy != null) {\n            println();\n            print0(ucase ? \"SAMPLE BY \" : \"sample by \");\n            sampleBy.accept(this);\n        }\n\n        SQLExpr ttl = x.getTtl();\n        if (ttl != null) {\n            println();\n            print0(ucase ? \"TTL \" : \"ttl \");\n            ttl.accept(this);\n        }\n\n        List<SQLAssignItem> settings = x.getSettings();\n        if (!settings.isEmpty()) {\n            println();\n            print0(ucase ? \"SETTINGS \" : \"settings \");\n            printAndAccept(settings, \", \");\n        }\n        printComment(x.getComment());\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableAddColumn x) {\n        print0(ucase ? \"ADD COLUMN \" : \"add column \");\n        printAndAccept(x.getColumns(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(CKAlterTableUpdateStatement x) {\n        print0(ucase ? \"ALTER TABLE \" : \"alter table \");\n        printExpr(x.getTableName());\n        if (x.getClusterName() != null) {\n            print0(ucase ? \" ON CLUSTER \" : \" on cluster \");\n            if (parameterized) {\n                print('?');\n            } else {\n                printExpr(x.getClusterName());\n            }\n        }\n        print0(ucase ? \" UPDATE \" : \" update \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLUpdateSetItem item = x.getItems().get(i);\n            visit(item);\n        }\n        if (x.getPartitionId() != null) {\n            print0(ucase ? \" IN PARTITION \" : \" in partition \");\n            if (parameterized) {\n                print('?');\n            } else {\n                printExpr(x.getPartitionId());\n            }\n        }\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ClickhouseColumnCodec x) {\n        print0(ucase ? \"CODEC(\" : \"codec(\");\n        printExpr(x.getExpr());\n        print(\")\");\n        return false;\n    }\n\n    public boolean visit(ClickhouseColumnTTL x) {\n        print0(ucase ? \" TTL \" : \" ttl \");\n        printExpr(x.getExpr());\n        return false;\n    }\n\n    @Override\n    public void printComment(String comment) {\n        if (comment == null) {\n            return;\n        }\n\n        if (isEnabled(VisitorFeature.OutputSkipMultilineComment) && comment.startsWith(\"/*\")) {\n            return;\n        }\n\n        if (isEnabled(VisitorFeature.OutputSkipSingleLineComment)\n                && (comment.startsWith(\"-\") || comment.startsWith(\"#\"))) {\n            return;\n        }\n\n        if (comment.startsWith(\"--\")\n                && comment.length() > 2\n                && comment.charAt(2) != ' '\n                && comment.charAt(2) != '-') {\n            print0(\"-- \");\n            print0(comment.substring(2));\n        } else if (comment.startsWith(\"#\")\n                && comment.length() > 1\n                && comment.charAt(1) != ' '\n                && comment.charAt(1) != '#') {\n            print0(\"# \");\n            print0(comment.substring(1));\n        } else if (comment.startsWith(\"/*\")) {\n            println();\n            print0(comment);\n        } else if (comment.startsWith(\"--\")) {\n            print0(comment);\n        }\n\n        char first = '\\0';\n        for (int i = 0; i < comment.length(); i++) {\n            char c = comment.charAt(i);\n            if (CharTypes.isWhitespace(c)) {\n                continue;\n            }\n            first = c;\n            break;\n        }\n\n        if (first == '-' || first == '#') {\n            endLineComment = true;\n        }\n    }\n\n    @Override\n    protected void printAfterFetch(SQLSelectQueryBlock queryBlock) {\n        if (queryBlock instanceof CKSelectQueryBlock) {\n            CKSelectQueryBlock ckSelectQueryBlock = ((CKSelectQueryBlock) queryBlock);\n            if (!ckSelectQueryBlock.getSettings().isEmpty()) {\n                println();\n                print0(ucase ? \"SETTINGS \" : \"settings \");\n                printAndAccept(ckSelectQueryBlock.getSettings(), \", \");\n            }\n            if (ckSelectQueryBlock.getFormat() != null) {\n                println();\n                print0(ucase ? \"FORMAT \" : \"format \");\n                ckSelectQueryBlock.getFormat().accept(this);\n            }\n        }\n    }\n\n    protected void printWhere(SQLSelectQueryBlock queryBlock) {\n        if (queryBlock instanceof CKSelectQueryBlock) {\n            SQLExpr preWhere = ((CKSelectQueryBlock) queryBlock).getPreWhere();\n            if (preWhere != null) {\n                println();\n                print0(ucase ? \"PREWHERE \" : \"prewhere \");\n                printExpr(preWhere);\n            }\n        }\n\n        SQLExpr where = queryBlock.getWhere();\n        if (where == null) {\n            return;\n        }\n\n        println();\n        print0(ucase ? \"WHERE \" : \"where \");\n\n        List<String> beforeComments = where.getBeforeCommentsDirect();\n        if (beforeComments != null && !beforeComments.isEmpty() && isPrettyFormat()) {\n            printlnComments(beforeComments);\n        }\n        printExpr(where, parameterized);\n    }\n\n    @Override\n    protected void printFrom(SQLSelectQueryBlock x) {\n        SQLTableSource from = x.getFrom();\n        if (from == null) {\n            return;\n        }\n\n        List<String> beforeComments = from.getBeforeCommentsDirect();\n        if (beforeComments != null) {\n            for (String comment : beforeComments) {\n                println();\n                print0(comment);\n            }\n        }\n\n        super.printFrom(x);\n        if (x instanceof CKSelectQueryBlock && ((CKSelectQueryBlock) x).isFinal()) {\n            print0(ucase ? \" FINAL\" : \" final\");\n        }\n    }\n\n    @Override\n    protected void printGroupBy(SQLSelectQueryBlock x) {\n        super.printGroupBy(x);\n        if (x instanceof CKSelectQueryBlock && ((CKSelectQueryBlock) x).isWithTotals()) {\n            print0(ucase ? \" WITH TOTALS\" : \" with totals\");\n        }\n    }\n\n    @Override\n    protected void printOrderBy(SQLSelectQueryBlock x) {\n        super.printOrderBy(x);\n        if (x instanceof CKSelectQueryBlock && ((CKSelectQueryBlock) x).isWithFill()) {\n            print0(ucase ? \" WITH FILL\" : \" with fill\");\n        }\n    }\n\n    @Override\n    protected void printLimit(SQLSelectQueryBlock x) {\n        super.printLimit(x);\n        if (x instanceof CKSelectQueryBlock && ((CKSelectQueryBlock) x).isWithTies()) {\n            print0(ucase ? \" WITH TIES\" : \" with ties\");\n        }\n    }\n\n    @Override\n    protected void printCreateTableAfterName(SQLCreateTableStatement x) {\n        if (x instanceof CKCreateTableStatement) {\n            CKCreateTableStatement ckStmt = (CKCreateTableStatement) x;\n            if (!StringUtils.isEmpty(ckStmt.getOnClusterName())) {\n                print0(ucase ? \" ON CLUSTER \" : \" on cluster \");\n                print(ckStmt.getOnClusterName());\n            }\n        }\n    }\n\n    @Override\n    protected void printEngine(SQLCreateTableStatement x) {\n        if (x instanceof CKCreateTableStatement) {\n            SQLExpr engine = ((CKCreateTableStatement) x).getEngine();\n            if (engine != null) {\n                print0(ucase ? \" ENGINE = \" : \" engine = \");\n                engine.accept(this);\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLMapDataType x) {\n        print0(ucase ? \"MAP(\" : \"map(\");\n\n        SQLDataType keyType = x.getKeyType();\n        SQLDataType valueType = x.getValueType();\n\n        keyType.accept(this);\n        print0(\", \");\n\n        valueType.accept(this);\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLArrayDataType x) {\n        print0(ucase ? \"ARRAY(\" : \"array(\");\n        x.getComponentType().accept(this);\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(CKCreateMaterializedViewStatement x) {\n        print0(ucase ? \"CREATE MATERIALIZED VIEW \" : \"create materialized view \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.getOnCluster() != null) {\n            print0(ucase ? \" ON CLUSTER \" : \" on cluster \");\n            print0(x.getOnCluster());\n        }\n\n        SQLName to = x.getTo();\n        if (to != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            to.accept(this);\n        }\n\n        if (x.getEngine() != null) {\n            println();\n            print0(ucase ? \"ENGINE = \" : \"engine = \");\n            x.getEngine().accept(this);\n        }\n\n        if (x.getCkPartitionBy() != null) {\n            println();\n            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n            x.getCkPartitionBy().accept(this);\n        }\n\n        if (x.getPrimaryKey() != null) {\n            println();\n            print0(ucase ? \"PRIMARY KEY \" : \"primary key \");\n            x.getPrimaryKey().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            println();\n            x.getOrderBy().accept(this);\n        }\n\n        if (!x.getSettings().isEmpty()) {\n            println();\n            print0(ucase ? \"SETTINGS \" : \"settings \");\n            printAndAccept(x.getSettings(), \", \");\n        }\n\n        if (x.isPopulate()) {\n            println();\n            print0(ucase ? \"POPULATE\" : \"populate\");\n        }\n\n        SQLSelect query = x.getQuery();\n        if (query != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            query.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(CKDropTableStatement x) {\n        print0(ucase ? \"DROP TABLE \" : \"drop table \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printAndAccept(x.getTableSources(), \", \");\n\n        // 输出 ON CLUSTER\n        if (x.getOnClusterName() != null && !x.getOnClusterName().isEmpty()) {\n            print0(ucase ? \" ON CLUSTER \" : \" on cluster \");\n            print0(x.getOnClusterName());\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/clickhouse/visitor/CKStatVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.clickhouse.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKAlterTableUpdateStatement;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\npublic class CKStatVisitor extends SchemaStatVisitor implements CKASTVisitor {\n    {\n        dbType = DbType.spark;\n    }\n\n    public CKStatVisitor() {\n        super(DbType.spark);\n    }\n\n    public CKStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    @Override\n    public boolean visit(CKAlterTableUpdateStatement x) {\n        TableStat stat = this.getTableStat(x.getTableName());\n        for (SQLUpdateSetItem column : x.getItems()) {\n            this.addColumn(x.getTableName(), column.getColumn().toString());\n        }\n        stat.incrementUpdateCount();\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/DataBricks.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class DataBricks {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.databricks);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/parser/DatabricksCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks.parser;\n\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class DatabricksCreateTableParser extends SparkCreateTableParser {\n    public DatabricksCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n    public SQLSelectParser createSQLSelectParser() {\n        return new DatabricksSelectParser(this.exprParser, selectListCache);\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        if (lexer.nextIf(Token.OR)) {\n            accept(Token.REPLACE);\n            createTable.config(SQLCreateTableStatement.Feature.OrReplace);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TEMPORARY) || lexer.identifierEquals(\"temp\")) {\n            lexer.nextToken();\n            createTable.setTemporary(true);\n        }\n    }\n\n    protected void createTableQuery(SQLCreateTableStatement stmt) {\n        if (lexer.token() == Token.WITH || lexer.token() == Token.AS || lexer.token() == Token.SELECT) {\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n            }\n            SQLSelect select = this.createSQLSelectParser().select();\n            stmt.setSelect(select);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/parser/DatabricksExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkExprParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class DatabricksExprParser extends SparkExprParser {\n    public DatabricksExprParser(String sql, SQLParserFeature... features) {\n        this(new DatabricksLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public DatabricksExprParser(Lexer lexer) {\n        super(lexer, DbType.databricks);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/parser/DatabricksLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkLexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class DatabricksLexer extends SparkLexer {\n    public DatabricksLexer(String input, SQLParserFeature... features) {\n        this(input, DbType.databricks, features);\n    }\n\n    public DatabricksLexer(String input, DbType dbType, SQLParserFeature... features) {\n        super(input, dbType, features);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/parser/DatabricksSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks.parser;\n\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\n\npublic class DatabricksSelectParser extends SparkSelectParser {\n    public DatabricksSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    @Override\n    protected SQLExprParser createExprParser() {\n    return new DatabricksExprParser(this.lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/parser/DatabricksStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks.parser;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLRefreshTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkStatementParser;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class DatabricksStatementParser extends SparkStatementParser {\n    public DatabricksStatementParser(String sql, SQLParserFeature... features) {\n        super(new DatabricksExprParser(sql, features));\n    }\n\n    @Override\n    public DatabricksSelectParser createSQLSelectParser() {\n        return new DatabricksSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new DatabricksCreateTableParser(this.exprParser);\n    }\n\n    public SQLStatement parseRefresh() {\n        acceptIdentifier(\"REFRESH\");\n        accept(Token.TABLE);\n        SQLRefreshTableStatement stmt = new SQLRefreshTableStatement();\n        stmt.setDbType(dbType);\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/visitor/DatabricksASTASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks.visitor;\n\nimport com.alibaba.druid.sql.dialect.spark.visitor.SparkASTVisitor;\n\npublic interface DatabricksASTASTVisitor extends SparkASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/databricks/visitor/DatabricksOutputASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.databricks.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.databricks.DataBricks;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.visitor.SparkOutputASTVisitor;\n\npublic class DatabricksOutputASTVisitor extends SparkOutputASTVisitor implements DatabricksASTASTVisitor {\n    public DatabricksOutputASTVisitor(StringBuilder appender) {\n        super(appender, DbType.databricks, DataBricks.DIALECT);\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        if (x instanceof HiveCreateTableStatement && ((HiveCreateTableStatement) x).getUsing() != null) {\n            print0(ucase ? \"OPTIONS (\" : \"options (\");\n        } else {\n            print0(ucase ? \"TBLPROPERTIES (\" : \"tblproperties (\");\n        }\n        incrementIndent();\n        println();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/Db2.java",
    "content": "package com.alibaba.druid.sql.dialect.db2;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Db2 {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.db2);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2IntermediateResultTableSource.java",
    "content": "package com.alibaba.druid.sql.dialect.db2.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLTableSourceImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DB2IntermediateResultTableSource extends SQLTableSourceImpl {\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n    }\n\n    public static enum Type {\n        OldTable,\n        NewTable,\n        FinalTable\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2Object.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\npublic interface DB2Object extends SQLObject {\n    void accept0(DB2ASTVisitor visitor);\n\n    interface Constants {\n        long CURRENT_DATE = FnvHash.fnv1a_64_lower(\"CURRENT DATE\");\n        long CURRENT_DATE2 = FnvHash.fnv1a_64_lower(\"CURRENT_DATE\");\n        long CURRENT_TIME = FnvHash.fnv1a_64_lower(\"CURRENT TIME\");\n        long CURRENT_SCHEMA = FnvHash.fnv1a_64_lower(\"CURRENT SCHEMA\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2Statement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\npublic interface DB2Statement extends SQLStatement, DB2Object {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2StatementImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class DB2StatementImpl extends SQLStatementImpl implements DB2Object {\n    public DB2StatementImpl() {\n        super(DbType.db2);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DB2ASTVisitor) {\n            accept0((DB2ASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public abstract void accept0(DB2ASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2CreateSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.db2.ast.DB2Statement;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class DB2CreateSchemaStatement extends SQLStatementImpl implements DB2Statement, SQLCreateStatement {\n    private SQLName schemaName;\n    private List<SQLCreateStatement> createStatements = new ArrayList<>();\n\n    public SQLName getName() {\n        return this.getSchemaName();\n    }\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    public List<SQLCreateStatement> getCreateStatements() {\n        return createStatements;\n    }\n\n    public void setCreateStatements(List<SQLCreateStatement> createStatements) {\n        this.createStatements = createStatements;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DB2ASTVisitor) {\n            accept0((DB2ASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(DB2ASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n        }\n\n        if (this.createStatements != null && !this.createStatements.isEmpty()) {\n            for (SQLCreateStatement stat : this.createStatements) {\n                acceptChild(visitor, stat);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2CreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.db2.ast.DB2Statement;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DB2CreateTableStatement extends SQLCreateTableStatement implements DB2Statement {\n    private boolean dataCaptureNone;\n    private boolean dataCaptureChanges;\n\n    protected SQLName database;\n    protected SQLName validproc;\n    protected SQLName indexIn;\n\n    protected boolean withData;\n    protected boolean withNoData;\n\n    public boolean isDataCaptureNone() {\n        return dataCaptureNone;\n    }\n\n    public void setDataCaptureNone(boolean dataCaptureNone) {\n        this.dataCaptureNone = dataCaptureNone;\n    }\n\n    public boolean isDataCaptureChanges() {\n        return dataCaptureChanges;\n    }\n\n    public void setDataCaptureChanges(boolean dataCaptureChanges) {\n        this.dataCaptureChanges = dataCaptureChanges;\n    }\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName database) {\n        if (database != null) {\n            database.setParent(this);\n        }\n        this.database = database;\n    }\n\n    public SQLName getValidproc() {\n        return validproc;\n    }\n\n    public void setValidproc(SQLName x) {\n        if (validproc != null) {\n            x.setParent(this);\n        }\n        this.validproc = x;\n    }\n\n    public SQLName getIndexIn() {\n        return indexIn;\n    }\n\n    public void setIndexIn(SQLName x) {\n        if (validproc != null) {\n            x.setParent(this);\n        }\n        this.indexIn = x;\n    }\n\n    public boolean isWithData() {\n        return withData;\n    }\n\n    public void setWithData(boolean withData) {\n        this.withData = withData;\n    }\n\n    public boolean isWithNoData() {\n        return withNoData;\n    }\n\n    public void setWithNoData(boolean withNoData) {\n        this.withNoData = withNoData;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DB2ASTVisitor) {\n            accept0((DB2ASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public void accept0(DB2ASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, tableSource);\n            this.acceptChild(visitor, tableElementList);\n            this.acceptChild(visitor, inherits);\n            this.acceptChild(visitor, select);\n            this.acceptChild(visitor, database);\n            this.acceptChild(visitor, validproc);\n            this.acceptChild(visitor, indexIn);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2DropSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLDropStatement;\nimport com.alibaba.druid.sql.dialect.db2.ast.DB2Statement;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DB2DropSchemaStatement extends SQLStatementImpl implements DB2Statement, SQLDropStatement {\n    private SQLName schemaName;\n    private boolean ifExists;\n    private boolean restrict;\n    private boolean cascade;\n\n    public SQLName getName() {\n        return this.getSchemaName();\n    }\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DB2ASTVisitor) {\n            accept0((DB2ASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(DB2ASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n        }\n\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2SelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.ast.DB2Object;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DB2SelectQueryBlock extends SQLSelectQueryBlock implements DB2Object {\n    private Isolation isolation;\n\n    private LockRequest lockRequest;\n\n    private boolean forReadOnly;\n\n    private SQLExpr optimizeFor;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DB2ASTVisitor) {\n            accept0((DB2ASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public void accept0(DB2ASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.selectList);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.groupBy);\n            acceptChild(visitor, this.getFirst());\n        }\n        visitor.endVisit(this);\n    }\n\n    public DB2SelectQueryBlock() {\n        dbType = DbType.db2;\n    }\n\n    public Isolation getIsolation() {\n        return isolation;\n    }\n\n    public void setIsolation(Isolation isolation) {\n        this.isolation = isolation;\n    }\n\n    public LockRequest getLockRequest() {\n        return lockRequest;\n    }\n\n    public void setLockRequest(LockRequest lockRequest) {\n        this.lockRequest = lockRequest;\n    }\n\n    public boolean isForReadOnly() {\n        return forReadOnly;\n    }\n\n    public void setForReadOnly(boolean forReadOnly) {\n        this.forReadOnly = forReadOnly;\n    }\n\n    public SQLExpr getOptimizeFor() {\n        return optimizeFor;\n    }\n\n    public void setOptimizeFor(SQLExpr optimizeFor) {\n        this.optimizeFor = optimizeFor;\n    }\n\n    public static enum Isolation {\n        RR, RS, CS, UR\n    }\n\n    public static enum LockRequest {\n        SHARE, UPDATE, EXCLUSIVE;\n    }\n\n    public void limit(int rowCount, int offset) {\n        if (offset <= 0) {\n            setFirst(new SQLIntegerExpr(rowCount));\n        } else {\n            throw new UnsupportedOperationException(\"not support offset\");\n        }\n    }\n\n    public void output(StringBuilder buf) {\n        this.accept(\n                new DB2OutputVisitor(buf)\n        );\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2ValuesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.db2.ast.DB2StatementImpl;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\n\npublic class DB2ValuesStatement extends DB2StatementImpl {\n    private SQLExpr expr;\n\n    @Override\n    public void accept0(DB2ASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2CreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.parser;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLPartitionByHash;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2CreateTableStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class DB2CreateTableParser extends SQLCreateTableParser {\n    public DB2CreateTableParser(String sql) {\n        super(new DB2ExprParser(sql));\n    }\n\n    public DB2CreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    @Override\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        DB2CreateTableStatement createTable = (DB2CreateTableStatement) stmt;\n        for (; ; ) {\n            if (lexer.nextIfIdentifier(FnvHash.Constants.DATA)) {\n                acceptIdentifier(\"CAPTURE\");\n\n                if (lexer.identifierEquals(FnvHash.Constants.NONE)) {\n                    lexer.nextToken();\n                    createTable.setDataCaptureNone(true);\n                    continue;\n                }\n\n                throw new ParserException(\"TODO \" + lexer.info());\n            } else if (lexer.nextIf(Token.IN)) {\n                if (lexer.nextIf(Token.DATABASE)) {\n                    SQLName database = this.exprParser.name();\n                    createTable.setDatabase(database);\n                } else if (lexer.identifierEquals(\"tablespace\")) {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                } else {\n                    SQLName tablespace = this.exprParser.name();\n                    createTable.setTablespace(tablespace);\n                }\n\n                continue;\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.PARTITIONING)) {\n                SQLPartitionByHash partitionBy = new SQLPartitionByHash();\n\n                accept(Token.KEY);\n                accept(Token.LPAREN);\n                this.exprParser.exprList(partitionBy.getColumns(), partitionBy);\n                accept(Token.RPAREN);\n                accept(Token.USING);\n                acceptIdentifier(\"HASHING\");\n                createTable.setPartitionBy(partitionBy);\n                continue;\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.VALIDPROC)) {\n                SQLName validproc = this.exprParser.name();\n                createTable.setValidproc(validproc);\n                continue;\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.COMPRESS)) {\n                createTable.setCompress(true);\n                lexer.nextIfIdentifier(FnvHash.Constants.YES);\n                continue;\n            } else if (lexer.nextIf(Token.INDEX)) {\n                accept(Token.IN);\n                SQLName indexIn = this.exprParser.name();\n                createTable.setIndexIn(indexIn);\n                continue;\n            }\n            break;\n        }\n    }\n\n    protected DB2CreateTableStatement newCreateStatement() {\n        return new DB2CreateTableStatement();\n    }\n\n    @Override\n    public void createTableAfterQuery(SQLCreateTableStatement stmt) {\n        Token token = lexer.token();\n        if (token != Token.EOF) {\n            if (lexer.nextIf(Token.WITH)) {\n                if (lexer.nextIfIdentifier(\"NO\")) {\n                    acceptIdentifier(\"DATA\");\n                    ((DB2CreateTableStatement) stmt).setWithNoData(true);\n                } else if (lexer.nextIfIdentifier(\"DATA\")) {\n                    ((DB2CreateTableStatement) stmt).setWithData(true);\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class DB2ExprParser extends SQLExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\", \"ROW_NUMBER\",\n                \"ROWNUMBER\"};\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public DB2ExprParser(String sql) {\n        this(new DB2Lexer(sql));\n        this.lexer.nextToken();\n        this.dbType = DbType.db2;\n    }\n\n    public DB2ExprParser(String sql, SQLParserFeature... features) {\n        this(new DB2Lexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public DB2ExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n        this.dbType = DbType.db2;\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                if (identExpr.hashCode64() == FnvHash.Constants.NEXT) {\n                    lexer.nextToken();\n                    accept(Token.FOR);\n                    SQLName seqName = this.name();\n                    SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.NextVal);\n                    return seqExpr;\n                } else if (identExpr.hashCode64() == FnvHash.Constants.PREVIOUS) {\n                    lexer.nextToken();\n                    accept(Token.FOR);\n                    SQLName seqName = this.name();\n                    SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.PrevVal);\n                    return seqExpr;\n                }\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.DATE)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                if (identExpr.hashCode64() == FnvHash.Constants.CURRENT) {\n                    lexer.nextToken();\n\n                    expr = new SQLIdentifierExpr(\"CURRENT DATE\");\n                }\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.DAY) && expr instanceof SQLIntegerExpr) {\n            lexer.nextToken();\n            expr = new SQLIntervalExpr(expr, SQLIntervalUnit.DAY);\n        } else if (lexer.identifierEquals(FnvHash.Constants.TIMESTAMP)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                if (identExpr.hashCode64() == FnvHash.Constants.CURRENT) {\n                    lexer.nextToken();\n\n                    expr = new SQLIdentifierExpr(\"CURRENT TIMESTAMP\");\n                }\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.TIME)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                if (identExpr.hashCode64() == FnvHash.Constants.CURRENT) {\n                    lexer.nextToken();\n\n                    expr = new SQLIdentifierExpr(\"CURRENT TIME\");\n                }\n            }\n        } else if (lexer.token() == Token.SCHEMA) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                if (identExpr.hashCode64() == FnvHash.Constants.CURRENT) {\n                    lexer.nextToken();\n\n                    expr = new SQLIdentifierExpr(\"CURRENT SCHEMA\");\n                }\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.PATH)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                if (identExpr.hashCode64() == FnvHash.Constants.CURRENT) {\n                    lexer.nextToken();\n\n                    expr = new SQLIdentifierExpr(\"CURRENT PATH\");\n                }\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.MONTHS)) {\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.MONTH);\n            lexer.nextToken();\n            expr = intervalExpr;\n        } else if (lexer.identifierEquals(FnvHash.Constants.YEARS)) {\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.YEAR);\n            lexer.nextToken();\n            expr = intervalExpr;\n        } else if (lexer.identifierEquals(FnvHash.Constants.DAYS)) {\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.DAY);\n            lexer.nextToken();\n            expr = intervalExpr;\n        } else if (lexer.identifierEquals(FnvHash.Constants.HOUR) || lexer.identifierEquals(FnvHash.Constants.HOURS)) {\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.HOUR);\n            lexer.nextToken();\n            expr = intervalExpr;\n        } else if (lexer.identifierEquals(FnvHash.Constants.MINUTES)) {\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.MINUTE);\n            lexer.nextToken();\n            expr = intervalExpr;\n        } else if (lexer.identifierEquals(FnvHash.Constants.SECONDS)) {\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.SECOND);\n            lexer.nextToken();\n            expr = intervalExpr;\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    protected SQLExpr dotRest(SQLExpr expr) {\n        if (lexer.identifierEquals(FnvHash.Constants.NEXTVAL)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.NextVal);\n                lexer.nextToken();\n                return seqExpr;\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.PREVVAL)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.PrevVal);\n                lexer.nextToken();\n                return seqExpr;\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.CURRVAL)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.CurrVal);\n                lexer.nextToken();\n                return seqExpr;\n            }\n        }\n\n        return super.dotRest(expr);\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        column = super.parseColumnRest(column);\n\n        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.ALWAYS)) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n\n            accept(Token.AS);\n\n            if (lexer.token() == Token.IDENTITY) {\n                SQLColumnDefinition.Identity identity = parseIdentity();\n                column.setIdentity(identity);\n            } else {\n                SQLExpr expr = this.expr();\n\n                column.setGeneratedAlwaysAs(expr);\n            }\n\n            parseColumnRest(column);\n        }\n\n        return column;\n    }\n\n    protected SQLColumnDefinition.Identity parseIdentity() {\n        SQLColumnDefinition.Identity identity = new SQLColumnDefinition.Identity();\n\n        accept(Token.IDENTITY);\n        if (lexer.token() == Token.LPAREN) {\n            accept(Token.LPAREN);\n\n            if (lexer.identifierEquals(FnvHash.Constants.START)) {\n                lexer.nextToken();\n                accept(Token.WITH);\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setSeed((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.INCREMENT)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setIncrement((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.CYCLE)) {\n                lexer.nextToken();\n                identity.setCycle(true);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.MINVALUE)) {\n                lexer.nextTokenValue();\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setMinValue((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.MAXVALUE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setMaxValue((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        return identity;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2Lexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.parser;\n\nimport com.alibaba.druid.sql.parser.DialectFeature;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.ParseAssignItemSkip;\n\npublic class DB2Lexer extends Lexer {\n    static final Keywords DB2_KEYWORDS;\n    static final DialectFeature DB2_FEATURE = new DialectFeature(\n            Collections.singletonList(ParseAssignItemSkip),\n            null\n    );\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"OPTIMIZE\", Token.OPTIMIZE);\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"IF\", Token.IF);\n        map.put(\"EXISTS\", Token.EXISTS);\n        map.put(\"RESTRICT\", Token.RESTRICT);\n        map.put(\"CASCADE\", Token.CASCADE);\n\n        DB2_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return DB2_KEYWORDS;\n    }\n\n    public DB2Lexer(String input) {\n        super(input);\n    }\n\n    public DB2Lexer(String input, SQLParserFeature... features) {\n        super(input);\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = DB2_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2SelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock.Isolation;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class DB2SelectParser extends SQLSelectParser {\n    public DB2SelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.db2;\n    }\n\n    public DB2SelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.db2;\n    }\n\n    public DB2SelectParser(String sql) {\n        this(new DB2ExprParser(sql));\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new DB2ExprParser(lexer);\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            accept(Token.RPAREN);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        accept(Token.SELECT);\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n        }\n\n        DB2SelectQueryBlock queryBlock = new DB2SelectQueryBlock();\n\n        if (lexer.token() == Token.DISTINCT) {\n            queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.UNIQUE) {\n            queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.ALL) {\n            queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n            lexer.nextToken();\n        }\n\n        parseSelectList(queryBlock);\n\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n\n            SQLExpr expr = expr();\n            if (lexer.token() != Token.COMMA) {\n                queryBlock.setInto(expr);\n            }\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseHierachical(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        if (lexer.token() == Token.ORDER) {\n            SQLOrderBy orderBy = parseOrderBy();\n            queryBlock.setOrderBy(orderBy);\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.FETCH) {\n                lexer.nextToken();\n                accept(Token.FIRST);\n                SQLExpr first = this.exprParser.primary();\n                queryBlock.setFirst(first);\n                if (lexer.identifierEquals(\"ROW\") || lexer.identifierEquals(\"ROWS\")) {\n                    lexer.nextToken();\n                }\n                accept(Token.ONLY);\n                continue;\n            }\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"RR\")) {\n                    queryBlock.setIsolation(Isolation.RR);\n                    parseLockRequest(queryBlock);\n                } else if (lexer.identifierEquals(\"RS\")) {\n                    queryBlock.setIsolation(Isolation.RS);\n                    parseLockRequest(queryBlock);\n                } else if (lexer.identifierEquals(\"CS\")) {\n                    queryBlock.setIsolation(Isolation.CS);\n                } else if (lexer.identifierEquals(\"UR\")) {\n                    queryBlock.setIsolation(Isolation.UR);\n                } else {\n                    throw new ParserException(\"TODO. \" + lexer.info());\n                }\n                lexer.nextToken();\n                continue;\n            }\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.UPDATE) {\n                    queryBlock.setForUpdate(true);\n                    lexer.nextToken();\n                } else {\n                    acceptIdentifier(\"READ\");\n                    accept(Token.ONLY);\n                    queryBlock.setForReadOnly(true);\n                }\n                continue;\n            }\n\n            if (lexer.token() == Token.OPTIMIZE) {\n                lexer.nextToken();\n                accept(Token.FOR);\n\n                queryBlock.setOptimizeFor(this.expr());\n                if (lexer.identifierEquals(\"ROW\")) {\n                    lexer.nextToken();\n                } else {\n                    acceptIdentifier(\"ROWS\");\n                }\n            }\n\n            break;\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    private void parseLockRequest(DB2SelectQueryBlock queryBlock) {\n        lexer.nextToken();\n        accept(Token.USE);\n        accept(Token.AND);\n        if (!lexer.identifierEquals(\"KEEP\")) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n        lexer.nextToken();\n        DB2SelectQueryBlock.LockRequest lockRequest = null;\n        switch (lexer.token()) {\n            case SHARE: {\n                lockRequest = DB2SelectQueryBlock.LockRequest.SHARE;\n                break;\n            }\n            case UPDATE: {\n                lockRequest = DB2SelectQueryBlock.LockRequest.UPDATE;\n                break;\n            }\n            case EXCLUSIVE: {\n                lockRequest = DB2SelectQueryBlock.LockRequest.EXCLUSIVE;\n                break;\n            }\n            default:\n                throw new ParserException(\"TODO. \" + lexer.info());\n        }\n        lexer.nextToken();\n        if (lexer.identifierEquals(\"LOCKS\")) {\n            queryBlock.setLockRequest(lockRequest);\n        } else {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n    }\n\n    @Override\n    protected void parseOrderByWith(SQLSelectGroupByClause groupBy, SQLSelectQueryBlock queryBlock) {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.CUBE)) {\n            lexer.nextToken();\n            groupBy.setWithCube(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.ROLLUP)) {\n            lexer.nextToken();\n            groupBy.setWithRollUp(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.RS)) {\n            lexer.nextToken();\n            ((DB2SelectQueryBlock) queryBlock).setIsolation(DB2SelectQueryBlock.Isolation.RS);\n        } else if (lexer.identifierEquals(FnvHash.Constants.RR)) {\n            lexer.nextToken();\n            ((DB2SelectQueryBlock) queryBlock).setIsolation(DB2SelectQueryBlock.Isolation.RR);\n        } else if (lexer.identifierEquals(FnvHash.Constants.CS)) {\n            lexer.nextToken();\n            ((DB2SelectQueryBlock) queryBlock).setIsolation(DB2SelectQueryBlock.Isolation.CS);\n        } else if (lexer.identifierEquals(FnvHash.Constants.UR)) {\n            lexer.nextToken();\n            ((DB2SelectQueryBlock) queryBlock).setIsolation(DB2SelectQueryBlock.Isolation.UR);\n        } else {\n            lexer.reset(mark);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2StatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.parser;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2CreateSchemaStatement;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2DropSchemaStatement;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2ValuesStatement;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.*;\n\npublic class DB2StatementParser extends SQLStatementParser {\n    public DB2StatementParser(String sql) {\n        super(new DB2ExprParser(sql));\n    }\n\n    public DB2StatementParser(String sql, SQLParserFeature... features) {\n        super(new DB2ExprParser(sql, features));\n    }\n\n    public DB2StatementParser(Lexer lexer) {\n        super(new DB2ExprParser(lexer));\n    }\n\n    public DB2SelectParser createSQLSelectParser() {\n        return new DB2SelectParser(this.exprParser, selectListCache);\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.token() == Token.VALUES) {\n            lexer.nextToken();\n            DB2ValuesStatement stmt = new DB2ValuesStatement();\n            stmt.setExpr(this.exprParser.expr());\n            statementList.add(stmt);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public SQLStatement parseCreateSchema() {\n        accept(Token.CREATE);\n        accept(Token.SCHEMA);\n\n        DB2CreateSchemaStatement stmt = new DB2CreateSchemaStatement();\n\n        stmt.setSchemaName(this.exprParser.name());\n\n        while (lexer.token() != SEMI && !lexer.isEOF()) {\n            if (lexer.token() == Token.CREATE) {\n                Lexer.SavePoint mark = lexer.markOut();\n                lexer.nextToken();\n                if (lexer.token() == Token.TABLE) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateTable());\n                    continue;\n                } else if (lexer.token() == VIEW) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateView());\n                    continue;\n                } else if (lexer.token() == INDEX) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateIndex());\n                    continue;\n                } else if (lexer.token() == SEQUENCE) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateSequence());\n                    continue;\n                } else if (lexer.token() == TRIGGER) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateTrigger());\n                    continue;\n                }\n            }\n\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n\n        return stmt;\n    }\n\n    @Override\n    protected SQLDropStatement parseDropSchema(boolean physical) {\n        DB2DropSchemaStatement stmt = new DB2DropSchemaStatement();\n\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setSchemaName(name);\n\n        if (lexer.token() == Token.CASCADE) {\n            lexer.nextToken();\n            stmt.setCascade(true);\n        } else {\n            stmt.setCascade(false);\n        }\n        if (lexer.token() == Token.RESTRICT) {\n            lexer.nextToken();\n            stmt.setRestrict(true);\n        }\n\n        return stmt;\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new DB2CreateTableParser(this.exprParser);\n    }\n\n    protected SQLAlterTableAlterColumn parseAlterColumn() {\n        if (lexer.token() == Token.COLUMN) {\n            lexer.nextToken();\n        }\n\n        SQLColumnDefinition column = this.exprParser.parseColumn();\n\n        SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn();\n        alterColumn.setColumn(column);\n\n        if (column.getDataType() == null && column.getConstraints().isEmpty()) {\n            if (lexer.token() == Token.SET) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setSetNotNull(true);\n                } else if (lexer.token() == Token.DEFAULT) {\n                    lexer.nextToken();\n                    SQLExpr defaultValue = this.exprParser.expr();\n                    alterColumn.setSetDefault(defaultValue);\n                } else if (lexer.identifierEquals(FnvHash.Constants.DATA)) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TYPE\");\n                    SQLDataType dataType = this.exprParser.parseDataType();\n                    alterColumn.setDataType(dataType);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            } else if (lexer.token() == Token.DROP) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setDropNotNull(true);\n                } else {\n                    accept(Token.DEFAULT);\n                    alterColumn.setDropDefault(true);\n                }\n            }\n        }\n\n        return alterColumn;\n    }\n\n    @Override\n    public SQLDeleteStatement parseDeleteStatement() {\n        SQLDeleteStatement deleteStatement = new SQLDeleteStatement(getDbType());\n\n        if (lexer.token() == Token.DELETE) {\n            lexer.nextToken();\n            if (lexer.token() == (Token.FROM)) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            SQLName tableName = exprParser.name();\n\n            deleteStatement.setTableName(tableName);\n\n            if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n                SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n                deleteStatement.setFrom(tableSource);\n            }\n\n            // try to parse alias\n            deleteStatement.setAlias(tableAlias());\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            SQLExpr where = this.exprParser.expr();\n            deleteStatement.setWhere(where);\n        }\n\n        return deleteStatement;\n    }\n\n    @Override\n    public SQLStatement parseTruncate() {\n        accept(Token.TRUNCATE);\n        if (!lexer.nextIf(Token.TABLE)) {\n            lexer.nextIfIdentifier(\"TABLE\");\n        }\n        SQLTruncateStatement stmt = new SQLTruncateStatement(getDbType());\n\n        SQLName name = this.exprParser.name();\n        stmt.addTableSource(name);\n\n        for (;;) {\n            if (lexer.token() == Token.DROP) {\n                lexer.nextToken();\n                acceptIdentifier(\"STORAGE\");\n                stmt.setDropStorage(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"REUSE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"STORAGE\");\n                stmt.setReuseStorage(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"IGNORE\")) {\n                lexer.nextToken();\n                accept(Token.DELETE);\n                acceptIdentifier(\"TRIGGERS\");\n                stmt.setIgnoreDeleteTriggers(true);\n                continue;\n            }\n\n            if (lexer.token() == Token.RESTRICT) {\n                lexer.nextToken();\n                accept(Token.WHEN);\n                accept(Token.DELETE);\n                acceptIdentifier(\"TRIGGERS\");\n                stmt.setRestrictWhenDeleteTriggers(true);\n                continue;\n            }\n\n            if (lexer.token() == Token.CONTINUE) {\n                lexer.nextToken();\n                accept(Token.IDENTITY);\n                continue;\n            }\n\n            if (lexer.token() == Token.RESTART) {\n                lexer.nextToken();\n                accept(Token.IDENTITY);\n                stmt.setRestartIdentity(Boolean.TRUE);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"IMMEDIATE\")) {\n                lexer.nextToken();\n                stmt.setImmediate(true);\n                continue;\n            }\n\n            break;\n        }\n\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2ASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.visitor;\n\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface DB2ASTVisitor extends SQLASTVisitor {\n    default boolean visit(DB2SelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(DB2SelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(DB2ValuesStatement x) {\n        return true;\n    }\n\n    default void endVisit(DB2ValuesStatement x) {\n    }\n\n    default boolean visit(DB2CreateTableStatement x) {\n        return visit((SQLCreateTableStatement) x);\n    }\n\n    default void endVisit(DB2CreateTableStatement x) {\n        endVisit((SQLCreateTableStatement) x);\n    }\n\n    default boolean visit(DB2CreateSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(DB2CreateSchemaStatement x) {\n    }\n\n    default boolean visit(DB2DropSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(DB2DropSchemaStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2ASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class DB2ASTVisitorAdapter extends SQLASTVisitorAdapter implements DB2ASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2EvalVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class DB2EvalVisitor extends DB2ASTVisitorAdapter implements SQLEvalVisitor {\n    private Map<String, Function> functions = new HashMap<String, Function>();\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public DB2EvalVisitor() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public DB2EvalVisitor(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLUnaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2ExportParameterVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLInListExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2CreateTableStatement;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class DB2ExportParameterVisitor extends DB2OutputVisitor implements ExportParameterVisitor {\n    /**\n     * true= if require parameterized sql output\n     */\n    private final boolean requireParameterizedOutput;\n\n    public DB2ExportParameterVisitor(final List<Object> parameters,\n                                     final StringBuilder appender,\n                                     final boolean wantParameterizedOutput) {\n        super(appender, true);\n        this.parameters = parameters;\n        this.requireParameterizedOutput = wantParameterizedOutput;\n    }\n\n    public DB2ExportParameterVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public DB2ExportParameterVisitor(final List<Object> parameters) {\n        this(parameters, new StringBuilder(), false);\n    }\n\n    public DB2ExportParameterVisitor(final StringBuilder appender) {\n        this(new ArrayList<Object>(), appender, true);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public boolean visit(SQLSelectItem x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOrderBy x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelectGroupByClause x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getArguments());\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n    @Override\n    public void endVisit(DB2CreateTableStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.Db2;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.*;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\npublic class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisitor {\n    public DB2OutputVisitor(StringBuilder appender) {\n        super(appender, DbType.db2, Db2.DIALECT);\n    }\n\n    public DB2OutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.db2, Db2.DIALECT, parameterized);\n    }\n\n    @Override\n    public boolean visit(DB2SelectQueryBlock x) {\n        this.visit((SQLSelectQueryBlock) x);\n\n        if (x.isForReadOnly()) {\n            println();\n            print0(ucase ? \"FOR READ ONLY\" : \"for read only\");\n        }\n\n        if (x.getIsolation() != null) {\n            println();\n            print0(ucase ? \"WITH \" : \"with \");\n            print0(x.getIsolation().name());\n            if (x.getLockRequest() != null) {\n                println();\n                print0(ucase ? \"USE AND KEEP \" + x.getLockRequest().name() + \" LOCKS\" : \"use and keep \" + x.getLockRequest().name().toLowerCase() + \" locks\");\n            }\n        }\n\n        if (x.getOptimizeFor() != null) {\n            println();\n            print0(ucase ? \"OPTIMIZE FOR \" : \"optimize for \");\n            x.getOptimizeFor().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(DB2SelectQueryBlock x) {\n    }\n\n    @Override\n    public boolean visit(DB2ValuesStatement x) {\n        print0(ucase ? \"VALUES \" : \"values \");\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public void endVisit(DB2ValuesStatement x) {\n    }\n\n    @Override\n    public boolean visit(DB2CreateTableStatement x) {\n        printCreateTable(x, true);\n\n        if (x.isDataCaptureNone()) {\n            println();\n            print(\"DATA CAPTURE NONE\");\n        } else if (x.isDataCaptureChanges()) {\n            println();\n            print(\"DATA CAPTURE CHANGES\");\n        }\n\n        SQLName tablespace = x.getTablespace();\n        if (tablespace != null) {\n            println();\n            print(\"IN \");\n            tablespace.accept(this);\n        }\n\n        SQLName indexIn = x.getIndexIn();\n        if (indexIn != null) {\n            println();\n            print(\"INDEX IN \");\n            indexIn.accept(this);\n        }\n\n        SQLName database = x.getDatabase();\n        if (database != null) {\n            println();\n            print(\"IN DATABASE \");\n            database.accept(this);\n        }\n\n        SQLName validproc = x.getValidproc();\n        if (validproc != null) {\n            println();\n            print(\"VALIDPROC \");\n            validproc.accept(this);\n        }\n\n        printPartitionBy(x);\n\n        Boolean compress = x.getCompress();\n        if (compress != null) {\n            println();\n            if (compress.booleanValue()) {\n                print0(ucase ? \"COMPRESS YES\" : \"compress yes\");\n            } else {\n                print0(ucase ? \"COMPRESS NO\" : \"compress no\");\n            }\n        }\n\n        if (x.isWithData()) {\n            println();\n            print0(ucase ? \"WITH DATA\" : \"with data\");\n        } else if (x.isWithNoData()) {\n            println();\n            print0(ucase ? \"WITH NO DATA\" : \"with no data\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(DB2CreateTableStatement x) {\n    }\n\n    @Override\n    public boolean visit(DB2CreateSchemaStatement x) {\n        printUcase(\"CREATE SCHEMA \");\n        if (x.getSchemaName() != null) {\n            x.getSchemaName().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(DB2CreateSchemaStatement x) {\n    }\n\n    @Override\n    public boolean visit(DB2DropSchemaStatement x) {\n        printUcase(\"DROP SCHEMA \");\n\n        if (x.isIfExists()) {\n            printUcase(\"IF EXISTS \");\n        }\n\n        if (x.getSchemaName() != null) {\n            x.getSchemaName().accept(this);\n        }\n\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n        if (x.isRestrict()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(DB2DropSchemaStatement x) {\n    }\n\n    protected void printOperator(SQLBinaryOperator operator) {\n        if (operator == SQLBinaryOperator.Concat) {\n            print0(ucase ? \"CONCAT\" : \"concat\");\n        } else {\n            print0(ucase ? operator.name : operator.nameLCase);\n        }\n    }\n\n    public boolean visit(SQLIntervalExpr x) {\n        SQLExpr value = x.getValue();\n        if (value instanceof SQLLiteralExpr || value instanceof SQLName || value instanceof SQLVariantRefExpr) {\n            value.accept(this);\n        } else {\n            print('(');\n            value.accept(this);\n            print(')');\n        }\n\n        SQLIntervalUnit unit = x.getUnit();\n        if (unit != null) {\n            print(' ');\n            print0(ucase ? unit.name : unit.nameLCase);\n            print(ucase ? 'S' : 's');\n        }\n        return false;\n    }\n\n    public boolean visit(SQLColumnDefinition.Identity x) {\n        print0(ucase ? \"GENERATED ALWAYS AS IDENTITY\" : \"generated always as identity\");\n\n        final Integer seed = x.getSeed();\n        final Integer increment = x.getIncrement();\n        final Integer minValue = x.getMinValue();\n        final Integer maxValue = x.getMaxValue();\n\n        if (seed != null || increment != null || x.isCycle() || minValue != null || maxValue != null) {\n            print0(\" (\");\n        }\n\n        if (seed != null) {\n            print0(ucase ? \"START WITH \" : \"start with \");\n            print(seed);\n        }\n\n        if (increment != null) {\n            if (seed != null) {\n                print0(\", \");\n            }\n            print0(ucase ? \"INCREMENT BY \" : \"increment by \");\n            print(increment);\n        }\n\n        if (x.isCycle()) {\n            if (seed != null || increment != null) {\n                print0(\", \");\n            }\n            print0(ucase ? \"CYCLE\" : \"cycle\");\n        }\n\n        if (minValue != null) {\n            if (seed != null || increment != null || x.isCycle()) {\n                print0(\", \");\n            }\n            print0(ucase ? \"MINVALUE \" : \"minvalue \");\n            print(minValue);\n        }\n\n        if (maxValue != null) {\n            if (seed != null || increment != null || x.isCycle() || minValue != null) {\n                print0(\", \");\n            }\n            print0(ucase ? \"MAXVALUE \" : \"maxvalue \");\n            print(maxValue);\n        }\n\n        if (seed != null || increment != null || x.isCycle() || minValue != null || maxValue != null) {\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddColumn x) {\n        print0(ucase ? \"ADD COLUMNS \" : \"add columns \");\n        printAndAccept(x.getColumns(), \", \");\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.db2.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.ast.DB2Object;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2CreateTableStatement;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2ValuesStatement;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\npublic class DB2SchemaStatVisitor extends SchemaStatVisitor implements DB2ASTVisitor {\n    public DB2SchemaStatVisitor() {\n        super(DbType.db2);\n    }\n\n    public DB2SchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    @Override\n    public boolean visit(DB2SelectQueryBlock x) {\n        return this.visit((SQLSelectQueryBlock) x);\n    }\n\n    @Override\n    public void endVisit(DB2SelectQueryBlock x) {\n        super.endVisit((SQLSelectQueryBlock) x);\n    }\n\n    @Override\n    public boolean visit(DB2ValuesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(DB2CreateTableStatement x) {\n        return visit((SQLCreateTableStatement) x);\n    }\n\n    @Override\n    public void endVisit(DB2CreateTableStatement x) {\n    }\n\n    protected boolean isPseudoColumn(long hash64) {\n        return hash64 == DB2Object.Constants.CURRENT_DATE\n                || hash64 == DB2Object.Constants.CURRENT_DATE2\n                || hash64 == DB2Object.Constants.CURRENT_TIME\n                || hash64 == DB2Object.Constants.CURRENT_SCHEMA;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/Dm.java",
    "content": "package com.alibaba.druid.sql.dialect.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Dm {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.dm);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/ast/DmObject.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmASTVisitor;\n\npublic interface DmObject extends SQLObject {\n    void accept0(DmASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/ast/DmObjectImpl.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class DmObjectImpl extends SQLObjectImpl implements DmObject {\n    public DmObjectImpl() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DmASTVisitor) {\n            this.accept0((DmASTVisitor) visitor);\n        }\n    }\n\n    public abstract void accept0(DmASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/ast/stmt/DmDeleteStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DmDeleteStatement extends SQLDeleteStatement {\n    public DmDeleteStatement() {\n        super(DbType.dm);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DmASTVisitor) {\n            accept0((DmASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(DmASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.tableSource);\n            acceptChild(visitor, this.where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/ast/stmt/DmInsertStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DmInsertStatement extends SQLInsertStatement {\n    public DmInsertStatement() {\n        dbType = DbType.dm;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DmASTVisitor) {\n            accept0((DmASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(DmASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.tableSource);\n            acceptChild(visitor, this.columns);\n            acceptChild(visitor, this.valuesList);\n            acceptChild(visitor, this.query);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/ast/stmt/DmSelectQueryBlock.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.dm.ast.DmObjectImpl;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class DmSelectQueryBlock extends SQLSelectQueryBlock {\n    private SQLTop top;\n    private FetchClause fetch;\n    private ForClause forClause;\n\n    public DmSelectQueryBlock() {\n        dbType = DbType.dm;\n    }\n\n    public SQLTop getTop() {\n        return top;\n    }\n\n    public void setTop(SQLTop top) {\n        if (top != null) {\n            top.setParent(this);\n        }\n        this.top = top;\n    }\n\n    public void setTop(int rowCount) {\n        setTop(new SQLTop(new SQLIntegerExpr(rowCount)));\n    }\n\n    public FetchClause getFetch() {\n        return fetch;\n    }\n\n    public void setFetch(FetchClause fetch) {\n        if (fetch != null) {\n            fetch.setParent(this);\n        }\n        this.fetch = fetch;\n    }\n\n    public ForClause getForClause() {\n        return forClause;\n    }\n\n    public void setForClause(ForClause forClause) {\n        if (forClause != null) {\n            forClause.setParent(this);\n        }\n        this.forClause = forClause;\n    }\n\n    public static class FetchClause extends DmObjectImpl {\n        public enum Option {\n            FIRST, NEXT\n        }\n\n        private Option option;\n        private SQLExpr count;\n\n        public Option getOption() {\n            return option;\n        }\n\n        public void setOption(Option option) {\n            this.option = option;\n        }\n\n        public SQLExpr getCount() {\n            return count;\n        }\n\n        public void setCount(SQLExpr count) {\n            if (count != null) {\n                count.setParent(this);\n            }\n            this.count = count;\n        }\n\n        @Override\n        public void accept0(DmASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, count);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class ForClause extends DmObjectImpl {\n        public enum Option {\n            UPDATE, SHARE\n        }\n\n        private Option option;\n        private List<SQLExpr> of = new ArrayList<>();\n        private boolean noWait;\n        private boolean skipLocked;\n        private SQLExpr waitTimeout;\n\n        public Option getOption() {\n            return option;\n        }\n\n        public void setOption(Option option) {\n            this.option = option;\n        }\n\n        public List<SQLExpr> getOf() {\n            return of;\n        }\n\n        public boolean isNoWait() {\n            return noWait;\n        }\n\n        public void setNoWait(boolean noWait) {\n            this.noWait = noWait;\n        }\n\n        public boolean isSkipLocked() {\n            return skipLocked;\n        }\n\n        public void setSkipLocked(boolean skipLocked) {\n            this.skipLocked = skipLocked;\n        }\n\n        public SQLExpr getWaitTimeout() {\n            return waitTimeout;\n        }\n\n        public void setWaitTimeout(SQLExpr waitTimeout) {\n            if (waitTimeout != null) {\n                waitTimeout.setParent(this);\n            }\n            this.waitTimeout = waitTimeout;\n        }\n\n        @Override\n        public void accept0(DmASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, of);\n                acceptChild(visitor, waitTimeout);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DmASTVisitor) {\n            accept0((DmASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(DmASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor visitor) {\n        acceptChild(visitor, top);\n        acceptChild(visitor, this.getSelectList());\n        acceptChild(visitor, this.getFrom());\n        acceptChild(visitor, this.getWhere());\n        acceptChild(visitor, this.getGroupBy());\n        acceptChild(visitor, this.getWindows());\n        acceptChild(visitor, this.getOrderBy());\n        acceptChild(visitor, this.getLimit());\n        acceptChild(visitor, fetch);\n        acceptChild(visitor, forClause);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/ast/stmt/DmSelectStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DmSelectStatement extends SQLSelectStatement {\n    public DmSelectStatement() {\n        super(DbType.dm);\n    }\n\n    public DmSelectStatement(SQLSelect select) {\n        super(select, DbType.dm);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DmASTVisitor) {\n            accept0((DmASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(DmASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.select);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/ast/stmt/DmUpdateStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.dm.visitor.DmASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class DmUpdateStatement extends SQLUpdateStatement {\n    public DmUpdateStatement() {\n        super(DbType.dm);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof DmASTVisitor) {\n            accept0((DmASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(DmASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.tableSource);\n            acceptChild(visitor, this.items);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.orderBy);\n            acceptChild(visitor, this.returning);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/parser/DmCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.parser;\n\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionByHash;\nimport com.alibaba.druid.sql.ast.SQLPartitionByList;\nimport com.alibaba.druid.sql.ast.SQLPartitionByRange;\nimport com.alibaba.druid.sql.parser.*;\n\npublic class DmCreateTableParser extends SQLCreateTableParser {\n    public DmCreateTableParser(Lexer lexer) {\n        super(new DmExprParser(lexer));\n    }\n\n    public DmCreateTableParser(String sql) {\n        super(new DmExprParser(sql));\n    }\n\n    public DmCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    @Override\n    public SQLPartitionBy parsePartitionBy() {\n        lexer.nextToken();\n        accept(Token.BY);\n\n        if (lexer.identifierEquals(\"LIST\")) {\n            lexer.nextToken();\n            SQLPartitionByList list = new SQLPartitionByList();\n\n            if (lexer.token() == Token.LPAREN) {\n                list.setType(SQLPartitionByList.PartitionByListType.LIST_EXPRESSION);\n                lexer.nextToken();\n                list.addColumn(this.exprParser.expr());\n                accept(Token.RPAREN);\n            } else {\n                acceptIdentifier(\"COLUMNS\");\n                list.setType(SQLPartitionByList.PartitionByListType.LIST_COLUMNS);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    list.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n\n            return list;\n        } else if (lexer.identifierEquals(\"HASH\")) {\n            SQLPartitionByHash hash = new SQLPartitionByHash();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.KEY) {\n                lexer.nextToken();\n                hash.setKey(true);\n            }\n\n            accept(Token.LPAREN);\n            this.exprParser.exprList(hash.getColumns(), hash);\n            accept(Token.RPAREN);\n            return hash;\n        } else if (lexer.identifierEquals(\"RANGE\")) {\n            SQLPartitionByRange range = new SQLPartitionByRange();\n            lexer.nextToken();\n\n            accept(Token.LPAREN);\n            this.exprParser.exprList(range.getColumns(), range);\n            accept(Token.RPAREN);\n            return range;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/parser/DmExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalType;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class DmExprParser extends SQLExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\",\n                \"ROW_NUMBER\", \"RANK\", \"DENSE_RANK\", \"PERCENT_RANK\",\n                \"CUME_DIST\", \"NTILE\", \"LAG\", \"LEAD\",\n                \"FIRST_VALUE\", \"LAST_VALUE\", \"NTH_VALUE\",\n                \"LISTAGG\", \"WM_CONCAT\"\n        };\n\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public DmExprParser(String sql) {\n        this(new DmLexer(sql));\n        this.lexer.nextToken();\n        this.dbType = DbType.dm;\n    }\n\n    public DmExprParser(String sql, SQLParserFeature... features) {\n        this(new DmLexer(sql, features));\n        this.lexer.nextToken();\n        this.dbType = DbType.dm;\n    }\n\n    public DmExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n        this.dbType = DbType.dm;\n    }\n\n    @Override\n    public SQLDataType parseDataType() {\n        if (lexer.token() == Token.TYPE) {\n            lexer.nextToken();\n        }\n        return super.parseDataType();\n    }\n\n    public DmSelectParser createSelectParser() {\n        return new DmSelectParser(this);\n    }\n\n    @Override\n    public SQLExpr primary() {\n        if (lexer.token() == Token.VALUES) {\n            lexer.nextToken();\n\n            SQLValuesExpr values = new SQLValuesExpr();\n            for (;;) {\n                accept(Token.LPAREN);\n                SQLListExpr listExpr = new SQLListExpr();\n                exprList(listExpr.getItems(), listExpr);\n                accept(Token.RPAREN);\n\n                listExpr.setParent(values);\n                values.getValues().add(listExpr);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            return values;\n        } else if (lexer.token() == Token.WITH) {\n            SQLQueryExpr queryExpr = new SQLQueryExpr(\n                    createSelectParser().select());\n            return queryExpr;\n        }\n\n        return super.primary();\n    }\n\n    @Override\n    protected SQLExpr parseInterval() {\n        accept(Token.INTERVAL);\n\n        OracleIntervalExpr interval = new OracleIntervalExpr();\n\n        if (lexer.token() == Token.LITERAL_CHARS) {\n            interval.setValue(new SQLCharExpr(lexer.stringVal()));\n        } else if (lexer.token() == Token.VARIANT) {\n            interval.setValue(new SQLVariantRefExpr(lexer.stringVal()));\n        } else if (lexer.token() == Token.QUES) {\n            interval.setValue(new SQLVariantRefExpr(\"?\"));\n        } else {\n            return new SQLIdentifierExpr(\"INTERVAL\");\n        }\n\n        lexer.nextToken();\n\n        OracleIntervalType type;\n        if (lexer.identifierEquals(FnvHash.Constants.YEAR)) {\n            lexer.nextToken();\n            type = OracleIntervalType.YEAR;\n        } else if (lexer.identifierEquals(FnvHash.Constants.MONTH)) {\n            lexer.nextToken();\n            type = OracleIntervalType.MONTH;\n        } else if (lexer.identifierEquals(FnvHash.Constants.DAY)) {\n            lexer.nextToken();\n            type = OracleIntervalType.DAY;\n        } else if (lexer.identifierEquals(FnvHash.Constants.HOUR)) {\n            lexer.nextToken();\n            type = OracleIntervalType.HOUR;\n        } else if (lexer.identifierEquals(FnvHash.Constants.MINUTE)) {\n            lexer.nextToken();\n            type = OracleIntervalType.MINUTE;\n        } else if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n            lexer.nextToken();\n            type = OracleIntervalType.SECOND;\n        } else {\n            throw new ParserException(\"illegal interval type. \" + lexer.info());\n        }\n\n        interval.setType(type);\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n            interval.setPrecision(this.primary());\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                if (lexer.token() != Token.LITERAL_INT) {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n                interval.setFactionalSecondsPrecision(lexer.integerValue().intValue());\n                lexer.nextToken();\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"SECOND\")) {\n                lexer.nextToken();\n                interval.setToType(OracleIntervalType.SECOND);\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {\n                        throw new ParserException(\"syntax error. \" + lexer.info());\n                    }\n                    interval.setToFactionalSecondsPrecision(primary());\n                    accept(Token.RPAREN);\n                }\n            } else {\n                interval.setToType(OracleIntervalType.MONTH);\n                lexer.nextToken();\n            }\n        }\n\n        return interval;\n    }\n\n    @Override\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (expr.getClass() == SQLIdentifierExpr.class) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            String ident = identifierExpr.getName();\n            long hash = identifierExpr.nameHashCode64();\n\n            if (lexer.token() == Token.COMMA || lexer.token() == Token.RPAREN) {\n                return super.primaryRest(expr);\n            }\n\n            if (FnvHash.Constants.TIMESTAMP == hash) {\n                if (lexer.token() != Token.LITERAL_ALIAS\n                        && lexer.token() != Token.LITERAL_CHARS\n                        && lexer.token() != Token.WITH) {\n                    return super.primaryRest(new SQLIdentifierExpr(ident));\n                }\n\n                SQLTimestampExpr timestamp = new SQLTimestampExpr();\n\n                if (lexer.token() == Token.WITH) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n                    timestamp.setWithTimeZone(true);\n                }\n\n                String literal = lexer.stringVal();\n                timestamp.setValue(literal);\n                accept(Token.LITERAL_CHARS);\n\n                if (lexer.identifierEquals(\"AT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n\n                    String timezone = lexer.stringVal();\n                    timestamp.setTimeZone(timezone);\n                    accept(Token.LITERAL_CHARS);\n                }\n\n                return primaryRest(timestamp);\n            } else if (FnvHash.Constants.EXTRACT == hash) {\n                return parseExtract(ident);\n            } else if (ident.equalsIgnoreCase(\"b\") && lexer.token() == Token.LITERAL_CHARS) {\n                String charValue = lexer.stringVal();\n                lexer.nextToken();\n                expr = new SQLBinaryExpr(charValue);\n                return primaryRest(expr);\n            }\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    private SQLExpr parseExtract(String ident) {\n        accept(Token.LPAREN);\n\n        SQLMethodInvokeExpr extract = new SQLMethodInvokeExpr(ident);\n\n        String fieldName = lexer.stringVal();\n        lexer.nextToken();\n\n        accept(Token.FROM);\n        SQLExpr source = this.expr();\n\n        extract.addArgument(new SQLIdentifierExpr(fieldName));\n        extract.addArgument(source);\n\n        accept(Token.RPAREN);\n\n        return primaryRest(extract);\n    }\n\n    @Override\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        // DM supports IDENTITY [(seed, increment)] syntax\n        if (lexer.token() == Token.IDENTITY) {\n            lexer.nextToken();\n            column.setAutoIncrement(true);\n            if (lexer.token() == Token.LPAREN) {\n                column.setIdentity(parseIdentity());\n            }\n            return parseColumnRest(column);\n        }\n        return super.parseColumnRest(column);\n    }\n\n    @Override\n    protected String alias() {\n        String alias = super.alias();\n        if (alias != null) {\n            return alias;\n        }\n        switch (lexer.token()) {\n        case INTERSECT:\n            alias = lexer.stringVal();\n            lexer.nextToken();\n            return alias;\n        default:\n            break;\n        }\n        return alias;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/parser/DmLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;\n\n/**\n * Lexer for Dameng (DM) database SQL dialect.\n *\n * <p>Extends the base {@link Lexer} with DM-specific keywords and Oracle-compatible\n * string scanning (single-quote doubling for escape). DM is an Oracle-compatible\n * Chinese relational database that supports both Oracle and MySQL syntax extensions.</p>\n */\npublic class DmLexer extends Lexer {\n    static final Keywords DM_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"CASCADE\", Token.CASCADE);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"CURRENT\", Token.CURRENT);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"NEXT\", Token.NEXT);\n        map.put(\"NOWAIT\", Token.NOWAIT);\n        map.put(\"OF\", Token.OF);\n\n        map.put(\"OFFSET\", Token.OFFSET);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"RECURSIVE\", Token.RECURSIVE);\n        map.put(\"RESTART\", Token.RESTART);\n\n        map.put(\"RESTRICT\", Token.RESTRICT);\n        map.put(\"RETURNING\", Token.RETURNING);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"ROWS\", Token.ROWS);\n        map.put(\"SHARE\", Token.SHARE);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"START\", Token.START);\n\n        map.put(\"USING\", Token.USING);\n        map.put(\"WINDOW\", Token.WINDOW);\n\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"IF\", Token.IF);\n        map.put(\"TYPE\", Token.TYPE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"PARTITION\", Token.PARTITION);\n\n        map.put(\"TOP\", Token.TOP);\n        map.put(\"PERCENT\", Token.PERCENT);\n\n        map.put(\"LOCAL\", Token.LOCAL);\n        map.put(\"GLOBAL\", Token.GLOBAL);\n\n        map.put(\"TEMPORARY\", Token.TEMPORARY);\n        map.put(\"TEMP\", Token.TEMP);\n\n        // DM-specific Oracle-compatible keywords\n        map.put(\"CONNECT\", Token.CONNECT);\n        map.put(\"PRIOR\", Token.PRIOR);\n        map.put(\"WAIT\", Token.WAIT);\n        map.put(\"SEQUENCE\", Token.SEQUENCE);\n        map.put(\"TABLESPACE\", Token.TABLESPACE);\n\n        DM_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return DM_KEYWORDS;\n    }\n\n    public DmLexer(String input, SQLParserFeature... features) {\n        super(input, true);\n        this.keepComments = true;\n        super.dbType = DbType.dm;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    @Override\n    protected void scanString() {\n        mark = pos;\n        boolean hasSpecial = false;\n\n        for (;;) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    @Override\n    protected void scanVariable_at() {\n        if (ch != '@') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n        char ch;\n\n        final char c1 = charAt(pos + 1);\n        if (c1 == '@') {\n            pos += 2;\n            token = Token.MONKEYS_AT_AT;\n            this.ch = charAt(++pos);\n            return;\n        }\n\n        for (;;) {\n            ch = charAt(++pos);\n\n            if (!isIdentifierChar(ch)) {\n                break;\n            }\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = addSymbol();\n        token = Token.VARIANT;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/parser/DmSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.dm.ast.stmt.DmSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class DmSelectParser extends SQLSelectParser {\n    public DmSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public DmSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public DmSelectParser(String sql) {\n        this(new DmExprParser(sql));\n    }\n\n    protected DmExprParser createExprParser() {\n        return new DmExprParser(lexer);\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.VALUES) {\n            return valuesQuery(acceptUnion);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            if (select instanceof SQLSelectQueryBlock) {\n                ((SQLSelectQueryBlock) select).setParenthesized(true);\n            }\n            accept(Token.RPAREN);\n            select.setParenthesized(true);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        DmSelectQueryBlock queryBlock = new DmSelectQueryBlock();\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.DISTINCT) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.ALL) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.UNIQUE) {\n                queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n                lexer.nextToken();\n            }\n\n            // DM supports TOP N [PERCENT] [WITH TIES]\n            if (lexer.token() == Token.TOP) {\n                SQLTop top = this.createExprParser().parseTop();\n                queryBlock.setTop(top);\n            }\n\n            parseSelectList(queryBlock);\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseHierachical(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        if (lexer.token() == Token.WINDOW) {\n            this.parseWindow(queryBlock);\n        }\n\n        queryBlock.setOrderBy(this.createExprParser().parseOrderBy());\n\n        // DM LIMIT syntax:\n        // LIMIT <count>\n        // LIMIT <offset>, <count>\n        // LIMIT <count> OFFSET <offset>\n        // OFFSET <offset> LIMIT <count>\n        // OFFSET <offset> ROW[S]\n        for (;;) {\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = getOrInitLimit(queryBlock);\n\n                lexer.nextToken();\n                if (lexer.token() == Token.ALL) {\n                    limit.setRowCount(new SQLIdentifierExpr(\"ALL\"));\n                    lexer.nextToken();\n                } else {\n                    SQLExpr first = expr();\n                    // LIMIT offset, count\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        SQLExpr second = expr();\n                        limit.setOffset(first);\n                        limit.setRowCount(second);\n                    } else {\n                        limit.setRowCount(first);\n                    }\n                }\n\n                if (lexer.token() == Token.OFFSET) {\n                    lexer.nextToken();\n                    SQLExpr offset = expr();\n                    limit.setOffset(offset);\n                    limit.setOffsetClause(true);\n                }\n\n                queryBlock.setLimit(limit);\n            } else if (lexer.token() == Token.OFFSET) {\n                SQLLimit limit = getOrInitLimit(queryBlock);\n                lexer.nextToken();\n                SQLExpr offset = expr();\n                limit.setOffset(offset);\n                limit.setOffsetClause(true);\n\n                if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) {\n                    lexer.nextToken();\n                }\n\n                queryBlock.setLimit(limit);\n            } else {\n                break;\n            }\n        }\n\n        // FETCH FIRST|NEXT <count> [PERCENT] ROW[S] ONLY|WITH TIES\n        if (lexer.token() == Token.FETCH) {\n            lexer.nextToken();\n            DmSelectQueryBlock.FetchClause fetch = new DmSelectQueryBlock.FetchClause();\n\n            if (lexer.token() == Token.FIRST) {\n                fetch.setOption(DmSelectQueryBlock.FetchClause.Option.FIRST);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.NEXT) {\n                fetch.setOption(DmSelectQueryBlock.FetchClause.Option.NEXT);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'FIRST' or 'NEXT'. \" + lexer.info());\n            }\n\n            SQLExpr count = expr();\n            fetch.setCount(count);\n\n            if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'ROW' or 'ROWS'. \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.ONLY) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'ONLY'. \" + lexer.info());\n            }\n\n            queryBlock.setFetch(fetch);\n        }\n\n        // FOR UPDATE [OF <col_list>] [NOWAIT | WAIT N | SKIP LOCKED]\n        // FOR READ ONLY (not commonly used, skip for now)\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n\n            DmSelectQueryBlock.ForClause forClause = new DmSelectQueryBlock.ForClause();\n\n            if (lexer.token() == Token.UPDATE) {\n                forClause.setOption(DmSelectQueryBlock.ForClause.Option.UPDATE);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.SHARE) {\n                forClause.setOption(DmSelectQueryBlock.ForClause.Option.SHARE);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'UPDATE' or 'SHARE'. \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.OF) {\n                lexer.nextToken();\n                for (;;) {\n                    SQLExpr expr = this.createExprParser().expr();\n                    expr.setParent(forClause);\n                    forClause.getOf().add(expr);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else {\n                        break;\n                    }\n                }\n            }\n\n            if (lexer.token() == Token.NOWAIT) {\n                lexer.nextToken();\n                forClause.setNoWait(true);\n            } else if (lexer.token() == Token.WAIT) {\n                lexer.nextToken();\n                SQLExpr waitTimeout = expr();\n                forClause.setWaitTimeout(waitTimeout);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SKIP)) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOCKED\");\n                forClause.setSkipLocked(true);\n            }\n\n            queryBlock.setForClause(forClause);\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    private SQLLimit getOrInitLimit(SQLSelectQueryBlock queryBlock) {\n        SQLLimit limit = queryBlock.getLimit();\n        if (limit == null) {\n            limit = new SQLLimit();\n            queryBlock.setLimit(limit);\n        }\n        return limit;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/parser/DmStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.dm.ast.stmt.*;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.List;\n\npublic class DmStatementParser extends SQLStatementParser {\n    public DmStatementParser(DmExprParser parser) {\n        super(parser);\n    }\n\n    public DmStatementParser(String sql) {\n        super(new DmExprParser(sql));\n    }\n\n    public DmStatementParser(String sql, SQLParserFeature... features) {\n        super(new DmExprParser(sql, features));\n    }\n\n    public DmStatementParser(Lexer lexer) {\n        super(new DmExprParser(lexer));\n    }\n\n    @Override\n    public DmSelectParser createSQLSelectParser() {\n        return new DmSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLUpdateStatement parseUpdateStatement() {\n        accept(Token.UPDATE);\n\n        DmUpdateStatement updateStatement = new DmUpdateStatement();\n\n        SQLSelectParser selectParser = this.exprParser.createSelectParser();\n        SQLTableSource tableSource = selectParser.parseTableSource();\n        updateStatement.setTableSource(tableSource);\n\n        parseUpdateSet(updateStatement);\n\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n            SQLTableSource from = selectParser.parseTableSource();\n            updateStatement.setFrom(from);\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            updateStatement.setWhere(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n\n            for (;;) {\n                updateStatement.getReturning().add(this.exprParser.expr());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        return updateStatement;\n    }\n\n    @Override\n    public DmInsertStatement parseInsert() {\n        DmInsertStatement stmt = new DmInsertStatement();\n\n        if (lexer.token() == Token.INSERT) {\n            lexer.nextToken();\n            accept(Token.INTO);\n\n            SQLName tableName = this.exprParser.name();\n            stmt.setTableName(tableName);\n\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.token() == Token.IDENTIFIER) {\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            }\n        }\n\n        if (lexer.token() == (Token.LPAREN)) {\n            lexer.nextToken();\n            this.exprParser.exprList(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == (Token.VALUES)) {\n            lexer.nextToken();\n\n            for (;;) {\n                accept(Token.LPAREN);\n                SQLInsertStatement.ValuesClause valuesClause = new SQLInsertStatement.ValuesClause();\n                this.exprParser.exprList(valuesClause.getValues(), valuesClause);\n                stmt.addValueCause(valuesClause);\n\n                accept(Token.RPAREN);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        } else if (lexer.token() == (Token.SELECT)) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n            stmt.setQuery(queryExpr.getSubQuery());\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public DmDeleteStatement parseDeleteStatement() {\n        lexer.nextToken();\n        DmDeleteStatement deleteStatement = new DmDeleteStatement();\n\n        if (lexer.token() == (Token.FROM)) {\n            lexer.nextToken();\n        }\n\n        SQLName tableName = exprParser.name();\n        deleteStatement.setTableName(tableName);\n\n        if (lexer.token() == Token.AS) {\n            accept(Token.AS);\n        }\n        if (lexer.token() == Token.IDENTIFIER) {\n            deleteStatement.setAlias(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.CURRENT) {\n                lexer.nextToken();\n                accept(Token.OF);\n                SQLName cursorName = this.exprParser.name();\n                SQLExpr where = new SQLCurrentOfCursorExpr(cursorName);\n                deleteStatement.setWhere(where);\n            } else {\n                SQLExpr where = this.exprParser.expr();\n                deleteStatement.setWhere(where);\n            }\n        }\n\n        return deleteStatement;\n    }\n\n    @Override\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        switch (lexer.token()) {\n            case BEGIN:\n            case START: {\n                SQLStatement stmt = parseBlock();\n                statementList.add(stmt);\n                return true;\n            }\n            case WITH:\n                statementList.add(parseWith());\n                return true;\n            default:\n                break;\n        }\n        return false;\n    }\n\n    @Override\n    public DmSelectStatement parseSelect() {\n        DmSelectParser selectParser = createSQLSelectParser();\n        SQLSelect select = selectParser.select();\n        return new DmSelectStatement(select);\n    }\n\n    @Override\n    public SQLStatement parseWith() {\n        SQLWithSubqueryClause with = this.parseWithQuery();\n\n        if (lexer.token() == Token.INSERT) {\n            DmInsertStatement stmt = this.parseInsert();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            DmSelectStatement stmt = this.parseSelect();\n            stmt.getSelect().setWithSubQuery(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.DELETE) {\n            DmDeleteStatement stmt = this.parseDeleteStatement();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.UPDATE) {\n            DmUpdateStatement stmt = (DmUpdateStatement) this.parseUpdateStatement();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        throw new ParserException(\"TODO. \" + lexer.info());\n    }\n\n    @Override\n    protected SQLAlterTableAlterColumn parseAlterColumn() {\n        if (lexer.token() == Token.COLUMN) {\n            lexer.nextToken();\n        }\n\n        SQLColumnDefinition column = this.exprParser.parseColumn();\n\n        SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn();\n        alterColumn.setColumn(column);\n\n        if (column.getDataType() == null && column.getConstraints().isEmpty()) {\n            if (lexer.token() == Token.SET) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setSetNotNull(true);\n                } else {\n                    accept(Token.DEFAULT);\n                    SQLExpr defaultValue = this.exprParser.expr();\n                    alterColumn.setSetDefault(defaultValue);\n                }\n            } else if (lexer.token() == Token.DROP) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setDropNotNull(true);\n                } else {\n                    accept(Token.DEFAULT);\n                    alterColumn.setDropDefault(true);\n                }\n            }\n        }\n        return alterColumn;\n    }\n\n    @Override\n    public SQLStatement parseShow() {\n        accept(Token.SHOW);\n        SQLShowTablesStatement stmt = new SQLShowTablesStatement();\n        stmt.setDatabase(this.exprParser.name());\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseCommit() {\n        SQLCommitStatement stmt = new SQLCommitStatement();\n        stmt.setDbType(this.dbType);\n        lexer.nextToken();\n        return stmt;\n    }\n\n    @Override\n    public SQLCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n        SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(getDbType());\n        if (lexer.token() == Token.UNIQUE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"CLUSTERED\")) {\n                lexer.nextToken();\n                stmt.setType(\"UNIQUE CLUSTERED\");\n            } else {\n                stmt.setType(\"UNIQUE\");\n            }\n        } else if (lexer.identifierEquals(\"FULLTEXT\")) {\n            stmt.setType(\"FULLTEXT\");\n            lexer.nextToken();\n        }\n\n        accept(Token.INDEX);\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        if (lexer.token() != Token.ON) {\n            stmt.setName(this.exprParser.name());\n        }\n\n        accept(Token.ON);\n\n        stmt.setTable(this.exprParser.name());\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n            String using = lexer.stringVal();\n            accept(Token.IDENTIFIER);\n            stmt.setUsing(using);\n        }\n\n        accept(Token.LPAREN);\n\n        for (;;) {\n            SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n            item.setParent(stmt);\n            stmt.addItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.TABLESPACE) {\n            lexer.nextToken();\n            SQLName tablespace = this.exprParser.name();\n            stmt.setTablespace(tablespace);\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new DmCreateTableParser(this.exprParser);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/visitor/DmASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.visitor;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.dm.ast.stmt.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface DmASTVisitor extends SQLASTVisitor {\n    default void endVisit(DmSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(DmSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(DmSelectQueryBlock.FetchClause x) {\n    }\n\n    default boolean visit(DmSelectQueryBlock.FetchClause x) {\n        return true;\n    }\n\n    default void endVisit(DmSelectQueryBlock.ForClause x) {\n    }\n\n    default boolean visit(DmSelectQueryBlock.ForClause x) {\n        return true;\n    }\n\n    default void endVisit(DmDeleteStatement x) {\n    }\n\n    default boolean visit(DmDeleteStatement x) {\n        return true;\n    }\n\n    default void endVisit(DmInsertStatement x) {\n    }\n\n    default boolean visit(DmInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(DmSelectStatement x) {\n        endVisit((SQLSelectStatement) x);\n    }\n\n    default boolean visit(DmSelectStatement x) {\n        return visit((SQLSelectStatement) x);\n    }\n\n    default void endVisit(DmUpdateStatement x) {\n    }\n\n    default boolean visit(DmUpdateStatement x) {\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/visitor/DmOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.dm.Dm;\nimport com.alibaba.druid.sql.dialect.dm.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.dm.ast.stmt.DmSelectQueryBlock.FetchClause;\nimport com.alibaba.druid.sql.dialect.dm.ast.stmt.DmSelectQueryBlock.ForClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\nimport java.util.List;\n\npublic class DmOutputVisitor extends SQLASTOutputVisitor implements DmASTVisitor, OracleASTVisitor {\n    public DmOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.dm, Dm.DIALECT);\n    }\n\n    public DmOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.dm, Dm.DIALECT, parameterized);\n    }\n\n    @Override\n    public boolean visit(FetchClause x) {\n        print0(ucase ? \"FETCH \" : \"fetch \");\n        if (FetchClause.Option.FIRST.equals(x.getOption())) {\n            print0(ucase ? \"FIRST \" : \"first \");\n        } else if (FetchClause.Option.NEXT.equals(x.getOption())) {\n            print0(ucase ? \"NEXT \" : \"next \");\n        }\n        x.getCount().accept(this);\n        print0(ucase ? \" ROWS ONLY\" : \" rows only\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ForClause x) {\n        print0(ucase ? \"FOR \" : \"for \");\n        if (ForClause.Option.UPDATE.equals(x.getOption())) {\n            print0(ucase ? \"UPDATE\" : \"update\");\n        } else if (ForClause.Option.SHARE.equals(x.getOption())) {\n            print0(ucase ? \"SHARE\" : \"share\");\n        }\n\n        if (x.getOf().size() > 0) {\n            print0(ucase ? \" OF \" : \" of \");\n            for (int i = 0; i < x.getOf().size(); ++i) {\n                if (i != 0) {\n                    println(\", \");\n                }\n                x.getOf().get(i).accept(this);\n            }\n        }\n\n        if (x.isNoWait()) {\n            print0(ucase ? \" NOWAIT\" : \" nowait\");\n        } else if (x.getWaitTimeout() != null) {\n            print0(ucase ? \" WAIT \" : \" wait \");\n            x.getWaitTimeout().accept(this);\n        } else if (x.isSkipLocked()) {\n            print0(ucase ? \" SKIP LOCKED\" : \" skip locked\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(DmSelectQueryBlock x) {\n        if ((!isParameterized()) && isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        final boolean bracket = x.isParenthesized();\n        if (bracket) {\n            print('(');\n        }\n\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == x.getDistionOption()) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        }\n\n        SQLTop top = x.getTop();\n        if (top != null) {\n            top.accept(this);\n            print(' ');\n        }\n\n        printSelectList(x.getSelectList());\n\n        SQLExprTableSource into = x.getInto();\n        if (into != null) {\n            println();\n            print0(ucase ? \"INTO \" : \"into \");\n            into.accept(this);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from != null) {\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n            printTableSource(from);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where, parameterized);\n        }\n\n        printHierarchical(x);\n\n        SQLSelectGroupByClause groupBy = x.getGroupBy();\n        if (groupBy != null) {\n            println();\n            visit(groupBy);\n        }\n\n        List<SQLWindow> windows = x.getWindows();\n        if (windows != null && windows.size() > 0) {\n            println();\n            print0(ucase ? \"WINDOW \" : \"window \");\n            printAndAccept(windows, \", \");\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            orderBy.accept(this);\n        }\n\n        SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            println();\n            visit(limit);\n        }\n\n        FetchClause fetch = x.getFetch();\n        if (fetch != null) {\n            println();\n            fetch.accept(this);\n        }\n\n        ForClause forClause = x.getForClause();\n        if (forClause != null) {\n            println();\n            forClause.accept(this);\n        }\n\n        if (bracket) {\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(DmDeleteStatement x) {\n        print0(ucase ? \"DELETE \" : \"delete \");\n\n        print0(ucase ? \"FROM \" : \"from \");\n\n        printTableSource(x.getTableSource());\n\n        if (x.getAlias() != null) {\n            print(' ');\n            print0(x.getAlias());\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where, parameterized);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(DmInsertStatement x) {\n        print0(ucase ? \"INSERT INTO \" : \"insert into \");\n\n        x.getTableSource().accept(this);\n\n        printInsertColumns(x.getColumns());\n\n        if (!x.getValuesList().isEmpty()) {\n            println();\n            print0(ucase ? \"VALUES\" : \"values\");\n            for (int i = 0, size = x.getValuesList().size(); i < size; ++i) {\n                if (i != 0) {\n                    print(',');\n                }\n                println();\n                print('(');\n                SQLInsertStatement.ValuesClause values = x.getValuesList().get(i);\n                printAndAccept(values.getValues(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.getQuery() != null) {\n            println();\n            x.getQuery().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(DmUpdateStatement x) {\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        printTableSource(x.getTableSource());\n\n        println();\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLUpdateSetItem item = x.getItems().get(i);\n            visit(item);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from != null) {\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n            printTableSource(from);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where, parameterized);\n        }\n\n        List<SQLExpr> returning = x.getReturning();\n        if (returning != null && returning.size() > 0) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            printAndAccept(returning, \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(DmSelectStatement x) {\n        return visit(x.getSelect());\n    }\n\n    @Override\n    public void endVisit(DmSelectStatement x) {\n    }\n\n    // Oracle AST visitor default implementations for DM Oracle-compatibility\n    @Override\n    public boolean visit(OracleSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/dm/visitor/DmSchemaStatVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.dm.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\npublic class DmSchemaStatVisitor extends SchemaStatVisitor implements DmASTVisitor {\n    public DmSchemaStatVisitor() {\n        super(DbType.dm);\n    }\n\n    public DmSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/Doris.java",
    "content": "package com.alibaba.druid.sql.dialect.doris;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Doris {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.doris);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/ast/DorisExprTableSource.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.doris.visitor.DorisASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class DorisExprTableSource extends SQLExprTableSource implements DorisObject {\n    protected List<SQLExpr> tablets;\n    protected SQLExpr repeatable;\n\n    public void addTablet(SQLExpr tablet) {\n        if (tablets == null) {\n            tablets = new ArrayList<>(2);\n        }\n\n        if (tablet != null) {\n            tablet.setParent(this);\n            tablets.add(tablet);\n        }\n    }\n\n    public List<SQLExpr> getTablets() {\n        if (tablets == null) {\n            tablets = new ArrayList<>(2);\n        }\n        return tablets;\n    }\n\n    public SQLExpr getRepeatable() {\n        return repeatable;\n    }\n\n    public void setRepeatable(SQLExpr repeatable) {\n        if (repeatable != null) {\n            repeatable.setParent(this);\n        }\n        this.repeatable = repeatable;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof DorisASTVisitor) {\n            accept0((DorisASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(DorisASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.tablets);\n            acceptChild(visitor, this.repeatable);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/ast/DorisObject.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.doris.visitor.DorisASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface DorisObject extends SQLObject {\n    default void accept0(SQLASTVisitor v) {\n        if (v instanceof DorisASTVisitor) {\n            accept0((DorisASTVisitor) v);\n        }\n    }\n    void accept0(DorisASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/ast/DorisObjectImpl.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.doris.visitor.DorisASTVisitor;\n\npublic abstract class DorisObjectImpl extends SQLObjectImpl implements DorisObject {\n    public abstract void accept0(DorisASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/parser/DorisCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionByList;\nimport com.alibaba.druid.sql.ast.SQLPartitionByRange;\nimport com.alibaba.druid.sql.ast.SQLPartitionByValue;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class DorisCreateTableParser\n        extends StarRocksCreateTableParser {\n    public DorisCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.doris;\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        if (lexer.nextIf(Token.PARTITION)) {\n            accept(Token.BY);\n            SQLPartitionBy partitionClause;\n            boolean hasLparen = false;\n            if (lexer.nextIfIdentifier(FnvHash.Constants.RANGE)) {\n                partitionClause = new SQLPartitionByRange();\n                accept(Token.LPAREN);\n                hasLparen = true;\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.LIST)) {\n                partitionClause = new SQLPartitionByList();\n                ((SQLPartitionByList) partitionClause).setType(SQLPartitionByList.PartitionByListType.LIST_EXPRESSION);\n                accept(Token.LPAREN);\n                hasLparen = true;\n            } else {\n                partitionClause = new SQLPartitionByValue();\n            }\n\n            for (; ;) {\n                partitionClause.addColumn(this.exprParser.expr());\n                if (lexer.nextIf(Token.COMMA)) {\n                    continue;\n                }\n                break;\n            }\n\n            if (hasLparen && !lexer.nextIf(Token.RPAREN)) {\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    if (lexer.token() == Token.RPAREN) {\n                        break;\n                    }\n                    partitionClause.addPartition(this.getExprParser().parsePartition());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n            return partitionClause;\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/parser/DorisExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksExprParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class DorisExprParser\n        extends StarRocksExprParser {\n    public DorisExprParser(String sql, SQLParserFeature... features) {\n        super(new DorisLexer(sql, features));\n        lexer.nextToken();\n        dbType = DbType.doris;\n    }\n\n    public DorisExprParser(Lexer lexer) {\n        super(lexer);\n        dbType = DbType.doris;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/parser/DorisLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksLexer;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class DorisLexer\n        extends StarRocksLexer {\n    static final Keywords DORIS_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"DISTINCTROW\", Token.DISTINCTROW);\n        map.put(\"EXCEPT\", Token.EXCEPT);\n        map.put(\"TABLET\", Token.TABLET);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"ROWS\", Token.ROWS);\n        map.put(\"PERCENT\", Token.PERCENT);\n        map.put(\"REPEATABLE\", Token.REPEATABLE);\n        map.put(\"TABLESAMPLE\", Token.TABLESAMPLE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"IF\", Token.IF);\n\n        map.put(\"ADD\", Token.ADD);\n        map.put(\"BOTH\", Token.BOTH);\n        map.put(\"DUAL\", Token.DUAL);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"FORCE\", Token.FORCE);\n        map.put(\"KILL\", Token.KILL);\n        map.put(\"BITMAP\", Token.BITMAP);\n        map.put(\"INVERTED\", Token.INVERTED);\n\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"ANALYZE\", Token.ANALYZE);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"MOD\", Token.MOD);\n        map.put(\"RLIKE\", Token.RLIKE);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n\n        DORIS_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return DORIS_KEYWORDS;\n    }\n\n    public DorisLexer(String input, SQLParserFeature... features) {\n        super(input);\n        this.keepComments = true;\n        dbType = DbType.doris;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/parser/DorisSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSampling;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.doris.ast.DorisExprTableSource;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class DorisSelectParser\n        extends StarRocksSelectParser {\n    public DorisSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.doris;\n    }\n\n    protected DorisExprParser createExprParser() {\n        return new DorisExprParser(lexer);\n    }\n\n    @Override\n    protected void parseBeforeSelectList(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token() == Token.DISTINCT) {\n            queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.DISTINCTROW) {\n            queryBlock.setDistionOption(SQLSetQuantifier.DISTINCTROW);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.ALL) {\n            lexer.nextToken();\n            if (lexer.nextIf(Token.EXCEPT)) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL_EXCEPT);\n            } else {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n            }\n        }\n    }\n\n    @Override\n    public void parseAfterTableSourceRest(SQLTableSource tableSource) {\n        if (tableSource instanceof DorisExprTableSource) {\n            DorisExprTableSource dorisExprTableSource = (DorisExprTableSource) tableSource;\n            if (lexer.nextIf(Token.PARTITION)) {\n                accept(Token.LPAREN);\n                do {\n                    dorisExprTableSource.addPartition(this.exprParser.name());\n                }\n                while (lexer.nextIf(Token.COMMA));\n                accept(Token.RPAREN);\n            }\n            if (lexer.nextIf(Token.TABLET)) {\n                accept(Token.LPAREN);\n                dorisExprTableSource.addTablet(expr());\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.nextIf(Token.TABLESAMPLE)) {\n                accept(Token.LPAREN);\n                SQLTableSampling sqlTableSampling = new SQLTableSampling();\n                SQLExpr expr = expr();\n                if (lexer.nextIf(Token.ROWS)) {\n                    sqlTableSampling.setRows(expr);\n                } else if (lexer.nextIf(Token.PERCENT)) {\n                    sqlTableSampling.setPercent(expr);\n                } else {\n                    sqlTableSampling.setByteLength(expr);\n                }\n                dorisExprTableSource.setSampling(sqlTableSampling);\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.nextIf(Token.REPEATABLE)) {\n                dorisExprTableSource.setRepeatable(expr());\n            }\n\n        }\n    }\n    @Override\n    protected SQLExprTableSource getTableSource() {\n        return new DorisExprTableSource();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/parser/DorisStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertInto;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksStatementParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class DorisStatementParser\n        extends StarRocksStatementParser {\n    public DorisStatementParser(SQLExprParser parser) {\n        super(parser);\n        dbType = DbType.doris;\n    }\n\n    public DorisStatementParser(String sql, SQLParserFeature... features) {\n        this(new DorisExprParser(sql, features));\n    }\n\n    @Override\n    public DorisSelectParser createSQLSelectParser() {\n        return new DorisSelectParser(this.exprParser, selectListCache);\n    }\n\n    public DorisCreateTableParser getSQLCreateTableParser() {\n        return new DorisCreateTableParser(this.exprParser);\n    }\n\n    @Override\n    protected void parseInsertOverwrite(SQLInsertInto insertStatement) {\n        insertStatement.setOverwrite(true);\n        accept(Token.TABLE);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/visitor/DorisASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.visitor;\n\nimport com.alibaba.druid.sql.dialect.doris.ast.DorisExprTableSource;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface DorisASTVisitor extends SQLASTVisitor {\n    default boolean visit(DorisExprTableSource x) { return true; }\n    default void endVisit(DorisExprTableSource x) {}\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/doris/visitor/DorisOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.doris.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLPivot;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.SQLUnpivot;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSampling;\nimport com.alibaba.druid.sql.dialect.doris.Doris;\nimport com.alibaba.druid.sql.dialect.doris.ast.DorisExprTableSource;\nimport com.alibaba.druid.sql.dialect.starrocks.visitor.StarRocksOutputVisitor;\n\nimport java.util.List;\n\npublic class DorisOutputVisitor extends StarRocksOutputVisitor implements DorisASTVisitor {\n    public DorisOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.doris, Doris.DIALECT);\n    }\n\n    public DorisOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.doris, Doris.DIALECT, parameterized);\n    }\n\n    public void printSqlSetQuantifier(SQLSelectQueryBlock x) {\n        final int distinctOption = x.getDistionOption();\n        if (SQLSetQuantifier.ALL == distinctOption) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == distinctOption) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == distinctOption) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        } else if (SQLSetQuantifier.ALL_EXCEPT == distinctOption) {\n            print0(ucase ? \"ALL EXCEPT \" : \"all except \");\n        }\n    }\n\n    @Override\n    public boolean visit(DorisExprTableSource x) {\n        printTableSourceExpr(x.getExpr());\n\n        if (!x.getPartitions().isEmpty()) {\n            println();\n            print(ucase ? \"PARTITION(\" : \"partition(\");\n            printAndAccept(x.getPartitions(), \", \");\n            print(\")\");\n        }\n\n        if (!x.getTablets().isEmpty()) {\n            println();\n            print(ucase ? \"TABLET(\" : \"tablet(\");\n            printAndAccept(x.getTablets(), \", \");\n            print(\")\");\n        }\n\n        final SQLTableSampling sampling = x.getSampling();\n        if (sampling != null) {\n            println();\n            sampling.accept(this);\n        }\n\n        if (x.getRepeatable() != null) {\n            println();\n            print0(ucase ? \"REPEATABLE \" : \"repeatable \");\n            x.getRepeatable().accept(this);\n        }\n\n        String alias = x.getAlias();\n        List<SQLName> columns = x.getColumnsDirect();\n        if (alias != null) {\n            print(' ');\n            if (columns != null && columns.size() > 0) {\n                print0(ucase ? \" AS \" : \" as \");\n            } else if (x.isNeedAsTokenForAlias()) {\n                print0(ucase ? \"AS \" : \"as \");\n            }\n            print0(alias);\n        }\n\n        if (columns != null && columns.size() > 0) {\n            print(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        SQLPivot pivot = x.getPivot();\n        if (pivot != null) {\n            println();\n            pivot.accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        if (isPrettyFormat() && x.hasAfterComment()) {\n            print(' ');\n            printlnComment(x.getAfterCommentsDirect());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTableSampling x) {\n        print0(ucase ? \"TABLESAMPLE\" : \"tablesample\");\n        print('(');\n\n        final SQLExpr percent = x.getPercent();\n        if (percent != null) {\n            percent.accept(this);\n            print0(ucase ? \" PERCENT\" : \" percent\");\n        }\n\n        final SQLExpr rows = x.getRows();\n        if (rows != null) {\n            rows.accept(this);\n            print0(ucase ? \" ROWS\" : \" rows\");\n        }\n\n        final SQLExpr size = x.getByteLength();\n        if (size != null) {\n            size.accept(this);\n        }\n\n        print(')');\n        return false;\n    }\n\n    @Override\n    public void printInsertOverWrite(SQLInsertStatement x) {\n        print0(ucase ? \"INSERT OVERWRITE TABLE \" : \"insert overwrite table \");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/GaussDb.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class GaussDb {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.gaussdb);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/ast/GaussDbDistributeBy.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.ast;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.dialect.gaussdb.visitor.GaussDbASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class GaussDbDistributeBy extends GaussDbObjectImpl {\n    protected SQLSubPartitionBy subPartitionBy;\n    protected List<SQLPartition> distributions = new ArrayList<>();\n    protected List<SQLName> storeIn = new ArrayList<SQLName>();\n    protected List<SQLExpr> columns = new ArrayList<SQLExpr>();\n    protected SQLName type;\n\n    protected SQLIntegerExpr lifeCycle;\n\n    public List<SQLPartition> getDistributions() {\n        return distributions;\n    }\n\n    public void setType(SQLName type) {\n        this.type = type;\n    }\n\n    public SQLName getType() {\n        return type;\n    }\n\n    public void addDistribution(SQLPartitionSingle distribution) {\n        if (distribution != null) {\n            distribution.setParent(this);\n        }\n        this.distributions.add(distribution);\n    }\n\n    public SQLSubPartitionBy getSubPartitionBy() {\n        return subPartitionBy;\n    }\n\n    public void setSubPartitionBy(SQLSubPartitionBy subPartitionBy) {\n        if (subPartitionBy != null) {\n            subPartitionBy.setParent(this);\n        }\n        this.subPartitionBy = subPartitionBy;\n    }\n\n    public List<SQLName> getStoreIn() {\n        return storeIn;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLExpr column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public boolean isDistributionColumn(long columnNameHashCode64) {\n        for (SQLExpr column : columns) {\n            if (column instanceof SQLIdentifierExpr\n                    && ((SQLIdentifierExpr) column)\n                    .nameHashCode64() == columnNameHashCode64) {\n                return true;\n            }\n        }\n\n        if (subPartitionBy != null) {\n            return subPartitionBy.isPartitionByColumn(columnNameHashCode64);\n        }\n        return false;\n    }\n\n    public SQLIntegerExpr getLifeCycle() {\n        return lifeCycle;\n    }\n\n    public void setLifeCycle(SQLIntegerExpr x) {\n        this.lifeCycle = x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof GaussDbASTVisitor) {\n            GaussDbASTVisitor vv = (GaussDbASTVisitor) v;\n            if (vv.visit(this)) {\n                acceptChild(v, this.columns);\n                acceptChild(v, this.distributions);\n                acceptChild(v, this.storeIn);\n                acceptChild(v, this.lifeCycle);\n                acceptChild(v, this.type);\n                acceptChild(v, this.subPartitionBy);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/ast/GaussDbObject.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.gaussdb.visitor.GaussDbASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface GaussDbObject extends SQLObject {\n    default void accept0(SQLASTVisitor v) {\n        if (v instanceof GaussDbASTVisitor) {\n            accept0((GaussDbASTVisitor) v);\n        }\n    }\n    void accept0(GaussDbASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/ast/GaussDbObjectImpl.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.gaussdb.visitor.GaussDbASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class GaussDbObjectImpl extends SQLObjectImpl implements GaussDbObject {\n    public void accept0(SQLASTVisitor v) {}\n    public void accept0(GaussDbASTVisitor visitor) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/ast/GaussDbPartitionValue.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLPartitionValue;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class GaussDbPartitionValue extends SQLPartitionValue {\n    private SQLExpr spaceName;\n    private SQLExpr dataNode;\n    private SQLExpr start;\n    private SQLExpr end;\n    private SQLExpr every;\n    private boolean isDistribute;\n\n    public GaussDbPartitionValue(Operator operator) {\n        super();\n        this.operator = operator;\n    }\n\n    public void setSpaceName(SQLExpr spaceName) {\n        if (spaceName != null) {\n            spaceName.setParent(this);\n        }\n        this.spaceName = spaceName;\n    }\n\n    public SQLExpr getSpaceName() {\n        return spaceName;\n    }\n\n    public void setDataNodes(SQLExpr dataNode) {\n        if (dataNode != null) {\n            dataNode.setParent(this);\n        }\n        this.dataNode = dataNode;\n    }\n\n    public SQLExpr getDataNode() {\n        return dataNode;\n    }\n\n    public void setStart(SQLExpr start) {\n        if (start != null) {\n            start.setParent(this);\n        }\n        this.start = start;\n    }\n\n    public SQLExpr getStart() {\n        return start;\n    }\n\n    public void setEnd(SQLExpr end) {\n        if (end != null) {\n            end.setParent(this);\n        }\n        this.end = end;\n    }\n\n    public SQLExpr getEnd() {\n        return end;\n    }\n\n    public void setEvery(SQLExpr every) {\n        if (every != null) {\n            every.setParent(this);\n        }\n        this.every = every;\n    }\n\n    public SQLExpr getEvery() {\n        return every;\n    }\n\n    public void setDistribute(boolean isDistribute) {\n        this.isDistribute = isDistribute;\n    }\n\n    public boolean getDistribute() {\n        return isDistribute;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, start);\n            acceptChild(visitor, end);\n            acceptChild(visitor, every);\n            acceptChild(visitor, spaceName);\n            acceptChild(visitor, dataNode);\n            visitor.endVisit(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/ast/stmt/GaussDbCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.GaussDbDistributeBy;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.GaussDbObject;\nimport com.alibaba.druid.sql.dialect.gaussdb.visitor.GaussDbASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class GaussDbCreateTableStatement extends SQLCreateTableStatement implements GaussDbObject {\n    protected GaussDbDistributeBy distributeBy;\n    protected SQLExpr toGroup;\n    protected SQLExpr toNode;\n    protected SQLExpr server;\n    private SQLExpr onCommitExpr;\n    private SQLExpr compressType;\n    private SQLExpr rowMovementType;\n    private ForeignTableMode foreignTableMode;\n\n    public GaussDbCreateTableStatement() {\n        super(DbType.gaussdb);\n    }\n\n    public void setDistributeBy(GaussDbDistributeBy distributeBy) {\n        if (distributeBy != null) {\n            distributeBy.setParent(this);\n        }\n        this.distributeBy = distributeBy;\n    }\n\n    public GaussDbDistributeBy getDistributeBy() {\n        return distributeBy;\n    }\n\n    public void setToGroup(SQLExpr toGroup) {\n        if (toGroup != null) {\n            toGroup.setParent(this);\n        }\n        this.toGroup = toGroup;\n    }\n\n    public SQLExpr getToGroup() {\n        return toGroup;\n    }\n\n    public void setToNode(SQLExpr toNode) {\n        if (toNode != null) {\n            toNode.setParent(this);\n        }\n        this.toNode = toNode;\n    }\n\n    public SQLExpr getToNode() {\n        return toNode;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof GaussDbASTVisitor) {\n            accept0((GaussDbASTVisitor) v);\n            return;\n        }\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public void accept0(GaussDbASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.distributeBy);\n            acceptChild((SQLASTVisitor) visitor);\n        }\n    }\n\n    public SQLExpr getOnCommitExpr() {\n        return onCommitExpr;\n    }\n\n    public void setOnCommitExpr(SQLExpr onCommitExpr) {\n        this.onCommitExpr = onCommitExpr;\n    }\n\n    public SQLExpr getCompressType() {\n        return compressType;\n    }\n\n    public void setCompressType(SQLExpr compressType) {\n        this.compressType = compressType;\n    }\n\n    public SQLExpr getRowMovementType() {\n        return rowMovementType;\n    }\n\n    public void setRowMovementType(SQLExpr rowMovementType) {\n        this.rowMovementType = rowMovementType;\n    }\n    public SQLExpr getServer() {\n        return server;\n    }\n\n    public void setServer(SQLExpr server) {\n        if (server != null) {\n            server.setParent(this);\n        }\n        this.server = server;\n    }\n\n    public ForeignTableMode getForeignTableMode() {\n        return foreignTableMode;\n    }\n\n    public void setForeignTableMode(ForeignTableMode foreignTableMode) {\n        this.foreignTableMode = foreignTableMode;\n    }\n\n    public enum ForeignTableMode {\n        WRITE_ONLY, READ_ONLY, READ_WRITE\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/ast/stmt/GaussDbInsertStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class GaussDbInsertStatement extends PGInsertStatement {\n    private boolean isIgnore;\n    private final List<SQLExpr> duplicateKeyUpdate = new ArrayList<SQLExpr>();\n\n    public void setIgnore(boolean ignore) {\n        isIgnore = ignore;\n    }\n\n    public boolean isIgnore() {\n        return isIgnore;\n    }\n\n    public List<SQLExpr> getDuplicateKeyUpdate() {\n        return duplicateKeyUpdate;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/parser/GaussDbCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.GaussDbDistributeBy;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.stmt.GaussDbCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGCreateTableParser;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class GaussDbCreateTableParser extends PGCreateTableParser {\n    public GaussDbCreateTableParser(String sql) {\n        super(new GaussDbExprParser(sql));\n    }\n\n    protected SQLCreateTableStatement newCreateStatement() {\n        return new GaussDbCreateTableStatement();\n    }\n\n    @Override\n    public GaussDbExprParser getExprParser() {\n        return (GaussDbExprParser) exprParser;\n    }\n\n    public GaussDbCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.gaussdb;\n    }\n\n    protected void createTableBodyItem(SQLCreateTableStatement createTable) {\n        if (lexer.token() == Token.PARTIAL) {\n            lexer.nextToken();\n            if (lexer.nextIfIdentifier(FnvHash.Constants.CLUSTER)) {\n                accept(Token.KEY);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                    createTable.addClusteredByItem(item);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else if (lexer.token() == Token.RPAREN) {\n                        accept(Token.RPAREN);\n                        break;\n                    }\n                }}\n        } else {\n            super.createTableBodyItem(createTable);\n        }\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        GaussDbCreateTableStatement gdStmt = (GaussDbCreateTableStatement) stmt;\n        if (lexer.identifierEquals(FnvHash.Constants.SERVER)) {\n            acceptIdentifier(FnvHash.Constants.SERVER);\n            gdStmt.setServer(exprParser.expr());\n            acceptIdentifier(FnvHash.Constants.OPTIONS);\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, false);\n            accept(Token.RPAREN);\n            if (lexer.nextIfIdentifier(\"write\")) {\n                accept(Token.ONLY);\n                gdStmt.setForeignTableMode(GaussDbCreateTableStatement.ForeignTableMode.WRITE_ONLY);\n            } else if (lexer.identifierEquals(\"read\")) {\n                if (lexer.nextIf(Token.ONLY)) {\n                    gdStmt.setForeignTableMode(GaussDbCreateTableStatement.ForeignTableMode.READ_ONLY);\n                } else if (lexer.identifierEquals(\"write\")) {\n                    gdStmt.setForeignTableMode(GaussDbCreateTableStatement.ForeignTableMode.READ_WRITE);\n                }\n            }\n        }\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            parseAssignItems(gdStmt.getTableOptions(), gdStmt, false);\n            accept(Token.RPAREN);\n        }\n        if (lexer.nextIf(Token.ON)) {\n            if (lexer.nextIfIdentifier(FnvHash.Constants.COMMIT)) {\n                if (lexer.identifierEquals(\"PRESERVE\") || lexer.token() == Token.DELETE) {\n                    gdStmt.setOnCommitExpr(exprParser.name());\n                    accept(Token.ROWS);\n                }\n            }\n        }\n        if (lexer.identifierEquals(\"COMPRESS\") || lexer.identifierEquals(\"NOCOMPRESS\")) {\n            gdStmt.setCompressType(exprParser.name());\n        }\n        GaussDbDistributeBy distributeByClause = parseDistributeBy();\n        if (distributeByClause != null) {\n            gdStmt.setDistributeBy(distributeByClause);\n        }\n\n        if (lexer.nextIf(Token.TO)) {\n            if (lexer.nextIf(Token.GROUP)) {\n                SQLExpr group = this.exprParser.expr();\n                gdStmt.setToGroup(group);\n            }\n            if (lexer.nextIfIdentifier(FnvHash.Constants.NODE)) {\n                SQLExpr node = this.exprParser.expr();\n                gdStmt.setToNode(node);\n            }\n        }\n\n        SQLPartitionBy partitionClause = parsePartitionBy();\n        if (partitionClause != null) {\n            gdStmt.setPartitionBy(partitionClause);\n        }\n\n        parseRowMovement(gdStmt);\n\n        if (lexer.nextIf(Token.COMMENT)) {\n            lexer.nextIf(Token.EQ);\n            SQLExpr comment = this.exprParser.expr();\n            gdStmt.setComment(comment);\n        }\n    }\n    public void parseRowMovement(GaussDbCreateTableStatement stmt) {\n        if (lexer.token() == Token.ENABLE || lexer.token() == Token.DISABLE) {\n            stmt.setRowMovementType(exprParser.name());\n            accept(Token.ROW);\n            acceptIdentifier(\"MOVEMENT\");\n        }\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        if (lexer.nextIf(Token.PARTITION)) {\n            accept(Token.BY);\n            if (lexer.nextIfIdentifier(FnvHash.Constants.HASH)) {\n                SQLPartitionBy hashPartition = new SQLPartitionByHash();\n                if (lexer.nextIf(Token.LPAREN)) {\n                    if (lexer.token() != Token.IDENTIFIER) {\n                        throw new ParserException(\"expect identifier. \" + lexer.info());\n                    }\n                    for (; ; ) {\n                        hashPartition.addColumn(this.exprParser.name());\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    return hashPartition;\n                }\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.RANGE)) {\n                return partitionByRange();\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.LIST)) {\n                return partitionByList();\n            }\n        }\n        return null;\n    }\n\n    protected SQLPartitionByRange partitionByRange() {\n        SQLPartitionByRange rangePartition = new SQLPartitionByRange();\n        accept(Token.LPAREN);\n        for (; ; ) {\n            rangePartition.addColumn(this.exprParser.name());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        accept(Token.LPAREN);\n        for (; ; ) {\n            rangePartition.addPartition(this.getExprParser().parsePartition());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        return rangePartition;\n    }\n\n    private SQLPartitionByList partitionByList() {\n        SQLPartitionByList listPartition = new SQLPartitionByList();\n        accept(Token.LPAREN);\n        for (; ; ) {\n            listPartition.addColumn(this.exprParser.name());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        accept(Token.LPAREN);\n        for (; ; ) {\n            if (lexer.token() == Token.PARTITION) {\n                listPartition.addPartition(this.getExprParser().parsePartition());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        return listPartition;\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        parseTableType(createTable);\n        parseTableType(createTable);\n    }\n\n    private void parseTableType(SQLCreateTableStatement createTable) {\n        if (lexer.nextIfIdentifier(\"UNLOGGED\")) {\n            createTable.config(SQLCreateTableStatement.Feature.Unlogged);\n        } else if (lexer.nextIfIdentifier(FnvHash.Constants.GLOBAL)) {\n            createTable.config(SQLCreateTableStatement.Feature.Global);\n        } else if (lexer.nextIfIdentifier(FnvHash.Constants.TEMPORARY) || lexer.nextIfIdentifier(\"TEMP\")) {\n            createTable.config(SQLCreateTableStatement.Feature.Temporary);\n        } else if (lexer.nextIf(Token.LOCAL)) {\n            createTable.config(SQLCreateTableStatement.Feature.Local);\n        } else if (lexer.nextIf(Token.FOREIGN)) {\n            createTable.config(SQLCreateTableStatement.Feature.External);\n        }\n    }\n\n    public GaussDbDistributeBy parseDistributeBy() {\n        if (lexer.token() == Token.DISTRIBUTE) {\n            lexer.nextToken();\n            accept(Token.BY);\n            GaussDbDistributeBy distributeBy = new GaussDbDistributeBy();\n            if (lexer.identifierEquals(FnvHash.Constants.HASH)) {\n                distributeBy.setType(this.exprParser.name());\n                if (lexer.nextIf(Token.LPAREN)) {\n                    for (; ; ) {\n                        distributeBy.addColumn(this.exprParser.name());\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    return distributeBy;\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.ROUNDROBIN)) {\n                distributeBy.setType(this.exprParser.name());\n                return distributeBy;\n            } else if (lexer.identifierEquals(FnvHash.Constants.REPLICATION)) {\n                distributeBy.setType(this.exprParser.name());\n                return distributeBy;\n            }\n        }\n        return null;\n    }\n\n    public GaussDbDistributeBy distributionByContent(GaussDbDistributeBy distributeBy) {\n        accept(Token.LPAREN);\n        for (; ; ) {\n            distributeBy.addColumn(this.exprParser.name());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        accept(Token.LPAREN);\n        for (; ; ) {\n            distributeBy.addDistribution(this.getExprParser().parseDistribution());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        return distributeBy;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/parser/GaussDbExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.GaussDbPartitionValue;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\nimport static com.alibaba.druid.util.FnvHash.fnv1a_64_lower;\n\npublic class GaussDbExprParser extends PGExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"SUM\", \"MAX\", \"MIN\", \"AVG\", \"MEDIAN\", \"PERCENTILE_CONT\", \"PERCENTILE_DISC\", \"COUNT\", \"ARRAY_AGG\",\n                \"STRING_AGG\", \"LIST_AGG\", \"GROUP_CONCAT\", \"COVAR_POP\", \"COVAR_SAMP\", \"STDDEV_POP\", \"STDDEV_SAMP\",\n                \"VAR_POP\", \"VAR_SAMP\", \"BIT_AND\", \"BIT_OR\", \"BOOL_AND\", \"BOOL_OR\", \"CORR\", \"EVERY\", \"RANK\", \"REGR_AVGX\",\n                \"REGR_AVGY\", \"REGR_COUNT\", \"REGR_INTERCEPT\", \"REGR_R2\", \"REGR_SLOPE\", \"REGR_SXX\", \"REGR_SXY\", \"REGR_SYY\",\n                \"STDDEV\", \"VARIANCE\", \"CHECKSUM\"\n        };\n        AGGREGATE_FUNCTIONS_CODES = fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public GaussDbExprParser(String sql, SQLParserFeature... features) {\n        this(new GaussDbLexer(sql, features));\n        this.lexer.nextToken();\n        dbType = DbType.gaussdb;\n    }\n\n    public GaussDbExprParser(GaussDbLexer lexer) {\n        super(lexer);\n        this.dbType = DbType.gaussdb;\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public SQLPartitionSingle parsePartition() {\n        accept(Token.PARTITION);\n        SQLPartitionSingle partitionDef = new SQLPartitionSingle();\n        SQLName name = this.name();\n        partitionDef.setName(name);\n        partitionDef.setValues(this.parsePartitionValues(false));\n        return partitionDef;\n    }\n\n    public SQLPartitionSingle parseDistribution() {\n        acceptIdentifier(\"SLICE\");\n        SQLPartitionSingle partitionDef = new SQLPartitionSingle();\n        SQLName name = this.name();\n        partitionDef.setName(name);\n        partitionDef.setValues(this.parsePartitionValues(true));\n        return partitionDef;\n    }\n\n    public SQLPartitionValue parsePartitionValues(boolean isDistribute) {\n        GaussDbPartitionValue values = null;\n        boolean isInterval = false;\n        if (lexer.token() == Token.VALUES) {\n            lexer.nextToken();\n            if (lexer.token() == Token.IN) {\n                lexer.nextToken();\n                values = new GaussDbPartitionValue(SQLPartitionValue.Operator.In);\n                accept(Token.LPAREN);\n                this.exprList(values.getItems(), values);\n                accept(Token.RPAREN);\n            } else if (lexer.identifierEquals(FnvHash.Constants.LESS)) {\n                lexer.nextToken();\n                acceptIdentifier(\"THAN\");\n                values = new GaussDbPartitionValue(SQLPartitionValue.Operator.LessThan);\n                if (lexer.identifierEquals(FnvHash.Constants.MAXVALUE)) {\n                    SQLIdentifierExpr maxValue = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                    maxValue.setParent(values);\n                    values.addItem(maxValue);\n                } else {\n                    //添加dataNode信息\n                    //   PARTITION p1 VALUES LESS THAN (200) TABLESPACE tbs_test_range1_p1\n                    accept(Token.LPAREN);\n                    this.exprList(values.getItems(), values);\n                    accept(Token.RPAREN);\n                }\n            } else if (lexer.token() == Token.LPAREN) {\n                values = new GaussDbPartitionValue(SQLPartitionValue.Operator.List);\n                lexer.nextToken();\n                this.exprList(values.getItems(), values);\n                accept(Token.RPAREN);\n                if (lexer.token() == Token.TABLESPACE) {\n                    lexer.nextToken();\n                    values.setSpaceName(this.expr());\n                } else if (lexer.identifierEquals(FnvHash.Constants.DATANODE)) {\n                    lexer.nextToken();\n                    values.setDataNodes(this.expr());\n                }\n            }\n        } else if (lexer.token() == Token.START) {\n            lexer.nextToken();\n            values = new GaussDbPartitionValue(SQLPartitionValue.Operator.StartEndEvery);\n            isInterval = true;\n            values.setStart(this.expr());\n        }\n        if (lexer.token() == Token.END) {\n            lexer.nextToken();\n            if (!isInterval) {\n                values = new GaussDbPartitionValue(SQLPartitionValue.Operator.StartEndEvery);\n            }\n            values.setEnd(this.expr());\n            if (lexer.identifierEquals(FnvHash.Constants.EVERY)) {\n                lexer.nextToken();\n                if (!isInterval) {\n                    values = new GaussDbPartitionValue(SQLPartitionValue.Operator.StartEndEvery);\n                }\n                values.setEvery(this.expr());\n            }\n        }\n        if (lexer.token() == Token.TABLESPACE) {\n            lexer.nextToken();\n            values.setSpaceName(this.expr());\n        } else if (lexer.identifierEquals(FnvHash.Constants.DATANODE)) {\n            lexer.nextToken();\n            values.setDataNodes(this.expr());\n        }\n        if (values != null) {\n            values.setDistribute(isDistribute);\n        }\n        return values;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.nextIfIdentifier(FnvHash.Constants.COMPRESS_MODE)) {\n            column.setCompression(this.expr());\n            return parseColumnRest(column);\n        }\n        if (lexer.nextIfIdentifier(FnvHash.Constants.COLLATE)) {\n            column.setCollateExpr(this.expr());\n            return parseColumnRest(column);\n        }\n\n        return super.parseColumnRest(column);\n    }\n\n    protected SQLAggregateExpr parseAggregateExprRest(SQLAggregateExpr aggregateExpr) {\n        if (lexer.token() == Token.ORDER) {\n            SQLOrderBy orderBy = this.parseOrderBy();\n            aggregateExpr.setOrderBy(orderBy);\n            //为了兼容之前的逻辑\n            aggregateExpr.putAttribute(\"ORDER BY\", orderBy);\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.SEPARATOR)) {\n            lexer.nextToken();\n\n            SQLExpr seperator = this.primary();\n            seperator.setParent(aggregateExpr);\n\n            aggregateExpr.putAttribute(\"SEPARATOR\", seperator);\n        }\n        return aggregateExpr;\n    }\n\n    @Override\n    protected SQLExpr parseInterval() {\n        accept(Token.INTERVAL);\n        SQLIntervalExpr intervalExpr = new SQLIntervalExpr();\n        if (lexer.token() != Token.LITERAL_CHARS\n                && lexer.token() != Token.LITERAL_INT\n                && lexer.token() != Token.VARIANT\n        ) {\n            return new SQLIdentifierExpr(\"INTERVAL\");\n        }\n        SQLExpr value = new SQLCharExpr(lexer.stringVal());\n        lexer.nextToken();\n        String literal = ((SQLCharExpr) value).getText();\n        String[] split = literal.split(\" \");\n        if (split.length == 2) {\n            return new SQLIntervalExpr(new SQLIntegerExpr(Integer.parseInt(split[0])), SQLIntervalUnit.of(split[1]));\n        } else {\n            if (lexer.identifierEquals(FnvHash.Constants.DAY)) {\n                lexer.nextToken();\n                intervalExpr.setUnit(SQLIntervalUnit.DAY);\n            } else if (lexer.identifierEquals(FnvHash.Constants.MONTH)) {\n                lexer.nextToken();\n                intervalExpr.setUnit(SQLIntervalUnit.MONTH);\n            } else if (lexer.identifierEquals(FnvHash.Constants.YEAR)) {\n                lexer.nextToken();\n                intervalExpr.setUnit(SQLIntervalUnit.YEAR);\n            } else if (lexer.identifierEquals(FnvHash.Constants.HOUR)) {\n                lexer.nextToken();\n                intervalExpr.setUnit(SQLIntervalUnit.HOUR);\n            } else if (lexer.identifierEquals(FnvHash.Constants.MINUTE)) {\n                lexer.nextToken();\n                intervalExpr.setUnit(SQLIntervalUnit.MINUTE);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n                lexer.nextToken();\n                intervalExpr.setUnit(SQLIntervalUnit.SECOND);\n            }\n            intervalExpr.setValue(value);\n            return intervalExpr;\n        }\n    }\n\n    @Override\n    protected String nameCommon() {\n        String identName = lexer.stringVal();\n        lexer.nextToken();\n        return identName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/parser/GaussDbLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGLexer;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class GaussDbLexer extends PGLexer {\n    static final Keywords GAUSSDB_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n        map.put(\"DISTRIBUTE\", Token.DISTRIBUTE);\n        map.put(\"SET\", Token.SET);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"START\", Token.START);\n        map.put(\"PARTIAL\", Token.PARTIAL);\n        map.put(\"KEY\", Token.KEY);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n        map.put(\"LOCAL\", Token.LOCAL);\n        map.putAll(PGLexer.PG_KEYWORDS.getKeywords());\n        map.remove(\"LANGUAGE\"); // GaussDB does not consider it as a reserved keyword\n        GAUSSDB_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return GAUSSDB_KEYWORDS;\n    }\n\n    public GaussDbLexer(String input, SQLParserFeature... features) {\n        super(input);\n        dbType = DbType.gaussdb;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/parser/GaussDbStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLListExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.stmt.GaussDbInsertStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;\nimport com.alibaba.druid.sql.parser.EOFParserException;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class GaussDbStatementParser extends PGSQLStatementParser {\n    public GaussDbStatementParser(String sql) {\n        super(new GaussDbExprParser(sql));\n    }\n\n    public GaussDbStatementParser(String sql, SQLParserFeature... features) {\n        super(new GaussDbExprParser(sql, features));\n    }\n\n    public GaussDbCreateTableParser getSQLCreateTableParser() {\n        return new GaussDbCreateTableParser(this.exprParser);\n    }\n\n    @Override\n    public SQLCreateTableStatement parseCreateTable() {\n        return getSQLCreateTableParser().parseCreateTable();\n    }\n\n    @Override\n    public PGInsertStatement parseInsert() {\n        GaussDbInsertStatement stmt = new GaussDbInsertStatement();\n\n        if (lexer.token() == Token.INSERT) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"IGNORE\")) {\n                lexer.nextToken();\n                stmt.setIgnore(true);\n            } else if (lexer.token() == Token.OVERWRITE) {\n                lexer.nextToken();\n                stmt.setOverwrite(true);\n            }\n            accept(Token.INTO);\n\n            stmt.setTableSource(this.exprParser.name());\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.token() == Token.IDENTIFIER) {\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            }\n\n        }\n\n        if (lexer.nextIf(Token.LPAREN)) {\n            this.exprParser.exprList(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.nextIf(Token.DEFAULT)) {\n            accept(Token.VALUES);\n            stmt.setDefaultValues(true);\n        }\n\n        if (lexer.nextIf(Token.VALUES)) {\n            for (; ; ) {\n                accept(Token.LPAREN);\n                SQLInsertStatement.ValuesClause valuesCaluse = new SQLInsertStatement.ValuesClause();\n                this.exprParser.exprList(valuesCaluse.getValues(), valuesCaluse);\n                stmt.addValueCause(valuesCaluse);\n\n                accept(Token.RPAREN);\n                if (lexer.nextIf(Token.COMMA)) {\n                    continue;\n                }\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.WITH) {\n            PGSelectStatement nextWithQuery = (PGSelectStatement) this.parseWith();\n            stmt.setQuery(nextWithQuery.getSelect());\n        } else if (lexer.token() == Token.SELECT) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n            stmt.setQuery(queryExpr.getSubQuery());\n        }\n\n        if (lexer.token() == (Token.SELECT)) {\n            SQLSelect select = this.createSQLSelectParser().select();\n            stmt.setQuery(select);\n        }\n\n        if (lexer.nextIf(Token.ON)) {\n            if (lexer.identifierEquals(FnvHash.Constants.CONFLICT)) {\n                lexer.nextToken();\n\n                if (lexer.nextIf(Token.LPAREN)) {\n                    List<SQLExpr> onConflictTarget = new ArrayList<SQLExpr>();\n                    this.exprParser.exprList(onConflictTarget, stmt);\n                    stmt.setOnConflictTarget(onConflictTarget);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.nextIf(Token.ON)) {\n                    accept(Token.CONSTRAINT);\n                    SQLName constraintName = this.exprParser.name();\n                    stmt.setOnConflictConstraint(constraintName);\n                }\n\n                if (lexer.nextIf(Token.WHERE)) {\n                    SQLExpr where = this.exprParser.expr();\n                    stmt.setOnConflictWhere(where);\n                }\n\n                if (lexer.nextIf(Token.DO)) {\n                    if (lexer.identifierEquals(FnvHash.Constants.NOTHING)) {\n                        lexer.nextToken();\n                        stmt.setOnConflictDoNothing(true);\n                    } else {\n                        accept(Token.UPDATE);\n                        accept(Token.SET);\n\n                        for (; ; ) {\n                            SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n                            stmt.addConflicUpdateItem(item);\n\n                            if (lexer.token() != Token.COMMA) {\n                                break;\n                            }\n\n                            lexer.nextToken();\n                        }\n                        if (lexer.nextIf(Token.WHERE)) {\n                            SQLExpr where = this.exprParser.expr();\n                            stmt.setOnConflictUpdateWhere(where);\n                        }\n                    }\n                }\n            } else if (lexer.identifierEquals(\"DUPLICATE\")) {\n                lexer.nextToken();\n                accept(Token.KEY);\n                accept(Token.UPDATE);\n\n                List<SQLExpr> duplicateKeyUpdate = stmt.getDuplicateKeyUpdate();\n                for (; ; ) {\n                    SQLName name = this.exprParser.name();\n                    accept(Token.EQ);\n                    SQLExpr value;\n                    try {\n                        value = this.exprParser.expr();\n                    } catch (EOFParserException e) {\n                        throw new ParserException(\"EOF, \" + name + \"=\", e);\n                    }\n\n                    SQLBinaryOpExpr assignment = new SQLBinaryOpExpr(name, SQLBinaryOperator.Equality, value);\n                    assignment.setParent(stmt);\n                    duplicateKeyUpdate.add(assignment);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextTokenIdent();\n                        continue;\n                    }\n                    break;\n                }\n            }\n        }\n\n        if (lexer.nextIf(Token.RETURNING)) {\n            SQLExpr returning = this.exprParser.expr();\n\n            if (lexer.nextIf(Token.COMMA)) {\n                SQLListExpr list = new SQLListExpr();\n                list.addItem(returning);\n\n                this.exprParser.exprList(list.getItems(), list);\n\n                returning = list;\n            }\n\n            stmt.setReturning(returning);\n        }\n        return stmt;\n    }\n\n    protected void createOptionSkip() {\n        lexer.nextIf(Token.LOCAL);\n        lexer.nextIfIdentifier(\"UNLOGGED\");\n        super.createOptionSkip();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/visitor/GaussDbASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.visitor;\n\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.GaussDbDistributeBy;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.stmt.GaussDbCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.stmt.GaussDbInsertStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\npublic interface GaussDbASTVisitor extends PGASTVisitor {\n    default boolean visit(GaussDbCreateTableStatement x) {\n        return true;\n    }\n    default void endVisit(GaussDbCreateTableStatement x) {\n    }\n    default boolean visit(GaussDbDistributeBy x) {\n        return true;\n    }\n    default void endVisit(GaussDbDistributeBy x) {\n    }\n\n    default boolean visit(GaussDbInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(GaussDbInsertStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/gaussdb/visitor/GaussDbOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.gaussdb.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;\nimport com.alibaba.druid.sql.dialect.gaussdb.GaussDb;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.GaussDbDistributeBy;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.GaussDbPartitionValue;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.stmt.GaussDbCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.gaussdb.ast.stmt.GaussDbInsertStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGVacuumStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\npublic class GaussDbOutputVisitor extends PGOutputVisitor implements GaussDbASTVisitor {\n    public GaussDbOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.gaussdb, GaussDb.DIALECT, parameterized);\n    }\n\n    public GaussDbOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.gaussdb, GaussDb.DIALECT);\n    }\n\n    @Override\n    public boolean visit(GaussDbCreateTableStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        printCreateTableFeatures(x);\n\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printTableSourceExpr(\n                x.getTableSource()\n                        .getExpr());\n\n        printCreateTableAfterName(x);\n\n        printTableElements(x);\n        printServer(x);\n\n        printCreateTableLike(x);\n\n        printTableOptions(x);\n\n        printForeignMode(x);\n\n        printOnCommit(x);\n\n        printCompressType(x);\n\n        printDistributeBy(x);\n\n        printToGroup(x);\n\n        printToNode(x);\n\n        printPartitionBy(x);\n\n        printRowMovement(x);\n\n        printComment(x.getComment());\n        return false;\n    }\n\n    public void printForeignMode(GaussDbCreateTableStatement x) {\n        if (x.getForeignTableMode() != null) {\n            switch (x.getForeignTableMode()) {\n                case WRITE_ONLY:\n                    print0(ucase ? \"WRITE ONLY\" : \"write only\");\n                    break;\n                case READ_ONLY:\n                    print0(ucase ? \"READ ONLY\" : \"read only\");\n                    break;\n                case READ_WRITE:\n                    print0(ucase ? \"READ WRITE\" : \"read write\");\n                    break;\n            }\n        }\n    }\n    public void printServer(GaussDbCreateTableStatement x) {\n        if (x.getServer() != null) {\n            println();\n            print0(ucase ? \"SERVER \" : \"server \");\n            x.getServer().accept(this);\n            println();\n        }\n    }\n    public void printRowMovement(GaussDbCreateTableStatement x) {\n        if (x.getRowMovementType() != null) {\n            println();\n            x.getRowMovementType().accept(this);\n            print(ucase ? \" ROW MOVEMENT\" : \" row movement\");\n        }\n    }\n\n    public void printCompressType(GaussDbCreateTableStatement x) {\n        if (x.getCompressType() != null) {\n            println();\n            x.getCompressType().accept(this);\n        }\n    }\n    public void printOnCommit(GaussDbCreateTableStatement x) {\n        if (x.getOnCommitExpr() != null) {\n            println();\n            print0(ucase ? \"ON COMMIT \" : \"on commit \");\n            x.getOnCommitExpr().accept(this);\n            print0(ucase ? \" ROWS\" : \" rows\");\n        }\n    }\n\n    public void printDistributeBy(GaussDbCreateTableStatement x) {\n        if (x.getDistributeBy() != null) {\n            x.getDistributeBy().accept(this);\n        }\n    }\n\n    public void printToGroup(GaussDbCreateTableStatement x) {\n        if (x.getToGroup() != null) {\n            println();\n            print0(ucase ? \"TO GROUP \" : \"to group \");\n            x.getToGroup().accept(this);\n        }\n    }\n\n    public void printToNode(GaussDbCreateTableStatement x) {\n        if (x.getToNode() != null) {\n            println();\n            print0(ucase ? \"TO NODE \" : \"to node \");\n            x.getToNode().accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByRange x) {\n        print0(ucase ? \"RANGE\" : \"range\");\n        printColumns(x.getColumns());\n        printPartitionsValue(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByList x) {\n        print0(ucase ? \"LIST\" : \"list\");\n        printColumns(x.getColumns());\n        printPartitionsValue(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        print0(ucase ? \"WITH (\" : \"with (\");\n        incrementIndent();\n        println();\n    }\n\n    protected void printTableElements(GaussDbCreateTableStatement x) {\n        int size = x.getTableElementList().size();\n        if (size == 0) {\n            return;\n        }\n\n        print0(\" (\");\n\n        this.indentCount++;\n        println();\n        for (int i = 0; i < size; ++i) {\n            printTableElement(x.getTableElementList(), i);\n        }\n        this.indentCount--;\n        if (!x.getClusteredBy().isEmpty()) {\n            print(',');\n            println();\n            print(\" \");\n            List<SQLExpr> clusterBy = x.getClusteredBy().stream().map(k -> k.getExpr()).collect(Collectors.toList());\n            print0(ucase ? \"  PARTIAL CLUSTER KEY \" : \"  partial cluster key\");\n            printColumns(clusterBy);\n\n        }\n        println();\n        print(')');\n    }\n\n    @Override\n    public boolean visit(SQLPartitionValue value) {\n        if (value instanceof GaussDbPartitionValue) {\n            GaussDbPartitionValue x = (GaussDbPartitionValue) value;\n            if (x.getOperator() == SQLPartitionValue.Operator.LessThan) {\n                print0(ucase ? \"VALUES LESS THAN\" : \"values less than\");\n                print0(\" (\");\n                if (x.getItems().size() == 1) {\n                    // for single specific value\n                    printExpr(x.getItems().get(0), parameterized);\n                } else {\n                    print(\"(\");\n                    printAndAccept(x.getItems(), \", \", false);\n                    print(')');\n                }\n                print(\")\");\n            } else if (x.getOperator() == SQLPartitionValue.Operator.StartEndEvery) {\n                if (x.getStart() != null) {\n                    print0(ucase ? \" START \" : \" start \");\n                    x.getStart().accept(this);\n                }\n                if (x.getEnd() != null) {\n                    print0(ucase ? \" END \" : \" end \");\n                    x.getEnd().accept(this);\n                }\n                if (x.getEvery() != null) {\n                    print0(ucase ? \" EVERY \" : \" every \");\n                    x.getEvery().accept(this);\n                }\n            } else if (x.getOperator() == SQLPartitionValue.Operator.List) {\n                print0(ucase ? \"VALUES \" : \"valuse \");\n                print0(\" (\");\n                if (x.getItems().size() == 1) {\n                    // for single specific value\n                    printExpr(x.getItems().get(0), parameterized);\n                } else {\n                    print(\"(\");\n                    printAndAccept(x.getItems(), \", \", false);\n                    print(')');\n                }\n                print0(\")\");\n            }\n            if (x.getSpaceName() != null) {\n                print0(ucase ? \" TABLESPACE \" : \" tablespace \");\n                x.getSpaceName().accept(this);\n            } else if (x.getDataNode() != null) {\n                print0(ucase ? \" DATANODE \" : \" datanode \");\n                x.getDataNode().accept(this);\n            }\n        } else {\n            super.visit(value);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionSingle x) {\n        GaussDbPartitionValue values = (GaussDbPartitionValue) x.getValues();\n        if (values.getDistribute()) {\n            print0(ucase ? \"SLICE \" : \"slice \");\n        } else {\n            print0(ucase ? \"PARTITION \" : \"partition \");\n        }\n        x.getName().accept(this);\n        print0(\" \");\n        values.accept(this);\n        return false;\n    }\n\n    public void printColumns(List<SQLExpr> columns) {\n        for (SQLExpr column : columns) {\n            if (!(column instanceof SQLName)) {\n                break;\n            }\n        }\n        if (columns.size() == 1) {\n            print0(\" (\");\n            columns.get(0).accept(this);\n            print(')');\n        } else {\n            print0(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n    }\n\n    @Override\n    public boolean visit(SQLColumnDefinition x) {\n        super.visit(x);\n        if (x.getOnUpdate() != null) {\n            print0(ucase ? \" ON UPDATE \" : \" on update \");\n            x.getOnUpdate().accept(this);\n        }\n        return false;\n    }\n\n    public void printPartitionsValue(List<SQLPartition> partitions) {\n        print(\" (\");\n        this.indentCount++;\n        for (int i = 0, size = partitions.size(); i < size; ++i) {\n            if (i != 0) {\n                print(',');\n            }\n            println();\n            SQLPartition sqlPartition = partitions.get(i);\n            sqlPartition.accept(this);\n        }\n        this.indentCount--;\n        println();\n        print(')');\n    }\n\n    @Override\n    public boolean visit(GaussDbDistributeBy x) {\n        println();\n        print0(ucase ? \"DISTRIBUTE BY \" : \"distribute by \");\n        x.getType().accept(this);\n        if (!x.getColumns().isEmpty()) {\n            printColumns(x.getColumns());\n        }\n        if (!x.getDistributions().isEmpty()) {\n            printPartitionsValue(x.getDistributions());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLInsertStatement x) {\n        if (x instanceof GaussDbInsertStatement) {\n            return visit((GaussDbInsertStatement) x);\n        }\n        return super.visit(x);\n    }\n\n    @Override\n    public boolean visit(PGInsertStatement x) {\n        if (x instanceof GaussDbInsertStatement) {\n            return visit((GaussDbInsertStatement) x);\n        }\n        return super.visit(x);\n    }\n\n    @Override\n    public boolean visit(GaussDbInsertStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.getInsertBeforeCommentsDirect() != null) {\n            printlnComments(x.getInsertBeforeCommentsDirect());\n        }\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n        print0(ucase ? \"INSERT \" : \"insert \");\n        if (x.isOverwrite()) {\n            print0(ucase ? \"OVERWRITE \" : \"overwrite \");\n        } else if (x.isIgnore()) {\n            print0(ucase ? \"IGNORE \" : \"ignore \");\n        }\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        String columnsString = x.getColumnsString();\n        if (columnsString != null) {\n            print0(columnsString);\n        } else {\n            printInsertColumns(x.getColumns());\n        }\n\n        if (x.isDefaultValues()) {\n            println();\n            print0(ucase ? \"DEFAULT VALUES\" : \"default values\");\n        }\n\n        printValuesOrQuery(x);\n\n        List<SQLExpr> duplicateKeyUpdate = x.getDuplicateKeyUpdate();\n        if (!duplicateKeyUpdate.isEmpty()) {\n            println();\n            print0(ucase ? \"ON DUPLICATE KEY UPDATE \" : \"on duplicate key update \");\n            for (int i = 0, size = duplicateKeyUpdate.size(); i < size; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        println();\n                    }\n                    print0(\", \");\n                }\n                duplicateKeyUpdate.get(i).accept(this);\n            }\n        }\n\n        printOnConflict(x);\n\n        printReturning(x);\n        return false;\n    }\n\n    protected void visitAggregateRest(SQLAggregateExpr x) {\n        super.visitAggregateRest(x);\n        Object value = x.getAttribute(\"SEPARATOR\");\n        if (value != null) {\n            print0(ucase ? \" SEPARATOR \" : \" separator \");\n            ((SQLObject) value).accept(this);\n        }\n    }\n\n    protected void printCompression(SQLColumnDefinition x) {\n        if (x.getCompression() != null) {\n            print0(ucase ? \" COMPRESS_MODE \" : \" compress_mode \");\n            x.getCompression().accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLIntervalExpr x) {\n        print0(ucase ? \"INTERVAL \" : \"interval \");\n        SQLExpr value = x.getValue();\n\n        boolean str = value instanceof SQLCharExpr;\n        if (!str) {\n            print('\\'');\n        }\n        value.accept(this);\n\n        SQLIntervalUnit unit = x.getUnit();\n        if (unit != null) {\n            print(' ');\n            print0(ucase ? unit.name : unit.nameLCase);\n            if (value instanceof SQLIntegerExpr) {\n                SQLIntegerExpr integerExpr = (SQLIntegerExpr) value;\n                if (integerExpr.getNumber().intValue() > 1) {\n                    print(ucase ? 'S' : 's');\n                }\n            }\n        }\n        if (!str) {\n            print('\\'');\n        }\n        return false;\n    }\n\n    @Override\n    protected void printVacuumRest(PGVacuumStatement x) {\n        if (x.isDeltaMerge()) {\n            print0(ucase ? \"DELTAMERGE \" : \"deltamerge \");\n        }\n        if (x.isHdfsDirectory()) {\n            print0(ucase ? \"HDFSDIRECTORY \" : \"hdfsdirectory \");\n        }\n    }\n\n    protected void printCreateTableFeatures(SQLCreateTableStatement x) {\n        if (x.isEnabled(SQLCreateTableStatement.Feature.OrReplace)) {\n            print0(ucase ? \"OR REPLACE \" : \"or replace \");\n        }\n        SQLCreateTableStatement.Feature[] features = {\n                SQLCreateTableStatement.Feature.Global,\n                SQLCreateTableStatement.Feature.Local,\n                SQLCreateTableStatement.Feature.Temporary,\n                SQLCreateTableStatement.Feature.Shadow,\n                SQLCreateTableStatement.Feature.External,\n                SQLCreateTableStatement.Feature.Transactional,\n                SQLCreateTableStatement.Feature.Dimension,\n                SQLCreateTableStatement.Feature.Unlogged\n        };\n\n        for (SQLCreateTableStatement.Feature feature : features) {\n            if (x.isEnabled(feature)) {\n                String name;\n                if (feature.equals(SQLCreateTableStatement.Feature.External)) {\n                    name = \"FOREIGN\";\n                } else {\n                    name = feature.name();\n                }\n                print0(ucase ? name.toUpperCase() : name.toLowerCase());\n                print(' ');\n            }\n        }\n    }\n\n    protected void printTableOptions(SQLCreateTableStatement x) {\n        List<SQLAssignItem> tblProperties = x.getTableOptions();\n        if (tblProperties.isEmpty()) {\n            return;\n        }\n        if (x.isEnabled(SQLCreateTableStatement.Feature.External)) {\n            print0(ucase ? \"OPTIONS (\" : \"options (\");\n            println();\n            indentCount++;\n            int i = 0;\n            for (SQLAssignItem property : tblProperties) {\n                if (i != 0) {\n                    print(\",\");\n                    println();\n                }\n                property.getTarget().accept(this);\n                print0(\" \");\n                property.getValue().accept(this);\n                i++;\n            }\n            indentCount--;\n            println();\n            print0(\")\");\n            println();\n        } else {\n            printTableOptionsPrefix(x);\n            int i = 0;\n            for (SQLAssignItem property : tblProperties) {\n                printTableOption(property.getTarget(), property.getValue(), i);\n                ++i;\n            }\n            printTableOptionsPostfix(x);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/H2.java",
    "content": "package com.alibaba.druid.sql.dialect.h2;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class H2 {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.h2);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2ExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.parser;\n\nimport com.alibaba.druid.sql.ast.expr.SQLDefaultExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class H2ExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\", \"ROW_NUMBER\",\n                \"ROWNUMBER\"};\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public H2ExprParser(String sql) {\n        this(new H2Lexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public H2ExprParser(String sql, SQLParserFeature... features) {\n        this(new H2Lexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public H2ExprParser(Lexer lexer) {\n        super(lexer);\n        dbType = lexer.getDbType();\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        column = super.parseColumnRest(column);\n\n        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.BY) {\n                lexer.nextToken();\n                accept(Token.DEFAULT);\n                column.setGeneratedAlwaysAs(new SQLDefaultExpr());\n            } else {\n                acceptIdentifier(\"ALWAYS\");\n                column.setGeneratedAlwaysAs(new SQLIdentifierExpr(\"ALWAYS\"));\n            }\n            accept(Token.AS);\n            acceptIdentifier(\"IDENTITY\");\n\n            SQLColumnDefinition.Identity identity = new SQLColumnDefinition.Identity();\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n\n                SQLIntegerExpr seed = (SQLIntegerExpr) this.primary();\n                accept(Token.COMMA);\n                SQLIntegerExpr increment = (SQLIntegerExpr) this.primary();\n                accept(Token.RPAREN);\n\n                identity.setSeed((Integer) seed.getNumber());\n                identity.setIncrement((Integer) increment.getNumber());\n            }\n            column.setIdentity(identity);\n        }\n\n        return column;\n    }\n\n    protected SQLColumnDefinition.Identity parseIdentity0() {\n        SQLColumnDefinition.Identity identity = new SQLColumnDefinition.Identity();\n\n        accept(Token.IDENTITY);\n        if (lexer.token() == Token.LPAREN) {\n            accept(Token.LPAREN);\n\n            if (lexer.identifierEquals(FnvHash.Constants.START)) {\n                lexer.nextToken();\n                accept(Token.WITH);\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setSeed((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.INCREMENT)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setIncrement((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.CYCLE)) {\n                lexer.nextToken();\n                identity.setCycle(true);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.MINVALUE)) {\n                lexer.nextTokenValue();\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setMinValue((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.MAXVALUE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setMaxValue((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        return identity;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2Lexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class H2Lexer extends Lexer {\n    static final Keywords H2_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"IF\", Token.IF);\n\n        H2_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return H2_KEYWORDS;\n    }\n\n    public H2Lexer(String input) {\n        super(input, null, DbType.h2);\n    }\n\n    public H2Lexer(String input, SQLParserFeature... features) {\n        super(input, null, DbType.h2);\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2SelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.parser;\n\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\n\npublic class H2SelectParser extends SQLSelectParser {\n    public H2SelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public H2SelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public H2SelectParser(String sql) {\n        this(new H2ExprParser(sql));\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new H2ExprParser(lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2StatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertInto;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLReplaceStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport static com.alibaba.druid.sql.parser.Token.LPAREN;\nimport static com.alibaba.druid.sql.parser.Token.RPAREN;\n\npublic class H2StatementParser extends SQLStatementParser {\n    public H2StatementParser(String sql) {\n        super(new H2ExprParser(sql));\n    }\n\n    public H2StatementParser(String sql, SQLParserFeature... features) {\n        super(new H2ExprParser(sql, features));\n    }\n\n    public H2StatementParser(Lexer lexer) {\n        super(new H2ExprParser(lexer));\n    }\n\n    public H2SelectParser createSQLSelectParser() {\n        return new H2SelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLStatement parseMerge() {\n        accept(Token.MERGE);\n        accept(Token.INTO);\n\n        SQLReplaceStatement stmt = new SQLReplaceStatement();\n        stmt.setDbType(DbType.h2);\n\n        SQLName tableName = exprParser.name();\n        stmt.setTableName(tableName);\n\n        if (lexer.token() == Token.KEY) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            this.exprParser.exprList(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.VALUES || lexer.identifierEquals(\"VALUE\")) {\n            lexer.nextToken();\n\n            parseValueClause(stmt.getValuesList(), null, 0, stmt);\n        } else if (lexer.token() == Token.SELECT) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n            stmt.setQuery(queryExpr);\n        } else if (lexer.token() == Token.LPAREN) {\n            SQLSelect select = this.createSQLSelectParser().select();\n            SQLQueryExpr queryExpr = new SQLQueryExpr(select);\n            stmt.setQuery(queryExpr);\n        }\n\n        return stmt;\n    }\n\n    @Override\n    protected void parseInsert0(SQLInsertInto insertStatement, boolean acceptSubQuery) {\n        super.parseInsert0(insertStatement, acceptSubQuery);\n        parseSetStatement(insertStatement);\n    }\n\n    private void parseSetStatement(SQLInsertInto insertStatement) {\n        if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n            SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n            insertStatement.addValueCause(values);\n\n            for (; ; ) {\n                SQLName name = this.exprParser.name();\n                insertStatement.addColumn(name);\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                } else {\n                    accept(Token.COLONEQ);\n                }\n                values.addValue(this.exprParser.expr());\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n    }\n\n    @Override\n    protected void alterTableAddRestSpecific(SQLAlterTableStatement stmt) {\n        if (lexer.token() == LPAREN) {\n            lexer.nextToken();\n            SQLAlterTableAddColumn item = parseAlterTableAddColumn();\n            stmt.addItem(item);\n            accept(RPAREN);\n            return;\n        }\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2ASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface H2ASTVisitor extends SQLASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2ASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class H2ASTVisitorAdapter extends SQLASTVisitorAdapter implements H2ASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2EvalVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class H2EvalVisitor extends H2ASTVisitorAdapter implements SQLEvalVisitor {\n    private Map<String, Function> functions = new HashMap<String, Function>();\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public H2EvalVisitor() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public H2EvalVisitor(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLUnaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2OutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLHexExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.h2.H2;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.List;\n\npublic class H2OutputVisitor extends SQLASTOutputVisitor implements H2ASTVisitor {\n    private static final Log LOG = LogFactory.getLog(H2OutputVisitor.class);\n\n    public H2OutputVisitor(StringBuilder appender) {\n    super(appender, DbType.h2, H2.DIALECT);\n    }\n\n    public H2OutputVisitor(StringBuilder appender, DbType dbType) {\n        super(appender, dbType);\n    }\n\n    public H2OutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.h2, parameterized);\n    }\n\n    public boolean visit(SQLReplaceStatement x) {\n        print0(ucase ? \"MERGE INTO \" : \"merge into \");\n\n        printTableSourceExpr(x.getTableName());\n\n        List<SQLExpr> columns = x.getColumns();\n        if (columns.size() > 0) {\n            print0(ucase ? \" KEY (\" : \" key (\");\n            for (int i = 0, size = columns.size(); i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n\n                SQLExpr columnn = columns.get(i);\n                printExpr(columnn, parameterized);\n            }\n            print(')');\n        }\n\n        List<SQLInsertStatement.ValuesClause> valuesClauseList = x.getValuesList();\n        if (!valuesClauseList.isEmpty()) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            int size = valuesClauseList.size();\n            if (size == 0) {\n                print0(\"()\");\n            } else {\n                for (int i = 0; i < size; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                    }\n                    visit(valuesClauseList.get(i));\n                }\n            }\n        }\n\n        SQLQueryExpr query = x.getQuery();\n        if (query != null) {\n            visit(query);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateDatabaseStatement x) {\n        /*\n        https://h2database.com/html/commands.html#create_schema\n        CREATE SCHEMA [ IF NOT EXISTS ]\n        { name [ AUTHORIZATION ownerName ] | [ AUTHORIZATION ownerName ] }\n        [ WITH tableEngineParamName [,...] ]\n         */\n\n        printUcase(\"CREATE SCHEMA \");\n\n        if (x.isIfNotExists()) {\n            printUcase(\"IF NOT EXISTS \");\n        }\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        /*\n        https://h2database.com/html/commands.html#create_table\n        CREATE [ CACHED | MEMORY ] [ { TEMP } | [ GLOBAL | LOCAL ] TEMPORARY ]\n        TABLE [ IF NOT EXISTS ] [schemaName.]tableName\n        [ ( { columnName [columnDefinition] | tableConstraintDefinition } [,...] ) ]\n        [ ENGINE tableEngineName ]\n        [ WITH tableEngineParamName [,...] ]\n        [ NOT PERSISTENT ] [ TRANSACTIONAL ]\n        [ AS query [ WITH [ NO ] DATA ] ]\n         */\n\n        printCreateTable(x, true);\n        return false;\n    }\n\n    protected void printTableElements(List<SQLTableElement> tableElementList) {\n        int size = tableElementList.size();\n        if (size == 0) {\n            return;\n        }\n\n        print0(\" (\");\n\n        this.indentCount++;\n        println();\n        for (int i = 0; i < size; ++i) {\n            SQLTableElement element = tableElementList.get(i);\n            if (element instanceof SQLPrimaryKey) {\n                SQLName name = ((SQLPrimaryKey) element).getName();\n                if (name != null) {\n                    printUcase(\"CONSTRAINT \");\n                    name.accept(this);\n                    print(' ');\n                }\n                printUcase(\"PRIMARY KEY \");\n                acceptChildName(((SQLPrimaryKey) element).getColumns());\n            } else if (element instanceof SQLUnique) {\n                if (\"UNIQUE\".equalsIgnoreCase(((SQLUnique) element).getIndexDefinition().getType())) {\n                    printUcase(\"UNIQUE \");\n                }\n                printUcase(\"KEY \");\n                print(addIndexNameSuffixForH2(((SQLUnique) element).getName()));\n                acceptChildName(((SQLUnique) element).getColumns());\n            } else if (element instanceof MySqlTableIndex) {\n                visit((MySqlTableIndex) element);\n            } else {\n                element.accept(this);\n            }\n\n            if (i != size - 1) {\n                print(',');\n            }\n            if (this.isPrettyFormat() && element.hasAfterComment()) {\n                print(' ');\n                printlnComment(element.getAfterCommentsDirect());\n            }\n\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        print(')');\n    }\n\n    private String addIndexNameSuffixForH2(SQLName name) {\n        String simpleName = name.getSimpleName();\n        if (simpleName.endsWith(\"`\")) {\n            return simpleName.replaceFirst(\"`$\", System.nanoTime() + \"`\");\n        } else {\n            return simpleName + System.nanoTime();\n        }\n    }\n\n    public boolean visit(MySqlTableIndex x) {\n        print0(ucase ? \"INDEX\" : \"index\");\n        if (x.getName() != null) {\n            print(' ');\n            x.getName().accept(this);\n        }\n\n        print('(');\n        for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            x.getColumns().get(i).accept(this);\n        }\n        print(')');\n\n        return false;\n    }\n\n    private void acceptChildName(List<SQLSelectOrderByItem> children) {\n        if (children == null) {\n            return;\n        }\n\n        print('(');\n        for (int i = 0; i < children.size(); i++) {\n            SQLSelectOrderByItem child = children.get(i);\n            if (child == null) {\n                continue;\n            }\n            if (child.getExpr() instanceof SQLMethodInvokeExpr) {\n                print0(((SQLMethodInvokeExpr) child.getExpr()).getMethodName());\n            } else {\n                print0(child.getExpr().toString());\n            }\n            if (i != children.size() - 1) {\n                print(',');\n            }\n        }\n        print(')');\n    }\n\n    @Override\n    public boolean visit(SQLCreateIndexStatement x) {\n        /* h2 CREATE INDEX BNF: https://h2database.com/html/commands.html#create_index\n        CREATE [ UNIQUE | SPATIAL ] INDEX\n        [ [ IF NOT EXISTS ] [schemaName.]indexName ]\n        ON [schemaName.]tableName ( indexColumn [,...] )\n        [ INCLUDE ( indexColumn [,...] ) ]\n         */\n\n        printUcase(\"CREATE \");\n\n        String type = x.getType();\n        if (\"UNIQUE\".equalsIgnoreCase(type) || \"SPATIAL\".equalsIgnoreCase(type)) {\n            printUcase(type + ' ');\n        }\n\n        printUcase(\"INDEX \");\n\n        if (x.isIfNotExists()) {\n            printUcase(\"IF NOT EXISTS \");\n        }\n\n        x.getName().accept(this);\n\n        printUcase(\" ON \");\n        x.getTable().accept(this);\n        print0(\" (\");\n        printAndAccept(x.getItems(), \", \");\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSetStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLHexExpr x) {\n        print0(\"X'\");\n        print0(x.getHex());\n        print0(\"'\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBinaryExpr x) {\n        print0(x.getText());\n        return false;\n    }\n\n    @Override\n    protected void printChars(String text) {\n        if (\"0000-00-00 00:00:00\".equals(text)) {\n            // TODO: this is not correct because '0000-00-00 00:00:00' could be a real string value\n            LOG.warn(\"Replacing '0000-00-00 00:00:00' with valid H2 datetime (unsafe replacement)\");\n            text = \"0001-01-01 00:00:00\";\n        }\n        super.printChars(text);\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableStatement x) {\n        /*\n        https://h2database.com/html/commands.html#alter_table_alter_column\n        ALTER TABLE [ IF EXISTS ] [schemaName.]tableName\n        ALTER COLUMN [ IF EXISTS ] columnName\n        { { columnDefinition }\n        | { RENAME TO name }\n        | SET GENERATED { ALWAYS | BY DEFAULT } [ alterIdentityColumnOption [...] ]\n        | alterIdentityColumnOption [...]\n        | DROP IDENTITY\n        | { SELECTIVITY int }\n        | { SET DEFAULT expression }\n        | { DROP DEFAULT }\n        | DROP EXPRESSION\n        | { SET ON UPDATE expression }\n        | { DROP ON UPDATE }\n        | { SET DEFAULT ON NULL }\n        | { DROP DEFAULT ON NULL }\n        | { SET NOT NULL }\n        | { DROP NOT NULL } | { SET NULL }\n        | { SET DATA TYPE dataTypeOrDomain [ USING newValueExpression ] }\n        | { SET { VISIBLE | INVISIBLE } } }\n         */\n\n        printAlterTable(x);\n        this.indentCount++;\n        for (int i = 0; i < x.getItems().size(); ++i) {\n            SQLAlterTableItem item = x.getItems().get(i);\n            println();\n            accept(item);\n            if (i + 1 < x.getItems().size()) {\n                SQLAlterTableItem later = x.getItems().get(i + 1);\n                if (later instanceof MySqlAlterTableModifyColumn) {\n                    print(\";\\n\");\n                    printAlterTable(x);\n                }\n            }\n        }\n        this.indentCount--;\n\n        return false;\n    }\n\n    private void printAlterTable(SQLAlterTableStatement x) {\n        printUcase(\"ALTER TABLE \");\n        if (x.isIfExists()) {\n            printUcase(\"IF EXISTS \");\n        }\n        printTableSourceExpr(x.getName());\n    }\n\n    private void accept(SQLAlterTableItem item) {\n        if (item instanceof MySqlAlterTableModifyColumn) {\n            MySqlAlterTableModifyColumn x = (MySqlAlterTableModifyColumn) item;\n            printUcase(\"ALTER COLUMN \");\n            x.getNewColumnDefinition().accept(this);\n        } else {\n            item.accept(this);\n        }\n    }\n\n    public boolean visit(SQLAlterTableAddConstraint x) {\n        if (x.isWithNoCheck()) {\n            this.print0(this.ucase ? \"WITH NOCHECK \" : \"with nocheck \");\n        }\n\n        this.print0(this.ucase ? \"ADD \" : \"add \");\n\n        if (x.getConstraint().getParent() instanceof SQLAlterTableAddConstraint && x.getConstraint() instanceof SQLForeignKeyImpl) {\n            this.visit((SQLForeignKeyImpl) x.getConstraint());\n        } else if (x.getConstraint().getParent() instanceof SQLAlterTableAddConstraint && x.getConstraint() instanceof SQLUnique) {\n            this.visit((SQLUnique) x.getConstraint());\n        } else {\n            x.getConstraint().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnique x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            this.print0(this.ucase ? \"CONSTRAINT \" : \"constraint \");\n            print(addIndexNameSuffixForH2(name));\n\n            this.print(' ');\n        }\n\n        this.print0(this.ucase ? \"UNIQUE (\" : \"unique (\");\n        this.printAndAccept(x.getColumns(), \", \");\n        this.print(')');\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2SchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.h2.visitor;\n\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\npublic class H2SchemaStatVisitor extends SchemaStatVisitor implements H2ASTVisitor {\n    public H2SchemaStatVisitor() {\n    }\n\n    public H2SchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/Hive.java",
    "content": "package com.alibaba.druid.sql.dialect.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Hive {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.hive);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveAddJarStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.hive.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class HiveAddJarStatement extends SQLStatementImpl {\n    public HiveAddJarStatement() {\n        this.dbType = DbType.hive;\n    }\n\n    private String path;\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof HiveASTVisitor) {\n            accept0((HiveASTVisitor) visitor);\n        }\n    }\n\n    protected void accept0(HiveASTVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveInputOutputFormat.java",
    "content": "package com.alibaba.druid.sql.dialect.hive.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class HiveInputOutputFormat extends SQLExprImpl {\n    private SQLExpr input;\n    private SQLExpr output;\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        HiveInputOutputFormat that = (HiveInputOutputFormat) o;\n\n        if (input != null ? !input.equals(that.input) : that.input != null) {\n            return false;\n        }\n        return output != null ? output.equals(that.output) : that.output == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = input != null ? input.hashCode() : 0;\n        result = 31 * result + (output != null ? output.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, input);\n            acceptChild(v, output);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public HiveInputOutputFormat clone() {\n        HiveInputOutputFormat x = new HiveInputOutputFormat();\n\n        if (input != null) {\n            x.setInput(input.clone());\n        }\n        if (output != null) {\n            x.setOutput(output.clone());\n        }\n\n        return x;\n    }\n\n    public SQLExpr getInput() {\n        return input;\n    }\n\n    public void setInput(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.input = x;\n    }\n\n    public SQLExpr getOutput() {\n        return output;\n    }\n\n    public void setOutput(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.output = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveInsert.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class HiveInsert extends SQLInsertInto {\n    public HiveInsert() {\n        partitions = new ArrayList<SQLAssignItem>();\n    }\n\n    public void setPartitions(List<SQLAssignItem> partitions) {\n        this.partitions = partitions;\n    }\n\n    @Override\n    public SQLInsertInto clone() {\n        HiveInsert x = new HiveInsert();\n        cloneTo(x);\n        return x;\n    }\n\n    public SQLExprTableSource getTableSource() {\n        return tableSource;\n    }\n\n    public void setTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSource = tableSource;\n    }\n\n    public void setTableSource(SQLName tableName) {\n        this.setTableSource(new SQLExprTableSource(tableName));\n    }\n\n    public SQLSelect getQuery() {\n        return query;\n    }\n\n    public void setQuery(SQLSelect query) {\n        if (query != null) {\n            query.setParent(this);\n        }\n        this.query = query;\n    }\n\n    public List<SQLInsertStatement.ValuesClause> getValuesList() {\n        return valuesList;\n    }\n\n    public void addValueCause(SQLInsertStatement.ValuesClause valueClause) {\n        if (valueClause != null) {\n            valueClause.setParent(this);\n        }\n        valuesList.add(valueClause);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof HiveASTVisitor) {\n            accept0((HiveASTVisitor) visitor);\n        } else {\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, valuesList);\n            acceptChild(visitor, query);\n        }\n    }\n\n    protected void accept0(HiveASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, valuesList);\n            acceptChild(visitor, query);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveInsertStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.hive.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class HiveInsertStatement extends SQLInsertStatement implements SQLStatement {\n    private boolean ifNotExists;\n\n    public HiveInsertStatement() {\n        dbType = DbType.hive;\n        partitions = new ArrayList<SQLAssignItem>();\n    }\n\n    public HiveInsertStatement clone() {\n        HiveInsertStatement x = new HiveInsertStatement();\n        super.cloneTo(x);\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OdpsASTVisitor) {\n            accept0((OdpsASTVisitor) visitor);\n        } else if (visitor instanceof HiveASTVisitor) {\n            accept0((HiveASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(HiveASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, with);\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, valuesList);\n            acceptChild(visitor, query);\n        }\n        visitor.endVisit(this);\n    }\n\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, with);\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, valuesList);\n            acceptChild(visitor, query);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLCommentHint> getHeadHintsDirect() {\n        return null;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveMultiInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class HiveMultiInsertStatement extends SQLStatementImpl {\n    protected SQLWithSubqueryClause with;\n    private SQLTableSource from;\n\n    private List<HiveInsert> items = new ArrayList<HiveInsert>();\n\n    public HiveMultiInsertStatement() {\n        super(DbType.hive);\n    }\n\n    public void setFrom(SQLTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.from = x;\n    }\n\n    public SQLTableSource getFrom() {\n        return from;\n    }\n\n    public List<HiveInsert> getItems() {\n        return items;\n    }\n\n    public void addItem(HiveInsert item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof HiveASTVisitor) {\n            accept0((HiveASTVisitor) visitor);\n        } else {\n            acceptChild(visitor, with);\n            acceptChild(visitor, from);\n            acceptChild(visitor, items);\n        }\n    }\n\n    public void accept0(HiveASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, with);\n            acceptChild(visitor, from);\n            acceptChild(visitor, items);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLWithSubqueryClause getWith() {\n        return with;\n    }\n\n    public void setWith(SQLWithSubqueryClause with) {\n        if (with != null) {\n            with.setParent(this);\n        }\n        this.with = with;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLListExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInputOutputFormat;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class HiveCreateTableParser extends SQLCreateTableParser {\n    public HiveCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public HiveCreateTableParser(Lexer lexer) {\n        super(new HiveExprParser(lexer));\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement stmt) {\n        if (lexer.nextIfIdentifier(FnvHash.Constants.EXTERNAL)) {\n            stmt.setExternal(true);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.TEMPORARY)) {\n            stmt.setTemporary(true);\n        }\n\n        if (lexer.nextIfIdentifier(\"TRANSACTIONAL\")) {\n            stmt.config(SQLCreateTableStatement.Feature.Transactional);\n        }\n    }\n\n    protected void createTableBody(SQLCreateTableStatement stmt) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                Token token = lexer.token();\n                if (token == Token.IDENTIFIER //\n                        || token == Token.LITERAL_ALIAS) {\n                    SQLColumnDefinition column = this.exprParser.parseColumn();\n                    stmt.getTableElementList().add(column);\n                } else if (token == Token.PRIMARY //\n                        || token == Token.UNIQUE //\n                        || token == Token.CHECK //\n                        || token == Token.CONSTRAINT\n                        || token == Token.FOREIGN) {\n                    SQLConstraint constraint = this.exprParser.parseConstraint();\n                    constraint.setParent(stmt);\n                    stmt.getTableElementList().add((SQLTableElement) constraint);\n                } else if (token == Token.TABLESPACE) {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                } else {\n                    SQLColumnDefinition column = this.exprParser.parseColumn();\n                    stmt.getTableElementList().add(column);\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.RPAREN) { // compatible for sql server\n                        break;\n                    }\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.RPAREN);\n        } else if (lexer.token() == Token.LIKE) {\n            parseLike((HiveCreateTableStatement) stmt);\n        }\n    }\n\n    protected void createTableQuery(SQLCreateTableStatement stmt) {\n        if (lexer.token() == Token.SELECT || lexer.token() == Token.AS) {\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n            }\n            SQLSelect select = this.createSQLSelectParser().select();\n            stmt.setSelect(select);\n        }\n    }\n\n    protected void parseCreateTableWithSerderPropertie(HiveCreateTableStatement stmt) {\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"SERDEPROPERTIES\");\n\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                String key = lexer.stringVal();\n                lexer.nextToken();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.primary();\n                stmt.getSerdeProperties().put(key, value);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n\n            accept(Token.RPAREN);\n        }\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement createTable) {\n        HiveCreateTableStatement stmt = (HiveCreateTableStatement) createTable;\n        if (lexer.nextIfIdentifier(FnvHash.Constants.ENGINE)) {\n            // skip engine=xxx\n            accept(Token.EQ);\n            lexer.nextToken();\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.CHARSET)) {\n            // skip charset = xxx\n            accept(Token.EQ);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USING) || lexer.token() == Token.USING) {\n            lexer.nextToken();\n            SQLExpr using = this.exprParser.expr();\n            stmt.setUsing(using);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.OPTIONS)) {\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, false);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.nextIf(Token.COMMENT)) {\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.MAPPED)) {\n            accept(Token.BY);\n            this.exprParser.parseAssignItem(stmt.getMappedBy(), stmt);\n        }\n\n        if (lexer.nextIf(Token.PARTITIONED)) {\n            accept(Token.BY);\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                if (lexer.token() != Token.IDENTIFIER) {\n                    throw new ParserException(\"expect identifier. \" + lexer.info());\n                }\n\n                SQLColumnDefinition column = this.exprParser.parseColumn();\n                stmt.addPartitionColumn(column);\n\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    column.addAfterComment(lexer.readAndResetComments());\n                }\n\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        column.addAfterComment(lexer.readAndResetComments());\n                    }\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.CLUSTERED)) {\n            accept(Token.BY);\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                stmt.addClusteredByItem(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SORTED)) {\n            parseSortedBy(stmt);\n        }\n\n        if (stmt.getClusteredBy().size() > 0 || stmt.getSortedBy().size() > 0) {\n            accept(Token.INTO);\n            if (lexer.token() == Token.LITERAL_INT) {\n                stmt.setBuckets(lexer.integerValue().intValue());\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"into buckets must be integer. \" + lexer.info());\n            }\n            acceptIdentifier(\"BUCKETS\");\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.SKEWED)) {\n            accept(Token.BY);\n            accept(Token.LPAREN);\n            this.exprParser.exprList(stmt.getSkewedBy(), stmt);\n            accept(Token.RPAREN);\n            accept(Token.ON);\n            accept(Token.LPAREN);\n            for (; ; ) {\n                if (lexer.token() == Token.LPAREN) {\n                    SQLListExpr list = new SQLListExpr();\n                    lexer.nextToken();\n                    this.exprParser.exprList(list.getItems(), list);\n                    accept(Token.RPAREN);\n                    stmt.addSkewedByOn(list);\n                } else {\n                    SQLExpr expr = this.exprParser.expr();\n                    stmt.addSkewedByOn(expr);\n                }\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n            if (lexer.nextIfIdentifier(FnvHash.Constants.STORED)) {\n                accept(Token.AS);\n                acceptIdentifier(\"DIRECTORIES\");\n                stmt.setSkewedByStoreAsDirectories(true);\n            }\n        }\n\n        if (lexer.token() == Token.ROW\n                || lexer.identifierEquals(FnvHash.Constants.ROW)) {\n            parseRowFormat(stmt);\n        }\n\n        if (Token.LBRACKET.equals(lexer.token())) {\n            stmt.setLbracketUse(true);\n            lexer.nextToken();\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.BY) {\n                accept(Token.BY);\n                SQLName name = this.exprParser.name();\n                stmt.setStoredBy(name);\n\n                parseCreateTableWithSerderPropertie(stmt);\n            } else {\n                accept(Token.AS);\n\n                if (lexer.identifierEquals(FnvHash.Constants.INPUTFORMAT)) {\n                    HiveInputOutputFormat format = new HiveInputOutputFormat();\n                    lexer.nextToken();\n                    format.setInput(this.exprParser.primary());\n\n                    if (lexer.identifierEquals(FnvHash.Constants.OUTPUTFORMAT)) {\n                        lexer.nextToken();\n                        format.setOutput(this.exprParser.primary());\n                    }\n                    stmt.setStoredAs(format);\n                } else {\n                    SQLName name = this.exprParser.name();\n                    stmt.setStoredAs(name);\n                }\n            }\n        }\n\n        if (Token.RBRACKET.equals(lexer.token())) {\n            stmt.setRbracketUse(true);\n            lexer.nextToken();\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.LOCATION)) {\n            lexer.nextToken();\n            SQLExpr location = this.exprParser.primary();\n            stmt.setLocation(location);\n        }\n\n        if (lexer.token() == Token.LIKE) {\n            parseLike(stmt);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n            parseOptions(stmt);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.META)) {\n            lexer.nextToken();\n            acceptIdentifier(\"LIFECYCLE\");\n            stmt.setLifeCycle(this.exprParser.primary());\n        }\n\n        createTableQuery(stmt);\n\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            Lexer.SavePoint mark = lexer.mark();\n            if (lexer.token() == Token.SELECT) {\n                stmt.setLikeQuery(true);\n                SQLSelect select = this.createSQLSelectParser().select();\n                stmt.setSelect(select);\n            } else {\n                lexer.reset(mark);\n\n                if (lexer.identifierEquals(FnvHash.Constants.MAPPING)) {\n                    SQLExpr like = this.exprParser.primary();\n                    stmt.setLike(new SQLExprTableSource(like));\n                } else {\n                    SQLName name = this.exprParser.name();\n                    stmt.setLike(name);\n                }\n            }\n        }\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USING) || lexer.token() == Token.USING) {\n            lexer.nextToken();\n            SQLExpr using = this.exprParser.expr();\n            stmt.setUsing(using);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, false);\n            accept(Token.RPAREN);\n        }\n    }\n\n    protected void parseOptions(SQLCreateTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            String name = lexer.stringVal();\n            lexer.nextToken();\n            if (lexer.token() == Token.DOT) {\n                lexer.nextToken();\n                name += \".\" + lexer.stringVal();\n                lexer.nextToken();\n            }\n\n            accept(Token.EQ);\n            SQLExpr value = this.exprParser.primary();\n            stmt.addOption(name, value);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                if (lexer.token() == Token.RPAREN) {\n                    break;\n                }\n                continue;\n            }\n            break;\n        }\n\n        accept(Token.RPAREN);\n    }\n\n    protected void parseLike(HiveCreateTableStatement stmt) {\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.MAPPING)) {\n            SQLExpr like = this.exprParser.primary();\n            stmt.setLike(new SQLExprTableSource(like));\n        } else if (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN) {\n            SQLSelect select = this.createSQLSelectParser().select();\n            stmt.setLikeQuery(true);\n            stmt.setSelect(select);\n        } else {\n            SQLName name = this.exprParser.name();\n            stmt.setLike(name);\n        }\n    }\n\n    protected void parseSortedBy(HiveCreateTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.BY);\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n            stmt.addSortedByItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n    }\n\n    protected void parseRowFormat(HiveCreateTableStatement stmt) {\n        SQLExternalRecordFormat format = this.getExprParser().parseRowFormat();\n        stmt.setRowFormat(format);\n        parseCreateTableWithSerderPropertie(stmt);\n    }\n\n    @Override\n    public HiveExprParser getExprParser() {\n        return (HiveExprParser) exprParser;\n    }\n\n    protected HiveCreateTableStatement newCreateStatement() {\n        return new HiveCreateTableStatement();\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new HiveSelectParser(this.exprParser, selectListCache);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCurrentTimeExpr;\nimport com.alibaba.druid.sql.ast.SQLCurrentUserExpr;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class HiveExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\", \"ROW_NUMBER\",\n                \"ROWNUMBER\"};\n\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public HiveExprParser(String sql) {\n        this(new HiveLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public HiveExprParser(String sql, SQLParserFeature... features) {\n        this(new HiveLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public HiveExprParser(Lexer lexer) {\n        this(lexer, DbType.hive);\n    }\n\n    public HiveExprParser(Lexer lexer, DbType dbType) {\n        super(lexer, dbType);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    @Override\n    protected SQLExpr primaryCommon(SQLExpr sqlExpr) {\n        sqlExpr = new SQLIdentifierExpr(lexer.stringVal());\n        lexer.nextToken();\n        return sqlExpr;\n    }\n    @Override\n    protected String doRestSpecific(SQLExpr expr) {\n        String name = null;\n        if ((lexer.token() == Token.LITERAL_INT || lexer.token() == Token.LITERAL_FLOAT)) {\n            name = lexer.numberString();\n            lexer.nextToken();\n        }\n        return name;\n    }\n\n    @Override\n    protected SQLExpr relationalRestEqeq(SQLExpr expr) {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n        SQLExpr rightExp;\n        try {\n            if (lexer.token() == Token.SEMI) {\n                lexer.reset(mark);\n                return expr;\n            }\n            rightExp = bitOr();\n        } catch (EOFParserException e) {\n            throw new ParserException(\"EOF, \" + expr + \"=\", e);\n        }\n\n        if (lexer.token() == Token.COLONEQ) {\n            lexer.nextToken();\n            SQLExpr colonExpr = expr();\n            rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType);\n        }\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr parseAssignItemOnColon(SQLExpr sqlExpr) {\n        if (lexer.token() == Token.COLON) {\n            lexer.nextToken();\n            String str = sqlExpr.toString() + ':';\n            str += lexer.numberString();\n            lexer.nextToken();\n            sqlExpr = new SQLIdentifierExpr(str);\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr parseSelectItemRest(String ident, long hash_lower) {\n        SQLExpr expr = null;\n        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)\n                && lexer.stringVal().charAt(0) != '`'\n        ) {\n            lexer.nextToken();\n            String collate = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLBinaryOpExpr binaryExpr = new SQLBinaryOpExpr(\n                    new SQLIdentifierExpr(ident),\n                    SQLBinaryOperator.COLLATE,\n                    new SQLIdentifierExpr(collate), dbType\n            );\n            expr = binaryExpr;\n\n        } else if (FnvHash.Constants.TIMESTAMP == hash_lower\n                && lexer.stringVal().charAt(0) != '`'\n                && lexer.token() == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLTimestampExpr ts = new SQLTimestampExpr(literal);\n            expr = ts;\n\n            if (lexer.identifierEquals(FnvHash.Constants.AT)) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n\n                String timeZone = null;\n                if (lexer.identifierEquals(FnvHash.Constants.TIME)) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.ZONE)) {\n                        lexer.nextToken();\n                        timeZone = lexer.stringVal();\n                        lexer.nextToken();\n                    }\n                }\n                if (timeZone == null) {\n                    lexer.reset(mark);\n                } else {\n                    ts.setTimeZone(timeZone);\n                }\n            }\n        } else if (FnvHash.Constants.DATETIME == hash_lower\n                && lexer.stringVal().charAt(0) != '`'\n                && lexer.token() == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLDateTimeExpr ts = new SQLDateTimeExpr(literal);\n            expr = ts;\n        } else if (FnvHash.Constants.CURRENT_DATE == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_DATE);\n\n        } else if (FnvHash.Constants.CURRENT_TIMESTAMP == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIMESTAMP);\n\n        } else if (FnvHash.Constants.CURRENT_TIME == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIME);\n\n        } else if (FnvHash.Constants.CURDATE == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURDATE);\n\n        } else if (FnvHash.Constants.LOCALTIME == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.LOCALTIME);\n\n        } else if (FnvHash.Constants.LOCALTIMESTAMP == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.LOCALTIMESTAMP);\n        }\n        return expr;\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (lexer.token() == Token.COLON) {\n            lexer.nextToken();\n            expr = dotRest(expr);\n            if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr spe = (SQLPropertyExpr) expr;\n                spe.setSplitString(\":\");\n            }\n            return expr;\n        }\n\n        switch (lexer.token()) {\n            case LBRACKET:\n                SQLArrayExpr array = new SQLArrayExpr();\n                array.setExpr(expr);\n                lexer.nextToken();\n                this.exprList(array.getValues(), array);\n                accept(Token.RBRACKET);\n                return primaryRest(array);\n            case LITERAL_CHARS:\n                if (expr instanceof SQLCharExpr) {\n                    StringBuilder text2 = new StringBuilder(((SQLCharExpr) expr).getText());\n                    do {\n                        String chars = lexer.stringVal();\n                        text2.append(chars);\n                        lexer.nextToken();\n                    } while (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS);\n                    expr = new SQLCharExpr(text2.toString());\n                }\n                break;\n            case IDENTIFIER:\n                if (lexer.identifierEquals(FnvHash.Constants.BD) && expr instanceof SQLNumericLiteralExpr) {\n                    lexer.nextToken();\n                    Number num = ((SQLNumericLiteralExpr) expr).getNumber();\n                    expr = new SQLDecimalExpr(num.toString());\n                }\n                break;\n            default:\n                break;\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    public SQLExpr primary() {\n        final Token tok = lexer.token();\n        switch (tok) {\n            case WITH: {\n                return primaryRest(\n                        new SQLQueryExpr(\n                                createSelectParser()\n                                        .select()));\n            }\n            case IDENTIFIER:\n                final long hash_lower = lexer.hashLCase();\n                if (hash_lower == FnvHash.Constants.OUTLINE) {\n                    lexer.nextToken();\n                    SQLExpr file = primary();\n                    SQLExpr expr = new MySqlOutFileExpr(file);\n\n                    return primaryRest(expr);\n                }\n\n                SQLCurrentTimeExpr currentTimeExpr = null;\n                if (hash_lower == FnvHash.Constants.CURRENT_TIMESTAMP) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIMESTAMP);\n                } else if (hash_lower == FnvHash.Constants.CURRENT_DATE) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_DATE);\n                } else if (hash_lower == FnvHash.Constants.CURRENT_USER && isEnabled(SQLParserFeature.EnableCurrentUserExpr)) {\n                    lexer.nextToken();\n                    return primaryRest(new SQLCurrentUserExpr());\n                }\n\n                if (currentTimeExpr != null) {\n                    String methodName = lexer.stringVal();\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.LPAREN) {\n                            lexer.nextToken();\n                        } else {\n                            return primaryRest(\n                                    methodRest(new SQLIdentifierExpr(methodName), false)\n                            );\n                        }\n                    }\n\n                    return primaryRest(currentTimeExpr);\n                }\n            default:\n                break;\n        }\n\n        return super.primary();\n    }\n\n    protected SQLExpr parseAliasExpr(String alias) {\n        String chars = alias.substring(1, alias.length() - 1);\n\n        StringBuilder buf = null;\n\n        for (int i = 0; i < chars.length(); ++i) {\n            char ch = chars.charAt(i);\n            if (ch == '\\\\' && i < chars.length() - 1) {\n                char next = chars.charAt(i + 1);\n                if (next == '\\\\') {\n                    if (buf == null) {\n                        buf = new StringBuilder();\n                        buf.append(chars.substring(0, i));\n                    }\n                    buf.append('\\\\');\n                    ++i;\n                } else if (next == '\\\"') {\n                    if (buf == null) {\n                        buf = new StringBuilder();\n                        buf.append(chars.substring(0, i));\n                    }\n                    buf.append('\"');\n                    ++i;\n                } else {\n                    if (buf != null) {\n                        buf.append(ch);\n                    }\n                }\n            } else {\n                if (buf != null) {\n                    buf.append(ch);\n                }\n            }\n        }\n\n        if (buf != null) {\n            chars = buf.toString();\n        }\n        return new SQLCharExpr(chars);\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.identifierEquals(FnvHash.Constants.MAPPED)) {\n            lexer.nextToken();\n            accept(Token.BY);\n            this.parseAssignItem(column.getMappedBy(), column);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COLPROPERTIES)) {\n            lexer.nextToken();\n            this.parseAssignItem(column.getColProperties(), column);\n        }\n\n        return super.parseColumnRest(column);\n    }\n\n    protected SQLExpr parseInterval() {\n        String str = lexer.stringVal();\n        accept(Token.INTERVAL);\n        if (lexer.token() == Token.AS || lexer.token() == Token.RPAREN) {\n            return new SQLIdentifierExpr(str);\n        }\n\n        SQLExpr value = expr();\n\n        if (value instanceof SQLIntervalExpr) {\n            return value;\n        }\n\n        if (lexer.token() != Token.IDENTIFIER) {\n            throw new ParserException(\"Syntax error. \" + lexer.info());\n        }\n\n        String unit = lexer.stringVal();\n        lexer.nextToken();\n\n        SQLIntervalExpr intervalExpr = new SQLIntervalExpr();\n        intervalExpr.setValue(value);\n        SQLIntervalUnit intervalUnit = SQLIntervalUnit.of(unit.toUpperCase());\n        if (intervalUnit == SQLIntervalUnit.YEAR\n                && lexer.token() == Token.TO) {\n            lexer.nextToken();\n            acceptIdentifier(\"MONTH\");\n            intervalUnit = SQLIntervalUnit.YEAR_TO_MONTH;\n        }\n        if (intervalUnit == SQLIntervalUnit.DAY && lexer.nextIf(Token.TO)) {\n            acceptIdentifier(FnvHash.Constants.SECOND);\n            intervalUnit = SQLIntervalUnit.DAY_SECOND;\n        } else if (intervalUnit == SQLIntervalUnit.HOUR && lexer.nextIf(Token.TO)) {\n            acceptIdentifier(FnvHash.Constants.SECOND);\n            intervalUnit = SQLIntervalUnit.HOUR_SECOND;\n        }\n        intervalExpr.setUnit(intervalUnit);\n\n        return intervalExpr;\n    }\n\n    protected SQLExpr primaryIdentifierRest(long hash_lower, String ident) {\n        if (ident.length() > 3 && ident.charAt(0) == '`' && ident.charAt(ident.length() - 1) == '`' && ident.indexOf('.') != -1) {\n            return topPropertyExpr(ident);\n        }\n        return super.primaryIdentifierRest(hash_lower, ident);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.DialectFeature;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.NotAllowCommentException;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.isWhitespace;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.*;\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;\n\npublic class HiveLexer extends Lexer {\n    public static final Keywords HIVE_KEYWORDS;\n    public static final DialectFeature HIVE_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    ScanSQLTypeWithFrom,\n                    NextTokenColon,\n                    ScanAliasU,\n                    JoinRightTableFrom,\n                    GroupByAll,\n                    SQLDateExpr,\n                    ParseAssignItemRparenCommaSetReturn,\n                    TableAliasLock,\n                    TableAliasPartition,\n                    AsSkip,\n                    AsSequence,\n                    AsDatabase,\n                    AsDefault\n            ),\n            Collections.singletonList(\n                    PrimaryBangBangSupport\n            )\n    );\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"USING\", Token.USING);\n\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"PARTITIONED\", Token.PARTITIONED);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n        //        map.put(\"SORT\", Token.SORT);\n        map.put(\"IF\", Token.IF);\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"RLIKE\", Token.RLIKE);\n        map.put(\"CONSTRAINT\", Token.CONSTRAINT);\n        map.put(\"DIV\", Token.DIV);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n\n        HIVE_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return HIVE_KEYWORDS;\n    }\n\n    public HiveLexer(String input, DbType dbType) {\n        super(input, dbType);\n        this.skipComment = true;\n        this.keepComments = true;\n        this.features |= SQLParserFeature.SupportUnicodeCodePoint.mask;\n    }\n\n    public HiveLexer(String input) {\n        this(input, DbType.hive);\n    }\n\n    public HiveLexer(String input, SQLParserFeature... features) {\n        this(input, DbType.hive, features);\n    }\n\n    public HiveLexer(String input, DbType dbType, SQLParserFeature... features) {\n        super(input, dbType);\n        this.skipComment = true;\n        this.keepComments = true;\n        this.features |= SQLParserFeature.SupportUnicodeCodePoint.mask;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    @Override\n    protected void scanString() {\n        {\n            boolean hasSpecial = false;\n            int startIndex = pos + 1;\n            int endIndex = -1; // text.indexOf('\\'', startIndex);\n            for (int i = startIndex; i < text.length(); ++i) {\n                final char ch = text.charAt(i);\n                if (ch == '\\\\') {\n                    hasSpecial = true;\n                    continue;\n                }\n                if (ch == '\\'') {\n                    endIndex = i;\n                    break;\n                }\n            }\n\n            if (endIndex == -1) {\n                throw new ParserException(\"unclosed str. \" + info());\n            }\n\n            String stringVal;\n            if (token == Token.AS) {\n                stringVal = text.substring(pos, endIndex + 1);\n            } else {\n                if (startIndex == endIndex) {\n                    stringVal = \"\";\n                } else {\n                    stringVal = text.substring(startIndex, endIndex);\n                }\n            }\n            // hasSpecial = stringVal.indexOf('\\\\') != -1;\n\n            if (!hasSpecial) {\n                this.stringVal = stringVal;\n                int pos = endIndex + 1;\n                char ch = charAt(pos);\n                if (ch != '\\'') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = LITERAL_CHARS;\n                    return;\n                }\n            }\n        }\n\n        mark = pos;\n        boolean hasSpecial = false;\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                switch (ch) {\n                    case '0':\n                        putChar('\\0');\n                        break;\n                    case '\\'':\n                        putChar('\\'');\n                        break;\n                    case '\"':\n                        putChar('\"');\n                        break;\n                    case 'b':\n                        putChar('\\b');\n                        break;\n                    case 'n':\n                        putChar('\\n');\n                        break;\n                    case 'r':\n                        putChar('\\r');\n                        break;\n                    case 't':\n                        putChar('\\t');\n                        break;\n                    case '\\\\':\n                        putChar('\\\\');\n                        break;\n                    case 'Z':\n                        putChar((char) 0x1A); // ctrl + Z\n                        break;\n                    case '%':\n                        putChar('%');\n                        break;\n                    case '_':\n                        putChar('_');\n                        break;\n                    case 'u':\n                        if ((features & SQLParserFeature.SupportUnicodeCodePoint.mask) != 0) {\n                            int codePointSize = 0;\n                            for (int i = 0; i < 4; i++, codePointSize++) {\n                                char c = charAt(pos + 1 + i);\n                                if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {\n                                    break;\n                                }\n                            }\n\n                            int intVal = Integer.parseInt(text.substring(pos + 1, pos + 1 + codePointSize), 16);\n                            pos += codePointSize;\n\n                            putChar((char) intVal);\n                        } else {\n                            putChar(ch);\n                        }\n                        break;\n                    default:\n                        putChar(ch);\n                        break;\n                }\n\n                continue;\n            }\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    public void scanComment() {\n        if (ch != '/' && ch != '-') {\n            throw new IllegalStateException();\n        }\n\n        Token lastToken = this.token;\n\n        mark = pos;\n        bufPos = 0;\n        scanChar();\n\n        if (ch == ' ') {\n            mark = pos;\n            bufPos = 0;\n            scanChar();\n\n            if (dialectFeatureEnabled(ScanHiveCommentDoubleSpace) && ch == ' ') {\n                mark = pos;\n                bufPos = 0;\n                scanChar();\n            }\n        }\n\n        // /*+ */\n        if (ch == '*') {\n            scanChar();\n            bufPos++;\n\n            while (ch == ' ') {\n                scanChar();\n                bufPos++;\n            }\n\n            boolean isHint = false;\n            int startHintSp = bufPos + 1;\n            if (ch == '+') {\n                isHint = true;\n                scanChar();\n                bufPos++;\n            }\n\n            for (; ; ) {\n                if (ch == '*') {\n                    if (charAt(pos + 1) == '/') {\n                        bufPos += 2;\n                        scanChar();\n                        scanChar();\n                        break;\n                    } else if (isWhitespace(charAt(pos + 1))) {\n                        int i = 2;\n                        for (; i < 1024 * 1024; ++i) {\n                            if (!isWhitespace(charAt(pos + i))) {\n                                break;\n                            }\n                        }\n                        if (charAt(pos + i) == '/') {\n                            bufPos += 2;\n                            pos += (i + 1);\n                            ch = charAt(pos);\n                            break;\n                        }\n                    }\n                }\n\n                scanChar();\n                if (ch == EOI) {\n                    break;\n                }\n                bufPos++;\n            }\n\n            if (isHint) {\n                stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 1);\n                token = Token.HINT;\n            } else {\n                stringVal = subString(mark, bufPos + 1);\n                token = Token.MULTI_LINE_COMMENT;\n                commentCount++;\n                if (keepComments) {\n                    addComment(stringVal);\n                }\n            }\n\n            if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {\n                return;\n            }\n\n            if (token != Token.HINT && !isAllowComment()) {\n                throw new NotAllowCommentException();\n            }\n\n            return;\n        }\n\n        if (!isAllowComment()) {\n            throw new NotAllowCommentException();\n        }\n\n        if (ch == '/' || ch == '-') {\n            scanChar();\n            bufPos++;\n\n            for (; ; ) {\n                if (ch == '\\r') {\n                    if (charAt(pos + 1) == '\\n') {\n                        line++;\n                        bufPos += 2;\n                        scanChar();\n                        break;\n                    }\n                    bufPos++;\n                    break;\n                } else if (ch == EOI) {\n                    if (pos >= text.length()) {\n                        break;\n                    }\n                }\n\n                if (ch == '\\n') {\n                    line++;\n                    scanChar();\n                    bufPos++;\n                    break;\n                }\n\n                scanChar();\n                bufPos++;\n            }\n\n            stringVal = subString(mark, ch != EOI ? bufPos : bufPos + 1);\n            token = Token.LINE_COMMENT;\n            commentCount++;\n            if (keepComments) {\n                addComment(stringVal);\n            }\n            endOfComment = isEOF();\n\n            if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {\n                return;\n            }\n\n            return;\n        }\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = HIVE_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.parser;\n\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\n\npublic class HiveSelectParser extends SQLSelectParser {\n    public HiveSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public HiveSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public HiveSelectParser(String sql) {\n        this(new HiveExprParser(sql));\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new HiveExprParser(lexer);\n    }\n\n    public void parseTableSourceSample(SQLTableSource tableSource) {\n        parseTableSourceSampleHive(tableSource);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveAddJarStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveLoadDataStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.FnvHash.Constants;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.LPAREN;\n\npublic class HiveStatementParser extends SQLStatementParser {\n    {\n        dbType = DbType.hive;\n    }\n\n    public HiveStatementParser(String sql) {\n        super(new HiveExprParser(sql));\n    }\n\n    public HiveStatementParser(String sql, SQLParserFeature... features) {\n        super(new HiveExprParser(sql, features));\n    }\n\n    public HiveStatementParser(Lexer lexer) {\n        super(new HiveExprParser(lexer));\n    }\n\n    public HiveStatementParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new HiveSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new HiveCreateTableParser(this.exprParser);\n    }\n\n    public SQLStatement parseInsert() {\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n\n            HiveMultiInsertStatement stmt = new HiveMultiInsertStatement();\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                SQLName tableName = this.exprParser.name();\n                SQLExprTableSource from = new SQLExprTableSource(tableName);\n                SQLTableSource tableSource = createSQLSelectParser().parseTableSourceRest(from);\n                stmt.setFrom(tableSource);\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    from.setAlias(lexer.stringVal());\n                    lexer.nextToken();\n                }\n            } else {\n                accept(Token.LPAREN);\n\n                SQLSelectParser selectParser = createSQLSelectParser();\n                SQLSelect select = selectParser.select();\n\n                accept(Token.RPAREN);\n\n                String alias = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n\n                SQLTableSource from = new SQLSubqueryTableSource(select, alias);\n\n                switch (lexer.token()) {\n                    case LEFT:\n                    case RIGHT:\n                    case FULL:\n                    case JOIN:\n                        from = selectParser.parseTableSourceRest(from);\n                        break;\n                    default:\n                        break;\n                }\n\n                stmt.setFrom(from);\n            }\n\n            for (; ; ) {\n                HiveInsert insert = parseHiveInsert();\n                stmt.addItem(insert);\n\n                if (lexer.token() != Token.INSERT) {\n                    break;\n                }\n            }\n\n            return stmt;\n        }\n\n        return parseHiveInsertStmt();\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.token() == Token.HINT) {\n            List<SQLCommentHint> hints = this.exprParser.parseHints();\n\n            boolean tddlHints = false;\n            boolean accept = false;\n\n            boolean acceptHint = false;\n            switch (lexer.token()) {\n                case SELECT:\n                case WITH:\n                case DELETE:\n                case UPDATE:\n                case INSERT:\n                case SHOW:\n                case REPLACE:\n                case TRUNCATE:\n                case DROP:\n                case ALTER:\n                case CREATE:\n                case CHECK:\n                case SET:\n                case DESC:\n                case OPTIMIZE:\n                case ANALYZE:\n                case KILL:\n                case EXPLAIN:\n                case LPAREN:\n                    acceptHint = true;\n                default:\n                    break;\n            }\n\n            if (lexer.identifierEquals(\"MSCK\")) {\n                acceptHint = true;\n            }\n\n            if (acceptHint) {\n                SQLStatementImpl stmt = (SQLStatementImpl) this.parseStatement();\n                stmt.setHeadHints(hints);\n                statementList.add(stmt);\n                return true;\n            }\n        }\n\n        if (lexer.token() == Token.FROM) {\n            SQLStatement stmt = this.parseInsert();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOAD)) {\n            HiveLoadDataStatement stmt = parseLoad();\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ANALYZE)) {\n            SQLStatement stmt = parseAnalyze();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXPORT)) {\n            SQLStatement stmt = parseExport();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IMPORT)) {\n            SQLStatement stmt = parseImport();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ADD)) {\n            SQLStatement stmt = parseAdd();\n            if (stmt != null) {\n                statementList.add(stmt);\n                return true;\n            }\n        }\n\n        if (lexer.identifierEquals(\"MSCK\")) {\n            SQLStatement stmt = parseMsck();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SHOW)) {\n            Lexer.SavePoint savePoint = this.lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.VIEWS)) {\n                lexer.nextToken();\n\n                SQLShowViewsStatement stmt = new SQLShowViewsStatement();\n                if (lexer.token() == Token.IN) {\n                    lexer.nextToken();\n                    SQLName db = this.exprParser.name();\n                    stmt.setDatabase(db);\n                }\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextToken();\n                    SQLExpr pattern = this.exprParser.expr();\n                    stmt.setLike(pattern);\n                }\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TABLES)) {\n                lexer.reset(savePoint);\n                SQLStatement stmt = this.parseShowTables();\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DATABASES)\n                    || lexer.identifierEquals(Constants.SCHEMAS)) {\n                lexer.nextToken();\n\n                SQLShowDatabasesStatement stmt = parseShowDatabases(false);\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.token() == Token.INDEX) {\n                lexer.nextToken();\n                SQLShowIndexesStatement stmt = new SQLShowIndexesStatement();\n                stmt.setType(\"INDEX\");\n\n                if (lexer.token() == Token.ON) {\n                    lexer.nextToken();\n                    SQLName table = exprParser.name();\n                    stmt.setTable(table);\n                }\n\n                if (lexer.token() == Token.HINT) {\n                    stmt.setHints(this.exprParser.parseHints());\n                }\n\n                statementList.add(stmt);\n\n                return true;\n            }\n\n            if (lexer.token() == Token.CREATE) {\n                SQLShowCreateTableStatement stmt = parseShowCreateTable();\n\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n                lexer.nextToken();\n\n                SQLShowPartitionsStmt stmt = new SQLShowPartitionsStmt();\n\n                if (lexer.token() == Token.FROM) {\n                    lexer.nextToken();\n                }\n                SQLExpr expr = this.exprParser.expr();\n                stmt.setTableSource(new SQLExprTableSource(expr));\n\n                if (lexer.token() == Token.PARTITION) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    parseAssignItems(stmt.getPartition(), stmt, false);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    stmt.setWhere(\n                            this.exprParser.expr()\n                    );\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.COLUMNS)) {\n                lexer.nextToken();\n\n                SQLShowColumnsStatement stmt = new SQLShowColumnsStatement();\n\n                if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                    lexer.nextToken();\n                    SQLName table = exprParser.name();\n                    if (lexer.token() == Token.SUB && table instanceof SQLIdentifierExpr) {\n                        lexer.mark();\n                        lexer.nextToken();\n                        String strVal = lexer.stringVal();\n                        lexer.nextToken();\n                        if (table instanceof SQLIdentifierExpr) {\n                            SQLIdentifierExpr ident = (SQLIdentifierExpr) table;\n                            table = new SQLIdentifierExpr(ident.getName() + \"-\" + strVal);\n                        }\n                    }\n                    stmt.setTable(table);\n                }\n\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextToken();\n                    SQLExpr like = exprParser.expr();\n                    stmt.setLike(like);\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = exprParser.expr();\n                    stmt.setWhere(where);\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n                lexer.nextToken();\n\n                SQLShowFunctionsStatement stmt = new SQLShowFunctionsStatement();\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextToken();\n                    SQLExpr like = this.exprParser.expr();\n                    stmt.setLike(like);\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n\n        return false;\n    }\n\n    protected HiveLoadDataStatement parseLoad() {\n        acceptIdentifier(\"LOAD\");\n        acceptIdentifier(\"DATA\");\n\n        HiveLoadDataStatement stmt = new HiveLoadDataStatement();\n        if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n            lexer.nextToken();\n            stmt.setLocal(true);\n        }\n\n        acceptIdentifier(\"INPATH\");\n\n        SQLExpr inpath = this.exprParser.expr();\n        stmt.setInpath(inpath);\n\n        if (lexer.token() == Token.OVERWRITE) {\n            lexer.nextToken();\n            stmt.setOverwrite(true);\n        }\n\n        accept(Token.INTO);\n        accept(Token.TABLE);\n        SQLExpr table = this.exprParser.expr();\n        stmt.setInto(table);\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            this.exprParser.exprList(stmt.getPartition(), stmt);\n            accept(Token.RPAREN);\n        }\n        return stmt;\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        SQLCreateTableParser parser = getSQLCreateTableParser();\n        return parser.parseCreateTable();\n    }\n\n    public SQLCreateFunctionStatement parseCreateFunction() {\n        return parseHiveCreateFunction();\n    }\n\n    public SQLCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n        accept(Token.INDEX);\n\n        SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(dbType);\n        stmt.setName(this.exprParser.name());\n\n        accept(Token.ON);\n\n        if (lexer.token() == Token.TABLE) {\n            lexer.nextToken();\n        }\n\n        stmt.setTable(this.exprParser.name());\n\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n            item.setParent(stmt);\n            stmt.addItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n            String indexType = lexer.stringVal();\n            accept(Token.LITERAL_CHARS);\n            stmt.setType(indexType);\n        }\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"DEFERRED\");\n            acceptIdentifier(\"REBUILD\");\n            stmt.setDeferedRebuild(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IDXPROPERTIES)) {\n            lexer.nextToken();\n            this.exprParser.parseAssignItem(stmt.getProperties(), stmt);\n        }\n\n        if (lexer.token() == Token.IN) {\n            lexer.nextToken();\n            accept(Token.TABLE);\n            SQLName inTable = this.exprParser.name();\n            stmt.setIn(inTable);\n        }\n\n        if (lexer.token() == Token.ROW\n                || lexer.identifierEquals(FnvHash.Constants.ROW)) {\n            SQLExternalRecordFormat format = this.getExprParser().parseRowFormat();\n            stmt.setRowFormat(format);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n            lexer.nextToken();\n            accept(Token.AS);\n            SQLName name = this.exprParser.name();\n            stmt.setStoredAs(name);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n            lexer.nextToken();\n            this.exprParser.parseAssignItem(stmt.getTableProperties(), stmt);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseExport() {\n        lexer.nextToken();\n        accept(Token.TABLE);\n        SQLExportTableStatement stmt = new SQLExportTableStatement();\n        stmt.setTable(\n                new SQLExprTableSource(\n                        this.exprParser.name()));\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getPartition(), stmt, false);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n            SQLExpr to = this.exprParser.primary();\n            stmt.setTo(to);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseAdd() {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(\"JAR\")) {\n            lexer.nextPath();\n            String path = lexer.stringVal();\n            HiveAddJarStatement stmt = new HiveAddJarStatement();\n            stmt.setPath(path);\n            lexer.nextToken();\n            return stmt;\n        }\n\n        lexer.reset(mark);\n        return null;\n    }\n\n    protected SQLStatement parseImport() {\n        lexer.nextToken();\n        SQLImportTableStatement stmt = new SQLImportTableStatement();\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            lexer.nextToken();\n            stmt.setExtenal(true);\n        }\n\n        if (lexer.token() == Token.TABLE) {\n            lexer.nextToken();\n\n            stmt.setTable(\n                    new SQLExprTableSource(\n                            this.exprParser.name()));\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getPartition(), stmt, false);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n            SQLExpr to = this.exprParser.primary();\n            stmt.setFrom(to);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterDatabase() {\n        accept(Token.ALTER);\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n\n        SQLAlterDatabaseStatement stmt = new SQLAlterDatabaseStatement();\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.DBPROPERTIES)) {\n                lexer.nextToken();\n                this.exprParser.parseAssignItem(stmt.getProperties(), stmt);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterSchema() {\n        return alterDatabase();\n    }\n\n    public SQLStatement parseCreateSchema() {\n        return parseCreateDatabase();\n    }\n\n    @Override\n    public HiveExprParser getExprParser() {\n        return (HiveExprParser) exprParser;\n    }\n\n    @Override\n    protected boolean alterTableAfterNameRest(SQLAlterTableStatement stmt) {\n        if (lexer.identifierEquals(Constants.RECOVER)) {\n            lexer.nextToken();\n            acceptIdentifier(\"PARTITIONS\");\n            stmt.addItem(new SQLAlterTableRecoverPartitions());\n        } else {\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    protected boolean alterTableSetRest(SQLAlterTableStatement stmt) {\n        if (lexer.identifierEquals(\"FILEFORMAT\")) {\n            lexer.nextToken();\n            SQLAlterTableSetFileFormat item = new SQLAlterTableSetFileFormat();\n            item.setValue(this.exprParser.primary());\n            stmt.addItem(item);\n        } else {\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public void parseCreateTableSupportSchema() {\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n    }\n\n    @Override\n    protected boolean parseAlterTableAddColumnBefore(SQLAlterTableAddColumn x) {\n        lexer.nextIfIdentifier(\"COLUMNS\");\n\n        if (lexer.nextIf(Token.IF)) {\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            x.setIfNotExists(true);\n        }\n\n        if (lexer.token() == LPAREN) {\n            lexer.nextToken();\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/stmt/HiveCreateFunctionStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.hive.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateFunctionStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class HiveCreateFunctionStatement extends SQLCreateFunctionStatement implements SQLCreateStatement {\n    protected boolean declare;\n    protected SQLExpr className;\n    protected SQLExpr location;\n    protected SQLExpr symbol;\n    protected ResourceType resourceType;\n    protected String code;\n\n    public HiveCreateFunctionStatement() {\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof HiveASTVisitor) {\n            accept0((HiveASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(HiveASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, name);\n            this.acceptChild(visitor, className);\n            this.acceptChild(visitor, location);\n            this.acceptChild(visitor, symbol);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getClassName() {\n        return className;\n    }\n\n    public void setClassName(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.className = x;\n    }\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public void setLocation(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.location = x;\n    }\n\n    public SQLExpr getSymbol() {\n        return symbol;\n    }\n\n    public void setSymbol(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.symbol = x;\n    }\n\n    public ResourceType getResourceType() {\n        return resourceType;\n    }\n\n    public void setResourceType(ResourceType resourceType) {\n        this.resourceType = resourceType;\n    }\n\n    public String getCode() {\n        return code;\n    }\n\n    public void setCode(String code) {\n        this.code = code;\n    }\n\n    public boolean isDeclare() {\n        return declare;\n    }\n\n    public void setDeclare(boolean declare) {\n        this.declare = declare;\n    }\n\n    public static enum ResourceType {\n        JAR, FILE, ARCHIVE, CODE\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/stmt/HiveCreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class HiveCreateTableStatement extends SQLCreateTableStatement {\n    protected List<SQLExpr> skewedBy = new ArrayList<SQLExpr>();\n    protected List<SQLExpr> skewedByOn = new ArrayList<SQLExpr>();\n    protected boolean skewedByStoreAsDirectories;\n    protected Map<String, SQLObject> serdeProperties = new LinkedHashMap<String, SQLObject>();\n\n    protected boolean likeQuery; // for DLA\n\n    protected List<SQLAssignItem> mappedBy = new ArrayList<SQLAssignItem>(1);\n    protected SQLExpr intoBuckets;\n    protected SQLExpr using;\n\n    private boolean lbracketUse;\n    private boolean rbracketUse;\n    public HiveCreateTableStatement() {\n        this.dbType = DbType.hive;\n    }\n\n    public HiveCreateTableStatement(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public boolean isLbracketUse() {\n        return lbracketUse;\n    }\n\n    public void setLbracketUse(boolean lbracketUse) {\n        this.lbracketUse = lbracketUse;\n    }\n\n    public boolean isRbracketUse() {\n        return rbracketUse;\n    }\n\n    public void setRbracketUse(boolean rbracketUse) {\n        this.rbracketUse = rbracketUse;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        super.acceptChild(v);\n\n        acceptChild(v, skewedBy);\n        acceptChild(v, skewedByOn);\n        for (SQLObject item : serdeProperties.values()) {\n            acceptChild(v, item);\n        }\n        acceptChild(v, intoBuckets);\n    }\n\n    public void cloneTo(HiveCreateTableStatement x) {\n        super.cloneTo(x);\n        for (SQLExpr item : skewedBy) {\n            x.addSkewedBy(item.clone());\n        }\n        for (SQLExpr item : skewedByOn) {\n            x.addSkewedByOn(item.clone());\n        }\n        for (Map.Entry<String, SQLObject> entry : serdeProperties.entrySet()) {\n            SQLObject entryValue = entry.getValue().clone();\n            entryValue.setParent(x);\n            x.serdeProperties.put(entry.getKey(), entryValue);\n        }\n\n        x.setLikeQuery(this.likeQuery);\n\n        if (mappedBy != null) {\n            for (SQLAssignItem item : mappedBy) {\n                SQLAssignItem item2 = item.clone();\n                item2.setParent(this);\n                x.mappedBy.add(item2);\n            }\n        }\n\n        if (intoBuckets != null) {\n            x.intoBuckets = intoBuckets.clone();\n        }\n\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n    }\n\n    public HiveCreateTableStatement clone() {\n        HiveCreateTableStatement x = new HiveCreateTableStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    public List<SQLExpr> getSkewedBy() {\n        return skewedBy;\n    }\n\n    public void addSkewedBy(SQLExpr item) {\n        item.setParent(this);\n        this.skewedBy.add(item);\n    }\n\n    public List<SQLExpr> getSkewedByOn() {\n        return skewedByOn;\n    }\n\n    public void addSkewedByOn(SQLExpr item) {\n        item.setParent(this);\n        this.skewedByOn.add(item);\n    }\n\n    public void setSkewedByStoreAsDirectories(boolean skewedByStoreAsDirectories) {\n        this.skewedByStoreAsDirectories = skewedByStoreAsDirectories;\n    }\n\n    public boolean isSkewedByStoreAsDirectories() {\n        return skewedByStoreAsDirectories;\n    }\n\n    public Map<String, SQLObject> getSerdeProperties() {\n        return serdeProperties;\n    }\n\n    public boolean isLikeQuery() {\n        return likeQuery;\n    }\n\n    public void setLikeQuery(boolean likeQuery) {\n        this.likeQuery = likeQuery;\n    }\n\n    public List<SQLAssignItem> getMappedBy() {\n        return mappedBy;\n    }\n\n    public SQLExpr getIntoBuckets() {\n        return intoBuckets;\n    }\n\n    public void setIntoBuckets(SQLExpr intoBuckets) {\n        this.intoBuckets = intoBuckets;\n    }\n\n    public SQLExpr getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.using = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/stmt/HiveLoadDataStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.hive.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class HiveLoadDataStatement extends SQLStatementImpl {\n    private boolean local;\n    private SQLExpr inpath;\n    private boolean overwrite;\n    private SQLExprTableSource into;\n\n    private final List<SQLExpr> partition = new ArrayList<SQLExpr>(4);\n\n    private SQLExternalRecordFormat format;\n    private SQLExpr storedBy;\n    private SQLExpr storedAs;\n    private SQLExpr rowFormat;\n    protected Map<String, SQLObject> serdeProperties = new LinkedHashMap<String, SQLObject>();\n    protected SQLExpr using;\n\n    public HiveLoadDataStatement() {\n        super(DbType.hive);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof HiveASTVisitor) {\n            accept0((HiveASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(HiveASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, inpath);\n            this.acceptChild(visitor, into);\n            this.acceptChild(visitor, partition);\n            this.acceptChild(visitor, storedAs);\n            this.acceptChild(visitor, storedBy);\n            this.acceptChild(visitor, rowFormat);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public SQLExpr getInpath() {\n        return inpath;\n    }\n\n    public void setInpath(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.inpath = x;\n    }\n\n    public boolean isOverwrite() {\n        return overwrite;\n    }\n\n    public void setOverwrite(boolean overwrite) {\n        this.overwrite = overwrite;\n    }\n\n    public SQLExprTableSource getInto() {\n        return into;\n    }\n\n    public void setInto(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.into = x;\n    }\n\n    public void setInto(SQLExpr x) {\n        if (x == null) {\n            this.into = null;\n            return;\n        }\n\n        setInto(new SQLExprTableSource(x));\n    }\n\n    public List<SQLExpr> getPartition() {\n        return partition;\n    }\n\n    public void addPartion(SQLAssignItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.partition.add(item);\n    }\n\n    public SQLExternalRecordFormat getFormat() {\n        return format;\n    }\n\n    public void setFormat(SQLExternalRecordFormat x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.format = x;\n    }\n\n    public SQLExpr getStoredBy() {\n        return storedBy;\n    }\n\n    public void setStoredBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedBy = x;\n    }\n\n    public SQLExpr getStoredAs() {\n        return storedAs;\n    }\n\n    public void setStoredAs(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedAs = x;\n    }\n\n    public SQLExpr getRowFormat() {\n        return rowFormat;\n    }\n\n    public void setRowFormat(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.rowFormat = x;\n    }\n\n    public SQLExpr getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.using = x;\n    }\n\n    public Map<String, SQLObject> getSerdeProperties() {\n        return serdeProperties;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/stmt/HiveMsckRepairStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.hive.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class HiveMsckRepairStatement extends SQLStatementImpl implements SQLAlterStatement {\n    private SQLExprTableSource table;\n    private SQLName database;\n    private boolean addPartitions;\n\n    public HiveMsckRepairStatement() {\n        super(DbType.hive);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof HiveASTVisitor) {\n            accept0((HiveASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(HiveASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n            this.acceptChild(visitor, database);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isAddPartitions() {\n        return addPartitions;\n    }\n\n    public void setAddPartitions(boolean addPartitions) {\n        this.addPartitions = addPartitions;\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public void setTable(SQLExpr x) {\n        if (x == null) {\n            this.table = null;\n            return;\n        }\n\n        setTable(new SQLExprTableSource(x));\n    }\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.database = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.visitor;\n\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveAddJarStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateFunctionStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveLoadDataStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveMsckRepairStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface HiveASTVisitor extends SQLASTVisitor {\n    default boolean visit(HiveInsert x) {\n        return true;\n    }\n\n    default void endVisit(HiveInsert x) {\n    }\n\n    default boolean visit(HiveMultiInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(HiveMultiInsertStatement x) {\n    }\n\n    default boolean visit(HiveInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(HiveInsertStatement x) {\n    }\n\n    default boolean visit(HiveCreateFunctionStatement x) {\n        return true;\n    }\n\n    default void endVisit(HiveCreateFunctionStatement x) {\n    }\n\n    default boolean visit(HiveLoadDataStatement x) {\n        return true;\n    }\n\n    default void endVisit(HiveLoadDataStatement x) {\n    }\n\n    default boolean visit(HiveMsckRepairStatement x) {\n        return true;\n    }\n\n    default void endVisit(HiveMsckRepairStatement x) {\n    }\n\n    default boolean visit(HiveAddJarStatement x) {\n        return true;\n    }\n\n    default void endVisit(HiveAddJarStatement x) {\n    }\n\n    default boolean visit(HiveCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(HiveCreateTableStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class HiveASTVisitorAdapter extends SQLASTVisitorAdapter implements HiveASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport com.alibaba.druid.sql.ast.SQLAdhocTableSource;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.Hive;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveAddJarStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateFunctionStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveLoadDataStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveMsckRepairStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic class HiveOutputVisitor extends SQLASTOutputVisitor implements HiveASTVisitor {\n    public HiveOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.hive, Hive.DIALECT);\n    }\n\n    public HiveOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect) {\n        super(appender, dbType, dialect);\n    }\n\n    public HiveOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.hive, Hive.DIALECT, parameterized);\n    }\n\n    public HiveOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect, boolean parameterized) {\n        super(appender, DbType.hive, Hive.DIALECT, parameterized);\n    }\n\n    @Override\n    public boolean visit(HiveInsert x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        if (x.getInsertBeforeCommentsDirect() != null) {\n            printlnComments(x.getInsertBeforeCommentsDirect());\n        }\n\n        SQLExprTableSource tableSource = x.getTableSource();\n\n        if (tableSource != null) {\n            if (x.isOverwrite()) {\n                print0(ucase ? \"INSERT OVERWRITE TABLE \" : \"insert overwrite table \");\n            } else {\n                print0(ucase ? \"INSERT INTO TABLE \" : \"insert into table \");\n            }\n\n            tableSource.accept(this);\n        }\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (partitions != null) {\n            int partitionsSize = partitions.size();\n            if (partitionsSize > 0) {\n                print0(ucase ? \" PARTITION (\" : \" partition (\");\n                for (int i = 0; i < partitionsSize; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                    }\n\n                    SQLAssignItem assign = partitions.get(i);\n                    assign.getTarget().accept(this);\n\n                    if (assign.getValue() != null) {\n                        print('=');\n                        assign.getValue().accept(this);\n                    }\n                }\n                print(')');\n            }\n            println();\n        }\n\n        SQLSelect select = x.getQuery();\n        List<SQLInsertStatement.ValuesClause> valuesList = x.getValuesList();\n        if (select != null) {\n            select.accept(this);\n        } else if (!valuesList.isEmpty()) {\n            print0(ucase ? \"VALUES \" : \"values \");\n            printAndAccept(valuesList, \", \");\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLExternalRecordFormat x) {\n        return hiveVisit(x);\n    }\n\n    @Override\n    public boolean visit(HiveMultiInsertStatement x) {\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (x.getFrom() != null) {\n            if (from instanceof SQLSubqueryTableSource) {\n                SQLSelect select = ((SQLSubqueryTableSource) from).getSelect();\n                print0(ucase ? \"FROM (\" : \"from (\");\n                this.indentCount++;\n                println();\n                select.accept(this);\n                this.indentCount--;\n                println();\n                print0(\") \");\n                String alias = x.getFrom().getAlias();\n                if (alias != null) {\n                    print0(alias);\n                }\n            } else {\n                print0(ucase ? \"FROM \" : \"from \");\n                from.accept(this);\n            }\n            println();\n        }\n\n        for (int i = 0; i < x.getItems().size(); ++i) {\n            HiveInsert insert = x.getItems().get(i);\n            if (i != 0) {\n                println();\n            }\n            insert.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(HiveInsertStatement x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n\n        List<String> insertBeforeComments = x.getInsertBeforeCommentsDirect();\n        if (insertBeforeComments != null) {\n            printlnComments(insertBeforeComments);\n        }\n\n        if (x.isOverwrite()) {\n            print0(ucase ? \"INSERT OVERWRITE TABLE \" : \"insert overwrite table \");\n        } else {\n            print0(ucase ? \"INSERT INTO TABLE \" : \"insert into table \");\n        }\n        x.getTableSource().accept(this);\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        int partitionSize = partitions.size();\n        if (partitionSize > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            for (int i = 0; i < partitionSize; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n\n                SQLAssignItem assign = partitions.get(i);\n                assign.getTarget().accept(this);\n\n                if (assign.getValue() != null) {\n                    print('=');\n                    assign.getValue().accept(this);\n                }\n            }\n            print(')');\n        }\n\n        List<SQLExpr> columns = x.getColumns();\n        if (columns.size() > 0) {\n            print(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \" IF NOT EXISTS\" : \" if not exists\");\n        }\n        println();\n\n        SQLSelect select = x.getQuery();\n        List<SQLInsertStatement.ValuesClause> valuesList = x.getValuesList();\n        if (select != null) {\n            select.accept(this);\n        } else if (!valuesList.isEmpty()) {\n            print0(ucase ? \"VALUES \" : \"values \");\n            printAndAccept(valuesList, \", \");\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLMergeStatement.WhenUpdate x) {\n        print0(ucase ? \"WHEN\" : \"when\");\n        if (x.isNot()) {\n            print0(ucase ? \" NOT\" : \" not\");\n        }\n        print0(ucase ? \" MATCHED \" : \" matched \");\n        this.indentCount++;\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            this.indentCount++;\n            if (SQLBinaryOpExpr.isAnd(where)) {\n                println();\n            } else {\n                print(' ');\n            }\n\n            print0(ucase ? \"AND \" : \"and \");\n\n            printExpr(where, parameterized);\n            this.indentCount--;\n            println();\n        }\n        print0(ucase ? \"UPDATE SET \" : \"update set \");\n        printAndAccept(x.getItems(), \", \");\n        this.indentCount--;\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveCreateFunctionStatement x) {\n        if (x.isTemporary()) {\n            print0(ucase ? \"CREATE TEMPORARY FUNCTION \" : \"create temporary function \");\n        } else {\n            print0(ucase ? \"CREATE FUNCTION \" : \"create function \");\n        }\n        x.getName().accept(this);\n\n        SQLExpr className = x.getClassName();\n        if (className != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            className.accept(this);\n        }\n\n        indentCount++;\n        SQLExpr location = x.getLocation();\n        HiveCreateFunctionStatement.ResourceType resourceType = x.getResourceType();\n\n        if (location != null) {\n            println();\n\n            if (resourceType != null) {\n                print0(ucase ? \"USING \" : \"using \");\n                print0(resourceType.name());\n                print(' ');\n            } else {\n                print0(ucase ? \"LOCATION \" : \"location \");\n            }\n            location.accept(this);\n        }\n\n        String code = x.getCode();\n        if (code != null) {\n            println();\n            print0(ucase ? \"USING\" : \"using\");\n            print0(code);\n        }\n\n        SQLExpr symbol = x.getSymbol();\n        if (symbol != null) {\n            println();\n            print0(ucase ? \"SYMBOL = \" : \"symbol = \");\n            symbol.accept(this);\n        }\n\n        indentCount--;\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveLoadDataStatement x) {\n        print0(ucase ? \"LOAD DATA \" : \"load data \");\n\n        if (x.isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        print0(ucase ? \"INPATH \" : \"inpath \");\n        x.getInpath().accept(this);\n\n        if (x.isOverwrite()) {\n            print0(ucase ? \" OVERWRITE INTO TABLE \" : \" overwrite into table \");\n        } else {\n            print0(ucase ? \" INTO TABLE \" : \" into table \");\n        }\n        x.getInto().accept(this);\n\n        if (x.getPartition().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveMsckRepairStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n        print0(ucase ? \"MSCK REPAIR\" : \"msck repair\");\n\n        SQLName database = x.getDatabase();\n        if (database != null) {\n            print0(ucase ? \" DATABASE \" : \" database \");\n            database.accept(this);\n        }\n\n        SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            print0(ucase ? \" TABLE \" : \" table \");\n            table.accept(this);\n        }\n\n        if (x.isAddPartitions()) {\n            print0(ucase ? \" ADD PARTITIONS\" : \" add partitions\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableExchangePartition x) {\n        print0(ucase ? \"EXCHANGE PARTITION (\" : \"exchange partition (\");\n        printAndAccept(x.getPartitions(), \", \");\n        print0(ucase ? \") WITH TABLE \" : \") with table \");\n        x.getTable().accept(this);\n\n        Boolean validation = x.getValidation();\n        if (validation != null) {\n            if (validation) {\n                print0(ucase ? \" WITH VALIDATION\" : \" with validation\");\n            } else {\n                print0(ucase ? \" WITHOUT VALIDATION\" : \" without validation\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateIndexStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        print0(ucase ? \"INDEX \" : \"index \");\n\n        x.getName().accept(this);\n        print0(ucase ? \" ON TABLE \" : \" on table \");\n        x.getTable().accept(this);\n        print0(\" (\");\n        printAndAccept(x.getItems(), \", \");\n        print(')');\n\n        String type = x.getType();\n        if (type != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            print0(type);\n        }\n\n        if (x.isDeferedRebuild()) {\n            print0(ucase ? \" WITH DEFERRED REBUILD\" : \" with deferred rebuild\");\n        }\n\n        if (x.getProperties().size() > 0) {\n            print0(ucase ? \" IDXPROPERTIES (\" : \" idxproperties (\");\n            printAndAccept(x.getProperties(), \", \");\n            print(')');\n        }\n\n        // for mysql\n        String using = x.getUsing();\n        if (using != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(using);\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        final SQLTableSource in = x.getIn();\n        if (in != null) {\n            print0(ucase ? \" IN TABLE \" : \" in table \");\n            in.accept(this);\n        }\n\n        final SQLExternalRecordFormat format = x.getRowFormat();\n        if (format != null) {\n            println();\n            print0(ucase ? \"ROW FORMAT DELIMITED \" : \"row rowFormat delimited \");\n            visit(format);\n        }\n\n        final SQLName storedAs = x.getStoredAs();\n        if (storedAs != null) {\n            print0(ucase ? \" STORED BY \" : \" stored by \");\n            storedAs.accept(this);\n        }\n\n        if (x.getTableProperties().size() > 0) {\n            print0(ucase ? \" TBLPROPERTIES (\" : \" tblproperties (\");\n            printAndAccept(x.getTableProperties(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCharExpr x, boolean parameterized) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        String text = x.getText();\n        if (text == null) {\n            print0(ucase ? \"NULL\" : \"null\");\n        } else {\n            StringBuilder buf = new StringBuilder(text.length() + 2);\n            buf.append('\\'');\n            for (int i = 0; i < text.length(); ++i) {\n                char ch = text.charAt(i);\n                switch (ch) {\n                    case '\\\\':\n                        buf.append(\"\\\\\\\\\");\n                        break;\n                    case '\\'':\n                        buf.append(\"\\\\'\");\n                        break;\n                    case '\\0':\n                        buf.append(\"\\\\0\");\n                        break;\n                    case '\\n':\n                        buf.append(\"\\\\n\");\n                        break;\n                    case '\\r':\n                        buf.append(\"\\\\r\");\n                        break;\n                    case '\\b':\n                        buf.append(\"\\\\b\");\n                        break;\n                    case '\\t':\n                        buf.append(\"\\\\t\");\n                        break;\n                    default:\n                        if (ch == '\\u2605') {\n                            buf.append(\"\\\\u2605\");\n                        } else if (ch == '\\u25bc') {\n                            buf.append(\"\\\\u25bc\");\n                        } else {\n                            buf.append(ch);\n                        }\n                        break;\n                }\n            }\n            buf.append('\\'');\n\n            print0(buf.toString());\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    public boolean visit(HiveAddJarStatement x) {\n        print0(ucase ? \"ADD JAR \" : \"add jar \");\n        print0(x.getPath());\n        return false;\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        print0(ucase ? \"TBLPROPERTIES (\" : \"tblproperties (\");\n        incrementIndent();\n        println();\n    }\n\n    public boolean visit(HiveCreateTableStatement x) {\n        return visit((SQLCreateTableStatement) x);\n    }\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        printCreateTable(x, true, true);\n        return false;\n    }\n\n    protected void printCreateTable(SQLCreateTableStatement x, boolean printSelect,\n                                    boolean printCommentAdvance) {\n        final SQLObject parent = x.getParent();\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (parent instanceof SQLAdhocTableSource) {\n            // skip\n        } else {\n            print0(ucase ? \"CREATE \" : \"create \");\n        }\n        printCreateTableFeatures(x);\n        print0(ucase ? \"TABLE \" : \"table \");\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        printTableSourceExpr(x.getName());\n        printTableElements(x.getTableElementList());\n        printInherits(x);\n        if (x instanceof HiveCreateTableStatement) {\n            printUsing((HiveCreateTableStatement) x);\n        }\n        if (printCommentAdvance) {\n            printComment(x.getComment());\n        }\n        if (x instanceof HiveCreateTableStatement) {\n            printMappedBy(((HiveCreateTableStatement) x).getMappedBy());\n        }\n        printPartitionedBy(x);\n        printClusteredBy(x);\n        printSortedBy(x.getSortedBy());\n        printIntoBuckets(x.getBuckets());\n        if (x instanceof HiveCreateTableStatement) {\n            printSkewedBy((HiveCreateTableStatement) x);\n        }\n        if (!printCommentAdvance) {\n            printComment(x.getComment());\n        }\n        printPartitionBy(x);\n        printRowFormat(x);\n        printCreateTableLike(x);\n        printStoredAs(x);\n        printStoredBy(x);\n        printLocation(x);\n        printCached(x);\n        printTableOptions(x);\n        printLifeCycle(x.getLifeCycle());\n        printSelectAs(x, printSelect);\n    }\n\n    protected void printUsing(HiveCreateTableStatement x) {\n        SQLExpr using = x.getUsing();\n        if (using != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            using.accept(this);\n        }\n    }\n\n    protected void printSkewedBy(HiveCreateTableStatement x) {\n        List<SQLExpr> skewedBy = x.getSkewedBy();\n        if (!skewedBy.isEmpty()) {\n            println();\n            print0(ucase ? \"SKEWED BY (\" : \"skewed by (\");\n            printAndAccept(skewedBy, \",\");\n            print(')');\n\n            List<SQLExpr> skewedByOn = x.getSkewedByOn();\n            if (!skewedByOn.isEmpty()) {\n                print0(ucase ? \" ON (\" : \" on (\");\n                printAndAccept(skewedByOn, \",\");\n                print(')');\n            }\n            if (x.isSkewedByStoreAsDirectories()) {\n                print(ucase ? \" STORED AS DIRECTORIES\" : \" stored as directories\");\n            }\n        }\n    }\n\n    protected void printRowFormat(SQLCreateTableStatement x) {\n        SQLExternalRecordFormat format = x.getRowFormat();\n        SQLExpr storedBy = x.getStoredBy();\n        if (format != null) {\n            println();\n            print0(ucase ? \"ROW FORMAT\" : \"row format\");\n            if (format.getSerde() == null) {\n                print0(ucase ? \" DELIMITED\" : \" delimited \");\n            }\n            visit(format);\n            if (storedBy == null) {\n                if (x instanceof HiveCreateTableStatement) {\n                    printSerdeProperties(((HiveCreateTableStatement) x).getSerdeProperties());\n                }\n            }\n        }\n    }\n\n    protected void printStoredBy(SQLCreateTableStatement x) {\n        SQLExpr storedBy = x.getStoredBy();\n        if (storedBy != null) {\n            printStoredBy(storedBy);\n\n            if (x instanceof HiveCreateTableStatement) {\n                Map<String, SQLObject> serdeProperties = ((HiveCreateTableStatement) x).getSerdeProperties();\n                printSerdeProperties(serdeProperties);\n            }\n        }\n    }\n\n    protected void printStoredBy(SQLExpr storedBy) {\n        if (storedBy == null) {\n            return;\n        }\n\n        println();\n        print0(ucase ? \"STORED BY \" : \"stored by \");\n\n        if (storedBy instanceof SQLIdentifierExpr) {\n            String name = ((SQLIdentifierExpr) storedBy).getName();\n            if (!name.isEmpty()\n                    && name.charAt(0) != '`'\n                    && name.charAt(0) != '\"'\n                    && name.charAt(0) != '\\''\n            ) {\n                print('\\'');\n                print(name);\n                print('\\'');\n                return;\n            }\n        }\n\n        printExpr(storedBy, parameterized);\n    }\n\n    protected void printStoredAs(SQLCreateTableStatement x) {\n        SQLExpr storedAs = x.getStoredAs();\n        if (storedAs != null) {\n            println();\n            boolean isHiveCreateTable = x instanceof HiveCreateTableStatement;\n            if (isHiveCreateTable && ((HiveCreateTableStatement) x).isLbracketUse()) {\n                print(\"[\");\n            }\n            print0(ucase ? \"STORED AS\" : \"stored as\");\n            if (storedAs instanceof SQLIdentifierExpr) {\n                print(' ');\n                printExpr(storedAs, parameterized);\n            } else {\n                incrementIndent();\n                println();\n                printExpr(storedAs, parameterized);\n                decrementIndent();\n            }\n\n            if (isHiveCreateTable && ((HiveCreateTableStatement) x).isRbracketUse()) {\n                print(\"]\");\n            }\n        }\n    }\n\n    protected void printSelectAs(SQLCreateTableStatement x, boolean printSelect) {\n        SQLSelect select = x.getSelect();\n        if (printSelect && select != null) {\n            println();\n            if (x instanceof HiveCreateTableStatement && ((HiveCreateTableStatement) x).isLikeQuery()) { // for dla\n                print0(ucase ? \"LIKE\" : \"like\");\n            } else {\n                print0(ucase ? \"AS\" : \"as\");\n            }\n            println();\n            visit(select);\n        }\n    }\n\n    protected void printCached(SQLCreateTableStatement x) {\n        // do nothing\n    }\n\n    protected void printTableElementsWithComment(SQLCreateTableStatement x) {\n        final List<SQLTableElement> tableElementList = x.getTableElementList();\n        int size = tableElementList.size();\n        if (size > 0) {\n            print0(\" (\");\n\n            if (this.isPrettyFormat() && x.hasBodyBeforeComment()) {\n                print(' ');\n                printlnComment(x.getBodyBeforeCommentsDirect());\n            }\n\n            this.indentCount++;\n            println();\n            for (int i = 0; i < size; ++i) {\n                SQLTableElement element = tableElementList.get(i);\n                element.accept(this);\n\n                if (i != size - 1) {\n                    print(',');\n                }\n                if (this.isPrettyFormat() && element.hasAfterComment()) {\n                    print(' ');\n                    printlnComment(element.getAfterCommentsDirect());\n                }\n\n                if (i != size - 1) {\n                    println();\n                }\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.hive.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateFunctionStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveLoadDataStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveMsckRepairStatement;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\npublic class HiveSchemaStatVisitor extends SchemaStatVisitor implements HiveASTVisitor {\n    public HiveSchemaStatVisitor() {\n        super(DbType.hive);\n    }\n\n    public HiveSchemaStatVisitor(DbType dbType) {\n        super(dbType);\n    }\n\n    public HiveSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    @Override\n    public boolean visit(HiveInsert x) {\n        setMode(x, TableStat.Mode.Insert);\n\n        SQLExprTableSource tableSource = x.getTableSource();\n        SQLExpr tableName = tableSource != null ? tableSource.getExpr() : null;\n\n        if (tableName instanceof SQLName) {\n            TableStat stat = getTableStat((SQLName) tableName);\n            stat.incrementInsertCount();\n\n        }\n\n        for (SQLAssignItem partition : x.getPartitions()) {\n            partition.accept(this);\n        }\n\n        accept(x.getQuery());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveMultiInsertStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n        return true;\n    }\n\n    @Override\n    public boolean visit(HiveInsertStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            with.accept(this);\n        }\n\n        setMode(x, TableStat.Mode.Insert);\n\n        SQLExprTableSource tableSource = x.getTableSource();\n        SQLExpr tableName = tableSource.getExpr();\n\n        if (tableName instanceof SQLName) {\n            TableStat stat = getTableStat((SQLName) tableName);\n            stat.incrementInsertCount();\n\n            List<SQLExpr> columns = x.getColumns();\n            for (SQLExpr column : columns) {\n                if (column instanceof SQLIdentifierExpr) {\n                    addColumn((SQLName) tableName, ((SQLIdentifierExpr) column).normalizedName());\n                }\n            }\n        }\n\n        for (SQLAssignItem partition : x.getPartitions()) {\n            partition.accept(this);\n        }\n\n        accept(x.getQuery());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveCreateFunctionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveLoadDataStatement x) {\n        TableStat tableStat = getTableStat(x.getInto());\n        if (tableStat != null) {\n            tableStat.incrementInsertCount();\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveMsckRepairStatement x) {\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hologres/Hologres.java",
    "content": "package com.alibaba.druid.sql.dialect.hologres;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Hologres {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.hologres);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hologres/parser/HologresCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.hologres.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionOf;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGCreateTableParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class HologresCreateTableParser\n        extends PGCreateTableParser {\n    public HologresCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.hologres;\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        boolean isLogical = lexer.nextIfIdentifier(\"LOGICAL\");\n        // For partition of/by for PG\n        for (int i = 0; i < 2; i++) {\n            if (lexer.token() == Token.PARTITION) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (Token.OF.equals(lexer.token())) {\n                    lexer.reset(mark);\n                    SQLPartitionOf partitionOf = parsePartitionOf();\n                    stmt.setPartitionOf(partitionOf);\n                } else if (Token.BY.equals(lexer.token())) {\n                    lexer.reset(mark);\n                    SQLPartitionBy partitionClause = parsePartitionBy();\n                    partitionClause.setLogical(isLogical);\n                    stmt.setPartitionBy(partitionClause);\n                }\n            }\n        }\n\n        if (lexer.nextIf(Token.WITH)) {\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, false);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.nextIf(Token.TABLESPACE)) {\n            stmt.setTablespace(\n                    this.exprParser.name()\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hologres/parser/HologresExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.hologres.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class HologresExprParser\n        extends PGExprParser {\n    public HologresExprParser(String sql, SQLParserFeature... features) {\n        super(new HologresLexer(sql, features));\n        lexer.nextToken();\n        dbType = DbType.hologres;\n    }\n\n    public HologresExprParser(Lexer lexer) {\n        super(lexer);\n        dbType = DbType.hologres;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hologres/parser/HologresLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.hologres.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGLexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class HologresLexer\n        extends PGLexer {\n    public HologresLexer(String input, SQLParserFeature... features) {\n        super(input, features);\n        dbType = DbType.hologres;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hologres/parser/HologresSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.hologres.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\n\npublic class HologresSelectParser\n        extends PGSelectParser {\n    public HologresSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.hologres;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hologres/parser/HologresStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.hologres.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class HologresStatementParser\n        extends PGSQLStatementParser {\n    public HologresStatementParser(HologresExprParser parser) {\n        super(parser);\n        dbType = DbType.hologres;\n    }\n\n    public HologresStatementParser(String sql, SQLParserFeature... features) {\n        this(new HologresExprParser(sql, features));\n    }\n\n    @Override\n    public HologresSelectParser createSQLSelectParser() {\n        return new HologresSelectParser(this.exprParser, selectListCache);\n    }\n\n    public HologresCreateTableParser getSQLCreateTableParser() {\n        return new HologresCreateTableParser(this.exprParser);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/hologres/visitor/HologresOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.hologres.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.clickhouse.ast.CKSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.hologres.Hologres;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;\nimport com.alibaba.druid.sql.parser.CharTypes;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\n\nimport java.util.List;\n\npublic class HologresOutputVisitor extends PGOutputVisitor {\n    public HologresOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.hologres, Hologres.DIALECT, parameterized);\n    }\n\n    public HologresOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.hologres, Hologres.DIALECT);\n    }\n\n    @Override\n    protected void printPartitionBy(SQLCreateTableStatement x) {\n        SQLPartitionBy partitionBy = x.getPartitioning();\n        if (partitionBy == null) {\n            return;\n        }\n        println();\n        if (partitionBy.getLogical() != null && partitionBy.getLogical()) {\n            print0(ucase ? \"LOGICAL \" : \"logical \");\n        }\n        print0(ucase ? \"PARTITION BY \" : \"partition by \");\n        partitionBy.accept(this);\n    }\n\n    @Override\n    protected void printFrom(SQLSelectQueryBlock x) {\n        SQLTableSource from = x.getFrom();\n        if (from == null) {\n            return;\n        }\n\n        List<String> beforeComments = from.getBeforeCommentsDirect();\n        if (beforeComments != null) {\n            for (String comment : beforeComments) {\n                println();\n                print0(comment);\n            }\n        }\n\n        super.printFrom(x);\n        if (x instanceof CKSelectQueryBlock && ((CKSelectQueryBlock) x).isFinal()) {\n            print0(ucase ? \" FINAL\" : \" final\");\n        }\n    }\n\n    @Override\n    public void printComment(String comment) {\n        if (comment == null) {\n            return;\n        }\n\n        if (isEnabled(VisitorFeature.OutputSkipMultilineComment) && comment.startsWith(\"/*\")) {\n            return;\n        }\n\n        if (isEnabled(VisitorFeature.OutputSkipSingleLineComment)\n                && (comment.startsWith(\"-\") || comment.startsWith(\"#\"))) {\n            return;\n        }\n\n        if (comment.startsWith(\"--\")\n                && comment.length() > 2\n                && comment.charAt(2) != ' '\n                && comment.charAt(2) != '-') {\n            print0(\"-- \");\n            print0(comment.substring(2));\n        } else if (comment.startsWith(\"#\")\n                && comment.length() > 1\n                && comment.charAt(1) != ' '\n                && comment.charAt(1) != '#') {\n            print0(\"# \");\n            print0(comment.substring(1));\n        } else if (comment.startsWith(\"/*\")) {\n            println();\n            print0(comment);\n        } else if (comment.startsWith(\"--\")) {\n            print0(comment);\n        }\n\n        char first = '\\0';\n        for (int i = 0; i < comment.length(); i++) {\n            char c = comment.charAt(i);\n            if (CharTypes.isWhitespace(c)) {\n                continue;\n            }\n            first = c;\n            break;\n        }\n\n        if (first == '-' || first == '#') {\n            endLineComment = true;\n        }\n    }\n\n    public void printArrayExprPrefix() {\n        print0(ucase ? \"ARRAY\" : \"array\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/Impala.java",
    "content": "package com.alibaba.druid.sql.dialect.impala;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Impala {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.impala);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/ast/ImpalaSQLPartitionValue.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLPartitionValue;\n\npublic class ImpalaSQLPartitionValue extends SQLPartitionValue {\n    private Integer leftBound;\n    private Integer rightBound;\n    private Operator leftOperator;\n    private Operator rightOperator;\n\n    public ImpalaSQLPartitionValue() {\n        super();\n    }\n    public void setOperator(Operator operator) {\n        this.operator = operator;\n    }\n\n    public Integer getLeftBound() {\n        return leftBound;\n    }\n\n    public void setLeftBound(Integer leftBound) {\n        this.leftBound = leftBound;\n    }\n\n    public Integer getRightBound() {\n        return rightBound;\n    }\n\n    public void setRightBound(Integer rightBound) {\n        this.rightBound = rightBound;\n    }\n\n    public String constructPartitionName() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\"partition_\").append(leftBound != null ? leftBound.toString() : \"\")\n                .append(\"_\").append(rightBound != null ? rightBound.toString() : \"\");\n        return sb.toString();\n    }\n\n    public Operator getLeftOperator() {\n        return leftOperator;\n    }\n\n    public void setLeftOperator(Operator leftOperator) {\n        this.leftOperator = leftOperator;\n    }\n\n    public Operator getRightOperator() {\n        return rightOperator;\n    }\n\n    public void setRightOperator(Operator rightOperator) {\n        this.rightOperator = rightOperator;\n    }\n\n    @Override\n    public ImpalaSQLPartitionValue clone() {\n        ImpalaSQLPartitionValue x = new ImpalaSQLPartitionValue();\n        x.setOperator(operator);\n        x.setLeftBound(leftBound);\n        x.setRightBound(rightBound);\n        x.setLeftOperator(leftOperator);\n        x.setRightOperator(rightOperator);\n        for (SQLExpr item : items) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/parser/ImpalaCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveCreateTableParser;\nimport com.alibaba.druid.sql.dialect.impala.stmt.ImpalaCreateTableStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class ImpalaCreateTableParser extends HiveCreateTableParser {\n    @Override\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new ImpalaCreateTableParser(this.exprParser);\n    }\n\n    public ImpalaCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.impala;\n    }\n\n    public ImpalaCreateTableParser(Lexer lexer) {\n        super(lexer);\n        dbType = DbType.impala;\n    }\n\n    protected ImpalaCreateTableStatement newCreateStatement() {\n        return new ImpalaCreateTableStatement();\n    }\n\n    @Override\n    protected void parseCreateTableRest(SQLCreateTableStatement createTable) {\n        ImpalaCreateTableStatement stmt = (ImpalaCreateTableStatement) createTable;\n\n        if (lexer.nextIf(Token.PARTITIONED)) {\n            accept(Token.BY);\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                if (lexer.token() != Token.IDENTIFIER) {\n                    throw new ParserException(\"expect identifier. \" + lexer.info());\n                }\n\n                SQLColumnDefinition column = this.exprParser.parseColumn();\n                stmt.addPartitionColumn(column);\n\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    column.addAfterComment(lexer.readAndResetComments());\n                }\n\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        column.addAfterComment(lexer.readAndResetComments());\n                    }\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SORT)) {\n            parseSortedBy(stmt);\n        }\n\n        // for kudu table\n        SQLPartitionBy partitionClause = parsePartitionBy();\n        stmt.setPartitionBy(partitionClause);\n        if (lexer.nextIf(Token.COMMENT)) {\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.token() == Token.ROW\n                || lexer.identifierEquals(FnvHash.Constants.ROW)) {\n            parseRowFormat(stmt);\n        }\n\n        if (Token.LBRACKET.equals(lexer.token())) {\n            stmt.setLbracketUse(true);\n            lexer.nextToken();\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n            lexer.nextToken();\n            accept(Token.AS);\n            SQLName name = this.exprParser.name();\n            stmt.setStoredAs(name);\n        }\n\n        if (Token.RBRACKET.equals(lexer.token())) {\n            stmt.setRbracketUse(true);\n            lexer.nextToken();\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.LOCATION)) {\n            lexer.nextToken();\n            SQLExpr location = this.exprParser.primary();\n            stmt.setLocation(location);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.UNCACHED)) {\n            lexer.nextToken();\n            stmt.setUnCached(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CACHED)) {\n            lexer.nextToken();\n            accept(Token.IN);\n            SQLExpr poolName = this.exprParser.primary();\n            stmt.setCachedPool(poolName);\n            if (lexer.hashLCase() == FnvHash.Constants.WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"REPLICATION\");\n                accept(Token.EQ);\n                stmt.setCachedReplication(this.exprParser.parseIntValue());\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n            parseOptions(stmt);\n        }\n\n        if (lexer.token() == Token.SELECT || lexer.token() == Token.AS) {\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n            }\n            SQLSelect select = this.createSQLSelectParser().select();\n            stmt.setSelect(select);\n        }\n\n        if (lexer.token() == Token.SELECT || lexer.token() == Token.AS) {\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n            }\n            SQLSelect select = this.createSQLSelectParser().select();\n            stmt.setSelect(select);\n        }\n\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            Lexer.SavePoint mark = lexer.mark();\n            if (lexer.token() == Token.SELECT) {\n                stmt.setLikeQuery(true);\n                SQLSelect select = this.createSQLSelectParser().select();\n                stmt.setSelect(select);\n            } else {\n                lexer.reset(mark);\n\n                if (lexer.identifierEquals(FnvHash.Constants.MAPPING)) {\n                    SQLExpr like = this.exprParser.primary();\n                    stmt.setLike(new SQLExprTableSource(like));\n                } else {\n                    SQLName name = this.exprParser.name();\n                    stmt.setLike(name);\n                }\n            }\n        }\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USING) || lexer.token() == Token.USING) {\n            lexer.nextToken();\n            SQLExpr using = this.exprParser.expr();\n            stmt.setUsing(using);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n            parseOptions(stmt);\n        }\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        if (lexer.nextIf(Token.PARTITION)) {\n            accept(Token.BY);\n            if (lexer.nextIfIdentifier(FnvHash.Constants.HASH)) {\n                SQLPartitionBy hashPartition = new SQLPartitionByHash();\n                if (lexer.nextIf(Token.LPAREN)) {\n                    // e.g. partition by hash(id,name) partitions 16\n                    // TODO: 'partition by hash(id) partitions 4, hash(name) partitions 4' not supported yet\n                    if (lexer.token() != Token.IDENTIFIER) {\n                        throw new ParserException(\"expect identifier. \" + lexer.info());\n                    }\n                    for (; ; ) {\n                        hashPartition.addColumn(this.exprParser.name());\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    acceptIdentifier(\"PARTITIONS\");\n                    hashPartition.setPartitionsCount(acceptInteger());\n                    return hashPartition;\n                } else {\n                    // e.g. partition by hash partitions 16\n                    acceptIdentifier(\"PARTITIONS\");\n                    int numPartitions = acceptInteger();\n                    hashPartition.setPartitionsCount(numPartitions);\n                    return hashPartition;\n                }\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.RANGE)) {\n                return partitionByRange();\n            }\n        }\n        return null;\n    }\n\n    private SQLPartitionByRange partitionByRange() {\n        SQLPartitionByRange rangePartition = new SQLPartitionByRange();\n        accept(Token.LPAREN);\n        for (; ; ) {\n            rangePartition.addColumn(this.exprParser.name());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        accept(Token.LPAREN);\n        for (; ; ) {\n            if (lexer.token() == Token.RPAREN) {\n                break;\n            }\n            rangePartition.addPartition(this.getExprParser().parsePartition());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        return rangePartition;\n    }\n\n    @Override\n    public ImpalaExprParser getExprParser() {\n        return (ImpalaExprParser) exprParser;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/parser/ImpalaExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLExprHint;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveExprParser;\nimport com.alibaba.druid.sql.dialect.impala.ast.ImpalaSQLPartitionValue;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class ImpalaExprParser extends HiveExprParser {\n    public ImpalaExprParser(Lexer lexer) {\n        super(lexer);\n    }\n    public ImpalaExprParser(String sql, SQLParserFeature... features) {\n        super(new ImpalaLexer(sql, features));\n        this.lexer.nextToken();\n        dbType = DbType.impala;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.nextIfIdentifier(\"ENCODING\")) {\n            column.setEncode(this.expr());\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.COMPRESSION)) {\n            column.setCompression(this.expr());\n        }\n\n        if (lexer.nextIfIdentifier(\"BLOCK_SIZE\")) {\n            column.setBlockSize(this.integerExpr());\n        }\n\n        return super.parseColumnRest(column);\n    }\n\n    public SQLPartitionSingle parsePartition() {\n        accept(Token.PARTITION);\n        SQLPartitionSingle partitionDef = new SQLPartitionSingle();\n        ImpalaSQLPartitionValue values = new ImpalaSQLPartitionValue();\n        SQLName name;\n        if (lexer.token() == Token.LITERAL_INT) {\n            Number number = lexer.integerValue();\n            lexer.nextToken();\n            if (lexer.token() == Token.LT || lexer.token() == Token.LTEQ) {\n                SQLPartitionValue.Operator leftOperator = getOperator(lexer.token());\n                lexer.nextToken();\n                values.setLeftOperator(leftOperator);\n                values.setLeftBound(number.intValue());\n                accept(Token.VALUES);\n                if (lexer.token() == Token.LT || lexer.token() == Token.LTEQ) {\n                    SQLPartitionValue.Operator rightOperator = getOperator(lexer.token());\n                    lexer.nextToken();\n                    values.setRightOperator(rightOperator);\n                    values.setRightBound(lexer.integerValue().intValue());\n                    accept(Token.LITERAL_INT);\n                }\n            }\n        } else if (lexer.token() == Token.VALUES) {\n            accept(Token.VALUES);\n            values.setRightOperator(getOperator(lexer.token()));\n            lexer.nextToken();\n            values.setRightBound(lexer.integerValue().intValue());\n            accept(Token.LITERAL_INT);\n        } else if (lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n            acceptIdentifier(\"VALUE\");\n            accept(Token.EQ);\n            values.setOperator(SQLPartitionValue.Operator.Equal);\n            if (lexer.nextIf(Token.LPAREN)) {\n                // for multiple values\n                for (; ; ) {\n                    if (lexer.token() == Token.LITERAL_INT) {\n                        values.addItem(new SQLIntegerExpr(lexer.integerValue().intValue()));\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        values.addItem(new SQLCharExpr(lexer.stringVal()));\n                        lexer.nextToken();\n                    }\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            } else {\n                // for single specific value\n                SQLCharExpr charExpr = new SQLCharExpr(lexer.stringVal());\n                values.addItem(charExpr);\n                lexer.nextToken();\n            }\n        }\n        partitionDef.setValues(values);\n        name = new SQLIdentifierExpr(values.constructPartitionName());\n        partitionDef.setName(name);\n        return partitionDef;\n    }\n\n    private SQLPartitionValue.Operator getOperator(Token token) {\n        switch (token) {\n            case LT:\n                return SQLPartitionValue.Operator.LessThan;\n            case LTEQ:\n                return SQLPartitionValue.Operator.LessThanEqual;\n            default:\n                return null;\n        }\n    }\n\n    @Override\n    public void parseHints(List hints) {\n        if (lexer.token() == Token.LBRACKET) {\n            lexer.nextToken();\n            hints.add(new SQLExprHint(expr()));\n            accept(Token.RBRACKET);\n        } else {\n            super.parseHints(hints);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/parser/ImpalaLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveLexer;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ImpalaLexer extends HiveLexer {\n    static final Keywords IMPALA_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>(HiveLexer.HIVE_KEYWORDS.getKeywords());\n        map.put(\"UPSERT\", Token.UPSERT);\n        IMPALA_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return IMPALA_KEYWORDS;\n    }\n\n    public ImpalaLexer(String input) {\n        super(input);\n        dbType = DbType.impala;\n    }\n\n    public ImpalaLexer(String input, SQLParserFeature... features) {\n        super(input, features);\n        dbType = DbType.impala;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/parser/ImpalaSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ImpalaSelectParser extends HiveSelectParser {\n    {\n        dbType = DbType.impala;\n    }\n\n    public ImpalaSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    @Override\n    protected SQLExprParser createExprParser() {\n        return new ImpalaExprParser(lexer);\n    }\n\n    @Override\n    protected void parseJoinHint(SQLJoinTableSource join) {\n        List<SQLHint> hints = new ArrayList<>();\n        this.exprParser.parseHints(hints);\n        join.setHints(hints);\n    }\n\n    @Override\n    protected void parseBeforeSelectList(SQLSelectQueryBlock queryBlock) {\n        if (lexer.nextIfIdentifier(\"STRAIGHT_JOIN\")) {\n            queryBlock.setDistionOption(SQLSetQuantifier.STRAIGHT_JOIN);\n        } else {\n            super.parseBeforeSelectList(queryBlock);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/parser/ImpalaStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertInto;\nimport com.alibaba.druid.sql.ast.statement.SQLRefreshTableStatement;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveSelectParser;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser;\nimport com.alibaba.druid.sql.dialect.impala.stmt.ImpalaInsertStatement;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.List;\n\npublic class ImpalaStatementParser extends HiveStatementParser {\n    {\n        dbType = DbType.impala;\n    }\n\n    public ImpalaStatementParser(String sql, SQLParserFeature... features) {\n        super(new ImpalaExprParser(sql, features));\n    }\n\n    public HiveSelectParser createSQLSelectParser() {\n        return new ImpalaSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new ImpalaCreateTableParser(this.exprParser);\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        SQLCreateTableParser parser = new ImpalaCreateTableParser(this.exprParser);\n        return parser.parseCreateTable();\n    }\n\n    @Override\n    public ImpalaExprParser getExprParser() {\n        return (ImpalaExprParser) exprParser;\n    }\n\n    @Override\n    public SQLStatement parseUpsert() {\n        ImpalaInsertStatement insertStatement = new ImpalaInsertStatement();\n\n        if (lexer.token() == Token.UPSERT || lexer.identifierEquals(\"UPSERT\")) {\n            lexer.nextToken();\n            insertStatement.setUpsert(true);\n        }\n\n        parseInsert0(insertStatement);\n        return insertStatement;\n    }\n\n    @Override\n    protected void parseInsert0(SQLInsertInto insertStatement) {\n        parseInsert0Hints(insertStatement, true);\n        parseInsert0(insertStatement, true);\n    }\n\n    @Override\n    protected void parseInsert0Hints(SQLInsertInto insertStatement, boolean isInsert) {\n        if (insertStatement instanceof ImpalaInsertStatement) {\n            ImpalaInsertStatement stmt = (ImpalaInsertStatement) insertStatement;\n            List<SQLHint> hints = isInsert ? stmt.getInsertHints() : stmt.getSelectHints();\n            this.getExprParser().parseHints(hints);\n        }\n    }\n\n    public SQLStatement parseRefresh() {\n        acceptIdentifier(\"REFRESH\");\n        SQLRefreshTableStatement stmt = new SQLRefreshTableStatement();\n        stmt.setDbType(dbType);\n        stmt.setName(this.exprParser.name());\n        if (lexer.nextIf(Token.PARTITION)) {\n            for (; ; ) {\n                SQLAssignItem item = this.exprParser.parseAssignItem(true, stmt);\n                item.setParent(stmt);\n                stmt.getPartitions().add(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/stmt/ImpalaCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\n\npublic class ImpalaCreateTableStatement extends HiveCreateTableStatement {\n    private boolean unCached;\n    private SQLExpr cachedPool;\n    private int cachedReplication = -1;\n\n    public boolean isCached() {\n        return cachedPool != null;\n    }\n\n    public SQLExpr getCachedPool() {\n        return cachedPool;\n    }\n\n    public void setCachedPool(SQLExpr cachedPool) {\n        this.cachedPool = cachedPool;\n    }\n\n    public int getCachedReplication() {\n        return cachedReplication;\n    }\n\n    public void setCachedReplication(int cachedReplication) {\n        this.cachedReplication = cachedReplication;\n    }\n\n    public boolean isUnCached() {\n        return unCached;\n    }\n\n    public void setUnCached(boolean unCached) {\n        this.unCached = unCached;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/stmt/ImpalaInsertStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ImpalaInsertStatement extends HiveInsertStatement {\n    public ImpalaInsertStatement() {\n        this.dbType = DbType.impala;\n    }\n\n    private List<SQLHint> insertHints = new ArrayList<>();\n    private List<SQLHint> selectHints = new ArrayList<>();\n\n    public void cloneTo(ImpalaInsertStatement x) {\n        super.cloneTo(x);\n        for (SQLHint hint : insertHints) {\n            SQLHint h2 = hint.clone();\n            h2.setParent(x);\n            x.insertHints.add(h2);\n        }\n        for (SQLHint hint : selectHints) {\n            SQLHint h2 = hint.clone();\n            h2.setParent(x);\n            x.selectHints.add(h2);\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, with);\n            acceptChild(visitor, insertHints);\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, valuesList);\n            acceptChild(visitor, selectHints);\n            acceptChild(visitor, query);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLHint> getInsertHints() {\n        return insertHints;\n    }\n\n    public void setInsertHints(List<SQLHint> insertHints) {\n        this.insertHints = insertHints;\n    }\n\n    public List<SQLHint> getSelectHints() {\n        return selectHints;\n    }\n\n    public void setSelectHints(List<SQLHint> selectHint) {\n        this.selectHints = selectHint;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/visitor/ImpalaASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.visitor;\n\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.dialect.impala.stmt.ImpalaCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.impala.stmt.ImpalaInsertStatement;\n\npublic interface ImpalaASTVisitor extends HiveASTVisitor {\n    default boolean visit(ImpalaCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(ImpalaCreateTableStatement x) {\n    }\n\n    default boolean visit(ImpalaInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(ImpalaInsertStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/impala/visitor/ImpalaOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.impala.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveOutputVisitor;\nimport com.alibaba.druid.sql.dialect.impala.Impala;\nimport com.alibaba.druid.sql.dialect.impala.ast.ImpalaSQLPartitionValue;\nimport com.alibaba.druid.sql.dialect.impala.stmt.ImpalaCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.impala.stmt.ImpalaInsertStatement;\n\nimport java.util.List;\n\npublic class ImpalaOutputVisitor extends HiveOutputVisitor implements ImpalaASTVisitor {\n    public ImpalaOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.impala, Impala.DIALECT);\n    }\n\n    public ImpalaOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.impala, Impala.DIALECT, parameterized);\n    }\n\n    @Override\n    protected void printJoinHint(SQLJoinTableSource x) {\n        if (!x.getHints().isEmpty()) {\n            print(' ');\n            printHints(x.getHints());\n        }\n    }\n\n    @Override\n    protected void printCached(SQLCreateTableStatement x) {\n        if (x instanceof ImpalaCreateTableStatement) {\n            ImpalaCreateTableStatement createTable = (ImpalaCreateTableStatement) x;\n            if (createTable.isCached()) {\n                println();\n                print0(ucase ? \"CACHED IN \" : \"cached in \");\n                createTable.getCachedPool().accept(this);\n                if (createTable.getCachedReplication() != -1) {\n                    print0(\" WITH REPLICATION = \");\n                    print0(String.valueOf(createTable.getCachedReplication()));\n                }\n            }\n            if (createTable.isUnCached()) {\n                println();\n                print0(ucase ? \"UNCACHED\" : \"uncached\");\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(ImpalaCreateTableStatement x) {\n        printCreateTable(x, true, false);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        if (x instanceof ImpalaCreateTableStatement) {\n            return visit((ImpalaCreateTableStatement) x);\n        }\n        return super.visit(x);\n    }\n\n    @Override\n    public boolean visit(SQLInsertStatement x) {\n        if (x instanceof ImpalaInsertStatement) {\n            return visit((ImpalaInsertStatement) x);\n        }\n        return super.visit(x);\n    }\n\n    @Override\n    public boolean visit(ImpalaInsertStatement x) {\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n\n        if (x.isUpsert()) {\n            print0(ucase ? \"UPSERT \" : \"upsert \");\n            printHint(x, true);\n            print0(ucase ? \"INTO \" : \"into \");\n        } else {\n            print0(ucase ? \"INSERT \" : \"insert \");\n            printHint(x, true);\n            if (x.isOverwrite()) {\n                print0(ucase ? \"OVERWRITE \" : \"overwrite \");\n            } else {\n                print0(ucase ? \"INTO \" : \"into \");\n            }\n        }\n\n        x.getTableSource().accept(this);\n\n        String columnsString = x.getColumnsString();\n        if (columnsString != null) {\n            print0(columnsString);\n        } else {\n            printInsertColumns(x.getColumns());\n        }\n\n        if (!x.getValuesList().isEmpty()) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            printAndAccept(x.getValuesList(), \", \");\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                printHint(x, false);\n                x.getQuery().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    private void printHint(ImpalaInsertStatement x, boolean isInsert) {\n        List<SQLHint> hints = isInsert ? x.getInsertHints() : x.getSelectHints();\n        if (!hints.isEmpty()) {\n            printHints(hints);\n            print(' ');\n        }\n    }\n\n    private void printHints(List<SQLHint> hints) {\n        for (SQLHint hint : hints) {\n            if (hint instanceof SQLCommentHint) {\n                print0((hint).toString());\n            } else if (hint instanceof SQLExprHint) {\n                print0(\"[\");\n                hint.accept(this);\n                print0(\"]\");\n            }\n        }\n    }\n\n    @Override\n    protected void printSortedBy(List<SQLSelectOrderByItem> sortedBy) {\n        if (sortedBy.size() > 0) {\n            println();\n            print0(ucase ? \"SORT BY (\" : \"sort by (\");\n            printAndAccept(sortedBy, \", \");\n            print(')');\n        }\n    }\n\n    @Override\n    protected void printPartitionBy(SQLCreateTableStatement x) {\n        SQLPartitionBy partitionBy = x.getPartitioning();\n        if (partitionBy == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"PARTITION BY \" : \"partition by \");\n        partitionBy.accept(this);\n    }\n\n    @Override\n    public boolean visit(SQLPartitionSingle x) {\n        ImpalaSQLPartitionValue values = (ImpalaSQLPartitionValue) x.getValues();\n        values.accept(this);\n        return false;\n    }\n\n    protected void printEncoding(SQLColumnDefinition x) {\n        if (x.getEncode() != null) {\n            print0(ucase ? \" ENCODING \" : \" encoding \");\n            x.getEncode().accept(this);\n        }\n    }\n\n    protected void printCompression(SQLColumnDefinition x) {\n        if (x.getCompression() != null) {\n            print0(ucase ? \" COMPRESSION \" : \" compression \");\n            x.getCompression().accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLPartitionValue x) {\n        if (x instanceof ImpalaSQLPartitionValue) {\n            ImpalaSQLPartitionValue partitionValue = (ImpalaSQLPartitionValue) x;\n            print0(ucase ? \" PARTITION \" : \" partition \");\n            if (partitionValue.getOperator() == SQLPartitionValue.Operator.Equal) {\n                print0(ucase ? \"VALUE\" : \"value\");\n                print0(\" = \");\n                if (partitionValue.getItems().size() == 1) {\n                    // for single specific value\n                    printExpr(partitionValue.getItems().get(0), parameterized);\n                } else {\n                    print(\"(\");\n                    printAndAccept(partitionValue.getItems(), \", \", false);\n                    print(')');\n                }\n            } else {\n                if (partitionValue.getLeftBound() != null) {\n                    print(partitionValue.getLeftBound());\n                    printOperator(partitionValue.getLeftOperator());\n                }\n                print0(ucase ? \"VALUES\" : \"values\");\n                if (partitionValue.getRightBound() != null) {\n                    printOperator(partitionValue.getRightOperator());\n                    print(partitionValue.getRightBound());\n                }\n            }\n        }\n\n        return false;\n    }\n\n    private void printOperator(SQLPartitionValue.Operator operator) {\n        switch (operator) {\n            case LessThan:\n                print0(\" < \");\n                break;\n            case LessThanEqual:\n                print0(\" <= \");\n                break;\n            case In:\n                print0(\" IN \");\n                break;\n            case List:\n                print0(\" LIST \");\n                break;\n            default:\n                throw new IllegalArgumentException(\"operator not support\");\n        }\n    }\n\n    @Override\n    public void printSqlSetQuantifier(SQLSelectQueryBlock x) {\n        final int distinctOption = x.getDistionOption();\n        if (SQLSetQuantifier.STRAIGHT_JOIN == distinctOption) {\n            print0(ucase ? \"STRAIGHT_JOIN \" : \"straight_join \");\n        } else {\n            super.printSqlSetQuantifier(x);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLRefreshTableStatement x) {\n        print0(ucase ? \"REFRESH \" : \"refresh \");\n        x.getName().accept(this);\n        if (!x.getPartitions().isEmpty()) {\n            print0(ucase ? \" PARTITION \" : \" partition \");\n            printAndAccept(x.getPartitions(), \", \");\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/informix/Informix.java",
    "content": "package com.alibaba.druid.sql.dialect.informix;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Informix {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.informix);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/informix/parser/InformixSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.informix.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class InformixSelectParser\n        extends SQLSelectParser {\n    public InformixSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    protected void querySelectListBefore(SQLSelectQueryBlock queryBlock) {\n        if (lexer.identifierEquals(FnvHash.Constants.SKIP)) {\n            lexer.nextToken();\n            SQLExpr offset = this.exprParser.primary();\n            queryBlock.setOffset(offset);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FIRST)) {\n            lexer.nextToken();\n            SQLExpr first = this.exprParser.primary();\n            queryBlock.setFirst(first);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/informix/parser/InformixStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.informix.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\npublic class InformixStatementParser\n        extends SQLStatementParser {\n    public InformixStatementParser(String sql, SQLParserFeature... features) {\n        super(sql, DbType.informix, features);\n    }\n\n    public InformixSelectParser createSQLSelectParser() {\n        return new InformixSelectParser(this.exprParser, selectListCache);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/informix/visitor/InformixOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.informix.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.informix.Informix;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\npublic class InformixOutputVisitor extends SQLASTOutputVisitor {\n    public InformixOutputVisitor(StringBuilder appender) {\n        this(appender, false);\n    }\n\n    public InformixOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.informix, Informix.DIALECT, parameterized);\n    }\n\n    protected void printSelectListBefore(SQLSelectQueryBlock x) {\n        print(' ');\n\n        SQLLimit limit = x.getLimit();\n        if (limit == null) {\n            return;\n        }\n\n        SQLExpr offset = limit.getOffset();\n        SQLExpr first = limit.getRowCount();\n        if (offset != null) {\n            print0(ucase ? \"SKIP \" : \"skip \");\n            offset.accept(this);\n        }\n\n        print0(ucase ? \" FIRST \" : \" first \");\n        first.accept(this);\n        print(' ');\n    }\n\n    protected void printFetchFirst(SQLSelectQueryBlock x) {\n        // ignore\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/MySQL.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic final class MySQL {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.mysql);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/AnalyzerIndexType.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast;\n\npublic enum AnalyzerIndexType {\n    INDEX, QUERY\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/FullTextType.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast;\n\n/**\n * @author lijun.cailj 2018/8/14\n */\npublic enum FullTextType {\n    CHARFILTER,\n    TOKENIZER,\n    TOKENFILTER,\n    ANALYZER,\n    DICTIONARY\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlForceIndexHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlForceIndexHint extends MySqlIndexHintImpl {\n    public MySqlForceIndexHint() {\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getIndexList());\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlForceIndexHint clone() {\n        MySqlForceIndexHint x = new MySqlForceIndexHint();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLHint;\n\npublic interface MySqlHint extends SQLHint, MySqlObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIgnoreIndexHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlIgnoreIndexHint extends MySqlIndexHintImpl {\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getIndexList());\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlIgnoreIndexHint clone() {\n        MySqlIgnoreIndexHint x = new MySqlIgnoreIndexHint();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIndexHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\npublic interface MySqlIndexHint extends MySqlHint {\n    public static enum Option {\n        JOIN(\"JOIN\"),\n        ORDER_BY(\"ORDER BY\"),\n        GROUP_BY(\"GROUP BY\");\n\n        public final String name;\n        public final String nameLCase;\n\n        Option(String name) {\n            this.name = name;\n            this.nameLCase = name.toLowerCase();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlIndexHintImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\n\npublic abstract class MySqlIndexHintImpl extends MySqlObjectImpl implements MySqlIndexHint {\n    private Option option;\n\n    private List<SQLName> indexList = new ArrayList<SQLName>();\n\n    @Override\n    public abstract void accept0(MySqlASTVisitor visitor);\n\n    public Option getOption() {\n        return option;\n    }\n\n    public void setOption(Option option) {\n        this.option = option;\n    }\n\n    public List<SQLName> getIndexList() {\n        return indexList;\n    }\n\n    public void setIndexList(List<SQLName> indexList) {\n        this.indexList = indexList;\n    }\n\n    public abstract MySqlIndexHintImpl clone();\n\n    public void cloneTo(MySqlIndexHintImpl x) {\n        x.option = option;\n        for (SQLName name : indexList) {\n            SQLName name2 = name.clone();\n            name2.setParent(x);\n            x.indexList.add(name2);\n        }\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (!(o instanceof MySqlIndexHintImpl)) {\n            return false;\n        }\n        MySqlIndexHintImpl that = (MySqlIndexHintImpl) o;\n        return getOption() == that.getOption() && Objects.equals(getIndexList(), that.getIndexList());\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(getOption(), getIndexList());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLIndex;\nimport com.alibaba.druid.sql.ast.statement.SQLTableConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLUnique;\nimport com.alibaba.druid.sql.ast.statement.SQLUniqueConstraint;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlKey extends SQLUnique implements SQLUniqueConstraint, SQLTableConstraint, SQLIndex {\n    public MySqlKey() {\n        dbType = DbType.mysql;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        }\n    }\n\n    protected void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getColumns());\n            acceptChild(visitor, this.getName());\n        }\n        visitor.endVisit(this);\n    }\n\n    public String getIndexType() {\n        return indexDefinition.getOptions().getIndexType();\n    }\n\n    public void setIndexType(String indexType) {\n        indexDefinition.getOptions().setIndexType(indexType);\n    }\n\n    public boolean isHasConstraint() {\n        return indexDefinition.hasConstraint();\n    }\n\n    public void setHasConstraint(boolean hasConstraint) {\n        indexDefinition.setHasConstraint(hasConstraint);\n    }\n\n    public void cloneTo(MySqlKey x) {\n        super.cloneTo(x);\n    }\n\n    public MySqlKey clone() {\n        MySqlKey x = new MySqlKey();\n        cloneTo(x);\n        return x;\n    }\n\n    public SQLExpr getKeyBlockSize() {\n        return indexDefinition.getOptions().getKeyBlockSize();\n    }\n\n    public void setKeyBlockSize(SQLExpr x) {\n        indexDefinition.getOptions().setKeyBlockSize(x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic interface MySqlObject extends SQLObject {\n    void accept0(MySqlASTVisitor v);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlObjectImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class MySqlObjectImpl extends SQLObjectImpl implements MySqlObject {\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) v);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + v.getClass().getName());\n        }\n    }\n\n    public abstract void accept0(MySqlASTVisitor v);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlPrimaryKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlPrimaryKey extends MySqlKey implements SQLPrimaryKey {\n    public MySqlPrimaryKey() {\n        dbType = DbType.mysql;\n    }\n\n    protected void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getColumns());\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlPrimaryKey clone() {\n        MySqlPrimaryKey x = new MySqlPrimaryKey();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlUnique.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlUnique extends MySqlKey {\n    public MySqlUnique() {\n    }\n\n    protected void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getColumns());\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlUnique clone() {\n        MySqlUnique x = new MySqlUnique();\n        cloneTo(x);\n        return x;\n    }\n\n    public SQLExpr getDbPartitionBy() {\n        return indexDefinition.getDbPartitionBy();\n    }\n\n    public void setDbPartitionBy(SQLExpr x) {\n        indexDefinition.setDbPartitionBy(x);\n    }\n\n    public boolean isGlobal() {\n        return indexDefinition.isGlobal();\n    }\n\n    public void setGlobal(boolean global) {\n        indexDefinition.setGlobal(global);\n    }\n\n    public boolean isLocal() {\n        return indexDefinition.isLocal();\n    }\n\n    public void setLocal(boolean local) {\n        indexDefinition.setLocal(local);\n    }\n\n    public SQLExpr getTablePartitions() {\n        return indexDefinition.getTbPartitions();\n    }\n\n    public void setTablePartitions(SQLExpr x) {\n        indexDefinition.setTbPartitions(x);\n    }\n\n    public SQLExpr getTablePartitionBy() {\n        return indexDefinition.getTbPartitionBy();\n    }\n\n    public void setTablePartitionBy(SQLExpr x) {\n        indexDefinition.setTbPartitionBy(x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MySqlUseIndexHint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlUseIndexHint extends MySqlIndexHintImpl {\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getIndexList());\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlUseIndexHint clone() {\n        MySqlUseIndexHint x = new MySqlUseIndexHint();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MysqlForeignKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * @author kiki\n */\npublic class MysqlForeignKey extends SQLForeignKeyImpl {\n    private SQLName indexName;\n    private Match referenceMatch;\n    protected Option onUpdate;\n    protected Option onDelete;\n\n    public MysqlForeignKey() {\n        dbType = DbType.mysql;\n    }\n\n    public SQLName getIndexName() {\n        return indexName;\n    }\n\n    public void setIndexName(SQLName indexName) {\n        this.indexName = indexName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        }\n    }\n\n    protected void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getReferencedTableName());\n            acceptChild(visitor, this.getReferencingColumns());\n            acceptChild(visitor, this.getReferencedColumns());\n\n            acceptChild(visitor, indexName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public MysqlForeignKey clone() {\n        MysqlForeignKey x = new MysqlForeignKey();\n        cloneTo(x);\n\n        if (indexName != null) {\n            x.setIndexName(indexName.clone());\n        }\n\n        x.referenceMatch = referenceMatch;\n        x.onUpdate = onUpdate;\n        x.onDelete = onDelete;\n\n        return x;\n    }\n\n    public Match getReferenceMatch() {\n        return referenceMatch;\n    }\n\n    public void setReferenceMatch(Match referenceMatch) {\n        this.referenceMatch = referenceMatch;\n    }\n\n    public Option getOnUpdate() {\n        return onUpdate;\n    }\n\n    public void setOnUpdate(Option onUpdate) {\n        this.onUpdate = onUpdate;\n    }\n\n    public Option getOnDelete() {\n        return onDelete;\n    }\n\n    public void setOnDelete(Option onDelete) {\n        this.onDelete = onDelete;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/MysqlPartitionSingle.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLPartitionSingle;\nimport com.alibaba.druid.sql.ast.SQLSubPartition;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MysqlPartitionSingle extends SQLPartitionSingle implements MySqlObject {\n    protected SQLExpr dataDirectory;\n    protected SQLExpr indexDirectory;\n    protected SQLExpr maxRows;\n    protected SQLExpr minRows;\n    protected SQLExpr engine;\n    protected SQLExpr comment;\n\n    public SQLExpr getIndexDirectory() {\n        return indexDirectory;\n    }\n\n    public void setIndexDirectory(SQLExpr indexDirectory) {\n        if (indexDirectory != null) {\n            indexDirectory.setParent(this);\n        }\n        this.indexDirectory = indexDirectory;\n    }\n\n    public SQLExpr getDataDirectory() {\n        return dataDirectory;\n    }\n\n    public void setDataDirectory(SQLExpr dataDirectory) {\n        if (dataDirectory != null) {\n            dataDirectory.setParent(this);\n        }\n        this.dataDirectory = dataDirectory;\n    }\n\n    public SQLExpr getMaxRows() {\n        return maxRows;\n    }\n\n    public void setMaxRows(SQLExpr maxRows) {\n        if (maxRows != null) {\n            maxRows.setParent(this);\n        }\n        this.maxRows = maxRows;\n    }\n\n    public SQLExpr getMinRows() {\n        return minRows;\n    }\n\n    public void setMinRows(SQLExpr minRows) {\n        if (minRows != null) {\n            minRows.setParent(this);\n        }\n        this.minRows = minRows;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr engine) {\n        if (engine != null) {\n            engine.setParent(this);\n        }\n        this.engine = engine;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    @Override\n    public MysqlPartitionSingle clone() {\n        MysqlPartitionSingle x = new MysqlPartitionSingle();\n\n        if (name != null) {\n            x.setName(name.clone());\n        }\n\n        if (subPartitionsCount != null) {\n            x.setSubPartitionsCount(subPartitionsCount.clone());\n        }\n\n        for (SQLSubPartition p : subPartitions) {\n            SQLSubPartition p2 = p.clone();\n            p2.setParent(x);\n            x.subPartitions.add(p2);\n        }\n\n        if (values != null) {\n            x.setValues(values.clone());\n        }\n\n        if (dataDirectory != null) {\n            x.setDataDirectory(dataDirectory.clone());\n        }\n        if (indexDirectory != null) {\n            x.setDataDirectory(indexDirectory.clone());\n        }\n        if (maxRows != null) {\n            x.setDataDirectory(maxRows.clone());\n        }\n        if (minRows != null) {\n            x.setDataDirectory(minRows.clone());\n        }\n        if (engine != null) {\n            x.setDataDirectory(engine.clone());\n        }\n        if (comment != null) {\n            x.setDataDirectory(comment.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, values);\n            acceptChild(visitor, dataDirectory);\n            acceptChild(visitor, indexDirectory);\n            acceptChild(visitor, maxRows);\n            acceptChild(visitor, minRows);\n            acceptChild(visitor, engine);\n            acceptChild(visitor, comment);\n            acceptChild(visitor, subPartitionsCount);\n            acceptChild(visitor, subPartitions);\n            acceptChild(visitor, locality);\n            acceptChild(visitor, tablespace);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/ConditionValue.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\n/**\n * @author zhujun [455910092@qq.com]\n * 2016-04-16\n */\npublic class ConditionValue {\n    // type for condition   SQLSTATE | SELF | SYSTEM | mysql_error_code\n    private ConditionType type;\n\n    //value for condition  condition_name | sqlstate | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_code\n    private String value;\n\n    public ConditionType getType() {\n        return type;\n    }\n\n    public void setType(ConditionType type) {\n        this.type = type;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public enum ConditionType {\n        SQLSTATE,\n        SELF,\n        SYSTEM,\n        MYSQL_ERROR_CODE\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLIfStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlCaseStatement extends MySqlStatementImpl {\n    //case expr\n    private SQLExpr condition;\n    //when statement list\n    private List<MySqlWhenStatement> whenList = new ArrayList<MySqlWhenStatement>();\n    //else statement\n    private SQLIfStatement.Else elseItem;\n\n    public SQLExpr getCondition() {\n        return condition;\n    }\n\n    public void setCondition(SQLExpr condition) {\n        this.condition = condition;\n    }\n\n    public List<MySqlWhenStatement> getWhenList() {\n        return whenList;\n    }\n\n    public void setWhenList(List<MySqlWhenStatement> whenList) {\n        this.whenList = whenList;\n    }\n\n    public void addWhenStatement(MySqlWhenStatement stmt) {\n        this.whenList.add(stmt);\n    }\n\n    public SQLIfStatement.Else getElseItem() {\n        return elseItem;\n    }\n\n    public void setElseItem(SQLIfStatement.Else elseItem) {\n        this.elseItem = elseItem;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, condition);\n            acceptChild(visitor, whenList);\n            acceptChild(visitor, elseItem);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<>(whenList);\n        if (elseItem != null) {\n            children.add(elseItem);\n        }\n        return children;\n    }\n\n    /**\n     * case when statement\n     *\n     * @author zz\n     */\n    public static class MySqlWhenStatement extends MySqlObjectImpl {\n        private SQLExpr condition;\n        private List<SQLStatement> statements = new ArrayList<SQLStatement>();\n\n        @Override\n        public void accept0(MySqlASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, condition);\n                acceptChild(visitor, statements);\n            }\n            visitor.endVisit(this);\n        }\n\n        public SQLExpr getCondition() {\n            return condition;\n        }\n\n        public void setCondition(SQLExpr condition) {\n            this.condition = condition;\n        }\n\n        public List<SQLStatement> getStatements() {\n            return statements;\n        }\n\n        public void setStatements(List<SQLStatement> statements) {\n            this.statements = statements;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCursorDeclareStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlCursorDeclareStatement extends MySqlStatementImpl {\n    //cursor name\n    private SQLName cursorName;\n    //select statement\n    private SQLSelect select;\n\n    public SQLName getCursorName() {\n        return cursorName;\n    }\n\n    public void setCursorName(SQLName cursorName) {\n        if (cursorName != null) {\n            cursorName.setParent(this);\n        }\n        this.cursorName = cursorName;\n    }\n\n    public void setCursorName(String cursorName) {\n        this.setCursorName(new SQLIdentifierExpr(cursorName));\n    }\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect select) {\n        if (select != null) {\n            select.setParent(this);\n        }\n        this.select = select;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, select);\n        }\n        visitor.endVisit(this);\n\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareConditionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * @author zhujun [455910092@qq.com]\n */\npublic class MySqlDeclareConditionStatement extends MySqlStatementImpl {\n    private String conditionName;\n    //sp statement\n    private ConditionValue conditionValue;\n\n    public String getConditionName() {\n        return conditionName;\n    }\n\n    public void setConditionName(String conditionName) {\n        this.conditionName = conditionName;\n    }\n\n    public ConditionValue getConditionValue() {\n        return conditionValue;\n    }\n\n    public void setConditionValue(ConditionValue conditionValue) {\n        this.conditionValue = conditionValue;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        // TODO Auto-generated method stub\n        visitor.visit(this);\n        visitor.endVisit(this);\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareHandlerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zhujun [455910092@qq.com]\n */\npublic class MySqlDeclareHandlerStatement extends MySqlStatementImpl {\n    //DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement\n\n    //handler type\n    private MySqlHandlerType handleType;\n    //sp statement\n    private SQLStatement spStatement;\n\n    private List<ConditionValue> conditionValues;\n\n    public MySqlDeclareHandlerStatement() {\n        conditionValues = new ArrayList<ConditionValue>();\n    }\n\n    public List<ConditionValue> getConditionValues() {\n        return conditionValues;\n    }\n\n    public void setConditionValues(List<ConditionValue> conditionValues) {\n        this.conditionValues = conditionValues;\n    }\n\n    public MySqlHandlerType getHandleType() {\n        return handleType;\n    }\n\n    public void setHandleType(MySqlHandlerType handleType) {\n        this.handleType = handleType;\n    }\n\n    public SQLStatement getSpStatement() {\n        return spStatement;\n    }\n\n    public void setSpStatement(SQLStatement spStatement) {\n        this.spStatement = spStatement;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, spStatement);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLDeclareItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlDeclareStatement extends MySqlStatementImpl {\n    private List<SQLDeclareItem> varList = new ArrayList<SQLDeclareItem>();\n\n    public List<SQLDeclareItem> getVarList() {\n        return varList;\n    }\n\n    public void addVar(SQLDeclareItem expr) {\n        varList.add(expr);\n    }\n\n    public void setVarList(List<SQLDeclareItem> varList) {\n        this.varList = varList;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, varList);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return varList;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlExplainType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\npublic enum MySqlExplainType {\n    EXTENDED,\n    PARTITIONS,\n    FORMAT\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlFormatName.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\npublic enum MySqlFormatName {\n    TRADITIONAL,\n    JSON\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlHandlerType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\n/**\n * @author zhujun [zhujunxxxxx@163.com]\n */\npublic enum MySqlHandlerType {\n    //DECLARE处理程序handler_type\n\n    CONTINUE,\n    EXIT,\n    UNDO\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlIterateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlIterateStatement extends MySqlStatementImpl {\n    private String labelName;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getLabelName() {\n        return labelName;\n    }\n\n    public void setLabelName(String labelName) {\n        this.labelName = labelName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlLeaveStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlLeaveStatement extends MySqlStatementImpl {\n    private String labelName;\n\n    public MySqlLeaveStatement() {\n    }\n\n    public MySqlLeaveStatement(String labelName) {\n        this.labelName = labelName;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getLabelName() {\n        return labelName;\n    }\n\n    public void setLabelName(String labelName) {\n        this.labelName = labelName;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>emptyList();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlRepeatStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlRepeatStatement extends MySqlStatementImpl {\n    private String labelName;\n\n    private List<SQLStatement> statements = new ArrayList<SQLStatement>();\n\n    private SQLExpr condition;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statements);\n            acceptChild(visitor, condition);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLStatement> getStatements() {\n        return statements;\n    }\n\n    public void setStatements(List<SQLStatement> statements) {\n        this.statements = statements;\n    }\n\n    public String getLabelName() {\n        return labelName;\n    }\n\n    public void setLabelName(String labelName) {\n        this.labelName = labelName;\n    }\n\n    public SQLExpr getCondition() {\n        return condition;\n    }\n\n    public void setCondition(SQLExpr condition) {\n        this.condition = condition;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlSelectIntoStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlSelectIntoStatement extends MySqlStatementImpl {\n    //select statement\n    private SQLSelect select;\n    //var list\n    private List<SQLExpr> varList = new ArrayList<SQLExpr>();\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect select) {\n        this.select = select;\n    }\n\n    public List<SQLExpr> getVarList() {\n        return varList;\n    }\n\n    public void setVarList(List<SQLExpr> varList) {\n        this.varList = varList;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, select);\n            acceptChild(visitor, varList);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic enum MySqlStatementType {\n    //select statement\n    SELECT(SQLSelectStatement.class.getName()),\n    //update statement\n    UPDATE(MySqlUpdateStatement.class.getName()),\n    //insert statement\n    INSERT(MySqlInsertStatement.class.getName()),\n    //delete statement\n    DELETE(MySqlDeleteStatement.class.getName()),\n    //while statement\n    WHILE(SQLWhileStatement.class.getName()),\n    //begin-end\n    IF(SQLIfStatement.class.getName()),\n    //begin-end\n    LOOP(SQLLoopStatement.class.getName()),\n    //begin-end\n    BLOCK(SQLBlockStatement.class.getName()),\n    //declare statement\n    DECLARE(MySqlDeclareStatement.class.getName()),\n    //select into\n    SELECTINTO(MySqlSelectIntoStatement.class.getName()),\n    //case\n    CASE(MySqlCaseStatement.class.getName()),\n\n    UNDEFINED;\n\n    public final String name;\n\n    MySqlStatementType() {\n        this(null);\n    }\n\n    MySqlStatementType(String name) {\n        this.name = name;\n    }\n\n    public static MySqlStatementType getType(SQLStatement stmt) {\n        String stmtClassName = stmt.getClass().getName();\n        for (MySqlStatementType type : MySqlStatementType.values()) {\n            if (type.name.equals(stmtClassName)) {\n                return type;\n            }\n        }\n        return UNDEFINED;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlCharExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlCharExpr extends SQLCharExpr implements MySqlExpr {\n    private String charset;\n    private String collate;\n\n    private String type;\n    protected boolean parenthesized;\n    public MySqlCharExpr() {\n    }\n\n    public MySqlCharExpr(String text) {\n        super(text);\n    }\n\n    public MySqlCharExpr(String text, String charset) {\n        super(text);\n        this.charset = charset;\n    }\n\n    public MySqlCharExpr(String text, String charset, String collate) {\n        super(text);\n        this.charset = charset;\n        this.collate = collate;\n    }\n\n    public String getCharset() {\n        return charset;\n    }\n\n    public void setCharset(String charset) {\n        this.charset = charset;\n    }\n\n    public String getCollate() {\n        return collate;\n    }\n\n    public void setCollate(String collate) {\n        this.collate = collate;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    @Override\n    public boolean isParenthesized() {\n        return parenthesized;\n    }\n\n    @Override\n    public void setParenthesized(boolean parenthesized) {\n        this.parenthesized = parenthesized;\n    }\n\n    public void output(StringBuilder buf) {\n        if (charset != null) {\n            buf.append(charset);\n            buf.append(' ');\n        }\n        if (super.text != null) {\n            super.output(buf);\n        }\n\n        if (collate != null) {\n            buf.append(\" COLLATE \");\n            buf.append(collate);\n        }\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            visitor.visit(this);\n            visitor.endVisit(this);\n        }\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String toString() {\n        StringBuilder buf = new StringBuilder();\n        output(buf);\n        return buf.toString();\n    }\n\n    public MySqlCharExpr clone() {\n        MySqlCharExpr x = new MySqlCharExpr(text);\n        x.collate = collate;\n        x.charset = charset;\n        x.type = type;\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\n\npublic interface MySqlExpr extends SQLExpr {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlExprImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\n\npublic abstract class MySqlExprImpl extends MySqlObjectImpl implements SQLExpr {\n    protected SQLCommentHint hint;\n\n    public SQLExpr clone() {\n        throw new UnsupportedOperationException();\n    }\n\n    public SQLCommentHint getHint() {\n        return hint;\n    }\n\n    public void setHint(SQLCommentHint hint) {\n        this.hint = hint;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlJSONTableExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlJSONTableExpr extends MySqlExprImpl {\n    private final List<Column> columns = new ArrayList<Column>();\n    private SQLExpr expr;\n    private SQLExpr path;\n\n    @Override\n    public void accept0(MySqlASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, expr);\n            acceptChild(v, path);\n            acceptChild(v, columns);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return null;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.expr = x;\n    }\n\n    public SQLExpr getPath() {\n        return path;\n    }\n\n    public void setPath(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.path = x;\n    }\n\n    public List<Column> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(Column column) {\n        column.setParent(this);\n        this.columns.add(column);\n    }\n\n    public static class Column extends MySqlObjectImpl {\n        private final List<Column> nestedColumns = new ArrayList<Column>();\n        private SQLName name;\n        private SQLDataType dataType;\n        private SQLExpr path;\n        private boolean ordinality;\n        private boolean exists;\n        private SQLExpr onError;\n        private SQLExpr onEmpty;\n\n        @Override\n        public void accept0(MySqlASTVisitor v) {\n            if (v.visit(this)) {\n                acceptChild(v, name);\n                acceptChild(v, dataType);\n                acceptChild(v, path);\n                acceptChild(v, onEmpty);\n                acceptChild(v, onError);\n            }\n            v.endVisit(this);\n        }\n\n        public SQLName getName() {\n            return name;\n        }\n\n        public void setName(SQLName x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.name = x;\n        }\n\n        public SQLDataType getDataType() {\n            return dataType;\n        }\n\n        public void setDataType(SQLDataType x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.dataType = x;\n        }\n\n        public SQLExpr getPath() {\n            return path;\n        }\n\n        public void setPath(SQLExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.path = x;\n        }\n\n        public boolean isOrdinality() {\n            return ordinality;\n        }\n\n        public void setOrdinality(boolean ordinality) {\n            this.ordinality = ordinality;\n        }\n\n        public boolean isExists() {\n            return exists;\n        }\n\n        public void setExists(boolean exists) {\n            this.exists = exists;\n        }\n\n        public SQLExpr getOnError() {\n            return onError;\n        }\n\n        public void setOnError(SQLExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.onError = x;\n        }\n\n        public SQLExpr getOnEmpty() {\n            return onEmpty;\n        }\n\n        public void setOnEmpty(SQLExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.onEmpty = x;\n        }\n\n        public List<Column> getNestedColumns() {\n            return nestedColumns;\n        }\n\n        public void addNestedColumn(Column column) {\n            column.setParent(this);\n            this.nestedColumns.add(column);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlOrderingExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLOrderingSpecification;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class MySqlOrderingExpr extends MySqlExprImpl implements MySqlExpr, SQLReplaceable {\n    protected SQLExpr expr;\n    protected SQLOrderingSpecification type;\n\n    public MySqlOrderingExpr() {\n    }\n\n    public MySqlOrderingExpr(SQLExpr expr, SQLOrderingSpecification type) {\n        super();\n        setExpr(expr);\n        this.type = type;\n    }\n\n    public MySqlOrderingExpr clone() {\n        MySqlOrderingExpr x = new MySqlOrderingExpr();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        x.type = type;\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor mysqlVisitor) {\n        if (mysqlVisitor.visit(this)) {\n            if (expr != null) {\n                expr.accept(mysqlVisitor);\n            }\n        }\n\n        mysqlVisitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.singletonList(this.expr);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public SQLOrderingSpecification getType() {\n        return type;\n    }\n\n    public void setType(SQLOrderingSpecification type) {\n        this.type = type;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        MySqlOrderingExpr other = (MySqlOrderingExpr) obj;\n        if (expr != other.expr) {\n            return false;\n        }\n        if (type == null) {\n            if (other.type != null) {\n                return false;\n            }\n        } else if (!type.equals(other.type)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        result = prime * result + ((type == null) ? 0 : type.hashCode());\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlOutFileExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class MySqlOutFileExpr extends MySqlObjectImpl implements SQLExpr {\n    private SQLExpr file;\n    private String charset;\n\n    private SQLExpr columnsTerminatedBy;\n    private boolean columnsEnclosedOptionally;\n    private SQLLiteralExpr columnsEnclosedBy;\n    private SQLLiteralExpr columnsEscaped;\n\n    private SQLLiteralExpr linesStartingBy;\n    private SQLLiteralExpr linesTerminatedBy;\n\n    private SQLExpr ignoreLinesNumber;\n\n    public MySqlOutFileExpr() {\n    }\n\n    public MySqlOutFileExpr(SQLExpr file) {\n        this.file = file;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, file);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List getChildren() {\n        return Collections.singletonList(file);\n    }\n\n    public SQLExpr getFile() {\n        return file;\n    }\n\n    public void setFile(SQLExpr file) {\n        this.file = file;\n    }\n\n    public String getCharset() {\n        return charset;\n    }\n\n    public void setCharset(String charset) {\n        this.charset = charset;\n    }\n\n    public SQLExpr getColumnsTerminatedBy() {\n        return columnsTerminatedBy;\n    }\n\n    public void setColumnsTerminatedBy(SQLExpr columnsTerminatedBy) {\n        this.columnsTerminatedBy = columnsTerminatedBy;\n    }\n\n    public boolean isColumnsEnclosedOptionally() {\n        return columnsEnclosedOptionally;\n    }\n\n    public void setColumnsEnclosedOptionally(boolean columnsEnclosedOptionally) {\n        this.columnsEnclosedOptionally = columnsEnclosedOptionally;\n    }\n\n    public SQLLiteralExpr getColumnsEnclosedBy() {\n        return columnsEnclosedBy;\n    }\n\n    public void setColumnsEnclosedBy(SQLLiteralExpr columnsEnclosedBy) {\n        this.columnsEnclosedBy = columnsEnclosedBy;\n    }\n\n    public SQLLiteralExpr getColumnsEscaped() {\n        return columnsEscaped;\n    }\n\n    public void setColumnsEscaped(SQLLiteralExpr columnsEscaped) {\n        this.columnsEscaped = columnsEscaped;\n    }\n\n    public SQLLiteralExpr getLinesStartingBy() {\n        return linesStartingBy;\n    }\n\n    public void setLinesStartingBy(SQLLiteralExpr linesStartingBy) {\n        this.linesStartingBy = linesStartingBy;\n    }\n\n    public SQLLiteralExpr getLinesTerminatedBy() {\n        return linesTerminatedBy;\n    }\n\n    public void setLinesTerminatedBy(SQLLiteralExpr linesTerminatedBy) {\n        this.linesTerminatedBy = linesTerminatedBy;\n    }\n\n    public SQLExpr getIgnoreLinesNumber() {\n        return ignoreLinesNumber;\n    }\n\n    public void setIgnoreLinesNumber(SQLExpr ignoreLinesNumber) {\n        this.ignoreLinesNumber = ignoreLinesNumber;\n    }\n\n    public SQLExpr clone() {\n        MySqlOutFileExpr x = new MySqlOutFileExpr();\n\n        if (file != null) {\n            x.setFile(file.clone());\n        }\n\n        x.charset = charset;\n\n        if (columnsTerminatedBy != null) {\n            x.setColumnsTerminatedBy(columnsTerminatedBy.clone());\n        }\n\n        x.columnsEnclosedOptionally = columnsEnclosedOptionally;\n\n        if (columnsEnclosedBy != null) {\n            x.setColumnsEnclosedBy(columnsEnclosedBy.clone());\n        }\n\n        if (columnsEscaped != null) {\n            x.setColumnsEscaped(columnsEscaped.clone());\n        }\n\n        if (linesStartingBy != null) {\n            x.setLinesStartingBy(linesStartingBy.clone());\n        }\n\n        if (linesTerminatedBy != null) {\n            x.setLinesTerminatedBy(linesTerminatedBy.clone());\n        }\n\n        if (ignoreLinesNumber != null) {\n            x.setIgnoreLinesNumber(ignoreLinesNumber.clone());\n        }\n\n        return x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlUserName.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class MySqlUserName extends MySqlExprImpl implements SQLName, Cloneable {\n    private String userName;\n    private String host;\n    private String identifiedBy;\n\n    private long userNameHashCod64;\n    private long hashCode64;\n\n    public String getUserName() {\n        return userName;\n    }\n\n    public void setUserName(String userName) {\n        this.userName = userName;\n\n        this.hashCode64 = 0;\n        this.userNameHashCod64 = 0;\n    }\n\n    public String getNormalizeUserName() {\n        return SQLUtils.normalize(userName);\n    }\n\n    public String getHost() {\n        return host;\n    }\n\n    public void setHost(String host) {\n        this.host = host;\n\n        this.hashCode64 = 0;\n        this.userNameHashCod64 = 0;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getSimpleName() {\n        StringBuilder buf = new StringBuilder();\n\n        if (userName.length() == 0 || userName.charAt(0) != '\\'') {\n            buf.append('\\'');\n            buf.append(userName);\n            buf.append('\\'');\n        } else {\n            buf.append(userName);\n        }\n\n        buf.append('@');\n\n        if (host.length() == 0 || host.charAt(0) != '\\'') {\n            buf.append('\\'');\n            buf.append(host);\n            buf.append('\\'');\n        } else {\n            buf.append(host);\n        }\n\n        if (identifiedBy != null) {\n            buf.append(\" identifiedBy by \");\n            buf.append(identifiedBy);\n        }\n\n        return buf.toString();\n    }\n\n    public String getIdentifiedBy() {\n        return identifiedBy;\n    }\n\n    public void setIdentifiedBy(String identifiedBy) {\n        this.identifiedBy = identifiedBy;\n    }\n\n    public String toString() {\n        return getSimpleName();\n    }\n\n    public MySqlUserName clone() {\n        MySqlUserName x = new MySqlUserName();\n\n        x.userName = userName;\n        x.host = host;\n        x.identifiedBy = identifiedBy;\n        x.hashCode64 = hashCode64;\n        x.userNameHashCod64 = userNameHashCod64;\n\n        return x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    public long nameHashCode64() {\n        if (userNameHashCod64 == 0\n                && userName != null) {\n            userNameHashCod64 = FnvHash.hashCode64(userName);\n        }\n        return userNameHashCod64;\n    }\n\n    @Override\n    public long hashCode64() {\n        if (hashCode64 == 0) {\n            if (host != null) {\n                long hash = FnvHash.hashCode64(host);\n                hash ^= '@';\n                hash *= 0x100000001b3L;\n                hash = FnvHash.hashCode64(hash, userName);\n\n                hashCode64 = hash;\n            } else {\n                hashCode64 = nameHashCode64();\n            }\n        }\n\n        return hashCode64;\n    }\n\n    @Override\n    public SQLColumnDefinition getResolvedColumn() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/CobarShowStatus.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class CobarShowStatus extends MySqlStatementImpl {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsBaselineStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019/9/5 10:48\n */\npublic class DrdsBaselineStatement extends MySqlStatementImpl implements SQLStatement {\n    private String operation;\n    private List<Long> baselineIds = new ArrayList<Long>();\n\n    private SQLSelect select;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getOperation() {\n        return operation;\n    }\n\n    public void setOperation(String operation) {\n        this.operation = operation;\n    }\n\n    public void addBaselineId(long id) {\n        baselineIds.add(id);\n    }\n\n    public List<Long> getBaselineIds() {\n        return baselineIds;\n    }\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect select) {\n        this.select = select;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsCancelDDLJob.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-16 21:45\n */\npublic class DrdsCancelDDLJob extends MySqlStatementImpl implements SQLStatement {\n    private List<Long> jobIds = new ArrayList<Long>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public List<Long> getJobIds() {\n        return jobIds;\n    }\n\n    public void addJobId(long id) {\n        jobIds.add(id);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsChangeDDLJob.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-07-22 17:01\n */\npublic class DrdsChangeDDLJob extends MySqlStatementImpl implements SQLStatement {\n    private long jobId;\n    private boolean skip;\n    private boolean add;\n    private List<String> groupAndTableNameList = new ArrayList<String>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public long getJobId() {\n        return jobId;\n    }\n\n    public void setJobId(long jobId) {\n        this.jobId = jobId;\n    }\n\n    public boolean isSkip() {\n        return skip;\n    }\n\n    public void setSkip(boolean skip) {\n        this.skip = skip;\n    }\n\n    public boolean isAdd() {\n        return add;\n    }\n\n    public void setAdd(boolean add) {\n        this.add = add;\n    }\n\n    public List<String> getGroupAndTableNameList() {\n        return groupAndTableNameList;\n    }\n\n    public void addGroupAndTableNameList(String groupAndTableName) {\n        this.groupAndTableNameList.add(groupAndTableName);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsClearDDLJobCache.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-07-22 10:09\n */\npublic class DrdsClearDDLJobCache extends MySqlStatementImpl implements SQLStatement {\n    private boolean allJobs;\n    private List<Long> jobIds = new ArrayList<Long>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isAllJobs() {\n        return allJobs;\n    }\n\n    public void setAllJobs(boolean allJobs) {\n        this.allJobs = allJobs;\n    }\n\n    public List<Long> getJobIds() {\n        return jobIds;\n    }\n\n    public void addJobId(long id) {\n        jobIds.add(id);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsInspectDDLJobCache.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-07-22 10:06\n */\npublic class DrdsInspectDDLJobCache extends MySqlStatementImpl implements SQLStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsRecoverDDLJob.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-16 22:02\n */\npublic class DrdsRecoverDDLJob extends MySqlStatementImpl implements SQLStatement {\n    private boolean allJobs;\n    private List<Long> jobIds = new ArrayList<Long>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isAllJobs() {\n        return allJobs;\n    }\n\n    public void setAllJobs(boolean allJobs) {\n        this.allJobs = allJobs;\n    }\n\n    public List<Long> getJobIds() {\n        return jobIds;\n    }\n\n    public void addJobId(long id) {\n        jobIds.add(id);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsRemoveDDLJob.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-18 23:41\n */\npublic class DrdsRemoveDDLJob extends MySqlStatementImpl implements SQLStatement {\n    private boolean allCompleted;\n    private boolean allPending;\n    private List<Long> jobIds = new ArrayList<Long>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isAllCompleted() {\n        return allCompleted;\n    }\n\n    public void setAllCompleted(boolean allCompleted) {\n        this.allCompleted = allCompleted;\n    }\n\n    public boolean isAllPending() {\n        return allPending;\n    }\n\n    public void setAllPending(boolean allPending) {\n        this.allPending = allPending;\n    }\n\n    public List<Long> getJobIds() {\n        return jobIds;\n    }\n\n    public void addJobId(long id) {\n        jobIds.add(id);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsRollbackDDLJob.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-18 23:37\n */\npublic class DrdsRollbackDDLJob extends MySqlStatementImpl implements SQLStatement {\n    private List<Long> jobIds = new ArrayList<Long>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public List<Long> getJobIds() {\n        return jobIds;\n    }\n\n    public void addJobId(long id) {\n        jobIds.add(id);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsShowDDLJobs.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLShowStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-16 21:37\n */\npublic class DrdsShowDDLJobs extends MySqlStatementImpl implements SQLShowStatement {\n    private boolean full;\n    private List<Long> jobIds = new ArrayList<Long>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public List<Long> getJobIds() {\n        return jobIds;\n    }\n\n    public void addJobId(long id) {\n        jobIds.add(id);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsShowGlobalIndex.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLShowStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019/10/8 20:06\n */\npublic class DrdsShowGlobalIndex extends MySqlStatementImpl implements SQLShowStatement {\n    private SQLName tableName;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLName getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(SQLName tableName) {\n        tableName.setParent(this);\n        this.tableName = tableName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/DrdsShowMetadataLock.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLShowStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019/10/8 20:08\n */\npublic class DrdsShowMetadataLock extends MySqlStatementImpl implements SQLShowStatement {\n    private SQLName schemaName;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        schemaName.setParent(this);\n        this.schemaName = schemaName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterDatabaseKillJob.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterDatabaseItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterDatabaseKillJob extends MySqlObjectImpl implements SQLAlterDatabaseItem {\n    private SQLName jobType;\n    private SQLName jobId;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, jobType);\n            acceptChild(visitor, jobId);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getJobType() {\n        return jobType;\n    }\n\n    public void setJobType(SQLName jobType) {\n        this.jobType = jobType;\n    }\n\n    public SQLName getJobId() {\n        return jobId;\n    }\n\n    public void setJobId(SQLName jobId) {\n        this.jobId = jobId;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterDatabaseSetOption.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterDatabaseItem;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlAlterDatabaseSetOption extends MySqlObjectImpl implements SQLAlterDatabaseItem {\n    private List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n    private SQLName on;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, options);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getOption(String name) {\n        for (SQLAssignItem item : options) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).getName().equalsIgnoreCase(name)) {\n                    return item.getValue();\n                }\n            }\n        }\n        return null;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public SQLName getOn() {\n        return on;\n    }\n\n    public void setOn(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.on = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterEventStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterEventStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName definer;\n    private SQLName name;\n\n    private MySqlEventSchedule schedule;\n    private boolean onCompletionPreserve;\n    private SQLName renameTo;\n    private Boolean enable;\n    private boolean disableOnSlave;\n    private SQLExpr comment;\n    private SQLStatement eventBody;\n\n    public MySqlAlterEventStatement() {\n        setDbType(DbType.mysql);\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, definer);\n            acceptChild(visitor, name);\n            acceptChild(visitor, schedule);\n            acceptChild(visitor, renameTo);\n            acceptChild(visitor, comment);\n            acceptChild(visitor, eventBody);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getDefiner() {\n        return definer;\n    }\n\n    public void setDefiner(SQLName definer) {\n        if (definer != null) {\n            definer.setParent(this);\n        }\n        this.definer = definer;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public MySqlEventSchedule getSchedule() {\n        return schedule;\n    }\n\n    public void setSchedule(MySqlEventSchedule schedule) {\n        if (schedule != null) {\n            schedule.setParent(this);\n        }\n        this.schedule = schedule;\n    }\n\n    public boolean isOnCompletionPreserve() {\n        return onCompletionPreserve;\n    }\n\n    public void setOnCompletionPreserve(boolean onCompletionPreserve) {\n        this.onCompletionPreserve = onCompletionPreserve;\n    }\n\n    public SQLName getRenameTo() {\n        return renameTo;\n    }\n\n    public void setRenameTo(SQLName renameTo) {\n        if (renameTo != null) {\n            renameTo.setParent(this);\n        }\n        this.renameTo = renameTo;\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public boolean isDisableOnSlave() {\n        return disableOnSlave;\n    }\n\n    public void setDisableOnSlave(boolean disableOnSlave) {\n        this.disableOnSlave = disableOnSlave;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public SQLStatement getEventBody() {\n        return eventBody;\n    }\n\n    public void setEventBody(SQLStatement eventBody) {\n        if (eventBody != null) {\n            eventBody.setParent(this);\n        }\n        this.eventBody = eventBody;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterLogFileGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterLogFileGroupStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n    private SQLExpr addUndoFile;\n    private SQLExpr initialSize;\n    private boolean wait;\n    private SQLExpr engine;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, addUndoFile);\n            acceptChild(visitor, initialSize);\n            acceptChild(visitor, engine);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getAddUndoFile() {\n        return addUndoFile;\n    }\n\n    public void setAddUndoFile(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.addUndoFile = x;\n    }\n\n    public SQLExpr getInitialSize() {\n        return initialSize;\n    }\n\n    public void setInitialSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.initialSize = x;\n    }\n\n    public boolean isWait() {\n        return wait;\n    }\n\n    public void setWait(boolean wait) {\n        this.wait = wait;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr engine) {\n        if (engine != null) {\n            engine.setParent(this);\n        }\n        this.engine = engine;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterServerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterServerStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    // options\n    private SQLExpr user;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getUser() {\n        return user;\n    }\n\n    public void setUser(SQLExpr user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.user = user;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, user);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableAlgorithm.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterTableAlgorithm extends MySqlObjectImpl implements SQLAlterTableItem {\n    private SQLExpr algorithmType;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, algorithmType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getAlgorithmType() {\n        return algorithmType;\n    }\n\n    public void setAlgorithmType(SQLExpr algorithmType) {\n        this.algorithmType = algorithmType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableAlterColumn.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterTableAlterColumn extends MySqlObjectImpl implements SQLAlterTableItem {\n    private SQLName column;\n    private String visibleType;\n    private boolean dropDefault;\n    private SQLExpr defaultExpr;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, column);\n            acceptChild(visitor, defaultExpr);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isDropDefault() {\n        return dropDefault;\n    }\n\n    public void setDropDefault(boolean dropDefault) {\n        this.dropDefault = dropDefault;\n    }\n\n    public String getVisibleType() {\n        return visibleType;\n    }\n\n    public void setVisibleType(String visibleType) {\n        this.visibleType = visibleType;\n    }\n\n    public SQLExpr getDefaultExpr() {\n        return defaultExpr;\n    }\n\n    public void setDefaultExpr(SQLExpr defaultExpr) {\n        this.defaultExpr = defaultExpr;\n    }\n\n    public SQLName getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLName column) {\n        this.column = column;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableAlterFullTextIndex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.AnalyzerIndexType;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterTableAlterFullTextIndex extends MySqlObjectImpl implements SQLAlterTableItem {\n    private SQLName indexName;\n\n    private AnalyzerIndexType analyzerType;\n    private SQLName analyzerName;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, indexName);\n            acceptChild(visitor, analyzerName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getIndexName() {\n        return indexName;\n    }\n\n    public void setIndexName(SQLName indexName) {\n        this.indexName = indexName;\n    }\n\n    public SQLName getAnalyzerName() {\n        return analyzerName;\n    }\n\n    public void setAnalyzerName(SQLName analyzerName) {\n        this.analyzerName = analyzerName;\n    }\n\n    public AnalyzerIndexType getAnalyzerType() {\n        return analyzerType;\n    }\n\n    public void setAnalyzerType(AnalyzerIndexType analyzerType) {\n        this.analyzerType = analyzerType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableChangeColumn.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterTableChangeColumn extends MySqlObjectImpl implements SQLAlterTableItem {\n    private SQLName columnName;\n\n    private SQLColumnDefinition newColumnDefinition;\n\n    private boolean first;\n\n    private SQLName firstColumn;\n    private SQLName afterColumn;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columnName);\n            acceptChild(visitor, newColumnDefinition);\n\n            acceptChild(visitor, firstColumn);\n            acceptChild(visitor, afterColumn);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getFirstColumn() {\n        return firstColumn;\n    }\n\n    public void setFirstColumn(SQLName firstColumn) {\n        this.firstColumn = firstColumn;\n    }\n\n    public SQLName getAfterColumn() {\n        return afterColumn;\n    }\n\n    public void setAfterColumn(SQLName afterColumn) {\n        this.afterColumn = afterColumn;\n    }\n\n    public SQLName getColumnName() {\n        return columnName;\n    }\n\n    public void setColumnName(SQLName columnName) {\n        this.columnName = columnName;\n    }\n\n    public SQLColumnDefinition getNewColumnDefinition() {\n        return newColumnDefinition;\n    }\n\n    public void setNewColumnDefinition(SQLColumnDefinition newColumnDefinition) {\n        this.newColumnDefinition = newColumnDefinition;\n    }\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public void setFirst(boolean first) {\n        this.first = first;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableDiscardTablespace.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlAlterTableDiscardTablespace extends MySqlObjectImpl implements SQLAlterTableItem, MySqlObject {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + visitor.getClass().getName());\n        }\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableForce.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-03 15:43\n */\npublic class MySqlAlterTableForce extends MySqlObjectImpl implements SQLAlterTableItem {\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableImportTablespace.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlAlterTableImportTablespace extends MySqlObjectImpl implements SQLAlterTableItem, MySqlObject {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + visitor.getClass().getName());\n        }\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableLock.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-03 15:50\n */\npublic class MySqlAlterTableLock extends MySqlObjectImpl implements SQLAlterTableItem {\n    private SQLExpr lockType;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, lockType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getLockType() {\n        return lockType;\n    }\n\n    public void setLockType(SQLExpr lockType) {\n        this.lockType = lockType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableModifyColumn.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterTableModifyColumn extends MySqlObjectImpl implements SQLAlterTableItem {\n    private SQLColumnDefinition newColumnDefinition;\n\n    private boolean first;\n\n    private SQLName firstColumn;\n    private SQLName afterColumn;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, newColumnDefinition);\n\n            acceptChild(visitor, firstColumn);\n            acceptChild(visitor, afterColumn);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getFirstColumn() {\n        return firstColumn;\n    }\n\n    public void setFirstColumn(SQLName firstColumn) {\n        this.firstColumn = firstColumn;\n    }\n\n    public SQLName getAfterColumn() {\n        return afterColumn;\n    }\n\n    public void setAfterColumn(SQLName afterColumn) {\n        this.afterColumn = afterColumn;\n    }\n\n    public SQLColumnDefinition getNewColumnDefinition() {\n        return newColumnDefinition;\n    }\n\n    public void setNewColumnDefinition(SQLColumnDefinition newColumnDefinition) {\n        this.newColumnDefinition = newColumnDefinition;\n    }\n\n    public boolean isFirst() {\n        return first;\n    }\n\n    public void setFirst(boolean first) {\n        this.first = first;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableOption.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterTableOption extends MySqlObjectImpl implements SQLAlterTableItem {\n    private String name;\n    private SQLObject value;\n\n    public MySqlAlterTableOption(String name, String value) {\n        this(name, new SQLIdentifierExpr(value));\n    }\n\n    public MySqlAlterTableOption(String name, SQLObject value) {\n        this.name = name;\n        this.setValue(value);\n    }\n\n    public MySqlAlterTableOption() {\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public SQLObject getValue() {\n        return value;\n    }\n\n    public void setValue(SQLObject value) {\n        this.value = value;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableOrderBy.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-03 15:59\n */\npublic class MySqlAlterTableOrderBy extends MySqlObjectImpl implements SQLAlterTableItem {\n    private List<SQLSelectOrderByItem> columns = new ArrayList<SQLSelectOrderByItem>();\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLSelectOrderByItem> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLSelectOrderByItem column) {\n        columns.add(column);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableValidation.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * version 1.0\n * Author zzy\n * Date 2019-06-03 16:22\n */\npublic class MySqlAlterTableValidation extends MySqlObjectImpl implements SQLAlterTableItem {\n    private boolean withValidation;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isWithValidation() {\n        return withValidation;\n    }\n\n    public void setWithValidation(boolean withValidation) {\n        this.withValidation = withValidation;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTablespaceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlAlterTablespaceStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    private SQLExpr addDataFile;\n    private SQLExpr dropDataFile;\n    private SQLExpr initialSize;\n    private boolean wait;\n    private SQLExpr engine;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, addDataFile);\n            acceptChild(visitor, initialSize);\n            acceptChild(visitor, engine);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getAddDataFile() {\n        return addDataFile;\n    }\n\n    public void setAddDataFile(SQLExpr addDataFile) {\n        if (addDataFile != null) {\n            addDataFile.setParent(this);\n        }\n        this.addDataFile = addDataFile;\n    }\n\n    public SQLExpr getDropDataFile() {\n        return dropDataFile;\n    }\n\n    public void setDropDataFile(SQLExpr dropDataFile) {\n        if (dropDataFile != null) {\n            dropDataFile.setParent(this);\n        }\n        this.dropDataFile = dropDataFile;\n    }\n\n    public SQLExpr getInitialSize() {\n        return initialSize;\n    }\n\n    public void setInitialSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.initialSize = x;\n    }\n\n    public boolean isWait() {\n        return wait;\n    }\n\n    public void setWait(boolean wait) {\n        this.wait = wait;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr engine) {\n        if (engine != null) {\n            engine.setParent(this);\n        }\n        this.engine = engine;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterUserStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlAlterUserStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private boolean ifExists;\n\n    private final List<AlterUser> alterUsers = new ArrayList<AlterUser>();\n\n    private PasswordOption passwordOption;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (AlterUser alterUser : alterUsers) {\n                acceptChild(visitor, alterUser.user);\n            }\n            if (passwordOption != null && passwordOption.getIntervalDays() != null) {\n                acceptChild(visitor, passwordOption.getIntervalDays());\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public List<SQLExpr> getUsers() {\n        List<SQLExpr> users = new ArrayList<SQLExpr>();\n        for (AlterUser alterUser : alterUsers) {\n            users.add(alterUser.user);\n        }\n        return users;\n    }\n\n    public List<AlterUser> getAlterUsers() {\n        return alterUsers;\n    }\n\n    public PasswordOption getPasswordOption() {\n        return passwordOption;\n    }\n\n    public void setPasswordOption(PasswordOption passwordOption) {\n        this.passwordOption = passwordOption;\n    }\n\n    public static class AuthOption {\n        private SQLCharExpr authString;\n\n        public SQLCharExpr getAuthString() {\n            return authString;\n        }\n\n        public void setAuthString(SQLCharExpr authString) {\n            this.authString = authString;\n        }\n    }\n\n    public static class AlterUser {\n        private SQLExpr user;\n        private AuthOption authOption;\n\n        private String accountLockOption;\n        public SQLExpr getUser() {\n            return user;\n        }\n\n        public void setUser(SQLExpr user) {\n            this.user = user;\n        }\n\n        public AuthOption getAuthOption() {\n            return authOption;\n        }\n\n        public void setAuthOption(AuthOption authOption) {\n            this.authOption = authOption;\n        }\n\n        public String getAccountLockOption() {\n            return accountLockOption;\n        }\n\n        public void setAccountLockOption(String accountLockOption) {\n            this.accountLockOption = accountLockOption;\n        }\n    }\n\n    public static class PasswordOption {\n        private PasswordExpire expire;\n        private SQLIntegerExpr intervalDays;\n\n        public PasswordExpire getExpire() {\n            return expire;\n        }\n\n        public void setExpire(PasswordExpire expire) {\n            this.expire = expire;\n        }\n\n        public SQLIntegerExpr getIntervalDays() {\n            return intervalDays;\n        }\n\n        public void setIntervalDays(SQLIntegerExpr intervalDays) {\n            this.intervalDays = intervalDays;\n        }\n    }\n\n    public enum PasswordExpire {\n        PASSWORD_EXPIRE,\n        PASSWORD_EXPIRE_DEFAULT,\n        PASSWORD_EXPIRE_NEVER,\n        PASSWORD_EXPIRE_INTERVAL\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAnalyzeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLAnalyzeTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class MySqlAnalyzeStatement extends SQLAnalyzeTableStatement implements MySqlStatement {\n    private boolean noWriteToBinlog;\n    private boolean local;\n\n    public MySqlAnalyzeStatement() {\n        super.dbType = DbType.mysql;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSources);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isNoWriteToBinlog() {\n        return noWriteToBinlog;\n    }\n\n    public void setNoWriteToBinlog(boolean noWriteToBinlog) {\n        this.noWriteToBinlog = noWriteToBinlog;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void addTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSources.add(tableSource);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlBinlogStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlBinlogStatement extends MySqlStatementImpl {\n    private SQLExpr expr;\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCheckTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlCheckTableStatement extends MySqlStatementImpl {\n    private final List<SQLExprTableSource> tables = new ArrayList<SQLExprTableSource>();\n\n    public MySqlCheckTableStatement() {\n    }\n\n    public void addTable(SQLExprTableSource table) {\n        if (table == null) {\n            return;\n        }\n\n        table.setParent(this);\n        tables.add(table);\n    }\n\n    public List<SQLExprTableSource> getTables() {\n        return tables;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tables);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlChecksumTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlChecksumTableStatement extends MySqlStatementImpl {\n    private final List<SQLExprTableSource> tables = new ArrayList<SQLExprTableSource>();\n\n    private boolean quick;\n    private boolean extended;\n\n    public MySqlChecksumTableStatement() {\n    }\n\n    public void addTable(SQLExprTableSource table) {\n        if (table == null) {\n            return;\n        }\n\n        table.setParent(this);\n        tables.add(table);\n    }\n\n    public List<SQLExprTableSource> getTables() {\n        return tables;\n    }\n\n    public boolean isQuick() {\n        return quick;\n    }\n\n    public void setQuick(boolean quick) {\n        this.quick = quick;\n    }\n\n    public boolean isExtended() {\n        return extended;\n    }\n\n    public void setExtended(boolean extended) {\n        this.extended = extended;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tables);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlClearPlanCacheStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlClearPlanCacheStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateAddLogFileGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlCreateAddLogFileGroupStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n    private SQLExpr addUndoFile;\n    private SQLExpr initialSize;\n    private SQLExpr undoBufferSize;\n    private SQLExpr redoBufferSize;\n    private SQLExpr nodeGroup;\n    private boolean wait;\n    private SQLExpr comment;\n    private SQLExpr engine;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getAddUndoFile() {\n        return addUndoFile;\n    }\n\n    public void setAddUndoFile(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.addUndoFile = x;\n    }\n\n    public SQLExpr getInitialSize() {\n        return initialSize;\n    }\n\n    public void setInitialSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.initialSize = x;\n    }\n\n    public SQLExpr getUndoBufferSize() {\n        return undoBufferSize;\n    }\n\n    public void setUndoBufferSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.undoBufferSize = x;\n    }\n\n    public SQLExpr getRedoBufferSize() {\n        return redoBufferSize;\n    }\n\n    public void setRedoBufferSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.redoBufferSize = x;\n    }\n\n    public boolean isWait() {\n        return wait;\n    }\n\n    public void setWait(boolean wait) {\n        this.wait = wait;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr engine) {\n        if (engine != null) {\n            engine.setParent(this);\n        }\n        this.engine = engine;\n    }\n\n    public SQLExpr getNodeGroup() {\n        return nodeGroup;\n    }\n\n    public void setNodeGroup(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.nodeGroup = x;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.comment = x;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, addUndoFile);\n            acceptChild(visitor, initialSize);\n            acceptChild(visitor, undoBufferSize);\n            acceptChild(visitor, redoBufferSize);\n            acceptChild(visitor, nodeGroup);\n            acceptChild(visitor, comment);\n            acceptChild(visitor, engine);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateEventStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlCreateEventStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName definer;\n    private SQLName name;\n\n    private boolean ifNotExists;\n\n    private MySqlEventSchedule schedule;\n    private boolean onCompletionPreserve;\n    private SQLName renameTo;\n    private Boolean enable;\n    private boolean disableOnSlave;\n    private SQLExpr comment;\n    private SQLStatement eventBody;\n\n    public MySqlCreateEventStatement() {\n        setDbType(DbType.mysql);\n    }\n\n    public SQLName getDefiner() {\n        return definer;\n    }\n\n    public void setDefiner(SQLName definer) {\n        if (definer != null) {\n            definer.setParent(this);\n        }\n        this.definer = definer;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public MySqlEventSchedule getSchedule() {\n        return schedule;\n    }\n\n    public void setSchedule(MySqlEventSchedule schedule) {\n        if (schedule != null) {\n            schedule.setParent(this);\n        }\n        this.schedule = schedule;\n    }\n\n    public boolean isOnCompletionPreserve() {\n        return onCompletionPreserve;\n    }\n\n    public void setOnCompletionPreserve(boolean onCompletionPreserve) {\n        this.onCompletionPreserve = onCompletionPreserve;\n    }\n\n    public SQLName getRenameTo() {\n        return renameTo;\n    }\n\n    public void setRenameTo(SQLName renameTo) {\n        if (renameTo != null) {\n            renameTo.setParent(this);\n        }\n        this.renameTo = renameTo;\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public boolean isDisableOnSlave() {\n        return disableOnSlave;\n    }\n\n    public void setDisableOnSlave(boolean disableOnSlave) {\n        this.disableOnSlave = disableOnSlave;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public SQLStatement getEventBody() {\n        return eventBody;\n    }\n\n    public void setEventBody(SQLStatement eventBody) {\n        if (eventBody != null) {\n            eventBody.setParent(this);\n        }\n        this.eventBody = eventBody;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, definer);\n            acceptChild(visitor, name);\n            acceptChild(visitor, schedule);\n            acceptChild(visitor, renameTo);\n            acceptChild(visitor, comment);\n            acceptChild(visitor, eventBody);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateExternalCatalogStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class MySqlCreateExternalCatalogStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n\n    private boolean ifNotExists;\n\n    private Map<SQLName, SQLName> properties = new HashMap<SQLName, SQLName>();\n    private SQLName comment;\n\n    public MySqlCreateExternalCatalogStatement() {\n        setDbType(DbType.mysql);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLName getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLName comment) {\n        if (comment != null) {\n            comment.setParent(this);\n        }\n        this.comment = comment;\n    }\n\n    public Map<SQLName, SQLName> getProperties() {\n        return properties;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, comment);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateServerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlCreateServerStatement extends MySqlStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n    private SQLName foreignDataWrapper;\n    private SQLExpr host;\n    private SQLExpr database;\n    private SQLExpr user;\n    private SQLExpr password;\n    private SQLExpr socket;\n    private SQLExpr owner;\n    private SQLExpr port;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLName getForeignDataWrapper() {\n        return foreignDataWrapper;\n    }\n\n    public void setForeignDataWrapper(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.foreignDataWrapper = x;\n    }\n\n    public SQLExpr getHost() {\n        return host;\n    }\n\n    public void setHost(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.host = x;\n    }\n\n    public SQLExpr getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.database = x;\n    }\n\n    public SQLExpr getUser() {\n        return user;\n    }\n\n    public void setUser(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.user = x;\n    }\n\n    public SQLExpr getPassword() {\n        return password;\n    }\n\n    public void setPassword(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.password = x;\n    }\n\n    public SQLExpr getSocket() {\n        return socket;\n    }\n\n    public void setSocket(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.socket = x;\n    }\n\n    public SQLExpr getOwner() {\n        return owner;\n    }\n\n    public void setOwner(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.owner = x;\n    }\n\n    public SQLExpr getPort() {\n        return port;\n    }\n\n    public void setPort(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.port = x;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, foreignDataWrapper);\n            acceptChild(visitor, host);\n            acceptChild(visitor, database);\n            acceptChild(visitor, user);\n            acceptChild(visitor, password);\n            acceptChild(visitor, socket);\n            acceptChild(visitor, owner);\n            acceptChild(visitor, port);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableSpaceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlCreateTableSpaceStatement extends MySqlStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n    private SQLExpr addDataFile;\n    private SQLExpr initialSize;\n    private SQLExpr extentSize;\n    private SQLExpr autoExtentSize;\n    private SQLExpr fileBlockSize;\n    private SQLExpr logFileGroup;\n    private SQLExpr maxSize;\n    private SQLExpr nodeGroup;\n    private boolean wait;\n    private SQLExpr comment;\n    private SQLExpr engine;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, addDataFile);\n            acceptChild(visitor, initialSize);\n            acceptChild(visitor, extentSize);\n            acceptChild(visitor, autoExtentSize);\n            acceptChild(visitor, fileBlockSize);\n            acceptChild(visitor, logFileGroup);\n            acceptChild(visitor, maxSize);\n            acceptChild(visitor, nodeGroup);\n            acceptChild(visitor, comment);\n            acceptChild(visitor, engine);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLExpr getAddDataFile() {\n        return addDataFile;\n    }\n\n    public void setAddDataFile(SQLExpr addDataFile) {\n        if (addDataFile != null) {\n            addDataFile.setParent(this);\n        }\n        this.addDataFile = addDataFile;\n    }\n\n    public SQLExpr getInitialSize() {\n        return initialSize;\n    }\n\n    public void setInitialSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.initialSize = x;\n    }\n\n    public SQLExpr getFileBlockSize() {\n        return fileBlockSize;\n    }\n\n    public void setFileBlockSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.fileBlockSize = x;\n    }\n\n    public boolean isWait() {\n        return wait;\n    }\n\n    public void setWait(boolean wait) {\n        this.wait = wait;\n    }\n\n    public SQLExpr getEngine() {\n        return engine;\n    }\n\n    public void setEngine(SQLExpr engine) {\n        if (engine != null) {\n            engine.setParent(this);\n        }\n        this.engine = engine;\n    }\n\n    public SQLExpr getLogFileGroup() {\n        return logFileGroup;\n    }\n\n    public void setLogFileGroup(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.logFileGroup = x;\n    }\n\n    public SQLExpr getExtentSize() {\n        return extentSize;\n    }\n\n    public void setExtentSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.extentSize = x;\n    }\n\n    public SQLExpr getAutoExtentSize() {\n        return autoExtentSize;\n    }\n\n    public void setAutoExtentSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.autoExtentSize = x;\n    }\n\n    public SQLExpr getMaxSize() {\n        return maxSize;\n    }\n\n    public void setMaxSize(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.maxSize = x;\n    }\n\n    public SQLExpr getNodeGroup() {\n        return nodeGroup;\n    }\n\n    public void setNodeGroup(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.nodeGroup = x;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.comment = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExprImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlShowColumnOutpuVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class MySqlCreateTableStatement extends SQLCreateTableStatement implements MySqlStatement {\n    private List<SQLCommentHint> hints = new ArrayList<SQLCommentHint>();\n    private List<SQLCommentHint> optionHints = new ArrayList<SQLCommentHint>();\n    private SQLName tableGroup;\n    //for drds\n    protected SQLExpr dbPartitionBy;\n    //for drds\n    protected SQLExpr dbPartitions;\n    //for drds\n    protected SQLExpr tablePartitionBy;\n    //for drds\n    protected SQLExpr tablePartitions;\n    //for drds\n    protected MySqlExtPartition exPartition;\n    // for ads\n    protected SQLName storedBy;\n    // for ads\n    protected SQLName distributeByType;\n    protected List<SQLName> distributeBy = new ArrayList<SQLName>();\n    protected boolean isBroadCast;\n    // for ads\n    protected Map<String, SQLName> with = new HashMap<String, SQLName>(3);\n\n    protected SQLStatement withSelect;\n    // adb\n    protected SQLName archiveBy;\n    protected Boolean withData;\n\n    protected Boolean single;\n\n    public MySqlCreateTableStatement() {\n        super(DbType.mysql);\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public SQLStatement getWithSelect() {\n        return withSelect;\n    }\n\n    public void setWithSelect(SQLStatement withSelect) {\n        this.withSelect = withSelect;\n    }\n\n    @Deprecated\n    public SQLSelect getQuery() {\n        return select;\n    }\n\n    @Deprecated\n    public void setQuery(SQLSelect query) {\n        this.select = query;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < hints.size(); i++) {\n                final SQLCommentHint hint = hints.get(i);\n                if (hint != null) {\n                    hint.accept(visitor);\n                }\n            }\n\n            if (tableSource != null) {\n                tableSource.accept(visitor);\n            }\n\n            for (int i = 0; i < tableElementList.size(); i++) {\n                final SQLTableElement element = tableElementList.get(i);\n                if (element != null) {\n                    element.accept(visitor);\n                }\n            }\n\n            if (like != null) {\n                like.accept(visitor);\n            }\n\n            if (select != null) {\n                select.accept(visitor);\n            }\n            if (withSelect != null) {\n                withSelect.accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public static class TableSpaceOption extends MySqlExprImpl {\n        private SQLName name;\n        private SQLExpr storage;\n\n        public SQLName getName() {\n            return name;\n        }\n\n        public void setName(SQLName name) {\n            if (name != null) {\n                name.setParent(this);\n            }\n            this.name = name;\n        }\n\n        public SQLExpr getStorage() {\n            return storage;\n        }\n\n        public void setStorage(SQLExpr storage) {\n            if (storage != null) {\n                storage.setParent(this);\n            }\n            this.storage = storage;\n        }\n\n        @Override\n        public void accept0(MySqlASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, getName());\n                acceptChild(visitor, getStorage());\n            }\n            visitor.endVisit(this);\n        }\n\n        public TableSpaceOption clone() {\n            TableSpaceOption x = new TableSpaceOption();\n\n            if (name != null) {\n                x.setName(name.clone());\n            }\n\n            if (storage != null) {\n                x.setStorage(storage.clone());\n            }\n\n            return x;\n        }\n\n        @Override\n        public List<SQLObject> getChildren() {\n            return null;\n        }\n\n    }\n\n    public List<SQLCommentHint> getOptionHints() {\n        return optionHints;\n    }\n\n    public void setOptionHints(List<SQLCommentHint> optionHints) {\n        this.optionHints = optionHints;\n    }\n\n    public SQLName getTableGroup() {\n        return tableGroup;\n    }\n\n    public void setTableGroup(SQLName tableGroup) {\n        this.tableGroup = tableGroup;\n    }\n\n    public void setTableGroup(String tableGroup) {\n        if (StringUtils.isEmpty(tableGroup)) {\n            this.tableGroup = null;\n        } else {\n            this.tableGroup = new SQLIdentifierExpr(tableGroup);\n        }\n    }\n\n    @Override\n    public void simplify() {\n        tableOptions.clear();\n//        tblProperties.clear();\n        super.simplify();\n    }\n\n    public void showColumns(StringBuilder out) throws IOException {\n        this.accept(new MySqlShowColumnOutpuVisitor(out));\n    }\n\n    public List<MySqlKey> getMysqlKeys() {\n        List<MySqlKey> mySqlKeys = new ArrayList<MySqlKey>();\n        for (SQLTableElement element : this.getTableElementList()) {\n            if (element instanceof MySqlKey) {\n                mySqlKeys.add((MySqlKey) element);\n            }\n        }\n        return mySqlKeys;\n    }\n\n    public List<MySqlTableIndex> getMysqlIndexes() {\n        List<MySqlTableIndex> indexList = new ArrayList<MySqlTableIndex>();\n        for (SQLTableElement element : this.getTableElementList()) {\n            if (element instanceof MySqlTableIndex) {\n                indexList.add((MySqlTableIndex) element);\n            }\n        }\n        return indexList;\n    }\n\n    public boolean apply(MySqlRenameTableStatement x) {\n        for (MySqlRenameTableStatement.Item item : x.getItems()) {\n            if (apply(item)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    protected boolean alterApply(SQLAlterTableItem item) {\n        if (item instanceof MySqlAlterTableAlterColumn) {\n            return apply((MySqlAlterTableAlterColumn) item);\n\n        } else if (item instanceof MySqlAlterTableChangeColumn) {\n            return apply((MySqlAlterTableChangeColumn) item);\n\n        } else if (item instanceof SQLAlterCharacter) {\n            return apply((SQLAlterCharacter) item);\n\n        } else if (item instanceof MySqlAlterTableModifyColumn) {\n            return apply((MySqlAlterTableModifyColumn) item);\n\n        } else if (item instanceof MySqlAlterTableOption) {\n            return apply((MySqlAlterTableOption) item);\n        }\n\n        return super.alterApply(item);\n    }\n\n    public boolean apply(SQLAlterTableAddIndex item) {\n        SQLName name = item.getIndexDefinition().getName();\n        if (name != null) {\n            long nameHashCode = name.nameHashCode64();\n            for (int i = 0; i < tableElementList.size(); i++) {\n                SQLTableElement e = tableElementList.get(i);\n                if (e instanceof MySqlTableIndex) {\n                    SQLName name1 = ((MySqlTableIndex) e).getName();\n                    if (name1 != null && name1.nameHashCode64() == nameHashCode) {\n                        return false;\n                    }\n                }\n            }\n        }\n\n        if (item.isUnique()) {\n            MySqlUnique x = new MySqlUnique();\n            item.cloneTo(x);\n            x.setParent(this);\n            this.tableElementList.add(x);\n            return true;\n        }\n\n        if (item.isKey()) {\n            MySqlKey x = new MySqlKey();\n            item.cloneTo(x);\n            x.setParent(this);\n            this.tableElementList.add(x);\n            return true;\n        }\n\n        MySqlTableIndex x = new MySqlTableIndex();\n        item.cloneTo(x);\n        x.setParent(this);\n        this.tableElementList.add(x);\n        return true;\n    }\n\n    public boolean apply(MySqlAlterTableOption item) {\n        addOption(item.getName(), (SQLExpr) item.getValue());\n        return true;\n    }\n\n    public boolean apply(SQLAlterCharacter item) {\n        SQLExpr charset = item.getCharacterSet();\n        if (charset != null) {\n            addOption(\"CHARACTER SET\", charset);\n        }\n\n        SQLExpr collate = item.getCollate();\n        if (collate != null) {\n            addOption(\"COLLATE\", collate);\n        }\n        return true;\n    }\n\n    public boolean apply(MySqlRenameTableStatement.Item item) {\n        if (!SQLUtils.nameEquals((SQLName) item.getName(), this.getName())) {\n            return false;\n        }\n        this.setName((SQLName) item.getTo().clone());\n        return true;\n    }\n\n    public boolean apply(MySqlAlterTableAlterColumn x) {\n        int columnIndex = columnIndexOf(x.getColumn());\n        if (columnIndex == -1) {\n            return false;\n        }\n\n        SQLExpr defaultExpr = x.getDefaultExpr();\n        SQLColumnDefinition column = (SQLColumnDefinition) tableElementList.get(columnIndex);\n\n        if (x.isDropDefault()) {\n            column.setDefaultExpr(null);\n        } else if (defaultExpr != null) {\n            column.setDefaultExpr(defaultExpr);\n        }\n\n        return true;\n    }\n\n    public boolean apply(MySqlAlterTableChangeColumn item) {\n        SQLName columnName = item.getColumnName();\n        int columnIndex = columnIndexOf(columnName);\n        if (columnIndex == -1) {\n            return false;\n        }\n\n        int afterIndex = columnIndexOf(item.getAfterColumn());\n        int beforeIndex = columnIndexOf(item.getFirstColumn());\n\n        int insertIndex = -1;\n        if (beforeIndex != -1) {\n            insertIndex = beforeIndex;\n        } else if (afterIndex != -1) {\n            insertIndex = afterIndex + 1;\n        } else if (item.isFirst()) {\n            insertIndex = 0;\n        }\n\n        SQLColumnDefinition column = item.getNewColumnDefinition().clone();\n        column.setParent(this);\n        if (insertIndex == -1 || insertIndex == columnIndex) {\n            tableElementList.set(columnIndex, column);\n        } else {\n            if (insertIndex > columnIndex) {\n                tableElementList.add(insertIndex, column);\n                tableElementList.remove(columnIndex);\n            } else {\n                tableElementList.remove(columnIndex);\n                tableElementList.add(insertIndex, column);\n            }\n        }\n\n        for (int i = 0; i < tableElementList.size(); i++) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof MySqlTableIndex) {\n                ((MySqlTableIndex) e).applyColumnRename(columnName, column);\n            } else if (e instanceof SQLUnique) {\n                SQLUnique unique = (SQLUnique) e;\n                unique.applyColumnRename(columnName, column);\n            }\n        }\n\n        return true;\n    }\n\n    public boolean apply(MySqlAlterTableModifyColumn item) {\n        SQLColumnDefinition column = item.getNewColumnDefinition().clone();\n        SQLName columnName = column.getName();\n\n        int columnIndex = columnIndexOf(columnName);\n        if (columnIndex == -1) {\n            return false;\n        }\n\n        int afterIndex = columnIndexOf(item.getAfterColumn());\n        int beforeIndex = columnIndexOf(item.getFirstColumn());\n\n        int insertIndex = -1;\n        if (beforeIndex != -1) {\n            insertIndex = beforeIndex;\n        } else if (afterIndex != -1) {\n            insertIndex = afterIndex + 1;\n        }\n\n        if (item.isFirst()) {\n            insertIndex = 0;\n        }\n\n        column.setParent(this);\n        if (insertIndex == -1 || insertIndex == columnIndex) {\n            tableElementList.set(columnIndex, column);\n            return true;\n        } else {\n            if (insertIndex > columnIndex) {\n                tableElementList.add(insertIndex, column);\n                tableElementList.remove(columnIndex);\n            } else {\n                tableElementList.remove(columnIndex);\n                tableElementList.add(insertIndex, column);\n            }\n        }\n\n        // Check key length like change.\n        // Just old name -> old name.\n        for (int i = 0; i < tableElementList.size(); i++) {\n            SQLTableElement e = tableElementList.get(i);\n            if (e instanceof MySqlTableIndex) {\n                ((MySqlTableIndex) e).applyColumnRename(columnName, column);\n            } else if (e instanceof SQLUnique) {\n                SQLUnique unique = (SQLUnique) e;\n                unique.applyColumnRename(columnName, column);\n            }\n        }\n\n        return true;\n    }\n\n    public void cloneTo(MySqlCreateTableStatement x) {\n        super.cloneTo(x);\n        if (partitionBy != null) {\n            x.setPartitionBy(partitionBy.clone());\n        }\n        if (localPartitioning != null) {\n            x.setLocalPartitioning(localPartitioning.clone());\n        }\n        for (SQLCommentHint hint : hints) {\n            SQLCommentHint h2 = hint.clone();\n            h2.setParent(x);\n            x.hints.add(h2);\n        }\n        for (SQLCommentHint hint : optionHints) {\n            SQLCommentHint h2 = hint.clone();\n            h2.setParent(x);\n            x.optionHints.add(h2);\n        }\n        if (like != null) {\n            x.setLike(like.clone());\n        }\n        if (tableGroup != null) {\n            x.setTableGroup(tableGroup.clone());\n        }\n\n        if (dbPartitionBy != null) {\n            x.setDbPartitionBy(dbPartitionBy.clone());\n        }\n\n        if (dbPartitions != null) {\n            x.setDbPartitionBy(dbPartitions.clone());\n        }\n\n        if (tablePartitionBy != null) {\n            x.setTablePartitionBy(tablePartitionBy.clone());\n        }\n\n        if (tablePartitions != null) {\n            x.setTablePartitions(tablePartitions.clone());\n        }\n\n        if (exPartition != null) {\n            x.setExPartition(exPartition.clone());\n        }\n\n        if (archiveBy != null) {\n            x.setArchiveBy(archiveBy.clone());\n        }\n\n        if (distributeByType != null) {\n            x.setDistributeByType(distributeByType.clone());\n        }\n\n        if (distributeByType != null) {\n            for (SQLName sqlName : distributeBy) {\n                x.getDistributeBy().add(sqlName.clone());\n            }\n        }\n\n        if (single != null) {\n            x.setSingle(single);\n        }\n\n    }\n\n    public MySqlCreateTableStatement clone() {\n        MySqlCreateTableStatement x = new MySqlCreateTableStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    public SQLExpr getDbPartitionBy() {\n        return dbPartitionBy;\n    }\n\n    public void setDbPartitionBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.dbPartitionBy = x;\n    }\n\n    public SQLExpr getTablePartitionBy() {\n        return tablePartitionBy;\n    }\n\n    public void setTablePartitionBy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.tablePartitionBy = x;\n    }\n\n    public SQLName getDistributeByType() {\n        return distributeByType;\n    }\n\n    public void setDistributeByType(SQLName distributeByType) {\n        this.distributeByType = distributeByType;\n    }\n\n    public List<SQLName> getDistributeBy() {\n        return distributeBy;\n    }\n\n    public SQLExpr getTbpartitions() {\n        return tablePartitions;\n    }\n\n    public SQLExpr getTablePartitions() {\n        return tablePartitions;\n    }\n\n    public void setTablePartitions(SQLExpr x) {\n        this.tablePartitions = x;\n    }\n\n    public SQLExpr getDbpartitions() {\n        return dbPartitions;\n    }\n\n    public void setDbPartitions(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.dbPartitions = x;\n    }\n\n    public MySqlExtPartition getExtPartition() {\n        return exPartition;\n    }\n\n    public void setExPartition(MySqlExtPartition x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.exPartition = x;\n    }\n\n    public SQLExpr getDbPartitions() {\n        return dbPartitions;\n    }\n\n    public SQLName getStoredBy() {\n        return storedBy;\n    }\n\n    public void setStoredBy(SQLName storedBy) {\n        this.storedBy = storedBy;\n    }\n\n    public Map<String, SQLName> getWith() {\n        return with;\n    }\n\n    public boolean isBroadCast() {\n        return isBroadCast;\n    }\n\n    public void setBroadCast(boolean broadCast) {\n        isBroadCast = broadCast;\n    }\n\n    public SQLName getArchiveBy() {\n        return archiveBy;\n    }\n\n    public void setArchiveBy(SQLName archiveBy) {\n        this.archiveBy = archiveBy;\n    }\n\n    public Boolean getWithData() {\n        return withData;\n    }\n\n    public void setWithData(Boolean withData) {\n        this.withData = withData;\n    }\n\n    public SQLExpr getEngine() {\n        return getOption(\"ENGINE\");\n    }\n\n    public void setEngine(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        addOption(\"ENGINE\", x);\n    }\n\n    public void setPageChecksum(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        addOption(\"PAGE_CHECKSUM\", x);\n    }\n\n    public void setTransactional(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        addOption(\"TRANSACTIONAL\", x);\n    }\n\n    public Boolean getSingle() {\n        return single;\n    }\n\n    public void setSingle(Boolean single) {\n        this.single = single;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlCreateUserStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlCreateUserStatement extends MySqlStatementImpl implements SQLCreateStatement {\n    private List<UserSpecification> users = new ArrayList<UserSpecification>(2);\n\n    private boolean ifNotExists;\n\n    public List<UserSpecification> getUsers() {\n        return users;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public void addUser(UserSpecification user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.users.add(user);\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, users);\n        }\n        visitor.endVisit(this);\n    }\n\n    public static class UserSpecification extends MySqlObjectImpl {\n        private SQLExpr user;\n        private boolean passwordHash;\n        private boolean randomPassword;\n        private SQLExpr password;\n        private SQLExpr authPlugin;\n        private boolean pluginAs;\n\n        public SQLExpr getUser() {\n            return user;\n        }\n\n        public void setUser(SQLExpr user) {\n            this.user = (SQLName) user;\n        }\n\n        public boolean isRandomPassword() {\n            return randomPassword;\n        }\n\n        public void setRandomPassword(boolean randomPassword) {\n            this.randomPassword = randomPassword;\n        }\n\n        public boolean isPasswordHash() {\n            return passwordHash;\n        }\n\n        public void setPasswordHash(boolean passwordHash) {\n            this.passwordHash = passwordHash;\n        }\n\n        public SQLExpr getPassword() {\n            return password;\n        }\n\n        public void setPassword(SQLExpr password) {\n            this.password = password;\n        }\n\n        public SQLExpr getAuthPlugin() {\n            return authPlugin;\n        }\n\n        public void setAuthPlugin(SQLExpr authPlugin) {\n            this.authPlugin = authPlugin;\n        }\n\n        public boolean isPluginAs() {\n            return pluginAs;\n        }\n\n        public void setPluginAs(boolean pluginAs) {\n            this.pluginAs = pluginAs;\n        }\n\n        @Override\n        public void accept0(MySqlASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, user);\n                acceptChild(visitor, password);\n                acceptChild(visitor, authPlugin);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDeleteStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlDeleteStatement extends SQLDeleteStatement {\n    private boolean lowPriority;\n    private boolean quick;\n    private boolean ignore;\n    private SQLOrderBy orderBy;\n    private SQLLimit limit;\n    // for petadata\n    private boolean forceAllPartitions;\n    private SQLName forcePartition;\n\n    private List<SQLCommentHint> hints;\n\n    private boolean fulltextDictionary;\n\n    public MySqlDeleteStatement() {\n        super(DbType.mysql);\n    }\n\n    public MySqlDeleteStatement clone() {\n        MySqlDeleteStatement x = new MySqlDeleteStatement();\n        cloneTo(x);\n\n        x.lowPriority = lowPriority;\n        x.quick = quick;\n        x.ignore = ignore;\n        x.fulltextDictionary = fulltextDictionary;\n\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n        if (orderBy != null) {\n            x.setOrderBy(orderBy.clone());\n        }\n        if (limit != null) {\n            x.setLimit(limit.clone());\n        }\n\n        return x;\n    }\n\n    public List<SQLCommentHint> getHints() {\n        if (hints == null) {\n            hints = new ArrayList<SQLCommentHint>();\n        }\n        return hints;\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n\n        return hints.size();\n    }\n\n    public boolean isLowPriority() {\n        return lowPriority;\n    }\n\n    public void setLowPriority(boolean lowPriority) {\n        this.lowPriority = lowPriority;\n    }\n\n    public boolean isQuick() {\n        return quick;\n    }\n\n    public void setQuick(boolean quick) {\n        this.quick = quick;\n    }\n\n    public boolean isIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(boolean ignore) {\n        this.ignore = ignore;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        if (limit != null) {\n            limit.setParent(this);\n        }\n        this.limit = limit;\n    }\n\n    public boolean isFulltextDictionary() {\n        return fulltextDictionary;\n    }\n\n    public void setFulltextDictionary(boolean fulltextDictionary) {\n        this.fulltextDictionary = fulltextDictionary;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (with != null) {\n                with.accept(visitor);\n            }\n\n            if (tableSource != null) {\n                tableSource.accept(visitor);\n            }\n\n            if (where != null) {\n                where.accept(visitor);\n            }\n\n            if (from != null) {\n                from.accept(visitor);\n            }\n\n            if (using != null) {\n                using.accept(visitor);\n            }\n\n            if (orderBy != null) {\n                orderBy.accept(visitor);\n            }\n\n            if (limit != null) {\n                limit.accept(visitor);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public boolean isForceAllPartitions() {\n        return forceAllPartitions;\n    }\n\n    public void setForceAllPartitions(boolean forceAllPartitions) {\n        this.forceAllPartitions = forceAllPartitions;\n    }\n\n    public SQLName getForcePartition() {\n        return forcePartition;\n    }\n\n    public void setForcePartition(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.forcePartition = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlDisabledPlanCacheStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlDisabledPlanCacheStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlEventSchedule.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlEventSchedule extends MySqlObjectImpl {\n    private SQLExpr at;\n    private SQLExpr every;\n    private SQLExpr starts;\n    private SQLExpr ends;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, at);\n            acceptChild(visitor, every);\n            acceptChild(visitor, starts);\n            acceptChild(visitor, ends);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getAt() {\n        return at;\n    }\n\n    public void setAt(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.at = x;\n    }\n\n    public SQLExpr getEvery() {\n        return every;\n    }\n\n    public void setEvery(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.every = x;\n    }\n\n    public SQLExpr getStarts() {\n        return starts;\n    }\n\n    public void setStarts(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.starts = x;\n    }\n\n    public SQLExpr getEnds() {\n        return ends;\n    }\n\n    public void setEnds(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.ends = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlExecuteForAdsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlExecuteForAdsStatement extends MySqlStatementImpl {\n    private SQLName action;\n    private SQLName role;\n    private SQLCharExpr targetId;\n    private SQLName status;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, action);\n            acceptChild(visitor, role);\n            acceptChild(visitor, targetId);\n            acceptChild(visitor, status);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getAction() {\n        return action;\n    }\n\n    public void setAction(SQLName action) {\n        this.action = action;\n    }\n\n    public SQLName getRole() {\n        return role;\n    }\n\n    public void setRole(SQLName role) {\n        this.role = role;\n    }\n\n    public SQLCharExpr getTargetId() {\n        return targetId;\n    }\n\n    public void setTargetId(SQLCharExpr targetId) {\n        this.targetId = targetId;\n    }\n\n    public SQLName getStatus() {\n        return status;\n    }\n\n    public void setStatus(SQLName status) {\n        this.status = status;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (action != null) {\n            children.add(action);\n        }\n        if (role != null) {\n            children.add(role);\n        }\n        if (targetId != null) {\n            children.add(targetId);\n        }\n        if (status != null) {\n            children.add(status);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlExecuteStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLExecuteImmediateStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlExecuteStatement extends SQLExecuteImmediateStatement implements MySqlStatement {\n    private final List<SQLExpr> parameters = new ArrayList<SQLExpr>();\n\n    public SQLName getStatementName() {\n        return (SQLName) dynamicSql;\n    }\n\n    public void setStatementName(SQLName x) {\n        super.setDynamicSql(x);\n    }\n\n    public List<SQLExpr> getParameters() {\n        return parameters;\n    }\n\n    public void accept0(MySqlASTVisitor v) {\n        if (v.visit(this)) {\n            super.acceptChild(v);\n            acceptChild(v, parameters);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof MySqlASTVisitor) {\n            ((MySqlASTVisitor) v).visit(this);\n        } else {\n            super.accept0(v);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlExplainPlanCacheStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlExplainPlanCacheStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlExplainStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLExplainStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlExplainStatement extends SQLExplainStatement implements MySqlStatement {\n    private boolean describe;\n    private SQLName tableName;\n    private SQLName columnName;\n    private SQLExpr wild;\n    private SQLExpr connectionId;\n\n    private boolean distributeInfo; // for ads\n\n    public MySqlExplainStatement() {\n        super(DbType.mysql);\n    }\n\n    public MySqlExplainStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            // tbl_name [col_name | wild]\n            if (tableName != null) {\n                tableName.accept(visitor);\n\n                if (columnName != null) {\n                    columnName.accept(visitor);\n                } else if (wild != null) {\n                    wild.accept(visitor);\n                }\n            } else {\n                // {explainable_stmt | FOR CONNECTION connection_id}\n                if (connectionId != null) {\n                    connectionId.accept(visitor);\n                } else {\n                    if (statement != null) {\n                        statement.accept(visitor);\n                    }\n                }\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public String toString() {\n        return SQLUtils.toMySqlString(this);\n    }\n\n    public boolean isDescribe() {\n        return describe;\n    }\n\n    public void setDescribe(boolean describe) {\n        this.describe = describe;\n    }\n\n    public SQLName getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.tableName = tableName;\n    }\n\n    public SQLName getColumnName() {\n        return columnName;\n    }\n\n    public void setColumnName(SQLName columnName) {\n        this.columnName = columnName;\n    }\n\n    public SQLExpr getWild() {\n        return wild;\n    }\n\n    public void setWild(SQLExpr wild) {\n        this.wild = wild;\n    }\n\n    public SQLExpr getConnectionId() {\n        return connectionId;\n    }\n\n    public void setConnectionId(SQLExpr connectionId) {\n        this.connectionId = connectionId;\n    }\n\n    public boolean isDistributeInfo() {\n        return distributeInfo;\n    }\n\n    public void setDistributeInfo(boolean distributeInfo) {\n        this.distributeInfo = distributeInfo;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlExtPartition.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlExtPartition extends MySqlObjectImpl implements Cloneable {\n    private final List<Item> items = new ArrayList<Item>();\n\n    public List<Item> getItems() {\n        return items;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < items.size(); i++) {\n                items.get(i).accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlExtPartition clone() {\n        MySqlExtPartition x = new MySqlExtPartition();\n        for (Item item : items) {\n            Item item1 = item.clone();\n            item1.setParent(x);\n            x.items.add(item1);\n        }\n        return x;\n    }\n\n    public static class Item extends MySqlObjectImpl implements Cloneable {\n        private SQLName dbPartition;\n        private SQLExpr dbPartitionBy;\n        private SQLName tbPartition;\n        private SQLExpr tbPartitionBy;\n\n        @Override\n        public void accept0(MySqlASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, dbPartition);\n                acceptChild(visitor, dbPartitionBy);\n                acceptChild(visitor, tbPartition);\n                acceptChild(visitor, tbPartitionBy);\n            }\n            visitor.endVisit(this);\n        }\n\n        public Item clone() {\n            Item x = new Item();\n\n            if (dbPartition != null) {\n                x.setDbPartition(dbPartition.clone());\n            }\n\n            if (dbPartitionBy != null) {\n                x.setDbPartitionBy(dbPartitionBy.clone());\n            }\n\n            if (tbPartition != null) {\n                x.setTbPartition(tbPartition.clone());\n            }\n\n            if (tbPartitionBy != null) {\n                x.setTbPartitionBy(tbPartitionBy.clone());\n            }\n\n            return x;\n        }\n\n        public SQLName getDbPartition() {\n            return dbPartition;\n        }\n\n        public void setDbPartition(SQLName x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.dbPartition = x;\n        }\n\n        public SQLName getTbPartition() {\n            return tbPartition;\n        }\n\n        public void setTbPartition(SQLName x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.tbPartition = x;\n        }\n\n        public SQLExpr getDbPartitionBy() {\n            return dbPartitionBy;\n        }\n\n        public void setDbPartitionBy(SQLExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.dbPartitionBy = x;\n        }\n\n        public SQLExpr getTbPartitionBy() {\n            return tbPartitionBy;\n        }\n\n        public void setTbPartitionBy(SQLExpr x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.tbPartitionBy = x;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlFlashbackStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlFlashbackStatement extends MySqlStatementImpl {\n    private SQLName name;\n    private SQLName renameTo;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, renameTo);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLName getRenameTo() {\n        return renameTo;\n    }\n\n    public void setRenameTo(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.renameTo = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlFlushStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 16/08/2017.\n */\npublic class MySqlFlushStatement extends MySqlStatementImpl {\n    private boolean noWriteToBinlog;\n    private boolean local;\n\n    private final List<SQLExprTableSource> tables = new ArrayList<SQLExprTableSource>();\n\n    private boolean withReadLock;\n    private boolean forExport;\n\n    private boolean binaryLogs;\n    private boolean desKeyFile;\n    private boolean engineLogs;\n    private boolean errorLogs;\n    private boolean generalLogs;\n    private boolean hots;\n    private boolean logs;\n    private boolean master;\n    private boolean privileges;\n    private boolean optimizerCosts;\n    private boolean queryCache;\n    private boolean relayLogs;\n    private SQLExpr relayLogsForChannel;\n    private boolean slowLogs;\n    private boolean status;\n    private boolean userResources;\n    private boolean tableOption;\n    private SQLIntegerExpr version; // for ads\n\n    public boolean isNoWriteToBinlog() {\n        return noWriteToBinlog;\n    }\n\n    public void setNoWriteToBinlog(boolean noWriteToBinlog) {\n        this.noWriteToBinlog = noWriteToBinlog;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public List<SQLExprTableSource> getTables() {\n        return tables;\n    }\n\n    public boolean isWithReadLock() {\n        return withReadLock;\n    }\n\n    public void setWithReadLock(boolean withReadLock) {\n        this.withReadLock = withReadLock;\n    }\n\n    public boolean isForExport() {\n        return forExport;\n    }\n\n    public void setForExport(boolean forExport) {\n        this.forExport = forExport;\n    }\n\n    public boolean isBinaryLogs() {\n        return binaryLogs;\n    }\n\n    public void setBinaryLogs(boolean binaryLogs) {\n        this.binaryLogs = binaryLogs;\n    }\n\n    public boolean isDesKeyFile() {\n        return desKeyFile;\n    }\n\n    public void setDesKeyFile(boolean desKeyFile) {\n        this.desKeyFile = desKeyFile;\n    }\n\n    public boolean isEngineLogs() {\n        return engineLogs;\n    }\n\n    public void setEngineLogs(boolean engineLogs) {\n        this.engineLogs = engineLogs;\n    }\n\n    public boolean isGeneralLogs() {\n        return generalLogs;\n    }\n\n    public void setGeneralLogs(boolean generalLogs) {\n        this.generalLogs = generalLogs;\n    }\n\n    public boolean isHots() {\n        return hots;\n    }\n\n    public void setHots(boolean hots) {\n        this.hots = hots;\n    }\n\n    public boolean isLogs() {\n        return logs;\n    }\n\n    public void setLogs(boolean logs) {\n        this.logs = logs;\n    }\n\n    public boolean isPrivileges() {\n        return privileges;\n    }\n\n    public void setPrivileges(boolean privileges) {\n        this.privileges = privileges;\n    }\n\n    public boolean isOptimizerCosts() {\n        return optimizerCosts;\n    }\n\n    public void setOptimizerCosts(boolean optimizerCosts) {\n        this.optimizerCosts = optimizerCosts;\n    }\n\n    public boolean isQueryCache() {\n        return queryCache;\n    }\n\n    public void setQueryCache(boolean queryCache) {\n        this.queryCache = queryCache;\n    }\n\n    public boolean isRelayLogs() {\n        return relayLogs;\n    }\n\n    public void setRelayLogs(boolean relayLogs) {\n        this.relayLogs = relayLogs;\n    }\n\n    public SQLExpr getRelayLogsForChannel() {\n        return relayLogsForChannel;\n    }\n\n    public void setRelayLogsForChannel(SQLExpr relayLogsForChannel) {\n        this.relayLogsForChannel = relayLogsForChannel;\n    }\n\n    public boolean isSlowLogs() {\n        return slowLogs;\n    }\n\n    public void setSlowLogs(boolean showLogs) {\n        this.slowLogs = showLogs;\n    }\n\n    public boolean isStatus() {\n        return status;\n    }\n\n    public void setStatus(boolean status) {\n        this.status = status;\n    }\n\n    public boolean isUserResources() {\n        return userResources;\n    }\n\n    public void setUserResources(boolean userResources) {\n        this.userResources = userResources;\n    }\n\n    public boolean isErrorLogs() {\n        return errorLogs;\n    }\n\n    public void setErrorLogs(boolean errorLogs) {\n        this.errorLogs = errorLogs;\n    }\n\n    public boolean isTableOption() {\n        return tableOption;\n    }\n\n    public void setTableOption(boolean tableOption) {\n        this.tableOption = tableOption;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tables);\n            acceptChild(visitor, relayLogsForChannel);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void addTable(SQLName name) {\n        if (name == null) {\n            return;\n        }\n        this.addTable(new SQLExprTableSource(name));\n    }\n\n    public void addTable(SQLExprTableSource table) {\n        if (table == null) {\n            return;\n        }\n        table.setParent(this);\n        this.tables.add(table);\n    }\n\n    public SQLIntegerExpr getVersion() {\n        return version;\n    }\n\n    public void setVersion(SQLIntegerExpr version) {\n        this.version = version;\n    }\n\n    public boolean isMaster() {\n        return master;\n    }\n\n    public void setMaster(boolean master) {\n        this.master = master;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlHelpStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlHelpStatement extends MySqlStatementImpl {\n    private SQLExpr content;\n\n    public SQLExpr getContent() {\n        return content;\n    }\n\n    public void setContent(SQLExpr content) {\n        this.content = content;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, content);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlHintStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2ASTVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class MySqlHintStatement extends MySqlStatementImpl {\n    private List<SQLCommentHint> hints;\n\n    private List<SQLStatement> hintStatements;\n\n    public MySqlHintStatement() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof H2ASTVisitor) {\n            return;\n        }\n        super.accept0(visitor);\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.hints);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n    public int getHintVersion() {\n        if (hints.size() != 1) {\n            return -1;\n        }\n\n        SQLCommentHint hint = hints.get(0);\n\n        String text = hint.getText();\n        if (text.length() < 7) {\n            return -1;\n        }\n\n        char c0 = text.charAt(0);\n        char c1 = text.charAt(1);\n        char c2 = text.charAt(2);\n        char c3 = text.charAt(3);\n        char c4 = text.charAt(4);\n        char c5 = text.charAt(5);\n        char c6 = text.charAt(6);\n\n        if (c0 != '!') {\n            return -1;\n        }\n\n        if (c1 >= '0' && c1 <= '9'\n                && c2 >= '0' && c2 <= '9'\n                && c3 >= '0' && c3 <= '9'\n                && c4 >= '0' && c4 <= '9'\n                && c5 >= '0' && c5 <= '9'\n                && c6 == ' ') {\n            return (c1 - '0') * 10000\n                    + (c2 - '0') * 1000\n                    + (c3 - '0') * 100\n                    + (c4 - '0') * 10\n                    + (c5 - '0');\n        }\n\n        return -1;\n    }\n\n    public List<SQLStatement> getHintStatements() {\n        if (hintStatements != null) {\n            return hintStatements;\n        }\n\n        if (hints.size() != 1) {\n            return null;\n        }\n\n        SQLCommentHint hint = hints.get(0);\n\n        String text = hint.getText();\n        if (text.length() < 7) {\n            return null;\n        }\n\n        char c0 = text.charAt(0);\n        char c1 = text.charAt(1);\n        char c2 = text.charAt(2);\n        char c3 = text.charAt(3);\n        char c4 = text.charAt(4);\n        char c5 = text.charAt(5);\n        char c6 = text.charAt(6);\n        if (c0 != '!') {\n            return null;\n        }\n\n        int start;\n        if (c1 == ' ') {\n            start = 2;\n        } else if (c1 >= '0' && c1 <= '9'\n                && c2 >= '0' && c2 <= '9'\n                && c3 >= '0' && c3 <= '9'\n                && c4 >= '0' && c4 <= '9'\n                && c5 >= '0' && c5 <= '9'\n                && c6 == ' ') {\n            start = 7;\n        } else {\n            return null;\n        }\n\n        String hintSql = text.substring(start);\n        hintStatements = SQLUtils.parseStatements(hintSql, dbType);\n        return hintStatements;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlInsertStatement extends SQLInsertStatement {\n    private boolean lowPriority;\n    private boolean delayed;\n    private boolean highPriority;\n    private boolean ignore;\n    private boolean rollbackOnFail;\n    private boolean fulltextDictionary; // for adb\n    private boolean overwrite; // for adb\n    private boolean ifNotExists; //for adb\n\n    protected List<SQLCommentHint> hints;\n\n    private final List<SQLExpr> duplicateKeyUpdate = new ArrayList<SQLExpr>();\n\n    public MySqlInsertStatement() {\n        dbType = DbType.mysql;\n    }\n\n    public void cloneTo(MySqlInsertStatement x) {\n        super.cloneTo(x);\n        x.lowPriority = lowPriority;\n        x.delayed = delayed;\n        x.highPriority = highPriority;\n        x.ignore = ignore;\n        x.rollbackOnFail = rollbackOnFail;\n        x.fulltextDictionary = fulltextDictionary;\n        x.overwrite = overwrite;\n        x.ifNotExists = ifNotExists;\n\n        for (SQLExpr e : duplicateKeyUpdate) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.duplicateKeyUpdate.add(e2);\n        }\n    }\n\n    public List<SQLExpr> getDuplicateKeyUpdate() {\n        return duplicateKeyUpdate;\n    }\n\n    public boolean isLowPriority() {\n        return lowPriority;\n    }\n\n    public void setLowPriority(boolean lowPriority) {\n        this.lowPriority = lowPriority;\n    }\n\n    public boolean isDelayed() {\n        return delayed;\n    }\n\n    public void setDelayed(boolean delayed) {\n        this.delayed = delayed;\n    }\n\n    public boolean isHighPriority() {\n        return highPriority;\n    }\n\n    public void setHighPriority(boolean highPriority) {\n        this.highPriority = highPriority;\n    }\n\n    public boolean isIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(boolean ignore) {\n        this.ignore = ignore;\n    }\n\n    public boolean isRollbackOnFail() {\n        return rollbackOnFail;\n    }\n\n    public void setRollbackOnFail(boolean rollbackOnFail) {\n        this.rollbackOnFail = rollbackOnFail;\n    }\n\n    public boolean isFulltextDictionary() {\n        return fulltextDictionary;\n    }\n\n    public void setFulltextDictionary(boolean fulltextDictionary) {\n        this.fulltextDictionary = fulltextDictionary;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (tableSource != null) {\n                tableSource.accept(visitor);\n            }\n\n            if (columns != null) {\n                for (SQLExpr column : columns) {\n                    if (column != null) {\n                        column.accept(visitor);\n                    }\n                }\n            }\n\n            if (valuesList != null) {\n                for (ValuesClause values : valuesList) {\n                    if (values != null) {\n                        values.accept(visitor);\n                    }\n                }\n            }\n\n            if (query != null) {\n                query.accept(visitor);\n            }\n\n            if (duplicateKeyUpdate != null) {\n                for (SQLExpr item : duplicateKeyUpdate) {\n                    if (item != null) {\n                        item.accept(visitor);\n                    }\n                }\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n        return hints.size();\n    }\n\n    public List<SQLCommentHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> x) {\n        if (x != null) {\n            for (int i = 0; i < x.size(); i++) {\n                x.get(i).setParent(this);\n            }\n        }\n        this.hints = x;\n    }\n\n    public SQLInsertStatement clone() {\n        MySqlInsertStatement x = new MySqlInsertStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public boolean isOverwrite() {\n        return overwrite;\n    }\n\n    @Override\n    public void setOverwrite(boolean overwrite) {\n        this.overwrite = overwrite;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlKillStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class MySqlKillStatement extends SQLStatementImpl {\n    private Type type;\n    private List<SQLExpr> threadIds = new ArrayList<SQLExpr>();\n\n    public static enum Type {\n        CONNECTION, QUERY\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public void setType(Type type) {\n        this.type = type;\n    }\n\n    public SQLExpr getThreadId() {\n        return threadIds.get(0);\n    }\n\n    public void setThreadId(SQLExpr threadId) {\n        if (this.threadIds.isEmpty()) {\n            this.threadIds.add(threadId);\n            return;\n        }\n        this.threadIds.set(0, threadId);\n    }\n\n    public List<SQLExpr> getThreadIds() {\n        return threadIds;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, threadIds);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLoadDataInFileStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlLoadDataInFileStatement extends MySqlStatementImpl {\n    private boolean lowPriority;\n    private boolean concurrent;\n    private boolean local;\n\n    private SQLLiteralExpr fileName;\n\n    private boolean replicate;\n    private boolean ignore;\n\n    private SQLName tableName;\n\n    private String charset;\n\n    private SQLLiteralExpr columnsTerminatedBy;\n    private boolean columnsEnclosedOptionally;\n    private SQLLiteralExpr columnsEnclosedBy;\n    private SQLLiteralExpr columnsEscaped;\n\n    private SQLLiteralExpr linesStartingBy;\n    private SQLLiteralExpr linesTerminatedBy;\n\n    private SQLExpr ignoreLinesNumber;\n\n    private List<SQLExpr> setList = new ArrayList<SQLExpr>();\n\n    private List<SQLExpr> columns = new ArrayList<SQLExpr>();\n\n    public boolean isLowPriority() {\n        return lowPriority;\n    }\n\n    public void setLowPriority(boolean lowPriority) {\n        this.lowPriority = lowPriority;\n    }\n\n    public boolean isConcurrent() {\n        return concurrent;\n    }\n\n    public void setConcurrent(boolean concurrent) {\n        this.concurrent = concurrent;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public SQLLiteralExpr getFileName() {\n        return fileName;\n    }\n\n    public void setFileName(SQLLiteralExpr fileName) {\n        this.fileName = fileName;\n    }\n\n    public boolean isReplicate() {\n        return replicate;\n    }\n\n    public void setReplicate(boolean replicate) {\n        this.replicate = replicate;\n    }\n\n    public boolean isIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(boolean ignore) {\n        this.ignore = ignore;\n    }\n\n    public SQLName getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.tableName = tableName;\n    }\n\n    public String getCharset() {\n        return charset;\n    }\n\n    public void setCharset(String charset) {\n        this.charset = charset;\n    }\n\n    public SQLLiteralExpr getColumnsTerminatedBy() {\n        return columnsTerminatedBy;\n    }\n\n    public void setColumnsTerminatedBy(SQLLiteralExpr columnsTerminatedBy) {\n        this.columnsTerminatedBy = columnsTerminatedBy;\n    }\n\n    public boolean isColumnsEnclosedOptionally() {\n        return columnsEnclosedOptionally;\n    }\n\n    public void setColumnsEnclosedOptionally(boolean columnsEnclosedOptionally) {\n        this.columnsEnclosedOptionally = columnsEnclosedOptionally;\n    }\n\n    public SQLLiteralExpr getColumnsEnclosedBy() {\n        return columnsEnclosedBy;\n    }\n\n    public void setColumnsEnclosedBy(SQLLiteralExpr columnsEnclosedBy) {\n        this.columnsEnclosedBy = columnsEnclosedBy;\n    }\n\n    public SQLLiteralExpr getColumnsEscaped() {\n        return columnsEscaped;\n    }\n\n    public void setColumnsEscaped(SQLLiteralExpr columnsEscaped) {\n        this.columnsEscaped = columnsEscaped;\n    }\n\n    public SQLLiteralExpr getLinesStartingBy() {\n        return linesStartingBy;\n    }\n\n    public void setLinesStartingBy(SQLLiteralExpr linesStartingBy) {\n        this.linesStartingBy = linesStartingBy;\n    }\n\n    public SQLLiteralExpr getLinesTerminatedBy() {\n        return linesTerminatedBy;\n    }\n\n    public void setLinesTerminatedBy(SQLLiteralExpr linesTerminatedBy) {\n        this.linesTerminatedBy = linesTerminatedBy;\n    }\n\n    public SQLExpr getIgnoreLinesNumber() {\n        return ignoreLinesNumber;\n    }\n\n    public void setIgnoreLinesNumber(SQLExpr ignoreLinesNumber) {\n        this.ignoreLinesNumber = ignoreLinesNumber;\n    }\n\n    public List<SQLExpr> getSetList() {\n        return setList;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, fileName);\n            acceptChild(visitor, tableName);\n            acceptChild(visitor, columnsTerminatedBy);\n            acceptChild(visitor, columnsEnclosedBy);\n            acceptChild(visitor, columnsEscaped);\n            acceptChild(visitor, linesStartingBy);\n            acceptChild(visitor, linesTerminatedBy);\n            acceptChild(visitor, ignoreLinesNumber);\n            acceptChild(visitor, setList);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (fileName != null) {\n            children.add(fileName);\n        }\n        if (tableName != null) {\n            children.add(tableName);\n        }\n        if (columnsTerminatedBy != null) {\n            children.add(columnsTerminatedBy);\n        }\n        if (columnsEnclosedBy != null) {\n            children.add(columnsEnclosedBy);\n        }\n        if (columnsEscaped != null) {\n            children.add(columnsEscaped);\n        }\n        if (linesStartingBy != null) {\n            children.add(linesStartingBy);\n        }\n        if (linesTerminatedBy != null) {\n            children.add(linesTerminatedBy);\n        }\n        if (ignoreLinesNumber != null) {\n            children.add(ignoreLinesNumber);\n        }\n        return children;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void setColumns(List<SQLExpr> columns) {\n        this.columns = columns;\n    }\n\n    public void setSetList(List<SQLExpr> setList) {\n        this.setList = setList;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLoadXmlStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlLoadXmlStatement extends MySqlStatementImpl {\n    private boolean lowPriority;\n    private boolean concurrent;\n    private boolean local;\n\n    private SQLLiteralExpr fileName;\n\n    private boolean replicate;\n    private boolean ignore;\n\n    private SQLName tableName;\n\n    private String charset;\n\n    private SQLExpr rowsIdentifiedBy;\n\n    private SQLExpr ignoreLinesNumber;\n\n    private final List<SQLExpr> setList = new ArrayList<SQLExpr>();\n\n    public SQLExpr getRowsIdentifiedBy() {\n        return rowsIdentifiedBy;\n    }\n\n    public void setRowsIdentifiedBy(SQLExpr rowsIdentifiedBy) {\n        this.rowsIdentifiedBy = rowsIdentifiedBy;\n    }\n\n    public boolean isLowPriority() {\n        return lowPriority;\n    }\n\n    public void setLowPriority(boolean lowPriority) {\n        this.lowPriority = lowPriority;\n    }\n\n    public boolean isConcurrent() {\n        return concurrent;\n    }\n\n    public void setConcurrent(boolean concurrent) {\n        this.concurrent = concurrent;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public SQLLiteralExpr getFileName() {\n        return fileName;\n    }\n\n    public void setFileName(SQLLiteralExpr fileName) {\n        this.fileName = fileName;\n    }\n\n    public boolean isReplicate() {\n        return replicate;\n    }\n\n    public void setReplicate(boolean replicate) {\n        this.replicate = replicate;\n    }\n\n    public boolean isIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(boolean ignore) {\n        this.ignore = ignore;\n    }\n\n    public SQLName getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(SQLName tableName) {\n        this.tableName = tableName;\n    }\n\n    public String getCharset() {\n        return charset;\n    }\n\n    public void setCharset(String charset) {\n        this.charset = charset;\n    }\n\n    public SQLExpr getIgnoreLinesNumber() {\n        return ignoreLinesNumber;\n    }\n\n    public void setIgnoreLinesNumber(SQLExpr ignoreLinesNumber) {\n        this.ignoreLinesNumber = ignoreLinesNumber;\n    }\n\n    public List<SQLExpr> getSetList() {\n        return setList;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, fileName);\n            acceptChild(visitor, tableName);\n            acceptChild(visitor, rowsIdentifiedBy);\n            // acceptChild(visitor, columnsTerminatedBy);\n            // acceptChild(visitor, columnsEnclosedBy);\n            // acceptChild(visitor, columnsEscaped);\n            // acceptChild(visitor, linesStartingBy);\n            // acceptChild(visitor, linesTerminatedBy);\n            acceptChild(visitor, ignoreLinesNumber);\n            acceptChild(visitor, setList);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (fileName != null) {\n            children.add(fileName);\n        }\n        if (tableName != null) {\n            children.add(tableName);\n        }\n        if (rowsIdentifiedBy != null) {\n            children.add(rowsIdentifiedBy);\n        }\n        if (ignoreLinesNumber != null) {\n            children.add(ignoreLinesNumber);\n        }\n        children.addAll(this.setList);\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLLockTableStatement;\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2ASTVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlLockTableStatement extends MySqlStatementImpl implements SQLLockTableStatement {\n    private List<Item> items = new ArrayList<Item>();\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof H2ASTVisitor) {\n            return;\n        }\n        super.accept0(visitor);\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, items);\n        }\n        visitor.endVisit(this);\n    }\n\n    public static enum LockType {\n        READ(\"READ\"), READ_LOCAL(\"READ LOCAL\"), WRITE(\"WRITE\"), LOW_PRIORITY_WRITE(\"LOW_PRIORITY WRITE\");\n\n        public final String name;\n\n        LockType(String name) {\n            this.name = name;\n        }\n    }\n\n    public List<Item> getItems() {\n        return items;\n    }\n\n    public void setItems(List<Item> items) {\n        this.items = items;\n    }\n\n    public static class Item extends MySqlObjectImpl {\n        private SQLExprTableSource tableSource = new SQLExprTableSource();\n\n        private LockType lockType;\n\n        private List<SQLCommentHint> hints;\n\n        @Override\n        public void accept0(MySqlASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, tableSource);\n            }\n            visitor.endVisit(this);\n        }\n\n        public SQLExprTableSource getTableSource() {\n            return tableSource;\n        }\n\n        public void setTableSource(SQLExprTableSource tableSource) {\n            if (tableSource != null) {\n                tableSource.setParent(this);\n            }\n            this.tableSource = tableSource;\n        }\n\n        public LockType getLockType() {\n            return lockType;\n        }\n\n        public void setLockType(LockType lockType) {\n            this.lockType = lockType;\n        }\n\n        public List<SQLCommentHint> getHints() {\n            return hints;\n        }\n\n        public void setHints(List<SQLCommentHint> hints) {\n            this.hints = hints;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlManageInstanceGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlManageInstanceGroupStatement extends MySqlStatementImpl {\n    private List<SQLExpr> groupNames = new ArrayList<SQLExpr>();\n    private SQLIntegerExpr replication;\n    private SQLName operation;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, groupNames);\n            acceptChild(visitor, replication);\n            acceptChild(visitor, operation);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<String> getGroupNamesToString() {\n        List<String> names = new ArrayList<String>(groupNames.size());\n        for (SQLExpr groupName : groupNames) {\n            names.add(groupName.toString());\n        }\n        return names;\n    }\n\n    public List<SQLExpr> getGroupNames() {\n        return groupNames;\n    }\n\n    public SQLIntegerExpr getReplication() {\n        return replication;\n    }\n\n    public void setReplication(SQLIntegerExpr replication) {\n        this.replication = replication;\n    }\n\n    public SQLName getOperation() {\n        return operation;\n    }\n\n    public void setOperation(SQLName operation) {\n        this.operation = operation;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlMigrateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlMigrateStatement extends MySqlStatementImpl {\n    private SQLName schema;\n    private SQLCharExpr shardNames;\n    private SQLIntegerExpr migrateType;\n    private SQLCharExpr fromInsId;\n    private SQLCharExpr fromInsIp;\n    private SQLIntegerExpr fromInsPort;\n    private SQLCharExpr fromInsStatus;\n    private SQLCharExpr toInsId;\n    private SQLCharExpr toInsIp;\n    private SQLIntegerExpr toInsPort;\n    private SQLCharExpr toInsStatus;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, schema);\n            acceptChild(visitor, shardNames);\n            acceptChild(visitor, migrateType);\n            acceptChild(visitor, fromInsId);\n            acceptChild(visitor, fromInsIp);\n            acceptChild(visitor, fromInsPort);\n            acceptChild(visitor, fromInsStatus);\n            acceptChild(visitor, toInsId);\n            acceptChild(visitor, toInsIp);\n            acceptChild(visitor, toInsPort);\n            acceptChild(visitor, toInsStatus);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getSchema() {\n        return schema;\n    }\n\n    public void setSchema(SQLName schema) {\n        this.schema = schema;\n    }\n\n    public SQLCharExpr getShardNames() {\n        return shardNames;\n    }\n\n    public void setShardNames(SQLCharExpr shardNames) {\n        this.shardNames = shardNames;\n    }\n\n    public SQLIntegerExpr getMigrateType() {\n        return migrateType;\n    }\n\n    public void setMigrateType(SQLIntegerExpr migrateType) {\n        this.migrateType = migrateType;\n    }\n\n    public SQLCharExpr getFromInsId() {\n        return fromInsId;\n    }\n\n    public void setFromInsId(SQLCharExpr fromInsId) {\n        this.fromInsId = fromInsId;\n    }\n\n    public SQLCharExpr getFromInsIp() {\n        return fromInsIp;\n    }\n\n    public void setFromInsIp(SQLCharExpr fromInsIp) {\n        this.fromInsIp = fromInsIp;\n    }\n\n    public SQLIntegerExpr getFromInsPort() {\n        return fromInsPort;\n    }\n\n    public void setFromInsPort(SQLIntegerExpr fromInsPort) {\n        this.fromInsPort = fromInsPort;\n    }\n\n    public SQLCharExpr getFromInsStatus() {\n        return fromInsStatus;\n    }\n\n    public void setFromInsStatus(SQLCharExpr fromInsStatus) {\n        this.fromInsStatus = fromInsStatus;\n    }\n\n    public SQLCharExpr getToInsId() {\n        return toInsId;\n    }\n\n    public void setToInsId(SQLCharExpr toInsId) {\n        this.toInsId = toInsId;\n    }\n\n    public SQLCharExpr getToInsIp() {\n        return toInsIp;\n    }\n\n    public void setToInsIp(SQLCharExpr toInsIp) {\n        this.toInsIp = toInsIp;\n    }\n\n    public SQLIntegerExpr getToInsPort() {\n        return toInsPort;\n    }\n\n    public void setToInsPort(SQLIntegerExpr toInsPort) {\n        this.toInsPort = toInsPort;\n    }\n\n    public SQLCharExpr getToInsStatus() {\n        return toInsStatus;\n    }\n\n    public void setToInsStatus(SQLCharExpr toInsStatus) {\n        this.toInsStatus = toInsStatus;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlOptimizeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlOptimizeStatement extends MySqlStatementImpl {\n    private boolean noWriteToBinlog;\n    private boolean local;\n\n    protected final List<SQLExprTableSource> tableSources = new ArrayList<SQLExprTableSource>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSources);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isNoWriteToBinlog() {\n        return noWriteToBinlog;\n    }\n\n    public void setNoWriteToBinlog(boolean noWriteToBinlog) {\n        this.noWriteToBinlog = noWriteToBinlog;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void addTableSource(SQLExprTableSource tableSource) {\n        if (tableSource != null) {\n            tableSource.setParent(this);\n        }\n        this.tableSources.add(tableSource);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlPartitionByKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlPartitionByKey extends SQLPartitionBy implements MySqlObject {\n    private int algorithm = 2;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + visitor.getClass().getName());\n        }\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, partitionsCount);\n            acceptChild(visitor, getPartitions());\n            acceptChild(visitor, subPartitionBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void cloneTo(MySqlPartitionByKey x) {\n        super.cloneTo(x);\n        for (SQLExpr column : columns) {\n            SQLExpr c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n        x.algorithm = algorithm;\n    }\n\n    public MySqlPartitionByKey clone() {\n        MySqlPartitionByKey x = new MySqlPartitionByKey();\n        cloneTo(x);\n        return x;\n    }\n\n    public int getAlgorithm() {\n        return algorithm;\n    }\n\n    public void setAlgorithm(int algorithm) {\n        this.algorithm = algorithm;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlPrepareStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlPrepareStatement extends MySqlStatementImpl {\n    private SQLName name;\n    private SQLExpr from;\n\n    public MySqlPrepareStatement() {\n    }\n\n    public MySqlPrepareStatement(SQLName name, SQLExpr from) {\n        this.name = name;\n        this.from = from;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public SQLExpr getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLExpr from) {\n        this.from = from;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, from);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        if (this.from != null) {\n            children.add(from);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlRaftLeaderTransferStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlRaftLeaderTransferStatement extends MySqlStatementImpl {\n    private SQLCharExpr shard;\n    private SQLCharExpr from;\n    private SQLCharExpr to;\n    private SQLIntegerExpr timeout;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, shard);\n            acceptChild(visitor, from);\n            acceptChild(visitor, to);\n            acceptChild(visitor, timeout);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLCharExpr getShard() {\n        return shard;\n    }\n\n    public void setShard(SQLCharExpr shard) {\n        this.shard = shard;\n    }\n\n    public SQLCharExpr getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLCharExpr from) {\n        this.from = from;\n    }\n\n    public SQLCharExpr getTo() {\n        return to;\n    }\n\n    public void setTo(SQLCharExpr to) {\n        this.to = to;\n    }\n\n    public SQLIntegerExpr getTimeout() {\n        return timeout;\n    }\n\n    public void setTimeout(SQLIntegerExpr timeout) {\n        this.timeout = timeout;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlRaftMemberChangeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlRaftMemberChangeStatement extends MySqlStatementImpl {\n    private SQLCharExpr shard;\n    private SQLCharExpr host;\n    private SQLCharExpr status;\n    private boolean force;\n    private boolean noLeader;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, shard);\n            acceptChild(visitor, host);\n            acceptChild(visitor, status);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLCharExpr getShard() {\n        return shard;\n    }\n\n    public void setShard(SQLCharExpr shard) {\n        this.shard = shard;\n    }\n\n    public SQLCharExpr getHost() {\n        return host;\n    }\n\n    public void setHost(SQLCharExpr host) {\n        this.host = host;\n    }\n\n    public SQLCharExpr getStatus() {\n        return status;\n    }\n\n    public void setStatus(SQLCharExpr status) {\n        this.status = status;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n\n    public boolean isNoLeader() {\n        return noLeader;\n    }\n\n    public void setNoLeader(boolean noLeader) {\n        this.noLeader = noLeader;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlRenameSequenceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlRenameSequenceStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private SQLName name;\n    private SQLName to;\n\n    public void accept0(MySqlASTVisitor v) {\n        if (v.visit(this)) {\n            if (name != null) {\n                name.accept(v);\n            }\n            if (to != null) {\n                to.accept(v);\n            }\n        }\n        v.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public SQLName getTo() {\n        return to;\n    }\n\n    public void setTo(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlRenameTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlRenameTableStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private List<Item> items = new ArrayList<Item>(2);\n\n    public List<Item> getItems() {\n        return items;\n    }\n\n    public void addItem(Item item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, items);\n        }\n        visitor.endVisit(this);\n    }\n\n    public static class Item extends MySqlObjectImpl {\n        private SQLName name;\n        private SQLName to;\n\n        public SQLName getName() {\n            return name;\n        }\n\n        public void setName(SQLName name) {\n            this.name = name;\n        }\n\n        public SQLName getTo() {\n            return to;\n        }\n\n        public void setTo(SQLName to) {\n            this.to = to;\n        }\n\n        @Override\n        public void accept0(MySqlASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, name);\n                acceptChild(visitor, to);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLWindow;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlObject {\n    private boolean hignPriority;\n    private boolean straightJoin;\n    private boolean smallResult;\n    private boolean bigResult;\n    private boolean bufferResult;\n    private Boolean cache;\n    private boolean calcFoundRows;\n    private SQLName procedureName;\n    private List<SQLExpr> procedureArgumentList;\n    private boolean lockInShareMode;\n    private SQLName forcePartition; // for petadata\n\n    public MySqlSelectQueryBlock() {\n        dbType = DbType.mysql;\n    }\n\n    public MySqlSelectQueryBlock clone() {\n        MySqlSelectQueryBlock x = new MySqlSelectQueryBlock();\n        cloneTo(x);\n\n        x.hignPriority = hignPriority;\n        x.straightJoin = straightJoin;\n\n        x.smallResult = smallResult;\n        x.bigResult = bigResult;\n        x.bufferResult = bufferResult;\n        x.cache = cache;\n        x.calcFoundRows = calcFoundRows;\n\n        if (procedureName != null) {\n            x.setProcedureName(procedureName.clone());\n        }\n        if (procedureArgumentList != null) {\n            for (SQLExpr arg : procedureArgumentList) {\n                SQLExpr arg_cloned = arg.clone();\n                arg_cloned.setParent(this);\n                x.procedureArgumentList.add(arg_cloned);\n            }\n        }\n        x.lockInShareMode = lockInShareMode;\n\n        return x;\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n\n        return hints.size();\n    }\n\n    public boolean isLockInShareMode() {\n        return lockInShareMode;\n    }\n\n    public void setLockInShareMode(boolean lockInShareMode) {\n        this.lockInShareMode = lockInShareMode;\n    }\n\n    public SQLName getProcedureName() {\n        return procedureName;\n    }\n\n    public void setProcedureName(SQLName procedureName) {\n        this.procedureName = procedureName;\n    }\n\n    public List<SQLExpr> getProcedureArgumentList() {\n        if (procedureArgumentList == null) {\n            procedureArgumentList = new ArrayList<SQLExpr>(2);\n        }\n        return procedureArgumentList;\n    }\n\n    public boolean isHignPriority() {\n        return hignPriority;\n    }\n\n    public void setHignPriority(boolean hignPriority) {\n        this.hignPriority = hignPriority;\n    }\n\n    public boolean isStraightJoin() {\n        return straightJoin;\n    }\n\n    public void setStraightJoin(boolean straightJoin) {\n        this.straightJoin = straightJoin;\n    }\n\n    public boolean isSmallResult() {\n        return smallResult;\n    }\n\n    public void setSmallResult(boolean smallResult) {\n        this.smallResult = smallResult;\n    }\n\n    public boolean isBigResult() {\n        return bigResult;\n    }\n\n    public void setBigResult(boolean bigResult) {\n        this.bigResult = bigResult;\n    }\n\n    public boolean isBufferResult() {\n        return bufferResult;\n    }\n\n    public void setBufferResult(boolean bufferResult) {\n        this.bufferResult = bufferResult;\n    }\n\n    public Boolean getCache() {\n        return cache;\n    }\n\n    public void setCache(Boolean cache) {\n        this.cache = cache;\n    }\n\n    public boolean isCalcFoundRows() {\n        return calcFoundRows;\n    }\n\n    public void setCalcFoundRows(boolean calcFoundRows) {\n        this.calcFoundRows = calcFoundRows;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        MySqlSelectQueryBlock that = (MySqlSelectQueryBlock) o;\n\n        if (hignPriority != that.hignPriority) {\n            return false;\n        }\n        if (straightJoin != that.straightJoin) {\n            return false;\n        }\n        if (smallResult != that.smallResult) {\n            return false;\n        }\n        if (bigResult != that.bigResult) {\n            return false;\n        }\n        if (bufferResult != that.bufferResult) {\n            return false;\n        }\n        if (calcFoundRows != that.calcFoundRows) {\n            return false;\n        }\n        if (lockInShareMode != that.lockInShareMode) {\n            return false;\n        }\n        if (cache != null ? !cache.equals(that.cache) : that.cache != null) {\n            return false;\n        }\n        if (procedureName != null ? !procedureName.equals(that.procedureName) : that.procedureName != null) {\n            return false;\n        }\n        if (procedureArgumentList != null ? !procedureArgumentList.equals(that.procedureArgumentList) :\n                that.procedureArgumentList != null) {\n            return false;\n        }\n        if (hints != null ? !hints.equals(that.hints) : that.hints != null) {\n            return false;\n        }\n        if (forcePartition != null ? !forcePartition.equals(that.forcePartition) : that.forcePartition != null) {\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = super.hashCode();\n        result = 31 * result + (hignPriority ? 1 : 0);\n        result = 31 * result + (straightJoin ? 1 : 0);\n        result = 31 * result + (smallResult ? 1 : 0);\n        result = 31 * result + (bigResult ? 1 : 0);\n        result = 31 * result + (bufferResult ? 1 : 0);\n        result = 31 * result + (cache != null ? cache.hashCode() : 0);\n        result = 31 * result + (calcFoundRows ? 1 : 0);\n        result = 31 * result + (procedureName != null ? procedureName.hashCode() : 0);\n        result = 31 * result + (procedureArgumentList != null ? procedureArgumentList.hashCode() : 0);\n        result = 31 * result + (lockInShareMode ? 1 : 0);\n        result = 31 * result + (hints != null ? hints.hashCode() : 0);\n        result = 31 * result + (forcePartition != null ? forcePartition.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            for (int i = 0; i < this.selectList.size(); i++) {\n                SQLSelectItem item = this.selectList.get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n\n            if (this.from != null) {\n                this.from.accept(visitor);\n            }\n\n            if (this.into != null) {\n                this.into.accept(visitor);\n            }\n\n            if (this.where != null) {\n                this.where.accept(visitor);\n            }\n\n            if (this.startWith != null) {\n                this.startWith.accept(visitor);\n            }\n\n            if (this.connectBy != null) {\n                this.connectBy.accept(visitor);\n            }\n\n            if (this.groupBy != null) {\n                this.groupBy.accept(visitor);\n            }\n\n            if (this.windows != null) {\n                for (SQLWindow item : windows) {\n                    item.accept(visitor);\n                }\n            }\n\n            if (this.orderBy != null) {\n                this.orderBy.accept(visitor);\n            }\n\n            if (this.distributeBy != null) {\n                for (int i = 0; i < distributeBy.size(); i++) {\n                    SQLSelectOrderByItem item = distributeBy.get(i);\n                    item.accept(visitor);\n                }\n            }\n\n            if (this.sortBy != null) {\n                for (int i = 0; i < sortBy.size(); i++) {\n                    SQLSelectOrderByItem item = sortBy.get(i);\n                    item.accept(visitor);\n                }\n            }\n\n            if (this.waitTime != null) {\n                this.waitTime.accept(visitor);\n            }\n\n            if (this.limit != null) {\n                this.limit.accept(visitor);\n            }\n\n            if (this.procedureName != null) {\n                this.procedureName.accept(visitor);\n            }\n\n            if (this.procedureArgumentList != null) {\n                for (SQLExpr item : procedureArgumentList) {\n                    item.accept(visitor);\n                }\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public SQLName getForcePartition() {\n        return forcePartition;\n    }\n\n    public void setForcePartition(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.forcePartition = x;\n    }\n\n    public String toString() {\n        return SQLUtils.toMySqlString(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSetTransactionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlSetTransactionStatement extends MySqlStatementImpl {\n    private Boolean global;\n\n    private Boolean session;\n    private boolean local;\n\n    private String isolationLevel;\n    private String accessModel;\n\n    private SQLExpr policy;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public Boolean getGlobal() {\n        return global;\n    }\n\n    public void setGlobal(Boolean global) {\n        this.global = global;\n    }\n\n    public String getIsolationLevel() {\n        return isolationLevel;\n    }\n\n    public void setIsolationLevel(String isolationLevel) {\n        this.isolationLevel = isolationLevel;\n    }\n\n    public String getAccessModel() {\n        return accessModel;\n    }\n\n    public void setAccessModel(String accessModel) {\n        this.accessModel = accessModel;\n    }\n\n    public Boolean getSession() {\n        return session;\n    }\n\n    public void setSession(Boolean session) {\n        this.session = session;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public SQLExpr getPolicy() {\n        return policy;\n    }\n\n    public void setPolicy(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.policy = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowAuthorsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowAuthorsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowBinLogEventsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowBinLogEventsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr in;\n    private SQLExpr from;\n    private SQLLimit limit;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, in);\n            acceptChild(visitor, from);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getIn() {\n        return in;\n    }\n\n    public void setIn(SQLExpr in) {\n        this.in = in;\n    }\n\n    public SQLExpr getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLExpr from) {\n        this.from = from;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        if (limit != null) {\n            limit.setParent(this);\n        }\n        this.limit = limit;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowBinaryLogsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowBinaryLogsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowBroadcastsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowBroadcastsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowCharacterSetStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class MySqlShowCharacterSetStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr where;\n    private SQLExpr pattern;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, pattern);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public SQLExpr getPattern() {\n        return pattern;\n    }\n\n    public void setPattern(SQLExpr pattern) {\n        this.pattern = pattern;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Arrays.<SQLObject>asList(this.where, pattern);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowClusterNameStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowClusterNameStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowCollationStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowCollationStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr where;\n    private SQLExpr pattern;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, pattern);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public SQLExpr getPattern() {\n        return pattern;\n    }\n\n    public void setPattern(SQLExpr pattern) {\n        this.pattern = pattern;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowConfigStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowConfigStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName name;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowContributorsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowContributorsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowCreateDatabaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowCreateDatabaseStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr database;\n\n    private boolean ifNotExists;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLExpr database) {\n        this.database = database;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowCreateEventStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowCreateEventStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr eventName;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, eventName);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getEventName() {\n        return eventName;\n    }\n\n    public void setEventName(SQLExpr eventName) {\n        this.eventName = eventName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowCreateFunctionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowCreateFunctionStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr name;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr functionName) {\n        this.name = functionName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowCreateProcedureStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowCreateProcedureStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr name;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr functionName) {\n        this.name = functionName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowCreateTriggerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowCreateTriggerStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr name;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr functionName) {\n        this.name = functionName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowDatabaseStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowDatabaseStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName name;\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n    private boolean full;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.limit = x;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.orderBy = x;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowDatasourcesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowDatasourcesStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowDdlStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * for ttdl5\n */\npublic class MySqlShowDdlStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowDsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowDsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowEngineStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowEngineStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr name;\n    private Option option;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        this.name = name;\n    }\n\n    public Option getOption() {\n        return option;\n    }\n\n    public void setOption(Option option) {\n        this.option = option;\n    }\n\n    public static enum Option {\n        STATUS, MUTEX\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowEnginesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowEnginesStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean storage;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isStorage() {\n        return storage;\n    }\n\n    public void setStorage(boolean storage) {\n        this.storage = storage;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowErrorsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowErrorsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean count;\n    private SQLLimit limit;\n\n    public boolean isCount() {\n        return count;\n    }\n\n    public void setCount(boolean count) {\n        this.count = count;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowEventsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowEventsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr schema;\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public SQLExpr getSchema() {\n        return schema;\n    }\n\n    public void setSchema(SQLExpr schema) {\n        this.schema = schema;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, schema);\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowFunctionCodeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowFunctionCodeStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr name;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr functionName) {\n        this.name = functionName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowFunctionStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowFunctionStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowGrantsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLShowGrantsStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowGrantsStatement extends SQLShowGrantsStatement implements MySqlShowStatement {\n    public MySqlShowGrantsStatement() {\n        dbType = DbType.mysql;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, user);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowHMSMetaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowHMSMetaStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName name;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public String getSchema() {\n        if (name instanceof SQLPropertyExpr) {\n            return ((SQLPropertyExpr) name).getOwnernName();\n        }\n        return null;\n    }\n\n    public String getTableName() {\n        return name.getSimpleName();\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowHelpStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowHelpStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowJobStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowJobStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean sync;\n    private SQLExpr where;\n\n    public MySqlShowJobStatusStatement() {\n    }\n\n    public boolean isSync() {\n        return sync;\n    }\n\n    public void setSync(boolean sync) {\n        this.sync = sync;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowMasterLogsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowMasterLogsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowMasterStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowMasterStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowMigrateTaskStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowMigrateTaskStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr where;\n\n    public MySqlShowMigrateTaskStatusStatement() {\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowNodeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowNodeStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowOpenTablesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowOpenTablesStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr database;\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLExpr database) {\n        this.database = database;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowPartitionsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowPartitionsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName name;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowPhysicalProcesslistStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowPhysicalProcesslistStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean full;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowPlanCacheStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowPlanCacheStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLSelect select;\n\n    public MySqlShowPlanCacheStatement() {\n    }\n\n    public MySqlShowPlanCacheStatement(SQLSelect select) {\n        setSelect(select);\n    }\n\n    public void accept0(MySqlASTVisitor v) {\n        if (v.visit(this)) {\n            if (select != null) {\n                select.accept(v);\n            }\n        }\n        v.endVisit(this);\n    }\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.select = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowPlanCacheStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowPlanCacheStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowPluginsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowPluginsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowPrivilegesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowPrivilegesStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowProcedureCodeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowProcedureCodeStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr name;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr functionName) {\n        this.name = functionName;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowProcedureStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowProcedureStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowProcessListStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLShowProcessListStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlShowProcessListStatement extends SQLShowProcessListStatement implements MySqlShowStatement {\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowProfileStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlShowProfileStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private List<Type> types = new ArrayList<Type>();\n\n    private SQLExpr forQuery;\n\n    private SQLLimit limit;\n\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public List<Type> getTypes() {\n        return types;\n    }\n\n    public SQLExpr getForQuery() {\n        return forQuery;\n    }\n\n    public void setForQuery(SQLExpr forQuery) {\n        this.forQuery = forQuery;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public static enum Type {\n        ALL(\"ALL\"), BLOCK_IO(\"BLOCK IO\"), CONTEXT_SWITCHES(\"CONTEXT SWITCHES\"), CPU(\"CPU\"), IPC(\"IPC\"),\n        MEMORY(\"MEMORY\"), PAGE_FAULTS(\"PAGE FAULTS\"), SOURCE(\"SOURCE\"), SWAPS(\"SWAPS\");\n\n        public final String name;\n\n        Type(String name) {\n            this.name = name;\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowProfilesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowProfilesStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowRelayLogEventsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowRelayLogEventsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLExpr logName;\n    private SQLExpr from;\n    private SQLLimit limit;\n\n    public SQLExpr getLogName() {\n        return logName;\n    }\n\n    public void setLogName(SQLExpr logName) {\n        this.logName = logName;\n    }\n\n    public SQLExpr getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLExpr from) {\n        this.from = from;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, logName);\n            acceptChild(visitor, from);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowRuleStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowRuleStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName name;\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n    private boolean full;\n    private boolean version;\n\n    public MySqlShowRuleStatement() {\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public boolean isVersion() {\n        return version;\n    }\n\n    public void setVersion(boolean version) {\n        this.version = version;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowRuleStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowRuleStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean lite = true;\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n    private boolean full;\n    private boolean version;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public boolean isLite() {\n        return lite;\n    }\n\n    public void setLite(boolean lite) {\n        this.lite = lite;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isVersion() {\n        return version;\n    }\n\n    public void setVersion(boolean version) {\n        this.version = version;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowSequencesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowSequencesStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowSlaveHostsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowSlaveHostsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowSlaveStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowSlaveStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowSlowStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowSlowStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean physical;\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n    private boolean full;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public boolean isPhysical() {\n        return physical;\n    }\n\n    public void setPhysical(boolean physical) {\n        this.physical = physical;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLShowStatement;\n\npublic interface MySqlShowStatement extends MySqlStatement, SQLShowStatement {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean global;\n    private boolean session;\n\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public MySqlShowStatusStatement() {\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n\n    public boolean isSession() {\n        return session;\n    }\n\n    public void setSession(boolean session) {\n        this.session = session;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTableStatusStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowTableStatusStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName database;\n    private SQLName tableGroup;\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public MySqlShowTableStatusStatement() {\n    }\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName database) {\n        this.database = database;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n            acceptChild(visitor, tableGroup);\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getTableGroup() {\n        return tableGroup;\n    }\n\n    public void setTableGroup(SQLName tableGroup) {\n        this.tableGroup = tableGroup;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTopologyStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowTopologyStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean full;\n    private SQLName name;\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTraceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowTraceStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLOrderBy orderBy;\n    private SQLExpr where;\n    private SQLLimit limit;\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public SQLOrderBy getOrderBy() {\n        return orderBy;\n    }\n\n    public void setOrderBy(SQLOrderBy orderBy) {\n        this.orderBy = orderBy;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, where);\n            acceptChild(visitor, orderBy);\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTriggersStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowTriggersStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName database;\n    private SQLExpr like;\n    private SQLExpr where;\n\n    public SQLName getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLName database) {\n        this.database = database;\n    }\n\n    public SQLExpr getLike() {\n        return like;\n    }\n\n    public void setLike(SQLExpr like) {\n        this.like = like;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr where) {\n        this.where = where;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, database);\n            acceptChild(visitor, like);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowWarningsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlShowWarningsStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean count;\n    private SQLLimit limit;\n\n    public boolean isCount() {\n        return count;\n    }\n\n    public void setCount(boolean count) {\n        this.count = count;\n    }\n\n    public SQLLimit getLimit() {\n        return limit;\n    }\n\n    public void setLimit(SQLLimit limit) {\n        this.limit = limit;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, limit);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\n\npublic interface MySqlStatement extends SQLStatement, MySqlObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlStatementImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic abstract class MySqlStatementImpl extends SQLStatementImpl implements MySqlStatement {\n    public MySqlStatementImpl() {\n        super(DbType.mysql);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + visitor.getClass().getName());\n        }\n    }\n\n    public void accept0(MySqlASTVisitor v) {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n\n    public List<SQLObject> getChildren() {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSubPartitionByKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLSubPartitionBy;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlSubPartitionByKey extends SQLSubPartitionBy implements MySqlObject {\n    private int algorithm = 2;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + visitor.getClass().getName());\n        }\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, subPartitionsCount);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLName column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public void cloneTo(MySqlSubPartitionByKey x) {\n        super.cloneTo(x);\n        for (SQLName column : columns) {\n            SQLName c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n        x.algorithm = algorithm;\n    }\n\n    public MySqlSubPartitionByKey clone() {\n        MySqlSubPartitionByKey x = new MySqlSubPartitionByKey();\n        cloneTo(x);\n        return x;\n    }\n\n    public int getAlgorithm() {\n        return algorithm;\n    }\n\n    public void setAlgorithm(int algorithm) {\n        this.algorithm = algorithm;\n    }\n\n    public boolean isPartitionByColumn(long columnNameHashCode64) {\n        for (SQLName column : columns) {\n            if (column.nameHashCode64() == columnNameHashCode64) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSubPartitionByList.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLSubPartitionBy;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlSubPartitionByList extends SQLSubPartitionBy implements MySqlObject {\n    private List<SQLExpr> keys = new ArrayList<SQLExpr>();\n\n    private List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + visitor.getClass().getName());\n        }\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, keys);\n            acceptChild(visitor, columns);\n            acceptChild(visitor, subPartitionsCount);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLExpr> getKeys() {\n        return keys;\n    }\n\n    public void addKey(SQLExpr key) {\n        if (key != null) {\n            key.setParent(this);\n        }\n        this.keys.add(key);\n    }\n\n    public List<SQLColumnDefinition> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLColumnDefinition column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public void cloneTo(MySqlSubPartitionByList x) {\n        super.cloneTo(x);\n        for (SQLExpr key : keys) {\n            SQLExpr k2 = key.clone();\n            k2.setParent(x);\n            x.keys.add(k2);\n        }\n        for (SQLColumnDefinition column : columns) {\n            SQLColumnDefinition c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n    }\n\n    public MySqlSubPartitionByList clone() {\n        MySqlSubPartitionByList x = new MySqlSubPartitionByList();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSubPartitionByValue.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLSubPartitionBy;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlSubPartitionByValue extends SQLSubPartitionBy implements MySqlObject {\n    private List<SQLExpr> columns = new ArrayList<SQLExpr>();\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            throw new IllegalArgumentException(\"not support visitor type : \" + visitor.getClass().getName());\n        }\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, subPartitionsCount);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLExpr column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public void cloneTo(MySqlSubPartitionByValue x) {\n        super.cloneTo(x);\n        for (SQLExpr column : columns) {\n            SQLExpr c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n\n    }\n\n    public MySqlSubPartitionByValue clone() {\n        MySqlSubPartitionByValue x = new MySqlSubPartitionByValue();\n        cloneTo(x);\n        return x;\n    }\n\n    public boolean isPartitionByColumn(long columnNameHashCode64) {\n        for (SQLExpr column : columns) {\n            if (column instanceof SQLName) {\n                if (((SQLName) column).nameHashCode64() == columnNameHashCode64) {\n                    return true;\n                } else if (column instanceof SQLMethodInvokeExpr) {\n                    List<SQLExpr> arguments = ((SQLMethodInvokeExpr) column).getArguments();\n                    for (SQLExpr argument : arguments) {\n                        if (((SQLName) argument).nameHashCode64() == columnNameHashCode64) {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlTableIndex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLIndex;\nimport com.alibaba.druid.sql.ast.SQLIndexDefinition;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.List;\n\npublic class MySqlTableIndex extends SQLConstraintImpl implements SQLTableElement, SQLIndex, MySqlObject {\n    private SQLIndexDefinition indexDefinition = new SQLIndexDefinition();\n\n    public MySqlTableIndex() {\n        indexDefinition.setParent(this);\n    }\n\n    public SQLIndexDefinition getIndexDefinition() {\n        return indexDefinition;\n    }\n\n    public SQLName getName() {\n        return indexDefinition.getName();\n    }\n\n    public String getIndexType() {\n        return indexDefinition.getType();\n    }\n\n    public void setIndexType(String indexType) {\n        indexDefinition.setType(indexType);\n    }\n\n    public void setName(SQLName name) {\n        indexDefinition.setName(name);\n    }\n\n    public List<SQLSelectOrderByItem> getColumns() {\n        return indexDefinition.getColumns();\n    }\n\n    public void addColumn(SQLSelectOrderByItem column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.indexDefinition.getColumns().add(column);\n    }\n\n    public void accept0(SQLASTVisitor visitor) {\n        accept0((MySqlASTVisitor) visitor);\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (indexDefinition.getName() != null) {\n                indexDefinition.getName().accept(visitor);\n            }\n\n            for (int i = 0; i < indexDefinition.getColumns().size(); i++) {\n                final SQLSelectOrderByItem item = indexDefinition.getColumns().get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n\n            for (int i = 0; i < indexDefinition.getCovering().size(); i++) {\n                final SQLName item = indexDefinition.getCovering().get(i);\n                if (item != null) {\n                    item.accept(visitor);\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlTableIndex clone() {\n        MySqlTableIndex x = new MySqlTableIndex();\n        indexDefinition.cloneTo(x.indexDefinition);\n        return x;\n    }\n\n    public boolean applyColumnRename(SQLName columnName, SQLColumnDefinition to) {\n        for (SQLSelectOrderByItem orderByItem : getColumns()) {\n            SQLExpr expr = orderByItem.getExpr();\n            if (expr instanceof SQLName\n                    && SQLUtils.nameEquals((SQLName) expr, columnName)) {\n                orderByItem.setExpr(to.getName().clone());\n                return true;\n            }\n\n            if (expr instanceof SQLMethodInvokeExpr\n                    && SQLUtils.nameEquals(((SQLMethodInvokeExpr) expr).getMethodName(), columnName.getSimpleName())) {\n                // More complex when with key length.\n                if (1 == ((SQLMethodInvokeExpr) expr).getArguments().size() &&\n                        ((SQLMethodInvokeExpr) expr).getArguments().get(0) instanceof SQLIntegerExpr) {\n                    if (to.getDataType().hasKeyLength() &&\n                            1 == to.getDataType().getArguments().size() &&\n                            to.getDataType().getArguments().get(0) instanceof SQLIntegerExpr) {\n                        int newKeyLength = ((SQLIntegerExpr) to.getDataType().getArguments().get(0)).getNumber().intValue();\n                        int oldKeyLength = ((SQLIntegerExpr) ((SQLMethodInvokeExpr) expr).getArguments().get(0)).getNumber().intValue();\n                        if (newKeyLength > oldKeyLength) {\n                            // Change name and keep key length.\n                            ((SQLMethodInvokeExpr) expr).setMethodName(to.getName().getSimpleName());\n                            return true;\n                        }\n                    }\n                    // Remove key length.\n                    orderByItem.setExpr(to.getName().clone());\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public boolean applyDropColumn(SQLName columnName) {\n        for (int i = indexDefinition.getColumns().size() - 1; i >= 0; i--) {\n            SQLExpr expr = indexDefinition.getColumns().get(i).getExpr();\n            if (expr instanceof SQLName\n                    && SQLUtils.nameEquals((SQLName) expr, columnName)) {\n                indexDefinition.getColumns().remove(i);\n                return true;\n            }\n            if (expr instanceof SQLMethodInvokeExpr\n                    && SQLUtils.nameEquals(((SQLMethodInvokeExpr) expr).getMethodName(), columnName.getSimpleName())) {\n                indexDefinition.getColumns().remove(i);\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        indexDefinition.addOption(name, value);\n    }\n\n    public SQLExpr getOption(String name) {\n        return indexDefinition.getOption(name);\n    }\n\n    protected SQLExpr getOption(long hash64) {\n        return indexDefinition.getOption(hash64);\n    }\n\n    public String getDistanceMeasure() {\n        return indexDefinition.getDistanceMeasure();\n    }\n\n    public String getAlgorithm() {\n        return indexDefinition.getAlgorithm();\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return indexDefinition.getCompatibleOptions();\n    }\n\n    public SQLExpr getComment() {\n        return indexDefinition.getOptions().getComment();\n    }\n\n    public void setComment(SQLExpr x) {\n        this.indexDefinition.getOptions().setComment(x);\n    }\n\n    public SQLExpr getDbPartitionBy() {\n        return indexDefinition.getDbPartitionBy();\n    }\n\n    public void setDbPartitionBy(SQLExpr x) {\n        indexDefinition.setDbPartitionBy(x);\n    }\n\n    public SQLExpr getTablePartitions() {\n        return indexDefinition.getTbPartitions();\n    }\n\n    public void setTablePartitions(SQLExpr x) {\n        indexDefinition.setTbPartitions(x);\n    }\n\n    public SQLExpr getTablePartitionBy() {\n        return indexDefinition.getTbPartitionBy();\n    }\n\n    public void setTablePartitionBy(SQLExpr x) {\n        indexDefinition.setTbPartitionBy(x);\n    }\n\n    public void setCovering(List<SQLName> covering) {\n        indexDefinition.setCovering(covering);\n    }\n\n    public boolean isGlobal() {\n        return this.indexDefinition.isGlobal();\n    }\n\n    public void setGlobal(boolean global) {\n        this.indexDefinition.setGlobal(global);\n    }\n\n    public boolean isLocal() {\n        return this.indexDefinition.isLocal();\n    }\n\n    public void setLocal(boolean local) {\n        this.indexDefinition.setLocal(local);\n    }\n\n    @Override\n    public List<SQLName> getCovering() {\n        return indexDefinition.getCovering();\n    }\n\n    public SQLName getIndexAnalyzerName() {\n        return indexDefinition.getIndexAnalyzerName();\n    }\n\n    public void setIndexAnalyzerName(SQLName indexAnalyzerName) {\n        this.indexDefinition.setIndexAnalyzerName(indexAnalyzerName);\n    }\n\n    public SQLName getQueryAnalyzerName() {\n        return indexDefinition.getQueryAnalyzerName();\n    }\n\n    public void setQueryAnalyzerName(SQLName queryAnalyzerName) {\n        this.indexDefinition.setQueryAnalyzerName(queryAnalyzerName);\n    }\n\n    public void setPartitioning(SQLPartitionBy sqlPartitioning) {\n        this.indexDefinition.setPartitioning(sqlPartitioning);\n    }\n\n    public SQLPartitionBy getPartitioning() {\n        return this.indexDefinition.getPartitioning();\n    }\n\n    public SQLName getWithDicName() {\n        return indexDefinition.getWithDicName();\n    }\n\n    public void setWithDicName(SQLName withDicName) {\n        this.indexDefinition.setWithDicName(withDicName);\n    }\n\n    public SQLName getAnalyzerName() {\n        return indexDefinition.getAnalyzerName();\n    }\n\n    public void setAnalyzerName(SQLName analyzerName) {\n        this.indexDefinition.setAnalyzerName(analyzerName);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUnlockTablesStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2ASTVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class MySqlUnlockTablesStatement extends MySqlStatementImpl {\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof H2ASTVisitor) {\n            return;\n        }\n        super.accept0(visitor);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUpdatePlanCacheStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlUpdatePlanCacheStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLSelect formSelect;\n    private SQLSelect toSelect;\n\n    public SQLSelect getFormSelect() {\n        return formSelect;\n    }\n\n    public void setFormSelect(SQLSelect formSelect) {\n        this.formSelect = formSelect;\n    }\n\n    public SQLSelect getToSelect() {\n        return toSelect;\n    }\n\n    public void setToSelect(SQLSelect toSelect) {\n        this.toSelect = toSelect;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, formSelect);\n            acceptChild(visitor, toSelect);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUpdateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlUpdateStatement extends SQLUpdateStatement implements MySqlStatement {\n    private boolean lowPriority;\n    private boolean ignore;\n    private boolean commitOnSuccess;\n    private boolean rollBackOnFail;\n    private boolean queryOnPk;\n    private SQLExpr targetAffectRow;\n\n    // for petadata\n    private boolean forceAllPartitions;\n    private SQLName forcePartition;\n\n    protected List<SQLCommentHint> hints;\n\n    public MySqlUpdateStatement() {\n        super(DbType.mysql);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (tableSource != null) {\n                tableSource.accept(visitor);\n            }\n\n            if (from != null) {\n                from.accept(visitor);\n            }\n\n            if (items != null) {\n                for (int i = 0; i < items.size(); i++) {\n                    SQLUpdateSetItem item = items.get(i);\n                    if (item != null) {\n                        item.accept(visitor);\n                    }\n                }\n            }\n\n            if (where != null) {\n                where.accept(visitor);\n            }\n\n            if (orderBy != null) {\n                orderBy.accept(visitor);\n            }\n\n            if (limit != null) {\n                limit.accept(visitor);\n            }\n\n            if (hints != null) {\n                for (int i = 0; i < hints.size(); i++) {\n                    SQLCommentHint hint = hints.get(i);\n                    if (hint != null) {\n                        hint.accept(visitor);\n                    }\n                }\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isLowPriority() {\n        return lowPriority;\n    }\n\n    public void setLowPriority(boolean lowPriority) {\n        this.lowPriority = lowPriority;\n    }\n\n    public boolean isIgnore() {\n        return ignore;\n    }\n\n    public void setIgnore(boolean ignore) {\n        this.ignore = ignore;\n    }\n\n    public boolean isCommitOnSuccess() {\n        return commitOnSuccess;\n    }\n\n    public void setCommitOnSuccess(boolean commitOnSuccess) {\n        this.commitOnSuccess = commitOnSuccess;\n    }\n\n    public boolean isRollBackOnFail() {\n        return rollBackOnFail;\n    }\n\n    public void setRollBackOnFail(boolean rollBackOnFail) {\n        this.rollBackOnFail = rollBackOnFail;\n    }\n\n    public boolean isQueryOnPk() {\n        return queryOnPk;\n    }\n\n    public void setQueryOnPk(boolean queryOnPk) {\n        this.queryOnPk = queryOnPk;\n    }\n\n    public SQLExpr getTargetAffectRow() {\n        return targetAffectRow;\n    }\n\n    public void setTargetAffectRow(SQLExpr targetAffectRow) {\n        if (targetAffectRow != null) {\n            targetAffectRow.setParent(this);\n        }\n        this.targetAffectRow = targetAffectRow;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        MySqlUpdateStatement that = (MySqlUpdateStatement) o;\n\n        if (lowPriority != that.lowPriority) {\n            return false;\n        }\n        if (ignore != that.ignore) {\n            return false;\n        }\n        if (commitOnSuccess != that.commitOnSuccess) {\n            return false;\n        }\n        if (rollBackOnFail != that.rollBackOnFail) {\n            return false;\n        }\n        if (queryOnPk != that.queryOnPk) {\n            return false;\n        }\n        if (this.hints != null ? !hints.equals(that.hints) : that.hints != null) {\n            return false;\n        }\n        if (limit != null ? !limit.equals(that.limit) : that.limit != null) {\n            return false;\n        }\n        return targetAffectRow != null ? targetAffectRow.equals(that.targetAffectRow) : that.targetAffectRow == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = super.hashCode();\n        result = 31 * result + (limit != null ? limit.hashCode() : 0);\n        result = 31 * result + (lowPriority ? 1 : 0);\n        result = 31 * result + (ignore ? 1 : 0);\n        result = 31 * result + (commitOnSuccess ? 1 : 0);\n        result = 31 * result + (rollBackOnFail ? 1 : 0);\n        result = 31 * result + (queryOnPk ? 1 : 0);\n        result = 31 * result + (targetAffectRow != null ? targetAffectRow.hashCode() : 0);\n        result = 31 * result + (hints != null ? hints.hashCode() : 0);\n        return result;\n    }\n\n    public SQLName getForcePartition() {\n        return forcePartition;\n    }\n\n    public void setForcePartition(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.forcePartition = x;\n    }\n\n    public boolean isForceAllPartitions() {\n        return forceAllPartitions;\n    }\n\n    public void setForceAllPartitions(boolean forceAllPartitions) {\n        this.forceAllPartitions = forceAllPartitions;\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n\n        return hints.size();\n    }\n\n    public List<SQLCommentHint> getHints() {\n        if (hints == null) {\n            hints = new ArrayList<SQLCommentHint>(2);\n        }\n        return hints;\n    }\n\n    public void setHints(List<SQLCommentHint> hints) {\n        this.hints = hints;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlUpdateTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSourceImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n// just for alibaba mysql\npublic class MySqlUpdateTableSource extends SQLTableSourceImpl {\n    private MySqlUpdateStatement update;\n\n    public MySqlUpdateTableSource(MySqlUpdateStatement update) {\n        this.update = update;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof MySqlASTVisitor) {\n            accept0((MySqlASTVisitor) visitor);\n        }\n        super.accept0(visitor);\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, update);\n        }\n        visitor.endVisit(this);\n    }\n\n    public MySqlUpdateStatement getUpdate() {\n        return update;\n    }\n\n    public void setUpdate(MySqlUpdateStatement update) {\n        this.update = update;\n    }\n\n    @Override\n    public MySqlUpdateTableSource clone() {\n        MySqlUpdateTableSource x = new MySqlUpdateTableSource(this.update);\n\n        x.setAlias(this.alias);\n\n        if (this.flashback != null) {\n            x.setFlashback(this.flashback.clone());\n        }\n\n        if (this.hints != null) {\n            for (SQLHint e : this.hints) {\n                SQLHint e2 = e.clone();\n                e2.setParent(x);\n                x.getHints().add(e2);\n            }\n        }\n\n        return x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlXAStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.DruidRuntimeException;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MySqlXAStatement extends MySqlStatementImpl {\n    private XAType type;\n    private SQLExpr id;\n\n    public XAType getType() {\n        return type;\n    }\n\n    public void setType(XAType type) {\n        this.type = type;\n    }\n\n    public SQLExpr getId() {\n        return id;\n    }\n\n    public void setId(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.id = x;\n    }\n\n    public void accept0(MySqlASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, id);\n        }\n        v.endVisit(this);\n    }\n\n    public enum XAType {\n        START,\n        BEGIN,\n        END,\n        PREPARE,\n        COMMIT,\n        ROLLBACK,\n        RECOVER;\n\n        public static XAType of(String typeStr) {\n            if (typeStr == null || typeStr.isEmpty()) {\n                return null;\n            }\n\n            switch (typeStr.toUpperCase()) {\n                case \"START\":\n                    return XAType.START;\n                case \"BEGIN\":\n                    return XAType.BEGIN;\n                case \"END\":\n                    return XAType.END;\n                case \"PREPARE\":\n                    return XAType.PREPARE;\n                case \"COMMIT\":\n                    return XAType.COMMIT;\n                case \"ROLLBACK\":\n                    return XAType.ROLLBACK;\n                case \"RECOVER\":\n                    return XAType.RECOVER;\n                default:\n                    throw new DruidRuntimeException(\"not support xa type \" + typeStr);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlAlterFullTextStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.FullTextType;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MysqlAlterFullTextStatement extends MySqlStatementImpl implements SQLAlterStatement {\n    private FullTextType type;\n\n    private SQLName name;\n\n    private SQLAssignItem item;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public FullTextType getType() {\n        return type;\n    }\n\n    public void setType(FullTextType type) {\n        this.type = type;\n    }\n\n    public SQLAssignItem getItem() {\n        return item;\n    }\n\n    public void setItem(SQLAssignItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.item = item;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlAlterTableAlterCheck.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MysqlAlterTableAlterCheck extends MySqlObjectImpl implements SQLAlterTableItem {\n    private SQLName name;\n    private Boolean enforced;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (getName() != null) {\n                getName().accept(visitor);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public Boolean getEnforced() {\n        return enforced;\n    }\n\n    public void setEnforced(Boolean enforced) {\n        this.enforced = enforced;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlCreateFullTextAnalyzerStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author lijun.cailj 2018/8/13\n */\npublic class MysqlCreateFullTextAnalyzerStatement extends MySqlStatementImpl {\n    private SQLName name;\n\n    private String tokenizer;\n    private List<String> charfilters = new ArrayList<String>();\n    private List<String> tokenizers = new ArrayList<String>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public String getTokenizer() {\n        return tokenizer;\n    }\n\n    public void setTokenizer(String tokenizer) {\n        this.tokenizer = tokenizer;\n    }\n\n    public List<String> getCharfilters() {\n        return charfilters;\n    }\n\n    public List<String> getTokenizers() {\n        return tokenizers;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlCreateFullTextCharFilterStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLTextLiteralExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author lijun.cailj 2018/8/13\n */\npublic class MysqlCreateFullTextCharFilterStatement extends MySqlStatementImpl {\n    private SQLName name; // for all, not null\n    private SQLTextLiteralExpr typeName;  // for charfilter/tokenizer/tokenfilter\n\n    protected final List<SQLAssignItem> options = new ArrayList<SQLAssignItem>(); // charfilter/tokenizer/tokenfilter\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, typeName);\n            acceptChild(visitor, options);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLTextLiteralExpr getTypeName() {\n        return typeName;\n    }\n\n    public void setTypeName(SQLTextLiteralExpr typeName) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.typeName = typeName;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        options.add(assignItem);\n    }\n\n    public SQLExpr getOption(String name) {\n        if (name == null) {\n            return null;\n        }\n\n        long hash64 = FnvHash.hashCode64(name);\n\n        for (SQLAssignItem item : options) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public Object getOptionValue(String name) {\n        SQLExpr option = getOption(name);\n        if (option instanceof SQLValuableExpr) {\n            return ((SQLValuableExpr) option).getValue();\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlCreateFullTextDictionaryStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MysqlCreateFullTextDictionaryStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private SQLName name;\n\n    private SQLColumnDefinition column;\n\n    private String comment;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLColumnDefinition getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLColumnDefinition column) {\n        this.column = column;\n    }\n\n    public String getComment() {\n        return comment;\n    }\n\n    public void setComment(String comment) {\n        this.comment = comment;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, column);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlCreateFullTextTokenFilterStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLTextLiteralExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author lijun.cailj 2018/8/13\n */\npublic class MysqlCreateFullTextTokenFilterStatement extends MySqlStatementImpl {\n    private SQLName name;\n    private SQLTextLiteralExpr typeName;\n    protected final List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, typeName);\n            acceptChild(visitor, options);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLTextLiteralExpr getTypeName() {\n        return typeName;\n    }\n\n    public void setTypeName(SQLTextLiteralExpr typeName) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.typeName = typeName;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        options.add(assignItem);\n    }\n\n    public SQLExpr getOption(String name) {\n        if (name == null) {\n            return null;\n        }\n\n        long hash64 = FnvHash.hashCode64(name);\n\n        for (SQLAssignItem item : options) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public Object getOptionValue(String name) {\n        SQLExpr option = getOption(name);\n        if (option instanceof SQLValuableExpr) {\n            return ((SQLValuableExpr) option).getValue();\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlCreateFullTextTokenizerStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLTextLiteralExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author lijun.cailj 2018/8/13\n */\npublic class MysqlCreateFullTextTokenizerStatement extends MySqlStatementImpl {\n    private SQLName name;\n    private SQLTextLiteralExpr typeName;\n    private SQLTextLiteralExpr userDefinedDict;\n    protected final List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, typeName);\n            acceptChild(visitor, options);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLTextLiteralExpr getUserDefinedDict() {\n        return userDefinedDict;\n    }\n\n    public void setUserDefinedDict(SQLTextLiteralExpr userDefinedDict) {\n        this.userDefinedDict = userDefinedDict;\n    }\n\n    public SQLTextLiteralExpr getTypeName() {\n        return typeName;\n    }\n\n    public void setTypeName(SQLTextLiteralExpr typeName) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.typeName = typeName;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        options.add(assignItem);\n    }\n\n    public SQLExpr getOption(String name) {\n        if (name == null) {\n            return null;\n        }\n\n        long hash64 = FnvHash.hashCode64(name);\n\n        for (SQLAssignItem item : options) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                if (((SQLIdentifierExpr) target).hashCode64() == hash64) {\n                    return item.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public Object getOptionValue(String name) {\n        SQLExpr option = getOption(name);\n        if (option instanceof SQLValuableExpr) {\n            return ((SQLValuableExpr) option).getValue();\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlDeallocatePrepareStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class MysqlDeallocatePrepareStatement extends MySqlStatementImpl {\n    private SQLName statementName;\n\n    public SQLName getStatementName() {\n        return statementName;\n    }\n\n    public void setStatementName(SQLName statementName) {\n        this.statementName = statementName;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statementName);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(statementName);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlDropFullTextStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLDropStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.FullTextType;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MysqlDropFullTextStatement extends MySqlStatementImpl implements SQLDropStatement {\n    private FullTextType type;\n\n    private SQLName name;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public FullTextType getType() {\n        return type;\n    }\n\n    public void setType(FullTextType type) {\n        this.type = type;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlShowCreateFullTextStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.mysql.ast.FullTextType;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MysqlShowCreateFullTextStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private FullTextType type;\n\n    private SQLName name;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public FullTextType getType() {\n        return type;\n    }\n\n    public void setType(FullTextType type) {\n        this.type = type;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlShowDbLockStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * @author lijun.cailj 2017/11/16\n */\npublic class MysqlShowDbLockStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlShowFullTextStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.ast.FullTextType;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\npublic class MysqlShowFullTextStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private FullTextType type;\n\n    public FullTextType getType() {\n        return type;\n    }\n\n    public void setType(FullTextType type) {\n        this.type = type;\n    }\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlShowHtcStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * @author lijun.cailj 2017/11/16\n */\npublic class MysqlShowHtcStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean full;\n    private boolean isHis;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public boolean isHis() {\n        return isHis;\n    }\n\n    public void setHis(boolean his) {\n        isHis = his;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MysqlShowStcStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\n/**\n * @author lijun.cailj 2017/11/16\n */\npublic class MysqlShowStcStatement extends MySqlStatementImpl implements MySqlShowStatement {\n    private boolean full;\n    private boolean isHis;\n\n    @Override\n    public void accept0(MySqlASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public boolean isHis() {\n        return isHis;\n    }\n\n    public void setHis(boolean his) {\n        isHis = his;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/SQLAlterResourceGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class SQLAlterResourceGroupStatement\n        extends SQLStatementImpl\n        implements SQLCreateStatement {\n    private SQLName name;\n    private Map<String, SQLExpr> properties = new HashMap<String, SQLExpr>();\n    private Boolean enable;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public void addProperty(String name, SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        properties.put(name, value);\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public Map<String, SQLExpr> getProperties() {\n        return properties;\n    }\n\n    public void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n            for (SQLExpr value : properties.values()) {\n                acceptChild(v, value);\n            }\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/SQLCreateResourceGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class SQLCreateResourceGroupStatement\n        extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n    private Map<String, SQLExpr> properties = new HashMap<String, SQLExpr>();\n    private Boolean enable;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public void addProperty(String name, SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        properties.put(name, value);\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public Map<String, SQLExpr> getProperties() {\n        return properties;\n    }\n\n    public void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n            for (SQLExpr value : properties.values()) {\n                acceptChild(v, value);\n            }\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/SQLListResourceGroupStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLListResourceGroupStatement\n        extends SQLStatementImpl implements SQLCreateStatement {\n    public void accept0(SQLASTVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/TidbSplitTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.ast.statement;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author lizongbo\n * @see  <a href=\"https://docs.pingcap.com/zh/tidb/stable/sql-statement-split-region\">...</a>\n */\npublic class TidbSplitTableStatement extends MySqlStatementImpl {\n    //region for\n    private boolean splitSyntaxOptionRegionFor;\n    //partition\n    private boolean splitSyntaxOptionPartition;\n\n    private SQLExprTableSource tableName;\n\n    private List<SQLExpr> partitionNameListOptions = new ArrayList<>();\n\n    private SQLName indexName;\n\n    private List<List<SQLExpr>> splitOptionBys = new ArrayList<>();\n    private List<SQLExpr> splitOptionBetween;\n    private List<SQLExpr> splitOptionAnd;\n    private long splitOptionRegions;\n\n    public boolean isSplitSyntaxOptionRegionFor() {\n        return splitSyntaxOptionRegionFor;\n    }\n\n    public void setSplitSyntaxOptionRegionFor(boolean splitSyntaxOptionRegionFor) {\n        this.splitSyntaxOptionRegionFor = splitSyntaxOptionRegionFor;\n    }\n\n    public boolean isSplitSyntaxOptionPartition() {\n        return splitSyntaxOptionPartition;\n    }\n\n    public void setSplitSyntaxOptionPartition(boolean splitSyntaxOptionPartition) {\n        this.splitSyntaxOptionPartition = splitSyntaxOptionPartition;\n    }\n\n    public SQLExprTableSource getTableName() {\n        return tableName;\n    }\n\n    public void setTableName(SQLExprTableSource tableName) {\n        this.tableName = tableName;\n    }\n\n    public List<SQLExpr> getPartitionNameListOptions() {\n        return partitionNameListOptions;\n    }\n\n    public void setPartitionNameListOptions(List<SQLExpr> partitionNameListOptions) {\n        this.partitionNameListOptions = partitionNameListOptions;\n    }\n\n    public SQLName getIndexName() {\n        return indexName;\n    }\n\n    public void setIndexName(SQLName indexName) {\n        this.indexName = indexName;\n    }\n\n    public List<List<SQLExpr>> getSplitOptionBys() {\n        return splitOptionBys;\n    }\n\n    public void setSplitOptionBys(List<List<SQLExpr>> splitOptionBys) {\n        this.splitOptionBys = splitOptionBys;\n    }\n\n    public List<SQLExpr> getSplitOptionBetween() {\n        return splitOptionBetween;\n    }\n\n    public void setSplitOptionBetween(List<SQLExpr> splitOptionBetween) {\n        this.splitOptionBetween = splitOptionBetween;\n    }\n\n    public List<SQLExpr> getSplitOptionAnd() {\n        return splitOptionAnd;\n    }\n\n    public void setSplitOptionAnd(List<SQLExpr> splitOptionAnd) {\n        this.splitOptionAnd = splitOptionAnd;\n    }\n\n    public long getSplitOptionRegions() {\n        return splitOptionRegions;\n    }\n\n    public void setSplitOptionRegions(long splitOptionRegions) {\n        this.splitOptionRegions = splitOptionRegions;\n    }\n\n    public void accept0(MySqlASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.getTableName().accept(visitor);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/executor/MySqlProcedureExecutor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.executor;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlProcedureExecutor {\n    public static int executeStatements(List<SQLStatement> list) {\n        return 0;\n    }\n\n    public static int executeStatement(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeIf(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeWhile(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeLoop(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeCase(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeAssign(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeOpen(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeFetch(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeClose(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeSQL(SQLStatement stmt) {\n        return 0;\n    }\n\n    public static int executeFunction(SQLStatement stmt) {\n        return 0;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MysqlPartitionSingle;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement.TableSpaceOption;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.MySqlUtils;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class MySqlCreateTableParser extends SQLCreateTableParser {\n    protected final Set<Long> supportOptions = new HashSet<>();\n\n    {\n        String[] supportOptions = new String[] {\n                \"PAGE_CHECKSUM\",\n                \"TRANSACTIONAL\",\n                \"BLOCK_FORMAT\",\n                \"REPLICA_NUM\",\n                \"TABLET_SIZE\",\n\n                \"USE_BLOOM_FILTER\",\n                \"AUTO_INCREMENT\",\n                \"AVG_ROW_LENGTH\",\n                \"CHECKSUM\",\n                \"CONNECTION\",\n\n                \"DELAY_KEY_WRITE\",\n                \"FULLTEXT_DICT\",\n                \"INSERT_METHOD\",\n                \"KEY_BLOCK_SIZE\",\n                \"MAX_ROWS\",\n\n                \"MIN_ROWS\",\n                \"PACK_KEYS\",\n                \"PASSWORD\",\n                \"ROW_FORMAT\",\n                \"STATS_AUTO_RECALC\",\n\n                \"STATS_PERSISTENT\",\n                \"STATS_SAMPLE_PAGES\",\n                \"STORAGE_TYPE\",\n                \"TABLE_PROPERTIES\",\n                \"ENCRYPTION\",\n\n                \"COMPRESSION\",\n                \"STORAGE_POLICY\"\n        };\n        for (String supportName : supportOptions) {\n            this.supportOptions.add(FnvHash.hashCode64(supportName));\n        }\n    }\n\n    public MySqlCreateTableParser(String sql) {\n        super(new MySqlExprParser(sql));\n    }\n\n    public MySqlCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    @Override\n    public MySqlExprParser getExprParser() {\n        return (MySqlExprParser) exprParser;\n    }\n\n    public MySqlCreateTableStatement parseCreateTable() {\n        MySqlCreateTableStatement stmt = new MySqlCreateTableStatement();\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            stmt.addBeforeComment(lexer.readAndResetComments());\n        }\n        accept(Token.CREATE);\n\n        if (lexer.nextIfIdentifier(\"TEMPORARY\")) {\n            stmt.config(SQLCreateTableStatement.Feature.Temporary);\n        } else if (lexer.nextIfIdentifier(\"SHADOW\")) {\n            stmt.config(SQLCreateTableStatement.Feature.Shadow);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DIMENSION)) {\n            lexer.nextToken();\n            stmt.setDimension(true);\n        }\n\n        if (lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(stmt.getHints());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            lexer.nextToken();\n            stmt.setExternal(true);\n        }\n\n        accept(Token.TABLE);\n\n        if (lexer.token() == Token.IF || lexer.identifierEquals(\"IF\")) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            SQLName name = this.exprParser.name();\n            stmt.setLike(name);\n        }\n\n        if (lexer.token() == Token.WITH) {\n            SQLSelect query = new MySqlSelectParser(this.exprParser).select();\n            stmt.setSelect(query);\n        } else if (lexer.token() == (Token.LPAREN)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.SELECT) {\n                SQLSelect query = new MySqlSelectParser(this.exprParser).select();\n                stmt.setSelect(query);\n            } else {\n                for (; ; ) {\n                    SQLColumnDefinition column = null;\n\n                    boolean global = false;\n                    if (lexer.identifierEquals(FnvHash.Constants.GLOBAL)) {\n                        final Lexer.SavePoint mark = lexer.mark();\n                        lexer.nextToken();\n                        if (lexer.token() == Token.INDEX || lexer.token() == Token.UNIQUE) {\n                            global = true;\n                        } else {\n                            lexer.reset(mark);\n                        }\n                    }\n\n                    boolean local = false;\n                    if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n                        final Lexer.SavePoint mark = lexer.mark();\n                        lexer.nextToken();\n                        if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY\n                            || lexer.token() == Token.UNIQUE) {\n                            local = true;\n                        } else if (lexer.token() == Token.FULLTEXT) {\n                            lexer.nextToken();\n\n                            if (lexer.token() == Token.KEY) {\n                                MySqlKey fulltextKey = new MySqlKey();\n                                this.exprParser.parseIndex(fulltextKey.getIndexDefinition());\n                                fulltextKey.setIndexType(\"FULLTEXT\");\n                                fulltextKey.setParent(stmt);\n                                stmt.getTableElementList().add(fulltextKey);\n\n                                while (lexer.token() == Token.HINT) {\n                                    lexer.nextToken();\n                                }\n\n                                if (lexer.token() == Token.RPAREN) {\n                                    break;\n                                } else if (lexer.token() == Token.COMMA) {\n                                    lexer.nextToken();\n                                    continue;\n                                }\n                            } else if (lexer.token() == Token.INDEX) {\n                                MySqlTableIndex idx = new MySqlTableIndex();\n                                this.exprParser.parseIndex(idx.getIndexDefinition());\n                                idx.setIndexType(\"FULLTEXT\");\n                                idx.setParent(stmt);\n                                stmt.getTableElementList().add(idx);\n\n                                if (lexer.token() == Token.RPAREN) {\n                                    break;\n                                } else if (lexer.token() == Token.COMMA) {\n                                    lexer.nextToken();\n                                    continue;\n                                }\n                            } else if (lexer.token() == Token.IDENTIFIER && MySqlUtils.isBuiltinDataType(\n                                lexer.stringVal())) {\n                                lexer.reset(mark);\n                            } else {\n                                MySqlTableIndex idx = new MySqlTableIndex();\n                                this.exprParser.parseIndex(idx.getIndexDefinition());\n                                idx.setIndexType(\"FULLTEXT\");\n                                idx.setParent(stmt);\n                                stmt.getTableElementList().add(idx);\n\n                                if (lexer.token() == Token.RPAREN) {\n                                    break;\n                                } else if (lexer.token() == Token.COMMA) {\n                                    lexer.nextToken();\n                                    continue;\n                                }\n                            }\n\n                        } else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {\n                            lexer.nextToken();\n                            if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY ||\n                                lexer.token() != Token.IDENTIFIER || !MySqlUtils.isBuiltinDataType(lexer.stringVal())) {\n                                MySqlTableIndex idx = new MySqlTableIndex();\n                                this.exprParser.parseIndex(idx.getIndexDefinition());\n                                idx.setIndexType(\"SPATIAL\");\n                                idx.setParent(stmt);\n                                stmt.getTableElementList().add(idx);\n\n                                if (lexer.token() == Token.RPAREN) {\n                                    break;\n                                } else if (lexer.token() == Token.COMMA) {\n                                    lexer.nextToken();\n                                    continue;\n                                }\n                            } else {\n                                lexer.reset(mark);\n                            }\n                        } else {\n                            lexer.reset(mark);\n                        }\n                    }\n\n                    if (lexer.token() == Token.FULLTEXT) {\n                        Lexer.SavePoint mark = lexer.mark();\n                        lexer.nextToken();\n\n                        if (lexer.token() == Token.KEY) {\n                            MySqlKey fulltextKey = new MySqlKey();\n                            this.exprParser.parseIndex(fulltextKey.getIndexDefinition());\n                            fulltextKey.setIndexType(\"FULLTEXT\");\n                            fulltextKey.setParent(stmt);\n                            stmt.getTableElementList().add(fulltextKey);\n\n                            while (lexer.token() == Token.HINT) {\n                                lexer.nextToken();\n                            }\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            } else if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        } else if (lexer.token() == Token.INDEX) {\n                            MySqlTableIndex idx = new MySqlTableIndex();\n                            this.exprParser.parseIndex(idx.getIndexDefinition());\n                            idx.setIndexType(\"FULLTEXT\");\n                            idx.setParent(stmt);\n                            stmt.getTableElementList().add(idx);\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            } else if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        } else if (lexer.token() == Token.IDENTIFIER && MySqlUtils.isBuiltinDataType(lexer.stringVal())) {\n                            lexer.reset(mark);\n                        } else {\n                            MySqlTableIndex idx = new MySqlTableIndex();\n                            this.exprParser.parseIndex(idx.getIndexDefinition());\n                            idx.setIndexType(\"FULLTEXT\");\n                            idx.setParent(stmt);\n                            stmt.getTableElementList().add(idx);\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            } else if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        }\n\n                    } else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {\n                        Lexer.SavePoint mark = lexer.mark();\n                        lexer.nextToken();\n                        if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY ||\n                                lexer.token() != Token.IDENTIFIER || !MySqlUtils.isBuiltinDataType(lexer.stringVal())) {\n                            MySqlTableIndex idx = new MySqlTableIndex();\n                            this.exprParser.parseIndex(idx.getIndexDefinition());\n                            idx.setIndexType(\"SPATIAL\");\n                            idx.setParent(stmt);\n                            stmt.getTableElementList().add(idx);\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            } else if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        } else {\n                            lexer.reset(mark);\n                        }\n                    }\n\n                    if (lexer.identifierEquals(FnvHash.Constants.ANN)) {\n                        Lexer.SavePoint mark = lexer.mark();\n                        lexer.nextToken();\n                        if (lexer.token() == Token.INDEX || lexer.token() == Token.KEY) {\n                            MySqlTableIndex idx = new MySqlTableIndex();\n                            this.exprParser.parseIndex(idx.getIndexDefinition());\n                            idx.setIndexType(\"ANN\");\n                            idx.setParent(stmt);\n                            stmt.getTableElementList().add(idx);\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            } else if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        } else {\n                            lexer.reset(mark);\n                        }\n                    }\n                    if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.KEY) {\n                            MySqlKey clsKey = new MySqlKey();\n                            this.exprParser.parseIndex(clsKey.getIndexDefinition());\n                            clsKey.setIndexType(\"CLUSTERED\");\n                            clsKey.setParent(stmt);\n                            stmt.getTableElementList().add(clsKey);\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        } else if (lexer.token() == Token.INDEX) {\n                            MySqlTableIndex idx = new MySqlTableIndex();\n                            this.exprParser.parseIndex(idx.getIndexDefinition());\n                            idx.setIndexType(\"CLUSTERED\");\n                            idx.setParent(stmt);\n                            stmt.getTableElementList().add(idx);\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            } else if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        }\n                    } else if (lexer.identifierEquals(FnvHash.Constants.CLUSTERING)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.KEY) {\n                            MySqlKey clsKey = new MySqlKey();\n                            this.exprParser.parseIndex(clsKey.getIndexDefinition());\n                            clsKey.setIndexType(\"CLUSTERING\");\n                            clsKey.setParent(stmt);\n                            stmt.getTableElementList().add(clsKey);\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        } else if (lexer.token() == Token.INDEX) {\n                            MySqlTableIndex idx = new MySqlTableIndex();\n                            this.exprParser.parseIndex(idx.getIndexDefinition());\n                            idx.setIndexType(\"CLUSTERING\");\n                            idx.setParent(stmt);\n                            stmt.getTableElementList().add(idx);\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            } else if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                        }\n                    } else if (lexer.token() == Token.IDENTIFIER //\n                            || lexer.token() == Token.LITERAL_CHARS) {\n                        column = this.exprParser.parseColumn();\n                        column.setParent(stmt);\n                        stmt.getTableElementList().add(column);\n\n                        if (lexer.isKeepComments() && lexer.hasComment()) {\n                            column.addAfterComment(lexer.readAndResetComments());\n                        }\n                    } else if (lexer.token() == Token.CONSTRAINT //\n                            || lexer.token() == Token.PRIMARY //\n                            || lexer.token() == Token.UNIQUE) {\n                        SQLTableConstraint constraint = this.parseConstraint();\n                        constraint.setParent(stmt);\n\n                        if (constraint instanceof MySqlUnique) {\n                            MySqlUnique unique = (MySqlUnique) constraint;\n                            if (global) {\n                                unique.setGlobal(true);\n                            }\n                            if (local) {\n                                unique.setLocal(true);\n                            }\n                        }\n\n                        stmt.getTableElementList().add(constraint);\n                    } else if (lexer.token() == (Token.INDEX)) {\n                        MySqlTableIndex idx = new MySqlTableIndex();\n                        this.exprParser.parseIndex(idx.getIndexDefinition());\n\n                        if (global) {\n                            idx.getIndexDefinition().setGlobal(true);\n                        }\n\n                        if (local) {\n                            idx.getIndexDefinition().setLocal(true);\n                        }\n\n                        idx.setParent(stmt);\n                        stmt.getTableElementList().add(idx);\n                    } else if (lexer.token() == (Token.KEY)) {\n                        Lexer.SavePoint savePoint = lexer.mark();\n                        lexer.nextToken();\n\n                        boolean isColumn = false;\n                        if (lexer.identifierEquals(FnvHash.Constants.VARCHAR)) {\n                            isColumn = true;\n                        }\n                        lexer.reset(savePoint);\n\n                        if (isColumn) {\n                            column = this.exprParser.parseColumn();\n                            stmt.getTableElementList().add(column);\n                        } else {\n                            stmt.getTableElementList().add(parseConstraint());\n                        }\n                    } else if (lexer.token() == (Token.PRIMARY)) {\n                        SQLTableConstraint pk = parseConstraint();\n                        pk.setParent(stmt);\n                        stmt.getTableElementList().add(pk);\n                    } else if (lexer.token() == (Token.FOREIGN)) {\n                        SQLForeignKeyConstraint fk = this.getExprParser().parseForeignKey();\n                        fk.setParent(stmt);\n                        stmt.getTableElementList().add(fk);\n                    } else if (lexer.token() == Token.CHECK) {\n                        SQLCheck check = this.exprParser.parseCheck();\n                        stmt.getTableElementList().add(check);\n                    } else if (lexer.token() == Token.LIKE) {\n                        lexer.nextToken();\n                        SQLTableLike tableLike = new SQLTableLike();\n                        tableLike.setTable(new SQLExprTableSource(this.exprParser.name()));\n                        tableLike.setParent(stmt);\n                        stmt.getTableElementList().add(tableLike);\n\n                        if (lexer.identifierEquals(FnvHash.Constants.INCLUDING)) {\n                            lexer.nextToken();\n                            acceptIdentifier(\"PROPERTIES\");\n                            tableLike.setIncludeProperties(true);\n                        } else if (lexer.identifierEquals(FnvHash.Constants.EXCLUDING)) {\n                            lexer.nextToken();\n                            acceptIdentifier(\"PROPERTIES\");\n                            tableLike.setExcludeProperties(true);\n                        }\n                    } else {\n                        column = this.exprParser.parseColumn();\n                        stmt.getTableElementList().add(column);\n                    }\n\n                    if (lexer.token() == Token.HINT) {\n                        lexer.nextToken();\n                    }\n\n                    if (lexer.token() != Token.COMMA) {\n                        break;\n                    } else {\n                        lexer.nextToken();\n                        if (lexer.isKeepComments() && lexer.hasComment() && column != null) {\n                            column.addAfterComment(lexer.readAndResetComments());\n                        }\n                    }\n                }\n            }\n\n            if (lexer.token() == Token.HINT) {\n                lexer.nextToken();\n            }\n\n            accept(Token.RPAREN);\n\n            if (lexer.token() == Token.HINT && lexer.stringVal().charAt(0) == '!') {\n                lexer.nextToken();\n            }\n        }\n\n        parseOptions(stmt);\n\n        if (lexer.token() == (Token.ON)) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        if (lexer.token() == Token.REPLACE) {\n            lexer.nextToken();\n            stmt.setReplace(true);\n        } else if (lexer.identifierEquals(\"IGNORE\")) {\n            lexer.nextToken();\n            stmt.setIgnore(true);\n        } else if (lexer.identifierEquals(\"SINGLE\")) { // for polardb-x\n            lexer.nextToken();\n            stmt.setSingle(true);\n        }\n\n        if (lexer.token() == (Token.AS)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                SQLSelect query = new MySqlSelectParser(this.exprParser).select();\n                stmt.setSelect(query);\n                accept(Token.RPAREN);\n            }\n            if (lexer.token() == Token.WITH) {\n                stmt.setWithSelect(this.parseWith());\n            }\n        }\n\n        SQLCommentHint hint = null;\n        if (lexer.token() == Token.HINT) {\n            hint = this.exprParser.parseHint();\n        }\n\n        if (lexer.token() == (Token.SELECT)) {\n            SQLSelect query = new MySqlSelectParser(this.exprParser).select();\n            if (hint != null) {\n                query.setHeadHint(hint);\n            }\n            stmt.setSelect(query);\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.NO)) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"DATA\");\n                    stmt.setWithData(false);\n                } else {\n                    acceptIdentifier(\"DATA\");\n                    stmt.setWithData(true);\n                }\n            }\n        }\n\n        while (lexer.token() == (Token.HINT)) {\n            this.exprParser.parseHints(stmt.getOptionHints());\n        }\n        return stmt;\n    }\n\n    public SQLPartitionBy parseLocalPartitionBy() {\n        lexer.nextToken();\n        accept(Token.PARTITION);\n        accept(Token.BY);\n        acceptIdentifier(\"RANGE\");\n\n        SQLPartitionByRange partitionClause = new SQLPartitionByRange();\n\n        accept(Token.LPAREN);\n        partitionClause.addColumn(this.exprParser.name());\n        accept(Token.RPAREN);\n\n        if (lexer.identifierEquals(FnvHash.Constants.STARTWITH)) {\n            lexer.nextToken();\n            partitionClause.setStartWith(exprParser.expr());\n        }\n\n        partitionClause.setInterval(getExprParser().parseInterval());\n\n        if (lexer.identifierEquals(\"EXPIRE\")) {\n            acceptIdentifier(\"EXPIRE\");\n            acceptIdentifier(\"AFTER\");\n            partitionClause.setExpireAfter((SQLIntegerExpr) exprParser.expr());\n        }\n\n        if (lexer.identifierEquals(\"PRE\")) {\n            acceptIdentifier(\"PRE\");\n            acceptIdentifier(\"ALLOCATE\");\n            partitionClause.setPreAllocate((SQLIntegerExpr) exprParser.expr());\n        }\n\n        if (lexer.identifierEquals(\"PIVOTDATE\")) {\n            acceptIdentifier(\"PIVOTDATE\");\n            partitionClause.setPivotDateExpr(exprParser.expr());\n        }\n\n        if (lexer.token() == Token.DISABLE) {\n            lexer.nextToken();\n            acceptIdentifier(\"SCHEDULE\");\n            partitionClause.setDisableSchedule(true);\n        }\n\n        return partitionClause;\n    }\n\n    protected boolean parseOption(MySqlCreateTableStatement stmt) {\n        if (lexer.token() == Token.IDENTIFIER\n                && supportOptions.contains(lexer.hashLCase())\n        ) {\n            String name = lexer.stringVal();\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n\n            SQLExpr expr = this.exprParser.expr();\n            stmt.addOption(name.toUpperCase(), expr);\n            return true;\n        }\n        return false;\n    }\n\n    protected void parseOptions(MySqlCreateTableStatement stmt) {\n        for (; ; ) {\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                SQLExpr expr = null;\n                if (lexer.token() == Token.MERGE) {\n                    expr = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                } else {\n                    expr = this.exprParser.expr();\n                }\n                stmt.setEngine(expr);\n                continue;\n            }\n\n            if (parseOption(stmt)) {\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.BLOCK_SIZE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                SQLExpr expr = null;\n                if (lexer.token() == Token.MERGE) {\n                    expr = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                } else {\n                    expr = this.exprParser.integerExpr();\n                }\n                stmt.addOption(\"BLOCK_SIZE\", expr);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.PCTFREE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                SQLExpr expr = this.exprParser.integerExpr();\n                stmt.addOption(\"PCTFREE\", expr);\n                continue;\n            }\n\n            if (lexer.token() == Token.DEFAULT) {\n                lexer.nextToken();\n                parseTableOptionCharsetOrCollate(stmt);\n                continue;\n            }\n\n            if (parseTableOptionCharsetOrCollate(stmt)) {\n                continue;\n            }\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                stmt.setComment(this.exprParser.expr());\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DATA)) {\n                lexer.nextToken();\n                acceptIdentifier(\"DIRECTORY\");\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                stmt.addOption(\"DATA DIRECTORY\", this.exprParser.expr());\n                continue;\n            }\n\n            if (lexer.token() == Token.INDEX) {\n                lexer.nextToken();\n                acceptIdentifier(\"DIRECTORY\");\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                stmt.addOption(\"INDEX DIRECTORY\", this.exprParser.expr());\n                continue;\n            }\n\n            if (lexer.token() == Token.UNION) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                accept(Token.LPAREN);\n                SQLListExpr list = new SQLListExpr();\n                this.exprParser.exprList(list.getItems(), list);\n                stmt.addOption(\"UNION\", list);\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.token() == Token.TABLESPACE) {\n                lexer.nextToken();\n\n                TableSpaceOption option = new TableSpaceOption();\n                option.setName(this.exprParser.name());\n\n                if (lexer.identifierEquals(\"STORAGE\")) {\n                    lexer.nextToken();\n                    option.setStorage(this.exprParser.name());\n                }\n\n                stmt.addOption(\"TABLESPACE\", option);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TABLEGROUP)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                SQLName tableGroup = this.exprParser.name();\n                stmt.setTableGroup(tableGroup);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"INDEX_ALL\")) {\n                lexer.nextToken();\n                accept(Token.EQ);\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    if (\"Y\".equalsIgnoreCase(lexer.stringVal())) {\n                        lexer.nextToken();\n                        stmt.addOption(\"INDEX_ALL\", new SQLCharExpr(\"Y\"));\n                    } else if (\"N\".equalsIgnoreCase(lexer.stringVal())) {\n                        lexer.nextToken();\n                        stmt.addOption(\"INDEX_ALL\", new SQLCharExpr(\"N\"));\n                    } else {\n                        throw new ParserException(\"INDEX_ALL accept parameter ['Y' or 'N'] only.\");\n                    }\n                }\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"RT_INDEX_ALL\")) {\n                lexer.nextToken();\n                accept(Token.EQ);\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    if (\"Y\".equalsIgnoreCase(lexer.stringVal())) {\n                        lexer.nextToken();\n                        stmt.addOption(\"RT_INDEX_ALL\", new SQLCharExpr(\"Y\"));\n                    } else if (\"N\".equalsIgnoreCase(lexer.stringVal())) {\n                        lexer.nextToken();\n                        stmt.addOption(\"RT_INDEX_ALL\", new SQLCharExpr(\"N\"));\n                    } else {\n                        throw new ParserException(\"RT_INDEX_ALL accepts parameter ['Y' or 'N'] only.\");\n                    }\n                }\n\n                continue;\n            }\n            if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                acceptIdentifier(\"OSS\");\n                stmt.setArchiveBy(new SQLIdentifierExpr(\"OSS\"));\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"HOT_PARTITION_COUNT\")) {\n                lexer.nextToken();\n                accept(Token.EQ);\n                try {\n                    stmt.addOption(\"HOT_PARTITION_COUNT\", this.exprParser.integerExpr());\n                } catch (Exception e) {\n                    throw new ParserException(\"only integer number is supported for hot_partition_count\");\n                }\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                    stmt.addClusteredByItem(item);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.token() == Token.PARTITION) {\n                SQLPartitionBy partitionClause = parsePartitionBy();\n                stmt.setPartitionBy(partitionClause);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n                SQLPartitionBy localPartitionClause = parseLocalPartitionBy();\n                stmt.setLocalPartitioning(localPartitionClause);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.BROADCAST)) {\n                lexer.nextToken();\n                stmt.setBroadCast(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DISTRIBUTE) || lexer.identifierEquals(FnvHash.Constants.DISTRIBUTED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                if (lexer.identifierEquals(FnvHash.Constants.HASH)) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        SQLName name = this.exprParser.name();\n                        stmt.getDistributeBy().add(name);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    stmt.setDistributeByType(new SQLIdentifierExpr(\"HASH\"));\n                } else if (lexer.identifierEquals(FnvHash.Constants.DUPLICATE)) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        SQLName name = this.exprParser.name();\n                        stmt.getDistributeBy().add(name);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    stmt.setDistributeByType(new SQLIdentifierExpr(\"DUPLICATE\"));\n                } else if (lexer.identifierEquals(FnvHash.Constants.BROADCAST)) {\n                    lexer.nextToken();\n                    stmt.setDistributeByType(new SQLIdentifierExpr(\"BROADCAST\"));\n                }\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DBPARTITION)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                SQLExpr dbPartitoinBy = this.exprParser.primary();\n                stmt.setDbPartitionBy(dbPartitoinBy);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DBPARTITIONS)) {\n                lexer.nextToken();\n                SQLExpr dbPartitions = this.exprParser.primary();\n                stmt.setDbPartitions(dbPartitions);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TBPARTITION)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                SQLExpr expr = this.exprParser.expr();\n                if (lexer.identifierEquals(FnvHash.Constants.STARTWITH)) {\n                    lexer.nextToken();\n                    SQLExpr start = this.exprParser.primary();\n                    acceptIdentifier(\"ENDWITH\");\n                    SQLExpr end = this.exprParser.primary();\n                    expr = new SQLBetweenExpr(expr, start, end);\n                }\n                stmt.setTablePartitionBy(expr);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TBPARTITIONS)) {\n                lexer.nextToken();\n                SQLExpr tbPartitions = this.exprParser.primary();\n                stmt.setTablePartitions(tbPartitions);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.EXTPARTITION)) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                MySqlExtPartition partitionDef = new MySqlExtPartition();\n\n                for (; ; ) {\n                    MySqlExtPartition.Item item = new MySqlExtPartition.Item();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.DBPARTITION)) {\n                        lexer.nextToken();\n                        SQLName name = this.exprParser.name();\n                        item.setDbPartition(name);\n                        accept(Token.BY);\n                        SQLExpr value = this.exprParser.primary();\n                        item.setDbPartitionBy(value);\n                    }\n\n                    if (lexer.identifierEquals(FnvHash.Constants.TBPARTITION)) {\n                        lexer.nextToken();\n                        SQLName name = this.exprParser.name();\n                        item.setTbPartition(name);\n                        accept(Token.BY);\n                        SQLExpr value = this.exprParser.primary();\n                        item.setTbPartitionBy(value);\n                    }\n\n                    item.setParent(partitionDef);\n                    partitionDef.getItems().add(item);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else {\n                        break;\n                    }\n                }\n                accept(Token.RPAREN);\n                stmt.setExPartition(partitionDef);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.OPTIONS)) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                stmt.putAttribute(\"ads.options\", Boolean.TRUE);\n                for (; ; ) {\n                    String name = lexer.stringVal();\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    SQLExpr value = this.exprParser.primary();\n                    stmt.addOption(name, value);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                SQLName name = this.exprParser.name();\n                stmt.setStoredBy(name);\n            }\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                for (; ; ) {\n                    String name = lexer.stringVal();\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    SQLName value = this.exprParser.name();\n                    stmt.getWith().put(name, value);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.token() == (Token.HINT)) {\n                this.exprParser.parseHints(stmt.getOptionHints());\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.SINGLE)) {\n                lexer.nextToken();\n                stmt.setSingle(true);\n                continue;\n            }\n            break;\n        }\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        lexer.nextToken();\n        accept(Token.BY);\n\n        SQLPartitionBy partitionClause;\n\n        boolean linera = false;\n        if (lexer.identifierEquals(FnvHash.Constants.LINEAR)) {\n            lexer.nextToken();\n            linera = true;\n        }\n\n        if (lexer.token() == Token.KEY) {\n            MySqlPartitionByKey clause = new MySqlPartitionByKey();\n            lexer.nextToken();\n\n            if (linera) {\n                clause.setLinear(true);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {\n                lexer.nextToken();\n                accept(Token.EQ);\n                clause.setAlgorithm(lexer.integerValue().shortValue());\n                lexer.nextToken();\n            }\n\n            accept(Token.LPAREN);\n            if (lexer.token() != Token.RPAREN) {\n                for (; ; ) {\n                    clause.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n            }\n            accept(Token.RPAREN);\n\n            partitionClause = clause;\n\n            partitionClauseRest(clause);\n        } else if (lexer.identifierEquals(FnvHash.Constants.HASH) || lexer.identifierEquals(\"UNI_HASH\")) {\n            SQLPartitionByHash clause = new SQLPartitionByHash();\n\n            if (lexer.identifierEquals(\"UNI_HASH\")) {\n                clause.setUnique(true);\n            }\n\n            lexer.nextToken();\n\n            if (linera) {\n                clause.setLinear(true);\n            }\n\n            if (lexer.token() == Token.KEY) {\n                lexer.nextToken();\n                clause.setKey(true);\n            }\n\n            accept(Token.LPAREN);\n            this.exprParser.exprList(clause.getColumns(), clause);\n            accept(Token.RPAREN);\n            partitionClause = clause;\n\n            partitionClauseRest(clause);\n\n        } else if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n            SQLPartitionByRange clause = partitionByRange();\n            partitionClause = clause;\n\n            partitionClauseRest(clause);\n\n        } else if (lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n            SQLPartitionByValue clause = partitionByValue();\n            partitionClause = clause;\n\n            partitionClauseRest(clause);\n\n        } else if (lexer.identifierEquals(FnvHash.Constants.LIST)) {\n            lexer.nextToken();\n            SQLPartitionByList clause = new SQLPartitionByList();\n\n            if (lexer.token() == Token.LPAREN) {\n                clause.setType(SQLPartitionByList.PartitionByListType.LIST_EXPRESSION);\n                lexer.nextToken();\n                clause.addColumn(this.exprParser.expr());\n                accept(Token.RPAREN);\n            } else {\n                acceptIdentifier(FnvHash.Constants.COLUMNS);\n                clause.setType(SQLPartitionByList.PartitionByListType.LIST_COLUMNS);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    clause.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n            partitionClause = clause;\n\n            partitionClauseRest(clause);\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            SQLPartitionByRange clause = partitionByRange();\n            partitionClause = clause;\n\n            partitionClauseRest(clause);\n        } else {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n            lexer.nextToken();\n            partitionClause.setLifeCycle((SQLIntegerExpr) exprParser.expr());\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            for (; ; ) {\n                MysqlPartitionSingle partitionDef = this.getExprParser()\n                        .parsePartition();\n\n                partitionClause.addPartition(partitionDef);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                } else {\n                    break;\n                }\n            }\n            accept(Token.RPAREN);\n        }\n        return partitionClause;\n    }\n\n    protected SQLPartitionByRange partitionByRange1() {\n        acceptIdentifier(\"RANGE\");\n\n        SQLPartitionByRange clause = new SQLPartitionByRange();\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            clause.addColumn(this.exprParser.expr());\n            accept(Token.RPAREN);\n        } else {\n            acceptIdentifier(\"COLUMNS\");\n            accept(Token.LPAREN);\n            for (; ; ) {\n                clause.addColumn(this.exprParser.name());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n        return clause;\n    }\n\n    protected SQLPartitionByValue partitionByValue() {\n        SQLPartitionByValue clause = new SQLPartitionByValue();\n        if (lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                clause.addColumn(this.exprParser.expr());\n                accept(Token.RPAREN);\n            }\n        }\n        return clause;\n    }\n\n    protected SQLPartitionByRange partitionByRange() {\n        SQLPartitionByRange clause = new SQLPartitionByRange();\n        if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                clause.addColumn(this.exprParser.expr());\n                accept(Token.RPAREN);\n            } else {\n                acceptIdentifier(\"COLUMNS\");\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    clause.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n        } else {\n            SQLExpr expr = this.exprParser.expr();\n            if (lexer.identifierEquals(FnvHash.Constants.STARTWITH)) {\n                lexer.nextToken();\n                SQLExpr start = this.exprParser.primary();\n                acceptIdentifier(\"ENDWITH\");\n                SQLExpr end = this.exprParser.primary();\n                expr = new SQLBetweenExpr(expr, start, end);\n            }\n            clause.setInterval(expr);\n        }\n\n        return clause;\n    }\n\n    protected void partitionClauseRest(SQLPartitionBy clause) {\n        if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)\n                || lexer.identifierEquals(FnvHash.Constants.TBPARTITIONS)\n                || lexer.identifierEquals(FnvHash.Constants.DBPARTITIONS)) {\n            lexer.nextToken();\n            SQLIntegerExpr countExpr = this.exprParser.integerExpr();\n            clause.setPartitionsCount(countExpr);\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"NUM\")) {\n                lexer.nextToken();\n            }\n\n            clause.setPartitionsCount(this.exprParser.expr());\n\n            clause.putAttribute(\"ads.partition\", Boolean.TRUE);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n            lexer.nextToken();\n            clause.setLifeCycle((SQLIntegerExpr) exprParser.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            SQLSubPartitionBy subPartitionByClause = null;\n\n            boolean linear = false;\n            if (lexer.identifierEquals(\"LINEAR\")) {\n                lexer.nextToken();\n                linear = true;\n            }\n\n            if (lexer.token() == Token.KEY) {\n                MySqlSubPartitionByKey subPartitionKey = new MySqlSubPartitionByKey();\n                lexer.nextToken();\n\n                if (linear) {\n                    clause.setLinear(true);\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    subPartitionKey.setAlgorithm(lexer.integerValue().shortValue());\n                    lexer.nextToken();\n                }\n\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    subPartitionKey.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n\n                subPartitionByClause = subPartitionKey;\n\n            } else if (lexer.identifierEquals(\"VALUE\")) {\n                MySqlSubPartitionByValue subPartitionByValue = new MySqlSubPartitionByValue();\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    subPartitionByValue.addColumn(this.exprParser.expr());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n\n                subPartitionByClause = subPartitionByValue;\n\n            } else if (lexer.identifierEquals(\"HASH\")) {\n                lexer.nextToken();\n                SQLSubPartitionByHash subPartitionHash = new SQLSubPartitionByHash();\n\n                if (linear) {\n                    clause.setLinear(true);\n                }\n\n                if (lexer.token() == Token.KEY) {\n                    lexer.nextToken();\n                    subPartitionHash.setKey(true);\n                }\n\n                accept(Token.LPAREN);\n                subPartitionHash.setExpr(this.exprParser.expr());\n                accept(Token.RPAREN);\n                subPartitionByClause = subPartitionHash;\n\n            } else if (lexer.identifierEquals(\"LIST\")) {\n                lexer.nextToken();\n                MySqlSubPartitionByList subPartitionList = new MySqlSubPartitionByList();\n\n                //for ads\n                if (lexer.token() == Token.KEY) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n\n                    for (; ; ) {\n                        SQLExpr expr = this.exprParser.expr();\n\n                        if (expr instanceof SQLIdentifierExpr\n                                && (lexer.identifierEquals(\"bigint\") || lexer.identifierEquals(\"long\"))) {\n                            String dataType = lexer.stringVal();\n                            lexer.nextToken();\n\n                            SQLColumnDefinition column = this.exprParser.createColumnDefinition();\n                            column.setName((SQLIdentifierExpr) expr);\n                            column.setDataType(new SQLDataTypeImpl(dataType));\n                            subPartitionList.addColumn(column);\n\n                            subPartitionList.putAttribute(\"ads.subPartitionList\", Boolean.TRUE);\n                        }\n\n                        subPartitionList.addKey(expr);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    subPartitionList.putAttribute(\"ads.subPartitionList\", Boolean.TRUE);\n                    accept(Token.RPAREN);\n                } else if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    SQLExpr expr;\n                    if (lexer.token() == Token.LITERAL_ALIAS) {\n                        expr = new SQLIdentifierExpr(lexer.stringVal());\n                        lexer.nextToken();\n                    } else {\n                        expr = this.exprParser.expr();\n                    }\n\n                    if (expr instanceof SQLIdentifierExpr\n                            && (lexer.identifierEquals(\"bigint\") || lexer.identifierEquals(\"long\"))) {\n                        String dataType = lexer.stringVal();\n                        lexer.nextToken();\n\n                        SQLColumnDefinition column = this.exprParser.createColumnDefinition();\n                        column.setName((SQLIdentifierExpr) expr);\n                        column.setDataType(new SQLDataTypeImpl(dataType));\n                        subPartitionList.addColumn(column);\n\n                        subPartitionList.putAttribute(\"ads.subPartitionList\", Boolean.TRUE);\n                    } else {\n                        subPartitionList.addKey(expr);\n                    }\n                    accept(Token.RPAREN);\n                } else {\n                    acceptIdentifier(\"COLUMNS\");\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        subPartitionList.addColumn(this.exprParser.parseColumn());\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                }\n                subPartitionByClause = subPartitionList;\n            } else if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n                lexer.nextToken();\n                SQLSubPartitionByRange range = new SQLSubPartitionByRange();\n\n                accept(Token.LPAREN);\n                this.exprParser.exprList(range.getColumns(), range);\n                accept(Token.RPAREN);\n                subPartitionByClause = range;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n                lexer.nextToken();\n                acceptIdentifier(\"OPTIONS\");\n                this.exprParser.parseAssignItem(subPartitionByClause.getOptions(), subPartitionByClause);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITIONS)) {\n                lexer.nextToken();\n                Number intValue = lexer.integerValue();\n                SQLNumberExpr numExpr = new SQLNumberExpr(intValue);\n                subPartitionByClause.setSubPartitionsCount(numExpr);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) { // ADB\n                lexer.nextToken();\n                subPartitionByClause.setSubPartitionsCount((SQLIntegerExpr) exprParser.expr());\n                subPartitionByClause.getAttributes().put(\"adb.partitons\", true);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextToken();\n                subPartitionByClause.setLifecycle((SQLIntegerExpr) exprParser.expr());\n            }\n\n            if (subPartitionByClause != null) {\n                subPartitionByClause.setLinear(linear);\n\n                clause.setSubPartitionBy(subPartitionByClause);\n            }\n        }\n    }\n\n    private boolean parseTableOptionCharsetOrCollate(MySqlCreateTableStatement stmt) {\n        if (lexer.identifierEquals(\"CHARACTER\")) {\n            lexer.nextToken();\n            accept(Token.SET);\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr charset;\n            if (lexer.token() == Token.IDENTIFIER) {\n                charset = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                charset = new SQLCharExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else {\n                charset = this.exprParser.primary();\n            }\n            stmt.addOption(\"CHARACTER SET\", charset);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"CHARSET\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr charset;\n            if (lexer.token() == Token.IDENTIFIER) {\n                charset = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                charset = new SQLCharExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else {\n                charset = this.exprParser.primary();\n            }\n            stmt.addOption(\"CHARSET\", charset);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"COLLATE\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            stmt.addOption(\"COLLATE\", this.exprParser.expr());\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"LOCALITY\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            stmt.addOption(\"LOCALITY\", this.exprParser.expr());\n            return true;\n        }\n\n        return false;\n    }\n\n    protected SQLTableConstraint parseConstraint() {\n        SQLName name = null;\n        boolean hasConstaint = false;\n        if (lexer.token() == (Token.CONSTRAINT)) {\n            hasConstaint = true;\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            name = this.exprParser.name();\n        }\n\n        SQLTableConstraint constraint = null;\n\n        if (lexer.token() == (Token.KEY)) {\n            MySqlKey key = new MySqlKey();\n            this.exprParser.parseIndex(key.getIndexDefinition());\n            key.setHasConstraint(hasConstaint);\n\n            if (name != null) {\n                key.setName(name);\n            }\n\n            constraint = key;\n        } else if (lexer.token() == Token.PRIMARY) {\n            MySqlPrimaryKey pk = this.getExprParser().parsePrimaryKey();\n            if (name != null) {\n                pk.setName(name);\n            }\n            pk.setHasConstraint(hasConstaint);\n            constraint = pk;\n        } else if (lexer.token() == Token.UNIQUE) {\n            MySqlUnique uk = this.getExprParser().parseUnique();\n            // should not use CONSTRAINT [symbol] for index name if index_name already specified\n            if (name != null && uk.getName() == null) {\n                uk.setName(name);\n            }\n\n            uk.setHasConstraint(hasConstaint);\n\n            constraint = uk;\n        } else if (lexer.token() == Token.FOREIGN) {\n            MysqlForeignKey fk = this.getExprParser().parseForeignKey();\n            fk.setName(name);\n            fk.setHasConstraint(hasConstaint);\n            constraint = fk;\n        } else if (lexer.token() == Token.CHECK) {\n            lexer.nextToken();\n            SQLCheck check = new SQLCheck();\n            check.setName(name);\n            SQLExpr expr = this.exprParser.primary();\n            check.setExpr(expr);\n            constraint = check;\n\n            boolean enforce = true;\n            if (Token.NOT.equals(lexer.token())) {\n                enforce = false;\n                lexer.nextToken();\n            }\n            if (lexer.stringVal().equalsIgnoreCase(\"ENFORCED\")) {\n                check.setEnforced(enforce);\n                lexer.nextToken();\n            }\n            if (lexer.token() == Token.HINT) {\n                String hintText = lexer.stringVal();\n                if (hintText != null) {\n                    hintText = hintText.trim();\n                }\n\n                if (hintText.startsWith(\"!\")) {\n                    if (hintText.endsWith(\"NOT ENFORCED\")) {\n                        check.setEnforced(false);\n                    } else if (hintText.endsWith(\" ENFORCED\")) {\n                        check.setEnforced(true);\n                    }\n                    lexer.nextToken();\n                }\n            }\n        }\n\n        if (constraint != null) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                SQLExpr comment = this.exprParser.primary();\n                constraint.setComment(comment);\n            }\n\n            return constraint;\n        }\n\n        throw new ParserException(\"TODO. \" + lexer.info());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl.Match;\nimport com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl.Option;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MysqlPartitionSingle;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.HexBin;\nimport com.alibaba.druid.util.MySqlUtils;\nimport com.alibaba.druid.util.StringUtils;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport java.sql.Types;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class MySqlExprParser extends SQLExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    public static final String[] SINGLE_WORD_TABLE_OPTIONS;\n\n    public static final long[] SINGLE_WORD_TABLE_OPTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"AVG\",\n                \"ANY_VALUE\",\n                \"BIT_AND\",\n                \"BIT_OR\",\n                \"BIT_XOR\",\n                \"COUNT\",\n                \"GROUP_CONCAT\",\n                \"LISTAGG\",\n                \"JSON_ARRAYAGG\",\n                \"JSON_OBJECTAGG\",\n                \"MAX\",\n                \"MIN\",\n                \"STD\",\n                \"STDDEV\",\n                \"STDDEV_POP\",\n                \"STDDEV_SAMP\",\n                \"SUM\",\n                \"VAR_POP\",\n                \"VAR_SAMP\",\n                \"VARIANCE\",\n        };\n\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n\n        // https://dev.mysql.com/doc/refman/5.7/en/create-table.html\n        String[] options = {\"AUTO_INCREMENT\", \"AVG_ROW_LENGTH\", /*\"CHARACTER SET\",*/ \"CHECKSUM\", \"COLLATE\", \"COMMENT\",\n                \"COMPRESSION\", \"CONNECTION\", /*\"{DATA|INDEX} DIRECTORY\",*/ \"DELAY_KEY_WRITE\", \"ENCRYPTION\", \"ENGINE\",\n                \"INSERT_METHOD\", \"KEY_BLOCK_SIZE\", \"MAX_ROWS\", \"MIN_ROWS\", \"PACK_KEYS\", \"PASSWORD\", \"ROW_FORMAT\",\n                \"STATS_AUTO_RECALC\", \"STATS_PERSISTENT\", \"STATS_SAMPLE_PAGES\", \"TABLESPACE\", \"UNION\",\n                \"STORAGE_TYPE\", \"STORAGE_POLICY\"};\n        SINGLE_WORD_TABLE_OPTIONS_CODES = FnvHash.fnv1a_64_lower(options, true);\n        SINGLE_WORD_TABLE_OPTIONS = new String[SINGLE_WORD_TABLE_OPTIONS_CODES.length];\n        for (String str : options) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(SINGLE_WORD_TABLE_OPTIONS_CODES, hash);\n            SINGLE_WORD_TABLE_OPTIONS[index] = str;\n        }\n    }\n\n    public MySqlExprParser(Lexer lexer) {\n        super(lexer, DbType.mysql);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public MySqlExprParser(String sql) {\n        this(new MySqlLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public MySqlExprParser(String sql, SQLParserFeature... features) {\n        super(new MySqlLexer(sql, features), DbType.mysql);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n        if (sql.length() > 6) {\n            char c0 = sql.charAt(0);\n            char c1 = sql.charAt(1);\n            char c2 = sql.charAt(2);\n            char c3 = sql.charAt(3);\n            char c4 = sql.charAt(4);\n            char c5 = sql.charAt(5);\n            char c6 = sql.charAt(6);\n\n            if (c0 == 'S' && c1 == 'E' && c2 == 'L' && c3 == 'E' && c4 == 'C' && c5 == 'T' && c6 == ' ') {\n                lexer.reset(6, ' ', Token.SELECT);\n                return;\n            }\n\n            if (c0 == 's' && c1 == 'e' && c2 == 'l' && c3 == 'e' && c4 == 'c' && c5 == 't' && c6 == ' ') {\n                lexer.reset(6, ' ', Token.SELECT);\n                return;\n            }\n\n            if (c0 == 'I' && c1 == 'N' && c2 == 'S' && c3 == 'E' && c4 == 'R' && c5 == 'T' && c6 == ' ') {\n                lexer.reset(6, ' ', Token.INSERT);\n                return;\n            }\n\n            if (c0 == 'i' && c1 == 'n' && c2 == 's' && c3 == 'e' && c4 == 'r' && c5 == 't' && c6 == ' ') {\n                lexer.reset(6, ' ', Token.INSERT);\n                return;\n            }\n\n            if (c0 == 'U' && c1 == 'P' && c2 == 'D' && c3 == 'A' && c4 == 'T' && c5 == 'E' && c6 == ' ') {\n                lexer.reset(6, ' ', Token.UPDATE);\n                return;\n            }\n\n            if (c0 == 'u' && c1 == 'p' && c2 == 'd' && c3 == 'a' && c4 == 't' && c5 == 'e' && c6 == ' ') {\n                lexer.reset(6, ' ', Token.UPDATE);\n                return;\n            }\n\n            if (c0 == '/' && c1 == '*' && (isEnabled(SQLParserFeature.OptimizedForParameterized) && !isEnabled(SQLParserFeature.TDDLHint))) {\n                MySqlLexer mySqlLexer = (MySqlLexer) lexer;\n                mySqlLexer.skipFirstHintsOrMultiCommentAndNextToken();\n                return;\n            }\n        }\n        this.lexer.nextToken();\n\n    }\n\n    public MySqlExprParser(String sql, boolean keepComments) {\n        this(new MySqlLexer(sql, true, keepComments));\n        this.lexer.nextToken();\n    }\n\n    public MySqlExprParser(String sql, boolean skipComment, boolean keepComments) {\n        this(new MySqlLexer(sql, skipComment, keepComments));\n        this.lexer.nextToken();\n    }\n\n    @Override\n    protected SQLExpr primaryIdentifierRest(long hash_lower, String ident) {\n        SQLExpr sqlExpr = null;\n        if (hash_lower == FnvHash.Constants.VARCHAR && lexer.token() == Token.LITERAL_CHARS) {\n            MySqlCharExpr mysqlChar = new MySqlCharExpr(lexer.stringVal());\n            mysqlChar.setType(\"VARCHAR\");\n            sqlExpr = mysqlChar;\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.CHAR && lexer.token() == Token.LITERAL_CHARS) {\n            MySqlCharExpr mysqlChar = new MySqlCharExpr(lexer.stringVal());\n            mysqlChar.setType(\"CHAR\");\n            sqlExpr = mysqlChar;\n            lexer.nextToken();\n        } else if (ident.startsWith(\"0x\") && (ident.length() % 2) == 0) {\n            sqlExpr = new SQLHexExpr(ident.substring(2));\n        } else if (hash_lower == FnvHash.Constants.JSON\n                && lexer.token() == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLJSONExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.DECIMAL\n                && lexer.token() == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLDecimalExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.DOUBLE\n                && lexer.token() == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLDoubleExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.FLOAT\n                && lexer.token() == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLFloatExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.SMALLINT\n                && lexer.token() == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLSmallIntExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.TINYINT && lexer.token() == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLTinyIntExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.BIGINT && lexer.token() == Token.LITERAL_CHARS) {\n            String strVal = lexer.stringVal();\n            if (strVal.startsWith(\"--\")) {\n                strVal = strVal.substring(2);\n            }\n            sqlExpr = new SQLBigIntExpr(strVal);\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.INTEGER && lexer.token() == Token.LITERAL_CHARS) {\n            String strVal = lexer.stringVal();\n            if (strVal.startsWith(\"--\")) {\n                strVal = strVal.substring(2);\n            }\n            SQLIntegerExpr integerExpr = SQLIntegerExpr.ofIntOrLong(Long.parseLong(strVal));\n            integerExpr.setType(\"INTEGER\");\n            sqlExpr = integerExpr;\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.REAL && lexer.token() == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLRealExpr(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr primaryLiteralCharsRest(SQLExpr sqlExpr) {\n        lexer.nextTokenValue();\n\n        for (; ; ) {\n            if (lexer.token() == Token.LITERAL_ALIAS) {\n                String concat = ((SQLCharExpr) sqlExpr).getText();\n                concat += lexer.stringVal();\n                lexer.nextTokenValue();\n                sqlExpr = new SQLCharExpr(concat);\n            } else if (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_NCHARS) {\n                String concat = ((SQLCharExpr) sqlExpr).getText();\n                concat += lexer.stringVal();\n                lexer.nextTokenValue();\n                sqlExpr = new SQLCharExpr(concat);\n            } else {\n                break;\n            }\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr primaryLiteralNCharsRest(SQLExpr sqlExpr) {\n        SQLMethodInvokeExpr concat = null;\n        for (; ; ) {\n            if (lexer.token() == Token.LITERAL_ALIAS) {\n                if (concat == null) {\n                    concat = new SQLMethodInvokeExpr(\"CONCAT\");\n                    concat.addArgument(sqlExpr);\n                    sqlExpr = concat;\n                }\n                String alias = lexer.stringVal();\n                lexer.nextToken();\n                SQLCharExpr concat_right = new SQLCharExpr(alias.substring(1, alias.length() - 1));\n                concat.addArgument(concat_right);\n            } else if (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_NCHARS) {\n                if (concat == null) {\n                    concat = new SQLMethodInvokeExpr(\"CONCAT\");\n                    concat.addArgument(sqlExpr);\n                    sqlExpr = concat;\n                }\n\n                String chars = lexer.stringVal();\n                lexer.nextToken();\n                SQLCharExpr concat_right = new SQLCharExpr(chars);\n                concat.addArgument(concat_right);\n            } else {\n                break;\n            }\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr bitXorRestSUBGT() {\n        if (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS) {\n            return primary();\n        } else {\n            return expr();\n        }\n    }\n\n    @Override\n    protected SQLExpr primarySubLiteralAliasRest() {\n        return new SQLCharExpr(lexer.stringVal());\n    }\n\n    @Override\n    protected void primaryQues() {\n        lexer.nextTokenValue();\n    }\n\n    @Override\n    protected SQLExpr primaryDistinct(SQLExpr sqlExpr) {\n        Lexer.SavePoint mark = lexer.mark();\n        sqlExpr = new SQLIdentifierExpr(lexer.stringVal());\n        lexer.nextToken();\n        if (lexer.token() != Token.LPAREN) {\n            lexer.reset(mark);\n            throw new ParserException(\"ERROR. \" + lexer.info());\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr methodRestAllowIdentifierMethodSpecific(String methodName, long hash_lower, SQLMethodInvokeExpr methodInvokeExpr) {\n        if (hash_lower == FnvHash.Constants.MATCH) {\n            return parseMatch();\n        } else if (hash_lower == FnvHash.Constants.EXTRACT) {\n            return parseExtract();\n        } else if (hash_lower == FnvHash.Constants.POSITION) {\n            return parsePosition();\n        } else if (hash_lower == FnvHash.Constants.CONVERT) {\n            methodInvokeExpr = new SQLMethodInvokeExpr(methodName, hash_lower);\n            SQLExpr arg0 = this.expr();\n            // Fix for using.\n            Object exprUsing = arg0.getAttributes().get(\"USING\");\n            if (exprUsing instanceof String) {\n                String charset = (String) exprUsing;\n                methodInvokeExpr.setUsing(new SQLIdentifierExpr(charset));\n                arg0.getAttributes().remove(\"USING\");\n            }\n            methodInvokeExpr.addArgument(arg0);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                SQLDataType dataType = this.parseDataType();\n                SQLDataTypeRefExpr dataTypeRefExpr = new SQLDataTypeRefExpr(dataType);\n                methodInvokeExpr.addArgument(dataTypeRefExpr);\n            }\n\n            if (lexer.token() == Token.USING || lexer.identifierEquals(FnvHash.Constants.USING)) {\n                lexer.nextToken();\n                SQLExpr using;\n                if (lexer.token() == Token.STAR) {\n                    lexer.nextToken();\n                    using = new SQLAllColumnExpr();\n                } else if (lexer.token() == Token.BINARY) {\n                    using = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                } else {\n                    using = this.primary();\n                }\n                methodInvokeExpr.setUsing(using);\n            }\n\n            accept(Token.RPAREN);\n\n            return primaryRest(methodInvokeExpr);\n        }\n        return null;\n    }\n\n    @Override\n    protected void exprListComma() {\n        lexer.nextTokenValue();\n    }\n\n    @Override\n    protected SQLBinaryOperator orRestGetOrOperator() {\n        return !isEnabled(SQLParserFeature.PipesAsConcat) ? SQLBinaryOperator.BooleanOr : SQLBinaryOperator.Concat;\n    }\n    protected void parseDataTypeByte(StringBuilder typeName) {\n        typeName.append(' ').append(lexer.stringVal());\n        lexer.nextToken();\n    }\n\n    @Override\n    protected void parseDataTypePrecision(StringBuilder typeName) {\n        if (lexer.identifierEquals(FnvHash.Constants.PRECISION)) {\n            typeName.append(' ').append(lexer.stringVal());\n            lexer.nextToken();\n        }\n    }\n\n    @Override\n    protected SQLExpr parseColumnRestDefault() {\n        SQLExpr defaultExpr;\n        if (lexer.token() == Token.LITERAL_CHARS) {\n            defaultExpr = new SQLCharExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else {\n            defaultExpr = bitOr();\n        }\n        return defaultExpr;\n    }\n\n    @Override\n    protected void parseIndexSpecific(SQLIndexDefinition indexDefinition) {\n        if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n            lexer.nextToken();\n            indexDefinition.getOptions().setIndexType(lexer.stringVal());\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"HASHMAP\")) {\n            lexer.nextToken();\n            indexDefinition.setHashMapType(true);\n            indexDefinition.getParent().putAttribute(\"ads.index\", Boolean.TRUE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.HASH)) {\n            lexer.nextToken();\n            indexDefinition.setHashType(true);\n            indexDefinition.getParent().putAttribute(\"ads.index\", Boolean.TRUE);\n        } else {\n            indexDefinition.setName(name());\n        }\n    }\n\n    @Override\n    protected void parseIndexOptions(SQLIndexDefinition indexDefinition) {\n        _opts:\n        while (true) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                indexDefinition.getOptions().setComment(primary());\n            } else if (lexer.identifierEquals(\"INVISIBLE\")) {\n                lexer.nextToken();\n                indexDefinition.getOptions().setInvisible(true);\n            } else if (lexer.identifierEquals(\"VISIBLE\")) {\n                lexer.nextToken();\n                indexDefinition.getOptions().setVisible(true);\n            } else if (lexer.identifierEquals(\"GLOBAL\")) {\n                lexer.nextToken();\n                indexDefinition.getOptions().setGlobal(true);\n            } else if (lexer.identifierEquals(\"LOCAL\")) {\n                lexer.nextToken();\n                indexDefinition.getOptions().setLocal(true);\n            } else if (lexer.token() == Token.HINT && lexer.stringVal().trim().equals(\"!80000 INVISIBLE\")) {\n                lexer.nextToken();\n                indexDefinition.getOptions().setInvisible(true);\n            } else {\n                switch (lexer.token()) {\n                    case WITH:\n                        Lexer.SavePoint mark = lexer.mark();\n                        lexer.nextToken();\n                        if (lexer.identifierEquals(\"PARSER\")) {\n                            lexer.nextToken();\n                            indexDefinition.getOptions().setParserName(lexer.stringVal());\n                            lexer.nextToken();\n                            break;\n                        }\n                        lexer.reset(mark);\n                        for (; ; ) {\n                            if (lexer.token() == Token.WITH) {\n                                lexer.nextToken();\n                                // Part from original MySqlCreateTableParser.\n                                if (lexer.token() == Token.INDEX) {\n                                    lexer.nextToken();\n                                    acceptIdentifier(\"ANALYZER\");\n                                    indexDefinition.setIndexAnalyzerName(name());\n                                    continue;\n                                } else if (lexer.identifierEquals(FnvHash.Constants.QUERY)) {\n                                    lexer.nextToken();\n                                    acceptIdentifier(\"ANALYZER\");\n                                    indexDefinition.setQueryAnalyzerName(name());\n                                    continue;\n                                } else if (lexer.identifierEquals(FnvHash.Constants.ANALYZER)) {\n                                    lexer.nextToken();\n                                    SQLName name = name();\n                                    indexDefinition.setAnalyzerName(name);\n                                    break;\n                                } else if (lexer.identifierEquals(\"DICT\")) {\n                                    lexer.nextToken();\n                                    indexDefinition.setWithDicName(name());\n                                    continue;\n                                }\n                            }\n                            break;\n                        }\n                        break;\n                    case LOCK:\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        indexDefinition.getOptions().setLock(lexer.stringVal());\n                        lexer.nextToken();\n                        break;\n\n                    case IDENTIFIER:\n                        if (lexer.identifierEquals(FnvHash.Constants.KEY_BLOCK_SIZE)\n                                || lexer.identifierEquals(FnvHash.Constants.BLOCK_SIZE)) {\n                            lexer.nextToken();\n                            if (lexer.token() == Token.EQ) {\n                                lexer.nextToken();\n                            }\n                            indexDefinition.getOptions().setKeyBlockSize(expr());\n                        } else if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n                            lexer.nextToken();\n                            indexDefinition.getOptions().setIndexType(lexer.stringVal());\n                            lexer.nextToken();\n                        } else if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {\n                            lexer.nextToken();\n                            if (lexer.token() == Token.EQ) {\n                                lexer.nextToken();\n                            }\n                            indexDefinition.getOptions().setAlgorithm(lexer.stringVal());\n                            lexer.nextToken();\n                        } else if (lexer.identifierEquals(FnvHash.Constants.DISTANCEMEASURE)) {\n                            // Caution: Not in MySql documents.\n                            SQLExpr key = new SQLIdentifierExpr(lexer.stringVal());\n                            lexer.nextToken();\n                            if (lexer.token() == Token.EQ) {\n                                lexer.nextToken();\n                            }\n                            SQLAssignItem item = new SQLAssignItem(key, primary());\n                            if (indexDefinition.getParent() != null) {\n                                item.setParent(indexDefinition.getParent());\n                            } else {\n                                item.setParent(indexDefinition);\n                            }\n                            // Add both with same object.\n                            indexDefinition.getOptions().getOtherOptions().add(item);\n                            indexDefinition.getCompatibleOptions().add(item);\n                        } else if (lexer.identifierEquals(FnvHash.Constants.DBPARTITION)) {\n                            lexer.nextToken();\n                            accept(Token.BY);\n                            indexDefinition.setDbPartitionBy(primary());\n                        } else if (lexer.identifierEquals(FnvHash.Constants.TBPARTITION)) {\n                            lexer.nextToken();\n                            accept(Token.BY);\n                            SQLExpr expr = expr();\n                            if (lexer.identifierEquals(FnvHash.Constants.STARTWITH)) {\n                                lexer.nextToken();\n                                SQLExpr start = primary();\n                                acceptIdentifier(\"ENDWITH\");\n                                SQLExpr end = primary();\n                                expr = new SQLBetweenExpr(expr, start, end);\n                            }\n                            indexDefinition.setTbPartitionBy(expr);\n                        } else if (lexer.identifierEquals(FnvHash.Constants.TBPARTITIONS)) {\n                            lexer.nextToken();\n                            indexDefinition.setTbPartitions(primary());\n                            //} else if (lexer.identifierEquals(FnvHash.Constants.GLOBAL)) {\n                            //    lexer.nextToken();\n                            //    indexDefinition.setGlobal(true);\n                        } else {\n                            break _opts;\n                        }\n                        break;\n                    case PARTITION:\n                        SQLPartitionBy partitionBy = new MySqlCreateTableParser(this).parsePartitionBy();\n                        indexDefinition.setPartitioning(partitionBy);\n                        break;\n                    default:\n                        break _opts;\n                }\n            }\n        }\n    }\n\n    @Override\n    protected SQLExpr parseSelectItemRest(String ident, long hash_lower) {\n        SQLExpr expr = null;\n        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)\n                && lexer.stringVal().charAt(0) != '`'\n        ) {\n            lexer.nextToken();\n            String collate = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLBinaryOpExpr binaryExpr = new SQLBinaryOpExpr(\n                    new SQLIdentifierExpr(ident),\n                    SQLBinaryOperator.COLLATE,\n                    new SQLIdentifierExpr(collate), dbType\n            );\n\n            expr = binaryExpr;\n        } else if (lexer.identifierEquals(FnvHash.Constants.REGEXP)\n                && lexer.stringVal().charAt(0) != '`') {\n            lexer.nextToken();\n            SQLExpr rightExp = bitOr();\n\n            SQLBinaryOpExpr binaryExpr = new SQLBinaryOpExpr(\n                    new SQLIdentifierExpr(ident),\n                    SQLBinaryOperator.RegExp,\n                    rightExp, dbType\n            );\n\n            expr = binaryExpr;\n            expr = relationalRest(expr);\n        } else if (FnvHash.Constants.TIMESTAMP == hash_lower\n                && lexer.stringVal().charAt(0) != '`'\n                && lexer.token() == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLTimestampExpr ts = new SQLTimestampExpr(literal);\n            expr = ts;\n\n            if (lexer.identifierEquals(FnvHash.Constants.AT)) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n\n                String timeZone = null;\n                if (lexer.identifierEquals(FnvHash.Constants.TIME)) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.ZONE)) {\n                        lexer.nextToken();\n                        timeZone = lexer.stringVal();\n                        lexer.nextToken();\n                    }\n                }\n                if (timeZone == null) {\n                    lexer.reset(mark);\n                } else {\n                    ts.setTimeZone(timeZone);\n                }\n            }\n        } else if (FnvHash.Constants.DATETIME == hash_lower\n                && lexer.stringVal().charAt(0) != '`'\n                && lexer.token() == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLDateTimeExpr ts = new SQLDateTimeExpr(literal);\n            expr = ts;\n        } else if (FnvHash.Constants.BOOLEAN == hash_lower\n                && lexer.stringVal().charAt(0) != '`'\n                && lexer.token() == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLBooleanExpr ts = new SQLBooleanExpr(Boolean.valueOf(literal));\n            expr = ts;\n        } else if ((FnvHash.Constants.CHAR == hash_lower || FnvHash.Constants.VARCHAR == hash_lower)\n                && lexer.token() == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLCharExpr charExpr = new SQLCharExpr(literal);\n            expr = charExpr;\n        } else if (FnvHash.Constants.CURRENT_DATE == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_DATE);\n\n        } else if (FnvHash.Constants.CURRENT_TIMESTAMP == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIMESTAMP);\n\n        } else if (FnvHash.Constants.CURRENT_TIME == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIME);\n\n        } else if (FnvHash.Constants.CURDATE == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURDATE);\n\n        } else if (FnvHash.Constants.LOCALTIME == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.LOCALTIME);\n\n        } else if (FnvHash.Constants.LOCALTIMESTAMP == hash_lower\n                && ident.charAt(0) != '`'\n                && lexer.token() != Token.LPAREN) {\n            expr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.LOCALTIMESTAMP);\n\n        } else if ((FnvHash.Constants._LATIN1 == hash_lower)\n                && ident.charAt(0) != '`'\n        ) {\n            String hexString;\n            if (lexer.token() == Token.LITERAL_HEX) {\n                hexString = lexer.hexString();\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                hexString = null;\n            } else {\n                acceptIdentifier(\"X\");\n                hexString = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n            }\n\n            if (hexString == null) {\n                String str = lexer.stringVal();\n                lexer.nextToken();\n\n                String collate = null;\n                if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                    lexer.nextToken();\n                    collate = lexer.stringVal();\n                    if (lexer.token() == Token.LITERAL_CHARS) {\n                        lexer.nextToken();\n                    } else {\n                        accept(Token.IDENTIFIER);\n                    }\n                }\n\n                expr = new MySqlCharExpr(str, \"_latin1\", collate);\n            } else {\n                expr = new MySqlCharExpr(hexString, \"_latin1\");\n            }\n        } else if ((FnvHash.Constants._UTF8 == hash_lower || FnvHash.Constants._UTF8MB4 == hash_lower)\n                && ident.charAt(0) != '`'\n        ) {\n            String hexString;\n            if (lexer.token() == Token.LITERAL_HEX) {\n                hexString = lexer.hexString();\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                hexString = null;\n            } else {\n                acceptIdentifier(\"X\");\n                hexString = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n            }\n\n            if (hexString == null) {\n                String str = lexer.stringVal();\n                lexer.nextToken();\n\n                String collate = null;\n                if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                    lexer.nextToken();\n                    collate = lexer.stringVal();\n                    if (lexer.token() == Token.LITERAL_CHARS) {\n                        lexer.nextToken();\n                    } else {\n                        accept(Token.IDENTIFIER);\n                    }\n                }\n\n                expr = new MySqlCharExpr(str, \"_utf8\", collate);\n            } else {\n                expr = new SQLCharExpr(\n                        MySqlUtils.utf8(hexString)\n                );\n            }\n        } else if ((FnvHash.Constants._UTF16 == hash_lower || FnvHash.Constants._UCS2 == hash_lower)\n                && ident.charAt(0) != '`'\n        ) {\n            String hexString;\n            if (lexer.token() == Token.LITERAL_HEX) {\n                hexString = lexer.hexString();\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                hexString = null;\n            } else {\n                acceptIdentifier(\"X\");\n                hexString = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n            }\n\n            if (hexString == null) {\n                String str = lexer.stringVal();\n                hexString = HexBin.encode(str.getBytes(MySqlUtils.ASCII));\n                lexer.nextToken();\n            }\n\n            expr = new MySqlCharExpr(hexString, \"_utf16\");\n        } else if (FnvHash.Constants._UTF32 == hash_lower\n                && ident.charAt(0) != '`'\n        ) {\n            String hexString;\n            if (lexer.token() == Token.LITERAL_HEX) {\n                hexString = lexer.hexString();\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                hexString = null;\n            } else {\n                acceptIdentifier(\"X\");\n                hexString = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n            }\n\n            if (hexString == null) {\n                String str = lexer.stringVal();\n                lexer.nextToken();\n                expr = new MySqlCharExpr(str, \"_utf32\");\n            } else {\n                expr = new SQLCharExpr(\n                        MySqlUtils.utf32(hexString)\n                );\n            }\n        } else if (FnvHash.Constants._GBK == hash_lower\n                && ident.charAt(0) != '`'\n        ) {\n            String hexString;\n            if (lexer.token() == Token.LITERAL_HEX) {\n                hexString = lexer.hexString();\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                hexString = null;\n            } else {\n                acceptIdentifier(\"X\");\n                hexString = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n            }\n\n            if (hexString == null) {\n                String str = lexer.stringVal();\n                lexer.nextToken();\n                expr = new MySqlCharExpr(str, \"_gbk\");\n            } else {\n                expr = new SQLCharExpr(\n                        MySqlUtils.gbk(hexString)\n                );\n            }\n        } else if (FnvHash.Constants._BIG5 == hash_lower\n                && ident.charAt(0) != '`'\n        ) {\n            String hexString;\n            if (lexer.token() == Token.LITERAL_HEX) {\n                hexString = lexer.hexString();\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                hexString = null;\n            } else {\n                acceptIdentifier(\"X\");\n                hexString = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n            }\n\n            if (hexString == null) {\n                String str = lexer.stringVal();\n                lexer.nextToken();\n                expr = new MySqlCharExpr(str, \"_big5\");\n            } else {\n                expr = new SQLCharExpr(\n                        MySqlUtils.big5(hexString)\n                );\n            }\n        }\n        return expr;\n    }\n\n    protected SQLExpr parseSelectItemMethod(SQLExpr expr) {\n        lexer.nextTokenValue();\n        return this.methodRest(expr, false);\n    }\n    protected Pair<String, SQLExpr> parseSelectItemIdentifier(SQLExpr expr) {\n        String as = null;\n        if (lexer.hashLCase() == FnvHash.Constants.FORCE) {\n            String force = lexer.stringVal();\n\n            Lexer.SavePoint savePoint = lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.reset(savePoint);\n                as = null;\n            } else {\n                as = force;\n                if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && as.length() > 1) {\n                    as = StringUtils.removeNameQuotes(as);\n                }\n                lexer.nextTokenComma();\n            }\n        } else if (lexer.hashLCase() == FnvHash.Constants.SOUNDS) {\n            String sounds = lexer.stringVal();\n\n            Lexer.SavePoint savePoint = lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.reset(savePoint);\n                expr = exprRest(expr);\n                as = as();\n            } else {\n                as = sounds;\n                if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && as.length() > 1) {\n                    as = StringUtils.removeNameQuotes(as);\n                }\n                lexer.nextTokenComma();\n            }\n        } else if (lexer.hashLCase() == FnvHash.Constants.COLLATE\n                && lexer.stringVal().charAt(0) != '`') {\n            expr = primaryRest(expr);\n            as = as();\n        } else if (lexer.hashLCase() == FnvHash.Constants.REGEXP\n                && lexer.stringVal().charAt(0) != '`') {\n            expr = exprRest(expr);\n            as = as();\n        } else {\n            as = lexer.stringVal();\n            if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && as.length() > 1) {\n                as = StringUtils.removeNameQuotes(as);\n            }\n            lexer.nextTokenComma();\n        }\n        return Pair.of(as, expr);\n    }\n\n    @Override\n    protected String parseSelectItemAlias(String alias) {\n        boolean specialChar = false;\n        for (int i = 0; i < alias.length(); ++i) {\n            char ch = alias.charAt(i);\n            if (ch == '`') {\n                specialChar = true;\n                break;\n            }\n        }\n        if (specialChar) {\n            alias = alias.replaceAll(\"`\", \"``\");\n            alias = '`' + alias + '`';\n        }\n        return alias;\n    }\n    public SQLExpr primary() {\n        final Token tok = lexer.token();\n        switch (tok) {\n            case IDENTIFIER:\n                final long hash_lower = lexer.hashLCase();\n                Lexer.SavePoint savePoint = lexer.mark();\n\n                if (hash_lower == FnvHash.Constants.OUTLINE) {\n                    lexer.nextToken();\n                    try {\n                        SQLExpr file = primary();\n                        SQLExpr expr = new MySqlOutFileExpr(file);\n\n                        return primaryRest(expr);\n                    } catch (ParserException e) {\n                        lexer.reset(savePoint);\n                    }\n                }\n\n                String strVal = lexer.stringVal();\n\n                boolean quoteStart = strVal.length() > 0 && (strVal.charAt(0) == '`' || strVal.charAt(0) == '\"');\n\n                if (!quoteStart) {\n                    // Allow function in order by when not start with '`'.\n                    setAllowIdentifierMethod(true);\n                }\n\n                SQLCurrentTimeExpr currentTimeExpr = null;\n                if (hash_lower == FnvHash.Constants.CURRENT_TIME && !quoteStart) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIME);\n                } else if (hash_lower == FnvHash.Constants.CURRENT_TIMESTAMP && !quoteStart) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIMESTAMP);\n                } else if (hash_lower == FnvHash.Constants.CURRENT_DATE && !quoteStart) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_DATE);\n                } else if (hash_lower == FnvHash.Constants.CURDATE && !quoteStart) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURDATE);\n                } else if (hash_lower == FnvHash.Constants.LOCALTIME && !quoteStart) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.LOCALTIME);\n                } else if (hash_lower == FnvHash.Constants.LOCALTIMESTAMP && !quoteStart) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.LOCALTIMESTAMP);\n                } else if (hash_lower == FnvHash.Constants.JSON_TABLE) {\n                    if (lexer.identifierEquals(\"JSON_TABLE\")) {\n                        lexer.nextToken();\n                        accept(Token.LPAREN);\n\n                        MySqlJSONTableExpr jsonTable = new MySqlJSONTableExpr();\n                        jsonTable.setExpr(\n                                this.expr());\n                        accept(Token.COMMA);\n                        jsonTable.setPath(\n                                this.expr());\n                        acceptIdentifier(\"COLUMNS\");\n                        accept(Token.LPAREN);\n                        for (; lexer.token() != Token.RPAREN; ) {\n                            jsonTable.addColumn(\n                                    parseJsonTableColumn());\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                            break;\n                        }\n                        accept(Token.RPAREN);\n\n                        accept(Token.RPAREN);\n                        return jsonTable;\n                    }\n                } else if ((hash_lower == FnvHash.Constants._LATIN1) && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n\n                        String collate = null;\n                        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                            lexer.nextToken();\n                            collate = lexer.stringVal();\n                            if (lexer.token() == Token.LITERAL_CHARS) {\n                                lexer.nextToken();\n                            } else {\n                                accept(Token.IDENTIFIER);\n                            }\n                        }\n\n                        charExpr = new MySqlCharExpr(str, \"_latin1\", collate);\n                    } else {\n                        charExpr = new MySqlCharExpr(hexString, \"_latin1\");\n                    }\n\n                    return primaryRest(charExpr);\n                } else if ((hash_lower == FnvHash.Constants._UTF8 || hash_lower == FnvHash.Constants._UTF8MB4)\n                        && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n\n                        String collate = null;\n                        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                            lexer.nextToken();\n                            collate = lexer.stringVal();\n                            if (lexer.token() == Token.LITERAL_CHARS) {\n                                lexer.nextToken();\n                            } else {\n                                accept(Token.IDENTIFIER);\n                            }\n                        }\n                        String charset = hash_lower == FnvHash.Constants._UTF8 ? \"_utf8\" : \"_utf8mb4\";\n                        charExpr = new MySqlCharExpr(str, charset, collate);\n                    } else {\n                        String str = MySqlUtils.utf8(hexString);\n                        charExpr = new SQLCharExpr(str);\n                    }\n\n                    return primaryRest(charExpr);\n                } else if ((hash_lower == FnvHash.Constants._UTF16 || hash_lower == FnvHash.Constants._UCS2)\n                        && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLCharExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n                        charExpr = new MySqlCharExpr(str, \"_utf16\");\n                    } else {\n                        charExpr = new SQLCharExpr(MySqlUtils.utf16(hexString));\n                    }\n\n                    return primaryRest(charExpr);\n                } else if ((hash_lower == FnvHash.Constants._UTF16LE)\n                        && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLCharExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n                        charExpr = new MySqlCharExpr(str, \"_utf16le\");\n                    } else {\n                        charExpr = new MySqlCharExpr(hexString, \"_utf16le\");\n                    }\n\n                    return primaryRest(charExpr);\n                } else if (hash_lower == FnvHash.Constants._UTF32 && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLCharExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n                        charExpr = new MySqlCharExpr(str, \"_utf32\");\n                    } else {\n                        charExpr = new SQLCharExpr(MySqlUtils.utf32(hexString));\n                    }\n\n                    return primaryRest(charExpr);\n                } else if (hash_lower == FnvHash.Constants._GBK && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLCharExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n                        charExpr = new MySqlCharExpr(str, \"_gbk\");\n                    } else {\n                        charExpr = new SQLCharExpr(MySqlUtils.gbk(hexString));\n                    }\n\n                    return primaryRest(charExpr);\n                } else if (hash_lower == FnvHash.Constants._UJIS && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLCharExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n                        charExpr = new MySqlCharExpr(str, \"_ujis\");\n                    } else {\n                        charExpr = new MySqlCharExpr(hexString, \"_ujis\");\n                    }\n\n                    return primaryRest(charExpr);\n                } else if (hash_lower == FnvHash.Constants._BIG5 && !quoteStart) {\n                    lexer.nextToken();\n\n                    String hexString;\n                    if (lexer.identifierEquals(FnvHash.Constants.X)) {\n                        lexer.nextToken();\n                        hexString = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_CHARS) {\n                        hexString = null;\n                    } else {\n                        hexString = lexer.hexString();\n                        lexer.nextToken();\n                    }\n\n                    SQLCharExpr charExpr;\n                    if (hexString == null) {\n                        String str = lexer.stringVal();\n                        lexer.nextToken();\n                        charExpr = new MySqlCharExpr(str, \"_big5\");\n                    } else {\n                        charExpr = new SQLCharExpr(MySqlUtils.big5(hexString));\n                    }\n\n                    return primaryRest(charExpr);\n                } else if (hash_lower == FnvHash.Constants.CURRENT_USER && isEnabled(SQLParserFeature.EnableCurrentUserExpr)) {\n                    lexer.nextToken();\n                    return primaryRest(\n                            new SQLCurrentUserExpr());\n                } else if (hash_lower == -5808529385363204345L && lexer.charAt(lexer.pos()) == '\\'') { // hex\n                    lexer.nextToken();\n                    SQLHexExpr hex = new SQLHexExpr(lexer.stringVal());\n                    lexer.nextToken();\n                    return primaryRest(hex);\n                }\n\n                if (currentTimeExpr != null) {\n                    String methodName = lexer.stringVal();\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.LPAREN) {\n                            lexer.nextToken();\n                        } else {\n                            return primaryRest(\n                                    methodRest(new SQLIdentifierExpr(methodName), false)\n                            );\n                        }\n                    }\n\n                    return primaryRest(currentTimeExpr);\n                }\n\n                return super.primary();\n            case VARIANT:\n                SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(lexer.stringVal());\n                lexer.nextToken();\n                if (varRefExpr.getName().equalsIgnoreCase(\"@@global\")) {\n                    accept(Token.DOT);\n                    varRefExpr = new SQLVariantRefExpr(lexer.stringVal(), true);\n                    lexer.nextToken();\n                } else if (varRefExpr.getName().equals(\"@\") && lexer.token() == Token.LITERAL_CHARS) {\n                    varRefExpr.setName(\"@'\" + lexer.stringVal() + \"'\");\n                    lexer.nextToken();\n                } else if (varRefExpr.getName().equals(\"@@\") && lexer.token() == Token.LITERAL_CHARS) {\n                    varRefExpr.setName(\"@@'\" + lexer.stringVal() + \"'\");\n                    lexer.nextToken();\n                }\n                return primaryRest(varRefExpr);\n            case VALUES:\n                lexer.nextToken();\n\n                if (lexer.token() != Token.LPAREN) {\n                    SQLExpr expr = primary();\n                    SQLValuesQuery values = new SQLValuesQuery();\n                    values.addValue(new SQLListExpr(expr));\n                    return new SQLQueryExpr(new SQLSelect(values));\n                }\n                return this.methodRest(new SQLIdentifierExpr(\"VALUES\"), true);\n            case BINARY:\n                lexer.nextToken();\n                if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI || lexer.token() == Token.EOF) {\n                    return new SQLIdentifierExpr(\"BINARY\");\n                } else {\n                    SQLUnaryExpr binaryExpr = new SQLUnaryExpr(SQLUnaryOperator.BINARY, primary());\n                    return primaryRest(binaryExpr);\n                }\n            default:\n                if (lexer.token() == Token.WITH) {\n                    SQLQueryExpr queryExpr = new SQLQueryExpr(\n                        createSelectParser()\n                            .select());\n                    return queryExpr;\n                }\n\n                return super.primary();\n        }\n\n    }\n\n    protected MySqlJSONTableExpr.Column parseJsonTableColumn() {\n        MySqlJSONTableExpr.Column column = new MySqlJSONTableExpr.Column();\n\n        SQLName name = this.name();\n        column.setName(\n                name);\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n            acceptIdentifier(\"ORDINALITY\");\n            column.setOrdinality(true);\n        } else {\n            boolean nested = name instanceof SQLIdentifierExpr\n                    && name.nameHashCode64() == FnvHash.Constants.NESTED;\n\n            if (!nested) {\n                column.setDataType(\n                        this.parseDataType());\n            }\n\n            if (lexer.token() == Token.EXISTS) {\n                lexer.nextToken();\n                column.setExists(true);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.PATH)) {\n                lexer.nextToken();\n                column.setPath(\n                        this.primary());\n            }\n\n            if (name instanceof SQLIdentifierExpr\n                    && name.nameHashCode64() == FnvHash.Constants.NESTED) {\n                acceptIdentifier(\"COLUMNS\");\n                accept(Token.LPAREN);\n                for (; lexer.token() != Token.RPAREN; ) {\n                    MySqlJSONTableExpr.Column nestedColumn = parseJsonTableColumn();\n                    column.addNestedColumn(nestedColumn);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n\n            for (int i = 0; i < 2; ++i) {\n                if (lexer.identifierEquals(\"ERROR\")\n                        || lexer.token() == Token.DEFAULT\n                        || lexer.token() == Token.NULL) {\n                    if (lexer.token() == Token.DEFAULT) {\n                        lexer.nextToken();\n                    }\n\n                    SQLExpr expr = this.expr();\n                    accept(Token.ON);\n                    if (lexer.identifierEquals(\"ERROR\")) {\n                        lexer.nextToken();\n                        column.setOnError(expr);\n                    } else {\n                        acceptIdentifier(\"EMPTY\");\n                        column.setOnEmpty(expr);\n                    }\n                }\n            }\n        }\n\n        return column;\n    }\n\n    public final SQLExpr primaryRest(SQLExpr expr) {\n        if (expr == null) {\n            throw new IllegalArgumentException(\"expr\");\n        }\n\n        if (lexer.token() == Token.LITERAL_CHARS) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                String ident = identExpr.getName();\n\n                if (ident.equalsIgnoreCase(\"x\")) {\n                    char ch = lexer.charAt(lexer.pos());\n                    if (ch == '\\'') {\n                        String charValue = lexer.stringVal();\n                        lexer.nextToken();\n                        expr = new SQLHexExpr(charValue);\n                        return primaryRest(expr);\n                    }\n\n//                } else if (ident.equalsIgnoreCase(\"b\")) {\n//                    String charValue = lexer.stringVal();\n//                    lexer.nextToken();\n//                    expr = new SQLBinaryExpr(charValue);\n//\n//                    return primaryRest(expr);\n                } else if (ident.startsWith(\"_\")) {\n                    String charValue = lexer.stringVal();\n                    lexer.nextToken();\n\n                    MySqlCharExpr mysqlCharExpr = new MySqlCharExpr(charValue);\n                    mysqlCharExpr.setCharset(identExpr.getName());\n                    if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                        lexer.nextToken();\n\n                        String collate = lexer.stringVal();\n                        mysqlCharExpr.setCollate(collate);\n                        if (lexer.token() == Token.LITERAL_CHARS) {\n                            lexer.nextToken();\n                        } else {\n                            accept(Token.IDENTIFIER);\n                        }\n                    }\n\n                    expr = mysqlCharExpr;\n\n                    return primaryRest(expr);\n                }\n            } else if (expr instanceof SQLCharExpr) {\n                StringBuilder text2 = new StringBuilder(((SQLCharExpr) expr).getText());\n                do {\n                    String chars = lexer.stringVal();\n                    text2.append(chars);\n                    lexer.nextToken();\n                } while (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS);\n                expr = new SQLCharExpr(text2.toString());\n            } else if (expr instanceof SQLVariantRefExpr) {\n                SQLMethodInvokeExpr concat = new SQLMethodInvokeExpr(\"CONCAT\");\n                concat.addArgument(expr);\n                concat.addArgument(this.primary());\n                expr = concat;\n\n                return primaryRest(expr);\n            }\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            if (expr instanceof SQLHexExpr) {\n                if (\"USING\".equalsIgnoreCase(lexer.stringVal())) {\n                    lexer.nextToken();\n                    if (lexer.token() != Token.IDENTIFIER) {\n                        throw new ParserException(\"syntax error, illegal hex. \" + lexer.info());\n                    }\n                    String charSet = lexer.stringVal();\n                    lexer.nextToken();\n                    expr.getAttributes().put(\"USING\", charSet);\n\n                    return primaryRest(expr);\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                if (lexer.token() != Token.IDENTIFIER\n                        && lexer.token() != Token.LITERAL_CHARS) {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n\n                String collate = lexer.stringVal();\n                lexer.nextToken();\n\n                SQLBinaryOpExpr binaryExpr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.COLLATE,\n                        new SQLIdentifierExpr(collate), DbType.mysql);\n\n                expr = binaryExpr;\n\n                return primaryRest(expr);\n            } else if (expr instanceof SQLVariantRefExpr) {\n                if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                    lexer.nextToken();\n\n                    if (lexer.token() != Token.IDENTIFIER\n                            && lexer.token() != Token.LITERAL_CHARS) {\n                        throw new ParserException(\"syntax error. \" + lexer.info());\n                    }\n\n                    String collate = lexer.stringVal();\n                    lexer.nextToken();\n\n                    expr.putAttribute(\"COLLATE\", collate);\n\n                    return primaryRest(expr);\n                }\n            }\n        } else if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            array.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            return primaryRest(array);\n        }\n\n//        if (lexer.token() == Token.LPAREN && expr instanceof SQLIdentifierExpr) {\n//            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n//            String ident = identExpr.getName();\n//\n//            if (\"POSITION\".equalsIgnoreCase(ident)) {\n//                return parsePosition();\n//            }\n//        }\n\n        if (lexer.token() == Token.VARIANT) {\n            String variant = lexer.stringVal();\n            if (\"@\".equals(variant)) {\n                return userNameRest(expr);\n            } else if (\"@localhost\".equals(variant)) {\n                return userNameRest(expr);\n            } else {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n        }\n\n        if (lexer.token() == Token.ERROR) {\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    public SQLName userName() {\n        SQLName name = this.name();\n        if (lexer.token() == Token.LPAREN && name.hashCode64() == FnvHash.Constants.CURRENT_USER) {\n            lexer.nextToken();\n            accept(Token.RPAREN);\n            return name;\n        }\n\n        return (SQLName) userNameRest(name);\n    }\n\n    private SQLExpr userNameRest(SQLExpr expr) {\n        if (lexer.token() != Token.VARIANT || !lexer.stringVal().startsWith(\"@\")) {\n            return expr;\n        }\n\n        MySqlUserName userName = new MySqlUserName();\n        if (expr instanceof SQLCharExpr) {\n            userName.setUserName(((SQLCharExpr) expr).getText());\n        } else {\n            userName.setUserName(((SQLIdentifierExpr) expr).getName());\n        }\n\n        String strVal = lexer.stringVal();\n        lexer.nextToken();\n\n        if (strVal.length() > 1) {\n            userName.setHost(strVal.substring(1));\n            return userName;\n        }\n\n        if (lexer.token() == Token.LITERAL_CHARS) {\n            userName.setHost(lexer.stringVal());\n        } else {\n            if (lexer.token() == Token.PERCENT) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            } else {\n                userName.setHost(lexer.stringVal());\n            }\n        }\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.IDENTIFIED)) {\n            Lexer.SavePoint mark = lexer.mark();\n\n            lexer.nextToken();\n            if (lexer.token() == Token.BY) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.PASSWORD)) {\n                    lexer.reset(mark);\n                } else {\n                    userName.setIdentifiedBy(lexer.stringVal());\n                    lexer.nextToken();\n                }\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        return userName;\n    }\n\n    protected SQLExpr parsePosition() {\n        SQLExpr expr = this.primary();\n        expr = this.primaryRest(expr);\n        expr = bitXorRest(expr);\n        expr = additiveRest(expr);\n        expr = shiftRest(expr);\n        expr = bitAndRest(expr);\n        expr = bitOrRest(expr);\n\n        if (lexer.token() == Token.IN) {\n            accept(Token.IN);\n        } else if (lexer.token() == Token.COMMA) {\n            accept(Token.COMMA);\n        } else {\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n        SQLExpr str = this.expr();\n        accept(Token.RPAREN);\n\n        SQLMethodInvokeExpr locate = new SQLMethodInvokeExpr(\"LOCATE\");\n        locate.addArgument(expr);\n        locate.addArgument(str);\n\n        return primaryRest(locate);\n    }\n\n    protected SQLExpr parseExtract() {\n        SQLExpr expr;\n        if (lexer.token() != Token.IDENTIFIER) {\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n\n        String unitVal = lexer.stringVal();\n        SQLIntervalUnit unit = SQLIntervalUnit.valueOf(unitVal.toUpperCase());\n        lexer.nextToken();\n\n        accept(Token.FROM);\n\n        SQLExpr value = expr();\n\n        SQLExtractExpr extract = new SQLExtractExpr();\n        extract.setValue(value);\n        extract.setUnit(unit);\n        accept(Token.RPAREN);\n\n        expr = extract;\n\n        return primaryRest(expr);\n    }\n\n    public SQLSelectParser createSelectParser() {\n        return new MySqlSelectParser(this);\n    }\n\n    protected SQLExpr parseInterval() {\n        accept(Token.INTERVAL);\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(\"INTERVAL\");\n            if (lexer.token() != Token.RPAREN) {\n                exprList(methodInvokeExpr.getArguments(), methodInvokeExpr);\n            }\n\n            accept(Token.RPAREN);\n\n            if (methodInvokeExpr.getArguments().size() == 1\n                    && lexer.token() == Token.IDENTIFIER) {\n                SQLExpr value = methodInvokeExpr.getArguments().get(0);\n                String unit = lexer.stringVal();\n                lexer.nextToken();\n\n                SQLIntervalExpr intervalExpr = new SQLIntervalExpr();\n                intervalExpr.setValue(value);\n                intervalExpr.setUnit(SQLIntervalUnit.valueOf(unit.toUpperCase()));\n                return intervalExpr;\n            } else {\n                return primaryRest(methodInvokeExpr);\n            }\n        } else {\n            SQLExpr value = expr();\n\n            if (lexer.token() != Token.IDENTIFIER) {\n                throw new ParserException(\"Syntax error. \" + lexer.info());\n            }\n\n            SQLIntervalUnit intervalUnit = null;\n\n            String unit = lexer.stringVal();\n            long unitHash = lexer.hashLCase();\n            lexer.nextToken();\n\n            intervalUnit = SQLIntervalUnit.valueOf(unit.toUpperCase());\n            if (lexer.token() == Token.TO) {\n                lexer.nextToken();\n                if (unitHash == FnvHash.Constants.YEAR) {\n                    if (lexer.identifierEquals(FnvHash.Constants.MONTH)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.YEAR_MONTH;\n                    } else {\n                        throw new ParserException(\"Syntax error. \" + lexer.info());\n                    }\n                } else if (unitHash == FnvHash.Constants.DAY) {\n                    if (lexer.identifierEquals(FnvHash.Constants.HOUR)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.DAY_HOUR;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.MINUTE)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.DAY_MINUTE;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.DAY_SECOND;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.MICROSECOND)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.DAY_MICROSECOND;\n                    } else {\n                        throw new ParserException(\"Syntax error. \" + lexer.info());\n                    }\n                } else if (unitHash == FnvHash.Constants.HOUR) {\n                    if (lexer.identifierEquals(FnvHash.Constants.MINUTE)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.HOUR_MINUTE;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.HOUR_SECOND;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.MICROSECOND)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.HOUR_MICROSECOND;\n                    } else {\n                        throw new ParserException(\"Syntax error. \" + lexer.info());\n                    }\n                } else if (unitHash == FnvHash.Constants.MINUTE) {\n                    if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.MINUTE_SECOND;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.MICROSECOND)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.MINUTE_MICROSECOND;\n                    } else {\n                        throw new ParserException(\"Syntax error. \" + lexer.info());\n                    }\n                } else if (unitHash == FnvHash.Constants.SECOND) {\n                    if (lexer.identifierEquals(FnvHash.Constants.MICROSECOND)) {\n                        lexer.nextToken();\n                        intervalUnit = SQLIntervalUnit.SECOND_MICROSECOND;\n                    } else {\n                        throw new ParserException(\"Syntax error. \" + lexer.info());\n                    }\n                } else {\n                    throw new ParserException(\"Syntax error. \" + lexer.info());\n                }\n            }\n\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr();\n            intervalExpr.setValue(value);\n            intervalExpr.setUnit(intervalUnit);\n\n            return intervalExpr;\n        }\n    }\n\n    public SQLColumnDefinition parseColumn() {\n        SQLColumnDefinition column = new SQLColumnDefinition();\n        column.setDbType(dbType);\n\n        SQLName name = name();\n        column.setName(name);\n        column.setDataType(\n                parseDataType());\n\n        if (column.getDataType() != null && column.getDataType().jdbcType() == Types.CHAR) {\n            // ENUM or SET with character set.\n            if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n                lexer.nextToken();\n\n                accept(Token.SET);\n\n                if (lexer.token() != Token.IDENTIFIER\n                        && lexer.token() != Token.LITERAL_CHARS) {\n                    throw new ParserException(lexer.info());\n                }\n                column.setCharsetExpr(primary());\n            }\n        }\n\n        // May multiple collate caused by type with collate.\n        while (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            SQLExpr collateExpr;\n            if (lexer.token() == Token.IDENTIFIER) {\n                collateExpr = new SQLIdentifierExpr(lexer.stringVal());\n            } else {\n                collateExpr = new SQLCharExpr(lexer.stringVal());\n            }\n            lexer.nextToken();\n            column.setCollateExpr(collateExpr);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)) {\n            lexer.nextToken();\n            acceptIdentifier(\"ALWAYS\");\n            accept(Token.AS);\n            accept(Token.LPAREN);\n            SQLExpr expr = this.expr();\n            accept(Token.RPAREN);\n            column.setGeneratedAlwaysAs(expr);\n        }\n\n        return parseColumnRest(column);\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            accept(Token.UPDATE);\n            SQLExpr expr = this.primary();\n            column.setOnUpdate(expr);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ENCODE)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            column.setEncode(this.charExpr());\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.COMPRESSION)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            column.setCompression(this.charExpr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)\n                || lexer.identifierEquals(FnvHash.Constants.CHARSET)) {\n            if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n                lexer.nextToken();\n                accept(Token.SET);\n            } else {\n                lexer.nextToken();\n            }\n\n            SQLExpr charSet;\n            if (lexer.token() == Token.IDENTIFIER) {\n                charSet = new SQLIdentifierExpr(lexer.stringVal());\n            } else {\n                charSet = new SQLCharExpr(lexer.stringVal());\n            }\n            lexer.nextToken();\n            column.setCharsetExpr(charSet);\n\n            return parseColumnRest(column);\n        }\n        if (lexer.identifierEquals(\"disableindex\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.TRUE) {\n                lexer.nextToken();\n                column.setDisableIndex(true);\n            }\n            return parseColumnRest(column);\n        }\n        if (lexer.identifierEquals(\"jsonIndexAttrs\")) {\n            lexer.nextToken();\n            column.setJsonIndexAttrsExpr(new SQLIdentifierExpr(lexer.stringVal()));\n            lexer.nextToken();\n            return parseColumnRest(column);\n        }\n        if (lexer.identifierEquals(\"precision\")) {\n            lexer.nextToken();\n            int precision = parseIntValue();\n            acceptIdentifier(\"scale\");\n            int scale = parseIntValue();\n\n            List<SQLExpr> arguments = column.getDataType().getArguments();\n            arguments.add(new SQLIntegerExpr(precision));\n            arguments.add(new SQLIntegerExpr(scale));\n\n            return parseColumnRest(column);\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            SQLExpr collateExpr;\n            if (lexer.token() == Token.IDENTIFIER) {\n                collateExpr = new SQLIdentifierExpr(lexer.stringVal());\n            } else {\n                collateExpr = new SQLCharExpr(lexer.stringVal());\n            }\n            lexer.nextToken();\n            column.setCollateExpr(collateExpr);\n            return parseColumnRest(column);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PRECISION)\n                && column.getDataType().nameHashCode64() == FnvHash.Constants.DOUBLE) {\n            lexer.nextToken();\n        }\n\n        /* Allow partition in alter table.\n        if (lexer.token() == Token.PARTITION) {\n            throw new ParserException(\"syntax error \" + lexer.info());\n        }\n        */\n\n        if (lexer.identifierEquals(\"COLUMN_FORMAT\")) {\n            lexer.nextToken();\n            SQLExpr expr = expr();\n            column.setFormat(expr);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STORAGE)) {\n            lexer.nextToken();\n            SQLExpr expr = expr();\n            column.setStorage(expr);\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            SQLExpr expr = expr();\n            column.setAsExpr(expr);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STORED) || lexer.identifierEquals(\"PERSISTENT\")) {\n            lexer.nextToken();\n            column.setStored(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.VIRTUAL)) {\n            lexer.nextToken();\n            column.setVirtual(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DELIMITER)) {\n            lexer.nextToken();\n            SQLExpr expr = this.expr();\n            column.setDelimiter(expr);\n            return parseColumnRest(column);\n        }\n\n        if (lexer.identifierEquals(\"delimiter_tokenizer\")) {\n            lexer.nextToken();\n            SQLExpr expr = this.expr();\n            column.setDelimiterTokenizer(expr);\n            return parseColumnRest(column);\n        }\n\n        if (lexer.identifierEquals(\"nlp_tokenizer\")) {\n            lexer.nextToken();\n            SQLExpr expr = this.expr();\n            column.setNlpTokenizer(expr);\n        }\n\n        if (lexer.identifierEquals(\"value_type\")) {\n            lexer.nextToken();\n            SQLExpr expr = this.expr();\n            column.setValueType(expr);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COLPROPERTIES)) {\n            lexer.nextToken();\n            this.parseAssignItem(column.getColProperties(), column);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ANNINDEX)) {\n            lexer.nextToken();\n\n            accept(Token.LPAREN);\n            SQLAnnIndex annIndex = new SQLAnnIndex();\n            for (; ; ) {\n                if (lexer.identifierEquals(FnvHash.Constants.TYPE)) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    String type = lexer.stringVal();\n                    annIndex.setIndexType(type);\n                    accept(Token.LITERAL_CHARS);\n                } else if (lexer.identifierEquals(FnvHash.Constants.RTTYPE)) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    String type = lexer.stringVal();\n                    annIndex.setRtIndexType(type);\n                    accept(Token.LITERAL_CHARS);\n                } else if (lexer.identifierEquals(FnvHash.Constants.DISTANCE)) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    String type = lexer.stringVal();\n                    annIndex.setDistance(type);\n                    accept(Token.LITERAL_CHARS);\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.RPAREN);\n\n            column.setAnnIndex(annIndex);\n\n            return parseColumnRest(column);\n        }\n\n        super.parseColumnRest(column);\n\n        return column;\n    }\n\n    protected SQLDataType parseDataTypeRest(SQLDataType dataType) {\n        super.parseDataTypeRest(dataType);\n\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.UNSIGNED)) {\n                lexer.nextToken();\n                ((SQLDataTypeImpl) dataType).setUnsigned(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SIGNED)) {\n                lexer.nextToken(); // skip\n            } else if (lexer.identifierEquals(FnvHash.Constants.ZEROFILL)) {\n                lexer.nextToken();\n                ((SQLDataTypeImpl) dataType).setZerofill(true);\n            } else {\n                break;\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {\n            lexer.nextToken();\n            dataType = new SQLArrayDataType(dataType);\n        }\n\n        return dataType;\n    }\n\n    public SQLAssignItem parseAssignItem(boolean variant, SQLObject parent) {\n        SQLAssignItem item = new SQLAssignItem();\n\n        SQLExpr var = primary();\n\n        String ident = null;\n        long identHash = 0;\n        if (variant && var instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) var;\n            ident = identExpr.getName();\n            identHash = identExpr.hashCode64();\n\n            if (identHash == FnvHash.Constants.GLOBAL) {\n                ident = lexer.stringVal();\n                lexer.nextToken();\n                var = new SQLVariantRefExpr(ident, true);\n            } else if (identHash == FnvHash.Constants.SESSION) {\n                ident = lexer.stringVal();\n                lexer.nextToken();\n                var = new SQLVariantRefExpr(ident, false, true);\n            } else {\n                var = new SQLVariantRefExpr(ident);\n            }\n        }\n\n        if (identHash == FnvHash.Constants.NAMES) {\n            String charset = lexer.stringVal();\n\n            SQLExpr varExpr = null;\n            boolean chars = false;\n            final Token token = lexer.token();\n            if (token == Token.IDENTIFIER) {\n                lexer.nextToken();\n            } else if (token == Token.DEFAULT) {\n                charset = \"DEFAULT\";\n                lexer.nextToken();\n            } else if (token == Token.QUES) {\n                varExpr = new SQLVariantRefExpr(\"?\");\n                lexer.nextToken();\n            } else {\n                chars = true;\n                accept(Token.LITERAL_CHARS);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                MySqlCharExpr charsetExpr = new MySqlCharExpr(charset);\n                lexer.nextToken();\n\n                String collate = lexer.stringVal();\n                lexer.nextToken();\n                charsetExpr.setCollate(collate);\n\n                item.setValue(charsetExpr);\n            } else {\n                if (varExpr != null) {\n                    item.setValue(varExpr);\n                } else {\n                    item.setValue(chars\n                            ? new SQLCharExpr(charset)\n                            : new SQLIdentifierExpr(charset)\n                    );\n                }\n            }\n\n            item.setTarget(var);\n            return item;\n        } else if (identHash == FnvHash.Constants.CHARACTER) {\n            var = new SQLVariantRefExpr(\"CHARACTER SET\");\n            accept(Token.SET);\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n        } else if (identHash == FnvHash.Constants.CHARSET) {\n            var = new SQLVariantRefExpr(\"CHARACTER SET\");\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n        } else if (identHash == FnvHash.Constants.TRANSACTION) {\n            var = new SQLVariantRefExpr(\"TRANSACTION\");\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n        } else {\n            if (lexer.token() == Token.COLONEQ) {\n                lexer.nextToken();\n            } else {\n                accept(Token.EQ);\n            }\n        }\n\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            item.setValue(new SQLIdentifierExpr(\"ON\"));\n        } else {\n            item.setValue(this.expr());\n        }\n\n        item.setTarget(var);\n        return item;\n    }\n\n    public SQLName nameRest(SQLName name) {\n        if (lexer.token() == Token.VARIANT && \"@\".equals(lexer.stringVal())) {\n            lexer.nextToken();\n            MySqlUserName userName = new MySqlUserName();\n            userName.setUserName(((SQLIdentifierExpr) name).getName());\n\n            if (lexer.token() == Token.LITERAL_CHARS) {\n                userName.setHost(\"'\" + lexer.stringVal() + \"'\");\n            } else {\n                userName.setHost(lexer.stringVal());\n            }\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.IDENTIFIED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                userName.setIdentifiedBy(lexer.stringVal());\n                lexer.nextToken();\n            }\n\n            return userName;\n        }\n        return super.nameRest(name);\n    }\n\n    @Override\n    public MySqlPrimaryKey parsePrimaryKey() {\n        MySqlPrimaryKey primaryKey = new MySqlPrimaryKey();\n        parseIndex(primaryKey.getIndexDefinition());\n        return primaryKey;\n        /*\n        accept(Token.PRIMARY);\n        accept(Token.KEY);\n\n        MySqlPrimaryKey primaryKey = new MySqlPrimaryKey();\n\n        if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n            lexer.nextToken();\n            primaryKey.setIndexType(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.token() != Token.LPAREN) {\n            SQLName name = this.name();\n            primaryKey.setName(name);\n        }\n\n        accept(Token.LPAREN);\n        for (;;) {\n            setAllowIdentifierMethod(false);\n\n            SQLExpr expr;\n            if (lexer.token() == Token.LITERAL_ALIAS) {\n                expr = this.name();\n            } else {\n                expr = this.expr();\n            }\n\n            setAllowIdentifierMethod(true);\n\n            SQLSelectOrderByItem item = new SQLSelectOrderByItem();\n\n            item.setExpr(expr);\n\n            if (lexer.token() == Token.ASC) {\n                lexer.nextToken();\n                item.setType(SQLOrderingSpecification.ASC);\n            } else if (lexer.token() == Token.DESC) {\n                lexer.nextToken();\n                item.setType(SQLOrderingSpecification.DESC);\n            }\n\n            primaryKey.addColumn(item);\n            if (!(lexer.token() == (Token.COMMA))) {\n                break;\n            } else {\n                lexer.nextToken();\n            }\n        }\n        accept(Token.RPAREN);\n\n        for (;;) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                SQLExpr comment = this.primary();\n                primaryKey.setComment(comment);\n            } else if (lexer.identifierEquals(FnvHash.Constants.KEY_BLOCK_SIZE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr keyBlockSize = this.primary();\n                primaryKey.setKeyBlockSize(keyBlockSize);\n            } else if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n                lexer.nextToken();\n                primaryKey.setIndexType(lexer.stringVal());\n                accept(Token.IDENTIFIER);\n            } else {\n                break;\n            }\n        }\n\n        return primaryKey;\n        */\n    }\n\n    public MySqlUnique parseUnique() {\n        MySqlUnique unique = new MySqlUnique();\n        parseIndex(unique.getIndexDefinition());\n        return unique;\n    }\n\n    protected SQLForeignKeyImpl createForeignKey() {\n        return new MysqlForeignKey();\n    }\n\n    public MysqlForeignKey parseForeignKey() {\n        accept(Token.FOREIGN);\n        accept(Token.KEY);\n\n        MysqlForeignKey fk = new MysqlForeignKey();\n\n        if (lexer.token() != Token.LPAREN) {\n            SQLName indexName = name();\n            fk.setIndexName(indexName);\n        }\n\n        accept(Token.LPAREN);\n        this.names(fk.getReferencingColumns(), fk);\n        accept(Token.RPAREN);\n\n        accept(Token.REFERENCES);\n\n        fk.setReferencedTableName(this.name());\n\n        accept(Token.LPAREN);\n        this.names(fk.getReferencedColumns());\n        accept(Token.RPAREN);\n\n        if (lexer.identifierEquals(FnvHash.Constants.MATCH)) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"FULL\") || lexer.token() == Token.FULL) {\n                fk.setReferenceMatch(Match.FULL);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.PARTIAL)) {\n                fk.setReferenceMatch(Match.PARTIAL);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.SIMPLE)) {\n                fk.setReferenceMatch(Match.SIMPLE);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n        }\n\n        while (lexer.token() == Token.ON) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.DELETE) {\n                lexer.nextToken();\n\n                Option option = parseReferenceOption();\n                fk.setOnDelete(option);\n            } else if (lexer.token() == Token.UPDATE) {\n                lexer.nextToken();\n\n                Option option = parseReferenceOption();\n                fk.setOnUpdate(option);\n            } else {\n                throw new ParserException(\"syntax error, expect DELETE or UPDATE, actual \" + lexer.token() + \" \"\n                        + lexer.info());\n            }\n        }\n        return fk;\n    }\n\n    protected SQLAggregateExpr parseAggregateExprRest(SQLAggregateExpr aggregateExpr) {\n        if (lexer.token() == Token.ORDER) {\n            SQLOrderBy orderBy = this.parseOrderBy();\n            aggregateExpr.setOrderBy(orderBy);\n            //为了兼容之前的逻辑\n            aggregateExpr.putAttribute(\"ORDER BY\", orderBy);\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.SEPARATOR)) {\n            lexer.nextToken();\n\n            SQLExpr seperator = this.primary();\n            seperator.setParent(aggregateExpr);\n\n            aggregateExpr.putAttribute(\"SEPARATOR\", seperator);\n        }\n        return aggregateExpr;\n    }\n\n    public MySqlOrderingExpr parseSelectGroupByItem() {\n        MySqlOrderingExpr item = new MySqlOrderingExpr();\n\n        item.setExpr(expr());\n\n        if (lexer.token() == Token.ASC) {\n            lexer.nextToken();\n            item.setType(SQLOrderingSpecification.ASC);\n        } else if (lexer.token() == Token.DESC) {\n            lexer.nextToken();\n            item.setType(SQLOrderingSpecification.DESC);\n        }\n\n        return item;\n    }\n\n    public SQLSubPartition parseSubPartition() {\n        SQLSubPartition subPartition = new SQLSubPartition();\n        subPartition.setName(this.name());\n\n        for (; ; ) {\n            boolean storage = false;\n            if (lexer.identifierEquals(FnvHash.Constants.DATA)) {\n                lexer.nextToken();\n                acceptIdentifier(\"DIRECTORY\");\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                subPartition.setDataDirectory(this.expr());\n            } else if (lexer.token() == Token.TABLESPACE) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLName tableSpace = this.name();\n                subPartition.setTablespace(tableSpace);\n            } else if (lexer.token() == Token.INDEX) {\n                lexer.nextToken();\n                acceptIdentifier(\"DIRECTORY\");\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                subPartition.setIndexDirectory(this.expr());\n            } else if (lexer.identifierEquals(FnvHash.Constants.MAX_ROWS)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr maxRows = this.primary();\n                subPartition.setMaxRows(maxRows);\n            } else if (lexer.identifierEquals(FnvHash.Constants.MIN_ROWS)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr minRows = this.primary();\n                subPartition.setMinRows(minRows);\n            } else if (lexer.identifierEquals(FnvHash.Constants.ENGINE) || //\n                    (storage = (lexer.token() == Token.STORAGE || lexer.identifierEquals(FnvHash.Constants.STORAGE)))) {\n                if (storage) {\n                    lexer.nextToken();\n                }\n                acceptIdentifier(\"ENGINE\");\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                SQLName engine = this.name();\n                subPartition.setEngine(engine);\n            } else if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr comment = this.primary();\n                subPartition.setComment(comment);\n            } else {\n                break;\n            }\n        }\n\n        return subPartition;\n    }\n\n    public MysqlPartitionSingle parsePartition() {\n        if (lexer.identifierEquals(FnvHash.Constants.DBPARTITION)\n                || lexer.identifierEquals(FnvHash.Constants.TBPARTITION)\n                || lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n            lexer.nextToken();\n        } else {\n            accept(Token.PARTITION);\n        }\n\n    MysqlPartitionSingle partitionDef = new MysqlPartitionSingle();\n\n        SQLName name;\n        if (lexer.token() == Token.LITERAL_INT) {\n            Number number = lexer.integerValue();\n            name = new SQLIdentifierExpr(number.toString());\n            lexer.nextToken();\n        } else {\n            name = this.name();\n        }\n        partitionDef.setName(name);\n\n        SQLPartitionValue values = this.parsePartitionValues();\n        if (values != null) {\n            partitionDef.setValues(values);\n        }\n\n        for (; ; ) {\n            boolean storage = false;\n            if (lexer.identifierEquals(FnvHash.Constants.DATA)) {\n                lexer.nextToken();\n                acceptIdentifier(\"DIRECTORY\");\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                partitionDef.setDataDirectory(this.expr());\n            } else if (lexer.token() == Token.TABLESPACE) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLName tableSpace = this.name();\n                partitionDef.setTablespace(tableSpace);\n            } else if (lexer.token() == Token.INDEX) {\n                lexer.nextToken();\n                acceptIdentifier(\"DIRECTORY\");\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                partitionDef.setIndexDirectory(this.expr());\n            } else if (lexer.identifierEquals(FnvHash.Constants.MAX_ROWS)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr maxRows = this.primary();\n                partitionDef.setMaxRows(maxRows);\n            } else if (lexer.identifierEquals(FnvHash.Constants.MIN_ROWS)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr minRows = this.primary();\n                partitionDef.setMaxRows(minRows);\n            } else if (lexer.identifierEquals(FnvHash.Constants.ENGINE) || //\n                    (storage = (lexer.token() == Token.STORAGE || lexer.identifierEquals(FnvHash.Constants.STORAGE)))) {\n                if (storage) {\n                    lexer.nextToken();\n                }\n                acceptIdentifier(\"ENGINE\");\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n\n                SQLName engine = this.name();\n                partitionDef.setEngine(engine);\n            } else if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr comment = this.primary();\n                partitionDef.setComment(comment);\n            } else {\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                acceptIdentifier(\"SUBPARTITION\");\n\n                SQLSubPartition subPartition = parseSubPartition();\n\n                partitionDef.addSubPartition(subPartition);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(\"LOCALITY\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLExpr locality = this.expr();\n            partitionDef.setLocality(locality);\n        }\n\n        return partitionDef;\n    }\n\n    protected SQLExpr parseAliasExpr(String alias) {\n        if (isEnabled(SQLParserFeature.KeepNameQuotes)) {\n            return new SQLIdentifierExpr(alias);\n        }\n        Lexer newLexer = new Lexer(alias);\n        newLexer.nextTokenValue();\n        return new SQLCharExpr(newLexer.stringVal());\n    }\n\n    public boolean parseTableOptions(List<SQLAssignItem> assignItems, SQLDDLStatement parent) {\n        // Check whether table options.\n        boolean succeed = false;\n\n        while (lexer.token() != Token.EOF) {\n            final long hash = lexer.hashLCase();\n            final int idx = Arrays.binarySearch(SINGLE_WORD_TABLE_OPTIONS_CODES, hash);\n            SQLAssignItem assignItem = null;\n            Lexer.SavePoint mark = null;\n\n            if (idx >= 0 && idx < SINGLE_WORD_TABLE_OPTIONS_CODES.length &&\n                    SINGLE_WORD_TABLE_OPTIONS_CODES[idx] == hash &&\n                    (lexer.token() == Token.IDENTIFIER || (lexer.token().name != null && lexer.token().name.length() == SINGLE_WORD_TABLE_OPTIONS[idx].length()))) {\n                // Special items.\n                if (lexer.token() == Token.TABLESPACE) {\n                    lexer.nextToken();\n\n                    MySqlCreateTableStatement.TableSpaceOption option = new MySqlCreateTableStatement.TableSpaceOption();\n                    option.setName(name());\n\n                    if (lexer.identifierEquals(\"STORAGE\")) {\n                        lexer.nextToken();\n                        option.setStorage(name());\n                    }\n                    assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"TABLESPACE\"), option);\n                } else if (lexer.token() == Token.UNION) {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n\n                    accept(Token.LPAREN);\n                    SQLListExpr list = new SQLListExpr();\n                    exprList(list.getItems(), list);\n                    accept(Token.RPAREN);\n                    assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"UNION\"), list);\n                } else if (lexer.identifierEquals(\"PACK_KEYS\")) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n\n                    if (lexer.identifierEquals(\"PACK\")) {\n                        lexer.nextToken();\n                        accept(Token.ALL);\n                        assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"PACK_KEYS\"), new SQLIdentifierExpr(\"PACK ALL\"));\n                    } else {\n                        assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"PACK_KEYS\"), expr());\n                    }\n                } else if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n\n                    SQLExpr expr;\n                    if (lexer.token() == Token.MERGE) {\n                        expr = new SQLIdentifierExpr(lexer.stringVal());\n                        lexer.nextToken();\n                    } else {\n                        expr = expr();\n                    }\n                    assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"ENGINE\"), expr);\n                } else {\n                    // Find single key, store as KV.\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n\n                    // STORAGE_POLICY\n                    assignItem = new SQLAssignItem(\n                            new SQLIdentifierExpr(SINGLE_WORD_TABLE_OPTIONS[idx]),\n                            idx == 9 ? charExpr() : expr()\n                    );\n                }\n            } else {\n                // Following may not table options. Save mark.\n                mark = lexer.mark();\n\n                if (lexer.token() == Token.DEFAULT) {\n                    // [DEFAULT] CHARACTER SET [=] charset_name\n                    // [DEFAULT] COLLATE [=] collation_name\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n                        lexer.nextToken();\n                        accept(Token.SET);\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        if (lexer.token() == Token.IDENTIFIER) {\n                            assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"CHARACTER SET\"), new SQLIdentifierExpr(lexer.stringVal()));\n                            lexer.nextToken();\n                        } else if (lexer.token() == Token.LITERAL_ALIAS || lexer.token() == Token.LITERAL_CHARS) {\n                            String charset = lexer.stringVal();\n                            if (charset.startsWith(\"\\\"\")) {\n                                charset = charset.substring(1, charset.length() - 1);\n                            }\n                            assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"CHARACTER SET\"), new SQLCharExpr(charset));\n                            lexer.nextToken();\n                        } else {\n                            assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"CHARACTER SET\"), expr());\n                        }\n                    } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"COLLATE\"), expr());\n                    }\n                } else if (hash == FnvHash.Constants.CHARACTER) {\n                    // CHARACTER SET [=] charset_name\n                    lexer.nextToken();\n                    accept(Token.SET);\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    } if (lexer.token() == Token.IDENTIFIER) {\n                        assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"CHARACTER SET\"), new SQLIdentifierExpr(lexer.stringVal()));\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.LITERAL_ALIAS || lexer.token() == Token.LITERAL_CHARS) {\n                        String charset = lexer.stringVal();\n                        if (charset.startsWith(\"\\\"\")) {\n                            charset = charset.substring(1, charset.length() - 1);\n                        }\n                        assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"CHARACTER SET\"), new SQLCharExpr(charset));\n                        lexer.nextToken();\n                    } else {\n                        assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"CHARACTER SET\"), expr());\n                    }\n                } else if (hash == FnvHash.Constants.DATA ||\n                        lexer.token() == Token.INDEX) {\n                    // {DATA|INDEX} DIRECTORY [=] 'absolute path to directory'\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(\"DIRECTORY\")) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        assignItem = new SQLAssignItem(new SQLIdentifierExpr(\"COLLATE\"), expr());\n                    }\n                }\n            }\n\n            if (assignItem != null) {\n                assignItem.setParent(parent);\n                assignItems.add(assignItem);\n                succeed = true;\n            } else {\n                if (mark != null) {\n                    lexer.reset(mark);\n                }\n                return succeed;\n            }\n\n            // Optional comma.\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n            } else if (lexer.token() == Token.EOF) {\n                break;\n            }\n        }\n        return succeed;\n    }\n\n    public SQLCheck parseCheck() {\n        SQLCheck check = super.parseCheck();\n        boolean enforce = true;\n        if (lexer.token() == Token.NOT) {\n            enforce = false;\n            lexer.nextToken();\n        }\n        if (lexer.nextIfIdentifier(\"ENFORCED\")) {\n            check.setEnforced(enforce);\n        }\n        return check;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlInsertReader.java",
    "content": "package com.alibaba.druid.sql.dialect.mysql.parser;\n\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.io.Reader;\n\npublic class MySqlInsertReader implements Closeable {\n    private final Reader in;\n\n    private char[] buf = new char[1024];\n    private int pos;\n    private char ch;\n\n    MySqlStatementParser parser;\n\n    private MySqlInsertStatement statement;\n\n    public MySqlInsertReader(Reader in) {\n        this.in = in;\n\n    }\n\n    public MySqlInsertStatement parseStatement() throws IOException {\n        in.read(buf);\n        String text = new String(buf);\n        parser = new MySqlStatementParser(text, SQLParserFeature.InsertReader);\n\n        statement = (MySqlInsertStatement) parser.parseStatement();\n        this.pos = parser.getLexer().pos() - 1;\n        this.ch = buf[pos];\n\n        return statement;\n    }\n\n    public MySqlInsertStatement getStatement() {\n        return statement;\n    }\n\n    public SQLInsertStatement.ValuesClause readCaluse() {\n        return null;\n    }\n\n    public boolean isEOF() {\n        return false;\n    }\n\n    @Override\n    public void close() {\n        JdbcUtils.close(in);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.isFirstIdentifierChar;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.*;\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;\n\npublic class MySqlLexer extends Lexer {\n    public static SymbolTable quoteTable = new SymbolTable(8192);\n    public static DialectFeature MYSQL_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    NextTokenPrefixN,\n                    ScanStringDoubleBackslash,\n                    JoinRightTableWith,\n                    PostNaturalJoin,\n                    MultipleJoinOn,\n                    GroupByPostDesc,\n                    GroupByItemOrder,\n                    SQLDateExpr,\n                    PrimaryLbraceOdbcEscape,\n                    ParseSelectItemPrefixX,\n                    ParseStatementListUpdatePlanCache,\n                    ParseStatementListRollbackReturn,\n                    ParseStatementListCommitReturn,\n                    ParseDropTableTables,\n                    AsSequence\n            ),\n            Collections.singletonList(\n                    AdditiveRestPipesAsConcat\n            )\n    );\n    static final Keywords MYSQL_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"DUAL\", Token.DUAL);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"IF\", Token.IF);\n        map.put(\"ELSEIF\", Token.ELSEIF);\n        map.put(\"KILL\", Token.KILL);\n\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"BINARY\", Token.BINARY);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"CACHE\", Token.CACHE);\n        map.put(\"ANALYZE\", Token.ANALYZE);\n        map.put(\"OPTIMIZE\", Token.OPTIMIZE);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"END\", Token.END);\n        map.put(\"DIV\", Token.DIV);\n        map.put(\"MERGE\", Token.MERGE);\n\n        // for oceanbase & mysql 5.7\n        map.put(\"PARTITION\", Token.PARTITION);\n\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"UNDO\", Token.UNDO);\n        map.put(\"SQLSTATE\", Token.SQLSTATE);\n        map.put(\"CONDITION\", Token.CONDITION);\n        map.put(\"MOD\", Token.MOD);\n        map.put(\"CONTAINS\", Token.CONTAINS);\n        map.put(\"RLIKE\", Token.RLIKE);\n        map.put(\"FULLTEXT\", Token.FULLTEXT);\n\n        MYSQL_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return MYSQL_KEYWORDS;\n    }\n\n    public MySqlLexer(char[] input, int inputLength, boolean skipComment) {\n        super(input, inputLength, skipComment);\n        this.dbType = DbType.mysql;\n    }\n\n    public MySqlLexer(String input) {\n        this(input, true, true);\n    }\n\n    public MySqlLexer(String input, SQLParserFeature... features) {\n        super(input, true);\n        this.keepComments = true;\n        this.dbType = DbType.mysql;\n\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    public MySqlLexer(String input, boolean skipComment, boolean keepComments) {\n        super(input, skipComment);\n        this.skipComment = skipComment;\n        this.keepComments = keepComments;\n        this.dbType = DbType.mysql;\n    }\n\n    public void scanSharp() {\n        if (ch != '#') {\n            throw new ParserException(\"illegal stat. \" + info());\n        }\n\n        if (charAt(pos + 1) == '{') {\n            scanVariable();\n            return;\n        }\n\n        Token lastToken = this.token;\n\n        mark = pos;\n        bufPos = 0;\n        scanChar();\n\n        for (; ; ) {\n            if (ch == '\\r') {\n                bufPos++;\n                scanChar();\n                if (ch == '\\n') {\n                    scanChar();\n                }\n                break;\n            } else if (ch == EOI) {\n                bufPos++;\n                break;\n            }\n\n            if (ch == '\\n') {\n                bufPos++;\n                scanChar();\n                break;\n            }\n\n            bufPos++;\n            scanChar();\n        }\n\n        stringVal = subString(mark, bufPos);\n        token = Token.LINE_COMMENT;\n        commentCount++;\n        if (keepComments) {\n            addComment(stringVal);\n        }\n\n        if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {\n            return;\n        }\n\n        endOfComment = isEOF();\n\n        if (!isAllowComment() && (endOfComment || !isSafeComment(stringVal))) {\n            throw new NotAllowCommentException();\n        }\n    }\n\n    public void scanVariable() {\n        if (ch != ':' && ch != '#' && ch != '$') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n\n        if (charAt(pos + 1) == '`') {\n            ++pos;\n            ++bufPos;\n            char ch;\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (ch == '`') {\n                    bufPos++;\n                    ch = charAt(++pos);\n                    break;\n                } else if (ch == EOI) {\n                    throw new ParserException(\"illegal identifier. \" + info());\n                }\n\n                bufPos++;\n                continue;\n            }\n\n            this.ch = charAt(pos);\n\n            stringVal = subString(mark, bufPos);\n            token = Token.VARIANT;\n        } else if (charAt(pos + 1) == '{') {\n            ++pos;\n            ++bufPos;\n            char ch;\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (ch == '}') {\n                    bufPos++;\n                    ch = charAt(++pos);\n                    break;\n                } else if (ch == EOI) {\n                    throw new ParserException(\"illegal identifier. \" + info());\n                }\n\n                bufPos++;\n                continue;\n            }\n\n            this.ch = charAt(pos);\n\n            stringVal = subString(mark, bufPos);\n            token = Token.VARIANT;\n        } else {\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (!isIdentifierCharForVariable(ch)) {\n                    break;\n                }\n\n                bufPos++;\n            }\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = subString(mark, bufPos);\n        token = Token.VARIANT;\n    }\n\n    protected void scanVariable_at() {\n        if (ch != '@') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n\n        if (charAt(pos + 1) == '@') {\n            ch = charAt(++pos);\n            bufPos++;\n        }\n\n        if (charAt(pos + 1) == '`') {\n            ++pos;\n            ++bufPos;\n            char ch;\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (ch == '`') {\n                    bufPos++;\n                    ++pos;\n                    break;\n                } else if (ch == EOI) {\n                    throw new ParserException(\"illegal identifier. \" + info());\n                }\n\n                bufPos++;\n                continue;\n            }\n\n            this.ch = charAt(pos);\n\n            stringVal = subString(mark, bufPos);\n            token = Token.VARIANT;\n        } else {\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (!isIdentifierChar(ch)) {\n                    break;\n                }\n\n                bufPos++;\n                continue;\n            }\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = subString(mark, bufPos);\n        token = Token.VARIANT;\n    }\n\n    public void scanIdentifier() {\n        hashLCase = 0;\n        hash = 0;\n\n        final char first = ch;\n\n        if (first == 'U'\n                && isEnabled(SQLParserFeature.Presto)\n                && charAt(pos + 1) == '&'\n                && charAt(pos + 2) == '\\'') {\n            initBuff(32);\n            pos += 3;\n\n            for (; ; pos++) {\n                ch = charAt(pos);\n                if (isEOF()) {\n                    lexError(\"unclosed.str.lit\");\n                    return;\n                }\n\n                if (ch == '\\'') {\n                    ch = charAt(++pos);\n                    break;\n                }\n\n                if (ch == '\\\\') {\n                    char c1 = charAt(++pos);\n                    char c2 = charAt(++pos);\n                    char c3 = charAt(++pos);\n                    char c4 = charAt(++pos);\n\n                    String tmp;\n                    if (ch == '+') {\n                        char c5 = charAt(++pos);\n                        char c6 = charAt(++pos);\n                        tmp = new String(new char[]{c1, c2, c3, c4, c5, c6});\n                    } else {\n                        tmp = new String(new char[]{c1, c2, c3, c4});\n                    }\n                    int intVal = Integer.parseInt(tmp, 16);\n                    putChar((char) intVal);\n                } else {\n                    putChar(ch);\n                }\n            }\n            stringVal = new String(buf, 0, bufPos);\n            token = LITERAL_CHARS;\n            return;\n        }\n\n        if ((ch == 'b' || ch == 'B')\n                && charAt(pos + 1) == '\\'') {\n            int i = 2;\n            int mark = pos + 2;\n            for (; ; ++i) {\n                char ch = charAt(pos + i);\n                if (ch == '0' || ch == '1') {\n                    continue;\n                } else if (ch == '\\'') {\n                    bufPos += i;\n                    pos += (i + 1);\n                    stringVal = subString(mark, i - 2);\n                    this.ch = charAt(pos);\n                    token = Token.BITS;\n                    return;\n                } else if (ch == EOI) {\n                    throw new ParserException(\"illegal identifier. \" + info());\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (ch == '`') {\n            mark = pos;\n            bufPos = 1;\n            char ch;\n\n            int startPos = pos + 1;\n            int quoteIndex;\n\n            hashLCase = 0xcbf29ce484222325L;\n            hash = 0xcbf29ce484222325L;\n\n            for (int i = startPos; ; ++i) {\n                if (i >= text.length()) {\n                    throw new ParserException(\"illegal identifier. \" + info());\n                }\n\n                ch = text.charAt(i);\n\n                if ('`' == ch) {\n                    if (i + 1 < text.length() && '`' == text.charAt(i + 1)) {\n                        ++i;\n                    } else {\n                        // End of identifier.\n                        quoteIndex = i;\n                        break;\n                    }\n                }\n\n                hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n                hashLCase *= 0x100000001b3L;\n\n                hash ^= ch;\n                hash *= 0x100000001b3L;\n            }\n\n            stringVal = quoteTable.addSymbol(text, pos, quoteIndex + 1 - pos, hash);\n            //stringVal = text.substring(mark, pos);\n            pos = quoteIndex + 1;\n            this.ch = charAt(pos);\n            token = Token.IDENTIFIER;\n        } else {\n            final boolean firstFlag = isFirstIdentifierChar(first);\n            if (!firstFlag) {\n                throw new ParserException(\"illegal identifier. \" + info());\n            }\n\n            hashLCase = 0xcbf29ce484222325L;\n            hash = 0xcbf29ce484222325L;\n\n            hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n            hashLCase *= 0x100000001b3L;\n\n            hash ^= ch;\n            hash *= 0x100000001b3L;\n\n            mark = pos;\n            bufPos = 1;\n            char ch = '\\0';\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (!isIdentifierChar(ch)) {\n                    break;\n                }\n\n                bufPos++;\n\n                hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n                hashLCase *= 0x100000001b3L;\n\n                hash ^= ch;\n                hash *= 0x100000001b3L;\n\n                continue;\n            }\n\n            this.ch = charAt(pos);\n\n            if (bufPos == 1) {\n                token = Token.IDENTIFIER;\n                stringVal = CharTypes.valueOf(first);\n                if (stringVal == null) {\n                    stringVal = Character.toString(first);\n                }\n                return;\n            }\n\n            Token tok = keywords.getKeyword(hashLCase);\n            if (tok != null) {\n                token = tok;\n                if (token == Token.IDENTIFIER) {\n                    stringVal = SymbolTable.global.addSymbol(text, mark, bufPos, hash);\n                } else {\n                    stringVal = null;\n                }\n            } else {\n                token = Token.IDENTIFIER;\n                stringVal = SymbolTable.global.addSymbol(text, mark, bufPos, hash);\n            }\n\n        }\n    }\n\n    @Override\n    protected final void scanString() {\n        {\n            boolean hasSpecial = false;\n            int startIndex = pos + 1;\n            int endIndex = -1; // text.indexOf('\\'', startIndex);\n            for (int i = startIndex; i < text.length(); ++i) {\n                final char ch = text.charAt(i);\n                if (ch == '\\\\') {\n                    hasSpecial = true;\n                    continue;\n                }\n                if (ch == '\\'') {\n                    endIndex = i;\n                    break;\n                }\n            }\n\n            if (endIndex == -1) {\n                throw new ParserException(\"unclosed str. \" + info());\n            }\n\n            String stringVal;\n            if (token == Token.AS) {\n                stringVal = text.substring(pos, endIndex + 1);\n            } else {\n                if (startIndex == endIndex) {\n                    stringVal = \"\";\n                } else {\n                    stringVal = text.substring(startIndex, endIndex);\n                }\n            }\n            // hasSpecial = stringVal.indexOf('\\\\') != -1;\n\n            if (!hasSpecial) {\n                this.stringVal = stringVal;\n                int pos = endIndex + 1;\n                char ch = charAt(pos);\n                if (ch != '\\'') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = LITERAL_CHARS;\n                    return;\n                }\n            }\n        }\n\n        mark = pos;\n        boolean hasSpecial = false;\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                switch (ch) {\n                    case '0':\n                        putChar('\\0');\n                        break;\n                    case '\\'':\n                        putChar('\\'');\n                        break;\n                    case '\"':\n                        putChar('\"');\n                        break;\n                    case 'b':\n                        putChar('\\b');\n                        break;\n                    case 'n':\n                        putChar('\\n');\n                        break;\n                    case 'r':\n                        putChar('\\r');\n                        break;\n                    case 't':\n                        putChar('\\t');\n                        break;\n                    case '\\\\':\n                        putChar('\\\\');\n                        break;\n                    case 'Z':\n                        putChar((char) 0x1A); // ctrl + Z\n                        break;\n                    case '%':\n                        putChar('\\\\');\n                        putChar('%');\n                        break;\n                    case '_':\n                        putChar('\\\\');\n                        putChar('_');\n                        break;\n                    case 'u':\n                        if ((features & SQLParserFeature.SupportUnicodeCodePoint.mask) != 0) {\n                            char c1 = charAt(++pos);\n                            char c2 = charAt(++pos);\n                            char c3 = charAt(++pos);\n                            char c4 = charAt(++pos);\n\n                            int intVal = Integer.parseInt(new String(new char[]{c1, c2, c3, c4}), 16);\n\n                            putChar((char) intVal);\n                        } else {\n                            putChar(ch);\n                        }\n                        break;\n                    default:\n                        putChar(ch);\n                        break;\n                }\n\n                continue;\n            }\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    public void skipFirstHintsOrMultiCommentAndNextToken() {\n        int starIndex = pos + 2;\n\n        for (; ; ) {\n            starIndex = text.indexOf('*', starIndex);\n            if (starIndex == -1 || starIndex == text.length() - 1) {\n                this.token = Token.ERROR;\n                return;\n            }\n\n            int slashIndex = starIndex + 1;\n            if (charAt(slashIndex) == '/') {\n                pos = slashIndex + 1;\n                ch = text.charAt(pos);\n                if (pos < text.length() - 6) {\n                    int pos_6 = pos + 6;\n                    char c0 = ch;\n                    char c1 = text.charAt(pos + 1);\n                    char c2 = text.charAt(pos + 2);\n                    char c3 = text.charAt(pos + 3);\n                    char c4 = text.charAt(pos + 4);\n                    char c5 = text.charAt(pos + 5);\n                    char c6 = text.charAt(pos_6);\n                    if (c0 == 's' && c1 == 'e' && c2 == 'l' && c3 == 'e' && c4 == 'c' && c5 == 't' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.SELECT);\n                        return;\n                    }\n\n                    if (c0 == 'i' && c1 == 'n' && c2 == 's' && c3 == 'e' && c4 == 'r' && c5 == 't' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.INSERT);\n                        return;\n                    }\n\n                    if (c0 == 'u' && c1 == 'p' && c2 == 'd' && c3 == 'a' && c4 == 't' && c5 == 'e' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.UPDATE);\n                        return;\n                    }\n\n                    if (c0 == 'd' && c1 == 'e' && c2 == 'l' && c3 == 'e' && c4 == 't' && c5 == 'e' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.DELETE);\n                        return;\n                    }\n\n                    if (c0 == 'S' && c1 == 'E' && c2 == 'L' && c3 == 'E' && c4 == 'C' && c5 == 'T' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.SELECT);\n                        return;\n                    }\n\n                    if (c0 == 'I' && c1 == 'N' && c2 == 'S' && c3 == 'E' && c4 == 'R' && c5 == 'T' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.INSERT);\n                        return;\n                    }\n\n                    if (c0 == 'U' && c1 == 'P' && c2 == 'D' && c3 == 'A' && c4 == 'T' && c5 == 'E' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.UPDATE);\n                        return;\n                    }\n\n                    if (c0 == 'D' && c1 == 'E' && c2 == 'L' && c3 == 'E' && c4 == 'T' && c5 == 'E' && c6 == ' ') {\n                        this.comments = null;\n                        reset(pos_6, ' ', Token.DELETE);\n                        return;\n                    }\n\n                    nextToken();\n                    return;\n                } else {\n                    nextToken();\n                    return;\n                }\n            }\n            starIndex++;\n        }\n    }\n\n    public void scanComment() {\n        Token lastToken = this.token;\n\n        if (ch == '-') {\n            boolean supportStandardComment = (features & SQLParserFeature.MySQLSupportStandardComment.mask) != 0;\n            /*\n             * just for tddl test case;\n             * test case : MySqlSelectTest_plus_sub_comment.java\n             */\n            char before_1 = pos == 0 ? ' ' : charAt(pos - 1);\n            char next_2 = charAt(pos + 2);\n            if (isDigit(next_2)) {\n                scanChar();\n                token = Token.SUB;\n                return;\n            } else if (supportStandardComment\n                    || ((before_1 == ' ' || (before_1 != '-' && before_1 != '+'))\n                    && (next_2 == ' ' || next_2 == EOI || next_2 == '\\n'))\n            ) {\n                // it is comments\n            } else if ((before_1 == '-' || before_1 == '+') && next_2 == ' ') {\n                throw new ParserException(\"illegal state. \" + info());\n            } else {\n                if (ch == '-') {\n                    scanChar();\n                    token = Token.SUB;\n                    return;\n                } else if (ch == '+') {\n                    scanChar();\n                    token = Token.PLUS;\n                    return;\n                }\n            }\n        } else if (ch != '/') {\n            throw new ParserException(\"illegal state. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 0;\n        scanChar();\n\n        // /*+ */\n        if (ch == '*') {\n            scanChar();\n            bufPos++;\n\n            while (ch == ' ') {\n                scanChar();\n                bufPos++;\n            }\n\n            boolean isHint = false;\n            int startHintSp = bufPos + 1;\n            if (ch == '!' //\n                    || ch == '+' // oceanbase hints\n\n                    || ((ch == 'T' && //TDDL hint\n                    charAt(pos + 1) == 'D' //\n                    && charAt(pos + 2) == 'D' //\n                    && charAt(pos + 3) == 'L')\n                    && isEnabled(SQLParserFeature.TDDLHint))\n            ) {\n                isHint = true;\n                scanChar();\n                bufPos++;\n            }\n\n            int starIndex = pos;\n\n            // Dealing with nesting hint.\n            int depth = 1;\n            while (true) {\n                char ch = charAt(starIndex);\n                if (ch == '/' && charAt(starIndex + 1) == '*') {\n                    starIndex += 2;\n                    ch = charAt(starIndex);\n                    if (ch == '!' || ch == '+') {\n                        ++depth;\n                        ++starIndex;\n                        continue;\n                    }\n                } else if (ch == '*' && charAt(starIndex + 1) == '/') {\n                    if (0 == --depth) {\n                        break;\n                    }\n                    starIndex += 2;\n                    continue;\n                }\n\n                if (ch == EOI) {\n                    this.token = Token.ERROR;\n                    return;\n                }\n                ++starIndex;\n            }\n\n            if (isHint) {\n                stringVal = this.subString(mark + startHintSp, starIndex - startHintSp - mark);\n                token = Token.HINT;\n            } else {\n                if (!optimizedForParameterized) {\n                    stringVal = this.subString(mark, starIndex + 2 - mark);\n                }\n                token = Token.MULTI_LINE_COMMENT;\n                commentCount++;\n                if (keepComments) {\n                    stringVal = this.subString(mark, starIndex + 2 - mark);\n                    addComment(stringVal);\n                }\n            }\n            pos = starIndex + 2;\n            ch = charAt(pos);\n\n            endOfComment = isEOF();\n\n            if (commentHandler != null\n                    && commentHandler.handle(lastToken, stringVal)) {\n                return;\n            }\n\n            if (!isHint && !isAllowComment() && !isSafeComment(stringVal)) {\n                throw new NotAllowCommentException();\n            }\n\n            return;\n        }\n\n        if (ch == '!' && isEnabled(SQLParserFeature.TDDLHint)) { // TDDL HINT\n            scanChar();\n            bufPos++;\n\n            while (ch == ' ') {\n                scanChar();\n                bufPos++;\n            }\n\n            int startHintSp = bufPos + 1;\n\n            int starIndex = pos;\n\n            for (; ; ) {\n                starIndex = text.indexOf('*', starIndex);\n                if (starIndex == -1 || starIndex == text.length() - 1) {\n                    this.token = Token.ERROR;\n                    return;\n                }\n                if (charAt(starIndex + 1) == '/') {\n                    stringVal = this.subString(mark + startHintSp, starIndex - startHintSp - mark);\n                    token = Token.HINT;\n                    pos = starIndex + 2;\n                    ch = charAt(pos);\n                    break;\n                }\n                starIndex++;\n            }\n\n            endOfComment = isEOF();\n\n            if (commentHandler != null\n                    && commentHandler.handle(lastToken, stringVal)) {\n                return;\n            }\n\n            if (!isAllowComment() && !isSafeComment(stringVal)) {\n                throw new NotAllowCommentException();\n            }\n\n            return;\n        }\n\n        if (ch == '/' || ch == '-') {\n            bufPos++;\n            scanChar();\n\n            for (; ; ) {\n                if (ch == '\\r') {\n                    bufPos++;\n                    scanChar();\n                    if (ch == '\\n') {\n                        scanChar();\n                    }\n                    break;\n                } else if (ch == EOI) {\n                    bufPos++;\n                    break;\n                }\n\n                if (ch == '\\n') {\n                    bufPos++;\n                    scanChar();\n                    break;\n                }\n\n                bufPos++;\n                scanChar();\n            }\n\n            stringVal = subString(mark, bufPos);\n            token = Token.LINE_COMMENT;\n            commentCount++;\n            if (keepComments) {\n                addComment(stringVal);\n            }\n\n            if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {\n                return;\n            }\n\n            endOfComment = isEOF();\n\n            if (!isAllowComment() && (endOfComment || !isSafeComment(stringVal))) {\n                throw new NotAllowCommentException();\n            }\n\n            return;\n        }\n    }\n\n    private static final boolean[] identifierFlags = new boolean[256];\n\n    static {\n        for (char c = 0; c < identifierFlags.length; ++c) {\n            if (c >= 'A' && c <= 'Z') {\n                identifierFlags[c] = true;\n            } else if (c >= 'a' && c <= 'z') {\n                identifierFlags[c] = true;\n            } else if (c >= '0' && c <= '9') {\n                identifierFlags[c] = true;\n            }\n        }\n        // identifierFlags['`'] = true;\n        identifierFlags['_'] = true;\n        identifierFlags['$'] = true;\n        //identifierFlags['-'] = true; // mysql\n    }\n\n    public static boolean isIdentifierChar(char c) {\n        if (c < identifierFlags.length) {\n            return identifierFlags[c];\n        }\n        return c != '　' && c != '，';\n    }\n\n    /**\n     * employee.code=:employee.code 解析异常\n     * 修复:变量名支持含符号.\n     *\n     * @param c the character to check\n     * @return true if the character is a valid identifier character for variables; otherwise false\n     */\n    public static boolean isIdentifierCharForVariable(char c) {\n        if (c == '.') {\n            return true;\n        }\n        return isIdentifierChar(c);\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = MYSQL_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author zz [455910092@qq.com]\n */\npublic class MySqlSelectIntoParser extends SQLSelectParser {\n    private List<SQLExpr> argsList;\n\n    public MySqlSelectIntoParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public MySqlSelectIntoParser(String sql) {\n        this(new MySqlExprParser(sql));\n    }\n\n    public MySqlSelectIntoStatement parseSelectInto() {\n        SQLSelect select = select();\n        MySqlSelectIntoStatement stmt = new MySqlSelectIntoStatement();\n        stmt.setSelect(select);\n        stmt.setVarList(argsList);\n        return stmt;\n\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == (Token.LPAREN)) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            accept(Token.RPAREN);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock();\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.HINT) {\n                this.exprParser.parseHints(queryBlock.getHints());\n            }\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == (Token.DISTINCT)) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"DISTINCTROW\")) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCTROW);\n                lexer.nextToken();\n            } else if (lexer.token() == (Token.ALL)) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"HIGH_PRIORITY\")) {\n                queryBlock.setHignPriority(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"STRAIGHT_JOIN\")) {\n                queryBlock.setStraightJoin(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"SQL_SMALL_RESULT\")) {\n                queryBlock.setSmallResult(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"SQL_BIG_RESULT\")) {\n                queryBlock.setBigResult(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"SQL_BUFFER_RESULT\")) {\n                queryBlock.setBufferResult(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"SQL_CACHE\")) {\n                queryBlock.setCache(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"SQL_NO_CACHE\")) {\n                queryBlock.setCache(false);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"SQL_CALC_FOUND_ROWS\")) {\n                queryBlock.setCalcFoundRows(true);\n                lexer.nextToken();\n            }\n\n            parseSelectList(queryBlock);\n\n            argsList = parseIntoArgs();\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        queryBlock.setOrderBy(this.exprParser.parseOrderBy());\n\n        if (lexer.token() == Token.LIMIT) {\n            queryBlock.setLimit(this.exprParser.parseLimit());\n        }\n\n        if (lexer.token() == Token.PROCEDURE) {\n            lexer.nextToken();\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        parseInto(queryBlock);\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n            accept(Token.UPDATE);\n\n            queryBlock.setForUpdate(true);\n        }\n\n        if (lexer.token() == Token.LOCK) {\n            lexer.nextToken();\n            accept(Token.IN);\n            acceptIdentifier(\"SHARE\");\n            acceptIdentifier(\"MODE\");\n            queryBlock.setLockInShareMode(true);\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    /**\n     * Parses the arguments for the INTO clause and returns a list of SQL expressions.\n     *\n     * @return a list of SQL expressions representing the arguments passed to the INTO clause\n     */\n    protected List<SQLExpr> parseIntoArgs() {\n        List<SQLExpr> args = new ArrayList<SQLExpr>();\n        if (lexer.token() == (Token.INTO)) {\n            accept(Token.INTO);\n            //lexer.nextToken();\n            for (; ; ) {\n                SQLExpr var = exprParser.primary();\n                if (var instanceof SQLIdentifierExpr) {\n                    var = new SQLVariantRefExpr(\n                            ((SQLIdentifierExpr) var).getName());\n                }\n                args.add(var);\n                if (lexer.token() == Token.COMMA) {\n                    accept(Token.COMMA);\n                    continue;\n                } else {\n                    break;\n                }\n            }\n        }\n        return args;\n    }\n\n    protected void parseInto(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token() == (Token.INTO)) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"OUTFILE\")) {\n                lexer.nextToken();\n\n                MySqlOutFileExpr outFile = new MySqlOutFileExpr();\n                outFile.setFile(expr());\n\n                queryBlock.setInto(outFile);\n\n                if (lexer.identifierEquals(\"FIELDS\") || lexer.identifierEquals(\"COLUMNS\")) {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(\"TERMINATED\")) {\n                        lexer.nextToken();\n                        accept(Token.BY);\n                    }\n                    outFile.setColumnsTerminatedBy((SQLLiteralExpr) expr());\n\n                    if (lexer.identifierEquals(\"OPTIONALLY\")) {\n                        lexer.nextToken();\n                        outFile.setColumnsEnclosedOptionally(true);\n                    }\n\n                    if (lexer.identifierEquals(\"ENCLOSED\")) {\n                        lexer.nextToken();\n                        accept(Token.BY);\n                        outFile.setColumnsEnclosedBy((SQLLiteralExpr) expr());\n                    }\n\n                    if (lexer.identifierEquals(\"ESCAPED\")) {\n                        lexer.nextToken();\n                        accept(Token.BY);\n                        outFile.setColumnsEscaped((SQLLiteralExpr) expr());\n                    }\n                }\n\n                if (lexer.identifierEquals(\"LINES\")) {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(\"STARTING\")) {\n                        lexer.nextToken();\n                        accept(Token.BY);\n                        outFile.setLinesStartingBy((SQLLiteralExpr) expr());\n                    } else {\n                        lexer.identifierEquals(\"TERMINATED\");\n                        lexer.nextToken();\n                        accept(Token.BY);\n                        outFile.setLinesTerminatedBy((SQLLiteralExpr) expr());\n                    }\n                }\n            } else {\n                queryBlock.setInto(this.exprParser.name());\n            }\n        }\n    }\n\n    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {\n        if (lexer.identifierEquals(\"USING\")) {\n            return tableSource;\n        }\n\n        parseIndexHintList(tableSource);\n\n        return super.parseTableSourceRest(tableSource);\n    }\n\n    private void parseIndexHintList(SQLTableSource tableSource) {\n        if (lexer.token() == Token.USE) {\n            lexer.nextToken();\n            MySqlUseIndexHint hint = new MySqlUseIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n            parseIndexHintList(tableSource);\n        }\n\n        if (lexer.identifierEquals(\"IGNORE\")) {\n            lexer.nextToken();\n            MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n            parseIndexHintList(tableSource);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n            MySqlForceIndexHint hint = new MySqlForceIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n            parseIndexHintList(tableSource);\n        }\n    }\n\n    private void parseIndexHint(MySqlIndexHintImpl hint) {\n        if (lexer.token() == Token.INDEX) {\n            lexer.nextToken();\n        } else {\n            accept(Token.KEY);\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.JOIN) {\n                lexer.nextToken();\n                hint.setOption(MySqlIndexHint.Option.JOIN);\n            } else if (lexer.token() == Token.ORDER) {\n                lexer.nextToken();\n                accept(Token.BY);\n                hint.setOption(MySqlIndexHint.Option.ORDER_BY);\n            } else {\n                accept(Token.GROUP);\n                accept(Token.BY);\n                hint.setOption(MySqlIndexHint.Option.GROUP_BY);\n            }\n        }\n\n        accept(Token.LPAREN);\n        if (lexer.token() == Token.PRIMARY) {\n            lexer.nextToken();\n            hint.getIndexList().add(new SQLIdentifierExpr(\"PRIMARY\"));\n        } else {\n            this.exprParser.names(hint.getIndexList());\n        }\n        accept(Token.RPAREN);\n    }\n\n    public SQLUnionQuery unionRest(SQLUnionQuery union) {\n        if (lexer.token() == Token.LIMIT) {\n            union.setLimit(this.exprParser.parseLimit());\n        }\n        return super.unionRest(union);\n    }\n\n    public MySqlExprParser getExprParser() {\n        return (MySqlExprParser) exprParser;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateTableSource;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlSelectParser extends SQLSelectParser {\n    protected boolean returningFlag;\n    protected MySqlUpdateStatement updateStmt;\n\n    public MySqlSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public MySqlSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public MySqlSelectParser(String sql) {\n        this(new MySqlExprParser(sql));\n    }\n\n    public void parseFrom(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token() == Token.EOF\n                || lexer.token() == Token.SEMI\n                || lexer.token() == Token.ORDER\n                || lexer.token() == Token.RPAREN\n                || lexer.token() == Token.UNION\n        ) {\n            return;\n        }\n\n        if (lexer.token() != Token.FROM) {\n            for (SQLSelectItem item : queryBlock.getSelectList()) {\n                SQLExpr expr = item.getExpr();\n                if (expr instanceof SQLAggregateExpr) {\n                    throw new ParserException(\"syntax error, expect \" + Token.FROM + \", actual \" + lexer.token() + \", \" + lexer.info());\n                }\n            }\n            return;\n        }\n\n        lexer.nextTokenIdent();\n\n        if (lexer.hasComment()) {\n            queryBlock.setCommentsAfterFrom(lexer.readAndResetComments());\n        }\n        while (lexer.token() == Token.HINT) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.UPDATE) { // taobao returning to urgly syntax\n            updateStmt = this.parseUpdateStatment();\n            List<SQLExpr> returnning = updateStmt.getReturning();\n            for (SQLSelectItem item : queryBlock.getSelectList()) {\n                SQLExpr itemExpr = item.getExpr();\n                itemExpr.setParent(updateStmt);\n                returnning.add(itemExpr);\n            }\n            returningFlag = true;\n            return;\n        }\n\n        SQLTableSource from = parseTableSource(queryBlock);\n        queryBlock.setFrom(from);\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        List<SQLCommentHint> hints = null;\n        if (lexer.token() == Token.HINT) {\n            hints = this.exprParser.parseHints();\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            select.setParenthesized(true);\n            accept(Token.RPAREN);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        if (lexer.token() == Token.VALUES) {\n            return valuesQuery(acceptUnion);\n        }\n\n        MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock();\n        queryBlock.setParent(parent);\n\n        class QueryHintHandler implements Lexer.CommentHandler {\n            private MySqlSelectQueryBlock queryBlock;\n            private Lexer lexer;\n\n            QueryHintHandler(MySqlSelectQueryBlock queryBlock, Lexer lexer) {\n                this.queryBlock = queryBlock;\n                this.lexer = lexer;\n            }\n\n            @Override\n            public boolean handle(Token lastToken, String comment) {\n                if (lexer.isEnabled(SQLParserFeature.TDDLHint)\n                        && (comment.startsWith(\"+ TDDL\")\n                        || comment.startsWith(\"+TDDL\")\n                        || comment.startsWith(\"!TDDL\")\n                        || comment.startsWith(\"TDDL\"))) {\n                    SQLCommentHint hint = new TDDLHint(comment);\n\n                    if (lexer.getCommentCount() > 0) {\n                        hint.addBeforeComment(lexer.getComments());\n                    }\n\n                    queryBlock.getHints().add(hint);\n\n                    lexer.nextToken();\n                }\n                return false;\n            }\n        }\n\n        this.lexer.setCommentHandler(new QueryHintHandler(queryBlock, this.lexer));\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            if (selectListCache != null) {\n                selectListCache.match(lexer, queryBlock);\n            }\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextTokenValue();\n\n            for (; ; ) {\n                if (lexer.token() == Token.HINT) {\n                    this.exprParser.parseHints(queryBlock.getHints());\n                } else {\n                    break;\n                }\n            }\n\n            while (true) {\n                Token token = lexer.token();\n                if (token == (Token.DISTINCT)) {\n                    queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.DISTINCTROW)) {\n                    queryBlock.setDistionOption(SQLSetQuantifier.DISTINCTROW);\n                    lexer.nextToken();\n                } else if (token == (Token.ALL)) {\n                    queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                    lexer.nextToken();\n                } else if (token == (Token.UNIQUE)) {\n                    queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.HIGH_PRIORITY)) {\n                    queryBlock.setHignPriority(true);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.STRAIGHT_JOIN)) {\n                    queryBlock.setStraightJoin(true);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.SQL_SMALL_RESULT)) {\n                    queryBlock.setSmallResult(true);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.SQL_BIG_RESULT)) {\n                    queryBlock.setBigResult(true);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.SQL_BUFFER_RESULT)) {\n                    queryBlock.setBufferResult(true);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.SQL_CACHE)) {\n                    queryBlock.setCache(true);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.SQL_NO_CACHE)) {\n                    queryBlock.setCache(false);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.SQL_CALC_FOUND_ROWS)) {\n                    queryBlock.setCalcFoundRows(true);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.TOP)) {\n                    Lexer.SavePoint mark = lexer.mark();\n\n                    lexer.nextToken();\n                    if (lexer.token() == Token.LITERAL_INT) {\n                        SQLLimit limit = new SQLLimit(lexer.integerValue().intValue());\n                        queryBlock.setLimit(limit);\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.DOT) {\n                        lexer.reset(mark);\n                        break;\n                    }\n                } else {\n                    break;\n                }\n            }\n\n            parseSelectList(queryBlock);\n\n            if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n                lexer.nextToken();\n                accept(Token.PARTITION);\n                SQLName partition = this.exprParser.name();\n                queryBlock.setForcePartition(partition);\n            }\n\n            parseInto(queryBlock);\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseHierachical(queryBlock);\n\n        if (lexer.token() == Token.GROUP || lexer.token() == Token.HAVING) {\n            parseGroupBy(queryBlock);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WINDOW)) {\n            parseWindow(queryBlock);\n        }\n\n        if (lexer.token() == Token.ORDER) {\n            queryBlock.setOrderBy(this.exprParser.parseOrderBy());\n        }\n\n        if (lexer.token() == Token.LIMIT) {\n            queryBlock.setLimit(this.exprParser.parseLimit());\n        }\n\n        if (lexer.token() == Token.FETCH) {\n            final Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.NEXT)) {\n                lexer.nextToken();\n                SQLExpr rows = this.exprParser.primary();\n                queryBlock.setLimit(\n                        new SQLLimit(rows));\n                acceptIdentifier(\"ROWS\");\n                acceptIdentifier(\"ONLY\");\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        if (lexer.token() == Token.PROCEDURE) {\n            lexer.nextToken();\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        if (lexer.token() == Token.INTO) {\n            parseInto(queryBlock);\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.UPDATE) {\n                lexer.nextToken();\n                queryBlock.setForUpdate(true);\n\n                if (lexer.identifierEquals(FnvHash.Constants.NO_WAIT)\n                        || lexer.identifierEquals(FnvHash.Constants.NOWAIT)) {\n                    lexer.nextToken();\n                    queryBlock.setNoWait(true);\n                } else if (lexer.identifierEquals(FnvHash.Constants.WAIT)) {\n                    lexer.nextToken();\n                    SQLExpr waitTime = this.exprParser.primary();\n                    queryBlock.setWaitTime(waitTime);\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.SKIP)) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"LOCKED\");\n                    queryBlock.setSkipLocked(true);\n                }\n            } else {\n                acceptIdentifier(\"SHARE\");\n                queryBlock.setForShare(true);\n            }\n        }\n\n        if (lexer.token() == Token.LOCK) {\n            lexer.nextToken();\n            accept(Token.IN);\n            acceptIdentifier(\"SHARE\");\n            acceptIdentifier(\"MODE\");\n            queryBlock.setLockInShareMode(true);\n        }\n\n        if (hints != null) {\n            queryBlock.setHints(hints);\n        }\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addAfterComment(lexer.readAndResetComments());\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    public SQLTableSource parseTableSource() {\n        return parseTableSource(null);\n    }\n\n    public SQLTableSource parseTableSource(SQLObject parent) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            List hints = null;\n            if (lexer.token() == Token.HINT) {\n                hints = new ArrayList();\n                this.exprParser.parseHints(hints);\n            }\n\n            SQLTableSource tableSource;\n            if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH) {\n                SQLSelect select = select();\n\n                accept(Token.RPAREN);\n\n                SQLSelectQueryBlock innerQuery = select.getQueryBlock();\n\n                boolean noOrderByAndLimit = innerQuery instanceof SQLSelectQueryBlock\n                        && ((SQLSelectQueryBlock) innerQuery).getOrderBy() == null\n                        && ((SQLSelectQueryBlock) select.getQuery()).getLimit() == null;\n\n                if (lexer.token() == Token.LIMIT) {\n                    SQLLimit limit = this.exprParser.parseLimit();\n                    if (parent != null && parent instanceof SQLSelectQueryBlock) {\n                        ((SQLSelectQueryBlock) parent).setLimit(limit);\n                    }\n                    if (parent == null && noOrderByAndLimit) {\n                        innerQuery.setLimit(limit);\n                    }\n                } else if (lexer.token() == Token.ORDER) {\n                    SQLOrderBy orderBy = this.exprParser.parseOrderBy();\n                    if (parent != null && parent instanceof SQLSelectQueryBlock) {\n                        ((SQLSelectQueryBlock) parent).setOrderBy(orderBy);\n                    }\n                    if (parent == null && noOrderByAndLimit) {\n                        innerQuery.setOrderBy(orderBy);\n                    }\n                }\n\n                SQLSelectQuery query = queryRest(select.getQuery(), false);\n                if (query instanceof SQLUnionQuery && select.getWithSubQuery() == null) {\n                    select.getQuery().setParenthesized(true);\n                    tableSource = new SQLUnionQueryTableSource((SQLUnionQuery) query);\n                } else {\n                    tableSource = SQLSubqueryTableSource.fixParenthesized(new SQLSubqueryTableSource(select));\n                }\n\n                if (hints != null) {\n                    tableSource.getHints().addAll(hints);\n                }\n\n            } else if (lexer.token() == Token.LPAREN) {\n                tableSource = parseTableSource();\n                if (lexer.token() != Token.RPAREN && tableSource instanceof SQLSubqueryTableSource) {\n                    SQLSubqueryTableSource sqlSubqueryTableSource = (SQLSubqueryTableSource) tableSource;\n                    SQLSelect select = sqlSubqueryTableSource.getSelect();\n\n                    SQLSelectQuery query = queryRest(select.getQuery(), true);\n                    if (query instanceof SQLUnionQuery && select.getWithSubQuery() == null) {\n                        select.getQuery().setParenthesized(true);\n                        tableSource = new SQLUnionQueryTableSource((SQLUnionQuery) query);\n                    } else {\n                        tableSource = SQLSubqueryTableSource.fixParenthesized(new SQLSubqueryTableSource(select));\n                    }\n\n                    if (hints != null) {\n                        tableSource.getHints().addAll(hints);\n                    }\n                } else if (lexer.token() != Token.RPAREN && tableSource instanceof SQLUnionQueryTableSource) {\n                    SQLUnionQueryTableSource unionQueryTableSource = (SQLUnionQueryTableSource) tableSource;\n                    SQLUnionQuery unionQuery = unionQueryTableSource.getUnion();\n\n                    SQLSelectQuery query = queryRest(unionQuery, true);\n                    if (query instanceof SQLUnionQuery) {\n                        unionQuery.setParenthesized(true);\n                        tableSource = new SQLUnionQueryTableSource((SQLUnionQuery) query);\n                    } else {\n                        tableSource = SQLSubqueryTableSource.fixParenthesized(new SQLSubqueryTableSource(unionQuery));\n                    }\n\n                    if (hints != null) {\n                        tableSource.getHints().addAll(hints);\n                    }\n                }\n                accept(Token.RPAREN);\n            } else {\n                tableSource = parseTableSource();\n                accept(Token.RPAREN);\n                if (lexer.token() == Token.AS\n                        && tableSource instanceof SQLValuesTableSource) {\n                    lexer.nextToken();\n                    String alias = lexer.stringVal();\n                    lexer.nextToken();\n                    tableSource.setAlias(alias);\n                    accept(Token.LPAREN);\n                    SQLValuesTableSource values = (SQLValuesTableSource) tableSource;\n                    this.exprParser.names(values.getColumns(), tableSource);\n                    accept(Token.RPAREN);\n                }\n            }\n\n            return parseTableSourceRest(tableSource);\n        } else if (lexer.token() == Token.LBRACE) {\n            accept(Token.LBRACE);\n            acceptIdentifier(\"OJ\");\n\n            SQLTableSource tableSrc = parseTableSource();\n\n            accept(Token.RBRACE);\n\n            tableSrc = parseTableSourceRest(tableSrc);\n\n            if (lexer.hasComment() && lexer.isKeepComments()) {\n                tableSrc.addAfterComment(lexer.readAndResetComments());\n            }\n\n            return tableSrc;\n        }\n\n        if (lexer.token() == Token.VALUES) {\n            return parseValues();\n        }\n\n        if (lexer.token() == Token.UPDATE) {\n            SQLTableSource tableSource = new MySqlUpdateTableSource(parseUpdateStatment());\n            return parseTableSourceRest(tableSource);\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        SQLTableSource unnestTableSource = parseUnnestTableSource();\n        if (unnestTableSource != null) {\n            SQLTableSource tableSrc = parseTableSourceRest(unnestTableSource);\n            return tableSrc;\n        }\n\n        SQLExprTableSource tableReference = new SQLExprTableSource();\n\n        parseTableSourceQueryTableExpr(tableReference);\n\n        SQLTableSource tableSrc = parseTableSourceRest(tableReference);\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            tableSrc.addAfterComment(lexer.readAndResetComments());\n        }\n\n        return tableSrc;\n    }\n\n    protected MySqlUpdateStatement parseUpdateStatment() {\n        MySqlUpdateStatement update = new MySqlUpdateStatement();\n\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {\n            lexer.nextToken();\n            update.setLowPriority(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            lexer.nextToken();\n            update.setIgnore(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COMMIT_ON_SUCCESS)) {\n            lexer.nextToken();\n            update.setCommitOnSuccess(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ROLLBACK_ON_FAIL)) {\n            lexer.nextToken();\n            update.setRollBackOnFail(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.QUEUE_ON_PK)) {\n            lexer.nextToken();\n            update.setQueryOnPk(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TARGET_AFFECT_ROW)) {\n            lexer.nextToken();\n            SQLExpr targetAffectRow = this.exprParser.expr();\n            update.setTargetAffectRow(targetAffectRow);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.ALL) {\n                lexer.nextToken();\n                acceptIdentifier(\"PARTITIONS\");\n                update.setForceAllPartitions(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n                lexer.nextToken();\n                update.setForceAllPartitions(true);\n            } else if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                SQLName partition = this.exprParser.name();\n                update.setForcePartition(partition);\n            } else {\n                throw new ParserException(\"TODO. \" + lexer.info());\n            }\n        }\n\n        while (lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(update.getHints());\n        }\n\n        SQLSelectParser selectParser = this.exprParser.createSelectParser();\n        SQLTableSource updateTableSource = selectParser.parseTableSource();\n        update.setTableSource(updateTableSource);\n\n        accept(Token.SET);\n\n        for (; ; ) {\n            SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n            update.addItem(item);\n\n            if (lexer.token() != Token.COMMA) {\n                break;\n            }\n\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            update.setWhere(this.exprParser.expr());\n        }\n\n        update.setOrderBy(this.exprParser.parseOrderBy());\n        update.setLimit(this.exprParser.parseLimit());\n\n        return update;\n    }\n\n    protected void parseInto(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token() != Token.INTO) {\n            return;\n        }\n\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.OUTFILE)) {\n            lexer.nextToken();\n\n            MySqlOutFileExpr outFile = new MySqlOutFileExpr();\n            outFile.setFile(expr());\n\n            queryBlock.setInto(outFile);\n\n            if (lexer.identifierEquals(FnvHash.Constants.FIELDS) || lexer.identifierEquals(FnvHash.Constants.COLUMNS)) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.TERMINATED)) {\n                    lexer.nextToken();\n                    accept(Token.BY);\n                }\n                outFile.setColumnsTerminatedBy(expr());\n\n                if (lexer.identifierEquals(FnvHash.Constants.OPTIONALLY)) {\n                    lexer.nextToken();\n                    outFile.setColumnsEnclosedOptionally(true);\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.ENCLOSED)) {\n                    lexer.nextToken();\n                    accept(Token.BY);\n                    outFile.setColumnsEnclosedBy((SQLLiteralExpr) expr());\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.ESCAPED)) {\n                    lexer.nextToken();\n                    accept(Token.BY);\n                    outFile.setColumnsEscaped((SQLLiteralExpr) expr());\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LINES)) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.STARTING)) {\n                    lexer.nextToken();\n                    accept(Token.BY);\n                    outFile.setLinesStartingBy((SQLLiteralExpr) expr());\n                } else {\n                    if (lexer.identifierEquals(FnvHash.Constants.TERMINATED)) {\n                        lexer.nextToken();\n                    }\n                    accept(Token.BY);\n                    outFile.setLinesTerminatedBy((SQLLiteralExpr) expr());\n                }\n            }\n        } else {\n            SQLExpr expr = this.expr();\n            if (lexer.token() != Token.COMMA) {\n                queryBlock.setInto(expr);\n                return;\n            }\n            SQLListExpr list = new SQLListExpr();\n            list.addItem(expr);\n            while (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                list.addItem(expr());\n            }\n            queryBlock.setInto(list);\n        }\n    }\n\n    protected SQLTableSource primaryTableSourceRest(SQLTableSource tableSource) {\n        if (lexer.token() == Token.USE) {\n            lexer.nextToken();\n            MySqlUseIndexHint hint = new MySqlUseIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            lexer.nextToken();\n            MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n            MySqlForceIndexHint hint = new MySqlForceIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            // 兼容jsqlparser 和presto\n            if (lexer.token() == Token.ON) {\n                tableSource.setAlias(\"partition\");\n            } else {\n                accept(Token.LPAREN);\n                this.exprParser.names(((SQLExprTableSource) tableSource).getPartitions(), tableSource);\n                accept(Token.RPAREN);\n            }\n        }\n\n        return tableSource;\n    }\n\n    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {\n        if (lexer.identifierEquals(FnvHash.Constants.TABLESAMPLE) && tableSource instanceof SQLExprTableSource) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n\n            SQLTableSampling sampling = new SQLTableSampling();\n\n            if (lexer.identifierEquals(FnvHash.Constants.BERNOULLI)) {\n                lexer.nextToken();\n                sampling.setBernoulli(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SYSTEM)) {\n                lexer.nextToken();\n                sampling.setSystem(true);\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.BUCKET)) {\n                    lexer.nextToken();\n                    SQLExpr bucket = this.exprParser.primary();\n                    sampling.setBucket(bucket);\n\n                    if (lexer.token() == Token.OUT) {\n                        lexer.nextToken();\n                        accept(Token.OF);\n                        SQLExpr outOf = this.exprParser.primary();\n                        sampling.setOutOf(outOf);\n                    }\n\n                    if (lexer.token() == Token.ON) {\n                        lexer.nextToken();\n                        SQLExpr on = this.exprParser.expr();\n                        sampling.setOn(on);\n                    }\n                }\n\n                if (lexer.token() == Token.LITERAL_INT || lexer.token() == Token.LITERAL_FLOAT) {\n                    SQLExpr val = this.exprParser.primary();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                        lexer.nextToken();\n                        sampling.setRows(val);\n                    } else if (lexer.token() == Token.RPAREN) {\n                        sampling.setRows(val);\n                    } else {\n                        acceptIdentifier(\"PERCENT\");\n                        sampling.setPercent(val);\n                    }\n                }\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    String strVal = lexer.stringVal();\n                    char first = strVal.charAt(0);\n                    char last = strVal.charAt(strVal.length() - 1);\n                    if (last >= 'a' && last <= 'z') {\n                        last -= 32; // to upper\n                    }\n\n                    boolean match = false;\n                    if ((first == '.' || (first >= '0' && first <= '9'))) {\n                        switch (last) {\n                            case 'B':\n                            case 'K':\n                            case 'M':\n                            case 'G':\n                            case 'T':\n                            case 'P':\n                                match = true;\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n                    SQLSizeExpr size = new SQLSizeExpr(strVal.substring(0, strVal.length() - 2), last);\n                    sampling.setByteLength(size);\n                    lexer.nextToken();\n                }\n\n                final SQLExprTableSource table = (SQLExprTableSource) tableSource;\n                table.setSampling(sampling);\n\n                accept(Token.RPAREN);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n            return tableSource;\n        }\n\n        parseIndexHintList(tableSource);\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            this.exprParser.names(((SQLExprTableSource) tableSource).getPartitions(), tableSource);\n            accept(Token.RPAREN);\n        }\n\n        return super.parseTableSourceRest(tableSource);\n    }\n\n    @Override\n    protected SQLTableSource parseLateralView(SQLTableSource tableSource) {\n        if (tableSource != null && \"LATERAL\".equalsIgnoreCase(tableSource.getAlias())) {\n            tableSource.setAlias(null);\n        }\n\n        if (lexer.token() == Token.VIEW) {\n            return super.parseLateralView(tableSource);\n        }\n\n        // MySQL 8.0.14+ LATERAL derived table: LATERAL (SELECT ...)\n        SQLTableSource lateralSource = parseLateralTableSource();\n\n        SQLJoinTableSource join = new SQLJoinTableSource();\n        join.setLeft(tableSource);\n        join.setRight(lateralSource);\n        join.setJoinType(SQLJoinTableSource.JoinType.COMMA);\n        return parseTableSourceRest(join);\n    }\n\n    private void parseIndexHintList(SQLTableSource tableSource) {\n        if (lexer.token() == Token.USE) {\n            lexer.nextToken();\n            MySqlUseIndexHint hint = new MySqlUseIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n            parseIndexHintList(tableSource);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            lexer.nextToken();\n            MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n            parseIndexHintList(tableSource);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n            MySqlForceIndexHint hint = new MySqlForceIndexHint();\n            parseIndexHint(hint);\n            tableSource.getHints().add(hint);\n            parseIndexHintList(tableSource);\n        }\n    }\n\n    private void parseIndexHint(MySqlIndexHintImpl hint) {\n        if (lexer.token() == Token.INDEX) {\n            lexer.nextToken();\n        } else {\n            accept(Token.KEY);\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.JOIN) {\n                lexer.nextToken();\n                hint.setOption(MySqlIndexHint.Option.JOIN);\n            } else if (lexer.token() == Token.ORDER) {\n                lexer.nextToken();\n                accept(Token.BY);\n                hint.setOption(MySqlIndexHint.Option.ORDER_BY);\n            } else {\n                accept(Token.GROUP);\n                accept(Token.BY);\n                hint.setOption(MySqlIndexHint.Option.GROUP_BY);\n            }\n        }\n\n        accept(Token.LPAREN);\n        while (lexer.token() != Token.RPAREN && lexer.token() != Token.EOF) {\n            if (lexer.token() == Token.PRIMARY) {\n                lexer.nextToken();\n                hint.getIndexList().add(new SQLIdentifierExpr(\"PRIMARY\"));\n            } else {\n                SQLName name = this.exprParser.name();\n                name.setParent(hint);\n                hint.getIndexList().add(name);\n            }\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n            } else {\n                break;\n            }\n        }\n        accept(Token.RPAREN);\n    }\n\n    public SQLUnionQuery unionRest(SQLUnionQuery union) {\n        if (lexer.token() == Token.LIMIT) {\n            union.setLimit(this.exprParser.parseLimit());\n        }\n        return super.unionRest(union);\n    }\n\n    public MySqlExprParser getExprParser() {\n        return (MySqlExprParser) exprParser;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.ConditionValue.ConditionType;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement.LockType;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.sql.repository.SchemaObject;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.*;\nimport static com.alibaba.druid.sql.parser.Token.ALTER;\nimport static com.alibaba.druid.sql.parser.Token.FALSE;\nimport static com.alibaba.druid.sql.parser.Token.GROUP;\nimport static com.alibaba.druid.sql.parser.Token.INDEX;\nimport static com.alibaba.druid.sql.parser.Token.SEMI;\nimport static com.alibaba.druid.sql.parser.Token.TABLE;\nimport static com.alibaba.druid.sql.parser.Token.TRUE;\nimport static com.alibaba.druid.sql.parser.Token.WITH;\nimport static com.alibaba.druid.util.FnvHash.Constants.*;\n\npublic class MySqlStatementParser extends SQLStatementParser {\n    private static final String AUTO_INCREMENT = \"AUTO_INCREMENT\";\n    private static final String AVG_ROW_LENGTH = \"AVG_ROW_LENGTH\";\n    private static final String CHECKSUM2 = \"CHECKSUM\";\n    private static final String DELAY_KEY_WRITE = \"DELAY_KEY_WRITE\";\n    private static final String ENCRYPTION2 = \"ENCRYPTION\";\n    private static final String INSERT_METHOD = \"INSERT_METHOD\";\n    private static final String KEY_BLOCK_SIZE2 = \"KEY_BLOCK_SIZE\";\n    private static final String MAX_ROWS2 = \"MAX_ROWS\";\n    private static final String MIN_ROWS2 = \"MIN_ROWS\";\n    private static final String PASSWORD2 = \"PASSWORD\";\n    private static final String STATS_AUTO_RECALC = \"STATS_AUTO_RECALC\";\n    private static final String STATS_PERSISTENT = \"STATS_PERSISTENT\";\n    private static final String STATS_SAMPLE_PAGES = \"STATS_SAMPLE_PAGES\";\n    private static final String TABLESPACE2 = \"TABLESPACE\";\n    private static final String CHAIN = \"CHAIN\";\n    private static final String ENGINES = \"ENGINES\";\n    private static final String ENGINE = \"ENGINE\";\n    private static final String BINLOG = \"BINLOG\";\n    private static final String EVENTS = \"EVENTS\";\n    private static final String GLOBAL = \"GLOBAL\";\n    private static final String VARIABLES = \"VARIABLES\";\n    private static final String STATUS = \"STATUS\";\n    private static final String DBLOCK = \"DBLOCK\";\n    private static final String RESET = \"RESET\";\n    private static final String DESCRIBE = \"DESCRIBE\";\n    private static final String WRITE = \"WRITE\";\n    private static final String READ = \"READ\";\n    private static final String LOCAL = \"LOCAL\";\n    private static final String TABLES = \"TABLES\";\n    private static final String CONNECTION = \"CONNECTION\";\n\n    private int maxIntoClause = -1;\n\n    public MySqlStatementParser(String sql) {\n        super(new MySqlExprParser(sql));\n    }\n\n    public MySqlStatementParser(String sql, SQLParserFeature... features) {\n        super(new MySqlExprParser(sql, features));\n    }\n\n    public MySqlStatementParser(String sql, boolean keepComments) {\n        super(new MySqlExprParser(sql, keepComments));\n    }\n\n    public MySqlStatementParser(String sql, boolean skipComment, boolean keepComments) {\n        super(new MySqlExprParser(sql, skipComment, keepComments));\n    }\n\n    public MySqlStatementParser(Lexer lexer) {\n        super(new MySqlExprParser(lexer));\n    }\n\n    public int getMaxIntoClause() {\n        return maxIntoClause;\n    }\n\n    public void setMaxIntoClause(int maxIntoClause) {\n        this.maxIntoClause = maxIntoClause;\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        MySqlCreateTableParser parser = new MySqlCreateTableParser(this.exprParser);\n        return parser.parseCreateTable();\n    }\n\n    public SQLStatement parseSelect() {\n        MySqlSelectParser selectParser = createSQLSelectParser();\n\n        SQLSelect select = selectParser.select();\n\n        if (selectParser.returningFlag) {\n            return selectParser.updateStmt;\n        }\n\n        return new SQLSelectStatement(select, DbType.mysql);\n    }\n\n    public SQLUpdateStatement parseUpdateStatement() {\n        return new MySqlSelectParser(this.exprParser, selectListCache).parseUpdateStatment();\n    }\n\n    protected MySqlUpdateStatement createUpdateStatement() {\n        return new MySqlUpdateStatement();\n    }\n\n    public MySqlDeleteStatement parseDeleteStatement() {\n        MySqlDeleteStatement deleteStatement = new MySqlDeleteStatement();\n\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            List<String> comments = lexer.readAndResetComments();\n\n            if (comments != null) {\n                deleteStatement.addBeforeComment(comments);\n            }\n        }\n\n        if (lexer.token() == Token.DELETE) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.HINT) {\n                this.getExprParser().parseHints(deleteStatement.getHints());\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {\n                deleteStatement.setLowPriority(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"QUICK\")) {\n                deleteStatement.setQuick(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n                deleteStatement.setIgnore(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n                Lexer.SavePoint savePoint = lexer.mark();\n                lexer.nextToken();\n\n                if (lexer.token() == Token.ALL) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"PARTITIONS\");\n                    deleteStatement.setForceAllPartitions(true);\n                } else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n                    lexer.nextToken();\n                    deleteStatement.setForceAllPartitions(true);\n                } else if (lexer.token() == Token.PARTITION) {\n                    lexer.nextToken();\n                    SQLName partition = this.exprParser.name();\n                    deleteStatement.setForcePartition(partition);\n                } else {\n                    lexer.reset(savePoint);\n                }\n            }\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                deleteStatement.setTableSource(createSQLSelectParser().parseTableSource());\n\n                if (lexer.token() == Token.FROM) {\n                    lexer.nextToken();\n                    SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n                    deleteStatement.setFrom(tableSource);\n                }\n            } else if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.FULLTEXT) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.DICTIONARY)) {\n                        lexer.nextToken();\n                        deleteStatement.setFulltextDictionary(true);\n                    }\n                }\n\n                deleteStatement.setTableSource(createSQLSelectParser().parseTableSource());\n            } else {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n                lexer.nextToken();\n\n                SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n                deleteStatement.setUsing(tableSource);\n            }\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            SQLExpr where = this.exprParser.expr();\n            deleteStatement.setWhere(where);\n        }\n\n        if (lexer.token() == (Token.ORDER)) {\n            SQLOrderBy orderBy = exprParser.parseOrderBy();\n            deleteStatement.setOrderBy(orderBy);\n        }\n\n        if (lexer.token() == Token.LIMIT) {\n            deleteStatement.setLimit(this.exprParser.parseLimit());\n        }\n\n        if (lexer.token() != Token.EOF && lexer.token() != SEMI) {\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n\n        return deleteStatement;\n    }\n\n    protected void createOptionSkip() {\n        super.createOptionSkip();\n\n        lexer.nextIf(HINT);\n\n        if (lexer.identifierEquals(FnvHash.Constants.PHYSICAL)) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == GROUP) {\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.SIMPLE)) {\n            lexer.nextToken();\n            if (lexer.token() == WITH) {\n                lexer.nextToken();\n                accept(Token.CACHE);\n            }\n        }\n    }\n\n    protected SQLStatement createTableRest(Lexer.SavePoint mark) {\n        if (lexer.identifierEquals(FnvHash.Constants.TIME)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.SEQUENCE) {\n                lexer.reset(mark);\n                return parseCreateSequence();\n            }\n        }\n\n        if (lexer.identifierEquals(ALGORITHM)) {\n            lexer.reset(mark);\n            return parseCreateView();\n        }\n\n        if (lexer.nextIfIdentifier(DEFINER)) {\n            accept(Token.EQ);\n            this.getExprParser().userName();\n\n            if (lexer.identifierEquals(FnvHash.Constants.SQL)) {\n                lexer.nextToken();\n                acceptIdentifier(\"SECURITY\");\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                lexer.nextToken();\n            }\n            if (lexer.identifierEquals(FnvHash.Constants.EVENT)) {\n                lexer.reset(mark);\n                return parseCreateEvent();\n            } else if (lexer.token() == Token.TRIGGER) {\n                lexer.reset(mark);\n                return parseCreateTrigger();\n            } else if (lexer.token() == Token.VIEW) {\n                lexer.reset(mark);\n                return parseCreateView();\n            } else if (lexer.token() == Token.FUNCTION) {\n                lexer.reset(mark);\n                return parseCreateFunction();\n            } else {\n                lexer.reset(mark);\n                return parseCreateProcedure();\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n            lexer.reset(mark);\n            return parseCreateIndex();\n        }\n\n        if (lexer.token() == Token.FULLTEXT) {\n            lexer.reset(mark);\n            return parseCreateFullTextStatement();\n        }\n\n        if (lexer.token() == Token.UNIQUE\n                || lexer.token() == INDEX\n                || lexer.identifierEquals(FnvHash.Constants.SPATIAL)\n                || lexer.identifierEquals(FnvHash.Constants.ANN)\n                || lexer.identifierEquals(FnvHash.Constants.GLOBAL)\n                || lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n            lexer.reset(mark);\n            return parseCreateIndex();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOGFILE)) {\n            lexer.reset(mark);\n            return parseCreateLogFileGroup();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DIMENSION) || lexer.identifierEquals(\"SHADOW\")) {\n            lexer.reset(mark);\n            return parseCreateTable();\n        }\n        return null;\n    }\n\n    public SQLStatement parseCreateFullTextStatement() {\n        Lexer.SavePoint mark = lexer.markOut();\n\n        accept(Token.CREATE);\n        accept(Token.FULLTEXT);\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARFILTER)) {\n            lexer.nextToken();\n            return parseFullTextCharFilter();\n        } else if (lexer.identifierEquals(FnvHash.Constants.TOKENIZER)) {\n            lexer.nextToken();\n            return parseFullTextTokenizer();\n        } else if (lexer.identifierEquals(FnvHash.Constants.TOKENFILTER)) {\n            lexer.nextToken();\n            return parseFullTextTokenFilter();\n        } else if (lexer.identifierEquals(FnvHash.Constants.ANALYZER)) {\n            lexer.nextToken();\n            return parseFullTextAnalyzer();\n        } else if (lexer.token() == INDEX) {\n            lexer.reset(mark);\n            return parseCreateIndex();\n        } else if (lexer.identifierEquals(FnvHash.Constants.DICTIONARY)) {\n            lexer.nextToken();\n            MysqlCreateFullTextDictionaryStatement stmt = new MysqlCreateFullTextDictionaryStatement();\n            SQLName name = this.exprParser.name();\n            stmt.setName(name);\n\n            accept(Token.LPAREN);\n\n            SQLColumnDefinition col = new SQLColumnDefinition();\n\n            col.setName(this.exprParser.name());\n\n            acceptIdentifier(\"varchar\");\n\n            col.setDataType(new SQLDataTypeImpl(\"varchar\"));\n\n            if (lexer.token() == Token.COMMENT) {\n                accept(Token.COMMENT);\n                col.setComment(this.exprParser.name());\n            }\n\n            stmt.setColumn(col);\n            accept(Token.RPAREN);\n\n            if (lexer.token() == Token.COMMENT) {\n                accept(Token.COMMENT);\n                stmt.setComment(this.exprParser.name().getSimpleName());\n            }\n            return stmt;\n        }\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    private SQLStatement parseFullTextAnalyzer() {\n        MysqlCreateFullTextAnalyzerStatement stmt = new MysqlCreateFullTextAnalyzerStatement();\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            String key = \"\";\n            if (lexer.token() == Token.LITERAL_ALIAS || lexer.token() == Token.LITERAL_CHARS) {\n                key = StringUtils.removeNameQuotes(lexer.stringVal());\n\n                if (key.equalsIgnoreCase(\"charfilter\")) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n\n                    accept(Token.LBRACKET);\n                    for (; ; ) {\n                        String c = SQLUtils.normalize(this.exprParser.name().getSimpleName());\n                        stmt.getCharfilters().add(c);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RBRACKET);\n                } else if (key.equalsIgnoreCase(\"tokenfilter\")) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n\n                    accept(Token.LBRACKET);\n                    for (; ; ) {\n                        String c = SQLUtils.normalize(this.exprParser.name().getSimpleName());\n                        stmt.getTokenizers().add(c);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RBRACKET);\n                } else if (key.equalsIgnoreCase(\"tokenizer\")) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n\n                    stmt.setTokenizer(SQLUtils.normalize(this.exprParser.name().getSimpleName()));\n                }\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        accept(Token.RPAREN);\n\n        String tokenizer = stmt.getTokenizer();\n        if (tokenizer == null || StringUtils.isEmpty(tokenizer)) {\n            throw new ParserException(\"tokenizer is require.\");\n        }\n\n        return stmt;\n    }\n\n    private SQLStatement parseFullTextTokenizer() {\n        MysqlCreateFullTextTokenizerStatement stmt = new MysqlCreateFullTextTokenizerStatement();\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLAssignItem assignItem = this.exprParser.parseAssignItem();\n            assignItem.setParent(stmt);\n\n            SQLExpr target = assignItem.getTarget();\n            if (\"type\".equalsIgnoreCase(((SQLTextLiteralExpr) target).getText())) {\n                stmt.setTypeName((SQLTextLiteralExpr) assignItem.getValue());\n            } else if (\"user_defined_dict\".equalsIgnoreCase(((SQLTextLiteralExpr) target).getText())) {\n                stmt.setUserDefinedDict((SQLTextLiteralExpr) assignItem.getValue());\n            } else {\n                stmt.getOptions().add(assignItem);\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        accept(Token.RPAREN);\n\n        SQLTextLiteralExpr typeName = stmt.getTypeName();\n        if (typeName == null || StringUtils.isEmpty(typeName.getText())) {\n            throw new ParserException(\"type is require.\");\n        }\n\n        return stmt;\n    }\n\n    private SQLStatement parseFullTextCharFilter() {\n        MysqlCreateFullTextCharFilterStatement stmt = new MysqlCreateFullTextCharFilterStatement();\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLAssignItem assignItem = this.exprParser.parseAssignItem();\n            assignItem.setParent(stmt);\n\n            if (\"type\".equalsIgnoreCase(((SQLTextLiteralExpr) assignItem.getTarget()).getText())) {\n                stmt.setTypeName((SQLTextLiteralExpr) assignItem.getValue());\n            } else {\n                stmt.getOptions().add(assignItem);\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        accept(Token.RPAREN);\n\n        SQLTextLiteralExpr typeName = stmt.getTypeName();\n        if (typeName == null || StringUtils.isEmpty(typeName.getText())) {\n            throw new ParserException(\"type is require.\");\n        }\n\n        return stmt;\n    }\n\n    private SQLStatement parseFullTextTokenFilter() {\n        MysqlCreateFullTextTokenFilterStatement stmt = new MysqlCreateFullTextTokenFilterStatement();\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLAssignItem assignItem = this.exprParser.parseAssignItem();\n            assignItem.setParent(stmt);\n\n            if (\"type\".equalsIgnoreCase(((SQLTextLiteralExpr) assignItem.getTarget()).getText())) {\n                stmt.setTypeName((SQLTextLiteralExpr) assignItem.getValue());\n            } else {\n                stmt.getOptions().add(assignItem);\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        accept(Token.RPAREN);\n\n        SQLTextLiteralExpr typeName = stmt.getTypeName();\n        if (typeName == null || StringUtils.isEmpty(typeName.getText())) {\n            throw new ParserException(\"type is require.\");\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseCreateOutline() {\n        accept(Token.CREATE);\n        acceptIdentifier(\"OUTLINE\");\n\n        SQLCreateOutlineStatement stmt = new SQLCreateOutlineStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.token() == Token.WHERE) {\n            lexer.nextToken();\n            stmt.setWhere(this.exprParser.expr());\n        }\n\n        accept(Token.ON);\n\n        expectedNextToken = Token.TO;\n        try {\n            SQLStatement on = this.parseStatement();\n            stmt.setOn(on);\n        } finally {\n            expectedNextToken = null;\n        }\n\n        accept(Token.TO);\n\n        SQLStatement to = this.parseStatement();\n        stmt.setTo(to);\n\n        return stmt;\n    }\n\n    public SQLStatement parseCreateTableSpace() {\n        if (lexer.token() == Token.CREATE) {\n            accept(Token.CREATE);\n        }\n\n        MySqlCreateTableSpaceStatement stmt = new MySqlCreateTableSpaceStatement();\n\n        accept(Token.TABLESPACE);\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.identifierEquals(FnvHash.Constants.ADD)) {\n            lexer.nextToken();\n            acceptIdentifier(\"DATAFILE\");\n            SQLExpr file = this.exprParser.primary();\n            stmt.setAddDataFile(file);\n        }\n\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr initialSize = this.exprParser.expr();\n                stmt.setInitialSize(initialSize);\n            } else if (lexer.identifierEquals(FnvHash.Constants.FILE_BLOCK_SIZE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr fileBlockSize = this.exprParser.expr();\n                stmt.setFileBlockSize(fileBlockSize);\n            } else if (lexer.identifierEquals(FnvHash.Constants.EXTENT_SIZE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr extentSize = this.exprParser.expr();\n                stmt.setExtentSize(extentSize);\n            } else if (lexer.identifierEquals(FnvHash.Constants.AUTOEXTEND_SIZE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr extentSize = this.exprParser.expr();\n                stmt.setAutoExtentSize(extentSize);\n            } else if (lexer.identifierEquals(FnvHash.Constants.MAX_SIZE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr size = this.exprParser.expr();\n                stmt.setMaxSize(size);\n            } else if (lexer.identifierEquals(FnvHash.Constants.NODEGROUP)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr size = this.exprParser.expr();\n                stmt.setNodeGroup(size);\n            } else if (lexer.identifierEquals(FnvHash.Constants.WAIT)) {\n                lexer.nextToken();\n                stmt.setWait(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr engine = this.exprParser.expr();\n                stmt.setEngine(engine);\n            } else if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                SQLExpr comment = this.exprParser.expr();\n                stmt.setComment(comment);\n            } else if (lexer.token() == Token.USE) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOGFILE\");\n                accept(GROUP);\n\n                SQLExpr logFileGroup = this.exprParser.expr();\n                stmt.setFileBlockSize(logFileGroup);\n            } else {\n                break;\n            }\n        }\n        return stmt;\n    }\n\n    public SQLStatement parseCreateServer() {\n        if (lexer.token() == Token.CREATE) {\n            accept(Token.CREATE);\n        }\n\n        MySqlCreateServerStatement stmt = new MySqlCreateServerStatement();\n\n        acceptIdentifier(\"SERVER\");\n        stmt.setName(this.exprParser.name());\n\n        accept(Token.FOREIGN);\n        acceptIdentifier(\"DATA\");\n        acceptIdentifier(\"WRAPPER\");\n        stmt.setForeignDataWrapper(this.exprParser.name());\n\n        acceptIdentifier(\"OPTIONS\");\n        accept(Token.LPAREN);\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.HOST)) {\n                lexer.nextToken();\n                SQLExpr host = this.exprParser.expr();\n                stmt.setHost(host);\n            } else if (lexer.token() == Token.USER) {\n                lexer.nextToken();\n                SQLExpr user = this.exprParser.expr();\n                stmt.setUser(user);\n            } else if (lexer.token() == Token.DATABASE) {\n                lexer.nextToken();\n                SQLExpr db = this.exprParser.expr();\n                stmt.setDatabase(db);\n            } else if (lexer.identifierEquals(FnvHash.Constants.PASSWORD)) {\n                lexer.nextToken();\n                SQLExpr pwd = this.exprParser.expr();\n                stmt.setPassword(pwd);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SOCKET)) {\n                lexer.nextToken();\n                SQLExpr sock = this.exprParser.expr();\n                stmt.setSocket(sock);\n            } else if (lexer.identifierEquals(FnvHash.Constants.OWNER)) {\n                lexer.nextToken();\n                SQLExpr owner = this.exprParser.expr();\n                stmt.setOwner(owner);\n            } else if (lexer.identifierEquals(FnvHash.Constants.PORT)) {\n                lexer.nextToken();\n                SQLExpr port = this.exprParser.expr();\n                stmt.setPort(port);\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n            } else {\n                break;\n            }\n        }\n        accept(Token.RPAREN);\n        return stmt;\n    }\n\n    public SQLCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n\n        SQLCreateIndexStatement stmt = new SQLCreateIndexStatement();\n\n        this.exprParser.parseIndex(stmt.getIndexDefinition());\n\n        return stmt;\n    }\n\n    private void parseCreateIndexUsing(SQLCreateIndexStatement stmt) {\n        if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.BTREE)) {\n                stmt.setUsing(\"BTREE\");\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.HASH)) {\n                stmt.setUsing(\"HASH\");\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n    }\n\n    public SQLStatement parseCreateUser() {\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n        }\n\n        accept(Token.USER);\n\n        MySqlCreateUserStatement stmt = new MySqlCreateUserStatement();\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        for (; ; ) {\n            MySqlCreateUserStatement.UserSpecification userSpec = new MySqlCreateUserStatement.UserSpecification();\n\n            if (lexer.token() == Token.IF) {\n                lexer.nextToken();\n                accept(Token.NOT);\n                accept(Token.EXISTS);\n                stmt.setIfNotExists(true);\n            }\n\n            MySqlUserName mySqlUserName = new MySqlUserName();\n            mySqlUserName.setUserName(trimQuotesBeginAndEnd(lexer.stringVal()));\n            lexer.nextToken();\n            String maybeHost = lexer.stringVal();\n            if (\"@\".equals(maybeHost)) {\n                lexer.nextToken();\n                mySqlUserName.setHost(trimQuotesBeginAndEnd(lexer.stringVal()));\n                lexer.nextToken();\n            } else if (maybeHost.startsWith(\"@\")) { // eg: @localhost\n                maybeHost = maybeHost.substring(1);\n                mySqlUserName.setHost(trimQuotesBeginAndEnd(maybeHost));\n                lexer.nextToken();\n            }\n\n            userSpec.setUser(mySqlUserName);\n\n            if (lexer.identifierEquals(FnvHash.Constants.IDENTIFIED)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.BY) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(\"RANDOM\")) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"PASSWORD\");\n                        userSpec.setRandomPassword(true);\n                    } else {\n                        if (lexer.identifierEquals(\"PASSWORD\")) {\n                            lexer.nextToken();\n                            userSpec.setPasswordHash(true);\n                        }\n                        SQLExpr password = this.exprParser.expr();\n                        if (password instanceof SQLIdentifierExpr || password instanceof SQLCharExpr) {\n                            userSpec.setPassword(password);\n                        } else {\n                            throw new ParserException(\"syntax error. invalid \" + password + \" expression.\");\n                        }\n                    }\n\n                } else if (lexer.token() == WITH) {\n                    lexer.nextToken();\n                    userSpec.setAuthPlugin(this.exprParser.expr());\n\n                    // IDENTIFIED WITH auth_plugin BY 'auth_string'\n                    // IDENTIFIED WITH auth_plugin AS 'auth_string'\n                    if (lexer.token() == Token.BY ||\n                            lexer.token() == Token.AS) {\n                        userSpec.setPluginAs(lexer.token() == Token.AS);\n                        lexer.nextToken();\n\n                        if (userSpec.isPluginAs()) {\n                            // Remove ' because lexer don't remove it when token after as.\n                            String psw = lexer.stringVal();\n                            userSpec.setPassword(new SQLCharExpr(trimQuotesBeginAndEnd(psw)));\n                            lexer.nextToken();\n                        } else {\n                            userSpec.setPassword(this.exprParser.charExpr());\n                        }\n                    }\n                }\n            }\n\n            stmt.addUser(userSpec);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        return stmt;\n    }\n\n    static String trimQuotesBeginAndEnd(String str) {\n        if (str == null || str.length() < 2) {\n            return str;\n        }\n        char beginChar = str.charAt(0);\n        char endChar = str.charAt(str.length() - 1);\n        if ((beginChar == '\\'' && endChar == '\\'') || (beginChar == '\\\"' && endChar == '\\\"')) {\n            return str.substring(1, str.length() - 1);\n        }\n        return str;\n    }\n    public SQLStatement parseKill() {\n        accept(Token.KILL);\n\n        MySqlKillStatement stmt = new MySqlKillStatement();\n\n        if (lexer.identifierEquals(\"CONNECTION\")) {\n            stmt.setType(MySqlKillStatement.Type.CONNECTION);\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.QUERY)\n                || lexer.identifierEquals(FnvHash.Constants.PROCESS)) {\n            stmt.setType(MySqlKillStatement.Type.QUERY);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.LITERAL_INT\n                || lexer.token() == Token.LITERAL_CHARS\n        ) {\n            // skip\n        } else if (lexer.token() == Token.ALL) {\n            SQLIdentifierExpr all = new SQLIdentifierExpr(lexer.stringVal());\n            all.setParent(stmt);\n            stmt.getThreadIds().add(all);\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"not support kill type \" + lexer.token() + \". \" + lexer.info());\n        }\n\n        this.exprParser.exprList(stmt.getThreadIds(), stmt);\n\n        if (lexer.token() == SEMI) {\n            lexer.nextToken();\n            stmt.setAfterSemi(true);\n        }\n        return stmt;\n    }\n\n    public SQLStatement parseBinlog() {\n        acceptIdentifier(\"binlog\");\n\n        MySqlBinlogStatement stmt = new MySqlBinlogStatement();\n\n        SQLExpr expr = this.exprParser.expr();\n        stmt.setExpr(expr);\n\n        return stmt;\n    }\n\n    public MySqlAnalyzeStatement parseAnalyze() {\n        accept(Token.ANALYZE);\n        MySqlAnalyzeStatement stmt = new MySqlAnalyzeStatement();\n\n        if (lexer.token() == TABLE) {\n            accept(TABLE);\n            List<SQLName> names = new ArrayList<SQLName>();\n            this.exprParser.names(names, stmt);\n\n            for (SQLName name : names) {\n                stmt.addTableSource(new SQLExprTableSource(name));\n            }\n            if (lexer.token() == WHERE) {\n                accept(WHERE);\n                SQLExpr where = this.exprParser.expr();\n                stmt.setAdbWhere(where);\n            }\n        } else if (lexer.token() == DATABASE) {\n            accept(DATABASE);\n            SQLName name = this.exprParser.name();\n            stmt.setAdbSchema((SQLIdentifierExpr) name);\n        } else if (lexer.token() == COLUMN) {\n            accept(COLUMN);\n            SQLName table = this.exprParser.name();\n            stmt.setTable(table);\n\n            accept(LPAREN);\n\n            for (; ; ) {\n                SQLName name = this.exprParser.name();\n                stmt.getAdbColumns().add((SQLIdentifierExpr) name);\n                if (lexer.token() == COMMA) {\n                    accept(COMMA);\n                    continue;\n                }\n                break;\n            }\n            accept(RPAREN);\n            if (lexer.token() == WHERE) {\n                accept(WHERE);\n                SQLExpr where = this.exprParser.expr();\n                stmt.setAdbWhere(where);\n            }\n        } else if (lexer.identifierEquals(\"columns\")) {\n            lexer.nextToken();\n            accept(GROUP);\n\n            SQLName table = this.exprParser.name();\n            stmt.setTable(table);\n\n            accept(LPAREN);\n\n            for (; ; ) {\n                SQLName name = this.exprParser.name();\n                stmt.getAdbColumnsGroup().add((SQLIdentifierExpr) name);\n                if (lexer.token() == COMMA) {\n                    accept(COMMA);\n                    continue;\n                }\n                break;\n            }\n            accept(RPAREN);\n            if (lexer.token() == WHERE) {\n                accept(WHERE);\n                SQLExpr where = this.exprParser.expr();\n                stmt.setAdbWhere(where);\n            }\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            stmt.setPartition(\n                    parsePartitionRef()\n            );\n        }\n\n        if (lexer.token() == Token.COMPUTE) {\n            lexer.nextToken();\n            acceptIdentifier(\"STATISTICS\");\n            stmt.setComputeStatistics(true);\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n            acceptIdentifier(\"COLUMNS\");\n            stmt.setForColums(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CACHE)) {\n            lexer.nextToken();\n            acceptIdentifier(\"METADATA\");\n            stmt.setCacheMetadata(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.NOSCAN)) {\n            lexer.nextToken();\n            stmt.setNoscan(true);\n        }\n\n        return stmt;\n    }\n\n    public MySqlOptimizeStatement parseOptimize() {\n        accept(Token.OPTIMIZE);\n        accept(TABLE);\n\n        MySqlOptimizeStatement stmt = new MySqlOptimizeStatement();\n        List<SQLName> names = new ArrayList<SQLName>();\n        this.exprParser.names(names, stmt);\n\n        for (SQLName name : names) {\n            stmt.addTableSource(new SQLExprTableSource(name));\n        }\n        return stmt;\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.identifierEquals(\"PREPARE\")) {\n            MySqlPrepareStatement stmt = parsePrepare();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"DEALLOCATE\")) {\n            MysqlDeallocatePrepareStatement stmt = parseDeallocatePrepare();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"LOAD\")) {\n            SQLStatement stmt = parseLoad();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.REPLACE) {\n            SQLReplaceStatement stmt = parseReplace();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"START\")) {\n            SQLStartTransactionStatement stmt = parseStart();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.SHOW) {\n            SQLStatement stmt = parseShow();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"CLEAR\")) {\n            lexer.nextToken();\n\n            if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(\"DDL\")) {\n                // CLEAR DDL CACHE { ALL | <job_id> [ , <job_id> ] ... }\n                lexer.nextToken();\n                accept(Token.CACHE);\n\n                DrdsClearDDLJobCache stmt = new DrdsClearDDLJobCache();\n                if (Token.ALL == lexer.token()) {\n                    lexer.nextToken();\n                    stmt.setAllJobs(true);\n                    statementList.add(stmt);\n                    return true;\n                } else {\n                    while (true) {\n                        stmt.addJobId(lexer.integerValue().longValue());\n                        accept(Token.LITERAL_INT);\n                        if (Token.COMMA == lexer.token()) {\n                            lexer.nextToken();\n                        } else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                            break;\n                        } else {\n                            throw new ParserException(\"syntax error, expect job id, actual \" + lexer.token() + \", \" + lexer.info());\n                        }\n                    }\n                    statementList.add(stmt);\n                    return true;\n                }\n            }\n\n            acceptIdentifier(\"PLANCACHE\");\n\n            statementList.add(new MySqlClearPlanCacheStatement());\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"DISABLED\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"PLANCACHE\");\n\n            statementList.add(new MySqlDisabledPlanCacheStatement());\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"XA\")) {\n            lexer.nextToken();\n            MySqlXAStatement stmt = new MySqlXAStatement();\n            String typeStr = lexer.stringVal();\n            stmt.setType(\n                    MySqlXAStatement.XAType.of(typeStr)\n            );\n            lexer.nextToken();\n\n            if (lexer.token() != EOF && lexer.token() != SEMI) {\n                SQLExpr xid = exprParser.expr();\n                stmt.setId(xid);\n            }\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.EXPLAIN) {\n            SQLStatement stmt = this.parseExplain();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(BINLOG)) {\n            SQLStatement stmt = parseBinlog();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(RESET)) {\n            SQLStatement stmt = parseReset();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.ANALYZE) {\n            SQLStatement stmt = parseAnalyze();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ARCHIVE)) {\n            SQLStatement stmt = parseArchive();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.BACKUP)) {\n            SQLStatement stmt = parseBackup();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RESTORE)) {\n            SQLStatement stmt = parseRestore();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"BUILD\")) {\n            SQLStatement stmt = parseBuildTable();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"CANCEL\")) {\n            SQLStatement stmt = parseCancelJob();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXPORT)) {\n            lexer.nextToken();\n            if (lexer.token() == TABLE) {\n                SQLStatement stmt = parseExportTable();\n                statementList.add(stmt);\n            } else if (lexer.token() == Token.DATABASE) {\n                SQLStatement stmt = parseExportDB();\n                statementList.add(stmt);\n            }\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IMPORT)) {\n            lexer.nextToken();\n            if (lexer.token() == TABLE) {\n                SQLStatement stmt = parseImportTable();\n                statementList.add(stmt);\n            } else if (lexer.token() == Token.DATABASE) {\n                SQLStatement stmt = parseImportDB();\n                statementList.add(stmt);\n            }\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"SUBMIT\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"JOB\");\n\n            SQLStatement stmt = parseSubmitJob();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.MIGRATE)) {\n            SQLStatement stmt = parseMigrate();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.OPTIMIZE) {\n            SQLStatement stmt = parseOptimize();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"HELP\")) {\n            lexer.nextToken();\n            MySqlHelpStatement stmt = new MySqlHelpStatement();\n            stmt.setContent(this.exprParser.primary());\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"FLUSH\")) {\n            SQLStatement stmt = parseFlush();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SYNC)) {\n            SQLStatement stmt = parseSync();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.INIT)) {\n            statementList.add(\n                    new SQLExprStatement(\n                            this.exprParser.expr()));\n            return true;\n        }\n\n        // DRDS async DDL.\n        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(FnvHash.Constants.RECOVER)) {\n            // RECOVER DDL {ALL | <job_id> [, <job_id>] ...}\n            lexer.nextToken();\n            acceptIdentifier(\"DDL\");\n            DrdsRecoverDDLJob stmt = new DrdsRecoverDDLJob();\n            if (Token.ALL == lexer.token()) {\n                lexer.nextToken();\n                stmt.setAllJobs(true);\n                statementList.add(stmt);\n                return true;\n            } else {\n                while (true) {\n                    stmt.addJobId(lexer.integerValue().longValue());\n                    accept(Token.LITERAL_INT);\n                    if (Token.COMMA == lexer.token()) {\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                        break;\n                    } else {\n                        throw new ParserException(\"syntax error, expect job id, actual \" + lexer.token() + \", \" + lexer.info());\n                    }\n                }\n                statementList.add(stmt);\n                return true;\n            }\n        }\n\n        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(FnvHash.Constants.REMOVE)) {\n            // REMOVE DDL { ALL { COMPLETED | PENDING } | <job_id> [, <job_id>] ...}\n            lexer.nextToken();\n            acceptIdentifier(\"DDL\");\n            DrdsRemoveDDLJob stmt = new DrdsRemoveDDLJob();\n            if (Token.ALL == lexer.token()) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"COMPLETED\")) {\n                    lexer.nextToken();\n                    stmt.setAllCompleted(true);\n                } else if (lexer.identifierEquals(\"PENDING\")) {\n                    lexer.nextToken();\n                    stmt.setAllPending(true);\n                } else {\n                    throw new ParserException(\"syntax error, expect COMPLETED or PENDING, actual \" + lexer.token() + \", \" + lexer.info());\n                }\n            } else {\n                while (true) {\n                    stmt.addJobId(lexer.integerValue().longValue());\n                    accept(Token.LITERAL_INT);\n                    if (Token.COMMA == lexer.token()) {\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                        break;\n                    } else {\n                        throw new ParserException(\"syntax error, expect job id, actual \" + lexer.token() + \", \" + lexer.info());\n                    }\n                }\n            }\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(\"INSPECT\")) {\n            // INSPECT DDL CACHE\n            lexer.nextToken();\n            acceptIdentifier(\"DDL\");\n            accept(Token.CACHE);\n            statementList.add(new DrdsInspectDDLJobCache());\n            return true;\n        }\n\n        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(FnvHash.Constants.CHANGE)) {\n            // CHANGE DDL <job_id> { SKIP | ADD } <group_and_table_name> [ , <group_and_table_name> ] ...\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"DDL\")) {\n                lexer.nextToken();\n\n                DrdsChangeDDLJob stmt = new DrdsChangeDDLJob();\n\n                stmt.setJobId(lexer.integerValue().longValue());\n                accept(Token.LITERAL_INT);\n\n                if (lexer.identifierEquals(\"SKIP\")) {\n                    lexer.nextToken();\n                    stmt.setSkip(true);\n                } else if (lexer.identifierEquals(\"ADD\")) {\n                    lexer.nextToken();\n                    stmt.setAdd(true);\n                } else {\n                    throw new ParserException(\"syntax error, expect SKIP or ADD, actual \" + lexer.token() + \", \" + lexer.info());\n                }\n\n                StringBuilder builder = new StringBuilder();\n                while (true) {\n                    if (Token.COMMA == lexer.token()) {\n                        lexer.nextToken();\n                        stmt.addGroupAndTableNameList(builder.toString());\n                        builder = new StringBuilder();\n                    } else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                        stmt.addGroupAndTableNameList(builder.toString());\n                        break;\n                    } else if (lexer.token() == Token.COLON) {\n                        builder.append(':');\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.DOT) {\n                        builder.append('.');\n                        lexer.nextToken();\n                    } else {\n                        builder.append(lexer.stringVal());\n                        lexer.nextToken();\n                    }\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n            lexer.reset(mark);\n        }\n\n        if (isEnabled(SQLParserFeature.DRDSBaseline) && lexer.identifierEquals(\"BASELINE\")) {\n            lexer.nextToken();\n\n            DrdsBaselineStatement stmt = new DrdsBaselineStatement();\n\n            if (Token.EOF == lexer.token() || SEMI == lexer.token() ||\n                    lexer.stringVal().isEmpty() || lexer.stringVal().equalsIgnoreCase(\"BASELINE\")) {\n                throw new ParserException(\"syntax error, expect baseline operation, actual \" + lexer.token() + \", \" + lexer.info());\n            }\n\n            stmt.setOperation(lexer.stringVal());\n\n            lexer.setToken(Token.COMMA); // Hack here: Set previous comma to deal with negative number.\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.SQL)) {\n                // Parse select.\n                lexer.nextToken();\n\n                if (lexer.token() == Token.HINT) {\n                    stmt.setHeadHints(this.exprParser.parseHints());\n                }\n\n                MySqlSelectParser selectParser = createSQLSelectParser();\n                stmt.setSelect(selectParser.select());\n            } else {\n                // Parse id list.\n                while (lexer.token() != Token.EOF && lexer.token() != SEMI) {\n                    stmt.addBaselineId(lexer.integerValue().longValue());\n                    accept(Token.LITERAL_INT);\n                    if (Token.COMMA == lexer.token()) {\n                        lexer.nextToken();\n                    }\n                }\n            }\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.DESC || lexer.identifierEquals(DESCRIBE)) {\n            SQLStatement stmt = parseDescribe();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.LOCK) {\n            lexer.nextToken();\n            String val = lexer.stringVal();\n            boolean isLockTables = TABLES.equalsIgnoreCase(val) && lexer.token() == Token.IDENTIFIER;\n            boolean isLockTable = \"TABLE\".equalsIgnoreCase(val) && lexer.token() == TABLE;\n            if (isLockTables || isLockTable) {\n                lexer.nextToken();\n            } else {\n                setErrorEndPos(lexer.pos());\n                throw new ParserException(\"syntax error, expect TABLES or TABLE, actual \" + lexer.token() + \", \" + lexer.info());\n            }\n\n            MySqlLockTableStatement stmt = new MySqlLockTableStatement();\n\n            for (; ; ) {\n                MySqlLockTableStatement.Item item = new MySqlLockTableStatement.Item();\n\n                SQLExprTableSource tableSource = null;\n                SQLName tableName = this.exprParser.name();\n\n                if (lexer.token() == Token.AS) {\n                    lexer.nextToken();\n                    String as = lexer.stringVal();\n                    tableSource = new SQLExprTableSource(tableName, as);\n                    lexer.nextToken();\n                } else {\n                    tableSource = new SQLExprTableSource(tableName);\n                }\n                item.setTableSource(tableSource);\n                stmt.getItems().add(item);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                if (lexer.identifierEquals(READ)) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(LOCAL)) {\n                        lexer.nextToken();\n                        item.setLockType(LockType.READ_LOCAL);\n                    } else {\n                        item.setLockType(LockType.READ);\n                    }\n                } else if (lexer.identifierEquals(WRITE)) {\n                    lexer.nextToken();\n                    item.setLockType(LockType.WRITE);\n                } else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {\n                    lexer.nextToken();\n                    acceptIdentifier(WRITE);\n                    item.setLockType(LockType.LOW_PRIORITY_WRITE);\n                } else {\n                    throw new ParserException(\n                            \"syntax error, expect READ or WRITE OR AS, actual \" + lexer.token() + \", \" + lexer.info());\n                }\n\n                if (lexer.token() == Token.HINT) {\n                    item.setHints(this.exprParser.parseHints());\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"UNLOCK\")) {\n            lexer.nextToken();\n            String val = lexer.stringVal();\n            boolean isUnLockTables = TABLES.equalsIgnoreCase(val) && lexer.token() == Token.IDENTIFIER;\n            boolean isUnLockTable = \"TABLE\".equalsIgnoreCase(val) && lexer.token() == TABLE;\n            statementList.add(new MySqlUnlockTablesStatement());\n            if (isUnLockTables || isUnLockTable) {\n                lexer.nextToken();\n            } else {\n                setErrorEndPos(lexer.pos());\n                throw new ParserException(\"syntax error, expect TABLES or TABLE, actual \" + lexer.token() + \", \" + lexer.info());\n            }\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) {\n            statementList.add(this.parseChecksum());\n            return true;\n        }\n\n        if (lexer.token() == Token.HINT) {\n            List<SQLCommentHint> hints = this.exprParser.parseHints();\n\n            boolean tddlHints = false;\n            boolean accept = false;\n\n            boolean acceptHint = false;\n            switch (lexer.token()) {\n                case SELECT:\n                case WITH:\n                case DELETE:\n                case UPDATE:\n                case INSERT:\n                case SHOW:\n                case REPLACE:\n                case TRUNCATE:\n                case DROP:\n                case ALTER:\n                case CREATE:\n                case CHECK:\n                case SET:\n                case DESC:\n                case OPTIMIZE:\n                case ANALYZE:\n                case KILL:\n                case EXPLAIN:\n                case LPAREN:\n                    acceptHint = true;\n                    break;\n                case IDENTIFIER:\n                    acceptHint = lexer.hashLCase() == FnvHash.Constants.DUMP\n                            || lexer.hashLCase() == FnvHash.Constants.RENAME\n                            || lexer.hashLCase() == FnvHash.Constants.DESCRIBE;\n                    break;\n                default:\n                    break;\n            }\n            if (hints.size() >= 1\n                    && statementList.isEmpty()\n                    && acceptHint) {\n                SQLCommentHint hint = hints.get(0);\n                String hintText = hint.getText().toUpperCase();\n                if (hintText.startsWith(\"+TDDL\")\n                        || hintText.startsWith(\"+ TDDL\")\n                        || hintText.startsWith(\"TDDL\")\n                        || hintText.startsWith(\"!TDDL\")) {\n                    tddlHints = true;\n                } else if (hintText.startsWith(\"+\")) {\n                    accept = true;\n                }\n            }\n\n            if (tddlHints) {\n                SQLStatementImpl stmt = (SQLStatementImpl) this.parseStatement();\n                stmt.setHeadHints(hints);\n                statementList.add(stmt);\n                return true;\n            } else if (accept) {\n                SQLStatementImpl stmt = (SQLStatementImpl) this.parseStatement();\n                stmt.setHeadHints(hints);\n                statementList.add(stmt);\n                return true;\n            }\n\n            MySqlHintStatement stmt = new MySqlHintStatement();\n            stmt.setHints(hints);\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.BEGIN) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token() == SEMI || lexer.token() == Token.EOF || lexer.token() == Token.IDENTIFIER) {\n                lexer.reset(mark);\n                statementList.add(this.parseTiDBBeginStatment());\n                return true;\n            } else {\n                lexer.reset(mark);\n            }\n            statementList.add(this.parseBlock());\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ADD)) {\n            statementList.add(parseAddManageInstanceGroup());\n            return true;\n        }\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            String label = lexer.stringVal();\n            Lexer.SavePoint savePoint = lexer.markOut();\n            lexer.nextToken();\n            if (lexer.token() == Token.VARIANT && lexer.stringVal().equals(\":\")) {\n                lexer.nextToken();\n                if (lexer.token() == Token.LOOP) {\n                    // parse loop statement\n                    statementList.add(this.parseLoop(label));\n                } else if (lexer.token() == Token.WHILE) {\n                    // parse while statement with label\n                    statementList.add(this.parseWhile(label));\n                } else if (lexer.token() == Token.BEGIN) {\n                    // parse begin-end statement with label\n                    SQLBlockStatement block = this.parseBlock(label);\n                    statementList.add(block);\n                } else if (lexer.token() == Token.REPEAT) {\n                    // parse repeat statement with label\n                    statementList.add(this.parseRepeat(label));\n                }\n                return true;\n            } else {\n                lexer.reset(savePoint);\n            }\n\n        }\n\n        if (lexer.token() == Token.CHECK) {\n            final Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.token() == TABLE) {\n                lexer.nextToken();\n\n                MySqlCheckTableStatement stmt = new MySqlCheckTableStatement();\n                for (; ; ) {\n                    SQLName table = this.exprParser.name();\n                    stmt.addTable(new SQLExprTableSource(table));\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n\n                    break;\n                }\n                statementList.add(stmt);\n            }\n            return true;\n        }\n        String strVal = lexer.stringVal();\n        if (strVal.equalsIgnoreCase(\"SPLIT\")) {\n            TidbSplitTableStatement stmt = this.parseTiDBSplitTableStatement();\n            statementList.add(stmt);\n            return true;\n        }\n\n        return false;\n    }\n\n    private TidbSplitTableStatement parseTiDBSplitTableStatement() {\n        TidbSplitTableStatement stmt = new TidbSplitTableStatement();\n        lexer.nextToken();\n        Lexer.SavePoint mark = lexer.mark();\n        String strVal = lexer.stringVal();\n        if (lexer.token() == PARTITION) {\n            accept(PARTITION);\n            stmt.setSplitSyntaxOptionPartition(true);\n        } else if (strVal.equalsIgnoreCase(\"REGION\")) {\n            acceptIdentifier(\"REGION\");\n            accept(FOR);\n            stmt.setSplitSyntaxOptionRegionFor(true);\n        } else {\n            lexer.reset(mark);\n        }\n        strVal = lexer.stringVal();\n        accept(TABLE);\n        SQLName tableNameTmp = this.exprParser.name();\n        SQLExprTableSource sqlExprTableSource = new SQLExprTableSource(tableNameTmp);\n        stmt.setTableName(sqlExprTableSource);\n        strVal = lexer.stringVal();\n        if (lexer.token() == INDEX) {\n            accept(INDEX);\n            SQLName indexName = this.exprParser.name();\n            stmt.setIndexName(indexName);\n        } else if (lexer.token() == PARTITION) {\n            accept(PARTITION);\n            accept(LPAREN);\n            this.exprParser.exprList(stmt.getPartitionNameListOptions(), stmt);\n            accept(RPAREN);\n            if (lexer.token() == INDEX) {\n                accept(INDEX);\n                SQLName indexName = this.exprParser.name();\n                stmt.setIndexName(indexName);\n            }\n        }\n        if (lexer.token() == BETWEEN) {\n            accept(BETWEEN);\n            accept(LPAREN);\n            List<SQLExpr> sqlExprBetweens = new ArrayList<>();\n            this.exprParser.exprList(sqlExprBetweens, stmt);\n            stmt.setSplitOptionBetween(sqlExprBetweens);\n            accept(RPAREN);\n            accept(AND);\n            accept(LPAREN);\n            List<SQLExpr> sqlExprAnds = new ArrayList<>();\n            this.exprParser.exprList(sqlExprAnds, stmt);\n            stmt.setSplitOptionAnd(sqlExprAnds);\n            accept(RPAREN);\n            acceptIdentifier(\"REGIONS\");\n            SQLIntegerExpr num = this.exprParser.integerExpr();\n            stmt.setSplitOptionRegions(num.getNumber().longValue());\n        } else if (lexer.token() == BY) {\n            accept(BY);\n            accept(LPAREN);\n            List<SQLExpr> byItems = new ArrayList<>();\n            this.exprParser.exprList(byItems, stmt);\n            accept(RPAREN);\n            stmt.getSplitOptionBys().add(byItems);\n            while (lexer.token() == COMMA) {\n                accept(COMMA);\n                accept(LPAREN);\n                byItems = new ArrayList<>();\n                this.exprParser.exprList(byItems, stmt);\n                accept(RPAREN);\n                stmt.getSplitOptionBys().add(byItems);\n            }\n\n        } else if (lexer.token() == PARTITION) {\n            accept(PARTITION);\n        }\n        return stmt;\n    }\n    private SQLStatement parseArchive() {\n        lexer.nextToken();\n        accept(TABLE);\n        SQLArchiveTableStatement stmt = new SQLArchiveTableStatement();\n\n        SQLName tableName = this.exprParser.name();\n        stmt.setTable(tableName);\n        stmt.setType(new SQLIdentifierExpr(\"UPLOAD\"));\n\n        if (lexer.token() == Token.LITERAL_INT) {\n            for (; ; ) {\n                stmt.getSpIdList().add(this.exprParser.integerExpr());\n                String pidStr = lexer.stringVal();\n                accept(Token.VARIANT);\n                String s = pidStr.replaceAll(\":\", \"\");\n                if (StringUtils.isEmpty(s)) {\n                    stmt.getpIdList().add(exprParser.integerExpr());\n                } else {\n                    stmt.getpIdList().add(new SQLIntegerExpr(Integer.valueOf(s)));\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n        }\n        return stmt;\n    }\n\n    private SQLStatement parseBackup() {\n        lexer.nextToken();\n        SQLBackupStatement stmt = new SQLBackupStatement();\n\n        String type = \"BACKUP_DATA\";\n        String action = \"BACKUP\";\n\n        if (lexer.identifierEquals(FnvHash.Constants.DATA)) {\n            lexer.nextToken();\n            accept(Token.INTO);\n            type = \"BACKUP_DATA\";\n\n            for (; ; ) {\n                stmt.getProperties().add(new SQLCharExpr(lexer.stringVal()));\n                accept(Token.LITERAL_CHARS);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.LOG)) {\n            type = \"BACKUP_LOG\";\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"LIST_LOGS\")) {\n                lexer.nextToken();\n                action = \"LIST_LOG\";\n\n            } else if (lexer.identifierEquals(FnvHash.Constants.STATUS)) {\n                lexer.nextToken();\n                action = \"STATUS\";\n            } else if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n                for (; ; ) {\n                    stmt.getProperties().add(new SQLCharExpr(lexer.stringVal()));\n                    accept(Token.LITERAL_CHARS);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n            }\n\n        } else if (lexer.identifierEquals(\"CANCEL\")) {\n            lexer.nextToken();\n            type = \"BACKUP_DATA\";\n            action = \"BACKUP_CANCEL\";\n            stmt.getProperties().add(new SQLCharExpr(lexer.stringVal()));\n            accept(Token.LITERAL_CHARS);\n        }\n\n        stmt.setType(new SQLIdentifierExpr(type));\n        stmt.setAction(new SQLIdentifierExpr(action));\n\n        return stmt;\n    }\n\n    private SQLStatement parseRestore() {\n        lexer.nextToken();\n\n        String type = \"DATA\";\n\n        SQLRestoreStatement stmt = new SQLRestoreStatement();\n\n        if (lexer.identifierEquals(FnvHash.Constants.DATA)) {\n            lexer.nextToken();\n            type = \"DATA\";\n        } else if (lexer.identifierEquals(FnvHash.Constants.LOG)) {\n            lexer.nextToken();\n            type = \"LOG\";\n        }\n\n        stmt.setType(new SQLIdentifierExpr(type));\n\n        accept(Token.FROM);\n        for (; ; ) {\n            stmt.getProperties().add(new SQLCharExpr(lexer.stringVal()));\n            accept(Token.LITERAL_CHARS);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        return stmt;\n    }\n\n    private SQLStatement parseBuildTable() {\n        lexer.nextToken();\n\n        SQLBuildTableStatement stmt = new SQLBuildTableStatement();\n\n        accept(TABLE);\n\n        stmt.setTable(this.exprParser.name());\n\n        if (lexer.identifierEquals(FnvHash.Constants.VERSION)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            stmt.setVersion(this.exprParser.integerExpr());\n        }\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"SPLIT\");\n\n            stmt.setWithSplit(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n\n            accept(EQ);\n\n            if (lexer.token() == TRUE) {\n                lexer.nextToken();\n                stmt.setForce(true);\n            } else if (lexer.token() == FALSE) {\n                lexer.nextToken();\n                stmt.setForce(false);\n            }\n        }\n\n        return stmt;\n    }\n\n    private SQLStatement parseCancelJob() {\n        lexer.nextToken();\n\n        // DRDS async DDL.\n        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(\"DDL\")) {\n            // CANCEL DDL <job_id> [, <job_id>] ...\n            lexer.nextToken();\n            DrdsCancelDDLJob cancelDDLJob = new DrdsCancelDDLJob();\n            while (true) {\n                cancelDDLJob.addJobId(lexer.integerValue().longValue());\n                accept(Token.LITERAL_INT);\n                if (Token.COMMA == lexer.token()) {\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                    break;\n                } else {\n                    throw new ParserException(\"syntax error, expect job id, actual \" + lexer.token() + \", \" + lexer.info());\n                }\n            }\n            return cancelDDLJob;\n        }\n\n        SQLCancelJobStatement stmt = new SQLCancelJobStatement();\n\n        if (lexer.identifierEquals(\"JOB\")) {\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"LOAD_JOB\")) {\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"SYNC_JOB\")) {\n            lexer.nextToken();\n            stmt.setImport(true);\n        }\n\n        stmt.setJobName(this.exprParser.name());\n\n        return stmt;\n\n    }\n\n    protected SQLStatement parseExportTable() {\n        accept(TABLE);\n        SQLExportTableStatement stmt = new SQLExportTableStatement();\n        stmt.setTable(\n                new SQLExprTableSource(\n                        this.exprParser.name()));\n        return stmt;\n    }\n\n    protected SQLStatement parseExportDB() {\n        accept(Token.DATABASE);\n        SQLExportDatabaseStatement stmt = new SQLExportDatabaseStatement();\n        stmt.setDb(this.exprParser.name());\n\n        if (lexer.identifierEquals(\"REALTIME\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            if (\"y\".equalsIgnoreCase(lexer.stringVal())) {\n                lexer.nextToken();\n                stmt.setRealtime(true);\n            } else if (\"n\".equalsIgnoreCase(lexer.stringVal())) {\n                lexer.nextToken();\n                stmt.setRealtime(false);\n            } else {\n                throw new ParserException(\"Invalid 'realtime' option, should be 'Y' or 'N'. \");\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseRaftLeaderTransfer() {\n        acceptIdentifier(\"RAFT_LEADER_TRANSFER\");\n        MySqlRaftLeaderTransferStatement stmt = new MySqlRaftLeaderTransferStatement();\n\n        acceptIdentifier(\"SHARD\");\n        accept(Token.EQ);\n\n        stmt.setShard(exprParser.charExpr());\n\n        accept(Token.FROM);\n        accept(Token.EQ);\n        stmt.setFrom(exprParser.charExpr());\n\n        accept(Token.TO);\n        accept(Token.EQ);\n        stmt.setTo(exprParser.charExpr());\n\n        acceptIdentifier(\"TIMEOUT\");\n        accept(Token.EQ);\n        stmt.setTimeout(exprParser.integerExpr());\n\n        return stmt;\n    }\n\n    protected SQLStatement parseRaftMemeberChange() {\n        acceptIdentifier(\"RAFT_MEMBER_CHANGE\");\n        MySqlRaftMemberChangeStatement stmt = new MySqlRaftMemberChangeStatement();\n\n        if (lexer.identifierEquals(\"NOLEADER\")) {\n            lexer.nextToken();\n            stmt.setNoLeader(true);\n        }\n\n        acceptIdentifier(\"SHARD\");\n        accept(Token.EQ);\n\n        stmt.setShard(exprParser.charExpr());\n\n        acceptIdentifier(\"HOST\");\n        accept(Token.EQ);\n        stmt.setHost(exprParser.charExpr());\n\n        acceptIdentifier(\"STATUS\");\n        accept(Token.EQ);\n        stmt.setStatus(exprParser.charExpr());\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n            stmt.setForce(true);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseMigrate() {\n        MySqlMigrateStatement stmt = new MySqlMigrateStatement();\n        acceptIdentifier(\"MIGRATE\");\n        accept(Token.DATABASE);\n\n        stmt.setSchema(exprParser.name());\n\n        acceptIdentifier(\"SHARDS\");\n        accept(Token.EQ);\n        stmt.setShardNames(exprParser.charExpr());\n\n        if (lexer.token() == GROUP) {\n            lexer.nextToken();\n            stmt.setMigrateType(new SQLIntegerExpr(0));\n        } else if (lexer.identifierEquals(FnvHash.Constants.HOST)) {\n            lexer.nextToken();\n            stmt.setMigrateType(new SQLIntegerExpr(1));\n        }\n\n        accept(Token.FROM);\n        stmt.setFromInsId(exprParser.charExpr());\n\n        if (lexer.token() == Token.VARIANT) {\n            lexer.nextToken();\n            stmt.setFromInsIp(exprParser.charExpr());\n\n            String variant = lexer.stringVal();\n            Integer number = Integer.valueOf(variant.substring(1, variant.length()));\n            stmt.setFromInsPort(new SQLIntegerExpr(number));\n            accept(Token.VARIANT);\n\n            accept(Token.VARIANT);\n            stmt.setFromInsStatus(exprParser.charExpr());\n        }\n\n        accept(Token.TO);\n        stmt.setToInsId(exprParser.charExpr());\n\n        if (lexer.token() == Token.VARIANT) {\n            lexer.nextToken();\n            stmt.setToInsIp(exprParser.charExpr());\n\n            String variant = lexer.stringVal();\n            Integer number = Integer.valueOf(variant.substring(1, variant.length()));\n            stmt.setToInsPort(new SQLIntegerExpr(number));\n            accept(Token.VARIANT);\n\n            accept(Token.VARIANT);\n            stmt.setToInsStatus(exprParser.charExpr());\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseImportDB() {\n        accept(Token.DATABASE);\n        SQLImportDatabaseStatement stmt = new SQLImportDatabaseStatement();\n\n        stmt.setDb(this.exprParser.name());\n\n        if (lexer.identifierEquals(FnvHash.Constants.STATUS)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            stmt.setStatus(this.exprParser.name());\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseImportTable() {\n        SQLImportTableStatement stmt = new SQLImportTableStatement();\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            lexer.nextToken();\n            stmt.setExtenal(true);\n        }\n\n        accept(TABLE);\n        stmt.setTable(\n                new SQLExprTableSource(\n                        this.exprParser.name()));\n\n        acceptIdentifier(\"VERSION\");\n        accept(Token.EQ);\n        stmt.setVersion(this.exprParser.integerExpr());\n\n        if (lexer.identifierEquals(\"BUILD\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            if (\"Y\".equalsIgnoreCase(lexer.stringVal())) {\n                lexer.nextToken();\n                stmt.setUsingBuild(true);\n            } else if (\"N\".equalsIgnoreCase(lexer.stringVal())) {\n                lexer.nextToken();\n                stmt.setUsingBuild(false);\n            } else {\n                throw new ParserException(\"Invalid 'build' option, should be 'Y' or 'N'. \");\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseSubmitJob() {\n        SQLSubmitJobStatement stmt = new SQLSubmitJobStatement();\n        if (lexer.identifierEquals(\"AWAIT\")) {\n            lexer.nextToken();\n            stmt.setAwait(true);\n        }\n\n        stmt.setStatment(this.parseStatement());\n\n        return stmt;\n    }\n\n    public SQLStatement parseSync() {\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(\"RAFT_LEADER_TRANSFER\")) {\n            return parseRaftLeaderTransfer();\n        } else if (lexer.identifierEquals(\"RAFT_MEMBER_CHANGE\")) {\n            return parseRaftMemeberChange();\n        } else {\n            acceptIdentifier(\"META\");\n            acceptIdentifier(\"TABLES\");\n\n            SQLSyncMetaStatement stmt = new SQLSyncMetaStatement();\n\n            if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n                stmt.setFrom(\n                        this.exprParser.name()\n                );\n            }\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextToken();\n                stmt.setLike(\n                        this.exprParser.expr()\n                );\n            }\n            return stmt;\n        }\n\n    }\n\n    public SQLStatement parseFlush() {\n        acceptIdentifier(\"FLUSH\");\n        MySqlFlushStatement stmt = new MySqlFlushStatement();\n\n        if (lexer.identifierEquals(\"NO_WRITE_TO_BINLOG\")) {\n            lexer.nextToken();\n            stmt.setNoWriteToBinlog(true);\n        }\n\n        if (lexer.identifierEquals(\"LOCAL\")) {\n            lexer.nextToken();\n            stmt.setLocal(true);\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.BINARY || lexer.identifierEquals(\"BINARY\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOGS\");\n                stmt.setBinaryLogs(true);\n            } else if (lexer.identifierEquals(\"DES_KEY_FILE\")) {\n                lexer.nextToken();\n                stmt.setDesKeyFile(true);\n            } else if (lexer.identifierEquals(\"ENGINE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOGS\");\n                stmt.setEngineLogs(true);\n            } else if (lexer.identifierEquals(\"ERROR\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOGS\");\n                stmt.setErrorLogs(true);\n            } else if (lexer.identifierEquals(\"GENERAL\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOGS\");\n                stmt.setGeneralLogs(true);\n            } else if (lexer.identifierEquals(\"HOSTS\")) {\n                lexer.nextToken();\n                stmt.setHots(true);\n            } else if (lexer.identifierEquals(\"LOGS\")) {\n                lexer.nextToken();\n                stmt.setLogs(true);\n            } else if (lexer.identifierEquals(\"PRIVILEGES\")) {\n                lexer.nextToken();\n                stmt.setPrivileges(true);\n            } else if (lexer.identifierEquals(\"OPTIMIZER_COSTS\")) {\n                lexer.nextToken();\n                stmt.setOptimizerCosts(true);\n            } else if (lexer.identifierEquals(\"QUERY\")) {\n                lexer.nextToken();\n                accept(Token.CACHE);\n                stmt.setQueryCache(true);\n            } else if (lexer.identifierEquals(\"RELAY\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOGS\");\n                stmt.setRelayLogs(true);\n                if (lexer.token() == Token.FOR) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"CHANNEL\");\n                    stmt.setRelayLogsForChannel(this.exprParser.primary());\n                }\n            } else if (lexer.identifierEquals(\"SLOW\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOGS\");\n                stmt.setSlowLogs(true);\n            } else if (lexer.identifierEquals(STATUS)) {\n                lexer.nextToken();\n                stmt.setStatus(true);\n            } else if (lexer.identifierEquals(\"USER_RESOURCES\")) {\n                lexer.nextToken();\n                stmt.setUserResources(true);\n            } else if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n        }\n\n        if (lexer.identifierEquals(\"TABLES\") || lexer.token() == TABLE) {\n            lexer.nextToken();\n\n            stmt.setTableOption(true);\n\n            if (lexer.token() == WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"READ\");\n                accept(Token.LOCK);\n                stmt.setWithReadLock(true);\n            }\n            for (; ; ) {\n                if (lexer.token() == Token.IDENTIFIER) {\n                    for (; ; ) {\n                        SQLName name = this.exprParser.name();\n                        stmt.addTable(name);\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    break;\n                }\n                break;\n            }\n\n            if (!stmt.getTables().isEmpty()) {\n                if (lexer.token() == Token.FOR) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"EXPORT\");\n                    stmt.setForExport(true);\n                } else if (lexer.token() == WITH) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"READ\");\n                    accept(Token.LOCK);\n                    stmt.setWithReadLock(true);\n                } else if (lexer.identifierEquals(FnvHash.Constants.VERSION)) {\n                    lexer.nextToken();\n                    accept(Token.EQ);\n                    stmt.setVersion(this.exprParser.integerExpr());\n                }\n            }\n\n        }\n\n        return stmt;\n    }\n\n    public SQLBeginStatement parseTiDBBeginStatment() {\n        SQLBeginStatement tidbBegin = new SQLBeginStatement();\n        tidbBegin.setDbType(dbType);\n        accept(Token.BEGIN);\n        if (lexer.token() == Token.IDENTIFIER) {\n            tidbBegin.setTidbTxnMode(this.exprParser.name());\n        }\n        return tidbBegin;\n    }\n\n    public SQLBlockStatement parseBlock() {\n        SQLBlockStatement block = new SQLBlockStatement();\n        block.setDbType(dbType);\n\n        accept(Token.BEGIN);\n        List<SQLStatement> statementList = block.getStatementList();\n        this.parseStatementList(statementList, -1, block);\n\n        if (lexer.token() != Token.END\n                && statementList.size() > 0\n                && (statementList.get(statementList.size() - 1) instanceof SQLCommitStatement\n                || statementList.get(statementList.size() - 1) instanceof SQLRollbackStatement)) {\n            block.setEndOfCommit(true);\n            return block;\n        }\n        accept(Token.END);\n\n        return block;\n    }\n\n    public MySqlExplainStatement parseDescribe() {\n        // see https://dev.mysql.com/doc/refman/5.7/en/explain.html\n        MySqlExplainStatement describe = new MySqlExplainStatement();\n\n        // {DESCRIBE | DESC}\n        if (lexer.token() == Token.DESC || lexer.identifierEquals(DESCRIBE)) {\n            lexer.nextToken();\n            describe.setDescribe(true);\n        } else {\n            throw new ParserException(\"expect one of {DESCRIBE | DESC} , actual \" + lexer.token() + \", \" + lexer.info());\n        }\n\n        return parseExplain(describe);\n    }\n\n    public MySqlExplainStatement parseExplain() {\n        // see https://dev.mysql.com/doc/refman/5.7/en/explain.html\n        MySqlExplainStatement explain = new MySqlExplainStatement();\n        lexer.computeRowAndColumn(explain);\n\n        // {EXPLAIN}\n        if (lexer.token() == Token.EXPLAIN) {\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"expect EXPLAIN , actual \" + lexer.token() + \", \" + lexer.info());\n        }\n\n        return parseExplain(explain);\n    }\n\n    private MySqlExplainStatement parseExplain(MySqlExplainStatement explain) {\n        if (lexer.identifierEquals(FnvHash.Constants.PLAN)) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        if (lexer.token() == Token.ANALYZE) {\n            lexer.nextToken();\n            explain.setType(\"ANALYZE\");\n        }\n\n        if (lexer.token() == Token.HINT) {\n            List<SQLCommentHint> hints = this.exprParser.parseHints();\n            explain.setHints(hints);\n        }\n        // see https://dev.mysql.com/doc/refman/5.7/en/explain.html\n\n        switch (dbType) {\n            case mysql:\n            case ads:\n            case supersql:\n            case presto:\n            case trino:\n                Lexer.SavePoint mark = lexer.mark();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.SELECT) {\n                        lexer.reset(mark);\n                        break;\n                    }\n\n                    for (; ; ) {\n                        if (lexer.identifierEquals(\"FORMAT\")) {\n                            lexer.nextToken();\n                            String format = lexer.stringVal();\n                            explain.setFormat(format);\n                            lexer.nextToken();\n                        } else if (lexer.identifierEquals(\"TYPE\")) {\n                            lexer.nextToken();\n                            String type = lexer.stringVal();\n                            explain.setType(type);\n                            lexer.nextToken();\n                        } else {\n                            break;\n                        }\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        } else {\n                            break;\n                        }\n                    }\n                    accept(Token.RPAREN);\n                    explain.setParenthesis(true);\n                }\n                break;\n            default:\n                break;\n        }\n\n        boolean table = false;\n        if (lexer.token() == Token.IDENTIFIER) {\n            final long hash = lexer.hashLCase();\n            String stringVal = lexer.stringVal();\n\n            if (hash == FnvHash.Constants.EXTENDED) {\n                explain.setExtended(true);\n                lexer.nextToken();\n            } else if (hash == FnvHash.Constants.PARTITIONS) {\n                explain.setType(stringVal);\n                lexer.nextToken();\n            } else if (hash == FnvHash.Constants.OPTIMIZER) {\n                explain.setOptimizer(true);\n                lexer.nextToken();\n            } else if (hash == FnvHash.Constants.FORMAT) {\n                lexer.nextToken();\n                accept(Token.EQ);\n\n                String format = lexer.stringVal();\n                explain.setFormat(format);\n                accept(Token.IDENTIFIER);\n            } else {\n                explain.setTableName(exprParser.name());\n                if (lexer.token() == Token.IDENTIFIER) {\n                    explain.setColumnName(exprParser.name());\n                } else if (lexer.token() == Token.LITERAL_CHARS) {\n                    explain.setWild(exprParser.expr());\n                }\n                table = true;\n            }\n        }\n\n        if (lexer.token() == Token.DISTRIBUTE) {\n            lexer.nextToken();\n            acceptIdentifier(\"INFO\");\n            explain.setDistributeInfo(true);\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n            acceptIdentifier(CONNECTION);\n            explain.setConnectionId(exprParser.expr());\n        } else if (!table) {\n            explain.setStatement(this.parseStatement());\n        }\n\n        return explain;\n    }\n\n    public SQLStatement parseShow() {\n        accept(Token.SHOW);\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n        }\n\n        boolean isPhysical = false;\n\n        if (lexer.identifierEquals(FnvHash.Constants.PHYSICAL)) {\n            lexer.nextToken();\n            isPhysical = true;\n        }\n\n        boolean full = false;\n        if (lexer.token() == Token.FULL) {\n            lexer.nextToken();\n            full = true;\n        } else if (lexer.token() == Token.HINT) {\n            String hints = lexer.stringVal().toLowerCase();\n            if (hints.endsWith(\" full\")\n                    && hints.length() <= 11\n                    && hints.charAt(0) == '!'\n                    && hints.charAt(1) == '5') {\n                lexer.nextToken();\n                full = true;\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STATS)) {\n            lexer.nextToken();\n            SQLShowStatisticStmt showStats = new SQLShowStatisticStmt();\n            showStats.setDbType(DbType.mysql);\n            if (full) {\n                showStats.setFull(true);\n            }\n            return showStats;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PROCESSLIST)) {\n            lexer.nextToken();\n            MySqlShowProcessListStatement stmt = new MySqlShowProcessListStatement();\n            stmt.setFull(full);\n\n            if (!full) {\n                if (lexer.identifierEquals(FnvHash.Constants.MPP)) {\n                    lexer.nextToken();\n                    stmt.setMpp(true);\n                }\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(\n                        this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                stmt.setOrderBy(\n                        this.exprParser.parseOrderBy());\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                stmt.setLimit(\n                        this.exprParser.parseLimit());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"COLUMNS\") || lexer.identifierEquals(\"FIELDS\")) {\n            lexer.nextToken();\n\n            SQLShowColumnsStatement stmt = parseShowColumns();\n            stmt.setFull(full);\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"COLUMNS\")) {\n            lexer.nextToken();\n\n            SQLShowColumnsStatement stmt = parseShowColumns();\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(TABLES)) {\n            lexer.nextToken();\n\n            SQLShowTablesStatement stmt = parseShowTables();\n            stmt.setFull(full);\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"DATABASES\")) {\n            lexer.nextToken();\n\n            SQLShowDatabasesStatement stmt = parseShowDatabases(isPhysical);\n\n            if (full) {\n                stmt.setFull(true);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"WARNINGS\")) {\n            lexer.nextToken();\n\n            MySqlShowWarningsStatement stmt = parseShowWarnings();\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"COUNT\")) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            accept(Token.STAR);\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(FnvHash.Constants.ERRORS)) {\n                lexer.nextToken();\n\n                MySqlShowErrorsStatement stmt = new MySqlShowErrorsStatement();\n                stmt.setCount(true);\n\n                return stmt;\n            } else {\n                acceptIdentifier(\"WARNINGS\");\n\n                MySqlShowWarningsStatement stmt = new MySqlShowWarningsStatement();\n                stmt.setCount(true);\n\n                return stmt;\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ERRORS)) {\n            lexer.nextToken();\n\n            MySqlShowErrorsStatement stmt = new MySqlShowErrorsStatement();\n            stmt.setLimit(this.exprParser.parseLimit());\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(STATUS)) {\n            lexer.nextToken();\n\n            MySqlShowStatusStatement stmt = parseShowStatus();\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(DBLOCK)) {\n            lexer.nextToken();\n\n            return new MysqlShowDbLockStatement();\n        }\n\n        if (lexer.identifierEquals(VARIABLES)) {\n            lexer.nextToken();\n\n            SQLShowVariantsStatement stmt = parseShowVariants();\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(GLOBAL)) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(STATUS)) {\n                lexer.nextToken();\n                MySqlShowStatusStatement stmt = parseShowStatus();\n                stmt.setGlobal(true);\n                return stmt;\n            }\n\n            if (lexer.identifierEquals(VARIABLES)) {\n                lexer.nextToken();\n                SQLShowVariantsStatement stmt = parseShowVariants();\n                stmt.setGlobal(true);\n                return stmt;\n            }\n\n            // DRDS GSI syntax.\n            if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && (INDEX == lexer.token() || lexer.identifierEquals(\"INDEXES\"))) {\n                lexer.nextToken();\n\n                DrdsShowGlobalIndex stmt = new DrdsShowGlobalIndex();\n                if (Token.FROM == lexer.token()) {\n                    lexer.nextToken();\n                    stmt.setTableName(this.exprParser.name());\n                }\n                return stmt;\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SESSION)) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(STATUS)) {\n                lexer.nextToken();\n                MySqlShowStatusStatement stmt = parseShowStatus();\n                stmt.setSession(true);\n                return stmt;\n            }\n\n            if (lexer.identifierEquals(VARIABLES)) {\n                lexer.nextToken();\n                SQLShowVariantsStatement stmt = parseShowVariants();\n                stmt.setSession(true);\n                return stmt;\n            }\n\n            SQLShowSessionStatement stmt = new SQLShowSessionStatement();\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextToken();\n                SQLExpr like = this.exprParser.expr();\n                stmt.setLike(like);\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"COBAR_STATUS\")) {\n            lexer.nextToken();\n            return new CobarShowStatus();\n        }\n\n        if (lexer.identifierEquals(\"AUTHORS\")) {\n            lexer.nextToken();\n            return new MySqlShowAuthorsStatement();\n        }\n\n        if (lexer.token() == Token.BINARY) {\n            lexer.nextToken();\n            acceptIdentifier(\"LOGS\");\n            return new MySqlShowBinaryLogsStatement();\n        }\n\n        if (lexer.identifierEquals(\"MASTER\")) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"LOGS\")) {\n                lexer.nextToken();\n                return new MySqlShowMasterLogsStatement();\n            }\n            acceptIdentifier(STATUS);\n            return new MySqlShowMasterStatusStatement();\n        }\n\n        if (lexer.identifierEquals(\"CLUSTER\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"NAME\");\n            return new MySqlShowClusterNameStatement();\n        }\n\n        if (lexer.identifierEquals(\"SYNC_JOB\")) {\n            lexer.nextToken();\n            acceptIdentifier(STATUS);\n            MySqlShowJobStatusStatement stmt = new MySqlShowJobStatusStatement();\n            stmt.setSync(true);\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n        if (lexer.identifierEquals(\"JOB\")) {\n            lexer.nextToken();\n            acceptIdentifier(STATUS);\n\n            MySqlShowJobStatusStatement stmt = new MySqlShowJobStatusStatement();\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n        if (lexer.identifierEquals(\"MIGRATE\")) {\n            lexer.nextToken();\n\n            acceptIdentifier(\"TASK\");\n            acceptIdentifier(STATUS);\n\n            MySqlShowMigrateTaskStatusStatement stmt = new MySqlShowMigrateTaskStatusStatement();\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARSET)) {\n            lexer.nextToken();\n\n            MySqlShowCharacterSetStatement stmt = new MySqlShowCharacterSetStatement();\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setPattern(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n            lexer.nextToken();\n            accept(Token.SET);\n            MySqlShowCharacterSetStatement stmt = new MySqlShowCharacterSetStatement();\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setPattern(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"COLLATION\")) {\n            lexer.nextToken();\n            MySqlShowCollationStatement stmt = new MySqlShowCollationStatement();\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setPattern(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(BINLOG)) {\n            lexer.nextToken();\n            acceptIdentifier(EVENTS);\n            MySqlShowBinLogEventsStatement stmt = new MySqlShowBinLogEventsStatement();\n\n            if (lexer.token() == Token.IN) {\n                lexer.nextToken();\n                stmt.setIn(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n                stmt.setFrom(this.exprParser.expr());\n            }\n\n            stmt.setLimit(this.exprParser.parseLimit());\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"CONTRIBUTORS\")) {\n            lexer.nextToken();\n            return new MySqlShowContributorsStatement();\n        }\n\n        if (lexer.token() == Token.ALL) {\n            lexer.nextToken();\n            accept(Token.CREATE);\n            accept(TABLE);\n\n            SQLShowCreateTableStatement stmt = new SQLShowCreateTableStatement();\n            stmt.setAll(true);\n            stmt.setName(this.exprParser.name());\n            return stmt;\n        }\n\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.DATABASE || lexer.token() == Token.SCHEMA) {\n                lexer.nextToken();\n\n                MySqlShowCreateDatabaseStatement stmt = new MySqlShowCreateDatabaseStatement();\n                if (lexer.token() == Token.IF) {\n                    lexer.nextToken();\n                    accept(Token.NOT);\n                    accept(Token.EXISTS);\n                    stmt.setIfNotExists(true);\n                }\n                stmt.setDatabase(this.exprParser.name());\n                return stmt;\n            }\n\n            if (lexer.identifierEquals(\"EVENT\")) {\n                lexer.nextToken();\n\n                MySqlShowCreateEventStatement stmt = new MySqlShowCreateEventStatement();\n                stmt.setEventName(this.exprParser.name());\n                return stmt;\n            }\n\n            if (lexer.token() == Token.FUNCTION) {\n                lexer.nextToken();\n\n                MySqlShowCreateFunctionStatement stmt = new MySqlShowCreateFunctionStatement();\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n\n            if (lexer.token() == Token.PROCEDURE) {\n                lexer.nextToken();\n\n                MySqlShowCreateProcedureStatement stmt = new MySqlShowCreateProcedureStatement();\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n            if (lexer.token() == TABLE) {\n                lexer.nextToken();\n                SQLShowCreateTableStatement stmt = new SQLShowCreateTableStatement();\n\n                if (lexer.token() != Token.LIKE) {\n                    stmt.setName(this.exprParser.name());\n                }\n\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.MAPPING)) {\n                        lexer.nextToken();\n                        accept(Token.LPAREN);\n                        SQLName name = this.exprParser.name();\n                        stmt.setLikeMapping(name);\n                        accept(Token.RPAREN);\n                    }\n                }\n\n                return stmt;\n            }\n\n            if (lexer.token() == Token.VIEW) {\n                lexer.nextToken();\n\n                SQLShowCreateViewStatement stmt = new SQLShowCreateViewStatement();\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n\n            if (lexer.token() == Token.TRIGGER) {\n                lexer.nextToken();\n\n                MySqlShowCreateTriggerStatement stmt = new MySqlShowCreateTriggerStatement();\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n\n            if (lexer.token() == Token.FULLTEXT) {\n                lexer.nextToken();\n                MysqlShowCreateFullTextStatement stmt = new MysqlShowCreateFullTextStatement();\n\n                stmt.setType(parseFullTextType());\n\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n\n            if (lexer.identifierEquals(\"MATERIALIZED\")) {\n                lexer.nextToken();\n                SQLShowCreateMaterializedViewStatement stmt = new SQLShowCreateMaterializedViewStatement();\n                accept(VIEW);\n\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n\n        if (lexer.identifierEquals(ENGINE)) {\n            lexer.nextToken();\n            MySqlShowEngineStatement stmt = new MySqlShowEngineStatement();\n            stmt.setName(this.exprParser.name());\n            stmt.setOption(MySqlShowEngineStatement.Option.valueOf(lexer.stringVal().toUpperCase()));\n            lexer.nextToken();\n            return stmt;\n        }\n\n        if (lexer.token() == Token.DATABASE || lexer.identifierEquals(FnvHash.Constants.DB)) {\n            lexer.nextToken();\n\n            MySqlShowDatabaseStatusStatement stmt = new MySqlShowDatabaseStatusStatement();\n\n            if (full) {\n                stmt.setFull(true);\n            }\n\n            if (lexer.identifierEquals(\"STATUS\")) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextTokenValue();\n                    stmt.setName(this.exprParser.name());\n                } else {\n                    if (lexer.token() == Token.WHERE) {\n                        lexer.nextToken();\n                        SQLExpr where = exprParser.expr();\n                        stmt.setWhere(where);\n                    }\n\n                    if (lexer.token() == Token.ORDER) {\n                        SQLOrderBy orderBy = exprParser.parseOrderBy();\n                        stmt.setOrderBy(orderBy);\n                    }\n\n                    if (lexer.token() == Token.LIMIT) {\n                        SQLLimit limit = exprParser.parseLimit();\n                        stmt.setLimit(limit);\n                    }\n                }\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"STORAGE\")) {\n            lexer.nextToken();\n            acceptIdentifier(ENGINES);\n            MySqlShowEnginesStatement stmt = new MySqlShowEnginesStatement();\n            stmt.setStorage(true);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(ENGINES)) {\n            lexer.nextToken();\n            MySqlShowEnginesStatement stmt = new MySqlShowEnginesStatement();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(EVENTS)) {\n            lexer.nextToken();\n            MySqlShowEventsStatement stmt = new MySqlShowEventsStatement();\n\n            if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                lexer.nextToken();\n                stmt.setSchema(this.exprParser.name());\n            }\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setLike(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        if (lexer.token() == Token.FUNCTION) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"CODE\")) {\n                lexer.nextToken();\n                MySqlShowFunctionCodeStatement stmt = new MySqlShowFunctionCodeStatement();\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n\n            acceptIdentifier(STATUS);\n            MySqlShowFunctionStatusStatement stmt = new MySqlShowFunctionStatusStatement();\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setLike(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        // MySqlShowFunctionStatusStatement\n\n        if (lexer.identifierEquals(ENGINE)) {\n            lexer.nextToken();\n            MySqlShowEngineStatement stmt = new MySqlShowEngineStatement();\n            stmt.setName(this.exprParser.name());\n            stmt.setOption(MySqlShowEngineStatement.Option.valueOf(lexer.stringVal().toUpperCase()));\n            lexer.nextToken();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"STORAGE\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            accept(Token.DEFAULT);\n            MySqlShowEnginesStatement stmt = new MySqlShowEnginesStatement();\n            stmt.setStorage(true);\n            return stmt;\n        }\n\n//        if (lexer.identifierEquals(\"KEYS\") || lexer.token() == Token.INDEX) {\n//            lexer.nextToken();\n//            accept(Token.FROM);\n//            MySqlShowKeysStatement stmt = new MySqlShowKeysStatement();\n//            stmt.setTable(exprParser.name());\n//            return stmt;\n//        }\n\n        if (lexer.identifierEquals(\"GRANTS\")) {\n            lexer.nextToken();\n            MySqlShowGrantsStatement stmt = new MySqlShowGrantsStatement();\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                stmt.setUser(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                SQLExpr on = this.exprParser.expr();\n                stmt.setOn(on);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.token() == INDEX || lexer.identifierEquals(\"INDEXES\") || lexer.identifierEquals(\"KEYS\")) {\n            SQLShowIndexesStatement stmt = new SQLShowIndexesStatement();\n\n            stmt.setType(lexer.stringVal());\n            lexer.nextToken();\n\n            if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                lexer.nextToken();\n                SQLName table = exprParser.name();\n                stmt.setTable(table);\n\n                if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                    lexer.nextToken();\n                    SQLName database = exprParser.name();\n                    stmt.setDatabase(database.toString());\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = exprParser.expr();\n                    stmt.setWhere(where);\n                }\n            }\n\n            if (lexer.token() == Token.HINT) {\n                stmt.setHints(this.exprParser.parseHints());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.token() == Token.OPEN || lexer.identifierEquals(\"OPEN\")) {\n            lexer.nextToken();\n            acceptIdentifier(TABLES);\n            MySqlShowOpenTablesStatement stmt = new MySqlShowOpenTablesStatement();\n\n            if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                lexer.nextToken();\n                stmt.setDatabase(this.exprParser.name());\n            }\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setLike(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"PLUGINS\")) {\n            lexer.nextToken();\n            MySqlShowPluginsStatement stmt = new MySqlShowPluginsStatement();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"HTC\")) {\n            lexer.nextToken();\n            MysqlShowHtcStatement stmt = new MysqlShowHtcStatement();\n            stmt.setFull(false);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"HMSMETA\")) {\n            lexer.nextToken();\n            SQLName name = this.exprParser.name();\n\n            MySqlShowHMSMetaStatement stmt = new MySqlShowHMSMetaStatement();\n            stmt.setName(name);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"STC\")) {\n            lexer.nextToken();\n            MysqlShowStcStatement stmt = new MysqlShowStcStatement();\n            if (lexer.identifierEquals(\"HIS\")) {\n                lexer.nextToken();\n                stmt.setHis(true);\n            } else {\n                stmt.setHis(false);\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"PRIVILEGES\")) {\n            lexer.nextToken();\n            MySqlShowPrivilegesStatement stmt = new MySqlShowPrivilegesStatement();\n            return stmt;\n        }\n\n        if (lexer.token() == Token.PROCEDURE) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"CODE\")) {\n                lexer.nextToken();\n                MySqlShowProcedureCodeStatement stmt = new MySqlShowProcedureCodeStatement();\n                stmt.setName(this.exprParser.name());\n                return stmt;\n            }\n\n            acceptIdentifier(STATUS);\n            MySqlShowProcedureStatusStatement stmt = new MySqlShowProcedureStatusStatement();\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setLike(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"PROFILES\")) {\n            lexer.nextToken();\n            MySqlShowProfilesStatement stmt = new MySqlShowProfilesStatement();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"PROFILE\")) {\n            lexer.nextToken();\n            MySqlShowProfileStatement stmt = new MySqlShowProfileStatement();\n\n            for (; ; ) {\n                if (lexer.token() == Token.ALL) {\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.ALL);\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(\"BLOCK\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"IO\");\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.BLOCK_IO);\n                } else if (lexer.identifierEquals(\"CONTEXT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"SWITCHES\");\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.CONTEXT_SWITCHES);\n                } else if (lexer.identifierEquals(\"CPU\")) {\n                    lexer.nextToken();\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.CPU);\n                } else if (lexer.identifierEquals(\"IPC\")) {\n                    lexer.nextToken();\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.IPC);\n                } else if (lexer.identifierEquals(\"MEMORY\")) {\n                    lexer.nextToken();\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.MEMORY);\n                } else if (lexer.identifierEquals(\"PAGE\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"FAULTS\");\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.PAGE_FAULTS);\n                } else if (lexer.identifierEquals(\"SOURCE\")) {\n                    lexer.nextToken();\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.SOURCE);\n                } else if (lexer.identifierEquals(\"SWAPS\")) {\n                    lexer.nextToken();\n                    stmt.getTypes().add(MySqlShowProfileStatement.Type.SWAPS);\n                } else {\n                    break;\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                acceptIdentifier(\"QUERY\");\n                stmt.setForQuery(this.exprParser.primary());\n            }\n\n            stmt.setLimit(this.exprParser.parseLimit());\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"RELAYLOG\")) {\n            lexer.nextToken();\n            acceptIdentifier(EVENTS);\n            MySqlShowRelayLogEventsStatement stmt = new MySqlShowRelayLogEventsStatement();\n\n            if (lexer.token() == Token.IN) {\n                lexer.nextToken();\n                stmt.setLogName(this.exprParser.primary());\n            }\n\n            if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n                stmt.setFrom(this.exprParser.primary());\n            }\n\n            stmt.setLimit(this.exprParser.parseLimit());\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"RELAYLOG\")) {\n            lexer.nextToken();\n            acceptIdentifier(EVENTS);\n            MySqlShowRelayLogEventsStatement stmt = new MySqlShowRelayLogEventsStatement();\n\n            if (lexer.token() == Token.IN) {\n                lexer.nextToken();\n                stmt.setLogName(this.exprParser.primary());\n            }\n\n            if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n                stmt.setFrom(this.exprParser.primary());\n            }\n\n            stmt.setLimit(this.exprParser.parseLimit());\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"SLAVE\")) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(STATUS)) {\n                lexer.nextToken();\n                return new MySqlShowSlaveStatusStatement();\n            } else {\n                acceptIdentifier(\"HOSTS\");\n                MySqlShowSlaveHostsStatement stmt = new MySqlShowSlaveHostsStatement();\n                return stmt;\n            }\n        }\n\n        if (lexer.token() == TABLE) {\n            lexer.nextToken();\n            acceptIdentifier(STATUS);\n            MySqlShowTableStatusStatement stmt = new MySqlShowTableStatusStatement();\n            if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                lexer.nextToken();\n\n                SQLName name = this.exprParser.name();\n                if (name instanceof SQLPropertyExpr) {\n                    stmt.setDatabase((SQLIdentifierExpr) ((SQLPropertyExpr) name).getOwner());\n                    stmt.setTableGroup(new SQLIdentifierExpr(((SQLPropertyExpr) name).getName()));\n                } else {\n                    stmt.setDatabase(name);\n                }\n            }\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                stmt.setLike(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"TRIGGERS\")) {\n            lexer.nextToken();\n            MySqlShowTriggersStatement stmt = new MySqlShowTriggersStatement();\n\n            if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                lexer.nextToken();\n                SQLName database = exprParser.name();\n                stmt.setDatabase(database);\n            }\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextTokenValue();\n                SQLExpr like = exprParser.expr();\n                stmt.setLike(like);\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.BROADCASTS)) {\n            lexer.nextToken();\n            MySqlShowBroadcastsStatement stmt = new MySqlShowBroadcastsStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DATASOURCES)) {\n            lexer.nextToken();\n            MySqlShowDatasourcesStatement stmt = new MySqlShowDatasourcesStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.NODE)) {\n            lexer.nextToken();\n            MySqlShowNodeStatement stmt = new MySqlShowNodeStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.HELP)) {\n            lexer.nextToken();\n            MySqlShowHelpStatement stmt = new MySqlShowHelpStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.token() == Token.SEQUENCE || lexer.identifierEquals(FnvHash.Constants.SEQUENCES)) {\n            lexer.nextToken();\n            MySqlShowSequencesStatement stmt = new MySqlShowSequencesStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"PARTITIONS\")) {\n            lexer.nextToken();\n            SQLShowPartitionsStmt stmt = new SQLShowPartitionsStmt();\n\n            if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n            }\n\n            SQLName name = exprParser.name();\n            stmt.setTableSource(name);\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                parseAssignItems(stmt.getPartition(), stmt, false);\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(\n                        this.exprParser.expr()\n                );\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"RULE\")) {\n            lexer.nextToken();\n\n            boolean version = false;\n            if (lexer.identifierEquals(FnvHash.Constants.VERSION)) {\n                version = true;\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.FULL) || lexer.token() == Token.FULL) {\n                full = true;\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.STATUS)) {\n                lexer.nextToken();\n                MySqlShowRuleStatusStatement stmt = new MySqlShowRuleStatusStatement();\n\n                if (full) {\n                    stmt.setFull(full);\n                }\n\n                if (version) {\n                    stmt.setVersion(true);\n                }\n\n                if (lexer.token() == Token.FROM) {\n                    lexer.nextToken();\n                }\n\n                if (full) {\n                    stmt.setLite(false);\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = exprParser.expr();\n                    stmt.setWhere(where);\n                }\n\n                if (lexer.token() == Token.ORDER) {\n                    SQLOrderBy orderBy = exprParser.parseOrderBy();\n                    stmt.setOrderBy(orderBy);\n                }\n\n                if (lexer.token() == Token.LIMIT) {\n                    SQLLimit limit = exprParser.parseLimit();\n                    stmt.setLimit(limit);\n                }\n\n                return stmt;\n            } else {\n                MySqlShowRuleStatement stmt = new MySqlShowRuleStatement();\n\n                if (full) {\n                    stmt.setFull(full);\n                }\n\n                if (version) {\n                    stmt.setVersion(true);\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.VERSION)) {\n                    lexer.nextToken();\n                    stmt.setVersion(true);\n                }\n\n                if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                    return stmt;\n                }\n\n                if (lexer.token() == Token.FROM) {\n                    lexer.nextToken();\n\n                    stmt.setName(exprParser.name());\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = exprParser.expr();\n                    stmt.setWhere(where);\n                }\n\n                if (lexer.token() == Token.ORDER) {\n                    SQLOrderBy orderBy = exprParser.parseOrderBy();\n                    stmt.setOrderBy(orderBy);\n                }\n\n                if (lexer.token() == Token.LIMIT) {\n                    SQLLimit limit = exprParser.parseLimit();\n                    stmt.setLimit(limit);\n                }\n                return stmt;\n            }\n\n        }\n\n        if (lexer.identifierEquals(\"DS\")) {\n            lexer.nextToken();\n            MySqlShowDsStatement stmt = new MySqlShowDsStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"DDL\")) {\n            lexer.nextToken();\n\n            // DRDS async DDL.\n            if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && !lexer.identifierEquals(\"STATUS\")) {\n                // SHOW [FULL] DDL.\n                DrdsShowDDLJobs showDDLJobs = new DrdsShowDDLJobs();\n                showDDLJobs.setFull(full);\n\n                while (lexer.token() != Token.EOF && lexer.token() != SEMI) {\n                    showDDLJobs.addJobId(lexer.integerValue().longValue());\n                    accept(Token.LITERAL_INT);\n                    if (Token.COMMA == lexer.token()) {\n                        lexer.nextToken();\n                    } else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                        break;\n                    } else {\n                        throw new ParserException(\"syntax error, expect job id, actual \" + lexer.token() + \", \" + lexer.info());\n                    }\n                }\n                return showDDLJobs;\n            }\n\n            acceptIdentifier(\"STATUS\");\n            MySqlShowDdlStatusStatement stmt = new MySqlShowDdlStatusStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"TRACE\")) {\n            lexer.nextToken();\n            MySqlShowTraceStatement stmt = new MySqlShowTraceStatement();\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"TOPOLOGY\")) {\n            lexer.nextToken();\n            MySqlShowTopologyStatement stmt = new MySqlShowTopologyStatement();\n\n            if (lexer.token() == Token.FROM) {\n                lexer.nextToken();\n            }\n            stmt.setName(exprParser.name());\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            stmt.setFull(full);\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PLANCACHE)) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.STATUS)) {\n                lexer.nextToken();\n                return new MySqlShowPlanCacheStatusStatement();\n            } else if (lexer.identifierEquals(FnvHash.Constants.PLAN)) {\n                lexer.nextToken();\n                SQLSelect select = this.createSQLSelectParser().select();\n                return new MySqlShowPlanCacheStatement(select);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SLOW)) {\n            MySqlShowSlowStatement stmt = parserShowSlow();\n            stmt.setPhysical(false);\n            stmt.setFull(full);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"PHYSICAL_SLOW\")) {\n            MySqlShowSlowStatement stmt = parserShowSlow();\n            stmt.setPhysical(true);\n            stmt.setFull(full);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.QUERY_TASK)) {\n            lexer.nextToken();\n            SQLShowQueryTaskStatement stmt = new SQLShowQueryTaskStatement();\n            stmt.setDbType(dbType);\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                stmt.setUser(\n                        exprParser.expr()\n                );\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = this.exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = this.exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = this.exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            if (full) {\n                stmt.setFull(true);\n            }\n\n            return stmt;\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.OUTLINES)) {\n            lexer.nextToken();\n            SQLShowOutlinesStatement stmt = new SQLShowOutlinesStatement();\n            stmt.setDbType(dbType);\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = this.exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n            if (lexer.token() == Token.ORDER) {\n                SQLOrderBy orderBy = this.exprParser.parseOrderBy();\n                stmt.setOrderBy(orderBy);\n            }\n\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = this.exprParser.parseLimit();\n                stmt.setLimit(limit);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RECYCLEBIN)) {\n            lexer.nextToken();\n\n            SQLShowRecylebinStatement stmt = new SQLShowRecylebinStatement();\n            stmt.setDbType(dbType);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TABLEGROUPS)) {\n            lexer.nextToken();\n\n            SQLShowTableGroupsStatement stmt = parseShowTableGroups();\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CATALOGS)) {\n            lexer.nextToken();\n\n            SQLShowCatalogsStatement stmt = new SQLShowCatalogsStatement();\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextToken();\n                SQLExpr like = this.exprParser.expr();\n                stmt.setLike(like);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n            lexer.nextToken();\n\n            SQLShowFunctionsStatement stmt = new SQLShowFunctionsStatement();\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextToken();\n                SQLExpr like = this.exprParser.expr();\n                stmt.setLike(like);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SCHEMAS)) {\n            lexer.nextToken();\n\n            SQLShowDatabasesStatement stmt = new SQLShowDatabasesStatement();\n            stmt.setPhysical(isPhysical);\n            if (lexer.token() == Token.IN || lexer.token() == Token.FROM) {\n                lexer.nextToken();\n                SQLName db = this.exprParser.name();\n                stmt.setDatabase(db);\n            }\n\n            if (full) {\n                stmt.setFull(true);\n            }\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextToken();\n                SQLExpr like = this.exprParser.expr();\n                stmt.setLike(like);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CONFIG)) {\n            lexer.nextToken();\n            SQLName name = this.exprParser.name();\n            MySqlShowConfigStatement stmt = new MySqlShowConfigStatement();\n            stmt.setName(name);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USERS)) {\n            lexer.nextToken();\n            SQLShowUsersStatement stmt = new SQLShowUsersStatement();\n            stmt.setDbType(dbType);\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PHYSICAL_PROCESSLIST)) {\n            lexer.nextToken();\n\n            MySqlShowPhysicalProcesslistStatement stmt = new MySqlShowPhysicalProcesslistStatement();\n            if (full) {\n                stmt.setFull(full);\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"MATERIALIZED\")) {\n            return parseShowMaterializedView();\n        }\n\n        if (lexer.token() == Token.FULLTEXT) {\n            lexer.nextToken();\n\n            MysqlShowFullTextStatement stmt = new MysqlShowFullTextStatement();\n\n            if (lexer.identifierEquals(FnvHash.Constants.CHARFILTERS)) {\n                stmt.setType(FullTextType.CHARFILTER);\n            } else if (lexer.identifierEquals(FnvHash.Constants.TOKENIZERS)) {\n                stmt.setType(FullTextType.TOKENIZER);\n            } else if (lexer.identifierEquals(FnvHash.Constants.TOKENFILTERS)) {\n                stmt.setType(FullTextType.TOKENFILTER);\n            } else if (lexer.identifierEquals(FnvHash.Constants.ANALYZERS)) {\n                stmt.setType(FullTextType.ANALYZER);\n            } else if (lexer.identifierEquals(FnvHash.Constants.DICTIONARIES)) {\n                stmt.setType(FullTextType.DICTIONARY);\n            } else {\n                throw new ParserException(\"type of full text must be [CHARFILTERS/TOKENIZERS/TOKENFILTERS/ANALYZERS/DICTIONARYS] .\");\n            }\n\n            lexer.nextToken();\n\n            return stmt;\n        }\n\n        // DRDS GSI management syntax.\n        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(\"METADATA\")) {\n            lexer.nextToken();\n\n            if (Token.LOCK == lexer.token() || lexer.identifierEquals(\"LOCKS\")) {\n                lexer.nextToken();\n\n                DrdsShowMetadataLock stmt = new DrdsShowMetadataLock();\n                if (SEMI == lexer.token() || Token.EOF == lexer.token()) {\n                    return stmt;\n                } else {\n                    stmt.setSchemaName(this.exprParser.name());\n                    return stmt;\n                }\n            } else {\n                throw new ParserException(\"syntax error, expect LOCK/LOCKS, actual \" + lexer.token() + \", \" + lexer.info());\n            }\n        }\n\n        // MySqlShowSlaveHostsStatement\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    private MySqlShowStatusStatement parseShowStatus() {\n        MySqlShowStatusStatement stmt = new MySqlShowStatusStatement();\n\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            SQLExpr like = exprParser.expr();\n            stmt.setLike(like);\n        }\n\n        if (lexer.token() == Token.WHERE) {\n            lexer.nextToken();\n            SQLExpr where = exprParser.expr();\n            stmt.setWhere(where);\n        }\n\n        return stmt;\n    }\n\n    public MySqlShowSlowStatement parserShowSlow() {\n        lexer.nextToken();\n        MySqlShowSlowStatement stmt = new MySqlShowSlowStatement();\n\n        if (lexer.token() == Token.WHERE) {\n            lexer.nextToken();\n            SQLExpr where = exprParser.expr();\n            stmt.setWhere(where);\n        }\n\n        if (lexer.token() == Token.ORDER) {\n            SQLOrderBy orderBy = exprParser.parseOrderBy();\n            stmt.setOrderBy(orderBy);\n        }\n\n        if (lexer.token() == Token.LIMIT) {\n            SQLLimit limit = exprParser.parseLimit();\n            stmt.setLimit(limit);\n        }\n\n        return stmt;\n    }\n\n    private MySqlShowWarningsStatement parseShowWarnings() {\n        MySqlShowWarningsStatement stmt = new MySqlShowWarningsStatement();\n\n        stmt.setLimit(this.exprParser.parseLimit());\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseRollback() {\n        acceptIdentifier(\"ROLLBACK\");\n\n        // DRDS async DDL.\n        if (isEnabled(SQLParserFeature.DRDSAsyncDDL) && lexer.identifierEquals(\"DDL\")) {\n            // ROLLBACK DDL <job_id> [, <job_id>] ...\n            lexer.nextToken();\n            DrdsRollbackDDLJob stmt = new DrdsRollbackDDLJob();\n            while (true) {\n                stmt.addJobId(lexer.integerValue().longValue());\n                accept(Token.LITERAL_INT);\n                if (Token.COMMA == lexer.token()) {\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.EOF || lexer.token() == SEMI) {\n                    break;\n                } else {\n                    throw new ParserException(\"syntax error, expect job id, actual \" + lexer.token() + \", \" + lexer.info());\n                }\n            }\n            return stmt;\n        }\n\n        SQLRollbackStatement stmt = new SQLRollbackStatement();\n\n        if (lexer.identifierEquals(\"WORK\")) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.AND) {\n            lexer.nextToken();\n            if (lexer.token() == Token.NOT) {\n                lexer.nextToken();\n                acceptIdentifier(CHAIN);\n                stmt.setChain(Boolean.FALSE);\n            } else {\n                acceptIdentifier(CHAIN);\n                stmt.setChain(Boolean.TRUE);\n            }\n        }\n\n        if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"SAVEPOINT\")) {\n                lexer.nextToken();\n            }\n\n            stmt.setTo(this.exprParser.name());\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseCommit() {\n        acceptIdentifier(\"COMMIT\");\n\n        SQLCommitStatement stmt = new SQLCommitStatement();\n\n        if (lexer.identifierEquals(\"WORK\")) {\n            lexer.nextToken();\n            stmt.setWork(true);\n        }\n\n        if (lexer.token() == Token.AND) {\n            lexer.nextToken();\n            if (lexer.token() == Token.NOT) {\n                lexer.nextToken();\n                acceptIdentifier(CHAIN);\n                stmt.setChain(Boolean.FALSE);\n            } else {\n                acceptIdentifier(CHAIN);\n                stmt.setChain(Boolean.TRUE);\n            }\n        }\n\n        return stmt;\n    }\n\n    public SQLReplaceStatement parseReplace() {\n        SQLReplaceStatement stmt = new SQLReplaceStatement();\n        stmt.setDbType(DbType.mysql);\n\n        List<SQLCommentHint> list = new ArrayList<SQLCommentHint>();\n\n        while (lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(list);\n        }\n        stmt.setHeadHints(list);\n\n        accept(Token.REPLACE);\n        while (lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(stmt.getHints());\n        }\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {\n            stmt.setLowPriority(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DELAYED)) {\n            stmt.setDelayed(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n        }\n\n        SQLName tableName = exprParser.name();\n        stmt.setTableName(tableName);\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLAssignItem ptExpr = new SQLAssignItem();\n                ptExpr.setTarget(this.exprParser.name());\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                    SQLExpr ptValue = this.exprParser.expr();\n                    ptExpr.setValue(ptValue);\n                }\n                stmt.addPartition(ptExpr);\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                }\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            if (lexer.token() == Token.SELECT) {\n                SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n                stmt.setQuery(queryExpr);\n            } else {\n                this.exprParser.exprList(stmt.getColumns(), stmt);\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.VALUES || lexer.identifierEquals(\"VALUE\")) {\n            lexer.nextToken();\n\n            parseValueClause(stmt.getValuesList(), null, 0, stmt);\n        } else if (lexer.token() == Token.SELECT) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n            stmt.setQuery(queryExpr);\n        } else if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n\n            SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n            values.setParent(stmt);\n            stmt.getValuesList().add(values);\n            for (; ; ) {\n                stmt.addColumn(this.exprParser.name());\n                if (lexer.token() == Token.COLONEQ) {\n                    lexer.nextToken();\n                } else {\n                    accept(Token.EQ);\n                }\n                values.addValue(this.exprParser.expr());\n\n                if (lexer.token() == (Token.COMMA)) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n        } else if (lexer.token() == Token.LPAREN) {\n            SQLSelect select = this.createSQLSelectParser().select();\n            SQLQueryExpr queryExpr = new SQLQueryExpr(select);\n            stmt.setQuery(queryExpr);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseLoad() {\n        acceptIdentifier(\"LOAD\");\n\n        if (lexer.identifierEquals(\"DATA\")) {\n            SQLStatement stmt = parseLoadDataInFile();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"XML\")) {\n            SQLStatement stmt = parseLoadXml();\n            return stmt;\n        }\n\n        throw new ParserException(\"TODO. \" + lexer.info());\n    }\n\n    protected MySqlLoadXmlStatement parseLoadXml() {\n        acceptIdentifier(\"XML\");\n\n        MySqlLoadXmlStatement stmt = new MySqlLoadXmlStatement();\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {\n            stmt.setLowPriority(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"CONCURRENT\")) {\n            stmt.setConcurrent(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(LOCAL)) {\n            stmt.setLocal(true);\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"INFILE\");\n\n        SQLLiteralExpr fileName = (SQLLiteralExpr) exprParser.expr();\n        stmt.setFileName(fileName);\n\n        if (lexer.token() == Token.REPLACE) {\n            stmt.setReplicate(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            stmt.setIgnore(true);\n            lexer.nextToken();\n        }\n\n        accept(Token.INTO);\n        accept(TABLE);\n\n        SQLName tableName = exprParser.name();\n        stmt.setTableName(tableName);\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n            lexer.nextToken();\n            accept(Token.SET);\n\n            if (lexer.token() != Token.LITERAL_CHARS) {\n                throw new ParserException(\"syntax error, illegal charset. \" + lexer.info());\n            }\n\n            String charset = lexer.stringVal();\n            lexer.nextToken();\n            stmt.setCharset(charset);\n        }\n\n        if (lexer.identifierEquals(\"ROWS\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"IDENTIFIED\");\n            accept(Token.BY);\n            SQLExpr rowsIdentifiedBy = exprParser.expr();\n            stmt.setRowsIdentifiedBy(rowsIdentifiedBy);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        if (lexer.token() == Token.SET) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        return stmt;\n    }\n\n    protected MySqlLoadDataInFileStatement parseLoadDataInFile() {\n        acceptIdentifier(\"DATA\");\n\n        MySqlLoadDataInFileStatement stmt = new MySqlLoadDataInFileStatement();\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {\n            stmt.setLowPriority(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"CONCURRENT\")) {\n            stmt.setConcurrent(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(LOCAL)) {\n            stmt.setLocal(true);\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"INFILE\");\n\n        SQLLiteralExpr fileName = (SQLLiteralExpr) exprParser.expr();\n        stmt.setFileName(fileName);\n\n        if (lexer.token() == Token.REPLACE) {\n            stmt.setReplicate(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            stmt.setIgnore(true);\n            lexer.nextToken();\n        }\n\n        accept(Token.INTO);\n        accept(TABLE);\n\n        SQLName tableName = exprParser.name();\n        stmt.setTableName(tableName);\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n            lexer.nextToken();\n            accept(Token.SET);\n\n            if (lexer.token() != Token.LITERAL_CHARS) {\n                throw new ParserException(\"syntax error, illegal charset. \" + lexer.info());\n            }\n\n            String charset = lexer.stringVal();\n            lexer.nextToken();\n            stmt.setCharset(charset);\n        }\n\n        if (lexer.identifierEquals(\"FIELDS\") || lexer.identifierEquals(\"COLUMNS\")) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"TERMINATED\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    stmt.setColumnsTerminatedBy(new SQLCharExpr(lexer.stringVal()));\n                    lexer.nextToken();\n                } else {\n                    SQLExpr primary = this.exprParser.primary();\n                    if (primary instanceof SQLHexExpr) {\n                        stmt.setColumnsTerminatedBy((SQLHexExpr) primary);\n                    } else {\n                        throw new ParserException(\"invalid expr for columns terminated : \" + primary);\n                    }\n                }\n            }\n\n            if (lexer.identifierEquals(\"OPTIONALLY\")) {\n                stmt.setColumnsEnclosedOptionally(true);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"ENCLOSED\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n                stmt.setColumnsEnclosedBy(new SQLCharExpr(lexer.stringVal()));\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"ESCAPED\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n                stmt.setColumnsEscaped(new SQLCharExpr(lexer.stringVal()));\n                lexer.nextToken();\n            }\n        }\n\n        if (lexer.identifierEquals(\"LINES\")) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"STARTING\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    stmt.setLinesStartingBy(new SQLCharExpr(lexer.stringVal()));\n                    lexer.nextToken();\n                } else {\n                    SQLExpr primary = this.exprParser.primary();\n                    if (primary instanceof SQLHexExpr) {\n                        stmt.setLinesStartingBy((SQLHexExpr) primary);\n                    } else {\n                        throw new ParserException(\"invalid expr for lines starting : \" + primary);\n                    }\n                }\n            }\n\n            if (lexer.identifierEquals(\"TERMINATED\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    stmt.setLinesTerminatedBy(new SQLCharExpr(lexer.stringVal()));\n                    lexer.nextToken();\n                } else {\n                    SQLExpr primary = this.exprParser.primary();\n                    if (primary instanceof SQLHexExpr) {\n                        stmt.setLinesTerminatedBy((SQLHexExpr) primary);\n                    } else {\n                        throw new ParserException(\"invalid expr for lines terminated : \" + primary);\n                    }\n                }\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            lexer.nextToken();\n            stmt.setIgnoreLinesNumber(this.exprParser.expr());\n            acceptIdentifier(\"LINES\");\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            this.exprParser.exprList(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n            this.exprParser.exprList(stmt.getSetList(), stmt);\n        }\n\n        return stmt;\n\n    }\n\n    public MySqlPrepareStatement parsePrepare() {\n        acceptIdentifier(\"PREPARE\");\n\n        SQLName name = exprParser.name();\n        accept(Token.FROM);\n        SQLExpr from = exprParser.expr();\n\n        return new MySqlPrepareStatement(name, from);\n    }\n\n    @Override\n    public SQLStatement parseExecute() {\n        acceptIdentifier(\"EXECUTE\");\n        if (lexer.identifierEquals(\"RESTART\") || lexer.identifierEquals(\"UPDATE\")) {\n            return parseExecuteForAds();\n        }\n\n        MySqlExecuteStatement stmt = new MySqlExecuteStatement();\n\n        SQLName statementName = exprParser.name();\n        stmt.setStatementName(statementName);\n\n        if (lexer.identifierEquals(\"USING\")) {\n            lexer.nextToken();\n            exprParser.exprList(stmt.getParameters(), stmt);\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            exprParser.exprList(stmt.getParameters(), stmt);\n        }\n        return stmt;\n    }\n\n    public MySqlExecuteForAdsStatement parseExecuteForAds() {\n        MySqlExecuteForAdsStatement stmt = new MySqlExecuteForAdsStatement();\n        stmt.setAction(exprParser.name());\n        stmt.setRole(exprParser.name());\n\n        stmt.setTargetId(exprParser.charExpr());\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            stmt.setStatus(exprParser.name());\n        }\n        return stmt;\n    }\n\n    public MysqlDeallocatePrepareStatement parseDeallocatePrepare() {\n        acceptIdentifier(\"DEALLOCATE\");\n        acceptIdentifier(\"PREPARE\");\n\n        MysqlDeallocatePrepareStatement stmt = new MysqlDeallocatePrepareStatement();\n        SQLName statementName = exprParser.name();\n        stmt.setStatementName(statementName);\n\n        return stmt;\n    }\n\n    public SQLInsertStatement parseInsert() {\n        MySqlInsertStatement stmt = new MySqlInsertStatement();\n\n        SQLName tableName = null;\n        if (lexer.token() == Token.INSERT) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                if (lexer.token() == Token.IDENTIFIER) {\n                    long hash = lexer.hashLCase();\n\n                    if (hash == FnvHash.Constants.LOW_PRIORITY) {\n                        stmt.setLowPriority(true);\n                        lexer.nextToken();\n                        continue;\n                    }\n\n                    if (hash == FnvHash.Constants.DELAYED) {\n                        stmt.setDelayed(true);\n                        lexer.nextToken();\n                        continue;\n                    }\n\n                    if (hash == FnvHash.Constants.HIGH_PRIORITY) {\n                        stmt.setHighPriority(true);\n                        lexer.nextToken();\n                        continue;\n                    }\n\n                    if (hash == FnvHash.Constants.IGNORE) {\n                        stmt.setIgnore(true);\n                        lexer.nextToken();\n                        continue;\n                    }\n\n                    if (hash == FnvHash.Constants.ROLLBACK_ON_FAIL) {\n                        stmt.setRollbackOnFail(true);\n                        lexer.nextToken();\n                        continue;\n                    }\n                }\n\n                break;\n            }\n\n            if (lexer.token() == Token.HINT) {\n                List<SQLCommentHint> hints = this.exprParser.parseHints();\n                stmt.setHints(hints);\n            }\n\n            if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n                if (lexer.token() == TABLE) {\n                    lexer.nextToken();\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.OVERWRITE)) {\n                lexer.nextToken();\n                stmt.setOverwrite(true);\n                if (lexer.token() == TABLE) {\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.INTO) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.token() == Token.LINE_COMMENT) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.FULLTEXT) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.DICTIONARY)) {\n                    lexer.nextToken();\n                    stmt.setFulltextDictionary(true);\n                }\n            }\n\n            tableName = this.exprParser.name();\n            stmt.setTableName(tableName);\n\n            if (lexer.token() == Token.HINT) {\n                String comment = \"/*\" + lexer.stringVal() + \"*/\";\n                lexer.nextToken();\n                stmt.getTableSource().addAfterComment(comment);\n            }\n\n            if (lexer.token() == Token.IDENTIFIER\n                    && !lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == WITH) {\n                SQLSelectStatement withStmt = (SQLSelectStatement) parseWith();\n                stmt.setQuery(withStmt.getSelect());\n            }\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLAssignItem ptExpr = new SQLAssignItem();\n                    ptExpr.setTarget(this.exprParser.name());\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                        SQLExpr ptValue = this.exprParser.expr();\n                        ptExpr.setValue(ptValue);\n                    }\n                    stmt.addPartition(ptExpr);\n                    if (lexer.token() != Token.COMMA) {\n                        break;\n                    } else {\n                        lexer.nextToken();\n                    }\n                }\n                accept(Token.RPAREN);\n\n                if (lexer.token() == Token.IF) {\n                    lexer.nextToken();\n                    accept(Token.NOT);\n                    accept(Token.EXISTS);\n\n                    stmt.setIfNotExists(true);\n                }\n            }\n        }\n\n        int columnSize = 0;\n        List<SQLColumnDefinition> columnDefinitionList = null;\n\n        if (lexer.token() == Token.LPAREN) {\n            boolean useInsertColumnsCache = lexer.isEnabled(SQLParserFeature.UseInsertColumnsCache);\n            InsertColumnsCache insertColumnsCache = null;\n\n            long tableNameHash = 0;\n            InsertColumnsCache.Entry cachedColumns = null;\n            if (useInsertColumnsCache) {\n                insertColumnsCache = this.insertColumnsCache;\n                if (insertColumnsCache == null) {\n                    insertColumnsCache = InsertColumnsCache.global;\n                }\n\n                if (tableName != null) {\n                    tableNameHash = tableName.nameHashCode64();\n                    cachedColumns = insertColumnsCache.get(tableNameHash);\n                }\n            }\n\n            SchemaObject tableObject = null;\n            int pos = lexer.pos();\n            if (cachedColumns != null\n                    && lexer.text.startsWith(cachedColumns.columnsString, pos)) {\n                if (!lexer.isEnabled(SQLParserFeature.OptimizedForParameterized)) {\n                    List<SQLExpr> columns = stmt.getColumns();\n                    List<SQLExpr> cachedColumns2 = cachedColumns.columns;\n                    for (int i = 0, size = cachedColumns2.size(); i < size; i++) {\n                        columns.add(cachedColumns2.get(i).clone());\n                    }\n                }\n                stmt.setColumnsString(cachedColumns.columnsFormattedString, cachedColumns.columnsFormattedStringHash);\n                int p2 = pos + cachedColumns.columnsString.length();\n                lexer.reset(p2);\n                lexer.nextToken();\n            } else {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token() == Token.SELECT) {\n                    lexer.reset(mark);\n                    SQLSelect select = this.exprParser.createSelectParser().select();\n                    select.setParent(stmt);\n                    stmt.setQuery(select);\n                } else {\n                    if (repository != null && lexer.isEnabled(SQLParserFeature.InsertValueCheckType)) {\n                        tableObject = repository.findTable(tableName.nameHashCode64());\n                    }\n\n                    if (tableObject != null) {\n                        columnDefinitionList = new ArrayList<SQLColumnDefinition>();\n                    }\n\n                    List<SQLExpr> columns = stmt.getColumns();\n\n                    if (lexer.token() != Token.RPAREN) {\n                        for (; ; ) {\n                            String identName;\n                            long hash;\n\n                            Token token = lexer.token();\n                            if (token == Token.IDENTIFIER) {\n                                identName = lexer.stringVal();\n                                hash = lexer.hashLCase();\n                            } else if (token == Token.LITERAL_CHARS) {\n                                if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                                    identName = lexer.stringVal();\n                                } else {\n                                    identName = '\\'' + lexer.stringVal() + '\\'';\n                                }\n                                hash = 0;\n                            } else if (token == Token.LITERAL_ALIAS) {\n                                identName = lexer.stringVal();\n                                if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                                    identName = SQLUtils.normalize(identName, dbType);\n                                }\n                                hash = 0;\n                            } else {\n                                identName = lexer.stringVal();\n                                hash = 0;\n                            }\n                            SQLExpr expr = new SQLIdentifierExpr(identName, hash);\n                            if (lexer.hasComment()) {\n                                expr.addBeforeComment(lexer.readAndResetComments());\n                            }\n                            lexer.nextTokenComma();\n                            while (lexer.token() == Token.DOT) {\n                                lexer.nextToken();\n                                String propertyName = lexer.stringVal();\n                                lexer.nextToken();\n                                expr = new SQLPropertyExpr(expr, propertyName);\n                            }\n                            if (lexer.hasComment()) {\n                                expr.addAfterComment(lexer.readAndResetComments());\n                            }\n                            expr.setParent(stmt);\n                            columns.add(expr);\n                            columnSize++;\n\n                            if (tableObject != null) {\n                                SQLColumnDefinition columnDefinition = tableObject.findColumn(hash);\n                                columnDefinitionList.add(columnDefinition);\n                            }\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextTokenIdent();\n                                continue;\n                            }\n\n                            break;\n                        }\n                        columnSize = stmt.getColumns().size();\n\n                        if (insertColumnsCache != null && tableName != null) {\n                            String columnsString = lexer.subString(pos, lexer.pos() - pos);\n\n                            List<SQLExpr> clonedColumns = new ArrayList<SQLExpr>(columnSize);\n                            for (int i = 0; i < columns.size(); i++) {\n                                clonedColumns.add(columns.get(i).clone());\n                            }\n\n                            StringBuilder buf = new StringBuilder();\n                            SQLASTOutputVisitor outputVisitor = SQLUtils.createOutputVisitor(buf, dbType);\n                            outputVisitor.printInsertColumns(columns);\n\n                            String formattedColumnsString = buf.toString();\n                            long columnsFormattedStringHash = FnvHash.fnv1a_64_lower(formattedColumnsString);\n\n                            insertColumnsCache.put(tableName.hashCode64(), columnsString, formattedColumnsString, clonedColumns);\n                            stmt.setColumnsString(formattedColumnsString, columnsFormattedStringHash);\n                        }\n                    }\n                    accept(Token.RPAREN);\n                }\n            }\n        }\n\n        List<SQLCommentHint> commentHints = null;\n        if (lexer.token() == Token.HINT) {\n            commentHints = this.exprParser.parseHints();\n        } else if (lexer.token() == Token.LINE_COMMENT) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.VALUES || lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n            lexer.nextTokenLParen();\n            if (lexer.isEnabled(SQLParserFeature.InsertReader)) {\n                return stmt;\n            }\n\n            if (lexer.isEnabled(SQLParserFeature.InsertValueNative)) {\n                parseValueClauseNative(stmt.getValuesList(), columnDefinitionList, columnSize, stmt);\n            } else {\n                parseValueClause(stmt.getValuesList(), columnDefinitionList, columnSize, stmt);\n            }\n        } else if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n\n            SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n            stmt.addValueCause(values);\n\n            for (; ; ) {\n                SQLName name = this.exprParser.name();\n                stmt.addColumn(name);\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                } else {\n                    accept(Token.COLONEQ);\n                }\n                values.addValue(this.exprParser.expr());\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n\n        } else if (lexer.token() == (Token.SELECT)) {\n            SQLSelect select = this.exprParser.createSelectParser().select();\n            if (commentHints != null && !commentHints.isEmpty()) {\n                select.setHeadHint(commentHints.get(0));\n            }\n            select.setParent(stmt);\n            stmt.setQuery(select);\n        } else if (lexer.token() == (Token.LPAREN)) {\n            lexer.nextToken();\n            SQLSelect select = this.exprParser.createSelectParser().select();\n            select.setParent(stmt);\n            stmt.setQuery(select);\n            accept(Token.RPAREN);\n        } else if (lexer.token() == WITH) {\n            SQLSelect query = this.exprParser.createSelectParser().select();\n            stmt.setQuery(query);\n        }\n\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            acceptIdentifier(\"DUPLICATE\");\n            accept(Token.KEY);\n            accept(Token.UPDATE);\n\n            List<SQLExpr> duplicateKeyUpdate = stmt.getDuplicateKeyUpdate();\n            for (; ; ) {\n                SQLName name = this.exprParser.name();\n                accept(Token.EQ);\n                SQLExpr value;\n                try {\n                    value = this.exprParser.expr();\n                } catch (EOFParserException e) {\n                    throw new ParserException(\"EOF, \" + name + \"=\", e);\n                }\n\n                SQLBinaryOpExpr assignment = new SQLBinaryOpExpr(name, SQLBinaryOperator.Equality, value);\n                assignment.setParent(stmt);\n                duplicateKeyUpdate.add(assignment);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextTokenIdent();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        return stmt;\n    }\n\n    public MySqlSelectParser createSQLSelectParser() {\n        return new MySqlSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLStatement parseSet() {\n        accept(Token.SET);\n\n        if (lexer.identifierEquals(FnvHash.Constants.PASSWORD)) {\n            lexer.nextToken();\n            SQLSetStatement stmt = new SQLSetStatement();\n            stmt.setDbType(dbType);\n            stmt.setOption(SQLSetStatement.Option.PASSWORD);\n\n            SQLExpr user = null;\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                user = this.exprParser.name();\n            }\n\n            accept(Token.EQ);\n\n            SQLExpr password = this.exprParser.expr();\n\n            stmt.set(user, password);\n\n            return stmt;\n        }\n\n        Boolean global = null;\n        Boolean session = null;\n        boolean local = false;\n        if (lexer.identifierEquals(GLOBAL)) {\n            global = Boolean.TRUE;\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.SESSION)) {\n            session = Boolean.TRUE;\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n            lexer.nextToken();\n            local = true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TRANSACTION)) {\n            MySqlSetTransactionStatement stmt = new MySqlSetTransactionStatement();\n            stmt.setGlobal(global);\n            stmt.setSession(session);\n\n            if (local) {\n                stmt.setLocal(true);\n            }\n\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"ISOLATION\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LEVEL\");\n\n                if (lexer.identifierEquals(READ)) {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(\"UNCOMMITTED\")) {\n                        stmt.setIsolationLevel(\"READ UNCOMMITTED\");\n                        lexer.nextToken();\n                    } else if (lexer.identifierEquals(WRITE)) {\n                        stmt.setIsolationLevel(\"READ WRITE\");\n                        lexer.nextToken();\n                    } else if (lexer.identifierEquals(\"ONLY\")) {\n                        stmt.setIsolationLevel(\"READ ONLY\");\n                        lexer.nextToken();\n                    } else if (lexer.identifierEquals(\"COMMITTED\")) {\n                        stmt.setIsolationLevel(\"READ COMMITTED\");\n                        lexer.nextToken();\n                    } else {\n                        throw new ParserException(\"UNKOWN TRANSACTION LEVEL : \" + lexer.stringVal() + \", \" + lexer.info());\n                    }\n                } else if (lexer.identifierEquals(\"SERIALIZABLE\")) {\n                    stmt.setIsolationLevel(\"SERIALIZABLE\");\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(\"REPEATABLE\")) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(READ)) {\n                        stmt.setIsolationLevel(\"REPEATABLE READ\");\n                        lexer.nextToken();\n                    } else {\n                        throw new ParserException(\"UNKOWN TRANSACTION LEVEL : \" + lexer.stringVal() + \", \" + lexer.info());\n                    }\n                } else {\n                    throw new ParserException(\"UNKOWN TRANSACTION LEVEL : \" + lexer.stringVal() + \", \" + lexer.info());\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.POLICY)) {\n                lexer.nextToken();\n                SQLExpr policy = this.exprParser.primary();\n                stmt.setPolicy(policy);\n            } else if (lexer.identifierEquals(READ)) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"ONLY\")) {\n                    stmt.setAccessModel(\"ONLY\");\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(\"WRITE\")) {\n                    stmt.setAccessModel(\"WRITE\");\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"UNKOWN ACCESS MODEL : \" + lexer.stringVal() + \", \" + lexer.info());\n                }\n            }\n\n            return stmt;\n        } else {\n            SQLSetStatement stmt = new SQLSetStatement(getDbType());\n            boolean mariadbSetStatementFlag = false;\n            if (lexer.identifierEquals(\"STATEMENT\")) {\n                mariadbSetStatementFlag = true;\n                lexer.nextToken();\n            }\n            parseAssignItems(stmt.getItems(), stmt, true);\n            if (mariadbSetStatementFlag) {\n                accept(Token.FOR);\n                SQLStatement maridbSetForStatement = this.parseStatement();\n                stmt.setMaridbSetForStatement(maridbSetForStatement);\n            }\n            if (global != null) {\n                SQLVariantRefExpr varRef = (SQLVariantRefExpr) stmt.getItems().get(0).getTarget();\n                varRef.setGlobal(true);\n            }\n\n            if (session != null) {\n                SQLVariantRefExpr varRef = (SQLVariantRefExpr) stmt.getItems().get(0).getTarget();\n                varRef.setSession(true);\n            }\n\n            if (lexer.token() == Token.HINT) {\n                stmt.setHints(this.exprParser.parseHints());\n            }\n\n            return stmt;\n        }\n    }\n\n    protected SQLStatement alterRest(Lexer.SavePoint mark) {\n        if (lexer.identifierEquals(ONLINE)\n                || lexer.identifierEquals(OFFLINE)\n                || lexer.identifierEquals(FnvHash.Constants.IGNORE)\n        ) {\n            lexer.reset(mark);\n            return alterTable();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOGFILE)) {\n            return alterLogFileGroup();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SERVER)) {\n            return alterServer();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {\n            return alterView();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.OUTLINE)) {\n            lexer.reset(mark);\n            return alterOutline();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            this.getExprParser().userName();\n            if (lexer.identifierEquals(FnvHash.Constants.EVENT)) {\n                lexer.reset(mark);\n                return alterEvent();\n            } else {\n                lexer.reset(mark);\n                return alterView();\n            }\n        }\n        if (lexer.identifierEquals(\"TABLEGROUP\")) {\n            lexer.reset(mark);\n            return alterTableGroup();\n        }\n\n        if (lexer.identifierEquals(\"SYSTEM\")) {\n            lexer.reset(mark);\n            return alterSystem();\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    private SQLStatement parseAddManageInstanceGroup() {\n        lexer.nextToken();\n        MySqlManageInstanceGroupStatement stmt = new MySqlManageInstanceGroupStatement();\n        stmt.setOperation(new SQLIdentifierExpr(\"ADD\"));\n\n        acceptIdentifier(\"INSTANCE_GROUP\");\n        for (; ; ) {\n            stmt.getGroupNames().add(exprParser.expr());\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        acceptIdentifier(\"REPLICATION\");\n        accept(Token.EQ);\n        stmt.setReplication(exprParser.integerExpr());\n        return stmt;\n    }\n\n    protected SQLStatement alterFullText() {\n        accept(ALTER);\n        accept(Token.FULLTEXT);\n\n        MysqlAlterFullTextStatement stmt = new MysqlAlterFullTextStatement();\n\n        stmt.setType(parseFullTextType());\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        accept(Token.SET);\n\n        SQLAssignItem item = this.exprParser.parseAssignItem();\n        stmt.setItem(item);\n        return stmt;\n    }\n\n    protected SQLStatement alterTableGroup() {\n        accept(ALTER);\n        acceptIdentifier(\"TABLEGROUP\");\n\n        SQLName name = this.exprParser.name();\n\n        SQLAlterTableGroupStatement stmt = new SQLAlterTableGroupStatement();\n        stmt.setName(name);\n\n        for (; ; ) {\n            SQLName key = this.exprParser.name();\n            accept(Token.EQ);\n            SQLExpr value = this.exprParser.expr();\n            stmt.getOptions().add(new SQLAssignItem(key, value));\n\n            if (lexer.token() == Token.EOF) {\n                break;\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterSystem() {\n        accept(ALTER);\n        acceptIdentifier(\"SYSTEM\");\n\n        if (lexer.token() == Token.SET) {\n            accept(Token.SET);\n            acceptIdentifier(\"CONFIG\");\n\n            SQLAlterSystemSetConfigStatement stmt = new SQLAlterSystemSetConfigStatement();\n\n            for (; ; ) {\n                SQLName key = this.exprParser.name();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.expr();\n                stmt.getOptions().add(new SQLAssignItem(key, value));\n\n                if (lexer.token() == Token.EOF) {\n                    break;\n                }\n            }\n\n            return stmt;\n\n        } else if (lexer.identifierEquals(\"GET\")) {\n            acceptIdentifier(\"GET\");\n            acceptIdentifier(\"CONFIG\");\n            SQLName name = this.exprParser.name();\n\n            SQLAlterSystemGetConfigStatement stmt = new SQLAlterSystemGetConfigStatement();\n            stmt.setName(name);\n\n            return stmt;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    protected SQLStatement alterOutline() {\n        accept(ALTER);\n\n        if (lexer.identifierEquals(FnvHash.Constants.OUTLINE)) {\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n\n        SQLAlterOutlineStatement stmt = new SQLAlterOutlineStatement();\n        stmt.setDbType(dbType);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.identifierEquals(\"RESYNC\")) {\n            lexer.nextToken();\n            stmt.setResync(true);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterView() {\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n\n        SQLAlterViewStatement createView = new SQLAlterViewStatement(getDbType());\n\n        if (lexer.identifierEquals(\"ALGORITHM\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            String algorithm = lexer.stringVal();\n            createView.setAlgorithm(algorithm);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"DEFINER\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLName definer = (SQLName) this.exprParser.expr();\n            createView.setDefiner(definer);\n        }\n\n        if (lexer.identifierEquals(\"SQL\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"SECURITY\");\n            String sqlSecurity = lexer.stringVal();\n            createView.setSqlSecurity(sqlSecurity);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n            createView.setForce(true);\n        }\n\n        this.accept(Token.VIEW);\n\n        if (lexer.token() == Token.IF || lexer.identifierEquals(\"IF\")) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            createView.setIfNotExists(true);\n        }\n\n        createView.setName(exprParser.name());\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                if (lexer.token() == Token.CONSTRAINT) {\n                    SQLTableConstraint constraint = (SQLTableConstraint) this.exprParser.parseConstraint();\n                    createView.addColumn(constraint);\n                } else {\n                    SQLColumnDefinition column = new SQLColumnDefinition();\n                    column.setDbType(dbType);\n                    SQLName expr = this.exprParser.name();\n                    column.setName(expr);\n\n                    this.exprParser.parseColumnRest(column);\n\n                    if (lexer.token() == Token.COMMENT) {\n                        lexer.nextToken();\n\n                        SQLExpr comment;\n                        if (lexer.token() == Token.LITERAL_ALIAS) {\n                            String alias = lexer.stringVal();\n                            if (alias.length() > 2 && alias.charAt(0) == '\"' && alias.charAt(alias.length() - 1) == '\"') {\n                                alias = alias.substring(1, alias.length() - 1);\n                            }\n                            comment = new SQLCharExpr(alias);\n                            lexer.nextToken();\n                        } else {\n                            comment = this.exprParser.primary();\n                        }\n                        column.setComment(comment);\n                    }\n\n                    column.setParent(createView);\n                    createView.addColumn(column);\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLCharExpr comment = (SQLCharExpr) exprParser.primary();\n            createView.setComment(comment);\n        }\n\n        this.accept(Token.AS);\n\n        SQLSelectParser selectParser = this.createSQLSelectParser();\n        createView.setSubQuery(selectParser.select());\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"CASCADED\")) {\n                createView.setWithCascaded(true);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"LOCAL\")) {\n                createView.setWithLocal(true);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"READ\")) {\n                lexer.nextToken();\n                accept(Token.ONLY);\n                createView.setWithReadOnly(true);\n            }\n\n            if (lexer.token() == Token.CHECK) {\n                lexer.nextToken();\n                acceptIdentifier(\"OPTION\");\n                createView.setWithCheckOption(true);\n            }\n        }\n\n        return createView;\n    }\n\n    protected SQLStatement alterTableSpace() {\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n\n        accept(Token.TABLESPACE);\n\n        SQLName name = this.exprParser.name();\n\n        MySqlAlterTablespaceStatement stmt = new MySqlAlterTablespaceStatement();\n        stmt.setName(name);\n\n        if (lexer.identifierEquals(FnvHash.Constants.ADD)) {\n            lexer.nextToken();\n            acceptIdentifier(\"DATAFILE\");\n            SQLExpr file = this.exprParser.primary();\n            stmt.setAddDataFile(file);\n        } else if (lexer.token() == Token.DROP) {\n            lexer.nextToken();\n            acceptIdentifier(\"DATAFILE\");\n            SQLExpr file = this.exprParser.primary();\n            stmt.setDropDataFile(file);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr initialSize = this.exprParser.expr();\n            stmt.setInitialSize(initialSize);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WAIT)) {\n            lexer.nextToken();\n            stmt.setWait(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr engine = this.exprParser.expr();\n            stmt.setEngine(engine);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterServer() {\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n        acceptIdentifier(\"SERVER\");\n\n        SQLName name = this.exprParser.name();\n\n        MySqlAlterServerStatement stmt = new MySqlAlterServerStatement();\n        stmt.setName(name);\n\n        acceptIdentifier(\"OPTIONS\");\n        accept(Token.LPAREN);\n        if (lexer.token() == Token.USER) {\n            lexer.nextToken();\n            SQLExpr user = this.exprParser.name();\n            stmt.setUser(user);\n        }\n        accept(Token.RPAREN);\n\n        return stmt;\n    }\n\n    protected SQLStatement parseCreateLogFileGroup() {\n        accept(Token.CREATE);\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n        acceptIdentifier(\"LOGFILE\");\n        accept(GROUP);\n\n        SQLName name = this.exprParser.name();\n\n        MySqlCreateAddLogFileGroupStatement stmt = new MySqlCreateAddLogFileGroupStatement();\n        stmt.setName(name);\n\n        acceptIdentifier(\"ADD\");\n        acceptIdentifier(\"UNDOFILE\");\n\n        SQLExpr fileName = this.exprParser.primary();\n        stmt.setAddUndoFile(fileName);\n\n        if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr initialSize = this.exprParser.expr();\n            stmt.setInitialSize(initialSize);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WAIT)) {\n            lexer.nextToken();\n            stmt.setWait(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr engine = this.exprParser.expr();\n            stmt.setEngine(engine);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterLogFileGroup() {\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n        acceptIdentifier(\"LOGFILE\");\n        accept(GROUP);\n\n        SQLName name = this.exprParser.name();\n\n        MySqlAlterLogFileGroupStatement stmt = new MySqlAlterLogFileGroupStatement();\n        stmt.setName(name);\n\n        acceptIdentifier(\"ADD\");\n        acceptIdentifier(\"UNDOFILE\");\n\n        SQLExpr fileName = this.exprParser.primary();\n        stmt.setAddUndoFile(fileName);\n\n        if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr initialSize = this.exprParser.expr();\n            stmt.setInitialSize(initialSize);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WAIT)) {\n            lexer.nextToken();\n            stmt.setWait(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr engine = this.exprParser.expr();\n            stmt.setEngine(engine);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterProcedure() {\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n        accept(Token.PROCEDURE);\n\n        SQLAlterProcedureStatement stmt = new SQLAlterProcedureStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        // for mysql\n        for (; ; ) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                SQLExpr comment = this.exprParser.primary();\n                stmt.setComment(comment);\n            } else if (lexer.identifierEquals(FnvHash.Constants.LANGUAGE)) {\n                lexer.nextToken();\n                acceptIdentifier(\"SQL\");\n                stmt.setLanguageSql(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SQL)) {\n                lexer.nextToken();\n                acceptIdentifier(\"SECURITY\");\n\n                SQLExpr sqlSecurity = this.exprParser.name();\n                stmt.setSqlSecurity(sqlSecurity);\n            } else if (lexer.identifierEquals(FnvHash.Constants.CONTAINS) || lexer.token() == Token.CONTAINS) {\n                lexer.nextToken();\n                acceptIdentifier(\"SQL\");\n                stmt.setContainsSql(true);\n            } else {\n                break;\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseAlterFunction() {\n        SQLAlterFunctionStatement stmt = new SQLAlterFunctionStatement();\n\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n        accept(Token.FUNCTION);\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        // for mysql\n        for (; ; ) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                SQLExpr comment = this.exprParser.primary();\n                stmt.setComment(comment);\n            } else if (lexer.identifierEquals(FnvHash.Constants.LANGUAGE)) {\n                lexer.nextToken();\n                acceptIdentifier(\"SQL\");\n                stmt.setLanguageSql(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SQL)) {\n                lexer.nextToken();\n                acceptIdentifier(\"SECURITY\");\n\n                SQLExpr sqlSecurity = this.exprParser.name();\n                stmt.setSqlSecurity(sqlSecurity);\n            } else if (lexer.identifierEquals(FnvHash.Constants.CONTAINS) || lexer.token() == Token.CONTAINS) {\n                lexer.nextToken();\n                acceptIdentifier(\"SQL\");\n                stmt.setContainsSql(true);\n            } else {\n                break;\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseCreateEvent() {\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n        }\n\n        MySqlCreateEventStatement stmt = new MySqlCreateEventStatement();\n\n        if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLName definer = this.getExprParser().userName();\n            stmt.setDefiner(definer);\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                accept(Token.RPAREN);\n            }\n        }\n\n        acceptIdentifier(\"EVENT\");\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        SQLName eventName = this.exprParser.name();\n        stmt.setName(eventName);\n\n        while (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.SCHEDULE)) {\n                lexer.nextToken();\n                MySqlEventSchedule schedule = parseSchedule();\n                stmt.setSchedule(schedule);\n            } else if (lexer.identifierEquals(FnvHash.Constants.COMPLETION)) {\n                lexer.nextToken();\n\n                boolean value;\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    value = false;\n                } else {\n                    value = true;\n                }\n                acceptIdentifier(\"PRESERVE\");\n                stmt.setOnCompletionPreserve(value);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n            lexer.nextToken();\n            accept(Token.TO);\n            SQLName renameTo = this.exprParser.name();\n            stmt.setRenameTo(renameTo);\n        }\n\n        if (lexer.token() == Token.ENABLE) {\n            stmt.setEnable(true);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.DISABLE) {\n            lexer.nextToken();\n            stmt.setEnable(false);\n\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                acceptIdentifier(\"SLAVE\");\n                stmt.setDisableOnSlave(true);\n            }\n        }\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLExpr comment = this.exprParser.primary();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.token() == Token.DO) {\n            lexer.nextToken();\n            SQLStatement eventBody = this.parseStatement();\n            stmt.setEventBody(eventBody);\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            SQLExpr expr = this.exprParser.expr();\n            SQLExprStatement eventBody = new SQLExprStatement(expr);\n            eventBody.setDbType(dbType);\n            stmt.setEventBody(eventBody);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterEvent() {\n        if (lexer.token() == ALTER) {\n            lexer.nextToken();\n        }\n\n        MySqlAlterEventStatement stmt = new MySqlAlterEventStatement();\n\n        if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLName definer = this.getExprParser().userName();\n            stmt.setDefiner(definer);\n        }\n\n        acceptIdentifier(\"EVENT\");\n\n        SQLName eventName = this.exprParser.name();\n        stmt.setName(eventName);\n\n        while (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.SCHEDULE)) {\n                lexer.nextToken();\n                MySqlEventSchedule schedule = parseSchedule();\n                stmt.setSchedule(schedule);\n            } else if (lexer.identifierEquals(FnvHash.Constants.COMPLETION)) {\n                lexer.nextToken();\n\n                boolean value;\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    value = false;\n                } else {\n                    value = true;\n                }\n                acceptIdentifier(\"PRESERVE\");\n                stmt.setOnCompletionPreserve(value);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n            lexer.nextToken();\n            accept(Token.TO);\n            SQLName renameTo = this.exprParser.name();\n            stmt.setRenameTo(renameTo);\n        }\n\n        if (lexer.token() == Token.ENABLE) {\n            stmt.setEnable(true);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.DISABLE) {\n            lexer.nextToken();\n            stmt.setEnable(false);\n\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                acceptIdentifier(\"SLAVE\");\n                stmt.setDisableOnSlave(true);\n            }\n        }\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLExpr comment = this.exprParser.primary();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.token() == Token.DO) {\n            lexer.nextToken();\n            SQLStatement eventBody = this.parseStatement();\n            stmt.setEventBody(eventBody);\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            SQLExpr expr = this.exprParser.expr();\n            SQLExprStatement eventBody = new SQLExprStatement(expr);\n            eventBody.setDbType(dbType);\n            stmt.setEventBody(eventBody);\n        }\n\n        return stmt;\n    }\n\n    private MySqlEventSchedule parseSchedule() {\n        MySqlEventSchedule schedule = new MySqlEventSchedule();\n\n        if (lexer.identifierEquals(FnvHash.Constants.AT)) {\n            lexer.nextToken();\n            schedule.setAt(this.exprParser.expr());\n        } else if (lexer.identifierEquals(FnvHash.Constants.EVERY)) {\n            lexer.nextToken();\n            SQLExpr value = this.exprParser.expr();\n            String unit = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLIntervalExpr intervalExpr = new SQLIntervalExpr();\n            intervalExpr.setValue(value);\n            intervalExpr.setUnit(SQLIntervalUnit.valueOf(unit.toUpperCase()));\n\n            schedule.setEvery(intervalExpr);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STARTS)) {\n            lexer.nextToken();\n            schedule.setStarts(this.exprParser.expr());\n\n            if (lexer.identifierEquals(FnvHash.Constants.ENDS)) {\n                lexer.nextToken();\n                schedule.setEnds(this.exprParser.expr());\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.ENDS)) {\n            lexer.nextToken();\n            schedule.setEnds(this.exprParser.expr());\n        }\n\n        return schedule;\n    }\n\n    private boolean parseAlterSpecification(SQLAlterTableStatement stmt) {\n        // Specification except table options.\n        switch (lexer.token()) {\n            case IDENTIFIER:\n                if (lexer.identifierEquals(FnvHash.Constants.ADD)) {\n                    alterTableAdd(stmt);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {\n                    // ALGORITHM [=] {DEFAULT | INSTANT | INPLACE | COPY}\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n                    MySqlAlterTableAlgorithm item = new MySqlAlterTableAlgorithm();\n                    item.setAlgorithmType(new SQLIdentifierExpr(lexer.stringVal()));\n                    stmt.addItem(item);\n                    lexer.nextToken();\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.CHANGE)) {\n                    // CHANGE [COLUMN] old_col_name new_col_name column_definition [FIRST|AFTER col_name]\n                    lexer.nextToken();\n                    if (lexer.token() == Token.COLUMN) {\n                        lexer.nextToken();\n                    }\n                    MySqlAlterTableChangeColumn item = new MySqlAlterTableChangeColumn();\n                    item.setColumnName(this.exprParser.name());\n                    item.setNewColumnDefinition(this.exprParser.parseColumn());\n                    if (lexer.identifierEquals(\"AFTER\")) {\n                        lexer.nextToken();\n                        item.setAfterColumn(this.exprParser.name());\n                    } else if (lexer.identifierEquals(\"FIRST\")) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.IDENTIFIER) {\n                            item.setFirstColumn(this.exprParser.name());\n                        } else {\n                            item.setFirst(true);\n                        }\n                    }\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.CONVERT)) {\n                    // CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]\n                    lexer.nextToken();\n                    accept(Token.TO);\n                    acceptIdentifier(\"CHARACTER\");\n                    accept(Token.SET);\n                    SQLAlterTableConvertCharSet item = new SQLAlterTableConvertCharSet();\n                    SQLExpr charset = this.exprParser.name();\n                    item.setCharset(charset);\n                    if (lexer.identifierEquals(\"COLLATE\")) {\n                        lexer.nextToken();\n                        SQLExpr collate = this.exprParser.primary();\n                        item.setCollate(collate);\n                    }\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.DISCARD)) {\n                    // DISCARD PARTITION {partition_names | ALL} TABLESPACE\n                    // DISCARD TABLESPACE\n                    lexer.nextToken();\n                    if (lexer.token() == Token.PARTITION) {\n                        lexer.nextToken();\n                        SQLAlterTableDiscardPartition item = new SQLAlterTableDiscardPartition();\n\n                        if (lexer.token() == Token.ALL) {\n                            lexer.nextToken();\n                            item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                        } else {\n                            this.exprParser.names(item.getPartitions(), item);\n                        }\n\n                        if (lexer.token() == Token.TABLESPACE) {\n                            lexer.nextToken();\n                            item.setTablespace(true);\n                        }\n\n                        stmt.addItem(item);\n                    } else {\n                        accept(Token.TABLESPACE);\n                        MySqlAlterTableDiscardTablespace item = new MySqlAlterTableDiscardTablespace();\n                        stmt.addItem(item);\n                    }\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.IMPORT)) {\n                    // IMPORT PARTITION {partition_names | ALL} TABLESPACE\n                    // IMPORT TABLESPACE\n                    lexer.nextToken();\n                    if (lexer.token() == Token.PARTITION) {\n                        lexer.nextToken();\n                        SQLAlterTableImportPartition item = new SQLAlterTableImportPartition();\n\n                        if (lexer.token() == Token.ALL) {\n                            lexer.nextToken();\n                            item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                        } else {\n                            this.exprParser.names(item.getPartitions(), item);\n                        }\n\n                        if (lexer.token() == Token.TABLESPACE) {\n                            lexer.nextToken();\n                            item.setTablespace(true);\n                        }\n\n                        stmt.addItem(item);\n                    } else {\n                        accept(Token.TABLESPACE);\n                        MySqlAlterTableImportTablespace item = new MySqlAlterTableImportTablespace();\n                        stmt.addItem(item);\n                    }\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n                    // FORCE\n                    lexer.nextToken();\n                    MySqlAlterTableForce item = new MySqlAlterTableForce();\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.MODIFY)) {\n                    // MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name]\n                    lexer.nextToken();\n                    if (lexer.token() == Token.COLUMN) {\n                        lexer.nextToken();\n                    }\n                    boolean paren = false;\n                    if (lexer.token() == Token.LPAREN) {\n                        paren = true;\n                        lexer.nextToken();\n                    }\n                    for (; ; ) {\n                        MySqlAlterTableModifyColumn item = new MySqlAlterTableModifyColumn();\n                        item.setNewColumnDefinition(this.exprParser.parseColumn());\n                        if (lexer.identifierEquals(\"AFTER\")) {\n                            lexer.nextToken();\n                            item.setAfterColumn(this.exprParser.name());\n                        } else if (lexer.identifierEquals(\"FIRST\")) {\n                            lexer.nextToken();\n                            if (lexer.token() == Token.IDENTIFIER) {\n                                item.setFirstColumn(this.exprParser.name());\n                            } else {\n                                item.setFirst(true);\n                            }\n                        }\n                        stmt.addItem(item);\n\n                        if (paren && lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n\n                    if (paren) {\n                        accept(Token.RPAREN);\n                    }\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n                    // RENAME {INDEX|KEY} old_index_name TO new_index_name\n                    // RENAME [TO|AS] new_tbl_name\n                    lexer.nextToken();\n                    switch (lexer.token()) {\n                        case INDEX:\n                        case KEY: {\n                            lexer.nextToken();\n                            SQLName name = this.exprParser.name();\n                            accept(Token.TO);\n                            SQLName to = this.exprParser.name();\n                            SQLAlterTableRenameIndex item = new SQLAlterTableRenameIndex(name, to);\n                            stmt.addItem(item);\n                            return true;\n                        }\n\n                        case COLUMN: {\n                            lexer.nextToken();\n                            SQLName columnName = exprParser.name();\n                            accept(Token.TO);\n                            SQLName toName = this.exprParser.name();\n                            SQLAlterTableRenameColumn renameColumn = new SQLAlterTableRenameColumn();\n                            renameColumn.setColumn(columnName);\n                            renameColumn.setTo(toName);\n                            stmt.addItem(renameColumn);\n                            return true;\n                        }\n\n                        case TO:\n                        case AS:\n                            lexer.nextToken();\n                        case IDENTIFIER:\n                            SQLAlterTableRename item = new SQLAlterTableRename();\n                            SQLName to = this.exprParser.name();\n                            item.setTo(to);\n                            stmt.addItem(item);\n                            return true;\n\n                        default:\n                            break;\n                    }\n                } else if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) {\n                    // WITHOUT VALIDATION\n                    lexer.nextToken();\n                    acceptIdentifier(\"VALIDATION\");\n                    MySqlAlterTableValidation item = new MySqlAlterTableValidation();\n                    item.setWithValidation(false);\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(\"COALESCE\")) {\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableCoalescePartition item = new SQLAlterTableCoalescePartition();\n                    SQLIntegerExpr countExpr = this.exprParser.integerExpr();\n                    item.setCount(countExpr);\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(\"REORGANIZE\")) {\n                    // REORGANIZE PARTITION partition_names INTO (partition_definitions)\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableReOrganizePartition item = new SQLAlterTableReOrganizePartition();\n\n                    this.exprParser.names(item.getNames(), item);\n\n                    accept(Token.INTO);\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        MysqlPartitionSingle partition = this.getExprParser().parsePartition();\n\n                        item.addPartition(partition);\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        } else {\n                            break;\n                        }\n                    }\n                    accept(Token.RPAREN);\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.EXCHANGE)) {\n                    // EXCHANGE PARTITION partition_name WITH TABLE tbl_name [{WITH|WITHOUT} VALIDATION]\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableExchangePartition item = new SQLAlterTableExchangePartition();\n\n                    SQLName partition = this.exprParser.name();\n                    item.addPartition(partition);\n\n                    accept(WITH);\n                    accept(TABLE);\n                    SQLName table = this.exprParser.name();\n                    item.setTable(table);\n\n                    if (lexer.token() == WITH) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"VALIDATION\");\n                        item.setValidation(true);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"VALIDATION\");\n                        item.setValidation(false);\n                    }\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(\"REBUILD\")) {\n                    // REBUILD PARTITION {partition_names | ALL}\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableRebuildPartition item = new SQLAlterTableRebuildPartition();\n\n                    if (lexer.token() == Token.ALL) {\n                        lexer.nextToken();\n                        item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                    } else {\n                        this.exprParser.names(item.getPartitions(), item);\n                    }\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(\"REPAIR\")) {\n                    // REPAIR PARTITION {partition_names | ALL}\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableRepairPartition item = new SQLAlterTableRepairPartition();\n\n                    if (lexer.token() == Token.ALL) {\n                        lexer.nextToken();\n                        item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                    } else {\n                        this.exprParser.names(item.getPartitions(), item);\n                    }\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.REMOVE)) {\n                    // REMOVE PARTITIONING\n                    lexer.nextToken();\n                    acceptIdentifier(\"PARTITIONING\");\n                    stmt.setRemovePatiting(true);\n                } else if (lexer.identifierEquals(\"UPGRADE\")) {\n                    // UPGRADE PARTITIONING\n                    lexer.nextToken();\n                    acceptIdentifier(\"PARTITIONING\");\n                    stmt.setUpgradePatiting(true);\n                } else if (lexer.identifierEquals(\"HOT_PARTITION_COUNT\")) {\n                    // UPGRADE PARTITIONING\n                    lexer.nextToken();\n                    accept(EQ);\n                    try {\n                        stmt.getTableOptions().add(new SQLAssignItem(new SQLIdentifierExpr(\"HOT_PARTITION_COUNT\"), this.exprParser.integerExpr()));\n                    } catch (Exception e) {\n                        throw new ParserException(\"only integer number is supported for hot_partition_count\");\n                    }\n                }\n\n                //\n                // Other not in MySql documents.\n                //\n\n                else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n                    // Caution: Not in MySql documents.\n                    SQLAlterTablePartitionCount item = new SQLAlterTablePartitionCount();\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n                    item.setCount((SQLIntegerExpr) exprParser.integerExpr());\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                        lexer.nextToken();\n                        SQLAlterTableSubpartitionLifecycle item = new SQLAlterTableSubpartitionLifecycle();\n                        if (lexer.token() == Token.LITERAL_INT) {\n                            for (; ; ) {\n                                item.getPartitionIds().add(this.exprParser.integerExpr());\n                                String pidStr = lexer.stringVal();\n                                accept(Token.VARIANT);\n                                String s = pidStr.replaceAll(\":\", \"\");\n                                if (StringUtils.isEmpty(s)) {\n                                    item.getSubpartitionLifeCycle().add(exprParser.integerExpr());\n                                } else {\n                                    item.getSubpartitionLifeCycle().add(new SQLIntegerExpr(Integer.valueOf(s)));\n                                }\n\n                                if (lexer.token() == Token.COMMA) {\n                                    lexer.nextToken();\n                                    continue;\n                                }\n\n                                break;\n                            }\n                        }\n                        stmt.addItem(item);\n                    }\n                    return true;\n                } else if (lexer.identifierEquals(\"BLOCK_SIZE\")) {\n                    // Caution: Not in MySql documents.\n                    SQLAlterTableBlockSize item = new SQLAlterTableBlockSize();\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        accept(Token.EQ);\n                    }\n                    item.setSize((SQLIntegerExpr) exprParser.expr());\n                    stmt.addItem(item);\n                    return true;\n                } else if (lexer.identifierEquals(INSERT_METHOD)) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n                    stmt.getTableOptions().add(new SQLAssignItem(new SQLIdentifierExpr(INSERT_METHOD), this.exprParser.primary()));\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n                    // Caution: Not in MySql documents.\n                    SQLAlterTableModifyClusteredBy clusteredBy = new SQLAlterTableModifyClusteredBy();\n\n                    acceptIdentifier(\"CLUSTERED\");\n                    accept(Token.BY);\n                    accept(Token.LPAREN);\n\n                    // for ads: ALTER TABLE SCHEMA1.TABLE1 CLUSTERED BY ();\n                    if (lexer.token() != Token.RPAREN) {\n                        for (; ; ) {\n                            clusteredBy.addClusterColumn(this.exprParser.name());\n\n                            if (lexer.token() == Token.COMMA) {\n                                accept(Token.COMMA);\n                                continue;\n                            }\n                            break;\n                        }\n                    }\n\n                    accept(Token.RPAREN);\n\n                    stmt.addItem(clusteredBy);\n                    return true;\n                } else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION_AVAILABLE_PARTITION_NUM)) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n                    SQLIntegerExpr num = this.exprParser.integerExpr();\n                    SQLAlterTableSubpartitionAvailablePartitionNum item = new SQLAlterTableSubpartitionAvailablePartitionNum();\n                    item.setNumber(num);\n                    stmt.addItem(item);\n                    return true;\n                }\n                break;\n\n            case ALTER: {\n                lexer.nextToken();\n                if (lexer.token() == INDEX) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n\n                    SQLName indexName = this.exprParser.name();\n\n                    if (lexer.identifierEquals(\"VISIBLE\") || lexer.identifierEquals(\"INVISIBLE\")) {\n                        SQLAlterTableAlterIndex alterIndex = new SQLAlterTableAlterIndex();\n                        alterIndex.setName(indexName);\n                        alterIndex.getIndexDefinition().getOptions().setVisible(lexer.identifierEquals(\"VISIBLE\"));\n                        alterIndex.getIndexDefinition().getOptions().setInvisible(lexer.identifierEquals(\"INVISIBLE\"));\n                        lexer.nextToken();\n                        stmt.addItem(alterIndex);\n                        break;\n                    }\n\n                    MySqlAlterTableAlterFullTextIndex alterIndex = new MySqlAlterTableAlterFullTextIndex();\n                    alterIndex.setIndexName(indexName);\n\n                    accept(Token.SET);\n                    accept(Token.FULLTEXT);\n\n                    if (lexer.token() == INDEX) {\n                        lexer.nextToken();\n                        alterIndex.setAnalyzerType(AnalyzerIndexType.INDEX);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.QUERY)) {\n                        lexer.nextToken();\n                        alterIndex.setAnalyzerType(AnalyzerIndexType.QUERY);\n                    }\n\n                    acceptIdentifier(\"ANALYZER\");\n\n                    accept(Token.EQ);\n\n                    alterIndex.setAnalyzerName(this.exprParser.name());\n                    stmt.addItem(alterIndex);\n                } else if (lexer.token() == Token.CHECK || lexer.token() == Token.CONSTRAINT) {\n                    lexer.nextToken();\n                    MysqlAlterTableAlterCheck check = new MysqlAlterTableAlterCheck();\n                    check.setName(this.exprParser.name());\n                    boolean enforce = true;\n                    if (lexer.token() == Token.NOT) {\n                        enforce = false;\n                        lexer.nextToken();\n                    }\n                    if (lexer.stringVal().equalsIgnoreCase(\"ENFORCED\")) {\n                        check.setEnforced(enforce);\n                        lexer.nextToken();\n                    }\n                    stmt.addItem(check);\n                } else {\n                    // ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}\n                    if (lexer.token() == Token.COLUMN) {\n                        lexer.nextToken();\n                    }\n                    MySqlAlterTableAlterColumn alterColumn = new MySqlAlterTableAlterColumn();\n                    alterColumn.setColumn(this.exprParser.name());\n                    if (lexer.token() == Token.SET) {\n                        lexer.nextToken();\n                        if (lexer.identifierEquals(\"VISIBLE\") || lexer.identifierEquals(\"INVISIBLE\")) {\n                            alterColumn.setVisibleType(lexer.stringVal());\n                            lexer.nextToken();\n                        } else {\n                            accept(Token.DEFAULT);\n                            alterColumn.setDefaultExpr(this.exprParser.expr());\n                        }\n                    } else {\n                        accept(Token.DROP);\n                        accept(Token.DEFAULT);\n                        alterColumn.setDropDefault(true);\n                    }\n                    stmt.addItem(alterColumn);\n                }\n                return true;\n            }\n\n            // [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]\n            // parse in table options.\n\n            case DISABLE:\n                lexer.nextToken();\n                if (lexer.token() == Token.CONSTRAINT) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n                    SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint();\n                    item.setConstraintName(this.exprParser.name());\n                    stmt.addItem(item);\n                } else {\n                    // DISABLE KEYS\n                    acceptIdentifier(\"KEYS\");\n                    SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys();\n                    stmt.addItem(item);\n                }\n                return true;\n\n            case ENABLE:\n                lexer.nextToken();\n                if (lexer.token() == Token.CONSTRAINT) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n                    SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint();\n                    item.setConstraintName(this.exprParser.name());\n                    stmt.addItem(item);\n                } else {\n                    // ENABLE KEYS\n                    acceptIdentifier(\"KEYS\");\n                    SQLAlterTableEnableKeys item = new SQLAlterTableEnableKeys();\n                    stmt.addItem(item);\n                }\n                return true;\n\n            case LOCK: {\n                // LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                MySqlAlterTableLock item = new MySqlAlterTableLock();\n                item.setLockType(new SQLIdentifierExpr(lexer.stringVal()));\n                lexer.nextToken();\n                stmt.addItem(item);\n                return true;\n            }\n\n            case ORDER: {\n                lexer.nextToken();\n                accept(Token.BY);\n                MySqlAlterTableOrderBy item = new MySqlAlterTableOrderBy();\n                while (true) {\n                    if (lexer.token() == Token.IDENTIFIER) {\n                        SQLSelectOrderByItem column = this.exprParser.parseSelectOrderByItem();\n                        column.setParent(item);\n                        item.addColumn(column);\n                    } else {\n                        break;\n                    }\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                    } else {\n                        break;\n                    }\n                }\n                stmt.addItem(item);\n                return true;\n            }\n\n            case WITH: {\n                // WITH VALIDATION\n                lexer.nextToken();\n                acceptIdentifier(\"VALIDATION\");\n                MySqlAlterTableValidation item = new MySqlAlterTableValidation();\n                item.setWithValidation(true);\n                stmt.addItem(item);\n                return true;\n            }\n\n            case DROP:\n                // DROP [COLUMN] col_name\n                // DROP {INDEX|KEY} index_name\n                // DROP PRIMARY KEY\n                // DROP FOREIGN KEY fk_symbol\n                // DROP PARTITION partition_names\n                // TODO: need check.\n                parseAlterDrop(stmt);\n                return true;\n\n            case TRUNCATE: {\n                // TRUNCATE PARTITION {partition_names | ALL}\n                lexer.nextToken();\n                accept(Token.PARTITION);\n                SQLAlterTableTruncatePartition item = new SQLAlterTableTruncatePartition();\n                if (lexer.token() == Token.ALL) {\n                    item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                    lexer.nextToken();\n                } else {\n                    this.exprParser.names(item.getPartitions(), item);\n                }\n                stmt.addItem(item);\n                return true;\n            }\n\n            case ANALYZE: {\n                // ANALYZE PARTITION {partition_names | ALL}\n                lexer.nextToken();\n                accept(Token.PARTITION);\n                SQLAlterTableAnalyzePartition item = new SQLAlterTableAnalyzePartition();\n                if (lexer.token() == Token.ALL) {\n                    lexer.nextToken();\n                    item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                } else {\n                    this.exprParser.names(item.getPartitions(), item);\n                }\n                stmt.addItem(item);\n                return true;\n            }\n\n            case CHECK: {\n                // CHECK PARTITION {partition_names | ALL}\n                lexer.nextToken();\n                accept(Token.PARTITION);\n                SQLAlterTableCheckPartition item = new SQLAlterTableCheckPartition();\n                if (lexer.token() == Token.ALL) {\n                    lexer.nextToken();\n                    item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                } else {\n                    this.exprParser.names(item.getPartitions(), item);\n                }\n                stmt.addItem(item);\n                return true;\n            }\n\n            case OPTIMIZE: {\n                // OPTIMIZE PARTITION {partition_names | ALL}\n                lexer.nextToken();\n                accept(Token.PARTITION);\n                SQLAlterTableOptimizePartition item = new SQLAlterTableOptimizePartition();\n                if (lexer.token() == Token.ALL) {\n                    lexer.nextToken();\n                    item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                } else {\n                    this.exprParser.names(item.getPartitions(), item);\n                }\n                stmt.addItem(item);\n                return true;\n            }\n\n            //\n            // Other not in MySql documents.\n            //\n\n            case SET: {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.RULE)) {\n                    SQLAlterTableSetOption setOption = new SQLAlterTableSetOption();\n                    SQLAssignItem item = this.exprParser.parseAssignItem();\n                    setOption.addOption(item);\n                    stmt.addItem(setOption);\n                } else {\n                    acceptIdentifier(\"TBLPROPERTIES\");\n                    SQLAlterTableSetOption setOption = new SQLAlterTableSetOption();\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        SQLAssignItem item = this.exprParser.parseAssignItem();\n                        setOption.addOption(item);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    stmt.addItem(setOption);\n\n                    if (lexer.token() == Token.ON) {\n                        lexer.nextToken();\n                        SQLName on = this.exprParser.name();\n                        setOption.setOn(on);\n                    }\n                }\n\n                return true;\n            }\n\n            case PARTITION: {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                    lexer.nextToken();\n                    SQLAlterTablePartitionLifecycle item = new SQLAlterTablePartitionLifecycle();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n                    item.setLifecycle((SQLIntegerExpr) exprParser.integerExpr());\n                    stmt.addItem(item);\n                    return true;\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n        }\n        return false;\n    }\n\n    @Override\n    protected void alterTableAddRest(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"ADD\");\n\n        switch (lexer.token()) {\n            case LPAREN:\n                parseAlterTableAddColumn(stmt);\n                break;\n            // ADD {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (key_part,...) [index_option] ...\n            case IDENTIFIER:\n                if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)\n                        || lexer.identifierEquals(FnvHash.Constants.CLUSTERED)\n                        || lexer.identifierEquals(FnvHash.Constants.CLUSTERING)\n                        || lexer.identifierEquals(FnvHash.Constants.ANN)\n                        || lexer.identifierEquals(FnvHash.Constants.GLOBAL)\n                        || lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n                    // Index.\n                    SQLAlterTableAddIndex item = new SQLAlterTableAddIndex();\n                    this.exprParser.parseIndex(item.getIndexDefinition());\n                    stmt.addItem(item);\n                } else if (lexer.identifierEquals(FnvHash.Constants.EXTPARTITION)) {\n                    // Caution: Not in MySql documents.\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    SQLAlterTableAddExtPartition extPartitionItem = new SQLAlterTableAddExtPartition();\n                    MySqlExtPartition partitionDef = parseExtPartition();\n                    extPartitionItem.setExPartition(partitionDef);\n                    stmt.addItem(extPartitionItem);\n                    accept(Token.RPAREN);\n                } else {\n                    // Add column.\n                    parseAlterTableAddColumn(stmt);\n                }\n                break;\n            default:\n                // Add column.\n                parseAlterTableAddColumn(stmt);\n                break;\n        }\n    }\n\n    protected void alterTableAddPartition(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"ADD\");\n        accept(PARTITION);\n        SQLAlterTableAddPartition item = new SQLAlterTableAddPartition();\n        if (lexer.identifierEquals(\"PARTITIONS\")) {\n            lexer.nextToken();\n            item.setPartitionCount(this.exprParser.integerExpr());\n        }\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                MysqlPartitionSingle partition = this.getExprParser().parsePartition();\n                item.addPartition(partition);\n                if (lexer.token() == COMMA) {\n                    lexer.nextToken();\n\n                    if (lexer.token() == PARTITION) {\n                        continue;\n                    }\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n        stmt.addItem(item);\n    }\n\n    protected void alterTableBefore(SQLAlterTableStatement stmt) {\n        for (;;) {\n            if (lexer.nextIfIdentifier(ONLINE)) {\n                stmt.setOnline(true);\n            } else if (lexer.nextIfIdentifier(OFFLINE)) {\n                stmt.setIgnore(true);\n            } else if (lexer.nextIfIdentifier(IGNORE)) {\n                stmt.setIgnore(true);\n            } else {\n                break;\n            }\n        }\n    }\n\n    protected SQLAlterStatement alterTableAfterName(SQLAlterTableStatement stmt) {\n        while (true) {\n            boolean parsed = ((MySqlExprParser) this.exprParser).parseTableOptions(stmt.getTableOptions(), stmt);\n            if (!parsed) {\n                parsed = parseAlterSpecification(stmt);\n            }\n\n            if (parsed) {\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            } else {\n                break;\n            }\n        }\n\n        // partition_options\n        if (Token.PARTITION == lexer.token()) {\n            SQLPartitionBy partitionBy = this.getSQLCreateTableParser().parsePartitionBy();\n            stmt.setPartition(partitionBy);\n        } else {\n            // Change to rename table if only one rename to xx.\n            if (stmt.getTableOptions().isEmpty() && 1 == stmt.getItems().size() && stmt.getItems().get(0) instanceof SQLAlterTableRename) {\n                MySqlRenameTableStatement renameStmt = new MySqlRenameTableStatement();\n                MySqlRenameTableStatement.Item item = new MySqlRenameTableStatement.Item();\n                item.setName((SQLName) stmt.getTableSource().getExpr());\n                item.setTo(((SQLAlterTableRename) stmt.getItems().get(0)).getToName());\n                renameStmt.addItem(item);\n                return renameStmt;\n            }\n        }\n\n        return stmt;\n    }\n\n    /*\n    protected SQLStatement parseAlterTableOld(boolean ignore) {\n        lexer.nextToken();\n\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.setIgnore(ignore);\n        stmt.setName(this.exprParser.name());\n\n        for_:\n        for (; ; ) {\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n            }\n\n            switch (lexer.token()) {\n                case DROP: {\n                    parseAlterDrop(stmt);\n                    break;\n                }\n                case TRUNCATE: {\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableTruncatePartition item = new SQLAlterTableTruncatePartition();\n                    if (lexer.token() == Token.ALL) {\n                        item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                        lexer.nextToken();\n                    } else {\n                        this.exprParser.names(item.getPartitions(), item);\n                    }\n                    stmt.addItem(item);\n                    break;\n                }\n                case ALTER: {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.INDEX) {\n                        lexer.nextToken();\n                        MySqlAlterTableAlterFullTextIndex alterIndex = new MySqlAlterTableAlterFullTextIndex();\n                        SQLName indexName = this.exprParser.name();\n                        alterIndex.setIndexName(indexName);\n\n                        accept(Token.SET);\n                        accept(Token.FULLTEXT);\n\n                        if (lexer.token() == Token.INDEX) {\n                            lexer.nextToken();\n                            alterIndex.setAnalyzerType(AnalyzerIndexType.INDEX);\n                        } else if (lexer.identifierEquals(FnvHash.Constants.QUERY)) {\n                            lexer.nextToken();\n                            alterIndex.setAnalyzerType(AnalyzerIndexType.QUERY);\n                        }\n\n                        acceptIdentifier(\"ANALYZER\");\n\n                        accept(Token.EQ);\n\n                        alterIndex.setAnalyzerName(this.exprParser.name());\n                        stmt.addItem(alterIndex);\n                    } else {\n                        if (lexer.token() == Token.COLUMN) {\n                            lexer.nextToken();\n                        }\n\n                        MySqlAlterTableAlterColumn alterColumn = new MySqlAlterTableAlterColumn();\n                        alterColumn.setColumn(this.exprParser.name());\n\n                        if (lexer.token() == Token.SET) {\n                            lexer.nextToken();\n                            accept(Token.DEFAULT);\n\n                            alterColumn.setDefaultExpr(this.exprParser.expr());\n                        } else {\n                            accept(Token.DROP);\n                            accept(Token.DEFAULT);\n                            alterColumn.setDropDefault(true);\n                        }\n\n                        stmt.addItem(alterColumn);\n                    }\n                    break;\n                }\n                case DISABLE: {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.CONSTRAINT) {\n                        lexer.nextToken();\n                        SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint();\n                        item.setConstraintName(this.exprParser.name());\n                        stmt.addItem(item);\n                    } else {\n                        acceptIdentifier(\"KEYS\");\n                        SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys();\n                        stmt.addItem(item);\n                    }\n                    break;\n                }\n                case ENABLE: {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.CONSTRAINT) {\n                        lexer.nextToken();\n                        SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint();\n                        item.setConstraintName(this.exprParser.name());\n                        stmt.addItem(item);\n                    } else {\n                        acceptIdentifier(\"KEYS\");\n                        SQLAlterTableEnableKeys item = new SQLAlterTableEnableKeys();\n                        stmt.addItem(item);\n                    }\n                    break;\n                }\n                case DEFAULT: {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n                        SQLAlterCharacter item = alterTableCharacter();\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        SQLAlterCharacter item = new SQLAlterCharacter();\n                        item.setCollate(this.exprParser.primary());\n                        stmt.addItem(item);\n                    } else {\n                        throw new ParserException(\"TODO \" + lexer.info());\n                    }\n                    continue for_;\n                }\n                case CHECK: {\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableCheckPartition item = new SQLAlterTableCheckPartition();\n\n                    if (lexer.token() == Token.ALL) {\n                        lexer.nextToken();\n                        item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                    } else {\n                        this.exprParser.names(item.getPartitions(), item);\n                    }\n\n                    stmt.addItem(item);\n                    break;\n                }\n                case OPTIMIZE: {\n                    lexer.nextToken();\n\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableOptimizePartition item = new SQLAlterTableOptimizePartition();\n\n                    if (lexer.token() == Token.ALL) {\n                        lexer.nextToken();\n                        item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                    } else {\n                        this.exprParser.names(item.getPartitions(), item);\n                    }\n\n                    stmt.addItem(item);\n                    break;\n                }\n                case ANALYZE: {\n                    lexer.nextToken();\n                    accept(Token.PARTITION);\n\n                    SQLAlterTableAnalyzePartition item = new SQLAlterTableAnalyzePartition();\n\n                    if (lexer.token() == Token.ALL) {\n                        lexer.nextToken();\n                        item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                    } else {\n                        this.exprParser.names(item.getPartitions(), item);\n                    }\n                    stmt.addItem(item);\n                    break;\n                }\n                case COMMENT: {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        accept(Token.EQ);\n                    }\n                    stmt.getTableOptions().put(\"COMMENT\", this.exprParser.charExpr());\n                    continue for_;\n                }\n                case UNION: {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n\n                    accept(Token.LPAREN);\n                    SQLTableSource tableSrc = this.createSQLSelectParser().parseTableSource();\n                    stmt.getTableOptions().put(\"UNION\", tableSrc);\n                    accept(Token.RPAREN);\n                    continue for_;\n                }\n                case SET: {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.RULE)) {\n                        SQLAlterTableSetOption setOption = new SQLAlterTableSetOption();\n                        SQLAssignItem item = this.exprParser.parseAssignItem();\n                        setOption.addOption(item);\n                        stmt.addItem(setOption);\n                    } else {\n                        acceptIdentifier(\"TBLPROPERTIES\");\n                        SQLAlterTableSetOption setOption = new SQLAlterTableSetOption();\n                        accept(Token.LPAREN);\n                        for (; ; ) {\n                            SQLAssignItem item = this.exprParser.parseAssignItem();\n                            setOption.addOption(item);\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                            break;\n                        }\n                        accept(Token.RPAREN);\n                        stmt.addItem(setOption);\n\n                        if (lexer.token() == Token.ON) {\n                            lexer.nextToken();\n                            SQLName on = this.exprParser.name();\n                            setOption.setOn(on);\n                        }\n                    }\n\n                    break;\n                }\n                default: {\n                    if (lexer.identifierEquals(FnvHash.Constants.ADD)) {\n                        lexer.nextToken();\n\n                        if (lexer.token() == Token.COLUMN) {\n                            lexer.nextToken();\n                            parseAlterTableAddColumn(stmt);\n                        } else if (lexer.token() == Token.INDEX\n                                || lexer.token() == Token.FULLTEXT\n                                || lexer.identifierEquals(FnvHash.Constants.SPATIAL)\n                                || lexer.identifierEquals(FnvHash.Constants.CLUSTERED)\n                                || lexer.identifierEquals(FnvHash.Constants.ANN)\n                                || lexer.identifierEquals(FnvHash.Constants.GLOBAL)\n                                || lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n                            SQLAlterTableAddIndex item = parseAlterTableAddIndex();\n                            item.setParent(stmt);\n                            stmt.addItem(item);\n                        } else if (lexer.token() == Token.UNIQUE) {\n                            SQLAlterTableAddIndex item = parseAlterTableAddIndex();\n                            item.setParent(stmt);\n                            stmt.addItem(item);\n                        } else if (lexer.token() == Token.PRIMARY) {\n                            SQLPrimaryKey primaryKey = this.exprParser.parsePrimaryKey();\n                            SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey);\n                            stmt.addItem(item);\n                        } else if (lexer.token() == Token.KEY) {\n                            // throw new ParserException(\"TODO \" + lexer.token() +\n                            // \" \" + lexer.stringVal());\n                            SQLAlterTableAddIndex item = parseAlterTableAddIndex();\n                            item.setParent(stmt);\n                            stmt.addItem(item);\n                        } else if (lexer.identifierEquals(FnvHash.Constants.CLUSTERING)) {\n                            SQLAlterTableAddClusteringKey item = parseAlterTableAddClusteringKey();\n                            item.setParent(stmt);\n                            stmt.addItem(item);\n                        } else if (lexer.token() == Token.FOREIGN) {\n                            MysqlForeignKey fk = this.getExprParser().parseForeignKey();\n                            SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk);\n\n                            stmt.addItem(item);\n                        } else if (lexer.token() == Token.CONSTRAINT) {\n                            lexer.nextToken();\n\n                            if (lexer.token() == Token.PRIMARY) {\n                                SQLPrimaryKey primaryKey = ((MySqlExprParser) this.exprParser).parsePrimaryKey();\n                                SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey);\n                                item.setParent(stmt);\n\n                                stmt.addItem(item);\n                            } else if (lexer.token() == Token.FOREIGN) {\n                                MysqlForeignKey fk = this.getExprParser().parseForeignKey();\n                                fk.setHasConstraint(true);\n\n                                SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk);\n\n                                stmt.addItem(item);\n                            } else if (lexer.token() == Token.UNIQUE) {\n                                SQLUnique unique = this.exprParser.parseUnique();\n                                SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(unique);\n                                stmt.addItem(item);\n                            } else {\n                                SQLName constraintName = this.exprParser.name();\n\n                                if (lexer.token() == Token.PRIMARY) {\n                                    SQLPrimaryKey primaryKey = ((MySqlExprParser) this.exprParser).parsePrimaryKey();\n\n                                    primaryKey.setName(constraintName);\n\n                                    SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey);\n                                    item.setParent(stmt);\n\n                                    stmt.addItem(item);\n                                } else if (lexer.token() == Token.FOREIGN) {\n                                    MysqlForeignKey fk = this.getExprParser().parseForeignKey();\n                                    fk.setName(constraintName);\n                                    fk.setHasConstraint(true);\n\n                                    SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk);\n\n                                    stmt.addItem(item);\n                                } else if (lexer.token() == Token.UNIQUE) {\n                                    SQLUnique unique = this.exprParser.parseUnique();\n                                    SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(unique);\n                                    stmt.addItem(item);\n                                } else {\n                                    throw new ParserException(\"TODO \" + lexer.info());\n                                }\n                            }\n                        } else if (lexer.token() == Token.PARTITION) {\n                            lexer.nextToken();\n\n                            SQLAlterTableAddPartition item = new SQLAlterTableAddPartition();\n\n                            if (lexer.identifierEquals(\"PARTITIONS\")) {\n                                lexer.nextToken();\n                                item.setPartitionCount(this.exprParser.integerExpr());\n                            }\n\n                            if (lexer.token() == Token.LPAREN) {\n                                lexer.nextToken();\n                                SQLPartition partition = this.getExprParser().parsePartition();\n                                accept(Token.RPAREN);\n                                item.addPartition(partition);\n                            }\n\n                            stmt.addItem(item);\n                        } else if (lexer.identifierEquals(FnvHash.Constants.EXTPARTITION)) {\n                            lexer.nextToken();\n                            accept(Token.LPAREN);\n                            SQLAlterTableAddExtPartition extPartitionItem = new SQLAlterTableAddExtPartition();\n                            MySqlExtPartition partitionDef = parseExtPartition();\n                            extPartitionItem.setExPartition(partitionDef);\n                            stmt.addItem(extPartitionItem);\n                            accept(Token.RPAREN);\n                        } else {\n                            parseAlterTableAddColumn(stmt);\n                        }\n                    } else if (lexer.identifierEquals(FnvHash.Constants.CHANGE)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.COLUMN) {\n                            lexer.nextToken();\n                        }\n                        MySqlAlterTableChangeColumn item = new MySqlAlterTableChangeColumn();\n                        item.setColumnName(this.exprParser.name());\n                        item.setNewColumnDefinition(this.exprParser.parseColumn());\n                        if (lexer.identifierEquals(\"AFTER\")) {\n                            lexer.nextToken();\n                            item.setAfterColumn(this.exprParser.name());\n                        } else if (lexer.identifierEquals(\"FIRST\")) {\n                            lexer.nextToken();\n                            if (lexer.token() == Token.IDENTIFIER) {\n                                item.setFirstColumn(this.exprParser.name());\n                            } else {\n                                item.setFirst(true);\n                            }\n                        }\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.MODIFY)) {\n                        lexer.nextToken();\n\n                        if (lexer.token() == Token.COLUMN) {\n                            lexer.nextToken();\n                        }\n\n                        boolean paren = false;\n                        if (lexer.token() == Token.LPAREN) {\n                            paren = true;\n                            lexer.nextToken();\n                        }\n\n                        for (; ; ) {\n                            MySqlAlterTableModifyColumn item = new MySqlAlterTableModifyColumn();\n                            item.setNewColumnDefinition(this.exprParser.parseColumn());\n                            if (lexer.identifierEquals(\"AFTER\")) {\n                                lexer.nextToken();\n                                item.setAfterColumn(this.exprParser.name());\n                            } else if (lexer.identifierEquals(\"FIRST\")) {\n                                lexer.nextToken();\n                                if (lexer.token() == Token.IDENTIFIER) {\n                                    item.setFirstColumn(this.exprParser.name());\n                                } else {\n                                    item.setFirst(true);\n                                }\n                            }\n                            stmt.addItem(item);\n\n                            if (paren && lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                            break;\n                        }\n\n                        if (paren) {\n                            accept(Token.RPAREN);\n                        }\n                    } else if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n                        lexer.nextToken();\n\n                        if (lexer.token() == Token.INDEX) {\n                            lexer.nextToken();\n                            SQLName name = this.exprParser.name();\n                            accept(Token.TO);\n                            SQLName to = this.exprParser.name();\n                            SQLAlterTableRenameIndex item = new SQLAlterTableRenameIndex(name, to);\n                            stmt.addItem(item);\n                            continue for_;\n                        }\n\n                        if (lexer.token() == Token.COLUMN) {\n                            lexer.nextToken();\n\n                            SQLName columnName = exprParser.name();\n                            accept(Token.TO);\n                            SQLName toName = this.exprParser.name();\n                            SQLAlterTableRenameColumn renameColumn = new SQLAlterTableRenameColumn();\n\n                            renameColumn.setColumn(columnName);\n                            renameColumn.setTo(toName);\n                            stmt.addItem(renameColumn);\n                            continue for_;\n                        }\n\n                        if (lexer.token() == Token.TO || lexer.token() == Token.AS) {\n                            lexer.nextToken();\n                        }\n\n                        if (stmt.getItems().size() > 0) {\n                            SQLAlterTableRename item = new SQLAlterTableRename();\n                            SQLName to = this.exprParser.name();\n                            item.setTo(to);\n                            stmt.addItem(item);\n                        } else {\n                            MySqlRenameTableStatement renameStmt = new MySqlRenameTableStatement();\n                            MySqlRenameTableStatement.Item item = new MySqlRenameTableStatement.Item();\n                            item.setName((SQLName) stmt.getTableSource().getExpr());\n                            item.setTo(this.exprParser.name());\n                            renameStmt.addItem(item);\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n\n                                SQLAlterTableRename alterItem = new SQLAlterTableRename();\n                                alterItem.setTo(item.getTo());\n                                stmt.addItem(alterItem);\n                                continue;\n                            } else {\n                                // SQLAlterTableRename\n                                return renameStmt;\n                            }\n\n                        }\n                    } else if (lexer.token() == Token.ORDER) {\n                        throw new ParserException(\"TODO \" + lexer.info());\n                    } else if (lexer.identifierEquals(\"CONVERT\")) {\n                        lexer.nextToken();\n                        accept(Token.TO);\n                        acceptIdentifier(\"CHARACTER\");\n                        accept(Token.SET);\n\n                        SQLAlterTableConvertCharSet item = new SQLAlterTableConvertCharSet();\n                        SQLExpr charset = this.exprParser.primary();\n                        item.setCharset(charset);\n\n                        if (lexer.identifierEquals(\"COLLATE\")) {\n                            lexer.nextToken();\n                            SQLExpr collate = this.exprParser.primary();\n                            item.setCollate(collate);\n                        }\n\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.DISCARD)) {\n                        lexer.nextToken();\n\n                        if (lexer.token() == Token.PARTITION) {\n                            lexer.nextToken();\n                            SQLAlterTableDiscardPartition item = new SQLAlterTableDiscardPartition();\n\n                            if (lexer.token() == Token.ALL) {\n                                lexer.nextToken();\n                                item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                            } else {\n                                this.exprParser.names(item.getPartitions(), item);\n                            }\n\n                            if (lexer.token() == Token.TABLESPACE) {\n                                lexer.nextToken();\n                                item.setTablespace(true);\n                            }\n\n                            stmt.addItem(item);\n                        } else {\n                            accept(Token.TABLESPACE);\n                            MySqlAlterTableDiscardTablespace item = new MySqlAlterTableDiscardTablespace();\n                            stmt.addItem(item);\n                        }\n\n                    } else if (lexer.identifierEquals(\"IMPORT\")) {\n                        lexer.nextToken();\n\n                        if (lexer.token() == Token.PARTITION) {\n                            lexer.nextToken();\n                            SQLAlterTableImportPartition item = new SQLAlterTableImportPartition();\n\n                            if (lexer.token() == Token.ALL) {\n                                lexer.nextToken();\n                                item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                            } else {\n                                this.exprParser.names(item.getPartitions(), item);\n                            }\n\n                            stmt.addItem(item);\n                        } else {\n                            accept(Token.TABLESPACE);\n                            MySqlAlterTableImportTablespace item = new MySqlAlterTableImportTablespace();\n                            stmt.addItem(item);\n                        }\n                    } else if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n                        throw new ParserException(\"TODO \" + lexer.info());\n                    } else if (lexer.identifierEquals(\"COALESCE\")) {\n                        lexer.nextToken();\n                        accept(Token.PARTITION);\n\n                        SQLAlterTableCoalescePartition item = new SQLAlterTableCoalescePartition();\n                        SQLIntegerExpr countExpr = this.exprParser.integerExpr();\n                        item.setCount(countExpr);\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(\"REORGANIZE\")) {\n                        lexer.nextToken();\n                        accept(Token.PARTITION);\n\n                        SQLAlterTableReOrganizePartition item = new SQLAlterTableReOrganizePartition();\n\n                        this.exprParser.names(item.getNames(), item);\n\n                        accept(Token.INTO);\n                        accept(Token.LPAREN);\n                        for (; ; ) {\n                            SQLPartition partition = this.getExprParser().parsePartition();\n\n                            item.addPartition(partition);\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            } else {\n                                break;\n                            }\n                        }\n                        accept(Token.RPAREN);\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.EXCHANGE)) {\n                        lexer.nextToken();\n                        accept(Token.PARTITION);\n\n                        SQLAlterTableExchangePartition item = new SQLAlterTableExchangePartition();\n\n                        SQLName partition = this.exprParser.name();\n                        item.addPartition(partition);\n\n                        accept(Token.WITH);\n                        accept(Token.TABLE);\n                        SQLName table = this.exprParser.name();\n                        item.setTable(table);\n\n                        if (lexer.token() == Token.WITH) {\n                            lexer.nextToken();\n                            acceptIdentifier(\"VALIDATION\");\n                            item.setValidation(true);\n                        } else if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) {\n                            lexer.nextToken();\n                            acceptIdentifier(\"VALIDATION\");\n                            item.setValidation(false);\n                        }\n\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(\"REBUILD\")) {\n                        lexer.nextToken();\n\n                        accept(Token.PARTITION);\n\n                        SQLAlterTableRebuildPartition item = new SQLAlterTableRebuildPartition();\n\n                        if (lexer.token() == Token.ALL) {\n                            lexer.nextToken();\n                            item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                        } else {\n                            this.exprParser.names(item.getPartitions(), item);\n                        }\n\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(\"REPAIR\")) {\n                        lexer.nextToken();\n\n                        accept(Token.PARTITION);\n\n                        SQLAlterTableRepairPartition item = new SQLAlterTableRepairPartition();\n\n                        if (lexer.token() == Token.ALL) {\n                            lexer.nextToken();\n                            item.getPartitions().add(new SQLIdentifierExpr(\"ALL\"));\n                        } else {\n                            this.exprParser.names(item.getPartitions(), item);\n                        }\n\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n                        SQLAlterTablePartitionCount item = new SQLAlterTablePartitionCount();\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        item.setCount((SQLIntegerExpr) exprParser.integerExpr());\n                        stmt.addItem(item);\n                    } else if (lexer.token() == Token.PARTITION) {\n                        lexer.nextToken();\n                        if(lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                            lexer.nextToken();\n                            SQLAlterTablePartitionLifecycle item = new SQLAlterTablePartitionLifecycle();\n                            if (lexer.token() == Token.EQ) {\n                                lexer.nextToken();\n                            }\n                            item.setLifecycle((SQLIntegerExpr) exprParser.integerExpr());\n                            stmt.addItem(item);\n                        }\n                    } else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n                        lexer.nextToken();\n                        if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                            lexer.nextToken();\n                            SQLAlterTableSubpartitionLifecycle item = new SQLAlterTableSubpartitionLifecycle();\n                            if (lexer.token() == Token.LITERAL_INT) {\n                                for (; ; ) {\n                                    item.getPartitionIds().add(this.exprParser.integerExpr());\n                                    String pidStr = lexer.stringVal();\n                                    accept(Token.VARIANT);\n                                    String s = pidStr.replaceAll(\":\", \"\");\n                                    if (StringUtils.isEmpty(s)) {\n                                        item.getSubpartitionLifeCycle().add(exprParser.integerExpr());\n                                    } else {\n                                        item.getSubpartitionLifeCycle().add(new SQLIntegerExpr(Integer.valueOf(s)));\n                                    }\n\n                                    if (lexer.token() == Token.COMMA) {\n                                        lexer.nextToken();\n                                        continue;\n                                    }\n\n                                    break;\n                                }\n                            }\n                            stmt.addItem(item);\n                        }\n                    } else if (lexer.identifierEquals(\"BLOCK_SIZE\")) {\n                        SQLAlterTableBlockSize item = new SQLAlterTableBlockSize();\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            accept(Token.EQ);\n                        }\n                        item.setSize((SQLIntegerExpr) exprParser.expr());\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(\"COMPRESSION\")) {\n                        SQLAlterTableCompression item = new SQLAlterTableCompression();\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        item.setName(exprParser.charExpr());\n                        stmt.addItem(item);\n                        continue for_;\n                    } else if (lexer.identifierEquals(\"REMOVE\")) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"PARTITIONING\");\n                        stmt.setRemovePatiting(true);\n                    } else if (lexer.identifierEquals(\"UPGRADE\")) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"PARTITIONING\");\n                        stmt.setUpgradePatiting(true);\n                    } else if (lexer.identifierEquals(\"ALGORITHM\")) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.addItem(new MySqlAlterTableOption(\"ALGORITHM\", lexer.stringVal()));\n                        lexer.nextToken();\n                        continue for_;\n                    } else if (lexer.identifierEquals(ENGINE)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(ENGINE, this.exprParser.primary());\n                        continue for_;\n                    } else if (lexer.identifierEquals(AUTO_INCREMENT)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(AUTO_INCREMENT, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(AVG_ROW_LENGTH)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(AVG_ROW_LENGTH, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(CHECKSUM2, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.CONNECTION)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(CONNECTION, this.exprParser.charExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.DATA) ||\n                            lexer.token() == Token.INDEX) {\n                        boolean isIndex = lexer.token() == Token.INDEX;\n                        lexer.nextToken();\n                        acceptIdentifier(\"DIRECTORY\");\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(\n                                isIndex ? \"INDEX DIRECTORY\" : \"DATA DIRECTORY\",\n                                this.exprParser.primary());\n                        continue for_;\n                    } else if (lexer.identifierEquals(DELAY_KEY_WRITE)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(DELAY_KEY_WRITE, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.ENCRYPTION)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(ENCRYPTION2, this.exprParser.primary());\n                        continue for_;\n                    } else if (lexer.identifierEquals(INSERT_METHOD)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(INSERT_METHOD, this.exprParser.primary());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.KEY_BLOCK_SIZE)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(KEY_BLOCK_SIZE2, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.MAX_ROWS)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(MAX_ROWS2, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.MIN_ROWS)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(MIN_ROWS2, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.PASSWORD)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(PASSWORD2, this.exprParser.primary());\n                        continue for_;\n                    } else if (lexer.identifierEquals(STATS_AUTO_RECALC)) {\n                        lexer.nextToken();\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(STATS_AUTO_RECALC, this.exprParser.primary());\n                        continue for_;\n                    } else if (lexer.identifierEquals(STATS_PERSISTENT)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(STATS_PERSISTENT, this.exprParser.primary());\n                        continue for_;\n                    } else if (lexer.identifierEquals(STATS_SAMPLE_PAGES)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        stmt.getTableOptions().put(STATS_SAMPLE_PAGES, this.exprParser.integerExpr());\n                        continue for_;\n                    } else if (lexer.token() == Token.TABLESPACE) {\n                        lexer.nextToken();\n                        MySqlCreateTableStatement.TableSpaceOption option = new MySqlCreateTableStatement.TableSpaceOption();\n                        option.setName(this.exprParser.name());\n                        if (lexer.identifierEquals(\"STORAGE\")) {\n                            lexer.nextToken();\n                            option.setStorage(this.exprParser.name());\n                        }\n                        stmt.addItem(new MySqlAlterTableOption(TABLESPACE2, option));\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        SQLAlterCharacter item = new SQLAlterCharacter();\n                        item.setCollate(this.exprParser.primary());\n                        stmt.addItem(item);\n                        continue for_;\n                    } else if (lexer.identifierEquals(\"PACK_KEYS\")) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        if (lexer.identifierEquals(\"PACK\")) {\n                            lexer.nextToken();\n                            accept(Token.ALL);\n                            stmt.getTableOptions().put(\"PACK_KEYS\", new SQLIdentifierExpr(\"PACK ALL\"));\n                        } else {\n                            stmt.getTableOptions().put(\"PACK_KEYS\", this.exprParser.primary());\n                        }\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n                        SQLAlterCharacter item = alterTableCharacter();\n                        stmt.addItem(item);\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n                        SQLAlterTableModifyClusteredBy clusteredBy = new SQLAlterTableModifyClusteredBy();\n\n                        acceptIdentifier(\"CLUSTERED\");\n                        accept(Token.BY);\n                        accept(Token.LPAREN);\n\n                        // for ads: ALTER TABLE SCHEMA1.TABLE1 CLUSTERED BY ();\n                        if (lexer.token() != Token.RPAREN) {\n                            for (; ; ) {\n                                clusteredBy.addClusterColumn(this.exprParser.name());\n\n                                if (lexer.token() == Token.COMMA) {\n                                    accept(Token.COMMA);\n                                    continue;\n                                }\n                                break;\n                            }\n                        }\n\n                        accept(Token.RPAREN);\n\n                        stmt.addItem(clusteredBy);\n                    } else if (lexer.identifierEquals(\"ROW_FORMAT\")) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n\n                        if (lexer.token() == Token.DEFAULT || lexer.token() == Token.IDENTIFIER) {\n                            SQLIdentifierExpr rowFormat = new SQLIdentifierExpr(lexer.stringVal());\n                            lexer.nextToken();\n                            stmt.getTableOptions().put(\"ROW_FORMAT\", rowFormat);\n                        } else {\n                            throw new ParserException(\"illegal syntax. \" + lexer.info());\n                        }\n\n                        continue for_;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION_AVAILABLE_PARTITION_NUM)) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        SQLIntegerExpr num = this.exprParser.integerExpr();\n                        SQLAlterTableSubpartitionAvailablePartitionNum item = new SQLAlterTableSubpartitionAvailablePartitionNum();\n                        item.setNumber(num);\n                        stmt.addItem(item);\n                    } else if (lexer.token() == Token.LOCK) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.EQ) {\n                            lexer.nextToken();\n                        }\n                        SQLIdentifierExpr rowFormat = new SQLIdentifierExpr(lexer.stringVal());\n                        lexer.nextToken();\n                        stmt.getTableOptions().put(\"LOCK\", rowFormat);\n                    } else {\n                        break for_;\n                    }\n                    break;\n                }\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n\n        }\n\n        return stmt;\n    }\n    */\n\n    private MySqlExtPartition parseExtPartition() {\n        MySqlExtPartition partitionDef = new MySqlExtPartition();\n        for (; ; ) {\n            MySqlExtPartition.Item item = new MySqlExtPartition.Item();\n\n            if (lexer.identifierEquals(FnvHash.Constants.DBPARTITION)) {\n                lexer.nextToken();\n                SQLName name = this.exprParser.name();\n                item.setDbPartition(name);\n                accept(Token.BY);\n                SQLExpr value = this.exprParser.primary();\n                item.setDbPartitionBy(value);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TBPARTITION)) {\n                lexer.nextToken();\n                SQLName name = this.exprParser.name();\n                item.setTbPartition(name);\n                accept(Token.BY);\n                SQLExpr value = this.exprParser.primary();\n                item.setTbPartitionBy(value);\n            }\n\n            item.setParent(partitionDef);\n            partitionDef.getItems().add(item);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n        }\n\n        return partitionDef;\n    }\n\n    private SQLAlterCharacter alterTableCharacter() {\n        lexer.nextToken();\n        accept(Token.SET);\n        if (lexer.token() == Token.EQ) {\n            lexer.nextToken();\n        }\n        SQLAlterCharacter item = new SQLAlterCharacter();\n        item.setCharacterSet(this.exprParser.primary());\n        if (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                item.setCollate(this.exprParser.primary());\n            }\n        }\n        return item;\n    }\n\n    protected void parseAlterTableAddColumn(SQLAlterTableStatement stmt) {\n        boolean parenFlag = false;\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            parenFlag = true;\n        }\n\n        SQLAlterTableAddColumn item = new SQLAlterTableAddColumn();\n        for (; ; ) {\n            SQLColumnDefinition columnDef = this.exprParser.parseColumn();\n            item.addColumn(columnDef);\n            if (lexer.identifierEquals(\"AFTER\")) {\n                lexer.nextToken();\n                item.setAfterColumn(this.exprParser.name());\n            } else if (lexer.identifierEquals(\"FIRST\")) {\n                lexer.nextToken();\n                if (lexer.token() == Token.IDENTIFIER) {\n                    item.setFirstColumn(this.exprParser.name());\n                } else {\n                    item.setFirst(true);\n                }\n            }\n\n            if (parenFlag && lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        if (parenFlag) {\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RESTRICT)) {\n            lexer.nextToken();\n            item.setRestrict(true);\n        } else if (lexer.token() == Token.CASCADE || lexer.identifierEquals(FnvHash.Constants.CASCADE)) {\n            lexer.nextToken();\n            item.setCascade(true);\n        } else {\n            item.setCascade(false);\n        }\n\n        stmt.addItem(item);\n    }\n\n    public void parseAlterDrop(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token() == INDEX) {\n            lexer.nextToken();\n            SQLName indexName = this.exprParser.name();\n            SQLAlterTableDropIndex item = new SQLAlterTableDropIndex();\n            item.setIndexName(indexName);\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.FOREIGN) {\n            lexer.nextToken();\n            accept(Token.KEY);\n            SQLName indexName = this.exprParser.name();\n            SQLAlterTableDropForeignKey item = new SQLAlterTableDropForeignKey();\n            item.setIndexName(indexName);\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.KEY) {\n            lexer.nextToken();\n            SQLName keyName = this.exprParser.name();\n            SQLAlterTableDropKey item = new SQLAlterTableDropKey();\n            item.setKeyName(keyName);\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.PRIMARY) {\n            lexer.nextToken();\n            accept(Token.KEY);\n            SQLAlterTableDropPrimaryKey item = new SQLAlterTableDropPrimaryKey();\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.CONSTRAINT) {\n            lexer.nextToken();\n            SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint();\n            item.setConstraintName(this.exprParser.name());\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.CHECK) {\n            lexer.nextToken();\n            SQLAlterTableDropCheck item = new SQLAlterTableDropCheck();\n            item.setCheckName(this.exprParser.name());\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.COLUMN) {\n            lexer.nextToken();\n            SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem();\n            if (lexer.token() == Token.IF) {\n                lexer.nextToken();\n                accept(Token.EXISTS);\n                item.setIfExists(true);\n            }\n            SQLName name = exprParser.name();\n            name.setParent(item);\n            item.addColumn(name);\n\n            if (dbType != DbType.mysql) {\n                while (lexer.token() == Token.COMMA) {\n                    Lexer.SavePoint savePoint = lexer.markOut();\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.CHANGE)\n                            || lexer.identifierEquals(FnvHash.Constants.MODIFY)) {\n                        lexer.reset(savePoint);\n                        break;\n                    }\n\n                    if (lexer.token() == Token.IDENTIFIER) {\n                        if (\"ADD\".equalsIgnoreCase(lexer.stringVal())) {\n                            lexer.reset(savePoint);\n                            break;\n                        }\n                        name = exprParser.name();\n                        name.setParent(item);\n                        item.addColumn(name);\n                    } else {\n                        lexer.reset(savePoint);\n                        break;\n                    }\n                }\n            }\n\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.PARTITION) {\n            SQLAlterTableDropPartition dropPartition = parseAlterTableDropPartition(false);\n            stmt.addItem(dropPartition);\n        } else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n            SQLAlterTableDropSubpartition dropPartition = parseAlterTableDropSubpartition();\n            stmt.addItem(dropPartition);\n        } else if (lexer.identifierEquals(FnvHash.Constants.CLUSTERING) || lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n            lexer.nextToken();\n            SQLAlterTableDropClusteringKey dropPartition = new SQLAlterTableDropClusteringKey();\n            accept(Token.KEY);\n            dropPartition.setKeyName(exprParser.name());\n            stmt.addItem(dropPartition);\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            if (lexer.identifierEquals(FnvHash.Constants.EXTPARTITION)) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                SQLAlterTableDropExtPartition extPartitionItem = new SQLAlterTableDropExtPartition();\n                MySqlExtPartition partitionDef = parseExtPartition();\n                extPartitionItem.setExPartition(partitionDef);\n                stmt.addItem(extPartitionItem);\n                accept(Token.RPAREN);\n            } else {\n                SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem();\n\n                SQLName name = this.exprParser.name();\n                item.addColumn(name);\n                stmt.addItem(item);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n\n                if (lexer.token() == Token.DROP) {\n                    parseAlterDrop(stmt);\n                }\n            }\n        } else {\n            super.parseAlterDrop(stmt);\n        }\n    }\n\n    public SQLStatement parseRename() {\n        acceptIdentifier(\"RENAME\");\n\n        if (lexer.token() == Token.SEQUENCE) {\n            lexer.nextToken();\n            MySqlRenameSequenceStatement stmt = new MySqlRenameSequenceStatement();\n\n            SQLName name = this.exprParser.name();\n            stmt.setName(name);\n\n            accept(Token.TO);\n\n            SQLName to = this.exprParser.name();\n            stmt.setTo(to);\n\n            return stmt;\n        }\n        if (lexer.token() == Token.USER) {\n            lexer.nextToken();\n            SQLRenameUserStatement stmt = new SQLRenameUserStatement();\n\n            SQLName name = this.exprParser.name();\n            stmt.setName(name);\n\n            accept(Token.TO);\n\n            SQLName to = this.exprParser.name();\n            stmt.setTo(to);\n\n            return stmt;\n        }\n\n        accept(TABLE);\n        MySqlRenameTableStatement stmt = new MySqlRenameTableStatement();\n\n        for (; ; ) {\n            MySqlRenameTableStatement.Item item = new MySqlRenameTableStatement.Item();\n            item.setName(this.exprParser.name());\n            accept(Token.TO);\n            item.setTo(this.exprParser.name());\n\n            stmt.addItem(item);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseCreateSchema() {\n        return parseCreateDatabase();\n    }\n\n    public SQLStatement parseCreateDatabase() {\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n\n        SQLCreateDatabaseStatement stmt = new SQLCreateDatabaseStatement(dbType);\n\n        if (lexer.token() == Token.HINT) {\n            List<SQLCommentHint> hints = this.exprParser.parseHints();\n            if (hints.size() == 1) {\n                String text = hints.get(0).getText();\n                if (text.charAt(0) == '!') {\n                    String[] words = text.trim().split(\"\\\\s+\");\n                    if (words.length > 2\n                            && words[words.length - 3].equalsIgnoreCase(\"IF\")\n                            && words[words.length - 2].equalsIgnoreCase(\"NOT\")\n                            && words[words.length - 1].equalsIgnoreCase(\"EXISTS\")) {\n                            stmt.setIfNotExists(true);\n                    }\n                }\n            }\n        }\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.DEFAULT) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.HINT) {\n            List<SQLCommentHint> hints = this.exprParser.parseHints();\n            if (hints.size() == 1) {\n                String text = hints.get(0).getText();\n                if (text.charAt(0) == '!') {\n                    String[] words = text.trim().split(\"\\\\s+\");\n                    int idx = 0;\n                    for (; idx < words.length; idx++) {\n                        if (words[idx].equalsIgnoreCase(\"CHARACTER\")\n                                && idx < words.length - 2 && words[idx + 1].equalsIgnoreCase(\"SET\")) {\n                            stmt.setCharacterSet(words[idx + 2]);\n                            idx += 2;\n                        } else if (words[idx].equalsIgnoreCase(\"COLLATE\")\n                                && idx < words.length - 1) {\n                            stmt.setCollate(words[idx + 1]);\n                            idx += 1;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (lexer.token() == Token.DEFAULT) {\n            lexer.nextToken();\n        }\n\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n                lexer.nextToken();\n                accept(Token.SET);\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                String charset = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n                stmt.setCharacterSet(charset);\n            } else if (lexer.identifierEquals(FnvHash.Constants.CHARSET)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                String charset = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n                stmt.setCharacterSet(charset);\n            } else if (lexer.token() == Token.DEFAULT) {\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                String collate = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n                stmt.setCollate(collate);\n            } else if (lexer.identifierEquals(FnvHash.Constants.PASSWORD)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr password = this.exprParser.primary();\n                stmt.setPassword(password);\n            }\n            //ads 特殊支持\n            else if (lexer.identifierEquals(\"SHARDS\") || lexer.identifierEquals(\"SHARD_ID\")\n                    || lexer.identifierEquals(\"REPLICATION\") || lexer.identifierEquals(\"STORAGE_DEPENDENCY\")\n                    || lexer.identifierEquals(\"REPLICA_TYPE\") || lexer.identifierEquals(\"DATA_REPLICATION\")) {\n                String key = lexer.stringVal();\n                lexer.nextToken();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.expr();\n                stmt.getOptions().put(key, value);\n            } else {\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n            String user = lexer.stringVal();\n            lexer.nextToken();\n            stmt.setUser(user);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.OPTIONS)) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                if (lexer.token() == Token.RPAREN) {\n                    accept(Token.RPAREN);\n                    break;\n                }\n                String key = lexer.stringVal();\n                lexer.nextToken();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.expr();\n                stmt.getOptions().put(key, value);\n            }\n        }\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLAssignItem assignItem = this.exprParser.parseAssignItem();\n                assignItem.setParent(stmt);\n                stmt.getDbProperties().add(assignItem);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.BY) {\n                accept(Token.BY);\n\n                for (; ; ) {\n                    List<SQLAssignItem> storedByItem = new ArrayList<SQLAssignItem>();\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        SQLAssignItem assignItem = this.exprParser.parseAssignItem();\n                        assignItem.setParent(stmt);\n                        storedByItem.add(assignItem);\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    stmt.getStoredBy().add(storedByItem);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n\n                    break;\n                }\n            } else if (lexer.token() == Token.IN) {\n                lexer.nextToken();\n\n                stmt.setStoredIn(this.exprParser.name());\n\n                accept(Token.ON);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLAssignItem assignItem = this.exprParser.parseAssignItem();\n                    assignItem.setParent(stmt);\n                    stmt.getStoredOn().add(assignItem);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            } else if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n                SQLExpr like = this.exprParser.expr();\n                stmt.setStoredAs(like);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        return stmt;\n    }\n\n    protected void parseUpdateSet(SQLUpdateStatement update) {\n        accept(Token.SET);\n\n        for (; ; ) {\n            SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n            update.addItem(item);\n\n            if (lexer.token() != Token.COMMA) {\n                break;\n            }\n\n            lexer.nextToken();\n        }\n    }\n\n    protected SQLStatement alterSchema() {\n        return alterDatabase();\n    }\n\n    public SQLStatement alterDatabase() {\n        lexer.nextIf(ALTER);\n\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n\n        SQLAlterDatabaseStatement stmt = new SQLAlterDatabaseStatement(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n            MySqlAlterDatabaseSetOption option = new MySqlAlterDatabaseSetOption();\n            for (; ; ) {\n                SQLName key = this.exprParser.name();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.expr();\n\n                option.getOptions().add(new SQLAssignItem(key, value));\n\n                if (lexer.token() == Token.EOF || lexer.token() == Token.ON) {\n                    break;\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                }\n            }\n            stmt.setItem(option);\n\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                SQLName on = this.exprParser.name();\n                option.setOn(on);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.token() == Token.KILL) {\n            MySqlAlterDatabaseKillJob item = new MySqlAlterDatabaseKillJob();\n            lexer.nextToken();\n            SQLName jobType = this.exprParser.name();\n            SQLName jobId = this.exprParser.name();\n            item.setJobType(jobType);\n            item.setJobId(jobId);\n\n            stmt.setItem(item);\n        }\n\n        if (lexer.identifierEquals(\"UPGRADE\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"DATA\");\n            acceptIdentifier(\"DIRECTORY\");\n            acceptIdentifier(\"NAME\");\n            stmt.setUpgradeDataDirectoryName(true);\n        }\n\n        if (lexer.token() == Token.DEFAULT) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n                SQLAlterCharacter item = alterTableCharacter();\n                stmt.setCharacter(item);\n            } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLAlterCharacter character = new SQLAlterCharacter();\n                character.setCollate(this.exprParser.primary());\n                stmt.setCharacter(character);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n            SQLAlterCharacter item = alterTableCharacter();\n            stmt.setCharacter(item);\n        } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLAlterCharacter character = new SQLAlterCharacter();\n            character.setCollate(this.exprParser.primary());\n            stmt.setCharacter(character);\n        }\n\n        return stmt;\n    }\n\n    public MySqlAlterUserStatement alterUser() {\n        accept(Token.USER);\n\n        MySqlAlterUserStatement stmt = new MySqlAlterUserStatement();\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        for (; ; ) {\n            MySqlAlterUserStatement.AlterUser alterUser = new MySqlAlterUserStatement.AlterUser();\n\n            SQLExpr user = this.exprParser.expr();\n            alterUser.setUser(user);\n            if (lexer.identifierEquals(\"ACCOUNT\")) {\n                lexer.nextToken();\n                alterUser.setAccountLockOption(lexer.stringVal());\n                lexer.nextToken();\n            }\n            if (lexer.identifierEquals(\"IDENTIFIED\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n\n                MySqlAlterUserStatement.AuthOption authOption = new MySqlAlterUserStatement.AuthOption();\n                SQLCharExpr authString = this.exprParser.charExpr();\n                authOption.setAuthString(authString);\n\n                alterUser.setAuthOption(authOption);\n            }\n\n            if (lexer.identifierEquals(\"PASSWORD\")) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"EXPIRE\")) {\n                    lexer.nextToken();\n\n                    MySqlAlterUserStatement.PasswordOption passwordOption = new MySqlAlterUserStatement.PasswordOption();\n\n                    if (lexer.token() == Token.DEFAULT) {\n                        lexer.nextToken();\n                        passwordOption.setExpire(MySqlAlterUserStatement.PasswordExpire.PASSWORD_EXPIRE_DEFAULT);\n                    } else if (lexer.identifierEquals(\"NEVER\")) {\n                        lexer.nextToken();\n                        passwordOption.setExpire(MySqlAlterUserStatement.PasswordExpire.PASSWORD_EXPIRE_NEVER);\n                    } else if (lexer.token() == Token.INTERVAL) {\n                        lexer.nextToken();\n                        passwordOption.setExpire(MySqlAlterUserStatement.PasswordExpire.PASSWORD_EXPIRE_INTERVAL);\n                        SQLIntegerExpr days = this.exprParser.integerExpr();\n                        passwordOption.setIntervalDays(days);\n                        acceptIdentifier(\"DAY\");\n                    } else {\n                        passwordOption.setExpire(MySqlAlterUserStatement.PasswordExpire.PASSWORD_EXPIRE);\n                    }\n                    stmt.setPasswordOption(passwordOption);\n                }\n            }\n\n            stmt.getAlterUsers().add(alterUser);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n        return stmt;\n    }\n\n    @Override\n    public MySqlExprParser getExprParser() {\n        return (MySqlExprParser) exprParser;\n    }\n\n    public SQLCreateFunctionStatement parseCreateFunction() {\n        SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.OR) {\n                lexer.nextToken();\n                accept(Token.REPLACE);\n                stmt.setOrReplace(true);\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLName definer = this.getExprParser().userName();\n            stmt.setDefiner(definer);\n        }\n\n        accept(Token.FUNCTION);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.LPAREN) { // match \"(\"\n            lexer.nextToken();\n            parserParameters(stmt.getParameters(), stmt);\n            accept(Token.RPAREN); // match \")\"\n        }\n\n        acceptIdentifier(\"RETURNS\");\n        SQLDataType dataType = this.exprParser.parseDataType();\n        stmt.setReturnDataType(dataType);\n\n        for (; ; ) {\n            if (lexer.identifierEquals(\"DETERMINISTIC\")) {\n                lexer.nextToken();\n                stmt.setDeterministic(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"DETERMINISTIC\")) {\n                lexer.nextToken();\n                stmt.setDeterministic(true);\n                continue;\n            }\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                stmt.setComment(lexer.stringVal());\n                lexer.nextToken();\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"LANGUAGE\")) {\n                lexer.nextToken();\n                stmt.setLanguage(lexer.stringVal());\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        SQLStatement block;\n        if (lexer.token() == Token.BEGIN) {\n            block = this.parseBlock();\n        } else {\n            block = this.parseStatement();\n        }\n\n        stmt.setBlock(block);\n\n        return stmt;\n    }\n\n    /**\n     * parse create procedure statement\n     */\n    public SQLCreateProcedureStatement parseCreateProcedure() {\n        /**\n         * CREATE OR REPALCE PROCEDURE SP_NAME(parameter_list) BEGIN block_statement END\n         */\n        SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.OR) {\n                lexer.nextToken();\n                accept(Token.REPLACE);\n                stmt.setOrReplace(true);\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLName definer = this.getExprParser().userName();\n            stmt.setDefiner(definer);\n        }\n\n        accept(Token.PROCEDURE);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            parserParameters(stmt.getParameters(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                stmt.setComment(this.exprParser.charExpr());\n            }\n            if (lexer.identifierEquals(FnvHash.Constants.LANGUAGE)) {\n                lexer.nextToken();\n                acceptIdentifier(\"SQL\");\n                stmt.setLanguageSql(true);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DETERMINISTIC)) {\n                lexer.nextToken();\n                stmt.setDeterministic(true);\n                continue;\n            }\n            if (lexer.identifierEquals(FnvHash.Constants.CONTAINS) || lexer.token() == Token.CONTAINS) {\n                lexer.nextToken();\n                acceptIdentifier(\"SQL\");\n                stmt.setContainsSql(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.SQL)) {\n                lexer.nextToken();\n                acceptIdentifier(\"SECURITY\");\n                SQLName authid = this.exprParser.name();\n                stmt.setAuthid(authid);\n            }\n\n            break;\n        }\n\n        SQLStatement block;\n        if (lexer.token() == Token.BEGIN) {\n            block = this.parseBlock();\n        } else {\n            block = this.parseStatement();\n        }\n\n        stmt.setBlock(block);\n\n        return stmt;\n    }\n\n    /**\n     * parse procedure statement block\n     *\n     * @param statementList\n     */\n    private void parseProcedureStatementList(List<SQLStatement> statementList) {\n        parseProcedureStatementList(statementList, -1);\n    }\n\n    /**\n     * parse procedure statement block\n     */\n    private void parseProcedureStatementList(List<SQLStatement> statementList, int max) {\n        for (; ; ) {\n            if (max != -1) {\n                if (statementList.size() >= max) {\n                    return;\n                }\n            }\n\n            if (lexer.token() == Token.EOF) {\n                return;\n            }\n            if (lexer.token() == Token.END) {\n                return;\n            }\n            if (lexer.token() == Token.ELSE) {\n                return;\n            }\n            if (lexer.token() == (SEMI)) {\n                lexer.nextToken();\n                continue;\n            }\n            if (lexer.token() == Token.WHEN) {\n                return;\n            }\n            if (lexer.token() == Token.UNTIL) {\n                return;\n            }\n            // select into\n            if (lexer.token() == (Token.SELECT)) {\n                statementList.add(this.parseSelectInto());\n                continue;\n            }\n\n            // update\n            if (lexer.token() == (Token.UPDATE)) {\n                statementList.add(parseUpdateStatement());\n                continue;\n            }\n\n            // create\n            if (lexer.token() == (Token.CREATE)) {\n                statementList.add(parseCreate());\n                continue;\n            }\n\n            // insert\n            if (lexer.token() == Token.INSERT) {\n                SQLStatement stmt = parseInsert();\n                statementList.add(stmt);\n                continue;\n            }\n\n            // delete\n            if (lexer.token() == (Token.DELETE)) {\n                statementList.add(parseDeleteStatement());\n                continue;\n            }\n\n            // call\n            if (lexer.token() == Token.LBRACE || lexer.identifierEquals(\"CALL\")) {\n                statementList.add(this.parseCall());\n                continue;\n            }\n\n            // begin\n            if (lexer.token() == Token.BEGIN) {\n                statementList.add(this.parseBlock());\n                continue;\n            }\n\n            if (lexer.token() == Token.VARIANT) {\n                SQLExpr variant = this.exprParser.primary();\n                if (variant instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) variant;\n                    if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) {\n                        SQLSetStatement stmt = new SQLSetStatement(binaryOpExpr.getLeft(), binaryOpExpr.getRight(),\n                                getDbType());\n                        statementList.add(stmt);\n                        continue;\n                    }\n                }\n                accept(Token.COLONEQ);\n                SQLExpr value = this.exprParser.expr();\n\n                SQLSetStatement stmt = new SQLSetStatement(variant, value, getDbType());\n                statementList.add(stmt);\n                continue;\n            }\n\n            // select\n            if (lexer.token() == Token.LPAREN) {\n                Lexer.SavePoint savePoint = lexer.markOut();\n                lexer.nextToken();\n\n                if (lexer.token() == Token.SELECT) {\n                    lexer.reset(savePoint);\n                    statementList.add(this.parseSelect());\n                    continue;\n                } else {\n                    throw new ParserException(\"TODO. \" + lexer.info());\n                }\n            }\n            // assign statement\n            if (lexer.token() == Token.SET) {\n                statementList.add(this.parseAssign());\n                continue;\n            }\n\n            // while statement\n            if (lexer.token() == Token.WHILE) {\n                SQLStatement stmt = this.parseWhile();\n                statementList.add(stmt);\n                continue;\n            }\n\n            // loop statement\n            if (lexer.token() == Token.LOOP) {\n                statementList.add(this.parseLoop());\n                continue;\n            }\n\n            // if statement\n            if (lexer.token() == Token.IF) {\n                statementList.add(this.parseIf());\n                continue;\n            }\n\n            // case statement\n            if (lexer.token() == Token.CASE) {\n                statementList.add(this.parseCase());\n                continue;\n            }\n\n            // declare statement\n            if (lexer.token() == Token.DECLARE) {\n                SQLStatement stmt = this.parseDeclare();\n                statementList.add(stmt);\n                continue;\n            }\n\n            // leave statement\n            if (lexer.token() == Token.LEAVE) {\n                statementList.add(this.parseLeave());\n                continue;\n            }\n\n            // iterate statement\n            if (lexer.token() == Token.ITERATE) {\n                statementList.add(this.parseIterate());\n                continue;\n            }\n\n            // repeat statement\n            if (lexer.token() == Token.REPEAT) {\n                statementList.add(this.parseRepeat());\n                continue;\n            }\n\n            // open cursor\n            if (lexer.token() == Token.OPEN) {\n                statementList.add(this.parseOpen());\n                continue;\n            }\n\n            // close cursor\n            if (lexer.token() == Token.CLOSE) {\n                statementList.add(this.parseClose());\n                continue;\n            }\n\n            // fetch cursor into\n            if (lexer.token() == Token.FETCH) {\n                statementList.add(this.parseFetch());\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) {\n                statementList.add(this.parseChecksum());\n                continue;\n            }\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                String label = lexer.stringVal();\n                Lexer.SavePoint savePoint = lexer.markOut();\n                lexer.nextToken();\n                if (lexer.token() == Token.VARIANT && lexer.stringVal().equals(\":\")) {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.LOOP) {\n                        // parse loop statement\n                        statementList.add(this.parseLoop(label));\n                    } else if (lexer.token() == Token.WHILE) {\n                        // parse while statement with label\n                        statementList.add(this.parseWhile(label));\n                    } else if (lexer.token() == Token.BEGIN) {\n                        // parse begin-end statement with label\n                        statementList.add(this.parseBlock(label));\n                    } else if (lexer.token() == Token.REPEAT) {\n                        // parse repeat statement with label\n                        statementList.add(this.parseRepeat(label));\n                    }\n                    continue;\n                } else {\n                    lexer.reset(savePoint);\n                }\n\n            }\n            throw new ParserException(\"TODO, \" + lexer.info());\n        }\n\n    }\n\n    public MySqlChecksumTableStatement parseChecksum() {\n        MySqlChecksumTableStatement stmt = new MySqlChecksumTableStatement();\n        if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) {\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n\n        accept(TABLE);\n\n        for (; ; ) {\n            SQLName table = this.exprParser.name();\n            stmt.addTable(new SQLExprTableSource(table));\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        return stmt;\n    }\n\n    @Override\n    protected void parseIfElse(SQLIfStatement stmt) {\n        while (lexer.nextIf(Token.ELSEIF)) {\n            SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf();\n            elseIf.setCondition(this.exprParser.expr());\n            elseIf.setParent(stmt);\n            accept(Token.THEN);\n            this.parseStatementList(elseIf.getStatements(), -1, elseIf);\n            stmt.getElseIfList().add(elseIf);\n        }\n\n        while (lexer.nextIf(Token.ELSE)) {\n            if (lexer.nextIf(Token.IF)) {\n                SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf();\n\n                elseIf.setCondition(this.exprParser.expr());\n                elseIf.setParent(stmt);\n\n                accept(Token.THEN);\n                this.parseStatementList(elseIf.getStatements(), -1, elseIf);\n\n                stmt.getElseIfList().add(elseIf);\n            } else {\n                SQLIfStatement.Else elseItem = new SQLIfStatement.Else();\n                this.parseStatementList(elseItem.getStatements(), -1, elseItem);\n                stmt.setElseItem(elseItem);\n                break;\n            }\n        }\n    }\n\n    /**\n     * parse while statement with label\n     *\n     * @return MySqlWhileStatement\n     */\n    public SQLWhileStatement parseWhile(String label) {\n        accept(Token.WHILE);\n\n        SQLWhileStatement stmt = new SQLWhileStatement();\n\n        stmt.setLabelName(label);\n\n        stmt.setCondition(this.exprParser.expr());\n\n        accept(Token.DO);\n\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n\n        accept(Token.END);\n\n        accept(Token.WHILE);\n\n        acceptIdentifier(label);\n\n        accept(SEMI);\n\n        stmt.setAfterSemi(true);\n\n        return stmt;\n\n    }\n\n    /**\n     * parse case statement\n     *\n     * @return MySqlCaseStatement\n     */\n    public MySqlCaseStatement parseCase() {\n        MySqlCaseStatement stmt = new MySqlCaseStatement();\n        accept(Token.CASE);\n\n        if (lexer.token() == Token.WHEN)// grammar 1\n        {\n            while (lexer.token() == Token.WHEN) {\n                MySqlWhenStatement when = new MySqlWhenStatement();\n\n                accept(Token.WHEN);\n\n                // when expr\n                when.setCondition(exprParser.expr());\n\n                accept(Token.THEN);\n\n                // when block\n                this.parseStatementList(when.getStatements(), -1, when);\n\n                stmt.addWhenStatement(when);\n            }\n            if (lexer.token() == Token.ELSE) {\n                // parse else block\n                SQLIfStatement.Else elseStmt = new SQLIfStatement.Else();\n                this.parseStatementList(elseStmt.getStatements(), -1, elseStmt);\n                stmt.setElseItem(elseStmt);\n            }\n        } else {\n            // case expr\n            stmt.setCondition(exprParser.expr());\n\n            while (lexer.token() == Token.WHEN) {\n                accept(Token.WHEN);\n                MySqlWhenStatement when = new MySqlWhenStatement();\n                // when expr\n                when.setCondition(exprParser.expr());\n\n                accept(Token.THEN);\n\n                // when block\n                this.parseStatementList(when.getStatements(), -1, when);\n\n                stmt.addWhenStatement(when);\n            }\n            if (lexer.token() == Token.ELSE) {\n                accept(Token.ELSE);\n                // else block\n                SQLIfStatement.Else elseStmt = new SQLIfStatement.Else();\n                this.parseStatementList(elseStmt.getStatements(), -1, elseStmt);\n                stmt.setElseItem(elseStmt);\n            }\n        }\n        accept(Token.END);\n        accept(Token.CASE);\n        accept(SEMI);\n        return stmt;\n\n    }\n\n    /**\n     * parse declare statement\n     */\n    public SQLStatement parseDeclare() {\n        Lexer.SavePoint savePoint = lexer.markOut();\n\n        lexer.nextToken();\n\n        if (lexer.token() == Token.CONTINUE) {\n            lexer.reset(savePoint);\n            return this.parseDeclareHandler();\n        }\n\n        lexer.nextToken();\n        if (lexer.token() == Token.CURSOR) {\n            lexer.reset(savePoint);\n            return this.parseCursorDeclare();\n        } else if (lexer.identifierEquals(\"HANDLER\")) {\n            //DECLARE异常处理程序 [add by zhujun 2016-04-16]\n            lexer.reset(savePoint);\n            return this.parseDeclareHandler();\n        } else if (lexer.token() == Token.CONDITION) {\n            //DECLARE异常 [add by zhujun 2016-04-17]\n            lexer.reset(savePoint);\n            return this.parseDeclareCondition();\n        } else {\n            lexer.reset(savePoint);\n        }\n\n        MySqlDeclareStatement stmt = new MySqlDeclareStatement();\n        accept(Token.DECLARE);\n        // lexer.nextToken();\n        for (; ; ) {\n            SQLDeclareItem item = new SQLDeclareItem();\n            item.setName(exprParser.name());\n\n            stmt.addVar(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                stmt.setAfterSemi(true);\n                continue;\n            } else if (lexer.token() != Token.EOF) {\n                // var type\n                item.setDataType(exprParser.parseDataType());\n\n                if (lexer.token() == Token.DEFAULT) {\n                    lexer.nextToken();\n                    SQLExpr defaultValue = this.exprParser.primary();\n                    item.setValue(defaultValue);\n                }\n\n                break;\n            } else {\n                throw new ParserException(\"TODO. \" + lexer.info());\n            }\n        }\n        return stmt;\n    }\n\n    /**\n     * parse assign statement\n     */\n    public SQLSetStatement parseAssign() {\n        accept(Token.SET);\n        SQLSetStatement stmt = new SQLSetStatement(getDbType());\n        parseAssignItems(stmt.getItems(), stmt);\n        return stmt;\n    }\n\n    /**\n     * parse select into\n     */\n    public MySqlSelectIntoStatement parseSelectInto() {\n        MySqlSelectIntoParser parse = new MySqlSelectIntoParser(this.exprParser);\n        return parse.parseSelectInto();\n    }\n\n    /**\n     * parse loop statement\n     */\n    @Override\n    public SQLLoopStatement parseLoop() {\n        SQLLoopStatement loopStmt = new SQLLoopStatement();\n        accept(Token.LOOP);\n        this.parseStatementList(loopStmt.getStatements(), -1, loopStmt);\n        accept(Token.END);\n        accept(Token.LOOP);\n        accept(SEMI);\n        loopStmt.setAfterSemi(true);\n        return loopStmt;\n    }\n\n    /**\n     * parse loop statement with label\n     */\n    public SQLLoopStatement parseLoop(String label) {\n        SQLLoopStatement loopStmt = new SQLLoopStatement();\n        loopStmt.setLabelName(label);\n        accept(Token.LOOP);\n        this.parseStatementList(loopStmt.getStatements(), -1, loopStmt);\n        accept(Token.END);\n        accept(Token.LOOP);\n        if (lexer.token() != SEMI) {\n            acceptIdentifier(label);\n        }\n        accept(SEMI);\n        loopStmt.setAfterSemi(true);\n        return loopStmt;\n    }\n\n    /**\n     * parse loop statement with label\n     */\n    public SQLBlockStatement parseBlock(String label) {\n        SQLBlockStatement block = new SQLBlockStatement();\n        block.setLabelName(label);\n        accept(Token.BEGIN);\n        this.parseStatementList(block.getStatementList(), -1, block);\n        accept(Token.END);\n        acceptIdentifier(label);\n        return block;\n    }\n\n    /**\n     * parse leave statement\n     */\n    public MySqlLeaveStatement parseLeave() {\n        accept(Token.LEAVE);\n        MySqlLeaveStatement leaveStmt = new MySqlLeaveStatement();\n        leaveStmt.setLabelName(exprParser.name().getSimpleName());\n        accept(SEMI);\n        return leaveStmt;\n    }\n\n    /**\n     * parse iterate statement\n     */\n    public MySqlIterateStatement parseIterate() {\n        accept(Token.ITERATE);\n        MySqlIterateStatement iterateStmt = new MySqlIterateStatement();\n        iterateStmt.setLabelName(exprParser.name().getSimpleName());\n        accept(SEMI);\n        return iterateStmt;\n    }\n\n    /**\n     * parse repeat statement\n     */\n    public MySqlRepeatStatement parseRepeat() {\n        MySqlRepeatStatement stmt = new MySqlRepeatStatement();\n        accept(Token.REPEAT);\n        parseStatementList(stmt.getStatements(), -1, stmt);\n        accept(Token.UNTIL);\n        stmt.setCondition(exprParser.expr());\n        accept(Token.END);\n        accept(Token.REPEAT);\n        accept(SEMI);\n        stmt.setAfterSemi(true);\n        return stmt;\n    }\n\n    /**\n     * Parses a REPEAT statement and returns a MySqlRepeatStatement object representing the parsed statement.\n     *\n     * @param label the label associated with the REPEAT statement\n     * @return a MySqlRepeatStatement object representing the parsed REPEAT statement\n     */\n    public MySqlRepeatStatement parseRepeat(String label) {\n        MySqlRepeatStatement repeatStmt = new MySqlRepeatStatement();\n        repeatStmt.setLabelName(label);\n        accept(Token.REPEAT);\n        this.parseStatementList(repeatStmt.getStatements(), -1, repeatStmt);\n        accept(Token.UNTIL);\n        repeatStmt.setCondition(exprParser.expr());\n        accept(Token.END);\n        accept(Token.REPEAT);\n        acceptIdentifier(label);\n        accept(SEMI);\n        return repeatStmt;\n    }\n\n    /**\n     * parse cursor declare statement\n     */\n    public MySqlCursorDeclareStatement parseCursorDeclare() {\n        MySqlCursorDeclareStatement stmt = new MySqlCursorDeclareStatement();\n        accept(Token.DECLARE);\n\n        stmt.setCursorName(exprParser.name());\n\n        accept(Token.CURSOR);\n\n        accept(Token.FOR);\n\n        //SQLSelectStatement selelctStmt = (SQLSelectStatement) parseSelect();\n        SQLSelect select = this.createSQLSelectParser().select();\n        stmt.setSelect(select);\n\n        accept(SEMI);\n\n        return stmt;\n    }\n\n    /**\n     * zhujun [455910092@qq.com]\n     * parse spstatement\n     */\n    public SQLStatement parseSpStatement() {\n        // update\n        if (lexer.token() == (Token.UPDATE)) {\n            return parseUpdateStatement();\n        }\n\n        // create\n        if (lexer.token() == (Token.CREATE)) {\n            return parseCreate();\n        }\n\n        // insert\n        if (lexer.token() == Token.INSERT) {\n            return parseInsert();\n        }\n\n        // delete\n        if (lexer.token() == (Token.DELETE)) {\n            return parseDeleteStatement();\n        }\n\n        // begin\n        if (lexer.token() == Token.BEGIN) {\n            return this.parseBlock();\n        }\n\n        // select\n        if (lexer.token() == Token.LPAREN) {\n            Lexer.SavePoint savePoint = lexer.markOut();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.SELECT) {\n                lexer.reset(savePoint);\n                return this.parseSelect();\n            } else {\n                throw new ParserException(\"TODO. \" + lexer.info());\n            }\n        }\n        // assign statement\n        if (lexer.token() == Token.SET) {\n            return parseAssign();\n        }\n\n        throw new ParserException(\"error sp_statement. \" + lexer.info());\n    }\n\n    /**\n     * 定义异常处理程序\n     *\n     * @author zhujun [455910092@qq.com]\n     * 2016-04-16\n     */\n    public MySqlDeclareHandlerStatement parseDeclareHandler() {\n        //DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement\n        //handler_type 取值为 CONTINUE | EXIT | UNDO\n        //condition_value 取值为 SQLWARNING | NOT FOUND | SQLEXCEPTION | SQLSTATE value(异常码 e.g 1062)\n\n        MySqlDeclareHandlerStatement stmt = new MySqlDeclareHandlerStatement();\n        accept(Token.DECLARE);\n        //String handlerType = exprParser.name().getSimpleName();\n        if (lexer.token() == Token.CONTINUE) {\n            stmt.setHandleType(MySqlHandlerType.CONTINUE);\n        } else if (lexer.token() == Token.EXIT) {\n            stmt.setHandleType(MySqlHandlerType.CONTINUE);\n        } else if (lexer.token() == Token.UNDO) {\n            stmt.setHandleType(MySqlHandlerType.CONTINUE);\n        } else {\n            throw new ParserException(\"unkown handle type. \" + lexer.info());\n        }\n        lexer.nextToken();\n\n        acceptIdentifier(\"HANDLER\");\n\n        accept(Token.FOR);\n\n        for (; ; ) {\n            String tokenName = lexer.stringVal();\n            ConditionValue condition = new ConditionValue();\n\n            if (tokenName.equalsIgnoreCase(\"NOT\")) {\n                //for 'NOT FOUND'\n                lexer.nextToken();\n                acceptIdentifier(\"FOUND\");\n                condition.setType(ConditionType.SYSTEM);\n                condition.setValue(\"NOT FOUND\");\n\n            } else if (tokenName.equalsIgnoreCase(\"SQLSTATE\")) {\n                //for SQLSTATE (SQLSTATE '10001')\n                condition.setType(ConditionType.SQLSTATE);\n                lexer.nextToken();\n                //condition.setValue(lexer.stringVal());\n                //lexer.nextToken();\n                condition.setValue(exprParser.name().toString());\n            } else if (lexer.identifierEquals(\"SQLEXCEPTION\")) {\n                //for SQLEXCEPTION\n                condition.setType(ConditionType.SYSTEM);\n                condition.setValue(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"SQLWARNING\")) {\n                //for SQLWARNING\n                condition.setType(ConditionType.SYSTEM);\n                condition.setValue(lexer.stringVal());\n                lexer.nextToken();\n            } else { //for condition_name or mysql_error_code\n                if (lexer.token() == Token.LITERAL_INT) {\n                    condition.setType(ConditionType.MYSQL_ERROR_CODE);\n                    condition.setValue(lexer.integerValue().toString());\n                } else {\n                    condition.setType(ConditionType.SELF);\n                    condition.setValue(tokenName);\n                }\n                lexer.nextToken();\n            }\n            stmt.getConditionValues().add(condition);\n            if (lexer.token() == Token.COMMA) {\n                accept(Token.COMMA);\n                continue;\n            } else if (lexer.token() != Token.EOF) {\n                break;\n            } else {\n                throw new ParserException(\"declare handle not eof\");\n            }\n        }\n\n        stmt.setSpStatement(parseSpStatement());\n\n        if (!(stmt.getSpStatement() instanceof SQLBlockStatement)) {\n            accept(SEMI);\n        }\n\n        return stmt;\n    }\n\n    /**\n     * zhujun [455910092@qq.com]\n     * 2016-04-17\n     * 定义条件\n     */\n    public MySqlDeclareConditionStatement parseDeclareCondition() {\n        MySqlDeclareConditionStatement stmt = new MySqlDeclareConditionStatement();\n        accept(Token.DECLARE);\n\n        stmt.setConditionName(exprParser.name().toString());\n\n        accept(Token.CONDITION);\n\n        accept(Token.FOR);\n\n        String tokenName = lexer.stringVal();\n        ConditionValue condition = new ConditionValue();\n        if (tokenName.equalsIgnoreCase(\"SQLSTATE\")) { //for SQLSTATE (SQLSTATE '10001')\n            condition.setType(ConditionType.SQLSTATE);\n            lexer.nextToken();\n            condition.setValue(exprParser.name().toString());\n        } else if (lexer.token() == Token.LITERAL_INT) {\n            condition.setType(ConditionType.MYSQL_ERROR_CODE);\n            condition.setValue(lexer.integerValue().toString());\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"declare condition grammer error. \" + lexer.info());\n        }\n\n        stmt.setConditionValue(condition);\n\n        accept(SEMI);\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseFlashback() {\n        MySqlFlashbackStatement stmt = new MySqlFlashbackStatement();\n        acceptIdentifier(\"FLASHBACK\");\n        accept(TABLE);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n        accept(Token.TO);\n        acceptIdentifier(\"BEFORE\");\n        accept(Token.DROP);\n\n        if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n            lexer.nextToken();\n            accept(Token.TO);\n            SQLName to = this.exprParser.name();\n            stmt.setRenameTo(to);\n        }\n\n        return stmt;\n    }\n\n    public java.sql.Timestamp getCurrentTimestamp() {\n        return now;\n    }\n\n    public java.sql.Date getCurrentDate() {\n        return currentDate;\n    }\n\n    public MySqlCreateTableParser getSQLCreateTableParser() {\n        return new MySqlCreateTableParser(this.exprParser);\n    }\n\n    @Override\n    public SQLStatement parseCopy() {\n        acceptIdentifier(\"COPY\");\n\n        SQLCopyFromStatement stmt = new SQLCopyFromStatement();\n\n        SQLExpr table = this.exprParser.name();\n        stmt.setTable(new SQLExprTableSource(table));\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            this.exprParser.names(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n        }\n\n        accept(Token.FROM);\n        SQLExpr from = this.exprParser.expr();\n        stmt.setFrom(from);\n\n        if (lexer.identifierEquals(FnvHash.Constants.CREDENTIALS)) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                if (lexer.identifierEquals(FnvHash.Constants.ACCESS_KEY_ID)) {\n                    lexer.nextToken();\n                    SQLExpr accessKeyId = this.exprParser.primary();\n                    stmt.setAccessKeyId(accessKeyId);\n                } else if (lexer.identifierEquals(FnvHash.Constants.ACCESS_KEY_SECRET)) {\n                    lexer.nextToken();\n                    SQLExpr accessKeySecret = this.exprParser.primary();\n                    stmt.setAccessKeySecret(accessKeySecret);\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLName name = this.exprParser.name();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr value = this.exprParser.expr();\n                SQLAssignItem item = new SQLAssignItem(name, value);\n                item.setParent(stmt);\n                stmt.getOptions().add(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n        return stmt;\n    }\n\n    @Override\n    protected void parseCreateMaterializedViewRest(SQLCreateMaterializedViewStatement stmt) {\n        stmt.setDbType(dbType);\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            for (; ; ) {\n                Token token = lexer.token();\n\n                if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.KEY) {\n                        MySqlKey clsKey = new MySqlKey();\n                        this.exprParser.parseIndex(clsKey.getIndexDefinition());\n                        clsKey.setIndexType(\"CLUSTERED\");\n                        clsKey.setParent(stmt);\n                        stmt.getTableElementList().add(clsKey);\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                    } else if (lexer.token() == INDEX) {\n                        MySqlTableIndex idx = new MySqlTableIndex();\n                        this.exprParser.parseIndex(idx.getIndexDefinition());\n                        idx.setIndexType(\"CLUSTERED\");\n                        idx.setParent(stmt);\n                        stmt.getTableElementList().add(idx);\n\n                        if (lexer.token() == Token.RPAREN) {\n                            break;\n                        } else if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                    }\n                }\n\n                if (token == Token.IDENTIFIER) {\n                    SQLColumnDefinition column = this.exprParser.parseColumn(stmt);\n                    stmt.getTableElementList().add((SQLTableElement) column);\n                } else if (token == Token.PRIMARY //\n                        || token == Token.UNIQUE //\n                        || token == Token.CHECK //\n                        || token == Token.CONSTRAINT\n                        || token == Token.FOREIGN) {\n                    SQLConstraint constraint = this.exprParser.parseConstraint();\n                    constraint.setParent(stmt);\n                    stmt.getTableElementList().add((SQLTableElement) constraint);\n                } else if (lexer.token() == (INDEX)) {\n                    MySqlTableIndex idx = new MySqlTableIndex();\n                    this.exprParser.parseIndex(idx.getIndexDefinition());\n\n                    idx.setParent(stmt);\n                    stmt.getTableElementList().add(idx);\n                } else if (lexer.token() == (Token.KEY)) {\n                    Lexer.SavePoint savePoint = lexer.mark();\n                    lexer.nextToken();\n\n                    boolean isColumn = false;\n                    if (lexer.identifierEquals(FnvHash.Constants.VARCHAR)) {\n                        isColumn = true;\n                    }\n                    lexer.reset(savePoint);\n\n                    if (isColumn) {\n                        stmt.getTableElementList().add(this.exprParser.parseColumn());\n                    } else {\n                        SQLName name = null;\n                        if (lexer.token() == Token.IDENTIFIER) {\n                            name = this.exprParser.name();\n                        }\n\n                        MySqlKey key = new MySqlKey();\n                        this.exprParser.parseIndex(key.getIndexDefinition());\n\n                        if (name != null) {\n                            key.setName(name);\n                        }\n                        key.setParent(stmt);\n                        stmt.getTableElementList().add(key);\n                    }\n                    continue;\n                }\n                if (lexer.token() == COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.DISTRIBUTED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                if (lexer.identifierEquals(FnvHash.Constants.HASH)) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        SQLName name = this.exprParser.name();\n                        stmt.getDistributedBy().add(name);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    stmt.setDistributedByType(new SQLIdentifierExpr(\"HASH\"));\n                } else if (lexer.identifierEquals(FnvHash.Constants.DUPLICATE)) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        SQLName name = this.exprParser.name();\n                        stmt.getDistributedBy().add(name);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                    stmt.setDistributedByType(new SQLIdentifierExpr(\"DUPLICATE\"));\n                } else if (lexer.identifierEquals(FnvHash.Constants.BROADCAST)) {\n                    lexer.nextToken();\n                    stmt.setDistributedByType(new SQLIdentifierExpr(\"BROADCAST\"));\n                }\n                continue;\n            } else if (lexer.identifierEquals(\"INDEX_ALL\")) {\n                lexer.nextToken();\n                accept(Token.EQ);\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    if (\"Y\".equalsIgnoreCase(lexer.stringVal())) {\n                        lexer.nextToken();\n                        stmt.addOption(\"INDEX_ALL\", new SQLCharExpr(\"Y\"));\n                    } else if (\"N\".equalsIgnoreCase(lexer.stringVal())) {\n                        lexer.nextToken();\n                        stmt.addOption(\"INDEX_ALL\", new SQLCharExpr(\"N\"));\n                    } else {\n                        throw new ParserException(\"INDEX_ALL accept parameter ['Y' or 'N'] only.\");\n                    }\n                }\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                SQLExpr expr = this.exprParser.expr();\n                stmt.addOption(\"ENGINE\", expr);\n                continue;\n            } else if (lexer.token() == Token.PARTITION) {\n                SQLPartitionBy partitionBy = this.exprParser.parsePartitionBy();\n                stmt.setPartitionBy(partitionBy);\n                continue;\n            } else if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                }\n                stmt.setComment(this.exprParser.expr());\n                continue;\n            }\n            break;\n        }\n    }\n\n    @Override\n    public void parseExplainFormatPartition(SQLExplainStatement explain) {\n        if (lexer.identifierEquals(\"FORMAT\")\n                || lexer.identifierEquals(\"PARTITIONS\")) {\n            explain.setType(lexer.stringVal());\n            lexer.nextToken();\n        }\n    }\n\n    @Override\n    public void parseExplainFormatType(SQLExplainStatement explain) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"FORMAT\")) {\n                lexer.nextToken();\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"TYPE\")) {\n                lexer.nextToken();\n                lexer.nextToken();\n            }\n\n            accept(Token.RPAREN);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\" ) {\n        return true;\n    }\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface MySqlASTVisitor extends SQLASTVisitor {\n    default boolean visit(MySqlTableIndex x) {\n        return true;\n    }\n\n    default void endVisit(MySqlTableIndex x) {\n    }\n\n    default boolean visit(MySqlKey x) {\n        return true;\n    }\n\n    default void endVisit(MySqlKey x) {\n    }\n\n    default boolean visit(MySqlPrimaryKey x) {\n        return true;\n    }\n\n    default void endVisit(MySqlPrimaryKey x) {\n    }\n\n    default boolean visit(MySqlUnique x) {\n        return true;\n    }\n\n    default void endVisit(MySqlUnique x) {\n    }\n\n    default boolean visit(MysqlForeignKey x) {\n        return visit((SQLForeignKeyImpl) x);\n    }\n\n    default void endVisit(MysqlForeignKey x) {\n        endVisit((SQLForeignKeyImpl) x);\n    }\n\n    default void endVisit(MySqlPrepareStatement x) {\n    }\n\n    default boolean visit(MySqlPrepareStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlExecuteStatement x) {\n    }\n\n    default boolean visit(MysqlDeallocatePrepareStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlDeallocatePrepareStatement x) {\n    }\n\n    default boolean visit(MySqlExecuteStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlDeleteStatement x) {\n    }\n\n    default boolean visit(MySqlDeleteStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlInsertStatement x) {\n    }\n\n    default boolean visit(MySqlInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlLoadDataInFileStatement x) {\n    }\n\n    default boolean visit(MySqlLoadDataInFileStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlLoadXmlStatement x) {\n    }\n\n    default boolean visit(MySqlLoadXmlStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowWarningsStatement x) {\n    }\n\n    default boolean visit(MySqlShowWarningsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowAuthorsStatement x) {\n    }\n\n    default boolean visit(MySqlShowAuthorsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlShowHtcStatement x) {\n    }\n\n    default boolean visit(MysqlShowHtcStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlShowStcStatement x) {\n    }\n\n    default boolean visit(MysqlShowStcStatement x) {\n        return true;\n    }\n\n    default void endVisit(CobarShowStatus x) {\n    }\n\n    default boolean visit(CobarShowStatus x) {\n        return true;\n    }\n\n    default void endVisit(DrdsShowDDLJobs x) {\n    }\n\n    default boolean visit(DrdsShowDDLJobs x) {\n        return true;\n    }\n\n    default void endVisit(DrdsCancelDDLJob x) {\n    }\n\n    default boolean visit(DrdsCancelDDLJob x) {\n        return true;\n    }\n\n    default void endVisit(DrdsRecoverDDLJob x) {\n    }\n\n    default boolean visit(DrdsRecoverDDLJob x) {\n        return true;\n    }\n\n    default void endVisit(DrdsRollbackDDLJob x) {\n    }\n\n    default boolean visit(DrdsRollbackDDLJob x) {\n        return true;\n    }\n\n    default void endVisit(DrdsRemoveDDLJob x) {\n    }\n\n    default boolean visit(DrdsRemoveDDLJob x) {\n        return true;\n    }\n\n    default void endVisit(DrdsInspectDDLJobCache x) {\n    }\n\n    default boolean visit(DrdsInspectDDLJobCache x) {\n        return true;\n    }\n\n    default void endVisit(DrdsClearDDLJobCache x) {\n    }\n\n    default boolean visit(DrdsClearDDLJobCache x) {\n        return true;\n    }\n\n    default void endVisit(DrdsChangeDDLJob x) {\n    }\n\n    default boolean visit(DrdsChangeDDLJob x) {\n        return true;\n    }\n\n    default void endVisit(DrdsBaselineStatement x) {\n    }\n\n    default boolean visit(DrdsBaselineStatement x) {\n        return true;\n    }\n\n    default void endVisit(DrdsShowGlobalIndex x) {\n    }\n\n    default boolean visit(DrdsShowGlobalIndex x) {\n        return true;\n    }\n\n    default void endVisit(DrdsShowMetadataLock x) {\n    }\n\n    default boolean visit(DrdsShowMetadataLock x) {\n        return true;\n    }\n\n    default void endVisit(MySqlBinlogStatement x) {\n    }\n\n    default boolean visit(MySqlBinlogStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateUserStatement x) {\n    }\n\n    default boolean visit(MySqlCreateUserStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateUserStatement.UserSpecification x) {\n    }\n\n    default boolean visit(MySqlCreateUserStatement.UserSpecification x) {\n        return true;\n    }\n\n    default void endVisit(MySqlPartitionByKey x) {\n    }\n\n    default boolean visit(MySqlPartitionByKey x) {\n        return true;\n    }\n\n    default void endVisit(MySqlUpdatePlanCacheStatement x) {\n    }\n\n    default boolean visit(MySqlUpdatePlanCacheStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowPlanCacheStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowPlanCacheStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlClearPlanCacheStatement x) {\n    }\n\n    default boolean visit(MySqlClearPlanCacheStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlDisabledPlanCacheStatement x) {\n    }\n\n    default boolean visit(MySqlDisabledPlanCacheStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlExplainPlanCacheStatement x) {\n    }\n\n    default boolean visit(MySqlExplainPlanCacheStatement x) {\n        return true;\n    }\n\n    default boolean visit(MySqlSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(MySqlSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(MySqlOutFileExpr x) {\n        return true;\n    }\n\n    default void endVisit(MySqlOutFileExpr x) {\n    }\n\n    default boolean visit(MySqlExplainStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlExplainStatement x) {\n    }\n\n    default boolean visit(MySqlUpdateStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlUpdateStatement x) {\n    }\n\n    default boolean visit(MySqlSetTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlSetTransactionStatement x) {\n    }\n\n    default boolean visit(MySqlShowHMSMetaStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowHMSMetaStatement x) {\n    }\n\n    default boolean visit(MySqlShowBinaryLogsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowBinaryLogsStatement x) {\n    }\n\n    default boolean visit(MySqlShowMasterLogsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowMasterLogsStatement x) {\n    }\n\n    default boolean visit(MySqlShowCharacterSetStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowCharacterSetStatement x) {\n    }\n\n    default boolean visit(MySqlShowCollationStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowCollationStatement x) {\n    }\n\n    default boolean visit(MySqlShowBinLogEventsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowBinLogEventsStatement x) {\n    }\n\n    default boolean visit(MySqlShowContributorsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowContributorsStatement x) {\n    }\n\n    default boolean visit(MySqlShowCreateDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowCreateDatabaseStatement x) {\n    }\n\n    default boolean visit(MySqlShowCreateEventStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowCreateEventStatement x) {\n    }\n\n    default boolean visit(MySqlShowCreateFunctionStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowCreateFunctionStatement x) {\n    }\n\n    default boolean visit(MySqlShowCreateProcedureStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowCreateProcedureStatement x) {\n    }\n\n    default boolean visit(MySqlShowCreateTriggerStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowCreateTriggerStatement x) {\n    }\n\n    default boolean visit(MySqlShowEngineStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowEngineStatement x) {\n    }\n\n    default boolean visit(MySqlShowEnginesStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowEnginesStatement x) {\n    }\n\n    default boolean visit(MySqlShowErrorsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowErrorsStatement x) {\n    }\n\n    default boolean visit(MySqlShowEventsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowEventsStatement x) {\n    }\n\n    default boolean visit(MySqlShowFunctionCodeStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowFunctionCodeStatement x) {\n    }\n\n    default boolean visit(MySqlShowFunctionStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowFunctionStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowGrantsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowGrantsStatement x) {\n    }\n\n    default boolean visit(MySqlUserName x) {\n        return true;\n    }\n\n    default void endVisit(MySqlUserName x) {\n    }\n\n    default boolean visit(MySqlAlterDatabaseSetOption x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterDatabaseSetOption x) {\n    }\n\n    default boolean visit(MySqlAlterDatabaseKillJob x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterDatabaseKillJob x) {\n    }\n\n    default boolean visit(MySqlShowMasterStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowMasterStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowOpenTablesStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowOpenTablesStatement x) {\n    }\n\n    default boolean visit(MySqlShowPluginsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowPluginsStatement x) {\n    }\n\n    default boolean visit(MySqlShowPartitionsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowPartitionsStatement x) {\n    }\n\n    default boolean visit(MySqlShowPrivilegesStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowPrivilegesStatement x) {\n    }\n\n    default boolean visit(MySqlShowProcedureCodeStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowProcedureCodeStatement x) {\n    }\n\n    default boolean visit(MySqlShowProcedureStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowProcedureStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowProcessListStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowProcessListStatement x) {\n    }\n\n    default boolean visit(MySqlShowProfileStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowProfileStatement x) {\n    }\n\n    default boolean visit(MySqlShowProfilesStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowProfilesStatement x) {\n    }\n\n    default boolean visit(MySqlShowRelayLogEventsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowRelayLogEventsStatement x) {\n    }\n\n    default boolean visit(MySqlShowSlaveHostsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowSlaveHostsStatement x) {\n    }\n\n    default boolean visit(MySqlShowSequencesStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowSequencesStatement x) {\n    }\n\n    default boolean visit(MySqlShowSlaveStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowSlaveStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowSlowStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowSlowStatement x) {\n    }\n\n    default boolean visit(MySqlShowTableStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowTableStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowTriggersStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowTriggersStatement x) {\n    }\n\n    default boolean visit(MySqlShowTraceStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowTraceStatement x) {\n    }\n\n    default boolean visit(MySqlShowBroadcastsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowBroadcastsStatement x) {\n    }\n\n    default boolean visit(MySqlShowRuleStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowRuleStatement x) {\n    }\n\n    default boolean visit(MySqlShowRuleStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowRuleStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowDsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowDsStatement x) {\n    }\n\n    default boolean visit(MySqlShowDdlStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowDdlStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowTopologyStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowTopologyStatement x) {\n    }\n\n    default boolean visit(MySqlRenameTableStatement.Item x) {\n        return true;\n    }\n\n    default void endVisit(MySqlRenameTableStatement.Item x) {\n    }\n\n    default boolean visit(MySqlRenameTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlRenameTableStatement x) {\n    }\n\n    default boolean visit(MysqlShowDbLockStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlShowDbLockStatement x) {\n    }\n\n    default boolean visit(MySqlShowDatabaseStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowDatabaseStatusStatement x) {\n    }\n\n    default boolean visit(MySqlUseIndexHint x) {\n        return true;\n    }\n\n    default void endVisit(MySqlUseIndexHint x) {\n    }\n\n    default boolean visit(MySqlIgnoreIndexHint x) {\n        return true;\n    }\n\n    default void endVisit(MySqlIgnoreIndexHint x) {\n    }\n\n    default boolean visit(MySqlLockTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlLockTableStatement x) {\n    }\n\n    default boolean visit(MySqlLockTableStatement.Item x) {\n        return true;\n    }\n\n    default void endVisit(MySqlLockTableStatement.Item x) {\n    }\n\n    default boolean visit(MySqlUnlockTablesStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlUnlockTablesStatement x) {\n    }\n\n    default boolean visit(MySqlForceIndexHint x) {\n        return true;\n    }\n\n    default void endVisit(MySqlForceIndexHint x) {\n    }\n\n    default boolean visit(MySqlAlterTableChangeColumn x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableChangeColumn x) {\n    }\n\n    default boolean visit(MySqlAlterTableOption x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableOption x) {\n    }\n\n    default boolean visit(MySqlCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateTableStatement x) {\n    }\n\n    default boolean visit(MySqlHelpStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlHelpStatement x) {\n    }\n\n    default boolean visit(MySqlCharExpr x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCharExpr x) {\n    }\n\n    default boolean visit(MySqlAlterTableModifyColumn x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableModifyColumn x) {\n    }\n\n    default boolean visit(MySqlAlterTableDiscardTablespace x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableDiscardTablespace x) {\n    }\n\n    default boolean visit(MySqlAlterTableImportTablespace x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableImportTablespace x) {\n    }\n\n    default boolean visit(MySqlCreateTableStatement.TableSpaceOption x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateTableStatement.TableSpaceOption x) {\n    }\n\n    default boolean visit(MySqlAnalyzeStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAnalyzeStatement x) {\n    }\n\n    default boolean visit(MySqlCreateExternalCatalogStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateExternalCatalogStatement x) {\n    }\n\n    default boolean visit(MySqlAlterUserStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterUserStatement x) {\n    }\n\n    default boolean visit(MySqlOptimizeStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlOptimizeStatement x) {\n    }\n\n    default boolean visit(MySqlHintStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlHintStatement x) {\n    }\n\n    default boolean visit(MySqlOrderingExpr x) {\n        return true;\n    }\n\n    default void endVisit(MySqlOrderingExpr x) {\n    }\n\n    default boolean visit(MySqlCaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCaseStatement x) {\n    }\n\n    default boolean visit(MySqlDeclareStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlDeclareStatement x) {\n    }\n\n    default boolean visit(MySqlSelectIntoStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlSelectIntoStatement x) {\n    }\n\n    default boolean visit(MySqlWhenStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlWhenStatement x) {\n    }\n\n    default boolean visit(MySqlLeaveStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlLeaveStatement x) {\n    }\n\n    default boolean visit(MySqlIterateStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlIterateStatement x) {\n    }\n\n    default boolean visit(MySqlRepeatStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlRepeatStatement x) {\n    }\n\n    default boolean visit(MySqlCursorDeclareStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCursorDeclareStatement x) {\n    }\n\n    default boolean visit(MySqlUpdateTableSource x) {\n        return true;\n    }\n\n    default void endVisit(MySqlUpdateTableSource x) {\n    }\n\n    default boolean visit(MySqlAlterTableAlterColumn x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableAlterColumn x) {\n    }\n\n    default boolean visit(MySqlAlterTableForce x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableForce x) {\n    }\n\n    default boolean visit(MySqlAlterTableLock x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableLock x) {\n    }\n\n    default boolean visit(MySqlAlterTableAlgorithm x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableAlgorithm x) {\n    }\n\n    default boolean visit(MySqlAlterTableOrderBy x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableOrderBy x) {\n    }\n\n    default boolean visit(MySqlAlterTableValidation x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableValidation x) {\n    }\n\n    default boolean visit(MySqlSubPartitionByKey x) {\n        return true;\n    }\n\n    default void endVisit(MySqlSubPartitionByKey x) {\n    }\n\n    default boolean visit(MySqlSubPartitionByList x) {\n        return true;\n    }\n\n    default void endVisit(MySqlSubPartitionByList x) {\n    }\n\n    default boolean visit(MySqlDeclareHandlerStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlDeclareHandlerStatement x) {\n    }\n\n    default boolean visit(MySqlDeclareConditionStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlDeclareConditionStatement x) {\n    }\n\n    default boolean visit(MySqlFlushStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlFlushStatement x) {\n    }\n\n    default boolean visit(MySqlEventSchedule x) {\n        return true;\n    }\n\n    default void endVisit(MySqlEventSchedule x) {\n    }\n\n    default boolean visit(MySqlCreateEventStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateEventStatement x) {\n    }\n\n    default boolean visit(MySqlCreateAddLogFileGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateAddLogFileGroupStatement x) {\n    }\n\n    default boolean visit(MySqlCreateServerStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateServerStatement x) {\n    }\n\n    default boolean visit(MySqlCreateTableSpaceStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCreateTableSpaceStatement x) {\n    }\n\n    default boolean visit(MySqlAlterEventStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterEventStatement x) {\n    }\n\n    default boolean visit(MySqlAlterLogFileGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterLogFileGroupStatement x) {\n    }\n\n    default boolean visit(MySqlAlterServerStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterServerStatement x) {\n    }\n\n    default boolean visit(MySqlAlterTablespaceStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTablespaceStatement x) {\n    }\n\n    default boolean visit(MySqlChecksumTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlChecksumTableStatement x) {\n    }\n\n    default boolean visit(MySqlShowDatasourcesStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowDatasourcesStatement x) {\n    }\n\n    default boolean visit(MySqlShowNodeStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowNodeStatement x) {\n    }\n\n    default boolean visit(MySqlShowHelpStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowHelpStatement x) {\n    }\n\n    default boolean visit(MySqlFlashbackStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlFlashbackStatement x) {\n    }\n\n    default boolean visit(MySqlShowConfigStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowConfigStatement x) {\n    }\n\n    default boolean visit(MySqlShowPlanCacheStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowPlanCacheStatement x) {\n    }\n\n    default boolean visit(MySqlShowPhysicalProcesslistStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowPhysicalProcesslistStatement x) {\n    }\n\n    default boolean visit(MySqlRenameSequenceStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlRenameSequenceStatement x) {\n    }\n\n    default boolean visit(MySqlCheckTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlCheckTableStatement x) {\n    }\n\n    default boolean visit(MysqlCreateFullTextCharFilterStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlCreateFullTextCharFilterStatement x) {\n    }\n\n    default boolean visit(MysqlShowFullTextStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlShowFullTextStatement x) {\n    }\n\n    default boolean visit(MysqlShowCreateFullTextStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlShowCreateFullTextStatement x) {\n    }\n\n    default boolean visit(MysqlAlterFullTextStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlAlterFullTextStatement x) {\n    }\n\n    default boolean visit(MysqlDropFullTextStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlDropFullTextStatement x) {\n    }\n\n    default boolean visit(MysqlCreateFullTextTokenizerStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlCreateFullTextTokenizerStatement x) {\n    }\n\n    default boolean visit(MysqlCreateFullTextTokenFilterStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlCreateFullTextTokenFilterStatement x) {\n    }\n\n    default boolean visit(MysqlCreateFullTextAnalyzerStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlCreateFullTextAnalyzerStatement x) {\n    }\n\n    default boolean visit(MysqlCreateFullTextDictionaryStatement x) {\n        return true;\n    }\n\n    default void endVisit(MysqlCreateFullTextDictionaryStatement x) {\n    }\n\n    default boolean visit(MySqlAlterTableAlterFullTextIndex x) {\n        return true;\n    }\n\n    default void endVisit(MySqlAlterTableAlterFullTextIndex x) {\n    }\n\n    default boolean visit(MySqlExecuteForAdsStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlExecuteForAdsStatement x) {\n    }\n\n    default boolean visit(MySqlManageInstanceGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlManageInstanceGroupStatement x) {\n    }\n\n    default boolean visit(MySqlRaftMemberChangeStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlRaftMemberChangeStatement x) {\n    }\n\n    default boolean visit(MySqlRaftLeaderTransferStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlRaftLeaderTransferStatement x) {\n    }\n\n    default boolean visit(MySqlMigrateStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlMigrateStatement x) {\n    }\n\n    default boolean visit(MySqlShowClusterNameStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowClusterNameStatement x) {\n    }\n\n    default boolean visit(MySqlShowJobStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowJobStatusStatement x) {\n    }\n\n    default boolean visit(MySqlShowMigrateTaskStatusStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlShowMigrateTaskStatusStatement x) {\n    }\n\n    default boolean visit(MySqlSubPartitionByValue x) {\n        return true;\n    }\n\n    default void endVisit(MySqlSubPartitionByValue x) {\n    }\n\n    default boolean visit(MySqlExtPartition x) {\n        return true;\n    }\n\n    default void endVisit(MySqlExtPartition x) {\n    }\n\n    default boolean visit(MySqlExtPartition.Item x) {\n        return true;\n    }\n\n    default void endVisit(MySqlExtPartition.Item x) {\n    }\n\n    default boolean visit(MySqlJSONTableExpr x) {\n        return true;\n    }\n\n    default void endVisit(MySqlJSONTableExpr x) {\n    }\n\n    default boolean visit(MySqlJSONTableExpr.Column x) {\n        return true;\n    }\n\n    default void endVisit(MySqlJSONTableExpr.Column x) {\n    }\n\n    default boolean visit(MysqlAlterTableAlterCheck x) {\n        return true;\n    }\n\n    default void endVisit(MysqlAlterTableAlterCheck x) {\n    }\n\n    default boolean visit(MySqlXAStatement x) {\n        return true;\n    }\n\n    default void endVisit(MySqlXAStatement x) {\n    }\n    default boolean visit(TidbSplitTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(TidbSplitTableStatement x) {\n    }\n\n} //\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySqlASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlEvalVisitorImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class MySqlEvalVisitorImpl extends MySqlASTVisitorAdapter implements SQLEvalVisitor {\n    private Map<String, Function> functions = new HashMap<String, Function>();\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public MySqlEvalVisitorImpl() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public MySqlEvalVisitorImpl(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLUnaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLHexExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLBinaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    @Override\n    public boolean visit(SQLBooleanExpr x) {\n        x.getAttributes().put(EVAL_VALUE, x.getBooleanValue());\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlExportParameterVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLInListExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlFlushStatement;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MySqlExportParameterVisitor extends MySqlOutputVisitor implements ExportParameterVisitor {\n    /**\n     * true= if require parameterized sql output\n     */\n    private boolean requireParameterizedOutput;\n\n    public MySqlExportParameterVisitor(List<Object> parameters, StringBuilder appender, boolean wantParameterizedOutput) {\n        super(appender, true);\n        this.parameters = parameters;\n        this.requireParameterizedOutput = wantParameterizedOutput;\n    }\n\n    public MySqlExportParameterVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public MySqlExportParameterVisitor(List<Object> parameters) {\n        this(parameters, null, false);\n    }\n\n    public MySqlExportParameterVisitor(final StringBuilder appender) {\n        this(new ArrayList<Object>(), appender, true);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public boolean visit(final SQLSelectItem x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLLimit x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLOrderBy x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelectGroupByClause x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getArguments());\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n    @Override\n    public boolean visit(MySqlFlushStatement x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(MySqlFlushStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.MySQL;\nimport com.alibaba.druid.sql.dialect.mysql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.ConditionValue.ConditionType;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement.TableSpaceOption;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.security.AccessControlException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\npublic class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTVisitor {\n    {\n        this.dbType = DbType.mysql;\n        this.shardingSupport = true;\n    }\n\n    public MySqlOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.mysql, MySQL.DIALECT);\n    }\n\n    public MySqlOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.mysql, MySQL.DIALECT, parameterized);\n\n        try {\n            configFromProperty();\n        } catch (AccessControlException e) {\n            // skip\n        }\n    }\n\n    private static boolean shardingSupportChecked;\n\n    public void configFromProperty() {\n        if (this.parameterized && !shardingSupportChecked) {\n            shardingSupportChecked = true;\n\n            String property = System.getProperties().getProperty(\"fastsql.parameterized.shardingSupport\");\n            if (\"true\".equals(property)) {\n                this.setShardingSupport(true);\n            } else if (\"false\".equals(property)) {\n                this.setShardingSupport(false);\n            }\n        }\n    }\n\n    public boolean isShardingSupport() {\n        return this.parameterized\n                && shardingSupport;\n    }\n\n    public void setShardingSupport(boolean shardingSupport) {\n        this.shardingSupport = shardingSupport;\n    }\n\n    @Override\n    public boolean visit(SQLSelectQueryBlock select) {\n        if (select instanceof MySqlSelectQueryBlock) {\n            return visit((MySqlSelectQueryBlock) select);\n        }\n\n        return super.visit(select);\n    }\n\n    public boolean visit(MySqlSelectQueryBlock x) {\n        final boolean bracket = x.isParenthesized();\n        if (bracket) {\n            print('(');\n        }\n\n        if ((!isParameterized()) && isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        String cachedSelectList = x.getCachedSelectList();\n\n        if (cachedSelectList != null) {\n            if (!isEnabled(VisitorFeature.OutputSkipSelectListCacheString)) {\n                print0(cachedSelectList);\n            }\n        } else {\n            print0(ucase ? \"SELECT \" : \"select \");\n\n            for (int i = 0, size = x.getHintsSize(); i < size; ++i) {\n                SQLCommentHint hint = x.getHints().get(i);\n                hint.accept(this);\n                print(' ');\n            }\n\n            switch (x.getDistionOption()) {\n                case SQLSetQuantifier.ALL:\n                    print0(ucase ? \"ALL \" : \"all \");\n                    break;\n                case SQLSetQuantifier.DISTINCT:\n                    print0(ucase ? \"DISTINCT \" : \"distinct \");\n                    break;\n                case SQLSetQuantifier.DISTINCTROW:\n                    print0(ucase ? \"DISTINCTROW \" : \"distinctrow \");\n                    break;\n                case SQLSetQuantifier.UNIQUE:\n                    print0(ucase ? \"UNIQUE \" : \"unique \");\n                    break;\n                default:\n                    break;\n            }\n\n            if (x.isHignPriority()) {\n                print0(ucase ? \"HIGH_PRIORITY \" : \"high_priority \");\n            }\n\n            if (x.isStraightJoin()) {\n                print0(ucase ? \"STRAIGHT_JOIN \" : \"straight_join \");\n            }\n\n            if (x.isSmallResult()) {\n                print0(ucase ? \"SQL_SMALL_RESULT \" : \"sql_small_result \");\n            }\n\n            if (x.isBigResult()) {\n                print0(ucase ? \"SQL_BIG_RESULT \" : \"sql_big_result \");\n            }\n\n            if (x.isBufferResult()) {\n                print0(ucase ? \"SQL_BUFFER_RESULT \" : \"sql_buffer_result \");\n            }\n\n            if (x.getCache() != null) {\n                if (x.getCache().booleanValue()) {\n                    print0(ucase ? \"SQL_CACHE \" : \"sql_cache \");\n                } else {\n                    print0(ucase ? \"SQL_NO_CACHE \" : \"sql_no_cache \");\n                }\n            }\n\n            if (x.isCalcFoundRows()) {\n                print0(ucase ? \"SQL_CALC_FOUND_ROWS \" : \"sql_calc_found_rows \");\n            }\n\n            printSelectList(x.getSelectList());\n\n            SQLName forcePartition = x.getForcePartition();\n            if (forcePartition != null) {\n                println();\n                print0(ucase ? \"FORCE PARTITION \" : \"force partition \");\n                printExpr(forcePartition, parameterized);\n            }\n\n            SQLExprTableSource into = x.getInto();\n            if (into != null) {\n                println();\n                print0(ucase ? \"INTO \" : \"into \");\n                printTableSource(into);\n            }\n        }\n\n        printFrom(x);\n\n        printWhere(x);\n\n        printHierarchical(x);\n\n        printGroupBy(x);\n        printWindow(x);\n        printOrderBy(x);\n\n        printLimit(x);\n\n        SQLName procedureName = x.getProcedureName();\n        if (procedureName != null) {\n            print0(ucase ? \" PROCEDURE \" : \" procedure \");\n            procedureName.accept(this);\n            if (!x.getProcedureArgumentList().isEmpty()) {\n                print('(');\n                printAndAccept(x.getProcedureArgumentList(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.isForUpdate()) {\n            println();\n            print0(ucase ? \"FOR UPDATE\" : \"for update\");\n            if (x.isNoWait()) {\n                print0(ucase ? \" NOWAIT\" : \" nowait\");\n            } else if (x.getWaitTime() != null) {\n                print0(ucase ? \" WAIT \" : \" wait \");\n                x.getWaitTime().accept(this);\n            }\n\n            if (x.isSkipLocked()) {\n                print0(ucase ? \" SKIP LOCKED\" : \" skip locked\");\n            }\n        }\n\n        if (x.isForShare()) {\n            println();\n            print0(ucase ? \"FOR SHARE\" : \"for share\");\n        }\n\n        if (x.isLockInShareMode()) {\n            println();\n            print0(ucase ? \"LOCK IN SHARE MODE\" : \"lock in share mode\");\n        }\n\n        if ((!isParameterized()) && isPrettyFormat() && x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n\n        if (bracket) {\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    protected void printFrom(SQLSelectQueryBlock x) {\n        SQLTableSource from = x.getFrom();\n        if (from == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"FROM \" : \"from \");\n        if (x.getCommentsAfterFrom() != null) {\n            printAfterComments(x.getCommentsAfterFrom());\n            println();\n        }\n        printTableSource(from);\n    }\n\n    public boolean visit(SQLColumnDefinition x) {\n        boolean parameterized = this.parameterized;\n        this.parameterized = false;\n\n        String columnName = replaceQuota(x.getName().getSimpleName());\n        printName0(columnName);\n\n        SQLDataType dataType = x.getDataType();\n        if (dataType != null) {\n            print(' ');\n            dataType.accept(this);\n        }\n\n        SQLExpr generatedAlawsAs = x.getGeneratedAlwaysAs();\n        if (generatedAlawsAs != null) {\n            print0(ucase ? \" GENERATED ALWAYS AS (\" : \" generated always as (\");\n            printExpr(generatedAlawsAs);\n            print(')');\n        }\n\n        if (x.isVirtual()) {\n            print0(ucase ? \" VIRTUAL\" : \" virtual\");\n        }\n\n        if (x.isVisible()) {\n            print0(ucase ? \" VISIBLE\" : \" visible\");\n        }\n\n        final SQLExpr charsetExpr = x.getCharsetExpr();\n        if (charsetExpr != null) {\n            print0(ucase ? \" CHARACTER SET \" : \" character set \");\n            charsetExpr.accept(this);\n        }\n\n        final SQLExpr collateExpr = x.getCollateExpr();\n        if (collateExpr != null) {\n            print0(ucase ? \" COLLATE \" : \" collate \");\n            collateExpr.accept(this);\n        }\n\n        for (SQLColumnConstraint item : x.getConstraints()) {\n            if (item instanceof SQLColumnReference) {\n                continue;\n            }\n            print(' ');\n            item.accept(this);\n        }\n\n        final SQLExpr defaultExpr = x.getDefaultExpr();\n        if (defaultExpr != null) {\n            print0(ucase ? \" DEFAULT \" : \" default \");\n            defaultExpr.accept(this);\n        }\n\n        final SQLExpr storage = x.getStorage();\n        if (storage != null) {\n            print0(ucase ? \" STORAGE \" : \" storage \");\n            storage.accept(this);\n        }\n\n        final SQLExpr format = x.getFormat();\n        if (format != null) {\n            printUcase(\" COLUMN_FORMAT \");\n            format.accept(this);\n        }\n\n        SQLExpr onUpdate = x.getOnUpdate();\n        if (onUpdate != null) {\n            print0(ucase ? \" ON UPDATE \" : \" on update \");\n\n            onUpdate.accept(this);\n        }\n\n        if (x.getJsonIndexAttrsExpr() != null) {\n            print0(ucase ? \" JSONINDEXATTRS '\" : \" jsonindexattrs '\");\n            x.getJsonIndexAttrsExpr().accept(this);\n            print0(\"' \");\n        }\n\n        boolean autoIncrement = x.isAutoIncrement();\n        if (!autoIncrement && x.getGeneratedAlwaysAs() == null && x.getIdentity() != null) {\n            autoIncrement = true;\n        }\n\n        if (autoIncrement) {\n            print0(ucase ? \" AUTO_INCREMENT\" : \" auto_increment\");\n        }\n\n        if (x.getDelimiterTokenizer() != null) {\n            print0(ucase ? \" DELIMITER_TOKENIZER \" : \" delimiter_tokenizer \");\n            x.getDelimiterTokenizer().accept(this);\n        }\n        if (x.getNlpTokenizer() != null) {\n            print0(ucase ? \" NLP_TOKENIZER \" : \" nlp_tokenizer \");\n            x.getNlpTokenizer().accept(this);\n        }\n        if (x.getValueType() != null) {\n            print0(ucase ? \" VALUE_TYPE \" : \" value_type \");\n            x.getValueType().accept(this);\n        }\n\n        final AutoIncrementType sequenceType = x.getSequenceType();\n        if (sequenceType != null) {\n            print0(ucase ? \" BY \" : \" by \");\n            print0(ucase ? sequenceType.getKeyword() : sequenceType.getKeyword().toLowerCase());\n        }\n\n        final SQLExpr unitCount = x.getUnitCount();\n        if (unitCount != null) {\n            print0(ucase ? \" UNIT COUNT \" : \" unit count \");\n            printExpr(unitCount);\n        }\n\n        final SQLExpr unitIndex = x.getUnitIndex();\n        if (unitIndex != null) {\n            print0(ucase ? \" INDEX \" : \" index \");\n            printExpr(unitIndex);\n        }\n\n        if (x.getStep() != null) {\n            print0(ucase ? \" STEP \" : \" STEP \");\n            printExpr(x.getStep());\n        }\n\n        SQLExpr delimiter = x.getDelimiter();\n        if (delimiter != null) {\n            print0(ucase ? \" DELIMITER \" : \" delimiter \");\n            delimiter.accept(this);\n        }\n\n        if (x.isDisableIndex() == true) {\n            print0(ucase ? \" DISABLEINDEX TRUE\" : \" disableindex true\");\n        }\n\n        final SQLAnnIndex annIndex = x.getAnnIndex();\n        if (annIndex != null) {\n            print(' ');\n            annIndex.accept(this);\n        }\n\n        if (x.getComment() != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            x.getComment().accept(this);\n        }\n\n        if (x.getAsExpr() != null) {\n            print0(ucase ? \" AS (\" : \" as (\");\n            x.getAsExpr().accept(this);\n            print(')');\n        }\n\n        if (x.isStored()) {\n            print0(ucase ? \" STORED\" : \" stored\");\n        }\n\n        if (x.getEncode() != null) {\n            print0(ucase ? \" ENCODE=\" : \" encode=\");\n            x.getEncode().accept(this);\n        }\n\n        if (x.getCompression() != null) {\n            print0(ucase ? \" COMPRESSION=\" : \" compression=\");\n            x.getCompression().accept(this);\n        }\n\n        List<SQLAssignItem> colProperties = x.getColPropertiesDirect();\n        if (colProperties != null && colProperties.size() > 0) {\n            print0(ucase ? \" COLPROPERTIES (\" : \" colproperties (\");\n            printAndAccept(colProperties, \", \");\n            print0(ucase ? \")\" : \")\");\n        }\n\n        for (SQLColumnConstraint item : x.getConstraints()) {\n            if (item instanceof SQLColumnReference) {\n                print(' ');\n                item.accept(this);\n            }\n        }\n\n        this.parameterized = parameterized;\n        return false;\n    }\n\n    public boolean visit(SQLDataType x) {\n        printDataType(x);\n\n        if (x instanceof SQLDataTypeImpl) {\n            SQLDataTypeImpl dataTypeImpl = (SQLDataTypeImpl) x;\n            if (dataTypeImpl.isUnsigned()) {\n                print0(ucase ? \" UNSIGNED\" : \" unsigned\");\n            }\n\n            if (dataTypeImpl.isZerofill()) {\n                print0(ucase ? \" ZEROFILL\" : \" zerofill\");\n            }\n\n            SQLExpr indexBy = ((SQLDataTypeImpl) x).getIndexBy();\n            if (indexBy != null) {\n                print0(ucase ? \" INDEX BY \" : \" index by \");\n                indexBy.accept(this);\n            }\n        }\n\n        if (x instanceof SQLCharacterDataType) {\n            SQLCharacterDataType charType = (SQLCharacterDataType) x;\n            if (charType.getCharSetName() != null) {\n                print0(ucase ? \" CHARACTER SET \" : \" character set \");\n                print0(charType.getCharSetName());\n\n                if (charType.getCollate() != null) {\n                    print0(ucase ? \" COLLATE \" : \" collate \");\n                    print0(charType.getCollate());\n                }\n            }\n\n            List<SQLCommentHint> hints = ((SQLCharacterDataType) x).hints;\n            if (hints != null) {\n                print(' ');\n                for (SQLCommentHint hint : hints) {\n                    hint.accept(this);\n                }\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCharacterDataType x) {\n        printDataType(x);\n\n        if (x.isHasBinary()) {\n            print0(ucase ? \" BINARY \" : \" binary \");\n        }\n\n        if (x.getCharSetName() != null) {\n            print0(ucase ? \" CHARACTER SET \" : \" character set \");\n            print0(x.getCharSetName());\n            if (x.getCollate() != null) {\n                print0(ucase ? \" COLLATE \" : \" collate \");\n                print0(x.getCollate());\n            }\n        } else if (x.getCollate() != null) {\n            print0(ucase ? \" COLLATE \" : \" collate \");\n            print0(x.getCollate());\n        }\n\n        List<SQLCommentHint> hints = ((SQLCharacterDataType) x).hints;\n        if (hints != null) {\n            print(' ');\n            for (SQLCommentHint hint : hints) {\n                hint.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlTableIndex x) {\n        String indexType = x.getIndexType();\n\n        boolean indexTypePrinted = false;\n        if (\"FULLTEXT\".equalsIgnoreCase(indexType)) {\n            print0(ucase ? \"FULLTEXT \" : \"fulltext \");\n            indexTypePrinted = true;\n        } else if (\"SPATIAL\".equalsIgnoreCase(indexType)) {\n            print0(ucase ? \"SPATIAL \" : \"spatial \");\n            indexTypePrinted = true;\n        } else if (\"CLUSTERED\".equalsIgnoreCase(indexType)) {\n            print0(ucase ? \"CLUSTERED \" : \"clustered \");\n            indexTypePrinted = true;\n        } else if (\"CLUSTERING\".equalsIgnoreCase(indexType)) {\n            print0(ucase ? \"CLUSTERING \" : \"clustering \");\n            indexTypePrinted = true;\n        }\n\n        if (x.getIndexDefinition().isGlobal()) {\n            print0(ucase ? \"GLOBAL \" : \"global \");\n        } else if (x.getIndexDefinition().isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        print0(ucase ? \"INDEX\" : \"index\");\n        if (x.getName() != null) {\n            print(' ');\n            x.getName().accept(this);\n        }\n\n        if (indexType != null && !indexTypePrinted) {\n            if (\"ANN\".equals(indexType)) {\n                print0(\" \");\n                print0(indexType);\n            }\n        }\n\n        if (Boolean.TRUE.equals(x.getAttribute(\"ads.index\"))) {\n            if (x.getIndexDefinition().isHashMapType()) {\n                print0(ucase ? \" HASHMAP\" : \" hashmap\");\n            } else if (x.getIndexDefinition().isHashType()) {\n                print0(ucase ? \" HASH\" : \" hash\");\n            }\n        }\n\n        String using = x.getIndexDefinition().hasOptions() ? x.getIndexDefinition().getOptions().getIndexType() : null;\n        if (using != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(using);\n        }\n\n        print('(');\n        for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            x.getColumns().get(i).accept(this);\n        }\n        print(')');\n\n        if (x.getAnalyzerName() != null) {\n            print0(ucase ? \" WITH ANALYZER \" : \" with analyzer \");\n            x.getAnalyzerName().accept(this);\n        } else {\n            if (x.getIndexAnalyzerName() != null) {\n                print0(ucase ? \" WITH INDEX ANALYZER \" : \" with index analyzer \");\n                x.getIndexAnalyzerName().accept(this);\n            }\n\n            if (x.getQueryAnalyzerName() != null) {\n                print0(ucase ? \" WITH QUERY ANALYZER \" : \" with query analyzer \");\n                x.getQueryAnalyzerName().accept(this);\n            }\n\n            if (x.getWithDicName() != null) {\n                printUcase(\" WITH DICT \");\n                x.getWithDicName().accept(this);\n            }\n        }\n\n        final List<SQLName> covering = x.getCovering();\n        if (null != covering && covering.size() > 0) {\n            print0(ucase ? \" COVERING \" : \" covering \");\n            print('(');\n            for (int i = 0, size = covering.size(); i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                covering.get(i).accept(this);\n            }\n            print(')');\n        }\n\n        final SQLExpr dbPartitionBy = x.getDbPartitionBy();\n        if (dbPartitionBy != null) {\n            print0(ucase ? \" DBPARTITION BY \" : \" dbpartition by \");\n            dbPartitionBy.accept(this);\n        }\n\n        final SQLExpr tablePartitionBy = x.getTablePartitionBy();\n        if (tablePartitionBy != null) {\n            print0(ucase ? \" TBPARTITION BY \" : \" tbpartition by \");\n            tablePartitionBy.accept(this);\n        }\n\n        final SQLExpr tablePartitions = x.getTablePartitions();\n        if (tablePartitions != null) {\n            print0(ucase ? \" TBPARTITIONS \" : \" tbpartitions \");\n            tablePartitions.accept(this);\n        }\n\n        final SQLPartitionBy partitionBy = x.getPartitioning();\n        if (partitionBy != null) {\n            print0(ucase ? \" PARTITION BY \" : \" partitions by \");\n            partitionBy.accept(this);\n        }\n\n        /*\n        final List<SQLAssignItem> options = x.getOptions();\n        if (options.size() > 0) {\n            for (SQLAssignItem option : options) {\n                print(' ');\n                option.accept(this);\n            }\n        }\n\n        final SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n        */\n        if (x.getIndexDefinition().hasOptions()) {\n            x.getIndexDefinition().getOptions().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlKey x) {\n        if (x.isHasConstraint()) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            if (x.getName() != null) {\n                x.getName().accept(this);\n                print(' ');\n            }\n        }\n\n        final String indexType = x.getIndexType();\n        boolean fullText = \"FULLTEXT\".equalsIgnoreCase(indexType);\n        boolean clustering = \"CLUSTERING\".equalsIgnoreCase(indexType);\n        boolean clustered = \"CLUSTERED\".equalsIgnoreCase(indexType);\n\n        if (fullText) {\n            print0(ucase ? \"FULLTEXT \" : \"fulltext \");\n        } else if (clustering) {\n            print0(ucase ? \"CLUSTERING \" : \"clustering \");\n        } else if (clustered) {\n            print0(ucase ? \"CLUSTERED \" : \"CLUSTERED \");\n        }\n\n        print0(ucase ? \"KEY\" : \"key\");\n\n        SQLName name = x.getName();\n        if (name != null) {\n            print(' ');\n            name.accept(this);\n        }\n\n        if (indexType != null && !fullText && !clustering && !clustered) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(indexType);\n        }\n\n        print0(\" (\");\n\n        for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            x.getColumns().get(i).accept(this);\n        }\n        print(')');\n\n        SQLIndexDefinition indexDefinition = x.getIndexDefinition();\n        if (indexDefinition.hasOptions()) {\n            indexDefinition.getOptions().accept(this);\n        }\n\n        SQLExpr comment = x.getComment();\n        if (indexDefinition.hasOptions()\n                && indexDefinition.getOptions().getComment() == comment) {\n            comment = null;\n        }\n\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            printExpr(comment);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCharExpr x, boolean parameterized) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (this.appender == null) {\n            return false;\n        }\n\n        if (parameterized) {\n            this.appender.append('?');\n            incrementReplaceCunt();\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            return false;\n        }\n\n        this.appender.append('\\'');\n\n        String text = x.getText();\n\n        boolean hasSpecial = false;\n        for (int i = 0; i < text.length(); ++i) {\n            char ch = text.charAt(i);\n            if (ch == '\\'' || ch == '\\\\' || ch == '\\0') {\n                hasSpecial = true;\n                break;\n            }\n        }\n\n        if (hasSpecial) {\n            boolean regForPresto = false;\n            if (isEnabled(VisitorFeature.OutputRegForPresto) && x.getParent() instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr regCall = (SQLMethodInvokeExpr) x.getParent();\n                long nameHash = regCall.methodNameHashCode64();\n                regForPresto = (x == regCall.getArguments().get(1)) && (nameHash == FnvHash.Constants.REGEXP_SUBSTR\n                        || nameHash == FnvHash.Constants.REGEXP_COUNT || nameHash == FnvHash.Constants.REGEXP_EXTRACT\n                        || nameHash == FnvHash.Constants.REGEXP_EXTRACT_ALL || nameHash == FnvHash.Constants.REGEXP_LIKE\n                        || nameHash == FnvHash.Constants.REGEXP_REPLACE || nameHash == FnvHash.Constants.REGEXP_SPLIT);\n            }\n\n            for (int i = 0; i < text.length(); ++i) {\n                char ch = text.charAt(i);\n                if (ch == '\\'') {\n                    appender.append('\\'');\n                    appender.append('\\'');\n                } else if (ch == '\\\\') {\n                    appender.append('\\\\');\n                    if (regForPresto) {\n                        continue;\n                    }\n                    if (i < text.length() - 1 && text.charAt(i + 1) == '_') {\n                        continue;\n                    }\n                    appender.append('\\\\');\n                } else if (ch == '\\0') {\n                    appender.append('\\\\');\n                    appender.append('0');\n                } else {\n                    appender.append(ch);\n                }\n            }\n        } else {\n            appender.append(text);\n        }\n\n        appender.append('\\'');\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        {\n            int index = x.getIndex();\n\n            if (inputParameters != null && index < inputParameters.size()) {\n                return super.visit(x);\n            }\n        }\n\n        if (x.isGlobal()) {\n            print0(\"@@global.\");\n        } else if (x.isSession()) {\n            print0(\"@@session.\");\n        }\n\n        String varName = x.getName();\n        for (int i = 0; i < varName.length(); ++i) {\n            char ch = varName.charAt(i);\n            if (ch == '\\'') {\n                if (varName.startsWith(\"@@\") && i == 2) {\n                    print(ch);\n                } else if (varName.startsWith(\"@\") && i == 1) {\n                    print(ch);\n                } else if (i != 0 && i != varName.length() - 1) {\n                    print0(\"\\\\'\");\n                } else {\n                    print(ch);\n                }\n            } else {\n                print(ch);\n            }\n        }\n\n        String collate = (String) x.getAttribute(\"COLLATE\");\n        if (collate != null) {\n            print0(ucase ? \" COLLATE \" : \" collate \");\n            print0(collate);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlPrepareStatement x) {\n        print0(ucase ? \"PREPARE \" : \"prepare \");\n        x.getName().accept(this);\n        print0(ucase ? \" FROM \" : \" from \");\n        x.getFrom().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExecuteStatement x) {\n        print0(ucase ? \"EXECUTE \" : \"execute \");\n        x.getStatementName().accept(this);\n        if (x.getParameters().size() > 0) {\n            print0(ucase ? \" USING \" : \" using \");\n            printAndAccept(x.getParameters(), \", \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExecuteForAdsStatement x) {\n        print0(ucase ? \"EXECUTE \" : \"execute \");\n        x.getAction().accept(this);\n        print(\" \");\n        x.getRole().accept(this);\n        print(\" \");\n        x.getTargetId().accept(this);\n        print(\" \");\n        if (x.getStatus() != null) {\n            x.getStatus().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlManageInstanceGroupStatement x) {\n        x.getOperation().accept(this);\n\n        print0(ucase ? \" INSTANCE_GROUP \" : \" instance_group \");\n        printAndAccept(x.getGroupNames(), \",\");\n\n        if (x.getReplication() != null) {\n            print0(ucase ? \" REPLICATION = \" : \" replication = \");\n            x.getReplication().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRaftMemberChangeStatement x) {\n        print0(ucase ? \"SYNC RAFT_MEMBER_CHANGE \" : \"sync raft_member_change \");\n\n        if (x.isNoLeader()) {\n            print0(ucase ? \"NOLEADER \" : \"noleader \");\n        }\n\n        print0(ucase ? \"SHARD=\" : \"shard=\");\n        x.getShard().accept(this);\n\n        print0(ucase ? \" HOST=\" : \" host=\");\n        x.getHost().accept(this);\n\n        print0(ucase ? \" STATUS=\" : \" status=\");\n        x.getStatus().accept(this);\n\n        if (x.isForce()) {\n            print0(ucase ? \" FORCE\" : \" force\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRaftLeaderTransferStatement x) {\n        print0(ucase ? \"SYNC RAFT_LEADER_TRANSFER SHARD=\" : \"sync raft_leader_transfer shard=\");\n        x.getShard().accept(this);\n\n        print0(ucase ? \" FROM=\" : \" from=\");\n        x.getFrom().accept(this);\n\n        print0(ucase ? \" TO=\" : \" to=\");\n        x.getTo().accept(this);\n\n        print0(ucase ? \" TIMEOUT=\" : \" timeout=\");\n        x.getTimeout().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlMigrateStatement x) {\n        return false;\n    }\n\n    @Override\n    public void endVisit(MySqlMigrateStatement x) {\n        print0(ucase ? \"MIGRATE DATABASE \" : \"migrate database \");\n        x.getSchema().accept(this);\n\n        print0(ucase ? \" SHARDS=\" : \"shards= \");\n        x.getShardNames().accept(this);\n        print0(\" \");\n        if (x.getMigrateType().getNumber().intValue() == 0) {\n            print0(ucase ? \"GROUP \" : \"group \");\n        } else if (x.getMigrateType().getNumber().intValue() == 1) {\n            print0(ucase ? \"HOST \" : \"host \");\n        }\n\n        print0(ucase ? \"FROM \" : \"from \");\n        x.getFromInsId().accept(this);\n\n        if (x.getFromInsIp() != null) {\n            print(\":\");\n            x.getFromInsIp().accept(this);\n            print(\":\");\n            x.getFromInsPort().accept(this);\n            print(\":\");\n            x.getFromInsStatus().accept(this);\n        }\n\n        print0(ucase ? \" TO \" : \" to \");\n        x.getToInsId().accept(this);\n\n        if (x.getToInsIp() != null) {\n            print(\":\");\n            x.getToInsIp().accept(this);\n            print(\":\");\n            x.getToInsPort().accept(this);\n            print(\":\");\n            x.getToInsStatus().accept(this);\n        }\n\n    }\n\n    @Override\n    public boolean visit(MySqlShowClusterNameStatement x) {\n        print0(ucase ? \"SHOW CLUSTER NAME\" : \"show cluster name\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowJobStatusStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n        if (x.isSync()) {\n            print0(ucase ? \"SYNC_JOB \" : \"sync_job \");\n        } else {\n            print0(ucase ? \"JOB \" : \"job \");\n        }\n        print0(ucase ? \"STATUS \" : \"status \");\n\n        if (x.getWhere() != null) {\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowMigrateTaskStatusStatement x) {\n        print0(ucase ? \"SHOW MIGRATE TASK STATUS\" : \"show migrate task status\");\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(MysqlDeallocatePrepareStatement x) {\n        print0(ucase ? \"DEALLOCATE PREPARE \" : \"deallocate prepare \");\n        x.getStatementName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDeleteStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (this.isPrettyFormat() && x.hasBeforeComment()) {\n            this.printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"DELETE \" : \"delete \");\n\n        for (int i = 0, size = x.getHintsSize(); i < size; ++i) {\n            SQLCommentHint hint = x.getHints().get(i);\n            hint.accept(this);\n            print(' ');\n        }\n\n        if (x.isLowPriority()) {\n            print0(ucase ? \"LOW_PRIORITY \" : \"low_priority \");\n        }\n\n        if (x.isQuick()) {\n            print0(ucase ? \"QUICK \" : \"quick \");\n        }\n\n        if (x.isIgnore()) {\n            print0(ucase ? \"IGNORE \" : \"ignore \");\n        }\n\n        if (x.isForceAllPartitions()) {\n            print0(ucase ? \"FORCE ALL PARTITIONS \" : \"force all partitions \");\n        } else {\n            SQLName partition = x.getForcePartition();\n            if (partition != null) {\n                print0(ucase ? \"FORCE PARTITION \" : \"force partition \");\n                printExpr(partition, parameterized);\n                print(' ');\n            }\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from == null) {\n            print0(ucase ? \"FROM \" : \"from \");\n            if (x.isFulltextDictionary()) {\n                print0(ucase ? \"FULLTEXT DICTIONARY \" : \"fulltext dictionary \");\n            }\n            x.getTableSource().accept(this);\n        } else {\n            x.getTableSource().accept(this);\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n            from.accept(this);\n        }\n\n        SQLTableSource using = x.getUsing();\n        if (using != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            using.accept(this);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            this.indentCount++;\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where, parameterized);\n            this.indentCount--;\n        }\n\n        if (x.getOrderBy() != null) {\n            println();\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            println();\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlInsertStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (this.isPrettyFormat() && x.hasBeforeComment()) {\n            this.printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        for (int i = 0, size = x.getHintsSize(); i < size; ++i) {\n            SQLCommentHint hint = x.getHints().get(i);\n            hint.accept(this);\n            print(' ');\n        }\n\n        if (x.isLowPriority()) {\n            print0(ucase ? \"LOW_PRIORITY \" : \"low_priority \");\n        }\n\n        if (x.isDelayed()) {\n            print0(ucase ? \"DELAYED \" : \"delayed \");\n        }\n\n        if (x.isHighPriority()) {\n            print0(ucase ? \"HIGH_PRIORITY \" : \"high_priority \");\n        }\n\n        if (x.isIgnore()) {\n            print0(ucase ? \"IGNORE \" : \"ignore \");\n        }\n\n        if (x.isRollbackOnFail()) {\n            print0(ucase ? \"ROLLBACK_ON_FAIL \" : \"rollback_on_fail \");\n        }\n\n        boolean outputIntoKeyword = true;\n        if (x.isOverwrite()) {\n            print0(ucase ? \"OVERWRITE \" : \"overwrite \");\n        }\n\n        if (outputIntoKeyword) {\n            print0(ucase ? \"INTO \" : \"into \");\n        }\n\n        if (x.isFulltextDictionary()) {\n            print0(ucase ? \"FULLTEXT DICTIONARY \" : \"fulltext dictionary \");\n        }\n\n        SQLExprTableSource tableSource = x.getTableSource();\n        if (tableSource != null) {\n            if (tableSource.getClass() == SQLExprTableSource.class) {\n                visit(tableSource);\n            } else {\n                tableSource.accept(this);\n            }\n        }\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (partitions != null) {\n            int partitionsSize = partitions.size();\n            if (partitionsSize > 0) {\n                print0(ucase ? \" PARTITION (\" : \" partition (\");\n                for (int i = 0; i < partitionsSize; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                    }\n\n                    SQLAssignItem assign = partitions.get(i);\n                    assign.getTarget().accept(this);\n\n                    if (assign.getValue() != null) {\n                        print('=');\n                        assign.getValue().accept(this);\n                    }\n                }\n                print(')');\n            }\n\n            if (x.isIfNotExists()) {\n                print0(ucase ? \" IF NOT EXISTS \" : \"if not exists \");\n            }\n        }\n\n        String columnsString = x.getColumnsString();\n        if (columnsString != null) {\n            if (!isEnabled(VisitorFeature.OutputSkipInsertColumnsString)) {\n                print0(columnsString);\n            }\n        } else {\n            List<SQLExpr> columns = x.getColumns();\n            if (columns.size() > 0) {\n                this.indentCount++;\n                print0(\" (\");\n                for (int i = 0, size = columns.size(); i < size; ++i) {\n                    if (i != 0) {\n                        if (i % 5 == 0) {\n                            println();\n                        }\n                        print0(\", \");\n                    }\n\n                    SQLExpr column = columns.get(i);\n                    if (column.hasBeforeComment()) {\n                        print(' ');\n                        printlnComment(column.getBeforeCommentsDirect());\n                        println();\n                    }\n                    if (column instanceof SQLIdentifierExpr) {\n                        printName0(((SQLIdentifierExpr) column).getName());\n                    } else {\n                        printExpr(column, parameterized);\n                    }\n                    if (column.hasAfterComment()) {\n                        print(' ');\n                        printlnComment(column.getAfterCommentsDirect());\n                        println();\n                    }\n                }\n                print(')');\n                this.indentCount--;\n            }\n        }\n\n        List<SQLInsertStatement.ValuesClause> valuesList = x.getValuesList();\n        if (!valuesList.isEmpty()) {\n            println();\n            printValuesList(valuesList);\n        }\n\n        if (x.getQuery() != null) {\n            println();\n            x.getQuery().accept(this);\n        }\n\n        List<SQLExpr> duplicateKeyUpdate = x.getDuplicateKeyUpdate();\n        if (!duplicateKeyUpdate.isEmpty()) {\n            println();\n            print0(ucase ? \"ON DUPLICATE KEY UPDATE \" : \"on duplicate key update \");\n            for (int i = 0, size = duplicateKeyUpdate.size(); i < size; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        println();\n                    }\n                    print0(\", \");\n                }\n                duplicateKeyUpdate.get(i).accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    protected void printValuesList(List<SQLInsertStatement.ValuesClause> valuesList) {\n        if (this.parameterized\n                && valuesList.size() > 1\n                && !this.parameterizedQuesUnMergeValuesList) {\n            print0(ucase ? \"VALUES \" : \"values \");\n            this.indentCount++;\n\n            boolean allConst = true;\n            if (valuesList.size() > 1) {\n                for (int index = 0; index < valuesList.size(); index++) {\n                    List<SQLExpr> values = valuesList.get(index).getValues();\n                    for (int i = 0; i < values.size(); i++) {\n                        SQLExpr value = values.get(i);\n                        if (value instanceof SQLLiteralExpr || value instanceof SQLVariantRefExpr) {\n                            continue;\n                        } else if (value instanceof SQLMethodInvokeExpr && ((SQLMethodInvokeExpr) value).getArguments().isEmpty()) {\n                            continue;\n                        }\n                        allConst = false;\n                        break;\n                    }\n                    if (!allConst) {\n                        break;\n                    }\n                }\n            }\n\n            if (!allConst) {\n                for (int index = 0; index < valuesList.size(); index++) {\n                    if (index != 0) {\n                        print(',');\n                        println();\n                    }\n                    visit(valuesList.get(index), this.parameters);\n                }\n            } else if (valuesList.size() > 1 && this.parameters != null) {\n                SQLInsertStatement.ValuesClause first = valuesList.get(0);\n\n                List<Object> valuesParameters = new ArrayList<Object>(first.getValues().size());\n                visit(first, valuesParameters);\n                this.parameters.add(valuesParameters);\n\n                for (int index = 1; index < valuesList.size(); index++) {\n                    List<SQLExpr> values = valuesList.get(index).getValues();\n                    valuesParameters = new ArrayList<Object>(values.size());\n\n                    for (int i = 0, size = values.size(); i < size; ++i) {\n                        SQLExpr expr = values.get(i);\n                        if (expr instanceof SQLIntegerExpr\n                                || expr instanceof SQLBooleanExpr\n                                || expr instanceof SQLNumberExpr\n                                || expr instanceof SQLCharExpr\n                                || expr instanceof SQLNCharExpr\n                                || expr instanceof SQLTimestampExpr\n                                || expr instanceof SQLDateExpr\n                                || expr instanceof SQLTimeExpr) {\n                            incrementReplaceCunt();\n                            ExportParameterVisitorUtils.exportParameter(valuesParameters, expr);\n                        } else if (expr instanceof SQLNullExpr) {\n                            incrementReplaceCunt();\n                            valuesParameters.add(null);\n                        } else {\n                            // skip\n                        }\n                    }\n\n                    this.parameters.add(valuesParameters);\n                }\n\n                this.incrementReplaceCunt();\n            } else {\n                if (valuesList.size() > 1) {\n                    this.incrementReplaceCunt();\n                }\n                visit(valuesList.get(0), this.parameters);\n            }\n\n            this.indentCount--;\n            return;\n        }\n\n        print0(ucase ? \"VALUES \" : \"values \");\n        if (valuesList.size() > 1) {\n            this.indentCount++;\n        }\n        for (int i = 0, size = valuesList.size(); i < size; ++i) {\n            if (i != 0) {\n                print(',');\n                println();\n            }\n\n            SQLInsertStatement.ValuesClause item = valuesList.get(i);\n            visit(item, parameters);\n        }\n        if (valuesList.size() > 1) {\n            this.indentCount--;\n        }\n    }\n\n    @Override\n    public boolean visit(MySqlLoadDataInFileStatement x) {\n        print0(ucase ? \"LOAD DATA \" : \"load data \");\n\n        if (x.isLowPriority()) {\n            print0(ucase ? \"LOW_PRIORITY \" : \"low_priority \");\n        }\n\n        if (x.isConcurrent()) {\n            print0(ucase ? \"CONCURRENT \" : \"concurrent \");\n        }\n\n        if (x.isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        print0(ucase ? \"INFILE \" : \"infile \");\n\n        x.getFileName().accept(this);\n\n        if (x.isReplicate()) {\n            print0(ucase ? \" REPLACE \" : \" replace \");\n        }\n\n        if (x.isIgnore()) {\n            print0(ucase ? \" IGNORE \" : \" ignore \");\n        }\n\n        print0(ucase ? \" INTO TABLE \" : \" into table \");\n        x.getTableName().accept(this);\n\n        if (x.getColumnsTerminatedBy() != null || x.getColumnsEnclosedBy() != null || x.getColumnsEscaped() != null) {\n            print0(ucase ? \" COLUMNS\" : \" columns\");\n            if (x.getColumnsTerminatedBy() != null) {\n                print0(ucase ? \" TERMINATED BY \" : \" terminated by \");\n                x.getColumnsTerminatedBy().accept(this);\n            }\n\n            if (x.getColumnsEnclosedBy() != null) {\n                if (x.isColumnsEnclosedOptionally()) {\n                    print0(ucase ? \" OPTIONALLY\" : \" optionally\");\n                }\n                print0(ucase ? \" ENCLOSED BY \" : \" enclosed by \");\n                x.getColumnsEnclosedBy().accept(this);\n            }\n\n            if (x.getColumnsEscaped() != null) {\n                print0(ucase ? \" ESCAPED BY \" : \" escaped by \");\n                x.getColumnsEscaped().accept(this);\n            }\n        }\n\n        if (x.getLinesStartingBy() != null || x.getLinesTerminatedBy() != null) {\n            print0(ucase ? \" LINES\" : \" lines\");\n            if (x.getLinesStartingBy() != null) {\n                print0(ucase ? \" STARTING BY \" : \" starting by \");\n                x.getLinesStartingBy().accept(this);\n            }\n\n            if (x.getLinesTerminatedBy() != null) {\n                print0(ucase ? \" TERMINATED BY \" : \" terminated by \");\n                x.getLinesTerminatedBy().accept(this);\n            }\n        }\n\n        if (x.getIgnoreLinesNumber() != null) {\n            print0(ucase ? \" IGNORE \" : \" ignore \");\n            x.getIgnoreLinesNumber().accept(this);\n            print0(ucase ? \" LINES\" : \" lines\");\n        }\n\n        if (!x.getColumns().isEmpty()) {\n            print0(\" (\");\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        if (!x.getSetList().isEmpty()) {\n            print0(ucase ? \" SET \" : \" set \");\n            printAndAccept(x.getSetList(), \", \");\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLReplaceStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        print0(ucase ? \"REPLACE \" : \"replace \");\n\n        if (x.isLowPriority()) {\n            print0(ucase ? \"LOW_PRIORITY \" : \"low_priority \");\n        }\n\n        if (x.isDelayed()) {\n            print0(ucase ? \"DELAYED \" : \"delayed \");\n        }\n\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \" \");\n            print0(\" \");\n        }\n\n        print0(ucase ? \"INTO \" : \"into \");\n\n        printTableSourceExpr(x.getTableName());\n\n        List<SQLExpr> columns = x.getColumns();\n        if (columns.size() > 0) {\n            print0(\" (\");\n            for (int i = 0, size = columns.size(); i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n\n                SQLExpr columnn = columns.get(i);\n                printExpr(columnn, parameterized);\n            }\n            print(')');\n        }\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (partitions != null) {\n            int partitionsSize = partitions.size();\n            if (partitionsSize > 0) {\n                print0(ucase ? \" PARTITION (\" : \" partition (\");\n                for (int i = 0; i < partitionsSize; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                    }\n\n                    SQLAssignItem assign = partitions.get(i);\n                    assign.getTarget().accept(this);\n\n                    if (assign.getValue() != null) {\n                        print('=');\n                        assign.getValue().accept(this);\n                    }\n                }\n                print(')');\n            }\n        }\n\n        List<SQLInsertStatement.ValuesClause> valuesClauseList = x.getValuesList();\n        if (!valuesClauseList.isEmpty()) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            int size = valuesClauseList.size();\n            if (size == 0) {\n                print0(\"()\");\n            } else {\n                for (int i = 0; i < size; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                    }\n                    visit(valuesClauseList.get(i));\n                }\n            }\n        }\n\n        SQLQueryExpr query = x.getQuery();\n        if (query != null) {\n            visit(query);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLStartTransactionStatement x) {\n        print0(ucase ? \"START TRANSACTION\" : \"start transaction\");\n        if (x.isConsistentSnapshot()) {\n            print0(ucase ? \" WITH CONSISTENT SNAPSHOT\" : \" with consistent snapshot\");\n        }\n\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            print(' ');\n            printAndAccept(x.getHints(), \" \");\n        }\n\n        if (x.isBegin()) {\n            print0(ucase ? \" BEGIN\" : \" begin\");\n        }\n\n        if (x.isWork()) {\n            print0(ucase ? \" WORK\" : \" work\");\n        }\n\n        SQLStartTransactionStatement.IsolationLevel isolationLevel = x.getIsolationLevel();\n        if (isolationLevel != null) {\n            print0(\" ISOLATION LEVEL \");\n            print(isolationLevel.getText());\n        }\n\n        if (x.isReadOnly()) {\n            print0(ucase ? \" READ ONLY\" : \" read only\");\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLRollbackStatement x) {\n        print0(ucase ? \"ROLLBACK\" : \"rollback\");\n\n        if (x.getChain() != null) {\n            if (x.getChain().booleanValue()) {\n                print0(ucase ? \" AND CHAIN\" : \" and chain\");\n            } else {\n                print0(ucase ? \" AND NO CHAIN\" : \" and no chain\");\n            }\n        }\n\n        if (x.getRelease() != null) {\n            if (x.getRelease().booleanValue()) {\n                print0(ucase ? \" AND RELEASE\" : \" and release\");\n            } else {\n                print0(ucase ? \" AND NO RELEASE\" : \" and no release\");\n            }\n        }\n\n        if (x.getTo() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            x.getTo().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowTablesStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.isFull()) {\n            print0(ucase ? \"SHOW FULL TABLES\" : \"show full tables\");\n        } else {\n            print0(ucase ? \"SHOW TABLES\" : \"show tables\");\n        }\n\n        if (x.getDatabase() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getDatabase().accept(this);\n        }\n\n        final SQLExpr like = x.getLike();\n        if (like != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            printExpr(like);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowHMSMetaStatement x) {\n        print0(ucase ? \"SHOW HMSMETA \" : \"show hmsmeta \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDatabaseStatusStatement x) {\n        if (x.isFull()) {\n            print0(ucase ? \"SHOW FULL DATABASE STATUS\" : \"show full database status\");\n        } else {\n            print0(ucase ? \"SHOW DATABASE STATUS\" : \"show database status\");\n        }\n\n        if (x.getName() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getName().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowWarningsStatement x) {\n        if (x.isCount()) {\n            print0(ucase ? \"SHOW COUNT(*) WARNINGS\" : \"show count(*) warnings\");\n        } else {\n            print0(ucase ? \"SHOW WARNINGS\" : \"show warnings\");\n            if (x.getLimit() != null) {\n                print(' ');\n                x.getLimit().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowStatusStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n\n        if (x.isGlobal()) {\n            print0(ucase ? \"GLOBAL \" : \"global \");\n        }\n\n        if (x.isSession()) {\n            print0(ucase ? \"SESSION \" : \"session \");\n        }\n\n        print0(ucase ? \"STATUS\" : \"status\");\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlLoadXmlStatement x) {\n        print0(ucase ? \"LOAD XML \" : \"load xml \");\n\n        if (x.isLowPriority()) {\n            print0(ucase ? \"LOW_PRIORITY \" : \"low_priority \");\n        }\n\n        if (x.isConcurrent()) {\n            print0(ucase ? \"CONCURRENT \" : \"concurrent \");\n        }\n\n        if (x.isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        print0(ucase ? \"INFILE \" : \"infile \");\n\n        x.getFileName().accept(this);\n\n        if (x.isReplicate()) {\n            print0(ucase ? \" REPLACE \" : \" replace \");\n        }\n\n        if (x.isIgnore()) {\n            print0(ucase ? \" IGNORE \" : \" ignore \");\n        }\n\n        print0(ucase ? \" INTO TABLE \" : \" into table \");\n        x.getTableName().accept(this);\n\n        if (x.getCharset() != null) {\n            print0(ucase ? \" CHARSET \" : \" charset \");\n            print0(x.getCharset());\n        }\n\n        if (x.getRowsIdentifiedBy() != null) {\n            print0(ucase ? \" ROWS IDENTIFIED BY \" : \" rows identified by \");\n            x.getRowsIdentifiedBy().accept(this);\n        }\n\n        if (!x.getSetList().isEmpty()) {\n            print0(ucase ? \" SET \" : \" set \");\n            printAndAccept(x.getSetList(), \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(CobarShowStatus x) {\n        print0(ucase ? \"SHOW COBAR_STATUS\" : \"show cobar_status\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsShowDDLJobs x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n        if (x.isFull()) {\n            print0(ucase ? \"FULL \" : \"full \");\n        }\n        print0(ucase ? \"DDL\" : \"ddl\");\n        boolean first = true;\n        for (Long id : x.getJobIds()) {\n            if (first) {\n                first = false;\n                print0(\" \");\n            } else {\n                print0(\", \");\n            }\n            print(id);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsCancelDDLJob x) {\n        print0(ucase ? \"CANCEL DDL\" : \"cancel ddl\");\n        boolean first = true;\n        for (Long id : x.getJobIds()) {\n            if (first) {\n                first = false;\n                print0(\" \");\n            } else {\n                print0(\", \");\n            }\n            print(id);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsRecoverDDLJob x) {\n        print0(ucase ? \"RECOVER DDL\" : \"recover ddl\");\n        if (x.isAllJobs()) {\n            print0(ucase ? \" ALL\" : \" all\");\n        } else {\n            boolean first = true;\n            for (Long id : x.getJobIds()) {\n                if (first) {\n                    first = false;\n                    print0(\" \");\n                } else {\n                    print0(\", \");\n                }\n                print(id);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsRollbackDDLJob x) {\n        print0(ucase ? \"ROLLBACK DDL\" : \"rollback ddl\");\n        boolean first = true;\n        for (Long id : x.getJobIds()) {\n            if (first) {\n                first = false;\n                print0(\" \");\n            } else {\n                print0(\", \");\n            }\n            print(id);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsRemoveDDLJob x) {\n        print0(ucase ? \"REMOVE DDL\" : \"remove ddl\");\n        if (x.isAllCompleted()) {\n            print0(ucase ? \" ALL COMPLETED\" : \" all completed\");\n        } else if (x.isAllPending()) {\n            print(ucase ? \" ALL PENDING\" : \" all pending\");\n        } else {\n            boolean first = true;\n            for (Long id : x.getJobIds()) {\n                if (first) {\n                    first = false;\n                    print0(\" \");\n                } else {\n                    print0(\", \");\n                }\n                print(id);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsInspectDDLJobCache x) {\n        print0(ucase ? \"INSPECT DDL CACHE\" : \"inspect ddl cache\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsClearDDLJobCache x) {\n        print0(ucase ? \"CLEAR DDL CACHE\" : \"clear ddl cache\");\n        if (x.isAllJobs()) {\n            print0(ucase ? \" ALL\" : \" all\");\n        } else {\n            boolean first = true;\n            for (Long id : x.getJobIds()) {\n                if (first) {\n                    first = false;\n                    print0(\" \");\n                } else {\n                    print0(\", \");\n                }\n                print(id);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsChangeDDLJob x) {\n        print0(ucase ? \"CHANGE DDL \" : \"change ddl \");\n        print(x.getJobId());\n        if (x.isSkip()) {\n            print0(ucase ? \" SKIP\" : \" skip\");\n        } else if (x.isAdd()) {\n            print0(ucase ? \" ADD\" : \" add\");\n        }\n\n        boolean first = true;\n        for (String name : x.getGroupAndTableNameList()) {\n            if (first) {\n                first = false;\n                print0(\" \");\n            } else {\n                print0(\", \");\n            }\n            print(name);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsBaselineStatement x) {\n        print0(ucase ? \"BASELINE \" : \"baseline \");\n        print0(ucase ? x.getOperation().toUpperCase() : x.getOperation().toLowerCase());\n\n        boolean isFirst = true;\n        for (Long id : x.getBaselineIds()) {\n            if (isFirst) {\n                print0(\" \");\n                isFirst = false;\n            } else {\n                print0(\", \");\n            }\n            print(id);\n        }\n\n        SQLSelect select = x.getSelect();\n        if (x.getSelect() != null) {\n            print(ucase ? \" SQL\" : \" sql\");\n            println();\n            List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n            if (headHints != null) {\n                for (SQLCommentHint hint : headHints) {\n                    visit((SQLCommentHint) hint);\n                    println();\n                }\n            }\n\n            this.visit(select);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsShowGlobalIndex x) {\n        print0(ucase ? \"SHOW GLOBAL INDEX\" : \"show global index\");\n        if (x.getTableName() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            printExpr(x.getTableName(), parameterized);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(DrdsShowMetadataLock x) {\n        print0(ucase ? \"SHOW METADATA LOCK\" : \"show metadata lock\");\n        if (x.getSchemaName() != null) {\n            print0(\" \");\n            printExpr(x.getSchemaName(), parameterized);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlBinlogStatement x) {\n        print0(ucase ? \"BINLOG \" : \"binlog \");\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateUserStatement x) {\n        print0(ucase ? \"CREATE USER \" : \"create user \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printAndAccept(x.getUsers(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(UserSpecification x) {\n        x.getUser().accept(this);\n\n        if (x.getAuthPlugin() != null) {\n            print0(ucase ? \" IDENTIFIED WITH \" : \" identified with \");\n            x.getAuthPlugin().accept(this);\n            if (x.getPassword() != null) {\n                if (x.isPluginAs()) {\n                    print0(ucase ? \" AS \" : \" as \");\n                } else {\n                    print0(ucase ? \" BY \" : \" by \");\n                }\n                x.getPassword().accept(this);\n            }\n        } else if (x.getPassword() != null) {\n            print0(ucase ? \" IDENTIFIED BY \" : \" identified by \");\n            if (x.isPasswordHash()) {\n                print0(ucase ? \"PASSWORD \" : \"password \");\n            }\n            x.getPassword().accept(this);\n        } else {\n            if (x.isRandomPassword()) {\n                print0(ucase ? \" IDENTIFIED BY \" : \" identified by \");\n                print0(ucase ? \"RANDOM PASSWORD \" : \"random password \");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlPartitionByKey x) {\n        if (x.isLinear()) {\n            print0(ucase ? \"LINEAR KEY (\" : \"linear key (\");\n        } else {\n            print0(ucase ? \"KEY (\" : \"key (\");\n        }\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        printPartitionsCountAndSubPartitions(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPlanCacheStatusStatement x) {\n        print0(ucase ? \"SHOW PLANCACHE STATUS\" : \"show plancache status\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlClearPlanCacheStatement x) {\n        print0(ucase ? \"CLEAR PLANCACHE\" : \"clear plancache\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDisabledPlanCacheStatement x) {\n        print0(ucase ? \"DISABLED PLANCACHE\" : \"disabled plancache\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExplainPlanCacheStatement x) {\n        print0(ucase ? \"EXPLAIN PLANCACHE\" : \"explain plancache\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUpdatePlanCacheStatement x) {\n        print0(ucase ? \"UPDATE PLANCACHE \" : \"update plancache \");\n        x.getFormSelect().accept(this);\n        println();\n        print0(ucase ? \" TO \" : \" to \");\n        println();\n        x.getToSelect().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlOutFileExpr x) {\n        print0(ucase ? \"OUTFILE \" : \"outfile \");\n        x.getFile().accept(this);\n\n        if (x.getCharset() != null) {\n            print0(ucase ? \" CHARACTER SET \" : \" character set \");\n            print0(x.getCharset());\n        }\n\n        if (x.getColumnsTerminatedBy() != null || x.getColumnsEnclosedBy() != null || x.getColumnsEscaped() != null) {\n            print0(ucase ? \" COLUMNS\" : \" columns\");\n            if (x.getColumnsTerminatedBy() != null) {\n                print0(ucase ? \" TERMINATED BY \" : \" terminated by \");\n                x.getColumnsTerminatedBy().accept(this);\n            }\n\n            if (x.getColumnsEnclosedBy() != null) {\n                if (x.isColumnsEnclosedOptionally()) {\n                    print0(ucase ? \" OPTIONALLY\" : \" optionally\");\n                }\n                print0(ucase ? \" ENCLOSED BY \" : \" enclosed by \");\n                x.getColumnsEnclosedBy().accept(this);\n            }\n\n            if (x.getColumnsEscaped() != null) {\n                print0(ucase ? \" ESCAPED BY \" : \" escaped by \");\n                x.getColumnsEscaped().accept(this);\n            }\n        }\n\n        if (x.getLinesStartingBy() != null || x.getLinesTerminatedBy() != null) {\n            print0(ucase ? \" LINES\" : \" lines\");\n            if (x.getLinesStartingBy() != null) {\n                print0(ucase ? \" STARTING BY \" : \" starting by \");\n                x.getLinesStartingBy().accept(this);\n            }\n\n            if (x.getLinesTerminatedBy() != null) {\n                print0(ucase ? \" TERMINATED BY \" : \" terminated by \");\n                x.getLinesTerminatedBy().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExplainStatement x) {\n        List<SQLCommentHint> hints = x.getHeadHintsDirect();\n        if (null != hints) {\n            for (int i = 0; i < hints.size(); i++) {\n                if (i != 0) {\n                    print(' ');\n                }\n                hints.get(i).accept(this);\n            }\n            println();\n        }\n\n        String name = x.isDescribe() ? \"desc\" : \"explain\";\n        print0(ucase ? name.toUpperCase() : name);\n\n        hints = x.getHints();\n        if (hints != null) {\n            print(' ');\n            for (int i = 0; i < hints.size(); i++) {\n                if (i != 0) {\n                    print(' ');\n                }\n                hints.get(i).accept(this);\n            }\n        }\n\n        String type = x.getType();\n        // tbl_name [col_name | wild]\n        if (x.getTableName() != null) {\n            print(' ');\n            x.getTableName().accept(this);\n            if (x.getColumnName() != null) {\n                print(' ');\n                x.getColumnName().accept(this);\n            } else if (x.getWild() != null) {\n                print(' ');\n                x.getWild().accept(this);\n            }\n        } else {\n            if (x.isExtended()) {\n                print0(ucase ? \" EXTENDED\" : \" extended\");\n            }\n\n            if (x.isOptimizer()) {\n                print0(ucase ? \" OPTIMIZER\" : \" optimizer\");\n            }\n\n            if (x.isDependency()) {\n                print0(ucase ? \" DEPENDENCY\" : \" dependency\");\n            }\n\n            if (x.isAuthorization()) {\n                print0(ucase ? \" AUTHORIZATION\" : \" authorization\");\n            }\n\n            // [explain_type]\n            String format = x.getFormat();\n            if (type != null || format != null) {\n                final boolean parenthesis = x.isParenthesis();\n                if (parenthesis) {\n                    print0(\" (\");\n                } else {\n                    print(' ');\n                }\n\n                if (type != null) {\n                    if (parenthesis) {\n                        print0(ucase ? \"TYPE \" : \"type \");\n                    }\n                    print0(type);\n                }\n\n                if (format != null) {\n                    if (type != null) {\n                        if (parenthesis) {\n                            print0(\", \");\n                        } else {\n                            print(' ');\n                        }\n                    }\n\n                    print0(ucase ? \"FORMAT \" : \"format \");\n                    if (!parenthesis) {\n                        print0(\"= \");\n                    }\n                    print0(format);\n                }\n\n                if (parenthesis) {\n                    print(')');\n                }\n            }\n\n            // {explainable_stmt | FOR CONNECTION connection_id}\n            if (x.getConnectionId() != null) {\n                print0(ucase ? \" FOR CONNECTION \" : \" for connection \");\n                x.getConnectionId().accept(this);\n            } else {\n                print(' ');\n                x.getStatement().accept(this);\n            }\n\n            if (x.isDistributeInfo()) {\n                print0(ucase ? \" DISTRIBUTE INFO\" : \" distribute info\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUpdateStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n            println();\n        }\n\n        List<SQLExpr> returning = x.getReturning();\n        if (returning != null && returning.size() > 0) {\n            print0(ucase ? \"SELECT \" : \"select \");\n            printAndAccept(returning, \", \");\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n        }\n\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        if (x.isLowPriority()) {\n            print0(ucase ? \"LOW_PRIORITY \" : \"low_priority \");\n        }\n\n        if (x.isIgnore()) {\n            print0(ucase ? \"IGNORE \" : \"ignore \");\n        }\n\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \" \");\n            print0(\" \");\n        }\n\n        if (x.isCommitOnSuccess()) {\n            print0(ucase ? \"COMMIT_ON_SUCCESS \" : \"commit_on_success \");\n        }\n\n        if (x.isRollBackOnFail()) {\n            print0(ucase ? \"ROLLBACK_ON_FAIL \" : \"rollback_on_fail \");\n        }\n\n        if (x.isQueryOnPk()) {\n            print0(ucase ? \"QUEUE_ON_PK \" : \"queue_on_pk \");\n        }\n\n        SQLExpr targetAffectRow = x.getTargetAffectRow();\n        if (targetAffectRow != null) {\n            print0(ucase ? \"TARGET_AFFECT_ROW \" : \"target_affect_row \");\n            printExpr(targetAffectRow, parameterized);\n            print(' ');\n        }\n\n        if (x.isForceAllPartitions()) {\n            print0(ucase ? \"FORCE ALL PARTITIONS \" : \"force all partitions \");\n        } else {\n            SQLName partition = x.getForcePartition();\n            if (partition != null) {\n                print0(ucase ? \"FORCE PARTITION \" : \"force partition \");\n                printExpr(partition, parameterized);\n                print(' ');\n            }\n        }\n\n        printTableSource(x.getTableSource());\n\n        println();\n        print0(ucase ? \"SET \" : \"set \");\n        List<SQLUpdateSetItem> items = x.getItems();\n        for (int i = 0, size = items.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLUpdateSetItem item = items.get(i);\n            visit(item);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            indentCount++;\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where, parameterized);\n            indentCount--;\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            visit(orderBy);\n        }\n\n        SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            println();\n            visit(limit);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSetTransactionStatement x) {\n        print0(ucase ? \"SET \" : \"set \");\n        if (x.getGlobal() != null && x.getGlobal()) {\n            print0(ucase ? \"GLOBAL \" : \"global \");\n        } else if (x.getSession() != null && x.getSession()) {\n            print0(ucase ? \"SESSION \" : \"session \");\n        }\n\n        print0(ucase ? \"TRANSACTION \" : \"transaction \");\n\n        if (x.getIsolationLevel() != null) {\n            print0(ucase ? \"ISOLATION LEVEL \" : \"isolation level \");\n            print0(x.getIsolationLevel());\n        }\n\n        final String accessModel = x.getAccessModel();\n        if (accessModel != null) {\n            print0(ucase ? \"READ \" : \"read \");\n            print0(accessModel);\n        }\n\n        final SQLExpr policy = x.getPolicy();\n        if (policy != null) {\n            print0(ucase ? \"POLICY \" : \"policy \");\n            policy.accept(this);\n        }\n\n        return false;\n    }\n\n//\n//    @Override\n//    public boolean visit(MySqlSetNamesStatement x) {\n//        print0(ucase ? \"SET NAMES \" : \"set names \");\n//        if (x.isDefault()) {\n//            print0(ucase ? \"DEFAULT\" : \"default\");\n//        } else {\n//            print0(x.getCharSet());\n//            if (x.getCollate() != null) {\n//                print0(ucase ? \" COLLATE \" : \" collate \");\n//                print0(x.getCollate());\n//            }\n//        }\n//        return false;\n//    }\n\n//    public boolean visit(MySqlSetCharSetStatement x) {\n//        print0(ucase ? \"SET CHARACTER SET \" : \"set character set \");\n//        if (x.isDefault()) {\n//            print0(ucase ? \"DEFAULT\" : \"default\");\n//        } else {\n//            print0(x.getCharSet());\n//            if (x.getCollate() != null) {\n//                print0(ucase ? \" COLLATE \" : \" collate \");\n//                print0(x.getCollate());\n//            }\n//        }\n//        return false;\n//    }\n\n    @Override\n    public boolean visit(MySqlShowAuthorsStatement x) {\n        print0(ucase ? \"SHOW AUTHORS\" : \"show authors\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowBinaryLogsStatement x) {\n        print0(ucase ? \"SHOW BINARY LOGS\" : \"show binary logs\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowMasterLogsStatement x) {\n        print0(ucase ? \"SHOW MASTER LOGS\" : \"show master logs\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCollationStatement x) {\n        print0(ucase ? \"SHOW COLLATION\" : \"show collation\");\n        if (x.getPattern() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getPattern().accept(this);\n        }\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowBinLogEventsStatement x) {\n        print0(ucase ? \"SHOW BINLOG EVENTS\" : \"show binlog events\");\n        if (x.getIn() != null) {\n            print0(ucase ? \" IN \" : \" in \");\n            x.getIn().accept(this);\n        }\n        if (x.getFrom() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getFrom().accept(this);\n        }\n        if (x.getLimit() != null) {\n            print(' ');\n            x.getLimit().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCharacterSetStatement x) {\n        print0(ucase ? \"SHOW CHARACTER SET\" : \"show character set\");\n        if (x.getPattern() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getPattern().accept(this);\n        }\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowContributorsStatement x) {\n        print0(ucase ? \"SHOW CONTRIBUTORS\" : \"show contributors\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateDatabaseStatement x) {\n        print0(ucase ? \"SHOW CREATE DATABASE \" : \"show create database \");\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        x.getDatabase().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateEventStatement x) {\n        print0(ucase ? \"SHOW CREATE EVENT \" : \"show create event \");\n        x.getEventName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateFunctionStatement x) {\n        print0(ucase ? \"SHOW CREATE FUNCTION \" : \"show create function \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateProcedureStatement x) {\n        print0(ucase ? \"SHOW CREATE PROCEDURE \" : \"show create procedure \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateTriggerStatement x) {\n        print0(ucase ? \"SHOW CREATE TRIGGER \" : \"show create trigger \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowEngineStatement x) {\n        print0(ucase ? \"SHOW ENGINE \" : \"show engine \");\n        x.getName().accept(this);\n        print(' ');\n        print0(x.getOption().name());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowEventsStatement x) {\n        print0(ucase ? \"SHOW EVENTS\" : \"show events\");\n        if (x.getSchema() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getSchema().accept(this);\n        }\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowFunctionCodeStatement x) {\n        print0(ucase ? \"SHOW FUNCTION CODE \" : \"show function code \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowFunctionStatusStatement x) {\n        print0(ucase ? \"SHOW FUNCTION STATUS\" : \"show function status\");\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowEnginesStatement x) {\n        if (x.isStorage()) {\n            print0(ucase ? \"SHOW STORAGE ENGINES\" : \"show storage engines\");\n        } else {\n            print0(ucase ? \"SHOW ENGINES\" : \"show engines\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowErrorsStatement x) {\n        if (x.isCount()) {\n            print0(ucase ? \"SHOW COUNT(*) ERRORS\" : \"show count(*) errors\");\n        } else {\n            print0(ucase ? \"SHOW ERRORS\" : \"show errors\");\n            if (x.getLimit() != null) {\n                print(' ');\n                x.getLimit().accept(this);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowGrantsStatement x) {\n        print0(ucase ? \"SHOW GRANTS\" : \"show grants\");\n        SQLExpr user = x.getUser();\n        if (user != null) {\n            print0(ucase ? \" FOR \" : \" for \");\n            user.accept(this);\n        }\n\n        SQLExpr on = x.getOn();\n        if (on != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            on.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUserName x) {\n        String userName = x.getUserName();\n\n        if (userName.length() > 0 && userName.charAt(0) == '\\'') {\n            print0(userName);\n        } else {\n            print('\\'');\n            print0(userName);\n            print('\\'');\n        }\n\n        String host = x.getHost();\n        if (host != null) {\n            print('@');\n\n            if (host.length() > 0 && host.charAt(0) == '\\'') {\n                print0(host);\n            } else {\n                print('\\'');\n                print0(host);\n                print('\\'');\n            }\n        }\n\n        String identifiedBy = x.getIdentifiedBy();\n        if (identifiedBy != null) {\n            print0(ucase ? \" IDENTIFIED BY '\" : \" identified by '\");\n            print0(identifiedBy);\n            print('\\'');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowMasterStatusStatement x) {\n        print0(ucase ? \"SHOW MASTER STATUS\" : \"show master status\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowOpenTablesStatement x) {\n        print0(ucase ? \"SHOW OPEN TABLES\" : \"show open tables\");\n\n        if (x.getDatabase() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getDatabase().accept(this);\n        }\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPluginsStatement x) {\n        print0(ucase ? \"SHOW PLUGINS\" : \"show plugins\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPartitionsStatement x) {\n        print0(ucase ? \"SHOW DBPARTITIONS \" : \"show dbpartitions \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowPartitionsStmt x) {\n        print0(ucase ? \"SHOW PARTITIONS FROM \" : \"show partitions from \");\n        x.getTableSource().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPrivilegesStatement x) {\n        print0(ucase ? \"SHOW PRIVILEGES\" : \"show privileges\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProcedureCodeStatement x) {\n        print0(ucase ? \"SHOW PROCEDURE CODE \" : \"show procedure code \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProcedureStatusStatement x) {\n        print0(ucase ? \"SHOW PROCEDURE STATUS\" : \"show procedure status\");\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProcessListStatement x) {\n        return visit((SQLShowProcessListStatement) x);\n    }\n\n    @Override\n    public boolean visit(MySqlShowProfileStatement x) {\n        print0(ucase ? \"SHOW PROFILE\" : \"show profile\");\n        for (int i = 0; i < x.getTypes().size(); ++i) {\n            if (i == 0) {\n                print(' ');\n            } else {\n                print0(\", \");\n            }\n            print0(x.getTypes().get(i).name);\n        }\n\n        if (x.getForQuery() != null) {\n            print0(ucase ? \" FOR QUERY \" : \" for query \");\n            x.getForQuery().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print(' ');\n            x.getLimit().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProfilesStatement x) {\n        print0(ucase ? \"SHOW PROFILES\" : \"show profiles\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowRelayLogEventsStatement x) {\n        print0(\"SHOW RELAYLOG EVENTS\");\n\n        if (x.getLogName() != null) {\n            print0(ucase ? \" IN \" : \" in \");\n            x.getLogName().accept(this);\n        }\n\n        if (x.getFrom() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getFrom().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print(' ');\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSlaveHostsStatement x) {\n        print0(ucase ? \"SHOW SLAVE HOSTS\" : \"show slave hosts\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSlowStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n\n        if (x.isFull()) {\n            print0(ucase ? \"FULL \" : \"full \");\n        }\n        if (x.isPhysical()) {\n            print0(ucase ? \"PHYSICAL_SLOW\" : \"PHYSICAL_SLOW\");\n        } else {\n            print0(ucase ? \"SLOW\" : \"slow\");\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSequencesStatement x) {\n        print0(ucase ? \"SHOW SEQUENCES\" : \"show sequences\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSlaveStatusStatement x) {\n        print0(ucase ? \"SHOW SLAVE STATUS\" : \"show slave status\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTableStatusStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        print0(ucase ? \"SHOW TABLE STATUS\" : \"show table status\");\n        if (x.getDatabase() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getDatabase().accept(this);\n            if (x.getTableGroup() != null) {\n                print0(\".\");\n                x.getTableGroup().accept(this);\n            }\n        }\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowDbLockStatement x) {\n        print0(ucase ? \"SHOW DBLOCK\" : \"show dblock\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowHtcStatement x) {\n        print0(ucase ? \"SHOW HTC\" : \"show htc\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowStcStatement x) {\n        if (x.isHis()) {\n            print0(ucase ? \"SHOW STC HIS\" : \"show stc his\");\n        } else {\n            print0(ucase ? \"SHOW STC\" : \"show stc\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTriggersStatement x) {\n        print0(ucase ? \"SHOW TRIGGERS\" : \"show triggers\");\n\n        if (x.getDatabase() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getDatabase().accept(this);\n        }\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowRuleStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n\n        if (x.isFull()) {\n            print0(ucase ? \"FULL RULE\" : \"full rule\");\n        } else {\n            print0(ucase ? \"RULE\" : \"rule\");\n        }\n\n        if (x.isVersion()) {\n            print0(ucase ? \" VERSION\" : \" version\");\n        }\n\n        if (x.getName() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getName().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowRuleStatusStatement x) {\n        print0(ucase ? \"SHOW RULE\" : \"show rule\");\n\n        if (x.isFull()) {\n            print0(ucase ? \" FULL\" : \" full\");\n        } else if (x.isVersion()) {\n            print0(ucase ? \" VERSION\" : \" version\");\n        }\n\n        print0(ucase ? \" STATUS\" : \" status\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPhysicalProcesslistStatement x) {\n        print0(ucase ? \"SHOW\" : \"show\");\n\n        if (x.isFull()) {\n            print0(ucase ? \" FULL\" : \" full\");\n        }\n\n        print0(ucase ? \" PHYSICAL_PROCESSLIST\" : \" physical_processlist\");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRenameSequenceStatement x) {\n        print0(ucase ? \"RENAME SEQUENCE \" : \"rename sequence \");\n        x.getName().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCheckTableStatement x) {\n        print0(ucase ? \"CHECK TABLE \" : \"check table \");\n        printAndAccept(x.getTables(), \"，\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextCharFilterStatement x) {\n        print0(ucase ? \"CREATE FULLTEXT CHARFILTER \" : \"create fulltext charfilter \");\n        x.getName().accept(this);\n        println(\"(\");\n        print0(\"\\\"type\\\" = \" + x.getTypeName());\n        println(\",\");\n        printAndAccept(x.getOptions(), \",\");\n\n        println();\n        print0(\")\");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowFullTextStatement x) {\n        print0(ucase ? \"SHOW FULLTEXT \" : \"show fulltext \");\n        if (x.getType() == FullTextType.DICTIONARY) {\n            print0(ucase ? \"DICTIONARIES\" : \"dictionaries\");\n        } else {\n            print0(ucase ? x.getType().toString().toUpperCase() + \"S\" : x.getType().toString().toLowerCase() + \"s\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowCreateFullTextStatement x) {\n        print0(ucase ? \"SHOW CREATE FULLTEXT \" : \"show create fulltext \");\n        print0(ucase ? x.getType().toString().toUpperCase() : x.getType().toString().toLowerCase());\n        print0(\" \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlAlterFullTextStatement x) {\n        print0(ucase ? \"ALTER FULLTEXT \" : \"alter fulltext \");\n        print0(ucase ? x.getType().toString().toUpperCase() : x.getType().toString().toLowerCase());\n        print0(\" \");\n        x.getName().accept(this);\n        print0(ucase ? \" SET \" : \" set \");\n        x.getItem().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropClusteringKey x) {\n        print0(ucase ? \"DROP CLUSTERED KEY \" : \"drop clustered key \");\n        x.getKeyName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlDropFullTextStatement x) {\n        print0(ucase ? \"DROP FULLTEXT \" : \"drop fulltext \");\n        print0(ucase ? x.getType().toString().toUpperCase() : x.getType().toString().toLowerCase());\n        print0(\" \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextTokenizerStatement x) {\n        print0(ucase ? \"CREATE FULLTEXT TOKENIZER \" : \"create fulltext tokenizer \");\n        x.getName().accept(this);\n        println(\"(\");\n        print0(\"\\\"type\\\" = \" + x.getTypeName());\n        if (x.getUserDefinedDict() != null) {\n            println(\",\");\n            print(\"\\\"user_defined_dict\\\" = \" + x.getUserDefinedDict());\n        }\n        if (!x.getOptions().isEmpty()) {\n            println(\",\");\n            printAndAccept(x.getOptions(), \",\");\n        }\n        println();\n        print0(\")\");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextTokenFilterStatement x) {\n        print0(ucase ? \"CREATE FULLTEXT TOKENFILTER \" : \"create fulltext tokenfilter \");\n        x.getName().accept(this);\n        println(\"(\");\n        println(\"\\\"type\\\" = \" + x.getTypeName() + \",\");\n        printAndAccept(x.getOptions(), \",\");\n\n        println();\n        print0(\")\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextAnalyzerStatement x) {\n        print0(ucase ? \"CREATE FULLTEXT ANALYZER \" : \"create fulltext analyzer \");\n        x.getName().accept(this);\n        println(\"(\");\n        print0(ucase ? \"\\\"TOKENIZER\\\" = \" : \"\\\"tokenizer\\\" = \");\n        print0(x.getTokenizer());\n        println(\",\");\n\n        if (!x.getCharfilters().isEmpty()) {\n            print0(ucase ? \"\\\"CHARFILTER\\\" = [\" : \"\\\"charfilter\\\" = [\");\n            for (int i = 0; i < x.getCharfilters().size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n\n                print0(\"\\\"\" + x.getCharfilters().get(i) + \"\\\"\");\n            }\n            println(\"],\");\n        }\n        if (!x.getTokenizers().isEmpty()) {\n            print0(ucase ? \"\\\"TOKENFILTER\\\" = [\" : \"\\\"tokenfilter\\\" = [\");\n            for (int i = 0; i < x.getTokenizers().size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n\n                print0(\"\\\"\" + x.getTokenizers().get(i) + \"\\\"\");\n            }\n            print(']');\n        }\n        println();\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextDictionaryStatement x) {\n        print0(ucase ? \"CREATE FULLTEXT DICTIONARY \" : \"create fulltext dictionary \");\n        x.getName().accept(this);\n        println('(');\n        x.getColumn().accept(this);\n        println();\n        print(')');\n\n        if (x.getComment() != null) {\n            println();\n            print0(ucase ? \"COMMENT \" : \"comment \");\n            print0(x.getComment());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableAlterFullTextIndex x) {\n        print0(ucase ? \" ALTER INDEX \" : \" alter index \");\n        x.getIndexName().accept(this);\n        print0(ucase ? \" FULLTEXT \" : \" fulltext \");\n        if (x.getAnalyzerType() != null) {\n            String analyzerType = x.getAnalyzerType().toString();\n            print0(ucase ? analyzerType.toUpperCase() : analyzerType.toLowerCase());\n        }\n        print0(ucase ? \" ANALYZER = \" : \" analyzer = \");\n        x.getAnalyzerName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExtPartition x) {\n        print0(ucase ? \"EXTPARTITION (\" : \"extpartition (\");\n        incrementIndent();\n        println();\n        for (int i = 0; i < x.getItems().size(); i++) {\n            if (i != 0) {\n                println(\", \");\n            }\n            MySqlExtPartition.Item item = x.getItems().get(i);\n            item.accept(this);\n        }\n        decrementIndent();\n        println();\n        print(')');\n        return false;\n    }\n\n    public boolean visit(MySqlExtPartition.Item x) {\n        SQLName dbPartition = x.getDbPartition();\n        if (dbPartition != null) {\n            print0(ucase ? \"DBPARTITION \" : \"dbpartition \");\n            dbPartition.accept(this);\n\n            SQLExpr dbPartitionBy = x.getDbPartitionBy();\n            if (dbPartitionBy != null) {\n                print0(ucase ? \" BY \" : \" by \");\n            }\n            dbPartitionBy.accept(this);\n        }\n\n        SQLName tbPartition = x.getTbPartition();\n        if (tbPartition != null) {\n            if (dbPartition != null) {\n                print(' ');\n            }\n\n            print0(ucase ? \"TBPARTITION \" : \"tbpartition \");\n            tbPartition.accept(this);\n\n            SQLExpr tbPartitionBy = x.getTbPartitionBy();\n            if (tbPartitionBy != null) {\n                print0(ucase ? \" BY \" : \" by \");\n            }\n            tbPartitionBy.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTraceStatement x) {\n        print0(ucase ? \"SHOW TRACE\" : \"show trace\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowBroadcastsStatement x) {\n        print0(ucase ? \"SHOW BROADCASTS\" : \"show broadcasts\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDatasourcesStatement x) {\n        print0(ucase ? \"SHOW DATASOURCES\" : \"show datasources\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowNodeStatement x) {\n        print0(ucase ? \"SHOW NODE\" : \"show node\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowHelpStatement x) {\n        print0(ucase ? \"SHOW HELP\" : \"show help\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlFlashbackStatement x) {\n        print0(ucase ? \"FLASHBACK TABLE \" : \"flashback table \");\n        x.getName().accept(this);\n        print0(ucase ? \" TO BEFORE DROP\" : \" to before drop\");\n\n        final SQLName renameTo = x.getRenameTo();\n        if (renameTo != null) {\n            print0(ucase ? \" RENAME TO \" : \" rename to \");\n            renameTo.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowConfigStatement x) {\n        print0(ucase ? \"SHOW CONFIG \" : \"show config \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPlanCacheStatement x) {\n        print0(ucase ? \"SHOW PLANCACHE PLAN\" : \"show plancache plan\");\n        println();\n        x.getSelect().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDdlStatusStatement x) {\n        print0(ucase ? \"SHOW DDL STATUS\" : \"show ddl status\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDsStatement x) {\n        print0(ucase ? \"SHOW DS\" : \"show ds\");\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTopologyStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n\n        if (x.isFull()) {\n            print0(ucase ? \"FULL \" : \"full \");\n        }\n\n        print0(ucase ? \"TOPOLOGY FROM \" : \"topology from \");\n\n        print0(x.getName().getSimpleName());\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.getOrderBy() != null) {\n            print0(\" \");\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            print0(\" \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowVariantsStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n\n        if (x.isGlobal()) {\n            print0(ucase ? \"GLOBAL \" : \"global \");\n        }\n\n        if (x.isSession()) {\n            print0(ucase ? \"SESSION \" : \"session \");\n        }\n\n        print0(ucase ? \"VARIABLES\" : \"variables\");\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        print0(ucase ? \"ALTER \" : \"alter \");\n        if (x.isOnline()) {\n            print0(ucase ? \"ONLINE  \" : \"online \");\n        } else if (x.isOffline()) {\n            print0(ucase ? \"OFFLINE  \" : \"offline \");\n        }\n        if (x.isIgnore()) {\n            print0(ucase ? \"IGNORE \" : \"ignore \");\n        }\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        printTableSourceExpr(x.getName());\n\n        this.indentCount++;\n        if (x.getTableOptions().size() > 0) {\n            println();\n        }\n        this.indentCount--;\n        {\n            int i = 0;\n            for (SQLAssignItem item : x.getTableOptions()) {\n                SQLExpr key = item.getTarget();\n                if (i != 0) {\n                    print(' ');\n                }\n                final String keyStringCase = ucase ? key.toString().toUpperCase() : key.toString().toLowerCase();\n                print0(keyStringCase);\n                if (\"TABLESPACE\".equalsIgnoreCase(keyStringCase)) {\n                    print(' ');\n                } else {\n                    print0(\" = \");\n                }\n                item.getValue().accept(this);\n                i++;\n            }\n        }\n        if (x.getItems().size() > 0) {\n            if (x.getTableOptions().size() > 0) {\n                print(',');\n            }\n        }\n        this.indentCount++;\n        for (int i = 0; i < x.getItems().size(); ++i) {\n            SQLAlterTableItem item = x.getItems().get(i);\n            if (i != 0) {\n                print(',');\n            }\n            println();\n            item.accept(this);\n        }\n\n        if (x.isRemovePatiting()) {\n            println();\n            print0(ucase ? \"REMOVE PARTITIONING\" : \"remove partitioning\");\n        }\n\n        if (x.isUpgradePatiting()) {\n            println();\n            print0(ucase ? \"UPGRADE PARTITIONING\" : \"upgrade partitioning\");\n        }\n        this.indentCount--;\n       SQLPartitionBy partitionBy = x.getPartition();\n        if (partitionBy != null) {\n            println();\n            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n            partitionBy.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddColumn x) {\n        print0(ucase ? \"ADD COLUMN \" : \"add column \");\n\n        if (x.getColumns().size() > 1) {\n            print('(');\n        }\n        printAndAccept(x.getColumns(), \", \");\n        if (x.getFirstColumn() != null) {\n            print0(ucase ? \" FIRST \" : \" first \");\n            x.getFirstColumn().accept(this);\n        } else if (x.getAfterColumn() != null) {\n            print0(ucase ? \" AFTER \" : \" after \");\n            x.getAfterColumn().accept(this);\n        } else if (x.isFirst()) {\n            print0(ucase ? \" FIRST\" : \" first\");\n        }\n\n        if (x.getColumns().size() > 1) {\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRenameTableStatement.Item x) {\n        x.getName().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRenameTableStatement x) {\n        print0(ucase ? \"RENAME TABLE \" : \"rename table \");\n        printAndAccept(x.getItems(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUseIndexHint x) {\n        print0(ucase ? \"USE INDEX \" : \"use index \");\n        if (x.getOption() != null) {\n            print0(ucase ? \"FOR \" : \"for \");\n            print0(x.getOption().name);\n            print(' ');\n        }\n        print('(');\n        printAndAccept(x.getIndexList(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlIgnoreIndexHint x) {\n        print0(ucase ? \"IGNORE INDEX \" : \"ignore index \");\n        if (x.getOption() != null) {\n            print0(ucase ? \"FOR \" : \"for \");\n            print0(ucase ? x.getOption().name : x.getOption().nameLCase);\n            print(' ');\n        }\n        print('(');\n        printAndAccept(x.getIndexList(), \", \");\n        print(')');\n        return false;\n    }\n\n    public boolean visit(SQLExprTableSource x) {\n        printTableSourceExpr(x.getExpr());\n\n        final SQLTableSampling sampling = x.getSampling();\n        if (sampling != null) {\n            print(' ');\n            sampling.accept(this);\n        }\n\n        if (x.getPartitionSize() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printlnAndAccept(x.getPartitions(), \", \");\n            print(')');\n        }\n\n        String alias = x.getAlias();\n        List<SQLName> columns = x.getColumnsDirect();\n        if (alias != null) {\n            print(' ');\n            if (columns != null && columns.size() > 0) {\n                print0(ucase ? \" AS \" : \" as \");\n            }\n            print0(alias);\n        }\n\n        if (columns != null && columns.size() > 0) {\n            print(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        if (isPrettyFormat() && x.hasAfterComment()) {\n            print(' ');\n            printlnComment(x.getAfterCommentsDirect());\n        }\n\n        for (int i = 0; i < x.getHintsSize(); ++i) {\n            print(' ');\n            x.getHints().get(i).accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlLockTableStatement x) {\n        print0(ucase ? \"LOCK TABLES\" : \"lock tables\");\n        List<MySqlLockTableStatement.Item> items = x.getItems();\n        if (items.size() > 0) {\n            print(' ');\n            printAndAccept(items, \", \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlLockTableStatement.Item x) {\n        x.getTableSource().accept(this);\n        if (x.getLockType() != null) {\n            print(' ');\n            print0(x.getLockType().name);\n        }\n\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            print(' ');\n            printAndAccept(x.getHints(), \" \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUnlockTablesStatement x) {\n        print0(ucase ? \"UNLOCK TABLES\" : \"unlock tables\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlForceIndexHint x) {\n        print0(ucase ? \"FORCE INDEX \" : \"force index \");\n        if (x.getOption() != null) {\n            print0(ucase ? \"FOR \" : \"for \");\n            print0(x.getOption().name);\n            print(' ');\n        }\n        print('(');\n        printAndAccept(x.getIndexList(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableChangeColumn x) {\n        print0(ucase ? \"CHANGE COLUMN \" : \"change column \");\n        x.getColumnName().accept(this);\n        print(' ');\n        x.getNewColumnDefinition().accept(this);\n        if (x.getFirstColumn() != null) {\n            print0(ucase ? \" FIRST \" : \" first \");\n            x.getFirstColumn().accept(this);\n        } else if (x.getAfterColumn() != null) {\n            print0(ucase ? \" AFTER \" : \" after \");\n            x.getAfterColumn().accept(this);\n        } else if (x.isFirst()) {\n            print0(ucase ? \" FIRST\" : \" first\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableModifyColumn x) {\n        print0(ucase ? \"MODIFY COLUMN \" : \"modify column \");\n        x.getNewColumnDefinition().accept(this);\n        if (x.getFirstColumn() != null) {\n            print0(ucase ? \" FIRST \" : \" first \");\n            x.getFirstColumn().accept(this);\n        } else if (x.getAfterColumn() != null) {\n            print0(ucase ? \" AFTER \" : \" after \");\n            x.getAfterColumn().accept(this);\n        } else if (x.isFirst()) {\n            print0(ucase ? \" FIRST\" : \" first\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableOption x) {\n        print0(x.getName());\n        print0(\" = \");\n        print0(x.getValue().toString());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterDatabaseSetOption x) {\n        print0(ucase ? \"SET \" : \"set \");\n        printAndAccept(x.getOptions(), \", \");\n\n        SQLName on = x.getOn();\n        if (on != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            on.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterDatabaseKillJob x) {\n        print0(ucase ? \"KILL \" : \"kill \");\n        x.getJobType().accept(this);\n        print0(\" \");\n        x.getJobId().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlHelpStatement x) {\n        print0(ucase ? \"HELP \" : \"help \");\n        x.getContent().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCharExpr x) {\n        if (this.parameterized) {\n            print('?');\n            incrementReplaceCunt();\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            return false;\n        }\n        if (x.isParenthesized()) {\n            print(\"(\");\n        }\n        String charset = x.getCharset();\n        String collate = x.getCollate();\n        String text = x.getText();\n\n        if (charset != null) {\n            print(charset);\n\n            long charsetHashCode = FnvHash.hashCode64(charset);\n            if (charsetHashCode == FnvHash.Constants._UCS2 || charsetHashCode == FnvHash.Constants._UTF16) {\n                print(\" x'\");\n            } else {\n                print(\" '\");\n            }\n            print(text);\n            print('\\'');\n        } else {\n            print('\\'');\n            print(text);\n            print('\\'');\n        }\n\n        if (collate != null) {\n            print(\" COLLATE \");\n            print(collate);\n        }\n        if (x.isParenthesized()) {\n            print(\")\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUnique x) {\n        visit(x.getIndexDefinition());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlForeignKey x) {\n        if (x.isHasConstraint()) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            if (x.getName() != null) {\n                x.getName().accept(this);\n                print(' ');\n            }\n        }\n\n        print0(ucase ? \"FOREIGN KEY\" : \"foreign key\");\n\n        if (x.getIndexName() != null) {\n            print(' ');\n            x.getIndexName().accept(this);\n        }\n\n        print0(\" (\");\n        printAndAccept(x.getReferencingColumns(), \", \");\n        print(')');\n\n        print0(ucase ? \" REFERENCES \" : \" references \");\n        x.getReferencedTableName().accept(this);\n\n        print0(\" (\");\n        printAndAccept(x.getReferencedColumns(), \", \");\n        print(')');\n\n        SQLForeignKeyImpl.Match match = x.getReferenceMatch();\n        if (match != null) {\n            print0(ucase ? \" MATCH \" : \" match \");\n            print0(ucase ? match.name : match.nameLCase);\n        }\n\n        if (x.getOnDelete() != null) {\n            print0(ucase ? \" ON DELETE \" : \" on delete \");\n            print0(ucase ? x.getOnDelete().name : x.getOnDelete().nameLCase);\n        }\n\n        if (x.getOnUpdate() != null) {\n            print0(ucase ? \" ON UPDATE \" : \" on update \");\n            print0(ucase ? x.getOnUpdate().name : x.getOnUpdate().nameLCase);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableDiscardTablespace x) {\n        print0(ucase ? \"DISCARD TABLESPACE\" : \"discard tablespace\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateExternalCatalogStatement x) {\n        print0(ucase ? \"CREATE EXTERNAL CATALOG \" : \"create external catalog \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        x.getName().accept(this);\n\n        print0(ucase ? \" PROPERTIES (\" : \" properties (\");\n\n        for (Map.Entry<SQLName, SQLName> entry : x.getProperties().entrySet()) {\n            println();\n            entry.getKey().accept(this);\n            print0(\"=\");\n            entry.getValue().accept(this);\n        }\n        print0(\")\");\n\n        printComment(x.getComment());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableImportTablespace x) {\n        print0(ucase ? \"IMPORT TABLESPACE\" : \"import tablespace\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAssignItem x) {\n        String tagetString = x.getTarget().toString();\n\n        boolean mysqlSpecial = false;\n\n        if (DbType.mysql == dbType) {\n            mysqlSpecial = \"NAMES\".equalsIgnoreCase(tagetString)\n                    || \"CHARACTER SET\".equalsIgnoreCase(tagetString)\n                    || \"CHARSET\".equalsIgnoreCase(tagetString);\n        }\n\n        if (!mysqlSpecial) {\n            x.getTarget().accept(this);\n            print0(\" = \");\n        } else {\n            print0(ucase ? tagetString.toUpperCase() : tagetString.toLowerCase());\n            print(' ');\n        }\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(TableSpaceOption x) {\n        x.getName().accept(this);\n\n        if (x.getStorage() != null) {\n            print(ucase ? \" STORAGE \" : \" storage \");\n            x.getStorage().accept(this);\n        }\n        return false;\n    }\n\n    protected void visitAggregateRest(SQLAggregateExpr x) {\n        boolean withGroup = x.isWithinGroup();\n        if (withGroup) {\n            print0(ucase ? \") WITHIN GROUP (\" : \") within group (\");\n        }\n        {\n            SQLOrderBy value = x.getOrderBy();\n            if (value != null) {\n                print(' ');\n                ((SQLObject) value).accept(this);\n            }\n        }\n        {\n            Object value = x.getAttribute(\"SEPARATOR\");\n            if (value != null) {\n                print0(ucase ? \" SEPARATOR \" : \" separator \");\n                ((SQLObject) value).accept(this);\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(MySqlAnalyzeStatement x) {\n        print0(ucase ? \"ANALYZE \" : \"analyze \");\n        if (x.isNoWriteToBinlog()) {\n            print0(ucase ? \"NO_WRITE_TO_BINLOG \" : \"no_write_to_binlog \");\n        }\n\n        if (x.isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        if (!x.getAdbColumns().isEmpty()) {\n            print0(ucase ? \"COLUMN \" : \"column \");\n        } else if (!x.getAdbColumnsGroup().isEmpty()) {\n            print0(ucase ? \"COLUMNS GROUP \" : \"columns group \");\n        } else if (x.getAdbSchema() != null) {\n            print0(ucase ? \"DATABASE \" : \"database \");\n            x.getAdbSchema().accept(this);\n        } else if (!x.getTableSources().isEmpty()) {\n            print0(ucase ? \"TABLE \" : \"table \");\n        }\n\n        printAndAccept(x.getTableSources(), \", \");\n\n        if (!x.getAdbColumns().isEmpty()) {\n            print0(\"(\");\n            printAndAccept(x.getAdbColumns(), \",\");\n            print0(\")\");\n            if (x.getAdbWhere() != null) {\n                println();\n                print0(ucase ? \" WHERE \" : \" WHERE \");\n                printExpr(x.getAdbWhere());\n            }\n        } else if (!x.getAdbColumnsGroup().isEmpty()) {\n            print0(\"(\");\n            printAndAccept(x.getAdbColumnsGroup(), \",\");\n            print0(\")\");\n            if (x.getAdbWhere() != null) {\n                println();\n                print0(ucase ? \" WHERE \" : \" WHERE \");\n                printExpr(x.getAdbWhere());\n            }\n        } else if (!x.getTableSources().isEmpty()) {\n            if (x.getAdbWhere() != null) {\n                println();\n                print0(ucase ? \" WHERE \" : \" WHERE \");\n                printExpr(x.getAdbWhere());\n            }\n        }\n\n        SQLPartitionRef partition = x.getPartition();\n        if (partition != null) {\n            print(' ');\n            partition.accept(this);\n        }\n\n        if (x.isComputeStatistics()) {\n            print0(ucase ? \" COMPUTE STATISTICS\" : \" compute statistics\");\n        }\n\n        if (x.isForColums()) {\n            print0(ucase ? \" FOR COLUMNS\" : \" for columns\");\n        }\n\n        if (x.isCacheMetadata()) {\n            print0(ucase ? \" CACHE METADATA\" : \" cache metadata\");\n        }\n\n        if (x.isNoscan()) {\n            print0(ucase ? \" NOSCAN\" : \" noscan\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlOptimizeStatement x) {\n        print0(ucase ? \"OPTIMIZE \" : \"optimize \");\n        if (x.isNoWriteToBinlog()) {\n            print0(ucase ? \"NO_WRITE_TO_BINLOG \" : \"No_write_to_binlog \");\n        }\n\n        if (x.isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        printAndAccept(x.getTableSources(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterUserStatement x) {\n        print0(ucase ? \"ALTER USER\" : \"alter user\");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \" IF EXISTS\" : \" if exists\");\n        }\n\n        for (int i = 0; i < x.getAlterUsers().size(); i++) {\n            if (i != 0) {\n                print(',');\n            }\n\n            MySqlAlterUserStatement.AlterUser alterUser = x.getAlterUsers().get(i);\n            print(' ');\n            alterUser.getUser().accept(this);\n\n            if (alterUser.getAuthOption() != null) {\n                print(\" IDENTIFIED BY \");\n                SQLCharExpr authString = alterUser.getAuthOption().getAuthString();\n                authString.accept(this);\n            }\n            if (alterUser.getAccountLockOption() != null) {\n                print0(ucase ? \" ACCOUNT \" : \" account \");\n                print0(ucase ? alterUser.getAccountLockOption().toUpperCase() : alterUser.getAccountLockOption().toLowerCase());\n            }\n        }\n\n        MySqlAlterUserStatement.PasswordOption passwordOption = x.getPasswordOption();\n        if (passwordOption != null) {\n            switch (passwordOption.getExpire()) {\n                case PASSWORD_EXPIRE:\n                    print0(ucase ? \" PASSWORD EXPIRE\" : \" password expire\");\n                    break;\n                case PASSWORD_EXPIRE_DEFAULT:\n                    print0(ucase ? \" PASSWORD EXPIRE DEFAULT\" : \" password expire default\");\n                    break;\n                case PASSWORD_EXPIRE_NEVER:\n                    print0(ucase ? \" PASSWORD EXPIRE NEVER\" : \" password expire never\");\n                    break;\n                case PASSWORD_EXPIRE_INTERVAL:\n                    print0(ucase ? \" PASSWORD EXPIRE INTERVAL \" : \" password expire interval \");\n                    passwordOption.getIntervalDays().accept(this);\n                    print0(ucase ? \" DAY\" : \" day\");\n                    break;\n                default:\n                    throw new RuntimeException(\"invalid password option:\" + passwordOption);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSetStatement x) {\n        boolean printSet = Boolean.TRUE.equals(x.getAttribute(\"parser.set\")) || DbType.oracle != dbType;\n        if (printSet) {\n            print0(ucase ? \"SET \" : \"set \");\n        }\n        if (x.getMaridbSetForStatement() != null) {\n            print0(ucase ? \"STATEMENT \" : \"statement \");\n        }\n        SQLSetStatement.Option option = x.getOption();\n        if (option != null) {\n            print(option.name());\n            print(' ');\n        }\n\n        if (option == SQLSetStatement.Option.PASSWORD) {\n            print0(\"FOR \");\n        }\n\n        printAndAccept(x.getItems(), \", \");\n\n        if (x.getMaridbSetForStatement() != null) {\n            print0(ucase ? \" FOR \" : \" for \");\n            x.getMaridbSetForStatement().accept(this);\n        }\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            print(' ');\n            printAndAccept(x.getHints(), \" \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlHintStatement x) {\n        List<SQLCommentHint> hints = x.getHints();\n\n        for (SQLCommentHint hint : hints) {\n            hint.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlOrderingExpr x) {\n        x.getExpr().accept(this);\n        if (x.getType() != null) {\n            print(' ');\n            print0(ucase ? x.getType().name : x.getType().nameLCase);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBlockStatement x) {\n        SQLObject parent = x.getParent();\n        String labelName = x.getLabelName();\n\n        if (labelName != null && !labelName.equals(\"\")) {\n            print0(labelName);\n            print0(\": \");\n        }\n\n        List<SQLParameter> parameters = x.getParameters();\n        if (!parameters.isEmpty()) {\n            this.indentCount++;\n            if (parent instanceof SQLCreateProcedureStatement) {\n                printIndent();\n            }\n            if (!(parent instanceof SQLCreateProcedureStatement)) {\n                print0(ucase ? \"DECLARE\" : \"declare\");\n                println();\n            }\n\n            for (int i = 0, size = parameters.size(); i < size; ++i) {\n                if (i != 0) {\n                    println();\n                }\n                SQLParameter param = parameters.get(i);\n                visit(param);\n                print(';');\n            }\n\n            this.indentCount--;\n            println();\n        }\n\n        print0(ucase ? \"BEGIN\" : \"begin\");\n        if (!x.isEndOfCommit()) {\n            this.indentCount++;\n        } else {\n            print(';');\n        }\n        println();\n        List<SQLStatement> statementList = x.getStatementList();\n        for (int i = 0, size = statementList.size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n            SQLStatement stmt = statementList.get(i);\n            stmt.accept(this);\n        }\n\n        if (!x.isEndOfCommit()) {\n            this.indentCount--;\n            println();\n            print0(ucase ? \"END\" : \"end\");\n            if (labelName != null && !labelName.equals(\"\")) {\n                print(' ');\n                print0(labelName);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement x) {\n        print0(ucase ? \"IF \" : \"if \");\n        x.getCondition().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n        println();\n        List<SQLStatement> statements = x.getStatements();\n        for (int i = 0, size = statements.size(); i < size; ++i) {\n            SQLStatement item = statements.get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        for (SQLIfStatement.ElseIf iterable_element : x.getElseIfList()) {\n            iterable_element.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            x.getElseItem().accept(this);\n        }\n\n        print0(ucase ? \"END IF\" : \"end if\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.ElseIf x) {\n        print0(ucase ? \"ELSEIF \" : \"elseif \");\n        x.getCondition().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.Else x) {\n        print0(ucase ? \"ELSE \" : \"else \");\n        this.indentCount++;\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCaseStatement x) {\n        print0(ucase ? \"CASE \" : \"case \");\n        if (x.getCondition() != null) {\n            x.getCondition().accept(this);\n        }\n        println();\n        for (int i = 0; i < x.getWhenList().size(); i++) {\n            x.getWhenList().get(i).accept(this);\n        }\n        if (x.getElseItem() != null) {\n            x.getElseItem().accept(this);\n        }\n        print0(ucase ? \"END CASE\" : \"end case\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDeclareStatement x) {\n        print0(ucase ? \"DECLARE \" : \"declare \");\n        printAndAccept(x.getVarList(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSelectIntoStatement x) {\n        x.getSelect().accept(this);\n        print0(ucase ? \" INTO \" : \" into \");\n        for (int i = 0; i < x.getVarList().size(); i++) {\n            x.getVarList().get(i).accept(this);\n            if (i != x.getVarList().size() - 1) {\n                print0(\", \");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlWhenStatement x) {\n        print0(ucase ? \"WHEN \" : \"when \");\n        x.getCondition().accept(this);\n        print0(\" THEN\");\n        println();\n        for (int i = 0; i < x.getStatements().size(); i++) {\n            x.getStatements().get(i).accept(this);\n            if (i != x.getStatements().size() - 1) {\n                println();\n            }\n        }\n        println();\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLLoopStatement x) {\n        if (x.getLabelName() != null && !x.getLabelName().equals(\"\")) {\n            print0(x.getLabelName());\n            print0(\": \");\n        }\n\n        print0(ucase ? \"LOOP \" : \"loop \");\n        this.indentCount++;\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END LOOP\" : \"end loop\");\n        if (x.getLabelName() != null && !x.getLabelName().equals(\"\")) {\n            print0(\" \");\n            print0(x.getLabelName());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLWhileStatement x) {\n        String label = x.getLabelName();\n\n        if (label != null && !label.isEmpty()) {\n            print0(x.getLabelName());\n            print0(\": \");\n        }\n        print0(ucase ? \"WHILE \" : \"while \");\n        x.getCondition().accept(this);\n        print0(ucase ? \" DO\" : \" do\");\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        println();\n        print0(ucase ? \"END WHILE\" : \"end while\");\n        if (label != null && !label.isEmpty()) {\n            print(' ');\n            print0(label);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlLeaveStatement x) {\n        print0(ucase ? \"LEAVE \" : \"leave \");\n        print0(x.getLabelName());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlIterateStatement x) {\n        print0(ucase ? \"ITERATE \" : \"iterate \");\n        print0(x.getLabelName());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRepeatStatement x) {\n        // TODO Auto-generated method stub\n        if (x.getLabelName() != null && !x.getLabelName().equals(\"\")) {\n            print0(x.getLabelName());\n            print0(\": \");\n        }\n\n        print0(ucase ? \"REPEAT \" : \"repeat \");\n        this.indentCount++;\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        print0(ucase ? \"UNTIL \" : \"until \");\n        x.getCondition().accept(this);\n        println();\n        print0(ucase ? \"END REPEAT\" : \"end repeat\");\n        if (x.getLabelName() != null && !x.getLabelName().equals(\"\")) {\n            print(' ');\n            print0(x.getLabelName());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCursorDeclareStatement x) {\n        print0(ucase ? \"DECLARE \" : \"declare \");\n        printExpr(x.getCursorName(), parameterized);\n        print0(ucase ? \" CURSOR FOR\" : \" cursor for\");\n        this.indentCount++;\n        println();\n        x.getSelect().accept(this);\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUpdateTableSource x) {\n        MySqlUpdateStatement update = x.getUpdate();\n        if (update != null) {\n            update.accept0(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableAlterColumn x) {\n        print0(ucase ? \"ALTER COLUMN \" : \"alter column \");\n        x.getColumn().accept(this);\n        if (x.getDefaultExpr() != null) {\n            print0(ucase ? \" SET DEFAULT \" : \" set default \");\n            x.getDefaultExpr().accept(this);\n        } else if (x.isDropDefault()) {\n            print0(ucase ? \" DROP DEFAULT\" : \" drop default\");\n        } else if (x.getVisibleType() != null) {\n            print0(ucase ? \" SET \" : \" set \");\n            print0(ucase ? x.getVisibleType().toUpperCase() : x.getVisibleType().toLowerCase());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableForce x) {\n        print0(ucase ? \"FORCE\" : \"force\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableLock x) {\n        print0(ucase ? \"LOCK = \" : \"lock = \");\n        printExpr(x.getLockType());\n        return false;\n    }\n\n    public boolean visit(MySqlAlterTableAlgorithm x) {\n        print0(ucase ? \"ALGORITHM = \" : \"algorithm = \");\n        printExpr(x.getAlgorithmType());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableOrderBy x) {\n        print0(ucase ? \"ORDER BY \" : \"order by \");\n        printAndAccept(x.getColumns(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableValidation x) {\n        if (x.isWithValidation()) {\n            print0(ucase ? \"WITH VALIDATION\" : \"with validation\");\n        } else {\n            print0(ucase ? \"WITHOUT VALIDATION\" : \"without validation\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSubPartitionByKey x) {\n        if (x.isLinear()) {\n            print0(ucase ? \"SUBPARTITION BY LINEAR KEY (\" : \"subpartition by linear key (\");\n        } else {\n            print0(ucase ? \"SUBPARTITION BY KEY (\" : \"subpartition by key (\");\n        }\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        if (x.getSubPartitionsCount() != null) {\n            print0(ucase ? \" SUBPARTITIONS \" : \" subpartitions \");\n            x.getSubPartitionsCount().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSubPartitionByValue x) {\n        print0(ucase ? \"SUBPARTITION BY VALUE (\" : \"subpartition by value (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        if (x.getLifecycle() != null) {\n            print0(ucase ? \" LIFECYCLE \" : \" lifecycle \");\n            x.getLifecycle().accept(this);\n        }\n\n        if (x.getSubPartitionsCount() != null) {\n            if ((Boolean) x.getAttribute(\"adb.partitons\")) {\n                print0(ucase ? \" PARTITIONS \" : \" partitions \");\n            } else {\n                print0(ucase ? \" SUBPARTITIONS \" : \" subpartitions \");\n            }\n            x.getSubPartitionsCount().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTablePartitionCount x) {\n        print0(ucase ? \"PARTITIONS \" : \"partitons \");\n        x.getCount().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableBlockSize x) {\n        print0(ucase ? \"BLOCK_SIZE \" : \"block_size \");\n        x.getSize().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableCompression x) {\n        print0(ucase ? \"COMPRESSION = \" : \"compression = \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSubPartitionByList x) {\n        print0(ucase ? \"SUBPARTITION BY LIST \" : \"subpartition by list \");\n        if (x.getKeys().size() > 0) {\n            if (Boolean.TRUE.equals(x.getAttribute(\"ads.subPartitionList\"))) {\n                print0(ucase ? \"KEY (\" : \"key (\");\n            } else {\n                print('(');\n            }\n\n            printAndAccept(x.getKeys(), \",\");\n            print0(\") \");\n        } else {\n            if (x.getColumns().size() == 1 && Boolean.TRUE.equals(x.getAttribute(\"ads.subPartitionList\"))) {\n                print('(');\n            } else {\n                print0(ucase ? \"COLUMNS (\" : \"columns (\");\n            }\n            printAndAccept(x.getColumns(), \", \");\n            print(\")\");\n        }\n\n        if (!x.getOptions().isEmpty()) {\n            println();\n            print0(ucase ? \"SUBPARTITION OPTIONS (\" : \"subpartition options (\");\n            printAndAccept(x.getOptions(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDeclareHandlerStatement x) {\n        String handleType = x.getHandleType().name();\n\n        print0(ucase ? \"DECLARE \" : \"declare \");\n        print0(ucase ? handleType : handleType.toLowerCase());\n        print0(ucase ? \" HANDLER FOR \" : \" handler for \");\n        for (int i = 0; i < x.getConditionValues().size(); i++) {\n            ConditionValue cv = x.getConditionValues().get(i);\n            if (cv.getType() == ConditionType.SQLSTATE) {\n                print0(ucase ? \" SQLSTATE \" : \" sqlstate \");\n                print0(cv.getValue());\n            } else if (cv.getType() == ConditionType.MYSQL_ERROR_CODE) {\n                print0(cv.getValue());\n            } else if (cv.getType() == ConditionType.SELF) {\n                print0(cv.getValue());\n            } else if (cv.getType() == ConditionType.SYSTEM) {\n                print0(ucase ? cv.getValue().toUpperCase() : cv.getValue().toLowerCase());\n            }\n\n            if (i != x.getConditionValues().size() - 1) {\n                print0(\", \");\n            }\n\n        }\n        this.indentCount++;\n        println();\n        x.getSpStatement().accept(this);\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDeclareConditionStatement x) {\n        print0(ucase ? \"DECLARE \" : \"declare \");\n        print0(x.getConditionName());\n        print0(ucase ? \" CONDITION FOR \" : \" condition for \");\n\n        if (x.getConditionValue().getType() == ConditionType.SQLSTATE) {\n            print0(ucase ? \"SQLSTATE \" : \"sqlstate \");\n            print0(x.getConditionValue().getValue());\n        } else {\n            print0(x.getConditionValue().getValue());\n        }\n\n        println();\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropColumnItem x) {\n        for (int i = 0; i < x.getColumns().size(); ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n\n            SQLName columnn = x.getColumns().get(i);\n\n            print0(ucase ? \"DROP COLUMN \" : \"drop column \");\n            columnn.accept(this);\n\n            if (x.isCascade()) {\n                print0(ucase ? \" CASCADE\" : \" cascade\");\n            }\n        }\n        return false;\n    }\n\n    /**\n     * visit procedure create node\n     */\n    @Override\n    public boolean visit(SQLCreateProcedureStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE PROCEDURE \" : \"create or replace procedure \");\n        } else {\n            print0(ucase ? \"CREATE PROCEDURE \" : \"create procedure \");\n        }\n        x.getName().accept(this);\n\n        int paramSize = x.getParameters().size();\n\n        print0(\" (\");\n        if (paramSize > 0) {\n            this.indentCount++;\n            println();\n\n            for (int i = 0; i < paramSize; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                    println();\n                }\n                SQLParameter param = x.getParameters().get(i);\n                param.accept(this);\n            }\n\n            this.indentCount--;\n            println();\n        }\n        print(')');\n\n        if (x.getComment() != null) {\n            println();\n            print(ucase ? \"COMMENT \" : \"comment \");\n            x.getComment().accept(this);\n        }\n        if (x.isDeterministic()) {\n            println();\n            print(ucase ? \"DETERMINISTIC\" : \"deterministic\");\n        }\n\n        if (x.isContainsSql()) {\n            println();\n            print0(ucase ? \"CONTAINS SQL\" : \"contains sql\");\n        }\n\n        if (x.isLanguageSql()) {\n            println();\n            print0(ucase ? \"LANGUAGE SQL\" : \"language sql\");\n        }\n\n        if (x.isNoSql()) {\n            println();\n            print(ucase ? \"NO SQL\" : \"no sql\");\n        }\n\n        if (x.isModifiesSqlData()) {\n            println();\n            print(ucase ? \"MODIFIES SQL DATA\" : \"modifies sql data\");\n        }\n\n        SQLName authid = x.getAuthid();\n        if (authid != null) {\n            println();\n            print(ucase ? \"SQL SECURITY \" : \"sql security \");\n            authid.accept(this);\n        }\n\n        println();\n        x.getBlock().accept(this);\n        return false;\n    }\n\n    protected void printCreateFunctionBody(SQLCreateFunctionStatement x) {\n        printCreateFunctionReturns(x);\n\n        String comment = x.getComment();\n        if (comment != null) {\n            print(ucase ? \" COMMENT \" : \" comment \");\n            print(ucase ? comment.toUpperCase() : comment.toLowerCase());\n        }\n\n        if (x.isDeterministic()) {\n            print(ucase ? \" DETERMINISTIC\" : \" deterministic\");\n        }\n\n        String language = x.getLanguage();\n        if (language != null) {\n            print(ucase ? \" LANGUAGE \" : \" language \");\n            print(ucase ? language.toUpperCase() : language.toLowerCase());\n        }\n\n        SQLStatement block = x.getBlock();\n\n        println();\n\n        block.accept(this);\n    }\n\n    protected void printCreateFunctionReturns(SQLCreateFunctionStatement x) {\n        println();\n        print(ucase ? \"RETURNS \" : \"returns \");\n        x.getReturnDataType().accept(this);\n    }\n\n    @Override\n    public boolean visit(SQLCommentStatement x) {\n        SQLCommentStatement.Type type = x.getType();\n\n        SQLExprTableSource on = x.getOn();\n        if (type == SQLCommentStatement.Type.TABLE) {\n            print0(ucase ? \"ALTER TABLE \" : \"alter table \");\n            on.accept(this);\n            print0(ucase ? \" COMMENT = \" : \" comment = \");\n            x.getComment().accept(this);\n        } else {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) on.getExpr();\n\n            SQLExpr table = propertyExpr.getOwner();\n            String column = propertyExpr.getName();\n\n            print0(ucase ? \"ALTER TABLE \" : \"alter table \");\n            printTableSourceExpr(table);\n            print0(ucase ? \" MODIFY COLUMN \" : \" modify column \");\n            print(column);\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            x.getComment().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlFlushStatement x) {\n        print0(ucase ? \"FLUSH\" : \"flush\");\n\n        if (x.isNoWriteToBinlog()) {\n            print0(ucase ? \" NO_WRITE_TO_BINLOG\" : \" no_write_to_binlog\");\n        } else if (x.isLocal()) {\n            print0(ucase ? \" LOCAL\" : \" local\");\n        }\n\n        if (x.isBinaryLogs()) {\n            print0(ucase ? \" BINARY LOGS\" : \" binary logs\");\n        }\n        if (x.isDesKeyFile()) {\n            print0(ucase ? \" DES_KEY_FILE\" : \" des_key_file\");\n        }\n        if (x.isEngineLogs()) {\n            print0(ucase ? \" ENGINE LOGS\" : \" engine logs\");\n        }\n        if (x.isErrorLogs()) {\n            print0(ucase ? \" ERROR LOGS\" : \" error logs\");\n        }\n        if (x.isGeneralLogs()) {\n            print0(ucase ? \" GENERAL LOGS\" : \" general logs\");\n        }\n        if (x.isHots()) {\n            print0(ucase ? \" HOSTS\" : \" hosts\");\n        }\n        if (x.isLogs()) {\n            print0(ucase ? \" LOGS\" : \" logs\");\n        }\n        if (x.isPrivileges()) {\n            print0(ucase ? \" PRIVILEGES\" : \" privileges\");\n        }\n        if (x.isOptimizerCosts()) {\n            print0(ucase ? \" OPTIMIZER_COSTS\" : \" optimizer_costs\");\n        }\n        if (x.isQueryCache()) {\n            print0(ucase ? \" QUERY CACHE\" : \" query cache\");\n        }\n        if (x.isRelayLogs()) {\n            print0(ucase ? \" RELAY LOGS\" : \" relay logs\");\n            SQLExpr channel = x.getRelayLogsForChannel();\n            if (channel != null) {\n                print(' ');\n                channel.accept(this);\n            }\n        }\n        if (x.isSlowLogs()) {\n            print0(ucase ? \" SLOW LOGS\" : \" slow logs\");\n        }\n        if (x.isStatus()) {\n            print0(ucase ? \" STATUS\" : \" status\");\n        }\n        if (x.isUserResources()) {\n            print0(ucase ? \" USER_RESOURCES\" : \" user_resources\");\n        }\n\n        if (x.isTableOption()) {\n            print0(ucase ? \" TABLES\" : \" tables\");\n\n            List<SQLExprTableSource> tables = x.getTables();\n            if (tables != null && tables.size() > 0) {\n                print(' ');\n                printAndAccept(tables, \", \");\n            }\n\n            if (x.isWithReadLock()) {\n                print0(ucase ? \" WITH READ LOCK\" : \" with read lock\");\n            }\n\n            if (x.isForExport()) {\n                print0(ucase ? \" FOR EXPORT\" : \" for export\");\n            }\n\n            if (x.getVersion() != null) {\n                print0(ucase ? \" VERSION = \" : \" version = \");\n                x.getVersion().accept(this);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlEventSchedule x) {\n        int cnt = 0;\n        if (x.getAt() != null) {\n            print0(ucase ? \"AT \" : \"at \");\n            printExpr(x.getAt(), parameterized);\n\n            cnt++;\n        }\n\n        if (x.getEvery() != null) {\n            print0(ucase ? \"EVERY \" : \"every \");\n            SQLIntervalExpr interval = (SQLIntervalExpr) x.getEvery();\n            printExpr(interval.getValue(), parameterized);\n            print(' ');\n            print(interval.getUnit().name());\n\n            cnt++;\n        }\n\n        if (x.getStarts() != null) {\n            if (cnt > 0) {\n                print(' ');\n            }\n\n            print0(ucase ? \"STARTS \" : \"starts \");\n            printExpr(x.getStarts(), parameterized);\n\n            cnt++;\n        }\n\n        if (x.getEnds() != null) {\n            if (cnt > 0) {\n                print(' ');\n            }\n            print0(ucase ? \"ENDS \" : \"ends \");\n            printExpr(x.getEnds(), parameterized);\n\n            cnt++;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateEventStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        SQLName definer = x.getDefiner();\n        if (definer != null) {\n            print0(ucase ? \"DEFINER = \" : \"definer = \");\n            definer.accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"EVENT \" : \"event \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printExpr(x.getName(), parameterized);\n\n        MySqlEventSchedule schedule = x.getSchedule();\n        print0(ucase ? \" ON SCHEDULE \" : \" on schedule \");\n        schedule.accept(this);\n\n        Boolean enable = x.getEnable();\n        if (enable != null) {\n            if (enable) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            } else {\n                print0(ucase ? \" DISABLE\" : \" disable\");\n                if (x.isDisableOnSlave()) {\n                    print0(ucase ? \" ON SLAVE\" : \" on slave\");\n                }\n            }\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        println();\n        SQLStatement body = x.getEventBody();\n        if (!(body instanceof SQLExprStatement)) {\n            print0(ucase ? \"DO\" : \"do\");\n            println();\n        }\n        body.accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateAddLogFileGroupStatement x) {\n        print0(ucase ? \"CREATE LOGFILE GROUP \" : \"create logfile group \");\n        x.getName().accept(this);\n        print(' ');\n        print0(ucase ? \"ADD UNDOFILE \" : \"add undofile \");\n        printExpr(x.getAddUndoFile(), false);\n\n        SQLExpr initialSize = x.getInitialSize();\n        if (initialSize != null) {\n            print0(ucase ? \" INITIAL_SIZE \" : \" initial_size \");\n            printExpr(initialSize, false);\n        }\n\n        SQLExpr undoBufferSize = x.getUndoBufferSize();\n        if (undoBufferSize != null) {\n            print0(ucase ? \" UNDO_BUFFER_SIZE \" : \" undo_buffer_size \");\n            printExpr(undoBufferSize, false);\n        }\n\n        SQLExpr redoBufferSize = x.getRedoBufferSize();\n        if (redoBufferSize != null) {\n            print0(ucase ? \" REDO_BUFFER_SIZE \" : \" redo_buffer_size \");\n            printExpr(redoBufferSize, false);\n        }\n\n        SQLExpr nodeGroup = x.getNodeGroup();\n        if (nodeGroup != null) {\n            print0(ucase ? \" NODEGROUP \" : \" nodegroup \");\n            printExpr(nodeGroup, false);\n        }\n\n        if (x.isWait()) {\n            print0(ucase ? \" WAIT\" : \" wait\");\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            printExpr(comment, parameterized);\n        }\n\n        SQLExpr engine = x.getEngine();\n        if (engine != null) {\n            print0(ucase ? \" ENGINE \" : \" engine \");\n            printExpr(engine, parameterized);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateServerStatement x) {\n        print0(ucase ? \"CREATE SERVER \" : \"create server \");\n        x.getName().accept(this);\n        print0(ucase ? \" FOREIGN DATA WRAPPER \" : \" foreign data wrapper \");\n        printExpr(x.getForeignDataWrapper(), parameterized);\n\n        print(\" OPTIONS(\");\n        int cnt = 0;\n        SQLExpr host = x.getHost();\n        if (host != null) {\n            print0(ucase ? \"HOST \" : \"host \");\n            printExpr(host, parameterized);\n            cnt++;\n        }\n\n        SQLExpr database = x.getDatabase();\n        if (database != null) {\n            if (cnt++ > 0) {\n                print(\", \");\n            }\n            print0(ucase ? \"DATABASE \" : \"database \");\n            printExpr(database, parameterized);\n        }\n\n        SQLExpr user = x.getUser();\n        if (user != null) {\n            if (cnt++ > 0) {\n                print(\", \");\n            }\n            print0(ucase ? \"USER \" : \"user \");\n            printExpr(user);\n        }\n\n        SQLExpr password = x.getPassword();\n        if (password != null) {\n            if (cnt++ > 0) {\n                print(\", \");\n            }\n            print0(ucase ? \"PASSWORD \" : \"password \");\n            printExpr(password);\n        }\n\n        SQLExpr socket = x.getSocket();\n        if (socket != null) {\n            if (cnt++ > 0) {\n                print(\", \");\n            }\n            print0(ucase ? \"SOCKET \" : \"socket \");\n            printExpr(socket);\n        }\n\n        SQLExpr owner = x.getOwner();\n        if (owner != null) {\n            if (cnt++ > 0) {\n                print(\", \");\n            }\n            print0(ucase ? \"OWNER \" : \"owner \");\n            printExpr(owner);\n        }\n\n        SQLExpr port = x.getPort();\n        if (port != null) {\n            if (cnt++ > 0) {\n                print(\", \");\n            }\n            print0(ucase ? \"PORT \" : \"port \");\n            printExpr(port);\n        }\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateTableSpaceStatement x) {\n        print0(ucase ? \"CREATE TABLESPACE \" : \"create tablespace \");\n        x.getName().accept(this);\n\n        SQLExpr addDataFile = x.getAddDataFile();\n        if (addDataFile != null) {\n            print0(ucase ? \" ADD DATAFILE \" : \" add datafile \");\n            addDataFile.accept(this);\n        }\n\n        SQLExpr fileBlockSize = x.getFileBlockSize();\n        if (fileBlockSize != null) {\n            print0(ucase ? \" FILE_BLOCK_SIZE = \" : \" file_block_size = \");\n            fileBlockSize.accept(this);\n        }\n\n        SQLExpr logFileGroup = x.getLogFileGroup();\n        if (logFileGroup != null) {\n            print0(ucase ? \" USE LOGFILE GROUP \" : \" use logfile group \");\n            logFileGroup.accept(this);\n        }\n\n        SQLExpr extentSize = x.getExtentSize();\n        if (extentSize != null) {\n            print0(ucase ? \" EXTENT_SIZE = \" : \" extent_size = \");\n            extentSize.accept(this);\n        }\n\n        SQLExpr initialSize = x.getInitialSize();\n        if (initialSize != null) {\n            print0(ucase ? \" INITIAL_SIZE = \" : \" initial_size = \");\n            initialSize.accept(this);\n        }\n\n        SQLExpr autoExtentSize = x.getAutoExtentSize();\n        if (autoExtentSize != null) {\n            print0(ucase ? \" AUTOEXTEND_SIZE = \" : \" autoextend_size = \");\n            autoExtentSize.accept(this);\n        }\n\n        SQLExpr maxSize = x.getMaxSize();\n        if (autoExtentSize != null) {\n            print0(ucase ? \" MAX_SIZE = \" : \" max_size = \");\n            maxSize.accept(this);\n        }\n\n        SQLExpr nodeGroup = x.getNodeGroup();\n        if (nodeGroup != null) {\n            print0(ucase ? \" NODEGROUP = \" : \" nodegroup = \");\n            nodeGroup.accept(this);\n        }\n\n        if (x.isWait()) {\n            print0(ucase ? \" WAIT\" : \" wait\");\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            printExpr(comment);\n        }\n\n        SQLExpr engine = x.getEngine();\n        if (engine != null) {\n            print0(ucase ? \" ENGINE \" : \" engine \");\n            printExpr(engine);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterEventStatement x) {\n        print0(ucase ? \"ALTER \" : \"alter \");\n\n        SQLName definer = x.getDefiner();\n        if (definer != null) {\n            print0(ucase ? \"DEFINER = \" : \"definer = \");\n            definer.accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"EVENT \" : \"event \");\n        printExpr(x.getName());\n\n        MySqlEventSchedule schedule = x.getSchedule();\n        if (schedule != null) {\n            print0(ucase ? \" ON SCHEDULE \" : \" on schedule \");\n            schedule.accept(this);\n        }\n\n        Boolean enable = x.getEnable();\n        if (enable != null) {\n            if (enable) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            } else {\n                print0(ucase ? \" DISABLE\" : \" disable\");\n                if (x.isDisableOnSlave()) {\n                    print0(ucase ? \" ON SLAVE\" : \" on slave\");\n                }\n            }\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        SQLStatement body = x.getEventBody();\n        if (body != null) {\n            println();\n            if (!(body instanceof SQLExprStatement)) {\n                print0(ucase ? \"DO\" : \"do\");\n                println();\n            }\n            body.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterLogFileGroupStatement x) {\n        print0(ucase ? \"ALTER LOGFILE GROUP \" : \"alter logfile group \");\n        x.getName().accept(this);\n        print(' ');\n        print0(ucase ? \"ADD UNDOFILE \" : \"add undofile \");\n        printExpr(x.getAddUndoFile());\n\n        SQLExpr initialSize = x.getInitialSize();\n        if (initialSize != null) {\n            print0(ucase ? \" INITIAL_SIZE \" : \" initial_size \");\n            printExpr(initialSize);\n        }\n\n        if (x.isWait()) {\n            print0(ucase ? \" WAIT\" : \" wait\");\n        }\n\n        SQLExpr engine = x.getEngine();\n        if (engine != null) {\n            print0(ucase ? \" ENGINE \" : \" engine \");\n            printExpr(engine);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterServerStatement x) {\n        print0(ucase ? \"ALTER SERVER \" : \"alter server \");\n        x.getName().accept(this);\n\n        print(\" OPTIONS(\");\n        SQLExpr user = x.getUser();\n        if (user != null) {\n            print0(ucase ? \"USER \" : \"user \");\n            printExpr(user);\n        }\n\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTablespaceStatement x) {\n        print0(ucase ? \"CREATE TABLESPACE \" : \"create tablespace \");\n        x.getName().accept(this);\n\n        SQLExpr addDataFile = x.getAddDataFile();\n        if (addDataFile != null) {\n            print0(ucase ? \" ADD DATAFILE \" : \" add datafile \");\n            addDataFile.accept(this);\n        }\n\n        SQLExpr initialSize = x.getInitialSize();\n        if (initialSize != null) {\n            print0(ucase ? \" INITIAL_SIZE = \" : \" initial_size = \");\n            initialSize.accept(this);\n        }\n\n        if (x.isWait()) {\n            print0(ucase ? \" WAIT\" : \" wait\");\n        }\n\n        SQLExpr engine = x.getEngine();\n        if (engine != null) {\n            print0(ucase ? \" ENGINE \" : \" engine \");\n            printExpr(engine);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlChecksumTableStatement x) {\n        print0(ucase ? \"CHECKSUM TABLE \" : \"checksum table \");\n        final List<SQLExprTableSource> tables = x.getTables();\n        for (int i = 0; i < tables.size(); i++) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            tables.get(i)\n                    .accept(this);\n        }\n        return false;\n    }\n\n    protected void printQuery(SQLSelectQuery x) {\n        Class<?> clazz = x.getClass();\n        if (clazz == MySqlSelectQueryBlock.class) {\n            visit((MySqlSelectQueryBlock) x);\n        } else if (clazz == SQLSelectQueryBlock.class) {\n            visit((SQLSelectQueryBlock) x);\n        } else if (clazz == SQLUnionQuery.class) {\n            visit((SQLUnionQuery) x);\n        } else {\n            x.accept(this);\n        }\n    }\n\n    public void printInsertColumns(List<SQLExpr> columns) {\n        final int size = columns.size();\n        if (size > 0) {\n            if (size > 5) {\n                this.indentCount++;\n                print(' ');\n            }\n            print('(');\n            for (int i = 0; i < size; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        println();\n                    }\n                    print0(\", \");\n                }\n\n                SQLExpr column = columns.get(i);\n                if (column instanceof SQLIdentifierExpr) {\n                    visit((SQLIdentifierExpr) column);\n                } else {\n                    printExpr(column, parameterized);\n                }\n\n                String dataType = (String) column.getAttribute(\"dataType\");\n                if (dataType != null) {\n                    print(' ');\n                    print(dataType);\n                }\n            }\n            print(')');\n            if (size > 5) {\n                this.indentCount--;\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLValuesTableSource x) {\n        print('(');\n        incrementIndent();\n        println();\n        print0(ucase ? \"VALUES \" : \"values \");\n        List<SQLListExpr> values = x.getValues();\n        for (int i = 0; i < values.size(); ++i) {\n            if (i != 0) {\n                print(\",\");\n                println();\n            }\n            SQLListExpr list = values.get(i);\n            visit(list);\n        }\n        decrementIndent();\n        println();\n        print0(\")\");\n        if (x.getAlias() != null) {\n            print0(\" AS \");\n            print0(x.getAlias());\n\n            if (x.getColumns().size() > 0) {\n                print0(\" (\");\n                printAndAccept(x.getColumns(), \", \");\n                print(')');\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLExternalRecordFormat x) {\n        return hiveVisit(x);\n    }\n\n    public boolean visit(MySqlJSONTableExpr x) {\n        print0(ucase ? \"JSON_TABLE(\" : \"json_table(\");\n        x.getExpr().accept(this);\n        print(',');\n        x.getPath().accept(this);\n        incrementIndent();\n        println();\n        print0(ucase ? \"COLUMNS (\" : \"columns (\");\n        incrementIndent();\n        println();\n        printlnAndAccept(x.getColumns(), \",\");\n        decrementIndent();\n        println();\n        print(')');\n        decrementIndent();\n        println();\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(TidbSplitTableStatement x) {\n        print0(ucase ? \"SPLIT \" : \"split \");\n        if (x.isSplitSyntaxOptionRegionFor()) {\n            print0(ucase ? \"REGION FOR \" : \"region for \");\n        }\n        if (x.isSplitSyntaxOptionPartition()) {\n            print0(ucase ? \"PARTITION \" : \"partition \");\n        }\n        print0(ucase ? \"TABLE \" : \"table \");\n        x.getTableName().accept(this);\n        print(' ');\n\n        if (!x.getPartitionNameListOptions().isEmpty()) {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartitionNameListOptions(), \",\");\n            print(\") \");\n        }\n        if (x.getIndexName() != null) {\n            print0(ucase ? \"INDEX \" : \"index \");\n            x.getIndexName().accept(this);\n            print(' ');\n        }\n        if (!x.getSplitOptionBys().isEmpty()) {\n            print0(ucase ? \"BY \" : \"by \");\n            boolean needCommon = false;\n            for (List<SQLExpr> list : x.getSplitOptionBys()) {\n                if (!needCommon) {\n                    needCommon = true;\n                } else {\n                    print0(\", \");\n                }\n                print0(\"(\");\n                printlnAndAccept(list, \", \");\n                print0(\")\");\n            }\n        }\n        if (x.getSplitOptionBetween() != null) {\n            print0(ucase ? \"BETWEEN (\" : \" between (\");\n            printAndAccept(x.getSplitOptionBetween(), \", \");\n            print0(ucase ? \") AND (\" : \") and (\");\n            printAndAccept(x.getSplitOptionAnd(), \", \");\n            print0(\") \");\n            print0(ucase ? \"REGIONS \" : \"regions \");\n            print(x.getSplitOptionRegions());\n        }\n\n        return false;\n    }\n\n    public boolean visit(MySqlJSONTableExpr.Column x) {\n        x.getName().accept(this);\n\n        if (x.isOrdinality()) {\n            print0(ucase ? \" FOR ORDINALITY\" : \" for ordinality\");\n        }\n\n        SQLDataType dataType = x.getDataType();\n        if (dataType != null) {\n            print(' ');\n            dataType.accept(this);\n        }\n\n        if (x.isExists()) {\n            print0(ucase ? \" EXISTS\" : \" exists\");\n        }\n\n        SQLExpr path = x.getPath();\n        if (path != null) {\n            print0(ucase ? \" PATH \" : \" path \");\n            path.accept(this);\n        }\n\n        List<MySqlJSONTableExpr.Column> nestedColumns = x.getNestedColumns();\n        if (nestedColumns.size() > 0) {\n            print0(ucase ? \" COLUMNS (\" : \" columns (\");\n            printAndAccept(nestedColumns, \", \");\n            print(')');\n        }\n\n        SQLExpr onEmpty = x.getOnEmpty();\n        if (onEmpty != null) {\n            print(' ');\n            if (!(onEmpty instanceof SQLNullExpr || onEmpty instanceof SQLIdentifierExpr)) {\n                print0(ucase ? \"DEFAULT \" : \"default \");\n            }\n            onEmpty.accept(this);\n            print0(ucase ? \" ON EMPTY\" : \" on empty\");\n        }\n\n        SQLExpr onError = x.getOnError();\n        if (onError != null) {\n            print(' ');\n            if (!(onError instanceof SQLNullExpr || onError instanceof SQLIdentifierExpr)) {\n                print0(ucase ? \"DEFAULT \" : \"default \");\n            }\n            onError.accept(this);\n            print0(ucase ? \" ON ERROR\" : \" on error\");\n        }\n        return false;\n    }\n\n//    public boolean visit(SQLSelectItem x) {\n//        SQLExpr expr = x.getExpr();\n//\n//        if (expr instanceof SQLIdentifierExpr) {\n//            print0(((SQLIdentifierExpr) expr).getName());\n//        } else if (expr instanceof SQLPropertyExpr) {\n//            visit((SQLPropertyExpr) expr);\n//        } else {\n//            printExpr(expr);\n//        }\n//\n//        String alias = x.getAlias();\n//        if (alias != null && alias.length() > 0) {\n//            print0(ucase ? \" AS \" : \" as \");\n//\n//            boolean hasSpecial = false;\n//            for (int i = 1; i < alias.length() - 1; ++i) {\n//                char ch = alias.charAt(i);\n//                if (ch == ' ' || ch == '\\\"' || ch == '\\n') {\n//                    hasSpecial = true;\n//                }\n//            }\n//            char c0 = alias.charAt(0);\n//            if (!hasSpecial) {\n//                print0(alias);\n//            } else {\n//                print('\"');\n//\n//                for (int i = 0; i < alias.length(); ++i) {\n//                    char ch = alias.charAt(i);\n//                    if (ch == '\\\"') {\n//                        print('\\\\');\n//                        print(ch);\n//                    } else if (ch == '\\n') {\n//                        print0(\"\\\\n\");\n//                    } else {\n//                        print(ch);\n//                    }\n//                }\n//\n//                print('\"');\n//            }\n//        }\n//        return false;\n//    }\n\n    public boolean visit(MysqlAlterTableAlterCheck x) {\n        print0(ucase ? \"ALTER CONSTRAINT \" : \"alter constraint \");\n\n        SQLName name = x.getName();\n        if (name != null) {\n            name.accept(this);\n            print(' ');\n        }\n\n        Boolean enforced = x.getEnforced();\n        if (enforced != null) {\n            if (enforced) {\n                print0(ucase ? \" ENFORCED\" : \" enforced\");\n            } else {\n                print0(ucase ? \" NOT ENFORCED\" : \" not enforced\");\n            }\n        }\n        return false;\n    }\n\n    public boolean visit(MySqlXAStatement x) {\n        print0(ucase ? \"XA \" : \"xa \");\n\n        MySqlXAStatement.XAType type = x.getType();\n        print0(ucase ? type.name() : type.name().toLowerCase());\n        SQLExpr id = x.getId();\n        if (id != null) {\n            print(' ');\n            printExpr(id);\n        }\n        return false;\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n    }\n\n    @Override\n    protected void printTableOptionsPostfix(SQLCreateTableStatement x) {\n    }\n\n    @Override\n    protected void printTableOption(SQLExpr name, SQLExpr value, int index) {\n        println();\n        name.accept(this);\n        print0(\" = \");\n        value.accept(this);\n    }\n\n    @Override\n    public boolean visit(SQLPartitionSingle x) {\n        if (x instanceof MysqlPartitionSingle) {\n            return visit((MysqlPartitionSingle) x);\n        }\n        return super.visit(x);\n    }\n\n    public boolean visit(MysqlPartitionSingle x) {\n        boolean isDbPartiton = false, isTbPartition = false;\n        final SQLObject parent = x.getParent();\n        if (parent != null) {\n            final SQLObject parent2 = parent.getParent();\n            if (parent2 instanceof MySqlCreateTableStatement) {\n                MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) parent2;\n                isDbPartiton = parent == stmt.getDbPartitionBy();\n                isTbPartition = parent == stmt.getTablePartitionBy();\n            }\n        }\n\n        if (isDbPartiton) {\n            print0(ucase ? \"DBPARTITION \" : \"dbpartition \");\n        } else if (isTbPartition) {\n            print0(ucase ? \"TBPARTITION \" : \"tbpartition \");\n        } else {\n            print0(ucase ? \"PARTITION \" : \"partition \");\n        }\n        x.getName().accept(this);\n        if (x.getValues() != null) {\n            print(' ');\n            x.getValues().accept(this);\n        }\n\n        if (x.getDataDirectory() != null) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"DATA DIRECTORY \" : \"data directory \");\n            x.getDataDirectory().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getIndexDirectory() != null) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"INDEX DIRECTORY \" : \"index directory \");\n            x.getIndexDirectory().accept(this);\n            this.indentCount--;\n        }\n\n        this.indentCount++;\n        if (x.getTablespace() != null) {\n            printTablespace(x.getTablespace());\n        }\n\n        if (x.getEngine() != null) {\n            println();\n            print0(ucase ? \"STORAGE ENGINE \" : \"storage engine \");\n            x.getEngine().accept(this);\n        }\n        this.indentCount--;\n\n        if (x.getMaxRows() != null) {\n            print0(ucase ? \" MAX_ROWS \" : \" max_rows \");\n            x.getMaxRows().accept(this);\n        }\n\n        if (x.getMinRows() != null) {\n            print0(ucase ? \" MIN_ROWS \" : \" min_rows \");\n            x.getMinRows().accept(this);\n        }\n\n        if (x.getComment() != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            x.getComment().accept(this);\n        }\n\n        if (x.getSubPartitionsCount() != null) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"SUBPARTITIONS \" : \"subpartitions \");\n            x.getSubPartitionsCount().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getSubPartitions().size() > 0) {\n            print(\" (\");\n            this.indentCount++;\n            for (int i = 0; i < x.getSubPartitions().size(); ++i) {\n                if (i != 0) {\n                    print(',');\n                }\n                println();\n                x.getSubPartitions().get(i).accept(this);\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        SQLExpr locality = x.getLocality();\n        if (locality != null) {\n            print(ucase ? \" LOCALITY = \" : \" locality = \");\n            locality.accept(this);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlParameterizedVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;\nimport com.alibaba.druid.sql.visitor.SQLASTParameterizedVisitor;\n\nimport java.util.List;\n\npublic class MySqlParameterizedVisitor extends SQLASTParameterizedVisitor implements MySqlASTVisitor {\n    public MySqlParameterizedVisitor() {\n        super(DbType.mysql);\n    }\n\n    public MySqlParameterizedVisitor(List<Object> outParameters) {\n        super(DbType.mysql, outParameters);\n    }\n\n    @Override\n    public boolean visit(MySqlCharExpr x) {\n        parameterizeAndExportPara(x);\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLListExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement.TableSpaceOption;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Mode;\n\npublic class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlASTVisitor {\n    public MySqlSchemaStatVisitor() {\n        super(DbType.mysql);\n    }\n\n    public MySqlSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    public boolean visit(SQLSelectStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        return true;\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.mysql;\n    }\n\n    // DUAL\n    public boolean visit(MySqlDeleteStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from != null) {\n            from.accept(this);\n        }\n\n        SQLTableSource using = x.getUsing();\n        if (using != null) {\n            using.accept(this);\n        }\n\n        SQLTableSource tableSource = x.getTableSource();\n        tableSource.accept(this);\n\n        if (tableSource instanceof SQLExprTableSource) {\n            TableStat stat = this.getTableStat((SQLExprTableSource) tableSource);\n            stat.incrementDeleteCount();\n        }\n\n        accept(x.getWhere());\n\n        accept(x.getOrderBy());\n        accept(x.getLimit());\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(MySqlInsertStatement x) {\n        setModeOrigin(x);\n    }\n\n    @Override\n    public boolean visit(MySqlInsertStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        setMode(x, Mode.Insert);\n\n        TableStat stat = getTableStat(x.getTableSource());\n\n        if (stat != null) {\n            stat.incrementInsertCount();\n        }\n\n        accept(x.getColumns());\n        accept(x.getValuesList());\n        accept(x.getQuery());\n        accept(x.getDuplicateKeyUpdate());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlTableIndex x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlKey x) {\n        for (SQLObject item : x.getColumns()) {\n            item.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlPrimaryKey x) {\n        for (SQLSelectOrderByItem item : x.getColumns()) {\n            SQLExpr expr = item.getExpr();\n            expr.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowColumnsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDatabaseStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateExternalCatalogStatement x) {\n        return true;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateUserStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlPartitionByKey x) {\n        accept(x.getColumns());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUpdatePlanCacheStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPlanCacheStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlClearPlanCacheStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDisabledPlanCacheStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterDatabaseSetOption x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterDatabaseKillJob x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExplainPlanCacheStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlOutFileExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExplainStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        SQLName tableName = x.getTableName();\n        if (tableName != null) {\n            getTableStat(tableName);\n\n            SQLName columnName = x.getColumnName();\n            if (columnName != null) {\n                addColumn(tableName, columnName.getSimpleName());\n            }\n        }\n\n        if (x.getStatement() != null) {\n            accept(x.getStatement());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUpdateStatement x) {\n        visit((SQLUpdateStatement) x);\n        for (SQLExpr item : x.getReturning()) {\n            item.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSetTransactionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowHMSMetaStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowAuthorsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowBinaryLogsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowMasterLogsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCollationStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowBinLogEventsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCharacterSetStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowContributorsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateDatabaseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateEventStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateFunctionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateProcedureStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowCreateTableStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowCreateTriggerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowEngineStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowEnginesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowErrorsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowEventsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowFunctionCodeStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowFunctionStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowGrantsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUserName x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowMasterStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowOpenTablesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPluginsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPartitionsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPrivilegesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProcedureCodeStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProcedureStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProcessListStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProfileStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowProfilesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowRelayLogEventsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowRuleStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowRuleStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSlaveHostsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSequencesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSlowStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowSlaveStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTableStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowDbLockStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowHtcStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowStcStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTriggersStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTraceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowBroadcastsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDdlStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowTopologyStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowVariantsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRenameTableStatement.Item x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRenameTableStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUseIndexHint x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlIgnoreIndexHint x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlLockTableStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlLockTableStatement.Item x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUnlockTablesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlForceIndexHint x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableChangeColumn x) {\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n\n        SQLName table = stmt.getName();\n\n        SQLName column = x.getColumnName();\n        String columnName = column.toString();\n        addColumn(table, columnName);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableModifyColumn x) {\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n\n        SQLName table = stmt.getName();\n\n        SQLName column = x.getNewColumnDefinition().getName();\n        String columnName = column.toString();\n        addColumn(table, columnName);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterCharacter x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableOption x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateTableStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        boolean val = super.visit((SQLCreateTableStatement) x);\n\n        SQLExpr union = x.getOption(\"union\");\n        if (union instanceof SQLListExpr) {\n            for (SQLExpr item : ((SQLListExpr) union).getItems()) {\n                if (item instanceof SQLName) {\n                    getTableStatWithUnwrap(item);\n                }\n            }\n        }\n        if (x.getWithSelect() instanceof SQLSelectStatement) {\n            visit((SQLSelectStatement) x.getWithSelect());\n        }\n\n        return val;\n    }\n\n    @Override\n    public boolean visit(MySqlHelpStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCharExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUnique x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableDiscardTablespace x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableImportTablespace x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(TableSpaceOption x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableAlterColumn x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableForce x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableLock x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableOrderBy x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableValidation x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCaseStatement x) {\n        accept(x.getWhenList());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSelectIntoStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlWhenStatement x) {\n        accept(x.getStatements());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlLeaveStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlIterateStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRepeatStatement x) {\n        accept(x.getStatements());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCursorDeclareStatement x) {\n        accept(x.getSelect());\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlUpdateTableSource x) {\n        if (x.getUpdate() != null) {\n            return this.visit(x.getUpdate());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSubPartitionByKey x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSubPartitionByList x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDeclareHandlerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlDeclareConditionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlFlushStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlEventSchedule x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateEventStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateAddLogFileGroupStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateServerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCreateTableSpaceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterEventStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterLogFileGroupStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterServerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTablespaceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlChecksumTableStatement x) {\n        return true;\n    }\n\n    @Override\n    public boolean visit(MySqlShowDatasourcesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowNodeStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowHelpStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlFlashbackStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowConfigStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPlanCacheStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowPhysicalProcesslistStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRenameSequenceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlCheckTableStatement x) {\n        for (SQLExprTableSource tableSource : x.getTables()) {\n            tableSource.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextCharFilterStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowFullTextStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlShowCreateFullTextStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlAlterFullTextStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlDropFullTextStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextTokenizerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextTokenFilterStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextAnalyzerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MysqlCreateFullTextDictionaryStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlAlterTableAlterFullTextIndex x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExecuteForAdsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlManageInstanceGroupStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRaftMemberChangeStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlRaftLeaderTransferStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlMigrateStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowClusterNameStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowJobStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlShowMigrateTaskStatusStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlSubPartitionByValue x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExtPartition x) {\n        return true;\n    }\n\n    @Override\n    public boolean visit(MySqlExtPartition.Item x) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlShowColumnOutpuVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 27/07/2017.\n */\npublic class MySqlShowColumnOutpuVisitor extends MySqlOutputVisitor {\n    public MySqlShowColumnOutpuVisitor(StringBuilder appender) {\n        super(appender);\n    }\n\n    public boolean visit(MySqlCreateTableStatement x) {\n        List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();\n        List<String> dataTypes = new ArrayList<String>();\n        List<String> defaultValues = new ArrayList<String>();\n\n        int name_len = -1, dataType_len = -1, defaultVal_len = 7, extra_len = 5;\n        for (SQLTableElement element : x.getTableElementList()) {\n            if (element instanceof SQLColumnDefinition) {\n                SQLColumnDefinition column = (SQLColumnDefinition) element;\n                columns.add(column);\n\n                String name = SQLUtils.normalize(column.getName().getSimpleName());\n                if (name_len < name.length()) {\n                    name_len = name.length();\n                }\n\n                StringBuilder dataType = new StringBuilder(column.getDataType().getName());\n                if (column.getDataType().getArguments().size() > 0) {\n                    dataType.append(\"(\");\n                    for (int i = 0; i < column.getDataType().getArguments().size(); i++) {\n                        if (i != 0) {\n                            dataType.append(\",\");\n                        }\n                        SQLExpr arg = column.getDataType().getArguments().get(i);\n                        dataType.append(arg.toString());\n                    }\n                    dataType.append(\")\");\n                }\n\n                if (dataType_len < dataType.length()) {\n                    dataType_len = dataType.length();\n                }\n                dataTypes.add(dataType.toString());\n\n                if (column.getDefaultExpr() == null) {\n                    defaultValues.add(null);\n                } else {\n                    String defaultVal = SQLUtils.toMySqlString(column.getDefaultExpr());\n                    if (defaultVal.length() > 2 && defaultVal.charAt(0) == '\\'' && defaultVal.charAt(defaultVal.length() - 1) == '\\'') {\n                        defaultVal = defaultVal.substring(1, defaultVal.length() - 1);\n                    }\n                    defaultValues.add(defaultVal);\n\n                    if (defaultVal_len < defaultVal.length()) {\n                        defaultVal_len = defaultVal.length();\n                    }\n                }\n\n                if (column.isAutoIncrement()) {\n                    extra_len = \"auto_increment\".length();\n                } else if (column.getOnUpdate() != null) {\n                    extra_len = \"on update CURRENT_TIMESTAMP\".length();\n                }\n            }\n        }\n\n        print(\"+-\");\n        print('-', name_len);\n        print(\"-+-\");\n        print('-', dataType_len);\n        print(\"-+------+-----+-\");\n        print('-', defaultVal_len);\n        print(\"-+-\");\n        print('-', extra_len);\n        print(\"-+\\n\");\n\n        print(\"| \");\n        print(\"Field\", name_len, ' ');\n        print(\" | \");\n        print(\"Type\", dataType_len, ' ');\n        print(\" | Null | Key | \");\n        print(\"Default\", defaultVal_len, ' ');\n        print(\" | \");\n        print(\"Extra\", extra_len, ' ');\n        print(\" |\\n\");\n\n        print(\"+-\");\n        print('-', name_len);\n        print(\"-+-\");\n        print('-', dataType_len);\n        print(\"-+------+-----+-\");\n        print('-', defaultVal_len);\n        print(\"-+-\");\n        print('-', extra_len);\n        print(\"-+\\n\");\n\n        for (int i = 0; i < columns.size(); i++) {\n            SQLColumnDefinition column = columns.get(i);\n            String name = SQLUtils.normalize(column.getName().getSimpleName());\n\n            print(\"| \");\n            print(name, name_len, ' ');\n            print(\" | \");\n\n            print(dataTypes.get(i), dataType_len, ' ');\n            print(\" | \");\n\n            if (column.containsNotNullConstaint()) {\n                print(\"NO \");\n            } else {\n                print(\"YES\");\n            }\n            print(\"  | \");\n\n            MySqlUnique unique = null;\n            if (x.isPrimaryColumn(name)) {\n                print(\"PRI\");\n            } else if (x.isUNI(name)) {\n                print(\"UNI\");\n            } else if (x.isMUL(name)) {\n                print(\"MUL\");\n            } else {\n                print(\"   \");\n            }\n            print(\" | \");\n\n            String defaultVal = defaultValues.get(i);\n            if (defaultVal == null) {\n                print(\"NULL\", defaultVal_len, ' ');\n            } else {\n                print(defaultVal, defaultVal_len, ' ');\n            }\n            print(\" | \");\n\n            if (column.isAutoIncrement()) {\n                print(\"auto_increment\", extra_len, ' ');\n            } else if (column.getOnUpdate() != null) {\n                print(\"on update CURRENT_TIMESTAMP\", extra_len, ' ');\n            } else {\n                print(' ', extra_len);\n            }\n            print(\" |\");\n            print(\"\\n\");\n        }\n        print(\"+-\");\n        print('-', name_len);\n        print(\"-+-\");\n        print('-', dataType_len);\n        print(\"-+------+-----+-\");\n        print('-', defaultVal_len);\n        print(\"-+-\");\n        print('-', extra_len);\n        print(\"-+\\n\");\n\n        return false;\n    }\n\n    void print(char ch, int count) {\n        for (int i = 0; i < count; ++i) {\n            print(ch);\n        }\n    }\n\n    void print(String text, int columnSize, char ch) {\n        print(text);\n        print(' ', columnSize - text.length());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/FromSubqueryResolver.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor.transform;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author wenshao[szujobs@hotmail.com]\n */\npublic class FromSubqueryResolver extends OracleASTVisitorAdapter {\n    private final List<SQLStatement> targetList;\n    private final String viewName;\n    private final Map<String, String> mappings = new LinkedHashMap<String, String>();\n\n    private int viewNameSeed = 1;\n\n    public FromSubqueryResolver(List<SQLStatement> targetList, String viewName) {\n        this.targetList = targetList;\n        this.viewName = viewName;\n    }\n\n    public boolean visit(OracleSelectSubqueryTableSource x) {\n        return visit((SQLSubqueryTableSource) x);\n    }\n\n    public boolean visit(SQLSubqueryTableSource x) {\n        String subViewName = generateSubViewName();\n\n        SQLObject parent = x.getParent();\n        if (parent instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;\n            queryBlock.setFrom(subViewName, x.getAlias());\n        } else if (parent instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) parent;\n            if (join.getLeft() == x) {\n                join.setLeft(subViewName, x.getAlias());\n            } else if (join.getRight() == x) {\n                join.setRight(subViewName, x.getAlias());\n            }\n        }\n\n        SQLCreateViewStatement stmt = new SQLCreateViewStatement();\n\n        stmt.setName(generateSubViewName());\n\n        SQLSelect select = x.getSelect();\n        stmt.setSubQuery(select);\n\n        targetList.add(0, stmt);\n\n        stmt.accept(new FromSubqueryResolver(targetList, viewName));\n\n        return false;\n    }\n\n    public boolean visit(SQLExprTableSource x) {\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            String ident = identifierExpr.getName();\n            String mappingIdent = mappings.get(ident);\n            if (mappingIdent != null) {\n                x.setExpr(new SQLIdentifierExpr(mappingIdent));\n            }\n        }\n        return false;\n    }\n\n    public boolean visit(OracleSelectTableReference x) {\n        return visit((SQLExprTableSource) x);\n    }\n\n    private String generateSubViewName() {\n        return this.viewName + \"_\" + targetList.size();\n    }\n\n    public static List<SQLStatement> resolve(SQLCreateViewStatement stmt) {\n        List<SQLStatement> targetList = new ArrayList<SQLStatement>();\n        targetList.add(stmt);\n\n        String viewName = SQLUtils.normalize(stmt.getName().getSimpleName());\n\n        FromSubqueryResolver visitor = new FromSubqueryResolver(targetList, viewName);\n\n        SQLWithSubqueryClause withSubqueryClause = stmt.getSubQuery().getWithSubQuery();\n        if (withSubqueryClause != null) {\n            stmt.getSubQuery().setWithSubQuery(null);\n\n            for (SQLWithSubqueryClause.Entry entry : withSubqueryClause.getEntries()) {\n                String entryName = entry.getAlias();\n\n                SQLCreateViewStatement entryStmt = new SQLCreateViewStatement();\n                entryStmt.setOrReplace(true);\n                entryStmt.setDbType(stmt.getDbType());\n\n                String entryViewName = visitor.generateSubViewName();\n                entryStmt.setName(entryViewName);\n                entryStmt.setSubQuery(entry.getSubQuery());\n\n                visitor.targetList.add(0, entryStmt);\n                visitor.mappings.put(entryName, entryViewName);\n\n                entryStmt.accept(visitor);\n            }\n        }\n\n        stmt.accept(visitor);\n\n        DbType dbType = stmt.getDbType();\n        for (int i = 0; i < targetList.size() - 1; ++i) {\n            SQLCreateViewStatement targetStmt = (SQLCreateViewStatement) targetList.get(i);\n            targetStmt.setOrReplace(true);\n            targetStmt.setDbType(dbType);\n            targetStmt.setAfterSemi(true);\n        }\n\n        return targetList;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/NameResolveVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor.transform;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\nimport com.alibaba.druid.util.FnvHash;\n\n/**\n * Created by wenshao on 26/07/2017.\n */\npublic class NameResolveVisitor extends OracleASTVisitorAdapter {\n    @Override\n    public boolean visit(SQLIdentifierExpr x) {\n        SQLObject parent = x.getParent();\n\n        if (parent instanceof SQLBinaryOpExpr\n                && x.getResolvedColumn() == null) {\n            SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) parent;\n            boolean isJoinCondition = binaryOpExpr.getLeft() instanceof SQLName\n                    && binaryOpExpr.getRight() instanceof SQLName;\n            if (isJoinCondition) {\n                return false;\n            }\n        }\n\n        String name = x.getName();\n\n        if (\"ROWNUM\".equalsIgnoreCase(name)) {\n            return false;\n        }\n\n        long hash = x.nameHashCode64();\n        SQLTableSource tableSource = null;\n\n        if (hash == FnvHash.Constants.LEVEL\n                || hash == FnvHash.Constants.CONNECT_BY_ISCYCLE\n                || hash == FnvHash.Constants.SYSTIMESTAMP) {\n            return false;\n        }\n\n        if (parent instanceof SQLPropertyExpr) {\n            return false;\n        }\n\n        for (; parent != null; parent = parent.getParent()) {\n            if (parent instanceof SQLTableSource) {\n                return false;\n            }\n\n            if (parent instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;\n\n                if (queryBlock.getInto() != null) {\n                    return false;\n                }\n\n                if (queryBlock.getParent() instanceof SQLSelect) {\n                    SQLObject pp = queryBlock.getParent().getParent();\n                    if (pp instanceof SQLInSubQueryExpr || pp instanceof SQLExistsExpr) {\n                        return false;\n                    }\n                }\n\n                SQLTableSource from = queryBlock.getFrom();\n                if (from instanceof SQLExprTableSource || from instanceof SQLSubqueryTableSource) {\n                    String alias = from.getAlias();\n                    if (alias != null) {\n                        // rownum 不加 alias\n                        boolean isRowNumColumn = isRowNumColumn(x, queryBlock);\n                        // 别名 不加 alias\n                        boolean isAliasColumn = isAliasColumn(x, queryBlock);\n                        if (!isRowNumColumn && !isAliasColumn) {\n                            SQLUtils.replaceInParent(x, new SQLPropertyExpr(alias, name));\n                        }\n                    }\n                }\n                return false;\n            }\n        }\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLPropertyExpr x) {\n        String ownerName = x.getOwnernName();\n        if (ownerName == null) {\n            return super.visit(x);\n        }\n\n        for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n            if (parent instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;\n                SQLTableSource tableSource = queryBlock.findTableSource(ownerName);\n                if (tableSource == null) {\n                    continue;\n                }\n\n                String alias = tableSource.computeAlias();\n                if (ownerName.equalsIgnoreCase(alias)\n                        && !ownerName.equals(alias)) {\n                    x.setOwner(alias);\n                }\n\n                break;\n            }\n        }\n\n        return super.visit(x);\n    }\n\n    /**\n     * 是否是 rownum 或者 rownum 别名\n     *\n     * @param x      x 是否是 rownum 或者 rownum 别名\n     * @param source 从 source 数据中查找 and 判断\n     * @return true：是、false：不是\n     */\n    public boolean isRowNumColumn(SQLExpr x, SQLSelectQueryBlock source) {\n        if (x instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) x;\n            long nameHashCode64 = identifierExpr.nameHashCode64();\n            if (nameHashCode64 == FnvHash.Constants.ROWNUM) {\n                return true;\n            }\n\n            SQLSelectQueryBlock queryBlock = source;\n            if (queryBlock.getFrom() instanceof SQLSubqueryTableSource\n                    && ((SQLSubqueryTableSource) queryBlock.getFrom()).getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock subQueryBlock = ((SQLSubqueryTableSource) queryBlock.getFrom()).getSelect().getQueryBlock();\n                SQLSelectItem selectItem = subQueryBlock.findSelectItem(nameHashCode64);\n\n                if (selectItem != null && isRowNumColumn(selectItem.getExpr(), subQueryBlock)) {\n                    return true;\n                }\n\n            }\n\n        }\n        return false;\n    }\n\n    /**\n     * 是否是 select item 字段的别名\n     *\n     * @param x      x 是否是 select item 字段的别名\n     * @param source 从 source 数据中查找 and 判断\n     * @return true：是、false：不是\n     */\n    public boolean isAliasColumn(SQLExpr x, SQLSelectQueryBlock source) {\n        if (x instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) x;\n            long nameHashCode64 = identifierExpr.nameHashCode64();\n            SQLSelectQueryBlock queryBlock = source;\n\n            SQLSelectItem selectItem = queryBlock.findSelectItem(nameHashCode64);\n            if (selectItem != null) {\n                return true;\n            }\n\n            if (queryBlock.getFrom() instanceof SQLSubqueryTableSource\n                    && ((SQLSubqueryTableSource) queryBlock.getFrom()).getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock subQueryBlock = ((SQLSubqueryTableSource) queryBlock.getFrom()).getSelect().getQueryBlock();\n\n                if (isAliasColumn(x, subQueryBlock)) {\n                    return true;\n                }\n\n            }\n\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/transform/OrderByResolve.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.mysql.visitor.transform;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 27/07/2017.\n */\npublic class OrderByResolve extends OracleASTVisitorAdapter {\n    static final long DBMS_RANDOM_VALUE = FnvHash.hashCode64(\"DBMS_RANDOM.value\");\n\n    public boolean visit(SQLSelect x) {\n        SQLSelectQueryBlock queryBlock = x.getQueryBlock();\n        if (queryBlock == null) {\n            return super.visit(x);\n        }\n\n        if (x.getOrderBy() != null && queryBlock.isForUpdate() && queryBlock.getOrderBy() == null) {\n            queryBlock.setOrderBy(x.getOrderBy());\n            x.setOrderBy(null);\n        }\n\n        SQLOrderBy orderBy = queryBlock.getOrderBy();\n        if (orderBy == null) {\n            return super.visit(x);\n        }\n\n        if (!queryBlock.selectItemHasAllColumn(false)) {\n            List<SQLSelectOrderByItem> notContainsOrderBy = new ArrayList<SQLSelectOrderByItem>();\n\n            for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) {\n                SQLExpr orderByExpr = orderByItem.getExpr();\n\n                if (orderByExpr instanceof SQLName) {\n                    if (((SQLName) orderByExpr).hashCode64() == DBMS_RANDOM_VALUE) {\n                        continue;\n                    }\n\n                    long hashCode64 = ((SQLName) orderByExpr).nameHashCode64();\n                    SQLSelectItem selectItem = queryBlock.findSelectItem(hashCode64);\n                    if (selectItem == null) {\n                        queryBlock.addSelectItem(orderByExpr.clone());\n                    }\n                }\n            }\n\n            if (notContainsOrderBy.size() > 0) {\n                for (SQLSelectOrderByItem orderByItem : notContainsOrderBy) {\n                    queryBlock.addSelectItem(orderByItem.getExpr());\n                }\n\n                OracleSelectQueryBlock queryBlock1 = new OracleSelectQueryBlock();\n                queryBlock1.setFrom(queryBlock, \"x\");\n                x.setQuery(queryBlock1);\n            }\n        }\n\n        return super.visit(x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/Odps.java",
    "content": "package com.alibaba.druid.sql.dialect.odps;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Odps {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.odps);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAddAccountProviderStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OdpsAddAccountProviderStatement extends SQLStatementImpl {\n    private SQLName provider;\n\n    public OdpsAddAccountProviderStatement() {\n        super(DbType.odps);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, provider);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getProvider() {\n        return provider;\n    }\n\n    public void setProvider(SQLName provider) {\n        if (provider != null) {\n            provider.setParent(this);\n        }\n        this.provider = provider;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAddFileStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsAddFileStatement extends OdpsStatementImpl implements SQLAlterStatement {\n    private FileType type = FileType.FILE;\n\n    private String file;\n    private String alias;\n\n    protected SQLExpr comment;\n    protected boolean force;\n\n    public OdpsAddFileStatement() {\n        super.dbType = DbType.odps;\n    }\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public FileType getType() {\n        return type;\n    }\n\n    public void setType(FileType type) {\n        this.type = type;\n    }\n\n    public String getFile() {\n        return file;\n    }\n\n    public void setFile(String file) {\n        this.file = file;\n    }\n\n    public String getAlias() {\n        return alias;\n    }\n\n    public void setAlias(String alias) {\n        this.alias = alias;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.comment = x;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n\n    public static enum FileType {\n        FILE, ARCHIVE, JAR, PY\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAddStatisticStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsAddStatisticStatement extends OdpsStatementImpl implements SQLAlterStatement {\n    private SQLExprTableSource table;\n\n    private OdpsStatisticClause statisticClause;\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(table);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public OdpsStatisticClause getStatisticClause() {\n        return statisticClause;\n    }\n\n    public void setStatisticClause(OdpsStatisticClause statisticClause) {\n        this.statisticClause = statisticClause;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAddTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLPrivilegeItem;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsAddTableStatement extends OdpsStatementImpl implements SQLAlterStatement {\n    private SQLExprTableSource table;\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>();\n    protected SQLExpr comment;\n    protected boolean force;\n\n    protected final List<SQLPrivilegeItem> privileges = new ArrayList<SQLPrivilegeItem>();\n    protected SQLName toPackage;\n\n    public OdpsAddTableStatement() {\n        super.dbType = DbType.odps;\n    }\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(table);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.comment = x;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public SQLName getToPackage() {\n        return toPackage;\n    }\n\n    public void setToPackage(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.toPackage = x;\n    }\n\n    public List<SQLPrivilegeItem> getPrivileges() {\n        return privileges;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAddUserStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OdpsAddUserStatement extends SQLStatementImpl {\n    private SQLName user;\n\n    public OdpsAddUserStatement() {\n        super(DbType.odps);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, user);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getUser() {\n        return user;\n    }\n\n    public void setUser(SQLName user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.user = user;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAlterTableChangeOwner.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsAlterTableChangeOwner extends OdpsObjectImpl\n        implements SQLAlterTableItem {\n    private SQLExpr value;\n\n    @Override\n    public void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, value);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.value = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAlterTableSetChangeLogs.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsAlterTableSetChangeLogs extends OdpsObjectImpl\n        implements SQLAlterTableItem {\n    private SQLExpr value;\n\n    @Override\n    public void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, value);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.value = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsAlterTableSetFileFormat.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsAlterTableSetFileFormat extends OdpsObjectImpl\n        implements SQLAlterTableItem {\n    private SQLExpr value;\n\n    @Override\n    public void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, value);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.value = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsCopyStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OdpsCopyStmt extends OdpsStatementImpl {\n    private String arguments;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getArguments() {\n        return arguments;\n    }\n\n    public void setArguments(String arguments) {\n        this.arguments = arguments;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsCountStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsCountStatement\n        extends OdpsStatementImpl implements SQLAlterStatement {\n    private SQLExprTableSource table;\n\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>();\n\n    public OdpsCountStatement() {\n        super.dbType = DbType.odps;\n    }\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(table);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsCreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLAliasedExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsCreateTableStatement extends HiveCreateTableStatement {\n    protected SQLAliasedExpr autoPartitionedBy;\n    protected final List<SQLExpr> withSerdeproperties = new ArrayList<SQLExpr>();\n\n    public OdpsCreateTableStatement() {\n        super(DbType.odps);\n    }\n\n    public SQLExprTableSource getLike() {\n        return like;\n    }\n\n    public void setLike(SQLName like) {\n        this.setLike(new SQLExprTableSource(like));\n    }\n\n    public void setLike(SQLExprTableSource like) {\n        this.like = like;\n    }\n\n    public SQLAliasedExpr getAutoPartitionedBy() {\n        return autoPartitionedBy;\n    }\n\n    public void setAutoPartitionedBy(SQLAliasedExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.autoPartitionedBy = x;\n    }\n\n    public void setAutoPartitionedBy(SQLExpr x, String alias) {\n        setAutoPartitionedBy(new SQLAliasedExpr(x, alias));\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof OdpsASTVisitor) {\n            accept0((OdpsASTVisitor) v);\n            return;\n        }\n\n        super.accept0(v);\n    }\n\n    protected void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        super.acceptChild(v);\n\n        acceptChild(v, withSerdeproperties);\n        acceptChild(v, storedBy);\n    }\n\n    public List<SQLExpr> getWithSerdeproperties() {\n        return withSerdeproperties;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsDeclareVariableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsDeclareVariableStatement extends OdpsStatementImpl {\n    private String variant;\n    private SQLDataType dataType;\n    private SQLExpr initValue;\n\n    public OdpsDeclareVariableStatement() {\n    }\n\n    public OdpsDeclareVariableStatement(String variant, SQLExpr initValue) {\n        this.variant = variant;\n        this.initValue = initValue;\n    }\n\n    @Override\n    protected void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, dataType);\n            acceptChild(v, initValue);\n        }\n        v.endVisit(this);\n    }\n\n    public String getVariant() {\n        return variant;\n    }\n\n    public void setVariant(String variant) {\n        this.variant = variant;\n    }\n\n    public SQLExpr getInitValue() {\n        return initValue;\n    }\n\n    public void setInitValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.initValue = x;\n    }\n\n    public SQLDataType getDataType() {\n        return dataType;\n    }\n\n    public void setDataType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.dataType = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsExstoreStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsExstoreStatement extends OdpsStatementImpl {\n    private SQLExprTableSource table;\n    private final List<SQLAssignItem> partitions = new ArrayList<>();\n\n    @Override\n    protected void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, table);\n            acceptChild(v, partitions);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsGrantStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLGrantStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLObjectType;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsGrantStmt extends SQLGrantStatement {\n    private SQLObjectType subjectType;\n\n    private boolean isSuper;\n\n    private boolean isLabel;\n    private SQLExpr label;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n    private SQLExpr expire;\n\n    public OdpsGrantStmt() {\n        super(DbType.odps);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, resource);\n            acceptChild(visitor, users);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLObjectType getSubjectType() {\n        return subjectType;\n    }\n\n    public void setSubjectType(SQLObjectType subjectType) {\n        this.subjectType = subjectType;\n    }\n\n    public boolean isSuper() {\n        return isSuper;\n    }\n\n    public void setSuper(boolean isSuper) {\n        this.isSuper = isSuper;\n    }\n\n    public boolean isLabel() {\n        return isLabel;\n    }\n\n    public void setLabel(boolean isLabel) {\n        this.isLabel = isLabel;\n    }\n\n    public SQLExpr getLabel() {\n        return label;\n    }\n\n    public void setLabel(SQLExpr label) {\n        this.label = label;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void setColumnList(List<SQLName> columns) {\n        this.columns = columns;\n    }\n\n    public SQLExpr getExpire() {\n        return expire;\n    }\n\n    public void setExpire(SQLExpr expire) {\n        this.expire = expire;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsInstallPackageStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsInstallPackageStatement extends OdpsStatementImpl {\n    private SQLName packageName;\n\n    @Override\n    protected void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, packageName);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLName getPackageName() {\n        return packageName;\n    }\n\n    public void setPackageName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.packageName = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsListStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OdpsListStmt extends SQLStatementImpl {\n    private SQLExpr object;\n\n    public OdpsListStmt() {\n        super(DbType.odps);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, object);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getObject() {\n        return object;\n    }\n\n    public void setObject(SQLExpr object) {\n        if (object != null) {\n            object.setParent(this);\n        }\n        this.object = object;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsNewExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsNewExpr extends SQLMethodInvokeExpr implements OdpsObject {\n    private boolean array;\n\n    private List<SQLExpr> initValues = new ArrayList<>();\n    private List<SQLDataType> typeParameters = new ArrayList<>();\n\n    public OdpsNewExpr() {\n    }\n\n    @Override\n    public OdpsNewExpr clone() {\n        OdpsNewExpr x = new OdpsNewExpr();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        accept0((OdpsASTVisitor) v);\n    }\n\n    @Override\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            if (this.owner != null) {\n                this.owner.accept(visitor);\n            }\n\n            for (SQLExpr arg : this.arguments) {\n                if (arg != null) {\n                    arg.accept(visitor);\n                }\n            }\n\n            if (this.from != null) {\n                this.from.accept(visitor);\n            }\n\n            if (this.using != null) {\n                this.using.accept(visitor);\n            }\n\n            if (this.hasFor != null) {\n                this.hasFor.accept(visitor);\n            }\n\n            visitor.endVisit(this);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void output(StringBuilder buf) {\n        buf.append(\"new \");\n        super.output(buf);\n    }\n\n    public boolean isArray() {\n        return array;\n    }\n\n    public void setArray(boolean array) {\n        this.array = array;\n    }\n\n    public List<SQLExpr> getInitValues() {\n        return initValues;\n    }\n\n    public List<SQLDataType> getTypeParameters() {\n        return typeParameters;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic interface OdpsObject extends SQLObject {\n    void accept0(OdpsASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsObjectImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class OdpsObjectImpl extends SQLObjectImpl implements OdpsObject {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public abstract void accept0(OdpsASTVisitor visitor);\n\n    public String toString() {\n        return SQLUtils.toOdpsString(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsPAIStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OdpsPAIStmt extends OdpsStatementImpl {\n    private String arguments;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getArguments() {\n        return arguments;\n    }\n\n    public void setArguments(String arguments) {\n        this.arguments = arguments;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsQueryAliasStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsQueryAliasStatement extends OdpsStatementImpl {\n    private String variant;\n    private boolean cache;\n    private SQLSelectStatement statement;\n\n    public OdpsQueryAliasStatement() {\n    }\n\n    public OdpsQueryAliasStatement(String variant, SQLSelectStatement statement) {\n        this.variant = variant;\n        this.statement = statement;\n    }\n\n    @Override\n    protected void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, statement);\n        }\n        v.endVisit(this);\n    }\n\n    public String getVariant() {\n        return variant;\n    }\n\n    public void setVariant(String variant) {\n        this.variant = variant;\n    }\n\n    public SQLSelectStatement getStatement() {\n        return statement;\n    }\n\n    public void setStatement(SQLSelectStatement statement) {\n        this.statement = statement;\n    }\n\n    public boolean isCache() {\n        return cache;\n    }\n\n    public void setCache(boolean cache) {\n        this.cache = cache;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsReadStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsReadStatement extends OdpsStatementImpl {\n    private SQLExprTableSource table;\n    private List<SQLAssignItem> partition = new ArrayList<SQLAssignItem>();\n    private List<SQLName> columns = new ArrayList<SQLName>();\n    private SQLExpr rowCount;\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n            this.acceptChild(visitor, columns);\n            this.acceptChild(visitor, partition);\n            this.acceptChild(visitor, rowCount);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(table);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public List<SQLAssignItem> getPartition() {\n        return partition;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public SQLExpr getRowCount() {\n        return rowCount;\n    }\n\n    public void setRowCount(SQLExpr rowCount) {\n        this.rowCount = rowCount;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsRemoveStatisticStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic class OdpsRemoveStatisticStatement extends OdpsStatementImpl {\n    private SQLExprTableSource table;\n\n    private OdpsStatisticClause statisticClause;\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(table);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public OdpsStatisticClause getStatisticClause() {\n        return statisticClause;\n    }\n\n    public void setStatisticClause(OdpsStatisticClause statisticClause) {\n        this.statisticClause = statisticClause;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsRemoveUserStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OdpsRemoveUserStatement extends SQLStatementImpl {\n    private SQLIdentifierExpr user;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, user);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLIdentifierExpr getUser() {\n        return user;\n    }\n\n    public void setUser(SQLIdentifierExpr user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.user = user;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsRestoreStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsRestoreStatement\n        extends OdpsStatementImpl implements SQLAlterStatement {\n    private final List<SQLAssignItem> properties = new ArrayList<SQLAssignItem>();\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>();\n    private SQLExprTableSource table;\n    private SQLExpr to;\n\n    private String alias;\n\n    public OdpsRestoreStatement() {\n        super.dbType = DbType.odps;\n    }\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(table);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public SQLExpr getTo() {\n        return to;\n    }\n\n    public void setTo(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.to = x;\n    }\n\n    public String getAlias() {\n        return alias;\n    }\n\n    public void setAlias(String alias) {\n        this.alias = alias;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsSelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLZOrderBy;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\n\npublic class OdpsSelectQueryBlock extends SQLSelectQueryBlock {\n    private SQLZOrderBy zOrderBy;\n\n    public OdpsSelectQueryBlock() {\n        dbType = DbType.odps;\n\n        clusterBy = new ArrayList<SQLSelectOrderByItem>();\n        distributeBy = new ArrayList<SQLSelectOrderByItem>();\n        sortBy = new ArrayList<SQLSelectOrderByItem>(2);\n    }\n\n    public OdpsSelectQueryBlock clone() {\n        OdpsSelectQueryBlock x = new OdpsSelectQueryBlock();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OdpsASTVisitor) {\n            accept0((OdpsASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.hints);\n            acceptChild(visitor, this.selectList);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.groupBy);\n            acceptChild(visitor, this.qualify);\n            acceptChild(visitor, this.orderBy);\n            acceptChild(visitor, this.zOrderBy);\n            acceptChild(visitor, this.clusterBy);\n            acceptChild(visitor, this.distributeBy);\n            acceptChild(visitor, this.sortBy);\n            acceptChild(visitor, this.limit);\n            acceptChild(visitor, this.into);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public String toString() {\n        return SQLUtils.toOdpsString(this);\n    }\n\n    public void limit(int rowCount, int offset) {\n        if (offset > 0) {\n            throw new UnsupportedOperationException(\"not support offset\");\n        }\n\n        setLimit(new SQLLimit(new SQLIntegerExpr(rowCount)));\n    }\n\n    public SQLZOrderBy getZOrderBy() {\n        return zOrderBy;\n    }\n\n    public void setZOrderBy(SQLZOrderBy x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n\n        this.zOrderBy = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsSetLabelStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsSetLabelStatement extends OdpsStatementImpl {\n    private String label;\n\n    private SQLExpr project;\n    private SQLExpr user;\n\n    private SQLTableSource table;\n\n    private List<SQLName> columns = new ArrayList<SQLName>();\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, user);\n        }\n        visitor.endVisit(this);\n    }\n\n    public String getLabel() {\n        return label;\n    }\n\n    public void setLabel(String label) {\n        this.label = label;\n    }\n\n    public SQLExpr getUser() {\n        return user;\n    }\n\n    public void setUser(SQLExpr user) {\n        this.user = user;\n        user.setParent(this);\n    }\n\n    public SQLTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLTableSource table) {\n        this.table = table;\n        table.setParent(this);\n    }\n\n    public SQLExpr getProject() {\n        return project;\n    }\n\n    public void setProject(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.project = x;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsShowChangelogsStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsShowChangelogsStatement extends SQLStatementImpl {\n    protected SQLExprTableSource table;\n    private boolean tables;\n    private List<SQLAssignItem> properties = new ArrayList<>();\n    private List<SQLAssignItem> partitions = new ArrayList<>();\n    private SQLExpr id;\n\n    public OdpsShowChangelogsStatement() {\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, table);\n            acceptChild(visitor, properties);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, id);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isTables() {\n        return tables;\n    }\n\n    public void setTables(boolean tables) {\n        this.tables = tables;\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public SQLExpr getId() {\n        return id;\n    }\n\n    public void setId(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.id = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsShowGrantsStmt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OdpsShowGrantsStmt extends SQLStatementImpl {\n    private boolean label;\n\n    private SQLExpr user;\n\n    private SQLExpr objectType;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, user);\n            acceptChild(visitor, objectType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getUser() {\n        return user;\n    }\n\n    public void setUser(SQLExpr user) {\n        if (user != null) {\n            user.setParent(this);\n        }\n        this.user = user;\n    }\n\n    public SQLExpr getObjectType() {\n        return objectType;\n    }\n\n    public void setObjectType(SQLExpr objectType) {\n        if (objectType != null) {\n            objectType.setParent(this);\n        }\n        this.objectType = objectType;\n    }\n\n    public boolean isLabel() {\n        return label;\n    }\n\n    public void setLabel(boolean label) {\n        this.label = label;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsStatementImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class OdpsStatementImpl extends SQLStatementImpl {\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    protected abstract void accept0(OdpsASTVisitor visitor);\n\n    public String toString() {\n        return SQLUtils.toOdpsString(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsStatisticClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\npublic abstract class OdpsStatisticClause extends OdpsObjectImpl {\n    public abstract static class ColumnStatisticClause extends OdpsStatisticClause {\n        protected SQLName column;\n\n        public SQLName getColumn() {\n            return column;\n        }\n\n        public void setColumn(SQLName column) {\n            if (column != null) {\n                column.setParent(this);\n            }\n            this.column = column;\n        }\n\n    }\n\n    public static class NullValue extends ColumnStatisticClause {\n        @Override\n        public void accept0(OdpsASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, column);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class ColumnSum extends ColumnStatisticClause {\n        @Override\n        public void accept0(OdpsASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, column);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class ColumnMin extends ColumnStatisticClause {\n        @Override\n        public void accept0(OdpsASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, column);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class DistinctValue extends ColumnStatisticClause {\n        @Override\n        public void accept0(OdpsASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, column);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class ColumnMax extends ColumnStatisticClause {\n        @Override\n        public void accept0(OdpsASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, column);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class ExpressionCondition extends OdpsStatisticClause {\n        private SQLExpr expr;\n\n        public SQLExpr getExpr() {\n            return expr;\n        }\n\n        public void setExpr(SQLExpr expr) {\n            if (expr != null) {\n                expr.setParent(this);\n            }\n            this.expr = expr;\n        }\n\n        @Override\n        public void accept0(OdpsASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, expr);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class TableCount extends OdpsStatisticClause {\n        @Override\n        public void accept0(OdpsASTVisitor visitor) {\n            visitor.visit(this);\n            visitor.endVisit(this);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsTransformExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsTransformExpr extends SQLExprImpl implements OdpsObject {\n    private SQLExternalRecordFormat inputRowFormat;\n    private final List<SQLExpr> inputColumns = new ArrayList<>();\n    private final List<SQLColumnDefinition> outputColumns = new ArrayList<>();\n    private SQLExpr using;\n    private final List<SQLExpr> resources = new ArrayList<>();\n    private SQLExternalRecordFormat outputRowFormat;\n\n    @Override\n    public boolean equals(Object o) {\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        return 0;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        accept0((OdpsASTVisitor) v);\n    }\n\n    @Override\n    public void accept0(OdpsASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, inputColumns);\n            acceptChild(v, outputColumns);\n        }\n        v.endVisit(this);\n    }\n\n    @Override\n    public SQLExpr clone() {\n        return null;\n    }\n\n    public SQLExternalRecordFormat getInputRowFormat() {\n        return inputRowFormat;\n    }\n\n    public void setInputRowFormat(SQLExternalRecordFormat inputRowFormat) {\n        this.inputRowFormat = inputRowFormat;\n    }\n\n    public List<SQLExpr> getInputColumns() {\n        return inputColumns;\n    }\n\n    public List<SQLColumnDefinition> getOutputColumns() {\n        return outputColumns;\n    }\n\n    public SQLExpr getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLExpr using) {\n        this.using = using;\n    }\n\n    public SQLExternalRecordFormat getOutputRowFormat() {\n        return outputRowFormat;\n    }\n\n    public void setOutputRowFormat(SQLExternalRecordFormat outputRowFormat) {\n        this.outputRowFormat = outputRowFormat;\n    }\n\n    public List<SQLExpr> getResources() {\n        return resources;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsUDTFSQLSelectItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\n\npublic class OdpsUDTFSQLSelectItem extends SQLSelectItem implements OdpsObject {\n    public OdpsUDTFSQLSelectItem() {\n        super.aliasList = new ArrayList<String>();\n    }\n\n    public void setAlias(String alias) {\n        throw new UnsupportedOperationException();\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OdpsASTVisitor) {\n            accept0((OdpsASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsUndoTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsUndoTableStatement\n        extends OdpsStatementImpl implements SQLAlterStatement {\n    private SQLExprTableSource table;\n    private List<SQLAssignItem> partitions = new ArrayList<>();\n    private SQLExpr to;\n\n    public OdpsUndoTableStatement() {\n        super.dbType = DbType.odps;\n    }\n\n    @Override\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, table);\n            this.acceptChild(visitor, partitions);\n            this.acceptChild(visitor, to);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(table);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n    }\n\n    public SQLExpr getTo() {\n        return to;\n    }\n\n    public void setTo(SQLExpr to) {\n        this.to = to;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsUnloadStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OdpsUnloadStatement extends SQLStatementImpl {\n    protected final List<SQLAssignItem> serdeProperties = new ArrayList<SQLAssignItem>();\n    protected final List<SQLAssignItem> properties = new ArrayList<SQLAssignItem>();\n    private final List<SQLAssignItem> partitions = new ArrayList<SQLAssignItem>();\n    protected SQLExpr location;\n    protected SQLExternalRecordFormat rowFormat;\n    protected SQLExpr storedAs;\n    private SQLTableSource from;\n\n    public OdpsUnloadStatement() {\n        super(DbType.odps);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OdpsASTVisitor) visitor);\n    }\n\n    protected void accept0(OdpsASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, from);\n            acceptChild(visitor, partitions);\n            acceptChild(visitor, location);\n            acceptChild(visitor, rowFormat);\n            acceptChild(visitor, storedAs);\n            acceptChild(visitor, properties);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLTableSource getFrom() {\n        return from;\n    }\n\n    public void setFrom(SQLName x) {\n        setFrom(\n                new SQLExprTableSource(x));\n    }\n\n    public void setFrom(SQLTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.from = x;\n    }\n\n    public List<SQLAssignItem> getPartitions() {\n        return partitions;\n    }\n\n    public SQLExpr getLocation() {\n        return location;\n    }\n\n    public void setLocation(SQLExpr location) {\n        this.location = location;\n    }\n\n    public SQLExternalRecordFormat getRowFormat() {\n        return rowFormat;\n    }\n\n    public void setRowFormat(SQLExternalRecordFormat x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.rowFormat = x;\n    }\n\n    public SQLExpr getStoredAs() {\n        return storedAs;\n    }\n\n    public void setStoredAs(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storedAs = x;\n    }\n\n    public List<SQLAssignItem> getSerdeProperties() {\n        return serdeProperties;\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.parser;\n\nimport com.alibaba.druid.sql.ast.ClusteringType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInputOutputFormat;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsCreateTableStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class OdpsCreateTableParser extends SQLCreateTableParser {\n    public OdpsCreateTableParser(String sql) {\n        super(new OdpsExprParser(sql));\n    }\n\n    public OdpsCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        OdpsCreateTableStatement stmt = new OdpsCreateTableStatement();\n\n        accept(Token.CREATE);\n\n        if (lexer.nextIf(Token.OR)) {\n            accept(Token.REPLACE);\n            stmt.config(SQLCreateTableStatement.Feature.OrReplace);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            lexer.nextToken();\n            stmt.setExternal(true);\n        }\n\n        accept(Token.TABLE);\n\n        if (lexer.token() == Token.IF || lexer.identifierEquals(\"IF\")) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            stmt.setComment(this.exprParser.primary());\n        }\n\n        if (lexer.token() == Token.SEMI || lexer.token() == Token.EOF) {\n            return stmt;\n        }\n\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n                parseOptions(stmt);\n\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextToken();\n                stmt.setLifeCycle(this.exprParser.expr());\n\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n                lexer.nextToken();\n                accept(Token.AS);\n\n                if (lexer.identifierEquals(FnvHash.Constants.INPUTFORMAT)) {\n                    HiveInputOutputFormat format = new HiveInputOutputFormat();\n                    lexer.nextToken();\n                    format.setInput(this.exprParser.primary());\n\n                    if (lexer.identifierEquals(FnvHash.Constants.OUTPUTFORMAT)) {\n                        lexer.nextToken();\n                        format.setOutput(this.exprParser.primary());\n                    }\n                    stmt.setStoredAs(format);\n                } else {\n                    SQLName name = this.exprParser.name();\n                    stmt.setStoredAs(name);\n                }\n\n                continue;\n            }\n\n            break;\n        }\n\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            SQLName name = this.exprParser.name();\n            stmt.setLike(name);\n        } else if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n\n            OdpsSelectParser selectParser = new OdpsSelectParser(this.exprParser);\n            SQLSelect select = selectParser.select();\n\n            stmt.setSelect(select);\n        } else if (lexer.token() != Token.LPAREN && stmt.isExternal()) {\n            // skip\n        } else {\n            accept(Token.LPAREN);\n\n            if (lexer.isKeepComments() && lexer.hasComment()) {\n                stmt.addBodyBeforeComment(lexer.readAndResetComments());\n            }\n\n            for (; ; ) {\n                SQLColumnDefinition column;\n                switch (lexer.token()) {\n                    case IDENTIFIER:\n                    case KEY:\n                    case SEQUENCE:\n                    case USER:\n                    case GROUP:\n                    case INDEX:\n                    case ENABLE:\n                    case DISABLE:\n                    case DESC:\n                    case ALL:\n                    case INTERVAL:\n                    case OPEN:\n                    case PARTITION:\n                    case SCHEMA:\n                    case CONSTRAINT:\n                    case COMMENT:\n                    case VIEW:\n                    case SHOW:\n                    case ORDER:\n                    case LEAVE:\n                    case UNIQUE:\n                    case DEFAULT:\n                    case EXPLAIN:\n                    case CHECK:\n                    case CLOSE:\n                    case IN:\n                    case OUT:\n                    case INOUT:\n                    case LIMIT:\n                    case FULL:\n                    case MINUS:\n                    case VALUES:\n                    case TRIGGER:\n                    case USE:\n                    case LIKE:\n                    case DISTRIBUTE:\n                    case DELETE:\n                    case UPDATE:\n                    case IS:\n                    case LEFT:\n                    case RIGHT:\n                    case REPEAT:\n                    case COMPUTE:\n                    case LOCK:\n                    case TABLE:\n                    case DO:\n                    case WHILE:\n                    case LOOP:\n                    case FOR:\n                    case RLIKE:\n                    case PROCEDURE:\n                    case GRANT:\n                    case EXCEPT:\n                    case CREATE:\n                    case PARTITIONED:\n                    case UNION:\n                    case PRIMARY:\n                    case INNER:\n                    case TO:\n                    case DECLARE:\n                    case REFERENCES:\n                    case FOREIGN:\n                    case ESCAPE:\n                    case BY:\n                    case ALTER:\n                    case SOME:\n                    case ASC:\n                    case NULL:\n                    case CURSOR:\n                    case FETCH:\n                    case OVER:\n                    case DATABASE:\n                    case FUNCTION:\n                        column = this.exprParser.parseColumn(stmt);\n                        break;\n                    default:\n                        throw new ParserException(\"expect identifier. \" + lexer.info());\n                }\n\n                stmt.addColumn(column);\n\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    column.addAfterComment(lexer.readAndResetComments());\n                }\n\n                if (!(lexer.token() == (Token.COMMA))) {\n                    break;\n                } else {\n                    lexer.nextToken();\n\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        column.addAfterComment(lexer.readAndResetComments());\n                    }\n                }\n            }\n            accept(Token.RPAREN);\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                stmt.setComment(this.exprParser.primary());\n                continue;\n            }\n\n            if (lexer.token() == Token.PARTITIONED) {\n                lexer.nextToken();\n                accept(Token.BY);\n                accept(Token.LPAREN);\n\n                for (; ; ) {\n                    switch (lexer.token()) {\n                        case INDEX:\n                        case KEY:\n                        case CHECK:\n                        case IDENTIFIER:\n                        case GROUP:\n                        case INTERVAL:\n                        case LOOP:\n                        case USER:\n                        case TABLE:\n                        case PARTITION:\n                        case SEQUENCE:\n                        case VARIANT:\n                            break;\n                        default:\n                            throw new ParserException(\"expect identifier. \" + lexer.info());\n                    }\n\n                    SQLColumnDefinition column = this.exprParser.parseColumn();\n                    stmt.addPartitionColumn(column);\n\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        column.addAfterComment(lexer.readAndResetComments());\n                    }\n\n                    if (lexer.token() != Token.COMMA) {\n                        break;\n                    } else {\n                        lexer.nextToken();\n                        if (lexer.isKeepComments() && lexer.hasComment()) {\n                            column.addAfterComment(lexer.readAndResetComments());\n                        }\n                    }\n                }\n\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"AUTO\")) {\n                accept(Token.PARTITIONED);\n                accept(Token.BY);\n                accept(Token.LPAREN);\n                stmt.setAutoPartitionedBy(\n                        this.exprParser.aliasedExpr());\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n                    stmt.setClusteringType(ClusteringType.Range);\n                }\n\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                    stmt.addClusteredByItem(item);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ROW)) {\n                SQLExternalRecordFormat recordFormat = this.exprParser.parseRowFormat();\n                stmt.setRowFormat(recordFormat);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.SORTED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                    stmt.addSortedByItem(item);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n\n                continue;\n            }\n\n            if (stmt.getClusteringType() != ClusteringType.Range &&\n                    (stmt.getClusteredBy().size() > 0 || stmt.getSortedBy().size() > 0) && lexer.token() == Token.INTO) {\n                lexer.nextToken();\n                if (lexer.token() == Token.LITERAL_INT) {\n                    stmt.setBuckets(lexer.integerValue().intValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"into buckets must be integer. \" + lexer.info());\n                }\n                acceptIdentifier(\"BUCKETS\");\n\n                if (lexer.token() == Token.INTO) {\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.LITERAL_INT) {\n                        stmt.setShards(lexer.integerValue().intValue());\n                        lexer.nextToken();\n                    } else {\n                        throw new ParserException(\"into shards must be integer. \" + lexer.info());\n                    }\n\n                    acceptIdentifier(\"SHARDS\");\n                }\n\n                continue;\n            }\n\n            if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LITERAL_INT) {\n                    stmt.setIntoBuckets(\n                            new SQLIntegerExpr(lexer.integerValue().intValue()));\n                    lexer.nextToken();\n                    acceptIdentifier(\"BUCKETS\");\n                } else {\n                    throw new ParserException(\"into shards must be integer. \" + lexer.info());\n                }\n                continue;\n            }\n\n            if (lexer.token() == Token.AS && stmt.getSelect() == null) {\n                lexer.nextToken();\n\n                OdpsSelectParser selectParser = new OdpsSelectParser(this.exprParser);\n                SQLSelect select = selectParser.select();\n\n                stmt.setSelect(select);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextToken();\n                stmt.setLifeCycle(this.exprParser.expr());\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.AS) {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.INPUTFORMAT)) {\n                        HiveInputOutputFormat format = new HiveInputOutputFormat();\n                        lexer.nextToken();\n                        format.setInput(this.exprParser.primary());\n\n                        if (lexer.identifierEquals(FnvHash.Constants.OUTPUTFORMAT)) {\n                            lexer.nextToken();\n                            format.setOutput(this.exprParser.primary());\n                        }\n                        stmt.setStoredAs(format);\n                    } else {\n                        SQLName storedAs = this.exprParser.name();\n                        stmt.setStoredAs(storedAs);\n                    }\n                } else {\n                    accept(Token.BY);\n                    SQLExpr storedBy = this.exprParser.expr();\n                    stmt.setStoredBy(storedBy);\n                }\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextToken();\n                stmt.setLifeCycle(this.exprParser.expr());\n                continue;\n            }\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"SERDEPROPERTIES\");\n                accept(Token.LPAREN);\n                this.exprParser.exprList(stmt.getWithSerdeproperties(), stmt);\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n                parseOptions(stmt);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LOCATION)) {\n                lexer.nextToken();\n                SQLExpr location = this.exprParser.expr();\n                stmt.setLocation(location);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n                parseOptions(stmt);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n                lexer.nextToken();\n                SQLExpr using = this.exprParser.expr();\n                stmt.setUsing(using);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextToken();\n                stmt.setLifeCycle(this.exprParser.expr());\n                continue;\n            }\n\n            break;\n        }\n\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSetStatement;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveExprParser;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsNewExpr;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsTransformExpr;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsUDTFSQLSelectItem;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class OdpsExprParser extends HiveExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"AVG\",\n                \"COUNT\",\n                \"LAG\",\n                \"LEAD\",\n                \"MAX\",\n                \"MIN\",\n                \"STDDEV\",\n                \"SUM\",\n                \"ROW_NUMBER\",\n                \"WM_CONCAT\",\n                \"STRAGG\",\n                \"COLLECT_LIST\",\n                \"COLLECT_SET\"//\n        };\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    @Override\n    protected SQLExpr primaryAs(SQLExpr sqlExpr) {\n        Lexer.SavePoint mark = lexer.mark();\n        String str = lexer.stringVal();\n        lexer.nextToken();\n        switch (lexer.token()) {\n            case COMMA:\n            case RPAREN:\n            case AS:\n            case EQ:\n            case EQEQ:\n            case LT:\n            case LTEQ:\n            case GT:\n            case GTEQ:\n            case LTGT:\n            case SEMI:\n                sqlExpr = new SQLIdentifierExpr(str);\n                break;\n            case DOT:\n                sqlExpr = primaryRest(\n                        new SQLIdentifierExpr(str)\n                );\n                break;\n            default:\n                lexer.reset(mark);\n                break;\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr primaryIn(SQLExpr sqlExpr) {\n        String str = lexer.stringVal();\n        lexer.nextToken();\n        switch (lexer.token()) {\n            case DOT:\n            case COMMA:\n            case LT:\n            case EQ:\n            case GT:\n            case RPAREN:\n            case IS:\n            case AS:\n                sqlExpr = new SQLIdentifierExpr(str);\n                break;\n            default:\n                break;\n        }\n        if (sqlExpr != null) {\n            return sqlExpr;\n        }\n\n        accept(Token.LPAREN);\n        SQLInListExpr in = new SQLInListExpr();\n        in.setExpr(\n                this.expr()\n        );\n        if (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n            this.exprList(in.getTargetList(), in);\n        }\n        accept(Token.RPAREN);\n        sqlExpr = in;\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr primaryColonColon(SQLExpr sqlExpr) {\n        lexer.nextToken();\n        SQLExpr temp = this.primary();\n        if (temp instanceof SQLArrayExpr) {\n            sqlExpr = temp;\n        } else {\n            SQLMethodInvokeExpr method = (SQLMethodInvokeExpr) temp;\n            method.setOwner(new SQLIdentifierExpr(\"\"));\n            sqlExpr = method;\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected void methodRestUsing(SQLMethodInvokeExpr methodInvokeExpr) {\n        if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n            lexer.nextToken();\n            SQLExpr using = this.primary();\n            methodInvokeExpr.setUsing(using);\n        }\n    }\n    protected String doRestSpecific(SQLExpr expr) {\n        String name = null;\n        if ((lexer.token() == Token.LITERAL_INT || lexer.token() == Token.LITERAL_FLOAT)) {\n            name = lexer.numberString();\n            lexer.nextToken();\n        } else if (lexer.token() == Token.DOT && expr.toString().equals(\"odps.sql.mapper\")) {\n                lexer.nextToken();\n                name = lexer.stringVal();\n                lexer.nextToken();\n        }\n        return name;\n    }\n\n    @Override\n    protected String nameCommon() {\n        String identName = lexer.stringVal();\n        lexer.nextToken();\n        return identName;\n    }\n\n    @Override\n    protected SQLExpr relationalRestBang(SQLExpr expr) {\n        lexer.nextToken();\n        return notRationalRest(expr, false);\n    }\n\n    @Override\n    protected void parseDataTypeComplex(StringBuilder typeName) {\n        if (lexer.token() == Token.LT && dbType == DbType.odps) {\n            lexer.nextToken();\n            typeName.append('<');\n            for (; ; ) {\n                SQLDataType itemType = this.parseDataType();\n                typeName.append(itemType.toString());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    typeName.append(\", \");\n                } else {\n                    break;\n                }\n            }\n            accept(Token.GT);\n            typeName.append('>');\n        }\n    }\n\n    @Override\n    protected void parseColumnCommentLiteralCharsRest(StringBuilder stringVal) {\n        for (; ; ) {\n            if (lexer.token() == Token.LITERAL_ALIAS) {\n                String tmp = lexer.stringVal();\n                if (tmp.length() > 2 && tmp.charAt(0) == '\"' && tmp.charAt(tmp.length() - 1) == '\"') {\n                    tmp = tmp.substring(1, tmp.length() - 1);\n                }\n\n                stringVal.append(tmp);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.LITERAL_CHARS) {\n                stringVal.append(lexer.stringVal());\n                lexer.nextToken();\n            } else {\n                break;\n            }\n        }\n    }\n\n    @Override\n    protected void parseAssignItemDot() {\n        if (lexer.token() == Token.DOT) {\n            lexer.nextToken();\n        }\n    }\n\n    @Override\n    protected void parseAssignItemNcToBeExecuted() {\n        if (lexer.identifierEquals(\"NC_TO_BE_EXECUTED\")) {\n            lexer.nextToken(); // skip\n        }\n    }\n\n    @Override\n    protected boolean parseAssignItemTblProperties(SQLAssignItem item) {\n        if (lexer.token() == Token.LPAREN) {\n            SQLListExpr list = new SQLListExpr();\n            this.exprList(list.getItems(), list);\n            item.setTarget(new SQLIdentifierExpr(\"tblproperties\"));\n            item.setValue(list);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    protected SQLExpr parseAssignItemSQLPropertyExprAndSub(SQLExpr sqlExpr) {\n        if (sqlExpr instanceof SQLPropertyExpr && lexer.token() == Token.SUB) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) sqlExpr;\n            String name = propertyExpr.getName() + '-';\n            lexer.nextToken();\n            if (lexer.token() == Token.IDENTIFIER) {\n                name += lexer.stringVal();\n                lexer.nextToken();\n            }\n            propertyExpr.setName(name);\n            return this.primaryRest(propertyExpr);\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected SQLExpr parseAssignItemSQLPropertyExpr(SQLExpr sqlExpr) {\n        if (sqlExpr instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) sqlExpr;\n\n            if (identifierEquals(\"DATEADD\")) {\n                String func = lexer.stringVal();\n                lexer.nextToken();\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    accept(Token.RPAREN);\n                    func += \"()\";\n                }\n\n                String name = propertyExpr.getName() + func;\n                propertyExpr.setName(name);\n            } else if (propertyExpr.getName().equalsIgnoreCase(\"enab\") && identifierEquals(\"le\")) {\n                String name = propertyExpr.getName() + lexer.stringVal();\n                lexer.nextToken();\n                propertyExpr.setName(name);\n            } else if (propertyExpr.getName().equalsIgnoreCase(\"sq\") && identifierEquals(\"l\")) {\n                String name = propertyExpr.getName() + lexer.stringVal();\n                lexer.nextToken();\n                propertyExpr.setName(name);\n            } else if (propertyExpr.getName().equalsIgnoreCase(\"s\") && identifierEquals(\"ql\")) {\n                String name = propertyExpr.getName() + lexer.stringVal();\n                lexer.nextToken();\n                propertyExpr.setName(name);\n                sqlExpr = this.primaryRest(propertyExpr);\n            } else if (lexer.token() == Token.BY) {\n                String name = propertyExpr.getName() + ' ' + lexer.stringVal();\n                lexer.nextToken();\n                propertyExpr.setName(name);\n                sqlExpr = this.primaryRest(propertyExpr);\n            }\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected boolean parseAssignItemSQLMethodInvokeExpr(SQLExpr sqlExpr, SQLAssignItem item) {\n        if (sqlExpr instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) sqlExpr;\n\n            SQLExpr owner = func.getOwner();\n            if (owner != null) {\n                item.setTarget(new SQLPropertyExpr(owner, func.getMethodName()));\n            } else {\n                item.setTarget(new SQLIdentifierExpr(func.getMethodName()));\n            }\n\n            SQLListExpr properties = new SQLListExpr();\n            for (SQLExpr argument : func.getArguments()) {\n                properties.addItem(argument);\n            }\n\n            item.setValue(properties);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    protected void parseAssignItemEq(SQLObject parent) {\n        if (parent instanceof SQLSetStatement || parent == null) {\n            lexer.nextTokenForSet();\n        } else {\n            lexer.nextToken();\n        }\n    }\n\n    @Override\n    protected void parseAssignItemSQLIdentifierExprAndVariant(SQLIdentifierExpr ident) {\n        if (lexer.identifierEquals(FnvHash.Constants.CLUSTER)\n                && ident.nameHashCode64() == FnvHash.Constants.RUNNING\n        ) {\n            String str = ident.getName() + \" \" + lexer.stringVal();\n            lexer.nextToken();\n            ident.setName(str);\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            ident.setName(ident.getName() + ' ' + lexer.stringVal());\n            lexer.nextToken();\n            while (lexer.token() == Token.IDENTIFIER) {\n                ident.setName(ident.getName() + ' ' + lexer.stringVal());\n                lexer.nextToken();\n            }\n        }\n    }\n    @Override\n    protected void parseAssignItemSQLIdentifierExpr(SQLExpr sqlExpr) {\n        if (sqlExpr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) sqlExpr;\n            if ((identExpr.getName().equalsIgnoreCase(\"et\")\n                    || identExpr.getName().equalsIgnoreCase(\"odps\")\n            )\n                    && lexer.token() == Token.IDENTIFIER) {\n                SQLExpr expr = this.primary();\n                identExpr.setName(\n                        identExpr.getName() + ' ' + expr.toString()\n                );\n            }\n        }\n    }\n\n    @Override\n    protected SQLExpr parseAssignItemOnLiteralFloat(SQLExpr sqlExpr) {\n        while (lexer.token() == Token.LITERAL_FLOAT && lexer.numberString().startsWith(\".\")) {\n            if (sqlExpr instanceof SQLNumberExpr) {\n                String numStr = String.valueOf(((SQLNumberExpr) sqlExpr).getValue());\n                numStr += lexer.numberString();\n                sqlExpr = new SQLIdentifierExpr(numStr);\n                lexer.nextToken();\n            } else if (sqlExpr instanceof SQLIdentifierExpr) {\n                String ident = ((SQLIdentifierExpr) sqlExpr).getName();\n                ident += lexer.numberString();\n                sqlExpr = new SQLIdentifierExpr(ident);\n                lexer.nextToken();\n            } else {\n                break;\n            }\n        }\n        return sqlExpr;\n    }\n\n    @Override\n    protected void parseAssignItemOnComma(SQLExpr sqlExpr, SQLAssignItem item, SQLObject parent) {\n        if (lexer.token() == Token.COMMA\n                && parent instanceof SQLSetStatement) {\n            SQLListExpr listExpr = new SQLListExpr();\n            listExpr.addItem(sqlExpr);\n            sqlExpr.setParent(listExpr);\n            do {\n                lexer.nextToken();\n                if (lexer.token() == Token.SET && dbType == DbType.odps) {\n                    break;\n                }\n                SQLExpr listItem = this.expr();\n                listItem.setParent(listExpr);\n                listExpr.addItem(listItem);\n            }\n            while (lexer.token() == Token.COMMA);\n            item.setValue(listExpr);\n        } else {\n            item.setValue(sqlExpr);\n        }\n    }\n\n    public OdpsExprParser(Lexer lexer) {\n        super(lexer);\n        this.dbType = DbType.odps;\n\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public OdpsExprParser(String sql, SQLParserFeature... features) {\n        this(new OdpsLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    protected SQLExpr parseAliasExpr(String alias) {\n        String chars = alias.substring(1, alias.length() - 1);\n        return new SQLCharExpr(chars);\n    }\n\n    static final long GSONBUILDER = FnvHash.fnv1a_64_lower(\"GSONBUILDER\");\n\n    @Override\n    public SQLSelectItem parseSelectItem() {\n        SQLExpr expr;\n        if (lexer.token() == Token.IDENTIFIER) {\n            String stringVal = lexer.stringVal();\n            long hash_lower = lexer.hashLCase();\n\n            int sourceLine = -1, sourceColumn = -1;\n            if (lexer.isKeepSourceLocation()) {\n                lexer.computeRowAndColumn();\n                sourceLine = lexer.getPosLine();\n                sourceColumn = lexer.getPosColumn();\n            }\n\n            lexer.nextTokenComma();\n\n            if (FnvHash.Constants.DATETIME == hash_lower\n                    && lexer.stringVal().charAt(0) != '`'\n                    && (lexer.token() == Token.LITERAL_CHARS\n                    || lexer.token() == Token.LITERAL_ALIAS)\n            ) {\n                String literal = lexer.stringVal();\n                lexer.nextToken();\n\n                SQLDateTimeExpr ts = new SQLDateTimeExpr(literal);\n                expr = ts;\n            } else if (FnvHash.Constants.DATE == hash_lower\n                    && lexer.stringVal().charAt(0) != '`'\n                    && (lexer.token() == Token.LITERAL_CHARS\n                    || lexer.token() == Token.LITERAL_ALIAS)\n            ) {\n                String literal = lexer.stringVal();\n                lexer.nextToken();\n\n                SQLDateExpr d = new SQLDateExpr(literal);\n                expr = d;\n            } else if (FnvHash.Constants.TIMESTAMP == hash_lower\n                    && lexer.stringVal().charAt(0) != '`'\n                    && (lexer.token() == Token.LITERAL_CHARS\n                    || lexer.token() == Token.LITERAL_ALIAS)\n            ) {\n                String literal = lexer.stringVal();\n                lexer.nextToken();\n\n                SQLTimestampExpr ts = new SQLTimestampExpr(literal);\n                expr = ts;\n            } else {\n                expr = new SQLIdentifierExpr(stringVal);\n                if (lexer.token() != Token.COMMA) {\n                    expr = this.primaryRest(expr);\n                    expr = this.exprRest(expr);\n                }\n            }\n\n            if (sourceLine != -1) {\n                expr.setSource(sourceLine, sourceColumn);\n            }\n        } else {\n            expr = expr();\n        }\n\n        String alias = null;\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n\n                OdpsUDTFSQLSelectItem selectItem = new OdpsUDTFSQLSelectItem();\n\n                selectItem.setExpr(expr);\n\n                for (; ; ) {\n                    alias = lexer.stringVal();\n                    lexer.nextToken();\n\n                    selectItem.getAliasList().add(alias);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n\n                accept(Token.RPAREN);\n\n                return selectItem;\n            } else {\n                alias = alias();\n            }\n        } else {\n            alias = as();\n        }\n\n        SQLSelectItem item = new SQLSelectItem(expr, alias);\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            item.addAfterComment(lexer.readAndResetComments());\n        }\n\n        return item;\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (lexer.token() == Token.COLON) {\n            lexer.nextToken();\n            if (lexer.token() == Token.LITERAL_INT && expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n                Number integerValue = lexer.integerValue();\n                lexer.nextToken();\n                propertyExpr.setName(propertyExpr.getName() + ':' + integerValue.intValue());\n                return propertyExpr;\n            }\n            expr = dotRest(expr);\n            if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr spe = (SQLPropertyExpr) expr;\n                spe.setSplitString(\":\");\n            }\n            return expr;\n        }\n\n        if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            array.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            return primaryRest(array);\n        } else if ((lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS) && expr instanceof SQLCharExpr) {\n            SQLCharExpr charExpr = new SQLCharExpr(lexer.stringVal());\n            lexer.nextTokenValue();\n            SQLMethodInvokeExpr concat = new SQLMethodInvokeExpr(\"concat\", null, expr, charExpr);\n\n            while (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS) {\n                charExpr = new SQLCharExpr(lexer.stringVal());\n                lexer.nextToken();\n                concat.addArgument(charExpr);\n            }\n\n            expr = concat;\n        }\n\n        if (lexer.token() == Token.LPAREN\n                && expr instanceof SQLIdentifierExpr\n                && ((SQLIdentifierExpr) expr).nameHashCode64() == FnvHash.Constants.TRANSFORM) {\n            String name = lexer.stringVal();\n            OdpsTransformExpr transformExpr = new OdpsTransformExpr();\n            lexer.nextToken();\n            List<SQLExpr> inputColumns = transformExpr.getInputColumns();\n            this.exprList(inputColumns, transformExpr);\n            accept(Token.RPAREN);\n\n            if (inputColumns.size() == 2\n                    && inputColumns.get(1) instanceof SQLBinaryOpExpr\n                    && ((SQLBinaryOpExpr) inputColumns.get(1)).getOperator() == SQLBinaryOperator.SubGt\n            ) {\n                SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(name);\n                for (SQLExpr item : inputColumns) {\n                    methodInvokeExpr.addArgument(item);\n                }\n                return primaryRest(methodInvokeExpr);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ROW)) {\n                SQLExternalRecordFormat recordFormat = this.parseRowFormat();\n                transformExpr.setInputRowFormat(recordFormat);\n            }\n\n            if (lexer.token() == Token.USING || lexer.identifierEquals(FnvHash.Constants.USING)) {\n                lexer.nextToken();\n                transformExpr.setUsing(this.expr());\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.RESOURCES)) {\n                lexer.nextToken();\n                this.exprList(transformExpr.getResources(), transformExpr);\n            }\n\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n                List<SQLColumnDefinition> outputColumns = transformExpr.getOutputColumns();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    for (; ; ) {\n                        SQLColumnDefinition column = this.parseColumn();\n                        outputColumns.add(column);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                } else {\n                    SQLColumnDefinition column = new SQLColumnDefinition();\n                    column.setName(this.name());\n                    outputColumns.add(column);\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ROW)) {\n                SQLExternalRecordFormat recordFormat = this.parseRowFormat();\n                transformExpr.setOutputRowFormat(recordFormat);\n            }\n\n            return transformExpr;\n        }\n\n        if (expr instanceof SQLIdentifierExpr\n                && ((SQLIdentifierExpr) expr).nameHashCode64() == FnvHash.Constants.NEW) {\n            SQLIdentifierExpr ident = (SQLIdentifierExpr) expr;\n            Lexer.SavePoint savePoint = lexer.markOut();\n\n            OdpsNewExpr newExpr = new OdpsNewExpr();\n            if (lexer.token() == Token.IDENTIFIER) { //.GSON\n                Lexer.SavePoint mark = lexer.mark();\n\n                StringBuilder methodName = new StringBuilder(lexer.stringVal());\n                lexer.nextToken();\n                switch (lexer.token()) {\n                    case ON:\n                    case WHERE:\n                    case GROUP:\n                    case ORDER:\n                    case INNER:\n                    case JOIN:\n                    case FULL:\n                    case OUTER:\n                    case LEFT:\n                    case RIGHT:\n                    case LATERAL:\n                    case FROM:\n                    case COMMA:\n                    case RPAREN:\n                        return ident;\n                    default:\n                        break;\n                }\n\n                while (lexer.token() == Token.DOT) {\n                    lexer.nextToken();\n                    methodName.append('.').append(lexer.stringVal());\n                    lexer.nextToken();\n                }\n\n                newExpr.setMethodName(methodName.toString());\n\n                if (lexer.token() == Token.LT) {\n                    lexer.nextToken();\n                    for (; ; ) {\n                        if (lexer.token() == Token.GT) {\n                            break;\n                        }\n                        SQLDataType paramType = this.parseDataType(false);\n                        paramType.setParent(newExpr);\n                        newExpr.getTypeParameters().add(paramType);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.GT);\n                }\n\n                if (lexer.token() == Token.LBRACKET) {\n                    lexer.nextToken();\n                    this.exprList(newExpr.getArguments(), newExpr);\n                    accept(Token.RBRACKET);\n                    if (lexer.token() == Token.LBRACKET) {\n                        lexer.nextToken();\n                        accept(Token.RBRACKET);\n                    }\n                    newExpr.setArray(true);\n\n                    if (lexer.token() == Token.LBRACE) {\n                        lexer.nextToken();\n                        for (; ; ) {\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            }\n\n                            SQLExpr item = this.expr();\n                            newExpr.getInitValues().add(item);\n                            item.setParent(newExpr);\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                            break;\n                        }\n                        accept(Token.RBRACE);\n                    }\n                    if (lexer.token() == Token.LBRACKET) {\n                        expr = primaryRest(newExpr);\n                    } else {\n                        expr = newExpr;\n                    }\n                } else if (lexer.token() != Token.LPAREN) {\n                    lexer.reset(savePoint);\n                    return ident;\n                } else {\n                    accept(Token.LPAREN);\n                    this.exprList(newExpr.getArguments(), newExpr);\n                    accept(Token.RPAREN);\n                    expr = newExpr;\n                }\n            } else if (lexer.identifierEquals(\"java\") || lexer.identifierEquals(\"com\")) {\n                SQLName name = this.name();\n                StringBuilder strName = new StringBuilder();\n                strName.append(ident.getName()).append(' ').append(name.toString());\n                if (lexer.token() == Token.LT) {\n                    lexer.nextToken();\n                    for (int i = 0; lexer.token() != Token.GT; i++) {\n                        if (i != 0) {\n                            strName.append(\", \");\n                        }\n                        SQLName arg = this.name();\n                        strName.append(arg.toString());\n                    }\n                    lexer.nextToken();\n                }\n                ident.setName(strName.toString());\n            }\n        }\n\n        if (expr == null) {\n            return null;\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    public SQLExpr relationalRest(SQLExpr expr) {\n        if (lexer.identifierEquals(\"REGEXP\")) {\n            lexer.nextToken();\n            SQLExpr rightExp = bitOr();\n\n            rightExp = relationalRest(rightExp);\n\n            return new SQLBinaryOpExpr(expr, SQLBinaryOperator.RegExp, rightExp, dbType);\n        }\n\n        return super.relationalRest(expr);\n    }\n\n    @Override\n    public OdpsSelectParser createSelectParser() {\n        return new OdpsSelectParser(this);\n    }\n\n    @Override\n    protected SQLExpr relationalRestEqeq(SQLExpr expr) {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n        SQLExpr rightExp;\n        try {\n            if (lexer.token() == Token.SEMI) {\n                lexer.reset(mark);\n                return expr;\n            }\n            rightExp = bitOr();\n        } catch (EOFParserException e) {\n            throw new ParserException(\"EOF, \" + expr + \"=\", e);\n        }\n\n        if (lexer.token() == Token.COLONEQ) {\n            lexer.nextToken();\n            SQLExpr colonExpr = expr();\n            rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType);\n        }\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) {\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            long hashCode64 = identifierExpr.hashCode64();\n            if (hashCode64 == FnvHash.Constants.STRUCT && acceptLPAREN) {\n                SQLStructExpr struct = struct();\n                if (lexer.isKeepSourceLocation()) {\n                    struct.setSource(identifierExpr.getSourceLine(), identifierExpr.getSourceColumn());\n                }\n                return struct;\n            }\n        }\n        return super.methodRest(expr, acceptLPAREN);\n    }\n\n    @Override\n    public SQLName name() {\n        SQLObject locationHolder = null;\n        if (lexer.isKeepSourceLocation()) {\n            locationHolder = new SQLIdentifierExpr(\"temp\");\n            lexer.computeRowAndColumn(locationHolder);\n        }\n\n        SQLName name = super.name();\n\n        if (locationHolder != null) {\n            name.setSource(locationHolder.getSourceLine(), locationHolder.getSourceColumn());\n        }\n\n        return name;\n    }\n\n    protected SQLExpr relationalRestVariant(SQLExpr expr) {\n        return expr;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveLexer;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.*;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.*;\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;\n\npublic class OdpsLexer extends HiveLexer {\n    static final Keywords ODPS_KEYWORDS;\n    static final DialectFeature ODPS_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    ScanSQLTypeBlockComment,\n                    ScanSQLTypeWithSemi,\n                    ScanSQLTypeWithFunction,\n                    ScanSQLTypeWithBegin,\n                    ScanSQLTypeWithAt,\n                    ScanVariableAt,\n                    ScanVariableMoveToSemi,\n                    ScanVariableSkipIdentifiers,\n                    ScanNumberCommonProcess,\n                    ScanHiveCommentDoubleSpace,\n                    QueryRestSemi,\n                    JoinAt,\n                    UserDefinedJoin,\n                    TwoConsecutiveUnion,\n                    RewriteGroupByCubeRollupToFunction,\n                    PrimaryTwoConsecutiveSet,\n                    ParseAllIdentifier,\n                    PrimaryRestCommaAfterLparen,\n                    InRestSpecificOperation,\n                    ParseAssignItemEqSemiReturn,\n                    ParseAssignItemEqeq,\n                    ParseStatementListLparenContinue,\n                    ParseRevokeFromUser,\n                    ParseCreateSql,\n                    TableAliasConnectWhere,\n                    TableAliasTable,\n                    TableAliasBetween,\n                    TableAliasRest,\n                    AliasLiteralFloat,\n                    ScanSQLTypeWithFrom,\n                    NextTokenColon,\n                    ScanAliasU,\n                    JoinRightTableFrom,\n                    GroupByAll,\n                    SQLDateExpr,\n                    ParseAssignItemRparenCommaSetReturn,\n                    TableAliasLock,\n                    TableAliasPartition,\n                    AsSkip,\n                    AsSequence,\n                    AsDatabase,\n                    AsDefault\n            ),\n            Arrays.asList(\n                    ParseStatementListSelectUnsupportedSyntax,\n                    ScanNumberPrefixB,\n                    ScanAliasU,\n                    AcceptUnion,\n                    PrimaryBangBangSupport\n            )\n    );\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"PARTITIONED\", Token.PARTITIONED);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n        map.put(\"OVER\", Token.OVER);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"IF\", Token.IF);\n        map.put(\"DISTRIBUTE\", Token.DISTRIBUTE);\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"RLIKE\", Token.RLIKE);\n        map.put(\"DIV\", Token.DIV);\n        map.put(\"LATERAL\", Token.LATERAL);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"；\", Token.SEMI);\n\n        ODPS_KEYWORDS = new Keywords(map);\n    }\n    public OdpsLexer(String input, SQLParserFeature... features) {\n        super(input);\n\n        init();\n\n        dbType = DbType.odps;\n        this.skipComment = true;\n        this.keepComments = false;\n\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return ODPS_KEYWORDS;\n    }\n\n    private void init() {\n        if (ch == '】' || ch == ' ' || ch == '，' || ch == '：' || ch == '、' || ch == '\\u200C' || ch == '；') {\n            ch = charAt(++pos);\n        }\n\n        if (ch == '上' && charAt(pos + 1) == '传') {\n            pos += 2;\n            ch = charAt(pos);\n\n            while (isWhitespace(ch)) {\n                ch = charAt(++pos);\n            }\n        }\n    }\n\n    public void scanIdentifier() {\n        hashLCase = 0;\n        hash = 0;\n\n        final char first = ch;\n\n        if (first == '`') {\n            mark = pos;\n            bufPos = 1;\n            char ch;\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (ch == '`') {\n                    bufPos++;\n                    ch = charAt(++pos);\n                    if (ch == '`') {\n                        ch = charAt(++pos);\n                        continue;\n                    }\n                    break;\n                } else if (ch == EOI) {\n                    throw new ParserException(\"illegal identifier. \" + info());\n                }\n\n                bufPos++;\n                continue;\n            }\n\n            this.ch = charAt(pos);\n\n            stringVal = subString(mark, bufPos);\n            token = Token.IDENTIFIER;\n\n            return;\n        }\n\n        final boolean firstFlag = isFirstIdentifierChar(first)\n                || ch == 'å'\n                || ch == 'ß'\n                || ch == 'ç';\n        if (!firstFlag) {\n            throw new ParserException(\"illegal identifier. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n        char ch;\n        for (; ; ) {\n            ch = charAt(++pos);\n\n            if (ch != 'ó'\n                    && ch != 'å'\n                    && ch != 'é'\n                    && ch != 'í'\n                    && ch != 'ß'\n                    && ch != 'ü'\n                    && !isIdentifierChar(ch)) {\n                if (ch == '{' && charAt(pos - 1) == '$') {\n                    int endIndex = this.text.indexOf('}', pos);\n                    if (endIndex != -1) {\n                        bufPos += (endIndex - pos + 1);\n                        pos = endIndex;\n                        continue;\n                    }\n                }\n\n                if (ch == '-'\n                        && bufPos > 7\n                        && text.regionMatches(false, mark, \"ALIYUN$\", 0, 7)) {\n                    continue;\n                }\n                break;\n            }\n\n            if (ch == ';') {\n                break;\n            }\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        if (ch == '@') { // for user identifier\n            bufPos++;\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (ch != '-' && ch != '.' && !isIdentifierChar(ch)) {\n                    break;\n                }\n\n                bufPos++;\n                continue;\n            }\n        }\n        this.ch = charAt(pos);\n\n        // bufPos\n        {\n            final int LEN = \"USING#CODE\".length();\n            if (bufPos == LEN && text.regionMatches(mark, \"USING#CODE\", 0, LEN)) {\n                bufPos = \"USING\".length();\n                pos -= 5;\n                this.ch = charAt(pos);\n            }\n        }\n\n        stringVal = addSymbol();\n        Token tok = keywords.getKeyword(stringVal);\n        if (tok != null) {\n            token = tok;\n        } else {\n            token = Token.IDENTIFIER;\n        }\n    }\n\n    public void scanVariable() {\n        if (ch == ':') {\n            token = Token.COLON;\n            ch = charAt(++pos);\n            return;\n        }\n\n        if (ch == '#'\n                && (charAt(pos + 1) == 'C' || charAt(pos + 1) == 'c')\n                && (charAt(pos + 2) == 'O' || charAt(pos + 2) == 'o')\n                && (charAt(pos + 3) == 'D' || charAt(pos + 3) == 'd')\n                && (charAt(pos + 4) == 'E' || charAt(pos + 4) == 'e')\n        ) {\n            int p1 = text.indexOf(\"#END CODE\", pos + 1);\n            int p2 = text.indexOf(\"#end code\", pos + 1);\n            if (p1 == -1) {\n                p1 = p2;\n            } else if (p1 > p2 && p2 != -1) {\n                p1 = p2;\n            }\n\n            if (p1 != -1) {\n                int end = p1 + \"#END CODE\".length();\n                stringVal = text.substring(pos, end);\n                token = Token.CODE;\n                pos = end;\n                ch = charAt(pos);\n                return;\n            }\n        }\n\n        super.scanVariable();\n    }\n\n    protected void scanVariable_at() {\n        scanVariable();\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = ODPS_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class OdpsSelectParser extends SQLSelectParser {\n    public OdpsSelectParser(SQLExprParser exprParser) {\n        super(exprParser.getLexer());\n        this.exprParser = exprParser;\n    }\n\n    public OdpsSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser.getLexer());\n        this.exprParser = exprParser;\n        this.selectListCache = selectListCache;\n    }\n\n    protected SQLSelectQueryBlock createSelectQueryBlock() {\n        return new OdpsSelectQueryBlock();\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            accept(Token.RPAREN);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        OdpsSelectQueryBlock queryBlock = new OdpsSelectQueryBlock();\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.FROM) {\n            parseFrom(queryBlock);\n            parseWhere(queryBlock);\n            parseGroupBy(queryBlock);\n\n            if (lexer.token() == Token.SELECT) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.HINT) {\n                    this.exprParser.parseHints(queryBlock.getHints());\n                }\n\n                if (lexer.token() == Token.COMMENT) {\n                    lexer.nextToken();\n                }\n\n                if (lexer.token() == Token.DISTINCT) {\n                    queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.UNIQUE) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token() == Token.DOT) {\n                        lexer.reset(mark);\n                    } else {\n                        queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n                    }\n                } else if (lexer.token() == Token.ALL) {\n                    String str = lexer.stringVal();\n                    lexer.nextToken();\n                    queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                }\n\n                parseSelectList(queryBlock);\n            }\n\n            if (queryBlock.getWhere() == null && lexer.token() == Token.WHERE) {\n                parseWhere(queryBlock);\n            }\n        } else {\n            accept(Token.SELECT);\n\n            if (lexer.token() == Token.HINT) {\n                this.exprParser.parseHints(queryBlock.getHints());\n            }\n\n            if (lexer.token() == Token.COMMENT) {\n                Lexer.SavePoint mark = lexer.mark();\n\n                String tokenStr = lexer.stringVal();\n                lexer.nextToken();\n                if (lexer.token() == Token.COMMA) {\n                    SQLIdentifierExpr expr = new SQLIdentifierExpr(tokenStr);\n                    queryBlock.addSelectItem(expr);\n                    lexer.nextToken();\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n\n            if (queryBlock.getSelectList().isEmpty()) {\n                if (lexer.token() == Token.DISTINCT) {\n                    queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.UNIQUE) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token() == Token.DOT || lexer.token() == Token.COMMA) {\n                        lexer.reset(mark);\n                    } else {\n                        queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n                    }\n                } else if (lexer.token() == Token.ALL) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    switch (lexer.token()) {\n                        case DOT:\n                        case COMMA:\n                        case SUB:\n                        case PLUS:\n                        case SLASH:\n                        case GT:\n                        case GTEQ:\n                        case EQ:\n                        case LT:\n                        case LTEQ:\n                            lexer.reset(mark);\n                            break;\n                        default:\n                            queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                            break;\n                    }\n                }\n            }\n\n            parseSelectList(queryBlock);\n\n            parseFrom(queryBlock);\n            if (queryBlock.getFrom() == null && lexer.token() == Token.LATERAL) {\n                lexer.nextToken();\n                SQLTableSource tableSource = this.parseLateralView(null);\n                queryBlock.setFrom(tableSource);\n            }\n\n            parseWhere(queryBlock);\n            parseGroupBy(queryBlock);\n        }\n\n        parseGroupBy(queryBlock);\n\n        if (lexer.identifierEquals(FnvHash.Constants.WINDOW)) {\n            parseWindow(queryBlock);\n        }\n\n        if (lexer.token() == Token.QUALIFY) {\n            lexer.nextToken();\n            SQLExpr qualify = this.exprParser.expr();\n            queryBlock.setQualify(qualify);\n        }\n\n        queryBlock.setOrderBy(this.exprParser.parseOrderBy());\n        queryBlock.setZOrderBy(this.exprParser.parseZOrderBy());\n\n        if (lexer.token() == Token.DISTRIBUTE) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            for (; ; ) {\n                SQLSelectOrderByItem distributeByItem = this.exprParser.parseSelectOrderByItem();\n                queryBlock.addDistributeBy(distributeByItem);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ZORDER)) {\n            queryBlock.setZOrderBy(this.exprParser.parseZOrderBy());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SORT)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            for (; ; ) {\n                SQLSelectOrderByItem sortByItem = this.exprParser.parseSelectOrderByItem();\n                queryBlock.addSortBy(sortByItem);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CLUSTER)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            for (; ; ) {\n                SQLSelectOrderByItem clusterByItem = this.exprParser.parseSelectOrderByItem();\n                queryBlock.addClusterBy(clusterByItem);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (lexer.token() == Token.LIMIT) {\n            SQLLimit limit = exprParser.parseLimit();\n            queryBlock.setLimit(limit);\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    public SQLTableSource parseTableSource() {\n        if (lexer.token() == Token.NULL) {\n            String str = lexer.stringVal();\n            lexer.nextToken();\n            return new SQLExprTableSource(new SQLIdentifierExpr(str));\n        }\n        SQLTableSource tableSource = super.parseTableSource();\n\n        if (lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(tableSource.getHints());\n        }\n\n        if (lexer.token() == Token.TABLE && tableSource.getAlias() == null) {\n            tableSource.setAlias(\n                    lexer.stringVal()\n            );\n            lexer.nextToken();\n\n            if (tableSource instanceof SQLLateralViewTableSource) {\n                if (lexer.token() == Token.AS) {\n                    parseLateralViewAs((SQLLateralViewTableSource) tableSource);\n                }\n            }\n\n            tableSource = parseTableSourceRest(tableSource);\n        }\n\n        return tableSource;\n    }\n\n    protected SQLTableSource primaryTableSourceRest(SQLTableSource tableSource) {\n        if (lexer.identifierEquals(FnvHash.Constants.LATERAL) || lexer.token() == Token.LATERAL) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token() == Token.VIEW) {\n                tableSource = parseLateralView(tableSource);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n        return tableSource;\n    }\n\n    public void parseTableSourceSample(SQLTableSource tableSource) {\n        parseTableSourceSampleHive(tableSource);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateFunctionStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveLoadDataStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlKillStatement;\nimport com.alibaba.druid.sql.dialect.odps.ast.*;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.COMMA;\nimport static com.alibaba.druid.sql.parser.Token.IDENTIFIER;\nimport static com.alibaba.druid.sql.parser.Token.LPAREN;\nimport static com.alibaba.druid.sql.parser.Token.ON;\nimport static com.alibaba.druid.sql.parser.Token.OVERWRITE;\nimport static com.alibaba.druid.sql.parser.Token.PARTITION;\nimport static com.alibaba.druid.sql.parser.Token.RPAREN;\n\npublic class OdpsStatementParser extends HiveStatementParser {\n    public OdpsStatementParser(String sql) {\n        super(new OdpsExprParser(sql));\n        dbType = DbType.odps;\n    }\n\n    public OdpsStatementParser(String sql, SQLParserFeature... features) {\n        super(new OdpsExprParser(sql, features));\n        dbType = DbType.odps;\n    }\n\n    public OdpsStatementParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.odps;\n    }\n\n    public SQLSelectStatement parseSelect() {\n        SQLSelect select = new OdpsSelectParser(this.exprParser)\n                .select();\n\n//        if (select.getWithSubQuery() == null && select.getQuery() instanceof SQLSelectQueryBlock) {\n//            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) select.getQuery();\n//            if (queryBlock.getFrom() == null && queryBlock.getWhere() != null) {\n//                throw new ParserException(\"none from query not support where clause.\");\n//            }\n//        }\n\n        return new SQLSelectStatement(select, DbType.odps);\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        SQLCreateTableParser parser = new OdpsCreateTableParser(this.exprParser);\n        return parser.parseCreateTable();\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new OdpsCreateTableParser(this.exprParser);\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.token() == Token.FROM) {\n            SQLStatement stmt = this.parseInsert();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"ANALYZE\")) {\n            SQLStatement stmt = parseAnalyze();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"ADD\")) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"STATISTIC\")) {\n                lexer.nextToken();\n                OdpsAddStatisticStatement stmt = new OdpsAddStatisticStatement();\n                stmt.setTable(this.exprParser.name());\n                stmt.setStatisticClause(parseStaticClause());\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.token() == Token.USER) {\n                lexer.nextToken();\n                OdpsAddUserStatement stmt = new OdpsAddUserStatement();\n                stmt.setUser(this.exprParser.name());\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(\"ACCOUNTPROVIDER\")) {\n                lexer.nextToken();\n                OdpsAddAccountProviderStatement stmt = new OdpsAddAccountProviderStatement();\n                stmt.setProvider(this.exprParser.name());\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.token() == Token.TABLE) {\n                lexer.nextToken();\n                OdpsAddTableStatement stmt = new OdpsAddTableStatement();\n                stmt.setTable(this.exprParser.name());\n\n                if (lexer.token() == Token.PARTITION) {\n                    lexer.nextToken();\n                    this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n                }\n\n                if (lexer.token() == Token.AS) {\n                    lexer.nextToken();\n                    SQLName name = this.exprParser.name();\n                    stmt.getTable().setAlias(name.toString());\n                }\n\n                if (lexer.token() == Token.COMMENT) {\n                    lexer.nextToken();\n                    stmt.setComment(this.exprParser.primary());\n                }\n\n                if (lexer.token() == Token.SUB) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"f\");\n                    stmt.setForce(true);\n                }\n\n                if (lexer.token() == Token.TO) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"PACKAGE\");\n                    SQLName packageName = this.exprParser.name();\n                    stmt.setToPackage(packageName);\n\n                    if (lexer.token() == Token.WITH) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"PRIVILEGES\");\n                        parsePrivilege(stmt.getPrivileges(), stmt);\n                    }\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.FILE)\n                    || lexer.identifierEquals(FnvHash.Constants.JAR)\n                    || lexer.identifierEquals(FnvHash.Constants.PY)\n                    || lexer.identifierEquals(FnvHash.Constants.ARCHIVE)) {\n                OdpsAddFileStatement stmt = new OdpsAddFileStatement();\n\n                long hash = lexer.hashLCase();\n                if (hash == FnvHash.Constants.JAR) {\n                    stmt.setType(OdpsAddFileStatement.FileType.JAR);\n                } else if (hash == FnvHash.Constants.PY) {\n                    stmt.setType(OdpsAddFileStatement.FileType.PY);\n                } else if (hash == FnvHash.Constants.ARCHIVE) {\n                    stmt.setType(OdpsAddFileStatement.FileType.ARCHIVE);\n                }\n\n                lexer.nextPath();\n                String path = lexer.stringVal();\n\n                lexer.nextToken();\n\n                stmt.setFile(path);\n\n                if (lexer.token() == Token.AS) {\n                    lexer.nextToken();\n                    SQLName name = this.exprParser.name();\n                    stmt.setAlias(name.toString());\n                }\n\n                if (lexer.token() == Token.COMMENT) {\n                    lexer.nextToken();\n                    stmt.setComment(this.exprParser.primary());\n                }\n\n                if (lexer.token() == Token.SUB) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"f\");\n                    stmt.setForce(true);\n                }\n                statementList.add(stmt);\n                return true;\n            }\n\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n\n        if (lexer.identifierEquals(\"REMOVE\")) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"STATISTIC\")) {\n                lexer.nextToken();\n                OdpsRemoveStatisticStatement stmt = new OdpsRemoveStatisticStatement();\n                stmt.setTable(this.exprParser.name());\n                stmt.setStatisticClause(parseStaticClause());\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.token() == Token.USER) {\n                lexer.nextToken();\n                OdpsRemoveUserStatement stmt = new OdpsRemoveUserStatement();\n                stmt.setUser((SQLIdentifierExpr) this.exprParser.name());\n                statementList.add(stmt);\n                return true;\n            }\n\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n\n        if (lexer.identifierEquals(\"READ\")) {\n            OdpsReadStatement stmt = new OdpsReadStatement();\n\n            if (lexer.hasComment() && lexer.isKeepComments()) {\n                stmt.addBeforeComment(lexer.readAndResetComments());\n            }\n            lexer.nextToken();\n\n            stmt.setTable(this.exprParser.name());\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                this.exprParser.names(stmt.getColumns(), stmt);\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n\n                accept(Token.LPAREN);\n                parseAssignItems(stmt.getPartition(), stmt);\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.LITERAL_INT) {\n                stmt.setRowCount(this.exprParser.primary());\n            }\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"LIST\")) {\n            OdpsListStmt stmt = new OdpsListStmt();\n\n            lexer.nextToken();\n            stmt.setObject(this.exprParser.expr());\n\n            if (lexer.identifierEquals(\"ROLES\")\n                    && stmt.getObject() instanceof SQLIdentifierExpr && ((SQLIdentifierExpr) stmt.getObject()).nameEquals(\"TENANT\")) {\n                lexer.nextToken();\n                stmt.setObject(new SQLIdentifierExpr(\"TENANT ROLES\"));\n            } else if (lexer.identifierEquals(\"OUTPUT\")\n                    && stmt.getObject() instanceof SQLIdentifierExpr && ((SQLIdentifierExpr) stmt.getObject()).nameEquals(\"TEMPORARY\")) {\n                lexer.nextToken();\n                stmt.setObject(new SQLIdentifierExpr(\"TEMPORARY OUTPUT\"));\n            }\n\n            statementList.add(stmt);\n\n            return true;\n        }\n\n        if (lexer.token() == Token.DESC || lexer.identifierEquals(\"DESCRIBE\")) {\n            SQLStatement stmt = parseDescribe();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"WHOAMI\")) {\n            lexer.nextToken();\n            SQLWhoamiStatement stmt = new SQLWhoamiStatement();\n            stmt.setDbType(DbType.odps);\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"COUNT\")) {\n            lexer.nextToken();\n            OdpsCountStatement stmt = new OdpsCountStatement();\n            stmt.setTable(this.exprParser.name());\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n            }\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"MSCK\")) {\n            SQLStatement stmt = parseMsck();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"alias\")) {\n            SQLStatement stmt = parseSet();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"EXSTORE\")) {\n            lexer.nextToken();\n            OdpsExstoreStatement stmt = new OdpsExstoreStatement();\n            SQLExpr table = this.exprParser.expr();\n            stmt.setTable(new SQLExprTableSource(table));\n            accept(Token.PARTITION);\n            this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"INSTALL\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"PACKAGE\");\n            OdpsInstallPackageStatement stmt = new OdpsInstallPackageStatement();\n            stmt.setPackageName(\n                    this.exprParser.name()\n            );\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"PAI\")) {\n            lexer.nextToken();\n            int semiPos = lexer.text.indexOf(';', lexer.pos());\n            while (semiPos != -1 && semiPos + 2 < lexer.text.length()) {\n                char next = lexer.text.charAt(semiPos + 1);\n                if (next == '\"' || next == '\\'') {\n                    semiPos = lexer.text.indexOf(';', semiPos + 1);\n                    continue;\n                }\n                break;\n            }\n            String arguments;\n            if (semiPos != -1) {\n                int count = semiPos - lexer.pos();\n                arguments = lexer.subString(lexer.pos(), count);\n                lexer.reset(semiPos);\n            } else {\n                arguments = lexer.subString(lexer.pos());\n                lexer.reset(lexer.text.length());\n            }\n            lexer.nextToken();\n\n            OdpsPAIStmt stmt = new OdpsPAIStmt();\n            stmt.setArguments(arguments);\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"COPY\")) {\n            SQLStatement stmt = parseCopy();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.KILL)) {\n            SQLStatement stmt = parseKill();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOAD)) {\n            HiveLoadDataStatement stmt = parseLoad();\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.MERGE)) {\n            SQLStatement stmt = parseMerge();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CLONE)) {\n            SQLStatement stmt = parseClone();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.UNLOAD)) {\n            SQLStatement stmt = parseUnload();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.BEGIN)) {\n            SQLStatement stmt = parseBlock();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RESTORE)) {\n            lexer.nextToken();\n            accept(Token.TABLE);\n            OdpsRestoreStatement stmt = new OdpsRestoreStatement();\n            stmt.setTable(this.exprParser.name());\n\n            if (lexer.token() == Token.LPAREN) {\n                this.exprParser.parseAssignItem(stmt.getProperties(), stmt);\n            }\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n            }\n\n            if (lexer.token() == Token.TO) {\n                lexer.nextToken();\n                acceptIdentifier(\"LSN\");\n                stmt.setTo(\n                        this.exprParser.expr()\n                );\n            }\n\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n                stmt.setAlias(\n                        this.alias()\n                );\n            }\n\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.UNDO)) {\n            lexer.nextToken();\n            accept(Token.TABLE);\n            OdpsUndoTableStatement stmt = new OdpsUndoTableStatement();\n            stmt.setTable(\n                    new SQLExprTableSource(\n                            this.exprParser.name()\n                    )\n            );\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n            }\n            accept(Token.TO);\n            stmt.setTo(\n                    this.exprParser.expr()\n            );\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.FUNCTION) {\n            HiveCreateFunctionStatement stmt = (HiveCreateFunctionStatement) parseHiveCreateFunction();\n            stmt.setDeclare(true);\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.VARIANT && lexer.stringVal().startsWith(\"@\")) {\n            Lexer.SavePoint mark = lexer.mark();\n            String variant = lexer.stringVal();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COLONEQ) {\n                lexer.nextToken();\n\n                boolean cache = false;\n                if (lexer.identifierEquals(FnvHash.Constants.CACHE)) {\n                    lexer.nextToken();\n                    accept(Token.ON);\n                    cache = true;\n                }\n\n                Lexer.SavePoint lpMark = null;\n                if (lexer.token() == Token.LPAREN) {\n                    lpMark = lexer.mark();\n                    lexer.nextToken();\n                }\n\n                switch (lexer.token()) {\n                    case LITERAL_INT:\n                    case LITERAL_FLOAT:\n                    case LITERAL_CHARS:\n                    case LITERAL_ALIAS:\n                    case IDENTIFIER:\n                    case CASE:\n                    case CAST:\n                    case IF:\n                    case VARIANT:\n                    case REPLACE:\n                    case NEW:\n                    case SUB:\n                    case TRUE:\n                    case FALSE: {\n                        if (lpMark != null) {\n                            lexer.reset(lpMark);\n                        }\n\n                        SQLExpr expr = this.exprParser.expr();\n                        SQLExprStatement stmt = new SQLExprStatement(\n                                new SQLAssignItem(new SQLIdentifierExpr(variant), expr)\n                        );\n                        statementList.add(stmt);\n                        return true;\n                    }\n                    default:\n                        if (lpMark != null) {\n                            lexer.reset(lpMark);\n                        }\n\n                        boolean paren = lexer.token() == Token.LPAREN;\n                        Lexer.SavePoint parenMark = lexer.mark();\n                        SQLSelect select;\n                        try {\n                            select = new OdpsSelectParser(this.exprParser)\n                                    .select();\n                        } catch (ParserException error) {\n                            if (paren) {\n                                lexer.reset(parenMark);\n                                SQLExpr expr = this.exprParser.expr();\n                                SQLExprStatement stmt = new SQLExprStatement(\n                                        new SQLAssignItem(new SQLIdentifierExpr(variant), expr)\n                                );\n                                statementList.add(stmt);\n                                return true;\n                            }\n                            throw error;\n                        }\n                        switch (lexer.token()) {\n                            case GT:\n                            case GTEQ:\n                            case EQ:\n                            case LT:\n                            case LTEQ:\n                                statementList.add(\n                                        new SQLExprStatement(\n                                                new SQLAssignItem(new SQLIdentifierExpr(variant),\n                                                        this.exprParser.exprRest(new SQLQueryExpr(select))\n                                                )\n                                        )\n                                );\n                                return true;\n                            default:\n                                break;\n                        }\n                        SQLSelectStatement stmt = new SQLSelectStatement(select, dbType);\n\n                        OdpsQueryAliasStatement aliasQueryStatement = new OdpsQueryAliasStatement(variant, stmt);\n                        aliasQueryStatement.setCache(cache);\n                        statementList.add(aliasQueryStatement);\n                        return true;\n                }\n            }\n\n            OdpsDeclareVariableStatement stmt = new OdpsDeclareVariableStatement();\n\n            if (lexer.token() != Token.EQ && lexer.token() != Token.SEMI && lexer.token() != Token.EOF) {\n                stmt.setDataType(\n                        this.exprParser.parseDataType()\n                );\n            }\n\n            if (lexer.token() == Token.EQ || lexer.token() == Token.COLONEQ) {\n                lexer.nextToken();\n                stmt.setInitValue(\n                        this.exprParser.expr()\n                );\n            }\n\n            if (lexer.token() == Token.SEMI) {\n                lexer.nextToken();\n            }\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.IF) {\n            SQLStatement stmt = parseIf();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.CODE) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token() == Token.EOF || lexer.token() == Token.SEMI) {\n                return true;\n            }\n            lexer.reset(mark);\n        }\n\n        if (identifierEquals(\"COST\")) {\n            SQLStatement stmt = parseCost();\n            statementList.add(stmt);\n            return true;\n        }\n\n        return false;\n    }\n\n    public SQLStatement parseIf() {\n        accept(Token.IF);\n        SQLIfStatement ifStmt = new SQLIfStatement();\n        ifStmt.setCondition(\n                this.exprParser.expr()\n        );\n\n        if (lexer.identifierEquals(\"BEGIN\")) {\n            lexer.nextToken();\n            parseStatementList(ifStmt.getStatements(), -1, ifStmt);\n            accept(Token.END);\n        } else {\n            SQLStatement stmt = parseStatement();\n            ifStmt.getStatements().add(stmt);\n            stmt.setParent(ifStmt);\n        }\n\n        if (lexer.token() == Token.SEMI) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.ELSE) {\n            lexer.nextToken();\n\n            SQLIfStatement.Else elseItem = new SQLIfStatement.Else();\n            if (lexer.identifierEquals(\"BEGIN\")) {\n                lexer.nextToken();\n                parseStatementList(elseItem.getStatements(), -1, ifStmt);\n                accept(Token.END);\n            } else {\n                SQLStatement stmt = parseStatement();\n                elseItem.getStatements().add(stmt);\n                stmt.setParent(elseItem);\n            }\n            ifStmt.setElseItem(elseItem);\n        }\n\n        return ifStmt;\n    }\n\n    public SQLStatement parseKill() {\n        acceptIdentifier(\"KILL\");\n        MySqlKillStatement stmt = new MySqlKillStatement();\n        SQLExpr instanceId = this.exprParser.primary();\n        stmt.setThreadId(instanceId);\n        return stmt;\n    }\n\n    public SQLStatement parseUnload() {\n        acceptIdentifier(\"UNLOAD\");\n        OdpsUnloadStatement stmt = new OdpsUnloadStatement();\n\n        accept(Token.FROM);\n        if (lexer.token() == Token.LPAREN || lexer.token() == Token.SELECT) {\n            stmt.setFrom(\n                    this.createSQLSelectParser().parseTableSource()\n            );\n        } else {\n            stmt.setFrom(\n                    this.exprParser.name()\n            );\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n        }\n\n        accept(Token.INTO);\n\n        if (lexer.identifierEquals(\"LOCATION\")) {\n            lexer.nextToken();\n            stmt.setLocation(this.exprParser.primary());\n        }\n\n        if (lexer.identifierEquals(\"ROW\")) {\n            SQLExternalRecordFormat format = this.exprParser.parseRowFormat();\n            stmt.setRowFormat(format);\n        }\n\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.STORED)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.BY) {\n                    lexer.nextToken();\n                } else {\n                    accept(Token.AS);\n                }\n                stmt.setStoredAs(\n                        this.exprParser.name());\n                continue;\n            }\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"SERDEPROPERTIES\");\n                this.exprParser.parseAssignItem(stmt.getSerdeProperties(), stmt);\n                continue;\n            }\n\n            if (identifierEquals(\"PROPERTIES\")) {\n                lexer.nextToken();\n                this.exprParser.parseAssignItem(stmt.getProperties(), stmt);\n                continue;\n            }\n\n            break;\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public OdpsExprParser getExprParser() {\n        return (OdpsExprParser) exprParser;\n    }\n\n    public SQLStatement parseClone() {\n        acceptIdentifier(\"CLONE\");\n        accept(Token.TABLE);\n        SQLCloneTableStatement stmt = new SQLCloneTableStatement();\n\n        stmt.setFrom(\n                this.exprParser.name());\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n        }\n\n        accept(Token.TO);\n\n        stmt.setTo(\n                this.exprParser.name());\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n\n            if (lexer.token() == OVERWRITE) {\n                lexer.nextToken();\n                stmt.setIfExistsOverwrite(true);\n            } else {\n                acceptIdentifier(\"IGNORE\");\n                stmt.setIfExistsIgnore(true);\n            }\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseBlock() {\n        SQLBlockStatement block = new SQLBlockStatement();\n        if (lexer.identifierEquals(FnvHash.Constants.BEGIN)) {\n            lexer.nextToken();\n        } else {\n            accept(Token.BEGIN);\n        }\n        this.parseStatementList(block.getStatementList(), -1, block);\n        accept(Token.END);\n        return block;\n    }\n\n    protected OdpsStatisticClause parseStaticClause() {\n        if (lexer.identifierEquals(\"TABLE_COUNT\")) {\n            lexer.nextToken();\n            return new OdpsStatisticClause.TableCount();\n        } else if (lexer.identifierEquals(\"NULL_VALUE\")) {\n            lexer.nextToken();\n            OdpsStatisticClause.NullValue null_value = new OdpsStatisticClause.NullValue();\n            null_value.setColumn(this.exprParser.name());\n            return null_value;\n        } else if (lexer.identifierEquals(\"DISTINCT_VALUE\")) {\n            lexer.nextToken();\n            OdpsStatisticClause.DistinctValue distinctValue = new OdpsStatisticClause.DistinctValue();\n            distinctValue.setColumn(this.exprParser.name());\n            return distinctValue;\n        } else if (lexer.identifierEquals(\"COLUMN_SUM\")) {\n            lexer.nextToken();\n            OdpsStatisticClause.ColumnSum column_sum = new OdpsStatisticClause.ColumnSum();\n            column_sum.setColumn(this.exprParser.name());\n            return column_sum;\n        } else if (lexer.identifierEquals(\"COLUMN_MAX\")) {\n            lexer.nextToken();\n            OdpsStatisticClause.ColumnMax column_max = new OdpsStatisticClause.ColumnMax();\n            column_max.setColumn(this.exprParser.name());\n            return column_max;\n        } else if (lexer.identifierEquals(\"COLUMN_MIN\")) {\n            lexer.nextToken();\n            OdpsStatisticClause.ColumnMin column_min = new OdpsStatisticClause.ColumnMin();\n            column_min.setColumn(this.exprParser.name());\n            return column_min;\n        } else if (lexer.identifierEquals(\"EXPRESSION_CONDITION\")) {\n            lexer.nextToken();\n            OdpsStatisticClause.ExpressionCondition expr_condition = new OdpsStatisticClause.ExpressionCondition();\n            expr_condition.setExpr(this.exprParser.expr());\n            return expr_condition;\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n    }\n\n    public SQLStatement parseInsert() {\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n\n            HiveMultiInsertStatement stmt = new HiveMultiInsertStatement();\n\n            if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.VARIANT) {\n                Lexer.SavePoint mark = lexer.mark();\n                SQLExpr tableName = this.exprParser.name();\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.reset(mark);\n                    tableName = this.exprParser.primary();\n                }\n\n                SQLTableSource from = new SQLExprTableSource(tableName);\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    String alias = alias();\n                    from.setAlias(alias);\n                }\n\n                SQLSelectParser selectParser = createSQLSelectParser();\n                from = selectParser.parseTableSourceRest(from);\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = this.exprParser.expr();\n                    SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock();\n                    queryBlock.addSelectItem(new SQLAllColumnExpr());\n                    queryBlock.setFrom(from);\n                    queryBlock.setWhere(where);\n\n                    if (lexer.token() == Token.GROUP) {\n                        selectParser.parseGroupBy(queryBlock);\n                    }\n\n                    stmt.setFrom(\n                            new SQLSubqueryTableSource(queryBlock)\n                    );\n                } else {\n                    stmt.setFrom(from);\n                }\n            } else {\n                SQLCommentHint hint = null;\n                if (lexer.token() == Token.HINT) {\n                    hint = this.exprParser.parseHint();\n                }\n                accept(Token.LPAREN);\n\n                boolean paren2 = lexer.token() == Token.LPAREN;\n\n                SQLSelectParser selectParser = createSQLSelectParser();\n                SQLSelect select = selectParser.select();\n\n                SQLTableSource from = null;\n                if (paren2 && lexer.token() != Token.RPAREN) {\n                    String subQueryAs = null;\n                    if (lexer.token() == Token.AS) {\n                        lexer.nextToken();\n                        subQueryAs = tableAlias(true);\n                    } else {\n                        subQueryAs = tableAlias(false);\n                    }\n                    SQLSubqueryTableSource subQuery = new SQLSubqueryTableSource(select, subQueryAs);\n                    from = selectParser.parseTableSourceRest(subQuery);\n                }\n\n                accept(Token.RPAREN);\n\n                String alias;\n\n                if (lexer.token() == Token.INSERT) {\n                    alias = null;\n                } else if (lexer.token() == Token.SELECT) {\n                    // skip\n                    alias = null;\n                } else {\n                    if (lexer.token() == Token.AS) {\n                        lexer.nextToken();\n                    }\n                    alias = lexer.stringVal();\n                    accept(Token.IDENTIFIER);\n                }\n\n                if (from == null) {\n                    from = new SQLSubqueryTableSource(select, alias);\n                } else {\n                    if (alias != null) {\n                        from.setAlias(alias);\n                    }\n                }\n\n                SQLTableSource tableSource = selectParser.parseTableSourceRest(from);\n\n                if (hint != null) {\n                    if (tableSource instanceof SQLJoinTableSource) {\n                        ((SQLJoinTableSource) tableSource).setHint(hint);\n                    }\n                }\n\n                stmt.setFrom(tableSource);\n            }\n\n            if (lexer.token() == Token.SELECT) {\n                SQLSelectParser selectParser = createSQLSelectParser();\n                SQLSelect query = selectParser.select();\n\n                HiveInsert insert = new HiveInsert();\n                insert.setQuery(query);\n                stmt.addItem(insert);\n                return stmt;\n            }\n\n            for (; ; ) {\n                HiveInsert insert = parseHiveInsert();\n                stmt.addItem(insert);\n\n                if (lexer.token() != Token.INSERT) {\n                    break;\n                }\n            }\n\n            return stmt;\n        }\n\n        return parseHiveInsertStmt();\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new OdpsSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLStatement parseShow() {\n        accept(Token.SHOW);\n\n        if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n            lexer.nextToken();\n\n            SQLShowPartitionsStmt stmt = new SQLShowPartitionsStmt();\n\n            SQLExpr expr = this.exprParser.expr();\n            stmt.setTableSource(new SQLExprTableSource(expr));\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                parseAssignItems(stmt.getPartition(), stmt, false);\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                stmt.setWhere(\n                        this.exprParser.expr()\n                );\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STATISTIC)) {\n            lexer.nextToken();\n\n            SQLShowStatisticStmt stmt = new SQLShowStatisticStmt();\n\n            SQLExpr expr = this.exprParser.expr();\n            stmt.setTableSource(new SQLExprTableSource(expr));\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n\n                accept(Token.LPAREN);\n                parseAssignItems(stmt.getPartitions(), stmt, false);\n                accept(Token.RPAREN);\n            }\n\n            if (identifierEquals(\"COLUMNS\")) {\n                lexer.nextToken();\n\n                if (lexer.token() != Token.SEMI) {\n                    accept(Token.LPAREN);\n                    this.exprParser.names(stmt.getColumns(), stmt);\n                    accept(Token.RPAREN);\n                }\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STATISTIC_LIST)) {\n            lexer.nextToken();\n\n            SQLShowStatisticListStmt stmt = new SQLShowStatisticListStmt();\n\n            SQLExpr expr = this.exprParser.expr();\n            stmt.setTableSource(new SQLExprTableSource(expr));\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PACKAGES)) {\n            lexer.nextToken();\n\n            SQLShowPackagesStatement stmt = new SQLShowPackagesStatement();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TABLES)) {\n            lexer.nextToken();\n\n            SQLShowTablesStatement stmt = new SQLShowTablesStatement();\n\n            if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                lexer.nextToken();\n                stmt.setDatabase(this.exprParser.name());\n            } else if (lexer.token() == IDENTIFIER) {\n                SQLName database = exprParser.name();\n                stmt.setDatabase(database);\n            }\n\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextToken();\n                stmt.setLike(this.exprParser.expr());\n            } else if (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS) {\n                stmt.setLike(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LABEL)) {\n            lexer.nextToken();\n            acceptIdentifier(\"GRANTS\");\n            OdpsShowGrantsStmt stmt = new OdpsShowGrantsStmt();\n            stmt.setLabel(true);\n\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                accept(Token.TABLE);\n                stmt.setObjectType(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                accept(Token.USER);\n                stmt.setUser(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.GRANTS)) {\n            lexer.nextToken();\n            OdpsShowGrantsStmt stmt = new OdpsShowGrantsStmt();\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                if (lexer.token() == Token.USER) {\n                    lexer.nextToken();\n                }\n                stmt.setUser(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                acceptIdentifier(\"type\");\n                stmt.setObjectType(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USERS)) {\n            lexer.nextToken();\n            SQLShowUsersStatement stmt = new SQLShowUsersStatement();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"RECYCLEBIN\")) {\n            lexer.nextToken();\n            SQLShowRecylebinStatement stmt = new SQLShowRecylebinStatement();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"VARIABLES\")) {\n            lexer.nextToken();\n            return parseShowVariants();\n        }\n\n        if (lexer.token() == Token.CREATE) {\n            return parseShowCreateTable();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n            lexer.nextToken();\n\n            SQLShowFunctionsStatement stmt = new SQLShowFunctionsStatement();\n            if (lexer.token() == Token.LIKE) {\n                lexer.nextToken();\n                stmt.setLike(\n                        this.exprParser.expr()\n                );\n            } else if (lexer.token() == Token.LITERAL_CHARS || lexer.token() == IDENTIFIER) {\n                stmt.setLike(\n                        this.exprParser.expr()\n                );\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ROLE)) {\n            lexer.nextToken();\n\n            SQLShowRoleStatement stmt = new SQLShowRoleStatement();\n\n            if (lexer.token() == Token.GRANT) {\n                lexer.nextToken();\n                stmt.setGrant(\n                        this.exprParser.name()\n                );\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"ACL\")) {\n            lexer.nextToken();\n\n            SQLShowACLStatement stmt = new SQLShowACLStatement();\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                stmt.setTable(\n                        new SQLExprTableSource(\n                                this.exprParser.name()\n                        )\n                );\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ROLES)) {\n            lexer.nextToken();\n\n            SQLShowRolesStatement stmt = new SQLShowRolesStatement();\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"HISTORY\")) {\n            lexer.nextToken();\n            SQLShowHistoryStatement stmt = new SQLShowHistoryStatement();\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.TABLES)) {\n                    lexer.nextToken();\n                    stmt.setTables(true);\n                } else if (lexer.token() == Token.TABLE) {\n                    lexer.nextToken();\n                    stmt.setTable(\n                            new SQLExprTableSource(\n                                    this.exprParser.name()\n                            )\n                    );\n                }\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                this.exprParser.parseAssignItem(stmt.getProperties(), stmt);\n            }\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"CHANGELOGS\")) {\n            lexer.nextToken();\n            OdpsShowChangelogsStatement stmt = new OdpsShowChangelogsStatement();\n\n            if (lexer.token() == Token.FOR) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.TABLES)) {\n                    lexer.nextToken();\n                    stmt.setTables(true);\n                } else if (lexer.token() == Token.TABLE) {\n                    lexer.nextToken();\n                    stmt.setTable(\n                            new SQLExprTableSource(\n                                    this.exprParser.name()\n                            )\n                    );\n                } else if (lexer.token() == IDENTIFIER) {\n                    stmt.setTable(\n                            new SQLExprTableSource(\n                                    this.exprParser.name()\n                            )\n                    );\n                }\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                this.exprParser.parseAssignItem(stmt.getProperties(), stmt);\n            }\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                this.exprParser.parseAssignItem(stmt.getPartitions(), stmt);\n            }\n\n            if (lexer.token() == Token.LITERAL_INT) {\n                stmt.setId(\n                        this.exprParser.primary()\n                );\n            }\n\n            return stmt;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    public SQLStatement parseCost() {\n        acceptIdentifier(\"COST\");\n        acceptIdentifier(\"SQL\");\n        SQLStatement stmt = parseStatement();\n        SQLCostStatement cost = new SQLCostStatement();\n        cost.setStatement(stmt);\n        return cost;\n    }\n\n    public SQLStatement parseSet() {\n        List<String> comments = null;\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            comments = lexer.readAndResetComments();\n        }\n\n        boolean setProject = false;\n        if (identifierEquals(\"SETPROJECT\")) {\n            lexer.nextToken();\n            setProject = true;\n        } else if (dbType == DbType.odps && identifierEquals(\"ALIAS\")) {\n            lexer.nextToken();\n        } else {\n            accept(Token.SET);\n        }\n\n        if (lexer.token() == Token.SET && dbType == DbType.odps) {\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"PROJECT\")) {\n            lexer.nextToken();\n            setProject = true;\n        }\n\n        if (setProject) {\n            SQLSetStatement stmt = new SQLSetStatement();\n            stmt.setOption(SQLSetStatement.Option.PROJECT);\n            SQLName target = this.exprParser.name();\n            accept(Token.EQ);\n            SQLExpr value = this.exprParser.expr();\n            stmt.set(target, value);\n            return stmt;\n        } else if (lexer.identifierEquals(\"LABEL\")) {\n            OdpsSetLabelStatement stmt = new OdpsSetLabelStatement();\n\n            if (comments != null) {\n                stmt.addBeforeComment(comments);\n            }\n\n            lexer.nextToken();\n\n            stmt.setLabel(lexer.stringVal());\n            lexer.nextToken();\n            accept(Token.TO);\n            if (lexer.token() == Token.USER) {\n                lexer.nextToken();\n\n                SQLName name = this.exprParser.name();\n                stmt.setUser(name);\n                return stmt;\n            }\n            accept(Token.TABLE);\n            SQLExpr expr = this.exprParser.name();\n            stmt.setTable(new SQLExprTableSource(expr));\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                this.exprParser.names(stmt.getColumns(), stmt);\n                accept(Token.RPAREN);\n            }\n\n            return stmt;\n        } else {\n            SQLSetStatement stmt = new SQLSetStatement(dbType);\n            stmt.putAttribute(\"parser.set\", Boolean.TRUE);\n\n            if (comments != null) {\n                stmt.addBeforeComment(comments);\n            }\n\n            parseAssignItems(stmt.getItems(), stmt);\n\n            return stmt;\n        }\n    }\n\n    public OdpsGrantStmt parseGrant() {\n        accept(Token.GRANT);\n        OdpsGrantStmt stmt = new OdpsGrantStmt();\n\n        if (lexer.identifierEquals(\"LABEL\")) {\n            stmt.setLabel(true);\n            lexer.nextToken();\n            stmt.setLabel(this.exprParser.expr());\n        } else {\n            if (lexer.identifierEquals(\"SUPER\")) {\n                stmt.setSuper(true);\n                lexer.nextToken();\n            }\n\n            parsePrivilege(stmt.getPrivileges(), stmt);\n        }\n\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"PROJECT\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.PROJECT);\n            } else if (lexer.identifierEquals(\"PACKAGE\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.PACKAGE);\n            } else if (lexer.token() == Token.FUNCTION) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.FUNCTION);\n            } else if (lexer.token() == Token.TABLE) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.TABLE);\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    this.exprParser.names(stmt.getColumns(), stmt);\n                    accept(Token.RPAREN);\n                }\n            } else if (lexer.identifierEquals(\"RESOURCE\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.RESOURCE);\n            } else if (lexer.identifierEquals(\"INSTANCE\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.INSTANCE);\n            } else if (lexer.identifierEquals(\"JOB\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.JOB);\n            } else if (lexer.identifierEquals(\"VOLUME\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.VOLUME);\n            } else if (lexer.identifierEquals(\"OfflineModel\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.OfflineModel);\n            } else if (lexer.identifierEquals(\"XFLOW\")) {\n                lexer.nextToken();\n                stmt.setResourceType(SQLObjectType.XFLOW);\n            }\n\n            stmt.setResource(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n            if (lexer.token() == Token.USER) {\n                lexer.nextToken();\n                stmt.setSubjectType(SQLObjectType.USER);\n            } else if (lexer.identifierEquals(\"ROLE\")) {\n                lexer.nextToken();\n                stmt.setSubjectType(SQLObjectType.ROLE);\n            }\n            stmt.getUsers().add(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"EXP\");\n            stmt.setExpire(this.exprParser.expr());\n        }\n\n        return stmt;\n    }\n\n    protected void parsePrivilege(List<SQLPrivilegeItem> privileges, SQLObject parent) {\n        for (; ; ) {\n            String privilege = null;\n            if (lexer.token() == Token.ALL) {\n                lexer.nextToken();\n                privilege = \"ALL\";\n            } else if (lexer.token() == Token.SELECT) {\n                privilege = \"SELECT\";\n                lexer.nextToken();\n            } else if (lexer.token() == Token.UPDATE) {\n                privilege = \"UPDATE\";\n                lexer.nextToken();\n            } else if (lexer.token() == Token.DELETE) {\n                privilege = \"DELETE\";\n                lexer.nextToken();\n            } else if (lexer.token() == Token.INSERT) {\n                privilege = \"INSERT\";\n                lexer.nextToken();\n            } else if (lexer.token() == Token.DROP) {\n                lexer.nextToken();\n                privilege = \"DROP\";\n            } else if (lexer.token() == Token.ALTER) {\n                lexer.nextToken();\n                privilege = \"ALTER\";\n            } else if (lexer.identifierEquals(\"DESCRIBE\")) {\n                privilege = \"DESCRIBE\";\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"READ\")) {\n                privilege = \"READ\";\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"WRITE\")) {\n                privilege = \"WRITE\";\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"EXECUTE\")) {\n                lexer.nextToken();\n                privilege = \"EXECUTE\";\n            } else if (lexer.identifierEquals(\"LIST\")) {\n                lexer.nextToken();\n                privilege = \"LIST\";\n            } else if (lexer.identifierEquals(\"CreateTable\")) {\n                lexer.nextToken();\n                privilege = \"CreateTable\";\n            } else if (lexer.identifierEquals(\"CreateInstance\")) {\n                lexer.nextToken();\n                privilege = \"CreateInstance\";\n            } else if (lexer.identifierEquals(\"CreateFunction\")) {\n                lexer.nextToken();\n                privilege = \"CreateFunction\";\n            } else if (lexer.identifierEquals(\"CreateResource\")) {\n                lexer.nextToken();\n                privilege = \"CreateResource\";\n            } else if (lexer.identifierEquals(\"CreateJob\")) {\n                lexer.nextToken();\n                privilege = \"CreateJob\";\n            } else if (lexer.identifierEquals(\"CreateVolume\")) {\n                lexer.nextToken();\n                privilege = \"CreateVolume\";\n            } else if (lexer.identifierEquals(\"CreateOfflineModel\")) {\n                lexer.nextToken();\n                privilege = \"CreateOfflineModel\";\n            } else if (lexer.identifierEquals(\"CreateXflow\")) {\n                lexer.nextToken();\n                privilege = \"CreateXflow\";\n            }\n\n            SQLExpr expr = null;\n            if (privilege != null) {\n                expr = new SQLIdentifierExpr(privilege);\n            } else {\n                expr = this.exprParser.expr();\n            }\n\n            SQLPrivilegeItem privilegeItem = new SQLPrivilegeItem();\n            privilegeItem.setAction(expr);\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                for (; ; ) {\n                    privilegeItem.getColumns().add(this.exprParser.name());\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n\n            expr.setParent(parent);\n            privileges.add(privilegeItem);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n    }\n\n    public SQLCreateFunctionStatement parseCreateFunction() {\n        return parseHiveCreateFunction();\n    }\n\n    protected HiveLoadDataStatement parseLoad() {\n        acceptIdentifier(\"LOAD\");\n\n        HiveLoadDataStatement stmt = new HiveLoadDataStatement();\n\n        if (lexer.token() == OVERWRITE) {\n            stmt.setOverwrite(true);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n        }\n\n        accept(Token.TABLE);\n\n        stmt.setInto(\n                this.exprParser.expr());\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            this.exprParser.exprList(stmt.getPartition(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n            lexer.nextToken();\n            stmt.setLocal(true);\n        }\n\n        accept(Token.FROM);\n\n        acceptIdentifier(\"LOCATION\");\n\n        SQLExpr inpath = this.exprParser.expr();\n        stmt.setInpath(inpath);\n\n        if (lexer.identifierEquals(\"STORED\")) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.BY) {\n                lexer.nextToken();\n                stmt.setStoredBy(this.exprParser.expr());\n            } else {\n                accept(Token.AS);\n                stmt.setStoredAs(this.exprParser.expr());\n            }\n        }\n\n        if (lexer.identifierEquals(\"ROW\")) {\n            lexer.nextToken();\n\n            acceptIdentifier(\"FORMAT\");\n            acceptIdentifier(\"SERDE\");\n            stmt.setRowFormat(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"SERDEPROPERTIES\");\n\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                String name = lexer.stringVal();\n                lexer.nextToken();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.primary();\n                stmt.getSerdeProperties().put(name, value);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(\"STORED\")) {\n            lexer.nextToken();\n\n            accept(Token.AS);\n            stmt.setStoredAs(this.exprParser.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n            lexer.nextToken();\n            stmt.setUsing(\n                    this.exprParser.expr()\n            );\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseCopy() {\n        lexer.nextToken();\n        int semiPos = lexer.text.indexOf(';', lexer.pos());\n        String arguments;\n        if (semiPos != -1) {\n            int count = semiPos - lexer.pos();\n            arguments = lexer.subString(lexer.pos(), count);\n            lexer.reset(semiPos);\n        } else {\n            arguments = lexer.subString(lexer.pos());\n            lexer.reset(lexer.text.length());\n        }\n        lexer.nextToken();\n\n        OdpsCopyStmt stmt = new OdpsCopyStmt();\n        stmt.setArguments(arguments);\n        return stmt;\n    }\n\n    @Override\n    protected boolean alterTableAfterNameRest(SQLAlterTableStatement stmt) {\n        if (lexer.identifierEquals(\"MERGE\")) {\n            alterTableMerge(stmt);\n        } else if ((lexer.identifierEquals(FnvHash.Constants.RANGE)\n                || lexer.identifierEquals(FnvHash.Constants.CLUSTERED))\n        ) {\n            if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n                lexer.nextToken();\n                acceptIdentifier(\"CLUSTERED\");\n                stmt.setRange(true);\n            } else {\n                lexer.nextToken();\n            }\n            accept(Token.BY);\n\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                stmt.addClusteredByItem(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        } else if (lexer.identifierEquals(FnvHash.Constants.SORTED)) {\n            alterTableSorted(stmt);\n        } else if (dbType == DbType.odps && lexer.token() == Token.NOT) {\n            lexer.nextToken();\n            acceptIdentifier(\"CLUSTERED\");\n            stmt.setNotClustered(true);\n        } else {\n            return true;\n        }\n        return super.alterTableAfterNameRest(stmt);\n    }\n\n    @Override\n    protected boolean alterTableSetRest(SQLAlterTableStatement stmt) {\n        if (lexer.identifierEquals(\"CHANGELOGS\")) {\n            lexer.nextToken();\n            OdpsAlterTableSetChangeLogs item = new OdpsAlterTableSetChangeLogs();\n            item.setValue(this.exprParser.primary());\n            stmt.addItem(item);\n        } else if (lexer.identifierEquals(\"FILEFORMAT\")) {\n            lexer.nextToken();\n            OdpsAlterTableSetFileFormat item = new OdpsAlterTableSetFileFormat();\n            item.setValue(this.exprParser.primary());\n            stmt.addItem(item);\n        } else {\n            return super.alterTableSetRest(stmt);\n        }\n        return false;\n    }\n\n    @Override\n    protected void alterTableChangeOwner(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.TO);\n        OdpsAlterTableChangeOwner item = new OdpsAlterTableChangeOwner();\n        item.setValue(this.exprParser.primary());\n        stmt.addItem(item);\n    }\n\n    @Override\n    protected void parseCreateMaterializedViewRest(SQLCreateMaterializedViewStatement stmt) {\n        if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n            lexer.nextToken();\n            stmt.setLifyCycle(\n                    this.exprParser.primary()\n            );\n        }\n\n        if (lexer.token() == Token.PARTITIONED) {\n            lexer.nextToken();\n            accept(ON);\n            accept(LPAREN);\n            this.exprParser.names(stmt.getPartitionedOn(), stmt);\n            accept(RPAREN);\n        }\n    }\n\n    @Override\n    public void parseUpdateStatementPartition(SQLUpdateStatement updateStatement) {\n        if (lexer.token() == PARTITION) {\n            lexer.nextToken();\n            updateStatement.setPartitions(new ArrayList<>());\n            this.exprParser.parseAssignItem(updateStatement.getPartitions(), updateStatement);\n        }\n    }\n\n    @Override\n    protected void parseUpdateSetComma() {\n        if (lexer.token() == COMMA) {\n            lexer.nextToken();\n        }\n    }\n\n    @Override\n    public void parseCreateViewAtDataType(SQLColumnDefinition column, SQLName expr) {\n        if (expr.getSimpleName().startsWith(\"@\")) {\n            column.setDataType(this.exprParser.parseDataType());\n        }\n    }\n\n    @Override\n    protected void parseWithQuerySkip() {\n        if (lexer.identifierEquals(FnvHash.Constants.STRING)\n                || lexer.identifierEquals(FnvHash.Constants.INT)\n                || lexer.identifierEquals(FnvHash.Constants.BIGINT)\n        ) {\n            lexer.nextToken(); // skip\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\") {\n        return true;\n    }\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.visitor;\n\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLGrantStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.dialect.odps.ast.*;\n\npublic interface OdpsASTVisitor extends HiveASTVisitor {\n    default void endVisit(OdpsCreateTableStatement x) {\n        endVisit((SQLCreateTableStatement) x);\n    }\n\n    default boolean visit(OdpsCreateTableStatement x) {\n        return visit((SQLCreateTableStatement) x);\n    }\n\n    default void endVisit(OdpsUDTFSQLSelectItem x) {\n    }\n\n    default boolean visit(OdpsUDTFSQLSelectItem x) {\n        return true;\n    }\n\n    default void endVisit(OdpsSetLabelStatement x) {\n    }\n\n    default boolean visit(OdpsSetLabelStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(OdpsSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(OdpsAddStatisticStatement x) {\n    }\n\n    default boolean visit(OdpsAddStatisticStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsRemoveStatisticStatement x) {\n    }\n\n    default boolean visit(OdpsRemoveStatisticStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsStatisticClause.TableCount x) {\n    }\n\n    default boolean visit(OdpsStatisticClause.TableCount x) {\n        return true;\n    }\n\n    default void endVisit(OdpsStatisticClause.ExpressionCondition x) {\n    }\n\n    default boolean visit(OdpsStatisticClause.ExpressionCondition x) {\n        return true;\n    }\n\n    default void endVisit(OdpsStatisticClause.NullValue x) {\n    }\n\n    default boolean visit(OdpsStatisticClause.NullValue x) {\n        return true;\n    }\n\n    default void endVisit(OdpsStatisticClause.DistinctValue x) {\n    }\n\n    default boolean visit(OdpsStatisticClause.DistinctValue x) {\n        return true;\n    }\n\n    default void endVisit(OdpsStatisticClause.ColumnSum x) {\n    }\n\n    default boolean visit(OdpsStatisticClause.ColumnSum x) {\n        return true;\n    }\n\n    default void endVisit(OdpsStatisticClause.ColumnMax x) {\n    }\n\n    default boolean visit(OdpsStatisticClause.ColumnMax x) {\n        return true;\n    }\n\n    default void endVisit(OdpsStatisticClause.ColumnMin x) {\n    }\n\n    default boolean visit(OdpsStatisticClause.ColumnMin x) {\n        return true;\n    }\n\n    default void endVisit(OdpsReadStatement x) {\n    }\n\n    default boolean visit(OdpsReadStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsShowGrantsStmt x) {\n    }\n\n    default boolean visit(OdpsShowGrantsStmt x) {\n        return true;\n    }\n\n    default void endVisit(OdpsShowChangelogsStatement x) {\n    }\n\n    default boolean visit(OdpsShowChangelogsStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsListStmt x) {\n    }\n\n    default boolean visit(OdpsListStmt x) {\n        return true;\n    }\n\n    default void endVisit(OdpsGrantStmt x) {\n        endVisit((SQLGrantStatement) x);\n    }\n\n    default boolean visit(OdpsGrantStmt x) {\n        return visit((SQLGrantStatement) x);\n    }\n\n    default boolean visit(OdpsAddTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsAddTableStatement x) {\n    }\n\n    default boolean visit(OdpsAddFileStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsAddFileStatement x) {\n    }\n\n    default boolean visit(OdpsAddUserStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsAddUserStatement x) {\n    }\n\n    default boolean visit(OdpsRemoveUserStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsRemoveUserStatement x) {\n    }\n\n    default boolean visit(OdpsAlterTableSetChangeLogs x) {\n        return true;\n    }\n\n    default void endVisit(OdpsAlterTableSetChangeLogs x) {\n    }\n\n    default boolean visit(OdpsAlterTableChangeOwner x) {\n        return true;\n    }\n\n    default void endVisit(OdpsAlterTableChangeOwner x) {\n    }\n\n    default boolean visit(OdpsCountStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsCountStatement x) {\n    }\n\n    default boolean visit(OdpsQueryAliasStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsQueryAliasStatement x) {\n    }\n\n    default boolean visit(OdpsTransformExpr x) {\n        return true;\n    }\n\n    default void endVisit(OdpsTransformExpr x) {\n    }\n\n    default boolean visit(OdpsExstoreStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsExstoreStatement x) {\n    }\n\n    default boolean visit(OdpsNewExpr x) {\n        return true;\n    }\n\n    default void endVisit(OdpsNewExpr x) {\n    }\n\n    default boolean visit(OdpsInstallPackageStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsInstallPackageStatement x) {\n    }\n\n    default boolean visit(OdpsDeclareVariableStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsDeclareVariableStatement x) {\n    }\n\n    default boolean visit(OdpsAddAccountProviderStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsAddAccountProviderStatement x) {\n    }\n\n    default boolean visit(OdpsUnloadStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsUnloadStatement x) {\n    }\n\n    default boolean visit(OdpsAlterTableSetFileFormat x) {\n        return true;\n    }\n\n    default void endVisit(OdpsAlterTableSetFileFormat x) {\n    }\n\n    default boolean visit(OdpsRestoreStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsRestoreStatement x) {\n    }\n\n    default boolean visit(OdpsUndoTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(OdpsUndoTableStatement x) {\n    }\n\n    default boolean visit(OdpsPAIStmt x) {\n        return true;\n    }\n\n    default void endVisit(OdpsPAIStmt x) {\n    }\n\n    default boolean visit(OdpsCopyStmt x) {\n        return true;\n    }\n\n    default void endVisit(OdpsCopyStmt x) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.visitor;\n\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitorAdapter;\n\npublic class OdpsASTVisitorAdapter extends HiveASTVisitorAdapter implements OdpsASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveLoadDataStatement;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveOutputVisitor;\nimport com.alibaba.druid.sql.dialect.odps.Odps;\nimport com.alibaba.druid.sql.dialect.odps.ast.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForStatement;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.math.BigDecimal;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class OdpsOutputVisitor extends HiveOutputVisitor implements OdpsASTVisitor {\n    private Set<String> builtInFunctions = new HashSet<String>();\n\n    {\n        builtInFunctions.add(\"IF\");\n        builtInFunctions.add(\"COALESCE\");\n        builtInFunctions.add(\"TO_DATE\");\n        builtInFunctions.add(\"SUBSTR\");\n        builtInFunctions.add(\"INSTR\");\n        builtInFunctions.add(\"LENGTH\");\n        builtInFunctions.add(\"SPLIT\");\n        builtInFunctions.add(\"TOLOWER\");\n        builtInFunctions.add(\"TOUPPER\");\n        builtInFunctions.add(\"EXPLODE\");\n        builtInFunctions.add(\"LEAST\");\n        builtInFunctions.add(\"GREATEST\");\n\n        groupItemSingleLine = true;\n    }\n\n    public OdpsOutputVisitor() {\n        this(new StringBuilder());\n    }\n\n    public OdpsOutputVisitor(boolean ucase) {\n        this(new StringBuilder());\n        config(VisitorFeature.OutputUCase, ucase);\n    }\n\n    public OdpsOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.odps, Odps.DIALECT);\n    }\n\n    @Override\n    public boolean visit(SQLMergeStatement.WhenUpdate x) {\n        print0(ucase ? \"WHEN MATCHED\" : \"when matched\");\n        this.indentCount++;\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            this.indentCount++;\n            if (SQLBinaryOpExpr.isAnd(where)) {\n                println();\n            } else {\n                print(' ');\n            }\n\n            print0(ucase ? \"AND \" : \"and \");\n\n            printExpr(where, parameterized);\n            this.indentCount--;\n            println();\n        } else {\n            print(' ');\n        }\n        println(ucase ? \"THEN UPDATE\" : \"then update\");\n        incrementIndent();\n        print(ucase ? \"SET \" : \"set \");\n        printlnAndAccept(x.getItems(), \",\");\n        decrementIndent();\n        this.indentCount--;\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsCreateTableStatement x) {\n        return visit((SQLCreateTableStatement) x);\n    }\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        printCreateTableFeatures(x);\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"TABLE IF NOT EXISTS \" : \"table if not exists \");\n        } else {\n            print0(ucase ? \"TABLE \" : \"table \");\n        }\n\n        x.getName().accept(this);\n        printCreateTableLike(x);\n        printTableElementsWithComment(x);\n        printComment(x.getComment());\n        printPartitionedBy(x);\n        printClusteredBy(x);\n        printSortedBy(x.getSortedBy());\n        printIntoBuckets(x.getBuckets());\n        printIntoShards(x.getShards());\n        printRowFormat(x);\n        printStoredBy(x.getStoredBy());\n        printStoredAs(x);\n        if (x instanceof OdpsCreateTableStatement) {\n            printSerdeProperties((OdpsCreateTableStatement) x);\n        }\n        printLocation(x);\n        printTableOptions(x);\n        printLifeCycle(x.getLifeCycle());\n        if (x instanceof HiveCreateTableStatement) {\n            printUsing((HiveCreateTableStatement) x);\n        }\n        printSelectAs(x, true);\n        return false;\n    }\n\n    protected void printPartitionedBy(SQLCreateTableStatement x) {\n        super.printPartitionedBy(x);\n        if (x instanceof OdpsCreateTableStatement) {\n            SQLAliasedExpr autoPartitionedBy = ((OdpsCreateTableStatement) x).getAutoPartitionedBy();\n            if (autoPartitionedBy != null) {\n                println();\n                print0(ucase ? \"AUTO PARTITIONED BY (\" : \"auto partitioned by (\");\n                autoPartitionedBy.accept(this);\n                print(\")\");\n            }\n        }\n    }\n\n    protected void printSerdeProperties(SQLCreateTableStatement x) {\n        if (x instanceof OdpsCreateTableStatement) {\n        List<SQLExpr> withSerdeproperties = ((OdpsCreateTableStatement) x).getWithSerdeproperties();\n            if (!withSerdeproperties.isEmpty()) {\n                println();\n                print0(ucase ? \"WITH SERDEPROPERTIES (\" : \"with serdeproperties (\");\n                printAndAccept(withSerdeproperties, \", \");\n                print(')');\n            }\n        }\n    }\n\n    public boolean visit(SQLDecimalExpr x) {\n        BigDecimal value = x.getValue();\n        print(value.toString());\n        print(\"BD\");\n\n        return false;\n    }\n\n//    protected void printSelectList(List<SQLSelectItem> selectList) {\n//        this.indentCount++;\n//        for (int i = 0, size = selectList.size(); i < size; ++i) {\n//            SQLSelectItem selectItem = selectList.get(i);\n//\n//            if (i != 0) {\n//                SQLSelectItem preSelectItem = selectList.get(i - 1);\n//                if (preSelectItem.hasAfterComment()) {\n//                    print(' ');\n//                    printlnComment(preSelectItem.getAfterCommentsDirect());\n//                }\n//\n//                println();\n//                print0(\", \");\n//            }\n//\n//            selectItem.accept(this);\n//\n//            if (i == selectList.size() - 1 && selectItem.hasAfterComment()) {\n//                print(' ');\n//                printlnComments(selectItem.getAfterCommentsDirect());\n//            }\n//        }\n//        this.indentCount--;\n//    }\n\n    @Override\n    public boolean visit(SQLSubqueryTableSource x) {\n        print('(');\n        this.indentCount++;\n        println();\n        x.getSelect().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        SQLPivot pivot = x.getPivot();\n        if (pivot != null) {\n            println();\n            pivot.accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        if (x.getAlias() != null) {\n            print(' ');\n            print0(x.getAlias());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLJoinTableSource x) {\n        SQLTableSource left = x.getLeft();\n        left.accept(this);\n\n        SQLTableSource right = x.getRight();\n        JoinType joinType = x.getJoinType();\n        if (joinType == JoinType.CROSS_JOIN\n                && right instanceof SQLUnnestTableSource\n        ) {\n            SQLUnnestTableSource unnest = (SQLUnnestTableSource) right;\n            if (unnest.isOrdinality()) {\n                print0(ucase ? \" LATERAL VIEW POSEXPLODE(\" : \" lateral view posexplode(\");\n            } else {\n                print0(ucase ? \" LATERAL VIEW EXPLODE(\" : \" lateral view explode(\");\n            }\n            List<SQLExpr> items = unnest.getItems();\n            printAndAccept(items, \", \");\n            print(')');\n\n            if (right.getAlias() != null) {\n                print(' ');\n                print0(right.getAlias());\n            }\n\n            final List<SQLName> columns = unnest.getColumns();\n            if (columns != null && columns.size() > 0) {\n                print0(ucase ? \" AS \" : \" as \");\n                printAndAccept(unnest.getColumns(), \", \");\n            }\n\n            return false;\n        }\n\n        if (joinType == JoinType.COMMA) {\n            print(',');\n        } else {\n            println();\n            printJoinType(joinType);\n        }\n\n        if (!(right instanceof SQLLateralViewTableSource)) {\n            print(' ');\n        }\n        right.accept(this);\n\n        if (x.getCondition() != null) {\n            println();\n            print0(ucase ? \"ON \" : \"on \");\n            this.indentCount++;\n            x.getCondition().accept(this);\n            this.indentCount--;\n            if (x.getAfterCommentsDirect() != null) {\n                printAfterComments(x.getAfterCommentsDirect());\n                println();\n            }\n        }\n\n        if (!x.getUsing().isEmpty()) {\n            print0(ucase ? \" USING (\" : \" using (\");\n            printAndAccept(x.getUsing(), \", \");\n            print(')');\n        }\n\n        if (x.getAlias() != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            print0(x.getAlias());\n        }\n\n        SQLJoinTableSource.UDJ udj = x.getUdj();\n        if (udj != null) {\n            println();\n            udj.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsUDTFSQLSelectItem x) {\n        x.getExpr().accept(this);\n\n        println();\n        print0(ucase ? \"AS (\" : \"as (\");\n\n        int aliasSize = x.getAliasList().size();\n        if (aliasSize > 5) {\n            this.indentCount++;\n            println();\n        }\n\n        for (int i = 0; i < aliasSize; ++i) {\n            if (i != 0) {\n                if (aliasSize > 5) {\n                    println(\",\");\n                } else {\n                    print0(\", \");\n                }\n            }\n            print0(x.getAliasList().get(i));\n        }\n\n        if (aliasSize > 5) {\n            this.indentCount--;\n            println();\n        }\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowStatisticStmt x) {\n        print0(ucase ? \"SHOW STATISTIC\" : \"show statistic\");\n        final SQLExprTableSource tableSource = x.getTableSource();\n        if (tableSource != null) {\n            print(' ');\n            tableSource.accept(this);\n        }\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (!partitions.isEmpty()) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(partitions, \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsSetLabelStatement x) {\n        print0(ucase ? \"SET LABEL \" : \"set label \");\n        print0(x.getLabel());\n        print0(ucase ? \" TO \" : \" to \");\n\n        if (x.getUser() != null) {\n            print0(ucase ? \"USER \" : \"user \");\n            x.getUser().accept(this);\n        } else if (x.getTable() != null) {\n            print0(ucase ? \"TABLE \" : \"table \");\n            x.getTable().accept(this);\n            if (x.getColumns().size() > 0) {\n                print('(');\n                printAndAccept(x.getColumns(), \", \");\n                print(')');\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsSelectQueryBlock x) {\n        if (isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        List<SQLCommentHint> hints = x.getHintsDirect();\n        if (hints != null) {\n            printAndAccept(hints, \" \");\n            print(' ');\n        }\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == x.getDistionOption()) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        }\n\n        printSelectList(x.getSelectList());\n\n        printFrom(x);\n        printWhere(x);\n        printGroupBy(x);\n        printWindow(x);\n        printQualify(x);\n        printOrderBy(x);\n\n        SQLZOrderBy zorderBy = x.getZOrderBy();\n        if (zorderBy != null) {\n            println();\n            zorderBy.accept(this);\n        }\n\n        final List<SQLSelectOrderByItem> distributeBy = x.getDistributeByDirect();\n        if (distributeBy.size() > 0) {\n            println();\n            print0(ucase ? \"DISTRIBUTE BY \" : \"distribute by \");\n            printAndAccept(distributeBy, \", \");\n        }\n\n        final List<SQLSelectOrderByItem> sortBy = x.getSortByDirect();\n        if (!sortBy.isEmpty()) {\n            println();\n            print0(ucase ? \"SORT BY \" : \"sort by \");\n            printAndAccept(sortBy, \", \");\n        }\n\n        final List<SQLSelectOrderByItem> clusterBy = x.getClusterByDirect();\n        if (clusterBy.size() > 0) {\n            println();\n            print0(ucase ? \"CLUSTER BY \" : \"cluster by \");\n            printAndAccept(clusterBy, \", \");\n        }\n\n        printLimit(x);\n\n        return false;\n    }\n\n    public boolean visit(SQLOrderBy x) {\n        int itemSize = x.getItems().size();\n        if (itemSize > 0) {\n            print0(ucase ? \"ORDER BY \" : \"order by \");\n            this.indentCount++;\n            for (int i = 0; i < itemSize; ++i) {\n                if (i != 0) {\n                    println(\", \");\n                }\n                x.getItems().get(i).accept(this);\n            }\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLZOrderBy x) {\n        int itemSize = x.getItems().size();\n        if (itemSize > 0) {\n            print0(ucase ? \"ZORDER BY \" : \"zorder by \");\n            this.indentCount++;\n            for (int i = 0; i < itemSize; ++i) {\n                if (i != 0) {\n                    println(\", \");\n                }\n                x.getItems().get(i).accept(this);\n            }\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAddStatisticStatement x) {\n        print0(ucase ? \"ADD STATISTIC \" : \"add statistic \");\n        x.getTable().accept(this);\n        print(' ');\n        x.getStatisticClause().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsRemoveStatisticStatement x) {\n        print0(ucase ? \"REMOVE STATISTIC \" : \"remove statistic \");\n        x.getTable().accept(this);\n        print(' ');\n        x.getStatisticClause().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsStatisticClause.TableCount x) {\n        print0(ucase ? \"TABLE_COUNT\" : \"table_count\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsStatisticClause.ExpressionCondition x) {\n        print0(ucase ? \"EXPRESSION_CONDITION \" : \"expression_condition \");\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsStatisticClause.NullValue x) {\n        print0(ucase ? \"NULL_VALUE \" : \"null_value \");\n        x.getColumn().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsStatisticClause.DistinctValue x) {\n        print0(ucase ? \"DISTINCT_VALUE \" : \"distinct_value \");\n        x.getColumn().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsStatisticClause.ColumnSum x) {\n        print0(ucase ? \"COLUMN_SUM \" : \"column_sum \");\n        x.getColumn().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsStatisticClause.ColumnMax x) {\n        print0(ucase ? \"COLUMN_MAX \" : \"column_max \");\n        x.getColumn().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsStatisticClause.ColumnMin x) {\n        print0(ucase ? \"COLUMN_MIN \" : \"column_min \");\n        x.getColumn().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsReadStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"READ \" : \"read \");\n        x.getTable().accept(this);\n\n        if (!x.getColumns().isEmpty()) {\n            print0(\" (\");\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        if (!x.getPartition().isEmpty()) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print(')');\n        }\n\n        if (x.getRowCount() != null) {\n            print(' ');\n            x.getRowCount().accept(this);\n        }\n\n        return false;\n    }\n\n    protected void printMethodOwner(SQLExpr owner) {\n        owner.accept(this);\n        if (owner instanceof SQLMethodInvokeExpr || owner instanceof SQLPropertyExpr) {\n            print('.');\n        } else {\n            print(':');\n        }\n    }\n\n    protected void printJoinType(JoinType joinType) {\n        if (joinType.equals(JoinType.LEFT_OUTER_JOIN)) {\n            print0(ucase ? \"LEFT OUTER JOIN\" : \"left outer join\");\n        } else if (joinType.equals(JoinType.RIGHT_OUTER_JOIN)) {\n            print0(ucase ? \"RIGHT OUTER JOIN\" : \"right outer join\");\n        } else if (joinType.equals(JoinType.FULL_OUTER_JOIN)) {\n            print0(ucase ? \"FULL OUTER JOIN\" : \"full outer join\");\n        } else {\n            print0(ucase ? joinType.name : joinType.nameLCase);\n        }\n    }\n\n    public boolean visit(SQLDataType x) {\n        String dataTypeName = x.getName();\n        if (dataTypeName.indexOf('<') != -1 || dataTypeName.equals(\"Object\")) {\n            print0(dataTypeName);\n        } else {\n            print0(ucase ? dataTypeName.toUpperCase() : dataTypeName.toLowerCase());\n        }\n\n        if (!x.getArguments().isEmpty()) {\n            print('(');\n            printAndAccept(x.getArguments(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    protected void printFunctionName(String name) {\n        if (name == null) {\n            return;\n        }\n\n        String upperName = name.toUpperCase();\n        if (builtInFunctions.contains(upperName)) {\n            print0(ucase ? upperName : name);\n        } else {\n            print0(name);\n        }\n    }\n\n    @Override\n    public boolean visit(OdpsShowGrantsStmt x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        if (x.isLabel()) {\n            print0(ucase ? \"SHOW LABEL GRANTS\" : \"show label grants\");\n\n            if (x.getObjectType() != null) {\n                print0(ucase ? \" ON TABLE \" : \" on table \");\n                x.getObjectType().accept(this);\n            }\n\n            if (x.getUser() != null) {\n                print0(ucase ? \" FOR USER \" : \" for user \");\n                x.getUser().accept(this);\n            }\n        } else {\n            print0(ucase ? \"SHOW GRANTS\" : \"show grants\");\n\n            if (x.getUser() != null) {\n                print0(ucase ? \" FOR \" : \" for \");\n                x.getUser().accept(this);\n            }\n\n            if (x.getObjectType() != null) {\n                print0(ucase ? \" ON TYPE \" : \" on type \");\n                x.getObjectType().accept(this);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsListStmt x) {\n        print0(ucase ? \"LIST \" : \"list \");\n        if (x.getObject() != null) {\n            x.getObject().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsGrantStmt x) {\n        print0(ucase ? \"GRANT \" : \"grant \");\n        if (x.isSuper()) {\n            print0(ucase ? \"SUPER \" : \"super \");\n        }\n\n        if (x.isLabel()) {\n            print0(ucase ? \"LABEL \" : \"label \");\n            x.getLabel().accept(this);\n        } else {\n            printAndAccept(x.getPrivileges(), \", \");\n        }\n\n        if (x.getResource() != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            if (x.getResourceType() != null) {\n                print0(ucase ? x.getResourceType().name() : x.getResourceType().name().toLowerCase());\n                print(' ');\n            }\n            x.getResource().accept(this);\n\n            if (x.getColumns().size() > 0) {\n                print('(');\n                printAndAccept(x.getColumns(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.getUsers() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            if (x.getSubjectType() != null) {\n                print0(x.getSubjectType().name());\n                print(' ');\n            }\n            printAndAccept(x.getUsers(), \",\");\n        }\n\n        if (x.getExpire() != null) {\n            print0(ucase ? \" WITH EXP \" : \" with exp \");\n            x.getExpire().accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCharExpr x, boolean parameterized) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        String text = x.getText();\n        if (text == null) {\n            print0(ucase ? \"NULL\" : \"null\");\n        } else {\n            StringBuilder buf = new StringBuilder(text.length() + 2);\n            buf.append('\\'');\n            for (int i = 0; i < text.length(); ++i) {\n                char ch = text.charAt(i);\n                switch (ch) {\n                    case '\\\\':\n                        buf.append(\"\\\\\\\\\");\n                        break;\n                    case '\\'':\n                        buf.append(\"\\\\'\");\n                        break;\n                    case '\\0':\n                        buf.append(\"\\\\0\");\n                        break;\n                    case '\\n':\n                        buf.append(\"\\\\n\");\n                        break;\n                    default:\n                        buf.append(ch);\n                        break;\n                }\n            }\n            buf.append('\\'');\n\n            print0(buf.toString());\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRenameColumn x) {\n        print0(ucase ? \"CHANGE COLUMN \" : \"change column \");\n        x.getColumn().accept(this);\n        print0(ucase ? \" RENAME TO \" : \" rename to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAddTableStatement x) {\n        print0(ucase ? \"ADD TABLE \" : \"add table \");\n        x.getTable().accept(this);\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (partitions.size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(partitions, \", \");\n            print(')');\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            printExpr(comment);\n        }\n\n        if (x.isForce()) {\n            print0(\" -f\");\n        }\n\n        SQLName toPackage = x.getToPackage();\n        if (toPackage != null) {\n            print0(ucase ? \" TO PACKAGE \" : \" to package \");\n            printExpr(toPackage);\n\n            List<SQLPrivilegeItem> privileges = x.getPrivileges();\n            if (!privileges.isEmpty()) {\n                print0(ucase ? \" WITH PRIVILEGES \" : \" with privileges \");\n                printAndAccept(privileges, \", \");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAddFileStatement x) {\n        print0(ucase ? \"ADD \" : \"add \");\n\n        OdpsAddFileStatement.FileType type = x.getType();\n        switch (type) {\n            case JAR:\n                print0(ucase ? \"JAR \" : \"jar \");\n                break;\n            case ARCHIVE:\n                print0(ucase ? \"ARCHIVE \" : \"archive \");\n                break;\n            case PY:\n                print0(ucase ? \"PY \" : \"py \");\n                break;\n            default:\n                print0(ucase ? \"FILE \" : \"file \");\n                break;\n        }\n\n        print0(x.getFile());\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            printExpr(comment);\n        }\n\n        if (x.isForce()) {\n            print0(\" -f\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAddUserStatement x) {\n        print0(ucase ? \"ADD USER \" : \"add user \");\n        printExpr(x.getUser());\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsRemoveUserStatement x) {\n        print0(ucase ? \"REMOVE USER \" : \"remove user \");\n        printExpr(x.getUser());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLWhoamiStatement x) {\n        print0(ucase ? \"WHOAMI\" : \"whoami\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAlterTableSetChangeLogs x) {\n        print0(ucase ? \"SET CHANGELOGS \" : \"set changelogs \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAlterTableChangeOwner x) {\n        print0(ucase ? \"CHANGEOWNER TO \" : \"changeowner to \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAlterTableSetFileFormat x) {\n        print0(ucase ? \"SET FILEFORMAT \" : \"set fileformat \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsCountStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"COUNT \" : \"count \");\n        x.getTable().accept(this);\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (partitions.size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(partitions, \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsQueryAliasStatement x) {\n        print0(x.getVariant());\n        print0(\" := \");\n        x.getStatement().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsTransformExpr x) {\n        print0(ucase ? \"TRANSFORM(\" : \"transform(\");\n        printAndAccept(x.getInputColumns(), \", \");\n        print(')');\n\n        SQLExpr using = x.getUsing();\n        if (using != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            using.accept(this);\n        }\n\n        List<SQLExpr> resources = x.getResources();\n        if (!resources.isEmpty()) {\n            println();\n            print0(ucase ? \"RESOURCES \" : \"resources \");\n            printAndAccept(resources, \", \");\n        }\n\n        List<SQLColumnDefinition> outputColumns = x.getOutputColumns();\n        if (!outputColumns.isEmpty()) {\n            println();\n            print0(ucase ? \"AS (\" : \"as (\");\n            printAndAccept(outputColumns, \", \");\n            print(')');\n        }\n\n        SQLExternalRecordFormat inputRowFormat = x.getInputRowFormat();\n        if (inputRowFormat != null) {\n            println();\n            print0(ucase ? \"ROW FORMAT DELIMITED\" : \"row format delimited\");\n            inputRowFormat.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsExstoreStatement x) {\n        print0(ucase ? \"EXSTORE \" : \"exstore \");\n        x.getTable().accept(this);\n        print0(ucase ? \" PARTITION (\" : \" partition (\");\n        printAndAccept(x.getPartitions(), \", \");\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(HiveLoadDataStatement x) {\n        print0(ucase ? \"LOAD \" : \"load \");\n\n        if (x.isOverwrite()) {\n            print0(ucase ? \"OVERWRITE \" : \"overwrite \");\n        }\n\n        print0(ucase ? \"INTO TABLE \" : \"into table \");\n\n        x.getInto().accept(this);\n\n        if (x.getPartition().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print(')');\n        }\n\n        println();\n        print0(ucase ? \"LOCATION \" : \"location \");\n        x.getInpath().accept(this);\n\n        printStoredBy(x.getStoredBy());\n\n        SQLExpr rowFormat = x.getRowFormat();\n        if (rowFormat != null) {\n            println();\n            print0(ucase ? \"ROW FORMAT SERDE \" : \"row format serde \");\n            rowFormat.accept(this);\n        }\n\n        printSerdeProperties(x.getSerdeProperties());\n\n        SQLExpr storedAs = x.getStoredAs();\n        if (storedAs != null) {\n            println();\n            print0(ucase ? \"STORED AS \" : \"stored as \");\n            printExpr(storedAs);\n        }\n\n        SQLExpr using = x.getUsing();\n        if (using != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            printExpr(using);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsNewExpr x) {\n        print0(\"new \");\n        super.visit((SQLMethodInvokeExpr) x);\n        return false;\n    }\n\n    public boolean visit(OdpsInstallPackageStatement x) {\n        print0(ucase ? \"INSTALL PACKAGE \" : \"install package \");\n        printExpr(x.getPackageName());\n        return false;\n    }\n\n    public boolean visit(OdpsPAIStmt x) {\n        print0(ucase ? \"PAI \" : \"pai \");\n        print0(x.getArguments());\n        return false;\n    }\n\n    public boolean visit(OdpsCopyStmt x) {\n        print0(ucase ? \"COPY \" : \"copy \");\n        print0(x.getArguments());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCurrentTimeExpr x) {\n        final SQLCurrentTimeExpr.Type type = x.getType();\n        print(ucase ? type.name : type.nameLCase);\n        print0(\"()\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropDatabaseStatement x) {\n        print0(ucase ? \"DROP \" : \"drop \");\n\n        if (x.isPhysical()) {\n            print0(ucase ? \"PHYSICAL \" : \"physical \");\n        }\n\n        print0(ucase ? \"SCHEMA \" : \"schema \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getDatabase().accept(this);\n\n        final Boolean restrict = x.getRestrict();\n        if (restrict != null && restrict.booleanValue()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n\n        return false;\n    }\n\n    protected void printMethodParameters(SQLMethodInvokeExpr x) {\n        List<SQLExpr> arguments = x.getArguments();\n\n        boolean needPrintLine = false;\n        if (arguments.size() > 10\n                && (arguments.size() % 2) == 0\n                && (x.methodNameHashCode64() == FnvHash.Constants.NAMED_STRUCT\n                || x.methodNameHashCode64() == FnvHash.Constants.MAP)\n        ) {\n            needPrintLine = true;\n        }\n        if (needPrintLine) {\n            print0('(');\n            incrementIndent();\n            println();\n            for (int i = 0, size = arguments.size(); i < size; i += 2) {\n                if (i != 0) {\n                    print0(',');\n                    println();\n                }\n\n                SQLExpr arg0 = arguments.get(i);\n                SQLExpr arg1 = arguments.get(i + 1);\n                printExpr(arg0);\n                this.print0(\", \");\n                printExpr(arg1);\n            }\n            decrementIndent();\n            println();\n            print0(')');\n            return;\n        }\n        super.printMethodParameters(x);\n    }\n\n    @Override\n    public void printMergeInsertRow() {\n        print(\" *\");\n    }\n\n    @Override\n    public boolean visit(SQLNotExpr x) {\n        tryPrintLparen(x);\n        print0(ucase ? \"NOT \" : \"not \");\n        SQLExpr expr = x.getExpr();\n\n        boolean needParentheses = false;\n\n        if (expr instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr;\n            needParentheses = binaryOpExpr.getOperator().isLogical();\n            if (binaryOpExpr.isParenthesized()) {\n                needParentheses = false;\n            }\n        } else if (expr instanceof SQLInListExpr || expr instanceof SQLNotExpr\n                || expr instanceof SQLBinaryOpExprGroup || expr instanceof SQLQueryExpr) {\n            needParentheses = true;\n        }\n        if (expr instanceof SQLExprImpl) {\n            SQLExprImpl exprImpl = (SQLExprImpl) expr;\n            if (exprImpl.getParenthesizedCount() > 0) {\n                needParentheses = false;\n            }\n        }\n\n        if (needParentheses) {\n            print('(');\n        }\n        if (needParentheses\n                && expr instanceof SQLQueryExpr\n                && isPrettyFormat()\n                && indentCount > 0) {\n            this.indentCount++;\n            println();\n            printExpr(expr, parameterized);\n            this.indentCount--;\n            println();\n            print(')');\n        } else {\n            printExpr(expr, parameterized);\n            if (needParentheses) {\n                print(')');\n            }\n        }\n        tryPrintRparen(x);\n\n        SQLCommentHint hint = x.getHint();\n        if (hint != null) {\n            hint.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBinaryOpExpr x) {\n        int parenCount = x.getParenthesizedCount();\n        if (parenCount <= 0 && x.isParenthesized()) {\n            parenCount = 1;\n        }\n        for (int i = 0; i < parenCount; i++) {\n            print('(');\n        }\n\n        boolean rs = visitInternal(x);\n\n        for (int i = 0; i < parenCount; i++) {\n            print(')');\n        }\n\n        List<String> afterComments = x.getAfterCommentsDirect();\n        if (!parameterized) {\n            if (afterComments != null && !afterComments.isEmpty() && isPrettyFormat()) {\n                print(' ');\n            }\n            printlnComment(afterComments);\n        }\n        return rs;\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        SQLObject parent = x.getParent();\n        if (parent instanceof SQLSelect) {\n            parent = parent.getParent();\n        }\n\n        // ODPS特殊处理：在二元运算符中，query表达式需要括号\n        if (parent instanceof SQLBinaryOpExpr) {\n            print('(');\n            SQLSelect subQuery = x.getSubQuery();\n            if (subQuery != null) {\n                if (isPrettyFormat() && indentCount > 0) {\n                    this.indentCount++;\n                    println();\n                    subQuery.accept(this);\n                    this.indentCount--;\n                    println();\n                } else {\n                    subQuery.accept(this);\n                }\n            }\n            print(')');\n            return false;\n        }\n\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        SQLSelect subQuery = x.getSubQuery();\n        if (subQuery != null) {\n            if (parent instanceof SQLInsertStatement.ValuesClause) {\n                println();\n                subQuery.accept(this);\n                println();\n            } else if ((parent instanceof SQLStatement\n                    && !(parent instanceof OracleForStatement))\n                    || (parent instanceof SQLSelectItem\n                    && (parent.getParent() instanceof SQLPivot || parent.getParent() instanceof SQLUnpivot))\n            ) {\n                this.indentCount++;\n\n                println();\n                subQuery.accept(this);\n\n                this.indentCount--;\n            } else if (parent instanceof SQLOpenStatement) {\n                println();\n                subQuery.accept(this);\n                println();\n            } else {\n                subQuery.accept(this);\n            }\n        }\n        if (x.isParenthesized()) {\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLListExpr x) {\n        // ODPS特殊处理：支持多层括号\n        int parenCount = x.getParenthesizedCount();\n        for (int i = 0; i < parenCount; i++) {\n            print('(');\n        }\n        if (parenCount == 0) {\n            print('(');\n        }\n        printAndAccept(x.getItems(), \", \");\n        for (int i = 0; i < parenCount; i++) {\n            print(')');\n        }\n        if (parenCount == 0) {\n            print(')');\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsSchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.odps.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.odps.ast.*;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\npublic class OdpsSchemaStatVisitor extends HiveSchemaStatVisitor implements OdpsASTVisitor {\n    public OdpsSchemaStatVisitor() {\n        super(DbType.odps);\n    }\n\n    public OdpsSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    @Override\n    public boolean visit(OdpsSetLabelStatement x) {\n        if (x.getTable() != null) {\n            x.getTable().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAddUserStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsRemoveUserStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAlterTableSetChangeLogs x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsAddTableStatement x) {\n        SQLExprTableSource table = x.getTable();\n        TableStat stat = getTableStatWithUnwrap(table.getExpr());\n        if (stat != null) {\n            stat.incrementAddCount();\n        }\n\n        resolvePartitions(table, x.getPartitions());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsUnloadStatement x) {\n        SQLExprTableSource table = (SQLExprTableSource) x.getFrom();\n        TableStat stat = getTableStatWithUnwrap(table.getExpr());\n        if (stat != null) {\n            stat.incrementSelectCount();\n        }\n\n        resolvePartitions(table, x.getPartitions());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsCountStatement x) {\n        SQLExprTableSource table = x.getTable();\n        TableStat stat = getTableStatWithUnwrap(table.getExpr());\n        if (stat != null) {\n            stat.incrementSelectCount();\n        }\n\n        resolvePartitions(table, x.getPartitions());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OdpsExstoreStatement x) {\n        SQLExprTableSource table = x.getTable();\n        TableStat stat = getTableStatWithUnwrap(table.getExpr());\n        if (stat != null) {\n            stat.incrementSelectCount();\n        }\n\n        resolvePartitions(table, x.getPartitions());\n\n        return false;\n    }\n\n    private void resolvePartitions(SQLExprTableSource table, List<SQLAssignItem> parttions) {\n        for (SQLAssignItem partition : parttions) {\n            SQLExpr target = partition.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr columnName = (SQLIdentifierExpr) target;\n                columnName.setResolvedTableSource(table);\n                columnName.accept(this);\n            }\n        }\n    }\n\n    public boolean visit(OdpsSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/Oracle.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Oracle {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.oracle);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalDay.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast;\n\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleDataTypeIntervalDay extends SQLDataTypeImpl implements OracleSQLObject {\n    private boolean toSecond;\n\n    protected final List<SQLExpr> fractionalSeconds = new ArrayList<SQLExpr>();\n\n    public OracleDataTypeIntervalDay() {\n        this.setName(\"INTERVAL DAY\");\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getArguments());\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isToSecond() {\n        return toSecond;\n    }\n\n    public void setToSecond(boolean toSecond) {\n        this.toSecond = toSecond;\n    }\n\n    public List<SQLExpr> getFractionalSeconds() {\n        return fractionalSeconds;\n    }\n\n    public OracleDataTypeIntervalDay clone() {\n        OracleDataTypeIntervalDay x = new OracleDataTypeIntervalDay();\n\n        super.cloneTo(x);\n\n        for (SQLExpr arg : fractionalSeconds) {\n            arg.setParent(x);\n            x.fractionalSeconds.add(arg);\n        }\n\n        return x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleDataTypeIntervalYear.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast;\n\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleDataTypeIntervalYear extends SQLDataTypeImpl implements OracleSQLObject {\n    public OracleDataTypeIntervalYear() {\n        this.setName(\"INTERVAL YEAR\");\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getArguments());\n        }\n        visitor.endVisit(this);\n    }\n\n    public OracleDataTypeIntervalYear clone() {\n        OracleDataTypeIntervalYear x = new OracleDataTypeIntervalYear();\n\n        super.cloneTo(x);\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OraclePartitionSingle.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLPartitionSingle;\nimport com.alibaba.druid.sql.ast.SQLSubPartition;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OraclePartitionSingle extends SQLPartitionSingle implements OracleSegmentAttributes {\n    protected boolean segmentCreationImmediate;\n    protected boolean segmentCreationDeferred;\n    protected SQLObject lobStorage;\n    private Integer pctfree;\n    private Integer pctused;\n    private Integer initrans;\n\n    private Integer maxtrans;\n    private Integer pctincrease;\n    private Integer freeLists;\n    private Boolean compress;\n    private Integer compressLevel;\n    private boolean compressForOltp;\n    private Integer pctthreshold;\n\n    private Boolean logging;\n    protected SQLObject storage;\n    public SQLExpr getLocality() {\n        return locality;\n    }\n\n    public void setLocality(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.locality = x;\n    }\n    public SQLObject getLobStorage() {\n        return lobStorage;\n    }\n\n    public void setLobStorage(SQLObject lobStorage) {\n        if (lobStorage != null) {\n            lobStorage.setParent(this);\n        }\n        this.lobStorage = lobStorage;\n    }\n\n    public boolean isSegmentCreationImmediate() {\n        return segmentCreationImmediate;\n    }\n\n    public void setSegmentCreationImmediate(boolean segmentCreationImmediate) {\n        this.segmentCreationImmediate = segmentCreationImmediate;\n    }\n\n    public boolean isSegmentCreationDeferred() {\n        return segmentCreationDeferred;\n    }\n\n    public void setSegmentCreationDeferred(boolean segmentCreationDeferred) {\n        this.segmentCreationDeferred = segmentCreationDeferred;\n    }\n\n    @Override\n    public Integer getPctfree() {\n        return pctfree;\n    }\n\n    @Override\n    public void setPctfree(Integer pctfree) {\n        this.pctfree = pctfree;\n    }\n\n    @Override\n    public Integer getPctused() {\n        return pctused;\n    }\n\n    @Override\n    public void setPctused(Integer pctused) {\n        this.pctused = pctused;\n    }\n\n    @Override\n    public Integer getInitrans() {\n        return initrans;\n    }\n\n    @Override\n    public void setInitrans(Integer initrans) {\n        this.initrans = initrans;\n    }\n\n    @Override\n    public Integer getMaxtrans() {\n        return maxtrans;\n    }\n\n    @Override\n    public void setMaxtrans(Integer maxtrans) {\n        this.maxtrans = maxtrans;\n    }\n\n    @Override\n    public Integer getPctincrease() {\n        return pctincrease;\n    }\n\n    @Override\n    public void setPctincrease(Integer pctincrease) {\n        this.pctincrease = pctincrease;\n    }\n\n    public Integer getFreeLists() {\n        return freeLists;\n    }\n\n    public void setFreeLists(Integer freeLists) {\n        this.freeLists = freeLists;\n    }\n\n    @Override\n    public Boolean getCompress() {\n        return compress;\n    }\n\n    @Override\n    public void setCompress(Boolean compress) {\n        this.compress = compress;\n    }\n\n    @Override\n    public Integer getCompressLevel() {\n        return compressLevel;\n    }\n\n    @Override\n    public void setCompressLevel(Integer compressLevel) {\n        this.compressLevel = compressLevel;\n    }\n\n    @Override\n    public boolean isCompressForOltp() {\n        return compressForOltp;\n    }\n\n    @Override\n    public void setCompressForOltp(boolean compressForOltp) {\n        this.compressForOltp = compressForOltp;\n    }\n\n    public Integer getPctthreshold() {\n        return pctthreshold;\n    }\n\n    public void setPctthreshold(Integer pctthreshold) {\n        this.pctthreshold = pctthreshold;\n    }\n\n    @Override\n    public Boolean getLogging() {\n        return logging;\n    }\n\n    @Override\n    public void setLogging(Boolean logging) {\n        this.logging = logging;\n    }\n\n    @Override\n    public SQLObject getStorage() {\n        return storage;\n    }\n\n    @Override\n    public void setStorage(SQLObject storage) {\n        this.storage = storage;\n    }\n\n    @Override\n    public OraclePartitionSingle clone() {\n        OraclePartitionSingle x = new OraclePartitionSingle();\n\n        if (name != null) {\n            x.setName(name.clone());\n        }\n\n        if (subPartitionsCount != null) {\n            x.setSubPartitionsCount(subPartitionsCount.clone());\n        }\n\n        for (SQLSubPartition p : subPartitions) {\n            SQLSubPartition p2 = p.clone();\n            p2.setParent(x);\n            x.subPartitions.add(p2);\n        }\n\n        if (values != null) {\n            x.setValues(values.clone());\n        }\n\n        x.segmentCreationImmediate = segmentCreationImmediate;\n        x.segmentCreationDeferred = segmentCreationDeferred;\n\n        if (lobStorage != null) {\n            x.setLobStorage(lobStorage.clone());\n        }\n\n        return x;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, values);\n            acceptChild(visitor, tablespace);\n            acceptChild(visitor, subPartitionsCount);\n            acceptChild(visitor, storage);\n            acceptChild(visitor, subPartitions);\n            acceptChild(visitor, locality);\n            acceptChild(visitor, lobStorage);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSQLObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic interface OracleSQLObject extends SQLObject {\n    void accept0(OracleASTVisitor v);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSQLObjectImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class OracleSQLObjectImpl extends SQLObjectImpl implements OracleSQLObject {\n    public OracleSQLObjectImpl() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof OracleASTVisitor) {\n            this.accept0((OracleASTVisitor) v);\n            return;\n        }\n\n        if (v instanceof SQLASTOutputVisitor) {\n            ((SQLASTOutputVisitor) v).print(this.toString());\n        }\n    }\n\n    public abstract void accept0(OracleASTVisitor visitor);\n\n    public OracleSQLObject clone() {\n        throw new UnsupportedOperationException(this.getClass().getName());\n    }\n\n    public SQLDataType computeDataType() {\n        return null;\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSegmentAttributes.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\n\n/**\n * Created by wenshao on 21/05/2017.\n */\npublic interface OracleSegmentAttributes extends SQLObject {\n    SQLName getTablespace();\n\n    void setTablespace(SQLName name);\n\n    Boolean getCompress();\n\n    void setCompress(Boolean compress);\n\n    Integer getCompressLevel();\n\n    void setCompressLevel(Integer compressLevel);\n\n    Integer getInitrans();\n\n    void setInitrans(Integer initrans);\n\n    Integer getMaxtrans();\n\n    void setMaxtrans(Integer maxtrans);\n\n    Integer getPctincrease();\n\n    void setPctincrease(Integer pctincrease);\n\n    Integer getPctused();\n\n    void setPctused(Integer pctused);\n\n    Integer getPctfree();\n\n    void setPctfree(Integer ptcfree);\n\n    Boolean getLogging();\n\n    void setLogging(Boolean logging);\n\n    SQLObject getStorage();\n\n    void setStorage(SQLObject storage);\n\n    boolean isCompressForOltp();\n\n    void setCompressForOltp(boolean compressForOltp);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleSegmentAttributesImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\n\n/**\n * Created by wenshao on 21/05/2017.\n */\npublic abstract class OracleSegmentAttributesImpl extends SQLObjectImpl implements OracleSegmentAttributes {\n    private Integer pctfree;\n    private Integer pctused;\n    private Integer initrans;\n\n    private Integer maxtrans;\n    private Integer pctincrease;\n    private Integer freeLists;\n    private Boolean compress;\n    private Integer compressLevel;\n    private boolean compressForOltp;\n    private Integer pctthreshold;\n\n    private Boolean logging;\n\n    protected SQLName tablespace;\n    protected SQLObject storage;\n\n    public SQLName getTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.tablespace = x;\n    }\n\n    public Boolean getCompress() {\n        return compress;\n    }\n\n    public void setCompress(Boolean compress) {\n        this.compress = compress;\n    }\n\n    public Integer getCompressLevel() {\n        return compressLevel;\n    }\n\n    public void setCompressLevel(Integer compressLevel) {\n        this.compressLevel = compressLevel;\n    }\n\n    public Integer getPctthreshold() {\n        return pctthreshold;\n    }\n\n    public void setPctthreshold(Integer pctthreshold) {\n        this.pctthreshold = pctthreshold;\n    }\n\n    public Integer getPctfree() {\n        return pctfree;\n    }\n\n    public void setPctfree(Integer ptcfree) {\n        this.pctfree = ptcfree;\n    }\n\n    public Integer getPctused() {\n        return pctused;\n    }\n\n    public void setPctused(Integer ptcused) {\n        this.pctused = ptcused;\n    }\n\n    public Integer getInitrans() {\n        return initrans;\n    }\n\n    public void setInitrans(Integer initrans) {\n        this.initrans = initrans;\n    }\n\n    public Integer getMaxtrans() {\n        return maxtrans;\n    }\n\n    public void setMaxtrans(Integer maxtrans) {\n        this.maxtrans = maxtrans;\n    }\n\n    public Integer getPctincrease() {\n        return pctincrease;\n    }\n\n    public void setPctincrease(Integer pctincrease) {\n        this.pctincrease = pctincrease;\n    }\n\n    public Integer getFreeLists() {\n        return freeLists;\n    }\n\n    public void setFreeLists(Integer freeLists) {\n        this.freeLists = freeLists;\n    }\n\n    public Boolean getLogging() {\n        return logging;\n    }\n\n    public void setLogging(Boolean logging) {\n        this.logging = logging;\n    }\n\n    public SQLObject getStorage() {\n        return storage;\n    }\n\n    public void setStorage(SQLObject storage) {\n        this.storage = storage;\n    }\n\n    public boolean isCompressForOltp() {\n        return compressForOltp;\n    }\n\n    public void setCompressForOltp(boolean compressForOltp) {\n        this.compressForOltp = compressForOltp;\n    }\n\n    public void cloneTo(OracleSegmentAttributesImpl x) {\n        x.pctfree = pctfree;\n        x.pctused = pctused;\n        x.initrans = initrans;\n\n        x.maxtrans = maxtrans;\n        x.pctincrease = pctincrease;\n        x.freeLists = freeLists;\n        x.compress = compress;\n        x.compressLevel = compressLevel;\n        x.compressForOltp = compressForOltp;\n        x.pctthreshold = pctthreshold;\n\n        x.logging = logging;\n\n        if (tablespace != null) {\n            x.setTablespace(tablespace.clone());\n        }\n\n        if (storage != null) {\n            x.setStorage(storage.clone());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/CycleClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class CycleClause extends OracleSQLObjectImpl {\n    private final List<SQLExpr> aliases = new ArrayList<SQLExpr>();\n    private SQLExpr mark;\n    private SQLExpr value;\n    private SQLExpr defaultValue;\n\n    public SQLExpr getMark() {\n        return mark;\n    }\n\n    public void setMark(SQLExpr mark) {\n        if (mark != null) {\n            mark.setParent(this);\n        }\n        this.mark = mark;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.value = value;\n    }\n\n    public SQLExpr getDefaultValue() {\n        return defaultValue;\n    }\n\n    public void setDefaultValue(SQLExpr defaultValue) {\n        if (defaultValue != null) {\n            defaultValue.setParent(this);\n        }\n        this.defaultValue = defaultValue;\n    }\n\n    public List<SQLExpr> getAliases() {\n        return aliases;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, aliases);\n            acceptChild(visitor, mark);\n            acceptChild(visitor, value);\n            acceptChild(visitor, defaultValue);\n        }\n        visitor.endVisit(this);\n    }\n\n    public CycleClause clone() {\n        CycleClause x = new CycleClause();\n\n        for (SQLExpr alias : aliases) {\n            SQLExpr alias2 = alias.clone();\n            alias2.setParent(x);\n            x.aliases.add(alias2);\n        }\n\n        if (mark != null) {\n            setMark(mark.clone());\n        }\n\n        if (value != null) {\n            setValue(value.clone());\n        }\n\n        if (defaultValue != null) {\n            setDefaultValue(defaultValue.clone());\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/ModelClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ModelClause extends OracleSQLObjectImpl {\n    private final List<CellReferenceOption> cellReferenceOptions = new ArrayList<CellReferenceOption>();\n    private ReturnRowsClause returnRowsClause;\n    private final List<ReferenceModelClause> referenceModelClauses = new ArrayList<ReferenceModelClause>();\n    private MainModelClause mainModel;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, returnRowsClause);\n            acceptChild(visitor, referenceModelClauses);\n            acceptChild(visitor, mainModel);\n        }\n        visitor.endVisit(this);\n    }\n\n    public MainModelClause getMainModel() {\n        return mainModel;\n    }\n\n    public void setMainModel(MainModelClause mainModel) {\n        this.mainModel = mainModel;\n    }\n\n    public ReturnRowsClause getReturnRowsClause() {\n        return returnRowsClause;\n    }\n\n    public void setReturnRowsClause(ReturnRowsClause returnRowsClause) {\n        this.returnRowsClause = returnRowsClause;\n    }\n\n    public List<ReferenceModelClause> getReferenceModelClauses() {\n        return referenceModelClauses;\n    }\n\n    public List<CellReferenceOption> getCellReferenceOptions() {\n        return cellReferenceOptions;\n    }\n\n    public static enum CellReferenceOption {\n        IgnoreNav(\"IGNORE NAV\"), KeepNav(\"KEEP NAV\"), UniqueDimension(\"UNIQUE DIMENSION\"),\n        UniqueSingleReference(\"UNIQUE SINGLE REFERENCE\");\n\n        public final String name;\n\n        CellReferenceOption() {\n            this(null);\n        }\n\n        CellReferenceOption(String name) {\n            this.name = name;\n        }\n\n        public String toString() {\n            return name;\n        }\n\n    }\n\n    public static class ReturnRowsClause extends OracleSQLObjectImpl {\n        private boolean all;\n\n        public boolean isAll() {\n            return all;\n        }\n\n        public void setAll(boolean all) {\n            this.all = all;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            visitor.visit(this);\n            visitor.endVisit(this);\n        }\n    }\n\n    public static class ReferenceModelClause extends OracleSQLObjectImpl {\n        private SQLExpr name;\n        private SQLSelect subQuery;\n        private final List<CellReferenceOption> cellReferenceOptions = new ArrayList<CellReferenceOption>();\n\n        public List<CellReferenceOption> getCellReferenceOptions() {\n            return cellReferenceOptions;\n        }\n\n        public SQLExpr getName() {\n            return name;\n        }\n\n        public void setName(SQLExpr name) {\n            this.name = name;\n        }\n\n        public SQLSelect getSubQuery() {\n            return subQuery;\n        }\n\n        public void setSubQuery(SQLSelect subQuery) {\n            this.subQuery = subQuery;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n        }\n    }\n\n    public static class ModelColumnClause extends OracleSQLObjectImpl {\n        private QueryPartitionClause queryPartitionClause;\n        private String alias;\n        private final List<ModelColumn> dimensionByColumns = new ArrayList<ModelColumn>();\n        private final List<ModelColumn> measuresColumns = new ArrayList<ModelColumn>();\n\n        public List<ModelColumn> getDimensionByColumns() {\n            return dimensionByColumns;\n        }\n\n        public List<ModelColumn> getMeasuresColumns() {\n            return measuresColumns;\n        }\n\n        public QueryPartitionClause getQueryPartitionClause() {\n            return queryPartitionClause;\n        }\n\n        public void setQueryPartitionClause(QueryPartitionClause queryPartitionClause) {\n            this.queryPartitionClause = queryPartitionClause;\n        }\n\n        public String getAlias() {\n            return alias;\n        }\n\n        public void setAlias(String alias) {\n            this.alias = alias;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, queryPartitionClause);\n                acceptChild(visitor, dimensionByColumns);\n                acceptChild(visitor, measuresColumns);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static class ModelColumn extends OracleSQLObjectImpl {\n        private SQLExpr expr;\n        private String alias;\n\n        public SQLExpr getExpr() {\n            return expr;\n        }\n\n        public void setExpr(SQLExpr expr) {\n            this.expr = expr;\n        }\n\n        public String getAlias() {\n            return alias;\n        }\n\n        public void setAlias(String alias) {\n            this.alias = alias;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, expr);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static class QueryPartitionClause extends OracleSQLObjectImpl {\n        private List<SQLExpr> exprList = new ArrayList<SQLExpr>();\n\n        public List<SQLExpr> getExprList() {\n            return exprList;\n        }\n\n        public void setExprList(List<SQLExpr> exprList) {\n            this.exprList = exprList;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, exprList);\n            }\n        }\n\n    }\n\n    public static class MainModelClause extends OracleSQLObjectImpl {\n        private SQLExpr mainModelName;\n        private ModelColumnClause modelColumnClause;\n\n        private final List<CellReferenceOption> cellReferenceOptions = new ArrayList<CellReferenceOption>();\n        private ModelRulesClause modelRulesClause;\n\n        public ModelRulesClause getModelRulesClause() {\n            return modelRulesClause;\n        }\n\n        public void setModelRulesClause(ModelRulesClause modelRulesClause) {\n            this.modelRulesClause = modelRulesClause;\n        }\n\n        public List<CellReferenceOption> getCellReferenceOptions() {\n            return cellReferenceOptions;\n        }\n\n        public ModelColumnClause getModelColumnClause() {\n            return modelColumnClause;\n        }\n\n        public void setModelColumnClause(ModelColumnClause modelColumnClause) {\n            this.modelColumnClause = modelColumnClause;\n        }\n\n        public SQLExpr getMainModelName() {\n            return mainModelName;\n        }\n\n        public void setMainModelName(SQLExpr mainModelName) {\n            this.mainModelName = mainModelName;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, mainModelName);\n                acceptChild(visitor, modelColumnClause);\n                acceptChild(visitor, modelRulesClause);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static class ModelRulesClause extends OracleSQLObjectImpl {\n        private final List<ModelRuleOption> options = new ArrayList<ModelRuleOption>();\n        private SQLExpr iterate;\n        private SQLExpr until;\n        private final List<CellAssignmentItem> cellAssignmentItems = new ArrayList<CellAssignmentItem>();\n\n        public SQLExpr getUntil() {\n            return until;\n        }\n\n        public void setUntil(SQLExpr until) {\n            this.until = until;\n        }\n\n        public SQLExpr getIterate() {\n            return iterate;\n        }\n\n        public void setIterate(SQLExpr iterate) {\n            this.iterate = iterate;\n        }\n\n        public List<ModelRuleOption> getOptions() {\n            return options;\n        }\n\n        public List<CellAssignmentItem> getCellAssignmentItems() {\n            return cellAssignmentItems;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, iterate);\n                acceptChild(visitor, until);\n                acceptChild(visitor, cellAssignmentItems);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static enum ModelRuleOption {\n        UPSERT(\"UPSERT\"), UPDATE(\"UPDATE\"), AUTOMATIC_ORDER(\"AUTOMATIC ORDER\"), SEQUENTIAL_ORDER(\"SEQUENTIAL ORDER\");\n\n        public final String name;\n\n        ModelRuleOption(String name) {\n            this.name = name;\n        }\n\n        public String toString() {\n            return name;\n        }\n    }\n\n    public static class CellAssignmentItem extends OracleSQLObjectImpl {\n        private ModelRuleOption option;\n        private CellAssignment cellAssignment;\n        private SQLOrderBy orderBy;\n        private SQLExpr expr;\n\n        public ModelRuleOption getOption() {\n            return option;\n        }\n\n        public void setOption(ModelRuleOption option) {\n            this.option = option;\n        }\n\n        public CellAssignment getCellAssignment() {\n            return cellAssignment;\n        }\n\n        public void setCellAssignment(CellAssignment cellAssignment) {\n            this.cellAssignment = cellAssignment;\n        }\n\n        public SQLOrderBy getOrderBy() {\n            return orderBy;\n        }\n\n        public void setOrderBy(SQLOrderBy orderBy) {\n            this.orderBy = orderBy;\n        }\n\n        public SQLExpr getExpr() {\n            return expr;\n        }\n\n        public void setExpr(SQLExpr expr) {\n            this.expr = expr;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, cellAssignment);\n                acceptChild(visitor, orderBy);\n                acceptChild(visitor, expr);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static class CellAssignment extends SQLExprImpl implements OracleExpr, SQLReplaceable {\n        private SQLExpr measureColumn;\n        private final List<SQLExpr> conditions = new ArrayList<SQLExpr>();\n\n        public List<SQLExpr> getConditions() {\n            return conditions;\n        }\n\n        public SQLExpr getMeasureColumn() {\n            return measureColumn;\n        }\n\n        public void setMeasureColumn(SQLExpr e) {\n            if (e != null) {\n                e.setParent(this);\n            }\n            this.measureColumn = e;\n        }\n\n        @Override\n        public boolean replace(SQLExpr expr, SQLExpr target) {\n            if (this.measureColumn == expr) {\n                setMeasureColumn(target);\n                return true;\n            }\n\n            for (int i = 0; i < conditions.size(); i++) {\n                if (conditions.get(i) == expr) {\n                    target.setParent(this);\n                    conditions.set(i, target);\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, measureColumn);\n                acceptChild(visitor, conditions);\n            }\n            visitor.endVisit(this);\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n\n            CellAssignment that = (CellAssignment) o;\n\n            if (measureColumn != null ? !measureColumn.equals(that.measureColumn) : that.measureColumn != null) {\n                return false;\n            }\n            return conditions.equals(that.conditions);\n        }\n\n        @Override\n        public int hashCode() {\n            int result = measureColumn != null ? measureColumn.hashCode() : 0;\n            result = 31 * result + conditions.hashCode();\n            return result;\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor visitor) {\n            accept0((OracleASTVisitor) visitor);\n        }\n\n        @Override\n        public SQLExpr clone() {\n            CellAssignment x = new CellAssignment();\n            if (measureColumn != null) {\n                x.setMeasureColumn(measureColumn.clone());\n            }\n            return null;\n        }\n\n        @Override\n        public List<SQLObject> getChildren() {\n            List children = new ArrayList();\n            children.add(measureColumn);\n            children.addAll(conditions);\n            return children;\n        }\n    }\n\n    public ModelClause clone() {\n        throw new UnsupportedOperationException();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleLobStorageClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributesImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleLobStorageClause extends OracleSegmentAttributesImpl implements OracleSQLObject {\n    private SQLName segementName;\n\n    private final List<SQLName> items = new ArrayList<SQLName>();\n\n    private boolean secureFile;\n    private boolean basicFile;\n\n    private Boolean enable;\n\n    private SQLExpr chunk;\n\n    private Boolean cache;\n    private Boolean logging;\n\n    private Boolean compress;\n    private Boolean keepDuplicate;\n    private boolean retention;\n\n    private OracleStorageClause storageClause;\n\n    private SQLExpr pctversion;\n\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, segementName);\n            acceptChild(visitor, items);\n            acceptChild(visitor, tablespace);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void cloneTo(OracleLobStorageClause x) {\n        super.cloneTo(x);\n\n        if (segementName != null) {\n            x.setSegementName(segementName.clone());\n        }\n\n        for (SQLName item : items) {\n            SQLName item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n\n        x.secureFile = secureFile;\n        x.basicFile = basicFile;\n        x.enable = enable;\n\n        if (chunk != null) {\n            x.setChunk(chunk.clone());\n        }\n\n        x.cache = cache;\n        x.logging = logging;\n        x.compress = compress;\n        x.keepDuplicate = keepDuplicate;\n        x.retention = retention;\n\n        if (storageClause != null) {\n            x.setStorageClause(storageClause.clone());\n        }\n\n        if (pctversion != null) {\n            x.setPctversion(pctversion.clone());\n        }\n    }\n\n    public OracleLobStorageClause clone() {\n        OracleLobStorageClause x = new OracleLobStorageClause();\n        cloneTo(x);\n        return x;\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public SQLExpr getChunk() {\n        return chunk;\n    }\n\n    public void setChunk(SQLExpr chunk) {\n        this.chunk = chunk;\n    }\n\n    public List<SQLName> getItems() {\n        return items;\n    }\n\n    public boolean isSecureFile() {\n        return secureFile;\n    }\n\n    public void setSecureFile(boolean secureFile) {\n        this.secureFile = secureFile;\n    }\n\n    public boolean isBasicFile() {\n        return basicFile;\n    }\n\n    public void setBasicFile(boolean basicFile) {\n        this.basicFile = basicFile;\n    }\n\n    public Boolean getCache() {\n        return cache;\n    }\n\n    public void setCache(Boolean cache) {\n        this.cache = cache;\n    }\n\n    public Boolean getLogging() {\n        return logging;\n    }\n\n    public void setLogging(Boolean logging) {\n        this.logging = logging;\n    }\n\n    public Boolean getCompress() {\n        return compress;\n    }\n\n    public void setCompress(Boolean compress) {\n        this.compress = compress;\n    }\n\n    public Boolean getKeepDuplicate() {\n        return keepDuplicate;\n    }\n\n    public void setKeepDuplicate(Boolean keepDuplicate) {\n        this.keepDuplicate = keepDuplicate;\n    }\n\n    public boolean isRetention() {\n        return retention;\n    }\n\n    public void setRetention(boolean retention) {\n        this.retention = retention;\n    }\n\n    public OracleStorageClause getStorageClause() {\n        return storageClause;\n    }\n\n    public void setStorageClause(OracleStorageClause storageClause) {\n        if (storageClause != null) {\n            storageClause.setParent(this);\n        }\n        this.storageClause = storageClause;\n    }\n\n    public SQLExpr getPctversion() {\n        return pctversion;\n    }\n\n    public void setPctversion(SQLExpr pctversion) {\n        if (pctversion != null) {\n            pctversion.setParent(this);\n        }\n        this.pctversion = pctversion;\n    }\n\n    public SQLName getSegementName() {\n        return segementName;\n    }\n\n    public void setSegementName(SQLName segementName) {\n        this.segementName = segementName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleReturningClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleReturningClause extends OracleSQLObjectImpl implements SQLReplaceable {\n    private List<SQLExpr> items = new ArrayList<SQLExpr>();\n    private List<SQLExpr> values = new ArrayList<SQLExpr>();\n\n    public List<SQLExpr> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLExpr item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public List<SQLExpr> getValues() {\n        return values;\n    }\n\n    public void addValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.values.add(value);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, items);\n            acceptChild(visitor, values);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public OracleReturningClause clone() {\n        OracleReturningClause x = new OracleReturningClause();\n\n        for (SQLExpr item : items) {\n            SQLExpr item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n\n        for (SQLExpr v : values) {\n            SQLExpr v2 = v.clone();\n            v2.setParent(x);\n            x.values.add(v2);\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = items.size() - 1; i >= 0; i--) {\n            if (items.get(i) == expr) {\n                target.setParent(this);\n                items.set(i, target);\n                return true;\n            }\n        }\n\n        for (int i = values.size() - 1; i >= 0; i--) {\n            if (values.get(i) == expr) {\n                target.setParent(this);\n                values.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleStorageClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleStorageClause extends OracleSQLObjectImpl {\n    private SQLExpr initial;\n    private SQLExpr next;\n    private SQLExpr minExtents;\n    private SQLExpr maxExtents;\n    private SQLExpr maxSize;\n    private SQLExpr pctIncrease;\n    private SQLExpr freeLists;\n    private SQLExpr freeListGroups;\n    private SQLExpr bufferPool;\n    private SQLExpr objno;\n    private FlashCacheType flashCache;\n    private FlashCacheType cellFlashCache;\n\n    public OracleStorageClause clone() {\n        OracleStorageClause x = new OracleStorageClause();\n        if (initial != null) {\n            x.setInitial(initial.clone());\n        }\n        if (next != null) {\n            x.setNext(next.clone());\n        }\n        if (minExtents != null) {\n            x.setMinExtents(minExtents.clone());\n        }\n        if (maxExtents != null) {\n            x.setMinExtents(maxExtents.clone());\n        }\n        if (maxSize != null) {\n            x.setMaxSize(maxSize.clone());\n        }\n        if (pctIncrease != null) {\n            x.setPctIncrease(pctIncrease.clone());\n        }\n        if (freeLists != null) {\n            x.setFreeLists(freeLists.clone());\n        }\n        if (freeListGroups != null) {\n            x.setFreeListGroups(freeListGroups.clone());\n        }\n        if (bufferPool != null) {\n            x.setBufferPool(bufferPool.clone());\n        }\n        if (objno != null) {\n            x.setObjno(objno.clone());\n        }\n        x.flashCache = flashCache;\n        x.cellFlashCache = cellFlashCache;\n        return x;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, initial);\n            acceptChild(visitor, next);\n            acceptChild(visitor, minExtents);\n            acceptChild(visitor, maxExtents);\n            acceptChild(visitor, maxSize);\n            acceptChild(visitor, pctIncrease);\n            acceptChild(visitor, freeLists);\n            acceptChild(visitor, freeListGroups);\n            acceptChild(visitor, bufferPool);\n            acceptChild(visitor, objno);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getMaxSize() {\n        return maxSize;\n    }\n\n    public void setMaxSize(SQLExpr maxSize) {\n        this.maxSize = maxSize;\n    }\n\n    public FlashCacheType getFlashCache() {\n        return flashCache;\n    }\n\n    public void setFlashCache(FlashCacheType flashCache) {\n        this.flashCache = flashCache;\n    }\n\n    public FlashCacheType getCellFlashCache() {\n        return cellFlashCache;\n    }\n\n    public void setCellFlashCache(FlashCacheType cellFlashCache) {\n        this.cellFlashCache = cellFlashCache;\n    }\n\n    public SQLExpr getPctIncrease() {\n        return pctIncrease;\n    }\n\n    public void setPctIncrease(SQLExpr pctIncrease) {\n        this.pctIncrease = pctIncrease;\n    }\n\n    public SQLExpr getNext() {\n        return next;\n    }\n\n    public void setNext(SQLExpr next) {\n        this.next = next;\n    }\n\n    public SQLExpr getMinExtents() {\n        return minExtents;\n    }\n\n    public void setMinExtents(SQLExpr minExtents) {\n        this.minExtents = minExtents;\n    }\n\n    public SQLExpr getMaxExtents() {\n        return maxExtents;\n    }\n\n    public void setMaxExtents(SQLExpr maxExtents) {\n        this.maxExtents = maxExtents;\n    }\n\n    public SQLExpr getObjno() {\n        return objno;\n    }\n\n    public void setObjno(SQLExpr objno) {\n        this.objno = objno;\n    }\n\n    public SQLExpr getInitial() {\n        return initial;\n    }\n\n    public void setInitial(SQLExpr initial) {\n        this.initial = initial;\n    }\n\n    public SQLExpr getFreeLists() {\n        return freeLists;\n    }\n\n    public void setFreeLists(SQLExpr freeLists) {\n        this.freeLists = freeLists;\n    }\n\n    public SQLExpr getFreeListGroups() {\n        return freeListGroups;\n    }\n\n    public void setFreeListGroups(SQLExpr freeListGroups) {\n        this.freeListGroups = freeListGroups;\n    }\n\n    public SQLExpr getBufferPool() {\n        return bufferPool;\n    }\n\n    public void setBufferPool(SQLExpr bufferPool) {\n        this.bufferPool = bufferPool;\n    }\n\n    public static enum FlashCacheType {\n        KEEP, NONE, DEFAULT\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/OracleWithSubqueryEntry.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause.Entry;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npublic class OracleWithSubqueryEntry extends Entry implements OracleSQLObject {\n    private SearchClause searchClause;\n    private CycleClause cycleClause;\n\n    public CycleClause getCycleClause() {\n        return cycleClause;\n    }\n\n    public void setCycleClause(CycleClause cycleClause) {\n        if (cycleClause != null) {\n            cycleClause.setParent(this);\n        }\n        this.cycleClause = cycleClause;\n    }\n\n    public SearchClause getSearchClause() {\n        return searchClause;\n    }\n\n    public void setSearchClause(SearchClause searchClause) {\n        if (searchClause != null) {\n            searchClause.setParent(this);\n        }\n        this.searchClause = searchClause;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            acceptChild(visitor, subQuery);\n            acceptChild(visitor, searchClause);\n            acceptChild(visitor, cycleClause);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    public void cloneTo(OracleWithSubqueryEntry x) {\n        super.cloneTo(x);\n\n        if (searchClause != null) {\n            setSearchClause(searchClause.clone());\n        }\n\n        if (cycleClause != null) {\n            setCycleClause(cycleClause.clone());\n        }\n    }\n\n    public OracleWithSubqueryEntry clone() {\n        OracleWithSubqueryEntry x = new OracleWithSubqueryEntry();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/PartitionExtensionClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PartitionExtensionClause extends OracleSQLObjectImpl {\n    private boolean subPartition;\n    private SQLName partition;\n    private final List<SQLName> target = new ArrayList<SQLName>();\n\n    public boolean isSubPartition() {\n        return subPartition;\n    }\n\n    public void setSubPartition(boolean subPartition) {\n        this.subPartition = subPartition;\n    }\n\n    public SQLName getPartition() {\n        return partition;\n    }\n\n    public void setPartition(SQLName partition) {\n        this.partition = partition;\n    }\n\n    public List<SQLName> getFor() {\n        return target;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, partition);\n            acceptChild(visitor, target);\n        }\n        visitor.endVisit(this);\n    }\n\n    public PartitionExtensionClause clone() {\n        PartitionExtensionClause x = new PartitionExtensionClause();\n\n        x.subPartition = subPartition;\n        if (partition != null) {\n            x.setPartition(partition.clone());\n        }\n\n        for (SQLName item : target) {\n            SQLName item1 = item.clone();\n            item1.setParent(x);\n            x.target.add(item1);\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/SampleClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SampleClause extends OracleSQLObjectImpl implements SQLReplaceable {\n    private boolean block;\n\n    private final List<SQLExpr> percent = new ArrayList<SQLExpr>();\n\n    private SQLExpr seedValue;\n\n    public boolean isBlock() {\n        return block;\n    }\n\n    public void setBlock(boolean block) {\n        this.block = block;\n    }\n\n    public List<SQLExpr> getPercent() {\n        return percent;\n    }\n\n    public void addPercent(SQLExpr x) {\n        if (x == null) {\n            return;\n        }\n        x.setParent(this);\n        this.percent.add(x);\n    }\n\n    public SQLExpr getSeedValue() {\n        return seedValue;\n    }\n\n    public void setSeedValue(SQLExpr seedValue) {\n        if (seedValue != null) {\n            seedValue.setParent(this);\n        }\n        this.seedValue = seedValue;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, seedValue);\n            acceptChild(visitor, percent);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public SampleClause clone() {\n        SampleClause x = new SampleClause();\n\n        x.block = block;\n\n        for (SQLExpr item : percent) {\n            SQLExpr item1 = item.clone();\n            item1.setParent(x);\n            x.percent.add(item1);\n        }\n\n        if (seedValue != null) {\n            x.setSeedValue(seedValue.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = percent.size() - 1; i >= 0; i--) {\n            if (percent.get(i) == expr) {\n                percent.set(i, target);\n                return true;\n            }\n        }\n\n        if (expr == seedValue) {\n            setSeedValue(target);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/clause/SearchClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.clause;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SearchClause extends OracleSQLObjectImpl {\n    public static enum Type {\n        DEPTH, BREADTH\n    }\n\n    private Type type;\n\n    private final List<SQLSelectOrderByItem> items = new ArrayList<SQLSelectOrderByItem>();\n\n    private SQLIdentifierExpr orderingColumn;\n\n    public Type getType() {\n        return type;\n    }\n\n    public void setType(Type type) {\n        this.type = type;\n    }\n\n    public List<SQLSelectOrderByItem> getItems() {\n        return items;\n    }\n\n    public void addItem(SQLSelectOrderByItem item) {\n        if (item != null) {\n            item.setParent(this);\n        }\n        this.items.add(item);\n    }\n\n    public SQLIdentifierExpr getOrderingColumn() {\n        return orderingColumn;\n    }\n\n    public void setOrderingColumn(SQLIdentifierExpr orderingColumn) {\n        if (orderingColumn != null) {\n            orderingColumn.setParent(this);\n        }\n        this.orderingColumn = orderingColumn;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, items);\n            acceptChild(visitor, orderingColumn);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SearchClause clone() {\n        SearchClause x = new SearchClause();\n\n        x.type = type;\n\n        for (SQLSelectOrderByItem item : items) {\n            SQLSelectOrderByItem item2 = item.clone();\n            item2.setParent(x);\n            x.items.add(item2);\n        }\n\n        if (orderingColumn != null) {\n            x.setOrderingColumn(orderingColumn.clone());\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAnalytic.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleAnalytic extends SQLOver implements SQLReplaceable, OracleExpr {\n    private OracleAnalyticWindowing windowing;\n\n    public OracleAnalytic() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) visitor);\n            return;\n        }\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.partitionBy);\n            acceptChild(visitor, this.orderBy);\n            acceptChild(visitor, this.windowing);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.partitionBy);\n            acceptChild(visitor, this.orderBy);\n            acceptChild(visitor, this.windowing);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        children.addAll(this.partitionBy);\n        if (this.orderBy != null) {\n            children.add(orderBy);\n        }\n        if (this.windowing != null) {\n            children.add(windowing);\n        }\n        return children;\n    }\n\n    public OracleAnalyticWindowing getWindowing() {\n        return this.windowing;\n    }\n\n    public OracleAnalytic clone() {\n        OracleAnalytic x = new OracleAnalytic();\n\n        cloneTo(x);\n\n        if (windowing != null) {\n            x.setWindowing(windowing.clone());\n        }\n\n        return x;\n    }\n\n    public void setWindowing(OracleAnalyticWindowing x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.windowing = x;\n    }\n\n    public SQLDataType computeDataType() {\n        return null;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        for (int i = 0; i < partitionBy.size(); i++) {\n            if (partitionBy.get(i) == expr) {\n                partitionBy.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleAnalyticWindowing.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleAnalyticWindowing extends SQLObjectImpl implements OracleExpr {\n    private Type type;\n    private SQLExpr expr;\n\n    public OracleAnalyticWindowing() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public Type getType() {\n        return this.type;\n    }\n\n    public void setType(Type type) {\n        this.type = type;\n    }\n\n    @Override\n    public OracleAnalyticWindowing clone() {\n        OracleAnalyticWindowing x = new OracleAnalyticWindowing();\n        x.type = type;\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        return x;\n    }\n\n    public static enum Type {\n        ROWS, RANGE;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.expr);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleArgumentExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleArgumentExpr extends OracleSQLObjectImpl implements SQLExpr, SQLReplaceable {\n    private String argumentName;\n    private SQLExpr value;\n\n    public OracleArgumentExpr() {\n    }\n\n    public OracleArgumentExpr(String argumentName, SQLExpr value) {\n        this.argumentName = argumentName;\n        setValue(value);\n    }\n\n    public String getArgumentName() {\n        return argumentName;\n    }\n\n    public void setArgumentName(String argumentName) {\n        this.argumentName = argumentName;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public OracleArgumentExpr clone() {\n        OracleArgumentExpr x = new OracleArgumentExpr();\n        x.argumentName = argumentName;\n\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (value == expr) {\n            setValue(target);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.value);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryDoubleExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleBinaryDoubleExpr extends SQLNumericLiteralExpr implements OracleExpr {\n    public OracleBinaryDoubleExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.DOUBLE));\n    }\n\n    public OracleBinaryDoubleExpr(Double value) {\n        this();\n        this.value = value;\n    }\n\n    @Override\n    public Number getNumber() {\n        return getValue();\n    }\n\n    public Double getValue() {\n        return (Double) value;\n    }\n\n    public void setValue(Double value) {\n        this.value = value;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        OracleBinaryDoubleExpr other = (OracleBinaryDoubleExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            value = null;\n            return;\n        }\n\n        this.setValue(number.doubleValue());\n    }\n\n    public OracleBinaryDoubleExpr clone() {\n        return new OracleBinaryDoubleExpr(getValue());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleBinaryFloatExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleBinaryFloatExpr extends SQLNumericLiteralExpr implements OracleExpr {\n    public OracleBinaryFloatExpr() {\n        super(new SQLDataTypeImpl(SQLDataType.Constants.FLOAT));\n    }\n\n    public OracleBinaryFloatExpr(Float value) {\n        this();\n        this.value = value;\n    }\n\n    public OracleBinaryFloatExpr clone() {\n        return new OracleBinaryFloatExpr(getValue());\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public Number getNumber() {\n        return getValue();\n    }\n\n    public Float getValue() {\n        return (Float) value;\n    }\n\n    public void setValue(Float value) {\n        this.value = value;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        OracleBinaryFloatExpr other = (OracleBinaryFloatExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public void setNumber(Number number) {\n        if (number == null) {\n            value = null;\n            return;\n        }\n\n        this.setValue(number.floatValue());\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleCursorExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleCursorExpr extends SQLExprImpl implements OracleExpr {\n    private SQLSelect query;\n\n    public OracleCursorExpr() {\n    }\n\n    public OracleCursorExpr clone() {\n        OracleCursorExpr x = new OracleCursorExpr();\n        if (query != null) {\n            x.setQuery(query.clone());\n        }\n        return x;\n    }\n\n    public OracleCursorExpr(SQLSelect query) {\n        setQuery(query);\n    }\n\n    public SQLSelect getQuery() {\n        return query;\n    }\n\n    public void setQuery(SQLSelect query) {\n        this.query = query;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, query);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.query);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((query == null) ? 0 : query.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        OracleCursorExpr other = (OracleCursorExpr) obj;\n        if (query == null) {\n            if (other.query != null) {\n                return false;\n            }\n        } else if (!query.equals(other.query)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDateTimeUnit.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\npublic enum OracleDateTimeUnit {\n    YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, TIMEZONE_HOURE, TIMEZONE_MINUTE, TIMEZONE_REGION, TIMEZONE_ABBR;\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDatetimeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class OracleDatetimeExpr extends OracleSQLObjectImpl implements SQLExpr {\n    private SQLExpr expr;\n    private SQLExpr timeZone;\n\n    public OracleDatetimeExpr() {\n    }\n\n    public OracleDatetimeExpr(SQLExpr expr, SQLExpr timeZone) {\n        this.expr = expr;\n        this.timeZone = timeZone;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n            acceptChild(visitor, timeZone);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    public SQLExpr getTimeZone() {\n        return timeZone;\n    }\n\n    public void setTimeZone(SQLExpr timeZone) {\n        this.timeZone = timeZone;\n    }\n\n    public OracleDatetimeExpr clone() {\n        OracleDatetimeExpr x = new OracleDatetimeExpr();\n\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n\n        if (timeZone != null) {\n            x.setTimeZone(timeZone.clone());\n        }\n\n        return x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Arrays.<SQLObject>asList(this.expr, this.timeZone);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\n\npublic interface OracleExpr extends SQLExpr, OracleSQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIntervalExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleIntervalExpr extends SQLExprImpl implements SQLLiteralExpr, OracleExpr, SQLReplaceable {\n    private SQLExpr value;\n    private OracleIntervalType type;\n    private SQLExpr precision;\n    private Integer factionalSecondsPrecision;\n    private OracleIntervalType toType;\n    private SQLExpr toFactionalSecondsPrecision;\n\n    public OracleIntervalExpr() {\n    }\n\n    @Override\n    public OracleIntervalExpr clone() {\n        OracleIntervalExpr x = new OracleIntervalExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        x.type = type;\n        x.precision = precision;\n        x.factionalSecondsPrecision = factionalSecondsPrecision;\n        x.toType = toType;\n        x.toFactionalSecondsPrecision = toFactionalSecondsPrecision;\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        if (this.precision == expr) {\n            setPrecision(target);\n            return true;\n        }\n\n        if (this.toFactionalSecondsPrecision == expr) {\n            setToFactionalSecondsPrecision(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.value);\n    }\n\n    public SQLExpr getValue() {\n        return this.value;\n    }\n\n    public void setValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.value = value;\n    }\n\n    public OracleIntervalType getType() {\n        return this.type;\n    }\n\n    public void setType(OracleIntervalType type) {\n        this.type = type;\n    }\n\n    public SQLExpr getPrecision() {\n        return this.precision;\n    }\n\n    public void setPrecision(Integer precision) {\n        this.setPrecision(new SQLIntegerExpr(precision));\n    }\n\n    public void setPrecision(SQLExpr precision) {\n        if (precision != null) {\n            precision.setParent(this);\n        }\n        this.precision = precision;\n    }\n\n    public Integer getFactionalSecondsPrecision() {\n        return this.factionalSecondsPrecision;\n    }\n\n    public void setFactionalSecondsPrecision(Integer factionalSecondsPrecision) {\n        this.factionalSecondsPrecision = factionalSecondsPrecision;\n    }\n\n    public OracleIntervalType getToType() {\n        return this.toType;\n    }\n\n    public void setToType(OracleIntervalType toType) {\n        this.toType = toType;\n    }\n\n    public SQLExpr getToFactionalSecondsPrecision() {\n        return this.toFactionalSecondsPrecision;\n    }\n\n    public void setToFactionalSecondsPrecision(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.toFactionalSecondsPrecision = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, value);\n            this.acceptChild(visitor, precision);\n            this.acceptChild(visitor, toFactionalSecondsPrecision);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((factionalSecondsPrecision == null) ? 0 : factionalSecondsPrecision.hashCode());\n        result = prime * result + ((precision == null) ? 0 : precision.hashCode());\n        result = prime * result + ((toFactionalSecondsPrecision == null) ? 0 : toFactionalSecondsPrecision.hashCode());\n        result = prime * result + ((toType == null) ? 0 : toType.hashCode());\n        result = prime * result + ((type == null) ? 0 : type.hashCode());\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        OracleIntervalExpr other = (OracleIntervalExpr) obj;\n        if (factionalSecondsPrecision == null) {\n            if (other.factionalSecondsPrecision != null) {\n                return false;\n            }\n        } else if (!factionalSecondsPrecision.equals(other.factionalSecondsPrecision)) {\n            return false;\n        }\n        if (precision == null) {\n            if (other.precision != null) {\n                return false;\n            }\n        } else if (!precision.equals(other.precision)) {\n            return false;\n        }\n        if (toFactionalSecondsPrecision == null) {\n            if (other.toFactionalSecondsPrecision != null) {\n                return false;\n            }\n        } else if (!toFactionalSecondsPrecision.equals(other.toFactionalSecondsPrecision)) {\n            return false;\n        }\n        if (toType != other.toType) {\n            return false;\n        }\n        if (type != other.type) {\n            return false;\n        }\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIntervalType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\npublic enum OracleIntervalType {\n    YEAR, MONTH, DAY, HOUR, MINUTE, SECOND;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIsOfTypeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleIsOfTypeExpr extends SQLExprImpl implements OracleExpr, SQLReplaceable {\n    private SQLExpr expr;\n    private List<SQLExpr> types = new ArrayList<SQLExpr>();\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        OracleIsOfTypeExpr that = (OracleIsOfTypeExpr) o;\n\n        if (expr != null ? !expr.equals(that.expr) : that.expr != null) {\n            return false;\n        }\n        return types != null ? types.equals(that.types) : that.types == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = expr != null ? expr.hashCode() : 0;\n        result = 31 * result + (types != null ? types.hashCode() : 0);\n        return result;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n            acceptChild(visitor, types);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n\n        for (int i = 0; i < types.size(); i++) {\n            if (types.get(i) == expr) {\n                target.setParent(this);\n                types.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public SQLExpr clone() {\n        OracleIsOfTypeExpr x = new OracleIsOfTypeExpr();\n        if (expr != null) {\n            x.setExpr(expr);\n        }\n        return null;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List children = new ArrayList<SQLExpr>();\n        if (expr != null) {\n            children.add(expr);\n        }\n        children.addAll(types);\n        return children;\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public List<SQLExpr> getTypes() {\n        return types;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleIsSetExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleIsSetExpr extends SQLExprImpl implements OracleExpr, SQLReplaceable {\n    private SQLExpr nestedTable;\n\n    public OracleIsSetExpr() {\n    }\n\n    public OracleIsSetExpr(SQLExpr nestedTable) {\n        this.nestedTable = nestedTable;\n    }\n\n    public OracleIsSetExpr clone() {\n        OracleIsSetExpr x = new OracleIsSetExpr();\n        if (nestedTable != null) {\n            x.setNestedTable(nestedTable.clone());\n        }\n        return x;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.nestedTable == expr) {\n            setNestedTable(target);\n            return true;\n        }\n        return false;\n    }\n\n    public SQLExpr getNestedTable() {\n        return nestedTable;\n    }\n\n    public void setNestedTable(SQLExpr nestedTable) {\n        if (nestedTable != null) {\n            nestedTable.setParent(this);\n        }\n        this.nestedTable = nestedTable;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, nestedTable);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.nestedTable);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((nestedTable == null) ? 0 : nestedTable.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        OracleIsSetExpr other = (OracleIsSetExpr) obj;\n        if (nestedTable == null) {\n            if (other.nestedTable != null) {\n                return false;\n            }\n        } else if (!nestedTable.equals(other.nestedTable)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleOuterExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleOuterExpr extends SQLExprImpl implements OracleExpr, SQLReplaceable {\n    private SQLExpr expr;\n\n    public OracleOuterExpr() {\n    }\n\n    public OracleOuterExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    public OracleOuterExpr clone() {\n        OracleOuterExpr x = new OracleOuterExpr();\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getExpr() {\n        return this.expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.expr == expr) {\n            setExpr(target);\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            this.accept0((OracleASTVisitor) visitor);\n        } else {\n            acceptChild(visitor, this.expr);\n        }\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(this.expr);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((expr == null) ? 0 : expr.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        OracleOuterExpr other = (OracleOuterExpr) obj;\n        if (expr == null) {\n            if (other.expr != null) {\n                return false;\n            }\n        } else if (!expr.equals(other.expr)) {\n            return false;\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleRangeExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class OracleRangeExpr extends OracleSQLObjectImpl implements SQLExpr {\n    private SQLExpr lowBound;\n    private SQLExpr upBound;\n\n    public OracleRangeExpr() {\n    }\n\n    public OracleRangeExpr(SQLExpr lowBound, SQLExpr upBound) {\n        setLowBound(lowBound);\n        setUpBound(upBound);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, lowBound);\n            acceptChild(visitor, upBound);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Arrays.<SQLObject>asList(this.lowBound, this.upBound);\n    }\n\n    public SQLExpr getLowBound() {\n        return lowBound;\n    }\n\n    public void setLowBound(SQLExpr lowBound) {\n        if (lowBound != null) {\n            lowBound.setParent(this);\n        }\n        this.lowBound = lowBound;\n    }\n\n    public SQLExpr getUpBound() {\n        return upBound;\n    }\n\n    public void setUpBound(SQLExpr upBound) {\n        if (upBound != null) {\n            upBound.setParent(this);\n        }\n        this.upBound = upBound;\n    }\n\n    public OracleRangeExpr clone() {\n        OracleRangeExpr x = new OracleRangeExpr();\n\n        if (lowBound != null) {\n            x.setLowBound(lowBound.clone());\n        }\n\n        if (upBound != null) {\n            x.setUpBound(upBound.clone());\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleSysdateExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class OracleSysdateExpr extends OracleSQLObjectImpl implements SQLExpr {\n    private String option;\n\n    public String getOption() {\n        return option;\n    }\n\n    public void setOption(String option) {\n        this.option = option;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public OracleSysdateExpr clone() {\n        OracleSysdateExpr x = new OracleSysdateExpr();\n        x.option = option;\n        return x;\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>emptyList();\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleTreatExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class OracleTreatExpr extends OracleSQLObjectImpl implements SQLExpr {\n    private SQLExpr expr;\n    private SQLExpr type;\n    private boolean ref;\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n\n    public SQLExpr getType() {\n        return type;\n    }\n\n    public void setType(SQLExpr type) {\n        if (type != null) {\n            type.setParent(this);\n        }\n        this.type = type;\n    }\n\n    public boolean isRef() {\n        return ref;\n    }\n\n    public void setRef(boolean ref) {\n        this.ref = ref;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n            acceptChild(visitor, type);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Arrays.<SQLObject>asList(this.expr, this.type);\n    }\n\n    public OracleTreatExpr clone() {\n        OracleTreatExpr x = new OracleTreatExpr();\n\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n\n        if (type != null) {\n            x.setType(type.clone());\n        }\n\n        x.ref = ref;\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterPackageStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\n/**\n * @author gaoWL\n */\npublic class OracleAlterPackageStatement extends OracleStatementImpl implements SQLAlterStatement, OracleStatement {\n    private SQLName name;\n\n    private boolean compile;\n\n    private boolean body;\n\n    private boolean pack;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n    public boolean isBody() {\n        return body;\n    }\n\n    public void setBody(boolean body) {\n        this.body = body;\n    }\n\n    public boolean isPack() {\n        return pack;\n    }\n\n    public void setPack(boolean pack) {\n        this.pack = pack;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSessionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleAlterSessionStatement extends OracleStatementImpl implements OracleAlterStatement {\n    private List<SQLAssignItem> items = new ArrayList<SQLAssignItem>();\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, items);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLAssignItem> getItems() {\n        return items;\n    }\n\n    public void setItems(List<SQLAssignItem> items) {\n        this.items = items;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\n\npublic interface OracleAlterStatement extends SQLAlterStatement, OracleStatement {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSummaryStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterSummaryStatement extends OracleStatementImpl implements OracleAlterStatement {\n    private SQLName name;\n\n    private boolean compile;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterSynonymStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterSynonymStatement extends OracleStatementImpl implements OracleAlterStatement {\n    private SQLName name;\n\n    private Boolean enable;\n\n    private boolean compile;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableDropPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterTableDropPartition extends OracleAlterTableItem {\n    private SQLName name;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\n\npublic abstract class OracleAlterTableItem extends OracleSQLObjectImpl implements SQLAlterTableItem {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableModify.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleAlterTableModify extends OracleAlterTableItem {\n    private List<SQLColumnDefinition> columns = new ArrayList<SQLColumnDefinition>();\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLColumnDefinition> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLColumnDefinition column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableMoveTablespace.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterTableMoveTablespace extends OracleAlterTableItem {\n    private SQLName name;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableRowMovement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterTableRowMovement extends OracleAlterTableItem {\n    /**\n     * true:ENABLE,false:DISABLE\n     */\n    private boolean enable;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isEnable() {\n        return enable;\n    }\n\n    public void setEnable(boolean enable) {\n        this.enable = enable;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableShrinkSpace.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterTableShrinkSpace extends OracleAlterTableItem {\n    private boolean compact;\n\n    private boolean cascade;\n\n    private boolean check;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isCompact() {\n        return compact;\n    }\n\n    public void setCompact(boolean compact) {\n        this.compact = compact;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isCheck() {\n        return check;\n    }\n\n    public void setCheck(boolean check) {\n        this.check = check;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableSplitPartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleAlterTableSplitPartition extends OracleAlterTableItem {\n    private SQLName name;\n    private List<SQLExpr> at = new ArrayList<SQLExpr>();\n    private List<SQLExpr> values = new ArrayList<SQLExpr>();\n    private List<NestedTablePartitionSpec> into = new ArrayList<NestedTablePartitionSpec>();\n\n    private UpdateIndexesClause updateIndexes;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, at);\n            acceptChild(visitor, values);\n            acceptChild(visitor, updateIndexes);\n        }\n        visitor.endVisit(this);\n    }\n\n    public UpdateIndexesClause getUpdateIndexes() {\n        return updateIndexes;\n    }\n\n    public void setUpdateIndexes(UpdateIndexesClause updateIndexes) {\n        this.updateIndexes = updateIndexes;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public List<SQLExpr> getAt() {\n        return at;\n    }\n\n    public void setAt(List<SQLExpr> at) {\n        this.at = at;\n    }\n\n    public List<NestedTablePartitionSpec> getInto() {\n        return into;\n    }\n\n    public void setInto(List<NestedTablePartitionSpec> into) {\n        this.into = into;\n    }\n\n    public List<SQLExpr> getValues() {\n        return values;\n    }\n\n    public void setValues(List<SQLExpr> values) {\n        this.values = values;\n    }\n\n    public static class NestedTablePartitionSpec extends OracleSQLObjectImpl {\n        private SQLName partition;\n\n        private List<SQLObject> segmentAttributeItems = new ArrayList<SQLObject>();\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, partition);\n                acceptChild(visitor, segmentAttributeItems);\n            }\n            visitor.endVisit(this);\n        }\n\n        public SQLName getPartition() {\n            return partition;\n        }\n\n        public void setPartition(SQLName partition) {\n            this.partition = partition;\n        }\n\n        public List<SQLObject> getSegmentAttributeItems() {\n            return segmentAttributeItems;\n        }\n\n        public void setSegmentAttributeItems(List<SQLObject> segmentAttributeItems) {\n            this.segmentAttributeItems = segmentAttributeItems;\n        }\n\n    }\n\n    public static class TableSpaceItem extends OracleSQLObjectImpl {\n        private SQLName tablespace;\n\n        public TableSpaceItem() {\n        }\n\n        public TableSpaceItem(SQLName tablespace) {\n            this.tablespace = tablespace;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, tablespace);\n            }\n            visitor.endVisit(this);\n        }\n\n        public SQLName getTablespace() {\n            return tablespace;\n        }\n\n        public void setTablespace(SQLName tablespace) {\n            this.tablespace = tablespace;\n        }\n    }\n\n    public static class UpdateIndexesClause extends OracleSQLObjectImpl {\n        private List<SQLObject> items = new ArrayList<SQLObject>();\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, items);\n            }\n            visitor.endVisit(this);\n        }\n\n        public List<SQLObject> getItems() {\n            return items;\n        }\n\n        public void setItems(List<SQLObject> items) {\n            this.items = items;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTableTruncatePartition.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterTableTruncatePartition extends OracleAlterTableItem {\n    private SQLName name;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTablespaceAddDataFile.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleAlterTablespaceAddDataFile extends OracleSQLObjectImpl implements OracleAlterTablespaceItem {\n    private List<OracleFileSpecification> files = new ArrayList<OracleFileSpecification>();\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, files);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<OracleFileSpecification> getFiles() {\n        return files;\n    }\n\n    public void setFiles(List<OracleFileSpecification> files) {\n        this.files = files;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTablespaceItem.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\n\npublic interface OracleAlterTablespaceItem extends OracleSQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTablespaceStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterTablespaceStatement extends OracleStatementImpl implements OracleAlterStatement {\n    private SQLName name;\n    private OracleAlterTablespaceItem item;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, item);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public OracleAlterTablespaceItem getItem() {\n        return item;\n    }\n\n    public void setItem(OracleAlterTablespaceItem item) {\n        this.item = item;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterTriggerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterTriggerStatement extends OracleStatementImpl implements OracleAlterStatement {\n    private SQLName name;\n\n    private Boolean enable;\n\n    private boolean compile;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleAlterViewStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleAlterViewStatement extends OracleStatementImpl implements OracleAlterStatement {\n    private SQLName name;\n\n    private Boolean enable;\n\n    private boolean compile;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isCompile() {\n        return compile;\n    }\n\n    public void setCompile(boolean compile) {\n        this.compile = compile;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCheck.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCheck;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleCheck extends SQLCheck implements OracleConstraint, OracleSQLObject {\n    private OracleUsingIndexClause using;\n    private SQLName exceptionsInto;\n    private Initially initially;\n    private Boolean deferrable;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) visitor);\n            return;\n        }\n\n        super.accept(visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getExpr());\n\n            acceptChild(visitor, using);\n            acceptChild(visitor, exceptionsInto);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getDeferrable() {\n        return deferrable;\n    }\n\n    public void setDeferrable(Boolean deferrable) {\n        this.deferrable = deferrable;\n    }\n\n    public Initially getInitially() {\n        return initially;\n    }\n\n    public void setInitially(Initially initially) {\n        this.initially = initially;\n    }\n\n    public SQLName getExceptionsInto() {\n        return exceptionsInto;\n    }\n\n    public void setExceptionsInto(SQLName exceptionsInto) {\n        this.exceptionsInto = exceptionsInto;\n    }\n\n    public OracleUsingIndexClause getUsing() {\n        return using;\n    }\n\n    public void setUsing(OracleUsingIndexClause using) {\n        if (using != null) {\n            using.setParent(this);\n        }\n        this.using = using;\n    }\n\n    public void cloneTo(OracleCheck x) {\n        super.cloneTo(x);\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n        if (exceptionsInto != null) {\n            x.setExceptionsInto(exceptionsInto.clone());\n        }\n        x.initially = initially;\n        x.deferrable = deferrable;\n    }\n\n    public OracleCheck clone() {\n        OracleCheck x = new OracleCheck();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConstraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\n\npublic interface OracleConstraint extends OracleSQLObject, SQLConstraint, SQLTableElement {\n    SQLName getExceptionsInto();\n\n    void setExceptionsInto(SQLName exceptionsInto);\n\n    Boolean getDeferrable();\n\n    void setDeferrable(Boolean enable);\n\n    Boolean getEnable();\n\n    void setEnable(Boolean enable);\n\n    Boolean getValidate();\n\n    void setValidate(Boolean validate);\n\n    Initially getInitially();\n\n    void setInitially(Initially value);\n\n    OracleUsingIndexClause getUsing();\n\n    void setUsing(OracleUsingIndexClause using);\n\n    public static enum Initially {\n        DEFERRED, IMMEDIATE\n    }\n\n    OracleConstraint clone();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleContinueStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleContinueStatement extends OracleStatementImpl {\n    private SQLExpr when;\n    private String label;\n\n    public SQLExpr getWhen() {\n        return when;\n    }\n\n    public void setWhen(SQLExpr when) {\n        if (when != null) {\n            when.setParent(this);\n        }\n        this.when = when;\n    }\n\n    public String getLabel() {\n        return label;\n    }\n\n    public void setLabel(String label) {\n        this.label = label;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, when);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateDatabaseDbLinkStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleCreateDatabaseDbLinkStatement extends OracleStatementImpl implements SQLCreateStatement {\n    private boolean shared;\n    private boolean isPublic;\n\n    private SQLName name;\n\n    private SQLName user;\n\n    private String password;\n\n    private SQLExpr using;\n\n    private SQLExpr authenticatedUser;\n    private String authenticatedPassword;\n\n    public boolean isShared() {\n        return shared;\n    }\n\n    public void setShared(boolean shared) {\n        this.shared = shared;\n    }\n\n    public boolean isPublic() {\n        return isPublic;\n    }\n\n    public void setPublic(boolean value) {\n        this.isPublic = value;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public SQLName getUser() {\n        return user;\n    }\n\n    public void setUser(SQLName user) {\n        this.user = user;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public SQLExpr getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLExpr using) {\n        this.using = using;\n    }\n\n    public SQLExpr getAuthenticatedUser() {\n        return authenticatedUser;\n    }\n\n    public void setAuthenticatedUser(SQLExpr authenticatedUser) {\n        this.authenticatedUser = authenticatedUser;\n    }\n\n    public String getAuthenticatedPassword() {\n        return authenticatedPassword;\n    }\n\n    public void setAuthenticatedPassword(String authenticatedPassword) {\n        this.authenticatedPassword = authenticatedPassword;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, user);\n            acceptChild(visitor, using);\n            acceptChild(visitor, authenticatedUser);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateIndexStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OraclePartitionSingle;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleCreateIndexStatement extends SQLCreateIndexStatement implements OracleDDLStatement, OracleSegmentAttributes, SQLCreateStatement {\n    private boolean online;\n\n    private boolean indexOnlyTopLevel;\n    private boolean cluster;\n\n    private boolean noParallel;\n\n    private SQLExpr parallel;\n\n    private Integer pctfree;\n    private Integer pctused;\n    private Integer initrans;\n\n    private Integer maxtrans;\n    private Integer pctincrease;\n    private Integer freeLists;\n    private Boolean compress;\n    private Integer compressLevel;\n    private boolean compressForOltp;\n    private Integer pctthreshold;\n\n    private Boolean logging;\n    private Boolean sort;\n    private boolean reverse;\n\n    protected SQLName tablespace;\n    protected SQLObject storage;\n\n    private Boolean enable;\n\n    private boolean computeStatistics;\n\n    public OracleCreateIndexStatement() {\n        super(DbType.oracle);\n    }\n\n    public SQLExpr getParallel() {\n        return parallel;\n    }\n\n    public void setParallel(SQLExpr parallel) {\n        this.parallel = parallel;\n    }\n\n    public boolean isNoParallel() {\n        return noParallel;\n    }\n\n    public void setNoParallel(boolean noParallel) {\n        this.noParallel = noParallel;\n    }\n\n    public boolean isIndexOnlyTopLevel() {\n        return indexOnlyTopLevel;\n    }\n\n    public void setIndexOnlyTopLevel(boolean indexOnlyTopLevel) {\n        this.indexOnlyTopLevel = indexOnlyTopLevel;\n    }\n\n    public Boolean getSort() {\n        return sort;\n    }\n\n    public void setSort(Boolean sort) {\n        this.sort = sort;\n    }\n\n    public boolean isReverse() {\n        return reverse;\n    }\n\n    public void setReverse(boolean reverse) {\n        this.reverse = reverse;\n    }\n\n    private boolean local;\n    private List<SQLName> localStoreIn = new ArrayList<SQLName>();\n    private List<OraclePartitionSingle> localPartitions = new ArrayList<>();\n\n    private boolean global;\n    private List<SQLPartitionBy> globalPartitions = new ArrayList<SQLPartitionBy>();\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getName());\n            acceptChild(visitor, getTable());\n            acceptChild(visitor, getItems());\n            acceptChild(visitor, getTablespace());\n            acceptChild(visitor, parallel);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public boolean isComputeStatistics() {\n        return computeStatistics;\n    }\n\n    public void setComputeStatistics(boolean computeStatistics) {\n        this.computeStatistics = computeStatistics;\n    }\n\n    public boolean isOnline() {\n        return online;\n    }\n\n    public void setOnline(boolean online) {\n        this.online = online;\n    }\n\n    public boolean isCluster() {\n        return cluster;\n    }\n\n    public void setCluster(boolean cluster) {\n        this.cluster = cluster;\n    }\n\n    //////////////\n\n    public SQLName getTablespace() {\n        return tablespace;\n    }\n\n    public void setTablespace(SQLName tablespace) {\n        if (tablespace != null) {\n            tablespace.setParent(this);\n        }\n        this.tablespace = tablespace;\n    }\n\n    public Boolean getCompress() {\n        return compress;\n    }\n\n    public void setCompress(Boolean compress) {\n        this.compress = compress;\n    }\n\n    public Integer getCompressLevel() {\n        return compressLevel;\n    }\n\n    public void setCompressLevel(Integer compressLevel) {\n        this.compressLevel = compressLevel;\n    }\n\n    public Integer getPctthreshold() {\n        return pctthreshold;\n    }\n\n    public void setPctthreshold(Integer pctthreshold) {\n        this.pctthreshold = pctthreshold;\n    }\n\n    public Integer getPctfree() {\n        return pctfree;\n    }\n\n    public void setPctfree(Integer ptcfree) {\n        this.pctfree = ptcfree;\n    }\n\n    public Integer getPctused() {\n        return pctused;\n    }\n\n    public void setPctused(Integer ptcused) {\n        this.pctused = ptcused;\n    }\n\n    public Integer getInitrans() {\n        return initrans;\n    }\n\n    public void setInitrans(Integer initrans) {\n        this.initrans = initrans;\n    }\n\n    public Integer getMaxtrans() {\n        return maxtrans;\n    }\n\n    public void setMaxtrans(Integer maxtrans) {\n        this.maxtrans = maxtrans;\n    }\n\n    public Integer getPctincrease() {\n        return pctincrease;\n    }\n\n    public void setPctincrease(Integer pctincrease) {\n        this.pctincrease = pctincrease;\n    }\n\n    public Integer getFreeLists() {\n        return freeLists;\n    }\n\n    public void setFreeLists(Integer freeLists) {\n        this.freeLists = freeLists;\n    }\n\n    public Boolean getLogging() {\n        return logging;\n    }\n\n    public void setLogging(Boolean logging) {\n        this.logging = logging;\n    }\n\n    public SQLObject getStorage() {\n        return storage;\n    }\n\n    public void setStorage(SQLObject storage) {\n        this.storage = storage;\n    }\n\n    public boolean isCompressForOltp() {\n        return compressForOltp;\n    }\n\n    public void setCompressForOltp(boolean compressForOltp) {\n        this.compressForOltp = compressForOltp;\n    }\n\n    public List<OraclePartitionSingle> getLocalPartitions() {\n        return localPartitions;\n    }\n\n    public boolean isLocal() {\n        return local;\n    }\n\n    public void setLocal(boolean local) {\n        this.local = local;\n    }\n\n    public List<SQLName> getLocalStoreIn() {\n        return localStoreIn;\n    }\n\n    public List<SQLPartitionBy> getGlobalPartitions() {\n        return globalPartitions;\n    }\n\n    public boolean isGlobal() {\n        return global;\n    }\n\n    public void setGlobal(boolean global) {\n        this.global = global;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreatePackageStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 23/05/2017.\n */\npublic class OracleCreatePackageStatement extends OracleStatementImpl implements SQLCreateStatement {\n    private boolean orReplace;\n    private SQLName name;\n\n    private boolean body;\n\n    private final List<SQLStatement> statements = new ArrayList<SQLStatement>();\n\n    public OracleCreatePackageStatement() {\n        super.setDbType(DbType.oracle);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, statements);\n        }\n        visitor.endVisit(this);\n    }\n\n    public OracleCreatePackageStatement clone() {\n        OracleCreatePackageStatement x = new OracleCreatePackageStatement();\n\n        x.orReplace = orReplace;\n        if (name != null) {\n            x.setName(name.clone());\n        }\n        x.body = body;\n\n        for (SQLStatement stmt : statements) {\n            SQLStatement s2 = stmt.clone();\n            s2.setParent(x);\n            x.statements.add(s2);\n        }\n\n        return x;\n    }\n\n    public boolean isOrReplace() {\n        return orReplace;\n    }\n\n    public void setOrReplace(boolean orReplace) {\n        this.orReplace = orReplace;\n    }\n\n    public boolean isBody() {\n        return body;\n    }\n\n    public void setBody(boolean body) {\n        this.body = body;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public List<SQLStatement> getStatements() {\n        return statements;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateSynonymStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleCreateSynonymStatement extends OracleStatementImpl implements SQLCreateStatement {\n    private boolean orReplace;\n    private SQLName name;\n    private boolean isPublic;\n    private SQLName object;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, object);\n        }\n    }\n\n    public boolean isPublic() {\n        return isPublic;\n    }\n\n    public void setPublic(boolean value) {\n        isPublic = value;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLName getObject() {\n        return object;\n    }\n\n    public void setObject(SQLName object) {\n        if (object != null) {\n            object.setParent(this);\n        }\n        this.object = object;\n    }\n\n    public boolean isOrReplace() {\n        return orReplace;\n    }\n\n    public void setOrReplace(boolean orReplace) {\n        this.orReplace = orReplace;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTableSpaceStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\n/**\n * @author gaoWL\n */\npublic class OracleCreateTableSpaceStatement extends OracleStatementImpl implements SQLCreateStatement, OracleStatement {\n    private SQLName name;\n\n    private String sql;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public void setSql(String sql) {\n        this.sql = sql;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributesImpl;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleCreateTableStatement extends SQLCreateTableStatement implements OracleDDLStatement, OracleSegmentAttributes {\n    private boolean inMemoryMetadata;\n\n    private boolean cursorSpecificSegment;\n\n    // NOPARALLEL\n    private Boolean parallel;\n    private SQLExpr parallelValue;\n\n    private OracleStorageClause storage;\n    private OracleLobStorageClause lobStorage;\n\n    private Integer pctfree;\n    private Integer pctused;\n    private Integer initrans;\n    private Integer maxtrans;\n    private Integer pctincrease;\n\n    private Integer compressLevel;\n    private boolean compressForOltp;\n\n    private Boolean cache;\n\n    private DeferredSegmentCreation deferredSegmentCreation;\n\n    private Boolean enableRowMovement;\n\n    private List<SQLName> clusterColumns = new ArrayList<SQLName>();\n    private SQLName cluster;\n\n    private Organization organization;\n\n    private SQLName of;\n    private OIDIndex oidIndex;\n    private boolean monitoring;\n    private List<SQLName> including = new ArrayList<SQLName>();\n    private OracleXmlColumnProperties xmlTypeColumnProperties;\n\n    public void simplify() {\n        tablespace = null;\n        storage = null;\n        lobStorage = null;\n\n        pctfree = null;\n        pctused = null;\n        initrans = null;\n        maxtrans = null;\n        pctincrease = null;\n\n        logging = null;\n        compress = null;\n        compressLevel = null;\n        compressForOltp = false;\n\n        onCommitPreserveRows = false;\n        onCommitDeleteRows = false;\n\n        super.simplify();\n    }\n\n    public OracleCreateTableStatement() {\n        super(DbType.oracle);\n    }\n\n    public OracleLobStorageClause getLobStorage() {\n        return lobStorage;\n    }\n\n    public void setLobStorage(OracleLobStorageClause lobStorage) {\n        this.lobStorage = lobStorage;\n    }\n\n    public DeferredSegmentCreation getDeferredSegmentCreation() {\n        return deferredSegmentCreation;\n    }\n\n    public void setDeferredSegmentCreation(DeferredSegmentCreation deferredSegmentCreation) {\n        this.deferredSegmentCreation = deferredSegmentCreation;\n    }\n\n    public Boolean getCache() {\n        return cache;\n    }\n\n    public void setCache(Boolean cache) {\n        this.cache = cache;\n    }\n\n    public boolean isOnCommitDeleteRows() {\n        return onCommitDeleteRows;\n    }\n\n    public void setOnCommitDeleteRows(boolean onCommitDeleteRows) {\n        this.onCommitDeleteRows = onCommitDeleteRows;\n    }\n\n    public Integer getCompressLevel() {\n        return compressLevel;\n    }\n\n    public void setCompressLevel(Integer compressLevel) {\n        this.compressLevel = compressLevel;\n    }\n\n    public Integer getPctfree() {\n        return pctfree;\n    }\n\n    public void setPctfree(Integer pctfree) {\n        this.pctfree = pctfree;\n    }\n\n    public Integer getPctused() {\n        return pctused;\n    }\n\n    public void setPctused(Integer pctused) {\n        this.pctused = pctused;\n    }\n\n    public Integer getInitrans() {\n        return initrans;\n    }\n\n    public void setInitrans(Integer initrans) {\n        this.initrans = initrans;\n    }\n\n    public Integer getMaxtrans() {\n        return maxtrans;\n    }\n\n    public void setMaxtrans(Integer maxtrans) {\n        this.maxtrans = maxtrans;\n    }\n\n    public Integer getPctincrease() {\n        return pctincrease;\n    }\n\n    public void setPctincrease(Integer pctincrease) {\n        this.pctincrease = pctincrease;\n    }\n\n    public Boolean getParallel() {\n        return parallel;\n    }\n\n    public void setParallel(Boolean parallel) {\n        this.parallel = parallel;\n    }\n\n    public SQLExpr getParallelValue() {\n        return parallelValue;\n    }\n\n    public void setParallelValue(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.parallelValue = x;\n    }\n\n    public boolean isCursorSpecificSegment() {\n        return cursorSpecificSegment;\n    }\n\n    public void setCursorSpecificSegment(boolean cursorSpecificSegment) {\n        this.cursorSpecificSegment = cursorSpecificSegment;\n    }\n\n    public boolean isInMemoryMetadata() {\n        return inMemoryMetadata;\n    }\n\n    public void setInMemoryMetadata(boolean inMemoryMetadata) {\n        this.inMemoryMetadata = inMemoryMetadata;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    public OracleStorageClause getStorage() {\n        return storage;\n    }\n\n    public void setStorage(SQLObject storage) {\n        if (storage != null) {\n            storage.setParent(this);\n        }\n        this.storage = (OracleStorageClause) storage;\n    }\n\n    public SQLName getOf() {\n        return of;\n    }\n\n    public void setOf(SQLName of) {\n        if (of != null) {\n            of.setParent(this);\n        }\n        this.of = of;\n    }\n\n    public OIDIndex getOidIndex() {\n        return oidIndex;\n    }\n\n    public void setOidIndex(OIDIndex oidIndex) {\n        if (oidIndex != null) {\n            oidIndex.setParent(this);\n        }\n        this.oidIndex = oidIndex;\n    }\n\n    public boolean isMonitoring() {\n        return monitoring;\n    }\n\n    public void setMonitoring(boolean monitoring) {\n        this.monitoring = monitoring;\n    }\n\n    public boolean isCompressForOltp() {\n        return compressForOltp;\n    }\n\n    public void setCompressForOltp(boolean compressForOltp) {\n        this.compressForOltp = compressForOltp;\n    }\n\n    public Boolean getEnableRowMovement() {\n        return enableRowMovement;\n    }\n\n    public void setEnableRowMovement(Boolean enableRowMovement) {\n        this.enableRowMovement = enableRowMovement;\n    }\n\n    public List<SQLName> getClusterColumns() {\n        return clusterColumns;\n    }\n\n    public SQLName getCluster() {\n        return cluster;\n    }\n\n    public void setCluster(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.cluster = x;\n    }\n\n    public List<SQLName> getIncluding() {\n        return including;\n    }\n\n    public Organization getOrganization() {\n        return organization;\n    }\n\n    public void setOrganization(Organization organization) {\n        if (organization != null) {\n            organization.setParent(this);\n        }\n        this.organization = organization;\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, tableSource);\n            this.acceptChild(visitor, of);\n            this.acceptChild(visitor, tableElementList);\n            this.acceptChild(visitor, tablespace);\n            this.acceptChild(visitor, select);\n            this.acceptChild(visitor, storage);\n            this.acceptChild(visitor, partitionBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public static enum DeferredSegmentCreation {\n        IMMEDIATE, DEFERRED\n    }\n\n    public static class Organization extends OracleSegmentAttributesImpl implements OracleSegmentAttributes, OracleSQLObject {\n        public String type;\n\n        private SQLName externalType;\n        private SQLExpr externalDirectory;\n        private SQLExternalRecordFormat externalDirectoryRecordFormat;\n        private List<SQLExpr> externalDirectoryLocation = new ArrayList<SQLExpr>();\n        private SQLExpr externalRejectLimit;\n\n        protected void accept0(SQLASTVisitor visitor) {\n            this.accept0((OracleASTVisitor) visitor);\n        }\n\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, tablespace);\n                acceptChild(visitor, storage);\n            }\n            visitor.endVisit(this);\n        }\n\n        public String getType() {\n            return type;\n        }\n\n        public void setType(String type) {\n            this.type = type;\n        }\n\n        public SQLName getExternalType() {\n            return externalType;\n        }\n\n        public void setExternalType(SQLName externalType) {\n            this.externalType = externalType;\n        }\n\n        public SQLExpr getExternalDirectory() {\n            return externalDirectory;\n        }\n\n        public void setExternalDirectory(SQLExpr externalDirectory) {\n            this.externalDirectory = externalDirectory;\n        }\n\n        public SQLExternalRecordFormat getExternalDirectoryRecordFormat() {\n            return externalDirectoryRecordFormat;\n        }\n\n        public void setExternalDirectoryRecordFormat(SQLExternalRecordFormat recordFormat) {\n            if (recordFormat != null) {\n                recordFormat.setParent(this);\n            }\n            this.externalDirectoryRecordFormat = recordFormat;\n        }\n\n        public SQLExpr getExternalRejectLimit() {\n            return externalRejectLimit;\n        }\n\n        public void setExternalRejectLimit(SQLExpr externalRejectLimit) {\n            if (externalRejectLimit != null) {\n                externalRejectLimit.setParent(this);\n            }\n            this.externalRejectLimit = externalRejectLimit;\n        }\n\n        public List<SQLExpr> getExternalDirectoryLocation() {\n            return externalDirectoryLocation;\n        }\n    }\n\n    public OracleXmlColumnProperties getXmlTypeColumnProperties() {\n        return xmlTypeColumnProperties;\n    }\n\n    public void setXmlTypeColumnProperties(OracleXmlColumnProperties x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.xmlTypeColumnProperties = x;\n    }\n\n    public static class OIDIndex extends OracleSegmentAttributesImpl implements OracleSQLObject {\n        private SQLName name;\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, name);\n                acceptChild(visitor, tablespace);\n                acceptChild(visitor, storage);\n            }\n            visitor.endVisit(this);\n        }\n\n        protected void accept0(SQLASTVisitor visitor) {\n            accept0((OracleASTVisitor) visitor);\n        }\n\n        public SQLName getName() {\n            return name;\n        }\n\n        public void setName(SQLName name) {\n            if (name != null) {\n                name.setParent(this);\n            }\n            this.name = name;\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleCreateTypeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleCreateTypeStatement extends OracleStatementImpl implements SQLCreateStatement {\n    private boolean orReplace;\n    private SQLName name;\n    private SQLName authId;\n    private boolean force;\n    private SQLName oid;\n    private boolean body;\n    private boolean object;\n    private boolean paren;\n    private Boolean isFinal;\n    private Boolean instantiable;\n\n    private SQLName under;\n\n    private List<SQLParameter> parameters = new ArrayList<SQLParameter>();\n\n    private SQLDataType tableOf;\n    private SQLDataType indexBy;\n\n    private SQLExpr varraySizeLimit;\n    private SQLDataType varrayDataType;\n\n    private String wrappedSource;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, authId);\n            acceptChild(visitor, oid);\n            acceptChild(visitor, under);\n            acceptChild(visitor, parameters);\n            acceptChild(visitor, tableOf);\n            acceptChild(visitor, varraySizeLimit);\n            acceptChild(visitor, varrayDataType);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public boolean isOrReplace() {\n        return orReplace;\n    }\n\n    public void setOrReplace(boolean orReplace) {\n        this.orReplace = orReplace;\n    }\n\n    public boolean isForce() {\n        return force;\n    }\n\n    public void setForce(boolean force) {\n        this.force = force;\n    }\n\n    public SQLName getOid() {\n        return oid;\n    }\n\n    public void setOid(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.oid = x;\n    }\n\n    public SQLName getAuthId() {\n        return authId;\n    }\n\n    public void setAuthId(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.authId = x;\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    public boolean isBody() {\n        return body;\n    }\n\n    public void setBody(boolean body) {\n        this.body = body;\n    }\n\n    public Boolean getFinal() {\n        return isFinal;\n    }\n\n    public void setFinal(boolean aFinal) {\n        isFinal = aFinal;\n    }\n\n    public Boolean getInstantiable() {\n        return instantiable;\n    }\n\n    public void setInstantiable(boolean instantiable) {\n        this.instantiable = instantiable;\n    }\n\n    public SQLDataType getTableOf() {\n        return tableOf;\n    }\n\n    public void setTableOf(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.tableOf = x;\n    }\n\n    public SQLDataType getIndexBy() {\n        return indexBy;\n    }\n\n    public void setIndexBy(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.indexBy = x;\n    }\n\n    public SQLExpr getVarraySizeLimit() {\n        return varraySizeLimit;\n    }\n\n    public void setVarraySizeLimit(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.varraySizeLimit = x;\n    }\n\n    public SQLDataType getVarrayDataType() {\n        return varrayDataType;\n    }\n\n    public void setVarrayDataType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.varrayDataType = x;\n    }\n\n    public SQLName getUnder() {\n        return under;\n    }\n\n    public void setUnder(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.under = x;\n    }\n\n    public boolean isObject() {\n        return object;\n    }\n\n    public void setObject(boolean object) {\n        this.object = object;\n    }\n\n    public boolean isParen() {\n        return paren;\n    }\n\n    public void setParen(boolean paren) {\n        this.paren = paren;\n    }\n\n    public String getWrappedSource() {\n        return wrappedSource;\n    }\n\n    public void setWrappedSource(String wrappedSource) {\n        this.wrappedSource = wrappedSource;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleDDLStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLDDLStatement;\n\npublic interface OracleDDLStatement extends SQLDDLStatement, OracleStatement {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleDeleteStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleDeleteStatement extends SQLDeleteStatement {\n    private final List<SQLHint> hints = new ArrayList<SQLHint>();\n    private OracleReturningClause returning;\n\n    public OracleDeleteStatement() {\n        super(DbType.oracle);\n    }\n\n    public OracleReturningClause getReturning() {\n        return returning;\n    }\n\n    public void setReturning(OracleReturningClause returning) {\n        this.returning = returning;\n    }\n\n    public List<SQLHint> getHints() {\n        return this.hints;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    protected void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.hints);\n            acceptChild(visitor, this.tableSource);\n            acceptChild(visitor, this.getWhere());\n            acceptChild(visitor, returning);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public OracleDeleteStatement clone() {\n        OracleDeleteStatement x = new OracleDeleteStatement();\n        cloneTo(x);\n\n        for (SQLHint hint : hints) {\n            SQLHint hint2 = hint.clone();\n            hint2.setParent(x);\n            x.hints.add(hint2);\n        }\n        if (returning != null) {\n            x.setReturning(returning.clone());\n        }\n\n        return x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleDropDbLinkStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLDropStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleDropDbLinkStatement extends OracleStatementImpl implements SQLDropStatement {\n    private boolean isPublic;\n\n    private SQLName name;\n\n    public boolean isPublic() {\n        return isPublic;\n    }\n\n    public void setPublic(boolean value) {\n        this.isPublic = value;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleDropPackageStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLDropStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\n/**\n * @author gaoWL\n */\npublic class OracleDropPackageStatement extends OracleStatementImpl implements SQLDropStatement, OracleStatement {\n    private SQLName name;\n\n    private boolean body;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public boolean isBody() {\n        return body;\n    }\n\n    public void setBody(boolean body) {\n        this.body = body;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExecuteImmediateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLArgument;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExecuteImmediateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleExecuteImmediateStatement extends SQLExecuteImmediateStatement implements OracleStatement {\n    private final List<SQLArgument> arguments = new ArrayList<SQLArgument>();\n\n    private final List<SQLExpr> returnInto = new ArrayList<SQLExpr>();\n\n    public OracleExecuteImmediateStatement() {\n    }\n\n    public OracleExecuteImmediateStatement(String dynamicSql) {\n        this.setDynamicSql(dynamicSql);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) v);\n            return;\n        }\n        super.accept0(v);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    protected OracleExecuteImmediateStatement cloneTo(OracleExecuteImmediateStatement x) {\n        super.cloneTo(x);\n\n        for (SQLArgument arg : arguments) {\n            SQLArgument a2 = arg.clone();\n            a2.setParent(x);\n            x.arguments.add(a2);\n        }\n\n        for (SQLExpr e : returnInto) {\n            SQLExpr e2 = e.clone();\n            e2.setParent(x);\n            x.returnInto.add(e2);\n        }\n        return x;\n    }\n\n    public OracleExecuteImmediateStatement clone() {\n        OracleExecuteImmediateStatement x = new OracleExecuteImmediateStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    public List<SQLArgument> getArguments() {\n        return arguments;\n    }\n\n    public List<SQLExpr> getReturnInto() {\n        return returnInto;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExitStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleExitStatement extends OracleStatementImpl {\n    private String label;\n\n    private SQLExpr when;\n\n    public SQLExpr getWhen() {\n        return when;\n    }\n\n    public void setWhen(SQLExpr when) {\n        if (when != null) {\n            when.setParent(this);\n        }\n        this.when = when;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, when);\n        }\n        visitor.endVisit(this);\n    }\n\n    public String getLabel() {\n        return label;\n    }\n\n    public void setLabel(String label) {\n        this.label = label;\n    }\n\n    @Override\n    public OracleExitStatement clone() {\n        OracleExitStatement x = new OracleExitStatement();\n\n        x.setLabel(this.label);\n\n        x.setAfterSemi(this.afterSemi);\n\n        x.setDbType(this.dbType);\n\n        if (when != null) {\n            x.setWhen(when.clone());\n        }\n\n        if (this.headHints != null) {\n            List<SQLCommentHint> headHintsClone = new ArrayList<SQLCommentHint>(this.headHints.size());\n            for (SQLCommentHint hint : headHints) {\n                SQLCommentHint h2 = hint.clone();\n                h2.setParent(x);\n                headHintsClone.add(h2);\n            }\n            x.setHeadHints(headHintsClone);\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExplainStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExplainStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleExplainStatement extends SQLExplainStatement implements OracleStatement {\n    private SQLExpr statementId;\n    private SQLExpr into;\n\n    public OracleExplainStatement() {\n        super(DbType.oracle);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statementId);\n            acceptChild(visitor, into);\n            acceptChild(visitor, statement);\n        }\n        visitor.endVisit(this);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n\n    public SQLExpr getStatementId() {\n        return statementId;\n    }\n\n    public void setStatementId(SQLExpr statementId) {\n        this.statementId = statementId;\n    }\n\n    public SQLExpr getInto() {\n        return into;\n    }\n\n    public void setInto(SQLExpr into) {\n        this.into = into;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleFileSpecification.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleFileSpecification extends OracleSQLObjectImpl {\n    private List<SQLExpr> fileNames = new ArrayList<SQLExpr>();\n\n    private SQLExpr size;\n\n    private boolean autoExtendOff;\n\n    private SQLExpr autoExtendOn;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, fileNames);\n            acceptChild(visitor, size);\n            acceptChild(visitor, autoExtendOn);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getAutoExtendOn() {\n        return autoExtendOn;\n    }\n\n    public void setAutoExtendOn(SQLExpr autoExtendOn) {\n        this.autoExtendOn = autoExtendOn;\n    }\n\n    public SQLExpr getSize() {\n        return size;\n    }\n\n    public void setSize(SQLExpr size) {\n        this.size = size;\n    }\n\n    public boolean isAutoExtendOff() {\n        return autoExtendOff;\n    }\n\n    public void setAutoExtendOff(boolean autoExtendOff) {\n        this.autoExtendOff = autoExtendOff;\n    }\n\n    public List<SQLExpr> getFileNames() {\n        return fileNames;\n    }\n\n    public void setFileNames(List<SQLExpr> fileNames) {\n        this.fileNames = fileNames;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLForStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleForStatement extends SQLForStatement implements OracleStatement {\n    private boolean all;\n\n    private SQLName endLabel;\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) v);\n            return;\n        }\n\n        super.accept0(v);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, index);\n            acceptChild(v, range);\n            acceptChild(v, statements);\n        }\n        v.endVisit(this);\n    }\n\n    public boolean isAll() {\n        return all;\n    }\n\n    public void setAll(boolean all) {\n        this.all = all;\n    }\n\n    public SQLName getEndLabel() {\n        return endLabel;\n    }\n\n    public void setEndLabel(SQLName endLabel) {\n        if (endLabel != null) {\n            endLabel.setParent(this);\n        }\n        this.endLabel = endLabel;\n    }\n\n    public OracleForStatement clone() {\n        OracleForStatement x = new OracleForStatement();\n        if (index != null) {\n            x.setIndex(index.clone());\n        }\n        if (range != null) {\n            x.setRange(range.clone());\n        }\n        for (SQLStatement stmt : statements) {\n            SQLStatement stmt2 = stmt.clone();\n            stmt2.setParent(x);\n            x.statements.add(stmt2);\n        }\n        x.all = all;\n        if (endLabel != null) {\n            x.setEndLabel(endLabel.clone());\n        }\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleForeignKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleForeignKey extends SQLForeignKeyImpl implements OracleConstraint, OracleSQLObject {\n    private OracleUsingIndexClause using;\n    private SQLName exceptionsInto;\n    private Initially initially;\n    private Boolean deferrable;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) visitor);\n            return;\n        }\n\n        super.accept(visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getReferencedTableName());\n            acceptChild(visitor, this.getReferencingColumns());\n            acceptChild(visitor, this.getReferencedColumns());\n\n            acceptChild(visitor, using);\n            acceptChild(visitor, exceptionsInto);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getDeferrable() {\n        return deferrable;\n    }\n\n    public void setDeferrable(Boolean deferrable) {\n        this.deferrable = deferrable;\n    }\n\n    public Initially getInitially() {\n        return initially;\n    }\n\n    public void setInitially(Initially initially) {\n        this.initially = initially;\n    }\n\n    public SQLName getExceptionsInto() {\n        return exceptionsInto;\n    }\n\n    public void setExceptionsInto(SQLName exceptionsInto) {\n        this.exceptionsInto = exceptionsInto;\n    }\n\n    public OracleUsingIndexClause getUsing() {\n        return using;\n    }\n\n    public void setUsing(OracleUsingIndexClause using) {\n        if (using != null) {\n            using.setParent(this);\n        }\n        this.using = using;\n    }\n\n    public void cloneTo(OracleForeignKey x) {\n        super.cloneTo(x);\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n        if (exceptionsInto != null) {\n            x.setExceptionsInto(exceptionsInto.clone());\n        }\n        x.initially = initially;\n        x.deferrable = deferrable;\n    }\n\n    public OracleForeignKey clone() {\n        OracleForeignKey x = new OracleForeignKey();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleGotoStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleGotoStatement extends OracleStatementImpl {\n    private SQLName label;\n\n    public OracleGotoStatement() {\n    }\n\n    public OracleGotoStatement(SQLName label) {\n        this.label = label;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, label);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getLabel() {\n        return label;\n    }\n\n    public void setLabel(SQLName label) {\n        this.label = label;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.statement.SQLErrorLoggingClause;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleInsertStatement extends SQLInsertStatement implements OracleStatement {\n    private OracleReturningClause returning;\n    private SQLErrorLoggingClause errorLogging;\n    private List<SQLHint> hints = new ArrayList<SQLHint>();\n\n    public OracleInsertStatement() {\n        dbType = DbType.oracle;\n    }\n\n    public void cloneTo(OracleInsertStatement x) {\n        super.cloneTo(x);\n        if (returning != null) {\n            x.setReturning(returning.clone());\n        }\n        if (errorLogging != null) {\n            x.setErrorLogging(errorLogging.clone());\n        }\n        for (SQLHint hint : hints) {\n            SQLHint h2 = hint.clone();\n            h2.setParent(x);\n            x.hints.add(h2);\n        }\n    }\n\n    public List<SQLHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLHint> hints) {\n        this.hints = hints;\n    }\n\n    public OracleReturningClause getReturning() {\n        return returning;\n    }\n\n    public void setReturning(OracleReturningClause returning) {\n        this.returning = returning;\n    }\n\n    public SQLErrorLoggingClause getErrorLogging() {\n        return errorLogging;\n    }\n\n    public void setErrorLogging(SQLErrorLoggingClause errorLogging) {\n        this.errorLogging = errorLogging;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, getTableSource());\n            this.acceptChild(visitor, getColumns());\n            this.acceptChild(visitor, getValues());\n            this.acceptChild(visitor, getQuery());\n            this.acceptChild(visitor, returning);\n            this.acceptChild(visitor, errorLogging);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public OracleInsertStatement clone() {\n        OracleInsertStatement x = new OracleInsertStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    @Override\n    public List<SQLCommentHint> getHeadHintsDirect() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLabelStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleLabelStatement extends OracleStatementImpl {\n    private SQLName label;\n\n    public OracleLabelStatement() {\n    }\n\n    public OracleLabelStatement(SQLName label) {\n        this.label = label;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, label);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getLabel() {\n        return label;\n    }\n\n    public void setLabel(SQLName label) {\n        this.label = label;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLobParameters.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleLobParameters extends OracleSQLObjectImpl {\n    private SQLName tableSpace;\n    private Boolean enableStorageInRow;\n    private SQLExpr chunk;\n    private Boolean cache;\n    private Boolean logging;\n    private Boolean compress;\n    private Boolean keepDuplicates;\n    private OracleStorageClause storage;\n    private SQLExpr pctVersion;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n    }\n\n    public OracleStorageClause getStorage() {\n        return storage;\n    }\n\n    public void setStorage(OracleStorageClause x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storage = x;\n    }\n\n    public SQLName getTableSpace() {\n        return tableSpace;\n    }\n\n    public void setTableSpace(SQLName tableSpace) {\n        this.tableSpace = tableSpace;\n    }\n\n    public Boolean getEnableStorageInRow() {\n        return enableStorageInRow;\n    }\n\n    public void setEnableStorageInRow(Boolean enableStorageInRow) {\n        this.enableStorageInRow = enableStorageInRow;\n    }\n\n    public SQLExpr getChunk() {\n        return chunk;\n    }\n\n    public void setChunk(SQLExpr chunk) {\n        this.chunk = chunk;\n    }\n\n    public Boolean getCache() {\n        return cache;\n    }\n\n    public void setCache(Boolean cache) {\n        this.cache = cache;\n    }\n\n    public Boolean getLogging() {\n        return logging;\n    }\n\n    public void setLogging(Boolean logging) {\n        this.logging = logging;\n    }\n\n    public Boolean getCompress() {\n        return compress;\n    }\n\n    public void setCompress(Boolean compress) {\n        this.compress = compress;\n    }\n\n    public Boolean getKeepDuplicates() {\n        return keepDuplicates;\n    }\n\n    public void setKeepDuplicates(Boolean keepDuplicates) {\n        this.keepDuplicates = keepDuplicates;\n    }\n\n    public SQLExpr getPctVersion() {\n        return pctVersion;\n    }\n\n    public void setPctVersion(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.pctVersion = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLLockTableStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleLockTableStatement extends OracleStatementImpl implements SQLLockTableStatement {\n    private SQLExprTableSource table;\n    private LockMode lockMode;\n    private boolean noWait;\n    private SQLExpr wait;\n    private SQLExpr partition;\n\n    public boolean isNoWait() {\n        return noWait;\n    }\n\n    public void setNoWait(boolean noWait) {\n        this.noWait = noWait;\n    }\n\n    public SQLExpr getWait() {\n        return wait;\n    }\n\n    public void setWait(SQLExpr wait) {\n        this.wait = wait;\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource table) {\n        if (table != null) {\n            table.setParent(this);\n        }\n        this.table = table;\n    }\n\n    public void setTable(SQLName table) {\n        this.setTable(new SQLExprTableSource(table));\n        this.table.setParent(this);\n    }\n\n    public LockMode getLockMode() {\n        return lockMode;\n    }\n\n    public void setLockMode(LockMode lockMode) {\n        this.lockMode = lockMode;\n    }\n\n    public SQLExpr getPartition() {\n        return partition;\n    }\n\n    public void setPartition(SQLExpr partition) {\n        this.partition = partition;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, table);\n            acceptChild(visitor, partition);\n            acceptChild(visitor, wait);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (table != null) {\n            children.add(table);\n        }\n        if (wait != null) {\n            children.add(wait);\n        }\n        if (partition != null) {\n            children.add(partition);\n        }\n        return children;\n    }\n\n    public static enum LockMode {\n        ROW_SHARE,\n        ROW_EXCLUSIVE,\n        SHARE_UPDATE,\n        SHARE,\n        SHARE_ROW_EXCLUSIVE,\n        EXCLUSIVE;\n\n        public String toString() {\n            switch (this) {\n                case ROW_SHARE:\n                    return \"ROW SHARE\";\n                case ROW_EXCLUSIVE:\n                    return \"ROW EXCLUSIVE\";\n                case SHARE_UPDATE:\n                    return \"SHARE UPDATE\";\n                case SHARE_ROW_EXCLUSIVE:\n                    return \"SHARE ROW EXCLUSIVE\";\n                default:\n                    return this.name();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleMultiInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.statement.SQLErrorLoggingClause;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertInto;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleMultiInsertStatement extends OracleStatementImpl {\n    public static enum Option {\n        ALL, FIRST\n    }\n\n    private SQLSelect subQuery;\n    private Option option;\n    private List<Entry> entries = new ArrayList<Entry>();\n    private List<SQLHint> hints = new ArrayList<SQLHint>(1);\n\n    public List<SQLHint> getHints() {\n        return hints;\n    }\n\n    public void setHints(List<SQLHint> hints) {\n        this.hints = hints;\n    }\n\n    public List<Entry> getEntries() {\n        return entries;\n    }\n\n    public void addEntry(Entry entry) {\n        if (entry != null) {\n            entry.setParent(this);\n        }\n        this.entries.add(entry);\n    }\n\n    public Option getOption() {\n        return option;\n    }\n\n    public void setOption(Option option) {\n        this.option = option;\n    }\n\n    public SQLSelect getSubQuery() {\n        return subQuery;\n    }\n\n    public void setSubQuery(SQLSelect subQuery) {\n        this.subQuery = subQuery;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.entries);\n            acceptChild(visitor, this.subQuery);\n        }\n        visitor.endVisit(this);\n    }\n\n    public static interface Entry extends OracleSQLObject {\n    }\n\n    public static class ConditionalInsertClause extends OracleSQLObjectImpl implements Entry {\n        private List<ConditionalInsertClauseItem> items = new ArrayList<ConditionalInsertClauseItem>();\n        private InsertIntoClause elseItem;\n\n        public InsertIntoClause getElseItem() {\n            return elseItem;\n        }\n\n        public void setElseItem(InsertIntoClause elseItem) {\n            this.elseItem = elseItem;\n        }\n\n        public List<ConditionalInsertClauseItem> getItems() {\n            return items;\n        }\n\n        public void addItem(ConditionalInsertClauseItem item) {\n            if (item != null) {\n                item.setParent(this);\n            }\n            this.items.add(item);\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, items);\n                acceptChild(visitor, elseItem);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static class ConditionalInsertClauseItem extends OracleSQLObjectImpl {\n        private SQLExpr when;\n        private InsertIntoClause then;\n\n        public SQLExpr getWhen() {\n            return when;\n        }\n\n        public void setWhen(SQLExpr when) {\n            this.when = when;\n        }\n\n        public InsertIntoClause getThen() {\n            return then;\n        }\n\n        public void setThen(InsertIntoClause then) {\n            this.then = then;\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, when);\n                acceptChild(visitor, then);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static class InsertIntoClause extends SQLInsertInto implements OracleSQLObject, Entry {\n        private OracleReturningClause returning;\n        private SQLErrorLoggingClause errorLogging;\n\n        public InsertIntoClause() {\n        }\n\n        public OracleReturningClause getReturning() {\n            return returning;\n        }\n\n        public void setReturning(OracleReturningClause returning) {\n            this.returning = returning;\n        }\n\n        public SQLErrorLoggingClause getErrorLogging() {\n            return errorLogging;\n        }\n\n        public void setErrorLogging(SQLErrorLoggingClause errorLogging) {\n            this.errorLogging = errorLogging;\n        }\n\n        @Override\n        protected void accept0(SQLASTVisitor visitor) {\n            this.accept0((OracleASTVisitor) visitor);\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                this.acceptChild(visitor, tableSource);\n                this.acceptChild(visitor, columns);\n                this.acceptChild(visitor, valuesList);\n                this.acceptChild(visitor, query);\n                this.acceptChild(visitor, returning);\n                this.acceptChild(visitor, errorLogging);\n            }\n\n            visitor.endVisit(this);\n        }\n\n        public void cloneTo(InsertIntoClause x) {\n            super.cloneTo(x);\n            if (returning != null) {\n                x.setReturning(returning.clone());\n            }\n            if (errorLogging != null) {\n                x.setErrorLogging(errorLogging.clone());\n            }\n        }\n\n        public InsertIntoClause clone() {\n            InsertIntoClause x = new InsertIntoClause();\n            cloneTo(x);\n            return x;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePipeRowStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OraclePipeRowStatement extends OracleStatementImpl {\n    private final List<SQLExpr> parameters = new ArrayList<SQLExpr>();\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLExpr> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public OraclePipeRowStatement clone() {\n        OraclePipeRowStatement x = new OraclePipeRowStatement();\n\n        x.setAfterSemi(this.afterSemi);\n\n        x.setDbType(this.dbType);\n\n        for (SQLExpr expr : parameters) {\n            SQLExpr expr2 = expr.clone();\n            expr2.setParent(x);\n            x.parameters.add(expr2);\n        }\n\n        if (this.headHints != null) {\n            List<SQLCommentHint> headHintsClone = new ArrayList<SQLCommentHint>(this.headHints.size());\n            for (SQLCommentHint hint : headHints) {\n                SQLCommentHint h2 = hint.clone();\n                h2.setParent(x);\n                headHintsClone.add(h2);\n            }\n            x.setHeadHints(headHintsClone);\n        }\n\n        return x;\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePrimaryKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLTableConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OraclePrimaryKey extends SQLPrimaryKeyImpl implements OracleConstraint, SQLPrimaryKey, SQLTableElement, SQLTableConstraint {\n    private OracleUsingIndexClause using;\n    private SQLName exceptionsInto;\n    private Boolean enable;\n    private Initially initially;\n    private Boolean deferrable;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getName());\n            acceptChild(visitor, getColumns());\n            acceptChild(visitor, using);\n            acceptChild(visitor, exceptionsInto);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getDeferrable() {\n        return deferrable;\n    }\n\n    public void setDeferrable(Boolean deferrable) {\n        this.deferrable = deferrable;\n    }\n\n    public OracleUsingIndexClause getUsing() {\n        return using;\n    }\n\n    public void setUsing(OracleUsingIndexClause using) {\n        this.using = using;\n    }\n\n    public SQLName getExceptionsInto() {\n        return exceptionsInto;\n    }\n\n    public void setExceptionsInto(SQLName exceptionsInto) {\n        this.exceptionsInto = exceptionsInto;\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public Initially getInitially() {\n        return initially;\n    }\n\n    public void setInitially(Initially initially) {\n        this.initially = initially;\n    }\n\n    public void cloneTo(OraclePrimaryKey x) {\n        super.cloneTo(x);\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n        if (exceptionsInto != null) {\n            x.setExceptionsInto(exceptionsInto.clone());\n        }\n        x.enable = enable;\n        x.initially = initially;\n        x.deferrable = deferrable;\n    }\n\n    public OraclePrimaryKey clone() {\n        OraclePrimaryKey x = new OraclePrimaryKey();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleRaiseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleRaiseStatement extends OracleStatementImpl {\n    private SQLExpr exception;\n\n    public SQLExpr getException() {\n        return exception;\n    }\n\n    public void setException(SQLExpr exception) {\n        this.exception = exception;\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, exception);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleRunStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleRunStatement extends SQLStatementImpl implements OracleStatement {\n    private SQLExpr expr;\n\n    public OracleRunStatement() {\n        super(DbType.oracle);\n    }\n\n    public OracleRunStatement(SQLExpr expr) {\n        super(DbType.oracle);\n        this.setExpr(expr);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, expr);\n        }\n        visitor.endVisit(this);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        if (expr != null) {\n            expr.setParent(this);\n        }\n        this.expr = expr;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectJoin.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleSelectJoin extends SQLJoinTableSource implements OracleSelectTableSource {\n    public OracleSelectJoin(String alias) {\n        super(alias);\n    }\n\n    public OracleSelectJoin() {\n    }\n\n    public OracleSelectJoin(SQLTableSource left, JoinType joinType, SQLTableSource right, SQLExpr condition) {\n        super(left, joinType, right, condition);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            this.accept0((OracleASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.left);\n            acceptChild(visitor, this.right);\n            acceptChild(visitor, this.condition);\n            acceptChild(visitor, this.using);\n            acceptChild(visitor, this.flashback);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        OracleSelectJoin that = (OracleSelectJoin) o;\n\n        if (pivot != null ? !pivot.equals(that.pivot) : that.pivot != null) {\n            return false;\n        }\n        if (unpivot != null ? !unpivot.equals(that.unpivot) : that.unpivot != null) {\n            return false;\n        }\n        return flashback != null ? flashback.equals(that.flashback) : that.flashback == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = pivot != null ? pivot.hashCode() : 0;\n        result = 31 * result + (unpivot != null ? unpivot.hashCode() : 0);\n        result = 31 * result + (flashback != null ? flashback.hashCode() : 0);\n        return result;\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n\n    public SQLJoinTableSource clone() {\n        OracleSelectJoin x = new OracleSelectJoin();\n        cloneTo(x);\n\n        if (pivot != null) {\n            x.setPivot(pivot.clone());\n        }\n\n        if (unpivot != null) {\n            x.setUnpivot(unpivot.clone());\n        }\n\n        if (flashback != null) {\n            x.setFlashback(flashback.clone());\n        }\n\n        return x;\n    }\n\n    public void setLeft(String tableName) {\n        SQLExprTableSource tableSource;\n        if (tableName == null || tableName.length() == 0) {\n            tableSource = null;\n        } else {\n            tableSource = new OracleSelectTableReference(new SQLIdentifierExpr(tableName));\n        }\n        this.setLeft(tableSource);\n    }\n\n    public void setRight(String tableName) {\n        SQLExprTableSource tableSource;\n        if (tableName == null || tableName.length() == 0) {\n            tableSource = null;\n        } else {\n            tableSource = new OracleSelectTableReference(new SQLIdentifierExpr(tableName));\n        }\n        this.setRight(tableSource);\n    }\n\n    public SQLJoinTableSource join(SQLTableSource right, JoinType joinType, SQLExpr condition) {\n        SQLJoinTableSource joined = new OracleSelectJoin(this, joinType, right, condition);\n        return joined;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectPivotBase.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLPivot;\n\npublic abstract class OracleSelectPivotBase extends SQLPivot {\n    public OracleSelectPivotBase() {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleSelectQueryBlock extends SQLSelectQueryBlock implements OracleSQLObject {\n    private ModelClause modelClause;\n\n    private boolean skipLocked;\n\n    public OracleSelectQueryBlock clone() {\n        OracleSelectQueryBlock x = new OracleSelectQueryBlock();\n\n        super.cloneTo(x);\n\n        if (modelClause != null) {\n            x.setModelClause(modelClause.clone());\n        }\n\n        if (forUpdateOf != null) {\n            for (SQLExpr item : forUpdateOf) {\n                SQLExpr item1 = item.clone();\n                item1.setParent(x);\n                x.getForUpdateOf().add(item1);\n            }\n        }\n\n        x.skipLocked = skipLocked;\n\n        return x;\n    }\n\n    public OracleSelectQueryBlock() {\n        dbType = DbType.oracle;\n    }\n\n    public ModelClause getModelClause() {\n        return modelClause;\n    }\n\n    public void setModelClause(ModelClause modelClause) {\n        this.modelClause = modelClause;\n    }\n\n    public boolean isSkipLocked() {\n        return skipLocked;\n    }\n\n    public void setSkipLocked(boolean skipLocked) {\n        this.skipLocked = skipLocked;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.hints);\n            acceptChild(visitor, this.selectList);\n            acceptChild(visitor, this.into);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.startWith);\n            acceptChild(visitor, this.connectBy);\n            acceptChild(visitor, this.groupBy);\n            acceptChild(visitor, this.orderBy);\n            acceptChild(visitor, this.waitTime);\n            acceptChild(visitor, this.limit);\n            acceptChild(visitor, this.modelClause);\n            acceptChild(visitor, this.forUpdateOf);\n        }\n        visitor.endVisit(this);\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n\n    public void limit(int rowCount, int offset) {\n        if (offset <= 0) {\n            SQLExpr rowCountExpr = new SQLIntegerExpr(rowCount);\n            SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, rowCountExpr, false,\n                    where);\n            setWhere(newCondition);\n        } else {\n            throw new UnsupportedOperationException(\"not support offset\");\n        }\n    }\n\n    public void setFrom(String tableName) {\n        SQLExprTableSource from;\n        if (tableName == null || tableName.length() == 0) {\n            from = null;\n        } else {\n            from = new OracleSelectTableReference(new SQLIdentifierExpr(tableName));\n        }\n        this.setFrom(from);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectRestriction.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic abstract class OracleSelectRestriction extends OracleSQLObjectImpl {\n    protected SQLName constraint;\n\n    public OracleSelectRestriction() {\n    }\n\n    public SQLName getConstraint() {\n        return constraint;\n    }\n\n    public void setConstraint(SQLName constraint) {\n        if (constraint != null) {\n            constraint.setParent(this);\n        }\n        this.constraint = constraint;\n    }\n\n    public static class CheckOption extends OracleSelectRestriction {\n        public CheckOption() {\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, this.constraint);\n            }\n\n            visitor.endVisit(this);\n        }\n\n        @Override\n        public CheckOption clone() {\n            CheckOption x = new CheckOption();\n            if (constraint != null) {\n                x.setConstraint(constraint.clone());\n            }\n            return x;\n        }\n    }\n\n    public static class ReadOnly extends OracleSelectRestriction {\n        public ReadOnly() {\n        }\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n            visitor.visit(this);\n\n            visitor.endVisit(this);\n        }\n\n        @Override\n        public ReadOnly clone() {\n            ReadOnly x = new ReadOnly();\n            return x;\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectSubqueryTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleSelectSubqueryTableSource extends SQLSubqueryTableSource implements OracleSelectTableSource {\n    public OracleSelectSubqueryTableSource() {\n    }\n\n    public OracleSelectSubqueryTableSource(String alias) {\n        super(alias);\n    }\n\n    public OracleSelectSubqueryTableSource(SQLSelect select, String alias) {\n        super(select, alias);\n    }\n\n    public OracleSelectSubqueryTableSource(SQLSelect select) {\n        super(select);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OracleASTVisitor) visitor);\n    }\n\n    protected void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getHints());\n            acceptChild(visitor, this.select);\n            acceptChild(visitor, this.pivot);\n            acceptChild(visitor, this.unpivot);\n            acceptChild(visitor, this.flashback);\n        }\n        visitor.endVisit(this);\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n\n    public OracleSelectSubqueryTableSource clone() {\n        OracleSelectSubqueryTableSource x = new OracleSelectSubqueryTableSource();\n        cloneTo(x);\n\n        if (pivot != null) {\n            setParent(pivot.clone());\n        }\n\n        if (unpivot != null) {\n            x.setUnpivot(unpivot.clone());\n        }\n\n        return x;\n    }\n\n    public void cloneTo(OracleSelectSubqueryTableSource x) {\n        x.alias = alias;\n\n        if (this.getPivot() != null) {\n            x.setPivot(this.getPivot());\n        }\n\n        if (select != null) {\n            x.select = select.clone();\n            x.select.setParent(x);\n        }\n\n        for (SQLName column : columns) {\n            SQLName c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableReference.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleSelectTableReference extends SQLExprTableSource implements OracleSelectTableSource {\n    private boolean only;\n\n    protected PartitionExtensionClause partition;\n    protected SampleClause sampleClause;\n\n    public OracleSelectTableReference() {\n    }\n\n    public OracleSelectTableReference(SQLExpr expr) {\n        this.setExpr(expr);\n    }\n\n    public PartitionExtensionClause getPartition() {\n        return partition;\n    }\n\n    public void setPartition(PartitionExtensionClause partition) {\n        if (partition != null) {\n            partition.setParent(this);\n        }\n        this.partition = partition;\n    }\n\n    public boolean isOnly() {\n        return this.only;\n    }\n\n    public void setOnly(boolean only) {\n        this.only = only;\n    }\n\n    public SampleClause getSampleClause() {\n        return sampleClause;\n    }\n\n    public void setSampleClause(SampleClause sampleClause) {\n        if (sampleClause != null) {\n            sampleClause.setParent(this);\n        }\n        this.sampleClause = sampleClause;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            this.accept0((OracleASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n            acceptChild(visitor, this.partition);\n            acceptChild(visitor, this.sampleClause);\n            acceptChild(visitor, this.pivot);\n            acceptChild(visitor, this.unpivot);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n\n        OracleSelectTableReference that = (OracleSelectTableReference) o;\n\n        if (only != that.only) {\n            return false;\n        }\n        if (pivot != null ? !pivot.equals(that.pivot) : that.pivot != null) {\n            return false;\n        }\n        if (unpivot != null ? !unpivot.equals(that.unpivot) : that.unpivot != null) {\n            return false;\n        }\n        if (partition != null ? !partition.equals(that.partition) : that.partition != null) {\n            return false;\n        }\n        if (sampleClause != null ? !sampleClause.equals(that.sampleClause) : that.sampleClause != null) {\n            return false;\n        }\n        return flashback != null ? flashback.equals(that.flashback) : that.flashback == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = super.hashCode();\n        result = 31 * result + (only ? 1 : 0);\n        result = 31 * result + (pivot != null ? pivot.hashCode() : 0);\n        result = 31 * result + (unpivot != null ? unpivot.hashCode() : 0);\n        result = 31 * result + (partition != null ? partition.hashCode() : 0);\n        result = 31 * result + (sampleClause != null ? sampleClause.hashCode() : 0);\n        result = 31 * result + (flashback != null ? flashback.hashCode() : 0);\n        return result;\n    }\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n\n    public OracleSelectTableReference clone() {\n        OracleSelectTableReference x = new OracleSelectTableReference();\n        cloneTo(x);\n\n        x.only = only;\n\n        if (pivot != null) {\n            x.setPivot(pivot.clone());\n        }\n\n        if (unpivot != null) {\n            x.setUnpivot(unpivot.clone());\n        }\n\n        if (partition != null) {\n            x.setPartition(partition.clone());\n        }\n\n        if (sampleClause != null) {\n            x.setSampleClause(sampleClause.clone());\n        }\n\n        if (flashback != null) {\n            setFlashback(flashback.clone());\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSelectTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\n\npublic interface OracleSelectTableSource extends SQLTableSource {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSetTransactionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleSetTransactionStatement extends OracleStatementImpl implements OracleStatement {\n    private boolean readOnly;\n    private boolean write;\n\n    private SQLExpr name;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        this.name = name;\n    }\n\n    public boolean isReadOnly() {\n        return readOnly;\n    }\n\n    public void setReadOnly(boolean readOnly) {\n        this.readOnly = readOnly;\n    }\n\n    public boolean isWrite() {\n        return write;\n    }\n\n    public void setWrite(boolean write) {\n        this.write = write;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\n\npublic interface OracleStatement extends SQLStatement, OracleSQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleStatementImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class OracleStatementImpl extends SQLStatementImpl implements OracleStatement {\n    public OracleStatementImpl() {\n        super(DbType.oracle);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    public abstract void accept0(OracleASTVisitor visitor);\n\n    public String toString() {\n        return SQLUtils.toOracleString(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSupplementalIdKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\n/**\n * Created by wenshao on 20/05/2017.\n */\npublic class OracleSupplementalIdKey extends OracleSQLObjectImpl implements SQLTableElement {\n    private boolean all;\n    private boolean primaryKey;\n    private boolean unique;\n    private boolean uniqueIndex;\n    private boolean foreignKey;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public boolean isAll() {\n        return all;\n    }\n\n    public void setAll(boolean all) {\n        this.all = all;\n    }\n\n    public boolean isPrimaryKey() {\n        return primaryKey;\n    }\n\n    public void setPrimaryKey(boolean primaryKey) {\n        this.primaryKey = primaryKey;\n    }\n\n    public boolean isUnique() {\n        return unique;\n    }\n\n    public void setUnique(boolean unique) {\n        this.unique = unique;\n    }\n\n    public boolean isForeignKey() {\n        return foreignKey;\n    }\n\n    public void setForeignKey(boolean foreignKey) {\n        this.foreignKey = foreignKey;\n    }\n\n    public boolean isUniqueIndex() {\n        return uniqueIndex;\n    }\n\n    public void setUniqueIndex(boolean uniqueIndex) {\n        this.uniqueIndex = uniqueIndex;\n    }\n\n    public OracleSupplementalIdKey clone() {\n        OracleSupplementalIdKey x = new OracleSupplementalIdKey();\n        x.all = all;\n        x.primaryKey = primaryKey;\n        x.unique = unique;\n        x.uniqueIndex = uniqueIndex;\n        x.foreignKey = foreignKey;\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleSupplementalLogGrp.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wenshao on 20/05/2017.\n */\npublic class OracleSupplementalLogGrp extends OracleSQLObjectImpl implements SQLTableElement {\n    private SQLName group;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n    private boolean always;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, group);\n            acceptChild(visitor, columns);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getGroup() {\n        return group;\n    }\n\n    public void setGroup(SQLName group) {\n        if (group != null) {\n            group.setParent(this);\n        }\n        this.group = group;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLName column) {\n        if (column != null) {\n            column.setParent(this);\n        }\n        this.columns.add(column);\n    }\n\n    public boolean isAlways() {\n        return always;\n    }\n\n    public void setAlways(boolean always) {\n        this.always = always;\n    }\n\n    public OracleSupplementalLogGrp clone() {\n        OracleSupplementalLogGrp x = new OracleSupplementalLogGrp();\n        if (group != null) {\n            x.setGroup(group.clone());\n        }\n        for (SQLName column : columns) {\n            SQLName c2 = column.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n        x.always = always;\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUnique.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLUnique;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OracleUnique extends SQLUnique implements OracleConstraint, OracleSQLObject {\n    private OracleUsingIndexClause using;\n    private SQLName exceptionsInto;\n    private Initially initially;\n    private Boolean deferrable;\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) visitor);\n            return;\n        }\n\n        super.accept(visitor);\n    }\n\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n            acceptChild(visitor, this.getColumns());\n            acceptChild(visitor, using);\n            acceptChild(visitor, exceptionsInto);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getDeferrable() {\n        return deferrable;\n    }\n\n    public void setDeferrable(Boolean deferrable) {\n        this.deferrable = deferrable;\n    }\n\n    public SQLName getExceptionsInto() {\n        return exceptionsInto;\n    }\n\n    public void setExceptionsInto(SQLName exceptionsInto) {\n        this.exceptionsInto = exceptionsInto;\n    }\n\n    public OracleUsingIndexClause getUsing() {\n        return using;\n    }\n\n    public void setUsing(OracleUsingIndexClause using) {\n        if (using != null) {\n            using.setParent(this);\n        }\n        this.using = using;\n    }\n\n    public Initially getInitially() {\n        return initially;\n    }\n\n    public void setInitially(Initially initially) {\n        this.initially = initially;\n    }\n\n    public void cloneTo(OracleUnique x) {\n        super.cloneTo(x);\n        if (using != null) {\n            x.setUsing(using.clone());\n        }\n        if (exceptionsInto != null) {\n            x.setExceptionsInto(exceptionsInto.clone());\n        }\n        x.initially = initially;\n        x.deferrable = deferrable;\n    }\n\n    public OracleUnique clone() {\n        OracleUnique x = new OracleUnique();\n        cloneTo(x);\n        return x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUpdateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleUpdateStatement extends SQLUpdateStatement implements OracleStatement, SQLReplaceable {\n    private List<SQLHint> hints = new ArrayList<SQLHint>(1);\n    private boolean only;\n    private String alias;\n\n    private final List<SQLExpr> returningInto = new ArrayList<SQLExpr>();\n\n    public OracleUpdateStatement() {\n        super(DbType.oracle);\n    }\n\n    public List<SQLExpr> getReturningInto() {\n        return returningInto;\n    }\n\n    public void addReturningInto(SQLExpr returningInto) {\n        if (returningInto == null) {\n            return;\n        }\n        returningInto.setParent(this);\n        this.returningInto.add(returningInto);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OracleASTVisitor) {\n            accept0((OracleASTVisitor) visitor);\n            return;\n        }\n\n        super.accept(visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.hints);\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, items);\n            acceptChild(visitor, where);\n            acceptChild(visitor, returning);\n            acceptChild(visitor, returningInto);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        boolean replace = super.replace(expr, target);\n        if (replace) {\n            return true;\n        }\n\n        for (int i = returningInto.size() - 1; i >= 0; i--) {\n            if (returningInto.get(i) == expr) {\n                target.setParent(this);\n                returningInto.set(i, target);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public String getAlias() {\n        return this.alias;\n    }\n\n    public void setAlias(String alias) {\n        this.alias = alias;\n    }\n\n    public boolean isOnly() {\n        return this.only;\n    }\n\n    public void setOnly(boolean only) {\n        this.only = only;\n    }\n\n    public int getHintsSize() {\n        if (hints == null) {\n            return 0;\n        }\n\n        return hints.size();\n    }\n\n    public List<SQLHint> getHints() {\n        if (hints == null) {\n            hints = new ArrayList<SQLHint>(2);\n        }\n        return hints;\n    }\n\n    public void setHints(List<SQLHint> hints) {\n        this.hints = hints;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n\n        OracleUpdateStatement that = (OracleUpdateStatement) o;\n\n        if (with != null ? !with.equals(that.getWith()) : that.getWith() != null) {\n            return false;\n        }\n        if (!items.equals(that.getItems())) {\n            return false;\n        }\n        if (where != null ? !where.equals(that.getWhere()) : that.getWhere() != null) {\n            return false;\n        }\n        if (from != null ? !from.equals(that.getFrom()) : that.getFrom() != null) {\n            return false;\n        }\n        if (hints != null ? !hints.equals(that.hints) : that.hints != null) {\n            return false;\n        }\n        if (tableSource != null ? !tableSource.equals(that.tableSource) : that.tableSource != null) {\n            return false;\n        }\n        if (returning != null ? !returning.equals(that.returning) : that.returning != null) {\n            return false;\n        }\n        return orderBy != null ? orderBy.equals(that.orderBy) : that.orderBy == null;\n    }\n\n    @Override\n    public int hashCode() {\n        int result = with != null ? with.hashCode() : 0;\n        result = 31 * result + items.hashCode();\n        result = 31 * result + (where != null ? where.hashCode() : 0);\n        result = 31 * result + (from != null ? from.hashCode() : 0);\n        result = 31 * result + (tableSource != null ? tableSource.hashCode() : 0);\n        result = 31 * result + (returning != null ? returning.hashCode() : 0);\n        result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);\n        result = 31 * result + (hints != null ? hints.hashCode() : 0);\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleUsingIndexClause.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OraclePartitionSingle;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObject;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributesImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleUsingIndexClause extends OracleSegmentAttributesImpl implements OracleSQLObject {\n    private SQLObject index;\n    private Boolean enable;\n\n    private boolean computeStatistics;\n    private boolean reverse;\n\n    private List<OraclePartitionSingle> localPartitionIndex = new ArrayList<>();\n\n    public OracleUsingIndexClause() {\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OracleASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, index);\n            acceptChild(visitor, tablespace);\n            acceptChild(visitor, storage);\n        }\n        visitor.endVisit(this);\n    }\n\n    public Boolean getEnable() {\n        return enable;\n    }\n\n    public void setEnable(Boolean enable) {\n        this.enable = enable;\n    }\n\n    public boolean isComputeStatistics() {\n        return computeStatistics;\n    }\n\n    public void setComputeStatistics(boolean computeStatistics) {\n        this.computeStatistics = computeStatistics;\n    }\n\n    public SQLObject getIndex() {\n        return index;\n    }\n\n    public void setIndex(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.index = x;\n    }\n\n    public void setIndex(SQLCreateIndexStatement x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.index = x;\n    }\n\n    public boolean isReverse() {\n        return reverse;\n    }\n\n    public void setReverse(boolean reverse) {\n        this.reverse = reverse;\n    }\n\n    public List<OraclePartitionSingle> getLocalPartitionIndex() {\n        return localPartitionIndex;\n    }\n\n    public void cloneTo(OracleUsingIndexClause x) {\n        super.cloneTo(x);\n        if (index != null) {\n            SQLObject idx = index.clone();\n            idx.setParent(x);\n            x.index = idx;\n        }\n        x.enable = enable;\n        x.computeStatistics = computeStatistics;\n        x.reverse = reverse;\n\n        for (OraclePartitionSingle p : localPartitionIndex) {\n            OraclePartitionSingle p2 = p.clone();\n            p2.setParent(x);\n            x.localPartitionIndex.add(p2);\n        }\n    }\n\n    public OracleUsingIndexClause clone() {\n        OracleUsingIndexClause x = new OracleUsingIndexClause();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleXmlColumnProperties.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\n\npublic class OracleXmlColumnProperties extends OracleSQLObjectImpl {\n    private SQLName column;\n    private OracleXMLTypeStorage storage;\n\n    private Boolean allowNonSchema;\n    private Boolean allowAnySchema;\n\n    @Override\n    public void accept0(OracleASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, storage);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getColumn() {\n        return column;\n    }\n\n    public void setColumn(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.column = x;\n    }\n\n    public OracleXMLTypeStorage getStorage() {\n        return storage;\n    }\n\n    public void setStorage(OracleXMLTypeStorage x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.storage = x;\n    }\n\n    public Boolean getAllowNonSchema() {\n        return allowNonSchema;\n    }\n\n    public void setAllowNonSchema(Boolean allowNonSchema) {\n        this.allowNonSchema = allowNonSchema;\n    }\n\n    public Boolean getAllowAnySchema() {\n        return allowAnySchema;\n    }\n\n    public void setAllowAnySchema(Boolean allowAnySchema) {\n        this.allowAnySchema = allowAnySchema;\n    }\n\n    public static class OracleXMLTypeStorage extends OracleSQLObjectImpl {\n        private boolean secureFile;\n        private boolean basicFile;\n\n        private boolean clob;\n        private boolean binaryXml;\n\n        private OracleLobParameters lobParameters;\n\n        @Override\n        public void accept0(OracleASTVisitor visitor) {\n        }\n\n        public boolean isSecureFile() {\n            return secureFile;\n        }\n\n        public void setSecureFile(boolean secureFile) {\n            this.secureFile = secureFile;\n        }\n\n        public boolean isBasicFile() {\n            return basicFile;\n        }\n\n        public void setBasicFile(boolean basicFile) {\n            this.basicFile = basicFile;\n        }\n\n        public boolean isClob() {\n            return clob;\n        }\n\n        public void setClob(boolean clob) {\n            this.clob = clob;\n        }\n\n        public boolean isBinaryXml() {\n            return binaryXml;\n        }\n\n        public void setBinaryXml(boolean binaryXml) {\n            this.binaryXml = binaryXml;\n        }\n\n        public OracleLobParameters getLobParameters() {\n            return lobParameters;\n        }\n\n        public void setLobParameters(OracleLobParameters x) {\n            if (x != null) {\n                x.setParent(this);\n            }\n            this.lobParameters = x;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleCreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OraclePartitionSingle;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement.DeferredSegmentCreation;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class OracleCreateTableParser extends SQLCreateTableParser {\n    public OracleCreateTableParser(Lexer lexer) {\n        super(new OracleExprParser(lexer));\n    }\n\n    public OracleCreateTableParser(String sql) {\n        super(new OracleExprParser(sql));\n    }\n\n    protected OracleCreateTableStatement newCreateStatement() {\n        return new OracleCreateTableStatement();\n    }\n\n    public OracleCreateTableStatement parseCreateTable() {\n        OracleCreateTableStatement stmt = (OracleCreateTableStatement) super.parseCreateTable();\n\n        if (lexer.token() == Token.OF) {\n            lexer.nextToken();\n            stmt.setOf(this.exprParser.name());\n\n            if (lexer.identifierEquals(\"OIDINDEX\")) {\n                lexer.nextToken();\n\n                OracleCreateTableStatement.OIDIndex oidIndex = new OracleCreateTableStatement.OIDIndex();\n\n                if (lexer.token() != Token.LPAREN) {\n                    oidIndex.setName(this.exprParser.name());\n                }\n                accept(Token.LPAREN);\n                this.getExprParser().parseSegmentAttributes(oidIndex);\n                accept(Token.RPAREN);\n\n                stmt.setOidIndex(oidIndex);\n            }\n        }\n\n        for (; ; ) {\n            this.getExprParser().parseSegmentAttributes(stmt);\n\n            if (lexer.identifierEquals(FnvHash.Constants.IN_MEMORY_METADATA)) {\n                lexer.nextToken();\n                stmt.setInMemoryMetadata(true);\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.CURSOR_SPECIFIC_SEGMENT)) {\n                lexer.nextToken();\n                stmt.setCursorSpecificSegment(true);\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.NOPARALLEL)) {\n                lexer.nextToken();\n                stmt.setParallel(false);\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.PARALLEL)) {\n                lexer.nextToken();\n                stmt.setParallel(true);\n\n                if (lexer.token() == Token.LITERAL_INT) {\n                    stmt.setParallelValue(this.exprParser.primary());\n                }\n                continue;\n            } else if (lexer.token() == Token.CACHE) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.TRUE);\n                continue;\n            } else if (lexer.token() == Token.NOCACHE) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                if (lexer.token() == Token.ROW) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"MOVEMENT\");\n                    stmt.setEnableRowMovement(Boolean.TRUE);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n                //stmt.setEnable(Boolean.TRUE);\n                continue;\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                if (lexer.token() == Token.ROW) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"MOVEMENT\");\n                    stmt.setEnableRowMovement(Boolean.FALSE);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n                //stmt.setEnable(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                accept(Token.COMMIT);\n\n                if (lexer.identifierEquals(\"PRESERVE\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"ROWS\");\n                    stmt.setOnCommitPreserveRows(true);\n                } else {\n                    accept(Token.DELETE);\n                    acceptIdentifier(\"ROWS\");\n                    stmt.setOnCommitDeleteRows(true);\n                }\n                continue;\n            } else if (lexer.identifierEquals(\"STORAGE\")) {\n                OracleStorageClause storage = ((OracleExprParser) this.exprParser).parseStorage();\n                stmt.setStorage(storage);\n                continue;\n            } else if (lexer.identifierEquals(\"ORGANIZATION\")) {\n                parseOrganization(stmt);\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.CLUSTER)) {\n                lexer.nextToken();\n                SQLName cluster = this.exprParser.name();\n                stmt.setCluster(cluster);\n                accept(Token.LPAREN);\n                this.exprParser.names(stmt.getClusterColumns(), cluster);\n                accept(Token.RPAREN);\n                continue;\n//            } else if (lexer.token() == Token.STORAGE) {\n//                OracleStorageClause storage = ((OracleExprParser) this.exprParser).parseStorage();\n//                stmt.setStorage(storage);\n//                continue;\n            } else if (lexer.identifierEquals(\"MONITORING\")) {\n                lexer.nextToken();\n                stmt.setMonitoring(true);\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.INCLUDING)) {\n                lexer.nextToken();\n                this.exprParser.names(stmt.getIncluding(), stmt);\n                acceptIdentifier(\"OVERFLOW\");\n                continue;\n            } else if (lexer.token() == Token.LOB) {\n                OracleLobStorageClause lobStorage = ((OracleExprParser) this.exprParser).parseLobStorage();\n                stmt.setLobStorage(lobStorage);\n                continue;\n            } else if (lexer.token() == Token.SEGMENT) {\n                lexer.nextToken();\n                accept(Token.CREATION);\n                if (lexer.token() == Token.IMMEDIATE) {\n                    lexer.nextToken();\n                    stmt.setDeferredSegmentCreation(DeferredSegmentCreation.IMMEDIATE);\n                } else {\n                    accept(Token.DEFERRED);\n                    stmt.setDeferredSegmentCreation(DeferredSegmentCreation.DEFERRED);\n                }\n                continue;\n            } else if (lexer.token() == Token.COLUMN) {\n                lexer.nextToken();\n                SQLName name = this.exprParser.name();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.SUBSTITUTABLE)) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"AT\");\n                    accept(Token.ALL);\n                    acceptIdentifier(\"LEVELS\");\n                }\n                // skip\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.VARRAY)) {\n                lexer.nextToken();\n                SQLName name = this.exprParser.name();\n\n                accept(Token.STORE);\n                accept(Token.AS);\n                if (lexer.identifierEquals(FnvHash.Constants.BASICFILE)) {\n                    lexer.nextToken();\n                }\n                this.getExprParser().parseLobStorage();\n                throw new ParserException(\"TODO : \" + lexer.info());\n            } else if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n\n                accept(Token.BY);\n\n                if (lexer.identifierEquals(\"RANGE\")) {\n                    SQLPartitionByRange partitionByRange = this.getExprParser().partitionByRange();\n                    this.getExprParser().partitionClauseRest(partitionByRange);\n                    stmt.setPartitionBy(partitionByRange);\n                    continue;\n                } else if (lexer.identifierEquals(\"HASH\")) {\n                    SQLPartitionByHash partitionByHash = this.getExprParser().partitionByHash();\n                    this.getExprParser().partitionClauseRest(partitionByHash);\n\n                    if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        for (; ; ) {\n                            OraclePartitionSingle partition = this.getExprParser().parsePartition();\n                            partitionByHash.addPartition(partition);\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            } else if (lexer.token() == Token.RPAREN) {\n                                lexer.nextToken();\n                                break;\n                            }\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        }\n                    }\n                    stmt.setPartitionBy(partitionByHash);\n                    continue;\n                } else if (lexer.identifierEquals(\"LIST\")) {\n                    SQLPartitionByList partitionByList = partitionByList();\n                    this.getExprParser().partitionClauseRest(partitionByList);\n                    stmt.setPartitionBy(partitionByList);\n                    continue;\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.XMLTYPE)) {\n                lexer.nextToken();\n                if (lexer.token() == Token.COLUMN) {\n                    lexer.nextToken();\n                }\n\n                OracleXmlColumnProperties xmlColumnProperties = new OracleXmlColumnProperties();\n                xmlColumnProperties.setColumn(this.exprParser.name());\n\n                if (lexer.token() == Token.STORE) {\n                    lexer.nextToken();\n                    accept(Token.AS);\n\n                    OracleXmlColumnProperties.OracleXMLTypeStorage storage = new OracleXmlColumnProperties.OracleXMLTypeStorage();\n                    if (lexer.identifierEquals(\"SECUREFILE\")) {\n                        storage.setSecureFile(true);\n                        lexer.nextToken();\n                    } else if (lexer.identifierEquals(\"BASICFILE\")) {\n                        storage.setBasicFile(true);\n                        lexer.nextToken();\n                    }\n\n                    if (lexer.identifierEquals(\"BINARY\")) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"XML\");\n                        storage.setBinaryXml(true);\n                    } else if (lexer.identifierEquals(\"CLOB\")) {\n                        lexer.nextToken();\n                        storage.setClob(true);\n                    }\n\n                    if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n\n                        OracleLobParameters lobParameters = new OracleLobParameters();\n\n                        for_:\n                        for (; ; ) {\n                            switch (lexer.token()) {\n                                case TABLESPACE: {\n                                    lexer.nextToken();\n                                    SQLName tableSpace = this.exprParser.name();\n                                    lobParameters.setTableSpace(tableSpace);\n                                }\n                                continue for_;\n                                case ENABLE:\n                                case DISABLE: {\n                                    Boolean enable = lexer.token() == Token.ENABLE;\n                                    lexer.nextToken();\n                                    accept(Token.STORAGE);\n                                    accept(Token.IN);\n                                    accept(Token.ROW);\n\n                                    lobParameters.setEnableStorageInRow(enable);\n                                }\n                                continue for_;\n                                case CHUNK:\n                                    lexer.nextToken();\n                                    SQLExpr chunk = this.exprParser.expr();\n                                    lobParameters.setChunk(chunk);\n                                    continue for_;\n                                case NOCACHE:\n                                    lexer.nextToken();\n                                    lobParameters.setCache(false);\n                                    continue for_;\n                                case LOGGING:\n                                    lexer.nextToken();\n                                    lobParameters.setLogging(true);\n                                    continue for_;\n                                case NOCOMPRESS:\n                                    lexer.nextToken();\n                                    lobParameters.setCompress(false);\n                                    continue for_;\n                                case KEEP_DUPLICATES:\n                                    lexer.nextToken();\n                                    lobParameters.setKeepDuplicates(true);\n                                    continue for_;\n                                case STORAGE:\n                                    OracleStorageClause storageClause = this.getExprParser().parseStorage();\n                                    lobParameters.setStorage(storageClause);\n                                    continue for_;\n                                case IDENTIFIER:\n                                    long hash = lexer.hashLCase();\n                                    if (hash == FnvHash.Constants.PCTVERSION) {\n                                        lobParameters.setPctVersion(this.exprParser.primary());\n                                        lexer.nextToken();\n                                        continue for_;\n                                    }\n                                    break for_;\n                                default:\n                                    break for_;\n                            }\n                        }\n\n                        accept(Token.RPAREN);\n\n                        storage.setLobParameters(lobParameters);\n                    }\n                }\n\n                for (; ; ) {\n                    if (lexer.identifierEquals(FnvHash.Constants.ALLOW)) {\n                        lexer.nextToken();\n                        if (lexer.identifierEquals(\"NONSCHEMA\")) {\n                            lexer.nextToken();\n                            xmlColumnProperties.setAllowNonSchema(true);\n                        } else if (lexer.identifierEquals(\"ANYSCHEMA\")) {\n                            lexer.nextToken();\n                            xmlColumnProperties.setAllowAnySchema(true);\n                        } else {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        }\n                        continue;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.DISALLOW)) {\n                        lexer.nextToken();\n                        if (lexer.identifierEquals(\"NONSCHEMA\")) {\n                            lexer.nextToken();\n                            xmlColumnProperties.setAllowNonSchema(false);\n                        } else if (lexer.identifierEquals(\"ANYSCHEMA\")) {\n                            lexer.nextToken();\n                            xmlColumnProperties.setAllowAnySchema(false);\n                        } else {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        }\n                        continue;\n                    }\n                    break;\n                }\n\n//                throw new ParserException(\"TODO : \" + lexer.info());\n\n                stmt.setXmlTypeColumnProperties(xmlColumnProperties);\n                continue;\n            }\n\n            break;\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n\n            SQLSelect select = new OracleSelectParser(exprParser).select();\n            stmt.setSelect(select);\n        }\n\n        return stmt;\n    }\n\n    private void parseOrganization(OracleCreateTableStatement stmt) {\n        OracleCreateTableStatement.Organization organization = new OracleCreateTableStatement.Organization();\n        acceptIdentifier(\"ORGANIZATION\");\n        if (lexer.token() == Token.INDEX) {\n            lexer.nextToken();\n            organization.setType(\"INDEX\");\n            this.getExprParser().parseSegmentAttributes(organization);\n\n            // index_org_table_clause http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7002.htm#i2129638\n            if (lexer.identifierEquals(FnvHash.Constants.PCTTHRESHOLD)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LITERAL_INT) {\n                    int pctthreshold = ((SQLNumericLiteralExpr) this.exprParser.primary()).getNumber().intValue();\n                    organization.setPctthreshold(pctthreshold);\n                }\n            }\n        } else if (lexer.identifierEquals(\"HEAP\")) {\n            lexer.nextToken();\n            organization.setType(\"HEAP\");\n            this.getExprParser().parseSegmentAttributes(organization);\n        } else if (lexer.identifierEquals(\"EXTERNAL\")) {\n            lexer.nextToken();\n            organization.setType(\"EXTERNAL\");\n            accept(Token.LPAREN);\n\n            if (lexer.identifierEquals(\"TYPE\")) {\n                lexer.nextToken();\n                organization.setExternalType(this.exprParser.name());\n            }\n\n            accept(Token.DEFAULT);\n            acceptIdentifier(\"DIRECTORY\");\n\n            organization.setExternalDirectory(this.exprParser.expr());\n\n            if (lexer.identifierEquals(\"ACCESS\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"PARAMETERS\");\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    SQLExternalRecordFormat recordFormat = new SQLExternalRecordFormat();\n\n                    if (lexer.identifierEquals(\"RECORDS\")) {\n                        lexer.nextToken();\n\n                        if (lexer.identifierEquals(\"DELIMITED\")) {\n                            lexer.nextToken();\n                            accept(Token.BY);\n\n                            if (lexer.identifierEquals(\"NEWLINE\")) {\n                                lexer.nextToken();\n                                recordFormat.setDelimitedBy(new SQLIdentifierExpr(\"NEWLINE\"));\n                            } else {\n                                throw new ParserException(\"TODO \" + lexer.info());\n                            }\n\n                            if (lexer.identifierEquals(FnvHash.Constants.NOLOGFILE)) {\n                                lexer.nextToken();\n                                recordFormat.setLogfile(false);\n                            }\n\n                            if (lexer.identifierEquals(FnvHash.Constants.NOBADFILE)) {\n                                lexer.nextToken();\n                                recordFormat.setBadfile(false);\n                            }\n                        } else {\n                            throw new ParserException(\"TODO \" + lexer.info());\n                        }\n                    }\n\n                    if (lexer.identifierEquals(FnvHash.Constants.FIELDS)) {\n                        lexer.nextToken();\n\n                        if (lexer.identifierEquals(FnvHash.Constants.TERMINATED)) {\n                            lexer.nextToken();\n                            accept(Token.BY);\n                            recordFormat.setTerminatedBy(this.exprParser.primary());\n                        } else {\n                            throw new ParserException(\"TODO \" + lexer.info());\n                        }\n\n                        if (lexer.identifierEquals(FnvHash.Constants.LTRIM)) {\n                            lexer.nextToken();\n                            recordFormat.setLtrim(true);\n                        }\n                    }\n\n                    if (lexer.identifierEquals(FnvHash.Constants.MISSING)) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"FIELD\");\n                        accept(Token.VALUES);\n                        acceptIdentifier(\"ARE\");\n                        accept(Token.NULL);\n                        recordFormat.setMissingFieldValuesAreNull(true);\n                    }\n\n                    if (lexer.token() == Token.REJECT) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"ROWS\");\n                        accept(Token.WITH);\n                        accept(Token.ALL);\n                        accept(Token.NULL);\n                        acceptIdentifier(\"FIELDS\");\n                        recordFormat.setRejectRowsWithAllNullFields(true);\n                    }\n\n                    organization.setExternalDirectoryRecordFormat(recordFormat);\n                    accept(Token.RPAREN);\n                } else if (lexer.token() == Token.USING) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"CLOB\");\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n            }\n\n            acceptIdentifier(\"LOCATION\");\n            accept(Token.LPAREN);\n            this.exprParser.exprList(organization.getExternalDirectoryLocation(), organization);\n            accept(Token.RPAREN);\n\n            accept(Token.RPAREN);\n\n            if (lexer.token() == Token.REJECT) {\n                lexer.nextToken();\n                accept(Token.LIMIT);\n\n                organization.setExternalRejectLimit(this.exprParser.primary());\n            }\n            //\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n        stmt.setOrganization(organization);\n    }\n\n    protected SQLPartitionByList partitionByList() {\n        acceptIdentifier(\"LIST\");\n        SQLPartitionByList partitionByList = new SQLPartitionByList();\n\n        accept(Token.LPAREN);\n        partitionByList.addColumn(this.exprParser.expr());\n        accept(Token.RPAREN);\n\n        this.getExprParser().parsePartitionByRest(partitionByList);\n\n        return partitionByList;\n    }\n\n    protected SQLTableElement parseCreateTableSupplementalLoggingProps() {\n        acceptIdentifier(\"SUPPLEMENTAL\");\n        acceptIdentifier(\"LOG\");\n\n        if (lexer.token() == Token.GROUP) {\n            lexer.nextToken();\n\n            OracleSupplementalLogGrp logGrp = new OracleSupplementalLogGrp();\n            logGrp.setGroup(this.exprParser.name());\n\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLName column = this.exprParser.name();\n\n                if (lexer.identifierEquals(\"NO\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"LOG\");\n                    column.putAttribute(\"NO LOG\", Boolean.TRUE);\n                }\n\n                logGrp.addColumn(column);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                if (lexer.token() == Token.RPAREN) {\n                    break;\n                }\n\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(\"ALWAYS\")) {\n                lexer.nextToken();\n                logGrp.setAlways(true);\n            }\n\n            return logGrp;\n        } else if (lexer.identifierEquals(FnvHash.Constants.DATA)) {\n            lexer.nextToken();\n\n            OracleSupplementalIdKey idKey = new OracleSupplementalIdKey();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                if (lexer.token() == Token.ALL) {\n                    lexer.nextToken();\n                    idKey.setAll(true);\n                } else if (lexer.token() == Token.PRIMARY) {\n                    lexer.nextToken();\n                    accept(Token.KEY);\n                    idKey.setPrimaryKey(true);\n                } else if (lexer.token() == Token.UNIQUE) {\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.INDEX) {\n                        lexer.nextToken();\n                        idKey.setUniqueIndex(true);\n                    } else {\n                        idKey.setUnique(true);\n                    }\n                } else if (lexer.token() == Token.FOREIGN) {\n                    lexer.nextToken();\n                    accept(Token.KEY);\n                    idKey.setForeignKey(true);\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                if (lexer.token() == Token.RPAREN) {\n                    break;\n                }\n\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n            accept(Token.RPAREN);\n            acceptIdentifier(\"COLUMNS\");\n\n            return idKey;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    @Override\n    public OracleExprParser getExprParser() {\n        return (OracleExprParser) exprParser;\n    }\n\n    @Override\n    protected SQLSelect createTableQueryRest() {\n        return new OracleSelectParser(this.exprParser).select();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.SQLKeep.DenseRank;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OraclePartitionSingle;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause.FlashCacheType;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraint.Initially;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.math.BigInteger;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class OracleExprParser extends SQLExprParser {\n    public boolean allowStringAdditive;\n\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"AVG\",\n                \"CORR\",\n                \"COVAR_POP\",\n                \"COVAR_SAMP\",\n                \"COUNT\",\n                \"CUME_DIST\",\n                \"DENSE_RANK\",\n                \"FIRST\",\n                \"FIRST_VALUE\",\n                \"LAG\",\n                \"LAST\",\n                \"LAST_VALUE\",\n                \"LISTAGG\",\n                \"LEAD\",\n                \"MAX\",  //\n                \"MIN\",\n                \"NTILE\",\n                \"PERCENT_RANK\",  //\n                \"PERCENTILE_CONT\",  //\n                \"PERCENTILE_DISC\",  //\n                \"RANK\",\n                \"RATIO_TO_REPORT\",\n                \"REGR_SLOPE\",\n                \"REGR_INTERCEPT\",  //\n                \"REGR_COUNT\",  //\n                \"REGR_R2\",\n                \"REGR_AVGX\",  //\n                \"REGR_AVGY\",  //\n                \"REGR_SXX\",  //\n                \"REGR_SYY\",  //\n                \"REGR_SXY\",\n                \"ROW_NUMBER\",  //\n                \"STDDEV\",  //\n                \"STDDEV_POP\",  //\n                \"STDDEV_SAMP\",\n                \"SUM\",\n                \"VAR_POP\",\n                \"VAR_SAMP\",\n                \"VARIANCE\",\n                \"WM_CONCAT\"\n        };\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public OracleExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n        this.dbType = DbType.oracle;\n    }\n\n    public OracleExprParser(String text) {\n        this(new OracleLexer(text));\n        this.lexer.nextToken();\n        this.dbType = DbType.oracle;\n    }\n\n    public OracleExprParser(String text, SQLParserFeature... features) {\n        this(new OracleLexer(text, features));\n        this.lexer.nextToken();\n        this.dbType = DbType.oracle;\n    }\n\n    protected boolean isCharType(long hash) {\n        return hash == FnvHash.Constants.CHAR\n                || hash == FnvHash.Constants.CHARACTER\n                || hash == FnvHash.Constants.NCHAR\n                || hash == FnvHash.Constants.VARCHAR\n                || hash == FnvHash.Constants.VARCHAR2\n                || hash == FnvHash.Constants.NVARCHAR\n                || hash == FnvHash.Constants.NVARCHAR2;\n    }\n\n    public SQLDataType parseDataType(boolean restrict) {\n        lexer.computeRowAndColumn();\n        int sourceLine = lexer.getLine(), sourceColumn = lexer.getPosColumn();\n\n        if (lexer.token() == Token.CONSTRAINT || lexer.token() == Token.COMMA) {\n            return null;\n        }\n\n        if (lexer.token() == Token.DEFAULT || lexer.token() == Token.NOT || lexer.token() == Token.NULL) {\n            return null;\n        }\n\n        if (lexer.token() == Token.INTERVAL) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"YEAR\")) {\n                lexer.nextToken();\n                OracleDataTypeIntervalYear interval = new OracleDataTypeIntervalYear();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    interval.addArgument(this.expr());\n                    accept(Token.RPAREN);\n                }\n\n                accept(Token.TO);\n                acceptIdentifier(\"MONTH\");\n\n                return interval;\n            } else {\n                acceptIdentifier(\"DAY\");\n                OracleDataTypeIntervalDay interval = new OracleDataTypeIntervalDay();\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    interval.addArgument(this.expr());\n                    accept(Token.RPAREN);\n                }\n\n                accept(Token.TO);\n                acceptIdentifier(\"SECOND\");\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    interval.getFractionalSeconds().add(this.expr());\n                    accept(Token.RPAREN);\n                }\n\n                return interval;\n            }\n        }\n\n        StringBuilder typeName = new StringBuilder();\n        if (lexer.token() == Token.EXCEPTION) {\n            typeName.append(\"EXCEPTION\");\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.LONG)) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.RAW)) {\n                lexer.nextToken();\n                typeName.append(\"LONG RAW\");\n            } else {\n                typeName.append(\"LONG\");\n            }\n        } else {\n            SQLName typeExpr = name();\n            typeName.append(typeExpr.toString());\n        }\n\n        String typeNameStr = typeName.toString();\n        if (\"TIMESTAMP\".equalsIgnoreCase(typeNameStr)) {\n            SQLDataTypeImpl timestamp = new SQLDataTypeImpl(typeNameStr);\n            timestamp.setDbType(dbType);\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                timestamp.addArgument(this.expr());\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"LOCAL\")) {\n                    lexer.nextToken();\n                    timestamp.setWithLocalTimeZone(true);\n                }\n\n                timestamp.setWithTimeZone(true);\n\n                acceptIdentifier(\"TIME\");\n                acceptIdentifier(\"ZONE\");\n            }\n\n            return timestamp;\n        }\n\n        if (\"national\".equalsIgnoreCase(typeName.toString())\n                && isCharType(lexer.hashLCase())) {\n            typeName.append(' ').append(lexer.stringVal());\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"VARYING\")) {\n                typeName.append(' ').append(lexer.stringVal());\n                lexer.nextToken();\n            }\n\n            SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                SQLExpr arg = this.expr();\n                arg.setParent(charType);\n                charType.addArgument(arg);\n                accept(Token.RPAREN);\n            }\n\n            charType = (SQLCharacterDataType) parseCharTypeRest(charType);\n\n            if (lexer.token() == Token.HINT) {\n                List<SQLCommentHint> hints = this.parseHints();\n                charType.setHints(hints);\n            }\n\n            return charType;\n        }\n\n        if (isCharType(typeName.toString())) {\n            if (lexer.identifierEquals(\"VARYING\")) {\n                typeName.append(' ').append(lexer.stringVal());\n                lexer.nextToken();\n            }\n\n            SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n\n                charType.addArgument(this.expr());\n\n                if (lexer.identifierEquals(\"CHAR\")) {\n                    lexer.nextToken();\n                    charType.setCharType(SQLCharacterDataType.CHAR_TYPE_CHAR);\n                } else if (lexer.identifierEquals(\"BYTE\")) {\n                    lexer.nextToken();\n                    charType.setCharType(SQLCharacterDataType.CHAR_TYPE_BYTE);\n                }\n\n                accept(Token.RPAREN);\n            } else if (lexer.token() == Token.COMMA) {\n                return parseCharTypeRest(charType);\n            } else if (restrict) {\n                accept(Token.LPAREN);\n            }\n\n            return parseCharTypeRest(charType);\n        }\n\n        if (lexer.token() == Token.PERCENT) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"TYPE\")) {\n                lexer.nextToken();\n                typeName.append(\"%TYPE\");\n            } else if (lexer.identifierEquals(\"ROWTYPE\")) {\n                lexer.nextToken();\n                typeName.append(\"%ROWTYPE\");\n            } else {\n                throw new ParserException(\"syntax error : \" + lexer.info());\n            }\n        }\n\n        SQLDataTypeImpl dataType = new SQLDataTypeImpl(typeName.toString());\n        dataType.setDbType(dbType);\n        dataType.setSource(sourceLine, sourceColumn);\n\n        return parseDataTypeRest(dataType);\n    }\n\n    public SQLExpr primary() {\n        final Token tok = lexer.token();\n\n        SQLExpr sqlExpr = null;\n        switch (tok) {\n            case SYSDATE:\n                lexer.nextToken();\n                OracleSysdateExpr sysdate = new OracleSysdateExpr();\n                if (lexer.token() == Token.MONKEYS_AT) {\n                    lexer.nextToken();\n                    accept(Token.BANG);\n                    sysdate.setOption(\"!\");\n                }\n                sqlExpr = sysdate;\n                return primaryRest(sqlExpr);\n            case PRIOR:\n                lexer.nextToken();\n                sqlExpr = expr();\n                sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Prior, sqlExpr);\n                return primaryRest(sqlExpr);\n            case COLON:\n                lexer.nextToken();\n                if (lexer.token() == Token.LITERAL_INT) {\n                    String name = \":\" + lexer.numberString();\n                    lexer.nextToken();\n                    return new SQLVariantRefExpr(name);\n                } else if (lexer.token() == Token.IDENTIFIER) {\n                    String name = lexer.stringVal();\n                    if (name.charAt(0) == 'B' || name.charAt(0) == 'b') {\n                        lexer.nextToken();\n                        return new SQLVariantRefExpr(\":\" + name);\n                    }\n                    throw new ParserException(\"syntax error : \" + lexer.info());\n                } else {\n                    throw new ParserException(\"syntax error : \" + lexer.info());\n                }\n            case LITERAL_ALIAS:\n                String alias = lexer.stringVal();\n                lexer.nextToken();\n                return primaryRest(new SQLIdentifierExpr(alias));\n            case BINARY_FLOAT:\n                OracleBinaryFloatExpr floatExpr = new OracleBinaryFloatExpr();\n                floatExpr.setValue(Float.parseFloat(lexer.numberString()));\n                lexer.nextToken();\n                return primaryRest(floatExpr);\n            case BINARY_DOUBLE:\n                OracleBinaryDoubleExpr doubleExpr = new OracleBinaryDoubleExpr();\n                doubleExpr.setValue(Double.parseDouble(lexer.numberString()));\n\n                lexer.nextToken();\n                return primaryRest(doubleExpr);\n            case TABLE:\n                lexer.nextToken();\n                return primaryRest(new SQLIdentifierExpr(\"TABLE\"));\n            case PLUS:\n                lexer.nextToken();\n                switch (lexer.token()) {\n                    case LITERAL_INT:\n                        sqlExpr = new SQLIntegerExpr(lexer.integerValue());\n                        lexer.nextToken();\n                        break;\n                    case LITERAL_FLOAT:\n                        sqlExpr = lexer.numberExpr();\n                        lexer.nextToken();\n                        break;\n                    case BINARY_FLOAT:\n                        sqlExpr = new OracleBinaryFloatExpr(Float.parseFloat(lexer.numberString()));\n                        lexer.nextToken();\n                        break;\n                    case BINARY_DOUBLE:\n                        sqlExpr = new OracleBinaryDoubleExpr(Double.parseDouble(lexer.numberString()));\n                        lexer.nextToken();\n                        break;\n                    case LPAREN:\n                        lexer.nextToken();\n                        sqlExpr = expr();\n                        accept(Token.RPAREN);\n                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);\n                        break;\n                    case IDENTIFIER: {\n                        sqlExpr = expr();\n                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);\n                        break;\n                    }\n                    default:\n                        throw new ParserException(\"TODO \" + lexer.info());\n                }\n                return primaryRest(sqlExpr);\n            case SUB:\n                lexer.nextToken();\n                switch (lexer.token()) {\n                    case LITERAL_INT:\n                        Number integerValue = lexer.integerValue();\n                        if (integerValue instanceof Integer) {\n                            int intVal = ((Integer) integerValue).intValue();\n                            if (intVal == Integer.MIN_VALUE) {\n                                integerValue = Long.valueOf(((long) intVal) * -1);\n                            } else {\n                                integerValue = Integer.valueOf(intVal * -1);\n                            }\n                        } else if (integerValue instanceof Long) {\n                            long longVal = ((Long) integerValue).longValue();\n                            if (longVal == 2147483648L) {\n                                integerValue = Integer.valueOf((int) (((long) longVal) * -1));\n                            } else {\n                                integerValue = Long.valueOf(longVal * -1);\n                            }\n                        } else {\n                            integerValue = ((BigInteger) integerValue).negate();\n                        }\n                        sqlExpr = new SQLIntegerExpr(integerValue);\n                        lexer.nextToken();\n                        break;\n                    case LITERAL_FLOAT:\n                        sqlExpr = lexer.numberExpr(true);\n                        lexer.nextToken();\n                        break;\n                    case BINARY_FLOAT:\n                        sqlExpr = new OracleBinaryFloatExpr(Float.parseFloat(lexer.numberString()) * -1);\n                        lexer.nextToken();\n                        break;\n                    case BINARY_DOUBLE:\n                        sqlExpr = new OracleBinaryDoubleExpr(Double.parseDouble(lexer.numberString()) * -1);\n                        lexer.nextToken();\n                        break;\n                    case IDENTIFIER:\n                        sqlExpr = primary();\n                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);\n                        break;\n                    case VARIANT:\n                    case QUES:\n                    case LITERAL_ALIAS:\n                        sqlExpr = expr();\n                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);\n                        break;\n                    case LPAREN:\n                        lexer.nextToken();\n                        sqlExpr = expr();\n                        accept(Token.RPAREN);\n                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);\n                        break;\n                    default:\n                        throw new ParserException(\"TODO \" + lexer.info());\n                }\n                return primaryRest(sqlExpr);\n\n            case CURSOR:\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                SQLSelect select = createSelectParser().select();\n                OracleCursorExpr cursorExpr = new OracleCursorExpr(select);\n\n                accept(Token.RPAREN);\n\n                sqlExpr = cursorExpr;\n                return primaryRest(sqlExpr);\n//           case MODEL:\n            case PCTFREE:\n            case INITRANS:\n            case MAXTRANS:\n            case SEGMENT:\n            case CREATION:\n            case IMMEDIATE:\n            case DEFERRED:\n            case STORAGE:\n            case NEXT:\n            case MINEXTENTS:\n            case MAXEXTENTS:\n            case MAXSIZE:\n            case PCTINCREASE:\n            case FLASH_CACHE:\n            case CELL_FLASH_CACHE:\n            case NONE:\n            case LOB:\n            case STORE:\n            case ROW:\n            case CHUNK:\n            case CACHE:\n            case NOCACHE:\n            case LOGGING:\n            case NOCOMPRESS:\n            case KEEP_DUPLICATES:\n            case EXCEPTIONS:\n            case PURGE:\n            case OUTER:\n                sqlExpr = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n                return primaryRest(sqlExpr);\n            default:\n                return super.primary();\n        }\n    }\n\n    @Override\n    protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) {\n        if (acceptLPAREN) {\n            accept(Token.LPAREN);\n        }\n\n        if (lexer.token() == Token.PLUS) {\n            lexer.nextToken();\n            accept(Token.RPAREN);\n            return new OracleOuterExpr(expr);\n        }\n\n        if (expr instanceof SQLIdentifierExpr) {\n            String methodName = ((SQLIdentifierExpr) expr).getName();\n            if (\"treat\".equalsIgnoreCase(methodName)) {\n                OracleTreatExpr treatExpr = new OracleTreatExpr();\n\n                treatExpr.setExpr(this.expr());\n\n                accept(Token.AS);\n\n                if (lexer.identifierEquals(\"REF\")) {\n                    treatExpr.setRef(true);\n                    lexer.nextToken();\n                }\n\n                treatExpr.setType(this.expr());\n                accept(Token.RPAREN);\n\n                return primaryRest(treatExpr);\n            }\n        }\n\n        return super.methodRest(expr, false);\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n            String ident = ((SQLIdentifierExpr) expr).getName();\n\n            final long hashCode64 = identExpr.hashCode64();\n            if (hashCode64 == FnvHash.Constants.TIMESTAMP) {\n                if (lexer.token() != Token.LITERAL_ALIAS && lexer.token() != Token.LITERAL_CHARS) {\n                    return new SQLIdentifierExpr(\"TIMESTAMP\");\n                }\n\n                SQLTimestampExpr timestamp = new SQLTimestampExpr();\n\n                String literal = lexer.stringVal();\n                timestamp.setValue(literal);\n                accept(Token.LITERAL_CHARS);\n\n                if (lexer.identifierEquals(\"AT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n\n                    String timezone = lexer.stringVal();\n                    timestamp.setTimeZone(timezone);\n                    accept(Token.LITERAL_CHARS);\n                }\n\n                return primaryRest(timestamp);\n            }\n        }\n        if (lexer.token() == Token.IDENTIFIER && expr instanceof SQLNumericLiteralExpr) {\n            String ident = lexer.stringVal();\n\n            if (ident.length() == 1) {\n                char unit = ident.charAt(0);\n                switch (unit) {\n                    case 'K':\n                    case 'M':\n                    case 'G':\n                    case 'T':\n                    case 'P':\n                    case 'E':\n                    case 'k':\n                    case 'm':\n                    case 'g':\n                    case 't':\n                    case 'p':\n                    case 'e':\n                        expr = new SQLSizeExpr(expr, SQLSizeExpr.Unit.valueOf(ident.toUpperCase()));\n                        lexer.nextToken();\n                        break;\n                    default:\n                        break;\n                }\n            }\n        }\n\n        if (lexer.token() == Token.DOTDOT) {\n            lexer.nextToken();\n            SQLExpr upBound = expr();\n\n            return new OracleRangeExpr(expr, upBound);\n        }\n\n        if (lexer.token() == Token.MONKEYS_AT) {\n            lexer.nextToken();\n\n            SQLDbLinkExpr dblink = new SQLDbLinkExpr();\n            dblink.setExpr(expr);\n\n            if (lexer.token() == Token.BANG) {\n                dblink.setDbLink(\"!\");\n                lexer.nextToken();\n            } else {\n                String link = lexer.stringVal();\n                if (lexer.token() == Token.LITERAL_ALIAS) {\n                    accept(Token.LITERAL_ALIAS);\n                } else {\n                    accept(Token.IDENTIFIER);\n                }\n                dblink.setDbLink(link);\n                if (lexer.token() == Token.LPAREN) {\n                    SQLExpr dblinkExpr = dblink.getExpr();\n                    if (dblinkExpr.getClass() == SQLPropertyExpr.class) {\n                        SQLExpr methodInvokeExpr = new SQLMethodInvokeExpr();\n                        SQLMethodInvokeExpr expr2 = (SQLMethodInvokeExpr) methodRest(methodInvokeExpr, true);\n\n                        expr2.setOwner(((SQLPropertyExpr) expr).getOwner());\n                        expr2.setMethodName(((SQLPropertyExpr) expr).getName());\n\n                        dblink.setExpr(expr2);\n                    }\n                }\n            }\n\n            expr = dblink;\n        }\n\n        if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr arrayExpr = new SQLArrayExpr();\n            arrayExpr.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(arrayExpr.getValues(), arrayExpr);\n            accept(Token.RBRACKET);\n            expr = arrayExpr;\n\n            expr = primaryRest(expr);\n        }\n\n        if (lexer.identifierEquals(\"DAY\") || lexer.identifierEquals(\"YEAR\")) {\n            Lexer.SavePoint savePoint = lexer.mark();\n\n            String name = lexer.stringVal();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.reset(savePoint);\n                return expr;\n            }\n\n            OracleIntervalExpr interval = new OracleIntervalExpr();\n            interval.setValue(expr);\n            OracleIntervalType type = OracleIntervalType.valueOf(name.toUpperCase());\n            interval.setType(type);\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                if (lexer.token() != Token.LITERAL_INT) {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n                interval.setPrecision(lexer.integerValue().intValue());\n                lexer.nextToken();\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.TO) {\n                lexer.nextToken();\n            } else {\n                lexer.reset(savePoint);\n                return expr;\n            }\n\n            if (lexer.identifierEquals(\"SECOND\")) {\n                lexer.nextToken();\n                interval.setToType(OracleIntervalType.SECOND);\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    if (lexer.token() != Token.LITERAL_INT) {\n                        throw new ParserException(\"syntax error. \" + lexer.info());\n                    }\n                    interval.setFactionalSecondsPrecision(lexer.integerValue().intValue());\n                    lexer.nextToken();\n                    accept(Token.RPAREN);\n                }\n            } else {\n                interval.setToType(OracleIntervalType.MONTH);\n                lexer.nextToken();\n            }\n\n            expr = interval;\n        }\n\n        if (lexer.identifierEquals(\"AT\")) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"LOCAL\")) {\n                lexer.nextToken();\n                expr = new OracleDatetimeExpr(expr, new SQLIdentifierExpr(\"LOCAL\"));\n            } else {\n                if (lexer.identifierEquals(\"TIME\")) {\n                    lexer.nextToken();\n                } else {\n                    lexer.reset(mark);\n                    return expr;\n                }\n                acceptIdentifier(\"ZONE\");\n\n                SQLExpr timeZone = primary();\n                expr = new OracleDatetimeExpr(expr, timeZone);\n            }\n        }\n\n        SQLExpr restExpr = super.primaryRest(expr);\n\n        if (restExpr != expr && restExpr instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr methodInvoke = (SQLMethodInvokeExpr) restExpr;\n            if (methodInvoke.getArguments().size() == 1) {\n                SQLExpr paramExpr = methodInvoke.getArguments().get(0);\n                if (paramExpr instanceof SQLIdentifierExpr && \"+\".equals(((SQLIdentifierExpr) paramExpr).getName())) {\n                    OracleOuterExpr outerExpr = new OracleOuterExpr();\n                    if (methodInvoke.getOwner() == null) {\n                        outerExpr.setExpr(new SQLIdentifierExpr(methodInvoke.getMethodName()));\n                    } else {\n                        outerExpr.setExpr(new SQLPropertyExpr(methodInvoke.getOwner(), methodInvoke.getMethodName()));\n                    }\n                    return outerExpr;\n                }\n            }\n        }\n\n        return restExpr;\n    }\n\n    protected SQLExpr dotRest(SQLExpr expr) {\n        if (lexer.token() == Token.LITERAL_ALIAS) {\n            String name = lexer.stringVal();\n            lexer.nextToken();\n            expr = new SQLPropertyExpr(expr, name);\n\n            if (lexer.token() == Token.DOT) {\n                lexer.nextToken();\n                expr = dotRest(expr);\n            }\n\n            return expr;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.NEXTVAL)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.NextVal);\n                lexer.nextToken();\n                return seqExpr;\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.CURRVAL)) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                SQLSequenceExpr seqExpr = new SQLSequenceExpr(identExpr, SQLSequenceExpr.Function.CurrVal);\n                lexer.nextToken();\n                return seqExpr;\n            }\n        }\n\n        return super.dotRest(expr);\n    }\n\n    protected SQLAggregateExpr parseAggregateExpr(String methodName) {\n//        methodName = methodName.toUpperCase();\n\n        SQLAggregateExpr aggregateExpr;\n        if (lexer.token() == Token.UNIQUE) {\n            aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.UNIQUE);\n            lexer.nextToken();\n        } else if (lexer.token() == (Token.ALL)) {\n            aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.ALL);\n            lexer.nextToken();\n        } else if (lexer.token() == (Token.DISTINCT)) {\n            aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.DISTINCT);\n            lexer.nextToken();\n        } else {\n            aggregateExpr = new SQLAggregateExpr(methodName);\n        }\n        exprList(aggregateExpr.getArguments(), aggregateExpr);\n\n        if (lexer.stringVal().equalsIgnoreCase(\"IGNORE\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setIgnoreNulls(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.RESPECT)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setIgnoreNulls(false);\n        }\n\n        accept(Token.RPAREN);\n\n        if (lexer.stringVal().equalsIgnoreCase(\"IGNORE\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setIgnoreNulls(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.RESPECT)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setIgnoreNulls(false);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WITHIN)) {\n            lexer.nextToken();\n            accept(Token.GROUP);\n            accept(Token.LPAREN);\n            SQLOrderBy orderBy = this.parseOrderBy();\n            aggregateExpr.setWithinGroup(true);\n            aggregateExpr.setOrderBy(orderBy);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(\"KEEP\")) {\n            lexer.nextToken();\n\n            SQLKeep keep = new SQLKeep();\n            accept(Token.LPAREN);\n            acceptIdentifier(\"DENSE_RANK\");\n            if (lexer.identifierEquals(\"FIRST\")) {\n                lexer.nextToken();\n                keep.setDenseRank(DenseRank.FIRST);\n            } else {\n                acceptIdentifier(\"LAST\");\n                keep.setDenseRank(DenseRank.LAST);\n            }\n\n            SQLOrderBy orderBy = this.parseOrderBy();\n            keep.setOrderBy(orderBy);\n\n            aggregateExpr.setKeep(keep);\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.OVER) {\n            OracleAnalytic over = new OracleAnalytic();\n\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            if (lexer.token() == Token.PARTITION) {\n                lexer.nextToken();\n                accept(Token.BY);\n\n                if (lexer.token() == (Token.LPAREN)) {\n                    lexer.nextToken();\n                    exprList(over.getPartitionBy(), over);\n                    accept(Token.RPAREN);\n                } else {\n                    exprList(over.getPartitionBy(), over);\n                }\n            }\n\n            final SQLOrderBy orderBy = parseOrderBy();\n            if (orderBy != null) {\n                over.setOrderBy(orderBy);\n\n                OracleAnalyticWindowing windowing = null;\n                if (lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                    lexer.nextToken();\n                    windowing = new OracleAnalyticWindowing();\n                    windowing.setType(OracleAnalyticWindowing.Type.ROWS);\n                } else if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n                    lexer.nextToken();\n                    windowing = new OracleAnalyticWindowing();\n                    windowing.setType(OracleAnalyticWindowing.Type.RANGE);\n                }\n\n                if (windowing != null) {\n                    if (lexer.identifierEquals(FnvHash.Constants.CURRENT)) {\n                        lexer.nextToken();\n                        accept(Token.ROW);\n                        windowing.setExpr(new SQLIdentifierExpr(\"CURRENT ROW\"));\n                        over.setWindowing(windowing);\n                    }\n                    if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) {\n                        lexer.nextToken();\n                        if (lexer.stringVal().equalsIgnoreCase(\"PRECEDING\")) {\n                            lexer.nextToken();\n                            windowing.setExpr(new SQLIdentifierExpr(\"UNBOUNDED PRECEDING\"));\n                        } else {\n                            throw new ParserException(\"syntax error. \" + lexer.info());\n                        }\n                    } else if (lexer.token() == Token.BETWEEN) {\n                        lexer.nextToken();\n                        SQLExpr beginExpr;\n\n                        if (lexer.identifierEquals(FnvHash.Constants.CURRENT)) {\n                            lexer.nextToken();\n                            accept(Token.ROW);\n                            beginExpr = new SQLIdentifierExpr(\"CURRENT ROW\");\n                        } else if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) {\n                            lexer.nextToken();\n                            if (lexer.stringVal().equalsIgnoreCase(\"PRECEDING\")) {\n                                lexer.nextToken();\n                                beginExpr = new SQLIdentifierExpr(\"UNBOUNDED PRECEDING\");\n                            } else {\n                                throw new ParserException(\"syntax error. \" + lexer.info());\n                            }\n                        } else {\n                            beginExpr = relational();\n                        }\n\n                        final SQLOver.WindowingBound beginBound = parseWindowingBound();\n                        if (beginBound != null) {\n                            over.setWindowingBetweenBeginBound(beginBound);\n                        }\n\n                        accept(Token.AND);\n                        SQLExpr endExpr;\n                        if (lexer.identifierEquals(FnvHash.Constants.CURRENT)) {\n                            lexer.nextToken();\n                            accept(Token.ROW);\n                            endExpr = new SQLIdentifierExpr(\"CURRENT ROW\");\n                        } else if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) {\n                            lexer.nextToken();\n                            if (lexer.stringVal().equalsIgnoreCase(\"FOLLOWING\")) {\n                                lexer.nextToken();\n                                endExpr = new SQLIdentifierExpr(\"UNBOUNDED FOLLOWING\");\n                            } else {\n                                throw new ParserException(\"syntax error. \" + lexer.info());\n                            }\n                        } else {\n                            endExpr = relational();\n                        }\n\n                        final SQLOver.WindowingBound endBound = parseWindowingBound();\n                        if (endBound != null) {\n                            over.setWindowingBetweenEndBound(endBound);\n                        }\n                        SQLExpr expr = new SQLBetweenExpr(null, beginExpr, endExpr);\n                        windowing.setExpr(expr);\n                    } else {\n                        SQLExpr expr = this.expr();\n                        windowing.setExpr(expr);\n\n                        acceptIdentifier(\"PRECEDING\");\n                        over.setWindowingPreceding(true);\n                    }\n\n                    over.setWindowing(windowing);\n                }\n            }\n\n            accept(Token.RPAREN);\n\n            aggregateExpr.setOver(over);\n        }\n        return aggregateExpr;\n    }\n\n    @SuppressWarnings(\"unused\")\n    private OracleIntervalType parseIntervalType() {\n        String currentTokenUpperValue = lexer.stringVal();\n        lexer.nextToken();\n\n        if (currentTokenUpperValue.equals(\"YEAR\")) {\n            return OracleIntervalType.YEAR;\n        }\n        if (currentTokenUpperValue.equals(\"MONTH\")) {\n            return OracleIntervalType.MONTH;\n        }\n        if (currentTokenUpperValue.equals(\"HOUR\")) {\n            return OracleIntervalType.HOUR;\n        }\n        if (currentTokenUpperValue.equals(\"MINUTE\")) {\n            return OracleIntervalType.MINUTE;\n        }\n        if (currentTokenUpperValue.equals(\"SECOND\")) {\n            return OracleIntervalType.SECOND;\n        }\n        throw new ParserException(\"syntax error. \" + lexer.info());\n    }\n\n    @Override\n    public OracleSelectParser createSelectParser() {\n        return new OracleSelectParser(this);\n    }\n\n    protected SQLExpr parseInterval() {\n        accept(Token.INTERVAL);\n\n        OracleIntervalExpr interval = new OracleIntervalExpr();\n\n        if (lexer.token() == Token.LITERAL_CHARS) {\n            interval.setValue(new SQLCharExpr(lexer.stringVal()));\n        } else if (lexer.token() == Token.VARIANT) {\n            interval.setValue(new SQLVariantRefExpr(lexer.stringVal()));\n        } else if (lexer.token() == Token.QUES) {\n            interval.setValue(new SQLVariantRefExpr(\"?\"));\n        } else {\n            return new SQLIdentifierExpr(\"INTERVAL\");\n        }\n\n        lexer.nextToken();\n\n        OracleIntervalType type;\n        if (lexer.identifierEquals(FnvHash.Constants.YEAR)) {\n            lexer.nextToken();\n            type = OracleIntervalType.YEAR;\n        } else if (lexer.identifierEquals(FnvHash.Constants.MONTH)) {\n            lexer.nextToken();\n            type = OracleIntervalType.MONTH;\n        } else if (lexer.identifierEquals(FnvHash.Constants.DAY)) {\n            lexer.nextToken();\n            type = OracleIntervalType.DAY;\n        } else if (lexer.identifierEquals(FnvHash.Constants.HOUR)) {\n            lexer.nextToken();\n            type = OracleIntervalType.HOUR;\n        } else if (lexer.identifierEquals(FnvHash.Constants.MINUTE)) {\n            lexer.nextToken();\n            type = OracleIntervalType.MINUTE;\n        } else if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n            lexer.nextToken();\n            type = OracleIntervalType.SECOND;\n        } else {\n            throw new ParserException(\"illegal interval type. \" + lexer.info());\n        }\n\n        interval.setType(type);\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n            interval.setPrecision(this.primary());\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                if (lexer.token() != Token.LITERAL_INT) {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n                interval.setFactionalSecondsPrecision(lexer.integerValue().intValue());\n                lexer.nextToken();\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"SECOND\")) {\n                lexer.nextToken();\n                interval.setToType(OracleIntervalType.SECOND);\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {\n                        throw new ParserException(\"syntax error. \" + lexer.info());\n                    }\n                    interval.setToFactionalSecondsPrecision(primary());\n                    accept(Token.RPAREN);\n                }\n            } else {\n                interval.setToType(OracleIntervalType.MONTH);\n                lexer.nextToken();\n            }\n        }\n\n        return interval;\n    }\n\n    public SQLExpr relationalRest(SQLExpr expr) {\n        if (lexer.token() == Token.IS) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.NOT) {\n                lexer.nextToken();\n                SQLExpr rightExpr = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.IsNot, rightExpr, getDbType());\n            } else if (lexer.identifierEquals(\"A\")) {\n                lexer.nextToken();\n                accept(Token.SET);\n                expr = new OracleIsSetExpr(expr);\n            } else if (lexer.token() == Token.OF) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.TYPE)) {\n                    lexer.nextToken();\n                }\n\n                OracleIsOfTypeExpr isOf = new OracleIsOfTypeExpr();\n                isOf.setExpr(expr);\n                accept(Token.LPAREN);\n\n                for (; ; ) {\n                    boolean only = lexer.identifierEquals(FnvHash.Constants.ONLY);\n                    if (only) {\n                        lexer.nextToken();\n                    }\n\n                    SQLExpr type = this.name();\n                    if (only) {\n                        type.putAttribute(\"ONLY\", true);\n                    }\n\n                    type.setParent(isOf);\n                    isOf.getTypes().add(type);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n\n                accept(Token.RPAREN);\n\n                expr = isOf;\n            } else {\n                SQLExpr rightExpr = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, rightExpr, getDbType());\n            }\n\n            return expr;\n        }\n        return super.relationalRest(expr);\n    }\n\n    public SQLName name() {\n        SQLName name = super.name();\n\n        if (lexer.token() == Token.MONKEYS_AT) {\n            lexer.nextToken();\n            if (lexer.token() != Token.IDENTIFIER) {\n                throw new ParserException(\"syntax error, expect identifier, but \" + lexer.token() + \", \" + lexer.info());\n            }\n            SQLDbLinkExpr dbLink = new SQLDbLinkExpr();\n            dbLink.setExpr(name);\n\n            StringBuilder link = new StringBuilder(lexer.stringVal());\n            lexer.nextToken();\n            while (lexer.token() == Token.DOT) {\n                lexer.nextToken();\n\n                String stringVal = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n                link.append(\".\").append(stringVal);\n            }\n\n            dbLink.setDbLink(link.toString());\n            return dbLink;\n        }\n//\n//        if (name.nameHashCode64() == FnvHash.Constants.UNSUPPORTED\n//                && lexer.identifierEquals(FnvHash.Constants.TYPE)) {\n//            name = new SQLIdentifierExpr(name.getSimpleName() + \" \" + lexer.stringVal());\n//            lexer.nextToken();\n//        }\n\n        return name;\n    }\n\n    public OraclePrimaryKey parsePrimaryKey() {\n        lexer.nextToken();\n        accept(Token.KEY);\n\n        OraclePrimaryKey primaryKey = new OraclePrimaryKey();\n        accept(Token.LPAREN);\n        orderBy(primaryKey.getColumns(), primaryKey);\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.USING) {\n            OracleUsingIndexClause using = parseUsingIndex();\n            primaryKey.setUsing(using);\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                primaryKey.setEnable(Boolean.TRUE);\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                primaryKey.setEnable(Boolean.FALSE);\n            } else if (lexer.identifierEquals(\"VALIDATE\")) {\n                lexer.nextToken();\n                primaryKey.setValidate(Boolean.TRUE);\n            } else if (lexer.identifierEquals(\"NOVALIDATE\")) {\n                lexer.nextToken();\n                primaryKey.setValidate(Boolean.FALSE);\n            } else if (lexer.identifierEquals(\"RELY\")) {\n                lexer.nextToken();\n                primaryKey.setRely(Boolean.TRUE);\n            } else if (lexer.identifierEquals(\"NORELY\")) {\n                lexer.nextToken();\n                primaryKey.setRely(Boolean.FALSE);\n            } else {\n                break;\n            }\n        }\n\n        return primaryKey;\n    }\n\n    private OracleUsingIndexClause parseUsingIndex() {\n        accept(Token.USING);\n        accept(Token.INDEX);\n\n        OracleUsingIndexClause using = new OracleUsingIndexClause();\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            OracleCreateIndexStatement createIndex = new OracleStatementParser(lexer).parseCreateIndex();\n            using.setIndex(createIndex);\n            accept(Token.RPAREN);\n        }\n\n        for (; ; ) {\n            this.parseSegmentAttributes(using);\n\n            if (lexer.token() == Token.COMPUTE) {\n                lexer.nextToken();\n                acceptIdentifier(\"STATISTICS\");\n                using.setComputeStatistics(true);\n                continue;\n            } else if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                using.setEnable(true);\n            } else if (lexer.token() == Token.REVERSE) {\n                lexer.nextToken();\n                using.setReverse(true);\n                continue;\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                using.setEnable(false);\n                continue;\n            } else if (lexer.identifierEquals(\"LOCAL\")) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                // http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5010.htm#i2125897\n                for (; ; ) {\n                    OraclePartitionSingle partition = this.parsePartition();\n                    partition.setParent(using);\n                    using.getLocalPartitionIndex().add(partition);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else if (lexer.token() == Token.RPAREN) {\n                        break;\n                    } else {\n                        throw new ParserException(\"TODO \" + lexer.info());\n                    }\n                }\n                accept(Token.RPAREN);\n                continue;\n            } else if (lexer.token() == Token.IDENTIFIER) {\n                using.setTablespace(this.name());\n                break;\n            } else {\n                break;\n            }\n        }\n\n        return using;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        column = super.parseColumnRest(column);\n\n        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.ALWAYS)) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n\n            accept(Token.AS);\n\n            if (lexer.token() == Token.NULL || lexer.token() == Token.DEFAULT || lexer.token() == Token.LPAREN) {\n                SQLExpr expr = this.expr();\n\n                column.setGeneratedAlwaysAs(expr);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.IDENTITY)) {\n                lexer.nextToken();\n                column.setIdentity(\n                        parseIdentity());\n            }\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                column.setEnable(Boolean.TRUE);\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                column.setEnable(Boolean.FALSE);\n            } else if (lexer.identifierEquals(\"VALIDATE\")) {\n                lexer.nextToken();\n                column.setValidate(Boolean.TRUE);\n            } else if (lexer.identifierEquals(\"NOVALIDATE\")) {\n                lexer.nextToken();\n                column.setValidate(Boolean.FALSE);\n            } else if (lexer.identifierEquals(\"RELY\")) {\n                lexer.nextToken();\n                column.setRely(Boolean.TRUE);\n            } else if (lexer.identifierEquals(\"NORELY\")) {\n                lexer.nextToken();\n                column.setRely(Boolean.FALSE);\n            } else if (lexer.identifierEquals(FnvHash.Constants.VISIBLE)) {\n                lexer.nextToken();\n                column.setVisible(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.VIRTUAL)) {\n                lexer.nextToken();\n                column.setVirtual(true);\n            } else {\n                break;\n            }\n        }\n\n        return column;\n    }\n\n    protected SQLColumnDefinition.Identity parseIdentity() {\n        accept(Token.LPAREN);\n        SQLColumnDefinition.Identity ident = new SQLColumnDefinition.Identity();\n        accept(Token.START);\n        accept(Token.WITH);\n\n        if (lexer.token() == Token.LITERAL_INT) {\n            ident.setSeed(lexer.integerValue().intValue());\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"TODO : \" + lexer.info());\n        }\n\n        if (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n            if (lexer.token() == Token.LITERAL_INT) {\n                ident.setIncrement(lexer.integerValue().intValue());\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n        }\n\n        accept(Token.RPAREN);\n        return ident;\n    }\n\n    public SQLExpr exprRest(SQLExpr expr) {\n        expr = super.exprRest(expr);\n\n        if (lexer.token() == Token.COLONEQ) {\n            lexer.nextToken();\n            SQLExpr right = expr();\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, right, getDbType());\n        }\n\n        return expr;\n    }\n\n    public SQLObject parseOpaque() {\n        acceptIdentifier(\"OPAQUE\");\n        acceptIdentifier(\"TYPE\");\n\n        SQLExpr expr = this.primary();\n\n        OracleLobStorageClause clause = new OracleLobStorageClause();\n\n        accept(Token.STORE);\n        accept(Token.AS);\n\n        if (lexer.identifierEquals(\"SECUREFILE\")) {\n            lexer.nextToken();\n            clause.setSecureFile(true);\n        }\n\n        if (lexer.identifierEquals(\"BASICFILE\")) {\n            lexer.nextToken();\n            clause.setBasicFile(true);\n        }\n\n        accept(Token.LOB);\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                this.parseSegmentAttributes(clause);\n\n                if (lexer.token() == Token.ENABLE) {\n                    lexer.nextToken();\n                    accept(Token.STORAGE);\n                    accept(Token.IN);\n                    accept(Token.ROW);\n                    clause.setEnable(true);\n                    continue;\n                } else if (lexer.token() == Token.DISABLE) {\n                    lexer.nextToken();\n                    accept(Token.STORAGE);\n                    accept(Token.IN);\n                    accept(Token.ROW);\n                    clause.setEnable(false);\n                    continue;\n                }\n\n                if (lexer.token() == Token.CHUNK) {\n                    lexer.nextToken();\n                    clause.setChunk(this.primary());\n                    continue;\n                }\n\n                if (lexer.token() == Token.NOCACHE) {\n                    lexer.nextToken();\n                    clause.setCache(false);\n                    if (lexer.token() == Token.LOGGING) {\n                        lexer.nextToken();\n                        clause.setLogging(true);\n                    }\n                    continue;\n                }\n\n                if (lexer.token() == Token.CACHE) {\n                    lexer.nextToken();\n                    clause.setCache(true);\n                    continue;\n                }\n\n                if (lexer.token() == Token.KEEP_DUPLICATES) {\n                    lexer.nextToken();\n                    clause.setKeepDuplicate(true);\n                    continue;\n                }\n\n                if (lexer.identifierEquals(\"PCTVERSION\")) {\n                    lexer.nextToken();\n                    clause.setPctversion(this.expr());\n                    continue;\n                }\n\n                if (lexer.identifierEquals(\"RETENTION\")) {\n                    lexer.nextToken();\n                    clause.setRetention(true);\n                    continue;\n                }\n\n                if (lexer.token() == Token.STORAGE) {\n                    OracleStorageClause storageClause = this.parseStorage();\n                    clause.setStorageClause(storageClause);\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        return clause;\n    }\n\n    public OracleLobStorageClause parseLobStorage() {\n        lexer.nextToken();\n\n        OracleLobStorageClause clause = new OracleLobStorageClause();\n\n        accept(Token.LPAREN);\n        this.names(clause.getItems());\n        accept(Token.RPAREN);\n\n        accept(Token.STORE);\n        accept(Token.AS);\n\n        if (lexer.identifierEquals(\"SECUREFILE\")) {\n            lexer.nextToken();\n            clause.setSecureFile(true);\n        }\n\n        if (lexer.identifierEquals(\"BASICFILE\")) {\n            lexer.nextToken();\n            clause.setBasicFile(true);\n        }\n\n        if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.LITERAL_ALIAS) {\n            SQLName segmentName = this.name();\n            clause.setSegementName(segmentName);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                this.parseSegmentAttributes(clause);\n\n                if (lexer.token() == Token.ENABLE) {\n                    lexer.nextToken();\n                    accept(Token.STORAGE);\n                    accept(Token.IN);\n                    accept(Token.ROW);\n                    clause.setEnable(true);\n                    continue;\n                } else if (lexer.token() == Token.DISABLE) {\n                    lexer.nextToken();\n                    accept(Token.STORAGE);\n                    accept(Token.IN);\n                    accept(Token.ROW);\n                    clause.setEnable(false);\n                    continue;\n                }\n\n                if (lexer.token() == Token.CHUNK) {\n                    lexer.nextToken();\n                    clause.setChunk(this.primary());\n                    continue;\n                }\n\n                if (lexer.token() == Token.NOCACHE) {\n                    lexer.nextToken();\n                    clause.setCache(false);\n                    if (lexer.token() == Token.LOGGING) {\n                        lexer.nextToken();\n                        clause.setLogging(true);\n                    }\n                    continue;\n                }\n\n                if (lexer.token() == Token.CACHE) {\n                    lexer.nextToken();\n                    clause.setCache(true);\n                    continue;\n                }\n\n                if (lexer.token() == Token.KEEP_DUPLICATES) {\n                    lexer.nextToken();\n                    clause.setKeepDuplicate(true);\n                    continue;\n                }\n\n                if (lexer.identifierEquals(\"PCTVERSION\")) {\n                    lexer.nextToken();\n                    clause.setPctversion(this.expr());\n                    continue;\n                }\n\n                if (lexer.identifierEquals(\"RETENTION\")) {\n                    lexer.nextToken();\n                    clause.setRetention(true);\n                    continue;\n                }\n\n                if (lexer.token() == Token.STORAGE) {\n                    OracleStorageClause storageClause = this.parseStorage();\n                    clause.setStorageClause(storageClause);\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        return clause;\n    }\n\n    public OracleStorageClause parseStorage() {\n        lexer.nextToken();\n        accept(Token.LPAREN);\n\n        OracleStorageClause storage = new OracleStorageClause();\n        for (; ; ) {\n            if (lexer.identifierEquals(\"INITIAL\")) {\n                lexer.nextToken();\n                storage.setInitial(this.expr());\n                continue;\n            } else if (lexer.token() == Token.NEXT) {\n                lexer.nextToken();\n                storage.setNext(this.expr());\n                continue;\n            } else if (lexer.token() == Token.MINEXTENTS) {\n                lexer.nextToken();\n                storage.setMinExtents(this.expr());\n                continue;\n            } else if (lexer.token() == Token.MAXEXTENTS) {\n                lexer.nextToken();\n                storage.setMaxExtents(this.expr());\n                continue;\n            } else if (lexer.token() == Token.MAXSIZE) {\n                lexer.nextToken();\n                storage.setMaxSize(this.expr());\n                continue;\n            } else if (lexer.token() == Token.PCTINCREASE) {\n                lexer.nextToken();\n                storage.setPctIncrease(this.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"FREELISTS\")) {\n                lexer.nextToken();\n                storage.setFreeLists(this.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"FREELIST\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"GROUPS\");\n                storage.setFreeListGroups(this.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"BUFFER_POOL\")) {\n                lexer.nextToken();\n                storage.setBufferPool(this.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"OBJNO\")) {\n                lexer.nextToken();\n                storage.setObjno(this.expr());\n                continue;\n            } else if (lexer.token() == Token.FLASH_CACHE) {\n                lexer.nextToken();\n                FlashCacheType flashCacheType;\n                if (lexer.identifierEquals(\"KEEP\")) {\n                    flashCacheType = FlashCacheType.KEEP;\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.NONE) {\n                    flashCacheType = FlashCacheType.NONE;\n                    lexer.nextToken();\n                } else {\n                    accept(Token.DEFAULT);\n                    flashCacheType = FlashCacheType.DEFAULT;\n                }\n                storage.setFlashCache(flashCacheType);\n                continue;\n            } else if (lexer.token() == Token.CELL_FLASH_CACHE) {\n                lexer.nextToken();\n                FlashCacheType flashCacheType;\n                if (lexer.identifierEquals(\"KEEP\")) {\n                    flashCacheType = FlashCacheType.KEEP;\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.NONE) {\n                    flashCacheType = FlashCacheType.NONE;\n                    lexer.nextToken();\n                } else {\n                    accept(Token.DEFAULT);\n                    flashCacheType = FlashCacheType.DEFAULT;\n                }\n                storage.setCellFlashCache(flashCacheType);\n                continue;\n            }\n\n            break;\n        }\n        accept(Token.RPAREN);\n        return storage;\n    }\n\n    public SQLUnique parseUnique() {\n        accept(Token.UNIQUE);\n\n        OracleUnique unique = new OracleUnique();\n        accept(Token.LPAREN);\n        orderBy(unique.getColumns(), unique);\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.USING) {\n            OracleUsingIndexClause using = parseUsingIndex();\n            unique.setUsing(using);\n        }\n\n        return unique;\n    }\n\n    public OracleConstraint parseConstraint() {\n        OracleConstraint constraint = (OracleConstraint) super.parseConstraint();\n\n        for (; ; ) {\n            if (lexer.token() == Token.EXCEPTIONS) {\n                lexer.nextToken();\n                accept(Token.INTO);\n                SQLName exceptionsInto = this.name();\n                constraint.setExceptionsInto(exceptionsInto);\n                continue;\n            }\n\n            if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                constraint.setEnable(false);\n                continue;\n            }\n\n            if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                constraint.setEnable(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.VALIDATE)) {\n                lexer.nextToken();\n                constraint.setValidate(Boolean.TRUE);\n                continue;\n            }\n            if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) {\n                lexer.nextToken();\n                constraint.setValidate(Boolean.FALSE);\n                continue;\n            }\n\n            if (lexer.token() == Token.INITIALLY) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.IMMEDIATE) {\n                    lexer.nextToken();\n                    constraint.setInitially(Initially.IMMEDIATE);\n                } else {\n                    accept(Token.DEFERRED);\n                    constraint.setInitially(Initially.DEFERRED);\n                }\n\n                continue;\n            }\n\n            if (lexer.token() == Token.NOT) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.DEFERRABLE)) {\n                    lexer.nextToken();\n                    constraint.setDeferrable(false);\n                    continue;\n                }\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DEFERRABLE)) {\n                lexer.nextToken();\n                constraint.setDeferrable(true);\n                continue;\n            }\n\n            if (lexer.token() == Token.USING) {\n                OracleUsingIndexClause using = parseUsingIndex();\n                constraint.setUsing(using);\n            }\n\n            break;\n        }\n\n        return constraint;\n    }\n\n    protected OracleForeignKey createForeignKey() {\n        return new OracleForeignKey();\n    }\n\n    protected SQLCheck createCheck() {\n        return new OracleCheck();\n    }\n\n    public OraclePartitionSingle parsePartition() {\n        accept(Token.PARTITION);\n        OraclePartitionSingle partition = new OraclePartitionSingle();\n        partition.setName(this.name());\n\n        SQLPartitionValue values = this.parsePartitionValues();\n        if (values != null) {\n            this.parseSegmentAttributes(values);\n        }\n\n        if (values != null) {\n            partition.setValues(values);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                SQLSubPartition subPartition = parseSubPartition();\n                this.parseSegmentAttributes(subPartition);\n\n                partition.addSubPartition(subPartition);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.RPAREN);\n        } else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITIONS)) {\n            lexer.nextToken();\n            SQLExpr subPartitionsCount = this.primary();\n            partition.setSubPartitionsCount(subPartitionsCount);\n        }\n\n        for (; ; ) {\n            parseSegmentAttributes(partition);\n\n            if (lexer.token() == Token.LOB) {\n                OracleLobStorageClause lobStorage = this.parseLobStorage();\n                partition.setLobStorage(lobStorage);\n                continue;\n            }\n\n            if (lexer.token() == Token.SEGMENT || lexer.identifierEquals(\"SEGMENT\")) {\n                lexer.nextToken();\n                accept(Token.CREATION);\n                if (lexer.token() == Token.IMMEDIATE) {\n                    lexer.nextToken();\n                    partition.setSegmentCreationImmediate(true);\n                } else if (lexer.token() == Token.DEFERRED) {\n                    lexer.nextToken();\n                    partition.setSegmentCreationDeferred(true);\n                }\n                continue;\n            }\n            break;\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                SQLSubPartition subPartition = parseSubPartition();\n                this.parseSegmentAttributes(subPartition);\n\n                partition.addSubPartition(subPartition);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        return partition;\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        lexer.nextToken();\n\n        accept(Token.BY);\n\n        SQLPartitionBy partitionBy;\n\n        if (lexer.identifierEquals(\"RANGE\")) {\n            return this.partitionByRange();\n        } else if (lexer.identifierEquals(\"HASH\")) {\n            SQLPartitionByHash partitionByHash = this.partitionByHash();\n            this.partitionClauseRest(partitionByHash);\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                for (; ; ) {\n                    OraclePartitionSingle partition = this.parsePartition();\n                    partitionByHash.addPartition(partition);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else if (lexer.token() == Token.RPAREN) {\n                        lexer.nextToken();\n                        break;\n                    }\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            }\n            return partitionByHash;\n        } else if (lexer.identifierEquals(\"LIST\")) {\n            SQLPartitionByList partitionByList = partitionByList();\n            this.partitionClauseRest(partitionByList);\n            return partitionByList;\n        } else {\n            throw new ParserException(\"TODO : \" + lexer.info());\n        }\n    }\n\n    protected SQLPartitionByList partitionByList() {\n        acceptIdentifier(\"LIST\");\n        SQLPartitionByList partitionByList = new SQLPartitionByList();\n\n        accept(Token.LPAREN);\n        partitionByList.addColumn(this.expr());\n        accept(Token.RPAREN);\n\n        this.parsePartitionByRest(partitionByList);\n\n        return partitionByList;\n    }\n\n    protected SQLSubPartition parseSubPartition() {\n        acceptIdentifier(\"SUBPARTITION\");\n\n        SQLSubPartition subPartition = new SQLSubPartition();\n        SQLName name = this.name();\n        subPartition.setName(name);\n\n        SQLPartitionValue values = this.parsePartitionValues();\n        if (values != null) {\n            subPartition.setValues(values);\n        }\n\n        if (lexer.token() == Token.TABLESPACE) {\n            lexer.nextToken();\n            subPartition.setTableSpace(this.name());\n        }\n\n        return subPartition;\n    }\n\n    public void parseSegmentAttributes(OracleSegmentAttributes attributes) {\n        for (; ; ) {\n            if (lexer.token() == Token.TABLESPACE) {\n                lexer.nextToken();\n                attributes.setTablespace(this.name());\n                continue;\n            } else if (lexer.token() == Token.NOCOMPRESS || lexer.identifierEquals(\"NOCOMPRESS\")) {\n                lexer.nextToken();\n                attributes.setCompress(Boolean.FALSE);\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.COMPRESS)) {\n                lexer.nextToken();\n                attributes.setCompress(Boolean.TRUE);\n\n                if (lexer.token() == Token.LITERAL_INT) {\n                    int compressLevel = this.parseIntValue();\n                    attributes.setCompressLevel(compressLevel);\n                } else if (lexer.identifierEquals(\"BASIC\")) {\n                    lexer.nextToken();\n                    // TODO COMPRESS BASIC\n                } else if (lexer.token() == Token.FOR) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(\"OLTP\")) {\n                        lexer.nextToken();\n                        attributes.setCompressForOltp(true);\n                    } else {\n                        throw new ParserException(\"TODO : \" + lexer.info());\n                    }\n                }\n                continue;\n            } else if (lexer.identifierEquals(\"NOCOMPRESS\")) {\n                lexer.nextToken();\n                attributes.setCompress(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.LOGGING || lexer.identifierEquals(\"LOGGING\")) {\n                lexer.nextToken();\n                attributes.setLogging(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(\"NOLOGGING\")) {\n                lexer.nextToken();\n                attributes.setLogging(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.INITRANS) {\n                lexer.nextToken();\n                attributes.setInitrans(this.parseIntValue());\n                continue;\n            } else if (lexer.token() == Token.MAXTRANS) {\n                lexer.nextToken();\n                attributes.setMaxtrans(this.parseIntValue());\n            } else if (lexer.token() == Token.PCTINCREASE) {\n                lexer.nextToken();\n                attributes.setPctincrease(this.parseIntValue());\n                continue;\n            } else if (lexer.token() == Token.PCTFREE) {\n                lexer.nextToken();\n                attributes.setPctfree(this.parseIntValue());\n                continue;\n            } else if (lexer.token() == Token.STORAGE || lexer.identifierEquals(\"STORAGE\")) {\n                OracleStorageClause storage = this.parseStorage();\n                attributes.setStorage(storage);\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.PCTUSED)) {\n                lexer.nextToken();\n                attributes.setPctused(this.parseIntValue());\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.USAGE)) {\n                lexer.nextToken();\n                acceptIdentifier(\"QUEUE\");\n                // TODO USAGE QUEUE\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.OPAQUE)) {\n                parseOpaque();\n                // TODO OPAQUE TYPE\n                continue;\n            } else {\n                break;\n            }\n        }\n    }\n\n    protected SQLPartitionByRange partitionByRange() {\n        acceptIdentifier(\"RANGE\");\n        accept(Token.LPAREN);\n        SQLPartitionByRange clause = new SQLPartitionByRange();\n        for (; ; ) {\n            SQLName column = this.name();\n            clause.addColumn(column);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.INTERVAL) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            clause.setInterval(this.expr());\n            accept(Token.RPAREN);\n        }\n\n        parsePartitionByRest(clause);\n\n        return clause;\n    }\n\n    protected void parsePartitionByRest(SQLPartitionBy clause) {\n        if (lexer.token() == Token.STORE) {\n            lexer.nextToken();\n            accept(Token.IN);\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLName tablespace = this.name();\n                clause.getStoreIn().add(tablespace);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n            SQLSubPartitionBy subPartitionBy = subPartitionBy();\n            clause.setSubPartitionBy(subPartitionBy);\n\n            if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITIONS)) {\n                lexer.nextToken();\n                Number intValue = lexer.integerValue();\n                SQLNumberExpr numExpr = new SQLNumberExpr(intValue);\n                subPartitionBy.setSubPartitionsCount(numExpr);\n                lexer.nextToken();\n            }\n        }\n\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            OraclePartitionSingle partition = this.parsePartition();\n\n            clause.addPartition(partition);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        accept(Token.RPAREN);\n    }\n\n    protected SQLSubPartitionBy subPartitionBy() {\n        lexer.nextToken();\n        accept(Token.BY);\n\n        if (lexer.identifierEquals(FnvHash.Constants.HASH)) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            SQLSubPartitionByHash byHash = new SQLSubPartitionByHash();\n            SQLExpr expr = this.expr();\n            byHash.setExpr(expr);\n            accept(Token.RPAREN);\n\n            return byHash;\n        } else if (lexer.identifierEquals(FnvHash.Constants.LIST)) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            SQLSubPartitionByList byList = new SQLSubPartitionByList();\n            SQLName column = this.name();\n            byList.setColumn(column);\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {\n                lexer.nextToken();\n                acceptIdentifier(\"TEMPLATE\");\n                accept(Token.LPAREN);\n\n                for (; ; ) {\n                    SQLSubPartition subPartition = this.parseSubPartition();\n                    subPartition.setParent(byList);\n                    byList.getSubPartitionTemplate().add(subPartition);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITIONS)) {\n                lexer.nextToken();\n                Number intValue = lexer.integerValue();\n                SQLNumberExpr numExpr = new SQLNumberExpr(intValue);\n                byList.setSubPartitionsCount(numExpr);\n                lexer.nextToken();\n            }\n\n            return byList;\n        }\n\n        throw new ParserException(\"TODO : \" + lexer.info());\n    }\n\n    protected void partitionClauseRest(SQLPartitionBy clause) {\n        if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n            lexer.nextToken();\n\n            SQLIntegerExpr countExpr = this.integerExpr();\n            clause.setPartitionsCount(countExpr);\n        }\n\n        if (lexer.token() == Token.STORE) {\n            lexer.nextToken();\n            accept(Token.IN);\n            accept(Token.LPAREN);\n            this.names(clause.getStoreIn(), clause);\n            accept(Token.RPAREN);\n        }\n    }\n\n    protected SQLPartitionByHash partitionByHash() {\n        acceptIdentifier(\"HASH\");\n        SQLPartitionByHash partitionByHash = new SQLPartitionByHash();\n\n        if (lexer.token() == Token.KEY) {\n            lexer.nextToken();\n            partitionByHash.setKey(true);\n        }\n\n        accept(Token.LPAREN);\n        this.exprList(partitionByHash.getColumns(), partitionByHash);\n        accept(Token.RPAREN);\n        return partitionByHash;\n    }\n\n    @Override\n    protected void parseIdentifySpecific() {\n        accept(Token.START);\n        accept(Token.WITH);\n    }\n\n    @Override\n    protected SQLExpr parseSelectItemRest(String ident, long hash_lower) {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleFunctionDataType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleFunctionDataType extends SQLDataTypeImpl {\n    private boolean isStatic;\n    private final List<SQLParameter> parameters = new ArrayList<SQLParameter>();\n\n    private SQLDataType returnDataType;\n\n    private SQLStatement block;\n\n    public boolean isStatic() {\n        return isStatic;\n    }\n\n    public void setStatic(boolean aStatic) {\n        isStatic = aStatic;\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    public SQLDataType getReturnDataType() {\n        return returnDataType;\n    }\n\n    public void setReturnDataType(SQLDataType x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.returnDataType = x;\n    }\n\n    public OracleFunctionDataType clone() {\n        OracleFunctionDataType x = new OracleFunctionDataType();\n        cloneTo(x);\n\n        x.isStatic = isStatic;\n        if (returnDataType != null) {\n            x.setReturnDataType(returnDataType.clone());\n        }\n        for (SQLParameter parameter : parameters) {\n            SQLParameter p2 = parameter.clone();\n            p2.setParent(x);\n            x.parameters.add(p2);\n        }\n\n        return x;\n    }\n\n    public SQLStatement getBlock() {\n        return block;\n    }\n\n    public void setBlock(SQLStatement block) {\n        if (block != null) {\n            block.setParent(this);\n        }\n        this.block = block;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.*;\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;\n\npublic class OracleLexer extends Lexer {\n    static final Keywords ORACLE_KEYWORDS;\n    static final DialectFeature ORACLE_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    ScanSQLTypeWithBegin,\n                    SQLDateExpr,\n                    PrimaryVariantColon,\n                    CreateTableBodySupplemental,\n                    AsCommaFrom\n            ),\n            Collections.singletonList(\n                    SQLTimestampExpr\n            )\n    );\n    static {\n        Map<String, Token> map = new HashMap<>(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"COMMENT\", Token.COMMENT);\n        map.put(\"COMMIT\", Token.COMMIT);\n        map.put(\"CONNECT\", Token.CONNECT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n\n        map.put(\"CROSS\", Token.CROSS);\n        map.put(\"CURSOR\", Token.CURSOR);\n        map.put(\"DECLARE\", Token.DECLARE);\n        map.put(\"ERRORS\", Token.ERRORS);\n        map.put(\"EXCEPTION\", Token.EXCEPTION);\n\n        map.put(\"EXCLUSIVE\", Token.EXCLUSIVE);\n        map.put(\"EXTRACT\", Token.EXTRACT);\n        map.put(\"GOTO\", Token.GOTO);\n        map.put(\"IF\", Token.IF);\n        map.put(\"ELSIF\", Token.ELSIF);\n\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"LOOP\", Token.LOOP);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"MERGE\", Token.MERGE);\n\n        map.put(\"MODE\", Token.MODE);\n        //        map.put(\"MODEL\", Token.MODEL);\n        map.put(\"NOWAIT\", Token.NOWAIT);\n        map.put(\"OF\", Token.OF);\n        map.put(\"PRIOR\", Token.PRIOR);\n\n        map.put(\"REJECT\", Token.REJECT);\n        map.put(\"RETURN\", Token.RETURN);\n        map.put(\"RETURNING\", Token.RETURNING);\n        map.put(\"REVERSE\", Token.REVERSE);\n        map.put(\"SAVEPOINT\", Token.SAVEPOINT);\n        map.put(\"SESSION\", Token.SESSION);\n\n        map.put(\"SHARE\", Token.SHARE);\n        map.put(\"START\", Token.START);\n        map.put(\"SYSDATE\", Token.SYSDATE);\n        map.put(\"UNLIMITED\", Token.UNLIMITED);\n        map.put(\"USING\", Token.USING);\n\n        map.put(\"WAIT\", Token.WAIT);\n        map.put(\"WITH\", Token.WITH);\n\n        map.put(\"PCTFREE\", Token.PCTFREE);\n        map.put(\"INITRANS\", Token.INITRANS);\n        map.put(\"MAXTRANS\", Token.MAXTRANS);\n        map.put(\"SEGMENT\", Token.SEGMENT);\n        map.put(\"CREATION\", Token.CREATION);\n        map.put(\"IMMEDIATE\", Token.IMMEDIATE);\n        map.put(\"DEFERRED\", Token.DEFERRED);\n        map.put(\"STORAGE\", Token.STORAGE);\n        map.put(\"NEXT\", Token.NEXT);\n        map.put(\"MINEXTENTS\", Token.MINEXTENTS);\n        map.put(\"MAXEXTENTS\", Token.MAXEXTENTS);\n        map.put(\"MAXSIZE\", Token.MAXSIZE);\n        map.put(\"PCTINCREASE\", Token.PCTINCREASE);\n        map.put(\"FLASH_CACHE\", Token.FLASH_CACHE);\n        map.put(\"CELL_FLASH_CACHE\", Token.CELL_FLASH_CACHE);\n        map.put(\"NONE\", Token.NONE);\n        map.put(\"LOB\", Token.LOB);\n        map.put(\"STORE\", Token.STORE);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"CHUNK\", Token.CHUNK);\n        map.put(\"CACHE\", Token.CACHE);\n        map.put(\"NOCACHE\", Token.NOCACHE);\n        map.put(\"LOGGING\", Token.LOGGING);\n        map.put(\"NOCOMPRESS\", Token.NOCOMPRESS);\n        map.put(\"KEEP_DUPLICATES\", Token.KEEP_DUPLICATES);\n        map.put(\"EXCEPTIONS\", Token.EXCEPTIONS);\n        map.put(\"PURGE\", Token.PURGE);\n        map.put(\"INITIALLY\", Token.INITIALLY);\n\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"TABLESPACE\", Token.TABLESPACE);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"CASCADE\", Token.CASCADE);\n        map.put(\"MATCHED\", Token.MATCHED);\n\n        map.put(\"，\", Token.COMMA);\n        map.put(\"（\", Token.LPAREN);\n        map.put(\"）\", Token.RPAREN);\n\n        ORACLE_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return ORACLE_KEYWORDS;\n    }\n\n    public OracleLexer(char[] input, int inputLength, boolean skipComment) {\n        super(input, inputLength, skipComment);\n        dbType = DbType.oracle;\n    }\n\n    public OracleLexer(String input) {\n        super(input);\n        this.skipComment = true;\n        this.keepComments = true;\n        dbType = DbType.oracle;\n    }\n\n    public OracleLexer(String input, SQLParserFeature... features) {\n        super(input);\n        this.skipComment = true;\n        this.keepComments = true;\n        dbType = DbType.oracle;\n\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    public void scanVariable() {\n        final char c0 = ch;\n        if (c0 != ':' && c0 != '#' && c0 != '$') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n        char ch;\n\n        boolean quoteFlag = false;\n        boolean mybatisFlag = false;\n\n        char c1 = charAt(pos + 1);\n        if (c0 == ':' && c1 == ' ') {\n            pos++;\n            bufPos = 2;\n            c1 = charAt(pos + 1);\n        }\n\n        if (c1 == '\"') {\n            pos++;\n            bufPos++;\n            quoteFlag = true;\n        } else if (c1 == '{') {\n            pos++;\n            bufPos++;\n            mybatisFlag = true;\n        }\n\n        if (c0 == ':' && c1 >= '0' && c1 <= '9') {\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (ch < '0' || ch > '9') {\n                    break;\n                }\n\n                bufPos++;\n            }\n        } else {\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (!isIdentifierChar(ch) && ch != ':') {\n                    break;\n                }\n\n                bufPos++;\n            }\n        }\n\n        if (quoteFlag) {\n            if (ch != '\"') {\n                throw new ParserException(\"syntax error. \" + info());\n            }\n            ++pos;\n            bufPos++;\n        } else if (mybatisFlag) {\n            if (ch != '}') {\n                throw new ParserException(\"syntax error\" + info());\n            }\n            ++pos;\n            bufPos++;\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = addSymbol();\n        Token tok = keywords.getKeyword(stringVal);\n        if (tok != null) {\n            token = tok;\n        } else {\n            token = Token.VARIANT;\n        }\n    }\n\n    protected void scanVariable_at() {\n        scanChar();\n\n        if (ch == '@') {\n            scanChar();\n            token = Token.MONKEYS_AT_AT;\n        } else {\n            token = Token.MONKEYS_AT;\n        }\n    }\n\n    public void scanComment() {\n        if (ch != '/' && ch != '-') {\n            throw new IllegalStateException();\n        }\n\n        mark = pos;\n        bufPos = 0;\n        scanChar();\n\n        // /*+ */\n        if (ch == '*') {\n            scanChar();\n            bufPos++;\n\n            while (ch == ' ') {\n                scanChar();\n                bufPos++;\n            }\n\n            boolean isHint = false;\n            int startHintSp = bufPos + 1;\n            if (ch == '+') {\n                isHint = true;\n                scanChar();\n                bufPos++;\n            }\n\n            while (!isEOF()) {\n                if (ch == '*' && charAt(pos + 1) == '/') {\n                    bufPos += 2;\n                    scanChar();\n                    scanChar();\n                    break;\n                }\n\n                scanChar();\n                bufPos++;\n            }\n\n            if (isHint) {\n                stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 1);\n                token = Token.HINT;\n            } else {\n                stringVal = subString(mark, bufPos + 1);\n                token = Token.MULTI_LINE_COMMENT;\n                commentCount++;\n                if (keepComments) {\n                    addComment(stringVal);\n                }\n            }\n\n            if (token != Token.HINT && !isAllowComment()) {\n                throw new NotAllowCommentException();\n            }\n\n            return;\n        }\n\n        if (!isAllowComment()) {\n            throw new NotAllowCommentException();\n        }\n\n        if (ch == '/' || ch == '-') {\n            scanChar();\n            bufPos++;\n\n            for (; ; ) {\n                if (ch == '\\r') {\n                    if (charAt(pos + 1) == '\\n') {\n                        bufPos += 2;\n                        scanChar();\n                        break;\n                    }\n                    bufPos++;\n                    break;\n                } else if (ch == EOI) {\n                    break;\n                }\n\n                if (ch == '\\n') {\n                    scanChar();\n                    bufPos++;\n                    break;\n                }\n\n                scanChar();\n                bufPos++;\n            }\n\n            stringVal = subString(mark, ch != EOI ? bufPos : bufPos + 1);\n            token = Token.LINE_COMMENT;\n            commentCount++;\n            if (keepComments) {\n                addComment(stringVal);\n            }\n            endOfComment = isEOF();\n        }\n    }\n\n    public void scanNumber() {\n        mark = pos;\n\n        if (ch == '-') {\n            bufPos++;\n            ch = charAt(++pos);\n        }\n\n        while (ch >= '0' && ch <= '9') {\n            bufPos++;\n            ch = charAt(++pos);\n        }\n\n        boolean isDouble = false;\n\n        if (ch == '.') {\n            if (charAt(pos + 1) == '.') {\n                token = Token.LITERAL_INT;\n                return;\n            }\n            bufPos++;\n            ch = charAt(++pos);\n            isDouble = true;\n\n            while (ch >= '0' && ch <= '9') {\n                bufPos++;\n                ch = charAt(++pos);\n            }\n        }\n\n        if ((ch == 'e' || ch == 'E') && isDigit2(charAt(pos + 1))) {\n            bufPos++;\n            ch = charAt(++pos);\n\n            if (ch == '+' || ch == '-') {\n                bufPos++;\n                ch = charAt(++pos);\n            }\n\n            while (ch >= '0' && ch <= '9') {\n                bufPos++;\n                ch = charAt(++pos);\n            }\n\n            isDouble = true;\n        }\n\n        if (ch == 'f' || ch == 'F') {\n            token = Token.BINARY_FLOAT;\n            scanChar();\n            return;\n        }\n\n        if (ch == 'd' || ch == 'D') {\n            token = Token.BINARY_DOUBLE;\n            scanChar();\n            return;\n        }\n\n        if (isDouble) {\n            token = Token.LITERAL_FLOAT;\n        } else {\n            token = Token.LITERAL_INT;\n        }\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = ORACLE_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleProcedureDataType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleProcedureDataType extends SQLDataTypeImpl {\n    private boolean isStatic;\n    private final List<SQLParameter> parameters = new ArrayList<SQLParameter>();\n\n    private SQLStatement block;\n\n    public boolean isStatic() {\n        return isStatic;\n    }\n\n    public void setStatic(boolean aStatic) {\n        isStatic = aStatic;\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    public OracleProcedureDataType clone() {\n        OracleProcedureDataType x = new OracleProcedureDataType();\n        cloneTo(x);\n\n        x.isStatic = isStatic;\n        for (SQLParameter parameter : parameters) {\n            SQLParameter p2 = parameter.clone();\n            p2.setParent(x);\n            x.parameters.add(p2);\n        }\n\n        return x;\n    }\n\n    public SQLStatement getBlock() {\n        return block;\n    }\n\n    public void setBlock(SQLStatement block) {\n        if (block != null) {\n            block.setParent(this);\n        }\n        this.block = block;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.*;\n\npublic class OracleSelectParser extends SQLSelectParser {\n    public OracleSelectParser(String sql) {\n        super(new OracleExprParser(sql));\n    }\n\n    public OracleSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public OracleSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public SQLSelect select() {\n        SQLSelect select = new SQLSelect();\n\n        if (lexer.token() == Token.WITH) {\n            SQLWithSubqueryClause with = this.parseWith();\n            select.setWithSubQuery(with);\n        }\n\n        SQLSelectQuery query = query();\n        select.setQuery(query);\n\n        SQLOrderBy orderBy = this.parseOrderBy();\n\n        OracleSelectQueryBlock queryBlock = null;\n        if (query instanceof SQLSelectQueryBlock) {\n            queryBlock = (OracleSelectQueryBlock) query;\n\n            if (queryBlock.getOrderBy() == null) {\n                queryBlock.setOrderBy(orderBy);\n            } else {\n                select.setOrderBy(orderBy);\n            }\n\n            if (orderBy != null) {\n                parseFetchClause(queryBlock);\n\n                select.setQuery(\n                        this.queryRest(queryBlock, true));\n            }\n        } else {\n            select.setOrderBy(orderBy);\n        }\n\n        if (lexer.token() == (Token.FOR)) {\n            if (queryBlock == null) {\n                throw new ParserException(\"TODO. \" + lexer.info());\n            }\n\n            lexer.nextToken();\n            accept(Token.UPDATE);\n\n            queryBlock.setForUpdate(true);\n\n            // OracleSelectForUpdate forUpdate = new OracleSelectForUpdate();\n\n            if (lexer.token() == Token.OF) {\n                lexer.nextToken();\n                this.exprParser.exprList(queryBlock.getForUpdateOf(), queryBlock);\n            } else if (lexer.token() == Token.LPAREN\n                    && queryBlock.isForUpdate()) {\n                this.exprParser.exprList(queryBlock.getForUpdateOf(), queryBlock);\n            }\n\n            if (lexer.token() == Token.NOWAIT) {\n                lexer.nextToken();\n                queryBlock.setNoWait(true);\n            } else if (lexer.token() == Token.WAIT) {\n                lexer.nextToken();\n                queryBlock.setWaitTime(this.exprParser.primary());\n            } else if (lexer.identifierEquals(\"SKIP\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOCKED\");\n                queryBlock.setSkipLocked(true);\n            }\n        }\n\n        if (lexer.token() == Token.ORDER) {\n            orderBy = this.exprParser.parseOrderBy();\n            if (queryBlock != null && queryBlock.getOrderBy() == null) {\n                queryBlock.setOrderBy(orderBy);\n            } else if (select.getOrderBy() == null) {\n                select.setOrderBy(orderBy);\n            } else {\n                throw new ParserException(\"illegal state.\");\n            }\n        }\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n\n            OracleSelectRestriction restriction = null;\n            if (lexer.identifierEquals(\"READ\")) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"ONLY\")) {\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n\n                restriction = new OracleSelectRestriction.ReadOnly();\n            } else if (lexer.token() == (Token.CHECK)) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"OPTION\")) {\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n\n                restriction = new OracleSelectRestriction.CheckOption();\n            } else {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.CONSTRAINT) {\n                lexer.nextToken();\n                String constraintName = lexer.stringVal();\n                SQLName constraint = new SQLIdentifierExpr(constraintName);\n                restriction.setConstraint(constraint);\n\n                lexer.nextToken();\n            }\n\n            select.setRestriction(restriction);\n        }\n\n        return select;\n    }\n\n    @Override\n    public SQLWithSubqueryClause parseWith() {\n        accept(Token.WITH);\n        SQLWithSubqueryClause subqueryFactoringClause = new SQLWithSubqueryClause();\n        for (; ; ) {\n            OracleWithSubqueryEntry entry = new OracleWithSubqueryEntry();\n\n            String alias = lexer.stringVal();\n            lexer.nextToken();\n            entry.setAlias(alias);\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                exprParser.names(entry.getColumns());\n                accept(Token.RPAREN);\n            }\n\n            accept(Token.AS);\n            accept(Token.LPAREN);\n            entry.setSubQuery(select());\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(\"SEARCH\")) {\n                lexer.nextToken();\n                SearchClause searchClause = new SearchClause();\n\n                if (lexer.token() != Token.IDENTIFIER) {\n                    throw new ParserException(\"syntax erorr : \" + lexer.token());\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.DEPTH)) {\n                    lexer.nextToken();\n                    searchClause.setType(SearchClause.Type.DEPTH);\n                } else if (lexer.identifierEquals(FnvHash.Constants.BREADTH)) {\n                    lexer.nextToken();\n                    searchClause.setType(SearchClause.Type.BREADTH);\n                } else {\n                    searchClause.setType(SearchClause.Type.valueOf(lexer.stringVal().toUpperCase()));\n                    lexer.nextToken();\n                }\n\n                acceptIdentifier(\"FIRST\");\n                accept(Token.BY);\n\n                searchClause.addItem(exprParser.parseSelectOrderByItem());\n\n                while (lexer.token() == (Token.COMMA)) {\n                    lexer.nextToken();\n                    searchClause.addItem(exprParser.parseSelectOrderByItem());\n                }\n\n                accept(Token.SET);\n\n                searchClause.setOrderingColumn((SQLIdentifierExpr) exprParser.name());\n\n                entry.setSearchClause(searchClause);\n            }\n\n            if (lexer.identifierEquals(\"CYCLE\")) {\n                lexer.nextToken();\n                CycleClause cycleClause = new CycleClause();\n                exprParser.exprList(cycleClause.getAliases(), cycleClause);\n                accept(Token.SET);\n                cycleClause.setMark(exprParser.expr());\n                accept(Token.TO);\n                cycleClause.setValue(exprParser.expr());\n                accept(Token.DEFAULT);\n                cycleClause.setDefaultValue(exprParser.expr());\n                entry.setCycleClause(cycleClause);\n            }\n\n            subqueryFactoringClause.addEntry(entry);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        return subqueryFactoringClause;\n    }\n\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            accept(Token.RPAREN);\n            select.setParenthesized(true);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        OracleSelectQueryBlock queryBlock = new OracleSelectQueryBlock();\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            parseHints(queryBlock);\n\n            if (lexer.token() == Token.DISTINCT) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.UNIQUE) {\n                queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.ALL) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                lexer.nextToken();\n            }\n\n            this.exprParser.parseHints(queryBlock.getHints());\n\n            parseSelectList(queryBlock);\n        }\n\n        parseInto(queryBlock);\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseHierachical(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        // connect by /  start 语法可能在group by之后，因此再次调用此函数\n        parseHierachical(queryBlock);\n\n        parseModelClause(queryBlock);\n\n        parseFetchClause(queryBlock);\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    public SQLSelectQuery queryRest(SQLSelectQuery selectQuery, boolean acceptUnion) {\n        if (!acceptUnion) {\n            return selectQuery;\n        }\n\n        if (lexer.token() == Token.UNION) {\n            do {\n                SQLUnionQuery union = new SQLUnionQuery();\n                union.setLeft(selectQuery);\n\n                lexer.nextToken();\n\n                if (lexer.token() == Token.ALL) {\n                    union.setOperator(SQLUnionOperator.UNION_ALL);\n                    lexer.nextToken();\n                } else if (lexer.token() == Token.DISTINCT) {\n                    union.setOperator(SQLUnionOperator.DISTINCT);\n                    lexer.nextToken();\n                }\n\n                SQLSelectQuery right = query(null, false);\n\n                union.setRight(right);\n\n                selectQuery = union;\n\n            } while (lexer.token() == Token.UNION);\n\n            selectQuery = queryRest(selectQuery, true);\n\n            return selectQuery;\n        }\n\n        if (lexer.token() == Token.INTERSECT) {\n            lexer.nextToken();\n\n            SQLUnionQuery union = new SQLUnionQuery();\n            union.setLeft(selectQuery);\n\n            union.setOperator(SQLUnionOperator.INTERSECT);\n\n            SQLSelectQuery right = this.query(null, false);\n            union.setRight(right);\n\n            return queryRest(union, true);\n        }\n\n        if (lexer.token() == Token.MINUS) {\n            lexer.nextToken();\n\n            SQLUnionQuery union = new SQLUnionQuery();\n            union.setLeft(selectQuery);\n\n            union.setOperator(SQLUnionOperator.MINUS);\n\n            SQLSelectQuery right = this.query(null, false);\n            union.setRight(right);\n\n            return queryRest(union, true);\n        }\n\n        return selectQuery;\n    }\n\n    private void parseModelClause(OracleSelectQueryBlock queryBlock) {\n        Lexer.SavePoint savePoint = lexer.mark();\n\n        if (!lexer.identifierEquals(FnvHash.Constants.MODEL)) {\n            return;\n        }\n\n        lexer.nextToken();\n\n        ModelClause model = new ModelClause();\n        parseCellReferenceOptions(model.getCellReferenceOptions());\n\n        if (lexer.identifierEquals(FnvHash.Constants.RETURN)) {\n            lexer.nextToken();\n            ReturnRowsClause returnRowsClause = new ReturnRowsClause();\n            if (lexer.token() == Token.ALL) {\n                lexer.nextToken();\n                returnRowsClause.setAll(true);\n            } else {\n                acceptIdentifier(\"UPDATED\");\n            }\n            acceptIdentifier(\"ROWS\");\n\n            model.setReturnRowsClause(returnRowsClause);\n        }\n\n        while (lexer.identifierEquals(FnvHash.Constants.REFERENCE)) {\n            ReferenceModelClause referenceModelClause = new ReferenceModelClause();\n            lexer.nextToken();\n\n            SQLExpr name = expr();\n            referenceModelClause.setName(name);\n\n            accept(Token.ON);\n            accept(Token.LPAREN);\n            SQLSelect subQuery = this.select();\n            accept(Token.RPAREN);\n            referenceModelClause.setSubQuery(subQuery);\n\n            parseModelColumnClause(referenceModelClause);\n\n            parseCellReferenceOptions(referenceModelClause.getCellReferenceOptions());\n\n            model.getReferenceModelClauses().add(referenceModelClause);\n        }\n\n        parseMainModelClause(model);\n\n        queryBlock.setModelClause(model);\n    }\n\n    private void parseMainModelClause(ModelClause modelClause) {\n        MainModelClause mainModel = new MainModelClause();\n\n        if (lexer.identifierEquals(\"MAIN\")) {\n            lexer.nextToken();\n            mainModel.setMainModelName(expr());\n        }\n\n        ModelColumnClause modelColumnClause = new ModelColumnClause();\n        parseQueryPartitionClause(modelColumnClause);\n        mainModel.setModelColumnClause(modelColumnClause);\n\n        acceptIdentifier(\"DIMENSION\");\n        accept(Token.BY);\n        accept(Token.LPAREN);\n        for (; ; ) {\n            if (lexer.token() == Token.RPAREN) {\n                lexer.nextToken();\n                break;\n            }\n\n            ModelColumn column = new ModelColumn();\n            column.setExpr(expr());\n            column.setAlias(as());\n            modelColumnClause.getDimensionByColumns().add(column);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n        }\n\n        acceptIdentifier(\"MEASURES\");\n        accept(Token.LPAREN);\n        for (; ; ) {\n            if (lexer.token() == Token.RPAREN) {\n                lexer.nextToken();\n                break;\n            }\n\n            ModelColumn column = new ModelColumn();\n            column.setExpr(expr());\n            column.setAlias(as());\n            modelColumnClause.getMeasuresColumns().add(column);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n        }\n        mainModel.setModelColumnClause(modelColumnClause);\n\n        parseCellReferenceOptions(mainModel.getCellReferenceOptions());\n\n        parseModelRulesClause(mainModel);\n\n        modelClause.setMainModel(mainModel);\n    }\n\n    private void parseModelRulesClause(MainModelClause mainModel) {\n        ModelRulesClause modelRulesClause = new ModelRulesClause();\n        if (lexer.identifierEquals(\"RULES\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.UPDATE) {\n                modelRulesClause.getOptions().add(ModelRuleOption.UPDATE);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"UPSERT\")) {\n                modelRulesClause.getOptions().add(ModelRuleOption.UPSERT);\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"AUTOMATIC\")) {\n                lexer.nextToken();\n                accept(Token.ORDER);\n                modelRulesClause.getOptions().add(ModelRuleOption.AUTOMATIC_ORDER);\n            } else if (lexer.identifierEquals(\"SEQUENTIAL\")) {\n                lexer.nextToken();\n                accept(Token.ORDER);\n                modelRulesClause.getOptions().add(ModelRuleOption.SEQUENTIAL_ORDER);\n            }\n        }\n\n        if (lexer.identifierEquals(\"ITERATE\")) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            modelRulesClause.setIterate(expr());\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(\"UNTIL\")) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                modelRulesClause.setUntil(expr());\n                accept(Token.RPAREN);\n            }\n        }\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            if (lexer.token() == Token.RPAREN) {\n                lexer.nextToken();\n                break;\n            }\n\n            CellAssignmentItem item = new CellAssignmentItem();\n            if (lexer.token() == Token.UPDATE) {\n                item.setOption(ModelRuleOption.UPDATE);\n            } else if (lexer.identifierEquals(\"UPSERT\")) {\n                item.setOption(ModelRuleOption.UPSERT);\n            }\n\n            item.setCellAssignment(parseCellAssignment());\n            item.setOrderBy(this.parseOrderBy());\n            accept(Token.EQ);\n\n            SQLExpr expr = this.expr();\n            item.setExpr(expr);\n\n            modelRulesClause.getCellAssignmentItems().add(item);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n        }\n\n        mainModel.setModelRulesClause(modelRulesClause);\n    }\n\n    private CellAssignment parseCellAssignment() {\n        CellAssignment cellAssignment = new CellAssignment();\n\n        cellAssignment.setMeasureColumn(this.exprParser.name());\n        accept(Token.LBRACKET);\n        this.exprParser.exprList(cellAssignment.getConditions(), cellAssignment);\n        accept(Token.RBRACKET);\n\n        return cellAssignment;\n    }\n\n    private void parseQueryPartitionClause(ModelColumnClause modelColumnClause) {\n        if (lexer.token() == Token.PARTITION) {\n            QueryPartitionClause queryPartitionClause = new QueryPartitionClause();\n\n            lexer.nextToken();\n            accept(Token.BY);\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                exprParser.exprList(queryPartitionClause.getExprList(), queryPartitionClause);\n                accept(Token.RPAREN);\n            } else {\n                exprParser.exprList(queryPartitionClause.getExprList(), queryPartitionClause);\n            }\n            modelColumnClause.setQueryPartitionClause(queryPartitionClause);\n        }\n    }\n\n    private void parseModelColumnClause(ReferenceModelClause referenceModelClause) {\n        throw new ParserException();\n    }\n\n    private void parseCellReferenceOptions(List<CellReferenceOption> options) {\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NAV\");\n            options.add(CellReferenceOption.IgnoreNav);\n        } else if (lexer.identifierEquals(FnvHash.Constants.KEEP)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NAV\");\n            options.add(CellReferenceOption.KeepNav);\n        }\n\n        if (lexer.token() == Token.UNIQUE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"DIMENSION\")) {\n                lexer.nextToken();\n                options.add(CellReferenceOption.UniqueDimension);\n            } else {\n                acceptIdentifier(\"SINGLE\");\n                acceptIdentifier(\"REFERENCE\");\n                options.add(CellReferenceOption.UniqueDimension);\n            }\n        }\n    }\n\n    @Override\n    public SQLTableSource parseTableSource(boolean forFrom) {\n        SQLTableSource tableSource = parseTableSourcePrimary(forFrom);\n        if (tableSource instanceof OracleSelectTableSource) {\n            return parseTableSourceRest((OracleSelectTableSource) tableSource);\n        }\n\n        return parseTableSourceRest(tableSource);\n    }\n\n    public SQLTableSource parseTableSourcePrimary(boolean forFrom) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            OracleSelectTableSource tableSource;\n            if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH) {\n                tableSource = new OracleSelectSubqueryTableSource(select());\n            } else if (lexer.token() == Token.LPAREN) {\n                tableSource = (OracleSelectTableSource) parseTableSource();\n            } else if (lexer.token() == Token.IDENTIFIER\n                    || lexer.token() == Token.LITERAL_ALIAS) {\n                SQLTableSource identTable = parseTableSource();\n                accept(Token.RPAREN);\n                parsePivot(identTable);\n                return identTable;\n            } else {\n                throw new ParserException(\"TODO :\" + lexer.info());\n            }\n\n            accept(Token.RPAREN);\n            if (forFrom) {\n                parsePivot(tableSource);\n                return tableSource;\n            }\n            if ((lexer.token() == Token.UNION || lexer.token() == Token.MINUS || lexer.token() == Token.EXCEPT)\n                    && tableSource instanceof OracleSelectSubqueryTableSource) {\n                ((OracleSelectSubqueryTableSource) tableSource).getSelect().getQueryBlock().setParenthesized(true);\n                OracleSelectSubqueryTableSource selectSubqueryTableSource = (OracleSelectSubqueryTableSource) tableSource;\n                SQLSelect select = selectSubqueryTableSource.getSelect();\n                SQLSelectQuery selectQuery = this.queryRest(select.getQuery(), true);\n                select.setQuery(selectQuery);\n            }\n\n            parsePivot(tableSource);\n\n            return tableSource;\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        OracleSelectTableReference tableReference = new OracleSelectTableReference();\n\n        if (lexer.identifierEquals(\"ONLY\")) {\n            lexer.nextToken();\n            tableReference.setOnly(true);\n            accept(Token.LPAREN);\n            parseTableSourceQueryTableExpr(tableReference);\n            accept(Token.RPAREN);\n        } else {\n            parseTableSourceQueryTableExpr(tableReference);\n            parsePivot(tableReference);\n        }\n\n        return tableReference;\n    }\n\n    private void parseTableSourceQueryTableExpr(OracleSelectTableReference tableReference) {\n        tableReference.setExpr(this.exprParser.expr());\n\n//        {\n//            FlashbackQueryClause clause = flashback();\n//            tableReference.setFlashback(clause);\n//        }\n\n        if (lexer.identifierEquals(\"SAMPLE\")) {\n            lexer.nextToken();\n\n            SampleClause sample = new SampleClause();\n\n            if (lexer.identifierEquals(\"BLOCK\")) {\n                sample.setBlock(true);\n                lexer.nextToken();\n            }\n\n            accept(Token.LPAREN);\n            this.exprParser.exprList(sample.getPercent(), sample);\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(\"SEED\")) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                sample.setSeedValue(expr());\n                accept(Token.RPAREN);\n            }\n\n            tableReference.setSampleClause(sample);\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            PartitionExtensionClause partition = new PartitionExtensionClause();\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                partition.setPartition(exprParser.name());\n                accept(Token.RPAREN);\n            } else if (lexer.token() == Token.BY) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                partition.setPartition(exprParser.name());\n                accept(Token.RPAREN);\n            } else {\n                accept(Token.FOR);\n                accept(Token.LPAREN);\n                exprParser.names(partition.getFor());\n                accept(Token.RPAREN);\n            }\n\n            tableReference.setPartition(partition);\n        }\n\n        if (lexer.identifierEquals(\"SUBPARTITION\")) {\n            lexer.nextToken();\n            PartitionExtensionClause partition = new PartitionExtensionClause();\n            partition.setSubPartition(true);\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                partition.setPartition(exprParser.name());\n                accept(Token.RPAREN);\n            } else {\n                accept(Token.FOR);\n                accept(Token.LPAREN);\n                exprParser.names(partition.getFor());\n                accept(Token.RPAREN);\n            }\n\n            tableReference.setPartition(partition);\n        }\n\n        if (lexer.identifierEquals(\"VERSIONS\")) {\n            SQLBetweenExpr betweenExpr = new SQLBetweenExpr();\n            betweenExpr.setTestExpr(new SQLIdentifierExpr(\"VERSIONS\"));\n            lexer.nextToken();\n\n            accept(Token.BETWEEN);\n\n            SQLFlashbackExpr start = new SQLFlashbackExpr();\n            if (lexer.identifierEquals(\"SCN\")) {\n                lexer.nextToken();\n                start.setType(SQLFlashbackExpr.Type.SCN);\n            } else {\n                acceptIdentifier(\"TIMESTAMP\");\n                start.setType(SQLFlashbackExpr.Type.TIMESTAMP);\n            }\n\n            SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) exprParser.expr();\n            if (binaryExpr.getOperator() != SQLBinaryOperator.BooleanAnd) {\n                throw new ParserException(\"syntax error : \" + binaryExpr.getOperator() + \", \" + lexer.info());\n            }\n\n            start.setExpr(binaryExpr.getLeft());\n\n            betweenExpr.setBeginExpr(start);\n            betweenExpr.setEndExpr(binaryExpr.getRight());\n\n            tableReference.setFlashback(betweenExpr);\n        }\n\n    }\n\n    private SQLExpr flashback() {\n        accept(Token.OF);\n        if (lexer.identifierEquals(\"SCN\")) {\n            lexer.nextToken();\n            return new SQLFlashbackExpr(SQLFlashbackExpr.Type.SCN, this.expr());\n        } else if (lexer.identifierEquals(\"SNAPSHOT\")) {\n            return this.expr();\n        } else {\n            lexer.nextToken();\n            return new SQLFlashbackExpr(SQLFlashbackExpr.Type.TIMESTAMP, this.expr());\n        }\n    }\n\n    protected SQLTableSource primaryTableSourceRest(SQLTableSource tableSource) {\n        if (tableSource instanceof OracleSelectTableSource) {\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.OF) {\n                    ((OracleSelectTableSource) tableSource).setFlashback(flashback());\n                }\n\n                tableSource.setAlias(tableAlias());\n            }\n        }\n\n        return tableSource;\n    }\n\n    protected SQLTableSource parseTableSourceRest(OracleSelectTableSource tableSource) {\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.OF) {\n                tableSource.setFlashback(flashback());\n                return parseTableSourceRest(tableSource);\n            }\n\n            tableSource.setAlias(tableAlias(true));\n        } else if ((tableSource.getAlias() == null) || (tableSource.getAlias().length() == 0)) {\n            if (lexer.token() != Token.LEFT && lexer.token() != Token.RIGHT && lexer.token() != Token.FULL) {\n                final String tableAlias = tableAlias();\n                tableSource.setAlias(tableAlias);\n            }\n        }\n\n        if (lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(tableSource.getHints());\n        }\n\n        SQLJoinTableSource.JoinType joinType = null;\n\n        if (lexer.token() == Token.LEFT) {\n            lexer.nextToken();\n            if (lexer.token() == Token.OUTER) {\n                lexer.nextToken();\n            }\n            accept(Token.JOIN);\n            joinType = SQLJoinTableSource.JoinType.LEFT_OUTER_JOIN;\n        }\n\n        if (lexer.token() == Token.RIGHT) {\n            lexer.nextToken();\n            if (lexer.token() == Token.OUTER) {\n                lexer.nextToken();\n            }\n            accept(Token.JOIN);\n            joinType = SQLJoinTableSource.JoinType.RIGHT_OUTER_JOIN;\n        }\n\n        if (lexer.token() == Token.FULL) {\n            lexer.nextToken();\n            if (lexer.token() == Token.OUTER) {\n                lexer.nextToken();\n            }\n            accept(Token.JOIN);\n            joinType = SQLJoinTableSource.JoinType.FULL_OUTER_JOIN;\n        }\n\n        boolean natural = lexer.identifierEquals(FnvHash.Constants.NATURAL);\n        if (natural) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.INNER) {\n            lexer.nextToken();\n            accept(Token.JOIN);\n            if (natural) {\n                joinType = SQLJoinTableSource.JoinType.NATURAL_INNER_JOIN;\n            } else {\n                joinType = SQLJoinTableSource.JoinType.INNER_JOIN;\n            }\n        }\n        if (lexer.token() == Token.CROSS) {\n            lexer.nextToken();\n            accept(Token.JOIN);\n            joinType = SQLJoinTableSource.JoinType.CROSS_JOIN;\n        }\n\n        if (lexer.token() == Token.JOIN) {\n            lexer.nextToken();\n            if (natural) {\n                joinType = SQLJoinTableSource.JoinType.NATURAL_JOIN;\n            } else {\n                joinType = SQLJoinTableSource.JoinType.JOIN;\n            }\n        }\n\n        if (lexer.token() == (Token.COMMA)) {\n            lexer.nextToken();\n            joinType = SQLJoinTableSource.JoinType.COMMA;\n        }\n\n        if (joinType != null) {\n            OracleSelectJoin join = new OracleSelectJoin();\n            join.setLeft(tableSource);\n            join.setJoinType(joinType);\n\n            SQLTableSource right;\n            right = parseTableSourcePrimary(false);\n            // Alias is already set for \"... JOIN (tbl1 alias1) ON ...\" syntax,\n            // so skip setting alias\n            if (right.getAlias() == null) {\n                String tableAlias = tableAlias();\n                right.setAlias(tableAlias);\n            }\n            join.setRight(right);\n\n            if (lexer.token() == Token.ON) {\n                lexer.nextToken();\n                join.setCondition(this.exprParser.expr());\n\n                if (lexer.token() == Token.ON\n                        && tableSource instanceof SQLJoinTableSource\n                        && ((SQLJoinTableSource) tableSource).getCondition() == null) {\n                    lexer.nextToken();\n                    SQLExpr leftCondidition = this.exprParser.expr();\n                    ((SQLJoinTableSource) tableSource).setCondition(leftCondidition);\n                }\n            } else if (lexer.token() == Token.USING) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                this.exprParser.exprList(join.getUsing(), join);\n                accept(Token.RPAREN);\n            }\n            if (lexer.hasComment() && lexer.isKeepComments()) {\n                join.addAfterComment(lexer.readAndResetComments());\n            }\n            parsePivot(join);\n\n            return parseTableSourceRest(join);\n        } else {\n            if (lexer.identifierEquals(FnvHash.Constants.PIVOT)) {\n                parsePivot(tableSource);\n            }\n        }\n\n        return tableSource;\n    }\n\n    protected void parseInto(OracleSelectQueryBlock x) {\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.FROM) {\n                return;\n            }\n\n            SQLExpr expr = expr();\n            if (lexer.token() != Token.COMMA) {\n                x.setInto(expr);\n                return;\n            }\n            SQLListExpr list = new SQLListExpr();\n            list.addItem(expr);\n            while (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                list.addItem(expr());\n            }\n            x.setInto(list);\n        }\n    }\n\n    private void parseHints(OracleSelectQueryBlock queryBlock) {\n        this.exprParser.parseHints(queryBlock.getHints());\n    }\n\n    protected void parsePivot(SQLTableSource tableSource) {\n        SQLSelectItem item;\n        if (lexer.identifierEquals(FnvHash.Constants.PIVOT)) {\n            lexer.nextToken();\n\n            SQLPivot pivot = new SQLPivot();\n\n            if (lexer.identifierEquals(\"XML\")) {\n                lexer.nextToken();\n                pivot.setXml(true);\n            }\n\n            accept(Token.LPAREN);\n            while (true) {\n                item = new SQLSelectItem();\n                item.setExpr((SQLAggregateExpr) this.exprParser.expr());\n                item.setAlias(as());\n                pivot.addItem(item);\n\n                if (!(lexer.token() == (Token.COMMA))) {\n                    break;\n                }\n                lexer.nextToken();\n            }\n\n            accept(Token.FOR);\n\n            if (lexer.token() == (Token.LPAREN)) {\n                lexer.nextToken();\n                while (true) {\n                    pivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                    lexer.nextToken();\n\n                    if (!(lexer.token() == (Token.COMMA))) {\n                        break;\n                    }\n                    lexer.nextToken();\n                }\n\n                accept(Token.RPAREN);\n            } else {\n                pivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                lexer.nextToken();\n            }\n\n            accept(Token.IN);\n            accept(Token.LPAREN);\n//            if (lexer.token() == (Token.LPAREN)) {\n//                throw new ParserException(\"TODO. \" + lexer.info());\n//            }\n\n            if (lexer.token() == (Token.SELECT)) {\n                SQLExpr expr = this.exprParser.expr();\n                item = new SQLSelectItem();\n                item.setExpr(expr);\n                item.setParent(pivot);\n                pivot.getPivotIn().add(item);\n            } else {\n                for (; ; ) {\n                    item = new SQLSelectItem();\n                    item.setExpr(this.exprParser.expr());\n                    item.setAlias(as());\n                    item.setParent(pivot);\n                    pivot.getPivotIn().add(item);\n\n                    if (lexer.token() != Token.COMMA) {\n                        break;\n                    }\n\n                    lexer.nextToken();\n                }\n            }\n\n            accept(Token.RPAREN);\n\n            accept(Token.RPAREN);\n\n            tableSource.setPivot(pivot);\n        } else if (lexer.identifierEquals(\"UNPIVOT\")) {\n            lexer.nextToken();\n\n            SQLUnpivot unPivot = new SQLUnpivot();\n            if (lexer.identifierEquals(\"INCLUDE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"NULLS\");\n                unPivot.setNullsIncludeType(SQLUnpivot.NullsIncludeType.INCLUDE_NULLS);\n            } else if (lexer.identifierEquals(\"EXCLUDE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"NULLS\");\n                unPivot.setNullsIncludeType(SQLUnpivot.NullsIncludeType.EXCLUDE_NULLS);\n            }\n\n            accept(Token.LPAREN);\n\n            if (lexer.token() == (Token.LPAREN)) {\n                lexer.nextToken();\n                this.exprParser.exprList(unPivot.getItems(), unPivot);\n                accept(Token.RPAREN);\n            } else {\n                unPivot.addItem(this.exprParser.expr());\n            }\n\n            accept(Token.FOR);\n\n            if (lexer.token() == (Token.LPAREN)) {\n                lexer.nextToken();\n                while (true) {\n                    unPivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                    lexer.nextToken();\n\n                    if (!(lexer.token() == (Token.COMMA))) {\n                        break;\n                    }\n                    lexer.nextToken();\n                }\n\n                accept(Token.RPAREN);\n            } else {\n                unPivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                lexer.nextToken();\n            }\n\n            accept(Token.IN);\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                item = new SQLSelectItem(this.expr(), new ArrayList<>(), false);\n                if (lexer.token() == (Token.AS)) {\n                    lexer.nextToken();\n                    if (lexer.token() == (Token.LPAREN)) {\n                        lexer.nextToken();\n                        for (; ; ) {\n                            item.getAliasList().add(alias());\n                            if (lexer.token() != Token.COMMA) {\n                                break;\n                            }\n\n                            lexer.nextToken();\n                        }\n                        accept(Token.RPAREN);\n                    } else {\n                        lexer.setToken(Token.LITERAL_ALIAS);\n                        item.setAlias(alias());\n                    }\n                }\n                unPivot.getPivotIn().add(item);\n\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                }\n\n                lexer.nextToken();\n            }\n\n            accept(Token.RPAREN);\n\n            accept(Token.RPAREN);\n\n            tableSource.setUnpivot(unPivot);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OraclePartitionSingle;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.NestedTablePartitionSpec;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.TableSpaceItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.UpdateIndexesClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement.LockMode;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.TABLE;\n\npublic class OracleStatementParser extends SQLStatementParser {\n    public OracleStatementParser(String sql) {\n        super(new OracleExprParser(sql));\n    }\n\n    public OracleStatementParser(String sql, SQLParserFeature... features) {\n        super(new OracleExprParser(sql, features));\n    }\n\n    public OracleStatementParser(Lexer lexer) {\n        super(new OracleExprParser(lexer));\n    }\n\n    @Override\n    public OracleExprParser getExprParser() {\n        return (OracleExprParser) exprParser;\n    }\n\n    public OracleCreateTableParser getSQLCreateTableParser() {\n        return new OracleCreateTableParser(lexer);\n    }\n\n    protected void parseInsert0Hints(SQLInsertInto insertStatement, boolean isInsert) {\n        if (insertStatement instanceof OracleInsertStatement) {\n            OracleInsertStatement stmt = (OracleInsertStatement) insertStatement;\n            this.getExprParser().parseHints(stmt.getHints());\n        } else {\n            List<SQLHint> hints = new ArrayList<>(1);\n            this.getExprParser().parseHints(hints);\n        }\n    }\n\n    public void parseStatementList(List<SQLStatement> statementList, int max, SQLObject parent) {\n        for (; ; ) {\n            if (max != -1) {\n                if (statementList.size() >= max) {\n                    return;\n                }\n            }\n\n            if (lexer.token() == Token.EOF) {\n                return;\n            }\n            if (lexer.token() == Token.END) {\n                return;\n            }\n            if (lexer.token() == Token.ELSE) {\n                return;\n            }\n\n            if (lexer.token() == (Token.SEMI)) {\n                lexer.nextToken();\n                if (!statementList.isEmpty()) {\n                    SQLStatement lastStmt = statementList.get(statementList.size() - 1);\n                    lastStmt.setAfterSemi(true);\n                }\n                continue;\n            }\n\n            if (lexer.token() == (Token.SELECT)) {\n                SQLStatement stmt = new SQLSelectStatement(new OracleSelectParser(this.exprParser).select(), DbType.oracle);\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == (Token.UPDATE)) {\n                SQLStatement stmt = parseUpdateStatement();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == (Token.CREATE)) {\n                SQLStatement stmt = parseCreate();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.INSERT) {\n                SQLStatement stmt = parseInsert();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == (Token.DELETE)) {\n                SQLStatement stmt = parseDeleteStatement();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == (Token.GET)) {\n                SQLStatement stmt = parseGetDiagnosticsStatement();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == (Token.SLASH)) {\n                lexer.nextToken();\n\n                SQLStatement stmt = new SQLScriptCommitStatement();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.ALTER) {\n                SQLStatement stmt = parserAlter();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.WITH) {\n                SQLSelectStatement stmt = new SQLSelectStatement(this.createSQLSelectParser().select(), dbType);\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.LBRACE || lexer.identifierEquals(\"CALL\")) {\n                SQLStatement stmt = parseCall();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.MERGE) {\n                SQLStatement stmt = parseMerge();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.BEGIN\n                    || lexer.token() == Token.DECLARE) {\n                SQLStatement stmt = parseBlock();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.LOCK) {\n                SQLStatement stmt = parseLock();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.TRUNCATE) {\n                SQLStatement stmt = parseTruncate();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.VARIANT) {\n                SQLExpr variant = this.exprParser.primary();\n                if (variant instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) variant;\n                    if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) {\n                        SQLSetStatement stmt = new SQLSetStatement(binaryOpExpr.getLeft(), binaryOpExpr.getRight(), getDbType());\n                        stmt.setParent(parent);\n                        statementList.add(stmt);\n                        continue;\n                    }\n                }\n                accept(Token.COLONEQ);\n                SQLExpr value = this.exprParser.expr();\n\n                SQLSetStatement stmt = new SQLSetStatement(variant, value, getDbType());\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.EXCEPTION) {\n                SQLExceptionStatement stmt = this.parseException();\n                stmt.setParent(parent);\n                if (parent instanceof SQLBlockStatement) {\n                    ((SQLBlockStatement) parent).setException(stmt);\n                } else {\n                    statementList.add(stmt);\n                }\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"EXIT\")) {\n                lexer.nextToken();\n                OracleExitStatement stmt = parseExit();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"REFRESH\")) {\n                SQLStatement stmt = parseRefresh();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.CONTINUE) {\n                lexer.nextToken();\n                OracleContinueStatement stmt = new OracleContinueStatement();\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    String label = lexer.stringVal();\n                    lexer.nextToken();\n                    stmt.setLabel(label);\n                }\n                if (lexer.token() == Token.WHEN) {\n                    lexer.nextToken();\n                    stmt.setWhen(this.exprParser.expr());\n                }\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.FETCH || lexer.identifierEquals(\"FETCH\")) {\n                SQLStatement stmt = parseFetch();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"ROLLBACK\")) {\n                SQLStatement stmt = parseRollback();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.EXPLAIN) {\n                OracleExplainStatement stmt = this.parseExplain();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                String strVal = lexer.stringVal();\n                if (strVal.equalsIgnoreCase(\"RAISE\")) {\n                    SQLStatement stmt = this.parseRaise();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (strVal.equalsIgnoreCase(\"FORALL\")) {\n                    SQLStatement stmt = this.parseFor();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (strVal.equalsIgnoreCase(\"RENAME\")) {\n                    SQLStatement stmt = this.parseRename();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (strVal.equalsIgnoreCase(\"EXECUTE\")) {\n                    SQLStatement stmt = this.parseExecute();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (strVal.equalsIgnoreCase(\"ANALYZE\")) {\n                    acceptIdentifier(\"ANALYZE\");\n                    if (lexer.token() == TABLE) {\n                        SQLAnalyzeTableStatement stmt = this.parseAnalyzeTable();\n                        stmt.setParent(parent);\n                        statementList.add(stmt);\n                        continue;\n                    }\n                }\n\n                if (strVal.equalsIgnoreCase(\"PIPE\")) {\n                    Lexer.SavePoint savePoint = lexer.mark();\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.ROW) {\n                        lexer.reset(savePoint);\n                        SQLStatement stmt = this.parsePipeRow();\n                        stmt.setParent(parent);\n                        statementList.add(stmt);\n                    } else {\n                        lexer.reset(savePoint);\n                    }\n                    continue;\n                }\n\n                if (strVal.equalsIgnoreCase(\"SHOW\")) {\n//                    Lexer.SavePoint savePoint = lexer.mark();\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(\"ERR\")) {\n                        lexer.nextToken();\n                    } else {\n                        accept(Token.ERRORS);\n                    }\n\n                    SQLShowErrorsStatement stmt = new SQLShowErrorsStatement();\n                    stmt.setDbType(dbType);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                SQLExpr expr = exprParser.expr();\n\n                if (expr instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr;\n                    if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) {\n                        SQLSetStatement stmt = new SQLSetStatement();\n                        stmt.setDbType(DbType.oracle);\n                        stmt.setParent(parent);\n\n                        SQLAssignItem assignItem = new SQLAssignItem(binaryOpExpr.getLeft(), binaryOpExpr.getRight());\n                        assignItem.setParent(stmt);\n                        stmt.getItems().add(assignItem);\n\n                        statementList.add(stmt);\n\n                        continue;\n                    }\n                }\n\n                SQLExprStatement stmt = new SQLExprStatement(expr);\n                stmt.setDbType(dbType);\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                Lexer.SavePoint savePoint = lexer.mark();\n                lexer.nextToken();\n\n                int parenCount = 0;\n                while (lexer.token() == Token.LPAREN) {\n                    savePoint = lexer.mark();\n                    lexer.nextToken();\n                    parenCount++;\n                }\n\n                if (lexer.token() == Token.SELECT) {\n                    lexer.reset(savePoint);\n\n                    SQLStatement stmt = parseSelect();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n\n                    for (int i = 0; i < parenCount; ++i) {\n                        accept(Token.RPAREN);\n                    }\n                    continue;\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            }\n\n            if (lexer.token() == Token.SET) {\n                SQLStatement stmt = parseSet();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.GRANT) {\n                statementList.add(this.parseGrant());\n                continue;\n            }\n\n            if (lexer.token() == Token.REVOKE) {\n                statementList.add(this.parseRevoke());\n                continue;\n            }\n\n            if (lexer.token() == Token.COMMENT) {\n                statementList.add(this.parseComment());\n                continue;\n            }\n            if (lexer.token() == Token.FOR) {\n                OracleForStatement forStatement = this.parseFor();\n                forStatement.setParent(parent);\n                if (lexer.token() == Token.IDENTIFIER) {\n                    String strVal = lexer.stringVal();\n                    int stmtListSize = statementList.size();\n                    if (stmtListSize > 0) {\n                        SQLStatement lastStmt = statementList.get(stmtListSize - 1);\n                        if (lastStmt instanceof OracleLabelStatement) {\n                            if (((OracleLabelStatement) lastStmt).getLabel().getSimpleName().equalsIgnoreCase(strVal)) {\n                                SQLName endLabbel = this.exprParser.name();\n                                forStatement.setEndLabel(endLabbel);\n                            }\n                        }\n                    }\n                }\n                statementList.add(forStatement);\n                continue;\n            }\n            if (lexer.token() == Token.LOOP) {\n                SQLStatement stmt = parseLoop();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n            if (lexer.token() == Token.IF) {\n                SQLStatement stmt = parseIf();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.GOTO) {\n                lexer.nextToken();\n                SQLName label = this.exprParser.name();\n                OracleGotoStatement stmt = new OracleGotoStatement(label);\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.COMMIT) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"WORK\")) {\n                    lexer.nextToken();\n                }\n                SQLCommitStatement stmt = new SQLCommitStatement();\n                stmt.setParent(parent);\n\n                if (lexer.identifierEquals(\"WRITE\")) {\n                    stmt.setWrite(true);\n                    lexer.nextToken();\n\n                    for (; ; ) {\n                        if (lexer.token() == Token.WAIT) {\n                            lexer.nextToken();\n                            stmt.setWait(Boolean.TRUE);\n                            continue;\n                        } else if (lexer.token() == Token.NOWAIT) {\n                            lexer.nextToken();\n                            stmt.setWait(Boolean.FALSE);\n                            continue;\n                        } else if (lexer.token() == Token.IMMEDIATE) {\n                            lexer.nextToken();\n                            stmt.setImmediate(Boolean.TRUE);\n                            continue;\n                        } else if (lexer.identifierEquals(\"BATCH\")) {\n                            lexer.nextToken();\n                            stmt.setImmediate(Boolean.FALSE);\n                            continue;\n                        }\n\n                        break;\n                    }\n                }\n\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.SAVEPOINT) {\n                lexer.nextToken();\n\n                SQLSavePointStatement stmt = new SQLSavePointStatement();\n                stmt.setDbType(dbType);\n                stmt.setParent(parent);\n\n                if (lexer.token() == Token.TO) {\n                    lexer.nextToken();\n                    stmt.setName(this.exprParser.name());\n                } else if (lexer.token() != Token.SEMI) {\n                    stmt.setName(this.exprParser.name());\n                }\n                accept(Token.SEMI);\n                stmt.setAfterSemi(true);\n\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.LTLT) {\n                lexer.nextToken();\n                SQLName label = this.exprParser.name();\n                OracleLabelStatement stmt = new OracleLabelStatement(label);\n                accept(Token.GTGT);\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.DROP) {\n                Lexer.SavePoint savePoint = lexer.mark();\n                lexer.nextToken();\n\n                if (lexer.token() == Token.TABLE) {\n                    SQLDropTableStatement stmt = parseDropTable(false);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                boolean isPublic = false;\n                if (lexer.identifierEquals(\"PUBLIC\")) {\n                    lexer.nextToken();\n                    isPublic = true;\n                }\n\n                if (lexer.token() == Token.DATABASE) {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(\"LINK\")) {\n                        lexer.nextToken();\n\n                        OracleDropDbLinkStatement stmt = new OracleDropDbLinkStatement();\n                        if (isPublic) {\n                            stmt.setPublic(isPublic);\n                        }\n\n                        stmt.setName(this.exprParser.name());\n\n                        statementList.add(stmt);\n                        continue;\n                    }\n                }\n\n                if (lexer.token() == Token.INDEX) {\n                    SQLStatement stmt = parseDropIndex();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.token() == Token.VIEW) {\n                    SQLStatement stmt = parseDropView(false);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.token() == Token.SEQUENCE) {\n                    SQLDropSequenceStatement stmt = parseDropSequence(false);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.token() == Token.TRIGGER) {\n                    SQLDropTriggerStatement stmt = parseDropTrigger(false);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.token() == Token.USER) {\n                    SQLDropUserStatement stmt = parseDropUser();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.token() == Token.PROCEDURE) {\n                    SQLDropProcedureStatement stmt = parseDropProcedure(false);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.token() == Token.FUNCTION) {\n                    SQLDropFunctionStatement stmt = parseDropFunction(false);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.SYNONYM)) {\n                    lexer.reset(savePoint);\n\n                    SQLStatement stmt = parseDropSynonym();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.TYPE)) {\n                    lexer.reset(savePoint);\n\n                    SQLStatement stmt = parseDropType();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.PACKAGE)) {\n                    lexer.reset(savePoint);\n\n                    SQLStatement stmt = parseDropPackage();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.MATERIALIZED)) {\n                    lexer.reset(savePoint);\n\n                    SQLStatement stmt = parseDropMaterializedView();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.NULL) {\n                lexer.nextToken();\n                SQLExprStatement stmt = new SQLExprStatement(new SQLNullExpr());\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.OPEN) {\n                SQLStatement stmt = this.parseOpen();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.CLOSE) {\n                SQLStatement stmt = this.parseClose();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.CASE) {\n                SQLStatement stmt = this.parseCase();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.PROCEDURE) {\n                SQLStatement stmt = this.parseCreateProcedure();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.ELSIF\n                    && (parent instanceof SQLIfStatement || parent instanceof SQLIfStatement.ElseIf)) {\n                break;\n            }\n\n            if (lexer.token() == Token.WHEN\n                    && parent instanceof SQLExceptionStatement.Item) {\n                break;\n            }\n\n            if (lexer.token() == Token.FUNCTION) {\n                SQLStatement stmt = this.parseFunction();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.WHILE) {\n                SQLStatement stmt = this.parseWhile();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.RETURN) {\n                SQLStatement stmt = this.parseReturn();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.TRIGGER) {\n                SQLStatement stmt = this.parseCreateTrigger();\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.MONKEYS_AT_AT) {\n                lexer.nextToken();\n\n                SQLExpr expr = exprParser.primary();\n\n                OracleRunStatement stmt = new OracleRunStatement(expr);\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            if (lexer.token() == Token.QUES) {\n                SQLExpr expr = this.exprParser.expr();\n                SQLExprStatement stmt = new SQLExprStatement(expr);\n                stmt.setParent(parent);\n                statementList.add(stmt);\n                continue;\n            }\n\n            throw new ParserException(\"TODO : \" + lexer.info());\n        }\n    }\n\n    private SQLStatement parseGetDiagnosticsStatement() {\n        accept(Token.GET);\n        accept(Token.DIAGNOSTICS);\n\n        SQLGetDiagnosticsStatement stmt = new SQLGetDiagnosticsStatement();\n        stmt.setDbType(dbType);\n\n        stmt.setExpr(this.exprParser.expr());\n        return stmt;\n    }\n\n    @Override\n    protected SQLStatement parseCreateTableSpace() {\n        accept(Token.CREATE);\n        OracleCreateTableSpaceStatement stmt = new OracleCreateTableSpaceStatement();\n        stmt.setDbType(dbType);\n        accept(Token.TABLESPACE);\n        stmt.setName(this.exprParser.name());\n        stmt.setSql(lexer.text);\n        return stmt;\n    }\n\n    public SQLStatement parseDropType() {\n        if (lexer.token() == Token.DROP) {\n            lexer.nextToken();\n        }\n        SQLDropTypeStatement stmt = new SQLDropTypeStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"TYPE\");\n\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n\n    public SQLStatement parseDropPackage() {\n        if (lexer.token() == Token.DROP) {\n            lexer.nextToken();\n        }\n        OracleDropPackageStatement stmt = new OracleDropPackageStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"PACKAGE\");\n\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseDropMaterializedView() {\n        if (lexer.token() == Token.DROP) {\n            lexer.nextToken();\n        }\n        SQLDropMaterializedViewStatement stmt = new SQLDropMaterializedViewStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"MATERIALIZED\");\n\n        accept(Token.VIEW);\n\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n\n    public SQLStatement parseDropSynonym() {\n        if (lexer.token() == Token.DROP) {\n            lexer.nextToken();\n        }\n        SQLDropSynonymStatement stmt = new SQLDropSynonymStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.identifierEquals(FnvHash.Constants.PUBLIC)) {\n            lexer.nextToken();\n            stmt.setPublic(true);\n        }\n\n        acceptIdentifier(\"SYNONYM\");\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n            stmt.setForce(true);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parsePipeRow() {\n        OraclePipeRowStatement stmt = new OraclePipeRowStatement();\n        acceptIdentifier(\"PIPE\");\n        accept(Token.ROW);\n        accept(Token.LPAREN);\n        this.exprParser.exprList(stmt.getParameters(), stmt);\n        accept(Token.RPAREN);\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseExecute() {\n        acceptIdentifier(\"EXECUTE\");\n\n        if (lexer.token() == Token.IMMEDIATE) {\n            lexer.nextToken();\n\n            OracleExecuteImmediateStatement stmt = new OracleExecuteImmediateStatement();\n\n            SQLExpr dyanmiacSql = this.exprParser.primary();\n            stmt.setDynamicSql(dyanmiacSql);\n\n            if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n\n                this.exprParser.exprList(stmt.getInto(), stmt);\n            }\n\n            if (lexer.token() == Token.USING) {\n                lexer.nextToken();\n\n                for (; ; ) {\n                    SQLArgument arg = new SQLArgument();\n\n                    if (lexer.token() == Token.IN) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.OUT) {\n                            lexer.nextToken();\n                            arg.setType(SQLParameter.ParameterType.INOUT);\n                        } else {\n                            arg.setType(SQLParameter.ParameterType.IN);\n                        }\n                    } else if (lexer.token() == Token.OUT) {\n                        lexer.nextToken();\n                        arg.setType(SQLParameter.ParameterType.OUT);\n                    }\n\n                    arg.setExpr(this.exprParser.primary());\n                    arg.setParent(stmt);\n                    stmt.getArguments().add(arg);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n            }\n\n            if (lexer.token() == Token.RETURNING) {\n                lexer.nextToken();\n                accept(Token.INTO);\n\n                this.exprParser.exprList(stmt.getReturnInto(), stmt);\n            }\n\n            return stmt;\n        }\n        throw new ParserException(\"TODO : \" + lexer.info());\n    }\n\n    public SQLStatement parseRename() {\n        lexer.nextToken();\n        SQLName from = this.exprParser.name();\n        accept(Token.TO);\n        SQLName to = this.exprParser.name();\n\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(dbType);\n        stmt.setTableSource(from);\n        SQLAlterTableRename toItem = new SQLAlterTableRename(to);\n        stmt.addItem(toItem);\n\n        return stmt;\n    }\n\n    private OracleExitStatement parseExit() {\n        OracleExitStatement stmt = new OracleExitStatement();\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            String label = lexer.stringVal();\n            stmt.setLabel(label);\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.WHEN) {\n            lexer.nextToken();\n            stmt.setWhen(this.exprParser.expr());\n        }\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n        return stmt;\n    }\n\n    public SQLStatement parseReturn() {\n        accept(Token.RETURN);\n        SQLReturnStatement stmt = new SQLReturnStatement();\n        if (lexer.token() != Token.SEMI) {\n            SQLExpr expr = this.exprParser.expr();\n            stmt.setExpr(expr);\n        }\n\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n\n        return stmt;\n    }\n\n    public SQLWhileStatement parseWhile() {\n        accept(Token.WHILE);\n\n        SQLWhileStatement stmt = new SQLWhileStatement();\n        stmt.setDbType(dbType);\n\n        stmt.setCondition(this.exprParser.expr());\n\n        accept(Token.LOOP);\n\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n        accept(Token.END);\n        accept(Token.LOOP);\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n\n        return stmt;\n    }\n\n    public SQLCreateFunctionStatement parseCreateFunction() {\n        SQLCreateFunctionStatement stmt = (SQLCreateFunctionStatement) parseFunction();\n        stmt.setCreate(true);\n        return stmt;\n    }\n\n    public SQLStatement parseFunction() {\n        SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n            if (lexer.token() == Token.OR) {\n                lexer.nextToken();\n                accept(Token.REPLACE);\n                stmt.setOrReplace(true);\n            }\n        } else {\n            if (lexer.token() == Token.DECLARE) {\n                lexer.nextToken();\n            }\n            stmt.setCreate(false);\n        }\n\n        accept(Token.FUNCTION);\n\n        SQLName functionName = this.exprParser.name();\n        stmt.setName(functionName);\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            parserParameters(stmt.getParameters(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WRAPPED)) {\n            lexer.nextToken();\n            int pos = lexer.text.indexOf(';', lexer.pos());\n            if (pos != -1) {\n                String wrappedString = lexer.subString(lexer.pos(), pos - lexer.pos());\n                stmt.setWrappedSource(wrappedString);\n                lexer.reset(pos, ';', Token.LITERAL_CHARS);\n                lexer.nextToken();\n                stmt.setAfterSemi(true);\n            } else {\n                String wrappedString = lexer.text.substring(lexer.pos());\n                stmt.setWrappedSource(wrappedString);\n                lexer.reset(lexer.text.length(), (char) LayoutCharacters.EOI, Token.EOF);\n                return stmt;\n            }\n\n            return stmt;\n        }\n\n        accept(Token.RETURN);\n        SQLDataType returnDataType = this.exprParser.parseDataType(false);\n        stmt.setReturnDataType(returnDataType);\n\n        if (identifierEquals(\"PIPELINED\")) {\n            lexer.nextToken();\n            stmt.setPipelined(true);\n        }\n\n        if (identifierEquals(\"DETERMINISTIC\")) {\n            lexer.nextToken();\n            stmt.setDeterministic(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.AUTHID)) {\n            lexer.nextToken();\n            String strVal = lexer.stringVal();\n            if (lexer.identifierEquals(FnvHash.Constants.CURRENT_USER)) {\n                lexer.nextToken();\n            } else {\n                acceptIdentifier(\"DEFINER\");\n            }\n            SQLName authid = new SQLIdentifierExpr(strVal);\n            stmt.setAuthid(authid);\n        }\n\n        if (identifierEquals(\"RESULT_CACHE\")) {\n            lexer.nextToken();\n            stmt.setResultCache(true);\n        }\n\n        if (lexer.token() == Token.SEMI) {\n            lexer.nextToken();\n            return stmt;\n        }\n\n        if (lexer.token() == Token.IS || lexer.token() == Token.AS) {\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"LANGUAGE\")) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"JAVA\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"NAME\");\n                String javaCallSpec = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n                stmt.setJavaCallSpec(javaCallSpec);\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"PARALLEL_ENABLE\")) {\n            lexer.nextToken();\n            stmt.setParallelEnable(true);\n        }\n\n        if (lexer.identifierEquals(\"AGGREGATE\")) {\n            lexer.nextToken();\n            stmt.setAggregate(true);\n        }\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n            SQLName using = this.exprParser.name();\n            stmt.setUsing(using);\n        }\n\n        SQLStatement block;\n        if (lexer.token() == Token.SEMI) {\n            stmt.setAfterSemi(true);\n            lexer.nextToken();\n            block = null;\n        } else {\n            block = this.parseBlock();\n        }\n\n        stmt.setBlock(block);\n\n        if (lexer.identifierEquals(functionName.getSimpleName())) {\n            lexer.nextToken();\n        }\n\n        // return stmt;\n\n        if (lexer.identifierEquals(functionName.getSimpleName())) {\n            lexer.nextToken();\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseRaise() {\n        lexer.nextToken();\n        OracleRaiseStatement stmt = new OracleRaiseStatement();\n        if (lexer.token() != Token.SEMI) {\n            stmt.setException(this.exprParser.expr());\n        }\n        accept(Token.SEMI);\n        return stmt;\n    }\n\n    public SQLStatement parseCase() {\n        SQLCaseStatement caseStmt = new SQLCaseStatement();\n        caseStmt.setDbType(dbType);\n        lexer.nextToken();\n        if (lexer.token() != Token.WHEN) {\n            caseStmt.setValueExpr(this.exprParser.expr());\n        }\n\n        accept(Token.WHEN);\n        SQLExpr testExpr = this.exprParser.expr();\n        accept(Token.THEN);\n        SQLStatement stmt = this.parseStatement();\n        if (lexer.token() == Token.SEMI) {\n            lexer.nextToken();\n        }\n        SQLCaseStatement.Item caseItem = new SQLCaseStatement.Item(testExpr, stmt);\n        caseStmt.addItem(caseItem);\n\n        while (lexer.token() == Token.WHEN) {\n            lexer.nextToken();\n            testExpr = this.exprParser.expr();\n            accept(Token.THEN);\n            stmt = this.parseStatement();\n            if (lexer.token() == Token.SEMI) {\n                lexer.nextToken();\n            }\n            caseItem = new SQLCaseStatement.Item(testExpr, stmt);\n            caseStmt.addItem(caseItem);\n        }\n\n        if (lexer.token() == Token.ELSE) {\n            lexer.nextToken();\n            this.parseStatementList(caseStmt.getElseStatements(), -1, caseStmt);\n        }\n\n        accept(Token.END);\n        accept(Token.CASE);\n        accept(Token.SEMI);\n        return caseStmt;\n    }\n\n    @Override\n    protected void parseIfElse(SQLIfStatement stmt) {\n        while (lexer.nextIf(Token.ELSIF)) {\n            SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf();\n            elseIf.setCondition(this.exprParser.expr());\n            elseIf.setParent(stmt);\n            accept(Token.THEN);\n            this.parseStatementList(elseIf.getStatements(), -1, elseIf);\n            stmt.getElseIfList().add(elseIf);\n        }\n\n        if (lexer.nextIf(Token.ELSE)) {\n            SQLIfStatement.Else elseItem = new SQLIfStatement.Else();\n            this.parseStatementList(elseItem.getStatements(), -1, elseItem);\n            stmt.setElseItem(elseItem);\n        }\n    }\n\n    @Override\n    public OracleForStatement parseFor() {\n        OracleForStatement stmt = new OracleForStatement();\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n        } else {\n            acceptIdentifier(\"FORALL\");\n            stmt.setAll(true);\n        }\n\n        stmt.setIndex(this.exprParser.name());\n        accept(Token.IN);\n        if (lexer.token() == Token.REVERSE) {\n            stmt.setReverse(true);\n            lexer.nextToken();\n        }\n        stmt.setRange(this.exprParser.expr());\n\n        if (stmt.isAll()) {\n            SQLStatement itemStmt = this.parseStatement();\n            itemStmt.setParent(stmt);\n            stmt.getStatements().add(itemStmt);\n        } else {\n            accept(Token.LOOP);\n\n            this.parseStatementList(stmt.getStatements(), -1, stmt);\n            accept(Token.END);\n            accept(Token.LOOP);\n\n            if (lexer.token() != Token.SEMI) {\n                SQLName endLabel = this.exprParser.name();\n                stmt.setEndLabel(endLabel);\n            }\n\n            accept(Token.SEMI);\n            stmt.setAfterSemi(true);\n        }\n        return stmt;\n    }\n\n    @Override\n    public SQLLoopStatement parseLoop() {\n        accept(Token.LOOP);\n\n        SQLLoopStatement stmt = new SQLLoopStatement();\n\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n        accept(Token.END);\n        accept(Token.LOOP);\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            String label = lexer.stringVal();\n            stmt.setLabelName(label);\n            lexer.nextToken();\n        }\n\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n        return stmt;\n    }\n\n    public SQLStatement parseSet() {\n        accept(Token.SET);\n\n        if (lexer.identifierEquals(\"TRANSACTION\")) {\n            lexer.nextToken();\n\n            OracleSetTransactionStatement stmt = new OracleSetTransactionStatement();\n\n            if (lexer.identifierEquals(\"READ\")) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"ONLY\")) {\n                    lexer.nextToken();\n                    stmt.setReadOnly(true);\n                } else {\n                    acceptIdentifier(\"WRITE\");\n                    stmt.setWrite(true);\n                }\n            }\n\n            if (lexer.identifierEquals(\"NAME\")) {\n                lexer.nextToken();\n\n                stmt.setName(this.exprParser.expr());\n            }\n\n            return stmt;\n        }\n\n        SQLSetStatement stmt = new SQLSetStatement(dbType);\n        stmt.setUseSet(true);\n        parseAssignItems(stmt.getItems(), stmt);\n\n        stmt.putAttribute(\"parser.set\", Boolean.TRUE);\n        return stmt;\n    }\n\n    public SQLStatement parserAlter() {\n        Lexer.SavePoint savePoint = lexer.mark();\n        accept(Token.ALTER);\n        if (lexer.token() == Token.SESSION) {\n            lexer.nextToken();\n\n            OracleAlterSessionStatement stmt = new OracleAlterSessionStatement();\n            if (lexer.token() == Token.SET) {\n                lexer.nextToken();\n                parseAssignItems(stmt.getItems(), stmt);\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n            return stmt;\n        } else if (lexer.token() == Token.PROCEDURE) {\n            lexer.nextToken();\n            SQLAlterProcedureStatement stmt = new SQLAlterProcedureStatement();\n            stmt.setName(this.exprParser.name());\n            if (lexer.identifierEquals(\"COMPILE\")) {\n                lexer.nextToken();\n                stmt.setCompile(true);\n            }\n\n            if (lexer.identifierEquals(\"REUSE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"SETTINGS\");\n                stmt.setReuseSettings(true);\n            }\n\n            return stmt;\n        } else if (lexer.token() == Token.TABLE) {\n            return parseAlterTable();\n        } else if (lexer.token() == Token.INDEX) {\n            lexer.reset(savePoint);\n            return alterIndex();\n        } else if (lexer.token() == Token.TRIGGER) {\n            lexer.nextToken();\n            OracleAlterTriggerStatement stmt = new OracleAlterTriggerStatement();\n            stmt.setName(this.exprParser.name());\n\n            for (; ; ) {\n                if (lexer.token() == Token.ENABLE) {\n                    lexer.nextToken();\n                    stmt.setEnable(Boolean.TRUE);\n                    continue;\n                } else if (lexer.token() == Token.DISABLE) {\n                    lexer.nextToken();\n                    stmt.setEnable(Boolean.FALSE);\n                    continue;\n                } else if (lexer.identifierEquals(\"COMPILE\")) {\n                    lexer.nextToken();\n                    stmt.setCompile(true);\n                    continue;\n                }\n                break;\n            }\n\n            return stmt;\n        } else if (lexer.identifierEquals(FnvHash.Constants.SYNONYM)) {\n            lexer.nextToken();\n            OracleAlterSynonymStatement stmt = new OracleAlterSynonymStatement();\n            stmt.setName(this.exprParser.name());\n\n            for (; ; ) {\n                if (lexer.token() == Token.ENABLE) {\n                    lexer.nextToken();\n                    stmt.setEnable(Boolean.TRUE);\n                    continue;\n                } else if (lexer.token() == Token.DISABLE) {\n                    lexer.nextToken();\n                    stmt.setEnable(Boolean.FALSE);\n                    continue;\n                } else if (lexer.identifierEquals(\"COMPILE\")) {\n                    lexer.nextToken();\n                    stmt.setCompile(true);\n                    continue;\n                }\n                break;\n            }\n\n            return stmt;\n        } else if (lexer.token() == Token.VIEW) {\n            lexer.nextToken();\n            OracleAlterViewStatement stmt = new OracleAlterViewStatement();\n            stmt.setName(this.exprParser.name());\n\n            for (; ; ) {\n                if (lexer.token() == Token.ENABLE) {\n                    lexer.nextToken();\n                    stmt.setEnable(Boolean.TRUE);\n                    continue;\n                } else if (lexer.token() == Token.DISABLE) {\n                    lexer.nextToken();\n                    stmt.setEnable(Boolean.FALSE);\n                    continue;\n                } else if (lexer.identifierEquals(\"COMPILE\")) {\n                    lexer.nextToken();\n                    stmt.setCompile(true);\n                    continue;\n                }\n                break;\n            }\n\n            return stmt;\n        } else if (lexer.token() == Token.TABLESPACE) {\n            lexer.nextToken();\n\n            OracleAlterTablespaceStatement stmt = new OracleAlterTablespaceStatement();\n            stmt.setName(this.exprParser.name());\n\n            if (lexer.identifierEquals(\"ADD\")) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"DATAFILE\")) {\n                    lexer.nextToken();\n\n                    OracleAlterTablespaceAddDataFile item = new OracleAlterTablespaceAddDataFile();\n\n                    for (; ; ) {\n                        OracleFileSpecification file = new OracleFileSpecification();\n\n                        for (; ; ) {\n                            SQLExpr fileName = this.exprParser.expr();\n                            file.getFileNames().add(fileName);\n\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n\n                            break;\n                        }\n\n                        if (lexer.identifierEquals(\"SIZE\")) {\n                            lexer.nextToken();\n                            file.setSize(this.exprParser.expr());\n                        }\n\n                        if (lexer.identifierEquals(\"AUTOEXTEND\")) {\n                            lexer.nextToken();\n                            if (lexer.identifierEquals(\"OFF\")) {\n                                lexer.nextToken();\n                                file.setAutoExtendOff(true);\n                            } else if (lexer.identifierEquals(\"ON\")) {\n                                lexer.nextToken();\n                                file.setAutoExtendOn(this.exprParser.expr());\n                            } else {\n                                throw new ParserException(\"TODO : \" + lexer.info());\n                            }\n                        }\n\n                        item.getFiles().add(file);\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n\n                        break;\n                    }\n\n                    stmt.setItem(item);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n\n            return stmt;\n        } else if (lexer.token() == Token.FUNCTION) {\n            lexer.reset(savePoint);\n            return parseAlterFunction();\n        } else if (lexer.token() == Token.SEQUENCE) {\n            lexer.reset(savePoint);\n            return alterSequence();\n        } else if (lexer.identifierEquals(FnvHash.Constants.TYPE)) {\n            lexer.reset(savePoint);\n            return parseAlterType();\n        } else if (lexer.identifierEquals(\"SUMMARY\")) {\n            lexer.nextToken();\n\n            OracleAlterSummaryStatement stmt = new OracleAlterSummaryStatement();\n            stmt.setName(this.exprParser.name());\n\n            if (lexer.identifierEquals(\"COMPILE\")) {\n                lexer.nextToken();\n                stmt.setCompile(true);\n            }\n\n            return stmt;\n        } else if (lexer.identifierEquals(FnvHash.Constants.PACKAGE)) {\n            lexer.reset(savePoint);\n            return parseAlterPackage();\n        }\n\n        throw new ParserException(\"TODO : \" + lexer.info());\n    }\n\n    protected SQLStatement parseAlterType() {\n        accept(Token.ALTER);\n        acceptIdentifier(\"TYPE\");\n\n        SQLAlterTypeStatement stmt = new SQLAlterTypeStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.identifierEquals(\"COMPILE\")) {\n            stmt.setCompile(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"DEBUG\")) {\n            stmt.setDebug(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"BODY\")) {\n            stmt.setBody(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"REUSE\")) {\n            stmt.setReuseSettings(true);\n            lexer.nextToken();\n            acceptIdentifier(\"SETTINGS\");\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseAlterPackage() {\n        accept(Token.ALTER);\n        acceptIdentifier(\"PACKAGE\");\n\n        OracleAlterPackageStatement stmt = new OracleAlterPackageStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.identifierEquals(\"COMPILE\")) {\n            stmt.setCompile(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"PACKAGE\")) {\n            stmt.setPack(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"BODY\")) {\n            stmt.setBody(true);\n            lexer.nextToken();\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseAlterFunction() {\n        accept(Token.ALTER);\n        accept(Token.FUNCTION);\n\n        SQLAlterFunctionStatement stmt = new SQLAlterFunctionStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        acceptIdentifier(\"COMPILE\");\n\n        if (lexer.identifierEquals(\"DEBUG\")) {\n            stmt.setDebug(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"REUSE\")) {\n            stmt.setReuseSettings(true);\n            lexer.nextToken();\n            acceptIdentifier(\"SETTINGS\");\n        }\n        return stmt;\n    }\n\n    private SQLStatement parseAlterTable() {\n        lexer.nextToken();\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.setName(this.exprParser.name());\n\n        for (; ; ) {\n            if (lexer.identifierEquals(FnvHash.Constants.ADD)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    SQLAlterTableAddColumn item = parseAlterTableAddColumn();\n\n                    stmt.addItem(item);\n\n                    accept(Token.RPAREN);\n                } else if (lexer.token() == Token.CONSTRAINT\n                        || lexer.token() == Token.FOREIGN\n                        || lexer.token() == Token.PRIMARY\n                        || lexer.token() == Token.UNIQUE\n                        || lexer.token() == Token.CHECK) {\n                    OracleConstraint constraint = ((OracleExprParser) this.exprParser).parseConstraint();\n                    SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint();\n                    constraint.setParent(item);\n                    item.setParent(stmt);\n                    item.setConstraint(constraint);\n                    stmt.addItem(item);\n                } else if (lexer.identifierEquals(FnvHash.Constants.SUPPLEMENTAL)) {\n                    SQLTableElement element = this.getSQLCreateTableParser()\n                            .parseCreateTableSupplementalLoggingProps();\n\n                    SQLAlterTableAddSupplemental item = new SQLAlterTableAddSupplemental();\n                    item.setElement(element);\n                    stmt.addItem(item);\n                } else if (lexer.token() == Token.IDENTIFIER) {\n                    SQLAlterTableAddColumn item = parseAlterTableAddColumn();\n                    stmt.addItem(item);\n                } else if (lexer.token() == Token.LITERAL_ALIAS) {\n                    SQLAlterTableAddColumn item = parseAlterTableAddColumn();\n                    stmt.addItem(item);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n\n                continue;\n            } else if (lexer.identifierEquals(FnvHash.Constants.MOVE)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.TABLESPACE) {\n                    lexer.nextToken();\n\n                    OracleAlterTableMoveTablespace item = new OracleAlterTableMoveTablespace();\n                    item.setName(this.exprParser.name());\n\n                    stmt.addItem(item);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            } else if (lexer.identifierEquals(\"RENAME\")) {\n                stmt.addItem(parseAlterTableRename());\n            } else if (lexer.identifierEquals(\"MODIFY\")) {\n                lexer.nextToken();\n\n                OracleAlterTableModify item = new OracleAlterTableModify();\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    for (; ; ) {\n                        SQLColumnDefinition columnDef = this.exprParser.parseColumn();\n                        item.addColumn(columnDef);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n\n                } else {\n                    SQLColumnDefinition columnDef = this.exprParser.parseColumn();\n                    item.addColumn(columnDef);\n                }\n\n                stmt.addItem(item);\n                continue;\n            } else if (lexer.identifierEquals(\"SPLIT\")) {\n                parseAlterTableSplit(stmt);\n                continue;\n            } else if (lexer.token() == Token.TRUNCATE) {\n                lexer.nextToken();\n                if (lexer.token() == Token.PARTITION) {\n                    lexer.nextToken();\n                    OracleAlterTableTruncatePartition item = new OracleAlterTableTruncatePartition();\n                    item.setName(this.exprParser.name());\n                    stmt.addItem(item);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n                continue;\n            } else if (lexer.token() == Token.DROP) {\n                parseAlterDrop(stmt);\n                continue;\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                if (lexer.token() == Token.CONSTRAINT) {\n                    lexer.nextToken();\n                    SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint();\n                    item.setConstraintName(this.exprParser.name());\n                    stmt.addItem(item);\n                } else if (lexer.token() == Token.ROW) {\n                    lexer.nextToken();\n                    OracleAlterTableRowMovement item = new OracleAlterTableRowMovement();\n                    acceptIdentifier(\"MOVEMENT\");\n                    item.setEnable(false);\n                    stmt.addItem(item);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            } else if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                if (lexer.token() == Token.CONSTRAINT) {\n                    lexer.nextToken();\n                    SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint();\n                    item.setConstraintName(this.exprParser.name());\n                    stmt.addItem(item);\n                } else if (lexer.token() == Token.ROW) {\n                    lexer.nextToken();\n                    OracleAlterTableRowMovement item = new OracleAlterTableRowMovement();\n                    acceptIdentifier(\"MOVEMENT\");\n                    item.setEnable(true);\n                    stmt.addItem(item);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            } else if (lexer.identifierEquals(\"SHRINK\")) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"SPACE\")) {\n                    lexer.nextToken();\n\n                    OracleAlterTableShrinkSpace item = new OracleAlterTableShrinkSpace();\n                    fillShrinkSpace(item);\n                    fillShrinkSpace(item);\n                    fillShrinkSpace(item);\n\n                    stmt.addItem(item);\n                }\n            }\n\n            break;\n        }\n\n        if (lexer.token() == Token.UPDATE) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"GLOBAL\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"INDEXES\");\n                stmt.setUpdateGlobalIndexes(true);\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n        }\n\n        return stmt;\n    }\n\n    public void fillShrinkSpace(OracleAlterTableShrinkSpace item) {\n        if (lexer.identifierEquals(\"COMPACT\")) {\n            item.setCompact(true);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.CASCADE) {\n            item.setCascade(true);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.CHECK) {\n            item.setCheck(true);\n            lexer.nextToken();\n        }\n    }\n\n    public void parseAlterDrop(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token() == Token.CONSTRAINT) {\n            lexer.nextToken();\n            SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint();\n            item.setConstraintName(this.exprParser.name());\n            if (lexer.token() == Token.CASCADE) {\n                lexer.nextToken();\n                item.setCascade(true);\n            }\n\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem();\n            this.exprParser.names(item.getColumns());\n            stmt.addItem(item);\n            accept(Token.RPAREN);\n        } else if (lexer.token() == Token.COLUMN) {\n            lexer.nextToken();\n            SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem();\n            if (lexer.token() == Token.IF) {\n                lexer.nextToken();\n                accept(Token.EXISTS);\n                item.setIfExists(true);\n            }\n            this.exprParser.names(item.getColumns());\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            OracleAlterTableDropPartition item = new OracleAlterTableDropPartition();\n            item.setName(this.exprParser.name());\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.INDEX) {\n            lexer.nextToken();\n            SQLName indexName = this.exprParser.name();\n            SQLAlterTableDropIndex item = new SQLAlterTableDropIndex();\n            item.setIndexName(indexName);\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.PRIMARY) {\n            lexer.nextToken();\n            accept(Token.KEY);\n            SQLAlterTableDropPrimaryKey item = new SQLAlterTableDropPrimaryKey();\n            stmt.addItem(item);\n        } else {\n            throw new ParserException(\"TODO : \" + lexer.info());\n        }\n    }\n\n    private void parseAlterTableSplit(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token() == Token.PARTITION) {\n            lexer.nextToken();\n            OracleAlterTableSplitPartition item = new OracleAlterTableSplitPartition();\n            item.setName(this.exprParser.name());\n\n            if (lexer.identifierEquals(\"AT\")) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                this.exprParser.exprList(item.getAt(), item);\n                accept(Token.RPAREN);\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                for (; ; ) {\n                    NestedTablePartitionSpec spec = new NestedTablePartitionSpec();\n                    accept(Token.PARTITION);\n                    spec.setPartition(this.exprParser.name());\n\n                    for (; ; ) {\n                        if (lexer.token() == Token.TABLESPACE) {\n                            lexer.nextToken();\n                            SQLName tablespace = this.exprParser.name();\n                            spec.getSegmentAttributeItems().add(new TableSpaceItem(tablespace));\n                            continue;\n                        } else if (lexer.identifierEquals(\"PCTREE\")) {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        } else if (lexer.identifierEquals(\"PCTUSED\")) {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        } else if (lexer.identifierEquals(\"INITRANS\")) {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n\n                        } else if (lexer.identifierEquals(\"STORAGE\")) {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n\n                        } else if (lexer.identifierEquals(\"LOGGING\")) {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        } else if (lexer.identifierEquals(\"NOLOGGING\")) {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        } else if (lexer.identifierEquals(\"FILESYSTEM_LIKE_LOGGING\")) {\n                            throw new ParserException(\"TODO : \" + lexer.info());\n\n                        }\n\n                        break;\n                    }\n\n                    item.getInto().add(spec);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.UPDATE) {\n                lexer.nextToken();\n                acceptIdentifier(\"INDEXES\");\n                UpdateIndexesClause updateIndexes = new UpdateIndexesClause();\n                item.setUpdateIndexes(updateIndexes);\n            }\n            stmt.addItem(item);\n        } else {\n            throw new ParserException(\"TODO : \" + lexer.info());\n        }\n    }\n\n    public OracleLockTableStatement parseLock() {\n        accept(Token.LOCK);\n        accept(Token.TABLE);\n\n        OracleLockTableStatement stmt = new OracleLockTableStatement();\n        stmt.setTable(this.exprParser.name());\n\n        if (Token.PARTITION == lexer.token()) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            stmt.setPartition(this.exprParser.expr());\n            accept(Token.RPAREN);\n        }\n\n        accept(Token.IN);\n\n        Token token = lexer.token();\n        if (token == Token.SHARE) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.ROW) {\n                lexer.nextToken();\n                accept(Token.EXCLUSIVE);\n                stmt.setLockMode(LockMode.SHARE_ROW_EXCLUSIVE);\n            } else if (lexer.token() == Token.UPDATE) {\n                lexer.nextToken();\n                stmt.setLockMode(LockMode.SHARE_UPDATE);\n            } else {\n                stmt.setLockMode(LockMode.SHARE);\n            }\n        } else if (token == Token.EXCLUSIVE) {\n            stmt.setLockMode(LockMode.EXCLUSIVE);\n            lexer.nextToken();\n        } else if (token == Token.ROW) {\n            lexer.nextToken();\n            token = lexer.token();\n            if (token == Token.SHARE) {\n                stmt.setLockMode(LockMode.ROW_SHARE);\n                lexer.nextToken();\n            } else if (token == Token.EXCLUSIVE) {\n                stmt.setLockMode(LockMode.ROW_EXCLUSIVE);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(lexer.info());\n            }\n        } else {\n            throw new ParserException(lexer.info());\n        }\n        accept(Token.MODE);\n\n        if (lexer.token() == Token.NOWAIT) {\n            lexer.nextToken();\n            stmt.setNoWait(true);\n        } else if (lexer.token() == Token.WAIT) {\n            lexer.nextToken();\n            stmt.setWait(exprParser.expr());\n        }\n        return stmt;\n    }\n\n    public SQLStatement parseBlock() {\n        SQLBlockStatement block = new SQLBlockStatement();\n        block.setDbType(DbType.oracle);\n\n        Lexer.SavePoint savePoint = lexer.mark();\n\n        if (lexer.token() == Token.DECLARE) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.CURSOR) {\n            parserParameters(block.getParameters(), block);\n            for (SQLParameter param : block.getParameters()) {\n                param.setParent(block);\n            }\n        }\n\n        if (lexer.token() == Token.PROCEDURE) {\n            SQLCreateProcedureStatement stmt = this.parseCreateProcedure();\n            for (SQLParameter param : block.getParameters()) {\n                param.setParent(stmt);\n                stmt.getParameters().add(param);\n            }\n            return stmt;\n        }\n\n        if (lexer.token() == Token.FUNCTION) {\n            if (savePoint.token == Token.DECLARE) {\n                lexer.reset(savePoint);\n            }\n            return this.parseCreateFunction();\n        }\n\n        accept(Token.BEGIN);\n\n        parseStatementList(block.getStatementList(), -1, block);\n\n        accept(Token.END);\n\n        Token token = lexer.token();\n\n        if (token == Token.EOF) {\n            return block;\n        }\n\n        if (token != Token.SEMI) {\n            String endLabel = lexer.stringVal();\n            accept(Token.IDENTIFIER);\n            block.setEndLabel(endLabel);\n        }\n        accept(Token.SEMI);\n\n        return block;\n    }\n\n    protected void parserParameters(List<SQLParameter> parameters, SQLObject parent) {\n        for (; ; ) {\n            SQLParameter parameter = new SQLParameter();\n            parameter.setParent(parent);\n\n            if (parent instanceof OracleCreateTypeStatement) {\n                if (lexer.identifierEquals(FnvHash.Constants.MAP)) {\n                    lexer.nextToken();\n                    parameter.setMap(true);\n                } else if (lexer.token() == Token.ORDER) {\n                    lexer.nextToken();\n                    parameter.setOrder(true);\n                }\n\n                // acceptIdentifier(\"MEMBER\");\n            }\n\n            SQLName name;\n            SQLDataType dataType = null;\n            if (lexer.token() == Token.CURSOR) {\n                lexer.nextToken();\n\n                dataType = new SQLDataTypeImpl();\n                dataType.setName(\"CURSOR\");\n\n                name = this.exprParser.name();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    this.parserParameters(parameter.getCursorParameters(), parameter);\n                    accept(Token.RPAREN);\n                }\n\n                accept(Token.IS);\n                SQLSelect select = this.createSQLSelectParser().select();\n                parameter.setDefaultValue(new SQLQueryExpr(select));\n\n            } else if (lexer.token() == Token.PROCEDURE\n                    || lexer.token() == Token.END\n                    || lexer.token() == Token.TABLE) {\n                break;\n            } else if (lexer.identifierEquals(FnvHash.Constants.TYPE)) {\n                lexer.nextToken();\n                name = this.exprParser.name();\n                accept(Token.IS);\n\n                if (lexer.identifierEquals(\"REF\")) {\n                    lexer.nextToken();\n                    accept(Token.CURSOR);\n\n                    dataType = new SQLDataTypeImpl(\"REF CURSOR\");\n                    dataType.setDbType(dbType);\n                } else if (lexer.token() == Token.TABLE) {\n                    lexer.nextToken();\n                    accept(Token.OF);\n\n                    SQLName sqlName = this.exprParser.name();\n\n                    if (lexer.token() == Token.PERCENT) {\n                        lexer.nextToken();\n\n                        String typeName;\n                        if (lexer.identifierEquals(FnvHash.Constants.ROWTYPE)) {\n                            lexer.nextToken();\n                            typeName = \"TABLE OF \" + sqlName.toString() + \"%ROWTYPE\";\n                        } else {\n                            acceptIdentifier(\"TYPE\");\n                            typeName = \"TABLE OF \" + sqlName.toString() + \"%TYPE\";\n                        }\n\n                        dataType = new SQLDataTypeImpl(typeName);\n                    } else if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        String typeName = \"TABLE OF \" + sqlName.toString();\n\n                        SQLIntegerExpr lenExpr = (SQLIntegerExpr) this.exprParser.expr();\n                        int len = lenExpr.getNumber().intValue();\n                        dataType = new SQLDataTypeImpl(typeName, len);\n                        accept(Token.RPAREN);\n                    } else {\n                        String typeName = \"TABLE OF \" + sqlName.toString();\n                        dataType = new SQLDataTypeImpl(typeName);\n                    }\n\n                    if (lexer.token() == Token.INDEX) {\n                        lexer.nextToken();\n                        accept(Token.BY);\n                        SQLExpr indexBy = this.exprParser.primary();\n                        ((SQLDataTypeImpl) dataType).setIndexBy(indexBy);\n                    }\n                    dataType.setDbType(dbType);\n                } else if (lexer.identifierEquals(\"VARRAY\")) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    int len = this.exprParser.acceptInteger();\n                    accept(Token.RPAREN);\n                    accept(Token.OF);\n\n                    if (lexer.identifierEquals(\"NUMBER\")) {\n                        lexer.nextToken();\n                        String typeName = \"VARRAY(\" + len + \") OF NUMBER\";\n\n                        if (lexer.token() == Token.LPAREN) {\n                            accept(Token.LPAREN);\n                            int numLen = this.exprParser.acceptInteger();\n                            accept(Token.RPAREN);\n                            typeName += \"(\" + numLen + \")\";\n                        }\n                        dataType = new SQLDataTypeImpl(typeName);\n                        dataType.setDbType(dbType);\n                    } else if (lexer.identifierEquals(\"VARCHAR2\")) {\n                        lexer.nextToken();\n                        String typeName = \"VARRAY(\" + len + \") OF VARCHAR2\";\n                        dataType = new SQLDataTypeImpl(typeName);\n                        dataType.setDbType(dbType);\n\n                        if (lexer.token() == Token.LPAREN) {\n                            lexer.nextToken();\n                            this.exprParser.exprList(dataType.getArguments(), dataType);\n                            accept(Token.RPAREN);\n                        }\n                    } else {\n                        throw new ParserException(\"TODO : \" + lexer.info());\n                    }\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.info());\n                }\n            } else {\n                if (lexer.token() == Token.KEY) {\n                    name = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(\"ENUM\")) {\n                    name = this.exprParser.name();\n                    SQLListExpr enumList = (SQLListExpr) this.exprParser.expr();\n                    parameter.setName(name);\n                    dataType = new SQLDataTypeImpl(\"ENUM\", enumList);\n                    parameter.setDataType(dataType);\n                    parameters.add(parameter);\n                    break;\n                } else {\n                    name = this.exprParser.name();\n                }\n\n                if (lexer.token() == Token.IN) {\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.OUT) {\n                        lexer.nextToken();\n                        parameter.setParamType(SQLParameter.ParameterType.INOUT);\n                    } else {\n                        parameter.setParamType(SQLParameter.ParameterType.IN);\n                    }\n                } else if (lexer.token() == Token.OUT) {\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.IN) {\n                        lexer.nextToken();\n                        parameter.setParamType(SQLParameter.ParameterType.INOUT);\n                    } else {\n                        parameter.setParamType(SQLParameter.ParameterType.OUT);\n                    }\n                } else if (lexer.token() == Token.INOUT) {\n                    lexer.nextToken();\n                    parameter.setParamType(SQLParameter.ParameterType.INOUT);\n                }\n\n                if (lexer.identifierEquals(\"NOCOPY\")) {\n                    lexer.nextToken();\n                    parameter.setNoCopy(true);\n                }\n\n                if (lexer.identifierEquals(\"CONSTANT\")) {\n                    lexer.nextToken();\n                    parameter.setConstant(true);\n                }\n\n                if ((name.nameHashCode64() == FnvHash.Constants.MEMBER\n                        || name.nameHashCode64() == FnvHash.Constants.STATIC)\n                        && lexer.token() == Token.FUNCTION) {\n                    if (name.nameHashCode64() == FnvHash.Constants.MEMBER) {\n                        parameter.setMember(true);\n                    }\n                    OracleFunctionDataType functionDataType = new OracleFunctionDataType();\n                    functionDataType.setStatic(name.nameHashCode64() == FnvHash.Constants.STATIC);\n                    lexer.nextToken();\n                    functionDataType.setName(lexer.stringVal());\n                    accept(Token.IDENTIFIER);\n                    if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        this.parserParameters(functionDataType.getParameters(), functionDataType);\n                        accept(Token.RPAREN);\n                    }\n                    accept(Token.RETURN);\n                    functionDataType.setReturnDataType(this.exprParser.parseDataType(false));\n                    dataType = functionDataType;\n                    name = null;\n\n                    if (lexer.token() == Token.IS) {\n                        lexer.nextToken();\n                        SQLStatement block = this.parseBlock();\n                        functionDataType.setBlock(block);\n                    }\n                } else if ((name.nameHashCode64() == FnvHash.Constants.MEMBER\n                        || name.nameHashCode64() == FnvHash.Constants.STATIC)\n                        && lexer.token() == Token.PROCEDURE) {\n                    if (name.nameHashCode64() == FnvHash.Constants.MEMBER) {\n                        parameter.setMember(true);\n                    }\n                    OracleProcedureDataType procedureDataType = new OracleProcedureDataType();\n                    procedureDataType.setStatic(name.nameHashCode64() == FnvHash.Constants.STATIC);\n                    lexer.nextToken();\n                    procedureDataType.setName(lexer.stringVal());\n                    accept(Token.IDENTIFIER);\n                    if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        this.parserParameters(procedureDataType.getParameters(), procedureDataType);\n                        accept(Token.RPAREN);\n                    }\n\n                    dataType = procedureDataType;\n                    name = null;\n\n                    if (lexer.token() == Token.IS) {\n                        lexer.nextToken();\n                        SQLStatement block = this.parseBlock();\n                        procedureDataType.setBlock(block);\n                    }\n                } else {\n                    dataType = this.exprParser.parseDataType(false);\n                }\n\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    parameter.setNotNull(true);\n                }\n\n                if (lexer.token() == Token.COLONEQ || lexer.token() == Token.DEFAULT) {\n                    lexer.nextToken();\n                    parameter.setDefaultValue(this.exprParser.expr());\n                }\n            }\n\n            parameter.setName(name);\n            parameter.setDataType(dataType);\n\n            parameters.add(parameter);\n            Token token = lexer.token();\n            if (token == Token.COMMA || token == Token.SEMI || token == Token.IS) {\n                lexer.nextToken();\n            }\n\n            token = lexer.token();\n            if (token != Token.BEGIN\n                    && token != Token.RPAREN\n                    && token != Token.EOF\n                    && token != Token.FUNCTION\n                    && !lexer.identifierEquals(\"DETERMINISTIC\")) {\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    public OracleSelectParser createSQLSelectParser() {\n        return new OracleSelectParser(this.exprParser, selectListCache);\n    }\n\n    public OracleStatement parseInsert() {\n        if (lexer.token() == Token.LPAREN) {\n            OracleInsertStatement stmt = new OracleInsertStatement();\n            parseInsert0(stmt, false);\n\n            stmt.setReturning(parseReturningClause());\n            stmt.setErrorLogging(parseErrorLoggingClause());\n\n            return stmt;\n        }\n\n        accept(Token.INSERT);\n\n        List<SQLHint> hints = new ArrayList<SQLHint>();\n\n        parseHints(hints);\n\n        if (lexer.token() == Token.INTO) {\n            OracleInsertStatement stmt = new OracleInsertStatement();\n            stmt.setHints(hints);\n\n            parseInsert0(stmt);\n\n            stmt.setReturning(parseReturningClause());\n            stmt.setErrorLogging(parseErrorLoggingClause());\n\n            return stmt;\n        }\n\n        OracleMultiInsertStatement stmt = parseMultiInsert();\n        stmt.setHints(hints);\n        return stmt;\n    }\n\n    public OracleMultiInsertStatement parseMultiInsert() {\n        OracleMultiInsertStatement stmt = new OracleMultiInsertStatement();\n\n        if (lexer.token() == Token.ALL) {\n            lexer.nextToken();\n            stmt.setOption(OracleMultiInsertStatement.Option.ALL);\n        } else if (lexer.token() == Token.FIRST || lexer.identifierEquals(\"FIRST\")) {\n            lexer.nextToken();\n            stmt.setOption(OracleMultiInsertStatement.Option.FIRST);\n        }\n\n        while (lexer.token() == Token.INTO) {\n            OracleMultiInsertStatement.InsertIntoClause clause = new OracleMultiInsertStatement.InsertIntoClause();\n\n            boolean acceptSubQuery = stmt.getEntries().isEmpty();\n            parseInsert0(clause, acceptSubQuery);\n\n            clause.setReturning(parseReturningClause());\n            clause.setErrorLogging(parseErrorLoggingClause());\n\n            stmt.addEntry(clause);\n        }\n\n        if (lexer.token() == Token.WHEN) {\n            OracleMultiInsertStatement.ConditionalInsertClause clause = new OracleMultiInsertStatement.ConditionalInsertClause();\n\n            while (lexer.token() == Token.WHEN) {\n                lexer.nextToken();\n\n                OracleMultiInsertStatement.ConditionalInsertClauseItem item = new OracleMultiInsertStatement.ConditionalInsertClauseItem();\n\n                item.setWhen(this.exprParser.expr());\n                accept(Token.THEN);\n                OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause();\n                parseInsert0(insertInto);\n                item.setThen(insertInto);\n\n                clause.addItem(item);\n            }\n\n            if (lexer.token() == Token.ELSE) {\n                lexer.nextToken();\n\n                OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause();\n                parseInsert0(insertInto, false);\n                clause.setElseItem(insertInto);\n            }\n            stmt.addEntry(clause);\n        }\n\n        SQLSelect subQuery = this.createSQLSelectParser().select();\n        stmt.setSubQuery(subQuery);\n\n        return stmt;\n    }\n\n    public OracleReturningClause parseReturningClause() {\n        OracleReturningClause clause = null;\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n            clause = new OracleReturningClause();\n\n            for (; ; ) {\n                SQLExpr item = exprParser.expr();\n                clause.addItem(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.INTO);\n            for (; ; ) {\n                SQLExpr item = exprParser.expr();\n                clause.addValue(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n        return clause;\n    }\n\n    public OracleExplainStatement parseExplain() {\n        accept(Token.EXPLAIN);\n        acceptIdentifier(\"PLAN\");\n        OracleExplainStatement stmt = new OracleExplainStatement();\n\n        if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n            acceptIdentifier(\"STATEMENT_ID\");\n            accept(Token.EQ);\n            stmt.setStatementId(this.exprParser.primary());\n        }\n\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n            stmt.setInto(this.exprParser.name());\n        }\n\n        accept(Token.FOR);\n        stmt.setStatement(parseStatement());\n\n        return stmt;\n    }\n\n    public SQLAnalyzeTableStatement parseAnalyzeTable() {\n        accept(Token.TABLE);\n        SQLAnalyzeTableStatement stmt = new SQLAnalyzeTableStatement();\n\n        List<SQLName> names = new ArrayList<SQLName>();\n        this.exprParser.names(names, stmt);\n\n        for (SQLName name : names) {\n            stmt.setTable(new SQLExprTableSource(name));\n        }\n\n        if (lexer.token() == Token.PARTITION) {\n            stmt.setPartition(\n                    parsePartitionRef()\n            );\n        }\n\n        if (lexer.token() == Token.COMPUTE) {\n            lexer.nextToken();\n            acceptIdentifier(\"STATISTICS\");\n            stmt.setComputeStatistics(true);\n        }\n\n        return stmt;\n    }\n\n    public OracleDeleteStatement parseDeleteStatement() {\n        OracleDeleteStatement deleteStatement = new OracleDeleteStatement();\n\n        if (lexer.token() == Token.DELETE) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            parseHints(deleteStatement.getHints());\n\n            if (lexer.token() == (Token.FROM)) {\n                lexer.nextToken();\n            }\n\n            if (lexer.identifierEquals(\"ONLY\")) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                SQLName tableName = exprParser.name();\n                deleteStatement.setTableName(tableName);\n\n                accept(Token.RPAREN);\n            } else if (lexer.token() == Token.LPAREN) {\n                SQLTableSource tableSource = this.createSQLSelectParser().parseTableSource();\n                deleteStatement.setTableSource(tableSource);\n            } else {\n                SQLName tableName = exprParser.name();\n                deleteStatement.setTableName(tableName);\n            }\n\n            deleteStatement.setAlias(tableAlias());\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            deleteStatement.setWhere(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            OracleReturningClause clause = this.parseReturningClause();\n            deleteStatement.setReturning(clause);\n        }\n        if (lexer.identifierEquals(\"RETURN\") || lexer.identifierEquals(\"RETURNING\")) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        if (lexer.identifierEquals(\"LOG\")) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        return deleteStatement;\n    }\n\n    public SQLStatement parseCreateDbLink() {\n        accept(Token.CREATE);\n\n        OracleCreateDatabaseDbLinkStatement dbLink = new OracleCreateDatabaseDbLinkStatement();\n\n        if (lexer.identifierEquals(\"SHARED\")) {\n            dbLink.setShared(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"PUBLIC\")) {\n            dbLink.setPublic(true);\n            lexer.nextToken();\n        }\n\n        accept(Token.DATABASE);\n        acceptIdentifier(\"LINK\");\n\n        dbLink.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.CONNECT) {\n            lexer.nextToken();\n            accept(Token.TO);\n\n            dbLink.setUser(this.exprParser.name());\n\n            if (lexer.identifierEquals(FnvHash.Constants.IDENTIFIED)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                dbLink.setPassword(lexer.stringVal());\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    lexer.nextToken();\n                } else {\n                    accept(Token.LITERAL_ALIAS);\n                }\n            }\n        }\n\n        if (lexer.identifierEquals(\"AUTHENTICATED\")) {\n            lexer.nextToken();\n            accept(Token.BY);\n            dbLink.setAuthenticatedUser(this.exprParser.name());\n\n            acceptIdentifier(\"IDENTIFIED\");\n            accept(Token.BY);\n            dbLink.setPassword(lexer.stringVal());\n            accept(Token.IDENTIFIER);\n        }\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n            dbLink.setUsing(this.exprParser.expr());\n        }\n\n        return dbLink;\n    }\n\n    public OracleCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n        OracleCreateIndexStatement stmt = new OracleCreateIndexStatement();\n        if (lexer.token() == Token.UNIQUE) {\n            stmt.setType(\"UNIQUE\");\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"BITMAP\")) {\n            stmt.setType(\"BITMAP\");\n            lexer.nextToken();\n        }\n\n        accept(Token.INDEX);\n\n        stmt.setName(this.exprParser.name());\n\n        accept(Token.ON);\n\n        if (lexer.identifierEquals(\"CLUSTER\")) {\n            lexer.nextToken();\n            stmt.setCluster(true);\n        }\n\n        stmt.setTable(this.exprParser.name());\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            String alias = lexer.stringVal();\n            stmt.getTable().setAlias(alias);\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n                stmt.addItem(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        for (; ; ) {\n            this.getExprParser().parseSegmentAttributes(stmt);\n\n            if (lexer.token() == Token.COMPUTE) {\n                lexer.nextToken();\n                acceptIdentifier(\"STATISTICS\");\n                stmt.setComputeStatistics(true);\n                continue;\n            } else if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                stmt.setEnable(true);\n                continue;\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                stmt.setEnable(false);\n                continue;\n            } else if (lexer.identifierEquals(\"ONLINE\")) {\n                lexer.nextToken();\n                stmt.setOnline(true);\n                continue;\n            } else if (lexer.identifierEquals(\"NOPARALLEL\")) {\n                lexer.nextToken();\n                stmt.setNoParallel(true);\n                continue;\n            } else if (lexer.identifierEquals(\"PARALLEL\")) {\n                lexer.nextToken();\n                stmt.setParallel(this.exprParser.expr());\n                continue;\n            } else if (lexer.token() == Token.INDEX) {\n                lexer.nextToken();\n                acceptIdentifier(\"ONLY\");\n                acceptIdentifier(\"TOPLEVEL\");\n                stmt.setIndexOnlyTopLevel(true);\n                continue;\n            } else if (lexer.identifierEquals(\"SORT\")) {\n                lexer.nextToken();\n                stmt.setSort(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(\"NOSORT\")) {\n                lexer.nextToken();\n                stmt.setSort(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.REVERSE) {\n                lexer.nextToken();\n                stmt.setReverse(true);\n                continue;\n            } else if (lexer.identifierEquals(\"LOCAL\")) {\n                lexer.nextToken();\n                stmt.setLocal(true);\n\n                for (; ; ) {\n                    if (lexer.token() == Token.STORE) {\n                        lexer.nextToken();\n                        accept(Token.IN);\n                        accept(Token.LPAREN);\n                        this.exprParser.names(stmt.getLocalStoreIn(), stmt);\n                        accept(Token.RPAREN);\n                    } else if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        for (; ; ) {\n                            OraclePartitionSingle partition = this.getExprParser().parsePartition();\n                            partition.setParent(stmt);\n                            stmt.getLocalPartitions().add(partition);\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            } else if (lexer.token() == Token.RPAREN) {\n                                lexer.nextToken();\n                                break;\n                            }\n                            throw new ParserException(\"TODO : \" + lexer.info());\n                        }\n                    } else {\n                        break;\n                    }\n                }\n            } else if (lexer.identifierEquals(\"GLOBAL\")) {\n                lexer.nextToken();\n                stmt.setGlobal(true);\n\n                if (lexer.token() == Token.PARTITION) {\n                    lexer.nextToken();\n\n                    accept(Token.BY);\n\n                    if (lexer.identifierEquals(\"RANGE\")) {\n                        SQLPartitionByRange partitionByRange = this.getExprParser().partitionByRange();\n                        this.getExprParser().partitionClauseRest(partitionByRange);\n                        partitionByRange.setParent(stmt);\n                        stmt.getGlobalPartitions().add(partitionByRange);\n                        continue;\n                    } else if (lexer.identifierEquals(\"HASH\")) {\n                        SQLPartitionByHash partitionByHash = this.getExprParser().partitionByHash();\n                        this.getExprParser().partitionClauseRest(partitionByHash);\n\n                        if (lexer.token() == Token.LPAREN) {\n                            lexer.nextToken();\n                            for (; ; ) {\n                                OraclePartitionSingle partition = this.getExprParser().parsePartition();\n                                partitionByHash.addPartition(partition);\n                                if (lexer.token() == Token.COMMA) {\n                                    lexer.nextToken();\n                                    continue;\n                                } else if (lexer.token() == Token.RPAREN) {\n                                    lexer.nextToken();\n                                    break;\n                                }\n                                throw new ParserException(\"TODO : \" + lexer.info());\n                            }\n                        }\n                        partitionByHash.setParent(stmt);\n                        stmt.getGlobalPartitions().add(partitionByHash);\n                        continue;\n                    }\n                }\n\n                break;\n            } else {\n                break;\n            }\n        }\n        return stmt;\n    }\n\n    public SQLCreateSequenceStatement parseCreateSequence() {\n        accept(Token.CREATE);\n        accept(Token.SEQUENCE);\n\n        SQLCreateSequenceStatement stmt = new SQLCreateSequenceStatement();\n        stmt.setDbType(DbType.oracle);\n        stmt.setName(this.exprParser.name());\n\n        for (; ; ) {\n            if (lexer.token() == Token.START) {\n                lexer.nextToken();\n                accept(Token.WITH);\n                stmt.setStartWith(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"INCREMENT\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n                stmt.setIncrementBy(this.exprParser.expr());\n                continue;\n            } else if (lexer.token() == Token.CACHE) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.TRUE);\n\n                if (lexer.token() == Token.LITERAL_INT || lexer.token() == Token.QUES) {\n                    stmt.setCacheValue(this.exprParser.primary());\n                }\n\n                continue;\n            } else if (lexer.token() == Token.NOCACHE) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.ORDER) {\n                lexer.nextToken();\n                stmt.setOrder(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(\"NOORDER\")) {\n                lexer.nextToken();\n                stmt.setOrder(Boolean.FALSE);\n                continue;\n            } else if (lexer.identifierEquals(\"CYCLE\")) {\n                lexer.nextToken();\n                stmt.setCycle(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(\"NOCYCLE\")) {\n                lexer.nextToken();\n                stmt.setCycle(Boolean.FALSE);\n                continue;\n            } else if (lexer.identifierEquals(\"MINVALUE\")) {\n                lexer.nextToken();\n                stmt.setMinValue(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"MAXVALUE\")) {\n                lexer.nextToken();\n                stmt.setMaxValue(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"NOMAXVALUE\")) {\n                lexer.nextToken();\n                stmt.setNoMaxValue(true);\n                continue;\n            } else if (lexer.identifierEquals(\"NOMINVALUE\")) {\n                lexer.nextToken();\n                stmt.setNoMinValue(true);\n                continue;\n            }\n            break;\n        }\n\n        return stmt;\n    }\n\n    public SQLCreateProcedureStatement parseCreateProcedure() {\n        SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n            if (lexer.token() == Token.OR) {\n                lexer.nextToken();\n                accept(Token.REPLACE);\n                stmt.setOrReplace(true);\n            }\n        } else {\n            stmt.setCreate(false);\n        }\n\n        accept(Token.PROCEDURE);\n\n        SQLName procedureName = this.exprParser.name();\n        stmt.setName(procedureName);\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            parserParameters(stmt.getParameters(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(\"AUTHID\")) {\n            lexer.nextToken();\n            String strVal = lexer.stringVal();\n            if (lexer.identifierEquals(\"CURRENT_USER\")) {\n                lexer.nextToken();\n            } else {\n                acceptIdentifier(\"DEFINER\");\n            }\n            SQLName authid = new SQLIdentifierExpr(strVal);\n            stmt.setAuthid(authid);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WRAPPED)) {\n            lexer.nextToken();\n            int pos = lexer.text.indexOf(';', lexer.pos());\n            if (pos != -1) {\n                String wrappedString = lexer.subString(lexer.pos(), pos - lexer.pos());\n                stmt.setWrappedSource(wrappedString);\n                lexer.reset(pos, ';', Token.LITERAL_CHARS);\n                lexer.nextToken();\n                stmt.setAfterSemi(true);\n            } else {\n                String wrappedString = lexer.text.substring(lexer.pos());\n                stmt.setWrappedSource(wrappedString);\n                lexer.reset(lexer.text.length(), (char) LayoutCharacters.EOI, Token.EOF);\n            }\n            return stmt;\n        }\n\n        if (lexer.token() == Token.SEMI) {\n            lexer.nextToken();\n            return stmt;\n        }\n\n        if (lexer.token() == Token.IS) {\n            lexer.nextToken();\n        } else {\n            accept(Token.AS);\n        }\n\n        if (lexer.identifierEquals(\"LANGUAGE\")) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"JAVA\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"NAME\");\n                String javaCallSpec = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n                stmt.setJavaCallSpec(javaCallSpec);\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n            return stmt;\n        }\n\n        SQLStatement block = this.parseBlock();\n\n        stmt.setBlock(block);\n\n        if (lexer.identifierEquals(procedureName.getSimpleName())) {\n            lexer.nextToken();\n        }\n\n        return stmt;\n    }\n\n    public SQLUpdateStatement parseUpdateStatement() {\n        return new OracleUpdateParser(this.lexer).parseUpdateStatement();\n    }\n\n    public SQLStatement parseCreatePackage() {\n        accept(Token.CREATE);\n\n        boolean repalce = false;\n        if (lexer.token() == Token.OR) {\n            lexer.nextToken();\n            accept(Token.REPLACE);\n            repalce = true;\n        }\n\n        acceptIdentifier(\"PACKAGE\");\n\n        OracleCreatePackageStatement stmt = new OracleCreatePackageStatement();\n        stmt.setOrReplace(repalce);\n\n        if (lexer.identifierEquals(\"BODY\")) {\n            lexer.nextToken();\n            stmt.setBody(true);\n        }\n\n        SQLName pkgName = this.exprParser.name();\n        stmt.setName(pkgName);\n\n        if (lexer.token() == Token.IS) {\n            lexer.nextToken();\n        } else {\n            accept(Token.AS);\n        }\n\n        // this.parseStatementList(stmt.getStatements(), -1, stmt);\n        for (; ; ) {\n            if (lexer.token() == Token.IDENTIFIER) {\n                SQLDeclareStatement varDecl = new SQLDeclareStatement();\n                varDecl.setDbType(dbType);\n                varDecl.setParent(stmt);\n\n                SQLDeclareItem varItem = new SQLDeclareItem();\n\n                boolean type = false;\n                if (lexer.identifierEquals(FnvHash.Constants.TYPE)) {\n                    lexer.nextToken();\n                    type = true;\n                }\n\n                SQLName name = this.exprParser.name();\n                varItem.setName(name);\n\n                if (type) {\n                    accept(Token.IS);\n                    if (lexer.identifierEquals(FnvHash.Constants.RECORD)) {\n                        lexer.nextToken();\n\n                        SQLRecordDataType recordDataType = new SQLRecordDataType();\n\n                        accept(Token.LPAREN);\n                        for (; ; ) {\n                            SQLColumnDefinition column = this.exprParser.parseColumn();\n                            recordDataType.addColumn(column);\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                            break;\n                        }\n                        accept(Token.RPAREN);\n                        varItem.setDataType(recordDataType);\n                    } else if (lexer.token() == Token.TABLE) {\n                        lexer.nextToken();\n                        accept(Token.OF);\n\n                        SQLDataType tableOfDataType = this.exprParser.parseDataType(false);\n                        String typeName = \"TABLE OF \" + tableOfDataType.toString();\n                        SQLDataTypeImpl tableOfType = new SQLDataTypeImpl(typeName);\n\n                        if (lexer.token() == Token.INDEX) {\n                            lexer.nextToken();\n                            accept(Token.BY);\n                            SQLExpr indexBy = this.exprParser.primary();\n                            tableOfType.setIndexBy(indexBy);\n                        }\n                        tableOfType.setDbType(dbType);\n                        varItem.setDataType(tableOfType);\n                    } else {\n                        acceptIdentifier(\"REF\");\n                        accept(Token.CURSOR);\n                        varItem.setDataType(new SQLDataTypeImpl(\"REF CURSOR\"));\n                    }\n                } else {\n                    varItem.setDataType(this.exprParser.parseDataType(false));\n                }\n                varItem.setParent(varDecl);\n\n                if (lexer.token() == Token.COLONEQ) {\n                    lexer.nextToken();\n                    SQLExpr defaultVal = this.exprParser.expr();\n                    varItem.setValue(defaultVal);\n                }\n\n                varDecl.getItems().add(varItem);\n\n                accept(Token.SEMI);\n                varDecl.setAfterSemi(true);\n\n                stmt.getStatements().add(varDecl);\n            } else if (lexer.token() == Token.FUNCTION) {\n                SQLStatement function = this.parseFunction();\n                function.setParent(stmt);\n                stmt.getStatements().add(function);\n            } else if (lexer.token() == Token.PROCEDURE) {\n                SQLStatement proc = this.parseCreateProcedure();\n                proc.setParent(stmt);\n                stmt.getStatements().add(proc);\n            } else if (lexer.token() == Token.END) {\n                break;\n\n            } else if (lexer.token() == Token.BEGIN) {\n                lexer.nextToken();\n                SQLBlockStatement block = new SQLBlockStatement();\n                parseStatementList(block.getStatementList(), -1, block);\n                accept(Token.END);\n                block.setParent(stmt);\n                stmt.getStatements().add(block);\n\n                if (lexer.identifierEquals(pkgName.getSimpleName())) {\n                    lexer.nextToken();\n                    accept(Token.SEMI);\n                    return stmt;\n                }\n\n                break;\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n        }\n\n        accept(Token.END);\n\n        if (lexer.identifierEquals(pkgName.getSimpleName())) {\n            lexer.nextToken();\n        }\n\n        accept(Token.SEMI);\n        return stmt;\n    }\n\n    public SQLStatement parseCreateSynonym() {\n        OracleCreateSynonymStatement stmt = new OracleCreateSynonymStatement();\n        accept(Token.CREATE);\n\n        if (lexer.token() == Token.OR) {\n            lexer.nextToken();\n            accept(Token.REPLACE);\n            stmt.setOrReplace(true);\n        }\n\n        if (lexer.identifierEquals(\"PUBLIC\")) {\n            lexer.nextToken();\n            stmt.setPublic(true);\n        }\n\n        acceptIdentifier(\"SYNONYM\");\n\n        stmt.setName(this.exprParser.name());\n\n        accept(Token.FOR);\n\n        stmt.setObject(this.exprParser.name());\n        return stmt;\n    }\n\n    public SQLStatement parseCreateType() {\n        OracleCreateTypeStatement stmt = new OracleCreateTypeStatement();\n        accept(Token.CREATE);\n\n        if (lexer.token() == Token.OR) {\n            lexer.nextToken();\n            accept(Token.REPLACE);\n            stmt.setOrReplace(true);\n        }\n\n        acceptIdentifier(\"TYPE\");\n\n        if (lexer.identifierEquals(\"BODY\")) {\n            lexer.nextToken();\n            stmt.setBody(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.identifierEquals(FnvHash.Constants.UNDER)) {\n            lexer.nextToken();\n            SQLName under = this.exprParser.name();\n            stmt.setUnder(under);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.AUTHID)) {\n            lexer.nextToken();\n            SQLName authId = this.exprParser.name();\n            stmt.setAuthId(authId);\n        }\n\n        if (lexer.token() == Token.AS || lexer.token() == Token.IS) {\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(\"OBJECT\")) {\n            lexer.nextToken();\n            stmt.setObject(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STATIC)) {\n            this.parserParameters(stmt.getParameters(), stmt);\n        } else if (lexer.token() == Token.TABLE) {\n            lexer.nextToken();\n            accept(Token.OF);\n            SQLDataType dataType = this.exprParser.parseDataType();\n            stmt.setTableOf(dataType);\n\n            if (lexer.token() == Token.INDEX) {\n                lexer.nextToken();\n                accept(Token.BY);\n                SQLDataType indexByDataType = this.exprParser.parseDataType();\n                stmt.setIndexBy(indexByDataType);\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.VARRAY)) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            SQLExpr sizeLimit = this.exprParser.primary();\n            stmt.setVarraySizeLimit(sizeLimit);\n            accept(Token.RPAREN);\n\n            accept(Token.OF);\n            SQLDataType dataType = this.exprParser.parseDataType();\n            stmt.setVarrayDataType(dataType);\n        } else if (lexer.identifierEquals(FnvHash.Constants.WRAPPED)) {\n            int pos = lexer.text.indexOf(';', lexer.pos());\n            if (pos != -1) {\n                String wrappedString = lexer.subString(lexer.pos(), pos - lexer.pos());\n                stmt.setWrappedSource(wrappedString);\n                lexer.reset(pos, ';', Token.LITERAL_CHARS);\n                lexer.nextToken();\n            }\n        } else {\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                this.parserParameters(stmt.getParameters(), stmt);\n                stmt.setParen(true);\n                accept(Token.RPAREN);\n            } else {\n                this.parserParameters(stmt.getParameters(), stmt);\n                if (lexer.token() == Token.END) {\n                    lexer.nextToken();\n                }\n            }\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.NOT) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.FINAL)) {\n                    lexer.nextToken();\n                    stmt.setFinal(false);\n                } else {\n                    acceptIdentifier(\"INSTANTIABLE\");\n                    stmt.setInstantiable(false);\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.FINAL)) {\n                lexer.nextToken();\n                stmt.setFinal(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.INSTANTIABLE)) {\n                lexer.nextToken();\n                stmt.setInstantiable(true);\n            } else {\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.SEMI) {\n            lexer.nextToken();\n            stmt.setAfterSemi(true);\n        }\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class OracleUpdateParser extends SQLStatementParser {\n    public OracleUpdateParser(String sql) {\n        super(new OracleExprParser(sql));\n    }\n\n    public OracleUpdateParser(Lexer lexer) {\n        super(new OracleExprParser(lexer));\n    }\n\n    public OracleUpdateStatement parseUpdateStatement() {\n        OracleUpdateStatement update = new OracleUpdateStatement();\n\n        if (lexer.token() == Token.UPDATE) {\n            lexer.nextToken();\n\n            parseHints(update);\n\n            if (lexer.identifierEquals(\"ONLY\")) {\n                update.setOnly(true);\n            }\n\n            SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource();\n            update.setTableSource(tableSource);\n\n            if ((update.getAlias() == null) || (update.getAlias().length() == 0)) {\n                update.setAlias(tableAlias());\n            }\n        }\n\n        parseUpdateSet(update);\n\n        parseWhere(update);\n\n        parseReturn(update);\n\n        parseErrorLoging(update);\n\n        return update;\n    }\n\n    private void parseErrorLoging(OracleUpdateStatement update) {\n        if (lexer.identifierEquals(\"LOG\")) {\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n    }\n\n    private void parseReturn(OracleUpdateStatement update) {\n        if (lexer.token() == Token.RETURN || lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                SQLExpr item = this.exprParser.expr();\n                update.getReturning().add(item);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.INTO);\n\n            for (; ; ) {\n                SQLExpr item = this.exprParser.expr();\n                update.addReturningInto(item);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n        }\n    }\n\n    private void parseHints(OracleUpdateStatement update) {\n        this.exprParser.parseHints(update.getHints());\n    }\n\n    private void parseWhere(OracleUpdateStatement update) {\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            update.setWhere(this.exprParser.expr());\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTParameterizedVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.visitor.SQLASTParameterizedVisitor;\n\nimport java.util.List;\n\npublic class OracleASTParameterizedVisitor extends SQLASTParameterizedVisitor implements OracleASTVisitor {\n    public OracleASTParameterizedVisitor() {\n        super(DbType.oracle);\n    }\n\n    public OracleASTParameterizedVisitor(List<Object> parameters) {\n        super(DbType.oracle, parameters);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\") {\n        return true;\n    }\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.InsertIntoClause;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface OracleASTVisitor extends SQLASTVisitor {\n    default void endVisit(OracleAnalytic x) {\n    }\n\n    default void endVisit(OracleAnalyticWindowing x) {\n    }\n\n    default void endVisit(OracleDeleteStatement x) {\n        endVisit((SQLDeleteStatement) x);\n    }\n\n    default void endVisit(OracleIntervalExpr x) {\n    }\n\n    default void endVisit(OracleOuterExpr x) {\n    }\n\n    default void endVisit(OracleSelectJoin x) {\n    }\n\n    default void endVisit(OracleSelectRestriction.CheckOption x) {\n    }\n\n    default void endVisit(OracleSelectRestriction.ReadOnly x) {\n    }\n\n    default void endVisit(OracleSelectSubqueryTableSource x) {\n    }\n\n    default void endVisit(OracleUpdateStatement x) {\n    }\n\n    default boolean visit(OracleAnalytic x) {\n        return true;\n    }\n\n    default boolean visit(OracleAnalyticWindowing x) {\n        return true;\n    }\n\n    default boolean visit(OracleDeleteStatement x) {\n        return visit((SQLDeleteStatement) x);\n    }\n\n    default boolean visit(OracleIntervalExpr x) {\n        return true;\n    }\n\n    default boolean visit(OracleOuterExpr x) {\n        return true;\n    }\n\n    default boolean visit(OracleSelectJoin x) {\n        return true;\n    }\n\n    default boolean visit(OracleSelectRestriction.CheckOption x) {\n        return true;\n    }\n\n    default boolean visit(OracleSelectRestriction.ReadOnly x) {\n        return true;\n    }\n\n    default boolean visit(OracleSelectSubqueryTableSource x) {\n        return true;\n    }\n\n    default boolean visit(OracleUpdateStatement x) {\n        return visit((SQLUpdateStatement) x);\n    }\n\n    default boolean visit(SampleClause x) {\n        return true;\n    }\n\n    default void endVisit(SampleClause x) {\n    }\n\n    default boolean visit(OracleSelectTableReference x) {\n        return true;\n    }\n\n    default void endVisit(OracleSelectTableReference x) {\n    }\n\n    default boolean visit(PartitionExtensionClause x) {\n        return true;\n    }\n\n    default void endVisit(PartitionExtensionClause x) {\n    }\n\n    default boolean visit(OracleWithSubqueryEntry x) {\n        return true;\n    }\n\n    default void endVisit(OracleWithSubqueryEntry x) {\n    }\n\n    default boolean visit(SearchClause x) {\n        return true;\n    }\n\n    default void endVisit(SearchClause x) {\n    }\n\n    default boolean visit(CycleClause x) {\n        return true;\n    }\n\n    default void endVisit(CycleClause x) {\n    }\n\n    default boolean visit(OracleBinaryFloatExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleBinaryFloatExpr x) {\n    }\n\n    default boolean visit(OracleBinaryDoubleExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleBinaryDoubleExpr x) {\n    }\n\n    default boolean visit(OracleCursorExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleCursorExpr x) {\n    }\n\n    default boolean visit(OracleIsSetExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleIsSetExpr x) {\n    }\n\n    default boolean visit(ModelClause.ReturnRowsClause x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.ReturnRowsClause x) {\n    }\n\n    default boolean visit(ModelClause.MainModelClause x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.MainModelClause x) {\n    }\n\n    default boolean visit(ModelClause.ModelColumnClause x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.ModelColumnClause x) {\n    }\n\n    default boolean visit(ModelClause.QueryPartitionClause x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.QueryPartitionClause x) {\n    }\n\n    default boolean visit(ModelClause.ModelColumn x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.ModelColumn x) {\n    }\n\n    default boolean visit(ModelClause.ModelRulesClause x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.ModelRulesClause x) {\n    }\n\n    default boolean visit(ModelClause.CellAssignmentItem x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.CellAssignmentItem x) {\n    }\n\n    default boolean visit(ModelClause.CellAssignment x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause.CellAssignment x) {\n    }\n\n    default boolean visit(ModelClause x) {\n        return true;\n    }\n\n    default void endVisit(ModelClause x) {\n    }\n\n    default boolean visit(OracleReturningClause x) {\n        return true;\n    }\n\n    default void endVisit(OracleReturningClause x) {\n    }\n\n    default boolean visit(OracleInsertStatement x) {\n        return visit((SQLInsertStatement) x);\n    }\n\n    default void endVisit(OracleInsertStatement x) {\n        endVisit((SQLInsertStatement) x);\n    }\n\n    default boolean visit(InsertIntoClause x) {\n        return true;\n    }\n\n    default void endVisit(InsertIntoClause x) {\n    }\n\n    default boolean visit(OracleMultiInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleMultiInsertStatement x) {\n    }\n\n    default boolean visit(ConditionalInsertClause x) {\n        return true;\n    }\n\n    default void endVisit(ConditionalInsertClause x) {\n    }\n\n    default boolean visit(ConditionalInsertClauseItem x) {\n        return true;\n    }\n\n    default void endVisit(ConditionalInsertClauseItem x) {\n    }\n\n    default boolean visit(OracleSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(OracleSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(OracleLockTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleLockTableStatement x) {\n    }\n\n    default boolean visit(OracleAlterSessionStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterSessionStatement x) {\n    }\n\n    default boolean visit(OracleDatetimeExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleDatetimeExpr x) {\n    }\n\n    default boolean visit(OracleSysdateExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleSysdateExpr x) {\n    }\n\n    default boolean visit(OracleArgumentExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleArgumentExpr x) {\n    }\n\n    default boolean visit(OracleSetTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleSetTransactionStatement x) {\n    }\n\n    default boolean visit(OracleExplainStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleExplainStatement x) {\n    }\n\n    default boolean visit(OracleAlterTableDropPartition x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableDropPartition x) {\n    }\n\n    default boolean visit(OracleAlterTableTruncatePartition x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableTruncatePartition x) {\n    }\n\n    default boolean visit(OracleAlterTableSplitPartition.TableSpaceItem x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableSplitPartition.TableSpaceItem x) {\n    }\n\n    default boolean visit(OracleAlterTableSplitPartition.UpdateIndexesClause x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableSplitPartition.UpdateIndexesClause x) {\n    }\n\n    default boolean visit(OracleAlterTableSplitPartition.NestedTablePartitionSpec x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableSplitPartition.NestedTablePartitionSpec x) {\n    }\n\n    default boolean visit(OracleAlterTableSplitPartition x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableSplitPartition x) {\n    }\n\n    default boolean visit(OracleAlterTableModify x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableModify x) {\n    }\n\n    default boolean visit(OracleCreateIndexStatement x) {\n        return visit((SQLCreateIndexStatement) x);\n    }\n\n    default void endVisit(OracleCreateIndexStatement x) {\n        endVisit((SQLCreateIndexStatement) x);\n    }\n\n    default boolean visit(OracleForStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleForStatement x) {\n    }\n\n    default boolean visit(OracleRangeExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleRangeExpr x) {\n    }\n\n    default boolean visit(OraclePrimaryKey x) {\n        return true;\n    }\n\n    default void endVisit(OraclePrimaryKey x) {\n    }\n\n    default boolean visit(OracleCreateTableStatement x) {\n        return visit((SQLCreateTableStatement) x);\n    }\n\n    default void endVisit(OracleCreateTableStatement x) {\n        endVisit((SQLCreateTableStatement) x);\n    }\n\n    default boolean visit(OracleStorageClause x) {\n        return true;\n    }\n\n    default void endVisit(OracleStorageClause x) {\n    }\n\n    default boolean visit(OracleGotoStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleGotoStatement x) {\n    }\n\n    default boolean visit(OracleLabelStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleLabelStatement x) {\n    }\n\n    default boolean visit(OracleAlterTriggerStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTriggerStatement x) {\n    }\n\n    default boolean visit(OracleAlterSynonymStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterSynonymStatement x) {\n    }\n\n    default boolean visit(OracleAlterViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterViewStatement x) {\n    }\n\n    default boolean visit(OracleAlterTableMoveTablespace x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableMoveTablespace x) {\n    }\n\n    default boolean visit(OracleAlterTableRowMovement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableRowMovement x) {\n    }\n\n    default boolean visit(OracleAlterTableShrinkSpace x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTableShrinkSpace x) {\n    }\n\n    default boolean visit(OracleAlterSummaryStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterSummaryStatement x) {\n    }\n\n    default boolean visit(OracleFileSpecification x) {\n        return true;\n    }\n\n    default void endVisit(OracleFileSpecification x) {\n    }\n\n    default boolean visit(OracleAlterTablespaceAddDataFile x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTablespaceAddDataFile x) {\n    }\n\n    default boolean visit(OracleAlterTablespaceStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterTablespaceStatement x) {\n    }\n\n    default boolean visit(OracleExitStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleExitStatement x) {\n    }\n\n    default boolean visit(OracleContinueStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleContinueStatement x) {\n    }\n\n    default boolean visit(OracleRaiseStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleRaiseStatement x) {\n    }\n\n    default boolean visit(OracleCreateDatabaseDbLinkStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleCreateDatabaseDbLinkStatement x) {\n    }\n\n    default boolean visit(OracleDropDbLinkStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleDropDbLinkStatement x) {\n    }\n\n    default boolean visit(OracleDataTypeIntervalYear x) {\n        return true;\n    }\n\n    default void endVisit(OracleDataTypeIntervalYear x) {\n    }\n\n    default boolean visit(OracleDataTypeIntervalDay x) {\n        return true;\n    }\n\n    default void endVisit(OracleDataTypeIntervalDay x) {\n    }\n\n    default boolean visit(OracleUsingIndexClause x) {\n        return true;\n    }\n\n    default void endVisit(OracleUsingIndexClause x) {\n    }\n\n    default boolean visit(OracleLobStorageClause x) {\n        return true;\n    }\n\n    default void endVisit(OracleLobStorageClause x) {\n    }\n\n    default boolean visit(OracleUnique x) {\n        return visit((SQLUnique) x);\n    }\n\n    default void endVisit(OracleUnique x) {\n        endVisit((SQLUnique) x);\n    }\n\n    default boolean visit(OracleForeignKey x) {\n        return visit((SQLForeignKeyImpl) x);\n    }\n\n    default void endVisit(OracleForeignKey x) {\n        endVisit((SQLForeignKeyImpl) x);\n    }\n\n    default boolean visit(OracleCheck x) {\n        return visit((SQLCheck) x);\n    }\n\n    default void endVisit(OracleCheck x) {\n        endVisit((SQLCheck) x);\n    }\n\n    default boolean visit(OracleSupplementalIdKey x) {\n        return true;\n    }\n\n    default void endVisit(OracleSupplementalIdKey x) {\n    }\n\n    default boolean visit(OracleSupplementalLogGrp x) {\n        return true;\n    }\n\n    default void endVisit(OracleSupplementalLogGrp x) {\n    }\n\n    default boolean visit(OracleCreateTableStatement.Organization x) {\n        return true;\n    }\n\n    default void endVisit(OracleCreateTableStatement.Organization x) {\n    }\n\n    default boolean visit(OracleCreateTableStatement.OIDIndex x) {\n        return true;\n    }\n\n    default void endVisit(OracleCreateTableStatement.OIDIndex x) {\n    }\n\n    default boolean visit(OracleCreatePackageStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleCreatePackageStatement x) {\n    }\n\n    default boolean visit(OracleExecuteImmediateStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleExecuteImmediateStatement x) {\n    }\n\n    default boolean visit(OracleTreatExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleTreatExpr x) {\n    }\n\n    default boolean visit(OracleCreateSynonymStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleCreateSynonymStatement x) {\n    }\n\n    default boolean visit(OracleCreateTypeStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleCreateTypeStatement x) {\n    }\n\n    default boolean visit(OraclePipeRowStatement x) {\n        return true;\n    }\n\n    default void endVisit(OraclePipeRowStatement x) {\n    }\n\n    default boolean visit(OracleIsOfTypeExpr x) {\n        return true;\n    }\n\n    default void endVisit(OracleIsOfTypeExpr x) {\n    }\n\n    default boolean visit(OracleRunStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleRunStatement x) {\n    }\n\n    default boolean visit(OracleXmlColumnProperties x) {\n        return true;\n    }\n\n    default void endVisit(OracleXmlColumnProperties x) {\n    }\n\n    default boolean visit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {\n        return true;\n    }\n\n    default void endVisit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {\n    }\n\n    default boolean visit(OracleAlterPackageStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleAlterPackageStatement x) {\n    }\n\n    default boolean visit(OracleDropPackageStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleDropPackageStatement x) {\n    }\n\n    default boolean visit(OracleCreateTableSpaceStatement x) {\n        return true;\n    }\n\n    default void endVisit(OracleCreateTableSpaceStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements OracleASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleEvalVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class OracleEvalVisitor extends OracleASTVisitorAdapter implements SQLEvalVisitor {\n    private Map<String, Function> functions = new HashMap<String, Function>();\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public OracleEvalVisitor() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public OracleEvalVisitor(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLUnaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleExportParameterVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLInListExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OracleExportParameterVisitor extends OracleParameterizedOutputVisitor implements ExportParameterVisitor {\n    /**\n     * true= if require parameterized sql output\n     */\n    private final boolean requireParameterizedOutput;\n\n    public OracleExportParameterVisitor(List<Object> parameters,\n                                        StringBuilder appender,\n                                        final boolean wantParameterizedOutput) {\n        super(appender, false);\n        this.parameters = parameters;\n        this.requireParameterizedOutput = wantParameterizedOutput;\n    }\n\n    public OracleExportParameterVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public OracleExportParameterVisitor(List<Object> parameters) {\n        this(parameters, new StringBuilder(), false);\n    }\n\n    public OracleExportParameterVisitor(final StringBuilder appender) {\n        this(new ArrayList<Object>(), appender, true);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public boolean visit(SQLSelectItem x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOrderBy x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelectGroupByClause x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getArguments());\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.oracle.Oracle;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OraclePartitionSingle;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.NestedTablePartitionSpec;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.TableSpaceItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition.UpdateIndexesClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.InsertIntoClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.CheckOption;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.ReadOnly;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleProcedureDataType;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\nimport java.util.List;\n\npublic class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleASTVisitor {\n    private final boolean printPostSemi;\n\n    {\n        this.dbType = DbType.oracle;\n    }\n\n    public OracleOutputVisitor(StringBuilder appender) {\n        this(appender, true);\n    }\n\n    public OracleOutputVisitor(StringBuilder appender, boolean printPostSemi) {\n        super(appender, DbType.oracle, Oracle.DIALECT);\n        this.printPostSemi = printPostSemi;\n    }\n\n    public boolean isPrintPostSemi() {\n        return printPostSemi;\n    }\n\n    private void printHints(List<SQLHint> hints) {\n        if (hints.size() > 0) {\n            print0(\"/*+ \");\n            printAndAccept(hints, \", \");\n            print0(\" */\");\n        }\n    }\n\n    public boolean visit(OracleAnalytic x) {\n        print0(ucase ? \"(\" : \"(\");\n\n        boolean space = false;\n        if (x.getPartitionBy().size() > 0) {\n            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n            printAndAccept(x.getPartitionBy(), \", \");\n\n            space = true;\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            if (space) {\n                print(' ');\n            }\n            visit(orderBy);\n            space = true;\n        }\n\n        OracleAnalyticWindowing windowing = x.getWindowing();\n        if (windowing != null) {\n            if (space) {\n                print(' ');\n            }\n            visit(windowing);\n        }\n\n        if (x.isWindowingPreceding()) {\n            print0(ucase ? \" PRECEDING\" : \" preceding\");\n        }\n        if (x.isWindowingBetweenEndFollowing()) {\n            print0(ucase ? \" FOLLOWING\" : \" following\");\n        }\n\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(OracleAnalyticWindowing x) {\n        print0(x.getType().name().toUpperCase());\n        print(' ');\n\n        SQLExpr expr = x.getExpr();\n\n        if (expr instanceof SQLBetweenExpr && x.getParent() instanceof SQLOver) {\n            SQLOver over = (SQLOver) x.getParent();\n            SQLBetweenExpr betweenExpr = (SQLBetweenExpr) expr;\n            SQLOver.WindowingBound beginBound = over.getWindowingBetweenBeginBound();\n            if (beginBound != null) {\n                print0(ucase ? \" BETWEEN \" : \" between \");\n                betweenExpr.getBeginExpr().accept(this);\n                print(' ');\n                print0(ucase ? beginBound.name : beginBound.nameLCase);\n                print0(ucase ? \" AND \" : \" and \");\n                betweenExpr.getEndExpr().accept(this);\n                return false;\n            }\n        }\n\n        expr.accept(this);\n\n        return false;\n    }\n\n    public boolean visit(OracleDeleteStatement x) {\n        print0(ucase ? \"DELETE \" : \"delete \");\n\n        SQLTableSource tableSource = x.getTableSource();\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        print0(ucase ? \"FROM \" : \"from \");\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY (\" : \"only (\");\n            x.getTableName().accept(this);\n            print(')');\n\n            printAlias(x.getAlias());\n        } else {\n            x.getTableSource().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            this.indentCount++;\n            print0(ucase ? \"WHERE \" : \"where \");\n            x.getWhere().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getReturning() != null) {\n            println();\n            x.getReturning().accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleIntervalExpr x) {\n        if (x.getValue() instanceof SQLLiteralExpr || x.getValue() instanceof SQLVariantRefExpr) {\n            print0(ucase ? \"INTERVAL \" : \"interval \");\n        }\n        x.getValue().accept(this);\n        print(' ');\n\n        print0(x.getType().name());\n\n        if (x.getPrecision() != null) {\n            print('(');\n            printExpr(x.getPrecision(), parameterized);\n            if (x.getFactionalSecondsPrecision() != null) {\n                print0(\", \");\n                print(x.getFactionalSecondsPrecision().intValue());\n            }\n            print(')');\n        }\n\n        if (x.getToType() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            print0(x.getToType().name());\n            if (x.getToFactionalSecondsPrecision() != null) {\n                print('(');\n                printExpr(x.getToFactionalSecondsPrecision(), parameterized);\n                print(')');\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleOuterExpr x) {\n        x.getExpr().accept(this);\n        print0(\"(+)\");\n        return false;\n    }\n\n    public boolean visit(SQLScriptCommitStatement astNode) {\n        print('/');\n        println();\n        return false;\n    }\n\n    public boolean visit(SQLSelect x) {\n        SQLWithSubqueryClause with = x.getWithSubQuery();\n        if (with != null) {\n            with.accept(this);\n            println();\n        }\n\n        SQLSelectQuery query = x.getQuery();\n        query.accept(this);\n\n        if (x.getRestriction() != null) {\n            println();\n            print(\"WITH \");\n            x.getRestriction().accept(this);\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            boolean hasFirst = false;\n            if (query instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n                hasFirst = queryBlock.getFirst() != null;\n            }\n\n            if (!hasFirst) {\n                println();\n                orderBy.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleSelectJoin x) {\n        x.getLeft().accept(this);\n        SQLTableSource right = x.getRight();\n\n        if (x.getJoinType() == JoinType.COMMA) {\n            print0(\", \");\n            x.getRight().accept(this);\n        } else {\n            boolean isRoot = x.getParent() instanceof SQLSelectQueryBlock;\n            if (isRoot) {\n                this.indentCount++;\n            }\n\n            println();\n            print0(ucase ? x.getJoinType().name : x.getJoinType().nameLCase);\n            print(' ');\n\n            if (right instanceof SQLJoinTableSource) {\n                print('(');\n                incrementIndent();\n                println();\n                right.accept(this);\n                decrementIndent();\n                println();\n                print(')');\n            } else {\n                right.accept(this);\n            }\n\n            if (isRoot) {\n                this.indentCount--;\n            }\n\n            if (x.getCondition() != null) {\n                print0(ucase ? \" ON \" : \" on \");\n                incrementIndent();\n                x.getCondition().accept(this);\n                decrementIndent();\n                print(' ');\n                if (x.getAfterCommentsDirect() != null) {\n                    printAfterComments(x.getAfterCommentsDirect());\n                    println();\n                }\n            }\n\n            if (x.getUsing().size() > 0) {\n                print0(ucase ? \" USING (\" : \" using (\");\n                printAndAccept(x.getUsing(), \", \");\n                print(')');\n            }\n\n            printFlashback(x.getFlashback());\n        }\n\n        SQLPivot pivot = x.getPivot();\n        if (pivot != null) {\n            println();\n            pivot.accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLSelectOrderByItem x) {\n        x.getExpr().accept(this);\n        if (x.getType() != null) {\n            print(' ');\n\n            String typeName = x.getType().name();\n            print0(ucase ? typeName.toUpperCase() : typeName.toLowerCase());\n        }\n\n        if (x.getNullsOrderType() != null) {\n            print(' ');\n            print0(x.getNullsOrderType().toFormalString());\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLSelectQueryBlock select) {\n        if (select instanceof OracleSelectQueryBlock) {\n            return visit((OracleSelectQueryBlock) select);\n        }\n\n        return super.visit(select);\n    }\n\n    public boolean visit(OracleSelectQueryBlock x) {\n        if (isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        if (x.getHintsSize() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == x.getDistionOption()) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        }\n\n        printSelectList(x.getSelectList());\n        printInto(x);\n        printFrom(x);\n        printWhere(x);\n        printHierarchical(x);\n        printGroupBy(x);\n        printModel(x);\n        printOrderBy(x);\n        printFetchFirst(x);\n\n        if (x.isForUpdate()) {\n            println();\n            print0(ucase ? \"FOR UPDATE\" : \"for update\");\n            if (x.getForUpdateOfSize() > 0) {\n                print(\" OF \");\n                printAndAccept(x.getForUpdateOf(), \", \");\n            }\n\n            if (x.isNoWait()) {\n                print0(ucase ? \" NOWAIT\" : \" nowait\");\n            } else if (x.isSkipLocked()) {\n                print0(ucase ? \" SKIP LOCKED\" : \" skip locked\");\n            } else if (x.getWaitTime() != null) {\n                print0(ucase ? \" WAIT \" : \" wait \");\n                x.getWaitTime().accept(this);\n            }\n        }\n\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    protected void printFrom(SQLSelectQueryBlock x) {\n        println();\n        print0(ucase ? \"FROM \" : \"from \");\n        if (x.getCommentsAfterFrom() != null) {\n            printAfterComments(x.getCommentsAfterFrom());\n            println();\n        }\n        SQLTableSource from = x.getFrom();\n        if (from == null) {\n            print0(ucase ? \"DUAL\" : \"dual\");\n        } else {\n            from.accept(this);\n        }\n    }\n\n    private void printInto(OracleSelectQueryBlock x) {\n        SQLExprTableSource into = x.getInto();\n        if (into == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"INTO \" : \"into \");\n        into.accept(this);\n    }\n\n    private void printModel(OracleSelectQueryBlock x) {\n        ModelClause model = x.getModelClause();\n        if (model == null) {\n            return;\n        }\n        println();\n        model.accept(this);\n    }\n\n    public boolean visit(CheckOption x) {\n        print0(ucase ? \"CHECK OPTION\" : \"check option\");\n        if (x.getConstraint() != null) {\n            print0(ucase ? \" CONSTRAINT\" : \" constraint\");\n            print(' ');\n            x.getConstraint().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(ReadOnly x) {\n        print0(ucase ? \"READ ONLY\" : \"read only\");\n        if (x.getConstraint() != null) {\n            print0(ucase ? \" CONSTRAINT\" : \" constraint\");\n            print(' ');\n            x.getConstraint().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(OracleSelectSubqueryTableSource x) {\n        print('(');\n        this.indentCount++;\n        println();\n        x.getSelect().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        SQLPivot pivot = x.getPivot();\n        if (pivot != null) {\n            println();\n            pivot.accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        printFlashback(x.getFlashback());\n\n        if ((x.getAlias() != null) && (x.getAlias().length() != 0)) {\n            print(' ');\n            print0(x.getAlias());\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleSelectTableReference x) {\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY (\" : \"only (\");\n            printTableSourceExpr(x.getExpr());\n\n            if (x.getPartition() != null) {\n                print(' ');\n                x.getPartition().accept(this);\n            }\n\n            print(')');\n        } else {\n            printTableSourceExpr(x.getExpr());\n\n            if (x.getPartition() != null) {\n                print(' ');\n                x.getPartition().accept(this);\n            }\n        }\n\n        if (x.getHints().size() > 0) {\n            this.printHints(x.getHints());\n        }\n\n        if (x.getSampleClause() != null) {\n            print(' ');\n            x.getSampleClause().accept(this);\n        }\n        if (x.getAfterCommentsDirect() != null) {\n            printAfterComments(x.getAfterCommentsDirect());\n            println();\n        }\n        if (x.getPivot() != null) {\n            println();\n            x.getPivot().accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        printFlashback(x.getFlashback());\n\n        printAlias(x.getAlias());\n\n        return false;\n    }\n\n    private void printFlashback(SQLExpr flashback) {\n        if (flashback == null) {\n            return;\n        }\n\n        println();\n\n        if (flashback instanceof SQLBetweenExpr) {\n            flashback.accept(this);\n        } else {\n            print0(ucase ? \"AS OF \" : \"as of \");\n            flashback.accept(this);\n        }\n    }\n\n    public boolean visit(OracleUpdateStatement x) {\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY (\" : \"only (\");\n            x.getTableSource().accept(this);\n            print(')');\n        } else {\n            x.getTableSource().accept(this);\n        }\n\n        printAlias(x.getAlias());\n\n        println();\n\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            x.getItems().get(i).accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            this.indentCount++;\n            x.getWhere().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getReturning().size() > 0) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            printAndAccept(x.getReturning(), \", \");\n            print0(ucase ? \" INTO \" : \" into \");\n            printAndAccept(x.getReturningInto(), \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SampleClause x) {\n        print0(ucase ? \"SAMPLE \" : \"sample \");\n\n        if (x.isBlock()) {\n            print0(ucase ? \"BLOCK \" : \"block \");\n        }\n\n        print('(');\n        printAndAccept(x.getPercent(), \", \");\n        print(')');\n\n        if (x.getSeedValue() != null) {\n            print0(ucase ? \" SEED (\" : \" seed (\");\n            x.getSeedValue().accept(this);\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PartitionExtensionClause x) {\n        if (x.isSubPartition()) {\n            print0(ucase ? \"SUBPARTITION \" : \"subpartition \");\n        } else {\n            print0(ucase ? \"PARTITION \" : \"partition \");\n        }\n\n        if (x.getPartition() != null) {\n            print('(');\n            x.getPartition().accept(this);\n            print(')');\n        } else {\n            print0(ucase ? \"FOR (\" : \"for (\");\n            printAndAccept(x.getFor(), \",\");\n            print(')');\n        }\n        return false;\n    }\n\n//    @Override\n//    public boolean visit(VersionsFlashbackQueryClause x) {\n//        print0(ucase ? \"VERSIONS BETWEEN \" : \"versions between \");\n//        print0(x.getType().name());\n//        print(' ');\n//        x.getBegin().accept(this);\n//        print0(ucase ? \" AND \" : \" and \");\n//        x.getEnd().accept(this);\n//        return false;\n//    }\n//\n//    @Override\n//    public void endVisit(VersionsFlashbackQueryClause x) {\n//\n//    }\n//\n//    @Override\n//    public boolean visit(AsOfFlashbackQueryClause x) {\n//        print0(ucase ? \"AS OF \" : \"as of \");\n//        print0(x.getType().name());\n//        print0(\" (\");\n//        x.getExpr().accept(this);\n//        print(')');\n//        return false;\n//    }\n//\n//    @Override\n//    public void endVisit(AsOfFlashbackQueryClause x) {\n//\n//    }\n\n    @Override\n    public boolean visit(OracleWithSubqueryEntry x) {\n        print0(x.getAlias());\n\n        if (x.getColumns().size() > 0) {\n            print0(\" (\");\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        print0(ucase ? \" AS \" : \" as \");\n        print('(');\n        this.indentCount++;\n        println();\n        x.getSubQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        if (x.getSearchClause() != null) {\n            println();\n            x.getSearchClause().accept(this);\n        }\n\n        if (x.getCycleClause() != null) {\n            println();\n            x.getCycleClause().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SearchClause x) {\n        print0(ucase ? \"SEARCH \" : \"search \");\n        print0(x.getType().name());\n        print0(ucase ? \" FIRST BY \" : \" first by \");\n        printAndAccept(x.getItems(), \", \");\n        print0(ucase ? \" SET \" : \" set \");\n        x.getOrderingColumn().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(CycleClause x) {\n        print0(ucase ? \"CYCLE \" : \"cycle \");\n        printAndAccept(x.getAliases(), \", \");\n        print0(ucase ? \" SET \" : \" set \");\n        x.getMark().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getValue().accept(this);\n        print0(ucase ? \" DEFAULT \" : \" default \");\n        x.getDefaultValue().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleBinaryFloatExpr x) {\n        if (x != null && x.getValue() != null) {\n            print0(x.getValue().toString());\n            print('F');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleBinaryDoubleExpr x) {\n        if (x != null && x.getValue() != null) {\n            print0(x.getValue().toString());\n            print('D');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleIsSetExpr x) {\n        x.getNestedTable().accept(this);\n        print0(ucase ? \" IS A SET\" : \" is a set\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ReturnRowsClause x) {\n        if (x.isAll()) {\n            print0(ucase ? \"RETURN ALL ROWS\" : \"return all rows\");\n        } else {\n            print0(ucase ? \"RETURN UPDATED ROWS\" : \"return updated rows\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause x) {\n        print0(ucase ? \"MODEL\" : \"model\");\n\n        this.indentCount++;\n        for (CellReferenceOption opt : x.getCellReferenceOptions()) {\n            print(' ');\n            print0(opt.name);\n        }\n\n        if (x.getReturnRowsClause() != null) {\n            print(' ');\n            x.getReturnRowsClause().accept(this);\n        }\n\n        for (ReferenceModelClause item : x.getReferenceModelClauses()) {\n            print(' ');\n            item.accept(this);\n        }\n\n        x.getMainModel().accept(this);\n        this.indentCount--;\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MainModelClause x) {\n        if (x.getMainModelName() != null) {\n            print0(ucase ? \" MAIN \" : \" main \");\n            x.getMainModelName().accept(this);\n        }\n\n        println();\n        x.getModelColumnClause().accept(this);\n\n        for (CellReferenceOption opt : x.getCellReferenceOptions()) {\n            println();\n            print0(opt.name);\n        }\n\n        println();\n        x.getModelRulesClause().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelColumnClause x) {\n        if (x.getQueryPartitionClause() != null) {\n            x.getQueryPartitionClause().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"DIMENSION BY (\" : \"dimension by (\");\n        printAndAccept(x.getDimensionByColumns(), \", \");\n        print(')');\n\n        println();\n        print0(ucase ? \"MEASURES (\" : \"measures (\");\n        printAndAccept(x.getMeasuresColumns(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(QueryPartitionClause x) {\n        print0(ucase ? \"PARTITION BY (\" : \"partition by (\");\n        printAndAccept(x.getExprList(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelColumn x) {\n        x.getExpr().accept(this);\n        if (x.getAlias() != null) {\n            print(' ');\n            print0(x.getAlias());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelRulesClause x) {\n        if (x.getOptions().size() > 0) {\n            print0(ucase ? \"RULES\" : \"rules\");\n            for (ModelRuleOption opt : x.getOptions()) {\n                print(' ');\n                print0(opt.name);\n            }\n        }\n\n        if (x.getIterate() != null) {\n            print0(ucase ? \" ITERATE (\" : \" iterate (\");\n            x.getIterate().accept(this);\n            print(')');\n\n            if (x.getUntil() != null) {\n                print0(ucase ? \" UNTIL (\" : \" until (\");\n                x.getUntil().accept(this);\n                print(')');\n            }\n        }\n\n        print0(\" (\");\n        printAndAccept(x.getCellAssignmentItems(), \", \");\n        print(')');\n        return false;\n\n    }\n\n    @Override\n    public boolean visit(CellAssignmentItem x) {\n        if (x.getOption() != null) {\n            print0(x.getOption().name);\n            print(' ');\n        }\n\n        x.getCellAssignment().accept(this);\n\n        if (x.getOrderBy() != null) {\n            print(' ');\n            x.getOrderBy().accept(this);\n        }\n\n        print0(\" = \");\n        x.getExpr().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(CellAssignment x) {\n        x.getMeasureColumn().accept(this);\n        print0(\"[\");\n        printAndAccept(x.getConditions(), \", \");\n        print0(\"]\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleReturningClause x) {\n        print0(ucase ? \"RETURNING \" : \"returning \");\n        printAndAccept(x.getItems(), \", \");\n        print0(ucase ? \" INTO \" : \" into \");\n        printAndAccept(x.getValues(), \", \");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleInsertStatement x) {\n        //visit((SQLInsertStatement) x);\n\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        printInsertColumns(x.getColumns());\n\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            x.getValues().accept(this);\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        if (x.getReturning() != null) {\n            println();\n            x.getReturning().accept(this);\n        }\n\n        if (x.getErrorLogging() != null) {\n            println();\n            x.getErrorLogging().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(InsertIntoClause x) {\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        if (x.getColumns().size() > 0) {\n            this.indentCount++;\n            println();\n            print('(');\n            for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        println();\n                    }\n                    print0(\", \");\n                }\n                x.getColumns().get(i).accept(this);\n            }\n            print(')');\n            this.indentCount--;\n        }\n\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            x.getValues().accept(this);\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement x) {\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        if (x.getHints().size() > 0) {\n            this.printHints(x.getHints());\n        }\n\n        if (x.getOption() != null) {\n            print0(x.getOption().name());\n            print(' ');\n        }\n\n        for (int i = 0, size = x.getEntries().size(); i < size; ++i) {\n            this.indentCount++;\n            println();\n            x.getEntries().get(i).accept(this);\n            this.indentCount--;\n        }\n\n        println();\n        x.getSubQuery().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ConditionalInsertClause x) {\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n\n            ConditionalInsertClauseItem item = x.getItems().get(i);\n\n            item.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            print0(ucase ? \"ELSE\" : \"else\");\n            this.indentCount++;\n            println();\n            x.getElseItem().accept(this);\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ConditionalInsertClauseItem x) {\n        print0(ucase ? \"WHEN \" : \"when \");\n        x.getWhen().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n        println();\n        x.getThen().accept(this);\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLockTableStatement x) {\n        print0(ucase ? \"LOCK TABLE \" : \"lock table \");\n        x.getTable().accept(this);\n        if (x.getPartition() != null) {\n            print0(\" PARTITION (\");\n            x.getPartition().accept(this);\n            print0(\") \");\n        }\n        print0(ucase ? \" IN \" : \" in \");\n        print0(x.getLockMode().toString());\n        print0(ucase ? \" MODE \" : \" mode \");\n        if (x.isNoWait()) {\n            print0(ucase ? \"NOWAIT\" : \"nowait\");\n        } else if (x.getWait() != null) {\n            print0(ucase ? \"WAIT \" : \"wait \");\n            x.getWait().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSessionStatement x) {\n        print0(ucase ? \"ALTER SESSION SET \" : \"alter session set \");\n        printAndAccept(x.getItems(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDatetimeExpr x) {\n        x.getExpr().accept(this);\n        SQLExpr timeZone = x.getTimeZone();\n\n        if (timeZone instanceof SQLIdentifierExpr) {\n            if (((SQLIdentifierExpr) timeZone).getName().equalsIgnoreCase(\"LOCAL\")) {\n                print0(ucase ? \" AT LOCAL\" : \"alter session set \");\n                return false;\n            }\n        }\n\n        print0(ucase ? \" AT TIME ZONE \" : \" at time zone \");\n        timeZone.accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSysdateExpr x) {\n        print0(ucase ? \"SYSDATE\" : \"sysdate\");\n        if (x.getOption() != null) {\n            print('@');\n            print0(x.getOption());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleArgumentExpr x) {\n        print0(x.getArgumentName());\n        print0(\" => \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSetTransactionStatement x) {\n        if (x.isReadOnly()) {\n            print0(ucase ? \"SET TRANSACTION READ ONLY\" : \"set transaction read only\");\n        } else {\n            print0(ucase ? \"SET TRANSACTION\" : \"set transaction\");\n        }\n\n        SQLExpr name = x.getName();\n        if (name != null) {\n            print0(ucase ? \" NAME \" : \" name \");\n            name.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExplainStatement x) {\n        print0(ucase ? \"EXPLAIN PLAN\" : \"explain plan\");\n        this.indentCount++;\n        println();\n        if (x.getStatementId() != null) {\n            print0(ucase ? \"SET STATEMENT_ID = \" : \"set statement_id = \");\n            x.getStatementId().accept(this);\n            println();\n        }\n\n        if (x.getInto() != null) {\n            print0(ucase ? \"INTO \" : \"into \");\n            x.getInto().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"FOR\" : \"for\");\n        println();\n        x.getStatement().accept(this);\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterProcedureStatement x) {\n        print0(ucase ? \"ALTER PROCEDURE \" : \"alter procedure \");\n        x.getName().accept(this);\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n        if (x.isReuseSettings()) {\n            print0(ucase ? \" REUSE SETTINGS\" : \" reuse settings\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableDropPartition x) {\n        print0(ucase ? \"DROP PARTITION \" : \"drop partition \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableStatement x) {\n        if (x.getItems().size() == 1) {\n            SQLAlterTableItem item = x.getItems().get(0);\n            if (item instanceof SQLAlterTableRename) {\n                SQLExpr to = ((SQLAlterTableRename) item).getTo().getExpr();\n\n                print0(ucase ? \"RENAME \" : \"rename \");\n                x.getName().accept(this);\n                print0(ucase ? \" TO \" : \" to \");\n                to.accept(this);\n                return false;\n            }\n        }\n\n        print0(ucase ? \"ALTER TABLE \" : \"alter table \");\n        printTableSourceExpr(x.getName());\n        this.indentCount++;\n        for (SQLAlterTableItem item : x.getItems()) {\n            println();\n            item.accept(this);\n        }\n        if (x.isUpdateGlobalIndexes()) {\n            println();\n            print0(ucase ? \"UPDATE GLOABL INDEXES\" : \"update gloabl indexes\");\n        }\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableTruncatePartition x) {\n        print0(ucase ? \"TRUNCATE PARTITION \" : \"truncate partition \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(TableSpaceItem x) {\n        print0(ucase ? \"TABLESPACE \" : \"tablespace \");\n        x.getTablespace().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(UpdateIndexesClause x) {\n        print0(ucase ? \"UPDATE INDEXES\" : \"update indexes\");\n        if (x.getItems().size() > 0) {\n            print('(');\n            printAndAccept(x.getItems(), \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition x) {\n        print0(ucase ? \"SPLIT PARTITION \" : \"split partition \");\n        x.getName().accept(this);\n\n        if (x.getAt().size() > 0) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"AT (\" : \"at (\");\n            printAndAccept(x.getAt(), \", \");\n            print(')');\n            this.indentCount--;\n        }\n\n        if (x.getInto().size() > 0) {\n            println();\n            this.indentCount++;\n            print0(ucase ? \"INTO (\" : \"into (\");\n            printAndAccept(x.getInto(), \", \");\n            print(')');\n            this.indentCount--;\n        }\n\n        if (x.getUpdateIndexes() != null) {\n            println();\n            this.indentCount++;\n            x.getUpdateIndexes().accept(this);\n            this.indentCount--;\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(NestedTablePartitionSpec x) {\n        print0(ucase ? \"PARTITION \" : \"partition \");\n        x.getPartition().accept(this);\n        for (SQLObject item : x.getSegmentAttributeItems()) {\n            print(' ');\n            item.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableModify x) {\n        print0(ucase ? \"MODIFY (\" : \"modify (\");\n        this.indentCount++;\n        for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n            println();\n            SQLColumnDefinition column = x.getColumns().get(i);\n            column.accept(this);\n            if (i != size - 1) {\n                print0(\", \");\n            }\n        }\n        this.indentCount--;\n        println();\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateIndexStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        if (x.getType() != null) {\n            print0(x.getType());\n            print(' ');\n        }\n\n        print0(ucase ? \"INDEX \" : \"index \");\n\n        x.getName().accept(this);\n        print0(ucase ? \" ON \" : \" on \");\n\n        if (x.isCluster()) {\n            print0(ucase ? \"CLUSTER \" : \"cluster \");\n        }\n\n        x.getTable().accept(this);\n\n        List<SQLSelectOrderByItem> items = x.getItems();\n        if (items.size() > 0) {\n            print('(');\n            printAndAccept(items, \", \");\n            print(')');\n        }\n\n        if (x.isIndexOnlyTopLevel()) {\n            println();\n            print0(ucase ? \"INDEX ONLY TOPLEVEL\" : \"index only toplevel\");\n        }\n\n        if (x.isComputeStatistics()) {\n            println();\n            print0(ucase ? \"COMPUTE STATISTICS\" : \"compute statistics\");\n        }\n\n        if (x.isReverse()) {\n            println();\n            print0(ucase ? \"REVERSE\" : \"reverse\");\n        }\n\n        this.printOracleSegmentAttributes(x);\n\n        if (x.isOnline()) {\n            print0(ucase ? \" ONLINE\" : \" online\");\n        }\n\n        if (x.isNoParallel()) {\n            print0(ucase ? \" NOPARALLEL\" : \" noparallel\");\n        } else if (x.getParallel() != null) {\n            print0(ucase ? \" PARALLEL \" : \" parallel \");\n            x.getParallel().accept(this);\n        }\n\n        Boolean sort = x.getSort();\n        if (sort != null) {\n            if (sort.booleanValue()) {\n                print0(ucase ? \" SORT\" : \" sort\");\n            } else {\n                print0(ucase ? \" NOSORT\" : \" nosort\");\n            }\n        }\n\n        if (x.getLocalPartitions().size() > 0) {\n            println();\n            print0(ucase ? \"LOCAL (\" : \"local (\");\n            this.indentCount++;\n            println();\n            printlnAndAccept(x.getLocalPartitions(), \",\");\n            this.indentCount--;\n            println();\n            print(')');\n        } else if (x.isLocal()) {\n            print0(ucase ? \" LOCAL\" : \" local\");\n        }\n\n        List<SQLName> localStoreIn = x.getLocalStoreIn();\n        if (localStoreIn.size() > 0) {\n            print0(ucase ? \" STORE IN (\" : \" store in (\");\n            printAndAccept(localStoreIn, \", \");\n            print(')');\n        }\n\n        List<SQLPartitionBy> globalPartitions = x.getGlobalPartitions();\n        if (globalPartitions.size() > 0) {\n            for (SQLPartitionBy globalPartition : globalPartitions) {\n                println();\n                print0(ucase ? \"GLOBAL \" : \"global \");\n                print0(ucase ? \"PARTITION BY \" : \"partition by \");\n                globalPartition.accept(this);\n            }\n\n        } else {\n            if (x.isGlobal()) {\n                print0(ucase ? \" GLOBAL\" : \" global\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleForStatement x) {\n        boolean all = x.isAll();\n        if (all) {\n            print0(ucase ? \"FORALL \" : \"forall \");\n        } else {\n            print0(ucase ? \"FOR \" : \"for \");\n        }\n        x.getIndex().accept(this);\n        print0(ucase ? \" IN \" : \" in \");\n\n        if (x.isReverse()) {\n            print0(ucase ? \"REVERSE \" : \"reverse \");\n        }\n\n        SQLExpr range = x.getRange();\n        range.accept(this);\n\n        if (!all) {\n            println();\n            print0(ucase ? \"LOOP\" : \"loop\");\n        }\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement stmt = x.getStatements().get(i);\n            stmt.accept(this);\n            if (!all) {\n                if (i != size - 1) {\n                    println();\n                }\n            }\n        }\n\n        this.indentCount--;\n        if (!all) {\n            println();\n            print0(ucase ? \"END LOOP\" : \"end loop\");\n            SQLName endLabel = x.getEndLabel();\n            if (endLabel != null) {\n                print(' ');\n                endLabel.accept(this);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.Else x) {\n        print0(ucase ? \"ELSE\" : \"else\");\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.ElseIf x) {\n        print0(ucase ? \"ELSIF \" : \"elsif \");\n        x.getCondition().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            println();\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement x) {\n        print0(ucase ? \"IF \" : \"if \");\n        int lines = this.lines;\n        this.indentCount++;\n        x.getCondition().accept(this);\n        this.indentCount--;\n\n        if (lines != this.lines) {\n            println();\n        } else {\n            print(' ');\n        }\n        print0(ucase ? \"THEN\" : \"then\");\n\n        this.indentCount++;\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            println();\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n        this.indentCount--;\n\n        for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) {\n            println();\n            elseIf.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            x.getElseItem().accept(this);\n        }\n        println();\n        print0(ucase ? \"END IF\" : \"end if\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRangeExpr x) {\n        x.getLowBound().accept(this);\n        print0(\"..\");\n        x.getUpBound().accept(this);\n        return false;\n    }\n\n    protected void visitColumnDefault(SQLColumnDefinition x) {\n        if (x.getParent() instanceof SQLBlockStatement) {\n            print0(\" := \");\n        } else {\n            print0(ucase ? \" DEFAULT \" : \" default \");\n        }\n        printExpr(x.getDefaultExpr(), false);\n    }\n\n    @Override\n    public boolean visit(OraclePrimaryKey x) {\n        if (x.getName() != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            x.getName().accept(this);\n            print(' ');\n        }\n        print0(ucase ? \"PRIMARY KEY (\" : \"primary key (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        Boolean rely = x.getRely();\n        if (rely != null) {\n            if (rely.booleanValue()) {\n                print0(ucase ? \" RELY\" : \" rely\");\n            }\n        }\n\n        printConstraintState(x);\n\n        Boolean validate = x.getValidate();\n        if (validate != null) {\n            if (validate.booleanValue()) {\n                print0(ucase ? \" VALIDATE\" : \" validate\");\n            } else {\n                print0(ucase ? \" NOVALIDATE\" : \" novalidate\");\n            }\n        }\n\n        return false;\n    }\n\n    protected void printConstraintState(OracleConstraint x) {\n        this.indentCount++;\n        if (x.getUsing() != null) {\n            println();\n            x.getUsing().accept(this);\n        }\n\n        if (x.getExceptionsInto() != null) {\n            println();\n            print0(ucase ? \"EXCEPTIONS INTO \" : \"exceptions into \");\n            x.getExceptionsInto().accept(this);\n        }\n\n        Boolean enable = x.getEnable();\n        if (enable != null) {\n            if (enable.booleanValue()) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            } else {\n                print0(ucase ? \" DISABLE\" : \" disable\");\n            }\n        }\n\n        if (x.getInitially() != null) {\n            print0(ucase ? \" INITIALLY \" : \" initially \");\n            print0(x.getInitially().name());\n        }\n\n        if (x.getDeferrable() != null) {\n            if (x.getDeferrable().booleanValue()) {\n                print0(ucase ? \" DEFERRABLE\" : \" deferrable\");\n            } else {\n                print0(ucase ? \" NOT DEFERRABLE\" : \" not deferrable\");\n            }\n        }\n        this.indentCount--;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement x) {\n        printCreateTable(x, false);\n\n        if (x.getOf() != null) {\n            println();\n            print0(ucase ? \"OF \" : \"of \");\n            x.getOf().accept(this);\n        }\n\n        OracleCreateTableStatement.OIDIndex oidIndex = x.getOidIndex();\n        if (oidIndex != null) {\n            println();\n            oidIndex.accept(this);\n        }\n\n        OracleCreateTableStatement.Organization organization = x.getOrganization();\n        if (organization != null) {\n            println();\n            this.indentCount++;\n            organization.accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getIncluding().size() > 0) {\n            print0(ucase ? \" INCLUDING \" : \" including \");\n            printAndAccept(x.getIncluding(), \", \");\n            print0(ucase ? \" OVERFLOW \" : \" overflow \");\n        }\n\n        printOracleSegmentAttributes(x);\n\n        if (x.isInMemoryMetadata()) {\n            println();\n            print0(ucase ? \"IN_MEMORY_METADATA\" : \"in_memory_metadata\");\n        }\n\n        if (x.isCursorSpecificSegment()) {\n            println();\n            print0(ucase ? \"CURSOR_SPECIFIC_SEGMENT\" : \"cursor_specific_segment\");\n        }\n\n        if (Boolean.TRUE.equals(x.getParallel())) {\n            println();\n            print0(ucase ? \"PARALLEL\" : \"parallel\");\n\n            final SQLExpr parallelValue = x.getParallelValue();\n            if (parallelValue != null) {\n                print(' ');\n                printExpr(parallelValue);\n            }\n        } else if (Boolean.FALSE.equals(x.getParallel())) {\n            println();\n            print0(ucase ? \"NOPARALLEL\" : \"noparallel\");\n        }\n\n        if (Boolean.TRUE.equals(x.getCache())) {\n            println();\n            print0(ucase ? \"CACHE\" : \"cache\");\n        } else if (Boolean.FALSE.equals(x.getCache())) {\n            println();\n            print0(ucase ? \"NOCACHE\" : \"nocache\");\n        }\n\n        if (x.getLobStorage() != null) {\n            println();\n            x.getLobStorage().accept(this);\n        }\n\n        if (x.isOnCommitPreserveRows()) {\n            println();\n            print0(ucase ? \"ON COMMIT PRESERVE ROWS\" : \"on commit preserve rows\");\n        } else if (x.isOnCommitDeleteRows()) {\n            println();\n            print0(ucase ? \"ON COMMIT DELETE ROWS\" : \"on commit delete rows\");\n        }\n\n        if (x.isMonitoring()) {\n            println();\n            print0(ucase ? \"MONITORING\" : \"monitoring\");\n        }\n\n        printPartitionBy(x);\n\n        if (x.getCluster() != null) {\n            println();\n            print0(ucase ? \"CLUSTER \" : \"cluster \");\n            x.getCluster().accept(this);\n            print0(\" (\");\n            printAndAccept(x.getClusterColumns(), \",\");\n            print0(\")\");\n        }\n\n        final OracleXmlColumnProperties xmlTypeColumnProperties = x.getXmlTypeColumnProperties();\n        if (xmlTypeColumnProperties != null) {\n            println();\n            xmlTypeColumnProperties.accept(this);\n        }\n\n        final SQLSelect select = x.getSelect();\n        if (select != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            select.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleStorageClause x) {\n        print0(ucase ? \"STORAGE (\" : \"storage (\");\n\n        this.indentCount++;\n        final SQLExpr initial = x.getInitial();\n        if (initial != null) {\n            println();\n            print0(ucase ? \"INITIAL \" : \"initial \");\n            printExpr(initial, false);\n        }\n\n        final SQLExpr next = x.getNext();\n        if (next != null) {\n            println();\n            print0(ucase ? \"NEXT \" : \"next \");\n            printExpr(next, false);\n        }\n\n        final SQLExpr minExtents = x.getMinExtents();\n        if (minExtents != null) {\n            println();\n            print0(ucase ? \"MINEXTENTS \" : \"minextents \");\n            printExpr(minExtents, false);\n        }\n\n        final SQLExpr maxExtents = x.getMaxExtents();\n        if (maxExtents != null) {\n            println();\n            print0(ucase ? \"MAXEXTENTS \" : \"maxextents \");\n            printExpr(maxExtents, false);\n        }\n\n        final SQLExpr pctIncrease = x.getPctIncrease();\n        if (pctIncrease != null) {\n            println();\n            print0(ucase ? \"PCTINCREASE \" : \"pctincrease \");\n            printExpr(pctIncrease, false);\n        }\n\n        final SQLExpr maxSize = x.getMaxSize();\n        if (maxSize != null) {\n            println();\n            print0(ucase ? \"MAXSIZE \" : \"maxsize \");\n            printExpr(maxSize, false);\n        }\n\n        final SQLExpr freeLists = x.getFreeLists();\n        if (freeLists != null) {\n            println();\n            print0(ucase ? \"FREELISTS \" : \"freelists \");\n            printExpr(freeLists, false);\n        }\n\n        final SQLExpr freeListGroups = x.getFreeListGroups();\n        if (freeListGroups != null) {\n            println();\n            print0(ucase ? \"FREELIST GROUPS \" : \"freelist groups \");\n            printExpr(freeListGroups, false);\n        }\n\n        final SQLExpr bufferPool = x.getBufferPool();\n        if (bufferPool != null) {\n            println();\n            print0(ucase ? \"BUFFER_POOL \" : \"buffer_pool \");\n            printExpr(bufferPool, false);\n        }\n\n        final SQLExpr objno = x.getObjno();\n        if (objno != null) {\n            println();\n            print0(ucase ? \"OBJNO \" : \"objno \");\n            printExpr(objno, false);\n        }\n\n        if (x.getFlashCache() != null) {\n            println();\n            print0(ucase ? \"FLASH_CACHE \" : \"flash_cache \");\n            print0(ucase ? x.getFlashCache().name() : x.getFlashCache().name().toLowerCase());\n        }\n\n        if (x.getCellFlashCache() != null) {\n            println();\n            print0(ucase ? \"CELL_FLASH_CACHE \" : \"cell_flash_cache \");\n            print0(ucase ? x.getCellFlashCache().name() : x.getCellFlashCache().name().toLowerCase());\n        }\n        this.indentCount--;\n        println();\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleGotoStatement x) {\n        print0(ucase ? \"GOTO \" : \"GOTO \");\n        x.getLabel().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLabelStatement x) {\n        print0(\"<<\");\n        x.getLabel().accept(this);\n        print0(\">>\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTriggerStatement x) {\n        print0(ucase ? \"ALTER TRIGGER \" : \"alter trigger \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSynonymStatement x) {\n        print0(ucase ? \"ALTER SYNONYM \" : \"alter synonym \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n//    @Override\n//    public boolean visit(AsOfSnapshotClause x) {\n//        print0(ucase ? \"AS OF SNAPSHOT(\" : \"as of snapshot(\");\n//        x.getExpr().accept(this);\n//        print(')');\n//        return false;\n//    }\n//\n//    @Override\n//    public void endVisit(AsOfSnapshotClause x) {\n//\n//    }\n\n    @Override\n    public boolean visit(OracleAlterViewStatement x) {\n        print0(ucase ? \"ALTER VIEW \" : \"alter view \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableMoveTablespace x) {\n        print0(ucase ? \" MOVE TABLESPACE \" : \" move tablespace \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableRowMovement x) {\n        if (x.isEnable()) {\n            print0(ucase ? \" ENABLE ROW MOVEMENT \" : \" enable row movement \");\n        } else {\n            print0(ucase ? \" DISABLE ROW MOVEMENT \" : \" disable row movement \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableShrinkSpace x) {\n        print0(ucase ? \" SHRINK SPACE \" : \" shrink space \");\n\n        if (x.isCompact()) {\n            print0(ucase ? \"COMPACT \" : \"compact \");\n        }\n\n        if (x.isCascade()) {\n            print0(ucase ? \"CASCADE \" : \"cascade \");\n        }\n\n        if (x.isCheck()) {\n            print0(ucase ? \"CHECK \" : \"check \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSummaryStatement x) {\n        print0(ucase ? \"ALTER SUMMARY \" : \"alter summary \");\n\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE \" : \" compile \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleFileSpecification x) {\n        printAndAccept(x.getFileNames(), \", \");\n\n        if (x.getSize() != null) {\n            print0(ucase ? \" SIZE \" : \" size \");\n            x.getSize().accept(this);\n        }\n\n        if (x.isAutoExtendOff()) {\n            print0(ucase ? \" AUTOEXTEND OFF\" : \" autoextend off\");\n        } else if (x.getAutoExtendOn() != null) {\n            print0(ucase ? \" AUTOEXTEND ON \" : \" autoextend on \");\n            x.getAutoExtendOn().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceAddDataFile x) {\n        print0(ucase ? \"ADD DATAFILE\" : \"add datafile\");\n        this.indentCount++;\n        for (OracleFileSpecification file : x.getFiles()) {\n            println();\n            file.accept(this);\n        }\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceStatement x) {\n        print0(ucase ? \"ALTER TABLESPACE \" : \"alter tablespace \");\n        x.getName().accept(this);\n        println();\n        x.getItem().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTruncateStatement x) {\n        print0(ucase ? \"TRUNCATE TABLE \" : \"truncate table \");\n        printAndAccept(x.getTableSources(), \", \");\n\n        if (x.isPurgeSnapshotLog()) {\n            print0(ucase ? \" PURGE SNAPSHOT LOG\" : \" purge snapshot log\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExitStatement x) {\n        print0(ucase ? \"EXIT\" : \"exit\");\n\n        if (x.getLabel() != null) {\n            print(' ');\n            print0(x.getLabel());\n        }\n\n        if (x.getWhen() != null) {\n            print0(ucase ? \" WHEN \" : \" when \");\n            x.getWhen().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleContinueStatement x) {\n        print0(ucase ? \"CONTINUE\" : \"continue\");\n\n        String label = x.getLabel();\n        if (label != null) {\n            print(' ');\n            print0(label);\n        }\n\n        if (x.getWhen() != null) {\n            print0(ucase ? \" WHEN \" : \" when \");\n            x.getWhen().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRaiseStatement x) {\n        print0(ucase ? \"RAISE\" : \"raise\");\n        if (x.getException() != null) {\n            print(' ');\n            x.getException().accept(this);\n        }\n        print(';');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSavePointStatement x) {\n        print0(ucase ? \"SAVEPOINT\" : \"savepoint\");\n        if (x.getName() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            x.getName().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    protected void printCreateFunctionBody(SQLCreateFunctionStatement x) {\n        String wrappedSource = x.getWrappedSource();\n        if (wrappedSource != null) {\n            print0(ucase ? \" WRAPPED \" : \" wrapped \");\n            print0(wrappedSource);\n\n            if (x.isAfterSemi()) {\n                print(';');\n            }\n            return;\n        }\n\n        printCreateFunctionReturns(x);\n\n        if (x.isPipelined()) {\n            print(ucase ? \"PIPELINED \" : \"pipelined \");\n        }\n\n        if (x.isDeterministic()) {\n            print(ucase ? \"DETERMINISTIC \" : \"deterministic \");\n        }\n\n        SQLName authid = x.getAuthid();\n        if (authid != null) {\n            print(ucase ? \" AUTHID \" : \" authid \");\n            authid.accept(this);\n        }\n\n        SQLStatement block = x.getBlock();\n\n        if (block != null && !x.isCreate()) {\n            println();\n            println(\"IS\");\n        } else {\n            println();\n            if (block instanceof SQLBlockStatement) {\n                SQLBlockStatement blockStatement = (SQLBlockStatement) block;\n                if (blockStatement.getParameters().size() > 0 || authid != null) {\n                    println(ucase ? \"AS\" : \"as\");\n                }\n            }\n        }\n\n        String javaCallSpec = x.getJavaCallSpec();\n        if (javaCallSpec != null) {\n            print0(ucase ? \"LANGUAGE JAVA NAME '\" : \"language java name '\");\n            print0(javaCallSpec);\n            print('\\'');\n            return;\n        }\n\n        if (x.isParallelEnable()) {\n            print0(ucase ? \"PARALLEL_ENABLE\" : \"parallel_enable\");\n            println();\n        }\n\n        if (x.isAggregate()) {\n            print0(ucase ? \"AGGREGATE\" : \"aggregate\");\n            println();\n        }\n\n        SQLName using = x.getUsing();\n        if (using != null) {\n            print0(ucase ? \"USING \" : \"using \");\n            using.accept(this);\n        }\n\n        if (block != null) {\n            block.accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(OracleCreateDatabaseDbLinkStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        if (x.isShared()) {\n            print0(ucase ? \"SHARE \" : \"share \");\n        }\n\n        if (x.isPublic()) {\n            print0(ucase ? \"PUBLIC \" : \"public \");\n        }\n\n        print0(ucase ? \"DATABASE LINK \" : \"database link \");\n\n        x.getName().accept(this);\n\n        if (x.getUser() != null) {\n            print0(ucase ? \" CONNECT TO \" : \" connect to \");\n            x.getUser().accept(this);\n\n            if (x.getPassword() != null) {\n                print0(ucase ? \" IDENTIFIED BY \" : \" identified by \");\n                print0(x.getPassword());\n            }\n        }\n\n        if (x.getAuthenticatedUser() != null) {\n            print0(ucase ? \" AUTHENTICATED BY \" : \" authenticated by \");\n            x.getAuthenticatedUser().accept(this);\n            if (x.getAuthenticatedPassword() != null) {\n                print0(ucase ? \" IDENTIFIED BY \" : \" identified by \");\n                print0(x.getAuthenticatedPassword());\n            }\n        }\n\n        if (x.getUsing() != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            x.getUsing().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDropDbLinkStatement x) {\n        print0(ucase ? \"DROP \" : \"drop \");\n        if (x.isPublic()) {\n            print0(ucase ? \"PUBLIC \" : \"public \");\n        }\n        print0(ucase ? \"DATABASE LINK \" : \"database link \");\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    public boolean visit(SQLCharacterDataType x) {\n        print0(x.getName());\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.size() > 0) {\n            print('(');\n            SQLExpr arg0 = arguments.get(0);\n            printExpr(arg0, false);\n            if (x.getCharType() != null) {\n                print(' ');\n                print0(x.getCharType());\n            }\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalYear x) {\n        print0(x.getName());\n        if (x.getArguments().size() > 0) {\n            print('(');\n            x.getArguments().get(0).accept(this);\n            print(')');\n        }\n\n        print0(ucase ? \" TO MONTH\" : \" to month\");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalDay x) {\n        print0(x.getName());\n        if (x.getArguments().size() > 0) {\n            print('(');\n            x.getArguments().get(0).accept(this);\n            print(')');\n        }\n\n        print0(ucase ? \" TO SECOND\" : \" to second\");\n\n        if (x.getFractionalSeconds().size() > 0) {\n            print('(');\n            x.getFractionalSeconds().get(0).accept(this);\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleUsingIndexClause x) {\n        print0(ucase ? \"USING INDEX\" : \"using index\");\n        final SQLObject index = x.getIndex();\n        if (index != null) {\n            print(' ');\n            if (index instanceof SQLCreateIndexStatement) {\n                print('(');\n                index.accept(this);\n                print(')');\n            } else {\n                index.accept(this);\n            }\n        }\n\n        printOracleSegmentAttributes(x);\n\n        if (x.isComputeStatistics()) {\n            println();\n            print0(ucase ? \"COMPUTE STATISTICS\" : \"compute statistics\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                println();\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                println();\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n\n        if (x.isReverse()) {\n            println();\n            print0(ucase ? \"REVERSE\" : \"reverse\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLobStorageClause x) {\n        print0(ucase ? \"LOB (\" : \"lob (\");\n        printAndAccept(x.getItems(), \",\");\n        print0(ucase ? \") STORE AS\" : \") store as\");\n\n        if (x.isSecureFile()) {\n            print0(ucase ? \" SECUREFILE\" : \" securefile\");\n        }\n\n        if (x.isBasicFile()) {\n            print0(ucase ? \" BASICFILE\" : \" basicfile\");\n        }\n\n        SQLName segementName = x.getSegementName();\n        if (segementName != null) {\n            print(' ');\n            segementName.accept(this);\n        }\n        print0(\" (\");\n        this.indentCount++;\n        printOracleSegmentAttributes(x);\n\n        if (x.getEnable() != null) {\n            println();\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE STORAGE IN ROW\" : \"enable storage in row\");\n            } else {\n                print0(ucase ? \"DISABLE STORAGE IN ROW\" : \"disable storage in row\");\n            }\n        }\n\n        if (x.getChunk() != null) {\n            println();\n            print0(ucase ? \"CHUNK \" : \"chunk \");\n            x.getChunk().accept(this);\n        }\n\n        if (x.getCache() != null) {\n            println();\n            if (x.getCache().booleanValue()) {\n                print0(ucase ? \"CACHE\" : \"cache\");\n            } else {\n                print0(ucase ? \"NOCACHE\" : \"nocache\");\n            }\n        }\n\n        if (x.getKeepDuplicate() != null) {\n            println();\n            if (x.getKeepDuplicate().booleanValue()) {\n                print0(ucase ? \"KEEP_DUPLICATES\" : \"keep_duplicates\");\n            } else {\n                print0(ucase ? \"DEDUPLICATE\" : \"deduplicate\");\n            }\n        }\n\n        if (x.isRetention()) {\n            println();\n            print0(ucase ? \"RETENTION\" : \"retention\");\n        }\n\n        this.indentCount--;\n        println();\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleUnique x) {\n        visit((SQLUnique) x);\n\n        printConstraintState(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleForeignKey x) {\n        visit((SQLForeignKeyImpl) x);\n\n        printConstraintState(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCheck x) {\n        visit((SQLCheck) x);\n\n        printConstraintState(x);\n        return false;\n    }\n\n    @Override\n    protected void printCascade() {\n        print0(ucase ? \" CASCADE CONSTRAINTS\" : \" cascade constraints\");\n    }\n\n    public boolean visit(SQLCharExpr x, boolean parameterized) {\n        if (x.getText() != null && x.getText().length() == 0) {\n            print0(ucase ? \"NULL\" : \"null\");\n        } else {\n            super.visit(x, parameterized);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSupplementalIdKey x) {\n        print0(ucase ? \"SUPPLEMENTAL LOG DATA (\" : \"supplemental log data (\");\n\n        int count = 0;\n\n        if (x.isAll()) {\n            print0(ucase ? \"ALL\" : \"all\");\n            count++;\n        }\n\n        if (x.isPrimaryKey()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"PRIMARY KEY\" : \"primary key\");\n            count++;\n        }\n\n        if (x.isUnique()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"UNIQUE\" : \"unique\");\n            count++;\n        }\n\n        if (x.isUniqueIndex()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"UNIQUE INDEX\" : \"unique index\");\n            count++;\n        }\n\n        if (x.isForeignKey()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"FOREIGN KEY\" : \"foreign key\");\n            count++;\n        }\n\n        print0(ucase ? \") COLUMNS\" : \") columns\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSupplementalLogGrp x) {\n        print0(ucase ? \"SUPPLEMENTAL LOG GROUP \" : \"supplemental log group \");\n        x.getGroup().accept(this);\n        print0(\" (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n        if (x.isAlways()) {\n            print0(ucase ? \" ALWAYS\" : \" always\");\n        }\n        return false;\n    }\n\n    public boolean visit(OracleCreateTableStatement.Organization x) {\n        String type = x.getType();\n\n        print0(ucase ? \"ORGANIZATION \" : \"organization \");\n        print0(ucase ? type : type.toLowerCase());\n\n        printOracleSegmentAttributes(x);\n\n        if (x.getPctthreshold() != null) {\n            println();\n            print0(ucase ? \"PCTTHRESHOLD \" : \"pctthreshold \");\n            print(x.getPctthreshold());\n        }\n\n        if (\"EXTERNAL\".equalsIgnoreCase(type)) {\n            print0(\" (\");\n\n            this.indentCount++;\n            if (x.getExternalType() != null) {\n                println();\n                print0(ucase ? \"TYPE \" : \"type \");\n                x.getExternalType().accept(this);\n            }\n\n            if (x.getExternalDirectory() != null) {\n                println();\n                print0(ucase ? \"DEFAULT DIRECTORY \" : \"default directory \");\n                x.getExternalDirectory().accept(this);\n            }\n\n            if (x.getExternalDirectoryRecordFormat() != null) {\n                println();\n                this.indentCount++;\n                print0(ucase ? \"ACCESS PARAMETERS (\" : \"access parameters (\");\n                x.getExternalDirectoryRecordFormat().accept(this);\n                this.indentCount--;\n                println();\n                print(')');\n            }\n\n            if (x.getExternalDirectoryLocation().size() > 0) {\n                println();\n                print0(ucase ? \"LOCATION (\" : \" location(\");\n                printAndAccept(x.getExternalDirectoryLocation(), \", \");\n                print(')');\n            }\n\n            this.indentCount--;\n            println();\n            print(')');\n\n            if (x.getExternalRejectLimit() != null) {\n                println();\n                print0(ucase ? \"REJECT LIMIT \" : \"reject limit \");\n                x.getExternalRejectLimit().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleCreateTableStatement.OIDIndex x) {\n        print0(ucase ? \"OIDINDEX\" : \"oidindex\");\n\n        if (x.getName() != null) {\n            print(' ');\n            x.getName().accept(this);\n        }\n        print(\" (\");\n        this.indentCount++;\n        printOracleSegmentAttributes(x);\n        this.indentCount--;\n        println();\n        print(\")\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreatePackageStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE PACKAGE \" : \"create or replace procedure \");\n        } else {\n            print0(ucase ? \"CREATE PACKAGE \" : \"create procedure \");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \"BODY \" : \"body \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.isBody()) {\n            println();\n            print0(ucase ? \"BEGIN\" : \"begin\");\n        }\n\n        this.indentCount++;\n\n        List<SQLStatement> statements = x.getStatements();\n        for (int i = 0, size = statements.size(); i < size; ++i) {\n            println();\n            SQLStatement stmt = statements.get(i);\n            stmt.accept(this);\n        }\n\n        this.indentCount--;\n\n        if (x.isBody() || statements.size() > 0) {\n            println();\n            print0(ucase ? \"END \" : \"end \");\n            x.getName().accept(this);\n            print(';');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAssignItem x) {\n        x.getTarget().accept(this);\n        print0(\" := \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExecuteImmediateStatement x) {\n        print0(ucase ? \"EXECUTE IMMEDIATE \" : \"execute immediate \");\n        x.getDynamicSql().accept(this);\n\n        List<SQLExpr> into = x.getInto();\n        if (into.size() > 0) {\n            print0(ucase ? \" INTO \" : \" into \");\n            printAndAccept(into, \", \");\n        }\n\n        List<SQLArgument> using = x.getArguments();\n        if (using.size() > 0) {\n            print0(ucase ? \" USING \" : \" using \");\n            printAndAccept(using, \", \");\n        }\n\n        List<SQLExpr> returnInto = x.getReturnInto();\n        if (returnInto.size() > 0) {\n            print0(ucase ? \" RETURNNING INTO \" : \" returnning into \");\n            printAndAccept(returnInto, \", \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleTreatExpr x) {\n        print0(ucase ? \"TREAT (\" : \"treat (\");\n        x.getExpr().accept(this);\n        print0(ucase ? \" AS \" : \" as \");\n        if (x.isRef()) {\n            print0(ucase ? \"REF \" : \"ref \");\n        }\n        x.getType().accept(this);\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateSynonymStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE \" : \"create or replace \");\n        } else {\n            print0(ucase ? \"CREATE \" : \"create \");\n        }\n\n        if (x.isPublic()) {\n            print0(ucase ? \"PUBLIC \" : \"public \");\n        }\n\n        print0(ucase ? \"SYNONYM \" : \"synonym \");\n\n        x.getName().accept(this);\n\n        print0(ucase ? \" FOR \" : \" for \");\n        x.getObject().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTypeStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE TYPE \" : \"create or replace type \");\n        } else {\n            print0(ucase ? \"CREATE TYPE \" : \"create type \");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \"BODY \" : \"body \");\n        }\n\n        x.getName().accept(this);\n\n        SQLName under = x.getUnder();\n        if (under != null) {\n            print0(ucase ? \" UNDER \" : \" under \");\n            under.accept(this);\n        }\n\n        SQLName authId = x.getAuthId();\n        if (authId != null) {\n            print0(ucase ? \" AUTHID \" : \" authid \");\n            authId.accept(this);\n        }\n\n        if (x.isForce()) {\n            print0(ucase ? \"FORCE \" : \"force \");\n        }\n\n        List<SQLParameter> parameters = x.getParameters();\n        SQLDataType tableOf = x.getTableOf();\n\n        if (x.isObject()) {\n            print0(\" AS OBJECT\");\n        }\n\n        if (parameters.size() > 0) {\n            if (x.isParen()) {\n                print(\" (\");\n            } else if (x.getParameters() != null && x.getParameters().size() > 0 && \"ENUM\".equals(x.getParameters().get(0).getDataType().getName())) {\n                print0(ucase ? \" AS\" : \" as\");\n            } else {\n                print0(ucase ? \" IS\" : \" is\");\n            }\n            indentCount++;\n            println();\n\n            for (int i = 0; i < parameters.size(); ++i) {\n                SQLParameter param = parameters.get(i);\n                param.accept(this);\n\n                SQLDataType dataType = param.getDataType();\n\n                if (i < parameters.size() - 1) {\n                    if (dataType instanceof OracleFunctionDataType\n                            && ((OracleFunctionDataType) dataType).getBlock() != null) {\n                        // skip\n                        println();\n                    } else if (dataType instanceof OracleProcedureDataType\n                            && ((OracleProcedureDataType) dataType).getBlock() != null) {\n                        // skip\n                        println();\n                    } else {\n                        println(\", \");\n                    }\n                }\n            }\n\n            indentCount--;\n            println();\n\n            if (x.isParen()) {\n                print0(\")\");\n            } else if (x.getParameters() != null && x.getParameters().size() > 0 && \"ENUM\".equals(x.getParameters().get(0).getDataType().getName())) {\n                //do nothing\n            } else {\n                print0(\"END\");\n            }\n        } else if (tableOf != null) {\n            print0(ucase ? \" AS TABLE OF \" : \" as table of \");\n            tableOf.accept(this);\n\n            SQLDataType indexBy = x.getIndexBy();\n            if (indexBy != null) {\n                print0(ucase ? \" INDEX BY \" : \" index by \");\n                indexBy.accept(this);\n            }\n        } else if (x.getVarraySizeLimit() != null) {\n            print0(ucase ? \" VARRAY (\" : \" varray (\");\n            x.getVarraySizeLimit().accept(this);\n            print0(ucase ? \") OF \" : \") of \");\n            x.getVarrayDataType().accept(this);\n        }\n\n        Boolean isFinal = x.getFinal();\n        if (isFinal != null) {\n            if (isFinal.booleanValue()) {\n                print0(ucase ? \" FINAL\" : \" final\");\n            } else {\n                print0(ucase ? \" NOT FINAL\" : \" not final\");\n            }\n        }\n\n        Boolean instantiable = x.getInstantiable();\n        if (instantiable != null) {\n            if (instantiable.booleanValue()) {\n                print0(ucase ? \" INSTANTIABLE\" : \" instantiable\");\n            } else {\n                print0(ucase ? \" NOT INSTANTIABLE\" : \" not instantiable\");\n            }\n        }\n\n        String wrappedSource = x.getWrappedSource();\n        if (wrappedSource != null) {\n            print0(ucase ? \" WRAPPED\" : \" wrapped\");\n            print0(wrappedSource);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OraclePipeRowStatement x) {\n        print0(ucase ? \"PIPE ROW(\" : \"pipe row(\");\n        printAndAccept(x.getParameters(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleIsOfTypeExpr x) {\n        printExpr(x.getExpr());\n        print0(ucase ? \" IS OF TYPE (\" : \" is of type (\");\n\n        List<SQLExpr> types = x.getTypes();\n        for (int i = 0, size = types.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLExpr type = types.get(i);\n            if (Boolean.TRUE.equals(type.getAttribute(\"ONLY\"))) {\n                print0(ucase ? \"ONLY \" : \"only \");\n            }\n            type.accept(this);\n        }\n\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRunStatement x) {\n        print0(\"@@\");\n        printExpr(x.getExpr());\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties x) {\n        print0(ucase ? \"XMLTYPE \" : \"xmltype \");\n        x.getColumn().accept(this);\n\n        final OracleXmlColumnProperties.OracleXMLTypeStorage storage = x.getStorage();\n        if (storage != null) {\n            storage.accept(this);\n        }\n\n        final Boolean allowNonSchema = x.getAllowNonSchema();\n        if (allowNonSchema != null) {\n            if (allowNonSchema.booleanValue()) {\n                print0(ucase ? \" ALLOW NONSCHEMA\" : \" allow nonschema\");\n            } else {\n                print0(ucase ? \" DISALLOW NONSCHEMA\" : \" disallow nonschema\");\n            }\n        }\n\n        final Boolean allowAnySchema = x.getAllowAnySchema();\n        if (allowAnySchema != null) {\n            if (allowAnySchema.booleanValue()) {\n                print0(ucase ? \" ALLOW ANYSCHEMA\" : \" allow anyschema\");\n            } else {\n                print0(ucase ? \" DISALLOW ANYSCHEMA\" : \" disallow anyschema\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExprTableSource x) {\n        printTableSourceExpr(x.getExpr());\n\n        final SQLTableSampling sampling = x.getSampling();\n        if (sampling != null) {\n            print(' ');\n            sampling.accept(this);\n        }\n\n        String alias = x.getAlias();\n        List<SQLName> columns = x.getColumnsDirect();\n        if (alias != null) {\n            SQLObject parent = x.getParent();\n            if (parent instanceof SQLCreateIndexStatement\n                    || parent instanceof SQLMergeStatement\n                    || parent instanceof SQLDeleteStatement) {\n                print(' ');\n                print0(alias);\n            } else {\n                print(' ');\n                print0(ucase ? \" AS \" : \" as \");\n                print0(alias);\n            }\n        }\n\n        if (columns != null && columns.size() > 0) {\n            print(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        if (isPrettyFormat() && x.hasAfterComment()) {\n            print(' ');\n            printlnComment(x.getAfterCommentsDirect());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {\n        return false;\n    }\n\n    public boolean visit(SQLSubPartition x) {\n        super.visit(x);\n        incrementIndent();\n        printOracleSegmentAttributes(x);\n        decrementIndent();\n        return false;\n    }\n\n    public boolean visit(SQLPartitionValue x) {\n        super.visit(x);\n        incrementIndent();\n        printOracleSegmentAttributes(x);\n        decrementIndent();\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLDropUserStatement x) {\n        super.endVisit(x);\n    }\n\n    @Override\n    public boolean visit(SQLDropUserStatement x) {\n        print0(ucase ? \"DROP USER \" : \"drop user \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        printAndAccept(x.getUsers(), \", \");\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterPackageStatement x) {\n        print0(ucase ? \"ALTER PACKAGE \" : \"alter package \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.isPack()) {\n            print0(ucase ? \" PACKAGE\" : \" package\");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \" BODY\" : \" body\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDropPackageStatement x) {\n        print0(ucase ? \"DROP PACKAGE \" : \"drop package \");\n        x.getName().accept(this);\n        if (x.isBody()) {\n            print0(ucase ? \"BODY \" : \"body \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableSpaceStatement x) {\n        print0(ucase ? x.getSql().toUpperCase() : x.getSql().toLowerCase());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionSingle x) {\n        if (x instanceof OraclePartitionSingle) {\n            return visit((OraclePartitionSingle) x);\n        }\n        return super.visit(x);\n    }\n\n    public boolean visit(OraclePartitionSingle x) {\n        boolean isDbPartiton = false, isTbPartition = false;\n        final SQLObject parent = x.getParent();\n        if (parent != null) {\n            final SQLObject parent2 = parent.getParent();\n            if (parent2 instanceof MySqlCreateTableStatement) {\n                MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) parent2;\n                isDbPartiton = parent == stmt.getDbPartitionBy();\n                isTbPartition = parent == stmt.getTablePartitionBy();\n            }\n        }\n\n        if (isDbPartiton) {\n            print0(ucase ? \"DBPARTITION \" : \"dbpartition \");\n        } else if (isTbPartition) {\n            print0(ucase ? \"TBPARTITION \" : \"tbpartition \");\n        } else {\n            print0(ucase ? \"PARTITION \" : \"partition \");\n        }\n        x.getName().accept(this);\n        if (x.getValues() != null) {\n            print(' ');\n            x.getValues().accept(this);\n        }\n\n        this.indentCount++;\n        printOracleSegmentAttributes(x);\n        this.indentCount--;\n        if (x.getSubPartitionsCount() != null) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"SUBPARTITIONS \" : \"subpartitions \");\n            x.getSubPartitionsCount().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getSubPartitions().size() > 0) {\n            print(\" (\");\n            this.indentCount++;\n            for (int i = 0; i < x.getSubPartitions().size(); ++i) {\n                if (i != 0) {\n                    print(',');\n                }\n                println();\n                x.getSubPartitions().get(i).accept(this);\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        SQLExpr locality = x.getLocality();\n        if (locality != null) {\n            print(ucase ? \" LOCALITY = \" : \" locality = \");\n            locality.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMergeStatement.WhenDelete x) {\n        print0(ucase ? \"DELETE\" : \"delete\");\n        if (x.isNot()) {\n            print0(ucase ? \" NOT MATCHED\" : \" not matched\");\n        }\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            printExpr(where, parameterized);\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleParameterizedOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.visitor.ParameterizedVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\n\npublic class OracleParameterizedOutputVisitor extends OracleOutputVisitor implements ParameterizedVisitor {\n    public OracleParameterizedOutputVisitor() {\n        this(new StringBuilder());\n        this.config(VisitorFeature.OutputParameterized, true);\n    }\n\n    public OracleParameterizedOutputVisitor(StringBuilder appender) {\n        super(appender);\n        this.config(VisitorFeature.OutputParameterized, true);\n    }\n\n    public OracleParameterizedOutputVisitor(StringBuilder appender, boolean printPostSemi) {\n        super(appender, printPostSemi);\n        this.config(VisitorFeature.OutputParameterized, true);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        x = SQLBinaryOpExpr.merge(this, x);\n\n        return super.visit(x);\n    }\n\n//    public boolean visit(SQLNumberExpr x) {\n//        print('?');\n//        incrementReplaceCunt();\n//\n//        if(this instanceof ExportParameterVisitor || this.parameters != null){\n//            ExportParameterVisitorUtils.exportParameter((this).getParameters(), x);\n//        }\n//        return false;\n//    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleRowNumToLimit.java",
    "content": "package com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class OracleRowNumToLimit extends OracleASTVisitorAdapter {\n    private Context context;\n    private boolean removeSelectListRownum = true;\n\n    @Override\n    public boolean visit(SQLSelect x) {\n        if (x.getWithSubQuery() != null) {\n            x.getWithSubQuery().accept(this);\n        }\n\n        if (x.getQuery() != null) {\n            x.getQuery().accept(this);\n        }\n\n        SQLSelectQueryBlock queryBlock = x.getQueryBlock();\n        if (queryBlock != null && queryBlock.getLimit() != null) {\n            SQLExpr rowCount = queryBlock.getLimit().getRowCount();\n            if (rowCount instanceof SQLIntegerExpr && SQLIntegerExpr.isZero((SQLIntegerExpr) rowCount)) {\n                x.setOrderBy(null);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectQueryBlock x) {\n        context = new Context(context);\n        context.queryBlock = x;\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            where.accept(this);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from != null) {\n            from.accept(this);\n        }\n\n        removeSelectListRowNum(x);\n\n        List<SQLSelectItem> selectList = x.getSelectList();\n        for (SQLSelectItem selectItem : selectList) {\n            selectItem.accept(this);\n        }\n\n        SQLExpr startWith = x.getStartWith();\n        if (startWith != null) {\n            startWith.accept(this);\n        }\n\n        boolean allColumn = false;\n        if (selectList.size() == 1) {\n            SQLExpr expr = selectList.get(0).getExpr();\n            if (expr instanceof SQLAllColumnExpr) {\n                allColumn = true;\n            } else if (expr instanceof SQLPropertyExpr && ((SQLPropertyExpr) expr).getName().equals(\"*\")) {\n                allColumn = true;\n            }\n        }\n        if ((!allColumn)\n                && x.getFrom() instanceof SQLSubqueryTableSource\n                && ((SQLSubqueryTableSource) x.getFrom()).getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock subQuery = ((SQLSubqueryTableSource) x.getFrom()).getSelect().getQueryBlock();\n            List<SQLSelectItem> subSelectList = subQuery.getSelectList();\n            if (subSelectList.size() >= selectList.size()) {\n                boolean match = true;\n                for (int i = 0; i < selectList.size(); i++) {\n                    if (!selectList.get(i).equals(subSelectList.get(i))) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) {\n                    allColumn = true;\n                }\n            }\n        }\n\n        if (x.getParent() instanceof SQLSelect\n                && x.getWhere() == null\n                && x.getOrderBy() == null\n                && allColumn\n                && x.getLimit() != null\n                && x.getFrom() instanceof SQLSubqueryTableSource\n                && ((SQLSubqueryTableSource) x.getFrom()).getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n            SQLSelect select = (SQLSelect) x.getParent();\n            SQLSelectQueryBlock subQuery = ((SQLSubqueryTableSource) x.getFrom()).getSelect().getQueryBlock();\n            subQuery.mergeLimit(x.getLimit());\n\n            x.setLimit(null);\n            select.setQuery(subQuery);\n            context.queryBlock = subQuery;\n\n            context.fixLimit();\n\n            subQuery.accept(this);\n        }\n\n        if (x.getParent() instanceof SQLUnionQuery\n                && x.getWhere() == null\n                && x.getOrderBy() == null\n                && allColumn\n                && x.getLimit() != null\n                && x.getFrom() instanceof SQLSubqueryTableSource\n                && ((SQLSubqueryTableSource) x.getFrom()).getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n            SQLUnionQuery union = (SQLUnionQuery) x.getParent();\n            SQLSelectQueryBlock subQuery = ((SQLSubqueryTableSource) x.getFrom()).getSelect().getQueryBlock();\n            subQuery.mergeLimit(x.getLimit());\n\n            x.setLimit(null);\n            if (union.getLeft() == x) {\n                union.setLeft(subQuery);\n            } else {\n                union.setRight(subQuery);\n            }\n            context.queryBlock = subQuery;\n\n            context.fixLimit();\n\n            subQuery.accept(this);\n        }\n\n        context = context.parent;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnionQuery x) {\n        if (x.getLeft() != null) {\n            x.getLeft().accept(this);\n        }\n\n        if (x.getRight() != null) {\n            x.getRight().accept(this);\n        }\n\n        if (x.getLeft() instanceof SQLSelectQueryBlock && x.getRight() instanceof SQLSelectQueryBlock) {\n            if (x.getOperator() == SQLUnionOperator.MINUS) {\n                boolean eqNonLimit;\n                {\n                    SQLSelectQueryBlock left = (SQLSelectQueryBlock) x.getLeft().clone();\n                    SQLSelectQueryBlock right = (SQLSelectQueryBlock) x.getRight().clone();\n\n                    left.setLimit(null);\n                    right.setLimit(null);\n\n                    eqNonLimit = left.toString().equals(right.toString());\n                }\n\n                if (eqNonLimit) {\n                    SQLSelectQueryBlock merged = (SQLSelectQueryBlock) x.getLeft().clone();\n                    SQLSelectQueryBlock right = (SQLSelectQueryBlock) x.getRight();\n\n                    SQLLimit leftLimit = merged.getLimit();\n                    SQLLimit rightLimit = right.getLimit();\n\n                    if ((leftLimit == null && rightLimit == null)\n                            || (leftLimit != null && leftLimit.equals(rightLimit))) {\n                        merged.setLimit(new SQLLimit(0));\n                    } else if (leftLimit == null) {\n                        SQLExpr rightOffset = rightLimit.getOffset();\n                        if (rightOffset != null && !SQLIntegerExpr.isZero(rightOffset)) {\n                            return false; // can not merge\n                        }\n                        SQLLimit limit = new SQLLimit();\n                        limit.setOffset(rightLimit.getRowCount());\n                        merged.setLimit(limit);\n                    } else {\n                        SQLExpr rightOffset = rightLimit.getOffset();\n                        if (rightOffset != null && !SQLIntegerExpr.isZero(rightOffset)) {\n                            return false; // can not merge\n                        }\n\n                        SQLExpr leftOffset = leftLimit.getOffset();\n                        if (leftOffset != null && !SQLIntegerExpr.isZero(leftOffset)) {\n                            return false; // todo\n                        }\n\n                        SQLExpr rightRowCount = rightLimit.getRowCount();\n                        SQLExpr leftRowCount = leftLimit.getRowCount();\n\n                        SQLLimit limit = new SQLLimit();\n                        limit.setOffset(rightRowCount);\n                        limit.setRowCount(substract(leftRowCount, rightRowCount));\n\n                        if (SQLIntegerExpr.isZero(limit.getRowCount())) {\n                            limit.setRowCount(0);\n                            limit.setOffset(null);\n                            if (merged.getOrderBy() != null) {\n                                merged.setOrderBy(null);\n                            }\n                        }\n\n                        merged.setLimit(limit);\n                    }\n\n                    SQLObject parent = x.getParent();\n                    if (parent instanceof SQLSelect) {\n                        SQLSelect select = (SQLSelect) parent;\n                        select.setQuery(merged);\n                    } else if (parent instanceof SQLUnionQuery) {\n                        SQLUnionQuery union = (SQLUnionQuery) parent;\n                        if (union.getLeft() == x) {\n                            union.setLeft(merged);\n                        } else {\n                            union.setRight(merged);\n                        }\n                    }\n                }\n            } else if (x.getOperator() == SQLUnionOperator.INTERSECT) {\n                boolean eqNonLimit;\n                {\n                    SQLSelectQueryBlock left = (SQLSelectQueryBlock) x.getLeft().clone();\n                    SQLSelectQueryBlock right = (SQLSelectQueryBlock) x.getRight().clone();\n\n                    left.setLimit(null);\n                    right.setLimit(null);\n\n                    eqNonLimit = left.toString().equals(right.toString());\n                }\n\n                if (eqNonLimit) {\n                    SQLSelectQueryBlock merged = (SQLSelectQueryBlock) x.getLeft().clone();\n                    SQLSelectQueryBlock right = (SQLSelectQueryBlock) x.getRight();\n\n                    SQLLimit leftLimit = merged.getLimit();\n                    SQLLimit rightLimit = right.getLimit();\n\n                    if (rightLimit == null\n                            || (rightLimit.equals(leftLimit))) {\n                        // skip\n                    } else if (leftLimit == null) {\n                        merged.setLimit(rightLimit.clone());\n                    } else {\n                        SQLLimit limit = new SQLLimit();\n\n                        SQLExpr rightOffset = rightLimit.getOffset();\n                        SQLExpr leftOffset = leftLimit.getOffset();\n\n                        if (leftOffset == null) {\n                            limit.setOffset(rightOffset);\n                        } else if (rightOffset == null) {\n                            limit.setOffset(leftOffset);\n                        } else if (rightOffset.equals(leftOffset)) {\n                            limit.setOffset(leftOffset);\n                        } else {\n                            if ((!(leftOffset instanceof SQLIntegerExpr)) || !(rightOffset instanceof SQLIntegerExpr)) {\n                                return false; // can not merged\n                            }\n\n                            limit.setOffset(SQLIntegerExpr.greatst((SQLIntegerExpr) leftOffset, (SQLIntegerExpr) rightOffset));\n                        }\n\n                        SQLExpr rightRowCount = rightLimit.getRowCount();\n                        SQLExpr leftRowCount = leftLimit.getRowCount();\n\n                        SQLExpr leftEnd = leftOffset == null ? leftRowCount : substract(leftRowCount, leftOffset);\n                        SQLExpr rightEnd = rightOffset == null ? rightRowCount : substract(rightRowCount, rightOffset);\n\n                        if ((leftEnd != null && !(leftEnd instanceof SQLIntegerExpr)) || (rightEnd != null && !(rightEnd instanceof SQLIntegerExpr))) {\n                            return false; // can not merged\n                        }\n\n                        SQLIntegerExpr end = SQLIntegerExpr.least((SQLIntegerExpr) leftEnd, (SQLIntegerExpr) rightEnd);\n\n                        if (limit.getOffset() == null) {\n                            limit.setRowCount(end);\n                        } else {\n                            limit.setRowCount(substract(end, limit.getOffset()));\n                        }\n\n                        merged.setLimit(limit);\n                    }\n\n                    SQLObject parent = x.getParent();\n                    if (parent instanceof SQLSelect) {\n                        SQLSelect select = (SQLSelect) parent;\n                        select.setQuery(merged);\n                    } else if (parent instanceof SQLUnionQuery) {\n                        SQLUnionQuery union = (SQLUnionQuery) parent;\n                        if (union.getLeft() == x) {\n                            union.setLeft(merged);\n                        } else {\n                            union.setRight(merged);\n                        }\n                    }\n                }\n            }\n        }\n\n        return false;\n    }\n\n    private void removeSelectListRowNum(SQLSelectQueryBlock x) {\n        SQLTableSource from = x.getFrom();\n        SQLLimit limit = x.getLimit();\n        if (limit == null\n                && from instanceof SQLSubqueryTableSource\n                && ((SQLSubqueryTableSource) from).getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n            limit = ((SQLSubqueryTableSource) from).getSelect().getQueryBlock().getLimit();\n        }\n\n        if (!removeSelectListRownum) {\n            return;\n\n        }\n        List<SQLSelectItem> selectList = x.getSelectList();\n        for (int i = selectList.size() - 1; i >= 0; i--) {\n            SQLSelectItem selectItem = selectList.get(i);\n            SQLExpr expr = selectItem.getExpr();\n            if (isRowNum(expr)\n                    && limit != null) {\n                selectList.remove(i);\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLBinaryOpExpr x) {\n        SQLExpr left = x.getLeft();\n        SQLExpr right = x.getRight();\n        SQLBinaryOperator op = x.getOperator();\n\n        if (context == null || context.queryBlock == null) {\n            return false;\n        }\n\n        boolean isRowNum = isRowNum(left);\n        if (isRowNum) {\n            if (op == SQLBinaryOperator.LessThan) {\n                if (SQLUtils.replaceInParent(x, null)) {\n                    context.setLimit(decrement(right));\n                    // 如果存在 offset, 重新计算 rowCount\n                    context.fixLimit();\n                }\n                return false;\n            } else if (op == SQLBinaryOperator.LessThanOrEqual) {\n                if (SQLUtils.replaceInParent(x, null)) {\n                    context.setLimit(right);\n                    // 如果存在 offset, 重新计算 rowCount\n                    context.fixLimit();\n                }\n                return false;\n            } else if (op == SQLBinaryOperator.Equality) {\n                if (SQLUtils.replaceInParent(x, null)) {\n                    context.setLimit(right);\n                    // 如果存在 offset, 重新计算 rowCount\n                    context.fixLimit();\n                }\n                return false;\n            } else if (op == SQLBinaryOperator.GreaterThanOrEqual) {\n                if (SQLUtils.replaceInParent(x, null)) {\n                    context.setOffset(decrement(right));\n                    // 如果存在 offset, 重新计算 rowCount\n                    context.fixLimit();\n                }\n                return false;\n            } else if (op == SQLBinaryOperator.GreaterThan) {\n                if (SQLUtils.replaceInParent(x, null)) {\n                    context.setOffset(right);\n                    // 如果存在 offset, 重新计算 rowCount\n                    context.fixLimit();\n                }\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        if (!isRowNum(x.getTestExpr())) {\n            return true;\n        }\n\n        if (SQLUtils.replaceInParent(x, null)) {\n            SQLExpr offset = decrement(x.getBeginExpr());\n            context.setOffset(offset);\n            if (offset instanceof SQLIntegerExpr) {\n                int val = ((SQLIntegerExpr) offset).getNumber().intValue();\n                if (val < 0) {\n                    offset = new SQLIntegerExpr(0);\n                }\n            }\n            context.setLimit(substract(x.getEndExpr(), offset));\n            SQLLimit limit = context.queryBlock.getLimit();\n            if (limit != null) {\n                limit.putAttribute(\"oracle.isFixLimit\", Boolean.TRUE);\n            }\n\n        }\n\n        return false;\n    }\n\n    public boolean isRowNum(SQLExpr x) {\n        if (x instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) x;\n            long nameHashCode64 = identifierExpr.nameHashCode64();\n            if (nameHashCode64 == FnvHash.Constants.ROWNUM) {\n                return true;\n            }\n\n            if (context != null\n                    && context.queryBlock != null\n                    && context.queryBlock.getFrom() instanceof SQLSubqueryTableSource\n                    && ((SQLSubqueryTableSource) context.queryBlock.getFrom()).getSelect().getQuery() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock subQueryBlock = ((SQLSubqueryTableSource) context.queryBlock.getFrom()).getSelect().getQueryBlock();\n                SQLSelectItem selectItem = subQueryBlock.findSelectItem(nameHashCode64);\n                this.context = new Context(this.context);\n                this.context.queryBlock = subQueryBlock;\n                try {\n                    if (selectItem != null && isRowNum(selectItem.getExpr())) {\n                        return true;\n                    }\n                } finally {\n                    this.context = this.context.parent;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public static class Context {\n        public final Context parent;\n\n        public Context(Context parent) {\n            this.parent = parent;\n        }\n\n        public SQLSelectQueryBlock queryBlock;\n\n        void setLimit(SQLExpr x) {\n            if (x instanceof SQLIntegerExpr) {\n                int val = ((SQLIntegerExpr) x).getNumber().intValue();\n                if (val < 0) {\n                    x = new SQLIntegerExpr(0);\n                }\n            }\n\n            SQLLimit limit = queryBlock.getLimit();\n            if (limit == null) {\n                limit = new SQLLimit();\n                queryBlock.setLimit(limit);\n            }\n            limit.setRowCount(x);\n        }\n\n        void fixLimit() {\n            SQLLimit limit = queryBlock.getLimit();\n            if (limit == null) {\n                return;\n            }\n\n            if (Boolean.TRUE.equals(limit.getAttribute(\"oracle.isFixLimit\"))) {\n                return;\n            }\n\n            if (limit.getRowCount() != null && limit.getOffset() != null) {\n                if (limit.getRowCount() instanceof SQLIntegerExpr && limit.getOffset() instanceof SQLIntegerExpr) {\n                    SQLIntegerExpr rowCountExpr = SQLIntegerExpr.substract((SQLIntegerExpr) limit.getRowCount(), (SQLIntegerExpr) limit.getOffset());\n                    limit.setRowCount(rowCountExpr);\n                } else {\n                    limit.setRowCount(substract(limit.getRowCount(), limit.getOffset()));\n                }\n                limit.putAttribute(\"oracle.isFixLimit\", Boolean.TRUE);\n\n            }\n        }\n\n        void setOffset(SQLExpr x) {\n            if (x instanceof SQLIntegerExpr) {\n                int val = ((SQLIntegerExpr) x).getNumber().intValue();\n                if (val < 0) {\n                    x = new SQLIntegerExpr(0);\n                }\n            }\n\n            SQLLimit limit = queryBlock.getLimit();\n            if (limit == null) {\n                limit = new SQLLimit();\n                queryBlock.setLimit(limit);\n            }\n            limit.setOffset(x);\n        }\n    }\n\n    public static SQLExpr decrement(SQLExpr x) {\n        if (x instanceof SQLIntegerExpr) {\n            int val = ((SQLIntegerExpr) x).getNumber().intValue() - 1;\n            return new SQLIntegerExpr(val);\n        }\n\n        return new SQLBinaryOpExpr(x.clone(), SQLBinaryOperator.Subtract, new SQLIntegerExpr(1));\n    }\n\n    public static SQLExpr substract(SQLExpr left, SQLExpr right) {\n        if (left == null && right == null) {\n            return null;\n        }\n\n        if (left == null) {\n            return null;\n        }\n\n        if (left instanceof SQLIntegerExpr && right instanceof SQLIntegerExpr) {\n            int rightVal = Math.max(0, ((SQLIntegerExpr) right).getNumber().intValue());\n            int leftVal = ((SQLIntegerExpr) left).getNumber().intValue();\n            int val = leftVal - rightVal;\n            if (val < 0) {\n                val = 0;\n            }\n            return new SQLIntegerExpr(val);\n        } else {\n            return new SQLBinaryOpExpr(left, SQLBinaryOperator.Subtract, right);\n        }\n\n    }\n\n    public static SQLExpr increment(SQLExpr x) {\n        if (x instanceof SQLIntegerExpr) {\n            int val = ((SQLIntegerExpr) x).getNumber().intValue() + 1;\n            return new SQLIntegerExpr(val);\n        }\n\n        return new SQLBinaryOpExpr(x.clone(), SQLBinaryOperator.Add, new SQLIntegerExpr(1));\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleWithSubqueryEntry;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsOfTypeExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleSysdateExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.InsertIntoClause;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.stat.TableStat.Mode;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class OracleSchemaStatVisitor extends SchemaStatVisitor implements OracleASTVisitor {\n    private static final Set<Long> PSEUDO_COLUMNS;\n    private static final Set<Long> FUNCTIONS_IDENT;\n    private static final Set<Long> IMPLICIT_CURSOR_ATTRIBUTES;\n\n    static {\n        PSEUDO_COLUMNS = new HashSet<>();\n        PSEUDO_COLUMNS.add(FnvHash.Constants.ROWID);\n        PSEUDO_COLUMNS.add(FnvHash.Constants.ROWNUM);\n        PSEUDO_COLUMNS.add(FnvHash.Constants.LEVEL);\n\n        FUNCTIONS_IDENT = new HashSet<>();\n        FUNCTIONS_IDENT.add(FnvHash.Constants.SYSDATE);\n        FUNCTIONS_IDENT.add(FnvHash.Constants.CURRENT_DATE);\n        FUNCTIONS_IDENT.add(FnvHash.Constants.CURRENT_TIMESTAMP);\n        FUNCTIONS_IDENT.add(FnvHash.Constants.SYSTIMESTAMP);\n        FUNCTIONS_IDENT.add(FnvHash.Constants.SQLCODE);\n        FUNCTIONS_IDENT.add(FnvHash.Constants.SQLERRM);\n\n        IMPLICIT_CURSOR_ATTRIBUTES = new HashSet<>();\n        IMPLICIT_CURSOR_ATTRIBUTES.add(FnvHash.Constants.FOUND);\n        IMPLICIT_CURSOR_ATTRIBUTES.add(FnvHash.Constants.NOTFOUND);\n        IMPLICIT_CURSOR_ATTRIBUTES.add(FnvHash.Constants.ROWCOUNT);\n        IMPLICIT_CURSOR_ATTRIBUTES.add(FnvHash.Constants.BULK_ROWCOUNT);\n        IMPLICIT_CURSOR_ATTRIBUTES.add(FnvHash.Constants.BULK_EXCEPTIONS);\n    }\n\n    public OracleSchemaStatVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public OracleSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    public OracleSchemaStatVisitor(List<Object> parameters) {\n        super(DbType.oracle, parameters);\n    }\n\n    protected Column getColumn(SQLExpr expr) {\n        if (expr instanceof OracleOuterExpr) {\n            expr = ((OracleOuterExpr) expr).getExpr();\n        }\n\n        return super.getColumn(expr);\n    }\n\n    public boolean visit(OracleSelectTableReference x) {\n        SQLExpr expr = x.getExpr();\n        TableStat stat = getTableStat(x);\n\n        if (expr instanceof SQLName) {\n            if (((SQLName) expr).nameHashCode64() == FnvHash.Constants.DUAL) {\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n                if (isSubQueryOrParamOrVariant(propertyExpr)) {\n                    return false;\n                }\n            } else if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n                if (isSubQueryOrParamOrVariant(identifierExpr)) {\n                    return false;\n                }\n            }\n\n            Mode mode = getMode();\n            switch (mode) {\n                case Delete:\n                    stat.incrementDeleteCount();\n                    break;\n                case Insert:\n                    stat.incrementInsertCount();\n                    break;\n                case Update:\n                    stat.incrementUpdateCount();\n                    break;\n                case Select:\n                    stat.incrementSelectCount();\n                    break;\n                case Merge:\n                    stat.incrementMergeCount();\n                    break;\n                default:\n                    break;\n            }\n\n            return false;\n        }\n\n        // accept(x.getExpr());\n\n        return false;\n    }\n\n    public boolean visit(OracleUpdateStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        setMode(x, Mode.Update);\n\n        SQLTableSource tableSource = x.getTableSource();\n        SQLExpr tableExpr = null;\n\n        if (tableSource instanceof SQLExprTableSource) {\n            tableExpr = ((SQLExprTableSource) tableSource).getExpr();\n        }\n\n        if (tableExpr instanceof SQLName) {\n            TableStat stat = getTableStat((SQLName) tableExpr);\n            stat.incrementUpdateCount();\n        } else {\n            tableSource.accept(this);\n        }\n\n        accept(x.getItems());\n        accept(x.getWhere());\n\n        return false;\n    }\n\n    public boolean visit(OracleSelectQueryBlock x) {\n        SQLExprTableSource into = x.getInto();\n//        if (into != null && into.getExpr() instanceof SQLName) {\n//            TableStat stat = getTableStat((SQLName) into.getExpr());\n//            if (stat != null) {\n//                stat.incrementInsertCount();\n//            }\n//        }\n\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    public void endVisit(OracleSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    public boolean visit(SQLPropertyExpr x) {\n        if (\"ROWNUM\".equalsIgnoreCase(x.getName())) {\n            return false;\n        }\n\n        return super.visit(x);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        String name = x.getName();\n\n        if (\"+\".equalsIgnoreCase(name)) {\n            return false;\n        }\n\n        long hashCode64 = x.hashCode64();\n        if (isPseudoColumn(hashCode64) || isFunctionIdentifier(hashCode64) ||\n                isImplicitCursorBinaryExpr(x.getParent())) {\n            return false;\n        }\n\n        return super.visit(x);\n    }\n\n    // This is to override the default behavior of the {@link SchemaStatVisitor} to ignore pseudo columns.\n    @Override\n    protected boolean isPseudoColumn(long hash) {\n        // Pseudo columns which are not covered by {@link SchemaStatVisitor} to ignore. Not all pseudo\n        // columns are ignored, for example, wildcard * is not ignored.\n        return PSEUDO_COLUMNS.contains(hash);\n    }\n\n    protected boolean isFunctionIdentifier(long hash) {\n        return FUNCTIONS_IDENT.contains(hash);\n    }\n\n    private static boolean isImplicitCursorBinaryExpr(SQLObject sqlObject) {\n        if (!(sqlObject instanceof SQLBinaryOpExpr)) {\n            return false;\n        }\n\n        SQLBinaryOpExpr sqlBinaryOpExpr = (SQLBinaryOpExpr) sqlObject;\n        if (sqlBinaryOpExpr.getOperator() == SQLBinaryOperator.Modulus) {\n            SQLExpr left = sqlBinaryOpExpr.getLeft();\n            SQLExpr right = sqlBinaryOpExpr.getRight();\n            return isImplicitCursorBinaryExpr(left, right);\n        }\n\n        return false;\n    }\n\n    private static boolean isImplicitCursorBinaryExpr(SQLExpr left, SQLExpr right) {\n        // Change: if it is an implicit cursor, skip it\n        if (left instanceof SQLIdentifierExpr && right instanceof SQLIdentifierExpr) {\n            long leftHashCode64 = ((SQLIdentifierExpr) left).hashCode64();\n            long rightHashCode64 = ((SQLIdentifierExpr) right).hashCode64();\n            return leftHashCode64 == FnvHash.Constants.SQL && IMPLICIT_CURSOR_ATTRIBUTES.contains(rightHashCode64);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectJoin x) {\n        super.visit(x);\n//\n//        for (SQLExpr item : x.getUsing()) {\n//            if (item instanceof SQLIdentifierExpr) {\n//                String columnName = ((SQLIdentifierExpr) item).getName();\n//                String leftTable = (String) x.getLeft().getAttribute(ATTR_TABLE);\n//                String rightTable = (String) x.getRight().getAttribute(ATTR_TABLE);\n//                if (leftTable != null && rightTable != null) {\n//                    Relationship relationship = new Relationship();\n//                    relationship.setLeft(new Column(leftTable, columnName));\n//                    relationship.setRight(new Column(rightTable, columnName));\n//                    relationship.setOperator(\"USING\");\n//                    relationships.add(relationship);\n//                }\n//\n//                if (leftTable != null) {\n//                    addColumn(leftTable, columnName);\n//                }\n//\n//                if (rightTable != null) {\n//                    addColumn(rightTable, columnName);\n//                }\n//            }\n//        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectSubqueryTableSource x) {\n        accept(x.getSelect());\n        accept(x.getPivot());\n        accept(x.getUnpivot());\n        accept(x.getFlashback());\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleWithSubqueryEntry x) {\n        x.getSubQuery().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(InsertIntoClause x) {\n        if (x.getTableName() instanceof SQLName) {\n            TableStat stat = getTableStat(x.getTableName());\n            stat.incrementInsertCount();\n        }\n\n        accept(x.getColumns());\n        accept(x.getQuery());\n        accept(x.getReturning());\n        accept(x.getErrorLogging());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        x.putAttribute(\"_original_use_mode\", getMode());\n        setMode(x, Mode.Insert);\n\n        accept(x.getSubQuery());\n        accept(x.getEntries());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ConditionalInsertClauseItem x) {\n        SQLObject parent = x.getParent();\n        if (parent instanceof ConditionalInsertClause) {\n            parent = parent.getParent();\n        }\n        if (parent instanceof OracleMultiInsertStatement) {\n            SQLSelect subQuery = ((OracleMultiInsertStatement) parent).getSubQuery();\n        }\n        x.getWhen().accept(this);\n        x.getThen().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSessionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLockTableStatement x) {\n        getTableStat(x.getTable());\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSysdateExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExceptionStatement.Item x) {\n        SQLExpr when = x.getWhen();\n        if (when instanceof SQLIdentifierExpr) {\n            return false;\n        } else if (when != null) {\n            when.accept(this);\n        }\n\n        for (SQLStatement stmt : x.getStatements()) {\n            stmt.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSetTransactionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExplainStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableDropPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableTruncatePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.TableSpaceItem x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.UpdateIndexesClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.NestedTablePartitionSpec x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableModify x) {\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n        SQLName tableName = stmt.getName();\n\n        for (SQLColumnDefinition column : x.getColumns()) {\n            SQLName columnName = column.getName();\n            addColumn(tableName, columnName.toString());\n\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleForStatement x) {\n        x.getRange().accept(this);\n        accept(x.getStatements());\n        return false;\n    }\n\n    @Override\n    public boolean visit(OraclePrimaryKey x) {\n        accept(x.getColumns());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement x) {\n        this.visit((SQLCreateTableStatement) x);\n\n        if (x.getSelect() != null) {\n            x.getSelect().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleStorageClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleGotoStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLabelStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTriggerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSynonymStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterViewStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableMoveTablespace x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleFileSpecification x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceAddDataFile x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExitStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleContinueStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRaiseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateDatabaseDbLinkStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDropDbLinkStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalYear x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalDay x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleUsingIndexClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLobStorageClause x) {\n        return false;\n    }\n\n    public boolean visit(OracleCreateTableStatement.Organization x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement.OIDIndex x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreatePackageStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        for (SQLStatement stmt : x.getStatements()) {\n            stmt.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExecuteImmediateStatement x) {\n        SQLExpr dynamicSql = x.getDynamicSql();\n\n        String sql = null;\n\n        if (dynamicSql instanceof SQLIdentifierExpr) {\n            String varName = ((SQLIdentifierExpr) dynamicSql).getName();\n\n            SQLExpr valueExpr = null;\n            if (x.getParent() instanceof SQLBlockStatement) {\n                List<SQLStatement> statementList = ((SQLBlockStatement) x.getParent()).getStatementList();\n                for (SQLStatement stmt : statementList) {\n                    if (stmt == x) {\n                        break;\n                    }\n\n                    if (stmt instanceof SQLSetStatement) {\n                        List<SQLAssignItem> items = ((SQLSetStatement) stmt).getItems();\n                        for (SQLAssignItem item : items) {\n                            if (item.getTarget().equals(dynamicSql)) {\n                                valueExpr = item.getValue();\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (valueExpr != null) {\n                dynamicSql = valueExpr;\n            }\n        }\n\n        if (dynamicSql instanceof SQLCharExpr) {\n            sql = ((SQLCharExpr) dynamicSql).getText();\n        }\n\n        if (sql != null) {\n            List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n            for (SQLStatement stmt : stmtList) {\n                stmt.accept(this);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateSynonymStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTypeStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OraclePipeRowStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleIsOfTypeExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleToMySqlOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oracle.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class OracleToMySqlOutputVisitor extends OracleOutputVisitor {\n    public OracleToMySqlOutputVisitor(StringBuilder appender, boolean printPostSemi) {\n        super(appender, printPostSemi);\n    }\n\n    public OracleToMySqlOutputVisitor(StringBuilder appender) {\n        super(appender);\n    }\n\n    public boolean visit(OracleSelectQueryBlock x) {\n        boolean parentIsSelectStatment = false;\n        {\n            if (x.getParent() instanceof SQLSelect) {\n                SQLSelect select = (SQLSelect) x.getParent();\n                if (select.getParent() instanceof SQLSelectStatement || select.getParent() instanceof SQLSubqueryTableSource) {\n                    parentIsSelectStatment = true;\n                }\n            }\n        }\n\n        if (!parentIsSelectStatment) {\n            return super.visit(x);\n        }\n\n        if (x.getWhere() instanceof SQLBinaryOpExpr //\n                && x.getFrom() instanceof SQLSubqueryTableSource //\n        ) {\n            int rownum;\n            String ident;\n            SQLBinaryOpExpr where = (SQLBinaryOpExpr) x.getWhere();\n            if (where.getRight() instanceof SQLIntegerExpr && where.getLeft() instanceof SQLIdentifierExpr) {\n                rownum = ((SQLIntegerExpr) where.getRight()).getNumber().intValue();\n                ident = ((SQLIdentifierExpr) where.getLeft()).getName();\n            } else {\n                return super.visit(x);\n            }\n\n            SQLSelect select = ((SQLSubqueryTableSource) x.getFrom()).getSelect();\n            SQLSelectQueryBlock queryBlock = null;\n            SQLSelect subSelect = null;\n            SQLBinaryOpExpr subWhere = null;\n            boolean isSubQueryRowNumMapping = false;\n\n            if (select.getQuery() instanceof SQLSelectQueryBlock) {\n                queryBlock = (SQLSelectQueryBlock) select.getQuery();\n                if (queryBlock.getWhere() instanceof SQLBinaryOpExpr) {\n                    subWhere = (SQLBinaryOpExpr) queryBlock.getWhere();\n                }\n\n                for (SQLSelectItem selectItem : queryBlock.getSelectList()) {\n                    if (isRowNumber(selectItem.getExpr())) {\n                        if (where.getLeft() instanceof SQLIdentifierExpr\n                                && ((SQLIdentifierExpr) where.getLeft()).getName().equals(selectItem.getAlias())) {\n                            isSubQueryRowNumMapping = true;\n                        }\n                    }\n                }\n\n                SQLTableSource subTableSource = queryBlock.getFrom();\n                if (subTableSource instanceof SQLSubqueryTableSource) {\n                    subSelect = ((SQLSubqueryTableSource) subTableSource).getSelect();\n                }\n            }\n\n            if (\"ROWNUM\".equalsIgnoreCase(ident)) {\n                SQLBinaryOperator op = where.getOperator();\n                Integer limit = null;\n                if (op == SQLBinaryOperator.LessThanOrEqual) {\n                    limit = rownum;\n                } else if (op == SQLBinaryOperator.LessThan) {\n                    limit = rownum - 1;\n                }\n\n                if (limit != null) {\n                    select.accept(this);\n                    println();\n                    print0(ucase ? \"LIMIT \" : \"limit \");\n                    print(limit);\n                    return false;\n                }\n            } else if (isSubQueryRowNumMapping) {\n                SQLBinaryOperator op = where.getOperator();\n                SQLBinaryOperator subOp = subWhere.getOperator();\n\n                if (isRowNumber(subWhere.getLeft()) //\n                        && subWhere.getRight() instanceof SQLIntegerExpr) {\n                    int subRownum = ((SQLIntegerExpr) subWhere.getRight()).getNumber().intValue();\n\n                    Integer offset = null;\n                    if (op == SQLBinaryOperator.GreaterThanOrEqual) {\n                        offset = rownum + 1;\n                    } else if (op == SQLBinaryOperator.GreaterThan) {\n                        offset = rownum;\n                    }\n\n                    if (offset != null) {\n                        Integer limit = null;\n                        if (subOp == SQLBinaryOperator.LessThanOrEqual) {\n                            limit = subRownum - offset;\n                        } else if (subOp == SQLBinaryOperator.LessThan) {\n                            limit = subRownum - 1 - offset;\n                        }\n\n                        if (limit != null) {\n                            subSelect.accept(this);\n                            println();\n                            print0(ucase ? \"LIMIT \" : \"limit \");\n                            print(offset);\n                            print0(\", \");\n                            print(limit);\n                            return false;\n                        }\n                    }\n                }\n            }\n        }\n        return super.visit(x);\n    }\n\n    static boolean isRowNumber(SQLExpr expr) {\n        if (expr instanceof SQLIdentifierExpr) {\n            return ((SQLIdentifierExpr) expr)\n                    .hashCode64() == FnvHash.Constants.ROWNUM;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/Oscar.java",
    "content": "package com.alibaba.druid.sql.dialect.oscar;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Oscar {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.oscar);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/OscarObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\n\npublic interface OscarObject extends SQLObject {\n    void accept0(OscarASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/OscarObjectImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class OscarObjectImpl extends SQLObjectImpl implements OscarObject {\n    public OscarObjectImpl() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((OscarASTVisitor) visitor);\n    }\n\n    public abstract void accept0(OscarASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/expr/OscarExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oscar.ast.OscarObject;\n\npublic interface OscarExpr extends SQLExpr, OscarObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarAlterSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarAlterSchemaStatement extends SQLStatementImpl implements OscarStatement, SQLAlterStatement {\n    private SQLIdentifierExpr schemaName;\n    private SQLIdentifierExpr newName;\n    private SQLIdentifierExpr newOwner;\n\n    public SQLIdentifierExpr getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLIdentifierExpr schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((PGASTVisitor) visitor);\n    }\n\n    public SQLIdentifierExpr getNewName() {\n        return newName;\n    }\n\n    public void setNewName(SQLIdentifierExpr newName) {\n        this.newName = newName;\n    }\n\n    public SQLIdentifierExpr getNewOwner() {\n        return newOwner;\n    }\n\n    public void setNewOwner(SQLIdentifierExpr newOwner) {\n        this.newOwner = newOwner;\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n            acceptChild(visitor, this.newName);\n            acceptChild(visitor, this.newOwner);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarAlterTableAlterColumnSetNotNull.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\npublic class OscarAlterTableAlterColumnSetNotNull {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarConnectToStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarConnectToStatement extends SQLStatementImpl implements OscarStatement {\n    private SQLName target;\n\n    public OscarConnectToStatement() {\n        super(DbType.oscar);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((PGASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, target);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLName getTarget() {\n        return target;\n    }\n\n    public void setTarget(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.target = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarCreateSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarCreateSchemaStatement extends SQLStatementImpl implements OscarStatement, SQLCreateStatement {\n    private SQLIdentifierExpr schemaName;\n    private SQLIdentifierExpr userName;\n    private boolean ifNotExists;\n    private boolean authorization;\n\n    public SQLIdentifierExpr getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLIdentifierExpr schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    public SQLIdentifierExpr getUserName() {\n        return userName;\n    }\n\n    public void setUserName(SQLIdentifierExpr userName) {\n        this.userName = userName;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public boolean isAuthorization() {\n        return authorization;\n    }\n\n    public void setAuthorization(boolean authorization) {\n        this.authorization = authorization;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((PGASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n            acceptChild(visitor, this.userName);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarDeleteStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarDeleteStatement extends SQLDeleteStatement implements OscarStatement {\n    private boolean returning;\n\n    public OscarDeleteStatement() {\n        super(DbType.oscar);\n    }\n\n    public boolean isReturning() {\n        return returning;\n    }\n\n    public void setReturning(boolean returning) {\n        this.returning = returning;\n    }\n\n    public String getAlias() {\n        if (tableSource == null) {\n            return null;\n        }\n        return tableSource.getAlias();\n    }\n\n    public void setAlias(String alias) {\n        this.tableSource.setAlias(alias);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, with);\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, using);\n            acceptChild(visitor, where);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public OscarDeleteStatement clone() {\n        OscarDeleteStatement x = new OscarDeleteStatement();\n        cloneTo(x);\n\n        x.returning = returning;\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarDropSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLDropStatement;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarDropSchemaStatement extends SQLStatementImpl implements OscarStatement, SQLDropStatement {\n    private SQLIdentifierExpr schemaName;\n    private boolean ifExists;\n    private boolean cascade;\n    private boolean restrict;\n\n    public SQLIdentifierExpr getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLIdentifierExpr schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((PGASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarFunctionTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.oscar.ast.OscarObject;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OscarFunctionTableSource extends SQLExprTableSource implements OscarObject {\n    private final List<SQLParameter> parameters = new ArrayList<SQLParameter>();\n\n    public OscarFunctionTableSource() {\n    }\n\n    public OscarFunctionTableSource(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        this.accept0((PGASTVisitor) visitor);\n    }\n\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n            acceptChild(visitor, this.parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public PGFunctionTableSource clone() {\n        PGFunctionTableSource x = new PGFunctionTableSource();\n\n        x.setAlias(this.alias);\n\n        for (SQLParameter e : this.parameters) {\n            SQLParameter e2 = e.clone();\n            e2.setParent(x);\n            x.getParameters().add(e2);\n        }\n\n        if (this.flashback != null) {\n            x.setFlashback(this.flashback.clone());\n        }\n\n        if (this.hints != null) {\n            for (SQLHint e : this.hints) {\n                SQLHint e2 = e.clone();\n                e2.setParent(x);\n                x.getHints().add(e2);\n            }\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OscarInsertStatement extends SQLInsertStatement implements OscarStatement {\n    private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();\n    private SQLExpr returning;\n    private boolean defaultValues;\n\n    private List<SQLExpr> onConflictTarget;\n    private SQLName onConflictConstraint;\n    private SQLExpr onConflictWhere;\n    private SQLExpr onConflictUpdateWhere;\n    private boolean onConflictDoNothing;\n    private List<SQLUpdateSetItem> onConflictUpdateSetItems;\n\n    public OscarInsertStatement() {\n        dbType = DbType.oscar;\n    }\n\n    public void cloneTo(OscarInsertStatement x) {\n        super.cloneTo(x);\n        for (ValuesClause v : valuesList) {\n            ValuesClause v2 = v.clone();\n            v2.setParent(x);\n            x.valuesList.add(v2);\n        }\n        if (returning != null) {\n            x.setReturning(returning.clone());\n        }\n        x.defaultValues = defaultValues;\n    }\n\n    public SQLExpr getReturning() {\n        return returning;\n    }\n\n    public void setReturning(SQLExpr returning) {\n        this.returning = returning;\n    }\n\n    public ValuesClause getValues() {\n        if (valuesList.isEmpty()) {\n            return null;\n        }\n        return valuesList.get(0);\n    }\n\n    public void setValues(ValuesClause values) {\n        if (valuesList.isEmpty()) {\n            valuesList.add(values);\n        } else {\n            valuesList.set(0, values);\n        }\n    }\n\n    public List<ValuesClause> getValuesList() {\n        return valuesList;\n    }\n\n    public void addValueCause(ValuesClause valueClause) {\n        valueClause.setParent(this);\n        valuesList.add(valueClause);\n    }\n\n    public boolean isDefaultValues() {\n        return defaultValues;\n    }\n\n    public void setDefaultValues(boolean defaultValues) {\n        this.defaultValues = defaultValues;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, with);\n            this.acceptChild(visitor, tableSource);\n            this.acceptChild(visitor, columns);\n            this.acceptChild(visitor, valuesList);\n            this.acceptChild(visitor, query);\n            this.acceptChild(visitor, returning);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public PGInsertStatement clone() {\n        PGInsertStatement x = new PGInsertStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    public List<SQLExpr> getOnConflictTarget() {\n        return onConflictTarget;\n    }\n\n    public void setOnConflictTarget(List<SQLExpr> onConflictTarget) {\n        this.onConflictTarget = onConflictTarget;\n    }\n\n    public boolean isOnConflictDoNothing() {\n        return onConflictDoNothing;\n    }\n\n    public void setOnConflictDoNothing(boolean onConflictDoNothing) {\n        this.onConflictDoNothing = onConflictDoNothing;\n    }\n\n    public List<SQLUpdateSetItem> getOnConflictUpdateSetItems() {\n        return onConflictUpdateSetItems;\n    }\n\n    public void addConflicUpdateItem(SQLUpdateSetItem item) {\n        if (onConflictUpdateSetItems == null) {\n            onConflictUpdateSetItems = new ArrayList<SQLUpdateSetItem>();\n        }\n\n        item.setParent(this);\n        onConflictUpdateSetItems.add(item);\n    }\n\n    public SQLName getOnConflictConstraint() {\n        return onConflictConstraint;\n    }\n\n    public void setOnConflictConstraint(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.onConflictConstraint = x;\n    }\n\n    public SQLExpr getOnConflictWhere() {\n        return onConflictWhere;\n    }\n\n    public void setOnConflictWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.onConflictWhere = x;\n    }\n\n    public SQLExpr getOnConflictUpdateWhere() {\n        return onConflictUpdateWhere;\n    }\n\n    public void setOnConflictUpdateWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.onConflictUpdateWhere = x;\n    }\n\n    @Override\n    public List<SQLCommentHint> getHeadHintsDirect() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarSelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oscar.ast.OscarObject;\nimport com.alibaba.druid.sql.dialect.oscar.ast.OscarObjectImpl;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OscarSelectQueryBlock extends SQLSelectQueryBlock implements OscarObject {\n    private List<SQLExpr> distinctOn = new ArrayList<SQLExpr>(2);\n\n    private SQLTop top;\n\n    private FetchClause fetch;\n    private ForClause forClause;\n    private IntoOptionTemp intoOptionTemp;\n    private IntoOptionLocal intoOptionLocal;\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.top);\n            acceptChild(visitor, this.distinctOn);\n            acceptChild(visitor, this.selectList);\n            acceptChild(visitor, this.into);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.groupBy);\n            acceptChild(visitor, this.windows);\n            acceptChild(visitor, this.orderBy);\n            acceptChild(visitor, this.limit);\n            acceptChild(visitor, this.fetch);\n            acceptChild(visitor, this.forClause);\n        }\n        visitor.endVisit(this);\n    }\n\n    public static enum IntoOptionTemp {\n        TEMPORARY, TEMP\n    }\n\n    public static enum IntoOptionLocal {\n        LOCAL, GLOBAL\n    }\n\n    public OscarSelectQueryBlock() {\n        dbType = DbType.oscar;\n    }\n\n    public IntoOptionTemp getIntoOptionTemp() {\n        return intoOptionTemp;\n    }\n\n    public void setIntoOptionTemp(IntoOptionTemp intoOptionTemp) {\n        this.intoOptionTemp = intoOptionTemp;\n    }\n\n    public IntoOptionLocal getIntoOptionLocal() {\n        return intoOptionLocal;\n    }\n\n    public void setIntoOptionLocal(IntoOptionLocal intoOptionLocal) {\n        this.intoOptionLocal = intoOptionLocal;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OscarASTVisitor) {\n            accept0((OscarASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public FetchClause getFetch() {\n        return fetch;\n    }\n\n    public void setFetch(FetchClause fetch) {\n        this.fetch = fetch;\n    }\n\n    public ForClause getForClause() {\n        return forClause;\n    }\n\n    public void setForClause(ForClause forClause) {\n        this.forClause = forClause;\n    }\n\n    public List<SQLExpr> getDistinctOn() {\n        return distinctOn;\n    }\n\n    public void setDistinctOn(List<SQLExpr> distinctOn) {\n        this.distinctOn = distinctOn;\n    }\n\n    public static class FetchClause extends OscarObjectImpl {\n        public static enum Option {\n            FIRST, NEXT\n        }\n\n        private Option option;\n        private SQLExpr count;\n\n        public Option getOption() {\n            return option;\n        }\n\n        public void setOption(Option option) {\n            this.option = option;\n        }\n\n        public SQLExpr getCount() {\n            return count;\n        }\n\n        public void setCount(SQLExpr count) {\n            this.count = count;\n        }\n\n        @Override\n        public void accept0(OscarASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, count);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public void setTop(SQLTop top) {\n        if (top != null) {\n            top.setParent(this);\n        }\n        this.top = top;\n    }\n\n    public SQLTop getTop() {\n        return top;\n    }\n\n    public void setTop(int rowCount) {\n        setTop(new SQLTop(new SQLIntegerExpr(rowCount)));\n    }\n\n    public static class ForClause extends OscarObjectImpl {\n        public static enum Option {\n            UPDATE, SHARE\n        }\n\n        private List<SQLExpr> of = new ArrayList<SQLExpr>(2);\n        private boolean noWait;\n        private boolean skipLocked;\n        private Option option;\n\n        public Option getOption() {\n            return option;\n        }\n\n        public void setOption(Option option) {\n            this.option = option;\n        }\n\n        public List<SQLExpr> getOf() {\n            return of;\n        }\n\n        public void setOf(List<SQLExpr> of) {\n            this.of = of;\n        }\n\n        public boolean isNoWait() {\n            return noWait;\n        }\n\n        public void setNoWait(boolean noWait) {\n            this.noWait = noWait;\n        }\n\n        public boolean isSkipLocked() {\n            return skipLocked;\n        }\n\n        public void setSkipLocked(boolean skipLocked) {\n            this.skipLocked = skipLocked;\n        }\n\n        @Override\n        public void accept0(OscarASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, of);\n            }\n            visitor.endVisit(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarSelectStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarSelectStatement extends SQLSelectStatement implements OscarStatement {\n    public OscarSelectStatement() {\n        super(DbType.oscar);\n    }\n\n    public OscarSelectStatement(SQLSelect select) {\n        super(select, DbType.oscar);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof OscarASTVisitor) {\n            accept0((OscarASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.select);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarShowStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLShowStatement;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarShowStatement extends SQLStatementImpl implements OscarStatement, SQLShowStatement {\n    private SQLExpr expr;\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        accept0((OscarASTVisitor) visitor);\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarStartTransactionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarStartTransactionStatement extends SQLStatementImpl implements OscarStatement {\n    public OscarStartTransactionStatement() {\n        super(DbType.oscar);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oscar.ast.OscarObject;\n\npublic interface OscarStatement extends SQLStatement, OscarObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/ast/stmt/OscarUpdateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class OscarUpdateStatement extends SQLUpdateStatement implements OscarStatement {\n    private boolean only;\n\n    public OscarUpdateStatement() {\n        super(DbType.oscar);\n    }\n\n    public boolean isOnly() {\n        return only;\n    }\n\n    public void setOnly(boolean only) {\n        this.only = only;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public void accept0(OscarASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/parser/OscarCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.oscar.parser;\n\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionByHash;\nimport com.alibaba.druid.sql.ast.SQLPartitionByList;\nimport com.alibaba.druid.sql.parser.*;\n\npublic class OscarCreateTableParser extends SQLCreateTableParser {\n    public OscarCreateTableParser(Lexer lexer) {\n        super(new OscarExprParser(lexer));\n    }\n\n    public OscarCreateTableParser(String sql) {\n        super(new OscarExprParser(sql));\n    }\n\n    public OscarCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        lexer.nextToken();\n        accept(Token.BY);\n\n        if (lexer.identifierEquals(\"LIST\")) {\n            lexer.nextToken();\n            SQLPartitionByList list = new SQLPartitionByList();\n\n            if (lexer.token() == Token.LPAREN) {\n                list.setType(SQLPartitionByList.PartitionByListType.LIST_EXPRESSION);\n                lexer.nextToken();\n                list.addColumn(this.exprParser.expr());\n                accept(Token.RPAREN);\n            } else {\n                acceptIdentifier(\"COLUMNS\");\n                list.setType(SQLPartitionByList.PartitionByListType.LIST_COLUMNS);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    list.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n\n            return list;\n        } else if (lexer.identifierEquals(\"HASH\") || lexer.identifierEquals(\"UNI_HASH\")) {\n            SQLPartitionByHash hash = new SQLPartitionByHash();\n\n            if (lexer.identifierEquals(\"UNI_HASH\")) {\n                hash.setUnique(true);\n            }\n\n            lexer.nextToken();\n\n            if (lexer.token() == Token.KEY) {\n                lexer.nextToken();\n                hash.setKey(true);\n            }\n\n            accept(Token.LPAREN);\n            this.exprParser.exprList(hash.getColumns(), hash);\n            accept(Token.RPAREN);\n            return hash;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/parser/OscarExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLArrayDataType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalType;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.*;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class OscarExprParser extends SQLExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = { \"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\", \"ROW_NUMBER\", \"PERCENTILE_CONT\", \"PERCENTILE_DISC\", \"RANK\", \"DENSE_RANK\", \"PERCENT_RANK\", \"CUME_DIST\" };\n\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public OscarExprParser(String sql) {\n        this(new OscarLexer(sql));\n        this.lexer.nextToken();\n        this.dbType = DbType.oscar;\n    }\n\n    public OscarExprParser(String sql, SQLParserFeature... features) {\n        this(new OscarLexer(sql));\n        this.lexer.nextToken();\n        this.dbType = DbType.oscar;\n    }\n\n    public OscarExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n        this.dbType = DbType.oscar;\n    }\n\n    @Override\n    public SQLDataType parseDataType() {\n        if (lexer.token() == Token.TYPE) {\n            lexer.nextToken();\n        }\n        return super.parseDataType();\n    }\n\n    protected SQLDataType parseDataTypeRest(SQLDataType dataType) {\n        dataType = super.parseDataTypeRest(dataType);\n\n        if (lexer.token() == Token.LBRACKET) {\n            lexer.nextToken();\n            accept(Token.RBRACKET);\n            dataType = new SQLArrayDataType(dataType);\n        }\n\n        return dataType;\n    }\n\n    public OscarSelectParser createSelectParser() {\n        return new OscarSelectParser(this);\n    }\n\n    public SQLExpr primary() {\n        if (lexer.token() == Token.ARRAY) {\n            String ident = lexer.stringVal();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LPAREN) {\n                SQLIdentifierExpr array = new SQLIdentifierExpr(ident);\n                return this.methodRest(array, true);\n            } else {\n                SQLArrayExpr array = new SQLArrayExpr();\n                array.setExpr(new SQLIdentifierExpr(ident));\n                accept(Token.LBRACKET);\n                this.exprList(array.getValues(), array);\n                accept(Token.RBRACKET);\n                return primaryRest(array);\n            }\n        } else if (lexer.token() == Token.POUND) {\n            lexer.nextToken();\n            if (lexer.token() == Token.LBRACE) {\n                lexer.nextToken();\n                String varName = lexer.stringVal();\n                lexer.nextToken();\n                accept(Token.RBRACE);\n                SQLVariantRefExpr expr = new SQLVariantRefExpr(\"#{\" + varName + \"}\");\n                return primaryRest(expr);\n            } else {\n                SQLExpr value = this.primary();\n                SQLUnaryExpr expr = new SQLUnaryExpr(SQLUnaryOperator.Pound, value);\n                return primaryRest(expr);\n            }\n        } else if (lexer.token() == Token.VALUES) {\n            lexer.nextToken();\n\n            SQLValuesExpr values = new SQLValuesExpr();\n            for (;;) {\n                accept(Token.LPAREN);\n                SQLListExpr listExpr = new SQLListExpr();\n                exprList(listExpr.getItems(), listExpr);\n                accept(Token.RPAREN);\n\n                listExpr.setParent(values);\n\n                values.getValues().add(listExpr);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            return values;\n        } else if (lexer.token() == Token.WITH) {\n            SQLQueryExpr queryExpr = new SQLQueryExpr(\n                    createSelectParser()\n                            .select());\n            return queryExpr;\n        }\n\n        return super.primary();\n    }\n\n    protected SQLExpr parseInterval() {\n        accept(Token.INTERVAL);\n\n        OracleIntervalExpr interval = new OracleIntervalExpr();\n\n        if (lexer.token() == Token.LITERAL_CHARS) {\n            interval.setValue(new SQLCharExpr(lexer.stringVal()));\n        } else if (lexer.token() == Token.VARIANT) {\n            interval.setValue(new SQLVariantRefExpr(lexer.stringVal()));\n        } else if (lexer.token() == Token.QUES) {\n            interval.setValue(new SQLVariantRefExpr(\"?\"));\n        } else {\n            return new SQLIdentifierExpr(\"INTERVAL\");\n        }\n\n        lexer.nextToken();\n\n        OracleIntervalType type;\n        if (lexer.identifierEquals(FnvHash.Constants.YEAR)) {\n            lexer.nextToken();\n            type = OracleIntervalType.YEAR;\n        } else if (lexer.identifierEquals(FnvHash.Constants.MONTH)) {\n            lexer.nextToken();\n            type = OracleIntervalType.MONTH;\n        } else if (lexer.identifierEquals(FnvHash.Constants.DAY)) {\n            lexer.nextToken();\n            type = OracleIntervalType.DAY;\n        } else if (lexer.identifierEquals(FnvHash.Constants.HOUR)) {\n            lexer.nextToken();\n            type = OracleIntervalType.HOUR;\n        } else if (lexer.identifierEquals(FnvHash.Constants.MINUTE)) {\n            lexer.nextToken();\n            type = OracleIntervalType.MINUTE;\n        } else if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n            lexer.nextToken();\n            type = OracleIntervalType.SECOND;\n        } else {\n            throw new ParserException(\"illegal interval type. \" + lexer.info());\n        }\n\n        interval.setType(type);\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n            interval.setPrecision(this.primary());\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                if (lexer.token() != Token.LITERAL_INT) {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n                interval.setFactionalSecondsPrecision(lexer.integerValue().intValue());\n                lexer.nextToken();\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"SECOND\")) {\n                lexer.nextToken();\n                interval.setToType(OracleIntervalType.SECOND);\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {\n                        throw new ParserException(\"syntax error. \" + lexer.info());\n                    }\n                    interval.setToFactionalSecondsPrecision(primary());\n                    accept(Token.RPAREN);\n                }\n            } else {\n                interval.setToType(OracleIntervalType.MONTH);\n                lexer.nextToken();\n            }\n        }\n\n        return interval;\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (lexer.token() == Token.COLONCOLON) {\n            lexer.nextToken();\n            SQLDataType dataType = this.parseDataType();\n\n            PGTypeCastExpr castExpr = new PGTypeCastExpr();\n\n            castExpr.setExpr(expr);\n            castExpr.setDataType(dataType);\n\n            return primaryRest(castExpr);\n        }\n\n        if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            array.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            return primaryRest(array);\n        }\n\n        if (expr.getClass() == SQLIdentifierExpr.class) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            String ident = identifierExpr.getName();\n            long hash = identifierExpr.nameHashCode64();\n\n            if (lexer.token() == Token.COMMA || lexer.token() == Token.RPAREN) {\n                return super.primaryRest(expr);\n            }\n\n            if (FnvHash.Constants.TIMESTAMP == hash) {\n                if (lexer.token() != Token.LITERAL_ALIAS //\n                        && lexer.token() != Token.LITERAL_CHARS //\n                        && lexer.token() != Token.WITH) {\n                    return super.primaryRest(\n                            new SQLIdentifierExpr(ident));\n                }\n\n                SQLTimestampExpr timestamp = new SQLTimestampExpr();\n\n                if (lexer.token() == Token.WITH) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n                    timestamp.setWithTimeZone(true);\n                }\n\n                String literal = lexer.stringVal();\n                timestamp.setValue(literal);\n                accept(Token.LITERAL_CHARS);\n\n                if (lexer.identifierEquals(\"AT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n\n                    String timezone = lexer.stringVal();\n                    timestamp.setTimeZone(timezone);\n                    accept(Token.LITERAL_CHARS);\n                }\n\n                return primaryRest(timestamp);\n            } else if (FnvHash.Constants.TIMESTAMPTZ == hash) {\n                if (lexer.token() != Token.LITERAL_ALIAS //\n                        && lexer.token() != Token.LITERAL_CHARS //\n                        && lexer.token() != Token.WITH) {\n                    return super.primaryRest(\n                            new SQLIdentifierExpr(ident));\n                }\n\n                SQLTimestampExpr timestamp = new SQLTimestampExpr();\n                timestamp.setWithTimeZone(true);\n\n                String literal = lexer.stringVal();\n                timestamp.setValue(literal);\n                accept(Token.LITERAL_CHARS);\n\n                if (lexer.identifierEquals(\"AT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n\n                    String timezone = lexer.stringVal();\n                    timestamp.setTimeZone(timezone);\n                    accept(Token.LITERAL_CHARS);\n                }\n\n                return primaryRest(timestamp);\n            } else if (FnvHash.Constants.EXTRACT == hash) {\n                accept(Token.LPAREN);\n\n                PGExtractExpr extract = new PGExtractExpr();\n\n                String fieldName = lexer.stringVal();\n                PGDateField field = PGDateField.valueOf(fieldName.toUpperCase());\n                lexer.nextToken();\n\n                extract.setField(field);\n\n                accept(Token.FROM);\n                SQLExpr source = this.expr();\n\n                extract.setSource(source);\n\n                accept(Token.RPAREN);\n\n                return primaryRest(extract);\n            } else if (FnvHash.Constants.POINT == hash) {\n                switch (lexer.token()) {\n                    case DOT:\n                    case EQ:\n                    case LTGT:\n                    case GT:\n                    case GTEQ:\n                    case LT:\n                    case LTEQ:\n                    case SUB:\n                    case PLUS:\n                    case SUBGT:\n                        break;\n                    default:\n                        SQLExpr value = this.primary();\n                        PGPointExpr point = new PGPointExpr();\n                        point.setValue(value);\n                        return primaryRest(point);\n                }\n            } else if (FnvHash.Constants.BOX == hash) {\n                SQLExpr value = this.primary();\n                PGBoxExpr box = new PGBoxExpr();\n                box.setValue(value);\n                return primaryRest(box);\n            } else if (FnvHash.Constants.MACADDR == hash) {\n                SQLExpr value = this.primary();\n                PGMacAddrExpr macaddr = new PGMacAddrExpr();\n                macaddr.setValue(value);\n                return primaryRest(macaddr);\n            } else if (FnvHash.Constants.INET == hash) {\n                    SQLExpr value = this.primary();\n                    PGInetExpr inet = new PGInetExpr();\n                    inet.setValue(value);\n                    return primaryRest(inet);\n            } else if (FnvHash.Constants.CIDR == hash) {\n                SQLExpr value = this.primary();\n                PGCidrExpr cidr = new PGCidrExpr();\n                cidr.setValue(value);\n                return primaryRest(cidr);\n            } else if (FnvHash.Constants.POLYGON == hash) {\n                SQLExpr value = this.primary();\n                PGPolygonExpr polygon = new PGPolygonExpr();\n                polygon.setValue(value);\n                return primaryRest(polygon);\n            } else if (FnvHash.Constants.CIRCLE == hash) {\n                SQLExpr value = this.primary();\n                PGCircleExpr circle = new PGCircleExpr();\n                circle.setValue(value);\n                return primaryRest(circle);\n            } else if (FnvHash.Constants.LSEG == hash) {\n                SQLExpr value = this.primary();\n                PGLineSegmentsExpr lseg = new PGLineSegmentsExpr();\n                lseg.setValue(value);\n                return primaryRest(lseg);\n            } else if (ident.equalsIgnoreCase(\"b\") && lexer.token() == Token.LITERAL_CHARS) {\n                String charValue = lexer.stringVal();\n                lexer.nextToken();\n                expr = new SQLBinaryExpr(charValue);\n\n                return primaryRest(expr);\n            }\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    @Override\n    protected String alias() {\n        String alias = super.alias();\n        if (alias != null) {\n            return alias;\n        }\n        // 某些关键字在alias时,不作为关键字,仍然是作用为别名\n        switch (lexer.token()) {\n        case INTERSECT:\n            // 具体可以参考SQLParser::alias()的方法实现\n            alias = lexer.stringVal();\n            lexer.nextToken();\n            return alias;\n        // TODO other cases\n        default:\n            break;\n        }\n        return alias;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/parser/OscarLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;\n\npublic class OscarLexer extends Lexer {\n    static final Keywords OSCAR_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"CASCADE\", Token.CASCADE);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"CURRENT\", Token.CURRENT);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"NEXT\", Token.NEXT);\n        map.put(\"NOWAIT\", Token.NOWAIT);\n        map.put(\"OF\", Token.OF);\n\n        map.put(\"OFFSET\", Token.OFFSET);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"RECURSIVE\", Token.RECURSIVE);\n        map.put(\"RESTART\", Token.RESTART);\n\n        map.put(\"RESTRICT\", Token.RESTRICT);\n        map.put(\"RETURNING\", Token.RETURNING);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"ROWS\", Token.ROWS);\n        map.put(\"SHARE\", Token.SHARE);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"START\", Token.START);\n\n        map.put(\"USING\", Token.USING);\n        map.put(\"WINDOW\", Token.WINDOW);\n\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"ARRAY\", Token.ARRAY);\n        map.put(\"IF\", Token.IF);\n        map.put(\"TYPE\", Token.TYPE);\n        map.put(\"ILIKE\", Token.ILIKE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"PARTITION\", Token.PARTITION);\n\n        map.put(\"TOP\", Token.TOP);\n        map.put(\"PERCENT\", Token.PERCENT);\n\n        map.put(\"LOCAL\", Token.LOCAL);\n        map.put(\"GLOBAL\", Token.GLOBAL);\n\n        map.put(\"TEMPORARY\", Token.TEMPORARY);\n        map.put(\"TEMP\", Token.TEMP);\n\n        OSCAR_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return OSCAR_KEYWORDS;\n    }\n\n    public OscarLexer(String input, SQLParserFeature... features) {\n        super(input, true);\n        this.keepComments = true;\n        super.dbType = DbType.oscar;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    protected void scanString() {\n        mark = pos;\n        boolean hasSpecial = false;\n\n        for (;;) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                putChar('\\\\');\n                switch (ch) {\n                    case '\\0':\n                        putChar('\\0');\n                        break;\n                    case '\\'':\n                        putChar('\\'');\n                        break;\n                    case '\"':\n                        putChar('\"');\n                        break;\n                    case 'b':\n                        putChar('b');\n                        break;\n                    case 'n':\n                        putChar('n');\n                        break;\n                    case 'r':\n                        putChar('r');\n                        break;\n                    case 't':\n                        putChar('t');\n                        break;\n                    case '\\\\':\n                        putChar('\\\\');\n                        break;\n                    case 'Z':\n                        putChar((char) 0x1A); // ctrl + Z\n                        break;\n                    default:\n                        putChar(ch);\n                        break;\n                }\n                scanChar();\n            }\n\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    public void scanSharp() {\n        scanChar();\n        if (ch == '>') {\n            scanChar();\n            if (ch == '>') {\n                scanChar();\n                token = Token.POUNDGTGT;\n            } else {\n                token = Token.POUNDGT;\n            }\n        } else {\n            token = Token.POUND;\n        }\n    }\n\n    protected void scanVariable_at() {\n        if (ch != '@') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n        char ch;\n\n        final char c1 = charAt(pos + 1);\n        if (c1 == '@') {\n            pos += 2;\n            token = Token.MONKEYS_AT_AT;\n            this.ch = charAt(++pos);\n            return;\n        } else if (c1 == '>') {\n            pos += 2;\n            token = Token.MONKEYS_AT_GT;\n            this.ch = charAt(++pos);\n            return;\n        }\n\n        for (;;) {\n            ch = charAt(++pos);\n\n            if (!isIdentifierChar(ch)) {\n                break;\n            }\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = addSymbol();\n        token = Token.VARIANT;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/parser/OscarSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.OscarFunctionTableSource;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.OscarSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class OscarSelectParser extends SQLSelectParser {\n    public OscarSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public OscarSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public OscarSelectParser(String sql) {\n        this(new OscarExprParser(sql));\n    }\n\n    protected OscarExprParser createExprParser() {\n        return new OscarExprParser(lexer);\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.VALUES) {\n            return valuesQuery(acceptUnion);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            if (select instanceof SQLSelectQueryBlock) {\n                ((SQLSelectQueryBlock) select).setParenthesized(true);\n            }\n            accept(Token.RPAREN);\n            select.setParenthesized(true);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        OscarSelectQueryBlock queryBlock = new OscarSelectQueryBlock();\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.DISTINCT) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                lexer.nextToken();\n\n                if (lexer.token() == Token.ON) {\n                    lexer.nextToken();\n\n                    for (;;) {\n                        SQLExpr expr = this.createExprParser().expr();\n                        queryBlock.getDistinctOn().add(expr);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        } else {\n                            break;\n                        }\n                    }\n                }\n            } else if (lexer.token() == Token.ALL) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.TOP) {\n                SQLTop top = this.createExprParser().parseTop();\n                queryBlock.setTop(top);\n            }\n\n            parseSelectList(queryBlock);\n\n            if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LOCAL) {\n                    lexer.nextToken();\n                    queryBlock.setIntoOptionLocal(OscarSelectQueryBlock.IntoOptionLocal.LOCAL);\n                } else if (lexer.token() == Token.GLOBAL) {\n                    lexer.nextToken();\n                    queryBlock.setIntoOptionLocal(OscarSelectQueryBlock.IntoOptionLocal.GLOBAL);\n                }\n\n                if (lexer.token() == Token.TEMPORARY) {\n                    lexer.nextToken();\n                    queryBlock.setIntoOptionTemp(OscarSelectQueryBlock.IntoOptionTemp.TEMPORARY);\n                } else if (lexer.token() == Token.TEMP) {\n                    lexer.nextToken();\n                    queryBlock.setIntoOptionTemp(OscarSelectQueryBlock.IntoOptionTemp.TEMP);\n                } else\n\n                if (lexer.token() == Token.TABLE) {\n                    lexer.nextToken();\n                }\n\n                SQLExpr name = this.createExprParser().name();\n\n                queryBlock.setInto(new SQLExprTableSource(name));\n            }\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        if (lexer.token() == Token.WINDOW) {\n            this.parseWindow(queryBlock);\n        }\n\n        queryBlock.setOrderBy(this.createExprParser().parseOrderBy());\n\n        for (;;) {\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = getOrInitLimit(queryBlock);\n\n                lexer.nextToken();\n                if (lexer.token() == Token.ALL) {\n                    limit.setRowCount(new SQLIdentifierExpr(\"ALL\"));\n                    lexer.nextToken();\n                } else {\n                    limit.setRowCount(expr());\n                }\n\n                queryBlock.setLimit(limit);\n            } else if (lexer.token() == Token.OFFSET) {\n                SQLLimit limit = getOrInitLimit(queryBlock);\n                lexer.nextToken();\n                SQLExpr offset = expr();\n                limit.setOffset(offset);\n\n                if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) {\n                    lexer.nextToken();\n                }\n            } else {\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.FETCH) {\n            lexer.nextToken();\n            OscarSelectQueryBlock.FetchClause fetch = new OscarSelectQueryBlock.FetchClause();\n\n            if (lexer.token() == Token.FIRST) {\n                fetch.setOption(OscarSelectQueryBlock.FetchClause.Option.FIRST);\n            } else if (lexer.token() == Token.NEXT) {\n                fetch.setOption(OscarSelectQueryBlock.FetchClause.Option.NEXT);\n            } else {\n                throw new ParserException(\"expect 'FIRST' or 'NEXT'. \" + lexer.info());\n            }\n\n            SQLExpr count = expr();\n            fetch.setCount(count);\n\n            if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'ROW' or 'ROWS'. \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.ONLY) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'ONLY'. \" + lexer.info());\n            }\n\n            queryBlock.setFetch(fetch);\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n\n            OscarSelectQueryBlock.ForClause forClause = new OscarSelectQueryBlock.ForClause();\n\n            if (lexer.token() == Token.UPDATE) {\n                forClause.setOption(OscarSelectQueryBlock.ForClause.Option.UPDATE);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.SHARE) {\n                forClause.setOption(OscarSelectQueryBlock.ForClause.Option.SHARE);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'FIRST' or 'NEXT'. \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.OF) {\n                for (;;) {\n                    SQLExpr expr = this.createExprParser().expr();\n                    forClause.getOf().add(expr);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else {\n                        break;\n                    }\n                }\n            }\n\n            if (lexer.token() == Token.NOWAIT) {\n                lexer.nextToken();\n                forClause.setNoWait(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SKIP)) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOCKED\");\n                forClause.setSkipLocked(true);\n            }\n\n            queryBlock.setForClause(forClause);\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    private SQLLimit getOrInitLimit(SQLSelectQueryBlock queryBlock) {\n        SQLLimit limit = queryBlock.getLimit();\n        if (limit == null) {\n            limit = new SQLLimit();\n            queryBlock.setLimit(limit);\n        }\n        return limit;\n    }\n\n    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {\n        if (lexer.token() == Token.AS && tableSource instanceof SQLExprTableSource) {\n            lexer.nextToken();\n\n            String alias = null;\n            if (lexer.token() == Token.IDENTIFIER) {\n                alias = lexer.stringVal();\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;\n\n                OscarFunctionTableSource functionTableSource = new OscarFunctionTableSource(exprTableSource.getExpr());\n                if (alias != null) {\n                    functionTableSource.setAlias(alias);\n                }\n\n                lexer.nextToken();\n                parserParameters(functionTableSource.getParameters());\n                accept(Token.RPAREN);\n\n                return super.parseTableSourceRest(functionTableSource);\n            }\n            if (alias != null) {\n                tableSource.setAlias(alias);\n                return super.parseTableSourceRest(tableSource);\n            }\n        }\n\n        return super.parseTableSourceRest(tableSource);\n    }\n\n    private void parserParameters(List<SQLParameter> parameters) {\n        for (;;) {\n            SQLParameter parameter = new SQLParameter();\n\n            parameter.setName(this.exprParser.name());\n            parameter.setDataType(this.exprParser.parseDataType());\n\n            parameters.add(parameter);\n            if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) {\n                continue;\n            }\n\n            break;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/visitor/OscarASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.visitor;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface OscarASTVisitor extends SQLASTVisitor {\n    default void endVisit(OscarSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(OscarSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(OscarSelectQueryBlock.FetchClause x) {\n    }\n\n    default boolean visit(OscarSelectQueryBlock.FetchClause x) {\n        return true;\n    }\n\n    default void endVisit(OscarSelectQueryBlock.ForClause x) {\n    }\n\n    default boolean visit(OscarSelectQueryBlock.ForClause x) {\n        return true;\n    }\n\n    default void endVisit(OscarDeleteStatement x) {\n    }\n\n    default boolean visit(OscarDeleteStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarInsertStatement x) {}\n\n    default boolean visit(OscarInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarSelectStatement x) {\n        endVisit((SQLSelectStatement) x);\n    }\n\n    default boolean visit(OscarSelectStatement x) {\n        return visit((SQLSelectStatement) x);\n    }\n\n    default void endVisit(OscarUpdateStatement x) {\n    }\n\n    default boolean visit(OscarUpdateStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarFunctionTableSource x) {\n    }\n\n    default boolean visit(OscarFunctionTableSource x) {\n        return true;\n    }\n\n    default void endVisit(OscarShowStatement x) {\n    }\n\n    default boolean visit(OscarShowStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarStartTransactionStatement x) {\n    }\n\n    default boolean visit(OscarStartTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarConnectToStatement x) {\n    }\n\n    default boolean visit(OscarConnectToStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarCreateSchemaStatement x) {\n    }\n\n    default boolean visit(OscarCreateSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarDropSchemaStatement x) {\n    }\n\n    default boolean visit(OscarDropSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(OscarAlterSchemaStatement x) {\n    }\n\n    default boolean visit(OscarAlterSchemaStatement x) {\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/visitor/OscarOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleProcedureDataType;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.dialect.oscar.Oscar;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.OscarSelectQueryBlock.FetchClause;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.OscarSelectQueryBlock.ForClause;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class OscarOutputVisitor extends SQLASTOutputVisitor implements OscarASTVisitor, OracleASTVisitor {\n    public OscarOutputVisitor(StringBuilder appender) {\n    super(appender, DbType.oscar, Oscar.DIALECT);\n    }\n\n    public OscarOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.oscar, Oscar.DIALECT, parameterized);\n    }\n\n    @Override\n    public boolean visit(FetchClause x) {\n        print0(ucase ? \"FETCH \" : \"fetch \");\n        if (FetchClause.Option.FIRST.equals(x.getOption())) {\n            print0(ucase ? \"FIRST \" : \"first \");\n        } else if (FetchClause.Option.NEXT.equals(x.getOption())) {\n            print0(ucase ? \"NEXT \" : \"next \");\n        }\n        x.getCount().accept(this);\n        print0(ucase ? \" ROWS ONLY\" : \" rows only\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ForClause x) {\n        print0(ucase ? \"FOR \" : \"for \");\n        if (ForClause.Option.UPDATE.equals(x.getOption())) {\n            print0(ucase ? \"UPDATE\" : \"update\");\n        } else if (ForClause.Option.SHARE.equals(x.getOption())) {\n            print0(ucase ? \"SHARE\" : \"share\");\n        }\n\n        if (x.getOf().size() > 0) {\n            print(' ');\n            for (int i = 0; i < x.getOf().size(); ++i) {\n                if (i != 0) {\n                    println(\", \");\n                }\n                x.getOf().get(i).accept(this);\n            }\n        }\n\n        if (x.isNoWait()) {\n            print0(ucase ? \" NOWAIT\" : \" nowait\");\n        } else if (x.isSkipLocked()) {\n            print0(ucase ? \" SKIP LOCKED\" : \" skip locked\");\n        }\n\n        return false;\n    }\n\n    public boolean visit(OscarSelectQueryBlock x) {\n        if ((!isParameterized()) && isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        final boolean bracket = x.isParenthesized();\n        if (bracket) {\n            print('(');\n        }\n\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n\n            List<SQLExpr> distinctOn = x.getDistinctOn();\n            if (distinctOn != null && distinctOn.size() > 0) {\n                print0(ucase ? \"ON \" : \"on \");\n\n                if (distinctOn.size() == 1 && distinctOn.get(0) instanceof SQLListExpr) {\n                    printExpr(distinctOn.get(0));\n                    print(' ');\n                } else {\n                    print0(\"(\");\n                    printAndAccept(distinctOn, \", \");\n                    print0(\") \");\n                }\n            }\n        }\n\n        SQLTop top = x.getTop();\n        if (top != null) {\n            visit(top);\n            print(' ');\n        }\n\n        printSelectList(x.getSelectList());\n\n        if (x.getInto() != null) {\n            println();\n\n            print0(ucase ? \"INTO \" : \"into \");\n\n            if (x.getIntoOptionLocal() != null) {\n                print0(x.getIntoOptionLocal().name());\n                print(' ');\n            }\n\n            if (x.getIntoOptionTemp() != null) {\n                print0(x.getIntoOptionTemp().name());\n                print(' ');\n            }\n\n            x.getInto().accept(this);\n        }\n\n        if (x.getFrom() != null) {\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n            x.getFrom().accept(this);\n        }\n\n        printWhere(x);\n\n        if (x.getGroupBy() != null) {\n            println();\n            x.getGroupBy().accept(this);\n        }\n\n//        if (x.getWindow() != null) {\n//            println();\n//            x.getWindow().accept(this);\n//        }\n\n        final List<SQLWindow> windows = x.getWindows();\n        if (windows != null && windows.size() > 0) {\n            println();\n            print0(ucase ? \"WINDOW \" : \"window \");\n            printAndAccept(windows, \", \");\n        }\n\n        if (x.getOrderBy() != null) {\n            println();\n            x.getOrderBy().accept(this);\n        }\n\n        if (x.getLimit() != null) {\n            println();\n            x.getLimit().accept(this);\n        }\n\n        if (x.getFetch() != null) {\n            println();\n            x.getFetch().accept(this);\n        }\n\n        if (x.getForClause() != null) {\n            println();\n            x.getForClause().accept(this);\n        }\n\n        if (bracket) {\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTruncateStatement x) {\n        print0(ucase ? \"TRUNCATE TABLE \" : \"truncate table \");\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY \" : \"only \");\n        }\n\n        printlnAndAccept(x.getTableSources(), \", \");\n\n        if (x.getRestartIdentity() != null) {\n            if (x.getRestartIdentity().booleanValue()) {\n                print0(ucase ? \" RESTART IDENTITY\" : \" restart identity\");\n            } else {\n                print0(ucase ? \" CONTINUE IDENTITY\" : \" continue identity\");\n            }\n        }\n\n        if (x.getCascade() != null) {\n            if (x.getCascade().booleanValue()) {\n                print0(ucase ? \" CASCADE\" : \" cascade\");\n            } else {\n                print0(ucase ? \" RESTRICT\" : \" restrict\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarDeleteStatement x) {\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"DELETE FROM \" : \"delete from \");\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY \" : \"only \");\n        }\n\n        printTableSourceExpr(x.getTableName());\n\n        if (x.getAlias() != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            print0(x.getAlias());\n        }\n\n        SQLTableSource using = x.getUsing();\n        if (using != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            using.accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            this.indentCount++;\n            x.getWhere().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.isReturning()) {\n            println();\n            print0(ucase ? \"RETURNING *\" : \"returning *\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarInsertStatement x) {\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"INSERT INTO \" : \"insert into \");\n\n        x.getTableSource().accept(this);\n\n        printInsertColumns(x.getColumns());\n\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            printlnAndAccept(x.getValuesList(), \", \");\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        List<SQLExpr> onConflictTarget = x.getOnConflictTarget();\n        List<SQLUpdateSetItem> onConflictUpdateSetItems = x.getOnConflictUpdateSetItems();\n        boolean onConflictDoNothing = x.isOnConflictDoNothing();\n\n        if (onConflictDoNothing\n                || (onConflictTarget != null && onConflictTarget.size() > 0)\n                || (onConflictUpdateSetItems != null && onConflictUpdateSetItems.size() > 0)) {\n            println();\n            print0(ucase ? \"ON CONFLICT\" : \"on conflict\");\n\n            if ((onConflictTarget != null && onConflictTarget.size() > 0)) {\n                print0(\" (\");\n                printAndAccept(onConflictTarget, \", \");\n                print(')');\n            }\n\n            SQLName onConflictConstraint = x.getOnConflictConstraint();\n            if (onConflictConstraint != null) {\n                print0(ucase ? \" ON CONSTRAINT \" : \" on constraint \");\n                printExpr(onConflictConstraint);\n            }\n\n            SQLExpr onConflictWhere = x.getOnConflictWhere();\n            if (onConflictWhere != null) {\n                print0(ucase ? \" WHERE \" : \" where \");\n                printExpr(onConflictWhere);\n            }\n\n            if (onConflictDoNothing) {\n                print0(ucase ? \" DO NOTHING\" : \" do nothing\");\n            } else if ((onConflictUpdateSetItems != null && onConflictUpdateSetItems.size() > 0)) {\n                print0(ucase ? \" DO UPDATE SET \" : \" do update set \");\n                printAndAccept(onConflictUpdateSetItems, \", \");\n                SQLExpr onConflictUpdateWhere = x.getOnConflictUpdateWhere();\n                if (onConflictUpdateWhere != null) {\n                    print0(ucase ? \" WHERE \" : \" where \");\n                    printExpr(onConflictUpdateWhere);\n                }\n            }\n        }\n\n        if (x.getReturning() != null) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            x.getReturning().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarSelectStatement x) {\n        return visit((SQLSelectStatement) x);\n    }\n\n    @Override\n    public boolean visit(OscarUpdateStatement x) {\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY \" : \"only \");\n        }\n\n        printTableSource(x.getTableSource());\n\n        println();\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLUpdateSetItem item = x.getItems().get(i);\n            visit(item);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from != null) {\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n            printTableSource(from);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            indentCount++;\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where);\n            indentCount--;\n        }\n\n        List<SQLExpr> returning = x.getReturning();\n        if (returning.size() > 0) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            printAndAccept(returning, \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarFunctionTableSource x) {\n        x.getExpr().accept(this);\n\n        if (x.getAlias() != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            print0(x.getAlias());\n        }\n\n        if (x.getParameters().size() > 0) {\n            print('(');\n            printAndAccept(x.getParameters(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBinaryExpr x) {\n        print0(ucase ? \"B'\" : \"b'\");\n        print0(x.getText());\n        print('\\'');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarShowStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLLimit x) {\n        print0(ucase ? \"LIMIT \" : \"limit \");\n\n        x.getRowCount().accept(this);\n\n        if (x.getOffset() != null) {\n            print0(ucase ? \" OFFSET \" : \" offset \");\n            x.getOffset().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarStartTransactionStatement x) {\n        print0(ucase ? \"START TRANSACTION\" : \"start transaction\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarConnectToStatement x) {\n        print0(ucase ? \"CONNECT TO \" : \"connect to \");\n        x.getTarget().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarCreateSchemaStatement x) {\n        printUcase(\"CREATE SCHEMA \");\n        if (x.isIfNotExists()) {\n            printUcase(\"IF NOT EXISTS \");\n        }\n\n        if (x.getSchemaName() != null) {\n            x.getSchemaName().accept(this);\n        }\n        if (x.isAuthorization()) {\n            printUcase(\"AUTHORIZATION \");\n            x.getUserName().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(OscarDropSchemaStatement x) {\n        printUcase(\"DROP SCHEMA \");\n        if (x.isIfExists()) {\n            printUcase(\"IF EXISTS \");\n        }\n        x.getSchemaName().accept(this);\n    }\n\n    @Override\n    public boolean visit(OscarDropSchemaStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OscarAlterSchemaStatement x) {\n        printUcase(\"ALTER SCHEMA \");\n        x.getSchemaName().accept(this);\n\n        if (x.getNewName() != null) {\n            print0(\" RENAME TO \");\n            x.getNewName().accept(this);\n        } else if (x.getNewOwner() != null) {\n            print0(\" OWNER TO \");\n            x.getNewOwner().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSetStatement x) {\n        print0(ucase ? \"SET \" : \"set \");\n\n        SQLSetStatement.Option option = x.getOption();\n        if (option != null) {\n            print(option.name());\n            print(' ');\n        }\n\n        List<SQLAssignItem> items = x.getItems();\n        for (int i = 0; i < items.size(); i++) {\n            if (i != 0) {\n                print0(\", \");\n            }\n\n            SQLAssignItem item = x.getItems().get(i);\n            SQLExpr target = item.getTarget();\n            target.accept(this);\n\n            SQLExpr value = item.getValue();\n\n            if (target instanceof SQLIdentifierExpr\n                    && ((SQLIdentifierExpr) target).getName().equalsIgnoreCase(\"TIME ZONE\")) {\n                print(' ');\n            } else {\n                if (value instanceof SQLPropertyExpr\n                        && ((SQLPropertyExpr) value).getOwner() instanceof SQLVariantRefExpr) {\n                    print0(\" := \");\n                } else {\n                    print0(\" TO \");\n                }\n            }\n\n            if (value instanceof SQLListExpr) {\n                SQLListExpr listExpr = (SQLListExpr) value;\n                printAndAccept(listExpr.getItems(), \", \");\n            } else {\n                value.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateUserStatement x) {\n        print0(ucase ? \"CREATE USER \" : \"create user \");\n        x.getUser().accept(this);\n        print0(ucase ? \" PASSWORD \" : \" password \");\n\n        SQLExpr passoword = x.getPassword();\n\n        if (passoword instanceof SQLIdentifierExpr) {\n            print('\\'');\n            passoword.accept(this);\n            print('\\'');\n        } else {\n            passoword.accept(this);\n        }\n\n        return false;\n    }\n\n    protected void printGrantPrivileges(SQLGrantStatement x) {\n        List<SQLPrivilegeItem> privileges = x.getPrivileges();\n        int i = 0;\n        for (SQLPrivilegeItem privilege : privileges) {\n            if (i != 0) {\n                print(\", \");\n            }\n\n            SQLExpr action = privilege.getAction();\n            if (action instanceof SQLIdentifierExpr) {\n                String name = ((SQLIdentifierExpr) action).getName();\n                if (\"RESOURCE\".equalsIgnoreCase(name)) {\n                    continue;\n                }\n            }\n\n            privilege.accept(this);\n            i++;\n        }\n    }\n\n    public boolean visit(SQLGrantStatement x) {\n        if (x.getResource() == null) {\n            print(\"ALTER ROLE \");\n\n            printAndAccept(x.getUsers(), \",\");\n\n            print(' ');\n            Set<SQLIdentifierExpr> pgPrivilegs = new LinkedHashSet<SQLIdentifierExpr>();\n            for (SQLPrivilegeItem privilege : x.getPrivileges()) {\n                SQLExpr action = privilege.getAction();\n                if (action instanceof SQLIdentifierExpr) {\n                    String name = ((SQLIdentifierExpr) action).getName();\n                    if (name.equalsIgnoreCase(\"CONNECT\")) {\n                        pgPrivilegs.add(new SQLIdentifierExpr(\"LOGIN\"));\n                    }\n                    if (name.toLowerCase().startsWith(\"create \")) {\n                        pgPrivilegs.add(new SQLIdentifierExpr(\"CREATEDB\"));\n                    }\n                }\n            }\n            int i = 0;\n            for (SQLExpr privilege : pgPrivilegs) {\n                if (i != 0) {\n                    print(' ');\n                }\n                privilege.accept(this);\n                i++;\n            }\n            return false;\n        }\n\n        return super.visit(x);\n    }\n    /** **************************************************************************/\n    // for oracle to postsql\n    /** **************************************************************************/\n\n    public boolean visit(OracleSysdateExpr x) {\n        print0(ucase ? \"CURRENT_TIMESTAMP\" : \"CURRENT_TIMESTAMP\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExceptionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExceptionStatement.Item x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleArgumentExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSetTransactionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExplainStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableDropPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableTruncatePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.TableSpaceItem x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.UpdateIndexesClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.NestedTablePartitionSpec x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableModify x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateIndexStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleForStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleFileSpecification x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceAddDataFile x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExitStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleContinueStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRaiseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateDatabaseDbLinkStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDropDbLinkStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalYear x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalDay x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleUsingIndexClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLobStorageClause x) {\n        return false;\n    }\n\n    public boolean visit(OracleSelectTableReference x) {\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY (\" : \"only (\");\n            printTableSourceExpr(x.getExpr());\n\n            if (x.getPartition() != null) {\n                print(' ');\n                x.getPartition().accept(this);\n            }\n\n            print(')');\n        } else {\n            printTableSourceExpr(x.getExpr());\n\n            if (x.getPartition() != null) {\n                print(' ');\n                x.getPartition().accept(this);\n            }\n        }\n\n        if (x.getHints().size() > 0) {\n            this.printHints(x.getHints());\n        }\n\n        if (x.getSampleClause() != null) {\n            print(' ');\n            x.getSampleClause().accept(this);\n        }\n\n        if (x.getPivot() != null) {\n            println();\n            x.getPivot().accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        printAlias(x.getAlias());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PartitionExtensionClause x) {\n        return false;\n    }\n\n    private void printHints(List<SQLHint> hints) {\n        if (hints.size() > 0) {\n            print0(\"/*+ \");\n            printAndAccept(hints, \", \");\n            print0(\" */\");\n        }\n    }\n\n    public boolean visit(OracleIntervalExpr x) {\n        if (x.getValue() instanceof SQLLiteralExpr || x.getValue() instanceof SQLVariantRefExpr) {\n            print0(ucase ? \"INTERVAL \" : \"interval \");\n        }\n        x.getValue().accept(this);\n        print(' ');\n\n        print0(x.getType().name());\n\n        if (x.getPrecision() != null) {\n            print('(');\n            printExpr(x.getPrecision());\n            if (x.getFactionalSecondsPrecision() != null) {\n                print0(\", \");\n                print(x.getFactionalSecondsPrecision().intValue());\n            }\n            print(')');\n        }\n\n        if (x.getToType() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            print0(x.getToType().name());\n            if (x.getToFactionalSecondsPrecision() != null) {\n                print('(');\n                printExpr(x.getToFactionalSecondsPrecision());\n                print(')');\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleOuterExpr x) {\n        x.getExpr().accept(this);\n        print0(\"(+)\");\n        return false;\n    }\n\n    public boolean visit(OracleBinaryFloatExpr x) {\n        if (x != null && x.getValue() != null) {\n            print0(x.getValue().toString());\n            print('F');\n        }\n        return false;\n    }\n\n    public boolean visit(OracleBinaryDoubleExpr x) {\n        if (x != null && x.getValue() != null) {\n            print0(x.getValue().toString());\n            print('D');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleIsSetExpr x) {\n        x.getNestedTable().accept(this);\n        print0(ucase ? \" IS A SET\" : \" is a set\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ReturnRowsClause x) {\n        if (x.isAll()) {\n            print0(ucase ? \"RETURN ALL ROWS\" : \"return all rows\");\n        } else {\n            print0(ucase ? \"RETURN UPDATED ROWS\" : \"return updated rows\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.MainModelClause x) {\n        if (x.getMainModelName() != null) {\n            print0(ucase ? \" MAIN \" : \" main \");\n            x.getMainModelName().accept(this);\n        }\n\n        println();\n        x.getModelColumnClause().accept(this);\n\n        for (ModelClause.CellReferenceOption opt : x.getCellReferenceOptions()) {\n            println();\n            print0(opt.name);\n        }\n\n        println();\n        x.getModelRulesClause().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ModelColumnClause x) {\n        if (x.getQueryPartitionClause() != null) {\n            x.getQueryPartitionClause().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"DIMENSION BY (\" : \"dimension by (\");\n        printAndAccept(x.getDimensionByColumns(), \", \");\n        print(')');\n\n        println();\n        print0(ucase ? \"MEASURES (\" : \"measures (\");\n        printAndAccept(x.getMeasuresColumns(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.QueryPartitionClause x) {\n        print0(ucase ? \"PARTITION BY (\" : \"partition by (\");\n        printAndAccept(x.getExprList(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ModelColumn x) {\n        x.getExpr().accept(this);\n        if (x.getAlias() != null) {\n            print(' ');\n            print0(x.getAlias());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ModelRulesClause x) {\n        if (x.getOptions().size() > 0) {\n            print0(ucase ? \"RULES\" : \"rules\");\n            for (ModelClause.ModelRuleOption opt : x.getOptions()) {\n                print(' ');\n                print0(opt.name);\n            }\n        }\n\n        if (x.getIterate() != null) {\n            print0(ucase ? \" ITERATE (\" : \" iterate (\");\n            x.getIterate().accept(this);\n            print(')');\n\n            if (x.getUntil() != null) {\n                print0(ucase ? \" UNTIL (\" : \" until (\");\n                x.getUntil().accept(this);\n                print(')');\n            }\n        }\n\n        print0(\" (\");\n        printAndAccept(x.getCellAssignmentItems(), \", \");\n        print(')');\n        return false;\n\n    }\n\n    @Override\n    public boolean visit(ModelClause.CellAssignmentItem x) {\n        if (x.getOption() != null) {\n            print0(x.getOption().name);\n            print(' ');\n        }\n\n        x.getCellAssignment().accept(this);\n\n        if (x.getOrderBy() != null) {\n            print(' ');\n            x.getOrderBy().accept(this);\n        }\n\n        print0(\" = \");\n        x.getExpr().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.CellAssignment x) {\n        x.getMeasureColumn().accept(this);\n        print0(\"[\");\n        printAndAccept(x.getConditions(), \", \");\n        print0(\"]\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause x) {\n        print0(ucase ? \"MODEL\" : \"model\");\n\n        this.indentCount++;\n        for (ModelClause.CellReferenceOption opt : x.getCellReferenceOptions()) {\n            print(' ');\n            print0(opt.name);\n        }\n\n        if (x.getReturnRowsClause() != null) {\n            print(' ');\n            x.getReturnRowsClause().accept(this);\n        }\n\n        for (ModelClause.ReferenceModelClause item : x.getReferenceModelClauses()) {\n            print(' ');\n            item.accept(this);\n        }\n\n        x.getMainModel().accept(this);\n        this.indentCount--;\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleReturningClause x) {\n        print0(ucase ? \"RETURNING \" : \"returning \");\n        printAndAccept(x.getItems(), \", \");\n        print0(ucase ? \" INTO \" : \" into \");\n        printAndAccept(x.getValues(), \", \");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleInsertStatement x) {\n        //visit((SQLInsertStatement) x);\n\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        printInsertColumns(x.getColumns());\n\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            x.getValues().accept(this);\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        if (x.getReturning() != null) {\n            println();\n            x.getReturning().accept(this);\n        }\n\n        if (x.getErrorLogging() != null) {\n            println();\n            x.getErrorLogging().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement.InsertIntoClause x) {\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        if (x.getColumns().size() > 0) {\n            this.indentCount++;\n            println();\n            print('(');\n            for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        println();\n                    }\n                    print0(\", \");\n                }\n                x.getColumns().get(i).accept(this);\n            }\n            print(')');\n            this.indentCount--;\n        }\n\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            x.getValues().accept(this);\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement x) {\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        if (x.getHints().size() > 0) {\n            this.printHints(x.getHints());\n        }\n\n        if (x.getOption() != null) {\n            print0(x.getOption().name());\n            print(' ');\n        }\n\n        for (int i = 0, size = x.getEntries().size(); i < size; ++i) {\n            this.indentCount++;\n            println();\n            x.getEntries().get(i).accept(this);\n            this.indentCount--;\n        }\n\n        println();\n        x.getSubQuery().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement.ConditionalInsertClause x) {\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n\n            OracleMultiInsertStatement.ConditionalInsertClauseItem item = x.getItems().get(i);\n\n            item.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            print0(ucase ? \"ELSE\" : \"else\");\n            this.indentCount++;\n            println();\n            x.getElseItem().accept(this);\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement.ConditionalInsertClauseItem x) {\n        print0(ucase ? \"WHEN \" : \"when \");\n        x.getWhen().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n        println();\n        x.getThen().accept(this);\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectQueryBlock x) {\n        if (isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        if (x.getHintsSize() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == x.getDistionOption()) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        }\n\n        printSelectList(x.getSelectList());\n\n        if (x.getInto() != null) {\n            println();\n            print0(ucase ? \"INTO \" : \"into \");\n            x.getInto().accept(this);\n        }\n\n        println();\n        print0(ucase ? \"FROM \" : \"from \");\n        if (x.getFrom() == null) {\n            print0(ucase ? \"DUAL\" : \"dual\");\n        } else {\n            x.getFrom().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            x.getWhere().accept(this);\n        }\n\n        printHierarchical(x);\n\n        if (x.getGroupBy() != null) {\n            println();\n            x.getGroupBy().accept(this);\n        }\n\n        if (x.getModelClause() != null) {\n            println();\n            x.getModelClause().accept(this);\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            orderBy.accept(this);\n        }\n\n        printFetchFirst(x);\n\n        if (x.isForUpdate()) {\n            println();\n            print0(ucase ? \"FOR UPDATE\" : \"for update\");\n            if (x.getForUpdateOfSize() > 0) {\n                print('(');\n                printAndAccept(x.getForUpdateOf(), \", \");\n                print(')');\n            }\n\n            if (x.isNoWait()) {\n                print0(ucase ? \" NOWAIT\" : \" nowait\");\n            } else if (x.isSkipLocked()) {\n                print0(ucase ? \" SKIP LOCKED\" : \" skip locked\");\n            } else if (x.getWaitTime() != null) {\n                print0(ucase ? \" WAIT \" : \" wait \");\n                x.getWaitTime().accept(this);\n            }\n        }\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLockTableStatement x) {\n        print0(ucase ? \"LOCK TABLE \" : \"lock table \");\n        x.getTable().accept(this);\n        print0(ucase ? \" IN \" : \" in \");\n        print0(x.getLockMode().toString());\n        print0(ucase ? \" MODE \" : \" mode \");\n        if (x.isNoWait()) {\n            print0(ucase ? \"NOWAIT\" : \"nowait\");\n        } else if (x.getWait() != null) {\n            print0(ucase ? \"WAIT \" : \"wait \");\n            x.getWait().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSessionStatement x) {\n        print0(ucase ? \"ALTER SESSION SET \" : \"alter session set \");\n        printAndAccept(x.getItems(), \", \");\n        return false;\n    }\n\n    public boolean visit(OracleRangeExpr x) {\n        x.getLowBound().accept(this);\n        print0(\"..\");\n        x.getUpBound().accept(this);\n        return false;\n    }\n\n    public boolean visit(OracleCheck x) {\n        visit((SQLCheck) x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSupplementalIdKey x) {\n        print0(ucase ? \"SUPPLEMENTAL LOG DATA (\" : \"supplemental log data (\");\n\n        int count = 0;\n\n        if (x.isAll()) {\n            print0(ucase ? \"ALL\" : \"all\");\n            count++;\n        }\n\n        if (x.isPrimaryKey()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"PRIMARY KEY\" : \"primary key\");\n            count++;\n        }\n\n        if (x.isUnique()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"UNIQUE\" : \"unique\");\n            count++;\n        }\n\n        if (x.isUniqueIndex()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"UNIQUE INDEX\" : \"unique index\");\n            count++;\n        }\n\n        if (x.isForeignKey()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"FOREIGN KEY\" : \"foreign key\");\n            count++;\n        }\n\n        print0(ucase ? \") COLUMNS\" : \") columns\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSupplementalLogGrp x) {\n        print0(ucase ? \"SUPPLEMENTAL LOG GROUP \" : \"supplemental log group \");\n        x.getGroup().accept(this);\n        print0(\" (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n        if (x.isAlways()) {\n            print0(ucase ? \" ALWAYS\" : \" always\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement.Organization x) {\n        String type = x.getType();\n\n        print0(ucase ? \"ORGANIZATION \" : \"organization \");\n        print0(ucase ? type : type.toLowerCase());\n\n        printOracleSegmentAttributes(x);\n\n        if (x.getPctthreshold() != null) {\n            println();\n            print0(ucase ? \"PCTTHRESHOLD \" : \"pctthreshold \");\n            print(x.getPctfree());\n        }\n\n        if (\"EXTERNAL\".equalsIgnoreCase(type)) {\n            print0(\" (\");\n\n            this.indentCount++;\n            if (x.getExternalType() != null) {\n                println();\n                print0(ucase ? \"TYPE \" : \"type \");\n                x.getExternalType().accept(this);\n            }\n\n            if (x.getExternalDirectory() != null) {\n                println();\n                print0(ucase ? \"DEFAULT DIRECTORY \" : \"default directory \");\n                x.getExternalDirectory().accept(this);\n            }\n\n            if (x.getExternalDirectoryRecordFormat() != null) {\n                println();\n                this.indentCount++;\n                print0(ucase ? \"ACCESS PARAMETERS (\" : \"access parameters (\");\n                x.getExternalDirectoryRecordFormat().accept(this);\n                this.indentCount--;\n                println();\n                print(')');\n            }\n\n            if (x.getExternalDirectoryLocation().size() > 0) {\n                println();\n                print0(ucase ? \"LOCATION (\" : \" location(\");\n                printAndAccept(x.getExternalDirectoryLocation(), \", \");\n                print(')');\n            }\n\n            this.indentCount--;\n            println();\n            print(')');\n\n            if (x.getExternalRejectLimit() != null) {\n                println();\n                print0(ucase ? \"REJECT LIMIT \" : \"reject limit \");\n                x.getExternalRejectLimit().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement.OIDIndex x) {\n        print0(ucase ? \"OIDINDEX\" : \"oidindex\");\n\n        if (x.getName() != null) {\n            print(' ');\n            x.getName().accept(this);\n        }\n        print(\" (\");\n        this.indentCount++;\n        printOracleSegmentAttributes(x);\n        this.indentCount--;\n        println();\n        print(\")\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreatePackageStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE PACKAGE \" : \"create or replace procedure \");\n        } else {\n            print0(ucase ? \"CREATE PACKAGE \" : \"create procedure \");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \"BODY \" : \"body \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.isBody()) {\n            println();\n            print0(ucase ? \"BEGIN\" : \"begin\");\n        }\n\n        this.indentCount++;\n\n        List<SQLStatement> statements = x.getStatements();\n        for (int i = 0, size = statements.size(); i < size; ++i) {\n            println();\n            SQLStatement stmt = statements.get(i);\n            stmt.accept(this);\n        }\n\n        this.indentCount--;\n\n        if (x.isBody() || statements.size() > 0) {\n            println();\n            print0(ucase ? \"END \" : \"end \");\n            x.getName().accept(this);\n            print(';');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExecuteImmediateStatement x) {\n        print0(ucase ? \"EXECUTE IMMEDIATE \" : \"execute immediate \");\n        x.getDynamicSql().accept(this);\n\n        List<SQLExpr> into = x.getInto();\n        if (into.size() > 0) {\n            print0(ucase ? \" INTO \" : \" into \");\n            printAndAccept(into, \", \");\n        }\n\n        List<SQLArgument> using = x.getArguments();\n        if (using.size() > 0) {\n            print0(ucase ? \" USING \" : \" using \");\n            printAndAccept(using, \", \");\n        }\n\n        List<SQLExpr> returnInto = x.getReturnInto();\n        if (returnInto.size() > 0) {\n            print0(ucase ? \" RETURNNING INTO \" : \" returnning into \");\n            printAndAccept(returnInto, \", \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleTreatExpr x) {\n        print0(ucase ? \"TREAT (\" : \"treat (\");\n        x.getExpr().accept(this);\n        print0(ucase ? \" AS \" : \" as \");\n        if (x.isRef()) {\n            print0(ucase ? \"REF \" : \"ref \");\n        }\n        x.getType().accept(this);\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateSynonymStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE \" : \"create or replace \");\n        } else {\n            print0(ucase ? \"CREATE \" : \"create \");\n        }\n\n        if (x.isPublic()) {\n            print0(ucase ? \"PUBLIC \" : \"public \");\n        }\n\n        print0(ucase ? \"SYNONYM \" : \"synonym \");\n\n        x.getName().accept(this);\n\n        print0(ucase ? \" FOR \" : \" for \");\n        x.getObject().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTypeStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE TYPE \" : \"create or replace type \");\n        } else {\n            print0(ucase ? \"CREATE TYPE \" : \"create type \");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \"BODY \" : \"body \");\n        }\n\n        x.getName().accept(this);\n\n        SQLName under = x.getUnder();\n        if (under != null) {\n            print0(ucase ? \" UNDER \" : \" under \");\n            under.accept(this);\n        }\n\n        SQLName authId = x.getAuthId();\n        if (authId != null) {\n            print0(ucase ? \" AUTHID \" : \" authid \");\n            authId.accept(this);\n        }\n\n        if (x.isForce()) {\n            print0(ucase ? \"FORCE \" : \"force \");\n        }\n\n        List<SQLParameter> parameters = x.getParameters();\n        SQLDataType tableOf = x.getTableOf();\n\n        if (x.isObject()) {\n            print0(\" AS OBJECT\");\n        }\n\n        if (parameters.size() > 0) {\n            if (x.isParen()) {\n                print(\" (\");\n            } else {\n                print0(ucase ? \" IS\" : \" is\");\n            }\n            indentCount++;\n            println();\n\n            for (int i = 0; i < parameters.size(); ++i) {\n                SQLParameter param = parameters.get(i);\n                param.accept(this);\n\n                SQLDataType dataType = param.getDataType();\n\n                if (i < parameters.size() - 1) {\n                    if (dataType instanceof OracleFunctionDataType\n                            && ((OracleFunctionDataType) dataType).getBlock() != null) {\n                        // skip\n                        println();\n                    } else if (dataType instanceof OracleProcedureDataType\n                            && ((OracleProcedureDataType) dataType).getBlock() != null) {\n                        // skip\n                        println();\n                    } else {\n                        println(\", \");\n                    }\n                }\n            }\n\n            indentCount--;\n            println();\n\n            if (x.isParen()) {\n                print0(\")\");\n            } else {\n                print0(\"END\");\n            }\n        } else if (tableOf != null) {\n            print0(ucase ? \" AS TABLE OF \" : \" as table of \");\n            tableOf.accept(this);\n        } else if (x.getVarraySizeLimit() != null) {\n            print0(ucase ? \" VARRAY (\" : \" varray (\");\n            x.getVarraySizeLimit().accept(this);\n            print0(ucase ? \") OF \" : \") of \");\n            x.getVarrayDataType().accept(this);\n        }\n\n        Boolean isFinal = x.getFinal();\n        if (isFinal != null) {\n            if (isFinal.booleanValue()) {\n                print0(ucase ? \" FINAL\" : \" final\");\n            } else {\n                print0(ucase ? \" NOT FINAL\" : \" not final\");\n            }\n        }\n\n        Boolean instantiable = x.getInstantiable();\n        if (instantiable != null) {\n            if (instantiable.booleanValue()) {\n                print0(ucase ? \" INSTANTIABLE\" : \" instantiable\");\n            } else {\n                print0(ucase ? \" NOT INSTANTIABLE\" : \" not instantiable\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OraclePipeRowStatement x) {\n        print0(ucase ? \"PIPE ROW(\" : \"pipe row(\");\n        printAndAccept(x.getParameters(), \", \");\n        print(')');\n        return false;\n    }\n\n    public boolean visit(OraclePrimaryKey x) {\n        visit((SQLPrimaryKey) x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement x) {\n        printCreateTable(x, false);\n\n        if (x.getOf() != null) {\n            println();\n            print0(ucase ? \"OF \" : \"of \");\n            x.getOf().accept(this);\n        }\n\n        if (x.getOidIndex() != null) {\n            println();\n            x.getOidIndex().accept(this);\n        }\n\n        if (x.getOrganization() != null) {\n            println();\n            this.indentCount++;\n            x.getOrganization().accept(this);\n            this.indentCount--;\n        }\n\n        printOracleSegmentAttributes(x);\n\n        if (x.isInMemoryMetadata()) {\n            println();\n            print0(ucase ? \"IN_MEMORY_METADATA\" : \"in_memory_metadata\");\n        }\n\n        if (x.isCursorSpecificSegment()) {\n            println();\n            print0(ucase ? \"CURSOR_SPECIFIC_SEGMENT\" : \"cursor_specific_segment\");\n        }\n\n        if (Boolean.TRUE.equals(x.getParallel())) {\n            println();\n            print0(ucase ? \"PARALLEL\" : \"parallel\");\n        } else if (Boolean.FALSE.equals(x.getParallel())) {\n            println();\n            print0(ucase ? \"NOPARALLEL\" : \"noparallel\");\n        }\n\n        if (Boolean.TRUE.equals(x.getCache())) {\n            println();\n            print0(ucase ? \"CACHE\" : \"cache\");\n        } else if (Boolean.FALSE.equals(x.getCache())) {\n            println();\n            print0(ucase ? \"NOCACHE\" : \"nocache\");\n        }\n\n        if (x.getLobStorage() != null) {\n            println();\n            x.getLobStorage().accept(this);\n        }\n\n        if (x.isOnCommitPreserveRows()) {\n            println();\n            print0(ucase ? \"ON COMMIT PRESERVE ROWS\" : \"on commit preserve rows\");\n        } else if (x.isOnCommitDeleteRows()) {\n            println();\n            print0(ucase ? \"ON COMMIT DELETE ROWS\" : \"on commit delete rows\");\n        }\n\n        if (x.isMonitoring()) {\n            println();\n            print0(ucase ? \"MONITORING\" : \"monitoring\");\n        }\n\n        printPartitionBy(x);\n\n        if (x.getCluster() != null) {\n            println();\n            print0(ucase ? \"CLUSTER \" : \"cluster \");\n            x.getCluster().accept(this);\n            print0(\" (\");\n            printAndAccept(x.getClusterColumns(), \",\");\n            print0(\")\");\n        }\n\n        if (x.getSelect() != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            x.getSelect().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleStorageClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleGotoStatement x) {\n        print0(ucase ? \"GOTO \" : \"GOTO \");\n        x.getLabel().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLabelStatement x) {\n        print0(\"<<\");\n        x.getLabel().accept(this);\n        print0(\">>\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTriggerStatement x) {\n        print0(ucase ? \"ALTER TRIGGER \" : \"alter trigger \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSynonymStatement x) {\n        print0(ucase ? \"ALTER SYNONYM \" : \"alter synonym \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterViewStatement x) {\n        print0(ucase ? \"ALTER VIEW \" : \"alter view \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableMoveTablespace x) {\n        print0(ucase ? \" MOVE TABLESPACE \" : \" move tablespace \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    public boolean visit(OracleForeignKey x) {\n        visit((SQLForeignKeyImpl) x);\n        return false;\n    }\n\n    public boolean visit(OracleUnique x) {\n        visit((SQLUnique) x);\n        return false;\n    }\n\n    public boolean visit(OracleSelectSubqueryTableSource x) {\n        print('(');\n        this.indentCount++;\n        println();\n        x.getSelect().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        if (x.getPivot() != null) {\n            println();\n            x.getPivot().accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        printFlashback(x.getFlashback());\n\n        if ((x.getAlias() != null) && (x.getAlias().length() != 0)) {\n            print(' ');\n            print0(x.getAlias());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnpivot x) {\n        print0(ucase ? \"UNPIVOT\" : \"unpivot\");\n        if (x.getNullsIncludeType() != null) {\n            print(' ');\n            print0(SQLUnpivot.NullsIncludeType.toString(x.getNullsIncludeType(), ucase));\n        }\n\n        print0(\" (\");\n        if (x.getItems().size() == 1) {\n            ((SQLExpr) x.getItems().get(0)).accept(this);\n        } else {\n            print0(\" (\");\n            printAndAccept(x.getItems(), \", \");\n            print(')');\n        }\n\n        if (x.getPivotFor().size() > 0) {\n            print0(ucase ? \" FOR \" : \" for \");\n            if (x.getPivotFor().size() == 1) {\n                ((SQLExpr) x.getPivotFor().get(0)).accept(this);\n            } else {\n                print('(');\n                printAndAccept(x.getPivotFor(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.getPivotIn().size() > 0) {\n            print0(ucase ? \" IN (\" : \" in (\");\n            printAndAccept(x.getPivotIn(), \", \");\n            print(')');\n        }\n\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleUpdateStatement x) {\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY (\" : \"only (\");\n            x.getTableSource().accept(this);\n            print(')');\n        } else {\n            x.getTableSource().accept(this);\n        }\n\n        printAlias(x.getAlias());\n\n        println();\n\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            x.getItems().get(i).accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            this.indentCount++;\n            x.getWhere().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getReturning().size() > 0) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            printAndAccept(x.getReturning(), \", \");\n            print0(ucase ? \" INTO \" : \" into \");\n            printAndAccept(x.getReturningInto(), \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SampleClause x) {\n        print0(ucase ? \"SAMPLE \" : \"sample \");\n\n        if (x.isBlock()) {\n            print0(ucase ? \"BLOCK \" : \"block \");\n        }\n\n        print('(');\n        printAndAccept(x.getPercent(), \", \");\n        print(')');\n\n        if (x.getSeedValue() != null) {\n            print0(ucase ? \" SEED (\" : \" seed (\");\n            x.getSeedValue().accept(this);\n            print(')');\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleSelectJoin x) {\n        x.getLeft().accept(this);\n        SQLTableSource right = x.getRight();\n\n        if (x.getJoinType() == SQLJoinTableSource.JoinType.COMMA) {\n            print0(\", \");\n            x.getRight().accept(this);\n        } else {\n            boolean isRoot = x.getParent() instanceof SQLSelectQueryBlock;\n            if (isRoot) {\n                this.indentCount++;\n            }\n\n            println();\n            print0(ucase ? x.getJoinType().name : x.getJoinType().nameLCase);\n            print(' ');\n\n            if (right instanceof SQLJoinTableSource) {\n                print('(');\n                right.accept(this);\n                print(')');\n            } else {\n                right.accept(this);\n            }\n\n            if (isRoot) {\n                this.indentCount--;\n            }\n\n            if (x.getCondition() != null) {\n                print0(ucase ? \" ON \" : \" on \");\n                x.getCondition().accept(this);\n                print(' ');\n                if (x.getAfterCommentsDirect() != null) {\n                    printAfterComments(x.getAfterCommentsDirect());\n                    println();\n                }\n            }\n\n            if (x.getUsing().size() > 0) {\n                print0(ucase ? \" USING (\" : \" using (\");\n                printAndAccept(x.getUsing(), \", \");\n                print(')');\n            }\n\n            printFlashback(x.getFlashback());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectRestriction.CheckOption x) {\n        print0(ucase ? \"CHECK OPTION\" : \"check option\");\n        if (x.getConstraint() != null) {\n            print0(ucase ? \" CONSTRAINT\" : \" constraint\");\n            print(' ');\n            x.getConstraint().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectRestriction.ReadOnly x) {\n        print0(ucase ? \"READ ONLY\" : \"read only\");\n        if (x.getConstraint() != null) {\n            print0(ucase ? \" CONSTRAINT\" : \" constraint\");\n            print(' ');\n            x.getConstraint().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(OracleDeleteStatement x) {\n        return visit((SQLDeleteStatement) x);\n    }\n\n    private void printFlashback(SQLExpr flashback) {\n        if (flashback == null) {\n            return;\n        }\n\n        println();\n\n        if (flashback instanceof SQLBetweenExpr) {\n            flashback.accept(this);\n        } else {\n            print0(ucase ? \"AS OF \" : \"as of \");\n            flashback.accept(this);\n        }\n    }\n\n    public boolean visit(OracleWithSubqueryEntry x) {\n        print0(x.getAlias());\n\n        if (x.getColumns().size() > 0) {\n            print0(\" (\");\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        print0(ucase ? \" AS \" : \" as \");\n        print('(');\n        this.indentCount++;\n        println();\n        x.getSubQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        if (x.getSearchClause() != null) {\n            println();\n            x.getSearchClause().accept(this);\n        }\n\n        if (x.getCycleClause() != null) {\n            println();\n            x.getCycleClause().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SearchClause x) {\n        print0(ucase ? \"SEARCH \" : \"search \");\n        print0(x.getType().name());\n        print0(ucase ? \" FIRST BY \" : \" first by \");\n        printAndAccept(x.getItems(), \", \");\n        print0(ucase ? \" SET \" : \" set \");\n        x.getOrderingColumn().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(CycleClause x) {\n        print0(ucase ? \"CYCLE \" : \"cycle \");\n        printAndAccept(x.getAliases(), \", \");\n        print0(ucase ? \" SET \" : \" set \");\n        x.getMark().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getValue().accept(this);\n        print0(ucase ? \" DEFAULT \" : \" default \");\n        x.getDefaultValue().accept(this);\n\n        return false;\n    }\n\n    public boolean visit(OracleAnalytic x) {\n        print0(ucase ? \"(\" : \"(\");\n\n        boolean space = false;\n        if (x.getPartitionBy().size() > 0) {\n            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n            printAndAccept(x.getPartitionBy(), \", \");\n\n            space = true;\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            if (space) {\n                print(' ');\n            }\n            visit(orderBy);\n            space = true;\n        }\n\n        OracleAnalyticWindowing windowing = x.getWindowing();\n        if (windowing != null) {\n            if (space) {\n                print(' ');\n            }\n            visit(windowing);\n        }\n\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(OracleAnalyticWindowing x) {\n        print0(x.getType().name().toUpperCase());\n        print(' ');\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleIsOfTypeExpr x) {\n        printExpr(x.getExpr());\n        print0(ucase ? \" IS OF TYPE (\" : \" is of type (\");\n\n        List<SQLExpr> types = x.getTypes();\n        for (int i = 0, size = types.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLExpr type = types.get(i);\n            if (Boolean.TRUE.equals(type.getAttribute(\"ONLY\"))) {\n                print0(ucase ? \"ONLY \" : \"only \");\n            }\n            type.accept(this);\n        }\n\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRunStatement x) {\n        print0(\"@@\");\n        printExpr(x.getExpr());\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.Else x) {\n        print0(ucase ? \"ELSE\" : \"else\");\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.ElseIf x) {\n        print0(ucase ? \"ELSE IF \" : \"else if \");\n        x.getCondition().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            println();\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement x) {\n        print0(ucase ? \"IF \" : \"if \");\n        int lines = this.lines;\n        this.indentCount++;\n        x.getCondition().accept(this);\n        this.indentCount--;\n\n        if (lines != this.lines) {\n            println();\n        } else {\n            print(' ');\n        }\n        print0(ucase ? \"THEN\" : \"then\");\n\n        this.indentCount++;\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            println();\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n        this.indentCount--;\n\n        for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) {\n            println();\n            elseIf.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            x.getElseItem().accept(this);\n        }\n        println();\n        print0(ucase ? \"END IF\" : \"end if\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateIndexStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        if (x.getType() != null) {\n            print0(x.getType());\n            print(' ');\n        }\n\n        print0(ucase ? \"INDEX\" : \"index\");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \" IF NOT EXISTS\" : \" if not exists\");\n        }\n\n        if (x.isConcurrently()) {\n            print0(ucase ? \" CONCURRENTLY\" : \" concurrently\");\n        }\n\n        SQLName name = x.getName();\n        if (name != null) {\n            print(' ');\n            name.accept(this);\n        }\n\n        print0(ucase ? \" ON \" : \" on \");\n        x.getTable().accept(this);\n\n        if (x.getUsing() != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(x.getUsing());\n        }\n        print0(\" (\");\n        printAndAccept(x.getItems(), \", \");\n        print(')');\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        boolean hasOptions = false;\n\n        if (x.getIndexDefinition().hasOptions()) {\n            SQLIndexOptions indexOptions = x.getIndexDefinition().getOptions();\n            if (indexOptions.getKeyBlockSize() != null ||\n                indexOptions.getParserName() != null ||\n                indexOptions.getAlgorithm() != null ||\n                indexOptions.getLock() != null ||\n                indexOptions.getOtherOptions().size() > 0) {\n                hasOptions = true;\n            }\n        }\n\n        if (hasOptions) {\n            print0(ucase ? \" WITH (\" : \" with (\");\n            SQLIndexOptions indexOptions = x.getIndexDefinition().getOptions();\n\n            SQLExpr keyBlockSize = indexOptions.getKeyBlockSize();\n            if (keyBlockSize != null) {\n                print0(ucase ? \" KEY_BLOCK_SIZE = \" : \" key_block_size = \");\n                printExpr(keyBlockSize, parameterized);\n            }\n\n            String parserName = indexOptions.getParserName();\n            if (parserName != null) {\n                print0(ucase ? \" WITH PARSER \" : \" with parser \");\n                print0(parserName);\n            }\n\n            String algorithm = indexOptions.getAlgorithm();\n            if (algorithm != null) {\n                print0(ucase ? \" ALGORITHM = \" : \" algorithm = \");\n                print0(algorithm);\n            }\n\n            String lock = indexOptions.getLock();\n            if (lock != null) {\n                print0(ucase ? \" LOCK \" : \" lock \");\n                print0(lock);\n            }\n\n            for (SQLAssignItem option : indexOptions.getOtherOptions()) {\n                option.accept(this);\n            }\n\n            print(')');\n        }\n\n        SQLName tablespace = x.getTablespace();\n        if (tablespace != null) {\n            print0(ucase ? \" TABLESPACE \" : \" tablespace \");\n            tablespace.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddColumn x) {\n        boolean odps = isOdps();\n        print0(ucase ? \"ADD COLUMN \" : \"add column \");\n        printAndAccept(x.getColumns(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {\n        return false;\n    }\n\n    public boolean visit(SQLArrayDataType x) {\n        x.getComponentType().accept(this);\n        print('[');\n        printAndAccept(x.getArguments(), \", \");\n        print(']');\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/visitor/OscarPermissionOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.*;\n\nimport java.util.List;\n\npublic class OscarPermissionOutputVisitor extends OscarOutputVisitor {\n    public OscarPermissionOutputVisitor(StringBuilder appender) {\n        super(appender);\n        this.dbType = DbType.oscar;\n    }\n\n    public OscarPermissionOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, parameterized);\n        this.dbType = DbType.oscar;\n    }\n\n    @Override\n    public boolean visit(SQLExprTableSource x) {\n        String catalog = x.getCatalog();\n        String schema = x.getSchema();\n        String tableName = x.getTableName();\n        List<SQLName> columns1 = x.getColumns();\n        int sourceColumn = x.getSourceColumn();\n\n        //SQLExpr sqlExpr = SQLUtils.toSQLExpr(\"id=3\", dbType);\n\n        print(\" (\");\n        print0(ucase ? \"SELECT \" : \"select \");\n        print('*');\n        print0(ucase ? \" FROM \" : \" from \");\n        printTableSourceExpr(x.getExpr());\n        //print0(ucase ? \" WHERE \" : \" where \");\n        //printExpr(sqlExpr);\n        print(')');\n\n        final SQLTableSampling sampling = x.getSampling();\n        if (sampling != null) {\n            print(' ');\n            sampling.accept(this);\n        }\n\n        String alias = x.getAlias();\n        List<SQLName> columns = x.getColumnsDirect();\n        if (alias != null) {\n            print(' ');\n            if (columns != null && columns.size() > 0) {\n                print0(ucase ? \" AS \" : \" as \");\n            }\n            print0(alias);\n        }\n\n        if (columns != null && columns.size() > 0) {\n            print(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        for (int i = 0; i < x.getHintsSize(); ++i) {\n            print(' ');\n            x.getHints().get(i).accept(this);\n        }\n\n        if (x.getPartitionSize() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printlnAndAccept(x.getPartitions(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/oscar/visitor/OscarStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.oscar.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oscar.parser.OscarCreateTableParser;\nimport com.alibaba.druid.sql.dialect.oscar.parser.OscarExprParser;\nimport com.alibaba.druid.sql.dialect.oscar.parser.OscarSelectParser;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class OscarStatementParser extends SQLStatementParser {\n    public static final String TIME_ZONE = \"TIME ZONE\";\n    public static final String TIME = \"TIME\";\n    public static final String LOCAL = \"LOCAL\";\n\n    public OscarStatementParser(OscarExprParser parser) {\n        super(parser);\n    }\n\n    public OscarStatementParser(String sql) {\n        super(new OscarExprParser(sql));\n    }\n\n    public OscarStatementParser(String sql, SQLParserFeature... features) {\n        super(new OscarExprParser(sql, features));\n    }\n\n    public OscarStatementParser(Lexer lexer) {\n        super(new OscarExprParser(lexer));\n    }\n\n    public OscarSelectParser createSQLSelectParser() {\n        return new OscarSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLUpdateStatement parseUpdateStatement() {\n        accept(Token.UPDATE);\n\n        OscarUpdateStatement updateStatement = new OscarUpdateStatement();\n\n        SQLSelectParser selectParser = this.exprParser.createSelectParser();\n        SQLTableSource tableSource = selectParser.parseTableSource();\n        updateStatement.setTableSource(tableSource);\n\n        parseUpdateSet(updateStatement);\n\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n            SQLTableSource from = selectParser.parseTableSource();\n            updateStatement.setFrom(from);\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            updateStatement.setWhere(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n\n            for (;;) {\n                updateStatement.getReturning().add(this.exprParser.expr());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        return updateStatement;\n    }\n\n    public OscarInsertStatement parseInsert() {\n        OscarInsertStatement stmt = new OscarInsertStatement();\n\n        if (lexer.token() == Token.INSERT) {\n            lexer.nextToken();\n            accept(Token.INTO);\n\n            SQLName tableName = this.exprParser.name();\n            stmt.setTableName(tableName);\n\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.token() == Token.IDENTIFIER) {\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            }\n\n        }\n\n        if (lexer.token() == Token.DEFAULT) {\n            lexer.nextToken();\n            accept(Token.VALUES);\n            stmt.setDefaultValues(true);\n        }\n\n        if (lexer.token() == (Token.LPAREN)) {\n            lexer.nextToken();\n            this.exprParser.exprList(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == (Token.VALUES)) {\n            lexer.nextToken();\n\n            for (;;) {\n                accept(Token.LPAREN);\n                SQLInsertStatement.ValuesClause valuesCaluse = new SQLInsertStatement.ValuesClause();\n                this.exprParser.exprList(valuesCaluse.getValues(), valuesCaluse);\n                stmt.addValueCause(valuesCaluse);\n\n                accept(Token.RPAREN);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        } else if (lexer.token() == (Token.SELECT)) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n            stmt.setQuery(queryExpr.getSubQuery());\n        }\n\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.CONFLICT)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    List<SQLExpr> onConflictTarget = new ArrayList<SQLExpr>();\n                    this.exprParser.exprList(onConflictTarget, stmt);\n                    stmt.setOnConflictTarget(onConflictTarget);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.token() == Token.ON) {\n                    lexer.nextToken();\n                    accept(Token.CONSTRAINT);\n                    SQLName constraintName = this.exprParser.name();\n                    stmt.setOnConflictConstraint(constraintName);\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = this.exprParser.expr();\n                    stmt.setOnConflictWhere(where);\n                }\n\n                if (lexer.token() == Token.DO) {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.NOTHING)) {\n                        lexer.nextToken();\n                        stmt.setOnConflictDoNothing(true);\n                    } else {\n                        accept(Token.UPDATE);\n                        accept(Token.SET);\n\n                        for (;;) {\n                            SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n                            stmt.addConflicUpdateItem(item);\n\n                            if (lexer.token() != Token.COMMA) {\n                                break;\n                            }\n\n                            lexer.nextToken();\n                        }\n                        if (lexer.token() == Token.WHERE) {\n                            lexer.nextToken();\n                            SQLExpr where = this.exprParser.expr();\n                            stmt.setOnConflictUpdateWhere(where);\n                        }\n                    }\n                }\n            }\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n            SQLExpr returning = this.exprParser.expr();\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                SQLListExpr list = new SQLListExpr();\n                list.addItem(returning);\n\n                this.exprParser.exprList(list.getItems(), list);\n\n                returning = list;\n            }\n\n            stmt.setReturning(returning);\n        }\n        return stmt;\n    }\n\n    public OscarCreateSchemaStatement parseCreateSchema() {\n        accept(Token.CREATE);\n        accept(Token.SCHEMA);\n\n        OscarCreateSchemaStatement stmt = new OscarCreateSchemaStatement();\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n\n            stmt.setIfNotExists(true);\n        }\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            if (lexer.identifierEquals(\"AUTHORIZATION\")) {\n                lexer.nextToken();\n                stmt.setAuthorization(true);\n\n                SQLIdentifierExpr userName = (SQLIdentifierExpr) this.exprParser.expr();\n                stmt.setUserName(userName);\n            } else {\n                SQLIdentifierExpr schemaName = (SQLIdentifierExpr) this.exprParser.expr();\n                stmt.setSchemaName(schemaName);\n\n                if (lexer.identifierEquals(\"AUTHORIZATION\")) {\n                    lexer.nextToken();\n                    stmt.setAuthorization(true);\n\n                    SQLIdentifierExpr userName = (SQLIdentifierExpr) this.exprParser.expr();\n                    stmt.setUserName(userName);\n                }\n            }\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterSchema() {\n        accept(Token.ALTER);\n        accept(Token.SCHEMA);\n\n        OscarAlterSchemaStatement stmt = new OscarAlterSchemaStatement();\n        stmt.setSchemaName(this.exprParser.identifier());\n\n        if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n            lexer.nextToken();\n            accept(Token.TO);\n            stmt.setNewName(this.exprParser.identifier());\n        } else if (lexer.identifierEquals(FnvHash.Constants.OWNER)) {\n            lexer.nextToken();\n            accept(Token.TO);\n            stmt.setNewOwner(this.exprParser.identifier());\n        }\n\n        return stmt;\n    }\n\n    public OscarDropSchemaStatement parseDropSchema(boolean physical) {\n        OscarDropSchemaStatement stmt = new OscarDropSchemaStatement();\n\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLIdentifierExpr name = this.exprParser.identifier();\n        stmt.setSchemaName(name);\n\n        if (lexer.identifierEquals(FnvHash.Constants.RESTRICT)) {\n            lexer.nextToken();\n            stmt.setRestrict(true);\n        } else if (lexer.token() == Token.CASCADE || lexer.identifierEquals(FnvHash.Constants.CASCADE)) {\n            lexer.nextToken();\n            stmt.setCascade(true);\n        } else {\n            stmt.setCascade(false);\n        }\n\n        return stmt;\n    }\n\n    public OscarDeleteStatement parseDeleteStatement() {\n        lexer.nextToken();\n        OscarDeleteStatement deleteStatement = new OscarDeleteStatement();\n\n        if (lexer.token() == (Token.FROM)) {\n            lexer.nextToken();\n        }\n        if (lexer.token() == (Token.ONLY)) {\n            lexer.nextToken();\n            deleteStatement.setOnly(true);\n        }\n\n        SQLName tableName = exprParser.name();\n\n        deleteStatement.setTableName(tableName);\n\n        if (lexer.token() == Token.AS) {\n            accept(Token.AS);\n        }\n        if (lexer.token() == Token.IDENTIFIER) {\n            deleteStatement.setAlias(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n\n            SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n            deleteStatement.setUsing(tableSource);\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.CURRENT) {\n                lexer.nextToken();\n                accept(Token.OF);\n                SQLName cursorName = this.exprParser.name();\n                SQLExpr where = new SQLCurrentOfCursorExpr(cursorName);\n                deleteStatement.setWhere(where);\n            } else {\n                SQLExpr where = this.exprParser.expr();\n                deleteStatement.setWhere(where);\n            }\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n            accept(Token.STAR);\n            deleteStatement.setReturning(true);\n        }\n\n        return deleteStatement;\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        switch (lexer.token()) {\n            case BEGIN:\n            case START: {\n                OscarStartTransactionStatement stmt = parseBegin();\n                statementList.add(stmt);\n                return true;\n            }\n            case WITH:\n                statementList.add(parseWith());\n                return true;\n            default:\n                if (lexer.identifierEquals(FnvHash.Constants.CONNECT)) {\n                    SQLStatement stmt = parseConnectTo();\n                    statementList.add(stmt);\n                    return true;\n                }\n\n                break;\n        }\n        return false;\n    }\n\n    protected OscarStartTransactionStatement parseBegin() {\n        OscarStartTransactionStatement stmt = new OscarStartTransactionStatement();\n        if (lexer.token() == Token.START) {\n            lexer.nextToken();\n            acceptIdentifier(\"TRANSACTION\");\n        } else {\n            accept(Token.BEGIN);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseConnectTo() {\n        acceptIdentifier(\"CONNECT\");\n        accept(Token.TO);\n\n        OscarConnectToStatement stmt = new OscarConnectToStatement();\n        SQLName target = this.exprParser.name();\n        stmt.setTarget(target);\n\n        return stmt;\n    }\n\n    public OscarSelectStatement parseSelect() {\n        OscarSelectParser selectParser = createSQLSelectParser();\n        SQLSelect select = selectParser.select();\n        return new OscarSelectStatement(select);\n    }\n\n    public SQLStatement parseWith() {\n        SQLWithSubqueryClause with = this.parseWithQuery();\n        // OscarWithClause with = this.parseWithClause();\n        if (lexer.token() == Token.INSERT) {\n            OscarInsertStatement stmt = this.parseInsert();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            OscarSelectStatement stmt = this.parseSelect();\n            stmt.getSelect().setWithSubQuery(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.DELETE) {\n            OscarDeleteStatement stmt = this.parseDeleteStatement();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.UPDATE) {\n            OscarUpdateStatement stmt = (OscarUpdateStatement) this.parseUpdateStatement();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        throw new ParserException(\"TODO. \" + lexer.info());\n    }\n\n    protected SQLAlterTableAlterColumn parseAlterColumn() {\n        if (lexer.token() == Token.COLUMN) {\n            lexer.nextToken();\n        }\n\n        SQLColumnDefinition column = this.exprParser.parseColumn();\n\n        SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn();\n        alterColumn.setColumn(column);\n\n        if (column.getDataType() == null && column.getConstraints().isEmpty()) {\n            if (lexer.token() == Token.SET) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setSetNotNull(true);\n                } else {\n                    accept(Token.DEFAULT);\n                    SQLExpr defaultValue = this.exprParser.expr();\n                    alterColumn.setSetDefault(defaultValue);\n                }\n            } else if (lexer.token() == Token.DROP) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setDropNotNull(true);\n                } else {\n                    accept(Token.DEFAULT);\n                    alterColumn.setDropDefault(true);\n                }\n            }\n        }\n        return alterColumn;\n    }\n\n    public SQLStatement parseShow() {\n        accept(Token.SHOW);\n        OscarShowStatement stmt = new OscarShowStatement();\n        switch (lexer.token()) {\n        case ALL:\n            stmt.setExpr(new SQLIdentifierExpr(Token.ALL.name()));\n            lexer.nextToken();\n            break;\n        default:\n            stmt.setExpr(this.exprParser.expr());\n            break;\n        }\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseCommit() {\n        SQLCommitStatement stmt = new SQLCommitStatement();\n        stmt.setDbType(this.dbType);\n        lexer.nextToken();\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseSet() {\n        accept(Token.SET);\n        Token token = lexer.token();\n        String range = \"\";\n\n        SQLSetStatement.Option option = null;\n        if (token == Token.SESSION) {\n            lexer.nextToken();\n            range = Token.SESSION.name();\n            option = SQLSetStatement.Option.SESSION;\n        } else if (token == Token.IDENTIFIER && LOCAL.equalsIgnoreCase(lexer.stringVal())) {\n            range = LOCAL;\n            option = SQLSetStatement.Option.LOCAL;\n            lexer.nextToken();\n        }\n\n        long hash = lexer.hashLCase();\n        String parameter = lexer.stringVal();\n        SQLExpr paramExpr;\n        List<SQLExpr> values = new ArrayList<SQLExpr>();\n        if (hash == FnvHash.Constants.TIME) {\n            lexer.nextToken();\n            acceptIdentifier(\"ZONE\");\n            paramExpr = new SQLIdentifierExpr(\"TIME ZONE\");\n            String value = lexer.stringVal();\n            if (lexer.token() == Token.IDENTIFIER) {\n                values.add(new SQLIdentifierExpr(value.toUpperCase()));\n            } else {\n                values.add(new SQLCharExpr(value));\n            }\n            lexer.nextToken();\n//            return new PGSetStatement(range, TIME_ZONE, exprs);\n        } else if (hash == FnvHash.Constants.ROLE) {\n            paramExpr = new SQLIdentifierExpr(parameter);\n            lexer.nextToken();\n            values.add(this.exprParser.primary());\n            lexer.nextToken();\n        } else {\n            paramExpr = new SQLIdentifierExpr(parameter);\n            lexer.nextToken();\n\n            while (!lexer.isEOF()) {\n                lexer.nextToken();\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    values.add(new SQLCharExpr(lexer.stringVal()));\n                } else if (lexer.token() == Token.LITERAL_INT) {\n                    values.add(new SQLIdentifierExpr(lexer.numberString()));\n                } else if (lexer.identifierEquals(FnvHash.Constants.JSON_SET)\n                        || lexer.identifierEquals(FnvHash.Constants.JSONB_SET)) {\n                    SQLExpr json_set = this.exprParser.expr();\n                    values.add(json_set);\n                } else {\n                    values.add(new SQLIdentifierExpr(lexer.stringVal()));\n                }\n                // skip comma\n                lexer.nextToken();\n            }\n        }\n\n        // value | 'value' | DEFAULT\n\n        SQLExpr valueExpr;\n        if (values.size() == 1) {\n            valueExpr = values.get(0);\n        } else {\n            SQLListExpr listExpr = new SQLListExpr();\n            for (SQLExpr value : values) {\n                listExpr.addItem(value);\n            }\n            valueExpr = listExpr;\n        }\n        SQLSetStatement stmt = new SQLSetStatement(paramExpr, valueExpr, dbType);\n        stmt.setOption(option);\n        return stmt;\n    }\n\n    public SQLCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n        SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(getDbType());\n        if (lexer.token() == Token.UNIQUE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"CLUSTERED\")) {\n                lexer.nextToken();\n                stmt.setType(\"UNIQUE CLUSTERED\");\n            } else {\n                stmt.setType(\"UNIQUE\");\n            }\n        } else if (lexer.identifierEquals(\"FULLTEXT\")) {\n            stmt.setType(\"FULLTEXT\");\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"NONCLUSTERED\")) {\n            stmt.setType(\"NONCLUSTERED\");\n            lexer.nextToken();\n        }\n\n        accept(Token.INDEX);\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CONCURRENTLY)) {\n            lexer.nextToken();\n            stmt.setConcurrently(true);\n        }\n\n        if (lexer.token() != Token.ON) {\n            stmt.setName(this.exprParser.name());\n        }\n\n        accept(Token.ON);\n\n        stmt.setTable(this.exprParser.name());\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n            String using = lexer.stringVal();\n            accept(Token.IDENTIFIER);\n            stmt.setUsing(using);\n        }\n\n        accept(Token.LPAREN);\n\n        for (;;) {\n            SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n            item.setParent(stmt);\n            stmt.addItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            for (;;) {\n                String optionName = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n                accept(Token.EQ);\n                SQLExpr option = this.exprParser.expr();\n                option.setParent(stmt);\n\n                stmt.addOption(optionName, option);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.TABLESPACE) {\n            lexer.nextToken();\n            SQLName tablespace = this.exprParser.name();\n            stmt.setTablespace(tablespace);\n        }\n\n        return stmt;\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new OscarCreateTableParser(this.exprParser);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/Phoenix.java",
    "content": "package com.alibaba.druid.sql.dialect.phoenix;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Phoenix {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.phoenix);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/ast/PhoenixObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.phoenix.visitor.PhoenixASTVisitor;\n\n/**\n * Created by wenshao on 16/9/14.\n */\npublic interface PhoenixObject extends SQLObject {\n    void accept0(PhoenixASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/ast/PhoenixStatementImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.phoenix.visitor.PhoenixASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * Created by wenshao on 16/9/14.\n */\npublic abstract class PhoenixStatementImpl extends SQLStatementImpl implements PhoenixObject {\n    public PhoenixStatementImpl() {\n        super(DbType.phoenix);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PhoenixASTVisitor) {\n            accept0((PhoenixASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public abstract void accept0(PhoenixASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/ast/PhoenixUpsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.ast;\n\nimport com.alibaba.druid.sql.dialect.phoenix.visitor.PhoenixASTVisitor;\n\n/**\n * Created by wenshao on 16/9/14.\n */\npublic class PhoenixUpsertStatement extends PhoenixStatementImpl {\n    @Override\n    public void accept0(PhoenixASTVisitor visitor) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/parser/PhoenixExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.parser;\n\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic class PhoenixExprParser extends SQLExprParser {\n    public PhoenixExprParser(String sql, SQLParserFeature... features) {\n        this(new PhoenixLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public PhoenixExprParser(Lexer lexer) {\n        super(lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/parser/PhoenixLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic class PhoenixLexer extends Lexer {\n    public static final Keywords PHOENIX_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"OPTIMIZE\", Token.OPTIMIZE);\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"UPSERT\", Token.UPSERT);\n\n        PHOENIX_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return PHOENIX_KEYWORDS;\n    }\n\n    public PhoenixLexer(String input, SQLParserFeature... features) {\n        super(input);\n        dbType = DbType.phoenix;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/parser/PhoenixStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertInto;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic class PhoenixStatementParser extends SQLStatementParser {\n    public PhoenixStatementParser(String sql) {\n        super(new PhoenixExprParser(sql));\n    }\n\n    public PhoenixStatementParser(Lexer lexer) {\n        super(new PhoenixExprParser(lexer));\n    }\n\n    @Override\n    protected void parseInsertColumns(SQLInsertInto insert) {\n        if (lexer.token() == Token.RPAREN) {\n            return;\n        }\n\n        for (; ; ) {\n            SQLName expr = this.exprParser.name();\n            expr.setParent(insert);\n            insert.getColumns().add(expr);\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                String text = lexer.stringVal();\n                if (text.equalsIgnoreCase(\"TINYINT\")\n                        || text.equalsIgnoreCase(\"BIGINT\")\n                        || text.equalsIgnoreCase(\"INTEGER\")\n                        || text.equalsIgnoreCase(\"DOUBLE\")\n                        || text.equalsIgnoreCase(\"DATE\")\n                        || text.equalsIgnoreCase(\"VARCHAR\")) {\n                    expr.getAttributes().put(\"dataType\", text);\n                    lexer.nextToken();\n                } else if (text.equalsIgnoreCase(\"CHAR\")) {\n                    String dataType = text;\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    SQLExpr char_len = this.exprParser.primary();\n                    accept(Token.RPAREN);\n                    dataType += (\"(\" + char_len.toString() + \")\");\n                    expr.getAttributes().put(\"dataType\", dataType);\n                }\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/visitor/PhoenixASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic interface PhoenixASTVisitor extends SQLASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/visitor/PhoenixOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.phoenix.Phoenix;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic class PhoenixOutputVisitor extends SQLASTOutputVisitor implements PhoenixASTVisitor {\n    public PhoenixOutputVisitor(StringBuilder appender) {\n    super(appender, DbType.phoenix, Phoenix.DIALECT);\n    }\n\n    public PhoenixOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.phoenix, Phoenix.DIALECT, parameterized);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/phoenix/visitor/PhoenixSchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.phoenix.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic class PhoenixSchemaStatVisitor extends SchemaStatVisitor implements PhoenixASTVisitor {\n    public PhoenixSchemaStatVisitor() {\n        super(DbType.phoenix);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/PG.java",
    "content": "package com.alibaba.druid.sql.dialect.postgresql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class PG {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.postgresql);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\npublic interface PGSQLObject extends SQLObject {\n    void accept0(PGASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/PGSQLObjectImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class PGSQLObjectImpl extends SQLObjectImpl implements PGSQLObject {\n    public PGSQLObjectImpl() {\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            this.accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    public abstract void accept0(PGASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGAttrExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\n\npublic class PGAttrExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr name;\n    private SQLExpr value;\n    private PGExprMode mode;\n\n    public static enum PGExprMode {\n        EMPTY,\n        EQ\n    }\n\n    public PGAttrExpr clone() {\n        PGAttrExpr x = new PGAttrExpr();\n        if (value != null) {\n            x.setName(name.clone());\n            x.setValue(value.clone());\n            x.setMode(this.mode);\n        }\n        return x;\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        this.name = name;\n    }\n\n    public SQLExpr getValue() { return value; }\n\n    public void setValue(SQLExpr value) { this.value = value; }\n\n    public PGExprMode getMode() { return this.mode; }\n\n    public void setMode(PGExprMode mode) { this.mode = mode; }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((name == null) ? 0 : name.hashCode());\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        result = prime * result + ((mode == null) ? 0 : mode.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGAttrExpr other = (PGAttrExpr) obj;\n\n        return Objects.equals(this.name, other.name) &&\n               Objects.equals(this.value, other.value) &&\n               Objects.equals(this.mode, other.mode);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGBoxExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGBoxExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGBoxExpr clone() {\n        PGBoxExpr x = new PGBoxExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGBoxExpr other = (PGBoxExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGCharExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGCharExpr extends SQLCharExpr implements PGExpr {\n    private boolean cSytle;\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            visitor.visit(this);\n            visitor.endVisit(this);\n        }\n    }\n\n    public boolean isCSytle() {\n        return cSytle;\n    }\n\n    public void setCSytle(boolean cSytle) {\n        this.cSytle = cSytle;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGCidrExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGCidrExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGCidrExpr clone() {\n        PGCidrExpr x = new PGCidrExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGCidrExpr other = (PGCidrExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGCircleExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGCircleExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGCircleExpr clone() {\n        PGCircleExpr x = new PGCircleExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGCircleExpr other = (PGCircleExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGDateField.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\npublic enum PGDateField {\n    CENTURY,\n    DAY,\n    DECADE,\n    DOW,\n    DOY,\n    EPOCH,\n    HOUR,\n    ISODOW,\n    ISOYEAR,\n    MICROSECONDS,\n    MILLENNIUM,\n    MILLISECONDS,\n    MINUTE,\n    MONTH,\n    QUARTER,\n    SECOND,\n    TIMEZONE,\n    TIMEZONE_HOUR,\n    TIMEZONE_MINUTE,\n    WEEK,\n    YEAR\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;\n\npublic interface PGExpr extends SQLExpr, PGSQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExprImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExprImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class PGExprImpl extends SQLExprImpl implements PGExpr {\n    @Override\n    public abstract void accept0(PGASTVisitor visitor);\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    public String toString() {\n        return SQLUtils.toPGString(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExtractExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGExtractExpr extends PGExprImpl implements SQLReplaceable {\n    private PGDateField field;\n    private SQLExpr source;\n\n    public PGExtractExpr clone() {\n        PGExtractExpr x = new PGExtractExpr();\n        x.field = field;\n        if (source != null) {\n            x.setSource(source.clone());\n        }\n        return x;\n    }\n\n    public PGDateField getField() {\n        return field;\n    }\n\n    public void setField(PGDateField field) {\n        this.field = field;\n    }\n\n    public SQLExpr getSource() {\n        return source;\n    }\n\n    public void setSource(SQLExpr source) {\n        if (source != null) {\n            source.setParent(this);\n        }\n        this.source = source;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.source == expr) {\n            setSource(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, source);\n        }\n        visitor.endVisit(this);\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(source);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((field == null) ? 0 : field.hashCode());\n        result = prime * result + ((source == null) ? 0 : source.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGExtractExpr other = (PGExtractExpr) obj;\n        if (field != other.field) {\n            return false;\n        }\n        if (source == null) {\n            if (other.source != null) {\n                return false;\n            }\n        } else if (!source.equals(other.source)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGInetExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGInetExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGInetExpr clone() {\n        PGInetExpr x = new PGInetExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGInetExpr other = (PGInetExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGLineSegmentsExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGLineSegmentsExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGLineSegmentsExpr clone() {\n        PGLineSegmentsExpr x = new PGLineSegmentsExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGLineSegmentsExpr other = (PGLineSegmentsExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGMacAddrExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGMacAddrExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGMacAddrExpr clone() {\n        PGMacAddrExpr x = new PGMacAddrExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGMacAddrExpr other = (PGMacAddrExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGPointExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGPointExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGPointExpr clone() {\n        PGPointExpr x = new PGPointExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGPointExpr other = (PGPointExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGPolygonExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLReplaceable;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PGPolygonExpr extends PGExprImpl implements SQLReplaceable {\n    private SQLExpr value;\n\n    public PGPolygonExpr clone() {\n        PGPolygonExpr x = new PGPolygonExpr();\n        if (value != null) {\n            x.setValue(value.clone());\n        }\n        return x;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        this.value = value;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, value);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public boolean replace(SQLExpr expr, SQLExpr target) {\n        if (this.value == expr) {\n            setValue(target);\n            return true;\n        }\n\n        return false;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(value);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((value == null) ? 0 : value.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        PGPolygonExpr other = (PGPolygonExpr) obj;\n        if (value == null) {\n            if (other.value != null) {\n                return false;\n            }\n        } else if (!value.equals(other.value)) {\n            return false;\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGTypeCastExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.expr;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLCastExpr;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGTypeCastExpr extends SQLCastExpr implements PGExpr {\n    public PGTypeCastExpr() {\n    }\n\n    public PGTypeCastExpr(SQLExpr expr, SQLDataType dataType) {\n        super(expr, dataType);\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n            acceptChild(visitor, this.dataType);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public PGTypeCastExpr clone() {\n        PGTypeCastExpr x = new PGTypeCastExpr();\n        x.isTry = isTry;\n        if (expr != null) {\n            x.setExpr(expr.clone());\n        }\n        if (dataType != null) {\n            x.setDataType(dataType.clone());\n        }\n        return x;\n    }\n\n    public String toString() {\n        return SQLUtils.toPGString(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGAlterDatabaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://www.postgresql.org/docs/current/sql-alterdatabase.html\">alter table</a>\n *\n */\npublic class PGAlterDatabaseStatement extends SQLStatementImpl implements PGSQLStatement, SQLAlterStatement {\n    private SQLIdentifierExpr databaseName;\n    private SQLIdentifierExpr renameToName;\n    private SQLIdentifierExpr ownerToName;\n    private SQLIdentifierExpr setTableSpaceName;\n    private boolean refreshCollationVersion;\n    private SQLIdentifierExpr setParameterName;\n    private boolean useEquals;\n    private SQLExpr setParameterValue;\n    private boolean setFromCurrent;\n    private SQLIdentifierExpr resetParameterName;\n    private boolean haveWith;\n    private Boolean allowConnections;\n    private Boolean setTemplateMark;\n\n    public SQLIdentifierExpr getDatabaseName() {\n        return databaseName;\n    }\n\n    public void setDatabaseName(SQLIdentifierExpr databaseName) {\n        this.databaseName = databaseName;\n    }\n\n    public SQLIdentifierExpr getRenameToName() {\n        return renameToName;\n    }\n\n    public void setRenameToName(SQLIdentifierExpr renameToName) {\n        this.renameToName = renameToName;\n    }\n\n    public SQLIdentifierExpr getOwnerToName() {\n        return ownerToName;\n    }\n\n    public void setOwnerToName(SQLIdentifierExpr ownerToName) {\n        this.ownerToName = ownerToName;\n    }\n\n    public SQLIdentifierExpr getSetTableSpaceName() {\n        return setTableSpaceName;\n    }\n\n    public void setSetTableSpaceName(SQLIdentifierExpr setTableSpaceName) {\n        this.setTableSpaceName = setTableSpaceName;\n    }\n\n    public boolean isRefreshCollationVersion() {\n        return refreshCollationVersion;\n    }\n\n    public void setRefreshCollationVersion(boolean refreshCollationVersion) {\n        this.refreshCollationVersion = refreshCollationVersion;\n    }\n\n    public SQLIdentifierExpr getSetParameterName() {\n        return setParameterName;\n    }\n\n    public void setSetParameterName(SQLIdentifierExpr setParameterName) {\n        this.setParameterName = setParameterName;\n    }\n\n    public boolean isUseEquals() {\n        return useEquals;\n    }\n\n    public void setUseEquals(boolean useEquals) {\n        this.useEquals = useEquals;\n    }\n\n    public SQLExpr getSetParameterValue() {\n        return setParameterValue;\n    }\n\n    public void setSetParameterValue(SQLExpr setParameterValue) {\n        this.setParameterValue = setParameterValue;\n    }\n\n    public boolean isSetFromCurrent() {\n        return setFromCurrent;\n    }\n\n    public void setSetFromCurrent(boolean setFromCurrent) {\n        this.setFromCurrent = setFromCurrent;\n    }\n\n    public SQLIdentifierExpr getResetParameterName() {\n        return resetParameterName;\n    }\n\n    public void setResetParameterName(SQLIdentifierExpr resetParameterName) {\n        this.resetParameterName = resetParameterName;\n    }\n\n    public boolean isHaveWith() {\n        return haveWith;\n    }\n\n    public void setHaveWith(boolean haveWith) {\n        this.haveWith = haveWith;\n    }\n\n    public Boolean getAllowConnections() {\n        return allowConnections;\n    }\n\n    public void setAllowConnections(Boolean allowConnections) {\n        this.allowConnections = allowConnections;\n    }\n\n    public Boolean getSetTemplateMark() {\n        return setTemplateMark;\n    }\n\n    public void setSetTemplateMark(Boolean setTemplateMark) {\n        this.setTemplateMark = setTemplateMark;\n    }\n\n    public PGAlterDatabaseStatement(DbType dbType) {\n        super.dbType = dbType;\n    }\n\n    @Override\n    public DDLObjectType getDDLObjectType() {\n        return DDLObjectType.DATABASE;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.databaseName);\n            acceptChild(visitor, this.renameToName);\n            acceptChild(visitor, this.ownerToName);\n            acceptChild(visitor, this.setTableSpaceName);\n            acceptChild(visitor, this.setParameterName);\n            acceptChild(visitor, this.setParameterValue);\n            acceptChild(visitor, this.resetParameterName);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGAlterSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGAlterSchemaStatement extends SQLStatementImpl implements PGSQLStatement, SQLAlterStatement {\n    private SQLName schemaName;\n    private SQLIdentifierExpr newName;\n    private SQLIdentifierExpr newOwner;\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    public SQLIdentifierExpr getNewName() {\n        return newName;\n    }\n\n    public void setNewName(SQLIdentifierExpr newName) {\n        this.newName = newName;\n    }\n\n    public SQLIdentifierExpr getNewOwner() {\n        return newOwner;\n    }\n\n    public void setNewOwner(SQLIdentifierExpr newOwner) {\n        this.newOwner = newOwner;\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n            acceptChild(visitor, this.newName);\n            acceptChild(visitor, this.newOwner);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGAlterTableAlterColumnSetNotNull.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\npublic class PGAlterTableAlterColumnSetNotNull {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGAnalyzeStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://www.postgresql.org/docs/current/sql-analyze.html\">ANALYZE — collect statistics about a database</a>\n */\npublic class PGAnalyzeStatement extends SQLStatementImpl implements PGSQLStatement {\n    private boolean verbose;\n    private boolean skipLocked;\n    private List<SQLExprTableSource> tableSources = new ArrayList<>();\n\n    public PGAnalyzeStatement(DbType dbType) {\n        super.dbType = dbType;\n    }\n\n    public boolean isVerbose() {\n        return verbose;\n    }\n\n    public void setVerbose(boolean verbose) {\n        this.verbose = verbose;\n    }\n\n    public boolean isSkipLocked() {\n        return skipLocked;\n    }\n\n    public void setSkipLocked(boolean skipLocked) {\n        this.skipLocked = skipLocked;\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void setTableSources(List<SQLExprTableSource> tableSources) {\n        this.tableSources = tableSources;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSources);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGConnectToStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGConnectToStatement extends SQLStatementImpl implements PGSQLStatement {\n    private SQLName target;\n\n    public PGConnectToStatement() {\n        super(DbType.postgresql);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            this.accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, target);\n        }\n        v.endVisit(this);\n    }\n\n    public SQLName getTarget() {\n        return target;\n    }\n\n    public void setTarget(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.target = x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGCopyStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGCopyStatement extends SQLStatementImpl implements PGSQLStatement {\n    private SQLExprTableSource table;\n    private final List<SQLName> columns = new ArrayList<SQLName>();\n    private SQLSelect query;\n    private boolean directionTo;\n    private SQLExpr target; // file path, STDIN, STDOUT\n    private boolean program;\n    private final List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n    private SQLExpr where;\n\n    public PGCopyStatement() {\n        super(DbType.postgresql);\n    }\n\n    public SQLExprTableSource getTable() {\n        return table;\n    }\n\n    public void setTable(SQLExprTableSource x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.table = x;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public SQLSelect getQuery() {\n        return query;\n    }\n\n    public void setQuery(SQLSelect x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.query = x;\n    }\n\n    public boolean isDirectionTo() {\n        return directionTo;\n    }\n\n    public void setDirectionTo(boolean directionTo) {\n        this.directionTo = directionTo;\n    }\n\n    public SQLExpr getTarget() {\n        return target;\n    }\n\n    public void setTarget(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.target = x;\n    }\n\n    public boolean isProgram() {\n        return program;\n    }\n\n    public void setProgram(boolean program) {\n        this.program = program;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public SQLExpr getWhere() {\n        return where;\n    }\n\n    public void setWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.where = x;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, table);\n            acceptChild(visitor, columns);\n            acceptChild(visitor, query);\n            acceptChild(visitor, target);\n            acceptChild(visitor, options);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGCreateDatabaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGAttrExpr;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGCreateDatabaseStatement extends SQLStatementImpl implements PGSQLStatement, SQLCreateStatement {\n    private SQLName name;\n    private boolean haveWith;\n    private List<PGAttrExpr> stats = new ArrayList<>();\n\n    public PGCreateDatabaseStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    @Override\n    public SQLName getName() { return this.name; }\n\n    public void setName(SQLName dbName) { this.name = dbName; }\n\n    public boolean isHaveWith() { return haveWith; }\n\n    public void setHaveWith(boolean haveWith) { this.haveWith = haveWith; }\n\n    public List<PGAttrExpr> getStats() { return stats; }\n\n    public void setStats(List<PGAttrExpr> stats) { this.stats = stats; }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.name);\n            acceptChild(visitor, this.stats);\n        }\n\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGCreateExtensionStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGCreateExtensionStatement extends SQLStatementImpl implements PGSQLStatement {\n    public PGCreateExtensionStatement() {\n        super(DbType.postgresql);\n    }\n\n    private SQLName name;\n    private boolean ifNotExists;\n    private SQLName schema;\n    private String version;\n    private boolean cascade;\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public SQLName getSchema() {\n        return schema;\n    }\n\n    public void setSchema(SQLName schema) {\n        if (schema != null) {\n            schema.setParent(this);\n        }\n        this.schema = schema;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, schema);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGCreateSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGCreateSchemaStatement extends SQLStatementImpl implements PGSQLStatement, SQLCreateStatement {\n    private SQLName schemaName;\n    private SQLIdentifierExpr userName;\n    private boolean ifNotExists;\n    private boolean authorization;\n    private List<SQLCreateStatement> createStatements = new ArrayList<>();\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    public SQLIdentifierExpr getUserName() {\n        return userName;\n    }\n\n    public void setUserName(SQLIdentifierExpr userName) {\n        this.userName = userName;\n    }\n\n    public boolean isIfNotExists() {\n        return ifNotExists;\n    }\n\n    public void setIfNotExists(boolean ifNotExists) {\n        this.ifNotExists = ifNotExists;\n    }\n\n    public boolean isAuthorization() {\n        return authorization;\n    }\n\n    public void setAuthorization(boolean authorization) {\n        this.authorization = authorization;\n    }\n\n    public List<SQLCreateStatement> getCreateStatements() {\n        return createStatements;\n    }\n\n    public void setCreateStatements(List<SQLCreateStatement> createStatements) {\n        this.createStatements = createStatements;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n            acceptChild(visitor, this.userName);\n        }\n\n        if (this.createStatements != null && !this.createStatements.isEmpty()) {\n            for (SQLCreateStatement stat : this.createStatements) {\n                acceptChild(visitor, stat);\n            }\n        }\n\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDeleteStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGDeleteStatement extends SQLDeleteStatement implements PGSQLStatement {\n    private boolean returning;\n\n    public PGDeleteStatement() {\n        super(DbType.postgresql);\n    }\n\n    public boolean isReturning() {\n        return returning;\n    }\n\n    public void setReturning(boolean returning) {\n        this.returning = returning;\n    }\n\n    public String getAlias() {\n        if (tableSource == null) {\n            return null;\n        }\n        return tableSource.getAlias();\n    }\n\n    public void setAlias(String alias) {\n        this.tableSource.setAlias(alias);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, with);\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, using);\n            acceptChild(visitor, where);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public PGDeleteStatement clone() {\n        PGDeleteStatement x = new PGDeleteStatement();\n        cloneTo(x);\n\n        x.returning = returning;\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDoStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGDoStatement extends SQLStatementImpl implements PGSQLStatement {\n    private SQLStatement block;\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, block);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLStatement getBlock() {\n        return block;\n    }\n\n    public void setBlock(SQLStatement block) {\n        if (block != null) {\n            block.setParent(this);\n        }\n        this.block = block;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDropDatabaseStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLDropCatalogStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGDropDatabaseStatement extends SQLDropCatalogStatement implements PGSQLStatement {\n    private boolean usingWith;\n    private boolean force;\n\n    public PGDropDatabaseStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public boolean isUsingWith() {\n        return usingWith;\n    }\n\n    public void setUsingWith(boolean usingWith) {\n        this.usingWith = usingWith;\n    }\n\n    public boolean isForce() { return force; }\n\n    public void setForce(boolean force) { this.force = force; }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.getName());\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGDropSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLDropStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGDropSchemaStatement extends SQLStatementImpl implements PGSQLStatement, SQLDropStatement {\n    private SQLName schemaName;\n    private List<SQLName> multipleNames = new ArrayList<>();\n    private boolean ifExists;\n    private boolean cascade;\n    private boolean restrict;\n\n    public SQLName getSchemaName() {\n        return this.schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    public List<SQLName> getMultipleNames() {\n        return this.multipleNames;\n    }\n\n    public void setMultipleNames(List<SQLName> multipleNames) {\n        this.multipleNames = multipleNames;\n    }\n\n    public boolean isIfExists() {\n        return ifExists;\n    }\n\n    public void setIfExists(boolean ifExists) {\n        this.ifExists = ifExists;\n    }\n\n    public boolean isCascade() {\n        return cascade;\n    }\n\n    public void setCascade(boolean cascade) {\n        this.cascade = cascade;\n    }\n\n    public boolean isRestrict() {\n        return restrict;\n    }\n\n    public void setRestrict(boolean restrict) {\n        this.restrict = restrict;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.schemaName);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGEndTransactionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * @author lizongbo\n * @see  <a href=\"https://www.postgresql.org/docs/current/sql-end.html\">end语法</a>\n */\npublic class PGEndTransactionStatement extends SQLStatementImpl implements PGSQLStatement {\n    public PGEndTransactionStatement() {\n        super(DbType.postgresql);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGFunctionTableSource.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLHint;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGFunctionTableSource extends SQLExprTableSource implements PGSQLObject {\n    private final List<SQLParameter> parameters = new ArrayList<SQLParameter>();\n\n    public PGFunctionTableSource() {\n    }\n\n    public PGFunctionTableSource(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    public List<SQLParameter> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            this.accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n            acceptChild(visitor, this.parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public PGFunctionTableSource clone() {\n        PGFunctionTableSource x = new PGFunctionTableSource();\n\n        x.setAlias(this.alias);\n\n        for (SQLParameter e : this.parameters) {\n            SQLParameter e2 = e.clone();\n            e2.setParent(x);\n            x.getParameters().add(e2);\n        }\n\n        if (this.flashback != null) {\n            x.setFlashback(this.flashback.clone());\n        }\n\n        if (this.hints != null) {\n            for (SQLHint e : this.hints) {\n                SQLHint e2 = e.clone();\n                e2.setParent(x);\n                x.getHints().add(e2);\n            }\n        }\n\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGInsertStatement extends SQLInsertStatement implements PGSQLStatement {\n    private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();\n    private SQLExpr returning;\n    private boolean defaultValues;\n\n    private List<SQLExpr> onConflictTarget;\n    private SQLName onConflictConstraint;\n    private SQLExpr onConflictWhere;\n    private SQLExpr onConflictUpdateWhere;\n    private boolean onConflictDoNothing;\n    private List<SQLUpdateSetItem> onConflictUpdateSetItems;\n\n    public PGInsertStatement() {\n        dbType = DbType.postgresql;\n    }\n\n    public void cloneTo(PGInsertStatement x) {\n        super.cloneTo(x);\n        for (ValuesClause v : valuesList) {\n            ValuesClause v2 = v.clone();\n            v2.setParent(x);\n            x.valuesList.add(v2);\n        }\n        if (returning != null) {\n            x.setReturning(returning.clone());\n        }\n        x.defaultValues = defaultValues;\n    }\n\n    public SQLExpr getReturning() {\n        return returning;\n    }\n\n    public void setReturning(SQLExpr returning) {\n        this.returning = returning;\n    }\n\n    public ValuesClause getValues() {\n        if (valuesList.isEmpty()) {\n            return null;\n        }\n        return valuesList.get(0);\n    }\n\n    public void setValues(ValuesClause values) {\n        if (valuesList.isEmpty()) {\n            valuesList.add(values);\n        } else {\n            valuesList.set(0, values);\n        }\n    }\n\n    public List<ValuesClause> getValuesList() {\n        return valuesList;\n    }\n\n    public void addValueCause(ValuesClause valueClause) {\n        valueClause.setParent(this);\n        valuesList.add(valueClause);\n    }\n\n    public boolean isDefaultValues() {\n        return defaultValues;\n    }\n\n    public void setDefaultValues(boolean defaultValues) {\n        this.defaultValues = defaultValues;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, with);\n            this.acceptChild(visitor, tableSource);\n            this.acceptChild(visitor, columns);\n            this.acceptChild(visitor, valuesList);\n            this.acceptChild(visitor, query);\n            this.acceptChild(visitor, returning);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public PGInsertStatement clone() {\n        PGInsertStatement x = new PGInsertStatement();\n        cloneTo(x);\n        return x;\n    }\n\n    public List<SQLExpr> getOnConflictTarget() {\n        return onConflictTarget;\n    }\n\n    public void setOnConflictTarget(List<SQLExpr> onConflictTarget) {\n        this.onConflictTarget = onConflictTarget;\n    }\n\n    public boolean isOnConflictDoNothing() {\n        return onConflictDoNothing;\n    }\n\n    public void setOnConflictDoNothing(boolean onConflictDoNothing) {\n        this.onConflictDoNothing = onConflictDoNothing;\n    }\n\n    public List<SQLUpdateSetItem> getOnConflictUpdateSetItems() {\n        return onConflictUpdateSetItems;\n    }\n\n    public void addConflicUpdateItem(SQLUpdateSetItem item) {\n        if (onConflictUpdateSetItems == null) {\n            onConflictUpdateSetItems = new ArrayList<SQLUpdateSetItem>();\n        }\n\n        item.setParent(this);\n        onConflictUpdateSetItems.add(item);\n    }\n\n    public SQLName getOnConflictConstraint() {\n        return onConflictConstraint;\n    }\n\n    public void setOnConflictConstraint(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.onConflictConstraint = x;\n    }\n\n    public SQLExpr getOnConflictWhere() {\n        return onConflictWhere;\n    }\n\n    public void setOnConflictWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.onConflictWhere = x;\n    }\n\n    public SQLExpr getOnConflictUpdateWhere() {\n        return onConflictUpdateWhere;\n    }\n\n    public void setOnConflictUpdateWhere(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.onConflictUpdateWhere = x;\n    }\n\n    @Override\n    public List<SQLCommentHint> getHeadHintsDirect() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSQLStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;\n\npublic interface PGSQLStatement extends SQLStatement, PGSQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGSelectQueryBlock extends SQLSelectQueryBlock implements PGSQLObject {\n    private List<SQLExpr> distinctOn = new ArrayList<SQLExpr>(2);\n\n    private FetchClause fetch;\n    private ForClause forClause;\n    private IntoOption intoOption;\n\n    public static enum IntoOption {\n        TEMPORARY, TEMP, UNLOGGED\n    }\n\n    public PGSelectQueryBlock() {\n        dbType = DbType.postgresql;\n    }\n\n    public IntoOption getIntoOption() {\n        return intoOption;\n    }\n\n    public void setIntoOption(IntoOption intoOption) {\n        this.intoOption = intoOption;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.distinctOn);\n            acceptChild(visitor, this.selectList);\n            acceptChild(visitor, this.into);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.groupBy);\n            acceptChild(visitor, this.windows);\n            acceptChild(visitor, this.orderBy);\n            acceptChild(visitor, this.limit);\n            acceptChild(visitor, this.fetch);\n            acceptChild(visitor, this.forClause);\n        }\n        visitor.endVisit(this);\n    }\n\n    public FetchClause getFetch() {\n        return fetch;\n    }\n\n    public void setFetch(FetchClause fetch) {\n        this.fetch = fetch;\n    }\n\n    public ForClause getForClause() {\n        return forClause;\n    }\n\n    public void setForClause(ForClause forClause) {\n        this.forClause = forClause;\n    }\n\n    public List<SQLExpr> getDistinctOn() {\n        return distinctOn;\n    }\n\n    public void setDistinctOn(List<SQLExpr> distinctOn) {\n        this.distinctOn = distinctOn;\n    }\n\n    public static class FetchClause extends PGSQLObjectImpl {\n        public static enum Option {\n            FIRST, NEXT\n        }\n\n        private Option option;\n        private SQLExpr count;\n\n        public Option getOption() {\n            return option;\n        }\n\n        public void setOption(Option option) {\n            this.option = option;\n        }\n\n        public SQLExpr getCount() {\n            return count;\n        }\n\n        public void setCount(SQLExpr count) {\n            this.count = count;\n        }\n\n        @Override\n        public void accept0(PGASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, count);\n            }\n            visitor.endVisit(this);\n        }\n\n    }\n\n    public static class ForClause extends PGSQLObjectImpl {\n        public static enum Option {\n            UPDATE, SHARE\n        }\n\n        private List<SQLExpr> of = new ArrayList<SQLExpr>(2);\n        private boolean noWait;\n        private boolean skipLocked;\n        private Option option;\n\n        public Option getOption() {\n            return option;\n        }\n\n        public void setOption(Option option) {\n            this.option = option;\n        }\n\n        public List<SQLExpr> getOf() {\n            return of;\n        }\n\n        public void setOf(List<SQLExpr> of) {\n            this.of = of;\n        }\n\n        public boolean isNoWait() {\n            return noWait;\n        }\n\n        public void setNoWait(boolean noWait) {\n            this.noWait = noWait;\n        }\n\n        public boolean isSkipLocked() {\n            return skipLocked;\n        }\n\n        public void setSkipLocked(boolean skipLocked) {\n            this.skipLocked = skipLocked;\n        }\n\n        @Override\n        public void accept0(PGASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, of);\n            }\n            visitor.endVisit(this);\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGSelectStatement extends SQLSelectStatement implements PGSQLStatement {\n    public PGSelectStatement() {\n        super(DbType.postgresql);\n    }\n\n    public PGSelectStatement(SQLSelect select) {\n        super(select, DbType.postgresql);\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.select);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGShowStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLShowStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGShowStatement extends SQLStatementImpl implements PGSQLStatement, SQLShowStatement {\n    private SQLExpr expr;\n\n    public PGShowStatement() {\n        super(DbType.postgresql);\n    }\n\n    public PGShowStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.expr);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGStartTransactionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGStartTransactionStatement extends SQLStatementImpl implements PGSQLStatement {\n    public PGStartTransactionStatement() {\n        super(DbType.postgresql);\n    }\n\n    private boolean useBegin;\n\n    public boolean isUseBegin() {\n        return useBegin;\n    }\n\n    public void setUseBegin(boolean useBegin) {\n        this.useBegin = useBegin;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGUpdateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PGUpdateStatement extends SQLUpdateStatement implements PGSQLStatement {\n    private boolean only;\n\n    public PGUpdateStatement() {\n        super(DbType.postgresql);\n    }\n\n    public boolean isOnly() {\n        return only;\n    }\n\n    public void setOnly(boolean only) {\n        this.only = only;\n    }\n\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n            return;\n        }\n\n        super.accept0(visitor);\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGVacuumStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://www.postgresql.org/docs/current/sql-vacuum.html\">VACUUM — garbage-collect and optionally analyze a database</a>\n */\npublic class PGVacuumStatement extends SQLStatementImpl implements PGSQLStatement {\n    private boolean full;\n    private boolean freeze;\n    private boolean verbose;\n    private boolean skipLocked;\n    private boolean analyze;\n    private boolean disablePageSkipping;\n    private boolean processToast;\n    private boolean truncate;\n    // gaussDb specific\n    private boolean deltaMerge;\n    private boolean hdfsDirectory;\n    private List<SQLExprTableSource> tableSources = new ArrayList<>();\n\n    public PGVacuumStatement(DbType dbType) {\n        super.dbType = dbType;\n    }\n\n    public boolean isVerbose() {\n        return verbose;\n    }\n\n    public void setVerbose(boolean verbose) {\n        this.verbose = verbose;\n    }\n\n    public boolean isSkipLocked() {\n        return skipLocked;\n    }\n\n    public void setSkipLocked(boolean skipLocked) {\n        this.skipLocked = skipLocked;\n    }\n\n    public List<SQLExprTableSource> getTableSources() {\n        return tableSources;\n    }\n\n    public void setTableSources(List<SQLExprTableSource> tableSources) {\n        this.tableSources = tableSources;\n    }\n\n    public boolean isFull() {\n        return full;\n    }\n\n    public void setFull(boolean full) {\n        this.full = full;\n    }\n\n    public boolean isFreeze() {\n        return freeze;\n    }\n\n    public void setFreeze(boolean freeze) {\n        this.freeze = freeze;\n    }\n\n    public boolean isAnalyze() {\n        return analyze;\n    }\n\n    public void setAnalyze(boolean analyze) {\n        this.analyze = analyze;\n    }\n\n    public boolean isDisablePageSkipping() {\n        return disablePageSkipping;\n    }\n\n    public void setDisablePageSkipping(boolean disablePageSkipping) {\n        this.disablePageSkipping = disablePageSkipping;\n    }\n\n    public boolean isProcessToast() {\n        return processToast;\n    }\n\n    public void setProcessToast(boolean processToast) {\n        this.processToast = processToast;\n    }\n\n    public boolean isTruncate() {\n        return truncate;\n    }\n\n    public void setTruncate(boolean truncate) {\n        this.truncate = truncate;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PGASTVisitor) {\n            accept0((PGASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(PGASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tableSources);\n        }\n        visitor.endVisit(this);\n    }\n\n    public boolean isDeltaMerge() {\n        return deltaMerge;\n    }\n\n    public void setDeltaMerge(boolean deltaMerge) {\n        this.deltaMerge = deltaMerge;\n    }\n\n    public boolean isHdfsDirectory() {\n        return hdfsDirectory;\n    }\n\n    public void setHdfsDirectory(boolean hdfsDirectory) {\n        this.hdfsDirectory = hdfsDirectory;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.postgresql.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionByHash;\nimport com.alibaba.druid.sql.ast.SQLPartitionByList;\nimport com.alibaba.druid.sql.ast.SQLPartitionByRange;\nimport com.alibaba.druid.sql.ast.SQLPartitionOf;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGCreateTableParser extends SQLCreateTableParser {\n    public PGCreateTableParser(Lexer lexer) {\n        super(new PGExprParser(lexer));\n    }\n\n    public PGCreateTableParser(String sql) {\n        super(new PGExprParser(sql));\n    }\n\n    public PGCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        // For partition of/by for PG\n        for (int i = 0; i < 2; i++) {\n            if (lexer.token() == Token.PARTITION) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (Token.OF.equals(lexer.token())) {\n                    lexer.reset(mark);\n                    SQLPartitionOf partitionOf = parsePartitionOf();\n                    stmt.setPartitionOf(partitionOf);\n                } else if (Token.BY.equals(lexer.token())) {\n                    lexer.reset(mark);\n                    SQLPartitionBy partitionClause = parsePartitionBy();\n                    stmt.setPartitionBy(partitionClause);\n                }\n            }\n        }\n\n        if (lexer.nextIf(Token.WITH)) {\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, false);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.nextIf(Token.TABLESPACE)) {\n            stmt.setTablespace(\n                    this.exprParser.name()\n            );\n        }\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        lexer.nextToken();\n        accept(Token.BY);\n\n        if (lexer.identifierEquals(\"LIST\")) {\n            lexer.nextToken();\n            SQLPartitionByList list = new SQLPartitionByList();\n\n            if (lexer.token() == Token.LPAREN) {\n                list.setType(SQLPartitionByList.PartitionByListType.LIST_EXPRESSION);\n                lexer.nextToken();\n                for (; ; ) {\n                    list.addColumn(this.exprParser.expr());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                    } else {\n                        break;\n                    }\n                }\n                accept(Token.RPAREN);\n            } else {\n                acceptIdentifier(\"COLUMNS\");\n                list.setType(SQLPartitionByList.PartitionByListType.LIST_COLUMNS);\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    list.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n\n            return list;\n        } else if (lexer.identifierEquals(\"HASH\") || lexer.identifierEquals(\"UNI_HASH\")) {\n            SQLPartitionByHash hash = new SQLPartitionByHash();\n\n            if (lexer.identifierEquals(\"UNI_HASH\")) {\n                hash.setUnique(true);\n            }\n\n            lexer.nextToken();\n\n            if (lexer.token() == Token.KEY) {\n                lexer.nextToken();\n                hash.setKey(true);\n            }\n\n            accept(Token.LPAREN);\n            this.exprParser.exprList(hash.getColumns(), hash);\n            accept(Token.RPAREN);\n            return hash;\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            SQLPartitionByRange clause = partitionByRange();\n            return clause;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n    protected SQLPartitionByRange partitionByRange() {\n        SQLPartitionByRange clause = new SQLPartitionByRange();\n        if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                clause.addColumn(this.exprParser.expr());\n                accept(Token.RPAREN);\n            } else {\n                acceptIdentifier(\"COLUMNS\");\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    clause.addColumn(this.exprParser.name());\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n        } else {\n            SQLExpr expr = this.exprParser.expr();\n            if (lexer.identifierEquals(FnvHash.Constants.STARTWITH)) {\n                lexer.nextToken();\n                SQLExpr start = this.exprParser.primary();\n                acceptIdentifier(\"ENDWITH\");\n                SQLExpr end = this.exprParser.primary();\n                expr = new SQLBetweenExpr(expr, start, end);\n            }\n            clause.setInterval(expr);\n        }\n\n        return clause;\n    }\n\n    public SQLPartitionOf parsePartitionOf() {\n        lexer.nextToken();\n        accept(Token.OF);\n        SQLPartitionOf partitionOf = new SQLPartitionOf();\n        SQLName tableNameTmp = this.exprParser.name();\n        SQLExprTableSource sqlExprTableSource = new SQLExprTableSource(tableNameTmp);\n        partitionOf.setParentTable(sqlExprTableSource);\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            if (lexer.token() == Token.CONSTRAINT) {\n                lexer.nextToken();\n                SQLName constraintName = this.exprParser.name();\n                partitionOf.setConstraintName(constraintName);\n                accept(Token.CHECK);\n                SQLExpr checkExpr = this.exprParser.expr();\n                partitionOf.setCheckExpr(checkExpr);\n            } else {\n                SQLName columnName = this.exprParser.name();\n                partitionOf.setColumnName(columnName);\n                if (lexer.token() == Token.DEFAULT) {\n                    accept(Token.DEFAULT);\n                    SQLExpr defaultExpr = this.exprParser.primary();\n                    partitionOf.setDefaultExpr(defaultExpr);\n                }\n            }\n            accept(Token.RPAREN);\n        }\n        if (lexer.token() == Token.DEFAULT) {\n            accept(Token.DEFAULT);\n            partitionOf.setUseDefault(true);\n            return partitionOf;\n        }\n        accept(Token.FOR);\n        accept(Token.VALUES);\n        if (lexer.token() == Token.FROM) {\n            accept(Token.FROM);\n            accept(Token.LPAREN);\n            List<SQLExpr> sqlExprBetweens = new ArrayList<>();\n            this.exprParser.exprList(sqlExprBetweens, partitionOf);\n            partitionOf.setForValuesFrom(sqlExprBetweens);\n            accept(Token.RPAREN);\n            accept(Token.TO);\n            accept(Token.LPAREN);\n            List<SQLExpr> sqlExprAnds = new ArrayList<>();\n            this.exprParser.exprList(sqlExprAnds, partitionOf);\n            partitionOf.setForValuesTo(sqlExprAnds);\n            accept(Token.RPAREN);\n            return partitionOf;\n        } else if (lexer.token() == Token.IN) {\n            accept(Token.IN);\n            accept(Token.LPAREN);\n            List<SQLExpr> sqlExprBetweens = new ArrayList<>();\n            this.exprParser.exprList(sqlExprBetweens, partitionOf);\n            partitionOf.setForValuesIn(sqlExprBetweens);\n            accept(Token.RPAREN);\n            return partitionOf;\n        }\n        if (lexer.token() == Token.WITH) {\n            accept(Token.WITH);\n            accept(Token.LPAREN);\n            acceptIdentifier(\"MODULUS\");\n            SQLExpr modulus = this.exprParser.primary();\n            partitionOf.setForValuesModulus(modulus);\n            accept(Token.COMMA);\n            acceptIdentifier(\"REMAINDER\");\n            SQLExpr remainder = (SQLIntegerExpr) this.exprParser.primary();\n            partitionOf.setForValuesRemainder(remainder);\n            accept(Token.RPAREN);\n            return partitionOf;\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLArrayDataType;\nimport com.alibaba.druid.sql.ast.SQLCurrentTimeExpr;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.*;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class PGExprParser extends SQLExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\",\n                \"SUM\", \"ROW_NUMBER\", \"PERCENTILE_CONT\", \"PERCENTILE_DISC\", \"RANK\",\n                \"DENSE_RANK\", \"PERCENT_RANK\", \"CUME_DIST\"\n        };\n\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public PGExprParser(String sql) {\n        this(new PGLexer(sql));\n        this.lexer.nextToken();\n        this.dbType = DbType.postgresql;\n    }\n\n    public PGExprParser(String sql, SQLParserFeature... features) {\n        this(new PGLexer(sql, features));\n        this.lexer.nextToken();\n        this.dbType = DbType.postgresql;\n    }\n\n    public PGExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n        this.dbType = DbType.postgresql;\n    }\n\n    @Override\n    public SQLDataType parseDataType() {\n        if (lexer.token() == Token.TYPE) {\n            lexer.nextToken();\n        }\n        return super.parseDataType();\n    }\n\n    protected SQLDataType parseDataTypeRest(SQLDataType dataType) {\n        dataType = super.parseDataTypeRest(dataType);\n\n        if (lexer.token() == Token.LBRACKET) {\n            lexer.nextToken();\n            accept(Token.RBRACKET);\n            dataType = new SQLArrayDataType(dataType);\n        }\n\n        return dataType;\n    }\n\n    public PGSelectParser createSelectParser() {\n        return new PGSelectParser(this);\n    }\n\n    @Override\n    protected SQLExpr methodRestAllowIdentifierMethodSpecific(String methodName, long hash_lower, SQLMethodInvokeExpr methodInvokeExpr) {\n        if (hash_lower == FnvHash.Constants.INT4) {\n            PGTypeCastExpr castExpr = new PGTypeCastExpr();\n            castExpr.setExpr(this.expr());\n            castExpr.setDataType(new SQLDataTypeImpl(methodName));\n            accept(Token.RPAREN);\n            return castExpr;\n        } else if (hash_lower == FnvHash.Constants.VARBIT) {\n            PGTypeCastExpr castExpr = new PGTypeCastExpr();\n            SQLExpr len = this.primary();\n            castExpr.setDataType(new SQLDataTypeImpl(methodName, len));\n            accept(Token.RPAREN);\n            castExpr.setExpr(this.expr());\n            return castExpr;\n        }\n        return null;\n    }\n\n    @Override\n    protected SQLExpr primaryOn(SQLExpr sqlExpr) {\n        String methodName = lexer.stringVal();\n        lexer.nextToken();\n        if (lexer.token() == Token.LPAREN) {\n            sqlExpr = this.methodRest(new SQLIdentifierExpr(methodName), true);\n            return sqlExpr;\n        }\n        throw new ParserException(\"ERROR. \" + lexer.info());\n    }\n\n    @Override\n    protected SQLExpr primaryLiteralCharsRest(SQLExpr sqlExpr) {\n        Lexer.SavePoint savePoint = lexer.mark();\n        lexer.nextToken();\n        if (lexer.token() == Token.IDENTIFIER) {\n            String collate = lexer.stringVal();\n            if (collate.equalsIgnoreCase(\"collate\")) {\n                lexer.nextToken();\n                String collateValue = lexer.stringVal();\n                if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.LITERAL_ALIAS || lexer.token() == Token.LITERAL_CHARS) {\n                    ((SQLCharExpr) sqlExpr).setCollate(lexer.stringVal());\n                } else {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n            } else {\n                lexer.reset(savePoint);\n            }\n        } else {\n            lexer.reset(savePoint);\n        }\n        lexer.nextToken();\n        return sqlExpr;\n    }\n\n    @Override\n    protected void parseUpdateSetItemLbracket(SQLUpdateSetItem item) {\n        SQLExpr column = item.getColumn();\n        column = this.primaryRest(column);\n        item.setColumn(column);\n    }\n\n    @Override\n    public SQLBinaryOperator andRestGetAndOperator() {\n        return SQLBinaryOperator.PG_And;\n    }\n\n    @Override\n    protected SQLExpr relationalRestTilde(SQLExpr expr) {\n        lexer.nextToken();\n        SQLExpr rightExp = relational();\n        rightExp = relationalRest(rightExp);\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr relationalRestTildeStar(SQLExpr expr) {\n        lexer.nextToken();\n        SQLExpr rightExp = relational();\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match_Insensitive, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr relationalRestQues(SQLExpr expr) {\n        lexer.nextToken();\n        SQLExpr rightExp = bitOr();\n        rightExp = relationalRest(rightExp);\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.JSONContains, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr relationalRestBangTilde(SQLExpr expr) {\n        lexer.nextToken();\n        SQLExpr rightExp = relational();\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr relationalRestBangTildeStar(SQLExpr expr) {\n        lexer.nextToken();\n        SQLExpr rightExp = relational();\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match_POSIX_Regular_Match_Insensitive, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr relationalRestTildeEq(SQLExpr expr) {\n        lexer.nextToken();\n        SQLExpr rightExp = relational();\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.SAME_AS, rightExp, dbType);\n    }\n\n    @Override\n    protected SQLExpr relationalRestIdentifierSimilar(SQLExpr expr) {\n        lexer.nextToken();\n        accept(Token.TO);\n        SQLExpr rightExp = bitOr();\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.SIMILAR_TO, rightExp, dbType);\n    }\n\n    @Override\n    protected void parseDataTypeDouble(StringBuilder typeName) {\n        typeName.append(' ').append(lexer.stringVal());\n        lexer.nextToken();\n    }\n\n    @Override\n    protected SQLExpr parseSelectItemRest(String ident, long hash_lower) {\n        SQLExpr expr;\n        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)\n                && lexer.stringVal().charAt(0) != '`'\n        ) {\n            lexer.nextToken();\n            String collate = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLBinaryOpExpr binaryExpr = new SQLBinaryOpExpr(\n                    new SQLIdentifierExpr(ident),\n                    SQLBinaryOperator.COLLATE,\n                    new SQLIdentifierExpr(collate), dbType\n            );\n\n            expr = binaryExpr;\n        } else {\n            expr = super.parseSelectItemRest(ident, hash_lower);\n        }\n        return expr;\n    }\n\n    public SQLExpr primary() {\n        if (lexer.token() == Token.ARRAY) {\n            String ident = lexer.stringVal();\n            lexer.nextToken();\n\n            if (lexer.token() == Token.LPAREN) {\n                SQLIdentifierExpr array = new SQLIdentifierExpr(ident);\n                return this.methodRest(array, true);\n            } else {\n                SQLArrayExpr array = new SQLArrayExpr();\n                array.setExpr(new SQLIdentifierExpr(ident));\n                accept(Token.LBRACKET);\n                this.exprList(array.getValues(), array);\n                accept(Token.RBRACKET);\n                return primaryRest(array);\n            }\n        } else if (lexer.token() == Token.POUND) {\n            lexer.nextToken();\n            if (lexer.token() == Token.LBRACE) {\n                lexer.nextToken();\n                String varName = lexer.stringVal();\n                lexer.nextToken();\n                accept(Token.RBRACE);\n                SQLVariantRefExpr expr = new SQLVariantRefExpr(\"#{\" + varName + \"}\");\n                return primaryRest(expr);\n            } else {\n                SQLExpr value = this.primary();\n                SQLUnaryExpr expr = new SQLUnaryExpr(SQLUnaryOperator.Pound, value);\n                return primaryRest(expr);\n            }\n        } else if (lexer.token() == Token.VALUES) {\n            lexer.nextToken();\n\n            SQLValuesExpr values = new SQLValuesExpr();\n            for (; ; ) {\n                accept(Token.LPAREN);\n                SQLListExpr listExpr = new SQLListExpr();\n                exprList(listExpr.getItems(), listExpr);\n                accept(Token.RPAREN);\n\n                listExpr.setParent(values);\n\n                values.getValues().add(listExpr);\n                Lexer.SavePoint savePoint = lexer.mark();\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    if (lexer.token() != Token.LPAREN) {\n                        lexer.reset(savePoint);\n                        break;\n                    }\n                    continue;\n                }\n                break;\n            }\n            return values;\n        } else if (lexer.identifierEquals(FnvHash.Constants.CURRENT_TIMESTAMP)) {\n            SQLCurrentTimeExpr currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIMESTAMP);\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.AT)) {\n                lexer.nextToken();\n                acceptIdentifier(\"time\");\n                acceptIdentifier(\"zone\");\n                String timeZone = lexer.stringVal();\n                lexer.nextToken();\n                currentTimeExpr.setTimeZone(timeZone);\n            }\n            return primaryRest(currentTimeExpr);\n        } else if (lexer.token() == Token.WITH) {\n            SQLQueryExpr queryExpr = new SQLQueryExpr(\n                    createSelectParser()\n                            .select());\n            return queryExpr;\n        }\n\n        return super.primary();\n    }\n\n    @Override\n    protected SQLExpr parseInterval() {\n        accept(Token.INTERVAL);\n        SQLIntervalExpr intervalExpr = new SQLIntervalExpr();\n        if (lexer.token() != Token.LITERAL_CHARS\n                && lexer.token() != Token.LITERAL_INT\n                && lexer.token() != Token.VARIANT\n        ) {\n            return new SQLIdentifierExpr(\"INTERVAL\");\n        }\n        intervalExpr.setValue(new SQLCharExpr(lexer.stringVal()));\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.DAY)) {\n            lexer.nextToken();\n            intervalExpr.setUnit(SQLIntervalUnit.DAY);\n        } else if (lexer.identifierEquals(FnvHash.Constants.MONTH)) {\n            lexer.nextToken();\n            intervalExpr.setUnit(SQLIntervalUnit.MONTH);\n        } else if (lexer.identifierEquals(FnvHash.Constants.YEAR)) {\n            lexer.nextToken();\n            intervalExpr.setUnit(SQLIntervalUnit.YEAR);\n        } else if (lexer.identifierEquals(FnvHash.Constants.HOUR)) {\n            lexer.nextToken();\n            intervalExpr.setUnit(SQLIntervalUnit.HOUR);\n        } else if (lexer.identifierEquals(FnvHash.Constants.MINUTE)) {\n            lexer.nextToken();\n            intervalExpr.setUnit(SQLIntervalUnit.MINUTE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.SECOND)) {\n            lexer.nextToken();\n            intervalExpr.setUnit(SQLIntervalUnit.SECOND);\n        } else if (lexer.identifierEquals(FnvHash.Constants.WEEK)) {\n            lexer.nextToken();\n            intervalExpr.setUnit(SQLIntervalUnit.WEEK);\n        }\n\n        return intervalExpr;\n    }\n\n    private SQLExpr tryParseJsonPathOperator(SQLExpr expr) {\n        String name;\n        if (expr instanceof SQLIdentifierExpr) {\n            name = ((SQLIdentifierExpr) expr).getName();\n        } else if (expr instanceof SQLPropertyExpr) {\n            name = ((SQLPropertyExpr) expr).getName();\n        } else {\n            return null;\n        }\n\n        if (name.length() <= 1 || name.charAt(name.length() - 1) != '#') {\n            return null;\n        }\n\n        SQLBinaryOperator jsonPathOp = null;\n        if (lexer.token() == Token.GT) {\n            jsonPathOp = SQLBinaryOperator.PoundGt;\n        } else if (lexer.token() == Token.GTGT) {\n            jsonPathOp = SQLBinaryOperator.PoundGtGt;\n        }\n\n        if (jsonPathOp == null) {\n            return null;\n        }\n\n        if (expr instanceof SQLIdentifierExpr) {\n            ((SQLIdentifierExpr) expr).setName(name.substring(0, name.length() - 1));\n        } else {\n            ((SQLPropertyExpr) expr).setName(name.substring(0, name.length() - 1));\n        }\n        lexer.nextToken();\n        SQLExpr rightExp = primary();\n        return new SQLBinaryOpExpr(expr, jsonPathOp, rightExp, dbType);\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (lexer.nextIf(Token.COLONCOLON)) {\n            SQLDataType dataType = this.parseDataType();\n\n            PGTypeCastExpr castExpr = new PGTypeCastExpr();\n\n            castExpr.setExpr(expr);\n            castExpr.setDataType(dataType);\n\n            return primaryRest(castExpr);\n        }\n\n        if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            array.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            return primaryRest(array);\n        }\n\n        // Handle #> and #>> JSON path operators (lexer consumes # as part of identifier)\n        {\n            SQLExpr jsonPathResult = tryParseJsonPathOperator(expr);\n            if (jsonPathResult != null) {\n                return jsonPathResult;\n            }\n        }\n\n        if (expr.getClass() == SQLIdentifierExpr.class) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            String ident = identifierExpr.getName();\n            long hash = identifierExpr.nameHashCode64();\n\n            if (lexer.token() == Token.COMMA || lexer.token() == Token.RPAREN) {\n                return super.primaryRest(expr);\n            }\n\n            if (FnvHash.Constants.TIMESTAMP == hash) {\n                if (lexer.token() != Token.LITERAL_ALIAS //\n                        && lexer.token() != Token.LITERAL_CHARS //\n                        && lexer.token() != Token.WITH) {\n                    return super.primaryRest(\n                            new SQLIdentifierExpr(ident));\n                }\n\n                SQLTimestampExpr timestamp = new SQLTimestampExpr();\n\n                if (lexer.token() == Token.WITH) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n                    timestamp.setWithTimeZone(true);\n                }\n\n                String literal = lexer.stringVal();\n                timestamp.setValue(literal);\n                accept(Token.LITERAL_CHARS);\n\n                if (lexer.identifierEquals(\"AT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n\n                    String timezone = lexer.stringVal();\n                    timestamp.setTimeZone(timezone);\n                    accept(Token.LITERAL_CHARS);\n                }\n\n                return primaryRest(timestamp);\n            } else if (FnvHash.Constants.TIMESTAMPTZ == hash) {\n                if (lexer.token() != Token.LITERAL_ALIAS //\n                        && lexer.token() != Token.LITERAL_CHARS //\n                        && lexer.token() != Token.WITH) {\n                    return super.primaryRest(\n                            new SQLIdentifierExpr(ident));\n                }\n\n                SQLTimestampExpr timestamp = new SQLTimestampExpr();\n                timestamp.setWithTimeZone(true);\n\n                String literal = lexer.stringVal();\n                timestamp.setValue(literal);\n                accept(Token.LITERAL_CHARS);\n\n                if (lexer.identifierEquals(\"AT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TIME\");\n                    acceptIdentifier(\"ZONE\");\n\n                    String timezone = lexer.stringVal();\n                    timestamp.setTimeZone(timezone);\n                    accept(Token.LITERAL_CHARS);\n                }\n\n                return primaryRest(timestamp);\n            } else if (FnvHash.Constants.EXTRACT == hash) {\n                accept(Token.LPAREN);\n\n                PGExtractExpr extract = new PGExtractExpr();\n\n                String fieldName = lexer.stringVal();\n                PGDateField field = PGDateField.valueOf(fieldName.toUpperCase());\n                lexer.nextToken();\n\n                extract.setField(field);\n\n                accept(Token.FROM);\n                SQLExpr source = this.expr();\n\n                extract.setSource(source);\n\n                accept(Token.RPAREN);\n\n                return primaryRest(extract);\n            } else if (FnvHash.Constants.E == hash && lexer.token() == Token.LITERAL_CHARS) {\n                String str = lexer.stringVal();\n                lexer.nextToken();\n                PGCharExpr cstyleStr = new PGCharExpr();\n                cstyleStr.setText(str);\n                cstyleStr.setCSytle(true);\n                return primaryRest(cstyleStr);\n            } else if (FnvHash.Constants.POINT == hash) {\n                switch (lexer.token()) {\n                    case DOT:\n                    case EQ:\n                    case LTGT:\n                    case GT:\n                    case GTEQ:\n                    case LT:\n                    case LTEQ:\n                    case SUB:\n                    case PLUS:\n                    case SUBGT:\n                        break;\n                    default:\n                        SQLExpr value = this.primary();\n                        PGPointExpr point = new PGPointExpr();\n                        point.setValue(value);\n                        return primaryRest(point);\n                }\n            } else if (FnvHash.Constants.BOX == hash) {\n                SQLExpr value = this.primary();\n                PGBoxExpr box = new PGBoxExpr();\n                box.setValue(value);\n                return primaryRest(box);\n            } else if (FnvHash.Constants.MACADDR == hash) {\n                SQLExpr value = this.primary();\n                PGMacAddrExpr macaddr = new PGMacAddrExpr();\n                macaddr.setValue(value);\n                return primaryRest(macaddr);\n            } else if (FnvHash.Constants.INET == hash) {\n                SQLExpr value = this.primary();\n                PGInetExpr inet = new PGInetExpr();\n                inet.setValue(value);\n                return primaryRest(inet);\n            } else if (FnvHash.Constants.CIDR == hash) {\n                SQLExpr value = this.primary();\n                PGCidrExpr cidr = new PGCidrExpr();\n                cidr.setValue(value);\n                return primaryRest(cidr);\n            } else if (FnvHash.Constants.POLYGON == hash) {\n                SQLExpr value = this.primary();\n                PGPolygonExpr polygon = new PGPolygonExpr();\n                polygon.setValue(value);\n                return primaryRest(polygon);\n            } else if (FnvHash.Constants.CIRCLE == hash) {\n                SQLExpr value = this.primary();\n                PGCircleExpr circle = new PGCircleExpr();\n                circle.setValue(value);\n                return primaryRest(circle);\n            } else if (FnvHash.Constants.LSEG == hash) {\n                SQLExpr value = this.primary();\n                PGLineSegmentsExpr lseg = new PGLineSegmentsExpr();\n                lseg.setValue(value);\n                return primaryRest(lseg);\n            } else if (ident.equalsIgnoreCase(\"b\") && lexer.token() == Token.LITERAL_CHARS) {\n                String charValue = lexer.stringVal();\n                lexer.nextToken();\n                expr = new SQLBinaryExpr(charValue);\n\n                return primaryRest(expr);\n            }\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    @Override\n    protected String alias() {\n        String alias = super.alias();\n        if (alias != null) {\n            return alias;\n        }\n        // 某些关键字在alias时,不作为关键字,仍然是作用为别名\n        switch (lexer.token()) {\n            case INTERSECT:\n                // 具体可以参考SQLParser::alias()的方法实现\n                alias = lexer.stringVal();\n                lexer.nextToken();\n                return alias;\n            // TODO other cases\n            default:\n                break;\n        }\n        return alias;\n    }\n\n    @Override\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        column = super.parseColumnRest(column);\n        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)) {\n            lexer.nextToken();\n            if (lexer.token() == Token.BY) {\n                lexer.nextToken();\n                accept(Token.DEFAULT);\n                column.setGenerateByDefault(true);\n            } else {\n                acceptIdentifier(\"ALWAYS\");\n            }\n            accept(Token.AS);\n            if (lexer.token() == Token.IDENTITY) {\n                accept(Token.IDENTITY);\n                SQLColumnDefinition.Identity identity = parseIdentity();\n                column.setIdentity(identity);\n            } else {\n                SQLExpr expr = this.expr();\n                column.setGeneratedAlwaysAs(expr);\n            }\n        }\n        return column;\n    }\n\n    @Override\n    protected SQLColumnDefinition.Identity parseIdentity() {\n        SQLColumnDefinition.Identity identity = new SQLColumnDefinition.Identity();\n        if (lexer.token() == Token.LPAREN) {\n            accept(Token.LPAREN);\n            if (lexer.identifierEquals(FnvHash.Constants.INCREMENT)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setIncrement((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n                accept(Token.START);\n                accept(Token.WITH);\n                if (lexer.token() == Token.LITERAL_INT) {\n                    identity.setSeed((Integer) lexer.integerValue());\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"TODO \" + lexer.info());\n                }\n            }\n            accept(Token.RPAREN);\n        }\n\n        return identity;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.*;\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;\n\npublic class PGLexer extends Lexer {\n    public static final Keywords PG_KEYWORDS;\n    public static final DialectFeature PG_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    ScanVariableGreaterThan,\n                    SQLDateExpr,\n                    ParseStatementListWhen\n            ),\n            null\n    );\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"CASCADE\", Token.CASCADE);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"CURRENT\", Token.CURRENT);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"NEXT\", Token.NEXT);\n        map.put(\"NOWAIT\", Token.NOWAIT);\n        map.put(\"OF\", Token.OF);\n\n        map.put(\"OFFSET\", Token.OFFSET);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"RECURSIVE\", Token.RECURSIVE);\n        map.put(\"RESTART\", Token.RESTART);\n\n        map.put(\"RESTRICT\", Token.RESTRICT);\n        map.put(\"RETURNING\", Token.RETURNING);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"ROWS\", Token.ROWS);\n        map.put(\"SHARE\", Token.SHARE);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"START\", Token.START);\n\n        map.put(\"USING\", Token.USING);\n        map.put(\"WINDOW\", Token.WINDOW);\n\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"ARRAY\", Token.ARRAY);\n        map.put(\"IF\", Token.IF);\n        map.put(\"TYPE\", Token.TYPE);\n        map.put(\"ILIKE\", Token.ILIKE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"INTERVAL\", Token.INTERVAL);\n        map.put(\"LANGUAGE\", Token.LANGUAGE);\n\n        PG_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return PG_KEYWORDS;\n    }\n\n    public PGLexer(String input, SQLParserFeature... features) {\n        super(input, true);\n        this.keepComments = true;\n        dbType = DbType.postgresql;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    protected void scanString() {\n        mark = pos;\n        boolean hasSpecial = false;\n\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                putChar('\\\\');\n                switch (ch) {\n                    case '\\0':\n                        putChar('\\0');\n                        break;\n                    case '\\'':\n                        putChar('\\'');\n                        break;\n                    case '\"':\n                        putChar('\"');\n                        break;\n                    case 'b':\n                        putChar('b');\n                        break;\n                    case 'n':\n                        putChar('n');\n                        break;\n                    case 'r':\n                        putChar('r');\n                        break;\n                    case 't':\n                        putChar('t');\n                        break;\n                    case '\\\\':\n                        putChar('\\\\');\n                        break;\n                    case 'Z':\n                        putChar((char) 0x1A); // ctrl + Z\n                        break;\n                    default:\n                        putChar(ch);\n                        break;\n                }\n                scanChar();\n            }\n\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    public void scanSharp() {\n        scanChar();\n        if (ch == '>') {\n            scanChar();\n            if (ch == '>') {\n                scanChar();\n                token = Token.POUNDGTGT;\n            } else {\n                token = Token.POUNDGT;\n            }\n        } else {\n            token = Token.POUND;\n        }\n    }\n\n    protected void scanVariable_at() {\n        if (ch != '@') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n        char ch;\n\n        final char c1 = charAt(pos + 1);\n        if (c1 == '@') {\n            pos += 2;\n            token = Token.MONKEYS_AT_AT;\n            this.ch = charAt(++pos);\n            return;\n        } else if (c1 == '>') {\n            pos += 2;\n            token = Token.MONKEYS_AT_GT;\n            this.ch = charAt(++pos);\n            return;\n        }\n\n        for (; ; ) {\n            ch = charAt(++pos);\n\n            if (!isIdentifierChar(ch)) {\n                break;\n            }\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = addSymbol();\n        token = Token.VARIANT;\n    }\n\n    protected void nextTokenQues() {\n        if (ch == '?') {\n            scanChar();\n            if (ch == '|') {\n                scanChar();\n                token = Token.QUESQUESBAR;\n            } else {\n                token = Token.QUESQUES;\n            }\n        } else if (ch == '|') {\n            scanChar();\n            if (ch == '|') {\n                unscan();\n                token = Token.QUES;\n            } else {\n                token = Token.QUESBAR;\n            }\n        } else if (ch == '&') {\n            scanChar();\n            token = Token.QUESAMP;\n        } else {\n            token = Token.QUES;\n        }\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = PG_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.parser;\n\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGAttrExpr;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.*;\n\npublic class PGSQLStatementParser extends SQLStatementParser {\n    public static final String TIME_ZONE = \"TIME ZONE\";\n    public static final String TIME = \"TIME\";\n    public static final String LOCAL = \"LOCAL\";\n\n    public PGSQLStatementParser(PGExprParser parser) {\n        super(parser);\n    }\n\n    public PGSQLStatementParser(String sql) {\n        super(new PGExprParser(sql));\n    }\n\n    public PGSQLStatementParser(String sql, SQLParserFeature... features) {\n        super(new PGExprParser(sql, features));\n    }\n\n    public PGSQLStatementParser(Lexer lexer) {\n        super(new PGExprParser(lexer));\n    }\n\n    public PGSelectParser createSQLSelectParser() {\n        return new PGSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLUpdateStatement parseUpdateStatement() {\n        accept(Token.UPDATE);\n\n        PGUpdateStatement updateStatement = new PGUpdateStatement();\n\n        SQLSelectParser selectParser = this.exprParser.createSelectParser();\n        SQLTableSource tableSource = selectParser.parseTableSource();\n        updateStatement.setTableSource(tableSource);\n\n        parseUpdateSet(updateStatement);\n\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n            SQLTableSource from = selectParser.parseTableSource();\n            updateStatement.setFrom(from);\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            updateStatement.setWhere(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                updateStatement.getReturning().add(this.exprParser.expr());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        return updateStatement;\n    }\n\n    public PGInsertStatement parseInsert() {\n        PGInsertStatement stmt = new PGInsertStatement();\n\n        if (lexer.token() == Token.INSERT) {\n            lexer.nextToken();\n            accept(Token.INTO);\n\n            SQLName tableName = this.exprParser.name();\n            stmt.setTableName(tableName);\n\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.token() == Token.IDENTIFIER) {\n                stmt.setAlias(lexer.stringVal());\n                lexer.nextToken();\n            }\n\n        }\n\n        if (lexer.token() == Token.DEFAULT) {\n            lexer.nextToken();\n            accept(Token.VALUES);\n            stmt.setDefaultValues(true);\n        }\n\n        if (lexer.token() == (Token.LPAREN)) {\n            lexer.nextToken();\n            this.exprParser.exprList(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == (Token.VALUES)) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                accept(Token.LPAREN);\n                SQLInsertStatement.ValuesClause valuesCaluse = new SQLInsertStatement.ValuesClause();\n                this.exprParser.exprList(valuesCaluse.getValues(), valuesCaluse);\n                stmt.addValueCause(valuesCaluse);\n\n                accept(Token.RPAREN);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.WITH) {\n            PGSelectStatement nextWithQuery = (PGSelectStatement) this.parseWith();\n            stmt.setQuery(nextWithQuery.getSelect());\n        } else if (lexer.token() == Token.SELECT) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n            stmt.setQuery(queryExpr.getSubQuery());\n        }\n\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.CONFLICT)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    List<SQLExpr> onConflictTarget = new ArrayList<SQLExpr>();\n                    this.exprParser.exprList(onConflictTarget, stmt);\n                    stmt.setOnConflictTarget(onConflictTarget);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.token() == Token.ON) {\n                    lexer.nextToken();\n                    accept(Token.CONSTRAINT);\n                    SQLName constraintName = this.exprParser.name();\n                    stmt.setOnConflictConstraint(constraintName);\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = this.exprParser.expr();\n                    stmt.setOnConflictWhere(where);\n                }\n\n                if (lexer.token() == Token.DO) {\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.NOTHING)) {\n                        lexer.nextToken();\n                        stmt.setOnConflictDoNothing(true);\n                    } else {\n                        accept(Token.UPDATE);\n                        accept(Token.SET);\n\n                        for (; ; ) {\n                            SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n                            stmt.addConflicUpdateItem(item);\n\n                            if (lexer.token() != Token.COMMA) {\n                                break;\n                            }\n\n                            lexer.nextToken();\n                        }\n                        if (lexer.token() == Token.WHERE) {\n                            lexer.nextToken();\n                            SQLExpr where = this.exprParser.expr();\n                            stmt.setOnConflictUpdateWhere(where);\n                        }\n                    }\n                }\n            }\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n            SQLExpr returning = this.exprParser.expr();\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                SQLListExpr list = new SQLListExpr();\n                list.addItem(returning);\n\n                this.exprParser.exprList(list.getItems(), list);\n\n                returning = list;\n            }\n\n            stmt.setReturning(returning);\n        }\n        return stmt;\n    }\n\n    @Override\n    public PGCreateDatabaseStatement parseCreateDatabase() {\n        accept(CREATE);\n        accept(DATABASE);\n        PGCreateDatabaseStatement stmt = new PGCreateDatabaseStatement(dbType);\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            stmt.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        stmt.setName(this.exprParser.identifier());\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n            stmt.setHaveWith(true);\n        }\n\n        for (;;) {\n            if (lexer.token() == Token.SEMI || lexer.isEOF()) {\n                break;\n            }\n\n            boolean isAttr = lexer.identifierEquals(FnvHash.Constants.TEMPLATE) ||\n                             lexer.identifierEquals(FnvHash.Constants.OWNER);\n\n            if (isAttr) {\n                SQLIdentifierExpr attrName = this.exprParser.identifier();\n\n                PGAttrExpr attrExpr = new PGAttrExpr();\n                if (lexer.token() == EQ) {\n                    lexer.nextToken();\n                    attrExpr.setMode(PGAttrExpr.PGExprMode.EQ);\n                } else {\n                    attrExpr.setMode(PGAttrExpr.PGExprMode.EMPTY);\n                }\n\n                attrExpr.setName(attrName);\n                attrExpr.setValue(this.exprParser.identifier());\n                stmt.getStats().add(attrExpr);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public PGCreateSchemaStatement parseCreateSchema() {\n        accept(Token.CREATE);\n        accept(Token.SCHEMA);\n\n        PGCreateSchemaStatement stmt = new PGCreateSchemaStatement();\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n\n            stmt.setIfNotExists(true);\n        }\n\n        if (lexer.token() == Token.IDENTIFIER) {\n            if (lexer.identifierEquals(\"AUTHORIZATION\")) {\n                lexer.nextToken();\n                stmt.setAuthorization(true);\n\n                SQLIdentifierExpr userName = (SQLIdentifierExpr) this.exprParser.expr();\n                stmt.setUserName(userName);\n            } else {\n                stmt.setSchemaName(this.exprParser.name());\n\n                if (lexer.identifierEquals(\"AUTHORIZATION\")) {\n                    lexer.nextToken();\n                    stmt.setAuthorization(true);\n\n                    SQLIdentifierExpr userName = (SQLIdentifierExpr) this.exprParser.expr();\n                    stmt.setUserName(userName);\n                }\n            }\n        }\n\n        while (lexer.token() != SEMI && !lexer.isEOF()) {\n            if (lexer.token() == Token.CREATE) {\n                Lexer.SavePoint mark = lexer.markOut();\n                lexer.nextToken();\n                if (lexer.token() == Token.TABLE) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateTable());\n                    continue;\n                } else if (lexer.token() == VIEW) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateView());\n                    continue;\n                } else if (lexer.token() == INDEX) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateIndex());\n                    continue;\n                } else if (lexer.token() == SEQUENCE) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateSequence());\n                    continue;\n                } else if (lexer.token() == TRIGGER) {\n                    lexer.reset(mark);\n                    stmt.getCreateStatements().add(this.parseCreateTrigger());\n                    continue;\n                }\n            }\n\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterSchema() {\n        accept(Token.ALTER);\n        accept(Token.SCHEMA);\n\n        PGAlterSchemaStatement stmt = new PGAlterSchemaStatement();\n        stmt.setSchemaName(this.exprParser.name());\n\n        if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n            lexer.nextToken();\n            accept(Token.TO);\n            stmt.setNewName(this.exprParser.identifier());\n        } else if (lexer.identifierEquals(FnvHash.Constants.OWNER)) {\n            lexer.nextToken();\n            accept(Token.TO);\n            stmt.setNewOwner(this.exprParser.identifier());\n        }\n\n        return stmt;\n    }\n\n    //with force\n    @Override\n    public PGDropDatabaseStatement parseDropDatabaseOrSchema(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        PGDropDatabaseStatement stmt = new PGDropDatabaseStatement(getDbType());\n\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n            stmt.setUsingWith(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {\n            lexer.nextToken();\n            stmt.setForce(true);\n        }\n\n        return stmt;\n    }\n\n    public PGDropSchemaStatement parseDropSchema(boolean physical) {\n        PGDropSchemaStatement stmt = new PGDropSchemaStatement();\n\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setSchemaName(name);\n        stmt.getMultipleNames().add(name);\n\n        while (lexer.token() == COMMA) {\n            lexer.nextToken();\n            stmt.getMultipleNames().add(this.exprParser.name());\n        }\n\n        if (lexer.token() == Token.CASCADE) {\n            lexer.nextToken();\n            stmt.setCascade(true);\n        } else {\n            stmt.setCascade(false);\n        }\n        if (lexer.token() == Token.RESTRICT) {\n            lexer.nextToken();\n            stmt.setRestrict(true);\n        }\n\n        return stmt;\n    }\n\n    public PGDeleteStatement parseDeleteStatement() {\n        lexer.nextToken();\n        PGDeleteStatement deleteStatement = new PGDeleteStatement();\n\n        if (lexer.token() == (Token.FROM)) {\n            lexer.nextToken();\n        }\n        if (lexer.token() == (Token.ONLY)) {\n            lexer.nextToken();\n            deleteStatement.setOnly(true);\n        }\n\n        SQLName tableName = exprParser.name();\n\n        deleteStatement.setTableName(tableName);\n\n        if (lexer.token() == Token.AS) {\n            accept(Token.AS);\n        }\n        if (lexer.token() == Token.IDENTIFIER) {\n            deleteStatement.setAlias(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n\n            SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n            deleteStatement.setUsing(tableSource);\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.CURRENT) {\n                lexer.nextToken();\n                accept(Token.OF);\n                SQLName cursorName = this.exprParser.name();\n                SQLExpr where = new SQLCurrentOfCursorExpr(cursorName);\n                deleteStatement.setWhere(where);\n            } else {\n                SQLExpr where = this.exprParser.expr();\n                deleteStatement.setWhere(where);\n            }\n        }\n\n        if (lexer.token() == Token.RETURNING) {\n            lexer.nextToken();\n            accept(Token.STAR);\n            deleteStatement.setReturning(true);\n        }\n\n        return deleteStatement;\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        switch (lexer.token()) {\n            case BEGIN:\n            case START: {\n                PGStartTransactionStatement stmt = parseBegin();\n                statementList.add(stmt);\n                return true;\n            }\n            case END: {\n                PGEndTransactionStatement stmt = parseEnd();\n                statementList.add(stmt);\n                return true;\n            }\n            case WITH:\n                statementList.add(parseWith());\n                return true;\n            case DO:\n                PGDoStatement pgDoStatement = parseDo();\n                statementList.add(pgDoStatement);\n                return true;\n            default:\n                if (lexer.identifierEquals(FnvHash.Constants.CONNECT)) {\n                    SQLStatement stmt = parseConnectTo();\n                    statementList.add(stmt);\n                    return true;\n                }\n\n                break;\n        }\n\n        String strVal = lexer.stringVal();\n        if (strVal.equalsIgnoreCase(\"ANALYZE\")) {\n            PGAnalyzeStatement stmt = this.parseAnalyzeTable();\n            statementList.add(stmt);\n            return true;\n        }\n        if (strVal.equalsIgnoreCase(\"VACUUM\")) {\n            PGVacuumStatement stmt = this.parseVacuumTable();\n            statementList.add(stmt);\n            return true;\n        }\n        if (\"COPY\".equalsIgnoreCase(strVal)) {\n            statementList.add(parseCopy());\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public SQLStatement parseCreate() {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken(); // skip CREATE\n\n        if (lexer.identifierEquals(\"EXTENSION\")) {\n            return parseCreateExtension();\n        }\n\n        lexer.reset(mark);\n        return super.parseCreate();\n    }\n\n    protected PGCreateExtensionStatement parseCreateExtension() {\n        lexer.nextToken(); // skip EXTENSION\n\n        PGCreateExtensionStatement stmt = new PGCreateExtensionStatement();\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n        }\n\n        for (;;) {\n            if (lexer.token() == Token.SCHEMA || lexer.identifierEquals(\"SCHEMA\")) {\n                lexer.nextToken();\n                stmt.setSchema(this.exprParser.name());\n            } else if (lexer.identifierEquals(\"VERSION\")) {\n                lexer.nextToken();\n                stmt.setVersion(lexer.stringVal());\n                lexer.nextToken();\n            } else if (lexer.token() == Token.CASCADE) {\n                lexer.nextToken();\n                stmt.setCascade(true);\n            } else {\n                break;\n            }\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseCopy() {\n        lexer.nextToken(); // skip COPY\n\n        PGCopyStatement stmt = new PGCopyStatement();\n\n        // COPY (query) TO ...\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            SQLSelect query = createSQLSelectParser().select();\n            accept(Token.RPAREN);\n            stmt.setQuery(query);\n        } else {\n            SQLName tableName = this.exprParser.name();\n            stmt.setTable(new SQLExprTableSource(tableName));\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                this.exprParser.names(stmt.getColumns(), stmt);\n                accept(Token.RPAREN);\n            }\n        }\n\n        // FROM or TO\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n            parseCopyTarget(stmt);\n        } else if (lexer.token() == Token.TO) {\n            lexer.nextToken();\n            stmt.setDirectionTo(true);\n            parseCopyTarget(stmt);\n        }\n\n        // WITH ( options )\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                for (;;) {\n                    SQLAssignItem item = parseCopyOption();\n                    stmt.getOptions().add(item);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n        }\n\n        // Legacy options (without WITH)\n        while (lexer.token() == Token.IDENTIFIER) {\n            String optName = lexer.stringVal();\n            if (\"DELIMITER\".equalsIgnoreCase(optName)\n                || \"NULL\".equalsIgnoreCase(optName)\n                || \"CSV\".equalsIgnoreCase(optName)\n                || \"HEADER\".equalsIgnoreCase(optName)\n                || \"QUOTE\".equalsIgnoreCase(optName)\n                || \"ESCAPE\".equalsIgnoreCase(optName)\n                || \"ENCODING\".equalsIgnoreCase(optName)) {\n                SQLAssignItem item = parseCopyOption();\n                stmt.getOptions().add(item);\n            } else {\n                break;\n            }\n        }\n\n        // WHERE (COPY FROM only, PG 12+)\n        if (lexer.token() == Token.WHERE) {\n            lexer.nextToken();\n            stmt.setWhere(this.exprParser.expr());\n        }\n\n        return stmt;\n    }\n\n    private void parseCopyTarget(PGCopyStatement stmt) {\n        if (lexer.identifierEquals(\"STDIN\")) {\n            stmt.setTarget(new SQLIdentifierExpr(\"STDIN\"));\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"STDOUT\")) {\n            stmt.setTarget(new SQLIdentifierExpr(\"STDOUT\"));\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"PROGRAM\")) {\n            lexer.nextToken();\n            stmt.setProgram(true);\n            stmt.setTarget(this.exprParser.expr());\n        } else {\n            stmt.setTarget(this.exprParser.expr());\n        }\n    }\n\n    private SQLAssignItem parseCopyOption() {\n        SQLAssignItem item = new SQLAssignItem();\n        // Handle reserved keywords that can appear as COPY option names (e.g., NULL, DEFAULT)\n        if (lexer.token() == Token.NULL) {\n            item.setTarget(new SQLIdentifierExpr(\"NULL\"));\n            lexer.nextToken();\n        } else if (lexer.token() == Token.DEFAULT) {\n            item.setTarget(new SQLIdentifierExpr(\"DEFAULT\"));\n            lexer.nextToken();\n        } else {\n            item.setTarget(this.exprParser.name());\n        }\n        // Value is optional (e.g., some options are flags)\n        if (lexer.token() != Token.COMMA && lexer.token() != Token.RPAREN && lexer.token() != Token.EOF) {\n            item.setValue(this.exprParser.expr());\n        }\n        return item;\n    }\n\n    public PGDoStatement parseDo() {\n        PGDoStatement stmt = new PGDoStatement();\n        stmt.setDbType(dbType);\n\n        accept(Token.DO);\n        SQLStatement block = this.parseBlock();\n        stmt.setBlock(block);\n\n        return stmt;\n    }\n\n    public SQLBlockStatement parseBlock() {\n        SQLBlockStatement block = new SQLBlockStatement();\n        block.setDbType(dbType);\n\n        if (lexer.token() == Token.VARIANT) {\n            String dollarQuotedStr = lexer.stringVal();\n            if (!dollarQuotedStr.endsWith(\"$\")) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n            block.setIsDollarQuoted(true);\n            String dollarQuoteTagName = dollarQuotedStr.substring(1, dollarQuotedStr.length() - 1);\n            block.setDollarQuoteTagName(dollarQuoteTagName);\n            lexer.nextToken();\n        }\n\n        String labelName = null;\n        if (lexer.token() == Token.IDENTIFIER) {\n            labelName = lexer.stringVal();\n            lexer.nextToken();\n        }\n\n        if (labelName != null) {\n            block.setLabelName(labelName);\n        }\n\n        if (lexer.token() == Token.DECLARE) {\n            lexer.nextToken();\n        }\n        if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.CURSOR) {\n            parseParameters(block.getParameters(), block);\n            for (SQLParameter param : block.getParameters()) {\n                param.setParent(block);\n            }\n        }\n\n        accept(Token.BEGIN);\n        List<SQLStatement> statementList = block.getStatementList();\n        this.parseStatementList(statementList, -1, block);\n        if (lexer.token() != Token.END\n            && !statementList.isEmpty()\n            && (statementList.get(statementList.size() - 1) instanceof SQLCommitStatement\n            || statementList.get(statementList.size() - 1) instanceof SQLRollbackStatement)) {\n            block.setEndOfCommit(true);\n            return block;\n        }\n        accept(Token.END);\n\n        Token token = lexer.token();\n        if (token != Token.SEMI) {\n            // \"END label;\" or \"END label $$ LANGUAGE plpgsql;\"\n            if (token == Token.IDENTIFIER) {\n                String endLabel = lexer.stringVal();\n                block.setEndLabel(endLabel);\n                if (!block.getLabelName().equals(endLabel)) {\n                    printError(lexer.token());\n                }\n                acceptIdentifier(endLabel);\n            }\n            if (lexer.token() == Token.VARIANT) {\n                parseEndDollarQuote(block);\n            }\n        }\n        accept(Token.SEMI);\n\n        if (lexer.token() == Token.VARIANT) {\n            // \"$$ LANGUAGE plpgsql;\"\n            parseEndDollarQuote(block);\n            accept(Token.SEMI);\n        }\n        return block;\n    }\n\n    private void parseEndDollarQuote(SQLBlockStatement block) {\n        String dollarQuotedStr = lexer.stringVal();\n        if (!dollarQuotedStr.endsWith(\"$\")) {\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n        String dollarQuoteTagName = dollarQuotedStr.substring(1, dollarQuotedStr.length() - 1);\n        if (!block.getDollarQuoteTagName().equals(dollarQuoteTagName)) {\n            printError(lexer.token());\n        }\n        lexer.nextToken();\n        if (lexer.token() != Token.SEMI) {\n            accept(Token.LANGUAGE);\n            block.setLanguage(lexer.stringVal());\n            acceptIdentifier(block.getLanguage());\n        }\n    }\n\n    private void parseParameters(List<SQLParameter> parameters, SQLObject parent) {\n        for (;;) {\n            SQLParameter parameter = new SQLParameter();\n            parameter.setParent(parent);\n\n            SQLName name;\n            SQLDataType dataType = null;\n            name = this.exprParser.name();\n            if (lexer.token() == Token.IN) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.OUT) {\n                    lexer.nextToken();\n                    parameter.setParamType(SQLParameter.ParameterType.INOUT);\n                } else {\n                    parameter.setParamType(SQLParameter.ParameterType.IN);\n                }\n            } else if (lexer.token() == Token.OUT) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.IN) {\n                    lexer.nextToken();\n                    parameter.setParamType(SQLParameter.ParameterType.INOUT);\n                } else {\n                    parameter.setParamType(SQLParameter.ParameterType.OUT);\n                }\n            } else if (lexer.token() == Token.INOUT) {\n                lexer.nextToken();\n                parameter.setParamType(SQLParameter.ParameterType.INOUT);\n            }\n\n            dataType = this.exprParser.parseDataType(false);\n\n            if (lexer.token() == Token.NOT) {\n                lexer.nextToken();\n                accept(Token.NULL);\n                parameter.setNotNull(true);\n            }\n\n            if (lexer.token() == Token.COLONEQ || lexer.token() == Token.DEFAULT) {\n                lexer.nextToken();\n                parameter.setDefaultValue(this.exprParser.expr());\n            }\n\n            parameter.setName(name);\n            parameter.setDataType(dataType);\n\n            parameters.add(parameter);\n            Token token = lexer.token();\n            if (token == Token.COMMA || token == Token.SEMI || token == Token.IS) {\n                lexer.nextToken();\n            }\n\n            token = lexer.token();\n            if (token != Token.BEGIN\n                    && token != Token.RPAREN\n                    && token != Token.EOF\n                    && token != Token.FUNCTION\n                    && !lexer.identifierEquals(\"DETERMINISTIC\")) {\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    protected PGStartTransactionStatement parseBegin() {\n        PGStartTransactionStatement stmt = new PGStartTransactionStatement();\n        if (lexer.token() == Token.START) {\n            lexer.nextToken();\n            acceptIdentifier(\"TRANSACTION\");\n        } else {\n            accept(Token.BEGIN);\n            stmt.setUseBegin(true);\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public PGEndTransactionStatement parseEnd() {\n        PGEndTransactionStatement stmt = new PGEndTransactionStatement();\n        accept(Token.END);\n        return stmt;\n    }\n\n    public SQLStatement parseConnectTo() {\n        acceptIdentifier(\"CONNECT\");\n        accept(Token.TO);\n\n        PGConnectToStatement stmt = new PGConnectToStatement();\n        SQLName target = this.exprParser.name();\n        stmt.setTarget(target);\n\n        return stmt;\n    }\n\n    public PGSelectStatement parseSelect() {\n        PGSelectParser selectParser = createSQLSelectParser();\n        SQLSelect select = selectParser.select();\n        return new PGSelectStatement(select);\n    }\n\n    public SQLStatement parseWith() {\n        SQLWithSubqueryClause with = this.parseWithQuery();\n        // PGWithClause with = this.parseWithClause();\n        if (lexer.token() == Token.INSERT) {\n            PGInsertStatement stmt = this.parseInsert();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            PGSelectStatement stmt = this.parseSelect();\n            stmt.getSelect().setWithSubQuery(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.DELETE) {\n            PGDeleteStatement stmt = this.parseDeleteStatement();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        if (lexer.token() == Token.UPDATE) {\n            PGUpdateStatement stmt = (PGUpdateStatement) this.parseUpdateStatement();\n            stmt.setWith(with);\n            return stmt;\n        }\n\n        throw new ParserException(\"TODO. \" + lexer.info());\n    }\n\n    protected SQLAlterTableAlterColumn parseAlterColumn() {\n        if (lexer.token() == Token.COLUMN) {\n            lexer.nextToken();\n        }\n\n        SQLColumnDefinition column = this.exprParser.parseColumn();\n        column.setDbType(dbType);\n        SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn();\n        alterColumn.setColumn(column);\n\n        if (column.getDataType() == null && column.getConstraints().isEmpty()) {\n            if (lexer.token() == Token.SET) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setSetNotNull(true);\n                } else {\n                    accept(Token.DEFAULT);\n                    SQLExpr defaultValue = this.exprParser.expr();\n                    alterColumn.setSetDefault(defaultValue);\n                }\n            } else if (lexer.token() == Token.DROP) {\n                lexer.nextToken();\n                if (lexer.token() == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    alterColumn.setDropNotNull(true);\n                } else {\n                    accept(Token.DEFAULT);\n                    alterColumn.setDropDefault(true);\n                }\n            }\n        }\n        return alterColumn;\n    }\n\n    public SQLStatement parseShow() {\n        accept(Token.SHOW);\n        PGShowStatement stmt = new PGShowStatement(dbType);\n        switch (lexer.token()) {\n            case ALL:\n                stmt.setExpr(new SQLIdentifierExpr(Token.ALL.name()));\n                lexer.nextToken();\n                break;\n            default:\n                stmt.setExpr(this.exprParser.expr());\n                break;\n        }\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseCommit() {\n        SQLCommitStatement stmt = new SQLCommitStatement();\n        stmt.setDbType(this.dbType);\n        lexer.nextToken();\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseSet() {\n        accept(Token.SET);\n        Token token = lexer.token();\n        String range = \"\";\n\n        SQLSetStatement.Option option = null;\n        if (token == Token.SESSION) {\n            lexer.nextToken();\n            range = Token.SESSION.name();\n            option = SQLSetStatement.Option.SESSION;\n        } else if (token == Token.IDENTIFIER && LOCAL.equalsIgnoreCase(lexer.stringVal())) {\n            range = LOCAL;\n            option = SQLSetStatement.Option.LOCAL;\n            lexer.nextToken();\n        }\n\n        long hash = lexer.hashLCase();\n        String parameter = lexer.stringVal();\n        SQLExpr paramExpr;\n        List<SQLExpr> values = new ArrayList<SQLExpr>();\n        if (hash == FnvHash.Constants.TIME) {\n            lexer.nextToken();\n            acceptIdentifier(\"ZONE\");\n            paramExpr = new SQLIdentifierExpr(\"TIME ZONE\");\n            String value = lexer.stringVal();\n            if (lexer.token() == Token.IDENTIFIER) {\n                values.add(new SQLIdentifierExpr(value.toUpperCase()));\n            } else {\n                values.add(new SQLCharExpr(value));\n            }\n            lexer.nextToken();\n//            return new PGSetStatement(range, TIME_ZONE, exprs);\n        } else if (hash == FnvHash.Constants.ROLE) {\n            paramExpr = new SQLIdentifierExpr(parameter);\n            lexer.nextToken();\n            values.add(this.exprParser.primary());\n            lexer.nextToken();\n        } else if (\"schema\".equalsIgnoreCase(parameter) || \"names\".equalsIgnoreCase(parameter)) {\n            paramExpr = new SQLIdentifierExpr(parameter);\n            lexer.nextToken();\n            String value = lexer.stringVal();\n            values.add(new SQLCharExpr(value));\n            lexer.nextToken();\n        } else {\n            paramExpr = new SQLIdentifierExpr(parameter);\n            lexer.nextToken();\n\n            while (!lexer.isEOF()) {\n                lexer.nextToken();\n                if (lexer.token() == Token.LITERAL_CHARS) {\n                    values.add(new SQLCharExpr(lexer.stringVal()));\n                } else if (lexer.token() == Token.LITERAL_INT) {\n                    values.add(new SQLIdentifierExpr(lexer.numberString()));\n                } else if (lexer.identifierEquals(FnvHash.Constants.JSON_SET)\n                        || lexer.identifierEquals(FnvHash.Constants.JSONB_SET)) {\n                    SQLExpr json_set = this.exprParser.expr();\n                    values.add(json_set);\n                } else {\n                    values.add(new SQLIdentifierExpr(lexer.stringVal()));\n                }\n                // skip comma\n                lexer.nextToken();\n                if (lexer.token() == SEMI) {\n                    break;\n                }\n            }\n        }\n\n        // value | 'value' | DEFAULT\n\n        SQLExpr valueExpr;\n        if (values.size() == 1) {\n            valueExpr = values.get(0);\n        } else {\n            SQLListExpr listExpr = new SQLListExpr();\n            for (SQLExpr value : values) {\n                listExpr.addItem(value);\n            }\n            valueExpr = listExpr;\n        }\n        SQLSetStatement stmt = new SQLSetStatement(paramExpr, valueExpr, dbType);\n        stmt.setUseSet(true);\n        stmt.setOption(option);\n        return stmt;\n    }\n\n    public SQLCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n        SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(getDbType());\n        if (lexer.token() == Token.UNIQUE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"CLUSTERED\")) {\n                lexer.nextToken();\n                stmt.setType(\"UNIQUE CLUSTERED\");\n            } else {\n                stmt.setType(\"UNIQUE\");\n            }\n        } else if (lexer.identifierEquals(\"FULLTEXT\")) {\n            stmt.setType(\"FULLTEXT\");\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"NONCLUSTERED\")) {\n            stmt.setType(\"NONCLUSTERED\");\n            lexer.nextToken();\n        }\n\n        accept(Token.INDEX);\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CONCURRENTLY)) {\n            lexer.nextToken();\n            stmt.setConcurrently(true);\n        }\n\n        if (lexer.token() != Token.ON) {\n            stmt.setName(this.exprParser.name());\n        }\n\n        accept(Token.ON);\n\n        stmt.setTable(this.exprParser.name());\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n            String using = lexer.stringVal();\n            accept(Token.IDENTIFIER);\n            stmt.setUsing(using);\n        }\n\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            SQLSelectOrderByItem item;\n            item = this.exprParser.parseSelectOrderByItem();\n\n            if (lexer.identifierEquals(\"jsonb_path_ops\") && item.getExpr() instanceof SQLIdentifierExpr) {\n                String ident = ((SQLIdentifierExpr) item.getExpr()).getName() + \" \" + lexer.stringVal();\n                lexer.nextToken();\n                item.setExpr(new SQLIdentifierExpr(ident));\n            }\n\n            item.setParent(stmt);\n            stmt.addItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                String optionName = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n                accept(Token.EQ);\n                SQLExpr option = this.exprParser.expr();\n                option.setParent(stmt);\n\n                stmt.addOption(optionName, option);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.TABLESPACE) {\n            lexer.nextToken();\n            SQLName tablespace = this.exprParser.name();\n            stmt.setTablespace(tablespace);\n        }\n\n        return stmt;\n    }\n\n    public PGCreateTableParser getSQLCreateTableParser() {\n        return new PGCreateTableParser(this.exprParser);\n    }\n\n    public PGAnalyzeStatement parseAnalyzeTable() {\n        PGAnalyzeStatement stmt = new PGAnalyzeStatement(this.dbType);\n        acceptIdentifier(\"ANALYZE\");\n        Lexer.SavePoint mark = lexer.mark();\n        String strVal = lexer.stringVal();\n        for (; ; ) {\n            if (Token.SEMI.equals(lexer.token())) {\n                stmt.setAfterSemi(true);\n                return stmt;\n            }\n            if (Token.EOF.equals(lexer.token())) {\n                return stmt;\n            }\n            if (strVal.equalsIgnoreCase(\"VERBOSE\")) {\n                stmt.setVerbose(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"SKIP_LOCKED\")) {\n                stmt.setSkipLocked(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else {\n                lexer.reset(mark);\n                break;\n            }\n        }\n        List<SQLName> names = new ArrayList<SQLName>();\n        this.exprParser.names(names, stmt);\n\n        for (SQLName name : names) {\n            SQLExprTableSource sqlExprTableSource = new SQLExprTableSource(name);\n            sqlExprTableSource.setParent(stmt);\n            stmt.getTableSources().add(sqlExprTableSource);\n        }\n        return stmt;\n    }\n\n    public PGVacuumStatement parseVacuumTable() {\n        PGVacuumStatement stmt = new PGVacuumStatement(this.dbType);\n        acceptIdentifier(\"VACUUM\");\n        Lexer.SavePoint mark = lexer.mark();\n        String strVal = lexer.stringVal();\n        for (; ; ) {\n            if (Token.SEMI.equals(lexer.token())) {\n                stmt.setAfterSemi(true);\n                return stmt;\n            }\n            if (Token.EOF.equals(lexer.token())) {\n                return stmt;\n            }\n            if (strVal.equalsIgnoreCase(\"FULL\")) {\n                stmt.setFull(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"FREEZE\")) {\n                stmt.setFreeze(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"VERBOSE\")) {\n                stmt.setVerbose(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"ANALYZE\")) {\n                stmt.setAnalyze(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"DISABLE_PAGE_SKIPPING\")) {\n                stmt.setDisablePageSkipping(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"SKIP_LOCKED\")) {\n                stmt.setSkipLocked(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"PROCESS_TOAST\")) {\n                stmt.setProcessToast(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"TRUNCATE\")) {\n                stmt.setTruncate(true);\n                lexer.nextToken();\n                mark = lexer.mark();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"DELTAMERGE\")) { // gaussDb\n                stmt.setDeltaMerge(true);\n                lexer.nextToken();\n                mark = lexer.markOut();\n                strVal = lexer.stringVal();\n                continue;\n            } else if (strVal.equalsIgnoreCase(\"HDFSDIRECTORY\")) { // gaussDb\n                stmt.setHdfsDirectory(true);\n                lexer.nextToken();\n                mark = lexer.markOut();\n                strVal = lexer.stringVal();\n                continue;\n            } else {\n                lexer.reset(mark);\n                break;\n            }\n        }\n        List<SQLName> names = new ArrayList<SQLName>();\n        this.exprParser.names(names, stmt);\n        for (SQLName name : names) {\n            SQLExprTableSource sqlExprTableSource = new SQLExprTableSource(name);\n            sqlExprTableSource.setParent(stmt);\n            stmt.getTableSources().add(sqlExprTableSource);\n        }\n        return stmt;\n    }\n\n    public PGAlterDatabaseStatement alterDatabase() {\n        accept(Token.ALTER);\n        if (!lexer.nextIf(Token.SCHEMA)) {\n            accept(Token.DATABASE);\n        }\n\n        PGAlterDatabaseStatement stmt = new PGAlterDatabaseStatement(dbType);\n        stmt.setDatabaseName(this.exprParser.identifier());\n        if (\"RENAME\".equalsIgnoreCase(lexer.stringVal())) {\n            lexer.nextToken();\n            accept(Token.TO);\n            stmt.setRenameToName(this.exprParser.identifier());\n        }\n        if (\"OWNER\".equalsIgnoreCase(lexer.stringVal())) {\n            lexer.nextToken();\n            accept(Token.TO);\n            stmt.setOwnerToName(this.exprParser.identifier());\n        }\n        if (\"REFRESH\".equalsIgnoreCase(lexer.stringVal())) {\n            lexer.nextToken();\n            acceptIdentifier(\"COLLATION\");\n            acceptIdentifier(\"VERSION\");\n            stmt.setRefreshCollationVersion(true);\n        }\n        if (Token.SET.equals(lexer.token())) {\n            lexer.nextToken();\n            if (Token.TABLESPACE.equals(lexer.token())) {\n                lexer.nextToken();\n                stmt.setSetTableSpaceName(this.exprParser.identifier());\n            } else {\n                stmt.setSetParameterName(this.exprParser.identifier());\n                if (Token.TO.equals(lexer.token())) {\n                    lexer.nextToken();\n                    stmt.setSetParameterValue(this.exprParser.expr());\n                } else {\n                    accept(Token.EQ);\n                    stmt.setUseEquals(true);\n                    stmt.setSetParameterValue(this.exprParser.expr());\n                }\n            }\n        }\n        if (\"RESET\".equalsIgnoreCase(lexer.stringVal())) {\n            lexer.nextToken();\n            stmt.setResetParameterName(this.exprParser.identifier());\n        }\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n            stmt.setHaveWith(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ALLOW_CONNECTIONS)) {\n            lexer.nextToken();\n            Token valueToken = lexer.token();\n            if (valueToken == TRUE) {\n                lexer.nextToken();\n                stmt.setAllowConnections(true);\n            } else if (valueToken == FALSE) {\n                lexer.nextToken();\n                stmt.setAllowConnections(false);\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IS_TEMPLATE)) {\n            lexer.nextToken();\n            Token valueToken = lexer.token();\n            if (valueToken == TRUE) {\n                lexer.nextToken();\n                stmt.setSetTemplateMark(true);\n            } else if (valueToken == FALSE) {\n                lexer.nextToken();\n                stmt.setSetTemplateMark(false);\n            }\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseCreateUser() {\n        accept(Token.CREATE);\n        accept(Token.USER);\n        SQLCreateUserStatement stmt = new SQLCreateUserStatement();\n        stmt.setDbType(dbType);\n        stmt.setUser(this.exprParser.name());\n        if (lexer.token() == Token.WITH) {\n            accept(Token.WITH);\n            stmt.setPostgresqlWith(true);\n        }\n        if (lexer.identifierEquals(\"ENCRYPTED\")) {\n            stmt.setPostgresqlEncrypted(true);\n            lexer.nextToken();\n        }\n        if (lexer.identifierEquals(\"PASSWORD\")) {\n            lexer.nextToken();\n        }\n        stmt.setPassword(this.exprParser.primary());\n        return stmt;\n    }\n\n    @Override\n    protected boolean alterTableAfterNameRest(SQLAlterTableStatement stmt) {\n        if (lexer.identifierEquals(\"CHANGEOWNER\") && lexer.identifierEquals(\"OWNER\")) {\n            alterTableOwner(stmt);\n        } else {\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    protected void alterTableAlterComma() {\n        if (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n        }\n    }\n\n    @Override\n    public void parseAlterDropRest(SQLAlterTableStatement stmt, SQLAlterTableDropColumnItem item) {\n        item.getColumns().add(this.exprParser.name());\n\n        if (lexer.token() == Token.CASCADE) {\n            item.setCascade(true);\n            lexer.nextToken();\n        }\n        if (RESTRICT == lexer.token()) {\n            item.setRestrict(true);\n            lexer.nextToken();\n        }\n        stmt.addItem(item);\n\n        if (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLSizeExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoOption;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class PGSelectParser extends SQLSelectParser {\n    public PGSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public PGSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public PGSelectParser(String sql) {\n        this(new PGExprParser(sql));\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new PGExprParser(lexer);\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.VALUES) {\n            return valuesQuery(acceptUnion);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            if (select instanceof SQLSelectQueryBlock) {\n                ((SQLSelectQueryBlock) select).setParenthesized(true);\n            }\n            accept(Token.RPAREN);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        PGSelectQueryBlock queryBlock = new PGSelectQueryBlock();\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.DISTINCT) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                lexer.nextToken();\n\n                if (lexer.token() == Token.ON) {\n                    lexer.nextToken();\n\n                    for (; ; ) {\n                        SQLExpr expr = this.createExprParser().expr();\n                        queryBlock.getDistinctOn().add(expr);\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        } else {\n                            break;\n                        }\n                    }\n                }\n            } else if (lexer.token() == Token.ALL) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                lexer.nextToken();\n            }\n\n            parseSelectList(queryBlock);\n\n            if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.TEMPORARY) {\n                    lexer.nextToken();\n                    queryBlock.setIntoOption(IntoOption.TEMPORARY);\n                } else if (lexer.token() == Token.TEMP) {\n                    lexer.nextToken();\n                    queryBlock.setIntoOption(IntoOption.TEMP);\n                } else if (lexer.token() == Token.UNLOGGED) {\n                    lexer.nextToken();\n                    queryBlock.setIntoOption(IntoOption.UNLOGGED);\n                }\n\n                if (lexer.token() == Token.TABLE) {\n                    lexer.nextToken();\n                }\n\n                SQLExpr name = this.createExprParser().name();\n\n                queryBlock.setInto(new SQLExprTableSource(name));\n            }\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        if (lexer.token() == Token.WINDOW) {\n            this.parseWindow(queryBlock);\n        }\n\n        queryBlock.setOrderBy(this.createExprParser().parseOrderBy());\n\n        for (; ; ) {\n            if (lexer.token() == Token.LIMIT) {\n                SQLLimit limit = getOrInitLimit(queryBlock);\n\n                lexer.nextToken();\n                if (lexer.token() == Token.ALL) {\n                    limit.setRowCount(new SQLIdentifierExpr(\"ALL\"));\n                    lexer.nextToken();\n                } else {\n                    limit.setRowCount(expr());\n                }\n\n            } else if (lexer.token() == Token.OFFSET) {\n                SQLLimit limit = getOrInitLimit(queryBlock);\n\n                lexer.nextToken();\n                SQLExpr offset = expr();\n                limit.setOffset(offset);\n\n                if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) {\n                    lexer.nextToken();\n                }\n            } else {\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.FETCH) {\n            lexer.nextToken();\n            PGSelectQueryBlock.FetchClause fetch = new PGSelectQueryBlock.FetchClause();\n\n            if (lexer.token() == Token.FIRST) {\n                fetch.setOption(PGSelectQueryBlock.FetchClause.Option.FIRST);\n            } else if (lexer.token() == Token.NEXT) {\n                fetch.setOption(PGSelectQueryBlock.FetchClause.Option.NEXT);\n            } else {\n                throw new ParserException(\"expect 'FIRST' or 'NEXT'. \" + lexer.info());\n            }\n            lexer.nextToken();\n            SQLExpr count = expr();\n            fetch.setCount(count);\n\n            if (lexer.token() == Token.ROW || lexer.token() == Token.ROWS) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'ROW' or 'ROWS'. \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.ONLY) {\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'ONLY'. \" + lexer.info());\n            }\n\n            queryBlock.setFetch(fetch);\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n\n            PGSelectQueryBlock.ForClause forClause = new PGSelectQueryBlock.ForClause();\n\n            if (lexer.token() == Token.UPDATE) {\n                forClause.setOption(PGSelectQueryBlock.ForClause.Option.UPDATE);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.SHARE) {\n                forClause.setOption(PGSelectQueryBlock.ForClause.Option.SHARE);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"expect 'FIRST' or 'NEXT'. \" + lexer.info());\n            }\n\n            if (lexer.token() == Token.OF) {\n                for (; ; ) {\n                    SQLExpr expr = this.createExprParser().expr();\n                    forClause.getOf().add(expr);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else {\n                        break;\n                    }\n                }\n            }\n\n            if (lexer.token() == Token.NOWAIT) {\n                lexer.nextToken();\n                forClause.setNoWait(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SKIP)) {\n                lexer.nextToken();\n                acceptIdentifier(\"LOCKED\");\n                forClause.setSkipLocked(true);\n            }\n\n            queryBlock.setForClause(forClause);\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    private SQLLimit getOrInitLimit(SQLSelectQueryBlock queryBlock) {\n        SQLLimit limit = queryBlock.getLimit();\n        if (limit == null) {\n            limit = new SQLLimit();\n            queryBlock.setLimit(limit);\n        }\n        return limit;\n    }\n\n    @Override\n    public SQLTableSource parseTableSource(boolean forFrom) {\n        if (lexer.token() == Token.LATERAL || lexer.identifierEquals(FnvHash.Constants.LATERAL)) {\n            lexer.nextToken();\n            SQLTableSource lateralSource = parseLateralTableSource();\n            return parseTableSourceRest(lateralSource);\n        }\n        return super.parseTableSource(forFrom);\n    }\n\n    @Override\n    protected SQLTableSource parseLateralView(SQLTableSource tableSource) {\n        if (tableSource != null && \"LATERAL\".equalsIgnoreCase(tableSource.getAlias())) {\n            tableSource.setAlias(null);\n        }\n\n        if (lexer.token() == Token.VIEW) {\n            return super.parseLateralView(tableSource);\n        }\n\n        SQLTableSource lateralSource = parseLateralTableSource();\n\n        SQLJoinTableSource join = new SQLJoinTableSource();\n        join.setLeft(tableSource);\n        join.setRight(lateralSource);\n        join.setJoinType(SQLJoinTableSource.JoinType.COMMA);\n        return parseTableSourceRest(join);\n    }\n\n    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {\n        if (lexer.token() == Token.AS && tableSource instanceof SQLExprTableSource) {\n            lexer.nextToken();\n\n            String alias = null;\n            if (lexer.token() == Token.IDENTIFIER) {\n                alias = lexer.stringVal();\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;\n\n                PGFunctionTableSource functionTableSource = new PGFunctionTableSource(exprTableSource.getExpr());\n                if (alias != null) {\n                    functionTableSource.setAlias(alias);\n                }\n\n                lexer.nextToken();\n                parserParameters(functionTableSource.getParameters());\n                accept(Token.RPAREN);\n\n                return super.parseTableSourceRest(functionTableSource);\n            }\n            if (alias != null) {\n                tableSource.setAlias(alias);\n                return super.parseTableSourceRest(tableSource);\n            }\n        }\n\n        return this.parseTableSourceTableSample(tableSource);\n    }\n\n    public SQLTableSource parseTableSourceTableSample(SQLTableSource tableSource) {\n        if (lexer.identifierEquals(FnvHash.Constants.TABLESAMPLE) && tableSource instanceof SQLExprTableSource) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            SQLTableSampling sampling = new SQLTableSampling();\n            if (lexer.identifierEquals(FnvHash.Constants.BERNOULLI)) {\n                lexer.nextToken();\n                sampling.setBernoulli(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SYSTEM)) {\n                lexer.nextToken();\n                sampling.setSystem(true);\n            }\n\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.BUCKET)) {\n                    lexer.nextToken();\n                    SQLExpr bucket = this.exprParser.primary();\n                    sampling.setBucket(bucket);\n\n                    if (lexer.token() == Token.OUT) {\n                        lexer.nextToken();\n                        accept(Token.OF);\n                        SQLExpr outOf = this.exprParser.primary();\n                        sampling.setOutOf(outOf);\n                    }\n\n                    if (lexer.token() == Token.ON) {\n                        lexer.nextToken();\n                        SQLExpr on = this.exprParser.expr();\n                        sampling.setOn(on);\n                    }\n                }\n\n                if (lexer.token() == Token.LITERAL_INT || lexer.token() == Token.LITERAL_FLOAT) {\n                    SQLExpr val = this.exprParser.primary();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                        lexer.nextToken();\n                        sampling.setRows(val);\n                    } else if (lexer.token() == Token.RPAREN) {\n                        sampling.setRows(val);\n                    } else {\n                        acceptIdentifier(\"PERCENT\");\n                        sampling.setPercent(val);\n                    }\n                }\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    String strVal = lexer.stringVal();\n                    char first = strVal.charAt(0);\n                    char last = strVal.charAt(strVal.length() - 1);\n                    if (last >= 'a' && last <= 'z') {\n                        last -= 32; // to upper\n                    }\n\n                    boolean match = false;\n                    if ((first == '.' || (first >= '0' && first <= '9'))) {\n                        switch (last) {\n                            case 'B':\n                            case 'K':\n                            case 'M':\n                            case 'G':\n                            case 'T':\n                            case 'P':\n                                match = true;\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n                    SQLSizeExpr size = new SQLSizeExpr(strVal.substring(0, strVal.length() - 2), last);\n                    sampling.setByteLength(size);\n                    lexer.nextToken();\n                }\n\n                final SQLExprTableSource table = (SQLExprTableSource) tableSource;\n                table.setSampling(sampling);\n\n                accept(Token.RPAREN);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.USING)) {\n            return tableSource;\n        }\n        return super.parseTableSourceRest(tableSource);\n    }\n\n    private void parserParameters(List<SQLParameter> parameters) {\n        for (; ; ) {\n            SQLParameter parameter = new SQLParameter();\n\n            parameter.setName(this.exprParser.name());\n            parameter.setDataType(this.exprParser.parseDataType());\n\n            parameters.add(parameter);\n            if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) {\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    @Override\n    protected List<String> getReturningFunctions() {\n        return Arrays.asList(\"GENERATE_SERIES\", \"GENERATE_SUBSCRIPTS\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface PGASTVisitor extends SQLASTVisitor {\n    default void endVisit(PGSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(PGSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(PGSelectQueryBlock.FetchClause x) {\n    }\n\n    default boolean visit(PGSelectQueryBlock.FetchClause x) {\n        return true;\n    }\n\n    default void endVisit(PGSelectQueryBlock.ForClause x) {\n    }\n\n    default boolean visit(PGSelectQueryBlock.ForClause x) {\n        return true;\n    }\n\n    default void endVisit(PGDeleteStatement x) {\n    }\n\n    default boolean visit(PGDeleteStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGInsertStatement x) {\n    }\n\n    default boolean visit(PGInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGSelectStatement x) {\n        endVisit((SQLSelectStatement) x);\n    }\n\n    default boolean visit(PGSelectStatement x) {\n        return visit((SQLSelectStatement) x);\n    }\n\n    default void endVisit(PGUpdateStatement x) {\n    }\n\n    default boolean visit(PGUpdateStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGFunctionTableSource x) {\n    }\n\n    default boolean visit(PGFunctionTableSource x) {\n        return true;\n    }\n\n    default void endVisit(PGTypeCastExpr x) {\n    }\n\n    default boolean visit(PGTypeCastExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGExtractExpr x) {\n    }\n\n    default boolean visit(PGExtractExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGBoxExpr x) {\n    }\n\n    default boolean visit(PGBoxExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGAttrExpr x) {\n    }\n\n    default boolean visit(PGAttrExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGPointExpr x) {\n    }\n\n    default boolean visit(PGPointExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGMacAddrExpr x) {\n    }\n\n    default boolean visit(PGMacAddrExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGInetExpr x) {\n    }\n\n    default boolean visit(PGInetExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGCidrExpr x) {\n    }\n\n    default boolean visit(PGCidrExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGPolygonExpr x) {\n    }\n\n    default boolean visit(PGPolygonExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGCircleExpr x) {\n    }\n\n    default boolean visit(PGCircleExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGLineSegmentsExpr x) {\n    }\n\n    default boolean visit(PGLineSegmentsExpr x) {\n        return true;\n    }\n\n    default void endVisit(PGShowStatement x) {\n    }\n\n    default boolean visit(PGShowStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGStartTransactionStatement x) {\n    }\n\n    default boolean visit(PGStartTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGDoStatement x) {\n    }\n\n    default boolean visit(PGDoStatement x) {\n        return true;\n    }\n    default void endVisit(PGEndTransactionStatement x) {\n    }\n    default boolean visit(PGEndTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGConnectToStatement x) {\n    }\n\n    default boolean visit(PGConnectToStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGCreateSchemaStatement x) {\n    }\n\n    default boolean visit(PGCreateSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGDropSchemaStatement x) {\n    }\n\n    default boolean visit(PGDropDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGDropDatabaseStatement x) {\n    }\n\n    default boolean visit(PGDropSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGAlterSchemaStatement x) {\n    }\n\n    default boolean visit(PGAlterSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGCharExpr x) {\n        endVisit((SQLCharExpr) x);\n    }\n\n    default boolean visit(PGCharExpr x) {\n        return visit((SQLCharExpr) x);\n    }\n\n    default void endVisit(PGAnalyzeStatement x) {\n    }\n\n    default boolean visit(PGAnalyzeStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGVacuumStatement x) {\n    }\n\n    default boolean visit(PGVacuumStatement x) {\n        return true;\n    }\n\n    default boolean visit(PGCreateDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGCreateDatabaseStatement x) {\n    }\n\n    default void endVisit(PGAlterDatabaseStatement x) {\n    }\n\n    default boolean visit(PGAlterDatabaseStatement x) {\n        return true;\n    }\n\n    default boolean visit(PGCreateExtensionStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGCreateExtensionStatement x) {\n    }\n\n    default boolean visit(PGCopyStatement x) {\n        return true;\n    }\n\n    default void endVisit(PGCopyStatement x) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.visitor;\n\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVisitor {\n    @Override\n    public void endVisit(FetchClause x) {\n    }\n\n    @Override\n    public boolean visit(FetchClause x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(ForClause x) {\n    }\n\n    @Override\n    public boolean visit(ForClause x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGDeleteStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGDeleteStatement x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGInsertStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGInsertStatement x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGUpdateStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGUpdateStatement x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGFunctionTableSource x) {\n    }\n\n    @Override\n    public boolean visit(PGFunctionTableSource x) {\n        return true;\n    }\n\n    @Override\n    public boolean visit(PGTypeCastExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGTypeCastExpr x) {\n    }\n\n    @Override\n    public void endVisit(PGExtractExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGExtractExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGBoxExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGBoxExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGPointExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGPointExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGMacAddrExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGMacAddrExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGInetExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGInetExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGCidrExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGCidrExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGPolygonExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGPolygonExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGCircleExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGCircleExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGLineSegmentsExpr x) {\n    }\n\n    @Override\n    public boolean visit(PGLineSegmentsExpr x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGShowStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGShowStatement x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGStartTransactionStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGStartTransactionStatement x) {\n        return true;\n    }\n    @Override\n    public void endVisit(PGEndTransactionStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGEndTransactionStatement x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGConnectToStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGConnectToStatement x) {\n        return true;\n    }\n\n    @Override\n    public void endVisit(PGCreateSchemaStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGCreateSchemaStatement x) {\n        return false;\n    }\n\n    @Override\n    public void endVisit(PGDropSchemaStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGDropSchemaStatement x) {\n        return false;\n    }\n\n    @Override\n    public void endVisit(PGAlterSchemaStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGAlterSchemaStatement x) {\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGEvalVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class PGEvalVisitor extends PGASTVisitorAdapter implements SQLEvalVisitor {\n    private Map<String, Function> functions = new HashMap<String, Function>();\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public PGEvalVisitor() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public PGEvalVisitor(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLUnaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLBinaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGExportParameterVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLInListExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PGExportParameterVisitor extends PGOutputVisitor implements ExportParameterVisitor {\n    /**\n     * true= if require parameterized sql output\n     */\n    private final boolean requireParameterizedOutput;\n\n    public PGExportParameterVisitor(final List<Object> parameters,\n                                    final StringBuilder appender,\n                                    final boolean wantParameterizedOutput) {\n        super(appender, true);\n        this.parameters = parameters;\n        this.requireParameterizedOutput = wantParameterizedOutput;\n    }\n\n    public PGExportParameterVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public PGExportParameterVisitor(final List<Object> parameters) {\n        this(parameters, new StringBuilder(), false);\n    }\n\n    public PGExportParameterVisitor(final StringBuilder appender) {\n        this(new ArrayList<Object>(), appender, true);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public boolean visit(SQLSelectItem x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOrderBy x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelectGroupByClause x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getArguments());\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;\nimport com.alibaba.druid.sql.dialect.oracle.ast.clause.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleProcedureDataType;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.PG;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor, OracleASTVisitor {\n    public PGOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.postgresql);\n    }\n    public PGOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect) {\n        super(appender, dbType, dialect);\n    }\n\n    public PGOutputVisitor(StringBuilder appender, boolean parameterized) {\n    super(appender, DbType.postgresql, PG.DIALECT, parameterized);\n    }\n\n    public PGOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect, boolean parameterized) {\n        super(appender, dbType, dialect, parameterized);\n    }\n\n    @Override\n    public boolean visit(FetchClause x) {\n        print0(ucase ? \"FETCH \" : \"fetch \");\n        if (FetchClause.Option.FIRST.equals(x.getOption())) {\n            print0(ucase ? \"FIRST \" : \"first \");\n        } else if (FetchClause.Option.NEXT.equals(x.getOption())) {\n            print0(ucase ? \"NEXT \" : \"next \");\n        }\n        x.getCount().accept(this);\n        print0(ucase ? \" ROWS ONLY\" : \" rows only\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ForClause x) {\n        print0(ucase ? \"FOR \" : \"for \");\n        if (ForClause.Option.UPDATE.equals(x.getOption())) {\n            print0(ucase ? \"UPDATE\" : \"update\");\n        } else if (ForClause.Option.SHARE.equals(x.getOption())) {\n            print0(ucase ? \"SHARE\" : \"share\");\n        }\n\n        if (x.getOf().size() > 0) {\n            print(' ');\n            for (int i = 0; i < x.getOf().size(); ++i) {\n                if (i != 0) {\n                    println(\", \");\n                }\n                x.getOf().get(i).accept(this);\n            }\n        }\n\n        if (x.isNoWait()) {\n            print0(ucase ? \" NOWAIT\" : \" nowait\");\n        } else if (x.isSkipLocked()) {\n            print0(ucase ? \" SKIP LOCKED\" : \" skip locked\");\n        }\n\n        return false;\n    }\n\n    public boolean visit(PGSelectQueryBlock x) {\n        if ((!isParameterized()) && isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        boolean bracket = x.isParenthesized();\n        if (bracket) {\n            if (x.getParent() instanceof SQLSelect && x.getParent().getParent() instanceof SQLSubqueryTableSource) {\n                bracket = false;\n            }\n        }\n        if (bracket) {\n            print('(');\n        }\n\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n\n            List<SQLExpr> distinctOn = x.getDistinctOn();\n            if (distinctOn != null && distinctOn.size() > 0) {\n                print0(ucase ? \"ON \" : \"on \");\n\n                if (distinctOn.size() == 1 && distinctOn.get(0) instanceof SQLListExpr) {\n                    printExpr(distinctOn.get(0));\n                    print(' ');\n                } else {\n                    print0(\"(\");\n                    printAndAccept(distinctOn, \", \");\n                    print0(\") \");\n                }\n            }\n        }\n\n        printSelectList(x.getSelectList());\n\n        if (x.getInto() != null) {\n            println();\n            if (x.getIntoOption() != null) {\n                print0(x.getIntoOption().name());\n                print(' ');\n            }\n\n            print0(ucase ? \"INTO \" : \"into \");\n            x.getInto().accept(this);\n        }\n\n        printFrom(x);\n        printWhere(x);\n        printGroupBy(x);\n        printWindow(x);\n        printOrderBy(x);\n        printLimit(x);\n\n        if (x.getFetch() != null) {\n            println();\n            x.getFetch().accept(this);\n        }\n\n        if (x.getForClause() != null) {\n            println();\n            x.getForClause().accept(this);\n        }\n\n        if (bracket) {\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTruncateStatement x) {\n        print0(ucase ? \"TRUNCATE TABLE \" : \"truncate table \");\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY \" : \"only \");\n        }\n\n        printlnAndAccept(x.getTableSources(), \",\");\n\n        if (x.getRestartIdentity() != null) {\n            if (x.getRestartIdentity().booleanValue()) {\n                print0(ucase ? \" RESTART IDENTITY\" : \" restart identity\");\n            } else {\n                print0(ucase ? \" CONTINUE IDENTITY\" : \" continue identity\");\n            }\n        }\n\n        if (x.getCascade() != null) {\n            if (x.getCascade().booleanValue()) {\n                print0(ucase ? \" CASCADE\" : \" cascade\");\n            } else {\n                print0(ucase ? \" RESTRICT\" : \" restrict\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGDeleteStatement x) {\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"DELETE FROM \" : \"delete from \");\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY \" : \"only \");\n        }\n\n        printTableSourceExpr(x.getTableName());\n\n        if (x.getAlias() != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            print0(x.getAlias());\n        }\n\n        SQLTableSource using = x.getUsing();\n        if (using != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            using.accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            this.indentCount++;\n            x.getWhere().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.isReturning()) {\n            println();\n            print0(ucase ? \"RETURNING *\" : \"returning *\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGInsertStatement x) {\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"INSERT INTO \" : \"insert into \");\n\n        x.getTableSource().accept(this);\n\n        printInsertColumns(x.getColumns());\n\n        printValuesOrQuery(x);\n\n        printOnConflict(x);\n\n        printReturning(x);\n        return false;\n    }\n\n    protected void printReturning(PGInsertStatement x) {\n        if (x.getReturning() != null) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            x.getReturning().accept(this);\n        }\n    }\n\n    protected void printValuesOrQuery(PGInsertStatement x) {\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            printlnAndAccept(x.getValuesList(), \",\");\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n    }\n\n    protected void printOnConflict(PGInsertStatement x) {\n        List<SQLExpr> onConflictTarget = x.getOnConflictTarget();\n        List<SQLUpdateSetItem> onConflictUpdateSetItems = x.getOnConflictUpdateSetItems();\n        boolean onConflictDoNothing = x.isOnConflictDoNothing();\n\n        if (onConflictDoNothing\n                || (onConflictTarget != null && onConflictTarget.size() > 0)\n                || (onConflictUpdateSetItems != null && onConflictUpdateSetItems.size() > 0)) {\n            println();\n            print0(ucase ? \"ON CONFLICT\" : \"on conflict\");\n\n            if ((onConflictTarget != null && onConflictTarget.size() > 0)) {\n                print0(\" (\");\n                printAndAccept(onConflictTarget, \", \");\n                print(')');\n            }\n\n            SQLName onConflictConstraint = x.getOnConflictConstraint();\n            if (onConflictConstraint != null) {\n                print0(ucase ? \" ON CONSTRAINT \" : \" on constraint \");\n                printExpr(onConflictConstraint);\n            }\n\n            SQLExpr onConflictWhere = x.getOnConflictWhere();\n            if (onConflictWhere != null) {\n                print0(ucase ? \" WHERE \" : \" where \");\n                printExpr(onConflictWhere);\n            }\n\n            if (onConflictDoNothing) {\n                print0(ucase ? \" DO NOTHING\" : \" do nothing\");\n            } else if ((onConflictUpdateSetItems != null && onConflictUpdateSetItems.size() > 0)) {\n                print0(ucase ? \" DO UPDATE SET \" : \" do update set \");\n                printAndAccept(onConflictUpdateSetItems, \", \");\n                SQLExpr onConflictUpdateWhere = x.getOnConflictUpdateWhere();\n                if (onConflictUpdateWhere != null) {\n                    print0(ucase ? \" WHERE \" : \" where \");\n                    printExpr(onConflictUpdateWhere);\n                }\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(PGSelectStatement x) {\n        return visit((SQLSelectStatement) x);\n    }\n\n    @Override\n    public boolean visit(PGUpdateStatement x) {\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY \" : \"only \");\n        }\n\n        printTableSource(x.getTableSource());\n\n        println();\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLUpdateSetItem item = x.getItems().get(i);\n            visit(item);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from != null) {\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n            printTableSource(from);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            indentCount++;\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where);\n            indentCount--;\n        }\n\n        List<SQLExpr> returning = x.getReturning();\n        if (returning.size() > 0) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            printAndAccept(returning, \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGFunctionTableSource x) {\n        x.getExpr().accept(this);\n\n        String alias = x.getAlias();\n        List<SQLParameter> parameters = x.getParameters();\n        if (alias != null || !x.getParameters().isEmpty()) {\n            print0(ucase ? \" AS\" : \" as\");\n        }\n\n        if (alias != null) {\n            print(' ');\n            print0(alias);\n        }\n\n        if (!parameters.isEmpty()) {\n            incrementIndent();\n            println();\n            print('(');\n            printAndAccept(parameters, \", \");\n            print(')');\n            decrementIndent();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGTypeCastExpr x) {\n        SQLExpr expr = x.getExpr();\n        SQLDataType dataType = x.getDataType();\n\n        if (dataType.nameHashCode64() == FnvHash.Constants.VARBIT) {\n            dataType.accept(this);\n            print(' ');\n            printExpr(expr);\n            return false;\n        }\n\n        if (expr != null) {\n            if (expr instanceof SQLBinaryOpExpr) {\n                expr.accept(this);\n            } else if (expr instanceof PGTypeCastExpr && dataType.getArguments().isEmpty()) {\n                dataType.accept(this);\n                print('(');\n                visit((PGTypeCastExpr) expr);\n                print(')');\n                return false;\n            } else {\n                expr.accept(this);\n            }\n        }\n        print0(\"::\");\n        dataType.accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGExtractExpr x) {\n        print0(ucase ? \"EXTRACT(\" : \"extract(\");\n        print0(x.getField().name());\n        print0(ucase ? \" FROM \" : \" from \");\n        x.getSource().accept(this);\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGAttrExpr x) {\n        int curLen = this.appender.length();\n        if (curLen > 0) {\n            char c = this.appender.charAt(curLen - 1);\n            if (!(c == ' ' || c == '\\t' || c == '\\n' || c == '\\r')) {\n                this.appender.append(\" \");\n            }\n        }\n\n        x.getName().accept(this);\n        if (x.getMode() == PGAttrExpr.PGExprMode.EQ) {\n            print0(\" = \");\n        } else {\n            print0(\" \");\n        }\n\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGBoxExpr x) {\n        print0(ucase ? \"BOX \" : \"box \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGPointExpr x) {\n        print0(ucase ? \"POINT \" : \"point \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGMacAddrExpr x) {\n        print0(\"macaddr \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGInetExpr x) {\n        print0(\"inet \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGCidrExpr x) {\n        print0(\"cidr \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGPolygonExpr x) {\n        print0(\"polygon \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGCircleExpr x) {\n        print0(\"circle \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGLineSegmentsExpr x) {\n        print0(\"lseg \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBinaryExpr x) {\n        print0(ucase ? \"B'\" : \"b'\");\n        print0(x.getText());\n        print('\\'');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGShowStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLLimit x) {\n        if (x.getRowCount() != null) {\n            print0(ucase ? \"LIMIT \" : \"limit \");\n            x.getRowCount().accept(this);\n        }\n        if (x.getOffset() != null) {\n            if (x.getRowCount() != null) {\n                print0(ucase ? \" OFFSET \" : \" offset \");\n            } else {\n                print0(ucase ? \"OFFSET \" : \"offset \");\n            }\n            x.getOffset().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGStartTransactionStatement x) {\n        if (x.isUseBegin()) {\n            print0(ucase ? \"BEGIN\" : \"begin\");\n            return false;\n        }\n        print0(ucase ? \"START TRANSACTION\" : \"start transaction\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGDoStatement x) {\n        print0(ucase ? \"DO \" : \"do \");\n        x.getBlock().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBlockStatement x) {\n        if (x.isDollarQuoted()) {\n            print(x.getDollarQuoteTagName() == null ? \"$$\" : \"$\" + x.getDollarQuoteTagName() + \"$\");\n            println();\n        }\n\n        if (x.getLabelName() != null) {\n            print0(x.getLabelName());\n            println();\n        }\n\n        if (!x.getParameters().isEmpty()) {\n            this.indentCount++;\n            if (x.getParent() instanceof SQLCreateProcedureStatement) {\n                SQLCreateProcedureStatement procedureStatement = (SQLCreateProcedureStatement) x.getParent();\n                if (procedureStatement.isCreate()) {\n                    printIndent();\n                }\n            }\n            if (!(x.getParent() instanceof SQLCreateProcedureStatement\n                    || x.getParent() instanceof SQLCreateFunctionStatement\n                    || x.getParent() instanceof OracleFunctionDataType\n                    || x.getParent() instanceof OracleProcedureDataType)\n            ) {\n                print0(ucase ? \"DECLARE\" : \"declare\");\n                println();\n            }\n\n            for (int i = 0, size = x.getParameters().size(); i < size; ++i) {\n                if (i != 0) {\n                    println();\n                }\n                SQLParameter param = x.getParameters().get(i);\n                param.accept(this);\n                print(';');\n            }\n\n            this.indentCount--;\n            println();\n        }\n        if (x.isHaveBeginEnd()) {\n            print0(ucase ? \"BEGIN\" : \"begin\");\n        }\n        this.indentCount++;\n\n        for (int i = 0, size = x.getStatementList().size(); i < size; ++i) {\n            println();\n            SQLStatement stmt = x.getStatementList().get(i);\n            stmt.accept(this);\n        }\n        this.indentCount--;\n\n        SQLStatement exception = x.getException();\n        if (exception != null) {\n            println();\n            exception.accept(this);\n        }\n\n        println();\n        if (x.isHaveBeginEnd()) {\n            // END [label];\n            if (x.getEndLabel() != null) {\n                print0(ucase ? \"END \" : \"end \");\n                print0(x.getEndLabel());\n                print(';');\n            } else {\n                print0(ucase ? \"END;\" : \"end;\");\n            }\n\n            if (x.isDollarQuoted()) {\n                println();\n                print(x.getDollarQuoteTagName() == null ? \"$$\" : \"$\" + x.getDollarQuoteTagName() + \"$\");\n                if (x.getLanguage() != null) {\n                    print0(\" LANGUAGE \" + x.getLanguage());\n                }\n                print(';');\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGEndTransactionStatement x) {\n        print0(ucase ? \"END\" : \"end\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGConnectToStatement x) {\n        print0(ucase ? \"CONNECT TO \" : \"connect to \");\n        x.getTarget().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGCreateDatabaseStatement x) {\n        printUcase(\"CREATE DATABASE \");\n\n        if (x.getName() != null) {\n            x.getName().accept(this);\n        }\n\n        if (x.isHaveWith()) {\n            printUcase(\" WITH\");\n        }\n\n        for (PGAttrExpr attrExpr : x.getStats()) {\n            attrExpr.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGDropDatabaseStatement x) {\n        print0(ucase ? \"DROP DATABASE \" : \"drop database \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.isForce()) {\n            if (x.isUsingWith()) {\n                print0(ucase ? \" WITH\" : \" with\");\n            }\n            print0(ucase ? \" FORCE\" : \" force\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGCreateSchemaStatement x) {\n        printUcase(\"CREATE SCHEMA \");\n        if (x.isIfNotExists()) {\n            printUcase(\"IF NOT EXISTS \");\n        }\n\n        if (x.getSchemaName() != null) {\n            x.getSchemaName().accept(this);\n        }\n        if (x.isAuthorization()) {\n            printUcase(\"AUTHORIZATION \");\n            x.getUserName().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGCreateExtensionStatement x) {\n        print0(ucase ? \"CREATE EXTENSION \" : \"create extension \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.getSchema() != null) {\n            print0(ucase ? \" SCHEMA \" : \" schema \");\n            x.getSchema().accept(this);\n        }\n\n        if (x.getVersion() != null) {\n            print0(ucase ? \" VERSION \" : \" version \");\n            print0(\"'\");\n            print0(x.getVersion());\n            print0(\"'\");\n        }\n\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGCopyStatement x) {\n        print0(ucase ? \"COPY \" : \"copy \");\n\n        if (x.getQuery() != null) {\n            print('(');\n            x.getQuery().accept(this);\n            print(')');\n        } else if (x.getTable() != null) {\n            x.getTable().accept(this);\n            if (!x.getColumns().isEmpty()) {\n                print('(');\n                printAndAccept(x.getColumns(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.isDirectionTo()) {\n            print0(ucase ? \" TO \" : \" to \");\n        } else {\n            print0(ucase ? \" FROM \" : \" from \");\n        }\n\n        if (x.isProgram()) {\n            print0(ucase ? \"PROGRAM \" : \"program \");\n        }\n\n        if (x.getTarget() != null) {\n            x.getTarget().accept(this);\n        }\n\n        if (!x.getOptions().isEmpty()) {\n            print0(ucase ? \" WITH (\" : \" with (\");\n            printAndAccept(x.getOptions(), \", \");\n            print(')');\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGDropSchemaStatement x) {\n        printUcase(\"DROP SCHEMA \");\n        if (x.isIfExists()) {\n            printUcase(\"IF EXISTS \");\n        }\n\n        List<SQLName> multipleName = x.getMultipleNames();\n        for (int i = 0; i < multipleName.size(); i++) {\n            if (i > 0) {\n                printUcase(\", \");\n            }\n            multipleName.get(i).accept(this);\n        }\n\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n        if (x.isRestrict()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGAlterSchemaStatement x) {\n        printUcase(\"ALTER SCHEMA \");\n        x.getSchemaName().accept(this);\n\n        if (x.getNewName() != null) {\n            print0(\" RENAME TO \");\n            x.getNewName().accept(this);\n        } else if (x.getNewOwner() != null) {\n            print0(\" OWNER TO \");\n            x.getNewOwner().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSetStatement x) {\n        if (x.isUseSet()) {\n            print0(ucase ? \"SET \" : \"set \");\n        }\n\n        SQLSetStatement.Option option = x.getOption();\n        if (option != null) {\n            print(option.name());\n            print(' ');\n        }\n\n        printAndAccept(x.getItems(), \", \");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAssignItem x) {\n        if (!(x.getParent() instanceof SQLSetStatement)) {\n            return super.visit(x);\n        }\n\n        x.getTarget().accept(this);\n        SQLExpr value = x.getValue();\n        boolean needSpace = false;\n        if (x.getTarget() instanceof SQLIdentifierExpr) {\n            String name = ((SQLIdentifierExpr) x.getTarget()).getName();\n            needSpace = \"TIME ZONE\".equalsIgnoreCase(name) || \"schema\".equalsIgnoreCase(name) || \"names\".equalsIgnoreCase(name);\n        }\n        if (needSpace) {\n            print(' ');\n        } else {\n            if (!((SQLSetStatement) x.getParent()).isUseSet()) {\n                print0(\" := \");\n            } else if (value instanceof SQLPropertyExpr\n                && ((SQLPropertyExpr) value).getOwner() instanceof SQLVariantRefExpr) {\n                print0(\" := \");\n            } else {\n                print0(\" TO \");\n            }\n        }\n\n        if (value instanceof SQLListExpr) {\n            SQLListExpr listExpr = (SQLListExpr) value;\n            printAndAccept(listExpr.getItems(), \", \");\n        } else {\n            value.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateUserStatement x) {\n        print0(ucase ? \"CREATE USER \" : \"create user \");\n        x.getUser().accept(this);\n        if (x.isPostgresqlWith()) {\n            print0(ucase ? \" WITH \" : \" with \");\n        }\n        if (x.isPostgresqlEncrypted()) {\n            print0(ucase ? \" ENCRYPTED \" : \" encrypted \");\n        }\n        print0(ucase ? \" PASSWORD \" : \" password \");\n\n        SQLExpr password = x.getPassword();\n\n        if (password instanceof SQLIdentifierExpr) {\n            print('\\'');\n            password.accept(this);\n            print('\\'');\n        } else {\n            password.accept(this);\n        }\n        return false;\n    }\n\n    protected void printGrantPrivileges(SQLGrantStatement x) {\n        List<SQLPrivilegeItem> privileges = x.getPrivileges();\n        int i = 0;\n        for (SQLPrivilegeItem privilege : privileges) {\n            if (i != 0) {\n                print(\", \");\n            }\n\n            SQLExpr action = privilege.getAction();\n            if (action instanceof SQLIdentifierExpr) {\n                String name = ((SQLIdentifierExpr) action).getName();\n                if (\"RESOURCE\".equalsIgnoreCase(name)) {\n                    continue;\n                }\n            }\n\n            privilege.accept(this);\n            i++;\n        }\n    }\n\n    public boolean visit(SQLGrantStatement x) {\n        if (x.getResource() == null) {\n            print(\"ALTER ROLE \");\n\n            printAndAccept(x.getUsers(), \",\");\n\n            print(' ');\n            Set<SQLIdentifierExpr> pgPrivilegs = new LinkedHashSet<SQLIdentifierExpr>();\n            for (SQLPrivilegeItem privilege : x.getPrivileges()) {\n                SQLExpr action = privilege.getAction();\n                if (action instanceof SQLIdentifierExpr) {\n                    String name = ((SQLIdentifierExpr) action).getName();\n                    if (name.equalsIgnoreCase(\"CONNECT\")) {\n                        pgPrivilegs.add(new SQLIdentifierExpr(\"LOGIN\"));\n                    }\n                    if (name.toLowerCase().startsWith(\"create \")) {\n                        pgPrivilegs.add(new SQLIdentifierExpr(\"CREATEDB\"));\n                    }\n                }\n            }\n            int i = 0;\n            for (SQLExpr privilege : pgPrivilegs) {\n                if (i != 0) {\n                    print(' ');\n                }\n                privilege.accept(this);\n                i++;\n            }\n            return false;\n        }\n\n        return super.visit(x);\n    }\n    /** **************************************************************************/\n    // for oracle to postsql\n\n    /**\n     *\n     **************************************************************************/\n\n    public boolean visit(OracleSysdateExpr x) {\n        print0(ucase ? \"CURRENT_TIMESTAMP\" : \"CURRENT_TIMESTAMP\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExceptionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExceptionStatement.Item x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleArgumentExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSetTransactionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExplainStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableDropPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableTruncatePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.TableSpaceItem x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.UpdateIndexesClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition.NestedTablePartitionSpec x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableSplitPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableModify x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateIndexStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleForStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleFileSpecification x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceAddDataFile x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTablespaceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExitStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleContinueStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRaiseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateDatabaseDbLinkStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDropDbLinkStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalYear x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleDataTypeIntervalDay x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleUsingIndexClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLobStorageClause x) {\n        return false;\n    }\n\n    public boolean visit(OracleSelectTableReference x) {\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY (\" : \"only (\");\n            printTableSourceExpr(x.getExpr());\n\n            if (x.getPartition() != null) {\n                print(' ');\n                x.getPartition().accept(this);\n            }\n\n            print(')');\n        } else {\n            printTableSourceExpr(x.getExpr());\n\n            if (x.getPartition() != null) {\n                print(' ');\n                x.getPartition().accept(this);\n            }\n        }\n\n        if (x.getHints().size() > 0) {\n            this.printHints(x.getHints());\n        }\n\n        if (x.getSampleClause() != null) {\n            print(' ');\n            x.getSampleClause().accept(this);\n        }\n\n        if (x.getPivot() != null) {\n            println();\n            x.getPivot().accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        printAlias(x.getAlias());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PartitionExtensionClause x) {\n        return false;\n    }\n\n    private void printHints(List<SQLHint> hints) {\n        if (hints.size() > 0) {\n            print0(\"/*+ \");\n            printAndAccept(hints, \", \");\n            print0(\" */\");\n        }\n    }\n\n    public boolean visit(OracleIntervalExpr x) {\n        if (x.getValue() instanceof SQLLiteralExpr || x.getValue() instanceof SQLVariantRefExpr) {\n            print0(ucase ? \"INTERVAL \" : \"interval \");\n        }\n        x.getValue().accept(this);\n        print(' ');\n\n        print0(x.getType().name());\n\n        if (x.getPrecision() != null) {\n            print('(');\n            printExpr(x.getPrecision());\n            if (x.getFactionalSecondsPrecision() != null) {\n                print0(\", \");\n                print(x.getFactionalSecondsPrecision().intValue());\n            }\n            print(')');\n        }\n\n        if (x.getToType() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            print0(x.getToType().name());\n            if (x.getToFactionalSecondsPrecision() != null) {\n                print('(');\n                printExpr(x.getToFactionalSecondsPrecision());\n                print(')');\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleOuterExpr x) {\n        x.getExpr().accept(this);\n        print0(\"(+)\");\n        return false;\n    }\n\n    public boolean visit(OracleBinaryFloatExpr x) {\n        if (x != null && x.getValue() != null) {\n            print0(x.getValue().toString());\n            print('F');\n        }\n        return false;\n    }\n\n    public boolean visit(OracleBinaryDoubleExpr x) {\n        if (x != null && x.getValue() != null) {\n            print0(x.getValue().toString());\n            print('D');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleIsSetExpr x) {\n        x.getNestedTable().accept(this);\n        print0(ucase ? \" IS A SET\" : \" is a set\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ReturnRowsClause x) {\n        if (x.isAll()) {\n            print0(ucase ? \"RETURN ALL ROWS\" : \"return all rows\");\n        } else {\n            print0(ucase ? \"RETURN UPDATED ROWS\" : \"return updated rows\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.MainModelClause x) {\n        if (x.getMainModelName() != null) {\n            print0(ucase ? \" MAIN \" : \" main \");\n            x.getMainModelName().accept(this);\n        }\n\n        println();\n        x.getModelColumnClause().accept(this);\n\n        for (ModelClause.CellReferenceOption opt : x.getCellReferenceOptions()) {\n            println();\n            print0(opt.name);\n        }\n\n        println();\n        x.getModelRulesClause().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ModelColumnClause x) {\n        if (x.getQueryPartitionClause() != null) {\n            x.getQueryPartitionClause().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"DIMENSION BY (\" : \"dimension by (\");\n        printAndAccept(x.getDimensionByColumns(), \", \");\n        print(')');\n\n        println();\n        print0(ucase ? \"MEASURES (\" : \"measures (\");\n        printAndAccept(x.getMeasuresColumns(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.QueryPartitionClause x) {\n        print0(ucase ? \"PARTITION BY (\" : \"partition by (\");\n        printAndAccept(x.getExprList(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ModelColumn x) {\n        x.getExpr().accept(this);\n        if (x.getAlias() != null) {\n            print(' ');\n            print0(x.getAlias());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.ModelRulesClause x) {\n        if (x.getOptions().size() > 0) {\n            print0(ucase ? \"RULES\" : \"rules\");\n            for (ModelClause.ModelRuleOption opt : x.getOptions()) {\n                print(' ');\n                print0(opt.name);\n            }\n        }\n\n        if (x.getIterate() != null) {\n            print0(ucase ? \" ITERATE (\" : \" iterate (\");\n            x.getIterate().accept(this);\n            print(')');\n\n            if (x.getUntil() != null) {\n                print0(ucase ? \" UNTIL (\" : \" until (\");\n                x.getUntil().accept(this);\n                print(')');\n            }\n        }\n\n        print0(\" (\");\n        printAndAccept(x.getCellAssignmentItems(), \", \");\n        print(')');\n        return false;\n\n    }\n\n    @Override\n    public boolean visit(ModelClause.CellAssignmentItem x) {\n        if (x.getOption() != null) {\n            print0(x.getOption().name);\n            print(' ');\n        }\n\n        x.getCellAssignment().accept(this);\n\n        if (x.getOrderBy() != null) {\n            print(' ');\n            x.getOrderBy().accept(this);\n        }\n\n        print0(\" = \");\n        x.getExpr().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause.CellAssignment x) {\n        x.getMeasureColumn().accept(this);\n        print0(\"[\");\n        printAndAccept(x.getConditions(), \", \");\n        print0(\"]\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(ModelClause x) {\n        print0(ucase ? \"MODEL\" : \"model\");\n\n        this.indentCount++;\n        for (ModelClause.CellReferenceOption opt : x.getCellReferenceOptions()) {\n            print(' ');\n            print0(opt.name);\n        }\n\n        if (x.getReturnRowsClause() != null) {\n            print(' ');\n            x.getReturnRowsClause().accept(this);\n        }\n\n        for (ModelClause.ReferenceModelClause item : x.getReferenceModelClauses()) {\n            print(' ');\n            item.accept(this);\n        }\n\n        x.getMainModel().accept(this);\n        this.indentCount--;\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleReturningClause x) {\n        print0(ucase ? \"RETURNING \" : \"returning \");\n        printAndAccept(x.getItems(), \", \");\n        print0(ucase ? \" INTO \" : \" into \");\n        printAndAccept(x.getValues(), \", \");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleInsertStatement x) {\n        //visit((SQLInsertStatement) x);\n\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        printInsertColumns(x.getColumns());\n\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            x.getValues().accept(this);\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        if (x.getReturning() != null) {\n            println();\n            x.getReturning().accept(this);\n        }\n\n        if (x.getErrorLogging() != null) {\n            println();\n            x.getErrorLogging().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement.InsertIntoClause x) {\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        if (x.getColumns().size() > 0) {\n            this.indentCount++;\n            println();\n            print('(');\n            for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        println();\n                    }\n                    print0(\", \");\n                }\n                x.getColumns().get(i).accept(this);\n            }\n            print(')');\n            this.indentCount--;\n        }\n\n        if (x.getValues() != null) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            x.getValues().accept(this);\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement x) {\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        if (x.getHints().size() > 0) {\n            this.printHints(x.getHints());\n        }\n\n        if (x.getOption() != null) {\n            print0(x.getOption().name());\n            print(' ');\n        }\n\n        for (int i = 0, size = x.getEntries().size(); i < size; ++i) {\n            this.indentCount++;\n            println();\n            x.getEntries().get(i).accept(this);\n            this.indentCount--;\n        }\n\n        println();\n        x.getSubQuery().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement.ConditionalInsertClause x) {\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n\n            OracleMultiInsertStatement.ConditionalInsertClauseItem item = x.getItems().get(i);\n\n            item.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            print0(ucase ? \"ELSE\" : \"else\");\n            this.indentCount++;\n            println();\n            x.getElseItem().accept(this);\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleMultiInsertStatement.ConditionalInsertClauseItem x) {\n        print0(ucase ? \"WHEN \" : \"when \");\n        x.getWhen().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n        println();\n        x.getThen().accept(this);\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectQueryBlock x) {\n        if (isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        if (x.getHintsSize() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == x.getDistionOption()) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        }\n\n        printSelectList(x.getSelectList());\n\n        if (x.getInto() != null) {\n            println();\n            print0(ucase ? \"INTO \" : \"into \");\n            x.getInto().accept(this);\n        }\n\n        println();\n        print0(ucase ? \"FROM \" : \"from \");\n        if (x.getFrom() != null) {\n            if (x.getCommentsAfterFrom() != null) {\n                printAfterComments(x.getCommentsAfterFrom());\n                println();\n            }\n            x.getFrom().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            x.getWhere().accept(this);\n        }\n\n        printHierarchical(x);\n\n        if (x.getGroupBy() != null) {\n            println();\n            x.getGroupBy().accept(this);\n        }\n\n        if (x.getModelClause() != null) {\n            println();\n            x.getModelClause().accept(this);\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            orderBy.accept(this);\n        }\n\n        printFetchFirst(x);\n\n        if (x.isForUpdate()) {\n            println();\n            print0(ucase ? \"FOR UPDATE\" : \"for update\");\n            if (x.getForUpdateOfSize() > 0) {\n                print(\" OF \");\n                printAndAccept(x.getForUpdateOf(), \", \");\n            }\n\n            if (x.isNoWait()) {\n                print0(ucase ? \" NOWAIT\" : \" nowait\");\n            } else if (x.isSkipLocked()) {\n                print0(ucase ? \" SKIP LOCKED\" : \" skip locked\");\n            } else if (x.getWaitTime() != null) {\n                print0(ucase ? \" WAIT \" : \" wait \");\n                x.getWaitTime().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLockTableStatement x) {\n        print0(ucase ? \"LOCK TABLE \" : \"lock table \");\n        x.getTable().accept(this);\n        print0(ucase ? \" IN \" : \" in \");\n        print0(x.getLockMode().toString());\n        print0(ucase ? \" MODE \" : \" mode \");\n        if (x.isNoWait()) {\n            print0(ucase ? \"NOWAIT\" : \"nowait\");\n        } else if (x.getWait() != null) {\n            print0(ucase ? \"WAIT \" : \"wait \");\n            x.getWait().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSessionStatement x) {\n        print0(ucase ? \"ALTER SESSION SET \" : \"alter session set \");\n        printAndAccept(x.getItems(), \", \");\n        return false;\n    }\n\n    public boolean visit(OracleRangeExpr x) {\n        x.getLowBound().accept(this);\n        print0(\"..\");\n        x.getUpBound().accept(this);\n        return false;\n    }\n\n    public boolean visit(OracleCheck x) {\n        visit((SQLCheck) x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSupplementalIdKey x) {\n        print0(ucase ? \"SUPPLEMENTAL LOG DATA (\" : \"supplemental log data (\");\n\n        int count = 0;\n\n        if (x.isAll()) {\n            print0(ucase ? \"ALL\" : \"all\");\n            count++;\n        }\n\n        if (x.isPrimaryKey()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"PRIMARY KEY\" : \"primary key\");\n            count++;\n        }\n\n        if (x.isUnique()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"UNIQUE\" : \"unique\");\n            count++;\n        }\n\n        if (x.isUniqueIndex()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"UNIQUE INDEX\" : \"unique index\");\n            count++;\n        }\n\n        if (x.isForeignKey()) {\n            if (count != 0) {\n                print0(\", \");\n            }\n            print0(ucase ? \"FOREIGN KEY\" : \"foreign key\");\n            count++;\n        }\n\n        print0(ucase ? \") COLUMNS\" : \") columns\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSupplementalLogGrp x) {\n        print0(ucase ? \"SUPPLEMENTAL LOG GROUP \" : \"supplemental log group \");\n        x.getGroup().accept(this);\n        print0(\" (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n        if (x.isAlways()) {\n            print0(ucase ? \" ALWAYS\" : \" always\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement.Organization x) {\n        String type = x.getType();\n\n        print0(ucase ? \"ORGANIZATION \" : \"organization \");\n        print0(ucase ? type : type.toLowerCase());\n\n        printOracleSegmentAttributes(x);\n\n        if (x.getPctthreshold() != null) {\n            println();\n            print0(ucase ? \"PCTTHRESHOLD \" : \"pctthreshold \");\n            print(x.getPctfree());\n        }\n\n        if (\"EXTERNAL\".equalsIgnoreCase(type)) {\n            print0(\" (\");\n\n            this.indentCount++;\n            if (x.getExternalType() != null) {\n                println();\n                print0(ucase ? \"TYPE \" : \"type \");\n                x.getExternalType().accept(this);\n            }\n\n            if (x.getExternalDirectory() != null) {\n                println();\n                print0(ucase ? \"DEFAULT DIRECTORY \" : \"default directory \");\n                x.getExternalDirectory().accept(this);\n            }\n\n            if (x.getExternalDirectoryRecordFormat() != null) {\n                println();\n                this.indentCount++;\n                print0(ucase ? \"ACCESS PARAMETERS (\" : \"access parameters (\");\n                x.getExternalDirectoryRecordFormat().accept(this);\n                this.indentCount--;\n                println();\n                print(')');\n            }\n\n            if (x.getExternalDirectoryLocation().size() > 0) {\n                println();\n                print0(ucase ? \"LOCATION (\" : \" location(\");\n                printAndAccept(x.getExternalDirectoryLocation(), \", \");\n                print(')');\n            }\n\n            this.indentCount--;\n            println();\n            print(')');\n\n            if (x.getExternalRejectLimit() != null) {\n                println();\n                print0(ucase ? \"REJECT LIMIT \" : \"reject limit \");\n                x.getExternalRejectLimit().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement.OIDIndex x) {\n        print0(ucase ? \"OIDINDEX\" : \"oidindex\");\n\n        if (x.getName() != null) {\n            print(' ');\n            x.getName().accept(this);\n        }\n        print(\" (\");\n        this.indentCount++;\n        printOracleSegmentAttributes(x);\n        this.indentCount--;\n        println();\n        print(\")\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreatePackageStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE PACKAGE \" : \"create or replace procedure \");\n        } else {\n            print0(ucase ? \"CREATE PACKAGE \" : \"create procedure \");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \"BODY \" : \"body \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.isBody()) {\n            println();\n            print0(ucase ? \"BEGIN\" : \"begin\");\n        }\n\n        this.indentCount++;\n\n        List<SQLStatement> statements = x.getStatements();\n        for (int i = 0, size = statements.size(); i < size; ++i) {\n            println();\n            SQLStatement stmt = statements.get(i);\n            stmt.accept(this);\n        }\n\n        this.indentCount--;\n\n        if (x.isBody() || statements.size() > 0) {\n            println();\n            print0(ucase ? \"END \" : \"end \");\n            x.getName().accept(this);\n            print(';');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleExecuteImmediateStatement x) {\n        print0(ucase ? \"EXECUTE IMMEDIATE \" : \"execute immediate \");\n        x.getDynamicSql().accept(this);\n\n        List<SQLExpr> into = x.getInto();\n        if (into.size() > 0) {\n            print0(ucase ? \" INTO \" : \" into \");\n            printAndAccept(into, \", \");\n        }\n\n        List<SQLArgument> using = x.getArguments();\n        if (using.size() > 0) {\n            print0(ucase ? \" USING \" : \" using \");\n            printAndAccept(using, \", \");\n        }\n\n        List<SQLExpr> returnInto = x.getReturnInto();\n        if (returnInto.size() > 0) {\n            print0(ucase ? \" RETURNNING INTO \" : \" returnning into \");\n            printAndAccept(returnInto, \", \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleTreatExpr x) {\n        print0(ucase ? \"TREAT (\" : \"treat (\");\n        x.getExpr().accept(this);\n        print0(ucase ? \" AS \" : \" as \");\n        if (x.isRef()) {\n            print0(ucase ? \"REF \" : \"ref \");\n        }\n        x.getType().accept(this);\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateSynonymStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE \" : \"create or replace \");\n        } else {\n            print0(ucase ? \"CREATE \" : \"create \");\n        }\n\n        if (x.isPublic()) {\n            print0(ucase ? \"PUBLIC \" : \"public \");\n        }\n\n        print0(ucase ? \"SYNONYM \" : \"synonym \");\n\n        x.getName().accept(this);\n\n        print0(ucase ? \" FOR \" : \" for \");\n        x.getObject().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleCreateTypeStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE TYPE \" : \"create or replace type \");\n        } else {\n            print0(ucase ? \"CREATE TYPE \" : \"create type \");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \"BODY \" : \"body \");\n        }\n\n        x.getName().accept(this);\n\n        SQLName under = x.getUnder();\n        if (under != null) {\n            print0(ucase ? \" UNDER \" : \" under \");\n            under.accept(this);\n        }\n\n        SQLName authId = x.getAuthId();\n        if (authId != null) {\n            print0(ucase ? \" AUTHID \" : \" authid \");\n            authId.accept(this);\n        }\n\n        if (x.isForce()) {\n            print0(ucase ? \"FORCE \" : \"force \");\n        }\n\n        List<SQLParameter> parameters = x.getParameters();\n        SQLDataType tableOf = x.getTableOf();\n\n        if (x.isObject()) {\n            print0(\" AS OBJECT\");\n        }\n\n        if (parameters.size() > 0) {\n            if (x.isParen()) {\n                print(\" (\");\n            } else {\n                print0(ucase ? \" IS\" : \" is\");\n            }\n            indentCount++;\n            println();\n\n            for (int i = 0; i < parameters.size(); ++i) {\n                SQLParameter param = parameters.get(i);\n                param.accept(this);\n\n                SQLDataType dataType = param.getDataType();\n\n                if (i < parameters.size() - 1) {\n                    if (dataType instanceof OracleFunctionDataType\n                            && ((OracleFunctionDataType) dataType).getBlock() != null) {\n                        // skip\n                        println();\n                    } else if (dataType instanceof OracleProcedureDataType\n                            && ((OracleProcedureDataType) dataType).getBlock() != null) {\n                        // skip\n                        println();\n                    } else {\n                        println(\", \");\n                    }\n                }\n            }\n\n            indentCount--;\n            println();\n\n            if (x.isParen()) {\n                print0(\")\");\n            } else {\n                print0(\"END\");\n            }\n        } else if (tableOf != null) {\n            print0(ucase ? \" AS TABLE OF \" : \" as table of \");\n            tableOf.accept(this);\n        } else if (x.getVarraySizeLimit() != null) {\n            print0(ucase ? \" VARRAY (\" : \" varray (\");\n            x.getVarraySizeLimit().accept(this);\n            print0(ucase ? \") OF \" : \") of \");\n            x.getVarrayDataType().accept(this);\n        }\n\n        Boolean isFinal = x.getFinal();\n        if (isFinal != null) {\n            if (isFinal.booleanValue()) {\n                print0(ucase ? \" FINAL\" : \" final\");\n            } else {\n                print0(ucase ? \" NOT FINAL\" : \" not final\");\n            }\n        }\n\n        Boolean instantiable = x.getInstantiable();\n        if (instantiable != null) {\n            if (instantiable.booleanValue()) {\n                print0(ucase ? \" INSTANTIABLE\" : \" instantiable\");\n            } else {\n                print0(ucase ? \" NOT INSTANTIABLE\" : \" not instantiable\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OraclePipeRowStatement x) {\n        print0(ucase ? \"PIPE ROW(\" : \"pipe row(\");\n        printAndAccept(x.getParameters(), \", \");\n        print(')');\n        return false;\n    }\n\n    public boolean visit(OraclePrimaryKey x) {\n        visit((SQLPrimaryKey) x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        int curLen = this.appender.length();\n        if (curLen > 0) {\n            char c = this.appender.charAt(curLen - 1);\n            if (!(c == ' ' || c == '\\t' || c == '\\n' || c == '\\r')) {\n                this.appender.append(\" \");\n            }\n        }\n\n        return super.visit(x);\n    }\n\n    @Override\n    public boolean visit(OracleCreateTableStatement x) {\n        printCreateTable(x, false);\n\n        if (x.getOf() != null) {\n            println();\n            print0(ucase ? \"OF \" : \"of \");\n            x.getOf().accept(this);\n        }\n\n        if (x.getOidIndex() != null) {\n            println();\n            x.getOidIndex().accept(this);\n        }\n\n        if (x.getOrganization() != null) {\n            println();\n            this.indentCount++;\n            x.getOrganization().accept(this);\n            this.indentCount--;\n        }\n\n        printOracleSegmentAttributes(x);\n\n        if (x.isInMemoryMetadata()) {\n            println();\n            print0(ucase ? \"IN_MEMORY_METADATA\" : \"in_memory_metadata\");\n        }\n\n        if (x.isCursorSpecificSegment()) {\n            println();\n            print0(ucase ? \"CURSOR_SPECIFIC_SEGMENT\" : \"cursor_specific_segment\");\n        }\n\n        if (Boolean.TRUE.equals(x.getParallel())) {\n            println();\n            print0(ucase ? \"PARALLEL\" : \"parallel\");\n        } else if (Boolean.FALSE.equals(x.getParallel())) {\n            println();\n            print0(ucase ? \"NOPARALLEL\" : \"noparallel\");\n        }\n\n        if (Boolean.TRUE.equals(x.getCache())) {\n            println();\n            print0(ucase ? \"CACHE\" : \"cache\");\n        } else if (Boolean.FALSE.equals(x.getCache())) {\n            println();\n            print0(ucase ? \"NOCACHE\" : \"nocache\");\n        }\n\n        if (x.getLobStorage() != null) {\n            println();\n            x.getLobStorage().accept(this);\n        }\n\n        if (x.isOnCommitPreserveRows()) {\n            println();\n            print0(ucase ? \"ON COMMIT PRESERVE ROWS\" : \"on commit preserve rows\");\n        } else if (x.isOnCommitDeleteRows()) {\n            println();\n            print0(ucase ? \"ON COMMIT DELETE ROWS\" : \"on commit delete rows\");\n        }\n\n        if (x.isMonitoring()) {\n            println();\n            print0(ucase ? \"MONITORING\" : \"monitoring\");\n        }\n\n        printPartitionBy(x);\n\n        if (x.getCluster() != null) {\n            println();\n            print0(ucase ? \"CLUSTER \" : \"cluster \");\n            x.getCluster().accept(this);\n            print0(\" (\");\n            printAndAccept(x.getClusterColumns(), \",\");\n            print0(\")\");\n        }\n\n        if (x.getSelect() != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            x.getSelect().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleStorageClause x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleGotoStatement x) {\n        print0(ucase ? \"GOTO \" : \"GOTO \");\n        x.getLabel().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleLabelStatement x) {\n        print0(\"<<\");\n        x.getLabel().accept(this);\n        print0(\">>\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTriggerStatement x) {\n        print0(ucase ? \"ALTER TRIGGER \" : \"alter trigger \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterSynonymStatement x) {\n        print0(ucase ? \"ALTER SYNONYM \" : \"alter synonym \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterViewStatement x) {\n        print0(ucase ? \"ALTER VIEW \" : \"alter view \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \"ENABLE\" : \"enable\");\n            } else {\n                print0(ucase ? \"DISABLE\" : \"disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleAlterTableMoveTablespace x) {\n        print0(ucase ? \" MOVE TABLESPACE \" : \" move tablespace \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    public boolean visit(OracleForeignKey x) {\n        visit((SQLForeignKeyImpl) x);\n        return false;\n    }\n\n    public boolean visit(OracleUnique x) {\n        visit((SQLUnique) x);\n        return false;\n    }\n\n    public boolean visit(OracleSelectSubqueryTableSource x) {\n        print('(');\n        this.indentCount++;\n        println();\n        x.getSelect().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        if (x.getPivot() != null) {\n            println();\n            x.getPivot().accept(this);\n        }\n\n        SQLUnpivot unpivot = x.getUnpivot();\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n\n        printFlashback(x.getFlashback());\n\n        if ((x.getAlias() != null) && (x.getAlias().length() != 0)) {\n            print(' ');\n            print0(x.getAlias());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLParameter x) {\n        SQLName name = x.getName();\n        if (x.getDataType() == null) {\n            x.getName().accept(this);\n            return false;\n        }\n        if (x.getDataType().getName().equalsIgnoreCase(\"CURSOR\")) {\n            x.getName().accept(this);\n            print0(ucase ? \"CURSOR \" : \"cursor \");\n            print0(ucase ? \" FOR\" : \" for\");\n            this.indentCount++;\n            println();\n            SQLSelect select = ((SQLQueryExpr) x.getDefaultValue()).getSubQuery();\n            select.accept(this);\n            this.indentCount--;\n\n        } else {\n            if (x.isMap()) {\n                print0(ucase ? \"MAP MEMBER \" : \"map member \");\n            } else if (x.isOrder()) {\n                print0(ucase ? \"ORDER MEMBER \" : \"order member \");\n            } else if (x.isMember()) {\n                print0(ucase ? \"MEMBER \" : \"member \");\n            }\n            SQLDataType dataType = x.getDataType();\n\n            if (DbType.oracle == dbType\n                || dataType instanceof OracleFunctionDataType\n                || dataType instanceof OracleProcedureDataType) {\n                if (dataType instanceof OracleFunctionDataType) {\n                    OracleFunctionDataType functionDataType = (OracleFunctionDataType) dataType;\n                    visit(functionDataType);\n                    return false;\n                }\n\n                if (dataType instanceof OracleProcedureDataType) {\n                    OracleProcedureDataType procedureDataType = (OracleProcedureDataType) dataType;\n                    visit(procedureDataType);\n                    return false;\n                }\n\n                String dataTypeName = dataType.getName();\n                boolean printType = (dataTypeName.startsWith(\"TABLE OF\") && x.getDefaultValue() == null)\n                                    || dataTypeName.equalsIgnoreCase(\"REF CURSOR\")\n                                    || dataTypeName.startsWith(\"VARRAY(\");\n                if (printType) {\n                    print0(ucase ? \"TYPE \" : \"type \");\n                }\n\n                //枚举类型特殊处理\n                if (\"ENUM\".equals(dataTypeName)) {\n                    dataType.accept(this);\n                    return false;\n                } else {\n                    name.accept(this);\n                }\n                if (x.getParamType() == SQLParameter.ParameterType.IN) {\n                    print0(ucase ? \" IN \" : \" in \");\n                } else if (x.getParamType() == SQLParameter.ParameterType.OUT) {\n                    print0(ucase ? \" OUT \" : \" out \");\n                } else if (x.getParamType() == SQLParameter.ParameterType.INOUT) {\n                    print0(ucase ? \" IN OUT \" : \" in out \");\n                } else {\n                    print(' ');\n                }\n\n                if (x.isNoCopy()) {\n                    print0(ucase ? \"NOCOPY \" : \"nocopy \");\n                }\n\n                if (x.isConstant()) {\n                    print0(ucase ? \"CONSTANT \" : \"constant \");\n                }\n\n                if (printType) {\n                    print0(ucase ? \"IS \" : \"is \");\n                }\n            } else {\n                if (x.getParamType() == SQLParameter.ParameterType.IN) {\n                    boolean skip = DbType.mysql == dbType\n                                   && x.getParent() instanceof SQLCreateFunctionStatement;\n\n                    if (!skip) {\n                        print0(ucase ? \"IN \" : \"in \");\n                    }\n                } else if (x.getParamType() == SQLParameter.ParameterType.OUT) {\n                    print0(ucase ? \"OUT \" : \"out \");\n                } else if (x.getParamType() == SQLParameter.ParameterType.INOUT) {\n                    print0(ucase ? \"INOUT \" : \"inout \");\n                }\n                x.getName().accept(this);\n                print(' ');\n            }\n\n            dataType.accept(this);\n\n            printParamDefaultValue(x);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnpivot x) {\n        print0(ucase ? \"UNPIVOT\" : \"unpivot\");\n        if (x.getNullsIncludeType() != null) {\n            print(' ');\n            print0(SQLUnpivot.NullsIncludeType.toString(x.getNullsIncludeType(), ucase));\n        }\n\n        print0(\" (\");\n        if (x.getItems().size() == 1) {\n            ((SQLExpr) x.getItems().get(0)).accept(this);\n        } else {\n            print0(\" (\");\n            printAndAccept(x.getItems(), \", \");\n            print(')');\n        }\n\n        if (x.getPivotFor().size() > 0) {\n            print0(ucase ? \" FOR \" : \" for \");\n            if (x.getPivotFor().size() == 1) {\n                ((SQLExpr) x.getPivotFor().get(0)).accept(this);\n            } else {\n                print('(');\n                printAndAccept(x.getPivotFor(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.getPivotIn().size() > 0) {\n            print0(ucase ? \" IN (\" : \" in (\");\n            printAndAccept(x.getPivotIn(), \", \");\n            print(')');\n        }\n\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleUpdateStatement x) {\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY (\" : \"only (\");\n            x.getTableSource().accept(this);\n            print(')');\n        } else {\n            x.getTableSource().accept(this);\n        }\n\n        printAlias(x.getAlias());\n\n        println();\n\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            x.getItems().get(i).accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            this.indentCount++;\n            x.getWhere().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getReturning().size() > 0) {\n            println();\n            print0(ucase ? \"RETURNING \" : \"returning \");\n            printAndAccept(x.getReturning(), \", \");\n            print0(ucase ? \" INTO \" : \" into \");\n            printAndAccept(x.getReturningInto(), \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SampleClause x) {\n        print0(ucase ? \"SAMPLE \" : \"sample \");\n\n        if (x.isBlock()) {\n            print0(ucase ? \"BLOCK \" : \"block \");\n        }\n\n        print('(');\n        printAndAccept(x.getPercent(), \", \");\n        print(')');\n\n        if (x.getSeedValue() != null) {\n            print0(ucase ? \" SEED (\" : \" seed (\");\n            x.getSeedValue().accept(this);\n            print(')');\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleSelectJoin x) {\n        x.getLeft().accept(this);\n        SQLTableSource right = x.getRight();\n\n        if (x.getJoinType() == SQLJoinTableSource.JoinType.COMMA) {\n            print0(\", \");\n            x.getRight().accept(this);\n        } else {\n            boolean isRoot = x.getParent() instanceof SQLSelectQueryBlock;\n            if (isRoot) {\n                this.indentCount++;\n            }\n\n            println();\n            print0(ucase ? x.getJoinType().name : x.getJoinType().nameLCase);\n            print(' ');\n\n            if (right instanceof SQLJoinTableSource) {\n                print('(');\n                right.accept(this);\n                print(')');\n            } else {\n                right.accept(this);\n            }\n\n            if (isRoot) {\n                this.indentCount--;\n            }\n\n            if (x.getCondition() != null) {\n                print0(ucase ? \" ON \" : \" on \");\n                x.getCondition().accept(this);\n                print(' ');\n                if (x.getAfterCommentsDirect() != null) {\n                    printAfterComments(x.getAfterCommentsDirect());\n                    println();\n                }\n            }\n\n            if (x.getUsing().size() > 0) {\n                print0(ucase ? \" USING (\" : \" using (\");\n                printAndAccept(x.getUsing(), \", \");\n                print(')');\n            }\n\n            printFlashback(x.getFlashback());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectRestriction.CheckOption x) {\n        print0(ucase ? \"CHECK OPTION\" : \"check option\");\n        if (x.getConstraint() != null) {\n            print0(ucase ? \" CONSTRAINT\" : \" constraint\");\n            print(' ');\n            x.getConstraint().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleSelectRestriction.ReadOnly x) {\n        print0(ucase ? \"READ ONLY\" : \"read only\");\n        if (x.getConstraint() != null) {\n            print0(ucase ? \" CONSTRAINT\" : \" constraint\");\n            print(' ');\n            x.getConstraint().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(OracleDeleteStatement x) {\n        return visit((SQLDeleteStatement) x);\n    }\n\n    private void printFlashback(SQLExpr flashback) {\n        if (flashback == null) {\n            return;\n        }\n\n        println();\n\n        if (flashback instanceof SQLBetweenExpr) {\n            flashback.accept(this);\n        } else {\n            print0(ucase ? \"AS OF \" : \"as of \");\n            flashback.accept(this);\n        }\n    }\n\n    public boolean visit(OracleWithSubqueryEntry x) {\n        print0(x.getAlias());\n\n        if (x.getColumns().size() > 0) {\n            print0(\" (\");\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        print0(ucase ? \" AS \" : \" as \");\n        print('(');\n        this.indentCount++;\n        println();\n        x.getSubQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        if (x.getSearchClause() != null) {\n            println();\n            x.getSearchClause().accept(this);\n        }\n\n        if (x.getCycleClause() != null) {\n            println();\n            x.getCycleClause().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SearchClause x) {\n        print0(ucase ? \"SEARCH \" : \"search \");\n        print0(x.getType().name());\n        print0(ucase ? \" FIRST BY \" : \" first by \");\n        printAndAccept(x.getItems(), \", \");\n        print0(ucase ? \" SET \" : \" set \");\n        x.getOrderingColumn().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(CycleClause x) {\n        print0(ucase ? \"CYCLE \" : \"cycle \");\n        printAndAccept(x.getAliases(), \", \");\n        print0(ucase ? \" SET \" : \" set \");\n        x.getMark().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getValue().accept(this);\n        print0(ucase ? \" DEFAULT \" : \" default \");\n        x.getDefaultValue().accept(this);\n\n        return false;\n    }\n\n    public boolean visit(OracleAnalytic x) {\n        print0(ucase ? \"(\" : \"(\");\n\n        boolean space = false;\n        if (x.getPartitionBy().size() > 0) {\n            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n            printAndAccept(x.getPartitionBy(), \", \");\n\n            space = true;\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            if (space) {\n                print(' ');\n            }\n            visit(orderBy);\n            space = true;\n        }\n\n        OracleAnalyticWindowing windowing = x.getWindowing();\n        if (windowing != null) {\n            if (space) {\n                print(' ');\n            }\n            visit(windowing);\n        }\n\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(OracleAnalyticWindowing x) {\n        print0(x.getType().name().toUpperCase());\n        print(' ');\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleIsOfTypeExpr x) {\n        printExpr(x.getExpr());\n        print0(ucase ? \" IS OF TYPE (\" : \" is of type (\");\n\n        List<SQLExpr> types = x.getTypes();\n        for (int i = 0, size = types.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLExpr type = types.get(i);\n            if (Boolean.TRUE.equals(type.getAttribute(\"ONLY\"))) {\n                print0(ucase ? \"ONLY \" : \"only \");\n            }\n            type.accept(this);\n        }\n\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleRunStatement x) {\n        print0(\"@@\");\n        printExpr(x.getExpr());\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.Else x) {\n        print0(ucase ? \"ELSE\" : \"else\");\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.ElseIf x) {\n        print0(ucase ? \"ELSIF \" : \"elsif \");\n        x.getCondition().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            println();\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement x) {\n        print0(ucase ? \"IF \" : \"if \");\n        int lines = this.lines;\n        this.indentCount++;\n        x.getCondition().accept(this);\n        this.indentCount--;\n\n        if (lines != this.lines) {\n            println();\n        } else {\n            print(' ');\n        }\n        print0(ucase ? \"THEN\" : \"then\");\n\n        this.indentCount++;\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            println();\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n        this.indentCount--;\n\n        for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) {\n            println();\n            elseIf.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            x.getElseItem().accept(this);\n        }\n        println();\n        print0(ucase ? \"END IF\" : \"end if\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateIndexStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        if (x.getType() != null) {\n            print0(x.getType());\n            print(' ');\n        }\n\n        print0(ucase ? \"INDEX\" : \"index\");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \" IF NOT EXISTS\" : \" if not exists\");\n        }\n\n        if (x.isConcurrently()) {\n            print0(ucase ? \" CONCURRENTLY\" : \" concurrently\");\n        }\n\n        SQLName name = x.getName();\n        if (name != null) {\n            print(' ');\n            name.accept(this);\n        }\n\n        print0(ucase ? \" ON \" : \" on \");\n        x.getTable().accept(this);\n\n        if (x.getUsing() != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(x.getUsing());\n        }\n        print0(\" (\");\n        printAndAccept(x.getItems(), \", \");\n        print(')');\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        boolean hasOptions = false;\n\n        if (x.getIndexDefinition().hasOptions()) {\n            SQLIndexOptions indexOptions = x.getIndexDefinition().getOptions();\n            if (indexOptions.getKeyBlockSize() != null ||\n                    indexOptions.getParserName() != null ||\n                    indexOptions.getAlgorithm() != null ||\n                    indexOptions.getLock() != null ||\n                    indexOptions.getOtherOptions().size() > 0) {\n                hasOptions = true;\n            }\n        }\n\n        if (hasOptions) {\n            print0(ucase ? \" WITH (\" : \" with (\");\n            SQLIndexOptions indexOptions = x.getIndexDefinition().getOptions();\n\n            SQLExpr keyBlockSize = indexOptions.getKeyBlockSize();\n            if (keyBlockSize != null) {\n                print0(ucase ? \" KEY_BLOCK_SIZE = \" : \" key_block_size = \");\n                printExpr(keyBlockSize, parameterized);\n            }\n\n            String parserName = indexOptions.getParserName();\n            if (parserName != null) {\n                print0(ucase ? \" WITH PARSER \" : \" with parser \");\n                print0(parserName);\n            }\n\n            String algorithm = indexOptions.getAlgorithm();\n            if (algorithm != null) {\n                print0(ucase ? \" ALGORITHM = \" : \" algorithm = \");\n                print0(algorithm);\n            }\n\n            String lock = indexOptions.getLock();\n            if (lock != null) {\n                print0(ucase ? \" LOCK \" : \" lock \");\n                print0(lock);\n            }\n\n            for (SQLAssignItem option : indexOptions.getOtherOptions()) {\n                option.accept(this);\n            }\n\n            print(')');\n        }\n\n        SQLName tablespace = x.getTablespace();\n        if (tablespace != null) {\n            print0(ucase ? \" TABLESPACE \" : \" tablespace \");\n            tablespace.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddColumn x) {\n        boolean odps = isOdps();\n        print0(ucase ? \"ADD COLUMN \" : \"add column \");\n        printAndAccept(x.getColumns(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {\n        return false;\n    }\n\n    public boolean visit(SQLArrayDataType x) {\n        SQLDataType componentType = x.getComponentType();\n        if (componentType != null) {\n            componentType.accept(this);\n        }\n        print('[');\n        printAndAccept(x.getArguments(), \", \");\n        print(']');\n        return false;\n    }\n\n    public boolean visit(SQLCharExpr x, boolean parameterized) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (parameterized) {\n            print('?');\n            incrementReplaceCunt();\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            return false;\n        }\n\n        if (x instanceof PGCharExpr && ((PGCharExpr) x).isCSytle()) {\n            print('E');\n        }\n        if (x.getCollate() != null) {\n            String collate = x.getCollate();\n            if (x.isParenthesized()) {\n                print('(');\n            }\n            printChars(x.getText());\n            print(\" COLLATE \");\n            if (collate.startsWith(\"'\") || collate.endsWith(\"\\\"\")) {\n                print(collate);\n            } else {\n                print('\\'');\n                print(collate);\n                print('\\'');\n            }\n            if (x.isParenthesized()) {\n                print(')');\n            }\n        } else {\n            printChars(x.getText());\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGAnalyzeStatement x) {\n        print0(ucase ? \"ANALYZE \" : \"analyze\");\n        if (x.isVerbose()) {\n            print0(ucase ? \"VERBOSE \" : \"verbose \");\n        }\n        if (x.isSkipLocked()) {\n            print0(ucase ? \"SKIP_LOCKED \" : \"skip_locked \");\n        }\n        printAndAccept(x.getTableSources(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGVacuumStatement x) {\n        print0(ucase ? \"VACUUM \" : \"vacuum\");\n        if (x.isFull()) {\n            print0(ucase ? \"FULL \" : \"full \");\n        }\n        if (x.isFreeze()) {\n            print0(ucase ? \"FREEZE \" : \"freeze \");\n        }\n        if (x.isVerbose()) {\n            print0(ucase ? \"VERBOSE \" : \"verbose \");\n        }\n        if (x.isAnalyze()) {\n            print0(ucase ? \"ANALYZE \" : \"analyze \");\n        }\n        if (x.isDisablePageSkipping()) {\n            print0(ucase ? \"DISABLE_PAGE_SKIPPING \" : \"disable_page_skipping \");\n        }\n        if (x.isSkipLocked()) {\n            print0(ucase ? \"SKIP_LOCKED \" : \"skip_locked \");\n        }\n        if (x.isProcessToast()) {\n            print0(ucase ? \"PROCESS_TOAST \" : \"process_toast \");\n        }\n        if (x.isTruncate()) {\n            print0(ucase ? \"TRUNCATE \" : \"truncate \");\n        }\n        printVacuumRest(x);\n        printAndAccept(x.getTableSources(), \", \");\n        return false;\n    }\n\n    protected void printVacuumRest(PGVacuumStatement x){\n    }\n\n    @Override\n    public boolean visit(PGAlterDatabaseStatement x) {\n        print0(ucase ? \"ALTER DATABASE \" : \"alter database \");\n        x.getDatabaseName().accept(this);\n        print(' ');\n        if (x.getRenameToName() != null) {\n            print0(ucase ? \"RENAME TO \" : \"rename to \");\n            x.getRenameToName().accept(this);\n        }\n        if (x.getOwnerToName() != null) {\n            print0(ucase ? \"OWNER TO \" : \"owner to \");\n            x.getOwnerToName().accept(this);\n        }\n\n        if (x.getSetTableSpaceName() != null) {\n            print0(ucase ? \"SET TABLESPACE \" : \"set tablespace \");\n            x.getSetTableSpaceName().accept(this);\n        }\n        if (x.isRefreshCollationVersion()) {\n            print0(ucase ? \"REFRESH COLLATION VERSION \" : \"refresh collation version \");\n        }\n        if (x.getSetParameterName() != null) {\n            print0(ucase ? \"SET \" : \"set \");\n            x.getSetParameterName().accept(this);\n            if (x.isUseEquals()) {\n                print(\" = \");\n            } else {\n                print0(ucase ? \" TO \" : \" to \");\n            }\n            x.getSetParameterValue().accept(this);\n        }\n        if (x.getResetParameterName() != null) {\n            print0(ucase ? \"RESET \" : \"reset \");\n            x.getResetParameterName().accept(this);\n        }\n        if (x.isHaveWith()) {\n            print0(ucase ? \"WITH \" : \"with \");\n        }\n        if (x.getAllowConnections() != null) {\n            print0(ucase ? \"ALLOW_CONNECTIONS \" : \"allow_connections \");\n            print0(String.valueOf(x.getAllowConnections()));\n        }\n        if (x.getSetTemplateMark() != null) {\n            print0(ucase ? \"IS_TEMPLATE \" : \"is_template \");\n            print0(String.valueOf(x.getSetTemplateMark()));\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableChangeOwner x) {\n        print0(ucase ? \"OWNER TO \" : \"owner to \");\n        print0(x.getOwner().getSimpleName());\n        return false;\n    }\n\n    @Override\n    protected void printAutoIncrement() {\n        print0(ucase ? \" GENERATED ALWAYS AS IDENTITY\" : \" generated always as identity\");\n    }\n\n    @Override\n    protected void printGeneratedAlways(SQLColumnDefinition x, boolean parameterized) {\n        SQLExpr generatedAlwaysAs = x.getGeneratedAlwaysAs();\n        SQLColumnDefinition.Identity identity = x.getIdentity();\n\n        if (generatedAlwaysAs != null || identity != null) {\n            if (x.isGenerateByDefault()) {\n                print0(ucase ? \" GENERATED BY DEFAULT AS \" : \" generated by default as \");\n            } else {\n                print0(ucase ? \" GENERATED ALWAYS AS \" : \" generated always as \");\n            }\n            if (generatedAlwaysAs != null) {\n                printExpr(generatedAlwaysAs, parameterized);\n                print(' ');\n            }\n            identity.accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLColumnDefinition.Identity x) {\n        print0(ucase ? \"IDENTITY\" : \"identity\");\n        Integer seed = x.getSeed();\n        if (seed != null) {\n            print0(ucase ? \" (INCREMENT BY \" : \" (increment by \");\n            if (x.getIncrement() != null) {\n                print(x.getIncrement());\n            } else {\n                print('1');\n            }\n            print0(ucase ? \" START WITH  \" : \" start with  \");\n            print(seed);\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIntervalExpr x) {\n        print0(ucase ? \"INTERVAL \" : \"interval \");\n        SQLExpr value = x.getValue();\n\n        boolean str = value instanceof SQLCharExpr;\n        if (!str) {\n            print('\\'');\n        }\n        value.accept(this);\n\n        SQLIntervalUnit unit = x.getUnit();\n        if (unit != null) {\n            print(' ');\n            print0(ucase ? unit.name : unit.nameLCase);\n        }\n        if (!str) {\n            print('\\'');\n        }\n        return false;\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        print0(ucase ? \"WITH (\" : \"with (\");\n        incrementIndent();\n        println();\n    }\n\n    protected boolean legacyCube() {\n        return true;\n    }\n\n    protected void printTableOption(SQLExpr name, SQLExpr value, int index) {\n        if (index != 0) {\n            print(\",\");\n            println();\n        }\n        String key = name.toString();\n        print0(key);\n        print0(\" = \");\n        value.accept(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.postgresql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Mode;\nimport com.alibaba.druid.util.PGUtils;\n\npublic class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisitor {\n    public PGSchemaStatVisitor() {\n        super(DbType.postgresql);\n    }\n\n    public PGSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.postgresql;\n    }\n\n    @Override\n    public boolean visit(PGDeleteStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n        }\n\n        SQLTableSource using = x.getUsing();\n        if (using != null) {\n            using.accept(this);\n        }\n\n        x.putAttribute(\"_original_use_mode\", getMode());\n        setMode(x, Mode.Delete);\n\n        TableStat stat = getTableStat(x.getTableName());\n        stat.incrementDeleteCount();\n\n        accept(x.getWhere());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGInsertStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n        }\n\n        x.putAttribute(\"_original_use_mode\", getMode());\n        setMode(x, Mode.Insert);\n\n        SQLName tableName = x.getTableName();\n        {\n            TableStat stat = getTableStat(tableName);\n            stat.incrementInsertCount();\n        }\n\n        accept(x.getColumns());\n        accept(x.getQuery());\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(PGSelectStatement x) {\n    }\n\n    @Override\n    public boolean visit(PGSelectStatement x) {\n        return visit((SQLSelectStatement) x);\n    }\n\n    public boolean isPseudoColumn(long hash) {\n        return PGUtils.isPseudoColumn(hash);\n    }\n\n    @Override\n    public boolean visit(PGUpdateStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n        }\n\n        TableStat stat = getTableStat(x.getTableName());\n        stat.incrementUpdateCount();\n\n        accept(x.getFrom());\n\n        accept(x.getItems());\n        accept(x.getWhere());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGTypeCastExpr x) {\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGShowStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGStartTransactionStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGEndTransactionStatement x) {\n        return false;\n    }\n    @Override\n    public boolean visit(PGConnectToStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGCreateSchemaStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGDropSchemaStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(PGAlterSchemaStatement x) {\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/Presto.java",
    "content": "package com.alibaba.druid.sql.dialect.presto;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Presto {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.presto);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/PrestoColumnConstraint.java",
    "content": "package com.alibaba.druid.sql.dialect.presto.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLConstraintImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PrestoColumnConstraint extends SQLConstraintImpl implements SQLColumnConstraint {\n    public PrestoColumnConstraint() {\n        dbType = DbType.presto;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor v) {}\n\n    @Override\n    public PrestoColumnConstraint clone() {\n        PrestoColumnConstraint prestoColumnConstraint = new PrestoColumnConstraint();\n        cloneTo(prestoColumnConstraint);\n        return prestoColumnConstraint;\n    }\n\n    public void cloneTo(PrestoColumnConstraint x) {\n        super.cloneTo(x);\n        x.dbType = dbType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/PrestoColumnWith.java",
    "content": "package com.alibaba.druid.sql.dialect.presto.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PrestoColumnWith extends PrestoColumnConstraint implements PrestoObject {\n    private final List<SQLAssignItem> properties;\n\n    public PrestoColumnWith() {\n        properties = new ArrayList<>();\n    }\n\n    public void addProperty(SQLAssignItem sqlAssignItem) {\n        if (sqlAssignItem != null) {\n            sqlAssignItem.setParent(this);\n            properties.add(sqlAssignItem);\n        }\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, properties);\n        }\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PrestoASTVisitor) {\n            accept0((PrestoASTVisitor) visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/PrestoDateTimeExpr.java",
    "content": "package com.alibaba.druid.sql.dialect.presto.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PrestoDateTimeExpr extends OracleDatetimeExpr implements PrestoObject {\n    public PrestoDateTimeExpr(SQLExpr expr, SQLExpr timeZone) {\n        super(expr, timeZone);\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getExpr());\n            acceptChild(visitor, getTimeZone());\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PrestoASTVisitor) {\n            accept0((PrestoASTVisitor) visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/PrestoObject.java",
    "content": "package com.alibaba.druid.sql.dialect.presto.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface PrestoObject extends SQLObject {\n    void accept0(PrestoASTVisitor visitor);\n    default void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PrestoASTVisitor) {\n            accept0((PrestoASTVisitor) visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoAlterFunctionStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.statement.SQLAlterFunctionStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PrestoAlterFunctionStatement extends SQLAlterFunctionStatement implements PrestoSQLStatement {\n    public PrestoAlterFunctionStatement() {\n    }\n\n    private boolean returnsNullOnNullInput;\n    private boolean calledOnNullInput;\n\n    public boolean isReturnsNullOnNullInput() {\n        return returnsNullOnNullInput;\n    }\n\n    public void setReturnsNullOnNullInput(boolean returnsNullOnNullInput) {\n        this.returnsNullOnNullInput = returnsNullOnNullInput;\n    }\n\n    public boolean isCalledOnNullInput() {\n        return calledOnNullInput;\n    }\n\n    public void setCalledOnNullInput(boolean calledOnNullInput) {\n        this.calledOnNullInput = calledOnNullInput;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof PrestoASTVisitor) {\n            this.accept0((PrestoASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        visitor.visit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoAlterSchemaStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PrestoAlterSchemaStatement extends SQLStatementImpl implements PrestoSQLStatement, SQLAlterStatement {\n    private SQLName schemaName;\n\n    private SQLIdentifierExpr newName;\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof PrestoASTVisitor) {\n            this.accept0((PrestoASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        visitor.visit(this);\n    }\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        this.schemaName = schemaName;\n    }\n\n    public SQLIdentifierExpr getNewName() {\n        return newName;\n    }\n\n    public void setNewName(SQLIdentifierExpr newName) {\n        this.newName = newName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoCreateTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class PrestoCreateTableStatement extends SQLCreateTableStatement implements PrestoSQLStatement {\n    public PrestoCreateTableStatement() {\n        this.dbType = DbType.presto;\n    }\n\n    public PrestoCreateTableStatement(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof PrestoASTVisitor) {\n            this.accept0((PrestoASTVisitor) v);\n        }\n        super.accept0(v);\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        visitor.visit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        super.acceptChild(v);\n    }\n\n    public void cloneTo(PrestoCreateTableStatement x) {\n        super.cloneTo(x);\n    }\n\n    public PrestoCreateTableStatement clone() {\n        PrestoCreateTableStatement x = new PrestoCreateTableStatement();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoDeallocatePrepareStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class PrestoDeallocatePrepareStatement extends SQLStatementImpl implements PrestoSQLStatement {\n    private SQLName statementName;\n\n    public SQLName getStatementName() {\n        return statementName;\n    }\n\n    public void setStatementName(SQLName statementName) {\n        this.statementName = statementName;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof PrestoASTVisitor) {\n            this.accept0((PrestoASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statementName);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>singletonList(statementName);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoExecuteStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PrestoExecuteStatement extends SQLStatementImpl implements PrestoSQLStatement {\n    private SQLName statementName;\n    private final List<SQLExpr> parameters = new ArrayList<SQLExpr>();\n\n    public PrestoExecuteStatement() {\n        dbType = DbType.presto;\n    }\n\n    public SQLName getStatementName() {\n        return statementName;\n    }\n\n    public void setStatementName(SQLName statementName) {\n        this.statementName = statementName;\n    }\n\n    public List<SQLExpr> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof PrestoASTVisitor) {\n            this.accept0((PrestoASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, statementName);\n            acceptChild(visitor, parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (statementName != null) {\n            children.add(statementName);\n        }\n        children.addAll(this.parameters);\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoPrepareStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class PrestoPrepareStatement extends SQLStatementImpl implements PrestoSQLStatement {\n    private SQLName name;\n    private SQLSelect select;\n    private HiveInsertStatement insert;\n\n    public PrestoPrepareStatement() {\n    }\n\n    public PrestoPrepareStatement(SQLName name) {\n        this.name = name;\n        dbType = DbType.presto;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        this.name = name;\n    }\n\n    public SQLSelect getSelect() {\n        return select;\n    }\n\n    public void setSelect(SQLSelect select) {\n        this.select = select;\n    }\n\n    public HiveInsertStatement getInsert() {\n        return insert;\n    }\n\n    public void setInsert(HiveInsertStatement insert) {\n        this.insert = insert;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof PrestoASTVisitor) {\n            this.accept0((PrestoASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(PrestoASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            if (this.select != null) {\n                acceptChild(visitor, select);\n            }\n            if (this.insert != null) {\n                acceptChild(visitor, insert);\n            }\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        if (this.select != null) {\n            children.add(select);\n        }\n        if (this.insert != null) {\n            children.add(insert);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoSQLStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.PrestoObject;\n\npublic interface PrestoSQLStatement extends SQLStatement, PrestoObject {}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/ast/stmt/PrestoSelectStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\n/**\n * presto 的 select语句\n * <p>\n * author zhangcanlong\n * date 2022/01/11\n */\npublic class PrestoSelectStatement extends SQLSelectStatement implements PrestoSQLStatement {\n    public PrestoSelectStatement() {\n        super(DbType.presto);\n    }\n\n    public PrestoSelectStatement(SQLSelect select) {\n        super(select, DbType.presto);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof PrestoASTVisitor) {\n            this.accept0((PrestoASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    public void accept0(PrestoASTVisitor visitor) {\n        super.accept0(visitor);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoCreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoCreateTableStatement;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\n\n/**\n * presto 的create table解析器\n *\n * @author yanlong\n * @since 2023-03-13\n */\npublic class PrestoCreateTableParser extends SQLCreateTableParser {\n    public PrestoCreateTableParser(String sql) {\n        super(sql);\n    }\n\n    public PrestoCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    @Override\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getTableOptions(), stmt, false);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n            SQLSelect select = this.createSQLSelectParser().select();\n            stmt.setSelect(select);\n        }\n        super.parseCreateTableRest(stmt);\n    }\n\n    protected PrestoCreateTableStatement newCreateStatement() {\n        return new PrestoCreateTableStatement();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.presto.ast.PrestoColumnWith;\nimport com.alibaba.druid.sql.dialect.presto.ast.PrestoDateTimeExpr;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\nimport static com.alibaba.druid.util.FnvHash.fnv1a_64_lower;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic class PrestoExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"ANY_VALUE\", \"ARBITRARY\", \"ARRAY_AGG\", \"AVG\", \"BOOL_AND\", \"BOOL_OR\", \"CHECKSUM\", \"COUNT\", \"COUNT_IF\",\n                \"EVERY\", \"GEOMETRIC_MEAN\", \"MAX_BY\", \"MIN_BY\", \"MAX\", \"MIN\", \"REDUCE_AGG\", \"SET_AGG\", \"SET_UNION\",\n                \"SUM\", \"BITWISE_AND_AGG\", \"BITWISE_OR_AGG\", \"BITWISE_XOR_AGG\", \"HISTOGRAM\", \"MAP_AGG\", \"MAP_UNION\",\n                \"MAP_UNION_SUM\", \"MULTIMAP_AGG\", \"APPROX_DISTINCT\", \"APPROX_PERCENTILE\", \"NUMERIC_HISTOGRAM\", \"CORR\",\n                \"COVAR_POP\", \"COVAR_SAMP\", \"ENTROPY\", \"KURTOSIS\", \"REGR_INTERCEPT\", \"REGR_SLOPE\", \"REGR_AVGX\",\n                \"REGR_AVGY\", \"REGR_COUNT\", \"REGR_R2\", \"REGR_SXX\", \"REGR_SXY\", \"REGR_SYY\", \"SKEWNESS\", \"STDDEV\",\n                \"STDDEV_POP\", \"STDDEV_SAMP\", \"VARIANCE\", \"VAR_POP\", \"VAR_SAMP\", \"CLASSIFICATION_MISS_RATE\",\n                \"CLASSIFICATION_FALL_OUT\", \"CLASSIFICATION_PRECISION\", \"CLASSIFICATION_RECALL\",\n                \"CLASSIFICATION_THRESHOLDS\", \"DIFFERENTIAL_ENTROPY\", \"APPROX_MOST_FREQUENT\", \"RESERVOIR_SAMPLE\",\n                \"NOISY_COUNT_GAUSSIAN\", \"NOISY_COUNT_IF_GAUSSIAN\", \"NOISY_SUM_GAUSSIAN\", \"NOISY_AVG_GAUSSIAN\",\n                \"NOISY_APPROX_SET_SFM\", \"NOISY_APPROX_SET_SFM_FROM_INDEX_AND_ZEROS\", \"NOISY_APPROX_DISTINCT_SFM\",\n                \"NOISY_EMPTY_APPROX_SET_SFM\", \"CARDINALITY\", \"MERGE\", \"MERGE_SFM\", \"CUME_DIST\", \"DENSE_RANK\", \"NTILE\",\n                \"PERCENT_RANK\", \"RANK\", \"ROW_NUMBER\", \"FIRST_VALUE\", \"LAST_VALUE\", \"NTH_VALUE\", \"LEAD\", \"LAG\", \"LISTAGG\"\n        };\n        AGGREGATE_FUNCTIONS_CODES = fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public PrestoExprParser(String sql, SQLParserFeature... features) {\n        this(new PrestoLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public PrestoExprParser(Lexer lexer, DbType dbType) {\n        super(lexer, dbType);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public PrestoExprParser(Lexer lexer) {\n        this(lexer, DbType.presto);\n    }\n\n    @Override\n    protected SQLColumnDefinition parseColumnSpecific(SQLColumnDefinition column) {\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            PrestoColumnWith prestoColumnWith = new PrestoColumnWith();\n            accept(Token.LPAREN);\n            parseAssignItems(prestoColumnWith.getProperties(), prestoColumnWith, false);\n            accept(Token.RPAREN);\n            column.addConstraint(prestoColumnWith);\n            return parseColumnRest(column);\n        }\n        return column;\n    }\n\n    @Override\n    public SQLExpr primaryRest(SQLExpr expr) {\n        Lexer.SavePoint savePoint = lexer.markOut();\n        if (lexer.identifierEquals(FnvHash.Constants.AT)) {\n            lexer.nextToken();\n            if (lexer.nextIfIdentifier(FnvHash.Constants.TIME)) {\n                acceptIdentifier(\"ZONE\");\n                SQLExpr timeZone = primary();\n                expr = new PrestoDateTimeExpr(expr, timeZone);\n            } else {\n                lexer.reset(savePoint);\n            }\n        }\n        return super.primaryRest(expr);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.presto.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.DialectFeature;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.AsDatabase;\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.SQLDateExpr;\n\npublic class PrestoLexer extends Lexer {\n    static final Keywords PRESTO_KEYWORDS;\n    static final DialectFeature PRESTO_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    SQLDateExpr,\n                    AsDatabase\n            ),\n            null\n    );\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"OPTIMIZE\", Token.OPTIMIZE);\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"UPSERT\", Token.UPSERT);\n\n        map.put(\"IF\", Token.IF);\n\n        PRESTO_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return PRESTO_KEYWORDS;\n    }\n\n    public PrestoLexer(String input, DbType dbType, SQLParserFeature... features) {\n        super(input, dbType);\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    public PrestoLexer(String input, SQLParserFeature... features) {\n        this(input, DbType.presto, features);\n    }\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = PRESTO_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\n/**\n * presto的 选择解析器\n * <p>\n * author zhangcanlong\n * date 2022/01/11\n */\npublic class PrestoSelectParser extends SQLSelectParser {\n    public PrestoSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public PrestoSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public PrestoSelectParser(String sql) {\n        this(new PrestoExprParser(sql));\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new PrestoExprParser(this.lexer);\n    }\n\n    @Override\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (this.lexer.token() == Token.LPAREN) {\n            this.lexer.nextToken();\n\n            SQLSelectQuery select = this.query();\n            this.accept(Token.RPAREN);\n\n            return this.queryRest(select, acceptUnion);\n        }\n\n        if (this.lexer.token() == Token.VALUES) {\n            return this.valuesQuery(acceptUnion);\n        }\n\n        SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock(this.dbType);\n\n        if (this.lexer.hasComment() && this.lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(this.lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.TABLE) {\n            lexer.nextToken();\n            queryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));\n            queryBlock.setFrom(parseTableSource());\n            return queryRest(queryBlock, acceptUnion);\n        }\n\n        this.accept(Token.SELECT);\n\n        if (this.lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(queryBlock.getHints());\n        }\n\n        if (this.lexer.token() == Token.COMMENT) {\n            this.lexer.nextToken();\n        }\n\n        if (this.lexer.token() == Token.DISTINCT) {\n            queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n            this.lexer.nextToken();\n        } else if (this.lexer.token() == Token.UNIQUE) {\n            queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n            this.lexer.nextToken();\n        } else if (this.lexer.token() == Token.ALL) {\n            queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n            this.lexer.nextToken();\n        }\n\n        this.parseSelectList(queryBlock);\n\n        if (this.lexer.token() == Token.INTO) {\n            this.lexer.nextToken();\n\n            SQLExpr expr = this.expr();\n            if (this.lexer.token() != Token.COMMA) {\n                queryBlock.setInto(expr);\n            }\n        }\n\n        this.parseFrom(queryBlock);\n\n        this.parseWhere(queryBlock);\n\n        this.parseGroupBy(queryBlock);\n\n        if (this.lexer.identifierEquals(FnvHash.Constants.WINDOW)) {\n            this.parseWindow(queryBlock);\n        }\n\n        this.parseSortBy(queryBlock);\n\n        this.parseFetchClause(queryBlock);\n\n        if (this.lexer.token() == Token.FOR) {\n            this.lexer.nextToken();\n            this.accept(Token.UPDATE);\n\n            queryBlock.setForUpdate(true);\n\n            if (this.lexer.identifierEquals(FnvHash.Constants.NO_WAIT) || this.lexer.identifierEquals(FnvHash.Constants.NOWAIT)) {\n                this.lexer.nextToken();\n                queryBlock.setNoWait(true);\n            } else if (this.lexer.identifierEquals(FnvHash.Constants.WAIT)) {\n                this.lexer.nextToken();\n                SQLExpr waitTime = this.exprParser.primary();\n                queryBlock.setWaitTime(waitTime);\n            }\n        }\n\n        return this.queryRest(queryBlock, acceptUnion);\n    }\n\n    @Override\n    public void parseFetchClause(SQLSelectQueryBlock queryBlock) {\n        // 如果是presto，则先解析 offset 再解析limit\n        if (this.lexer.identifierEquals(FnvHash.Constants.OFFSET) || this.lexer.token() == Token.OFFSET) {\n            this.lexer.nextToken();\n            SQLExpr offset = this.exprParser.expr();\n            queryBlock.setOffset(offset);\n            if (this.lexer.identifierEquals(FnvHash.Constants.ROW) || this.lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                this.lexer.nextToken();\n            }\n        }\n\n        if (this.lexer.token() == Token.LIMIT) {\n            SQLLimit limit = queryBlock.getLimit();\n            // 原始的limit\n            SQLLimit originLimit = this.exprParser.parseLimit();\n            if (limit == null) {\n                limit = originLimit;\n            }\n            limit.setRowCount(originLimit.getRowCount());\n            queryBlock.setLimit(limit);\n            return;\n        }\n\n        if (this.lexer.token() == Token.FETCH) {\n            this.lexer.nextToken();\n            if (this.lexer.token() == Token.FIRST || this.lexer.token() == Token.NEXT || this.lexer.identifierEquals(FnvHash.Constants.NEXT)) {\n                this.lexer.nextToken();\n            } else {\n                this.acceptIdentifier(\"FIRST\");\n            }\n            SQLExpr first = this.exprParser.primary();\n            queryBlock.setFirst(first);\n            if (this.lexer.identifierEquals(FnvHash.Constants.ROW) || this.lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                this.lexer.nextToken();\n            }\n\n            if (this.lexer.token() == Token.ONLY) {\n                this.lexer.nextToken();\n            } else {\n                this.acceptIdentifier(\"ONLY\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExplainStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertInto;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLShowColumnsStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLShowCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLShowCreateViewStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLShowDatabasesStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLShowFunctionsStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLShowIndexesStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLShowPartitionsStmt;\nimport com.alibaba.druid.sql.ast.statement.SQLShowViewsStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MysqlDeallocatePrepareStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoAlterFunctionStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoAlterSchemaStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoExecuteStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoPrepareStatement;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.FnvHash.Constants;\n\nimport java.util.List;\n\n/**\n * Created by wenshao on 16/9/13.\n */\npublic class PrestoStatementParser extends SQLStatementParser {\n    {\n        dbType = DbType.presto;\n    }\n    public PrestoStatementParser(String sql) {\n        super(new PrestoExprParser(sql));\n    }\n    public PrestoStatementParser(String sql, SQLParserFeature... features) {\n        super(new PrestoExprParser(sql, features));\n    }\n\n    public PrestoStatementParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n    public PrestoStatementParser(Lexer lexer) {\n        super(new PrestoExprParser(lexer));\n    }\n\n    @Override\n    public PrestoSelectParser createSQLSelectParser() {\n        return new PrestoSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public PGSelectStatement parseSelect() {\n        PrestoSelectParser selectParser = createSQLSelectParser();\n        SQLSelect select = selectParser.select();\n        return new PGSelectStatement(select);\n    }\n\n    @Override\n    protected void parseInsertColumns(SQLInsertInto insert) {\n        if (lexer.token() == Token.RPAREN) {\n            return;\n        }\n\n        for (; ; ) {\n            SQLName expr = this.exprParser.name();\n            expr.setParent(insert);\n            insert.getColumns().add(expr);\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                String text = lexer.stringVal();\n                if (text.equalsIgnoreCase(\"TINYINT\")\n                        || text.equalsIgnoreCase(\"BIGINT\")\n                        || text.equalsIgnoreCase(\"INTEGER\")\n                        || text.equalsIgnoreCase(\"DOUBLE\")\n                        || text.equalsIgnoreCase(\"DATE\")\n                        || text.equalsIgnoreCase(\"VARCHAR\")) {\n                    expr.getAttributes().put(\"dataType\", text);\n                    lexer.nextToken();\n                } else if (text.equalsIgnoreCase(\"CHAR\")) {\n                    String dataType = text;\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    SQLExpr char_len = this.exprParser.primary();\n                    accept(Token.RPAREN);\n                    dataType += (\"(\" + char_len.toString() + \")\");\n                    expr.getAttributes().put(\"dataType\", dataType);\n                }\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    @Override\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new PrestoCreateTableParser(this.exprParser);\n    }\n\n    protected SQLStatement parseAlterFunction() {\n        accept(Token.ALTER);\n        accept(Token.FUNCTION);\n\n        PrestoAlterFunctionStatement stmt = new PrestoAlterFunctionStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n\n        /*\n         * 因支持写函数参数项，名称处理\n         * ALTER FUNCTION qualified_function_name [ ( parameter_type[, ...] ) ]\n         * RETURNS NULL ON NULL INPUT | CALLED ON NULL INPUT\n         */\n        if (lexer.token() == Token.LPAREN) {\n            StringBuilder needAppendName = new StringBuilder();\n            needAppendName.append(\"(\");\n            for (; ; ) {\n                lexer.nextToken();\n                needAppendName.append(lexer.stringVal());\n\n                lexer.nextToken();\n                if (lexer.token() == Token.RPAREN) {\n                    break;\n                }\n\n                // 处理fn(a, )\n                if (lexer.token() == Token.COMMA) {\n                    needAppendName.append(\",\");\n                    Lexer.SavePoint mark = lexer.mark();\n\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.RPAREN) {\n                        setErrorEndPos(lexer.pos());\n                        throw new ParserException(\"syntax error, actual \" + lexer.token() + \", \" + lexer.info());\n                    }\n                    lexer.reset(mark);\n                }\n            }\n            accept(Token.RPAREN);\n            needAppendName.append(\")\");\n\n            if (needAppendName.length() > 0) {\n                if (name instanceof SQLPropertyExpr) {\n                    SQLPropertyExpr sqlPropertyExpr = (SQLPropertyExpr) name;\n                    sqlPropertyExpr.setName(sqlPropertyExpr.getName() + needAppendName);\n                } else if (name instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr sqlIdentifierExpr = (SQLIdentifierExpr) name;\n                    sqlIdentifierExpr.setName(sqlIdentifierExpr.getName() + needAppendName);\n                }\n            }\n        }\n        stmt.setName(name);\n\n        if (lexer.identifierEquals(\"CALLED\")) {\n            lexer.nextToken();\n            stmt.setCalledOnNullInput(true);\n        } else if (lexer.identifierEquals(\"RETURNS\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULL\");\n            stmt.setCalledOnNullInput(true);\n        } else {\n            setErrorEndPos(lexer.pos());\n            throw new ParserException(\"syntax error, actual \" + lexer.token() + \", \" + lexer.info());\n        }\n        accept(Token.ON);\n        accept(Token.NULL);\n        acceptIdentifier(\"INPUT\");\n        return stmt;\n    }\n\n    @Override\n    protected SQLStatement alterSchema() {\n        accept(Token.ALTER);\n        accept(Token.SCHEMA);\n\n        PrestoAlterSchemaStatement stmt = new PrestoAlterSchemaStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setSchemaName(name);\n\n        acceptIdentifier(\"RENAME\");\n        accept(Token.TO);\n\n        stmt.setNewName(this.exprParser.identifier());\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseInsert() {\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n\n            HiveMultiInsertStatement stmt = new HiveMultiInsertStatement();\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                SQLName tableName = this.exprParser.name();\n                SQLExprTableSource from = new SQLExprTableSource(tableName);\n                SQLTableSource tableSource = createSQLSelectParser().parseTableSourceRest(from);\n                stmt.setFrom(tableSource);\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    from.setAlias(lexer.stringVal());\n                    lexer.nextToken();\n                }\n            } else {\n                accept(Token.LPAREN);\n\n                SQLSelectParser selectParser = createSQLSelectParser();\n                SQLSelect select = selectParser.select();\n\n                accept(Token.RPAREN);\n\n                String alias = lexer.stringVal();\n                accept(Token.IDENTIFIER);\n\n                SQLTableSource from = new SQLSubqueryTableSource(select, alias);\n\n                switch (lexer.token()) {\n                    case LEFT:\n                    case RIGHT:\n                    case FULL:\n                    case JOIN:\n                        from = selectParser.parseTableSourceRest(from);\n                        break;\n                    default:\n                        break;\n                }\n\n                stmt.setFrom(from);\n            }\n\n            for (; ; ) {\n                HiveInsert insert = parseHiveInsert();\n                stmt.addItem(insert);\n\n                if (lexer.token() != Token.INSERT) {\n                    break;\n                }\n            }\n\n            return stmt;\n        }\n\n        return parseHiveInsertStmt();\n    }\n\n    @Override\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.identifierEquals(\"PREPARE\")) {\n            PrestoPrepareStatement stmt = parsePrepare();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"EXECUTE\")) {\n            acceptIdentifier(\"EXECUTE\");\n\n            if (lexer.identifierEquals(\"IMMEDIATE\")) {\n                acceptIdentifier(\"IMMEDIATE\");\n            }\n\n            PrestoExecuteStatement stmt = parseExecute();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"DEALLOCATE\")) {\n            MysqlDeallocatePrepareStatement stmt = parseDeallocatePrepare();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SHOW)) {\n            Lexer.SavePoint savePoint = this.lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.VIEWS)) {\n                lexer.nextToken();\n\n                SQLShowViewsStatement stmt = new SQLShowViewsStatement();\n                if (lexer.token() == Token.IN) {\n                    lexer.nextToken();\n                    SQLName db = this.exprParser.name();\n                    stmt.setDatabase(db);\n                }\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextToken();\n                    SQLExpr pattern = this.exprParser.expr();\n                    stmt.setLike(pattern);\n                }\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.TABLES)) {\n                lexer.reset(savePoint);\n                SQLStatement stmt = this.parseShowTables();\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.DATABASES)\n                || lexer.identifierEquals(Constants.SCHEMAS)) {\n                lexer.nextToken();\n\n                SQLShowDatabasesStatement stmt = parseShowDatabases(false);\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.token() == Token.INDEX) {\n                lexer.nextToken();\n                SQLShowIndexesStatement stmt = new SQLShowIndexesStatement();\n                stmt.setType(\"INDEX\");\n\n                if (lexer.token() == Token.ON) {\n                    lexer.nextToken();\n                    SQLName table = exprParser.name();\n                    stmt.setTable(table);\n                }\n\n                if (lexer.token() == Token.HINT) {\n                    stmt.setHints(this.exprParser.parseHints());\n                }\n\n                statementList.add(stmt);\n\n                return true;\n            }\n\n            if (lexer.token() == Token.CREATE) {\n                Lexer.SavePoint savePointCreateTable = this.lexer.mark();\n                lexer.nextToken();\n                if (lexer.token() == Token.TABLE) {\n                    lexer.reset(savePointCreateTable);\n                    SQLShowCreateTableStatement stmt = parseShowCreateTable();\n\n                    statementList.add(stmt);\n                    return true;\n                }\n                if (lexer.token() == Token.VIEW) {\n                    lexer.nextToken();\n                    SQLShowCreateViewStatement stmt = new SQLShowCreateViewStatement();\n                    SQLName view = exprParser.name();\n                    stmt.setName(view);\n                    statementList.add(stmt);\n                    return true;\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {\n                lexer.nextToken();\n\n                SQLShowPartitionsStmt stmt = new SQLShowPartitionsStmt();\n\n                if (lexer.token() == Token.FROM) {\n                    lexer.nextToken();\n                }\n                SQLExpr expr = this.exprParser.expr();\n                stmt.setTableSource(new SQLExprTableSource(expr));\n\n                if (lexer.token() == Token.PARTITION) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    parseAssignItems(stmt.getPartition(), stmt, false);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    stmt.setWhere(\n                        this.exprParser.expr()\n                    );\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.COLUMNS)) {\n                lexer.nextToken();\n\n                SQLShowColumnsStatement stmt = new SQLShowColumnsStatement();\n\n                if (lexer.token() == Token.FROM || lexer.token() == Token.IN) {\n                    lexer.nextToken();\n                    SQLName table = exprParser.name();\n                    if (lexer.token() == Token.SUB && table instanceof SQLIdentifierExpr) {\n                        lexer.mark();\n                        lexer.nextToken();\n                        String strVal = lexer.stringVal();\n                        lexer.nextToken();\n                        if (table instanceof SQLIdentifierExpr) {\n                            SQLIdentifierExpr ident = (SQLIdentifierExpr) table;\n                            table = new SQLIdentifierExpr(ident.getName() + \"-\" + strVal);\n                        }\n                    }\n                    stmt.setTable(table);\n                }\n\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextToken();\n                    SQLExpr like = exprParser.expr();\n                    stmt.setLike(like);\n                }\n\n                if (lexer.token() == Token.WHERE) {\n                    lexer.nextToken();\n                    SQLExpr where = exprParser.expr();\n                    stmt.setWhere(where);\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n            if (lexer.identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n                lexer.nextToken();\n\n                SQLShowFunctionsStatement stmt = new SQLShowFunctionsStatement();\n                if (lexer.token() == Token.LIKE) {\n                    lexer.nextToken();\n                    SQLExpr like = this.exprParser.expr();\n                    stmt.setLike(like);\n                }\n\n                statementList.add(stmt);\n                return true;\n            }\n\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n        return false;\n    }\n\n    public PrestoPrepareStatement parsePrepare() {\n        acceptIdentifier(\"PREPARE\");\n\n        SQLName name = exprParser.name();\n        accept(Token.FROM);\n        PrestoPrepareStatement stmt = new PrestoPrepareStatement(name);\n\n        if (lexer.token() == Token.SELECT) {\n            SQLSelect select = createSQLSelectParser().select();\n            stmt.setSelect(select);\n        } else if (lexer.token() == Token.INSERT) {\n            SQLStatement sqlStatement = parseInsert();\n            stmt.setInsert((HiveInsertStatement) sqlStatement);\n        }\n        return stmt;\n    }\n\n    public PrestoExecuteStatement parseExecute() {\n        PrestoExecuteStatement stmt = new PrestoExecuteStatement();\n\n        SQLName statementName = exprParser.name();\n        stmt.setStatementName(statementName);\n\n        if (lexer.identifierEquals(\"USING\")) {\n            lexer.nextToken();\n            exprParser.exprList(stmt.getParameters(), stmt);\n        } else if (lexer.token() == Token.IDENTIFIER) {\n            exprParser.exprList(stmt.getParameters(), stmt);\n        }\n        return stmt;\n    }\n\n    public MysqlDeallocatePrepareStatement parseDeallocatePrepare() {\n        acceptIdentifier(\"DEALLOCATE\");\n        acceptIdentifier(\"PREPARE\");\n\n        MysqlDeallocatePrepareStatement stmt = new MysqlDeallocatePrepareStatement();\n        SQLName statementName = exprParser.name();\n        stmt.setStatementName(statementName);\n\n        return stmt;\n    }\n\n    @Override\n    public void parseCreateTableSupportSchema() {\n        if (lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n    }\n\n    @Override\n    public void parseExplainFormatType(SQLExplainStatement explain) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"FORMAT\")) {\n                lexer.nextToken();\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"TYPE\")) {\n                lexer.nextToken();\n                lexer.nextToken();\n            }\n\n            accept(Token.RPAREN);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/visitor/PrestoASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.presto.visitor;\n\nimport com.alibaba.druid.sql.dialect.presto.ast.PrestoColumnWith;\nimport com.alibaba.druid.sql.dialect.presto.ast.PrestoDateTimeExpr;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoAlterFunctionStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoAlterSchemaStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoDeallocatePrepareStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoExecuteStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoPrepareStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface PrestoASTVisitor extends SQLASTVisitor {\n    default boolean visit(PrestoCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(PrestoCreateTableStatement x) {\n    }\n\n    default boolean visit(PrestoAlterFunctionStatement x) {\n        return true;\n    }\n\n    default void endVisit(PrestoAlterFunctionStatement x) {\n    }\n\n    default boolean visit(PrestoAlterSchemaStatement x) {\n        return true;\n    }\n\n    default void endVisit(PrestoAlterSchemaStatement x) {\n    }\n\n    default boolean visit(PrestoPrepareStatement x) {\n        return true;\n    }\n\n    default void endVisit(PrestoPrepareStatement x) {\n    }\n\n    default boolean visit(PrestoExecuteStatement x) {\n        return true;\n    }\n\n    default void endVisit(PrestoExecuteStatement x) {\n    }\n\n    default boolean visit(PrestoDeallocatePrepareStatement x) {\n        return true;\n    }\n\n    default void endVisit(PrestoDeallocatePrepareStatement x) {\n    }\n\n    default boolean visit(PrestoColumnWith x) { return true; }\n\n    default void endVisit(PrestoColumnWith x) {\n    }\n\n    default boolean visit(PrestoDateTimeExpr x) {\n        return true;\n    }\n\n    default void endVisit(PrestoDateTimeExpr x) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/presto/visitor/PrestoOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.presto.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.expr.SQLArrayExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLDecimalExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.presto.Presto;\nimport com.alibaba.druid.sql.dialect.presto.ast.PrestoColumnWith;\nimport com.alibaba.druid.sql.dialect.presto.ast.PrestoDateTimeExpr;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoAlterFunctionStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoAlterSchemaStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoDeallocatePrepareStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoExecuteStatement;\nimport com.alibaba.druid.sql.dialect.presto.ast.stmt.PrestoPrepareStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\nimport java.math.BigDecimal;\n\n/**\n * presto 的输出的视图信息\n *\n * @author zhangcanlong\n * @since 2022-01-07\n */\npublic class PrestoOutputVisitor extends SQLASTOutputVisitor implements PrestoASTVisitor {\n    public PrestoOutputVisitor(StringBuilder appender) {\n        this(appender, DbType.presto);\n    }\n\n    public PrestoOutputVisitor(StringBuilder appender, DbType dbType) {\n        super(appender, dbType, Presto.DIALECT);\n    }\n\n    public PrestoOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect) {\n        super(appender, dbType, dialect);\n    }\n\n    public PrestoOutputVisitor(StringBuilder appender, boolean parameterized) {\n        this(appender, DbType.presto, Presto.DIALECT, parameterized);\n    }\n\n    public PrestoOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect, boolean parameterized) {\n        super(appender, dbType, dialect, parameterized);\n    }\n\n    @Override\n    public boolean visit(SQLLimit x) {\n        if (x.getOffset() != null) {\n            this.print0(this.ucase ? \" OFFSET \" : \" offset \");\n            x.getOffset().accept(this);\n        }\n        this.print0(this.ucase ? \" LIMIT \" : \" limit \");\n        x.getRowCount().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLDecimalExpr x) {\n        BigDecimal value = x.getValue();\n        print0(ucase ? \"DECIMAL '\" : \"decimal '\");\n        print(value.toString());\n        print('\\'');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        /*\n            https://prestodb.io/docs/current/sql/create-table.html\n            CREATE TABLE [ IF NOT EXISTS ]\n            table_name (\n              { column_name data_type [ COMMENT comment ] [ WITH ( property_name = expression [, ...] ) ]\n              | LIKE existing_table_name [ { INCLUDING | EXCLUDING } PROPERTIES ] }\n              [, ...]\n            )\n            [ COMMENT table_comment ]\n            [ WITH ( property_name = expression [, ...] ) ]\n\n            https://prestodb.io/docs/current/sql/create-table-as.html\n            CREATE TABLE [ IF NOT EXISTS ] table_name [ ( column_alias, ... ) ]\n            [ COMMENT table_comment ]\n            [ WITH ( property_name = expression [, ...] ) ]\n            AS query\n            [ WITH [ NO ] DATA ]\n         */\n\n        printCreateTable(x, false);\n        printTableOptions(x);\n        printSelectAs(x, true);\n        return false;\n    }\n\n    @Override\n    protected void printTableOption(SQLExpr name, SQLExpr value, int index) {\n        if (index != 0) {\n            print(\",\");\n            println();\n        }\n        String key = name.toString();\n        print0(key);\n        print0(\" = \");\n        value.accept(this);\n    }\n\n    @Override\n    public boolean visit(PrestoAlterFunctionStatement x) {\n        print0(ucase ? \"ALTER FUNCTION \" : \"alter function \");\n        x.getName().accept(this);\n\n        if (x.isCalledOnNullInput()) {\n            print0(\" CALLED ON NULL INPUT\");\n        }\n\n        if (x.isReturnsNullOnNullInput()) {\n            print0(\" RETURNS NULL ON NULL INPUT\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(PrestoAlterSchemaStatement x) {\n        print0(ucase ? \"ALTER SCHEMA \" : \"alter achema \");\n        x.getSchemaName().accept(this);\n\n        print0(ucase ? \" RENAME TO \" : \" rename to \");\n        x.getNewName().accept(this);\n        return false;\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        print0(ucase ? \"WITH (\" : \"with (\");\n        incrementIndent();\n        println();\n    }\n\n    @Override\n    public boolean visit(SQLArrayExpr x) {\n        print0(ucase ? \"ARRAY[\" : \"array[\");\n        printAndAccept(x.getValues(), \", \");\n        print(']');\n        return false;\n    }\n\n    @Override\n    public boolean visit(PrestoPrepareStatement x) {\n        print0(ucase ? \"PREPARE \" : \"prepare \");\n        x.getName().accept(this);\n        print0(ucase ? \" FROM \" : \" from \");\n        if (x.getSelect() != null) {\n            x.getSelect().accept(this);\n        } else if (x.getInsert() != null) {\n            x.getInsert().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(PrestoExecuteStatement x) {\n        print0(ucase ? \"EXECUTE \" : \"execute \");\n        x.getStatementName().accept(this);\n        if (x.getParameters().size() > 0) {\n            print0(ucase ? \" USING \" : \" using \");\n            printAndAccept(x.getParameters(), \", \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(PrestoDeallocatePrepareStatement x) {\n        print0(ucase ? \"DEALLOCATE PREPARE \" : \"deallocate prepare \");\n        x.getStatementName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(PrestoColumnWith x) {\n        print0(ucase ? \"WITH(\" : \"with(\");\n        printAndAccept(x.getProperties(), \",\");\n        print0(\")\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(PrestoDateTimeExpr x) {\n        x.getExpr().accept(this);\n        SQLExpr timeZone = x.getTimeZone();\n        print0(ucase ? \" AT TIME ZONE \" : \" at time zone \");\n        timeZone.accept(this);\n        return false;\n    }\n\n    public void printArrayExprPrefix() {\n        print0(ucase ? \"ARRAY\" : \"array\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/Redshift.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Redshift {\n    public static final SQLDialect dialect = SQLDialect.of(DbType.redshift);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/parser/RedshiftCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGCreateTableParser;\nimport com.alibaba.druid.sql.dialect.redshift.stmt.RedshiftCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.redshift.stmt.RedshiftSortKey;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.List;\npublic class RedshiftCreateTableParser\n        extends PGCreateTableParser {\n    public RedshiftCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.redshift;\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        List<String> comments = null;\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            comments = lexer.readAndResetComments();\n        }\n\n        RedshiftCreateTableStatement createTable = new RedshiftCreateTableStatement();\n        if (comments != null) {\n            createTable.addBeforeComment(comments);\n        }\n\n        createTable.setDbType(dbType);\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            createTable.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        accept(Token.CREATE);\n        createTableBefore(createTable);\n        accept(Token.TABLE);\n        createTableBeforeName(createTable);\n        createTable.setName(\n                this.exprParser.name());\n        createTableAfterName(createTable);\n        createTableBody(createTable);\n        createTableQuery(createTable);\n        parseCreateTableRest(createTable);\n\n        return createTable;\n    }\n\n    @Override\n    public void parseCreateTableRest(SQLCreateTableStatement createTable) {\n        if (createTable instanceof RedshiftCreateTableStatement) {\n            RedshiftCreateTableStatement redshiftCreateTableStatement = (RedshiftCreateTableStatement) createTable;\n            if (lexer.nextIf(Token.BACKUP)) {\n                redshiftCreateTableStatement.setBackup(this.exprParser.expr());\n            }\n            if (lexer.nextIf(Token.DISTSTYLE)) {\n                if (lexer.token() == Token.EVEN || lexer.token() == Token.KEY || lexer.token() == Token.AUTO || lexer.token() == Token.ALL) {\n                    redshiftCreateTableStatement.setDistStyle(new SQLIdentifierExpr(lexer.token().name));\n                    lexer.nextToken();\n                } else {\n                    throw new IllegalArgumentException();\n                }\n            }\n\n            if (lexer.nextIf(Token.DISTKEY)) {\n                accept(Token.LPAREN);\n                redshiftCreateTableStatement.setDistKey(this.exprParser.expr());\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.COMPOUND || lexer.token() == Token.INTERLEAVED) {\n                RedshiftSortKey sortKey = new RedshiftSortKey();\n                sortKey.setCompound(lexer.token() == Token.COMPOUND);\n                sortKey.setInterleaved(lexer.token() == Token.INTERLEAVED);\n                lexer.nextToken();\n                accept(Token.SORTKEY);\n                accept(Token.LPAREN);\n                for (;;) {\n                    sortKey.addColumn(this.exprParser.expr());\n                    if (!lexer.nextIf(Token.COMMA)) {\n                        break;\n                    }\n                }\n                accept(Token.RPAREN);\n                redshiftCreateTableStatement.setSortKey(sortKey);\n            } else if (lexer.nextIf(Token.SORTKEY)) {\n                RedshiftSortKey sortKey = new RedshiftSortKey();\n                if (lexer.nextIf(Token.AUTO)) {\n                    sortKey.setAuto(true);\n                } else if (lexer.nextIf(Token.LPAREN)) {\n                    for (;;) {\n                        sortKey.addColumn(this.exprParser.expr());\n                        if (!lexer.nextIf(Token.COMMA)) {\n                            break;\n                        }\n                    }\n                    accept(Token.RPAREN);\n                }\n                redshiftCreateTableStatement.setSortKey(sortKey);\n            }\n\n            if (lexer.nextIf(Token.ENCODE)) {\n                accept(Token.AUTO);\n                redshiftCreateTableStatement.setEncodeAuto(true);\n            }\n        } else {\n            super.parseCreateTableRest(createTable);\n        }\n    }\n\n    @Override\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        if (lexer.nextIfIdentifier(\"TEMPORARY\") || lexer.nextIfIdentifier(\"TEMP\")) {\n            createTable.config(SQLCreateTableStatement.Feature.Temporary);\n        }\n        super.createTableBefore(createTable);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/parser/RedshiftExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser;\nimport com.alibaba.druid.sql.dialect.redshift.stmt.RedshiftColumnEncode;\nimport com.alibaba.druid.sql.dialect.redshift.stmt.RedshiftColumnKey;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class RedshiftExprParser\n        extends PGExprParser {\n    public RedshiftExprParser(String sql, SQLParserFeature... features) {\n        super(new RedshiftLexer(sql, features));\n        lexer.nextToken();\n        dbType = DbType.redshift;\n    }\n\n    public RedshiftExprParser(Lexer lexer) {\n        super(lexer);\n        dbType = DbType.redshift;\n    }\n\n    @Override\n    protected SQLColumnDefinition parseColumnSpecific(SQLColumnDefinition column) {\n        switch (lexer.token()) {\n            case ENCODE: {\n                lexer.nextToken();\n                SQLExpr codecExpr;\n                if (lexer.token() == Token.AUTO) {\n                    codecExpr = new SQLIdentifierExpr(\"AUTO\");\n                    lexer.nextToken();\n                } else {\n                    codecExpr = expr();\n                }\n                RedshiftColumnEncode sqlColumnEncode = new RedshiftColumnEncode();\n                sqlColumnEncode.setExpr(codecExpr);\n                column.addConstraint(sqlColumnEncode);\n                return parseColumnRest(column);\n            }\n            case SORTKEY:\n            case DISTKEY:\n                RedshiftColumnKey key = new RedshiftColumnKey();\n                if (lexer.token() == Token.DISTKEY) {\n                    key.setDistKey(true);\n                } else {\n                    key.setSortKey(true);\n                }\n                lexer.nextToken();\n                column.addConstraint(key);\n                return parseColumnRest(column);\n            case IDENTITY:\n                lexer.nextToken();\n                SQLColumnDefinition.Identity identity = parseIdentity();\n                column.setIdentity(identity);\n                return parseColumnRest(column);\n            default:\n                return column;\n        }\n    }\n\n    @Override\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)) {\n            lexer.nextToken();\n            accept(Token.BY);\n            accept(Token.DEFAULT);\n            accept(Token.AS);\n            accept(Token.IDENTITY);\n            SQLColumnDefinition.Identity id = parseIdentity();\n            column.setGeneratedAlwaysAs(id);\n        } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            column.setCollateExpr(expr());\n        }\n        return super.parseColumnRest(column);\n    }\n\n    @Override\n    protected SQLColumnDefinition.Identity parseIdentity() {\n        accept(Token.LPAREN);\n        SQLColumnDefinition.Identity ident = new SQLColumnDefinition.Identity();\n        parseIdentifySpecific();\n        if (lexer.token() == Token.LITERAL_INT) {\n            ident.setSeed(lexer.integerValue().intValue());\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"TODO : \" + lexer.info());\n        }\n\n        if (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n            if (lexer.token() == Token.LITERAL_INT) {\n                ident.setIncrement(lexer.integerValue().intValue());\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"TODO : \" + lexer.info());\n            }\n        }\n\n        accept(Token.RPAREN);\n        return ident;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/parser/RedshiftLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGLexer;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class RedshiftLexer\n        extends PGLexer {\n    static final Keywords REDSHIFT_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"CASCADE\", Token.CASCADE);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"CURRENT\", Token.CURRENT);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"NEXT\", Token.NEXT);\n        map.put(\"NOWAIT\", Token.NOWAIT);\n        map.put(\"OF\", Token.OF);\n\n        map.put(\"OFFSET\", Token.OFFSET);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"RECURSIVE\", Token.RECURSIVE);\n        map.put(\"RESTART\", Token.RESTART);\n\n        map.put(\"RESTRICT\", Token.RESTRICT);\n        map.put(\"RETURNING\", Token.RETURNING);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"ROWS\", Token.ROWS);\n        map.put(\"SHARE\", Token.SHARE);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"START\", Token.START);\n\n        map.put(\"USING\", Token.USING);\n        map.put(\"WINDOW\", Token.WINDOW);\n\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"ARRAY\", Token.ARRAY);\n        map.put(\"IF\", Token.IF);\n        map.put(\"TYPE\", Token.TYPE);\n        map.put(\"ILIKE\", Token.ILIKE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"INTERVAL\", Token.INTERVAL);\n        map.put(\"LANGUAGE\", Token.LANGUAGE);\n        map.put(\"LOCAL\", Token.LOCAL);\n        map.put(\"TOP\", Token.TOP);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n        map.put(\"TABLE\", Token.TABLE);\n        map.put(\"ENCODE\", Token.ENCODE);\n        map.put(\"DISTSTYLE\", Token.DISTSTYLE);\n        map.put(\"AUTO\", Token.AUTO);\n        map.put(\"EVEN\", Token.EVEN);\n        map.put(\"KEY\", Token.KEY);\n        map.put(\"ALL\", Token.ALL);\n        map.put(\"DISTKEY\", Token.DISTKEY);\n        map.put(\"COMPOUND\", Token.COMPOUND);\n        map.put(\"INTERLEAVED\", Token.INTERLEAVED);\n        map.put(\"SORTKEY\", Token.SORTKEY);\n        map.put(\"BACKUP\", Token.BACKUP);\n\n        REDSHIFT_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return REDSHIFT_KEYWORDS;\n    }\n\n    public RedshiftLexer(String input, SQLParserFeature... features) {\n        super(input, features);\n        dbType = DbType.redshift;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/parser/RedshiftSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSelectParser;\nimport com.alibaba.druid.sql.dialect.redshift.stmt.RedshiftSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class RedshiftSelectParser\n        extends PGSelectParser {\n    public RedshiftSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.redshift;\n    }\n\n    protected RedshiftExprParser createExprParser() {\n        return new RedshiftExprParser(lexer);\n    }\n\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            accept(Token.RPAREN);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        RedshiftSelectQueryBlock queryBlock = new RedshiftSelectQueryBlock();\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.TOP) {\n                SQLTop top = this.createExprParser().parseTop();\n                queryBlock.setTop(top);\n            }\n\n            if (lexer.token() == Token.DISTINCT) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.ALL) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                lexer.nextToken();\n            }\n\n            parseSelectList(queryBlock);\n        }\n\n        parseInto(queryBlock);\n\n        parseFrom(queryBlock);\n\n        //TODO(lingo): Support oracle-style outer join, see https://docs.aws.amazon.com/redshift/latest/dg/r_WHERE_oracle_outer.html\n        parseWhere(queryBlock);\n\n        parseHierachical(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        qualify(queryBlock);\n\n        parseSortBy(queryBlock);\n\n        parseFetchClause(queryBlock);\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    protected void parseInto(RedshiftSelectQueryBlock queryBlock) {\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n            if (lexer.nextIfIdentifier(\"TEMP\")) {\n                queryBlock.setInsertTemp(true);\n            }\n\n            if (lexer.nextIfIdentifier(\"TEMPORARY\")) {\n                queryBlock.setInsertTemporary(true);\n            }\n\n            if (lexer.nextIf(Token.TABLE)) {\n                queryBlock.setInsertTable(true);\n            }\n\n            SQLTableSource into = this.parseTableSource();\n            queryBlock.setInto((SQLExprTableSource) into);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/parser/RedshiftStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class RedshiftStatementParser\n        extends PGSQLStatementParser {\n    public RedshiftStatementParser(RedshiftExprParser parser) {\n        super(parser);\n        dbType = DbType.redshift;\n    }\n\n    public RedshiftStatementParser(String sql, SQLParserFeature... features) {\n        this(new RedshiftExprParser(sql, features));\n    }\n\n    @Override\n    public RedshiftSelectParser createSQLSelectParser() {\n        return new RedshiftSelectParser(this.exprParser, selectListCache);\n    }\n\n    public RedshiftCreateTableParser getSQLCreateTableParser() {\n        return new RedshiftCreateTableParser(this.exprParser);\n    }\n\n    protected void createOptionSkip() {\n        lexer.nextIf(Token.LOCAL);\n        super.createOptionSkip();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftColumnConstraint.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLConstraintImpl;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class RedshiftColumnConstraint extends SQLConstraintImpl implements SQLColumnConstraint {\n    public RedshiftColumnConstraint() {\n        dbType = DbType.redshift;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor v) {}\n\n    @Override\n    public RedshiftColumnConstraint clone() {\n        RedshiftColumnConstraint redshiftColumnConstraint = new RedshiftColumnConstraint();\n        cloneTo(redshiftColumnConstraint);\n        return redshiftColumnConstraint;\n    }\n\n    public void cloneTo(RedshiftColumnConstraint x) {\n        super.cloneTo(x);\n        x.dbType = dbType;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftColumnEncode.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class RedshiftColumnEncode extends RedshiftColumnConstraint {\n    private SQLExpr expr;\n    public RedshiftColumnEncode() {\n        super();\n    }\n    public SQLExpr getExpr() {\n        return expr;\n    }\n\n    public void setExpr(SQLExpr expr) {\n        this.expr = expr;\n    }\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof RedshiftASTVisitor) {\n            RedshiftASTVisitor vv = (RedshiftASTVisitor) v;\n            if (vv.visit(this)) {\n                acceptChild(vv, expr);\n            }\n            vv.endVisit(this);\n        }\n    }\n\n    @Override\n    public RedshiftColumnEncode clone() {\n        RedshiftColumnEncode redshiftColumnEncode = new RedshiftColumnEncode();\n        super.cloneTo(redshiftColumnEncode);\n        redshiftColumnEncode.setExpr(expr.clone());\n        return redshiftColumnEncode;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftColumnKey.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class RedshiftColumnKey extends RedshiftColumnConstraint {\n    private boolean isDistKey;\n    private boolean isSortKey;\n\n    public boolean isDistKey() {\n        return isDistKey;\n    }\n\n    public void setDistKey(boolean distKey) {\n        isDistKey = distKey;\n    }\n\n    public boolean isSortKey() {\n        return isSortKey;\n    }\n\n    public void setSortKey(boolean sortKey) {\n        isSortKey = sortKey;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof RedshiftASTVisitor) {\n            ((RedshiftASTVisitor) v).visit(this);\n            ((RedshiftASTVisitor) v).endVisit(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class RedshiftCreateTableStatement extends SQLCreateTableStatement implements RedshiftObject {\n    private SQLExpr distStyle;\n    private SQLExpr distKey;\n    private SQLExpr backup;\n    private RedshiftSortKey sortKey;\n    private boolean encodeAuto;\n\n    public RedshiftCreateTableStatement() {\n        super(DbType.redshift);\n        encodeAuto = false;\n    }\n\n    public SQLExpr getDistStyle() {\n        return distStyle;\n    }\n\n    public void setDistStyle(SQLExpr distStyle) {\n        if (distStyle != null) {\n            distStyle.setParent(this);\n        }\n        this.distStyle = distStyle;\n    }\n\n    public SQLExpr getDistKey() {\n        return distKey;\n    }\n\n    public void setDistKey(SQLExpr distKey) {\n        if (distKey != null) {\n            distKey.setParent(this);\n        }\n        this.distKey = distKey;\n    }\n\n    public RedshiftSortKey getSortKey() {\n        return sortKey;\n    }\n\n    public void setSortKey(RedshiftSortKey sortKey) {\n        if (sortKey != null) {\n            sortKey.setParent(this);\n        }\n        this.sortKey = sortKey;\n    }\n\n    public boolean isEncodeAuto() {\n        return encodeAuto;\n    }\n\n    public void setEncodeAuto(boolean encodeAuto) {\n        this.encodeAuto = encodeAuto;\n    }\n\n    public SQLExpr getBackup() {\n        return backup;\n    }\n\n    public void setBackup(SQLExpr backup) {\n        if (backup != null) {\n            backup.setParent(this);\n        }\n        this.backup = backup;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof RedshiftASTVisitor) {\n            accept0((RedshiftASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(RedshiftASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.backup);\n            acceptChild(visitor, this.distStyle);\n            acceptChild(visitor, this.distKey);\n            acceptChild(visitor, this.sortKey);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftObject.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface RedshiftObject extends SQLObject {\n    default void accept0(SQLASTVisitor v) {\n        if (v instanceof RedshiftASTVisitor) {\n            accept0((RedshiftASTVisitor) v);\n        }\n    }\n    void accept0(RedshiftASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftObjectImpl.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftASTVisitor;\n\npublic abstract class RedshiftObjectImpl extends SQLObjectImpl implements RedshiftObject {\n    public abstract void accept0(RedshiftASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftSelectQueryBlock.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class RedshiftSelectQueryBlock extends SQLSelectQueryBlock {\n    private SQLTop top;\n    private boolean insertTable;\n    private boolean insertTemp;\n    private boolean insertTemporary;\n\n    public RedshiftSelectQueryBlock() {\n        super(DbType.redshift);\n        insertTable = false;\n        insertTemp = false;\n        insertTemporary = false;\n    }\n\n    public SQLTop getTop() {\n        return top;\n    }\n\n    public void setTop(SQLTop top) {\n        if (top != null) {\n            top.setParent(this);\n        }\n        this.top = top;\n    }\n\n    public boolean isInsertTable() {\n        return insertTable;\n    }\n\n    public void setInsertTable(boolean insertTable) {\n        this.insertTable = insertTable;\n    }\n\n    public boolean isInsertTemp() {\n        return insertTemp;\n    }\n\n    public void setInsertTemp(boolean insertTemp) {\n        this.insertTemp = insertTemp;\n    }\n\n    public boolean isInsertTemporary() {\n        return insertTemporary;\n    }\n\n    public void setInsertTemporary(boolean insertTemporary) {\n        this.insertTemporary = insertTemporary;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof RedshiftASTVisitor) {\n            accept0((RedshiftASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(RedshiftASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.top);\n            acceptChild(visitor, this.selectList);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.groupBy);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/stmt/RedshiftSortKey.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.redshift.visitor.RedshiftASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class RedshiftSortKey extends RedshiftObjectImpl {\n    private boolean compound;\n    private boolean interleaved;\n    private boolean auto;\n    private List<SQLExpr> columns;\n\n    public RedshiftSortKey() {\n        compound = false;\n        interleaved = false;\n        auto = false;\n        columns = new ArrayList<>();\n    }\n\n    public boolean isCompound() {\n        return compound;\n    }\n\n    public void setCompound(boolean compound) {\n        this.compound = compound;\n    }\n\n    public boolean isInterleaved() {\n        return interleaved;\n    }\n\n    public void setInterleaved(boolean interleaved) {\n        this.interleaved = interleaved;\n    }\n\n    public boolean isAuto() {\n        return auto;\n    }\n\n    public void setAuto(boolean auto) {\n        this.auto = auto;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public void addColumn(SQLExpr sqlExpr) {\n        if (sqlExpr != null) {\n            sqlExpr.setParent(this);\n            columns.add(sqlExpr);\n        }\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof RedshiftASTVisitor) {\n            accept0((RedshiftASTVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(RedshiftASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, columns);\n            visitor.endVisit(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/visitor/RedshiftASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.visitor;\n\nimport com.alibaba.druid.sql.dialect.redshift.stmt.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface RedshiftASTVisitor extends SQLASTVisitor {\n    default boolean visit(RedshiftSelectQueryBlock x) {\n        return true;\n    }\n    default void endVisit(RedshiftSelectQueryBlock x) {}\n    default boolean visit(RedshiftSortKey x) {\n        return true;\n    }\n    default void endVisit(RedshiftSortKey x) {}\n    default boolean visit(RedshiftCreateTableStatement x) {\n        return true;\n    }\n    default void endVisit(RedshiftCreateTableStatement x) {}\n    default boolean visit(RedshiftColumnEncode x) { return true; }\n    default void endVisit(RedshiftColumnEncode x) {}\n\n    default boolean visit(RedshiftColumnKey x) {\n        return true;\n    }\n\n    default void endVisit(RedshiftColumnKey x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/redshift/visitor/RedshiftOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.redshift.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;\nimport com.alibaba.druid.sql.dialect.redshift.Redshift;\nimport com.alibaba.druid.sql.dialect.redshift.stmt.*;\n\npublic class RedshiftOutputVisitor extends PGOutputVisitor implements RedshiftASTVisitor {\n    public RedshiftOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.redshift, Redshift.dialect, parameterized);\n    }\n\n    public RedshiftOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.redshift, Redshift.dialect);\n    }\n\n    public boolean visit(RedshiftSelectQueryBlock x) {\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        SQLTop top = x.getTop();\n        if (top != null) {\n            visit(top);\n            print(' ');\n        }\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        }\n\n        printSelectList(x.getSelectList());\n        printInto(x);\n        printFrom(x);\n        printWhere(x);\n        printHierarchical(x);\n        printGroupBy(x);\n        printQualify(x);\n        printOrderBy(x);\n        printFetchFirst(x);\n        printAfterFetch(x);\n\n        return false;\n    }\n\n    @Override\n    protected void printInto(SQLSelectQueryBlock x) {\n        if (x instanceof RedshiftSelectQueryBlock) {\n            RedshiftSelectQueryBlock queryBlock = (RedshiftSelectQueryBlock) x;\n            SQLExprTableSource into = x.getInto();\n            if (into != null) {\n                println();\n                print0(ucase ? \"INTO \" : \"into \");\n                if (queryBlock.isInsertTemp()) {\n                    print0(ucase ? \"TEMP \" : \"temp \");\n                }\n                if (queryBlock.isInsertTemporary()) {\n                    print0(ucase ? \"TEMPORARY \" : \"temporary \");\n                }\n                if (queryBlock.isInsertTable()) {\n                    print0(ucase ? \"TABLE \" : \"table \");\n                }\n                into.accept(this);\n            }\n        } else {\n            super.printInto(x);\n        }\n    }\n\n    @Override\n    public boolean visit(RedshiftCreateTableStatement x) {\n        printCreateTable(x, false);\n        println();\n\n        if (x.getSelect() != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            x.getSelect().accept(this);\n        }\n\n        if (x.getBackup() != null) {\n            print0(ucase ? \"BACKUP \" : \"backup \");\n            x.getBackup().accept(this);\n            println();\n        }\n        if (x.getDistStyle() != null) {\n            print0(ucase ? \"DISTSTYLE \" : \"diststyle \");\n            x.getDistStyle().accept(this);\n            println();\n        }\n        if (x.getDistKey() != null) {\n            print0(ucase ? \"DISTKEY(\" : \"distkey(\");\n            x.getDistKey().accept(this);\n            print0(\")\");\n            println();\n        }\n        if (x.getSortKey() != null) {\n            if (x.getSortKey().isCompound()) {\n                print0(ucase ? \"COMPOUND \" : \"compound \");\n            } else if (x.getSortKey().isInterleaved()) {\n                print0(ucase ? \"INTERLEAVED \" : \"interleaved \");\n            }\n\n            if (!x.getSortKey().getColumns().isEmpty()) {\n                print0(ucase ? \"SORTKEY(\" : \"sortkey(\");\n                printAndAccept(x.getSortKey().getColumns(), \", \");\n                print0(\")\");\n            } else if (x.getSortKey().isAuto()) {\n                print0(ucase ? \"SORTKEY AUTO\" : \"sortkey auto\");\n            }\n            println();\n        }\n        if (x.isEncodeAuto()) {\n            print0(ucase ? \"ENCODE AUTO\" : \"encode auto\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(RedshiftColumnEncode x) {\n        print0(ucase ? \"ENCODE \" : \"encode \");\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(RedshiftColumnKey x) {\n        if (x.isDistKey()) {\n            print0(ucase ? \"DISTKEY\" : \"distkey\");\n        }\n        if (x.isSortKey()) {\n            print0(ucase ? \"SORTKEY\" : \"sortkey\");\n        }\n        return false;\n    }\n\n    protected void printGeneratedAlways(SQLColumnDefinition x, boolean parameterized) {\n        SQLExpr generatedAlwaysAs = x.getGeneratedAlwaysAs();\n        if (generatedAlwaysAs != null) {\n            print0(ucase ? \" GENERATED BY DEFAULT AS \" : \" generated by default as \");\n            printExpr(generatedAlwaysAs, parameterized);\n        }\n\n        SQLColumnDefinition.Identity identity = x.getIdentity();\n        if (identity != null) {\n            print(' ');\n            identity.accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLColumnDefinition.Identity x) {\n        print0(ucase ? \"IDENTITY\" : \"identity\");\n        Integer seed = x.getSeed();\n        if (seed != null) {\n            print0(\" (\");\n            print(seed);\n            print0(\", \");\n            print(x.getIncrement());\n            print(')');\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/snowflake/SnowflakeCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.snowflake;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class SnowflakeCreateTableParser extends SQLCreateTableParser {\n    public SnowflakeCreateTableParser(String sql) {\n        super(new SnowflakeExprParser(sql));\n    }\n\n    public SnowflakeCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new SnowflakeSelectParser(this.exprParser, selectListCache);\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        if (lexer.nextIf(Token.OR)) {\n            accept(Token.REPLACE);\n            createTable.config(SQLCreateTableStatement.Feature.OrReplace);\n        }\n\n        // Support LOCAL/GLOBAL keywords (compatibility)\n        if (lexer.nextIfIdentifier(\"LOCAL\") || lexer.nextIfIdentifier(\"GLOBAL\")) {\n            // consumed\n        }\n\n        // Support TRANSIENT keyword\n        if (lexer.nextIfIdentifier(\"TRANSIENT\")) {\n            createTable.putAttribute(\"TRANSIENT\", true);\n        }\n\n        // Support VOLATILE keyword\n        if (lexer.nextIfIdentifier(\"VOLATILE\")) {\n            createTable.putAttribute(\"VOLATILE\", true);\n        }\n\n        // Support TEMPORARY/TEMP keywords (as Token or identifier)\n        if (lexer.nextIf(Token.TEMPORARY)) {\n            createTable.setTemporary(true);\n        } else if (lexer.nextIfIdentifier(\"TEMPORARY\") || lexer.nextIfIdentifier(\"TEMP\")) {\n            createTable.setTemporary(true);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.EXTERNAL)) {\n            createTable.setExternal(true);\n        }\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        for (;;) {\n            if (lexer.nextIf(Token.COMMENT)) {\n                lexer.nextIf(Token.EQ);\n                SQLExpr comment = this.exprParser.expr();\n                stmt.setComment(comment);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"CLUSTER\")) {\n                accept(Token.BY);\n                accept(Token.LPAREN);\n                for (;;) {\n                    SQLSelectOrderByItem item = exprParser.parseSelectOrderByItem();\n                    item.setParent(stmt);\n                    stmt.getClusteredBy().add(item);\n                    if (lexer.nextIf(Token.COMMA)) {\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"CLONE\")) {\n                stmt.setLike(exprParser.name());\n                continue;\n            }\n\n            if (lexer.nextIf(Token.LIKE)) {\n                stmt.setLike(exprParser.name());\n                continue;\n            }\n\n            if (lexer.nextIf(Token.AS)) {\n                stmt.setSelect(\n                        this.createSQLSelectParser().select()\n                );\n                continue;\n            }\n\n            // DATA_RETENTION_TIME_IN_DAYS = n\n            if (lexer.nextIfIdentifier(\"DATA_RETENTION_TIME_IN_DAYS\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"DATA_RETENTION_TIME_IN_DAYS\", this.exprParser.expr());\n                continue;\n            }\n\n            // MAX_DATA_EXTENSION_TIME_IN_DAYS = n\n            if (lexer.nextIfIdentifier(\"MAX_DATA_EXTENSION_TIME_IN_DAYS\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"MAX_DATA_EXTENSION_TIME_IN_DAYS\", this.exprParser.expr());\n                continue;\n            }\n\n            // CHANGE_TRACKING = TRUE/FALSE\n            if (lexer.nextIfIdentifier(\"CHANGE_TRACKING\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"CHANGE_TRACKING\", this.exprParser.expr());\n                continue;\n            }\n\n            // ENABLE_SCHEMA_EVOLUTION = TRUE/FALSE\n            if (lexer.nextIfIdentifier(\"ENABLE_SCHEMA_EVOLUTION\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"ENABLE_SCHEMA_EVOLUTION\", this.exprParser.expr());\n                continue;\n            }\n\n            // DEFAULT_DDL_COLLATION = 'spec'\n            if (lexer.nextIfIdentifier(\"DEFAULT_DDL_COLLATION\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"DEFAULT_DDL_COLLATION\", this.exprParser.expr());\n                continue;\n            }\n\n            // COPY GRANTS\n            if (lexer.nextIfIdentifier(\"COPY\")) {\n                if (lexer.nextIf(Token.GRANT)) {\n                    stmt.putAttribute(\"COPY_GRANTS\", true);\n                    continue;\n                }\n            }\n\n            // TAG\n            if (lexer.nextIf(Token.WITH)) {\n                if (lexer.nextIfIdentifier(\"TAG\")) {\n                    parseTag(stmt);\n                    continue;\n                }\n            }\n            if (lexer.nextIfIdentifier(\"TAG\")) {\n                parseTag(stmt);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextIf(Token.EQ);\n                stmt.setLifeCycle(this.exprParser.primary());\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    private void parseTag(SQLCreateTableStatement stmt) {\n        lexer.nextToken(); // skip TAG\n        accept(Token.LPAREN);\n        for (;;) {\n            SQLExpr tagName = exprParser.name();\n            accept(Token.EQ);\n            SQLExpr tagValue = this.exprParser.primary();\n            stmt.putAttribute(\"TAG_\" + tagName, tagValue);\n            if (!lexer.nextIf(Token.COMMA)) {\n                break;\n            }\n        }\n        accept(Token.RPAREN);\n    }\n\n    @Override\n    protected SQLSelect createTableQueryRest() {\n        return new SnowflakeSelectParser(this.exprParser, selectListCache).select();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/snowflake/SnowflakeExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.snowflake;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\nimport static com.alibaba.druid.util.FnvHash.fnv1a_64_lower;\n\npublic class SnowflakeExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"ANY_VALUE\",\n                \"APPROX_COUNT_DISTINCT\",\n                \"APPROX_PERCENTILE\",\n                \"APPROX_TOP_K\",\n                \"ARRAY_AGG\",\n                \"AVG\",\n                \"BITAND_AGG\",\n                \"BITOR_AGG\",\n                \"BITXOR_AGG\",\n                \"BOOLAND_AGG\",\n                \"BOOLOR_AGG\",\n                \"CORR\",\n                \"COUNT\",\n                \"COUNT_IF\",\n                \"COVAR_POP\",\n                \"COVAR_SAMP\",\n                \"FIRST_VALUE\",\n                \"GROUPING\",\n                \"HASH_AGG\",\n                \"HLL\",\n                \"HLL_ACCUMULATE\",\n                \"HLL_COMBINE\",\n                \"HLL_ESTIMATE\",\n                \"HLL_EXPORT\",\n                \"HLL_IMPORT\",\n                \"KURTOSIS\",\n                \"LAST_VALUE\",\n                \"LAG\",\n                \"LEAD\",\n                \"LISTAGG\",\n                \"MAX\",\n                \"MEDIAN\",\n                \"MIN\",\n                \"MIN_BY\",\n                \"MAX_BY\",\n                \"MODE\",\n                \"OBJECT_AGG\",\n                \"PERCENTILE_CONT\",\n                \"PERCENTILE_DISC\",\n                \"REGR_AVGX\",\n                \"REGR_AVGY\",\n                \"REGR_COUNT\",\n                \"REGR_INTERCEPT\",\n                \"REGR_R2\",\n                \"REGR_SLOPE\",\n                \"REGR_SXX\",\n                \"REGR_SXY\",\n                \"REGR_SYY\",\n                \"REGR_VALX\",\n                \"REGR_VALY\",\n                \"SKEW\",\n                \"STDDEV\",\n                \"STDDEV_POP\",\n                \"STDDEV_SAMP\",\n                \"SUM\",\n                \"VAR_POP\",\n                \"VAR_SAMP\",\n                \"VARIANCE\",\n                \"VARIANCE_POP\",\n                \"VARIANCE_SAMP\"\n        };\n        AGGREGATE_FUNCTIONS_CODES = fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    {\n        dbType = DbType.snowflake;\n    }\n\n    public SnowflakeExprParser(String sql) {\n        this(new SnowflakeLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public SnowflakeExprParser(String sql, SQLParserFeature... features) {\n        this(new SnowflakeLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public SnowflakeExprParser(Lexer lexer) {\n        super(lexer);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    static final long TRY_CAST = fnv1a_64_lower(\"TRY_CAST\");\n    static final long FLATTEN = fnv1a_64_lower(\"FLATTEN\");\n    static final long GENERATOR = fnv1a_64_lower(\"GENERATOR\");\n    static final long RESULT_SCAN = fnv1a_64_lower(\"RESULT_SCAN\");\n\n    protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) {\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            long hashCode64 = identifierExpr.hashCode64();\n\n            if (hashCode64 == TRY_CAST && acceptLPAREN) {\n                SQLCastExpr castExpr = new SQLCastExpr();\n                lexer.nextToken();\n                castExpr.setExpr(expr());\n                castExpr.setTry(true);\n                accept(Token.AS);\n                castExpr.setDataType(parseDataType());\n                accept(Token.RPAREN);\n                return castExpr;\n            }\n        }\n        return super.methodRest(expr, acceptLPAREN);\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        // Support Snowflake :: cast operator (e.g. column::VARCHAR)\n        while (lexer.nextIf(Token.COLONCOLON)) {\n            SQLDataType dataType = this.parseDataType();\n            expr = new SQLCastExpr(expr, dataType);\n        }\n\n        // Support Snowflake semi-structured data access: expr:field\n        if (lexer.token() == Token.COLON && expr instanceof SQLIdentifierExpr) {\n            // variant path access e.g. src:key\n            lexer.nextToken();\n            String fieldName = lexer.stringVal();\n            lexer.nextToken();\n            SQLExpr pathExpr = new SQLPropertyExpr(expr, fieldName);\n\n            // chain dot access: src:key.subkey\n            while (lexer.nextIf(Token.DOT)) {\n                String subField = lexer.stringVal();\n                lexer.nextToken();\n                pathExpr = new SQLPropertyExpr(pathExpr, subField);\n            }\n\n            // allow :: cast after path access: src:key::VARCHAR\n            while (lexer.nextIf(Token.COLONCOLON)) {\n                SQLDataType dataType = this.parseDataType();\n                pathExpr = new SQLCastExpr(pathExpr, dataType);\n            }\n\n            return primaryRest(pathExpr);\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    @Override\n    public SQLExpr primary() {\n        // Handle Snowflake JSON object construction: {'key': 'value', ...}\n        if (lexer.token() == Token.LBRACE) {\n            return parseJSONObject();\n        }\n\n        return super.primary();\n    }\n\n    /**\n     * Parse Snowflake JSON object construction: {'key': 'value', ...}\n     */\n    private SQLExpr parseJSONObject() {\n        accept(Token.LBRACE);\n\n        // Check if it's a special timestamp/date literal like {ts '...'}\n        if (lexer.token() == Token.IDENTIFIER) {\n            String ident = lexer.stringVal();\n            if (\"ts\".equalsIgnoreCase(ident) || \"d\".equalsIgnoreCase(ident)\n                    || \"t\".equalsIgnoreCase(ident) || \"fn\".equalsIgnoreCase(ident)) {\n                // Let parent handle it\n                lexer.reset(lexer.mark()); // Reset to before LBRACE\n                return super.primary();\n            }\n        }\n\n        // Parse JSON object as a method call representation: OBJECT_CONSTRUCT(key, value, ...)\n        SQLMethodInvokeExpr objectConstruct = new SQLMethodInvokeExpr(\"OBJECT_CONSTRUCT\", null);\n\n        for (;;) {\n            if (lexer.token() == Token.RBRACE) {\n                break;\n            }\n\n            // Parse key (can be string literal or identifier)\n            SQLExpr key;\n            if (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS) {\n                key = this.primary();\n            } else if (lexer.token() == Token.IDENTIFIER) {\n                key = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else {\n                key = this.primary();\n            }\n\n            objectConstruct.addParameter(key);\n\n            // Expect colon separator\n            if (lexer.token() == Token.COLON) {\n                lexer.nextToken();\n            }\n\n            // Parse value\n            SQLExpr value = this.expr();\n            objectConstruct.addParameter(value);\n\n            // Check for comma or end\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        accept(Token.RBRACE);\n\n        return objectConstruct;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        // Support Snowflake AUTOINCREMENT / IDENTITY\n        if (lexer.identifierEquals(\"AUTOINCREMENT\")) {\n            lexer.nextToken();\n            column.setAutoIncrement(true);\n            if (lexer.nextIf(Token.LPAREN)) {\n                this.expr();\n                accept(Token.COMMA);\n                this.expr();\n                accept(Token.RPAREN);\n            }\n        } else if (lexer.identifierEquals(\"IDENTITY\")) {\n            lexer.nextToken();\n            column.setAutoIncrement(true);\n            if (lexer.nextIf(Token.LPAREN)) {\n                this.expr();\n                accept(Token.COMMA);\n                this.expr();\n                accept(Token.RPAREN);\n            }\n        }\n\n        // Support Snowflake COLLATE\n        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            column.setCollateExpr(primary());\n        }\n\n        // Support MASKING POLICY\n        if (lexer.identifierEquals(\"MASKING\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"POLICY\");\n            this.name(); // policy name\n            if (lexer.nextIf(Token.USING)) {\n                accept(Token.LPAREN);\n                this.exprList(new java.util.ArrayList<>(), column);\n                accept(Token.RPAREN);\n            }\n        }\n\n        // Support TAG\n        if (lexer.nextIf(Token.WITH)) {\n            if (lexer.identifierEquals(\"TAG\")) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                for (;;) {\n                    this.name();\n                    accept(Token.EQ);\n                    this.primary();\n                    if (!lexer.nextIf(Token.COMMA)) {\n                        break;\n                    }\n                }\n                accept(Token.RPAREN);\n            }\n        }\n\n        return super.parseColumnRest(column);\n    }\n\n    public SQLSelectParser createSelectParser() {\n        return new SnowflakeSelectParser(this, null);\n    }\n\n    @Override\n    public SQLLimit parseLimit() {\n        if (lexer.token() != Token.LIMIT) {\n            return null;\n        }\n\n        SQLLimit limit = new SQLLimit();\n        lexer.nextTokenValue();\n\n        SQLExpr temp;\n        if (lexer.token() == Token.LITERAL_INT) {\n            temp = new SQLIntegerExpr(lexer.integerValue());\n            lexer.nextTokenComma();\n            if (lexer.token() != Token.COMMA && lexer.token() != Token.EOF && lexer.token() != Token.IDENTIFIER) {\n                temp = this.primaryRest(temp);\n                temp = this.exprRest(temp);\n            }\n        } else {\n            temp = this.expr();\n        }\n\n        if (lexer.token() == Token.COMMA) {\n            limit.setOffset(temp);\n            lexer.nextTokenValue();\n\n            SQLExpr rowCount;\n            if (lexer.token() == Token.LITERAL_INT) {\n                rowCount = new SQLIntegerExpr(lexer.integerValue());\n                lexer.nextToken();\n                if (lexer.token() != Token.EOF && lexer.token() != Token.IDENTIFIER) {\n                    rowCount = this.primaryRest(rowCount);\n                    rowCount = this.exprRest(rowCount);\n                }\n            } else {\n                rowCount = this.expr();\n            }\n\n            limit.setRowCount(rowCount);\n        } else if (lexer.token() == Token.OFFSET || lexer.identifierEquals(FnvHash.Constants.OFFSET)) {\n            // Handle both Token.OFFSET and identifier OFFSET\n            limit.setRowCount(temp);\n            lexer.nextToken();\n            limit.setOffset(this.expr());\n            limit.setOffsetClause(true);\n        } else {\n            limit.setRowCount(temp);\n        }\n\n        return limit;\n    }\n\n    protected SQLCastExpr parseCastFormat(SQLCastExpr cast) {\n        if (lexer.nextIfIdentifier(\"FORMAT\")) {\n            cast.setFormat(this.expr());\n        }\n        return cast;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/snowflake/SnowflakeLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.snowflake;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\n\npublic class SnowflakeLexer extends Lexer {\n    static final Keywords SNOWFLAKE_KEYWORDS;\n    static final DialectFeature SNOWFLAKE_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    SQLDateExpr,\n                    SQLTimestampExpr,\n                    GroupByAll,\n                    DialectFeature.LexerFeature.NextTokenColon\n            ),\n            null\n    );\n\n    static {\n        Map<String, Token> map = new HashMap<String, Token>();\n\n        map.put(\"ALL\", Token.ALL);\n        map.put(\"ALTER\", Token.ALTER);\n        map.put(\"AND\", Token.AND);\n        map.put(\"ANY\", Token.ANY);\n        map.put(\"AS\", Token.AS);\n        map.put(\"ASC\", Token.ASC);\n        map.put(\"BETWEEN\", Token.BETWEEN);\n        map.put(\"BY\", Token.BY);\n        map.put(\"CASE\", Token.CASE);\n        map.put(\"CAST\", Token.CAST);\n        map.put(\"CHECK\", Token.CHECK);\n        map.put(\"COLUMN\", Token.COLUMN);\n        map.put(\"COMMENT\", Token.COMMENT);\n        map.put(\"CONSTRAINT\", Token.CONSTRAINT);\n        map.put(\"CREATE\", Token.CREATE);\n        map.put(\"CROSS\", Token.CROSS);\n        map.put(\"CURRENT\", Token.CURRENT);\n        map.put(\"CURSOR\", Token.CURSOR);\n        map.put(\"DEFAULT\", Token.DEFAULT);\n        map.put(\"DELETE\", Token.DELETE);\n        map.put(\"DESC\", Token.DESC);\n        map.put(\"DISABLE\", Token.DISABLE);\n        map.put(\"DISTINCT\", Token.DISTINCT);\n        map.put(\"DROP\", Token.DROP);\n        map.put(\"ELSE\", Token.ELSE);\n        map.put(\"ENABLE\", Token.ENABLE);\n        map.put(\"END\", Token.END);\n        map.put(\"ESCAPE\", Token.ESCAPE);\n        map.put(\"EXCEPT\", Token.EXCEPT);\n        map.put(\"EXISTS\", Token.EXISTS);\n        map.put(\"EXTRACT\", Token.EXTRACT);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FOR\", Token.FOR);\n        map.put(\"FOREIGN\", Token.FOREIGN);\n        map.put(\"FROM\", Token.FROM);\n        map.put(\"FULL\", Token.FULL);\n        map.put(\"FUNCTION\", Token.FUNCTION);\n        map.put(\"GRANT\", Token.GRANT);\n        map.put(\"GROUP\", Token.GROUP);\n        map.put(\"HAVING\", Token.HAVING);\n        map.put(\"IF\", Token.IF);\n        map.put(\"ILIKE\", Token.ILIKE);\n        map.put(\"IN\", Token.IN);\n        map.put(\"INDEX\", Token.INDEX);\n        map.put(\"INNER\", Token.INNER);\n        map.put(\"INSERT\", Token.INSERT);\n        map.put(\"INTERSECT\", Token.INTERSECT);\n        map.put(\"INTERVAL\", Token.INTERVAL);\n        map.put(\"INTO\", Token.INTO);\n        map.put(\"IS\", Token.IS);\n        map.put(\"JOIN\", Token.JOIN);\n        map.put(\"KEY\", Token.KEY);\n        map.put(\"LATERAL\", Token.LATERAL);\n        map.put(\"LEFT\", Token.LEFT);\n        map.put(\"LIKE\", Token.LIKE);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"MINUS\", Token.MINUS);\n        map.put(\"NOT\", Token.NOT);\n        map.put(\"NULL\", Token.NULL);\n        map.put(\"OF\", Token.OF);\n        map.put(\"ON\", Token.ON);\n        map.put(\"OR\", Token.OR);\n        map.put(\"ORDER\", Token.ORDER);\n        map.put(\"OUTER\", Token.OUTER);\n        map.put(\"OVER\", Token.OVER);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"PRIMARY\", Token.PRIMARY);\n        map.put(\"PROCEDURE\", Token.PROCEDURE);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n        map.put(\"RECURSIVE\", Token.RECURSIVE);\n        map.put(\"REFERENCES\", Token.REFERENCES);\n        map.put(\"REPLACE\", Token.REPLACE);\n        map.put(\"RETURN\", Token.RETURN);\n        map.put(\"REVOKE\", Token.REVOKE);\n        map.put(\"RIGHT\", Token.RIGHT);\n        map.put(\"ROWS\", Token.ROWS);\n        map.put(\"SELECT\", Token.SELECT);\n        map.put(\"SET\", Token.SET);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"SOME\", Token.SOME);\n        map.put(\"TABLE\", Token.TABLE);\n        map.put(\"TABLESAMPLE\", Token.TABLESAMPLE);\n        map.put(\"THEN\", Token.THEN);\n        map.put(\"TO\", Token.TO);\n        map.put(\"TOP\", Token.TOP);\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"TRUNCATE\", Token.TRUNCATE);\n        map.put(\"UNION\", Token.UNION);\n        map.put(\"UNIQUE\", Token.UNIQUE);\n        map.put(\"UPDATE\", Token.UPDATE);\n        map.put(\"USE\", Token.USE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"VALUES\", Token.VALUES);\n        map.put(\"VIEW\", Token.VIEW);\n        map.put(\"WHEN\", Token.WHEN);\n        map.put(\"WHERE\", Token.WHERE);\n        map.put(\"WINDOW\", Token.WINDOW);\n        map.put(\"WITH\", Token.WITH);\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"EXCEPTION\", Token.EXCEPTION);\n        map.put(\"LOOP\", Token.LOOP);\n        map.put(\"WHILE\", Token.WHILE);\n        map.put(\"DO\", Token.DO);\n        map.put(\"START\", Token.START);\n        map.put(\"COMMENT\", Token.COMMENT);\n        map.put(\"SEQUENCE\", Token.SEQUENCE);\n        map.put(\"SESSION\", Token.SESSION);\n        map.put(\"GRANT\", Token.GRANT);\n        map.put(\"REVOKE\", Token.REVOKE);\n        map.put(\"COMMIT\", Token.COMMIT);\n        map.put(\"SAVEPOINT\", Token.SAVEPOINT);\n        map.put(\"DECLARE\", Token.DECLARE);\n        map.put(\"IMMEDIATE\", Token.IMMEDIATE);\n        map.put(\"TEMPORARY\", Token.TEMPORARY);\n        map.put(\"TEMP\", Token.TEMP);\n        map.put(\"IF\", Token.IF);\n        map.put(\"EXISTS\", Token.EXISTS);\n        map.put(\"REPLACE\", Token.REPLACE);\n        map.put(\"OFFSET\", Token.OFFSET);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n        map.put(\"NEXT\", Token.NEXT);\n        map.put(\"TYPE\", Token.TYPE);\n        map.put(\"LOGGING\", Token.LOGGING);\n        map.put(\"SCHEMA\", Token.SCHEMA);\n        map.put(\"DATABASE\", Token.DATABASE);\n        map.put(\"PRIOR\", Token.PRIOR);\n\n        SNOWFLAKE_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return SNOWFLAKE_KEYWORDS;\n    }\n\n    public SnowflakeLexer(String input, SQLParserFeature... features) {\n        super(input);\n        dbType = DbType.snowflake;\n        this.skipComment = true;\n        this.keepComments = true;\n        this.features |= SQLParserFeature.SupportUnicodeCodePoint.mask;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = SNOWFLAKE_FEATURE;\n    }\n\n    @Override\n    protected void scanVariable_at() {\n        if (ch != '@') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n        char c;\n\n        // Handle @@ for session variables\n        final char c1 = charAt(pos + 1);\n        if (c1 == '@') {\n            ++pos;\n            bufPos++;\n        }\n\n        // Scan identifier characters including path separators for stage paths\n        for (; ; ) {\n            c = charAt(++pos);\n\n            // Snowflake stage paths can contain / and other characters\n            if (Character.isLetterOrDigit(c) || c == '_' || c == '$' || c == '/' || c == '.' || c == '-') {\n                bufPos++;\n                continue;\n            }\n\n            break;\n        }\n\n        this.ch = charAt(pos);\n        stringVal = addSymbol();\n        token = Token.VARIANT;\n    }\n\n    @Override\n    public void scanComment() {\n        if ((ch == '/' && charAt(pos + 1) == '/')\n                || (ch == '-' && charAt(pos + 1) == '-')) {\n            scanSingleLineComment();\n        } else if (ch == '/' && charAt(pos + 1) == '*') {\n            scanMultiLineComment();\n        } else {\n            throw new IllegalStateException();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/snowflake/SnowflakeSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.snowflake;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSampling;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class SnowflakeSelectParser extends SQLSelectParser {\n    public SnowflakeSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.snowflake;\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new SnowflakeExprParser(lexer);\n    }\n\n    @Override\n    protected void parseTop(SQLSelectQueryBlock x) {\n        // Support Snowflake SELECT TOP n syntax\n        if (lexer.token() == Token.TOP) {\n            lexer.nextToken();\n            SQLExpr topExpr = this.exprParser.primary();\n            SQLLimit limit = new SQLLimit();\n            limit.setRowCount(topExpr);\n            x.setLimit(limit);\n        }\n    }\n\n    protected void querySelectListBefore(SQLSelectQueryBlock x) {\n        if (lexer.nextIf(Token.DISTINCT)) {\n            x.setDistinct();\n        } else if (lexer.nextIf(Token.ALL)) {\n            x.setDistionOption(SQLSetQuantifier.ALL);\n        }\n    }\n\n    @Override\n    protected String tableAlias(boolean must) {\n        Token tok = lexer.token();\n\n        // Don't treat TABLESAMPLE or SAMPLE as table alias\n        if (tok == Token.TABLESAMPLE) {\n            if (must) {\n                throw new ParserException(\"illegal alias. \" + lexer.info());\n            }\n            return null;\n        }\n        if (lexer.identifierEquals(\"SAMPLE\")) {\n            if (must) {\n                throw new ParserException(\"illegal alias. \" + lexer.info());\n            }\n            return null;\n        }\n\n        if (tok == Token.VALUES) {\n            String alias = lexer.stringVal();\n            lexer.nextToken();\n            return alias;\n        }\n        return super.tableAlias(must);\n    }\n\n    @Override\n    public SQLTableSource parseTableSource(boolean forFrom) {\n        // Handle LATERAL as the start of a table source\n        if (lexer.token() == Token.LATERAL) {\n            lexer.nextToken();\n            // LATERAL FLATTEN(...) or LATERAL (SELECT ...)\n            if (lexer.token() == Token.LPAREN) {\n                // Could be LATERAL (SELECT ...)\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH) {\n                    SQLSelect select = select();\n                    accept(Token.RPAREN);\n                    SQLSubqueryTableSource subquery = new SQLSubqueryTableSource(select);\n                    subquery.putAttribute(\"LATERAL\", true);\n                    String alias = tableAlias();\n                    if (alias != null) {\n                        subquery.setAlias(alias);\n                    }\n                    return parseTableSourceRest(subquery);\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n            // LATERAL followed by function call like FLATTEN(...)\n            SQLExpr funcExpr = this.exprParser.expr();\n            SQLExprTableSource funcTableSource = new SQLExprTableSource(funcExpr);\n            funcTableSource.putAttribute(\"LATERAL\", true);\n            String alias = tableAlias();\n            if (alias != null) {\n                funcTableSource.setAlias(alias);\n            }\n            return parseTableSourceRest(funcTableSource);\n        }\n        return super.parseTableSource(forFrom);\n    }\n\n    @Override\n    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {\n        // Handle Time Travel: AT/BEFORE clause\n        if (lexer.identifierEquals(\"AT\") || lexer.identifierEquals(\"BEFORE\")) {\n            return parseTimeTravel(tableSource);\n        }\n\n        // Handle COMMA followed by LATERAL as a special case for Snowflake\n        if (lexer.token() == Token.COMMA) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token() == Token.LATERAL) {\n                lexer.nextToken();\n                // Parse LATERAL FLATTEN(...) or LATERAL (SELECT ...)\n                SQLTableSource rightTableSource;\n                if (lexer.token() == Token.LPAREN) {\n                    Lexer.SavePoint mark2 = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH) {\n                        SQLSelect select = select();\n                        accept(Token.RPAREN);\n                        SQLSubqueryTableSource subquery = new SQLSubqueryTableSource(select);\n                        subquery.putAttribute(\"LATERAL\", true);\n                        String alias = tableAlias();\n                        if (alias != null) {\n                            subquery.setAlias(alias);\n                        }\n                        rightTableSource = subquery;\n                    } else {\n                        lexer.reset(mark2);\n                        SQLExpr funcExpr = this.exprParser.expr();\n                        SQLExprTableSource funcTs = new SQLExprTableSource(funcExpr);\n                        funcTs.putAttribute(\"LATERAL\", true);\n                        String alias = tableAlias();\n                        if (alias != null) {\n                            funcTs.setAlias(alias);\n                        }\n                        rightTableSource = funcTs;\n                    }\n                } else {\n                    // LATERAL followed by function call like FLATTEN(...)\n                    SQLExpr funcExpr = this.exprParser.expr();\n                    SQLExprTableSource funcTs = new SQLExprTableSource(funcExpr);\n                    funcTs.putAttribute(\"LATERAL\", true);\n                    String alias = tableAlias();\n                    if (alias != null) {\n                        funcTs.setAlias(alias);\n                    }\n                    rightTableSource = funcTs;\n                }\n\n                SQLJoinTableSource join = new SQLJoinTableSource();\n                join.setLeft(tableSource);\n                join.setRight(rightTableSource);\n                join.setJoinType(SQLJoinTableSource.JoinType.COMMA);\n\n                return parseTableSourceRest(join);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        // Continue with parent class processing (which includes parseTableSourceSample)\n        return super.parseTableSourceRest(tableSource);\n    }\n\n    /**\n     * Parse Snowflake Time Travel syntax: AT/BEFORE (TIMESTAMP | OFFSET | STATEMENT => value)\n     */\n    private SQLTableSource parseTimeTravel(SQLTableSource tableSource) {\n        String timeTravelType = lexer.stringVal(); // AT or BEFORE\n        lexer.nextToken();\n\n        accept(Token.LPAREN);\n\n        // Parse TIMESTAMP => value, OFFSET => value, or STATEMENT => value\n        String paramType = lexer.stringVal();\n        lexer.nextToken();\n        accept(Token.EQGT);  // => operator\n        SQLExpr paramValue = this.exprParser.expr();\n\n        accept(Token.RPAREN);\n\n        // Store as attribute on table source\n        tableSource.putAttribute(\"TIME_TRAVEL\", timeTravelType);\n        tableSource.putAttribute(\"TIME_TRAVEL_TYPE\", paramType);\n        tableSource.putAttribute(\"TIME_TRAVEL_VALUE\", paramValue);\n\n        return parseTableSourceRest(tableSource);\n    }\n\n    @Override\n    protected SQLTableSource parseLateralView(SQLTableSource tableSource) {\n        // In Snowflake, LATERAL can be followed by:\n        // 1. FLATTEN(...) - table function\n        // 2. TABLE(FLATTEN(...)) - table function with TABLE keyword\n        // 3. (SELECT ...) - lateral subquery\n\n        if (tableSource != null && \"LATERAL\".equalsIgnoreCase(tableSource.getAlias())) {\n            tableSource.setAlias(null);\n        }\n\n        if (lexer.token() == Token.VIEW) {\n            // Hive-style LATERAL VIEW (fallback to parent)\n            return super.parseLateralView(tableSource);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            // LATERAL (SELECT ...) - lateral subquery\n            lexer.nextToken();\n            SQLSelect select = select();\n            accept(Token.RPAREN);\n            SQLSubqueryTableSource subquery = new SQLSubqueryTableSource(select);\n            subquery.putAttribute(\"LATERAL\", true);\n            String alias = tableAlias();\n            if (alias != null) {\n                subquery.setAlias(alias);\n            }\n\n            SQLJoinTableSource join = new SQLJoinTableSource();\n            join.setLeft(tableSource);\n            join.setRight(subquery);\n            join.setJoinType(SQLJoinTableSource.JoinType.COMMA);\n\n            return parseTableSourceRest(join);\n        }\n\n        // LATERAL FLATTEN(...) or LATERAL identifier(...)\n        SQLExpr funcExpr = this.exprParser.expr();\n        SQLExprTableSource funcTableSource = new SQLExprTableSource(funcExpr);\n        funcTableSource.putAttribute(\"LATERAL\", true);\n        String alias = tableAlias();\n        if (alias != null) {\n            funcTableSource.setAlias(alias);\n        }\n\n        SQLJoinTableSource join = new SQLJoinTableSource();\n        join.setLeft(tableSource);\n        join.setRight(funcTableSource);\n        join.setJoinType(SQLJoinTableSource.JoinType.COMMA);\n\n        return parseTableSourceRest(join);\n    }\n\n    @Override\n    protected List<String> getReturningFunctions() {\n        return Arrays.asList(\"GENERATE_SERIES\", \"FLATTEN\", \"GENERATOR\", \"RESULT_SCAN\", \"SPLIT_TO_TABLE\");\n    }\n\n    @Override\n    public void parseTableSourceSample(SQLTableSource tableSource) {\n        // Handle Snowflake SAMPLE / TABLESAMPLE syntax\n        // Check if we're at SAMPLE or TABLESAMPLE token\n        if (lexer.token() != Token.TABLESAMPLE && !lexer.identifierEquals(\"SAMPLE\")) {\n            return;\n        }\n\n        boolean hasSample = false;\n        if (lexer.token() == Token.TABLESAMPLE) {\n            lexer.nextToken();\n            hasSample = true;\n        } else if (lexer.identifierEquals(\"SAMPLE\")) {\n            lexer.nextToken();\n            hasSample = true;\n        }\n\n        if (hasSample) {\n            accept(Token.LPAREN);\n\n            SQLTableSampling sampling = new SQLTableSampling();\n\n            // Parse the sample value\n            if (lexer.token() == Token.LITERAL_INT || lexer.token() == Token.LITERAL_FLOAT) {\n                SQLExpr val = this.exprParser.primary();\n\n                // Check for PERCENT keyword (identifier)\n                if (lexer.identifierEquals(\"PERCENT\")) {\n                    lexer.nextToken();\n                    sampling.setPercent(val);\n                } else if (lexer.token() == Token.ROWS || lexer.identifierEquals(\"ROWS\")) {\n                    // ROWS can be Token or identifier\n                    lexer.nextToken();\n                    sampling.setRows(val);\n                } else {\n                    // Default is percent\n                    sampling.setPercent(val);\n                }\n            }\n\n            accept(Token.RPAREN);\n\n            if (tableSource instanceof SQLExprTableSource) {\n                ((SQLExprTableSource) tableSource).setSampling(sampling);\n            }\n        }\n    }\n\n    @Override\n    protected SQLTableSource primaryTableSourceRest(SQLTableSource tableSource) {\n        return tableSource;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/snowflake/SnowflakeStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.snowflake;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class SnowflakeStatementParser extends SQLStatementParser {\n    public SnowflakeStatementParser(String sql) {\n        super(new SnowflakeExprParser(sql));\n    }\n\n    public SnowflakeStatementParser(String sql, SQLParserFeature... features) {\n        super(new SnowflakeExprParser(sql, features));\n    }\n\n    public SnowflakeStatementParser(Lexer lexer) {\n        super(new SnowflakeExprParser(lexer));\n    }\n\n    @Override\n    protected void createOptionSkip() {\n        super.createOptionSkip();\n        if (lexer.nextIfIdentifier(\"TRANSIENT\") || lexer.nextIfIdentifier(\"VOLATILE\")) {\n            // consumed\n        }\n    }\n\n    public SnowflakeSelectParser createSQLSelectParser() {\n        return new SnowflakeSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new SnowflakeCreateTableParser(this.exprParser);\n    }\n\n    @Override\n    protected SQLStatement alterRest(Lexer.SavePoint mark) {\n        // Handle Snowflake-specific ALTER statements\n        // Note: ALTER token has already been consumed when we reach here\n        if (lexer.nextIf(Token.SESSION)) {\n            return parseAlterSessionRest();\n        }\n        if (lexer.nextIfIdentifier(\"WAREHOUSE\")) {\n            return parseAlterWarehouseRest();\n        }\n        if (lexer.nextIfIdentifier(\"STAGE\")) {\n            return parseAlterStageRest();\n        }\n        if (lexer.nextIfIdentifier(\"TASK\")) {\n            return parseAlterTaskRest();\n        }\n        if (lexer.nextIfIdentifier(\"STREAM\")) {\n            return parseAlterStreamRest();\n        }\n        if (lexer.nextIfIdentifier(\"PIPE\")) {\n            return parseAlterPipeRest();\n        }\n        if (lexer.nextIfIdentifier(\"FILE\")) {\n            lexer.nextIfIdentifier(\"FORMAT\");\n            return parseAlterFileFormatRest();\n        }\n        if (lexer.nextIfIdentifier(\"FORMAT\")) {\n            return parseAlterFileFormatRest();\n        }\n        return super.alterRest(mark);\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.token() == Token.BEGIN) {\n            statementList.add(parseBlock());\n            return true;\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.COPY)) {\n            statementList.add(parseCopy());\n            return true;\n        }\n\n        if (lexer.nextIfIdentifier(\"CALL\")) {\n            statementList.add(parseCall());\n            return true;\n        }\n\n        // COMMIT / ROLLBACK\n        if (lexer.token() == Token.COMMIT) {\n            statementList.add(parseCommit());\n            return true;\n        }\n\n        return false;\n    }\n\n    public SQLStatement parseBlock() {\n        accept(Token.BEGIN);\n        if (lexer.nextIfIdentifier(\"TRANSACTION\") || lexer.nextIfIdentifier(\"TRAN\")) {\n            // Handle optional NAME clause\n            if (lexer.nextIfIdentifier(\"NAME\")) {\n                this.exprParser.name();\n            }\n            SQLStartTransactionStatement startTrans = new SQLStartTransactionStatement(dbType);\n            return startTrans;\n        }\n        SQLBlockStatement block = new SQLBlockStatement();\n        parseStatementList(block.getStatementList(), -1, block);\n        if (lexer.nextIf(Token.EXCEPTION)) {\n            block.setException(parseException());\n        }\n        accept(Token.END);\n        return block;\n    }\n\n    @Override\n    protected void parseInsertOverwrite(SQLInsertInto insertStatement) {\n        insertStatement.setOverwrite(true);\n        lexer.nextIf(Token.INTO);\n    }\n\n    @Override\n    protected void mergeBeforeName() {\n        this.lexer.nextIf(Token.INTO);\n    }\n\n    public SQLDeleteStatement parseDeleteStatement() {\n        SQLDeleteStatement deleteStatement = new SQLDeleteStatement(getDbType());\n\n        accept(Token.DELETE);\n        lexer.nextIf(Token.FROM);\n\n        SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n        deleteStatement.setTableSource(tableSource);\n\n        if (lexer.nextIf(Token.USING)) {\n            SQLTableSource using = createSQLSelectParser().parseTableSource();\n            deleteStatement.setUsing(using);\n        }\n\n        if (lexer.nextIf(Token.WHERE)) {\n            SQLExpr where = this.exprParser.expr();\n            deleteStatement.setWhere(where);\n        }\n\n        return deleteStatement;\n    }\n\n    @Override\n    public SQLUseStatement parseUse() {\n        accept(Token.USE);\n\n        SQLUseStatement stmt = new SQLUseStatement(getDbType());\n\n        // USE DATABASE db_name / USE SCHEMA schema_name / USE WAREHOUSE wh_name / USE ROLE role_name\n        if (lexer.nextIf(Token.DATABASE)) {\n            SQLName name = this.exprParser.name();\n            stmt.setDatabase(new SQLPropertyExpr(new SQLIdentifierExpr(\"DATABASE\"), name.getSimpleName()));\n        } else if (lexer.nextIf(Token.SCHEMA)) {\n            SQLName name = this.exprParser.name();\n            stmt.setDatabase(new SQLPropertyExpr(new SQLIdentifierExpr(\"SCHEMA\"), name.getSimpleName()));\n        } else if (lexer.nextIfIdentifier(\"WAREHOUSE\")) {\n            SQLName name = this.exprParser.name();\n            stmt.setDatabase(new SQLPropertyExpr(new SQLIdentifierExpr(\"WAREHOUSE\"), name.getSimpleName()));\n        } else if (lexer.nextIfIdentifier(\"ROLE\")) {\n            SQLName name = this.exprParser.name();\n            stmt.setDatabase(new SQLPropertyExpr(new SQLIdentifierExpr(\"ROLE\"), name.getSimpleName()));\n        } else {\n            stmt.setDatabase(this.exprParser.name());\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseCopy() {\n        acceptIdentifier(\"COPY\");\n        accept(Token.INTO);\n\n        SQLCopyFromStatement copyStmt = new SQLCopyFromStatement();\n        copyStmt.setDbType(getDbType());\n\n        SQLName tableName = this.exprParser.name();\n        copyStmt.setTable(new SQLExprTableSource(tableName));\n\n        if (lexer.nextIf(Token.LPAREN)) {\n            for (;;) {\n                copyStmt.getColumns().add(this.exprParser.name());\n                if (!lexer.nextIf(Token.COMMA)) {\n                    break;\n                }\n            }\n            accept(Token.RPAREN);\n        }\n\n        accept(Token.FROM);\n\n        SQLExpr from = this.exprParser.expr();\n        copyStmt.setFrom(from);\n\n        parseCopyIntoOptions();\n\n        return copyStmt;\n    }\n\n    private void parseCopyIntoOptions() {\n        for (;;) {\n            if (lexer.nextIfIdentifier(\"FILES\")) {\n                lexer.nextIf(Token.EQ);\n                accept(Token.LPAREN);\n                for (;;) {\n                    this.exprParser.expr();\n                    if (!lexer.nextIf(Token.COMMA)) {\n                        break;\n                    }\n                }\n                accept(Token.RPAREN);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"PATTERN\")) {\n                lexer.nextIf(Token.EQ);\n                this.exprParser.expr();\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"FILE_FORMAT\")) {\n                lexer.nextIf(Token.EQ);\n                if (lexer.nextIf(Token.LPAREN)) {\n                    parseKeyValuePairs();\n                    accept(Token.RPAREN);\n                } else {\n                    this.exprParser.name();\n                }\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"VALIDATION_MODE\")) {\n                lexer.nextIf(Token.EQ);\n                this.exprParser.expr();\n                continue;\n            }\n\n            // generic key = value options\n            if (lexer.token() == Token.IDENTIFIER) {\n                Lexer.SavePoint mark = lexer.mark();\n                String key = lexer.stringVal();\n                lexer.nextToken();\n                if (lexer.nextIf(Token.EQ)) {\n                    this.exprParser.expr();\n                    continue;\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n\n            break;\n        }\n    }\n\n    private void parseKeyValuePairs() {\n        for (;;) {\n            if (lexer.token() == Token.RPAREN) {\n                break;\n            }\n            // Handle both IDENTIFIER and keyword tokens (like TYPE, FORMAT, etc.)\n            if (lexer.token() == Token.IDENTIFIER\n                    || lexer.token() == Token.TYPE\n                    || lexer.token() == Token.FORMAT\n                    || lexer.token() == Token.COMMENT\n                    || lexer.token() == Token.LOGGING) {\n                lexer.nextToken();\n                if (lexer.nextIf(Token.EQ)) {\n                    this.exprParser.expr();\n                }\n                // Check for comma separator between key-value pairs\n                if (lexer.nextIf(Token.COMMA)) {\n                    continue;\n                }\n                // If no comma, check if we're at the closing paren\n                if (lexer.token() == Token.RPAREN) {\n                    break;\n                }\n                continue;\n            }\n            break;\n        }\n    }\n\n    @Override\n    public SQLStatement parseExecute() {\n        acceptIdentifier(\"EXECUTE\");\n        // IMMEDIATE is a Token, use token comparison\n        if (lexer.token() == Token.IDENTIFIER && lexer.identifierEquals(\"IMMEDIATE\")) {\n            lexer.nextToken();\n        } else if (lexer.token() == Token.IMMEDIATE) {\n            lexer.nextToken();\n        } else {\n            acceptIdentifier(\"IMMEDIATE\");\n        }\n\n        SQLCallStatement stmt = new SQLCallStatement(getDbType());\n        stmt.setProcedureName(new SQLIdentifierExpr(\"EXECUTE IMMEDIATE\"));\n\n        SQLExpr expr = this.exprParser.expr();\n        stmt.getParameters().add(expr);\n\n        return stmt;\n    }\n\n    @Override\n    public SQLCallStatement parseCall() {\n        acceptIdentifier(\"CALL\");\n\n        SQLCallStatement stmt = new SQLCallStatement(getDbType());\n        stmt.setProcedureName(this.exprParser.name());\n\n        accept(Token.LPAREN);\n        this.exprParser.exprList(stmt.getParameters(), stmt);\n        accept(Token.RPAREN);\n\n        return stmt;\n    }\n\n    public SQLStatement parseShow() {\n        accept(Token.SHOW);\n\n        if (lexer.nextIfIdentifier(\"TABLES\")) {\n            SQLShowTablesStatement stmt = new SQLShowTablesStatement();\n            parseShowLikeAndIn(stmt);\n            return stmt;\n        }\n\n        if (lexer.nextIf(Token.DATABASE) || lexer.nextIfIdentifier(\"DATABASES\")) {\n            SQLShowDatabasesStatement stmt = new SQLShowDatabasesStatement();\n            if (lexer.nextIf(Token.LIKE)) {\n                stmt.setLike(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        if (lexer.nextIfIdentifier(\"SCHEMAS\")) {\n            SQLShowDatabasesStatement stmt = new SQLShowDatabasesStatement();\n            if (lexer.nextIf(Token.LIKE)) {\n                stmt.setLike(this.exprParser.expr());\n            }\n            if (lexer.nextIf(Token.IN) || lexer.nextIf(Token.FROM)) {\n                lexer.nextIf(Token.DATABASE);\n                stmt.setDatabase(this.exprParser.name());\n            }\n            return stmt;\n        }\n\n        if (lexer.nextIfIdentifier(\"COLUMNS\")) {\n            SQLShowColumnsStatement stmt = new SQLShowColumnsStatement();\n            if (lexer.nextIf(Token.LIKE)) {\n                stmt.setLike(this.exprParser.expr());\n            }\n            if (lexer.nextIf(Token.IN) || lexer.nextIf(Token.FROM)) {\n                lexer.nextIf(Token.TABLE);\n                stmt.setTable(this.exprParser.name());\n            }\n            return stmt;\n        }\n\n        if (lexer.nextIf(Token.VIEW) || lexer.nextIfIdentifier(\"VIEWS\")) {\n            SQLShowViewsStatement stmt = new SQLShowViewsStatement();\n            if (lexer.nextIf(Token.LIKE)) {\n                stmt.setLike(this.exprParser.expr());\n            }\n            if (lexer.nextIf(Token.IN) || lexer.nextIf(Token.FROM)) {\n                lexer.nextIf(Token.DATABASE);\n                lexer.nextIf(Token.SCHEMA);\n                stmt.setDatabase(this.exprParser.name());\n            }\n            return stmt;\n        }\n\n        if (lexer.nextIfIdentifier(\"WAREHOUSES\")) {\n            SQLShowTablesStatement stmt = new SQLShowTablesStatement();\n            if (lexer.nextIf(Token.LIKE)) {\n                stmt.setLike(this.exprParser.expr());\n            }\n            return stmt;\n        }\n\n        if (lexer.nextIfIdentifier(\"GRANTS\")) {\n            SQLShowGrantsStatement stmt = new SQLShowGrantsStatement();\n            if (lexer.nextIf(Token.ON)) {\n                lexer.nextIf(Token.TABLE);\n                lexer.nextIf(Token.DATABASE);\n                lexer.nextIf(Token.SCHEMA);\n                lexer.nextIf(Token.VIEW);\n                lexer.nextIfIdentifier(\"WAREHOUSE\");\n                lexer.nextIfIdentifier(\"ROLE\");\n                stmt.setOn(this.exprParser.name());\n            }\n            if (lexer.nextIf(Token.TO)) {\n                lexer.nextIfIdentifier(\"ROLE\");\n                lexer.nextIfIdentifier(\"USER\");\n                stmt.setUser(this.exprParser.name());\n            }\n            return stmt;\n        }\n\n        // Generic SHOW handler\n        String showItem = lexer.stringVal();\n        lexer.nextToken();\n\n        SQLShowTablesStatement stmt = new SQLShowTablesStatement();\n        if (lexer.nextIf(Token.LIKE)) {\n            stmt.setLike(this.exprParser.expr());\n        }\n        if (lexer.nextIf(Token.IN) || lexer.nextIf(Token.FROM)) {\n            lexer.nextIf(Token.DATABASE);\n            lexer.nextIf(Token.SCHEMA);\n            lexer.nextIf(Token.TABLE);\n            stmt.setDatabase(this.exprParser.name());\n        }\n        return stmt;\n    }\n\n    private void parseShowLikeAndIn(SQLShowTablesStatement stmt) {\n        if (lexer.nextIf(Token.LIKE)) {\n            stmt.setLike(this.exprParser.expr());\n        }\n        if (lexer.nextIf(Token.IN) || lexer.nextIf(Token.FROM)) {\n            lexer.nextIf(Token.DATABASE);\n            lexer.nextIf(Token.SCHEMA);\n            stmt.setDatabase(this.exprParser.name());\n        }\n    }\n\n    @Override\n    public SQLStatement parseDescribe() {\n        lexer.nextIf(Token.DESC);\n        lexer.nextIfIdentifier(\"DESCRIBE\");\n\n        SQLDescribeStatement stmt = new SQLDescribeStatement();\n        stmt.setDbType(getDbType());\n\n        if (lexer.nextIf(Token.TABLE)) {\n            // consumed\n        } else if (lexer.nextIf(Token.FUNCTION)) {\n            // consumed\n        } else if (lexer.nextIf(Token.VIEW)) {\n            // consumed\n        } else if (lexer.nextIfIdentifier(\"SCHEMA\")) {\n            // consumed\n        } else if (lexer.nextIfIdentifier(\"DATABASE\")) {\n            // consumed\n        } else if (lexer.nextIfIdentifier(\"STAGE\")) {\n            // consumed\n        } else if (lexer.nextIfIdentifier(\"TASK\")) {\n            // consumed\n        } else if (lexer.nextIfIdentifier(\"STREAM\")) {\n            // consumed\n        } else if (lexer.nextIfIdentifier(\"PIPE\")) {\n            // consumed\n        }\n\n        stmt.setObject(this.exprParser.name());\n\n        return stmt;\n    }\n\n    // ==================== ALTER SESSION ====================\n\n    public SQLStatement parseAlterSession() {\n        accept(Token.ALTER);\n        accept(Token.SESSION);\n        return parseAlterSessionRest();\n    }\n\n    private SQLStatement parseAlterSessionRest() {\n        SQLSetStatement stmt = new SQLSetStatement(getDbType());\n\n        if (lexer.nextIf(Token.SET)) {\n            for (;;) {\n                SQLName name = this.exprParser.name();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.expr();\n                stmt.getItems().add(new SQLAssignItem(name, value));\n                if (!lexer.nextIf(Token.COMMA)) {\n                    break;\n                }\n            }\n        } else if (lexer.nextIfIdentifier(\"UNSET\")) {\n            for (;;) {\n                SQLName name = this.exprParser.name();\n                stmt.getItems().add(new SQLAssignItem(name, new SQLIdentifierExpr(\"UNSET\")));\n                if (!lexer.nextIf(Token.COMMA)) {\n                    break;\n                }\n            }\n        }\n\n        return stmt;\n    }\n\n    // ==================== ALTER WAREHOUSE ====================\n\n    public SQLStatement parseAlterWarehouse() {\n        accept(Token.ALTER);\n        acceptIdentifier(\"WAREHOUSE\");\n        return parseAlterWarehouseRest();\n    }\n\n    private SQLStatement parseAlterWarehouseRest() {\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.putAttribute(\"objectType\", \"WAREHOUSE\");\n\n        lexer.nextIf(Token.IF);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.nextIfIdentifier(\"SUSPEND\") || lexer.nextIfIdentifier(\"RESUME\")\n                || lexer.nextIfIdentifier(\"ABORT\")) {\n            if (lexer.nextIfIdentifier(\"ALL\")) {\n                acceptIdentifier(\"QUERIES\");\n            }\n        } else if (lexer.nextIf(Token.SET)) {\n            parseWarehouseParameters(stmt);\n        } else if (lexer.nextIfIdentifier(\"UNSET\")) {\n            while (lexer.token() == Token.IDENTIFIER) {\n                this.exprParser.name();\n                if (!lexer.nextIf(Token.COMMA)) {\n                    break;\n                }\n            }\n        } else if (lexer.nextIfIdentifier(\"RENAME\")) {\n            accept(Token.TO);\n            this.exprParser.name();\n        }\n\n        return stmt;\n    }\n\n    private void parseWarehouseParameters(SQLAlterTableStatement stmt) {\n        for (;;) {\n            if (lexer.token() == Token.IDENTIFIER) {\n                SQLName paramName = this.exprParser.name();\n                accept(Token.EQ);\n                SQLExpr value = this.exprParser.expr();\n                stmt.putAttribute(paramName.getSimpleName(), value);\n                if (!lexer.nextIf(Token.COMMA)) {\n                    break;\n                }\n                continue;\n            }\n            break;\n        }\n    }\n\n    // ==================== ALTER STAGE ====================\n\n    public SQLStatement parseAlterStage() {\n        accept(Token.ALTER);\n        acceptIdentifier(\"STAGE\");\n        return parseAlterStageRest();\n    }\n\n    private SQLStatement parseAlterStageRest() {\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.putAttribute(\"objectType\", \"STAGE\");\n\n        lexer.nextIf(Token.IF);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.nextIfIdentifier(\"RENAME\")) {\n            accept(Token.TO);\n            stmt.putAttribute(\"NEW_NAME\", this.exprParser.name());\n        } else if (lexer.nextIf(Token.SET)) {\n            parseStageOptions(stmt);\n        } else if (lexer.nextIfIdentifier(\"UNSET\")) {\n            while (lexer.token() == Token.IDENTIFIER) {\n                this.exprParser.name();\n                if (!lexer.nextIf(Token.COMMA)) {\n                    break;\n                }\n            }\n        } else if (lexer.nextIfIdentifier(\"REFRESH\")) {\n            if (lexer.nextIf(Token.LPAREN)) {\n                lexer.nextIfIdentifier(\"SUBPATH\");\n                lexer.nextIf(Token.EQ);\n                this.exprParser.expr();\n                accept(Token.RPAREN);\n            }\n        }\n\n        return stmt;\n    }\n\n    private void parseStageOptions(SQLAlterTableStatement stmt) {\n        for (;;) {\n            if (lexer.nextIfIdentifier(\"URL\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"URL\", this.exprParser.expr());\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"STORAGE_INTEGRATION\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"STORAGE_INTEGRATION\", this.exprParser.name());\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"CREDENTIALS\")) {\n                lexer.nextIf(Token.EQ);\n                accept(Token.LPAREN);\n                parseKeyValuePairs();\n                accept(Token.RPAREN);\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"ENCRYPTION\")) {\n                lexer.nextIf(Token.EQ);\n                accept(Token.LPAREN);\n                parseKeyValuePairs();\n                accept(Token.RPAREN);\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"FILE_FORMAT\")) {\n                lexer.nextIf(Token.EQ);\n                if (lexer.nextIf(Token.LPAREN)) {\n                    parseKeyValuePairs();\n                    accept(Token.RPAREN);\n                } else {\n                    stmt.putAttribute(\"FILE_FORMAT\", this.exprParser.name());\n                }\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"COPY_OPTIONS\")) {\n                lexer.nextIf(Token.EQ);\n                accept(Token.LPAREN);\n                parseKeyValuePairs();\n                accept(Token.RPAREN);\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"COMMENT\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"COMMENT\", this.exprParser.expr());\n                continue;\n            }\n            break;\n        }\n    }\n\n    // ==================== ALTER TASK ====================\n\n    public SQLStatement parseAlterTask() {\n        accept(Token.ALTER);\n        acceptIdentifier(\"TASK\");\n        return parseAlterTaskRest();\n    }\n\n    private SQLStatement parseAlterTaskRest() {\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.putAttribute(\"objectType\", \"TASK\");\n\n        lexer.nextIf(Token.IF);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.nextIfIdentifier(\"SUSPEND\") || lexer.nextIfIdentifier(\"RESUME\")) {\n            stmt.putAttribute(\"ACTION\", lexer.stringVal());\n        } else if (lexer.nextIfIdentifier(\"REMOVE\")) {\n            acceptIdentifier(\"AFTER\");\n            stmt.putAttribute(\"REMOVE_AFTER\", true);\n        } else if (lexer.nextIfIdentifier(\"ADD\")) {\n            acceptIdentifier(\"AFTER\");\n            stmt.putAttribute(\"ADD_AFTER\", this.exprParser.name());\n        } else if (lexer.nextIfIdentifier(\"RENAME\")) {\n            accept(Token.TO);\n            stmt.putAttribute(\"NEW_NAME\", this.exprParser.name());\n        } else if (lexer.nextIf(Token.SET)) {\n            parseTaskOptions(stmt);\n        } else if (lexer.nextIfIdentifier(\"UNSET\")) {\n            while (lexer.token() == Token.IDENTIFIER) {\n                this.exprParser.name();\n                if (!lexer.nextIf(Token.COMMA)) {\n                    break;\n                }\n            }\n        } else if (lexer.nextIfIdentifier(\"FINALIZE\")) {\n            stmt.putAttribute(\"FINALIZE\", true);\n        } else if (lexer.nextIfIdentifier(\"MODIFY\")) {\n            accept(Token.AS);\n            SQLStatement taskSql = parseStatement();\n            stmt.putAttribute(\"TASK_SQL\", taskSql);\n        }\n\n        return stmt;\n    }\n\n    private void parseTaskOptions(SQLAlterTableStatement stmt) {\n        for (;;) {\n            if (lexer.nextIfIdentifier(\"WAREHOUSE\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"WAREHOUSE\", this.exprParser.name());\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"SCHEDULE\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"SCHEDULE\", this.exprParser.expr());\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"ALLOW_OVERLAPPING_EXECUTION\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"ALLOW_OVERLAPPING_EXECUTION\", this.exprParser.expr());\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"COMMENT\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"COMMENT\", this.exprParser.expr());\n                continue;\n            }\n            if (lexer.nextIfIdentifier(\"AFTER\")) {\n                stmt.putAttribute(\"AFTER\", this.exprParser.name());\n                continue;\n            }\n            if (lexer.nextIf(Token.WHEN)) {\n                stmt.putAttribute(\"WHEN\", this.exprParser.expr());\n                continue;\n            }\n            break;\n        }\n    }\n\n    // ==================== ALTER STREAM ====================\n\n    public SQLStatement parseAlterStream() {\n        accept(Token.ALTER);\n        acceptIdentifier(\"STREAM\");\n        return parseAlterStreamRest();\n    }\n\n    private SQLStatement parseAlterStreamRest() {\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.putAttribute(\"objectType\", \"STREAM\");\n\n        lexer.nextIf(Token.IF);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.nextIfIdentifier(\"RENAME\")) {\n            accept(Token.TO);\n            stmt.putAttribute(\"NEW_NAME\", this.exprParser.name());\n        } else if (lexer.nextIf(Token.SET)) {\n            if (lexer.nextIfIdentifier(\"COMMENT\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"COMMENT\", this.exprParser.expr());\n            }\n        } else if (lexer.nextIfIdentifier(\"UNSET\")) {\n            lexer.nextIfIdentifier(\"COMMENT\");\n        }\n\n        return stmt;\n    }\n\n    // ==================== ALTER PIPE ====================\n\n    public SQLStatement parseAlterPipe() {\n        accept(Token.ALTER);\n        acceptIdentifier(\"PIPE\");\n        return parseAlterPipeRest();\n    }\n\n    private SQLStatement parseAlterPipeRest() {\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.putAttribute(\"objectType\", \"PIPE\");\n\n        lexer.nextIf(Token.IF);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.nextIfIdentifier(\"RENAME\")) {\n            accept(Token.TO);\n            stmt.putAttribute(\"NEW_NAME\", this.exprParser.name());\n        } else if (lexer.nextIf(Token.SET)) {\n            if (lexer.nextIfIdentifier(\"COMMENT\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"COMMENT\", this.exprParser.expr());\n            }\n        } else if (lexer.nextIfIdentifier(\"UNSET\")) {\n            lexer.nextIfIdentifier(\"COMMENT\");\n        } else if (lexer.nextIfIdentifier(\"REFRESH\")) {\n            if (lexer.nextIfIdentifier(\"PREFIX\")) {\n                lexer.nextIf(Token.EQ);\n                this.exprParser.expr();\n            }\n        } else if (lexer.nextIfIdentifier(\"PAUSE\") || lexer.nextIfIdentifier(\"RESUME\")) {\n            stmt.putAttribute(\"ACTION\", lexer.stringVal());\n        }\n\n        return stmt;\n    }\n\n    // ==================== ALTER FILE FORMAT ====================\n\n    public SQLStatement parseAlterFileFormat() {\n        accept(Token.ALTER);\n        lexer.nextIfIdentifier(\"FILE\");\n        lexer.nextIfIdentifier(\"FORMAT\");\n        return parseAlterFileFormatRest();\n    }\n\n    private SQLStatement parseAlterFileFormatRest() {\n        SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType());\n        stmt.putAttribute(\"objectType\", \"FILE_FORMAT\");\n\n        lexer.nextIf(Token.IF);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.nextIfIdentifier(\"RENAME\")) {\n            accept(Token.TO);\n            stmt.putAttribute(\"NEW_NAME\", this.exprParser.name());\n        } else if (lexer.nextIf(Token.SET)) {\n            if (lexer.nextIfIdentifier(\"COMMENT\")) {\n                lexer.nextIf(Token.EQ);\n                stmt.putAttribute(\"COMMENT\", this.exprParser.expr());\n            }\n        }\n\n        return stmt;\n    }\n\n    // ==================== COMMIT ====================\n\n    public SQLStatement parseCommit() {\n        accept(Token.COMMIT);\n        SQLCommitStatement stmt = new SQLCommitStatement();\n        stmt.setDbType(getDbType());\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/Spark.java",
    "content": "package com.alibaba.druid.sql.dialect.spark;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Spark {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.spark);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/ast/SparkCreateTableStatement.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.visitor.SparkASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author peiheng.qph\n * @version $Id: AntsparkCreateTableStatement.java, v 0.1 2018年09月14日 15:02 peiheng.qph Exp $\n */\npublic class SparkCreateTableStatement extends HiveCreateTableStatement {\n    protected List<SQLAssignItem> mappedBy = new ArrayList<SQLAssignItem>(1);\n    protected List<SQLExpr> skewedBy = new ArrayList<SQLExpr>();\n    protected List<SQLExpr> skewedByOn = new ArrayList<SQLExpr>();\n    protected Map<String, SQLObject> serdeProperties = new LinkedHashMap<String, SQLObject>();\n    protected SQLExprTableSource datasource;\n\n    public SparkCreateTableStatement() {\n        super(DbType.spark);\n    }\n\n    public List<SQLAssignItem> getMappedBy() {\n        return mappedBy;\n    }\n\n    public List<SQLExpr> getSkewedBy() {\n        return skewedBy;\n    }\n\n    public void addSkewedBy(SQLExpr item) {\n        item.setParent(this);\n        this.skewedBy.add(item);\n    }\n\n    public List<SQLExpr> getSkewedByOn() {\n        return skewedByOn;\n    }\n\n    public void addSkewedByOn(SQLExpr item) {\n        item.setParent(this);\n        this.skewedByOn.add(item);\n    }\n\n    public Map<String, SQLObject> getSerdeProperties() {\n        return serdeProperties;\n    }\n\n    public void setDatasource(SQLExpr datasource) {\n        this.datasource = new SQLExprTableSource(datasource);\n    }\n\n    /**\n     * Getter method for property datasource.\n     *\n     * @return property value of datasource\n     */\n    public SQLExprTableSource getDatasource() {\n        return datasource;\n    }\n\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SparkASTVisitor) {\n            accept0((SparkASTVisitor) v);\n            return;\n        }\n        super.accept0(v);\n    }\n\n    protected void accept0(SparkASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v);\n        }\n        v.endVisit(this);\n    }\n\n    protected void acceptChild(SQLASTVisitor v) {\n        super.acceptChild(v);\n\n        acceptChild(v, datasource);\n        acceptChild(v, skewedBy);\n        acceptChild(v, skewedByOn);\n        for (SQLObject item : serdeProperties.values()) {\n            acceptChild(v, item);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/ast/stmt/SparkCacheTableStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.spark.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.dialect.spark.visitor.SparkASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SparkCacheTableStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n    private SQLSelect query;\n    protected List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n    private boolean lazy;\n    private boolean as;\n\n    public SparkCacheTableStatement() {\n        this.dbType = DbType.spark;\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLSelect getQuery() {\n        return query;\n    }\n\n    public void setQuery(SQLSelectQuery query) {\n        this.setQuery(new SQLSelect(query));\n    }\n\n    public void setQuery(SQLSelect query) {\n        if (query != null) {\n            query.setParent(this);\n        }\n        this.query = query;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void addOption(SQLAssignItem item) {\n        item.setParent(this);\n        this.options.add(item);\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        addOption(assignItem);\n    }\n\n    public boolean isLazy() {\n        return lazy;\n    }\n\n    public void setLazy(boolean lazy) {\n        this.lazy = lazy;\n    }\n\n    public boolean isAs() {\n        return as;\n    }\n\n    public void setAs(boolean as) {\n        this.as = as;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SparkASTVisitor) {\n            this.accept0((SparkASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    public void accept0(SparkASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, query);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        if (this.query != null) {\n            children.add(query);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/ast/stmt/SparkCreateScanStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.spark.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.dialect.spark.visitor.SparkASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SparkCreateScanStatement extends SQLStatementImpl implements SQLCreateStatement {\n    private SQLName name;\n    private SQLExprTableSource on;\n    protected SQLExpr using;\n    protected List<SQLAssignItem> options = new ArrayList<SQLAssignItem>();\n\n    public SparkCreateScanStatement() {\n        super(DbType.spark);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExprTableSource getOn() {\n        return on;\n    }\n\n    public void setOn(SQLExprTableSource on) {\n        if (on != null) {\n            on.setParent(this);\n        }\n        this.on = on;\n    }\n\n    public void setOn(SQLName on) {\n        this.setOn(new SQLExprTableSource(on));\n    }\n\n    public SQLExpr getUsing() {\n        return using;\n    }\n\n    public void setUsing(SQLExpr x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.using = x;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void addOption(SQLAssignItem item) {\n        item.setParent(this);\n        this.options.add(item);\n    }\n\n    public void addOption(String name, SQLExpr value) {\n        SQLAssignItem assignItem = new SQLAssignItem(new SQLIdentifierExpr(name), value);\n        assignItem.setParent(this);\n        addOption(assignItem);\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SparkASTVisitor) {\n            accept0((SparkASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    public void accept0(SparkASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, name);\n            acceptChild(visitor, on);\n        }\n        visitor.endVisit(this);\n    }\n\n    @Override\n    public List<SQLObject> getChildren() {\n        List<SQLObject> children = new ArrayList<SQLObject>();\n        if (name != null) {\n            children.add(name);\n        }\n        if (this.on != null) {\n            children.add(on);\n        }\n        return children;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/parser/SparkCreateTableParser.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.parser;\n\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveCreateTableParser;\nimport com.alibaba.druid.sql.dialect.spark.ast.SparkCreateTableStatement;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.util.FnvHash;\n\n/**\n * @author peiheng.qph\n * @version $Id: AntsparkCreateTableParser.java, v 0.1 2018年09月14日 15:03 peiheng.qph Exp $\n */\npublic class SparkCreateTableParser extends HiveCreateTableParser {\n    public SparkCreateTableParser(String sql) {\n        super(new SparkExprParser(sql));\n    }\n\n    public SparkCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement stmt) {\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            lexer.nextToken();\n            stmt.setExternal(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.TEMPORARY)) {\n            lexer.nextToken();\n            stmt.setTemporary(true);\n        }\n    }\n\n    private void parseRowFormat(SparkCreateTableStatement stmt) {\n    }\n\n    private void parseSortedBy(SparkCreateTableStatement stmt) {\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new SparkSelectParser(this.exprParser, selectListCache);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/parser/SparkExprParser.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLExternalRecordFormat;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveExprParser;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\n/**\n * @author peiheng.qph\n * @version $Id: AntsparkExprParser.java, v 0.1 2018年09月14日 15:04 peiheng.qph Exp $\n */\npublic class SparkExprParser extends HiveExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\", \"ROW_NUMBER\",\n                \"ROWNUMBER\"};\n\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public SparkExprParser(String sql) {\n        this(new SparkLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public SparkExprParser(String sql, SQLParserFeature... features) {\n        this(new SparkLexer(sql, features));\n        this.lexer.nextToken();\n    }\n    public SparkExprParser(Lexer lexer) {\n        this(lexer, DbType.spark);\n    }\n\n    public SparkExprParser(Lexer lexer, DbType dbType) {\n        super(lexer, dbType);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n    public SQLExpr primaryRest(SQLExpr expr) {\n        //        if(lexer.token() == Token.COLON) {\n        //            lexer.nextToken();\n        //            expr = dotRest(expr);\n        //            return expr;\n        //        }\n\n        if (lexer.token() == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            array.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            return primaryRest(array);\n        }\n\n        if (expr instanceof SQLCharExpr\n                && lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            ((SQLCharExpr) expr).setCollate(lexer.stringVal());\n            accept(Token.IDENTIFIER);\n        }\n\n        while (lexer.nextIf(Token.COLONCOLON)) {\n            expr = new SQLCastExpr(expr, parseDataType());\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    public SQLExpr primary() {\n        final Token tok = lexer.token();\n        switch (tok) {\n            case LIKE:\n                Lexer.SavePoint mark = lexer.markOut();\n                lexer.nextToken();\n                if (lexer.nextIf(Token.LPAREN)) {\n                    SQLExpr left = expr();\n                    accept(Token.COMMA);\n                    SQLExpr right = expr();\n                    accept(Token.RPAREN);\n                    return primaryRest(\n                            new SQLBinaryOpExpr(left, SQLBinaryOperator.Like, right)\n                    );\n                } else {\n                    lexer.reset(mark);\n                }\n                break;\n            case IDENTIFIER:\n                final long hash_lower = lexer.hashLCase();\n                if (hash_lower == FnvHash.Constants.OUTLINE) {\n                    lexer.nextToken();\n                    SQLExpr file = primary();\n                    SQLExpr expr = new MySqlOutFileExpr(file);\n\n                    return primaryRest(expr);\n                }\n\n                if (hash_lower == FnvHash.Constants.X) {\n                    String x = lexer.stringVal();\n                    lexer.nextToken();\n                    SQLExpr expr;\n                    if (lexer.token() == Token.LITERAL_CHARS) {\n                        expr = new SQLHexExpr(lexer.stringVal());\n                        lexer.nextToken();\n                    } else {\n                        expr = new SQLCharExpr(x);\n                    }\n                    return primaryRest(expr);\n                }\n\n                SQLCurrentTimeExpr currentTimeExpr = null;\n                if (hash_lower == FnvHash.Constants.CURRENT_TIMESTAMP) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_TIMESTAMP);\n                } else if (hash_lower == FnvHash.Constants.CURRENT_DATE) {\n                    currentTimeExpr = new SQLCurrentTimeExpr(SQLCurrentTimeExpr.Type.CURRENT_DATE);\n                } else if (hash_lower == FnvHash.Constants.CURRENT_USER && isEnabled(SQLParserFeature.EnableCurrentUserExpr)) {\n                    lexer.nextToken();\n                    return primaryRest(new SQLCurrentUserExpr());\n                }\n\n                if (currentTimeExpr != null) {\n                    String methodName = lexer.stringVal();\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.LPAREN) {\n                        lexer.nextToken();\n                        if (lexer.token() == Token.LPAREN) {\n                            lexer.nextToken();\n                        } else {\n                            return primaryRest(\n                                    methodRest(new SQLIdentifierExpr(methodName), false)\n                            );\n                        }\n                    }\n\n                    return primaryRest(currentTimeExpr);\n                }\n                break;\n            default:\n                break;\n        }\n\n        return super.primary();\n    }\n\n    public SQLExternalRecordFormat parseRowFormat() {\n        lexer.nextToken();\n        acceptIdentifier(\"FORMAT\");\n\n        if (lexer.identifierEquals(FnvHash.Constants.DELIMITED)) {\n            lexer.nextToken();\n        }\n\n        SQLExternalRecordFormat format = new SQLExternalRecordFormat();\n\n        if (lexer.identifierEquals(FnvHash.Constants.FIELDS)) {\n            lexer.nextToken();\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n\n            format.setTerminatedBy(this.expr());\n        } else if (lexer.identifierEquals(\"FIELD\")) {\n            throw new ParserException(\"syntax error, expect FIELDS, \" + lexer.info());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LINES)) {\n            lexer.nextToken();\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n\n            format.setLinesTerminatedBy(this.expr());\n        }\n\n        if (lexer.token() == Token.ESCAPE || lexer.identifierEquals(FnvHash.Constants.ESCAPED)) {\n            lexer.nextToken();\n            accept(Token.BY);\n            format.setEscapedBy(this.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COLLECTION)) {\n            lexer.nextToken();\n            acceptIdentifier(\"ITEMS\");\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n            format.setCollectionItemsTerminatedBy(this.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.MAP)) {\n            lexer.nextToken();\n            acceptIdentifier(\"KEYS\");\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n            format.setMapKeysTerminatedBy(this.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SERDE)) {\n            lexer.nextToken();\n            format.setSerde(this.expr());\n        }\n\n        return format;\n    }\n\n    protected SQLExpr parseAliasExpr(String alias) {\n        String chars = alias.substring(1, alias.length() - 1);\n        return new SQLCharExpr(chars);\n    }\n\n    protected SQLExpr parseDatasource(String alias) {\n        String chars = alias.substring(1, alias.length() - 1);\n        return new SQLCharExpr(chars);\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.identifierEquals(FnvHash.Constants.MAPPED)) {\n            lexer.nextToken();\n            accept(Token.BY);\n            this.parseAssignItem(column.getMappedBy(), column);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COLPROPERTIES)) {\n            lexer.nextToken();\n            this.parseAssignItem(column.getColProperties(), column);\n        }\n\n        return super.parseColumnRest(column);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/parser/SparkLexer.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveLexer;\nimport com.alibaba.druid.sql.parser.DialectFeature;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.NextTokenColon;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.ScanAliasU;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.ScanSQLTypeWithFrom;\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\n/**\n * @author peiheng.qph\n * @version $Id: AntsparkLexer.java, v 0.1 2018年09月14日 15:04 peiheng.qph Exp $\n */\npublic class SparkLexer extends HiveLexer {\n    static final Keywords SPARK_KEYWORDS;\n    static final DialectFeature SPARK_FEATURE = new DialectFeature(\n            Arrays.asList(\n                    QueryTable,\n                    ParseSelectItemPrefixX,\n                    JoinRightTableFrom,\n                    ScanSQLTypeWithFrom,\n                    NextTokenColon,\n                    ScanAliasU,\n                    JoinRightTableFrom,\n                    GroupByAll,\n                    SQLDateExpr,\n                    ParseAssignItemRparenCommaSetReturn,\n                    TableAliasLock,\n                    TableAliasPartition,\n                    AsSkip,\n                    AsSequence,\n                    AsDatabase,\n                    AsDefault\n            ),\n            Collections.singletonList(\n                    PrimaryBangBangSupport\n            )\n    );\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"USING\", Token.USING);\n\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"PARTITIONED\", Token.PARTITIONED);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n        //        map.put(\"SORT\", Token.SORT);\n        map.put(\"IF\", Token.IF);\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"RLIKE\", Token.RLIKE);\n        map.put(\"CONSTRAINT\", Token.CONSTRAINT);\n        map.put(\"CACHE\", Token.CACHE);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n        map.put(\"OR\", Token.OR);\n\n        SPARK_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return SPARK_KEYWORDS;\n    }\n\n    public SparkLexer(String input) {\n        this(input, DbType.spark);\n    }\n\n    public SparkLexer(String input, DbType dbType) {\n        super(input, dbType);\n    }\n\n    public SparkLexer(String input, SQLParserFeature... features) {\n        super(input, DbType.spark, features);\n    }\n    public SparkLexer(String input, DbType dbType, SQLParserFeature... features) {\n        super(input, dbType, features);\n    }\n    @Override\n    protected void initDialectFeature() {\n        this.dialectFeature = SPARK_FEATURE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/parser/SparkSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.spark.parser;\n\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\n\npublic class SparkSelectParser extends HiveSelectParser {\n    public SparkSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SparkSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/parser/SparkStatementParser.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLShowFunctionsStatement;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser;\nimport com.alibaba.druid.sql.dialect.spark.ast.stmt.SparkCacheTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.ast.stmt.SparkCreateScanStatement;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\n/**\n * @author peiheng.qph\n * @version $Id: AntsparkStateMentParser.java, v 0.1 2018年09月14日 15:07 peiheng.qph Exp $\n */\npublic class SparkStatementParser extends HiveStatementParser {\n    public SparkStatementParser(String sql) {\n        super(new SparkExprParser(sql));\n    }\n\n    public SparkStatementParser(Lexer lexer) {\n        super(lexer);\n    }\n\n    public SparkStatementParser(String sql, SQLParserFeature... features) {\n        super(new SparkExprParser(sql, features));\n    }\n\n    public SparkStatementParser(SQLExprParser sqlExprParser) {\n        super(sqlExprParser);\n    }\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new SparkCreateTableParser(this.exprParser);\n    }\n\n    protected void alterTableUnset(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"TBLPROPERTIES\");\n        accept(Token.LPAREN);\n        exprParser.names(stmt.getUnsetTableOptions(), stmt);\n        accept(Token.RPAREN);\n    }\n\n    public SQLStatement parseCreateScan() {\n        SparkCreateScanStatement stmt = new SparkCreateScanStatement();\n        accept(Token.CREATE);\n        acceptIdentifier(\"SCAN\");\n        stmt.setName(exprParser.name());\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            stmt.setOn(this.exprParser.name());\n        }\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n            stmt.setUsing(this.exprParser.expr());\n        }\n        if (lexer.identifierEquals(\"OPTIONS\")) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                SQLAssignItem item = this.exprParser.parseAssignItem();\n                stmt.addOption(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n\n        return stmt;\n    }\n\n    public SparkCacheTableStatement parseCache() {\n        accept(Token.CACHE);\n        SparkCacheTableStatement stmt = new SparkCacheTableStatement();\n        if (lexer.identifierEquals(\"LAZY\")) {\n            lexer.nextToken();\n            stmt.setLazy(true);\n        }\n        accept(Token.TABLE);\n        stmt.setName(exprParser.name());\n        if (lexer.identifierEquals(\"OPTIONS\")) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                SQLAssignItem item = this.exprParser.parseAssignItem();\n                stmt.addOption(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n            accept(Token.RPAREN);\n        }\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n            stmt.setAs(true);\n        }\n        if (!lexer.isEOF()) {\n            SQLSelectParser selectParser = createSQLSelectParser();\n            SQLSelect query = selectParser.select();\n            stmt.setQuery(query);\n        }\n\n        return stmt;\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.identifierEquals(FnvHash.Constants.SHOW)) {\n            Lexer.SavePoint savePoint = this.lexer.mark();\n            lexer.nextToken();\n            if (lexer.token() == Token.USER\n                || lexer.identifierEquals(FnvHash.Constants.SYSTEM)\n                || lexer.token() == Token.ALL\n                || lexer.identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n                SQLShowFunctionsStatement stmt = new SQLShowFunctionsStatement();\n\n                if (!lexer.identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n                    SQLName name = this.exprParser.name();\n                    stmt.setKind(name);\n                }\n                if (lexer.identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n                    lexer.nextToken();\n\n                    if (lexer.token() == Token.LIKE) {\n                        lexer.nextToken();\n                        SQLExpr like = this.exprParser.expr();\n                        stmt.setLike(like);\n                    }\n                    statementList.add(stmt);\n                    return true;\n                }\n            }\n            lexer.reset(savePoint);\n        }\n        return super.parseStatementListDialect(statementList);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/visitor/SparkASTVisitor.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.visitor;\n\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor;\nimport com.alibaba.druid.sql.dialect.spark.ast.SparkCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.ast.stmt.SparkCacheTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.ast.stmt.SparkCreateScanStatement;\n\n/**\n * @author peiheng.qph\n * @version $Id: AntsparkVisitor.java, v 0.1 2018年09月14日 15:07 peiheng.qph Exp $\n */\npublic interface SparkASTVisitor extends HiveASTVisitor {\n    default boolean visit(SparkCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SparkCreateTableStatement x) {}\n\n    default boolean visit(SparkCreateScanStatement x) {\n        return true;\n    }\n\n    default void endVisit(SparkCreateScanStatement x) {\n    }\n\n    default boolean visit(SparkCacheTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SparkCacheTableStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/visitor/SparkOutputASTVisitor.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLHexExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveOutputVisitor;\nimport com.alibaba.druid.sql.dialect.spark.Spark;\nimport com.alibaba.druid.sql.dialect.spark.ast.SparkCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.ast.stmt.SparkCacheTableStatement;\nimport com.alibaba.druid.sql.dialect.spark.ast.stmt.SparkCreateScanStatement;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\n\nimport java.util.Map;\nimport java.util.Map.Entry;\n\n/**\n * @author peiheng.qph\n * @version $Id: SparkOutputVisitor.java, v 0.1 2018年09月17日 10:40 peiheng.qph Exp $\n */\npublic class SparkOutputASTVisitor extends HiveOutputVisitor implements SparkASTVisitor {\n    public SparkOutputASTVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect) {\n        super(appender, dbType, dialect);\n    }\n\n    public SparkOutputASTVisitor(StringBuilder appender) {\n        super(appender, DbType.spark, Spark.DIALECT);\n    }\n\n    //add using statment\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        if (x instanceof SparkCreateTableStatement) {\n            return visit((SparkCreateTableStatement) x);\n        }\n        return super.visit(x);\n    }\n\n    @Override\n    public boolean visit(SparkCreateTableStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        printCreateTableFeatures(x);\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"TABLE IF NOT EXISTS \" : \"table if not exists \");\n        } else {\n            print0(ucase ? \"TABLE \" : \"table \");\n        }\n\n        x.getName().accept(this);\n        printCreateTableLike(x);\n        printTableElementsWithComment(x);\n        printUsing(x);\n\n        printComment(x.getComment());\n        printPartitionedBy(x);\n        printClusteredBy(x);\n        printSortedBy(x.getSortedBy());\n        printIntoBuckets(x.getBuckets());\n        printStoredAs(x);\n        printSelectAs(x, true);\n        printTableOptions(x);\n        printLocation(x);\n        return false;\n    }\n\n    protected void printUsing(SparkCreateTableStatement x) {\n        if (x.getDatasource() != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            print0(x.getDatasource().toString());\n        }\n    }\n\n    protected void printTableOptions(SparkCreateTableStatement x) {\n        Map<String, SQLObject> serdeProperties = x.getSerdeProperties();\n        if (serdeProperties.size() > 0) {\n            println();\n            print0(ucase ? \"TBLPROPERTIES (\" : \"tblproperties (\");\n            String seperator = \"\";\n            for (Entry<String, SQLObject> entry : serdeProperties.entrySet()) {\n                print0(\"'\" + entry.getKey() + \"'='\");\n                entry.getValue().accept(this);\n                print0(\"'\" + seperator);\n                seperator = \",\";\n            }\n            print(')');\n        }\n    }\n\n    @Override\n    public boolean visit(SQLHexExpr x) {\n        if (this.parameterized) {\n            print('?');\n            incrementReplaceCunt();\n\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            return false;\n        }\n\n        print0(\"x'\");\n        print0(x.getHex());\n        print('\\'');\n        return false;\n    }\n\n    public boolean visit(SparkCreateScanStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        print0(ucase ? \"SCAN \" : \"scan \");\n\n        x.getName().accept(this);\n        if (x.getOn() != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            x.getOn().accept(this);\n        }\n\n        SQLExpr using = x.getUsing();\n        if (using != null) {\n            println();\n            print0(ucase ? \"USING \" : \"using \");\n            printExpr(using);\n        }\n\n        if (x.getOptions().size() > 0) {\n            print0(ucase ? \" OPTIONS (\" : \" options (\");\n            printAndAccept(x.getOptions(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    public boolean visit(SparkCacheTableStatement x) {\n        print0(ucase ? \"CACHE \" : \"cache \");\n        if (x.isLazy()) {\n            print0(ucase ? \" LAZY \" : \" lazy \");\n        }\n        print0(ucase ? \"TABLE \" : \"table \");\n        x.getName().accept(this);\n\n        if (x.getOptions().size() > 0) {\n            print0(ucase ? \" OPTIONS (\" : \" options (\");\n            printAndAccept(x.getOptions(), \", \");\n            print(')');\n        }\n\n        if (x.isAs()) {\n            print0(ucase ? \" AS \" : \" as \");\n        }\n\n        SQLSelect query = x.getQuery();\n        if (query != null) {\n            print(' ');\n            query.accept(this);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/spark/visitor/SparkSchemaStatASTVisitor.java",
    "content": "/**\n * Alipay.com Inc.\n * Copyright (c) 2004-2018 All Rights Reserved.\n */\npackage com.alibaba.druid.sql.dialect.spark.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor;\nimport com.alibaba.druid.sql.dialect.spark.ast.SparkCreateTableStatement;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\n\n/**\n * @author peiheng.qph\n * @version $Id: AntsparkSchemaStatVisitor.java, v 0.1 2018年09月16日 23:09 peiheng.qph Exp $\n */\npublic class SparkSchemaStatASTVisitor extends HiveSchemaStatVisitor implements SparkASTVisitor {\n    {\n        dbType = DbType.spark;\n    }\n\n    public SparkSchemaStatASTVisitor() {\n        super(DbType.spark);\n    }\n\n    public SparkSchemaStatASTVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    @Override\n    public boolean visit(SparkCreateTableStatement x) {\n        return super.visit((SQLCreateTableStatement) x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/SQLite.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class SQLite {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.sqlite);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/ast/SQLiteAttachStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLiteAttachStatement extends SQLStatementImpl {\n    private SQLExpr database;\n    private SQLName schemaName;\n\n    public SQLiteAttachStatement() {\n        super(DbType.sqlite);\n    }\n\n    public SQLExpr getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(SQLExpr database) {\n        if (database != null) {\n            database.setParent(this);\n        }\n        this.database = database;\n    }\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        if (schemaName != null) {\n            schemaName.setParent(this);\n        }\n        this.schemaName = schemaName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLiteASTVisitor) {\n            accept0((SQLiteASTVisitor) v);\n        }\n    }\n\n    protected void accept0(SQLiteASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, database);\n            acceptChild(v, schemaName);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/ast/SQLiteDetachStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLiteDetachStatement extends SQLStatementImpl {\n    private SQLName schemaName;\n\n    public SQLiteDetachStatement() {\n        super(DbType.sqlite);\n    }\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        if (schemaName != null) {\n            schemaName.setParent(this);\n        }\n        this.schemaName = schemaName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLiteASTVisitor) {\n            accept0((SQLiteASTVisitor) v);\n        }\n    }\n\n    protected void accept0(SQLiteASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, schemaName);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/ast/SQLitePragmaStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLitePragmaStatement extends SQLStatementImpl {\n    private SQLName name;\n    private SQLExpr value;\n\n    public SQLitePragmaStatement() {\n        super(DbType.sqlite);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    public SQLExpr getValue() {\n        return value;\n    }\n\n    public void setValue(SQLExpr value) {\n        if (value != null) {\n            value.setParent(this);\n        }\n        this.value = value;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLiteASTVisitor) {\n            accept0((SQLiteASTVisitor) v);\n        }\n    }\n\n    protected void accept0(SQLiteASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n            acceptChild(v, value);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/ast/SQLiteReindexStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLiteReindexStatement extends SQLStatementImpl {\n    private SQLName name;\n\n    public SQLiteReindexStatement() {\n        super(DbType.sqlite);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName name) {\n        if (name != null) {\n            name.setParent(this);\n        }\n        this.name = name;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLiteASTVisitor) {\n            accept0((SQLiteASTVisitor) v);\n        }\n    }\n\n    protected void accept0(SQLiteASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, name);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/ast/SQLiteVacuumStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLiteVacuumStatement extends SQLStatementImpl {\n    private SQLName schemaName;\n\n    public SQLiteVacuumStatement() {\n        super(DbType.sqlite);\n    }\n\n    public SQLName getSchemaName() {\n        return schemaName;\n    }\n\n    public void setSchemaName(SQLName schemaName) {\n        if (schemaName != null) {\n            schemaName.setParent(this);\n        }\n        this.schemaName = schemaName;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLiteASTVisitor) {\n            accept0((SQLiteASTVisitor) v);\n        }\n    }\n\n    protected void accept0(SQLiteASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, schemaName);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/parser/SQLiteExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.parser;\n\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class SQLiteExprParser extends SQLExprParser {\n    private static final String[] AGGREGATE_FUNCTIONS;\n    private static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"AVG\", \"COUNT\", \"GROUP_CONCAT\", \"MAX\", \"MIN\", \"SUM\", \"TOTAL\"\n        };\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public SQLiteExprParser(String sql) {\n        this(new SQLiteLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public SQLiteExprParser(String sql, SQLParserFeature... features) {\n        this(new SQLiteLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public SQLiteExprParser(Lexer lexer) {\n        super(lexer);\n        dbType = lexer.getDbType();\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        column = super.parseColumnRest(column);\n\n        if (lexer.identifierEquals(\"AUTOINCREMENT\")\n                || lexer.identifierEquals(\"AUTO_INCREMENT\")) {\n            lexer.nextToken();\n            column.setAutoIncrement(true);\n        }\n\n        return column;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/parser/SQLiteLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.Token.IDENTIFIER;\n\npublic class SQLiteLexer extends Lexer {\n    static final Keywords SQLITE_KEYWORDS;\n\n    static {\n        Map<String, Token> map = new HashMap<>();\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"LIMIT\", Token.LIMIT);\n        map.put(\"IF\", Token.IF);\n        map.put(\"OF\", Token.OF);\n        map.put(\"REPLACE\", Token.REPLACE);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"ROW\", Token.ROW);\n        map.put(\"CONCAT\", Token.CONCAT);\n\n        SQLITE_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return SQLITE_KEYWORDS;\n    }\n\n    public SQLiteLexer(String input) {\n        super(input, null, DbType.sqlite);\n    }\n\n    public SQLiteLexer(String input, SQLParserFeature... features) {\n        super(input, null, DbType.sqlite);\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    @Override\n    protected void scanLBracket() {\n        mark = pos;\n\n        if (buf == null) {\n            buf = new char[32];\n        }\n\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == ']') {\n                scanChar();\n                token = IDENTIFIER;\n                break;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        stringVal = subString(mark, bufPos + 2);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/parser/SQLiteSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.parser;\n\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\n\npublic class SQLiteSelectParser extends SQLSelectParser {\n    public SQLiteSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SQLiteSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public SQLiteSelectParser(String sql) {\n        this(new SQLiteExprParser(sql));\n    }\n\n    protected SQLExprParser createExprParser() {\n        return new SQLiteExprParser(lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/parser/SQLiteStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.parser;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLReplaceStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.dialect.sqlite.ast.*;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.List;\n\npublic class SQLiteStatementParser extends SQLStatementParser {\n    public SQLiteStatementParser(String sql) {\n        super(new SQLiteExprParser(sql));\n    }\n\n    public SQLiteStatementParser(String sql, SQLParserFeature... features) {\n        super(new SQLiteExprParser(sql, features));\n    }\n\n    public SQLiteStatementParser(Lexer lexer) {\n        super(new SQLiteExprParser(lexer));\n    }\n\n    public SQLiteSelectParser createSQLSelectParser() {\n        return new SQLiteSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n        SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(getDbType());\n\n        if (lexer.token() == Token.UNIQUE) {\n            stmt.setType(\"UNIQUE\");\n            lexer.nextToken();\n        }\n\n        accept(Token.INDEX);\n\n        if (lexer.token() == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n        accept(Token.ON);\n        stmt.setTable(this.exprParser.name());\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n            item.setParent(stmt);\n            stmt.addItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseInsert() {\n        if (lexer.token() == Token.INSERT) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.OR) {\n            lexer.nextToken();\n            String action = lexer.stringVal().toUpperCase();\n            lexer.nextToken();\n\n            if (\"REPLACE\".equals(action)) {\n                SQLReplaceStatement stmt = new SQLReplaceStatement();\n                stmt.setDbType(getDbType());\n                accept(Token.INTO);\n                stmt.setTableName(exprParser.name());\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    this.exprParser.exprList(stmt.getColumns(), stmt);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.token() == Token.VALUES || lexer.identifierEquals(\"VALUE\")) {\n                    lexer.nextToken();\n                    parseValueClause(stmt.getValuesList(), null, 0, stmt);\n                } else if (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN) {\n                    SQLSelect select = this.createSQLSelectParser().select();\n                    SQLQueryExpr queryExpr = new SQLQueryExpr(select);\n                    stmt.setQuery(queryExpr);\n                }\n\n                return stmt;\n            }\n\n            // INSERT OR IGNORE/ABORT/ROLLBACK/FAIL -> parse as regular INSERT\n            SQLInsertStatement stmt = new SQLInsertStatement();\n            stmt.setDbType(getDbType());\n            parseInsert0(stmt);\n            return stmt;\n        }\n\n        SQLInsertStatement stmt = new SQLInsertStatement();\n        stmt.setDbType(getDbType());\n        parseInsert0(stmt);\n        return stmt;\n    }\n\n    @Override\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        String identifier = null;\n        if (lexer.token() == Token.IDENTIFIER) {\n            identifier = lexer.stringVal();\n        }\n\n        if (identifier == null) {\n            return false;\n        }\n\n        String upperIdent = identifier.toUpperCase();\n        switch (upperIdent) {\n            case \"PRAGMA\":\n                statementList.add(parsePragma());\n                return true;\n            case \"ATTACH\":\n                statementList.add(parseAttach());\n                return true;\n            case \"DETACH\":\n                statementList.add(parseDetach());\n                return true;\n            case \"VACUUM\":\n                statementList.add(parseVacuum());\n                return true;\n            case \"REINDEX\":\n                statementList.add(parseReindex());\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    private SQLitePragmaStatement parsePragma() {\n        lexer.nextToken(); // skip PRAGMA\n\n        SQLitePragmaStatement stmt = new SQLitePragmaStatement();\n        stmt.setName(exprParser.name());\n\n        if (lexer.token() == Token.EQ) {\n            lexer.nextToken();\n            stmt.setValue(exprParser.expr());\n        } else if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            stmt.setValue(exprParser.expr());\n            accept(Token.RPAREN);\n        }\n\n        return stmt;\n    }\n\n    private SQLiteAttachStatement parseAttach() {\n        lexer.nextToken(); // skip ATTACH\n\n        SQLiteAttachStatement stmt = new SQLiteAttachStatement();\n\n        if (lexer.token() == Token.DATABASE) {\n            lexer.nextToken();\n        }\n\n        stmt.setDatabase(exprParser.expr());\n        accept(Token.AS);\n        stmt.setSchemaName(exprParser.name());\n\n        return stmt;\n    }\n\n    private SQLiteDetachStatement parseDetach() {\n        lexer.nextToken(); // skip DETACH\n\n        SQLiteDetachStatement stmt = new SQLiteDetachStatement();\n\n        if (lexer.token() == Token.DATABASE) {\n            lexer.nextToken();\n        }\n\n        stmt.setSchemaName(exprParser.name());\n\n        return stmt;\n    }\n\n    private SQLiteVacuumStatement parseVacuum() {\n        lexer.nextToken(); // skip VACUUM\n\n        SQLiteVacuumStatement stmt = new SQLiteVacuumStatement();\n\n        if (lexer.token() != Token.SEMI && lexer.token() != Token.EOF) {\n            stmt.setSchemaName(exprParser.name());\n        }\n\n        return stmt;\n    }\n\n    private SQLiteReindexStatement parseReindex() {\n        lexer.nextToken(); // skip REINDEX\n\n        SQLiteReindexStatement stmt = new SQLiteReindexStatement();\n\n        if (lexer.token() != Token.SEMI && lexer.token() != Token.EOF) {\n            stmt.setName(exprParser.name());\n        }\n\n        return stmt;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/visitor/SQLiteASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.visitor;\n\nimport com.alibaba.druid.sql.dialect.sqlite.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface SQLiteASTVisitor extends SQLASTVisitor {\n    default boolean visit(SQLitePragmaStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLitePragmaStatement x) {\n    }\n\n    default boolean visit(SQLiteAttachStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLiteAttachStatement x) {\n    }\n\n    default boolean visit(SQLiteDetachStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLiteDetachStatement x) {\n    }\n\n    default boolean visit(SQLiteVacuumStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLiteVacuumStatement x) {\n    }\n\n    default boolean visit(SQLiteReindexStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLiteReindexStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/visitor/SQLiteASTVisitorAdapter.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class SQLiteASTVisitorAdapter extends SQLASTVisitorAdapter implements SQLiteASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/visitor/SQLiteEvalVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLiteEvalVisitor extends SQLiteASTVisitorAdapter implements SQLEvalVisitor {\n    private Map<String, Function> functions = new HashMap<String, Function>();\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public SQLiteEvalVisitor() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public SQLiteEvalVisitor(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLUnaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/visitor/SQLiteOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.sqlite.SQLite;\nimport com.alibaba.druid.sql.dialect.sqlite.ast.*;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\npublic class SQLiteOutputVisitor extends SQLASTOutputVisitor implements SQLiteASTVisitor {\n    public SQLiteOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.sqlite, SQLite.DIALECT);\n    }\n\n    public SQLiteOutputVisitor(StringBuilder appender, DbType dbType) {\n        super(appender, dbType);\n    }\n\n    public SQLiteOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.sqlite, parameterized);\n    }\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        printCreateTable(x, true);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLitePragmaStatement x) {\n        printUcase(\"PRAGMA \");\n        x.getName().accept(this);\n        if (x.getValue() != null) {\n            print0(\" = \");\n            x.getValue().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLiteAttachStatement x) {\n        printUcase(\"ATTACH DATABASE \");\n        x.getDatabase().accept(this);\n        printUcase(\" AS \");\n        x.getSchemaName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLiteDetachStatement x) {\n        printUcase(\"DETACH DATABASE \");\n        x.getSchemaName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLiteVacuumStatement x) {\n        printUcase(\"VACUUM\");\n        if (x.getSchemaName() != null) {\n            print(' ');\n            x.getSchemaName().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLiteReindexStatement x) {\n        printUcase(\"REINDEX\");\n        if (x.getName() != null) {\n            print(' ');\n            x.getName().accept(this);\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlite/visitor/SQLiteSchemaStatVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlite.visitor;\n\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\npublic class SQLiteSchemaStatVisitor extends SchemaStatVisitor implements SQLiteASTVisitor {\n    public SQLiteSchemaStatVisitor() {\n    }\n\n    public SQLiteSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/SqlServer.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlserver;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class SqlServer {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.sqlserver);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast;\n\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.dialect.transact.ast.TransactSQLObject;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface SQLServerObject extends TransactSQLObject {\n    default void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) v);\n        }\n    }\n    void accept0(SQLServerASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerObjectImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\n\npublic abstract class SQLServerObjectImpl extends SQLObjectImpl implements SQLServerObject {\n    public SQLServerObjectImpl() {\n    }\n\n    public abstract void accept0(SQLServerASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerOutput.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLServerOutput extends SQLServerObjectImpl {\n    protected SQLExprTableSource into;\n\n    protected final List<SQLExpr> columns = new ArrayList<SQLExpr>();\n\n    protected final List<SQLSelectItem> selectList = new ArrayList<SQLSelectItem>();\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, selectList);\n            this.acceptChild(visitor, into);\n            this.acceptChild(visitor, columns);\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public SQLExprTableSource getInto() {\n        return into;\n    }\n\n    public void setInto(SQLExprTableSource into) {\n        this.into = into;\n    }\n\n    public List<SQLExpr> getColumns() {\n        return columns;\n    }\n\n    public List<SQLSelectItem> getSelectList() {\n        return selectList;\n    }\n\n    public SQLServerOutput clone() {\n        SQLServerOutput x = new SQLServerOutput();\n        if (into != null) {\n            x.setInto(into.clone());\n        }\n        for (SQLExpr c : columns) {\n            SQLExpr c2 = c.clone();\n            c2.setParent(x);\n            x.columns.add(c2);\n        }\n        for (SQLSelectItem item : selectList) {\n            SQLSelectItem item2 = item.clone();\n            item2.setParent(x);\n            x.selectList.add(item2);\n        }\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerSelectQueryBlock.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLServerSelectQueryBlock extends SQLSelectQueryBlock {\n    private SQLTop top;\n    private List<SQLAssignItem> options = new ArrayList<>();\n\n    public SQLServerSelectQueryBlock() {\n        dbType = DbType.sqlserver;\n    }\n\n    public SQLTop getTop() {\n        return top;\n    }\n\n    public List<SQLAssignItem> getOptions() {\n        return options;\n    }\n\n    public void setTop(SQLTop top) {\n        if (top != null) {\n            top.setParent(this);\n        }\n        this.top = top;\n    }\n\n    public void setTop(int rowCount) {\n        setTop(new SQLTop(new SQLIntegerExpr(rowCount)));\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.top);\n            acceptChild(visitor, this.selectList);\n            acceptChild(visitor, this.from);\n            acceptChild(visitor, this.where);\n            acceptChild(visitor, this.groupBy);\n        }\n        visitor.endVisit(this);\n    }\n\n    public void limit(int rowCount, int offset) {\n        if (offset <= 0) {\n            setTop(rowCount);\n        } else {\n            throw new UnsupportedOperationException(\"not support offset\");\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\npublic interface SQLServerStatement extends SQLStatement, SQLServerObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerStatementImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic abstract class SQLServerStatementImpl extends SQLStatementImpl implements SQLServerStatement {\n    public SQLServerStatementImpl() {\n        super(DbType.sqlserver);\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) visitor);\n        }\n    }\n\n    public abstract void accept0(SQLServerASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\n\npublic interface SQLServerExpr extends SQLExpr {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.expr;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements SQLServerExpr, SQLName {\n    private String server;\n    private String database;\n    private String schema;\n\n    protected long schemaHashCode64;\n    protected long hashCode64;\n\n    public SQLServerObjectReferenceExpr() {\n    }\n\n    public SQLServerObjectReferenceExpr(SQLExpr owner) {\n        if (owner instanceof SQLIdentifierExpr) {\n            this.database = ((SQLIdentifierExpr) owner).getName();\n        } else if (owner instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propExpr = (SQLPropertyExpr) owner;\n\n            this.server = ((SQLIdentifierExpr) propExpr.getOwner()).getName();\n            this.database = propExpr.getName();\n        } else {\n            throw new IllegalArgumentException(owner.toString());\n        }\n    }\n\n    public String getSimpleName() {\n        if (schema != null) {\n            return schema;\n        }\n\n        if (database != null) {\n            return database;\n        }\n        return server;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public void output(StringBuilder buf) {\n        boolean flag = false;\n        if (server != null) {\n            buf.append(server);\n            flag = true;\n        }\n\n        if (flag) {\n            buf.append('.');\n        }\n        if (database != null) {\n            buf.append(database);\n            flag = true;\n        }\n\n        if (flag) {\n            buf.append('.');\n        }\n\n        if (schema != null) {\n            buf.append(schema);\n            flag = true;\n        }\n    }\n\n    public String getServer() {\n        return server;\n    }\n\n    public void setServer(String server) {\n        this.server = server;\n    }\n\n    public String getDatabase() {\n        return database;\n    }\n\n    public void setDatabase(String database) {\n        this.database = database;\n    }\n\n    public String getSchema() {\n        return schema;\n    }\n\n    public void setSchema(String schema) {\n        this.schema = schema;\n    }\n\n    public SQLServerObjectReferenceExpr clone() {\n        SQLServerObjectReferenceExpr x = new SQLServerObjectReferenceExpr();\n\n        x.server = server;\n        x.database = database;\n        x.schema = schema;\n\n        x.schemaHashCode64 = schemaHashCode64;\n        x.hashCode64 = hashCode64;\n\n        return x;\n    }\n\n    public long nameHashCode64() {\n        if (schemaHashCode64 == 0\n                && schema != null) {\n            schemaHashCode64 = FnvHash.hashCode64(schema);\n        }\n        return schemaHashCode64;\n    }\n\n    @Override\n    public long hashCode64() {\n        if (hashCode64 == 0) {\n            if (server == null) {\n                hashCode64 = new SQLPropertyExpr(\n                        new SQLPropertyExpr(server, database),\n                        schema\n                ).hashCode64();\n            } else {\n                hashCode64 = new SQLPropertyExpr(database, schema)\n                        .hashCode64();\n            }\n        }\n        return hashCode64;\n    }\n\n    @Override\n    public SQLColumnDefinition getResolvedColumn() {\n        return null;\n    }\n\n    public List<SQLObject> getChildren() {\n        return Collections.<SQLObject>emptyList();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerExecStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLServerExecStatement extends SQLServerStatementImpl implements SQLServerStatement {\n    private SQLName returnStatus;\n    private SQLName moduleName;\n    private List<SQLServerParameter> parameters = new ArrayList<SQLServerParameter>();\n\n    public SQLName getModuleName() {\n        return moduleName;\n    }\n\n    public void setModuleName(SQLName moduleName) {\n        this.moduleName = moduleName;\n    }\n\n    public List<SQLServerParameter> getParameters() {\n        return parameters;\n    }\n\n    public void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, this.returnStatus);\n            acceptChild(visitor, this.moduleName);\n            acceptChild(visitor, this.parameters);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLName getReturnStatus() {\n        return returnStatus;\n    }\n\n    public void setReturnStatus(SQLName returnStatus) {\n        this.returnStatus = returnStatus;\n    }\n\n    /**\n     * @author zz [455910092@qq.com]\n     */\n    public static class SQLServerParameter extends SQLServerObjectImpl {\n        private SQLExpr expr;\n        //sql server 支持参数只有input 和 output 两种\n        private boolean type;\n\n        public SQLExpr getExpr() {\n            return expr;\n        }\n\n        public void setExpr(SQLExpr expr) {\n            this.expr = expr;\n        }\n\n        public boolean getType() {\n            return type;\n        }\n\n        public void setType(boolean type) {\n            this.type = type;\n        }\n\n        @Override\n        public void accept0(SQLASTVisitor v) {\n            if (v instanceof SQLServerASTVisitor) {\n                ((SQLServerASTVisitor) v).visit(this);\n            }\n        }\n\n        @Override\n        public void accept0(SQLServerASTVisitor visitor) {\n            if (visitor.visit(this)) {\n                acceptChild(visitor, expr);\n            }\n            visitor.endVisit(this);\n\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerInsertStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObject;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLServerInsertStatement extends SQLInsertStatement implements SQLServerObject {\n    private boolean defaultValues;\n\n    private SQLTop top;\n\n    private SQLServerOutput output;\n\n    public SQLServerInsertStatement() {\n        dbType = DbType.sqlserver;\n    }\n\n    public void cloneTo(SQLServerInsertStatement x) {\n        super.cloneTo(x);\n        x.defaultValues = defaultValues;\n        if (top != null) {\n            x.setTop(top.clone());\n        }\n        if (output != null) {\n            x.setOutput(output.clone());\n        }\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) v);\n        } else {\n            super.accept0(v);\n        }\n    }\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            this.acceptChild(visitor, getTop());\n            this.acceptChild(visitor, getTableSource());\n            this.acceptChild(visitor, getColumns());\n            this.acceptChild(visitor, getOutput());\n            this.acceptChild(visitor, getValuesList());\n            this.acceptChild(visitor, getQuery());\n        }\n\n        visitor.endVisit(this);\n    }\n\n    public boolean isDefaultValues() {\n        return defaultValues;\n    }\n\n    public void setDefaultValues(boolean defaultValues) {\n        this.defaultValues = defaultValues;\n    }\n\n    public SQLServerOutput getOutput() {\n        return output;\n    }\n\n    public void setOutput(SQLServerOutput output) {\n        this.output = output;\n    }\n\n    public SQLTop getTop() {\n        return top;\n    }\n\n    public void setTop(SQLTop top) {\n        if (top != null) {\n            top.setParent(this);\n            top.setParentheses(true);\n        }\n        this.top = top;\n    }\n\n    public SQLServerInsertStatement clone() {\n        SQLServerInsertStatement x = new SQLServerInsertStatement();\n        cloneTo(x);\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerRollbackStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLRollbackStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLServerRollbackStatement extends SQLRollbackStatement implements SQLServerStatement {\n    private boolean work;\n\n    private SQLExpr name;\n\n    public boolean isWork() {\n        return work;\n    }\n\n    public void setWork(boolean work) {\n        this.work = work;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) visitor);\n        }\n    }\n\n    public void accept0(SQLServerASTVisitor visitor) {\n        visitor.visit(this);\n\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getName() {\n        return name;\n    }\n\n    public void setName(SQLExpr name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetTransactionIsolationLevelStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\n\npublic class SQLServerSetTransactionIsolationLevelStatement extends SQLServerStatementImpl implements SQLServerStatement {\n    private String level;\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n\n    public String getLevel() {\n        return level;\n    }\n\n    public void setLevel(String level) {\n        this.level = level;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerThrowStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLServerThrowStatement extends SQLStatementImpl implements SQLServerStatement {\n    private SQLExpr errorNumber;\n    private SQLExpr message;\n    private SQLExpr state;\n\n    public SQLServerThrowStatement() {\n        super(DbType.sqlserver);\n    }\n\n    public SQLExpr getErrorNumber() {\n        return errorNumber;\n    }\n\n    public void setErrorNumber(SQLExpr errorNumber) {\n        if (errorNumber != null) {\n            errorNumber.setParent(this);\n        }\n        this.errorNumber = errorNumber;\n    }\n\n    public SQLExpr getMessage() {\n        return message;\n    }\n\n    public void setMessage(SQLExpr message) {\n        if (message != null) {\n            message.setParent(this);\n        }\n        this.message = message;\n    }\n\n    public SQLExpr getState() {\n        return state;\n    }\n\n    public void setState(SQLExpr state) {\n        if (state != null) {\n            state.setParent(this);\n        }\n        this.state = state;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, errorNumber);\n            acceptChild(visitor, message);\n            acceptChild(visitor, state);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerTryCatchStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SQLServerTryCatchStatement extends SQLStatementImpl implements SQLServerStatement {\n    public SQLServerTryCatchStatement() {\n        super(DbType.sqlserver);\n    }\n\n    private final List<SQLStatement> tryStatements = new ArrayList<SQLStatement>();\n    private final List<SQLStatement> catchStatements = new ArrayList<SQLStatement>();\n\n    public List<SQLStatement> getTryStatements() {\n        return tryStatements;\n    }\n\n    public List<SQLStatement> getCatchStatements() {\n        return catchStatements;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) visitor);\n        }\n    }\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, tryStatements);\n            acceptChild(visitor, catchStatements);\n        }\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerUpdateStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLServerUpdateStatement extends SQLUpdateStatement implements SQLServerStatement {\n    private SQLTop top;\n    private SQLServerOutput output;\n\n    public SQLServerUpdateStatement() {\n        super(DbType.sqlserver);\n    }\n\n    public SQLTop getTop() {\n        return top;\n    }\n\n    public void setTop(SQLTop top) {\n        if (top != null) {\n            top.setParent(this);\n            top.setParentheses(true);\n        }\n        this.top = top;\n    }\n\n    public SQLServerOutput getOutput() {\n        return output;\n    }\n\n    public void setOutput(SQLServerOutput output) {\n        if (output != null) {\n            output.setParent(this);\n        }\n        this.output = output;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof SQLServerASTVisitor) {\n            accept0((SQLServerASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, top);\n            acceptChild(visitor, tableSource);\n            acceptChild(visitor, items);\n            acceptChild(visitor, output);\n            acceptChild(visitor, from);\n            acceptChild(visitor, where);\n        }\n        visitor.endVisit(this);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerWaitForStatement.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatementImpl;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\n\npublic class SQLServerWaitForStatement extends SQLServerStatementImpl implements SQLServerStatement {\n    private SQLExpr delay;\n\n    private SQLExpr time;\n\n    private SQLStatement statement;\n\n    private SQLExpr timeout;\n\n    @Override\n    public void accept0(SQLServerASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, delay);\n            acceptChild(visitor, time);\n            acceptChild(visitor, statement);\n            acceptChild(visitor, timeout);\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getDelay() {\n        return delay;\n    }\n\n    public void setDelay(SQLExpr delay) {\n        this.delay = delay;\n    }\n\n    public SQLExpr getTime() {\n        return time;\n    }\n\n    public void setTime(SQLExpr time) {\n        this.time = time;\n    }\n\n    public SQLStatement getStatement() {\n        return statement;\n    }\n\n    public void setStatement(SQLStatement statement) {\n        this.statement = statement;\n    }\n\n    public SQLExpr getTimeout() {\n        return timeout;\n    }\n\n    public void setTimeout(SQLExpr timeout) {\n        this.timeout = timeout;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class SQLServerExprParser extends SQLExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"AVG\",\n                \"COUNT\",\n                \"FIRST_VALUE\",\n                \"MAX\",\n                \"MIN\",\n                \"ROW_NUMBER\",\n                \"STDDEV\",\n                \"SUM\"\n        };\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public SQLServerExprParser(Lexer lexer) {\n        super(lexer);\n        this.dbType = DbType.sqlserver;\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public SQLServerExprParser(String sql) {\n        this(new SQLServerLexer(sql));\n        this.lexer.nextToken();\n        this.dbType = DbType.sqlserver;\n    }\n\n    public SQLServerExprParser(String sql, SQLParserFeature... features) {\n        this(new SQLServerLexer(sql, features));\n        this.lexer.nextToken();\n        this.dbType = DbType.sqlserver;\n    }\n\n    public SQLExpr primary() {\n        if (lexer.token() == Token.LBRACKET) {\n            lexer.nextToken();\n            SQLExpr name = this.name();\n            accept(Token.RBRACKET);\n            return primaryRest(name);\n        }\n\n        return super.primary();\n    }\n\n    public SQLServerSelectParser createSelectParser() {\n        return new SQLServerSelectParser(this);\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        final Token token = lexer.token();\n        if (token == Token.DOTDOT) {\n            expr = nameRest((SQLName) expr);\n        } else if (lexer.identifierEquals(FnvHash.Constants.VALUE)\n                && expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n            if (identExpr.nameHashCode64() == FnvHash.Constants.NEXT) {\n                lexer.nextToken();\n                accept(Token.FOR);\n\n                SQLName name = this.name();\n                SQLSequenceExpr seq = new SQLSequenceExpr();\n                seq.setSequence(name);\n                seq.setFunction(SQLSequenceExpr.Function.NextVal);\n                expr = seq;\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            if (lexer.token() != Token.IDENTIFIER && lexer.token() != Token.LITERAL_CHARS) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n            String collate = lexer.stringVal();\n            lexer.nextToken();\n            SQLBinaryOpExpr binaryExpr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.COLLATE,\n                    new SQLIdentifierExpr(collate), DbType.sqlserver);\n            expr = binaryExpr;\n        }\n\n        return super.primaryRest(expr);\n    }\n\n    protected SQLExpr dotRest(SQLExpr expr) {\n        boolean backet = false;\n\n        if (lexer.token() == Token.LBRACKET) {\n            lexer.nextToken();\n            backet = true;\n        }\n\n        expr = super.dotRest(expr);\n\n        if (backet) {\n            accept(Token.RBRACKET);\n        }\n\n        return expr;\n    }\n\n    public SQLName nameRest(SQLName expr) {\n        if (lexer.token() == Token.DOTDOT) {\n            lexer.nextToken();\n\n            boolean backet = false;\n            if (lexer.token() == Token.LBRACKET) {\n                lexer.nextToken();\n                backet = true;\n            }\n            String text = lexer.stringVal();\n            lexer.nextToken();\n\n            if (backet) {\n                accept(Token.RBRACKET);\n            }\n\n            SQLServerObjectReferenceExpr owner = new SQLServerObjectReferenceExpr(expr);\n            expr = new SQLPropertyExpr(owner, text);\n        }\n\n        return super.nameRest(expr);\n    }\n\n    protected SQLServerOutput parserOutput() {\n        if (lexer.identifierEquals(\"OUTPUT\")) {\n            lexer.nextToken();\n            SQLServerOutput output = new SQLServerOutput();\n\n            final List<SQLSelectItem> selectList = output.getSelectList();\n            for (; ; ) {\n                final SQLSelectItem selectItem = parseSelectItem();\n                selectList.add(selectItem);\n\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                }\n\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.INTO) {\n                lexer.nextToken();\n                output.setInto(new SQLExprTableSource(this.name()));\n                if (lexer.token() == (Token.LPAREN)) {\n                    lexer.nextToken();\n                    this.exprList(output.getColumns(), output);\n                    accept(Token.RPAREN);\n                }\n            }\n            return output;\n        }\n        return null;\n    }\n\n    public SQLSelectItem parseSelectItem() {\n        SQLExpr expr;\n        if (lexer.token() == Token.IDENTIFIER) {\n            expr = new SQLIdentifierExpr(lexer.stringVal());\n            lexer.computeRowAndColumn(expr);\n            lexer.nextTokenComma();\n\n            if (lexer.token() != Token.COMMA) {\n                expr = this.primaryRest(expr);\n                expr = this.exprRest(expr);\n            }\n        } else {\n            expr = this.expr();\n        }\n        final String alias = as();\n        return new SQLSelectItem(expr, alias);\n    }\n\n    public SQLColumnDefinition createColumnDefinition() {\n        SQLColumnDefinition column = new SQLColumnDefinition();\n        column.setDbType(dbType);\n        return column;\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        if (lexer.token() == Token.IDENTITY) {\n            lexer.nextToken();\n\n            SQLColumnDefinition.Identity identity = new SQLColumnDefinition.Identity();\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n\n                SQLIntegerExpr seed = (SQLIntegerExpr) this.primary();\n                accept(Token.COMMA);\n                SQLIntegerExpr increment = (SQLIntegerExpr) this.primary();\n                accept(Token.RPAREN);\n\n                identity.setSeed((Integer) seed.getNumber());\n                identity.setIncrement((Integer) increment.getNumber());\n            }\n\n            if (lexer.token() == Token.NOT) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.NULL) {\n                    lexer.nextToken();\n                    column.setDefaultExpr(new SQLNullExpr());\n                } else {\n                    accept(Token.FOR);\n                    acceptIdentifier(\"REPLICATION \");\n                    identity.setNotForReplication(true);\n                }\n            }\n\n            column.setIdentity(identity);\n        }\n\n        return super.parseColumnRest(column);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.*;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;\nimport static com.alibaba.druid.sql.parser.Token.IDENTIFIER;\n\npublic class SQLServerLexer extends Lexer {\n    static final Keywords SQLSERVER_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"CURSOR\", Token.CURSOR);\n        map.put(\"TOP\", Token.TOP);\n        map.put(\"USE\", Token.USE);\n        map.put(\"WITH\", Token.WITH);\n        map.put(\"PERCENT\", Token.PERCENT);\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"DECLARE\", Token.DECLARE);\n        map.put(\"IF\", Token.IF);\n        map.put(\"ELSE\", Token.ELSE);\n        map.put(\"BEGIN\", Token.BEGIN);\n        map.put(\"END\", Token.END);\n\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"OPTION\", Token.OPTION);\n\n        SQLSERVER_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return SQLSERVER_KEYWORDS;\n    }\n\n    public SQLServerLexer(char[] input, int inputLength, boolean skipComment) {\n        super(input, inputLength, skipComment);\n        dbType = DbType.sqlserver;\n    }\n\n    public SQLServerLexer(String input) {\n        super(input);\n        dbType = DbType.sqlserver;\n    }\n\n    public SQLServerLexer(String input, SQLParserFeature... features) {\n        super(input);\n        dbType = DbType.sqlserver;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    public void scanComment() {\n        if (ch != '/' && ch != '-') {\n            throw new IllegalStateException();\n        }\n\n        mark = pos;\n        bufPos = 0;\n        scanChar();\n\n        // /*+ */\n        if (ch == '*') {\n            scanChar();\n            bufPos++;\n\n            while (ch == ' ') {\n                scanChar();\n                bufPos++;\n            }\n\n            boolean isHint = false;\n            int startHintSp = bufPos + 1;\n            if (ch == '!') {\n                isHint = true;\n                scanChar();\n                bufPos++;\n            }\n\n            for (; ; ) {\n                if (ch == '*' && charAt(pos + 1) == '/') {\n                    bufPos += 2;\n                    scanChar();\n                    scanChar();\n                    break;\n                }\n\n                scanChar();\n                bufPos++;\n            }\n\n            if (isHint) {\n                stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 1);\n                token = Token.HINT;\n            } else {\n                stringVal = subString(mark, bufPos);\n                token = Token.MULTI_LINE_COMMENT;\n                commentCount++;\n                if (keepComments) {\n                    addComment(stringVal);\n                }\n            }\n\n            if (token != Token.HINT && !isAllowComment() && !isSafeComment(stringVal)) {\n                throw new NotAllowCommentException();\n            }\n\n            return;\n        }\n\n        if (ch == '/' || ch == '-') {\n            scanChar();\n            bufPos = 2;\n\n            for (; ; ) {\n                if (ch == '\\r') {\n                    if (charAt(pos + 1) == '\\n') {\n                        bufPos += 2;\n                        scanChar();\n                        break;\n                    }\n                    bufPos++;\n                    break;\n                } else if (ch == EOI) {\n                    break;\n                }\n\n                if (ch == '\\n') {\n                    scanChar();\n                    bufPos++;\n                    break;\n                }\n\n                scanChar();\n                bufPos++;\n            }\n\n            stringVal = subString(mark, bufPos);\n            token = Token.LINE_COMMENT;\n            commentCount++;\n            if (keepComments) {\n                addComment(stringVal);\n            }\n            endOfComment = isEOF();\n\n            if (!isAllowComment() && (isEOF() || !isSafeComment(stringVal))) {\n                throw new NotAllowCommentException();\n            }\n            return;\n        }\n    }\n\n    protected void scanLBracket() {\n        mark = pos;\n\n        if (buf == null) {\n            buf = new char[32];\n        }\n\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == ']') {\n                scanChar();\n                token = IDENTIFIER;\n                break;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        stringVal = subString(mark, bufPos + 2);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.*;\n\npublic class SQLServerSelectParser extends SQLSelectParser {\n    public SQLServerSelectParser(String sql) {\n        super(new SQLServerExprParser(sql));\n    }\n\n    public SQLServerSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    public SQLServerSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    public SQLSelect select() {\n        SQLSelect select = new SQLSelect();\n\n        if (lexer.token() == Token.WITH) {\n            SQLWithSubqueryClause with = this.parseWith();\n            select.setWithSubQuery(with);\n        }\n\n        select.setQuery(query());\n        select.setOrderBy(parseOrderBy());\n\n        if (select.getOrderBy() == null) {\n            select.setOrderBy(parseOrderBy());\n        }\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"BROWSE\")) {\n                lexer.nextToken();\n                select.setForBrowse(true);\n            } else if (lexer.identifierEquals(\"XML\")) {\n                lexer.nextToken();\n\n                for (; ; ) {\n                    if (lexer.identifierEquals(\"AUTO\") //\n                            || lexer.identifierEquals(\"TYPE\") //\n                            || lexer.identifierEquals(\"XMLSCHEMA\") //\n                    ) {\n                        select.getForXmlOptions().add(lexer.stringVal());\n                        lexer.nextToken();\n                    } else if (lexer.identifierEquals(\"ELEMENTS\")) {\n                        lexer.nextToken();\n                        if (lexer.identifierEquals(\"XSINIL\")) {\n                            lexer.nextToken();\n                            select.getForXmlOptions().add(\"ELEMENTS XSINIL\");\n                        } else {\n                            select.getForXmlOptions().add(\"ELEMENTS\");\n                        }\n                    } else if (lexer.identifierEquals(\"PATH\")) {\n                        SQLExpr xmlPath = this.exprParser.expr();\n                        select.setXmlPath(xmlPath);\n                    } else {\n                        break;\n                    }\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else {\n                        break;\n                    }\n                }\n            } else {\n                throw new ParserException(\"syntax error, not support option : \" + lexer.token() + \", \" + lexer.info());\n            }\n        }\n\n        if (lexer.identifierEquals(\"OFFSET\")) {\n            lexer.nextToken();\n            SQLExpr offset = this.expr();\n\n            acceptIdentifier(\"ROWS\");\n            select.setOffset(offset);\n\n            if (lexer.token() == Token.FETCH) {\n                lexer.nextToken();\n                acceptIdentifier(\"NEXT\");\n\n                SQLExpr rowCount = expr();\n                acceptIdentifier(\"ROWS\");\n                acceptIdentifier(\"ONLY\");\n                select.setRowCount(rowCount);\n            }\n        }\n\n        return select;\n    }\n\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            accept(Token.RPAREN);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        SQLServerSelectQueryBlock queryBlock = new SQLServerSelectQueryBlock();\n\n        if (lexer.token() == Token.SELECT) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.DISTINCT) {\n                queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n                lexer.nextToken();\n            } else if (lexer.token() == Token.ALL) {\n                queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.TOP) {\n                SQLTop top = this.createExprParser().parseTop();\n                queryBlock.setTop(top);\n            }\n\n            parseSelectList(queryBlock);\n        }\n\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n\n            SQLTableSource into = this.parseTableSource();\n            queryBlock.setInto((SQLExprTableSource) into);\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        queryBlock.setOrderBy(this.exprParser.parseOrderBy());\n\n        parseFetchClause(queryBlock);\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    protected SQLServerExprParser createExprParser() {\n        return new SQLServerExprParser(lexer);\n    }\n\n    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                SQLExpr expr = this.expr();\n                SQLExprHint hint = new SQLExprHint(expr);\n                hint.setParent(tableSource);\n                tableSource.getHints().add(hint);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                } else {\n                    break;\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        return super.parseTableSourceRest(tableSource);\n    }\n\n    @Override\n    protected void afterParseFetchClause(SQLSelectQueryBlock queryBlock) {\n        if (queryBlock instanceof SQLServerSelectQueryBlock) {\n            SQLServerSelectQueryBlock sqlServerSelectQueryBlock = (SQLServerSelectQueryBlock) queryBlock;\n            if (lexer.token() == Token.OPTION) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLAssignItem item = this.exprParser.parseAssignItem();\n                    sqlServerSelectQueryBlock.getOptions().add(item);\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Collection;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.Token.LITERAL_ALIAS;\n\npublic class SQLServerStatementParser extends SQLStatementParser {\n    public SQLServerStatementParser(String sql) {\n        super(new SQLServerExprParser(sql));\n    }\n\n    public SQLServerStatementParser(String sql, SQLParserFeature... features) {\n        super(new SQLServerExprParser(sql, features));\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new SQLServerSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLServerStatementParser(Lexer lexer) {\n        super(new SQLServerExprParser(lexer));\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        if (lexer.token() == Token.WITH) {\n            SQLStatement stmt = parseSelect();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXEC) || lexer.identifierEquals(FnvHash.Constants.EXECUTE)) {\n            lexer.nextToken();\n\n            SQLServerExecStatement execStmt = new SQLServerExecStatement();\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n                this.parseExecParameter(execStmt.getParameters(), execStmt);\n                accept(Token.RPAREN);\n            } else {\n                SQLName sqlNameName = this.exprParser.name();\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                    execStmt.setReturnStatus(sqlNameName);\n                    execStmt.setModuleName(this.exprParser.name());\n                } else {\n                    execStmt.setModuleName(sqlNameName);\n                }\n\n                if (lexer.token() != Token.SEMI && lexer.token() != Token.EOF) {\n                    this.parseExecParameter(execStmt.getParameters(), execStmt);\n                }\n            }\n            statementList.add(execStmt);\n            return true;\n        }\n\n        if (lexer.token() == Token.DECLARE) {\n            statementList.add(this.parseDeclare());\n            return true;\n        }\n\n        if (lexer.token() == Token.IF) {\n            statementList.add(this.parseIf());\n            return true;\n        }\n\n        if (lexer.token() == Token.BEGIN) {\n            statementList.add(this.parseBlock());\n            return true;\n        }\n\n        if (lexer.token() == Token.COMMIT) {\n            statementList.add(this.parseCommit());\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WAITFOR)) {\n            statementList.add(this.parseWaitFor());\n            return true;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.GO)) {\n            lexer.nextToken();\n\n            SQLStatement stmt = new SQLScriptCommitStatement();\n            statementList.add(stmt);\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"BREAK\")) {\n            lexer.nextToken();\n            statementList.add(new SQLBreakStatement());\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"CONTINUE\")) {\n            lexer.nextToken();\n            statementList.add(new SQLContinueStatement());\n            return true;\n        }\n\n        if (lexer.identifierEquals(\"THROW\")) {\n            lexer.nextToken();\n            SQLServerThrowStatement throwStmt = new SQLServerThrowStatement();\n            if (lexer.token() != Token.SEMI && lexer.token() != Token.EOF) {\n                throwStmt.setErrorNumber(this.exprParser.expr());\n                accept(Token.COMMA);\n                throwStmt.setMessage(this.exprParser.expr());\n                accept(Token.COMMA);\n                throwStmt.setState(this.exprParser.expr());\n            }\n            statementList.add(throwStmt);\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * SQLServer parse Parameter statement support out type\n     *\n     * @author zz [455910092@qq.com]\n     */\n    public void parseExecParameter(Collection<SQLServerParameter> exprCol, SQLObject parent) {\n        if (lexer.token() == Token.RPAREN || lexer.token() == Token.RBRACKET) {\n            return;\n        }\n\n        if (lexer.token() == Token.EOF) {\n            return;\n        }\n        SQLServerParameter param = new SQLServerParameter();\n        SQLExpr expr = this.exprParser.expr();\n        expr.setParent(parent);\n        param.setExpr(expr);\n        if (lexer.token() == Token.OUT) {\n            param.setType(true);\n            accept(Token.OUT);\n        }\n        exprCol.add(param);\n        while (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n            param = new SQLServerParameter();\n            expr = this.exprParser.expr();\n            expr.setParent(parent);\n            param.setExpr(expr);\n            if (lexer.token() == Token.OUT) {\n                param.setType(true);\n                accept(Token.OUT);\n            }\n            exprCol.add(param);\n        }\n    }\n\n    public SQLStatement parseDeclare() {\n        this.accept(Token.DECLARE);\n\n        SQLDeclareStatement declareStatement = new SQLDeclareStatement();\n\n        for (; ; ) {\n            SQLDeclareItem item = new SQLDeclareItem();\n            declareStatement.addItem(item);\n\n            item.setName(this.exprParser.name());\n\n            if (lexer.token() == Token.AS) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.TABLE) {\n                lexer.nextToken();\n                item.setType(SQLDeclareItem.Type.TABLE);\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    for (; ; ) {\n                        if (lexer.token() == Token.IDENTIFIER //\n                                || lexer.token() == Token.LITERAL_ALIAS) {\n                            SQLColumnDefinition column = this.exprParser.parseColumn();\n                            item.getTableElementList().add(column);\n                        } else if (lexer.token() == Token.PRIMARY //\n                                || lexer.token() == Token.UNIQUE //\n                                || lexer.token() == Token.CHECK //\n                                || lexer.token() == Token.CONSTRAINT) {\n                            SQLConstraint constraint = this.exprParser.parseConstraint();\n                            constraint.setParent(item);\n                            item.getTableElementList().add((SQLTableElement) constraint);\n                        } else if (lexer.token() == Token.TABLESPACE) {\n                            throw new ParserException(\"TODO \" + lexer.info());\n                        } else {\n                            SQLColumnDefinition column = this.exprParser.parseColumn();\n                            item.getTableElementList().add(column);\n                        }\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n\n                            if (lexer.token() == Token.RPAREN) {\n                                break;\n                            }\n                            continue;\n                        }\n\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                }\n                break;\n            } else if (lexer.token() == Token.CURSOR) {\n                item.setType(SQLDeclareItem.Type.CURSOR);\n                lexer.nextToken();\n            } else {\n                item.setType(SQLDeclareItem.Type.LOCAL);\n                item.setDataType(this.exprParser.parseDataType());\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                    item.setValue(this.exprParser.expr());\n                }\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n        }\n        return declareStatement;\n    }\n\n    public SQLStatement parseInsert() {\n        SQLServerInsertStatement insertStatement = new SQLServerInsertStatement();\n\n        if (lexer.token() == Token.INSERT) {\n            accept(Token.INSERT);\n        }\n\n        parseInsert0(insertStatement);\n        return insertStatement;\n    }\n\n    protected void parseInsert0(SQLInsertInto insert, boolean acceptSubQuery) {\n        SQLServerInsertStatement insertStatement = (SQLServerInsertStatement) insert;\n\n        SQLTop top = this.getExprParser().parseTop();\n        if (top != null) {\n            insertStatement.setTop(top);\n        }\n\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n        }\n\n        SQLName tableName = this.exprParser.name();\n        insertStatement.setTableName(tableName);\n\n        if (lexer.token() == Token.LITERAL_ALIAS) {\n            insertStatement.setAlias(tableAlias());\n        }\n\n        parseInsert0Hints(insertStatement, false);\n\n        if (lexer.token() == Token.IDENTIFIER && !lexer.stringVal().equalsIgnoreCase(\"OUTPUT\")) {\n            insertStatement.setAlias(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == (Token.LPAREN)) {\n            lexer.nextToken();\n            this.exprParser.exprList(insertStatement.getColumns(), insertStatement);\n            accept(Token.RPAREN);\n        }\n\n        SQLServerOutput output = this.getExprParser().parserOutput();\n        if (output != null) {\n            insertStatement.setOutput(output);\n        }\n\n        if (lexer.token() == Token.VALUES) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                accept(Token.LPAREN);\n                SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n                this.exprParser.exprList(values.getValues(), values);\n                insertStatement.addValueCause(values);\n                accept(Token.RPAREN);\n\n                if (!parseCompleteValues && insertStatement.getValuesList().size() >= parseValuesSize) {\n                    lexer.skipToEOF();\n                    break;\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                } else {\n                    break;\n                }\n            }\n        } else if (acceptSubQuery && (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN)) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();\n            insertStatement.setQuery(queryExpr.getSubQuery());\n        } else if (lexer.token() == Token.DEFAULT) {\n            lexer.nextToken();\n            accept(Token.VALUES);\n            insertStatement.setDefaultValues(true);\n        }\n    }\n\n    protected SQLServerUpdateStatement createUpdateStatement() {\n        return new SQLServerUpdateStatement();\n    }\n\n    public SQLUpdateStatement parseUpdateStatement() {\n        SQLServerUpdateStatement updateStatement = createUpdateStatement();\n\n        accept(Token.UPDATE);\n\n        SQLTop top = this.getExprParser().parseTop();\n        if (top != null) {\n            updateStatement.setTop(top);\n        }\n\n        SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource();\n        updateStatement.setTableSource(tableSource);\n\n        parseUpdateSet(updateStatement);\n\n        SQLServerOutput output = this.getExprParser().parserOutput();\n        if (output != null) {\n            updateStatement.setOutput(output);\n        }\n\n        if (lexer.token() == Token.FROM) {\n            lexer.nextToken();\n            SQLTableSource from = this.exprParser.createSelectParser().parseTableSource();\n            updateStatement.setFrom(from);\n        }\n\n        if (lexer.token() == (Token.WHERE)) {\n            lexer.nextToken();\n            updateStatement.setWhere(this.exprParser.expr());\n        }\n\n        return updateStatement;\n    }\n\n    @Override\n    public SQLServerExprParser getExprParser() {\n        return (SQLServerExprParser) exprParser;\n    }\n\n    public SQLStatement parseSet() {\n        accept(Token.SET);\n\n        if (lexer.identifierEquals(FnvHash.Constants.TRANSACTION)) {\n            lexer.nextToken();\n            acceptIdentifier(\"ISOLATION\");\n            acceptIdentifier(\"LEVEL\");\n\n            SQLServerSetTransactionIsolationLevelStatement stmt = new SQLServerSetTransactionIsolationLevelStatement();\n\n            if (lexer.identifierEquals(\"READ\")) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"UNCOMMITTED\")) {\n                    stmt.setLevel(\"READ UNCOMMITTED\");\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(\"COMMITTED\")) {\n                    stmt.setLevel(\"READ COMMITTED\");\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"UNKOWN TRANSACTION LEVEL : \" + lexer.stringVal() + \", \" + lexer.info());\n                }\n            } else if (lexer.identifierEquals(\"SERIALIZABLE\")) {\n                stmt.setLevel(\"SERIALIZABLE\");\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"SNAPSHOT\")) {\n                stmt.setLevel(\"SNAPSHOT\");\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"REPEATABLE\")) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"READ\")) {\n                    stmt.setLevel(\"REPEATABLE READ\");\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"UNKOWN TRANSACTION LEVEL : \" + lexer.stringVal() + \", \" + lexer.info());\n                }\n            } else {\n                throw new ParserException(\"UNKOWN TRANSACTION LEVEL : \" + lexer.stringVal() + \", \" + lexer.info());\n            }\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STATISTICS)) {\n            lexer.nextToken();\n\n            SQLSetStatement stmt = new SQLSetStatement();\n\n            if (lexer.identifierEquals(\"IO\") || lexer.identifierEquals(\"XML\") || lexer.identifierEquals(\"PROFILE\")\n                    || lexer.identifierEquals(\"TIME\")) {\n                SQLExpr target = new SQLIdentifierExpr(\"STATISTICS \" + lexer.stringVal().toUpperCase());\n\n                lexer.nextToken();\n                if (lexer.token() == Token.ON) {\n                    stmt.set(target, new SQLIdentifierExpr(\"ON\"));\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.OFF)) {\n                    stmt.set(target, new SQLIdentifierExpr(\"OFF\"));\n                    lexer.nextToken();\n                }\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IDENTITY_INSERT)) {\n            SQLSetStatement stmt = new SQLSetStatement();\n            stmt.setOption(SQLSetStatement.Option.IDENTITY_INSERT);\n\n            lexer.nextToken();\n            SQLName table = this.exprParser.name();\n\n            if (lexer.token() == Token.ON) {\n                SQLExpr value = new SQLIdentifierExpr(\"ON\");\n                stmt.set(table, value);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.OFF)) {\n                SQLExpr value = new SQLIdentifierExpr(\"OFF\");\n                stmt.set(table, value);\n                lexer.nextToken();\n            }\n            return stmt;\n        }\n\n        if (lexer.token() == Token.VARIANT) {\n            SQLSetStatement stmt = new SQLSetStatement(getDbType());\n            parseAssignItems(stmt.getItems(), stmt);\n            return stmt;\n        } else {\n            SQLSetStatement stmt = new SQLSetStatement();\n            SQLExpr target = this.exprParser.expr();\n\n            if (lexer.token() == Token.ON) {\n                stmt.set(target, new SQLIdentifierExpr(\"ON\"));\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"OFF\")) {\n                stmt.set(target, new SQLIdentifierExpr(\"OFF\"));\n                lexer.nextToken();\n            } else {\n                stmt.set(target, this.exprParser.expr());\n            }\n            return stmt;\n        }\n    }\n\n    public SQLIfStatement parseIf() {\n        accept(Token.IF);\n\n        SQLIfStatement stmt = new SQLIfStatement();\n\n        stmt.setCondition(this.exprParser.expr());\n\n        this.parseStatementList(stmt.getStatements(), 1, stmt);\n\n        if (lexer.token() == Token.SEMI) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.ELSE) {\n            lexer.nextToken();\n\n            SQLIfStatement.Else elseItem = new SQLIfStatement.Else();\n            this.parseStatementList(elseItem.getStatements(), 1, elseItem);\n            stmt.setElseItem(elseItem);\n        }\n\n        return stmt;\n    }\n\n    @Override\n    public SQLWhileStatement parseWhile() {\n        accept(Token.WHILE);\n        SQLWhileStatement stmt = new SQLWhileStatement();\n        stmt.setCondition(this.exprParser.expr());\n        accept(Token.BEGIN);\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n        accept(Token.END);\n        return stmt;\n    }\n\n    @Override\n    public SQLStatement parseReturn() {\n        if (lexer.token() == Token.RETURN\n                || lexer.identifierEquals(\"RETURN\")) {\n            lexer.nextToken();\n        }\n\n        SQLReturnStatement stmt = new SQLReturnStatement();\n        if (lexer.token() != Token.SEMI\n                && lexer.token() != Token.EOF\n                && lexer.token() != Token.END) {\n            SQLExpr expr = this.exprParser.expr();\n            stmt.setExpr(expr);\n        }\n\n        if (lexer.token() == Token.SEMI) {\n            accept(Token.SEMI);\n            stmt.setAfterSemi(true);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseBlock() {\n        accept(Token.BEGIN);\n\n        if (lexer.identifierEquals(\"TRY\")) {\n            return parseTryCatch();\n        }\n\n        if (lexer.identifierEquals(\"TRANSACTION\") || lexer.identifierEquals(\"TRAN\")) {\n            lexer.nextToken();\n\n            SQLStartTransactionStatement startTrans = new SQLStartTransactionStatement(dbType);\n\n            if (lexer.token() == Token.IDENTIFIER) {\n                SQLName name = this.exprParser.name();\n                startTrans.setName(name);\n            }\n            return startTrans;\n        }\n\n        SQLBlockStatement block = new SQLBlockStatement();\n        parseStatementList(block.getStatementList());\n\n        accept(Token.END);\n\n        return block;\n    }\n\n    public SQLStatement parseCommit() {\n        acceptIdentifier(\"COMMIT\");\n\n        SQLCommitStatement stmt = new SQLCommitStatement();\n\n        if (lexer.identifierEquals(\"WORK\")) {\n            lexer.nextToken();\n            stmt.setWork(true);\n        }\n\n        if (lexer.identifierEquals(\"TRAN\") || lexer.identifierEquals(\"TRANSACTION\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.VARIANT) {\n                stmt.setTransactionName(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                acceptIdentifier(\"DELAYED_DURABILITY\");\n                accept(Token.EQ);\n                stmt.setDelayedDurability(this.exprParser.expr());\n                accept(Token.RPAREN);\n            }\n\n        }\n\n        return stmt;\n    }\n\n    public SQLServerRollbackStatement parseRollback() {\n        acceptIdentifier(\"ROLLBACK\");\n\n        SQLServerRollbackStatement stmt = new SQLServerRollbackStatement();\n\n        if (lexer.identifierEquals(\"WORK\")) {\n            lexer.nextToken();\n            stmt.setWork(true);\n        }\n\n        if (lexer.identifierEquals(\"TRAN\") || lexer.identifierEquals(\"TRANSACTION\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.IDENTIFIER || lexer.token() == Token.VARIANT) {\n                stmt.setName(this.exprParser.expr());\n            }\n\n        }\n\n        return stmt;\n    }\n\n    public SQLServerWaitForStatement parseWaitFor() {\n        acceptIdentifier(\"WAITFOR\");\n\n        SQLServerWaitForStatement stmt = new SQLServerWaitForStatement();\n\n        if (lexer.identifierEquals(\"DELAY\")) {\n            lexer.nextToken();\n            stmt.setDelay(this.exprParser.expr());\n        }\n\n        if (lexer.identifierEquals(\"TIME\")) {\n            lexer.nextToken();\n            stmt.setTime(this.exprParser.expr());\n        }\n\n        if (lexer.token() == Token.COMMA) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"TIMEOUT\")) {\n                lexer.nextToken();\n                stmt.setTimeout(this.exprParser.expr());\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseTryCatch() {\n        acceptIdentifier(\"TRY\");\n\n        SQLServerTryCatchStatement stmt = new SQLServerTryCatchStatement();\n\n        parseStatementList(stmt.getTryStatements(), -1, stmt);\n\n        accept(Token.END);\n        acceptIdentifier(\"TRY\");\n\n        accept(Token.BEGIN);\n        acceptIdentifier(\"CATCH\");\n\n        parseStatementList(stmt.getCatchStatements(), -1, stmt);\n\n        accept(Token.END);\n        acceptIdentifier(\"CATCH\");\n\n        return stmt;\n    }\n\n    @Override\n    public SQLCreateProcedureStatement parseCreateProcedure() {\n        SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token() == Token.CREATE) {\n            lexer.nextToken();\n            if (lexer.token() == Token.OR) {\n                lexer.nextToken();\n                accept(Token.REPLACE);\n                stmt.setOrReplace(true);\n            }\n        } else {\n            stmt.setCreate(false);\n        }\n\n        if (lexer.token() == Token.PROCEDURE || lexer.identifierEquals(\"PROC\")) {\n            lexer.nextToken();\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        // SQL Server parameters: @param type, @param2 type ...  (no parentheses)\n        if (lexer.token() == Token.VARIANT || lexer.token() == Token.LPAREN) {\n            boolean useParen = lexer.token() == Token.LPAREN;\n            if (useParen) {\n                lexer.nextToken();\n            }\n            parseSQLServerProcedureParameters(stmt);\n            if (useParen) {\n                accept(Token.RPAREN);\n            }\n        }\n\n        // WITH EXECUTE AS { CALLER | SELF | OWNER | 'user_name' }\n        // or WITH RECOMPILE, ENCRYPTION, etc.\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.EXECUTE)) {\n                lexer.nextToken();\n                accept(Token.AS);\n                SQLName executeAs = this.exprParser.name();\n                stmt.setAuthid(executeAs);\n            } else {\n                // skip other WITH options like RECOMPILE, ENCRYPTION\n                this.exprParser.name();\n                while (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    this.exprParser.name();\n                }\n            }\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n        }\n\n        SQLStatement block = this.parseBlock();\n        stmt.setBlock(block);\n\n        return stmt;\n    }\n\n    @Override\n    protected SQLStatement alterProcedure() {\n        accept(Token.ALTER);\n        return parseCreateProcedure();\n    }\n\n    @Override\n    protected void createOptionSkip() {\n        // Handle SQL Server's CREATE OR ALTER syntax before delegating to parent\n        if (lexer.token() == Token.OR) {\n            Lexer.SavePoint mark = lexer.markOut();\n            lexer.nextToken();\n            if (lexer.token() == Token.ALTER) {\n                lexer.nextToken();\n                // continue to parent for remaining options\n            } else {\n                lexer.reset(mark);\n            }\n        }\n        super.createOptionSkip();\n    }\n\n    @Override\n    protected SQLStatement alterRest(Lexer.SavePoint mark) {\n        if (lexer.token() == Token.TRIGGER) {\n            lexer.reset(mark);\n            return parseAlterTrigger();\n        }\n        return super.alterRest(mark);\n    }\n\n    protected SQLStatement parseAlterTrigger() {\n        accept(Token.ALTER);\n        return parseCreateTriggerBody(false);\n    }\n\n    @Override\n    protected SQLStatement parseAlterFunction() {\n        accept(Token.ALTER);\n        return parseCreateFunctionBody(false);\n    }\n\n    @Override\n    public SQLCreateStatement parseCreateTrigger() {\n        accept(Token.CREATE);\n\n        boolean orAlter = false;\n        if (lexer.token() == Token.OR) {\n            lexer.nextToken();\n            if (lexer.token() == Token.ALTER) {\n                lexer.nextToken();\n                orAlter = true;\n            } else {\n                accept(Token.REPLACE);\n            }\n        }\n\n        SQLCreateTriggerStatement stmt = parseCreateTriggerBody(true);\n        if (orAlter) {\n            stmt.setOrReplace(true);\n        }\n        return stmt;\n    }\n\n    private SQLCreateTriggerStatement parseCreateTriggerBody(boolean isCreate) {\n        accept(Token.TRIGGER);\n\n        SQLCreateTriggerStatement stmt = new SQLCreateTriggerStatement(dbType);\n        stmt.setName(this.exprParser.name());\n\n        accept(Token.ON);\n        stmt.setOn(this.exprParser.name());\n\n        // parse trigger type: AFTER | INSTEAD OF | FOR\n        if (lexer.identifierEquals(FnvHash.Constants.AFTER)) {\n            stmt.setTriggerType(SQLCreateTriggerStatement.TriggerType.AFTER);\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"INSTEAD\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"OF\");\n            stmt.setTriggerType(SQLCreateTriggerStatement.TriggerType.INSTEAD_OF);\n        } else if (lexer.token() == Token.FOR) {\n            stmt.setTriggerType(SQLCreateTriggerStatement.TriggerType.AFTER);\n            lexer.nextToken();\n        }\n\n        // parse trigger events: INSERT, UPDATE, DELETE\n        for (;;) {\n            if (lexer.token() == Token.INSERT) {\n                lexer.nextToken();\n                stmt.setInsert(true);\n            } else if (lexer.token() == Token.UPDATE) {\n                lexer.nextToken();\n                stmt.setUpdate(true);\n            } else if (lexer.token() == Token.DELETE) {\n                lexer.nextToken();\n                stmt.setDelete(true);\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        // optional WITH clause - skip (not stored on SQLCreateTriggerStatement)\n        parseWithOptions();\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n        }\n\n        SQLStatement block = this.parseBlock();\n        stmt.setBody(block);\n\n        return stmt;\n    }\n\n    @Override\n    public SQLCreateFunctionStatement parseCreateFunction() {\n        accept(Token.CREATE);\n\n        boolean orAlter = false;\n        if (lexer.token() == Token.OR) {\n            lexer.nextToken();\n            if (lexer.token() == Token.ALTER) {\n                lexer.nextToken();\n                orAlter = true;\n            } else {\n                accept(Token.REPLACE);\n            }\n        }\n\n        SQLCreateFunctionStatement stmt = parseCreateFunctionBody(true);\n        if (orAlter) {\n            stmt.setOrReplace(true);\n        }\n        return stmt;\n    }\n\n    private SQLCreateFunctionStatement parseCreateFunctionBody(boolean isCreate) {\n        accept(Token.FUNCTION);\n\n        SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement();\n        stmt.setDbType(dbType);\n        stmt.setCreate(isCreate);\n        stmt.setName(this.exprParser.name());\n\n        // parse parameters\n        accept(Token.LPAREN);\n        if (lexer.token() != Token.RPAREN) {\n            for (;;) {\n                SQLParameter parameter = new SQLParameter();\n                parameter.setParamType(SQLParameter.ParameterType.DEFAULT);\n                parameter.setName(this.exprParser.name());\n                parameter.setDataType(this.exprParser.parseDataType());\n\n                if (lexer.token() == Token.EQ) {\n                    lexer.nextToken();\n                    parameter.setDefaultValue(this.exprParser.expr());\n                }\n\n                stmt.getParameters().add(parameter);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n        accept(Token.RPAREN);\n\n        // RETURNS return_type | RETURNS TABLE\n        acceptIdentifier(\"RETURNS\");\n        if (lexer.token() == Token.TABLE) {\n            lexer.nextToken();\n            stmt.setReturnDataType(new SQLDataTypeImpl(\"TABLE\"));\n        } else {\n            stmt.setReturnDataType(this.exprParser.parseDataType());\n        }\n\n        // optional WITH clause (e.g., WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT)\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            for (;;) {\n                SQLExpr optionExpr = this.exprParser.name();\n                SQLAssignItem item = new SQLAssignItem(optionExpr, null);\n                stmt.getOptions().add(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n        }\n\n        // inline table-valued function: RETURN (subquery)\n        if (lexer.token() == Token.RETURN || lexer.identifierEquals(\"RETURN\")) {\n            lexer.nextToken();\n            if (lexer.token() == Token.LPAREN) {\n                SQLSelect select = this.createSQLSelectParser().select();\n                SQLReturnStatement returnStmt = new SQLReturnStatement();\n                returnStmt.setExpr(new SQLQueryExpr(select));\n                stmt.setBlock(returnStmt);\n            } else {\n                SQLReturnStatement returnStmt = new SQLReturnStatement();\n                returnStmt.setExpr(this.exprParser.expr());\n                stmt.setBlock(returnStmt);\n            }\n        } else {\n            // scalar function: BEGIN...END block\n            SQLStatement block = this.parseBlock();\n            stmt.setBlock(block);\n        }\n\n        return stmt;\n    }\n\n    private void parseWithOptions() {\n        if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.EXECUTE)) {\n                lexer.nextToken();\n                accept(Token.AS);\n                this.exprParser.name();\n            } else {\n                this.exprParser.name();\n                while (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    this.exprParser.name();\n                }\n            }\n        }\n    }\n\n    private void parseSQLServerProcedureParameters(SQLCreateProcedureStatement stmt) {\n        for (; ; ) {\n            if (lexer.token() == Token.RPAREN || lexer.token() == Token.AS\n                    || lexer.token() == Token.WITH || lexer.token() == Token.EOF) {\n                break;\n            }\n\n            SQLParameter parameter = new SQLParameter();\n            parameter.setParamType(SQLParameter.ParameterType.DEFAULT);\n            parameter.setName(this.exprParser.name());\n            parameter.setDataType(this.exprParser.parseDataType());\n\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n                parameter.setDefaultValue(this.exprParser.expr());\n            }\n\n            if (lexer.token() == Token.OUT || lexer.identifierEquals(\"OUTPUT\")) {\n                parameter.setParamType(SQLParameter.ParameterType.OUT);\n                lexer.nextToken();\n            }\n\n            stmt.getParameters().add(parameter);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n            } else {\n                break;\n            }\n        }\n    }\n\n    public void parseAlterDrop(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token() == Token.CONSTRAINT) {\n            lexer.nextToken();\n            SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint();\n            item.setConstraintName(this.exprParser.name());\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.COLUMN) {\n            lexer.nextToken();\n            SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem();\n            if (lexer.token() == Token.IF) {\n                lexer.nextToken();\n                accept(Token.EXISTS);\n                item.setIfExists(true);\n            }\n            SQLName name = exprParser.name();\n            name.setParent(item);\n            item.addColumn(name);\n            while (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.COLUMN) {\n                    lexer.nextToken();\n                }\n                name = exprParser.name();\n                name.setParent(item);\n                item.addColumn(name);\n            }\n\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.INDEX) {\n            lexer.nextToken();\n            SQLName indexName = this.exprParser.name();\n            SQLAlterTableDropIndex item = new SQLAlterTableDropIndex();\n            item.setIndexName(indexName);\n            stmt.addItem(item);\n        } else if (lexer.token() == Token.PRIMARY) {\n            lexer.nextToken();\n            accept(Token.KEY);\n            SQLAlterTableDropPrimaryKey item = new SQLAlterTableDropPrimaryKey();\n            stmt.addItem(item);\n        } else {\n            throw new ParserException(\"TODO : \" + lexer.info());\n        }\n    }\n\n    protected void alterTableAddRestSpecific(SQLAlterTableStatement stmt) {\n        if (lexer.token() == LITERAL_ALIAS) {\n            SQLAlterTableAddColumn item = parseAlterTableAddColumn();\n            stmt.addItem(item);\n            return;\n        }\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/MSSQLServerExportParameterVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLInListExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MSSQLServerExportParameterVisitor extends SQLServerOutputVisitor implements ExportParameterVisitor {\n    /**\n     * true= if require parameterized sql output\n     */\n    private final boolean requireParameterizedOutput;\n\n    public MSSQLServerExportParameterVisitor(final List<Object> parameters,\n                                             final StringBuilder appender,\n                                             final boolean wantParameterizedOutput) {\n        super(appender, true);\n        this.parameters = parameters;\n        this.requireParameterizedOutput = wantParameterizedOutput;\n    }\n\n    public MSSQLServerExportParameterVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public MSSQLServerExportParameterVisitor(final List<Object> parameters) {\n        this(parameters, new StringBuilder(), false);\n    }\n\n    public MSSQLServerExportParameterVisitor(final StringBuilder appender) {\n        this(new ArrayList<Object>(), appender, true);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public boolean visit(SQLSelectItem x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOrderBy x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelectGroupByClause x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getArguments());\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLBetweenExpr x) {\n        if (requireParameterizedOutput) {\n            return super.visit(x);\n        }\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n        return true;\n    }\n\n//    public boolean visit(SQLBinaryOpExpr x) {\n//        if(requireParameterizedOutput){\n//            return super.visit(x);\n//        }\n//        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n//        return true;\n//    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.visitor;\n\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface SQLServerASTVisitor extends SQLASTVisitor {\n    default boolean visit(SQLServerSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    default void endVisit(SQLServerSelectQueryBlock x) {\n        endVisit((SQLSelectQueryBlock) x);\n    }\n\n    default boolean visit(SQLServerObjectReferenceExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerObjectReferenceExpr x) {\n    }\n\n    default boolean visit(SQLServerInsertStatement x) {\n        return visit((SQLInsertStatement) x);\n    }\n\n    default void endVisit(SQLServerInsertStatement x) {\n        endVisit((SQLInsertStatement) x);\n    }\n\n    default boolean visit(SQLServerUpdateStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerUpdateStatement x) {\n    }\n\n    default boolean visit(SQLServerExecStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerExecStatement x) {\n    }\n\n    default boolean visit(SQLServerSetTransactionIsolationLevelStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerSetTransactionIsolationLevelStatement x) {\n    }\n\n    default boolean visit(SQLServerOutput x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerOutput x) {\n    }\n\n    default boolean visit(SQLServerRollbackStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerRollbackStatement x) {\n    }\n\n    default boolean visit(SQLServerWaitForStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerWaitForStatement x) {\n    }\n\n    default boolean visit(SQLServerParameter x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerParameter x) {\n    }\n\n    default boolean visit(SQLServerTryCatchStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerTryCatchStatement x) {\n    }\n\n    default boolean visit(SQLServerThrowStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLServerThrowStatement x) {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.visitor;\n\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\n\npublic class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements SQLServerASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerEvalVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLServerEvalVisitor extends SQLServerASTVisitorAdapter implements SQLEvalVisitor {\n    private Map<String, Function> functions = new HashMap<String, Function>();\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public SQLServerEvalVisitor() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public SQLServerEvalVisitor(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLUnaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLSequenceExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType;\nimport com.alibaba.druid.sql.dialect.sqlserver.SqlServer;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLServerASTVisitor {\n    public SQLServerOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.sqlserver, SqlServer.DIALECT);\n    }\n\n    public SQLServerOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect) {\n        super(appender, dbType, dialect);\n    }\n\n    public SQLServerOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.sqlserver, SqlServer.DIALECT, parameterized);\n    }\n\n    public SQLServerOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect, boolean parameterized) {\n        super(appender, dbType, dialect, parameterized);\n    }\n    public boolean visit(SQLServerSelectQueryBlock x) {\n        print0(ucase ? \"SELECT \" : \"select \");\n\n        if (SQLSetQuantifier.ALL == x.getDistionOption()) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == x.getDistionOption()) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        }\n\n        SQLTop top = x.getTop();\n        if (top != null) {\n            visit(top);\n            print(' ');\n        }\n\n        printSelectList(x.getSelectList());\n        printInto(x);\n        printFrom(x);\n        printWhere(x);\n        printGroupBy(x);\n        printOrderBy(x);\n        printFetchFirst(x);\n        printAfterFetch(x);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerObjectReferenceExpr x) {\n        print0(x.toString());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerInsertStatement x) {\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n            println();\n        }\n        print0(ucase ? \"INSERT \" : \"insert \");\n\n        if (x.getTop() != null) {\n            x.getTop().setParent(x);\n            x.getTop().accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"INTO \" : \"into \");\n\n        x.getTableSource().accept(this);\n\n        printInsertColumns(x.getColumns());\n\n        if (x.getOutput() != null) {\n            println();\n            x.getOutput().setParent(x);\n            x.getOutput().accept(this);\n        }\n\n        if (!x.getValuesList().isEmpty()) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            for (int i = 0, size = x.getValuesList().size(); i < size; ++i) {\n                if (i != 0) {\n                    print(',');\n                    println();\n                }\n                x.getValuesList().get(i).accept(this);\n            }\n        }\n\n        if (x.getQuery() != null) {\n            println();\n            x.getQuery().accept(this);\n        }\n\n        if (x.isDefaultValues()) {\n            print0(ucase ? \" DEFAULT VALUES\" : \" default values\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerUpdateStatement x) {\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        SQLTop top = x.getTop();\n        if (top != null) {\n            top.accept(this);\n            print(' ');\n        }\n\n        printTableSource(x.getTableSource());\n\n        println();\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLUpdateSetItem item = x.getItems().get(i);\n            visit(item);\n        }\n\n        SQLServerOutput output = x.getOutput();\n        if (output != null) {\n            println();\n            visit(output);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from != null) {\n            println();\n            print0(ucase ? \"FROM \" : \"from \");\n            printTableSource(from);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            indentCount++;\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where);\n            indentCount--;\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLExprTableSource x) {\n        printTableSourceExpr(x.getExpr());\n\n        String alias = x.getAlias();\n        if (alias != null) {\n            print(' ');\n            print0(alias);\n        }\n\n        if (isPrettyFormat() && x.hasAfterComment()) {\n            print(' ');\n            printlnComment(x.getAfterCommentsDirect());\n        }\n\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            print0(ucase ? \" WITH (\" : \" with (\");\n            printAndAccept(x.getHints(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLColumnDefinition x) {\n        boolean parameterized = this.parameterized;\n        this.parameterized = false;\n\n        String columnName = replaceQuota(x.getName().getSimpleName());\n        printName0(columnName);\n\n        if (x.getDataType() != null) {\n            print(' ');\n            x.getDataType().accept(this);\n        }\n\n        if (x.getDefaultExpr() != null) {\n            visitColumnDefault(x);\n        }\n\n        for (SQLColumnConstraint item : x.getConstraints()) {\n            print(' ');\n            item.accept(this);\n        }\n\n        final SQLColumnDefinition.Identity identity = x.getIdentity();\n        if (identity != null) {\n            print(' ');\n            identity.accept(this);\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable().booleanValue()) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            }\n        }\n\n        this.parameterized = parameterized;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerExecStatement x) {\n        print0(ucase ? \"EXEC \" : \"exec \");\n\n        SQLName returnStatus = x.getReturnStatus();\n        if (returnStatus != null) {\n            returnStatus.accept(this);\n            print0(\" = \");\n        }\n\n        SQLName moduleName = x.getModuleName();\n        if (moduleName != null) {\n            moduleName.accept(this);\n            print(' ');\n        } else {\n            print0(\" (\");\n        }\n        printAndAccept(x.getParameters(), \", \");\n\n        if (moduleName == null) {\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerSetTransactionIsolationLevelStatement x) {\n        print0(ucase ? \"SET TRANSACTION ISOLATION LEVEL \" : \"set transaction isolation level \");\n        print0(x.getLevel());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSetStatement x) {\n        print0(ucase ? \"SET \" : \"set \");\n\n        SQLSetStatement.Option option = x.getOption();\n        if (option != null) {\n            print(option.name());\n            print(' ');\n        }\n\n        List<SQLAssignItem> items = x.getItems();\n        for (int i = 0; i < items.size(); i++) {\n            if (i != 0) {\n                print0(\", \");\n            }\n\n            SQLAssignItem item = x.getItems().get(i);\n            item.getTarget().accept(this);\n\n            SQLExpr value = item.getValue();\n            if (value instanceof SQLIdentifierExpr\n                    && (((SQLIdentifierExpr) value).nameHashCode64() == FnvHash.Constants.ON\n                    || ((SQLIdentifierExpr) value).nameHashCode64() == FnvHash.Constants.OFF)) {\n                print(' ');\n            } else {\n                print0(\" = \");\n            }\n            value.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerOutput x) {\n        print0(ucase ? \"OUTPUT \" : \"output \");\n        printSelectList(x.getSelectList());\n\n        if (x.getInto() != null) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"INTO \" : \"into \");\n            x.getInto().accept(this);\n\n            if (x.getColumns().size() > 0) {\n                this.indentCount++;\n                println();\n                print('(');\n                for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n                    if (i != 0) {\n                        if (i % 5 == 0) {\n                            println();\n                        }\n                        print0(\", \");\n                    }\n\n                    x.getColumns().get(i).accept(this);\n                }\n                print(')');\n                this.indentCount--;\n            }\n        }\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBlockStatement x) {\n        print0(ucase ? \"BEGIN\" : \"begin\");\n        this.indentCount++;\n        println();\n        for (int i = 0, size = x.getStatementList().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n            SQLStatement stmt = x.getStatementList().get(i);\n            stmt.setParent(x);\n            stmt.accept(this);\n            print(';');\n        }\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END\" : \"end\");\n        return false;\n    }\n\n    @Override\n    protected void printGrantOn(SQLGrantStatement x) {\n        if (x.getResource() != null) {\n            print0(ucase ? \" ON \" : \" on \");\n\n            if (x.getResourceType() != null) {\n                print0(x.getResourceType().name());\n                print0(\"::\");\n            }\n\n            x.getResource().accept(this);\n        }\n    }\n\n    public boolean visit(SQLSelect x) {\n        super.visit(x);\n        if (x.isForBrowse()) {\n            println();\n            print0(ucase ? \"FOR BROWSE\" : \"for browse\");\n        }\n\n        if (x.getForXmlOptionsSize() > 0) {\n            println();\n            print0(ucase ? \"FOR XML \" : \"for xml \");\n            for (int i = 0; i < x.getForXmlOptions().size(); ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                    print0(x.getForXmlOptions().get(i));\n                }\n            }\n        }\n\n        if (x.getXmlPath() != null) {\n            println();\n            print0(ucase ? \"FOR XML \" : \"for xml \");\n            x.getXmlPath().accept(this);\n        }\n\n        if (x.getOffset() != null) {\n            println();\n            print0(ucase ? \"OFFSET \" : \"offset \");\n            x.getOffset().accept(this);\n            print0(ucase ? \" ROWS\" : \" rows\");\n\n            if (x.getRowCount() != null) {\n                print0(ucase ? \" FETCH NEXT \" : \" fetch next \");\n                x.getRowCount().accept(this);\n                print0(ucase ? \" ROWS ONLY\" : \" rows only\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCommitStatement x) {\n        print0(ucase ? \"COMMIT\" : \"commit\");\n\n        if (x.isWork()) {\n            print0(ucase ? \" WORK\" : \" work\");\n        } else {\n            print0(ucase ? \" TRANSACTION\" : \" transaction\");\n            if (x.getTransactionName() != null) {\n                print(' ');\n                x.getTransactionName().accept(this);\n            }\n            if (x.getDelayedDurability() != null) {\n                print0(ucase ? \" WITH ( DELAYED_DURABILITY = \" : \" with ( delayed_durability = \");\n                x.getDelayedDurability().accept(this);\n                print0(\" )\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerRollbackStatement x) {\n        print0(ucase ? \"ROLLBACK\" : \"rollback\");\n\n        if (x.isWork()) {\n            print0(ucase ? \" WORK\" : \" work\");\n        } else {\n            print0(ucase ? \" TRANSACTION\" : \" transaction\");\n            if (x.getName() != null) {\n                print(' ');\n                x.getName().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerWaitForStatement x) {\n        print0(ucase ? \"WAITFOR\" : \"waitfor\");\n\n        if (x.getDelay() != null) {\n            print0(ucase ? \" DELAY \" : \" delay \");\n            x.getDelay().accept(this);\n        } else if (x.getTime() != null) {\n            print0(ucase ? \" TIME \" : \" time \");\n            x.getTime().accept(this);\n        }\n        if (x.getStatement() != null) {\n            print0(ucase ? \" DELAY \" : \" delay \");\n            x.getStatement().accept(this);\n        }\n\n        if (x.getTimeout() != null) {\n            print0(ucase ? \" ,TIMEOUT \" : \" ,timeout \");\n            x.getTimeout().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerParameter x) {\n        // TODO Auto-generated method stub\n        x.getExpr().accept(this);\n        if (x.getType()) {\n            print0(ucase ? \" OUT\" : \" out\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLStartTransactionStatement x) {\n        print0(ucase ? \"BEGIN TRANSACTION\" : \"begin transaction\");\n        if (x.getName() != null) {\n            print(' ');\n            x.getName().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLScriptCommitStatement x) {\n        print0(ucase ? \"GO\" : \"go\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateUserStatement x) {\n        print0(ucase ? \"CREATE USER \" : \"create user \");\n        x.getUser().accept(this);\n        print0(ucase ? \" WITH PASSWORD = \" : \" with password = \");\n\n        SQLExpr passoword = x.getPassword();\n\n        if (passoword instanceof SQLIdentifierExpr) {\n            print('\\'');\n            passoword.accept(this);\n            print('\\'');\n        } else {\n            passoword.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLSequenceExpr x) {\n        SQLSequenceExpr.Function function = x.getFunction();\n        switch (function) {\n            case NextVal:\n                print0(ucase ? \"NEXT VALUE FOR \" : \"next value for \");\n                break;\n            default:\n                throw new ParserException(\"not support function : \" + function);\n        }\n        printExpr(x.getSequence());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddColumn x) {\n        boolean odps = isOdps();\n        print0(ucase ? \"ADD \" : \"add \");\n        printAndAccept(x.getColumns(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerTryCatchStatement x) {\n        print0(ucase ? \"BEGIN TRY\" : \"begin try\");\n        this.indentCount++;\n        for (SQLStatement stmt : x.getTryStatements()) {\n            println();\n            stmt.accept(this);\n        }\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END TRY\" : \"end try\");\n        println();\n        print0(ucase ? \"BEGIN CATCH\" : \"begin catch\");\n        this.indentCount++;\n        for (SQLStatement stmt : x.getCatchStatements()) {\n            println();\n            stmt.accept(this);\n        }\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END CATCH\" : \"end catch\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerThrowStatement x) {\n        print0(ucase ? \"THROW\" : \"throw\");\n        if (x.getErrorNumber() != null) {\n            print(' ');\n            x.getErrorNumber().accept(this);\n            print0(\", \");\n            x.getMessage().accept(this);\n            print0(\", \");\n            x.getState().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLWhileStatement x) {\n        print0(ucase ? \"WHILE \" : \"while \");\n        x.getCondition().accept(this);\n        println();\n        print0(ucase ? \"BEGIN\" : \"begin\");\n        this.indentCount++;\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            println();\n            SQLStatement stmt = x.getStatements().get(i);\n            stmt.accept(this);\n        }\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END\" : \"end\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateProcedureStatement x) {\n        if (x.isCreate()) {\n            if (x.isOrReplace()) {\n                print0(ucase ? \"CREATE OR ALTER PROCEDURE \" : \"create or alter procedure \");\n            } else {\n                print0(ucase ? \"CREATE PROCEDURE \" : \"create procedure \");\n            }\n        } else {\n            print0(ucase ? \"ALTER PROCEDURE \" : \"alter procedure \");\n        }\n\n        x.getName().accept(this);\n\n        int paramSize = x.getParameters().size();\n        if (paramSize > 0) {\n            this.indentCount++;\n            for (int i = 0; i < paramSize; ++i) {\n                println();\n                SQLParameter param = x.getParameters().get(i);\n                param.accept(this);\n                if (i < paramSize - 1) {\n                    print(',');\n                }\n            }\n            this.indentCount--;\n        }\n\n        SQLName authid = x.getAuthid();\n        if (authid != null) {\n            println();\n            print0(ucase ? \"WITH EXECUTE AS \" : \"with execute as \");\n            authid.accept(this);\n        }\n\n        println();\n        print0(ucase ? \"AS\" : \"as\");\n        println();\n\n        SQLStatement block = x.getBlock();\n        if (block != null) {\n            block.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateTriggerStatement x) {\n        if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR ALTER TRIGGER \" : \"create or alter trigger \");\n        } else {\n            print0(ucase ? \"CREATE TRIGGER \" : \"create trigger \");\n        }\n\n        x.getName().accept(this);\n\n        println();\n        print0(ucase ? \"ON \" : \"on \");\n        x.getOn().accept(this);\n\n        println();\n        TriggerType triggerType = x.getTriggerType();\n        if (TriggerType.INSTEAD_OF.equals(triggerType)) {\n            print0(ucase ? \"INSTEAD OF \" : \"instead of \");\n        } else if (TriggerType.AFTER.equals(triggerType)) {\n            print0(ucase ? \"AFTER \" : \"after \");\n        } else if (triggerType != null) {\n            String name = triggerType.name();\n            print0(ucase ? name : name.toLowerCase());\n            print(' ');\n        }\n\n        boolean first = true;\n        if (x.isInsert()) {\n            print0(ucase ? \"INSERT\" : \"insert\");\n            first = false;\n        }\n        if (x.isUpdate()) {\n            if (!first) {\n                print0(\", \");\n            }\n            print0(ucase ? \"UPDATE\" : \"update\");\n            first = false;\n        }\n        if (x.isDelete()) {\n            if (!first) {\n                print0(\", \");\n            }\n            print0(ucase ? \"DELETE\" : \"delete\");\n        }\n\n        println();\n        print0(ucase ? \"AS\" : \"as\");\n        println();\n\n        if (x.getBody() != null) {\n            x.getBody().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateFunctionStatement x) {\n        boolean create = x.isCreate();\n        if (create) {\n            if (x.isOrReplace()) {\n                print0(ucase ? \"CREATE OR ALTER FUNCTION \" : \"create or alter function \");\n            } else {\n                print0(ucase ? \"CREATE FUNCTION \" : \"create function \");\n            }\n        } else {\n            print0(ucase ? \"ALTER FUNCTION \" : \"alter function \");\n        }\n\n        x.getName().accept(this);\n\n        print0(\" (\");\n        int paramSize = x.getParameters().size();\n        if (paramSize > 0) {\n            this.indentCount++;\n            for (int i = 0; i < paramSize; ++i) {\n                if (i != 0) {\n                    print(',');\n                }\n                println();\n                SQLParameter param = x.getParameters().get(i);\n                param.accept(this);\n            }\n            this.indentCount--;\n            println();\n        }\n        print(')');\n\n        SQLDataType returnDataType = x.getReturnDataType();\n        if (returnDataType != null) {\n            println();\n            print0(ucase ? \"RETURNS \" : \"returns \");\n            returnDataType.accept(this);\n        }\n\n        List<SQLAssignItem> options = x.getOptions();\n        if (options != null && !options.isEmpty()) {\n            println();\n            print0(ucase ? \"WITH \" : \"with \");\n            for (int i = 0; i < options.size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                options.get(i).getTarget().accept(this);\n            }\n        }\n\n        println();\n        print0(ucase ? \"AS\" : \"as\");\n        println();\n\n        SQLStatement block = x.getBlock();\n        if (block != null) {\n            block.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    protected void printAfterFetch(SQLSelectQueryBlock queryBlock) {\n        if (queryBlock instanceof SQLServerSelectQueryBlock) {\n            SQLServerSelectQueryBlock sqlServerSelectQueryBlock = ((SQLServerSelectQueryBlock) queryBlock);\n            if (!sqlServerSelectQueryBlock.getOptions().isEmpty()) {\n                println();\n                print0(ucase ? \"OPTION(\" : \"option(\");\n                printAndAccept(sqlServerSelectQueryBlock.getOptions(), \", \");\n                print0(\")\");\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.sqlserver.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\npublic class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQLServerASTVisitor {\n    public SQLServerSchemaStatVisitor() {\n        super(DbType.sqlserver);\n    }\n\n    public SQLServerSchemaStatVisitor(SchemaRepository repository) {\n        super(repository);\n    }\n\n    @Override\n    public boolean visit(SQLServerObjectReferenceExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerUpdateStatement x) {\n        TableStat stat = getTableStat(x.getTableName());\n        stat.incrementUpdateCount();\n\n        accept(x.getItems());\n        accept(x.getFrom());\n        accept(x.getWhere());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerExecStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerSetTransactionIsolationLevelStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerOutput x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLServerRollbackStatement x) {\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLServerWaitForStatement x) {\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLServerParameter x) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/StarRocks.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class StarRocks {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.starrocks);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/ast/StarRocksAggregateKey.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLTableConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLUnique;\nimport com.alibaba.druid.sql.dialect.starrocks.visitor.StarRocksASTVisitor;\n\npublic class StarRocksAggregateKey extends SQLUnique implements SQLTableConstraint, StarRocksObject {\n    @Override\n    public void accept0(StarRocksASTVisitor v) {\n        super.accept0(v);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/ast/StarRocksDuplicateKey.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLTableConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLUnique;\nimport com.alibaba.druid.sql.dialect.starrocks.visitor.StarRocksASTVisitor;\n\npublic class StarRocksDuplicateKey extends SQLUnique implements SQLTableConstraint, StarRocksObject {\n    @Override\n    public void accept0(StarRocksASTVisitor v) {\n        super.accept0(v);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/ast/StarRocksIndexDefinition.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.ast;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * INDEX index_name (col_name[, col_name, ...]) [USING BITMAP] [COMMENT '']\n * @author lizongbo\n * @see <a href=\"https://docs.starrocks.io/zh/docs/sql-reference/sql-statements/data-definition/CREATE_TABLE/\">...</a>\n */\npublic class StarRocksIndexDefinition extends SQLObjectImpl implements SQLTableElement {\n    private SQLName indexName;\n    private List<SQLName> columns = new ArrayList<SQLName>();\n    private String indexType;\n    private SQLExpr comment;\n    private final List<SQLAssignItem> indexOption = new ArrayList<SQLAssignItem>();\n\n    public List<SQLAssignItem> getIndexOption() {\n        return indexOption;\n    }\n\n    public String getIndexType() {\n        return indexType;\n    }\n\n    public void setIndexType(String indexType) {\n        this.indexType = indexType;\n    }\n\n    public SQLName getIndexName() {\n        return indexName;\n    }\n\n    public void setIndexName(SQLName indexName) {\n        this.indexName = indexName;\n    }\n\n    public List<SQLName> getColumns() {\n        return columns;\n    }\n\n    public void setColumns(List<SQLName> columns) {\n        this.columns = columns;\n    }\n\n    public SQLExpr getComment() {\n        return comment;\n    }\n\n    public void setComment(SQLExpr comment) {\n        this.comment = comment;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v.visit(this)) {\n            acceptChild(v, indexName);\n            acceptChild(v, columns);\n        }\n        v.endVisit(this);\n\n    }\n\n    @Override\n    public StarRocksIndexDefinition clone() {\n        StarRocksIndexDefinition x = new StarRocksIndexDefinition();\n        if (indexName != null) {\n            x.setIndexName(indexName.clone());\n        }\n        for (SQLName column : columns) {\n            SQLName columnCloned = column.clone();\n            columnCloned.setParent(x);\n            x.columns.add(columnCloned);\n        }\n        x.indexType = indexType;\n        x.comment = comment;\n        return x;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/ast/StarRocksObject.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.starrocks.visitor.StarRocksASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface StarRocksObject extends SQLObject {\n    void accept0(StarRocksASTVisitor v);\n\n    @Override\n    default void accept(SQLASTVisitor visitor) {\n        if (visitor instanceof StarRocksASTVisitor) {\n            accept0((StarRocksASTVisitor) visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/ast/statement/StarRocksCreateResourceStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatementImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLDDLStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class StarRocksCreateResourceStatement extends SQLStatementImpl implements SQLDDLStatement, SQLCreateStatement {\n    private SQLName name;\n    private List<SQLAssignItem> properties = new LinkedList<>();\n    private boolean external;\n\n    public StarRocksCreateResourceStatement() {\n        dbType = DbType.starrocks;\n    }\n\n    public StarRocksCreateResourceStatement(DbType dbType) {\n        super(dbType);\n    }\n\n    public SQLName getName() {\n        return name;\n    }\n\n    public void setName(SQLName x) {\n        if (x != null) {\n            x.setParent(this);\n        }\n        this.name = x;\n    }\n\n    public List<SQLAssignItem> getProperties() {\n        return properties;\n    }\n\n    public void setProperties(List<SQLAssignItem> properties) {\n        this.properties = properties;\n    }\n\n    public void addProperty(SQLAssignItem assignItem) {\n        if (assignItem != null) {\n            assignItem.setParent(this);\n        }\n        this.properties.add(assignItem);\n    }\n\n    public void addProperty(SQLExpr key, SQLExpr value) {\n        addProperty(new SQLAssignItem(key, value));\n    }\n\n    public void addProperty(String key, String value) {\n        addProperty(new SQLCharExpr(key), new SQLCharExpr(value));\n    }\n\n    public boolean isExternal() {\n        return external;\n    }\n\n    public void setExternal(boolean external) {\n        this.external = external;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        visitor.preVisit(this);\n        visitor.visit(this);\n        visitor.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/ast/statement/StarRocksCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.ast.statement;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.DistributedByType;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksObject;\nimport com.alibaba.druid.sql.dialect.starrocks.visitor.StarRocksASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class StarRocksCreateTableStatement extends SQLCreateTableStatement implements StarRocksObject {\n    protected DistributedByType distributedByType;\n    protected final List<SQLSelectOrderByItem> distributedBy = new ArrayList<>();\n    protected final List<SQLAssignItem> brokerProperties = new ArrayList<>();\n    public StarRocksCreateTableStatement() {\n        super(DbType.starrocks);\n    }\n\n    public DistributedByType getDistributedByType() {\n        return distributedByType;\n    }\n\n    public void setDistributedByType(DistributedByType distributedByType) {\n        this.distributedByType = distributedByType;\n    }\n\n    public List<SQLSelectOrderByItem> getDistributedBy() {\n        return distributedBy;\n    }\n\n    public List<SQLAssignItem> getBrokerProperties() {\n        return brokerProperties;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        if (v instanceof StarRocksASTVisitor) {\n            accept0((StarRocksASTVisitor) v);\n            return;\n        }\n        super.accept0(v);\n    }\n\n    @Override\n    public void accept0(StarRocksASTVisitor v) {\n        if (v.visit(this)) {\n            super.acceptChild(v);\n            acceptChild(v, engine);\n            acceptChild(v, orderBy);\n        }\n        v.endVisit(this);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/parser/StarRocksCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.parser;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksAggregateKey;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksDuplicateKey;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksIndexDefinition;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.statement.StarRocksCreateTableStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class StarRocksCreateTableParser extends SQLCreateTableParser {\n    public StarRocksCreateTableParser(Lexer lexer) {\n        super(new StarRocksExprParser(lexer));\n    }\n\n    public StarRocksCreateTableParser(String sql) {\n        super(new StarRocksExprParser(sql));\n    }\n\n    public StarRocksCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    @Override\n    public StarRocksExprParser getExprParser() {\n        return (StarRocksExprParser) exprParser;\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        if (lexer.nextIfIdentifier(FnvHash.Constants.EXTERNAL)) {\n            createTable.setExternal(true);\n        }\n        if (lexer.nextIfIdentifier(FnvHash.Constants.TEMPORARY)) {\n            createTable.setTemporary(true);\n        }\n    }\n\n    public void parseUniqueKey(SQLCreateTableStatement stmt) {\n        SQLUnique sqlUnique;\n        if (lexer.nextIfIdentifier(FnvHash.Constants.DUPLICATE)) {\n            sqlUnique = new StarRocksDuplicateKey();\n        } else if (lexer.nextIfIdentifier(FnvHash.Constants.AGGREGATE)) {\n            sqlUnique = new StarRocksAggregateKey();\n        } else if (lexer.nextIf(Token.PRIMARY)) {\n            sqlUnique = new SQLPrimaryKeyImpl();\n        } else if (lexer.nextIf(Token.UNIQUE)) {\n            sqlUnique = new SQLUnique();\n        } else {\n            return;\n        }\n        accept(Token.KEY);\n        accept(Token.LPAREN);\n        this.exprParser.orderBy(sqlUnique.getColumns(), sqlUnique);\n        accept(Token.RPAREN);\n        stmt.setUnique(sqlUnique);\n    }\n\n    protected void parseIndex(SQLCreateTableStatement createTable) {\n        if (lexer.token() == Token.INDEX) {\n            StarRocksIndexDefinition index = new StarRocksIndexDefinition();\n            lexer.nextToken();\n            index.setIndexName(this.exprParser.name());\n            accept(Token.LPAREN);\n            for (; ; ) {\n                index.getColumns().add(this.exprParser.name());\n                if (!(lexer.token() == (Token.COMMA))) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                }\n            }\n            accept(Token.RPAREN);\n            if (lexer.token() == Token.USING) {\n                lexer.nextToken();\n                if (lexer.token() == Token.BITMAP) {\n                    lexer.nextToken();\n                    index.setIndexType(\"BITMAP\");\n                } else if (lexer.token() == Token.NGRAMBF) {\n                    lexer.nextToken();\n                    index.setIndexType(\"NGRAMBF\");\n                    if (lexer.token() == Token.LPAREN) {\n                        accept(Token.LPAREN);\n                        parseAssignItems(index.getIndexOption(), createTable, false);\n                        accept(Token.RPAREN);\n                    }\n                } else if (lexer.token() == Token.INVERTED) {\n                    lexer.nextToken();\n                    index.setIndexType(\"INVERTED\");\n                }\n            }\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                index.setComment(this.exprParser.expr());\n            }\n            index.setParent(createTable);\n            createTable.getTableElementList().add(index);\n        }\n    }\n\n    public void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        StarRocksCreateTableStatement srStmt = (StarRocksCreateTableStatement) stmt;\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.ENGINE)) {\n            accept(Token.EQ);\n            srStmt.setEngine(\n                    this.exprParser.expr()\n            );\n        }\n\n        parseUniqueKey(stmt);\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLExpr comment = this.exprParser.expr();\n            srStmt.setComment(comment);\n        }\n\n        if (lexer.nextIfIdentifier(\"AUTO\")) {\n            SQLPartitionBy partitionBy = this.parsePartitionBy();\n            if (partitionBy != null) {\n                partitionBy.setAuto(true);\n            }\n            stmt.setPartitionBy(partitionBy);\n        } else {\n            stmt.setPartitionBy(this.parsePartitionBy());\n        }\n\n        // Distributed by.\n        if (lexer.nextIfIdentifier(FnvHash.Constants.DISTRIBUTED)) {\n            accept(Token.BY);\n            if (lexer.nextIfIdentifier(FnvHash.Constants.HASH)) {\n                srStmt.setDistributedByType(DistributedByType.Hash);\n                accept(Token.LPAREN);\n                this.exprParser.orderBy(srStmt.getDistributedBy(), srStmt);\n                accept(Token.RPAREN);\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.RANDOM)) {\n                srStmt.setDistributedByType(DistributedByType.Random);\n            }\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.BUCKETS)) {\n            if (lexer.token() == Token.LITERAL_INT) {\n                stmt.setBuckets(lexer.integerValue().intValue());\n                lexer.nextToken();\n            } else if (lexer.nextIfIdentifier(\"AUTO\")) {\n                stmt.setAutoBucket(true);\n            }\n        }\n\n        if (lexer.token() == Token.ORDER) {\n            SQLOrderBy orderBy = this.exprParser.parseOrderBy();\n            srStmt.setOrderBy(orderBy);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.PROPERTIES)) {\n            accept(Token.LPAREN);\n            parseAssignItems(srStmt.getTableOptions(), srStmt, false);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.BROKER)) {\n            acceptIdentifier(FnvHash.Constants.PROPERTIES);\n            accept(Token.LPAREN);\n            parseAssignItems(srStmt.getBrokerProperties(), srStmt, false);\n            accept(Token.RPAREN);\n        }\n    }\n\n    /**\n     * PARTITION BY RANGE (col1[,col2])\n     * PARTITION BY LIST (col1[,col2])\n     * PARTITION BY (col1[,col2])\n     * PARTITION BY FUNC(param1[,param2])\n     *\n     * @return\n     */\n    public SQLPartitionBy parsePartitionBy() {\n        if (lexer.nextIf(Token.PARTITION)) {\n            accept(Token.BY);\n            SQLPartitionBy partitionClause;\n            boolean hasLparen = false;\n            if (lexer.nextIfIdentifier(FnvHash.Constants.RANGE)) {\n                partitionClause = new SQLPartitionByRange();\n                accept(Token.LPAREN);\n                hasLparen = true;\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.LIST)) {\n                partitionClause = new SQLPartitionByList();\n                ((SQLPartitionByList) partitionClause).setType(SQLPartitionByList.PartitionByListType.LIST_EXPRESSION);\n                accept(Token.LPAREN);\n                hasLparen = true;\n            } else if (lexer.nextIf(Token.LPAREN)) {\n                partitionClause = new SQLPartitionByValue();\n                hasLparen = true;\n            } else {\n                partitionClause = new SQLPartitionByValue();\n            }\n            for (; ; ) {\n                partitionClause.addColumn(this.exprParser.expr());\n                if (lexer.nextIf(Token.COMMA)) {\n                    continue;\n                }\n                break;\n            }\n            if (hasLparen) {\n                accept(Token.RPAREN);\n            }\n            accept(Token.LPAREN);\n            for (; ; ) {\n                if (lexer.token() == Token.RPAREN) {\n                    break;\n                }\n                partitionClause.addPartition(this.getExprParser().parsePartition());\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n            return partitionClause;\n        }\n        return null;\n    }\n\n    protected StarRocksCreateTableStatement newCreateStatement() {\n        return new StarRocksCreateTableStatement();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/parser/StarRocksExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\n\npublic class StarRocksExprParser extends SQLExprParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n\n    static {\n        String[] strings = {\n                \"SUM\",\n                \"MAX\",\n                \"MIN\",\n                \"REPLACE\",\n                \"HLL_UNION\",\n                \"BITMAP_UNION\",\n                \"REPLACE_IF_NOT_NULL\",\n        };\n\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n    }\n\n    public StarRocksExprParser(String sql) {\n        this(new StarRocksLexer(sql));\n        this.lexer.nextToken();\n    }\n\n    public StarRocksExprParser(String sql, DbType dbType, SQLParserFeature... features) {\n        super(sql, dbType, features);\n    }\n\n    public StarRocksExprParser(Lexer lexer) {\n        super(lexer, DbType.starrocks);\n        this.aggregateFunctions = AGGREGATE_FUNCTIONS;\n        this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    }\n\n    public StarRocksExprParser(String sql, boolean keepComments) {\n        this(new StarRocksLexer(sql, true, keepComments));\n        this.lexer.nextToken();\n    }\n\n    public StarRocksExprParser(String sql, boolean skipComment, boolean keepComments) {\n        this(new StarRocksLexer(sql, skipComment, keepComments));\n        this.lexer.nextToken();\n    }\n\n    public StarRocksExprParser(Lexer lexer, DbType dbType) {\n        super(lexer, dbType);\n    }\n\n    public StarRocksExprParser(String sql, SQLParserFeature... features) {\n        super(new StarRocksLexer(sql, features), DbType.starrocks);\n        this.lexer.nextToken();\n    }\n\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        String text = lexer.stringVal();\n        for (int i = 0; i < AGGREGATE_FUNCTIONS.length; ++i) {\n            if (text.equalsIgnoreCase(AGGREGATE_FUNCTIONS[i])) {\n            SQLCharExpr aggType = new SQLCharExpr(text);\n                column.setAggType(aggType);\n                lexer.nextToken();\n            }\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.nextToken();\n            SQLExpr expr = expr();\n            column.setAsExpr(expr);\n        }\n\n        if (lexer.token() == Token.USING) {\n            lexer.nextToken();\n            SQLCharExpr bitmap = new SQLCharExpr(lexer.stringVal());\n            column.setBitmap(bitmap);\n            lexer.nextToken();\n\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n            SQLCharExpr indexComment = new SQLCharExpr(lexer.stringVal());\n                column.setIndexComment(indexComment);\n                lexer.nextToken();\n            }\n\n        }\n\n        return super.parseColumnRest(column);\n    }\n\n    @Override\n    protected String nameCommon() {\n        String identName = lexer.stringVal();\n        lexer.nextToken();\n        return identName;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/parser/StarRocksLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class StarRocksLexer extends Lexer {\n    static final Keywords STARROCKS_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"ADD\", Token.ADD);\n        map.put(\"BOTH\", Token.BOTH);\n        map.put(\"DUAL\", Token.DUAL);\n        map.put(\"FALSE\", Token.FALSE);\n        map.put(\"FORCE\", Token.FORCE);\n        map.put(\"IF\", Token.IF);\n        map.put(\"KILL\", Token.KILL);\n        map.put(\"BITMAP\", Token.BITMAP);\n        map.put(\"NGRAMBF\", Token.NGRAMBF);\n\n        map.put(\"TRUE\", Token.TRUE);\n        map.put(\"SHOW\", Token.SHOW);\n        map.put(\"ANALYZE\", Token.ANALYZE);\n        map.put(\"ROW\", Token.ROW);\n\n        map.put(\"PARTITION\", Token.PARTITION);\n\n        map.put(\"MOD\", Token.MOD);\n        map.put(\"RLIKE\", Token.RLIKE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n        STARROCKS_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return STARROCKS_KEYWORDS;\n    }\n\n    public StarRocksLexer(String input) {\n        this(input, true, true);\n    }\n\n    public StarRocksLexer(char[] input, int inputLength, boolean skipComment) {\n        super(input, inputLength, skipComment);\n        dbType = DbType.starrocks;\n    }\n\n    public StarRocksLexer(String input, SQLParserFeature... features) {\n        super(input, true);\n        this.keepComments = true;\n        dbType = DbType.starrocks;\n\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    public StarRocksLexer(String input, boolean skipComment, boolean keepComments) {\n        super(input, skipComment);\n        this.skipComment = skipComment;\n        this.keepComments = keepComments;\n        dbType = DbType.starrocks;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/parser/StarRocksSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\n\npublic class StarRocksSelectParser extends SQLSelectParser {\n    public StarRocksSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.starrocks;\n    }\n\n    protected StarRocksExprParser createExprParser() {\n        return new StarRocksExprParser(lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/parser/StarRocksStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.parser;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.statement.StarRocksCreateResourceStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class StarRocksStatementParser extends SQLStatementParser {\n    public StarRocksStatementParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n    public StarRocksStatementParser(String sql) {\n        super(new StarRocksExprParser(sql));\n    }\n\n    public StarRocksStatementParser(String sql, SQLParserFeature... features) {\n        super(new StarRocksExprParser(sql, features));\n    }\n\n    public StarRocksStatementParser(String sql, boolean keepComments) {\n        super(new StarRocksExprParser(sql, keepComments));\n    }\n\n    public StarRocksStatementParser(String sql, boolean skipComment, boolean keepComments) {\n        super(new StarRocksExprParser(sql, skipComment, keepComments));\n    }\n\n    public StarRocksStatementParser(Lexer lexer) {\n        super(new StarRocksExprParser(lexer));\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new StarRocksCreateTableParser(this.exprParser);\n    }\n\n    @Override\n    public SQLCreateTableStatement parseCreateTable() {\n        return getSQLCreateTableParser().parseCreateTable();\n    }\n\n    protected SQLStatement createResource() {\n        StarRocksCreateResourceStatement stmt = new StarRocksCreateResourceStatement();\n        accept(Token.CREATE);\n        // create external source\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            acceptIdentifier(\"EXTERNAL\");\n            stmt.setExternal(true);\n        }\n\n        acceptIdentifier(\"RESOURCE\");\n\n        stmt.setName(this.exprParser.name());\n        acceptIdentifier(\"PROPERTIES\");\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            if (lexer.token() == Token.RPAREN) {\n                accept(Token.RPAREN);\n                break;\n            }\n\n            stmt.addProperty(this.exprParser.parseAssignItem(true, stmt));\n            if (lexer.token() == Token.COMMA) {\n                accept(Token.COMMA);\n            }\n        }\n\n        return stmt;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/visitor/StarRocksASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.visitor;\n\nimport com.alibaba.druid.sql.dialect.starrocks.ast.statement.StarRocksCreateTableStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface StarRocksASTVisitor extends SQLASTVisitor {\n    default boolean visit(StarRocksCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(StarRocksCreateTableStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/starrocks/visitor/StarRocksOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.starrocks.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport com.alibaba.druid.sql.ast.DistributedByType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLPartition;\nimport com.alibaba.druid.sql.ast.expr.SQLArrayExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableAlterColumn;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLNotNullConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLNullConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;\nimport com.alibaba.druid.sql.dialect.starrocks.StarRocks;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksAggregateKey;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksDuplicateKey;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksIndexDefinition;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.statement.StarRocksCreateResourceStatement;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.statement.StarRocksCreateTableStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.util.List;\nimport java.util.Locale;\n\npublic class StarRocksOutputVisitor extends SQLASTOutputVisitor implements StarRocksASTVisitor {\n    {\n        this.shardingSupport = true;\n    }\n\n    public StarRocksOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.starrocks, StarRocks.DIALECT);\n    }\n\n    public StarRocksOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect) {\n        super(appender, dbType, dialect);\n    }\n\n    public StarRocksOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.starrocks, StarRocks.DIALECT, parameterized);\n    }\n\n    public StarRocksOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect, boolean parameterized) {\n        super(appender, dbType, dialect, parameterized);\n    }\n\n    @Override\n    protected void printEngine(SQLCreateTableStatement x) {\n        if (x instanceof StarRocksCreateTableStatement) {\n            SQLExpr engine = ((StarRocksCreateTableStatement) x).getEngine();\n            if (engine != null) {\n                print0(ucase ? \" ENGINE = \" : \" engine = \");\n                engine.accept(this);\n            }\n        }\n    }\n\n    public boolean visit(StarRocksCreateTableStatement x) {\n        return visit((SQLCreateTableStatement) x);\n    }\n\n    @Override\n    public boolean visit(SQLCreateTableStatement x) {\n        printCreateTable(x, false);\n        printEngine(x);\n        printUniqueKey(x);\n        printComment(x.getComment());\n        printPartitionBy(x);\n        printDistributedBy(x);\n        printOrderBy(x);\n        printTableOptions(x);\n        printSelectAs(x, true);\n        return false;\n    }\n\n    protected void printCreateTable(SQLCreateTableStatement x, boolean printSelect) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        printCreateTableFeatures(x);\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printTableSourceExpr(\n                x.getTableSource()\n                        .getExpr());\n\n        printCreateTableAfterName(x);\n        printTableElements(x.getTableElementList());\n    }\n\n    protected void printUniqueKey(SQLCreateTableStatement x) {\n        if (x.getUnique() != null) {\n            println();\n            if (x.getUnique() instanceof StarRocksAggregateKey) {\n                print0(ucase ? \"AGGREGATE KEY (\" : \"aggregate key (\");\n            } else if (x.getUnique() instanceof StarRocksDuplicateKey) {\n                print0(ucase ? \"DUPLICATE KEY (\" : \"duplicate key (\");\n            } else if (x.getUnique() instanceof SQLPrimaryKeyImpl) {\n                print0(ucase ? \"PRIMARY KEY (\" : \"primary key (\");\n            } else {\n                print0(ucase ? \"UNIQUE KEY (\" : \"unique key (\");\n            }\n            printAndAccept(x.getUnique().getColumns(), \", \");\n            print0(\")\");\n        }\n    }\n\n    protected void printDistributedBy(SQLCreateTableStatement x) {\n        if (x instanceof StarRocksCreateTableStatement) {\n            StarRocksCreateTableStatement createTable = (StarRocksCreateTableStatement) x;\n            if (createTable.getDistributedByType() != null) {\n                println();\n                print0(ucase ? \"DISTRIBUTED BY \" : \"distributed by \");\n                DistributedByType distributedByType = createTable.getDistributedByType();\n                if (DistributedByType.Random.equals(distributedByType)) {\n                    print0(ucase ? \"RANDOM BUCKETS\" : \"random buckets\");\n                    if (createTable.getBuckets() > 0) {\n                        print0(\" \");\n                        print0(String.valueOf(createTable.getBuckets()));\n                    }\n                } else if (DistributedByType.Hash.equals(distributedByType) && !createTable.getDistributedBy().isEmpty()) {\n                    print0(ucase ? \"HASH (\" : \"hash (\");\n                    printAndAccept(createTable.getDistributedBy(), \", \");\n                    print0(\")\");\n                    if (createTable.isAutoBucket()) {\n                        print0(ucase ? \" BUCKETS AUTO\" : \" buckets auto\");\n                    } else if (createTable.getBuckets() > 0) {\n                        print0(ucase ? \" BUCKETS \" : \" buckets \");\n                        print0(String.valueOf(createTable.getBuckets()));\n                    }\n                }\n            }\n        }\n    }\n\n    protected void printOrderBy(SQLCreateTableStatement x) {\n        if (x instanceof StarRocksCreateTableStatement) {\n            StarRocksCreateTableStatement createTable = (StarRocksCreateTableStatement) x;\n            printOrderBy(createTable.getOrderBy());\n        }\n    }\n\n    @Override\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        print0(ucase ? \"PROPERTIES (\" : \"properties (\");\n        incrementIndent();\n        println();\n    }\n\n    @Override\n    protected void printTableOptions(SQLCreateTableStatement statement) {\n        super.printTableOptions(statement);\n        if (statement instanceof StarRocksCreateTableStatement) {\n            StarRocksCreateTableStatement x = (StarRocksCreateTableStatement) statement;\n            if (!x.getBrokerProperties().isEmpty()) {\n                println();\n                print0(ucase ? \"BROKER PROPERTIES (\" : \"broker properties (\");\n                incrementIndent();\n                println();\n                int i = 0;\n                for (SQLAssignItem property : x.getBrokerProperties()) {\n                    printTableOption(property.getTarget(), property.getValue(), i);\n                    ++i;\n                }\n                decrementIndent();\n                println();\n                print0(\")\");\n            }\n        }\n    }\n\n    protected void print(List<? extends SQLExpr> exprList) {\n        int size = exprList.size();\n        if (size == 0) {\n            return;\n        }\n\n        print0(\" (\");\n\n        this.indentCount++;\n        println();\n        for (int i = 0; i < size; ++i) {\n            SQLExpr element = exprList.get(i);\n\n            if (element instanceof SQLArrayExpr) {\n                SQLArrayExpr array = ((SQLArrayExpr) element);\n                SQLExpr expr = array.getExpr();\n\n                if (expr instanceof SQLIdentifierExpr\n                        && ((SQLIdentifierExpr) expr).nameHashCode64() == FnvHash.Constants.ARRAY\n                        && printNameQuote\n                ) {\n                    print0(((SQLIdentifierExpr) expr).getName());\n                } else if (expr != null) {\n                    expr.accept(this);\n                }\n\n                print('[');\n                printAndAccept(array.getValues(), \", \");\n\n                if (i != size - 1) {\n                    print0(\",\");\n                }\n\n                print(']');\n            } else {\n                element.accept(this);\n            }\n\n            if (i != size - 1 && !(element instanceof SQLArrayExpr)) {\n                print(',');\n            }\n\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        print(')');\n    }\n\n    public boolean visit(SQLColumnDefinition x) {\n        String columnName = replaceQuota(x.getName().getSimpleName());\n        printName0(columnName);\n\n        final SQLDataType dataType = x.getDataType();\n\n        if (dataType != null) {\n            if (JdbcUtils.isPgsqlDbType(dbType) && x.getParent() instanceof SQLAlterTableAlterColumn) {\n                print0(ucase ? \" TYPE \" : \" type \");\n            } else {\n                print(' ');\n            }\n            dataType.accept(this);\n        }\n\n        if (x.getAggType() != null) {\n            visitAggType(x);\n        }\n\n        for (SQLColumnConstraint item : x.getConstraints()) {\n            if (item instanceof SQLNullConstraint || item instanceof SQLNotNullConstraint) {\n                print(' ');\n                item.accept(this);\n            }\n        }\n\n        if (x.getDefaultExpr() != null) {\n            visitColumnDefault(x);\n        }\n\n        if (x.isAutoIncrement()) {\n            printAutoIncrement();\n        }\n\n        if (x.getComment() != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            x.getComment().accept(this);\n        }\n\n        if (x.getAsExpr() != null) {\n            print(' ');\n            print0(ucase ? \"AS \" : \"as \");\n            x.getAsExpr().accept(this);\n        }\n        if (x.getBitmap() != null) {\n            print(' ');\n            print0(ucase ? \"USING \" : \"using \");\n            print0(ucase ? x.getBitmap().getText().toUpperCase(Locale.ROOT) : x.getBitmap().getText().toLowerCase(Locale.ROOT));\n        }\n        if (x.getIndexComment() != null) {\n            print(' ');\n            print0(ucase ? \"COMMENT \" : \"comment \");\n            x.getIndexComment().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(StarRocksCreateResourceStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        if (x.isExternal()) {\n            print0(ucase ? \"EXTERNAL \" : \"external \");\n        }\n\n        print0(ucase ? \"RESOURCE \" : \"resource \");\n        x.getName().accept(this);\n        println();\n\n        print0(ucase ? \"PROPERTIES\" : \"properties\");\n        print(x.getProperties());\n        return false;\n    }\n\n    public boolean visit(StarRocksIndexDefinition x) {\n        print0(ucase ? \"INDEX \" : \"index \");\n        x.getIndexName().accept(this);\n        print('(');\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n        if (x.getIndexType() != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(x.getIndexType());\n            if (!x.getIndexOption().isEmpty()) {\n                print0(\"(\");\n                int i = 0;\n                for (SQLAssignItem sqlAssignItem : x.getIndexOption()) {\n                    printIndexOption(sqlAssignItem.getTarget(), sqlAssignItem.getValue(), i);\n                    i++;\n                }\n                print0(\")\");\n            }\n        }\n        if (x.getComment() != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            x.getComment().accept(this);\n        }\n        return false;\n    }\n\n    protected void printIndexOption(SQLExpr name, SQLExpr value, int index) {\n        if (index != 0) {\n            print(\", \");\n        }\n\n        String key = name.toString();\n\n        boolean unquote = false;\n\n        print0(key);\n        if (unquote) {\n            print('\\'');\n        }\n\n        print0(\" = \");\n        value.accept(this);\n    }\n\n    @Override\n    protected void printSQLPartitions(List<SQLPartition> partitions) {\n        int partitionsSize = partitions.size();\n        print0(\" (\");\n        if (partitionsSize > 0) {\n            this.indentCount++;\n            for (int i = 0; i < partitionsSize; ++i) {\n                println();\n                partitions.get(i).accept(this);\n                if (i != partitionsSize - 1) {\n                    print0(\",\");\n                }\n            }\n            this.indentCount--;\n            println();\n        }\n        print(')');\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/SuperSql.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class SuperSql {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.supersql);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/ast/SuperSqlObject.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.supersql.visitor.SuperSqlASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface SuperSqlObject extends SQLObject {\n    void accept0(SuperSqlASTVisitor visitor);\n\n    @Override\n    default void accept(SQLASTVisitor visitor) {\n        if (visitor instanceof SuperSqlASTVisitor) {\n            accept0((SuperSqlASTVisitor) visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/parser/SuperSqlCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.parser;\n\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoCreateTableParser;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class SuperSqlCreateTableParser extends PrestoCreateTableParser {\n    public SuperSqlCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    @Override\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        if (lexer.nextIf(Token.PARTITIONED)) {\n            accept(Token.BY);\n            accept(Token.LPAREN);\n            for (; ; ) {\n                if (lexer.token() != Token.IDENTIFIER) {\n                    throw new ParserException(\"expect identifier. \" + lexer.info());\n                }\n\n                SQLColumnDefinition column = this.exprParser.parseColumn();\n                stmt.addPartitionColumn(column);\n\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    column.addAfterComment(lexer.readAndResetComments());\n                }\n\n                if (lexer.token() != Token.COMMA) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        column.addAfterComment(lexer.readAndResetComments());\n                    }\n                }\n            }\n            accept(Token.RPAREN);\n        }\n        super.parseCreateTableRest(stmt);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/parser/SuperSqlExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoExprParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class SuperSqlExprParser extends PrestoExprParser {\n    public SuperSqlExprParser(String sql, SQLParserFeature... features) {\n        this(new SuperSqlLexer(sql, features));\n        this.lexer.nextToken();\n    }\n\n    public SuperSqlExprParser(Lexer lexer) {\n        super(lexer, DbType.supersql);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/parser/SuperSqlLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoLexer;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class SuperSqlLexer extends PrestoLexer {\n    static final Keywords SUPERSQL_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"FIRST\", Token.FIRST);\n        map.put(\"ONLY\", Token.ONLY);\n        map.put(\"OPTIMIZE\", Token.OPTIMIZE);\n        map.put(\"OF\", Token.OF);\n        map.put(\"CONCAT\", Token.CONCAT);\n        map.put(\"CONTINUE\", Token.CONTINUE);\n        map.put(\"IDENTITY\", Token.IDENTITY);\n        map.put(\"MERGE\", Token.MERGE);\n        map.put(\"USING\", Token.USING);\n        map.put(\"MATCHED\", Token.MATCHED);\n        map.put(\"UPSERT\", Token.UPSERT);\n        map.put(\"IF\", Token.IF);\n        map.put(\"OVERWRITE\", Token.OVERWRITE);\n        map.put(\"PARTITION\", Token.PARTITION);\n        map.put(\"PARTITIONED\", Token.PARTITIONED);\n        map.put(\"RLIKE\", Token.RLIKE);\n\n        SUPERSQL_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return SUPERSQL_KEYWORDS;\n    }\n\n    public SuperSqlLexer(String input, SQLParserFeature... features) {\n        super(input, features);\n        this.dbType = DbType.supersql;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/parser/SuperSqlSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.parser;\n\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\n\npublic class SuperSqlSelectParser extends PrestoSelectParser {\n    public SuperSqlSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n    }\n\n    @Override\n    protected SQLExprParser createExprParser() {\n    return new SuperSqlExprParser(this.lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/parser/SuperSqlStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.parser;\n\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoStatementParser;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class SuperSqlStatementParser extends PrestoStatementParser {\n    public SuperSqlStatementParser(String sql, SQLParserFeature... features) {\n        super(new SuperSqlExprParser(sql, features));\n    }\n\n    @Override\n    public SuperSqlSelectParser createSQLSelectParser() {\n        return new SuperSqlSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new SuperSqlCreateTableParser(this.exprParser);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/visitor/SuperSqlASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.visitor;\n\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoASTVisitor;\n\npublic interface SuperSqlASTVisitor extends PrestoASTVisitor {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/supersql/visitor/SuperSqlOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.supersql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoOutputVisitor;\nimport com.alibaba.druid.sql.dialect.supersql.SuperSql;\n\npublic class SuperSqlOutputVisitor extends PrestoOutputVisitor implements SuperSqlASTVisitor {\n    public SuperSqlOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.supersql, SuperSql.DIALECT);\n    }\n\n    public SuperSqlOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.supersql, SuperSql.DIALECT, parameterized);\n    }\n\n    @Override\n    public void printInsertOverWrite(SQLInsertStatement x) {\n        print0(ucase ? \"INSERT OVERWRITE TABLE \" : \"insert overwrite table \");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/Synapse.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class Synapse {\n    public static final SQLDialect dialect = SQLDialect.of(DbType.synapse);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/ast/stmt/SynapseCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.ast.stmt;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.synapse.visitor.SynapseASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SynapseCreateTableStatement extends SQLCreateTableStatement {\n    private SQLExpr distribution;\n    private List<SQLExpr> clusteredIndexColumns = new ArrayList<>();\n    private boolean isDistributionHash;\n\n    public SynapseCreateTableStatement() {\n        super();\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor visitor) {\n        if (visitor instanceof SynapseASTVisitor) {\n            accept0((SynapseASTVisitor) visitor);\n        } else {\n            super.accept0(visitor);\n        }\n    }\n\n    protected void accept0(SynapseASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            acceptChild(visitor, getTableSource());\n            acceptChild(visitor, getTableElementList());\n            acceptChild(visitor, getInherits());\n            acceptChild(visitor, getSelect());\n        }\n        visitor.endVisit(this);\n    }\n\n    public SQLExpr getDistribution() {\n        return distribution;\n    }\n\n    public void setDistribution(SQLExpr distribution) {\n        this.distribution = distribution;\n    }\n\n    public List<SQLExpr> getClusteredIndexColumns() {\n        return clusteredIndexColumns;\n    }\n\n    public void setClusteredIndexColumns(List<SQLExpr> clusteredIndexColumns) {\n        this.clusteredIndexColumns = clusteredIndexColumns;\n    }\n\n    public boolean isDistributionHash() {\n        return isDistributionHash;\n    }\n\n    public void setDistributionHash(boolean distributionHash) {\n        isDistributionHash = distributionHash;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/parser/SynapseCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.synapse.ast.stmt.SynapseCreateTableStatement;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class SynapseCreateTableParser extends SQLCreateTableParser {\n    public SynapseCreateTableParser(String sql) {\n        super(sql);\n        this.dbType = DbType.synapse;\n    }\n\n    public SynapseCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        this.dbType = DbType.synapse;\n    }\n\n    @Override\n    protected SynapseCreateTableStatement newCreateStatement() {\n        return new SynapseCreateTableStatement();\n    }\n\n    @Override\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        if (stmt instanceof SynapseCreateTableStatement) {\n            SynapseCreateTableStatement synapseStmt = (SynapseCreateTableStatement) stmt;\n\n            if (lexer.token() == Token.WITH) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                parseSynapseWithOptions(synapseStmt);\n\n                accept(Token.RPAREN);\n            }\n        }\n\n        super.parseCreateTableRest(stmt);\n    }\n\n    private void parseSynapseWithOptions(SynapseCreateTableStatement stmt) {\n        for (;;) {\n            if (lexer.identifierEquals(\"DISTRIBUTION\")) {\n                lexer.nextToken();\n                accept(Token.EQ);\n\n                if (lexer.identifierEquals(\"HASH\")) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    SQLExpr distributionColumn = this.exprParser.expr();\n                    stmt.setDistribution(distributionColumn);\n                    stmt.setDistributionHash(true);\n                    accept(Token.RPAREN);\n                } else if (lexer.identifierEquals(\"ROUND_ROBIN\")) {\n                    lexer.nextToken();\n                    stmt.setDistributionHash(false);\n                } else if (lexer.identifierEquals(\"REPLICATE\")) {\n                    lexer.nextToken();\n                    stmt.setDistributionHash(false);\n                }\n            } else if (lexer.identifierEquals(\"CLUSTERED\")) {\n                lexer.nextToken();\n                accept(Token.INDEX);\n                accept(Token.LPAREN);\n\n                for (;;) {\n                    SQLExpr column = this.exprParser.expr();\n                    stmt.getClusteredIndexColumns().add(column);\n\n                    if (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n\n                accept(Token.RPAREN);\n            } else {\n                break;\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/parser/SynapseExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerExprParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class SynapseExprParser extends SQLServerExprParser {\n    public SynapseExprParser(String sql, SQLParserFeature... features) {\n        super(sql, features);\n        this.dbType = DbType.synapse;\n    }\n\n    public SynapseExprParser(Lexer lexer) {\n        super(lexer);\n        this.dbType = DbType.synapse;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/parser/SynapseLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerLexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\npublic class SynapseLexer extends SQLServerLexer {\n    public SynapseLexer(String input, SQLParserFeature... features) {\n        super(input, features);\n        this.dbType = DbType.synapse;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/parser/SynapseSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerSelectParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\n\npublic class SynapseSelectParser extends SQLServerSelectParser {\n    public SynapseSelectParser(SQLExprParser exprParser) {\n        super(exprParser);\n        this.dbType = DbType.synapse;\n    }\n\n    public SynapseSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        this.dbType = DbType.synapse;\n    }\n\n    public SynapseSelectParser(String sql) {\n        super(sql);\n        this.dbType = DbType.synapse;\n    }\n\n    @Override\n    protected SynapseExprParser createExprParser() {\n        return new SynapseExprParser(this.lexer);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/parser/SynapseStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\n\npublic class SynapseStatementParser extends SQLServerStatementParser {\n    public SynapseStatementParser(String sql) {\n        super(sql);\n        this.dbType = DbType.synapse;\n    }\n\n    public SynapseStatementParser(String sql, SQLParserFeature... features) {\n        super(sql, features);\n        this.dbType = DbType.synapse;\n    }\n\n    public SynapseStatementParser(Lexer lexer) {\n        super(lexer);\n        this.dbType = DbType.synapse;\n    }\n\n    @Override\n    public SQLSelectParser createSQLSelectParser() {\n        return new SynapseSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new SynapseCreateTableParser(this.exprParser);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/visitor/SynapseASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.visitor;\n\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.sql.dialect.synapse.ast.stmt.SynapseCreateTableStatement;\n\npublic interface SynapseASTVisitor extends SQLServerASTVisitor {\n    default boolean visit(SynapseCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SynapseCreateTableStatement x) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/synapse/visitor/SynapseOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.synapse.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor;\nimport com.alibaba.druid.sql.dialect.synapse.Synapse;\nimport com.alibaba.druid.sql.dialect.synapse.ast.stmt.SynapseCreateTableStatement;\n\npublic class SynapseOutputVisitor extends SQLServerOutputVisitor implements SynapseASTVisitor {\n    public SynapseOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.synapse, Synapse.dialect);\n    }\n\n    public SynapseOutputVisitor(StringBuilder appender, boolean parameterized) {\n        super(appender, DbType.synapse, Synapse.dialect, parameterized);\n    }\n\n    @Override\n    public boolean visit(SynapseCreateTableStatement x) {\n        print0(ucase ? \"CREATE TABLE \" : \"create table \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printTableSourceExpr(x.getTableSource().getExpr());\n\n        printTableElements(x.getTableElementList());\n\n        if (x.getSelect() != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            x.getSelect().accept(this);\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/TeraData.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class TeraData {\n    public static final SQLDialect dialect = SQLDialect.of(DbType.teradata);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TDCreateTableStatement.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;\nimport com.alibaba.druid.sql.dialect.teradata.visitor.TDASTVisitor;\n\npublic class TDCreateTableStatement extends SQLCreateTableStatement implements TDObject {\n    private OnCommitType onCommitRows;\n    private SQLPrimaryKey primaryKey;\n    public OnCommitType getOnCommitRows() {\n        return onCommitRows;\n    }\n\n    public void setOnCommitRows(OnCommitType onCommitRows) {\n        this.onCommitRows = onCommitRows;\n    }\n\n    public SQLPrimaryKey getPrimaryKey() {\n        return primaryKey;\n    }\n\n    public void setPrimaryKey(SQLPrimaryKey primaryKey) {\n        if (primaryKey != null) {\n            primaryKey.setParent(this);\n        }\n        this.primaryKey = primaryKey;\n    }\n\n    public TDCreateTableStatement(DbType dbType) {\n        super(dbType);\n    }\n    @Override\n    public void accept0(TDASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            visitor.endVisit(this);\n        }\n    }\n\n    public enum OnCommitType {\n        DELETE,\n        PRESERVE\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TDDateDataType.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.ast;\n\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.dialect.teradata.visitor.TDASTVisitor;\n\npublic class TDDateDataType extends SQLDataTypeImpl implements TDObject {\n    private SQLExpr format;\n\n    public TDDateDataType(String name) {\n        super(name);\n    }\n\n    public void setFormat(SQLExpr expr) {\n        format = expr;\n    }\n\n    public SQLExpr getFormat() {\n        return format;\n    }\n    @Override\n    public void accept0(TDASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            format.accept(visitor);\n            visitor.endVisit(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TDNormalize.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.dialect.teradata.visitor.TDASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class TDNormalize extends SQLObjectImpl implements TDObject {\n    private boolean meets;\n    private boolean overlaps;\n    private boolean meetsFirst;\n\n    public boolean isMeets() {\n        return meets;\n    }\n\n    public void setMeets(boolean meets) {\n        this.meets = meets;\n    }\n\n    public boolean isOverlaps() {\n        return overlaps;\n    }\n\n    public void setOverlaps(boolean overlaps) {\n        this.overlaps = overlaps;\n    }\n\n    public boolean isMeetsFirst() {\n        return meetsFirst;\n    }\n\n    public void setMeetsFirst(boolean meetsFirst) {\n        this.meetsFirst = meetsFirst;\n    }\n\n    @Override\n    public void accept0(SQLASTVisitor v) {\n        if (v instanceof TDASTVisitor) {\n            accept0((TDASTVisitor) v);\n        }\n    }\n\n    @Override\n    public void accept0(TDASTVisitor visitor) {\n        if (visitor.visit(this)) {\n            visitor.endVisit(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TDObject.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.dialect.teradata.visitor.TDASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface TDObject extends SQLObject {\n  @Override\n  default void accept(SQLASTVisitor v) {\n    if (v instanceof TDASTVisitor) {\n      accept0((TDASTVisitor) v);\n    }\n  }\n\n  void accept0(TDASTVisitor visitor);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/TDSelectQueryBlock.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.ast;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\n\npublic class TDSelectQueryBlock extends SQLSelectQueryBlock {\n    private SQLTop top;\n    private boolean withDeletedRows;\n    private boolean asJson;\n    private TDNormalize normalize;\n\n    public TDSelectQueryBlock(DbType dbType) {\n        super(dbType);\n        withDeletedRows = false;\n        asJson = false;\n    }\n\n    public SQLTop getTop() {\n        return top;\n    }\n\n    public void setTop(SQLTop top) {\n        if (top != null) {\n            top.setParent(this);\n        }\n        this.top = top;\n    }\n\n    public boolean isWithDeletedRows() {\n        return withDeletedRows;\n    }\n\n    public void setWithDeletedRows(boolean withDeletedRows) {\n        this.withDeletedRows = withDeletedRows;\n    }\n\n    public boolean isAsJson() {\n        return asJson;\n    }\n\n    public void setAsJson(boolean asJson) {\n        this.asJson = asJson;\n    }\n\n    public TDNormalize getNormalize() {\n        return normalize;\n    }\n\n    public void setNormalize(TDNormalize normalize) {\n        if (normalize != null) {\n            normalize.setParent(this);\n        }\n        this.normalize = normalize;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TDCreateTableParser.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDCreateTableStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLCreateTableParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class TDCreateTableParser extends SQLCreateTableParser {\n  /** <p>\n   * CREATE [ SET | MULTISET ] [ GLOBAL TEMPORARY | VOLATILE ] TABLE table_specification\n   *    [ , table_option [,...] ] Not supported.\n   *        { MAP = map_name [COLOCATE USING colocation_name |\n   *            [NO] FALLBACK [PROTECTION] |\n   *            WITH JOURNAL TABLE = table_specification |\n   *            [NO] LOG |\n   *            [ NO | DUAL ] [BEFORE] JOURNAL |\n   *            [ NO | DUAL | LOCAL | NOT LOCAL ] AFTER JOURNAL |\n   *            CHECKSUM = { DEFAULT | ON | OFF } |\n   *            FREESPACE = integer [PERCENT] |\n   *            mergeblockratio |\n   *            datablocksize |\n   *            blockcompression |\n   *            isolated_loading\n   *        }\n   *    ( column_partition_definition ) Limited supported\n   *        column_name data_type [ column_data_type_attribute [,...] ] |\n   *        [ COLUMN | ROW ] ( column_name data_type [column_attributes] [,...] )\n   *        [ [NO] AUTO COMPRESS] |\n   *        PERIOD FOR period_name ( period_begin_column , period_end_column ) |\n   *        normalize_option |\n   *        table_constraint\n   *        ][,...]\n   *    [ index [,...] ] Limited supported\n   *        [UNIQUE] PRIMARY INDEX [index_name] ( index_column_name [,...] ) |\n   *        NO PRIMARY INDEX |\n   *        PRIMARY AMP [INDEX] [index_name] ( index_column_name [,...] ) |\n   *        PARTITION BY { partitioning_level | ( partitioning_level [,...] ) } |\n   *        UNIQUE INDEX [ index_name ] [ ( index_column_name [,...] ) ] [loading] |\n   *        INDEX [index_name] [ALL] ( index_column_name [,...] ) [ordering] [loading]\n   *    [ table_preservation ][;]\n   *        ON COMMIT { DELETE | PRESERVE } ROWS\n   * </p>\n   */\n\n    public TDCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = DbType.teradata;\n    }\n\n    @Override\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        // Need to support both [ SET | MULTISET ] [ GLOBAL TEMPORARY | VOLATILE ] and [ GLOBAL TEMPORARY | VOLATILE ][ SET | MULTISET ].\n        parseTableType(createTable);\n        parseTableType(createTable);\n    }\n\n    private void parseTableType(SQLCreateTableStatement createTable) {\n        if (lexer.nextIf(Token.SET)) {\n            createTable.config(SQLCreateTableStatement.Feature.Set);\n        } else if (lexer.nextIfIdentifier(FnvHash.Constants.MULTISET)) {\n            createTable.config(SQLCreateTableStatement.Feature.MultiSet);\n        } else if (lexer.nextIfIdentifier(FnvHash.Constants.GLOBAL)) {\n            createTable.config(SQLCreateTableStatement.Feature.Global);\n            acceptIdentifier(FnvHash.Constants.TEMPORARY);\n            createTable.config(SQLCreateTableStatement.Feature.Temporary);\n        } else if (lexer.nextIfIdentifier(FnvHash.Constants.VOLATILE)) {\n            createTable.config(SQLCreateTableStatement.Feature.Volatile);\n        }\n    }\n\n    @Override\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        super.parseCreateTableRest(stmt);\n        if (stmt instanceof TDCreateTableStatement) {\n            if (lexer.token() == Token.PRIMARY) {\n                SQLPrimaryKey sqlPrimaryKey = this.exprParser.parsePrimaryKey();\n                ((TDCreateTableStatement) stmt).setPrimaryKey(sqlPrimaryKey);\n            }\n            if (lexer.nextIf(Token.ON)) {\n                acceptIdentifier(\"COMMIT\");\n                if (lexer.nextIf(Token.DELETE)) {\n                    ((TDCreateTableStatement) stmt)\n                            .setOnCommitRows(TDCreateTableStatement.OnCommitType.DELETE);\n                } else if (lexer.nextIfIdentifier(\"PRESERVE\")) {\n                    ((TDCreateTableStatement) stmt).setOnCommitRows(TDCreateTableStatement.OnCommitType.PRESERVE);\n                } else {\n                    throw new ParserException(\"syntax error \" + lexer.info());\n                }\n                acceptIdentifier(\"ROWS\");\n            }\n        }\n    }\n\n    @Override\n    protected SQLCreateTableStatement newCreateStatement() {\n        return new TDCreateTableStatement(getDbType());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TDExprParser.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDDateDataType;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.util.FnvHash;\n\npublic class TDExprParser extends SQLExprParser {\n    public TDExprParser(String sql, SQLParserFeature... features) {\n        super(new TDLexer(sql, features));\n        lexer.nextToken();\n        dbType = DbType.teradata;\n    }\n\n    public TDExprParser(Lexer lexer) {\n        super(lexer);\n        lexer.nextToken();\n        this.dbType = DbType.teradata;\n    }\n\n    @Override\n    protected SQLDataType parseDataTypeDate(StringBuilder typeName, int sourceLine, int sourceColumn) {\n        TDDateDataType dataType = new TDDateDataType(typeName.toString());\n        dataType.setDbType(dbType);\n        dataType.setSource(sourceLine, sourceColumn);\n        if (lexer.nextIf(Token.FORMAT) || lexer.nextIfIdentifier(FnvHash.Constants.FORMAT)) {\n            dataType.setFormat(expr());\n        }\n        return dataType;\n    }\n\n    @Override\n    public SQLPrimaryKey parsePrimaryKey() {\n        accept(Token.PRIMARY);\n        accept(Token.INDEX);\n        SQLPrimaryKeyImpl pk = new SQLPrimaryKeyImpl();\n        accept(Token.LPAREN);\n        orderBy(pk.getColumns(), pk);\n        accept(Token.RPAREN);\n        parsePrimaryKeyRest(pk);\n        return pk;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TDLexer.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.Keywords;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.Token;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class TDLexer extends Lexer {\n    static final Keywords TERADATA_KEYWORDS;\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n        map.put(\"SEL\", Token.SELECT);\n        map.put(\"TOP\", Token.TOP);\n        map.put(\"QUALIFY\", Token.QUALIFY);\n\n        TERADATA_KEYWORDS = new Keywords(map);\n    }\n\n    @Override\n    protected Keywords loadKeywords() {\n        return TERADATA_KEYWORDS;\n    }\n\n    public TDLexer(String input, SQLParserFeature... features) {\n        super(input);\n        this.keepComments = true;\n        dbType = DbType.teradata;\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TDSelectParser.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDNormalize;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDSelectQueryBlock;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLSelectParser;\nimport com.alibaba.druid.sql.parser.Token;\n\npublic class TDSelectParser extends SQLSelectParser {\n    /**\n     * <p>\n     * [ request_modifier ] { SELECT | SEL }\n     * [ WITH DELETED ROWS ]\n     * [ AS JSON ]\n     * [ select_list ]\n     *    { { DISTINCT | ALL | normalize } [ { table_name.] * | column_name }.ALL ] |\n     *        TOP_clause\n     *    }\n     *    { * | expr_spec [,...] }\n     * [ FROM_clause ]\n     *    FROM\n     *        { table_name [ [AS] correlation_name ] |\n     *            join |\n     *            derived_table_spec(Not supported) |\n     *            table_function(Not supported)  |\n     *            table_operator(Not supported) }\n     * [ WITH_clause ]\n     *    WITH\n     *        { query_name [ column_list ] AS ( select_expression ) |\n     *            RECURSIVE recursive_query_name [ column_list ] AS ( seed seed_spec [...] )\n     *        }\n     * [ WHERE_clause ]\n     * [ GROUP_BY_clause ]\n     * [ HAVING_clause | QUALIFY_clause ]\n     * [ SAMPLE_clause ] Not supported.\n     *    SAMPLE\n     *        [ WITH REPLACEMENT ]\n     *        [ RANDOMIZED LOCALIZATION ]\n     *        { { fraction_description | count_description } [,...] |\n     *            when_clause ]\n     *        }\n     * [ EXPAND_ON_clause ] Not supported.\n     *    EXPAND ON expand_expression [AS] expand_column_alias\n     *        [ BY { interval_literal |\n     *                ANCHOR [PERIOD] anchor_name [ AT time_literal ]}\n     *        ] [ FOR period_expression ]\n     * [ ORDER_BY_clause ]\n     *    ORDER BY\n     *        { expression | column_name | column_name_alias | column_position }\n     *        [ ASC |DESC ] [ NULLS { FIRST | LAST } ]\n     * [ WITH_clause [,...] ] [;]\n     * </p>\n     */\n    public TDSelectParser(Lexer lexer) {\n        super(lexer);\n    }\n\n    public TDSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser, selectListCache);\n        dbType = DbType.teradata;\n    }\n\n    protected TDExprParser createExprParser() {\n        return new TDExprParser(lexer);\n    }\n\n    protected SQLSelectQueryBlock createSelectQueryBlock() {\n        return new TDSelectQueryBlock(dbType);\n    }\n\n    @Override\n    protected void querySelectListBefore(SQLSelectQueryBlock x) {\n        if (x instanceof TDSelectQueryBlock) {\n            if (lexer.nextIf(Token.WITH)) {\n                acceptIdentifier(\"DELETED\");\n                acceptIdentifier(\"ROWS\");\n                ((TDSelectQueryBlock) x).setWithDeletedRows(true);\n            }\n            if (lexer.nextIf(Token.AS)) {\n                acceptIdentifier(\"JSON\");\n                ((TDSelectQueryBlock) x).setAsJson(true);\n            }\n        }\n    }\n    @Override\n    protected void parseBeforeSelectList(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token() == Token.DISTINCT) {\n            queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.UNIQUE) {\n            queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n            lexer.nextToken();\n        } else if (lexer.nextIfIdentifier(\"NORMALIZE\") && queryBlock instanceof TDSelectQueryBlock) {\n            TDNormalize tdNormalize = new TDNormalize();\n            if (lexer.nextIf(Token.ON)) {\n                if (lexer.nextIfIdentifier(\"MEETS\")) {\n                    tdNormalize.setMeets(true);\n                    tdNormalize.setMeetsFirst(true);\n                } else if (lexer.nextIfIdentifier(\"OVERLAPS\")) {\n                    tdNormalize.setOverlaps(true);\n                    tdNormalize.setMeetsFirst(false);\n                } else {\n                    setErrorEndPos(lexer.pos());\n                    printError(lexer.token());\n                }\n                if (lexer.nextIf(Token.OR)) {\n                    if (lexer.nextIfIdentifier(\"MEETS\")) {\n                        tdNormalize.setMeets(true);\n                    } else if (lexer.nextIfIdentifier(\"OVERLAPS\")) {\n                        tdNormalize.setOverlaps(true);\n                    } else {\n                        setErrorEndPos(lexer.pos());\n                        printError(lexer.token());\n                    }\n                }\n            }\n            ((TDSelectQueryBlock) queryBlock).setNormalize(tdNormalize);\n        }\n    }\n\n    @Override\n    protected void parseTop(SQLSelectQueryBlock x) {\n        if (x instanceof TDSelectQueryBlock) {\n            SQLTop top = this.exprParser.parseTop();\n            ((TDSelectQueryBlock) x).setTop(top);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TDStatementParser.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\n\npublic class TDStatementParser extends SQLStatementParser {\n    public TDStatementParser(TDExprParser parser) {\n        super(parser);\n        dbType = DbType.teradata;\n    }\n    public TDStatementParser(String sql, SQLParserFeature... features) {\n    this(new TDExprParser(sql, features));\n    }\n\n    @Override\n    public TDSelectParser createSQLSelectParser() {\n        return new TDSelectParser(this.exprParser, selectListCache);\n    }\n\n    @Override\n    public TDCreateTableParser getSQLCreateTableParser() {\n        return new TDCreateTableParser(this.exprParser);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TDASTVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.visitor;\n\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDDateDataType;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDNormalize;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic interface TDASTVisitor extends SQLASTVisitor {\n    default boolean visit(TDNormalize x) {\n        return true;\n    }\n    default void endVisit(TDNormalize x) {}\n    default boolean visit(TDDateDataType x) {\n        return true;\n    }\n    default void endVisit(TDDateDataType x) {}\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TDOutputVisitor.java",
    "content": "package com.alibaba.druid.sql.dialect.teradata.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLSetQuantifier;\nimport com.alibaba.druid.sql.ast.SQLTop;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.teradata.TeraData;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDDateDataType;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDNormalize;\nimport com.alibaba.druid.sql.dialect.teradata.ast.TDSelectQueryBlock;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\npublic class TDOutputVisitor extends SQLASTOutputVisitor implements TDASTVisitor {\n    public TDOutputVisitor(StringBuilder appender) {\n        super(appender, DbType.teradata, TeraData.dialect);\n    }\n\n    protected void printSelectListBefore(SQLSelectQueryBlock x) {\n        if (x instanceof TDSelectQueryBlock) {\n            print(' ');\n            TDSelectQueryBlock tdSelectQueryBlock = (TDSelectQueryBlock) x;\n            if (tdSelectQueryBlock.isWithDeletedRows()) {\n                print0(ucase ? \"WITH DELETED ROWS \" : \" with deleted rows \");\n            }\n            if (tdSelectQueryBlock.isAsJson()) {\n                print0(ucase ? \"AS JSON \" : \" as json \");\n            }\n        }\n    }\n    @Override\n    public void printSqlSetQuantifier(SQLSelectQueryBlock x) {\n        final int distinctOption = x.getDistionOption();\n        if (SQLSetQuantifier.ALL == distinctOption) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == distinctOption) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (x instanceof TDSelectQueryBlock && (((TDSelectQueryBlock) x).getNormalize() != null)) {\n            TDNormalize normalize = ((TDSelectQueryBlock) x).getNormalize();\n            print0(ucase ? \"NORMALIZE \" : \"normalize \");\n            if (normalize.isMeets() || normalize.isOverlaps()) {\n                print0(ucase ? \"ON \" : \"on \");\n                if (normalize.isMeetsFirst()) {\n                    print0(ucase ? \"MEETS \" : \"meets \");\n                } else {\n                    print0(ucase ? \"OVERLAPS \" : \"overlaps \");\n                }\n                if (normalize.isMeets() && normalize.isOverlaps()) {\n                    print0(ucase ? \"OR \" : \"or \");\n                    if (!normalize.isMeetsFirst()) {\n                        print0(ucase ? \"MEETS \" : \"meets \");\n                    } else {\n                        print0(ucase ? \"OVERLAPS \" : \"overlaps \");\n                    }\n                }\n            }\n        }\n    }\n\n    @Override\n    public void printTop(SQLSelectQueryBlock x) {\n        if (x instanceof TDSelectQueryBlock) {\n            SQLTop top = ((TDSelectQueryBlock) x).getTop();\n            if (top != null) {\n                print(' ');\n                visit(top);\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLDataType x) {\n        super.visit(x);\n        if (x instanceof TDDateDataType) {\n            TDDateDataType dataType = (TDDateDataType) x;\n            if (dataType.getFormat() != null) {\n                print(ucase ? \" FORMAT \" : \" format \");\n                dataType.getFormat().accept(this);\n            }\n        }\n        return false;\n    }\n\n    protected void printCreateTableRest(SQLCreateTableStatement x) {\n        if (x instanceof TDCreateTableStatement) {\n            TDCreateTableStatement stmt = (TDCreateTableStatement) x;\n            if (stmt.getPrimaryKey() != null) {\n                visit((SQLPrimaryKeyImpl) stmt.getPrimaryKey());\n            }\n            if (stmt.getOnCommitRows() != null) {\n                print0(ucase ? \"ON COMMIT \" : \"on commit \");\n                print0(ucase ? stmt.getOnCommitRows().name().toUpperCase() : stmt.getOnCommitRows().name().toLowerCase());\n                print0(ucase ? \" ROWS\" : \" rows\");\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLPrimaryKeyImpl x) {\n        println();\n        print0(ucase ? \"PRIMARY INDEX \" : \"primary index \");\n\n        print('(');\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n        println();\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/dialect/transact/ast/TransactSQLObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.dialect.transact.ast;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\n\npublic interface TransactSQLObject extends SQLObject {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/CharTypes.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;\n\npublic class CharTypes {\n    private static final boolean[] hexFlags = new boolean[256];\n\n    static {\n        for (char c = 0; c < hexFlags.length; ++c) {\n            if (c >= 'A' && c <= 'F') {\n                hexFlags[c] = true;\n            } else if (c >= 'a' && c <= 'f') {\n                hexFlags[c] = true;\n            } else if (c >= '0' && c <= '9') {\n                hexFlags[c] = true;\n            }\n        }\n    }\n\n    public static boolean isHex(char c) {\n        return c < 256 && hexFlags[c];\n    }\n\n    public static boolean isDigit(char c) {\n        return c >= '0' && c <= '9';\n    }\n\n    private static final boolean[] firstIdentifierFlags = new boolean[256];\n    private static final boolean[] UNDERSCORE_LETTERS = new boolean[256];\n\n    static {\n        // the Latin letter decimal values range between 192('À') and 255('ÿ') but exclude 215('×') and 247('÷').\n        for (char c = 0; c < firstIdentifierFlags.length; ++c) {\n            if ((c >= 'A' && c <= 'Z')\n                    || (c >= 'a' && c <= 'z')\n                    || (c >= 'À' && c <= 'ÿ' && c != '×' && c != '÷')) {\n                firstIdentifierFlags[c] = true;\n            }\n        }\n        firstIdentifierFlags['`'] = true;\n        firstIdentifierFlags['_'] = true;\n        firstIdentifierFlags['$'] = true;\n\n        for (char c = 'A'; c <= 'Z'; ++c) {\n            UNDERSCORE_LETTERS[c] = true;\n        }\n        for (char c = 'a'; c <= 'z'; ++c) {\n            UNDERSCORE_LETTERS[c] = true;\n        }\n        UNDERSCORE_LETTERS['_'] = true;\n    }\n\n    public static boolean letterOrUnderScore(char c) {\n        return (c & ~0xFF) == 0 && UNDERSCORE_LETTERS[c & 0xFF];\n    }\n\n    public static boolean isFirstIdentifierChar(char c) {\n        if (c < firstIdentifierFlags.length) {\n            return firstIdentifierFlags[c];\n        }\n        return c != '　' && c != '，';\n    }\n\n    private static final String[] stringCache = new String[256];\n    private static final boolean[] identifierFlags = new boolean[256];\n\n    static {\n        for (char c = 0; c < identifierFlags.length; ++c) {\n            if (c >= 'A' && c <= 'Z') {\n                identifierFlags[c] = true;\n            } else if (c >= 'a' && c <= 'z') {\n                identifierFlags[c] = true;\n            } else if (c >= '0' && c <= '9') {\n                identifierFlags[c] = true;\n            }\n        }\n        // identifierFlags['`'] = true;\n        identifierFlags['_'] = true;\n        identifierFlags['$'] = true;\n        identifierFlags['#'] = true;\n\n        for (int i = 0; i < identifierFlags.length; i++) {\n            if (identifierFlags[i]) {\n                char ch = (char) i;\n                stringCache[i] = Character.toString(ch);\n            }\n        }\n    }\n\n    public static boolean isIdentifierChar(char c) {\n        if (c < identifierFlags.length) {\n            return identifierFlags[c];\n        }\n        return c != '　' && c != '，' && c != '）' && c != '（';\n    }\n\n    public static String valueOf(char ch) {\n        if (ch < stringCache.length) {\n            return stringCache[ch];\n        }\n        return null;\n    }\n\n    private static final boolean[] whitespaceFlags = new boolean[256];\n\n    static {\n        for (int i = 0; i <= 32; ++i) {\n            whitespaceFlags[i] = true;\n        }\n\n        whitespaceFlags[EOI] = false;\n        for (int i = 0x7F; i <= 0xA0; ++i) {\n            whitespaceFlags[i] = true;\n        }\n\n        whitespaceFlags[160] = true; // 特别处理\n//        whitespaceFlags[223] = true; // 特别处理, odps\n//        whitespaceFlags[229] = true; // 特别处理, odps\n//        whitespaceFlags[231] = true; // 特别处理, odps ç\n    }\n\n    /**\n     * @return false if {@link LayoutCharacters#EOI}\n     */\n    public static boolean isWhitespace(char c) {\n        return (c < whitespaceFlags.length && whitespaceFlags[c]) //\n                || c == '　'; // Chinese space\n    }\n\n    public static String trim(String value) {\n        int len = value.length();\n        int st = 0;\n\n        while ((st < len) && (isWhitespace(value.charAt(st)))) {\n            st++;\n        }\n        while ((st < len) && isWhitespace(value.charAt(len - 1))) {\n            len--;\n        }\n        return ((st > 0) || (len < value.length())) ? value.substring(st, len) : value;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/DialectFeature.java",
    "content": "package com.alibaba.druid.sql.parser;\n\nimport java.util.List;\n\npublic class DialectFeature {\n    private long lexerFeature;\n\n    private long parserFeature;\n\n    public DialectFeature() {\n        lexerFeature = 0L;\n        parserFeature = 0L;\n        configFeature(\n                LexerFeature.ScanNumberPrefixB,\n                LexerFeature.ScanNumberCommonProcess,\n                ParserFeature.AcceptUnion,\n                ParserFeature.SQLTimestampExpr,\n                ParserFeature.PrimaryBangBangSupport,\n                ParserFeature.AdditiveRestPipesAsConcat,\n                ParserFeature.ParseStatementListSelectUnsupportedSyntax\n        );\n    }\n\n    public DialectFeature(List<Feature> configFeatures, List<Feature> unConfigFeatures) {\n        this();\n        if (configFeatures != null) {\n          for (Feature configFeature : configFeatures) {\n            configFeature(configFeature);\n          }\n        }\n        if (unConfigFeatures != null) {\n          for (Feature unConfigFeature : unConfigFeatures) {\n            unconfigFeature(unConfigFeature);\n          }\n        }\n    }\n\n    public DialectFeature(Feature... features) {\n        lexerFeature = 0L;\n        parserFeature = 0L;\n        if (features != null && features.length > 0) {\n            configFeature(features);\n        }\n    }\n\n    public DialectFeature(boolean enable, Feature... features) {\n        this();\n        if (features != null && features.length > 0) {\n            if (enable) {\n                configFeature(features);\n            } else {\n                unconfigFeature(features);\n            }\n        }\n    }\n\n    public void configFeature(Feature feature, boolean state) {\n        if (feature instanceof LexerFeature) {\n            this.lexerFeature = feature.config(this.lexerFeature, state);\n        } else if (feature instanceof ParserFeature) {\n            this.parserFeature = feature.config(this.parserFeature, state);\n        } else {\n            throw new ParserException(\"Unsupported feature type.\");\n        }\n    }\n\n    public void configFeature(Feature... features) {\n        for (Feature feature : features) {\n            configFeature(feature, true);\n        }\n    }\n\n    public void unconfigFeature(Feature... features) {\n        for (Feature feature : features) {\n            configFeature(feature, false);\n        }\n    }\n\n    public boolean isEnabled(Feature feature) {\n        if (feature instanceof LexerFeature) {\n            return feature.isEnabled(this.lexerFeature);\n        } else if (feature instanceof ParserFeature) {\n            return feature.isEnabled(this.parserFeature);\n        } else {\n            throw new ParserException(\"Unsupported feature type.\");\n        }\n    }\n\n    public interface Feature {\n        boolean isEnabled(long features);\n        long config(long features, boolean state);\n        long getMask();\n    }\n\n    public enum LexerFeature implements Feature {\n        ScanSQLTypeBlockComment(1L),\n        ScanSQLTypeWithSemi(1L << 1),\n        ScanSQLTypeWithFrom(1L << 2),\n        ScanSQLTypeWithFunction(1L << 3),\n        ScanSQLTypeWithBegin(1L << 4),\n        ScanSQLTypeWithAt(1L << 5),\n        NextTokenColon(1L << 6),\n        NextTokenPrefixN(1L << 7),\n        // Deprecated alias kept for compatibility. Use ScanStringDoubleBackslash.\n        @Deprecated\n        ScanString2PutDoubleBackslash(1L << 8),\n        ScanStringDoubleBackslash(1L << 8),\n        ScanAliasU(1L << 9),\n        ScanNumberPrefixB(1L << 10),\n        ScanNumberCommonProcess(1L << 11),\n        ScanVariableAt(1L << 12),\n        ScanVariableGreaterThan(1L << 13),\n        ScanVariableSkipIdentifiers(1L << 14),\n        ScanVariableMoveToSemi(1L << 15),\n        ScanHiveCommentDoubleSpace(1L << 16),\n        ScanSubAsIdentifier(1L << 17);\n\n        private final long mask;\n\n        @Override\n        public long getMask() {\n            return mask;\n        }\n\n        LexerFeature(long mask) {\n            this.mask = mask;\n        }\n\n        @Override\n        public boolean isEnabled(long features) {\n            return (features & mask) != 0;\n        }\n\n        @Override\n        public long config(long features, boolean state) {\n            if (state) {\n                features |= this.mask;\n            } else {\n                features &= ~this.mask;\n            }\n\n            return features;\n        }\n    }\n\n    public enum ParserFeature implements Feature {\n        AcceptUnion(1L),\n        QueryRestSemi(1L << 1),\n        AsofJoin(1L << 2),\n        GlobalJoin(1L << 3),\n        JoinAt(1L << 4),\n        JoinRightTableWith(1L << 5),\n        JoinRightTableFrom(1L << 6),\n        JoinRightTableAlias(1L << 7),\n        PostNaturalJoin(1L << 8),\n        MultipleJoinOn(1L << 9),\n        // Deprecated alias kept for compatibility. Use UserDefinedJoin.\n        @Deprecated\n        UDJ(1L << 10),\n        UserDefinedJoin(1L << 10),\n        TwoConsecutiveUnion(1L << 11),\n        QueryTable(1L << 12),\n        GroupByAll(1L << 13),\n        RewriteGroupByCubeRollupToFunction(1L << 14),\n        GroupByPostDesc(1L << 15),\n        GroupByItemOrder(1L << 16),\n        SQLDateExpr(1L << 17),\n        SQLTimestampExpr(1L << 18),\n        PrimaryVariantColon(1L << 19),\n        PrimaryBangBangSupport(1L << 20),\n        PrimaryTwoConsecutiveSet(1L << 21),\n        PrimaryLbraceOdbcEscape(1L << 22),\n        ParseAllIdentifier(1L << 23),\n        PrimaryRestCommaAfterLparen(1L << 24),\n        InRestSpecificOperation(1L << 25),\n        AdditiveRestPipesAsConcat(1L << 26),\n        ParseAssignItemRparenCommaSetReturn(1L << 27),\n        ParseAssignItemEqSemiReturn(1L << 28),\n        ParseAssignItemSkip(1L << 29),\n        ParseAssignItemEqeq(1L << 30),\n        ParseSelectItemPrefixX(1L << 31),\n        ParseLimitBy(1L << 32),\n        ParseStatementListWhen(1L << 33),\n        ParseStatementListSelectUnsupportedSyntax(1L << 34),\n        ParseStatementListUpdatePlanCache(1L << 35),\n        ParseStatementListRollbackReturn(1L << 36),\n        ParseStatementListCommitReturn(1L << 37),\n        ParseStatementListLparenContinue(1L << 38),\n        ParseRevokeFromUser(1L << 39),\n        ParseDropTableTables(1L << 40),\n        ParseCreateSql(1L << 41),\n        CreateTableBodySupplemental(1L << 42),\n        TableAliasConnectWhere(1L << 43),\n        TableAliasAsof(1L << 44),\n        TableAliasLock(1L << 45),\n        TableAliasPartition(1L << 46),\n        TableAliasTable(1L << 47),\n        TableAliasBetween(1L << 48),\n        TableAliasRest(1L << 49),\n        AsCommaFrom(1L << 50),\n        AsSkip(1L << 51),\n        AsSequence(1L << 52),\n        AsDatabase(1L << 53),\n        AsDefault(1L << 54),\n        AliasLiteralFloat(1L << 55);\n\n        private final long mask;\n\n        ParserFeature(long mask) {\n            this.mask = mask;\n        }\n\n        @Override\n        public long getMask() {\n            return mask;\n        }\n\n        @Override\n        public boolean isEnabled(long features) {\n            return (features & mask) != 0;\n        }\n\n        @Override\n        public long config(long features, boolean state) {\n            if (state) {\n                features |= this.mask;\n            } else {\n                features &= ~this.mask;\n            }\n\n            return features;\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/EOFParserException.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\n@SuppressWarnings(\"serial\")\npublic class EOFParserException extends ParserException {\n    public EOFParserException() {\n        super(\"EOF\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/InsertColumnsCache.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\npublic class InsertColumnsCache {\n    public static InsertColumnsCache global;\n\n    static {\n        global = new InsertColumnsCache(8192);\n    }\n\n    public ConcurrentMap<Long, Entry> cache = new ConcurrentHashMap<Long, Entry>();\n\n    private final Entry[] buckets;\n    private final int indexMask;\n\n    public InsertColumnsCache(int tableSize) {\n        this.indexMask = tableSize - 1;\n        this.buckets = new Entry[tableSize];\n    }\n\n    public final Entry get(long hashCode64) {\n        final int bucket = ((int) hashCode64) & indexMask;\n        for (Entry entry = buckets[bucket]; entry != null; entry = entry.next) {\n            if (hashCode64 == entry.hashCode64) {\n                return entry;\n            }\n        }\n\n        return null;\n    }\n\n    public boolean put(long hashCode64, String columnsString, String columnsFormattedString, List<SQLExpr> columns) {\n        final int bucket = ((int) hashCode64) & indexMask;\n\n        for (Entry entry = buckets[bucket]; entry != null; entry = entry.next) {\n            if (hashCode64 == entry.hashCode64) {\n                return true;\n            }\n        }\n\n        Entry entry = new Entry(hashCode64, columnsString, columnsFormattedString, columns, buckets[bucket]);\n        buckets[bucket] = entry;  // 并发是处理时会可能导致缓存丢失，但不影响正确性\n\n        return false;\n    }\n\n    public static final class Entry {\n        public final long hashCode64;\n        public final String columnsString;\n        public final String columnsFormattedString;\n        public final long columnsFormattedStringHash;\n        public final List<SQLExpr> columns;\n        public final Entry next;\n\n        public Entry(long hashCode64,\n                     String columnsString,\n                     String columnsFormattedString,\n                     List<SQLExpr> columns,\n                     Entry next) {\n            this.hashCode64 = hashCode64;\n            this.columnsString = columnsString;\n            this.columnsFormattedString = columnsFormattedString;\n            this.columnsFormattedStringHash = FnvHash.fnv1a_64_lower(columnsFormattedString);\n            this.columns = columns;\n            this.next = next;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/Keywords.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class Keywords {\n    private final Map<String, Token> keywords;\n    private final long[] hashArray;\n    private final Token[] tokens;\n\n    public static final Keywords DEFAULT_KEYWORDS;\n    public static final Keywords SQLITE_KEYWORDS;\n    public static final Keywords DM_KEYWORDS;\n\n    static {\n        Map<String, Token> map = new HashMap<>();\n\n        map.put(\"ALL\", Token.ALL);\n        map.put(\"ALTER\", Token.ALTER);\n        map.put(\"AND\", Token.AND);\n        map.put(\"ANY\", Token.ANY);\n        map.put(\"AS\", Token.AS);\n\n        map.put(\"ENABLE\", Token.ENABLE);\n        map.put(\"DISABLE\", Token.DISABLE);\n\n        map.put(\"ASC\", Token.ASC);\n        map.put(\"BETWEEN\", Token.BETWEEN);\n        map.put(\"BY\", Token.BY);\n        map.put(\"CASE\", Token.CASE);\n        map.put(\"CAST\", Token.CAST);\n\n        map.put(\"CHECK\", Token.CHECK);\n        map.put(\"CONSTRAINT\", Token.CONSTRAINT);\n        map.put(\"CREATE\", Token.CREATE);\n        map.put(\"DATABASE\", Token.DATABASE);\n        map.put(\"DEFAULT\", Token.DEFAULT);\n        map.put(\"DIAGNOSTICS\", Token.DIAGNOSTICS);\n        map.put(\"COLUMN\", Token.COLUMN);\n        map.put(\"TABLESPACE\", Token.TABLESPACE);\n        map.put(\"PROCEDURE\", Token.PROCEDURE);\n        map.put(\"FUNCTION\", Token.FUNCTION);\n\n        map.put(\"DELETE\", Token.DELETE);\n        map.put(\"DESC\", Token.DESC);\n        map.put(\"DISTINCT\", Token.DISTINCT);\n        map.put(\"DROP\", Token.DROP);\n        map.put(\"ELSE\", Token.ELSE);\n        map.put(\"EXPLAIN\", Token.EXPLAIN);\n        map.put(\"EXCEPT\", Token.EXCEPT);\n\n        map.put(\"END\", Token.END);\n        map.put(\"ESCAPE\", Token.ESCAPE);\n        map.put(\"EXISTS\", Token.EXISTS);\n        map.put(\"FOR\", Token.FOR);\n        map.put(\"FOREIGN\", Token.FOREIGN);\n\n        map.put(\"FROM\", Token.FROM);\n        map.put(\"FULL\", Token.FULL);\n        map.put(\"GET\", Token.GET);\n        map.put(\"GROUP\", Token.GROUP);\n        map.put(\"HAVING\", Token.HAVING);\n        map.put(\"IN\", Token.IN);\n\n        map.put(\"INDEX\", Token.INDEX);\n        map.put(\"INNER\", Token.INNER);\n        map.put(\"INSERT\", Token.INSERT);\n        map.put(\"INTERSECT\", Token.INTERSECT);\n        map.put(\"INTERVAL\", Token.INTERVAL);\n\n        map.put(\"INTO\", Token.INTO);\n        map.put(\"IS\", Token.IS);\n        map.put(\"JOIN\", Token.JOIN);\n        map.put(\"KEY\", Token.KEY);\n        map.put(\"LEFT\", Token.LEFT);\n\n        map.put(\"LIKE\", Token.LIKE);\n        map.put(\"LOCK\", Token.LOCK);\n        map.put(\"MINUS\", Token.MINUS);\n        map.put(\"NOT\", Token.NOT);\n\n        map.put(\"NULL\", Token.NULL);\n        map.put(\"ON\", Token.ON);\n        map.put(\"OR\", Token.OR);\n        map.put(\"ORDER\", Token.ORDER);\n        map.put(\"OUTER\", Token.OUTER);\n\n        map.put(\"PRIMARY\", Token.PRIMARY);\n        map.put(\"REFERENCES\", Token.REFERENCES);\n        map.put(\"RIGHT\", Token.RIGHT);\n        map.put(\"SCHEMA\", Token.SCHEMA);\n        map.put(\"SELECT\", Token.SELECT);\n\n        map.put(\"SET\", Token.SET);\n        map.put(\"SOME\", Token.SOME);\n        map.put(\"TABLE\", Token.TABLE);\n        map.put(\"THEN\", Token.THEN);\n        map.put(\"TRUNCATE\", Token.TRUNCATE);\n\n        map.put(\"UNION\", Token.UNION);\n        map.put(\"UNIQUE\", Token.UNIQUE);\n        map.put(\"UPDATE\", Token.UPDATE);\n        map.put(\"VALUES\", Token.VALUES);\n        map.put(\"VIEW\", Token.VIEW);\n        map.put(\"SEQUENCE\", Token.SEQUENCE);\n        map.put(\"TRIGGER\", Token.TRIGGER);\n        map.put(\"USER\", Token.USER);\n\n        map.put(\"WHEN\", Token.WHEN);\n        map.put(\"WHERE\", Token.WHERE);\n        map.put(\"XOR\", Token.XOR);\n\n        map.put(\"OVER\", Token.OVER);\n        map.put(\"TO\", Token.TO);\n        map.put(\"USE\", Token.USE);\n\n        map.put(\"REPLACE\", Token.REPLACE);\n\n        map.put(\"COMMENT\", Token.COMMENT);\n        map.put(\"COMPUTE\", Token.COMPUTE);\n        map.put(\"WITH\", Token.WITH);\n        map.put(\"GRANT\", Token.GRANT);\n        map.put(\"REVOKE\", Token.REVOKE);\n\n        // MySql procedure: add by zz\n        map.put(\"WHILE\", Token.WHILE);\n        map.put(\"DO\", Token.DO);\n        map.put(\"DECLARE\", Token.DECLARE);\n        map.put(\"LOOP\", Token.LOOP);\n        map.put(\"LEAVE\", Token.LEAVE);\n        map.put(\"ITERATE\", Token.ITERATE);\n        map.put(\"REPEAT\", Token.REPEAT);\n        map.put(\"UNTIL\", Token.UNTIL);\n        map.put(\"OPEN\", Token.OPEN);\n        map.put(\"CLOSE\", Token.CLOSE);\n        map.put(\"CURSOR\", Token.CURSOR);\n        map.put(\"FETCH\", Token.FETCH);\n        map.put(\"OUT\", Token.OUT);\n        map.put(\"INOUT\", Token.INOUT);\n\n        map.put(\"LIMIT\", Token.LIMIT);\n\n        DEFAULT_KEYWORDS = new Keywords(map);\n\n        {\n            Map<String, Token> sqlitemap = new HashMap<>(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n            sqlitemap.put(\"LIMIT\", Token.LIMIT);\n            SQLITE_KEYWORDS = new Keywords(sqlitemap);\n        }\n\n        {\n            Map<String, Token> sqlitemap = new HashMap<>(Keywords.DEFAULT_KEYWORDS.getKeywords());\n\n            sqlitemap.put(\"MERGE\", Token.MERGE);\n            sqlitemap.put(\"MATCHED\", Token.MATCHED);\n            sqlitemap.put(\"USING\", Token.USING);\n            DM_KEYWORDS = new Keywords(sqlitemap);\n        }\n    }\n\n    public boolean containsValue(Token token) {\n        return this.keywords.containsValue(token);\n    }\n\n    public Keywords(Map<String, Token> keywords) {\n        this.keywords = keywords;\n\n        this.hashArray = new long[keywords.size()];\n        this.tokens = new Token[keywords.size()];\n\n        int index = 0;\n        for (String k : keywords.keySet()) {\n            hashArray[index++] = FnvHash.fnv1a_64_lower(k);\n        }\n        Arrays.sort(hashArray);\n        for (Map.Entry<String, Token> entry : keywords.entrySet()) {\n            long k = FnvHash.fnv1a_64_lower(entry.getKey());\n            index = Arrays.binarySearch(hashArray, k);\n            tokens[index] = entry.getValue();\n        }\n    }\n\n    public Token getKeyword(long hash) {\n        int index = Arrays.binarySearch(hashArray, hash);\n        if (index < 0) {\n            return null;\n        }\n        return tokens[index];\n    }\n\n    public Token getKeyword(String key) {\n        long k = FnvHash.fnv1a_64_lower(key);\n        int index = Arrays.binarySearch(hashArray, k);\n        if (index < 0) {\n            return null;\n        }\n        return tokens[index];\n//        return keywords.get(key);\n    }\n\n    public Map<String, Token> getKeywords() {\n        return keywords;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/LayoutCharacters.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface LayoutCharacters {\n    /**\n     * Tabulator column increment.\n     */\n    static final int TabInc = 8;\n\n    /**\n     * Tabulator character.\n     */\n    static final byte TAB = 0x8;\n\n    /**\n     * Line feed character.\n     */\n    static final byte LF = 0xA;\n\n    /**\n     * Form feed character.\n     */\n    static final byte FF = 0xC;\n\n    /**\n     * Carriage return character.\n     */\n    static final byte CR = 0xD;\n\n    /**\n     * End of input character. Used as a sentinel to denote the character one beyond the last defined character in a\n     * source file.\n     */\n    static final byte EOI = 0x1A;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/Lexer.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLNumberExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.TimeZone;\n\nimport static com.alibaba.druid.sql.parser.CharTypes.*;\nimport static com.alibaba.druid.sql.parser.DialectFeature.LexerFeature.*;\nimport static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;\nimport static com.alibaba.druid.sql.parser.SQLParserFeature.*;\nimport static com.alibaba.druid.sql.parser.Token.*;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class Lexer {\n    protected static final DialectFeature FEATURE = new DialectFeature();\n    protected static SymbolTable symbols_l2 = new SymbolTable(512);\n\n    protected int features; //SQLParserFeature.of(SQLParserFeature.EnableSQLBinaryOpExprGroup);\n    protected TimeZone timeZone;\n    public final String text;\n    protected int pos;\n    protected int mark;\n    protected int numberSale;\n    protected boolean numberExp;\n\n    protected char ch;\n\n    protected char[] buf;\n    protected int bufPos;\n\n    protected Token token;\n\n    protected Keywords keywords;\n\n    protected String stringVal;\n    protected long hashLCase; // fnv1a_64\n    protected long hash;\n\n    protected int commentCount;\n    protected List<String> comments;\n    protected boolean skipComment = true;\n    private SavePoint savePoint;\n\n    /*\n     * anti sql injection\n     */\n    private boolean allowComment = true;\n    private int varIndex = -1;\n    protected CommentHandler commentHandler;\n    protected boolean endOfComment;\n    protected boolean keepComments;\n    protected int line;\n    protected int lines;\n    protected DbType dbType;\n\n    protected boolean optimizedForParameterized;\n    protected boolean keepSourceLocation;\n\n    protected int startPos;\n    protected int posLine;\n    protected int posColumn;\n    protected DialectFeature dialectFeature;\n\n    public Lexer(String input) {\n        this(input, (CommentHandler) null);\n    }\n\n    public Lexer(String input, DbType dbType) {\n        this(input, null, dbType);\n    }\n\n    public Lexer(String input, CommentHandler commentHandler) {\n        this(input, true);\n        this.commentHandler = commentHandler;\n    }\n\n    public Lexer(String input, CommentHandler commentHandler, DbType dbType) {\n        this(input, true);\n        this.commentHandler = commentHandler;\n        this.dbType = dbType;\n\n        if (DbType.dm == dbType) {\n            this.keywords = Keywords.DM_KEYWORDS;\n        }\n    }\n    protected Keywords loadKeywords() {\n        return Keywords.DEFAULT_KEYWORDS;\n    }\n\n    public boolean isKeepSourceLocation() {\n        return keepSourceLocation;\n    }\n\n    public boolean isKeepComments() {\n        return keepComments;\n    }\n\n    public void setKeepComments(boolean keepComments) {\n        this.keepComments = keepComments;\n    }\n\n    public CommentHandler getCommentHandler() {\n        return commentHandler;\n    }\n\n    public void setCommentHandler(CommentHandler commentHandler) {\n        this.commentHandler = commentHandler;\n    }\n\n    public final char charAt(int index) {\n        if (index >= text.length()) {\n            return EOI;\n        }\n\n        return text.charAt(index);\n    }\n\n    public final String addSymbol() {\n        return subString(mark, bufPos);\n    }\n\n    public final String subString(int offset, int count) {\n        return text.substring(offset, offset + count);\n    }\n\n    public final String subString(int offset) {\n        return text.substring(offset);\n    }\n\n    public final char[] sub_chars(int offset, int count) {\n        char[] chars = new char[count];\n        text.getChars(offset, offset + count, chars, 0);\n        return chars;\n    }\n\n    protected void initBuff(int size) {\n        if (buf == null) {\n            if (size < 32) {\n                buf = new char[32];\n            } else {\n                buf = new char[size + 32];\n            }\n        } else if (buf.length < size) {\n            buf = Arrays.copyOf(buf, size);\n        }\n    }\n\n    public void arraycopy(int srcPos, char[] dest, int destPos, int length) {\n        text.getChars(srcPos, srcPos + length, dest, destPos);\n    }\n\n    public boolean isAllowComment() {\n        return allowComment;\n    }\n\n    public void setAllowComment(boolean allowComment) {\n        this.allowComment = allowComment;\n    }\n\n    public int nextVarIndex() {\n        return ++varIndex;\n    }\n\n    public static class SavePoint {\n        int bp;\n        int startPos;\n        int sp;\n        int np;\n        char ch;\n        long hash;\n        long hashLCase;\n        public Token token;\n        String stringVal;\n    }\n\n    public Keywords getKeywords() {\n        return keywords;\n    }\n\n    //出现多次调用mark()后调用reset()会有问题\n    @Deprecated\n    public SavePoint mark() {\n        return this.savePoint = markOut();\n    }\n\n    public SavePoint markOut() {\n        SavePoint savePoint = new SavePoint();\n        savePoint.bp = pos;\n        savePoint.sp = bufPos;\n        savePoint.np = mark;\n        savePoint.ch = ch;\n        savePoint.token = token;\n        savePoint.stringVal = stringVal;\n        savePoint.hash = hash;\n        savePoint.hashLCase = hashLCase;\n        savePoint.startPos = startPos;\n        return savePoint;\n    }\n\n    public void reset(SavePoint savePoint) {\n        this.pos = savePoint.bp;\n        this.bufPos = savePoint.sp;\n        this.mark = savePoint.np;\n        this.ch = savePoint.ch;\n        this.token = savePoint.token;\n        this.stringVal = savePoint.stringVal;\n        this.hash = savePoint.hash;\n        this.hashLCase = savePoint.hashLCase;\n        this.startPos = savePoint.startPos;\n    }\n\n    //出现多次调用mark()后调用reset()会有问题\n    @Deprecated\n    public void reset() {\n        this.reset(this.savePoint);\n    }\n\n    public void reset(int pos) {\n        this.pos = pos;\n        this.ch = charAt(pos);\n    }\n\n    public Lexer(String input, boolean skipComment) {\n        this.skipComment = skipComment;\n\n        this.text = input;\n        this.pos = 0;\n        ch = charAt(pos);\n        while (ch == '\\u200B' || ch == '\\n') {\n            if (ch == '\\n') {\n                line++;\n            }\n            ch = charAt(++pos);\n        }\n        initDialectFeature();\n        this.keywords = loadKeywords();\n    }\n\n    protected void initDialectFeature() {\n        this.dialectFeature = FEATURE;\n    }\n\n    public Lexer(char[] input, int inputLength, boolean skipComment) {\n        this(new String(input, 0, inputLength), skipComment);\n    }\n\n    protected final void scanChar() {\n        ch = charAt(++pos);\n    }\n\n    protected void unscan() {\n        ch = charAt(--pos);\n    }\n\n    public boolean isEOF() {\n        return pos >= text.length();\n    }\n\n    /**\n     * Report an error at the given position using the provided arguments.\n     */\n    protected void lexError(String key, Object... args) {\n        token = ERROR;\n    }\n\n    /**\n     * Return the current token, set by nextToken().\n     */\n    public final Token token() {\n        return token;\n    }\n\n    public boolean nextIf(Token token) {\n        if (this.token == token) {\n            nextToken();\n            return true;\n        }\n        return false;\n    }\n\n    public final boolean nextIfComma() {\n        if (this.token == COMMA) {\n            nextToken();\n            return true;\n        }\n        return false;\n    }\n\n    public final boolean nextIfIdentifier(String identifier) {\n        if (this.identifierEquals(identifier)) {\n            nextToken();\n            return true;\n        }\n        return false;\n    }\n\n    public final boolean nextIfIdentifier(long hashCode54) {\n        if (this.identifierEquals(hashCode54)) {\n            nextToken();\n            return true;\n        }\n        return false;\n    }\n\n    public void setToken(Token token) {\n        this.token = token;\n    }\n\n    public final DbType getDbType() {\n        return this.dbType;\n    }\n\n    public String info() {\n        computeRowAndColumn();\n\n        StringBuilder buf = new StringBuilder();\n        buf.append(\"pos \")\n                .append(pos)\n                .append(\", line \")\n                .append(this.getPosLine())\n                .append(\", column \")\n                .append(this.getPosColumn());\n        if (token != null) {\n            if (token.name != null) {\n                buf.append(\", token \").append(token.name);\n            } else {\n                buf.append(\", token \").append(token.name());\n            }\n        }\n\n        if (token == Token.IDENTIFIER\n                || token == Token.LITERAL_ALIAS\n                || token == Token.LITERAL_CHARS) {\n            buf.append(\" \")\n                    .append(\n                            stringVal());\n        }\n\n        if (isEnabled(SQLParserFeature.PrintSQLWhileParsingFailed)) {\n            buf.append(\", SQL : \");\n            buf.append(text);\n        }\n\n        return buf.toString();\n    }\n\n    public final void nextTokenComma() {\n        if (ch == ' ') {\n            scanChar();\n        }\n\n        if (ch == ',' || ch == '，') {\n            scanChar();\n            token = COMMA;\n            return;\n        }\n\n        if (ch == ')' || ch == '）') {\n            scanChar();\n            token = RPAREN;\n            return;\n        }\n\n        if (ch == '.') {\n            scanChar();\n            token = DOT;\n            return;\n        }\n\n        if (ch == 'a' || ch == 'A') {\n            char ch_next = charAt(pos + 1);\n            if (ch_next == 's' || ch_next == 'S') {\n                char ch_next_2 = charAt(pos + 2);\n                if (ch_next_2 == ' ') {\n                    pos += 2;\n                    ch = ' ';\n                    token = Token.AS;\n                    stringVal = \"AS\";\n                    return;\n                }\n            }\n        }\n\n        nextToken();\n    }\n\n    public final void nextTokenCommaValue() {\n        if (ch == ' ') {\n            scanChar();\n        }\n\n        if (ch == ',' || ch == '，') {\n            scanChar();\n            token = COMMA;\n            return;\n        }\n\n        if (ch == ')' || ch == '）') {\n            scanChar();\n            token = RPAREN;\n            return;\n        }\n\n        if (ch == '.') {\n            scanChar();\n            token = DOT;\n            return;\n        }\n\n        if (ch == 'a' || ch == 'A') {\n            char ch_next = charAt(pos + 1);\n            if (ch_next == 's' || ch_next == 'S') {\n                char ch_next_2 = charAt(pos + 2);\n                if (ch_next_2 == ' ') {\n                    pos += 2;\n                    ch = ' ';\n                    token = Token.AS;\n                    stringVal = \"AS\";\n                    return;\n                }\n            }\n        }\n\n        nextTokenValue();\n    }\n\n    public final void nextTokenEq() {\n        if (ch == ' ') {\n            scanChar();\n        }\n\n        if (ch == '=') {\n            scanChar();\n            if (ch == '=') {\n                scanChar();\n                token = EQEQ;\n            } else if (ch == '>') {\n                scanChar();\n                token = EQGT;\n            } else {\n                token = EQ;\n            }\n            return;\n        }\n\n        if (ch == '.') {\n            scanChar();\n            token = DOT;\n            return;\n        }\n\n        if (ch == 'a' || ch == 'A') {\n            char ch_next = charAt(pos + 1);\n            if (ch_next == 's' || ch_next == 'S') {\n                char ch_next_2 = charAt(pos + 2);\n                if (ch_next_2 == ' ') {\n                    pos += 2;\n                    ch = ' ';\n                    token = Token.AS;\n                    stringVal = \"AS\";\n                    return;\n                }\n            }\n        }\n\n        nextToken();\n    }\n\n    public final void nextTokenLParen() {\n        if (ch == ' ') {\n            scanChar();\n        }\n\n        if (ch == '(' || ch == '（') {\n            scanChar();\n            token = LPAREN;\n            return;\n        }\n        nextToken();\n    }\n\n    public final void nextTokenValue() {\n        while (ch == ' ') {\n            scanChar();\n        }\n\n        this.startPos = pos;\n        if (ch == '\\'') {\n            bufPos = 0;\n            scanString();\n            return;\n        }\n\n        if (ch == '\"' && !isEnabled(SQLParserFeature.KeepNameQuotes)) {\n            bufPos = 0;\n            scanString2_d();\n            return;\n        }\n\n        if (ch == '0') {\n            bufPos = 0;\n            if (charAt(pos + 1) == 'x') {\n                scanChar();\n                scanChar();\n                scanHexaDecimal();\n            } else {\n                scanNumber();\n            }\n            return;\n        }\n\n        if (ch > '0' && ch <= '9') {\n            bufPos = 0;\n            scanNumber();\n            return;\n        }\n\n        if (ch == '-') {\n            char next = charAt(pos + 1);\n            if (next >= '0' && next <= '9') {\n                bufPos = 0;\n                scanNumber();\n                return;\n            }\n        }\n\n        if (ch == '?') {\n            scanChar();\n            token = Token.QUES;\n            return;\n        }\n\n        if (ch == 'n' || ch == 'N') {\n            char c1 = 0, c2, c3, c4;\n            if (pos + 4 < text.length()\n                    && ((c1 = text.charAt(pos + 1)) == 'u' || c1 == 'U')\n                    && ((c2 = text.charAt(pos + 2)) == 'l' || c2 == 'L')\n                    && ((c3 = text.charAt(pos + 3)) == 'l' || c3 == 'L')\n                    && (isWhitespace(c4 = text.charAt(pos + 4)) || c4 == ',' || c4 == ')' || c4 == '）')) {\n                pos += 4;\n                ch = c4;\n                token = Token.NULL;\n                stringVal = \"NULL\";\n                return;\n            }\n\n            if (c1 == '\\'') {\n                bufPos = 0;\n                ++pos;\n                ch = '\\'';\n                scanString();\n                token = Token.LITERAL_NCHARS;\n                return;\n            }\n        }\n\n        if (ch == ')' || ch == '）') {\n            scanChar();\n            token = Token.RPAREN;\n            return;\n        }\n\n        if (ch == '（') {\n            scanChar();\n            token = Token.LPAREN;\n            return;\n        }\n\n        if (ch == '$' && isVariantChar(charAt(pos + 1))) {\n            scanVariable();\n            return;\n        }\n\n        if (isFirstIdentifierChar(ch)) {\n            scanIdentifier();\n            return;\n        }\n\n        nextToken();\n    }\n\n    static boolean isVariantChar(char ch) {\n        return ch == '{' || (ch >= '0' && ch <= '9');\n    }\n\n    public final void nextTokenBy() {\n        while (ch == ' ') {\n            scanChar();\n        }\n\n        if (ch == 'b' || ch == 'B') {\n            char ch_next = charAt(pos + 1);\n            if (ch_next == 'y' || ch_next == 'Y') {\n                char ch_next_2 = charAt(pos + 2);\n                if (ch_next_2 == ' ') {\n                    pos += 2;\n                    ch = ' ';\n                    token = Token.BY;\n                    stringVal = \"BY\";\n                    return;\n                }\n            }\n        }\n\n        nextToken();\n    }\n\n    public final void nextTokenNotOrNull() {\n        while (ch == ' ') {\n            scanChar();\n        }\n\n        if ((ch == 'n' || ch == 'N') && pos + 3 < text.length()) {\n            char c1 = text.charAt(pos + 1);\n            char c2 = text.charAt(pos + 2);\n            char c3 = text.charAt(pos + 3);\n\n            if ((c1 == 'o' || c1 == 'O')\n                    && (c2 == 't' || c2 == 'T')\n                    && isWhitespace(c3)) {\n                pos += 3;\n                ch = c3;\n                token = Token.NOT;\n                stringVal = \"NOT\";\n                return;\n            }\n\n            char c4;\n            if (pos + 4 < text.length()\n                    && (c1 == 'u' || c1 == 'U')\n                    && (c2 == 'l' || c2 == 'L')\n                    && (c3 == 'l' || c3 == 'L')\n                    && isWhitespace(c4 = text.charAt(pos + 4))) {\n                pos += 4;\n                ch = c4;\n                token = Token.NULL;\n                stringVal = \"NULL\";\n                return;\n            }\n        }\n\n        nextToken();\n    }\n\n    public final void nextTokenIdent() {\n        while (ch == ' ') {\n            scanChar();\n        }\n\n        if (ch == '$' && isVariantChar(charAt(pos + 1))) {\n            scanVariable();\n            return;\n        }\n\n        if (isFirstIdentifierChar(ch) && ch != '（') {\n            scanIdentifier();\n            return;\n        }\n\n        if (ch == ')') {\n            scanChar();\n            token = RPAREN;\n            return;\n        }\n\n        nextToken();\n    }\n\n    public final SQLType scanSQLType() {\n        _loop:\n        for (; ; ) {\n            while (isWhitespace(ch)) {\n                ch = charAt(++pos);\n            }\n\n            if (ch == '/') {\n                if (pos + 1 < text.length() && text.charAt(pos + 1) == '*') {\n                    int index = text.indexOf(\"*/\", pos + 2);\n                    if (index == -1) {\n                        return SQLType.UNKNOWN;\n                    }\n\n                    pos = index + 2;\n                    ch = charAt(pos);\n                    continue;\n                } else if (pos + 2 < text.length()\n                        && text.charAt(pos + 1) == ' '\n                        && text.charAt(pos + 2) == '*'\n                        && dialectFeatureEnabled(ScanSQLTypeBlockComment)\n                ) {\n                    int index = text.indexOf(\"* /\", pos + 3);\n                    if (index == -1) {\n                        return SQLType.UNKNOWN;\n                    }\n\n                    pos = index + 3;\n                    ch = charAt(pos);\n                    continue;\n                }\n            }\n\n            if (dialectFeatureEnabled(ScanSQLTypeWithSemi)) {\n                while (ch == ';') {\n                    ch = charAt(++pos);\n\n                    if (isEOF()) {\n                        return SQLType.EMPTY;\n                    }\n\n                    while (isWhitespace(ch)) {\n                        ch = charAt(++pos);\n                    }\n                    continue _loop;\n                }\n            }\n\n            if (pos + 1 < text.length()\n                    && ((ch == '-' && text.charAt(pos + 1) == '-') || (ch == '—' && text.charAt(pos + 1) == '—'))) {\n                int index = text.indexOf('\\n', pos + 2);\n                if (index == -1) {\n                    reset(0);\n                    nextToken();\n                    if (token == EOF) {\n                        return SQLType.EMPTY;\n                    }\n\n                    return SQLType.UNKNOWN;\n                }\n\n                pos = index + 1;\n                ch = charAt(pos);\n                continue;\n            }\n\n            break;\n        }\n\n        while (ch == '(') {\n            ch = charAt(++pos);\n\n            while (isWhitespace(ch)) {\n                ch = charAt(++pos);\n            }\n        }\n\n        long hashCode = FnvHash.BASIC;\n        for (; ; ) {\n            char c;\n            if (ch >= 'a' && ch <= 'z') {\n                c = ch;\n            } else if (ch >= 'A' && ch <= 'Z') {\n                c = (char) (ch + 32);\n            } else {\n                break;\n            }\n            hashCode ^= c;\n            hashCode *= FnvHash.PRIME;\n\n            ch = charAt(++pos);\n        }\n\n        if (ch == '_' || (ch >= '0' && ch <= '9')) {\n            return SQLType.UNKNOWN;\n        }\n\n        if (hashCode == FnvHash.Constants.SELECT) {\n            return SQLType.SELECT;\n        } else if (hashCode == FnvHash.Constants.INSERT) {\n            return SQLType.INSERT;\n        } else if (hashCode == FnvHash.Constants.DELETE) {\n            return SQLType.DELETE;\n        } else if (hashCode == FnvHash.Constants.UPDATE) {\n            return SQLType.UPDATE;\n        } else if (hashCode == FnvHash.Constants.REPLACE) {\n            return SQLType.REPLACE;\n        } else if (hashCode == FnvHash.Constants.TRUNCATE) {\n            return SQLType.TRUNCATE;\n        } else if (hashCode == FnvHash.Constants.MERGE) {\n            return SQLType.MERGE;\n        } else if (hashCode == FnvHash.Constants.CREATE) {\n            return SQLType.CREATE;\n        } else if (hashCode == FnvHash.Constants.ALTER) {\n            return SQLType.ALTER;\n        } else if (hashCode == FnvHash.Constants.SHOW) {\n            nextToken();\n            if (identifierEquals(FnvHash.Constants.STATISTIC)) {\n                return SQLType.SHOW_STATISTIC;\n            } else if (identifierEquals(FnvHash.Constants.STATISTIC_LIST)) {\n                return SQLType.SHOW_STATISTIC_LIST;\n            } else if (identifierEquals(FnvHash.Constants.TABLES) || identifierEquals(\"TABLES；\")) {\n                return SQLType.SHOW_TABLES;\n            } else if (identifierEquals(FnvHash.Constants.PARTITIONS)) {\n                return SQLType.SHOW_PARTITIONS;\n            } else if (identifierEquals(FnvHash.Constants.CATALOGS)) {\n                return SQLType.SHOW_CATALOGS;\n            } else if (identifierEquals(FnvHash.Constants.FUNCTIONS)) {\n                return SQLType.SHOW_FUNCTIONS;\n            } else if (identifierEquals(FnvHash.Constants.ROLES)) {\n                return SQLType.SHOW_ROLES;\n            } else if (identifierEquals(FnvHash.Constants.ROLE)) {\n                return SQLType.SHOW_ROLE;\n            } else if (identifierEquals(FnvHash.Constants.LABEL)) {\n                return SQLType.SHOW_LABEL;\n            } else if (identifierEquals(FnvHash.Constants.GRANTS)) {\n                return SQLType.SHOW_GRANTS;\n            } else if (identifierEquals(FnvHash.Constants.GRANT)\n                    || token == GRANT\n            ) {\n                return SQLType.SHOW_GRANT;\n            } else if (identifierEquals(FnvHash.Constants.RECYCLEBIN)) {\n                return SQLType.SHOW_RECYCLEBIN;\n            } else if (identifierEquals(\"VARIABLES\")) {\n                return SQLType.SHOW_VARIABLES;\n            } else if (identifierEquals(\"HISTORY\")) {\n                return SQLType.SHOW_HISTORY;\n            } else if (identifierEquals(\"PACKAGES\")) {\n                return SQLType.SHOW_PACKAGES;\n            } else if (identifierEquals(\"PACKAGE\")) {\n                return SQLType.SHOW_PACKAGE;\n            } else if (identifierEquals(\"CHANGELOGS\")) {\n                return SQLType.SHOW_CHANGELOGS;\n            } else if (identifierEquals(\"ACL\")) {\n                return SQLType.SHOW_ACL;\n            } else if (token == CREATE) {\n                nextToken();\n                if (token == TABLE) {\n                    return SQLType.SHOW_CREATE_TABLE;\n                }\n            }\n            return SQLType.SHOW;\n        } else if (hashCode == FnvHash.Constants.DESC) {\n            return SQLType.DESC;\n        } else if (hashCode == FnvHash.Constants.DESCRIBE) {\n            return SQLType.DESC;\n        } else if (hashCode == FnvHash.Constants.SET) {\n            nextToken();\n            if (identifierEquals(FnvHash.Constants.LABEL)) {\n                return SQLType.SET_LABEL;\n            } else if (identifierEquals(\"PROJECT\")) {\n                return SQLType.SET_PROJECT;\n            }\n            return SQLType.SET;\n        } else if (hashCode == FnvHash.Constants.SETPROJECT) {\n            return SQLType.SET_PROJECT;\n        } else if (hashCode == FnvHash.Constants.KILL) {\n            return SQLType.KILL;\n        } else if (hashCode == FnvHash.Constants.MSCK) {\n            return SQLType.MSCK;\n        } else if (hashCode == FnvHash.Constants.USE) {\n            return SQLType.USE;\n        } else if (hashCode == FnvHash.Constants.DROP) {\n            return SQLType.DROP;\n        } else if (hashCode == FnvHash.Constants.LIST) {\n            nextToken();\n            if (identifierEquals(FnvHash.Constants.USERS)) {\n                return SQLType.LIST_USERS;\n            } else if (identifierEquals(FnvHash.Constants.TABLES)) {\n                return SQLType.LIST_TABLES;\n            } else if (identifierEquals(FnvHash.Constants.ROLES)) {\n                return SQLType.LIST_ROLES;\n            } else if (identifierEquals(FnvHash.Constants.TEMPORARY)) {\n                return SQLType.LIST_TEMPORARY_OUTPUT;\n            } else if (identifierEquals(\"TENANT\")) {\n                nextToken();\n                if (identifierEquals(FnvHash.Constants.ROLES)) {\n                    return SQLType.LIST_TENANT_ROLES;\n                }\n            } else if (identifierEquals(\"TRUSTEDPROJECTS\")) {\n                return SQLType.LIST_TRUSTEDPROJECTS;\n            } else if (identifierEquals(\"ACCOUNTPROVIDERS\")) {\n                return SQLType.LIST_ACCOUNTPROVIDERS;\n            }\n            return SQLType.LIST;\n        } else if (hashCode == FnvHash.Constants.ROLLBACK) {\n            return SQLType.ROLLBACK;\n        } else if (hashCode == FnvHash.Constants.COMMIT) {\n            return SQLType.COMMIT;\n        } else if (hashCode == FnvHash.Constants.WHO) {\n            return SQLType.WHO;\n        } else if (hashCode == FnvHash.Constants.GRANT) {\n            return SQLType.GRANT;\n        } else if (hashCode == FnvHash.Constants.REVOKE) {\n            return SQLType.REVOKE;\n        } else if (hashCode == FnvHash.Constants.ANALYZE) {\n            return SQLType.ANALYZE;\n        } else if (hashCode == FnvHash.Constants.EXPLAIN) {\n            return SQLType.EXPLAIN;\n        } else if (hashCode == FnvHash.Constants.READ) {\n            return SQLType.READ;\n        } else if (hashCode == FnvHash.Constants.WITH) {\n            return SQLType.WITH;\n        } else if (hashCode == FnvHash.Constants.DUMP) {\n            nextToken();\n            if (identifierEquals(FnvHash.Constants.DATA)) {\n                return SQLType.DUMP_DATA;\n            }\n        } else if (hashCode == FnvHash.Constants.ADD) {\n            nextToken();\n            if (token == Token.USER || identifierEquals(FnvHash.Constants.USER)) {\n                return SQLType.ADD_USER;\n            } else if (token == TABLE) {\n                return SQLType.ADD_TABLE;\n            } else if (token == FUNCTION) {\n                return SQLType.ADD_FUNCTION;\n            } else if (identifierEquals(FnvHash.Constants.STATISTIC)) {\n                return SQLType.ADD_STATISTIC;\n            } else if (identifierEquals(FnvHash.Constants.RESOURCE)) {\n                return SQLType.ADD_RESOURCE;\n            } else if (identifierEquals(\"VOLUME\")) {\n                return SQLType.ADD_VOLUME;\n            } else if (identifierEquals(\"ACCOUNTPROVIDER\")) {\n                return SQLType.ADD_ACCOUNTPROVIDER;\n            } else if (identifierEquals(\"TRUSTEDPROJECT\")) {\n                return SQLType.ADD_TRUSTEDPROJECT;\n            } else {\n                return SQLType.ADD;\n            }\n        } else if (hashCode == FnvHash.Constants.REMOVE) {\n            nextToken();\n            if (token == Token.USER || identifierEquals(FnvHash.Constants.USER)) {\n                return SQLType.REMOVE_USER;\n            }\n\n            if (identifierEquals(FnvHash.Constants.RESOURCE)) {\n                return SQLType.REMOVE_RESOURCE;\n            }\n            return SQLType.REMOVE;\n        } else if (hashCode == FnvHash.Constants.TUNNEL) {\n            nextToken();\n            if (identifierEquals(FnvHash.Constants.DOWNLOAD)) {\n                return SQLType.TUNNEL_DOWNLOAD;\n            }\n        } else if (hashCode == FnvHash.Constants.UPLOAD) {\n            return SQLType.UPLOAD;\n        } else if (hashCode == FnvHash.Constants.WHOAMI) {\n            return SQLType.WHOAMI;\n        } else if (hashCode == FnvHash.Constants.COUNT) {\n            return SQLType.COUNT;\n        } else if (hashCode == FnvHash.Constants.CLONE) {\n            return SQLType.CLONE;\n        } else if (hashCode == FnvHash.Constants.LOAD) {\n            return SQLType.LOAD;\n        } else if (hashCode == FnvHash.Constants.INSTALL) {\n            return SQLType.INSTALL;\n        } else if (hashCode == FnvHash.Constants.UNLOAD) {\n            return SQLType.UNLOAD;\n        } else if (hashCode == FnvHash.Constants.ALLOW) {\n            return SQLType.ALLOW;\n        } else if (hashCode == FnvHash.Constants.PURGE) {\n            return SQLType.PURGE;\n        } else if (hashCode == FnvHash.Constants.RESTORE) {\n            return SQLType.RESTORE;\n        } else if (hashCode == FnvHash.Constants.EXSTORE) {\n            return SQLType.EXSTORE;\n        } else if (hashCode == FnvHash.Constants.UNDO) {\n            return SQLType.UNDO;\n        } else if (hashCode == FnvHash.Constants.REMOVE) {\n            return SQLType.REMOVE;\n        } else if (hashCode == FnvHash.Constants.FROM && dialectFeatureEnabled(ScanSQLTypeWithFrom)) {\n            return SQLType.INSERT_MULTI;\n        } else if (hashCode == FnvHash.Constants.ADD) {\n            return SQLType.ADD;\n        } else if (hashCode == FnvHash.Constants.IF) {\n            return SQLType.SCRIPT;\n        } else if (hashCode == FnvHash.Constants.FUNCTION && dialectFeatureEnabled(ScanSQLTypeWithFunction)) {\n            return SQLType.SCRIPT;\n        } else if (hashCode == FnvHash.Constants.BEGIN && dialectFeatureEnabled(ScanSQLTypeWithBegin)) {\n            return SQLType.SCRIPT;\n        } else if (ch == '@') {\n            nextToken();\n            if (token == VARIANT && dialectFeatureEnabled(ScanSQLTypeWithAt)) {\n                nextToken();\n\n                if (token == TABLE) {\n                    return SQLType.SCRIPT;\n                }\n\n                // datatype\n                if (token == IDENTIFIER) {\n                    nextToken();\n                }\n\n                if (token == COLONEQ || token == SEMI) {\n                    return SQLType.SCRIPT;\n                }\n            }\n        }\n\n        if (ch == EOI) {\n            return SQLType.EMPTY;\n        }\n        return SQLType.UNKNOWN;\n    }\n\n    public final SQLType scanSQLTypeV2() {\n        SQLType sqlType = scanSQLType();\n        if (sqlType == SQLType.CREATE) {\n            nextToken();\n            if (token == Token.USER || identifierEquals(FnvHash.Constants.USER)) {\n                return SQLType.CREATE_USER;\n            }\n\n            _for:\n            for (int i = 0; i < 1000; ++i) {\n                switch (token) {\n                    case EOF:\n                    case ERROR:\n                        break _for;\n                    case TABLE:\n                        sqlType = SQLType.CREATE_TABLE;\n                        break;\n                    case VIEW:\n                        if (sqlType == SQLType.CREATE) {\n                            sqlType = SQLType.CREATE_VIEW;\n                            break _for;\n                        }\n                        break;\n                    case FUNCTION:\n                        if (sqlType == SQLType.CREATE) {\n                            sqlType = SQLType.CREATE_FUNCTION;\n                            break _for;\n                        }\n                        break;\n                    case SELECT:\n                        if (sqlType == SQLType.CREATE_TABLE) {\n                            sqlType = SQLType.CREATE_TABLE_AS_SELECT;\n                            break _for;\n                        }\n                        break;\n                    default:\n                        if (sqlType == SQLType.CREATE && identifierEquals(FnvHash.Constants.ROLE)) {\n                            sqlType = SQLType.CREATE_ROLE;\n                            break _for;\n                        }\n                        if (sqlType == SQLType.CREATE && identifierEquals(FnvHash.Constants.PACKAGE)) {\n                            sqlType = SQLType.CREATE_PACKAGE;\n                            break _for;\n                        }\n                        break;\n                }\n\n                nextToken();\n            }\n        } else if (sqlType == SQLType.DROP) {\n            nextToken();\n            if (token == Token.USER || identifierEquals(FnvHash.Constants.USER)) {\n                return SQLType.DROP_USER;\n            } else if (token == TABLE) {\n                return SQLType.DROP_TABLE;\n            } else if (token == VIEW) {\n                return SQLType.DROP_VIEW;\n            } else if (token == FUNCTION) {\n                return SQLType.DROP_FUNCTION;\n            } else if (identifierEquals(FnvHash.Constants.ROLE)) {\n                return SQLType.DROP_ROLE;\n            } else if (identifierEquals(FnvHash.Constants.RESOURCE)) {\n                return SQLType.DROP_RESOURCE;\n            } else if (identifierEquals(FnvHash.Constants.MATERIALIZED)) {\n                nextToken();\n                if (token == VIEW) {\n                    return SQLType.DROP_MATERIALIZED_VIEW;\n                }\n            }\n        } else if (sqlType == SQLType.ALTER) {\n            nextToken();\n            if (token == Token.USER || identifierEquals(FnvHash.Constants.USER)) {\n                return SQLType.ALTER_USER;\n            } else if (token == TABLE) {\n                return SQLType.ALTER_TABLE;\n            } else if (token == VIEW) {\n                return SQLType.ALTER_VIEW;\n            }\n        } else if (sqlType == SQLType.INSERT) {\n            nextToken();\n            boolean overwrite = token == OVERWRITE;\n            for (int i = 0; i < 1000; ++i) {\n                nextToken();\n\n                if (token == SELECT) {\n                    return overwrite\n                            ? SQLType.INSERT_OVERWRITE_SELECT\n                            : SQLType.INSERT_INTO_SELECT;\n                } else if (token == VALUES) {\n                    return overwrite ? SQLType.INSERT_OVERWRITE_VALUES : SQLType.INSERT_INTO_VALUES;\n                } else if (token == ERROR || token == EOF) {\n                    if (overwrite) {\n                        sqlType = SQLType.INSERT_OVERWRITE;\n                    }\n                    break;\n                }\n            }\n            return sqlType;\n        }\n\n        return sqlType;\n    }\n\n    public final void nextTokenAlias() {\n        startPos = pos;\n        bufPos = 0;\n        while (isWhitespace(ch)) {\n            if (ch == '\\n') {\n                line++;\n            }\n\n            ch = charAt(++pos);\n            startPos = pos;\n            continue;\n        }\n\n        if (ch == '\"') {\n            scanAlias();\n        } else if (ch == '\\'') {\n            scanAlias();\n\n            int p;\n            if (stringVal.length() > 1\n                    && stringVal.indexOf('\"') == -1\n                    && ((p = stringVal.indexOf('\\'', 1)) == -1 || p == stringVal.length() - 1)\n            ) {\n                char[] chars = stringVal.toCharArray();\n                chars[0] = '\"';\n                chars[chars.length - 1] = '\"';\n                stringVal = new String(chars);\n            }\n            token = LITERAL_ALIAS;\n        } else {\n            nextToken();\n        }\n    }\n\n    public final void nextPath() {\n        while (isWhitespace(ch)) {\n            ch = charAt(++pos);\n        }\n        stringVal = null;\n        mark = pos;\n        while (!isWhitespace(ch) && ch != ';' && pos < text.length()) {\n            ch = charAt(++pos);\n        }\n        bufPos = pos - mark;\n\n        if (ch != ';') {\n            ch = charAt(++pos);\n        }\n\n        token = LITERAL_PATH;\n    }\n\n    public final void nextTokenForSet() {\n        while (isWhitespace(ch)) {\n            ch = charAt(++pos);\n        }\n\n        char first = ch;\n        if (first == '$') {\n            scanVariable();\n            return;\n        }\n\n        if (isFirstIdentifierChar(first) || (first >= '0' && first <= '9') || first == '{') {\n            stringVal = null;\n            mark = pos;\n            while (ch != ';' && ch != EOI) {\n                ch = charAt(++pos);\n            }\n\n            bufPos = pos - mark;\n\n            stringVal = this.subString(mark, bufPos);\n            token = IDENTIFIER;\n            return;\n        }\n\n        nextToken();\n    }\n\n    public final boolean skipToNextLine(int startPosition) {\n        for (int i = 0; ; ++i) {\n            int pos = startPosition + i;\n            char ch = charAt(pos);\n            if (ch == '\\n') {\n                this.pos = pos;\n                this.ch = charAt(this.pos);\n                return true;\n            }\n\n            if (ch == EOI) {\n                this.pos = pos;\n                break;\n            }\n        }\n\n        return false;\n    }\n\n    public final boolean skipToNextLineOrParameter(int startPosition) {\n        for (int i = 0; ; ++i) {\n            int pos = startPosition + i;\n            char ch = charAt(pos);\n            if (ch == '\\n') {\n                this.pos = pos;\n                this.ch = charAt(this.pos);\n                return true;\n            }\n            if (ch == '$' && charAt(pos + 1) == '{') {\n                this.pos = pos;\n                this.ch = charAt(this.pos);\n                return true;\n            }\n\n            if (ch == EOI) {\n                this.pos = pos;\n                break;\n            }\n        }\n\n        return false;\n    }\n\n    protected void nextTokenQues() {\n        token = Token.QUES;\n    }\n\n    public final void nextToken() {\n        startPos = pos;\n        bufPos = 0;\n        if (comments != null && comments.size() > 0) {\n            comments = null;\n        }\n\n        this.lines = 0;\n        int startLine = line;\n\n        for (; ; ) {\n            if (isWhitespace(ch)) {\n                if (ch == '\\n') {\n                    line++;\n\n                    lines = line - startLine;\n                }\n\n                ch = charAt(++pos);\n                startPos = pos;\n                continue;\n            }\n\n            if (ch == EOI && pos < text.length()) {\n                ch = charAt(++pos);\n                continue;\n            }\n\n            if (ch == '$') {\n                scanVariable();\n                return;\n            }\n\n            if (isFirstIdentifierChar(ch)) {\n                if (ch == '（') {\n                    scanChar();\n                    token = LPAREN;\n                    return;\n                } else if (ch == '）') {\n                    scanChar();\n                    token = RPAREN;\n                    return;\n                }\n\n                if (ch == 'N' || ch == 'n') {\n                    if (charAt(pos + 1) == '\\'') {\n                        ++pos;\n                        ch = '\\'';\n                        scanString();\n                        token = Token.LITERAL_NCHARS;\n                        return;\n                    }\n                }\n\n                if (ch == '—' && charAt(pos + 1) == '—' && charAt(pos + 2) == '\\n') {\n                    pos += 3;\n                    ch = charAt(pos);\n                    continue;\n                }\n\n                scanIdentifier();\n                return;\n            }\n\n            switch (ch) {\n                case '0':\n                    if (charAt(pos + 1) == 'x') {\n                        scanChar();\n                        scanChar();\n                        scanHexaDecimal();\n                    } else {\n                        scanNumber();\n                    }\n                    return;\n                case '1':\n                case '2':\n                case '3':\n                case '4':\n                case '5':\n                case '6':\n                case '7':\n                case '8':\n                case '9':\n                    scanNumber();\n                    return;\n                case ',':\n                case '，':\n                    scanChar();\n                    token = COMMA;\n                    return;\n                case '(':\n                case '（':\n                    scanChar();\n                    token = LPAREN;\n                    return;\n                case ')':\n                case '）':\n                    scanChar();\n                    token = RPAREN;\n                    return;\n                case '[':\n                    scanLBracket();\n                    return;\n                case ']':\n                    scanChar();\n                    token = RBRACKET;\n                    return;\n                case '{':\n                    scanChar();\n                    token = LBRACE;\n                    return;\n                case '}':\n                    scanChar();\n                    token = RBRACE;\n                    return;\n                case ':':\n                    scanChar();\n                    if (ch == '=') {\n                        scanChar();\n                        token = COLONEQ;\n                    } else if (ch == ':') {\n                        scanChar();\n                        token = COLONCOLON;\n                    } else {\n                        if (isEnabled(SQLParserFeature.TDDLHint) || dialectFeatureEnabled(NextTokenColon)) {\n                            token = COLON;\n                            return;\n                        }\n                        unscan();\n                        scanVariable();\n                    }\n                    return;\n                case '#':\n                    scanSharp();\n                    if ((token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT) && skipComment) {\n                        bufPos = 0;\n                        continue;\n                    }\n                    return;\n                case '.':\n                    scanChar();\n                    if (isDigit(ch)\n                            && (pos == 1 || token != IDENTIFIER)\n                    ) {\n                        unscan();\n                        scanNumber();\n                        return;\n                    } else if (ch == '.') {\n                        scanChar();\n                        if (ch == '.') {\n                            scanChar();\n                            token = Token.DOTDOTDOT;\n                        } else {\n                            token = Token.DOTDOT;\n                        }\n                    } else {\n                        token = Token.DOT;\n                    }\n                    return;\n                case '\\'':\n                    scanString();\n                    return;\n                case '\\\"':\n                    scanAlias();\n                    return;\n                case '*':\n                    scanChar();\n                    token = Token.STAR;\n                    return;\n                case '?':\n                    scanChar();\n                    nextTokenQues();\n                    return;\n                case ';':\n                    scanChar();\n                    token = Token.SEMI;\n                    return;\n                case '`':\n                    throw new ParserException(\"backtick quote is not supported for current dialect. \" + info());\n                case '@':\n                    scanVariable_at();\n                    return;\n                case '-':\n                    char next = charAt(pos + 1);\n                    if (next == '-') {\n                        scanComment();\n                        if ((token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT) && skipComment) {\n                            bufPos = 0;\n                            continue;\n                        }\n                    } else if (next >= '0' && next <= '9') {\n                        if (token == null) {\n                            scanNumber();\n                            return;\n                        }\n                        switch (token) {\n                            case COMMA:\n                            case LPAREN:\n                            case WITH:\n                            case BY:\n                                scanNumber();\n                                break;\n                            default:\n                                scanOperator();\n                                break;\n                        }\n                    } else {\n                        scanOperator();\n                    }\n                    return;\n                case '/':\n                    char nextChar = charAt(pos + 1);\n                    if (nextChar == '/'\n                            || nextChar == '*'\n                            || (nextChar == '!' && isEnabled(SQLParserFeature.TDDLHint))) {\n                        scanComment();\n                        if ((token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT) && skipComment) {\n                            bufPos = 0;\n                            continue;\n                        }\n                    } else if (nextChar == ' ' && charAt(pos + 2) == '*') {\n                        scanComment();\n                        if ((token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT) && skipComment) {\n                            bufPos = 0;\n                            continue;\n                        }\n                    } else if (nextChar == ' ' && charAt(pos + 2) == ' ' && charAt(pos + 3) == '*') {\n                        scanComment();\n                        if ((token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT) && skipComment) {\n                            bufPos = 0;\n                            continue;\n                        }\n                    } else {\n                        token = Token.SLASH;\n                        scanChar();\n                    }\n                    return;\n                default:\n                    if (Character.isLetter(ch)) {\n                        scanIdentifier();\n                        return;\n                    }\n\n                    if (isOperator(ch)) {\n                        scanOperator();\n                        return;\n                    }\n\n                    if (ch == '\\\\' && charAt(pos + 1) == 'N'\n                            && dialectFeatureEnabled(NextTokenPrefixN)) {\n                        scanChar();\n                        scanChar();\n                        token = Token.NULL;\n                        return;\n                    }\n\n                    // QS_TODO ?\n                    if (isEOF()) { // JLS\n                        token = EOF;\n                    } else {\n                        lexError(\"illegal.char\", String.valueOf((int) ch));\n                        scanChar();\n                    }\n\n                    return;\n            }\n        }\n\n    }\n\n    protected void scanLBracket() {\n        scanChar();\n        token = LBRACKET;\n    }\n\n    private void scanOperator() {\n        switch (ch) {\n            case '+':\n                scanChar();\n                token = Token.PLUS;\n                break;\n            case '-':\n                scanChar();\n                if (ch == '>') {\n                    scanChar();\n                    if (ch == '>') {\n                        scanChar();\n                        token = Token.SUBGTGT;\n                    } else {\n                        token = Token.SUBGT;\n                    }\n                } else {\n                    token = Token.SUB;\n                }\n                break;\n            case '*':\n                scanChar();\n                token = Token.STAR;\n                break;\n            case '/':\n                scanChar();\n                token = Token.SLASH;\n                break;\n            case '&':\n                scanChar();\n                if (ch == '&') {\n                    scanChar();\n                    token = Token.AMPAMP;\n                } else {\n                    token = Token.AMP;\n                }\n                break;\n            case '|':\n                scanChar();\n                if (ch == '|') {\n                    scanChar();\n                    if (ch == '/') {\n                        if (charAt(pos + 1) == '*') {\n                            token = Token.BARBAR;\n                            break;\n                        }\n                        scanChar();\n                        token = Token.BARBARSLASH;\n                    } else {\n                        token = Token.BARBAR;\n                    }\n                } else if (ch == '/') {\n                    scanChar();\n                    token = Token.BARSLASH;\n                } else {\n                    token = Token.BAR;\n                }\n                break;\n            case '^':\n                scanChar();\n                if (ch == '=') {\n                    scanChar();\n                    token = Token.CARETEQ;\n                } else {\n                    token = Token.CARET;\n                }\n                break;\n            case '%':\n                scanChar();\n                token = Token.PERCENT;\n                break;\n            case '=':\n                scanChar();\n                if (ch == ' ') {\n                    scanChar();\n                }\n\n                if (ch == '=') {\n                    scanChar();\n                    token = Token.EQEQ;\n                } else if (ch == '>') {\n                    scanChar();\n                    token = Token.EQGT;\n                } else {\n                    token = Token.EQ;\n                }\n                break;\n            case '>':\n                scanChar();\n                if (ch == '=') {\n                    scanChar();\n                    token = Token.GTEQ;\n                } else if (ch == '>') {\n                    scanChar();\n                    if (ch == '>') {\n                        scanChar();\n                        token = Token.GTGTGT;\n                    } else {\n                        token = Token.GTGT;\n                    }\n                } else {\n                    token = Token.GT;\n                }\n                break;\n            case '<':\n                scanChar();\n                if (ch == '=') {\n                    scanChar();\n                    if (ch == '>') {\n                        token = Token.LTEQGT;\n                        scanChar();\n                    } else {\n                        token = Token.LTEQ;\n                    }\n                } else if (ch == '>') {\n                    scanChar();\n                    token = Token.LTGT;\n                } else if (ch == '<') {\n                    scanChar();\n\n                    if (ch == '<') {\n                        scanChar();\n                        token = Token.LTLTLT;\n                    } else {\n                        token = Token.LTLT;\n                    }\n                } else if (ch == '@') {\n                    scanChar();\n                    token = Token.LT_MONKEYS_AT;\n                } else if (ch == '-' && charAt(pos + 1) == '>') {\n                    scanChar();\n                    scanChar();\n                    token = Token.LT_SUB_GT;\n                } else {\n                    if (ch == ' ') {\n                        char c1 = charAt(pos + 1);\n                        if (c1 == '=') {\n                            scanChar();\n                            scanChar();\n                            if (ch == '>') {\n                                token = Token.LTEQGT;\n                                scanChar();\n                            } else {\n                                token = Token.LTEQ;\n                            }\n                        } else if (c1 == '>') {\n                            scanChar();\n                            scanChar();\n                            token = Token.LTGT;\n                        } else if (c1 == '<') {\n                            scanChar();\n                            scanChar();\n                            token = Token.LTLT;\n                        } else if (c1 == '@') {\n                            scanChar();\n                            scanChar();\n                            token = Token.LT_MONKEYS_AT;\n                        } else if (c1 == '-' && charAt(pos + 2) == '>') {\n                            scanChar();\n                            scanChar();\n                            scanChar();\n                            token = Token.LT_SUB_GT;\n                        } else {\n                            token = Token.LT;\n                        }\n                    } else {\n                        token = Token.LT;\n                    }\n                }\n                break;\n            case '!':\n                scanChar();\n                while (isWhitespace(ch)) {\n                    scanChar();\n                }\n                if (ch == '=') {\n                    scanChar();\n                    token = Token.BANGEQ;\n                } else if (ch == '>') {\n                    scanChar();\n                    token = Token.BANGGT;\n                } else if (ch == '<') {\n                    scanChar();\n                    token = Token.BANGLT;\n                } else if (ch == '!') {\n                    scanChar();\n                    token = Token.BANGBANG; // postsql\n                } else if (ch == '~') {\n                    scanChar();\n                    if (ch == '*') {\n                        scanChar();\n                        token = Token.BANG_TILDE_STAR; // postsql\n                    } else {\n                        token = Token.BANG_TILDE; // postsql\n                    }\n                } else {\n                    token = Token.BANG;\n                }\n                break;\n            case '?':\n                scanChar();\n                token = Token.QUES;\n                break;\n            case '~':\n                scanChar();\n                if (ch == '*') {\n                    scanChar();\n                    token = Token.TILDE_STAR;\n                } else if (ch == '=') {\n                    scanChar();\n                    token = Token.TILDE_EQ; // postsql\n                } else {\n                    token = Token.TILDE;\n                }\n                break;\n            default:\n                throw new ParserException(\"unexpected character '\" + ch + \"'. \" + info());\n        }\n    }\n\n    protected void scanString() {\n        mark = pos;\n        boolean hasSpecial = false;\n        Token preToken = this.token;\n\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            if (preToken == Token.AS) {\n                stringVal = subString(mark, bufPos + 2);\n            } else {\n                stringVal = subString(mark + 1, bufPos);\n            }\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    protected final void scanString2() {\n        {\n            boolean hasSpecial = false;\n            int startIndex = pos + 1;\n            int endIndex = -1; // text.indexOf('\\'', startIndex);\n            for (int i = startIndex; i < text.length(); ++i) {\n                final char ch = text.charAt(i);\n                if (ch == '\\\\') {\n                    hasSpecial = true;\n                    continue;\n                }\n                if (ch == '\\'') {\n                    endIndex = i;\n                    break;\n                }\n            }\n\n            if (endIndex == -1) {\n                throw new ParserException(\"unclosed str. \" + info());\n            }\n\n            String stringVal;\n            if (token == Token.AS) {\n                stringVal = text.substring(pos, endIndex + 1);\n            } else {\n                if (startIndex == endIndex) {\n                    stringVal = \"\";\n                } else {\n                    stringVal = text.substring(startIndex, endIndex);\n                }\n            }\n            // hasSpecial = stringVal.indexOf('\\\\') != -1;\n\n            if (!hasSpecial) {\n                this.stringVal = stringVal;\n                int pos = endIndex + 1;\n                char ch = charAt(pos);\n                if (ch != '\\'') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = LITERAL_CHARS;\n                    return;\n                }\n            }\n        }\n\n        mark = pos;\n        boolean hasSpecial = false;\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                scanString2PutEscapedChar(ch, true);\n\n                continue;\n            }\n            if (ch == '\\'') {\n                scanChar();\n                if (ch != '\\'') {\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\\'');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    protected final void scanString2_d() {\n        {\n            boolean hasSpecial = false;\n            int startIndex = pos + 1;\n            int endIndex = -1; // text.indexOf('\\'', startIndex);\n            for (int i = startIndex; i < text.length(); ++i) {\n                final char ch = text.charAt(i);\n                if (ch == '\\\\') {\n                    int i1 = i + 1;\n                    if (i1 < text.length()) {\n                        hasSpecial = true;\n                        ++i;\n                        continue;\n                    }\n                }\n\n                if (ch == '\"') {\n                    int i1 = i + 1;\n                    if (i1 < text.length() && text.charAt(i1) == '\"') {\n                        hasSpecial = true;\n                        ++i;\n                        continue;\n                    }\n                    endIndex = i;\n                    break;\n                }\n            }\n\n            if (endIndex == -1) {\n                throw new ParserException(\"unclosed str. \" + info());\n            }\n\n            String stringVal;\n            if (token == Token.AS) {\n                stringVal = subString(pos, endIndex + 1 - pos);\n            } else {\n                if (charAt(endIndex + 1) == '.') {\n                    stringVal = subString(startIndex - 1, (endIndex - startIndex) + 2);\n                } else {\n                    stringVal = subString(startIndex, endIndex - startIndex);\n                }\n            }\n            // hasSpecial = stringVal.indexOf('\\\\') != -1;\n\n            if (!hasSpecial) {\n                this.stringVal = stringVal;\n                int pos = endIndex + 1;\n                char ch = charAt(pos);\n                if (ch == '.') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = Token.IDENTIFIER;\n                    return;\n                }\n\n                if (ch != '\\'') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = LITERAL_CHARS;\n                    return;\n                }\n            }\n        }\n\n        mark = pos;\n        boolean hasSpecial = false;\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n                if (!hasSpecial) {\n                    initBuff(bufPos);\n                    arraycopy(mark + 1, buf, 0, bufPos);\n                    hasSpecial = true;\n                }\n\n                scanString2PutEscapedChar(ch, false);\n\n                continue;\n            }\n            if (ch == '\"') {\n                scanChar();\n                if (ch != '\"') {\n                    if (buf != null && bufPos > 0) {\n                        stringVal = new String(buf, 0, bufPos);\n                    }\n                    token = LITERAL_CHARS;\n                    break;\n                } else {\n                    if (!hasSpecial) {\n                        initBuff(bufPos);\n                        arraycopy(mark + 1, buf, 0, bufPos);\n                        hasSpecial = true;\n                    }\n                    putChar('\"');\n                    continue;\n                }\n            }\n\n            if (!hasSpecial) {\n                bufPos++;\n                continue;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        if (!hasSpecial) {\n            stringVal = subString(mark + 1, bufPos);\n        } else {\n            stringVal = new String(buf, 0, bufPos);\n        }\n    }\n\n    private void scanString2PutEscapedChar(char escaped, boolean supportUnicodeCodePoint) {\n        switch (escaped) {\n            case '0':\n                putChar('\\0');\n                return;\n            case '\\'':\n                putChar('\\'');\n                return;\n            case '\"':\n                putChar('\"');\n                return;\n            case 'b':\n                putChar('\\b');\n                return;\n            case 'n':\n                putChar('\\n');\n                return;\n            case 'r':\n                putChar('\\r');\n                return;\n            case 't':\n                putChar('\\t');\n                return;\n            case '\\\\':\n                putChar('\\\\');\n                return;\n            case 'Z':\n                putChar((char) 0x1A); // ctrl + Z\n                return;\n            case '%':\n                if (dialectFeatureEnabled(ScanStringDoubleBackslash)) {\n                    putChar('\\\\');\n                }\n                putChar('%');\n                return;\n            case '_':\n                if (dialectFeatureEnabled(ScanStringDoubleBackslash)) {\n                    putChar('\\\\');\n                }\n                putChar('_');\n                return;\n            case 'u':\n                if (supportUnicodeCodePoint\n                        && (features & SQLParserFeature.SupportUnicodeCodePoint.mask) != 0) {\n                    char c1 = charAt(++pos);\n                    char c2 = charAt(++pos);\n                    char c3 = charAt(++pos);\n                    char c4 = charAt(++pos);\n                    if (!CharTypes.isHex(c1) || !CharTypes.isHex(c2) || !CharTypes.isHex(c3) || !CharTypes.isHex(c4)) {\n                        throw new ParserException(\"invalid unicode escape sequence '\\\\u\"\n                                + c1 + c2 + c3 + c4 + \"', expected 4 hex digits. \" + info());\n                    }\n                    int intVal = Integer.parseInt(new String(new char[]{c1, c2, c3, c4}), 16);\n                    putChar((char) intVal);\n                    return;\n                }\n                putChar(escaped);\n                return;\n            default:\n                putChar(escaped);\n        }\n    }\n\n    protected void scanAlias() {\n        final char quote = ch;\n        {\n            boolean hasSpecial = false;\n            int startIndex = pos + 1;\n            int endIndex = -1; // text.indexOf('\\'', startIndex);\n            for (int i = startIndex; i < text.length(); ++i) {\n                final char ch = text.charAt(i);\n                if (ch == '\\\\') {\n                    hasSpecial = true;\n                    i++;\n                    continue;\n                }\n                if (ch == quote) {\n                    if (i + 1 < text.length()) {\n                        char ch_next = charAt(i + 1);\n                        if (ch_next == quote) {\n                            hasSpecial = true;\n                            i++;\n                            continue;\n                        }\n                    }\n\n                    endIndex = i;\n                    break;\n                }\n            }\n\n            if (endIndex == -1) {\n                throw new ParserException(\"unclosed str. \" + info());\n            }\n\n            String stringVal = subString(pos, endIndex + 1 - pos);\n            // hasSpecial = stringVal.indexOf('\\\\') != -1;\n\n            if (!hasSpecial) {\n                this.stringVal = stringVal;\n                int pos = endIndex + 1;\n                char ch = charAt(pos);\n                if (ch != '\\'') {\n                    this.pos = pos;\n                    this.ch = ch;\n                    token = LITERAL_ALIAS;\n                    return;\n                }\n            }\n        }\n\n        mark = pos;\n        initBuff(bufPos);\n        //putChar(ch);\n\n        putChar(ch);\n        for (; ; ) {\n            if (isEOF()) {\n                lexError(\"unclosed.str.lit\");\n                return;\n            }\n\n            ch = charAt(++pos);\n\n            if (ch == '\\\\') {\n                scanChar();\n\n                switch (ch) {\n                    case '0':\n                        putChar('\\0');\n                        break;\n                    case '\\'':\n                        if (ch == quote) {\n                            putChar('\\\\');\n                        }\n                        putChar('\\'');\n                        break;\n                    case '\"':\n                        if (ch == quote) {\n                            putChar('\\\\');\n                        }\n                        putChar('\"');\n                        break;\n                    case 'b':\n                        putChar('\\b');\n                        break;\n                    case 'n':\n                        putChar('\\n');\n                        break;\n                    case 'r':\n                        putChar('\\r');\n                        break;\n                    case 't':\n                        putChar('\\t');\n                        break;\n                    case '\\\\':\n                        putChar('\\\\');\n                        putChar('\\\\');\n                        break;\n                    case 'Z':\n                        putChar((char) 0x1A); // ctrl + Z\n                        break;\n                    case 'u':\n                        if (dialectFeatureEnabled(ScanAliasU)) {\n                            if (pos + 4 < text.length()) {\n                                char c1 = charAt(++pos);\n                                char c2 = charAt(++pos);\n                                char c3 = charAt(++pos);\n                                char c4 = charAt(++pos);\n                                if (!CharTypes.isHex(c1) || !CharTypes.isHex(c2) || !CharTypes.isHex(c3) || !CharTypes.isHex(c4)) {\n                                    throw new ParserException(\"invalid unicode escape sequence '\\\\u\"\n                                            + c1 + c2 + c3 + c4 + \"', expected 4 hex digits. \" + info());\n                                }\n                                int intVal = Integer.parseInt(new String(new char[]{c1, c2, c3, c4}), 16);\n                                putChar((char) intVal);\n                            } else {\n                                throw new ParserException(\"unclosed unicode escape sequence. \" + info());\n                            }\n                        } else {\n                            putChar(ch);\n                        }\n                        break;\n                    default:\n                        putChar(ch);\n                        break;\n                }\n\n                continue;\n            }\n\n            if (ch == quote) {\n                char ch_next = charAt(pos + 1);\n\n                if (ch_next == quote) {\n                    putChar('\\\\');\n                    putChar(ch);\n                    scanChar();\n                    continue;\n                }\n\n                putChar(ch);\n                scanChar();\n                token = LITERAL_ALIAS;\n                break;\n            }\n\n            if (bufPos == buf.length) {\n                putChar(ch);\n            } else {\n                buf[bufPos++] = ch;\n            }\n        }\n\n        stringVal = new String(buf, 0, bufPos);\n    }\n\n    public void scanSharp() {\n        scanVariable();\n    }\n\n    public void scanVariable() {\n        if (ch != ':' && ch != '#' && ch != '$' && !(ch == '@' && dialectFeatureEnabled(ScanVariableAt))) {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n        mark = pos;\n        bufPos = 1;\n        char ch;\n\n        final char c1 = charAt(pos + 1);\n        if (c1 == '>' && dialectFeatureEnabled(ScanVariableGreaterThan)) {\n            pos += 2;\n            token = Token.MONKEYS_AT_GT;\n            this.ch = charAt(++pos);\n            return;\n        } else if (c1 == '{') {\n            pos++;\n            bufPos++;\n\n            boolean ident = false;\n            for (; ; ) {\n                ch = charAt(++pos);\n                if (isEOF() || ch == ';' || ch == '；' || ch == '\\r' || ch == '\\n') {\n                    pos--;\n                    bufPos--;\n                    break;\n                }\n\n                if (ch == '}' && !ident) {\n                    if (isIdentifierChar(charAt(pos + 1))) {\n                        bufPos++;\n                        ident = true;\n                        continue;\n                    }\n                    break;\n                }\n\n                if (ident && ch == '$') {\n                    if (charAt(pos + 1) == '{') {\n                        bufPos++;\n                        ident = false;\n                        continue;\n                    }\n                }\n\n                if (ident) {\n                    if (isWhitespace(ch)) {\n                        pos--;\n                        break;\n                    } else if (ch == ',' || ch == ')' || ch == '(') {\n                        pos--;\n                        break;\n                    }\n                }\n\n                bufPos++;\n            }\n\n            if (ch != '}' && !ident) {\n                throw new ParserException(\"syntax error. \" + info());\n            }\n            ++pos;\n            bufPos++;\n\n            char endChar = ch;\n            this.ch = charAt(pos);\n\n            if (dialectFeatureEnabled(ScanVariableMoveToSemi) && !isWhitespace(endChar)) {\n                while (isIdentifierChar(this.ch) && ch != ';' && ch != '；') {\n                    ++pos;\n                    bufPos++;\n                    this.ch = charAt(pos);\n                }\n            }\n\n            stringVal = addSymbol();\n            token = ident ? IDENTIFIER : Token.VARIANT;\n            return;\n        } else if (c1 == '$' && charAt(pos + 2) == '{') {\n            pos += 2;\n            bufPos += 2;\n\n            for (; ; ) {\n                ch = charAt(++pos);\n\n                if (ch == '}') {\n                    break;\n                }\n\n                bufPos++;\n                continue;\n            }\n\n            if (ch != '}') {\n                throw new ParserException(\"syntax error. \" + info());\n            }\n            ++pos;\n            bufPos++;\n\n            this.ch = charAt(pos);\n\n            if (dialectFeatureEnabled(ScanVariableSkipIdentifiers)) {\n                while (isIdentifierChar(this.ch)) {\n                    ++pos;\n                    bufPos++;\n                    this.ch = charAt(pos);\n                }\n            }\n\n            stringVal = addSymbol();\n            token = Token.VARIANT;\n            return;\n        }\n\n        for (; ; ) {\n            ch = charAt(++pos);\n\n            if (!isIdentifierChar(ch)) {\n                break;\n            }\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = addSymbol();\n\n        token = Token.VARIANT;\n    }\n\n    protected void scanVariable_at() {\n        if (ch != '@') {\n            throw new ParserException(\"illegal variable. \" + info());\n        }\n\n        mark = pos;\n        bufPos = 1;\n        char ch;\n\n        final char c1 = charAt(pos + 1);\n        if (c1 == '@') {\n            ++pos;\n            bufPos++;\n        }\n\n        for (; ; ) {\n            ch = charAt(++pos);\n\n            if (!isIdentifierChar(ch)) {\n                break;\n            }\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        stringVal = addSymbol();\n        token = Token.VARIANT;\n    }\n\n    public void scanComment() {\n        if (!allowComment) {\n            throw new NotAllowCommentException();\n        }\n\n        if ((ch == '/' && charAt(pos + 1) == '/')\n                || (ch == '-' && charAt(pos + 1) == '-')) {\n            scanSingleLineComment();\n        } else if (ch == '/' && charAt(pos + 1) == '*') {\n            scanMultiLineComment();\n        } else {\n            throw new IllegalStateException();\n        }\n    }\n\n    public List<String> scanLineArgument() {\n        List<String> args = new ArrayList<>();\n        while (ch == ' ') {\n            scanChar();\n        }\n\n        int start = pos;\n        for (; ; ) {\n            if (ch == ' '\n                    || ch == '\\r'\n                    || ch == '\\n'\n                    || ch == EOI\n                    || (ch == ';' && (pos >= text.length() - 1 || isWhitespace(text.charAt(pos + 1))))\n            ) {\n                while (pos < text.length() - 1) {\n                    char c1 = text.charAt(pos);\n                    if (c1 == ' ' || c1 == '\\r' || c1 == '\\n' || c1 == '\\t') {\n                        pos++;\n                        continue;\n                    }\n                    break;\n                }\n\n                String arg = text.substring(start, pos);\n                arg = arg.trim();\n                if (arg.length() > 0) {\n                    args.add(arg);\n                }\n                if (ch == ';') {\n                    break;\n                }\n                scanChar();\n                start = pos - 1;\n                if (ch == '\\r' || ch == '\\n' || ch == EOI) {\n                    break;\n                } else {\n                    continue;\n                }\n            }\n\n            scanChar();\n        }\n        if (ch == EOI) {\n            token = EOF;\n        } else if (ch == ';') {\n            token = COMMA;\n        } else {\n            nextToken();\n        }\n        return args;\n    }\n\n    protected void scanMultiLineComment() {\n        Token lastToken = this.token;\n        int depth = 1;\n\n        scanChar();\n        scanChar();\n        mark = pos;\n        bufPos = 0;\n\n        for (; ; ) {\n            if (ch == '/' && charAt(pos + 1) == '*') {\n                scanChar();\n                scanChar();\n                ++depth;\n            }\n\n            if (ch == '*' && charAt(pos + 1) == '/') {\n                int curPos = pos;\n                boolean terminated = true;\n                // If '*/' has leading '--' in the same line, just skip it. For example '-- xxxx */'.\n                while (curPos > 0 && charAt(curPos) != '\\n') {\n                    if (charAt(curPos) == '-' && (curPos + 1) < text.length() && charAt(curPos + 1) == '-') {\n                        terminated = false;\n                    }\n                    curPos--;\n                }\n                if (terminated) {\n                    scanChar();\n                    scanChar();\n                    if (0 == --depth) {\n                        break;\n                    }\n                }\n            }\n\n            // multiline comment结束符错误\n            if (ch == EOI) {\n                throw new ParserException(\"unterminated /* comment. \" + info());\n            }\n            scanChar();\n            bufPos++;\n        }\n\n        stringVal = subString(mark - 2, bufPos + 4);\n        token = Token.MULTI_LINE_COMMENT;\n        commentCount++;\n        if (keepComments) {\n            addComment(stringVal);\n        }\n\n        if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {\n            return;\n        }\n\n        if (!isAllowComment() && !isSafeComment(stringVal)) {\n            throw new NotAllowCommentException();\n        }\n    }\n\n    protected void scanSingleLineComment() {\n        Token lastToken = this.token;\n\n        mark = pos;\n        bufPos = 2;\n\n        scanChar();\n        scanChar();\n\n        for (; ; ) {\n            if (ch == '\\r') {\n                if (charAt(pos + 1) == '\\n') {\n                    line++;\n                    scanChar();\n                    break;\n                }\n                bufPos++;\n                break;\n            }\n\n            if (ch == '\\n') {\n                line++;\n                scanChar();\n                break;\n            }\n\n            if (ch == EOI) {\n                break;\n            }\n\n            scanChar();\n            bufPos++;\n        }\n\n        stringVal = subString(mark, bufPos);\n        token = Token.LINE_COMMENT;\n        commentCount++;\n        if (keepComments) {\n            addComment(stringVal);\n        }\n\n        if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {\n            return;\n        }\n\n        if (!isAllowComment() && !isSafeComment(stringVal)) {\n            throw new NotAllowCommentException();\n        }\n    }\n\n    public void scanIdentifier() {\n        this.hashLCase = 0;\n        this.hash = 0;\n\n        final char first = ch;\n\n        if (ch == '`') {\n            mark = pos;\n            bufPos = 1;\n            char ch;\n\n            int startPos = pos + 1;\n            int quoteIndex = text.indexOf('`', startPos);\n            if (quoteIndex == -1) {\n                throw new ParserException(\"illegal identifier. \" + info());\n            }\n\n            hashLCase = 0xcbf29ce484222325L;\n            hash = 0xcbf29ce484222325L;\n\n            for (int i = startPos; i < quoteIndex; ++i) {\n                ch = text.charAt(i);\n\n                hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n                hashLCase *= 0x100000001b3L;\n\n                hash ^= ch;\n                hash *= 0x100000001b3L;\n            }\n\n            stringVal = MySqlLexer.quoteTable.addSymbol(text, pos, quoteIndex + 1 - pos, hash);\n            //stringVal = text.substring(mark, pos);\n            pos = quoteIndex + 1;\n            this.ch = charAt(pos);\n            token = Token.IDENTIFIER;\n            return;\n        }\n\n        final boolean firstFlag = isFirstIdentifierChar(first);\n        if (!firstFlag) {\n            throw new ParserException(\"illegal identifier. \" + info());\n        }\n\n        hashLCase = 0xcbf29ce484222325L;\n        hash = 0xcbf29ce484222325L;\n\n        hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n        hashLCase *= 0x100000001b3L;\n\n        hash ^= ch;\n        hash *= 0x100000001b3L;\n\n        mark = pos;\n        bufPos = 1;\n        char ch = 0;\n        boolean hasLeftBrace = false;\n        for (; ; ) {\n            char c0 = ch;\n            ch = charAt(++pos);\n\n            if (!isIdentifierChar(ch)) {\n                if (((ch == '（' || ch == '）') && c0 > 256) || ch == '$') {\n                    bufPos++;\n                    continue;\n                } else if (ch == '{' && c0 == '$') {\n                    hasLeftBrace = true;\n                    bufPos++;\n                    continue;\n                } else if (ch == '}' && hasLeftBrace) {\n                    hasLeftBrace = false;\n                    bufPos++;\n                    continue;\n                } else if (ch == '-'\n                        && isIdentifierChar(charAt(pos + 1))\n                        && dialectFeatureEnabled(ScanSubAsIdentifier)) {\n                    hash ^= ch;\n                    hash *= 0x100000001b3L;\n\n                    hashLCase ^= ch;\n                    hashLCase *= 0x100000001b3L;\n\n                    bufPos++;\n                    continue;\n                }\n                break;\n            }\n\n            hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n            hashLCase *= 0x100000001b3L;\n\n            hash ^= ch;\n            hash *= 0x100000001b3L;\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        if (bufPos == 1) {\n            switch (first) {\n                case '（':\n                    token = Token.LPAREN;\n                    return;\n                case '）':\n                    token = Token.RPAREN;\n                    return;\n                default:\n                    break;\n            }\n            token = Token.IDENTIFIER;\n            stringVal = CharTypes.valueOf(first);\n            if (stringVal == null) {\n                stringVal = Character.toString(first);\n            }\n            return;\n        }\n\n        Token tok = keywords.getKeyword(hashLCase);\n        if (tok != null) {\n            token = tok;\n            if (token == Token.IDENTIFIER) {\n                stringVal = SymbolTable.global.addSymbol(text, mark, bufPos, hash);\n            } else {\n                stringVal = null;\n            }\n        } else {\n            token = Token.IDENTIFIER;\n            stringVal = SymbolTable.global.addSymbol(text, mark, bufPos, hash);\n        }\n    }\n\n    protected boolean isFirstIdentifierChar0(char ch) {\n        return CharTypes.letterOrUnderScore(ch);\n    }\n\n    protected void scanIdentifier0() {\n        this.hashLCase = 0;\n        this.hash = 0;\n\n        final char first = ch;\n\n        if (ch == '`') {\n            mark = pos;\n            bufPos = 1;\n            char ch;\n\n            int startPos = pos + 1;\n            int quoteIndex = text.indexOf('`', startPos);\n            if (quoteIndex == -1) {\n                throw new ParserException(\"illegal identifier. \" + info());\n            }\n\n            hashLCase = 0xcbf29ce484222325L;\n            hash = 0xcbf29ce484222325L;\n\n            for (int i = startPos; i < quoteIndex; ++i) {\n                ch = text.charAt(i);\n\n                hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n                hashLCase *= 0x100000001b3L;\n\n                hash ^= ch;\n                hash *= 0x100000001b3L;\n            }\n\n            stringVal = MySqlLexer.quoteTable.addSymbol(text, pos, quoteIndex + 1 - pos, hash);\n            //stringVal = text.substring(mark, pos);\n            pos = quoteIndex + 1;\n            this.ch = charAt(pos);\n            token = Token.IDENTIFIER;\n            return;\n        }\n\n        if (!isFirstIdentifierChar0(first)) {\n            throw new ParserException(\"illegal identifier. \" + info());\n        }\n\n        hashLCase = 0xcbf29ce484222325L;\n        hash = 0xcbf29ce484222325L;\n\n        hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n        hashLCase *= 0x100000001b3L;\n\n        hash ^= ch;\n        hash *= 0x100000001b3L;\n\n        mark = pos;\n        bufPos = 1;\n        char ch = 0;\n        boolean hasLeftBrace = false;\n        for (; ; ) {\n            char c0 = ch;\n            ch = charAt(++pos);\n\n            if (!isIdentifierChar(ch)) {\n                if (((ch == '（' || ch == '）') && c0 > 256) || ch == '$') {\n                    bufPos++;\n                    continue;\n                } else if (ch == '{' && c0 == '$') {\n                    hasLeftBrace = true;\n                    bufPos++;\n                    continue;\n                } else if (ch == '}' && hasLeftBrace) {\n                    hasLeftBrace = false;\n                    bufPos++;\n                    continue;\n                } else if (ch == '-'\n                        && isIdentifierChar(charAt(pos + 1))\n                        && dialectFeatureEnabled(ScanSubAsIdentifier)) {\n                    hash ^= ch;\n                    hash *= 0x100000001b3L;\n\n                    hashLCase ^= ch;\n                    hashLCase *= 0x100000001b3L;\n\n                    bufPos++;\n                    continue;\n                }\n                break;\n            }\n\n            hashLCase ^= ((ch >= 'A' && ch <= 'Z') ? (ch + 32) : ch);\n            hashLCase *= 0x100000001b3L;\n\n            hash ^= ch;\n            hash *= 0x100000001b3L;\n\n            bufPos++;\n            continue;\n        }\n\n        this.ch = charAt(pos);\n\n        if (bufPos == 1) {\n            switch (first) {\n                case '（':\n                    token = Token.LPAREN;\n                    return;\n                case '）':\n                    token = Token.RPAREN;\n                    return;\n                default:\n                    break;\n            }\n            token = Token.IDENTIFIER;\n            stringVal = CharTypes.valueOf(first);\n            if (stringVal == null) {\n                stringVal = Character.toString(first);\n            }\n            return;\n        }\n\n        Token tok = keywords.getKeyword(hashLCase);\n        if (tok != null) {\n            token = tok;\n            if (token == Token.IDENTIFIER) {\n                stringVal = SymbolTable.global.addSymbol(text, mark, bufPos, hash);\n            } else {\n                stringVal = null;\n            }\n        } else {\n            token = Token.IDENTIFIER;\n            stringVal = SymbolTable.global.addSymbol(text, mark, bufPos, hash);\n        }\n    }\n\n    public void scanNumber() {\n        mark = pos;\n        numberSale = 0;\n        numberExp = false;\n        bufPos = 0;\n\n        if (ch == '0' && charAt(pos + 1) == 'b' && dialectFeatureEnabled(ScanNumberPrefixB)) {\n            int i = 2;\n            int mark = pos + 2;\n            for (; ; ++i) {\n                char ch = charAt(pos + i);\n                if (ch == '0' || ch == '1') {\n                    continue;\n                } else if (ch >= '2' && ch <= '9') {\n                    break;\n                } else {\n                    bufPos += i;\n                    pos += i;\n                    stringVal = subString(mark, i - 2);\n                    this.ch = charAt(pos);\n                    token = Token.BITS;\n                    return;\n                }\n            }\n        }\n\n        if (ch == '-') {\n            bufPos++;\n            ch = charAt(++pos);\n        }\n\n        for (; ; ) {\n            if (ch >= '0' && ch <= '9') {\n                bufPos++;\n            } else {\n                break;\n            }\n            ch = charAt(++pos);\n        }\n\n        if (ch == '.') {\n            if (charAt(pos + 1) == '.') {\n                token = Token.LITERAL_INT;\n                return;\n            }\n            bufPos++;\n            ch = charAt(++pos);\n\n            for (numberSale = 0; ; numberSale++) {\n                if (ch >= '0' && ch <= '9') {\n                    bufPos++;\n                } else {\n                    break;\n                }\n                ch = charAt(++pos);\n            }\n\n            numberExp = true;\n        }\n\n        if ((ch == 'e' || ch == 'E')\n                && (isDigit(charAt(pos + 1)) || (isDigit2(charAt(pos + 1)) && isDigit2(charAt(pos + 2))))) {\n            numberExp = true;\n\n            bufPos++;\n            ch = charAt(++pos);\n\n            if (ch == '+' || ch == '-') {\n                bufPos++;\n                ch = charAt(++pos);\n            }\n\n            for (; ; ) {\n                if (ch >= '0' && ch <= '9') {\n                    bufPos++;\n                } else {\n                    break;\n                }\n                ch = charAt(++pos);\n            }\n\n            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {\n                numberExp = false;\n            }\n        } else if (ch == 'd' || ch == 'D') {\n            if (!isIdentifierChar(charAt(pos + 1))) {\n                ch = charAt(++pos);\n                token = Token.LITERAL_FLOAT;\n                return;\n            }\n        }\n\n        if (numberSale > 0 || numberExp) {\n            if (text.charAt(mark) == '.' && isIdentifierChar(ch)) {\n                pos = mark + 1;\n                ch = charAt(pos);\n                token = Token.DOT;\n                return;\n            }\n            token = Token.LITERAL_FLOAT;\n            return;\n        }\n\n        if (ch != '`') {\n            if (isFirstIdentifierChar(ch)\n                    && ch != '）'\n                    && !(ch == 'b' && bufPos == 1 && charAt(pos - 1) == '0' && dialectFeatureEnabled(\n                    ScanNumberCommonProcess))\n            ) {\n                bufPos++;\n                boolean brace = false;\n                for (; ; ) {\n                    char c0 = ch;\n                    ch = charAt(++pos);\n\n                    if (isEOF()) {\n                        break;\n                    }\n\n                    if (!isIdentifierChar(ch)) {\n                        if (ch == '{' && charAt(pos - 1) == '$' && !brace) {\n                            bufPos++;\n                            brace = true;\n                            continue;\n                        }\n\n                        if (ch == '}' && brace) {\n                            bufPos++;\n                            brace = false;\n                            continue;\n                        }\n\n                        if ((ch == '（' || ch == '）')\n                                && c0 > 256) {\n                            bufPos++;\n                            continue;\n                        }\n                        break;\n                    }\n\n                    bufPos++;\n                    continue;\n                }\n\n                stringVal = addSymbol();\n                hashLCase = FnvHash.hashCode64(stringVal);\n                token = Token.IDENTIFIER;\n                return;\n            }\n        }\n\n        token = Token.LITERAL_INT;\n    }\n\n    public void scanHexaDecimal() {\n        mark = pos;\n        bufPos = 0;\n\n        if (ch == '-') {\n            bufPos++;\n            ch = charAt(++pos);\n        }\n\n        for (; ; ) {\n            if (CharTypes.isHex(ch)) {\n                bufPos++;\n            } else {\n                break;\n            }\n            ch = charAt(++pos);\n        }\n\n        if (isIdentifierChar(ch)) {\n            for (; ; ) {\n                bufPos++;\n                ch = charAt(++pos);\n                if (!isIdentifierChar(ch)) {\n                    break;\n                }\n            }\n            mark -= 2;\n            bufPos += 2;\n            stringVal = addSymbol();\n            hashLCase = FnvHash.hashCode64(stringVal);\n            token = Token.IDENTIFIER;\n            return;\n        }\n\n        token = Token.LITERAL_HEX;\n    }\n\n    public String hexString() {\n        return subString(mark, bufPos);\n    }\n\n    public final boolean isDigit(char ch) {\n        return ch >= '0' && ch <= '9';\n    }\n\n    protected static final boolean isDigit2(char ch) {\n        return ch == '+' || ch == '-' || (ch >= '0' && ch <= '9');\n    }\n\n    /**\n     * Append a character to sbuf.\n     */\n    protected final void putChar(char ch) {\n        if (bufPos == buf.length) {\n            char[] newsbuf = new char[buf.length * 2];\n            System.arraycopy(buf, 0, newsbuf, 0, buf.length);\n            buf = newsbuf;\n        }\n        buf[bufPos++] = ch;\n    }\n\n    /**\n     * Return the current token's position: a 0-based offset from beginning of the raw input stream (before unicode\n     * translation)\n     */\n    public final int pos() {\n        return pos;\n    }\n\n    /**\n     * The value of a literal token, recorded as a string. For integers, leading 0x and 'l' suffixes are suppressed.\n     */\n    public final String stringVal() {\n        if (stringVal == null) {\n            stringVal = subString(mark, bufPos);\n        }\n        return stringVal;\n    }\n\n    private void stringVal(StringBuilder out) {\n        if (stringVal != null) {\n            out.append(stringVal);\n            return;\n        }\n\n        out.append(text, mark, mark + bufPos);\n    }\n\n    public final boolean identifierEquals(String text) {\n        if (token != Token.IDENTIFIER) {\n            return false;\n        }\n\n        if (stringVal == null) {\n            stringVal = subString(mark, bufPos);\n        }\n        return text.equalsIgnoreCase(stringVal);\n    }\n\n    public final boolean identifierEquals(long hash_lower) {\n        if (token != Token.IDENTIFIER) {\n            return false;\n        }\n\n        if (this.hashLCase == 0) {\n            if (stringVal == null) {\n                stringVal = subString(mark, bufPos);\n            }\n            this.hashLCase = FnvHash.fnv1a_64_lower(stringVal);\n        }\n        return this.hashLCase == hash_lower;\n    }\n\n    public final long hashLCase() {\n        if (this.hashLCase == 0) {\n            if (stringVal == null) {\n                stringVal = subString(mark, bufPos);\n            }\n            this.hashLCase = FnvHash.fnv1a_64_lower(stringVal);\n        }\n        return hashLCase;\n    }\n\n    public final List<String> readAndResetComments() {\n        List<String> comments = this.comments;\n\n        this.comments = null;\n\n        return comments;\n    }\n\n    private boolean isOperator(char ch) {\n        switch (ch) {\n            case '!':\n            case '%':\n            case '&':\n            case '*':\n            case '+':\n            case '-':\n            case '<':\n            case '=':\n            case '>':\n            case '^':\n            case '|':\n            case '~':\n            case ';':\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    private static final long MULTMIN_RADIX_TEN = Long.MIN_VALUE / 10;\n    private static final long N_MULTMAX_RADIX_TEN = -Long.MAX_VALUE / 10;\n\n    public final boolean isNegativeIntegerValue() {\n        return charAt(mark) == '-';\n    }\n\n    // QS_TODO negative number is invisible for lexer\n    public final Number integerValue() {\n        long result = 0;\n        boolean negative = false;\n        int i = mark, max = mark + bufPos;\n        long limit;\n        long multmin;\n        int digit;\n\n        if (charAt(mark) == '-') {\n            negative = true;\n            limit = Long.MIN_VALUE;\n            i++;\n        } else {\n            limit = -Long.MAX_VALUE;\n        }\n        multmin = negative ? MULTMIN_RADIX_TEN : N_MULTMAX_RADIX_TEN;\n        if (i < max) {\n            digit = charAt(i++) - '0';\n            result = -digit;\n        }\n        while (i < max) {\n            // Accumulating negatively avoids surprises near MAX_VALUE\n            digit = charAt(i++) - '0';\n            if (result < multmin) {\n                return new BigInteger(\n                        numberString());\n            }\n            result *= 10;\n            if (result < limit + digit) {\n                return new BigInteger(numberString());\n            }\n            result -= digit;\n        }\n\n        if (negative) {\n            if (i > mark + 1) {\n                if (result >= Integer.MIN_VALUE) {\n                    return (int) result;\n                }\n                return result;\n            } else { /* Only got \"-\" */\n                throw new NumberFormatException(numberString());\n            }\n        } else {\n            result = -result;\n            if (result <= Integer.MAX_VALUE) {\n                return (int) result;\n            }\n            return result;\n        }\n    }\n\n    public int bp() {\n        return this.pos;\n    }\n\n    public char current() {\n        return this.ch;\n    }\n\n    //todo fix reset reset字段会导致lexer的游标不对齐 不建议使用\n    @Deprecated\n    public void reset(int mark, char markChar, Token token) {\n        this.pos = mark;\n        this.ch = markChar;\n        this.token = token;\n    }\n\n    public final String numberString() {\n        return text.substring(mark, mark + bufPos);\n        // return subString(mark, bufPos);\n    }\n\n    public BigDecimal decimalValue() {\n        if (numberSale > 0 && !numberExp) {\n            int len = bufPos;\n\n            if (len < 20) {\n                long unscaleVal = 0;\n\n                boolean negative = false;\n                int i = 0;\n                char first = text.charAt(mark);\n                if (first == '+') {\n                    i++;\n                } else if (first == '-') {\n                    i++;\n                    negative = true;\n                }\n                for (; i < len; ++i) {\n                    char ch = text.charAt(mark + i);\n                    if (ch == '.') {\n                        continue;\n                    }\n                    int digit = ch - '0';\n                    unscaleVal = unscaleVal * 10 + digit;\n                }\n                return BigDecimal.valueOf(negative ? -unscaleVal : unscaleVal, numberSale);\n            }\n        }\n\n        char[] value = sub_chars(mark, bufPos);\n        if (!StringUtils.isNumber(value)) {\n            throw new ParserException(value + \" is not a number! \" + info());\n        }\n        return new BigDecimal(value);\n    }\n\n    public SQLNumberExpr numberExpr() {\n        char[] value = sub_chars(mark, bufPos);\n        if (!StringUtils.isNumber(value)) {\n            throw new ParserException(value + \" is not a number! \" + info());\n        }\n\n        return new SQLNumberExpr(value);\n    }\n\n    public SQLNumberExpr numberExpr(SQLObject parent) {\n        char[] value = sub_chars(mark, bufPos);\n        if (!StringUtils.isNumber(value)) {\n            throw new ParserException(value + \" is not a number! \" + info());\n        }\n\n        return new SQLNumberExpr(value, parent);\n    }\n\n    public SQLNumberExpr numberExpr(boolean negate) {\n        char[] value = sub_chars(mark, bufPos);\n        if (!StringUtils.isNumber(value)) {\n            throw new ParserException(value + \" is not a number! \" + info());\n        }\n\n        if (negate) {\n            char[] chars = new char[value.length + 1];\n            chars[0] = '-';\n            System.arraycopy(value, 0, chars, 1, value.length);\n            return new SQLNumberExpr(chars);\n        } else {\n            return new SQLNumberExpr(value);\n        }\n    }\n\n    public static interface CommentHandler {\n        boolean handle(Token lastToken, String comment);\n    }\n\n    public boolean hasComment() {\n        return comments != null;\n    }\n\n    public int getCommentCount() {\n        return commentCount;\n    }\n\n    public void skipToEOF() {\n        pos = text.length();\n        this.token = Token.EOF;\n    }\n\n    public boolean isEndOfComment() {\n        return endOfComment;\n    }\n\n    protected boolean isSafeComment(String comment) {\n        if (comment == null) {\n            return true;\n        }\n        comment = comment.toLowerCase();\n        if (comment.indexOf(\"select\") != -1 //\n                || comment.indexOf(\"delete\") != -1 //\n                || comment.indexOf(\"insert\") != -1 //\n                || comment.indexOf(\"update\") != -1 //\n                || comment.indexOf(\"into\") != -1 //\n                || comment.indexOf(\"where\") != -1 //\n                || containsWord(comment, \"or\") //\n                || containsWord(comment, \"and\") //\n                || comment.indexOf(\"union\") != -1 //\n                || comment.indexOf(\"drop\") != -1 //\n                || comment.indexOf(\"alter\") != -1 //\n                || comment.indexOf(\"create\") != -1 //\n                || comment.indexOf(\"truncate\") != -1 //\n                || comment.indexOf(\"exec\") != -1 //\n                || comment.indexOf(\"grant\") != -1 //\n                || comment.indexOf(\"revoke\") != -1 //\n                || comment.indexOf('\\'') != -1 //\n                || comment.indexOf('=') != -1 //\n                || comment.indexOf('>') != -1 //\n                || comment.indexOf('<') != -1 //\n                || comment.indexOf('&') != -1 //\n                || comment.indexOf('|') != -1 //\n                || comment.indexOf('^') != -1 //\n                || comment.indexOf(';') != -1 //\n        ) {\n            return false;\n        }\n        return true;\n    }\n\n    private static boolean containsWord(String text, String word) {\n        int index = 0;\n        while ((index = text.indexOf(word, index)) != -1) {\n            boolean startBound = (index == 0 || !Character.isLetterOrDigit(text.charAt(index - 1)));\n            boolean endBound = (index + word.length() >= text.length()\n                    || !Character.isLetterOrDigit(text.charAt(index + word.length())));\n            if (startBound && endBound) {\n                return true;\n            }\n            index += word.length();\n        }\n        return false;\n    }\n\n    protected void addComment(String comment) {\n        if (comments == null) {\n            comments = new ArrayList<String>(2);\n        }\n        comments.add(comment);\n    }\n\n    public final List<String> getComments() {\n        return comments;\n    }\n\n    public int getLine() {\n        return line;\n    }\n\n    public void computeRowAndColumn(SQLObject x) {\n        if (!keepSourceLocation) {\n            return;\n        }\n\n        int line = 1;\n        int column = 1;\n        for (int i = 0; i < startPos; ++i) {\n            char ch = text.charAt(i);\n            if (ch == '\\n') {\n                column = 1;\n                line++;\n            } else {\n                column++;\n            }\n        }\n        x.setSource(line, column);\n    }\n\n    public void computeRowAndColumn() {\n        int line = 1;\n        int column = 1;\n        for (int i = 0; i < startPos; ++i) {\n            char ch = text.charAt(i);\n            if (ch == '\\n') {\n                column = 1;\n                line++;\n            } else {\n                column++;\n            }\n        }\n\n        this.posLine = line;\n        this.posColumn = column;\n    }\n\n    public int getPosLine() {\n        return posLine;\n    }\n\n    public int getPosColumn() {\n        return posColumn;\n    }\n\n    public void config(SQLParserFeature feature, boolean state) {\n        features = SQLParserFeature.config(features, feature, state);\n\n        if (feature == OptimizedForParameterized) {\n            optimizedForParameterized = state;\n        } else if (feature == KeepComments) {\n            this.keepComments = state;\n        } else if (feature == KeepSourceLocation) {\n            this.keepSourceLocation = state;\n        } else if (feature == SkipComments) {\n            this.skipComment = state;\n        }\n    }\n\n    public TimeZone getTimeZone() {\n        return timeZone;\n    }\n\n    public void setTimeZone(TimeZone timeZone) {\n        this.timeZone = timeZone;\n    }\n\n    public final boolean isEnabled(SQLParserFeature feature) {\n        return SQLParserFeature.isEnabled(this.features, feature);\n    }\n\n    public static String parameterize(String sql, DbType dbType) {\n        Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n        lexer.optimizedForParameterized = true; // optimized\n\n        lexer.nextToken();\n\n        StringBuilder buf = new StringBuilder();\n\n        for_:\n        for (; ; ) {\n            Token token = lexer.token;\n            switch (token) {\n                case LITERAL_ALIAS:\n                case LITERAL_FLOAT:\n                case LITERAL_CHARS:\n                case LITERAL_INT:\n                case LITERAL_NCHARS:\n                case LITERAL_HEX:\n                case VARIANT:\n                    if (buf.length() != 0) {\n                        buf.append(' ');\n                    }\n                    buf.append('?');\n                    break;\n                case COMMA:\n                    buf.append(',');\n                    break;\n                case EQ:\n                    buf.append('=');\n                    break;\n                case EOF:\n                    break for_;\n                case ERROR:\n                    return sql;\n                case SELECT:\n                    buf.append(\"SELECT\");\n                    break;\n                case UPDATE:\n                    buf.append(\"UPDATE\");\n                    break;\n                default:\n                    if (buf.length() != 0) {\n                        buf.append(' ');\n                    }\n                    lexer.stringVal(buf);\n                    break;\n            }\n\n            lexer.nextToken();\n        }\n\n        return buf.toString();\n    }\n\n    public String getSource() {\n        return text;\n    }\n\n    protected boolean dialectFeatureEnabled(DialectFeature.LexerFeature feature) {\n        return dialectFeature.isEnabled(feature);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/NotAllowCommentException.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\npublic class NotAllowCommentException extends ParserException {\n    private static final long serialVersionUID = 1L;\n\n    public NotAllowCommentException() {\n        this(\"comment not allow\");\n    }\n\n    public NotAllowCommentException(String message, Throwable e) {\n        super(message, e);\n    }\n\n    public NotAllowCommentException(String message) {\n        super(message);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/ParserException.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.FastsqlException;\n\nimport java.io.Serializable;\n\npublic class ParserException extends FastsqlException implements Serializable {\n    private static final long serialVersionUID = 1L;\n\n    private final int line;\n    private final int column;\n\n    public ParserException() {\n        this.line = 0;\n        this.column = 0;\n    }\n\n    public ParserException(String message) {\n        super(message);\n        this.line = 0;\n        this.column = 0;\n    }\n\n    public ParserException(String message, Throwable e) {\n        super(message, e);\n        this.line = 0;\n        this.column = 0;\n    }\n\n    public ParserException(String message, int line, int column) {\n        super(message);\n        this.line = line;\n        this.column = column;\n    }\n\n    public ParserException(Throwable ex, String sql) {\n        super(\"parse error. detail message is :\\n\" + ex.getMessage() + \"\\nsource sql is : \\n\" + sql, ex);\n        this.line = 0;\n        this.column = 0;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLPartitionBy;\nimport com.alibaba.druid.sql.ast.SQLPartitionOf;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.template.SQLSelectQueryTemplate;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.CreateTableBodySupplemental;\nimport static com.alibaba.druid.sql.parser.SQLParserFeature.Template;\n\npublic class SQLCreateTableParser extends SQLDDLParser {\n    public SQLCreateTableParser(String sql) {\n        super(sql);\n    }\n\n    public SQLCreateTableParser(SQLExprParser exprParser) {\n        super(exprParser);\n        dbType = exprParser.dbType;\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        List<String> comments = null;\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            comments = lexer.readAndResetComments();\n        }\n\n        SQLCreateTableStatement createTable = newCreateStatement();\n        if (comments != null) {\n            createTable.addBeforeComment(comments);\n        }\n\n        createTable.setDbType(dbType);\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            createTable.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        accept(Token.CREATE);\n        createTableBefore(createTable);\n        if (lexer.token == Token.TABLE || lexer.identifierEquals(FnvHash.Constants.TABLE)) {\n            lexer.nextToken();\n        } else {\n            setErrorEndPos(lexer.pos());\n            printError(lexer.token);\n        }\n        createTableBeforeName(createTable);\n        createTable.setName(\n                this.exprParser.name());\n        createTableAfterName(createTable);\n        createTableBody(createTable);\n        parseCreateTableRest(createTable);\n        createTableQuery(createTable);\n        createTableAfterQuery(createTable);\n        return createTable;\n    }\n\n    protected SQLSelect createTableQueryRest() {\n        return this.createSQLSelectParser().select();\n    }\n\n    protected void createTableQuery(SQLCreateTableStatement createTable) {\n        if (lexer.nextIf(Token.AS)) {\n            SQLSelect select;\n            if ((lexer.token == Token.IDENTIFIER || lexer.token == Token.VARIANT)\n                    && lexer.isEnabled(Template)\n                    && lexer.stringVal.startsWith(\"$\")) {\n                select = new SQLSelect(\n                        new SQLSelectQueryTemplate(lexer.stringVal));\n                lexer.nextToken();\n            } else {\n                select = createTableQueryRest();\n            }\n            createTable.setSelect(select);\n        }\n    }\n\n    protected void createTableBody(SQLCreateTableStatement createTable) {\n        if (lexer.nextIf(Token.LPAREN)) {\n            for (; ; ) {\n                createTableBodyItem(createTable);\n                if (lexer.nextIf(Token.COMMA)) {\n                    if (lexer.token == Token.RPAREN) { // compatible for sql server\n                        break;\n                    }\n                    continue;\n                }\n\n                break;\n            }\n\n            accept(Token.RPAREN);\n\n            createTableAfter(createTable);\n        }\n    }\n\n    protected void createTableBodyItem(SQLCreateTableStatement createTable) {\n        Token token = lexer.token;\n        if (lexer.identifierEquals(FnvHash.Constants.SUPPLEMENTAL)\n                && dialectFeatureEnabled(CreateTableBodySupplemental)) {\n            SQLTableElement element = this.parseCreateTableSupplementalLoggingProps();\n            element.setParent(createTable);\n            createTable.getTableElementList().add(element);\n        } else if (token == Token.IDENTIFIER //\n                || token == Token.LITERAL_ALIAS) {\n            SQLColumnDefinition column = this.exprParser.parseColumn(createTable);\n            column.setParent(createTable);\n            createTable.getTableElementList().add(column);\n        } else if (token == Token.PRIMARY //\n                || token == Token.UNIQUE //\n                || token == Token.CHECK //\n                || token == Token.CONSTRAINT\n                || token == Token.FOREIGN) {\n            SQLConstraint constraint = this.exprParser.parseConstraint();\n            constraint.setParent(createTable);\n            createTable.getTableElementList().add((SQLTableElement) constraint);\n        } else if (token == Token.TABLESPACE) {\n            throw new ParserException(\"TABLESPACE as table element is not supported, use it after table definition. \" + lexer.info());\n        } else if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            SQLTableLike tableLike = new SQLTableLike();\n            tableLike.setTable(new SQLExprTableSource(this.exprParser.name()));\n            tableLike.setParent(createTable);\n            createTable.getTableElementList().add(tableLike);\n\n            if (lexer.identifierEquals(FnvHash.Constants.INCLUDING)) {\n                lexer.nextToken();\n                if (lexer.nextIfIdentifier(FnvHash.Constants.PROPERTIES)) {\n                    tableLike.setIncludeProperties(true);\n                } else if (lexer.nextIfIdentifier(\"DISTRIBUTION\")) {\n                    tableLike.setIncludeDistribution(true);\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.EXCLUDING)) {\n                lexer.nextToken();\n                if (lexer.nextIfIdentifier(FnvHash.Constants.PROPERTIES)) {\n                    tableLike.setExcludeProperties(true);\n                } else if (lexer.nextIfIdentifier(\"DISTRIBUTION\")) {\n                    tableLike.setExcludeDistribution(true);\n                }\n            }\n        } else if (lexer.token() == Token.INDEX) {\n            parseIndex(createTable);\n        } else {\n            SQLColumnDefinition column = this.exprParser.parseColumn();\n            createTable.getTableElementList().add(column);\n        }\n    }\n\n    protected void parseIndex(SQLCreateTableStatement createTable) {\n        SQLColumnDefinition column = this.exprParser.parseColumn();\n        createTable.getTableElementList().add(column);\n    }\n\n    protected void createTableBefore(SQLCreateTableStatement createTable) {\n        if (lexer.nextIfIdentifier(\"GLOBAL\")) {\n            createTable.config(SQLCreateTableStatement.Feature.Global);\n            if (lexer.nextIfIdentifier(\"TEMPORARY\") || lexer.nextIfIdentifier(\"TEMP\")) {\n                createTable.config(SQLCreateTableStatement.Feature.Temporary);\n            } else {\n                throw new ParserException(\"syntax error \" + lexer.info());\n            }\n        } else if (lexer.nextIfIdentifier(\"LOCAL\") || lexer.nextIf(Token.LOCAL)) {\n            createTable.config(SQLCreateTableStatement.Feature.Local);\n            if (lexer.nextIfIdentifier(\"TEMPORARY\") || lexer.nextIfIdentifier(\"TEMP\")) {\n                createTable.config(SQLCreateTableStatement.Feature.Temporary);\n            } else {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.DIMENSION)) {\n            createTable.config(SQLCreateTableStatement.Feature.Dimension);\n        }\n    }\n\n    protected void createTableBeforeName(SQLCreateTableStatement createTable) {\n        if (lexer.nextIf(Token.IF) || lexer.nextIfIdentifier(\"IF\")) {\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n\n            createTable.setIfNotExists(true);\n        }\n    }\n\n    protected void createTableAfterName(SQLCreateTableStatement createTable) {}\n\n    protected void createTableAfter(SQLCreateTableStatement stmt) {\n        if (lexer.nextIfIdentifier(FnvHash.Constants.INHERITS)) {\n            accept(Token.LPAREN);\n            SQLName inherits = this.exprParser.name();\n            stmt.setInherits(new SQLExprTableSource(inherits));\n            accept(Token.RPAREN);\n        }\n    }\n\n    protected void parseCreateTableRest(SQLCreateTableStatement stmt) {\n        // For partition of for PG\n        if (lexer.token() == Token.PARTITION) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            // For partition of for PG\n            if (Token.OF.equals(lexer.token())) {\n                lexer.reset(mark);\n                SQLPartitionOf partitionOf = parsePartitionOf();\n                stmt.setPartitionOf(partitionOf);\n                // For partition by\n            } else if (Token.BY.equals(lexer.token())) {\n                lexer.reset(mark);\n                SQLPartitionBy partitionClause = parsePartitionBy();\n                stmt.setPartitionBy(partitionClause);\n            }\n        }\n\n        if (lexer.nextIf(Token.TABLESPACE)) {\n            stmt.setTablespace(\n                    this.exprParser.name()\n            );\n        }\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        return null;\n    }\n\n    public SQLPartitionOf parsePartitionOf() {\n        return null;\n    }\n\n    protected SQLTableElement parseCreateTableSupplementalLoggingProps() {\n        throw new ParserException(\"SUPPLEMENTAL LOGGING is not supported for current dialect. \" + lexer.info());\n    }\n\n    protected SQLCreateTableStatement newCreateStatement() {\n        return new SQLCreateTableStatement(getDbType());\n    }\n\n    protected void parseOptions(SQLCreateTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            String name = lexer.stringVal();\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLExpr value = this.exprParser.primary();\n            stmt.addOption(name, value);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                if (lexer.token() == Token.RPAREN) {\n                    break;\n                }\n                continue;\n            }\n            break;\n        }\n\n        accept(Token.RPAREN);\n    }\n\n    protected void createTableAfterQuery(SQLCreateTableStatement stmt) {\n    }\n\n    /**\n     * Parse table COMMENT clause, common across multiple dialects (Hive, ClickHouse, GaussDB, StarRocks, BigQuery).\n     * Usage: call this in dialect-specific parseCreateTableRest() when COMMENT token is encountered.\n     *\n     * @return true if COMMENT was parsed, false otherwise\n     */\n    protected boolean parseTableComment(SQLCreateTableStatement stmt) {\n        if (lexer.nextIf(Token.COMMENT)) {\n            if (lexer.nextIf(Token.EQ)) {\n                // COMMENT = 'xxx'\n            }\n            stmt.setComment(this.exprParser.primary());\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * Parse ENGINE = expr clause, common across MySQL, Hive, ClickHouse, StarRocks and other dialects.\n     *\n     * @return true if ENGINE was parsed, false otherwise\n     */\n    protected boolean parseTableEngine(SQLCreateTableStatement stmt) {\n        if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n            lexer.nextToken();\n            if (lexer.nextIf(Token.EQ)) {\n                // ENGINE = xxx\n            }\n            stmt.setEngine(this.exprParser.primary());\n            return true;\n        }\n        return false;\n    }\n\n    /**\n     * Parse table-level assignment properties like WITH (key=value, ...) or TBLPROPERTIES (key=value, ...).\n     * Common across PostgreSQL, GaussDB, Hive, and other dialects.\n     *\n     * @param stmt the create table statement\n     * @param keyword the keyword to match (e.g., \"TBLPROPERTIES\")\n     * @return true if properties were parsed, false otherwise\n     */\n    protected boolean parseTableProperties(SQLCreateTableStatement stmt, String keyword) {\n        if (lexer.identifierEquals(keyword)) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLAssignItem item = this.exprParser.parseAssignItem(true, stmt);\n                item.setParent(stmt);\n                stmt.getTableOptions().add(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLDDLParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLTableConstraint;\n\npublic class SQLDDLParser extends SQLStatementParser {\n    public SQLDDLParser(String sql) {\n        super(sql);\n    }\n\n    public SQLDDLParser(SQLExprParser exprParser) {\n        super(exprParser);\n    }\n\n    protected SQLTableConstraint parseConstraint() {\n        if (lexer.token == Token.CONSTRAINT) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token == Token.IDENTIFIER) {\n            this.exprParser.name();\n            throw new ParserException(\"TODO. \" + lexer.info());\n        }\n\n        if (lexer.token == Token.PRIMARY) {\n            lexer.nextToken();\n            accept(Token.KEY);\n\n            SQLPrimaryKeyImpl pk = new SQLPrimaryKeyImpl();\n            accept(Token.LPAREN);\n            this.exprParser.orderBy(pk.getColumns(), pk);\n            accept(Token.RPAREN);\n\n            return pk;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr;\nimport com.alibaba.druid.sql.parser.Lexer.SavePoint;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.StringUtils;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.Token.*;\n\npublic class SQLExprParser extends SQLParser {\n    public static final String[] AGGREGATE_FUNCTIONS;\n\n    public static final long[] AGGREGATE_FUNCTIONS_CODES;\n    private static final List<String> NESTED_DATA_TYPE;\n\n    static {\n        String[] strings = {\"AVG\", \"COUNT\", \"MAX\", \"MIN\", \"STDDEV\", \"SUM\"};\n        AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);\n        AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];\n        for (String str : strings) {\n            long hash = FnvHash.fnv1a_64_lower(str);\n            int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);\n            AGGREGATE_FUNCTIONS[index] = str;\n        }\n        NESTED_DATA_TYPE = Collections.singletonList(\"array\");\n    }\n\n    protected String[] aggregateFunctions = AGGREGATE_FUNCTIONS;\n    protected long[] aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;\n    protected List<String> nestedDataType = NESTED_DATA_TYPE;\n\n    protected boolean allowIdentifierMethod = true;\n\n    public SQLExprParser(String sql) {\n        super(sql);\n    }\n\n    public SQLExprParser(String sql, DbType dbType, SQLParserFeature... features) {\n        super(sql, dbType, features);\n    }\n\n    public SQLExprParser(Lexer lexer) {\n        super(lexer);\n    }\n\n    public SQLExprParser(Lexer lexer, DbType dbType) {\n        super(lexer, dbType);\n    }\n\n    public void setAllowIdentifierMethod(boolean allowIdentifierMethod) {\n        this.allowIdentifierMethod = allowIdentifierMethod;\n    }\n\n    public SQLExpr expr() {\n        if (lexer.token == Token.STAR) {\n            lexer.nextToken();\n\n            SQLAllColumnExpr expr = new SQLAllColumnExpr();\n\n            if (lexer.token == Token.DOT) {\n                lexer.nextToken();\n                accept(Token.STAR);\n                return new SQLPropertyExpr(expr, \"*\");\n            }\n\n            if (lexer.token == Token.EXCEPT) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                List<SQLExpr> except = new ArrayList<>();\n                this.exprList(except, expr);\n                expr.setExcept(except);\n                accept(Token.RPAREN);\n            }\n\n            return expr;\n        }\n\n        boolean parenthesized = (lexer.token == Token.LPAREN);\n        SQLExpr expr = primary();\n        if (parenthesized && expr instanceof SQLBinaryOpExpr) {\n            if (((SQLBinaryOpExpr) expr).isParenthesized()) {\n                parenthesized = false;\n            }\n        }\n        if (parenthesized && expr instanceof SQLCaseExpr) {\n            parenthesized = false;\n            ((SQLCaseExpr) expr).setParenthesized(true);\n        }\n        if (parenthesized && expr instanceof SQLUnaryExpr) {\n            if (((SQLUnaryExpr) expr).isParenthesized()) {\n                parenthesized = false;\n            }\n        }\n        if (parenthesized && expr instanceof SQLQueryExpr) {\n            parenthesized = false;\n            ((SQLQueryExpr) expr).setParenthesized(true);\n        }\n        if (parenthesized && expr instanceof SQLNotExpr) {\n            parenthesized = false;\n        }\n        if (parenthesized && expr instanceof SQLIdentifierExpr) {\n            parenthesized = false;\n            ((SQLIdentifierExpr) expr).setParenthesized(true);\n        }\n        Lexer.SavePoint mark = lexer.mark();\n        Token token = lexer.token;\n        if (token == Token.COMMA) {\n            return expr;\n        } else if (token == Token.EQ || token == Token.EQEQ) {\n            expr = relationalRest(expr);\n            expr = andRest(expr);\n            expr = xorRest(expr);\n            expr = orRest(expr);\n            return expr;\n        }\n        if (token == Token.IN) {\n            lexer.nextToken();\n            if (lexer.token == Token.PARTITION) {\n                lexer.reset(mark);\n                return expr;\n            } else {\n                lexer.reset(mark);\n                return exprRest(expr);\n            }\n        } else {\n            SQLExpr sqlExpr = exprRest(expr);\n            if (token == SUBGT) {\n                parenthesized = false;\n            }\n            if (parenthesized && sqlExpr instanceof SQLBinaryOpExpr) {\n                ((SQLBinaryOpExpr) sqlExpr).setParenthesized(true);\n            }\n            if (parenthesized && sqlExpr instanceof SQLUnaryExpr) {\n                ((SQLUnaryExpr) sqlExpr).setParenthesized(true);\n            }\n            if (parenthesized && sqlExpr instanceof MySqlCharExpr) {\n                ((MySqlCharExpr) sqlExpr).setParenthesized(true);\n            }\n            return sqlExpr;\n        }\n    }\n\n    public SQLExpr exprRest(SQLExpr expr) {\n        expr = bitXorRest(expr);\n        expr = multiplicativeRest(expr);\n        expr = additiveRest(expr);\n        expr = shiftRest(expr);\n        expr = bitAndRest(expr);\n        expr = bitOrRest(expr);\n        expr = inRest(expr);\n        expr = relationalRest(expr);\n//        expr = equalityRest(expr);\n        expr = andRest(expr);\n        expr = xorRest(expr);\n        expr = orRest(expr);\n\n        return expr;\n    }\n\n    public final SQLExpr bitXor() {\n        SQLExpr expr = primary();\n        return bitXorRest(expr);\n    }\n\n    protected SQLExpr bitXorRestSUBGT() {\n        return primary();\n    }\n    public SQLExpr bitXorRest(SQLExpr expr) {\n        Token token = lexer.token;\n        switch (token) {\n            case CARET: {\n                lexer.nextToken();\n                SQLBinaryOperator op;\n                if (lexer.token == Token.EQ) {\n                    lexer.nextToken();\n                    op = SQLBinaryOperator.BitwiseXorEQ;\n                } else {\n                    op = SQLBinaryOperator.BitwiseXor;\n                }\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case SUBGT: {\n                lexer.nextToken();\n                SQLExpr rightExp = bitXorRestSUBGT();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGt, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case LT_SUB_GT: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PG_ST_DISTANCE, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case SUBGTGT: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGtGt, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case POUNDGT: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGt, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case POUNDGTGT: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGtGt, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case QUESQUES: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQues, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case QUESBAR: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesBar, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case QUESQUESBAR: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQuesBar, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n            case QUESAMP: {\n                lexer.nextToken();\n                SQLExpr rightExp = primary();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesAmp, rightExp, dbType);\n                expr = bitXorRest(expr);\n                break;\n            }\n\n            default:\n                break;\n        }\n\n        return expr;\n    }\n\n    public final SQLExpr multiplicative() {\n        SQLExpr expr = bitXor();\n        return multiplicativeRest(expr);\n    }\n\n    public SQLExpr multiplicativeRest(SQLExpr expr) {\n        final Token token = lexer.token;\n        if (token == Token.STAR) {\n            lexer.nextToken();\n            SQLExpr rightExp = bitXor();\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Multiply, rightExp, getDbType());\n            expr = multiplicativeRest(expr);\n        } else if (token == Token.SLASH) {\n            lexer.nextToken();\n            SQLExpr rightExp = bitXor();\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Divide, rightExp, getDbType());\n            expr = multiplicativeRest(expr);\n        } else if (token == Token.PERCENT) {\n            lexer.nextToken();\n            SQLExpr rightExp = bitXor();\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp, getDbType());\n            expr = multiplicativeRest(expr);\n        } else if (token == Token.DIV) {\n            lexer.nextToken();\n            SQLExpr rightExp = bitXor();\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.DIV, rightExp, getDbType());\n            expr = multiplicativeRest(expr);\n        } else if (lexer.identifierEquals(FnvHash.Constants.MOD) || lexer.token == Token.MOD) {\n            Lexer.SavePoint savePoint = lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.token == Token.COMMA\n                    || lexer.token == Token.EOF\n                    || lexer.token == Token.ON\n                    || lexer.token == Token.WHERE\n                    || lexer.token == Token.RPAREN) {\n                lexer.reset(savePoint);\n                return expr;\n            }\n\n            SQLExpr rightExp = bitXor();\n\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp, dbType);\n\n            expr = multiplicativeRest(expr);\n        } else if (token == Token.LITERAL_INT && lexer.isNegativeIntegerValue()) {\n            Number number = lexer.integerValue();\n            if (number instanceof Integer) {\n                number = -number.intValue();\n            } else if (number instanceof Long) {\n                number = -number.longValue();\n            } else if (number instanceof BigInteger) {\n                number = ((BigInteger) number).abs();\n            } else {\n                throw new ParserException(\"not support value : \" + number + \", \" + lexer.info());\n            }\n            SQLIntegerExpr rightExp = new SQLIntegerExpr(number);\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Subtract, rightExp, dbType);\n\n            lexer.nextToken();\n            expr = multiplicativeRest(expr);\n\n        }\n        return expr;\n    }\n\n    public SQLIntegerExpr integerExpr() {\n        SQLIntegerExpr intExpr = null;\n        if (lexer.token() == Token.SUB) {\n            lexer.nextToken();\n            intExpr = new SQLIntegerExpr(lexer.integerValue().longValue() * -1);\n        } else {\n            intExpr = new SQLIntegerExpr(lexer.integerValue());\n        }\n        accept(Token.LITERAL_INT);\n        return intExpr;\n    }\n\n    public SQLCharExpr charExpr() {\n        SQLCharExpr charExpr = new SQLCharExpr(lexer.stringVal());\n        accept(Token.LITERAL_CHARS);\n        return charExpr;\n    }\n\n    public int parseIntValue() {\n        if (lexer.token == Token.LITERAL_INT) {\n            Number number = this.lexer.integerValue();\n            int intVal = ((Integer) number).intValue();\n            lexer.nextToken();\n            return intVal;\n        } else {\n            throw new ParserException(\"not int. \" + lexer.info());\n        }\n    }\n\n    public void parseAssignItems(List<? super SQLAssignItem> items, SQLObject parent, boolean variant) {\n        for (; ; ) {\n            SQLAssignItem item = parseAssignItem(variant, parent);\n            item.setParent(parent);\n            items.add(item);\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n        }\n    }\n\n    protected SQLExpr primaryIdentifierRest(long hash_lower, String ident) {\n        SQLExpr sqlExpr = null;\n        if (hash_lower == FnvHash.Constants.VARCHAR && lexer.token == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLCharExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else if (hash_lower == FnvHash.Constants.CHAR && lexer.token == Token.LITERAL_CHARS) {\n            sqlExpr = new SQLCharExpr(lexer.stringVal());\n            lexer.nextToken();\n        }\n        return sqlExpr;\n    }\n\n    protected SQLPropertyExpr topPropertyExpr(String ident) {\n        String substring = ident.substring(1, ident.length() - 1);\n        String[] items = substring.split(\"\\\\.\");\n        SQLPropertyExpr expr = new SQLPropertyExpr(items[0], items[1]);\n        for (int i = 2; i < items.length; i++) {\n            expr = new SQLPropertyExpr(expr, items[i]);\n        }\n        return expr;\n    }\n\n    protected SQLExpr primaryLiteralCharsRest(SQLExpr sqlExpr) {\n        lexer.nextToken();\n        return sqlExpr;\n    }\n\n    protected SQLExpr primaryLiteralNCharsRest(SQLExpr sqlExpr) {\n        return sqlExpr;\n    }\n\n    protected SQLExpr primaryDefaultRest() {\n        return new SQLDefaultExpr();\n    }\n\n    protected SQLExpr primarySubLiteralAliasRest() {\n        return new SQLIdentifierExpr(lexer.stringVal());\n    }\n\n    protected void primaryQues() {\n        lexer.nextToken();\n    }\n\n    protected SQLExpr primaryCommon(SQLExpr sqlExpr) {\n        throw new ParserException(\"ERROR. \" + lexer.info());\n    }\n\n    protected SQLExpr primaryAs(SQLExpr sqlExpr) {\n        return sqlExpr;\n    }\n\n    protected SQLExpr primaryDistinct(SQLExpr sqlExpr) {\n        throw new ParserException(\"ERROR. \" + lexer.info());\n    }\n\n    protected SQLExpr primaryIn(SQLExpr sqlExpr) {\n        throw new ParserException(\"ERROR. \" + lexer.info());\n    }\n\n    protected SQLExpr primaryOn(SQLExpr sqlExpr) {\n        throw new ParserException(\"ERROR. \" + lexer.info());\n    }\n\n    protected SQLExpr primaryColonColon(SQLExpr sqlExpr) {\n        throw new ParserException(\"ERROR. \" + lexer.info());\n    }\n\n    public SQLExpr primary() {\n        List<String> beforeComments = null;\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            beforeComments = lexer.readAndResetComments();\n        }\n\n        SQLExpr sqlExpr = null;\n\n        final Token tok = lexer.token;\n\n        switch (tok) {\n            case LPAREN:\n                sqlExpr = primaryLParen();\n                break;\n            case INSERT:\n                lexer.nextToken();\n                if (lexer.token != Token.LPAREN) {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n                sqlExpr = new SQLIdentifierExpr(\"INSERT\");\n                break;\n            case IDENTIFIER:\n                sqlExpr = primaryIdentifier();\n                break;\n            case NEW:\n                throw new ParserException(\"NEW expression is not supported for current dialect. \" + lexer.info());\n            case LITERAL_INT:\n                Number number = lexer.integerValue();\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.BD)) {\n                    SQLDecimalExpr decimalExpr = new SQLDecimalExpr();\n                    decimalExpr.setValue(new BigDecimal(number.intValue()));\n                    lexer.nextToken();\n                    sqlExpr = decimalExpr;\n                } else {\n                    sqlExpr = new SQLIntegerExpr(number);\n                }\n                break;\n            case LITERAL_FLOAT:\n                sqlExpr = lexer.numberExpr();\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.BD)) {\n                    SQLDecimalExpr decimalExpr = new SQLDecimalExpr();\n                    decimalExpr.setValue(new BigDecimal(sqlExpr.toString()));\n                    lexer.nextToken();\n                    sqlExpr = decimalExpr;\n                }\n\n                break;\n            case LITERAL_CHARS: {\n                sqlExpr = new SQLCharExpr(lexer.stringVal());\n                sqlExpr = primaryLiteralCharsRest(sqlExpr);\n                break;\n            }\n            case LITERAL_NCHARS:\n                sqlExpr = new SQLNCharExpr(lexer.stringVal());\n                lexer.nextToken();\n                sqlExpr = primaryLiteralNCharsRest(sqlExpr);\n                break;\n            case VARIANT: {\n                sqlExpr = primaryVariant();\n            }\n            break;\n            case DEFAULT:\n                sqlExpr = primaryDefaultRest();\n                lexer.nextToken();\n                break;\n            case DUAL:\n            case KEY:\n//            case DISTINCT:\n            case LIMIT:\n            case SCHEMA:\n            case COLUMN:\n            case IF:\n            case END:\n            case COMMENT:\n            case COMPUTE:\n            case ENABLE:\n            case DISABLE:\n            case INITIALLY:\n            case SEQUENCE:\n            case USER:\n            case EXPLAIN:\n            case WITH:\n            case GRANT:\n            case REPLACE:\n            case INDEX:\n//            case MODEL:\n            case PCTFREE:\n            case INITRANS:\n            case MAXTRANS:\n            case SEGMENT:\n            case CREATION:\n            case IMMEDIATE:\n            case DEFERRED:\n            case STORAGE:\n            case NEXT:\n            case MINEXTENTS:\n            case MAXEXTENTS:\n            case MAXSIZE:\n            case PCTINCREASE:\n            case FLASH_CACHE:\n            case CELL_FLASH_CACHE:\n            case NONE:\n            case LOB:\n            case STORE:\n            case ROW:\n            case CHUNK:\n            case CACHE:\n            case NOCACHE:\n            case LOGGING:\n            case NOCOMPRESS:\n            case KEEP_DUPLICATES:\n            case EXCEPTIONS:\n            case PURGE:\n            case FULL:\n            case TO:\n            case IDENTIFIED:\n            case PASSWORD:\n            case BINARY:\n            case WINDOW:\n            case OFFSET:\n            case SHARE:\n            case START:\n            case CONNECT:\n            case MATCHED:\n            case ERRORS:\n            case REJECT:\n            case UNLIMITED:\n            case BEGIN:\n            case EXCLUSIVE:\n            case MODE:\n            case ADVISE:\n            case VIEW:\n            case ESCAPE:\n            case OVER:\n            case ORDER:\n            case CONSTRAINT:\n            case TYPE:\n            case OPEN:\n            case REPEAT:\n            case TABLE:\n            case TRUNCATE:\n            case EXCEPTION:\n            case FUNCTION:\n            case IDENTITY:\n            case EXTRACT:\n            case DESC:\n            case DO:\n            case GROUP:\n            case MOD:\n            case CONCAT:\n            case PRIMARY:\n            case PARTITION:\n            case LEAVE:\n            case CLOSE:\n            case CONDITION:\n            case OUT:\n            case USE:\n            case EXCEPT:\n            case INTERSECT:\n            case MERGE:\n            case MINUS:\n            case UNTIL:\n            case TOP:\n            case SHOW:\n            case INOUT:\n            case OUTER:\n            case QUALIFY:\n            case GET:\n                sqlExpr = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n                break;\n            case CASE:\n                sqlExpr = primaryCase();\n                break;\n            case EXISTS: {\n                String strVal = lexer.stringVal();\n                lexer.nextToken();\n                switch (lexer.token) {\n                    case COMMA:\n                    case DOT:\n                        sqlExpr = new SQLIdentifierExpr(strVal);\n                        break;\n                    default:\n                        accept(Token.LPAREN);\n                        sqlExpr = new SQLExistsExpr(createSelectParser().select());\n                        accept(Token.RPAREN);\n                        parseQueryPlanHint(sqlExpr);\n                        break;\n                }\n\n                break;\n            }\n            case NOT:\n                sqlExpr = primaryNot();\n                break;\n            case FROM:\n            case SELECT:\n                sqlExpr = parseQueryExpr();\n                break;\n            case CAST:\n                sqlExpr = parseCast();\n                break;\n            case SUB:\n                sqlExpr = primarySub();\n                break;\n            case PLUS:\n                sqlExpr = primaryPlus();\n                break;\n            case TILDE:\n                lexer.nextToken();\n                SQLExpr unaryValueExpr = primary();\n                SQLUnaryExpr unary = new SQLUnaryExpr(SQLUnaryOperator.Compl, unaryValueExpr);\n                sqlExpr = unary;\n                break;\n            case QUES:\n                primaryQues();\n                SQLVariantRefExpr quesVarRefExpr = new SQLVariantRefExpr(\"?\");\n                quesVarRefExpr.setIndex(lexer.nextVarIndex());\n                sqlExpr = quesVarRefExpr;\n                break;\n            case LEFT:\n                sqlExpr = new SQLIdentifierExpr(\"LEFT\");\n                lexer.nextToken();\n                break;\n            case RIGHT:\n                sqlExpr = new SQLIdentifierExpr(\"RIGHT\");\n                lexer.nextToken();\n                break;\n            case INNER:\n                sqlExpr = new SQLIdentifierExpr(\"INNER\");\n                lexer.nextToken();\n                break;\n            case DATABASE:\n                sqlExpr = new SQLIdentifierExpr(\"DATABASE\");\n                lexer.nextToken();\n                break;\n            case CASCADE:\n                sqlExpr = new SQLIdentifierExpr(\"CASCADE\");\n                lexer.nextToken();\n                break;\n            case LOCK:\n                sqlExpr = new SQLIdentifierExpr(\"LOCK\");\n                lexer.nextToken();\n                break;\n            case NULL:\n                sqlExpr = new SQLNullExpr();\n                lexer.nextToken();\n                break;\n            case BANG:\n                lexer.nextToken();\n                sqlExpr = new SQLUnaryExpr(\n                        SQLUnaryOperator.Not,\n                        primary()\n                );\n                break;\n            case BANGBANG: {\n                if (!dialectFeatureEnabled(PrimaryBangBangSupport)) {\n                    throw new ParserException(lexer.info());\n                }\n                lexer.nextToken();\n                sqlExpr = new SQLUnaryExpr(\n                        SQLUnaryOperator.Not,\n                        primary()\n                );\n                break;\n            }\n            case BANG_TILDE: {\n                lexer.nextToken();\n                SQLExpr bangExpr = primary();\n                sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Not, new SQLUnaryExpr(SQLUnaryOperator.Compl, bangExpr));\n                break;\n            }\n            case LITERAL_HEX:\n                String hex = lexer.hexString();\n                sqlExpr = new SQLHexExpr(hex);\n                lexer.nextToken();\n                break;\n            case INTERVAL:\n                sqlExpr = parseInterval();\n                break;\n            case COLON:\n                lexer.nextToken();\n                if (lexer.token == Token.LITERAL_ALIAS) {\n                    sqlExpr = new SQLVariantRefExpr(\":\\\"\" + lexer.stringVal() + \"\\\"\");\n                    lexer.nextToken();\n                }\n                break;\n            case ANY:\n                sqlExpr = parseAny();\n                break;\n            case SOME:\n                sqlExpr = parseSome();\n                break;\n            case ALL:\n                sqlExpr = parseAll();\n                break;\n            case LITERAL_ALIAS:\n                sqlExpr = parseAliasExpr(lexer.stringVal());\n                lexer.nextToken();\n                break;\n            case EOF:\n                throw new EOFParserException();\n            case TRUE:\n                lexer.nextToken();\n                sqlExpr = new SQLBooleanExpr(true);\n                break;\n            case FALSE:\n                lexer.nextToken();\n                sqlExpr = new SQLBooleanExpr(false);\n                break;\n            case BITS: {\n                String strVal = lexer.stringVal();\n                lexer.nextToken();\n                sqlExpr = new SQLBinaryExpr(strVal);\n                break;\n            }\n            case GLOBAL:\n            case CONTAINS:\n                sqlExpr = inRest(null);\n                break;\n            case SET: {\n                Lexer.SavePoint savePoint = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token == Token.SET && dialectFeatureEnabled(PrimaryTwoConsecutiveSet)) {\n                    lexer.nextToken();\n                }\n                if (lexer.token() == Token.LPAREN) {\n                    sqlExpr = new SQLIdentifierExpr(\"SET\");\n                } else if (lexer.token == Token.DOT) {\n                    sqlExpr = new SQLIdentifierExpr(\"SET\");\n                    sqlExpr = this.primaryRest(sqlExpr);\n                } else {\n                    lexer.reset(savePoint);\n                    throw new ParserException(\"ERROR. \" + lexer.info());\n                }\n                break;\n            }\n            case LBRACE: {\n                sqlExpr = primaryLBrace();\n                break;\n            }\n            case VALUES:\n            case TRIGGER:\n            case FOR:\n            case CHECK:\n            case DELETE:\n            case BY:\n            case UPDATE:\n            case LOOP:\n            case LIKE:\n            case UNION:\n            case CREATE:\n            case COMMA:\n            case STAR:\n            case DIV:\n            case DISTRIBUTE:\n            case UNIQUE:\n            case PROCEDURE:\n            case REFERENCES:\n            case IS:\n            case REVOKE:\n            case DECLARE:\n            case DROP:\n            case RLIKE:\n            case FOREIGN:\n            case FETCH:\n            case ASC:\n            case CURSOR:\n            case ALTER:\n                sqlExpr = primaryCommon(sqlExpr);\n                break;\n            case AS: {\n                sqlExpr = primaryAs(sqlExpr);\n                break;\n            }\n            case DISTINCT:\n                sqlExpr = primaryDistinct(sqlExpr);\n                break;\n            case BETWEEN:\n            case IN:\n                sqlExpr = primaryIn(sqlExpr);\n                break;\n            case LBRACKET:\n                SQLArrayExpr arrayTmp = new SQLArrayExpr();\n                lexer.nextToken();\n                this.exprList(arrayTmp.getValues(), arrayTmp);\n                accept(Token.RBRACKET);\n                sqlExpr = arrayTmp;\n                break;\n            case ON:\n                sqlExpr = primaryOn(sqlExpr);\n                break;\n            case COLONCOLON:\n                sqlExpr = primaryColonColon(sqlExpr);\n                break;\n            case ARRAY: {\n                SQLArrayExpr array = new SQLArrayExpr();\n                array.setExpr(new SQLIdentifierExpr(\"ARRAY\"));\n                lexer.nextToken();\n                if (lexer.nextIf(Token.LT)) {\n                    SQLDataType sqlDataType = this.parseDataType();\n                    array.setDataType(sqlDataType);\n                    accept(Token.GT);\n                }\n                if (lexer.nextIf(Token.LBRACKET)) {\n                    this.exprList(array.getValues(), array);\n                    accept(Token.RBRACKET);\n                } else {\n                    throw new ParserException(\"Syntax error. \" + lexer.info());\n                }\n\n                sqlExpr = array;\n                break;\n            }\n            case LITERAL_TEXT_BLOCK:\n                sqlExpr = new SQLCharExpr(lexer.stringVal());\n                lexer.nextToken();\n                break;\n            default:\n                throw new ParserException(\"ERROR. \" + lexer.info());\n        }\n\n        SQLExpr expr = primaryRest(sqlExpr);\n\n        if (beforeComments != null) {\n            expr.addBeforeComment(beforeComments);\n        }\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n             expr.addAfterComment(lexer.readAndResetComments());\n        }\n        return expr;\n    }\n\n    private SQLExpr primaryLParen() {\n        lexer.nextToken();\n        if (lexer.token == Token.RPAREN) {\n            lexer.nextToken();\n            return new SQLMethodInvokeExpr();\n        }\n\n        SQLExpr sqlExpr = expr();\n\n        if (lexer.token == Token.COMMA) {\n            SQLListExpr listExpr = new SQLListExpr();\n            listExpr.addItem(sqlExpr);\n            do {\n                lexer.nextToken();\n                listExpr.addItem(expr());\n            } while (lexer.token == Token.COMMA);\n\n            sqlExpr = listExpr;\n        }\n        if (sqlExpr instanceof SQLExprImpl) {\n            ((SQLExprImpl) sqlExpr).setParenthesized(true);\n        }\n\n        if ((lexer.token == Token.UNION || lexer.token == Token.MINUS || lexer.token == Token.EXCEPT)\n                && sqlExpr instanceof SQLQueryExpr) {\n            SQLQueryExpr queryExpr = (SQLQueryExpr) sqlExpr;\n\n            SQLSelectQuery query = this.createSelectParser().queryRest(queryExpr.getSubQuery().getQuery(), true);\n            queryExpr.getSubQuery().setQuery(query);\n        }\n\n        accept(Token.RPAREN);\n        return sqlExpr;\n    }\n\n    private SQLExpr primaryIdentifier() {\n        String ident = lexer.stringVal();\n        long hash_lower = lexer.hashLCase();\n\n        int sourceLine = -1, sourceColumn = -1;\n        if (lexer.keepSourceLocation) {\n            lexer.computeRowAndColumn();\n            sourceLine = lexer.posLine;\n            sourceColumn = lexer.posColumn;\n        }\n\n        lexer.nextToken();\n        if (lexer.identifierEquals(\"COLLATE\")) {\n            acceptIdentifier(\"COLLATE\");\n            String collateValue = lexer.stringVal();\n            if (lexer.token == Token.IDENTIFIER || lexer.token == Token.LITERAL_ALIAS || lexer.token == Token.LITERAL_CHARS) {\n                SQLIdentifierExpr identifierExpr = new SQLIdentifierExpr(ident);\n                identifierExpr.setCollate(collateValue);\n                lexer.nextToken();\n                return identifierExpr;\n            }\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n\n        if (hash_lower == FnvHash.Constants.TRY_CAST) {\n            accept(Token.LPAREN);\n            SQLCastExpr cast = new SQLCastExpr();\n            cast.setTry(true);\n            cast.setExpr(expr());\n            accept(Token.AS);\n            cast.setDataType(parseDataType(false));\n            accept(Token.RPAREN);\n            return cast;\n        }\n\n        if (hash_lower == FnvHash.Constants.DATE\n                && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)\n                && (dialectFeatureEnabled(SQLDateExpr))) {\n            String literal = lexer.token == Token.LITERAL_CHARS ? lexer.stringVal() : \"?\";\n            lexer.nextToken();\n            SQLDateExpr dateExpr = new SQLDateExpr();\n            dateExpr.setValue(literal);\n            return dateExpr;\n        }\n\n        if (hash_lower == FnvHash.Constants.TIMESTAMP\n                && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)\n                && dialectFeatureEnabled(SQLTimestampExpr)) {\n            SQLTimestampExpr dateExpr = new SQLTimestampExpr(lexer.stringVal());\n            lexer.nextToken();\n            return dateExpr;\n        }\n\n        if (hash_lower == FnvHash.Constants.TIME\n                && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)) {\n            SQLTimeExpr dateExpr = new SQLTimeExpr(lexer.stringVal());\n            lexer.nextToken();\n            return dateExpr;\n        }\n        if (hash_lower == FnvHash.Constants.TIME && lexer.token == Token.LITERAL_ALIAS) {\n            SQLTimeExpr dateExpr = new SQLTimeExpr(SQLUtils.normalize(lexer.stringVal()));\n            lexer.nextToken();\n            return dateExpr;\n        }\n\n        if (hash_lower == FnvHash.Constants.DATETIME\n                && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)) {\n            SQLDateTimeExpr dateExpr = new SQLDateTimeExpr(lexer.stringVal());\n            lexer.nextToken();\n            return dateExpr;\n        }\n        if (hash_lower == FnvHash.Constants.DATETIME && lexer.token == Token.LITERAL_ALIAS) {\n            SQLDateTimeExpr dateExpr = new SQLDateTimeExpr(SQLUtils.normalize(lexer.stringVal()));\n            lexer.nextToken();\n            return dateExpr;\n        }\n\n        if (hash_lower == FnvHash.Constants.BOOLEAN && lexer.token == Token.LITERAL_CHARS) {\n            SQLExpr sqlExpr = new SQLBooleanExpr(Boolean.valueOf(lexer.stringVal()));\n            lexer.nextToken();\n            return sqlExpr;\n        }\n        if (hash_lower == FnvHash.Constants.DATE && lexer.token == Token.LITERAL_ALIAS) {\n            SQLExpr sqlExpr = new SQLDateExpr(lexer.stringVal());\n            lexer.nextToken();\n            return sqlExpr;\n        }\n        if (hash_lower == FnvHash.Constants.DATETIME && lexer.token == Token.LITERAL_ALIAS) {\n            SQLExpr sqlExpr = new SQLDateTimeExpr(lexer.stringVal());\n            lexer.nextToken();\n            return sqlExpr;\n        }\n        if (hash_lower == FnvHash.Constants.TIMESTAMP && lexer.token == Token.LITERAL_ALIAS) {\n            SQLExpr sqlExpr = new SQLTimestampExpr(lexer.stringVal());\n            lexer.nextToken();\n            return sqlExpr;\n        }\n        if (hash_lower == FnvHash.Constants.ARRAY && (lexer.token == Token.LBRACKET || lexer.token == Token.LT)) {\n            return parseArrayExpr(ident);\n        }\n\n        SQLExpr sqlExpr = primaryIdentifierRest(hash_lower, ident);\n        if (sqlExpr != null) {\n            return sqlExpr;\n        }\n\n        char c0 = ident.charAt(0);\n        if (c0 == '`' || c0 == '[' || c0 == '\"') {\n            if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                ident = ident.substring(1, ident.length() - 1);\n            }\n            hash_lower = FnvHash.hashCode64(ident);\n        }\n        SQLIdentifierExpr identifierExpr = new SQLIdentifierExpr(ident, hash_lower);\n        if (sourceLine != -1) {\n            identifierExpr.setSource(sourceLine, sourceColumn);\n        }\n        return identifierExpr;\n    }\n\n    private SQLExpr primaryVariant() {\n        if (lexer.keepSourceLocation) {\n            lexer.computeRowAndColumn();\n        }\n        int line = lexer.getPosLine(), column = lexer.getPosColumn();\n        String varName = lexer.stringVal();\n        lexer.nextToken();\n\n        if (varName.equals(\":\") && lexer.token == Token.IDENTIFIER && dialectFeatureEnabled(PrimaryVariantColon)) {\n            String part2 = lexer.stringVal();\n            lexer.nextToken();\n            varName += part2;\n        }\n\n        SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(varName);\n        varRefExpr.setSource(line, column);\n        if (varName.startsWith(\":\")) {\n            varRefExpr.setIndex(lexer.nextVarIndex());\n        }\n        if (varRefExpr.getName().equals(\"@\")\n                && (lexer.token == Token.LITERAL_CHARS || (lexer.token == Token.VARIANT && lexer.stringVal().startsWith(\"@\")))) {\n            varRefExpr.setName(\"@'\" + lexer.stringVal() + \"'\");\n            lexer.nextToken();\n        } else if (varRefExpr.getName().equals(\"@@\") && lexer.token == Token.LITERAL_CHARS) {\n            varRefExpr.setName(\"@@'\" + lexer.stringVal() + \"'\");\n            lexer.nextToken();\n        }\n        return varRefExpr;\n    }\n\n    private SQLExpr primaryCase() {\n        SQLCaseExpr caseExpr = new SQLCaseExpr();\n        lexer.nextToken();\n        if (lexer.token != Token.WHEN) {\n            caseExpr.setValueExpr(expr());\n        }\n\n        accept(Token.WHEN);\n        SQLExpr testExpr = expr();\n        accept(Token.THEN);\n        SQLExpr valueExpr = expr();\n        SQLCaseExpr.Item caseItem = new SQLCaseExpr.Item(testExpr, valueExpr);\n        caseExpr.addItem(caseItem);\n\n        while (lexer.token == Token.WHEN) {\n            lexer.nextToken();\n            testExpr = expr();\n            accept(Token.THEN);\n            valueExpr = expr();\n            caseItem = new SQLCaseExpr.Item(testExpr, valueExpr);\n            caseExpr.addItem(caseItem);\n        }\n\n        if (lexer.token == Token.ELSE) {\n            lexer.nextToken();\n            caseExpr.setElseExpr(expr());\n        }\n\n        accept(Token.END);\n        return caseExpr;\n    }\n\n    private SQLExpr primaryNot() {\n        lexer.nextToken();\n        if (lexer.token == Token.EXISTS) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            SQLExistsExpr exists = new SQLExistsExpr(createSelectParser().select(), true);\n            accept(Token.RPAREN);\n\n            parseQueryPlanHint(exists);\n            if (lexer.token == Token.EQ) {\n                exists.setNot(false);\n                SQLExpr relational = this.relationalRest(exists);\n                return new SQLNotExpr(relational);\n            }\n            return exists;\n        }\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLExpr notTarget = expr();\n            if (notTarget instanceof SQLBinaryOpExpr) {\n                ((SQLBinaryOpExpr) notTarget).setParenthesized(true);\n            } else if (notTarget instanceof SQLUnaryExpr) {\n                ((SQLUnaryExpr) notTarget).setParenthesized(true);\n            } else if (notTarget instanceof SQLIdentifierExpr) {\n                ((SQLIdentifierExpr) notTarget).setParenthesized(true);\n            }\n            accept(Token.RPAREN);\n            notTarget = bitXorRest(notTarget);\n            notTarget = multiplicativeRest(notTarget);\n            notTarget = additiveRest(notTarget);\n            notTarget = shiftRest(notTarget);\n            notTarget = bitAndRest(notTarget);\n            notTarget = bitOrRest(notTarget);\n            notTarget = inRest(notTarget);\n            notTarget = relationalRest(notTarget);\n            SQLExpr sqlExpr = new SQLNotExpr(notTarget);\n\n            parseQueryPlanHint(sqlExpr);\n            return primaryRest(sqlExpr);\n        }\n\n        SQLExpr restExpr = relational();\n        SQLExpr sqlExpr = new SQLNotExpr(restExpr);\n        parseQueryPlanHint(sqlExpr);\n        return sqlExpr;\n    }\n\n    private SQLExpr primarySub() {\n        lexer.nextToken();\n        switch (lexer.token) {\n            case LITERAL_INT:\n                Number integerValue = lexer.integerValue();\n                if (integerValue instanceof Integer) {\n                    int intVal = integerValue.intValue();\n                    if (intVal == Integer.MIN_VALUE) {\n                        integerValue = Long.valueOf(((long) intVal) * -1);\n                    } else {\n                        integerValue = Integer.valueOf(intVal * -1);\n                    }\n                } else if (integerValue instanceof Long) {\n                    long longVal = ((Long) integerValue).longValue();\n                    if (longVal == 2147483648L) {\n                        integerValue = Integer.valueOf((int) (((long) longVal) * -1));\n                    } else {\n                        integerValue = Long.valueOf(longVal * -1);\n                    }\n                } else {\n                    integerValue = ((BigInteger) integerValue).negate();\n                }\n                SQLExpr sqlExpr = new SQLIntegerExpr(integerValue);\n                lexer.nextToken();\n                return sqlExpr;\n            case LITERAL_FLOAT:\n                sqlExpr = lexer.numberExpr(true);\n                lexer.nextToken();\n                return sqlExpr;\n            case LITERAL_CHARS:\n            case LITERAL_ALIAS:\n                sqlExpr = primarySubLiteralAliasRest();\n                lexer.nextToken();\n\n                if (lexer.token == Token.LPAREN\n                        || lexer.token == Token.LBRACKET\n                        || lexer.token == Token.DOT) {\n                    sqlExpr = primaryRest(sqlExpr);\n                }\n                return new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);\n            case QUES: {\n                SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr(\"?\");\n                variantRefExpr.setIndex(lexer.nextVarIndex());\n                sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, variantRefExpr);\n                lexer.nextToken();\n                return sqlExpr;\n            }\n            case PLUS:\n            case SUB:\n            case LPAREN:\n            case IDENTIFIER:\n            case BANG:\n            case CASE:\n            case CAST:\n            case NULL:\n            case INTERVAL:\n            case LBRACE:\n            case IF:\n            case CHECK:\n            case INDEX:\n            case PRIMARY:\n            case KEY:\n            case REPLACE:\n                sqlExpr = primary();\n\n                while (lexer.token == Token.HINT) {\n                    lexer.nextToken();\n                }\n\n                return new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);\n            case VARIANT:\n                sqlExpr = primary();\n                return new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);\n            default:\n                throw new ParserException(\"unexpected token after unary minus: \" + lexer.token + \". \" + lexer.info());\n        }\n    }\n\n    private SQLExpr primaryPlus() {\n        lexer.nextToken();\n        switch (lexer.token) {\n            case LITERAL_CHARS:\n            case LITERAL_ALIAS:\n                SQLExpr sqlExpr = new SQLIdentifierExpr(lexer.stringVal());\n                sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);\n                lexer.nextToken();\n                return sqlExpr;\n            case QUES: {\n                SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr(\"?\");\n                variantRefExpr.setIndex(lexer.nextVarIndex());\n                sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, variantRefExpr);\n                lexer.nextToken();\n                return sqlExpr;\n            }\n            case PLUS:\n            case SUB:\n            case LITERAL_FLOAT:\n            case LITERAL_INT:\n            case LPAREN:\n            case IDENTIFIER:\n            case BANG:\n            case CASE:\n            case CAST:\n            case NULL:\n            case INTERVAL:\n            case LBRACE:\n            case IF:\n            case CHECK:\n            case REPLACE:\n                sqlExpr = primary();\n\n                while (lexer.token == Token.HINT) {\n                    lexer.nextToken();\n                }\n\n                return new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);\n            default:\n                throw new ParserException(\"unexpected token after unary plus: \" + lexer.token + \". \" + lexer.info());\n        }\n    }\n\n    private SQLExpr primaryLBrace() {\n        lexer.nextToken();\n        SQLExpr sqlExpr;\n        if (lexer.identifierEquals(FnvHash.Constants.TS)) {\n            lexer.nextToken();\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n            sqlExpr = new SQLTimestampExpr(literal);\n        } else if (lexer.identifierEquals(FnvHash.Constants.D)\n                || lexer.identifierEquals(FnvHash.Constants.DATE)\n        ) {\n            lexer.nextToken();\n            String literal = lexer.stringVal();\n            if (literal.length() > 2\n                    && literal.charAt(0) == '\"'\n                    && literal.charAt(literal.length() - 1) == '\"') {\n                literal = literal.substring(1, literal.length() - 1);\n            }\n            lexer.nextToken();\n            sqlExpr = new SQLDateExpr(literal);\n        } else if (lexer.identifierEquals(FnvHash.Constants.T)) {\n            lexer.nextToken();\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n            sqlExpr = new SQLTimeExpr(literal);\n        } else if (lexer.identifierEquals(FnvHash.Constants.FN)) {\n            lexer.nextToken();\n            sqlExpr = this.expr();\n        } else if (dialectFeatureEnabled(PrimaryLbraceOdbcEscape)) {\n            sqlExpr = this.expr(); // {identifier expr} is ODBC escape syntax and is accepted for ODBC compatibility.\n        } else if (lexer.nextIf(LBRACE)) {\n            // support dbt style: {{ source(a,b) }} as identifier\n            sqlExpr = new SQLPatternExpr(this.expr());\n            // skip }\n            accept(RBRACE);\n        } else {\n            throw new ParserException(\"ERROR. \" + lexer.info());\n        }\n        accept(Token.RBRACE);\n        return sqlExpr;\n    }\n\n    protected SQLExpr parseArrayExpr(String ident) {\n        SQLExpr sqlExpr;\n        SQLArrayExpr array = new SQLArrayExpr();\n        array.setExpr(new SQLIdentifierExpr(ident));\n        if (lexer.nextIf(Token.LT)) {\n            SQLDataType sqlDataType = this.parseDataType();\n            array.setDataType(sqlDataType);\n            accept(Token.GT);\n        }\n\n        if (lexer.nextIf(Token.LBRACKET)) {\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n        } else {\n            throw new ParserException(\"Syntax error. \" + lexer.info());\n        }\n        sqlExpr = array;\n        return sqlExpr;\n    }\n\n    protected SQLExpr parseCast() {\n        String castStr = lexer.stringVal();\n        lexer.nextToken();\n\n        if (lexer.token != Token.LPAREN) {\n            return new SQLIdentifierExpr(castStr);\n        } else {\n            lexer.nextToken();\n            SQLCastExpr cast = new SQLCastExpr();\n            cast.setExpr(\n                    expr());\n            accept(Token.AS);\n            cast.setDataType(\n                    parseDataType(false));\n            if (cast.getDataType() instanceof SQLArrayDataType) {\n                SQLArrayDataType arrayDataType = (SQLArrayDataType) cast.getDataType();\n                if (arrayDataType.getDbType() == null) {\n                    arrayDataType.setDbType(dbType);\n                }\n                arrayDataType.setUsedForCast(true);\n            }\n            cast = parseCastFormat(cast);\n            accept(Token.RPAREN);\n            return cast;\n        }\n    }\n\n    protected SQLCastExpr parseCastFormat(SQLCastExpr cast) {\n        return cast;\n    }\n\n    protected SQLExpr parseQueryExpr() {\n        return new SQLQueryExpr(\n                createSelectParser()\n                        .select());\n    }\n\n    protected SQLExpr parseAll() {\n        SQLExpr sqlExpr;\n        String str = lexer.stringVal();\n        lexer.nextToken();\n        switch (lexer.token) {\n            case DOT:\n            case SLASH:\n            case EQ:\n            case GT:\n            case GTEQ:\n            case LT:\n            case LTEQ:\n            case STAR:\n            case DIV:\n                return primaryRest(new SQLIdentifierExpr(str));\n            case COMMA:\n            case PLUS:\n            case SUB:\n            case RPAREN:\n            case WHERE:\n            case GROUP:\n            case SEMI:\n            case AS:\n            case FROM:\n            case ORDER:\n            case LIMIT:\n            case UNION:\n                return new SQLIdentifierExpr(str);\n            case IDENTIFIER:\n                if (dialectFeatureEnabled(ParseAllIdentifier)) {\n                    return new SQLIdentifierExpr(str);\n                }\n                break;\n            default:\n                break;\n        }\n\n        SQLAllExpr allExpr = new SQLAllExpr();\n\n        accept(Token.LPAREN);\n        if (lexer.token != Token.SELECT && lexer.token != Token.VALUES && lexer.token != Token.LPAREN) {\n            SQLExpr expr = this.expr();\n            SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(\"ALL\");\n            methodInvokeExpr.addArgument(expr);\n            while (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                methodInvokeExpr.addArgument(expr());\n            }\n            accept(Token.RPAREN);\n            return methodInvokeExpr;\n        }\n        SQLSelect allSubQuery = createSelectParser().select();\n        allExpr.setSubQuery(allSubQuery);\n        accept(Token.RPAREN);\n\n        allSubQuery.setParent(allExpr);\n\n        sqlExpr = allExpr;\n        return sqlExpr;\n    }\n\n    protected SQLExpr parseSome() {\n        SQLExpr sqlExpr;\n\n        String str = lexer.stringVal();\n        lexer.nextToken();\n        if (lexer.token != Token.LPAREN) {\n            return new SQLIdentifierExpr(str);\n        }\n        lexer.nextToken();\n\n        if (lexer.token != Token.SELECT && lexer.token != Token.VALUES && lexer.token != Token.LPAREN) {\n            SQLExpr expr = this.expr();\n            SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(\"SOME\");\n            methodInvokeExpr.addArgument(expr);\n            while (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                methodInvokeExpr.addArgument(expr());\n            }\n            accept(Token.RPAREN);\n            return methodInvokeExpr;\n        }\n\n        SQLSomeExpr someExpr = new SQLSomeExpr();\n        SQLSelect someSubQuery = createSelectParser().select();\n        someExpr.setSubQuery(someSubQuery);\n        accept(Token.RPAREN);\n\n        someSubQuery.setParent(someExpr);\n\n        sqlExpr = someExpr;\n        return sqlExpr;\n    }\n\n    protected SQLExpr parseAny() {\n        SQLExpr sqlExpr;\n        lexer.nextToken();\n        if (lexer.token == Token.LPAREN) {\n            accept(Token.LPAREN);\n\n            if (lexer.token != Token.SELECT && lexer.token != Token.VALUES && lexer.token != Token.LPAREN) {\n                SQLExpr expr = this.expr();\n                SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(\"ANY\");\n                methodInvokeExpr.addArgument(expr);\n                while (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    methodInvokeExpr.addArgument(expr());\n                }\n                accept(Token.RPAREN);\n                return methodInvokeExpr;\n            }\n\n            SQLSelect anySubQuery = createSelectParser().select();\n            SQLAnyExpr anyExpr = new SQLAnyExpr(anySubQuery);\n            accept(Token.RPAREN);\n\n            sqlExpr = anyExpr;\n        } else {\n            sqlExpr = new SQLIdentifierExpr(\"ANY\");\n        }\n        return sqlExpr;\n    }\n\n    protected SQLExpr parseAliasExpr(String alias) {\n        return new SQLIdentifierExpr(alias);\n    }\n\n    protected SQLExpr parseInterval() {\n        String str = lexer.stringVal();\n        accept(Token.INTERVAL);\n        switch (lexer.token) {\n            case COMMA:\n            case IS:\n            case BETWEEN:\n            case IN:\n            case RPAREN:\n            case EQ:\n            case BANGEQ:\n            case LTGT:\n            case LT:\n            case LTEQ:\n            case GT:\n            case GTEQ:\n            case STAR:\n            case DIV:\n            case SLASH:\n            case DOT:\n            case FROM:\n            case ORDER:\n            case THEN:\n            case END:\n            case AS:\n            case UNION:\n            case SEMI:\n            case ASC:\n            case DESC:\n            case ELSE:\n                return new SQLIdentifierExpr(str);\n            case PLUS:\n            case SUB: {\n                break;\n            }\n            default:\n                if (lexer.identifierEquals(FnvHash.Constants.GROUPING)) {\n                    return new SQLIdentifierExpr(str);\n                }\n                break;\n        }\n\n        SQLExpr value = expr();\n\n        if (value instanceof SQLCharExpr) {\n            String literal = ((SQLCharExpr) value).getText();\n            int space = literal.indexOf(' ');\n            if (space != -1) {\n                int intervalValue = Integer.valueOf(literal.substring(0, space));\n                String unitStr = literal.substring(space + 1).toUpperCase();\n                SQLIntervalUnit unit = SQLIntervalUnit.of(unitStr);\n                return new SQLIntervalExpr(new SQLIntegerExpr(intervalValue), unit);\n            }\n        }\n\n        if (lexer.token() != Token.IDENTIFIER) {\n            throw new ParserException(\"Syntax error. \" + lexer.info());\n        }\n\n        String unit = lexer.stringVal().toUpperCase();\n        lexer.nextToken();\n\n        SQLIntervalExpr intervalExpr = new SQLIntervalExpr();\n        intervalExpr.setValue(value);\n        intervalExpr.setUnit(SQLIntervalUnit.of(unit));\n\n        return intervalExpr;\n    }\n\n    public SQLSelectParser createSelectParser() {\n        return new SQLSelectParser(this);\n    }\n\n    public SQLExpr primaryRest(SQLExpr expr) {\n        if (expr == null) {\n            throw new ParserException(\"expr\" + \", \" + lexer.info());\n        }\n\n        Token token = lexer.token;\n        if (token == Token.OF) {\n            if (expr instanceof SQLIdentifierExpr) {\n                long hashCode64 = ((SQLIdentifierExpr) expr).hashCode64();\n                if (hashCode64 == FnvHash.Constants.CURRENT) {\n                    lexer.nextToken();\n                    SQLName cursorName = this.name();\n                    return new SQLCurrentOfCursorExpr(cursorName);\n                }\n            }\n        } else if (token == Token.FOR) {\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr idenExpr = (SQLIdentifierExpr) expr;\n                if (idenExpr.hashCode64() == FnvHash.Constants.NEXTVAL) {\n                    lexer.nextToken();\n                    SQLName seqName = this.name();\n                    SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.NextVal);\n                    return seqExpr;\n                } else if (idenExpr.hashCode64() == FnvHash.Constants.CURRVAL) {\n                    lexer.nextToken();\n                    SQLName seqName = this.name();\n                    SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.CurrVal);\n                    return seqExpr;\n                } else if (idenExpr.hashCode64() == FnvHash.Constants.PREVVAL) {\n                    lexer.nextToken();\n                    SQLName seqName = this.name();\n                    SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.PrevVal);\n                    return seqExpr;\n                }\n            }\n        } else if (token == Token.LBRACKET) {\n            SQLArrayExpr array = new SQLArrayExpr();\n            array.setExpr(expr);\n            lexer.nextToken();\n            this.exprList(array.getValues(), array);\n            accept(Token.RBRACKET);\n            expr = array;\n            return primaryRest(expr);\n        } else if (token == Token.DOT) {\n            lexer.nextToken();\n\n            if (expr instanceof SQLCharExpr) {\n                String text = ((SQLCharExpr) expr).getText();\n                expr = new SQLIdentifierExpr(text);\n            }\n\n            if (expr instanceof SQLDefaultExpr) {\n                expr = new SQLIdentifierExpr(expr.toString());\n            }\n\n            expr = dotRest(expr);\n            return primaryRest(expr);\n        } else if (lexer.identifierEquals(FnvHash.Constants.SETS) //\n                && expr.getClass() == SQLIdentifierExpr.class //\n                && \"GROUPING\".equalsIgnoreCase(((SQLIdentifierExpr) expr).getName())) {\n            SQLGroupingSetExpr groupingSets = new SQLGroupingSetExpr();\n            lexer.nextToken();\n\n            accept(Token.LPAREN);\n\n            for (; ; ) {\n                SQLExpr item;\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    if (lexer.token == Token.COMMA && dialectFeatureEnabled(PrimaryRestCommaAfterLparen)) {\n                        lexer.nextToken();\n                    }\n\n                    SQLListExpr listExpr = new SQLListExpr();\n                    this.exprList(listExpr.getItems(), listExpr);\n                    item = listExpr;\n\n                    accept(Token.RPAREN);\n                } else {\n                    item = this.expr();\n                }\n\n                item.setParent(groupingSets);\n                groupingSets.addParameter(item);\n\n                if (lexer.token == Token.RPAREN) {\n                    break;\n                }\n\n                accept(Token.COMMA);\n            }\n\n            this.exprList(groupingSets.getParameters(), groupingSets);\n\n            accept(Token.RPAREN);\n\n            return groupingSets;\n        } else if (lexer.token == Token.LITERAL_CHARS && expr instanceof SQLIdentifierExpr && ((SQLIdentifierExpr) expr).hashCode64() == FnvHash.Constants.DECIMAL) {\n            expr = new SQLDecimalExpr(lexer.stringVal());\n            lexer.nextToken();\n        } else {\n            if (lexer.token == Token.LPAREN &&\n                    !(expr instanceof SQLIntegerExpr) && !(expr instanceof SQLHexExpr) && !(expr instanceof SQLVariantRefExpr)\n            ) {\n                SQLExpr method = methodRest(expr, true);\n                if (lexer.token == Token.LBRACKET || lexer.token == Token.DOT) {\n                    method = primaryRest(method);\n                }\n                return method;\n            }\n        }\n\n        return expr;\n    }\n\n    protected SQLExpr parseExtract() {\n        throw new ParserException(\"not supported.\");\n    }\n\n    protected SQLExpr parsePosition() {\n        throw new ParserException(\"not supported.\");\n    }\n\n    protected SQLExpr parseMatch() {\n        SQLMatchAgainstExpr matchAgainstExpr = new SQLMatchAgainstExpr();\n\n        if (lexer.token() == Token.RPAREN) {\n            lexer.nextToken();\n        } else {\n            exprList(matchAgainstExpr.getColumns(), matchAgainstExpr);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.AGAINST)) {\n            lexer.nextToken();\n        }\n\n        accept(Token.LPAREN);\n        SQLExpr against = primary();\n        matchAgainstExpr.setAgainst(against);\n\n        if (lexer.token() == Token.IN) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.NATURAL)) {\n                lexer.nextToken();\n                acceptIdentifier(\"LANGUAGE\");\n                acceptIdentifier(\"MODE\");\n                if (lexer.token() == Token.WITH) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"QUERY\");\n                    acceptIdentifier(\"EXPANSION\");\n                    matchAgainstExpr.setSearchModifier(SQLMatchAgainstExpr.SearchModifier.IN_NATURAL_LANGUAGE_MODE_WITH_QUERY_EXPANSION);\n                } else {\n                    matchAgainstExpr.setSearchModifier(SQLMatchAgainstExpr.SearchModifier.IN_NATURAL_LANGUAGE_MODE);\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.BOOLEAN)) {\n                lexer.nextToken();\n                acceptIdentifier(\"MODE\");\n                matchAgainstExpr.setSearchModifier(SQLMatchAgainstExpr.SearchModifier.IN_BOOLEAN_MODE);\n            } else {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n        } else if (lexer.token() == Token.WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"QUERY\");\n            acceptIdentifier(\"EXPANSION\");\n            matchAgainstExpr.setSearchModifier(SQLMatchAgainstExpr.SearchModifier.WITH_QUERY_EXPANSION);\n        }\n\n        accept(Token.RPAREN);\n\n        return primaryRest(matchAgainstExpr);\n    }\n\n    protected SQLExpr methodRestAllowIdentifierMethodSpecific(String methodName, long hash_lower, SQLMethodInvokeExpr methodInvokeExpr) {\n        return null;\n    }\n\n    protected void methodRestUsing(SQLMethodInvokeExpr methodInvokeExpr) {\n    }\n    protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) {\n        if (acceptLPAREN) {\n            accept(Token.LPAREN);\n        }\n\n        boolean distinct = false;\n        if (lexer.token == Token.DISTINCT) {\n            lexer.nextToken();\n            distinct = true;\n\n            if (lexer.token == Token.RPAREN || lexer.token == Token.COMMA) {\n                throw new ParserException(lexer.info());\n            }\n        }\n\n        String methodName = null;\n        String aggMethodName = null;\n        SQLMethodInvokeExpr methodInvokeExpr = null;\n        SQLExpr owner = null;\n        String trimOption = null;\n\n        long hash_lower = 0L;\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            methodName = identifierExpr.getName();\n            hash_lower = identifierExpr.nameHashCode64();\n\n            if (allowIdentifierMethod) {\n                if (hash_lower == FnvHash.Constants.TRIM) {\n                    if (lexer.identifierEquals(FnvHash.Constants.LEADING)) {\n                        trimOption = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.identifierEquals(FnvHash.Constants.BOTH)) {\n                        trimOption = lexer.stringVal();\n                        lexer.nextToken();\n                    } else if (lexer.identifierEquals(FnvHash.Constants.TRAILING)) {\n                        trimOption = lexer.stringVal();\n                        lexer.nextToken();\n                    }\n                } else if (hash_lower == FnvHash.Constants.TRY_CAST) {\n                    SQLCastExpr cast = new SQLCastExpr();\n                    cast.setTry(true);\n                    cast.setExpr(expr());\n                    accept(Token.AS);\n                    cast.setDataType(parseDataType(false));\n                    accept(Token.RPAREN);\n                    return cast;\n                } else {\n                    SQLExpr resultExpr = methodRestAllowIdentifierMethodSpecific(methodName, hash_lower, methodInvokeExpr);\n                    if (resultExpr != null) {\n                        return resultExpr;\n                    }\n                }\n            }\n\n            if (distinct) {\n                aggMethodName = methodName;\n            } else {\n                aggMethodName = getAggregateFunction(hash_lower);\n            }\n        } else if (expr instanceof SQLPropertyExpr) {\n            methodName = ((SQLPropertyExpr) expr).getSimpleName();\n            aggMethodName = SQLUtils.normalize(methodName);\n            hash_lower = FnvHash.fnv1a_64_lower(aggMethodName);\n            aggMethodName = getAggregateFunction(hash_lower);\n\n            owner = ((SQLPropertyExpr) expr).getOwner();\n        } else if (expr instanceof SQLDefaultExpr) {\n            methodName = \"DEFAULT\";\n        } else if (expr instanceof SQLCharExpr) {\n            methodName = ((SQLCharExpr) expr).getText();\n            if (isAggregateFunction(methodName)) {\n                aggMethodName = methodName;\n            }\n        } else if (expr instanceof SQLDbLinkExpr) {\n            SQLDbLinkExpr dbLinkExpr = (SQLDbLinkExpr) expr;\n            methodName = dbLinkExpr.toString();\n        }\n\n        if (aggMethodName != null) {\n            SQLAggregateExpr aggregateExpr = parseAggregateExpr(methodName);\n            if (distinct) {\n                aggregateExpr.setOption(SQLAggregateOption.DISTINCT);\n            }\n\n            if (lexer.token == Token.COLONCOLON) {\n                return primaryRest(aggregateExpr);\n            }\n\n            return primaryRest(aggregateExpr);\n        }\n\n        methodInvokeExpr = new SQLMethodInvokeExpr(methodName, hash_lower);\n        if (lexer.keepSourceLocation) {\n            int line, column;\n            if (lexer.keepSourceLocation) {\n                lexer.computeRowAndColumn();\n            }\n            if (expr instanceof SQLObjectImpl) {\n                line = expr.getSourceLine();\n                column = expr.getSourceColumn();\n            } else {\n                line = lexer.getPosLine();\n                column = lexer.getPosColumn();\n            }\n            methodInvokeExpr.setSource(line, column);\n        }\n        if (owner != null) {\n            methodInvokeExpr.setOwner(owner);\n        }\n        if (trimOption != null) {\n            methodInvokeExpr.setTrimOption(trimOption);\n        }\n\n        Token token = lexer.token;\n        if (\"XMLSERIALIZE\".equals(methodName) && lexer.identifierEquals(\"CONTENT\")) {\n            SQLExpr contentExpr = expr();\n            methodInvokeExpr.setContent(contentExpr);\n        }\n        if (\"XMLELEMENT\".equals(methodName) && lexer.identifierEquals(\"NAME\")) {\n            Lexer.SavePoint mark = lexer.markOut();\n            lexer.nextToken(); // Skip NAME if it is a keyword\n            if (lexer.token != Token.IDENTIFIER) {\n                // No other identifier name comes after NAME, so NAME itself is\n                // the xml element name. Reset lexer to NAME\n                lexer.reset(mark);\n            }\n        }\n        if (token != Token.RPAREN && token != Token.FROM) {\n            exprList(methodInvokeExpr.getArguments(), methodInvokeExpr);\n            if (lexer.token == Token.RPAREN) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token == Token.LPAREN) {\n                    //for clickhouse parametric functions\n                    //处理类似偏函数的语法 func(x,y)(a,b,c)\n                    lexer.nextToken();\n                    SQLParametricMethodInvokeExpr parametricExpr =\n                            new SQLParametricMethodInvokeExpr(methodName, hash_lower);\n                    methodInvokeExpr.cloneTo(parametricExpr);\n                    methodInvokeExpr = parametricExpr;\n                    exprList(((SQLParametricMethodInvokeExpr) methodInvokeExpr).getSecondArguments(), methodInvokeExpr);\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n        }\n\n        if (hash_lower == FnvHash.Constants.EXIST\n                && methodInvokeExpr.getArguments().size() == 1\n                && methodInvokeExpr.getArguments().get(0) instanceof SQLQueryExpr) {\n            throw new ParserException(\"exists syntax error.\");\n        }\n\n        if (lexer.token == Token.FROM) {\n            lexer.nextToken();\n            SQLExpr from = this.expr();\n            methodInvokeExpr.setFrom(from);\n\n            if (lexer.token == Token.FOR) {\n                lexer.nextToken();\n                SQLExpr forExpr = expr();\n                methodInvokeExpr.setFor(forExpr);\n            }\n        }\n\n        if (lexer.token == Token.USING || lexer.identifierEquals(FnvHash.Constants.USING)) {\n            lexer.nextToken();\n            SQLExpr using;\n            if (lexer.token == Token.STAR) {\n                lexer.nextToken();\n                using = new SQLAllColumnExpr();\n            } else if (lexer.token == Token.BINARY) {\n                using = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else {\n                using = this.primary();\n            }\n            methodInvokeExpr.setUsing(using);\n        }\n\n        // mysql\n        if (hash_lower == FnvHash.Constants.WEIGHT_STRING) {\n            if (lexer.token == Token.AS) {\n                lexer.nextToken();\n                SQLDataType as = this.parseDataType();\n                methodInvokeExpr.putAttribute(\"as\", as);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LEVEL)) {\n                lexer.nextToken();\n                List<SQLSelectOrderByItem> levels = new ArrayList<SQLSelectOrderByItem>();\n                for (; ; ) {\n                    SQLSelectOrderByItem level = this.parseSelectOrderByItem();\n                    levels.add(level);\n                    if (lexer.token == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                methodInvokeExpr.putAttribute(\"levels\", levels);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.REVERSE)) {\n                lexer.nextToken();\n                methodInvokeExpr.putAttribute(\"reverse\", true);\n            }\n        }\n\n        if (lexer.token == Token.AS || lexer.identifierEquals(FnvHash.Constants.AS)) {\n            lexer.nextToken();\n            final SQLExpr as = this.primary();\n            methodInvokeExpr.setAs(as);\n        }\n        SQLAggregateExpr aggregateExpr = null;\n        if (lexer.token == Token.ORDER) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            aggregateExpr = new SQLAggregateExpr(methodName);\n            aggregateExpr.getArguments().addAll(methodInvokeExpr.getArguments());\n\n            SQLOrderBy orderBy = new SQLOrderBy();\n            this.orderBy(orderBy.getItems(), orderBy);\n            aggregateExpr.setOrderBy(orderBy);\n        }\n\n        accept(Token.RPAREN);\n\n        methodRestUsing(methodInvokeExpr);\n\n        if (lexer.identifierEquals(FnvHash.Constants.FILTER)) {\n            if (aggregateExpr == null) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                Token nextToken = lexer.token;\n                lexer.reset(mark);\n\n                if (nextToken == Token.LPAREN) {\n                    aggregateExpr = new SQLAggregateExpr(methodName);\n                    aggregateExpr.getArguments().addAll(methodInvokeExpr.getArguments());\n                    filter(aggregateExpr);\n                }\n            } else {\n                filter(aggregateExpr);\n            }\n        }\n\n        if (lexer.token == Token.OVER) {\n            if (aggregateExpr == null) {\n                aggregateExpr = new SQLAggregateExpr(methodName);\n                aggregateExpr.addArguments(methodInvokeExpr.getArguments());\n            }\n            over(aggregateExpr);\n        }\n\n        if (aggregateExpr != null) {\n            return primaryRest(aggregateExpr);\n        }\n\n        if (lexer.token == Token.LPAREN) {\n            return methodInvokeExpr;\n        }\n\n        return primaryRest(methodInvokeExpr);\n\n        //throw new ParserException(\"not support token:\" + lexer.token + \", \" + lexer.info());\n    }\n\n    protected String doRestSpecific(SQLExpr expr) {\n        return null;\n    }\n\n    protected void aliasedItems(List<SQLAliasedExpr> items, SQLObject parent) {\n        while (true) {\n            SQLAliasedExpr aliasedExpr = aliasedExpr();\n            aliasedExpr.setParent(parent);\n            items.add(aliasedExpr);\n\n            if (lexer.nextIfComma()) {\n                if (lexer.token() == Token.FROM || lexer.token() == Token.RPAREN) {\n                    break;\n                }\n                continue;\n            }\n            break;\n        }\n    }\n\n    public SQLAliasedExpr aliasedExpr() {\n        return new SQLAliasedExpr(expr(), as());\n    }\n\n    protected SQLExpr dotRest(SQLExpr expr) {\n        if (lexer.nextIf(STAR)) {\n            SQLAllColumnExpr allColumnExpr = new SQLAllColumnExpr();\n            allColumnExpr.setOwner(expr);\n            if (lexer.nextIf(EXCEPT)) {\n                accept(Token.LPAREN);\n                List<SQLExpr> except = new ArrayList<>();\n                this.exprList(except, allColumnExpr);\n                allColumnExpr.setExcept(except);\n                accept(Token.RPAREN);\n            }\n            if (lexer.nextIf(REPLACE)) {\n                accept(Token.LPAREN);\n                this.aliasedItems(allColumnExpr.getReplace(), allColumnExpr);\n                accept(Token.RPAREN);\n            }\n            expr = allColumnExpr;\n        } else {\n            String name;\n            long hash_lower = 0L;\n\n            if (lexer.token == Token.IDENTIFIER) {\n                name = lexer.stringVal();\n                hash_lower = lexer.hashLCase;\n                lexer.nextToken();\n\n                if (hash_lower == FnvHash.Constants.NEXTVAL) {\n                    expr = new SQLSequenceExpr((SQLName) expr, SQLSequenceExpr.Function.NextVal);\n                    return primaryRest(expr);\n                } else if (hash_lower == FnvHash.Constants.CURRVAL) {\n                    expr = new SQLSequenceExpr((SQLName) expr, SQLSequenceExpr.Function.CurrVal);\n                    return primaryRest(expr);\n                } else if (hash_lower == FnvHash.Constants.PREVVAL) {\n                    expr = new SQLSequenceExpr((SQLName) expr, SQLSequenceExpr.Function.PrevVal);\n                    return primaryRest(expr);\n                }\n            } else if (lexer.token == Token.LITERAL_CHARS\n                    || lexer.token == Token.LITERAL_ALIAS) {\n                name = lexer.stringVal();\n                lexer.nextToken();\n            } else if (lexer.getKeywords().containsValue(lexer.token)) {\n                name = lexer.stringVal();\n                lexer.nextToken();\n            } else if (lexer.token == Token.VARIANT && lexer.stringVal().startsWith(\"$\")) {\n                name = lexer.stringVal();\n                lexer.nextToken();\n            } else {\n                name = doRestSpecific(expr);\n                if (name == null) {\n                    throw new ParserException(\"error : \" + lexer.info());\n                }\n            }\n\n            if (lexer.token == Token.LPAREN) {\n                boolean aggregate = hash_lower == FnvHash.Constants.WM_CONCAT\n                        && expr instanceof SQLIdentifierExpr\n                        && ((SQLIdentifierExpr) expr).nameHashCode64() == FnvHash.Constants.WMSYS;\n                expr = methodRest(expr, name, aggregate);\n            } else {\n                if (name.length() > 0 && name.charAt(0) == '`') {\n                    if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                        name = name.substring(1, name.length() - 1);\n                    }\n                    hash_lower = FnvHash.hashCode64(name);\n                }\n\n                expr = new SQLPropertyExpr(expr, name, hash_lower);\n            }\n        }\n\n        expr = primaryRest(expr);\n        return expr;\n    }\n\n    private SQLExpr methodRest(SQLExpr expr, String name, boolean aggregate) {\n        lexer.nextToken();\n\n        if (lexer.token == Token.DISTINCT) {\n            lexer.nextToken();\n\n            SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(name, SQLAggregateOption.DISTINCT);\n            aggregateExpr.setOwner(expr);\n\n            if (lexer.token == Token.RPAREN) {\n                lexer.nextToken();\n            } else {\n                if (lexer.token == Token.PLUS) {\n                    aggregateExpr.getArguments().add(new SQLIdentifierExpr(\"+\"));\n                    lexer.nextToken();\n                } else {\n                    exprList(aggregateExpr.getArguments(), aggregateExpr);\n                }\n                accept(Token.RPAREN);\n            }\n            expr = aggregateExpr;\n        } else if (aggregate) {\n            SQLAggregateExpr methodInvokeExpr = new SQLAggregateExpr(name);\n            methodInvokeExpr.setMethodName(expr.toString() + \".\" + name);\n            if (lexer.token == Token.RPAREN) {\n                lexer.nextToken();\n            } else {\n                if (lexer.token == Token.PLUS) {\n                    methodInvokeExpr.addArgument(new SQLIdentifierExpr(\"+\"));\n                    lexer.nextToken();\n                } else {\n                    exprList(methodInvokeExpr.getArguments(), methodInvokeExpr);\n                }\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token == Token.OVER) {\n                over(methodInvokeExpr);\n            }\n\n            expr = methodInvokeExpr;\n        } else {\n            SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(name);\n            methodInvokeExpr.setOwner(expr);\n            if (lexer.token == Token.RPAREN) {\n                lexer.nextToken();\n            } else {\n                if (lexer.token == Token.PLUS) {\n                    methodInvokeExpr.addArgument(new SQLIdentifierExpr(\"+\"));\n                    lexer.nextToken();\n                } else {\n                    exprList(methodInvokeExpr.getArguments(), methodInvokeExpr);\n                }\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token == Token.OVER) {\n                SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(methodInvokeExpr.getMethodName());\n                aggregateExpr.setOwner(methodInvokeExpr.getOwner());\n                aggregateExpr.getArguments().addAll(methodInvokeExpr.getArguments());\n                over(aggregateExpr);\n                methodInvokeExpr = aggregateExpr;\n            }\n\n            expr = methodInvokeExpr;\n        }\n        return expr;\n    }\n\n    public final SQLExpr groupComparisionRest(SQLExpr expr) {\n        return expr;\n    }\n\n    public final void names(Collection<SQLName> exprCol) {\n        names(exprCol, null);\n    }\n\n    public final void names(Collection<SQLName> exprCol, SQLObject parent) {\n        if (lexer.token == Token.RBRACE) {\n            return;\n        }\n\n        if (lexer.token == Token.EOF) {\n            return;\n        }\n\n        SQLName name = name();\n        name.setParent(parent);\n        exprCol.add(name);\n\n        while (lexer.token == Token.COMMA) {\n            lexer.nextToken();\n\n            if (parent instanceof SQLLateralViewTableSource && lexer.token == Token.NULL) {\n                name = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else {\n                name = name();\n            }\n\n            name.setParent(parent);\n            exprCol.add(name);\n        }\n    }\n\n    @Deprecated\n    public final void exprList(Collection<SQLExpr> exprCol) {\n        exprList(exprCol, null);\n    }\n\n    protected void exprListComma() {\n        lexer.nextToken();\n    }\n\n    public final void exprList(Collection<SQLExpr> exprCol, SQLObject parent) {\n        exprList(exprCol, parent, false);\n    }\n    public final void exprList(Collection<SQLExpr> exprCol, SQLObject parent, boolean isNestDataType) {\n        if (lexer.token == Token.RPAREN\n                || lexer.token == Token.RBRACKET\n                || lexer.token == Token.SEMI) {\n            return;\n        }\n\n        if (lexer.token == Token.EOF) {\n            return;\n        }\n\n        for (; ; ) {\n            SQLExpr expr;\n            if ((lexer.token == Token.ROW || (isNestDataType && lexer.token == IDENTIFIER)) && parent instanceof SQLDataType) {\n                SQLDataType dataType = this.parseDataType();\n                expr = new SQLDataTypeRefExpr(dataType);\n            } else {\n                expr = expr();\n            }\n\n            if (expr != null) {\n                expr.setParent(parent);\n                exprCol.add(expr);\n                // https://github.com/alibaba/druid/issues/5709\n                if (lexer.hasComment()\n                        && lexer.isKeepComments()\n                        && lexer.getComments().size() == 1\n                        && lexer.getComments().get(0).startsWith(\"--\")) {\n                    expr.addAfterComment(lexer.readAndResetComments());\n                }\n            }\n\n            if (lexer.token == Token.COMMA) {\n                exprListComma();\n                continue;\n            }\n            break;\n        }\n    }\n\n    public SQLIdentifierExpr identifier() {\n        SQLName name = name();\n        if (name instanceof SQLIdentifierExpr) {\n            return (SQLIdentifierExpr) name;\n        }\n        throw new ParserException(\"identifier excepted, \" + lexer.info());\n    }\n\n    protected String nameCommon() {\n        throw new ParserException(\"illegal name, \" + lexer.info());\n    }\n\n    public SQLName name() {\n        String identName;\n        long hash = 0;\n        if (lexer.token == Token.LITERAL_ALIAS) {\n            identName = lexer.stringVal();\n            lexer.nextToken();\n        } else if (lexer.token == Token.IDENTIFIER) {\n            identName = lexer.stringVal();\n\n            char c0 = identName.charAt(0);\n            if (c0 != '[') {\n                hash = lexer.hashLCase();\n            }\n            lexer.nextToken();\n        } else if (lexer.token == Token.LITERAL_CHARS) {\n            identName = '\\'' + lexer.stringVal() + '\\'';\n            lexer.nextToken();\n        } else if (lexer.token == Token.VARIANT) {\n            identName = lexer.stringVal();\n            lexer.nextToken();\n        } else {\n            switch (lexer.token) {\n//                case MODEL:\n                case MODE:\n                case ERRORS:\n                case NOWAIT:\n                case COMMIT:\n                case PCTFREE:\n                case INITRANS:\n                case MAXTRANS:\n                case SEGMENT:\n                case CREATION:\n                case IMMEDIATE:\n                case DEFERRED:\n                case STORAGE:\n                case NEXT:\n                case MINEXTENTS:\n                case MAXEXTENTS:\n                case MAXSIZE:\n                case PCTINCREASE:\n                case FLASH_CACHE:\n                case CELL_FLASH_CACHE:\n                case NONE:\n                case LOB:\n                case STORE:\n                case ROW:\n                case CHUNK:\n                case CACHE:\n                case NOCACHE:\n                case LOGGING:\n                case NOCOMPRESS:\n                case KEEP_DUPLICATES:\n                case EXCEPTIONS:\n                case PURGE:\n                case INITIALLY:\n                case END:\n                case COMMENT:\n                case ENABLE:\n                case DISABLE:\n                case SEQUENCE:\n                case USER:\n                case ANALYZE:\n                case OPTIMIZE:\n                case GRANT:\n                case REVOKE:\n                    // binary有很多含义，lexer识别了这个token，实际上应该当做普通IDENTIFIER\n                case BINARY:\n                case OVER:\n                case ORDER:\n                case DO:\n                case INNER:\n                case JOIN:\n                case TYPE:\n                case FUNCTION:\n                case KEY:\n                case UNIQUE:\n                case SCHEMA:\n                case INTERVAL:\n                case EXPLAIN:\n                case SET:\n                case TABLESPACE:\n                case PARTITION:\n                case CLOSE:\n                case INOUT:\n                case GOTO:\n                case DEFAULT:\n                case FULLTEXT:\n                case WITH:\n                case ANY:\n                case BEGIN:\n                case CAST:\n                case COMPUTE:\n                case ESCAPE:\n                case EXCEPT:\n                case FULL:\n                case INTERSECT:\n                case MERGE:\n                case MINUS:\n                case OPEN:\n                case SOME:\n                case TRUNCATE:\n                case UNTIL:\n                case VIEW:\n                case GROUP:\n                case INDEX:\n                case DESC:\n                case ALL:\n                case SHOW:\n                case FOR:\n                case LEAVE:\n                case REPEAT:\n                case LOOP:\n                case IS:\n                case LOCK:\n                case REFERENCES:\n                case EXCEPTION:\n                    identName = lexer.stringVal();\n                    lexer.nextToken();\n                    break;\n                case CONSTRAINT:\n                case CHECK:\n                case VALUES:\n                case IN:\n                case OUT:\n                case LIMIT:\n                case TRIGGER:\n                case USE:\n                case LIKE:\n                case DISTRIBUTE:\n                case DELETE:\n                case UPDATE:\n                case PROCEDURE:\n                case LEFT:\n                case RIGHT:\n                case TABLE:\n                case RLIKE:\n                case CREATE:\n                case PARTITIONED:\n                case UNION:\n                case PRIMARY:\n                case TO:\n                case DECLARE:\n                case AS:\n                case BY:\n                case EXISTS:\n                case FOREIGN:\n                case ALTER:\n                case ASC:\n                case NULL:\n                case CURSOR:\n                case FETCH:\n                case BITMAP:\n                case NGRAMBF:\n                case INVERTED:\n                case DATABASE:\n                    identName = nameCommon();\n                    break;\n                default:\n                    throw new ParserException(\"illegal name, \" + lexer.info());\n            }\n        }\n\n        SQLName identifierExpr = null;\n        if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n            if (identName.indexOf('.') == -1) {\n                identName = SQLUtils.forcedNormalize(identName, dbType);\n                hash = 0;\n            } else {\n                identifierExpr = (SQLName) primaryIdentifierRest(hash, identName);\n            }\n        }\n\n        if (identifierExpr == null) {\n            identifierExpr = new SQLIdentifierExpr(identName, hash);\n        }\n        if (lexer.keepSourceLocation) {\n            lexer.computeRowAndColumn(identifierExpr);\n        }\n\n        SQLName name = identifierExpr;\n\n        name = nameRest(name);\n\n        return name;\n    }\n\n    public SQLName nameRest(SQLName name) {\n        if (lexer.token == Token.DOT) {\n            lexer.nextToken();\n\n            if (lexer.token == Token.KEY) {\n                name = new SQLPropertyExpr(name, \"KEY\");\n                lexer.nextToken();\n                return name;\n            }\n\n            if (lexer.token != Token.LITERAL_ALIAS\n                    && lexer.token != Token.IDENTIFIER\n                    && lexer.token != Token.VARIANT\n                    && lexer.token != Token.LITERAL_CHARS\n                    && (!lexer.getKeywords().containsValue(lexer.token))) {\n                throw new ParserException(\"error, \" + lexer.info());\n            }\n\n            String propertyName;\n            if (lexer.token == Token.LITERAL_CHARS) {\n                propertyName = '\\'' + lexer.stringVal() + '\\'';\n            } else {\n                propertyName = lexer.stringVal();\n            }\n            if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                propertyName = SQLUtils.forcedNormalize(propertyName, dbType);\n            }\n            name = new SQLPropertyExpr(name, propertyName);\n            lexer.nextToken();\n            name = nameRest(name);\n        }\n\n        return name;\n    }\n\n    public boolean isAggregateFunction(String word) {\n        long hash_lower = FnvHash.fnv1a_64_lower(word);\n        return isAggregateFunction(hash_lower);\n    }\n\n    protected boolean isAggregateFunction(long hash_lower) {\n        return Arrays.binarySearch(aggregateFunctionHashCodes, hash_lower) >= 0;\n    }\n\n    protected String getAggregateFunction(long hash_lower) {\n        int index = Arrays.binarySearch(aggregateFunctionHashCodes, hash_lower);\n        if (index < 0) {\n            return null;\n        }\n        return aggregateFunctions[index];\n    }\n\n    protected SQLAggregateExpr parseAggregateExpr(String methodName) {\n        SQLAggregateExpr aggregateExpr;\n        if (lexer.token == Token.ALL) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token == Token.DOT) {\n                aggregateExpr = new SQLAggregateExpr(methodName);\n                lexer.reset(mark);\n            } else {\n                aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.ALL);\n            }\n        } else if (lexer.token == Token.DISTINCT) {\n            aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.DISTINCT);\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.DEDUPLICATION)) { // just for nut\n            aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.DEDUPLICATION);\n            lexer.nextToken();\n        } else {\n            aggregateExpr = new SQLAggregateExpr(methodName);\n        }\n\n        exprList(aggregateExpr.getArguments(), aggregateExpr);\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setIgnoreNulls(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RESPECT)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setRespectNulls(true);\n\n        }\n\n        if (lexer.token != Token.RPAREN) {\n            parseAggregateExprRest(aggregateExpr);\n        }\n\n        if (lexer.token == ORDER) {\n            aggregateExpr.setOrderBy(\n                    this.parseOrderBy());\n        }\n\n        if (lexer.nextIf(LIMIT)) {\n            aggregateExpr.setLimit(\n                    expr()\n            );\n        }\n\n        accept(Token.RPAREN);\n\n        if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setIgnoreNulls(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RESPECT)) {\n            lexer.nextToken();\n            acceptIdentifier(\"NULLS\");\n            aggregateExpr.setRespectNulls(true);\n        }\n\n        if (lexer.nextIfIdentifier(FnvHash.Constants.WITHIN)) {\n            accept(Token.GROUP);\n            accept(Token.LPAREN);\n            SQLOrderBy orderBy = this.parseOrderBy();\n            aggregateExpr.setWithinGroup(true);\n            aggregateExpr.setOrderBy(orderBy);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FILTER)) {\n            filter(aggregateExpr);\n        }\n\n        if (lexer.token == Token.OVER) {\n            over(aggregateExpr);\n        }\n\n        return aggregateExpr;\n    }\n\n    protected void filter(SQLAggregateExpr x) {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n\n        switch (lexer.token) {\n            case COMMA:\n            case FROM:\n                lexer.reset(mark);\n                return;\n            default:\n                break;\n        }\n\n        accept(Token.LPAREN);\n        accept(Token.WHERE);\n        SQLExpr filter = this.expr();\n        accept(Token.RPAREN);\n        x.setFilter(filter);\n    }\n\n    protected void over(SQLAggregateExpr aggregateExpr) {\n        lexer.nextToken();\n\n        if (lexer.token != Token.LPAREN) {\n            SQLName overRef = this.name();\n            aggregateExpr.setOverRef(overRef);\n            return;\n        }\n\n        SQLOver over = new SQLOver();\n        over(over);\n        aggregateExpr.setOver(over);\n    }\n\n    protected void over(SQLOver over) {\n        lexer.nextToken();\n\n        if (lexer.token == Token.PARTITION || lexer.identifierEquals(\"PARTITION\")) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            if (lexer.token == (Token.LPAREN)) {\n                lexer.nextToken();\n                exprList(over.getPartitionBy(), over);\n                accept(Token.RPAREN);\n\n                if (over.getPartitionBy().size() == 1) {\n                    switch (lexer.token) {\n                        case SLASH:\n                        case DIV:\n                        case STAR:\n                        case PLUS:\n                        case SUB:\n                            SQLExpr first = this.exprRest(over.getPartitionBy().get(0));\n                            first.setParent(over);\n                            over.getPartitionBy().set(0, first);\n                            break;\n                        default:\n                            break;\n                    }\n\n                    if (lexer.token == Token.COMMA) {\n                        lexer.nextToken();\n                        exprList(over.getPartitionBy(), over);\n                    }\n                }\n            } else if (lexer.token == Token.ALL) {\n                SQLName name = this.name();\n                name.setParent(over);\n                over.getPartitionBy().add(name);\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    exprList(over.getPartitionBy(), over);\n                }\n            } else {\n                exprList(over.getPartitionBy(), over);\n            }\n        }\n\n        over.setOrderBy(parseOrderBy());\n        over.setDistributeBy(parseDistributeBy());\n        over.setSortBy(parseSortBy());\n        over.setClusterBy(parseClusterBy());\n\n        if (lexer.token == Token.OF) {\n            lexer.nextToken();\n            SQLName of = this.name();\n            over.setOf(of);\n        }\n\n        SQLOver.WindowingType windowingType = null;\n        if (lexer.identifierEquals(FnvHash.Constants.ROWS) || lexer.token == Token.ROWS) {\n            windowingType = SQLOver.WindowingType.ROWS;\n\n        } else if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {\n            windowingType = SQLOver.WindowingType.RANGE;\n        }\n\n        if (windowingType != null) {\n            over.setWindowingType(windowingType);\n            lexer.nextToken();\n\n            if (lexer.token == Token.BETWEEN) {\n                lexer.nextToken();\n\n                if (lexer.token == Token.LITERAL_INT\n                        || lexer.token == Token.LITERAL_FLOAT\n                        || lexer.token == Token.LITERAL_CHARS\n                        || lexer.token == Token.CAST\n                ) {\n                    SQLExpr betweenBegin = this.additive();\n                    over.setWindowingBetweenBegin(betweenBegin);\n                } else if (lexer.token == Token.IDENTIFIER) {\n                    long hash = lexer.hashLCase();\n\n                    if (hash != FnvHash.Constants.PRECEDING\n                            && hash != FnvHash.Constants.FOLLOWING\n                            && hash != FnvHash.Constants.CURRENT\n                            && hash != FnvHash.Constants.UNBOUNDED) {\n                        SQLExpr betweenBegin = this.primary();\n                        over.setWindowingBetweenBegin(betweenBegin);\n                    }\n                } else if (lexer.token == Token.INTERVAL) {\n                    SQLExpr betweenBegin = this.primary();\n                    over.setWindowingBetweenBegin(betweenBegin);\n                }\n\n                final SQLOver.WindowingBound beginBound = parseWindowingBound();\n                if (beginBound != null) {\n                    over.setWindowingBetweenBeginBound(beginBound);\n                }\n\n                accept(Token.AND);\n\n                if (lexer.token == Token.LITERAL_INT\n                        || lexer.token == Token.LITERAL_FLOAT\n                        || lexer.token == Token.LITERAL_CHARS\n                ) {\n                    SQLExpr betweenEnd = this.additive();\n                    over.setWindowingBetweenEnd(betweenEnd);\n                } else if (lexer.token == Token.INTERVAL) {\n                    SQLExpr betweenBegin = this.additive();\n                    over.setWindowingBetweenEnd(betweenBegin);\n                } else if (lexer.token == Token.IDENTIFIER) {\n                    long hash = lexer.hashLCase();\n\n                    if (hash != FnvHash.Constants.PRECEDING\n                            && hash != FnvHash.Constants.FOLLOWING\n                            && hash != FnvHash.Constants.CURRENT\n                            && hash != FnvHash.Constants.UNBOUNDED) {\n                        SQLExpr betweenBegin = this.additive();\n                        over.setWindowingBetweenEnd(betweenBegin);\n                    }\n                }\n\n                final SQLOver.WindowingBound endBound = parseWindowingBound();\n                if (endBound != null) {\n                    over.setWindowingBetweenEndBound(endBound);\n                }\n            } else {\n                if (lexer.token == Token.LITERAL_INT\n                        || lexer.token == Token.LITERAL_FLOAT\n                        || lexer.token == Token.LITERAL_CHARS\n                        || lexer.token == Token.INTERVAL\n                ) {\n                    SQLExpr betweenBegin = this.additive();\n                    over.setWindowingBetweenBegin(betweenBegin);\n                } else if (lexer.token == Token.IDENTIFIER) {\n                    long hash = lexer.hashLCase();\n\n                    if (hash != FnvHash.Constants.PRECEDING\n                            && hash != FnvHash.Constants.FOLLOWING\n                            && hash != FnvHash.Constants.CURRENT\n                            && hash != FnvHash.Constants.UNBOUNDED) {\n                        SQLExpr betweenBegin = this.additive();\n                        over.setWindowingBetweenBegin(betweenBegin);\n                    }\n                }\n\n                final SQLOver.WindowingBound beginBound = parseWindowingBound();\n                if (beginBound != null) {\n                    over.setWindowingBetweenBeginBound(beginBound);\n                }\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXCLUDE)) {\n            lexer.nextToken();\n            acceptIdentifier(\"CURRENT\");\n            acceptIdentifier(\"ROW\");\n            over.setExcludeCurrentRow(true);\n        }\n\n        accept(Token.RPAREN);\n    }\n\n    protected SQLOver.WindowingBound parseWindowingBound() {\n        if (lexer.identifierEquals(FnvHash.Constants.PRECEDING)) {\n            lexer.nextToken();\n            return SQLOver.WindowingBound.PRECEDING;\n        } else if (lexer.identifierEquals(FnvHash.Constants.FOLLOWING)) {\n            lexer.nextToken();\n            return SQLOver.WindowingBound.FOLLOWING;\n        } else if (lexer.identifierEquals(FnvHash.Constants.CURRENT) || lexer.token == Token.CURRENT) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.ROW)) {\n                lexer.nextToken();\n            } else {\n                accept(Token.ROW);\n            }\n            return SQLOver.WindowingBound.CURRENT_ROW;\n        } else if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.PRECEDING)) {\n                lexer.nextToken();\n                return SQLOver.WindowingBound.UNBOUNDED_PRECEDING;\n            } else {\n                acceptIdentifier(\"FOLLOWING\");\n                return SQLOver.WindowingBound.UNBOUNDED_FOLLOWING;\n            }\n        }\n\n        return null;\n    }\n\n    protected SQLAggregateExpr parseAggregateExprRest(SQLAggregateExpr aggregateExpr) {\n        return aggregateExpr;\n    }\n\n    public SQLOrderBy parseOrderBy() {\n        if (lexer.token == Token.ORDER) {\n            SQLOrderBy orderBy = new SQLOrderBy();\n\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.SIBLINGS)) {\n                lexer.nextToken();\n                orderBy.setSiblings(true);\n            }\n\n            accept(Token.BY);\n\n            orderBy(orderBy.getItems(), orderBy);\n\n            if (lexer.token == Token.ORDER) {\n                throw new ParserException(lexer.info()); // dual order by\n            }\n\n            return orderBy;\n        }\n\n        return null;\n    }\n\n    public SQLZOrderBy parseZOrderBy() {\n        if (lexer.identifierEquals(\"ZORDER\")) {\n            SQLZOrderBy orderBy = new SQLZOrderBy();\n\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.SIBLINGS)) {\n                lexer.nextToken();\n                orderBy.setSibings(true);\n            }\n\n            accept(Token.BY);\n\n            orderBy(orderBy.getItems(), orderBy);\n\n            if (lexer.token == Token.ORDER) {\n                throw new ParserException(lexer.info()); // dual order by\n            }\n\n            return orderBy;\n        }\n\n        return null;\n    }\n\n    public SQLOrderBy parseDistributeBy() {\n        if (lexer.token == Token.DISTRIBUTE || lexer.identifierEquals(\"DISTRIBUTE\")) {\n            SQLOrderBy orderBy = new SQLOrderBy();\n\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.SIBLINGS)) {\n                lexer.nextToken();\n                orderBy.setSiblings(true);\n            }\n\n            accept(Token.BY);\n\n            orderBy(orderBy.getItems(), orderBy);\n\n            if (lexer.token == Token.ORDER) {\n                throw new ParserException(lexer.info()); // dual order by\n            }\n\n            return orderBy;\n        }\n\n        return null;\n    }\n\n    public SQLOrderBy parseSortBy() {\n        if (lexer.token == Token.SORT || lexer.identifierEquals(FnvHash.Constants.SORT)) {\n            SQLOrderBy orderBy = new SQLOrderBy();\n\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.SIBLINGS)) {\n                lexer.nextToken();\n                orderBy.setSiblings(true);\n            }\n\n            accept(Token.BY);\n\n            orderBy(orderBy.getItems(), orderBy);\n\n            if (lexer.token == Token.ORDER) {\n                throw new ParserException(lexer.info()); // dual order by\n            }\n\n            return orderBy;\n        }\n\n        return null;\n    }\n\n    public SQLOrderBy parseClusterBy() {\n        if (lexer.identifierEquals(FnvHash.Constants.CLUSTER)) {\n            SQLOrderBy orderBy = new SQLOrderBy();\n\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(FnvHash.Constants.SIBLINGS)) {\n                lexer.nextToken();\n                orderBy.setSiblings(true);\n            }\n\n            accept(Token.BY);\n\n            orderBy(orderBy.getItems(), orderBy);\n\n            if (lexer.token == Token.ORDER) {\n                throw new ParserException(lexer.info()); // dual order by\n            }\n\n            return orderBy;\n        }\n\n        return null;\n    }\n\n    public void orderBy(List<SQLSelectOrderByItem> items, SQLObject parent) {\n        SQLSelectOrderByItem item = parseSelectOrderByItem();\n        item.setParent(parent);\n        items.add(item);\n        while (lexer.nextIf(Token.COMMA) || (item.getExpr() instanceof SQLVariantRefExpr && lexer.token == IDENTIFIER)) {\n            item = parseSelectOrderByItem();\n            item.setParent(parent);\n            items.add(item);\n        }\n    }\n\n    public SQLSelectOrderByItem parseSelectOrderByItem() {\n        SQLSelectOrderByItem item = new SQLSelectOrderByItem();\n\n        setAllowIdentifierMethod(false);\n\n        try {\n            SQLExpr expr;\n            if (lexer.token() == Token.LITERAL_ALIAS) {\n                expr = name();\n                expr = primaryRest(expr);\n                expr = exprRest(expr);\n            } else if (lexer.token == Token.LPAREN) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                for (int i = 0; ; ++i) {\n                    expr = this.expr();\n                    if (lexer.token == Token.ASC) {\n                        lexer.nextToken();\n                        item.setType(SQLOrderingSpecification.ASC);\n                        if (lexer.token == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        accept(Token.RPAREN);\n                    } else if (lexer.token == Token.DESC) {\n                        lexer.nextToken();\n                        item.setType(SQLOrderingSpecification.DESC);\n                        if (lexer.token == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        accept(Token.RPAREN);\n                    } else {\n                        if (i > 0 && lexer.token == Token.RPAREN) {\n                            lexer.nextToken();\n                            break;\n                        }\n                        lexer.reset(mark);\n                        expr = expr();\n                    }\n                    break;\n                }\n            } else {\n                expr = expr();\n            }\n            if (isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                if (expr instanceof SQLPropertyExpr) {\n                    SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n                    SQLExpr owner = propertyExpr.getOwner();\n                    if (owner != null) {\n                        String ownerStr = SQLUtils.toSQLString(owner);\n                        if (ownerStr.length() > 1) {\n                            ownerStr = StringUtils.removeNameQuotes(ownerStr);\n                        }\n                        propertyExpr.setOwner(ownerStr);\n                    }\n                    String name = propertyExpr.getName();\n                    if (name.length() > 1) {\n                        name = StringUtils.removeNameQuotes(name);\n                        propertyExpr.setName(name);\n                    }\n                    expr = propertyExpr;\n                }\n            }\n            item.setExpr(expr);\n        } finally {\n            setAllowIdentifierMethod(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n            String collate = lexer.stringVal();\n            item.setCollate(collate);\n            lexer.nextToken();\n            if (lexer.token == Token.DOT) {\n                lexer.nextToken();\n                String collateOther = lexer.stringVal();\n                item.setCollate(collate + \".\" + collateOther);\n                lexer.nextToken();\n            }\n        }\n        if (lexer.token == Token.LITERAL_ALIAS) {\n            SQLExpr name = this.expr();\n            item.setOpclass(name);\n        }\n        if (lexer.token == Token.ASC) {\n            lexer.nextToken();\n            item.setType(SQLOrderingSpecification.ASC);\n        } else if (lexer.token == Token.DESC) {\n            lexer.nextToken();\n            item.setType(SQLOrderingSpecification.DESC);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.NULLS)) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.FIRST) || lexer.token == Token.FIRST) {\n                lexer.nextToken();\n                item.setNullsOrderType(SQLSelectOrderByItem.NullsOrderType.NullsFirst);\n            } else if (lexer.identifierEquals(FnvHash.Constants.LAST)) {\n                lexer.nextToken();\n                item.setNullsOrderType(SQLSelectOrderByItem.NullsOrderType.NullsLast);\n            } else {\n                throw new ParserException(\"syntax error, expect FIRST or LAST after NULLS, actual \" + lexer.stringVal() + \". \" + lexer.info());\n            }\n        }\n\n        if (lexer.token == Token.HINT) {\n            item.setHint(this.parseHint());\n        }\n\n        return item;\n    }\n\n    protected void parseUpdateSetItemLbracket(SQLUpdateSetItem item) {\n    }\n    public SQLUpdateSetItem parseUpdateSetItem() {\n        SQLUpdateSetItem item = new SQLUpdateSetItem();\n\n        if (lexer.token == (Token.LPAREN)) {\n            lexer.nextToken();\n            SQLListExpr list = new SQLListExpr();\n            this.exprList(list.getItems(), list);\n            accept(Token.RPAREN);\n            item.setColumn(list);\n        } else {\n            String identName;\n            long hash;\n\n            Token token = lexer.token();\n            if (token == Token.IDENTIFIER) {\n                identName = lexer.stringVal();\n                hash = lexer.hashLCase();\n            } else if (token == Token.LITERAL_CHARS) {\n                identName = '\\'' + lexer.stringVal() + '\\'';\n                hash = 0;\n            } else {\n                identName = lexer.stringVal();\n                hash = 0;\n            }\n            lexer.nextTokenEq();\n            SQLExpr expr = new SQLIdentifierExpr(identName, hash);\n            while (lexer.token() == Token.DOT) {\n                lexer.nextToken();\n                String propertyName = lexer.stringVal();\n                lexer.nextTokenEq();\n                expr = new SQLPropertyExpr(expr, propertyName);\n            }\n\n            item.setColumn(expr);\n        }\n\n        if (lexer.token == Token.LBRACKET) {\n            parseUpdateSetItemLbracket(item);\n        }\n\n        if (lexer.token == Token.COLONEQ) {\n            lexer.nextTokenValue();\n        } else if (lexer.token == Token.EQ) {\n            lexer.nextTokenValue();\n        } else {\n            throw new ParserException(\"syntax error, expect EQ, actual \" + lexer.token + \" \"\n                    + lexer.info());\n        }\n\n        item.setValue(this.expr());\n        return item;\n    }\n\n    public final SQLExpr bitAnd() {\n        SQLExpr expr = shift();\n\n        if (lexer.token == Token.AMP) {\n            expr = bitAndRest(expr);\n        }\n\n        return expr;\n    }\n\n    public final SQLExpr bitAndRest(SQLExpr expr) {\n        while (lexer.token == Token.AMP) {\n            lexer.nextToken();\n            SQLExpr rightExp = shift();\n            expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseAnd, rightExp, getDbType());\n        }\n        return expr;\n    }\n\n    public final SQLExpr bitOr() {\n        SQLExpr expr = bitAnd();\n\n        if (lexer.token == Token.BAR) {\n            expr = bitOrRest(expr);\n        }\n\n        return expr;\n    }\n\n    public final SQLExpr bitOrRest(SQLExpr expr) {\n        while (lexer.token == Token.BAR) {\n            lexer.nextToken();\n            SQLBinaryOperator op = SQLBinaryOperator.BitwiseOr;\n            if (lexer.token == Token.BAR) {\n                lexer.nextToken();\n                op = SQLBinaryOperator.Concat;\n            }\n            SQLExpr rightExp = bitAnd();\n            expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType());\n            expr = bitAndRest(expr);\n        }\n        return expr;\n    }\n\n    public final SQLExpr inRest(SQLExpr expr) {\n        boolean global = false;\n\n        // for clickhouse\n        Lexer.SavePoint globalMark = lexer.mark();\n        if (lexer.token == Token.GLOBAL) {\n            global = true;\n            lexer.nextToken();\n            // global not in logic\n            if (lexer.token == Token.NOT) {\n                lexer.nextToken();\n                return notRationalRest(expr, true);\n            }\n\n        }\n\n        if (lexer.token == Token.IN) {\n            Lexer.SavePoint mark = lexer.mark();\n\n            lexer.nextTokenLParen();\n\n            if (lexer.token == Token.COMMA) {\n                lexer.reset(mark);\n                return expr;\n            }\n\n            SQLInListExpr inListExpr = new SQLInListExpr(expr);\n            List<SQLExpr> targetList = inListExpr.getTargetList();\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextTokenValue();\n\n                List<SQLCommentHint> hints = null;\n\n                if (lexer.token == Token.HINT) {\n                    hints = this.parseHints();\n                }\n\n                if (lexer.token == Token.WITH) {\n                    SQLSelect select = this.createSelectParser().select();\n                    SQLInSubQueryExpr queryExpr = new SQLInSubQueryExpr(select);\n                    queryExpr.setExpr(expr);\n                    accept(Token.RPAREN);\n                    return queryExpr;\n                }\n\n                if (lexer.token != Token.RPAREN) {\n                    for (; ; ) {\n                        SQLExpr item;\n                        if (lexer.token == Token.LITERAL_INT) {\n                            item = new SQLIntegerExpr(lexer.integerValue());\n                            lexer.nextToken();\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                item = this.primaryRest(item);\n                                item = this.exprRest(item);\n                            }\n                        } else {\n                            item = this.expr();\n                        }\n\n                        item.setParent(inListExpr);\n                        targetList.add(item);\n\n                        if (item instanceof SQLCharExpr\n                                && lexer.token == Token.LITERAL_CHARS\n                                && dialectFeatureEnabled(InRestSpecificOperation)\n                        ) {\n                            continue;\n                        }\n\n                        if (lexer.token == Token.COMMA) {\n                            lexer.nextTokenValue();\n\n                            if (lexer.token == Token.RPAREN && dialectFeatureEnabled(InRestSpecificOperation)) {\n                                break;\n                            }\n                            continue;\n                        }\n                        item.addAfterComment(lexer.comments);\n                        break;\n                    }\n\n                    switch (lexer.token) {\n                        case MINUS:\n                        case EXCEPT:\n                        case UNION: {\n                            if (targetList.size() == 1\n                                    && targetList.get(0) instanceof SQLQueryExpr) {\n                                SQLQueryExpr queryExpr = (SQLQueryExpr) targetList.get(0);\n                                SQLSelectQuery query = this.createSelectParser().queryRest(queryExpr.getSubQuery().getQuery(), true);\n                                if (query != queryExpr.getSubQuery()) {\n                                    queryExpr.getSubQuery().setQuery(query);\n                                }\n\n                                if (hints != null && hints.size() > 0) {\n                                    queryExpr.getSubQuery().setHeadHint(hints.get(0));\n                                }\n                            }\n                            break;\n                        }\n                        default:\n                            break;\n                    }\n                }\n\n                int line = lexer.line;\n                accept(Token.RPAREN);\n                if (line + 1 == lexer.line\n                        && lexer.hasComment()\n                        && lexer.getComments().get(0).startsWith(\"--\")) {\n                    inListExpr.addAfterComment(lexer.readAndResetComments());\n                }\n            } else {\n                SQLExpr itemExpr = primary();\n                itemExpr.setParent(inListExpr);\n                targetList.add(itemExpr);\n            }\n\n            parseQueryPlanHint(inListExpr);\n            expr = inListExpr;\n\n            if (targetList.size() == 1) {\n                SQLExpr targetExpr = targetList.get(0);\n                if (targetExpr instanceof SQLQueryExpr) {\n                    SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr();\n                    inSubQueryExpr.setExpr(inListExpr.getExpr());\n                    inSubQueryExpr.setSubQuery(((SQLQueryExpr) targetExpr).getSubQuery());\n\n                    inSubQueryExpr.setHint(inListExpr.getHint());\n\n                    if (global) {\n                        inSubQueryExpr.setGlobal(true);\n                    }\n\n                    expr = inSubQueryExpr;\n                }\n            }\n        } else if (lexer.token == Token.CONTAINS) {\n            lexer.nextTokenLParen();\n\n            SQLContainsExpr containsExpr = new SQLContainsExpr(expr);\n            List<SQLExpr> targetList = containsExpr.getTargetList();\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextTokenValue();\n\n                if (lexer.token == Token.WITH) {\n                    SQLSelect select = this.createSelectParser().select();\n                    SQLInSubQueryExpr queryExpr = new SQLInSubQueryExpr(select);\n                    queryExpr.setExpr(expr);\n                    accept(Token.RPAREN);\n                    return queryExpr;\n                }\n\n                for (; ; ) {\n                    SQLExpr item;\n                    if (lexer.token == Token.LITERAL_INT) {\n                        item = new SQLIntegerExpr(lexer.integerValue());\n                        lexer.nextToken();\n                        if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                            item = this.primaryRest(item);\n                            item = this.exprRest(item);\n                        }\n                    } else {\n                        item = this.expr();\n                    }\n\n                    item.setParent(containsExpr);\n                    targetList.add(item);\n                    if (lexer.token == Token.COMMA) {\n                        lexer.nextTokenValue();\n                        continue;\n                    }\n                    break;\n                }\n\n                accept(Token.RPAREN);\n            } else {\n                SQLExpr itemExpr = primary();\n                itemExpr.setParent(containsExpr);\n                targetList.add(itemExpr);\n            }\n\n            expr = containsExpr;\n        } else {\n            lexer.reset(globalMark);\n        }\n\n        return expr;\n    }\n\n    public final SQLExpr additive() {\n        SQLExpr expr = multiplicative();\n\n        if (lexer.token == Token.PLUS\n                || lexer.token == Token.BARBAR\n                || lexer.token == Token.CONCAT\n                || lexer.token == Token.SUB) {\n            expr = additiveRest(expr);\n        }\n\n        return expr;\n    }\n\n    public final SQLExpr additiveRest(SQLExpr expr) {\n        Token token = lexer.token;\n\n        SQLBinaryOperator operator;\n        if (token == Token.PLUS) {\n            lexer.nextToken();\n\n            while (lexer.token == Token.HINT) {\n                SQLCommentHint hint = parseHint();\n                if (expr instanceof SQLObjectImpl) {\n                    ((SQLObjectImpl) expr).setHint(hint);\n                }\n            }\n\n            operator = SQLBinaryOperator.Add;\n        } else if ((token == Token.BARBAR || token == Token.CONCAT)\n                && (isEnabled(SQLParserFeature.PipesAsConcat) || dialectFeatureEnabled(AdditiveRestPipesAsConcat))) {\n            lexer.nextToken();\n            operator = SQLBinaryOperator.Concat;\n        } else if (token == Token.SUB) {\n            lexer.nextToken();\n            operator = SQLBinaryOperator.Subtract;\n        } else {\n            return expr;\n        }\n\n        SQLExpr rightExp = multiplicative();\n        return additiveRest(\n                new SQLBinaryOpExpr(expr, operator, rightExp, dbType)\n        );\n    }\n\n    public final SQLExpr shift() {\n        SQLExpr expr = additive();\n        if (lexer.token == Token.LTLT || lexer.token == Token.GTGT || lexer.token == Token.GTGTGT) {\n            expr = shiftRest(expr);\n        }\n        return expr;\n    }\n\n    public SQLExpr shiftRest(SQLExpr expr) {\n        SQLBinaryOperator operator = null;\n        if (lexer.token == Token.LTLT) {\n            lexer.nextToken();\n            operator = SQLBinaryOperator.LeftShift;\n        } else if (lexer.token == Token.GTGT) {\n            lexer.nextToken();\n            operator = SQLBinaryOperator.RightShift;\n        } else if (lexer.token == Token.GTGTGT) {\n            lexer.nextToken();\n            operator = SQLBinaryOperator.RightShiftUnsigned;\n        }\n\n        if (operator != null) {\n            SQLExpr rightExp = additive();\n            expr = new SQLBinaryOpExpr(expr, operator, rightExp, dbType);\n            expr = shiftRest(expr);\n        }\n\n        return expr;\n    }\n\n    public SQLExpr and() {\n        SQLExpr expr = relational();\n        if (lexer.token == Token.AND || lexer.token == Token.AMPAMP) {\n            expr = andRest(expr);\n        }\n        return expr;\n    }\n\n    //for ads\n    public void parseQueryPlanHint(SQLExpr expr) {\n        if (lexer.token == Token.HINT && (expr instanceof SQLInListExpr\n                || expr instanceof SQLBinaryOpExpr\n                || expr instanceof SQLInSubQueryExpr\n                || expr instanceof SQLExistsExpr\n                || expr instanceof SQLNotExpr\n                || expr instanceof SQLBetweenExpr)) {\n            String text = lexer.stringVal().trim();\n\n            Lexer hintLex = SQLParserUtils.createLexer(text, dbType);\n            hintLex.nextToken();\n\n            //防止SQL注入\n            if (hintLex.token == Token.PLUS) {\n                if (expr instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr;\n\n                    SQLBinaryOperator operator = binaryOpExpr.getOperator();\n\n                    if (operator == SQLBinaryOperator.BooleanAnd\n                            || operator == SQLBinaryOperator.BooleanOr) {\n                        if (binaryOpExpr.isParenthesized()) {\n                            binaryOpExpr.setHint(new SQLCommentHint(text));\n                        } else {\n                            SQLExpr right = binaryOpExpr.getRight();\n                            if (right instanceof SQLBinaryOpExpr\n                                    || right instanceof SQLBetweenExpr) {\n                                ((SQLExprImpl) right).setHint(new SQLCommentHint(text));\n                            }\n                        }\n                    } else {\n                        binaryOpExpr.setHint(new SQLCommentHint(text));\n                    }\n                } else if (expr instanceof SQLObjectImpl) {\n                    ((SQLExprImpl) expr).setHint(new SQLCommentHint(text));\n                } else {\n                    throw new ParserException(\"hint cannot be applied to expression type \" + expr.getClass().getSimpleName() + \". \" + lexer.info());\n                }\n                this.lexer.nextToken();\n            }\n        }\n    }\n\n    protected SQLBinaryOperator andRestGetAndOperator() {\n        return SQLBinaryOperator.BooleanAnd;\n    }\n    public SQLExpr andRest(SQLExpr expr) {\n        for (; ; ) {\n            if (expr instanceof SQLBinaryOpExpr) {\n                parseQueryPlanHint(expr);\n            }\n\n            Token token = lexer.token;\n\n            if (token == Token.AND) {\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    expr.addAfterComment(lexer.readAndResetComments());\n                }\n\n                lexer.nextToken();\n\n                SQLExpr rightExp = relational();\n\n                if (expr instanceof SQLBinaryOpExpr) {\n                    parseQueryPlanHint(rightExp);\n                }\n\n                if (lexer.token == Token.AND\n                        && lexer.isEnabled(SQLParserFeature.EnableSQLBinaryOpExprGroup)) {\n                    SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanAnd, dbType);\n                    group.add(expr);\n                    group.add(rightExp);\n\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        rightExp.addAfterComment(lexer.readAndResetComments());\n                    }\n\n                    for (; ; ) {\n                        lexer.nextToken();\n                        SQLExpr more = relational();\n\n                        if (more instanceof SQLBinaryOpExpr) {\n                            parseQueryPlanHint(more);\n                        }\n\n                        group.add(more);\n\n                        if (lexer.token == Token.AND) {\n                            if (lexer.isKeepComments() && lexer.hasComment()) {\n                                more.addAfterComment(lexer.readAndResetComments());\n                            }\n\n                            continue;\n                        }\n                        break;\n                    }\n\n                    expr = group;\n                } else {\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanAnd, rightExp, dbType);\n                }\n            } else if (token == Token.AMPAMP) {\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    expr.addAfterComment(lexer.readAndResetComments());\n                }\n\n                lexer.nextToken();\n\n                SQLExpr rightExp = relational();\n\n                SQLBinaryOperator operator = andRestGetAndOperator();\n\n                expr = new SQLBinaryOpExpr(expr, operator, rightExp, dbType);\n            } else if (token == Token.VARIANT) {\n                SQLExpr expr1 = relationalRestVariant(expr);\n                if (expr1 == expr) {\n                    break;\n                }\n                expr = expr1;\n            } else {\n                break;\n            }\n        }\n\n        return expr;\n    }\n\n    public SQLExpr xor() {\n        SQLExpr expr = and();\n        if (lexer.token == Token.XOR) {\n            expr = xorRest(expr);\n        }\n        return expr;\n    }\n\n    public SQLExpr xorRest(SQLExpr expr) {\n        for (; ; ) {\n            if (lexer.token == Token.XOR) {\n                lexer.nextToken();\n                SQLExpr rightExp = and();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanXor, rightExp, dbType);\n            } else {\n                break;\n            }\n        }\n\n        return expr;\n    }\n\n    public SQLExpr or() {\n        SQLExpr expr = xor();\n        if (lexer.token == Token.OR || lexer.token == Token.BARBAR) {\n            expr = orRest(expr);\n        }\n        return expr;\n    }\n\n    protected SQLBinaryOperator orRestGetOrOperator() {\n        return SQLBinaryOperator.Concat;\n    }\n    public SQLExpr orRest(SQLExpr expr) {\n        for (; ; ) {\n            if (lexer.token == Token.OR) {\n                if (lexer.isKeepComments() && lexer.hasComment()) {\n                    expr.addAfterComment(lexer.readAndResetComments());\n                }\n\n                lexer.nextToken();\n                SQLExpr rightExp = xor();\n\n                if (lexer.token == Token.OR\n                        && lexer.isEnabled(SQLParserFeature.EnableSQLBinaryOpExprGroup)) {\n                    SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanOr, dbType);\n                    group.add(expr);\n                    group.add(rightExp);\n\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        rightExp.addAfterComment(lexer.readAndResetComments());\n                    }\n\n                    for (; ; ) {\n                        lexer.nextToken();\n                        SQLExpr more = xor();\n                        group.add(more);\n                        if (lexer.token == Token.OR) {\n                            if (lexer.isKeepComments() && lexer.hasComment()) {\n                                more.addAfterComment(lexer.readAndResetComments());\n                            }\n\n                            continue;\n                        }\n                        break;\n                    }\n\n                    expr = group;\n                } else {\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanOr, rightExp, dbType);\n                }\n            } else if (lexer.token == Token.BARBAR) {\n                lexer.nextToken();\n                SQLExpr rightExp = xor();\n\n                SQLBinaryOperator op = orRestGetOrOperator();\n\n                expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);\n            } else if (lexer.token == Token.VARIANT) {\n                SQLExpr expr1 = relationalRestVariant(expr);\n                if (expr == expr1) {\n                    break;\n                }\n                expr = expr1;\n            } else {\n                break;\n            }\n        }\n\n        return expr;\n    }\n\n    public SQLExpr relational() {\n        SQLExpr expr = bitOr();\n\n        return relationalRest(expr);\n    }\n\n    protected SQLExpr relationalRestQues(SQLExpr expr) {\n        return expr;\n    }\n\n    protected SQLExpr relationalRestBang(SQLExpr expr) {\n        return expr;\n    }\n\n    protected SQLExpr relationalRestEqeq(SQLExpr expr) {\n        lexer.nextToken();\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.EqEq, expr());\n    }\n\n    protected SQLExpr relationalRestTilde(SQLExpr expr) {\n        return expr;\n    }\n\n    protected SQLExpr relationalRestTildeStar(SQLExpr expr) {\n        return expr;\n    }\n    protected SQLExpr relationalRestBangTilde(SQLExpr expr) {\n        return expr;\n    }\n\n    protected SQLExpr relationalRestBangTildeStar(SQLExpr expr) {\n        return expr;\n    }\n\n    protected SQLExpr relationalRestTildeEq(SQLExpr expr) {\n        return expr;\n    }\n\n    protected SQLExpr relationalRestIdentifierSimilar(SQLExpr expr) {\n        return expr;\n    }\n    public SQLExpr relationalRest(SQLExpr expr) {\n        final SQLExpr initExpr = expr;\n        SQLExpr rightExp = null;\n\n        Token token = lexer.token;\n\n        switch (token) {\n            case EQ: {\n                lexer.nextToken();\n                try {\n                    rightExp = bitOr();\n                } catch (EOFParserException e) {\n                    throw new ParserException(\"EOF, \" + expr + \"=\", e);\n                }\n\n                if (lexer.token == Token.COLONEQ) {\n                    lexer.nextToken();\n                    SQLExpr colonExpr = expr();\n                    rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType);\n                }\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);\n            }\n            break;\n            case IS: {\n                lexer.nextTokenNotOrNull();\n\n                SQLBinaryOperator op;\n                if (lexer.token == Token.NOT) {\n                    op = SQLBinaryOperator.IsNot;\n                    lexer.nextTokenNotOrNull();\n                } else {\n                    op = SQLBinaryOperator.Is;\n                }\n\n                if (lexer.identifierEquals(FnvHash.Constants.JSON)) {\n                    lexer.nextToken();\n\n                    String name = \"JSON\";\n                    if (lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n                        lexer.nextToken();\n                        name = \"JSON VALUE\";\n                    } else if (lexer.identifierEquals(FnvHash.Constants.OBJECT)) {\n                        lexer.nextToken();\n                        name = \"JSON OBJECT\";\n                    } else if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {\n                        lexer.nextToken();\n                        name = \"JSON ARRAY\";\n                    } else if (lexer.identifierEquals(FnvHash.Constants.SCALAR)) {\n                        lexer.nextToken();\n                        name = \"JSON SCALAR\";\n                    }\n\n                    rightExp = new SQLIdentifierExpr(name);\n                } else if (lexer.token == Token.DISTINCT) {\n                    lexer.nextToken();\n                    accept(Token.FROM);\n\n                    if (op == SQLBinaryOperator.Is) {\n                        op = SQLBinaryOperator.IsDistinctFrom;\n                    } else {\n                        op = SQLBinaryOperator.IsNotDistinctFrom;\n                    }\n                    rightExp = bitOr();\n                } else {\n                    rightExp = primary();\n                }\n                expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);\n            }\n            break;\n            case EQGT: {\n                lexer.nextToken();\n                rightExp = expr();\n                if (expr instanceof SQLIdentifierExpr) {\n                    String argumentName = ((SQLIdentifierExpr) expr).getName();\n                    expr = new OracleArgumentExpr(argumentName, rightExp);\n                } else {\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, dbType);\n                }\n            }\n            break;\n            case BANGEQ:\n            case CARETEQ: {\n                lexer.nextToken();\n                rightExp = bitOr();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, dbType);\n            }\n            break;\n            case COLONEQ: {\n                lexer.nextToken();\n                rightExp = expr();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, dbType);\n            }\n            break;\n            case LT: {\n                SQLBinaryOperator op = SQLBinaryOperator.LessThan;\n\n                lexer.nextToken();\n                if (lexer.token == Token.EQ) {\n                    lexer.nextToken();\n                    op = SQLBinaryOperator.LessThanOrEqual;\n                } else if (lexer.token == Token.LT) {\n                    lexer.nextToken();\n                    op = SQLBinaryOperator.LeftShift;\n                    rightExp = additive();\n                }\n\n                if (rightExp == null) {\n                    rightExp = bitOr();\n                }\n\n                expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType());\n            }\n            break;\n            case LTEQ:\n                lexer.nextToken();\n                rightExp = bitOr();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqual, rightExp, getDbType());\n                break;\n            case LTLTLT:\n                lexer.nextToken();\n                rightExp = bitOr();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LeftShiftUnsigned, rightExp, getDbType());\n                break;\n            case LTEQGT: {\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqualOrGreaterThan, rightExp, getDbType());\n            }\n            break;\n            case GT: {\n                SQLBinaryOperator op = SQLBinaryOperator.GreaterThan;\n\n                lexer.nextToken();\n\n                if (lexer.token == Token.EQ) {\n                    lexer.nextToken();\n                    op = SQLBinaryOperator.GreaterThanOrEqual;\n                }\n\n                if (lexer.token == Token.GT) {\n                    lexer.nextToken();\n                    op = SQLBinaryOperator.RightShift;\n                    rightExp = additive();\n                } else if (lexer.token == Token.GTGT) {\n                    lexer.nextToken();\n                    op = SQLBinaryOperator.RightShiftUnsigned;\n                    rightExp = additive();\n                }\n\n                if (rightExp == null) {\n                    rightExp = bitOr();\n                }\n                expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);\n            }\n            break;\n            case GTEQ: {\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.GreaterThanOrEqual, rightExp, dbType);\n            }\n            break;\n            case BANGLT: {\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLessThan, rightExp, dbType);\n            }\n            break;\n            case BANGGT:\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotGreaterThan, rightExp, dbType);\n                break;\n            case LTGT:\n                lexer.nextToken();\n                rightExp = bitOr();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrGreater, rightExp, dbType);\n                break;\n            case LIKE: {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextTokenValue();\n                if (lexer.token == Token.COMMA) {\n                    lexer.reset(mark);\n                    return expr;\n                }\n                rightExp = bitOr();\n\n                if (rightExp.getClass() == SQLIdentifierExpr.class) {\n                    String name = ((SQLIdentifierExpr) rightExp).getName();\n                    int length = name.length();\n                    if (length > 1\n                            && name.charAt(0) == name.charAt(length - 1)\n                            && name.charAt(0) != '`'\n                    ) {\n                        rightExp = new SQLCharExpr(name.substring(1, length - 1));\n                    }\n                }\n\n                // rightExp = relationalRest(rightExp);\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Like, rightExp, dbType);\n\n                if (lexer.token == Token.ESCAPE) {\n                    lexer.nextToken();\n                    rightExp = primary();\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp, dbType);\n                }\n                break;\n            }\n            case ILIKE:\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.ILike, rightExp, dbType);\n                break;\n            case MONKEYS_AT_AT:\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.AT_AT, rightExp, dbType);\n                break;\n            case MONKEYS_AT_GT:\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Array_Contains, rightExp, dbType);\n                break;\n            case LT_MONKEYS_AT:\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                rightExp = relationalRest(rightExp);\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Array_ContainedBy, rightExp, dbType);\n                break;\n            case QUES:\n                expr = relationalRestQues(expr);\n                break;\n            case NOT:\n                lexer.nextToken();\n                expr = notRationalRest(expr, false);\n                break;\n            case BANG:\n                expr = relationalRestBang(expr);\n                break;\n            case BETWEEN:\n                lexer.nextToken();\n                SQLExpr beginExpr = relational();\n                accept(Token.AND);\n                SQLExpr endExpr = relational();\n                expr = new SQLBetweenExpr(expr, beginExpr, endExpr);\n                parseQueryPlanHint(expr);\n                break;\n            case IN:\n            case CONTAINS:\n            case GLOBAL:\n                expr = inRest(expr);\n                break;\n            case EQEQ:\n                expr = relationalRestEqeq(expr);\n                break;\n            case TILDE:\n                expr = relationalRestTilde(expr);\n                break;\n            case TILDE_STAR:\n                expr = relationalRestTildeStar(expr);\n                break;\n            case BANG_TILDE:\n                expr = relationalRestBangTilde(expr);\n                break;\n            case BANG_TILDE_STAR:\n                expr = relationalRestBangTildeStar(expr);\n                break;\n            case TILDE_EQ:\n                expr = relationalRestTildeEq(expr);\n                break;\n            case RLIKE: {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                switch (lexer.token) {\n                    case COMMA:\n                        lexer.reset(mark);\n                        break;\n                    default:\n                        rightExp = bitOr();\n                        expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RLike, rightExp, dbType);\n                        break;\n                }\n                break;\n            }\n            case IDENTIFIER:\n                long hash = lexer.hashLCase;\n                if (hash == FnvHash.Constants.SOUNDS) {\n                    lexer.nextToken();\n                    accept(Token.LIKE);\n\n                    rightExp = bitOr();\n\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SoudsLike, rightExp, dbType);\n                } else if (hash == FnvHash.Constants.REGEXP) {\n                    lexer.nextToken();\n                    rightExp = bitOr();\n\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RegExp, rightExp, dbType);\n                } else if (hash == FnvHash.Constants.SIMILAR) {\n                    expr = relationalRestIdentifierSimilar(expr);\n                } else {\n                    return expr;\n                }\n                break;\n            case VARIANT:\n                return relationalRestVariant(expr);\n            default:\n                return expr;\n        }\n\n        if (expr == initExpr) {\n            return expr;\n        }\n\n        switch (lexer.token) {\n            case BETWEEN:\n            case IS:\n            case EQ:\n            case EQEQ:\n            case IN:\n            case CONTAINS:\n            case BANG_TILDE_STAR:\n            case TILDE_EQ:\n            case LT:\n            case LTEQ:\n            case LTEQGT:\n            case GT:\n            case GTEQ:\n            case LTGT:\n            case BANGEQ:\n            case LIKE:\n            case NOT:\n                expr = relationalRest(expr);\n                break;\n            default:\n                break;\n        }\n\n        return expr;\n    }\n\n    protected SQLExpr relationalRestVariant(SQLExpr expr) {\n        String value = lexer.stringVal();\n        lexer.nextToken();\n        SQLExpr variantExpr = new SQLVariantRefExpr(value);\n        if (lexer.token == Token.IN) {\n            variantExpr = inRest(variantExpr);\n        }\n        return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Blank, variantExpr, dbType);\n    }\n\n    public SQLExpr notRationalRest(SQLExpr expr, boolean global) {\n        switch (lexer.token) {\n            case LIKE:\n                lexer.nextTokenValue();\n                SQLExpr rightExp = bitOr();\n\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLike, rightExp, dbType);\n\n                if (lexer.token == Token.ESCAPE) {\n                    lexer.nextToken();\n                    rightExp = bitOr();\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp, dbType);\n                }\n                break;\n            case IN:\n                lexer.nextToken();\n\n                SQLInListExpr inListExpr = new SQLInListExpr(expr, true);\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    exprList(inListExpr.getTargetList(), inListExpr);\n                    expr = inListExpr;\n\n                    switch (lexer.token) {\n                        case MINUS:\n                        case UNION: {\n                            List<SQLExpr> targetList = inListExpr.getTargetList();\n                            if (targetList.size() == 1\n                                    && targetList.get(0) instanceof SQLQueryExpr) {\n                                SQLQueryExpr queryExpr = (SQLQueryExpr) targetList.get(0);\n                                queryExpr.getSubQuery().getQuery().setParenthesized(queryExpr.isParenthesized());\n                                SQLSelectQuery query = this.createSelectParser().queryRest(queryExpr.getSubQuery().getQuery(), true);\n                                if (query != queryExpr.getSubQuery()) {\n                                    queryExpr.getSubQuery().setQuery(query);\n                                }\n                            }\n                            break;\n                        }\n                        default:\n                            break;\n                    }\n\n                    accept(Token.RPAREN);\n                } else {\n                    SQLExpr valueExpr = this.primary();\n                    valueExpr.setParent(inListExpr);\n                    inListExpr.getTargetList().add(valueExpr);\n                    expr = inListExpr;\n                }\n\n                parseQueryPlanHint(inListExpr);\n\n                if (inListExpr.getTargetList().size() == 1) {\n                    SQLExpr targetExpr = inListExpr.getTargetList().get(0);\n                    if (targetExpr instanceof SQLQueryExpr) {\n                        SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr();\n                        inSubQueryExpr.setNot(true);\n                        inSubQueryExpr.setExpr(inListExpr.getExpr());\n                        inSubQueryExpr.setSubQuery(((SQLQueryExpr) targetExpr).getSubQuery());\n                        inSubQueryExpr.setGlobal(global);\n                        expr = inSubQueryExpr;\n                    }\n                }\n\n                break;\n            case CONTAINS:\n                lexer.nextToken();\n\n                SQLContainsExpr containsExpr = new SQLContainsExpr(expr, true);\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    exprList(containsExpr.getTargetList(), containsExpr);\n                    expr = containsExpr;\n\n                    switch (lexer.token) {\n                        case MINUS:\n                        case UNION: {\n                            List<SQLExpr> targetList = containsExpr.getTargetList();\n                            if (targetList.size() == 1\n                                    && targetList.get(0) instanceof SQLQueryExpr) {\n                                SQLQueryExpr queryExpr = (SQLQueryExpr) targetList.get(0);\n                                SQLSelectQuery query = this.createSelectParser().queryRest(queryExpr.getSubQuery().getQuery(), true);\n                                if (query != queryExpr.getSubQuery()) {\n                                    queryExpr.getSubQuery().setQuery(query);\n                                }\n                            }\n                            break;\n                        }\n                        default:\n                            break;\n                    }\n\n                    accept(Token.RPAREN);\n                } else {\n                    SQLExpr valueExpr = this.primary();\n                    valueExpr.setParent(containsExpr);\n                    containsExpr.getTargetList().add(valueExpr);\n                    expr = containsExpr;\n                }\n\n                if (containsExpr.getTargetList().size() == 1) {\n                    SQLExpr targetExpr = containsExpr.getTargetList().get(0);\n                    if (targetExpr instanceof SQLQueryExpr) {\n                        SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr();\n                        inSubQueryExpr.setNot(true);\n                        inSubQueryExpr.setExpr(containsExpr.getExpr());\n                        inSubQueryExpr.setSubQuery(((SQLQueryExpr) targetExpr).getSubQuery());\n                        expr = inSubQueryExpr;\n                    }\n                }\n\n                break;\n            case BETWEEN:\n                lexer.nextToken();\n                SQLExpr beginExpr = relational();\n                accept(Token.AND);\n                SQLExpr endExpr = relational();\n\n                expr = new SQLBetweenExpr(expr, true, beginExpr, endExpr);\n                break;\n            case ILIKE:\n                lexer.nextToken();\n                rightExp = bitOr();\n\n                return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotILike, rightExp, dbType);\n            case LPAREN:\n                expr = this.primary();\n                break;\n            case RLIKE:\n                lexer.nextToken();\n                rightExp = bitOr();\n                expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRLike, rightExp, dbType);\n                expr = relationalRest(expr);\n                break;\n            case IDENTIFIER:\n                long hash = lexer.hashLCase();\n                if (hash == FnvHash.Constants.REGEXP) {\n                    lexer.nextToken();\n                    rightExp = bitOr();\n                    expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRegExp, rightExp, dbType);\n                    expr = relationalRest(expr);\n                }\n                break;\n            default:\n                throw new ParserException(\"unexpected token in NOT expression: \" + lexer.token + \". \" + lexer.info());\n        }\n\n        return expr;\n    }\n\n    public SQLDataType parseDataType() {\n        return parseDataType(true);\n    }\n\n    protected SQLDataType parseDataTypeNested() {\n        return null;\n    }\n\n    protected void parseDataTypeByte(StringBuilder typeName) {\n    }\n\n    protected void parseDataTypeDouble(StringBuilder typeName) {\n    }\n\n    protected void parseDataTypePrecision(StringBuilder typeName) {\n    }\n    protected void parseDataTypeComplex(StringBuilder typeName) {\n    }\n\n    protected SQLDataType parseDataTypeDate(StringBuilder typeName, int sourceLine, int sourceColumn) {\n        SQLDataType dataType = new SQLDataTypeImpl(typeName.toString());\n        dataType.setDbType(dbType);\n        dataType.setSource(sourceLine, sourceColumn);\n        return dataType;\n    }\n    public SQLDataType parseDataType(boolean restrict) {\n        if (lexer.keepSourceLocation) {\n            lexer.computeRowAndColumn();\n        }\n        int sourceLine = lexer.getPosLine(), sourceColumn = lexer.getPosColumn();\n\n        Token token = lexer.token;\n        if (token == Token.DEFAULT || token == Token.NOT || token == Token.NULL) {\n            return null;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ARRAY) || lexer.token() == Token.ARRAY) {\n            return parseArrayDataType();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.MAP)) {\n            lexer.nextToken();\n\n            if (lexer.token == Token.LPAREN) { // presto\n                lexer.nextToken();\n                SQLDataType keyType = parseDataType();\n                accept(Token.COMMA);\n                SQLDataType valueType = parseDataType();\n                accept(Token.RPAREN);\n                return new SQLMapDataType(keyType, valueType, dbType);\n            }\n\n            accept(Token.LT);\n\n            SQLDataType keyType = parseDataType();\n            accept(Token.COMMA);\n            SQLDataType valueType = parseDataType();\n            if (lexer.token == Token.GTGT) {\n                lexer.token = Token.GT;\n            } else {\n                accept(Token.GT);\n            }\n\n            return new SQLMapDataType(keyType, valueType, dbType);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.STRUCT)) {\n            return parseDataTypeStruct();\n        } else if (lexer.token == Token.TABLE) {\n            lexer.nextToken();\n            SQLTableDataType table = new SQLTableDataType();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLColumnDefinition column;\n                if (lexer.token == Token.STAR) {\n                    lexer.nextToken();\n                    column = new SQLColumnDefinition();\n                    column.setName(\"*\");\n                    accept(Token.ANY);\n                } else {\n                    column = this.parseColumn();\n                }\n                column.setParent(table);\n                table.getColumns().add(column);\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            accept(Token.RPAREN);\n            return table;\n        } else if (lexer.identifierEquals(FnvHash.Constants.ROW) || lexer.token == Token.ROW) {\n            lexer.nextToken();\n            return parseDataTypeRow();\n        } else if (lexer.identifierEquals(FnvHash.Constants.NESTED)) {\n            SQLDataType dataType = parseDataTypeNested();\n            if (dataType != null) {\n                return dataType;\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.UNIONTYPE)) {\n            lexer.nextToken();\n            accept(Token.LT);\n\n            SQLUnionDataType unionType = new SQLUnionDataType();\n            for (; ; ) {\n                SQLDataType item = this.parseDataType();\n                unionType.add(item);\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n            accept(Token.GT);\n            return unionType;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.GENERATED)\n                || lexer.identifierEquals(FnvHash.Constants.RENAME)) {\n            return null;\n        }\n\n        SQLName typeExpr = name();\n        final long typeNameHashCode = typeExpr.nameHashCode64();\n        StringBuilder typeName = new StringBuilder(typeExpr.toString());\n\n        if (typeNameHashCode == FnvHash.Constants.LONG\n                && lexer.identifierEquals(FnvHash.Constants.BYTE)) {\n            parseDataTypeByte(typeName);\n        } else if (typeNameHashCode == FnvHash.Constants.DOUBLE) {\n            parseDataTypeDouble(typeName);\n            parseDataTypePrecision(typeName);\n        }\n\n        if (typeNameHashCode == FnvHash.Constants.UNSIGNED) {\n            if (lexer.token == Token.IDENTIFIER) {\n                typeName.append(' ').append(lexer.stringVal());\n                lexer.nextToken();\n            }\n        } else if (typeNameHashCode == FnvHash.Constants.SIGNED) {\n            if (lexer.token == Token.IDENTIFIER) {\n                typeName.append(' ').append(lexer.stringVal());\n                lexer.nextToken();\n            }\n        } else if (isCharType(typeNameHashCode)) {\n            SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());\n\n            //for ads\n            if (lexer.token == Token.LBRACKET) {\n                SQLArrayDataType arrayDataType = new SQLArrayDataType(charType, dbType);\n                lexer.nextToken();\n                accept(Token.RBRACKET);\n                arrayDataType.putAttribute(\"ads.arrayDataType\", Boolean.TRUE);\n                return arrayDataType;\n            }\n\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                if (typeNameHashCode == FnvHash.Constants.ENUM) {\n                    exprList(charType.getArguments(), charType);\n                } else {\n                    SQLExpr arg = this.expr();\n                    arg.setParent(charType);\n                    charType.addArgument(arg);\n                }\n                accept(Token.RPAREN);\n            }\n\n            charType = (SQLCharacterDataType) parseCharTypeRest(charType);\n\n            if (lexer.token == Token.HINT) {\n                List<SQLCommentHint> hints = this.parseHints();\n                charType.setHints(hints);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {\n                return parseDataTypeRest(charType);\n            } else if (lexer.token == Token.LBRACKET) {\n                return parseDataTypeRest(charType);\n            }\n\n            return charType;\n        } else if (typeNameHashCode == FnvHash.Constants.DATE) {\n            return parseDataTypeRest(parseDataTypeDate(typeName, sourceLine, sourceColumn));\n        }\n\n        if (\"national\".equalsIgnoreCase(typeName.toString()) &&\n                (lexer.identifierEquals(FnvHash.Constants.CHAR)\n                        || lexer.identifierEquals(FnvHash.Constants.VARCHAR))) {\n            typeName.append(' ').append(lexer.stringVal());\n            lexer.nextToken();\n\n            SQLCharacterDataType charType = new SQLCharacterDataType(typeName.toString());\n\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                SQLExpr arg = this.expr();\n                arg.setParent(charType);\n                charType.addArgument(arg);\n                accept(Token.RPAREN);\n            }\n\n            charType = (SQLCharacterDataType) parseCharTypeRest(charType);\n\n            if (lexer.token == Token.HINT) {\n                List<SQLCommentHint> hints = this.parseHints();\n                charType.setHints(hints);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {\n                return parseDataTypeRest(charType);\n            }\n\n            return charType;\n        }\n\n        if (\"character\".equalsIgnoreCase(typeName.toString()) && \"varying\".equalsIgnoreCase(lexer.stringVal())) {\n            typeName.append(' ').append(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        parseDataTypeComplex(typeName);\n\n        SQLDataType dataType = new SQLDataTypeImpl(typeName.toString());\n        dataType.setDbType(dbType);\n\n        //for ads\n        if (lexer.token == Token.LBRACKET) {\n            dataType = new SQLArrayDataType(dataType, dbType);\n            lexer.nextToken();\n            if (lexer.token == Token.LITERAL_INT) {\n                SQLExpr arg = this.expr();\n                arg.setParent(dataType);\n                dataType.getArguments().add(arg);\n            }\n            accept(Token.RBRACKET);\n            dataType.putAttribute(\"ads.arrayDataType\", Boolean.TRUE);\n        }\n\n        dataType.setSource(sourceLine, sourceColumn);\n        return parseDataTypeRest(dataType);\n    }\n\n    protected SQLArrayDataType parseArrayDataType() {\n        lexer.nextToken();\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            SQLArrayDataType array = new SQLArrayDataType(null, dbType);\n            this.exprList(array.getArguments(), array, true);\n            accept(Token.RPAREN);\n            return array;\n        }\n\n        accept(Token.LT);\n        SQLDataType itemType = parseDataType();\n\n        if (lexer.token == Token.GTGTGT) {\n            lexer.token = Token.GTGT;\n        } else if (lexer.token == Token.GTGT) {\n            lexer.token = Token.GT;\n        } else {\n            accept(Token.GT);\n        }\n\n        SQLArrayDataType array = new SQLArrayDataType(itemType, dbType);\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            this.exprList(array.getArguments(), array, true);\n            accept(Token.RPAREN);\n        }\n\n        return array;\n    }\n\n    protected SQLStructDataType parseDataTypeStruct() {\n        acceptIdentifier(\"STRUCT\");\n\n        SQLStructDataType struct = new SQLStructDataType(dbType);\n        accept(Token.LT);\n        for (; ; ) {\n            SQLName name;\n            switch (lexer.token) {\n                case GROUP:\n                case ORDER:\n                case FROM:\n                case TO:\n                    name = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                    break;\n                default:\n                    name = this.name();\n                    break;\n            }\n\n            accept(Token.COLON);\n            SQLDataType dataType = this.parseDataType();\n            SQLStructDataType.Field field = struct.addField(name, dataType);\n\n            if (lexer.token == Token.COMMENT) {\n                lexer.nextToken();\n                SQLCharExpr chars = (SQLCharExpr) this.primary();\n                field.setComment(chars.getText());\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        if (lexer.token == Token.GTGTGT) {\n            lexer.token = Token.GTGT;\n        } else if (lexer.token == Token.GTGT) {\n            lexer.token = Token.GT;\n        } else {\n            accept(Token.GT);\n        }\n        return struct;\n    }\n\n    protected SQLRowDataType parseDataTypeRow() {\n        SQLRowDataType struct = new SQLRowDataType(dbType);\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            SQLDataType dataType = null;\n            Lexer.SavePoint mark = lexer.mark();\n            SQLName name;\n            switch (lexer.token) {\n                case GROUP:\n                case ORDER:\n                case FROM:\n                case TO:\n                    name = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                    break;\n                case ROW:\n                    lexer.nextToken();\n                    name = null;\n                    dataType = this.parseDataTypeRow();\n                    break;\n                default:\n                    name = this.name();\n                    break;\n            }\n\n            if (lexer.token == Token.COMMA) {\n                lexer.reset(mark);\n                dataType = this.parseDataType();\n                struct.addField(null, dataType);\n                lexer.nextToken();\n                continue;\n            }\n\n            if (lexer.token != Token.RPAREN) {\n                dataType = this.parseDataType();\n            }\n            SQLStructDataType.Field field = struct.addField(name, dataType);\n\n            if (lexer.token == Token.COMMENT) {\n                lexer.nextToken();\n                SQLCharExpr chars = (SQLCharExpr) this.primary();\n                field.setComment(chars.getText());\n            }\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        return struct;\n    }\n\n    protected void parseDataTypeParams(Collection<SQLExpr> exprCol, SQLDataType parent) {\n        if (nestedDataType.contains(parent.getName().toLowerCase())) {\n            exprList(exprCol, parent, true);\n        } else {\n            exprList(exprCol, parent);\n        }\n    }\n\n    protected SQLDataType parseDataTypeRest(SQLDataType dataType) {\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            parseDataTypeParams(dataType.getArguments(), dataType);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PRECISION)\n                && dataType.nameHashCode64() == FnvHash.Constants.DOUBLE) {\n            lexer.nextToken();\n            dataType.setName(\"DOUBLE PRECISION\");\n        }\n\n        long nameHash = dataType.nameHashCode64();\n        if (FnvHash.Constants.TIMESTAMP == nameHash || FnvHash.Constants.TIME == nameHash) {\n            if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) {\n                lexer.nextToken();\n                acceptIdentifier(\"TIME\");\n                acceptIdentifier(\"ZONE\");\n                dataType.setWithTimeZone(false);\n            } else if (lexer.token == Token.WITH) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.TIME)) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"ZONE\");\n                    dataType.setWithTimeZone(true);\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n        } else if (FnvHash.Constants.INTERVAL == nameHash) {\n            if (lexer.token == Token.IDENTIFIER) {\n                String interval = dataType.getName();\n                if (SQLIntervalUnit.of(lexer.stringVal) != null) {\n                    interval += ' ' + lexer.stringVal;\n                    lexer.nextToken();\n                    if (lexer.nextIf(Token.TO)) {\n                        interval += \" to \" + lexer.stringVal;\n                        lexer.nextToken();\n                        dataType.setName(interval);\n                    }\n                }\n            }\n        }\n\n        return dataType;\n    }\n\n    protected boolean isCharType(String dataTypeName) {\n        long hash = FnvHash.hashCode64(dataTypeName);\n        return isCharType(hash);\n    }\n\n    protected boolean isCharType(long hash) {\n        return hash == FnvHash.Constants.CHAR\n                || hash == FnvHash.Constants.VARCHAR\n                || hash == FnvHash.Constants.NCHAR\n                || hash == FnvHash.Constants.NVARCHAR\n                || hash == FnvHash.Constants.TINYTEXT\n                || hash == FnvHash.Constants.TEXT\n                || hash == FnvHash.Constants.MEDIUMTEXT\n                || hash == FnvHash.Constants.LONGTEXT\n                || hash == FnvHash.Constants.STRING\n                || hash == FnvHash.Constants.ENUM;\n    }\n\n    protected SQLDataType parseCharTypeRest(SQLCharacterDataType charType) {\n        if (lexer.token == Token.BINARY) {\n            charType.setHasBinary(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {\n            lexer.nextToken();\n\n            accept(Token.SET);\n\n            if (lexer.token != Token.IDENTIFIER\n                    && lexer.token != Token.LITERAL_CHARS\n                    && lexer.token != Token.BINARY) {\n                throw new ParserException(lexer.info());\n            }\n            charType.setCharSetName(lexer.stringVal());\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.CHARSET)) {\n            lexer.nextToken();\n\n            if (lexer.token != Token.IDENTIFIER\n                    && lexer.token != Token.LITERAL_CHARS\n                    && lexer.token != Token.BINARY) {\n                throw new ParserException(lexer.info());\n            }\n            charType.setCharSetName(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.token == Token.BINARY) {\n            charType.setHasBinary(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {\n            lexer.nextToken();\n\n            if (lexer.token == Token.LITERAL_ALIAS\n                    || lexer.token == Token.IDENTIFIER\n                    || lexer.token == Token.LITERAL_CHARS) {\n                StringBuilder collate = new StringBuilder(lexer.stringVal());\n                lexer.nextToken();\n                if (lexer.token == Token.DOT) {\n                    lexer.nextToken();\n                    if (lexer.token == Token.LITERAL_ALIAS\n                            || lexer.token == Token.IDENTIFIER\n                            || lexer.token == Token.LITERAL_CHARS) {\n                        collate.append(\".\").append(lexer.stringVal());\n                        lexer.nextToken();\n\n                    } else {\n                        throw new ParserException(lexer.info());\n                    }\n                }\n                charType.setCollate(collate.toString());\n            } else {\n                throw new ParserException(lexer.info());\n            }\n        }\n\n        return charType;\n    }\n\n    @Override\n    public void accept(Token token) {\n        if (lexer.token == token) {\n            lexer.nextToken();\n        } else {\n            StringBuilder sb = new StringBuilder();\n            sb.append(\"syntax error, expect \");\n            sb.append((token.name != null ? token.name : token.toString()));\n            sb.append(\", actual \");\n            sb.append((lexer.token.name != null ? lexer.token.name : lexer.token.toString()));\n            sb.append(\" \");\n            sb.append(lexer.info());\n\n            throw new ParserException(sb.toString());\n        }\n    }\n\n    public SQLColumnDefinition parseColumn() {\n        return parseColumn(null);\n    }\n\n    public SQLColumnDefinition parseColumn(SQLObject parent) {\n        SQLColumnDefinition column = createColumnDefinition();\n        column.setParent(parent);\n        column.setDbType(dbType);\n        if (Token.IF == lexer.token) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            column.setIfNotExists(true);\n        }\n        column.setName(\n                name());\n\n        final Token token = lexer.token;\n        if (token != Token.SET //\n                && token != Token.DROP\n                && token != Token.PRIMARY\n                && token != Token.RPAREN\n                && token != Token.COMMA\n                && token != Token.COMMENT\n        ) {\n            column.setDataType(\n                    parseDataType());\n        }\n        return parseColumnRest(column);\n    }\n\n    public SQLColumnDefinition createColumnDefinition() {\n        SQLColumnDefinition column = new SQLColumnDefinition();\n        column.setDbType(dbType);\n        return column;\n    }\n\n    protected SQLColumnDefinition parseColumnSpecific(SQLColumnDefinition column) {\n        return column;\n    }\n\n    protected SQLExpr parseColumnRestDefault() {\n        return bitOr();\n    }\n\n    protected void parseColumnCommentLiteralCharsRest(StringBuilder stringVal) {\n    }\n    public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {\n        switch (lexer.token) {\n            case DEFAULT:\n                lexer.nextToken();\n                SQLExpr defaultExpr = parseColumnRestDefault();\n                column.setDefaultExpr(defaultExpr);\n                return parseColumnRest(column);\n            case NOT: {\n                lexer.nextToken();\n                accept(Token.NULL);\n                SQLNotNullConstraint notNull = new SQLNotNullConstraint();\n                if (lexer.token == Token.HINT) {\n                    List<SQLCommentHint> hints = this.parseHints();\n                    notNull.setHints(hints);\n                }\n                column.addConstraint(notNull);\n                return parseColumnRest(column);\n            }\n            case NULL:\n                lexer.nextToken();\n                column.getConstraints().add(new SQLNullConstraint());\n                return parseColumnRest(column);\n            case PRIMARY:\n                lexer.nextToken();\n                accept(Token.KEY);\n                column.addConstraint(new SQLColumnPrimaryKey());\n                return parseColumnRest(column);\n            case UNIQUE:\n                lexer.nextToken();\n                if (lexer.token == Token.KEY) {\n                    lexer.nextToken();\n                }\n                column.addConstraint(new SQLColumnUniqueKey());\n                return parseColumnRest(column);\n            case ENABLE: {\n                lexer.nextToken();\n                List<SQLColumnConstraint> constraints = column.getConstraints();\n                if (!constraints.isEmpty()) {\n                    SQLColumnConstraint lastConstraint = constraints.get(constraints.size() - 1);\n                    if (lastConstraint instanceof SQLConstraintImpl) {\n                        ((SQLConstraintImpl) lastConstraint).setEnable(true);\n                    }\n                }\n                return parseColumnRest(column);\n            }\n            case DISABLE:\n                lexer.nextToken();\n                if (lexer.stringVal != null && lexer.stringVal.equalsIgnoreCase(\"novalidate\")) {\n                    column.setDisableNovalidate(true);\n                    lexer.nextToken();\n                }\n                return parseColumnRest(column);\n            case KEY:\n                lexer.nextToken();\n                column.addConstraint(new SQLColumnPrimaryKey());\n                return parseColumnRest(column);\n            case REFERENCES: {\n                SQLColumnReference ref = parseReference();\n                column.addConstraint(ref);\n                return parseColumnRest(column);\n            }\n            case CONSTRAINT:\n                lexer.nextToken();\n\n                SQLName name = this.name();\n\n                if (lexer.token == Token.PRIMARY) {\n                    lexer.nextToken();\n                    accept(Token.KEY);\n                    SQLColumnPrimaryKey pk = new SQLColumnPrimaryKey();\n                    pk.setName(name);\n                    column.addConstraint(pk);\n                    return parseColumnRest(column);\n                }\n\n                if (lexer.token == Token.UNIQUE) {\n                    lexer.nextToken();\n                    SQLColumnUniqueKey uk = new SQLColumnUniqueKey();\n                    uk.setName(name);\n\n                    column.addConstraint(uk);\n                    return parseColumnRest(column);\n                }\n\n                if (lexer.token == Token.REFERENCES) {\n                    SQLColumnReference ref = parseReference();\n                    ref.setName(name);\n                    column.addConstraint(ref);\n                    return parseColumnRest(column);\n                }\n\n                if (lexer.token == Token.NOT) {\n                    lexer.nextToken();\n                    accept(Token.NULL);\n                    SQLNotNullConstraint notNull = new SQLNotNullConstraint();\n                    notNull.setName(name);\n                    column.addConstraint(notNull);\n                    return parseColumnRest(column);\n                }\n\n                if (lexer.token == Token.CHECK) {\n                    SQLColumnCheck check = parseColumnCheck();\n                    check.setName(name);\n                    check.setParent(column);\n                    column.addConstraint(check);\n                    return parseColumnRest(column);\n                }\n\n                if (lexer.token == Token.DEFAULT) {\n                    lexer.nextToken();\n                    SQLExpr expr = this.expr();\n                    column.setDefaultExpr(expr);\n                    return parseColumnRest(column);\n                }\n\n                throw new ParserException(\"unsupported column constraint after CONSTRAINT keyword. \" + lexer.info());\n            case CHECK:\n                SQLColumnCheck check = parseColumnCheck();\n                column.addConstraint(check);\n                return parseColumnRest(column);\n            case IDENTIFIER:\n                long hash = lexer.hashLCase();\n                if (hash == FnvHash.Constants.AUTO_INCREMENT) {\n                    lexer.nextToken();\n                    column.setAutoIncrement(true);\n                    //sequence parser\n                    if (lexer.token == Token.BY) {\n                        lexer.nextToken();\n                        if (lexer.hashLCase() == FnvHash.Constants.GROUP) {\n                            lexer.nextToken();\n                            column.setSequenceType(AutoIncrementType.GROUP);\n                            if (lexer.identifierEquals(FnvHash.Constants.UNIT)) {\n                                lexer.nextToken();\n\n                                if (lexer.identifierEquals(FnvHash.Constants.COUNT)) {\n                                    lexer.nextToken();\n                                    SQLExpr unitCount = primary();\n                                    column.setUnitCount(unitCount);\n                                }\n\n                                if (lexer.token == Token.INDEX) {\n                                    lexer.nextToken();\n                                    SQLExpr unitIndex = primary();\n                                    column.setUnitIndex(unitIndex);\n                                }\n\n                                if (lexer.hashLCase() == FnvHash.Constants.STEP) {\n                                    lexer.nextToken();\n                                    SQLExpr step = primary();\n                                    column.setStep(step);\n                                }\n                            } else {\n                                return parseColumnRest(column);\n                            }\n                        } else if (lexer.hashLCase() == FnvHash.Constants.TIME) {\n                            lexer.nextToken();\n                            column.setSequenceType(AutoIncrementType.TIME);\n                            return parseColumnRest(column);\n                        } else if (lexer.hashLCase() == FnvHash.Constants.SIMPLE) {\n                            lexer.nextToken();\n                            if (lexer.hashLCase() == FnvHash.Constants.WITH) {\n                                lexer.nextToken();\n                                if (lexer.hashLCase() == FnvHash.Constants.CACHE) {\n                                    column.setSequenceType(AutoIncrementType.SIMPLE_CACHE);\n                                } else {\n                                    throw new ParserException(\"syntax error, expect CACHE after SIMPLE WITH, actual \" + lexer.stringVal() + \". \" + lexer.info());\n                                }\n                                lexer.nextToken();\n                                return parseColumnRest(column);\n                            } else {\n                                column.setSequenceType(AutoIncrementType.SIMPLE);\n                                return parseColumnRest(column);\n                            }\n                        }\n                        return parseColumnRest(column);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.UNIT)) {\n                        lexer.nextToken();\n\n                        if (lexer.identifierEquals(FnvHash.Constants.COUNT)) {\n                            lexer.nextToken();\n                            SQLExpr unitCount = primary();\n                            column.setUnitCount(unitCount);\n                        }\n\n                        if (lexer.token == Token.INDEX) {\n                            lexer.nextToken();\n                            SQLExpr unitIndex = primary();\n                            column.setUnitIndex(unitIndex);\n                        }\n\n                        if (lexer.hashLCase() == FnvHash.Constants.STEP) {\n                            lexer.nextToken();\n                            SQLExpr unitIndex = primary();\n                            column.setStep(unitIndex);\n                        }\n                    } else if (lexer.token == Token.LPAREN) {\n                        column.setIdentity(parseIdentity());\n                    }\n                    return parseColumnRest(column);\n                }\n                break;\n            case COMMENT:\n                lexer.nextToken();\n\n                if (lexer.token == Token.LITERAL_ALIAS) {\n                    String alias = lexer.stringVal();\n                    if (alias.length() > 2 && alias.charAt(0) == '\"' && alias.charAt(alias.length() - 1) == '\"') {\n                        alias = alias.substring(1, alias.length() - 1);\n                    }\n                    column.setComment(alias);\n                    lexer.nextToken();\n                } else if (lexer.token == Token.LITERAL_CHARS) {\n                    StringBuilder stringVal = new StringBuilder(lexer.stringVal());\n                    lexer.nextToken();\n                    parseColumnCommentLiteralCharsRest(stringVal);\n                    column.setComment(stringVal.toString());\n                } else {\n                    column.setComment(primary());\n                }\n                return parseColumnRest(column);\n            default:\n                return parseColumnSpecific(column);\n        }\n\n        return column;\n    }\n\n    protected void parseIdentifySpecific() {\n    }\n    protected void parsePrimaryKeyRest(SQLPrimaryKeyImpl primaryKey){\n    }\n\n    protected void parseForeignKeyRest(SQLForeignKeyImpl foreignKey){\n    }\n\n    protected SQLColumnDefinition.Identity parseIdentity() {\n        accept(Token.LPAREN);\n        SQLColumnDefinition.Identity ident = new SQLColumnDefinition.Identity();\n        parseIdentifySpecific();\n        if (lexer.token == Token.LITERAL_INT) {\n            ident.setSeed(lexer.integerValue().intValue());\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"syntax error, expect integer for IDENTITY seed, actual \" + lexer.token + \". \" + lexer.info());\n        }\n\n        if (lexer.token == Token.COMMA) {\n            lexer.nextToken();\n            if (lexer.token == Token.LITERAL_INT) {\n                ident.setIncrement(lexer.integerValue().intValue());\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"syntax error, expect integer for IDENTITY increment, actual \" + lexer.token + \". \" + lexer.info());\n            }\n        }\n\n        accept(Token.RPAREN);\n        return ident;\n    }\n\n    protected SQLColumnReference parseReference() {\n        SQLColumnReference fk = new SQLColumnReference();\n\n        lexer.nextToken();\n        fk.setTable(this.name());\n        if (lexer.nextIf(LPAREN)) {\n            this.names(fk.getColumns(), fk);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.MATCH)) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"FULL\") || lexer.token() == Token.FULL) {\n                fk.setReferenceMatch(SQLForeignKeyImpl.Match.FULL);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.PARTIAL)) {\n                fk.setReferenceMatch(SQLForeignKeyImpl.Match.PARTIAL);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(FnvHash.Constants.SIMPLE)) {\n                fk.setReferenceMatch(SQLForeignKeyImpl.Match.SIMPLE);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"syntax error, expect FULL, PARTIAL or SIMPLE after MATCH, actual \" + lexer.stringVal() + \". \" + lexer.info());\n            }\n        }\n\n        while (lexer.token() == Token.ON) {\n            lexer.nextToken();\n\n            if (lexer.token() == Token.DELETE) {\n                lexer.nextToken();\n\n                SQLForeignKeyImpl.Option option = parseReferenceOption();\n                fk.setOnDelete(option);\n            } else if (lexer.token() == Token.UPDATE) {\n                lexer.nextToken();\n\n                SQLForeignKeyImpl.Option option = parseReferenceOption();\n                fk.setOnUpdate(option);\n            } else {\n                throw new ParserException(\"syntax error, expect DELETE or UPDATE, actual \" + lexer.token() + \" \"\n                        + lexer.info());\n            }\n        }\n\n        return fk;\n    }\n\n    protected SQLForeignKeyImpl.Option parseReferenceOption() {\n        SQLForeignKeyImpl.Option option;\n        if (lexer.token() == Token.RESTRICT || lexer.identifierEquals(FnvHash.Constants.RESTRICT)) {\n            option = SQLForeignKeyImpl.Option.RESTRICT;\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.CASCADE) || lexer.token == CASCADE) {\n            option = SQLForeignKeyImpl.Option.CASCADE;\n            lexer.nextToken();\n        } else if (lexer.token() == Token.SET) {\n            lexer.nextToken();\n            if (lexer.token() == Token.NULL) {\n                accept(Token.NULL);\n                option = SQLForeignKeyImpl.Option.SET_NULL;\n            } else if (lexer.token == Token.DEFAULT) {\n                accept(Token.DEFAULT);\n                option = SQLForeignKeyImpl.Option.SET_DEFAULT;\n            } else {\n                throw new ParserException(\"syntax error,\" + lexer.info());\n            }\n        } else if (lexer.identifierEquals(FnvHash.Constants.NO)) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.ACTION)) {\n                option = SQLForeignKeyImpl.Option.NO_ACTION;\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"syntax error, expect ACTION, actual \" + lexer.token() + \" \"\n                        + lexer.info());\n            }\n        } else {\n            throw new ParserException(\"syntax error, expect ACTION, actual \" + lexer.token() + \" \"\n                    + lexer.info());\n        }\n\n        return option;\n    }\n\n    protected SQLColumnCheck parseColumnCheck() {\n        lexer.nextToken();\n        SQLExpr expr = this.primary();\n        SQLColumnCheck check = new SQLColumnCheck(expr);\n\n        if (lexer.token == Token.DISABLE) {\n            lexer.nextToken();\n            check.setEnable(false);\n        } else if (lexer.token == Token.ENABLE) {\n            lexer.nextToken();\n            check.setEnable(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.VALIDATE)) {\n            lexer.nextToken();\n            check.setValidate(Boolean.TRUE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) {\n            lexer.nextToken();\n            check.setValidate(Boolean.FALSE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.RELY)) {\n            lexer.nextToken();\n            check.setRely(Boolean.TRUE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.NORELY)) {\n            lexer.nextToken();\n            check.setRely(Boolean.FALSE);\n        } else if (lexer.identifierEquals(\"ENFORCED\")) {\n            lexer.nextToken();\n            check.setEnforced(true);\n        } else if (lexer.token == Token.NOT) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"ENFORCED\")) {\n                lexer.nextToken();\n                check.setEnforced(false);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        return check;\n    }\n\n    public SQLPrimaryKey parsePrimaryKey() {\n        accept(Token.PRIMARY);\n        accept(Token.KEY);\n\n        SQLPrimaryKeyImpl pk = new SQLPrimaryKeyImpl();\n\n        if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {\n            lexer.nextToken();\n            pk.setClustered(true);\n        }\n\n        accept(Token.LPAREN);\n        orderBy(pk.getColumns(), pk);\n        accept(Token.RPAREN);\n\n        if (lexer.token == Token.DISABLE) {\n            lexer.nextToken();\n            acceptIdentifier(\"NOVALIDATE\");\n            pk.setDisableNovalidate(true);\n        }\n        parsePrimaryKeyRest(pk);\n        return pk;\n    }\n\n    public SQLUnique parseUnique() {\n        accept(Token.UNIQUE);\n\n        SQLUnique unique = new SQLUnique();\n        accept(Token.LPAREN);\n        orderBy(unique.getColumns(), unique);\n        accept(Token.RPAREN);\n\n        if (lexer.token == Token.DISABLE) {\n            lexer.nextToken();\n            SavePoint savePoint = lexer.mark();\n            if (\"NOVALIDATE\".equalsIgnoreCase(lexer.stringVal())) {\n                unique.setDisableNovalidate(true);\n                lexer.nextToken();\n            } else {\n                lexer.reset(savePoint);\n            }\n        } else if (lexer.token == Token.ENABLE) {\n            lexer.nextToken();\n            unique.setEnable(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.VALIDATE)) {\n            lexer.nextToken();\n            unique.setValidate(Boolean.TRUE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) {\n            lexer.nextToken();\n            unique.setValidate(Boolean.FALSE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.RELY)) {\n            lexer.nextToken();\n            unique.setRely(Boolean.TRUE);\n        } else if (lexer.identifierEquals(FnvHash.Constants.NORELY)) {\n            lexer.nextToken();\n            unique.setRely(Boolean.FALSE);\n        }\n\n        return unique;\n    }\n\n    /**\n     * Parse constraint state options: ENABLE/DISABLE, VALIDATE/NOVALIDATE, RELY/NORELY.\n     * Common across Oracle, base SQL, and other dialects.\n     * Callers can use this to avoid duplicating the same if-else chain.\n     *\n     * @param constraint the unique constraint to set options on\n     * @return true if at least one option was parsed\n     */\n    protected boolean parseConstraintStateOptions(SQLUnique constraint) {\n        boolean parsed = false;\n        for (; ; ) {\n            if (lexer.token == Token.ENABLE) {\n                lexer.nextToken();\n                constraint.setEnable(Boolean.TRUE);\n                parsed = true;\n            } else if (lexer.token == Token.DISABLE) {\n                lexer.nextToken();\n                SavePoint savePoint = lexer.mark();\n                if (\"NOVALIDATE\".equalsIgnoreCase(lexer.stringVal())) {\n                    constraint.setDisableNovalidate(true);\n                    lexer.nextToken();\n                } else {\n                    lexer.reset(savePoint);\n                    constraint.setEnable(Boolean.FALSE);\n                }\n                parsed = true;\n            } else if (lexer.identifierEquals(FnvHash.Constants.VALIDATE)) {\n                lexer.nextToken();\n                constraint.setValidate(Boolean.TRUE);\n                parsed = true;\n            } else if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) {\n                lexer.nextToken();\n                constraint.setValidate(Boolean.FALSE);\n                parsed = true;\n            } else if (lexer.identifierEquals(FnvHash.Constants.RELY)) {\n                lexer.nextToken();\n                constraint.setRely(Boolean.TRUE);\n                parsed = true;\n            } else if (lexer.identifierEquals(FnvHash.Constants.NORELY)) {\n                lexer.nextToken();\n                constraint.setRely(Boolean.FALSE);\n                parsed = true;\n            } else {\n                break;\n            }\n        }\n        return parsed;\n    }\n\n    public void parseAssignItem(List<SQLAssignItem> outList, SQLObject parent) {\n        accept(Token.LPAREN);\n        if (lexer.token() != Token.RPAREN) {\n            for (; ; ) {\n                SQLAssignItem item = this.parseAssignItem(true, parent);\n                item.setParent(parent);\n                outList.add(item);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n        accept(Token.RPAREN);\n    }\n\n    public SQLAssignItem parseAssignItem() {\n        return parseAssignItem(true, null);\n    }\n\n    public SQLAssignItem parseAssignItem(boolean variant) {\n        return parseAssignItem(variant, null);\n    }\n\n    protected void parseAssignItemDot() {\n    }\n\n    protected void parseAssignItemNcToBeExecuted() {\n    }\n\n    protected boolean parseAssignItemTblProperties(SQLAssignItem item) {\n        return false;\n    }\n\n    protected SQLExpr parseAssignItemSQLPropertyExprAndSub(SQLExpr sqlExpr) {\n        return sqlExpr;\n    }\n\n    protected void parseAssignItemSQLIdentifierExpr(SQLExpr sqlExpr) {\n    }\n\n    protected SQLExpr parseAssignItemSQLPropertyExpr(SQLExpr sqlExpr) {\n        return sqlExpr;\n    }\n\n    protected void parseAssignItemSQLIdentifierExprAndVariant(SQLIdentifierExpr ident) {\n    }\n\n    protected boolean parseAssignItemSQLMethodInvokeExpr(SQLExpr sqlExpr, SQLAssignItem item) {\n        return false;\n    }\n\n    protected void parseAssignItemEq(SQLObject parent) {\n        lexer.nextToken();\n    }\n\n    protected SQLExpr parseAssignItemOnLiteralFloat(SQLExpr sqlExpr) {\n        return sqlExpr;\n    }\n\n    protected SQLExpr parseAssignItemOnColon(SQLExpr sqlExpr) {\n        return sqlExpr;\n    }\n\n    protected void parseAssignItemOnComma(SQLExpr sqlExpr, SQLAssignItem item, SQLObject parent) {\n        item.setValue(sqlExpr);\n    }\n    public SQLAssignItem parseAssignItem(boolean variant, SQLObject parent) {\n        SQLAssignItem item = new SQLAssignItem();\n        parseAssignItemDot();\n\n        SQLExpr var;\n\n        parseAssignItemNcToBeExecuted();\n\n        if (lexer.identifierEquals(FnvHash.Constants.TBLPROPERTIES)) {\n            var = new SQLIdentifierExpr(lexer.stringVal());\n            lexer.nextToken();\n            if (parseAssignItemTblProperties(item)) {\n                return item;\n            }\n        } else {\n            var = primary();\n        }\n\n        var = parseAssignItemSQLPropertyExprAndSub(var);\n        parseAssignItemSQLIdentifierExpr(var);\n        var = parseAssignItemSQLPropertyExpr(var);\n\n        if (variant && var instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr ident = (SQLIdentifierExpr) var;\n            parseAssignItemSQLIdentifierExprAndVariant(ident);\n            String identName = (ident).getName();\n            if (identName.indexOf('@') != -1\n                    || identName.indexOf('#') != -1\n                    || identName.indexOf(':') != -1\n                    || identName.indexOf(' ') != -1) {\n                var = new SQLVariantRefExpr(identName);\n            }\n        }\n\n        if (parseAssignItemSQLMethodInvokeExpr(var, item)) {\n            return item;\n        }\n\n        item.setTarget(var);\n\n        if (lexer.token == Token.COLONEQ) {\n            lexer.nextToken();\n        } else if (lexer.token == Token.TRUE || lexer.identifierEquals(FnvHash.Constants.TRUE)) {\n            lexer.nextToken();\n            item.setValue(new SQLBooleanExpr(true));\n            return item;\n        } else if (lexer.token == Token.ON) {\n            lexer.nextToken();\n            item.setValue(new SQLIdentifierExpr(\"ON\"));\n            return item;\n        } else if ((lexer.token == Token.RPAREN || lexer.token == Token.COMMA || lexer.token == Token.SET)\n                && dialectFeatureEnabled(ParseAssignItemRparenCommaSetReturn)) {\n            return item;\n        } else {\n            if (lexer.token == Token.EQ) {\n                parseAssignItemEq(parent);\n                if (lexer.token == Token.SEMI && dialectFeatureEnabled(ParseAssignItemEqSemiReturn)) {\n                    return item;\n                }\n            } else if (dialectFeatureEnabled(ParseAssignItemSkip)\n                    || lexer.token == Token.QUES\n                    || lexer.token == Token.LITERAL_CHARS\n                    || lexer.token == Token.LITERAL_ALIAS\n                    || lexer.identifierEquals(\"utf8mb4\")\n            ) {\n                // skip\n            } else if (lexer.token == Token.EQEQ && dialectFeatureEnabled(ParseAssignItemEqeq)) {\n                lexer.nextToken();\n            } else {\n                accept(Token.EQ);\n            }\n        }\n\n        if (lexer.token == Token.ON) {\n            item.setValue(new SQLIdentifierExpr(lexer.stringVal()));\n            lexer.nextToken();\n        } else {\n            if (lexer.token == Token.ALL) {\n                item.setValue(new SQLIdentifierExpr(lexer.stringVal()));\n                lexer.nextToken();\n            } else {\n                SQLExpr expr = expr();\n                expr = parseAssignItemOnLiteralFloat(expr);\n                expr = parseAssignItemOnColon(expr);\n                parseAssignItemOnComma(expr, item, parent);\n            }\n        }\n        return item;\n    }\n\n    public List<SQLCommentHint> parseHints() {\n        List<SQLCommentHint> hints = new ArrayList<SQLCommentHint>();\n        parseHints(hints);\n        return hints;\n    }\n\n    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n    public void parseHints(List hints) {\n        while (lexer.token == Token.HINT) {\n            String text = lexer.stringVal();\n            SQLCommentHint hint;\n\n            if (lexer.isEnabled(SQLParserFeature.TDDLHint)\n                    && (text.startsWith(\"+ TDDL\")\n                    || text.startsWith(\"+TDDL\")\n                    || text.startsWith(\"!TDDL\")\n                    || text.startsWith(\"TDDL\"))) {\n                hint = new TDDLHint(text);\n            } else {\n                hint = new SQLCommentHint(text);\n            }\n\n            if (lexer.commentCount > 0) {\n                hint.addBeforeComment(lexer.comments);\n            }\n\n            hints.add(hint);\n            lexer.nextToken();\n        }\n    }\n\n    public SQLCommentHint parseHint() {\n        String text = lexer.stringVal();\n        SQLCommentHint hint;\n\n        if (lexer.isEnabled(SQLParserFeature.TDDLHint)\n                && (text.startsWith(\"+ TDDL\")\n                || text.startsWith(\"+TDDL\")\n                || text.startsWith(\"!TDDL\")\n                || text.startsWith(\"TDDL\"))) {\n            hint = new TDDLHint(text);\n        } else {\n            hint = new SQLCommentHint(text);\n        }\n\n        if (lexer.commentCount > 0) {\n            hint.addBeforeComment(lexer.comments);\n        }\n\n        lexer.nextToken();\n        return hint;\n    }\n\n    protected void parseIndexSpecific(SQLIndexDefinition indexDefinition) {\n        indexDefinition.setName(name());\n    }\n\n    protected void parseIndexOptions(SQLIndexDefinition indexDefinition) {\n        while (true) {\n            if (lexer.token() == Token.COMMENT) {\n                lexer.nextToken();\n                indexDefinition.getOptions().setComment(primary());\n            } else {\n                break;\n            }\n        }\n    }\n\n    public void parseIndex(SQLIndexDefinition indexDefinition) {\n        if (lexer.token() == Token.CONSTRAINT) {\n            indexDefinition.setHasConstraint(true);\n            lexer.nextToken();\n            if (lexer.token() == Token.IDENTIFIER\n                    && !lexer.identifierEquals(FnvHash.Constants.GLOBAL)\n                    && !lexer.identifierEquals(FnvHash.Constants.LOCAL)\n                    && !lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {\n                indexDefinition.setSymbol(name());\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.GLOBAL)) {\n            indexDefinition.setGlobal(true);\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n            indexDefinition.setLocal(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.FULLTEXT\n                || lexer.token() == Token.UNIQUE\n                || lexer.token() == Token.PRIMARY\n                || lexer.identifierEquals(FnvHash.Constants.SPATIAL)\n                || lexer.identifierEquals(FnvHash.Constants.CLUSTERED)\n                || lexer.identifierEquals(FnvHash.Constants.CLUSTERING)\n                || lexer.identifierEquals(FnvHash.Constants.ANN)) {\n            indexDefinition.setType(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.GLOBAL)) {\n            indexDefinition.setGlobal(true);\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(FnvHash.Constants.LOCAL)) {\n            indexDefinition.setLocal(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.token() == Token.INDEX) {\n            indexDefinition.setIndex(true);\n            lexer.nextToken();\n        } else if (lexer.token() == Token.KEY) {\n            indexDefinition.setKey(true);\n            lexer.nextToken();\n        }\n\n        while (lexer.token() != Token.LPAREN && lexer.token() != Token.ON) {\n            parseIndexSpecific(indexDefinition);\n        }\n\n        if (lexer.token() == Token.ON) {\n            lexer.nextToken();\n            indexDefinition.setTable(new SQLExprTableSource(name()));\n        }\n\n        parseIndexRest(indexDefinition, indexDefinition.getParent());\n\n        // Options, partitions.\n        parseIndexOptions(indexDefinition);\n    }\n\n    public SQLConstraint parseConstraint() {\n        SQLName name = null;\n\n        boolean nextIfConstraint = lexer.nextIf(CONSTRAINT);\n        if (nextIfConstraint) {\n            if (lexer.token != PRIMARY\n                    && lexer.token != UNIQUE\n                    && lexer.token != KEY\n                    && lexer.token != FOREIGN\n                    && lexer.token != CHECK\n                    && lexer.token != DEFAULT\n            ) {\n                name = this.name();\n            }\n        }\n\n        SQLConstraint constraint;\n        switch (lexer.token) {\n            case PRIMARY:\n                constraint = parsePrimaryKey();\n                break;\n            case UNIQUE:\n                constraint = parseUnique();\n                break;\n            case KEY:\n                constraint = parseUnique();\n                break;\n            case FOREIGN:\n                constraint = parseForeignKey();\n                break;\n            case CHECK:\n                constraint = parseCheck();\n                break;\n            case DEFAULT:\n                constraint = parseDefault();\n                break;\n            default:\n                throw new ParserException(\"unsupported constraint type: \" + lexer.token + \". \" + lexer.info());\n        }\n\n        if (name == null && lexer.token == Token.IDENTIFIER) {\n            name = name();\n        }\n\n        if (name != null) {\n            constraint.setName(name);\n        }\n\n        if (nextIfConstraint) {\n            constraint.setHasConstraint(true);\n        }\n\n        return constraint;\n    }\n\n    public SQLCheck parseCheck() {\n        accept(Token.CHECK);\n        SQLCheck check = createCheck();\n        accept(Token.LPAREN);\n        check.setExpr(this.expr());\n        if (check.getExpr() instanceof SQLExprImpl) {\n            ((SQLExprImpl) check.getExpr()).setParenthesized(true);\n        }\n        accept(Token.RPAREN);\n        return check;\n    }\n\n    public SQLDefault parseDefault() {\n        accept(Token.DEFAULT);\n        SQLDefault sqlDefault = new SQLDefault();\n\n        if (lexer.token == Token.LPAREN) {\n            while (lexer.token == Token.LPAREN) {\n                accept(Token.LPAREN);\n            }\n\n            sqlDefault.setExpr(this.expr());\n\n            while (lexer.token == Token.RPAREN) {\n                accept(Token.RPAREN);\n            }\n        } else {\n            sqlDefault.setExpr(this.expr());\n        }\n\n        accept(Token.FOR);\n        sqlDefault.setColumn(this.expr());\n\n        if (lexer.token == Token.WITH) {\n            lexer.nextToken();\n            accept(Token.VALUES);\n            sqlDefault.setWithValues(true);\n        }\n\n        return sqlDefault;\n    }\n\n    protected SQLCheck createCheck() {\n        return new SQLCheck();\n    }\n\n    public SQLForeignKeyConstraint parseForeignKey() {\n        accept(Token.FOREIGN);\n        accept(Token.KEY);\n\n        SQLForeignKeyImpl fk = createForeignKey();\n\n        accept(Token.LPAREN);\n        this.names(fk.getReferencingColumns(), fk);\n        accept(Token.RPAREN);\n\n        accept(Token.REFERENCES);\n\n        fk.setReferencedTableName(this.name());\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            this.names(fk.getReferencedColumns(), fk);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token == Token.ON) {\n            lexer.nextToken();\n            accept(Token.DELETE);\n            if (lexer.identifierEquals(FnvHash.Constants.CASCADE) || lexer.token == Token.CASCADE) {\n                lexer.nextToken();\n                fk.setOnDeleteCascade(true);\n            } else {\n                accept(Token.SET);\n                accept(Token.NULL);\n                fk.setOnDeleteSetNull(true);\n            }\n        }\n\n        if (lexer.token == Token.DISABLE) {\n            Lexer.SavePoint mark = lexer.mark();\n\n            lexer.nextToken();\n            if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) {\n                lexer.nextToken();\n                fk.setDisableNovalidate(true);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n        parseForeignKeyRest(fk);\n        return fk;\n    }\n\n    protected SQLForeignKeyImpl createForeignKey() {\n        return new SQLForeignKeyImpl();\n    }\n\n    protected SQLExpr parseSelectItemRest(String ident, long hash_lower) {\n        SQLExpr expr = null;\n        if (FnvHash.Constants.TIMESTAMP == hash_lower\n                && lexer.stringVal().charAt(0) != '`'\n                && lexer.token == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLTimestampExpr ts = new SQLTimestampExpr(literal);\n            expr = ts;\n\n            if (lexer.identifierEquals(FnvHash.Constants.AT)) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n\n                String timeZone = null;\n                if (lexer.identifierEquals(FnvHash.Constants.TIME)) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(FnvHash.Constants.ZONE)) {\n                        lexer.nextToken();\n                        timeZone = lexer.stringVal();\n                        lexer.nextToken();\n                    }\n                }\n                if (timeZone == null) {\n                    lexer.reset(mark);\n                } else {\n                    ts.setTimeZone(timeZone);\n                }\n            }\n        } else if (FnvHash.Constants.DATETIME == hash_lower\n                && lexer.stringVal().charAt(0) != '`'\n                && lexer.token == Token.LITERAL_CHARS) {\n            String literal = lexer.stringVal();\n            lexer.nextToken();\n\n            SQLDateTimeExpr ts = new SQLDateTimeExpr(literal);\n            expr = ts;\n        }\n        return expr;\n    }\n\n    protected Pair<String, SQLExpr> parseSelectItemIdentifier(SQLExpr expr) {\n        String as = lexer.stringVal();\n        if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && as.length() > 1) {\n            as = StringUtils.removeNameQuotes(as);\n        }\n        lexer.nextTokenComma();\n        return Pair.of(as, expr);\n    }\n\n    protected SQLExpr parseSelectItemMethod(SQLExpr expr) {\n        return this.methodRest(expr, true);\n    }\n\n    protected String parseSelectItemAlias(String alias) {\n        boolean specialChar = false;\n        for (int i = 0; i < alias.length(); ++i) {\n            char ch = alias.charAt(i);\n            if (!CharTypes.isIdentifierChar(ch)) {\n                specialChar = true;\n                break;\n            }\n        }\n        if (specialChar) {\n            alias = alias.replaceAll(\"\\\"\", \"\\\\\\\"\");\n        }\n        return alias;\n    }\n    public SQLSelectItem parseSelectItem() {\n        SQLExpr expr;\n        boolean connectByRoot = false;\n        Token token = lexer.token;\n        int startPos = lexer.startPos;\n        if (token == Token.IDENTIFIER\n                && !(lexer.hashLCase() == -5808529385363204345L && lexer.charAt(lexer.pos) == '\\'' && (dialectFeatureEnabled(\n                ParseSelectItemPrefixX))) // x'123' X'123'\n        ) {\n            int sourceLine = -1, sourceColumn = -1;\n            if (lexer.isKeepSourceLocation()) {\n                lexer.computeRowAndColumn();\n                sourceLine = lexer.getPosLine();\n                sourceColumn = lexer.getPosColumn();\n            }\n\n            String ident = lexer.stringVal();\n            long hash_lower = lexer.hashLCase();\n            lexer.nextTokenComma();\n\n            if (hash_lower == FnvHash.Constants.CONNECT_BY_ROOT) {\n                connectByRoot = lexer.token != Token.LPAREN;\n                if (connectByRoot) {\n                    expr = new SQLIdentifierExpr(lexer.stringVal());\n                    lexer.nextToken();\n                } else {\n                    expr = new SQLIdentifierExpr(ident);\n                }\n            } else if (FnvHash.Constants.DATE == hash_lower\n                    && lexer.stringVal().charAt(0) != '`'\n                    && (lexer.token == Token.LITERAL_CHARS || lexer.token == LITERAL_ALIAS)\n                    && (dialectFeatureEnabled(SQLDateExpr))\n            ) {\n                String literal = lexer.stringVal();\n                lexer.nextToken();\n\n                SQLDateExpr dateExpr = new SQLDateExpr();\n                dateExpr.setValue(literal);\n\n                expr = dateExpr;\n            } else if (FnvHash.Constants.TIME == hash_lower\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String literal = lexer.stringVal();\n                lexer.nextToken();\n\n                expr = new SQLTimeExpr(literal);\n            } else if (hash_lower == FnvHash.Constants.DECIMAL\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String decimal = lexer.stringVal();\n                expr = new SQLDecimalExpr(decimal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.REAL\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String decimal = lexer.stringVal();\n                expr = new SQLRealExpr(decimal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.DOUBLE\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String decimal = lexer.stringVal();\n                expr = new SQLDoubleExpr(decimal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.FLOAT\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String decimal = lexer.stringVal();\n                expr = new SQLFloatExpr(decimal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.BIGINT\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String strVal = lexer.stringVal();\n                if (strVal.startsWith(\"--\")) {\n                    strVal = strVal.substring(2);\n                }\n                expr = new SQLBigIntExpr(strVal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.INTEGER\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String strVal = lexer.stringVal();\n                if (strVal.startsWith(\"--\")) {\n                    strVal = strVal.substring(2);\n                }\n                SQLIntegerExpr integerExpr = SQLIntegerExpr.ofIntOrLong(Long.parseLong(strVal));\n                integerExpr.setType(\"INTEGER\");\n                expr = integerExpr;\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.SMALLINT\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String decimal = lexer.stringVal();\n                expr = new SQLSmallIntExpr(decimal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.TINYINT\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String decimal = lexer.stringVal();\n                expr = new SQLTinyIntExpr(decimal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.JSON\n                    && lexer.token == Token.LITERAL_CHARS) {\n                String decimal = lexer.stringVal();\n                expr = new SQLJSONExpr(decimal);\n                lexer.nextToken();\n            } else if (hash_lower == FnvHash.Constants.TRY_CAST) {\n                accept(Token.LPAREN);\n                SQLCastExpr cast = new SQLCastExpr();\n                cast.setTry(true);\n                cast.setExpr(expr());\n                accept(Token.AS);\n                cast.setDataType(parseDataType(false));\n                accept(Token.RPAREN);\n                expr = cast;\n            } else if (FnvHash.Constants.CURRENT_USER == hash_lower\n                    && ident.charAt(0) != '`'\n                    && lexer.token != Token.LPAREN && isEnabled(SQLParserFeature.EnableCurrentUserExpr)) {\n                expr = new SQLCurrentUserExpr();\n            } else {\n                expr = parseSelectItemRest(ident, hash_lower);\n                if (expr == null) {\n                    if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                        ident = SQLUtils.normalize(ident, dbType);\n                    }\n                    if (ident.charAt(0) == '\"' && ident.charAt(ident.length() - 1) == '\"') {\n                        hash_lower = FnvHash.hashCode64(ident);\n                    }\n                    SQLIdentifierExpr identifierExpr = new SQLIdentifierExpr(ident, hash_lower);\n                    if (lexer.keepSourceLocation) {\n                        lexer.computeRowAndColumn();\n                        identifierExpr.setSource(lexer.posLine, lexer.posColumn);\n                    }\n                    expr = identifierExpr;\n                }\n            }\n\n            token = lexer.token;\n\n            if (token == Token.DOT) {\n                lexer.nextTokenIdent();\n\n                if (lexer.token == Token.STAR) {\n                    expr = dotRest(expr);\n                } else {\n                    String name = lexer.stringVal();\n                    long name_hash_lower = lexer.hashLCase();\n                    lexer.nextTokenComma();\n\n                    token = lexer.token;\n                    if (token == Token.LPAREN) {\n                        boolean aggregate = hash_lower == FnvHash.Constants.WMSYS && name_hash_lower == FnvHash.Constants.WM_CONCAT;\n                        expr = methodRest(expr, name, aggregate);\n                        token = lexer.token;\n                    } else {\n                        if (name_hash_lower == FnvHash.Constants.NEXTVAL) {\n                            expr = new SQLSequenceExpr((SQLIdentifierExpr) expr, SQLSequenceExpr.Function.NextVal);\n                        } else if (name_hash_lower == FnvHash.Constants.CURRVAL) {\n                            expr = new SQLSequenceExpr((SQLIdentifierExpr) expr, SQLSequenceExpr.Function.CurrVal);\n                        } else if (name_hash_lower == FnvHash.Constants.PREVVAL) {\n                            expr = new SQLSequenceExpr((SQLIdentifierExpr) expr, SQLSequenceExpr.Function.PrevVal);\n                        } else {\n                            if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {\n                                name = SQLUtils.normalize(name, dbType);\n                            }\n                            if (name.charAt(0) == '\"') {\n                                name_hash_lower = FnvHash.hashCode64(name);\n                            }\n                            expr = new SQLPropertyExpr(expr, name, name_hash_lower);\n                        }\n                    }\n                }\n            }\n\n            if (token == Token.COMMA) {\n                return new SQLSelectItem(expr, (String) null, connectByRoot);\n            }\n\n            if (token == Token.AS) {\n                lexer.nextTokenAlias();\n                String as = null;\n                if (lexer.token != Token.COMMA && lexer.token != Token.FROM) {\n                    as = lexer.stringVal();\n                    if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && as.length() > 1) {\n                        as = StringUtils.removeNameQuotes(as);\n                    }\n\n                    lexer.nextTokenComma();\n\n                    if (lexer.token == Token.DOT) {\n                        lexer.nextToken();\n                        as += '.' + lexer.stringVal();\n                        lexer.nextToken();\n                    }\n                }\n\n                return new SQLSelectItem(expr, as, connectByRoot);\n            }\n\n            if (token == Token.LITERAL_ALIAS) {\n                String as = lexer.stringVal();\n                if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && as.length() > 1) {\n                    as = StringUtils.removeNameQuotes(as);\n                }\n                lexer.nextTokenComma();\n                return new SQLSelectItem(expr, as, connectByRoot);\n            }\n\n            if (token == Token.IDENTIFIER\n                    && hash_lower != FnvHash.Constants.CURRENT) {\n                Pair<String, SQLExpr> pair = parseSelectItemIdentifier(expr);\n                String as = pair.getKey();\n                expr = pair.getValue();\n                return new SQLSelectItem(expr, as, connectByRoot);\n            }\n\n            if (token == Token.LPAREN) {\n                expr = parseSelectItemMethod(expr);\n            } else {\n                expr = this.primaryRest(expr);\n            }\n            expr = this.exprRest(expr);\n\n            if (sourceLine != -1) {\n                expr.setSource(sourceLine, sourceColumn);\n            }\n        } else if (lexer.nextIf(STAR)) {\n            SQLAllColumnExpr star = new SQLAllColumnExpr();\n\n            if (lexer.nextIf(Token.EXCEPT)) {\n                accept(Token.LPAREN);\n                List<SQLExpr> except = new ArrayList<>();\n                this.exprList(except, star);\n                star.setExcept(except);\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.nextIf(REPLACE)) {\n                accept(Token.LPAREN);\n                this.aliasedItems(star.getReplace(), star);\n                accept(Token.RPAREN);\n            }\n\n            expr = star;\n            return new SQLSelectItem(expr, (String) null, connectByRoot);\n        } else if (token == Token.DO || token == Token.JOIN || token == Token.TABLESPACE) {\n            expr = this.name();\n            expr = this.exprRest(expr);\n        } else {\n            if (lexer.token == Token.DISTINCT && dbType == DbType.elastic_search) {\n                lexer.nextToken();\n            }\n\n            while (lexer.token == Token.HINT) {\n                lexer.nextToken();\n            }\n            expr = expr();\n        }\n\n        String alias;\n        List<String> aliasList = null;\n        if (expr instanceof SQLVariantRefExpr && ((SQLVariantRefExpr) expr).isTemplateParameter() && lexer.token != AS) {\n            alias = null;\n        } else {\n            switch (lexer.token) {\n                case FULL:\n                case TABLESPACE:\n                    alias = lexer.stringVal();\n                    lexer.nextToken();\n                    break;\n                case AS:\n                    lexer.nextTokenAlias();\n                    if (lexer.token == Token.LITERAL_INT) {\n                        alias = '\"' + lexer.stringVal() + '\"';\n                        lexer.nextToken();\n                    } else if (lexer.token == Token.LPAREN) {\n                        lexer.nextToken();\n                        aliasList = new ArrayList<String>();\n                        for (; ; ) {\n                            String stringVal = lexer.stringVal();\n                            lexer.nextToken();\n                            aliasList.add(stringVal);\n                            if (lexer.token() == Token.COMMA) {\n                                lexer.nextToken();\n                                continue;\n                            }\n                            break;\n                        }\n                        accept(Token.RPAREN);\n\n                        alias = null;\n                    } else {\n                        alias = alias();\n                    }\n                    break;\n                case EOF:\n                    alias = null;\n                    break;\n                default:\n                    alias = as();\n                    break;\n            }\n        }\n\n        if (alias == null && isEnabled(SQLParserFeature.SelectItemGenerateAlias)\n                && (!(expr instanceof SQLName))\n                && !(expr instanceof SQLNumericLiteralExpr)\n                && !(expr instanceof SQLCharExpr)\n                && !(expr instanceof SQLNullExpr)\n                && !(expr instanceof SQLBooleanExpr)) {\n            alias = lexer.text.substring(startPos, lexer.startPos);\n\n            if (lexer.comments != null) {\n                for (int i = lexer.comments.size() - 1; i >= 0; i--) {\n                    String comment = lexer.comments.get(i);\n                    int p = alias.lastIndexOf(comment);\n                    if (p >= 0) {\n                        alias = alias.substring(0, p - 1);\n                    }\n                }\n            }\n\n            alias = CharTypes.trim(alias);\n\n            if (alias.length() > 0) {\n                alias = parseSelectItemAlias(alias);\n            }\n        }\n\n        SQLSelectItem selectItem;\n        if (aliasList != null) {\n            selectItem = new SQLSelectItem(expr, aliasList, connectByRoot);\n        } else {\n            selectItem = new SQLSelectItem(expr, alias, connectByRoot);\n        }\n        if (lexer.token == Token.HINT && !lexer.isEnabled(SQLParserFeature.StrictForWall)) {\n            String comment = \"/*\" + lexer.stringVal() + \"*/\";\n            selectItem.addAfterComment(comment);\n            lexer.nextToken();\n        }\n\n        return selectItem;\n    }\n\n    public SQLPartition parsePartition() {\n        if (lexer.nextIf(Token.PARTITION)) {\n            SQLPartitionSingle partitionDef = new SQLPartitionSingle();\n            SQLName name = this.name();\n            partitionDef.setName(name);\n            partitionDef.setValues(this.parsePartitionValues());\n            return partitionDef;\n        } else if (lexer.nextIf(START) || lexer.nextIfIdentifier(FnvHash.Constants.START)) {\n            SQLPartitionBatch partitionDef = new SQLPartitionBatch();\n            accept(Token.LPAREN);\n            partitionDef.setStart(this.expr());\n            accept(Token.RPAREN);\n            if (lexer.nextIf(Token.END) || lexer.nextIfIdentifier(FnvHash.Constants.END)) {\n                accept(Token.LPAREN);\n                partitionDef.setEnd(this.expr());\n                accept(Token.RPAREN);\n            } else {\n                throw new ParserException(\"syntax error, expect END, \" + lexer.info());\n            }\n            acceptIdentifier(FnvHash.Constants.EVERY);\n            accept(Token.LPAREN);\n            partitionDef.setEvery(this.expr());\n            accept(Token.RPAREN);\n            return partitionDef;\n        }\n        return null;\n    }\n\n    public SQLPartitionSpec parsePartitionSpec() {\n        SQLPartitionSpec spec = new SQLPartitionSpec();\n        accept(Token.PARTITION);\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            SQLPartitionSpec.Item item = new SQLPartitionSpec.Item();\n            item.setColumn(\n                    this.name());\n\n            accept(Token.EQ);\n\n            item.setValue(\n                    this.expr());\n\n            spec.addItem(item);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n        }\n\n        accept(Token.RPAREN);\n        return spec;\n    }\n\n    public SQLPartitionBy parsePartitionBy() {\n        lexer.nextToken();\n        accept(Token.BY);\n\n        SQLPartitionBy partitionClause = null;\n        if (lexer.identifierEquals(\"VALUE\")) {\n            partitionClause = new SQLPartitionByValue();\n            if (lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.LPAREN) {\n                    lexer.nextToken();\n                    partitionClause.addColumn(expr());\n                    accept(Token.RPAREN);\n                }\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {\n                lexer.nextToken();\n                partitionClause.setLifeCycle((SQLIntegerExpr) expr());\n            }\n        }\n        return partitionClause;\n    }\n\n    public SQLExpr parseGroupingSet() {\n        String tmp = lexer.stringVal();\n        acceptIdentifier(\"GROUPING\");\n\n        SQLGroupingSetExpr expr = new SQLGroupingSetExpr();\n\n        if (lexer.token == Token.SET || lexer.identifierEquals(FnvHash.Constants.SET)) {\n            lexer.nextToken();\n        } else {\n            return new SQLIdentifierExpr(tmp);\n        }\n\n        accept(Token.LPAREN);\n\n        this.exprList(expr.getParameters(), expr);\n\n        accept(Token.RPAREN);\n\n        return expr;\n    }\n\n    public SQLPartitionValue parsePartitionValues() {\n        SQLPartitionValue values = null;\n        if (lexer.nextIf(Token.VALUES)) {\n            if (lexer.nextIf(Token.IN)) {\n                values = new SQLPartitionValue(SQLPartitionValue.Operator.In);\n                accept(Token.LPAREN);\n                this.exprList(values.getItems(), values);\n                accept(Token.RPAREN);\n            } else if (lexer.nextIfIdentifier(FnvHash.Constants.LESS)) {\n                acceptIdentifier(FnvHash.Constants.THAN);\n                values = new SQLPartitionValue(SQLPartitionValue.Operator.LessThan);\n                if (lexer.nextIfIdentifier(FnvHash.Constants.MAXVALUE)) {\n                    SQLIdentifierExpr maxValue = new SQLIdentifierExpr(\"MAXVALUE\");\n                    maxValue.setParent(values);\n                    values.addItem(maxValue);\n                } else {\n                    accept(Token.LPAREN);\n                    this.exprList(values.getItems(), values);\n                    accept(Token.RPAREN);\n                }\n            } else if (lexer.nextIf(Token.LPAREN)) {\n                values = new SQLPartitionValue(SQLPartitionValue.Operator.List);\n                this.exprList(values.getItems(), values);\n                accept(Token.RPAREN);\n            } else if (lexer.nextIf(Token.LBRACKET)) {\n                values = new SQLPartitionValue(SQLPartitionValue.Operator.FixedRange);\n                this.exprList(values.getItems(), values);\n                accept(Token.RPAREN);\n            }\n        }\n        return values;\n    }\n\n    protected static boolean isIdent(SQLExpr expr, String name) {\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n            return identExpr.getName().equalsIgnoreCase(name);\n        }\n        return false;\n    }\n\n    public SQLLimit parseLimit() {\n        if (lexer.token != Token.LIMIT) {\n            return null;\n        }\n\n        SQLLimit limit = new SQLLimit();\n        lexer.nextTokenValue();\n\n        SQLExpr temp;\n        if (lexer.token == Token.LITERAL_INT) {\n            temp = new SQLIntegerExpr(lexer.integerValue());\n            lexer.nextTokenComma();\n            if (lexer.token != Token.COMMA && lexer.token != Token.EOF && lexer.token != Token.IDENTIFIER) {\n                temp = this.primaryRest(temp);\n                temp = this.exprRest(temp);\n            }\n        } else {\n            temp = this.expr();\n        }\n\n        if (lexer.token == (Token.COMMA)) {\n            limit.setOffset(temp);\n            lexer.nextTokenValue();\n\n            SQLExpr rowCount;\n            if (lexer.token == Token.LITERAL_INT) {\n                rowCount = new SQLIntegerExpr(lexer.integerValue());\n                lexer.nextToken();\n                if (lexer.token != Token.EOF && lexer.token != Token.IDENTIFIER) {\n                    rowCount = this.primaryRest(rowCount);\n                    rowCount = this.exprRest(rowCount);\n                }\n            } else {\n                rowCount = this.expr();\n            }\n\n            limit.setRowCount(rowCount);\n        } else if (lexer.identifierEquals(FnvHash.Constants.OFFSET)) {\n            limit.setRowCount(temp);\n            lexer.nextToken();\n            limit.setOffset(this.expr());\n            limit.setOffsetClause(true);\n        } else {\n            limit.setRowCount(temp);\n        }\n\n        if (lexer.token == Token.BY && dialectFeatureEnabled(ParseLimitBy)) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                SQLExpr item = this.expr();\n                limit.addBy(item);\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        return limit;\n    }\n\n    public void parseIndexRest(SQLIndex idx) {\n        parseIndexRest(idx, idx);\n    }\n\n    public void parseIndexRest(SQLIndex idx, SQLObject parent) {\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLSelectOrderByItem selectOrderByItem = this.parseSelectOrderByItem();\n            selectOrderByItem.setParent(parent);\n            idx.getColumns().add(selectOrderByItem);\n            if (!(lexer.token() == (Token.COMMA))) {\n                break;\n            } else {\n                lexer.nextToken();\n            }\n        }\n        accept(Token.RPAREN);\n\n        if (lexer.identifierEquals(FnvHash.Constants.COVERING)) {\n            Lexer.SavePoint mark = lexer.mark();\n\n            lexer.nextToken();\n\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n            } else {\n                lexer.reset(mark);\n                return;\n            }\n\n            for (; ; ) {\n                SQLName name = this.name();\n                name.setParent(parent);\n                idx.getCovering().add(name);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n    }\n\n    public SQLExternalRecordFormat parseRowFormat() {\n        lexer.nextToken();\n        acceptIdentifier(\"FORMAT\");\n\n        if (lexer.identifierEquals(FnvHash.Constants.DELIMITED)) {\n            lexer.nextToken();\n        }\n\n        SQLExternalRecordFormat format = new SQLExternalRecordFormat();\n\n        Lexer.SavePoint mark = lexer.mark();\n        String strVal = lexer.stringVal();\n        if (NULL.equals(lexer.token())) {\n            lexer.nextToken();\n            acceptIdentifier(\"DEFINED\");\n            accept(Token.AS);\n            strVal = lexer.stringVal();\n            String value = strVal.substring(1, strVal.length() - 1);\n            SQLCharExpr emptyExpr = new SQLCharExpr(value);\n            format.setNullDefinedAs(emptyExpr);\n            lexer.nextToken();\n        }\n//        for (; ; ) {\n//            if (strVal.equalsIgnoreCase(\"FULL\")) {\n//\n//                stmt.setTruncate(true);\n//                lexer.nextToken();\n//                mark = lexer.mark();\n//                strVal = lexer.stringVal();\n//                continue;\n//            } else {\n//                lexer.reset(mark);\n//                break;\n//            }\n//        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LINES)) {\n            lexer.nextToken();\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n\n            format.setLinesTerminatedBy(this.expr());\n        }\n        if (lexer.identifierEquals(FnvHash.Constants.FIELDS)) {\n            lexer.nextToken();\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n\n            format.setTerminatedBy(this.expr());\n        } else if (lexer.identifierEquals(\"FIELD\")) {\n            throw new ParserException(\"syntax error, expect FIELDS, \" + lexer.info());\n        }\n\n        if (lexer.token() == Token.ESCAPE || lexer.identifierEquals(FnvHash.Constants.ESCAPED)) {\n            lexer.nextToken();\n            accept(Token.BY);\n            format.setEscapedBy(this.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LINES)) {\n            lexer.nextToken();\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n\n            format.setLinesTerminatedBy(this.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COLLECTION)) {\n            lexer.nextToken();\n            acceptIdentifier(\"ITEMS\");\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n            format.setCollectionItemsTerminatedBy(this.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.MAP)) {\n            lexer.nextToken();\n            acceptIdentifier(\"KEYS\");\n            acceptIdentifier(\"TERMINATED\");\n            accept(Token.BY);\n            format.setMapKeysTerminatedBy(this.expr());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SERDE)) {\n            lexer.nextToken();\n            format.setSerde(this.expr());\n        }\n\n        return format;\n    }\n\n    public SQLTop parseTop() {\n        if (lexer.token() == Token.TOP) {\n            SQLTop top = new SQLTop();\n            lexer.computeRowAndColumn(top);\n            lexer.nextToken();\n\n            boolean paren = false;\n            if (lexer.token() == Token.LPAREN) {\n                top.setParentheses(true);\n                paren = true;\n                lexer.nextToken();\n            }\n\n            if (lexer.token() == Token.LITERAL_INT) {\n                top.setExpr(lexer.integerValue().intValue());\n                lexer.nextToken();\n            } else {\n                top.setExpr(primary());\n            }\n\n            if (paren) {\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token() == Token.PERCENT) {\n                lexer.nextToken();\n                top.setPercent(true);\n            }\n\n            return top;\n        }\n\n        return null;\n    }\n\n    protected SQLStructExpr struct() {\n        SQLStructExpr structExpr = new SQLStructExpr();\n        accept(Token.LPAREN);\n        aliasedItems(structExpr.getItems(), structExpr);\n        if (lexer.token == Token.GTGT) {\n            lexer.token = Token.RPAREN;\n        } else {\n            accept(Token.RPAREN);\n        }\n        return structExpr;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLInsertValueHandler.java",
    "content": "package com.alibaba.druid.sql.parser;\n\nimport java.math.BigDecimal;\nimport java.sql.SQLException;\n\npublic interface SQLInsertValueHandler {\n    Object newRow() throws SQLException;\n\n    void processInteger(Object row, int index, Number value) throws SQLException;\n\n    void processString(Object row, int index, String value) throws SQLException;\n\n    void processDate(Object row, int index, String value) throws SQLException;\n\n    void processDate(Object row, int index, java.util.Date value) throws SQLException;\n\n    void processTimestamp(Object row, int index, String value) throws SQLException;\n\n    void processTimestamp(Object row, int index, java.util.Date value) throws SQLException;\n\n    void processTime(Object row, int index, String value) throws SQLException;\n\n    void processDecimal(Object row, int index, BigDecimal value) throws SQLException;\n\n    void processBoolean(Object row, int index, boolean value) throws SQLException;\n\n    void processNull(Object row, int index) throws SQLException;\n\n    void processFunction(Object row,\n                         int index,\n                         String funcName,\n                         long funcNameHashCode64,\n                         Object... values) throws SQLException;\n\n    void processRow(Object row) throws SQLException;\n\n    void processComplete() throws SQLException;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLParseException.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.FastsqlException;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\n@SuppressWarnings(\"serial\")\n@Deprecated\npublic class SQLParseException extends FastsqlException {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.TimeZone;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\n\npublic class SQLParser {\n    protected final Lexer lexer;\n    protected DbType dbType;\n\n    public SQLParser(String sql, DbType dbType, SQLParserFeature... features) {\n        this(new Lexer(sql, null, dbType), dbType);\n        for (SQLParserFeature feature : features) {\n            config(feature, true);\n        }\n\n        this.lexer.nextToken();\n    }\n\n    public SQLParser(String sql) {\n        this(sql, null);\n    }\n\n    public SQLParser(Lexer lexer) {\n        this(lexer, null);\n        if (dbType == null) {\n            dbType = lexer.dbType;\n        }\n    }\n\n    public SQLParser(Lexer lexer, DbType dbType) {\n        this.lexer = lexer;\n        this.dbType = dbType;\n    }\n\n    public final Lexer getLexer() {\n        return lexer;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    protected boolean identifierEquals(String text) {\n        return lexer.identifierEquals(text);\n    }\n\n    protected void acceptIdentifier(String text) {\n        if (lexer.identifierEquals(text)) {\n            lexer.nextToken();\n        } else {\n            setErrorEndPos(lexer.pos());\n            throw new ParserException(\"syntax error, expect \" + text + \", actual \" + lexer.token + \", \" + lexer.info());\n        }\n    }\n\n    protected void acceptIdentifier(Long hash) {\n        if (lexer.identifierEquals(hash)) {\n            lexer.nextToken();\n        } else {\n            setErrorEndPos(lexer.pos());\n            throw new ParserException(\"syntax error, expect \" + hash + \", actual \" + lexer.token + \", \" + lexer.info());\n        }\n    }\n\n    protected String tableAlias() {\n        return tableAlias(false);\n    }\n\n    protected String tableAlias(boolean must) {\n        final Token token = lexer.token;\n        if (token == Token.CONNECT\n                || token == Token.START\n                || token == Token.SELECT\n                || token == Token.FROM\n                || token == Token.WHERE) {\n            if (token == Token.WHERE && tableAliasFeatureEnabled(TableAliasConnectWhere)) {\n                return null;\n            }\n\n            if (must) {\n                throw new ParserException(\"illegal alias. \" + lexer.info());\n            }\n            return null;\n        }\n\n        if (token == Token.IDENTIFIER) {\n            String ident = lexer.stringVal;\n            long hash = lexer.hashLCase;\n            if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && ident.length() > 1) {\n                ident = StringUtils.removeNameQuotes(ident);\n            }\n\n            if (hash == FnvHash.Constants.START\n                    || hash == FnvHash.Constants.CONNECT\n                    || hash == FnvHash.Constants.NATURAL\n                    || hash == FnvHash.Constants.CROSS\n                    || hash == FnvHash.Constants.OFFSET\n                    || hash == FnvHash.Constants.LIMIT) {\n                if (must) {\n                    throw new ParserException(\"illegal alias. \" + lexer.info());\n                }\n\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                switch (lexer.token) {\n                    case EOF:\n                    case COMMA:\n                    case WHERE:\n                    case INNER:\n                    case LEFT:\n                    case RIGHT:\n                    case FULL:\n                    case ON:\n                    case GROUP:\n                    case ORDER:\n                        return ident;\n                    case JOIN:\n                        if (hash != FnvHash.Constants.NATURAL\n                                && hash != FnvHash.Constants.CROSS) {\n                            return ident;\n                        }\n                        lexer.reset(mark);\n                        break;\n                    default:\n                        lexer.reset(mark);\n                        break;\n                }\n\n                return null;\n            }\n\n            if (!must) {\n                if (hash == FnvHash.Constants.MODEL) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token == Token.PARTITION\n                            || lexer.identifierEquals(FnvHash.Constants.DIMENSION)\n                            || lexer.identifierEquals(FnvHash.Constants.IGNORE)\n                            || lexer.identifierEquals(FnvHash.Constants.KEEP)) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return ident;\n                } else if (hash == FnvHash.Constants.WINDOW) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token == Token.IDENTIFIER) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return ident;\n                } else if (hash == FnvHash.Constants.DISTRIBUTE\n                        || hash == FnvHash.Constants.SORT\n                        || hash == FnvHash.Constants.CLUSTER\n                        || hash == FnvHash.Constants.ZORDER\n                ) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token == Token.BY) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return ident;\n                } else if (hash == FnvHash.Constants.ASOF && tableAliasFeatureEnabled(TableAliasAsof)) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token == Token.LEFT || lexer.token == Token.JOIN) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return ident;\n                }\n            }\n        }\n\n        if (!must) {\n            String aliasFromOptional = tableAliasFromOptionalKeyword(token);\n            if (aliasFromOptional != null) {\n                return aliasFromOptional;\n            }\n        }\n\n        if (must) {\n            String aliasFromRest = tableAliasFromRequiredRest();\n            if (aliasFromRest != null) {\n                return aliasFromRest;\n            }\n            return this.alias();\n        }\n\n        return this.as();\n    }\n\n    private String tableAliasFromOptionalKeyword(Token token) {\n        switch (token) {\n            case LEFT:\n            case RIGHT:\n            case INNER:\n            case FULL: {\n                Lexer.SavePoint mark = lexer.mark();\n                String strVal = lexer.stringVal();\n                lexer.nextToken();\n                if (lexer.token == Token.OUTER\n                        || lexer.token == Token.JOIN\n                        || lexer.identifierEquals(FnvHash.Constants.ANTI)\n                        || lexer.identifierEquals(FnvHash.Constants.SEMI)) {\n                    lexer.reset(mark);\n                    return null;\n                }\n                return strVal;\n            }\n            case OUTER:\n            case IN:\n            case SET:\n            case BY: {\n                Lexer.SavePoint mark = lexer.mark();\n                String strVal = lexer.stringVal();\n                lexer.nextToken();\n                switch (lexer.token) {\n                    case WHERE:\n                    case GROUP:\n                    case ORDER:\n                    case LEFT:\n                    case RIGHT:\n                    case FULL:\n                    case RPAREN:\n                    case ON:\n                    case JOIN:\n                    case SEMI:\n                        return strVal;\n                    default:\n                        lexer.reset(mark);\n                        break;\n                }\n                break;\n            }\n            case FOR:\n            case GRANT:\n            case CHECK:\n            case LEAVE:\n            case TRIGGER:\n            case CREATE:\n            case ASC:\n            case INOUT:\n            case DESC:\n            case SCHEMA:\n            case IS:\n            case DECLARE:\n            case DROP:\n            case FETCH:\n            case LOCK:\n                if (tableAliasFeatureEnabled(TableAliasLock)) {\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    return strVal;\n                }\n                break;\n            case PARTITION:\n                if (tableAliasFeatureEnabled(TableAliasPartition)) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    if (lexer.token == Token.LPAREN) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return strVal;\n                }\n                break;\n            case TABLE:\n                if (tableAliasFeatureEnabled(TableAliasTable)) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    switch (lexer.token) {\n                        case FROM:\n                        case GROUP:\n                        case ORDER:\n                        case ON:\n                            return strVal;\n                        default:\n                            lexer.reset(mark);\n                            break;\n                    }\n                }\n                break;\n            case SHOW:\n            case REFERENCES:\n            case REPEAT:\n            case USE:\n            case MOD:\n            case OUT: {\n                String strVal = lexer.stringVal();\n                lexer.nextToken();\n                return strVal;\n            }\n            case QUALIFY: {\n                String strVal = lexer.stringVal();\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token != Token.WHERE\n                        && lexer.token != Token.GROUP\n                        && lexer.token != Token.HAVING\n                        && lexer.token != Token.WINDOW\n                        && lexer.token != Token.ORDER\n                        && lexer.token != Token.LIMIT\n                        && lexer.token != Token.EOF\n                        && lexer.token != Token.COMMA\n                ) {\n                    lexer.reset(mark);\n                    return null;\n                }\n                return strVal;\n            }\n            case DISTRIBUTE: {\n                String strVal = lexer.stringVal();\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token == Token.BY) {\n                    lexer.reset(mark);\n                    return null;\n                }\n                return strVal;\n            }\n            case MINUS:\n            case EXCEPT:\n            case LIMIT:\n            case BETWEEN:\n                if (tableAliasFeatureEnabled(TableAliasBetween)) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    switch (lexer.token) {\n                        case EOF:\n                        case COMMA:\n                        case WHERE:\n                        case GROUP:\n                        case ORDER:\n                        case LEFT:\n                        case RIGHT:\n                        case FULL:\n                        case RPAREN:\n                        case ON:\n                        case JOIN:\n                        case SEMI:\n                            return strVal;\n                        default:\n                            lexer.reset(mark);\n                            break;\n                    }\n                }\n                break;\n            case UNION: {\n                Lexer.SavePoint mark = lexer.mark();\n                String strVal = lexer.stringVal();\n                lexer.nextToken();\n                switch (lexer.token) {\n                    case GROUP:\n                    case ORDER:\n                    case SEMI:\n                    case LEFT:\n                    case RIGHT:\n                    case INNER:\n                    case JOIN:\n                    case RPAREN:\n                        return strVal;\n                    default:\n                        lexer.reset(mark);\n                        return null;\n                }\n            }\n            default:\n                break;\n        }\n\n        return null;\n    }\n\n    private String tableAliasFromRequiredRest() {\n        if (tableAliasFeatureEnabled(TableAliasRest)) {\n            switch (lexer.token) {\n                case GROUP:\n                case ORDER: {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    if (lexer.token == Token.BY) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return strVal;\n                }\n                case UNION: {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    if (lexer.token == Token.ALL) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return strVal;\n                }\n                case LIMIT: {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    if (lexer.token == Token.LITERAL_INT) {\n                        lexer.reset(mark);\n                        return null;\n                    }\n                    return strVal;\n                }\n                case BETWEEN: {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    switch (lexer.token) {\n                        case GROUP:\n                        case ORDER:\n                        case SEMI:\n                        case LEFT:\n                        case RIGHT:\n                        case INNER:\n                        case JOIN:\n                            return strVal;\n                        default:\n                            lexer.reset(mark);\n                            return null;\n                    }\n                }\n                default:\n                    break;\n            }\n        }\n        return null;\n    }\n\n    private boolean tableAliasFeatureEnabled(DialectFeature.ParserFeature feature) {\n        return dialectFeatureEnabled(feature);\n    }\n\n    protected String as() {\n        String alias = null;\n\n        final Token token = lexer.token;\n\n        if (token == Token.COMMA) {\n            return null;\n        }\n\n        if (token == Token.AS) {\n            lexer.nextTokenAlias();\n            if (lexer.token == Token.LPAREN) {\n                return null;\n            }\n\n            // for oracle\n            if (dialectFeatureEnabled(AsCommaFrom) && (lexer.token == Token.COMMA || lexer.token == Token.FROM)) {\n                return null;\n            }\n\n            alias = lexer.stringVal();\n            lexer.nextToken();\n\n            if (alias != null) {\n                while (lexer.token == Token.DOT) {\n                    lexer.nextToken();\n                    alias += ('.' + lexer.token.name());\n                    lexer.nextToken();\n                }\n\n                return alias;\n            }\n\n            if (lexer.token == Token.LPAREN) {\n                return null;\n            }\n\n            throw new ParserException(\"Error : \" + lexer.info());\n        }\n\n        if (lexer.token == Token.LITERAL_ALIAS) {\n            alias = lexer.stringVal();\n            lexer.nextToken();\n        } else if (lexer.token == Token.IDENTIFIER) {\n            alias = lexer.stringVal();\n            boolean skip = false;\n            if (dialectFeatureEnabled(AsSkip)) {\n                skip = \"TBLPROPERTIES\".equalsIgnoreCase(alias);\n            }\n            if (skip) {\n                alias = null;\n            } else {\n                lexer.nextToken();\n            }\n        } else if (lexer.token == Token.LITERAL_CHARS) {\n            alias = \"'\" + lexer.stringVal() + \"'\";\n            lexer.nextToken();\n        } else {\n            switch (lexer.token) {\n                case CASE:\n                case USER:\n                case LOB:\n                case END:\n                case DEFERRED:\n                case OUTER:\n                case DO:\n                case LOOP:\n                case STORE:\n                case MOD:\n                case ANY:\n                case BEGIN:\n                case CAST:\n                case COMPUTE:\n                case ESCAPE:\n                case FULL:\n                case MERGE:\n                case OPEN:\n                case SOME:\n                case TRUNCATE:\n                case UNTIL:\n                case VIEW:\n                case KILL:\n                case COMMENT:\n                case TABLESPACE:\n                case REPEAT:\n                case PRIMARY:\n                case FOREIGN:\n                case UNIQUE:\n                case LEAVE:\n                case ENABLE:\n                case DISABLE:\n                case REPLACE:\n                    alias = lexer.stringVal();\n                    lexer.nextToken();\n                    break;\n                case INTERSECT:\n                case EXCEPT:\n                case DESC:\n                case INOUT:\n                case MINUS:\n                case UPDATE:\n                case DELETE:\n                case TABLE:\n                case UNION:\n                case EXPLAIN:\n                case CREATE:\n                case LIMIT:\n                case USE:\n                case BY:\n                case ALTER:\n                case IN:\n                case INTO:\n                case ASC: {\n                    alias = lexer.stringVal();\n\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n                    if (lexer.token() != Token.COMMA\n                            && lexer.token() != Token.RPAREN\n                            && lexer.token() != Token.FROM\n                            && lexer.token() != Token.SEMI\n                            && lexer.token() != Token.SEMI\n                    ) {\n                        alias = null;\n                        lexer.reset(mark);\n                    }\n                    break;\n                }\n                case CLOSE:\n                case SEQUENCE:\n                    if (dialectFeatureEnabled(AsSequence)) {\n                        alias = lexer.stringVal();\n                        lexer.nextToken();\n                        break;\n                    }\n                    break;\n                case CHECK:\n                case INDEX:\n                case ALL:\n                case INNER:\n                case VALUES:\n                case SHOW:\n                case TO:\n                case REFERENCES:\n                case LIKE:\n                case RLIKE:\n                case NULL:\n                case RIGHT:\n                case LEFT:\n                case DATABASE:\n                    if (dialectFeatureEnabled(AsDatabase)) {\n                        alias = lexer.stringVal();\n                        lexer.nextToken();\n                        break;\n                    }\n                    break;\n                case GROUP:\n                case ORDER:\n                case DISTRIBUTE:\n                case DEFAULT:\n                    if (dialectFeatureEnabled(AsDefault)) {\n                        Lexer.SavePoint mark = lexer.mark();\n                        alias = lexer.stringVal();\n                        lexer.nextToken();\n                        if (lexer.token == Token.BY) {\n                            lexer.reset(mark);\n                            alias = null;\n                        }\n                        break;\n                    }\n                    break;\n                default:\n                    break;\n            }\n        }\n\n        switch (lexer.token) {\n            case KEY:\n            case INTERVAL:\n            case CONSTRAINT:\n                alias = lexer.token.name();\n                lexer.nextToken();\n                return alias;\n            default:\n                break;\n        }\n\n        if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && alias != null && alias.length() > 1) {\n            alias = StringUtils.removeNameQuotes(alias);\n        }\n        return alias;\n    }\n\n    protected String alias() {\n        String alias = null;\n        if (lexer.token == Token.LITERAL_ALIAS) {\n            alias = lexer.stringVal();\n            lexer.nextToken();\n        } else if (lexer.token == Token.IDENTIFIER) {\n            alias = lexer.stringVal();\n            lexer.nextToken();\n        } else if (lexer.token == Token.LITERAL_CHARS) {\n            alias = \"'\" + lexer.stringVal() + \"'\";\n            lexer.nextToken();\n        } else if (lexer.token == Token.LITERAL_FLOAT && dialectFeatureEnabled(AliasLiteralFloat)) {\n            String numStr = lexer.numberString();\n            lexer.nextToken();\n            if (lexer.token == Token.IDENTIFIER) {\n                numStr += lexer.stringVal();\n                lexer.nextToken();\n            }\n            return numStr;\n        } else {\n            switch (lexer.token) {\n                case KEY:\n                case INDEX:\n                case CASE:\n//                case MODEL:\n                case PCTFREE:\n                case INITRANS:\n                case MAXTRANS:\n                case SEGMENT:\n                case CREATION:\n                case IMMEDIATE:\n                case DEFERRED:\n                case STORAGE:\n                case NEXT:\n                case MINEXTENTS:\n                case MAXEXTENTS:\n                case MAXSIZE:\n                case PCTINCREASE:\n                case FLASH_CACHE:\n                case CELL_FLASH_CACHE:\n                case NONE:\n                case LOB:\n                case STORE:\n                case ROW:\n                case CHUNK:\n                case CACHE:\n                case NOCACHE:\n                case LOGGING:\n                case NOCOMPRESS:\n                case KEEP_DUPLICATES:\n                case EXCEPTIONS:\n                case PURGE:\n                case INITIALLY:\n                case END:\n                case COMMENT:\n                case ENABLE:\n                case DISABLE:\n                case SEQUENCE:\n                case USER:\n                case ANALYZE:\n                case OPTIMIZE:\n                case GRANT:\n                case REVOKE:\n                case FULL:\n                case TO:\n                case NEW:\n                case INTERVAL:\n                case LOCK:\n                case LIMIT:\n                case IDENTIFIED:\n                case PASSWORD:\n                case BINARY:\n                case WINDOW:\n                case OFFSET:\n                case SHARE:\n                case START:\n                case CONNECT:\n                case MATCHED:\n                case ERRORS:\n                case REJECT:\n                case UNLIMITED:\n                case BEGIN:\n                case EXCLUSIVE:\n                case MODE:\n                case ADVISE:\n                case TYPE:\n                case CLOSE:\n                case OPEN:\n                case ANY:\n                case CAST:\n                case COMPUTE:\n                case ESCAPE:\n                case INTERSECT:\n                case MERGE:\n                case MINUS:\n                case SOME:\n                case TRUNCATE:\n                case UNTIL:\n                case VIEW:\n                case FUNCTION:\n                case DESC:\n                case KILL:\n                case SHOW:\n                case NULL:\n                case ALL:\n                case CONSTRAINT:\n                case INNER:\n                case LEFT:\n                case RIGHT:\n                case VALUES:\n                case SCHEMA:\n                case PARTITION:\n                case UPDATE:\n                case DO:\n                case LOOP:\n                case REPEAT:\n                case DEFAULT:\n                case LIKE:\n                case IS:\n                case UNIQUE:\n                case CHECK:\n                case INOUT:\n                case DECLARE:\n                case TABLE:\n                case TRIGGER:\n                case IN:\n                case OUT:\n                case BY:\n                case EXCEPT:\n                case TABLESPACE:\n                case CREATE:\n                case DELETE:\n                case PRIMARY:\n                case FOREIGN:\n                case REFERENCES:\n                case INTO:\n                case USE:\n                case LEAVE:\n                case DISTRIBUTE:\n                case AS:\n                case FOR:\n                case PARTITIONED:\n                case REPLACE:\n                case ALTER:\n                case EXPLAIN:\n                case ASC:\n                case DATABASE:\n                case TRUE:\n                case FALSE:\n                case OUTER:\n                case DROP:\n                    alias = lexer.stringVal();\n                    lexer.nextToken();\n                    return alias;\n                case GROUP:\n                case ORDER:\n                    {\n                        Lexer.SavePoint mark = lexer.mark();\n                        alias = lexer.stringVal();\n                        lexer.nextToken();\n                        if (lexer.token == Token.BY) {\n                            lexer.reset(mark);\n                            alias = null;\n                        }\n                    }\n                    break;\n                case QUES:\n                    alias = \"?\";\n                    lexer.nextToken();\n                    return alias;\n                case UNION: {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    if (lexer.token == Token.ALL) {\n                        lexer.reset(mark);\n                        return null;\n                    } else {\n                        return strVal;\n                    }\n                }\n                default:\n                    break;\n            }\n        }\n        return alias;\n    }\n\n    protected void printError(Token token) {\n        String arround;\n        if (lexer.mark >= 0 && (lexer.text.length() > lexer.mark + 30)) {\n            int begin, end;\n            if (lexer.mark - 5 > 0) {\n                begin = lexer.mark - 5;\n                end = lexer.mark + 30;\n            } else {\n                begin = lexer.mark;\n                end = lexer.mark + 30;\n            }\n\n            if (begin < 10) {\n                begin = 0;\n            } else {\n                for (int i = 1; i < 10 && i < begin; ++i) {\n                    char ch = lexer.text.charAt(begin - i);\n                    if (ch == ' ' || ch == '\\n') {\n                        begin = begin - i + 1;\n                    }\n                }\n            }\n\n            arround = lexer.text.substring(begin, end);\n        } else if (lexer.mark >= 0) {\n            if (lexer.mark - 5 > 0) {\n                arround = lexer.text.substring(lexer.mark - 5);\n            } else {\n                arround = lexer.text.substring(lexer.mark);\n            }\n        } else {\n            arround = lexer.text;\n        }\n\n        // throw new\n        // ParserException(\"syntax error, error arround:'\"+arround+\"',expect \"\n        // + token + \", actual \" + lexer.token + \" \"\n        // + lexer.stringVal() + \", pos \" + this.lexer.pos());\n        StringBuilder buf = new StringBuilder()\n                .append(\"syntax error, error in :'\")\n                .append(arround);\n        if (token != lexer.token) {\n            buf.append(\"', expect \")\n                    .append(token.name)\n                    .append(\", actual \")\n                    .append(lexer.token.name);\n        }\n        buf.append(\", \")\n                .append(\n                        lexer.info());\n\n        throw new ParserException(buf.toString());\n    }\n\n    public void accept(Token token) {\n        if (!lexer.nextIf(token)) {\n            setErrorEndPos(lexer.pos());\n            printError(token);\n        }\n    }\n\n    public int acceptInteger() {\n        if (lexer.token == Token.LITERAL_INT) {\n            Number number = lexer.integerValue();\n            int intVal = number.intValue();\n            lexer.nextToken();\n            return intVal;\n        } else {\n            throw new ParserException(\"syntax error, expect int, actual \" + lexer.token + \" \"\n                    + lexer.info());\n        }\n    }\n\n    public void match(Token token) {\n        if (lexer.token != token) {\n            throw new ParserException(\"syntax error, expect \" + token + \", actual \" + lexer.token + \" \"\n                    + lexer.info());\n        }\n    }\n\n    private int errorEndPos = -1;\n\n    protected void setErrorEndPos(int errPos) {\n        if (errPos > errorEndPos) {\n            errorEndPos = errPos;\n        }\n    }\n\n    public void config(SQLParserFeature feature, boolean state) {\n        this.lexer.config(feature, state);\n    }\n\n    public TimeZone getTimeZone() {\n        return lexer.getTimeZone();\n    }\n\n    public void setTimeZone(TimeZone timeZone) {\n        this.lexer.setTimeZone(timeZone);\n    }\n\n    public final boolean isEnabled(SQLParserFeature feature) {\n        return lexer.isEnabled(feature);\n    }\n\n    protected SQLCreateTableStatement newCreateStatement() {\n        return new SQLCreateTableStatement(dbType);\n    }\n\n    protected boolean dialectFeatureEnabled(DialectFeature.ParserFeature feature) {\n        return this.lexer.dialectFeature.isEnabled(feature);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLParserFeature.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\npublic enum SQLParserFeature {\n    KeepInsertValueClauseOriginalString,\n    KeepSelectListOriginalString, // for improved sql parameterized performance\n    UseInsertColumnsCache,\n    EnableSQLBinaryOpExprGroup,\n    OptimizedForParameterized,\n    OptimizedForForParameterizedSkipValue,\n    KeepComments,\n    SkipComments,\n    StrictForWall,\n\n    TDDLHint,\n    DRDSAsyncDDL,\n    DRDSBaseline,\n    InsertReader,\n    IgnoreNameQuotes,\n    KeepNameQuotes, //for ads, presto\n\n    SelectItemGenerateAlias,\n\n    PipesAsConcat, // for mysql\n\n    InsertValueCheckType,\n\n    InsertValueNative,\n\n    EnableCurrentTimeExpr,\n    EnableCurrentUserExpr,\n\n    KeepSourceLocation,\n\n    SupportUnicodeCodePoint,\n    PrintSQLWhileParsingFailed,\n    EnableMultiUnion,\n\n    Spark,\n    Presto,\n    MySQLSupportStandardComment,\n\n    Template;\n\n    SQLParserFeature() {\n        mask = (1 << ordinal());\n    }\n\n    public final int mask;\n\n    public static boolean isEnabled(int features, SQLParserFeature feature) {\n        return (features & feature.mask) != 0;\n    }\n\n    public static int config(int features, SQLParserFeature feature, boolean state) {\n        if (state) {\n            features |= feature.mask;\n        } else {\n            features &= ~feature.mask;\n        }\n\n        return features;\n    }\n\n    public static int of(SQLParserFeature... features) {\n        if (features == null) {\n            return 0;\n        }\n\n        int value = 0;\n\n        for (SQLParserFeature feature : features) {\n            value |= feature.mask;\n        }\n\n        return value;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.athena.parser.AthenaExprParser;\nimport com.alibaba.druid.sql.dialect.athena.parser.AthenaLexer;\nimport com.alibaba.druid.sql.dialect.athena.parser.AthenaStatementParser;\nimport com.alibaba.druid.sql.dialect.bigquery.parser.BigQueryExprParser;\nimport com.alibaba.druid.sql.dialect.bigquery.parser.BigQueryLexer;\nimport com.alibaba.druid.sql.dialect.bigquery.parser.BigQueryStatementParser;\nimport com.alibaba.druid.sql.dialect.blink.parser.BlinkStatementParser;\nimport com.alibaba.druid.sql.dialect.clickhouse.parser.CKExprParser;\nimport com.alibaba.druid.sql.dialect.clickhouse.parser.CKLexer;\nimport com.alibaba.druid.sql.dialect.clickhouse.parser.CKStatementParser;\nimport com.alibaba.druid.sql.dialect.databricks.parser.DatabricksExprParser;\nimport com.alibaba.druid.sql.dialect.databricks.parser.DatabricksLexer;\nimport com.alibaba.druid.sql.dialect.databricks.parser.DatabricksStatementParser;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2ExprParser;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2Lexer;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.dm.ast.stmt.DmSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.dm.parser.DmExprParser;\nimport com.alibaba.druid.sql.dialect.dm.parser.DmLexer;\nimport com.alibaba.druid.sql.dialect.dm.parser.DmStatementParser;\nimport com.alibaba.druid.sql.dialect.doris.parser.DorisExprParser;\nimport com.alibaba.druid.sql.dialect.doris.parser.DorisLexer;\nimport com.alibaba.druid.sql.dialect.doris.parser.DorisStatementParser;\nimport com.alibaba.druid.sql.dialect.gaussdb.parser.GaussDbExprParser;\nimport com.alibaba.druid.sql.dialect.gaussdb.parser.GaussDbLexer;\nimport com.alibaba.druid.sql.dialect.gaussdb.parser.GaussDbStatementParser;\nimport com.alibaba.druid.sql.dialect.h2.parser.H2ExprParser;\nimport com.alibaba.druid.sql.dialect.h2.parser.H2Lexer;\nimport com.alibaba.druid.sql.dialect.h2.parser.H2StatementParser;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveExprParser;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveLexer;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser;\nimport com.alibaba.druid.sql.dialect.hologres.parser.HologresExprParser;\nimport com.alibaba.druid.sql.dialect.hologres.parser.HologresLexer;\nimport com.alibaba.druid.sql.dialect.hologres.parser.HologresStatementParser;\nimport com.alibaba.druid.sql.dialect.impala.parser.ImpalaExprParser;\nimport com.alibaba.druid.sql.dialect.impala.parser.ImpalaLexer;\nimport com.alibaba.druid.sql.dialect.impala.parser.ImpalaStatementParser;\nimport com.alibaba.druid.sql.dialect.informix.parser.InformixStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.odps.parser.OdpsExprParser;\nimport com.alibaba.druid.sql.dialect.odps.parser.OdpsLexer;\nimport com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleLexer;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;\nimport com.alibaba.druid.sql.dialect.oscar.ast.stmt.OscarSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.oscar.parser.OscarExprParser;\nimport com.alibaba.druid.sql.dialect.oscar.parser.OscarLexer;\nimport com.alibaba.druid.sql.dialect.oscar.visitor.OscarStatementParser;\nimport com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixExprParser;\nimport com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixLexer;\nimport com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixStatementParser;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGLexer;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoExprParser;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoLexer;\nimport com.alibaba.druid.sql.dialect.presto.parser.PrestoStatementParser;\nimport com.alibaba.druid.sql.dialect.redshift.parser.RedshiftExprParser;\nimport com.alibaba.druid.sql.dialect.redshift.parser.RedshiftLexer;\nimport com.alibaba.druid.sql.dialect.redshift.parser.RedshiftStatementParser;\nimport com.alibaba.druid.sql.dialect.snowflake.SnowflakeExprParser;\nimport com.alibaba.druid.sql.dialect.snowflake.SnowflakeLexer;\nimport com.alibaba.druid.sql.dialect.snowflake.SnowflakeStatementParser;\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkExprParser;\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkLexer;\nimport com.alibaba.druid.sql.dialect.spark.parser.SparkStatementParser;\nimport com.alibaba.druid.sql.dialect.sqlite.parser.SQLiteExprParser;\nimport com.alibaba.druid.sql.dialect.sqlite.parser.SQLiteLexer;\nimport com.alibaba.druid.sql.dialect.sqlite.parser.SQLiteStatementParser;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerExprParser;\nimport com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksExprParser;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksLexer;\nimport com.alibaba.druid.sql.dialect.starrocks.parser.StarRocksStatementParser;\nimport com.alibaba.druid.sql.dialect.supersql.parser.SuperSqlExprParser;\nimport com.alibaba.druid.sql.dialect.supersql.parser.SuperSqlLexer;\nimport com.alibaba.druid.sql.dialect.supersql.parser.SuperSqlStatementParser;\nimport com.alibaba.druid.sql.dialect.synapse.parser.SynapseExprParser;\nimport com.alibaba.druid.sql.dialect.synapse.parser.SynapseLexer;\nimport com.alibaba.druid.sql.dialect.synapse.parser.SynapseStatementParser;\nimport com.alibaba.druid.sql.dialect.teradata.parser.TDExprParser;\nimport com.alibaba.druid.sql.dialect.teradata.parser.TDLexer;\nimport com.alibaba.druid.sql.dialect.teradata.parser.TDStatementParser;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\npublic class SQLParserUtils {\n    private static final ConcurrentMap<String, DialectParserProvider> DIALECT_PARSER_PROVIDERS = new ConcurrentHashMap<>();\n    private static final Map<DbType, StatementParserFactory> BUILTIN_STATEMENT_PARSER_FACTORIES = new EnumMap<>(DbType.class);\n    private static final Map<DbType, ExprParserFactory> BUILTIN_EXPR_PARSER_FACTORIES = new EnumMap<>(DbType.class);\n    private static final Map<DbType, LexerFactory> BUILTIN_LEXER_FACTORIES = new EnumMap<>(DbType.class);\n\n    private interface StatementParserFactory {\n        SQLStatementParser create(String sql, DbType dbType, SQLParserFeature... features);\n    }\n\n    private interface ExprParserFactory {\n        SQLExprParser create(String sql, DbType dbType, SQLParserFeature... features);\n    }\n\n    private interface LexerFactory {\n        Lexer create(String sql, DbType dbType, SQLParserFeature... features);\n    }\n\n    public interface DialectParserProvider {\n        SQLStatementParser createSQLStatementParser(String sql, DbType dbType, SQLParserFeature... features);\n\n        SQLExprParser createExprParser(String sql, DbType dbType, SQLParserFeature... features);\n\n        Lexer createLexer(String sql, DbType dbType, SQLParserFeature... features);\n    }\n\n    static {\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new OracleStatementParser(sql, features),\n                DbType.oracle, DbType.oceanbase_oracle, DbType.polardb2);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new MySqlStatementParser(sql, features),\n                DbType.mysql, DbType.tidb, DbType.mariadb, DbType.goldendb, DbType.oceanbase, DbType.drds, DbType.polardbx);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> {\n            MySqlStatementParser parser = new MySqlStatementParser(sql, features);\n            parser.dbType = dbType;\n            parser.exprParser.dbType = dbType;\n            return parser;\n        }, DbType.elastic_search);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new PGSQLStatementParser(sql, features),\n                DbType.postgresql, DbType.greenplum, DbType.edb);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new GaussDbStatementParser(sql, features), DbType.gaussdb);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new HologresStatementParser(sql, features), DbType.hologres);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new RedshiftStatementParser(sql, features), DbType.redshift);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new SQLServerStatementParser(sql, features),\n                DbType.sqlserver, DbType.jtds);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new SynapseStatementParser(sql, features), DbType.synapse);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new H2StatementParser(sql, features), DbType.h2, DbType.lealone);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new BlinkStatementParser(sql, features), DbType.blink);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new DB2StatementParser(sql, features), DbType.db2);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new OdpsStatementParser(sql, features), DbType.odps);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new PhoenixStatementParser(sql), DbType.phoenix);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new HiveStatementParser(sql, features), DbType.hive);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new PrestoStatementParser(sql, features), DbType.presto, DbType.trino);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new SuperSqlStatementParser(sql, features), DbType.supersql);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new AthenaStatementParser(sql, features), DbType.athena);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new BigQueryStatementParser(sql, features), DbType.bigquery);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new SnowflakeStatementParser(sql, features), DbType.snowflake);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new SparkStatementParser(sql, features), DbType.spark);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new DatabricksStatementParser(sql, features), DbType.databricks);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new CKStatementParser(sql, features), DbType.clickhouse);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new StarRocksStatementParser(sql, features), DbType.starrocks);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new InformixStatementParser(sql, features), DbType.informix);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new ImpalaStatementParser(sql, features), DbType.impala);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new DorisStatementParser(sql, features), DbType.doris);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new OscarStatementParser(sql, features), DbType.oscar);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new DmStatementParser(sql, features), DbType.dm);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new TDStatementParser(sql, features), DbType.teradata);\n        registerBuiltinStatementParserFactory((sql, dbType, features) -> new SQLiteStatementParser(sql, features), DbType.sqlite);\n\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new OracleExprParser(sql, features), DbType.oracle);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new MySqlExprParser(sql, features), DbType.mysql, DbType.mariadb);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> {\n            MySqlExprParser parser = new MySqlExprParser(sql, features);\n            parser.dbType = dbType;\n            return parser;\n        }, DbType.elastic_search);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new H2ExprParser(sql, features), DbType.h2, DbType.lealone);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new PGExprParser(sql, features),\n                DbType.postgresql, DbType.greenplum, DbType.edb);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new GaussDbExprParser(sql, features), DbType.gaussdb);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new HologresExprParser(sql, features), DbType.hologres);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new RedshiftExprParser(sql, features), DbType.redshift);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new SQLServerExprParser(sql, features), DbType.sqlserver, DbType.jtds);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new SynapseExprParser(sql, features), DbType.synapse);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new DB2ExprParser(sql, features), DbType.db2);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new OdpsExprParser(sql, features), DbType.odps);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new PhoenixExprParser(sql, features), DbType.phoenix);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new PrestoExprParser(sql, features), DbType.presto, DbType.trino);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new SuperSqlExprParser(sql, features), DbType.supersql);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new AthenaExprParser(sql, features), DbType.athena);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new HiveExprParser(sql, features), DbType.hive);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new SparkExprParser(sql, features), DbType.spark);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new DatabricksExprParser(sql, features), DbType.databricks);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new BigQueryExprParser(sql, features), DbType.bigquery);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new SnowflakeExprParser(sql, features), DbType.snowflake);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new CKExprParser(sql, features), DbType.clickhouse);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new OscarExprParser(sql, features), DbType.oscar);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new DmExprParser(sql, features), DbType.dm);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new StarRocksExprParser(sql, features), DbType.starrocks);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new ImpalaExprParser(sql, features), DbType.impala);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new DorisExprParser(sql, features), DbType.doris);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new TDExprParser(sql, features), DbType.teradata);\n        registerBuiltinExprParserFactory((sql, dbType, features) -> new SQLiteExprParser(sql, features), DbType.sqlite);\n\n        registerBuiltinLexerFactory((sql, dbType, features) -> new OracleLexer(sql, features), DbType.oracle);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new MySqlLexer(sql, features), DbType.mysql, DbType.mariadb);\n        registerBuiltinLexerFactory((sql, dbType, features) -> {\n            MySqlLexer lexer = new MySqlLexer(sql, features);\n            lexer.dbType = dbType;\n            return lexer;\n        }, DbType.elastic_search);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new H2Lexer(sql, features), DbType.h2, DbType.lealone);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new PGLexer(sql, features),\n                DbType.postgresql, DbType.greenplum, DbType.edb);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new GaussDbLexer(sql, features), DbType.gaussdb);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new HologresLexer(sql, features), DbType.hologres);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new RedshiftLexer(sql, features), DbType.redshift);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new DB2Lexer(sql, features), DbType.db2);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new OdpsLexer(sql, features), DbType.odps);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new PhoenixLexer(sql, features), DbType.phoenix);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new PrestoLexer(sql, features), DbType.presto, DbType.trino);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new SuperSqlLexer(sql, features), DbType.supersql);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new AthenaLexer(sql, features), DbType.athena);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new SynapseLexer(sql, features), DbType.synapse);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new SparkLexer(sql), DbType.spark);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new DatabricksLexer(sql), DbType.databricks);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new OscarLexer(sql, features), DbType.oscar);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new DmLexer(sql, features), DbType.dm);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new CKLexer(sql, features), DbType.clickhouse);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new StarRocksLexer(sql, features), DbType.starrocks);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new HiveLexer(sql, features), DbType.hive);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new BigQueryLexer(sql, features), DbType.bigquery);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new SnowflakeLexer(sql, features), DbType.snowflake);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new ImpalaLexer(sql, features), DbType.impala);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new DorisLexer(sql, features), DbType.doris);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new TDLexer(sql, features), DbType.teradata);\n        registerBuiltinLexerFactory((sql, dbType, features) -> new SQLiteLexer(sql, features), DbType.sqlite);\n    }\n\n    private static void registerBuiltinStatementParserFactory(StatementParserFactory factory, DbType... dbTypes) {\n        for (DbType dbType : dbTypes) {\n            BUILTIN_STATEMENT_PARSER_FACTORIES.put(dbType, factory);\n        }\n    }\n\n    private static void registerBuiltinExprParserFactory(ExprParserFactory factory, DbType... dbTypes) {\n        for (DbType dbType : dbTypes) {\n            BUILTIN_EXPR_PARSER_FACTORIES.put(dbType, factory);\n        }\n    }\n\n    private static void registerBuiltinLexerFactory(LexerFactory factory, DbType... dbTypes) {\n        for (DbType dbType : dbTypes) {\n            BUILTIN_LEXER_FACTORIES.put(dbType, factory);\n        }\n    }\n\n    public static DialectParserProvider registerDialectParserProvider(String dialectKey, DialectParserProvider provider) {\n        String normalizedDialectKey = normalizeDialectKey(dialectKey);\n        if (provider == null) {\n            throw new IllegalArgumentException(\"provider must not be null\");\n        }\n\n        return DIALECT_PARSER_PROVIDERS.put(normalizedDialectKey, provider);\n    }\n\n    public static DialectParserProvider unregisterDialectParserProvider(String dialectKey) {\n        String normalizedDialectKey = normalizeDialectKey(dialectKey);\n        return DIALECT_PARSER_PROVIDERS.remove(normalizedDialectKey);\n    }\n\n    public static DialectParserProvider getDialectParserProvider(String dialectKey) {\n        String normalizedDialectKey = normalizeDialectKey(dialectKey);\n        return DIALECT_PARSER_PROVIDERS.get(normalizedDialectKey);\n    }\n\n    private static String normalizeDialectKey(String dialectKey) {\n        if (dialectKey == null) {\n            throw new IllegalArgumentException(\"dialectKey must not be null\");\n        }\n\n        String normalizedDialectKey = dialectKey.trim();\n        if (normalizedDialectKey.isEmpty()) {\n            throw new IllegalArgumentException(\"dialectKey must not be blank\");\n        }\n\n        return normalizedDialectKey.toLowerCase(Locale.ROOT);\n    }\n\n    private static DialectParserProvider getDialectParserProvider(DbType dbType) {\n        if (dbType == null) {\n            return null;\n        }\n        return DIALECT_PARSER_PROVIDERS.get(dbType.name().toLowerCase(Locale.ROOT));\n    }\n\n    public static SQLStatementParser createSQLStatementParser(String sql, DbType dbType) {\n        SQLParserFeature[] features;\n        if (DbType.odps == dbType || DbType.mysql == dbType) {\n            features = new SQLParserFeature[]{SQLParserFeature.KeepComments};\n        } else {\n            features = new SQLParserFeature[]{};\n        }\n        return createSQLStatementParser(sql, dbType, features);\n    }\n\n    public static SQLStatementParser createSQLStatementParser(String sql, DbType dbType, boolean keepComments) {\n        SQLParserFeature[] features;\n        if (keepComments) {\n            features = new SQLParserFeature[]{SQLParserFeature.KeepComments};\n        } else {\n            features = new SQLParserFeature[]{};\n        }\n\n        return createSQLStatementParser(sql, dbType, features);\n    }\n\n    public static SQLStatementParser createSQLStatementParser(String sql, String dbType, SQLParserFeature... features) {\n        DialectParserProvider provider = dbType == null ? null : getDialectParserProvider(dbType);\n        if (provider != null) {\n            DbType parsedDbType = DbType.of(dbType);\n            SQLStatementParser parser = provider.createSQLStatementParser(sql, parsedDbType == null ? DbType.other : parsedDbType, features);\n            if (parser != null) {\n                return parser;\n            }\n        }\n        return createSQLStatementParser(sql, dbType == null ? null : DbType.valueOf(dbType), features);\n    }\n\n    public static SQLStatementParser createSQLStatementParser(String sql, DbType dbType, SQLParserFeature... features) {\n        if (sql.indexOf(\"\\r\\n\") != -1) {\n            // com.alibaba.druid.sql.parser.Lexer only recognizes Linux newline '\\n'.\n            sql = sql.replace(\"\\r\\n\", \"\\n\");\n        }\n\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        DialectParserProvider provider = getDialectParserProvider(dbType);\n        if (provider != null) {\n            SQLStatementParser parser = provider.createSQLStatementParser(sql, dbType, features);\n            if (parser != null) {\n                return parser;\n            }\n        }\n        StatementParserFactory factory = BUILTIN_STATEMENT_PARSER_FACTORIES.get(dbType);\n        if (factory != null) {\n            return factory.create(sql, dbType, features);\n        }\n        return new SQLStatementParser(sql, dbType, features);\n    }\n\n    public static SQLExprParser createExprParser(String sql, DbType dbType, SQLParserFeature... features) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        DialectParserProvider provider = getDialectParserProvider(dbType);\n        if (provider != null) {\n            SQLExprParser parser = provider.createExprParser(sql, dbType, features);\n            if (parser != null) {\n                return parser;\n            }\n        }\n        ExprParserFactory factory = BUILTIN_EXPR_PARSER_FACTORIES.get(dbType);\n        if (factory != null) {\n            return factory.create(sql, dbType, features);\n        }\n        return new SQLExprParser(sql, dbType, features);\n    }\n\n    public static Lexer createLexer(String sql, DbType dbType) {\n        return createLexer(sql, dbType, new SQLParserFeature[0]);\n    }\n\n    public static Lexer createLexer(String sql, DbType dbType, SQLParserFeature... features) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        DialectParserProvider provider = getDialectParserProvider(dbType);\n        if (provider != null) {\n            Lexer lexer = provider.createLexer(sql, dbType, features);\n            if (lexer != null) {\n                return lexer;\n            }\n        }\n        LexerFactory factory = BUILTIN_LEXER_FACTORIES.get(dbType);\n        if (factory != null) {\n            return factory.create(sql, dbType, features);\n        }\n        Lexer lexer = new Lexer(sql, null, dbType);\n        for (SQLParserFeature feature : features) {\n            lexer.config(feature, true);\n        }\n        return lexer;\n    }\n\n    public static SQLSelectQueryBlock createSelectQueryBlock(DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        switch (dbType) {\n            case mysql:\n                return new MySqlSelectQueryBlock();\n            case oracle:\n                return new OracleSelectQueryBlock();\n            case db2:\n                return new DB2SelectQueryBlock();\n            case postgresql:\n            case greenplum:\n            case edb:\n            case hologres:\n            case redshift:\n                return new PGSelectQueryBlock();\n            case odps:\n                return new OdpsSelectQueryBlock();\n            case sqlserver:\n                return new SQLServerSelectQueryBlock();\n            case synapse:\n                return new SQLServerSelectQueryBlock();\n            case oscar:\n                return new OscarSelectQueryBlock();\n            case dm:\n                return new DmSelectQueryBlock();\n            default:\n                return new SQLSelectQueryBlock(dbType);\n        }\n    }\n\n    public static SQLType getSQLType(String sql, DbType dbType) {\n        Lexer lexer = createLexer(sql, dbType);\n        return lexer.scanSQLType();\n    }\n\n    public static SQLType getSQLTypeV2(String sql, DbType dbType) {\n        Lexer lexer = createLexer(sql, dbType);\n        return lexer.scanSQLTypeV2();\n    }\n\n    public static boolean startsWithHint(String sql, DbType dbType) {\n        Lexer lexer = createLexer(sql, dbType);\n        lexer.nextToken();\n        return lexer.token() == Token.HINT;\n    }\n\n    public static boolean containsAny(String sql, DbType dbType, Token token) {\n        Lexer lexer = createLexer(sql, dbType);\n        for (; ; ) {\n            lexer.nextToken();\n            final Token tok = lexer.token;\n            switch (tok) {\n                case EOF:\n                case ERROR:\n                    return false;\n                default:\n                    if (tok == token) {\n                        return true;\n                    }\n                    break;\n            }\n        }\n    }\n\n    public static boolean containsAny(String sql, DbType dbType, Token token1, Token token2) {\n        Lexer lexer = createLexer(sql, dbType);\n        for (; ; ) {\n            lexer.nextToken();\n            final Token tok = lexer.token;\n            switch (tok) {\n                case EOF:\n                case ERROR:\n                    return false;\n                default:\n                    if (tok == token1 || tok == token2) {\n                        return true;\n                    }\n                    break;\n            }\n        }\n    }\n\n    public static boolean containsAny(String sql, DbType dbType, Token token1, Token token2, Token token3) {\n        Lexer lexer = createLexer(sql, dbType);\n        for (; ; ) {\n            lexer.nextToken();\n            final Token tok = lexer.token;\n            switch (tok) {\n                case EOF:\n                case ERROR:\n                    return false;\n                default:\n                    if (tok == token1 || tok == token2 || tok == token3) {\n                        return true;\n                    }\n                    break;\n            }\n        }\n    }\n\n    public static boolean containsAny(String sql, DbType dbType, Token... tokens) {\n        if (tokens == null) {\n            return false;\n        }\n\n        Lexer lexer = createLexer(sql, dbType);\n        for (; ; ) {\n            lexer.nextToken();\n            final Token tok = lexer.token;\n            switch (tok) {\n                case EOF:\n                case ERROR:\n                    return false;\n                default:\n                    for (int i = 0; i < tokens.length; i++) {\n                        if (tokens[i] == tok) {\n                            return true;\n                        }\n                    }\n                    break;\n            }\n        }\n    }\n\n    public static Object getSimpleSelectValue(String sql, DbType dbType) {\n        return getSimpleSelectValue(sql, dbType, null);\n    }\n\n    public static Object getSimpleSelectValue(String sql, DbType dbType, SimpleValueEvalHandler handler) {\n        Lexer lexer = createLexer(sql, dbType);\n        lexer.nextToken();\n\n        if (lexer.token != Token.SELECT && lexer.token != Token.VALUES) {\n            return null;\n        }\n\n        lexer.nextTokenValue();\n\n        SQLExpr expr = null;\n        Object value;\n        switch (lexer.token) {\n            case LITERAL_INT:\n                value = lexer.integerValue();\n                break;\n            case LITERAL_CHARS:\n            case LITERAL_NCHARS:\n                value = lexer.stringVal();\n                break;\n            case LITERAL_FLOAT:\n                value = lexer.decimalValue();\n                break;\n            default:\n                if (handler == null) {\n                    return null;\n                }\n\n                expr = new SQLExprParser(lexer).expr();\n                try {\n                    value = handler.eval(expr);\n                } catch (Exception error) {\n                    // skip\n                    value = null;\n                }\n                break;\n        }\n\n        lexer.nextToken();\n\n        if (lexer.token == Token.FROM) {\n            lexer.nextToken();\n            if (lexer.token == Token.DUAL) {\n                lexer.nextToken();\n            } else {\n                return null;\n            }\n        }\n        if (lexer.token != Token.EOF) {\n            return null;\n        }\n\n        return value;\n    }\n\n    public static interface SimpleValueEvalHandler {\n        Object eval(SQLExpr expr);\n    }\n\n    public static String replaceBackQuote(String sql, DbType dbType) {\n        int i = sql.indexOf('`');\n\n        if (i == -1) {\n            return sql;\n        }\n\n        char[] chars = sql.toCharArray();\n        Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n\n        int len = chars.length;\n        int off = 0;\n\n        for_:\n        for (; ; ) {\n            lexer.nextToken();\n\n            int p0, p1;\n            char c0, c1;\n            switch (lexer.token) {\n                case IDENTIFIER:\n                    p0 = lexer.startPos + off;\n                    p1 = lexer.pos - 1 + off;\n                    c0 = chars[p0];\n                    c1 = chars[p1];\n                    if (c0 == '`' && c1 == '`') {\n                        if (p1 - p0 > 2 && chars[p0 + 1] == '\\'' && chars[p1 - 1] == '\\'') {\n                            System.arraycopy(chars, p0 + 1, chars, p0, p1 - p0 - 1);\n                            System.arraycopy(chars, p1 + 1, chars, p1 - 1, chars.length - p1 - 1);\n                            len -= 2;\n                            off -= 2;\n                        } else {\n                            chars[p0] = '\"';\n                            chars[p1] = '\"';\n                        }\n\n                    }\n                    break;\n                case EOF:\n                case ERROR:\n                    break for_;\n                default:\n                    break;\n            }\n        }\n\n        return new String(chars, 0, len);\n    }\n\n    public static String addBackQuote(String sql, DbType dbType) {\n        if (StringUtils.isEmpty(sql)) {\n            return sql;\n        }\n        SQLStatementParser parser = createSQLStatementParser(sql, dbType);\n        StringBuilder buf = new StringBuilder(sql.length() + 20);\n        SQLASTOutputVisitor out = SQLUtils.createOutputVisitor(buf, DbType.mysql);\n        out.config(VisitorFeature.OutputNameQuote, true);\n\n        SQLType sqlType = getSQLType(sql, dbType);\n        if (sqlType == SQLType.INSERT) {\n            parser.config(SQLParserFeature.InsertReader, true);\n\n            SQLInsertStatement stmt = (SQLInsertStatement) parser.parseStatement();\n            int startPos = parser.getLexer().startPos;\n\n            stmt.accept(out);\n\n            if (stmt.getQuery() == null) {\n                buf.append(' ');\n                buf.append(sql, startPos, sql.length());\n            }\n        } else {\n            SQLStatement stmt = parser.parseStatement();\n            stmt.accept(out);\n        }\n\n        return buf.toString();\n    }\n\n    public static List<String> split(String sql, DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        {\n            Lexer lexer = createLexer(sql, dbType);\n            lexer.nextToken();\n\n            boolean script = false;\n            if (dbType == DbType.odps && lexer.token == Token.VARIANT) {\n                script = true;\n            }\n\n            if (script) {\n                return Collections.singletonList(sql);\n            }\n        }\n\n        List list = new ArrayList();\n\n        Lexer lexer = createLexer(sql, dbType);\n        lexer.config(SQLParserFeature.SkipComments, false);\n        lexer.config(SQLParserFeature.KeepComments, true);\n\n        boolean set = false, paiOrJar = false;\n        int start = 0;\n        Token token = lexer.token;\n        for (; lexer.token != Token.EOF; ) {\n            if (token == Token.SEMI) {\n                int len = lexer.startPos - start;\n                if (len > 0) {\n                    String lineSql = sql.substring(start, lexer.startPos);\n                    lineSql = lineSql.trim();\n                    if (!lineSql.isEmpty()) {\n                        list.add(lineSql);\n                    }\n                }\n                start = lexer.startPos + 1;\n                set = false;\n            } else if (token == Token.CREATE) {\n                lexer.nextToken();\n\n                if (lexer.token == Token.FUNCTION || lexer.identifierEquals(\"FUNCTION\")) {\n                    lexer.nextToken();\n                    lexer.nextToken();\n                    if (lexer.token == Token.AS) {\n                        lexer.nextToken();\n                        if (lexer.token == Token.LITERAL_CHARS) {\n                            lexer.nextToken();\n                            token = lexer.token;\n                            continue;\n                        }\n                    }\n                    lexer.startPos = sql.length();\n                    break;\n                }\n\n                token = lexer.token;\n                continue;\n            } else if (set && token == Token.EQ && dbType == DbType.odps) {\n                lexer.nextTokenForSet();\n                token = lexer.token;\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"USING\")) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"jar\")) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.token == Token.SET) {\n                set = true;\n            }\n\n            if (lexer.identifierEquals(\"ADD\") && (dbType == DbType.hive || dbType == DbType.odps || dbType == DbType.spark)) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"JAR\")) {\n                    lexer.nextPath();\n                }\n            } else {\n                lexer.nextToken();\n            }\n            token = lexer.token;\n        }\n\n        if (start != sql.length() && token != Token.SEMI) {\n            int end = lexer.startPos;\n            if (end > sql.length()) {\n                end = sql.length();\n            }\n            String splitSql = sql.substring(start, end).trim();\n            if (!paiOrJar) {\n                splitSql = removeComment(splitSql, dbType).trim();\n            } else {\n                if (splitSql.endsWith(\";\")) {\n                    splitSql = splitSql.substring(0, splitSql.length() - 1).trim();\n                }\n            }\n            if (!splitSql.isEmpty()) {\n                list.add(splitSql);\n            }\n        }\n\n        return list;\n    }\n\n    public static List<String> splitAndRemoveComment(String sql, DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        boolean containsCommentAndSemi = false;\n        {\n            Lexer lexer = createLexer(sql, dbType);\n            lexer.config(SQLParserFeature.SkipComments, false);\n            lexer.config(SQLParserFeature.KeepComments, true);\n\n            while (lexer.token != Token.EOF) {\n                if (lexer.token == Token.LINE_COMMENT\n                        || lexer.token == Token.MULTI_LINE_COMMENT\n                        || lexer.token == Token.SEMI) {\n                    containsCommentAndSemi = true;\n                    break;\n                }\n                lexer.nextToken();\n            }\n\n            if (!containsCommentAndSemi) {\n                return Collections.singletonList(sql);\n            }\n        }\n\n        {\n            Lexer lexer = createLexer(sql, dbType);\n            lexer.nextToken();\n\n            boolean script = false;\n            if (dbType == DbType.odps && lexer.token == Token.VARIANT) {\n                script = true;\n            }\n\n            if (script || lexer.identifierEquals(\"pai\") || lexer.identifierEquals(\"jar\") || lexer.identifierEquals(\"copy\")) {\n                return Collections.singletonList(sql);\n            }\n        }\n\n        List list = new ArrayList();\n\n        Lexer lexer = createLexer(sql, dbType);\n        lexer.config(SQLParserFeature.SkipComments, false);\n        lexer.config(SQLParserFeature.KeepComments, true);\n        lexer.nextToken();\n\n        boolean set = false, paiOrJar = false;\n        int start = 0;\n        Token preToken = null;\n        int prePos = 0;\n        Token token = lexer.token;\n        Token startToken = lexer.token;\n        while (token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT) {\n            lexer.nextToken();\n            token = lexer.token;\n            startToken = token;\n            start = lexer.startPos;\n        }\n\n        for (int tokens = 1; lexer.token != Token.EOF; ) {\n            if (token == Token.SEMI) {\n                int len = lexer.startPos - start;\n                if (len > 0) {\n                    String lineSql = sql.substring(start, lexer.startPos);\n                    String splitSql = set\n                            ? removeLeftComment(lineSql, dbType)\n                            : removeComment(lineSql, dbType\n                    ).trim();\n                    if (!splitSql.isEmpty()) {\n                        list.add(splitSql);\n                    }\n                }\n                lexer.nextToken();\n                token = lexer.token;\n                start = lexer.startPos;\n                startToken = token;\n                set = false;\n                tokens = token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT ? 0 : 1;\n                continue;\n            } else if (token == Token.MULTI_LINE_COMMENT) {\n                int len = lexer.startPos - start;\n                if (len > 0) {\n                    String splitSql = removeComment(\n                            sql.substring(start, lexer.startPos),\n                            dbType\n                    ).trim();\n                    if (!splitSql.isEmpty()) {\n                        list.add(splitSql);\n                    }\n                }\n                lexer.nextToken();\n                token = lexer.token;\n                start = lexer.startPos;\n                startToken = token;\n                tokens = token == Token.LINE_COMMENT || token == Token.MULTI_LINE_COMMENT ? 0 : 1;\n                continue;\n            } else if (token == Token.CREATE) {\n                lexer.nextToken();\n\n                if (lexer.token == Token.FUNCTION || lexer.identifierEquals(\"FUNCTION\")) {\n                    lexer.nextToken();\n                    lexer.nextToken();\n                    if (lexer.token == Token.AS) {\n                        lexer.nextToken();\n                        if (lexer.token == Token.LITERAL_CHARS) {\n                            lexer.nextToken();\n                            token = lexer.token;\n                            continue;\n                        }\n                    }\n                    lexer.startPos = sql.length();\n                    break;\n                }\n\n                token = lexer.token;\n                continue;\n            } else if (set && token == Token.EQ && dbType == DbType.odps) {\n                lexer.nextTokenForSet();\n                token = lexer.token;\n                continue;\n            } else if (dbType == DbType.odps\n                    && (preToken == null || preToken == Token.LINE_COMMENT || preToken == Token.SEMI)\n                    && (lexer.identifierEquals(\"pai\") || lexer.identifierEquals(\"jar\") || lexer.identifierEquals(\"copy\"))) {\n                lexer.scanLineArgument();\n                paiOrJar = true;\n            }\n\n            if (lexer.identifierEquals(\"USING\")) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"jar\")) {\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.token == Token.SET) {\n                set = true;\n            }\n\n            prePos = lexer.pos;\n            if (lexer.identifierEquals(\"ADD\") && (dbType == DbType.hive || dbType == DbType.odps || dbType == DbType.spark)) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"JAR\")) {\n                    lexer.nextPath();\n                }\n            } else {\n                lexer.nextToken();\n            }\n            preToken = token;\n            token = lexer.token;\n            if (token == Token.LINE_COMMENT\n                    && tokens == 0) {\n                start = lexer.pos;\n                startToken = token;\n            }\n\n            if (token != Token.LINE_COMMENT && token != Token.MULTI_LINE_COMMENT && token != Token.SEMI) {\n                tokens++;\n            }\n        }\n\n        if (start != sql.length() && token != Token.SEMI) {\n            int end = lexer.startPos;\n            if (end > sql.length()) {\n                end = sql.length();\n            }\n            String splitSql = sql.substring(start, end).trim();\n            if (!paiOrJar) {\n                splitSql = removeComment(splitSql, dbType).trim();\n            } else {\n                if (splitSql.endsWith(\";\")) {\n                    splitSql = splitSql.substring(0, splitSql.length() - 1).trim();\n                }\n            }\n            if (!splitSql.isEmpty()) {\n                list.add(splitSql);\n            }\n        }\n\n        return list;\n    }\n\n    public static String removeLeftComment(String sql, DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        sql = sql.trim();\n        if (sql.startsWith(\"jar\")) {\n            return sql;\n        }\n\n        boolean containsComment = false;\n        {\n            Lexer lexer = createLexer(sql, dbType);\n            lexer.config(SQLParserFeature.SkipComments, false);\n            lexer.config(SQLParserFeature.KeepComments, true);\n\n            while (lexer.token != Token.EOF) {\n                if (lexer.token == Token.LINE_COMMENT || lexer.token == Token.MULTI_LINE_COMMENT) {\n                    containsComment = true;\n                    break;\n                }\n                lexer.nextToken();\n            }\n\n            if (!containsComment) {\n                return sql;\n            }\n        }\n\n        StringBuilder sb = new StringBuilder();\n\n        Lexer lexer = createLexer(sql, dbType);\n        lexer.config(SQLParserFeature.SkipComments, false);\n        lexer.config(SQLParserFeature.KeepComments, true);\n        lexer.nextToken();\n\n        int start = 0;\n        for (; lexer.token != Token.EOF; lexer.nextToken()) {\n            if (lexer.token == Token.LINE_COMMENT || lexer.token == Token.MULTI_LINE_COMMENT) {\n                continue;\n            }\n            start = lexer.startPos;\n            break;\n        }\n\n        if (start != sql.length()) {\n            sb.append(sql.substring(start, sql.length()));\n        }\n\n        return sb.toString();\n    }\n\n    public static String removeComment(String sql, DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        sql = sql.trim();\n        if (sql.startsWith(\"jar\") || sql.startsWith(\"JAR\")) {\n            return sql;\n        }\n\n        if ((sql.startsWith(\"pai\") || sql.startsWith(\"PAI\")) && sql.indexOf(';') == -1) {\n            return sql;\n        }\n\n        boolean containsComment = false;\n        {\n            Lexer lexer = createLexer(sql, dbType);\n            lexer.config(SQLParserFeature.SkipComments, false);\n            lexer.config(SQLParserFeature.KeepComments, true);\n\n            while (lexer.token != Token.EOF) {\n                if (lexer.token == Token.LINE_COMMENT || lexer.token == Token.MULTI_LINE_COMMENT) {\n                    containsComment = true;\n                    break;\n                }\n                lexer.nextToken();\n            }\n\n            if (!containsComment) {\n                return sql;\n            }\n        }\n\n        StringBuilder sb = new StringBuilder();\n\n        Lexer lexer = createLexer(sql, dbType);\n        lexer.config(SQLParserFeature.SkipComments, false);\n        lexer.config(SQLParserFeature.KeepComments, true);\n\n        int start = 0;\n        Token token = lexer.token;\n        for (; lexer.token != Token.EOF; ) {\n            if (token == Token.LINE_COMMENT) {\n                int len = lexer.startPos - start;\n                if (len > 0) {\n                    sb.append(sql.substring(start, lexer.startPos));\n                }\n                start = lexer.startPos + lexer.stringVal().length();\n                if (lexer.startPos > 1 && lexer.text.charAt(lexer.startPos - 1) == '\\n') {\n                    while (start + 1 < lexer.text.length() && lexer.text.charAt(start) == '\\n') {\n                        start = start + 1;\n                    }\n                }\n            } else if (token == Token.MULTI_LINE_COMMENT) {\n                int len = lexer.startPos - start;\n                if (len > 0) {\n                    sb.append(sql.substring(start, lexer.startPos));\n                }\n                start = lexer.startPos + lexer.stringVal().length();\n            }\n\n            if (lexer.identifierEquals(\"ADD\")) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"JAR\")) {\n                    lexer.nextPath();\n                }\n            } else {\n                lexer.nextToken();\n            }\n            token = lexer.token;\n        }\n\n        if (start != sql.length() && token != Token.LINE_COMMENT && token != Token.MULTI_LINE_COMMENT) {\n            sb.append(sql.substring(start, sql.length()));\n        }\n\n        return sb.toString();\n    }\n\n    public static List<String> getTables(String sql, DbType dbType) {\n        Set<String> tables = new LinkedHashSet<>();\n\n        boolean set = false;\n        Lexer lexer = createLexer(sql, dbType);\n        lexer.nextToken();\n\n        SQLExprParser exprParser;\n        switch (dbType) {\n            case odps:\n                exprParser = new OdpsExprParser(lexer);\n                break;\n            case mysql:\n                exprParser = new MySqlExprParser(lexer);\n                break;\n            default:\n                exprParser = new SQLExprParser(lexer);\n                break;\n        }\n\n        for_:\n        for (; lexer.token != Token.EOF; ) {\n            switch (lexer.token) {\n                case CREATE:\n                case DROP:\n                case ALTER:\n                    set = false;\n                    lexer.nextToken();\n\n                    if (lexer.token == Token.TABLE) {\n                        lexer.nextToken();\n\n                        if (lexer.token == Token.IF) {\n                            lexer.nextToken();\n\n                            if (lexer.token == Token.NOT) {\n                                lexer.nextToken();\n                            }\n\n                            if (lexer.token == Token.EXISTS) {\n                                lexer.nextToken();\n                            }\n                        }\n\n                        SQLName name = exprParser.name();\n                        tables.add(name.toString());\n\n                        if (lexer.token == Token.AS) {\n                            lexer.nextToken();\n                        }\n                    }\n                    continue for_;\n                case FROM:\n                case JOIN:\n                    lexer.nextToken();\n                    if (lexer.token != Token.LPAREN\n                            && lexer.token != Token.VALUES\n                    ) {\n                        SQLName name = exprParser.name();\n                        tables.add(name.toString());\n                    }\n                    continue for_;\n                case SEMI:\n                    set = false;\n                    break;\n                case SET:\n                    set = true;\n                    break;\n                case EQ:\n                    if (set && dbType == DbType.odps) {\n                        lexer.nextTokenForSet();\n                        continue for_;\n                    }\n                    break;\n                default:\n                    break;\n            }\n\n            lexer.nextToken();\n\n        }\n\n        return new ArrayList<>(tables);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectListCache.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\npublic class SQLSelectListCache {\n    private static final Log LOG = LogFactory.getLog(SQLSelectListCache.class);\n    private final DbType dbType;\n    private final List<Entry> entries = new CopyOnWriteArrayList<Entry>();\n\n    public SQLSelectListCache(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public void add(String select) {\n        if (select == null || select.length() == 0) {\n            return;\n        }\n\n        SQLSelectParser selectParser = SQLParserUtils.createSQLStatementParser(select, dbType)\n                .createSQLSelectParser();\n        SQLSelectQueryBlock queryBlock = SQLParserUtils.createSelectQueryBlock(dbType);\n        selectParser.accept(Token.SELECT);\n\n        selectParser.parseSelectList(queryBlock);\n\n        selectParser.accept(Token.FROM);\n        selectParser.accept(Token.EOF);\n\n        String printSql = queryBlock.toString();\n        long printSqlHash = FnvHash.fnv1a_64_lower(printSql);\n        entries.add(\n                new Entry(\n                        select.substring(6),\n                        queryBlock,\n                        printSql,\n                        printSqlHash\n                )\n        );\n\n        if (entries.size() > 5) {\n            LOG.warn(\"SelectListCache is too large.\");\n        }\n    }\n\n    public int getSize() {\n        return entries.size();\n    }\n\n    public void clear() {\n        entries.clear();\n    }\n\n    public boolean match(Lexer lexer, SQLSelectQueryBlock queryBlock) {\n        if (lexer.token != Token.SELECT) {\n            return false;\n        }\n\n        int pos = lexer.pos;\n        String text = lexer.text;\n\n        for (int i = 0; i < entries.size(); i++) {\n            Entry entry = entries.get(i);\n            String block = entry.sql;\n            if (text.startsWith(block, pos)) {\n                //SQLSelectQueryBlock queryBlockCached = queryBlockCache.get(i);\n                // queryBlockCached.cloneSelectListTo(queryBlock);\n                queryBlock.setCachedSelectList(entry.printSql, entry.printSqlHash);\n\n                int len = pos + block.length();\n                //todo fix reset\n                lexer.reset(len, text.charAt(len), Token.FROM);\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private static class Entry {\n        public final String sql;\n        public final SQLSelectQueryBlock queryBlock;\n        public final String printSql;\n        public final long printSqlHash;\n\n        public Entry(String sql, SQLSelectQueryBlock queryBlock, String printSql, long printSqlHash) {\n            this.sql = sql;\n            this.queryBlock = queryBlock;\n            this.printSql = printSql;\n            this.printSqlHash = printSqlHash;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\n\npublic class SQLSelectParser extends SQLParser {\n    protected SQLExprParser exprParser;\n    protected SQLSelectListCache selectListCache;\n\n    public SQLSelectParser(String sql) {\n        super(sql);\n    }\n\n    public SQLSelectParser(Lexer lexer) {\n        super(lexer);\n    }\n\n    public SQLSelectParser(SQLExprParser exprParser) {\n        this(exprParser, null);\n    }\n\n    public SQLSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {\n        super(exprParser.getLexer(), exprParser.getDbType());\n        this.exprParser = exprParser;\n        this.selectListCache = selectListCache;\n    }\n\n    public SQLSelect select() {\n        SQLSelect select = new SQLSelect();\n\n        Lexer.SavePoint mark = null;\n        int parenCount = 0;\n        while (lexer.token == Token.LPAREN) {\n            if (mark == null) {\n                mark = lexer.markOut();\n            }\n            parenCount++;\n            lexer.nextToken();\n        }\n\n        if (lexer.token == Token.WITH) {\n            SQLWithSubqueryClause with = this.parseWith();\n            select.setWithSubQuery(with);\n        } else {\n            if (mark != null) {\n                lexer.reset(mark);\n                parenCount = 0;\n            }\n        }\n\n        SQLSelectQuery query = query(select, true);\n        select.setQuery(query);\n\n        SQLOrderBy orderBy = this.parseOrderBy();\n\n        if (query instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n\n            if (queryBlock.getOrderBy() == null) {\n                queryBlock.setOrderBy(orderBy);\n                if (lexer.token == Token.LIMIT) {\n                    SQLLimit limit = this.exprParser.parseLimit();\n                    queryBlock.setLimit(limit);\n                }\n            } else {\n                select.setOrderBy(orderBy);\n                if (lexer.token == Token.LIMIT) {\n                    SQLLimit limit = this.exprParser.parseLimit();\n                    select.setLimit(limit);\n                }\n            }\n\n            if (orderBy != null) {\n                parseFetchClause(queryBlock);\n            }\n        } else {\n            select.setOrderBy(orderBy);\n        }\n\n        if (lexer.token == Token.LIMIT) {\n            SQLLimit limit = this.exprParser.parseLimit();\n            select.setLimit(limit);\n        }\n\n        while (lexer.token == Token.HINT) {\n            this.exprParser.parseHints(select.getHints());\n        }\n\n        for (int i = 0; i < parenCount; i++) {\n            accept(Token.RPAREN);\n        }\n\n        if (parenCount > 0 && lexer.token == Token.UNION) {\n            select.setQuery(\n                    this.queryRest(select.getQuery(), true));\n        }\n\n        return select;\n    }\n\n    protected void afterParseFetchClause(SQLSelectQueryBlock queryBlock) {}\n    protected void afterParseLimitClause(SQLSelectQueryBlock queryBlock) {}\n\n    protected SQLUnionQuery createSQLUnionQuery() {\n        return new SQLUnionQuery(dbType);\n    }\n\n    public SQLUnionQuery unionRest(SQLUnionQuery union) {\n        if (lexer.token == Token.ORDER) {\n            SQLOrderBy orderBy = this.exprParser.parseOrderBy();\n            union.setOrderBy(orderBy);\n            return unionRest(union);\n        }\n\n        if (lexer.token == Token.LIMIT) {\n            SQLLimit limit = this.exprParser.parseLimit();\n            union.setLimit(limit);\n        }\n        return union;\n    }\n\n    public SQLSelectQuery queryRest(SQLSelectQuery selectQuery) {\n        return queryRest(selectQuery, true);\n    }\n\n    public SQLSelectQuery queryRest(SQLSelectQuery selectQuery, boolean acceptUnion) {\n        if (!acceptUnion) {\n            return selectQuery;\n        }\n\n        if (lexer.token == Token.UNION) {\n            do {\n                Lexer.SavePoint uninMark = lexer.mark();\n                lexer.nextToken();\n\n                switch (lexer.token) {\n                    case GROUP:\n                    case ORDER:\n                    case WHERE:\n                    case RPAREN:\n                        lexer.reset(uninMark);\n                        return selectQuery;\n                    default:\n                        break;\n                }\n\n                if (lexer.token == Token.SEMI && dialectFeatureEnabled(QueryRestSemi)) {\n                    break;\n                }\n\n                SQLUnionQuery union = createSQLUnionQuery();\n                union.setLeft(selectQuery);\n\n                if (lexer.token == Token.ALL) {\n                    union.setOperator(SQLUnionOperator.UNION_ALL);\n                    lexer.nextToken();\n                } else if (lexer.token == Token.DISTINCT) {\n                    union.setOperator(SQLUnionOperator.DISTINCT);\n                    lexer.nextToken();\n                }\n\n                boolean paren = lexer.token == Token.LPAREN;\n                SQLSelectQuery right = this.query(paren ? null : union, false);\n                union.setRight(right);\n\n                while (lexer.isEnabled(SQLParserFeature.EnableMultiUnion)\n                        && lexer.token == Token.UNION\n                ) {\n                    Lexer.SavePoint mark = lexer.mark();\n                    lexer.nextToken();\n\n                    if (lexer.token == Token.UNION && dialectFeatureEnabled(TwoConsecutiveUnion)) {\n                        continue; // skip\n                    }\n\n                    if (lexer.token == Token.ALL) {\n                        if (union.getOperator() == SQLUnionOperator.UNION_ALL) {\n                            lexer.nextToken();\n                        } else {\n                            lexer.reset(mark);\n                            break;\n                        }\n                    } else if (lexer.token == Token.DISTINCT) {\n                        if (union.getOperator() == SQLUnionOperator.DISTINCT) {\n                            lexer.nextToken();\n                        } else {\n                            lexer.reset(mark);\n                            break;\n                        }\n                    } else if (union.getOperator() == SQLUnionOperator.UNION) {\n                        // skip\n                    } else {\n                        lexer.reset(mark);\n                        break;\n                    }\n\n                    paren = lexer.token == Token.LPAREN;\n                    SQLSelectQuery r = this.query(paren ? null : union, false);\n                    r.setParenthesized(paren);\n                    union.addRelation(r);\n                    right = r;\n                }\n\n                if (!paren) {\n                    if (right instanceof SQLSelectQueryBlock) {\n                        SQLSelectQueryBlock rightQuery = (SQLSelectQueryBlock) right;\n                        SQLOrderBy orderBy = rightQuery.getOrderBy();\n                        if (orderBy != null) {\n                            union.setOrderBy(orderBy);\n                            rightQuery.setOrderBy(null);\n                        }\n\n                        SQLLimit limit = rightQuery.getLimit();\n                        if (limit != null) {\n                            union.setLimit(limit);\n                            rightQuery.setLimit(null);\n                        }\n                    } else if (right instanceof SQLUnionQuery) {\n                        SQLUnionQuery rightUnion = (SQLUnionQuery) right;\n                        final SQLOrderBy orderBy = rightUnion.getOrderBy();\n                        if (orderBy != null) {\n                            union.setOrderBy(orderBy);\n                            rightUnion.setOrderBy(null);\n                        }\n\n                        SQLLimit limit = rightUnion.getLimit();\n                        if (limit != null) {\n                            union.setLimit(limit);\n                            rightUnion.setLimit(null);\n                        }\n                    }\n                }\n\n                union = unionRest(union);\n\n                selectQuery = union;\n\n            } while (lexer.token() == Token.UNION);\n\n            selectQuery = queryRest(selectQuery, true);\n\n            return selectQuery;\n        }\n\n        if (lexer.token == Token.EXCEPT) {\n            lexer.nextToken();\n\n            SQLUnionQuery union = new SQLUnionQuery();\n            union.setLeft(selectQuery);\n\n            if (lexer.token == Token.ALL) {\n                lexer.nextToken();\n                union.setOperator(SQLUnionOperator.EXCEPT_ALL);\n            } else if (lexer.token == Token.DISTINCT) {\n                lexer.nextToken();\n                union.setOperator(SQLUnionOperator.EXCEPT_DISTINCT);\n            } else {\n                union.setOperator(SQLUnionOperator.EXCEPT);\n            }\n\n            boolean paren = lexer.token == Token.LPAREN;\n\n            SQLSelectQuery right = this.query(union, false);\n            union.setRight(right);\n\n            if (!paren) {\n                if (right instanceof SQLSelectQueryBlock) {\n                    SQLSelectQueryBlock rightQuery = (SQLSelectQueryBlock) right;\n                    SQLOrderBy orderBy = rightQuery.getOrderBy();\n                    if (orderBy != null) {\n                        union.setOrderBy(orderBy);\n                        rightQuery.setOrderBy(null);\n                    }\n\n                    SQLLimit limit = rightQuery.getLimit();\n                    if (limit != null) {\n                        union.setLimit(limit);\n                        rightQuery.setLimit(null);\n                    }\n                } else if (right instanceof SQLUnionQuery) {\n                    SQLUnionQuery rightUnion = (SQLUnionQuery) right;\n                    final SQLOrderBy orderBy = rightUnion.getOrderBy();\n                    if (orderBy != null) {\n                        union.setOrderBy(orderBy);\n                        rightUnion.setOrderBy(null);\n                    }\n\n                    SQLLimit limit = rightUnion.getLimit();\n                    if (limit != null) {\n                        union.setLimit(limit);\n                        rightUnion.setLimit(null);\n                    }\n                }\n            }\n\n            return queryRest(union, true);\n        }\n\n        if (lexer.token == Token.INTERSECT) {\n            lexer.nextToken();\n\n            SQLUnionQuery union = new SQLUnionQuery();\n            union.setLeft(selectQuery);\n\n            if (lexer.token() == Token.DISTINCT) {\n                lexer.nextToken();\n                union.setOperator(SQLUnionOperator.INTERSECT_DISTINCT);\n            } else if (lexer.token == Token.ALL) {\n                lexer.nextToken();\n                union.setOperator(SQLUnionOperator.INTERSECT_ALL);\n            } else {\n                union.setOperator(SQLUnionOperator.INTERSECT);\n            }\n\n            boolean paren = lexer.token == Token.LPAREN;\n            SQLSelectQuery right = this.query(union, false);\n            union.setRight(right);\n            if (!paren) {\n                if (right instanceof SQLSelectQueryBlock) {\n                    SQLSelectQueryBlock rightQuery = (SQLSelectQueryBlock) right;\n                    SQLOrderBy orderBy = rightQuery.getOrderBy();\n                    if (orderBy != null) {\n                        union.setOrderBy(orderBy);\n                        rightQuery.setOrderBy(null);\n                    }\n\n                    SQLLimit limit = rightQuery.getLimit();\n                    if (limit != null) {\n                        union.setLimit(limit);\n                        rightQuery.setLimit(null);\n                    }\n                } else if (right instanceof SQLUnionQuery) {\n                    SQLUnionQuery rightUnion = (SQLUnionQuery) right;\n                    final SQLOrderBy orderBy = rightUnion.getOrderBy();\n                    if (orderBy != null) {\n                        union.setOrderBy(orderBy);\n                        rightUnion.setOrderBy(null);\n                    }\n\n                    SQLLimit limit = rightUnion.getLimit();\n                    if (limit != null) {\n                        union.setLimit(limit);\n                        rightUnion.setLimit(null);\n                    }\n                }\n            }\n\n            return queryRest(union, true);\n        }\n\n        if (acceptUnion && lexer.token == Token.MINUS) {\n            lexer.nextToken();\n\n            SQLUnionQuery union = new SQLUnionQuery();\n            union.setLeft(selectQuery);\n\n            union.setOperator(SQLUnionOperator.MINUS);\n            if (lexer.token == Token.DISTINCT) {\n                union.setOperator(SQLUnionOperator.MINUS_DISTINCT);\n                lexer.nextToken();\n            } else if (lexer.token == Token.ALL) {\n                union.setOperator(SQLUnionOperator.MINUS_ALL);\n                lexer.nextToken();\n            }\n\n            SQLSelectQuery right = this.query(union, false);\n            union.setRight(right);\n\n            return queryRest(union, true);\n        }\n\n        return selectQuery;\n    }\n\n    private void setToLeft(SQLSelectQuery selectQuery,\n                           SQLUnionQuery parentUnion,\n                           SQLUnionQuery union,\n                           SQLSelectQuery right) {\n        SQLUnionOperator operator = union.getOperator();\n\n        if (union.getLeft() instanceof SQLUnionQuery) {\n            SQLUnionQuery left = (SQLUnionQuery) union.getLeft();\n            while (left.getLeft() instanceof SQLUnionQuery) {\n                left = (SQLUnionQuery) left.getLeft();\n            }\n\n            left.setLeft(new SQLUnionQuery(parentUnion.getLeft(), parentUnion.getOperator(), left.getLeft()));\n\n            parentUnion.setLeft(union.getLeft());\n            parentUnion.setRight(union.getRight());\n        } else {\n            parentUnion.setRight(right);\n            union.setLeft(parentUnion.getLeft());\n            parentUnion.setLeft(union);\n            union.setRight(selectQuery);\n            union.setOperator(parentUnion.getOperator());\n            parentUnion.setOperator(operator);\n        }\n\n    }\n\n    public SQLSelectQuery query() {\n        return query(null, true);\n    }\n\n    public SQLSelectQuery query(SQLObject parent) {\n        return query(parent, true);\n    }\n\n    protected SQLSelectQueryBlock createSelectQueryBlock() {\n        return new SQLSelectQueryBlock(dbType);\n    }\n\n    protected void querySelectListBefore(SQLSelectQueryBlock x) {\n    }\n\n    protected void parseTop(SQLSelectQueryBlock x) {\n    }\n\n    protected void queryBefore(SQLSelectQueryBlock x) {\n    }\n\n    public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n\n            SQLSelectQuery select = query();\n            accept(Token.RPAREN);\n            select.setParenthesized(true);\n\n            return queryRest(select, acceptUnion);\n        }\n\n        if (lexer.token() == Token.VALUES) {\n            return valuesQuery(acceptUnion);\n        }\n\n        SQLSelectQueryBlock queryBlock = createSelectQueryBlock();\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            queryBlock.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token() == Token.TABLE && dialectFeatureEnabled(QueryTable)) {\n            lexer.nextToken();\n            queryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr()));\n            queryBlock.setFrom(parseTableSource());\n            return queryRest(queryBlock, acceptUnion);\n        }\n\n        queryBefore(queryBlock);\n\n        accept(Token.SELECT);\n\n        querySelectListBefore(queryBlock);\n\n        if (lexer.token() == Token.HINT) {\n            this.exprParser.parseHints(queryBlock.getHints());\n        }\n\n        lexer.nextIf(Token.COMMENT);\n\n        parseTop(queryBlock);\n        parseBeforeSelectList(queryBlock);\n\n        parseSelectList(queryBlock);\n\n        if (lexer.token() == Token.INTO) {\n            lexer.nextToken();\n\n            SQLExpr expr = expr();\n            if (lexer.token() != Token.COMMA) {\n                queryBlock.setInto(expr);\n            }\n        }\n\n        parseFrom(queryBlock);\n\n        parseWhere(queryBlock);\n\n        parseGroupBy(queryBlock);\n\n        qualify(queryBlock);\n        parseWindow(queryBlock);\n\n        parseSortBy(queryBlock);\n\n        parseFetchClause(queryBlock);\n\n        if (lexer.token() == Token.FOR) {\n            lexer.nextToken();\n            accept(Token.UPDATE);\n\n            queryBlock.setForUpdate(true);\n\n            if (lexer.identifierEquals(FnvHash.Constants.NO_WAIT) || lexer.identifierEquals(FnvHash.Constants.NOWAIT)) {\n                lexer.nextToken();\n                queryBlock.setNoWait(true);\n            } else if (lexer.identifierEquals(FnvHash.Constants.WAIT)) {\n                lexer.nextToken();\n                SQLExpr waitTime = this.exprParser.primary();\n                queryBlock.setWaitTime(waitTime);\n            }\n        }\n\n        return queryRest(queryBlock, acceptUnion);\n    }\n\n    protected void parseBeforeSelectList(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token == Token.DISTINCT) {\n            queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);\n            lexer.nextToken();\n        } else if (lexer.token == Token.UNIQUE) {\n            queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);\n            lexer.nextToken();\n        } else if (lexer.token == Token.ALL) {\n            queryBlock.setDistionOption(SQLSetQuantifier.ALL);\n            lexer.nextToken();\n        }\n    }\n\n    protected SQLSelectQuery valuesQuery(boolean acceptUnion) {\n        lexer.nextToken();\n        SQLValuesQuery valuesQuery = new SQLValuesQuery();\n\n        for (; ; ) {\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                SQLListExpr listExpr = new SQLListExpr();\n                this.exprParser.exprList(listExpr.getItems(), listExpr);\n                accept(Token.RPAREN);\n                valuesQuery.addValue(listExpr);\n            } else {\n                this.exprParser.exprList(valuesQuery.getValues(), valuesQuery);\n            }\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n        }\n\n        return queryRest(valuesQuery, acceptUnion);\n    }\n\n    protected void withSubquery(SQLSelect select) {\n        if (lexer.token == Token.WITH) {\n            lexer.nextToken();\n\n            SQLWithSubqueryClause withQueryClause = new SQLWithSubqueryClause();\n\n            if (lexer.token == Token.RECURSIVE || lexer.identifierEquals(FnvHash.Constants.RECURSIVE)) {\n                lexer.nextToken();\n                withQueryClause.setRecursive(true);\n            }\n\n            for (; ; ) {\n                SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry();\n                entry.setParent(withQueryClause);\n\n                String alias = this.lexer.stringVal();\n                lexer.nextToken();\n                entry.setAlias(alias);\n\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n                    exprParser.names(entry.getColumns());\n                    accept(Token.RPAREN);\n                }\n\n                accept(Token.AS);\n                accept(Token.LPAREN);\n                entry.setSubQuery(select());\n                accept(Token.RPAREN);\n\n                withQueryClause.addEntry(entry);\n\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n\n            select.setWithSubQuery(withQueryClause);\n        }\n    }\n\n    public SQLWithSubqueryClause parseWith() {\n        SQLWithSubqueryClause withQueryClause = new SQLWithSubqueryClause();\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            withQueryClause.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        accept(Token.WITH);\n\n        if (lexer.token == Token.RECURSIVE || lexer.identifierEquals(FnvHash.Constants.RECURSIVE)) {\n            lexer.nextToken();\n            withQueryClause.setRecursive(true);\n        }\n\n        for (; ; ) {\n            SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry();\n            entry.setParent(withQueryClause);\n\n            String alias = this.lexer.stringVal();\n            lexer.nextToken();\n            if (lexer.nextIf(Token.LPAREN)) {\n                exprParser.names(entry.getColumns(), entry);\n                accept(Token.RPAREN);\n            }\n            entry.setAlias(alias);\n\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                exprParser.names(entry.getColumns());\n                accept(Token.RPAREN);\n            }\n\n            accept(Token.AS);\n            accept(Token.LPAREN);\n\n            switch (lexer.token) {\n                case SELECT:\n                case LPAREN:\n                case WITH:\n                case FROM:\n                case VALUES:\n                    entry.setSubQuery(select());\n                    break;\n                default:\n                    break;\n            }\n\n            accept(Token.RPAREN);\n\n            withQueryClause.addEntry(entry);\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        return withQueryClause;\n    }\n\n    public void parseWhere(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token != Token.WHERE) {\n            return;\n        }\n        lexer.nextTokenIdent();\n        List<String> beforeComments = null;\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            beforeComments = lexer.readAndResetComments();\n        }\n\n        SQLExpr where;\n\n        if (lexer.token == Token.IDENTIFIER) {\n            String ident = lexer.stringVal();\n            long hash_lower = lexer.hashLCase();\n            lexer.nextTokenEq();\n\n            SQLExpr identExpr;\n            if (lexer.token == Token.LITERAL_CHARS) {\n                String literal = lexer.stringVal;\n                if (hash_lower == FnvHash.Constants.TIMESTAMP) {\n                    identExpr = new SQLTimestampExpr(literal);\n                    lexer.nextToken();\n                } else if (hash_lower == FnvHash.Constants.DATE) {\n                    identExpr = new SQLDateExpr(literal);\n                    lexer.nextToken();\n                } else if (hash_lower == FnvHash.Constants.REAL) {\n                    identExpr = new SQLRealExpr(Float.parseFloat(literal));\n                    lexer.nextToken();\n                } else {\n                    identExpr = new SQLIdentifierExpr(ident, hash_lower);\n                }\n            } else if (lexer.identifierEquals(\"COLLATE\")) {\n                acceptIdentifier(\"COLLATE\");\n                String collateValue = lexer.stringVal();\n                if (lexer.token == Token.IDENTIFIER || lexer.token == Token.LITERAL_ALIAS || lexer.token == Token.LITERAL_CHARS) {\n                    identExpr = new SQLIdentifierExpr(ident);\n                    ((SQLIdentifierExpr) identExpr).setCollate(collateValue);\n                    lexer.nextToken();\n                } else {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n            } else {\n                identExpr = new SQLIdentifierExpr(ident, hash_lower);\n            }\n\n            if (lexer.token == Token.DOT) {\n                identExpr = this.exprParser.primaryRest(identExpr);\n            }\n\n            if (lexer.token == Token.EQ) {\n                SQLExpr rightExp;\n\n                lexer.nextToken();\n\n                try {\n                    rightExp = this.exprParser.bitOr();\n                } catch (EOFParserException e) {\n                    throw new ParserException(\"EOF, \" + ident + \"=\", e);\n                }\n\n                where = new SQLBinaryOpExpr(identExpr, SQLBinaryOperator.Equality, rightExp, dbType);\n                switch (lexer.token) {\n                    case BETWEEN:\n                    case IS:\n                    case EQ:\n                    case IN:\n                    case CONTAINS:\n                    case BANG_TILDE_STAR:\n                    case TILDE_EQ:\n                    case LT:\n                    case LTEQ:\n                    case LTEQGT:\n                    case GT:\n                    case GTEQ:\n                    case LTGT:\n                    case BANGEQ:\n                    case LIKE:\n                    case NOT:\n                    case VARIANT:\n                        where = this.exprParser.relationalRest(where);\n                        break;\n                    default:\n                        break;\n                }\n\n                where = this.exprParser.andRest(where);\n                where = this.exprParser.xorRest(where);\n                where = this.exprParser.orRest(where);\n            } else {\n                identExpr = this.exprParser.primaryRest(identExpr);\n                where = this.exprParser.exprRest(identExpr);\n            }\n        } else {\n            while (lexer.token == Token.HINT) {\n                lexer.nextToken();\n            }\n\n            where = this.exprParser.expr();\n\n            while (lexer.token == Token.HINT) {\n                lexer.nextToken();\n            }\n        }\n//            where = this.exprParser.expr();\n\n        if (beforeComments != null) {\n            where.addBeforeComment(beforeComments);\n        }\n\n        if (lexer.hasComment() && lexer.isKeepComments() //\n                && lexer.token != Token.INSERT // odps multi-insert\n        ) {\n            where.addAfterComment(lexer.readAndResetComments());\n        }\n\n        queryBlock.setWhere(where);\n\n    }\n\n    protected void parseAfterOrderBy(SQLSelectQueryBlock queryBlock) {}\n\n    protected void parseSortBy(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token() == Token.ORDER) {\n            SQLOrderBy orderBy = parseOrderBy();\n            queryBlock.setOrderBy(orderBy);\n            parseAfterOrderBy(queryBlock);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.DISTRIBUTE)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            for (; ; ) {\n                SQLSelectOrderByItem distributeByItem = this.exprParser.parseSelectOrderByItem();\n                queryBlock.addDistributeBy(distributeByItem);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.SORT)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            for (; ; ) {\n                SQLSelectOrderByItem sortByItem = this.exprParser.parseSelectOrderByItem();\n                queryBlock.addSortBy(sortByItem);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.CLUSTER)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            for (; ; ) {\n                SQLSelectOrderByItem clusterByItem = this.exprParser.parseSelectOrderByItem();\n                queryBlock.addClusterBy(clusterByItem);\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    protected void qualify(SQLSelectQueryBlock queryBlock) {\n        if (!lexer.nextIf(Token.QUALIFY)) {\n            return;\n        }\n        SQLExpr qualify = exprParser.expr();\n        queryBlock.setQualify(qualify);\n    }\n\n    protected void parseWindow(SQLSelectQueryBlock queryBlock) {\n        if (!(lexer.identifierEquals(FnvHash.Constants.WINDOW) || lexer.token == Token.WINDOW)) {\n            return;\n        }\n\n        lexer.nextToken();\n\n        for (; ; ) {\n            SQLName name = this.exprParser.name();\n            accept(Token.AS);\n            SQLOver over = new SQLOver();\n            this.exprParser.over(over);\n            queryBlock.addWindow(new SQLWindow(name, over));\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    public void parseGroupBy(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token == Token.GROUP) {\n            lexer.nextTokenBy();\n            accept(Token.BY);\n\n            SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause();\n\n            if (lexer.token == Token.HINT) {\n                groupBy.setHint(this.exprParser.parseHint());\n            }\n\n            if (lexer.token == Token.ALL) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (!lexer.identifierEquals(FnvHash.Constants.GROUPING)) {\n                    if (dialectFeatureEnabled(GroupByAll)) {\n                        lexer.reset(mark);\n                    } else {\n                        throw new ParserException(\"group by all syntax error. \" + lexer.info());\n                    }\n                }\n            } else if (lexer.token == Token.DISTINCT) {\n                lexer.nextToken();\n                groupBy.setDistinct(true);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.ROLLUP)) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                groupBy.setWithRollUp(true);\n            }\n            if (lexer.identifierEquals(FnvHash.Constants.CUBE)) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                groupBy.setWithCube(true);\n            }\n\n            for (; ; ) {\n                List<String> comments = null;\n                if (lexer.hasComment()) {\n                    comments = lexer.readAndResetComments();\n                }\n                SQLExpr item = parseGroupByItem();\n                if (comments != null) {\n                    item.addBeforeComment(comments);\n                }\n\n                item.setParent(groupBy);\n                groupBy.addItem(item);\n\n                if (lexer.token == Token.COMMA) {\n                    int line = lexer.line;\n                    lexer.nextToken();\n\n                    if (lexer.hasComment()\n                            && lexer.isKeepComments()\n                            && lexer.getComments().size() == 1\n                            && lexer.getComments().get(0).startsWith(\"--\")\n                            && lexer.line == line + 1) {\n                        item.addAfterComment(lexer.readAndResetComments());\n                    }\n                    continue;\n                } else if (lexer.identifierEquals(FnvHash.Constants.GROUPING)) {\n                    continue;\n                } else {\n                    break;\n                }\n            }\n            if (groupBy.isWithRollUp() || groupBy.isWithCube()) {\n                accept(Token.RPAREN);\n                groupBy.setParen(true);\n\n                if (lexer.token == Token.COMMA && dialectFeatureEnabled(RewriteGroupByCubeRollupToFunction)) {\n                    lexer.nextToken();\n                    SQLMethodInvokeExpr func = new SQLMethodInvokeExpr(groupBy.isWithCube() ? \"CUBE\" : \"ROLLUP\");\n                    func.getArguments().addAll(groupBy.getItems());\n                    groupBy.getItems().clear();\n                    groupBy.setWithCube(false);\n                    groupBy.setWithRollUp(false);\n                    for (SQLExpr arg : func.getArguments()) {\n                        arg.setParent(func);\n                    }\n                    groupBy.addItem(func);\n                    this.exprParser.exprList(groupBy.getItems(), groupBy);\n                }\n            }\n\n            if (lexer.token == (Token.HAVING)) {\n                lexer.nextToken();\n\n                SQLExpr having = this.exprParser.expr();\n                groupBy.setHaving(having);\n            }\n\n            if (lexer.token == Token.WITH) {\n                parseOrderByWith(groupBy, queryBlock);\n            }\n\n            if (groupBy.getHaving() == null && lexer.token == Token.HAVING) {\n                lexer.nextToken();\n\n                SQLExpr having = this.exprParser.expr();\n                groupBy.setHaving(having);\n            }\n\n            queryBlock.setGroupBy(groupBy);\n        } else if (lexer.token == (Token.HAVING)) {\n            lexer.nextToken();\n\n            SQLSelectGroupByClause groupBy = new SQLSelectGroupByClause();\n            groupBy.setHaving(this.exprParser.expr());\n\n            if (lexer.token == (Token.GROUP)) {\n                lexer.nextToken();\n                accept(Token.BY);\n\n                for (; ; ) {\n                    SQLExpr item = parseGroupByItem();\n\n                    item.setParent(groupBy);\n                    groupBy.addItem(item);\n\n                    if (!(lexer.token == (Token.COMMA))) {\n                        break;\n                    }\n\n                    lexer.nextToken();\n                }\n            }\n\n            if (lexer.token == Token.WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"ROLLUP\");\n\n                groupBy.setWithRollUp(true);\n            }\n\n            if (dialectFeatureEnabled(GroupByPostDesc)\n                    && lexer.token == Token.DESC) {\n                lexer.nextToken(); // skip\n            }\n\n            queryBlock.setGroupBy(groupBy);\n        }\n    }\n\n    protected void parseOrderByWith(SQLSelectGroupByClause groupBy, SQLSelectQueryBlock queryBlock) {\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n\n        if (lexer.identifierEquals(FnvHash.Constants.CUBE)) {\n            lexer.nextToken();\n            groupBy.setWithCube(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.ROLLUP)) {\n            lexer.nextToken();\n            groupBy.setWithRollUp(true);\n        } else {\n            lexer.reset(mark);\n        }\n    }\n\n    protected SQLExpr parseGroupByItem() {\n        if (lexer.token == Token.LPAREN) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.token == Token.RPAREN) {\n                lexer.nextToken();\n                return new SQLListExpr();\n            }\n\n            lexer.reset(mark);\n        }\n        if (lexer.nextIf(Token.ALL)) {\n            return new SQLIdentifierExpr(\"ALL\");\n        }\n        SQLExpr item;\n        if (lexer.identifierEquals(FnvHash.Constants.ROLLUP)) {\n            SQLMethodInvokeExpr rollup = new SQLMethodInvokeExpr(lexer.stringVal());\n            lexer.nextToken();\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                for (; ; ) {\n                    if (lexer.token == Token.RPAREN) {\n                        break;\n                    }\n\n                    SQLExpr expr;\n                    if (lexer.token == Token.LPAREN) {\n                        accept(Token.LPAREN);\n                        SQLListExpr list = new SQLListExpr();\n                        if (lexer.token == Token.COMMA) {\n                            lexer.nextToken();\n                        }\n                        this.exprParser.exprList(list.getItems(), list);\n                        accept(Token.RPAREN);\n                        expr = list;\n                    } else {\n                        expr = this.exprParser.expr();\n                    }\n                    rollup.addArgument(expr);\n\n                    if (lexer.token == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            }\n            item = rollup;\n        } else {\n            item = this.exprParser.expr();\n        }\n        if (lexer.nextIf(Token.AS)) {\n            item = new SQLAliasedExpr(item, lexer.stringVal);\n            lexer.nextToken();\n        }\n\n        if (dialectFeatureEnabled(GroupByItemOrder)) {\n            if (lexer.token == Token.DESC) {\n                lexer.nextToken(); // skip\n                item = new MySqlOrderingExpr(item, SQLOrderingSpecification.DESC);\n            } else if (lexer.token == Token.ASC) {\n                lexer.nextToken(); // skip\n                item = new MySqlOrderingExpr(item, SQLOrderingSpecification.ASC);\n            }\n        }\n\n        if (lexer.token == Token.HINT) {\n            SQLCommentHint hint = this.exprParser.parseHint(); // skip\n            if (item instanceof SQLObjectImpl) {\n                ((SQLObjectImpl) item).setHint(hint);\n            }\n        }\n\n        return item;\n    }\n\n    protected void parseSelectList(SQLSelectQueryBlock queryBlock) {\n        final List<SQLSelectItem> selectList = queryBlock.getSelectList();\n        boolean hasComma = true;\n        for (; ; ) {\n            List<String> previousComments = lexer.comments;\n            final SQLSelectItem selectItem = this.exprParser.parseSelectItem();\n            selectItem.addBeforeComment(previousComments);\n            selectList.add(selectItem);\n            selectItem.setParent(queryBlock);\n            if (!hasComma && selectItem.getExpr() instanceof SQLVariantRefExpr) {\n                SQLVariantRefExpr sqlVariantRefExpr = (SQLVariantRefExpr) selectItem.getExpr();\n                sqlVariantRefExpr.setHasPrefixComma(false);\n                hasComma = true;\n            }\n            //https://github.com/alibaba/druid/issues/5708\n            if (lexer.hasComment()\n                    && lexer.isKeepComments()\n                    && !lexer.getComments().isEmpty()\n                    && lexer.getComments().get(0).startsWith(\"--\")) {\n                selectItem.addAfterComment(lexer.readAndResetComments());\n            }\n\n            if (lexer.token != Token.COMMA) {\n                if (lexer.token == Token.VARIANT) {\n                    hasComma = false;\n                    continue;\n                } else if (selectItem.getExpr() instanceof SQLVariantRefExpr && ((SQLVariantRefExpr) selectItem.getExpr()).isTemplateParameter() && lexer.token != Token.FROM) {\n                    continue;\n                } else {\n                    break;\n                }\n            }\n\n            int line = lexer.line;\n            lexer.nextToken();\n            if (lexer.hasComment()\n                    && lexer.isKeepComments()\n                    && lexer.getComments().size() == 1\n                    && lexer.getComments().get(0).startsWith(\"--\")\n                    && lexer.line == line + 1) {\n                selectItem.addAfterComment(lexer.readAndResetComments());\n            }\n\n            // https://github.com/alibaba/druid/issues/5140\n            if (lexer.token == Token.FROM || lexer.token == Token.UNION) {\n                if (parseSelectListFromError()) {\n                    throw new ParserException(\"syntax error, expect is not TOKEN:from \" + lexer.info());\n                } else {\n                    break;\n                }\n            }\n            if (lexer.token == Token.RPAREN && dbType == DbType.bigquery) {\n                break;\n            }\n        }\n    }\n\n    protected boolean parseSelectListFromError() {\n        return true;\n    }\n\n    public void parseFrom(SQLSelectQueryBlock queryBlock) {\n        if (!lexer.nextIf(Token.FROM)) {\n            return;\n        }\n        if (lexer.hasComment()) {\n            queryBlock.setCommentsAfterFrom(lexer.readAndResetComments());\n        }\n        queryBlock.setFrom(\n                parseTableSource(true));\n\n    }\n\n    public SQLTableSource parseTableSource() {\n        return parseTableSource(false);\n    }\n    public SQLTableSource parseTableSource(boolean forFrom) {\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            SQLTableSource tableSource;\n            if (lexer.token == Token.SELECT || lexer.token == Token.WITH\n                    || lexer.token == Token.SEL) {\n                SQLSelect select = select();\n                SQLSelectQuery selectQuery = select.getQuery();\n                selectQuery.setParenthesized(true);\n\n                boolean acceptUnion = !(selectQuery instanceof SQLUnionQuery) && dialectFeatureEnabled(AcceptUnion);\n                SQLSelectQuery query = queryRest(selectQuery, acceptUnion);\n                if (query instanceof SQLUnionQuery) {\n                    tableSource = new SQLUnionQueryTableSource((SQLUnionQuery) query);\n                    SQLWithSubqueryClause with = select.getWithSubQuery();\n                    if (with != null) {\n                        ((SQLUnionQuery) query).setWith(with);\n                    }\n                } else {\n                    tableSource = SQLSubqueryTableSource.fixParenthesized(new SQLSubqueryTableSource(select));\n                }\n            } else if (lexer.token == Token.LPAREN) {\n                tableSource = parseTableSource();\n\n                while ((lexer.token == Token.UNION\n                        || lexer.token == Token.EXCEPT\n                        || lexer.token == Token.INTERSECT\n                        || lexer.token == Token.MINUS)) {\n                    if (tableSource instanceof SQLUnionQueryTableSource) {\n                        SQLUnionQueryTableSource unionQueryTableSource = (SQLUnionQueryTableSource) tableSource;\n                        SQLUnionQuery union = unionQueryTableSource.getUnion();\n                        unionQueryTableSource.setUnion(\n                                (SQLUnionQuery) queryRest(union)\n                        );\n                    } else if (tableSource instanceof SQLSubqueryTableSource) {\n                        SQLSelect select = ((SQLSubqueryTableSource) tableSource).getSelect();\n                        if (select != null) {\n                            SQLSelectQuery query = select.getQuery();\n                            SQLSelectQuery queryRest = queryRest(query, true);\n                            select.setQuery(queryRest);\n                        }\n                    } else {\n                        break;\n                    }\n                }\n            } else {\n                tableSource = parseTableSource();\n            }\n            if (lexer.token == Token.RPAREN) {\n                lexer.nextToken();\n            }\n            if (lexer.token == Token.AS) {\n                lexer.nextToken();\n                String alias = this.tableAlias(true);\n                tableSource.setAlias(alias);\n\n                if (tableSource instanceof SQLValuesTableSource\n                        && ((SQLValuesTableSource) tableSource).getColumns().isEmpty()) {\n                    SQLValuesTableSource values = (SQLValuesTableSource) tableSource;\n                    accept(Token.LPAREN);\n                    this.exprParser.names(values.getColumns(), values);\n                    accept(Token.RPAREN);\n                } else if (tableSource instanceof SQLSubqueryTableSource) {\n                    SQLSubqueryTableSource values = (SQLSubqueryTableSource) tableSource;\n                    if (lexer.token == Token.LPAREN) {\n                        lexer.nextToken();\n                        this.exprParser.names(values.getColumns(), values);\n                        accept(Token.RPAREN);\n                    }\n                }\n            }\n\n            return parseTableSourceRest(tableSource);\n        }\n\n        if (lexer.token() == Token.VALUES) {\n            SQLValuesTableSource tableSource = new SQLValuesTableSource();\n            lexer.computeRowAndColumn(tableSource);\n            lexer.nextToken();\n\n            for (; ; ) {\n                accept(Token.LPAREN);\n                SQLListExpr listExpr = new SQLListExpr();\n                this.exprParser.exprList(listExpr.getItems(), listExpr);\n                accept(Token.RPAREN);\n\n                listExpr.setParent(tableSource);\n\n                tableSource.getValues().add(listExpr);\n\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n\n            if (lexer.token == Token.RPAREN || lexer.token == Token.SEMI || lexer.token == Token.EOF) {\n                return tableSource;\n            }\n\n            String alias = this.tableAlias();\n            if (alias != null) {\n                tableSource.setAlias(alias);\n            }\n\n            accept(Token.LPAREN);\n            this.exprParser.names(tableSource.getColumns(), tableSource);\n            accept(Token.RPAREN);\n\n            return parseTableSourceRest(tableSource);\n        }\n\n        if (lexer.token == Token.SELECT) {\n            throw new ParserException(\"unexpected SELECT in table source, subquery must be wrapped in parentheses. \" + lexer.info());\n        }\n\n        SQLTableSource unnestTableSource = parseUnnestTableSource();\n        if (unnestTableSource != null) {\n            return parseTableSourceRest(unnestTableSource);\n        }\n\n        SQLTableSource generatedTableSource = parseGeneratedTableSource();\n        if (generatedTableSource != null) {\n            return parseTableSourceRest(generatedTableSource);\n        }\n\n        SQLExprTableSource tableReference = getTableSource();\n\n        parseTableSourceQueryTableExpr(tableReference);\n\n        SQLTableSource tableSrc = parseTableSourceRest(tableReference);\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            tableSrc.addAfterComment(lexer.readAndResetComments());\n        }\n\n        return tableSrc;\n    }\n\n    protected SQLExprTableSource getTableSource() {\n        return new SQLExprTableSource();\n    }\n\n    protected void parseTableSourceQueryTableExpr(SQLExprTableSource tableReference) {\n        if (lexer.token == Token.LITERAL_ALIAS || lexer.identifierEquals(FnvHash.Constants.IDENTIFIED)\n                || lexer.token == Token.LITERAL_CHARS) {\n            tableReference.setExpr(this.exprParser.name());\n            return;\n        }\n\n        if (lexer.token == Token.HINT) {\n            SQLCommentHint hint = this.exprParser.parseHint();\n            tableReference.setHint(hint);\n        }\n\n        SQLExpr expr;\n        switch (lexer.token) {\n            case ALL:\n            case SET:\n                expr = this.exprParser.name();\n                break;\n            default:\n                expr = exprParser.expr();\n                break;\n        }\n\n        if (expr instanceof SQLBinaryOpExpr) {\n            throw new ParserException(\"Invalid from clause : \" + expr.toString().replace(\"\\n\", \" \"));\n        }\n\n        tableReference.setExpr(expr);\n    }\n\n    protected SQLTableSource parseLateralTableSource() {\n        if (lexer.token == Token.LPAREN) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token == Token.SELECT || lexer.token == Token.WITH || lexer.token == Token.VALUES) {\n                SQLSelect select = select();\n                accept(Token.RPAREN);\n                SQLSubqueryTableSource subquery = new SQLSubqueryTableSource(select);\n                subquery.setLateral(true);\n                String alias = tableAlias();\n                if (alias != null) {\n                    subquery.setAlias(alias);\n                }\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n                    this.exprParser.names(subquery.getColumns(), subquery);\n                    accept(Token.RPAREN);\n                }\n                return subquery;\n            } else {\n                lexer.reset(mark);\n                SQLExpr funcExpr = this.exprParser.expr();\n                SQLExprTableSource funcTableSource = new SQLExprTableSource(funcExpr);\n                funcTableSource.setLateral(true);\n                String alias = tableAlias();\n                if (alias != null) {\n                    funcTableSource.setAlias(alias);\n                }\n                return funcTableSource;\n            }\n        } else {\n            SQLExpr funcExpr = this.exprParser.expr();\n            SQLExprTableSource funcTableSource = new SQLExprTableSource(funcExpr);\n            funcTableSource.setLateral(true);\n            String alias = tableAlias();\n            if (alias != null) {\n                funcTableSource.setAlias(alias);\n            }\n            return funcTableSource;\n        }\n    }\n\n    protected SQLTableSource parseUnnestTableSource() {\n        if (lexer.identifierEquals(FnvHash.Constants.UNNEST)) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n\n            if (lexer.nextIf(Token.LPAREN)) {\n                SQLUnnestTableSource unnest = new SQLUnnestTableSource();\n                this.exprParser.exprList(unnest.getItems(), unnest);\n                accept(Token.RPAREN);\n\n                if (lexer.nextIf(Token.WITH)) {\n                    acceptIdentifier(\"ORDINALITY\");\n                    unnest.setOrdinality(true);\n                }\n\n                String alias = this.tableAlias();\n                unnest.setAlias(alias);\n\n                if (lexer.nextIf(Token.LPAREN)) {\n                    this.exprParser.names(unnest.getColumns(), unnest);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.nextIf(Token.WITH)) {\n                    acceptIdentifier(\"OFFSET\");\n                    lexer.nextIf(Token.AS);\n                    unnest.setOffset(\n                            this.exprParser.expr()\n                    );\n                }\n                return unnest;\n            } else {\n                lexer.reset(mark);\n            }\n        }\n        return null;\n    }\n\n    protected SQLTableSource parseGeneratedTableSource() {\n        for (String returningFunction : getReturningFunctions()) {\n            if (lexer.identifierEquals(returningFunction)) {\n                Lexer.SavePoint mark = lexer.mark();\n                SQLIdentifierExpr methodName = new SQLIdentifierExpr(returningFunction);\n                lexer.nextToken();\n\n                if (lexer.nextIf(Token.LPAREN)) {\n                    SQLGeneratedTableSource generated = new SQLGeneratedTableSource();\n                    generated.setMethodName(methodName);\n                    this.exprParser.exprList(generated.getItems(), generated);\n                    accept(Token.RPAREN);\n\n                    String alias = this.tableAlias();\n                    generated.setAlias(alias);\n\n                    if (lexer.nextIf(Token.LPAREN)) {\n                        this.exprParser.names(generated.getColumns(), generated);\n                        accept(Token.RPAREN);\n                    }\n                    return generated;\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n        }\n        return null;\n    }\n\n    protected List<String> getReturningFunctions() {\n        return Collections.singletonList(\"GENERATE_SERIES\");\n    }\n\n    protected SQLTableSource primaryTableSourceRest(SQLTableSource tableSource) {\n        return tableSource;\n    }\n\n    public void parseTableSourceSample(SQLTableSource tableSource) {\n    }\n\n    public void parseTableSourceSampleHive(SQLTableSource tableSource) {\n        if (lexer.identifierEquals(FnvHash.Constants.TABLESAMPLE) && tableSource instanceof SQLExprTableSource) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token() == Token.LPAREN) {\n                lexer.nextToken();\n\n                SQLTableSampling sampling = new SQLTableSampling();\n\n                if (lexer.identifierEquals(FnvHash.Constants.BUCKET)) {\n                    lexer.nextToken();\n                    SQLExpr bucket = this.exprParser.primary();\n                    sampling.setBucket(bucket);\n\n                    if (lexer.token() == Token.OUT) {\n                        lexer.nextToken();\n                        accept(Token.OF);\n                        SQLExpr outOf = this.exprParser.primary();\n                        sampling.setOutOf(outOf);\n                    }\n\n                    if (lexer.token() == Token.ON) {\n                        lexer.nextToken();\n                        SQLExpr on = this.exprParser.expr();\n                        sampling.setOn(on);\n                    }\n                }\n\n                if (lexer.token() == Token.LITERAL_INT || lexer.token() == Token.LITERAL_FLOAT) {\n                    SQLExpr val = this.exprParser.primary();\n\n                    if (lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                        lexer.nextToken();\n                        sampling.setRows(val);\n                    } else {\n                        acceptIdentifier(\"PERCENT\");\n                        sampling.setPercent(val);\n                    }\n                }\n\n                if (lexer.token() == Token.IDENTIFIER) {\n                    String strVal = lexer.stringVal();\n                    char first = strVal.charAt(0);\n                    char last = strVal.charAt(strVal.length() - 1);\n                    if (last >= 'a' && last <= 'z') {\n                        last -= 32; // to upper\n                    }\n\n                    boolean match = false;\n                    if ((first == '.' || (first >= '0' && first <= '9'))) {\n                        switch (last) {\n                            case 'B':\n                            case 'K':\n                            case 'M':\n                            case 'G':\n                            case 'T':\n                            case 'P':\n                                match = true;\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n                    SQLSizeExpr size = new SQLSizeExpr(strVal.substring(0, strVal.length() - 2), last);\n                    sampling.setByteLength(size);\n                    lexer.nextToken();\n                }\n\n                final SQLExprTableSource table = (SQLExprTableSource) tableSource;\n                table.setSampling(sampling);\n\n                accept(Token.RPAREN);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n    }\n    protected void parseJoinHint(SQLJoinTableSource join){}\n\n    public SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {\n        parseTableSourceSample(tableSource);\n        if (lexer.hasComment()\n                && lexer.isKeepComments()\n                && !(tableSource instanceof SQLSubqueryTableSource)) {\n            tableSource.addAfterComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token == Token.HINT && dbType == DbType.odps) {\n            List<SQLCommentHint> hints = this.exprParser.parseHints();\n            for (SQLCommentHint hint : hints) {\n                tableSource.addAfterComment(hint.getText());\n            }\n        }\n\n        if (tableSource.getAlias() == null || tableSource.getAlias().length() == 0) {\n            Token token = lexer.token;\n            long hash;\n            switch (token) {\n                case LEFT:\n                case RIGHT:\n                case FULL: {\n                    Lexer.SavePoint mark = lexer.mark();\n                    String strVal = lexer.stringVal();\n                    lexer.nextToken();\n                    if (lexer.token == Token.OUTER\n                            || lexer.token == Token.JOIN\n                            || lexer.identifierEquals(FnvHash.Constants.ANTI)\n                            || lexer.identifierEquals(FnvHash.Constants.ARRAY)\n                            || lexer.identifierEquals(FnvHash.Constants.SEMI)) {\n                        lexer.reset(mark);\n                    } else {\n                        tableSource.setAlias(strVal);\n                    }\n                }\n                break;\n                case OUTER:\n                    break;\n                default:\n                    if (identifierEquals(\"ARRAY\")) {\n                        Lexer.SavePoint mark = lexer.mark();\n                        String strVal = lexer.stringVal();\n                        lexer.nextToken();\n                        if (lexer.token == Token.JOIN) {\n                            lexer.reset(mark);\n                        } else {\n                            tableSource.setAlias(strVal);\n                        }\n                        break;\n                    }\n                    if (identifierEquals(\"PIVOT\") || identifierEquals(\"UNPIVOT\")) {\n                        parsePivot(tableSource);\n                    } else if (!(token == Token.IDENTIFIER\n                            && ((hash = lexer.hashLCase()) == FnvHash.Constants.STRAIGHT_JOIN\n                            || hash == FnvHash.Constants.CROSS))) {\n                        boolean must = false;\n                        if (lexer.token == Token.AS) {\n                            lexer.nextToken();\n                            must = true;\n                        }\n                        String alias = tableAlias(must);\n                        if (alias != null) {\n                            if (isEnabled(SQLParserFeature.IgnoreNameQuotes) && alias.length() > 1) {\n                                alias = StringUtils.removeNameQuotes(alias);\n                            }\n                            tableSource.setAlias(alias);\n\n                            if (lexer.token == Token.HINT) {\n                                tableSource.addAfterComment(\"/*\" + lexer.stringVal + \"*/\");\n                                lexer.nextToken();\n                            }\n\n                            if ((tableSource instanceof SQLValuesTableSource)\n                                    && ((SQLValuesTableSource) tableSource).getColumns().isEmpty()) {\n                                SQLValuesTableSource values = (SQLValuesTableSource) tableSource;\n                                accept(Token.LPAREN);\n                                this.exprParser.names(values.getColumns(), values);\n                                accept(Token.RPAREN);\n                            } else if (tableSource instanceof SQLSubqueryTableSource) {\n                                SQLSubqueryTableSource subQuery = (SQLSubqueryTableSource) tableSource;\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextToken();\n                                    this.exprParser.names(subQuery.getColumns(), subQuery);\n                                    accept(Token.RPAREN);\n                                }\n                            } else if (tableSource instanceof SQLUnionQueryTableSource) {\n                                SQLUnionQueryTableSource union = (SQLUnionQueryTableSource) tableSource;\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextToken();\n                                    this.exprParser.names(union.getColumns(), union);\n                                    accept(Token.RPAREN);\n                                }\n                            } else if (lexer.token == Token.LPAREN\n                                    && tableSource instanceof SQLExprTableSource\n                                    && (((SQLExprTableSource) tableSource).getExpr() instanceof SQLVariantRefExpr\n                                    || ((SQLExprTableSource) tableSource).getExpr() instanceof SQLIdentifierExpr\n                            )\n                            ) {\n                                lexer.nextToken();\n                                SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;\n                                this.exprParser.names(exprTableSource.getColumns(), exprTableSource);\n                                accept(Token.RPAREN);\n                            }\n\n                            if (lexer.token == Token.WHERE) {\n                                return tableSource;\n                            }\n\n                            return parseTableSourceRest(tableSource);\n                        }\n                    }\n                    break;\n            }\n\n        } else if (identifierEquals(\"PIVOT\") || identifierEquals(\"UNPIVOT\")) {\n            parsePivot(tableSource);\n        }\n\n        SQLJoinTableSource.JoinType joinType = null;\n\n        boolean natural = lexer.identifierEquals(FnvHash.Constants.NATURAL);\n        if (natural) {\n            lexer.nextToken();\n        }\n\n        boolean asof = false;\n        if (lexer.identifierEquals(FnvHash.Constants.ASOF) && dialectFeatureEnabled(AsofJoin)) {\n            lexer.nextToken();\n            asof = true;\n        }\n\n        if (lexer.token == Token.OUTER) {\n            Lexer.SavePoint mark = lexer.mark();\n            String str = lexer.stringVal();\n            lexer.nextToken();\n            if (tableSource.getAlias() == null &&\n                    !lexer.identifierEquals(FnvHash.Constants.APPLY)) {\n                tableSource.setAlias(str);\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        boolean global = false;\n        if (dialectFeatureEnabled(GlobalJoin)) {\n            if (lexer.token == Token.GLOBAL) {\n                lexer.nextToken();\n                global = true;\n            }\n        }\n        if (identifierEquals(\"ARRAY\")) {\n            lexer.nextToken();\n            accept(Token.JOIN);\n            joinType = SQLJoinTableSource.JoinType.ARRAY_JOIN;\n        }\n        switch (lexer.token) {\n            case LEFT:\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(FnvHash.Constants.SEMI)) {\n                    lexer.nextToken();\n                    joinType = SQLJoinTableSource.JoinType.LEFT_SEMI_JOIN;\n                } else if (lexer.identifierEquals(FnvHash.Constants.ANTI)) {\n                    lexer.nextToken();\n                    joinType = SQLJoinTableSource.JoinType.LEFT_ANTI_JOIN;\n                } else if (lexer.identifierEquals(FnvHash.Constants.ARRAY)) {\n                    lexer.nextToken();\n                    joinType = SQLJoinTableSource.JoinType.LEFT_ARRAY_JOIN;\n                } else if (lexer.token == Token.OUTER) {\n                    lexer.nextToken();\n                    joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_LEFT_JOIN : SQLJoinTableSource.JoinType.LEFT_OUTER_JOIN;\n                } else {\n                    joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_LEFT_JOIN : SQLJoinTableSource.JoinType.LEFT_OUTER_JOIN;\n                }\n\n                if (dialectFeatureEnabled(JoinAt) && lexer.token == Token.IDENTIFIER && lexer.stringVal().startsWith(\"join@\")) {\n                    lexer.stringVal = lexer.stringVal().substring(5);\n                    break;\n                }\n\n                accept(Token.JOIN);\n                break;\n            case RIGHT:\n                lexer.nextToken();\n                if (lexer.token == Token.OUTER) {\n                    lexer.nextToken();\n                }\n                accept(Token.JOIN);\n                joinType = SQLJoinTableSource.JoinType.RIGHT_OUTER_JOIN;\n                break;\n            case FULL:\n                lexer.nextToken();\n                if (lexer.token == Token.OUTER) {\n                    lexer.nextToken();\n                }\n                accept(Token.JOIN);\n                joinType = SQLJoinTableSource.JoinType.FULL_OUTER_JOIN;\n                break;\n            case INNER:\n                lexer.nextToken();\n                accept(Token.JOIN);\n                joinType = SQLJoinTableSource.JoinType.INNER_JOIN;\n                break;\n            case JOIN:\n                lexer.nextIf(Token.JOIN);\n                joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_JOIN : SQLJoinTableSource.JoinType.JOIN;\n                break;\n            case COMMA:\n                lexer.nextToken();\n                joinType = SQLJoinTableSource.JoinType.COMMA;\n                break;\n            case OUTER:\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.APPLY)) {\n                    lexer.nextToken();\n                    joinType = SQLJoinTableSource.JoinType.OUTER_APPLY;\n                }\n                break;\n            case CROSS:\n                lexer.nextToken();\n                accept(Token.JOIN);\n                joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_CROSS_JOIN : SQLJoinTableSource.JoinType.CROSS_JOIN;\n                break;\n            case STRAIGHT_JOIN:\n            case IDENTIFIER:\n                final long hash = lexer.hashLCase;\n                if (hash == FnvHash.Constants.STRAIGHT_JOIN) {\n                    lexer.nextToken();\n                    joinType = SQLJoinTableSource.JoinType.STRAIGHT_JOIN;\n                } else if (hash == FnvHash.Constants.STRAIGHT) {\n                    lexer.nextToken();\n                    accept(Token.JOIN);\n                    joinType = SQLJoinTableSource.JoinType.STRAIGHT_JOIN;\n                } else if (hash == FnvHash.Constants.CROSS) {\n                    lexer.nextToken();\n                    if (lexer.token == Token.JOIN) {\n                        lexer.nextToken();\n                        joinType = natural ? SQLJoinTableSource.JoinType.NATURAL_CROSS_JOIN : SQLJoinTableSource.JoinType.CROSS_JOIN;\n                    } else if (lexer.identifierEquals(FnvHash.Constants.APPLY)) {\n                        lexer.nextToken();\n                        joinType = SQLJoinTableSource.JoinType.CROSS_APPLY;\n                    }\n                }\n                break;\n            default:\n                break;\n        }\n\n        if (joinType != null) {\n            SQLJoinTableSource join = new SQLJoinTableSource();\n            join.setLeft(tableSource);\n            join.setJoinType(joinType);\n            join.setGlobal(global);\n            if (asof) {\n                join.setAsof(true);\n            }\n\n            boolean isBrace = false;\n            if (SQLJoinTableSource.JoinType.COMMA == joinType) {\n                if (lexer.token == Token.LBRACE) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"OJ\");\n                    isBrace = true;\n                }\n            }\n\n            parseJoinHint(join);\n\n            SQLTableSource rightTableSource = null;\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                if (lexer.token == Token.SELECT\n                        || (lexer.token == Token.WITH && dialectFeatureEnabled(JoinRightTableWith))\n                        || (lexer.token == Token.FROM && dialectFeatureEnabled(JoinRightTableFrom))) {\n                    SQLSelect select = this.select();\n                    rightTableSource = SQLSubqueryTableSource.fixParenthesized(new SQLSubqueryTableSource(select));\n                } else {\n                    rightTableSource = this.parseTableSource();\n                    if (rightTableSource instanceof SQLExprTableSource) {\n                        SQLExprTableSource sqlExprTableSource = (SQLExprTableSource) rightTableSource;\n                        if (sqlExprTableSource.getExpr() instanceof SQLQueryExpr) {\n                            SQLQueryExpr expr = (SQLQueryExpr) sqlExprTableSource.getExpr();\n                            expr.setParenthesized(true);\n                        }\n                    }\n                }\n                if (lexer.token == Token.UNION\n                        || lexer.token == Token.EXCEPT\n                        || lexer.token == Token.MINUS\n                        || lexer.token == Token.INTERSECT) {\n                    if (rightTableSource instanceof SQLSubqueryTableSource) {\n                        SQLSelect select = ((SQLSubqueryTableSource) rightTableSource).getSelect();\n                        SQLSelectQuery query = queryRest(select.getQuery(), true);\n                        select.setQuery(query);\n                    } else if (rightTableSource instanceof SQLUnionQueryTableSource) {\n                        SQLUnionQueryTableSource unionTableSrc = (SQLUnionQueryTableSource) rightTableSource;\n                        unionTableSrc.setUnion((SQLUnionQuery)\n                                queryRest(\n                                        unionTableSrc.getUnion()\n                                )\n                        );\n                    }\n                }\n\n                accept(Token.RPAREN);\n\n                if (rightTableSource instanceof SQLValuesTableSource\n                        && (lexer.token == Token.AS || lexer.token == Token.IDENTIFIER)\n                        && rightTableSource.getAlias() == null\n                        && ((SQLValuesTableSource) rightTableSource).getColumns().isEmpty()\n                ) {\n                    if (lexer.token == Token.AS) {\n                        lexer.nextToken();\n                    }\n                    rightTableSource.setAlias(tableAlias(true));\n\n                    if (lexer.token == Token.LPAREN) {\n                        lexer.nextToken();\n                        this.exprParser.names(((SQLValuesTableSource) rightTableSource).getColumns(), rightTableSource);\n                        accept(Token.RPAREN);\n                    }\n                }\n            } else {\n                if (lexer.token == Token.LATERAL || lexer.identifierEquals(FnvHash.Constants.LATERAL)) {\n                    lexer.nextToken();\n                    rightTableSource = parseLateralTableSource();\n                } else if (lexer.token == Token.VALUES) {\n                    rightTableSource = this.parseValues();\n                } else {\n                    SQLTableSource unnestTableSource = parseUnnestTableSource();\n                    if (unnestTableSource != null) {\n                        if (lexer.identifierEquals(FnvHash.Constants.CROSS)\n                                || lexer.token == Token.CROSS\n                                || lexer.token == Token.LEFT\n                                || lexer.token == Token.RIGHT\n                                || lexer.token == Token.COMMA\n                                || lexer.token == Token.INNER\n                                || lexer.token == Token.JOIN\n                                || lexer.token == Token.FULL\n                        ) {\n                            rightTableSource = unnestTableSource;\n                        } else {\n                            rightTableSource = parseTableSourceRest(unnestTableSource);\n                        }\n                    }\n                }\n\n                if (rightTableSource == null) {\n                    boolean aliasToken = lexer.token == Token.LITERAL_ALIAS;\n                    SQLExpr expr;\n                    switch (lexer.token) {\n                        case ALL:\n                        case LITERAL_CHARS:\n                        case LITERAL_ALIAS:\n                            expr = this.exprParser.name();\n                            break;\n                        default:\n                            expr = this.expr();\n                            break;\n                    }\n\n                    if (aliasToken && expr instanceof SQLCharExpr) {\n                        expr = new SQLIdentifierExpr(((SQLCharExpr) expr).getText());\n                    }\n                    SQLExprTableSource exprTableSource = new SQLExprTableSource(expr);\n\n                    if (expr instanceof SQLMethodInvokeExpr && lexer.token == Token.AS) {\n                        lexer.nextToken();\n                        String alias = this.tableAlias(true);\n                        exprTableSource.setAlias(alias);\n\n                        if (lexer.token == Token.LPAREN) {\n                            lexer.nextToken();\n\n                            this.exprParser.names(exprTableSource.getColumns(), exprTableSource);\n                            accept(Token.RPAREN);\n                        }\n                    }\n\n                    rightTableSource = exprTableSource;\n                }\n                rightTableSource = primaryTableSourceRest(rightTableSource);\n            }\n\n            if (lexer.token == Token.USING\n                    || lexer.identifierEquals(FnvHash.Constants.USING)) {\n                Lexer.SavePoint savePoint = lexer.mark();\n                lexer.nextToken();\n\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n                    join.setRight(rightTableSource);\n                    this.exprParser.exprList(join.getUsing(), join);\n                    accept(Token.RPAREN);\n                } else if (lexer.token == Token.IDENTIFIER) {\n                    if (JoinType.COMMA.equals(joinType)) {\n                        lexer.reset(savePoint);\n                        join.setRight(rightTableSource);\n                        return join;\n                    } else {\n                        join.setRight(rightTableSource);\n                        this.exprParser.exprList(join.getUsing(), join);\n                        }\n                } else {\n                    join.setAlias(this.tableAlias());\n                }\n            } else if (lexer.token == Token.STRAIGHT_JOIN || lexer.identifierEquals(FnvHash.Constants.STRAIGHT_JOIN)) {\n                primaryTableSourceRest(rightTableSource);\n\n            } else if (rightTableSource.getAlias() == null && !(rightTableSource instanceof SQLValuesTableSource)) {\n                int line = lexer.line;\n                String tableAlias;\n                if (lexer.token == Token.AS) {\n                    lexer.nextToken();\n\n                    if (lexer.token != Token.ON) {\n                        if (dialectFeatureEnabled(JoinRightTableAlias) && rightTableSource instanceof SQLExprTableSource) {\n                            SQLExprTableSource exprTableSource = (SQLExprTableSource) rightTableSource;\n                            exprTableSource.setNeedAsTokenForAlias(true);\n                        }\n                        tableAlias = this.tableAlias(true);\n                    } else {\n                        tableAlias = null;\n                    }\n                } else {\n                    tableAlias = this.tableAlias(false);\n                }\n\n                if (tableAlias != null) {\n                    rightTableSource.setAlias(tableAlias);\n\n                    if (line + 1 == lexer.line\n                            && lexer.hasComment()\n                            && lexer.getComments().get(0).startsWith(\"--\")) {\n                        rightTableSource.addAfterComment(lexer.readAndResetComments());\n                    }\n\n                    if (lexer.token == Token.LPAREN) {\n                        if (rightTableSource instanceof SQLSubqueryTableSource) {\n                            lexer.nextToken();\n                            List<SQLName> columns = ((SQLSubqueryTableSource) rightTableSource).getColumns();\n                            this.exprParser.names(columns, rightTableSource);\n                            accept(Token.RPAREN);\n                        } else if (rightTableSource instanceof SQLExprTableSource\n                                && ((SQLExprTableSource) rightTableSource).getExpr() instanceof SQLMethodInvokeExpr) {\n                            List<SQLName> columns = ((SQLExprTableSource) rightTableSource).getColumns();\n                            if (columns.isEmpty()) {\n                                lexer.nextToken();\n                                this.exprParser.names(columns, rightTableSource);\n                                accept(Token.RPAREN);\n                            }\n                        }\n                    }\n                }\n\n                rightTableSource = primaryTableSourceRest(rightTableSource);\n            }\n\n            if (lexer.token == Token.WITH) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n\n                for (; ; ) {\n                    SQLExpr hintExpr = this.expr();\n                    SQLExprHint hint = new SQLExprHint(hintExpr);\n                    hint.setParent(tableSource);\n                    rightTableSource.getHints().add(hint);\n                    if (lexer.token == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    } else {\n                        break;\n                    }\n                }\n\n                accept(Token.RPAREN);\n            }\n\n            join.setRight(rightTableSource);\n\n            if (!natural) {\n                if (!StringUtils.isEmpty(tableSource.getAlias())\n                        && tableSource.aliasHashCode64() == FnvHash.Constants.NATURAL && dialectFeatureEnabled(\n                        PostNaturalJoin)) {\n                    tableSource.setAlias(null);\n                    natural = true;\n                    if (natural && join.getJoinType() == SQLJoinTableSource.JoinType.LEFT_OUTER_JOIN) {\n                        join.setJoinType(SQLJoinTableSource.JoinType.NATURAL_LEFT_JOIN);\n                    }\n                    if (natural && join.getJoinType() == JoinType.RIGHT_OUTER_JOIN) {\n                        join.setJoinType(SQLJoinTableSource.JoinType.NATURAL_RIGHT_JOIN);\n                    }\n                    if (natural && join.getJoinType() == JoinType.INNER_JOIN) {\n                        join.setJoinType(SQLJoinTableSource.JoinType.NATURAL_INNER_JOIN);\n                    }\n                }\n            }\n            join.setNatural(natural);\n\n            if (lexer.token == Token.ON) {\n                lexer.nextToken();\n                SQLExpr joinOn = expr();\n                join.setCondition(joinOn);\n\n                while (lexer.token == Token.ON\n                        && dialectFeatureEnabled(MultipleJoinOn)) {\n                    lexer.nextToken();\n\n                    SQLExpr joinOn2 = expr();\n                    join.addCondition(joinOn2);\n                }\n\n                if (dialectFeatureEnabled(UserDefinedJoin) && lexer.identifierEquals(FnvHash.Constants.USING)) {\n                    SQLJoinTableSource.UDJ udj = new SQLJoinTableSource.UDJ();\n                    lexer.nextToken();\n                    udj.setFunction(this.exprParser.name());\n                    accept(Token.LPAREN);\n                    this.exprParser.exprList(udj.getArguments(), udj);\n                    accept(Token.RPAREN);\n\n                    if (lexer.token != Token.AS) {\n                        udj.setAlias(alias());\n                    }\n\n                    accept(Token.AS);\n                    accept(Token.LPAREN);\n                    this.exprParser.names(udj.getColumns(), udj);\n                    accept(Token.RPAREN);\n\n                    if (lexer.identifierEquals(FnvHash.Constants.SORT)) {\n                        lexer.nextToken();\n                        accept(Token.BY);\n                        this.exprParser.orderBy(udj.getSortBy(), udj);\n                    }\n\n                    if (lexer.token == Token.WITH) {\n                        lexer.nextToken();\n                        acceptIdentifier(\"UDFPROPERTIES\");\n                        this.exprParser.parseAssignItem(udj.getProperties(), udj);\n                    }\n\n                    join.setUdj(udj);\n                }\n            } else if (lexer.token == Token.USING\n                    || lexer.identifierEquals(FnvHash.Constants.USING)) {\n                Lexer.SavePoint savePoint = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n                    this.exprParser.exprList(join.getUsing(), join);\n                    accept(Token.RPAREN);\n                } else {\n                    lexer.reset(savePoint);\n                }\n            }\n            SQLTableSource tableSourceReturn = parseTableSourceRest(join);\n\n            if (isBrace) {\n                accept(Token.RBRACE);\n            }\n\n            return parseTableSourceRest(tableSourceReturn);\n        }\n\n        if ((tableSource.aliasHashCode64() == FnvHash.Constants.LATERAL || lexer.token == Token.LATERAL)\n                && lexer.token() == Token.VIEW) {\n            return parseLateralView(tableSource);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.LATERAL) || lexer.token == Token.LATERAL) {\n            lexer.nextToken();\n            return parseLateralView(tableSource);\n        }\n\n        parseAfterTableSourceRest(tableSource);\n        return tableSource;\n    }\n\n    public void parseAfterTableSourceRest(SQLTableSource tableSource) {}\n\n    public SQLExpr expr() {\n        return this.exprParser.expr();\n    }\n\n    public SQLOrderBy parseOrderBy() {\n        return this.exprParser.parseOrderBy();\n    }\n\n    public void acceptKeyword(String ident) {\n        if (lexer.token == Token.IDENTIFIER && ident.equalsIgnoreCase(lexer.stringVal())) {\n            lexer.nextToken();\n        } else {\n            setErrorEndPos(lexer.pos());\n            throw new ParserException(\"syntax error, expect \" + ident + \", actual \" + lexer.token + \", \" + lexer.info());\n        }\n    }\n\n    public void parseFetchClause(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token == Token.LIMIT) {\n            SQLLimit limit = this.exprParser.parseLimit();\n            queryBlock.setLimit(limit);\n            afterParseLimitClause(queryBlock);\n            afterParseFetchClause(queryBlock);\n            return;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.OFFSET) || lexer.token == Token.OFFSET) {\n            lexer.nextToken();\n            SQLExpr offset = this.exprParser.expr();\n            queryBlock.setOffset(offset);\n            if (lexer.identifierEquals(FnvHash.Constants.ROW) || lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                lexer.nextToken();\n            }\n        }\n\n        if (lexer.token == Token.FETCH) {\n            lexer.nextToken();\n            if (lexer.token == Token.FIRST\n                    || lexer.token == Token.NEXT\n                    || lexer.identifierEquals(FnvHash.Constants.NEXT)) {\n                lexer.nextToken();\n            } else {\n                acceptIdentifier(\"FIRST\");\n            }\n            SQLExpr first = this.exprParser.primary();\n            queryBlock.setFirst(first);\n            if (lexer.identifierEquals(FnvHash.Constants.ROW) || lexer.identifierEquals(FnvHash.Constants.ROWS)) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token == Token.ONLY) {\n                lexer.nextToken();\n            } else {\n                acceptIdentifier(\"ONLY\");\n            }\n        }\n        afterParseFetchClause(queryBlock);\n    }\n\n    protected void parseHierachical(SQLSelectQueryBlock queryBlock) {\n        if (lexer.token == Token.CONNECT || lexer.identifierEquals(FnvHash.Constants.CONNECT)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            if (lexer.token == Token.PRIOR || lexer.identifierEquals(FnvHash.Constants.PRIOR)) {\n                lexer.nextToken();\n                queryBlock.setPrior(true);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.NOCYCLE)) {\n                queryBlock.setNoCycle(true);\n                lexer.nextToken();\n\n                if (lexer.token == Token.PRIOR) {\n                    lexer.nextToken();\n                    queryBlock.setPrior(true);\n                }\n            }\n            queryBlock.setConnectBy(this.exprParser.expr());\n        }\n\n        if (lexer.token == Token.START || lexer.identifierEquals(FnvHash.Constants.START)) {\n            lexer.nextToken();\n            accept(Token.WITH);\n\n            queryBlock.setStartWith(this.exprParser.expr());\n        }\n\n        if (lexer.token == Token.CONNECT || lexer.identifierEquals(FnvHash.Constants.CONNECT)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            if (lexer.token == Token.PRIOR || lexer.identifierEquals(FnvHash.Constants.PRIOR)) {\n                lexer.nextToken();\n                queryBlock.setPrior(true);\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.NOCYCLE)) {\n                queryBlock.setNoCycle(true);\n                lexer.nextToken();\n\n                if (lexer.token == Token.PRIOR || lexer.identifierEquals(FnvHash.Constants.PRIOR)) {\n                    lexer.nextToken();\n                    queryBlock.setPrior(true);\n                }\n            }\n            queryBlock.setConnectBy(this.exprParser.expr());\n        }\n    }\n\n    protected SQLTableSource parseLateralView(SQLTableSource tableSource) {\n        accept(Token.VIEW);\n        if (tableSource != null && \"LATERAL\".equalsIgnoreCase(tableSource.getAlias())) {\n            tableSource.setAlias(null);\n        }\n        SQLLateralViewTableSource lateralViewTabSrc = new SQLLateralViewTableSource();\n        lateralViewTabSrc.setTableSource(tableSource);\n\n        if (lexer.token == Token.OUTER) {\n            lateralViewTabSrc.setOuter(true);\n            lexer.nextToken();\n        }\n\n        SQLMethodInvokeExpr udtf = (SQLMethodInvokeExpr) this.exprParser.primary();\n        lateralViewTabSrc.setMethod(udtf);\n\n        String alias = null;\n        if (lexer.token != Token.AS) {\n            alias = alias();\n        }\n        if (alias != null) {\n            lateralViewTabSrc.setAlias(alias);\n        }\n\n        if (lexer.token == Token.AS) {\n            parseLateralViewAs(lateralViewTabSrc);\n        }\n\n        if (lexer.token == Token.ON) {\n            lexer.nextToken();\n            lateralViewTabSrc.setOn(\n                    this.exprParser.expr()\n            );\n        }\n\n        return parseTableSourceRest(lateralViewTabSrc);\n    }\n\n    public void parseLateralViewAs(SQLLateralViewTableSource lateralViewTabSrc) {\n        accept(Token.AS);\n\n        Lexer.SavePoint mark = null;\n        for (; ; ) {\n            SQLName name;\n            if (lexer.token == Token.NULL) {\n                name = new SQLIdentifierExpr(lexer.stringVal());\n                lexer.nextToken();\n            } else {\n                name = this.exprParser.name();\n                if (name instanceof SQLPropertyExpr) {\n                    lexer.reset(mark);\n                    break;\n                }\n            }\n            name.setParent(lateralViewTabSrc);\n            lateralViewTabSrc.getColumns().add(name);\n            if (lexer.token == Token.COMMA) {\n                mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token != Token.LPAREN) {\n                    continue;\n                }\n                lexer.reset(mark);\n            }\n            break;\n        }\n    }\n\n    public SQLValuesTableSource parseValues() {\n        SQLValuesTableSource tableSource = new SQLValuesTableSource();\n        lexer.computeRowAndColumn(tableSource);\n        accept(Token.VALUES);\n\n        for (; ; ) {\n            // compatible (VALUES 1,2,3) and (VALUES (1), (2), (3)) for ads\n            boolean isSingleValue = true;\n            if (lexer.token == Token.ROW) {\n                lexer.nextToken();\n            }\n            if (lexer.token() == Token.LPAREN) {\n                accept(Token.LPAREN);\n                isSingleValue = false;\n            }\n\n            SQLListExpr listExpr = new SQLListExpr();\n\n            if (isSingleValue) {\n                SQLExpr expr = expr();\n                expr.setParent(listExpr);\n                listExpr.getItems().add(expr);\n            } else {\n                this.exprParser.exprList(listExpr.getItems(), listExpr);\n                accept(Token.RPAREN);\n            }\n\n            listExpr.setParent(tableSource);\n\n            tableSource.getValues().add(listExpr);\n\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        String alias = this.tableAlias();\n        if (alias != null) {\n            tableSource.setAlias(alias);\n        }\n\n        if (lexer.token() == Token.LPAREN) {\n            lexer.nextToken();\n            this.exprParser.names(tableSource.getColumns(), tableSource);\n            accept(Token.RPAREN);\n        }\n\n        return tableSource;\n    }\n\n    protected void parsePivotIn(SQLObjectImpl parent, List<SQLSelectItem> items) {\n        for (; ; ) {\n            SQLSelectItem item = new SQLSelectItem();\n            SQLExpr expr = this.exprParser.expr();\n            if (expr instanceof SQLIdentifierExpr) {\n                String name = ((SQLIdentifierExpr) expr).getName();\n                if (name.length() > 1 && SQLUtils.isQuoteChar(name.charAt(0)) && name.charAt(name.length() - 1) == name.charAt(0)) {\n                    expr = new SQLCharExpr(SQLUtils.removeQuote(name));\n                }\n            }\n            item.setExpr(expr);\n            item.setAlias(as());\n            item.setParent(parent);\n            items.add(item);\n            if (lexer.token() != Token.COMMA) {\n                break;\n            }\n            lexer.nextToken();\n        }\n    }\n    protected void parsePivot(SQLTableSource tableSource) {\n        SQLSelectItem item;\n        if (lexer.identifierEquals(FnvHash.Constants.PIVOT)) {\n            lexer.nextToken();\n\n            SQLPivot pivot = new SQLPivot();\n\n            if (lexer.identifierEquals(\"XML\")) {\n                lexer.nextToken();\n                pivot.setXml(true);\n            }\n\n            accept(Token.LPAREN);\n            while (true) {\n                item = new SQLSelectItem();\n                item.setExpr(this.exprParser.expr());\n                item.setAlias(as());\n                pivot.addItem(item);\n\n                if (!(lexer.token() == (Token.COMMA))) {\n                    break;\n                }\n                lexer.nextToken();\n            }\n\n            accept(Token.FOR);\n\n            if (lexer.token() == (Token.LPAREN)) {\n                lexer.nextToken();\n                while (true) {\n                    pivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                    lexer.nextToken();\n\n                    if (!(lexer.token() == (Token.COMMA))) {\n                        break;\n                    }\n                    lexer.nextToken();\n                }\n\n                accept(Token.RPAREN);\n            } else {\n                pivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                lexer.nextToken();\n            }\n\n            accept(Token.IN);\n            accept(Token.LPAREN);\n//            if (lexer.token() == (Token.LPAREN)) {\n//                throw new ParserException(\"TODO. \" + lexer.info());\n//            }\n\n            if (lexer.token() == (Token.SELECT)) {\n                SQLExpr expr = this.exprParser.expr();\n                item = new SQLSelectItem();\n                item.setExpr(expr);\n                item.setParent(pivot);\n                pivot.getPivotIn().add(item);\n            } else {\n                parsePivotIn(pivot, pivot.getPivotIn());\n            }\n\n            accept(Token.RPAREN);\n\n            accept(Token.RPAREN);\n\n            tableSource.setPivot(pivot);\n        } else if (lexer.identifierEquals(\"UNPIVOT\")) {\n            lexer.nextToken();\n\n            SQLUnpivot unPivot = new SQLUnpivot();\n            if (lexer.identifierEquals(\"INCLUDE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"NULLS\");\n                unPivot.setNullsIncludeType(SQLUnpivot.NullsIncludeType.INCLUDE_NULLS);\n            } else if (lexer.identifierEquals(\"EXCLUDE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"NULLS\");\n                unPivot.setNullsIncludeType(SQLUnpivot.NullsIncludeType.EXCLUDE_NULLS);\n            }\n\n            accept(Token.LPAREN);\n            if (lexer.token() == (Token.LPAREN)) {\n                lexer.nextToken();\n                this.exprParser.exprList(unPivot.getItems(), unPivot);\n                accept(Token.RPAREN);\n            } else {\n                unPivot.addItem(this.exprParser.expr());\n            }\n\n            accept(Token.FOR);\n\n            if (lexer.token() == (Token.LPAREN)) {\n                lexer.nextToken();\n                while (true) {\n                    unPivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                    lexer.nextToken();\n\n                    if (!(lexer.token() == (Token.COMMA))) {\n                        break;\n                    }\n                    lexer.nextToken();\n                }\n\n                accept(Token.RPAREN);\n            } else {\n                unPivot.getPivotFor().add(new SQLIdentifierExpr(lexer.stringVal()));\n                lexer.nextToken();\n            }\n\n            accept(Token.IN);\n            accept(Token.LPAREN);\n\n            if (lexer.token() == (Token.SELECT)) {\n                throw new ParserException(\"subquery in UNPIVOT IN clause is not supported. \" + lexer.info());\n            }\n            parsePivotIn(unPivot, unPivot.getPivotIn());\n\n            accept(Token.RPAREN);\n            accept(Token.RPAREN);\n\n            tableSource.setUnpivot(unPivot);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.SQLParameter.ParameterType;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateFunctionStatement;\nimport com.alibaba.druid.sql.dialect.hive.stmt.HiveMsckRepairStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.FullTextType;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.FnvHash.Constants;\nimport com.alibaba.druid.util.MySqlUtils;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.math.BigDecimal;\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.TimeZone;\nimport java.util.UUID;\n\nimport static com.alibaba.druid.sql.parser.DialectFeature.ParserFeature.*;\nimport static com.alibaba.druid.sql.parser.Token.*;\n\npublic class SQLStatementParser extends SQLParser {\n    protected SchemaRepository repository;\n    protected SQLExprParser exprParser;\n    protected boolean parseCompleteValues = true;\n    protected int parseValuesSize = 3;\n    protected SQLSelectListCache selectListCache;\n    protected InsertColumnsCache insertColumnsCache;\n\n    protected java.sql.Timestamp now;\n    protected java.sql.Date currentDate;\n\n    protected Token expectedNextToken;\n    private static final boolean END_TOKEN_CHECKING_ENABLED = !Boolean.getBoolean(\"druid_sql_parser_end_token_checking_disabled\");\n    private static final String UNSUPPORT_TOKEN_MSG_PREFIX = \"not supported. \";\n    private enum StatementListParseResult {\n        NOT_MATCHED,\n        CONTINUE,\n        RETURN\n    }\n\n    public SQLStatementParser(String sql) {\n        this(sql, null);\n    }\n\n    public SQLStatementParser(String sql, DbType dbType) {\n        this(SQLParserUtils.createExprParser(sql, dbType));\n    }\n\n    public SQLStatementParser(String sql, DbType dbType, SQLParserFeature... features) {\n        this(SQLParserUtils.createExprParser(sql, dbType, features));\n    }\n\n    public SQLStatementParser(SQLExprParser exprParser) {\n        super(exprParser.getLexer(), exprParser.getDbType());\n        this.exprParser = exprParser;\n        this.dbType = exprParser.dbType;\n    }\n\n    protected SQLStatementParser(Lexer lexer, DbType dbType) {\n        super(lexer, dbType);\n    }\n\n    public boolean isKeepComments() {\n        return lexer.isKeepComments();\n    }\n\n    public void setKeepComments(boolean keepComments) {\n        this.lexer.setKeepComments(keepComments);\n    }\n\n    public SQLExprParser getExprParser() {\n        return exprParser;\n    }\n\n    public SchemaRepository getRepository() {\n        return repository;\n    }\n\n    public void setRepository(SchemaRepository repository) {\n        this.repository = repository;\n    }\n\n    public List<SQLStatement> parseStatementList() {\n        List<SQLStatement> statementList = new ArrayList<SQLStatement>();\n        parseStatementList(statementList, -1, null);\n        return statementList;\n    }\n\n    public List<SQLStatement> parseStatementList(SQLObject parent) {\n        List<SQLStatement> statementList = new ArrayList<SQLStatement>();\n        parseStatementList(statementList, -1, parent);\n        return statementList;\n    }\n\n    public void parseStatementList(List<SQLStatement> statementList) {\n        parseStatementList(statementList, -1, null);\n    }\n\n    public void parseStatementList(List<SQLStatement> statementList, int max) {\n        parseStatementList(statementList, max, null);\n    }\n\n    public void parseStatementList(List<SQLStatement> statementList, int max, SQLObject parent) {\n        if (lexer.token == Token.SELECT) {\n            String[] words = lexer.text.split(\"\\\\s+\");\n            if (words.length == 2\n                    && \"select\".equalsIgnoreCase(words[0])\n                    && \"@@session.tx_read_only\".equalsIgnoreCase(words[1])) {\n                SQLSelect select = new SQLSelect();\n                MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock();\n                queryBlock.addSelectItem(new SQLPropertyExpr(new SQLVariantRefExpr(\"@@session\"), \"tx_read_only\"));\n                select.setQuery(queryBlock);\n\n                SQLSelectStatement stmt = new SQLSelectStatement(select);\n                statementList.add(stmt);\n\n                lexer.reset(29, '\\u001A', Token.EOF);\n                return;\n            }\n        }\n\n        boolean semi = false;\n        for (int i = 0; ; i++) {\n            if (max != -1) {\n                if (statementList.size() >= max) {\n                    return;\n                }\n            }\n            while (lexer.token == MULTI_LINE_COMMENT || lexer.token == LINE_COMMENT) {\n                lexer.nextToken();\n            }\n\n            switch (lexer.token) {\n                case EOF:\n                case END:\n                case UNTIL:\n                case ELSE:\n                case WHEN:\n                case EXCEPTION:\n                    if (lexer.isKeepComments() && lexer.hasComment() && !statementList.isEmpty()) {\n                        SQLStatement stmt = statementList.get(statementList.size() - 1);\n                        stmt.addAfterComment(lexer.readAndResetComments());\n                    }\n                    if (END == lexer.token && dialectFeatureEnabled(ParseStatementListWhen)) {\n                        Lexer.SavePoint savePoint = lexer.mark();\n                        lexer.nextToken();\n                        if (lexer.token == Token.IF) {\n                            lexer.reset(savePoint);\n                            return;\n                        }\n\n                        if (parent instanceof SQLBlockStatement) {\n                            lexer.reset(savePoint);\n                            return;\n                        }\n\n                        lexer.reset(savePoint);\n                        SQLStatement stmt = parseEnd();\n                        stmt.setParent(parent);\n                        statementList.add(stmt);\n                        continue;\n                    }\n                    return;\n                case ELSEIF:\n                    if (parent instanceof SQLIfStatement) {\n                        return;\n                    }\n                    break;\n                case SEMI: {\n                    char ch = lexer.ch;\n                    lexer.nextToken();\n\n                    if (statementList.size() > 0) {\n                        SQLStatement lastStmt = statementList.get(statementList.size() - 1);\n                        lastStmt.setAfterSemi(true);\n\n                        if (lexer.isKeepComments()) {\n                            if (ch == '\\n'\n                                    && lexer.getComments() != null\n                                    && !lexer.getComments().isEmpty()\n                                    && !(lastStmt instanceof SQLSetStatement)\n                            ) {\n                                lexer.getComments().add(0, new String(\"\\n\"));\n                            }\n                            lastStmt.addAfterComment(lexer.readAndResetComments());\n                        }\n                    }\n\n                    semi = true;\n\n                    continue;\n                }\n                case WITH: {\n                    SQLStatement stmt = parseWith();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case SELECT: {\n                    MySqlHintStatement hintStatement = null;\n                    if (i == 1\n                            && !statementList.isEmpty()\n                            && statementList.get(statementList.size() - i) instanceof MySqlHintStatement) {\n                        hintStatement = (MySqlHintStatement) statementList.get(statementList.size() - i);\n                    } else if (i > 0 && dialectFeatureEnabled(ParseStatementListSelectUnsupportedSyntax) && !semi\n                            && !(!statementList.isEmpty() && statementList.size() - i >= 0 && statementList.get(statementList.size() - i).isAfterSemi())\n                    ) {\n                        throw new ParserException(\"syntax error. \" + lexer.info());\n                    }\n                    SQLStatement stmt = parseSelect();\n                    stmt.setParent(parent);\n                    if (hintStatement != null && stmt instanceof SQLStatementImpl) {\n                        SQLStatementImpl stmtImpl = (SQLStatementImpl) stmt;\n                        List<SQLCommentHint> hints = stmtImpl.getHeadHintsDirect();\n                        if (hints == null) {\n                            stmtImpl.setHeadHints(hintStatement.getHints());\n                        } else {\n                            hints.addAll(hintStatement.getHints());\n                        }\n                        statementList.set(statementList.size() - 1, stmt);\n                    } else {\n                        statementList.add(stmt);\n                    }\n                    semi = false;\n                    continue;\n                }\n                case UPDATE: {\n                    //FOR ADS\n                    Lexer.SavePoint savePoint = lexer.mark();\n                    lexer.nextToken();\n                    if (dialectFeatureEnabled(ParseStatementListUpdatePlanCache) && lexer.identifierEquals(\"PLANCACHE\")) {\n                        lexer.nextToken();\n                        if (lexer.token == Token.SELECT) {\n                            MySqlUpdatePlanCacheStatement stmt = new MySqlUpdatePlanCacheStatement();\n\n                            SQLSelect fromSelect = createSQLSelectParser().select();\n                            accept(Token.TO);\n                            SQLSelect toSelect = createSQLSelectParser().select();\n\n                            stmt.setFormSelect(fromSelect);\n                            stmt.setToSelect(toSelect);\n\n                            statementList.add(stmt);\n                            continue;\n                        }\n                    }\n\n                    lexer.reset(savePoint);\n                    SQLStatement stmt = parseUpdateStatement();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case CREATE: {\n                    List<String> comments = null;\n                    if (lexer.isKeepComments() && lexer.hasComment()) {\n                        comments = lexer.readAndResetComments();\n                    }\n                    SQLStatement stmt = parseCreate();\n                    stmt.addBeforeComment(comments);\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case INSERT: {\n                    SQLStatement stmt = parseInsert();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case DELETE: {\n                    SQLStatement stmt = parseDeleteStatement();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case GET: {\n                    SQLStatement stmt = parseGetDiagnosticsStatement();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case EXPLAIN: {\n                    if (lexer.keepSourceLocation) {\n                        lexer.computeRowAndColumn();\n                    }\n                    int sourceLine = lexer.posLine;\n                    int sourceColumn = lexer.posColumn;\n\n                    //FOR ADS\n                    Lexer.SavePoint savePoint = lexer.mark();\n                    lexer.nextToken();\n\n                    if (lexer.identifierEquals(\"PLANCACHE\")) {\n                        lexer.nextToken();\n                        MySqlExplainPlanCacheStatement stmt = new MySqlExplainPlanCacheStatement();\n                        stmt.setSource(sourceLine, sourceColumn);\n                        statementList.add(stmt);\n//                    } else if(lexer.token ==  Token.ANALYZE) {\n//                        lexer.nextToken();\n//\n//                        SQLExplainAnalyzeStatement stmt = new SQLExplainAnalyzeStatement();\n//                        stmt.setSelect(createSQLSelectParser().select());\n//                        statementList.add(stmt);\n                    } else {\n                        lexer.reset(savePoint);\n                        SQLExplainStatement stmt = parseExplain();\n                        stmt.setSource(sourceLine, sourceColumn);\n                        stmt.setParent(parent);\n                        statementList.add(stmt);\n                    }\n                    continue;\n                }\n                case SET: {\n                    SQLStatement stmt = parseSet();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case ALTER: {\n                    SQLStatement stmt = parseAlter();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case TRUNCATE: {\n                    SQLStatement stmt = parseTruncate();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case USE: {\n                    SQLStatement stmt = parseUse();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case GRANT: {\n                    SQLStatement stmt = parseGrant();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case REVOKE: {\n                    SQLStatement stmt = parseRevoke();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case SHOW: {\n                    SQLStatement stmt = parseShow();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case MERGE: {\n                    SQLStatement stmt = parseMerge();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case REPEAT: {\n                    SQLStatement stmt = parseRepeat();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case DECLARE: {\n                    SQLStatement stmt = parseDeclare();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case WHILE: {\n                    SQLStatement stmt = parseWhile();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case IF: {\n                    SQLStatement stmt = parseIf();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case CASE: {\n                    SQLStatement stmt = parseCase();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case OPEN: {\n                    SQLStatement stmt = parseOpen();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case FETCH: {\n                    SQLStatement stmt = parseFetch();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case DROP: {\n                    SQLStatement stmt = parseDrop();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case COMMENT: {\n                    SQLStatement stmt = parseComment();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case KILL: {\n                    SQLStatement stmt = parseKill();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case CLOSE: {\n                    SQLStatement stmt = parseClose();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case RETURN: {\n                    SQLStatement stmt = parseReturn();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case UPSERT: {\n                    SQLStatement stmt = parseUpsert();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case LEAVE: {\n                    SQLStatement stmt = parseLeave();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                case CACHE: {\n                    SQLStatement stmt = parseCache();\n                    stmt.setParent(parent);\n                    statementList.add(stmt);\n                    continue;\n                }\n                default:\n                    break;\n            }\n\n            StatementListParseResult parseResult = parseStatementListNonStandard(statementList, parent);\n            if (parseResult == StatementListParseResult.RETURN) {\n                return;\n            }\n            if (parseResult == StatementListParseResult.CONTINUE) {\n                continue;\n            }\n\n            int size = statementList.size();\n            if (parseStatementListDialect(statementList)) {\n                if (parent != null) {\n                    for (int j = size; j < statementList.size(); ++j) {\n                        SQLStatement dialectStmt = statementList.get(j);\n                        dialectStmt.setParent(parent);\n                    }\n                }\n\n                continue;\n            }\n\n            // throw new ParserException(\"syntax error, \" + lexer.token + \" \"\n            // + lexer.stringVal() + \", pos \"\n            // + lexer.pos());\n            throw new ParserException(UNSUPPORT_TOKEN_MSG_PREFIX + lexer.info());\n        }\n\n    }\n\n    private StatementListParseResult parseStatementListNonStandard(List<SQLStatement> statementList, SQLObject parent) {\n        if (lexer.token == Token.LBRACE || lexer.identifierEquals(\"CALL\")) {\n            SQLCallStatement stmt = parseCall();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"UPSERT\")) {\n            SQLStatement stmt = parseUpsert();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"LIST\")) {\n            Lexer.SavePoint mark = lexer.mark();\n            SQLStatement stmt = parseList();\n            if (stmt != null) {\n                statementList.add(stmt);\n                return StatementListParseResult.CONTINUE;\n            } else {\n                lexer.reset(mark);\n            }\n        }\n\n        if (lexer.identifierEquals(\"RENAME\")) {\n            SQLStatement stmt = parseRename();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"RELEASE\")) {\n            SQLStatement stmt = parseReleaseSavePoint();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"SAVEPOINT\")) {\n            SQLStatement stmt = parseSavePoint();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"REFRESH\")) {\n            SQLStatement stmt = parseRefresh();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"SETPROJECT\")) {\n            SQLStatement stmt = parseSet();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COPY)) {\n            SQLStatement stmt = parseCopy();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == Token.DESC || lexer.identifierEquals(FnvHash.Constants.DESCRIBE)) {\n            SQLStatement stmt = parseDescribe();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"ROLLBACK\")) {\n            SQLStatement stmt = parseRollback();\n            statementList.add(stmt);\n            if (parent instanceof SQLBlockStatement\n                    && dialectFeatureEnabled(ParseStatementListRollbackReturn)) {\n                return StatementListParseResult.RETURN;\n            }\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"DUMP\")) {\n            SQLStatement stmt = parseDump();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.COMMIT)) {\n            SQLStatement stmt = parseCommit();\n            statementList.add(stmt);\n            if (parent instanceof SQLBlockStatement\n                    && dialectFeatureEnabled(ParseStatementListCommitReturn)) {\n                return StatementListParseResult.RETURN;\n            }\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RETURN)) {\n            SQLStatement stmt = parseReturn();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PURGE)) {\n            SQLStatement stmt = parsePurge();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.FLASHBACK)) {\n            SQLStatement stmt = parseFlashback();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.WHO)) {\n            SQLStatement stmt = parseWhoami();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == Token.FOR) {\n            SQLStatement stmt = parseFor();\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == Token.LPAREN) {\n            Lexer.SavePoint savePoint = lexer.markOut();\n\n            int parenCount = 0;\n            do {\n                lexer.nextToken();\n                parenCount++;\n            } while (lexer.token == Token.LPAREN);\n\n            if (lexer.token == RPAREN && parenCount == 1 && dialectFeatureEnabled(ParseStatementListLparenContinue)) {\n                lexer.nextToken();\n                return StatementListParseResult.CONTINUE;\n            }\n\n            if (lexer.token == Token.SELECT) {\n                lexer.reset(savePoint);\n                SQLStatement stmt = parseSelect();\n                statementList.add(stmt);\n                return StatementListParseResult.CONTINUE;\n            } else {\n                throw new ParserException(\"unsupported statement after WITH clause, expect SELECT. \" + lexer.info());\n            }\n        }\n\n        if (lexer.token == Token.VALUES) {\n            SQLValuesTableSource values = this.createSQLSelectParser().parseValues();\n            SQLSelectStatement stmt = new SQLSelectStatement();\n            stmt.setSelect(\n                    new SQLSelect(values)\n            );\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"OPTIMIZE\")) {\n            SQLStatement stmt = parseOptimize();\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == WHILE) {\n            SQLStatement stmt = parseWhile();\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == LOOP) {\n            SQLStatement stmt = parseLoop();\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == CONTINUE) {\n            SQLStatement stmt = parseContinue();\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == LEAVE) {\n            SQLStatement stmt = parseLeave();\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"EXECUTE\")) {\n            SQLStatement stmt = parseExecute();\n            statementList.add(stmt);\n            stmt.setParent(parent);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"START\")) {\n            SQLStartTransactionStatement stmt = parseStart();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.token == COMPUTE) {\n            SQLStatement stmt = parseCompute();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        if (lexer.identifierEquals(\"RESET\")) {\n            SQLStatement stmt = parseReset();\n            statementList.add(stmt);\n            return StatementListParseResult.CONTINUE;\n        }\n\n        return StatementListParseResult.NOT_MATCHED;\n    }\n\n    public SQLStatement parseExecute() {\n        throw new ParserException(\"EXECUTE statement is not supported for current dialect. \" + lexer.info());\n    }\n\n    private SQLStatement parseGetDiagnosticsStatement() {\n        accept(Token.GET);\n        accept(Token.DIAGNOSTICS);\n\n        SQLGetDiagnosticsStatement stmt = new SQLGetDiagnosticsStatement();\n        stmt.setDbType(dbType);\n\n        stmt.setExpr(this.exprParser.expr());\n        return stmt;\n    }\n\n    public SQLStatement parseOptimize() {\n        acceptIdentifier(\"OPTIMIZE\");\n        accept(TABLE);\n\n        SQLOptimizeStatement stmt = new SQLOptimizeStatement();\n        List<SQLName> names = new ArrayList<SQLName>();\n        this.exprParser.names(names, stmt);\n\n        for (SQLName name : names) {\n            stmt.addTableSource(new SQLExprTableSource(name));\n        }\n\n        if (lexer.token == ON) {\n            lexer.nextToken();\n            acceptIdentifier(\"CLUSTER\");\n            SQLName cluster = this.exprParser.name();\n            stmt.setCluster(cluster);\n        }\n\n        if (lexer.token() == FINAL) {\n            lexer.nextToken();\n            stmt.setFinal(true);\n        }\n\n        if (lexer.identifierEquals(\"DEDUPLICATE\")) {\n            lexer.nextToken();\n            stmt.setDeduplicate(true);\n            if (lexer.token == BY) {\n                lexer.nextToken();\n                stmt.setDeduplicateBy(\n                        this.exprParser.expr()\n                );\n            }\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseCopy() {\n        throw new ParserException(\"COPY statement is not supported for current dialect. \" + lexer.info());\n    }\n\n    public SQLStatement parseFor() {\n        accept(Token.FOR);\n\n        SQLForStatement stmt = new SQLForStatement();\n        stmt.setDbType(dbType);\n\n        stmt.setIndex(this.exprParser.name());\n        accept(Token.IN);\n        stmt.setRange(this.exprParser.expr());\n\n        accept(Token.LOOP);\n\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n        accept(Token.END);\n        accept(Token.LOOP);\n\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n\n        return stmt;\n    }\n\n    public SQLStatement parseFlashback() {\n        throw new ParserException(\"not supported. \" + lexer.info());\n    }\n\n    public SQLStatement parseDump() {\n        SQLDumpStatement stmt = new SQLDumpStatement();\n        acceptIdentifier(\"DUMP\");\n        acceptIdentifier(\"DATA\");\n\n        if (lexer.identifierEquals(FnvHash.Constants.OVERWRITE)) {\n            lexer.nextToken();\n            stmt.setOverwrite(true);\n        }\n\n        if (lexer.token == Token.INTO) {\n            lexer.nextToken();\n            if (lexer.token == LITERAL_CHARS) {\n                stmt.setInto(new SQLCharExpr(lexer.stringVal));\n                lexer.nextToken();\n            } else {\n                stmt.setInto(this.exprParser.expr());\n            }\n        }\n\n        SQLSelect select = createSQLSelectParser().select();\n        stmt.setSelect(select);\n        return stmt;\n    }\n\n    public SQLStatement parseDrop() {\n        List<String> beforeComments = null;\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            beforeComments = lexer.readAndResetComments();\n        }\n\n        Lexer.SavePoint mark = lexer.mark();\n        lexer.nextToken();\n\n        final SQLStatement stmt;\n\n        List<SQLCommentHint> hints = null;\n        if (lexer.token == Token.HINT) {\n            hints = this.exprParser.parseHints();\n        }\n\n        boolean temporary = false;\n\n        if (lexer.token == Token.TEMPORARY || lexer.identifierEquals(FnvHash.Constants.TEMPORARY)) {\n            lexer.nextToken();\n            temporary = true;\n        }\n\n        boolean physical = false;\n        if (lexer.identifierEquals(FnvHash.Constants.PHYSICAL)) {\n            lexer.nextToken();\n            physical = true;\n        }\n\n        switch (lexer.token) {\n            case USER:\n                stmt = parseDropUser();\n                break;\n            case INDEX:\n                stmt = parseDropIndex();\n                break;\n            case VIEW:\n                stmt = parseDropView(false);\n                break;\n            case TRIGGER:\n                stmt = parseDropTrigger(false);\n                break;\n            case DATABASE:\n                stmt = parseDropDatabaseOrSchema(false);\n                if (physical) {\n                    ((SQLDropDatabaseStatement) stmt).setPhysical(physical);\n                }\n                break;\n            case SCHEMA:\n                stmt = parseDropSchema(physical);\n                break;\n            case FUNCTION:\n                SQLDropFunctionStatement dropFunc = parseDropFunction(false);\n                if (temporary) {\n                    dropFunc.setTemporary(true);\n                }\n                stmt = dropFunc;\n                break;\n            case TABLESPACE:\n                stmt = parseDropTablespace(false);\n                break;\n            case PROCEDURE:\n                stmt = parseDropProcedure(false);\n                break;\n            case SEQUENCE:\n                stmt = parseDropSequence(false);\n                break;\n            case TABLE: {\n                SQLDropTableStatement dropTable = parseDropTable(false);\n                if (temporary) {\n                    dropTable.setTemporary(true);\n                }\n                if (hints != null) {\n                    dropTable.setHints(hints);\n                }\n                stmt = dropTable;\n                break;\n            }\n            default:\n                if (lexer.token == Token.TABLE || lexer.identifierEquals(\"TEMPORARY\") || lexer.identifierEquals(FnvHash.Constants.PARTITIONED)) {\n                    SQLDropTableStatement dropTable = parseDropTable(false);\n                    if (hints != null) {\n                        dropTable.setHints(hints);\n                    }\n                    stmt = dropTable;\n                } else if (lexer.identifierEquals(Constants.TABLES)) {\n                    stmt = parseDropTable(false);\n                } else if (lexer.identifierEquals(FnvHash.Constants.EVENT)) {\n                    stmt = parseDropEvent();\n                } else if (lexer.identifierEquals(FnvHash.Constants.RESOURCE)) {\n                    stmt = parseDropResource();\n\n                } else if (lexer.identifierEquals(FnvHash.Constants.LOGFILE)) {\n                    stmt = parseDropLogFileGroup();\n\n                } else if (lexer.identifierEquals(FnvHash.Constants.SERVER)) {\n                    stmt = parseDropServer();\n\n                } else if (lexer.identifierEquals(FnvHash.Constants.TABLEGROUP)) {\n                    stmt = parseDropTableGroup();\n                } else if (lexer.identifierEquals(FnvHash.Constants.ROLE)) {\n                    lexer.reset(mark);\n                    stmt = parseDropRole();\n                } else if (lexer.identifierEquals(FnvHash.Constants.OUTLINE)) {\n                    lexer.reset(mark);\n                    stmt = parseDropOutline();\n\n                } else if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n                    lexer.nextToken();\n                    if (lexer.token == Token.TABLE) {\n                        lexer.reset(mark);\n                        stmt = parseDropTable(true);\n                    } else if (lexer.identifierEquals(FnvHash.Constants.CATALOG)) {\n                        lexer.reset(mark);\n                        stmt = parseDropCatalog();\n                    } else {\n                        throw new ParserException(\"unsupported DROP EXTERNAL target, expect TABLE or CATALOG. \" + lexer.info());\n                    }\n                } else if (lexer.token() == Token.FULLTEXT) {\n                    lexer.nextToken();\n\n                    FullTextType type = parseFullTextType();\n                    SQLName name = this.exprParser.name();\n\n                    MysqlDropFullTextStatement x = new MysqlDropFullTextStatement();\n                    x.setName(name);\n                    x.setType(type);\n                    stmt = x;\n                } else if (lexer.identifierEquals(\"INSTANCE_GROUP\")) {\n                    lexer.nextToken();\n                    MySqlManageInstanceGroupStatement x = new MySqlManageInstanceGroupStatement();\n                    x.setOperation(new SQLIdentifierExpr(\"DROP\"));\n\n                    for (; ; ) {\n                        x.getGroupNames().add(exprParser.expr());\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    stmt = x;\n                } else if (lexer.identifierEquals(\"MATERIALIZED\")) {\n                    stmt = parseDropMaterializedView();\n                } else if (lexer.identifierEquals(\"OFFLINEMODEL\")) {\n                    stmt = parseDropOfflineModel();\n                } else {\n                    throw new ParserException(\"unsupported DROP target '\" + lexer.stringVal() + \"'. \" + lexer.info());\n                }\n\n                break;\n        }\n\n        if (beforeComments != null) {\n            stmt.addBeforeComment(beforeComments);\n        }\n\n        return stmt;\n    }\n\n    protected FullTextType parseFullTextType() {\n        FullTextType textType;\n\n        if (lexer.identifierEquals(FnvHash.Constants.CHARFILTER)) {\n            textType = FullTextType.CHARFILTER;\n        } else if (lexer.identifierEquals(FnvHash.Constants.TOKENIZER)) {\n            textType = FullTextType.TOKENIZER;\n        } else if (lexer.identifierEquals(FnvHash.Constants.TOKENFILTER)) {\n            textType = FullTextType.TOKENFILTER;\n        } else if (lexer.identifierEquals(FnvHash.Constants.ANALYZER)) {\n            textType = FullTextType.ANALYZER;\n        } else if (lexer.identifierEquals(FnvHash.Constants.DICTIONARY)) {\n            textType = FullTextType.DICTIONARY;\n        } else {\n            throw new ParserException(\"type of full text must be [CHARFILTER/TOKENIZER/TOKENFILTER/ANALYZER/DICTIONARY] .\");\n        }\n        lexer.nextToken();\n        return textType;\n    }\n\n    protected SQLStatement parseWhoami() {\n        lexer.nextToken();\n        acceptIdentifier(\"AM\");\n        acceptIdentifier(\"I\");\n        return new SQLWhoamiStatement();\n    }\n\n    protected SQLStatement parseDropOutline() {\n        accept(Token.DROP);\n\n        SQLDropOutlineStatement stmt = new SQLDropOutlineStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"OUTLINE\");\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    public SQLStatement parseRefresh() {\n        if (lexer.identifierEquals(\"REFRESH\")) {\n            lexer.nextToken();\n        }\n        SQLRefreshMaterializedViewStatement stmt = new SQLRefreshMaterializedViewStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"MATERIALIZED\");\n\n        if (lexer.identifierEquals(\"CONCURRENTLY\")) {\n            lexer.nextToken();\n            stmt.setConcurrently(true);\n        }\n        accept(Token.VIEW);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n\n            if (lexer.token() == IDENTIFIER && \"NO\".equalsIgnoreCase(lexer.stringVal())) {\n                lexer.nextToken();\n                stmt.setWithNoData(true);\n            }\n\n            if (lexer.token() == IDENTIFIER && \"DATA\".equalsIgnoreCase(lexer.stringVal())) {\n                lexer.nextToken();\n                stmt.setWithData(true);\n            } else {\n                throw new ParserException(\"syntax error, expect DATA, actual \" + lexer.token() + \", pos \" + lexer.pos());\n            }\n        }\n        return stmt;\n    }\n\n    public SQLStatement parseShowMaterializedView() {\n        if (lexer.token() == Token.SHOW) {\n            lexer.nextToken();\n        }\n        SQLShowMaterializedViewStatement stmt = new SQLShowMaterializedViewStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"MATERIALIZED\");\n\n        acceptIdentifier(\"VIEWS\");\n\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            stmt.setLike(this.exprParser.charExpr());\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseDropMaterializedView() {\n        if (lexer.token() == Token.DROP) {\n            lexer.nextToken();\n        }\n        SQLDropMaterializedViewStatement stmt = new SQLDropMaterializedViewStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"MATERIALIZED\");\n\n        accept(Token.VIEW);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n\n    public SQLStatement parseDropOfflineModel() {\n        if (lexer.token() == Token.DROP) {\n            lexer.nextToken();\n        }\n        SQLDropOfflineModelStatement stmt = new SQLDropOfflineModelStatement();\n        stmt.setDbType(dbType);\n\n        acceptIdentifier(\"OFFLINEMODEL\");\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n\n    protected SQLStatement parseDropCatalog() {\n        accept(Token.DROP);\n\n        SQLDropCatalogStatement stmt = new SQLDropCatalogStatement(dbType);\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            stmt.setExternal(true);\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"CATALOG\");\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    protected SQLStatement parseDropRole() {\n        accept(Token.DROP);\n        acceptIdentifier(\"ROLE\");\n\n        SQLDropRoleStatement stmt = new SQLDropRoleStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    protected SQLStatement parseDropTableGroup() {\n        if (lexer.token == Token.DROP) {\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"TABLEGROUP\");\n\n        SQLDropTableGroupStatement stmt = new SQLDropTableGroupStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    protected SQLStatement parseDropServer() {\n        if (lexer.token == Token.DROP) {\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"SERVER\");\n\n        SQLDropServerStatement stmt = new SQLDropServerStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    protected SQLStatement parseDropLogFileGroup() {\n        if (lexer.token == Token.DROP) {\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"LOGFILE\");\n        accept(Token.GROUP);\n\n        SQLDropLogFileGroupStatement stmt = new SQLDropLogFileGroupStatement();\n        stmt.setDbType(dbType);\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n            lexer.nextToken();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr engine = this.exprParser.primary();\n            stmt.setEngine(engine);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseDropEvent() {\n        if (lexer.token == Token.DROP) {\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"EVENT\");\n\n        SQLDropEventStatement stmt = new SQLDropEventStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    protected SQLStatement parseDropResource() {\n        if (lexer.token == Token.DROP) {\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"RESOURCE\");\n\n        if (lexer.token == GROUP) {\n            lexer.nextToken();\n            SQLDropResourceGroupStatement stmt = new SQLDropResourceGroupStatement();\n            stmt.setDbType(dbType);\n\n            if (lexer.token == Token.IF) {\n                lexer.nextToken();\n                accept(Token.EXISTS);\n                stmt.setIfExists(true);\n            }\n\n            SQLName name = this.exprParser.name();\n            stmt.setName(name);\n\n            return stmt;\n        }\n\n        SQLDropResourceStatement stmt = new SQLDropResourceStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    protected SQLStatement alterTableSpace() {\n        throw new ParserException(\"ALTER TABLESPACE is not supported for current dialect. \" + lexer.info());\n    }\n\n    protected SQLStatement alterProcedure() {\n        throw new ParserException(\"ALTER PROCEDURE is not supported for current dialect. \" + lexer.info());\n    }\n\n    protected SQLStatement parseAlterFunction() {\n        throw new ParserException(\"ALTER FUNCTION is not supported for current dialect. \" + lexer.info());\n    }\n\n    public SQLStatement parseKill() {\n        throw new ParserException(\"not supported. \" + lexer.info());\n    }\n\n    public SQLStatement parseCase() {\n        throw new ParserException(\"not supported. \" + lexer.info());\n    }\n\n    public SQLStatement parseIf() {\n        accept(Token.IF);\n        SQLIfStatement stmt = new SQLIfStatement();\n        stmt.setCondition(this.exprParser.expr());\n        accept(Token.THEN);\n\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n\n        parseIfElse(stmt);\n\n        accept(Token.END);\n        accept(Token.IF);\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n        return stmt;\n    }\n\n    protected void parseIfElse(SQLIfStatement stmt) {\n        while (lexer.token == Token.ELSE || lexer.token == Token.ELSEIF) {\n            boolean isConcatenated = lexer.token == Token.ELSEIF;\n            if (lexer.nextIf(Token.ELSEIF) || (lexer.nextIf(Token.ELSE) && lexer.nextIf(Token.IF))) {\n                SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf();\n                elseIf.setConcatenated(isConcatenated);\n                elseIf.setCondition(this.exprParser.expr());\n                elseIf.setParent(stmt);\n                accept(Token.THEN);\n                this.parseStatementList(elseIf.getStatements(), -1, elseIf);\n                stmt.getElseIfList().add(elseIf);\n            } else {\n                SQLIfStatement.Else elseItem = new SQLIfStatement.Else();\n                this.parseStatementList(elseItem.getStatements(), -1, elseItem);\n                stmt.setElseItem(elseItem);\n                break;\n            }\n        }\n    }\n\n    public SQLWhileStatement parseWhile() {\n        accept(Token.WHILE);\n        SQLWhileStatement stmt = new SQLWhileStatement();\n\n        stmt.setCondition(this.exprParser.expr());\n\n        accept(Token.DO);\n\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n\n        accept(Token.END);\n\n        accept(Token.WHILE);\n\n        accept(SEMI);\n\n        stmt.setAfterSemi(true);\n\n        return stmt;\n    }\n\n    public SQLStatement parseLoop() {\n        accept(Token.LOOP);\n        SQLLoopStatement stmt = new SQLLoopStatement();\n        this.parseStatementList(stmt.getStatements(), -1, stmt);\n        accept(Token.END);\n        accept(Token.LOOP);\n        return stmt;\n    }\n\n    public SQLStatement parseDeclare() {\n        throw new ParserException(\"not supported. \" + lexer.info());\n    }\n\n    public SQLStatement parseContinue() {\n        accept(Token.CONTINUE);\n        return new SQLContinueStatement();\n    }\n\n    public SQLStatement parseRepeat() {\n        throw new ParserException(\"not supported. \" + lexer.info());\n    }\n\n    public SQLStatement parseLeave() {\n        accept(LEAVE);\n        return new SQLLeaveStatement();\n    }\n\n    public SQLStatement parseCache() {\n        throw new ParserException(\"not supported. \" + lexer.info());\n    }\n\n    public SQLStatement parsePurge() {\n        acceptIdentifier(\"PURGE\");\n\n        if (lexer.token == Token.TABLE) {\n            lexer.nextToken();\n            SQLName tableName = this.exprParser.name();\n\n            SQLPurgeTableStatement stmt = new SQLPurgeTableStatement();\n            stmt.setTable(tableName);\n\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.RECYCLEBIN)) {\n            lexer.nextToken();\n            SQLPurgeRecyclebinStatement stmt = new SQLPurgeRecyclebinStatement();\n            return stmt;\n        }\n\n        if (lexer.token == ALL) {\n            lexer.nextToken();\n\n            SQLPurgeTableStatement stmt = new SQLPurgeTableStatement();\n            stmt.setAll(true);\n\n            if (lexer.token == LITERAL_INT) {\n                stmt.setCount(lexer.integerValue().intValue());\n                lexer.nextToken();\n            }\n            return stmt;\n        }\n\n        if (lexer.identifierEquals(\"TEMPORARY\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"OUTPUT\");\n            SQLPurgeTemporaryOutputStatement stmt = new SQLPurgeTemporaryOutputStatement();\n            stmt.setName(\n                    this.exprParser.name());\n            return stmt;\n        }\n\n        SQLPurgeLogsStatement stmt = new SQLPurgeLogsStatement();\n\n        if (lexer.token == Token.BINARY) {\n            lexer.nextToken();\n            stmt.setBinary(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.MASTER)) {\n            lexer.nextToken();\n            stmt.setMaster(true);\n        }\n\n        if (lexer.token == ALL) {\n            lexer.nextToken();\n            stmt.setAll(true);\n            return stmt;\n        }\n\n        acceptIdentifier(\"LOGS\");\n\n        if (lexer.token == Token.TO) {\n            lexer.nextToken();\n            SQLExpr to = this.exprParser.expr();\n            stmt.setTo(to);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.BEFORE)) {\n            lexer.nextToken();\n            SQLExpr before = this.exprParser.expr();\n            stmt.setBefore(before);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseReturn() {\n        if (lexer.token == Token.RETURN\n                || lexer.identifierEquals(\"RETURN\")) {\n            lexer.nextToken();\n        }\n\n        SQLReturnStatement stmt = new SQLReturnStatement();\n        if (lexer.token != Token.SEMI) {\n            SQLExpr expr = this.exprParser.expr();\n            stmt.setExpr(expr);\n        }\n\n        if (lexer.token == Token.SEMI) {\n            accept(Token.SEMI);\n            stmt.setAfterSemi(true);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseUpsert() {\n        SQLInsertStatement insertStatement = new SQLInsertStatement();\n\n        if (lexer.token == Token.UPSERT || lexer.identifierEquals(\"UPSERT\")) {\n            lexer.nextToken();\n            insertStatement.setUpsert(true);\n        }\n\n        parseInsert0(insertStatement);\n        return insertStatement;\n    }\n\n    public SQLStatement parseRollback() {\n        lexer.nextToken();\n\n        if (lexer.nextIfIdentifier(\"TRANSACTION\")) {\n            return new SQLRollbackTransactionStatement();\n        }\n\n        if (lexer.identifierEquals(\"WORK\")) {\n            lexer.nextToken();\n        }\n\n        SQLRollbackStatement stmt = new SQLRollbackStatement(getDbType());\n\n        if (lexer.token == Token.TO) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"SAVEPOINT\") || lexer.token == Token.SAVEPOINT) {\n                lexer.nextToken();\n            }\n\n            stmt.setTo(this.exprParser.name());\n        }\n        return stmt;\n    }\n\n    public SQLStatement parseCommit() {\n        acceptIdentifier(\"COMMIT\");\n        if (lexer.nextIfIdentifier(\"TRANSACTION\")) {\n            return new SQLCommitTransactionStatement();\n        }\n        return new SQLCommitStatement();\n    }\n\n    public SQLStatement parseShow() {\n        throw new ParserException(\"SHOW statement is not supported for current dialect. \" + lexer.info());\n    }\n\n    public SQLUseStatement parseUse() {\n        accept(Token.USE);\n        SQLUseStatement stmt = new SQLUseStatement(getDbType());\n        stmt.setDatabase(this.exprParser.name());\n        return stmt;\n    }\n\n    protected SQLExpr parseUser() {\n        SQLExpr user = this.exprParser.expr();\n        return user;\n    }\n\n    public SQLGrantStatement parseGrant() {\n        accept(Token.GRANT);\n        SQLGrantStatement stmt = new SQLGrantStatement(getDbType());\n\n        parsePrivilege(stmt.getPrivileges(), stmt);\n\n        if (lexer.token == Token.ON) {\n            lexer.nextToken();\n\n            switch (lexer.token) {\n                case PROCEDURE:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.PROCEDURE);\n                    break;\n                case FUNCTION:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.FUNCTION);\n                    break;\n                case TABLE:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.TABLE);\n                    break;\n                case USER:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.USER);\n                    break;\n                case DATABASE:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.DATABASE);\n                    break;\n                case IDENTIFIER:\n                    if (lexer.identifierEquals(\"SYSTEM\")) {\n                        lexer.nextToken();\n                        stmt.setResourceType(SQLObjectType.SYSTEM);\n                    }\n                    break;\n                default:\n                    break;\n            }\n\n            if (stmt.getResourceType() != null && lexer.token == Token.COLONCOLON) {\n                lexer.nextToken(); // sql server\n            }\n\n            SQLExpr expr;\n            if (lexer.token == Token.DOT) {\n                expr = new SQLAllColumnExpr();\n                lexer.nextToken();\n            } else {\n                expr = this.exprParser.expr();\n            }\n\n            if (stmt.getResourceType() == SQLObjectType.TABLE || stmt.getResourceType() == null) {\n                stmt.setResource(new SQLExprTableSource(expr));\n            } else {\n                stmt.setResource(expr);\n            }\n        }\n\n        if (lexer.token == Token.TO) {\n            lexer.nextToken();\n            for (; ; ) {\n                SQLExpr user = parseUser();\n                stmt.getUsers().add(user);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n        }\n\n        if (lexer.token == Token.WITH) {\n            lexer.nextToken();\n\n            if (lexer.token == Token.GRANT) {\n                lexer.nextToken();\n                acceptIdentifier(\"OPTION\");\n                stmt.setWithGrantOption(true);\n            }\n\n            for (; ; ) {\n                if (lexer.identifierEquals(\"MAX_QUERIES_PER_HOUR\")) {\n                    lexer.nextToken();\n                    stmt.setMaxQueriesPerHour(this.exprParser.primary());\n                    continue;\n                }\n\n                if (lexer.identifierEquals(\"MAX_UPDATES_PER_HOUR\")) {\n                    lexer.nextToken();\n                    stmt.setMaxUpdatesPerHour(this.exprParser.primary());\n                    continue;\n                }\n\n                if (lexer.identifierEquals(\"MAX_CONNECTIONS_PER_HOUR\")) {\n                    lexer.nextToken();\n                    stmt.setMaxConnectionsPerHour(this.exprParser.primary());\n                    continue;\n                }\n\n                if (lexer.identifierEquals(\"MAX_USER_CONNECTIONS\")) {\n                    lexer.nextToken();\n                    stmt.setMaxUserConnections(this.exprParser.primary());\n                    continue;\n                }\n\n                break;\n            }\n        }\n\n        if (lexer.identifierEquals(\"ADMIN\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"OPTION\");\n            stmt.setAdminOption(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.IDENTIFIED)) {\n            lexer.nextToken();\n            accept(Token.BY);\n\n            if (lexer.identifierEquals(\"PASSWORD\")) {\n                lexer.nextToken();\n                String password = lexer.stringVal();\n                accept(Token.LITERAL_CHARS);\n                stmt.setIdentifiedByPassword(password);\n            } else {\n                stmt.setIdentifiedBy(this.exprParser.expr());\n            }\n        }\n\n        if (lexer.token == Token.WITH) {\n            lexer.nextToken();\n            if (lexer.token == Token.GRANT) {\n                lexer.nextToken();\n                acceptIdentifier(\"OPTION\");\n                stmt.setWithGrantOption(true);\n            }\n        }\n\n        return stmt;\n    }\n\n    protected void parsePrivilege(List<SQLPrivilegeItem> privileges, SQLObject parent) {\n        for (; ; ) {\n            String privilege = null;\n            if (lexer.token == Token.ALL) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"PRIVILEGES\")) {\n                    privilege = \"ALL PRIVILEGES\";\n                    lexer.nextToken();\n                } else {\n                    privilege = \"ALL\";\n                }\n            } else if (lexer.token == Token.SELECT) {\n                privilege = \"SELECT\";\n                lexer.nextToken();\n            } else if (lexer.token == Token.UPDATE) {\n                privilege = \"UPDATE\";\n                lexer.nextToken();\n            } else if (lexer.token == Token.DELETE) {\n                privilege = \"DELETE\";\n                lexer.nextToken();\n            } else if (lexer.token == Token.INSERT) {\n                privilege = \"INSERT\";\n                lexer.nextToken();\n            } else if (lexer.token == Token.INDEX) {\n                lexer.nextToken();\n                privilege = \"INDEX\";\n            } else if (lexer.token == Token.TRIGGER) {\n                lexer.nextToken();\n                privilege = \"TRIGGER\";\n            } else if (lexer.token == Token.REFERENCES) {\n                privilege = \"REFERENCES\";\n                lexer.nextToken();\n            } else if (lexer.token == Token.DESC) {\n                privilege = \"DESCRIBE\";\n                lexer.nextToken();\n            } else if (lexer.token == TRUNCATE) {\n                privilege = \"TRUNCATE\";\n                lexer.nextToken();\n            } else if (lexer.token == Token.CREATE) {\n                lexer.nextToken();\n\n                if (lexer.token == Token.TABLE) {\n                    privilege = \"CREATE TABLE\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.SESSION) {\n                    privilege = \"CREATE SESSION\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.TABLESPACE) {\n                    privilege = \"CREATE TABLESPACE\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.USER) {\n                    privilege = \"CREATE USER\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.VIEW) {\n                    privilege = \"CREATE VIEW\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.PROCEDURE) {\n                    privilege = \"CREATE PROCEDURE\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.SEQUENCE) {\n                    privilege = \"CREATE SEQUENCE\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.ANY) {\n                    lexer.nextToken();\n\n                    if (lexer.token == Token.TABLE) {\n                        lexer.nextToken();\n                        privilege = \"CREATE ANY TABLE\";\n                    } else if (lexer.identifierEquals(\"MATERIALIZED\")) {\n                        lexer.nextToken();\n                        accept(Token.VIEW);\n                        privilege = \"CREATE ANY MATERIALIZED VIEW\";\n                    } else {\n                        throw new ParserException(\"unsupported CREATE ANY privilege type '\" + lexer.stringVal() + \"'. \" + lexer.info());\n                    }\n                } else if (lexer.identifierEquals(\"SYNONYM\")) {\n                    privilege = \"CREATE SYNONYM\";\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(\"ROUTINE\")) {\n                    privilege = \"CREATE ROUTINE\";\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(\"TEMPORARY\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"TABLES\");\n                    privilege = \"CREATE TEMPORARY TABLES\";\n                } else if (lexer.token == Token.ON) {\n                    privilege = \"CREATE\";\n                } else if (lexer.token == Token.COMMA) {\n                    privilege = \"CREATE\";\n                } else {\n                    throw new ParserException(\"unsupported CREATE privilege type '\" + lexer.stringVal() + \"'. \" + lexer.info());\n                }\n            } else if (lexer.token == Token.ALTER) {\n                lexer.nextToken();\n                if (lexer.token == Token.TABLE) {\n                    privilege = \"ALTER TABLE\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.SESSION) {\n                    privilege = \"ALTER SESSION\";\n                    lexer.nextToken();\n                } else if (lexer.identifierEquals(FnvHash.Constants.ROUTINE)) {\n                    privilege = \"ALTER ROUTINE\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.ANY) {\n                    lexer.nextToken();\n\n                    if (lexer.token == Token.TABLE) {\n                        lexer.nextToken();\n                        privilege = \"ALTER ANY TABLE\";\n                    } else if (lexer.identifierEquals(\"MATERIALIZED\")) {\n                        lexer.nextToken();\n                        accept(Token.VIEW);\n                        privilege = \"ALTER ANY MATERIALIZED VIEW\";\n                    } else {\n                        throw new ParserException(\"unsupported ALTER ANY privilege type '\" + lexer.stringVal() + \"'. \" + lexer.info());\n                    }\n                } else if (lexer.token == Token.ON || lexer.token == Token.COMMA) {\n                    privilege = \"ALTER\";\n                } else {\n                    throw new ParserException(\"unsupported ALTER privilege type '\" + lexer.stringVal() + \"'. \" + lexer.info());\n                }\n            } else if (lexer.token == Token.DROP) {\n                lexer.nextToken();\n                if (lexer.token == Token.TABLE) {\n                    privilege = \"DROP TABLE\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.SESSION) {\n                    privilege = \"DROP SESSION\";\n                    lexer.nextToken();\n                } else if (lexer.token == Token.ANY) {\n                    lexer.nextToken();\n\n                    if (lexer.token == Token.TABLE) {\n                        lexer.nextToken();\n                        privilege = \"DROP ANY TABLE\";\n                    } else if (lexer.identifierEquals(\"MATERIALIZED\")) {\n                        lexer.nextToken();\n                        accept(Token.VIEW);\n                        privilege = \"DROP ANY MATERIALIZED VIEW\";\n                    } else {\n                        throw new ParserException(\"unsupported DROP ANY privilege type '\" + lexer.stringVal() + \"'. \" + lexer.info());\n                    }\n                } else {\n                    privilege = \"DROP\";\n                }\n            } else if (lexer.identifierEquals(\"USAGE\")) {\n                privilege = \"USAGE\";\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"EXECUTE\")) {\n                privilege = \"EXECUTE\";\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"PROXY\")) {\n                privilege = \"PROXY\";\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"QUERY\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"REWRITE\");\n                privilege = \"QUERY REWRITE\";\n            } else if (lexer.identifierEquals(\"GLOBAL\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"QUERY\");\n                acceptIdentifier(\"REWRITE\");\n                privilege = \"GLOBAL QUERY REWRITE\";\n            } else if (lexer.identifierEquals(\"INHERIT\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"PRIVILEGES\");\n                privilege = \"INHERIT PRIVILEGES\";\n            } else if (lexer.identifierEquals(\"EVENT\")) {\n                lexer.nextToken();\n                privilege = \"EVENT\";\n            } else if (lexer.identifierEquals(\"FILE\")) {\n                lexer.nextToken();\n                privilege = \"FILE\";\n            } else if (lexer.identifierEquals(\"DESCRIBE\")) {\n                lexer.nextToken();\n                privilege = \"DESCRIBE\";\n            } else if (lexer.token == Token.GRANT) {\n                lexer.nextToken();\n                acceptIdentifier(\"OPTION\");\n\n                if (lexer.token == Token.FOR) {\n                    privilege = \"GRANT OPTION FOR\";\n                    lexer.nextToken();\n                } else {\n                    privilege = \"GRANT OPTION\";\n                }\n            } else if (lexer.token == Token.LOCK) {\n                lexer.nextToken();\n                acceptIdentifier(\"TABLES\");\n                privilege = \"LOCK TABLES\";\n            } else if (lexer.identifierEquals(\"PROCESS\")) {\n                lexer.nextToken();\n                privilege = \"PROCESS\";\n            } else if (lexer.identifierEquals(\"RELOAD\")) {\n                lexer.nextToken();\n                privilege = \"RELOAD\";\n            } else if (lexer.identifierEquals(\"CONNECT\")) {\n                privilege = \"CONNECT\";\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"RESOURCE\")) {\n                lexer.nextToken();\n                privilege = \"RESOURCE\";\n            } else if (lexer.token == Token.CONNECT) {\n                lexer.nextToken();\n                privilege = \"CONNECT\";\n            } else if (lexer.identifierEquals(\"REPLICATION\")) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"SLAVE\")) {\n                    lexer.nextToken();\n                    privilege = \"REPLICATION SLAVE\";\n                } else {\n                    acceptIdentifier(\"CLIENT\");\n                    privilege = \"REPLICATION CLIENT\";\n                }\n            } else if (lexer.token == Token.SHOW) {\n                lexer.nextToken();\n\n                if (lexer.token == Token.VIEW) {\n                    lexer.nextToken();\n                    privilege = \"SHOW VIEW\";\n                } else if (lexer.identifierEquals(\"DATABASES\")) {\n                    acceptIdentifier(\"DATABASES\");\n                    privilege = \"SHOW DATABASES\";\n                } else {\n                    privilege = \"SHOW\";\n                }\n            } else if (lexer.identifierEquals(\"SHUTDOWN\")) {\n                lexer.nextToken();\n                privilege = \"SHUTDOWN\";\n            } else if (lexer.identifierEquals(\"SUPER\")) {\n                lexer.nextToken();\n                privilege = \"SUPER\";\n\n            } else if (lexer.identifierEquals(\"CONTROL\")) { // sqlserver\n                lexer.nextToken();\n                privilege = \"CONTROL\";\n            } else if (lexer.identifierEquals(\"IMPERSONATE\")) { // sqlserver\n                lexer.nextToken();\n                privilege = \"IMPERSONATE\";\n            } else if (lexer.identifierEquals(\"LOAD\")) { // sqlserver\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"DATA\")) {\n                    lexer.nextToken();\n                    privilege = \"LOAD DATA\";\n                }\n            } else if (lexer.identifierEquals(\"DUMP\")) { // sqlserver\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"DATA\")) {\n                    lexer.nextToken();\n                    privilege = \"DUMP DATA\";\n                }\n            }\n\n            if (privilege != null) {\n                SQLExpr expr = new SQLIdentifierExpr(privilege);\n\n                SQLPrivilegeItem privilegeItem = new SQLPrivilegeItem();\n                privilegeItem.setAction(expr);\n\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n                    for (; ; ) {\n                        privilegeItem.getColumns().add(this.exprParser.name());\n\n                        if (lexer.token() == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                }\n\n                expr.setParent(parent);\n                privileges.add(privilegeItem);\n            }\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n    }\n\n    public SQLRevokeStatement parseRevoke() {\n        accept(Token.REVOKE);\n\n        SQLRevokeStatement stmt = new SQLRevokeStatement(dbType);\n\n        if (lexer.token == Token.GRANT) {\n            lexer.nextToken();\n            acceptIdentifier(\"OPTION\");\n\n            stmt.setGrantOption(true);\n\n            if (lexer.token == Token.FOR) {\n                lexer.nextToken();\n            }\n        }\n\n        parsePrivilege(stmt.getPrivileges(), stmt);\n\n        if (lexer.token == Token.ON) {\n            lexer.nextToken();\n\n            switch (lexer.token) {\n                case PROCEDURE:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.PROCEDURE);\n                    break;\n                case FUNCTION:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.FUNCTION);\n                    break;\n                case TABLE:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.TABLE);\n                    break;\n                case USER:\n                    lexer.nextToken();\n                    stmt.setResourceType(SQLObjectType.USER);\n                    break;\n                case IDENTIFIER:\n                    if (lexer.identifierEquals(\"SYSTEM\")) {\n                        lexer.nextToken();\n                        stmt.setResourceType(SQLObjectType.SYSTEM);\n                    } else if (lexer.identifierEquals(\"PROJECT\")) {\n                        lexer.nextToken();\n                        stmt.setResourceType(SQLObjectType.PROJECT);\n                    }\n\n                    break;\n                default:\n                    break;\n            }\n\n            SQLExpr expr = this.exprParser.expr();\n            if (stmt.getResourceType() == SQLObjectType.TABLE || stmt.getResourceType() == null) {\n                stmt.setResource(new SQLExprTableSource(expr));\n            } else {\n                stmt.setResource(expr);\n            }\n        }\n\n        if (lexer.token == Token.FROM) {\n            lexer.nextToken();\n            for (; ; ) {\n                if (lexer.token() == Token.USER && dialectFeatureEnabled(ParseRevokeFromUser)) {\n                    lexer.nextToken();\n                }\n                SQLExpr user = parseUser();\n                stmt.getUsers().add(user);\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseSavePoint() {\n        acceptIdentifier(\"SAVEPOINT\");\n        SQLSavePointStatement stmt = new SQLSavePointStatement(getDbType());\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n\n    public SQLStatement parseReleaseSavePoint() {\n        acceptIdentifier(\"RELEASE\");\n        acceptIdentifier(\"SAVEPOINT\");\n        SQLReleaseSavePointStatement stmt = new SQLReleaseSavePointStatement(getDbType());\n        stmt.setName(this.exprParser.name());\n        return stmt;\n    }\n\n    public final SQLStatement parseAlter() {\n        List<String> comments = null;\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            comments = lexer.readAndResetComments();\n        }\n\n        Lexer.SavePoint mark = lexer.mark();\n        accept(Token.ALTER);\n\n        SQLStatement stmt;\n        switch (lexer.token) {\n            case TABLE:\n                lexer.reset(mark);\n                stmt = alterTable();\n                break;\n            case VIEW:\n                lexer.reset(mark);\n                stmt = alterView();\n                break;\n            case INDEX:\n                lexer.reset(mark);\n                stmt = alterIndex();\n                break;\n            case DATABASE:\n                lexer.reset(mark);\n                stmt = alterDatabase();\n                break;\n            case USER:\n                stmt = alterUser();\n                break;\n            case SCHEMA:\n                lexer.reset(mark);\n                stmt = alterSchema();\n                break;\n            case FUNCTION:\n                lexer.reset(mark);\n                stmt = parseAlterFunction();\n                break;\n            case PROCEDURE:\n                lexer.reset(mark);\n                stmt = alterProcedure();\n                break;\n            case TABLESPACE:\n                lexer.reset(mark);\n                stmt = alterTableSpace();\n                break;\n            case SEQUENCE:\n                lexer.reset(mark);\n                stmt = alterSequence();\n                break;\n            case FULLTEXT:\n                lexer.reset(mark);\n                stmt = alterFullText();\n                break;\n            case IDENTIFIER:\n                if (lexer.identifierEquals(FnvHash.Constants.MATERIALIZED)) {\n                    stmt = alterMaterialized();\n                } else if (lexer.identifierEquals(Constants.RESOURCE)) {\n                    lexer.reset(mark);\n                    stmt = alterResourceGroup();\n                } else if (lexer.identifierEquals(Constants.EVENT)) {\n                    lexer.reset(mark);\n                    stmt = alterEvent();\n                } else {\n                    stmt = alterRest(mark);\n                }\n                break;\n            default:\n                stmt = alterRest(mark);\n                break;\n        }\n\n        if (comments != null) {\n            stmt.addBeforeComment(comments);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterRest(Lexer.SavePoint mark) {\n        throw new ParserException(\"unsupported ALTER statement. \" + lexer.info());\n    }\n\n    protected SQLStatement alterEvent() {\n        throw new ParserException(\"ALTER EVENT is not supported for current dialect. \" + lexer.info());\n    }\n\n    public SQLStatement alterUser() {\n        throw new ParserException(\"ALTER USER is not supported for current dialect. \" + lexer.info());\n    }\n\n    protected SQLStatement alterView() {\n        accept(ALTER);\n        accept(VIEW);\n        SQLName viewName = this.exprParser.name();\n\n        if (lexer.nextIfIdentifier(Constants.RENAME)) {\n            SQLAlterViewRenameStatement stmt = new SQLAlterViewRenameStatement();\n            stmt.setName(viewName);\n            accept(Token.TO);\n            stmt.setTo(\n                    exprParser.name()\n            );\n\n            if (lexer.identifierEquals(\"CHANGEOWNER\")) {\n                lexer.nextToken();\n                accept(TO);\n\n                stmt.setChangeOwnerTo(\n                        exprParser.name()\n                );\n            }\n\n            return stmt;\n        }\n\n        SQLAlterViewStatement alterView = new SQLAlterViewStatement(dbType);\n        alterView.setTableSource(new SQLExprTableSource(viewName));\n\n        for (; ; ) {\n            if (lexer.nextIf(SET)) {\n                acceptIdentifier(\"TBLPROPERTIES\");\n                this.exprParser.parseAssignItem(alterView.getOptions(), alterView);\n                continue;\n            }\n\n            if (lexer.nextIfIdentifier(\"UNSET\")) {\n                alterViewUnset(alterView);\n                continue;\n            }\n            break;\n        }\n\n        if (lexer.nextIf(AS) || lexer.token() == SELECT) {\n            if (lexer.token() == SELECT) {\n                alterView.setSubQuery(\n                        createSQLSelectParser()\n                                .select()\n                );\n                return alterView;\n            }\n        }\n        return alterView;\n    }\n\n    protected SQLAlterTableStatement createSQLAlterTableStatement() {\n        return new SQLAlterTableStatement(dbType);\n    }\n\n    protected SQLAlterStatement alterTable() {\n        SQLAlterTableStatement stmt = createSQLAlterTableStatement();\n\n        accept(ALTER);\n        alterTableBefore(stmt);\n        accept(TABLE);\n\n        if (lexer.token == ONLY) {\n            lexer.nextToken();\n            stmt.setOnly(true);\n        }\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        return alterTableAfterName(stmt);\n    }\n\n    protected void alterTableBefore(SQLAlterTableStatement stmt) {\n    }\n\n    protected boolean alterTableAfterNameRest(SQLAlterTableStatement stmt) {\n        return true;\n    }\n    protected SQLAlterStatement alterTableAfterName(SQLAlterTableStatement stmt) {\n        _for:\n        for (; ; ) {\n            switch (lexer.token) {\n                case DROP:\n                    parseAlterDrop(stmt);\n                    break;\n                case DISABLE:\n                    alterTableDisable(stmt);\n                    break;\n                case ENABLE:\n                    alterTableEnable(stmt);\n                    break;\n                case ALTER:\n                    alterTableAlter(stmt);\n                    break;\n                case DELETE:\n                    alterTableDelete(stmt);\n                    break;\n                case WITH:\n                    alterTableWith(stmt);\n                    break;\n                case SET:\n                    alterTableSet(stmt);\n                    break;\n                case PARTITION:\n                    alterTablePartition(stmt);\n                    break;\n                case TRUNCATE:\n                    alterTableTruncate(stmt);\n                    break;\n                case REPLACE:\n                    stmt.addItem(\n                            parseAlterTableReplaceColumn()\n                    );\n                    break;\n                default:\n                    if (lexer.identifierEquals(Constants.ADD)) {\n                        alterTableAdd(stmt);\n                    } else if (lexer.nextIfIdentifier(\"UNSET\")) {\n                        alterTableUnset(stmt);\n                    } else if (lexer.identifierEquals(\"VALIDATE\")) {\n                        lexer.nextToken();\n                        accept(Token.CONSTRAINT);\n                        SQLAlterTableValidateConstraint item = new SQLAlterTableValidateConstraint();\n                        item.setConstraintName(this.exprParser.name());\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(\"ATTACH\")) {\n                        alterTableAttach(stmt);\n                    } else if (lexer.identifierEquals(\"DETACH\")) {\n                        alterTableDetach(stmt);\n                    } else if (lexer.identifierEquals(Constants.CHANGE)) {\n                        alterTableChange(stmt);\n                    } else if (lexer.identifierEquals(Constants.EXCHANGE)) {\n                        alterTableExchange(stmt);\n                    } else if (lexer.identifierEquals(\"RENAME\")) {\n                        stmt.addItem(parseAlterTableRename());\n                    } else if (lexer.identifierEquals(\"TOUCH\")) {\n                        alterTableTouch(stmt);\n                    } else if (lexer.identifierEquals(Constants.ARCHIVE)) {\n                        alterTableAchive(stmt);\n                    } else if (lexer.identifierEquals(Constants.UNARCHIVE)) {\n                        alterTableUnarchive(stmt);\n                    } else if (lexer.identifierEquals(Constants.SUBPARTITION_AVAILABLE_PARTITION_NUM)) {\n                        lexer.nextToken();\n                        accept(Token.EQ);\n                        SQLIntegerExpr num = this.exprParser.integerExpr();\n                        SQLAlterTableSubpartitionAvailablePartitionNum item = new SQLAlterTableSubpartitionAvailablePartitionNum();\n                        item.setNumber(num);\n                        stmt.addItem(item);\n                    } else if (lexer.identifierEquals(\"CHANGEOWNER\")) {\n                        alterTableChangeOwner(stmt);\n                    } else if ((stmt.getClusteredBy().size() > 0 || stmt.getSortedBy().size() > 0) && lexer.token == Token.INTO) {\n                        lexer.nextToken();\n\n                        int num;\n                        if (lexer.token() == Token.LITERAL_INT) {\n                            num = lexer.integerValue().intValue();\n                            lexer.nextToken();\n                        } else {\n                            throw new ParserException(\"into buckets must be integer. \" + lexer.info());\n                        }\n\n                        if (lexer.identifierEquals(Constants.BUCKETS)) {\n                            stmt.setBuckets(num);\n                            lexer.nextToken();\n                        } else {\n                            acceptIdentifier(\"SHARDS\");\n                            stmt.setShards(num);\n                        }\n                    } else {\n                        if (alterTableAfterNameRest(stmt)) {\n                            break _for;\n                        }\n                    }\n                    break;\n            }\n        }\n\n        return stmt;\n    }\n\n    private void alterViewUnset(SQLAlterViewStatement alterView) {\n        acceptIdentifier(\"TBLPROPERTIES\");\n        accept(LPAREN);\n        this.exprParser.names(alterView.getUnsetOptions(), alterView);\n        accept(RPAREN);\n    }\n\n    protected void alterTableUnset(SQLAlterTableStatement stmt) {\n        throw new ParserException(\"ALTER TABLE ... UNSET is not supported for current dialect. \" + lexer.info());\n    }\n\n    protected void alterTableSorted(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.BY);\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n            stmt.addSortedByItem(item);\n            if (lexer.token() == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n    }\n\n    protected void alterTableMerge(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n\n        boolean ifExists = false;\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            ifExists = true;\n        }\n\n        if (lexer.token == PARTITION) {\n            SQLAlterTableMergePartition item = new SQLAlterTableMergePartition();\n            for (; ; ) {\n                item.addPartition(\n                        this.getExprParser().parsePartitionSpec()\n                );\n                if (lexer.token == COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n\n            accept(OVERWRITE);\n            item.setOverwritePartition(\n                    this.getExprParser().parsePartitionSpec()\n            );\n\n            if (ifExists) {\n                item.setIfExists(true);\n            }\n\n            if (lexer.identifierEquals(Constants.PURGE)) {\n                lexer.nextToken();\n                item.setPurge(true);\n            }\n\n            stmt.addItem(item);\n        } else {\n            acceptIdentifier(\"SMALLFILES\");\n            stmt.setMergeSmallFiles(true);\n        }\n    }\n\n    private void alterTableUnarchive(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n\n        accept(Token.PARTITION);\n\n        SQLAlterTableUnarchivePartition item = new SQLAlterTableUnarchivePartition();\n        accept(Token.LPAREN);\n        parseAssignItems(item.getPartitions(), item, false);\n        accept(Token.RPAREN);\n\n        stmt.addItem(item);\n    }\n\n    private void alterTableAchive(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n\n        if (lexer.token == PARTITION) {\n            lexer.nextToken();\n\n            SQLAlterTableArchivePartition item = new SQLAlterTableArchivePartition();\n            accept(Token.LPAREN);\n            parseAssignItems(item.getPartitions(), item, false);\n            accept(Token.RPAREN);\n            stmt.addItem(item);\n        }\n    }\n\n    protected void alterTableOwner(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        accept(TO);\n        SQLName name = this.exprParser.name();\n        SQLAlterTableChangeOwner changeOwner = new SQLAlterTableChangeOwner();\n        changeOwner.setOwner(name);\n\n        stmt.addItem(changeOwner);\n    }\n\n    private void alterTableTouch(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        SQLAlterTableTouch item = new SQLAlterTableTouch();\n\n        if (lexer.token == Token.PARTITION) {\n            lexer.nextToken();\n\n            accept(Token.LPAREN);\n            parseAssignItems(item.getPartition(), item);\n            accept(Token.RPAREN);\n        }\n\n        stmt.addItem(item);\n    }\n\n    protected void alterTableTruncate(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.nextIf(Token.PARTITION)) {\n            SQLAlterTableTruncatePartition item = new SQLAlterTableTruncatePartition();\n            if (lexer.nextIf(Token.FOR)) {\n                accept(Token.LPAREN);\n                do {\n                    item.addPartitionValue(exprParser.expr());\n                }\n                while (lexer.nextIf(Token.COMMA));\n                accept(Token.RPAREN);\n            } else {\n                item.addPartition(exprParser.name());\n            }\n            stmt.addItem(item);\n        }\n    }\n\n    private void alterTablePartition(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n\n        SQLAlterTableRenamePartition renamePartition = new SQLAlterTableRenamePartition();\n\n        accept(Token.LPAREN);\n\n        parseAssignItems(renamePartition.getPartition(), renamePartition);\n\n        accept(Token.RPAREN);\n\n        if (lexer.token == Token.ENABLE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"LIFECYCLE\")) {\n                lexer.nextToken();\n            }\n\n            SQLAlterTableEnableLifecycle enableLifeCycle = new SQLAlterTableEnableLifecycle();\n            for (SQLAssignItem condition : renamePartition.getPartition()) {\n                enableLifeCycle.getPartition().add(condition);\n                condition.setParent(enableLifeCycle);\n            }\n            stmt.addItem(enableLifeCycle);\n\n            return;\n        }\n\n        if (lexer.token == Token.DISABLE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"LIFECYCLE\")) {\n                lexer.nextToken();\n            }\n\n            SQLAlterTableDisableLifecycle disableLifeCycle = new SQLAlterTableDisableLifecycle();\n            for (SQLAssignItem condition : renamePartition.getPartition()) {\n                disableLifeCycle.getPartition().add(condition);\n                condition.setParent(disableLifeCycle);\n            }\n            stmt.addItem(disableLifeCycle);\n\n            return;\n        }\n\n        if (lexer.identifierEquals(\"MERGE\")) {\n            alterTablePartitionMerge(stmt, renamePartition);\n            return;\n        }\n        if (lexer.token == Token.SET) {\n            alterTablePartitionSet(stmt, renamePartition);\n            return;\n        }\n\n        if (lexer.identifierEquals(\"ARCHIVE\")) {\n            alterTablePartitionArchive(stmt, renamePartition);\n            return;\n        }\n\n        if (lexer.identifierEquals(Constants.ADD)) {\n            alterTableAdd(stmt);\n            return;\n        }\n\n        acceptIdentifier(\"RENAME\");\n        accept(Token.TO);\n        accept(Token.PARTITION);\n\n        accept(Token.LPAREN);\n\n        parseAssignItems(renamePartition.getTo(), renamePartition);\n\n        accept(Token.RPAREN);\n\n        stmt.addItem(renamePartition);\n    }\n\n    private static void alterTablePartitionArchive(SQLAlterTableStatement stmt,\n                                                   SQLAlterTableRenamePartition renamePartition) {\n        SQLAlterTableArchive archive = new SQLAlterTableArchive();\n        for (SQLAssignItem condition : renamePartition.getPartition()) {\n            archive.getPartition().add(condition);\n            condition.setParent(archive);\n        }\n        stmt.addItem(archive);\n    }\n\n    private static void alterTablePartitionMerge(SQLAlterTableStatement stmt,\n                                                 SQLAlterTableRenamePartition renamePartition) {\n        SQLAlterTablePartition alterTablePartition = new SQLAlterTablePartition();\n        for (SQLAssignItem condition : renamePartition.getPartition()) {\n            alterTablePartition.getPartition().add(condition);\n            condition.setParent(alterTablePartition);\n        }\n        stmt.addItem(alterTablePartition);\n    }\n\n    private void alterTablePartitionSet(SQLAlterTableStatement stmt, SQLAlterTableRenamePartition renamePartition) {\n        SQLAlterTablePartitionSetProperties alterTablePartition = new SQLAlterTablePartitionSetProperties();\n        for (SQLAssignItem condition : renamePartition.getPartition()) {\n            alterTablePartition.getPartition().add(condition);\n            condition.setParent(alterTablePartition);\n        }\n\n        accept(SET);\n        if (lexer.nextIfIdentifier(\"LOCATION\")) {\n            alterTablePartition.setLocation(\n                    exprParser.expr()\n            );\n        } else {\n            acceptIdentifier(\"PARTITIONPROPERTIES\");\n            accept(LPAREN);\n            this.parseAssignItems(alterTablePartition.getPartitionProperties(), alterTablePartition);\n            accept(RPAREN);\n        }\n        stmt.addItem(alterTablePartition);\n    }\n\n    protected boolean alterTableSetRest(SQLAlterTableStatement stmt) {\n        return true;\n    }\n    protected void alterTableSet(SQLAlterTableStatement stmt) {\n        accept(SET);\n        if (lexer.token == TABLESPACE) {\n            lexer.nextToken();\n            SQLAlterTableSetTableSpace setTableSapce = new SQLAlterTableSetTableSpace();\n            setTableSapce.setTableSpaceName(this.exprParser.primary());\n            stmt.addItem(setTableSapce);\n        } else if (lexer.token == Token.SCHEMA) {\n            lexer.nextToken();\n            SQLAlterTableSetSchema setSchema = new SQLAlterTableSetSchema();\n            setSchema.setSchemaName(this.exprParser.primary());\n            stmt.addItem(setSchema);\n        } else if (lexer.token == Token.COMMENT) {\n            lexer.nextToken();\n            SQLAlterTableSetComment setComment = new SQLAlterTableSetComment();\n            setComment.setComment(this.exprParser.primary());\n            stmt.addItem(setComment);\n        } else if (lexer.identifierEquals(Constants.LIFECYCLE)) {\n            lexer.nextToken();\n            SQLAlterTableSetLifecycle setLifecycle = new SQLAlterTableSetLifecycle();\n            setLifecycle.setLifecycle(this.exprParser.primary());\n            stmt.addItem(setLifecycle);\n        } else if (lexer.identifierEquals(Constants.LOCATION)) {\n            lexer.nextToken();\n            SQLAlterTableSetLocation setLocation = new SQLAlterTableSetLocation();\n            setLocation.setLocation(this.exprParser.primary());\n            stmt.addItem(setLocation);\n        } else if (lexer.identifierEquals(Constants.TBLPROPERTIES)) {\n            alterTableSetTblProperties(stmt);\n        } else if (lexer.identifierEquals(\"SERDEPROPERTIES\")) {\n            alterTableSetSerdeProperties(stmt);\n        } else if (lexer.identifierEquals(FnvHash.Constants.SERDE)) {\n            lexer.nextToken();\n            SQLAlterTableSetSerde setTableSerde = new SQLAlterTableSetSerde();\n            setTableSerde.setSerde(this.exprParser.primary());\n\n            if (lexer.token == Token.WITH) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.SERDEPROPERTIES)) {\n                    lexer.nextToken();\n                    accept(Token.LPAREN);\n                    for (; ; ) {\n                        SQLAssignItem item = this.exprParser.parseAssignItem();\n                        setTableSerde.addSerdeProperties(item);\n                        if (lexer.token == Token.COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                    accept(Token.RPAREN);\n                }\n            }\n            stmt.addItem(setTableSerde);\n        } else {\n            if (alterTableSetRest(stmt)) {\n                throw new ParserException(\"unsupported ALTER TABLE SET option. \" + lexer.info());\n            }\n        }\n    }\n\n    protected void alterTableChangeOwner(SQLAlterTableStatement stmt) {\n        throw new ParserException(\"ALTER TABLE ... CHANGE OWNER is not supported for current dialect. \" + lexer.info());\n    }\n\n    protected void alterTableSetSerdeProperties(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"SERDEPROPERTIES\");\n        SQLAlterTableSetSerdeProperties setOption = new SQLAlterTableSetSerdeProperties();\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLAssignItem item = this.exprParser.parseAssignItem();\n            setOption.addSerdeProperties(item);\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        stmt.addItem(setOption);\n    }\n\n    protected void alterTableSetTblProperties(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        SQLAlterTableSetOption setOption = new SQLAlterTableSetOption();\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLAssignItem item = this.exprParser.parseAssignItem();\n            setOption.addOption(item);\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n        stmt.addItem(setOption);\n    }\n\n    protected void alterTableWith(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        acceptIdentifier(\"NOCHECK\");\n        acceptIdentifier(\"ADD\");\n        SQLConstraint check = this.exprParser.parseConstraint();\n\n        SQLAlterTableAddConstraint addCheck = new SQLAlterTableAddConstraint();\n        addCheck.setWithNoCheck(true);\n        addCheck.setConstraint(check);\n        stmt.addItem(addCheck);\n    }\n\n    private void alterTableExchange(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.PARTITION);\n\n        SQLAlterTableExchangePartition item = new SQLAlterTableExchangePartition();\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLExpr partition = this.exprParser.name();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n                SQLExpr value = this.exprParser.primary();\n                partition = new SQLAssignItem(partition, value);\n            }\n\n            item.addPartition(partition);\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n        accept(Token.RPAREN);\n\n        accept(Token.WITH);\n        accept(Token.TABLE);\n        SQLName table = this.exprParser.name();\n        item.setTable(table);\n\n        if (lexer.token == Token.WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"VALIDATION\");\n            item.setValidation(true);\n        } else if (lexer.identifierEquals(Constants.WITHOUT)) {\n            lexer.nextToken();\n            acceptIdentifier(\"VALIDATION\");\n            item.setValidation(false);\n        }\n\n        stmt.addItem(item);\n    }\n\n    private void alterTableChange(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token == Token.COLUMN) {\n            lexer.nextToken();\n        }\n        SQLName columnName = this.exprParser.name();\n\n        if (lexer.identifierEquals(\"RENAME\")) {\n            lexer.nextToken();\n            accept(Token.TO);\n            SQLName toName = this.exprParser.name();\n            SQLAlterTableRenameColumn renameColumn = new SQLAlterTableRenameColumn();\n\n            renameColumn.setColumn(columnName);\n            renameColumn.setTo(toName);\n\n            stmt.addItem(renameColumn);\n        } else if (lexer.token == Token.COMMENT) {\n            lexer.nextToken();\n\n            SQLExpr comment;\n            if (lexer.token == Token.LITERAL_ALIAS) {\n                String alias = lexer.stringVal();\n                if (alias.length() > 2 && alias.charAt(0) == '\"' && alias.charAt(alias.length() - 1) == '\"') {\n                    alias = alias.substring(1, alias.length() - 1);\n                }\n                comment = new SQLCharExpr(alias);\n                lexer.nextToken();\n            } else {\n                comment = this.exprParser.primary();\n            }\n\n            SQLColumnDefinition column = new SQLColumnDefinition();\n            column.setDbType(dbType);\n            column.setName(columnName);\n            column.setComment(comment);\n\n            SQLAlterTableAlterColumn changeColumn = new SQLAlterTableAlterColumn();\n\n            changeColumn.setColumn(column);\n\n            stmt.addItem(changeColumn);\n        } else if (lexer.token == Token.NULL) {\n            lexer.nextToken();\n            stmt.addItem(\n                    new SQLAlterTableAddConstraint(\n                            new SQLNullConstraint()\n                    )\n            );\n        } else if (lexer.nextIfIdentifier(Constants.FIRST)) {\n            SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn();\n            alterColumn.setOriginColumn(columnName);\n            alterColumn.setFirst(true);\n            stmt.addItem(alterColumn);\n        } else {\n            SQLColumnDefinition column = this.exprParser.parseColumn();\n\n            SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn();\n            alterColumn.setColumn(column);\n            alterColumn.setOriginColumn(columnName);\n\n            if (lexer.identifierEquals(Constants.AFTER)) {\n                lexer.nextToken();\n                alterColumn.setAfter(\n                        this.exprParser.name()\n                );\n            } else if (lexer.identifierEquals(Constants.FIRST)) {\n                lexer.nextToken();\n                alterColumn.setFirst(true);\n            }\n\n            stmt.addItem(alterColumn);\n        }\n    }\n\n    private void alterTableDelete(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token == Token.WHERE) {\n            lexer.nextToken();\n\n            SQLAlterTableDeleteByCondition alterColumn = new SQLAlterTableDeleteByCondition();\n            alterColumn.setWhere(this.exprParser.expr());\n            stmt.addItem(alterColumn);\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n    }\n\n    protected void alterTableAlterComma() {\n    }\n    private void alterTableAlter(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token == Token.COLUMN) {\n            SQLAlterTableAlterColumn alterColumn = parseAlterColumn();\n            stmt.addItem(alterColumn);\n            alterTableAlterComma();\n        } else if (lexer.token == Token.LITERAL_ALIAS) {\n            SQLAlterTableAlterColumn alterColumn = parseAlterColumn();\n            stmt.addItem(alterColumn);\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n    }\n\n    private void alterTableAttach(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.PARTITION);\n        SQLAlterTableAttachPartition item = new SQLAlterTableAttachPartition();\n        item.setPartitionName(this.exprParser.name());\n        if (lexer.token() == DEFAULT) {\n            accept(Token.DEFAULT);\n            item.setDefaultFlag(true);\n        }\n        stmt.addItem(item);\n    }\n\n    private void alterTableDetach(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        accept(Token.PARTITION);\n        SQLAlterTableDetachPartition item = new SQLAlterTableDetachPartition();\n        item.setPartitionName(this.exprParser.name());\n        if (lexer.identifierEquals(\"CONCURRENTLY\")) {\n            lexer.nextToken();\n            item.setConcurrently(true);\n        }\n        if (lexer.identifierEquals(\"FINALIZE\")) {\n            lexer.nextToken();\n            item.setFinalize(true);\n        }\n        stmt.addItem(item);\n    }\n\n    private void alterTableEnable(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n        if (lexer.token == Token.CONSTRAINT) {\n            lexer.nextToken();\n            SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint();\n            item.setConstraintName(this.exprParser.name());\n            stmt.addItem(item);\n        } else if (lexer.identifierEquals(\"LIFECYCLE\")) {\n            lexer.nextToken();\n            SQLAlterTableEnableLifecycle item = new SQLAlterTableEnableLifecycle();\n            stmt.addItem(item);\n        } else {\n            acceptIdentifier(\"KEYS\");\n            SQLAlterTableEnableKeys item = new SQLAlterTableEnableKeys();\n            stmt.addItem(item);\n        }\n    }\n\n    private void alterTableDisable(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n\n        if (lexer.token == Token.CONSTRAINT) {\n            lexer.nextToken();\n            SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint();\n            item.setConstraintName(this.exprParser.name());\n            stmt.addItem(item);\n        } else if (lexer.identifierEquals(\"LIFECYCLE\")) {\n            lexer.nextToken();\n            SQLAlterTableDisableLifecycle item = new SQLAlterTableDisableLifecycle();\n            stmt.addItem(item);\n        } else {\n            acceptIdentifier(\"KEYS\");\n            SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys();\n            stmt.addItem(item);\n        }\n    }\n\n    protected void alterTableAdd(SQLAlterTableStatement stmt) {\n        Lexer.SavePoint mark = lexer.mark();\n\n        acceptIdentifier(\"ADD\");\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n        }\n\n        switch (lexer.token) {\n            case COLUMN:\n                lexer.nextToken();\n                parseAlterTableAddColumn(stmt);\n                break;\n            case INDEX:\n            case KEY:\n            case FULLTEXT:\n                lexer.reset(mark);\n                alterTableAddIndex(stmt);\n                break;\n            case PRIMARY:\n            case UNIQUE:\n            case CHECK:\n            case FOREIGN:\n            case DEFAULT:\n            case CONSTRAINT: {\n                lexer.reset(mark);\n                alterTableAddConstraint(stmt);\n                break;\n            }\n            case PARTITION: {\n                lexer.reset(mark);\n                alterTableAddPartition(stmt);\n                break;\n            }\n            default:\n                lexer.reset(mark);\n                alterTableAddRest(stmt);\n        }\n    }\n\n    protected void alterTableAddIndex(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"ADD\");\n        SQLAlterTableAddIndex item = new SQLAlterTableAddIndex();\n        this.exprParser.parseIndex(item.getIndexDefinition());\n        stmt.addItem(item);\n    }\n\n    protected void alterTableAddConstraint(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"ADD\");\n        SQLConstraint constraint = this.exprParser.parseConstraint();\n        SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(constraint);\n        if (lexer.identifierEquals(\"NO\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"INHERIT\");\n            item.setNoInherit(true);\n        }\n        if (lexer.token == Token.NOT) {\n            lexer.nextToken();\n            acceptIdentifier(\"VALID\");\n            item.setNotValid(true);\n        }\n        stmt.addItem(item);\n    }\n\n    protected void alterTableAddRestSpecific(SQLAlterTableStatement stmt) {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    protected void alterTableAddRest(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"ADD\");\n        if (lexer.token == Token.IDENTIFIER) {\n            SQLAlterTableAddColumn item = parseAlterTableAddColumn();\n            stmt.addItem(item);\n            return;\n        }\n        alterTableAddRestSpecific(stmt);\n    }\n\n    protected void alterTableAddPartition(SQLAlterTableStatement stmt) {\n        acceptIdentifier(\"ADD\");\n\n        boolean ifNotExists = false;\n        if (lexer.nextIf(Token.IF)) {\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            ifNotExists = true;\n        }\n\n        for (; ; ) {\n            lexer.nextToken();\n            SQLAlterTableAddPartition addPartition = new SQLAlterTableAddPartition();\n\n            addPartition.setIfNotExists(ifNotExists);\n\n            accept(Token.LPAREN);\n\n            parseAssignItems(addPartition.getPartitions(), addPartition, false);\n\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(Constants.LOCATION)) {\n                lexer.nextToken();\n                SQLExpr location = this.exprParser.primary();\n                addPartition.setLocation(location);\n            }\n\n            stmt.addItem(addPartition);\n\n            if (lexer.token == Token.PARTITION) {\n                continue;\n            }\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"ADD\") || lexer.token == Token.PARTITION) {\n                    continue;\n                }\n            }\n\n            break;\n        }\n    }\n\n    protected SQLStatement alterFullText() {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    protected SQLStatement alterDatabase() {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    protected SQLStatement alterSchema() {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    protected SQLAlterTableItem parseAlterTableRename() {\n        acceptIdentifier(\"RENAME\");\n\n        if (lexer.token == Token.COLUMN) {\n            lexer.nextToken();\n            SQLAlterTableRenameColumn renameColumn = new SQLAlterTableRenameColumn();\n            renameColumn.setColumn(this.exprParser.name());\n            accept(Token.TO);\n            renameColumn.setTo(this.exprParser.name());\n            return renameColumn;\n        } else if (lexer.token == Token.CONSTRAINT) {\n            lexer.nextToken();\n            SQLAlterTableRenameConstraint renameConstraint = new SQLAlterTableRenameConstraint();\n            renameConstraint.setConstraint(this.exprParser.name());\n            accept(Token.TO);\n            renameConstraint.setTo(this.exprParser.name());\n            return renameConstraint;\n        }\n\n        if (lexer.token == Token.TO) {\n            lexer.nextToken();\n            SQLAlterTableRename item = new SQLAlterTableRename();\n            item.setTo(this.exprParser.name());\n            return item;\n        }\n\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    protected SQLAlterTableAlterColumn parseAlterColumn() {\n        lexer.nextToken();\n        SQLColumnDefinition column = this.exprParser.parseColumn();\n\n        SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn();\n        alterColumn.setColumn(column);\n        return alterColumn;\n    }\n\n    public void parseAlterDropRest(SQLAlterTableStatement stmt, SQLAlterTableDropColumnItem item) {\n        boolean paren = false;\n        if (lexer.token == LPAREN) {\n            lexer.nextToken();\n            paren = true;\n        }\n        this.exprParser.names(item.getColumns());\n        if (paren) {\n            accept(RPAREN);\n        }\n\n        if (lexer.token == Token.CASCADE) {\n            item.setCascade(true);\n            lexer.nextToken();\n        }\n        if (RESTRICT == lexer.token) {\n            item.setRestrict(true);\n            lexer.nextToken();\n        }\n        stmt.addItem(item);\n    }\n    public void parseAlterDrop(SQLAlterTableStatement stmt) {\n        lexer.nextToken();\n\n        boolean ifExists = false;\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n\n            accept(Token.EXISTS);\n            ifExists = true;\n        }\n\n        if (lexer.token == Token.CONSTRAINT) {\n            lexer.nextToken();\n            SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint();\n            if (lexer.token == Token.IF) {\n                lexer.nextToken();\n                accept(Token.EXISTS);\n                item.setIfExists(true);\n            }\n            item.setConstraintName(this.exprParser.name());\n            if (lexer.token == RESTRICT) {\n                lexer.nextToken();\n                item.setRestrict(true);\n            } else if (lexer.token == CASCADE) {\n                lexer.nextToken();\n                item.setCascade(true);\n            }\n            stmt.addItem(item);\n        } else if (lexer.token == Token.COLUMN || lexer.identifierEquals(Constants.COLUMNS)) {\n            lexer.nextToken();\n            SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem();\n            if (lexer.token == Token.IF) {\n                lexer.nextToken();\n                accept(Token.EXISTS);\n                item.setIfExists(true);\n            }\n\n            parseAlterDropRest(stmt, item);\n        } else if (lexer.token == Token.LITERAL_ALIAS) {\n            SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem();\n            this.exprParser.names(item.getColumns());\n\n            if (lexer.token == Token.CASCADE) {\n                item.setCascade(true);\n                lexer.nextToken();\n            }\n\n            stmt.addItem(item);\n        } else if (lexer.token == Token.PARTITION) {\n            {\n                SQLAlterTableDropPartition dropPartition = parseAlterTableDropPartition(ifExists);\n                stmt.addItem(dropPartition);\n            }\n\n            while (lexer.token == COMMA) {\n                lexer.nextToken();\n                Lexer.SavePoint mark = lexer.mark();\n                if (lexer.token == Token.PARTITION) {\n                    SQLAlterTableDropPartition dropPartition = parseAlterTableDropPartition(ifExists);\n                    stmt.addItem(dropPartition);\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n\n        } else if (lexer.token == Token.INDEX) {\n            lexer.nextToken();\n            SQLName indexName = this.exprParser.name();\n            SQLAlterTableDropIndex item = new SQLAlterTableDropIndex();\n            item.setIndexName(indexName);\n            stmt.addItem(item);\n        } else if (lexer.token == Token.PRIMARY) {\n            lexer.nextToken();\n            accept(Token.KEY);\n            SQLAlterTableDropPrimaryKey item = new SQLAlterTableDropPrimaryKey();\n            stmt.addItem(item);\n        } else {\n            throw new ParserException(\"TODO \" + lexer.info());\n        }\n    }\n\n    protected SQLAlterTableDropPartition parseAlterTableDropPartition(boolean ifExists) {\n        lexer.nextToken();\n        SQLAlterTableDropPartition dropPartition = new SQLAlterTableDropPartition();\n\n        dropPartition.setIfExists(ifExists);\n\n        if (lexer.token == Token.LPAREN) {\n            accept(Token.LPAREN);\n            this.exprParser.exprList(dropPartition.getPartitions(), dropPartition);\n            accept(Token.RPAREN);\n\n            if (lexer.identifierEquals(\"PURGE\")) {\n                lexer.nextToken();\n                dropPartition.setPurge(true);\n            }\n        } else {\n            for (; ; ) {\n                SQLExpr partition = this.exprParser.expr();\n                dropPartition.addPartition(partition);\n                if (lexer.token == COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                break;\n            }\n            dropPartition.getAttributes().put(\"SIMPLE\", true);\n        }\n\n        return dropPartition;\n    }\n\n    protected SQLAlterTableDropSubpartition parseAlterTableDropSubpartition() {\n        lexer.nextToken();\n        SQLAlterTableDropSubpartition item = new SQLAlterTableDropSubpartition();\n\n        if (lexer.token() == Token.LITERAL_INT) {\n            for (; ; ) {\n                item.getPartitionIds().add(this.exprParser.integerExpr());\n                String pidStr = lexer.stringVal();\n                accept(Token.VARIANT);\n                String s = pidStr.replaceAll(\":\", \"\");\n                if (StringUtils.isEmpty(s)) {\n                    item.getSubpartitionIds().add(exprParser.integerExpr());\n                } else {\n                    item.getSubpartitionIds().add(new SQLIntegerExpr(Integer.valueOf(s)));\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n\n                break;\n            }\n        }\n\n        return item;\n    }\n\n    public SQLStatement parseRename() {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    public SQLStatement parseList() {\n        if (lexer.identifierEquals(Constants.LIST)) {\n            this.lexer.nextToken();\n            if (lexer.identifierEquals(Constants.RESOURCE)) {\n                this.lexer.nextToken();\n                if (lexer.identifierEquals(Constants.GROUP) || lexer.token == GROUP) {\n                    this.lexer.nextToken();\n                    return new SQLListResourceGroupStatement();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    protected SQLDropTableStatement parseDropTable(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        SQLDropTableStatement stmt = new SQLDropTableStatement(getDbType());\n\n        if (lexer.identifierEquals(FnvHash.Constants.TEMPORARY)) {\n            lexer.nextToken();\n            stmt.setTemporary(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.PARTITIONED)) {\n            lexer.nextToken();\n            stmt.setDropPartition(true);\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.EXTERNAL)) {\n            lexer.nextToken();\n            stmt.setExternal(true);\n        }\n\n        if (lexer.token == TABLE) {\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(Constants.TABLES) && dialectFeatureEnabled(ParseDropTableTables)) {\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"expected token: TABLE.\");\n        }\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        for (; ; ) {\n            SQLName name = this.exprParser.name();\n            SQLExprTableSource tab;\n            if (lexer.token == Token.AS) {\n                lexer.nextToken();\n                String alias = this.exprParser.name().getSimpleName();\n                tab = new SQLExprTableSource(name, alias);\n            } else {\n                tab = new SQLExprTableSource(name);\n            }\n\n            stmt.addPartition(tab);\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        parseDropTableAfterName(stmt);\n\n        for (; ; ) {\n            if (lexer.identifierEquals(\"RESTRICT\")) {\n                lexer.nextToken();\n                stmt.setRestrict(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(FnvHash.Constants.CASCADE) || lexer.token == CASCADE) {\n                lexer.nextToken();\n                stmt.setCascade(true);\n\n                if (lexer.identifierEquals(\"CONSTRAINTS\")) { // for oracle\n                    lexer.nextToken();\n                }\n\n                continue;\n            }\n\n            if (lexer.token == Token.PURGE || lexer.identifierEquals(\"PURGE\")) {\n                lexer.nextToken();\n                stmt.setPurge(true);\n                continue;\n            }\n\n            break;\n        }\n\n        if (stmt.isDropPartition()) {\n            if (lexer.token() == Token.WHERE) {\n                lexer.nextToken();\n                SQLExpr where = this.exprParser.expr();\n                stmt.setWhere(where);\n            }\n\n        }\n\n        return stmt;\n    }\n\n    protected void parseDropTableAfterName(SQLDropTableStatement stmt) {\n        // for subclass to override\n    }\n\n    protected SQLDropSequenceStatement parseDropSequence(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        lexer.nextToken();\n\n        SQLName name = this.exprParser.name();\n\n        SQLDropSequenceStatement stmt = new SQLDropSequenceStatement(getDbType());\n        stmt.setName(name);\n        return stmt;\n    }\n\n    protected SQLDropTriggerStatement parseDropTrigger(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        lexer.nextToken();\n        SQLDropTriggerStatement stmt = new SQLDropTriggerStatement(getDbType());\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n\n        stmt.setName(name);\n        return stmt;\n    }\n\n    protected SQLDropViewStatement parseDropView(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        SQLDropViewStatement stmt = new SQLDropViewStatement(getDbType());\n\n        accept(Token.VIEW);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        for (; ; ) {\n            SQLName name = this.exprParser.name();\n            stmt.addPartition(new SQLExprTableSource(name));\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        if (lexer.identifierEquals(\"RESTRICT\")) {\n            lexer.nextToken();\n            stmt.setRestrict(true);\n        } else if (lexer.identifierEquals(FnvHash.Constants.CASCADE) || lexer.token == CASCADE) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"CONSTRAINTS\")) { // for oracle\n                lexer.nextToken();\n            }\n\n            stmt.setCascade(true);\n        }\n\n        return stmt;\n    }\n\n    protected SQLDropStatement parseDropSchema(boolean physical) {\n        SQLDropStatement stmt = parseDropDatabaseOrSchema(false);\n        if (physical) {\n            ((SQLDropDatabaseStatement) stmt).setPhysical(physical);\n        }\n        return stmt;\n    }\n\n    protected SQLDropStatement parseDropDatabaseOrSchema(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        SQLDropDatabaseStatement stmt = new SQLDropDatabaseStatement(getDbType());\n\n        if (lexer.token == Token.SCHEMA) {\n            lexer.nextToken();\n        } else {\n            accept(Token.DATABASE);\n        }\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setDatabase(name);\n\n        if (lexer.identifierEquals(FnvHash.Constants.RESTRICT)) {\n            lexer.nextToken();\n            stmt.setRestrict(true);\n        } else if (lexer.token == Token.CASCADE || lexer.identifierEquals(FnvHash.Constants.CASCADE)) {\n            lexer.nextToken();\n            stmt.setCascade(true);\n        } else {\n            stmt.setCascade(false);\n        }\n\n        return stmt;\n    }\n\n    protected void parserParameters(List<SQLParameter> parameters, SQLObject parent) {\n        if (lexer.token() == Token.RPAREN) {\n            return;\n        }\n\n        for (; ; ) {\n            SQLParameter parameter = new SQLParameter();\n\n            if (lexer.token() == Token.CURSOR) {\n                SQLDataTypeImpl dataType = new SQLDataTypeImpl();\n                lexer.computeRowAndColumn(dataType);\n\n                lexer.nextToken();\n\n                parameter.setName(this.exprParser.name());\n\n                accept(Token.IS);\n                SQLSelect select = this.createSQLSelectParser().select();\n\n                dataType.setName(\"CURSOR\");\n                parameter.setDataType(dataType);\n\n                parameter.setDefaultValue(new SQLQueryExpr(select));\n\n            } else if (lexer.token() == Token.IN || lexer.token() == Token.OUT || lexer.token() == Token.INOUT) {\n                if (lexer.token() == Token.IN) {\n                    parameter.setParamType(ParameterType.IN);\n                } else if (lexer.token() == Token.OUT) {\n                    parameter.setParamType(ParameterType.OUT);\n                } else if (lexer.token() == Token.INOUT) {\n                    parameter.setParamType(ParameterType.INOUT);\n                }\n                lexer.nextToken();\n\n                parameter.setName(this.exprParser.name());\n\n                parameter.setDataType(this.exprParser.parseDataType());\n            } else {\n                // default parameter type is in\n                parameter.setParamType(ParameterType.DEFAULT);\n                parameter.setName(this.exprParser.name());\n                if (lexer.token() != Token.COMMA && lexer.token() != Token.RPAREN) {\n                    parameter.setDataType(this.exprParser.parseDataType());\n                    if (lexer.token() == Token.COLONEQ) {\n                        lexer.nextToken();\n                        parameter.setDefaultValue(this.exprParser.expr());\n                    }\n                }\n            }\n\n            parameters.add(parameter);\n            if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) {\n                continue;\n            }\n\n            break;\n        }\n    }\n\n    protected SQLDropFunctionStatement parseDropFunction(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        SQLDropFunctionStatement stmt = new SQLDropFunctionStatement(getDbType());\n\n        accept(Token.FUNCTION);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n//在这里要判断是否带函数声明\n        if (lexer.token() == Token.LPAREN) { // match \"(\"\n            lexer.nextToken();\n            stmt.setParameters(new ArrayList<>());\n            parserParameters(stmt.getParameters(), stmt);\n            accept(Token.RPAREN); // match \")\"\n        }\n        return stmt;\n    }\n\n    protected SQLDropTableSpaceStatement parseDropTablespace(boolean acceptDrop) {\n        SQLDropTableSpaceStatement stmt = new SQLDropTableSpaceStatement(getDbType());\n\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            stmt.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        accept(Token.TABLESPACE);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) {\n            lexer.nextToken();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr engine = this.exprParser.primary();\n            stmt.setEngine(engine);\n        }\n\n        return stmt;\n    }\n\n    protected SQLDropProcedureStatement parseDropProcedure(boolean acceptDrop) {\n        if (acceptDrop) {\n            accept(Token.DROP);\n        }\n\n        SQLDropProcedureStatement stmt = new SQLDropProcedureStatement(getDbType());\n\n        accept(Token.PROCEDURE);\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    public SQLStatement parseTruncate() {\n        accept(Token.TRUNCATE);\n        if (!lexer.nextIf(Token.TABLE)) {\n            lexer.nextIfIdentifier(\"TABLE\");\n        }\n        SQLTruncateStatement stmt = new SQLTruncateStatement(getDbType());\n\n        if (lexer.nextIf(Token.ONLY)) {\n            stmt.setOnly(true);\n        }\n\n        if (lexer.nextIf(Token.IF)) {\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        for (; ; ) {\n            SQLName name = this.exprParser.name();\n            stmt.addTableSource(name);\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        if (lexer.token == Token.PARTITION) {\n            lexer.nextToken();\n\n            if (lexer.token == LPAREN) {\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLAssignItem item = this.exprParser.parseAssignItem();\n                    item.setParent(stmt);\n                    stmt.getPartitions().add(item);\n                    if (lexer.token == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            } else { // for adb\n                if (lexer.token == ALL) {\n                    lexer.nextToken();\n                    stmt.setPartitionAll(true);\n                } else {\n                    for (; ; ) {\n                        stmt.getPartitionsForADB().add(exprParser.integerExpr());\n                        if (lexer.token == COMMA) {\n                            lexer.nextToken();\n                            continue;\n                        }\n                        break;\n                    }\n                }\n            }\n        }\n\n        for (; ; ) {\n            if (lexer.token == Token.PURGE) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"SNAPSHOT\")) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"LOG\");\n                    stmt.setPurgeSnapshotLog(true);\n                } else {\n                    throw new ParserException(\"TODO : \" + lexer.token + \" \" + lexer.stringVal());\n                }\n                continue;\n            }\n\n            if (lexer.token == Token.RESTART) {\n                lexer.nextToken();\n                accept(Token.IDENTITY);\n                stmt.setRestartIdentity(Boolean.TRUE);\n                continue;\n            } else if (lexer.token == Token.SHARE) {\n                lexer.nextToken();\n                accept(Token.IDENTITY);\n                stmt.setRestartIdentity(Boolean.FALSE);\n                continue;\n            }\n\n            if (lexer.token == Token.CASCADE) {\n                lexer.nextToken();\n                stmt.setCascade(Boolean.TRUE);\n                continue;\n            } else if (lexer.token == Token.RESTRICT) {\n                lexer.nextToken();\n                stmt.setCascade(Boolean.FALSE);\n                continue;\n            }\n\n            if (lexer.token == Token.DROP) {\n                lexer.nextToken();\n                acceptIdentifier(\"STORAGE\");\n                stmt.setDropStorage(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"REUSE\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"STORAGE\");\n                stmt.setReuseStorage(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"IGNORE\")) {\n                lexer.nextToken();\n                accept(Token.DELETE);\n                acceptIdentifier(\"TRIGGERS\");\n                stmt.setIgnoreDeleteTriggers(true);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"RESTRICT\")) {\n                lexer.nextToken();\n                accept(Token.WHEN);\n                accept(Token.DELETE);\n                acceptIdentifier(\"TRIGGERS\");\n                stmt.setRestrictWhenDeleteTriggers(true);\n                continue;\n            }\n\n            if (lexer.token == Token.CONTINUE) {\n                lexer.nextToken();\n                accept(Token.IDENTITY);\n                continue;\n            }\n\n            if (lexer.identifierEquals(\"IMMEDIATE\")) {\n                lexer.nextToken();\n                stmt.setImmediate(true);\n                continue;\n            }\n\n            break;\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseInsert() {\n        SQLInsertStatement stmt = new SQLInsertStatement();\n\n        if (lexer.token == Token.INSERT) {\n            accept(Token.INSERT);\n        }\n\n        parseInsert0(stmt);\n        return stmt;\n    }\n\n    protected void parseInsert0(SQLInsertInto insertStatement) {\n        parseInsert0(insertStatement, true);\n    }\n\n    /**\n     * Impala dml support multiple place hint.\n     * First hint_clause isInsert is true, second hint_clause isInsert is false.\n     * ***************************************\n     * [with_clause]\n     *   INSERT [hint_clause] { INTO | OVERWRITE } [TABLE] table_name\n     *   [(column_list)]\n     *   [ PARTITION (partition_clause)]\n     * {\n     *     [hint_clause] select_statement\n     *   | VALUES (value [, value ...]) [, (value [, value ...]) ...]\n     * }\n     * ***************************************\n     */\n    protected void parseInsert0Hints(SQLInsertInto insertStatement, boolean isInsert) {\n    }\n\n    protected void parseInsertOverwrite(SQLInsertInto insertStatement) {\n        insertStatement.setOverwrite(true);\n    }\n    protected void parseInsert0(SQLInsertInto insertStatement, boolean acceptSubQuery) {\n        if (lexer.nextIf(OVERWRITE) || lexer.nextIfIdentifier(Constants.OVERWRITE)) {\n            parseInsertOverwrite(insertStatement);\n        } else if (lexer.nextIf(INTO)) {\n            insertStatement.setOverwrite(false);\n        }\n\n        SQLName tableName = this.exprParser.name();\n        insertStatement.setTableName(tableName);\n\n        if (lexer.token == Token.LITERAL_ALIAS) {\n            insertStatement.setAlias(tableAlias());\n        }\n\n        parseInsert0Hints(insertStatement, false);\n\n        if (lexer.token == Token.IDENTIFIER) {\n            insertStatement.setAlias(lexer.stringVal());\n            lexer.nextToken();\n        }\n\n        if (lexer.token == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLAssignItem ptExpr = new SQLAssignItem();\n                ptExpr.setTarget(this.exprParser.name());\n                if (lexer.token == Token.EQ || lexer.token == Token.EQEQ) {\n                    lexer.nextTokenValue();\n                    SQLExpr ptValue = this.exprParser.expr();\n                    ptExpr.setValue(ptValue);\n                }\n                insertStatement.addPartition(ptExpr);\n                if (!(lexer.token == (Token.COMMA))) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                }\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token == (Token.LPAREN)) {\n            lexer.nextToken();\n            parseInsertColumns(insertStatement);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token == Token.VALUES) {\n            lexer.nextToken();\n            for (; ; ) {\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n                    this.exprParser.exprList(values.getValues(), values);\n                    insertStatement.addValueCause(values);\n                    accept(Token.RPAREN);\n                } else { // oracle\n                    SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n                    SQLExpr value = this.exprParser.expr();\n                    values.addValue(value);\n                    insertStatement.addValueCause(values);\n                }\n\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                } else {\n                    break;\n                }\n            }\n        } else if (acceptSubQuery && (lexer.token == WITH || lexer.token == Token.SELECT || lexer.token == Token.LPAREN)) {\n            SQLSelect select = this.createSQLSelectParser().select();\n            insertStatement.setQuery(select);\n        } else if (lexer.identifierEquals(FnvHash.Constants.VALUE)) {\n            throw new ParserException(\"'values' expected, but 'value'. \" + lexer.info());\n        }\n    }\n\n    protected void parseInsertColumns(SQLInsertInto insert) {\n        this.exprParser.exprList(insert.getColumns(), insert);\n    }\n\n    public boolean parseStatementListDialect(List<SQLStatement> statementList) {\n        return false;\n    }\n\n    public SQLDropUserStatement parseDropUser() {\n        accept(Token.USER);\n\n        SQLDropUserStatement stmt = new SQLDropUserStatement(getDbType());\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n        for (; ; ) {\n            if (lexer.token == Token.IF) { // skip for adb\n                lexer.nextToken();\n                accept(Token.EXISTS);\n            }\n            SQLExpr expr = this.exprParser.expr();\n            stmt.addUser(expr);\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n\n        if (lexer.token == CASCADE) {\n            lexer.nextToken();\n            stmt.setCascade(true);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseDropIndex() {\n        accept(Token.INDEX);\n        SQLDropIndexStatement stmt = new SQLDropIndexStatement(getDbType());\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.EXISTS);\n            stmt.setIfExists(true);\n        }\n\n        stmt.setIndexName(this.exprParser.name());\n\n        if (lexer.token == Token.ON) {\n            lexer.nextToken();\n            stmt.setTableName(this.exprParser.name());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {\n            lexer.nextToken();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr algorithm = this.exprParser.primary();\n            stmt.setAlgorithm(algorithm);\n        }\n\n        if (lexer.token == Token.LOCK) {\n            lexer.nextToken();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr option = this.exprParser.primary();\n            stmt.setLockOption(option);\n        }\n        // for mysql\n        return stmt;\n    }\n\n    public SQLCallStatement parseCall() {\n        boolean brace = false;\n        if (lexer.token == Token.LBRACE) {\n            lexer.nextToken();\n            brace = true;\n        }\n\n        SQLCallStatement stmt = new SQLCallStatement(getDbType());\n\n        if (lexer.token == Token.QUES) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            stmt.setOutParameter(new SQLVariantRefExpr(\"?\"));\n        }\n\n        acceptIdentifier(\"CALL\");\n\n        stmt.setProcedureName(exprParser.name());\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            exprParser.exprList(stmt.getParameters(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (brace) {\n            accept(Token.RBRACE);\n            stmt.setBrace(true);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseSet() {\n        accept(Token.SET);\n        SQLSetStatement stmt = new SQLSetStatement(getDbType());\n\n        parseAssignItems(stmt.getItems(), stmt);\n\n        return stmt;\n    }\n\n    public void parseAssignItems(List<? super SQLAssignItem> items, SQLObject parent) {\n        parseAssignItems(items, parent, true);\n    }\n\n    public void parseAssignItems(List<? super SQLAssignItem> items, SQLObject parent, boolean variant) {\n        exprParser.parseAssignItems(items, parent, variant);\n    }\n\n    public SQLPartitionRef parsePartitionRef() {\n        accept(Token.PARTITION);\n\n        SQLPartitionRef partitionRef = new SQLPartitionRef();\n\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            SQLIdentifierExpr name = (SQLIdentifierExpr) this.exprParser.name();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n                SQLExpr value = this.exprParser.expr();\n                partitionRef.addItem(name, value);\n            } else {\n                partitionRef.addItem(new SQLPartitionRef.Item(name));\n            }\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            } else {\n                break;\n            }\n        }\n\n        accept(Token.RPAREN);\n\n        return partitionRef;\n    }\n\n    public SQLStatement parseCreatePackage() {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    public SQLStatement parseCreate() {\n        Lexer.SavePoint mark = lexer.markOut();\n        accept(Token.CREATE);\n\n        createOptionSkip();\n\n        switch (lexer.token) {\n            case FOREIGN:\n            case TABLE:\n                lexer.reset(mark);\n                return parseCreateTable();\n            case INDEX:\n            case UNIQUE:\n                lexer.reset(mark);\n                return parseCreateIndex();\n            case SEQUENCE:\n                lexer.reset(mark);\n                return parseCreateSequence();\n            case DATABASE:\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"LINK\")) {\n                    lexer.reset(mark);\n                    return parseCreateDbLink();\n                }\n                lexer.reset(mark);\n                return parseCreateDatabase();\n            case SCHEMA:\n                lexer.reset(mark);\n                return parseCreateSchema();\n            case USER:\n                lexer.reset(mark);\n                return parseCreateUser();\n            case FUNCTION:\n                lexer.reset(mark);\n                return parseCreateFunction();\n            case VIEW:\n                lexer.reset(mark);\n                return parseCreateView();\n            case PROCEDURE:\n                lexer.reset(mark);\n                return parseCreateProcedure();\n            case TRIGGER:\n                lexer.reset(mark);\n                return parseCreateTrigger();\n            case TABLESPACE:\n                lexer.reset(mark);\n                return parseCreateTableSpace();\n            default:\n                if (lexer.identifierEquals(Constants.PUBLIC)) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(\"SYNONYM\")) {\n                        lexer.reset(mark);\n                        return parseCreateSynonym();\n                    } else {\n                        lexer.reset(mark);\n                        return parseCreateDbLink();\n                    }\n                } else if (lexer.identifierEquals(\"SHARE\")) {\n                    lexer.reset(mark);\n                    return parseCreateDbLink();\n                } else if (lexer.identifierEquals(\"SYNONYM\")) {\n                    lexer.reset(mark);\n                    return parseCreateSynonym();\n                } else if (lexer.identifierEquals(Constants.BITMAP)) {\n                    lexer.reset(mark);\n                    return parseCreateIndex();\n                } else if (lexer.identifierEquals(Constants.MATERIALIZED)) {\n                    lexer.reset(mark);\n                    return parseCreateMaterializedView();\n                } else if (lexer.identifierEquals(Constants.TYPE)) {\n                    lexer.reset(mark);\n                    return parseCreateType();\n                } else if (lexer.identifierEquals(Constants.TABLEGROUP)) {\n                    lexer.reset(mark);\n                    return parseCreateTableGroup();\n                } else if (lexer.identifierEquals(Constants.SQL) && dialectFeatureEnabled(ParseCreateSql)) {\n                    lexer.reset(mark);\n                    return parseCreateFunction();\n                } else if (lexer.identifierEquals(Constants.DIMENSION)) {\n                    lexer.reset(mark);\n                    return parseCreateTable();\n                } else if (lexer.identifierEquals(Constants.ROLE)) {\n                    lexer.reset(mark);\n                    return parseCreateRole();\n                } else if (lexer.identifierEquals(Constants.RESOURCE)) {\n                    lexer.reset(mark);\n                    return createResource();\n                } else if (lexer.identifierEquals(Constants.PACKAGE)) {\n                    lexer.reset(mark);\n                    return parseCreatePackage();\n                } else if (lexer.identifierEquals(Constants.EVENT)) {\n                    lexer.reset(mark);\n                    return parseCreateEvent();\n                } else if (lexer.identifierEquals(Constants.SERVER)) {\n                    lexer.reset(mark);\n                    return parseCreateServer();\n                } else if (lexer.identifierEquals(Constants.OUTLINE)) {\n                    lexer.reset(mark);\n                    return parseCreateOutline();\n                } else if (lexer.identifierEquals(Constants.EXTERNAL)) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(Constants.CATALOG)) {\n                        lexer.reset(mark);\n                        return parseCreateExternalCatalog();\n                    }\n                    if (lexer.token == TABLE) {\n                        lexer.reset(mark);\n                        return parseCreateTable();\n                    }\n                    throw new ParserException(\"parse create error, \" + lexer.info());\n                } else if (lexer.identifierEquals(FnvHash.Constants.SCAN)) {\n                    lexer.reset(mark);\n                    return parseCreateScan();\n                } else if (lexer.identifierEquals(FnvHash.Constants.TABLE)) {\n                    lexer.reset(mark);\n                    return parseCreateTable();\n                } else if (lexer.identifierEquals(Constants.SET) || lexer.identifierEquals(Constants.MULTISET) || lexer.identifierEquals(Constants.VOLATILE)) {\n                    lexer.reset(mark);\n                    return parseCreateTable();\n                } else if (lexer.identifierEquals(Constants.GLOBAL)) {\n                    lexer.nextToken();\n                    if (lexer.identifierEquals(Constants.TEMPORARY)) {\n                        lexer.reset(mark);\n                        return parseCreateTable();\n                    }\n                } else if (lexer.identifierEquals(Constants.MODEL)) {\n                    lexer.reset(mark);\n                    return parseCreateModel();\n                }\n\n                SQLStatement stmt = createTableRest(mark);\n                if (stmt == null) {\n                    throw new ParserException(\"parse create error, \" + lexer.info());\n                }\n                return stmt;\n        }\n    }\n\n    protected void createOptionSkip() {\n        if (lexer.nextIf(OR)) {\n            accept(REPLACE);\n            lexer.nextIfIdentifier(Constants.FORCE);\n        }\n\n        lexer.nextIfIdentifier(Constants.GLOBAL);\n\n        if (lexer.identifierEquals(Constants.TEMPORARY)\n                || lexer.token == Token.TEMPORARY\n                || lexer.identifierEquals(\"TEMP\")\n        ) {\n            lexer.nextToken();\n        }\n        lexer.nextIfIdentifier(\"TRANSACTIONAL\");\n        lexer.nextIfIdentifier(Constants.NONCLUSTERED);\n    }\n\n    protected SQLStatement createTableRest(Lexer.SavePoint mark) {\n        return null;\n    }\n\n    public SQLStatement parseCreateScan() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    protected SQLStatement parseCreateModel() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    public SQLStatement parseCreateRole() {\n        accept(Token.CREATE);\n        acceptIdentifier(\"ROLE\");\n        SQLName name = this.exprParser.name();\n\n        SQLCreateRoleStatement stmt = new SQLCreateRoleStatement(dbType);\n        stmt.setName(name);\n\n        return stmt;\n    }\n\n    protected SQLStatement parseCreateTableSpace() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    protected SQLStatement parseCreateOutline() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    protected SQLStatement parseCreateServer() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    protected SQLStatement parseCreateEvent() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    public SQLStatement parseCreateType() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    public SQLStatement parseCreateTableGroup() {\n        accept(Token.CREATE);\n        acceptIdentifier(\"TABLEGROUP\");\n\n        SQLCreateTableGroupStatement stmt = new SQLCreateTableGroupStatement();\n\n        if (lexer.identifierEquals(Constants.IF)) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        if (lexer.token == Token.PARTITION || lexer.identifierEquals(\"PARTITION\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"NUM\");\n            SQLExpr num = this.exprParser.expr();\n            stmt.setPartitionNum(num);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseCreateUser() {\n        accept(Token.CREATE);\n        accept(Token.USER);\n\n        SQLCreateUserStatement stmt = new SQLCreateUserStatement();\n        stmt.setUser(this.exprParser.name());\n\n        acceptIdentifier(\"IDENTIFIED\");\n        accept(Token.BY);\n        stmt.setPassword(this.exprParser.primary());\n\n        return stmt;\n    }\n\n    public SQLCreateFunctionStatement parseCreateFunction() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    protected void parseCreateMaterializedViewRest(SQLCreateMaterializedViewStatement stmt) {\n        if (lexer.token == Token.PARTITION) {\n            SQLPartitionBy partitionBy = this.exprParser.parsePartitionBy();\n            stmt.setPartitionBy(partitionBy);\n        }\n    }\n    public SQLStatement parseCreateMaterializedView() {\n        accept(Token.CREATE);\n        acceptIdentifier(\"MATERIALIZED\");\n        accept(Token.VIEW);\n\n        SQLCreateMaterializedViewStatement stmt = new SQLCreateMaterializedViewStatement();\n\n        if (lexer.token == IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        parseCreateMaterializedViewRest(stmt);\n\n        for (; ; ) {\n            if (exprParser instanceof OracleExprParser) {\n                ((OracleExprParser) exprParser).parseSegmentAttributes(stmt);\n            }\n\n            if (lexer.identifierEquals(\"REFRESH\")) {\n                lexer.nextToken();\n                boolean refresh = false;\n                for (; ; ) {\n                    if (lexer.identifierEquals(\"FAST\")) {\n                        lexer.nextToken();\n                        stmt.setRefreshFast(true);\n\n                        refresh = true;\n                    } else if (lexer.identifierEquals(\"COMPLETE\")) {\n                        lexer.nextToken();\n                        stmt.setRefreshComplete(true);\n\n                        refresh = true;\n                    } else if (lexer.identifierEquals(Constants.FORCE)) {\n                        lexer.nextToken();\n                        stmt.setRefreshForce(true);\n\n                        refresh = true;\n                    } else if (lexer.token == Token.ON) {\n                        lexer.nextToken();\n                        if (lexer.token == Token.COMMIT || lexer.identifierEquals(Constants.COMMIT)) {\n                            lexer.nextToken();\n                            stmt.setRefreshOnCommit(true);\n                            refresh = true;\n                        } else if (lexer.identifierEquals(Constants.OVERWRITE)) {\n                            lexer.nextToken();\n                            stmt.setRefreshOnOverWrite(true);\n\n                            refresh = true;\n                        } else {\n                            acceptIdentifier(\"DEMAND\");\n                            stmt.setRefreshOnDemand(true);\n\n                            refresh = true;\n                        }\n                    } else if (lexer.identifierEquals(Constants.START)) {\n                        lexer.nextToken();\n                        accept(Token.WITH);\n                        SQLExpr startWith = this.exprParser.expr();\n                        stmt.setStartWith(startWith);\n                        stmt.setRefreshStartWith(true);\n\n                        refresh = true;\n                    } else if (lexer.identifierEquals(Constants.NEXT)) {\n                        lexer.nextToken();\n                        SQLExpr next = this.exprParser.expr();\n                        stmt.setNext(next);\n                        stmt.setRefreshNext(true);\n\n                        refresh = true;\n                    } else {\n                        break;\n                    }\n                }\n\n                if (!refresh) {\n                    throw new ParserException(\"refresh clause is empty. \" + lexer.info());\n                }\n\n            } else if (lexer.identifierEquals(\"BUILD\")) {\n                lexer.nextToken();\n\n                if (lexer.identifierEquals(\"IMMEDIATE\") || lexer.token == Token.IMMEDIATE) {\n                    lexer.nextToken();\n                    stmt.setBuildImmediate(true);\n                } else {\n                    accept(Token.DEFERRED);\n                    stmt.setBuildDeferred(true);\n                }\n            } else if (lexer.identifierEquals(\"PARALLEL\")) {\n                lexer.nextToken();\n                stmt.setParallel(true);\n                if (lexer.token == Token.LITERAL_INT) {\n                    stmt.setParallelValue(lexer.integerValue().intValue());\n                    lexer.nextToken();\n                }\n            } else if (lexer.identifierEquals(Constants.NOCACHE) || lexer.token == Token.NOCACHE) {\n                lexer.nextToken();\n                stmt.setCache(false);\n            } else if (lexer.identifierEquals(Constants.NOPARALLEL)) {\n                lexer.nextToken();\n                stmt.setParallel(false);\n            } else if (lexer.token == Token.WITH) {\n                lexer.nextToken();\n                acceptIdentifier(\"ROWID\");\n                stmt.setWithRowId(true);\n            } else {\n                break;\n            }\n        }\n\n        Boolean enableQueryRewrite = null;\n        if (lexer.token == Token.ENABLE) {\n            lexer.nextToken();\n            enableQueryRewrite = true;\n        }\n\n        if (lexer.token == Token.DISABLE) {\n            lexer.nextToken();\n            enableQueryRewrite = false;\n        }\n\n        if (enableQueryRewrite != null) {\n            acceptIdentifier(\"QUERY\");\n            acceptIdentifier(\"REWRITE\");\n            stmt.setEnableQueryRewrite(enableQueryRewrite);\n        }\n\n        accept(Token.AS);\n        SQLSelect select = this.createSQLSelectParser().select();\n        stmt.setQuery(select);\n\n        return stmt;\n    }\n\n    public SQLStatement parseCreateDbLink() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    public SQLStatement parseCreateSynonym() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    public SQLStatement parseCreateExternalCatalog() {\n        MySqlCreateExternalCatalogStatement stmt = new MySqlCreateExternalCatalogStatement();\n\n        if (lexer.token == Token.CREATE) {\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"EXTERNAL\");\n        acceptIdentifier(\"CATALOG\");\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        acceptIdentifier(\"PROPERTIES\");\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            SQLName key = this.exprParser.name();\n            accept(Token.EQ);\n            SQLName value = this.exprParser.name();\n\n            stmt.getProperties().put(key, value);\n\n            if (lexer.token == Token.RPAREN) {\n                accept(Token.RPAREN);\n                break;\n            }\n        }\n\n        if (lexer.token() == Token.COMMENT) {\n            lexer.nextToken();\n            SQLName comment = this.exprParser.name();\n            stmt.setComment(comment);\n        }\n\n        return stmt;\n    }\n\n    public SQLCreateStatement parseCreateTrigger() {\n        SQLCreateTriggerStatement stmt = new SQLCreateTriggerStatement(getDbType());\n\n        if (lexer.token == Token.CREATE) {\n            lexer.nextToken();\n\n            if (lexer.token == Token.OR) {\n                lexer.nextToken();\n                accept(Token.REPLACE);\n\n                stmt.setOrReplace(true);\n            }\n        }\n\n        if (lexer.identifierEquals(Constants.DEFINER)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLName definer = ((MySqlExprParser) this.exprParser).userName();\n            stmt.setDefiner(definer);\n\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                accept(Token.RPAREN);\n            }\n        }\n\n        accept(Token.TRIGGER);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.identifierEquals(Constants.BEFORE)) {\n            stmt.setTriggerType(TriggerType.BEFORE);\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(Constants.AFTER)) {\n            stmt.setTriggerType(TriggerType.AFTER);\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(Constants.INSTEAD)) {\n            lexer.nextToken();\n            accept(Token.OF);\n            stmt.setTriggerType(TriggerType.INSTEAD_OF);\n        }\n\n        for (; ; ) {\n            if (lexer.token == Token.INSERT) {\n                lexer.nextToken();\n                stmt.setInsert(true);\n            } else if (lexer.token == Token.UPDATE) {\n                lexer.nextToken();\n                stmt.setUpdate(true);\n\n                if (lexer.token == Token.OF) {\n                    lexer.nextToken();\n                    this.exprParser.names(stmt.getUpdateOfColumns(), stmt);\n                }\n            } else if (lexer.token == Token.DELETE) {\n                lexer.nextToken();\n                stmt.setDelete(true);\n            }\n\n            if (lexer.token == Token.COMMA\n                    || lexer.token == Token.OR) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        accept(Token.ON);\n        stmt.setOn(this.exprParser.name());\n\n        if (lexer.token == Token.FOR) {\n            lexer.nextToken();\n            acceptIdentifier(\"EACH\");\n            accept(Token.ROW);\n            stmt.setForEachRow(true);\n        }\n\n        if (lexer.token == Token.WHEN) {\n            lexer.nextToken();\n            SQLExpr condition = this.exprParser.expr();\n            stmt.setWhen(condition);\n        }\n\n        //for postgresql https://www.postgresql.org/docs/current/sql-createtrigger.html\n        if (lexer.identifierEquals(\"EXECUTE\")) {\n            lexer.nextToken();\n            String executeType = lexer.stringVal();\n            stmt.setExecuteType(executeType);\n            lexer.nextToken();\n            SQLExpr executeFunc = this.exprParser.expr();\n            stmt.setExecuteFunc(executeFunc);\n            return stmt;\n        }\n        List<SQLStatement> body = new ArrayList<>();\n        this.parseStatementList(body, 1);\n        if (body.isEmpty()) {\n            throw new ParserException(\"syntax error\");\n        }\n        stmt.setBody(body.get(0));\n        return stmt;\n    }\n\n    public SQLStatement parseBlock() {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n\n    public SQLStatement parseCreateSchema() {\n        return parseCreateDatabase();\n    }\n\n    public void parseCreateTableSupportSchema() {\n        accept(Token.DATABASE);\n    }\n    public SQLStatement parseCreateDatabase() {\n        accept(CREATE);\n        SQLCreateDatabaseStatement stmt = new SQLCreateDatabaseStatement(dbType);\n\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            stmt.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        if (lexer.token == Token.CREATE) {\n            lexer.nextToken();\n        }\n\n        parseCreateTableSupportSchema();\n\n        if (lexer.token == Token.IF || lexer.identifierEquals(\"IF\")) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token == Token.COMMENT) {\n            lexer.nextToken();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        if (lexer.identifierEquals(Constants.LOCATION)) {\n            lexer.nextToken();\n            SQLExpr location = this.exprParser.expr();\n            stmt.setLocation(location);\n        }\n\n        if (lexer.token == Token.WITH) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(Constants.DBPROPERTIES)) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                for (; ; ) {\n                    SQLAssignItem assignItem = this.exprParser.parseAssignItem();\n                    assignItem.setParent(stmt);\n                    stmt.getDbProperties().add(assignItem);\n\n                    if (lexer.token == Token.COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                    break;\n                }\n                accept(Token.RPAREN);\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        if (lexer.token == Token.COMMENT) {\n            lexer.nextToken();\n            if (lexer.token == Token.EQ) {\n                lexer.nextToken();\n            }\n            SQLExpr comment = this.exprParser.expr();\n            stmt.setComment(comment);\n        }\n\n        return stmt;\n    }\n\n    public SQLCreateProcedureStatement parseCreateProcedure() {\n        throw new ParserException(\"TODO \" + lexer.token);\n    }\n\n    public SQLCreateStatement parseCreateSequence() {\n        accept(Token.CREATE);\n        SQLCreateSequenceStatement stmt = new SQLCreateSequenceStatement();\n\n        if (lexer.token == Token.GROUP) {\n            lexer.nextToken();\n            stmt.setGroup(true);\n        } else if (lexer.identifierEquals(Constants.SIMPLE)) {\n            lexer.nextToken();\n            stmt.setSimple(true);\n            if (lexer.token == Token.WITH) {\n                lexer.nextToken();\n                accept(Token.CACHE);\n                stmt.setWithCache(true);\n            }\n        } else if (lexer.identifierEquals(Constants.TIME)) {\n            lexer.nextToken();\n            stmt.setTime(true);\n        }\n\n        accept(Token.SEQUENCE);\n\n        stmt.setDbType(dbType);\n        stmt.setName(this.exprParser.name());\n\n        for (; ; ) {\n            if (lexer.token() == Token.START || lexer.identifierEquals(Constants.START)) {\n                lexer.nextToken();\n                accept(Token.WITH);\n                stmt.setStartWith(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(Constants.INCREMENT)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                stmt.setIncrementBy(this.exprParser.expr());\n                continue;\n            } else if (lexer.token() == Token.CACHE || lexer.identifierEquals(Constants.CACHE)) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.TRUE);\n\n                if (lexer.token() == Token.LITERAL_INT) {\n                    stmt.setCacheValue(this.exprParser.primary());\n                }\n                continue;\n            } else if (lexer.token == Token.WITH) {\n                lexer.nextToken();\n                accept(Token.CACHE);\n                stmt.setCache(true);\n                continue;\n            } else if (lexer.token() == Token.NOCACHE || lexer.identifierEquals(Constants.NOCACHE)) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.ORDER) {\n                lexer.nextToken();\n                stmt.setOrder(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(\"NOORDER\")) {\n                lexer.nextToken();\n                stmt.setOrder(Boolean.FALSE);\n                continue;\n            } else if (lexer.identifierEquals(\"CYCLE\")) {\n                lexer.nextToken();\n                stmt.setCycle(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(Constants.NOCYCLE)) {\n                lexer.nextToken();\n                stmt.setCycle(Boolean.FALSE);\n                continue;\n            } else if (lexer.identifierEquals(\"MINVALUE\")) {\n                lexer.nextToken();\n                stmt.setMinValue(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"MAXVALUE\")) {\n                lexer.nextToken();\n                stmt.setMaxValue(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"NOMAXVALUE\")) {\n                lexer.nextToken();\n                stmt.setNoMaxValue(true);\n                continue;\n            } else if (lexer.identifierEquals(\"NOMINVALUE\")) {\n                lexer.nextToken();\n                stmt.setNoMinValue(true);\n                continue;\n            }\n            break;\n        }\n\n        if (lexer.identifierEquals(Constants.UNIT)) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(Constants.COUNT)) {\n                lexer.nextToken();\n                SQLExpr unitCount = this.exprParser.primary();\n                stmt.setUnitCount(unitCount);\n            }\n\n            if (lexer.token == Token.INDEX) {\n                lexer.nextToken();\n                SQLExpr unitIndex = this.exprParser.primary();\n                stmt.setUnitIndex(unitIndex);\n            }\n\n            if (lexer.hashLCase() == Constants.STEP) {\n                lexer.nextToken();\n                SQLExpr step = this.exprParser.primary();\n                stmt.setStep(step);\n            }\n\n        }\n\n        return stmt;\n    }\n\n    public SQLCreateIndexStatement parseCreateIndex() {\n        accept(Token.CREATE);\n        SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(getDbType());\n        if (lexer.token == Token.UNIQUE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(\"CLUSTERED\")) {\n                lexer.nextToken();\n                stmt.setType(\"UNIQUE CLUSTERED\");\n            } else if (lexer.identifierEquals(\"NONCLUSTERED\")) {\n                stmt.setType(\"UNIQUE NONCLUSTERED\");\n                lexer.nextToken();\n            } else {\n                stmt.setType(\"UNIQUE\");\n            }\n        } else if (lexer.token() == Token.FULLTEXT) {\n            stmt.setType(\"FULLTEXT\");\n            lexer.nextToken();\n        } else if (lexer.identifierEquals(\"NONCLUSTERED\")) {\n            stmt.setType(\"NONCLUSTERED\");\n            lexer.nextToken();\n        }\n\n        accept(Token.INDEX);\n\n        stmt.setName(this.exprParser.name());\n\n        accept(Token.ON);\n\n        stmt.setTable(this.exprParser.name());\n\n        accept(Token.LPAREN);\n\n        for (; ; ) {\n            SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem();\n            item.setParent(stmt);\n            stmt.addItem(item);\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n\n        return stmt;\n    }\n\n    public SQLCreateTableParser getSQLCreateTableParser() {\n        return new SQLCreateTableParser(this.exprParser);\n    }\n\n    public SQLStatement parseSelect() {\n        SQLSelectParser selectParser = createSQLSelectParser();\n        SQLSelect select = selectParser.select();\n        return new SQLSelectStatement(select, getDbType());\n    }\n\n    public SQLSelectParser createSQLSelectParser() {\n        return new SQLSelectParser(this.exprParser, selectListCache);\n    }\n\n    public SQLSelectParser createSQLSelectParser(SQLExprParser exprParser) {\n        return new SQLSelectParser(exprParser);\n    }\n\n    public void parseUpdateStatementPartition(SQLUpdateStatement updateStatement) {\n    }\n    public SQLUpdateStatement parseUpdateStatement() {\n        SQLUpdateStatement updateStatement = createUpdateStatement();\n\n        if (lexer.nextIf(UPDATE)) {\n            SQLTableSource tableSource = this.exprParser.createSelectParser().parseTableSource();\n            updateStatement.setTableSource(tableSource);\n        }\n\n        parseUpdateStatementPartition(updateStatement);\n\n        parseUpdateSet(updateStatement);\n\n        if (lexer.nextIf(FROM)) {\n            updateStatement.setFrom(this.createSQLSelectParser().parseTableSource());\n        }\n\n        if (lexer.token == (Token.WHERE)) {\n            lexer.nextToken();\n            updateStatement.setWhere(this.exprParser.expr());\n        }\n        updateStatement.setLimit(this.exprParser.parseLimit());\n        return updateStatement;\n    }\n\n    protected void parseUpdateSetComma() {\n    }\n    protected void parseUpdateSet(SQLUpdateStatement update) {\n        accept(Token.SET);\n\n        parseUpdateSetComma();\n\n        for (; ; ) {\n            SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n            update.addItem(item);\n\n            if (lexer.token != Token.COMMA) {\n                break;\n            }\n\n            lexer.nextToken();\n            if (lexer.token == WHERE) {\n                break;\n            }\n        }\n    }\n\n    protected SQLUpdateStatement createUpdateStatement() {\n        return new SQLUpdateStatement(getDbType());\n    }\n\n    public SQLDeleteStatement parseDeleteStatement() {\n        SQLDeleteStatement deleteStatement = new SQLDeleteStatement(getDbType());\n\n        if (lexer.nextIf(Token.DELETE)) {\n            lexer.nextIf(Token.FROM);\n\n            if (lexer.token == Token.COMMENT) {\n                lexer.nextToken();\n            }\n\n            SQLName tableName = exprParser.name();\n\n            deleteStatement.setTableName(tableName);\n            deleteStatement.setAlias(\n                    tableAlias()\n            );\n\n            if (lexer.token == Token.FROM) {\n                lexer.nextToken();\n                SQLTableSource tableSource = createSQLSelectParser().parseTableSource();\n                deleteStatement.setFrom(tableSource);\n            }\n        }\n\n        if (lexer.token == (Token.WHERE)) {\n            lexer.nextToken();\n            SQLExpr where = this.exprParser.expr();\n            deleteStatement.setWhere(where);\n        }\n\n        return deleteStatement;\n    }\n\n    public SQLCreateTableStatement parseCreateTable() {\n        return getSQLCreateTableParser()\n                .parseCreateTable();\n    }\n\n    public void parseCreateViewAfterName(SQLCreateViewStatement createView) {\n    }\n    public void parseCreateViewAtDataType(SQLColumnDefinition column, SQLName expr) {\n    }\n    public SQLCreateViewStatement parseCreateView() {\n        SQLCreateViewStatement createView = new SQLCreateViewStatement(getDbType());\n\n        if (lexer.token == Token.CREATE) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token == Token.OR) {\n            lexer.nextToken();\n            accept(Token.REPLACE);\n            createView.setOrReplace(true);\n        }\n\n        if (lexer.identifierEquals(\"ALGORITHM\")) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            String algorithm = lexer.stringVal();\n            createView.setAlgorithm(algorithm);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(Constants.DEFINER)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLName definer = (SQLName) ((MySqlExprParser) this.exprParser).userName();\n            createView.setDefiner(definer);\n        }\n\n        if (lexer.identifierEquals(Constants.SQL)) {\n            lexer.nextToken();\n            acceptIdentifier(\"SECURITY\");\n            String sqlSecurity = lexer.stringVal();\n            createView.setSqlSecurity(sqlSecurity);\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(Constants.FORCE)) {\n            lexer.nextToken();\n            createView.setForce(true);\n        }\n\n        lexer.nextIfIdentifier(Constants.GLOBAL);\n\n        if (lexer.nextIfIdentifier(Constants.TEMPORARY) || lexer.nextIfIdentifier(\"TEMP\")) {\n            createView.setTemporary(true);\n        }\n\n        this.accept(Token.VIEW);\n\n        if (lexer.token == Token.IF || lexer.identifierEquals(\"IF\")) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            createView.setIfNotExists(true);\n        }\n\n        createView.setName(exprParser.name());\n        parseCreateViewAfterName(createView);\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                if (lexer.token == Token.CONSTRAINT) {\n                    SQLTableConstraint constraint = (SQLTableConstraint) this.exprParser.parseConstraint();\n                    createView.addColumn(constraint);\n                } else if (lexer.token == Token.RPAREN) {\n                    break;\n                } else {\n                    SQLColumnDefinition column = new SQLColumnDefinition();\n                    column.setDbType(dbType);\n                    SQLName expr = this.exprParser.name();\n                    column.setName(expr);\n\n                    parseCreateViewAtDataType(column, expr);\n\n                    this.exprParser.parseColumnRest(column);\n\n                    if (lexer.token == Token.COMMENT) {\n                        lexer.nextToken();\n\n                        SQLExpr comment;\n                        if (lexer.token == Token.LITERAL_ALIAS) {\n                            String alias = lexer.stringVal();\n                            if (alias.length() > 2 && alias.charAt(0) == '\"' && alias.charAt(alias.length() - 1) == '\"') {\n                                alias = alias.substring(1, alias.length() - 1);\n                            }\n                            comment = new SQLCharExpr(alias);\n                            lexer.nextToken();\n                        } else {\n                            comment = this.exprParser.primary();\n                        }\n                        column.setComment(comment);\n                    }\n\n                    column.setParent(createView);\n                    createView.addColumn(column);\n                }\n\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                } else {\n                    break;\n                }\n            }\n\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(\"RETURNS\")) {\n            lexer.nextToken();\n            SQLVariantRefExpr varRef = (SQLVariantRefExpr) this.exprParser.expr();\n            createView.setReturns(varRef);\n            createView.setReturnsDataType(\n                    (SQLTableDataType) this.exprParser.parseDataType()\n            );\n        }\n\n        if (lexer.token == Token.COMMENT) {\n            lexer.nextToken();\n            SQLCharExpr comment = (SQLCharExpr) exprParser.primary();\n            createView.setComment(comment);\n        }\n\n        createViewAs(createView);\n\n        if (lexer.token == Token.WITH) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(\"CASCADED\")) {\n                createView.setWithCascaded(true);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"LOCAL\")) {\n                createView.setWithLocal(true);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(\"READ\")) {\n                lexer.nextToken();\n                accept(Token.ONLY);\n                createView.setWithReadOnly(true);\n            }\n\n            if (lexer.token == Token.CHECK) {\n                lexer.nextToken();\n                acceptIdentifier(\"OPTION\");\n                createView.setWithCheckOption(true);\n            }\n        }\n\n        return createView;\n    }\n\n    protected void createViewAs(SQLCreateViewStatement createView) {\n        if (lexer.token == Token.AS) {\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(Constants.BEGIN)) {\n            SQLBlockStatement block = (SQLBlockStatement) this.parseBlock();\n            createView.setScript(block);\n            return;\n        }\n        SQLSelectParser selectParser = this.createSQLSelectParser();\n        SQLSelect select;\n        if (lexer.token == VALUES) {\n            SQLTableSource tablesource = selectParser.parseTableSource();\n            if (tablesource instanceof SQLSelectQuery) {\n                select = new SQLSelect((SQLSelectQuery) tablesource);\n            } else {\n                SQLSelectQueryBlock queryBlock = selectParser.createSelectQueryBlock();\n                queryBlock.addSelectItem(new SQLAllColumnExpr());\n                queryBlock.setFrom(tablesource);\n                select = new SQLSelect(queryBlock);\n            }\n        } else {\n            select = selectParser.select();\n        }\n        createView.setSubQuery(select);\n    }\n\n    public SQLCommentStatement parseComment() {\n        accept(Token.COMMENT);\n        SQLCommentStatement stmt = new SQLCommentStatement();\n\n        accept(Token.ON);\n\n        if (lexer.token == Token.TABLE) {\n            stmt.setType(SQLCommentStatement.Type.TABLE);\n            lexer.nextToken();\n        } else if (lexer.token == Token.COLUMN) {\n            stmt.setType(SQLCommentStatement.Type.COLUMN);\n            lexer.nextToken();\n        } else if (lexer.token == INDEX) {\n            stmt.setType(SQLCommentStatement.Type.INDEX);\n            lexer.nextToken();\n        } else if (lexer.token == VIEW) {\n            stmt.setType(SQLCommentStatement.Type.VIEW);\n            lexer.nextToken();\n        }\n\n        stmt.setOn(this.exprParser.name());\n\n        accept(Token.IS);\n        stmt.setComment(this.exprParser.expr());\n\n        return stmt;\n    }\n\n    protected void parseAlterTableAddColumn(SQLAlterTableStatement stmt) {\n        stmt.addItem(\n                parseAlterTableAddColumn()\n        );\n    }\n\n    protected boolean parseAlterTableAddColumnBefore(SQLAlterTableAddColumn x) {\n        return false;\n    }\n\n    protected SQLAlterTableAddColumn parseAlterTableAddColumn() {\n        SQLAlterTableAddColumn item = new SQLAlterTableAddColumn();\n        boolean columns = parseAlterTableAddColumnBefore(item);\n\n        for (; ; ) {\n            SQLColumnDefinition columnDef = this.exprParser.parseColumn();\n            item.addColumn(columnDef);\n\n            if (lexer.token == Token.WITH) {\n                Lexer.SavePoint mark = lexer.mark();\n                lexer.nextToken();\n                if (lexer.token == Token.DEFAULT) {\n                    lexer.nextToken();\n                    SQLExpr defaultExpr = this.exprParser.expr();\n                    columnDef.setDefaultExpr(defaultExpr);\n                } else {\n                    lexer.reset(mark);\n                }\n            }\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(\"ADD\") || lexer.token() == Token.ALTER) {\n                    break;\n                }\n                continue;\n            }\n            break;\n        }\n\n        if (columns) {\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(Constants.RESTRICT)) {\n            lexer.nextToken();\n            item.setRestrict(true);\n        } else if (lexer.token() == Token.CASCADE || lexer.identifierEquals(Constants.CASCADE)) {\n            lexer.nextToken();\n            item.setCascade(true);\n        } else {\n            item.setCascade(false);\n        }\n\n        return item;\n    }\n\n    protected SQLAlterTableReplaceColumn parseAlterTableReplaceColumn() {\n        accept(Token.REPLACE);\n        acceptIdentifier(\"COLUMNS\");\n\n        SQLAlterTableReplaceColumn item = new SQLAlterTableReplaceColumn();\n\n        accept(Token.LPAREN);\n        for (; ; ) {\n            SQLColumnDefinition columnDef = this.exprParser.parseColumn();\n            item.addColumn(columnDef);\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(Constants.ADD)) {\n                    break;\n                }\n                continue;\n            }\n            break;\n        }\n        accept(Token.RPAREN);\n\n        return item;\n    }\n\n    public SQLStatement parseStatement() {\n        final SQLStatement ret = parseStatement0();\n\n        if (END_TOKEN_CHECKING_ENABLED) {\n            checkEndToken();\n        }\n\n        if (lexer.nextIf(SEMI)) {\n            ret.setAfterSemi(true);\n        }\n\n        return ret;\n    }\n\n    protected SQLStatement parseStatement0() {\n        final SQLStatement ret;\n        if (lexer.token == Token.SELECT) {\n            ret = this.parseSelect();\n        } else if (lexer.token == Token.INSERT) {\n            ret = this.parseInsert();\n        } else if (lexer.token == Token.UPDATE) {\n            ret = this.parseUpdateStatement();\n        } else if (lexer.token == Token.DELETE) {\n            ret = this.parseDeleteStatement();\n        } else {\n            final List<SQLStatement> list = new ArrayList<SQLStatement>(1);\n            this.parseStatementList(list, 1, null);\n            ret = list.get(0);\n        }\n        return ret;\n    }\n\n    private void checkEndToken() {\n        if (lexer.token != Token.EOF\n                && lexer.token != Token.SEMI\n                && lexer.token != expectedNextToken) {\n            // keep exception format consistent with parseStatementList method.\n            throw new ParserException(UNSUPPORT_TOKEN_MSG_PREFIX + lexer.info());\n        }\n    }\n\n    public void parseExplainFormatPartition(SQLExplainStatement explain) {\n    }\n\n    public void parseExplainFormatType(SQLExplainStatement explain) {\n    }\n    public SQLExplainStatement parseExplain() {\n        accept(Token.EXPLAIN);\n        if (lexer.identifierEquals(\"PLAN\")) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token == Token.FOR) {\n            lexer.nextToken();\n        }\n\n        SQLExplainStatement explain = new SQLExplainStatement(dbType);\n\n        if (lexer.token == Token.ANALYZE || lexer.identifierEquals(Constants.ANALYZE)) {\n            lexer.nextToken();\n            explain.setType(\"ANALYZE\");\n        }\n\n        if (lexer.token == Token.HINT) {\n            explain.setHints(this.exprParser.parseHints());\n        }\n\n        if (lexer.identifierEquals(Constants.EXTENDED)) {\n            lexer.nextToken();\n            explain.setExtended(true);\n        }\n\n        if (lexer.identifierEquals(Constants.DEPENDENCY)) {\n            lexer.nextToken();\n            explain.setDependency(true);\n        }\n\n        if (lexer.identifierEquals(Constants.AUTHORIZATION)) {\n            lexer.nextToken();\n            explain.setAuthorization(true);\n        }\n\n        parseExplainFormatPartition(explain);\n        parseExplainFormatType(explain);\n        explain.setStatement(parseStatement());\n        return explain;\n    }\n\n    protected SQLAlterTableAddClusteringKey parseAlterTableAddClusteringKey() {\n        lexer.nextToken();\n        SQLAlterTableAddClusteringKey item = new SQLAlterTableAddClusteringKey();\n        accept(Token.KEY);\n        item.setName(exprParser.name());\n        accept(LPAREN);\n        for (; ; ) {\n            item.getColumns().add(exprParser.name());\n            if (lexer.token == COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n            break;\n        }\n        accept(RPAREN);\n        return item;\n    }\n\n    /*\n    protected SQLAlterTableAddIndex parseAlterTableAddIndex() {\n        SQLAlterTableAddIndex item = new SQLAlterTableAddIndex();\n\n        if (lexer.token() == Token.FULLTEXT) {\n            lexer.nextToken();\n            item.setType(\"FULLTEXT\");\n        } else if (lexer.identifierEquals(Constants.SPATIAL)) {\n            lexer.nextToken();\n            item.setType(\"SPATIAL\");\n        } else if (lexer.identifierEquals(Constants.CLUSTERED)) {\n            lexer.nextToken();\n            item.setType(\"CLUSTERED\");\n        } else if (lexer.identifierEquals(Constants.ANN)) {\n            lexer.nextToken();\n            item.setType(\"ANN\");\n        }\n\n        if (lexer.identifierEquals(Constants.GLOBAL)) {\n            item.setGlobal(true);\n            lexer.nextToken();\n        }\n\n        if (lexer.token == Token.UNIQUE) {\n            item.setUnique(true);\n            lexer.nextToken();\n            if (lexer.token == Token.INDEX) {\n                lexer.nextToken();\n            } else if (lexer.token == Token.KEY) {\n                item.setKey(true);\n                lexer.nextToken();\n            }\n        } else {\n            if (lexer.token == Token.INDEX) {\n                accept(Token.INDEX);\n            } else if (lexer.token == Token.KEY) {\n                item.setKey(true);\n                accept(Token.KEY);\n            }\n        }\n\n        if (lexer.token != Token.LPAREN) {\n            item.setName(this.exprParser.name());\n\n            if (DbType.mysql == dbType) {\n                if (lexer.identifierEquals(\"HASHMAP\")) {\n                    lexer.nextToken();\n                    item.setHashMapType(true);\n                }\n                else if (lexer.identifierEquals(Constants.USING)) {\n                    lexer.nextToken();\n                    String indexType = lexer.stringVal;\n                    item.setType(indexType);\n                    accept(Token.IDENTIFIER);\n                }\n            }\n\n        }\n\n        this.exprParser.parseIndexRest(item);\n\n        if (dbType == DbType.mysql) {\n            for (; ; ) {\n                if (lexer.identifierEquals(Constants.DISTANCEMEASURE)\n                        || lexer.identifierEquals(Constants.ALGORITHM)\n                        || lexer.token == Token.LOCK) {\n                    String name = lexer.stringVal();\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n                    SQLExpr option = this.exprParser.primary();\n                    item.addOption(name, option);\n                } else {\n                    break;\n                }\n            }\n        }\n\n        if (DbType.mysql == dbType) {\n            if (lexer.identifierEquals(Constants.USING)) {\n                lexer.nextToken();\n                String indexType = lexer.stringVal;\n                item.setType(indexType);\n                accept(Token.IDENTIFIER);\n            }\n\n            if (lexer.identifierEquals(Constants.DBPARTITION)) {\n                SQLPartitionBy partitionClause = this.getSQLCreateTableParser().parsePartitionBy();\n                item.setDbPartitionBy(partitionClause);\n            }\n\n            if (lexer.identifierEquals(Constants.TBPARTITION)) {\n                lexer.nextToken();\n                accept(Token.BY);\n                SQLExpr expr = this.exprParser.expr();\n                if (lexer.identifierEquals(Constants.STARTWITH)) {\n                    lexer.nextToken();\n                    SQLExpr start = this.exprParser.primary();\n                    acceptIdentifier(\"ENDWITH\");\n                    SQLExpr end = this.exprParser.primary();\n                    expr = new SQLBetweenExpr(expr, start, end);\n                }\n                item.setTablePartitionBy(expr);\n            }\n\n            if (lexer.identifierEquals(Constants.TBPARTITIONS)) {\n                lexer.nextToken();\n                SQLExpr tbPartitions = this.exprParser.primary();\n                item.setTablePartitions(tbPartitions);\n            }\n        }\n\n        for (;;) {\n            if (lexer.token == Token.COMMENT) {\n                lexer.nextToken();\n                SQLExpr comment = this.exprParser.primary();\n                item.setComment(comment);\n            } else if (DbType.mysql == dbType) {\n                if (lexer.identifierEquals(Constants.KEY_BLOCK_SIZE)) {\n                    lexer.nextToken();\n                    if (lexer.token() == Token.EQ) {\n                        lexer.nextToken();\n                    }\n                    SQLExpr keyBlockSize = this.exprParser.primary();\n                    item.setKeyBlockSize(keyBlockSize);\n                } else if (lexer.token() == Token.WITH) {\n                    lexer.nextToken();\n                    acceptIdentifier(\"PARSER\");\n                    item.setParserName(lexer.stringVal);\n                    accept(Token.IDENTIFIER);\n                } else if (lexer.identifierEquals(Constants.USING)) {\n                    // Or index_type in index_option.\n                    lexer.nextToken();\n                    item.setType(lexer.stringVal);\n                    accept(Token.IDENTIFIER);\n                } else {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        return item;\n    }\n    */\n\n    /**\n     * Parses the SQL OPEN statement and returns the corresponding SQLOpenStatement object.\n     *\n     * @return the parsed SQLOpenStatement object representing the SQL OPEN statement\n     * @throws ParserException if an error occurs during parsing\n     */\n    public SQLOpenStatement parseOpen() {\n        SQLOpenStatement stmt = new SQLOpenStatement();\n        accept(Token.OPEN);\n\n        final SQLName cursorName;\n        if (lexer.token == Token.QUES) {\n            lexer.nextToken();\n            cursorName = new SQLIdentifierExpr(\"?\");\n        } else {\n            cursorName = exprParser.name();\n        }\n        stmt.setCursorName(cursorName);\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            this.exprParser.exprList(stmt.getColumns(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token == Token.FOR) {\n            lexer.nextToken();\n            if (lexer.token == Token.SELECT) {\n                SQLSelectParser selectParser = createSQLSelectParser();\n                SQLSelect select = selectParser.select();\n                SQLQueryExpr queryExpr = new SQLQueryExpr(select);\n                stmt.setFor(queryExpr);\n            } else if (lexer.token == Token.LITERAL_CHARS) {\n                String chars = lexer.stringVal;\n                SQLExprParser exprParser = SQLParserUtils.createExprParser(chars, dbType);\n                SQLSelectParser selectParser = this.createSQLSelectParser(exprParser);\n                SQLSelect select = selectParser.select();\n                SQLQueryExpr queryExpr = new SQLQueryExpr(select);\n                stmt.setFor(queryExpr);\n\n                lexer.nextToken();\n            } else if (lexer.token == Token.QUES) {\n                lexer.nextToken();\n                stmt.setFor(new SQLVariantRefExpr(\"?\"));\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        if (lexer.token == Token.USING) {\n            lexer.nextToken();\n            this.exprParser.exprList(stmt.getUsing(), stmt);\n        }\n\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n        return stmt;\n    }\n\n    public SQLFetchStatement parseFetch() {\n        accept(Token.FETCH);\n\n        SQLFetchStatement stmt = new SQLFetchStatement();\n        stmt.setCursorName(this.exprParser.name());\n\n        if (lexer.identifierEquals(\"BULK\")) {\n            lexer.nextToken();\n            acceptIdentifier(\"COLLECT\");\n            stmt.setBulkCollect(true);\n        }\n\n        accept(Token.INTO);\n        for (; ; ) {\n            stmt.getInto().add(this.exprParser.name());\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        if (lexer.token == Token.LIMIT) {\n            SQLLimit limit = this.exprParser.parseLimit();\n            stmt.setLimit(limit);\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement parseClose() {\n        SQLCloseStatement stmt = new SQLCloseStatement();\n        accept(Token.CLOSE);\n        stmt.setCursorName(exprParser.name());\n        accept(Token.SEMI);\n        stmt.setAfterSemi(true);\n        return stmt;\n    }\n\n    public boolean isParseCompleteValues() {\n        return parseCompleteValues;\n    }\n\n    public void setParseCompleteValues(boolean parseCompleteValues) {\n        this.parseCompleteValues = parseCompleteValues;\n    }\n\n    public int getParseValuesSize() {\n        return parseValuesSize;\n    }\n\n    public void setParseValuesSize(int parseValuesSize) {\n        this.parseValuesSize = parseValuesSize;\n    }\n\n    public SQLStatement parseMerge() {\n        if (lexer.identifierEquals(Constants.MERGE)) {\n            lexer.nextToken();\n        } else {\n            accept(Token.MERGE);\n        }\n\n        SQLMergeStatement stmt = new SQLMergeStatement();\n        stmt.setDbType(dbType);\n\n        parseHints(stmt.getHints());\n\n        mergeBeforeName();\n\n        if (lexer.token == Token.LPAREN) {\n            lexer.nextToken();\n            SQLSelect select = this.createSQLSelectParser().select();\n            SQLSubqueryTableSource tableSource = SQLSubqueryTableSource.fixParenthesized(new SQLSubqueryTableSource(select));\n            stmt.setInto(tableSource);\n            accept(Token.RPAREN);\n        } else {\n            stmt.setInto(exprParser.name());\n        }\n\n        stmt.getInto().setAlias(tableAlias());\n\n        if (lexer.identifierEquals(Constants.USING)) {\n            lexer.nextToken();\n        } else {\n            accept(Token.USING);\n        }\n\n        SQLTableSource using = this.createSQLSelectParser().parseTableSource();\n        stmt.setUsing(using);\n\n        accept(Token.ON);\n        stmt.setOn(exprParser.expr());\n\n        for (; ; ) {\n            if (!parseMergeWhen(stmt)) {\n                break;\n            }\n        }\n\n        SQLErrorLoggingClause errorClause = parseErrorLoggingClause();\n        stmt.setErrorLoggingClause(errorClause);\n\n        return stmt;\n    }\n\n    protected boolean parseMergeWhen(SQLMergeStatement stmt) {\n        if (!lexer.nextIf(WHEN)) {\n            return false;\n        }\n\n        boolean not = lexer.nextIf(NOT);\n        accept(MATCHED);\n\n        SQLName by = null;\n        if (lexer.nextIf(BY)) {\n            by = this.exprParser.name();\n        }\n\n        SQLExpr where = null;\n        if (lexer.nextIf(Token.AND)) {\n            where = this.exprParser.expr();\n        }\n\n        accept(THEN);\n\n        if (lexer.nextIf(Token.DO)) {\n            acceptIdentifier(\"NOTHING\");\n            stmt.addWhen(new SQLMergeStatement.WhenDoNothing(not, by, where));\n            return true;\n        }\n\n        if (lexer.nextIf(DELETE)) {\n            stmt.addWhen(new SQLMergeStatement.WhenDelete(not, by, where));\n            return true;\n        }\n\n        if (lexer.nextIf(UPDATE)) {\n            accept(SET);\n            SQLMergeStatement.WhenUpdate updateClause = new SQLMergeStatement.WhenUpdate(not, by, where);\n            for (; ; ) {\n                SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();\n\n                updateClause.addItem(item);\n                item.setParent(updateClause);\n\n                if (lexer.nextIf(Token.COMMA)) {\n                    continue;\n                }\n\n                break;\n            }\n\n            if (lexer.nextIf(Token.WHERE)) {\n                updateClause.setWhere(exprParser.expr());\n            }\n\n            stmt.addWhen(updateClause);\n\n            if (lexer.nextIf(DELETE)) {\n                SQLMergeStatement.WhenDelete whenDelete = new SQLMergeStatement.WhenDelete();\n                if (lexer.nextIf(Token.WHERE)) {\n                    whenDelete.setWhere(exprParser.expr());\n                }\n                stmt.addWhen(whenDelete);\n            }\n            return true;\n        }\n\n        accept(INSERT);\n        SQLMergeStatement.WhenInsert insertClause = new SQLMergeStatement.WhenInsert(not, by, where);\n\n        if (lexer.token == Token.LPAREN) {\n            accept(Token.LPAREN);\n            exprParser.exprList(insertClause.getColumns(), insertClause);\n            accept(Token.RPAREN);\n        }\n        if (lexer.nextIfIdentifier(\"ROW\") || lexer.nextIfIdentifier(\"*\") || lexer.nextIf(Token.STAR)) {\n            insertClause.setInsertRow(true);\n        } else {\n            accept(Token.VALUES);\n            accept(Token.LPAREN);\n            exprParser.exprList(insertClause.getValues(), insertClause);\n            accept(Token.RPAREN);\n            insertClause.setInsertRow(false);\n        }\n\n        if (lexer.token == Token.WHERE) {\n            lexer.nextToken();\n            insertClause.setWhere(exprParser.expr());\n        }\n\n        stmt.addWhen(insertClause);\n        return true;\n    }\n\n    protected void mergeBeforeName() {\n        accept(Token.INTO);\n    }\n\n    protected SQLErrorLoggingClause parseErrorLoggingClause() {\n        if (lexer.identifierEquals(\"LOG\")) {\n            SQLErrorLoggingClause errorClause = new SQLErrorLoggingClause();\n\n            lexer.nextToken();\n            accept(Token.ERRORS);\n            if (lexer.token == Token.INTO) {\n                lexer.nextToken();\n                errorClause.setInto(exprParser.name());\n            }\n\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n                errorClause.setSimpleExpression(exprParser.expr());\n                accept(Token.RPAREN);\n            }\n\n            if (lexer.token == Token.REJECT) {\n                lexer.nextToken();\n                accept(Token.LIMIT);\n                errorClause.setLimit(exprParser.expr());\n            }\n\n            return errorClause;\n        }\n        return null;\n    }\n\n    public void parseHints(List<SQLHint> hints) {\n        this.getExprParser().parseHints(hints);\n    }\n\n    public SQLStatement parseDescribe() {\n        if (lexer.token == Token.DESC || lexer.identifierEquals(\"DESCRIBE\")) {\n            lexer.nextToken();\n        } else {\n            throw new ParserException(\"expect DESC, actual \" + lexer.token);\n        }\n\n        SQLDescribeStatement stmt = new SQLDescribeStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token == Token.DATABASE) {\n            lexer.nextToken();\n            stmt.setObjectType(SQLObjectType.DATABASE);\n        } else if (lexer.token == Token.SCHEMA) {\n            lexer.nextToken();\n            stmt.setObjectType(SQLObjectType.SCHEMA);\n        } else if (lexer.token == FUNCTION) {\n            lexer.nextToken();\n            stmt.setObjectType(SQLObjectType.FUNCTION);\n        } else if (lexer.identifierEquals(\"ROLE\")) {\n            lexer.nextToken();\n            stmt.setObjectType(SQLObjectType.ROLE);\n        } else if (lexer.identifierEquals(\"PACKAGE\")) {\n            lexer.nextToken();\n            stmt.setObjectType(SQLObjectType.PACKAGE);\n        } else if (lexer.identifierEquals(\"INSTANCE\")) {\n            lexer.nextToken();\n            stmt.setObjectType(SQLObjectType.INSTANCE);\n        } else if (lexer.token == TABLE) {\n            lexer.nextToken();\n            stmt.setObjectType(SQLObjectType.TABLE);\n        }\n\n        if (lexer.identifierEquals(Constants.EXTENDED)) {\n            lexer.nextToken();\n            stmt.setExtended(true);\n        }\n\n        if (lexer.identifierEquals(Constants.FORMATTED)) {\n            lexer.nextToken();\n            stmt.setFormatted(true);\n        }\n\n        stmt.setObject(this.exprParser.name());\n\n        if (lexer.token == Token.IDENTIFIER) {\n            SQLName column = this.exprParser.name();\n            stmt.setColumn(column);\n        }\n\n        if (lexer.token == Token.PARTITION) {\n            lexer.nextToken();\n            this.accept(Token.LPAREN);\n            for (; ; ) {\n                stmt.getPartition().add(this.exprParser.expr());\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n                if (lexer.token == Token.RPAREN) {\n                    lexer.nextToken();\n                    break;\n                }\n            }\n        }\n\n        if (lexer.token == Token.IDENTIFIER && stmt.getColumn() == null) {\n            SQLName column = this.exprParser.name();\n            stmt.setColumn(column);\n        }\n\n        return stmt;\n    }\n\n    protected void parseWithQuerySkip() {\n    }\n\n    public SQLWithSubqueryClause parseWithQuery() {\n        SQLWithSubqueryClause withQueryClause = new SQLWithSubqueryClause();\n        if (lexer.hasComment() && lexer.isKeepComments()) {\n            withQueryClause.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        accept(Token.WITH);\n\n        if (lexer.token == Token.RECURSIVE || lexer.identifierEquals(\"RECURSIVE\")) {\n            lexer.nextToken();\n            withQueryClause.setRecursive(true);\n        }\n\n        for (; ; ) {\n            SQLWithSubqueryClause.Entry entry = new SQLWithSubqueryClause.Entry();\n            entry.setParent(withQueryClause);\n\n            if (lexer.hasComment() && lexer.isKeepComments()) {\n                entry.addBeforeComment(lexer.readAndResetComments());\n            }\n\n            String alias = this.lexer.stringVal();\n            lexer.nextToken();\n            entry.setAlias(alias);\n\n            if (lexer.token == Token.LPAREN) {\n                lexer.nextToken();\n\n                for (; ; ) {\n                    if (lexer.token == RPAREN) {\n                        break;\n                    }\n\n                    SQLName name = exprParser.name();\n                    parseWithQuerySkip();\n                    name.setParent(entry);\n                    entry.getColumns().add(name);\n                    if (lexer.token == COMMA) {\n                        lexer.nextToken();\n                        continue;\n                    }\n                }\n\n                accept(Token.RPAREN);\n            }\n\n            accept(Token.AS);\n            accept(Token.LPAREN);\n\n            switch (lexer.token) {\n                case VALUES:\n                case WITH:\n                case SELECT:\n                case LPAREN:\n                case FROM:\n                    entry.setSubQuery(\n                            this.createSQLSelectParser()\n                                    .select());\n                    break;\n                case INSERT:\n                    entry.setReturningStatement(\n                            this.parseInsert()\n                    );\n                    break;\n                case UPDATE:\n                    entry.setReturningStatement(\n                            this.parseUpdateStatement()\n                    );\n                    break;\n                case DELETE:\n                    entry.setReturningStatement(\n                            this.parseDeleteStatement()\n                    );\n                    break;\n                default:\n                    break;\n            }\n\n            accept(Token.RPAREN);\n\n            withQueryClause.addEntry(entry);\n\n            if (lexer.token == Token.COMMA) {\n                lexer.nextToken();\n                continue;\n            }\n\n            break;\n        }\n\n        return withQueryClause;\n    }\n\n    public SQLStatement parseEnd() {\n        throw new ParserException(\"TODO. \" + lexer.info());\n    }\n\n    public SQLStatement parseWith() {\n        SQLWithSubqueryClause with = this.parseWithQuery();\n\n        SQLStatement stmt = null;\n        if (lexer.token == Token.SELECT || lexer.token == Token.LPAREN) {\n            SQLSelectParser selectParser = createSQLSelectParser();\n            SQLSelect select = selectParser.select();\n            select.setWithSubQuery(with);\n            stmt = new SQLSelectStatement(select, dbType);\n        } else if (lexer.token == Token.INSERT) {\n            SQLInsertStatement insert = (SQLInsertStatement) this.parseInsert();\n            insert.setWith(with);\n            stmt = insert;\n        } else if (lexer.token == Token.UPSERT) {\n            SQLInsertStatement insert = (SQLInsertStatement) this.parseUpsert();\n            insert.setWith(with);\n            stmt = insert;\n        } else if (lexer.token == Token.FROM) {\n            HiveMultiInsertStatement insert = (HiveMultiInsertStatement) this.parseInsert();\n            insert.setWith(with);\n            stmt = insert;\n        } else if (lexer.token == UPDATE) {\n            SQLUpdateStatement update = this.parseUpdateStatement();\n            update.setWith(with);\n            stmt = update;\n        }\n\n        if (stmt != null) {\n            if (lexer.nextIf(SEMI)) {\n                stmt.setAfterSemi(true);\n            }\n            return stmt;\n        }\n\n        throw new ParserException(\"TODO. \" + lexer.info());\n    }\n\n    protected void parseValueClause(\n            List<SQLInsertStatement.ValuesClause> valueClauseList,\n            int columnSize,\n            SQLObject parent) {\n        parseValueClause(valueClauseList, null, 0, parent);\n    }\n\n    protected void parseValueClauseNative(\n            List<SQLInsertStatement.ValuesClause> valueClauseList,\n            List<SQLColumnDefinition> columnDefinitionList,\n            int columnSize,\n            SQLObject parent\n    ) {\n        final TimeZone timeZone = lexer.getTimeZone();\n        SQLInsertStatement.ValuesClause values;\n        for (int i = 0; ; ++i) {\n            int startPos = lexer.pos - 1;\n\n            if (lexer.token != Token.LPAREN) {\n                throw new ParserException(\"syntax error, expect ')', \" + lexer.info());\n            }\n//            lexer.nextTokenValue();\n\n            if (lexer.ch == '\\'') { // for performance\n                lexer.bufPos = 0;\n                lexer.scanString();\n            } else if (lexer.ch == '0') {\n                lexer.bufPos = 0;\n                if (lexer.charAt(lexer.pos + 1) == 'x') {\n                    lexer.scanChar();\n                    lexer.scanChar();\n                    lexer.scanHexaDecimal();\n                } else {\n                    lexer.scanNumber();\n                }\n            } else if (lexer.ch > '0' && lexer.ch <= '9') {\n                lexer.bufPos = 0;\n                lexer.scanNumber();\n            } else if (lexer.ch == '-' && lexer.charAt(lexer.pos + 1) != '-') {\n                lexer.scanNumber();\n            } else {\n                lexer.nextTokenValue();\n            }\n\n            if (lexer.token() != Token.RPAREN) {\n                List valueExprList;\n                if (columnSize > 0) {\n                    valueExprList = new ArrayList(columnSize);\n                } else {\n                    valueExprList = new ArrayList();\n                }\n                values = new SQLInsertStatement.ValuesClause(valueExprList, parent);\n\n                int funcExecCount = 0;\n                for (int j = 0; ; ++j) {\n                    SQLExpr expr = null;\n                    Object value = null;\n\n                    SQLColumnDefinition columnDefinition = null;\n                    if (columnDefinitionList != null && j < columnDefinitionList.size()) {\n                        columnDefinition = columnDefinitionList.get(j);\n                    }\n\n                    SQLDataType dataType = null;\n                    if (columnDefinition != null) {\n                        dataType = columnDefinition.getDataType();\n                    }\n\n                    switch (lexer.token) {\n                        case LITERAL_INT: {\n                            Number integerValue = lexer.integerValue();\n\n                            if (lexer.ch == ',') {\n                                lexer.ch = lexer.charAt(++lexer.pos);\n                                lexer.token = COMMA;\n                            } else {\n                                lexer.nextTokenCommaValue();\n                            }\n\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                expr = new SQLIntegerExpr(integerValue, values);\n                                expr = this.exprParser.exprRest(expr);\n                                expr.setParent(values);\n                            } else {\n                                value = integerValue;\n                            }\n                            break;\n                        }\n                        case LITERAL_CHARS: {\n                            String strVal = lexer.stringVal();\n\n                            if (lexer.ch == ',') {\n                                lexer.ch = lexer.charAt(++lexer.pos);\n                                lexer.token = COMMA;\n                            } else {\n                                lexer.nextTokenCommaValue();\n                            }\n\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                expr = new SQLCharExpr(strVal, values);\n                                expr = this.exprParser.exprRest(expr);\n                                expr.setParent(values);\n                            } else {\n                                value = strVal;\n                            }\n                            break;\n                        }\n                        case LITERAL_NCHARS: {\n                            String strVal = lexer.stringVal();\n\n                            if (lexer.ch == ',') {\n                                lexer.ch = lexer.charAt(++lexer.pos);\n                                lexer.token = COMMA;\n                            } else {\n                                lexer.nextTokenCommaValue();\n                            }\n\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                expr = new SQLNCharExpr(strVal, values);\n                                expr = this.exprParser.exprRest(expr);\n                                expr.setParent(values);\n                            } else {\n                                value = strVal;\n                            }\n                            break;\n                        }\n                        case LITERAL_FLOAT: {\n                            BigDecimal number = lexer.decimalValue();\n\n                            if (dataType != null\n                                    && dataType.nameHashCode64() == Constants.DECIMAL) {\n                                int precision = 0, scale = 0;\n                                List<SQLExpr> arguments = dataType.getArguments();\n                                if (arguments.size() > 0) {\n                                    SQLExpr arg0 = arguments.get(0);\n                                    if (arg0 instanceof SQLIntegerExpr) {\n                                        precision = ((SQLIntegerExpr) arg0).getNumber().intValue();\n                                    }\n                                }\n                                if (arguments.size() > 1) {\n                                    SQLExpr arg0 = arguments.get(1);\n                                    if (arg0 instanceof SQLIntegerExpr) {\n                                        scale = ((SQLIntegerExpr) arg0).getNumber().intValue();\n                                    }\n                                }\n\n                                if (number instanceof BigDecimal) {\n                                    number = MySqlUtils.decimal(number, precision, scale);\n                                }\n                            }\n\n                            if (lexer.ch == ',') {\n                                lexer.ch = lexer.charAt(++lexer.pos);\n                                lexer.token = COMMA;\n                            } else {\n                                lexer.nextTokenCommaValue();\n                            }\n\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                expr = new SQLDecimalExpr(number);\n                                expr = this.exprParser.exprRest(expr);\n                                expr.setParent(values);\n                            } else {\n                                value = number;\n                            }\n                            break;\n                        }\n                        case NULL: {\n                            lexer.nextTokenCommaValue();\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                expr = new SQLNullExpr(parent);\n                                expr = this.exprParser.exprRest(expr);\n                                expr.setParent(values);\n                            } else {\n                                value = null;\n                            }\n                            break;\n                        }\n                        case IDENTIFIER: {\n                            long hash = lexer.hashLCase();\n                            if (hash == Constants.DATE) {\n                                lexer.nextTokenValue();\n                                String strVal = lexer.stringVal();\n                                value = java.sql.Date.valueOf(strVal);\n                                lexer.nextTokenComma();\n                            } else if (hash == Constants.TIMESTAMP && timeZone != null) {\n                                lexer.nextTokenValue();\n                                String strVal = lexer.stringVal();\n                                value = new java.sql.Timestamp(MySqlUtils.parseDate(strVal, timeZone)\n                                        .getTime());\n                                lexer.nextTokenComma();\n                            } else if (hash == Constants.CURDATE\n                                    || hash == Constants.CUR_DATE\n                                    || hash == Constants.CURRENT_DATE) {\n                                lexer.nextTokenValue();\n\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextToken();\n                                    accept(Token.RPAREN);\n                                }\n\n                                if (now == null) {\n                                    now = new java.sql.Timestamp(System.currentTimeMillis());\n                                }\n\n                                if (currentDate == null) {\n                                    currentDate = new java.sql.Date(now.getTime());\n                                }\n                                value = currentDate;\n                                funcExecCount++;\n                            } else if ((hash == Constants.SYSDATE\n                                    || hash == Constants.NOW\n                                    || hash == Constants.CURRENT_TIMESTAMP)\n                                    && timeZone != null) {\n                                lexer.nextTokenValue();\n\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextToken();\n                                    accept(Token.RPAREN);\n                                }\n\n                                if (now == null) {\n                                    now = new java.sql.Timestamp(System.currentTimeMillis());\n                                }\n                                value = now;\n                                funcExecCount++;\n                            } else if (hash == Constants.UUID) {\n                                lexer.nextTokenLParen();\n                                accept(Token.LPAREN);\n                                accept(Token.RPAREN);\n                                value = UUID.randomUUID().toString();\n                                funcExecCount++;\n                            } else {\n                                value = null;\n                                Lexer.SavePoint mark = lexer.mark();\n                                expr = exprParser.expr();\n                                if (expr instanceof SQLName) {\n                                    lexer.reset(mark);\n                                    lexer.info();\n                                    throw new ParserException(\"insert value error, token \" + lexer.stringVal() + \", line \" + lexer.posLine + \", column \" + lexer.posColumn, lexer.posLine, lexer.posColumn);\n                                }\n                                expr.setParent(values);\n                            }\n                            break;\n                        }\n                        default:\n                            value = null;\n                            expr = exprParser.expr();\n                            expr.setParent(values);\n                            break;\n                    }\n\n                    if (expr != null) {\n                        expr.setParent(values);\n                        value = expr;\n                    }\n\n                    if (lexer.token == Token.COMMA) {\n                        valueExprList.add(value);\n\n                        if (lexer.ch == '\\'') { // for performance\n                            lexer.bufPos = 0;\n                            lexer.scanString();\n                        } else if (lexer.ch == '0') {\n                            lexer.bufPos = 0;\n                            if (lexer.charAt(lexer.pos + 1) == 'x') {\n                                lexer.scanChar();\n                                lexer.scanChar();\n                                lexer.scanHexaDecimal();\n                            } else {\n                                lexer.scanNumber();\n                            }\n                        } else if (lexer.ch > '0' && lexer.ch <= '9') {\n                            lexer.bufPos = 0;\n                            lexer.scanNumber();\n                        } else if (lexer.ch == '-' && lexer.charAt(lexer.pos + 1) != '-') {\n                            lexer.bufPos = 0;\n                            lexer.scanNumber();\n                        } else {\n                            lexer.nextTokenValue();\n                        }\n                        continue;\n                    } else if (lexer.token == Token.RPAREN) {\n                        valueExprList.add(value);\n                        break;\n                    } else {\n                        expr = this.exprParser.primaryRest(expr);\n                        if (lexer.token != Token.COMMA && lexer.token() != Token.RPAREN) {\n                            expr = this.exprParser.exprRest(expr);\n                        }\n                        expr.setParent(values);\n\n                        valueExprList.add(expr);\n                        if (lexer.token == Token.COMMA) {\n                            lexer.nextTokenValue();\n                            continue;\n                        } else {\n                            break;\n                        }\n                    }\n                }\n\n                if (funcExecCount == 0 && lexer.isEnabled(SQLParserFeature.KeepInsertValueClauseOriginalString)) {\n                    int endPos = lexer.pos();\n                    String orginalString = lexer.subString(startPos, endPos - startPos);\n                    values.setOriginalString(orginalString);\n                }\n            } else {\n                values = new SQLInsertStatement.ValuesClause(new ArrayList<SQLExpr>(0));\n            }\n\n            valueClauseList.add(values);\n\n            if (lexer.token != Token.RPAREN) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n\n            if (!parseCompleteValues && valueClauseList.size() >= parseValuesSize) {\n                lexer.skipToEOF();\n                break;\n            }\n\n            lexer.nextTokenComma();\n            while (lexer.token == Token.HINT) {\n                this.exprParser.parseHints();\n            }\n            if (lexer.token == Token.COMMA) {\n                lexer.nextTokenLParen();\n                if (values != null) {\n                    columnSize = values.getValues().size();\n                }\n                continue;\n            } else {\n                break;\n            }\n        }\n    }\n\n    public void parseValueClause(SQLInsertValueHandler valueHandler) throws SQLException {\n        for (; ; ) {\n            if (lexer.token != Token.LPAREN) {\n                throw new ParserException(\"syntax error, expect ')', \" + lexer.info());\n            }\n\n            if (lexer.ch == '\\'') { // for performance\n                lexer.bufPos = 0;\n                lexer.scanString();\n            } else if (lexer.ch == '0') {\n                lexer.bufPos = 0;\n                if (lexer.charAt(lexer.pos + 1) == 'x') {\n                    lexer.scanChar();\n                    lexer.scanChar();\n                    lexer.scanHexaDecimal();\n                } else {\n                    lexer.scanNumber();\n                }\n            } else if (lexer.ch > '0' && lexer.ch <= '9') {\n                lexer.bufPos = 0;\n                lexer.scanNumber();\n            } else if (lexer.ch == '-' && lexer.charAt(lexer.pos + 1) != '-') {\n                lexer.scanNumber();\n            } else {\n                lexer.nextTokenValue();\n            }\n\n            if (lexer.token() != Token.RPAREN) {\n                Object row = valueHandler.newRow();\n\n                for (int j = 0; ; ++j) {\n                    switch (lexer.token) {\n                        case LITERAL_INT: {\n                            Number number = lexer.integerValue();\n\n                            if (lexer.ch == ',') {\n                                lexer.ch = lexer.charAt(++lexer.pos);\n                                lexer.token = COMMA;\n                            } else {\n                                lexer.nextTokenCommaValue();\n                            }\n\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                throw new ParserException(\"insert value error, \" + lexer.info());\n                            }\n\n                            valueHandler.processInteger(row, j, number);\n                            break;\n                        }\n                        case LITERAL_CHARS:\n                        case LITERAL_NCHARS: {\n                            String strVal = lexer.stringVal();\n\n                            if (lexer.ch == ',') {\n                                lexer.ch = lexer.charAt(++lexer.pos);\n                                lexer.token = COMMA;\n                            } else {\n                                lexer.nextTokenCommaValue();\n                            }\n\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                throw new ParserException(\"insert value error, \" + lexer.info());\n                            }\n\n                            valueHandler.processString(row, j, strVal);\n                            break;\n                        }\n                        case LITERAL_FLOAT: {\n                            BigDecimal number = lexer.decimalValue();\n\n                            if (lexer.ch == ',') {\n                                lexer.ch = lexer.charAt(++lexer.pos);\n                                lexer.token = COMMA;\n                            } else {\n                                lexer.nextTokenCommaValue();\n                            }\n\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                throw new ParserException(\"insert value error, \" + lexer.info());\n                            }\n\n                            valueHandler.processDecimal(row, j, number);\n                            break;\n                        }\n                        case NULL: {\n                            lexer.nextTokenCommaValue();\n                            if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                                throw new ParserException(\"insert value error, \" + lexer.info());\n                            }\n\n                            valueHandler.processNull(row, j);\n                            break;\n                        }\n                        case TRUE:\n                            valueHandler.processBoolean(row, j, true);\n                            lexer.nextTokenComma();\n                            break;\n                        case FALSE:\n                            valueHandler.processBoolean(row, j, false);\n                            lexer.nextTokenComma();\n                            break;\n                        case IDENTIFIER: {\n                            long hash = lexer.hashLCase();\n                            if (hash == Constants.DATE) {\n                                lexer.nextTokenValue();\n                                String strVal = lexer.stringVal();\n                                valueHandler.processDate(row, j, strVal);\n                                lexer.nextTokenComma();\n                            } else if (hash == Constants.TIMESTAMP) {\n                                lexer.nextTokenValue();\n                                String strVal = lexer.stringVal();\n                                valueHandler.processTimestamp(row, j, strVal);\n                                lexer.nextTokenComma();\n                            } else if (hash == Constants.TIME) {\n                                lexer.nextTokenValue();\n                                String strVal = lexer.stringVal();\n                                valueHandler.processTime(row, j, strVal);\n                                lexer.nextTokenComma();\n                            } else if (hash == Constants.DECIMAL) {\n                                lexer.nextTokenValue();\n                                String strVal = lexer.stringVal();\n                                BigDecimal decimal = new BigDecimal(strVal);\n                                valueHandler.processDecimal(row, j, decimal);\n                                lexer.nextTokenComma();\n                            } else if (hash == Constants.CURDATE\n                                    || hash == Constants.CUR_DATE\n                                    || hash == Constants.CURRENT_DATE\n                                    || hash == Constants.SYSDATE) {\n                                lexer.nextTokenLParen();\n\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextToken();\n                                    accept(Token.RPAREN);\n                                }\n\n                                if (currentDate == null) {\n                                    currentDate = new java.sql.Date(now.getTime());\n                                }\n\n                                valueHandler.processDate(row, j, currentDate);\n                            } else if (hash == Constants.NOW\n                                    || hash == Constants.CURRENT_TIMESTAMP) {\n                                lexer.nextTokenLParen();\n\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextToken();\n                                    accept(Token.RPAREN);\n                                }\n\n                                if (now == null) {\n                                    now = new java.sql.Timestamp(System.currentTimeMillis());\n                                }\n\n                                valueHandler.processTimestamp(row, j, now);\n                            } else if (hash == Constants.UUID) {\n                                String funcName = lexer.stringVal();\n                                lexer.nextTokenLParen();\n\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextToken();\n                                    accept(Token.RPAREN);\n                                } else {\n                                    throw new ParserException(\"insert value error, \" + lexer.info());\n                                }\n\n                                if (now == null) {\n                                    now = new java.sql.Timestamp(System.currentTimeMillis());\n                                }\n\n                                valueHandler.processFunction(row, j, funcName, hash);\n                            } else if (hash == Constants.STR_TO_DATE || hash == Constants.DATE_PARSE) {\n                                String funcName = lexer.stringVal();\n                                lexer.nextTokenLParen();\n\n                                String strVal, format;\n                                if (lexer.token == Token.LPAREN) {\n                                    lexer.nextTokenValue();\n                                    strVal = lexer.stringVal();\n                                    lexer.nextTokenComma();\n                                    accept(Token.COMMA);\n                                    format = lexer.stringVal();\n                                    lexer.nextTokenValue();\n                                    accept(Token.RPAREN);\n                                } else {\n                                    throw new ParserException(\"insert value error, \" + lexer.info());\n                                }\n\n                                valueHandler.processFunction(row, j, funcName, hash, strVal, format);\n                            } else if (Constants.CLOTHES_FEATURE_EXTRACT_V1 == hash ||\n                                    Constants.CLOTHES_ATTRIBUTE_EXTRACT_V1 == hash ||\n                                    Constants.GENERIC_FEATURE_EXTRACT_V1 == hash ||\n                                    Constants.TEXT_FEATURE_EXTRACT_V1 == hash ||\n                                    Constants.FACE_FEATURE_EXTRACT_V1 == hash) {\n                                String funcName = lexer.stringVal();\n                                lexer.nextTokenLParen();\n\n                                String urlVal;\n                                if (Token.LPAREN == lexer.token) {\n                                    lexer.nextTokenValue();\n                                    urlVal = lexer.stringVal();\n                                    lexer.nextToken();\n                                    accept(Token.RPAREN);\n                                } else {\n                                    throw new ParserException(\"insert value error, \" + lexer.info());\n                                }\n\n                                valueHandler.processFunction(row, j, funcName, hash, urlVal);\n                            } else {\n                                throw new ParserException(\"insert value error, \" + lexer.info());\n                            }\n                            break;\n                        }\n                        default:\n                            throw new ParserException(\"insert value error, \" + lexer.info());\n                    }\n\n                    if (lexer.token == Token.COMMA) {\n                        if (lexer.ch == '\\'') { // for performance\n                            lexer.bufPos = 0;\n                            lexer.scanString();\n                        } else if (lexer.ch == '0') {\n                            lexer.bufPos = 0;\n                            if (lexer.charAt(lexer.pos + 1) == 'x') {\n                                lexer.scanChar();\n                                lexer.scanChar();\n                                lexer.scanHexaDecimal();\n                            } else {\n                                lexer.scanNumber();\n                            }\n                        } else if (lexer.ch > '0' && lexer.ch <= '9') {\n                            lexer.bufPos = 0;\n                            lexer.scanNumber();\n                        } else if (lexer.ch == '-' && lexer.charAt(lexer.pos + 1) != '-') {\n                            lexer.bufPos = 0;\n                            lexer.scanNumber();\n                        } else {\n                            lexer.nextTokenValue();\n                        }\n                        continue;\n                    } else if (lexer.token == Token.RPAREN) {\n                        break;\n                    } else {\n                        throw new ParserException(\"insert value error, \" + lexer.info());\n//\n//                        if (lexer.token == Token.COMMA) {\n//                            lexer.nextTokenValue();\n//                            continue;\n//                        } else {\n//                            break;\n//                        }\n                    }\n                } // for j\n\n                valueHandler.processRow(row);\n            }\n\n            if (lexer.token != Token.RPAREN) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n\n            lexer.nextTokenComma();\n            while (lexer.token == Token.HINT) {\n                this.exprParser.parseHints();\n            }\n            if (lexer.token == Token.COMMA) {\n                lexer.nextTokenLParen();\n                continue;\n            } else {\n                valueHandler.processComplete();\n                break;\n            }\n        }\n    }\n\n    protected void parseValueClause(\n            List<SQLInsertStatement.ValuesClause> valueClauseList,\n            List<SQLColumnDefinition> columnDefinitionList,\n            int columnSize,\n            SQLObject parent\n    ) {\n        final boolean optimizedForParameterized = lexer.isEnabled(SQLParserFeature.OptimizedForForParameterizedSkipValue);\n\n        SQLInsertStatement.ValuesClause values;\n        for (int i = 0; ; ++i) {\n            int startPos = lexer.pos - 1;\n\n            if (lexer.token == Token.ROW) {\n                lexer.nextToken();\n            }\n            if (lexer.token != Token.LPAREN) {\n                throw new ParserException(\"syntax error, expect ')', \" + lexer.info());\n            }\n//            lexer.nextTokenValue();\n\n            if (lexer.ch == '\\'') { // for performance\n                lexer.bufPos = 0;\n                lexer.scanString();\n            } else if (lexer.ch == '0') {\n                lexer.bufPos = 0;\n                if (lexer.charAt(lexer.pos + 1) == 'x') {\n                    lexer.scanChar();\n                    lexer.scanChar();\n                    lexer.scanHexaDecimal();\n                } else {\n                    lexer.scanNumber();\n                }\n            } else if (lexer.ch > '0' && lexer.ch <= '9') {\n                lexer.bufPos = 0;\n                lexer.scanNumber();\n            } else if (lexer.ch == '-' && lexer.charAt(lexer.pos + 1) != '-') {\n                lexer.bufPos = 0;\n                lexer.scanNumber();\n            } else {\n                lexer.nextTokenValue();\n            }\n\n            if (lexer.token() != Token.RPAREN) {\n                List valueExprList;\n                if (columnSize > 0) {\n                    valueExprList = new ArrayList(columnSize);\n                } else {\n                    valueExprList = new ArrayList();\n                }\n                values = new SQLInsertStatement.ValuesClause(valueExprList, parent);\n\n                for (int j = 0; ; ++j) {\n                    SQLExpr expr;\n\n                    SQLColumnDefinition columnDefinition = null;\n                    if (columnDefinitionList != null && j < columnDefinitionList.size()) {\n                        columnDefinition = columnDefinitionList.get(j);\n                    }\n\n                    SQLDataType dataType = null;\n                    if (columnDefinition != null) {\n                        dataType = columnDefinition.getDataType();\n                    }\n\n                    if (lexer.token == Token.LITERAL_INT) {\n                        if (optimizedForParameterized) {\n                            expr = new SQLVariantRefExpr(\"?\", values);\n                            values.incrementReplaceCount();\n                        } else {\n                            expr = new SQLIntegerExpr(lexer.integerValue(), values);\n                        }\n                        if (lexer.ch == ',') {\n                            lexer.ch = lexer.charAt(++lexer.pos);\n                            lexer.token = COMMA;\n                        } else {\n                            lexer.nextTokenCommaValue();\n                        }\n\n                        if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                            expr = this.exprParser.exprRest(expr);\n                            expr.setParent(values);\n                        }\n                    } else if (lexer.token == Token.LITERAL_CHARS) {\n                        if (optimizedForParameterized) {\n                            expr = new SQLVariantRefExpr(\"?\", values);\n                            values.incrementReplaceCount();\n                        } else {\n                            expr = new SQLCharExpr(lexer.stringVal(), values);\n                        }\n\n                        if (lexer.ch == ',') {\n                            lexer.ch = lexer.charAt(++lexer.pos);\n                            lexer.token = COMMA;\n                        } else {\n                            lexer.nextTokenCommaValue();\n                        }\n\n                        if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                            expr = this.exprParser.exprRest(expr);\n                            expr.setParent(values);\n                        }\n                    } else if (lexer.token == Token.LITERAL_NCHARS) {\n                        if (optimizedForParameterized) {\n                            expr = new SQLVariantRefExpr(\"?\", values);\n                            values.incrementReplaceCount();\n                        } else {\n                            expr = new SQLNCharExpr(lexer.stringVal(), values);\n                        }\n\n                        if (lexer.ch == ',') {\n                            lexer.ch = lexer.charAt(++lexer.pos);\n                            lexer.token = COMMA;\n                        } else {\n                            lexer.nextTokenCommaValue();\n                        }\n\n                        if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                            expr = this.exprParser.exprRest(expr);\n                            expr.setParent(values);\n                        }\n                    } else if (lexer.token == Token.LITERAL_FLOAT) {\n                        if (optimizedForParameterized) {\n                            expr = new SQLVariantRefExpr(\"?\", values);\n                            values.incrementReplaceCount();\n                        } else {\n                            SQLNumberExpr numberExpr = lexer.numberExpr(values);\n\n                            if (dataType != null\n                                    && dataType.nameHashCode64() == Constants.DECIMAL) {\n                                Number number = numberExpr.getNumber();\n\n                                int precision = 0, scale = 0;\n                                List<SQLExpr> arguments = dataType.getArguments();\n                                if (arguments.size() > 0) {\n                                    SQLExpr arg0 = arguments.get(0);\n                                    if (arg0 instanceof SQLIntegerExpr) {\n                                        precision = ((SQLIntegerExpr) arg0).getNumber().intValue();\n                                    }\n                                }\n                                if (arguments.size() > 1) {\n                                    SQLExpr arg0 = arguments.get(1);\n                                    if (arg0 instanceof SQLIntegerExpr) {\n                                        scale = ((SQLIntegerExpr) arg0).getNumber().intValue();\n                                    }\n                                }\n\n                                if (number instanceof BigDecimal) {\n                                    number = MySqlUtils.decimal((BigDecimal) number, precision, scale);\n                                    numberExpr.setNumber(number);\n                                }\n                            }\n\n                            expr = numberExpr;\n                        }\n\n                        if (lexer.ch == ',') {\n                            lexer.ch = lexer.charAt(++lexer.pos);\n                            lexer.token = COMMA;\n                        } else {\n                            lexer.nextTokenCommaValue();\n                        }\n\n                        if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                            expr = this.exprParser.exprRest(expr);\n                            expr.setParent(values);\n                        }\n                    } else if (lexer.token == Token.NULL) {\n                        if (optimizedForParameterized) {\n                            expr = new SQLVariantRefExpr(\"?\", parent);\n                            values.incrementReplaceCount();\n                        } else {\n                            expr = new SQLNullExpr(parent);\n                        }\n                        lexer.nextTokenCommaValue();\n                        if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {\n                            expr = this.exprParser.exprRest(expr);\n                            expr.setParent(values);\n                        }\n                    } else {\n                        expr = exprParser.expr();\n                        expr.setParent(values);\n                    }\n\n                    if (lexer.token == Token.COMMA) {\n                        valueExprList.add(expr);\n\n                        if (lexer.ch == '\\'') { // for performance\n                            lexer.bufPos = 0;\n                            lexer.scanString();\n                        } else if (lexer.ch == '0') {\n                            lexer.bufPos = 0;\n                            if (lexer.charAt(lexer.pos + 1) == 'x') {\n                                lexer.scanChar();\n                                lexer.scanChar();\n                                lexer.scanHexaDecimal();\n                            } else {\n                                lexer.scanNumber();\n                            }\n                        } else if (lexer.ch > '0' && lexer.ch <= '9') {\n                            lexer.bufPos = 0;\n                            lexer.scanNumber();\n                        } else if (lexer.ch == '-' && lexer.charAt(lexer.pos + 1) != '-') {\n                            lexer.bufPos = 0;\n                            lexer.scanNumber();\n                        } else {\n                            lexer.nextTokenValue();\n                        }\n                        continue;\n                    } else if (lexer.token == Token.RPAREN) {\n                        valueExprList.add(expr);\n                        break;\n                    } else {\n                        expr = this.exprParser.primaryRest(expr);\n                        if (lexer.token != Token.COMMA && lexer.token() != Token.RPAREN) {\n                            expr = this.exprParser.exprRest(expr);\n                        }\n                        expr.setParent(values);\n\n                        valueExprList.add(expr);\n                        if (lexer.token == Token.COMMA) {\n                            lexer.nextTokenValue();\n                            continue;\n                        } else {\n                            break;\n                        }\n                    }\n                }\n\n                if (lexer.isEnabled(SQLParserFeature.KeepInsertValueClauseOriginalString)) {\n                    int endPos = lexer.pos();\n                    String orginalString = lexer.subString(startPos, endPos - startPos);\n                    values.setOriginalString(orginalString);\n                }\n            } else {\n                values = new SQLInsertStatement.ValuesClause(new ArrayList<SQLExpr>(0));\n            }\n\n            valueClauseList.add(values);\n\n            if (lexer.token != Token.RPAREN) {\n                throw new ParserException(\"syntax error. \" + lexer.info());\n            }\n\n            if (!parseCompleteValues && valueClauseList.size() >= parseValuesSize) {\n                lexer.skipToEOF();\n                break;\n            }\n\n            lexer.nextTokenComma();\n            while (lexer.token == Token.HINT) {\n                this.exprParser.parseHints();\n            }\n            if (lexer.token == Token.COMMA) {\n                lexer.nextTokenLParen();\n                if (values != null) {\n                    columnSize = values.getValues().size();\n                }\n                continue;\n            } else {\n                break;\n            }\n        }\n    }\n\n    public SQLSelectListCache getSelectListCache() {\n        return selectListCache;\n    }\n\n    public void setSelectListCache(SQLSelectListCache selectListCache) {\n        this.selectListCache = selectListCache;\n    }\n\n    protected HiveInsertStatement parseHiveInsertStmt() {\n        HiveInsertStatement insert = new HiveInsertStatement();\n        insert.setDbType(dbType);\n\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            insert.addInsertBeforeComment(lexer.readAndResetComments());\n        }\n\n        SQLSelectParser selectParser = createSQLSelectParser();\n\n        accept(Token.INSERT);\n\n        if (lexer.token == Token.INTO) {\n            lexer.nextToken();\n        } else {\n            accept(Token.OVERWRITE);\n            insert.setOverwrite(true);\n        }\n\n        if (lexer.token == Token.TABLE) {\n            lexer.nextToken();\n        }\n        insert.setTableSource(this.exprParser.name());\n\n        boolean columnsParsed = false;\n\n        if (lexer.token == (Token.LPAREN)) {\n            Lexer.SavePoint mark = lexer.mark();\n            lexer.nextToken();\n            if (lexer.token == Token.SELECT || lexer.token == WITH) {\n                lexer.reset(mark);\n            } else {\n                parseInsertColumns(insert);\n                columnsParsed = true;\n                accept(Token.RPAREN);\n            }\n        }\n\n        if (lexer.token == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLAssignItem ptExpr = new SQLAssignItem();\n                ptExpr.setTarget(this.exprParser.name());\n                if (lexer.token == Token.EQ || lexer.token == Token.EQEQ) {\n                    lexer.nextTokenValue();\n                    SQLExpr ptValue = this.exprParser.expr();\n                    ptExpr.setValue(ptValue);\n                }\n                insert.addPartition(ptExpr);\n                if (!(lexer.token == (Token.COMMA))) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                }\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (!columnsParsed && lexer.token == Token.LPAREN) {\n            Lexer.SavePoint m1 = lexer.mark();\n\n            lexer.nextToken();\n            boolean select;\n            if (lexer.token == LPAREN) {\n                Lexer.SavePoint m2 = lexer.mark();\n                lexer.nextToken();\n                select = lexer.token == SELECT;\n                lexer.reset(m2);\n            } else {\n                select = lexer.token == SELECT || lexer.token == WITH;\n            }\n            if (!select) {\n                parseInsertColumns(insert);\n                accept(Token.RPAREN);\n            } else {\n                lexer.reset(m1);\n            }\n        }\n\n        if (lexer.token == Token.IF) {\n            lexer.nextToken();\n            accept(Token.NOT);\n            accept(Token.EXISTS);\n            insert.setIfNotExists(true);\n        }\n\n        if (lexer.token == Token.VALUES) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n                    this.exprParser.exprList(values.getValues(), values);\n                    insert.addValueCause(values);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                } else {\n                    break;\n                }\n            }\n        } else {\n            SQLSelect query = selectParser.select();\n            insert.setQuery(query);\n        }\n\n        return insert;\n    }\n\n    protected HiveInsert parseHiveInsert() {\n        HiveInsert insert = new HiveInsert();\n\n        if (lexer.isKeepComments() && lexer.hasComment()) {\n            insert.addBeforeComment(lexer.readAndResetComments());\n        }\n\n        SQLSelectParser selectParser = createSQLSelectParser();\n\n        accept(Token.INSERT);\n\n        if (lexer.token == Token.INTO) {\n            lexer.nextToken();\n        } else {\n            accept(Token.OVERWRITE);\n            insert.setOverwrite(true);\n        }\n\n        if (lexer.token == Token.TABLE) {\n            lexer.nextToken();\n        }\n        insert.setTableSource(this.exprParser.name());\n\n        if (lexer.token == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            for (; ; ) {\n                SQLAssignItem ptExpr = new SQLAssignItem();\n                ptExpr.setTarget(this.exprParser.name());\n                if (lexer.token == Token.EQ) {\n                    lexer.nextToken();\n                    SQLExpr ptValue = this.exprParser.expr();\n                    ptExpr.setValue(ptValue);\n                }\n                insert.addPartition(ptExpr);\n                if (lexer.token != Token.COMMA) {\n                    break;\n                } else {\n                    lexer.nextToken();\n                }\n            }\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.token == LPAREN) {\n            lexer.nextToken();\n            this.exprParser.exprList(insert.getColumns(), insert);\n            accept(RPAREN);\n        }\n\n        if (lexer.token == Token.VALUES) {\n            lexer.nextToken();\n\n            for (; ; ) {\n                if (lexer.token == Token.LPAREN) {\n                    lexer.nextToken();\n\n                    SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();\n                    this.exprParser.exprList(values.getValues(), values);\n                    insert.addValueCause(values);\n                    accept(Token.RPAREN);\n                }\n\n                if (lexer.token == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                } else {\n                    break;\n                }\n            }\n        } else {\n            SQLSelect query = selectParser.select();\n            insert.setQuery(query);\n        }\n\n        return insert;\n    }\n\n    protected SQLShowDatabasesStatement parseShowDatabases(boolean isPhysical) {\n        SQLShowDatabasesStatement stmt = new SQLShowDatabasesStatement();\n\n        stmt.setPhysical(isPhysical);\n        if (lexer.token == Token.LIKE) {\n            lexer.nextToken();\n            SQLExpr like = exprParser.expr();\n            stmt.setLike(like);\n        }\n\n        if (lexer.token == Token.WHERE) {\n            lexer.nextToken();\n            SQLExpr where = exprParser.expr();\n            stmt.setWhere(where);\n        }\n\n        if (lexer.identifierEquals(Constants.EXTRA)) {\n            lexer.nextToken();\n            stmt.setExtra(true);\n        }\n\n        return stmt;\n    }\n\n    protected SQLShowTableGroupsStatement parseShowTableGroups() {\n        SQLShowTableGroupsStatement stmt = new SQLShowTableGroupsStatement();\n\n        if (lexer.token == Token.IN) {\n            lexer.nextToken();\n            SQLName db = exprParser.name();\n            stmt.setDatabase(db);\n        }\n\n        return stmt;\n    }\n\n    protected SQLShowTablesStatement parseShowTables() {\n        SQLShowTablesStatement stmt = new SQLShowTablesStatement();\n\n        if (lexer.identifierEquals(Constants.SHOW)) {\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(Constants.TABLES)) {\n            lexer.nextToken();\n        }\n\n        if (lexer.identifierEquals(Constants.EXTENDED)) {\n            lexer.nextToken();\n            stmt.setExtended(true);\n        }\n\n        if (lexer.token == Token.FROM || lexer.token == Token.IN) {\n            lexer.nextToken();\n            SQLName database = exprParser.name();\n            if (lexer.token == Token.SUB && database instanceof SQLIdentifierExpr) {\n                lexer.mark();\n                lexer.nextToken();\n                String strVal = lexer.stringVal();\n                lexer.nextToken();\n                if (database instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr ident = (SQLIdentifierExpr) database;\n                    database = new SQLIdentifierExpr(ident.getName() + \"-\" + strVal);\n                }\n            }\n            stmt.setDatabase(database);\n        }\n\n        if (lexer.token == Token.LIKE) {\n            lexer.nextToken();\n            SQLExpr like = exprParser.expr();\n            stmt.setLike(like);\n        }\n\n        if (lexer.token == Token.WHERE) {\n            lexer.nextToken();\n            SQLExpr where = exprParser.expr();\n            stmt.setWhere(where);\n        }\n\n        return stmt;\n    }\n\n    protected SQLShowColumnsStatement parseShowColumns() {\n        SQLShowColumnsStatement stmt = new SQLShowColumnsStatement();\n\n        if (lexer.token == Token.FROM) {\n            lexer.nextToken();\n            SQLName table = exprParser.name();\n            stmt.setTable(table);\n\n            if (lexer.token == Token.FROM || lexer.token == Token.IN) {\n                lexer.nextToken();\n                SQLName database = exprParser.name();\n                stmt.setDatabase(database);\n            }\n        } else if (lexer.token == Token.IN) {\n            lexer.nextToken();\n            SQLName table = exprParser.name();\n            stmt.setTable(table);\n        }\n\n        if (lexer.token == Token.LIKE) {\n            lexer.nextToken();\n            SQLExpr like = exprParser.expr();\n            stmt.setLike(like);\n        }\n\n        if (lexer.token == Token.WHERE) {\n            lexer.nextToken();\n            SQLExpr where = exprParser.expr();\n            stmt.setWhere(where);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterIndex() {\n        accept(Token.ALTER);\n        lexer.nextToken();\n        SQLAlterIndexStatement stmt = new SQLAlterIndexStatement();\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.identifierEquals(\"RENAME\")) {\n            lexer.nextToken();\n            accept(Token.TO);\n            stmt.setRenameTo(this.exprParser.name());\n        }\n\n        if (lexer.token == Token.ON) {\n            lexer.nextToken();\n            if (lexer.token == Token.TABLE) {\n                lexer.nextToken();\n            }\n            SQLName table = this.exprParser.name();\n            stmt.setTable(table);\n        }\n\n        if (lexer.token == Token.PARTITION) {\n            lexer.nextToken();\n            accept(Token.LPAREN);\n            parseAssignItems(stmt.getPartitions(), stmt);\n            accept(Token.RPAREN);\n        }\n\n        if (lexer.identifierEquals(Constants.DBPARTITION)) {\n            SQLPartitionBy partitionClause = this.getSQLCreateTableParser().parsePartitionBy();\n            stmt.setDbPartitionBy(partitionClause);\n        }\n\n        if (lexer.token == Token.ENABLE) {\n            lexer.nextToken();\n            stmt.setEnable(true);\n        }\n\n        if (lexer.token == Token.DISABLE) {\n            lexer.nextToken();\n            stmt.setEnable(false);\n        }\n        if (lexer.hashLCase == Constants.UNUSABLE) {\n            lexer.nextToken();\n            stmt.setUnusable(true);\n        }\n\n        for (; ; ) {\n            if (lexer.identifierEquals(\"rebuild\")) {\n                lexer.nextToken();\n\n                SQLAlterIndexStatement.Rebuild rebuild = new SQLAlterIndexStatement.Rebuild();\n                stmt.setRebuild(rebuild);\n                continue;\n            } else if (lexer.identifierEquals(\"MONITORING\")) {\n                lexer.nextToken();\n                acceptIdentifier(\"USAGE\");\n                stmt.setMonitoringUsage(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(\"PARALLEL\")) {\n                lexer.nextToken();\n                stmt.setParallel(this.exprParser.expr());\n            }\n            break;\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseAnalyze() {\n        lexer.nextToken();\n        accept(Token.TABLE);\n\n        SQLAnalyzeTableStatement stmt = new SQLAnalyzeTableStatement();\n\n        SQLName table = this.exprParser.name();\n        stmt.setTable(table);\n\n        if (lexer.token() == Token.PARTITION) {\n            stmt.setPartition(parsePartitionRef());\n        }\n\n        accept(Token.COMPUTE);\n        acceptIdentifier(\"STATISTICS\");\n        stmt.setComputeStatistics(true);\n\n        if (lexer.token == Token.FOR) {\n            lexer.nextToken();\n            acceptIdentifier(\"COLUMNS\");\n            stmt.setForColums(true);\n\n            if (lexer.token == LPAREN) {\n                lexer.nextToken();\n                this.exprParser.names(stmt.getColumns(), stmt);\n                accept(RPAREN);\n            }\n        }\n\n        if (lexer.identifierEquals(Constants.CACHE)) {\n            lexer.nextToken();\n            acceptIdentifier(\"METADATA\");\n            stmt.setCacheMetadata(true);\n        }\n\n        if (lexer.identifierEquals(Constants.NOSCAN)) {\n            lexer.nextToken();\n            stmt.setNoscan(true);\n        }\n\n        return stmt;\n    }\n\n    public SQLAlterSequenceStatement alterSequence() {\n        accept(Token.ALTER);\n\n        accept(Token.SEQUENCE);\n\n        SQLAlterSequenceStatement stmt = new SQLAlterSequenceStatement();\n        stmt.setDbType(dbType);\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.identifierEquals(Constants.CHANGE)) {\n            lexer.nextToken();\n            accept(Token.TO);\n\n            if (lexer.identifierEquals(Constants.SIMPLE)) {\n                stmt.setChangeToSimple(true);\n                lexer.nextToken();\n                if (lexer.hashLCase() == Constants.WITH) {\n                    lexer.nextToken();\n                    accept(Token.CACHE);\n                    stmt.setWithCache(true);\n                }\n            } else if (lexer.token == Token.GROUP) {\n                stmt.setChangeToGroup(true);\n                lexer.nextToken();\n            } else if (lexer.identifierEquals(Constants.TIME)) {\n                stmt.setChangeToTime(true);\n                lexer.nextToken();\n            } else {\n                throw new ParserException(\"TODO \" + lexer.info());\n            }\n        }\n\n        for (; ; ) {\n            if (lexer.token() == Token.START || lexer.identifierEquals(Constants.START)) {\n                lexer.nextToken();\n                accept(Token.WITH);\n                stmt.setStartWith(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"INCREMENT\")) {\n                lexer.nextToken();\n                accept(Token.BY);\n                stmt.setIncrementBy(this.exprParser.expr());\n                continue;\n            } else if (lexer.token() == Token.CACHE) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.TRUE);\n\n                if (lexer.token() == Token.LITERAL_INT || lexer.token() == Token.QUES) {\n                    stmt.setCacheValue(this.exprParser.primary());\n                }\n\n                continue;\n            } else if (lexer.token() == Token.NOCACHE) {\n                lexer.nextToken();\n                stmt.setCache(Boolean.FALSE);\n                continue;\n            } else if (lexer.token() == Token.ORDER) {\n                lexer.nextToken();\n                stmt.setOrder(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(Constants.RESTART)) {\n                lexer.nextToken();\n                stmt.setRestart(true);\n\n                if (lexer.token == Token.WITH || lexer.token == Token.EQ) {\n                    lexer.nextToken();\n                    stmt.setRestartWith(this.exprParser.primary());\n                } else if (lexer.token == LITERAL_INT) {\n                    stmt.setRestartWith(this.exprParser.primary());\n                }\n\n                continue;\n            } else if (lexer.identifierEquals(\"NOORDER\")) {\n                lexer.nextToken();\n                stmt.setOrder(Boolean.FALSE);\n                continue;\n            } else if (lexer.identifierEquals(\"CYCLE\")) {\n                lexer.nextToken();\n                stmt.setCycle(Boolean.TRUE);\n                continue;\n            } else if (lexer.identifierEquals(\"NOCYCLE\")) {\n                lexer.nextToken();\n                stmt.setCycle(Boolean.FALSE);\n                continue;\n            } else if (lexer.identifierEquals(\"MINVALUE\")) {\n                lexer.nextToken();\n                stmt.setMinValue(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"MAXVALUE\")) {\n                lexer.nextToken();\n                stmt.setMaxValue(this.exprParser.expr());\n                continue;\n            } else if (lexer.identifierEquals(\"NOMAXVALUE\")) {\n                lexer.nextToken();\n                stmt.setNoMaxValue(true);\n                continue;\n            } else if (lexer.identifierEquals(\"NOMINVALUE\")) {\n                lexer.nextToken();\n                stmt.setNoMinValue(true);\n                continue;\n            }\n            break;\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement parseMsck() {\n        lexer.nextToken();\n        if (lexer.identifierEquals(\"REPAIR\")) {\n            lexer.nextToken();\n        }\n\n        HiveMsckRepairStatement stmt = new HiveMsckRepairStatement();\n\n        if (lexer.token() == Token.DATABASE || lexer.token() == Token.SCHEMA) {\n            lexer.nextToken();\n            SQLName name = this.exprParser.name();\n            stmt.setDatabase(name);\n        }\n\n        if (lexer.token() == Token.TABLE) {\n            lexer.nextToken();\n\n            SQLExpr tableExpr = this.exprParser.expr();\n            stmt.setTable(tableExpr);\n        }\n\n        if (lexer.identifierEquals(Constants.ADD)) {\n            lexer.nextToken();\n            acceptIdentifier(\"PARTITIONS\");\n            stmt.setAddPartitions(true);\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement createResource() {\n        accept(Token.CREATE);\n        acceptIdentifier(\"RESOURCE\");\n        accept(Token.GROUP);\n\n        SQLCreateResourceGroupStatement stmt = new SQLCreateResourceGroupStatement();\n        stmt.setName(this.exprParser.name());\n\n        for (; ; ) {\n            if (lexer.token() == Token.SEMI || lexer.token() == Token.EOF) {\n                break;\n            }\n            if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                stmt.setEnable(true);\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                stmt.setEnable(false);\n            }\n\n            Lexer.SavePoint m = lexer.mark();\n            String name = lexer.stringVal();\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n                SQLExpr value = this.exprParser.expr();\n                if (lexer.token() == Token.COMMA) {\n                    SQLListExpr list = new SQLListExpr();\n                    list.addItem(value);\n                    while (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        list.addItem(this.exprParser.expr());\n                    }\n                    stmt.addProperty(name, list);\n                } else {\n                    stmt.addProperty(name, value);\n                }\n            } else {\n                lexer.reset(m);\n                break;\n            }\n        }\n\n        return stmt;\n    }\n\n    protected SQLStatement alterResourceGroup() {\n        accept(ALTER);\n        acceptIdentifier(\"RESOURCE\");\n        accept(Token.GROUP);\n\n        SQLAlterResourceGroupStatement stmt = new SQLAlterResourceGroupStatement();\n        stmt.setName(this.exprParser.name());\n\n        for (; ; ) {\n            if (lexer.token() == Token.SEMI || lexer.token() == Token.EOF) {\n                break;\n            }\n\n            if (lexer.token() == Token.ENABLE) {\n                lexer.nextToken();\n                stmt.setEnable(true);\n            } else if (lexer.token() == Token.DISABLE) {\n                lexer.nextToken();\n                stmt.setEnable(false);\n            }\n\n            Lexer.SavePoint m = lexer.mark();\n            String name = lexer.stringVal();\n            lexer.nextToken();\n            if (lexer.token() == Token.EQ) {\n                lexer.nextToken();\n                SQLExpr value = this.exprParser.expr();\n                if (lexer.token() == Token.COMMA) {\n                    SQLListExpr list = new SQLListExpr();\n                    list.addItem(value);\n                    while (lexer.token() == Token.COMMA) {\n                        lexer.nextToken();\n                        list.addItem(this.exprParser.expr());\n                    }\n                    stmt.addProperty(name, list);\n                } else {\n                    stmt.addProperty(name, value);\n                }\n            } else {\n                lexer.reset(m);\n                break;\n            }\n\n        }\n\n        return stmt;\n    }\n\n    public SQLStatement alterMaterialized() {\n        SQLAlterMaterializedViewStatement stmt = new SQLAlterMaterializedViewStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token == ALTER) {\n            lexer.nextToken();\n        }\n\n        acceptIdentifier(\"MATERIALIZED\");\n        accept(Token.VIEW);\n\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.EOF) {\n            throw new ParserException(\"syntax error. \" + lexer.info());\n        }\n\n        for (; ; ) {\n            if (lexer.identifierEquals(\"REFRESH\")) {\n                lexer.nextToken();\n\n                if (lexer.token() == Token.EOF) {\n                    throw new ParserException(\"syntax error. \" + lexer.info());\n                }\n\n                boolean refresh = false;\n                for (; ; ) {\n                    if (lexer.identifierEquals(\"FAST\")) {\n                        lexer.nextToken();\n                        stmt.setRefreshFast(true);\n\n                        refresh = true;\n                    } else if (lexer.identifierEquals(\"COMPLETE\")) {\n                        lexer.nextToken();\n                        stmt.setRefreshComplete(true);\n\n                        refresh = true;\n                    } else if (lexer.identifierEquals(Constants.FORCE)) {\n                        lexer.nextToken();\n                        stmt.setRefreshForce(true);\n\n                        refresh = true;\n                    } else if (lexer.token == Token.ON) {\n                        lexer.nextToken();\n                        if (lexer.token == Token.COMMIT || lexer.identifierEquals(Constants.COMMIT)) {\n                            lexer.nextToken();\n                            stmt.setRefreshOnCommit(true);\n                        } else if (lexer.identifierEquals(Constants.OVERWRITE)) {\n                            lexer.nextToken();\n                            stmt.setRefreshOnOverWrite(true);\n                        } else {\n                            acceptIdentifier(\"DEMAND\");\n                            stmt.setRefreshOnDemand(true);\n                        }\n\n                        refresh = true;\n                    } else if (lexer.identifierEquals(Constants.START)) {\n                        lexer.nextToken();\n                        accept(Token.WITH);\n                        SQLExpr startWith = this.exprParser.expr();\n                        stmt.setStartWith(startWith);\n                        stmt.setRefreshStartWith(true);\n\n                        refresh = true;\n                    } else if (lexer.identifierEquals(Constants.NEXT)) {\n                        lexer.nextToken();\n                        SQLExpr next = this.exprParser.expr();\n                        stmt.setNext(next);\n                        stmt.setRefreshNext(true);\n\n                        refresh = true;\n                    } else {\n                        break;\n                    }\n                }\n                if (!refresh) {\n                    throw new ParserException(\"refresh clause is empty. \" + lexer.info());\n                }\n            } else if (lexer.identifierEquals(\"REBUILD\")) {\n                lexer.nextToken();\n                stmt.setRebuild(true);\n                continue;\n            } else {\n                break;\n            }\n        }\n\n        Boolean enableQueryRewrite = null;\n        if (lexer.token == Token.ENABLE) {\n            lexer.nextToken();\n            enableQueryRewrite = true;\n        }\n\n        if (lexer.token == Token.DISABLE) {\n            lexer.nextToken();\n            enableQueryRewrite = false;\n        }\n\n        if (enableQueryRewrite != null) {\n            acceptIdentifier(\"QUERY\");\n            acceptIdentifier(\"REWRITE\");\n            stmt.setEnableQueryRewrite(enableQueryRewrite);\n        }\n\n        if (lexer.token == PARTITION) {\n            lexer.nextToken();\n            accept(LPAREN);\n            this.exprParser.exprList(stmt.getPartitions(), stmt);\n            accept(RPAREN);\n        }\n\n        return stmt;\n    }\n\n    public SQLCreateFunctionStatement parseHiveCreateFunction() {\n        HiveCreateFunctionStatement stmt = new HiveCreateFunctionStatement();\n        stmt.setDbType(dbType);\n\n        if (lexer.token == CREATE) {\n            lexer.nextToken();\n        }\n\n        if (lexer.token == OR) {\n            lexer.nextToken();\n            accept(REPLACE);\n            stmt.setOrReplace(true);\n        }\n\n        if (lexer.identifierEquals(Constants.TEMPORARY)) {\n            lexer.nextToken();\n            stmt.setTemporary(true);\n        }\n\n        boolean sql = false; // TODO for odps\n        if (lexer.identifierEquals(Constants.SQL)) {\n            lexer.nextToken();\n            sql = true;\n        }\n\n        accept(Token.FUNCTION);\n\n        if (lexer.token == IF) {\n            lexer.nextToken();\n            accept(NOT);\n            accept(EXISTS);\n            stmt.setIfNotExists(true);\n        }\n\n        SQLName name = this.exprParser.name();\n        stmt.setName(name);\n\n        parameters(stmt.getParameters(), stmt);\n\n        if (lexer.identifierEquals(Constants.RETURNS)) {\n            lexer.nextToken();\n            if (lexer.token == VARIANT) {\n                lexer.nextToken(); // TODO\n            }\n            SQLDataType returnDataType = this.exprParser.parseDataType();\n            stmt.setReturnDataType(returnDataType);\n        }\n\n        if (lexer.token == IDENTIFIER && lexer.stringVal().toUpperCase().startsWith(\"RETURNS@\")) {\n            lexer.nextToken();\n            SQLDataType returnDataType = this.exprParser.parseDataType();\n            stmt.setReturnDataType(returnDataType);\n        }\n\n        if (lexer.token() == Token.AS) {\n            lexer.setToken(Token.IDENTIFIER);\n            lexer.nextToken();\n            if (lexer.token != BEGIN && !lexer.identifierEquals(Constants.BEGIN)) {\n                SQLExpr className = this.exprParser.expr();\n                stmt.setClassName(className);\n            }\n        }\n\n        if (lexer.identifierEquals(Constants.LOCATION)) {\n            lexer.nextToken();\n            SQLExpr location = this.exprParser.primary();\n            stmt.setLocation(location);\n        }\n\n        if (lexer.identifierEquals(Constants.SYMBOL)) {\n            lexer.nextToken();\n            accept(Token.EQ);\n            SQLExpr symbol = this.exprParser.primary();\n            stmt.setSymbol(symbol);\n        }\n\n        if (lexer.token() == Token.USING || lexer.hashLCase() == Constants.USING) {\n            lexer.nextToken();\n\n            if (lexer.identifierEquals(Constants.JAR)) {\n                lexer.nextToken();\n                stmt.setResourceType(HiveCreateFunctionStatement.ResourceType.JAR);\n            } else if (lexer.identifierEquals(Constants.ARCHIVE)) {\n                lexer.nextToken();\n                stmt.setResourceType(HiveCreateFunctionStatement.ResourceType.ARCHIVE);\n            } else if (lexer.identifierEquals(Constants.FILE)) {\n                lexer.nextToken();\n                stmt.setResourceType(HiveCreateFunctionStatement.ResourceType.FILE);\n            } else if (lexer.token == Token.CODE) {\n                stmt.setCode(lexer.stringVal());\n                lexer.nextToken();\n                stmt.setResourceType(HiveCreateFunctionStatement.ResourceType.CODE);\n                return stmt;\n            }\n\n            SQLExpr location = this.exprParser.primary();\n            stmt.setLocation(location);\n        }\n\n        return stmt;\n    }\n\n    protected void parameters(List<SQLParameter> parameters, SQLObject parent) {\n        if (lexer.token == LPAREN) {\n            lexer.nextToken();\n            while (lexer.token != RPAREN) {\n                SQLParameter param = new SQLParameter();\n                param.setName(this.exprParser.name());\n                param.setDataType(this.exprParser.parseDataType());\n                if (lexer.token == COMMA) {\n                    lexer.nextToken();\n                }\n                parameters.add(param);\n                param.setParent(parent);\n            }\n            accept(RPAREN);\n        }\n    }\n\n    protected SQLShowCreateTableStatement parseShowCreateTable() {\n        lexer.nextToken();\n        accept(Token.TABLE);\n\n        SQLShowCreateTableStatement stmt = new SQLShowCreateTableStatement();\n        stmt.setDbType(dbType);\n        stmt.setName(this.exprParser.name());\n\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            if (lexer.identifierEquals(Constants.MAPPING)) {\n                lexer.nextToken();\n                accept(Token.LPAREN);\n                SQLName name = this.exprParser.name();\n                stmt.setLikeMapping(name);\n                accept(Token.RPAREN);\n            }\n        }\n        return stmt;\n    }\n\n    public SQLShowVariantsStatement parseShowVariants() {\n        SQLShowVariantsStatement stmt = new SQLShowVariantsStatement();\n        stmt.setDbType(dbType);\n        if (lexer.token() == Token.LIKE) {\n            lexer.nextToken();\n            SQLExpr like = exprParser.expr();\n            stmt.setLike(like);\n        }\n\n        if (lexer.token() == Token.WHERE) {\n            lexer.nextToken();\n            SQLExpr where = exprParser.expr();\n            stmt.setWhere(where);\n        }\n\n        return stmt;\n    }\n\n    protected SQLExceptionStatement parseException() {\n        accept(Token.EXCEPTION);\n        SQLExceptionStatement stmt = new SQLExceptionStatement();\n\n        for (; ; ) {\n            accept(Token.WHEN);\n            SQLExceptionStatement.Item item = new SQLExceptionStatement.Item();\n            item.setWhen(this.exprParser.expr());\n            accept(Token.THEN);\n\n            this.parseStatementList(item.getStatements(), -1, item);\n\n            stmt.addItem(item);\n\n            if (lexer.token() == Token.SEMI) {\n                lexer.nextToken();\n            }\n\n            if (lexer.token() != Token.WHEN) {\n                break;\n            }\n        }\n        return stmt;\n    }\n\n    public SQLResetStatement parseReset() {\n        acceptIdentifier(\"RESET\");\n        SQLResetStatement stmt = new SQLResetStatement();\n        for (; ; ) {\n            if (lexer.token() == Token.IDENTIFIER) {\n                if (lexer.identifierEquals(\"QUERY\")) {\n                    lexer.nextToken();\n                    accept(Token.CACHE);\n                    stmt.getOptions().add(\"QUERY CACHE\");\n                } else {\n                    stmt.getOptions().add(lexer.stringVal());\n                    lexer.nextToken();\n                }\n\n                if (lexer.token() == Token.COMMA) {\n                    lexer.nextToken();\n                    continue;\n                }\n            }\n            break;\n        }\n\n        return stmt;\n    }\n    public SQLComputeIncrementalStatsStatement parseCompute() {\n        accept(COMPUTE);\n        acceptIdentifier(\"INCREMENTAL\");\n        acceptIdentifier(\"STATS\");\n        SQLComputeIncrementalStatsStatement stmt = new SQLComputeIncrementalStatsStatement();\n        stmt.setName(this.exprParser.expr());\n        if (lexer.nextIf(PARTITION)) {\n            stmt.setPartition(this.exprParser.expr());\n        }\n        return stmt;\n    }\n    public SQLStartTransactionStatement parseStart() {\n        acceptIdentifier(\"START\");\n        acceptIdentifier(\"TRANSACTION\");\n\n        SQLStartTransactionStatement stmt = new SQLStartTransactionStatement(dbType);\n\n        if (lexer.token() == WITH) {\n            lexer.nextToken();\n            acceptIdentifier(\"CONSISTENT\");\n            acceptIdentifier(\"SNAPSHOT\");\n            stmt.setConsistentSnapshot(true);\n        }\n\n        if (lexer.token() == Token.BEGIN) {\n            lexer.nextToken();\n            stmt.setBegin(true);\n            if (lexer.identifierEquals(\"WORK\")) {\n                lexer.nextToken();\n                stmt.setWork(true);\n            }\n        }\n\n        if (lexer.token() == Token.HINT) {\n            stmt.setHints(this.exprParser.parseHints());\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.ISOLATION)) {\n            lexer.nextToken();\n            acceptIdentifier(\"LEVEL\");\n\n            if (lexer.identifierEquals(FnvHash.Constants.READ)) {\n                lexer.nextToken();\n                if (lexer.identifierEquals(FnvHash.Constants.UNCOMMITTED)) {\n                    lexer.nextToken();\n                    stmt.setIsolationLevel(SQLStartTransactionStatement.IsolationLevel.READ_UNCOMMITTED);\n                } else if (lexer.identifierEquals(FnvHash.Constants.COMMITTED)) {\n                    lexer.nextToken();\n                    stmt.setIsolationLevel(SQLStartTransactionStatement.IsolationLevel.READ_COMMITTED);\n                } else {\n                    throw new ParserException(lexer.info());\n                }\n            } else if (lexer.identifierEquals(FnvHash.Constants.REPEATABLE)) {\n                lexer.nextToken();\n                acceptIdentifier(\"READ\");\n                stmt.setIsolationLevel(SQLStartTransactionStatement.IsolationLevel.REPEATABLE_READ);\n            } else if (lexer.identifierEquals(FnvHash.Constants.SERIALIZABLE)) {\n                lexer.nextToken();\n                stmt.setIsolationLevel(SQLStartTransactionStatement.IsolationLevel.SERIALIZABLE);\n            } else {\n                throw new ParserException(lexer.info());\n            }\n        }\n\n        if (lexer.identifierEquals(FnvHash.Constants.READ)) {\n            lexer.nextToken();\n            acceptIdentifier(\"ONLY\");\n            stmt.setReadOnly(true);\n        }\n\n        return stmt;\n    }\n    public SQLStatement parseClone() {\n        throw new ParserException(\"TODO \" + lexer.info());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SQLType.java",
    "content": "package com.alibaba.druid.sql.parser;\n\npublic enum SQLType {\n    SELECT,\n    UPDATE,\n    INSERT_SELECT,\n    INSERT_INTO_SELECT,\n    INSERT_OVERWRITE_SELECT,\n    INSERT_VALUES,\n    INSERT_INTO_VALUES,\n    INSERT_OVERWRITE_VALUES,\n    INSERT,\n    INSERT_INTO,\n    INSERT_OVERWRITE,\n    INSERT_MULTI,\n    DELETE,\n    MERGE,\n\n    CREATE,\n    ALTER,\n    DROP,\n    TRUNCATE,\n\n    REPLACE,\n    ANALYZE,\n\n    EXPLAIN,\n\n    SHOW,\n    SHOW_TABLES,\n    SHOW_USERS,\n    SHOW_PARTITIONS,\n    SHOW_CATALOGS,\n    SHOW_FUNCTIONS,\n    SHOW_ROLE,\n    SHOW_ROLES,\n    SHOW_PACKAGE,\n    SHOW_PACKAGES,\n    SHOW_CHANGELOGS,\n    SHOW_ACL,\n    SHOW_RECYCLEBIN,\n    SHOW_VARIABLES,\n    SHOW_HISTORY,\n    SHOW_GRANT,\n    SHOW_GRANTS,\n    SHOW_CREATE_TABLE,\n    SHOW_STATISTIC,\n    SHOW_STATISTIC_LIST,\n    SHOW_LABEL,\n    DESC,\n    SET,\n    SET_PROJECT,\n    SET_LABEL,\n    DUMP_DATA,\n    LIST, // for analyticdb\n    LIST_USERS,\n    LIST_TABLES,\n    LIST_ROLES,\n    LIST_TENANT_ROLES,\n    LIST_TRUSTEDPROJECTS,\n    LIST_ACCOUNTPROVIDERS,\n    LIST_TEMPORARY_OUTPUT,\n    WHO, // for analyticdb\n    GRANT,\n    REVOKE,\n\n    COMMIT,\n    ROLLBACK,\n    USE,\n    KILL,\n    MSCK,\n\n    ADD_USER,\n    REMOVE_USER,\n    REMOVE_RESOURCE,\n\n    CREATE_USER,\n    CREATE_TABLE,\n    CREATE_TABLE_AS_SELECT,\n    CREATE_VIEW,\n    CREATE_FUNCTION,\n    CREATE_ROLE,\n    CREATE_PACKAGE,\n\n    DROP_USER,\n    DROP_TABLE,\n    DROP_VIEW,\n    DROP_MATERIALIZED_VIEW,\n    DROP_FUNCTION,\n    DROP_ROLE,\n    DROP_RESOURCE,\n    ALTER_USER,\n    ALTER_TABLE,\n    ALTER_VIEW,\n    READ,\n\n    ADD_TABLE,\n    ADD_FUNCTION,\n    ADD_RESOURCE,\n    ADD_TRUSTEDPROJECT,\n    ADD_VOLUME,\n    ADD_STATISTIC,\n    ADD_ACCOUNTPROVIDER,\n    TUNNEL_DOWNLOAD,\n    UPLOAD,\n\n    WHOAMI,\n    SCRIPT,\n    COUNT,\n\n    ADD,\n    CLONE,\n    LOAD,\n    INSTALL,\n    UNLOAD,\n    ALLOW,\n    PURGE,\n    RESTORE,\n    EXSTORE,\n    UNDO,\n    REMOVE,\n\n    EMPTY,\n\n    ALTER_TABLE_ADD_PARTITION,\n    ALTER_TABLE_MERGE_PARTITION,\n    ALTER_TABLE_DROP_PARTITION,\n    ALTER_TABLE_RENAME_PARTITION,\n    ALTER_TABLE_SET_LIFECYCLE,\n    ALTER_TABLE_ENABLE_LIFECYCLE,\n    ALTER_TABLE_DISABLE_LIFECYCLE,\n    ALTER_TABLE_RENAME,\n    ALTER_TABLE_ADD_COLUMN,\n    ALTER_TABLE_RENAME_COLUMN,\n    ALTER_TABLE_ALTER_COLUMN,\n    ALTER_TABLE_SET_TBLPROPERTIES,\n    ALTER_TABLE_SET_COMMENT,\n    ALTER_TABLE_TOUCH,\n    ALTER_TABLE_CHANGE_OWNER,\n\n    MULTI,\n\n    WITH,\n    SET_UNKNOWN,\n    UNKNOWN,\n\n    ERROR,\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\nimport java.nio.charset.StandardCharsets;\n\n/**\n * @author wenshao[szujobs@hotmail.com]\n */\npublic class SymbolTable {\n    private static final boolean JVM_16;\n\n    static {\n        String version = null;\n        try {\n            version = System.getProperty(\"java.specification.version\");\n        } catch (IllegalArgumentException ex) {\n            // skip\n        } catch (SecurityException error) {\n            // skip\n        }\n        JVM_16 = \"1.6\".equals(version);\n    }\n\n    public static SymbolTable global = new SymbolTable(32768);\n\n    private final Entry[] entries;\n    private final int indexMask;\n\n    public SymbolTable(int tableSize) {\n        this.indexMask = tableSize - 1;\n        this.entries = new Entry[tableSize];\n    }\n\n    public String addSymbol(String buffer, int offset, int len, long hash) {\n        final int bucket = ((int) hash) & indexMask;\n\n        Entry entry = entries[bucket];\n        if (entry != null) {\n            if (hash == entry.hash && len == entry.len\n                    && buffer.regionMatches(offset, entry.value, 0, len)) {\n                return entry.value;\n            }\n\n            String str = JVM_16\n                    ? subString(buffer, offset, len)\n                    : buffer.substring(offset, offset + len);\n\n            return str;\n        }\n\n        String str = JVM_16\n                ? subString(buffer, offset, len)\n                : buffer.substring(offset, offset + len);\n        entry = new Entry(hash, len, str);\n        entries[bucket] = entry;\n        return str;\n    }\n\n    public String addSymbol(byte[] buffer, int offset, int len, long hash) {\n        final int bucket = ((int) hash) & indexMask;\n\n        Entry entry = entries[bucket];\n        if (entry != null) {\n            if (hash == entry.hash) {\n                return entry.value;\n            }\n\n            String str = subString(buffer, offset, len);\n\n            return str;\n        }\n\n        String str = subString(buffer, offset, len);\n        entry = new Entry(hash, len, str);\n        entries[bucket] = entry;\n        return str;\n    }\n\n    public String addSymbol(String symbol, long hash) {\n        final int bucket = ((int) hash) & indexMask;\n\n        Entry entry = entries[bucket];\n        if (entry != null) {\n            if (hash == entry.hash && symbol.length() == entry.len\n                    && symbol.equals(entry.value)) {\n                return entry.value;\n            }\n\n            return symbol;\n        }\n\n        entry = new Entry(hash, symbol.length(), symbol);\n        entries[bucket] = entry;\n        return symbol;\n    }\n\n    public String findSymbol(long hash) {\n        final int bucket = ((int) hash) & indexMask;\n        Entry entry = entries[bucket];\n        if (entry != null && entry.hash == hash) {\n            return entry.value;\n        }\n        return null;\n    }\n\n    private static String subString(String src, int offset, int len) {\n        char[] chars = new char[len];\n        src.getChars(offset, offset + len, chars, 0);\n        return new String(chars);\n    }\n\n    private static String subString(byte[] bytes, int from, int len) {\n        byte[] strBytes = new byte[len];\n        System.arraycopy(bytes, from, strBytes, 0, len);\n        return new String(strBytes, StandardCharsets.UTF_8);\n    }\n\n    private static class Entry {\n        public final long hash;\n        public final int len;\n        public final String value;\n\n        public Entry(long hash, int len, String value) {\n            this.hash = hash;\n            this.len = len;\n            this.value = value;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/parser/Token.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.parser;\n\n/**\n * SQL Token\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic enum Token {\n    SELECT(\"SELECT\"),\n    DELETE(\"DELETE\"),\n    INSERT(\"INSERT\"),\n    UPDATE(\"UPDATE\"),\n\n    FROM(\"FROM\"),\n    HAVING(\"HAVING\"),\n    WHERE(\"WHERE\"),\n    ORDER(\"ORDER\"),\n    BY(\"BY\"),\n    GROUP(\"GROUP\"),\n    INTO(\"INTO\"),\n    AS(\"AS\"),\n\n    CREATE(\"CREATE\"),\n    ALTER(\"ALTER\"),\n    DROP(\"DROP\"),\n    SET(\"SET\"),\n\n    NULL(\"NULL\"),\n    NOT(\"NOT\"),\n    DISTINCT(\"DISTINCT\"),\n    DISTINCTROW(\"DISTINCTROW\"),\n\n    TABLE(\"TABLE\"),\n    TABLESPACE(\"TABLESPACE\"),\n    VIEW(\"VIEW\"),\n    SEQUENCE(\"SEQUENCE\"),\n    TRIGGER(\"TRIGGER\"),\n    USER(\"USER\"),\n    INDEX(\"INDEX\"),\n    SESSION(\"SESSION\"),\n    PROCEDURE(\"PROCEDURE\"),\n    FUNCTION(\"FUNCTION\"),\n\n    PRIMARY(\"PRIMARY\"),\n    KEY(\"KEY\"),\n    DEFAULT(\"DEFAULT\"),\n    CONSTRAINT(\"CONSTRAINT\"),\n    CHECK(\"CHECK\"),\n    UNIQUE(\"UNIQUE\"),\n    FOREIGN(\"FOREIGN\"),\n    REFERENCES(\"REFERENCES\"),\n    LANGUAGE(\"LANGUAGE\"),\n    PARTIAL(\"PARTIAL\"),\n\n    EXPLAIN(\"EXPLAIN\"),\n    FOR(\"FOR\"),\n    REVERSE(\"REVERSE\"),\n    IF(\"IF\"),\n\n    LOCAL(\"LOCAL\"),\n    GLOBAL(\"GLOBAL\"),\n    ALL(\"ALL\"),\n    UNION(\"UNION\"),\n    EXCEPT(\"EXCEPT\"),\n    INTERSECT(\"INTERSECT\"),\n    MINUS(\"MINUS\"),\n    INNER(\"INNER\"),\n    LEFT(\"LEFT\"),\n    RIGHT(\"RIGHT\"),\n    FULL(\"FULL\"),\n    OUTER(\"OUTER\"),\n    JOIN(\"JOIN\"),\n    STRAIGHT_JOIN(\"STRAIGHT_JOIN\"),\n    ON(\"ON\"),\n    SCHEMA(\"SCHEMA\"),\n    CAST(\"CAST\"),\n    COLUMN(\"COLUMN\"),\n    USE(\"USE\"),\n    DATABASE(\"DATABASE\"),\n    TO(\"TO\"),\n\n    AND(\"AND\"),\n    OR(\"OR\"),\n    XOR(\"XOR\"),\n    CASE(\"CASE\"),\n    WHEN(\"WHEN\"),\n    THEN(\"THEN\"),\n    ELSE(\"ELSE\"),\n    ELSIF(\"ELSIF\"),\n    ELSEIF(\"ELSEIF\"),\n    END(\"END\"),\n    EXISTS(\"EXISTS\"),\n    IN(\"IN\"),\n\n    NEW(\"NEW\"),\n    ASC(\"ASC\"),\n    DESC(\"DESC\"),\n    IS(\"IS\"),\n    LIKE(\"LIKE\"),\n    ESCAPE(\"ESCAPE\"),\n    BETWEEN(\"BETWEEN\"),\n    VALUES(\"VALUES\"),\n    INTERVAL(\"INTERVAL\"),\n\n    LOCK(\"LOCK\"),\n    SOME(\"SOME\"),\n    ANY(\"ANY\"),\n    TRUNCATE(\"TRUNCATE\"),\n\n    RETURN(\"RETURN\"),\n\n    // mysql\n    TRUE(\"TRUE\"),\n    FALSE(\"FALSE\"),\n    LIMIT(\"LIMIT\"),\n    KILL(\"KILL\"),\n    IDENTIFIED(\"IDENTIFIED\"),\n    PASSWORD(\"PASSWORD\"),\n    DUAL(\"DUAL\"),\n    BINARY(\"BINARY\"),\n    SHOW(\"SHOW\"),\n    REPLACE(\"REPLACE\"),\n    PERIOD(\"PERIOD\"),\n\n    BITS(\"BITS\"),\n\n    // MySql procedure add by zz\n    WHILE(\"WHILE\"),\n    DO(\"DO\"),\n    LEAVE(\"LEAVE\"),\n    ITERATE(\"ITERATE\"),\n    REPEAT(\"REPEAT\"),\n    UNTIL(\"UNTIL\"),\n    OPEN(\"OPEN\"),\n    CLOSE(\"CLOSE\"),\n    OUT(\"OUT\"),\n    INOUT(\"INOUT\"),\n    EXIT(\"EXIT\"),\n    UNDO(\"UNDO\"),\n    SQLSTATE(\"SQLSTATE\"),\n    CONDITION(\"CONDITION\"),\n    DIV(\"DIV\"),\n\n    //postgresql\n    GET(\"GET\"),\n    DIAGNOSTICS(\"DIAGNOSTICS\"),\n    WINDOW(\"WINDOW\"),\n    OFFSET(\"OFFSET\"),\n    ROW(\"ROW\"),\n    ROWS(\"ROWS\"),\n    ONLY(\"ONLY\"),\n    FIRST(\"FIRST\"),\n    NEXT(\"NEXT\"),\n    FETCH(\"FETCH\"),\n    OF(\"OF\"),\n    SHARE(\"SHARE\"),\n    NOWAIT(\"NOWAIT\"),\n    RECURSIVE(\"RECURSIVE\"),\n    TEMPORARY(\"TEMPORARY\"),\n    TEMP(\"TEMP\"),\n    UNLOGGED(\"UNLOGGED\"),\n    RESTART(\"RESTART\"),\n    IDENTITY(\"IDENTITY\"),\n    CONTINUE(\"CONTINUE\"),\n    CASCADE(\"CASCADE\"),\n    RESTRICT(\"RESTRICT\"),\n    USING(\"USING\"),\n    CURRENT(\"CURRENT\"),\n    RETURNING(\"RETURNING\"),\n    COMMENT(\"COMMENT\"),\n    OVER(\"OVER\"),\n    TYPE(\"TYPE\"),\n    ILIKE(\"ILIKE\"),\n    RLIKE(\"RLIKE\"),\n    FULLTEXT(\"FULLTEXT\"),\n\n    // oracle\n    START(\"START\"),\n    PRIOR(\"PRIOR\"),\n    CONNECT(\"CONNECT\"),\n    WITH(\"WITH\"),\n    EXTRACT(\"EXTRACT\"),\n    CURSOR(\"CURSOR\"),\n    //    MODEL(\"MODEL\"),\n    MERGE(\"MERGE\"),\n    MATCHED(\"MATCHED\"),\n    ERRORS(\"ERRORS\"),\n    REJECT(\"REJECT\"),\n    UNLIMITED(\"UNLIMITED\"),\n    BEGIN(\"BEGIN\"),\n    EXCLUSIVE(\"EXCLUSIVE\"),\n    MODE(\"MODE\"),\n    WAIT(\"WAIT\"),\n    ADVISE(\"ADVISE\"),\n    SYSDATE(\"SYSDATE\"),\n    DECLARE(\"DECLARE\"),\n    EXCEPTION(\"EXCEPTION\"),\n    GRANT(\"GRANT\"),\n    REVOKE(\"REVOKE\"),\n    LOOP(\"LOOP\"),\n    GOTO(\"GOTO\"),\n    COMMIT(\"COMMIT\"),\n    SAVEPOINT(\"SAVEPOINT\"),\n    CROSS(\"CROSS\"),\n\n    PCTFREE(\"PCTFREE\"),\n    INITRANS(\"INITRANS\"),\n    MAXTRANS(\"MAXTRANS\"),\n    INITIALLY(\"INITIALLY\"),\n    ENABLE(\"ENABLE\"),\n    DISABLE(\"DISABLE\"),\n    SEGMENT(\"SEGMENT\"),\n    CREATION(\"CREATION\"),\n    IMMEDIATE(\"IMMEDIATE\"),\n    DEFERRED(\"DEFERRED\"),\n    STORAGE(\"STORAGE\"),\n    MINEXTENTS(\"MINEXTENTS\"),\n    MAXEXTENTS(\"MAXEXTENTS\"),\n    MAXSIZE(\"MAXSIZE\"),\n    PCTINCREASE(\"PCTINCREASE\"),\n    FLASH_CACHE(\"FLASH_CACHE\"),\n    CELL_FLASH_CACHE(\"CELL_FLASH_CACHE\"),\n    NONE(\"NONE\"),\n    LOB(\"LOB\"),\n    STORE(\"STORE\"),\n    CHUNK(\"CHUNK\"),\n    CACHE(\"CACHE\"),\n    NOCACHE(\"NOCACHE\"),\n    LOGGING(\"LOGGING\"),\n    NOCOMPRESS(\"NOCOMPRESS\"),\n    KEEP_DUPLICATES(\"KEEP_DUPLICATES\"),\n    EXCEPTIONS(\"EXCEPTIONS\"),\n    PURGE(\"PURGE\"),\n\n    COMPUTE(\"COMPUTE\"),\n    ANALYZE(\"ANALYZE\"),\n    OPTIMIZE(\"OPTIMIZE\"),\n\n    // bigquery\n    RAISE(\"RAISE\"),\n\n    // transact-sql\n    TOP(\"TOP\"),\n\n    ARRAY(\"ARRAY\"),\n    DISTRIBUTE(\"DISTRIBUTE\"),\n    OPTION(\"OPTION\"),\n\n    // hive\n\n    EOF,\n    ERROR,\n    IDENTIFIER,\n    HINT,\n    VARIANT,\n    LITERAL_INT,\n    LITERAL_FLOAT,\n    LITERAL_HEX,\n    LITERAL_CHARS,\n    LITERAL_NCHARS,\n    LITERAL_TEXT_BLOCK,\n\n    CODE, // odps\n\n    LITERAL_PATH,\n\n    LITERAL_ALIAS,\n    LINE_COMMENT,\n    MULTI_LINE_COMMENT,\n\n    // Oracle\n    BINARY_FLOAT,\n    BINARY_DOUBLE,\n\n    // odps,hive\n    PARTITION,\n    PARTITIONED,\n    OVERWRITE,\n    SORT,\n    LATERAL,\n\n    // clickhouse\n    PREWHERE(\"PREWHERE\"),\n    SETTINGS(\"SETTINGS\"),\n    FINAL(\"FINAL\"),\n    TTL(\"TTL\"),\n    CODEC(\"CODEC\"),\n\n    // Teradata\n    SEL(\"SEL\"),\n    LOCKING(\"LOCKING\"),\n    ACCESS(\"ACCESS\"),\n    VOLATILE(\"VOLATILE\"),\n    MULTISET(\"MULTISET\"),\n    POSITION(\"POSITION\"),\n    RANGE_N(\"RANGE_N\"),\n    FORMAT(\"FORMAT\"),\n    QUALIFY(\"QUALIFY\"),\n    MOD(\"MOD\"),\n    CONTAINS(\"CONTAINS\"),\n\n    CONCAT(\"CONCAT\"), // DB2\n\n    UPSERT(\"UPSERT\"), // Phoenix\n\n    // StarRocks\n    ADD(\"ADD\"),\n    BOTH(\"BOTH\"),\n    FORCE(\"FORCE\"),\n    BITMAP(\"BITMAP\"),\n    NGRAMBF(\"NGRAMBF\"),\n    // Doris\n    INVERTED(\"INVERTED\"),\n    // Redshift\n    ENCODE(\"ENCODE\"),\n    DISTSTYLE(\"DISTSTYLE\"),\n    AUTO(\"AUTO\"),\n    EVEN(\"EVEN\"),\n    DISTKEY(\"DISTKEY\"),\n    SORTKEY(\"SORTKEY\"),\n    COMPOUND(\"COMPOUND\"),\n    INTERLEAVED(\"INTERLEAVED\"),\n    BACKUP(\"BACKUP\"),\n    TABLET(\"TABLET\"),\n    REPEATABLE(\"REPEATABLE\"),\n    TABLESAMPLE(\"TABLESAMPLE\"),\n\n    LPAREN(\"(\"),\n    RPAREN(\")\"),\n    LBRACE(\"{\"),\n    RBRACE(\"}\"),\n    LBRACKET(\"[\"),\n    RBRACKET(\"]\"),\n    SEMI(\";\"),\n    COMMA(\",\"),\n    DOT(\".\"),\n    DOTDOT(\"..\"),\n    DOTDOTDOT(\"...\"),\n    EQ(\"=\"),\n    GT(\">\"),\n    LT(\"<\"),\n    LT_SUB_GT(\"<->\"),\n    BANG(\"!\"),\n    BANGBANG(\"!!\"),\n    BANG_TILDE(\"!~\"),\n    BANG_TILDE_STAR(\"!~*\"),\n    TILDE(\"~\"),\n    TILDE_STAR(\"~*\"),\n    TILDE_EQ(\"~=\"),\n    QUES(\"?\"),\n    QUESQUES(\"??\"),\n    QUESBAR(\"?|\"),\n    QUESQUESBAR(\"??|\"),\n    QUESAMP(\"?&\"),\n    COLON(\":\"),\n    COLONCOLON(\"::\"),\n    COLONEQ(\":=\"),\n    EQEQ(\"==\"),\n    EQGT(\"=>\"),\n    LTEQ(\"<=\"),\n    LTEQGT(\"<=>\"),\n    LTGT(\"<>\"),\n    GTEQ(\">=\"),\n    BANGEQ(\"!=\"),\n    BANGGT(\"!>\"),\n    BANGLT(\"!<\"),\n    AMPAMP(\"&&\"),\n    BARBAR(\"||\"),\n    BARBARSLASH(\"||/\"),\n    BARSLASH(\"|/\"),\n    PLUS(\"+\"),\n    SUB(\"-\"),\n    SUBGT(\"->\"),\n    SUBGTGT(\"->>\"),\n    STAR(\"*\"),\n    SLASH(\"/\"),\n    AMP(\"&\"),\n    BAR(\"|\"),\n    CARET(\"^\"),\n    CARETEQ(\"^=\"),\n    PERCENT(\"%\"),\n    LTLT(\"<<\"),\n    LTLTLT(\"<<<\"),\n    GTGT(\">>\"),\n    GTGTGT(\">>>\"),\n    MONKEYS_AT(\"@\"),\n    MONKEYS_AT_AT(\"@@\"),\n    POUND(\"#\"),\n    POUNDGT(\"#>\"),\n    POUNDGTGT(\"#>>\"),\n    MONKEYS_AT_GT(\"@>\"),\n    LT_MONKEYS_AT(\"<@\");\n\n    public final String name;\n\n    Token() {\n        this(null);\n    }\n\n    Token(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/Schema.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.repository;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Created by wenshao on 21/07/2017.\n */\npublic class Schema {\n    private String catalog;\n    private String name;\n    protected final Map<Long, SchemaObject> objects = new ConcurrentHashMap<Long, SchemaObject>(16, 0.75f, 1);\n    protected final Map<Long, SchemaObject> functions = new ConcurrentHashMap<Long, SchemaObject>(16, 0.75f, 1);\n    private SchemaRepository repository;\n\n    protected Schema(SchemaRepository repository) {\n        this(repository, null);\n    }\n\n    protected Schema(SchemaRepository repository, String name) {\n        this.repository = repository;\n        this.setName(name);\n    }\n\n    protected Schema(SchemaRepository repository, String catalog, String name) {\n        this.repository = repository;\n        this.catalog = catalog;\n        this.name = name;\n    }\n\n    public SchemaRepository getRepository() {\n        return repository;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getSimpleName() {\n        if (name != null) {\n            int p = name.indexOf('.');\n            if (p != -1) {\n                SQLExpr expr = SQLUtils.toSQLExpr(name, repository.dbType);\n                if (expr instanceof SQLPropertyExpr) {\n                    return ((SQLPropertyExpr) expr).getSimpleName();\n                } else {\n                    return name.substring(p + 1);\n                }\n            } else {\n                return name;\n            }\n        }\n        return null;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n\n        if (name != null && name.indexOf('.') != -1) {\n            SQLExpr expr = SQLUtils.toSQLExpr(name, repository.dbType);\n            if (expr instanceof SQLPropertyExpr) {\n                catalog = ((SQLPropertyExpr) expr).getOwnernName();\n            }\n        }\n    }\n\n    public SchemaObject findTable(String tableName) {\n        long hashCode64 = FnvHash.hashCode64(tableName);\n        return findTable(hashCode64);\n    }\n\n    public SchemaObject findTable(long nameHashCode64) {\n        SchemaObject object = objects.get(nameHashCode64);\n\n        if (object != null && object.getType() == SchemaObjectType.Table) {\n            return object;\n        }\n\n        return null;\n    }\n\n    public SchemaObject findView(String viewName) {\n        long hashCode64 = FnvHash.hashCode64(viewName);\n        return findView(hashCode64);\n    }\n\n    public SchemaObject findView(long nameHashCode64) {\n        SchemaObject object = objects.get(nameHashCode64);\n\n        if (object != null && object.getType() == SchemaObjectType.View) {\n            return object;\n        }\n\n        return null;\n    }\n\n    public SchemaObject findTableOrView(String tableName) {\n        long hashCode64 = FnvHash.hashCode64(tableName);\n        return findTableOrView(hashCode64);\n    }\n\n    public SchemaObject findTableOrView(long hashCode64) {\n        SchemaObject object = objects.get(hashCode64);\n\n        if (object == null) {\n            return null;\n        }\n\n        SchemaObjectType type = object.getType();\n        if (type == SchemaObjectType.Table || type == SchemaObjectType.View) {\n            return object;\n        }\n\n        return null;\n    }\n\n    public SchemaObject findFunction(String functionName) {\n        functionName = SQLUtils.normalize(functionName);\n        // FnvHash.hashCode64 is case insensitivity\n        return functions.get(FnvHash.hashCode64(functionName));\n    }\n\n    public boolean isSequence(String name) {\n        long nameHashCode64 = FnvHash.hashCode64(name);\n        SchemaObject object = objects.get(nameHashCode64);\n        return object != null\n                && object.getType() == SchemaObjectType.Sequence;\n    }\n\n    public SchemaObject findTable(SQLTableSource tableSource, String alias) {\n        if (tableSource instanceof SQLExprTableSource) {\n            if (StringUtils.equalsIgnoreCase(alias, tableSource.computeAlias())) {\n                SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;\n\n                SchemaObject tableObject = exprTableSource.getSchemaObject();\n                if (tableObject != null) {\n                    return tableObject;\n                }\n\n                SQLExpr expr = exprTableSource.getExpr();\n                if (expr instanceof SQLIdentifierExpr) {\n                    long tableNameHashCode64 = ((SQLIdentifierExpr) expr).nameHashCode64();\n\n                    tableObject = findTable(tableNameHashCode64);\n                    if (tableObject != null) {\n                        exprTableSource.setSchemaObject(tableObject);\n                    }\n                    return tableObject;\n                }\n\n                if (expr instanceof SQLPropertyExpr) {\n                    long tableNameHashCode64 = ((SQLPropertyExpr) expr).nameHashCode64();\n\n                    tableObject = findTable(tableNameHashCode64);\n                    if (tableObject != null) {\n                        exprTableSource.setSchemaObject(tableObject);\n                    }\n                    return tableObject;\n                }\n            }\n            return null;\n        }\n\n        if (tableSource instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n            SQLTableSource left = join.getLeft();\n\n            SchemaObject tableObject = findTable(left, alias);\n            if (tableObject != null) {\n                return tableObject;\n            }\n\n            SQLTableSource right = join.getRight();\n            tableObject = findTable(right, alias);\n            return tableObject;\n        }\n\n        return null;\n    }\n\n    public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLSelectItem selectItem) {\n        if (selectItem == null) {\n            return null;\n        }\n\n        return findColumn(tableSource, selectItem.getExpr());\n    }\n\n    public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLExpr expr) {\n        SchemaObject object = findTable(tableSource, expr);\n        if (object != null) {\n            if (expr instanceof SQLAggregateExpr) {\n                SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr;\n                String function = aggregateExpr.getMethodName();\n                if (\"min\".equalsIgnoreCase(function)\n                        || \"max\".equalsIgnoreCase(function)) {\n                    SQLExpr arg = aggregateExpr.getArguments().get(0);\n                    expr = arg;\n                }\n            }\n\n            if (expr instanceof SQLName) {\n                return object.findColumn(((SQLName) expr).getSimpleName());\n            }\n        }\n\n        return null;\n    }\n\n    public SchemaObject findTable(SQLTableSource tableSource, SQLSelectItem selectItem) {\n        if (selectItem == null) {\n            return null;\n        }\n\n        return findTable(tableSource, selectItem.getExpr());\n    }\n\n    public SchemaObject findTable(SQLTableSource tableSource, SQLExpr expr) {\n        if (expr instanceof SQLAggregateExpr) {\n            SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr;\n            String function = aggregateExpr.getMethodName();\n            if (\"min\".equalsIgnoreCase(function)\n                    || \"max\".equalsIgnoreCase(function)) {\n                SQLExpr arg = aggregateExpr.getArguments().get(0);\n                return findTable(tableSource, arg);\n            }\n        }\n\n        if (expr instanceof SQLPropertyExpr) {\n            String ownerName = ((SQLPropertyExpr) expr).getOwnernName();\n            return findTable(tableSource, ownerName);\n        }\n\n        if (expr instanceof SQLAllColumnExpr || expr instanceof SQLIdentifierExpr) {\n            if (tableSource instanceof SQLExprTableSource) {\n                return findTable(tableSource, tableSource.computeAlias());\n            }\n\n            if (tableSource instanceof SQLJoinTableSource) {\n                SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n\n                SchemaObject table = findTable(join.getLeft(), expr);\n                if (table == null) {\n                    table = findTable(join.getRight(), expr);\n                }\n                return table;\n            }\n            return null;\n        }\n\n        return null;\n    }\n\n    public Map<String, SchemaObject> getTables(SQLTableSource x) {\n        Map<String, SchemaObject> tables = new LinkedHashMap<String, SchemaObject>();\n        computeTables(x, tables);\n        return tables;\n    }\n\n    protected void computeTables(SQLTableSource x, Map<String, SchemaObject> tables) {\n        if (x == null) {\n            return;\n        }\n\n        if (x instanceof SQLExprTableSource) {\n            SQLExprTableSource exprTableSource = (SQLExprTableSource) x;\n\n            SQLExpr expr = exprTableSource.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                long tableNameHashCode64 = ((SQLIdentifierExpr) expr).nameHashCode64();\n                String tableName = ((SQLIdentifierExpr) expr).getName();\n\n                SchemaObject table = exprTableSource.getSchemaObject();\n                if (table == null) {\n                    table = findTable(tableNameHashCode64);\n\n                    if (table != null) {\n                        exprTableSource.setSchemaObject(table);\n                    }\n                }\n\n                if (table != null) {\n                    tables.put(tableName, table);\n\n                    String alias = x.getAlias();\n                    if (alias != null && !alias.equalsIgnoreCase(tableName)) {\n                        tables.put(alias, table);\n                    }\n                }\n            }\n\n            return;\n        }\n\n        if (x instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) x;\n            computeTables(join.getLeft(), tables);\n            computeTables(join.getRight(), tables);\n        }\n    }\n\n    public int getTableCount() {\n        int count = 0;\n        for (SchemaObject object : this.objects.values()) {\n            if (object.getType() == SchemaObjectType.Table) {\n                count++;\n            }\n        }\n        return count;\n    }\n\n    public Collection<SchemaObject> getObjects() {\n        return this.objects.values();\n    }\n\n    public boolean removeObject(Long nameHashCode64) {\n        return this.objects.remove(nameHashCode64) != null;\n    }\n\n    public int getViewCount() {\n        int count = 0;\n        for (SchemaObject object : this.objects.values()) {\n            if (object.getType() == SchemaObjectType.View) {\n                count++;\n            }\n        }\n        return count;\n    }\n\n    public List<String> showTables() {\n        List<String> tables = new ArrayList<String>(objects.size());\n        for (SchemaObject object : objects.values()) {\n            if (object.getType() == SchemaObjectType.Table) {\n                tables.add(object.getName());\n            }\n        }\n        Collections.sort(tables);\n        return tables;\n    }\n\n    public String getCatalog() {\n        return catalog;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/SchemaObject.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.repository;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.ast.statement.SQLUniqueConstraint;\nimport com.alibaba.druid.util.FnvHash;\n\n/**\n * Created by wenshao on 03/06/2017.\n */\npublic class SchemaObject {\n    private final Schema schema;\n    private final String name;\n    private final long hashCode64;\n\n    private final SchemaObjectType type;\n    private SQLStatement statement;\n    private long rowCount = -1;\n\n    protected SchemaObject(Schema schema, String name, SchemaObjectType type) {\n        this(schema, name, type, null);\n    }\n\n    protected SchemaObject(Schema schema, String name, SchemaObjectType type, SQLStatement statement) {\n        this.schema = schema;\n        this.name = name;\n        this.type = type;\n        this.statement = statement;\n\n        this.hashCode64 = FnvHash.hashCode64(name);\n    }\n\n    public SchemaObject clone() {\n        SchemaObject x = new SchemaObject(schema, name, type);\n\n        if (statement != null) {\n            x.statement = statement.clone();\n        }\n        x.rowCount = rowCount;\n\n        return x;\n    }\n\n    public long nameHashCode64() {\n        return hashCode64;\n    }\n\n    public static enum Type {\n        Sequence, Table, View, Index, Function\n    }\n\n    public SQLStatement getStatement() {\n        return statement;\n    }\n\n    public SQLColumnDefinition findColumn(String columName) {\n        long hash = FnvHash.hashCode64(columName);\n        return findColumn(hash);\n    }\n\n    public SQLColumnDefinition findColumn(long columNameHash) {\n        if (statement == null) {\n            return null;\n        }\n\n        if (statement instanceof SQLCreateTableStatement) {\n            return ((SQLCreateTableStatement) statement).findColumn(columNameHash);\n        }\n\n        return null;\n    }\n\n    public boolean matchIndex(String columnName) {\n        if (statement == null) {\n            return false;\n        }\n\n        if (statement instanceof SQLCreateTableStatement) {\n            SQLTableElement index = ((SQLCreateTableStatement) statement).findIndex(columnName);\n            return index != null;\n        }\n\n        return false;\n    }\n\n    public boolean matchKey(String columnName) {\n        if (statement == null) {\n            return false;\n        }\n\n        if (statement instanceof SQLCreateTableStatement) {\n            SQLTableElement index = ((SQLCreateTableStatement) statement).findIndex(columnName);\n            return index instanceof SQLUniqueConstraint;\n        }\n\n        return false;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public SchemaObjectType getType() {\n        return type;\n    }\n\n    public long getRowCount() {\n        return rowCount;\n    }\n\n    public Schema getSchema() {\n        return schema;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/SchemaObjectType.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.repository;\n\n/**\n * Created by wenshao on 08/06/2017.\n */\npublic enum SchemaObjectType {\n    Sequence, Table, View, Index, Function\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/SchemaRepository.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.repository;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.FastsqlException;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.repository.function.Function;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Created by wenshao on 03/06/2017.\n */\npublic class SchemaRepository {\n    private static Log LOG = LogFactory.getLog(SchemaRepository.class);\n\n    private Schema defaultSchema;\n    protected DbType dbType;\n    protected DbType schemaDbType;\n    protected SQLASTVisitor consoleVisitor;\n    protected Map<String, Schema> schemas = new LinkedHashMap<String, Schema>();\n    protected final Map<Long, Function> internalFunctions = new ConcurrentHashMap<Long, Function>(16, 0.75f, 1);\n    protected SchemaLoader schemaLoader;\n\n    public SchemaRepository() {\n    }\n\n    public SchemaRepository(DbType dbType) {\n        this(dbType, dbType);\n    }\n\n    public SchemaRepository(DbType dbType, DbType schemaDbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n        if (schemaDbType == null) {\n            schemaDbType = dbType;\n        }\n\n        this.dbType = dbType;\n        this.schemaDbType = schemaDbType;\n\n        switch (dbType) {\n            case mysql:\n                consoleVisitor = new MySqlConsoleSchemaVisitor();\n                break;\n            case oracle:\n                consoleVisitor = new OracleConsoleSchemaVisitor();\n                break;\n            case sqlserver:\n                consoleVisitor = new SqlServerConsoleSchemaVisitor();\n                break;\n            default:\n                consoleVisitor = new DefaultConsoleSchemaVisitor();\n                break;\n        }\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public String getDefaultSchemaName() {\n        return getDefaultSchema().getName();\n    }\n\n    public void setDefaultSchema(String name) {\n        if (name == null) {\n            defaultSchema = null;\n            return;\n        }\n\n        String normalizedName = SQLUtils.normalize(name)\n                .toLowerCase();\n\n        Schema defaultSchema = schemas.get(normalizedName);\n        if (defaultSchema != null) {\n            this.defaultSchema = defaultSchema;\n            return;\n        }\n\n        if (this.defaultSchema != null\n                && this.defaultSchema.getName() == null) {\n            this.defaultSchema.setName(name);\n\n            schemas.put(normalizedName, this.defaultSchema);\n            return;\n        }\n\n        defaultSchema = new Schema(this);\n        defaultSchema.setName(name);\n        schemas.put(normalizedName, defaultSchema);\n        this.defaultSchema = defaultSchema;\n    }\n\n    public Schema findSchema(String schema) {\n        return findSchema(schema, false);\n    }\n\n    protected Schema findSchema(String name, boolean create) {\n        if (name == null || name.length() == 0) {\n            return getDefaultSchema();\n        }\n\n        name = SQLUtils.normalize(name);\n        String normalizedName = name.toLowerCase();\n\n        if (getDefaultSchema() != null && defaultSchema.getName() == null && create) {\n            defaultSchema.setName(name);\n            schemas.put(normalizedName, defaultSchema);\n            return defaultSchema;\n        }\n\n        Schema schema = schemas.get(normalizedName);\n        if (schema == null && create) {\n            int p = name.indexOf('.');\n\n            String catalog = null;\n            if (p != -1) {\n                catalog = name.substring(0, p);\n            }\n            schema = new Schema(this, catalog, name);\n            schemas.put(normalizedName, schema);\n        }\n        return schema;\n    }\n\n    public Schema getDefaultSchema() {\n        if (defaultSchema == null) {\n            defaultSchema = new Schema(this);\n        }\n\n        return defaultSchema;\n    }\n\n    public void setDefaultSchema(Schema schema) {\n        this.defaultSchema = schema;\n    }\n\n    public SchemaObject findTable(String tableName) {\n        if (tableName.indexOf('.') != -1) {\n            SQLExpr expr = SQLUtils.toSQLExpr(tableName, dbType);\n            if (!(expr instanceof SQLIdentifierExpr)) {\n                return findTable((SQLName) expr);\n            }\n        }\n        SchemaObject object = getDefaultSchema()\n                .findTable(tableName);\n\n        if (object != null) {\n            return object;\n        }\n\n        String ddl = loadDDL(tableName);\n        if (ddl == null) {\n            return null;\n        }\n\n        DbType schemaDbType = this.schemaDbType;\n        if (schemaDbType == null) {\n            schemaDbType = dbType;\n        }\n\n        SchemaObject schemaObject = acceptDDL(ddl, schemaDbType);\n        if (schemaObject != null) {\n            return schemaObject;\n        }\n\n        return getDefaultSchema()\n                .findTable(tableName);\n    }\n\n    public SchemaObject findView(String viewName) {\n        SchemaObject object = getDefaultSchema()\n                .findView(viewName);\n\n        if (object != null) {\n            return object;\n        }\n\n        String ddl = loadDDL(viewName);\n        if (ddl == null) {\n            return null;\n        }\n\n        acceptDDL(ddl);\n\n        return getDefaultSchema()\n                .findView(viewName);\n    }\n\n    public SchemaObject findTable(long tableNameHash) {\n        return getDefaultSchema()\n                .findTable(tableNameHash);\n    }\n\n    public SchemaObject findTableOrView(String tableName) {\n        return findTableOrView(tableName, true);\n    }\n\n    public SchemaObject findTableOrView(String tableName, boolean onlyCurrent) {\n        Schema schema = getDefaultSchema();\n\n        SchemaObject object = schema.findTableOrView(tableName);\n        if (object != null) {\n            return object;\n        }\n\n        for (Schema s : this.schemas.values()) {\n            if (s == schema) {\n                continue;\n            }\n\n            object = schema.findTableOrView(tableName);\n            if (object != null) {\n                return object;\n            }\n        }\n\n        String ddl = loadDDL(tableName);\n        if (ddl == null) {\n            return null;\n        }\n\n        acceptDDL(ddl);\n\n        // double check\n        object = schema.findTableOrView(tableName);\n        if (object != null) {\n            return object;\n        }\n\n        for (Schema s : this.schemas.values()) {\n            if (s == schema) {\n                continue;\n            }\n\n            object = schema.findTableOrView(tableName);\n            if (object != null) {\n                return object;\n            }\n        }\n\n        return null;\n    }\n\n    public Collection<Schema> getSchemas() {\n        return schemas.values();\n    }\n\n    public SchemaObject findFunction(String functionName) {\n        return getDefaultSchema().findFunction(functionName);\n    }\n\n    public void acceptDDL(String ddl) {\n        acceptDDL(ddl, schemaDbType);\n    }\n\n    public SchemaObject acceptDDL(String ddl, DbType dbType) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(ddl, dbType);\n        for (SQLStatement stmt : stmtList) {\n            if (stmt instanceof SQLCreateTableStatement) {\n                SchemaObject schemaObject = acceptCreateTable((SQLCreateTableStatement) stmt);\n                if (stmtList.size() == 1) {\n                    return schemaObject;\n                }\n            } else if (stmt instanceof SQLCreateViewStatement) {\n                SchemaObject schemaObject = acceptView((SQLCreateViewStatement) stmt);\n                if (stmtList.size() == 1) {\n                    return schemaObject;\n                }\n            } else {\n                accept(stmt);\n            }\n        }\n\n        return null;\n    }\n\n    public void accept(SQLStatement stmt) {\n        stmt.accept(consoleVisitor);\n    }\n\n    public boolean isSequence(String name) {\n        return getDefaultSchema().isSequence(name);\n    }\n\n    public SchemaObject findTable(SQLTableSource tableSource, String alias) {\n        return getDefaultSchema().findTable(tableSource, alias);\n    }\n\n    public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLSelectItem selectItem) {\n        return getDefaultSchema().findColumn(tableSource, selectItem);\n    }\n\n    public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLExpr expr) {\n        return getDefaultSchema().findColumn(tableSource, expr);\n    }\n\n    public SchemaObject findTable(SQLTableSource tableSource, SQLSelectItem selectItem) {\n        return getDefaultSchema().findTable(tableSource, selectItem);\n    }\n\n    public SchemaObject findTable(SQLTableSource tableSource, SQLExpr expr) {\n        return getDefaultSchema().findTable(tableSource, expr);\n    }\n\n    public Map<String, SchemaObject> getTables(SQLTableSource x) {\n        return getDefaultSchema().getTables(x);\n    }\n\n    public boolean removeTable(SQLName name) {\n        return getDefaultSchema()\n                .removeObject(\n                        name.nameHashCode64());\n    }\n\n    public int getTableCount() {\n        return getDefaultSchema().getTableCount();\n    }\n\n    public Collection<SchemaObject> getObjects() {\n        return getDefaultSchema().getObjects();\n    }\n\n    public int getViewCount() {\n        return getDefaultSchema().getViewCount();\n    }\n\n    public void resolve(SQLSelectStatement stmt, SchemaResolveVisitor.Option... options) {\n        if (stmt == null) {\n            return;\n        }\n\n        SchemaResolveVisitor resolveVisitor = createResolveVisitor(options);\n        resolveVisitor.visit(stmt);\n    }\n\n    public void resolve(SQLSelect select, SchemaResolveVisitor.Option... options) {\n        if (select == null) {\n            return;\n        }\n\n        SchemaResolveVisitor resolveVisitor = createResolveVisitor(options);\n        resolveVisitor.visit(select);\n    }\n\n    public void resolve(SQLSelectQueryBlock queryBlock, SchemaResolveVisitor.Option... options) {\n        if (queryBlock == null) {\n            return;\n        }\n\n        SchemaResolveVisitor resolveVisitor = createResolveVisitor(options);\n        resolveVisitor.visit(queryBlock);\n    }\n\n    public void resolve(SQLStatement stmt, SchemaResolveVisitor.Option... options) {\n        if (stmt == null) {\n            return;\n        }\n\n        SchemaResolveVisitor resolveVisitor = createResolveVisitor(options);\n        if (stmt instanceof SQLSelectStatement) {\n            resolveVisitor.visit((SQLSelectStatement) stmt);\n        } else {\n            stmt.accept(resolveVisitor);\n        }\n    }\n\n    private SchemaResolveVisitor createResolveVisitor(SchemaResolveVisitor.Option... options) {\n        int optionsValue = SchemaResolveVisitor.Option.of(options);\n\n        SchemaResolveVisitor resolveVisitor;\n        switch (dbType) {\n            case mysql:\n            case mariadb:\n            case tidb:\n            case sqlite:\n            case polardbx:\n                resolveVisitor = new SchemaResolveVisitorFactory.MySqlResolveVisitor(this, optionsValue);\n                break;\n            case oracle:\n                resolveVisitor = new SchemaResolveVisitorFactory.OracleResolveVisitor(this, optionsValue);\n                break;\n            case db2:\n                resolveVisitor = new SchemaResolveVisitorFactory.DB2ResolveVisitor(this, optionsValue);\n                break;\n            case odps:\n                resolveVisitor = new SchemaResolveVisitorFactory.OdpsResolveVisitor(this, optionsValue);\n                break;\n            case hive:\n                resolveVisitor = new SchemaResolveVisitorFactory.HiveResolveVisitor(this, optionsValue);\n                break;\n            case postgresql:\n            case greenplum:\n            case edb:\n                resolveVisitor = new SchemaResolveVisitorFactory.PGResolveVisitor(this, optionsValue);\n                break;\n            case sqlserver:\n                resolveVisitor = new SchemaResolveVisitorFactory.SQLServerResolveVisitor(this, optionsValue);\n                break;\n            default:\n                resolveVisitor = new SchemaResolveVisitorFactory.SQLResolveVisitor(this, optionsValue);\n                break;\n        }\n\n        return resolveVisitor;\n    }\n\n    public String resolve(String input) {\n        SchemaResolveVisitor visitor\n                = createResolveVisitor(\n                SchemaResolveVisitor.Option.ResolveAllColumn,\n                SchemaResolveVisitor.Option.ResolveIdentifierAlias);\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(input, dbType);\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n\n        return SQLUtils.toSQLString(stmtList, dbType);\n    }\n\n    public String console(String input) {\n        try {\n            StringBuilder buf = new StringBuilder();\n\n            List<SQLStatement> stmtList = SQLUtils.parseStatements(input, dbType, SQLParserFeature.IgnoreNameQuotes);\n\n            for (SQLStatement stmt : stmtList) {\n                if (stmt instanceof SQLShowColumnsStatement) {\n                    SQLShowColumnsStatement showColumns = ((SQLShowColumnsStatement) stmt);\n                    SQLName db = showColumns.getDatabase();\n                    Schema schema;\n                    if (db == null) {\n                        schema = getDefaultSchema();\n                    } else {\n                        schema = findSchema(db.getSimpleName());\n                    }\n\n                    SQLName table = null;\n                    SchemaObject schemaObject = null;\n                    if (schema != null) {\n                        table = showColumns.getTable();\n                        schemaObject = schema.findTable(table.nameHashCode64());\n                    }\n\n                    if (schemaObject == null) {\n                        buf.append(\"ERROR 1146 (42S02): Table '\")\n                                .append(table)\n                                .append(\"' doesn't exist\\n\");\n                    } else {\n                        MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();\n                        createTableStmt.showColumns(buf);\n                    }\n                } else if (stmt instanceof SQLShowCreateTableStatement) {\n                    SQLShowCreateTableStatement showCreateTableStmt = (SQLShowCreateTableStatement) stmt;\n                    SQLName table = showCreateTableStmt.getName();\n                    SchemaObject schemaObject = findTable(table);\n                    if (schemaObject == null) {\n                        buf.append(\"ERROR 1146 (42S02): Table '\")\n                                .append(table)\n                                .append(\"' doesn't exist\\n\");\n                    } else {\n                        MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();\n                        createTableStmt.output(buf);\n                    }\n                } else if (stmt instanceof MySqlRenameTableStatement) {\n                    MySqlRenameTableStatement renameStmt = (MySqlRenameTableStatement) stmt;\n                    for (MySqlRenameTableStatement.Item item : renameStmt.getItems()) {\n                        renameTable(item.getName(), item.getTo());\n                    }\n                } else if (stmt instanceof SQLShowTablesStatement) {\n                    SQLShowTablesStatement showTables = (SQLShowTablesStatement) stmt;\n                    SQLName database = showTables.getDatabase();\n\n                    Schema schema;\n                    if (database == null) {\n                        schema = getDefaultSchema();\n                    } else {\n                        schema = findSchema(database.getSimpleName());\n                    }\n                    if (schema != null) {\n                        for (String table : schema.showTables()) {\n                            buf.append(table);\n                            buf.append('\\n');\n                        }\n                    }\n                } else {\n                    stmt.accept(consoleVisitor);\n                }\n            }\n\n            if (buf.length() == 0) {\n                return \"\\n\";\n            }\n\n            return buf.toString();\n        } catch (IOException ex) {\n            throw new FastsqlException(\"exeucte command error.\", ex);\n        }\n    }\n\n    public SchemaObject findTable(SQLName name) {\n        if (name instanceof SQLIdentifierExpr) {\n            return findTable(\n                    ((SQLIdentifierExpr) name).getName());\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) name;\n            SQLExpr owner = propertyExpr.getOwner();\n            String schema;\n            String catalog = null;\n            if (owner instanceof SQLIdentifierExpr) {\n                schema = ((SQLIdentifierExpr) owner).getName();\n            } else if (owner instanceof SQLPropertyExpr) {\n                schema = ((SQLPropertyExpr) owner).getName();\n                catalog = ((SQLPropertyExpr) owner).getOwnernName();\n            } else {\n                return null;\n            }\n\n            long tableHashCode64 = propertyExpr.nameHashCode64();\n\n            Schema schemaObj = findSchema(schema, false);\n            if (schemaObj != null) {\n                SchemaObject table = schemaObj.findTable(tableHashCode64);\n                if (table != null) {\n                    return table;\n                }\n            }\n\n            String ddl = loadDDL(catalog, schema, propertyExpr.getName());\n\n            if (ddl == null) {\n                schemaObj = findSchema(schema, true);\n            } else {\n                List<SQLStatement> stmtList = SQLUtils.parseStatements(ddl, schemaDbType);\n                for (SQLStatement stmt : stmtList) {\n                    accept(stmt);\n                }\n\n                if (stmtList.size() == 1) {\n                    SQLStatement stmt = stmtList.get(0);\n                    if (stmt instanceof SQLCreateTableStatement) {\n                        SQLCreateTableStatement createStmt = (SQLCreateTableStatement) stmt;\n                        String schemaName = createStmt.getSchema();\n                        schemaObj = findSchema(schemaName, true);\n                    }\n                }\n            }\n\n            if (schemaObj == null) {\n                return null;\n            }\n\n            return schemaObj.findTable(tableHashCode64);\n        }\n\n        return null;\n    }\n\n    public SchemaObject findView(SQLName name) {\n        if (name instanceof SQLIdentifierExpr) {\n            return findView(\n                    ((SQLIdentifierExpr) name).getName());\n        }\n\n        if (name instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) name;\n            SQLExpr owner = propertyExpr.getOwner();\n            String schema;\n            String catalog = null;\n            if (owner instanceof SQLIdentifierExpr) {\n                schema = ((SQLIdentifierExpr) owner).getName();\n            } else if (owner instanceof SQLPropertyExpr) {\n                schema = ((SQLPropertyExpr) owner).getName();\n                catalog = ((SQLPropertyExpr) owner).getOwnernName();\n            } else {\n                return null;\n            }\n\n            long tableHashCode64 = propertyExpr.nameHashCode64();\n\n            Schema schemaObj = findSchema(schema, false);\n            if (schemaObj != null) {\n                SchemaObject table = schemaObj.findView(tableHashCode64);\n                if (table != null) {\n                    return table;\n                }\n            }\n\n            String ddl = loadDDL(catalog, schema, propertyExpr.getName());\n\n            if (ddl == null) {\n                schemaObj = findSchema(schema, true);\n            } else {\n                List<SQLStatement> stmtList = SQLUtils.parseStatements(ddl, schemaDbType);\n                for (SQLStatement stmt : stmtList) {\n                    accept(stmt);\n                }\n\n                if (stmtList.size() == 1) {\n                    SQLStatement stmt = stmtList.get(0);\n                    if (stmt instanceof SQLCreateTableStatement) {\n                        SQLCreateTableStatement createStmt = (SQLCreateTableStatement) stmt;\n                        String schemaName = createStmt.getSchema();\n                        schemaObj = findSchema(schemaName, true);\n                    }\n                }\n            }\n\n            if (schemaObj == null) {\n                return null;\n            }\n\n            return schemaObj.findView(tableHashCode64);\n        }\n\n        return null;\n    }\n\n    private boolean renameTable(SQLName name, SQLName to) {\n        Schema schema;\n        if (name instanceof SQLPropertyExpr) {\n            String schemaName = ((SQLPropertyExpr) name).getOwnernName();\n            schema = findSchema(schemaName);\n        } else {\n            schema = getDefaultSchema();\n        }\n\n        if (schema == null) {\n            return false;\n        }\n\n        long nameHashCode64 = name.nameHashCode64();\n        SchemaObject schemaObject = schema.findTable(nameHashCode64);\n        if (schemaObject != null) {\n            MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) schemaObject.getStatement();\n            if (createTableStmt != null) {\n                createTableStmt.setName(to.clone());\n                acceptCreateTable(createTableStmt);\n            }\n\n            schema.objects.remove(nameHashCode64);\n        }\n        return true;\n    }\n\n    public SchemaObject findTable(SQLExprTableSource x) {\n        if (x == null) {\n            return null;\n        }\n\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLName) {\n            return findTable((SQLName) expr);\n        }\n\n        return null;\n    }\n\n    public class MySqlConsoleSchemaVisitor extends MySqlASTVisitorAdapter {\n        public boolean visit(SQLDropSequenceStatement x) {\n            acceptDropSequence(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateSequenceStatement x) {\n            acceptCreateSequence(x);\n            return false;\n        }\n\n        public boolean visit(MySqlCreateTableStatement x) {\n            acceptCreateTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateTableStatement x) {\n            acceptCreateTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLDropTableStatement x) {\n            acceptDropTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateIndexStatement x) {\n            acceptCreateIndex(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateFunctionStatement x) {\n            acceptCreateFunction(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterTableStatement x) {\n            acceptAlterTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLUseStatement x) {\n            String schema = x.getDatabase().getSimpleName();\n            setDefaultSchema(schema);\n            return false;\n        }\n\n        public boolean visit(SQLDropIndexStatement x) {\n            acceptDropIndex(x);\n            return false;\n        }\n    }\n\n    public class OracleConsoleSchemaVisitor extends OracleASTVisitorAdapter {\n        public boolean visit(SQLDropSequenceStatement x) {\n            acceptDropSequence(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateSequenceStatement x) {\n            acceptCreateSequence(x);\n            return false;\n        }\n\n        public boolean visit(OracleCreateTableStatement x) {\n            visit((SQLCreateTableStatement) x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateTableStatement x) {\n            acceptCreateTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLDropTableStatement x) {\n            acceptDropTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateIndexStatement x) {\n            acceptCreateIndex(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateFunctionStatement x) {\n            acceptCreateFunction(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterTableStatement x) {\n            acceptAlterTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLUseStatement x) {\n            String schema = x.getDatabase().getSimpleName();\n            setDefaultSchema(schema);\n            return false;\n        }\n\n        public boolean visit(SQLDropIndexStatement x) {\n            acceptDropIndex(x);\n            return false;\n        }\n    }\n\n    public class SqlServerConsoleSchemaVisitor extends SQLServerASTVisitorAdapter {\n        public SqlServerConsoleSchemaVisitor() {\n            this.dbType = DbType.sqlserver;\n        }\n\n        public boolean visit(SQLDropSequenceStatement x) {\n            acceptDropSequence(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateSequenceStatement x) {\n            acceptCreateSequence(x);\n            return false;\n        }\n\n        public boolean visit(OracleCreateTableStatement x) {\n            visit((SQLCreateTableStatement) x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateTableStatement x) {\n            acceptCreateTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLDropTableStatement x) {\n            acceptDropTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateIndexStatement x) {\n            acceptCreateIndex(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateFunctionStatement x) {\n            acceptCreateFunction(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterTableStatement x) {\n            acceptAlterTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLUseStatement x) {\n            String schema = x.getDatabase().getSimpleName();\n            setDefaultSchema(schema);\n            return false;\n        }\n\n        public boolean visit(SQLDropIndexStatement x) {\n            acceptDropIndex(x);\n            return false;\n        }\n    }\n\n    public class DefaultConsoleSchemaVisitor extends SQLASTVisitorAdapter {\n        public boolean visit(SQLDropSequenceStatement x) {\n            acceptDropSequence(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateSequenceStatement x) {\n            acceptCreateSequence(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateTableStatement x) {\n            acceptCreateTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLDropTableStatement x) {\n            acceptDropTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterViewStatement x) {\n            acceptView(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateIndexStatement x) {\n            acceptCreateIndex(x);\n            return false;\n        }\n\n        public boolean visit(SQLCreateFunctionStatement x) {\n            acceptCreateFunction(x);\n            return false;\n        }\n\n        public boolean visit(SQLAlterTableStatement x) {\n            acceptAlterTable(x);\n            return false;\n        }\n\n        public boolean visit(SQLDropIndexStatement x) {\n            acceptDropIndex(x);\n            return false;\n        }\n    }\n\n    SchemaObject acceptCreateTable(MySqlCreateTableStatement x) {\n        SQLExprTableSource like = x.getLike();\n        if (like != null) {\n            SchemaObject table = findTable((SQLName) like.getExpr());\n            if (table != null) {\n                MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) table.getStatement();\n                MySqlCreateTableStatement stmtCloned = stmt.clone();\n                stmtCloned.setName(x.getName().clone());\n                acceptCreateTable((SQLCreateTableStatement) stmtCloned);\n                return table;\n            }\n        }\n\n        return acceptCreateTable((SQLCreateTableStatement) x);\n    }\n\n    SchemaObject acceptCreateTable(SQLCreateTableStatement x) {\n        SQLCreateTableStatement x1 = x.clone();\n        String schemaName = x1.getSchema();\n\n        Schema schema = findSchema(schemaName, true);\n\n        SQLSelect select = x1.getSelect();\n\n        if (select != null) {\n            select.accept(createResolveVisitor(SchemaResolveVisitor.Option.ResolveAllColumn));\n\n            SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();\n            this.resolve(queryBlock);\n\n            if (queryBlock != null) {\n                List<SQLSelectItem> selectList = queryBlock.getSelectList();\n                for (SQLSelectItem selectItem : selectList) {\n                    SQLExpr selectItemExpr = selectItem.getExpr();\n                    if (selectItemExpr instanceof SQLAllColumnExpr\n                            || (selectItemExpr instanceof SQLPropertyExpr && ((SQLPropertyExpr) selectItemExpr).getName().equals(\"*\"))) {\n                        continue;\n                    }\n\n                    SQLColumnDefinition column = null;\n                    if (selectItemExpr instanceof SQLName) {\n                        final SQLColumnDefinition resolvedColumn = ((SQLName) selectItemExpr).getResolvedColumn();\n                        if (resolvedColumn != null) {\n                            column = new SQLColumnDefinition();\n                            column.setDataType(\n                                    selectItem.computeDataType());\n                            if (DbType.mysql == dbType) {\n                                if (resolvedColumn.getDefaultExpr() != null) {\n                                    column.setDefaultExpr(resolvedColumn.getDefaultExpr().clone());\n                                }\n                                if (resolvedColumn.getConstraints().size() > 0) {\n                                    for (SQLColumnConstraint constraint : resolvedColumn.getConstraints()) {\n                                        column.addConstraint(constraint.clone());\n                                    }\n                                }\n                                if (resolvedColumn.getComment() != null) {\n                                    column.setComment(resolvedColumn.getComment());\n                                }\n                            }\n                        }\n                    }\n\n                    if (column == null) {\n                        column = new SQLColumnDefinition();\n                        SQLDataType dataType = null;\n                        try {\n                            dataType = selectItem.computeDataType();\n                        } catch (Throwable ignored) {\n                            // ignore\n                        }\n                        if (dataType != null) {\n                            column.setDataType(dataType.clone());\n                        }\n                    }\n\n                    String name = selectItem.computeAlias();\n                    column.setName(name);\n                    column.setDbType(dbType);\n                    x1.addColumn(column);\n                }\n                if (x1.getTableElementList().size() > 0) {\n                    x1.setSelect(null);\n                }\n            }\n        }\n\n        SQLExprTableSource like = x1.getLike();\n        if (like != null) {\n            SchemaObject tableObject = null;\n\n            SQLName name = like.getName();\n            if (name != null) {\n                tableObject = findTable(name);\n            }\n\n            SQLCreateTableStatement tableStmt = null;\n            if (tableObject != null) {\n                SQLStatement stmt = tableObject.getStatement();\n                if (stmt instanceof SQLCreateTableStatement) {\n                    tableStmt = (SQLCreateTableStatement) stmt;\n                }\n            }\n\n            if (tableStmt != null) {\n                SQLName tableName = x1.getName();\n                tableStmt.cloneTo(x1);\n                x1.setName(tableName);\n                x1.setLike((SQLExprTableSource) null);\n            }\n        }\n\n        x1.setSchema(null);\n\n        String name = x1.computeName();\n        SchemaObject table = schema.findTableOrView(name);\n        if (table != null) {\n            if (x1.isIfNotExists()) {\n                return table;\n            }\n\n            LOG.info(\"replaced table '\" + name + \"'\");\n        }\n\n        table = new SchemaObject(schema, name, SchemaObjectType.Table, x1);\n        schema.objects.put(table.nameHashCode64(), table);\n        return table;\n    }\n\n    boolean acceptDropTable(SQLDropTableStatement x) {\n        for (SQLExprTableSource table : x.getTableSources()) {\n            String schemaName = table.getSchema();\n            Schema schema = findSchema(schemaName, false);\n            if (schema == null) {\n                continue;\n            }\n            long nameHashCode64 = table.getName().nameHashCode64();\n            schema.objects.remove(nameHashCode64);\n        }\n        return true;\n    }\n\n    SchemaObject acceptView(SQLCreateViewStatement x) {\n        String schemaName = x.getSchema();\n\n        Schema schema = findSchema(schemaName, true);\n\n        String name = x.computeName();\n        SchemaObject view = schema.findTableOrView(name);\n        if (view != null) {\n            return view;\n        }\n\n        SchemaObject object = new SchemaObject(schema, name, SchemaObjectType.View, x.clone());\n        long nameHashCode64 = FnvHash.hashCode64(name);\n        schema.objects.put(nameHashCode64, object);\n        return object;\n    }\n\n    boolean acceptView(SQLAlterViewStatement x) {\n        String schemaName = x.getSchema();\n\n        Schema schema = findSchema(schemaName, true);\n\n        String name = x.computeName();\n        SchemaObject view = schema.findTableOrView(name);\n        if (view != null) {\n            return false;\n        }\n\n        SchemaObject object = new SchemaObject(schema, name, SchemaObjectType.View, x.clone());\n        schema.objects.put(object.nameHashCode64(), object);\n        return true;\n    }\n\n    boolean acceptDropIndex(SQLDropIndexStatement x) {\n        if (x.getTableName() == null) {\n            return false;\n        }\n        SQLName table = x.getTableName().getName();\n        SchemaObject object = findTable(table);\n\n        if (object != null) {\n            SQLCreateTableStatement stmt = (SQLCreateTableStatement) object.getStatement();\n            if (stmt != null) {\n                stmt.apply(x);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    boolean acceptCreateIndex(SQLCreateIndexStatement x) {\n        String schemaName = x.getSchema();\n\n        Schema schema = findSchema(schemaName, true);\n\n        String name = x.getName().getSimpleName();\n        SchemaObject object = new SchemaObject(schema, name, SchemaObjectType.Index, x.clone());\n        schema.objects.put(object.nameHashCode64(), object);\n\n        return true;\n    }\n\n    boolean acceptCreateFunction(SQLCreateFunctionStatement x) {\n        String schemaName = x.getSchema();\n        Schema schema = findSchema(schemaName, true);\n\n        String name = x.getName().getSimpleName();\n        SchemaObject object = new SchemaObject(schema, name, SchemaObjectType.Function, x.clone());\n        schema.functions.put(object.nameHashCode64(), object);\n\n        return true;\n    }\n\n    boolean acceptAlterTable(SQLAlterTableStatement x) {\n        String schemaName = x.getSchema();\n\n        if (dbType == DbType.sqlserver) {\n            SQLName tableName = x.getTableSource().getName();\n            if (tableName instanceof SQLPropertyExpr) {\n                SQLExpr owner = ((SQLPropertyExpr) tableName).getOwner();\n                if (owner instanceof SQLPropertyExpr) {\n                    schemaName = ((SQLPropertyExpr) owner).getName();\n                }\n            }\n        }\n\n        Schema schema = findSchema(schemaName, true);\n        SchemaObject object = schema.findTable(x.nameHashCode64());\n        schema.getTables(x.getTableSource());\n        if (object != null) {\n            SQLCreateTableStatement stmt = (SQLCreateTableStatement) object.getStatement();\n            if (stmt != null) {\n                stmt.apply(x);\n                x.getTableSource().setSchemaObject(object);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public boolean acceptCreateSequence(SQLCreateSequenceStatement x) {\n        String schemaName = x.getSchema();\n        Schema schema = findSchema(schemaName, true);\n\n        String name = x.getName().getSimpleName();\n        SchemaObject object = new SchemaObject(schema, name, SchemaObjectType.Sequence);\n        schema.objects.put(object.nameHashCode64(), object);\n        return false;\n    }\n\n    public boolean acceptDropSequence(SQLDropSequenceStatement x) {\n        String schemaName = x.getSchema();\n        Schema schema = findSchema(schemaName, true);\n\n        long nameHashCode64 = x.getName().nameHashCode64();\n        schema.objects.remove(nameHashCode64);\n        return false;\n    }\n\n    public SQLDataType findFuntionReturnType(long functionNameHashCode) {\n        if (functionNameHashCode == FnvHash.Constants.LEN || functionNameHashCode == FnvHash.Constants.LENGTH) {\n            return SQLIntegerExpr.DATA_TYPE;\n        }\n\n        return null;\n    }\n\n    protected String loadDDL(String table) {\n        if (table == null) {\n            return null;\n        }\n\n        table = SQLUtils.normalize(table, schemaDbType);\n\n        if (schemaLoader != null) {\n            return schemaLoader.loadDDL(null, null, table);\n        }\n        return null;\n    }\n\n    protected String loadDDL(String schema, String table) {\n        if (table == null) {\n            return null;\n        }\n\n        table = SQLUtils.normalize(table, dbType);\n        if (schema != null) {\n            schema = SQLUtils.normalize(schema, dbType);\n        }\n\n        if (schemaLoader != null) {\n            return schemaLoader.loadDDL(null, schema, table);\n        }\n        return null;\n    }\n\n    protected String loadDDL(String catalog, String schema, String table) {\n        if (table == null) {\n            return null;\n        }\n\n        table = SQLUtils.normalize(table, dbType);\n        if (schema != null) {\n            schema = SQLUtils.normalize(schema, dbType);\n        }\n        if (catalog != null) {\n            catalog = SQLUtils.normalize(catalog, dbType);\n        }\n\n        if (schemaLoader != null) {\n            return schemaLoader.loadDDL(catalog, schema, table);\n        }\n        return null;\n    }\n\n    public SchemaLoader getSchemaLoader() {\n        return schemaLoader;\n    }\n\n    public void setSchemaLoader(SchemaLoader schemaLoader) {\n        this.schemaLoader = schemaLoader;\n    }\n\n    public static interface SchemaLoader {\n        String loadDDL(String catalog, String schema, String objectName);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.repository;\n\nimport com.alibaba.druid.sql.ast.SQLDeclareItem;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.SQLOver;\nimport com.alibaba.druid.sql.ast.SQLParameter;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.druid.sql.repository.SchemaResolveVisitorFactory.*;\n\n/**\n * Created by wenshao on 03/08/2017.\n */\npublic interface SchemaResolveVisitor extends SQLASTVisitor {\n    boolean isEnabled(Option option);\n\n    int getOptions();\n\n    public static enum Option {\n        ResolveAllColumn,\n        ResolveIdentifierAlias,\n        CheckColumnAmbiguous;\n\n        private Option() {\n            mask = (1 << ordinal());\n        }\n\n        public final int mask;\n\n        public static int of(Option... options) {\n            if (options == null) {\n                return 0;\n            }\n\n            int value = 0;\n\n            for (Option option : options) {\n                value |= option.mask;\n            }\n\n            return value;\n        }\n    }\n\n    SchemaRepository getRepository();\n\n    Context getContext();\n\n    Context createContext(SQLObject object);\n\n    void popContext();\n\n    public static class Context {\n        public final Context parent;\n        public final SQLObject object;\n        public final int level;\n\n        private SQLTableSource tableSource;\n\n        private SQLTableSource from;\n\n        private Map<Long, SQLTableSource> tableSourceMap;\n\n        protected Map<Long, SQLDeclareItem> declares;\n\n        public Context(SQLObject object, Context parent) {\n            this.object = object;\n            this.parent = parent;\n            this.level = parent == null\n                    ? 0\n                    : parent.level + 1;\n        }\n\n        public SQLTableSource getFrom() {\n            return from;\n        }\n\n        public void setFrom(SQLTableSource from) {\n            this.from = from;\n        }\n\n        public SQLTableSource getTableSource() {\n            return tableSource;\n        }\n\n        public void setTableSource(SQLTableSource tableSource) {\n            this.tableSource = tableSource;\n        }\n\n        public void addTableSource(long alias_hash, SQLTableSource tableSource) {\n            if (tableSourceMap == null) {\n                tableSourceMap = new HashMap<Long, SQLTableSource>();\n            }\n\n            tableSourceMap.put(alias_hash, tableSource);\n        }\n\n        protected void declare(SQLDeclareItem x) {\n            if (declares == null) {\n                declares = new HashMap<Long, SQLDeclareItem>();\n            }\n            declares.put(x.getName().nameHashCode64(), x);\n        }\n\n        protected SQLDeclareItem findDeclare(long nameHash) {\n            if (declares == null) {\n                return null;\n            }\n            return declares.get(nameHash);\n        }\n\n        protected SQLTableSource findTableSource(long nameHash) {\n            SQLTableSource table = null;\n            if (tableSourceMap != null) {\n                table = tableSourceMap.get(nameHash);\n            }\n\n            return table;\n        }\n\n        protected SQLTableSource findTableSourceRecursive(long nameHash) {\n            for (Context ctx = this; ctx != null; ctx = ctx.parent) {\n                if (ctx.tableSourceMap != null) {\n                    SQLTableSource table = ctx.tableSourceMap.get(nameHash);\n                    if (table != null) {\n                        return table;\n                    }\n                }\n            }\n\n            return null;\n        }\n    }\n\n    default boolean visit(SQLSelectStatement x) {\n        resolve(this, x.getSelect());\n        return false;\n    }\n\n    default boolean visit(SQLSelect x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLWithSubqueryClause x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLIfStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLCreateFunctionStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLExprTableSource x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLSelectQueryBlock x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLForeignKeyImpl x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLIdentifierExpr x) {\n        resolveIdent(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLPropertyExpr x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLBinaryOpExpr x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLAllColumnExpr x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLCreateTableStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLUpdateStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLDeleteStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLAlterTableStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLInsertStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLParameter x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLDeclareItem x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLOver x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLMethodInvokeExpr x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLUnionQuery x) {\n        resolveUnion(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLMergeStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLCreateProcedureStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLBlockStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLReplaceStatement x) {\n        resolve(this, x);\n        return false;\n    }\n\n    default boolean visit(SQLCastExpr x) {\n        x.getExpr()\n                .accept(this);\n        return true;\n    }\n\n    default boolean visit(SQLFetchStatement x) {\n        resolve(this, x);\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.repository;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.db2.ast.DB2Object;\nimport com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCursorDeclareStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.*;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.PGUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nclass SchemaResolveVisitorFactory {\n    static class MySqlResolveVisitor extends MySqlASTVisitorAdapter implements SchemaResolveVisitor {\n        private SchemaRepository repository;\n        private int options;\n        private Context context;\n\n        public MySqlResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(MySqlRepeatStatement x) {\n            return true;\n        }\n\n        public boolean visit(MySqlDeclareStatement x) {\n            for (SQLDeclareItem declareItem : x.getVarList()) {\n                visit(declareItem);\n            }\n            return false;\n        }\n\n        public boolean visit(MySqlCursorDeclareStatement x) {\n            return true;\n        }\n\n        public boolean visit(MysqlForeignKey x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(MySqlSelectQueryBlock x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        public boolean visit(MySqlCreateTableStatement x) {\n            resolve(this, x);\n            SQLExprTableSource like = x.getLike();\n            if (like != null) {\n                like.accept(this);\n            }\n            return false;\n        }\n\n        public boolean visit(MySqlUpdateStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(MySqlDeleteStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(MySqlInsertStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static class DB2ResolveVisitor extends DB2ASTVisitorAdapter implements SchemaResolveVisitor {\n        private SchemaRepository repository;\n        private int options;\n        private Context context;\n\n        public DB2ResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(DB2SelectQueryBlock x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        public boolean visit(SQLIdentifierExpr x) {\n            long hash64 = x.hashCode64();\n            if (hash64 == FnvHash.Constants.CURRENT_DATE || hash64 == DB2Object.Constants.CURRENT_TIME) {\n                return false;\n            }\n\n            resolveIdent(this, x);\n            return true;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        @Override\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static class OracleResolveVisitor extends OracleASTVisitorAdapter implements SchemaResolveVisitor {\n        private SchemaRepository repository;\n        private int options;\n        private Context context;\n\n        public OracleResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(OracleCreatePackageStatement x) {\n            Context ctx = createContext(x);\n\n            for (SQLStatement stmt : x.getStatements()) {\n                stmt.accept(this);\n            }\n\n            popContext();\n            return false;\n        }\n\n        public boolean visit(OracleForStatement x) {\n            Context ctx = createContext(x);\n\n            SQLName index = x.getIndex();\n            SQLExpr range = x.getRange();\n\n            if (index != null) {\n                SQLDeclareItem declareItem = new SQLDeclareItem(index, null);\n                declareItem.setParent(x);\n\n                if (index instanceof SQLIdentifierExpr) {\n                    ((SQLIdentifierExpr) index).setResolvedDeclareItem(declareItem);\n                }\n                declareItem.setResolvedObject(range);\n                ctx.declare(declareItem);\n                if (range instanceof SQLQueryExpr) {\n                    SQLSelect select = ((SQLQueryExpr) range).getSubQuery();\n                    SQLSubqueryTableSource tableSource = new SQLSubqueryTableSource(select);\n                    declareItem.setResolvedObject(tableSource);\n                }\n\n                index.accept(this);\n            }\n\n            if (range != null) {\n                range.accept(this);\n            }\n\n            for (SQLStatement stmt : x.getStatements()) {\n                stmt.accept(this);\n            }\n\n            popContext();\n            return false;\n        }\n\n        public boolean visit(OracleForeignKey x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(OracleSelectTableReference x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(OracleSelectQueryBlock x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        public boolean visit(SQLIdentifierExpr x) {\n            if (x.nameHashCode64() == FnvHash.Constants.ROWNUM) {\n                return false;\n            }\n\n            resolveIdent(this, x);\n            return true;\n        }\n\n        public boolean visit(OracleCreateTableStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(OracleUpdateStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(OracleDeleteStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(OracleMultiInsertStatement x) {\n            Context ctx = createContext(x);\n\n            SQLSelect select = x.getSubQuery();\n            visit(select);\n\n            OracleSelectSubqueryTableSource tableSource = new OracleSelectSubqueryTableSource(select);\n            tableSource.setParent(x);\n            ctx.setTableSource(tableSource);\n\n            for (OracleMultiInsertStatement.Entry entry : x.getEntries()) {\n                entry.accept(this);\n            }\n\n            popContext();\n            return false;\n        }\n\n        public boolean visit(OracleMultiInsertStatement.InsertIntoClause x) {\n            for (SQLExpr column : x.getColumns()) {\n                if (column instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr identColumn = (SQLIdentifierExpr) column;\n                    identColumn.setResolvedTableSource(x.getTableSource());\n                }\n            }\n            return true;\n        }\n\n        public boolean visit(OracleInsertStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static class OdpsResolveVisitor extends OdpsASTVisitorAdapter implements SchemaResolveVisitor {\n        private int options;\n        private SchemaRepository repository;\n        private Context context;\n\n        public OdpsResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(OdpsSelectQueryBlock x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        public boolean visit(OdpsCreateTableStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(HiveInsert x) {\n            Context ctx = createContext(x);\n\n            SQLExprTableSource tableSource = x.getTableSource();\n            if (tableSource != null) {\n                ctx.setTableSource(x.getTableSource());\n                visit(tableSource);\n            }\n\n            List<SQLAssignItem> partitions = x.getPartitions();\n            if (partitions != null) {\n                for (SQLAssignItem item : partitions) {\n                    item.accept(this);\n                }\n            }\n\n            SQLSelect select = x.getQuery();\n            if (select != null) {\n                visit(select);\n            }\n\n            popContext();\n            return false;\n        }\n\n        public boolean visit(HiveInsertStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static class HiveResolveVisitor extends HiveASTVisitorAdapter implements SchemaResolveVisitor {\n        private int options;\n        private SchemaRepository repository;\n        private Context context;\n\n        public HiveResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(OdpsSelectQueryBlock x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        public boolean visit(SQLCreateTableStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(HiveInsert x) {\n            Context ctx = createContext(x);\n\n            SQLExprTableSource tableSource = x.getTableSource();\n            if (tableSource != null) {\n                ctx.setTableSource(x.getTableSource());\n                visit(tableSource);\n            }\n\n            List<SQLAssignItem> partitions = x.getPartitions();\n            if (partitions != null) {\n                for (SQLAssignItem item : partitions) {\n                    item.accept(this);\n                }\n            }\n\n            SQLSelect select = x.getQuery();\n            if (select != null) {\n                visit(select);\n            }\n\n            popContext();\n            return false;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static class PGResolveVisitor extends PGASTVisitorAdapter implements SchemaResolveVisitor {\n        private int options;\n        private SchemaRepository repository;\n        private Context context;\n\n        public PGResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(PGSelectQueryBlock x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(PGFunctionTableSource x) {\n            for (SQLParameter parameter : x.getParameters()) {\n                SQLName name = parameter.getName();\n                if (name instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr identName = (SQLIdentifierExpr) name;\n                    identName.setResolvedTableSource(x);\n                }\n            }\n\n            return false;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        public boolean visit(SQLIdentifierExpr x) {\n            if (PGUtils.isPseudoColumn(x.nameHashCode64())) {\n                return false;\n            }\n\n            resolveIdent(this, x);\n            return true;\n        }\n\n        public boolean visit(PGUpdateStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(PGDeleteStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(PGSelectStatement x) {\n            createContext(x);\n            visit(x.getSelect());\n            popContext();\n            return false;\n        }\n\n        public boolean visit(PGInsertStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static class SQLServerResolveVisitor extends SQLServerASTVisitorAdapter implements SchemaResolveVisitor {\n        private int options;\n        private SchemaRepository repository;\n        private Context context;\n\n        public SQLServerResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(SQLServerSelectQueryBlock x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        public boolean visit(SQLServerUpdateStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        public boolean visit(SQLServerInsertStatement x) {\n            resolve(this, x);\n            return false;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static class SQLResolveVisitor extends SQLASTVisitorAdapter implements SchemaResolveVisitor {\n        private int options;\n        private SchemaRepository repository;\n        private Context context;\n\n        public SQLResolveVisitor(SchemaRepository repository, int options) {\n            this.repository = repository;\n            this.options = options;\n        }\n\n        public boolean visit(SQLSelectItem x) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                resolveIdent(this, (SQLIdentifierExpr) expr);\n                return false;\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                resolve(this, (SQLPropertyExpr) expr);\n                return false;\n            }\n\n            return true;\n        }\n\n        @Override\n        public boolean isEnabled(Option option) {\n            return (options & option.mask) != 0;\n        }\n\n        public int getOptions() {\n            return options;\n        }\n\n        @Override\n        public Context getContext() {\n            return context;\n        }\n\n        public Context createContext(SQLObject object) {\n            return this.context = new Context(object, context);\n        }\n\n        @Override\n        public void popContext() {\n            if (context != null) {\n                context = context.parent;\n            }\n        }\n\n        public SchemaRepository getRepository() {\n            return repository;\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLCreateTableStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLExprTableSource table = x.getTableSource();\n        ctx.setTableSource(table);\n\n        table.accept(visitor);\n\n        List<SQLTableElement> elements = x.getTableElementList();\n        for (int i = 0; i < elements.size(); i++) {\n            SQLTableElement e = elements.get(i);\n            if (e instanceof SQLColumnDefinition) {\n                SQLColumnDefinition columnn = (SQLColumnDefinition) e;\n                SQLName columnnName = columnn.getName();\n                if (columnnName instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) columnnName;\n                    identifierExpr.setResolvedTableSource(table);\n                    identifierExpr.setResolvedColumn(columnn);\n                }\n            } else if (e instanceof SQLUniqueConstraint) {\n                List<SQLSelectOrderByItem> columns = ((SQLUniqueConstraint) e).getColumns();\n                for (SQLSelectOrderByItem orderByItem : columns) {\n                    SQLExpr orderByItemExpr = orderByItem.getExpr();\n                    if (orderByItemExpr instanceof SQLIdentifierExpr) {\n                        SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) orderByItemExpr;\n                        identifierExpr.setResolvedTableSource(table);\n\n                        SQLColumnDefinition column = x.findColumn(identifierExpr.nameHashCode64());\n                        if (column != null) {\n                            identifierExpr.setResolvedColumn(column);\n                        }\n                    }\n                }\n            } else {\n                e.accept(visitor);\n            }\n        }\n\n        SQLSelect select = x.getSelect();\n        if (select != null) {\n            visitor.visit(select);\n        }\n\n        SchemaRepository repository = visitor.getRepository();\n        if (repository != null) {\n            repository.acceptCreateTable(x);\n        }\n\n        visitor.popContext();\n\n        SQLExprTableSource like = x.getLike();\n        if (like != null) {\n            like.accept(visitor);\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLUpdateStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            with.accept(visitor);\n        }\n\n        SQLTableSource table = x.getTableSource();\n        SQLTableSource from = x.getFrom();\n\n        ctx.setTableSource(table);\n        ctx.setFrom(from);\n\n        table.accept(visitor);\n        if (from != null) {\n            from.accept(visitor);\n        }\n\n        List<SQLUpdateSetItem> items = x.getItems();\n        for (SQLUpdateSetItem item : items) {\n            SQLExpr column = item.getColumn();\n            if (column instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) column;\n                identifierExpr.setResolvedTableSource(table);\n                visitor.visit(identifierExpr);\n            } else if (column instanceof SQLListExpr) {\n                SQLListExpr columnGroup = (SQLListExpr) column;\n                for (SQLExpr columnGroupItem : columnGroup.getItems()) {\n                    if (columnGroupItem instanceof SQLIdentifierExpr) {\n                        SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) columnGroupItem;\n                        identifierExpr.setResolvedTableSource(table);\n                        visitor.visit(identifierExpr);\n                    } else {\n                        columnGroupItem.accept(visitor);\n                    }\n                }\n            } else {\n                column.accept(visitor);\n            }\n            SQLExpr value = item.getValue();\n            if (value != null) {\n                value.accept(visitor);\n            }\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            where.accept(visitor);\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            orderBy.accept(visitor);\n        }\n\n        for (SQLExpr sqlExpr : x.getReturning()) {\n            sqlExpr.accept(visitor);\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLDeleteStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visitor.visit(with);\n        }\n\n        SQLTableSource table = x.getTableSource();\n        SQLTableSource from = x.getFrom();\n\n        if (from == null) {\n            from = x.getUsing();\n        }\n\n        if (table == null && from != null) {\n            table = from;\n            from = null;\n        }\n\n        if (from != null) {\n            ctx.setFrom(from);\n            from.accept(visitor);\n        }\n\n        if (table != null) {\n            if (from != null && table instanceof SQLExprTableSource) {\n                SQLExpr tableExpr = ((SQLExprTableSource) table).getExpr();\n                if (tableExpr instanceof SQLPropertyExpr\n                        && ((SQLPropertyExpr) tableExpr).getName().equals(\"*\")) {\n                    String alias = ((SQLPropertyExpr) tableExpr).getOwnernName();\n                    SQLTableSource refTableSource = from.findTableSource(alias);\n                    if (refTableSource != null) {\n                        ((SQLPropertyExpr) tableExpr).setResolvedTableSource(refTableSource);\n                    }\n                }\n            }\n            table.accept(visitor);\n            ctx.setTableSource(table);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            where.accept(visitor);\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLInsertStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visitor.visit(with);\n        }\n\n        SQLTableSource table = x.getTableSource();\n\n        ctx.setTableSource(table);\n\n        if (table != null) {\n            table.accept(visitor);\n        }\n\n        for (SQLExpr column : x.getColumns()) {\n            column.accept(visitor);\n        }\n\n        if (x instanceof HiveInsertStatement) {\n            for (SQLAssignItem item : ((HiveInsertStatement) x).getPartitions()) {\n                item.accept(visitor);\n            }\n        }\n\n        for (SQLInsertStatement.ValuesClause valuesClause : x.getValuesList()) {\n            valuesClause.accept(visitor);\n        }\n\n        SQLSelect query = x.getQuery();\n        if (query != null) {\n            visitor.visit(query);\n        }\n\n        if (x instanceof OracleInsertStatement) {\n            SQLObject returning = ((OracleInsertStatement) x).getReturning();\n            if (returning != null) {\n                returning.accept(visitor);\n            }\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolveIdent(SchemaResolveVisitor visitor, SQLIdentifierExpr x) {\n        SchemaResolveVisitor.Context ctx = visitor.getContext();\n        if (ctx == null) {\n            return;\n        }\n\n        String ident = x.getName();\n        long hash = x.nameHashCode64();\n        SQLTableSource tableSource = null;\n\n        if ((hash == FnvHash.Constants.LEVEL || hash == FnvHash.Constants.CONNECT_BY_ISCYCLE)\n                && ctx.object instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) ctx.object;\n            if (queryBlock.getStartWith() != null\n                    || queryBlock.getConnectBy() != null) {\n                return;\n            }\n        }\n\n        SQLTableSource ctxTable = ctx.getTableSource();\n\n        if (ctxTable instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) ctxTable;\n            tableSource = join.findTableSourceWithColumn(hash, ident, visitor.getOptions());\n            if (tableSource == null) {\n                final SQLTableSource left = join.getLeft(), right = join.getRight();\n\n                if (left instanceof SQLSubqueryTableSource\n                        && right instanceof SQLExprTableSource) {\n                    SQLSelect leftSelect = ((SQLSubqueryTableSource) left).getSelect();\n                    if (leftSelect.getQuery() instanceof SQLSelectQueryBlock) {\n                        boolean hasAllColumn = ((SQLSelectQueryBlock) leftSelect.getQuery()).selectItemHasAllColumn();\n                        if (!hasAllColumn) {\n                            tableSource = right;\n                        }\n                    }\n                } else if (right instanceof SQLSubqueryTableSource\n                        && left instanceof SQLExprTableSource) {\n                    SQLSelect rightSelect = ((SQLSubqueryTableSource) right).getSelect();\n                    if (rightSelect.getQuery() instanceof SQLSelectQueryBlock) {\n                        boolean hasAllColumn = ((SQLSelectQueryBlock) rightSelect.getQuery()).selectItemHasAllColumn();\n                        if (!hasAllColumn) {\n                            tableSource = left;\n                        }\n                    }\n                } else if (left instanceof SQLExprTableSource && right instanceof SQLExprTableSource) {\n                    SQLExprTableSource leftExprTableSource = (SQLExprTableSource) left;\n                    SQLExprTableSource rightExprTableSource = (SQLExprTableSource) right;\n\n                    if (leftExprTableSource.getSchemaObject() != null\n                            && rightExprTableSource.getSchemaObject() == null) {\n                        tableSource = rightExprTableSource;\n\n                    } else if (rightExprTableSource.getSchemaObject() != null\n                            && leftExprTableSource.getSchemaObject() == null) {\n                        tableSource = leftExprTableSource;\n                    }\n                }\n            }\n        } else if (ctxTable instanceof SQLSubqueryTableSource) {\n            tableSource = ctxTable.findTableSourceWithColumn(hash, ident, visitor.getOptions());\n        } else if (ctxTable instanceof SQLLateralViewTableSource) {\n            tableSource = ctxTable.findTableSourceWithColumn(hash, ident, visitor.getOptions());\n\n            if (tableSource == null) {\n                tableSource = ((SQLLateralViewTableSource) ctxTable).getTableSource();\n            }\n        } else {\n            for (SchemaResolveVisitor.Context parentCtx = ctx;\n                 parentCtx != null;\n                 parentCtx = parentCtx.parent) {\n                SQLDeclareItem declareItem = parentCtx.findDeclare(hash);\n                if (declareItem != null) {\n                    x.setResolvedDeclareItem(declareItem);\n                    return;\n                }\n\n                if (parentCtx.object instanceof SQLBlockStatement) {\n                    SQLBlockStatement block = (SQLBlockStatement) parentCtx.object;\n                    SQLParameter parameter = block.findParameter(hash);\n                    if (parameter != null) {\n                        x.setResolvedParameter(parameter);\n                        return;\n                    }\n                } else if (parentCtx.object instanceof SQLCreateProcedureStatement) {\n                    SQLCreateProcedureStatement createProc = (SQLCreateProcedureStatement) parentCtx.object;\n                    SQLParameter parameter = createProc.findParameter(hash);\n                    if (parameter != null) {\n                        x.setResolvedParameter(parameter);\n                        return;\n                    }\n                }\n            }\n\n            tableSource = ctxTable;\n            if (tableSource instanceof SQLExprTableSource) {\n                SchemaObject table = ((SQLExprTableSource) tableSource).getSchemaObject();\n                if (table != null) {\n                    if (table.findColumn(hash) == null) {\n                        SQLCreateTableStatement createStmt = null;\n                        {\n                            SQLStatement smt = table.getStatement();\n                            if (smt instanceof SQLCreateTableStatement) {\n                                createStmt = (SQLCreateTableStatement) smt;\n                            }\n                        }\n\n                        if (createStmt != null && createStmt.getTableElementList().size() > 0) {\n                            tableSource = null; // maybe parent\n                        }\n                    }\n                }\n            }\n        }\n\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr();\n\n            if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) expr;\n                if (func.methodNameHashCode64() == FnvHash.Constants.ANN) {\n                    expr = func.getArguments().get(0);\n                }\n            }\n\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                long identHash = identExpr.nameHashCode64();\n\n                tableSource = unwrapAlias(ctx, tableSource, identHash);\n            }\n        }\n\n        if (tableSource != null) {\n            x.setResolvedTableSource(tableSource);\n\n            SQLObject column = tableSource.findColumn(hash);\n            if (column == null) {\n                column = tableSource.resolveColumn(hash);\n            }\n            if (column != null) {\n                x.setResolvedColumn(column);\n            }\n\n            if (ctxTable instanceof SQLJoinTableSource) {\n                String alias = tableSource.computeAlias();\n                if (alias == null || tableSource instanceof SQLWithSubqueryClause.Entry) {\n                    return;\n                }\n\n                if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveIdentifierAlias)) {\n                    SQLPropertyExpr propertyExpr = new SQLPropertyExpr(new SQLIdentifierExpr(alias), ident, hash);\n                    propertyExpr.setResolvedColumn(x.getResolvedColumn());\n                    propertyExpr.setResolvedTableSource(x.getResolvedTableSource());\n                    SQLUtils.replaceInParent(x, propertyExpr);\n                }\n            }\n        }\n\n        if (x.getResolvedColumn() == null\n                && x.getResolvedTableSource() == null) {\n            for (SchemaResolveVisitor.Context parentCtx = ctx;\n                 parentCtx != null;\n                 parentCtx = parentCtx.parent) {\n                SQLDeclareItem declareItem = parentCtx.findDeclare(hash);\n                if (declareItem != null) {\n                    x.setResolvedDeclareItem(declareItem);\n                    return;\n                }\n\n                if (parentCtx.object instanceof SQLBlockStatement) {\n                    SQLBlockStatement block = (SQLBlockStatement) parentCtx.object;\n                    SQLParameter parameter = block.findParameter(hash);\n                    if (parameter != null) {\n                        x.setResolvedParameter(parameter);\n                        return;\n                    }\n                } else if (parentCtx.object instanceof SQLCreateProcedureStatement) {\n                    SQLCreateProcedureStatement createProc = (SQLCreateProcedureStatement) parentCtx.object;\n                    SQLParameter parameter = createProc.findParameter(hash);\n                    if (parameter != null) {\n                        x.setResolvedParameter(parameter);\n                        return;\n                    }\n                }\n            }\n        }\n\n        if (x.getResolvedColumnObject() == null && ctx.object instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) ctx.object;\n            boolean having = false;\n            for (SQLObject current = x, parent = x.getParent(); parent != null; current = parent, parent = parent.getParent()) {\n                if (parent instanceof SQLSelectGroupByClause && parent.getParent() == queryBlock) {\n                    SQLSelectGroupByClause groupBy = (SQLSelectGroupByClause) parent;\n                    if (current == groupBy.getHaving()) {\n                        having = true;\n                    }\n                    break;\n                }\n            }\n            if (having) {\n                SQLSelectItem selectItem = queryBlock.findSelectItem(x.hashCode64());\n                if (selectItem != null) {\n                    x.setResolvedColumn(selectItem);\n                }\n            }\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLPropertyExpr x) {\n        SchemaResolveVisitor.Context ctx = visitor.getContext();\n        if (ctx == null) {\n            return;\n        }\n\n        long owner_hash = 0;\n        {\n            SQLExpr ownerObj = x.getOwner();\n            if (ownerObj instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr owner = (SQLIdentifierExpr) ownerObj;\n                owner_hash = owner.nameHashCode64();\n            } else if (ownerObj instanceof SQLPropertyExpr) {\n                owner_hash = ((SQLPropertyExpr) ownerObj).hashCode64();\n            }\n        }\n\n        SQLTableSource tableSource = null;\n        SQLTableSource ctxTable = ctx.getTableSource();\n\n        if (ctxTable != null) {\n            tableSource = ctxTable.findTableSource(owner_hash);\n        }\n\n        if (tableSource == null) {\n            SQLTableSource ctxFrom = ctx.getFrom();\n            if (ctxFrom != null) {\n                tableSource = ctxFrom.findTableSource(owner_hash);\n            }\n        }\n\n        if (tableSource == null) {\n            for (SchemaResolveVisitor.Context parentCtx = ctx;\n                 parentCtx != null;\n                 parentCtx = parentCtx.parent) {\n                SQLTableSource parentCtxTable = parentCtx.getTableSource();\n\n                if (parentCtxTable != null) {\n                    tableSource = parentCtxTable.findTableSource(owner_hash);\n                    if (tableSource == null) {\n                        SQLTableSource ctxFrom = parentCtx.getFrom();\n                        if (ctxFrom != null) {\n                            tableSource = ctxFrom.findTableSource(owner_hash);\n                        }\n                    }\n\n                    if (tableSource != null) {\n                        break;\n                    }\n                } else {\n                    if (parentCtx.object instanceof SQLBlockStatement) {\n                        SQLBlockStatement block = (SQLBlockStatement) parentCtx.object;\n                        SQLParameter parameter = block.findParameter(owner_hash);\n                        if (parameter != null) {\n                            x.setResolvedOwnerObject(parameter);\n                            return;\n                        }\n                    } else if (parentCtx.object instanceof SQLMergeStatement) {\n                        SQLMergeStatement mergeStatement = (SQLMergeStatement) parentCtx.object;\n                        SQLTableSource into = mergeStatement.getInto();\n                        if (into instanceof SQLSubqueryTableSource\n                                && into.aliasHashCode64() == owner_hash) {\n                            x.setResolvedOwnerObject(into);\n                        }\n                    }\n\n                    SQLDeclareItem declareItem = parentCtx.findDeclare(owner_hash);\n                    if (declareItem != null) {\n                        SQLObject resolvedObject = declareItem.getResolvedObject();\n                        if (resolvedObject instanceof SQLCreateProcedureStatement\n                                || resolvedObject instanceof SQLCreateFunctionStatement\n                                || resolvedObject instanceof SQLTableSource) {\n                            x.setResolvedOwnerObject(resolvedObject);\n                        }\n                        break;\n                    }\n                }\n            }\n        }\n\n        if (tableSource != null) {\n            x.setResolvedTableSource(tableSource);\n            SQLObject column = tableSource.resolveColum(\n                    x.nameHashCode64());\n            if (column instanceof SQLColumnDefinition) {\n                x.setResolvedColumn((SQLColumnDefinition) column);\n            } else if (column instanceof SQLSelectItem) {\n                x.setResolvedColumn((SQLSelectItem) column);\n            }\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLBinaryOpExpr x) {\n        final SQLBinaryOperator op = x.getOperator();\n        final SQLExpr left = x.getLeft();\n\n        if ((op == SQLBinaryOperator.BooleanAnd || op == SQLBinaryOperator.BooleanOr)\n                && left instanceof SQLBinaryOpExpr\n                && ((SQLBinaryOpExpr) left).getOperator() == op) {\n            List<SQLExpr> groupList = SQLBinaryOpExpr.split(x, op);\n            for (int i = 0; i < groupList.size(); i++) {\n                SQLExpr item = groupList.get(i);\n                item.accept(visitor);\n            }\n            return;\n        }\n\n        if (left != null) {\n            if (left instanceof SQLBinaryOpExpr) {\n                resolve(visitor, (SQLBinaryOpExpr) left);\n            } else {\n                left.accept(visitor);\n            }\n        }\n\n        SQLExpr right = x.getRight();\n        if (right != null) {\n            right.accept(visitor);\n        }\n    }\n\n    static SQLTableSource unwrapAlias(SchemaResolveVisitor.Context ctx, SQLTableSource tableSource, long identHash) {\n        if (ctx == null) {\n            return tableSource;\n        }\n\n        if (ctx.object instanceof SQLDeleteStatement\n                && (ctx.getTableSource() == null || tableSource == ctx.getTableSource())\n                && ctx.getFrom() != null) {\n            SQLTableSource found = ctx.getFrom().findTableSource(identHash);\n            if (found != null) {\n                return found;\n            }\n        }\n\n        for (SchemaResolveVisitor.Context parentCtx = ctx;\n             parentCtx != null;\n             parentCtx = parentCtx.parent) {\n            SQLWithSubqueryClause with = null;\n            if (parentCtx.object instanceof SQLSelect) {\n                SQLSelect select = (SQLSelect) parentCtx.object;\n                with = select.getWithSubQuery();\n            } else if (parentCtx.object instanceof SQLDeleteStatement) {\n                SQLDeleteStatement delete = (SQLDeleteStatement) parentCtx.object;\n                with = delete.getWith();\n            } else if (parentCtx.object instanceof SQLInsertStatement) {\n                SQLInsertStatement insertStmt = (SQLInsertStatement) parentCtx.object;\n                with = insertStmt.getWith();\n            } else if (parentCtx.object instanceof SQLUpdateStatement) {\n                SQLUpdateStatement updateStmt = (SQLUpdateStatement) parentCtx.object;\n                with = updateStmt.getWith();\n            }\n\n            if (with != null) {\n                SQLWithSubqueryClause.Entry entry = with.findEntry(identHash);\n                if (entry != null) {\n                    return entry;\n                }\n            }\n        }\n        return tableSource;\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLSelectQueryBlock x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n        if (ctx != null && ctx.level >= 32) {\n            return;\n        }\n\n        SQLTableSource from = x.getFrom();\n\n        if (from != null) {\n            ctx.setTableSource(from);\n\n            Class fromClass = from.getClass();\n            if (fromClass == SQLExprTableSource.class) {\n                visitor.visit((SQLExprTableSource) from);\n            } else {\n                from.accept(visitor);\n            }\n        } else if (x.getParent() != null && x.getParent().getParent() instanceof HiveInsert\n                && x.getParent().getParent().getParent() instanceof HiveMultiInsertStatement) {\n            HiveMultiInsertStatement insert = (HiveMultiInsertStatement) x.getParent().getParent().getParent();\n            if (insert.getFrom() instanceof SQLExprTableSource) {\n                from = insert.getFrom();\n                ctx.setTableSource(from);\n            }\n        }\n\n        List<SQLSelectItem> selectList = x.getSelectList();\n\n        List<SQLSelectItem> columns = new ArrayList<SQLSelectItem>();\n        for (int i = selectList.size() - 1; i >= 0; i--) {\n            SQLSelectItem selectItem = selectList.get(i);\n            SQLExpr expr = selectItem.getExpr();\n            if (expr instanceof SQLAllColumnExpr) {\n                SQLAllColumnExpr allColumnExpr = (SQLAllColumnExpr) expr;\n                SQLExpr owner = allColumnExpr.getOwner();\n                SQLTableSource resolvedTableSource = from;\n                if (owner instanceof SQLIdentifierExpr) {\n                    String ownerName = ((SQLIdentifierExpr) owner).getName();\n                    resolvedTableSource = x.findTableSource(ownerName);\n                }\n                allColumnExpr.setResolvedTableSource(resolvedTableSource);\n\n                visitor.visit(allColumnExpr);\n\n                if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) {\n                    extractColumns(visitor, resolvedTableSource, null, columns);\n                }\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n                visitor.visit(propertyExpr);\n\n                String ownerName = propertyExpr.getOwnernName();\n                if (propertyExpr.getName().equals(\"*\")) {\n                    if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) {\n                        SQLTableSource tableSource = x.findTableSource(ownerName);\n                        extractColumns(visitor, tableSource, ownerName, columns);\n                    }\n                }\n\n                SQLColumnDefinition column = propertyExpr.getResolvedColumn();\n                if (column != null) {\n                    continue;\n                }\n                SQLTableSource tableSource = x.findTableSource(propertyExpr.getOwnernName());\n                if (tableSource != null) {\n                    column = tableSource.findColumn(propertyExpr.nameHashCode64());\n                    if (column != null) {\n                        propertyExpr.setResolvedColumn(column);\n                    }\n                }\n            } else if (expr instanceof SQLAllColumnExpr) {\n                SQLAllColumnExpr allColumnExpr = (SQLAllColumnExpr) expr;\n                SQLExpr owner = allColumnExpr.getOwner();\n                if (owner instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr ownerIdent = (SQLIdentifierExpr) owner;\n                    String ownerName = ownerIdent.getName();\n                    if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) {\n                        SQLTableSource tableSource = x.findTableSource(ownerName);\n                        extractColumns(visitor, tableSource, ownerName, columns);\n                    }\n                }\n            } else if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                visitor.visit(identExpr);\n\n                long name_hash = identExpr.nameHashCode64();\n\n                SQLColumnDefinition column = identExpr.getResolvedColumn();\n                if (column != null) {\n                    continue;\n                }\n                if (from == null) {\n                    continue;\n                }\n                column = from.findColumn(name_hash);\n                if (column != null) {\n                    identExpr.setResolvedColumn(column);\n                }\n            } else {\n                expr.accept(visitor);\n            }\n\n            if (columns.size() > 0) {\n                for (SQLSelectItem column : columns) {\n                    column.setParent(x);\n                    column.getExpr().accept(visitor);\n                }\n\n                selectList.remove(i);\n                selectList.addAll(i, columns);\n                columns.clear();\n            }\n        }\n\n        SQLExprTableSource into = x.getInto();\n        if (into != null) {\n            visitor.visit(into);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            if (where instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) where;\n                resolveExpr(visitor, binaryOpExpr.getLeft());\n                resolveExpr(visitor, binaryOpExpr.getRight());\n            } else if (where instanceof SQLBinaryOpExprGroup) {\n                SQLBinaryOpExprGroup binaryOpExprGroup = (SQLBinaryOpExprGroup) where;\n                for (SQLExpr item : binaryOpExprGroup.getItems()) {\n                    if (item instanceof SQLBinaryOpExpr) {\n                        SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) item;\n                        resolveExpr(visitor, binaryOpExpr.getLeft());\n                        resolveExpr(visitor, binaryOpExpr.getRight());\n                    } else {\n                        item.accept(visitor);\n                    }\n                }\n            } else {\n                where.accept(visitor);\n            }\n        }\n\n        SQLExpr startWith = x.getStartWith();\n        if (startWith != null) {\n            startWith.accept(visitor);\n        }\n\n        SQLExpr connectBy = x.getConnectBy();\n        if (connectBy != null) {\n            connectBy.accept(visitor);\n        }\n\n        SQLSelectGroupByClause groupBy = x.getGroupBy();\n        if (groupBy != null) {\n            groupBy.accept(visitor);\n        }\n\n        List<SQLWindow> windows = x.getWindows();\n        if (windows != null) {\n            for (SQLWindow window : windows) {\n                window.accept(visitor);\n            }\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) {\n                SQLExpr orderByItemExpr = orderByItem.getExpr();\n\n                if (orderByItemExpr instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr orderByItemIdentExpr = (SQLIdentifierExpr) orderByItemExpr;\n                    long hash = orderByItemIdentExpr.nameHashCode64();\n                    SQLSelectItem selectItem = x.findSelectItem(hash);\n\n                    if (selectItem != null) {\n                        orderByItem.setResolvedSelectItem(selectItem);\n\n                        SQLExpr selectItemExpr = selectItem.getExpr();\n                        if (selectItemExpr instanceof SQLIdentifierExpr) {\n                            orderByItemIdentExpr.setResolvedTableSource(((SQLIdentifierExpr) selectItemExpr).getResolvedTableSource());\n                            orderByItemIdentExpr.setResolvedColumn(((SQLIdentifierExpr) selectItemExpr).getResolvedColumn());\n                        } else if (selectItemExpr instanceof SQLPropertyExpr) {\n                            orderByItemIdentExpr.setResolvedTableSource(((SQLPropertyExpr) selectItemExpr).getResolvedTableSource());\n                            orderByItemIdentExpr.setResolvedColumn(((SQLPropertyExpr) selectItemExpr).getResolvedColumn());\n                        }\n                        continue;\n                    }\n                }\n\n                orderByItemExpr.accept(visitor);\n            }\n        }\n\n        int forUpdateOfSize = x.getForUpdateOfSize();\n        if (forUpdateOfSize > 0) {\n            for (SQLExpr sqlExpr : x.getForUpdateOf()) {\n                sqlExpr.accept(visitor);\n            }\n        }\n\n        List<SQLSelectOrderByItem> distributeBy = x.getDistributeBy();\n        if (distributeBy != null) {\n            for (SQLSelectOrderByItem item : distributeBy) {\n                item.accept(visitor);\n            }\n        }\n\n        List<SQLSelectOrderByItem> sortBy = x.getSortBy();\n        if (sortBy != null) {\n            for (SQLSelectOrderByItem item : sortBy) {\n                item.accept(visitor);\n            }\n        }\n\n        visitor.popContext();\n    }\n\n    static void extractColumns(SchemaResolveVisitor visitor,\n                               SQLTableSource from,\n                               String ownerName,\n                               List<SQLSelectItem> columns) {\n        if (from instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) from).getExpr();\n\n            SchemaRepository repository = visitor.getRepository();\n            if (repository == null) {\n                return;\n            }\n\n            String alias = from.getAlias();\n\n            SchemaObject table = repository.findTable((SQLExprTableSource) from);\n            if (table != null) {\n                SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) table.getStatement();\n                for (SQLTableElement e : createTableStmt.getTableElementList()) {\n                    if (e instanceof SQLColumnDefinition) {\n                        SQLColumnDefinition column = (SQLColumnDefinition) e;\n\n                        if (alias != null) {\n                            SQLPropertyExpr name = new SQLPropertyExpr(alias, column.getName().getSimpleName());\n                            name.setResolvedColumn(column);\n                            columns.add(new SQLSelectItem(name));\n                        } else if (ownerName != null) {\n                            SQLPropertyExpr name = new SQLPropertyExpr(ownerName, column.getName().getSimpleName());\n                            name.setResolvedColumn(column);\n                            columns.add(new SQLSelectItem(name));\n                        } else if (from.getParent() instanceof SQLJoinTableSource\n                                && from instanceof SQLExprTableSource\n                                && expr instanceof SQLName) {\n                            String tableName = expr.toString();\n                            SQLPropertyExpr name = new SQLPropertyExpr(tableName, column.getName().getSimpleName());\n                            name.setResolvedColumn(column);\n                            columns.add(new SQLSelectItem(name));\n                        } else {\n                            SQLIdentifierExpr name = (SQLIdentifierExpr) column.getName().clone();\n                            name.setResolvedColumn(column);\n                            columns.add(new SQLSelectItem(name));\n                        }\n                    }\n                }\n                return;\n            }\n\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLTableSource resolvedTableSource = ((SQLIdentifierExpr) expr).getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLWithSubqueryClause.Entry) {\n                    SQLWithSubqueryClause.Entry entry = (SQLWithSubqueryClause.Entry) resolvedTableSource;\n                    SQLSelect select = ((SQLWithSubqueryClause.Entry) resolvedTableSource).getSubQuery();\n                    SQLSelectQueryBlock firstQueryBlock = select.getFirstQueryBlock();\n                    if (firstQueryBlock != null) {\n                        for (SQLSelectItem item : firstQueryBlock.getSelectList()) {\n                            String itemAlias = item.computeAlias();\n                            if (itemAlias != null) {\n                                SQLIdentifierExpr columnExpr = new SQLIdentifierExpr(itemAlias);\n                                columnExpr.setResolvedColumn(item);\n                                columns.add(\n                                        new SQLSelectItem(columnExpr));\n                            }\n                        }\n                    }\n                }\n            }\n\n        } else if (from instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) from;\n            extractColumns(visitor, join.getLeft(), ownerName, columns);\n            extractColumns(visitor, join.getRight(), ownerName, columns);\n        } else if (from instanceof SQLSubqueryTableSource) {\n            SQLSelectQueryBlock subQuery = ((SQLSubqueryTableSource) from).getSelect().getQueryBlock();\n            if (subQuery == null) {\n                return;\n            }\n            final List<SQLSelectItem> subSelectList = subQuery.getSelectList();\n            for (SQLSelectItem subSelectItem : subSelectList) {\n                if (subSelectItem.getAlias() != null) {\n                    continue;\n                }\n\n                if (!(subSelectItem.getExpr() instanceof SQLName)) {\n                    return; // skip\n                }\n            }\n\n            for (SQLSelectItem subSelectItem : subSelectList) {\n                String alias = subSelectItem.computeAlias();\n                columns.add(new SQLSelectItem(new SQLIdentifierExpr(alias)));\n            }\n        } else if (from instanceof SQLUnionQueryTableSource) {\n            SQLSelectQueryBlock firstQueryBlock = ((SQLUnionQueryTableSource) from).getUnion().getFirstQueryBlock();\n            if (firstQueryBlock == null) {\n                return;\n            }\n\n            final List<SQLSelectItem> subSelectList = firstQueryBlock.getSelectList();\n            for (SQLSelectItem subSelectItem : subSelectList) {\n                if (subSelectItem.getAlias() != null) {\n                    continue;\n                }\n\n                if (!(subSelectItem.getExpr() instanceof SQLName)) {\n                    return; // skip\n                }\n            }\n\n            for (SQLSelectItem subSelectItem : subSelectList) {\n                String alias = subSelectItem.computeAlias();\n                columns.add(new SQLSelectItem(new SQLIdentifierExpr(alias)));\n            }\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLAllColumnExpr x) {\n        SQLTableSource tableSource = x.getResolvedTableSource();\n\n        if (tableSource == null) {\n            SQLSelectQueryBlock queryBlock = null;\n            for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n                if (parent instanceof SQLTableSource) {\n                    return;\n                }\n                if (parent instanceof SQLSelectQueryBlock) {\n                    queryBlock = (SQLSelectQueryBlock) parent;\n                    break;\n                }\n            }\n\n            if (queryBlock == null) {\n                return;\n            }\n\n            SQLTableSource from = queryBlock.getFrom();\n            if (from == null || from instanceof SQLJoinTableSource) {\n                return;\n            }\n\n            x.setResolvedTableSource(from);\n            tableSource = from;\n        }\n\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLTableSource resolvedTableSource = ((SQLIdentifierExpr) expr).getResolvedTableSource();\n                if (resolvedTableSource != null) {\n                    x.setResolvedTableSource(resolvedTableSource);\n                }\n            }\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor v, SQLMethodInvokeExpr x) {\n        SQLExpr owner = x.getOwner();\n        if (owner != null) {\n            resolveExpr(v, owner);\n        }\n\n        for (SQLExpr arg : x.getArguments()) {\n            resolveExpr(v, arg);\n        }\n\n        SQLExpr from = x.getFrom();\n        if (from != null) {\n            resolveExpr(v, from);\n        }\n\n        SQLExpr using = x.getUsing();\n        if (using != null) {\n            resolveExpr(v, using);\n        }\n\n        SQLExpr _for = x.getFor();\n        if (_for != null) {\n            resolveExpr(v, _for);\n        }\n\n        long nameHash = x.methodNameHashCode64();\n        SchemaRepository repository = v.getRepository();\n        if (repository != null) {\n            SQLDataType dataType = repository.findFuntionReturnType(nameHash);\n            if (dataType != null) {\n                x.setResolvedReturnDataType(dataType);\n            }\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLSelect x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLWithSubqueryClause with = x.getWithSubQuery();\n        if (with != null) {\n            visitor.visit(with);\n        }\n\n        SQLSelectQuery query = x.getQuery();\n        if (query != null) {\n            if (query instanceof SQLSelectQueryBlock) {\n                try {\n                    visitor.visit((SQLSelectQueryBlock) query);\n                } catch (StackOverflowError ignored) {\n                    // ignore\n                }\n            } else {\n                query.accept(visitor);\n            }\n        }\n\n        SQLSelectQueryBlock queryBlock = x.getFirstQueryBlock();\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            for (SQLSelectOrderByItem orderByItem : orderBy.getItems()) {\n                SQLExpr orderByItemExpr = orderByItem.getExpr();\n\n                if (orderByItemExpr instanceof SQLIdentifierExpr) {\n                    SQLIdentifierExpr orderByItemIdentExpr = (SQLIdentifierExpr) orderByItemExpr;\n                    long hash = orderByItemIdentExpr.nameHashCode64();\n\n                    SQLSelectItem selectItem = null;\n                    if (queryBlock != null) {\n                        selectItem = queryBlock.findSelectItem(hash);\n                    }\n\n                    if (selectItem != null) {\n                        orderByItem.setResolvedSelectItem(selectItem);\n\n                        SQLExpr selectItemExpr = selectItem.getExpr();\n                        if (selectItemExpr instanceof SQLIdentifierExpr) {\n                            orderByItemIdentExpr.setResolvedTableSource(((SQLIdentifierExpr) selectItemExpr).getResolvedTableSource());\n                            orderByItemIdentExpr.setResolvedColumn(((SQLIdentifierExpr) selectItemExpr).getResolvedColumn());\n                        } else if (selectItemExpr instanceof SQLPropertyExpr) {\n                            orderByItemIdentExpr.setResolvedTableSource(((SQLPropertyExpr) selectItemExpr).getResolvedTableSource());\n                            orderByItemIdentExpr.setResolvedColumn(((SQLPropertyExpr) selectItemExpr).getResolvedColumn());\n                        }\n                        continue;\n                    }\n                }\n\n                orderByItemExpr.accept(visitor);\n            }\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLWithSubqueryClause x) {\n        List<SQLWithSubqueryClause.Entry> entries = x.getEntries();\n        final SchemaResolveVisitor.Context context = visitor.getContext();\n        for (SQLWithSubqueryClause.Entry entry : entries) {\n            SQLSelect query = entry.getSubQuery();\n            if (query != null) {\n                visitor.visit(query);\n\n                final long alias_hash = entry.aliasHashCode64();\n                if (context != null && alias_hash != 0) {\n                    context.addTableSource(alias_hash, entry);\n                }\n            } else if (entry.getExpr() != null) {\n                entry.getExpr().accept(visitor);\n            } else {\n                SQLStatement returningStatement = entry.getReturningStatement();\n                if (returningStatement != null) {\n                    returningStatement.accept(visitor);\n                }\n            }\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLExprTableSource x) {\n        SQLExpr expr = x.getExpr();\n\n        SQLExpr annFeature = null;\n        if (expr instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) expr;\n            if (func.methodNameHashCode64() == FnvHash.Constants.ANN) {\n                expr = func.getArguments().get(0);\n\n                annFeature = func.getArguments().get(1);\n                if (annFeature instanceof SQLIdentifierExpr) {\n                    ((SQLIdentifierExpr) annFeature).setResolvedTableSource(x);\n                } else if (annFeature instanceof SQLPropertyExpr) {\n                    ((SQLPropertyExpr) annFeature).setResolvedTableSource(x);\n                }\n            }\n        }\n\n        if (expr instanceof SQLName || expr instanceof SQLAllColumnExpr) {\n            if (x.getSchemaObject() != null) {\n                return;\n            }\n\n            SQLIdentifierExpr identifierExpr = null;\n\n            if (expr instanceof SQLIdentifierExpr) {\n                identifierExpr = (SQLIdentifierExpr) expr;\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLExpr owner = ((SQLPropertyExpr) expr).getOwner();\n                if (owner instanceof SQLIdentifierExpr) {\n                    identifierExpr = (SQLIdentifierExpr) owner;\n                }\n            } else if (expr instanceof SQLAllColumnExpr) {\n                SQLExpr owner = ((SQLAllColumnExpr) expr).getOwner();\n                if (owner instanceof SQLIdentifierExpr) {\n                    identifierExpr = (SQLIdentifierExpr) owner;\n                }\n            }\n\n            if (identifierExpr != null) {\n                checkParameter(visitor, identifierExpr);\n\n                SQLTableSource tableSource = unwrapAlias(visitor.getContext(), null, identifierExpr.nameHashCode64());\n                if (tableSource == null && x.getParent() instanceof HiveMultiInsertStatement) {\n                    SQLWithSubqueryClause with = ((HiveMultiInsertStatement) x.getParent()).getWith();\n                    if (with != null) {\n                        SQLWithSubqueryClause.Entry entry = with.findEntry(identifierExpr.nameHashCode64());\n                        tableSource = entry;\n                    }\n                }\n\n                if (tableSource != null) {\n                    identifierExpr.setResolvedTableSource(tableSource);\n                    return;\n                }\n            }\n\n            SchemaRepository repository = visitor.getRepository();\n            if (repository != null) {\n                SchemaObject table = repository.findTable((SQLName) expr);\n                if (table != null) {\n                    x.setSchemaObject(table);\n\n                    if (annFeature != null) {\n                        if (annFeature instanceof SQLIdentifierExpr) {\n                            SQLIdentifierExpr identExpr = (SQLIdentifierExpr) annFeature;\n                            SQLColumnDefinition column = table.findColumn(identExpr.nameHashCode64());\n                            if (column != null) {\n                                identExpr.setResolvedColumn(column);\n                            }\n                        }\n                    }\n                    return;\n                }\n\n                SchemaObject view = repository.findView((SQLName) expr);\n                if (view != null) {\n                    x.setSchemaObject(view);\n                    return;\n                }\n            }\n            return;\n        }\n\n        if (expr instanceof SQLMethodInvokeExpr) {\n            visitor.visit((SQLMethodInvokeExpr) expr);\n            return;\n        }\n\n        if (expr instanceof SQLQueryExpr) {\n            SQLSelect select =\n                    ((SQLQueryExpr) expr)\n                            .getSubQuery();\n\n            visitor.visit(select);\n\n            SQLSelectQueryBlock queryBlock = select.getQueryBlock();\n            if (queryBlock != null && annFeature instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) annFeature;\n                SQLObject columnDef = queryBlock.resolveColum(identExpr.nameHashCode64());\n                if (columnDef instanceof SQLColumnDefinition) {\n                    identExpr.setResolvedColumn((SQLColumnDefinition) columnDef);\n                } else if (columnDef instanceof SQLSelectItem) {\n                    identExpr.setResolvedColumn((SQLSelectItem) columnDef);\n                }\n            }\n            //if (queryBlock.findColumn())\n            return;\n        }\n\n        expr.accept(visitor);\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLAlterTableStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLTableSource tableSource = x.getTableSource();\n        ctx.setTableSource(tableSource);\n\n        for (SQLAlterTableItem item : x.getItems()) {\n            item.accept(visitor);\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLMergeStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLTableSource into = x.getInto();\n        if (into instanceof SQLExprTableSource) {\n            ctx.setTableSource(into);\n        } else {\n            into.accept(visitor);\n        }\n\n        SQLTableSource using = x.getUsing();\n        if (using != null) {\n            using.accept(visitor);\n            ctx.setFrom(using);\n        }\n\n        SQLExpr on = x.getOn();\n        if (on != null) {\n            on.accept(visitor);\n        }\n\n        List<SQLMergeStatement.When> whens = x.getWhens();\n        for (SQLMergeStatement.When when : whens) {\n            SQLName by = when.getBy();\n            if (by != null) {\n                by.accept(visitor);\n            }\n\n            if (when instanceof SQLMergeStatement.WhenUpdate) {\n                SQLMergeStatement.WhenUpdate updateClause = (SQLMergeStatement.WhenUpdate) when;\n                for (SQLUpdateSetItem item : updateClause.getItems()) {\n                    SQLExpr column = item.getColumn();\n\n                    if (column instanceof SQLIdentifierExpr) {\n                        ((SQLIdentifierExpr) column).setResolvedTableSource(into);\n                    } else if (column instanceof SQLPropertyExpr) {\n                        ((SQLPropertyExpr) column).setResolvedTableSource(into);\n                    } else {\n                        column.accept(visitor);\n                    }\n\n                    SQLExpr value = item.getValue();\n                    if (value != null) {\n                        value.accept(visitor);\n                    }\n                }\n            } else if (when instanceof SQLMergeStatement.WhenInsert) {\n                SQLMergeStatement.WhenInsert insertClause = (SQLMergeStatement.WhenInsert) when;\n                for (SQLExpr column : insertClause.getColumns()) {\n                    if (column instanceof SQLIdentifierExpr) {\n                        ((SQLIdentifierExpr) column).setResolvedTableSource(into);\n                    } else if (column instanceof SQLPropertyExpr) {\n                        ((SQLPropertyExpr) column).setResolvedTableSource(into);\n                    }\n                    column.accept(visitor);\n                }\n                for (SQLExpr value : insertClause.getValues()) {\n                    value.accept(visitor);\n                }\n            }\n\n            SQLExpr where = when.getWhere();\n            if (where != null) {\n                where.accept(visitor);\n            }\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLCreateFunctionStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        {\n            SQLDeclareItem declareItem = new SQLDeclareItem(x.getName().clone(), null);\n            declareItem.setResolvedObject(x);\n\n            SchemaResolveVisitor.Context parentCtx = visitor.getContext();\n            if (parentCtx != null) {\n                parentCtx.declare(declareItem);\n            } else {\n                ctx.declare(declareItem);\n            }\n        }\n\n        for (SQLParameter parameter : x.getParameters()) {\n            parameter.accept(visitor);\n        }\n\n        SQLStatement block = x.getBlock();\n        if (block != null) {\n            block.accept(visitor);\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLCreateProcedureStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        {\n            SQLDeclareItem declareItem = new SQLDeclareItem(x.getName().clone(), null);\n            declareItem.setResolvedObject(x);\n\n            SchemaResolveVisitor.Context parentCtx = visitor.getContext();\n            if (parentCtx != null) {\n                parentCtx.declare(declareItem);\n            } else {\n                ctx.declare(declareItem);\n            }\n        }\n\n        for (SQLParameter parameter : x.getParameters()) {\n            parameter.accept(visitor);\n        }\n\n        SQLStatement block = x.getBlock();\n        if (block != null) {\n            block.accept(visitor);\n        }\n\n        visitor.popContext();\n    }\n\n    static boolean resolve(SchemaResolveVisitor visitor, SQLIfStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLExpr condition = x.getCondition();\n        if (condition != null) {\n            condition.accept(visitor);\n        }\n\n        for (SQLStatement stmt : x.getStatements()) {\n            stmt.accept(visitor);\n        }\n\n        for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) {\n            elseIf.accept(visitor);\n        }\n\n        SQLIfStatement.Else e = x.getElseItem();\n        if (e != null) {\n            e.accept(visitor);\n        }\n\n        visitor.popContext();\n        return false;\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLBlockStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        for (SQLParameter parameter : x.getParameters()) {\n            visitor.visit(parameter);\n        }\n\n        for (SQLStatement stmt : x.getStatementList()) {\n            stmt.accept(visitor);\n        }\n\n        SQLStatement exception = x.getException();\n        if (exception != null) {\n            exception.accept(visitor);\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLParameter x) {\n        SQLName name = x.getName();\n        if (name instanceof SQLIdentifierExpr) {\n            ((SQLIdentifierExpr) name).setResolvedParameter(x);\n        }\n\n        SQLExpr expr = x.getDefaultValue();\n\n        SchemaResolveVisitor.Context ctx = null;\n        if (expr != null) {\n            if (expr instanceof SQLQueryExpr) {\n                ctx = visitor.createContext(x);\n\n                SQLSubqueryTableSource tableSource = new SQLSubqueryTableSource(((SQLQueryExpr) expr).getSubQuery());\n                tableSource.setParent(x);\n                tableSource.setAlias(x.getName().getSimpleName());\n\n                ctx.setTableSource(tableSource);\n            }\n\n            expr.accept(visitor);\n        }\n\n        if (ctx != null) {\n            visitor.popContext();\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLDeclareItem x) {\n        SchemaResolveVisitor.Context ctx = visitor.getContext();\n        if (ctx != null) {\n            ctx.declare(x);\n        }\n\n        SQLName name = x.getName();\n        if (name instanceof SQLIdentifierExpr) {\n            ((SQLIdentifierExpr) name).setResolvedDeclareItem(x);\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLOver x) {\n        SQLName of = x.getOf();\n        SQLOrderBy orderBy = x.getOrderBy();\n        List<SQLExpr> partitionBy = x.getPartitionBy();\n\n        if (of == null // skip if of is not null\n                && orderBy != null) {\n            orderBy.accept(visitor);\n        }\n\n        if (partitionBy != null) {\n            for (SQLExpr expr : partitionBy) {\n                expr.accept(visitor);\n            }\n        }\n    }\n\n    private static boolean checkParameter(SchemaResolveVisitor visitor, SQLIdentifierExpr x) {\n        if (x.getResolvedParameter() != null) {\n            return true;\n        }\n\n        SchemaResolveVisitor.Context ctx = visitor.getContext();\n        if (ctx == null) {\n            return false;\n        }\n\n        long hash = x.hashCode64();\n        for (SchemaResolveVisitor.Context parentCtx = ctx;\n             parentCtx != null;\n             parentCtx = parentCtx.parent) {\n            if (parentCtx.object instanceof SQLBlockStatement) {\n                SQLBlockStatement block = (SQLBlockStatement) parentCtx.object;\n                SQLParameter parameter = block.findParameter(hash);\n                if (parameter != null) {\n                    x.setResolvedParameter(parameter);\n                    return true;\n                }\n            }\n\n            if (parentCtx.object instanceof SQLCreateProcedureStatement) {\n                SQLCreateProcedureStatement createProc = (SQLCreateProcedureStatement) parentCtx.object;\n                SQLParameter parameter = createProc.findParameter(hash);\n                if (parameter != null) {\n                    x.setResolvedParameter(parameter);\n                    return true;\n                }\n            }\n\n            if (parentCtx.object instanceof SQLSelect) {\n                SQLSelect select = (SQLSelect) parentCtx.object;\n                SQLWithSubqueryClause with = select.getWithSubQuery();\n                if (with != null) {\n                    SQLWithSubqueryClause.Entry entry = with.findEntry(hash);\n                    if (entry != null) {\n                        x.setResolvedTableSource(entry);\n                        return true;\n                    }\n                }\n\n                SchemaRepository repo = visitor.getRepository();\n                if (repo != null) {\n                    SchemaObject view = repo.findView(x);\n                    if (view != null && view.getStatement() instanceof SQLCreateViewStatement) {\n                        x.setResolvedOwnerObject(view.getStatement());\n                    }\n                }\n            }\n\n            SQLDeclareItem declareItem = parentCtx.findDeclare(hash);\n            if (declareItem != null) {\n                x.setResolvedDeclareItem(declareItem);\n                break;\n            }\n        }\n        return false;\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLReplaceStatement x) {\n        SchemaResolveVisitor.Context ctx = visitor.createContext(x);\n\n        SQLExprTableSource tableSource = x.getTableSource();\n        ctx.setTableSource(tableSource);\n        visitor.visit(tableSource);\n\n        for (SQLExpr column : x.getColumns()) {\n            column.accept(visitor);\n        }\n\n        SQLQueryExpr queryExpr = x.getQuery();\n        if (queryExpr != null) {\n            visitor.visit(queryExpr.getSubQuery());\n        }\n\n        visitor.popContext();\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLFetchStatement x) {\n        resolveExpr(visitor, x.getCursorName());\n        for (SQLExpr expr : x.getInto()) {\n            resolveExpr(visitor, expr);\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLForeignKeyConstraint x) {\n        SchemaRepository repository = visitor.getRepository();\n        SQLObject parent = x.getParent();\n\n        if (parent instanceof SQLCreateTableStatement) {\n            SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) parent;\n            SQLTableSource table = createTableStmt.getTableSource();\n            for (SQLName item : x.getReferencingColumns()) {\n                SQLIdentifierExpr columnName = (SQLIdentifierExpr) item;\n                columnName.setResolvedTableSource(table);\n\n                SQLColumnDefinition column = createTableStmt.findColumn(columnName.nameHashCode64());\n                if (column != null) {\n                    columnName.setResolvedColumn(column);\n                }\n            }\n        } else if (parent instanceof SQLAlterTableAddConstraint) {\n            SQLAlterTableStatement stmt = (SQLAlterTableStatement) parent.getParent();\n            SQLTableSource table = stmt.getTableSource();\n            for (SQLName item : x.getReferencingColumns()) {\n                SQLIdentifierExpr columnName = (SQLIdentifierExpr) item;\n                columnName.setResolvedTableSource(table);\n            }\n        }\n\n        if (repository == null) {\n            return;\n        }\n\n        SQLExprTableSource table = x.getReferencedTable();\n        for (SQLName item : x.getReferencedColumns()) {\n            SQLIdentifierExpr columnName = (SQLIdentifierExpr) item;\n            columnName.setResolvedTableSource(table);\n        }\n\n        SQLName tableName = table.getName();\n\n        SchemaObject tableObject = repository.findTable(tableName);\n        if (tableObject == null) {\n            return;\n        }\n\n        SQLStatement tableStmt = tableObject.getStatement();\n        if (tableStmt instanceof SQLCreateTableStatement) {\n            SQLCreateTableStatement refCreateTableStmt = (SQLCreateTableStatement) tableStmt;\n            for (SQLName item : x.getReferencedColumns()) {\n                SQLIdentifierExpr columnName = (SQLIdentifierExpr) item;\n                SQLColumnDefinition column = refCreateTableStmt.findColumn(columnName.nameHashCode64());\n                if (column != null) {\n                    columnName.setResolvedColumn(column);\n                }\n            }\n        }\n    }\n\n    static void resolve(SchemaResolveVisitor visitor, SQLCreateViewStatement x) {\n        x.getSubQuery()\n                .accept(visitor);\n    }\n\n    // for performance\n    static void resolveExpr(SchemaResolveVisitor visitor, SQLExpr x) {\n        if (x == null) {\n            return;\n        }\n\n        Class<?> clazz = x.getClass();\n        if (clazz == SQLIdentifierExpr.class) {\n            visitor.visit((SQLIdentifierExpr) x);\n            return;\n        } else if (clazz == SQLIntegerExpr.class || clazz == SQLCharExpr.class) {\n            // skip\n            return;\n        }\n\n        x.accept(visitor);\n    }\n\n    static void resolveUnion(SchemaResolveVisitor visitor, SQLUnionQuery x) {\n        SQLUnionOperator operator = x.getOperator();\n        List<SQLSelectQuery> relations = x.getRelations();\n        if (relations.size() > 2) {\n            for (SQLSelectQuery relation : relations) {\n                relation.accept(visitor);\n            }\n            return;\n        }\n        SQLSelectQuery left = x.getLeft();\n        SQLSelectQuery right = x.getRight();\n\n        boolean bracket = x.isParenthesized() && !(x.getParent() instanceof SQLUnionQueryTableSource);\n\n        if ((!bracket)\n                && left instanceof SQLUnionQuery\n                && ((SQLUnionQuery) left).getOperator() == operator\n                && !right.isParenthesized()\n                && x.getOrderBy() == null) {\n            SQLUnionQuery leftUnion = (SQLUnionQuery) left;\n\n            List<SQLSelectQuery> rights = new ArrayList<SQLSelectQuery>();\n            rights.add(right);\n\n            if (leftUnion.getRelations().size() > 2) {\n                rights.addAll(leftUnion.getRelations());\n            } else {\n                for (; ; ) {\n                    SQLSelectQuery leftLeft = leftUnion.getLeft();\n                    SQLSelectQuery leftRight = leftUnion.getRight();\n\n                    if ((!leftUnion.isParenthesized())\n                            && leftUnion.getOrderBy() == null\n                            && (!leftLeft.isParenthesized())\n                            && (!leftRight.isParenthesized())\n                            && leftLeft instanceof SQLUnionQuery\n                            && ((SQLUnionQuery) leftLeft).getOperator() == operator) {\n                        rights.add(leftRight);\n                        leftUnion = (SQLUnionQuery) leftLeft;\n                        continue;\n                    } else {\n                        rights.add(leftRight);\n                        rights.add(leftLeft);\n                    }\n                    break;\n                }\n            }\n\n            for (int i = rights.size() - 1; i >= 0; i--) {\n                SQLSelectQuery item = rights.get(i);\n                item.accept(visitor);\n            }\n            return;\n        }\n\n        if (left != null) {\n            left.accept(visitor);\n        }\n\n        if (right != null) {\n            right.accept(visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/function/Function.java",
    "content": "package com.alibaba.druid.sql.repository.function;\n\npublic interface Function {\n    FunctionType getType();\n\n    FunctionHandler findHandler();\n\n    FunctionHandler findHandler(String signature);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/function/FunctionHandler.java",
    "content": "package com.alibaba.druid.sql.repository.function;\n\npublic interface FunctionHandler {\n    String getSignature();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/function/FunctionType.java",
    "content": "package com.alibaba.druid.sql.repository.function;\n\npublic enum FunctionType {\n    Scalar,\n    Aggregate,\n    Window\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/function/SignatureUtils.java",
    "content": "package com.alibaba.druid.sql.repository.function;\n\nimport java.lang.reflect.Type;\nimport java.sql.Time;\n\npublic class SignatureUtils {\n    public static Type getJavaType(String signature) {\n        if (signature == null || signature.length() == 0) {\n            return null;\n        }\n\n        char c0 = signature.charAt(0);\n        if (signature.length() == 1) {\n            switch (c0) {\n                case 'b':\n                    return byte.class;\n                case 's':\n                    return short.class;\n                case 'i':\n                    return int.class;\n                case 'j':\n                    return long.class;\n                case 'f':\n                    return float.class;\n                case 'd':\n                    return double.class;\n                case 'c':\n                    return char.class;\n\n                case 'g':\n                    return String.class; // not null\n                case 'a':\n                    return java.sql.Date.class; // not null\n                case 't':\n                    return Time.class; // not null\n                case 'p':\n                    return java.sql.Timestamp.class; // not null\n\n                case 'B':\n                    return Byte.class;\n                case 'S':\n                    return Short.class;\n                case 'I':\n                    return Integer.class;\n                case 'J':\n                    return Long.class;\n                case 'F':\n                    return Float.class;\n                case 'D':\n                    return Double.class;\n                case 'C':\n                    return Character.class;\n\n                case 'G':\n                    return String.class;\n                case 'A':\n                    return java.sql.Date.class;\n                case 'T':\n                    return Time.class;\n                case 'P':\n                    return java.sql.Timestamp.class;\n\n                default:\n                    break;\n            }\n        }\n\n        throw new UnsupportedOperationException(\"type : \" + signature + \" is not support.\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/repository/function/Signatures.java",
    "content": "package com.alibaba.druid.sql.repository.function;\n\npublic class Signatures {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/template/SQLSelectQueryTemplate.java",
    "content": "package com.alibaba.druid.sql.template;\n\nimport com.alibaba.druid.sql.ast.SQLObjectImpl;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQuery;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\n\npublic class SQLSelectQueryTemplate extends SQLObjectImpl implements SQLSelectQuery {\n    private String text;\n\n    public SQLSelectQueryTemplate() {\n    }\n\n    public SQLSelectQueryTemplate(String text) {\n        this.text = text;\n    }\n\n    public String getText() {\n        return text;\n    }\n\n    @Override\n    protected void accept0(SQLASTVisitor v) {\n        v.visit(this);\n        v.endVisit(this);\n    }\n\n    @Override\n    public boolean isParenthesized() {\n        return false;\n    }\n\n    @Override\n    public void setParenthesized(boolean parenthesized) {\n    }\n\n    @Override\n    public SQLSelectQueryTemplate clone() {\n        return new SQLSelectQueryTemplate(text);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/ExportParameterVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport java.util.List;\n\npublic interface ExportParameterVisitor extends SQLASTVisitor {\n    boolean isParameterizedMergeInList();\n\n    void setParameterizedMergeInList(boolean flag);\n\n    List<Object> getParameters();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/ExportParameterVisitorUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ExportParameterVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlExportParameterVisitor;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleExportParameterVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGExportParameterVisitor;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.MSSQLServerExportParameterVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class ExportParameterVisitorUtils {\n    //private for util class not need new instance\n    private ExportParameterVisitorUtils() {\n        super();\n    }\n\n    public static ExportParameterVisitor createExportParameterVisitor(StringBuilder out, DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        switch (dbType) {\n            case mysql:\n            case mariadb:\n            case tidb:\n            case polardbx:\n                return new MySqlExportParameterVisitor(out);\n            case oracle:\n                return new OracleExportParameterVisitor(out);\n            case db2:\n                return new DB2ExportParameterVisitor(out);\n            case h2:\n            case lealone:\n                return new MySqlExportParameterVisitor(out);\n            case sqlserver:\n            case jtds:\n                return new MSSQLServerExportParameterVisitor(out);\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGExportParameterVisitor(out);\n            default:\n                return new ExportParameterizedOutputVisitor(out);\n        }\n    }\n\n    public static boolean exportParamterAndAccept(final List<Object> parameters, List<SQLExpr> list) {\n        for (int i = 0, size = list.size(); i < size; ++i) {\n            SQLExpr param = list.get(i);\n\n            SQLExpr result = exportParameter(parameters, param);\n            if (result != param) {\n                list.set(i, result);\n            }\n        }\n\n        return false;\n    }\n\n    public static SQLExpr exportParameter(final List<Object> parameters, final SQLExpr param) {\n        Object value = null;\n        boolean replace = false;\n\n        if (param instanceof SQLCharExpr) {\n            value = ((SQLCharExpr) param).getText();\n            String vStr = (String) value;\n//            if (vStr.length() > 1) {\n//                value = StringUtils.removeNameQuotes(vStr);\n//            }\n            replace = true;\n        } else if (param instanceof SQLNCharExpr) {\n            value = ((SQLNCharExpr) param).getText();\n            replace = true;\n        } else if (param instanceof SQLBooleanExpr) {\n            value = ((SQLBooleanExpr) param).getBooleanValue();\n            replace = true;\n        } else if (param instanceof SQLNumericLiteralExpr) {\n            value = ((SQLNumericLiteralExpr) param).getNumber();\n            replace = true;\n        } else if (param instanceof SQLHexExpr) {\n            value = ((SQLHexExpr) param).toBytes();\n            replace = true;\n        } else if (param instanceof SQLTimestampExpr) {\n            value = ((SQLTimestampExpr) param).getValue();\n            replace = true;\n        } else if (param instanceof SQLDateExpr) {\n            value = ((SQLDateExpr) param).getValue();\n            replace = true;\n        } else if (param instanceof SQLTimeExpr) {\n            value = ((SQLTimeExpr) param).getValue();\n            replace = true;\n        } else if (param instanceof SQLListExpr) {\n            SQLListExpr list = ((SQLListExpr) param);\n\n            List<Object> listValues = new ArrayList<Object>();\n            for (int i = 0; i < list.getItems().size(); i++) {\n                SQLExpr listItem = list.getItems().get(i);\n\n                if (listItem instanceof SQLCharExpr) {\n                    Object listValue = ((SQLCharExpr) listItem).getText();\n                    listValues.add(listValue);\n                } else if (listItem instanceof SQLBooleanExpr) {\n                    Object listValue = ((SQLBooleanExpr) listItem).getBooleanValue();\n                    listValues.add(listValue);\n                } else if (listItem instanceof SQLNumericLiteralExpr) {\n                    Object listValue = ((SQLNumericLiteralExpr) listItem).getNumber();\n                    listValues.add(listValue);\n                } else if (listItem instanceof SQLHexExpr) {\n                    Object listValue = ((SQLHexExpr) listItem).toBytes();\n                    listValues.add(listValue);\n                }\n            }\n\n            if (listValues.size() == list.getItems().size()) {\n                value = listValues;\n                replace = true;\n            }\n        } else if (param instanceof SQLNullExpr) {\n            value = null;\n            replace = true;\n        }\n\n        if (replace) {\n            SQLObject parent = param.getParent();\n            if (parent != null) {\n                List<SQLObject> mergedList = null;\n                if (parent instanceof SQLBinaryOpExpr) {\n                    mergedList = ((SQLBinaryOpExpr) parent).getMergedList();\n                }\n                if (mergedList != null) {\n                    List<Object> mergedListParams = new ArrayList<Object>(mergedList.size() + 1);\n                    for (int i = 0; i < mergedList.size(); ++i) {\n                        SQLObject item = mergedList.get(i);\n                        if (item instanceof SQLBinaryOpExpr) {\n                            SQLBinaryOpExpr binaryOpItem = (SQLBinaryOpExpr) item;\n                            exportParameter(mergedListParams, binaryOpItem.getRight());\n                        }\n                    }\n                    if (mergedListParams.size() > 0) {\n                        mergedListParams.add(0, value);\n                        value = mergedListParams;\n                    }\n                }\n            }\n\n            if (parameters != null) {\n                parameters.add(value);\n            }\n\n            return new SQLVariantRefExpr(\"?\");\n        }\n\n        return param;\n    }\n\n    public static void exportParameter(final List<Object> parameters, SQLBinaryOpExpr x) {\n        if (x.getLeft() instanceof SQLLiteralExpr\n                && x.getRight() instanceof SQLLiteralExpr\n                && x.getOperator().isRelational()) {\n            return;\n        }\n\n        {\n            SQLExpr leftResult = ExportParameterVisitorUtils.exportParameter(parameters, x.getLeft());\n            if (leftResult != x.getLeft()) {\n                x.setLeft(leftResult);\n            }\n        }\n\n        {\n            SQLExpr rightResult = exportParameter(parameters, x.getRight());\n            if (rightResult != x.getRight()) {\n                x.setRight(rightResult);\n            }\n        }\n    }\n\n    public static void exportParameter(final List<Object> parameters, SQLBetweenExpr x) {\n        {\n            SQLExpr result = exportParameter(parameters, x.getBeginExpr());\n            if (result != x.getBeginExpr()) {\n                x.setBeginExpr(result);\n            }\n        }\n\n        {\n            SQLExpr result = exportParameter(parameters, x.getEndExpr());\n            if (result != x.getBeginExpr()) {\n                x.setEndExpr(result);\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/ExportParameterizedOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ExportParameterizedOutputVisitor extends SQLASTOutputVisitor implements ExportParameterVisitor {\n    /**\n     * true= if require parameterized sql output\n     */\n    private final boolean requireParameterizedOutput;\n\n    public ExportParameterizedOutputVisitor(final List<Object> parameters,\n                                            final StringBuilder appender,\n                                            final boolean wantParameterizedOutput) {\n        super(appender, true);\n        this.parameters = parameters;\n        this.requireParameterizedOutput = wantParameterizedOutput;\n    }\n\n    public ExportParameterizedOutputVisitor() {\n        this(new ArrayList<Object>());\n    }\n\n    public ExportParameterizedOutputVisitor(final List<Object> parameters) {\n        this(parameters, new StringBuilder(), false);\n    }\n\n    public ExportParameterizedOutputVisitor(final StringBuilder appender) {\n        this(new ArrayList<Object>(), appender, true);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLExprUtils;\nimport com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLDDLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryOutputVisitor;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKOutputVisitor;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor;\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2OutputVisitor;\nimport com.alibaba.druid.sql.dialect.hologres.visitor.HologresOutputVisitor;\nimport com.alibaba.druid.sql.dialect.informix.visitor.InformixOutputVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlParameterizedVisitor;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTParameterizedVisitor;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor;\nimport com.alibaba.druid.sql.dialect.phoenix.visitor.PhoenixOutputVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;\nimport com.alibaba.druid.sql.dialect.presto.visitor.PrestoOutputVisitor;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor;\nimport com.alibaba.druid.sql.dialect.synapse.visitor.SynapseOutputVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TimeZone;\n\npublic class ParameterizedOutputVisitorUtils {\n    private static final SQLParserFeature[] defaultFeatures = {\n            SQLParserFeature.EnableSQLBinaryOpExprGroup,\n            SQLParserFeature.UseInsertColumnsCache,\n            SQLParserFeature.OptimizedForParameterized,\n    };\n\n    private static final SQLParserFeature[] defaultFeatures2 = {\n            SQLParserFeature.EnableSQLBinaryOpExprGroup,\n            SQLParserFeature.UseInsertColumnsCache,\n            SQLParserFeature.OptimizedForParameterized,\n            SQLParserFeature.OptimizedForForParameterizedSkipValue,\n    };\n\n    private static final SQLParserFeature[] defaultFeatures_tddl = {\n            SQLParserFeature.EnableSQLBinaryOpExprGroup,\n            SQLParserFeature.UseInsertColumnsCache,\n            SQLParserFeature.OptimizedForParameterized,\n            SQLParserFeature.TDDLHint,\n    };\n\n    private static final SQLParserFeature[] defaultFeatures2_tddl = {\n            SQLParserFeature.EnableSQLBinaryOpExprGroup,\n            SQLParserFeature.UseInsertColumnsCache,\n            SQLParserFeature.OptimizedForParameterized,\n            SQLParserFeature.OptimizedForForParameterizedSkipValue,\n            SQLParserFeature.TDDLHint,\n    };\n\n    public static String parameterize(String sql, DbType dbType) {\n        return parameterize(sql, dbType, null, null);\n    }\n\n    public static String parameterize(String sql, DbType dbType, VisitorFeature... features) {\n        return parameterize(sql, dbType, null, features);\n    }\n\n    public static String parameterize(\n            String sql,\n            DbType dbType,\n            SQLSelectListCache selectListCache) {\n        return parameterize(sql, dbType, selectListCache, null);\n    }\n\n    public static String parameterize(\n            String sql,\n            DbType dbType,\n            List<Object> outParameters) {\n        return parameterize(sql, dbType, null, outParameters);\n    }\n\n    public static String parameterize(\n            String sql,\n            DbType dbType,\n            List<Object> outParameters,\n            VisitorFeature... features) {\n        return parameterize(sql, dbType, null, outParameters, features);\n    }\n\n    public static String parameterizeForTDDL(\n            String sql,\n            DbType dbType,\n            List<Object> outParameters,\n            VisitorFeature... features) {\n        return parameterizeForTDDL(sql, dbType, null, outParameters, features);\n    }\n\n    private static void configVisitorFeatures(ParameterizedVisitor visitor, VisitorFeature... features) {\n        if (features != null) {\n            for (VisitorFeature feature : features) {\n                visitor.config(feature, true);\n            }\n        }\n    }\n\n    public static String parameterize(\n            String sql,\n            DbType dbType,\n            SQLSelectListCache selectListCache,\n            List<Object> outParameters,\n            VisitorFeature... visitorFeatures) {\n        final SQLParserFeature[] features = outParameters == null\n                ? defaultFeatures2\n                : defaultFeatures;\n\n        return parameterize(sql, dbType, selectListCache, outParameters, features, visitorFeatures);\n    }\n\n    public static String parameterizeForTDDL(\n            String sql,\n            DbType dbType,\n            SQLSelectListCache selectListCache,\n            List<Object> outParameters,\n            VisitorFeature... visitorFeatures) {\n        final SQLParserFeature[] features = outParameters == null\n                ? defaultFeatures2_tddl\n                : defaultFeatures_tddl;\n\n        return parameterize(sql, dbType, selectListCache, outParameters, features, visitorFeatures);\n    }\n\n    public static String parameterize(\n            String sql,\n            DbType dbType,\n            SQLSelectListCache selectListCache,\n            List<Object> outParameters,\n            SQLParserFeature[] features,\n            VisitorFeature... visitorFeatures) {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, features);\n\n        if (selectListCache != null) {\n            parser.setSelectListCache(selectListCache);\n        }\n\n        List<SQLStatement> statementList = parser.parseStatementList();\n        if (statementList.isEmpty()) {\n            return sql;\n        }\n\n        StringBuilder out = new StringBuilder(sql.length());\n        ParameterizedVisitor visitor = createParameterizedOutputVisitor(out, dbType);\n        if (outParameters != null) {\n            visitor.setOutputParameters(outParameters);\n        }\n\n        configVisitorFeatures(visitor, visitorFeatures);\n\n        for (int i = 0; i < statementList.size(); i++) {\n            SQLStatement stmt = statementList.get(i);\n\n            if (i > 0) {\n                SQLStatement preStmt = statementList.get(i - 1);\n\n                if (preStmt.getClass() == stmt.getClass()) {\n                    StringBuilder buf = new StringBuilder(sql.length());\n                    ParameterizedVisitor v1 = createParameterizedOutputVisitor(buf, dbType);\n                    preStmt.accept(v1);\n                    if (out.length() == buf.length() && out.toString().contentEquals(buf)) {\n                        continue;\n                    }\n                }\n\n                if (!preStmt.isAfterSemi()) {\n                    out.append(\";\\n\");\n                } else {\n                    out.append('\\n');\n                }\n            }\n\n            if (stmt.hasBeforeComment()) {\n                stmt.getBeforeCommentsDirect().clear();\n            }\n\n            Class<?> stmtClass = stmt.getClass();\n            if (stmtClass == SQLSelectStatement.class) { // only for performance\n                SQLSelectStatement selectStatement = (SQLSelectStatement) stmt;\n                visitor.visit(selectStatement);\n                visitor.postVisit(selectStatement);\n            } else {\n                stmt.accept(visitor);\n            }\n        }\n\n        if (visitor.getReplaceCount() == 0\n                && parser.getLexer().getCommentCount() == 0\n                && sql.charAt(0) != '/') {\n            boolean notUseOriginalSql = false;\n            if (visitorFeatures != null) {\n                for (VisitorFeature visitorFeature : visitorFeatures) {\n                    if (visitorFeature == VisitorFeature.OutputParameterizedZeroReplaceNotUseOriginalSql) {\n                        notUseOriginalSql = true;\n                        break;\n                    }\n                }\n            }\n            if (!notUseOriginalSql) {\n                int ddlStmtCount = 0;\n                for (SQLStatement stmt : statementList) {\n                    if (stmt instanceof SQLDDLStatement) {\n                        ddlStmtCount++;\n                    }\n                }\n                if (ddlStmtCount == statementList.size()) {\n                    notUseOriginalSql = true;\n                }\n            }\n\n            if (!notUseOriginalSql) {\n                return sql;\n            }\n        }\n\n        return out.toString();\n    }\n\n    public static long parameterizeHash(\n            String sql,\n            DbType dbType,\n            List<Object> outParameters) {\n        return parameterizeHash(sql, dbType, null, outParameters, null);\n    }\n\n    public static long parameterizeHash(\n            String sql,\n            DbType dbType,\n            SQLSelectListCache selectListCache,\n            List<Object> outParameters) {\n        return parameterizeHash(sql, dbType, selectListCache, outParameters, null);\n    }\n\n    public static long parameterizeHash(\n            String sql,\n            DbType dbType,\n            SQLSelectListCache selectListCache,\n            List<Object> outParameters,\n            VisitorFeature... visitorFeatures) {\n        final SQLParserFeature[] features = outParameters == null\n                ? defaultFeatures2\n                : defaultFeatures;\n\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, features);\n\n        if (selectListCache != null) {\n            parser.setSelectListCache(selectListCache);\n        }\n\n        List<SQLStatement> statementList = parser.parseStatementList();\n        final int stmtSize = statementList.size();\n        if (stmtSize == 0) {\n            return 0L;\n        }\n\n        StringBuilder out = new StringBuilder(sql.length());\n        ParameterizedVisitor visitor = createParameterizedOutputVisitor(out, dbType);\n        if (outParameters != null) {\n            visitor.setOutputParameters(outParameters);\n        }\n        configVisitorFeatures(visitor, visitorFeatures);\n\n        if (stmtSize == 1) {\n            SQLStatement stmt = statementList.get(0);\n            if (stmt.getClass() == SQLSelectStatement.class) {\n                SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;\n\n                if (selectListCache != null) {\n                    SQLSelectQueryBlock queryBlock = selectStmt.getSelect().getQueryBlock();\n                    if (queryBlock != null) {\n                        String cachedSelectList = queryBlock.getCachedSelectList();\n                        long cachedSelectListHash = queryBlock.getCachedSelectListHash();\n                        if (cachedSelectList != null) {\n                            visitor.config(VisitorFeature.OutputSkipSelectListCacheString, true);\n                        }\n\n                        visitor.visit(selectStmt);\n                        return FnvHash.fnv1a_64_lower(cachedSelectListHash, out);\n                    }\n                }\n\n                visitor.visit(selectStmt);\n            } else if (stmt.getClass() == MySqlInsertStatement.class) {\n                MySqlInsertStatement insertStmt = (MySqlInsertStatement) stmt;\n                String columnsString = insertStmt.getColumnsString();\n                if (columnsString != null) {\n                    long columnsStringHash = insertStmt.getColumnsStringHash();\n                    visitor.config(VisitorFeature.OutputSkipInsertColumnsString, true);\n\n                    ((MySqlASTVisitor) visitor).visit(insertStmt);\n                    return FnvHash.fnv1a_64_lower(columnsStringHash, out);\n                }\n            } else {\n                stmt.accept(visitor);\n            }\n\n            return FnvHash.fnv1a_64_lower(out);\n        }\n\n        for (int i = 0; i < statementList.size(); i++) {\n            if (i > 0) {\n                out.append(\";\\n\");\n            }\n            SQLStatement stmt = statementList.get(i);\n\n            if (stmt.hasBeforeComment()) {\n                stmt.getBeforeCommentsDirect().clear();\n            }\n\n            Class<?> stmtClass = stmt.getClass();\n            if (stmtClass == SQLSelectStatement.class) { // only for performance\n                SQLSelectStatement selectStatement = (SQLSelectStatement) stmt;\n                visitor.visit(selectStatement);\n                visitor.postVisit(selectStatement);\n            } else {\n                stmt.accept(visitor);\n            }\n        }\n\n        return FnvHash.fnv1a_64_lower(out);\n    }\n\n    public static String parameterize(List<SQLStatement> statementList, DbType dbType) {\n        StringBuilder out = new StringBuilder();\n        ParameterizedVisitor visitor = createParameterizedOutputVisitor(out, dbType);\n\n        for (int i = 0; i < statementList.size(); i++) {\n            if (i > 0) {\n                out.append(\";\\n\");\n            }\n            SQLStatement stmt = statementList.get(i);\n\n            if (stmt.hasBeforeComment()) {\n                stmt.getBeforeCommentsDirect().clear();\n            }\n            stmt.accept(visitor);\n        }\n\n        return out.toString();\n    }\n\n    public static String parameterize(SQLStatement stmt, DbType dbType) {\n        StringBuilder out = new StringBuilder();\n        ParameterizedVisitor visitor = createParameterizedOutputVisitor(out, dbType);\n\n        if (stmt.hasBeforeComment()) {\n            stmt.getBeforeCommentsDirect().clear();\n        }\n        stmt.accept(visitor);\n\n        return out.toString();\n    }\n\n    public static SQLStatement parameterizeOf(String sql, DbType dbType) {\n        return parameterizeOf(sql, null, dbType);\n    }\n\n    public static SQLStatement parameterizeOf(String sql, List<Object> outParameters, DbType dbType) {\n        if (dbType == DbType.mysql) {\n            SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n            MySqlParameterizedVisitor visitor = new MySqlParameterizedVisitor(outParameters);\n            stmt.accept(visitor);\n            return stmt;\n        } else if (dbType == DbType.oracle) {\n            SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.oracle);\n            OracleASTParameterizedVisitor visitor = new OracleASTParameterizedVisitor(outParameters);\n            stmt.accept(visitor);\n            return stmt;\n        } else {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    public static ParameterizedVisitor createParameterizedOutputVisitor(StringBuilder out, DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        switch (dbType) {\n            case oracle:\n            case oceanbase_oracle:\n            case polardb2:\n                return new OracleParameterizedOutputVisitor(out);\n            case mysql:\n            case tidb:\n            case mariadb:\n            case goldendb:\n            case oceanbase:\n            case drds:\n            case elastic_search:\n            case polardbx:\n                return new MySqlOutputVisitor(out, true);\n            case h2:\n            case lealone:\n                return new H2OutputVisitor(out, true);\n            case informix:\n                return new InformixOutputVisitor(out, true);\n            case postgresql:\n            case greenplum:\n            case edb:\n            case gaussdb:\n                return new PGOutputVisitor(out, true);\n            case hologres:\n                return new HologresOutputVisitor(out, true);\n            case sqlserver:\n            case jtds:\n                return new SQLServerOutputVisitor(out, true);\n            case synapse:\n                return new SynapseOutputVisitor(out, true);\n            case db2:\n                return new DB2OutputVisitor(out, true);\n            case phoenix:\n                return new PhoenixOutputVisitor(out, true);\n            case presto:\n            case trino:\n                return new PrestoOutputVisitor(out, true);\n            case clickhouse:\n                return new CKOutputVisitor(out, true);\n            case bigquery:\n                return new BigQueryOutputVisitor(out, true);\n            default:\n                return new SQLASTOutputVisitor(out, true);\n        }\n    }\n\n    public static String restore(String sql, DbType dbType, List<Object> parameters) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, dbType);\n        visitor.setInputParameters(parameters);\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n\n        return out.toString();\n    }\n\n    public static String restore(String sql, DbType dbType, Map<String, Object> parameters) {\n        if (parameters == null || parameters.size() == 0) {\n            return sql;\n        }\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        RestoreVisitor v = new RestoreVisitor(parameters);\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(v);\n        }\n\n        StringBuilder out = new StringBuilder(sql.length());\n        SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, dbType);\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(visitor);\n        }\n\n        return out.toString();\n    }\n\n    private static class RestoreVisitor extends SQLASTVisitorAdapter {\n        Map<String, Object> parameters;\n        TimeZone timeZone;\n\n        public RestoreVisitor(Map<String, Object> parameters) {\n            this.parameters = parameters;\n        }\n\n        public boolean visit(SQLVariantRefExpr x) {\n            String name = x.getName();\n            if (name.length() > 3) {\n                char c0 = name.charAt(0);\n                char c1 = name.charAt(1);\n                char c1x = name.charAt(name.length() - 1);\n\n                if (c0 == '#' && c1 == '{' && c1x == '}') {\n                    String key = name.substring(2, name.length() - 1);\n                    Object value = parameters.get(key);\n                    SQLExpr expr = SQLExprUtils.fromJavaObject(value, timeZone);\n                    SQLUtils.replaceInParent(x, expr);\n                }\n            }\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\n\nimport java.util.List;\n\npublic interface ParameterizedVisitor extends PrintableVisitor {\n    int getReplaceCount();\n\n    void incrementReplaceCunt();\n\n    DbType getDbType();\n\n    void setOutputParameters(List<Object> parameters);\n\n    void config(VisitorFeature feature, boolean state);\n\n    boolean isEnabled(VisitorFeature feature);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/PrintableVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\npublic interface PrintableVisitor extends SQLASTVisitor {\n    boolean isUppCase();\n\n    void print(char value);\n\n    void print(String text);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType;\nimport com.alibaba.druid.sql.ast.statement.SQLMergeStatement.WhenInsert;\nimport com.alibaba.druid.sql.ast.statement.SQLMergeStatement.WhenUpdate;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInputOutputFormat;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsNewExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreatePackageStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForStatement;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleProcedureDataType;\nimport com.alibaba.druid.sql.parser.CharTypes;\nimport com.alibaba.druid.sql.template.SQLSelectQueryTemplate;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.NClob;\nimport java.text.SimpleDateFormat;\nimport java.time.Instant;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.LocalTime;\nimport java.time.OffsetDateTime;\nimport java.time.OffsetTime;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.time.temporal.TemporalAmount;\nimport java.util.*;\n\nimport static com.alibaba.druid.util.Utils.getBoolean;\n\npublic class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements ParameterizedVisitor, PrintableVisitor {\n    public static Boolean defaultPrintStatementAfterSemi;\n\n    static {\n        try {\n            defaultPrintStatementAfterSemi = getBoolean(System.getProperties(), \"fastsql.sql.output.printStatementAfterSemi\"); // compatible for early versions\n        } catch (SecurityException ex) {\n            // skip\n        }\n    }\n\n    protected final StringBuilder appender;\n    protected int indentCount;\n    protected boolean ucase = true;\n    protected int selectListNumberOfLine = 5;\n\n    protected boolean groupItemSingleLine;\n\n    protected List<Object> parameters;\n    protected List<Object> inputParameters;\n    protected Set<String> tables;\n    protected String table; // for improved\n\n    protected boolean exportTables;\n\n    protected DbType dbType;\n\n    protected Map<String, String> tableMapping;\n\n    protected int replaceCount;\n\n    protected boolean parameterizedMergeInList;\n    protected boolean parameterizedQuesUnMergeInList;\n    protected boolean parameterizedQuesUnMergeValuesList;\n    protected boolean printNameQuote;\n\n    protected boolean parameterized;\n    protected boolean shardingSupport;\n\n    protected transient int lines;\n    private TimeZone timeZone;\n    protected boolean endLineComment;\n\n    protected SQLDialect dialect;\n    protected final SQLASTOutputVisitorBinaryOpSupport binaryOpSupport = new SQLASTOutputVisitorBinaryOpSupport(this);\n\n    protected Boolean printStatementAfterSemi = defaultPrintStatementAfterSemi;\n\n    {\n        features |= VisitorFeature.OutputPrettyFormat.mask;\n    }\n\n    public SQLASTOutputVisitor(StringBuilder appender) {\n        this.appender = appender;\n    }\n\n    public SQLASTOutputVisitor(StringBuilder appender, DbType dbType) {\n        this(appender, dbType, SQLDialect.of(dbType));\n    }\n\n    public SQLASTOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect) {\n        this.appender = appender;\n        this.dbType = dbType;\n        this.dialect = dialect;\n    }\n\n    public SQLASTOutputVisitor(StringBuilder appender, boolean parameterized) {\n        this.appender = appender;\n        this.dialect = SQLDialect.of(dbType);\n        this.config(VisitorFeature.OutputParameterized, parameterized);\n    }\n\n    public SQLASTOutputVisitor(StringBuilder appender, DbType dbType, boolean parameterized) {\n        this(appender, dbType, SQLDialect.of(dbType), parameterized);\n    }\n\n    public SQLASTOutputVisitor(StringBuilder appender, DbType dbType, SQLDialect dialect, boolean parameterized) {\n        this.appender = appender;\n        this.dbType = dbType;\n        this.dialect = dialect;\n        this.config(VisitorFeature.OutputParameterized, parameterized);\n    }\n\n    public int getReplaceCount() {\n        return this.replaceCount;\n    }\n\n    public void incrementReplaceCunt() {\n        replaceCount++;\n    }\n\n    public TimeZone getTimeZone() {\n        return timeZone;\n    }\n\n    public void setTimeZone(TimeZone timeZone) {\n        this.timeZone = timeZone;\n    }\n\n    public void addTableMapping(String srcTable, String destTable) {\n        if (tableMapping == null) {\n            tableMapping = new HashMap<String, String>();\n        }\n\n        if (srcTable.indexOf('.') >= 0) {\n            SQLExpr expr = SQLUtils.toSQLExpr(srcTable, dbType);\n            if (expr instanceof SQLPropertyExpr) {\n                srcTable = ((SQLPropertyExpr) expr).simplify().toString();\n            }\n        } else {\n            srcTable = SQLUtils.normalize(srcTable);\n        }\n        tableMapping.put(srcTable, destTable);\n    }\n\n    public void setTableMapping(Map<String, String> tableMapping) {\n        this.tableMapping = tableMapping;\n    }\n\n    public List<Object> getParameters() {\n        if (parameters == null) {\n            parameters = new ArrayList<Object>();\n        }\n\n        return parameters;\n    }\n\n    public boolean isDesensitize() {\n        return isEnabled(VisitorFeature.OutputDesensitize);\n    }\n\n    public void setDesensitize(boolean desensitize) {\n        config(VisitorFeature.OutputDesensitize, desensitize);\n    }\n\n    public Set<String> getTables() {\n        if (this.table != null && this.tables == null) {\n            return Collections.singleton(this.table);\n        }\n        return this.tables;\n    }\n\n    @Deprecated\n    public void setParameters(List<Object> parameters) {\n        if (parameters != null && parameters.size() > 0) {\n            this.inputParameters = parameters;\n        } else {\n            this.parameters = parameters;\n        }\n    }\n\n    public void setInputParameters(List<Object> parameters) {\n        this.inputParameters = parameters;\n    }\n\n    /**\n     * @since 1.1.5\n     */\n    public void setOutputParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public int getIndentCount() {\n        return indentCount;\n    }\n\n    public StringBuilder getAppender() {\n        return appender;\n    }\n\n    public boolean isPrettyFormat() {\n        return isEnabled(VisitorFeature.OutputPrettyFormat);\n    }\n\n    public void setPrettyFormat(boolean prettyFormat) {\n        config(VisitorFeature.OutputPrettyFormat, prettyFormat);\n    }\n\n    public void decrementIndent() {\n        this.indentCount--;\n    }\n\n    public void incrementIndent() {\n        this.indentCount++;\n    }\n\n    public boolean isParameterized() {\n        return isEnabled(VisitorFeature.OutputParameterized);\n    }\n\n    public void setParameterized(boolean parameterized) {\n        config(VisitorFeature.OutputParameterized, parameterized);\n    }\n\n    public boolean isParameterizedMergeInList() {\n        return parameterizedMergeInList;\n    }\n\n    public void setParameterizedMergeInList(boolean parameterizedMergeInList) {\n        this.parameterizedMergeInList = parameterizedMergeInList;\n    }\n\n    public boolean isParameterizedQuesUnMergeInList() {\n        return parameterizedQuesUnMergeInList;\n    }\n\n    public void setParameterizedQuesUnMergeInList(boolean parameterizedQuesUnMergeInList) {\n        config(VisitorFeature.OutputParameterizedQuesUnMergeInList, parameterizedQuesUnMergeInList);\n    }\n\n    public boolean isExportTables() {\n        return exportTables;\n    }\n\n    public void setExportTables(boolean exportTables) {\n        this.exportTables = exportTables;\n    }\n\n    public final void print(char value) {\n        if (endLineComment) {\n            println();\n        }\n\n        print0(value);\n    }\n\n    protected final void print0(char value) {\n        if (this.appender == null) {\n            return;\n        }\n\n        this.appender.append(value);\n    }\n\n    public void print(int value) {\n        if (this.appender == null) {\n            return;\n        }\n\n        appender.append(value);\n    }\n\n    public void print(long value) {\n        if (this.appender == null) {\n            return;\n        }\n\n        appender.append(value);\n    }\n\n    public void print(float value) {\n        if (this.appender == null) {\n            return;\n        }\n\n        appender.append(value);\n    }\n\n    public void print(double value) {\n        if (this.appender == null) {\n            return;\n        }\n\n        appender.append(value);\n    }\n\n    public void print(Date date) {\n        if (this.appender == null) {\n            return;\n        }\n\n        SimpleDateFormat dateFormat;\n        if (date instanceof java.sql.Date) {\n            dateFormat = new SimpleDateFormat(\"yyyy-MM-dd\");\n            print0(\"DATE \");\n        } else if (date instanceof java.sql.Time) {\n            dateFormat = new SimpleDateFormat(\"HH:mm:ss\");\n            print0(\"TIME \");\n        } else {\n            dateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss.SSS\");\n            print0(\"TIMESTAMP \");\n        }\n\n        if (timeZone != null) {\n            dateFormat.setTimeZone(timeZone);\n        }\n\n        print0(\"'\" + dateFormat.format(date) + \"'\");\n    }\n\n    public void print(String text) {\n        if (this.appender == null) {\n            return;\n        }\n        print0(text);\n    }\n\n    protected void print0(String text) {\n        if (appender == null) {\n            return;\n        }\n\n        this.appender.append(text);\n    }\n\n    protected void printUcase(String text) {\n        print0(ucase ? text.toUpperCase() : text.toLowerCase());\n    }\n    protected void printName0(String name, boolean needQuote) {\n        StringBuilder appender = this.appender;\n        if (appender == null || name.isEmpty()) {\n            return;\n        }\n\n        SQLDialect dialect = this.dialect;\n        char quote = '\"';\n        boolean keyword = false;\n        if (isEnabled(VisitorFeature.OutputNameQuote) && dialect != null && dialect.getQuoteChars() != SQLDialect.DEFAULT_QUOTE_INT && needQuote) {\n            keyword = dialect.isKeyword(name);\n            quote = SQLDialect.Quote.getQuote(dialect.getQuoteChars());\n        }\n\n        if (keyword) {\n            appender.append(quote);\n        }\n        appender.append(name);\n        if (keyword) {\n            appender.append(quote);\n        }\n    }\n\n    protected void printName0(String name) {\n        printName0(name, true);\n    }\n\n    protected boolean nameHasSpecial(String alias) {\n        int len = alias.length();\n        if (len == 0) {\n            return false;\n        }\n        char c0 = alias.charAt(0);\n        if (c0 != '\"' && c0 != '\\'' && c0 != '`' && c0 != '[') {\n            for (int i = 1; i < len; ++i) {\n                char ch = alias.charAt(i);\n                if (ch < 256 &&\n                        !((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' || ch == '$')) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    protected void printAlias0(String alias) {\n        boolean special = nameHasSpecial(alias);\n        StringBuilder appender = this.appender;\n        SQLDialect dialect = this.dialect;\n        char quote = dialect != null ? SQLDialect.Quote.getQuote(dialect.getQuoteChars()) : '\"';\n        boolean needQuote = special;\n        if (!needQuote && isEnabled(VisitorFeature.OutputNameQuote) && dialect != null) {\n            needQuote = dialect.isAliasKeyword(alias);\n        }\n\n        if (needQuote) {\n            appender.append(quote);\n        }\n        appender.append(alias);\n        if (needQuote) {\n            appender.append(quote);\n        }\n    }\n\n    protected void printAlias(String alias) {\n        if (alias == null || alias.length() == 0) {\n            return;\n        }\n\n        print(' ');\n\n        printAlias0(alias);\n    }\n\n    protected void printPrefix(boolean predicate, String ucaseMessage, String lcaseMessage) {\n        if (!predicate) {\n            return;\n        }\n        print0(ucase ? ucaseMessage : lcaseMessage);\n    }\n\n    protected void printAndAccept(List<? extends SQLObject> nodes, String seperator) {\n        for (int i = 0, size = nodes.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(seperator);\n            }\n            nodes.get(i).accept(this);\n        }\n    }\n\n    protected void printlnAndAccept(List<? extends SQLObject> nodes, boolean needPrintLine) {\n        if (needPrintLine) {\n            incrementIndent();\n            println();\n        }\n        for (int i = 0; i < nodes.size(); i++) {\n            if (i != 0) {\n                if (needPrintLine) {\n                    print0(',');\n                    println();\n                } else {\n                    print0(\", \");\n                }\n            }\n            nodes.get(i)\n                    .accept(this);\n        }\n        if (needPrintLine) {\n            decrementIndent();\n            println();\n        }\n    }\n\n    protected void printAndAccept(\n            String prefix,\n            String suffix,\n            List<? extends SQLObject> nodes,\n            String separator,\n            int lineItems\n    ) {\n        int size = nodes.size();\n        print(prefix);\n        incrementIndent();\n        if (size > lineItems) {\n            println();\n        }\n        for (int i = 0; i < size; ++i) {\n            if (i != 0) {\n                if (i % lineItems == 0) {\n                    println(separator.trim());\n                } else {\n                    print0(separator);\n                }\n            }\n            nodes.get(i).accept(this);\n        }\n        decrementIndent();\n        if (size > lineItems) {\n            println();\n        }\n        print(suffix);\n    }\n\n    protected void printAndAccept(List<? extends SQLExpr> nodes, String seperator, boolean parameterized) {\n        for (int i = 0, size = nodes.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(seperator);\n            }\n            printExpr(nodes.get(i), parameterized);\n        }\n    }\n\n    private static int paramCount(SQLExpr x) {\n        if (x instanceof SQLName) {\n            return 1;\n        }\n\n        if (x instanceof SQLAggregateExpr) {\n            SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) x;\n            List<SQLExpr> args = aggregateExpr.getArguments();\n            int paramCount = 1;\n            for (SQLExpr arg : args) {\n                paramCount += paramCount(arg);\n            }\n            if (aggregateExpr.getOver() != null) {\n                paramCount += 1;\n            }\n            return paramCount;\n        }\n\n        if (x instanceof SQLMethodInvokeExpr) {\n            List<SQLExpr> params = ((SQLMethodInvokeExpr) x).getArguments();\n            int paramCount = 1;\n            for (SQLExpr param : params) {\n                paramCount += paramCount(param);\n            }\n            return paramCount;\n        }\n\n        if (x instanceof SQLBinaryOpExpr) {\n            return paramCount(((SQLBinaryOpExpr) x).getLeft())\n                    + paramCount(((SQLBinaryOpExpr) x).getRight());\n        }\n\n        if (x instanceof SQLCaseExpr) {\n            return 10;\n        }\n\n        return 1;\n    }\n\n    protected void printSelectList(List<SQLSelectItem> selectList) {\n        this.indentCount++;\n        for (int i = 0, lineItemCount = 0, size = selectList.size(); i < size; ++i, ++lineItemCount) {\n            SQLSelectItem selectItem = selectList.get(i);\n            if (selectItem.hasBeforeComment()) {\n                printlnComments(selectItem.getBeforeCommentsDirect());\n            }\n            SQLExpr selectItemExpr = selectItem.getExpr();\n\n            int paramCount = paramCount(selectItemExpr);\n\n            boolean methodOrBinary = (!(selectItemExpr instanceof SQLName))\n                    && (selectItemExpr instanceof SQLMethodInvokeExpr\n                    || selectItemExpr instanceof SQLAggregateExpr\n                    || selectItemExpr instanceof SQLBinaryOpExpr);\n\n            if (methodOrBinary) {\n                lineItemCount += (paramCount - 1);\n            }\n\n            if (i != 0) {\n                SQLSelectItem preSelectItem = selectList.get(i - 1);\n                if (preSelectItem.getAfterCommentsDirect() != null) {\n                    lineItemCount = 0;\n                    println();\n                } else if (methodOrBinary) {\n                    if (lineItemCount >= selectListNumberOfLine) {\n                        lineItemCount = paramCount;\n                        println();\n                    }\n                } else if (lineItemCount >= selectListNumberOfLine\n                        || selectItemExpr instanceof SQLQueryExpr\n                        || selectItemExpr instanceof SQLCaseExpr\n                        || (selectItemExpr instanceof SQLCharExpr && ((SQLCharExpr) selectItemExpr).getText().length() > 20)) {\n                    lineItemCount = 0;\n                    println();\n                }\n                if (selectItem.getExpr() instanceof SQLVariantRefExpr && !((SQLVariantRefExpr) selectItem.getExpr()).isHasPrefixComma()) {\n                    print0(\" \");\n                } else {\n                    print0(\", \");\n                }\n            }\n\n            if (selectItem.getClass() == SQLSelectItem.class) {\n                this.visit(selectItem);\n            } else {\n                selectItem.accept(this);\n            }\n\n            if (selectItem.hasAfterComment()) {\n                print(' ');\n                printlnComment(selectItem.getAfterCommentsDirect());\n            }\n        }\n        this.indentCount--;\n    }\n\n    protected void printlnAndAccept(List<? extends SQLObject> nodes, String seperator) {\n        for (int i = 0, size = nodes.size(); i < size; ++i) {\n            if (i != 0) {\n                println(seperator);\n            }\n\n            ((SQLObject) nodes.get(i)).accept(this);\n        }\n    }\n\n    protected void printIndent() {\n        if (this.appender == null) {\n            return;\n        }\n\n        for (int i = 0; i < this.indentCount; ++i) {\n            this.appender.append('\\t');\n        }\n    }\n\n    public void println() {\n        if (!isPrettyFormat() && !endLineComment) {\n            print(' ');\n            return;\n        }\n\n        print0('\\n');\n        lines++;\n        printIndent();\n        if (endLineComment) {\n            endLineComment = false;\n        }\n    }\n\n    public void println(String text) {\n        print(text);\n        println();\n    }\n\n    public void println(char ch) {\n        print(ch);\n        println();\n    }\n\n    // ////////////////////\n\n    public boolean visit(SQLBetweenExpr x) {\n        return binaryOpSupport.visitBetweenExpr(x);\n    }\n\n    public boolean visit(SQLBinaryOpExprGroup x) {\n        return binaryOpSupport.visitBinaryOpExprGroup(x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return binaryOpSupport.visitBinaryOpExpr(x);\n    }\n\n    public boolean visit(SQLTypeExpr x) {\n        boolean needPrefixDataType = ! (x instanceof SQLBooleanExpr);\n        boolean needQuota = ! (x instanceof SQLBooleanExpr);\n        if (needPrefixDataType) {\n            String dataType = x.getDataType().getName();\n            print(ucase ? dataType.toUpperCase() : dataType.toLowerCase());\n            print(' ');\n        }\n        if (parameterized) {\n            print('?');\n        } else {\n            if (needQuota) {\n                print(\"'\");\n            }\n            print(x.getValue().toString());\n            if (needQuota) {\n                print(\"'\");\n            }\n        }\n        return false;\n    }\n    public boolean visitInternal(SQLBinaryOpExpr x) {\n        SQLBinaryOperator operator = x.getOperator();\n        if (this.parameterized\n                && operator == SQLBinaryOperator.BooleanOr\n                && !isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeOr)) {\n            x = SQLBinaryOpExpr.merge(this, x);\n\n            operator = x.getOperator();\n        }\n\n        if (inputParameters != null\n                && inputParameters.size() > 0\n                && operator == SQLBinaryOperator.Equality\n                && x.getRight() instanceof SQLVariantRefExpr\n        ) {\n            SQLVariantRefExpr right = (SQLVariantRefExpr) x.getRight();\n            int index = right.getIndex();\n            if (index >= 0 && index < inputParameters.size()) {\n                Object param = inputParameters.get(index);\n                if (param instanceof Collection) {\n                    x.getLeft().accept(this);\n                    print0(\" IN (\");\n                    right.accept(this);\n                    print(')');\n                    return false;\n                }\n            }\n        }\n\n        SQLObject parent = x.getParent();\n        boolean isRoot = parent instanceof SQLSelectQueryBlock;\n        boolean relational = operator == SQLBinaryOperator.BooleanAnd\n                || operator == SQLBinaryOperator.BooleanOr;\n        if (isRoot && relational) {\n            this.indentCount++;\n        }\n\n        List<SQLExpr> groupList = new ArrayList<SQLExpr>();\n        SQLExpr left = x.getLeft();\n        SQLExpr right = x.getRight();\n\n        if (inputParameters != null\n                && operator != SQLBinaryOperator.Equality) {\n            int varIndex = -1;\n            if (right instanceof SQLVariantRefExpr) {\n                varIndex = ((SQLVariantRefExpr) right).getIndex();\n            }\n\n            Object param = null;\n            if (varIndex >= 0 && varIndex < inputParameters.size()) {\n                param = inputParameters.get(varIndex);\n            }\n\n            if (param instanceof Collection) {\n                Collection values = (Collection) param;\n\n                if (values.size() > 0) {\n                    print('(');\n                    int valIndex = 0;\n                    for (Object value : values) {\n                        if (valIndex++ != 0) {\n                            print0(ucase ? \" OR \" : \" or \");\n                        }\n                        printExpr(left, parameterized);\n                        print(' ');\n                        if (operator == SQLBinaryOperator.Is) {\n                            print('=');\n                        } else {\n                            printOperator(operator);\n                        }\n                        print(' ');\n                        printParameter(value);\n                    }\n                    print(')');\n                    return false;\n                }\n            }\n        }\n\n        if (operator.isRelational()\n                && left instanceof SQLIntegerExpr\n                && right instanceof SQLIntegerExpr) {\n            print(((SQLIntegerExpr) left).getNumber().longValue());\n            print(' ');\n            printOperator(operator);\n            print(' ');\n            Number number = ((SQLIntegerExpr) right).getNumber();\n            if (right.hasBeforeComment()) {\n                printlnComments(right.getBeforeCommentsDirect());\n            }\n            if (number instanceof BigInteger) {\n                print0(((BigInteger) number).toString());\n            } else {\n                print(number.longValue());\n            }\n            if (right.hasAfterComment()) {\n                printAfterComments(right.getAfterCommentsDirect());\n            }\n            return false;\n        }\n\n        for (; ; ) {\n            if (left instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) left).getOperator() == operator\n                && operator != SQLBinaryOperator.IsNot && operator != SQLBinaryOperator.Is && operator != SQLBinaryOperator.Modulus) {\n                SQLBinaryOpExpr binaryLeft = (SQLBinaryOpExpr) left;\n                groupList.add(binaryLeft.getRight());\n                left = binaryLeft.getLeft();\n            } else {\n                groupList.add(left);\n                break;\n            }\n        }\n\n        for (int i = groupList.size() - 1; i >= 0; --i) {\n            SQLExpr item = groupList.get(i);\n\n            if (relational) {\n                if (isPrettyFormat() && item.hasBeforeComment() && !parameterized) {\n                    printlnComments(item.getBeforeCommentsDirect());\n                }\n            }\n\n            visitBinaryLeft(item, operator);\n\n//            if (isPrettyFormat() && item.hasAfterComment()) {\n//                print(' ');\n//                printlnComment(item.getAfterCommentsDirect());\n//            }\n\n            if (i != groupList.size() - 1\n                    && isPrettyFormat()\n                    && item.getParent() != null\n                    && item.getParent().hasAfterComment()\n                    && !parameterized) {\n                print(' ');\n                printlnComment(item.getParent().getAfterCommentsDirect());\n            }\n\n            boolean printOpSpace = true;\n            if (relational) {\n                if ((DbType.hive == dbType || DbType.spark == dbType) && x.getParent() instanceof SQLMethodInvokeExpr) {\n                    print(' ');\n                } else {\n                    println();\n                }\n            } else {\n                if (operator == SQLBinaryOperator.Modulus\n                        && DbType.oracle == dbType\n                        && left instanceof SQLIdentifierExpr\n                        && right instanceof SQLIdentifierExpr\n                        && ((SQLIdentifierExpr) right).getName().equalsIgnoreCase(\"NOTFOUND\")) {\n                    printOpSpace = false;\n                }\n                if (printOpSpace && operator != SQLBinaryOperator.Blank) {\n                    print(' ');\n                }\n            }\n            printOperator(operator);\n            if (printOpSpace) {\n                print(' ');\n            }\n        }\n        visitorBinaryRight(x);\n\n        if (isRoot && relational) {\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    protected void printOperator(SQLBinaryOperator operator) {\n        print0(ucase ? operator.name : operator.nameLCase);\n    }\n\n    private void visitorBinaryRight(SQLBinaryOpExpr x) {\n        SQLExpr right = x.getRight();\n        SQLBinaryOperator op = x.getOperator();\n        if (right instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryRight = (SQLBinaryOpExpr) right;\n            SQLBinaryOperator rightOp = binaryRight.getOperator();\n\n            boolean rightRational = rightOp == SQLBinaryOperator.BooleanAnd\n                    || rightOp == SQLBinaryOperator.BooleanOr;\n\n            if (rightOp.priority >= op.priority\n                    || (rightOp != op\n                    && rightOp.isLogical()\n                    && op.isLogical()\n            )) {\n                if (rightRational) { //这里需要验证\n                    this.indentCount++;\n                }\n                //print('(');\n                printExpr(binaryRight, parameterized);\n                //print(')');\n\n                if (rightRational) {\n                    this.indentCount--;\n                }\n            } else {\n                printExpr(binaryRight, parameterized);\n            }\n        } else if (right instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) right;\n            if (group.getOperator() == x.getOperator()) {\n                visit(group);\n            } else {\n                indentCount++;\n                print('(');\n                visit(group);\n                print(')');\n                indentCount--;\n            }\n        } else if (SQLBinaryOperator.Equality.priority >= op.priority\n                && (right instanceof SQLNotExpr)) {\n            indentCount++;\n            print('(');\n            printExpr(right, parameterized);\n            print(')');\n            indentCount--;\n        } else {\n            printExpr(right, parameterized);\n        }\n\n        if (x.getHint() != null) {\n            x.getHint().accept(this);\n        }\n    }\n\n    private void visitBinaryLeft(SQLExpr left, SQLBinaryOperator op) {\n        if (left instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryLeft = (SQLBinaryOpExpr) left;\n            SQLBinaryOperator leftOp = binaryLeft.getOperator();\n            SQLObject parent = left.getParent();\n            boolean leftRational = leftOp == SQLBinaryOperator.BooleanAnd\n                    || leftOp == SQLBinaryOperator.BooleanOr;\n\n            final boolean bracket;\n            if (leftOp.priority > op.priority) {\n                bracket = true;\n            } else if (leftOp.priority == op.priority\n                    && parent instanceof SQLBinaryOpExpr\n                    && parent.getParent() instanceof SQLBinaryOpExpr\n                    && leftOp.priority == ((SQLBinaryOpExpr) parent.getParent()).getOperator().priority\n                    && left == ((SQLBinaryOpExpr) parent).getRight()) {\n                bracket = true;\n            } else if ((leftOp == SQLBinaryOperator.Is || leftOp == SQLBinaryOperator.IsNot) && !op.isLogical()) {\n                bracket = true;\n            } else if (binaryLeft.isParenthesized()) {\n                if (leftOp != op && ((leftOp.isLogical() && op.isLogical()) || op == SQLBinaryOperator.Is)) {\n                    bracket = true;\n                } else {\n                    bracket = false;\n                }\n            } else {\n                bracket = false;\n            }\n\n            if (bracket) {\n                if (leftRational) {\n                    this.indentCount++;\n                }\n                //print('(');\n                printExpr(left, parameterized);\n               // print(')');\n\n                if (leftRational) {\n                    this.indentCount--;\n                }\n            } else {\n                printExpr(left, parameterized);\n            }\n        } else if (left instanceof SQLBinaryOpExprGroup) {\n            SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) left;\n            if (group.getOperator() == op) {\n                visit(group);\n            } else {\n                indentCount++;\n                print('(');\n                visit(group);\n                print(')');\n                indentCount--;\n            }\n        } else if (left instanceof SQLInListExpr) {\n            SQLInListExpr inListExpr = (SQLInListExpr) left;\n            boolean quote;\n            if (inListExpr.isNot()) {\n                quote = op.priority <= SQLBinaryOperator.Equality.priority;\n            } else {\n                quote = op.priority < SQLBinaryOperator.Equality.priority;\n            }\n            if (inListExpr.isParenthesized()) {\n                quote = false;\n            }\n            if (quote) {\n                print('(');\n            }\n            visit(inListExpr);\n            if (quote) {\n                print(')');\n            }\n        } else if (left instanceof SQLBetweenExpr) {\n            SQLBetweenExpr betweenExpr = (SQLBetweenExpr) left;\n            visit(betweenExpr);\n        } else if (left instanceof SQLNotExpr) {\n            printExpr(left);\n        } else if (left instanceof SQLUnaryExpr) {\n            SQLUnaryExpr unary = (SQLUnaryExpr) left;\n\n            boolean quote = true;\n            switch (unary.getOperator()) {\n                case BINARY:\n                    quote = false;\n                    break;\n                case Plus:\n                case Negative:\n                    quote = op.priority < SQLBinaryOperator.Add.priority;\n                    break;\n                default:\n                    break;\n            }\n            if (((SQLUnaryExpr) left).isParenthesized()) {\n                quote = false;\n            }\n            if (quote) {\n                //print('(');\n                printExpr(left);\n               //print(')');\n            } else {\n                printExpr(left);\n            }\n        } else {\n            printExpr(left, parameterized);\n        }\n    }\n\n    protected void printTableSource(SQLTableSource x) {\n        Class<?> clazz = x.getClass();\n        if (clazz == SQLJoinTableSource.class) {\n            visit((SQLJoinTableSource) x);\n        } else if (clazz == SQLExprTableSource.class) {\n            visit((SQLExprTableSource) x);\n        } else if (clazz == SQLSubqueryTableSource.class) {\n            visit((SQLSubqueryTableSource) x);\n        } else {\n            x.accept(this);\n        }\n    }\n\n    protected void printQuery(SQLSelectQuery x) {\n        Class<?> clazz = x.getClass();\n        if (clazz == SQLSelectQueryBlock.class) {\n            visit((SQLSelectQueryBlock) x);\n        } else if (clazz == SQLUnionQuery.class) {\n            visit((SQLUnionQuery) x);\n        } else {\n            x.accept(this);\n        }\n    }\n\n    protected final void printExpr(SQLExpr x) {\n        printExpr(x, parameterized);\n    }\n\n    protected final void printExpr(SQLExpr x, boolean parameterized) {\n        Class<?> clazz = x.getClass();\n        if (clazz == SQLIdentifierExpr.class) {\n            visit((SQLIdentifierExpr) x);\n        } else if (clazz == SQLPropertyExpr.class) {\n            visit((SQLPropertyExpr) x);\n        } else if (clazz == SQLAllColumnExpr.class) {\n            visit((SQLAllColumnExpr) x);\n        } else if (clazz == SQLAggregateExpr.class) {\n            visit((SQLAggregateExpr) x);\n        } else if (clazz == SQLBinaryOpExpr.class) {\n            visit((SQLBinaryOpExpr) x);\n        } else if (clazz == SQLCharExpr.class) {\n            visit((SQLCharExpr) x, parameterized);\n        } else if (clazz == SQLNullExpr.class) {\n            visit((SQLNullExpr) x);\n        } else if (clazz == SQLIntegerExpr.class) {\n            printInteger((SQLIntegerExpr) x, parameterized);\n        } else if (clazz == SQLNumberExpr.class) {\n            visit((SQLNumberExpr) x);\n        } else if (clazz == SQLMethodInvokeExpr.class) {\n            visit((SQLMethodInvokeExpr) x);\n        } else if (clazz == SQLVariantRefExpr.class) {\n            visit((SQLVariantRefExpr) x);\n        } else if (clazz == SQLBinaryOpExprGroup.class) {\n            visit((SQLBinaryOpExprGroup) x);\n        } else if (clazz == SQLCaseExpr.class) {\n            visit((SQLCaseExpr) x);\n        } else if (clazz == SQLInListExpr.class) {\n            visit((SQLInListExpr) x);\n        } else if (clazz == SQLNotExpr.class) {\n            visit((SQLNotExpr) x);\n        } else {\n            x.accept(this);\n        }\n    }\n    public boolean visit(SQLCaseExpr x) {\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        this.indentCount++;\n        print0(ucase ? \"CASE\" : \"case\");\n\n        SQLExpr valueExpr = x.getValueExpr();\n        if (valueExpr != null) {\n            print(' ');\n            printExpr(valueExpr, parameterized);\n        }\n\n        List<SQLCaseExpr.Item> items = x.getItems();\n        for (int i = 0, size = items.size(); i < size; ++i) {\n            println();\n            visit(items.get(i));\n        }\n\n        SQLExpr elExpr = x.getElseExpr();\n        if (elExpr != null) {\n            println();\n            print0(ucase ? \"ELSE \" : \"else \");\n            if (elExpr instanceof SQLCaseExpr) {\n                this.indentCount++;\n                println();\n                visit((SQLCaseExpr) elExpr);\n                this.indentCount--;\n            } else {\n                printExpr(elExpr, parameterized);\n            }\n        }\n\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END\" : \"end\");\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        return false;\n    }\n\n    public boolean visit(SQLCaseExpr.Item x) {\n        print0(ucase ? \"WHEN \" : \"when \");\n        SQLExpr conditionExpr = x.getConditionExpr();\n        int lines = this.lines;\n        this.indentCount++;\n        printExpr(conditionExpr, parameterized);\n        this.indentCount--;\n\n        boolean println = lines != this.lines;\n        if (isPrettyFormat() && !println) {\n            List<String> afterComments = conditionExpr.getAfterCommentsDirect();\n            if (afterComments != null && !afterComments.isEmpty()) {\n                println = true;\n            }\n        }\n\n        if (println) {\n            println();\n        } else {\n            print(' ');\n        }\n\n        print0(ucase ? \"THEN \" : \"then \");\n        SQLExpr valueExpr = x.getValueExpr();\n        if (valueExpr instanceof SQLCaseExpr) {\n            this.indentCount++;\n            println();\n            visit((SQLCaseExpr) valueExpr);\n            this.indentCount--;\n        } else {\n            this.indentCount++;\n            printExpr(valueExpr, parameterized);\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCaseStatement x) {\n        print0(ucase ? \"CASE\" : \"case\");\n        SQLExpr valueExpr = x.getValueExpr();\n        if (valueExpr != null) {\n            print(' ');\n            printExpr(valueExpr, parameterized);\n        }\n        this.indentCount++;\n        println();\n        printlnAndAccept(x.getItems(), \" \");\n\n        if (x.getElseStatements().size() > 0) {\n            println();\n            print0(ucase ? \"ELSE \" : \"else \");\n            printlnAndAccept(x.getElseStatements(), \"\");\n        }\n\n        this.indentCount--;\n\n        println();\n        print0(ucase ? \"END CASE\" : \"end case\");\n        if (DbType.oracle == dbType) {\n            print(';');\n        }\n        return false;\n    }\n\n    public boolean visit(SQLCaseStatement.Item x) {\n        print0(ucase ? \"WHEN \" : \"when \");\n        printExpr(x.getConditionExpr(), parameterized);\n        print0(ucase ? \" THEN \" : \" then \");\n\n        SQLStatement stmt = x.getStatement();\n        if (stmt != null) {\n            stmt.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLGetDiagnosticsStatement x) {\n        print(ucase ? \"GET DIAGNOSTICS \" : \"get diagnostics \");\n\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLCastExpr x) {\n        tryPrintLparen(x);\n        if (x.isTry()) {\n            print0(ucase ? \"TRY_CAST(\" : \"try_cast(\");\n        } else {\n            print0(ucase ? \"CAST(\" : \"cast(\");\n        }\n        x.getExpr().accept(this);\n        print0(ucase ? \" AS \" : \" as \");\n        x.getDataType().accept(this);\n        print0(\")\");\n        tryPrintRparen(x);\n        return false;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return visit(x, this.parameterized);\n    }\n\n    public boolean visit(SQLCharExpr x, boolean parameterized) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        if (parameterized) {\n            print('?');\n            incrementReplaceCunt();\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            return false;\n        }\n\n        printChars(x.getText());\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    protected void printChars(String text) {\n        if (text == null) {\n            print0(ucase ? \"NULL\" : \"null\");\n        } else {\n            print('\\'');\n            int index = text.indexOf('\\'');\n            if (index >= 0) {\n                text = text.replaceAll(\"'\", \"''\");\n            }\n            print0(text);\n            print('\\'');\n        }\n    }\n\n    public boolean visit(SQLDataType x) {\n        printDataType(x);\n\n        return false;\n    }\n\n    protected void printDataType(SQLDataType x) {\n        boolean parameterized = this.parameterized;\n        this.parameterized = false;\n\n        print0(x.getName());\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.size() > 0) {\n            print('(');\n            for (int i = 0, size = arguments.size(); i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                printExpr(arguments.get(i), false);\n            }\n            print(')');\n        }\n\n        Boolean withTimeZone = x.getWithTimeZone();\n        if (withTimeZone != null) {\n            if (withTimeZone) {\n                if (x.isWithLocalTimeZone()) {\n                    print0(ucase ? \" WITH LOCAL TIME ZONE\" : \" with local time zone\");\n                } else {\n                    print0(ucase ? \" WITH TIME ZONE\" : \" with time zone\");\n                }\n            } else {\n                print0(ucase ? \" WITHOUT TIME ZONE\" : \" without time zone\");\n            }\n        }\n\n        if (x instanceof SQLDataTypeImpl) {\n            SQLExpr indexBy = ((SQLDataTypeImpl) x).getIndexBy();\n            if (indexBy != null) {\n                print0(ucase ? \" INDEX BY \" : \" index by \");\n                indexBy.accept(this);\n            }\n        }\n\n        this.parameterized = parameterized;\n    }\n\n    public boolean visit(SQLCharacterDataType x) {\n        visit((SQLDataType) x);\n\n        List<SQLCommentHint> hints = ((SQLCharacterDataType) x).hints;\n        if (hints != null) {\n            print(' ');\n            for (SQLCommentHint hint : hints) {\n                hint.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLExistsExpr x) {\n        if (x.isNot()) {\n            print0(ucase ? \"NOT EXISTS (\" : \"not exists (\");\n        } else {\n            print0(ucase ? \"EXISTS (\" : \"exists (\");\n        }\n        this.indentCount++;\n        println();\n        visit(x.getSubQuery());\n        this.indentCount--;\n        println();\n        print(')');\n\n        SQLCommentHint hint = x.getHint();\n        if (hint != null) {\n            print(' ');\n            hint.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        String replacedName = x.getName();\n        if (x.getParent() instanceof SQLBinaryOpExpr\n        || x.getParent() instanceof SQLSelectItem) {\n            replacedName = replaceQuota(x.getName());\n        }\n        printName0(replacedName);\n        if (x.getCollate() != null) {\n            String collate = x.getCollate();\n            print(\" COLLATE \");\n            if (collate.startsWith(\"'\") || collate.endsWith(\"\\\"\")) {\n                print(collate);\n            } else {\n                print('\\'');\n                print(collate);\n                print('\\'');\n            }\n        }\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    private boolean printName(SQLName x, String name) {\n        boolean shardingSupport = this.shardingSupport\n                && this.parameterized;\n        return printName(x, name, shardingSupport);\n    }\n\n    public String unwrapShardingTable(String name) {\n        char c0 = name.charAt(0);\n        char c_last = name.charAt(name.length() - 1);\n        final boolean quote = (c0 == '`' && c_last == '`') || (c0 == '\"' && c_last == '\"');\n\n        int end = name.length();\n        if (quote) {\n            end--;\n        }\n\n        int num_cnt = 0, postfixed_cnt = 0;\n        for (int i = end - 1; i > 0; --i, postfixed_cnt++) {\n            char ch = name.charAt(i);\n            if (ch >= '0' && ch <= '9') {\n                num_cnt++;\n            }\n\n            if (ch != '_' && (ch < '0' || ch > '9')) {\n                break;\n            }\n        }\n        if (num_cnt < 1 || postfixed_cnt < 2) {\n            return name;\n        }\n\n        int start = end - postfixed_cnt;\n        if (start < 1) {\n            return name;\n        }\n\n        String realName = name.substring(quote ? 1 : 0, start);\n        return realName;\n    }\n\n    private boolean printName(SQLName x, String name, boolean shardingSupport) {\n        if (shardingSupport) {\n            SQLObject parent = x.getParent();\n            shardingSupport = parent instanceof SQLExprTableSource || parent instanceof SQLPropertyExpr;\n\n            if (parent instanceof SQLPropertyExpr && parent.getParent() instanceof SQLExprTableSource) {\n                shardingSupport = false;\n            }\n        }\n\n        if (shardingSupport) {\n            final boolean quote = name.charAt(0) == '`' && name.charAt(name.length() - 1) == '`';\n\n            String unwrappedName = unwrapShardingTable(name);\n            if (unwrappedName != name) {\n                boolean isAlias = false;\n                for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n                    if (parent instanceof SQLSelectQueryBlock) {\n                        SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom();\n                        if (quote) {\n                            String name2 = name.substring(1, name.length() - 1);\n                            if (isTableSourceAlias(from, name, name2)) {\n                                isAlias = true;\n                            }\n                        } else {\n                            if (isTableSourceAlias(from, name)) {\n                                isAlias = true;\n                            }\n                        }\n                        break;\n                    }\n                }\n\n                if (!isAlias) {\n                    print0(unwrappedName);\n                    incrementReplaceCunt();\n                    return false;\n                } else {\n                    printName0(name);\n                    return false;\n                }\n            }\n        }\n\n        printName0(name);\n        return false;\n    }\n\n    public boolean visit(SQLInListExpr x) {\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        final SQLExpr expr = x.getExpr();\n\n        boolean quote = false;\n        if (expr instanceof SQLBinaryOpExpr) {\n            SQLBinaryOperator operator = ((SQLBinaryOpExpr) expr).getOperator();\n            switch (operator) {\n                case BooleanAnd:\n                case BooleanOr:\n                case BooleanXor:\n                case Assignment:\n                    quote = true;\n                    break;\n                default:\n                    quote = false;\n                    break;\n            }\n        } else if (expr instanceof SQLNotExpr\n                || expr instanceof SQLBetweenExpr\n                || expr instanceof SQLInListExpr\n                || expr instanceof SQLUnaryExpr\n                || expr instanceof SQLBinaryOpExprGroup) {\n            quote = true;\n        }\n\n        if (this.parameterized) {\n            List<SQLExpr> targetList = x.getTargetList();\n\n            boolean allLiteral = true;\n            for (SQLExpr item : targetList) {\n                if (!((item instanceof SQLUnaryExpr && ((SQLUnaryExpr) item).getExpr() instanceof SQLLiteralExpr) || item instanceof SQLLiteralExpr\n                    || item instanceof SQLVariantRefExpr)) {\n                    if (item instanceof SQLListExpr) {\n                        SQLListExpr list = (SQLListExpr) item;\n                        for (SQLExpr listItem : list.getItems()) {\n                            if (!(listItem instanceof SQLLiteralExpr\n                                    || listItem instanceof SQLVariantRefExpr)) {\n                                allLiteral = false;\n                                break;\n                            }\n                        }\n                        if (allLiteral) {\n                            break;\n                        }\n                        continue;\n                    }\n                    allLiteral = false;\n                    break;\n                }\n            }\n\n            if (allLiteral) {\n                boolean changed = true;\n                if (targetList.size() == 1 && targetList.get(0) instanceof SQLVariantRefExpr) {\n                    changed = false;\n                }\n\n                if (quote) {\n                    print('(');\n                }\n                printExpr(expr, parameterized);\n                if (quote) {\n                    print(')');\n                }\n\n                if (x.isNot()) {\n                    print(ucase ? \" NOT IN\" : \" not in\");\n                } else {\n                    print(ucase ? \" IN\" : \" in\");\n                }\n\n                if ((!parameterizedQuesUnMergeInList) || (targetList.size() == 1 && !(targetList.get(0) instanceof SQLListExpr))) {\n//                    if (parameters != null) {\n//                        print(\" (\");\n//                        for (int i = 0; i < targetList.size(); i++) {\n//                            if(i != 0) {\n//                                print(\", \");\n//                            }\n//                            SQLExpr item = targetList.get(i);\n//                            printExpr(item);\n//                        }\n//                        print(')');\n//                        return false;\n//                    } else {\n//\n//                    }\n                    print(\" (?)\");\n                } else {\n                    print(\" (\");\n                    for (int i = 0; i < targetList.size(); i++) {\n                        if (i != 0) {\n                            print(\", \");\n                        }\n                        SQLExpr item = targetList.get(i);\n                        if (item instanceof SQLListExpr) {\n                            visit((SQLListExpr) item);\n                            changed = false;\n                        } else {\n                            print(\"?\");\n                        }\n                    }\n                    print(\")\");\n                }\n\n                if (changed) {\n                    incrementReplaceCunt();\n                    if (this.parameters != null) {\n                        if (parameterizedMergeInList) {\n                            List<Object> subList = new ArrayList<Object>(x.getTargetList().size());\n                            for (SQLExpr target : x.getTargetList()) {\n                                ExportParameterVisitorUtils.exportParameter(subList, target);\n                            }\n                            if (subList != null) {\n                                parameters.add(subList);\n                            }\n                        } else {\n                            for (SQLExpr target : x.getTargetList()) {\n                                ExportParameterVisitorUtils.exportParameter(this.parameters, target);\n                            }\n                        }\n                    }\n                }\n\n                if (x.getHint() != null) {\n                    x.getHint().accept(this);\n                }\n                if (x.isParenthesized()) {\n                    print(')');\n                }\n                return false;\n            }\n        }\n\n        //if (quote) {\n            //print('(');\n        //}\n        printExpr(expr, parameterized);\n        //if (quote) {\n            //print(')');\n        //}\n\n        if (x.isNot()) {\n            print0(ucase ? \" NOT IN \" : \" not in \");\n        } else {\n            print0(ucase ? \" IN \" : \" in \");\n        }\n\n        boolean quoteValue = !((x.getParent() instanceof SQLMethodInvokeExpr\n                && ((SQLMethodInvokeExpr) x.getParent()).getArguments().size() == 1)\n                && ((SQLMethodInvokeExpr) x.getParent()).methodNameHashCode64() == FnvHash.Constants.POSITION);\n        if (quoteValue) {\n            print('(');\n        }\n\n        final List<SQLExpr> list = x.getTargetList();\n\n        boolean printLn = false;\n        if (list.size() > 5) {\n            printLn = true;\n            for (int i = 0, size = list.size(); i < size; ++i) {\n                if (!(list.get(i) instanceof SQLCharExpr)) {\n                    printLn = false;\n                    break;\n                }\n            }\n        }\n\n        if (printLn) {\n            this.indentCount++;\n            println();\n            for (int i = 0, size = list.size(); i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                    println();\n                }\n                SQLExpr item = list.get(i);\n                printExpr(item, parameterized);\n            }\n            this.indentCount--;\n            println();\n        } else {\n            List<SQLExpr> targetList = x.getTargetList();\n            for (int i = 0; i < targetList.size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                printExpr(targetList.get(i), parameterized);\n            }\n        }\n\n        if (quoteValue) {\n            print(')');\n        }\n\n        List<String> afterComments = x.getAfterCommentsDirect();\n        if (afterComments != null && !afterComments.isEmpty() && afterComments.get(0).startsWith(\"--\")) {\n            print(' ');\n        }\n        printlnComment(afterComments);\n\n        if (x.getHint() != null) {\n            x.getHint().accept(this);\n        }\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        return false;\n    }\n\n    public boolean visit(SQLContainsExpr x) {\n        SQLExpr expr = x.getExpr();\n        if (expr != null) {\n            printExpr(expr, parameterized);\n            print(' ');\n        }\n\n        if (x.isNot()) {\n            print0(ucase ? \"NOT CONTAINS (\" : \" not contains (\");\n        } else {\n            print0(ucase ? \"CONTAINS (\" : \" contains (\");\n        }\n\n        final List<SQLExpr> list = x.getTargetList();\n\n        boolean printLn = false;\n        if (list.size() > 5) {\n            printLn = true;\n            for (int i = 0, size = list.size(); i < size; ++i) {\n                if (!(list.get(i) instanceof SQLCharExpr)) {\n                    printLn = false;\n                    break;\n                }\n            }\n        }\n\n        if (printLn) {\n            this.indentCount++;\n            println();\n            for (int i = 0, size = list.size(); i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                    println();\n                }\n                SQLExpr item = list.get(i);\n                printExpr(item, parameterized);\n            }\n            this.indentCount--;\n            println();\n        } else {\n            List<SQLExpr> targetList = x.getTargetList();\n            for (int i = 0; i < targetList.size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                printExpr(targetList.get(i), parameterized);\n            }\n        }\n\n        print(')');\n        return false;\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        boolean parameterized = this.parameterized;\n        if (x.isParenthesized() && !parameterized) {\n            print('(');\n        }\n        printInteger(x, parameterized);\n        if (x.isParenthesized() && !parameterized) {\n            print(')');\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    private static final Integer ONE = Integer.valueOf(1);\n\n    protected void printInteger(SQLIntegerExpr x, boolean parameterized) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        Number number = x.getNumber();\n        if (number.equals(ONE)) {\n            if (DbType.oracle.equals(dbType)) {\n                SQLObject parent = x.getParent();\n                if (parent instanceof SQLBinaryOpExpr) {\n                    SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) parent;\n                    SQLExpr left = binaryOpExpr.getLeft();\n                    SQLBinaryOperator op = binaryOpExpr.getOperator();\n                    if (left instanceof SQLIdentifierExpr\n                            && op == SQLBinaryOperator.Equality) {\n                        String name = ((SQLIdentifierExpr) left).getName();\n                        if (\"rownum\".equals(name)) {\n                            print(1);\n                            if (x.hasAfterComment()) {\n                                printAfterComments(x.getAfterCommentsDirect());\n                            }\n                            return;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (parameterized) {\n            if (isEnabled(VisitorFeature.OutputParameterizedUnMergeZero)\n                    && (number instanceof Integer\n                    || number instanceof Long) && number.longValue() == 0) {\n                parameterized = false;\n            }\n            if (isEnabled(VisitorFeature.OutputParameterizedUnMergeOne)\n                    && (number instanceof Integer\n                    || number instanceof Long) && number.longValue() == 1) {\n                parameterized = false;\n            }\n        }\n\n        if (parameterized) {\n            print('?');\n            incrementReplaceCunt();\n\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            if (x.hasAfterComment()) {\n                printAfterComments(x.getAfterCommentsDirect());\n            }\n            return;\n        }\n\n        if (number instanceof BigDecimal || number instanceof BigInteger) {\n            print(number.toString());\n        } else {\n            print(number.longValue());\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n    }\n\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        SQLExpr owner = x.getOwner();\n        if (owner != null) {\n            printMethodOwner(owner);\n        }\n\n        if (parameterized) {\n            List<SQLExpr> arguments = x.getArguments();\n            if (x.methodNameHashCode64() == FnvHash.Constants.TRIM\n                    && arguments.size() == 1\n                    && arguments.get(0) instanceof SQLCharExpr && x.getTrimOption() == null && x.getFrom() == null) {\n                print('?');\n\n                if (parameters != null) {\n                    SQLCharExpr charExpr = (SQLCharExpr) arguments.get(0);\n                    parameters.add(charExpr.getText().trim());\n                }\n\n                replaceCount++;\n                if (x.hasAfterComment()) {\n                    printAfterComments(x.getAfterCommentsDirect());\n                }\n                return false;\n            }\n        }\n\n        String function = x.getMethodName();\n        if (function != null) {\n            printFunctionName(function);\n        }\n        printMethodParameters(x);\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    protected void printMethodParameters(SQLMethodInvokeExpr x, List<SQLExpr> parameters) {\n        String function = x.getMethodName();\n        long nameHashCode64 = x.methodNameHashCode64();\n        if (!x.isRemoveBrackets()) {\n            print('(');\n        }\n\n        String trimOption = x.getTrimOption();\n        if (trimOption != null) {\n            print0(trimOption);\n\n            if (parameters.size() > 0) {\n                print(' ');\n            }\n        }\n        final SQLExpr contentExpr = x.getContent();\n        if (contentExpr != null) {\n            print(contentExpr.toString());\n            print(' ');\n        }\n\n        for (int i = 0, size = parameters.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLExpr param = parameters.get(i);\n\n            if (this.parameterized) {\n                if (size == 2 && i == 1 && param instanceof SQLCharExpr) {\n                    if (DbType.oracle == dbType) {\n                        if (\"TO_CHAR\".equalsIgnoreCase(function)\n                                || \"TO_DATE\".equalsIgnoreCase(function)) {\n                            printChars(((SQLCharExpr) param).getText());\n                            continue;\n                        }\n                    } else if (DbType.mysql == dbType) {\n                        if (\"DATE_FORMAT\".equalsIgnoreCase(function)) {\n                            printChars(((SQLCharExpr) param).getText());\n                            continue;\n                        }\n                    }\n                }\n\n            }\n\n            if (param instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) param;\n                SQLBinaryOperator op = binaryOpExpr.getOperator();\n                if (op == SQLBinaryOperator.BooleanAnd || op == SQLBinaryOperator.BooleanOr) {\n                    this.indentCount++;\n                    printExpr(param, parameterized);\n                    this.indentCount--;\n                    continue;\n                }\n            }\n\n            if (i == 0 && (nameHashCode64 == FnvHash.Constants.TIMESTAMPDIFF || nameHashCode64 == FnvHash.Constants.TIMESTAMPADD)\n                    && param instanceof SQLIdentifierExpr) {\n                if (DbType.mysql == dbType) {\n                    print(((SQLIdentifierExpr) param).getName());\n                    continue;\n                }\n            }\n\n            printExpr(param, parameterized);\n        }\n    }\n    protected void printMethodParameters(SQLMethodInvokeExpr x) {\n        List<SQLExpr> parameters = x.getArguments();\n\n        printMethodParameters(x, parameters);\n        if (x instanceof SQLParametricMethodInvokeExpr) {\n            print(')');\n            printMethodParameters(x, ((SQLParametricMethodInvokeExpr) x).getSecondArguments());\n        }\n\n        SQLExpr from = x.getFrom();\n        if (from != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            printExpr(from, parameterized);\n\n            SQLExpr _for = x.getFor();\n            if (_for != null) {\n                print0(ucase ? \" FOR \" : \" for \");\n                printExpr(_for, parameterized);\n            }\n        }\n\n        SQLExpr using = x.getUsing();\n\n        boolean odpsTransformUsing = false;\n        if (using != null) {\n            odpsTransformUsing = x.methodNameHashCode64() == FnvHash.Constants.TRANSFORM;\n            if (!odpsTransformUsing) {\n                print0(ucase ? \" USING \" : \" using \");\n                printExpr(using, parameterized);\n            }\n        }\n\n        if (x.methodNameHashCode64() == FnvHash.Constants.WEIGHT_STRING) {\n            SQLDataType as = (SQLDataType) x.getAttribute(\"as\");\n            if (as != null) {\n                print0(ucase ? \" AS \" : \" as \");\n                as.accept(this);\n            }\n\n            List<SQLSelectOrderByItem> levels = (List<SQLSelectOrderByItem>) x.getAttribute(\"levels\");\n            if (levels != null && levels.size() > 0) {\n                print0(ucase ? \" LEVEL \" : \" level \");\n                printAndAccept(levels, \", \");\n            }\n\n            Boolean reverse = (Boolean) x.getAttribute(\"reverse\");\n            if (reverse != null) {\n                print0(ucase ? \" REVERSE\" : \" reverse\");\n            }\n        }\n\n        final SQLExpr asExpr = x.getAs();\n        if (asExpr != null) {\n            print(\" as \");\n            print(asExpr.toString());\n        }\n        if (!x.isRemoveBrackets()) {\n            print(')');\n        }\n\n        if (odpsTransformUsing) {\n            print0(ucase ? \" USING \" : \" using \");\n            printExpr(using, parameterized);\n        }\n    }\n\n    protected void printMethodOwner(SQLExpr owner) {\n        printExpr(owner, parameterized);\n        print('.');\n    }\n\n    protected void printFunctionName(String name) {\n        printName0(name, false);\n    }\n\n    public boolean visit(SQLAggregateExpr x) {\n        boolean parameterized = this.parameterized;\n        if (x.methodNameHashCode64() == FnvHash.Constants.GROUP_CONCAT) {\n            this.parameterized = false;\n        }\n        if (x.methodNameHashCode64() == FnvHash.Constants.COUNT) {\n            List<SQLExpr> arguments = x.getArguments();\n            if (arguments.size() == 1) {\n                SQLExpr arg0 = arguments.get(0);\n                if (arg0 instanceof SQLLiteralExpr) {\n                    this.parameterized = false;\n                }\n            }\n        }\n\n        if (x.getOwner() != null) {\n            printExpr(x.getOwner());\n            print(\".\");\n        }\n\n        String methodName = x.getMethodName();\n        print0(ucase ? methodName : methodName.toLowerCase());\n        print('(');\n\n        SQLAggregateOption option = x.getOption();\n        if (option != null) {\n            print0(option.toString());\n            print(' ');\n        }\n\n        List<SQLExpr> arguments = x.getArguments();\n        for (int i = 0, size = arguments.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            printExpr(arguments.get(i), false);\n        }\n\n        visitAggregateRest(x);\n\n        print(')');\n\n        if (x.isIgnoreNulls()) {\n            print0(ucase ? \" IGNORE NULLS\" : \" ignore nulls\");\n        }\n\n        SQLKeep keep = x.getKeep();\n        if (keep != null) {\n            print(' ');\n            visit(keep);\n        }\n\n        final SQLExpr filter = x.getFilter();\n        if (filter != null) {\n            print0(ucase ? \" FILTER (WHERE \" : \" filter (where \");\n            printExpr(filter);\n            print(')');\n        }\n\n        SQLOver over = x.getOver();\n        if (over != null) {\n            print0(ucase ? \" OVER \" : \" over \");\n            over.accept(this);\n        }\n\n        final SQLName overRef = x.getOverRef();\n        if (overRef != null) {\n            print0(ucase ? \" OVER \" : \" over \");\n            overRef.accept(this);\n        }\n\n        this.parameterized = parameterized;\n        return false;\n    }\n\n    protected void visitAggregateRest(SQLAggregateExpr x) {\n        boolean withGroup = x.isWithinGroup();\n        if (withGroup) {\n            print0(ucase ? \") WITHIN GROUP (\" : \") within group (\");\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            if (!x.isWithinGroup()) {\n                print(' ');\n            }\n            orderBy.accept(this);\n        }\n        SQLExpr limit = x.getLimit();\n        if (limit != null) {\n            print0(ucase ? \" LIMIT \" : \" limit \");\n            limit.accept(this);\n        }\n    }\n\n    public boolean visit(SQLAllColumnExpr x) {\n        SQLExpr owner = x.getOwner();\n        if (owner != null) {\n            printExpr(owner);\n            print('.');\n        }\n\n        print('*');\n\n        List<SQLExpr> except = x.getExcept();\n        if (except != null) {\n            print(ucase ? \" EXCEPT(\" : \"except(\");\n            printAndAccept(except, \", \");\n            print(')');\n        }\n\n        List<SQLAliasedExpr> replace = x.getReplace();\n        if (!replace.isEmpty()) {\n            print(ucase ? \" REPLACE(\" : \"replace(\");\n            printAndAccept(replace, \", \");\n            print(')');\n        }\n\n        return true;\n    }\n\n    public boolean visit(SQLNCharExpr x) {\n        if (this.parameterized) {\n            print('?');\n            incrementReplaceCunt();\n\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            return false;\n        }\n\n        if ((x.getText() == null) || (x.getText().length() == 0)) {\n            print0(ucase ? \"NULL\" : \"null\");\n        } else {\n            print0(ucase ? \"N'\" : \"n'\");\n            print0(x.getText().replace(\"'\", \"''\"));\n            print('\\'');\n        }\n        return false;\n    }\n\n    public boolean visit(SQLNotExpr x) {\n        print0(ucase ? \"NOT \" : \"not \");\n        SQLExpr expr = x.getExpr();\n\n        boolean needParentheses = false;\n\n        if (expr instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr;\n            needParentheses = binaryOpExpr.getOperator().isLogical();\n            if (binaryOpExpr.isParenthesized()) {\n                needParentheses = false;\n            }\n        } else if (expr instanceof SQLInListExpr || expr instanceof SQLNotExpr\n                || expr instanceof SQLBinaryOpExprGroup || expr instanceof SQLQueryExpr) {\n            needParentheses = true;\n        }\n\n        if (needParentheses) {\n            print('(');\n        }\n        printExpr(expr, parameterized);\n\n        if (needParentheses) {\n            print(')');\n        }\n\n        SQLCommentHint hint = x.getHint();\n        if (hint != null) {\n            hint.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLNullExpr x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        SQLObject parent = x.getParent();\n        if (this.parameterized\n                && (parent instanceof ValuesClause || parent instanceof SQLInListExpr ||\n                (parent instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) parent).getOperator() == SQLBinaryOperator.Equality))) {\n            print('?');\n            incrementReplaceCunt();\n\n            if (this.parameters != null) {\n                if (parent instanceof SQLBinaryOpExpr) {\n                    ExportParameterVisitorUtils.exportParameter((this).getParameters(), x);\n                } else {\n                    this.getParameters().add(null);\n                }\n            }\n            if (x.hasAfterComment()) {\n                printAfterComments(x.getAfterCommentsDirect());\n            }\n            return false;\n        }\n\n        print0(ucase ? \"NULL\" : \"null\");\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        if (this.parameterized) {\n            print('?');\n            incrementReplaceCunt();\n\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter((this).getParameters(), x);\n            }\n            return false;\n        }\n\n        x.output(appender);\n        return false;\n    }\n\n    public boolean visit(SQLPropertyExpr x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        SQLExpr owner = x.getOwner();\n\n        String mapTableName = null, ownerName = null;\n        if (owner instanceof SQLIdentifierExpr) {\n            ownerName = ((SQLIdentifierExpr) owner).getName();\n            if (tableMapping != null) {\n                mapTableName = tableMapping.get(ownerName);\n\n                if (mapTableName == null\n                        && ownerName.length() > 2\n                        && ownerName.charAt(0) == '`'\n                        && ownerName.charAt(ownerName.length() - 1) == '`') {\n                    ownerName = ownerName.substring(1, ownerName.length() - 1);\n                    mapTableName = tableMapping.get(ownerName);\n                }\n            }\n        }\n\n        if (mapTableName != null) {\n            for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n                if (parent instanceof SQLSelectQueryBlock) {\n                    SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom();\n                    if (isTableSourceAlias(from, mapTableName, ownerName)) {\n                        mapTableName = null;\n                    }\n                    break;\n                }\n            }\n        }\n\n        if (mapTableName != null) {\n            printName0(mapTableName);\n        } else {\n            if (owner instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr ownerIdent = (SQLIdentifierExpr) owner;\n                printName(\n                        ownerIdent,\n                        replaceQuota(ownerIdent.getName()),\n                        this.shardingSupport && this.parameterized\n                );\n            } else if (owner != null) {\n                printExpr(owner, parameterized);\n            }\n        }\n        if (x.getSplitString() != null) {\n            print(x.getSplitString());\n        } else {\n            print('.');\n        }\n        String name = replaceQuota(x.getName());\n        if (\"*\".equals(name)) {\n            print0(name);\n        } else {\n            printName0(name);\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    protected boolean isTableSourceAlias(SQLTableSource from, String... tableNames) {\n        String alias = from.getAlias();\n\n        if (alias != null) {\n            for (String tableName : tableNames) {\n                if (alias.equalsIgnoreCase(tableName)) {\n                    return true;\n                }\n            }\n\n            if (alias.length() > 2 && alias.charAt(0) == '`' && alias.charAt(alias.length() - 1) == '`') {\n                alias = alias.substring(1, alias.length() - 1);\n                for (String tableName : tableNames) {\n                    if (alias.equalsIgnoreCase(tableName)) {\n                        return true;\n                    }\n                }\n            }\n        }\n        if (from instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) from;\n            return isTableSourceAlias(join.getLeft(), tableNames)\n                    || isTableSourceAlias(join.getRight(), tableNames);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLQueryExpr x) {\n        SQLObject parent = x.getParent();\n        if (parent instanceof SQLSelect) {\n            parent = parent.getParent();\n        }\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        SQLSelect subQuery = x.getSubQuery();\n        if (parent instanceof ValuesClause) {\n            println();\n            visit(subQuery);\n            println();\n        } else if ((parent instanceof SQLStatement\n                && !(parent instanceof OracleForStatement))\n                || (parent instanceof SQLSelectItem\n                && (parent.getParent() instanceof SQLPivot || parent.getParent() instanceof SQLUnpivot))\n        ) {\n            this.indentCount++;\n\n            println();\n            visit(subQuery);\n\n            this.indentCount--;\n        } else if (parent instanceof SQLOpenStatement) {\n            visit(subQuery);\n        } else if (parent instanceof SQLMethodInvokeExpr\n                && ((SQLMethodInvokeExpr) parent).getArguments().size() == 1\n                && (((SQLMethodInvokeExpr) parent).methodNameHashCode64() == FnvHash.Constants.LATERAL\n                || ((SQLMethodInvokeExpr) parent).methodNameHashCode64() == FnvHash.Constants.ARRAY)\n        ) {\n            this.indentCount++;\n            println();\n            visit(subQuery);\n            this.indentCount--;\n            println();\n        } else if (parent instanceof SQLMethodInvokeExpr && ((SQLMethodInvokeExpr) parent).getArguments().size() == 1) {\n            this.indentCount++;\n            println();\n            visit(subQuery);\n            this.indentCount--;\n            println();\n        } else {\n            this.indentCount++;\n            println();\n            visit(subQuery);\n            this.indentCount--;\n            println();\n        }\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        return false;\n    }\n\n    protected boolean legacyCube() {\n        return dbType == DbType.oracle;\n    }\n\n    public boolean visit(SQLSelectGroupByClause x) {\n        boolean paren = legacyCube() || x.isParen();\n        boolean rollup = x.isWithRollUp();\n        boolean cube = x.isWithCube();\n\n        List<SQLExpr> items = x.getItems();\n        int itemSize = items.size();\n        if (itemSize > 0) {\n            print0(ucase ? \"GROUP BY \" : \"group by \");\n\n            if (x.isDistinct()) {\n                print0(ucase ? \"DISTINCT \" : \"distinct \");\n            }\n\n            if (paren && rollup) {\n                print0(ucase ? \"ROLLUP (\" : \"rollup (\");\n            } else if (paren && cube) {\n                print0(ucase ? \"CUBE (\" : \"cube (\");\n            }\n            this.indentCount++;\n            for (int i = 0; i < itemSize; ++i) {\n                SQLExpr item = items.get(i);\n                if (isPrettyFormat() && item.hasBeforeComment()) {\n                    if (i != 0) {\n                        print(' ');\n                    }\n                    printlnComments(item.getBeforeCommentsDirect());\n                }\n\n                if (i != 0) {\n                    if (groupItemSingleLine) {\n                        if (item instanceof SQLGroupingSetExpr) {\n                            if (!item.hasBeforeComment()) {\n                                println();\n                            }\n                        } else {\n                            println(',');\n                        }\n                    } else {\n                        if (item instanceof SQLGroupingSetExpr) {\n                            println();\n                        } else {\n                            print(\", \");\n                        }\n                    }\n                }\n                if (item instanceof SQLIntegerExpr) {\n                    printInteger((SQLIntegerExpr) item, false);\n                } else if (item instanceof MySqlOrderingExpr && ((MySqlOrderingExpr) item).getExpr() instanceof SQLIntegerExpr) {\n                    MySqlOrderingExpr orderingExpr = (MySqlOrderingExpr) item;\n                    printInteger((SQLIntegerExpr) orderingExpr.getExpr(), false);\n                    print(' ' + orderingExpr.getType().name);\n                } else {\n                    item.accept(this);\n                    if (i != itemSize - 1 && item.hasAfterComment()) {\n                        // 如果下一项是 SQLGroupingSetExpr，则不打印换行，因为后续会自动打印\n                        if (i + 1 < itemSize && items.get(i + 1) instanceof SQLGroupingSetExpr) {\n                            // 不打印换行，避免出现空行\n                        } else {\n                            println();\n                        }\n                    }\n                }\n\n                SQLCommentHint hint = null;\n                if (item instanceof SQLExprImpl) {\n                    hint = ((SQLExprImpl) item).getHint();\n                }\n                if (hint != null) {\n                    hint.accept(this);\n                }\n            }\n            if (paren && (rollup || cube)) {\n                print(')');\n            }\n            this.indentCount--;\n        }\n\n        SQLExpr having = x.getHaving();\n        if (having != null) {\n            printHaving(having);\n        }\n\n        if (x.isWithRollUp() && !paren) {\n            print0(ucase ? \" WITH ROLLUP\" : \" with rollup\");\n        }\n\n        if (x.isWithCube() && !paren) {\n            print0(ucase ? \" WITH CUBE\" : \" with cube\");\n        }\n\n        return false;\n    }\n\n    protected void printHaving(SQLExpr having) {\n        println();\n        print0(ucase ? \"HAVING \" : \"having \");\n        having.accept(this);\n    }\n\n    public boolean visit(SQLSelect x) {\n        SQLHint headHint = x.getHeadHint();\n        if (headHint != null) {\n            headHint.accept(this);\n            println();\n        }\n\n        SQLWithSubqueryClause withSubQuery = x.getWithSubQuery();\n        if (withSubQuery != null) {\n            withSubQuery.accept(this);\n            println();\n        }\n\n        printQuery(x.getQuery());\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            orderBy.accept(this);\n        }\n\n        final SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            println();\n            limit.accept(this);\n        }\n\n        if (x.getHintsSize() > 0) {\n            printAndAccept(x.getHints(), \"\");\n        }\n\n        return false;\n    }\n\n    protected void printSelectListBefore(SQLSelectQueryBlock x) {\n        print(' ');\n    }\n\n    public void printSqlSetQuantifier(SQLSelectQueryBlock x) {\n        final int distinctOption = x.getDistionOption();\n        if (SQLSetQuantifier.ALL == distinctOption) {\n            print0(ucase ? \"ALL \" : \"all \");\n        } else if (SQLSetQuantifier.DISTINCT == distinctOption) {\n            print0(ucase ? \"DISTINCT \" : \"distinct \");\n        } else if (SQLSetQuantifier.UNIQUE == distinctOption) {\n            print0(ucase ? \"UNIQUE \" : \"unique \");\n        }\n    }\n\n    public void printTop(SQLSelectQueryBlock x) {\n    }\n    public boolean visit(SQLSelectQueryBlock x) {\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        if (isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            with.accept(this);\n            println();\n        }\n\n        print0(ucase ? \"SELECT\" : \"select\");\n\n        if (x.getHintsSize() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        printTop(x);\n        printSelectListBefore(x);\n        printSqlSetQuantifier(x);\n\n        printSelectList(\n                x.getSelectList());\n\n        printInto(x);\n        printFrom(x);\n        printWhere(x);\n\n        printHierarchical(x);\n\n        printGroupBy(x);\n\n        printQualify(x);\n        printWindow(x);\n\n        printOrderBy(x);\n\n        final List<SQLSelectOrderByItem> distributeBy = x.getDistributeByDirect();\n        if (distributeBy != null && distributeBy.size() > 0) {\n            println();\n            print0(ucase ? \"DISTRIBUTE BY \" : \"distribute by \");\n            printAndAccept(distributeBy, \", \");\n        }\n\n        List<SQLSelectOrderByItem> sortBy = x.getSortByDirect();\n        if (sortBy != null && sortBy.size() > 0) {\n            println();\n            print0(ucase ? \"SORT BY \" : \"sort by \");\n            printAndAccept(sortBy, \", \");\n        }\n\n        final List<SQLSelectOrderByItem> clusterBy = x.getClusterByDirect();\n        if (clusterBy != null && clusterBy.size() > 0) {\n            println();\n            print0(ucase ? \"CLUSTER BY \" : \"cluster by \");\n            printAndAccept(clusterBy, \", \");\n        }\n\n        printFetchFirst(x);\n        printAfterFetch(x);\n\n        if (x.isForUpdate()) {\n            println();\n            print0(ucase ? \"FOR UPDATE\" : \"for update\");\n        }\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        return false;\n    }\n\n    protected void printInto(SQLSelectQueryBlock x) {\n        SQLExprTableSource into = x.getInto();\n        if (into != null) {\n            println();\n            print0(ucase ? \"INTO \" : \"into \");\n            into.accept(this);\n        }\n    }\n\n    protected void printQualify(SQLSelectQueryBlock x) {\n        SQLExpr qualify = x.getQualify();\n        if (qualify == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"QUALIFY \" : \"qualify \");\n        qualify.accept(this);\n    }\n\n    protected void printOrderBy(SQLSelectQueryBlock x) {\n        SQLOrderBy orderBy = x.getOrderBy();\n        printOrderBy(orderBy);\n    }\n\n    protected void printOrderBy(SQLOrderBy orderBy) {\n        if (orderBy == null) {\n            return;\n        }\n        println();\n        orderBy.accept(this);\n    }\n\n    protected void printFrom(SQLSelectQueryBlock x) {\n        SQLTableSource from = x.getFrom();\n        if (from == null) {\n            return;\n        }\n\n        println();\n        boolean printFrom = from instanceof SQLLateralViewTableSource\n                && ((SQLLateralViewTableSource) from).getTableSource() == null;\n        if (!printFrom) {\n            print0(ucase ? \"FROM \" : \"from \");\n            if (x.getCommentsAfterFrom() != null) {\n                printAfterComments(x.getCommentsAfterFrom());\n                println();\n            }\n        }\n        printTableSource(from);\n    }\n\n    protected void printGroupBy(SQLSelectQueryBlock x) {\n        SQLSelectGroupByClause groupBy = x.getGroupBy();\n        if (groupBy == null) {\n            return;\n        }\n        println();\n        visit(groupBy);\n    }\n\n    protected void printLimit(SQLSelectQueryBlock x) {\n        SQLLimit limit = x.getLimit();\n        if (limit == null) {\n            return;\n        }\n        println();\n        limit.accept(this);\n    }\n\n    protected void printWindow(SQLSelectQueryBlock x) {\n        List<SQLWindow> windows = x.getWindows();\n        if (windows == null || windows.isEmpty()) {\n            return;\n        }\n        println();\n        print0(ucase ? \"WINDOW \" : \"window \");\n        printAndAccept(windows, \", \");\n    }\n\n    protected void printWhere(SQLSelectQueryBlock queryBlock) {\n        SQLExpr where = queryBlock.getWhere();\n        if (where == null) {\n            return;\n        }\n\n        println();\n        print0(ucase ? \"WHERE \" : \"where \");\n\n        List<String> beforeComments = where.getBeforeCommentsDirect();\n        if (beforeComments != null && !beforeComments.isEmpty() && isPrettyFormat()) {\n            printlnComments(beforeComments);\n        }\n        printExpr(where, parameterized);\n    }\n\n    protected void printAfterFetch(SQLSelectQueryBlock x) {}\n    protected void printFetchFirst(SQLSelectQueryBlock x) {\n        SQLLimit limit = x.getLimit();\n        if (limit == null) {\n            return;\n        }\n\n        SQLExpr offset = limit.getOffset();\n        SQLExpr first = limit.getRowCount();\n\n        if (DbType.db2 == dbType\n                || DbType.oracle == dbType\n                || DbType.sqlserver == dbType\n        ) {\n            //order by 语句必须在FETCH FIRST ROWS ONLY之前\n            SQLObject parent = x.getParent();\n            if (parent instanceof SQLSelect) {\n                SQLOrderBy orderBy = ((SQLSelect) parent).getOrderBy();\n                if (orderBy != null && orderBy.getItems().size() > 0) {\n                    println();\n                    print0(ucase ? \"ORDER BY \" : \"order by \");\n                    printAndAccept(orderBy.getItems(), \", \");\n                }\n            }\n\n            println();\n\n            if (offset != null) {\n                print0(ucase ? \"OFFSET \" : \"offset \");\n                offset.accept(this);\n                print0(ucase ? \" ROWS\" : \" rows\");\n            }\n\n            if (first != null) {\n                if (offset != null) {\n                    print(' ');\n                }\n                if (DbType.sqlserver == dbType && offset != null) {\n                    print0(ucase ? \"FETCH NEXT \" : \"fetch next \");\n                } else {\n                    print0(ucase ? \"FETCH FIRST \" : \"fetch first \");\n                }\n                first.accept(this);\n                print0(ucase ? \" ROWS ONLY\" : \" rows only\");\n            }\n        } else {\n            printLimit(x);\n        }\n    }\n\n    public boolean visit(SQLStructExpr x) {\n        SQLStructDataType dataType = x.getDataType();\n        if (dataType != null) {\n            dataType.accept(this);\n            print('(');\n        } else {\n            print0(ucase ? \"STRUCT(\" : \"struct(\");\n        }\n        printlnAndAccept(\n                x.getItems(),\n                needPrintLine(x));\n        print(')');\n        return false;\n    }\n\n    protected boolean needPrintLine(SQLStructExpr x) {\n        List<SQLAliasedExpr> fields = x.getItems();\n        boolean needPrintLine = false;\n        if (fields.size() > 5) {\n            needPrintLine = true;\n        } else {\n            for (SQLAliasedExpr field : fields) {\n                SQLExpr fieldDataType = field.getExpr();\n                if (fieldDataType instanceof SQLArrayDataType || fieldDataType instanceof SQLStructExpr) {\n                    needPrintLine = true;\n                    break;\n                }\n            }\n        }\n        return needPrintLine;\n    }\n\n    public boolean visit(SQLAliasedExpr x) {\n        SQLExpr expr = x.getExpr();\n        if (expr == null) {\n            return false;\n        }\n        expr.accept(this);\n\n        String alias = x.getAlias();\n        if (alias != null && alias.length() > 0) {\n            printExprAlias(alias);\n\n            return false;\n        }\n        return false;\n    }\n\n    public boolean visit(SQLSelectItem x) {\n        if (x.isConnectByRoot()) {\n            print0(ucase ? \"CONNECT_BY_ROOT \" : \"connect_by_root \");\n        }\n\n        SQLExpr expr = x.getExpr();\n\n        if (expr instanceof SQLIdentifierExpr) {\n            String name = replaceQuota(((SQLIdentifierExpr) expr).getName());\n            printName0(name);\n        } else if (expr instanceof SQLPropertyExpr) {\n            visit((SQLPropertyExpr) expr);\n        } else if (expr != null) {\n            printExpr(expr, parameterized);\n        }\n\n        String alias = x.getAlias();\n        if (alias != null && alias.length() > 0) {\n            printExprAlias(alias);\n\n            return false;\n        }\n\n        List<String> aliasList = x.getAliasList();\n        if (aliasList == null) {\n            return false;\n        }\n\n        println();\n        print0(ucase ? \"AS (\" : \"as (\");\n\n        int aliasSize = aliasList.size();\n        if (aliasSize > 5) {\n            this.indentCount++;\n            println();\n        }\n\n        for (int i = 0; i < aliasSize; ++i) {\n            if (i != 0) {\n                if (aliasSize > 5) {\n                    println(\",\");\n                } else {\n                    print0(\", \");\n                }\n            }\n            printAlias0(aliasList.get(i));\n        }\n\n        if (aliasSize > 5) {\n            this.indentCount--;\n            println();\n        }\n        print(')');\n\n        return false;\n    }\n\n    protected void printExprAlias(String alias) {\n        alias = replaceQuota(alias);\n        print0(ucase ? \" AS \" : \" as \");\n        printAlias0(alias);\n    }\n\n    public boolean visit(SQLOrderBy x) {\n        List<SQLSelectOrderByItem> items = x.getItems();\n\n        if (items.size() > 0) {\n            if (x.isSiblings()) {\n                print0(ucase ? \"ORDER SIBLINGS BY \" : \"order siblings by \");\n            } else {\n                print0(ucase ? \"ORDER BY \" : \"order by \");\n            }\n\n            for (int i = 0, size = items.size(); i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                SQLSelectOrderByItem item = items.get(i);\n                visit(item);\n            }\n        }\n        return false;\n    }\n\n    public boolean visit(SQLSelectOrderByItem x) {\n        SQLExpr expr = x.getExpr();\n\n        if (expr instanceof SQLIntegerExpr) {\n            print(((SQLIntegerExpr) expr).getNumber().longValue());\n        } else if (expr instanceof SQLCharExpr) {\n            if (dialect != null) {\n                String name = \"'\" + ((SQLCharExpr) expr).getText() + \"'\";\n                printName0(replaceQuota(name));\n            } else {\n                printExpr(expr, parameterized);\n            }\n        } else if (expr instanceof SQLIdentifierExpr) {\n            ((SQLIdentifierExpr) expr).setName(replaceQuota(((SQLIdentifierExpr) expr).getName()));\n            printExpr(expr, parameterized);\n        } else {\n            printExpr(expr, parameterized);\n        }\n\n        String collate = x.getCollate();\n        if (collate != null) {\n            print0(ucase ? \" COLLATE \" : \" collate \");\n            print0(collate);\n        }\n        if (x.getOpclass() != null) {\n            print(' ');\n            x.getOpclass().accept(this);\n        }\n        SQLOrderingSpecification type = x.getType();\n        if (type != null) {\n            print(' ');\n            print0(ucase ? type.name : type.nameLCase);\n        }\n        SQLSelectOrderByItem.NullsOrderType nullsOrderType = x.getNullsOrderType();\n        if (nullsOrderType != null) {\n            print(' ');\n            print0(nullsOrderType.toFormalString());\n        }\n\n        SQLCommentHint hint = x.getHint();\n        if (hint != null) {\n            visit(hint);\n        }\n\n        return false;\n    }\n\n    protected void addTable(String table) {\n        if (tables == null) {\n            if (this.table == null) {\n                this.table = table;\n                return;\n            } else {\n                tables = new LinkedHashSet<String>();\n                tables.add(this.table);\n            }\n        }\n        this.tables.add(table);\n    }\n\n    protected void printTableSourceExpr(SQLExpr expr) {\n        if (exportTables) {\n            addTable(expr.toString());\n        }\n\n        if (isEnabled(VisitorFeature.OutputDesensitize)) {\n            String ident = null;\n            if (expr instanceof SQLIdentifierExpr) {\n                ident = ((SQLIdentifierExpr) expr).getName();\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n                propertyExpr.getOwner().accept(this);\n                print('.');\n\n                ident = propertyExpr.getName();\n            }\n\n            if (ident != null) {\n                String desensitizeTable = SQLUtils.desensitizeTable(ident);\n                print0(desensitizeTable);\n                return;\n            }\n        }\n\n        if (tableMapping != null && expr instanceof SQLName) {\n            String tableName;\n            if (expr instanceof SQLIdentifierExpr) {\n                tableName = ((SQLIdentifierExpr) expr).normalizedName();\n            } else if (expr instanceof SQLPropertyExpr) {\n                tableName = ((SQLPropertyExpr) expr).normalizedName();\n            } else {\n                tableName = expr.toString();\n            }\n\n            String destTableName = tableMapping.get(tableName);\n            if (destTableName == null) {\n                if (expr instanceof SQLPropertyExpr) {\n                    SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n                    String propName = propertyExpr.getName();\n                    destTableName = tableMapping.get(propName);\n                    if (destTableName == null\n                            && propName.length() > 2 && propName.charAt(0) == '`' && propName.charAt(propName.length() - 1) == '`') {\n                        destTableName = tableMapping.get(propName.substring(1, propName.length() - 1));\n                    }\n\n                    if (destTableName != null) {\n                        propertyExpr.getOwner().accept(this);\n                        print('.');\n                        print(destTableName);\n                        return;\n                    }\n                } else if (expr instanceof SQLIdentifierExpr) {\n                    boolean quote = tableName.length() > 2 && tableName.charAt(0) == '`' && tableName.charAt(tableName.length() - 1) == '`';\n                    if (quote) {\n                        destTableName = tableMapping.get(tableName.substring(1, tableName.length() - 1));\n                    }\n                }\n            }\n            if (destTableName != null) {\n                tableName = destTableName;\n                printName0(tableName);\n                return;\n            }\n        }\n\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            final String name = identifierExpr.getName();\n            if (!this.parameterized) {\n                printName0(name, false);\n                if (identifierExpr.hasAfterComment()) {\n                    printAfterComments(identifierExpr.getAfterCommentsDirect());\n                }\n                return;\n            }\n\n            boolean shardingSupport = this.shardingSupport\n                    && this.parameterized;\n\n            if (shardingSupport) {\n                String nameUnwrappe = unwrapShardingTable(name);\n\n                if (!name.equals(nameUnwrappe)) {\n                    incrementReplaceCunt();\n                }\n\n                printName0(nameUnwrappe);\n            } else {\n                printName0(name);\n            }\n            if (identifierExpr.hasAfterComment()) {\n                printAfterComments(identifierExpr.getAfterCommentsDirect());\n            }\n        } else if (expr instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n            SQLExpr owner = propertyExpr.getOwner();\n\n            if (owner instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identOwner = (SQLIdentifierExpr) owner;\n\n                String ownerName = replaceQuota(identOwner.getName());\n                if (!this.parameterized) {\n                    printName0(ownerName);\n                } else {\n                    if (shardingSupport) {\n                        ownerName = unwrapShardingTable(ownerName);\n                    }\n                    printName0(ownerName);\n                }\n            } else {\n                printExpr(owner);\n            }\n            print('.');\n\n            final String name = replaceQuota(propertyExpr.getName());\n            if (!this.parameterized) {\n                printName0(name);\n                return;\n            }\n\n            boolean shardingSupport = this.shardingSupport\n                    && this.parameterized;\n\n            if (shardingSupport) {\n                String nameUnwrappe = unwrapShardingTable(name);\n\n                if (!name.equals(nameUnwrappe)) {\n                    incrementReplaceCunt();\n                }\n\n                printName0(nameUnwrappe);\n            } else {\n                printName0(name);\n            }\n        } else if (expr instanceof SQLMethodInvokeExpr) {\n            visit((SQLMethodInvokeExpr) expr);\n        } else {\n            expr.accept(this);\n        }\n\n    }\n\n    public String replaceQuota(String name) {\n        if (dialect != null && name.length() >= 2 && dialect.getQuoteChars() != SQLDialect.DEFAULT_QUOTE_INT) {\n            if ((name.charAt(0) == '`' && name.charAt(name.length() - 1) == '`')\n                    || (name.charAt(0) == '\"' && name.charAt(name.length() - 1) == '\"')\n                    || (name.charAt(0) == '\\'' && name.charAt(name.length() - 1) == '\\'')\n                    || (name.charAt(0) == '[' && name.charAt(name.length() - 1) == ']')) {\n                if (!SQLDialect.Quote.isValidQuota(dialect.getQuoteChars(), SQLDialect.Quote.of(name.charAt(0)))) {\n                    char quote = SQLDialect.Quote.getQuote(dialect.getQuoteChars());\n                    if (quote == '[') {\n                        name = '[' + name.substring(1, name.length() - 1) + ']';\n                    } else {\n                        name = quote + name.substring(1, name.length() - 1) + quote;\n                    }\n                }\n            }\n        }\n        return name;\n    }\n    public boolean visit(SQLExprTableSource x) {\n        if (x.isLateral()) {\n            print0(ucase ? \"LATERAL \" : \"lateral \");\n        }\n        printTableSourceExpr(x.getExpr());\n\n        final SQLTableSampling sampling = x.getSampling();\n        if (sampling != null) {\n            print(' ');\n            sampling.accept(this);\n        }\n\n        String alias = x.getAlias();\n        List<SQLName> columns = x.getColumnsDirect();\n        if (alias != null) {\n            print(' ');\n            if (columns != null && columns.size() > 0) {\n                print0(ucase ? \" AS \" : \" as \");\n            } else if (x.isNeedAsTokenForAlias()) {\n                print0(ucase ? \"AS \" : \"as \");\n            }\n            printAlias0(alias);\n        }\n\n        if (columns != null && columns.size() > 0) {\n            print(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        printPivot(x.getPivot());\n\n        printUnpivot(x.getUnpivot());\n\n        if (isPrettyFormat() && x.hasAfterComment()) {\n            print(' ');\n            printlnComment(x.getAfterCommentsDirect());\n        }\n\n        return false;\n    }\n\n    protected void printPivot(SQLPivot pivot) {\n        if (pivot != null) {\n            println();\n            pivot.accept(this);\n        }\n    }\n\n    protected void printUnpivot(SQLUnpivot unpivot) {\n        if (unpivot != null) {\n            println();\n            unpivot.accept(this);\n        }\n    }\n\n    public boolean visit(SQLSelectStatement stmt) {\n        List<SQLCommentHint> headHints = stmt.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (stmt.hasBeforeComment()) {\n            printlnComments(stmt.getBeforeCommentsDirect());\n        }\n\n        SQLSelect select = stmt.getSelect();\n        if (select != null) {\n            this.visit(select);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        int index = x.getIndex();\n\n        if (index < 0 || inputParameters == null || index >= inputParameters.size()) {\n            print0(x.getName());\n            if (x.hasAfterComment()) {\n                printAfterComments(x.getAfterCommentsDirect());\n            }\n            return false;\n        }\n\n        Object param = inputParameters.get(index);\n\n        SQLObject parent = x.getParent();\n\n        boolean in;\n        if (parent instanceof SQLInListExpr) {\n            in = true;\n        } else if (parent instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) parent;\n            if (binaryOpExpr.getOperator() == SQLBinaryOperator.Equality) {\n                in = true;\n            } else {\n                in = false;\n            }\n        } else {\n            in = false;\n        }\n\n        if (in && param instanceof Collection) {\n            boolean first = true;\n            for (Object item : (Collection) param) {\n                if (!first) {\n                    print0(\", \");\n                }\n                printParameter(item);\n                first = false;\n            }\n        } else {\n            printParameter(param);\n        }\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    private void printParameterWithSingleQuot(Object param) {\n        print0(\"'\");\n        print(String.valueOf(param));\n        print0(\"'\");\n    }\n    public void printParameter(Object param) {\n        if (param == null) {\n            print0(ucase ? \"NULL\" : \"null\");\n            return;\n        }\n\n        if (param instanceof Double) {\n            param = BigDecimal.valueOf((double) param);\n        }\n        if (param instanceof BigDecimal) { // 不需要科学计数法输出\n            print0(((BigDecimal) param).toPlainString());\n            return;\n        }\n        if (param instanceof Calendar) {\n            printParameterWithSingleQuot(new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss.SSS\").format(new java.sql.Timestamp(((Calendar) param).getTimeInMillis())));\n            return;\n        }\n        if (param instanceof LocalDateTime) {\n            printParameterWithSingleQuot(((LocalDateTime) param).format(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SSS\")));\n            return;\n        }\n        if (param instanceof ZonedDateTime) {\n            printParameterWithSingleQuot(((ZonedDateTime) param).format(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SSS\")));\n            return;\n        }\n        if (param instanceof OffsetDateTime) {\n            printParameterWithSingleQuot(((OffsetDateTime) param).format(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SSS\")));\n            return;\n        }\n        if (param instanceof OffsetTime || param instanceof LocalTime || param instanceof LocalDate || param instanceof Instant) {\n            printParameterWithSingleQuot(param.toString());\n            return;\n        }\n        if (param instanceof TemporalAmount) {\n            printParameterWithSingleQuot(param.toString());\n            return;\n        }\n        if (param instanceof Number //\n                || param instanceof Boolean || param instanceof java.time.temporal.Temporal) {\n            print0(param.toString());\n            return;\n        }\n\n        if (param instanceof String) {\n            SQLCharExpr charExpr = new SQLCharExpr((String) param);\n            visit(charExpr);\n            return;\n        }\n\n        if (param instanceof Date) {\n            print((Date) param);\n            return;\n        }\n\n        if (param instanceof InputStream) {\n            print0(\"'<InputStream>'\");\n            return;\n        }\n\n        if (param instanceof Reader) {\n            print0(\"'<Reader>'\");\n            return;\n        }\n\n        if (param instanceof Blob) {\n            print0(\"'<Blob>'\");\n            return;\n        }\n\n        if (param instanceof NClob) {\n            print0(\"'<NClob>'\");\n            return;\n        }\n\n        if (param instanceof Clob) {\n            print0(\"'<Clob>'\");\n            return;\n        }\n\n        if (param instanceof byte[]) {\n            byte[] bytes = (byte[]) param;\n            int bytesLen = bytes.length;\n            char[] chars = new char[bytesLen * 2 + 3];\n            chars[0] = 'x';\n            chars[1] = '\\'';\n            for (int i = 0; i < bytes.length; i++) {\n                int a = bytes[i] & 0xFF;\n                int b0 = a >> 4;\n                int b1 = a & 0xf;\n\n                chars[i * 2 + 2] = (char) (b0 + (b0 < 10 ? 48 : 55)); //hexChars[b0];\n                chars[i * 2 + 3] = (char) (b1 + (b1 < 10 ? 48 : 55));\n            }\n            chars[chars.length - 1] = '\\'';\n            print0(new String(chars));\n            return;\n        }\n\n        if (param instanceof Character) {\n            print('\\'');\n            print((Character) param);\n            print('\\'');\n            return;\n        }\n\n        print0(\"'\" + param.getClass().getName() + \"'\");\n    }\n\n    public boolean visit(SQLDropTableStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"DROP \" : \"drop \");\n        List<SQLCommentHint> hints = x.getHints();\n        if (hints != null) {\n            printAndAccept(hints, \" \");\n            print(' ');\n        }\n\n        if (x.isExternal()) {\n            print0(ucase ? \"EXTERNAL \" : \"external \");\n        }\n\n        if (x.isDropPartition()) {\n            print0(ucase ? \"PARTITIONED \" : \"partitioned \");\n        }\n\n        if (x.isTemporary()) {\n            print0(ucase ? \"TEMPORARY TABLE \" : \"temporary table \");\n        } else {\n            print0(ucase ? \"TABLE \" : \"table \");\n        }\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printAndAccept(x.getTableSources(), \", \");\n\n        if (x.isCascade()) {\n            printCascade();\n        }\n\n        if (x.isRestrict()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n\n        if (x.isPurge()) {\n            print0(ucase ? \" PURGE\" : \" purge\");\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    protected void printCascade() {\n        print0(ucase ? \" CASCADE\" : \" cascade\");\n    }\n\n    public boolean visit(SQLDropViewStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"DROP VIEW \" : \"drop view \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printAndAccept(x.getTableSources(), \", \");\n\n        if (x.isCascade()) {\n            printCascade();\n        }\n        return false;\n    }\n\n    public boolean visit(SQLDropEventStatement x) {\n        print0(ucase ? \"DROP EVENT \" : \"drop event \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printExpr(x.getName(), parameterized);\n        return false;\n    }\n\n    public boolean visit(SQLDropResourceStatement x) {\n        print0(ucase ? \"DROP RESOURCE \" : \"drop resource \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printExpr(x.getName(), parameterized);\n        return false;\n    }\n\n    public boolean visit(SQLDropResourceGroupStatement x) {\n        print0(ucase ? \"DROP RESOURCE GROUP \" : \"drop resource group \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printExpr(x.getName(), parameterized);\n        return false;\n    }\n\n    public boolean visit(SQLListResourceGroupStatement x) {\n        print0(ucase ? \"LIST RESOURCE GROUP\" : \"list resource group\");\n\n        return false;\n    }\n\n    public boolean visit(SQLColumnDefinition x) {\n        boolean parameterized = this.parameterized;\n        this.parameterized = false;\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        String columnName = replaceQuota(x.getName().getSimpleName());\n        printName0(columnName);\n        final SQLDataType dataType = x.getDataType();\n        if (dataType != null) {\n            if (JdbcUtils.isPgsqlDbType(dbType) && x.getParent() instanceof SQLAlterTableAlterColumn) {\n                print0(ucase ? \" TYPE \" : \" type \");\n            } else {\n                print(' ');\n            }\n            dataType.accept(this);\n        }\n\n        if (x.getAggType() != null) {\n            visitAggType(x);\n        }\n\n        if (x.getDefaultExpr() != null) {\n            visitColumnDefault(x);\n        }\n\n        if (x.isAutoIncrement()) {\n            printAutoIncrement();\n        }\n\n        final AutoIncrementType sequenceType = x.getSequenceType();\n        if (sequenceType != null) {\n            print0(\" \");\n            print0(ucase ? sequenceType.getKeyword() : sequenceType.getKeyword().toLowerCase());\n        }\n\n        for (SQLColumnConstraint item : x.getConstraints()) {\n            boolean newLine = item instanceof SQLForeignKeyConstraint //\n                    || item instanceof SQLPrimaryKey //\n                    || item instanceof SQLColumnCheck //\n                    || item.getName() != null;\n            if (newLine) {\n                this.indentCount++;\n                println();\n            } else {\n                print(' ');\n            }\n\n            item.accept(this);\n\n            if (newLine) {\n                this.indentCount--;\n            }\n        }\n\n        if (x.getCollateExpr() != null) {\n            print0(ucase ? \" COLLATE \" : \" collate \");\n            x.getCollateExpr().accept(this);\n        }\n\n        if (x.isDisableNovalidate()) {\n            print0(ucase ? \" DISABLE NOVALIDATE\" : \" disable novalidate\");\n        }\n\n        printGeneratedAlways(x, parameterized);\n\n        if (x.isVirtual()) {\n            print0(ucase ? \" VIRTUAL\" : \" virtual\");\n        }\n\n        if (x.isVisible()) {\n            print0(ucase ? \" VISIBLE\" : \" visible\");\n        }\n\n        Boolean enable = x.getEnable();\n        if (enable != null) {\n            if (enable.booleanValue()) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            }\n        }\n\n        if (x.getComment() != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            x.getComment().accept(this);\n        }\n\n        printMappedBy(x.getMappedByDirect());\n\n        printColumnProperties(x);\n\n        printEncoding(x);\n\n        printCompression(x);\n\n        printBlockSize(x);\n\n        this.parameterized = parameterized;\n\n        return false;\n    }\n\n    protected void printEncoding(SQLColumnDefinition x) {\n        if (x.getEncode() != null) {\n            print0(ucase ? \" ENCODE=\" : \" encode=\");\n            x.getEncode().accept(this);\n        }\n    }\n\n    protected void printCompression(SQLColumnDefinition x) {\n        if (x.getCompression() != null) {\n            print0(ucase ? \" COMPRESSION=\" : \" compression=\");\n            x.getCompression().accept(this);\n        }\n    }\n\n    protected void printBlockSize(SQLColumnDefinition x) {\n        if (x.getBlockSize() != null) {\n            print0(ucase ? \" BLOCK_SIZE \" : \" block_size \");\n            x.getBlockSize().accept(this);\n        }\n    }\n\n    protected void printColumnProperties(SQLColumnDefinition x) {\n        List<SQLAssignItem> colProperties = x.getColPropertiesDirect();\n        if (colProperties == null || colProperties.isEmpty()) {\n            return;\n        }\n        print0(ucase ? \" COLPROPERTIES (\" : \" colproperties (\");\n        printAndAccept(colProperties, \", \");\n        print0(ucase ? \")\" : \")\");\n    }\n\n    protected void printMappedBy(List<SQLAssignItem> mappedBy) {\n        if (mappedBy != null && mappedBy.size() > 0) {\n            print0(ucase ? \" MAPPED BY (\" : \" mapped by (\");\n            printAndAccept(mappedBy, \", \");\n            print0(ucase ? \")\" : \")\");\n        }\n    }\n\n    protected void printGeneratedAlways(SQLColumnDefinition x, boolean parameterized) {\n        SQLExpr generatedAlwaysAs = x.getGeneratedAlwaysAs();\n        if (generatedAlwaysAs != null) {\n            print0(ucase ? \" GENERATED ALWAYS AS \" : \" generated always as \");\n            printExpr(generatedAlwaysAs, parameterized);\n        }\n\n        SQLColumnDefinition.Identity identity = x.getIdentity();\n        if (identity != null) {\n            if (dbType == DbType.h2) {\n                print0(ucase ? \" AS \" : \" as \");\n            } else {\n                print(' ');\n            }\n            identity.accept(this);\n        }\n    }\n\n    protected void printAutoIncrement() {\n        print0(ucase ? \" AUTO_INCREMENT\" : \" auto_increment\");\n    }\n\n    @Override\n    public boolean visit(SQLColumnDefinition.Identity x) {\n        print0(ucase ? \"IDENTITY\" : \"identity\");\n        Integer seed = x.getSeed();\n        if (seed != null) {\n            print0(\" (\");\n            print(seed);\n            print0(\", \");\n            print(x.getIncrement());\n            print(')');\n        }\n        return false;\n    }\n\n    protected void visitColumnDefault(SQLColumnDefinition x) {\n        print0(ucase ? \" DEFAULT \" : \" default \");\n        printExpr(x.getDefaultExpr(), false);\n    }\n\n    protected void visitAggType(SQLColumnDefinition x) {\n        print(' ');\n        print0(ucase ? x.getAggType().getText().toUpperCase(Locale.ROOT) :\n                x.getAggType().getText().toLowerCase(Locale.ROOT));\n    }\n\n    public boolean visit(SQLDeleteStatement x) {\n        SQLTableSource from = x.getFrom();\n        String alias = x.getAlias();\n\n        if (from == null) {\n            print0(ucase ? \"DELETE FROM \" : \"delete from \");\n            printTableSourceExpr(x.getTableName());\n\n            if (alias != null) {\n                print(' ');\n                print0(alias);\n            }\n        } else {\n            print0(ucase ? \"DELETE \" : \"delete \");\n            printTableSourceExpr(x.getTableName());\n            print0(ucase ? \" FROM \" : \" from \");\n            from.accept(this);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            this.indentCount++;\n            where.accept(this);\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCurrentOfCursorExpr x) {\n        print0(ucase ? \"CURRENT OF \" : \"current of \");\n        printExpr(x.getCursorName(), parameterized);\n        return false;\n    }\n\n    public void printInsertOverWrite(SQLInsertStatement x) {\n        print0(ucase ? \"INSERT OVERWRITE \" : \"insert overwrite \");\n    }\n    public boolean visit(SQLInsertStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.getInsertBeforeCommentsDirect() != null) {\n            printlnComments(x.getInsertBeforeCommentsDirect());\n        }\n\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            visit(with);\n            println();\n        }\n\n        if (x.isUpsert()) {\n            print0(ucase ? \"UPSERT INTO \" : \"upsert into \");\n        } else {\n            if (x.isOverwrite()) {\n                printInsertOverWrite(x);\n            } else {\n                print0(ucase ? \"INSERT INTO \" : \"insert into \");\n            }\n        }\n\n        x.getTableSource().accept(this);\n\n        if (x.getPartitions() != null && !x.getPartitions().isEmpty()) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartitions(), \", \");\n            print(')');\n        }\n        String columnsString = x.getColumnsString();\n        if (columnsString != null) {\n            print0(columnsString);\n        } else {\n            printInsertColumns(x.getColumns());\n        }\n\n        if (!x.getValuesList().isEmpty()) {\n            println();\n            print0(ucase ? \"VALUES \" : \"values \");\n            printAndAccept(x.getValuesList(), \", \");\n        } else {\n            if (x.getQuery() != null) {\n                println();\n                x.getQuery().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public void printInsertColumns(List<SQLExpr> columns) {\n        final int size = columns.size();\n        if (size > 0) {\n            if (size > 5) {\n                this.indentCount++;\n                println();\n            } else {\n                print(' ');\n            }\n            print('(');\n            for (int i = 0; i < size; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        println();\n                    }\n                    print0(\", \");\n                }\n\n                SQLExpr column = columns.get(i);\n                // 打印 前注释\n                if (column.hasBeforeComment()) {\n                    printlnComments(column.getBeforeCommentsDirect());\n                }\n                if (column instanceof SQLIdentifierExpr) {\n                    visit((SQLIdentifierExpr) column);\n                } else {\n                    printExpr(column, parameterized);\n                }\n                // 打印 后注释\n                if (isPrettyFormat() && column.hasAfterComment()) {\n                    print(' ');\n                    printlnComment(column.getAfterCommentsDirect());\n                    println();\n                }\n                String dataType = (String) column.getAttribute(\"dataType\");\n                if (dataType != null) {\n                    print(' ');\n                    print(dataType);\n                }\n            }\n            print(')');\n            if (size > 5) {\n                this.indentCount--;\n            }\n        }\n    }\n\n    public boolean visit(SQLUpdateSetItem x) {\n        printExpr(x.getColumn(), parameterized);\n        print0(\" = \");\n        printExpr(x.getValue(), parameterized);\n        return false;\n    }\n\n    public boolean visit(SQLUpdateStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.getWith() != null) {\n            x.getWith().accept(this);\n            println();\n        }\n\n        print0(ucase ? \"UPDATE \" : \"update \");\n\n        printTableSource(x.getTableSource());\n\n        println();\n        print0(ucase ? \"SET \" : \"set \");\n        for (int i = 0, size = x.getItems().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            SQLUpdateSetItem item = (SQLUpdateSetItem) x.getItems().get(i);\n            visit(item);\n        }\n\n        SQLTableSource from = x.getFrom();\n        if (from instanceof SQLTableSourceImpl) {\n            println();\n            indentCount++;\n            print0(ucase ? \"FROM \" : \"from \");\n            if (from instanceof SQLSubqueryTableSource) {\n                visit((SQLSubqueryTableSource) from);\n            } else if (from instanceof SQLExprTableSource) {\n                visit((SQLExprTableSource) from);\n            }\n            indentCount--;\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            indentCount++;\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where, parameterized);\n            indentCount--;\n        }\n        if (x.getLimit() != null) {\n            println();\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    protected void printTableElements(List<SQLTableElement> tableElementList) {\n        int size = tableElementList.size();\n        if (size == 0) {\n            return;\n        }\n\n        print0(\" (\");\n\n        this.indentCount++;\n        println();\n        for (int i = 0; i < size; ++i) {\n            printTableElement(tableElementList, i);\n        }\n        this.indentCount--;\n        println();\n        print(')');\n    }\n\n    protected void printTableElement(List<SQLTableElement> tableElementList, int i) {\n        int size = tableElementList.size();\n        SQLTableElement element = tableElementList.get(i);\n        element.accept(this);\n\n        if (i != size - 1) {\n            print(',');\n        }\n        if (this.isPrettyFormat() && element.hasAfterComment()) {\n            print(' ');\n            printlnComment(element.getAfterCommentsDirect());\n        }\n\n        if (i != size - 1) {\n            println();\n        }\n    }\n\n    protected void printEngine(SQLCreateTableStatement x) {\n    }\n\n    protected void printCreateTableRest(SQLCreateTableStatement x) {\n    }\n\n    protected void printOrderBy(SQLCreateTableStatement x) {\n    }\n    public boolean visit(SQLCreateTableStatement x) {\n        printCreateTable(x, false);\n        printPartitionOf(x);\n        printEngine(x);\n        printPartitionBy(x);\n        printTableOptions(x);\n        printCreateTableRest(x);\n        printTablespace(x.getTablespace());\n        printSelectAs(x, true);\n        return false;\n    }\n\n    protected void printPartitionBy(SQLCreateTableStatement x) {\n        SQLPartitionBy partitionBy = x.getPartitioning();\n        if (partitionBy == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"PARTITION BY \" : \"partition by \");\n        partitionBy.accept(this);\n    }\n\n    protected void printSortedBy(List<SQLSelectOrderByItem> sortedBy) {\n        if (sortedBy.size() > 0) {\n            println();\n            print0(ucase ? \"SORTED BY (\" : \"sorted by (\");\n            printAndAccept(sortedBy, \", \");\n            print(')');\n        }\n    }\n\n    protected void printClusteredBy(SQLCreateTableStatement x) {\n        List<SQLSelectOrderByItem> clusteredBy = x.getClusteredBy();\n        if (clusteredBy.isEmpty()) {\n            return;\n        }\n        println();\n        if (x.getClusteringType() == ClusteringType.Range) {\n            print0(ucase ? \"RANGE \" : \"range \");\n        }\n        print0(ucase ? \"CLUSTERED BY (\" : \"clustered by (\");\n        printAndAccept(clusteredBy, \",\");\n        print(')');\n    }\n\n    protected void printCreateTableAfterName(SQLCreateTableStatement x) {}\n\n    protected void printCreateTable(SQLCreateTableStatement x, boolean printSelect) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        printCreateTableFeatures(x);\n\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printTableSourceExpr(\n                x.getTableSource()\n                .getExpr());\n\n        printCreateTableAfterName(x);\n\n        printTableElements(x.getTableElementList());\n\n        printInherits(x);\n\n        printComment(x.getComment());\n        printCollate(x);\n\n        printPartitionedBy(x);\n        printClusteredBy(x);\n        printSortedBy(x.getSortedBy());\n        printIntoBuckets(x.getBuckets());\n        printIntoShards(x.getShards());\n\n        printStoredAs(x);\n        printStoredBy(x);\n        printLifeCycle(x.getLifeCycle());\n\n        printCreateTableLike(x);\n\n        printSelectAs(x, printSelect);\n    }\n\n    protected void printInherits(SQLCreateTableStatement x) {\n        SQLExprTableSource inherits = x.getInherits();\n        if (inherits != null) {\n            print0(ucase ? \" INHERITS (\" : \" inherits (\");\n            inherits.accept(this);\n            print(')');\n        }\n    }\n\n    protected void printStoredBy(SQLCreateTableStatement x) {\n        SQLExpr storedBy = x.getStoredBy();\n        if (storedBy != null) {\n            print0(ucase ? \" STORE BY \" : \" store by \");\n            printExpr(storedBy, parameterized);\n        }\n    }\n\n    protected void printSelectAs(SQLCreateTableStatement x, boolean printSelect) {\n        SQLSelect select = x.getSelect();\n        if (printSelect && select != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n\n            println();\n            visit(select);\n        }\n    }\n\n    protected void printPartitionOf(SQLCreateTableStatement x) {\n        SQLPartitionOf partitionOf = x.getPartitionOf();\n        if (partitionOf != null) {\n            println();\n            print0(ucase ? \"PARTITION OF \" : \"partition of \");\n            partitionOf.accept(this);\n        }\n    }\n\n    protected void printTablespace(SQLName tablespace) {\n        if (tablespace != null) {\n            println();\n            print0(ucase ? \"TABLESPACE \" : \"tablespace \");\n            tablespace.accept(this);\n        }\n    }\n\n    protected void printComment(SQLExpr comment) {\n        if (comment == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"COMMENT \" : \"comment \");\n        comment.accept(this);\n    }\n\n    protected void printCollate(SQLCreateTableStatement x){\n    }\n\n    protected void printStoredAs(SQLCreateTableStatement x) {\n        SQLExpr storedAs = x.getStoredAs();\n        if (storedAs == null) {\n            return;\n        }\n        print0(ucase ? \" STORE AS \" : \" store as \");\n        printExpr(storedAs, parameterized);\n    }\n\n    public boolean visit(SQLUniqueConstraint x) {\n        if (x.getName() != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            x.getName().accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"UNIQUE (\" : \"unique (\");\n        List<SQLSelectOrderByItem> columns = x.getColumns();\n        for (int i = 0, size = columns.size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            visit(columns.get(i));\n        }\n        print(')');\n        return false;\n    }\n\n    public boolean visit(SQLNotNullConstraint x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n        print0(ucase ? \"NOT NULL\" : \"not null\");\n\n        Boolean enable = x.getEnable();\n        if (enable != null) {\n            if (enable.booleanValue()) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            } else {\n                print0(ucase ? \" DISABLE\" : \" disable\");\n            }\n        }\n\n        List<SQLCommentHint> hints = x.hints;\n        if (hints != null) {\n            print(' ');\n            for (SQLCommentHint hint : hints) {\n                hint.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLNullConstraint x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n        print0(ucase ? \"NULL\" : \"null\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnionQuery x) {\n        SQLWithSubqueryClause with = x.getWith();\n        if (with != null) {\n            with.accept(this);\n            println();\n        }\n        SQLUnionOperator operator = x.getOperator();\n\n        List<SQLSelectQuery> relations = x.getRelations();\n        if (relations.size() > 2) {\n            for (int i = 0; i < relations.size(); i++) {\n                if (i != 0) {\n                    println();\n                    print0(ucase ? operator.name : operator.nameLCase);\n                    println();\n                }\n\n                SQLSelectQuery item = relations.get(i);\n                item.accept(this);\n            }\n\n            SQLOrderBy orderBy = x.getOrderBy();\n            if (orderBy != null) {\n                println();\n                orderBy.accept(this);\n            }\n\n            SQLLimit limit = x.getLimit();\n            if (limit != null) {\n                println();\n                limit.accept(this);\n            }\n            return false;\n        }\n\n        SQLSelectQuery left = x.getLeft();\n        SQLSelectQuery right = x.getRight();\n\n        boolean bracket = x.isParenthesized() && !(x.getParent() instanceof SQLUnionQueryTableSource);\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if ((!bracket)\n                && left instanceof SQLUnionQuery\n                && ((SQLUnionQuery) left).getOperator() == operator\n                && !right.isParenthesized()\n                && x.getLimit() == null\n                && orderBy == null) {\n            SQLUnionQuery leftUnion = (SQLUnionQuery) left;\n\n            if (right instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock rightQueryBlock = (SQLSelectQueryBlock) right;\n                if (rightQueryBlock.getOrderBy() != null || rightQueryBlock.getLimit() != null) {\n                    rightQueryBlock.setParenthesized(true);\n                }\n            }\n\n            List<SQLSelectQuery> rights = new ArrayList<SQLSelectQuery>();\n            rights.add(right);\n\n            if (leftUnion.getRelations().size() > 2) {\n                rights.addAll(leftUnion.getRelations());\n            } else {\n                for (; ; ) {\n                    SQLSelectQuery leftLeft = leftUnion.getLeft();\n                    SQLSelectQuery leftRight = leftUnion.getRight();\n\n                    if (leftRight instanceof SQLSelectQueryBlock) {\n                        SQLSelectQueryBlock leftRightQueryBlock = (SQLSelectQueryBlock) leftRight;\n                        if (leftRightQueryBlock.getOrderBy() != null || leftRightQueryBlock.getLimit() != null) {\n                            leftRightQueryBlock.setParenthesized(true);\n                        }\n                    }\n\n                    if ((!leftUnion.isParenthesized())\n                            && leftUnion.getOrderBy() == null\n                            && (!leftLeft.isParenthesized())\n                            && (!leftRight.isParenthesized())\n                            && leftLeft instanceof SQLUnionQuery\n                            && ((SQLUnionQuery) leftLeft).getOperator() == operator) {\n                        rights.add(leftRight);\n                        leftUnion = (SQLUnionQuery) leftLeft;\n                        continue;\n                    } else {\n                        rights.add(leftRight);\n                        rights.add(leftLeft);\n                    }\n                    break;\n                }\n            }\n\n            for (int i = rights.size() - 1; i >= 0; i--) {\n                SQLSelectQuery item = rights.get(i);\n                item.accept(this);\n\n                if (i > 0) {\n                    println();\n                    print0(ucase ? operator.name : operator.nameLCase);\n                    println();\n                }\n            }\n            return false;\n        }\n\n        if (bracket) {\n            print('(');\n        }\n\n        if (left != null) {\n            for (; ; ) {\n                if (left.getClass() == SQLUnionQuery.class) {\n                    SQLUnionQuery leftUnion = (SQLUnionQuery) left;\n                    if (leftUnion.getRelations().size() > 2) {\n                        visit(leftUnion);\n                    } else {\n                        SQLSelectQuery leftLeft = leftUnion.getLeft();\n                        SQLSelectQuery leftRigt = leftUnion.getRight();\n                        if ((!leftUnion.isParenthesized())\n                                && leftUnion.getRight() instanceof SQLSelectQueryBlock\n                                && leftUnion.getLeft() != null\n                                && leftUnion.getLimit() == null\n                                && leftUnion.getOrderBy() == null) {\n                            if (leftLeft.getClass() == SQLUnionQuery.class) {\n                                visit((SQLUnionQuery) leftLeft);\n                            } else {\n                                printQuery(leftLeft);\n                            }\n                            println();\n                            print0(ucase ? leftUnion.getOperator().name : leftUnion.getOperator().nameLCase);\n                            println();\n                            leftRigt.accept(this);\n                        } else {\n                            visit(leftUnion);\n                        }\n                    }\n                } else {\n                    left.accept(this);\n                }\n                break;\n            }\n        }\n\n        if (right == null) {\n            return false;\n        }\n\n        println();\n        print0(ucase ? operator.name : operator.nameLCase);\n        println();\n\n        boolean needParen = false;\n        if ((!right.isParenthesized())\n                && right instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock rightQuery = (SQLSelectQueryBlock) right;\n            if (rightQuery.getOrderBy() != null || rightQuery.getLimit() != null) {\n                needParen = true;\n            }\n        }\n\n        if (needParen) {\n            print('(');\n            right.accept(this);\n            print(')');\n        } else {\n            right.accept(this);\n        }\n\n        if (orderBy != null) {\n            println();\n            orderBy.accept(this);\n        }\n\n        SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            println();\n            limit.accept(this);\n        }\n\n        if (bracket) {\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnaryExpr x) {\n        SQLUnaryOperator operator = x.getOperator();\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        print0(operator.name);\n        SQLExpr expr = x.getExpr();\n\n        switch (operator) {\n            case BINARY:\n            case Prior:\n            case ConnectByRoot:\n            case NOT:\n                print(' ');\n                if (operator != SQLUnaryOperator.Prior && expr instanceof SQLBinaryOpExpr && !((SQLBinaryOpExpr) expr).isParenthesized()) {\n                    print('(');\n                    expr.accept(this);\n                    print(')');\n                } else {\n                    expr.accept(this);\n                }\n                return false;\n            default:\n                break;\n        }\n\n        if (expr instanceof SQLBinaryOpExpr\n                || expr instanceof SQLBinaryOpExprGroup\n                || expr instanceof SQLUnaryExpr\n                || expr instanceof SQLNotExpr\n                || expr instanceof SQLBetweenExpr\n                || expr instanceof SQLInListExpr\n                || expr instanceof SQLInSubQueryExpr) {\n            incrementIndent();\n            //print('(');\n            expr.accept(this);\n            //print(')');\n            decrementIndent();\n        } else {\n            expr.accept(this);\n        }\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLHexExpr x) {\n        if (this.parameterized) {\n            print('?');\n            incrementReplaceCunt();\n\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n            return false;\n        }\n\n        print0(\"0x\");\n        print0(x.getHex());\n\n        String charset = (String) x.getAttribute(\"USING\");\n        if (charset != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(charset);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSetStatement x) {\n        if (x.getHeadHintsDirect() != null) {\n            for (SQLCommentHint hint : x.getHeadHintsDirect()) {\n                hint.accept(this);\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        SQLSetStatement.Option option = x.getOption();\n\n        boolean printSet = Boolean.TRUE.equals(x.getAttribute(\"parser.set\")) || !JdbcUtils.isOracleDbType(dbType);\n        if (printSet) {\n            if (option == SQLSetStatement.Option.PROJECT) {\n                print0(ucase ? \"SETPROJECT \" : \"setproject \");\n            } else {\n                print0(ucase ? \"SET \" : \"set \");\n            }\n        }\n\n        if (option != null && option != SQLSetStatement.Option.PROJECT) {\n            print(option.name());\n            print(' ');\n        }\n\n        printAndAccept(x.getItems(), \", \");\n\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            print(' ');\n            printAndAccept(x.getHints(), \" \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAssignItem x) {\n        x.getTarget().accept(this);\n\n        SQLExpr value = x.getValue();\n        if (value != null) {\n            print0(\" =\");\n            if (!(value instanceof SQLQueryExpr)) {\n                print(' ');\n            }\n            value.accept(this);\n        } else {\n            if (dbType == DbType.odps) {\n                print0(\" = \");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCallStatement x) {\n        if (x.isBrace()) {\n            print('{');\n        }\n        if (x.getOutParameter() != null) {\n            x.getOutParameter().accept(this);\n            print0(\" = \");\n        }\n\n        print0(ucase ? \"CALL \" : \"call \");\n        x.getProcedureName().accept(this);\n        print('(');\n\n        printAndAccept(x.getParameters(), \", \");\n        print(')');\n        if (x.isBrace()) {\n            print('}');\n        }\n        return false;\n    }\n\n    protected void printJoinHint(SQLJoinTableSource x){}\n    @Override\n    public boolean visit(SQLJoinTableSource x) {\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n        SQLCommentHint hint = x.getHint();\n        if (hint != null) {\n            hint.accept(this);\n        }\n\n        SQLTableSource left = x.getLeft();\n\n        String alias = x.getAlias();\n        if (alias != null) {\n            print('(');\n        }\n\n        JoinType joinType = x.getJoinType();\n        if (left instanceof SQLJoinTableSource\n                && ((SQLJoinTableSource) left).getJoinType() == JoinType.COMMA\n                && joinType != JoinType.COMMA\n                && DbType.postgresql != dbType\n                && ((SQLJoinTableSource) left).getAttribute(\"ads.comma_join\") == null) {\n            print('(');\n            printTableSource(left);\n            print(')');\n        } else {\n            printTableSource(left);\n        }\n        this.indentCount++;\n\n        if (joinType == JoinType.COMMA) {\n            print(',');\n        } else {\n            println();\n\n            boolean asof = x.isAsof();\n            if (asof) {\n                print0(ucase ? \" ASOF \" : \" asof \");\n            }\n\n            if (x.isNatural()) {\n                //print0(ucase ? \"NATURAL \" : \"natural \");\n            }\n\n            if (x.isGlobal()) {\n                print0(ucase ? \"GLOBAL \" : \"global \");\n            }\n\n            printJoinType(joinType);\n        }\n        printJoinHint(x);\n        print(' ');\n\n        SQLTableSource right = x.getRight();\n        if (right instanceof SQLJoinTableSource && ((SQLJoinTableSource) right).getJoinType() == JoinType.COMMA) {\n            print('(');\n            printTableSource(right);\n            print(')');\n        } else {\n            printTableSource(right);\n        }\n\n        SQLExpr condition = x.getCondition();\n        if (condition != null) {\n            boolean newLine = false;\n\n            if (right instanceof SQLSubqueryTableSource) {\n                newLine = true;\n            } else if (condition instanceof SQLBinaryOpExpr) {\n                SQLBinaryOperator op = ((SQLBinaryOpExpr) condition).getOperator();\n                if (op == SQLBinaryOperator.BooleanAnd || op == SQLBinaryOperator.BooleanOr) {\n                    newLine = true;\n                }\n            } else if (condition instanceof SQLBinaryOpExprGroup) {\n                newLine = true;\n            }\n            if (newLine) {\n                println();\n            } else {\n                print(' ');\n            }\n            this.indentCount++;\n            print0(ucase ? \"ON \" : \"on \");\n            printExpr(condition, parameterized);\n            if (x.getAfterCommentsDirect() != null) {\n                printAfterComments(x.getAfterCommentsDirect());\n                println();\n            }\n            this.indentCount--;\n        }\n\n        if (x.getUsing().size() > 0) {\n            print0(ucase ? \" USING (\" : \" using (\");\n            printAndAccept(x.getUsing(), \", \");\n            print(')');\n        }\n\n        if (alias != null) {\n            print0(ucase ? \") AS \" : \") as \");\n            print0(alias);\n        }\n\n        SQLJoinTableSource.UDJ udj = x.getUdj();\n        if (udj != null) {\n            println();\n            udj.accept(this);\n        }\n\n        this.indentCount--;\n\n        printPivot(x.getPivot());\n        printUnpivot(x.getUnpivot());\n        if (x.hasAfterComment()) {\n            printAfterComments(x.getAfterCommentsDirect());\n        }\n        return false;\n    }\n\n    public boolean visit(SQLJoinTableSource.UDJ x) {\n        print0(ucase ? \"USING \" : \"using \");\n        x.getFunction().accept(this);\n        print('(');\n        printAndAccept(x.getArguments(), \", \");\n        print0(\") \");\n        print0(x.getAlias());\n        print0(ucase ? \" AS (\" : \" as (\");\n        printAndAccept(x.getColumns(), \", \");\n        print0(\")\");\n\n        List<SQLAssignItem> properties = x.getProperties();\n        if (!properties.isEmpty()) {\n            print0(ucase ? \" WITH UDFPROPERTIES (\" : \" with udfproperties (\");\n            printAndAccept(properties, \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    protected void printJoinType(JoinType joinType) {\n        print0(ucase ? joinType.name : joinType.nameLCase);\n    }\n\n    static String[] variantValuesCache_1 = new String[64];\n    static String[] variantValuesCache = new String[64];\n\n    static {\n        for (int len = 0; len < variantValuesCache_1.length; ++len) {\n            StringBuilder buf = new StringBuilder();\n            buf.append('(');\n            for (int i = 0; i < len; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        buf.append(\"\\n\\t\");\n                    }\n                    buf.append(\", \");\n                }\n                buf.append('?');\n            }\n            buf.append(')');\n            variantValuesCache_1[len] = buf.toString();\n        }\n\n        for (int len = 0; len < variantValuesCache.length; ++len) {\n            StringBuilder buf = new StringBuilder();\n            buf.append('(');\n            for (int i = 0; i < len; ++i) {\n                if (i != 0) {\n                    if (i % 5 == 0) {\n                        buf.append(\"\\n\\t\\t\");\n                    }\n                    buf.append(\", \");\n                }\n                buf.append('?');\n            }\n            buf.append(')');\n            variantValuesCache[len] = buf.toString();\n        }\n    }\n\n    @Override\n    public boolean visit(ValuesClause x) {\n        return visit(x, parameters);\n    }\n\n    public boolean visit(ValuesClause x, List<Object> parameters) {\n        if ((!this.parameterized)\n                && isEnabled(VisitorFeature.OutputUseInsertValueClauseOriginalString)\n                && x.getOriginalString() != null) {\n            print0(x.getOriginalString());\n            return false;\n        }\n\n        int xReplaceCount = x.getReplaceCount();\n        final List<SQLExpr> values = x.getValues();\n\n        this.replaceCount += xReplaceCount;\n\n        if (xReplaceCount == values.size() && xReplaceCount < variantValuesCache.length) {\n            String variantValues;\n            if (indentCount == 0) {\n                variantValues = variantValuesCache_1[xReplaceCount];\n            } else {\n                variantValues = variantValuesCache[xReplaceCount];\n            }\n            print0(variantValues);\n            return false;\n        }\n\n        if (inputParameters != null\n                && inputParameters.size() > 0\n                && inputParameters.get(0) instanceof Collection\n                && ((Collection) inputParameters.get(0)).size() == x.getValues().size()) {\n            incrementIndent();\n            for (int i = 0; i < inputParameters.size(); i++) {\n                Collection params = (Collection) inputParameters.get(i);\n                if (i != 0) {\n                    print(',');\n                    println();\n                }\n\n                print('(');\n                int j = 0;\n                for (Object item : (Collection) params) {\n                    if (j != 0) {\n                        if (j % 5 == 0) {\n                            println();\n                        }\n                        print0(\", \");\n                    }\n                    printParameter(item);\n                    j++;\n                }\n                print(')');\n            }\n            decrementIndent();\n            return false;\n        }\n\n        print('(');\n        this.indentCount++;\n\n        for (int i = 0, size = values.size(); i < size; ++i) {\n            if (i != 0) {\n                if (i % 5 == 0) {\n                    println();\n                }\n                print0(\", \");\n            }\n\n            Object value = values.get(i);\n\n            if (value instanceof SQLExpr) {\n                SQLExpr expr = values.get(i);\n\n                if (this.parameterized &&\n                        (expr instanceof SQLIntegerExpr\n                                || expr instanceof SQLBooleanExpr\n                                || expr instanceof SQLNumberExpr\n                                || expr instanceof SQLCharExpr\n                                || expr instanceof SQLNCharExpr\n                                || expr instanceof SQLTimestampExpr\n                                || expr instanceof SQLDateExpr\n                                || expr instanceof SQLTimeExpr)) {\n                    print('?');\n                    incrementReplaceCunt();\n                    if (parameters != null) {\n                        ExportParameterVisitorUtils.exportParameter(parameters, expr);\n                    }\n                    continue;\n                } else if (this.parameterized && expr instanceof SQLNullExpr) {\n                    print('?');\n                    if (parameters != null) {\n                        parameters.add(null);\n                    }\n                    incrementReplaceCunt();\n                } else if (expr instanceof SQLVariantRefExpr) {\n                    visit((SQLVariantRefExpr) expr);\n                } else {\n                    expr.accept(this);\n                }\n            } else if (value instanceof Integer) {\n                print(((Integer) value).intValue());\n            } else if (value instanceof Long) {\n                print(((Long) value).longValue());\n            } else if (value instanceof String) {\n                printChars((String) value);\n            } else if (value instanceof Float) {\n                print(((Float) value).floatValue());\n            } else if (value instanceof Double) {\n                print(((Double) value).doubleValue());\n            } else if (value instanceof Date) {\n                print((Date) value);\n            } else if (value instanceof BigDecimal) {\n                print(((BigDecimal) value).toPlainString());\n            } else if (value instanceof BigInteger) {\n                print(value.toString());\n            } else if (value == null) {\n                print0(ucase ? \"NULL\" : \"null\");\n            } else {\n                throw new UnsupportedOperationException();\n            }\n        }\n\n        this.indentCount--;\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSomeExpr x) {\n        print0(ucase ? \"SOME (\" : \"some (\");\n        this.indentCount++;\n        println();\n        x.getSubQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAnyExpr x) {\n        print0(ucase ? \"ANY (\" : \"any (\");\n        this.indentCount++;\n        println();\n        x.getSubQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAllExpr x) {\n        print0(ucase ? \"ALL (\" : \"all (\");\n        this.indentCount++;\n        println();\n        x.getSubQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLInSubQueryExpr x) {\n        if (x.getExpr() instanceof SQLIdentifierExpr) {\n            String columnName = replaceQuota(((SQLIdentifierExpr) x.getExpr()).getName());\n            printName0(columnName);\n        } else {\n            x.getExpr().accept(this);\n        }\n        if (x.isNot()) {\n            if (x.isGlobal()) {\n                print0(ucase ? \" GLOBAL NOT IN (\" : \" global not in (\");\n            } else {\n                print0(ucase ? \" NOT IN (\" : \" not in (\");\n            }\n        } else {\n            if (x.isGlobal()) {\n                print0(ucase ? \" GLOBAL IN (\" : \" global in (\");\n            } else {\n                print0(ucase ? \" IN (\" : \" in (\");\n            }\n        }\n\n        this.indentCount++;\n        println();\n        x.getSubQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        if (x.getHint() != null) {\n            x.getHint().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLListExpr x) {\n        print('(');\n        printAndAccept(x.getItems(), \", \");\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubqueryTableSource x) {\n        if (x.isLateral()) {\n            print0(ucase ? \"LATERAL\" : \"lateral\");\n        }\n        print('(');\n        this.indentCount++;\n        println();\n\n        if (x.getHintsSize() > 0) {\n            printAndAccept(x.getHints(), \" \");\n            println();\n        }\n\n        this.visit(x.getSelect());\n        this.indentCount--;\n        println();\n        print(')');\n\n        final List<SQLName> columns = x.getColumns();\n        final String alias = x.getAlias();\n        if (alias != null) {\n            if (!columns.isEmpty()) {\n                print0(\" AS \");\n            } else {\n                print(' ');\n            }\n            print0(alias);\n        }\n\n        if (!columns.isEmpty()) {\n            print0(\" (\");\n            for (int i = 0; i < columns.size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                printExpr(columns.get(i));\n            }\n            print(')');\n        }\n\n        printPivot(x.getPivot());\n\n        printUnpivot(x.getUnpivot());\n\n        if (isPrettyFormat() && x.hasAfterComment()) {\n            print(' ');\n            printlnComment(x.getAfterCommentsDirect());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnnestTableSource x) {\n        print0(ucase ? \"UNNEST(\" : \"unnest(\");\n        incrementIndent();\n        List<SQLExpr> items = x.getItems();\n        printAndAccept(items, \", \");\n        decrementIndent();\n        print(')');\n\n        if (x.isOrdinality()) {\n            print0(ucase ? \" WITH ORDINALITY\" : \" with ordinality\");\n        }\n\n        final List<SQLName> columns = x.getColumns();\n        final String alias = x.getAlias();\n        if (alias != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            print0(alias);\n        }\n\n        if (columns.size() > 0) {\n            print0(\" (\");\n            for (int i = 0; i < columns.size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                printExpr(columns.get(i));\n            }\n            print(')');\n        }\n\n        if (x.getOffset() != null) {\n            print0(ucase ? \" WITH OFFSET AS \" : \" with offset as \");\n            x.getOffset().accept(this);\n        }\n        printPivot(x.getPivot());\n        printUnpivot(x.getUnpivot());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLGeneratedTableSource x) {\n        printExpr(x.getMethodName());\n        print('(');\n        List<SQLExpr> items = x.getItems();\n        printAndAccept(items, \", \");\n        print(')');\n\n        final List<SQLName> columns = x.getColumns();\n        final String alias = x.getAlias();\n        if (alias != null) {\n            if (columns.size() > 0) {\n                print0(ucase ? \" AS \" : \" as \");\n            } else {\n                print(' ');\n            }\n            print0(alias);\n        }\n\n        if (columns.size() > 0) {\n            print0(\" (\");\n            for (int i = 0; i < columns.size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                printExpr(columns.get(i));\n            }\n            print(')');\n        }\n        printPivot(x.getPivot());\n        printUnpivot(x.getUnpivot());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTruncateStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        print0(ucase ? \"TRUNCATE TABLE \" : \"truncate table \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printAndAccept(x.getTableSources(), \", \");\n\n        if (x.getPartitions().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartitions(), \", \");\n            print(')');\n        }\n\n        if (x.isPartitionAll()) {\n            print0(ucase ? \" PARTITION ALL\" : \" partition all\");\n        } else if (x.getPartitionsForADB().size() > 0) {\n            print0(ucase ? \" PARTITION \" : \" partition \");\n            printAndAccept(x.getPartitionsForADB(), \", \");\n        }\n\n        if (x.isDropStorage()) {\n            print0(ucase ? \" DROP STORAGE\" : \" drop storage\");\n        }\n\n        if (x.isReuseStorage()) {\n            print0(ucase ? \" REUSE STORAGE\" : \" reuse storage\");\n        }\n\n        if (x.isIgnoreDeleteTriggers()) {\n            print0(ucase ? \" IGNORE DELETE TRIGGERS\" : \" ignore delete triggers\");\n        }\n\n        if (x.isRestrictWhenDeleteTriggers()) {\n            print0(ucase ? \" RESTRICT WHEN DELETE TRIGGERS\" : \" restrict when delete triggers\");\n        }\n\n        if (x.isContinueIdentity()) {\n            print0(ucase ? \" CONTINUE IDENTITY\" : \" continue identity\");\n        }\n\n        if (x.isImmediate()) {\n            print0(ucase ? \" IMMEDIATE\" : \" immediate\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDefaultExpr x) {\n        print0(ucase ? \"DEFAULT\" : \"default\");\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLCommentStatement x) {\n    }\n\n    @Override\n    public boolean visit(SQLCommentStatement x) {\n        print0(ucase ? \"COMMENT ON \" : \"comment on \");\n        if (x.getType() != null) {\n            print0(x.getType().name());\n            print(' ');\n        }\n        x.getOn().accept(this);\n\n        print0(ucase ? \" IS \" : \" is \");\n        x.getComment().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBeginStatement x) {\n        print0(ucase ? \"BEGIN \" : \"begin \");\n        if (x.getTidbTxnMode() != null) {\n            x.getTidbTxnMode().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUseStatement x) {\n        print0(ucase ? \"USE \" : \"use \");\n        x.getDatabase().accept(this);\n        return false;\n    }\n\n    protected boolean isOdps() {\n        return DbType.odps == dbType;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddColumn x) {\n        print0(ucase ? \"ADD\" : \"add\");\n\n        if (DbType.odps == dbType || DbType.hive == dbType || DbType.spark == dbType) {\n            print0(ucase ? \" COLUMNS\" : \" columns\");\n        }\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \" IF NOT EXISTS\" : \" if not exists\");\n        }\n\n        print0(\" (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        final Boolean restrict = x.getRestrict();\n        if (restrict != null && restrict.booleanValue()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableReplaceColumn x) {\n        print0(ucase ? \"REPLACE COLUMNS (\" : \"replace columns (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropColumnItem x) {\n        print0(ucase ? \"DROP COLUMN \" : \"drop column \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        this.printAndAccept(x.getColumns(), \", \");\n\n        if (x.isRestrict()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDeleteByCondition x) {\n        printUcase(\"DELETE WHERE \");\n        x.getWhere().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLAlterTableAddColumn x) {\n    }\n\n    @Override\n    public boolean visit(SQLDropIndexStatement x) {\n        print0(ucase ? \"DROP INDEX \" : \"drop index \");\n        x.getIndexName().accept(this);\n\n        SQLExprTableSource table = x.getTableName();\n        if (table != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            table.accept(this);\n        }\n\n        SQLExpr algorithm = x.getAlgorithm();\n        if (algorithm != null) {\n            print0(ucase ? \" ALGORITHM \" : \" algorithm \");\n            algorithm.accept(this);\n        }\n\n        SQLExpr lockOption = x.getLockOption();\n        if (lockOption != null) {\n            print0(ucase ? \" LOCK \" : \" lock \");\n            lockOption.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropLogFileGroupStatement x) {\n        print0(ucase ? \"DROP LOGFILE GROUP \" : \"drop logfile group \");\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropServerStatement x) {\n        print0(ucase ? \"DROP SERVER \" : \"drop server \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropTypeStatement x) {\n        print0(ucase ? \"DROP TYPE \" : \"drop type \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropSynonymStatement x) {\n        if (x.isPublic()) {\n            print0(ucase ? \"DROP PUBLIC SYNONYM \" : \"drop public synonym \");\n        } else {\n            print0(ucase ? \"DROP SYNONYM \" : \"drop synonym \");\n        }\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.isForce()) {\n            print0(ucase ? \" FORCE\" : \" force\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSavePointStatement x) {\n        print0(ucase ? \"SAVEPOINT\" : \"savepoint\");\n        SQLExpr name = x.getName();\n        if (name != null) {\n            print(' ');\n            name.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLReleaseSavePointStatement x) {\n        print0(ucase ? \"RELEASE SAVEPOINT \" : \"release savepoint \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRollbackStatement x) {\n        print0(ucase ? \"ROLLBACK\" : \"rollback\");\n        if (x.getTo() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            x.getTo().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLCommentHint x) {\n        if (x.hasBeforeComment() && !parameterized) {\n            printlnComment(x.getBeforeCommentsDirect());\n            println();\n        }\n        print0(\"/*\");\n        print0(x.getText());\n        print0(\"*/\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateDatabaseStatement x) {\n        if (x.getHeadHintsDirect() != null) {\n            for (SQLCommentHint hint : x.getHeadHintsDirect()) {\n                hint.accept(this);\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        if (x.isPhysical()) {\n            print0(ucase ? \"PHYSICAL \" : \"physical \");\n        }\n\n        print0(ucase ? \"DATABASE \" : \"database \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        x.getName().accept(this);\n\n        if (x.getCharacterSet() != null) {\n            print0(ucase ? \" CHARACTER SET \" : \" character set \");\n            print0(x.getCharacterSet());\n        }\n\n        final String collate = x.getCollate();\n        if (collate != null) {\n            print0(ucase ? \" COLLATE \" : \" collate \");\n            print0(collate);\n        }\n\n        final SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            printExpr(comment, false);\n        }\n\n        final SQLExpr location = x.getLocation();\n        if (location != null) {\n            print0(ucase ? \" LOCATION \" : \" location \");\n            printExpr(location, false);\n        }\n\n        if (x.getDbProperties().size() > 0) {\n            if (dbType == DbType.mysql\n                    || dbType == DbType.ads\n                    || dbType == DbType.mariadb) {\n                println();\n                print0(ucase ? \"WITH (\" : \"with (\");\n            } else if (dbType == DbType.hive || dbType == DbType.presto || dbType == DbType.trino || dbType == DbType.supersql || dbType == DbType.spark) {\n                println();\n                print0(ucase ? \"WITH DBPROPERTIES (\" : \"with dbproperties (\");\n            } else {\n                println();\n                print0(ucase ? \"WITH PROPERTIES (\" : \"with properties (\");\n            }\n            incrementIndent();\n            println();\n            printlnAndAccept(x.getDbProperties(), \",\");\n            decrementIndent();\n            println();\n            print(')');\n        }\n\n        if (x.getUser() != null) {\n            print0(ucase ? \" FOR \" : \" for \");\n            print0(\"'\" + x.getUser() + \"'\");\n        }\n\n        if (x.getOptions().size() > 0) {\n            print0(ucase ? \" OPTIONS (\" : \" options (\");\n            for (Map.Entry<String, SQLExpr> option : x.getOptions().entrySet()) {\n                print0(option.getKey());\n                print0(\"=\");\n                printExpr(option.getValue(), false);\n                print0(\" \");\n            }\n            print(')');\n        }\n\n        final List<List<SQLAssignItem>> storedBy = x.getStoredBy();\n        if (!storedBy.isEmpty()) {\n            println();\n            print0(ucase ? \"STORED BY \" : \"stored by \");\n\n            incrementIndent();\n            for (int i = 0; i < storedBy.size(); i++) {\n                List<SQLAssignItem> items = storedBy.get(i);\n                if (i != 0) {\n                    print(',');\n                    println();\n                }\n                print('(');\n                printAndAccept(items, \", \");\n                print(')');\n            }\n            decrementIndent();\n        }\n\n        final SQLExpr storedIn = x.getStoredIn();\n        if (storedIn != null) {\n            println();\n            print0(ucase ? \"STORED IN \" : \"stored in \");\n            printExpr(storedIn);\n\n            final List<SQLAssignItem> storedOn = x.getStoredOn();\n            if (storedOn.size() > 0) {\n                print0(ucase ? \" ON (\" : \" on (\");\n                printAndAccept(storedOn, \", \");\n                print(')');\n            }\n        }\n\n        final SQLExpr storedAs = x.getStoredAs();\n        if (storedAs != null) {\n            println();\n            print0(ucase ? \"STORED AS \" : \"stored as \");\n            printExpr(storedAs);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCreateTableGroupStatement x) {\n        print0(ucase ? \"CREATE TABLEGROUP \" : \"create tablegroup \");\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        x.getName().accept(this);\n\n        SQLExpr partitionNum = x.getPartitionNum();\n        if (partitionNum != null) {\n            print0(ucase ? \" PARTITION NUM \" : \" partition num \");\n            printExpr(partitionNum);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLDropTableGroupStatement x) {\n        print0(ucase ? \"DROP TABLEGROUP \" : \"drop tablegroup \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableGroupStatement x) {\n        print0(ucase ? \"ALTER TABLEGROUP \" : \"alter tablegroup \");\n        x.getName().accept(this);\n        print0(\" \");\n        printAndAccept(x.getOptions(), \" \");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterSystemGetConfigStatement x) {\n        print0(ucase ? \"ALTER SYSTEM GET CONFIG \" : \"alter system get config \");\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterSystemSetConfigStatement x) {\n        print0(ucase ? \"ALTER SYSTEM SET CONFIG \" : \"alter system set config \");\n\n        printAndAccept(x.getOptions(), \" \");\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterViewStatement x) {\n        print0(ucase ? \"ALTER \" : \"alter \");\n\n        this.indentCount++;\n        String algorithm = x.getAlgorithm();\n        if (algorithm != null && algorithm.length() > 0) {\n            print0(ucase ? \"ALGORITHM = \" : \"algorithm = \");\n            print0(algorithm);\n            println();\n        }\n\n        SQLName definer = x.getDefiner();\n        if (definer != null) {\n            print0(ucase ? \"DEFINER = \" : \"definer = \");\n            definer.accept(this);\n            println();\n        }\n\n        String sqlSecurity = x.getSqlSecurity();\n        if (sqlSecurity != null && sqlSecurity.length() > 0) {\n            print0(ucase ? \"SQL SECURITY \" : \"sql security \");\n            print0(sqlSecurity);\n            println();\n        }\n\n        this.indentCount--;\n\n        print0(ucase ? \"VIEW \" : \"view \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        x.getTableSource().accept(this);\n\n        List<SQLTableElement> columns = x.getColumns();\n        if (columns.size() > 0) {\n            print0(\" (\");\n            this.indentCount++;\n            println();\n            for (int i = 0; i < columns.size(); ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                    println();\n                }\n                columns.get(i).accept(this);\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        printComment(x.getComment());\n\n        println();\n        print0(ucase ? \"AS\" : \"as\");\n        println();\n\n        SQLSelect subQuery = x.getSubQuery();\n        if (subQuery != null) {\n            subQuery.accept(this);\n        }\n\n        if (x.isWithCheckOption()) {\n            println();\n            print0(ucase ? \"WITH CHECK OPTION\" : \"with check option\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateViewStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n        if (x.isOrReplace()) {\n            print0(ucase ? \"OR REPLACE \" : \"or replace \");\n        }\n\n        this.indentCount++;\n        String algorithm = x.getAlgorithm();\n        if (algorithm != null && algorithm.length() > 0) {\n            print0(ucase ? \"ALGORITHM = \" : \"algorithm = \");\n            print0(algorithm);\n            println();\n        }\n\n        SQLName definer = x.getDefiner();\n        if (definer != null) {\n            print0(ucase ? \"DEFINER = \" : \"definer = \");\n            definer.accept(this);\n            println();\n        }\n\n        String sqlSecurity = x.getSqlSecurity();\n        if (sqlSecurity != null && sqlSecurity.length() > 0) {\n            print0(ucase ? \"SQL SECURITY \" : \"sql security \");\n            print0(sqlSecurity);\n            println();\n        }\n\n        this.indentCount--;\n        if (x.isTemporary()) {\n            print0(ucase ? \"TEMP \" : \"temp \");\n        }\n        print0(ucase ? \"VIEW \" : \"view \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        x.getTableSource().accept(this);\n\n        if (x.isOnCluster()) {\n            print0(ucase ? \" ON CLUSTER\" : \" on cluster\");\n        }\n\n        SQLName to = x.getTo();\n        if (to != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            to.accept(this);\n        }\n\n        List<SQLTableElement> columns = x.getColumns();\n        if (columns.size() > 0) {\n            print0(\" (\");\n            this.indentCount++;\n            println();\n            for (int i = 0; i < columns.size(); ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                    println();\n                }\n                columns.get(i).accept(this);\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        printComment(x.getComment());\n\n        printCreateViewAs(x);\n\n        if (x.isWithCheckOption()) {\n            println();\n            print0(ucase ? \"WITH CHECK OPTION\" : \"with check option\");\n        }\n\n        return false;\n    }\n\n    protected void printCreateViewAs(SQLCreateViewStatement x) {\n        println();\n        print0(ucase ? \"AS\" : \"as\");\n        println();\n\n        SQLSelect subQuery = x.getSubQuery();\n        if (subQuery != null) {\n            subQuery.accept(this);\n        }\n\n        SQLBlockStatement script = x.getScript();\n        if (script != null) {\n            script.accept(this);\n        }\n    }\n\n    public boolean visit(SQLCreateViewStatement.Column x) {\n        x.getExpr().accept(this);\n\n        SQLCharExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropIndex x) {\n        print0(ucase ? \"DROP INDEX \" : \"drop index \");\n        x.getIndexName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOver x) {\n        print0(ucase ? \"(\" : \"(\");\n        if (x.getPartitionBy().size() > 0) {\n            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n            printAndAccept(x.getPartitionBy(), \", \");\n            print(' ');\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            orderBy.accept(this);\n        }\n\n        SQLOrderBy distributeBy = x.getDistributeBy();\n        if (distributeBy != null) {\n            List<SQLSelectOrderByItem> items = distributeBy.getItems();\n\n            if (items.size() > 0) {\n                print0(ucase ? \"DISTRIBUTE BY \" : \"distribute by \");\n\n                for (int i = 0, size = items.size(); i < size; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                    }\n                    SQLSelectOrderByItem item = items.get(i);\n                    visit(item);\n                }\n            }\n        }\n\n        SQLOrderBy sortBy = x.getSortBy();\n        if (sortBy != null) {\n            List<SQLSelectOrderByItem> items = sortBy.getItems();\n\n            if (items.size() > 0) {\n                if (distributeBy != null) {\n                    print0(\" \");\n                }\n                print0(ucase ? \"SORT BY \" : \"sort by \");\n\n                for (int i = 0, size = items.size(); i < size; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                    }\n                    SQLSelectOrderByItem item = items.get(i);\n                    visit(item);\n                }\n            }\n        }\n\n        if (x.getOf() != null) {\n            print0(ucase ? \" OF \" : \" of \");\n            x.getOf().accept(this);\n        }\n\n//        if (x.getWindowing() != null) {\n//            if (SQLOver.WindowingType.ROWS.equals(x.getWindowingType())) {\n//                print0(ucase ? \" ROWS\" : \" rows\");\n//            } else if (SQLOver.WindowingType.RANGE.equals(x.getWindowingType())) {\n//                print0(ucase ? \" RANGE\" : \" range\");\n//            }\n//\n//            printWindowingExpr(x.getWindowing());\n//\n//            if (x.isWindowingPreceding()) {\n//                print0(ucase ? \" PRECEDING\" : \" preceding\");\n//            } else if (x.isWindowingFollowing()) {\n//                print0(ucase ? \" FOLLOWING\" : \" following\");\n//            }\n//        }\n\n        final SQLExpr windowingBetweenBegin = x.getWindowingBetweenBegin();\n        final SQLExpr windowingBetweenEnd = x.getWindowingBetweenEnd();\n        final SQLOver.WindowingBound beginBound = x.getWindowingBetweenBeginBound();\n        final SQLOver.WindowingBound endBound = x.getWindowingBetweenEndBound();\n        final SQLOver.WindowingType windowingType = x.getWindowingType();\n\n        if (windowingBetweenEnd != null || endBound != null) {\n            if (windowingType != null) {\n                print(' ');\n                print0(ucase ? windowingType.name : windowingType.nameLCase);\n            }\n            print0(ucase ? \" BETWEEN\" : \" between\");\n\n            printWindowingExpr(windowingBetweenBegin);\n\n            if (beginBound != null) {\n                print(' ');\n                print0(ucase ? beginBound.name : beginBound.nameLCase);\n            }\n\n            print0(ucase ? \" AND\" : \" and\");\n\n            printWindowingExpr(windowingBetweenEnd);\n\n            if (endBound != null) {\n                print(' ');\n                print0(ucase ? endBound.name : endBound.nameLCase);\n            }\n        } else {\n            if (windowingType != null) {\n                print(' ');\n                print0(ucase ? windowingType.name : windowingType.nameLCase);\n            }\n\n            printWindowingExpr(windowingBetweenBegin);\n\n            if (beginBound != null) {\n                print(' ');\n                print0(ucase ? beginBound.name : beginBound.nameLCase);\n            }\n        }\n\n        if (x.isExcludeCurrentRow()) {\n            print0(ucase ? \" EXCLUDE CURRENT ROW\" : \" exclude current row\");\n        }\n\n        print(')');\n        return false;\n    }\n\n    void printWindowingExpr(SQLExpr expr) {\n        if (expr == null) {\n            return;\n        }\n        print(' ');\n        if (expr instanceof SQLIdentifierExpr) {\n            String ident = ((SQLIdentifierExpr) expr).getName();\n            print0(ucase ? ident : ident.toLowerCase());\n        } else {\n            expr.accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLKeep x) {\n        if (x.getDenseRank() == SQLKeep.DenseRank.FIRST) {\n            print0(ucase ? \"KEEP (DENSE_RANK FIRST \" : \"keep (dense_rank first \");\n        } else {\n            print0(ucase ? \"KEEP (DENSE_RANK LAST \" : \"keep (dense_rank last \");\n        }\n\n        x.getOrderBy().accept(this);\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLColumnPrimaryKey x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n        print0(ucase ? \"PRIMARY KEY\" : \"primary key\");\n        if (x.isNotEnforced()) {\n            print0(ucase ? \" NOT ENFORCED\" : \" not enforced\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLColumnUniqueKey x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n        print0(ucase ? \"UNIQUE\" : \"unique\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLColumnCheck x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n        print0(ucase ? \"CHECK \" : \"check \");\n        x.getExpr().accept(this);\n        print(\"\");\n\n        Boolean enable = x.getEnable();\n        if (enable != null) {\n            if (enable.booleanValue()) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            } else {\n                print0(ucase ? \" DISABLE\" : \" disable\");\n            }\n        }\n\n        Boolean enforced = x.getEnforced();\n        if (enforced != null) {\n            if (enforced.booleanValue()) {\n                print0(ucase ? \" ENFORCED\" : \" enforced\");\n            } else {\n                print0(ucase ? \" NOT ENFORCED\" : \" not enforced\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLColumnDefault x) {\n        print0(ucase ? \"DEFAULT \" : \"default \");\n        x.getDefaultExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLWithSubqueryClause x) {\n        if ((!isParameterized()) && isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"WITH \" : \"with \");\n        if (Boolean.TRUE.equals(x.getRecursive())) {\n            print0(ucase ? \"RECURSIVE \" : \"recursive \");\n        }\n        this.indentCount++;\n        printlnAndAccept(x.getEntries(), \",\");\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLWithSubqueryClause.Entry x) {\n        if (isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(x.getAlias());\n\n        if (x.getColumns().size() > 0) {\n            print0(\" (\");\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n        print(' ');\n        print0(ucase ? \"AS \" : \"as \");\n        print('(');\n        this.indentCount++;\n        println();\n        SQLSelect query = x.getSubQuery();\n        if (query != null) {\n            query.accept(this);\n        } else {\n            x.getReturningStatement().accept(this);\n        }\n        this.indentCount--;\n        println();\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableModifyClusteredBy x) {\n        print0(ucase ? \"CLUSTERED BY \" : \"clustered by \");\n        if (!x.getClusterColumns().isEmpty()) {\n            printAndAccept(x.getClusterColumns(), \", \");\n        } else {\n            print0(\"()\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAlterColumn x) {\n        if (DbType.odps == dbType) {\n            print0(ucase ? \"CHANGE COLUMN\" : \"change column\");\n        } else if (DbType.hive == dbType || DbType.spark == dbType) {\n            print0(ucase ? \"CHANGE\" : \"change\");\n        } else {\n            print0(ucase ? \"ALTER COLUMN\" : \"alter column\");\n        }\n\n        SQLName originColumn = x.getOriginColumn();\n        if (originColumn != null) {\n            print(' ');\n            originColumn.accept(this);\n        }\n\n        SQLColumnDefinition column = x.getColumn();\n        if (column != null) {\n            print(' ');\n            column.accept(this);\n        }\n\n        if (x.isSetNotNull()) { // postgresql\n            print0(ucase ? \" SET NOT NULL\" : \" set not null\");\n        }\n\n        if (x.isDropNotNull()) { // postgresql\n            print0(ucase ? \" DROP NOT NULL\" : \" drop not null\");\n        }\n\n        if (x.getSetDefault() != null) { // postgresql\n            print0(ucase ? \" SET DEFAULT \" : \" set default \");\n            x.getSetDefault().accept(this);\n        }\n\n        if (x.isDropDefault()) { // postgresql\n            print0(ucase ? \" DROP DEFAULT\" : \" drop default\");\n        }\n\n        final SQLDataType dataType = x.getDataType();\n        if (dataType != null) {\n            print0(ucase ? \" SET DATA TYPE \" : \" set data type \");\n            dataType.accept(this);\n        }\n\n        final SQLName after = x.getAfter();\n        if (after != null) {\n            print0(ucase ? \" AFTER \" : \" after \");\n            after.accept(this);\n        }\n\n        if (x.isFirst()) {\n            print0(ucase ? \" FIRST\" : \" first\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCheck x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"CHECK \" : \"check \");\n        this.indentCount++;\n        x.getExpr().accept(this);\n        this.indentCount--;\n        print(\"\");\n\n        Boolean enforced = x.getEnforced();\n        if (enforced != null) {\n            if (enforced.booleanValue()) {\n                print0(ucase ? \" ENFORCED\" : \" enforced\");\n            } else {\n                print0(ucase ? \" NOT ENFORCED\" : \" not enforced\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDefault x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"DEFAULT \" : \"default \");\n        this.indentCount++;\n        x.getExpr().accept(this);\n        this.indentCount--;\n\n        print0(ucase ? \" FOR \" : \" for \");\n\n        this.indentCount++;\n        x.getColumn().accept(this);\n        this.indentCount--;\n\n        if (x.isWithValues()) {\n            print0(ucase ? \" WITH VALUES\" : \" with values\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropForeignKey x) {\n        print0(ucase ? \"DROP FOREIGN KEY \" : \"drop foreign key \");\n        x.getIndexName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropPrimaryKey x) {\n        print0(ucase ? \"DROP PRIMARY KEY\" : \"drop primary key\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropKey x) {\n        print0(ucase ? \"DROP KEY \" : \"drop key \");\n        x.getKeyName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTablePartitionCount x) {\n        print0(ucase ? \"PARTITIONS \" : \"partitons \");\n        x.getCount().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableBlockSize x) {\n        print0(ucase ? \"BLOCK_SIZE \" : \"block_size \");\n        x.getSize().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableEnableKeys x) {\n        print0(ucase ? \"ENABLE KEYS\" : \"enable keys\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDisableKeys x) {\n        print0(ucase ? \"DISABLE KEYS\" : \"disable keys\");\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableDisableConstraint x) {\n        print0(ucase ? \"DISABLE CONSTRAINT \" : \"disable constraint \");\n        x.getConstraintName().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableEnableConstraint x) {\n        print0(ucase ? \"ENABLE CONSTRAINT \" : \"enable constraint \");\n        x.getConstraintName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropConstraint x) {\n        print0(ucase ? \"DROP CONSTRAINT \" : \"drop constraint \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        x.getConstraintName().accept(this);\n\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        } else if (x.isRestrict()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n        return false;\n    }\n    @Override\n    public boolean visit(SQLAlterTableDropCheck x) {\n        print0(ucase ? \"DROP CHECK \" : \"drop check \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        x.getCheckName().accept(this);\n        return false;\n    }\n    @Override\n    public boolean visit(SQLAlterTableValidateConstraint x) {\n        print0(ucase ? \"VALIDATE CONSTRAINT \" : \"validate constraint \");\n        x.getConstraintName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableStatement x) {\n        print0(ucase ? \"ALTER TABLE \" : \"alter table \");\n\n        if (x.isOnly()) {\n            print0(ucase ? \"ONLY \" : \"only \");\n        }\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        printTableSourceExpr(x.getName());\n\n        SQLName on = x.getOn();\n        if (on != null) {\n            print(ucase ? \" ON CLUSTER \" : \" on cluster \");\n            printExpr(on);\n        }\n\n        this.indentCount++;\n        for (int i = 0; i < x.getItems().size(); ++i) {\n            SQLAlterTableItem item = x.getItems().get(i);\n            if (i != 0) {\n                SQLAlterTableItem former = x.getItems().get(i - 1);\n                if ((this.dbType == DbType.hive || this.dbType == DbType.odps || this.dbType == DbType.spark)\n                        && former instanceof SQLAlterTableAddPartition\n                        && item instanceof SQLAlterTableAddPartition) {\n                    // ignore comma\n                } else {\n                    print(',');\n                }\n            }\n            println();\n            item.accept(this);\n        }\n        this.indentCount--;\n\n        if (x.isMergeSmallFiles()) {\n            print0(ucase ? \" MERGE SMALLFILES\" : \" merge smallfiles\");\n        }\n\n        List<SQLSelectOrderByItem> clusteredBy = x.getClusteredBy();\n        if (clusteredBy.size() > 0) {\n            println();\n            if (x.isRange()) {\n                print0(ucase ? \"RANGE \" : \"range \");\n            }\n            print0(ucase ? \"CLUSTERED BY (\" : \"clustered by (\");\n            printAndAccept(clusteredBy, \",\");\n            print0(\")\");\n        }\n\n        List<SQLSelectOrderByItem> sortedBy = x.getSortedBy();\n        printSortedBy(sortedBy);\n        printIntoBuckets(x.getBuckets());\n        printIntoShards(x.getShards());\n\n        if (x.isNotClustered()) {\n            print0(ucase ? \" NOT CLUSTERED\" : \" not clustered\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExprHint x) {\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateIndexStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        String type = x.getType();\n\n        if (type != null) {\n            print0(ucase ? type.toUpperCase() : type.toLowerCase());\n            print(' ');\n        }\n\n        if (x.isGlobal()) {\n            print0(ucase ? \"GLOBAL \" : \"global \");\n        }\n\n        if (x.isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        print0(ucase ? \"INDEX \" : \"index \");\n\n        x.getName().accept(this);\n        print0(ucase ? \" ON \" : \" on \");\n        x.getTable().accept(this);\n        print0(\" (\");\n        printAndAccept(x.getItems(), \", \");\n        print(')');\n\n        List<SQLName> covering = x.getCovering();\n        if (covering.size() > 0) {\n            print0(ucase ? \" COVERING (\" : \" covering (\");\n            printAndAccept(covering, \", \");\n            print(')');\n        }\n\n        final SQLExpr dbPartitionBy = x.getDbPartitionBy();\n        if (dbPartitionBy != null) {\n            print0(ucase ? \" DBPARTITION BY \" : \" dbpartition by \");\n            dbPartitionBy.accept(this);\n        }\n\n        final SQLExpr tablePartitionBy = x.getTablePartitionBy();\n        if (tablePartitionBy != null) {\n            print0(ucase ? \" TBPARTITION BY \" : \" tbpartition by \");\n            tablePartitionBy.accept(this);\n        }\n\n        SQLExpr tablePartitions = x.getTablePartitions();\n        if (tablePartitions != null) {\n            print0(ucase ? \" TBPARTITIONS \" : \" tbpartitions \");\n            tablePartitions.accept(this);\n        }\n\n        if (x.getIndexDefinition().hasOptions()) {\n            String using = x.getIndexDefinition().getOptions().getIndexType();\n            if (using != null) {\n                print0(ucase ? \" USING \" : \" using \");\n                print0(ucase ? using.toUpperCase() : using.toLowerCase());\n            }\n\n            x.getIndexDefinition().getOptions().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnique x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n        print0(ucase ? \"UNIQUE (\" : \"unique (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n        if (x.isDisableNovalidate()) {\n            print0(ucase ? \" DISABLE NOVALIDATE\" : \" disable novalidate\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPrimaryKeyImpl x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"PRIMARY KEY \" : \"primary key \");\n\n        if (x.isClustered()) {\n            print0(ucase ? \"CLUSTERED \" : \"clustered \");\n        }\n\n        print('(');\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        if (x.isDisableNovalidate()) {\n            print0(ucase ? \" DISABLE NOVALIDATE\" : \" disable novalidate\");\n        }\n\n        if (x.isNotEnforced()) {\n            print0(ucase ? \" NOT ENFORCED\" : \" not enforced\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRenameColumn x) {\n        print0(ucase ? \"RENAME COLUMN \" : \"rename column \");\n        x.getColumn().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRenameConstraint x) {\n        print0(ucase ? \"RENAME CONSTRAINT \" : \"rename constraint \");\n        x.getConstraint().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLColumnReference x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"REFERENCES \" : \"references \");\n        x.getTable().accept(this);\n        if (!x.getColumns().isEmpty()) {\n            print0(\" (\");\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        if (x.isNotEnforced()) {\n            print0(ucase ? \" NOT ENFORCED\" : \" not enforced\");\n        }\n        SQLForeignKeyImpl.Match match = x.getReferenceMatch();\n        if (match != null) {\n            print0(ucase ? \" MATCH \" : \" match \");\n            print0(ucase ? match.name : match.nameLCase);\n        }\n\n        if (x.getOnDelete() != null) {\n            print0(ucase ? \" ON DELETE \" : \" on delete \");\n            print0(ucase ? x.getOnDelete().name : x.getOnDelete().nameLCase);\n        }\n\n        if (x.getOnUpdate() != null) {\n            print0(ucase ? \" ON UPDATE \" : \" on update \");\n            print0(ucase ? x.getOnUpdate().name : x.getOnUpdate().nameLCase);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLForeignKeyImpl x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            name.accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"FOREIGN KEY (\" : \"foreign key (\");\n        printAndAccept(x.getReferencingColumns(), \", \");\n        print(')');\n\n        this.indentCount++;\n        println();\n        print0(ucase ? \"REFERENCES \" : \"references \");\n        x.getReferencedTableName().accept(this);\n\n        if (x.getReferencedColumns().size() > 0) {\n            print0(\" (\");\n            printAndAccept(x.getReferencedColumns(), \", \");\n            print(')');\n        }\n\n        if (x.isOnDeleteCascade()) {\n            println();\n            print0(ucase ? \"ON DELETE CASCADE\" : \"on delete cascade\");\n        } else if (x.isOnDeleteSetNull()) {\n            print0(ucase ? \"ON DELETE SET NULL\" : \"on delete set null\");\n        }\n\n        if (x.isDisableNovalidate()) {\n            print0(ucase ? \" DISABLE NOVALIDATE\" : \" disable novalidate\");\n        }\n\n        if (x.isNotEnforced()) {\n            print0(ucase ? \" NOT ENFORCED\" : \" not enforced\");\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropSequenceStatement x) {\n        print0(ucase ? \"DROP SEQUENCE \" : \"drop sequence \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLDropSequenceStatement x) {\n    }\n\n    @Override\n    public boolean visit(SQLDropTriggerStatement x) {\n        print0(ucase ? \"DROP TRIGGER \" : \"drop trigger \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLDropUserStatement x) {\n    }\n\n    @Override\n    public boolean visit(SQLDropUserStatement x) {\n        print0(ucase ? \"DROP USER \" : \"drop user \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        printAndAccept(x.getUsers(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCancelJobStatement x) {\n        print0(ucase ? \"CANCEL JOB \" : \"cancel job \");\n        x.getJobName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExplainAnalyzeStatement x) {\n        print0(ucase ? \"EXPLAIN ANALYZE \" : \"explain analyze \");\n        println();\n        x.getSelect().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExplainStatement x) {\n        print0(ucase ? \"EXPLAIN\" : \"explain\");\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            print(' ');\n            printAndAccept(x.getHints(), \" \");\n        }\n\n        if (x.isExtended()) {\n            print0(ucase ? \" EXTENDED\" : \" extended\");\n        }\n\n        if (x.isDependency()) {\n            print0(ucase ? \" DEPENDENCY\" : \" dependency\");\n        }\n\n        if (x.isAuthorization()) {\n            print0(ucase ? \" AUTHORIZATION\" : \" authorization\");\n        }\n\n        String type = x.getType();\n        if (type != null) {\n            print(' ');\n            if (type.indexOf(' ') >= 0) {\n                print('(');\n                print0(type);\n                print(')');\n            } else {\n                print0(type);\n            }\n        }\n        println();\n        x.getStatement().accept(this);\n        return false;\n    }\n\n    protected void printGrantPrivileges(SQLGrantStatement x) {\n    }\n\n    @Override\n    public boolean visit(SQLGrantStatement x) {\n        print0(ucase ? \"GRANT \" : \"grant \");\n        printAndAccept(x.getPrivileges(), \", \");\n\n        printGrantOn(x);\n\n        if (x.getUsers() != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            printAndAccept(x.getUsers(), \",\");\n        }\n\n        if (x.getWithGrantOption()) {\n            print0(ucase ? \" WITH GRANT OPTION\" : \" with grant option\");\n        }\n\n        boolean with = false;\n        SQLExpr maxQueriesPerHour = x.getMaxQueriesPerHour();\n        if (maxQueriesPerHour != null) {\n            if (!with) {\n                print0(ucase ? \" WITH\" : \" with\");\n                with = true;\n            }\n            print0(ucase ? \" MAX_QUERIES_PER_HOUR \" : \" max_queries_per_hour \");\n            maxQueriesPerHour.accept(this);\n        }\n\n        SQLExpr maxUpdatesPerHour = x.getMaxUpdatesPerHour();\n        if (maxUpdatesPerHour != null) {\n            if (!with) {\n                print0(ucase ? \" WITH\" : \" with\");\n                with = true;\n            }\n            print0(ucase ? \" MAX_UPDATES_PER_HOUR \" : \" max_updates_per_hour \");\n            maxUpdatesPerHour.accept(this);\n        }\n\n        SQLExpr maxConnectionsPerHour = x.getMaxConnectionsPerHour();\n        if (maxConnectionsPerHour != null) {\n            if (!with) {\n                print0(ucase ? \" WITH\" : \" with\");\n                with = true;\n            }\n            print0(ucase ? \" MAX_CONNECTIONS_PER_HOUR \" : \" max_connections_per_hour \");\n            maxConnectionsPerHour.accept(this);\n        }\n\n        SQLExpr maxUserConnections = x.getMaxUserConnections();\n        if (maxUserConnections != null) {\n            if (!with) {\n                print0(ucase ? \" WITH\" : \" with\");\n                with = true;\n            }\n            print0(ucase ? \" MAX_USER_CONNECTIONS \" : \" max_user_connections \");\n            maxUserConnections.accept(this);\n        }\n\n        if (x.isAdminOption()) {\n            if (!with) {\n                print0(ucase ? \" WITH\" : \" with\");\n                with = true;\n            }\n            print0(ucase ? \" ADMIN OPTION\" : \" admin option\");\n        }\n\n        if (x.getIdentifiedBy() != null) {\n            print0(ucase ? \" IDENTIFIED BY \" : \" identified by \");\n            x.getIdentifiedBy().accept(this);\n        }\n\n        return false;\n    }\n\n    protected void printGrantOn(SQLGrantStatement x) {\n        if (x.getResource() != null) {\n            print0(ucase ? \" ON \" : \" on \");\n\n            SQLObjectType resourceType = x.getResourceType();\n            if (resourceType != null) {\n                print0(ucase ? resourceType.name : resourceType.nameLCase);\n                print(' ');\n            }\n\n            x.getResource().accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLRevokeStatement x) {\n        print0(ucase ? \"REVOKE \" : \"revoke \");\n\n        if (x.isGrantOption()) {\n            print0(ucase ? \"GRANT OPTION\" : \"grant option\");\n\n            if (x.getPrivileges().size() > 0) {\n                print0(ucase ? \" FOR \" : \" for \");\n            }\n        }\n\n        printAndAccept(x.getPrivileges(), \", \");\n\n        if (x.getResource() != null) {\n            print0(ucase ? \" ON \" : \" on \");\n\n            if (x.getResourceType() != null) {\n                print0(x.getResourceType().name());\n                print(' ');\n            }\n\n            x.getResource().accept(this);\n        }\n\n        if (x.getUsers() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n\n            if (dbType == DbType.odps) {\n                print0(ucase ? \"USER \" : \"user \");\n            }\n\n            printAndAccept(x.getUsers(), \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropDatabaseStatement x) {\n        print0(ucase ? \"DROP \" : \"drop \");\n\n        if (x.isPhysical()) {\n            print0(ucase ? \"PHYSICAL \" : \"physical \");\n        }\n\n        print0(ucase ? \"DATABASE \" : \"database \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getDatabase().accept(this);\n\n        final Boolean restrict = x.getRestrict();\n        if (restrict != null && restrict.booleanValue()) {\n            print0(ucase ? \" RESTRICT\" : \" restrict\");\n        }\n\n        if (x.isCascade()) {\n            print0(ucase ? \" CASCADE\" : \" cascade\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropCatalogStatement x) {\n        if (x.isExternal()) {\n            print0(ucase ? \"DROP EXTERNAL CATALOG \" : \"drop external catalog \");\n        } else {\n            print0(ucase ? \"DROP CATALOG \" : \"drop catalog \");\n        }\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropFunctionStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                visit((SQLCommentHint) hint);\n                println();\n            }\n        }\n\n        if (x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        if (x.isTemporary()) {\n            print0(ucase ? \"DROP TEMPORARY FUNCTION \" : \"drop temporary function \");\n        } else {\n            print0(ucase ? \"DROP FUNCTION \" : \"drop function \");\n        }\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getName().accept(this);\n        if (x.getParameters() != null) {\n            print0(\"(\");\n            int paramSize = x.getParameters().size();\n            if (paramSize > 0) {\n                this.indentCount++;\n                println();\n                for (int i = 0; i < paramSize; ++i) {\n                    if (i != 0) {\n                        print0(\", \");\n                        println();\n                    }\n                    SQLParameter param = x.getParameters().get(i);\n                    param.accept(this);\n                }\n                this.indentCount--;\n                println();\n            }\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropTableSpaceStatement x) {\n        print0(ucase ? \"DROP TABLESPACE \" : \"drop tablespace \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getName().accept(this);\n\n        SQLExpr engine = x.getEngine();\n        if (engine != null) {\n            print0(ucase ? \" ENGINE \" : \" engine \");\n            engine.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropProcedureStatement x) {\n        print0(ucase ? \"DROP PROCEDURE \" : \"drop procedure \");\n\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n\n        x.getName().accept(this);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIndexOptions x) {\n        /*\n        String using = x.getIndexType();\n        if (using != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(using);\n        }\n        */\n        if (x.isGlobal()) {\n            print0(ucase ? \" GLOBAL\" : \" global\");\n        } else if (x.isLocal()) {\n            print0(ucase ? \" LOCAL\" : \" local\");\n        }\n\n        if (x.isInvisible()) {\n            print0(ucase ? \" INVISIBLE\" : \" invisible\");\n        } else if (x.isVisible()) {\n            print0(ucase ? \" VISIBLE\" : \" visible\");\n        }\n\n        SQLExpr keyBlockSize = x.getKeyBlockSize();\n        if (keyBlockSize != null) {\n            print0(ucase ? \" KEY_BLOCK_SIZE = \" : \" key_block_size = \");\n            printExpr(keyBlockSize, parameterized);\n        }\n\n        String parserName = x.getParserName();\n        if (parserName != null) {\n            print0(ucase ? \" WITH PARSER \" : \" with parser \");\n            print0(parserName);\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            printExpr(comment, parameterized);\n        }\n\n        String algorithm = x.getAlgorithm();\n        if (algorithm != null) {\n            print0(ucase ? \" ALGORITHM = \" : \" algorithm = \");\n            print0(algorithm);\n        }\n\n        String lock = x.getLock();\n        if (lock != null) {\n            print0(ucase ? \" LOCK = \" : \" lock = \");\n            print0(lock);\n        }\n\n        final List<SQLAssignItem> options = x.getOtherOptions();\n        if (options.size() > 0) {\n            for (SQLAssignItem option : options) {\n                print(' ');\n                option.accept(this);\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIndexDefinition x) {\n        /*\n        if (x.hasConstraint()) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            if (x.getSymbol() != null) {\n                x.getSymbol().accept(this);\n                print(' ');\n            }\n        }\n        */\n\n        boolean mysql = DbType.mysql == dbType;\n\n        String type = x.getType();\n\n        if (type != null) {\n            print0(ucase ? type.toUpperCase() : type.toLowerCase());\n            print(' ');\n        }\n\n        if (x.isGlobal()) {\n            print0(ucase ? \"GLOBAL \" : \"global \");\n        } else if (x.isLocal()) {\n            print0(ucase ? \"LOCAL \" : \"local \");\n        }\n\n        if (x.isIndex()) {\n            print0(ucase ? \"INDEX \" : \"index \");\n        }\n\n        if (x.isKey()) {\n            print0(ucase ? \"KEY \" : \"key \");\n        }\n\n        if (x.getName() != null && (type == null || !type.equalsIgnoreCase(\"primary\"))) {\n            x.getName().accept(this);\n            print(' ');\n        }\n\n        String using = x.getOptions().getIndexType();\n        if (using != null) {\n            print0(ucase ? \"USING \" : \"using \");\n            print0(using);\n            print(' ');\n        }\n\n        if (x.isHashMapType()) {\n            print0(ucase ? \"HASHMAP \" : \"hashmap \");\n        }\n\n        if (x.getColumns().size() > 0) {\n            print('(');\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        if (x.getAnalyzerName() != null) {\n            print0(ucase ? \" WITH ANALYZER \" : \" with analyzer \");\n            x.getAnalyzerName().accept(this);\n        } else {\n            if (x.getIndexAnalyzerName() != null) {\n                print0(ucase ? \" WITH INDEX ANALYZER \" : \" with index analyzer \");\n                x.getIndexAnalyzerName().accept(this);\n            }\n\n            if (x.getQueryAnalyzerName() != null) {\n                print0(ucase ? \" WITH QUERY ANALYZER \" : \" with query analyzer \");\n                x.getQueryAnalyzerName().accept(this);\n            }\n\n            if (x.getWithDicName() != null) {\n                printUcase(\" WITH DICT \");\n                x.getWithDicName().accept(this);\n            }\n        }\n\n        List<SQLName> covering = x.getCovering();\n        if (covering.size() > 0) {\n            print0(ucase ? \" COVERING (\" : \" covering (\");\n            printAndAccept(covering, \", \");\n            print(')');\n        }\n\n        final SQLExpr dbPartitionBy = x.getDbPartitionBy();\n        if (dbPartitionBy != null) {\n            print0(ucase ? \" DBPARTITION BY \" : \" dbpartition by \");\n            dbPartitionBy.accept(this);\n        }\n\n        final SQLExpr tablePartitionBy = x.getTbPartitionBy();\n        if (tablePartitionBy != null) {\n            print0(ucase ? \" TBPARTITION BY \" : \" tbpartition by \");\n            tablePartitionBy.accept(this);\n        }\n\n        SQLExpr tablePartitions = x.getTbPartitions();\n        if (tablePartitions != null) {\n            print0(ucase ? \" TBPARTITIONS \" : \" tbpartitions \");\n            tablePartitions.accept(this);\n        }\n\n        if (x.hasOptions()) {\n            x.getOptions().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddIndex x) {\n        print0(ucase ? \"ADD \" : \"add \");\n\n        visit(x.getIndexDefinition());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAlterIndex x) {\n        print0(ucase ? \"ALTER INDEX \" : \"alter index \");\n\n        visit(x.getIndexDefinition());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddConstraint x) {\n        if (x.isWithNoCheck()) {\n            print0(ucase ? \"WITH NOCHECK \" : \"with nocheck \");\n        }\n\n        print0(ucase ? \"ADD \" : \"add \");\n\n        x.getConstraint().accept(this);\n        if (x.isNoInherit()) {\n            print0(ucase ? \" NO  INHERIT\" : \" no inherit\");\n        }\n        if (x.isNotValid()) {\n            print0(ucase ? \" NOT VALID\" : \" not valid\");\n        }\n        return false;\n    }\n\n    public boolean visit(SQLCreateTriggerStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        if (x.isOrReplace()) {\n            print0(ucase ? \"OR REPLACE \" : \"or replace \");\n        }\n\n        print0(ucase ? \"TRIGGER \" : \"trigger \");\n\n        x.getName().accept(this);\n\n        this.indentCount++;\n        println();\n        if (TriggerType.INSTEAD_OF.equals(x.getTriggerType())) {\n            print0(ucase ? \"INSTEAD OF\" : \"instead of\");\n        } else {\n            String triggerTypeName = x.getTriggerType().name();\n            print0(ucase ? triggerTypeName : triggerTypeName.toLowerCase());\n        }\n\n        if (x.isInsert()) {\n            print0(ucase ? \" INSERT\" : \" insert\");\n        }\n\n        if (x.isDelete()) {\n            if (x.isInsert()) {\n                print0(ucase ? \" OR\" : \" or\");\n            }\n            print0(ucase ? \" DELETE\" : \" delete\");\n        }\n\n        if (x.isUpdate()) {\n            if (x.isInsert() || x.isDelete()) {\n                print0(ucase ? \" OR\" : \" or\");\n            }\n            print0(ucase ? \" UPDATE\" : \" update\");\n\n            List<SQLName> colums = x.getUpdateOfColumns();\n            for (SQLName colum : colums) {\n                print(' ');\n                colum.accept(this);\n            }\n        }\n\n        println();\n        print0(ucase ? \"ON \" : \"on \");\n        x.getOn().accept(this);\n\n        if (x.isForEachRow()) {\n            println();\n            print0(ucase ? \"FOR EACH ROW\" : \"for each row\");\n        }\n\n        SQLExpr when = x.getWhen();\n        if (when != null) {\n            println();\n            print0(ucase ? \"WHEN \" : \"when \");\n            when.accept(this);\n        }\n        this.indentCount--;\n        println();\n        if (x.getExecuteType() != null && x.getExecuteFunc() != null) {\n            print0(ucase ? x.getExecuteType().toUpperCase() : x.getExecuteType().toLowerCase());\n            print0(\" \");\n            x.getExecuteFunc().accept(this);\n        }\n        if (x.getBody() != null) {\n            x.getBody().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLBooleanExpr x) {\n        if (isParameterized()) {\n            print('?');\n            return false;\n        }\n        print0(x.getBooleanValue() ? \"true\" : \"false\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnionQueryTableSource x) {\n        print('(');\n        this.indentCount++;\n        println();\n        x.getUnion().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n\n        final List<SQLName> columns = x.getColumns();\n        final String alias = x.getAlias();\n        if (alias != null) {\n            if (columns.size() > 0) {\n                print0(\" AS \");\n            } else {\n                print(' ');\n            }\n            print0(alias);\n        }\n        printPivot(x.getPivot());\n        printUnpivot(x.getUnpivot());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTimestampExpr x) {\n        if (this.parameterized) {\n            print('?');\n            incrementReplaceCunt();\n\n            if (this.parameters != null) {\n                ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n            }\n        } else {\n            print0(ucase ? \"TIMESTAMP \" : \"timestamp \");\n\n            if (x.isWithTimeZone()) {\n                print0(ucase ? \" WITH TIME ZONE \" : \" with time zone \");\n            }\n\n            print('\\'');\n            print0(x.getValue());\n            print('\\'');\n\n            if (x.getTimeZone() != null) {\n                print0(ucase ? \" AT TIME ZONE '\" : \" at time zone '\");\n                print0(x.getTimeZone());\n                print('\\'');\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBinaryExpr x) {\n        print0(\"b'\");\n        print0(x.getText());\n        print('\\'');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRename x) {\n        print0(ucase ? \"RENAME TO \" : \"rename to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowTablesStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.isFull()) {\n            print0(ucase ? \"SHOW FULL TABLES\" : \"show full tables\");\n        } else {\n            print0(ucase ? \"SHOW TABLES\" : \"show tables\");\n        }\n\n        if (x.isExtended()) {\n            print0(ucase ? \" EXTENDED\" : \" extended\");\n        }\n\n        if (x.getDatabase() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getDatabase().accept(this);\n        }\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        } else if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n        return false;\n    }\n\n    protected void printlnComment(List<String> comments) {\n        if (comments != null) {\n            for (int i = 0; i < comments.size(); ++i) {\n                String comment = comments.get(i);\n                boolean lineComment = comment.startsWith(\"--\");\n                if (lineComment) {\n                    comment = comment.trim();\n                }\n                if (i != 0 && lineComment) {\n                    println();\n                }\n\n                printComment(comment);\n            }\n        }\n    }\n\n    public void printComment(String comment) {\n        if (comment == null) {\n            return;\n        }\n\n        if (isEnabled(VisitorFeature.OutputSkipMultilineComment) && comment.startsWith(\"/*\")) {\n            return;\n        }\n\n        if (isEnabled(VisitorFeature.OutputSkipSingleLineComment)\n                && (comment.startsWith(\"-\") || comment.startsWith(\"#\"))) {\n            return;\n        }\n\n        if (comment.startsWith(\"--\")\n                && comment.length() > 2\n                && comment.charAt(2) != ' '\n                && comment.charAt(2) != '-') {\n            print0(\"-- \");\n            print0(comment.substring(2));\n        } else if (comment.startsWith(\"#\")\n                && comment.length() > 1\n                && comment.charAt(1) != ' '\n                && comment.charAt(1) != '#') {\n            print0(\"# \");\n            print0(comment.substring(1));\n        } else {\n            print0(comment);\n        }\n\n        char first = '\\0';\n        for (int i = 0; i < comment.length(); i++) {\n            char c = comment.charAt(i);\n            if (CharTypes.isWhitespace(c)) {\n                continue;\n            }\n            first = c;\n            break;\n        }\n\n        if (first == '-' || first == '#') {\n            endLineComment = true;\n        }\n    }\n\n    protected void printlnComments(List<String> comments) {\n        if (comments != null) {\n            for (int i = 0; i < comments.size(); ++i) {\n                String comment = comments.get(i);\n                printComment(comment);\n                println();\n            }\n        }\n    }\n\n    protected void printAfterComments(List<String> comments) {\n        if (comments != null) {\n            print0(\" \");\n            int i = 0;\n            String comment = comments.get(i);\n            printComment(comment);\n            i++;\n            for (; i < comments.size(); ++i) {\n                println();\n                comment = comments.get(i);\n                printComment(comment);\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLAlterViewRenameStatement x) {\n        print0(ucase ? \"ALTER VIEW \" : \"alter view \");\n        x.getName().accept(this);\n\n        SQLName to = x.getTo();\n        if (to != null) {\n            print0(ucase ? \" RENAME TO \" : \" rename to \");\n            printExpr(to);\n        }\n\n        SQLName changeOwnerTo = x.getChangeOwnerTo();\n        if (changeOwnerTo != null) {\n            print0(ucase ? \" CHANGEOWNER TO \" : \" changeowner to \");\n            printExpr(changeOwnerTo);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddPartition x) {\n        boolean printAdd = true;\n        if (x.getParent() instanceof SQLAlterTableStatement) {\n            SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n            int p = stmt.getChildren().indexOf(x);\n            if (p > 0 && stmt.getChildren().get(p - 1) instanceof SQLAlterTableAddPartition) {\n                printAdd = false;\n            }\n        }\n\n        if (printAdd) {\n            print0(ucase ? \"ADD \" : \"add \");\n\n            if (x.isIfNotExists()) {\n                print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n            }\n        } else {\n            print('\\t');\n            indentCount++;\n        }\n\n        if (x.getPartitionCount() != null) {\n            print0(ucase ? \"PARTITION PARTITIONS \" : \"partition partitions \");\n            x.getPartitionCount().accept(this);\n        }\n\n        if (x.getPartitions().size() > 0) {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartitions(), \", \");\n            print(')');\n        }\n\n        SQLExpr location = x.getLocation();\n        if (location != null) {\n            print0(ucase ? \" LOCATION \" : \" location \");\n            location.accept(this);\n        }\n\n        if (!printAdd) {\n            indentCount--;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddExtPartition x) {\n        print0(ucase ? \"ADD \" : \"add \");\n\n        MySqlExtPartition extPartition = x.getExtPartition();\n        if (extPartition != null) {\n            println();\n            extPartition.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropExtPartition x) {\n        print0(ucase ? \"DROP \" : \"drop \");\n\n        MySqlExtPartition extPartition = x.getExtPartition();\n        if (extPartition != null) {\n            println();\n            extPartition.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableReOrganizePartition x) {\n        print0(ucase ? \"REORGANIZE \" : \"reorganize \");\n\n        printAndAccept(x.getNames(), \", \");\n\n        print0(ucase ? \" INTO (\" : \" into (\");\n        printAndAccept(x.getPartitions(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropPartition x) {\n        boolean printDrop = true;\n        if (x.getParent() instanceof SQLAlterTableStatement) {\n            SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n            int p = stmt.getChildren().indexOf(x);\n            if (p > 0 && stmt.getChildren().get(p - 1) instanceof SQLAlterTableDropPartition) {\n                printDrop = false;\n            }\n        }\n\n        if (printDrop) {\n            print0(ucase ? \"DROP \" : \"drop \");\n\n            if (x.isIfExists()) {\n                print0(ucase ? \"IF EXISTS \" : \"if exists \");\n            }\n        } else {\n            print('\\t');\n            indentCount++;\n        }\n\n        if (x.getAttribute(\"SIMPLE\") != null) {\n            print0(ucase ? \"PARTITION \" : \"partition \");\n            printAndAccept(x.getPartitions(), \",\");\n        } else {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartitions(), \", \");\n            print(')');\n        }\n\n        if (x.isPurge()) {\n            print0(ucase ? \" PURGE\" : \" purge\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRenamePartition x) {\n        print0(ucase ? \"PARTITION (\" : \"partition (\");\n        printAndAccept(x.getPartition(), \", \");\n        print0(ucase ? \") RENAME TO PARTITION(\" : \") rename to partition(\");\n        printAndAccept(x.getTo(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetComment x) {\n        print0(ucase ? \"SET COMMENT \" : \"set comment \");\n        x.getComment().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetTableSpace x) {\n        print0(ucase ? \"SET TABLESPACE \" : \"set tablespace \");\n        x.getTableSpaceName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetSchema x) {\n        print0(ucase ? \"SET SCHEMA \" : \"set schema \");\n        x.getSchemaName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetFileFormat x) {\n        print0(ucase ? \"SET FILEFORMAT \" : \"set fileformat \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPrivilegeItem x) {\n        SQLExpr action = x.getAction();\n        if (action instanceof SQLIdentifierExpr) {\n            String actionName = ((SQLIdentifierExpr) action).getName();\n            print0(ucase ? actionName.toUpperCase() : actionName.toLowerCase());\n        } else {\n            printExpr(action);\n        }\n\n        List<SQLName> columns = x.getColumns();\n        int size = columns.size();\n        if (size > 0) {\n            print0(\"(\");\n            for (int i = 0; i < size; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                SQLName column = columns.get(i);\n                if (column instanceof SQLIdentifierExpr) {\n                    print0(((SQLIdentifierExpr) column).getName());\n                } else {\n                    printExpr(column);\n                }\n            }\n            print0(\")\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetLifecycle x) {\n        print0(ucase ? \"SET LIFECYCLE \" : \"set lifecycle \");\n        x.getLifecycle().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetLocation x) {\n        print0(ucase ? \"SET LOCATION \" : \"set location \");\n        x.getLocation().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableEnableLifecycle x) {\n        if (!x.getPartition().isEmpty()) {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print0(\") \");\n        }\n\n        print0(ucase ? \"ENABLE LIFECYCLE\" : \"enable lifecycle\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableArchive x) {\n        if (!x.getPartition().isEmpty()) {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print0(\") \");\n        }\n\n        print0(ucase ? \"ARCHIVE\" : \"archive\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDisableLifecycle x) {\n        if (!x.getPartition().isEmpty()) {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print0(\") \");\n        }\n\n        print0(ucase ? \"DISABLE LIFECYCLE\" : \"disable lifecycle\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTablePartition x) {\n        if (!x.getPartition().isEmpty()) {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print0(\") \");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTablePartitionSetProperties x) {\n        if (!x.getPartition().isEmpty()) {\n            print0(ucase ? \"PARTITION (\" : \"partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print0(\") \");\n        }\n\n        if (!x.getPartitionProperties().isEmpty()) {\n            print0(ucase ? \"SET PARTITIONPROPERTIES (\" : \"set partitionproperties (\");\n            printAndAccept(x.getPartitionProperties(), \", \");\n            print0(\") \");\n        }\n\n        SQLExpr location = x.getLocation();\n        if (location != null) {\n            println();\n            print0(ucase ? \"SET LOCATION \" : \"set location \");\n            location.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableTouch x) {\n        print0(ucase ? \"TOUCH\" : \"touch\");\n        if (!x.getPartition().isEmpty()) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetSerde x) {\n        print0(ucase ? \"SET SERDE \" : \"set serde \");\n        x.getSerde().accept(this);\n\n        if (x.getSerdeProperties().size() > 0) {\n            println();\n            print0(ucase ? \"WITH SERDEPROPERTIES (\" : \"with serdeproperties (\");\n            printAndAccept(x.getSerdeProperties(), \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    public void printArrayExprPrefix() {\n    }\n    @Override\n    public boolean visit(SQLArrayExpr x) {\n        SQLExpr expr = x.getExpr();\n\n        boolean arrayValue = expr instanceof SQLIdentifierExpr\n                && ((SQLIdentifierExpr) expr).nameHashCode64() == FnvHash.Constants.ARRAY;\n        if (arrayValue && printNameQuote) {\n            print0(((SQLIdentifierExpr) expr).getName());\n        } else if (expr != null) {\n            expr.accept(this);\n        } else {\n            printArrayExprPrefix();\n        }\n\n        if (x.getDataType() != null) {\n            print('<');\n            x.getDataType().accept(this);\n            print('>');\n        }\n\n        boolean brace = arrayValue && (dbType == DbType.hive || dbType == DbType.spark || dbType == DbType.odps);\n\n        print(brace ? '(' : '[');\n        List<SQLExpr> values = x.getValues();\n        int size = values.size();\n        for (int i = 0, columnIndex = 0; i < size; i++, columnIndex++) {\n            SQLExpr value = values.get(i);\n            if (i != 0) {\n                print(',');\n                if (i % 5 == 0 || value instanceof SQLStructExpr) {\n                    println();\n                    columnIndex = 0;\n                } else {\n                    print0(' ');\n                }\n            }\n            printExpr(value);\n        }\n        print(brace ? ')' : ']');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOpenStatement x) {\n        print0(ucase ? \"OPEN \" : \"open \");\n        printExpr(x.getCursorName(), parameterized);\n\n        List<SQLExpr> columns = x.getColumns();\n        if (columns.size() > 0) {\n            print('(');\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        SQLExpr forExpr = x.getFor();\n        if (forExpr != null) {\n            print0(ucase ? \" FOR \" : \" for \");\n            forExpr.accept(this);\n        }\n\n        List<SQLExpr> using = x.getUsing();\n        if (using.size() > 0) {\n            print0(ucase ? \" USING \" : \" using \");\n            printAndAccept(using, \", \");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLFetchStatement x) {\n        print0(ucase ? \"FETCH \" : \"fetch \");\n        x.getCursorName().accept(this);\n        if (x.isBulkCollect()) {\n            print0(ucase ? \" BULK COLLECT INTO \" : \" bulk collect into \");\n        } else {\n            print0(ucase ? \" INTO \" : \" into \");\n        }\n        printAndAccept(x.getInto(), \", \");\n\n        final SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            print(' ');\n            limit.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCloseStatement x) {\n        print0(ucase ? \"CLOSE \" : \"close \");\n        printExpr(x.getCursorName(), parameterized);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLGroupingSetExpr x) {\n        print0(ucase ? \"GROUPING SETS\" : \"grouping sets\");\n        print0(\" (\");\n        printAndAccept(x.getParameters(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement x) {\n        print0(ucase ? \"IF \" : \"if \");\n        x.getCondition().accept(this);\n        this.indentCount++;\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n\n        for (SQLIfStatement.ElseIf elseIf : x.getElseIfList()) {\n            println();\n            elseIf.accept(this);\n        }\n\n        if (x.getElseItem() != null) {\n            println();\n            x.getElseItem().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.Else x) {\n        print0(ucase ? \"ELSE\" : \"else\");\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIfStatement.ElseIf x) {\n        if (x.isConcatenated()) {\n            print0(ucase ? \"ELSEIF \" : \"elseif \");\n        } else {\n            print0(ucase ? \"ELSE IF \" : \"else if \");\n        }\n        x.getCondition().accept(this);\n        println();\n        print0(ucase ? \" THEN\" : \" then\");\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            if (i != 0) {\n                println();\n            }\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLLoopStatement x) {\n        print0(ucase ? \"LOOP\" : \"loop\");\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n\n            if (i != size - 1) {\n                println();\n            }\n        }\n\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END LOOP\" : \"end loop\");\n        if (x.getLabelName() != null) {\n            print(' ');\n            print0(x.getLabelName());\n        }\n        return false;\n    }\n\n    public boolean visit(OracleFunctionDataType x) {\n        if (x.isStatic()) {\n            print0(ucase ? \"STATIC \" : \"static \");\n        }\n\n        print0(ucase ? \"FUNCTION \" : \"function \");\n\n        print0(x.getName());\n\n        print(\" (\");\n        printAndAccept(x.getParameters(), \", \");\n        print(\")\");\n        print0(ucase ? \" RETURN \" : \" return \");\n        x.getReturnDataType().accept(this);\n\n        SQLStatement block = x.getBlock();\n        if (block != null) {\n            println();\n            print0(ucase ? \"IS\" : \"is\");\n            println();\n            block.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(OracleProcedureDataType x) {\n        if (x.isStatic()) {\n            print0(ucase ? \"STATIC \" : \"static \");\n        }\n\n        print0(ucase ? \"PROCEDURE \" : \"procedure \");\n\n        print0(x.getName());\n\n        if (x.getParameters().size() > 0) {\n            print(\" (\");\n            printAndAccept(x.getParameters(), \", \");\n            print(\")\");\n        }\n\n        SQLStatement block = x.getBlock();\n        if (block != null) {\n            println();\n            print0(ucase ? \"IS\" : \"is\");\n            println();\n            block.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLParameter x) {\n        SQLName name = x.getName();\n        if (x.getDataType().getName().equalsIgnoreCase(\"CURSOR\")) {\n            print0(ucase ? \"CURSOR \" : \"cursor \");\n            x.getName().accept(this);\n            print0(ucase ? \" IS\" : \" is\");\n            this.indentCount++;\n            println();\n            SQLSelect select = ((SQLQueryExpr) x.getDefaultValue()).getSubQuery();\n            select.accept(this);\n            this.indentCount--;\n\n        } else {\n            if (x.isMap()) {\n                print0(ucase ? \"MAP MEMBER \" : \"map member \");\n            } else if (x.isOrder()) {\n                print0(ucase ? \"ORDER MEMBER \" : \"order member \");\n            } else if (x.isMember()) {\n                print0(ucase ? \"MEMBER \" : \"member \");\n            }\n            SQLDataType dataType = x.getDataType();\n\n            if (DbType.oracle == dbType\n                    || dataType instanceof OracleFunctionDataType\n                    || dataType instanceof OracleProcedureDataType) {\n                if (dataType instanceof OracleFunctionDataType) {\n                    OracleFunctionDataType functionDataType = (OracleFunctionDataType) dataType;\n                    visit(functionDataType);\n                    return false;\n                }\n\n                if (dataType instanceof OracleProcedureDataType) {\n                    OracleProcedureDataType procedureDataType = (OracleProcedureDataType) dataType;\n                    visit(procedureDataType);\n                    return false;\n                }\n\n                String dataTypeName = dataType.getName();\n                boolean printType = (dataTypeName.startsWith(\"TABLE OF\") && x.getDefaultValue() == null)\n                        || dataTypeName.equalsIgnoreCase(\"REF CURSOR\")\n                        || dataTypeName.startsWith(\"VARRAY(\");\n                if (printType) {\n                    print0(ucase ? \"TYPE \" : \"type \");\n                }\n\n                //枚举类型特殊处理\n                if (\"ENUM\".equals(dataTypeName)) {\n                    dataType.accept(this);\n                    return false;\n                } else {\n                    name.accept(this);\n                }\n                if (x.getParamType() == SQLParameter.ParameterType.IN) {\n                    print0(ucase ? \" IN \" : \" in \");\n                } else if (x.getParamType() == SQLParameter.ParameterType.OUT) {\n                    print0(ucase ? \" OUT \" : \" out \");\n                } else if (x.getParamType() == SQLParameter.ParameterType.INOUT) {\n                    print0(ucase ? \" IN OUT \" : \" in out \");\n                } else {\n                    print(' ');\n                }\n\n                if (x.isNoCopy()) {\n                    print0(ucase ? \"NOCOPY \" : \"nocopy \");\n                }\n\n                if (x.isConstant()) {\n                    print0(ucase ? \"CONSTANT \" : \"constant \");\n                }\n\n                if (printType) {\n                    print0(ucase ? \"IS \" : \"is \");\n                }\n            } else {\n                if (x.getParamType() == SQLParameter.ParameterType.IN) {\n                    boolean skip = DbType.mysql == dbType\n                            && x.getParent() instanceof SQLCreateFunctionStatement;\n\n                    if (!skip) {\n                        print0(ucase ? \"IN \" : \"in \");\n                    }\n                } else if (x.getParamType() == SQLParameter.ParameterType.OUT) {\n                    print0(ucase ? \"OUT \" : \"out \");\n                } else if (x.getParamType() == SQLParameter.ParameterType.INOUT) {\n                    print0(ucase ? \"INOUT \" : \"inout \");\n                }\n                x.getName().accept(this);\n                print(' ');\n            }\n\n            dataType.accept(this);\n            if (x.isNotNull()) {\n                print0(ucase ? \" NOT NULL\" : \" not null\");\n            }\n            printParamDefaultValue(x);\n        }\n\n        return false;\n    }\n\n    protected void printParamDefaultValue(SQLParameter x) {\n        if (x.getDefaultValue() != null) {\n            print0(\" := \");\n            x.getDefaultValue().accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLDeclareItem x) {\n        SQLDataType dataType = x.getDataType();\n\n        if (dataType instanceof SQLRecordDataType) {\n            print0(ucase ? \"TYPE \" : \"type \");\n        }\n\n        x.getName().accept(this);\n\n        if (x.getType() == SQLDeclareItem.Type.TABLE) {\n            print0(ucase ? \" TABLE\" : \" table\");\n            int size = x.getTableElementList().size();\n\n            if (size > 0) {\n                print0(\" (\");\n                this.indentCount++;\n                println();\n                for (int i = 0; i < size; ++i) {\n                    if (i != 0) {\n                        print(',');\n                        println();\n                    }\n                    x.getTableElementList().get(i).accept(this);\n                }\n                this.indentCount--;\n                println();\n                print(')');\n            }\n        } else if (x.getType() == SQLDeclareItem.Type.CURSOR) {\n            print0(ucase ? \" CURSOR\" : \" cursor\");\n        } else {\n            if (dataType != null) {\n                if (dataType instanceof SQLRecordDataType) {\n                    print0(ucase ? \" IS \" : \" is \");\n                } else {\n                    print(' ');\n                }\n                dataType.accept(this);\n            }\n            if (x.getValue() != null) {\n                if (DbType.mysql == getDbType() || DbType.bigquery == getDbType()) {\n                    print0(ucase ? \" DEFAULT \" : \" default \");\n                } else {\n                    print0(\" = \");\n                }\n                x.getValue().accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionValue x) {\n        if (x.getOperator() == SQLPartitionValue.Operator.LessThan //\n                && DbType.oracle != getDbType() && x.getItems().size() == 1 //\n                && x.getItems().get(0) instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr ident = (SQLIdentifierExpr) x.getItems().get(0);\n            if (\"MAXVALUE\".equalsIgnoreCase(ident.getName())) {\n                print0(ucase ? \"VALUES LESS THAN MAXVALUE\" : \"values less than maxvalue\");\n                return false;\n            }\n        }\n\n        if (x.getOperator() == SQLPartitionValue.Operator.LessThan) {\n            print0(ucase ? \"VALUES LESS THAN (\" : \"values less than (\");\n        } else if (x.getOperator() == SQLPartitionValue.Operator.In) {\n            print0(ucase ? \"VALUES IN (\" : \"values in (\");\n        } else if (x.getOperator() == SQLPartitionValue.Operator.FixedRange) {\n            print(ucase ? \"VALUES [\" : \"values [\");\n        } else {\n            print(ucase ? \"VALUES (\" : \"values (\");\n        }\n        printAndAccept(x.getItems(), \", \", false);\n        print(')');\n        return false;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public boolean isUppCase() {\n        return ucase;\n    }\n\n    public void setUppCase(boolean val) {\n        this.config(VisitorFeature.OutputUCase, val);\n    }\n\n    @Override\n    public boolean visit(SQLPartitionBatch x) {\n        print0(ucase ? \"START (\" : \"start (\");\n        x.getStart().accept(this);\n        print0(ucase ? \") END (\" : \") end (\");\n        x.getEnd().accept(this);\n        print0(ucase ? \") EVERY (\" : \") every (\");\n        x.getEvery().accept(this);\n        print0(\")\");\n        return false;\n    }\n    @Override\n    public boolean visit(SQLPartitionSingle x) {\n        boolean isDbPartiton = false, isTbPartition = false;\n        final SQLObject parent = x.getParent();\n        if (parent != null) {\n            final SQLObject parent2 = parent.getParent();\n            if (parent2 instanceof MySqlCreateTableStatement) {\n                MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) parent2;\n                isDbPartiton = parent == stmt.getDbPartitionBy();\n                isTbPartition = parent == stmt.getTablePartitionBy();\n            }\n        }\n\n        if (isDbPartiton) {\n            print0(ucase ? \"DBPARTITION \" : \"dbpartition \");\n        } else if (isTbPartition) {\n            print0(ucase ? \"TBPARTITION \" : \"tbpartition \");\n        } else {\n            print0(ucase ? \"PARTITION \" : \"partition \");\n        }\n        x.getName().accept(this);\n        if (x.getValues() != null) {\n            print(' ');\n            x.getValues().accept(this);\n        }\n\n        if (x.getSubPartitionsCount() != null) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"SUBPARTITIONS \" : \"subpartitions \");\n            x.getSubPartitionsCount().accept(this);\n            this.indentCount--;\n        }\n\n        if (x.getSubPartitions().size() > 0) {\n            print(\" (\");\n            this.indentCount++;\n            for (int i = 0; i < x.getSubPartitions().size(); ++i) {\n                if (i != 0) {\n                    print(',');\n                }\n                println();\n                x.getSubPartitions().get(i).accept(this);\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        SQLExpr locality = x.getLocality();\n        if (locality != null) {\n            print(ucase ? \" LOCALITY = \" : \" locality = \");\n            locality.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByRange x) {\n        SQLExpr interval = x.getInterval();\n        if (x.getColumns().isEmpty()\n                && (interval instanceof SQLBetweenExpr || interval instanceof SQLMethodInvokeExpr)) {\n            interval.accept(this);\n        } else {\n            print0(ucase ? \"RANGE\" : \"range\");\n\n            boolean columns = true;\n            for (SQLExpr column : x.getColumns()) {\n                if (!(column instanceof SQLName)) {\n                    columns = false;\n                    break;\n                }\n            }\n\n            if (x.getColumns().size() == 1) {\n                if (DbType.mysql == getDbType() && columns) {\n                    print0(ucase ? \" COLUMNS (\" : \" columns (\");\n                } else {\n                    print0(\" (\");\n                }\n                x.getColumns().get(0).accept(this);\n                print(')');\n            } else {\n                if (DbType.mysql == getDbType() && columns) {\n                    print0(ucase ? \" COLUMNS (\" : \" columns (\");\n                } else {\n                    print0(\" (\");\n                }\n                printAndAccept(x.getColumns(), \", \");\n                print(')');\n            }\n\n            if (interval != null) {\n                print0(ucase ? \" INTERVAL (\" : \" interval (\");\n                interval.accept(this);\n                print(')');\n            }\n        }\n\n        printPartitionsCountAndSubPartitions(x);\n        printSQLPartitions(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByList x) {\n        print0(ucase ? \"LIST \" : \"list \");\n        if (SQLPartitionByList.PartitionByListType.LIST_COLUMNS.equals(x.getType())) {\n            print0(ucase ? \"COLUMNS (\" : \"columns (\");\n            printAndAccept(x.getColumns(), \", \");\n            print0(\")\");\n        } else {\n            print('(');\n            printAndAccept(x.getColumns(), \", \");\n            print0(\")\");\n        }\n\n        printPartitionsCountAndSubPartitions(x);\n\n        printSQLPartitions(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByHash x) {\n        if (x.isLinear()) {\n            print0(ucase ? \"LINEAR HASH \" : \"linear hash \");\n        } else {\n            if (x.isUnique()) {\n                print0(ucase ? \"UNI_HASH \" : \"uni_hash \");\n            } else {\n                print0(ucase ? \"HASH \" : \"hash \");\n            }\n        }\n\n        if (x.isKey()) {\n            print0(ucase ? \"KEY\" : \"key\");\n        }\n        if (!x.getColumns().isEmpty()) {\n            print('(');\n            printAndAccept(x.getColumns(), \", \");\n            print(')');\n        }\n\n        printPartitionsCountAndSubPartitions(x);\n\n        printSQLPartitions(x.getPartitions());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByValue x) {\n        print0(ucase ? \"VALUE \" : \"value \");\n\n        print('(');\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        printPartitionsCountAndSubPartitions(x);\n\n        printSQLPartitions(x.getPartitions());\n\n        return false;\n    }\n\n    protected void printSQLPartitions(List<SQLPartition> partitions) {\n        int partitionsSize = partitions.size();\n        if (partitionsSize > 0) {\n            print0(\" (\");\n            this.indentCount++;\n            for (int i = 0; i < partitionsSize; ++i) {\n                println();\n                partitions.get(i).accept(this);\n                if (i != partitionsSize - 1) {\n                    print0(\",\");\n                }\n            }\n            this.indentCount--;\n            println();\n            print(')');\n        }\n    }\n\n    protected void printPartitionsCountAndSubPartitions(SQLPartitionBy x) {\n        final SQLExpr partitionsCount = x.getPartitionsCount();\n        if (partitionsCount != null) {\n            boolean isDbPartiton = false, isTbPartition = false;\n            if (x.getParent() instanceof MySqlCreateTableStatement) {\n                MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) x.getParent();\n                isDbPartiton = x == stmt.getDbPartitionBy();\n                isTbPartition = x == stmt.getTablePartitionBy();\n            }\n\n            if (Boolean.TRUE.equals(x.getAttribute(\"ads.partition\"))) {\n                print0(ucase ? \" PARTITION NUM \" : \" partition num \");\n            } else {\n                if (isDbPartiton) {\n                    print0(ucase ? \" DBPARTITIONS \" : \" dbpartitions \");\n                } else if (isTbPartition) {\n                    print0(ucase ? \" TBPARTITIONS \" : \" tbpartitions \");\n                } else {\n                    print0(ucase ? \" PARTITIONS \" : \" partitions \");\n                }\n            }\n\n            partitionsCount.accept(this);\n        }\n\n        printLifeCycle(x.getLifeCycle());\n\n        if (x.getSubPartitionBy() != null) {\n            println();\n            x.getSubPartitionBy().accept(this);\n        }\n\n        if (x.getStoreIn().size() > 0) {\n            println();\n            print0(ucase ? \"STORE IN (\" : \"store in (\");\n            printAndAccept(x.getStoreIn(), \", \");\n            print(')');\n        }\n    }\n\n    @Override\n    public boolean visit(SQLSubPartitionByHash x) {\n        if (x.isLinear()) {\n            print0(ucase ? \"SUBPARTITION BY LINEAR HASH \" : \"subpartition by linear hash \");\n        } else {\n            print0(ucase ? \"SUBPARTITION BY HASH \" : \"subpartition by hash \");\n        }\n\n        if (x.isKey()) {\n            print0(ucase ? \"KEY\" : \"key\");\n        }\n\n        print('(');\n        x.getExpr().accept(this);\n        print(')');\n\n        if (x.getSubPartitionsCount() != null) {\n            print0(ucase ? \" SUBPARTITIONS \" : \" subpartitions \");\n            x.getSubPartitionsCount().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubPartitionByRange x) {\n        print0(ucase ? \"SUBPARTITION BY RANGE \" : \"subpartition by range \");\n\n        SQLExpr subPartitionsCount = x.getSubPartitionsCount();\n        if (subPartitionsCount != null) {\n            print0(ucase ? \" SUBPARTITIONS \" : \" subpartitions \");\n            subPartitionsCount.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubPartitionByList x) {\n        if (x.isLinear()) {\n            print0(ucase ? \"SUBPARTITION BY LINEAR HASH \" : \"subpartition by linear hash \");\n        } else {\n            print0(ucase ? \"SUBPARTITION BY HASH \" : \"subpartition by hash \");\n        }\n\n        print('(');\n        x.getColumn().accept(this);\n        print(')');\n\n        if (x.getSubPartitionsCount() != null) {\n            print0(ucase ? \" SUBPARTITIONS \" : \" subpartitions \");\n            x.getSubPartitionsCount().accept(this);\n        }\n\n        if (x.getSubPartitionTemplate().size() > 0) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"SUBPARTITION TEMPLATE (\" : \"subpartition template (\");\n            this.indentCount++;\n            println();\n            printlnAndAccept(x.getSubPartitionTemplate(), \",\");\n            this.indentCount--;\n            println();\n            print(')');\n            this.indentCount--;\n        }\n\n        printLifeCycle(x.getLifecycle());\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubPartition x) {\n        print0(ucase ? \"SUBPARTITION \" : \"subpartition \");\n        x.getName().accept(this);\n\n        if (x.getValues() != null) {\n            print(' ');\n            x.getValues().accept(this);\n        }\n\n        SQLName tableSpace = x.getTableSpace();\n        if (tableSpace != null) {\n            print0(ucase ? \" TABLESPACE \" : \" tablespace \");\n            tableSpace.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterDatabaseStatement x) {\n        print0(ucase ? \"ALTER DATABASE \" : \"alter database \");\n        x.getName().accept(this);\n        if (x.isUpgradeDataDirectoryName()) {\n            print0(ucase ? \" UPGRADE DATA DIRECTORY NAME\" : \" upgrade data directory name\");\n        }\n\n        if (x.getProperties().size() > 0) {\n            print0(ucase ? \" SET DBPROPERTIES (\" : \"set dbproperties (\");\n            printAndAccept(x.getProperties(), \", \");\n            print(')');\n        }\n\n        SQLAlterDatabaseItem item = x.getItem();\n        if (item instanceof MySqlAlterDatabaseSetOption) {\n            MySqlAlterDatabaseSetOption setOption = (MySqlAlterDatabaseSetOption) item;\n            print0(ucase ? \" SET \" : \" set \");\n            printAndAccept(setOption.getOptions(), \", \");\n\n            SQLName on = setOption.getOn();\n            if (on != null) {\n                print0(ucase ? \" ON \" : \" on \");\n                on.accept(this);\n            }\n        }\n\n        if (item instanceof MySqlAlterDatabaseKillJob) {\n            print0(ucase ? \" KILL \" : \" kill \");\n            MySqlAlterDatabaseKillJob kill = (MySqlAlterDatabaseKillJob) item;\n            kill.getJobType().accept(this);\n            print0(\" \");\n            kill.getJobId().accept(this);\n        }\n\n        SQLAlterCharacter character = x.getCharacter();\n        if (character != null) {\n            print(' ');\n            character.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableConvertCharSet x) {\n        print0(ucase ? \"CONVERT TO CHARACTER SET \" : \"convert to character set \");\n        x.getCharset().accept(this);\n\n        if (x.getCollate() != null) {\n            print0(ucase ? \" COLLATE \" : \" collate \");\n            x.getCollate().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableCoalescePartition x) {\n        print0(ucase ? \"COALESCE PARTITION \" : \"coalesce partition \");\n        x.getCount().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableTruncatePartition x) {\n        print0(ucase ? \"TRUNCATE PARTITION \" : \"truncate partition \");\n        if (x.getPartitionValues().isEmpty()) {\n            printPartitions(x.getPartitions());\n        } else {\n            print0(ucase ? \"FOR \" : \"for \");\n            print0(\"(\");\n            printAndAccept(x.getPartitionValues(), \", \");\n            print0(\")\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDiscardPartition x) {\n        print0(ucase ? \"DISCARD PARTITION \" : \"discard partition \");\n        printPartitions(x.getPartitions());\n\n        if (x.isTablespace()) {\n            print0(ucase ? \" TABLESPACE\" : \" tablespace\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableExchangePartition x) {\n        print0(ucase ? \"EXCHANGE PARTITION \" : \"exchange partition \");\n        printAndAccept(x.getPartitions(), \", \");\n        print0(ucase ? \" WITH TABLE \" : \" with table \");\n        x.getTable().accept(this);\n\n        Boolean validation = x.getValidation();\n        if (validation != null) {\n            if (validation) {\n                print0(ucase ? \" WITH VALIDATION\" : \" with validation\");\n            } else {\n                print0(ucase ? \" WITHOUT VALIDATION\" : \" without validation\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableImportPartition x) {\n        print0(ucase ? \"IMPORT PARTITION \" : \"import partition \");\n        printPartitions(x.getPartitions());\n\n        if (x.isTablespace()) {\n            print0(ucase ? \" TABLESPACE\" : \" tablespace\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAnalyzePartition x) {\n        print0(ucase ? \"ANALYZE PARTITION \" : \"analyze partition \");\n\n        printPartitions(x.getPartitions());\n        return false;\n    }\n\n    protected void printPartitions(List<SQLName> partitions) {\n        if (partitions.size() == 1 && \"ALL\".equalsIgnoreCase(partitions.get(0).getSimpleName())) {\n            print0(ucase ? \"ALL\" : \"all\");\n        } else {\n            printAndAccept(partitions, \", \");\n        }\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableCheckPartition x) {\n        print0(ucase ? \"CHECK PARTITION \" : \"check partition \");\n        printPartitions(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableOptimizePartition x) {\n        print0(ucase ? \"OPTIMIZE PARTITION \" : \"optimize partition \");\n        printPartitions(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRebuildPartition x) {\n        print0(ucase ? \"REBUILD PARTITION \" : \"rebuild partition \");\n        printPartitions(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRepairPartition x) {\n        print0(ucase ? \"REPAIR PARTITION \" : \"repair partition \");\n        printPartitions(x.getPartitions());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSequenceExpr x) {\n        x.getSequence().accept(this);\n        print('.');\n        print0(ucase ? x.getFunction().name : x.getFunction().nameLCase);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMergeStatement x) {\n        print0(ucase ? \"MERGE \" : \"merge \");\n        if (x.getHints().size() > 0) {\n            printAndAccept(x.getHints(), \", \");\n            print(' ');\n        }\n\n        print0(ucase ? \"INTO \" : \"into \");\n        x.getInto().accept(this);\n\n        println();\n        print0(ucase ? \"USING \" : \"using \");\n        x.getUsing().accept(this);\n\n        print0(ucase ? \" ON \" : \" on \");\n        x.getOn().accept(this);\n\n        for (SQLMergeStatement.When when : x.getWhens()) {\n            println();\n            when.accept(this);\n        }\n\n        SQLErrorLoggingClause errorLogging = x.getErrorLoggingClause();\n        if (errorLogging != null) {\n            println();\n            errorLogging.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(WhenUpdate x) {\n        print0(ucase ? \"WHEN\" : \"when\");\n        if (x.isNot()) {\n            print0(ucase ? \" NOT\" : \" not\");\n        }\n        print0(ucase ? \" MATCHED\" : \" matched\");\n        SQLName by = x.getBy();\n        if (by != null) {\n            print0(ucase ? \" BY \" : \" by \");\n            by.accept(this);\n        }\n        print0(ucase ? \" THEN UPDATE\" : \" then update\");\n        println();\n        incrementIndent();\n        print(ucase ? \"SET \" : \"set \");\n        printlnAndAccept(x.getItems(), \",\");\n        decrementIndent();\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where, parameterized);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMergeStatement.WhenDoNothing x) {\n        print0(ucase ? \"WHEN\" : \"when\");\n        if (x.isNot()) {\n            print0(ucase ? \" NOT\" : \" not\");\n        }\n        print0(ucase ? \" MATCHED\" : \" matched\");\n        SQLName by = x.getBy();\n        if (by != null) {\n            print0(ucase ? \" BY \" : \" by \");\n            by.accept(this);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            print0(ucase ? \" AND \" : \" and \");\n            printExpr(where, parameterized);\n        }\n        print0(ucase ? \" THEN DO NOTHING\" : \" then do nothing\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMergeStatement.WhenDelete x) {\n        print0(ucase ? \"WHEN\" : \"when\");\n        if (x.isNot()) {\n            print0(ucase ? \" NOT\" : \" not\");\n        }\n        print0(ucase ? \" MATCHED\" : \" matched\");\n        SQLName by = x.getBy();\n        if (by != null) {\n            print0(ucase ? \" BY \" : \" by \");\n            by.accept(this);\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            print0(ucase ? \" AND \" : \" and \");\n            printExpr(where, parameterized);\n        }\n        print0(ucase ? \" THEN DELETE\" : \" then delete\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(WhenInsert x) {\n        print0(ucase ? \"WHEN\" : \"when\");\n        if (x.isNot()) {\n            print0(ucase ? \" NOT\" : \" not\");\n        }\n        print0(ucase ? \" MATCHED\" : \" matched\");\n        SQLName by = x.getBy();\n        if (by != null) {\n            print0(ucase ? \" BY \" : \" by \");\n            by.accept(this);\n        }\n        print0(ucase ? \" THEN INSERT\" : \" then insert\");\n        if (x.isInsertRow()) {\n            printMergeInsertRow();\n        } else {\n            if (x.getColumns().size() > 0) {\n                printAndAccept(\" (\", \")\", x.getColumns(), \", \", 5);\n            }\n            println();\n            printAndAccept(\n                    ucase ? \"VALUES (\" : \"values (\",\n                    \")\",\n                    x.getValues(),\n                    \", \",\n                    5\n            );\n        }\n        if (x.getWhere() != null) {\n            this.indentCount++;\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            x.getWhere().accept(this);\n            this.indentCount--;\n        }\n\n        return false;\n    }\n\n    public void printMergeInsertRow() {\n        print(ucase ? \" ROW\" : \"row\");\n    }\n    @Override\n    public boolean visit(SQLErrorLoggingClause x) {\n        print0(ucase ? \"LOG ERRORS \" : \"log errors \");\n        if (x.getInto() != null) {\n            print0(ucase ? \"INTO \" : \"into \");\n            x.getInto().accept(this);\n            print(' ');\n        }\n\n        if (x.getSimpleExpression() != null) {\n            print('(');\n            x.getSimpleExpression().accept(this);\n            print(')');\n        }\n\n        if (x.getLimit() != null) {\n            print0(ucase ? \" REJECT LIMIT \" : \" reject limit \");\n            x.getLimit().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateSequenceStatement x) {\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        if (x.isGroup()) {\n            print0(ucase ? \"GROUP \" : \"group \");\n        } else if (x.isSimple()) {\n            print0(ucase ? \"SIMPLE \" : \"simple \");\n            final Boolean cache = x.getWithCache();\n            if (cache != null && cache.booleanValue()) {\n                print0(ucase ? \"WITH CACHE \" : \"with cache \");\n            }\n        } else if (x.isTime()) {\n            print0(ucase ? \"TIME \" : \"time \");\n        }\n\n        print0(ucase ? \"SEQUENCE \" : \"sequence \");\n        x.getName().accept(this);\n\n        if (x.getStartWith() != null) {\n            print0(ucase ? \" START WITH \" : \" start with \");\n            x.getStartWith().accept(this);\n        }\n\n        if (x.getIncrementBy() != null) {\n            print0(ucase ? \" INCREMENT BY \" : \" increment by \");\n            x.getIncrementBy().accept(this);\n        }\n\n        if (x.getMaxValue() != null) {\n            print0(ucase ? \" MAXVALUE \" : \" maxvalue \");\n            x.getMaxValue().accept(this);\n        }\n\n        if (x.isNoMaxValue()) {\n            if (DbType.postgresql == dbType) {\n                print0(ucase ? \" NO MAXVALUE\" : \" no maxvalue\");\n            } else {\n                print0(ucase ? \" NOMAXVALUE\" : \" nomaxvalue\");\n            }\n        }\n\n        if (x.getMinValue() != null) {\n            print0(ucase ? \" MINVALUE \" : \" minvalue \");\n            x.getMinValue().accept(this);\n        }\n\n        if (x.isNoMinValue()) {\n            if (DbType.postgresql == dbType) {\n                print0(ucase ? \" NO MINVALUE\" : \" no minvalue\");\n            } else {\n                print0(ucase ? \" NOMINVALUE\" : \" nominvalue\");\n            }\n        }\n\n        if (x.getCycle() != null) {\n            if (x.getCycle().booleanValue()) {\n                print0(ucase ? \" CYCLE\" : \" cycle\");\n            } else {\n                if (DbType.postgresql == dbType) {\n                    print0(ucase ? \" NO CYCLE\" : \" no cycle\");\n                } else {\n                    print0(ucase ? \" NOCYCLE\" : \" nocycle\");\n                }\n            }\n        }\n\n        Boolean cache = x.getCache();\n        if (cache != null) {\n            if (cache.booleanValue()) {\n                print0(ucase ? \" CACHE\" : \" cache\");\n\n                SQLExpr cacheValue = x.getCacheValue();\n                if (cacheValue != null) {\n                    print(' ');\n                    cacheValue.accept(this);\n                }\n            } else {\n                print0(ucase ? \" NOCACHE\" : \" nocache\");\n            }\n        }\n\n        Boolean order = x.getOrder();\n        if (order != null) {\n            if (order.booleanValue()) {\n                print0(ucase ? \" ORDER\" : \" order\");\n            } else {\n                print0(ucase ? \" NOORDER\" : \" noorder\");\n            }\n        }\n\n        final SQLExpr unitCount = x.getUnitCount();\n        if (unitCount != null) {\n            print0(ucase ? \" UNIT COUNT \" : \" unit count \");\n            printExpr(unitCount);\n        }\n\n        final SQLExpr unitIndex = x.getUnitIndex();\n        if (unitIndex != null) {\n            print0(ucase ? \" INDEX \" : \" index \");\n            printExpr(unitIndex);\n        }\n\n        if (x.getStep() != null) {\n            print0(ucase ? \" STEP \" : \" step \");\n            printExpr(x.getStep());\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterSequenceStatement x) {\n        print0(ucase ? \"ALTER SEQUENCE \" : \"alter sequence \");\n        x.getName().accept(this);\n\n        if (x.isChangeToSimple()) {\n            print0(ucase ? \" CHANGE TO SIMPLE\" : \" change to simple\");\n            final Boolean cache = x.getWithCache();\n            if (cache != null && cache.booleanValue()) {\n                print0(ucase ? \" WITH CACHE\" : \"  with cache\");\n            }\n        } else if (x.isChangeToGroup()) {\n            print0(ucase ? \" CHANGE TO GROUP\" : \" change to group\");\n        } else if (x.isChangeToTime()) {\n            print0(ucase ? \" CHANGE TO TIME\" : \" change to time\");\n        }\n\n        if (x.getStartWith() != null) {\n            print0(ucase ? \" START WITH \" : \" start with \");\n            x.getStartWith().accept(this);\n        }\n\n        if (x.getIncrementBy() != null) {\n            print0(ucase ? \" INCREMENT BY \" : \" increment by \");\n            x.getIncrementBy().accept(this);\n        }\n\n        if (x.getMaxValue() != null) {\n            print0(ucase ? \" MAXVALUE \" : \" maxvalue \");\n            x.getMaxValue().accept(this);\n        }\n\n        if (x.isNoMaxValue()) {\n            if (DbType.postgresql == dbType) {\n                print0(ucase ? \" NO MAXVALUE\" : \" no maxvalue\");\n            } else {\n                print0(ucase ? \" NOMAXVALUE\" : \" nomaxvalue\");\n            }\n        }\n\n        if (x.getMinValue() != null) {\n            print0(ucase ? \" MINVALUE \" : \" minvalue \");\n            x.getMinValue().accept(this);\n        }\n\n        if (x.isNoMinValue()) {\n            if (DbType.postgresql == dbType) {\n                print0(ucase ? \" NO MINVALUE\" : \" no minvalue\");\n            } else {\n                print0(ucase ? \" NOMINVALUE\" : \" nominvalue\");\n            }\n        }\n\n        if (x.getCycle() != null) {\n            if (x.getCycle().booleanValue()) {\n                print0(ucase ? \" CYCLE\" : \" cycle\");\n            } else {\n                if (DbType.postgresql == dbType) {\n                    print0(ucase ? \" NO CYCLE\" : \" no cycle\");\n                } else {\n                    print0(ucase ? \" NOCYCLE\" : \" nocycle\");\n                }\n            }\n        }\n\n        Boolean cache = x.getCache();\n        if (cache != null) {\n            if (cache.booleanValue()) {\n                print0(ucase ? \" CACHE\" : \" cache\");\n\n                SQLExpr cacheValue = x.getCacheValue();\n                if (cacheValue != null) {\n                    print(' ');\n                    cacheValue.accept(this);\n                }\n            } else {\n                print0(ucase ? \" NOCACHE\" : \" nocache\");\n            }\n        }\n\n        Boolean order = x.getOrder();\n        if (order != null) {\n            if (order.booleanValue()) {\n                print0(ucase ? \" ORDER\" : \" order\");\n            } else {\n                print0(ucase ? \" NOORDER\" : \" noorder\");\n            }\n        }\n\n        if (x.isRestart()) {\n            print0(ucase ? \" RESTART\" : \" restart\");\n\n            SQLExpr restartWith = x.getRestartWith();\n            if (restartWith != null) {\n                print0(ucase ? \" WITH \" : \" with \");\n                restartWith.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLDateExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLTimeExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLDateTimeExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLTimestampNTZExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLRealExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLDecimalExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLDoubleExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLFloatExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLSmallIntExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLTinyIntExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLBigIntExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    public boolean visit(SQLLimit x) {\n        print0(ucase ? \"LIMIT \" : \"limit \");\n        SQLExpr offset = x.getOffset();\n        boolean offsetClause = x.isOffsetClause();\n        if (offset != null && !offsetClause) {\n            printExpr(offset, parameterized);\n            print0(\", \");\n        }\n\n        SQLExpr rowCount = x.getRowCount();\n        if (rowCount != null) {\n            printExpr(rowCount, parameterized);\n        }\n\n        if (offset != null && offsetClause) {\n            print0(ucase ? \" OFFSET \" : \" offset \");\n            printExpr(offset, parameterized);\n        }\n\n        final List<SQLExpr> by = x.getBy();\n        if (by != null) {\n            print0(ucase ? \" BY \" : \" by \");\n            for (int i = 0; i < by.size(); i++) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                by.get(i).accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLDescribeStatement x) {\n        print0(ucase ? \"DESC \" : \"desc \");\n        if (x.getObjectType() != null) {\n            print0(x.getObjectType().name());\n            print(' ');\n        }\n\n        if (x.isExtended()) {\n            print0(ucase ? \"EXTENDED \" : \"extended \");\n        }\n\n        if (x.isFormatted()) {\n            print0(ucase ? \"FORMATTED \" : \"formatted \");\n        }\n\n        if (x.getObject() != null) {\n            x.getObject().accept(this);\n        }\n\n        SQLName column = x.getColumn();\n        if (column != null) {\n            print(' ');\n            column.accept(this);\n        }\n\n        if (x.getPartition().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    protected void printHierarchical(SQLSelectQueryBlock x) {\n        SQLExpr startWith = x.getStartWith(), connectBy = x.getConnectBy();\n        if (startWith != null || connectBy != null) {\n            println();\n            if (x.getStartWith() != null) {\n                print0(ucase ? \"START WITH \" : \"start with \");\n                x.getStartWith().accept(this);\n                println();\n            }\n\n            print0(ucase ? \"CONNECT BY \" : \"connect by \");\n\n            if (x.isNoCycle()) {\n                print0(ucase ? \"NOCYCLE \" : \"nocycle \");\n            }\n\n            if (x.isPrior()) {\n                print0(ucase ? \"PRIOR \" : \"prior \");\n            }\n\n            x.getConnectBy().accept(this);\n        }\n    }\n\n    public void printOracleSegmentAttributes(OracleSegmentAttributes x) {\n        if (x.getPctfree() != null) {\n            println();\n            print0(ucase ? \"PCTFREE \" : \"pctfree \");\n            print(x.getPctfree());\n        }\n\n        if (x.getPctused() != null) {\n            println();\n            print0(ucase ? \"PCTUSED \" : \"pctused \");\n            print(x.getPctused());\n        }\n\n        if (x.getInitrans() != null) {\n            println();\n            print0(ucase ? \"INITRANS \" : \"initrans \");\n            print(x.getInitrans());\n        }\n\n        if (x.getMaxtrans() != null) {\n            println();\n            print0(ucase ? \"MAXTRANS \" : \"maxtrans \");\n            print(x.getMaxtrans());\n        }\n\n        if (Boolean.FALSE.equals(x.getCompress())) {\n            println();\n            print0(ucase ? \"NOCOMPRESS\" : \"nocompress\");\n        } else if (Boolean.TRUE.equals(x.getCompress())) {\n            println();\n            print0(ucase ? \"COMPRESS\" : \"compress\");\n\n            if (x.getCompressLevel() != null) {\n                print(' ');\n                print(x.getCompressLevel());\n            }\n        }\n\n        if (Boolean.TRUE.equals(x.getLogging())) {\n            println();\n            print0(ucase ? \"LOGGING\" : \"logging\");\n        } else if (Boolean.FALSE.equals(x.getLogging())) {\n            println();\n            print0(ucase ? \"NOLOGGING\" : \"nologging\");\n        }\n\n        printTablespace(x.getTablespace());\n\n        if (x.getStorage() != null) {\n            println();\n            x.getStorage().accept(this);\n        }\n    }\n\n    @Override\n    public boolean visit(SQLWhileStatement x) {\n        String label = x.getLabelName();\n\n        if (label != null && !label.isEmpty()) {\n            print0(x.getLabelName());\n            print0(\": \");\n        }\n        print0(ucase ? \"WHILE \" : \"while \");\n        x.getCondition().accept(this);\n        print0(ucase ? \" LOOP\" : \" loop\");\n        println();\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement item = x.getStatements().get(i);\n            item.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n        println();\n        print0(ucase ? \"END LOOP\" : \"end loop\");\n        if (label != null && !label.isEmpty()) {\n            print(' ');\n            print0(label);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDeclareStatement x) {\n        boolean printDeclare = !(x.getParent() instanceof OracleCreatePackageStatement);\n        if (printDeclare) {\n            print0(ucase ? \"DECLARE \" : \"declare \");\n        }\n        this.printAndAccept(x.getItems(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLReturnStatement x) {\n        print0(ucase ? \"RETURN\" : \"return\");\n\n        if (x.getExpr() != null) {\n            print(' ');\n            x.getExpr().accept(this);\n        }\n        return false;\n    }\n\n    public void postVisit(SQLObject x) {\n        if (x instanceof SQLStatement) {\n            SQLStatement stmt = (SQLStatement) x;\n\n            boolean printSemi = printStatementAfterSemi == null\n                    ? stmt.isAfterSemi()\n                    : printStatementAfterSemi.booleanValue();\n\n            if (printSemi) {\n                print(';');\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLArgument x) {\n        SQLParameter.ParameterType type = x.getType();\n        if (type != null) {\n            print0(type.name());\n            print(' ');\n        }\n\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCommitStatement x) {\n        print0(ucase ? \"COMMIT\" : \"commit\");\n\n        if (x.isWrite()) {\n            print0(ucase ? \" WRITE\" : \" write\");\n            if (x.getWait() != null) {\n                if (x.getWait().booleanValue()) {\n                    print0(ucase ? \" WAIT\" : \" wait\");\n                } else {\n                    print0(ucase ? \" NOWAIT\" : \" nowait\");\n                }\n            }\n\n            if (x.getImmediate() != null) {\n                if (x.getImmediate().booleanValue()) {\n                    print0(ucase ? \" IMMEDIATE\" : \" immediate\");\n                } else {\n                    print0(ucase ? \" BATCH\" : \" batch\");\n                }\n            }\n        }\n\n        if (x.isWork()) {\n            print0(ucase ? \" WORK\" : \" work\");\n        }\n\n        if (x.getChain() != null) {\n            if (x.getChain().booleanValue()) {\n                print0(ucase ? \" AND CHAIN\" : \" and chain\");\n            } else {\n                print0(ucase ? \" AND NO CHAIN\" : \" and no chain\");\n            }\n        }\n\n        if (x.getRelease() != null) {\n            if (x.getRelease().booleanValue()) {\n                print0(ucase ? \" AND RELEASE\" : \" and release\");\n            } else {\n                print0(ucase ? \" AND NO RELEASE\" : \" and no release\");\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLFlashbackExpr x) {\n        print0(x.getType().name());\n        print(' ');\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLBinaryOpExpr && !((SQLBinaryOpExpr) expr).isParenthesized()) {\n            print('(');\n            expr.accept(this);\n            print(')');\n        } else {\n            expr.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropMaterializedViewStatement x) {\n        print0(ucase ? \"DROP MATERIALIZED VIEW \" : \"drop materialized view \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowMaterializedViewStatement x) {\n        print0(ucase ? \"SHOW MATERIALIZED VIEWS\" : \"show materialized views\");\n\n        if (x.getLike() != null) {\n            printUcase(\" LIKE \");\n            x.getLike().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowCreateMaterializedViewStatement x) {\n        print0(ucase ? \"SHOW CREATE MATERIALIZED VIEW \" : \"show create materialized view \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRefreshMaterializedViewStatement x) {\n        print0(ucase ? \"REFRESH MATERIALIZED\" : \"refresh materialized\");\n\n        if (x.isConcurrently()) {\n            print0(ucase ? \" CONCURRENTLY\" : \" concurrently\");\n        }\n\n        print0(ucase ? \" VIEW \" : \" view \");\n\n        x.getName().accept(this);\n\n        if (x.isWithNoData()) {\n            print0(ucase ? \" WITH NO DATA\" : \" with no data\");\n        } else if (x.isWithData()) {\n            print0(ucase ? \" WITH DATA\" : \" with data\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterMaterializedViewStatement x) {\n        print0(ucase ? \"ALTER MATERIALIZED VIEW \" : \"alter materialized view \");\n        x.getName().accept(this);\n\n        if (x.isRefresh()) {\n            println();\n            print(ucase ? \"REFRESH\" : \"refresh\");\n\n            if (x.isRefreshFast()) {\n                print(ucase ? \" FAST\" : \" fast\");\n            } else if (x.isRefreshComplete()) {\n                print(ucase ? \" COMPLETE\" : \" complete\");\n            } else if (x.isRefreshForce()) {\n                print(ucase ? \" FORCE\" : \" force\");\n            }\n\n            if (x.isRefreshOnCommit()) {\n                print(ucase ? \" ON COMMIT\" : \" on commit\");\n            } else if (x.isRefreshOnDemand()) {\n                print(ucase ? \" ON DEMAND\" : \" on demand\");\n            } else if (x.isRefreshOnOverWrite()) {\n                print(ucase ? \" ON OVERWRITE\" : \" on overwrite\");\n            }\n\n            if (x.getStartWith() != null) {\n                println();\n                print(ucase ? \"START WITH \" : \"start with \");\n                x.getStartWith().accept(this);\n            }\n\n            if (x.getNext() != null) {\n                print(ucase ? \" NEXT \" : \" next \");\n                x.getNext().accept(this);\n            }\n\n        }\n\n        Boolean enableQueryRewrite = x.getEnableQueryRewrite();\n        if (enableQueryRewrite != null) {\n            println();\n            if (enableQueryRewrite) {\n                print(ucase ? \"ENABLE QUERY REWRITE\" : \"enable query rewrite\");\n            } else {\n                print(ucase ? \"DISABLE QUERY REWRITE\" : \"disable query rewrite\");\n            }\n        }\n\n        if (x.isRebuild()) {\n            print0(ucase ? \" REBUILD\" : \" rebuild\");\n        }\n\n        List<SQLExpr> partitions = x.getPartitions();\n        if (!partitions.isEmpty()) {\n            print0(ucase ? \"PARTITIONS (\" : \"partitions (\");\n            printAndAccept(partitions, \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLAlterMaterializedViewStatement x) {\n    }\n\n    public boolean visit(SQLCreateMaterializedViewStatement x) {\n        print0(ucase ? \"CREATE MATERIALIZED VIEW \" : \"create materialized view \");\n        x.getName().accept(this);\n\n        if (dbType == DbType.mysql) {\n            printTableElements(x.getTableElementList());\n\n            if (x.getDistributedByType() != null) {\n                println();\n                if (isEnabled(VisitorFeature.OutputDistributedLiteralInCreateTableStmt)) {\n                    print0(ucase ? \"DISTRIBUTED BY \" : \"distributed by \");\n                } else {\n                    print0(ucase ? \"DISTRIBUTE BY \" : \"distribute by \");\n                }\n\n                SQLName distributeByType = x.getDistributedByType();\n\n                if (\"HASH\".equalsIgnoreCase(distributeByType.getSimpleName())) {\n                    print0(ucase ? \"HASH(\" : \"hash(\");\n                    printAndAccept(x.getDistributedBy(), \",\");\n                    print0(\")\");\n\n                } else if (\"DUPLICATE\".equalsIgnoreCase(distributeByType.getSimpleName())) {\n                    print0(ucase ? \"DUPLICATE(\" : \"duplicate(\");\n                    printAndAccept(x.getDistributedBy(), \",\");\n                    print0(\")\");\n\n                } else if (\"BROADCAST\".equalsIgnoreCase(distributeByType.getSimpleName())) {\n                    print0(ucase ? \"BROADCAST \" : \"broadcast \");\n                }\n            }\n\n            for (SQLAssignItem option : x.getTableOptions()) {\n                String key = ((SQLIdentifierExpr) option.getTarget()).getName();\n\n                print(' ');\n                print0(ucase ? key : key.toLowerCase());\n\n                if (\"TABLESPACE\".equals(key)) {\n                    print(' ');\n                    option.getValue().accept(this);\n                    continue;\n                }\n\n                print0(\" = \");\n\n                option.getValue().accept(this);\n            }\n\n            printComment(x.getComment());\n        }\n\n        SQLPartitionBy partitionBy = x.getPartitionBy();\n        if (partitionBy != null) {\n            println();\n            print0(ucase ? \"PARTITION BY \" : \"partition by \");\n            partitionBy.accept(this);\n        }\n\n        this.printOracleSegmentAttributes(x);\n        println();\n\n        Boolean cache = x.getCache();\n        if (cache != null) {\n            print(cache ? \"CACHE\" : \"NOCACHE\");\n            println();\n        }\n\n        Boolean parallel = x.getParallel();\n        if (parallel != null) {\n            if (parallel) {\n                print(ucase ? \"PARALLEL\" : \"parallel\");\n                Integer parallelValue = x.getParallelValue();\n                if (parallelValue != null) {\n                    print(' ');\n                    print(parallelValue);\n                }\n            } else {\n                print(ucase ? \"NOPARALLEL\" : \"noparallel\");\n            }\n            println();\n        }\n\n        if (x.isBuildImmediate()) {\n            println(ucase ? \"BUILD IMMEDIATE\" : \"build immediate\");\n        }\n\n        if (x.isRefresh()) {\n            print(ucase ? \"REFRESH\" : \"refresh\");\n\n            if (x.isRefreshFast()) {\n                print(ucase ? \" FAST\" : \" fast\");\n            } else if (x.isRefreshComplete()) {\n                print(ucase ? \" COMPLETE\" : \" complete\");\n            } else if (x.isRefreshForce()) {\n                print(ucase ? \" FORCE\" : \" force\");\n            }\n\n            if (x.isRefreshOnCommit()) {\n                print(ucase ? \" ON COMMIT\" : \" on commit\");\n            } else if (x.isRefreshOnDemand()) {\n                print(ucase ? \" ON DEMAND\" : \" on demand\");\n            } else if (x.isRefreshOnOverWrite()) {\n                print(ucase ? \" ON OVERWRITE\" : \" on overwrite\");\n            }\n\n            if (x.getStartWith() != null) {\n                println();\n                print(ucase ? \"START WITH \" : \"start with \");\n                x.getStartWith().accept(this);\n            }\n\n            if (x.getNext() != null) {\n                print(ucase ? \" NEXT \" : \" next \");\n                x.getNext().accept(this);\n            }\n\n            println();\n        }\n\n        Boolean enableQueryRewrite = x.getEnableQueryRewrite();\n        if (enableQueryRewrite != null) {\n            if (enableQueryRewrite) {\n                print(ucase ? \"ENABLE QUERY REWRITE\" : \"enable query rewrite\");\n            } else {\n                print(ucase ? \"DISABLE QUERY REWRITE\" : \"disable query rewrite\");\n            }\n            println();\n        }\n\n        println(ucase ? \"AS\" : \"as\");\n        x.getQuery().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLCreateUserStatement x) {\n        print0(ucase ? \"CREATE USER \" : \"create user \");\n        x.getUser().accept(this);\n        print0(ucase ? \" IDENTIFIED BY \" : \" identified by \");\n        x.getPassword().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLAlterFunctionStatement x) {\n        print0(ucase ? \"ALTER FUNCTION \" : \"alter function \");\n        x.getName().accept(this);\n\n        if (x.isDebug()) {\n            print0(ucase ? \" DEBUG\" : \" debug\");\n        }\n\n        if (x.isReuseSettings()) {\n            print0(ucase ? \" REUSE SETTINGS\" : \" reuse settings\");\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLAlterTypeStatement x) {\n        print0(ucase ? \"ALTER TYPE \" : \"alter type \");\n        x.getName().accept(this);\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (x.isBody()) {\n            print0(ucase ? \" BODY\" : \" body\");\n        }\n\n        if (x.isDebug()) {\n            print0(ucase ? \" DEBUG\" : \" debug\");\n        }\n\n        if (x.isReuseSettings()) {\n            print0(ucase ? \" REUSE SETTINGS\" : \" reuse settings\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIntervalExpr x) {\n        print0(ucase ? \"INTERVAL \" : \"interval \");\n        SQLExpr value = x.getValue();\n\n        boolean quote = (dbType == DbType.presto || dbType == DbType.trino || dbType == DbType.supersql)\n                && !(value instanceof SQLTextLiteralExpr);\n        if (quote) {\n            print('\\'');\n        }\n        value.accept(this);\n        if (quote) {\n            print('\\'');\n        }\n\n        SQLIntervalUnit unit = x.getUnit();\n        if (unit != null) {\n            print(' ');\n            print0(ucase ? unit.name : unit.nameLCase);\n        }\n        return false;\n    }\n\n    public Boolean getPrintStatementAfterSemi() {\n        return printStatementAfterSemi;\n    }\n\n    public void setPrintStatementAfterSemi(Boolean printStatementAfterSemi) {\n        this.printStatementAfterSemi = printStatementAfterSemi;\n    }\n\n    public void config(VisitorFeature... features) {\n        for (VisitorFeature feature : features) {\n            config(feature, true);\n        }\n    }\n\n    public void config(VisitorFeature feature, boolean state) {\n        super.config(feature, state);\n        if (feature == VisitorFeature.OutputUCase) {\n            this.ucase = state;\n        } else if (feature == VisitorFeature.OutputParameterized) {\n            this.parameterized = state;\n        } else if (feature == VisitorFeature.OutputParameterizedQuesUnMergeInList) {\n            this.parameterizedQuesUnMergeInList = state;\n        } else if (feature == VisitorFeature.OutputParameterizedQuesUnMergeValuesList) {\n            this.parameterizedQuesUnMergeValuesList = state;\n        } else if (feature == VisitorFeature.OutputParameterizedUnMergeShardingTable) {\n            this.shardingSupport = !state;\n            this.parameterizedQuesUnMergeValuesList = state;\n        } else if (feature == VisitorFeature.OutputNameQuote) {\n            this.printNameQuote = state;\n        }\n    }\n\n    public void setFeatures(int features) {\n        super.setFeatures(features);\n        this.ucase = isEnabled(VisitorFeature.OutputUCase);\n        this.parameterized = isEnabled(VisitorFeature.OutputParameterized);\n        this.parameterizedQuesUnMergeInList = isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeInList);\n        this.parameterizedQuesUnMergeValuesList = isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeValuesList);\n        this.shardingSupport = !isEnabled(VisitorFeature.OutputParameterizedUnMergeShardingTable);\n        this.printNameQuote = isEnabled(VisitorFeature.OutputNameQuote);\n    }\n\n    /////////////// for oracle\n    public boolean visit(OracleCursorExpr x) {\n        print0(ucase ? \"CURSOR(\" : \"cursor(\");\n        this.indentCount++;\n        println();\n        x.getQuery().accept(this);\n        this.indentCount--;\n        println();\n        print(')');\n        return false;\n    }\n\n    public boolean visit(OracleDatetimeExpr x) {\n        x.getExpr().accept(this);\n        SQLExpr timeZone = x.getTimeZone();\n\n        if (timeZone instanceof SQLIdentifierExpr) {\n            if (((SQLIdentifierExpr) timeZone).getName().equalsIgnoreCase(\"LOCAL\")) {\n                print0(ucase ? \" AT LOCAL\" : \" at local\");\n                return false;\n            }\n        }\n\n        print0(ucase ? \" AT TIME ZONE \" : \" at time zone \");\n        timeZone.accept(this);\n\n        return false;\n    }\n\n    public boolean visit(SQLAtTimeZoneExpr x) {\n        x.getExpr().accept(this);\n        SQLExpr timeZone = x.getTimeZone();\n\n        if (timeZone instanceof SQLIdentifierExpr) {\n            if (((SQLIdentifierExpr) timeZone).getName().equalsIgnoreCase(\"LOCAL\")) {\n                print0(ucase ? \" AT LOCAL\" : \" at local\");\n                return false;\n            }\n        }\n\n        print0(ucase ? \" AT TIME ZONE \" : \" at time zone \");\n        timeZone.accept(this);\n\n        return false;\n    }\n\n    ///////////// for odps & hive\n    @Override\n    public boolean visit(SQLLateralViewTableSource x) {\n        SQLTableSource tableSource = x.getTableSource();\n        if (tableSource != null) {\n            tableSource.accept(this);\n        }\n\n        this.indentCount++;\n        println();\n        print0(ucase ? \"LATERAL VIEW \" : \"lateral view \");\n\n        if (x.isOuter()) {\n            print0(ucase ? \"OUTER \" : \"outer \");\n        }\n\n        x.getMethod().accept(this);\n        if (x.getAlias() != null) {\n            print(' ');\n            print0(x.getAlias());\n        }\n\n        if (x.getColumns() != null && x.getColumns().size() > 0) {\n            print0(ucase ? \" AS \" : \" as \");\n            printAndAccept(x.getColumns(), \", \");\n        }\n\n        SQLExpr on = x.getOn();\n        if (on != null) {\n            println();\n            print0(ucase ? \"ON \" : \"on \");\n            printExpr(on);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowErrorsStatement x) {\n        print0(ucase ? \"SHOW ERRORS\" : \"show errors\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowRecylebinStatement x) {\n        print0(ucase ? \"SHOW RECYCLEBIN\" : \"show recyclebin\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowCatalogsStatement x) {\n        print0(ucase ? \"SHOW CATALOGS\" : \"show catalogs\");\n        final SQLExpr like = x.getLike();\n        if (like != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            printExpr(like);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowFunctionsStatement x) {\n        if (x.getKind() != null) {\n            print0(ucase ? \"SHOW \" : \"show \");\n            printExpr(x.getKind());\n            print0(ucase ? \" FUNCTIONS\" : \" functions\");\n        } else {\n            print0(ucase ? \"SHOW FUNCTIONS\" : \"show functions\");\n        }\n\n        final SQLExpr like = x.getLike();\n        if (like != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            printExpr(like);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowSessionStatement x) {\n        print0(ucase ? \"SHOW SESSION\" : \"show session\");\n        final SQLExpr like = x.getLike();\n        if (like != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            printExpr(like);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterCharacter x) {\n        if (x.getCharacterSet() != null) {\n            print0(ucase ? \"CHARACTER SET = \" : \"character set = \");\n            x.getCharacterSet().accept(this);\n        }\n\n        if (x.getCollate() != null) {\n            if (x.getCharacterSet() != null) {\n                print0(\", \");\n            }\n            print0(ucase ? \"COLLATE = \" : \"collate = \");\n            x.getCollate().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRecordDataType x) {\n        print0(ucase ? \"RECORD (\" : \"record (\");\n        indentCount++;\n        println();\n        List<SQLColumnDefinition> columns = x.getColumns();\n        for (int i = 0; i < columns.size(); i++) {\n            if (i != 0) {\n                println();\n            }\n            columns.get(i).accept(this);\n            if (i != columns.size() - 1) {\n                print0(\", \");\n            }\n        }\n        indentCount--;\n        println();\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExprStatement x) {\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBlockStatement x) {\n        if (!x.getParameters().isEmpty()) {\n            this.indentCount++;\n            if (x.getParent() instanceof SQLCreateProcedureStatement) {\n                SQLCreateProcedureStatement procedureStatement = (SQLCreateProcedureStatement) x.getParent();\n                if (procedureStatement.isCreate()) {\n                    printIndent();\n                }\n            }\n            if (!(x.getParent() instanceof SQLCreateProcedureStatement\n                    || x.getParent() instanceof SQLCreateFunctionStatement\n                    || x.getParent() instanceof OracleFunctionDataType\n                    || x.getParent() instanceof OracleProcedureDataType)\n            ) {\n                print0(ucase ? \"DECLARE\" : \"declare\");\n                println();\n            }\n\n            for (int i = 0, size = x.getParameters().size(); i < size; ++i) {\n                if (i != 0) {\n                    println();\n                }\n                SQLParameter param = x.getParameters().get(i);\n                param.accept(this);\n                print(';');\n            }\n\n            this.indentCount--;\n            println();\n        }\n        if (x.isHaveBeginEnd()) {\n            print0(ucase ? \"BEGIN\" : \"begin\");\n        }\n        this.indentCount++;\n\n        for (int i = 0, size = x.getStatementList().size(); i < size; ++i) {\n            println();\n            SQLStatement stmt = x.getStatementList().get(i);\n            stmt.accept(this);\n        }\n        this.indentCount--;\n\n        SQLStatement exception = x.getException();\n        if (exception != null) {\n            println();\n            exception.accept(this);\n        }\n\n        println();\n        if (x.isHaveBeginEnd()) {\n            print0(ucase ? \"END;\" : \"end;\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateProcedureStatement x) {\n        boolean create = x.isCreate();\n        if (!create) {\n            print0(ucase ? \"PROCEDURE \" : \"procedure \");\n        } else if (x.isOrReplace()) {\n            print0(ucase ? \"CREATE OR REPLACE PROCEDURE \" : \"create or replace procedure \");\n        } else {\n            print0(ucase ? \"CREATE PROCEDURE \" : \"create procedure \");\n        }\n        x.getName().accept(this);\n\n        int paramSize = x.getParameters().size();\n\n        if (paramSize > 0) {\n            print0(\" (\");\n            this.indentCount++;\n            println();\n\n            for (int i = 0; i < paramSize; ++i) {\n                if (i != 0) {\n                    print0(\", \");\n                    println();\n                }\n                SQLParameter param = x.getParameters().get(i);\n                param.accept(this);\n            }\n\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        SQLName authid = x.getAuthid();\n        if (authid != null) {\n            print(ucase ? \" AUTHID \" : \" authid \");\n            authid.accept(this);\n        }\n\n        SQLStatement block = x.getBlock();\n        String wrappedSource = x.getWrappedSource();\n        if (wrappedSource != null) {\n            print0(ucase ? \" WRAPPED \" : \" wrapped \");\n            print0(wrappedSource);\n        } else {\n            if (block != null && !create) {\n                println();\n                print(\"IS\");\n                println();\n            } else {\n                println();\n                if (block instanceof SQLBlockStatement) {\n                    SQLBlockStatement blockStatement = (SQLBlockStatement) block;\n                    if (blockStatement.getParameters().size() > 0 || authid != null) {\n                        println(ucase ? \"AS\" : \"as\");\n                    } else {\n                        println(ucase ? \"IS\" : \"is\");\n                    }\n                }\n            }\n\n            String javaCallSpec = x.getJavaCallSpec();\n            if (javaCallSpec != null) {\n                print0(ucase ? \"LANGUAGE JAVA NAME '\" : \"language java name '\");\n                print0(javaCallSpec);\n                print('\\'');\n                return false;\n            }\n        }\n\n        boolean afterSemi = false;\n        if (block != null) {\n            block.accept(this);\n\n            if (block instanceof SQLBlockStatement\n                    && ((SQLBlockStatement) block).getStatementList().size() > 0) {\n                afterSemi = ((SQLBlockStatement) block).getStatementList().get(0).isAfterSemi();\n            }\n        }\n\n        if ((!afterSemi) && x.getParent() instanceof OracleCreatePackageStatement) {\n            print(';');\n        }\n        return false;\n    }\n\n    protected boolean hiveVisit(SQLExternalRecordFormat x) {\n        indentCount++;\n        if (x.getDelimitedBy() != null) {\n            println();\n            print0(ucase ? \"LINES TERMINATED BY \" : \"lines terminated by \");\n            x.getDelimitedBy().accept(this);\n        }\n\n        SQLExpr terminatedBy = x.getTerminatedBy();\n        if (terminatedBy != null) {\n            println();\n            print0(ucase ? \"FIELDS TERMINATED BY \" : \"fields terminated by \");\n            terminatedBy.accept(this);\n        }\n\n        SQLExpr escapedBy = x.getEscapedBy();\n        if (escapedBy != null) {\n            println();\n            print0(ucase ? \"ESCAPED BY \" : \"escaped by \");\n            escapedBy.accept(this);\n        }\n\n        SQLExpr collectionItemsTerminatedBy = x.getCollectionItemsTerminatedBy();\n        if (collectionItemsTerminatedBy != null) {\n            println();\n            print0(ucase ? \"COLLECTION ITEMS TERMINATED BY \" : \"collection items terminated by \");\n            collectionItemsTerminatedBy.accept(this);\n        }\n\n        SQLExpr mapKeysTerminatedBy = x.getMapKeysTerminatedBy();\n        if (mapKeysTerminatedBy != null) {\n            println();\n            print0(ucase ? \"MAP KEYS TERMINATED BY \" : \"map keys terminated by \");\n            mapKeysTerminatedBy.accept(this);\n        }\n\n        SQLExpr linesTerminatedBy = x.getLinesTerminatedBy();\n        if (linesTerminatedBy != null) {\n            println();\n            print0(ucase ? \"LINES TERMINATED BY \" : \"lines terminated by \");\n            linesTerminatedBy.accept(this);\n        }\n\n        SQLExpr nullDefinedAs = x.getNullDefinedAs();\n        if (nullDefinedAs != null) {\n            println();\n            print0(ucase ? \"NULL DEFINED AS \" : \"null defined as \");\n            nullDefinedAs.accept(this);\n        }\n\n        SQLExpr serde = x.getSerde();\n        if (serde != null) {\n            println();\n            print0(ucase ? \"SERDE \" : \"serde \");\n            serde.accept(this);\n        }\n\n        indentCount--;\n\n        return false;\n    }\n\n    public boolean visit(SQLExternalRecordFormat x) {\n        SQLExpr delimitedBy = x.getDelimitedBy();\n        if (delimitedBy != null) {\n            println();\n            print0(ucase ? \"RECORDS DELIMITED BY \" : \"records delimited by \");\n            delimitedBy.accept(this);\n        }\n\n        Boolean logfile = x.getLogfile();\n        if (logfile != null) {\n            if (logfile) {\n                print0(ucase ? \" LOGFILE\" : \" logfile\");\n            } else {\n                print0(ucase ? \" NOLOGFILE\" : \" nologfile\");\n            }\n        }\n\n        Boolean badfile = x.getBadfile();\n        if (badfile != null) {\n            if (badfile) {\n                print0(ucase ? \" BADFILE\" : \" badfile\");\n            } else {\n                print0(ucase ? \" NOBADFILE\" : \" nobadfile\");\n            }\n        }\n\n        SQLExpr terminatedBy = x.getTerminatedBy();\n        if (terminatedBy != null) {\n            println();\n            print0(ucase ? \"FIELDS TERMINATED BY \" : \"fields terminated by \");\n            terminatedBy.accept(this);\n        }\n\n        if (x.isLtrim()) {\n            print0(ucase ? \" LTRIM\" : \" ltrim\");\n        }\n\n        if (x.isMissingFieldValuesAreNull()) {\n            print0(ucase ? \" MISSING FIELD VALUES ARE NULL\" : \" missing field values are null\");\n        }\n\n        if (x.isRejectRowsWithAllNullFields()) {\n            print0(ucase ? \" REJECT ROWS WITH ALL NULL FIELDS\" : \" reject rows with all null fields\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLArrayDataType x) {\n        final List<SQLExpr> arguments = x.getArguments();\n        if (Boolean.TRUE.equals(x.getAttribute(\"ads.arrayDataType\"))) {\n            x.getComponentType().accept(this);\n            print('[');\n            printAndAccept(arguments, \", \");\n            print(']');\n        } else {\n            SQLDataType componentType = x.getComponentType();\n            if (x.isUsedForCast() && componentType != null && componentType.getArguments() != null && componentType.getArguments().size() > 0) {\n                componentType.accept(this);\n                print0(ucase ? \" ARRAY\" : \" array\");\n            } else if (componentType != null) {\n                print0(ucase ? \"ARRAY<\" : \"array<\");\n                componentType.accept(this);\n                print('>');\n            } else {\n                print0(ucase ? \"ARRAY\" : \"array\");\n            }\n\n            if (arguments.size() > 0) {\n                print('(');\n                printAndAccept(arguments, \", \");\n                print(')');\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMapDataType x) {\n        print0(ucase ? \"MAP<\" : \"map<\");\n\n        SQLDataType keyType = x.getKeyType();\n        SQLDataType valueType = x.getValueType();\n\n        keyType.accept(this);\n        print0(\", \");\n\n        valueType.accept(this);\n        print('>');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLStructDataType x) {\n        print0(ucase ? \"STRUCT<\" : \"struct<\");\n        List<SQLStructDataType.Field> fields = x.getFields();\n        boolean needPrintLine = false;\n        if (fields.size() > 5) {\n            needPrintLine = true;\n        } else {\n            for (SQLStructDataType.Field field : fields) {\n                SQLDataType fieldDataType = field.getDataType();\n                if (fieldDataType instanceof SQLArrayDataType || fieldDataType instanceof SQLStructDataType) {\n                    needPrintLine = true;\n                    break;\n                }\n            }\n        }\n        printlnAndAccept(x.getFields(), needPrintLine);\n        print('>');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRowDataType x) {\n        print0(ucase ? \"ROW(\" : \"row(\");\n        printAndAccept(x.getFields(), \",\");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnionDataType x) {\n        print0(ucase ? \"UNIONTYPE<\" : \"uniontype<\");\n        printAndAccept(x.getItems(), \", \");\n        print('>');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLStructDataType.Field x) {\n        SQLName name = x.getName();\n        if (name != null) {\n            name.accept(this);\n        }\n        SQLDataType dataType = x.getDataType();\n\n        if (dataType != null) {\n            if (x.getParent() instanceof SQLRowDataType) {\n                if (name != null) {\n                    print(' ');\n                }\n            } else {\n                print(':');\n            }\n\n            dataType.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableMergePartition x) {\n        print0(ucase ? \"MERGE \" : \"merge \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        println();\n        printlnAndAccept(x.getPartitions(), \", \");\n        println();\n        print0(ucase ? \"OVERWRITE\" : \"overwrite\");\n        println();\n        x.getOverwritePartition().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLPartitionSpec x) {\n        print0(ucase ? \"PARTITION (\" : \"partition (\");\n        printAndAccept(x.getItems(), \", \");\n        print(')');\n        return false;\n    }\n\n    public boolean visit(SQLPartitionSpec.Item x) {\n        x.getColumn().accept(this);\n        print0(\" = \");\n        x.getValue().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableSubpartitionAvailablePartitionNum x) {\n        print0(ucase ? \"SUBPARTITION_AVAILABLE_PARTITION_NUM = \" : \"subpartition_available_partition_num = \");\n        x.getNumber().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowDatabasesStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n        if (x.isFull()) {\n            print0(ucase ? \"FULL \" : \"full \");\n        }\n        if (x.isPhysical()) {\n            print0(ucase ? \"PHYSICAL \" : \"physical \");\n        }\n        print0(ucase ? \"DATABASES\" : \"databases\");\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        if (x.isExtra()) {\n            print0(ucase ? \" EXTRA\" : \" extra\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowTableGroupsStatement x) {\n        print0(ucase ? \"SHOW TABLEGROUPS\" : \"show tablegroups\");\n\n        if (x.getDatabase() != null) {\n            print0(ucase ? \" IN \" : \" in \");\n            x.getDatabase().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowColumnsStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.isFull()) {\n            print0(ucase ? \"SHOW FULL COLUMNS\" : \"show full columns\");\n        } else {\n            print0(ucase ? \"SHOW COLUMNS\" : \"show columns\");\n        }\n\n        if (x.getTable() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            if (x.getDatabase() != null) {\n                x.getDatabase().accept(this);\n                print('.');\n            }\n            x.getTable().accept(this);\n        }\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowCreateTableStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (x.isAll()) {\n            print0(ucase ? \"SHOW ALL CREATE TABLE \" : \"show all create table \");\n        } else {\n            print0(ucase ? \"SHOW CREATE TABLE \" : \"show create table \");\n        }\n        x.getName().accept(this);\n\n        if (x.getLikeMapping() != null) {\n            print0(ucase ? \" LIKE MAPPING (\" : \" like mapping ( \");\n            x.getLikeMapping().accept(this);\n            print0(\")\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowProcessListStatement x) {\n        print0(ucase ? \"SHOW \" : \"show \");\n\n        if (x.isFull()) {\n            print0(ucase ? \"FULL \" : \"full \");\n        }\n\n        print0(ucase ? \"PROCESSLIST\" : \"processlist\");\n\n        if (x.isMpp()) {\n            print0(ucase ? \" MPP\" : \" mpp\");\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            where.accept(this);\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            print(' ');\n            orderBy.accept(this);\n        }\n\n        SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            print(' ');\n            limit.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetOption x) {\n        print0(ucase ? \"SET TBLPROPERTIES (\" : \"set tblproperties (\");\n        printAndAccept(x.getOptions(), \", \");\n        print(')');\n\n        final SQLExpr on = x.getOn();\n        if (on != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            on.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetSerdeProperties x) {\n        print0(ucase ? \"SET SERDEPROPERTIES (\" : \"set serdeproperties (\");\n        printAndAccept(x.getSerdeProperties(), \", \");\n        print(')');\n\n        final SQLExpr on = x.getOn();\n        if (on != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            on.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowCreateViewStatement x) {\n        print0(ucase ? \"SHOW CREATE VIEW \" : \"show create view \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowViewsStatement x) {\n        print0(ucase ? \"SHOW VIEWS\" : \"show views\");\n        if (x.getDatabase() != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getDatabase().accept(this);\n        }\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableRenameIndex x) {\n        print0(ucase ? \"RENAME INDEX \" : \"rename index \");\n        x.getName().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLCreateRoleStatement x) {\n        print0(ucase ? \"CREATE ROLE \" : \"create role \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLDropRoleStatement x) {\n        print0(ucase ? \"DROP ROLE \" : \"drop role \");\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLMatchAgainstExpr x) {\n    }\n\n    @Override\n    public boolean visit(SQLMatchAgainstExpr x) {\n        print0(ucase ? \"MATCH (\" : \"match (\");\n        printAndAccept(x.getColumns(), \", \");\n        print(')');\n\n        print0(ucase ? \" AGAINST (\" : \" against (\");\n        x.getAgainst().accept(this);\n        if (x.getSearchModifier() != null) {\n            print(' ');\n            print0(ucase ? x.getSearchModifier().name : x.getSearchModifier().nameLCase);\n        }\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(MySqlPrimaryKey x) {\n        visit(x.getIndexDefinition());\n        /*\n        if (x.getName() != null) {\n            print0(ucase ? \"CONSTRAINT \" : \"constraint \");\n            x.getName().accept(this);\n            print(' ');\n        }\n\n        print0(ucase ? \"PRIMARY KEY\" : \"primary key\");\n\n        if (x.getIndexType() != null) {\n            print0(ucase ? \" USING \" : \" using \");\n            print0(x.getIndexType());\n        }\n\n        print0(\" (\");\n\n        for (int i = 0, size = x.getColumns().size(); i < size; ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            x.getColumns().get(i).accept(this);\n        }\n        print(')');\n\n        SQLExpr keyBlockSize = x.getKeyBlockSize();\n        if (keyBlockSize != null) {\n            print0(ucase ? \" KEY_BLOCK_SIZE = \" : \" key_block_size = \");\n            keyBlockSize.accept(this);\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n        */\n\n        return false;\n    }\n\n    public boolean visit(MySqlCreateTableStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        if (isPrettyFormat() && x.hasBeforeComment()) {\n            printlnComments(x.getBeforeCommentsDirect());\n        }\n\n        print0(ucase ? \"CREATE \" : \"create \");\n\n        for (SQLCommentHint hint : x.getHints()) {\n            hint.accept(this);\n            print(' ');\n        }\n\n        printCreateTableFeatures(x);\n\n        print0(ucase ? \"TABLE \" : \"table \");\n\n        if (x.isIfNotExists()) {\n            print0(ucase ? \"IF NOT EXISTS \" : \"if not exists \");\n        }\n\n        printTableSourceExpr(x.getName());\n\n        if (x.getLike() != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            x.getLike().accept(this);\n        }\n\n        printTableElements(x.getTableElementList());\n\n        if (x.isBroadCast()) {\n            print0(ucase ? \" BROADCAST\" : \" broadcast\");\n        }\n\n        List<SQLAssignItem> tableOptions = x.getTableOptions();\n        if (Boolean.TRUE.equals(x.getAttribute(\"ads.options\"))) {\n            if (tableOptions.size() > 0) {\n                println();\n                print0(ucase ? \"OPTIONS (\" : \"options (\");\n                printAndAccept(tableOptions, \", \");\n                print(')');\n            }\n        } else {\n            for (SQLAssignItem option : tableOptions) {\n                String key = ((SQLIdentifierExpr) option.getTarget()).getName();\n\n                print(' ');\n                print0(ucase ? key : key.toLowerCase());\n\n                if (\"TABLESPACE\".equals(key)) {\n                    print(' ');\n                    option.getValue().accept(this);\n                    continue;\n                }\n\n                print0(\" = \");\n\n                option.getValue().accept(this);\n            }\n        }\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        if (x.getDistributeByType() != null) {\n            println();\n            if (isEnabled(VisitorFeature.OutputDistributedLiteralInCreateTableStmt)) {\n                print0(ucase ? \"DISTRIBUTED BY \" : \"distributed by \");\n            } else {\n                print0(ucase ? \"DISTRIBUTE BY \" : \"distribute by \");\n            }\n\n            SQLName distributeByType = x.getDistributeByType();\n\n            if (\"HASH\".equalsIgnoreCase(distributeByType.getSimpleName())) {\n                print0(ucase ? \"HASH(\" : \"hash(\");\n                printAndAccept(x.getDistributeBy(), \",\");\n                print0(\")\");\n\n            } else if (\"DUPLICATE\".equalsIgnoreCase(distributeByType.getSimpleName())) {\n                print0(ucase ? \"DUPLICATE(\" : \"duplicate(\");\n                printAndAccept(x.getDistributeBy(), \",\");\n                print0(\")\");\n\n            } else if (\"BROADCAST\".equalsIgnoreCase(distributeByType.getSimpleName())) {\n                print0(ucase ? \"BROADCAST \" : \"broadcast \");\n            }\n        }\n\n        printPartitionBy(x);\n\n        List<SQLSelectOrderByItem> clusteredBy = x.getClusteredBy();\n        if (clusteredBy.size() > 0) {\n            println();\n            print0(ucase ? \"CLUSTERED BY (\" : \"clustered by (\");\n            printAndAccept(clusteredBy, \",\");\n            print0(\")\");\n        }\n\n        SQLExpr dbPartitionBy = x.getDbPartitionBy();\n        if (dbPartitionBy != null) {\n            println();\n            print0(ucase ? \"DBPARTITION BY \" : \"dbpartition by \");\n            dbPartitionBy.accept(this);\n        }\n\n        SQLExpr dbpartitions = x.getDbpartitions();\n        if (dbpartitions != null) {\n            print0(ucase ? \" DBPARTITIONS \" : \" dbpartitions \");\n            dbpartitions.accept(this);\n        }\n\n        SQLExpr tbPartitionsBy = x.getTablePartitionBy();\n        if (tbPartitionsBy != null) {\n            println();\n            print0(ucase ? \"TBPARTITION BY \" : \"tbpartition by \");\n            tbPartitionsBy.accept(this);\n        }\n\n        SQLExpr tablePartitions = x.getTablePartitions();\n        if (tablePartitions != null) {\n            print0(ucase ? \" TBPARTITIONS \" : \" tbpartitions \");\n            tablePartitions.accept(this);\n        }\n\n        MySqlExtPartition extPartition = x.getExtPartition();\n        if (extPartition != null) {\n            println();\n            extPartition.accept(this);\n        }\n\n        if (x.getArchiveBy() != null) {\n            println();\n            print0(ucase ? \"ARCHIVE BY = \" : \"archive by = \");\n            x.getArchiveBy().accept(this);\n        }\n\n        if (x.getTableGroup() != null) {\n            println();\n            print0(ucase ? \"TABLEGROUP \" : \"tablegroup \");\n            x.getTableGroup().accept(this);\n        }\n\n        if (x.isReplace()) {\n            println();\n            print0(ucase ? \"REPLACE \" : \"replace \");\n        } else if (x.isIgnore()) {\n            println();\n            print0(ucase ? \"IGNORE \" : \"ignore \");\n        }\n\n        if (x.getSelect() != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            x.getSelect().accept(this);\n        }\n        if (x.getWithSelect() != null) {\n            println();\n            print0(ucase ? \"AS\" : \"as\");\n            println();\n            x.getWithSelect().accept(this);\n        }\n\n        if (x.getStoredBy() != null) {\n            println();\n            print0(ucase ? \" STORED BY \" : \" stored by \");\n            x.getStoredBy().accept(this);\n        }\n\n        if (x.getWith().size() > 0) {\n            println();\n            print0(ucase ? \" WITH (\" : \" with (\");\n            int i = 0;\n            for (Map.Entry<String, SQLName> option : x.getWith().entrySet()) {\n                if (i != 0) {\n                    print0(\", \");\n                }\n                print0(option.getKey());\n                print0(\" = \");\n                option.getValue().accept(this);\n                i++;\n            }\n            print(')');\n        }\n\n        if (x.getWithData() != null) {\n            println();\n            if (x.getWithData()) {\n                print0(ucase ? \"WITH DATA\" : \"with data\");\n            } else {\n                print0(ucase ? \"WITH NO DATA\" : \"with no data\");\n            }\n        }\n\n        for (SQLCommentHint hint : x.getOptionHints()) {\n            print(' ');\n            hint.accept(this);\n        }\n        return false;\n    }\n\n    protected void printCreateTableFeatures(SQLCreateTableStatement x) {\n        if (x.isEnabled(SQLCreateTableStatement.Feature.OrReplace)) {\n            print0(ucase ? \"OR REPLACE \" : \"or replace \");\n        }\n        SQLCreateTableStatement.Feature[] features = {\n                SQLCreateTableStatement.Feature.Global,\n                SQLCreateTableStatement.Feature.Local,\n                SQLCreateTableStatement.Feature.Temporary,\n                SQLCreateTableStatement.Feature.Shadow,\n                SQLCreateTableStatement.Feature.External,\n                SQLCreateTableStatement.Feature.Transactional,\n                SQLCreateTableStatement.Feature.Dimension,\n                SQLCreateTableStatement.Feature.Unlogged\n        };\n\n        for (SQLCreateTableStatement.Feature feature : features) {\n            if (x.isEnabled(feature)) {\n                String name = feature.name();\n                print0(ucase ? name.toUpperCase() : name.toLowerCase());\n                print(' ');\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLShowPartitionsStmt x) {\n        print0(ucase ? \"SHOW PARTITIONS \" : \"show partitions \");\n        x.getTableSource().accept(this);\n\n        if (x.getPartition().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print0(\")\");\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            where.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLValuesExpr x) {\n        print0(ucase ? \"VALUES\" : \"values\");\n        printAndAccept(x.getValues(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDumpStatement x) {\n        List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        print0(ucase ? \"DUMP DATA \" : \"dump data \");\n\n        if (x.isOverwrite()) {\n            print0(ucase ? \"OVERWRITE \" : \"overwrite \");\n        }\n\n        SQLExprTableSource into = x.getInto();\n        if (into != null) {\n            print0(ucase ? \"INTO \" : \"into \");\n            into.accept(this);\n            print0(\" \");\n        }\n\n        x.getSelect().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLValuesTableSource x) {\n        List<SQLName> columns = x.getColumns();\n\n        boolean quote = columns.size() > 0;\n        if (quote) {\n            if (x.getParent() instanceof SQLSelect && x.getParent().getParent() instanceof SQLCreateViewStatement) {\n                quote = false;\n            }\n        }\n        if (quote) {\n            print('(');\n        }\n        print0(ucase ? \"VALUES \" : \"values \");\n        printAndAccept(x.getValues(), \", \");\n\n        if (quote) {\n            print(')');\n        }\n\n        String alias = x.getAlias();\n        if (alias != null) {\n            print0(ucase ? \" AS \" : \" as \");\n            print0(alias);\n        }\n\n        if (columns.size() > 0) {\n            if (alias == null) {\n                print0(ucase ? \" AS\" : \" as\");\n            }\n            print0(\" (\");\n            printAndAccept(columns, \", \");\n            print(')');\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRefreshTableStatement x) {\n        print0(ucase ? \"REFRESH TABLE \" : \"refresh table \");\n        x.getName().accept(this);\n        return false;\n    }\n    @Override\n    public boolean visit(SQLExtractExpr x) {\n        print0(ucase ? \"EXTRACT(\" : \"extract(\");\n        print0(x.getUnit().name());\n        print0(ucase ? \" FROM \" : \" from \");\n        x.getValue().accept(this);\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLWindow x) {\n        x.getName().accept(this);\n        print0(ucase ? \" AS \" : \" as \");\n        x.getOver().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLJSONExpr x) {\n        return visit((SQLTypeExpr) x);\n    }\n\n    @Override\n    public boolean visit(SQLAnnIndex x) {\n        print0(ucase ? \"ANNINDX (type = '\" : \"annindx (type = '\");\n\n        final int indexType = x.getIndexType();\n        if ((indexType & SQLAnnIndex.IndexType.Flat.mask) != 0) {\n            print0(ucase ? \"FLAT\" : \"flat\");\n        }\n\n        if ((indexType & SQLAnnIndex.IndexType.FastIndex.mask) != 0) {\n            if (indexType != SQLAnnIndex.IndexType.FastIndex.mask) {\n                print(',');\n            }\n            print0(ucase ? \"FLAT_INDEX\" : \"flat_index\");\n        }\n\n        print0(ucase ? \"', DISTANCE = '\" : \"', distance = '\");\n        print0(x.getDistance().name());\n        print0(\"'\");\n\n        final int rtIndexType = x.getRtIndexType();\n        if (rtIndexType != 0) {\n            print0(ucase ? \", RTTYPE = '\" : \", rttype = '\");\n\n            if ((rtIndexType & SQLAnnIndex.IndexType.Flat.mask) != 0) {\n                print0(ucase ? \"FLAT\" : \"flat\");\n            }\n\n            if ((rtIndexType & SQLAnnIndex.IndexType.FastIndex.mask) != 0) {\n                if (rtIndexType != SQLAnnIndex.IndexType.FastIndex.mask) {\n                    print(',');\n                }\n                print0(ucase ? \"FLAT_INDEX \" : \"flat_index \");\n            }\n\n            print('\\'');\n        }\n\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableRecoverPartitions x) {\n        print0(ucase ? \"RECOVER PARTITIONS\" : \"recover partitions\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterIndexStatement x) {\n        print0(ucase ? \"ALTER INDEX \" : \"alter index \");\n        x.getName().accept(this);\n\n        if (x.getRenameTo() != null) {\n            print0(ucase ? \" RENAME TO \" : \" rename to \");\n            x.getRenameTo().accept(this);\n        }\n\n        final SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            table.accept(this);\n        }\n\n        if (x.getPartitions().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartitions(), \", \");\n            print(')');\n        }\n\n        if (x.isCompile()) {\n            print0(ucase ? \" COMPILE\" : \" compile\");\n        }\n\n        if (Boolean.TRUE.equals(x.getEnable())) {\n            print0(ucase ? \" ENABLE\" : \" enable\");\n        }\n        if (Boolean.FALSE.equals(x.getEnable())) {\n            print0(ucase ? \" DISABLE\" : \" disable\");\n        }\n\n        if (x.isUnusable()) {\n            print0(ucase ? \" UNUSABLE\" : \" unusable\");\n        }\n\n        if (x.getMonitoringUsage() != null) {\n            print0(ucase ? \" MONITORING USAGE\" : \" monitoring usage\");\n        }\n\n        if (x.getRebuild() != null) {\n            print(' ');\n            x.getRebuild().accept(this);\n        }\n\n        if (x.getParallel() != null) {\n            print0(ucase ? \" PARALLEL\" : \" parallel\");\n            x.getParallel().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterIndexStatement.Rebuild x) {\n        print0(ucase ? \"REBUILD\" : \"rebuild\");\n\n        if (x.getOption() != null) {\n            print(' ');\n            x.getOption().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowIndexesStatement x) {\n        final List<SQLCommentHint> headHints = x.getHeadHintsDirect();\n        if (headHints != null) {\n            for (SQLCommentHint hint : headHints) {\n                hint.accept(this);\n                println();\n            }\n        }\n\n        print0(ucase ? \"SHOW \" : \"show \");\n        print0(ucase ? x.getType().toUpperCase() : x.getType().toLowerCase());\n\n        final SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            x.getTable().accept(this);\n        }\n\n        if (x.getHints() != null && x.getHints().size() > 0) {\n            print(' ');\n            printAndAccept(x.getHints(), \" \");\n        }\n\n        if (x.getWhere() != null) {\n            print0(ucase ? \" WHERE \" : \" where \");\n            x.getWhere().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAnalyzeTableStatement x) {\n        print0(ucase ? \"ANALYZE TABLE \" : \"analyze table \");\n\n        printAndAccept(x.getTables(), \", \");\n\n        SQLPartitionRef partition = x.getPartition();\n        if (partition != null) {\n            print(' ');\n            partition.accept(this);\n        }\n\n        if (x.isComputeStatistics()) {\n            print0(ucase ? \" COMPUTE STATISTICS\" : \" compute statistics\");\n        }\n\n        if (x.isForColums()) {\n            print0(ucase ? \" FOR COLUMNS\" : \" for columns\");\n        }\n\n        if (x.isCacheMetadata()) {\n            print0(ucase ? \" CACHE METADATA\" : \" cache metadata\");\n        }\n\n        if (x.isNoscan()) {\n            print0(ucase ? \" NOSCAN\" : \" noscan\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionRef x) {\n        print0(ucase ? \"PARTITION (\" : \"partition (\");\n        for (int i = 0; i < x.getItems().size(); i++) {\n            if (i != 0) {\n                print(\", \");\n            }\n            SQLPartitionRef.Item item = x.getItems().get(i);\n            visit(item);\n        }\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(SQLPartitionRef.Item x) {\n        visit(x.getColumnName());\n\n        SQLExpr value = x.getValue();\n        if (value != null) {\n            SQLBinaryOperator operator = x.getOperator();\n            if (operator == null) {\n                print(\" = \");\n            } else {\n                printOperator(operator);\n            }\n\n            printExpr(value);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLExportTableStatement x) {\n        print0(ucase ? \"EXPORT TABLE \" : \"export table \");\n        x.getTable().accept(this);\n\n        if (x.getPartition().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print(')');\n        }\n\n        final SQLExpr to = x.getTo();\n        if (to != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            to.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLImportTableStatement x) {\n        if (x.isExtenal()) {\n            print0(ucase ? \"IMPORT EXTERNAL\" : \"import external\");\n        } else {\n            print0(ucase ? \"IMPORT\" : \"import\");\n        }\n\n        final SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            print0(ucase ? \" TABLE \" : \" table \");\n            table.accept(this);\n        }\n\n        if (x.getPartition().size() > 0) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(x.getPartition(), \", \");\n            print(')');\n        }\n\n        final SQLExpr from = x.getFrom();\n        if (from != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            from.accept(this);\n        }\n\n        final SQLExpr location = x.getLocation();\n        if (location != null) {\n            print0(ucase ? \" LOCATION \" : \" location \");\n            location.accept(this);\n        }\n\n        if (x.getVersion() != null) {\n            print0(ucase ? \" VERSIOIN = \" : \" version = \");\n            x.getVersion().accept(this);\n        }\n\n        if (x.isUsingBuild()) {\n            print0(ucase ? \" BUILD = 'Y'\" : \" build = 'y'\");\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLTableSampling x) {\n        print0(ucase ? \"TABLESAMPLE \" : \"tablesample \");\n\n        if (x.isBernoulli()) {\n            print0(ucase ? \"BERNOULLI \" : \"bernoulli \");\n        } else if (x.isSystem()) {\n            print0(ucase ? \"SYSTEM \" : \"system \");\n        }\n\n        print('(');\n\n        final SQLExpr bucket = x.getBucket();\n        if (bucket != null) {\n            print0(ucase ? \"BUCKET \" : \"bucket \");\n            bucket.accept(this);\n        }\n\n        final SQLExpr outOf = x.getOutOf();\n        if (outOf != null) {\n            print0(ucase ? \" OUT OF \" : \" out of \");\n            outOf.accept(this);\n        }\n\n        final SQLExpr on = x.getOn();\n        if (on != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            on.accept(this);\n        }\n\n        final SQLExpr percent = x.getPercent();\n        if (percent != null) {\n            percent.accept(this);\n            print0(ucase ? \" PERCENT\" : \" percent\");\n        }\n\n        final SQLExpr rows = x.getRows();\n        if (rows != null) {\n            rows.accept(this);\n\n            if (!JdbcUtils.isMysqlDbType(dbType) && !JdbcUtils.isPgsqlDbType(dbType)) {\n                print0(ucase ? \" ROWS\" : \" rows\");\n            }\n        }\n\n        final SQLExpr size = x.getByteLength();\n        if (size != null) {\n            size.accept(this);\n        }\n\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSizeExpr x) {\n        x.getValue().accept(this);\n        print0(x.getUnit().name());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableArchivePartition x) {\n        print0(ucase ? \"ARCHIVE PARTITION (\" : \"archive partition (\");\n        printAndAccept(x.getPartitions(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableUnarchivePartition x) {\n        print0(ucase ? \"UNARCHIVE PARTITION (\" : \"unarchive partition (\");\n        printAndAccept(x.getPartitions(), \", \");\n        print(')');\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateOutlineStatement x) {\n        print0(ucase ? \"CREATE OUTLINE \" : \"create outline \");\n        x.getName().accept(this);\n        print0(ucase ? \" ON \" : \" on \");\n        x.getOn().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropOutlineStatement x) {\n        print0(ucase ? \"DROP OUTLINE \" : \"drop outline \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropOfflineModelStatement x) {\n        print0(ucase ? \"DROP OFFLINEMODEL \" : \"drop offlinemodel \");\n        if (x.isIfExists()) {\n            print0(ucase ? \"IF EXISTS \" : \"if exists \");\n        }\n        x.getName().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowQueryTaskStatement x) {\n        if (x.isFull()) {\n            print0(ucase ? \"SHOW FULL QUERY_TASK\" : \"show full query_task\");\n        } else {\n            print0(ucase ? \"SHOW QUERY_TASK\" : \"show query_task\");\n        }\n\n        if (x.getUser() != null) {\n            println();\n            print0(ucase ? \"FOR \" : \"for \");\n            printExpr(x.getUser());\n        }\n\n        final SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where);\n        }\n\n        final SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            visit(orderBy);\n        }\n\n        final SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            println();\n            visit(limit);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowOutlinesStatement x) {\n        print0(ucase ? \"SHOW OUTLINES\" : \"show outlines\");\n\n        final SQLExpr where = x.getWhere();\n        if (where != null) {\n            println();\n            print0(ucase ? \"WHERE \" : \"where \");\n            printExpr(where);\n        }\n\n        final SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            println();\n            visit(orderBy);\n        }\n\n        final SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            println();\n            visit(limit);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPurgeTableStatement x) {\n        print0(ucase ? \"PURGE TABLE \" : \"purge table \");\n        x.getTable().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPurgeRecyclebinStatement x) {\n        print0(ucase ? \"PURGE RECYCLEBIN\" : \"purge recyclebin\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPurgeLogsStatement x) {\n        print0(ucase ? \"PURGE\" : \"purge\");\n\n        if (x.isBinary()) {\n            print0(ucase ? \" BINARY\" : \" binary\");\n        }\n\n        if (x.isMaster()) {\n            print0(ucase ? \" MASTER\" : \" master\");\n        }\n\n        if (x.isAll()) {\n            print0(ucase ? \" ALL\" : \" all\");\n            return false;\n        }\n\n        print0(ucase ? \" LOGS\" : \" logs\");\n\n        final SQLExpr to = x.getTo();\n        if (to != null) {\n            print0(ucase ? \" TO \" : \" to \");\n            to.accept(this);\n        }\n\n        if (x.getBefore() != null) {\n            print0(ucase ? \" BEFORE \" : \" before \");\n            x.getBefore().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterOutlineStatement x) {\n        print0(ucase ? \"ALTER OUTLINE \" : \"alter outline \");\n        x.getName().accept(this);\n\n        if (x.isResync()) {\n            print0(ucase ? \" RESYNC\" : \" resync\");\n        }\n\n        if (x.isDisable()) {\n            print0(ucase ? \" DISABLE\" : \" disable\");\n        }\n\n        if (x.isEnable()) {\n            print0(ucase ? \" ENABLE\" : \" enable\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddSupplemental x) {\n        print0(ucase ? \"ADD \" : \"add \");\n        x.getElement().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLDbLinkExpr x) {\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) x.getExpr();\n            SQLExpr owner = methodInvokeExpr.getOwner();\n            if (owner != null) {\n                printMethodOwner(owner);\n            }\n\n            String function = methodInvokeExpr.getMethodName();\n\n            printFunctionName(function);\n            print('@');\n            print0(x.getDbLink());\n\n            printMethodParameters(methodInvokeExpr);\n        } else {\n            if (expr != null) {\n                expr.accept(this);\n                print('@');\n            }\n            print0(x.getDbLink());\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowStatisticStmt x) {\n        if (x.isFull()) {\n            print0(ucase ? \"SHOW FULL STATS\" : \"show full stats\");\n        } else {\n            print0(ucase ? \"SHOW STATS\" : \"show stats\");\n        }\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (!partitions.isEmpty()) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(partitions, \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowStatisticListStmt x) {\n        print0(ucase ? \"SHOW STATISTIC_LIST\" : \"show statistic_list\");\n\n        SQLExprTableSource table = x.getTableSource();\n        if (table != null) {\n            print(' ');\n            table.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowPackagesStatement x) {\n        print0(ucase ? \"SHOW PACKAGES\" : \"show packages\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowGrantsStatement x) {\n        print0(ucase ? \"SHOW GRANTS\" : \"show grants\");\n        SQLExpr user = x.getUser();\n        if (user != null) {\n            print0(ucase ? \" FOR \" : \" for \");\n            user.accept(this);\n        }\n\n        SQLExpr on = x.getOn();\n        if (on != null) {\n            print0(ucase ? \" ON \" : \" on \");\n            on.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCurrentTimeExpr x) {\n        final SQLCurrentTimeExpr.Type type = x.getType();\n        print(ucase ? type.name : type.nameLCase);\n\n        String timeZone = x.getTimeZone();\n        if (timeZone != null) {\n            print(ucase ? \" AT TIME ZONE\" : \" at time zone\");\n            print0(timeZone);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCurrentUserExpr x) {\n        print(ucase ? \"CURRENT_USER\" : \"current_user\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAdhocTableSource x) {\n        final SQLCreateTableStatement definition = x.getDefinition();\n        definition.accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLExecuteImmediateStatement x) {\n        print(ucase ? \"EXECUTE IMMEDIATE \" : \"execute immediate \");\n        x.getDynamicSql().accept(this);\n        List<SQLExpr> into = x.getInto();\n        if (!into.isEmpty()) {\n            print(ucase ? \" INTO \" : \" into \");\n            printAndAccept(into, \", \");\n        }\n        return false;\n    }\n\n    public boolean visit(SQLContinueStatement x) {\n        print(ucase ? \"CONTINUE\" : \"continue\");\n        return false;\n    }\n\n    public boolean visit(SQLBreakStatement x) {\n        print(ucase ? \"BREAK\" : \"break\");\n        return false;\n    }\n\n    public boolean visit(SQLLeaveStatement x) {\n        print(ucase ? \"LEAVE\" : \"leave\");\n        return false;\n    }\n\n    protected void printCreateTableLike(SQLCreateTableStatement x) {\n        SQLExprTableSource like = x.getLike();\n        if (like == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"LIKE \" : \"like \");\n        like.accept(this);\n    }\n\n    protected void printPartitionedBy(SQLCreateTableStatement x) {\n        List<SQLColumnDefinition> partitionColumns = x.getPartitionColumns();\n        int partitionSize = partitionColumns.size();\n        if (partitionSize == 0) {\n            return;\n        }\n\n        println();\n        print0(ucase ? \"PARTITIONED BY (\" : \"partitioned by (\");\n        this.indentCount++;\n        println();\n        for (int i = 0; i < partitionSize; ++i) {\n            SQLColumnDefinition column = partitionColumns.get(i);\n            printPartitionedByColumn(column);\n\n            if (i != partitionSize - 1) {\n                print(',');\n            }\n            if (this.isPrettyFormat() && column.hasAfterComment()) {\n                print(' ');\n                printlnComment(column.getAfterCommentsDirect());\n            }\n\n            if (i != partitionSize - 1) {\n                println();\n            }\n        }\n        this.indentCount--;\n        println();\n        print(')');\n    }\n\n    protected void printLifeCycle(SQLExpr lifeCycle) {\n        if (lifeCycle == null) {\n            return;\n        }\n        println();\n        print0(ucase ? \"LIFECYCLE \" : \"lifecycle \");\n        lifeCycle.accept(this);\n    }\n\n    protected void printPartitionedByColumn(SQLColumnDefinition column) {\n        column.accept(this);\n    }\n\n    protected void printSerdeProperties(Map<String, SQLObject> serdeProperties) {\n        if (serdeProperties.isEmpty()) {\n            return;\n        }\n\n        println();\n        print0(ucase ? \"WITH SERDEPROPERTIES (\" : \"with serdeproperties (\");\n        incrementIndent();\n        println();\n        int i = 0;\n        for (Map.Entry<String, SQLObject> option : serdeProperties.entrySet()) {\n            if (i != 0) {\n                print(\",\");\n                println();\n            }\n            String key = option.getKey();\n\n            boolean unquote = false;\n            char c0;\n            if (key.length() > 0 && (c0 = key.charAt(0)) != '\"' && c0 != '`' && c0 != '\\'') {\n                unquote = true;\n            }\n\n            if (unquote) {\n                print('\\'');\n            }\n            print0(key);\n            if (unquote) {\n                print('\\'');\n            }\n\n            print0(\" = \");\n            option.getValue().accept(this);\n            ++i;\n        }\n        decrementIndent();\n        println();\n        print(')');\n    }\n\n    protected void printTableOptionsPrefix(SQLCreateTableStatement x) {\n        println();\n        print0(ucase ? \"OPTIONS (\" : \"options (\");\n        incrementIndent();\n        println();\n    }\n\n    protected void printTableOptionsPostfix(SQLCreateTableStatement x) {\n        decrementIndent();\n        println();\n        print(')');\n    }\n\n    protected void printTableOption(SQLExpr name, SQLExpr value, int index) {\n        if (index != 0) {\n            print(\",\");\n            println();\n        }\n\n        String key = name.toString();\n\n        boolean unquote = false;\n        char c0;\n        if (!key.isEmpty() && (c0 = key.charAt(0)) != '\"' && c0 != '`' && c0 != '\\'') {\n            unquote = true;\n        }\n\n        if (unquote) {\n            print('\\'');\n        }\n        print0(key);\n        if (unquote) {\n            print('\\'');\n        }\n\n        print0(\" = \");\n        value.accept(this);\n    }\n\n    protected void printTableOptions(SQLCreateTableStatement x) {\n        List<SQLAssignItem> tblProperties = x.getTableOptions();\n        if (tblProperties.isEmpty()) {\n            return;\n        }\n\n        printTableOptionsPrefix(x);\n        int i = 0;\n        for (SQLAssignItem property : tblProperties) {\n            printTableOption(property.getTarget(), property.getValue(), i);\n            ++i;\n        }\n\n        printTableOptionsPostfix(x);\n    }\n\n    protected void printIntoBuckets(int buckets) {\n        if (buckets > 0) {\n            println();\n            print0(ucase ? \"INTO \" : \"into \");\n            print(buckets);\n            print0(ucase ? \" BUCKETS\" : \" buckets\");\n        }\n    }\n\n    protected void printIntoShards(int shards) {\n        if (shards > 0) {\n            println();\n            print0(ucase ? \"INTO \" : \"into \");\n            print(shards);\n            print0(ucase ? \" SHARDS\" : \" shards\");\n        }\n    }\n\n    protected void printLocation(SQLCreateTableStatement x) {\n        SQLExpr location = x.getLocation();\n        if (location != null) {\n            println();\n            print0(ucase ? \"LOCATION \" : \"location \");\n            printExpr(location, parameterized);\n        }\n    }\n\n    protected void printRowFormat(SQLCreateTableStatement x) {\n        SQLExternalRecordFormat format = x.getRowFormat();\n        if (format != null) {\n            println();\n            print0(ucase ? \"ROW FORMAT\" : \"row format\");\n            if (format.getSerde() == null) {\n                print0(ucase ? \" DELIMITED\" : \" delimited \");\n            }\n            visit(format);\n            println();\n        }\n    }\n    @Override\n    public boolean visit(HiveInputOutputFormat x) {\n        print0(ucase ? \"INPUTFORMAT \" : \"inputformat \");\n        x.getInput().accept(this);\n        println();\n        print0(ucase ? \"OUTPUTFORMAT \" : \"outputformat \");\n        x.getOutput().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLWhoamiStatement x) {\n        print0(ucase ? \"WHO AM I\" : \"who am i\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLForStatement x) {\n        print0(ucase ? \"FOR \" : \"for \");\n        x.getIndex().accept(this);\n        print0(ucase ? \" IN \" : \" in \");\n\n        SQLExpr range = x.getRange();\n        range.accept(this);\n\n        println();\n        print0(ucase ? \"LOOP\" : \"loop\");\n\n        this.indentCount++;\n        println();\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            SQLStatement stmt = x.getStatements().get(i);\n            stmt.accept(this);\n            if (i != size - 1) {\n                println();\n            }\n        }\n\n        this.indentCount--;\n        println();\n        print0(ucase ? \"END LOOP\" : \"end loop\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCopyFromStatement x) {\n        print0(ucase ? \"COPY \" : \"copy \");\n        SQLExprTableSource table = x.getTable();\n        table.accept(this);\n\n        List<SQLName> columns = x.getColumns();\n        if (columns.size() > 0) {\n            print('(');\n            printAndAccept(columns, \", \");\n            print(\")\");\n        }\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (partitions.size() > 0) {\n            print0(ucase ? \" PARTITIONS (\" : \" partitions (\");\n            printAndAccept(partitions, \", \");\n            print(\")\");\n        }\n\n        print0(ucase ? \" FROM \" : \" from \");\n        x.getFrom().accept(this);\n\n        SQLExpr accessKeyId = x.getAccessKeyId();\n        SQLExpr accessKeySecret = x.getAccessKeySecret();\n        if (accessKeyId != null || accessKeySecret != null) {\n            print0(ucase ? \" CREDENTIALS\" : \" credentials\");\n            if (accessKeyId != null) {\n                print0(ucase ? \" access_key_id \" : \" access_key_id \");\n                accessKeyId.accept(this);\n            }\n\n            if (accessKeySecret != null) {\n                print0(ucase ? \" ACCESS_KEY_SECRET \" : \" access_key_secret \");\n                accessKeySecret.accept(this);\n            }\n        }\n\n        List<SQLAssignItem> options = x.getOptions();\n        if (options.size() > 0) {\n            print0(ucase ? \" WITH (\" : \" with (\");\n            printAndAccept(options, \", \");\n            print(')');\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowUsersStatement x) {\n        print0(ucase ? \"SHOW USERS\" : \"show users\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSyncMetaStatement x) {\n        print0(ucase ? \"SYNC META TABLE\" : \"sync meta table\");\n\n        Boolean restrict = x.getRestrict();\n        if (restrict != null && restrict.booleanValue()) {\n            print0(ucase ? \" RESTRICT \" : \" restrict \");\n        }\n\n        Boolean ignore = x.getIgnore();\n        if (ignore != null && ignore.booleanValue()) {\n            print0(ucase ? \" IGNORE \" : \" ignore \");\n        }\n\n        SQLName from = x.getFrom();\n        if (from != null) {\n            print0(ucase ? \" FROM \" : \" from \");\n            from.accept(this);\n        }\n\n        SQLExpr like = x.getLike();\n        if (like != null) {\n            print0(ucase ? \" LIKE \" : \" like \");\n            like.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTableLike x) {\n        print0(ucase ? \"LIKE \" : \"like \");\n        x.getTable().accept(this);\n\n        if (x.isIncludeProperties()) {\n            print0(ucase ? \" INCLUDING PROPERTIES\" : \" including properties\");\n        } else if (x.isExcludeProperties()) {\n            print0(ucase ? \" EXCLUDING PROPERTIES\" : \" excluding properties\");\n        } else if (x.isIncludeDistribution()) {\n            print0(ucase ? \" INCLUDING DISTRIBUTION\" : \" including distribution\");\n        } else if (x.isExcludeDistribution()) {\n            print0(ucase ? \" EXCLUDING DISTRIBUTION\" : \" excluding distribution\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLValuesQuery x) {\n        print0(ucase ? \"VALUES \" : \"values \");\n        printAndAccept(x.getValues(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBuildTableStatement x) {\n        print0(ucase ? \"BUILD TABLE \" : \"build table \");\n\n        x.getTable().accept(this);\n\n        if (x.getVersion() != null) {\n            print0(ucase ? \" VERSION = \" : \" version = \");\n            x.getVersion().accept(this);\n        }\n\n        if (x.isWithSplit()) {\n            print0(ucase ? \" WITH SPLIT\" : \" with split\");\n        }\n\n        if (x.isForce()) {\n            print0(ucase ? \" FORCE = true\" : \" force = true\");\n        } else {\n            print0(ucase ? \" FORCE = false\" : \" force = false\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExportDatabaseStatement x) {\n        print0(ucase ? \"EXPORT DATABASE \" : \"export database \");\n\n        x.getDb().accept(this);\n\n        print0(ucase ? \" REALTIME = \" : \" realtime = \");\n        if (x.isRealtime()) {\n            print0(ucase ? \"'Y'\" : \"'y'\");\n        } else {\n            print0(ucase ? \"'N'\" : \"'n'\");\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLImportDatabaseStatement x) {\n        print0(ucase ? \"IMPORT DATABASE \" : \"import database \");\n\n        x.getDb().accept(this);\n\n        if (x.getStatus() != null) {\n            print0(ucase ? \" STATUS = \" : \" status = \");\n            x.getStatus().accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRenameUserStatement x) {\n        print0(ucase ? \"RENAME USER \" : \"rename user \");\n\n        x.getName().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubmitJobStatement x) {\n        print0(ucase ? \"SUBMIT JOB \" : \"submit job \");\n\n        if (x.isAwait()) {\n            print0(ucase ? \"AWAIT \" : \"await \");\n        }\n\n        x.getStatment().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRestoreStatement x) {\n        print0(ucase ? \"RESTORE \" : \"restore \");\n\n        x.getType().accept(this);\n        print0(ucase ? \" FROM \" : \" from \");\n\n        printAndAccept(x.getProperties(), \",\");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLArchiveTableStatement x) {\n        print0(ucase ? \"ARCHIVE TABLE \" : \"archive table \");\n\n        x.getTable().accept(this);\n\n        for (int i = 0; i < x.getSpIdList().size(); i++) {\n            if (i != 0) {\n                print0(\",\");\n            }\n            print0(\" \");\n            x.getSpIdList().get(i).accept(this);\n            print0(\":\");\n            x.getpIdList().get(i).accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBackupStatement x) {\n        print0(ucase ? \"BACKUP \" : \"backup \");\n\n        String type = x.getType().getSimpleName().toUpperCase();\n        String action = x.getAction().getSimpleName().toUpperCase();\n\n        if (\"BACKUP_DATA\".equalsIgnoreCase(type)) {\n            if (\"BACKUP\".equalsIgnoreCase(action)) {\n                print0(ucase ? \"DATA INTO \" : \"data into \");\n            } else if (\"BACKUP_CANCEL\".equalsIgnoreCase(action)) {\n                print0(ucase ? \"CANCEL \" : \"cancel \");\n            }\n        } else if (\"BACKUP_LOG\".equalsIgnoreCase(type)) {\n            print0(ucase ? \"LOG \" : \"log \");\n            if (\"BACKUP\".equalsIgnoreCase(action)) {\n                print0(ucase ? \"INTO \" : \"into \");\n            } else if (\"LIST_LOG\".equalsIgnoreCase(action)) {\n                print0(ucase ? \"LIST_LOGS\" : \"list_logs\");\n            } else if (\"STATUS\".equalsIgnoreCase(action)) {\n                print0(ucase ? \"STATUS\" : \"status\");\n            }\n        }\n\n        printAndAccept(x.getProperties(), \",\");\n\n        return false;\n    }\n\n    public void visitStatementList(List<SQLStatement> statementList) {\n        boolean printStmtSeperator;\n        if (DbType.sqlserver == dbType) {\n            printStmtSeperator = false;\n        } else {\n            printStmtSeperator = DbType.oracle != dbType;\n        }\n\n        for (int i = 0, size = statementList.size(); i < size; i++) {\n            SQLStatement stmt = statementList.get(i);\n\n            if (i > 0) {\n                SQLStatement preStmt = statementList.get(i - 1);\n                if (printStmtSeperator && !preStmt.isAfterSemi()) {\n                    print(\";\");\n                }\n\n                List<String> comments = preStmt.getAfterCommentsDirect();\n                if (comments != null) {\n                    for (int j = 0; j < comments.size(); ++j) {\n                        String comment = comments.get(j);\n                        if (j != 0) {\n                            println();\n                        }\n                        printComment(comment);\n                    }\n                }\n\n                if (printStmtSeperator) {\n                    println();\n                }\n\n                if (!(stmt instanceof SQLSetStatement)) {\n                    println();\n                }\n            }\n            {\n                List<String> comments = stmt.getBeforeCommentsDirect();\n                if (comments != null) {\n                    for (String comment : comments) {\n                        printComment(comment);\n                        println();\n                    }\n                }\n            }\n            stmt.accept(this);\n\n            if (i == size - 1) {\n                List<String> comments = stmt.getAfterCommentsDirect();\n                if (comments != null) {\n                    for (int j = 0; j < comments.size(); ++j) {\n                        String comment = comments.get(j);\n                        if (j != 0) {\n                            println();\n                        }\n                        printComment(comment);\n                    }\n                }\n            }\n        }\n    }\n\n    @Override\n    public boolean visit(SQLCreateResourceGroupStatement x) {\n        print0(ucase ? \"CREATE RESOURCE GROUP \" : \"create resource group \");\n        x.getName().accept(this);\n\n        for (Map.Entry<String, SQLExpr> entry : x.getProperties().entrySet()) {\n            print(' ');\n            print(entry.getKey());\n            print(\" = \");\n\n            SQLExpr value = entry.getValue();\n            if (value instanceof SQLListExpr) {\n                printAndAccept(((SQLListExpr) value).getItems(), \",\");\n            } else {\n                value.accept(this);\n            }\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable()) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            } else {\n                print0(ucase ? \" DISABLE\" : \" disable\");\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterResourceGroupStatement x) {\n        print0(ucase ? \"ALTER RESOURCE GROUP \" : \"create resource group \");\n        x.getName().accept(this);\n\n        for (Map.Entry<String, SQLExpr> entry : x.getProperties().entrySet()) {\n            print(' ');\n            print(entry.getKey());\n            print(\" = \");\n\n            SQLExpr value = entry.getValue();\n            if (value instanceof SQLListExpr) {\n                printAndAccept(((SQLListExpr) value).getItems(), \",\");\n            } else {\n                value.accept(this);\n            }\n        }\n\n        if (x.getEnable() != null) {\n            if (x.getEnable()) {\n                print0(ucase ? \" ENABLE\" : \" enable\");\n            } else {\n                print0(ucase ? \" DISABLE\" : \" disable\");\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlKillStatement x) {\n        if (MySqlKillStatement.Type.CONNECTION.equals(x.getType())) {\n            print0(ucase ? \"KILL CONNECTION \" : \"kill connection \");\n        } else if (MySqlKillStatement.Type.QUERY.equals(x.getType())) {\n            print0(ucase ? \"KILL QUERY \" : \"kill query \");\n        } else {\n            print0(ucase ? \"KILL \" : \"kill \");\n        }\n\n        printAndAccept(x.getThreadIds(), \", \");\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLTop x) {\n        boolean parameterized = this.parameterized;\n        this.parameterized = false;\n\n        print0(ucase ? \"TOP \" : \"top \");\n\n        boolean paren = false;\n\n        if (x.isParentheses()) {\n            paren = true;\n            print('(');\n        }\n\n        x.getExpr().accept(this);\n\n        if (paren) {\n            print(')');\n        }\n\n        if (x.isPercent()) {\n            print0(ucase ? \" PERCENT\" : \" percent\");\n        }\n\n        this.parameterized = parameterized;\n        return false;\n    }\n\n    public boolean visit(OdpsNewExpr x) {\n        print0(ucase ? \"NEW \" : \"new \");\n        return super.visit((SQLMethodInvokeExpr) x);\n    }\n\n    public boolean visit(SQLPurgeTemporaryOutputStatement x) {\n        print0(ucase ? \"PURGE TEMPORARY OUTPUT \" : \"purge temporary output \");\n        printExpr(x.getName());\n        return false;\n    }\n\n    public boolean visit(SQLCloneTableStatement x) {\n        print0(ucase ? \"CLONE TABLE \" : \"clone table \");\n        x.getFrom().accept(this);\n        print0(ucase ? \" TO \" : \" to \");\n        x.getTo().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableAttachPartition x) {\n        print0(ucase ? \"ATTACH PARTITION \" : \"attach partition \");\n        x.getPartitionName().accept(this);\n        if (x.isDefaultFlag()) {\n            print0(ucase ? \" DEFAULT\" : \" default\");\n        }\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableDetachPartition x) {\n        print0(ucase ? \"DETACH  PARTITION \" : \"detach partition \");\n        x.getPartitionName().accept(this);\n        if (x.isConcurrently()) {\n            print0(ucase ? \" CONCURRENTLY\" : \" concurrently\");\n        }\n        if (x.isFinalize()) {\n            print0(ucase ? \" FINALIZE\" : \" finalize\");\n        }\n        return false;\n    }\n    public boolean visit(SQLOptimizeStatement x) {\n        print0(ucase ? \"OPTIMIZE TABLE \" : \"optimize table \");\n\n        printAndAccept(x.getTableSources(), \", \");\n\n        SQLName cluster = x.getCluster();\n        if (cluster != null) {\n            print0(ucase ? \" ON CLUSTER \" : \" on cluster \");\n            cluster.accept(this);\n        }\n\n        if (x.isFinal()) {\n            print0(ucase ? \" FINAL\" : \" final\");\n        }\n\n        if (x.isDeduplicate()) {\n            print0(ucase ? \" DEDUPLICATE\" : \" deduplicate\");\n\n            SQLExpr deduplicateBy = x.getDeduplicateBy();\n            if (deduplicateBy != null) {\n                print0(ucase ? \" BY \" : \" by \");\n                deduplicateBy.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPivot x) {\n        print0(ucase ? \"PIVOT\" : \"pivot\");\n        if (x.isXml()) {\n            print0(ucase ? \" XML\" : \" xml\");\n        }\n        print0(\" (\");\n        printAndAccept(x.getItems(), \", \");\n\n        if (x.getPivotFor().size() > 0) {\n            print0(ucase ? \" FOR \" : \" for \");\n            if (x.getPivotFor().size() == 1) {\n                ((SQLExpr) x.getPivotFor().get(0)).accept(this);\n            } else {\n                print('(');\n                printAndAccept(x.getPivotFor(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.getPivotIn().size() > 0) {\n            print0(ucase ? \" IN (\" : \" in (\");\n            printAndAccept(x.getPivotIn(), \", \");\n            print(')');\n        }\n\n        print(')');\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnpivot x) {\n        print0(ucase ? \"UNPIVOT\" : \"unpivot\");\n        if (x.getNullsIncludeType() != null) {\n            print(' ');\n            print0(SQLUnpivot.NullsIncludeType.toString(x.getNullsIncludeType(), ucase));\n        }\n\n        print0(\" (\");\n        if (x.getItems().size() == 1) {\n            ((SQLExpr) x.getItems().get(0)).accept(this);\n        } else {\n            print0(\" (\");\n            printAndAccept(x.getItems(), \", \");\n            print(')');\n        }\n\n        if (x.getPivotFor().size() > 0) {\n            print0(ucase ? \" FOR \" : \" for \");\n            if (x.getPivotFor().size() == 1) {\n                ((SQLExpr) x.getPivotFor().get(0)).accept(this);\n            } else {\n                print('(');\n                printAndAccept(x.getPivotFor(), \", \");\n                print(')');\n            }\n        }\n\n        if (x.getPivotIn().size() > 0) {\n            print0(ucase ? \" IN (\" : \" in (\");\n            printAndAccept(x.getPivotIn(), \", \");\n            print(')');\n        }\n\n        print(')');\n\n        return false;\n    }\n\n    public boolean visit(SQLShowHistoryStatement x) {\n        if (x.isTables()) {\n            print0(ucase ? \"SHOW HISTORY FOR TABLES \" : \"show history for tables \");\n        } else {\n            print0(ucase ? \"SHOW HISTORY FOR TABLE \" : \"show history for table \");\n        }\n        x.getTable().accept(this);\n\n        List<SQLAssignItem> properties = x.getProperties();\n        if (!properties.isEmpty()) {\n            print0(\" (\");\n            printAndAccept(properties, \", \");\n            print(')');\n        }\n\n        List<SQLAssignItem> partitions = x.getPartitions();\n        if (!partitions.isEmpty()) {\n            print0(ucase ? \" PARTITION (\" : \" partition (\");\n            printAndAccept(partitions, \", \");\n            print(')');\n        }\n        // HISTORY\n        return false;\n    }\n\n    public boolean visit(SQLCostStatement x) {\n        print0(ucase ? \"COST SQL\" : \"cost sql\");\n        println();\n        x.getStatement().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLPartitionOf x) {\n        x.getParentTable().accept(this);\n        if (x.isUseDefault()) {\n            print0(ucase ? \" DEFAULT\" : \" pdefault\");\n        }\n        if (x.getColumnName() != null || x.getConstraintName() != null || x.getCheckExpr() != null) {\n            print0(\" (\");\n        }\n        if (x.getColumnName() != null) {\n            x.getColumnName().accept(this);\n        }\n        if (x.getConstraintName() != null) {\n            print0(ucase ? \" CONSTRAINT \" : \" constraint \");\n            x.getConstraintName().accept(this);\n        }\n        if (x.getCheckExpr() != null) {\n            print0(ucase ? \" CHECK \" : \" check \");\n            x.getCheckExpr().accept(this);\n            print0(\"\");\n        }\n        if (x.getDefaultExpr() != null) {\n            print0(ucase ? \" DEFAULT \" : \" default \");\n            x.getDefaultExpr().accept(this);\n        }\n        if (x.getColumnName() != null || x.getConstraintName() != null || x.getCheckExpr() != null) {\n            print0(\" )\");\n        }\n        if (x.getForValuesFrom() != null && x.getForValuesTo() != null) {\n            print0(ucase ? \" FOR VALUES FROM (\" : \" for values from (\");\n            printAndAccept(x.getForValuesFrom(), \", \");\n            print0(ucase ? \") TO (\" : \") to (\");\n            printAndAccept(x.getForValuesTo(), \", \");\n            print0(\")\");\n        }\n        if (x.getForValuesIn() != null) {\n            print0(ucase ? \" FOR VALUES IN (\" : \" for values in (\");\n            printAndAccept(x.getForValuesIn(), \", \");\n            print0(\")\");\n        }\n        if (x.getForValuesModulus() != null && x.getForValuesRemainder() != null) {\n            print0(ucase ? \" FOR VALUES WITH (\" : \" for values with (\");\n            print0(ucase ? \"MODULUS \" : \"modulus \");\n            x.getForValuesModulus().accept(this);\n            print0(\" , \");\n            print0(ucase ? \"REMAINDER \" : \"remainder \");\n            x.getForValuesRemainder().accept(this);\n            print0(\")\");\n        }\n        return false;\n    }\n\n    public boolean visit(SQLAlterProcedureStatement x) {\n        print0(ucase ? \"ALTER PROCEDURE \" : \"alter procedure \");\n        x.getName().accept(this);\n\n        SQLExpr comment = x.getComment();\n        if (comment != null) {\n            print0(ucase ? \" COMMENT \" : \" comment \");\n            comment.accept(this);\n        }\n\n        if (x.isLanguageSql()) {\n            print0(ucase ? \" LANGUAGE SQL\" : \" language sql\");\n        }\n\n        SQLExpr sqlSecurity = x.getSqlSecurity();\n        if (sqlSecurity != null) {\n            print0(ucase ? \" SQL SECURITY \" : \" sql security \");\n            sqlSecurity.accept(this);\n        }\n\n        if (x.isContainsSql()) {\n            print0(ucase ? \" CONTAINS SQL\" : \" contains sql\");\n        }\n        return false;\n    }\n\n    public boolean visit(SQLCommitTransactionStatement x) {\n        print0(ucase ? \"COMMIT TRANSACTION\" : \"commit transaction\");\n        return false;\n    }\n\n    public boolean visit(SQLRollbackTransactionStatement x) {\n        print0(ucase ? \"ROLLBACK TRANSACTION\" : \"rollback transaction\");\n        return false;\n    }\n\n    public boolean visit(SQLStartTransactionStatement x) {\n        print0(ucase ? \"START TRANSACTION\" : \"start transaction\");\n        return false;\n    }\n\n    public boolean visit(SQLRaiseStatement x) {\n        print0(ucase ? \"RAISE\" : \"raise\");\n        if (x.getMessage() != null) {\n            print0(ucase ? \" USING MESSAGE = \" : \" using message = \");\n            x.getMessage().accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLComputeIncrementalStatsStatement x) {\n        print0(ucase ? \"COMPUTE INCREMENTAL STATS \" : \"compute incremental stats \");\n        x.getName().accept(this);\n        if (x.getPartition() != null) {\n            print0(ucase ? \" PARTITION \" : \" partition \");\n            x.getPartition().accept(this);\n        }\n        return false;\n    }\n    @Override\n    public boolean visit(SQLExceptionStatement.Item x) {\n        print0(ucase ? \"WHEN \" : \"when \");\n        x.getWhen().accept(this);\n        print0(ucase ? \" THEN\" : \" then\");\n\n        this.indentCount++;\n        if (x.getStatements().size() > 1) {\n            println();\n        } else {\n            if (x.getStatements().size() == 1\n                    && x.getStatements().get(0) instanceof SQLIfStatement) {\n                println();\n            } else {\n                print(' ');\n            }\n        }\n\n        for (int i = 0, size = x.getStatements().size(); i < size; ++i) {\n            if (i != 0 && size > 1) {\n                println();\n            }\n            SQLStatement stmt = x.getStatements().get(i);\n            stmt.accept(this);\n        }\n\n        this.indentCount--;\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExceptionStatement x) {\n        print0(ucase ? \"EXCEPTION\" : \"exception\");\n        this.indentCount++;\n        List<SQLExceptionStatement.Item> items = x.getItems();\n        for (int i = 0, size = items.size(); i < size; ++i) {\n            println();\n            SQLExceptionStatement.Item item = items.get(i);\n            item.accept(this);\n        }\n        this.indentCount--;\n        return false;\n    }\n    protected void tryPrintLparen(SQLExprImpl x) {\n        if (x.isParenthesized()) {\n            print('(');\n        }\n        for (int i = 1; i < x.getParenthesizedCount(); ++i) {\n            print('(');\n        }\n    }\n\n    protected void tryPrintRparen(SQLExprImpl x) {\n        if (x.isParenthesized()) {\n            print(')');\n        }\n        for (int i = 1; i < x.getParenthesizedCount(); ++i) {\n            print(')');\n        }\n    }\n\n    public boolean visit(SQLSelectQueryTemplate x) {\n        print0(x.getText());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateFunctionStatement x) {\n        boolean create = x.isCreate();\n        if (create) {\n            print0(ucase ? \"CREATE \" : \"create \");\n\n            if (x.isOrReplace()) {\n                print0(ucase ? \"OR REPLACE \" : \"or replace \");\n            }\n        }\n\n        if (x.isTemporary()) {\n            print0(ucase ? \"TEMPORARY \" : \"temporary \");\n        }\n        print0(ucase ? \"FUNCTION \" : \"function \");\n\n        x.getName().accept(this);\n\n        int paramSize = x.getParameters().size();\n\n        if (paramSize > 0) {\n            print0(\" (\");\n            this.indentCount++;\n            println();\n\n            for (int i = 0; i < paramSize; ++i) {\n                if (i != 0) {\n                    print(',');\n                    println();\n                }\n                SQLParameter param = x.getParameters().get(i);\n                param.accept(this);\n            }\n\n            this.indentCount--;\n            println();\n            print(')');\n        }\n\n        printCreateFunctionBody(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLResetStatement x) {\n        print0(ucase ? \"RESET \" : \"reset \");\n        for (int i = 0; i < x.getOptions().size(); ++i) {\n            if (i != 0) {\n                print0(\", \");\n            }\n            print0(x.getOptions().get(i));\n        }\n        return false;\n    }\n    protected void printCreateFunctionBody(SQLCreateFunctionStatement x) {\n        printCreateFunctionReturns(x);\n\n        SQLStatement block = x.getBlock();\n        if (block == null) {\n            return;\n        }\n        println();\n        println(ucase ? \"AS\" : \"as\");\n        block.accept(this);\n    }\n\n    protected void printCreateFunctionReturns(SQLCreateFunctionStatement x) {\n        SQLDataType returnDataType = x.getReturnDataType();\n        if (returnDataType == null) {\n            return;\n        }\n        println();\n        print(ucase ? \"RETURN \" : \"return \");\n        returnDataType.accept(this);\n    }\n\n    @Override\n    public String toString() {\n        return appender.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitorBinaryOpSupport.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExprGroup;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.expr.SQLExprUtils;\nimport com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLNullExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nclass SQLASTOutputVisitorBinaryOpSupport {\n    private final SQLASTOutputVisitor visitor;\n\n    SQLASTOutputVisitorBinaryOpSupport(SQLASTOutputVisitor visitor) {\n        this.visitor = visitor;\n    }\n\n    boolean visitBetweenExpr(SQLBetweenExpr x) {\n        final SQLExpr testExpr = x.getTestExpr();\n        final SQLExpr beginExpr = x.getBeginExpr();\n        final SQLExpr endExpr = x.getEndExpr();\n        if (x.isParenthesized()) {\n            visitor.print('(');\n        }\n        if (testExpr != null) {\n            visitor.printExpr(testExpr, visitor.parameterized);\n        }\n\n        if (x.isNot()) {\n            visitor.print0(visitor.ucase ? \" NOT BETWEEN \" : \" not between \");\n        } else {\n            visitor.print0(visitor.ucase ? \" BETWEEN \" : \" between \");\n        }\n\n        int lines = visitor.lines;\n        if (beginExpr instanceof SQLBinaryOpExpr) {\n            visitor.incrementIndent();\n            visitor.printExpr(beginExpr, visitor.parameterized);\n            visitor.decrementIndent();\n        } else {\n            visitor.printExpr(beginExpr, visitor.parameterized);\n        }\n\n        if (lines != visitor.lines) {\n            visitor.println();\n            visitor.print0(visitor.ucase ? \"AND \" : \"and \");\n        } else {\n            visitor.print0(visitor.ucase ? \" AND \" : \" and \");\n        }\n\n        if (endExpr instanceof SQLBinaryOpExpr) {\n            visitor.incrementIndent();\n            visitor.printExpr(endExpr, visitor.parameterized);\n            visitor.decrementIndent();\n        } else {\n            visitor.printExpr(endExpr, visitor.parameterized);\n        }\n\n        if (x.getHint() != null) {\n            x.getHint().accept(visitor);\n        }\n        if (x.isParenthesized()) {\n            visitor.print(')');\n        }\n        return false;\n    }\n\n    boolean visitBinaryOpExprGroup(SQLBinaryOpExprGroup x) {\n        SQLObject parent = x.getParent();\n        SQLBinaryOperator operator = x.getOperator();\n\n        boolean isRoot = parent instanceof SQLSelectQueryBlock || parent instanceof SQLBinaryOpExprGroup;\n\n        List<SQLExpr> items = x.getItems();\n        if (items.isEmpty()) {\n            visitor.print(\"true\");\n            return false;\n        }\n\n        if (isRoot) {\n            visitor.indentCount++;\n        }\n\n        if (visitor.parameterized) {\n            SQLExpr firstLeft = null;\n            SQLBinaryOperator firstOp = null;\n            List<Object> parameters = new ArrayList<Object>(items.size());\n\n            List<SQLBinaryOpExpr> literalItems = null;\n\n            if ((operator != SQLBinaryOperator.BooleanOr || !visitor.isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeOr))\n                    && (operator != SQLBinaryOperator.BooleanAnd || !visitor.isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeAnd))) {\n                for (int i = 0; i < items.size(); i++) {\n                    SQLExpr item = items.get(i);\n                    if (item instanceof SQLBinaryOpExpr) {\n                        SQLBinaryOpExpr binaryItem = (SQLBinaryOpExpr) item;\n                        SQLExpr left = binaryItem.getLeft();\n                        SQLExpr right = binaryItem.getRight();\n\n                        if (right instanceof SQLLiteralExpr && !(right instanceof SQLNullExpr)) {\n                            if (left instanceof SQLLiteralExpr) {\n                                if (literalItems == null) {\n                                    literalItems = new ArrayList<SQLBinaryOpExpr>();\n                                }\n                                literalItems.add(binaryItem);\n                                continue;\n                            }\n\n                            if (visitor.parameters != null) {\n                                ExportParameterVisitorUtils.exportParameter(parameters, right);\n                            }\n                        } else if (right instanceof SQLVariantRefExpr) {\n                            // skip\n                        } else {\n                            firstLeft = null;\n                            break;\n                        }\n\n                        if (firstLeft == null) {\n                            firstLeft = binaryItem.getLeft();\n                            firstOp = binaryItem.getOperator();\n                        } else {\n                            if (firstOp != binaryItem.getOperator() || !SQLExprUtils.equals(firstLeft, left)) {\n                                firstLeft = null;\n                                break;\n                            }\n                        }\n                    } else {\n                        firstLeft = null;\n                        break;\n                    }\n                }\n            }\n\n            if (firstLeft != null) {\n                if (literalItems != null) {\n                    for (SQLBinaryOpExpr literalItem : literalItems) {\n                        visitor.visit(literalItem);\n                        visitor.println();\n                        visitor.printOperator(operator);\n                        visitor.print(' ');\n                    }\n                }\n                visitor.printExpr(firstLeft, visitor.parameterized);\n                visitor.print(' ');\n                visitor.printOperator(firstOp);\n                visitor.print0(\" ?\");\n\n                if (visitor.parameters != null && parameters.size() > 0) {\n                    visitor.parameters.addAll(parameters);\n                }\n\n                visitor.incrementReplaceCunt();\n                if (isRoot) {\n                    visitor.indentCount--;\n                }\n                return false;\n            }\n        }\n\n        for (int i = 0; i < items.size(); i++) {\n            SQLExpr item = items.get(i);\n\n            if (i != 0) {\n                visitor.println();\n                visitor.printOperator(operator);\n                visitor.print(' ');\n            }\n\n            if (item.hasBeforeComment()) {\n                visitor.printlnComments(item.getBeforeCommentsDirect());\n            }\n\n            if (item instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) item;\n                SQLBinaryOperator itemOp = binaryOpExpr.getOperator();\n\n                boolean isLogic = itemOp.isLogical();\n                if (isLogic) {\n                    visitor.indentCount++;\n                }\n\n                visitor.visit(binaryOpExpr);\n\n                if (isLogic) {\n                    visitor.indentCount--;\n                }\n            } else if (item instanceof SQLBinaryOpExprGroup) {\n                visitor.print('(');\n                visitor.visit((SQLBinaryOpExprGroup) item);\n                visitor.print(')');\n            } else {\n                visitor.printExpr(item, visitor.parameterized);\n            }\n        }\n        List<String> afterComments = x.getAfterCommentsDirect();\n        if (!visitor.parameterized) {\n            if (afterComments != null && !afterComments.isEmpty() && visitor.isPrettyFormat()) {\n                visitor.print(' ');\n            }\n            visitor.printlnComment(afterComments);\n        }\n        if (isRoot) {\n            visitor.indentCount--;\n        }\n        return false;\n    }\n\n    boolean visitBinaryOpExpr(SQLBinaryOpExpr x) {\n        if (x.isParenthesized()) {\n            visitor.print('(');\n        }\n        boolean rs = visitor.visitInternal(x);\n        if (x.isParenthesized()) {\n            visitor.print(')');\n        }\n        List<String> afterComments = x.getAfterCommentsDirect();\n        if (!visitor.parameterized) {\n            if (afterComments != null && !afterComments.isEmpty() && visitor.isPrettyFormat()) {\n                visitor.print(' ');\n            }\n            visitor.printlnComment(afterComments);\n        }\n        return rs;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTParameterizedVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.List;\n\npublic class SQLASTParameterizedVisitor extends SQLASTVisitorAdapter {\n    protected DbType dbType;\n\n    protected List<Object> parameters;\n    private int replaceCount;\n\n    public SQLASTParameterizedVisitor(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public int getReplaceCount() {\n        return this.replaceCount;\n    }\n\n    public void incrementReplaceCunt() {\n        replaceCount++;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public SQLASTParameterizedVisitor(DbType dbType, List<Object> parameters) {\n        this.dbType = dbType;\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    @Override\n    public boolean visit(SQLTimestampExpr x) {\n        parameterizeAndExportPara(x);\n        return false;\n    }\n\n    public void parameterizeAndExportPara(SQLExpr x) {\n        SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr(\"?\");\n        variantRefExpr.setIndex(this.replaceCount);\n\n        SQLUtils.replaceInParent(x, variantRefExpr);\n        incrementReplaceCunt();\n        ExportParameterVisitorUtils.exportParameter(this.parameters, x);\n    }\n\n    public void parameterize(SQLExpr x) {\n        SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr(\"?\");\n        variantRefExpr.setIndex(this.replaceCount);\n\n        SQLUtils.replaceInParent(x, variantRefExpr);\n        incrementReplaceCunt();\n    }\n\n    @Override\n    public boolean visit(SQLCharExpr x) {\n        parameterizeAndExportPara(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIntegerExpr x) {\n        SQLObject parent = x.getParent();\n        if (parent instanceof SQLSelectGroupByClause || parent instanceof SQLSelectOrderByItem) {\n            return false;\n        }\n        parameterizeAndExportPara(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        List<SQLExpr> arguments = x.getArguments();\n        if (x.methodNameHashCode64() == FnvHash.Constants.TRIM\n                && arguments.size() == 1\n                && arguments.get(0) instanceof SQLCharExpr && x.getTrimOption() == null && x.getFrom() == null) {\n            parameterizeAndExportPara(x);\n\n            if (this.parameters != null) {\n                SQLCharExpr charExpr = (SQLCharExpr) arguments.get(0);\n                this.parameters.add(charExpr.getText().trim());\n            }\n\n            replaceCount++;\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLNCharExpr x) {\n        parameterizeAndExportPara(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        SQLObject parent = x.getParent();\n        if (parent instanceof SQLInsertStatement || parent instanceof ValuesClause || parent instanceof SQLInListExpr ||\n                (parent instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) parent).getOperator() == SQLBinaryOperator.Equality)) {\n            parameterize(x);\n\n            if (this.parameters != null) {\n                if (parent instanceof SQLBinaryOpExpr) {\n                    ExportParameterVisitorUtils.exportParameter(parameters, x);\n                } else {\n                    this.parameters.add(null);\n                }\n            }\n            return false;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLNumberExpr x) {\n        parameterizeAndExportPara(x);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLHexExpr x) {\n        parameterizeAndExportPara(x);\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\") {\n        return true;\n    }\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQueryVisitor;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInputOutputFormat;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlKillStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.SQLAlterResourceGroupStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.SQLCreateResourceGroupStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.SQLListResourceGroupStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.StarRocksIndexDefinition;\nimport com.alibaba.druid.sql.dialect.starrocks.ast.statement.StarRocksCreateResourceStatement;\nimport com.alibaba.druid.sql.template.SQLSelectQueryTemplate;\n\nimport java.util.function.Consumer;\nimport java.util.function.Predicate;\n\npublic interface SQLASTVisitor {\n    default void endVisit(SQLAllColumnExpr x) {\n    }\n\n    default void endVisit(SQLBetweenExpr x) {\n    }\n\n    default void endVisit(SQLBinaryOpExpr x) {\n    }\n\n    default void endVisit(SQLCaseExpr x) {\n    }\n\n    default void endVisit(SQLCaseExpr.Item x) {\n    }\n\n    default void endVisit(SQLCaseStatement x) {\n    }\n\n    default void endVisit(SQLCaseStatement.Item x) {\n    }\n\n    default void endVisit(SQLCharExpr x) {\n    }\n\n    default void endVisit(SQLIdentifierExpr x) {\n    }\n\n    default void endVisit(SQLInListExpr x) {\n    }\n\n    default void endVisit(SQLIntegerExpr x) {\n    }\n\n    default void endVisit(SQLSmallIntExpr x) {\n    }\n\n    default void endVisit(SQLBigIntExpr x) {\n    }\n\n    default void endVisit(SQLTinyIntExpr x) {\n    }\n\n    default void endVisit(SQLExistsExpr x) {\n    }\n\n    default void endVisit(SQLNCharExpr x) {\n    }\n\n    default void endVisit(SQLNotExpr x) {\n    }\n\n    default void endVisit(SQLNullExpr x) {\n    }\n\n    default void endVisit(SQLNumberExpr x) {\n    }\n\n    default void endVisit(SQLRealExpr x) {\n    }\n\n    default void endVisit(SQLPropertyExpr x) {\n    }\n\n    default void endVisit(SQLSelectGroupByClause x) {\n    }\n\n    default void endVisit(SQLSelectItem x) {\n    }\n\n    default void endVisit(SQLSelectStatement x) {\n    }\n\n    default void postVisit(SQLObject x) {\n    }\n\n    default void preVisit(SQLObject x) {\n    }\n\n    /**\n     * Compatibility-first default entry for table-source visit paths.\n     * Specific table-source visit methods delegate here unless overridden.\n     */\n    default boolean visitTableSource(SQLTableSource x) {\n        return true;\n    }\n\n    /**\n     * Compatibility-first default exit for table-source visit paths.\n     * Specific table-source endVisit methods delegate here unless overridden.\n     */\n    default void endVisitTableSource(SQLTableSource x) {\n    }\n\n    default boolean visit(SQLAllColumnExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLTableSourceImpl x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLTableSourceImpl x) {\n        endVisitTableSource(x);\n    }\n    default boolean visit(SQLBetweenExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLBinaryOpExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLCaseExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLCaseExpr.Item x) {\n        return true;\n    }\n\n    default boolean visit(SQLCaseStatement x) {\n        return true;\n    }\n\n    default boolean visit(SQLCaseStatement.Item x) {\n        return true;\n    }\n\n    default boolean visit(SQLCastExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLCharExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLExistsExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLIdentifierExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLInListExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLIntegerExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLSmallIntExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLBigIntExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLTinyIntExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLNCharExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLNotExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLNullExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLNumberExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLRealExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLPropertyExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLSelectGroupByClause x) {\n        return true;\n    }\n\n    default boolean visit(SQLSelectItem x) {\n        return true;\n    }\n\n    default boolean visit(SQLStructExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLStructExpr x) {\n    }\n\n    default boolean visit(SQLAliasedExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLAliasedExpr x) {\n    }\n\n    default void endVisit(SQLCastExpr x) {\n    }\n\n    default boolean visit(SQLSelectStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAggregateExpr x) {\n    }\n\n    default boolean visit(SQLAggregateExpr x) {\n        return true;\n    }\n\n    default boolean visit(SQLVariantRefExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLVariantRefExpr x) {\n    }\n\n    default boolean visit(SQLQueryExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLQueryExpr x) {\n    }\n\n    default boolean visit(SQLUnaryExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLUnaryExpr x) {\n    }\n\n    default boolean visit(SQLHexExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLHexExpr x) {\n    }\n\n    default boolean visit(SQLSelect x) {\n        return true;\n    }\n\n    default void endVisit(SQLSelect select) {\n    }\n\n    default boolean visit(SQLSelectQueryBlock x) {\n        return true;\n    }\n\n    default void endVisit(SQLSelectQueryBlock x) {\n    }\n\n    default boolean visit(SQLExprTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLExprTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLOrderBy x) {\n        return true;\n    }\n\n    default void endVisit(SQLOrderBy x) {\n    }\n\n    default boolean visit(SQLZOrderBy x) {\n        return true;\n    }\n\n    default void endVisit(SQLZOrderBy x) {\n    }\n\n    default boolean visit(SQLSelectOrderByItem x) {\n        return true;\n    }\n\n    default void endVisit(SQLSelectOrderByItem x) {\n    }\n\n    default boolean visit(SQLDropTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropTableStatement x) {\n    }\n\n    default boolean visit(SQLCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateTableStatement x) {\n    }\n\n    default boolean visit(SQLColumnDefinition x) {\n        return true;\n    }\n\n    default void endVisit(SQLColumnDefinition x) {\n    }\n\n    default boolean visit(SQLColumnDefinition.Identity x) {\n        return true;\n    }\n\n    default void endVisit(SQLColumnDefinition.Identity x) {\n    }\n\n    default boolean visit(SQLDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLDataType x) {\n    }\n\n    default boolean visit(SQLCharacterDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLCharacterDataType x) {\n    }\n\n    default boolean visit(SQLDeleteStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDeleteStatement x) {\n    }\n\n    default boolean visit(SQLCurrentOfCursorExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLCurrentOfCursorExpr x) {\n    }\n\n    default boolean visit(SQLInsertStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLInsertStatement x) {\n    }\n\n    default boolean visit(SQLInsertStatement.ValuesClause x) {\n        return true;\n    }\n\n    default void endVisit(SQLInsertStatement.ValuesClause x) {\n    }\n\n    default boolean visit(SQLUpdateSetItem x) {\n        return true;\n    }\n\n    default void endVisit(SQLUpdateSetItem x) {\n    }\n\n    default boolean visit(SQLUpdateStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLUpdateStatement x) {\n    }\n\n    default boolean visit(SQLGetDiagnosticsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLGetDiagnosticsStatement x) {\n    }\n\n    default boolean visit(SQLCreateViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateViewStatement x) {\n    }\n\n    default boolean visit(SQLCreateViewStatement.Column x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateViewStatement.Column x) {\n    }\n\n    default boolean visit(SQLNotNullConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLNotNullConstraint x) {\n    }\n\n    default void endVisit(SQLMethodInvokeExpr x) {\n    }\n\n    default boolean visit(SQLMethodInvokeExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLUnionQuery x) {\n    }\n\n    default boolean visit(SQLUnionQuery x) {\n        return true;\n    }\n\n    default void endVisit(SQLSetStatement x) {\n    }\n\n    default boolean visit(SQLSetStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAssignItem x) {\n    }\n\n    default boolean visit(SQLAssignItem x) {\n        return true;\n    }\n\n    default void endVisit(SQLCallStatement x) {\n    }\n\n    default boolean visit(SQLCallStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLJoinTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLJoinTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLJoinTableSource.UDJ x) {\n    }\n\n    default boolean visit(SQLJoinTableSource.UDJ x) {\n        return true;\n    }\n\n    default void endVisit(SQLSomeExpr x) {\n    }\n\n    default boolean visit(SQLSomeExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLAnyExpr x) {\n    }\n\n    default boolean visit(SQLAnyExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLAllExpr x) {\n    }\n\n    default boolean visit(SQLAllExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLInSubQueryExpr x) {\n    }\n\n    default boolean visit(SQLInSubQueryExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLListExpr x) {\n    }\n\n    default boolean visit(SQLListExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLSubqueryTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLSubqueryTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLTruncateStatement x) {\n    }\n\n    default boolean visit(SQLTruncateStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDefaultExpr x) {\n    }\n\n    default boolean visit(SQLDefaultExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLCommentStatement x) {\n    }\n\n    default boolean visit(SQLCommentStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLBeginStatement x) {\n    }\n\n    default boolean visit(SQLBeginStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLUseStatement x) {\n    }\n\n    default boolean visit(SQLUseStatement x) {\n        return true;\n    }\n\n    default boolean visit(SQLAlterTableAddColumn x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAddColumn x) {\n    }\n\n    default boolean visit(SQLAlterTableDeleteByCondition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDeleteByCondition x) {\n    }\n\n    default boolean visit(SQLAlterTableModifyClusteredBy x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableModifyClusteredBy x) {\n    }\n\n    default boolean visit(SQLAlterTableDropColumnItem x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropColumnItem x) {\n    }\n\n    default boolean visit(SQLAlterTableDropIndex x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropIndex x) {\n    }\n\n    default boolean visit(SQLAlterTableGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableGroupStatement x) {\n    }\n\n    default boolean visit(SQLAlterSystemSetConfigStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterSystemSetConfigStatement x) {\n    }\n\n    default boolean visit(SQLAlterSystemGetConfigStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterSystemGetConfigStatement x) {\n    }\n\n    default boolean visit(SQLDropIndexStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropIndexStatement x) {\n    }\n\n    default boolean visit(SQLDropViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropViewStatement x) {\n    }\n\n    default boolean visit(SQLSavePointStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLSavePointStatement x) {\n    }\n\n    default boolean visit(SQLRollbackStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLRollbackStatement x) {\n    }\n\n    default boolean visit(SQLReleaseSavePointStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLReleaseSavePointStatement x) {\n    }\n\n    default void endVisit(SQLCommentHint x) {\n    }\n\n    default boolean visit(SQLCommentHint x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateDatabaseStatement x) {\n    }\n\n    default boolean visit(SQLCreateDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLOver x) {\n    }\n\n    default boolean visit(SQLOver x) {\n        return true;\n    }\n\n    default void endVisit(SQLKeep x) {\n    }\n\n    default boolean visit(SQLKeep x) {\n        return true;\n    }\n\n    default void endVisit(SQLColumnPrimaryKey x) {\n    }\n\n    default boolean visit(SQLColumnPrimaryKey x) {\n        return true;\n    }\n\n    default boolean visit(SQLColumnUniqueKey x) {\n        return true;\n    }\n\n    default void endVisit(SQLColumnUniqueKey x) {\n    }\n\n    default void endVisit(SQLWithSubqueryClause x) {\n    }\n\n    default boolean visit(SQLWithSubqueryClause x) {\n        return true;\n    }\n\n    default void endVisit(SQLWithSubqueryClause.Entry x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLWithSubqueryClause.Entry x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLAlterTableAlterColumn x) {\n    }\n\n    default boolean visit(SQLAlterTableAlterColumn x) {\n        return true;\n    }\n\n    default boolean visit(SQLCheck x) {\n        return true;\n    }\n\n    default void endVisit(SQLCheck x) {\n    }\n\n    default boolean visit(SQLDefault x) {\n        return true;\n    }\n\n    default void endVisit(SQLDefault x) {\n    }\n\n    default boolean visit(SQLAlterTableDropForeignKey x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropForeignKey x) {\n    }\n\n    default boolean visit(SQLAlterTableDropPrimaryKey x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropPrimaryKey x) {\n    }\n\n    default boolean visit(SQLAlterTableDisableKeys x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDisableKeys x) {\n    }\n\n    default boolean visit(SQLAlterTableEnableKeys x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableEnableKeys x) {\n    }\n\n    default boolean visit(SQLAlterTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableDisableConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDisableConstraint x) {\n    }\n\n    default boolean visit(SQLAlterTableEnableConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableEnableConstraint x) {\n    }\n\n    default boolean visit(SQLColumnCheck x) {\n        return true;\n    }\n\n    default void endVisit(SQLColumnCheck x) {\n    }\n\n    default boolean visit(SQLColumnDefault x) {\n        return true;\n    }\n\n    default void endVisit(SQLColumnDefault x) {\n    }\n\n    default boolean visit(SQLExprHint x) {\n        return true;\n    }\n\n    default void endVisit(SQLExprHint x) {\n    }\n\n    default boolean visit(SQLAlterTableDropConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropConstraint x) {\n    }\n    default boolean visit(SQLAlterTableDropCheck x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropCheck x) {\n    }\n    default boolean visit(SQLAlterTableValidateConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableValidateConstraint x) {\n    }\n\n    default boolean visit(SQLUnique x) {\n        return true;\n    }\n\n    default void endVisit(SQLUnique x) {\n    }\n\n    default boolean visit(SQLPrimaryKeyImpl x) {\n        return true;\n    }\n\n    default void endVisit(SQLPrimaryKeyImpl x) {\n    }\n\n    default boolean visit(SQLCreateIndexStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateIndexStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableRenameColumn x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRenameColumn x) {\n    }\n\n    default boolean visit(SQLAlterTableRenameConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRenameConstraint x) {\n    }\n\n    default boolean visit(SQLColumnReference x) {\n        return true;\n    }\n\n    default void endVisit(SQLColumnReference x) {\n    }\n\n    default boolean visit(SQLForeignKeyImpl x) {\n        return true;\n    }\n\n    default void endVisit(SQLForeignKeyImpl x) {\n    }\n\n    default boolean visit(SQLDropSequenceStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropSequenceStatement x) {\n    }\n\n    default boolean visit(SQLDropTriggerStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropTriggerStatement x) {\n    }\n\n    default void endVisit(SQLDropUserStatement x) {\n    }\n\n    default boolean visit(SQLDropUserStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLExplainStatement x) {\n    }\n\n    default boolean visit(SQLExplainStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLGrantStatement x) {\n    }\n\n    default boolean visit(SQLGrantStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropDatabaseStatement x) {\n    }\n\n    default boolean visit(SQLDropDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLIndexOptions x) {\n    }\n\n    default boolean visit(SQLIndexOptions x) {\n        return true;\n    }\n\n    default void endVisit(SQLIndexDefinition x) {\n    }\n\n    default boolean visit(SQLIndexDefinition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAddIndex x) {\n    }\n\n    default boolean visit(SQLAlterTableAddIndex x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAlterIndex x) {\n    }\n\n    default boolean visit(SQLAlterTableAlterIndex x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAddConstraint x) {\n    }\n\n    default boolean visit(SQLAlterTableAddConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateTriggerStatement x) {\n    }\n\n    default boolean visit(SQLCreateTriggerStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropFunctionStatement x) {\n    }\n\n    default boolean visit(SQLDropFunctionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropTableSpaceStatement x) {\n    }\n\n    default boolean visit(SQLDropTableSpaceStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropProcedureStatement x) {\n    }\n\n    default boolean visit(SQLDropProcedureStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLBooleanExpr x) {\n    }\n\n    default boolean visit(SQLBooleanExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLUnionQueryTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLUnionQueryTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLTimestampExpr x) {\n    }\n\n    default boolean visit(SQLTimestampExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLTimestampNTZExpr x) {\n    }\n\n    default boolean visit(SQLTimestampNTZExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLDateTimeExpr x) {\n    }\n\n    default boolean visit(SQLDateTimeExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLDoubleExpr x) {\n    }\n\n    default boolean visit(SQLDoubleExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLFloatExpr x) {\n    }\n\n    default boolean visit(SQLFloatExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLRevokeStatement x) {\n    }\n\n    default boolean visit(SQLRevokeStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLBinaryExpr x) {\n    }\n\n    default boolean visit(SQLBinaryExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRename x) {\n    }\n\n    default boolean visit(SQLAlterTableRename x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterViewRenameStatement x) {\n    }\n\n    default boolean visit(SQLAlterViewRenameStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowTablesStatement x) {\n    }\n\n    default boolean visit(SQLShowTablesStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAddPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableAddPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAddExtPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableAddExtPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropExtPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableDropExtPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableDropPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRenamePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableRenamePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetComment x) {\n    }\n\n    default boolean visit(SQLAlterTableSetComment x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetTableSpace x) {\n    }\n\n    default boolean visit(SQLAlterTableSetTableSpace x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetSchema x) {\n    }\n\n    default boolean visit(SQLAlterTableSetSchema x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetLifecycle x) {\n    }\n\n    default boolean visit(SQLPrivilegeItem x) {\n        return true;\n    }\n\n    default void endVisit(SQLPrivilegeItem x) {\n    }\n\n    default boolean visit(SQLAlterTableSetLifecycle x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableEnableLifecycle x) {\n    }\n\n    default boolean visit(SQLAlterTableSetLocation x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetLocation x) {\n    }\n\n    default boolean visit(SQLAlterTableEnableLifecycle x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTablePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableArchive x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableArchive x) {\n    }\n\n    default boolean visit(SQLAlterTablePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTablePartitionSetProperties x) {\n    }\n\n    default boolean visit(SQLAlterTablePartitionSetProperties x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDisableLifecycle x) {\n    }\n\n    default boolean visit(SQLAlterTableDisableLifecycle x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableTouch x) {\n    }\n\n    default boolean visit(SQLAlterTableTouch x) {\n        return true;\n    }\n\n    default void endVisit(SQLArrayExpr x) {\n    }\n\n    default boolean visit(SQLArrayExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLOpenStatement x) {\n    }\n\n    default boolean visit(SQLOpenStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLFetchStatement x) {\n    }\n\n    default boolean visit(SQLFetchStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCloseStatement x) {\n    }\n\n    default boolean visit(SQLCloseStatement x) {\n        return true;\n    }\n\n    default boolean visit(SQLGroupingSetExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLGroupingSetExpr x) {\n    }\n\n    default boolean visit(SQLIfStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLIfStatement x) {\n    }\n\n    default boolean visit(SQLIfStatement.ElseIf x) {\n        return true;\n    }\n\n    default void endVisit(SQLIfStatement.ElseIf x) {\n    }\n\n    default boolean visit(SQLIfStatement.Else x) {\n        return true;\n    }\n\n    default void endVisit(SQLIfStatement.Else x) {\n    }\n\n    default boolean visit(SQLLoopStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLLoopStatement x) {\n    }\n\n    default boolean visit(SQLParameter x) {\n        return true;\n    }\n\n    default void endVisit(SQLParameter x) {\n    }\n\n    default boolean visit(SQLCreateProcedureStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateProcedureStatement x) {\n    }\n\n    default boolean visit(SQLCreateFunctionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateFunctionStatement x) {\n    }\n\n    default boolean visit(SQLBlockStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLBlockStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableDropKey x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropKey x) {\n    }\n\n    default boolean visit(SQLDeclareItem x) {\n        return true;\n    }\n\n    default void endVisit(SQLDeclareItem x) {\n    }\n\n    default boolean visit(SQLPartitionValue x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionValue x) {\n    }\n\n    default boolean visit(SQLPartitionSingle x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionSingle x) {\n    }\n\n    default boolean visit(SQLPartitionBatch x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionBatch x) {\n    }\n    default boolean visit(SQLPartitionByRange x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionByRange x) {\n    }\n\n    default boolean visit(SQLPartitionByHash x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionByHash x) {\n    }\n\n    default boolean visit(SQLPartitionByList x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionByList x) {\n    }\n    default boolean visit(SQLPartitionOf x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionOf x) {\n    }\n\n    default boolean visit(SQLSubPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLSubPartition x) {\n    }\n\n    default boolean visit(SQLSubPartitionByHash x) {\n        return true;\n    }\n\n    default void endVisit(SQLSubPartitionByHash x) {\n    }\n\n    default boolean visit(SQLSubPartitionByRange x) {\n        return true;\n    }\n\n    default void endVisit(SQLSubPartitionByRange x) {\n    }\n\n    default boolean visit(SQLSubPartitionByList x) {\n        return true;\n    }\n\n    default void endVisit(SQLSubPartitionByList x) {\n    }\n\n    default boolean visit(SQLAlterDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterDatabaseStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableConvertCharSet x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableConvertCharSet x) {\n    }\n\n    default boolean visit(SQLAlterTableReOrganizePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableReOrganizePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableCoalescePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableCoalescePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableTruncatePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableTruncatePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableDiscardPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDiscardPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableImportPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableImportPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableAnalyzePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAnalyzePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableCheckPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableCheckPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableOptimizePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableOptimizePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableRebuildPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRebuildPartition x) {\n    }\n\n    default boolean visit(SQLAlterTableRepairPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRepairPartition x) {\n    }\n\n    default boolean visit(SQLSequenceExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLSequenceExpr x) {\n    }\n\n    default boolean visit(SQLMergeStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLMergeStatement x) {\n    }\n\n    default boolean visit(SQLMergeStatement.WhenUpdate x) {\n        return true;\n    }\n\n    default void endVisit(SQLMergeStatement.WhenUpdate x) {\n    }\n\n    default boolean visit(SQLMergeStatement.WhenInsert x) {\n        return true;\n    }\n\n    default boolean visit(SQLMergeStatement.WhenDelete x) {\n        return true;\n    }\n\n    default void endVisit(SQLMergeStatement.WhenDelete x) {\n    }\n\n    default boolean visit(SQLMergeStatement.WhenDoNothing x) {\n        return true;\n    }\n\n    default void endVisit(SQLMergeStatement.WhenDoNothing x) {\n    }\n\n    default void endVisit(SQLMergeStatement.WhenInsert x) {\n    }\n\n    default boolean visit(SQLErrorLoggingClause x) {\n        return true;\n    }\n\n    default void endVisit(SQLErrorLoggingClause x) {\n    }\n\n    default boolean visit(SQLNullConstraint x) {\n        return true;\n    }\n\n    default void endVisit(SQLNullConstraint x) {\n    }\n\n    default boolean visit(SQLCreateSequenceStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateSequenceStatement x) {\n    }\n\n    default boolean visit(SQLDateExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLDateExpr x) {\n    }\n\n    default boolean visit(SQLLimit x) {\n        return true;\n    }\n\n    default void endVisit(SQLLimit x) {\n    }\n\n    default void endVisit(SQLStartTransactionStatement x) {\n    }\n\n    default boolean visit(SQLStartTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDescribeStatement x) {\n    }\n\n    default boolean visit(SQLDescribeStatement x) {\n        return true;\n    }\n\n    /**\n     * support procedure\n     */\n    default boolean visit(SQLWhileStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLWhileStatement x) {\n    }\n\n    default boolean visit(SQLDeclareStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDeclareStatement x) {\n    }\n\n    default boolean visit(SQLReturnStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLReturnStatement x) {\n    }\n\n    default boolean visit(SQLArgument x) {\n        return true;\n    }\n\n    default void endVisit(SQLArgument x) {\n    }\n\n    default boolean visit(SQLCommitStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCommitStatement x) {\n    }\n\n    default boolean visit(SQLFlashbackExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLFlashbackExpr x) {\n    }\n\n    default boolean visit(SQLCreateMaterializedViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateMaterializedViewStatement x) {\n    }\n\n    default boolean visit(SQLShowCreateMaterializedViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowCreateMaterializedViewStatement x) {\n    }\n\n    default boolean visit(SQLBinaryOpExprGroup x) {\n        return true;\n    }\n\n    default void endVisit(SQLBinaryOpExprGroup x) {\n    }\n\n    default boolean visit(SQLScriptCommitStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLScriptCommitStatement x) {\n    }\n\n    default boolean visit(SQLReplaceStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLReplaceStatement x) {\n    }\n\n    default boolean visit(SQLCreateUserStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateUserStatement x) {\n    }\n\n    default boolean visit(SQLAlterFunctionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterFunctionStatement x) {\n    }\n\n    default boolean visit(SQLAlterTypeStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTypeStatement x) {\n    }\n\n    default boolean visit(SQLIntervalExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLIntervalExpr x) {\n    }\n\n    default boolean visit(SQLLateralViewTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLLateralViewTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLShowErrorsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowErrorsStatement x) {\n    }\n\n    default boolean visit(SQLShowGrantsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowGrantsStatement x) {\n    }\n\n    default boolean visit(SQLShowPackagesStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowPackagesStatement x) {\n    }\n\n    default boolean visit(SQLShowRecylebinStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowRecylebinStatement x) {\n    }\n\n    default boolean visit(SQLAlterCharacter x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterCharacter x) {\n    }\n\n    default boolean visit(SQLExprStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLExprStatement x) {\n    }\n\n    default boolean visit(SQLAlterProcedureStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterProcedureStatement x) {\n    }\n\n    default boolean visit(SQLAlterViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterViewStatement x) {\n    }\n\n    default boolean visit(SQLDropEventStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropEventStatement x) {\n    }\n\n    default boolean visit(SQLDropLogFileGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropLogFileGroupStatement x) {\n    }\n\n    default boolean visit(SQLDropServerStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropServerStatement x) {\n    }\n\n    default boolean visit(SQLDropSynonymStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropSynonymStatement x) {\n    }\n\n    default boolean visit(SQLRecordDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLRecordDataType x) {\n    }\n\n    default boolean visit(SQLDropTypeStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropTypeStatement x) {\n    }\n\n    default boolean visit(SQLExternalRecordFormat x) {\n        return true;\n    }\n\n    default void endVisit(SQLExternalRecordFormat x) {\n    }\n\n    default boolean visit(SQLArrayDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLArrayDataType x) {\n    }\n\n    default boolean visit(SQLMapDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLMapDataType x) {\n    }\n\n    default boolean visit(SQLStructDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLStructDataType x) {\n    }\n\n    default boolean visit(SQLRowDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLRowDataType x) {\n    }\n\n    default boolean visit(SQLStructDataType.Field x) {\n        return true;\n    }\n\n    default void endVisit(SQLStructDataType.Field x) {\n    }\n\n    default boolean visit(SQLDropMaterializedViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropMaterializedViewStatement x) {\n    }\n\n    default boolean visit(SQLShowMaterializedViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowMaterializedViewStatement x) {\n    }\n\n    default boolean visit(SQLRefreshMaterializedViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLRefreshMaterializedViewStatement x) {\n    }\n\n    default boolean visit(SQLAlterMaterializedViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterMaterializedViewStatement x) {\n    }\n\n    default boolean visit(SQLCreateTableGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateTableGroupStatement x) {\n    }\n\n    default boolean visit(SQLDropTableGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropTableGroupStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableSubpartitionAvailablePartitionNum x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSubpartitionAvailablePartitionNum x) {\n    }\n\n    default void endVisit(SQLShowDatabasesStatement x) {\n    }\n\n    default boolean visit(SQLShowDatabasesStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowTableGroupsStatement x) {\n    }\n\n    default boolean visit(SQLShowTableGroupsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowColumnsStatement x) {\n    }\n\n    default boolean visit(SQLShowColumnsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowCreateTableStatement x) {\n    }\n\n    default boolean visit(SQLShowCreateTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowProcessListStatement x) {\n    }\n\n    default boolean visit(SQLShowProcessListStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetOption x) {\n    }\n\n    default boolean visit(SQLAlterTableSetOption x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetSerdeProperties x) {\n    }\n\n    default boolean visit(SQLAlterTableSetSerdeProperties x) {\n        return true;\n    }\n\n    default boolean visit(SQLShowCreateViewStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowCreateViewStatement x) {\n    }\n\n    default boolean visit(SQLShowViewsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowViewsStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableRenameIndex x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRenameIndex x) {\n    }\n\n    default boolean visit(SQLAlterSequenceStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterSequenceStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableExchangePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableExchangePartition x) {\n    }\n\n    default boolean visit(SQLCreateRoleStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateRoleStatement x) {\n    }\n\n    default boolean visit(SQLDropRoleStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropRoleStatement x) {\n    }\n\n    default boolean visit(SQLAlterTableReplaceColumn x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableReplaceColumn x) {\n    }\n\n    default boolean visit(SQLMatchAgainstExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLMatchAgainstExpr x) {\n    }\n\n    default boolean visit(SQLTimeExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLTimeExpr x) {\n    }\n\n    default boolean visit(SQLDropCatalogStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropCatalogStatement x) {\n    }\n\n    default void endVisit(SQLShowPartitionsStmt x) {\n    }\n\n    default boolean visit(SQLShowPartitionsStmt x) {\n        return true;\n    }\n\n    default void endVisit(SQLValuesExpr x) {\n    }\n\n    default boolean visit(SQLValuesExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLContainsExpr x) {\n    }\n\n    default boolean visit(SQLContainsExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLDumpStatement x) {\n    }\n\n    default boolean visit(SQLDumpStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLValuesTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLValuesTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLExtractExpr x) {\n    }\n\n    default boolean visit(SQLExtractExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLWindow x) {\n    }\n\n    default boolean visit(SQLWindow x) {\n        return true;\n    }\n\n    default void endVisit(SQLJSONExpr x) {\n    }\n\n    default boolean visit(SQLJSONExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLDecimalExpr x) {\n    }\n\n    default boolean visit(SQLDecimalExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLAnnIndex x) {\n    }\n\n    default boolean visit(SQLAnnIndex x) {\n        return true;\n    }\n\n    default void endVisit(SQLUnionDataType x) {\n    }\n\n    default boolean visit(SQLUnionDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableRecoverPartitions x) {\n    }\n\n    default boolean visit(SQLAlterTableRecoverPartitions x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterIndexStatement x) {\n    }\n\n    default boolean visit(SQLAlterIndexStatement x) {\n        return true;\n    }\n\n    default boolean visit(SQLAlterIndexStatement.Rebuild x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterIndexStatement.Rebuild x) {\n    }\n\n    default boolean visit(SQLShowIndexesStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowIndexesStatement x) {\n    }\n\n    default boolean visit(SQLAnalyzeTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAnalyzeTableStatement x) {\n    }\n\n    default boolean visit(SQLExportTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLExportTableStatement x) {\n    }\n\n    default boolean visit(SQLImportTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLImportTableStatement x) {\n    }\n\n    default boolean visit(SQLTableSampling x) {\n        return true;\n    }\n\n    default void endVisit(SQLTableSampling x) {\n    }\n\n    default boolean visit(SQLSizeExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLSizeExpr x) {\n    }\n\n    default boolean visit(SQLAlterTableArchivePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableArchivePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableUnarchivePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableUnarchivePartition x) {\n    }\n\n    default boolean visit(SQLCreateOutlineStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateOutlineStatement x) {\n    }\n\n    default boolean visit(SQLDropOutlineStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropOutlineStatement x) {\n    }\n\n    default boolean visit(SQLDropOfflineModelStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropOfflineModelStatement x) {\n    }\n\n    default boolean visit(SQLAlterOutlineStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterOutlineStatement x) {\n    }\n\n    default boolean visit(SQLShowOutlinesStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowOutlinesStatement x) {\n    }\n\n    default boolean visit(SQLPurgeTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLPurgeTableStatement x) {\n    }\n\n    default boolean visit(SQLPurgeTemporaryOutputStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLPurgeTemporaryOutputStatement x) {\n    }\n\n    default boolean visit(SQLPurgeLogsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLPurgeLogsStatement x) {\n    }\n\n    default boolean visit(SQLPurgeRecyclebinStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLPurgeRecyclebinStatement x) {\n    }\n\n    default boolean visit(SQLShowStatisticStmt x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowStatisticStmt x) {\n    }\n\n    default boolean visit(SQLShowStatisticListStmt x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowStatisticListStmt x) {\n    }\n\n    default boolean visit(SQLAlterTableAddSupplemental x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAddSupplemental x) {\n    }\n\n    default boolean visit(SQLShowCatalogsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowCatalogsStatement x) {\n    }\n\n    default boolean visit(SQLShowFunctionsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowFunctionsStatement x) {\n    }\n\n    default boolean visit(SQLShowSessionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowSessionStatement x) {\n    }\n\n    default boolean visit(SQLDbLinkExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLDbLinkExpr x) {\n    }\n\n    default boolean visit(SQLCurrentTimeExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLCurrentTimeExpr x) {\n    }\n\n    default boolean visit(SQLCurrentUserExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLCurrentUserExpr x) {\n    }\n\n    default boolean visit(SQLShowQueryTaskStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowQueryTaskStatement x) {\n    }\n\n    default boolean visit(SQLAdhocTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLAdhocTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(HiveInputOutputFormat x) {\n        return true;\n    }\n\n    default void endVisit(HiveInputOutputFormat x) {\n    }\n\n    default boolean visit(SQLExplainAnalyzeStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLExplainAnalyzeStatement x) {\n    }\n\n    default boolean visit(SQLPartitionRef x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionRef x) {\n    }\n\n    default boolean visit(SQLPartitionRef.Item x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionRef.Item x) {\n    }\n\n    default boolean visit(SQLWhoamiStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLWhoamiStatement x) {\n    }\n\n    default boolean visit(SQLDropResourceStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLDropResourceStatement x) {\n    }\n\n    default boolean visit(SQLForStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLForStatement x) {\n    }\n\n    default boolean visit(SQLUnnestTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLUnnestTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLGeneratedTableSource x) {\n        return visitTableSource(x);\n    }\n\n    default void endVisit(SQLGeneratedTableSource x) {\n        endVisitTableSource(x);\n    }\n\n    default boolean visit(SQLCopyFromStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCopyFromStatement x) {\n    }\n\n    default boolean visit(SQLShowUsersStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowUsersStatement x) {\n    }\n\n    default boolean visit(SQLSubmitJobStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLSubmitJobStatement x) {\n    }\n\n    default boolean visit(SQLTableLike x) {\n        return true;\n    }\n\n    default void endVisit(SQLTableLike x) {\n    }\n\n    default boolean visit(SQLSyncMetaStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLSyncMetaStatement x) {\n    }\n\n    default void endVisit(SQLValuesQuery x) {\n    }\n\n    default boolean visit(SQLValuesQuery x) {\n        return true;\n    }\n\n    default void endVisit(SQLDataTypeRefExpr x) {\n    }\n\n    default boolean visit(SQLDataTypeRefExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLArchiveTableStatement x) {\n    }\n\n    default boolean visit(SQLArchiveTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLBackupStatement x) {\n    }\n\n    default boolean visit(SQLBackupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLRestoreStatement x) {\n    }\n\n    default boolean visit(SQLRestoreStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLBuildTableStatement x) {\n    }\n\n    default boolean visit(SQLBuildTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCancelJobStatement x) {\n    }\n\n    default boolean visit(SQLCancelJobStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLExportDatabaseStatement x) {\n    }\n\n    default boolean visit(SQLExportDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLImportDatabaseStatement x) {\n    }\n\n    default boolean visit(SQLImportDatabaseStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLRenameUserStatement x) {\n    }\n\n    default boolean visit(SQLRenameUserStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionByValue x) {\n    }\n\n    default boolean visit(SQLPartitionByValue x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTablePartitionCount x) {\n    }\n\n    default boolean visit(SQLAlterTablePartitionCount x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableBlockSize x) {\n    }\n\n    default boolean visit(SQLAlterTableBlockSize x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableCompression x) {\n    }\n\n    default boolean visit(SQLAlterTableCompression x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTablePartitionLifecycle x) {\n    }\n\n    default boolean visit(SQLAlterTablePartitionLifecycle x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSubpartitionLifecycle x) {\n    }\n\n    default boolean visit(SQLAlterTableSubpartitionLifecycle x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropSubpartition x) {\n    }\n\n    default boolean visit(SQLAlterTableDropSubpartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDropClusteringKey x) {\n    }\n\n    default boolean visit(SQLAlterTableDropClusteringKey x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAddClusteringKey x) {\n    }\n\n    default boolean visit(SQLAlterTableAddClusteringKey x) {\n        return true;\n    }\n\n    default void endVisit(MySqlKillStatement x) {\n    }\n\n    default boolean visit(MySqlKillStatement x) {\n        return true;\n    }\n\n    default boolean visit(SQLCreateResourceGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCreateResourceGroupStatement x) {\n    }\n\n    default boolean visit(SQLAlterResourceGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterResourceGroupStatement x) {\n    }\n\n    default void endVisit(SQLDropResourceGroupStatement x) {\n    }\n\n    default boolean visit(SQLDropResourceGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLListResourceGroupStatement x) {\n    }\n\n    default boolean visit(SQLListResourceGroupStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableMergePartition x) {\n    }\n\n    default boolean visit(SQLAlterTableMergePartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionSpec x) {\n    }\n\n    default boolean visit(SQLPartitionSpec x) {\n        return true;\n    }\n\n    default void endVisit(SQLPartitionSpec.Item x) {\n    }\n\n    default boolean visit(SQLPartitionSpec.Item x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableChangeOwner x) {\n    }\n\n    default boolean visit(SQLAlterTableChangeOwner x) {\n        return true;\n    }\n\n    default void endVisit(SQLTableDataType x) {\n    }\n\n    default boolean visit(SQLTableDataType x) {\n        return true;\n    }\n\n    default void endVisit(SQLCloneTableStatement x) {\n    }\n\n    default boolean visit(SQLCloneTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowHistoryStatement x) {\n    }\n\n    default boolean visit(SQLShowHistoryStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowRoleStatement x) {\n    }\n\n    default boolean visit(SQLShowRoleStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowRolesStatement x) {\n    }\n\n    default boolean visit(SQLShowRolesStatement x) {\n        return true;\n    }\n\n    default boolean visit(SQLShowVariantsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowVariantsStatement x) {\n    }\n\n    default boolean visit(SQLShowACLStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLShowACLStatement x) {\n    }\n\n    default boolean visit(SQLOptimizeStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLOptimizeStatement x) {\n    }\n    default boolean visit(SQLAlterTableAttachPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableAttachPartition x) {\n    }\n    default boolean visit(SQLAlterTableDetachPartition x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableDetachPartition x) {\n    }\n\n    default boolean visit(SQLPivot x) {\n        return true;\n    }\n\n    default void endVisit(SQLPivot x) {\n    }\n\n    default boolean visit(SQLUnpivot x) {\n        return true;\n    }\n\n    default void endVisit(SQLUnpivot x) {\n    }\n\n    default void preVisit(StarRocksCreateResourceStatement x) {\n    }\n\n    default boolean visit(StarRocksCreateResourceStatement x) {\n        return true;\n    }\n\n    default void endVisit(StarRocksCreateResourceStatement x) {\n    }\n\n    default boolean visit(SQLCostStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCostStatement x) {\n    }\n    default boolean visit(StarRocksIndexDefinition x) {\n        return true;\n    }\n\n    default void endVisit(StarRocksIndexDefinition x) {\n    }\n\n    default boolean visit(SQLSelectQueryTemplate x) {\n        return true;\n    }\n\n    default void endVisit(SQLSelectQueryTemplate x) {\n    }\n\n    default boolean visit(SQLAlterTableSetSerde x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetSerde x) {\n    }\n\n    default boolean visit(SQLAlterTableSetFileFormat x) {\n        return true;\n    }\n\n    default void endVisit(SQLAlterTableSetFileFormat x) {\n    }\n\n    default boolean visit(SQLTop x) { return true; }\n\n    default void endVisit(SQLTop x) {\n    }\n\n    default boolean visit(SQLPatternExpr x) { return true; }\n\n    default void endVisit(SQLPatternExpr x) {\n    }\n\n    default boolean visit(SQLCommitTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLCommitTransactionStatement x) {\n    }\n\n    default boolean visit(SQLRaiseStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLRaiseStatement x) {\n    }\n\n    default boolean visit(SQLAtTimeZoneExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLAtTimeZoneExpr x) {\n    }\n\n    default boolean visit(SQLRollbackTransactionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLRollbackTransactionStatement x) {}\n\n    default boolean visit(SQLExceptionStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLExceptionStatement x) {}\n\n    default boolean visit(SQLExceptionStatement.Item x) {\n        return true;\n    }\n\n    default void endVisit(SQLExceptionStatement.Item x) {}\n\n    default boolean visit(SQLContinueStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLContinueStatement x) {}\n\n    default boolean visit(SQLBreakStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLBreakStatement x) {}\n\n    default boolean visit(SQLLeaveStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLLeaveStatement x) {}\n\n    default boolean visit(SQLExecuteImmediateStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLExecuteImmediateStatement x) {}\n    default boolean visit(SQLRefreshTableStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLRefreshTableStatement x) {\n    }\n\n    default boolean visit(SQLTypeExpr x) {\n        return true;\n    }\n\n    default void endVisit(SQLTypeExpr x) {\n    }\n\n    default boolean visit(SQLComputeIncrementalStatsStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLComputeIncrementalStatsStatement x) {\n    }\n\n    default boolean visit(SQLResetStatement x) {\n        return true;\n    }\n\n    default void endVisit(SQLResetStatement x) {\n    }\n    static SQLASTVisitor ofMethodInvoke(Consumer<SQLMethodInvokeExpr> p) {\n        return ofMethodInvoke(null, p);\n    }\n\n    static SQLASTVisitor ofMethodInvoke(Predicate<String> filter, Consumer<SQLMethodInvokeExpr> p) {\n        class MethodInvokeVisitor implements SQLASTVisitor, BigQueryVisitor, OdpsASTVisitor, OracleASTVisitor, MySqlASTVisitor, PGASTVisitor {\n            final Predicate<String> filter;\n            final Consumer<SQLMethodInvokeExpr> p;\n            public MethodInvokeVisitor(Predicate<String> filter, Consumer<SQLMethodInvokeExpr> p) {\n                this.filter = filter;\n                this.p = p;\n            }\n\n            public boolean visit(SQLMethodInvokeExpr x) {\n                if (filter == null || filter.test(x.getMethodName())) {\n                    p.accept(x);\n                }\n                return true;\n            }\n\n            public boolean visit(SQLAggregateExpr x) {\n                if (filter == null || filter.test(x.getMethodName())) {\n                    p.accept(x);\n                }\n                return true;\n            }\n        }\n        return new MethodInvokeVisitor(filter, p);\n    }\n\n    static SQLASTVisitor ofAggregate(Consumer<SQLAggregateExpr> p) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLAggregateExpr x) {\n                p.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofAggregate(Predicate<String> filter, Consumer<SQLAggregateExpr> p) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLAggregateExpr x) {\n                if (filter == null || filter.test(x.getMethodName())) {\n                    p.accept(x);\n                }\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofCast(Consumer<SQLCastExpr> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLCastExpr x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofUnnest(Consumer<SQLUnnestTableSource> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLUnnestTableSource x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofExprTableSource(Consumer<SQLExprTableSource> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLExprTableSource x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofDelete(Consumer<SQLDeleteStatement> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLDeleteStatement x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofMerge(Consumer<SQLMergeStatement> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLMergeStatement x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofDeclare(Consumer<SQLDeclareStatement> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLDeclareStatement x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofIf(Consumer<SQLIfStatement> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLIfStatement x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofPropertyExpr(Consumer<SQLPropertyExpr> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLPropertyExpr x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n\n    static SQLASTVisitor ofIdentifier(Consumer<SQLIdentifierExpr> h) {\n        return new SQLASTVisitor() {\n            public boolean visit(SQLIdentifierExpr x) {\n                h.accept(x);\n                return true;\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\n\npublic class SQLASTVisitorAdapter implements SQLASTVisitor {\n    protected DbType dbType;\n    protected int features;\n\n    public final boolean isEnabled(VisitorFeature feature) {\n        return VisitorFeature.isEnabled(this.features, feature);\n    }\n\n    public final boolean isEnabled(int features, VisitorFeature feature) {\n        return VisitorFeature.isEnabled(this.features | features, feature);\n    }\n\n    public void config(VisitorFeature feature, boolean state) {\n        features = VisitorFeature.config(features, feature, state);\n    }\n\n    public int getFeatures() {\n        return features;\n    }\n\n    public void setFeatures(int features) {\n        this.features = features;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLDataTypeValidator.java",
    "content": "package com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.FastsqlException;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.HiveUtils;\nimport com.alibaba.druid.util.MySqlUtils;\nimport com.alibaba.druid.util.OdpsUtils;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic class SQLDataTypeValidator extends SQLASTVisitorAdapter {\n    private long[] supportTypeHashCodes;\n\n    public SQLDataTypeValidator(String[] supportTypes) {\n        this.supportTypeHashCodes = FnvHash.fnv1a_64_lower(supportTypes, true);\n    }\n\n    public SQLDataTypeValidator(Set<String> typeSet) {\n        this.supportTypeHashCodes = new long[typeSet.size()];\n\n        int i = 0;\n        for (String type : typeSet) {\n            this.supportTypeHashCodes[i++] = FnvHash.fnv1a_64_lower(type);\n        }\n        Arrays.sort(supportTypeHashCodes);\n    }\n\n    public boolean visit(SQLDataType x) {\n        validate(x);\n        return true;\n    }\n\n    public boolean visit(SQLCharacterDataType x) {\n        validate(x);\n        return true;\n    }\n\n    public boolean visit(SQLArrayDataType x) {\n        validate(x);\n        return true;\n    }\n\n    public boolean visit(SQLMapDataType x) {\n        validate(x);\n        return true;\n    }\n\n    public boolean visit(SQLStructDataType x) {\n        validate(x);\n        return true;\n    }\n\n    public void validate(SQLDataType x) {\n        long hash = x.nameHashCode64();\n        if (Arrays.binarySearch(supportTypeHashCodes, hash) < 0) {\n            String msg = \"illegal dataType : \" + x.getName();\n\n            final SQLObject parent = x.getParent();\n            if (parent instanceof SQLColumnDefinition) {\n                SQLColumnDefinition column = (SQLColumnDefinition) parent;\n                if (column.getName() != null) {\n                    msg += \", column \" + column.getName();\n                }\n            }\n            throw new FastsqlException(msg);\n        }\n    }\n\n    private static String[] odpsTypes;\n    private static String[] hiveTypes;\n    private static String[] mysqlTypes;\n\n    public static SQLDataTypeValidator of(DbType dbType) {\n        Set<String> typeSet = null;\n        String[] types = null;\n        switch (dbType) {\n            case odps: {\n                types = odpsTypes;\n                if (types == null) {\n                    typeSet = new HashSet<>();\n                    OdpsUtils.DIALECT.dumpBuiltInDataTypes(typeSet);\n                }\n                break;\n            }\n            case hive: {\n                types = hiveTypes;\n                if (types == null) {\n                    typeSet = new HashSet<>();\n                    HiveUtils.loadDataTypes(typeSet);\n                }\n                break;\n            }\n            case mysql: {\n                types = mysqlTypes;\n                if (types == null) {\n                    typeSet = new HashSet<>();\n                    MySqlUtils.loadDataTypes(typeSet);\n                }\n                break;\n            }\n            default:\n                break;\n        }\n\n        if (types == null && typeSet != null) {\n            types = typeSet.toArray(new String[typeSet.size()]);\n        }\n\n        if (types == null) {\n            throw new FastsqlException(\"dataType \" + dbType + \" not support.\");\n        }\n\n        return new SQLDataTypeValidator(types);\n    }\n\n    public static void check(SQLStatement stmt) {\n        SQLDataTypeValidator v = of(stmt.getDbType());\n        stmt.accept(v);\n    }\n\n    public static void check(List<SQLStatement> stmtList) {\n        if (stmtList.isEmpty()) {\n            return;\n        }\n\n        DbType dbType = stmtList.get(0).getDbType();\n        SQLDataTypeValidator v = of(dbType);\n\n        check(stmtList, dbType);\n    }\n\n    public static void check(List<SQLStatement> stmtList, DbType dbType) {\n        if (stmtList.isEmpty()) {\n            return;\n        }\n\n        SQLDataTypeValidator v = of(dbType);\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(v);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.List;\n\npublic interface SQLEvalVisitor extends SQLASTVisitor {\n    public static final String EVAL_VALUE = \"eval.value\";\n    public static final String EVAL_EXPR = \"eval.expr\";\n    public static final Object EVAL_ERROR = new Object();\n    public static final Object EVAL_VALUE_COUNT = new Object();\n    public static final Object EVAL_VALUE_NULL = new Object();\n\n    Function getFunction(String funcName);\n\n    void registerFunction(String funcName, Function function);\n\n    void unregisterFunction(String funcName);\n\n    List<Object> getParameters();\n\n    void setParameters(List<Object> parameters);\n\n    int incrementAndGetVariantIndex();\n\n    boolean isMarkVariantIndex();\n\n    void setMarkVariantIndex(boolean markVariantIndex);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorImpl.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.visitor.functions.Function;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SQLEvalVisitorImpl extends SQLASTVisitorAdapter implements SQLEvalVisitor {\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private Map<String, Function> functions = new HashMap<String, Function>();\n\n    private int variantIndex = -1;\n\n    private boolean markVariantIndex = true;\n\n    public SQLEvalVisitorImpl() {\n        this(new ArrayList<Object>(1));\n    }\n\n    public SQLEvalVisitorImpl(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public int incrementAndGetVariantIndex() {\n        return ++variantIndex;\n    }\n\n    public int getVariantIndex() {\n        return variantIndex;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean visit(SQLHexExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLCaseExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLInListExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLNullExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public boolean visit(SQLQueryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    public boolean isMarkVariantIndex() {\n        return markVariantIndex;\n    }\n\n    public void setMarkVariantIndex(boolean markVariantIndex) {\n        this.markVariantIndex = markVariantIndex;\n    }\n\n    @Override\n    public Function getFunction(String funcName) {\n        return functions.get(funcName);\n    }\n\n    @Override\n    public void registerFunction(String funcName, Function function) {\n        functions.put(funcName, function);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n\n    @Override\n    public void unregisterFunction(String funcName) {\n        functions.remove(funcName);\n    }\n\n    @Override\n    public boolean visit(SQLBooleanExpr x) {\n        x.getAttributes().put(EVAL_VALUE, x.getBooleanValue());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBinaryExpr x) {\n        return SQLEvalVisitorUtils.visit(this, x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.FastsqlException;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2EvalVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlEvalVisitorImpl;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleEvalVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGEvalVisitor;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerEvalVisitor;\nimport com.alibaba.druid.sql.visitor.functions.*;\nimport com.alibaba.druid.util.HexBin;\nimport com.alibaba.druid.util.Utils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils.WallConditionContext;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.util.regex.Pattern;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.*;\n\npublic class SQLEvalVisitorUtils {\n    private static Map<String, Function> functions = new HashMap<String, Function>();\n\n    static {\n        registerBaseFunctions();\n    }\n\n    public static Object evalExpr(DbType dbType, String expr, Object... parameters) {\n        SQLExpr sqlExpr = SQLUtils.toSQLExpr(expr, dbType);\n        return eval(dbType, sqlExpr, parameters);\n    }\n\n    public static Object evalExpr(DbType dbType, String expr, List<Object> parameters) {\n        SQLExpr sqlExpr = SQLUtils.toSQLExpr(expr);\n        return eval(dbType, sqlExpr, parameters);\n    }\n\n    public static Object eval(DbType dbType, SQLObject sqlObject, Object... parameters) {\n        Object value = eval(dbType, sqlObject, Arrays.asList(parameters));\n\n        if (value == EVAL_VALUE_NULL) {\n            value = null;\n        }\n\n        return value;\n    }\n\n    public static Object getValue(SQLObject sqlObject) {\n        if (sqlObject instanceof SQLNumericLiteralExpr) {\n            return ((SQLNumericLiteralExpr) sqlObject).getNumber();\n        }\n\n        return sqlObject.getAttribute(EVAL_VALUE);\n    }\n\n    public static Object eval(DbType dbType, SQLObject sqlObject, List<Object> parameters) {\n        return eval(dbType, sqlObject, parameters, true);\n    }\n\n    public static Object eval(DbType dbType, SQLObject sqlObject, List<Object> parameters, boolean throwError) {\n        SQLEvalVisitor visitor = createEvalVisitor(dbType);\n        visitor.setParameters(parameters);\n\n        Object value;\n        if (sqlObject instanceof SQLValuableExpr) {\n            value = ((SQLValuableExpr) sqlObject).getValue();\n        } else {\n            sqlObject.accept(visitor);\n\n            value = getValue(sqlObject);\n\n            if (value == null) {\n                if (throwError && !sqlObject.containsAttribute(EVAL_VALUE)) {\n                    throw new FastsqlException(\"eval error : \" + SQLUtils.toSQLString(sqlObject, dbType));\n                }\n            }\n        }\n\n        return value;\n    }\n\n    public static SQLEvalVisitor createEvalVisitor(DbType dbType) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        switch (dbType) {\n            case mysql:\n            case mariadb:\n            case tidb:\n            case h2:\n            case lealone:\n            case polardbx:\n                return new MySqlEvalVisitorImpl();\n            case oracle:\n                return new OracleEvalVisitor();\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGEvalVisitor();\n            case sqlserver:\n            case jtds:\n                return new SQLServerEvalVisitor();\n            case db2:\n                return new DB2EvalVisitor();\n            default:\n                return new SQLEvalVisitorImpl();\n        }\n    }\n\n    static void registerBaseFunctions() {\n        functions.put(\"now\", Now.instance);\n        functions.put(\"concat\", Concat.instance);\n        functions.put(\"concat_ws\", Concat.instance);\n        functions.put(\"ascii\", Ascii.instance);\n        functions.put(\"bin\", Bin.instance);\n        functions.put(\"bit_length\", BitLength.instance);\n        functions.put(\"insert\", Insert.instance);\n        functions.put(\"instr\", Instr.instance);\n        functions.put(\"char\", Char.instance);\n        functions.put(\"elt\", Elt.instance);\n        functions.put(\"left\", Left.instance);\n        functions.put(\"locate\", Locate.instance);\n        functions.put(\"lpad\", Lpad.instance);\n        functions.put(\"rpad\", Rpad.instance);\n        functions.put(\"ltrim\", Ltrim.instance);\n        functions.put(\"mid\", Substring.instance);\n        functions.put(\"substr\", Substring.instance);\n        functions.put(\"substring\", Substring.instance);\n        functions.put(\"right\", Right.instance);\n        functions.put(\"reverse\", Reverse.instance);\n        functions.put(\"len\", Length.instance);\n        functions.put(\"length\", Length.instance);\n        functions.put(\"char_length\", Length.instance);\n        functions.put(\"character_length\", Length.instance);\n        functions.put(\"trim\", Trim.instance);\n        functions.put(\"ucase\", Ucase.instance);\n        functions.put(\"upper\", Ucase.instance);\n        functions.put(\"lcase\", Lcase.instance);\n        functions.put(\"lower\", Lcase.instance);\n        functions.put(\"hex\", Hex.instance);\n        functions.put(\"unhex\", Unhex.instance);\n        functions.put(\"greatest\", Greatest.instance);\n        functions.put(\"least\", Least.instance);\n        functions.put(\"isnull\", Isnull.instance);\n        functions.put(\"if\", If.instance);\n        functions.put(\"to_date\", ToDate.instance);\n        functions.put(\"to_char\", ToChar.instance);\n        functions.put(\"dateadd\", DateAdd.instance);\n\n        functions.put(\"md5\", OneParamFunctions.instance);\n        functions.put(\"bit_count\", OneParamFunctions.instance);\n        functions.put(\"soundex\", OneParamFunctions.instance);\n        functions.put(\"space\", OneParamFunctions.instance);\n        functions.put(\"replace\", Replace.instance);\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        SQLExpr owner = x.getOwner();\n        if (owner != null) {\n            owner.accept(visitor);\n        }\n\n        String methodName = x.getMethodName();\n        if (methodName == null) {\n            return true;\n        }\n        methodName = methodName.toLowerCase();\n\n        Function function = visitor.getFunction(methodName);\n\n        if (function == null) {\n            function = functions.get(methodName);\n        }\n\n        if (function != null) {\n            Object result = function.eval(visitor, x);\n\n            if (result != SQLEvalVisitor.EVAL_ERROR && result != null) {\n                x.putAttribute(EVAL_VALUE, result);\n            }\n            return false;\n        }\n\n        switch (methodName) {\n            case \"mod\": {\n                if (x.getArguments().size() != 2) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                SQLExpr param1 = x.getArguments().get(1);\n                param0.accept(visitor);\n                param1.accept(visitor);\n\n                Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n                Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n                if (param0Value == null || param1Value == null) {\n                    return false;\n                }\n\n                long intValue0 = castToLong(param0Value);\n                long intValue1 = castToLong(param1Value);\n\n                long result = intValue0 % intValue1;\n                if (result >= Integer.MIN_VALUE && result <= Integer.MAX_VALUE) {\n                    int intResult = (int) result;\n                    x.putAttribute(EVAL_VALUE, intResult);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"abs\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                Object result;\n                if (paramValue instanceof Integer) {\n                    result = Math.abs(((Integer) paramValue).intValue());\n                } else if (paramValue instanceof Long) {\n                    result = Math.abs(((Long) paramValue).longValue());\n                } else {\n                    result = castToDecimal(paramValue).abs();\n                }\n\n                x.putAttribute(EVAL_VALUE, result);\n                break;\n            }\n            case \"acos\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.acos(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"asin\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.asin(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"atan\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.atan(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"atan2\": {\n                if (x.getArguments().size() != 2) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                SQLExpr param1 = x.getArguments().get(1);\n                param0.accept(visitor);\n                param1.accept(visitor);\n\n                Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n                Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n                if (param0Value == null || param1Value == null) {\n                    return false;\n                }\n\n                double doubleValue0 = castToDouble(param0Value);\n                double doubleValue1 = castToDouble(param1Value);\n                double result = Math.atan2(doubleValue0, doubleValue1);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"ceil\":\n            case \"ceiling\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                if (Double.isNaN(doubleValue)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    int result = (int) Math.ceil(doubleValue);\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"cos\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.cos(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"sin\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.sin(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"log\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.log(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"log10\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.log10(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"tan\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.tan(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"sqrt\": {\n                if (x.getArguments().size() != 1) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                param0.accept(visitor);\n\n                Object paramValue = param0.getAttributes().get(EVAL_VALUE);\n                if (paramValue == null) {\n                    return false;\n                }\n\n                double doubleValue = castToDouble(paramValue);\n                double result = Math.sqrt(doubleValue);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"power\":\n            case \"pow\": {\n                if (x.getArguments().size() != 2) {\n                    return false;\n                }\n\n                SQLExpr param0 = x.getArguments().get(0);\n                SQLExpr param1 = x.getArguments().get(1);\n                param0.accept(visitor);\n                param1.accept(visitor);\n\n                Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n                Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n                if (param0Value == null || param1Value == null) {\n                    return false;\n                }\n\n                double doubleValue0 = castToDouble(param0Value);\n                double doubleValue1 = castToDouble(param1Value);\n                double result = Math.pow(doubleValue0, doubleValue1);\n\n                if (Double.isNaN(result)) {\n                    x.putAttribute(EVAL_VALUE, null);\n                } else {\n                    x.putAttribute(EVAL_VALUE, result);\n                }\n                break;\n            }\n            case \"pi\": {\n                x.putAttribute(EVAL_VALUE, Math.PI);\n                break;\n            }\n            case \"rand\": {\n                x.putAttribute(EVAL_VALUE, Math.random());\n                break;\n            }\n            case \"chr\": {\n                SQLExpr first = x.getArguments().get(0);\n                Object firstResult = getValue(first);\n                if (firstResult instanceof Number) {\n                    int intValue = ((Number) firstResult).intValue();\n                    char ch = (char) intValue;\n                    x.putAttribute(EVAL_VALUE, Character.toString(ch));\n                }\n                break;\n            }\n            case \"current_user\":\n                x.putAttribute(EVAL_VALUE, \"CURRENT_USER\");\n                break;\n            case \"name\": {\n                if (owner != null && x.getArguments().isEmpty()) {\n                    Object ownerValue = owner.getAttribute(EVAL_VALUE);\n                    if (ownerValue == null) {\n                        ownerValue = owner;\n                    }\n                    if (ownerValue instanceof SQLDataType) {\n                        String name = ((SQLDataType) ownerValue).getName();\n                        x.putAttribute(EVAL_VALUE, name);\n                    }\n                    if (ownerValue instanceof SQLMethodInvokeExpr) {\n                        String name = ((SQLMethodInvokeExpr) ownerValue).getMethodName();\n                        x.putAttribute(EVAL_VALUE, name);\n                    }\n                }\n                break;\n            }\n            case \"type\": {\n                if (owner != null && x.getArguments().isEmpty()) {\n                    Object ownerValue = owner.getAttribute(EVAL_VALUE);\n                    if (ownerValue == null) {\n                        ownerValue = owner;\n                    }\n                    String type = type(ownerValue);\n                    x.putAttribute(EVAL_VALUE, type);\n                }\n                break;\n            }\n            case \"parent\": {\n                if (owner != null && x.getArguments().isEmpty()) {\n                    Object ownerValue = owner.getAttribute(EVAL_VALUE);\n                    if (ownerValue == null) {\n                        ownerValue = owner;\n                    }\n                    if (ownerValue instanceof SQLObject) {\n                        SQLObject parent = ((SQLObject) ownerValue).getParent();\n                        if (parent instanceof SQLSelect) {\n                            parent = parent.getParent();\n                        }\n                        if (parent instanceof SQLSelectStatement) {\n                            x.putAttribute(EVAL_VALUE, EVAL_VALUE_NULL);\n                        }\n                    }\n                }\n                break;\n            }\n            default:\n                break;\n        }\n\n        return false;\n    }\n\n    public static String type(Object x) {\n        if (x instanceof SQLIntervalExpr) {\n            return \"interval\";\n        }\n\n        if (x instanceof SQLCharExpr || x instanceof String) {\n            return \"string\";\n        }\n\n        if (x instanceof SQLNumericLiteralExpr || x instanceof Number) {\n            return \"number\";\n        }\n\n        if (x instanceof SQLMethodInvokeExpr) {\n            return \"function\";\n        }\n\n        if (x instanceof SQLIdentifierExpr) {\n            SQLColumnDefinition column = ((SQLIdentifierExpr) x).getResolvedColumn();\n            if (column != null) {\n                SQLDataType dataType = column.getDataType();\n\n                if (dataType instanceof SQLCharacterDataType) {\n                    return \"string\";\n                }\n                String dataTypeName = dataType.getName();\n                if (dataTypeName != null) {\n                    dataTypeName = dataTypeName.toLowerCase();\n                    switch (dataTypeName) {\n                        case \"tinyint\":\n                        case \"smallint\":\n                        case \"int\":\n                        case \"integer\":\n                        case \"bigint\":\n                        case \"numeric\":\n                        case \"number\":\n                        case \"decimal\":\n                        case \"float\":\n                        case \"double\":\n                            return \"number\";\n                        default:\n                            break;\n                    }\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLCharExpr x) {\n        x.putAttribute(EVAL_VALUE, x.getText());\n        return true;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLHexExpr x) {\n        String hex = x.getHex();\n        byte[] bytes = HexBin.decode(hex);\n        if (bytes == null) {\n            x.putAttribute(EVAL_VALUE, EVAL_ERROR);\n        } else {\n            String val = new String(bytes);\n            x.putAttribute(EVAL_VALUE, val);\n        }\n        return true;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLBinaryExpr x) {\n        String text = x.getText();\n\n        long[] words = new long[text.length() / 64 + 1];\n        for (int i = text.length() - 1; i >= 0; --i) {\n            char ch = text.charAt(i);\n            if (ch == '1') {\n                int wordIndex = i >> 6;\n                words[wordIndex] |= (1L << (text.length() - 1 - i));\n            }\n        }\n\n        Object val;\n\n        if (words.length == 1) {\n            val = words[0];\n        } else {\n            byte[] bytes = new byte[words.length * 8];\n\n            for (int i = 0; i < words.length; ++i) {\n                Utils.putLong(bytes, (words.length - 1 - i) * 8, words[i]);\n            }\n\n            val = new BigInteger(bytes);\n        }\n\n        x.putAttribute(EVAL_VALUE, val);\n\n        return false;\n    }\n\n    public static SQLExpr unwrap(SQLExpr expr) {\n        if (expr == null) {\n            return null;\n        }\n\n        if (expr instanceof SQLQueryExpr) {\n            SQLSelect select = ((SQLQueryExpr) expr).getSubQuery();\n            if (select == null) {\n                return null;\n            }\n            if (select.getQuery() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) select.getQuery();\n                if (queryBlock.getFrom() == null) {\n                    if (queryBlock.getSelectList().size() == 1) {\n                        return queryBlock.getSelectList().get(0).getExpr();\n                    }\n                }\n            }\n        }\n\n        return expr;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLBetweenExpr x) {\n        SQLExpr testExpr = unwrap(x.getTestExpr());\n        testExpr.accept(visitor);\n\n        if (!testExpr.getAttributes().containsKey(EVAL_VALUE)) {\n            return false;\n        }\n\n        Object value = testExpr.getAttribute(EVAL_VALUE);\n\n        SQLExpr beginExpr = unwrap(x.getBeginExpr());\n        beginExpr.accept(visitor);\n        if (!beginExpr.getAttributes().containsKey(EVAL_VALUE)) {\n            return false;\n        }\n\n        Object begin = beginExpr.getAttribute(EVAL_VALUE);\n\n        if (lt(value, begin)) {\n            x.getAttributes().put(EVAL_VALUE, x.isNot() ? true : false);\n            return false;\n        }\n\n        SQLExpr endExpr = unwrap(x.getEndExpr());\n        endExpr.accept(visitor);\n        if (!endExpr.getAttributes().containsKey(EVAL_VALUE)) {\n            return false;\n        }\n\n        Object end = endExpr.getAttribute(EVAL_VALUE);\n\n        if (gt(value, end)) {\n            x.getAttributes().put(EVAL_VALUE, x.isNot() ? true : false);\n            return false;\n        }\n\n        x.getAttributes().put(EVAL_VALUE, x.isNot() ? false : true);\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLNullExpr x) {\n        x.getAttributes().put(EVAL_VALUE, EVAL_VALUE_NULL);\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLCaseExpr x) {\n        Object value;\n        if (x.getValueExpr() != null) {\n            x.getValueExpr().accept(visitor);\n\n            if (!x.getValueExpr().getAttributes().containsKey(EVAL_VALUE)) {\n                return false;\n            }\n\n            value = x.getValueExpr().getAttribute(EVAL_VALUE);\n        } else {\n            value = null;\n        }\n\n        for (SQLCaseExpr.Item item : x.getItems()) {\n            item.getConditionExpr().accept(visitor);\n\n            if (!item.getConditionExpr().getAttributes().containsKey(EVAL_VALUE)) {\n                return false;\n            }\n\n            Object conditionValue = item.getConditionExpr().getAttribute(EVAL_VALUE);\n\n            if ((x.getValueExpr() != null && eq(value, conditionValue))\n                    || (x.getValueExpr() == null && conditionValue instanceof Boolean && Boolean.TRUE.equals((Boolean) conditionValue))) {\n                item.getValueExpr().accept(visitor);\n\n                if (item.getValueExpr().getAttributes().containsKey(EVAL_VALUE)) {\n                    x.getAttributes().put(EVAL_VALUE, item.getValueExpr().getAttribute(EVAL_VALUE));\n                }\n\n                return false;\n            }\n        }\n\n        if (x.getElseExpr() != null) {\n            x.getElseExpr().accept(visitor);\n\n            if (x.getElseExpr().getAttributes().containsKey(EVAL_VALUE)) {\n                x.getAttributes().put(EVAL_VALUE, x.getElseExpr().getAttribute(EVAL_VALUE));\n            }\n        }\n\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLInListExpr x) {\n        SQLExpr valueExpr = x.getExpr();\n        valueExpr.accept(visitor);\n        if (!valueExpr.getAttributes().containsKey(EVAL_VALUE)) {\n            return false;\n        }\n        Object value = valueExpr.getAttribute(EVAL_VALUE);\n\n        for (SQLExpr item : x.getTargetList()) {\n            item.accept(visitor);\n            if (!item.getAttributes().containsKey(EVAL_VALUE)) {\n                return false;\n            }\n            Object itemValue = item.getAttribute(EVAL_VALUE);\n            if (eq(value, itemValue)) {\n                x.getAttributes().put(EVAL_VALUE, x.isNot() ? false : true);\n                return false;\n            }\n        }\n\n        x.getAttributes().put(EVAL_VALUE, x.isNot() ? true : false);\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLQueryExpr x) {\n        if (WallVisitorUtils.isSimpleCountTableSource(null, ((SQLQueryExpr) x).getSubQuery())) {\n            x.putAttribute(EVAL_VALUE, 1);\n            return false;\n        }\n\n        if (x.getSubQuery().getQuery() instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x.getSubQuery().getQuery();\n\n            boolean nullFrom = false;\n            if (queryBlock.getFrom() == null) {\n                nullFrom = true;\n            } else if (queryBlock.getFrom() instanceof SQLExprTableSource) {\n                SQLExpr expr = ((SQLExprTableSource) queryBlock.getFrom()).getExpr();\n                if (expr instanceof SQLIdentifierExpr) {\n                    if (\"dual\".equalsIgnoreCase(((SQLIdentifierExpr) expr).getName())) {\n                        nullFrom = true;\n                    }\n                }\n            }\n\n            if (nullFrom) {\n                List<Object> row = new ArrayList<Object>(queryBlock.getSelectList().size());\n                for (int i = 0; i < queryBlock.getSelectList().size(); ++i) {\n                    SQLSelectItem item = queryBlock.getSelectList().get(i);\n                    item.getExpr().accept(visitor);\n                    Object cell = item.getExpr().getAttribute(EVAL_VALUE);\n                    row.add(cell);\n                }\n                List<List<Object>> rows = new ArrayList<List<Object>>(1);\n                rows.add(row);\n\n                Object result = rows;\n                queryBlock.putAttribute(EVAL_VALUE, result);\n                x.getSubQuery().putAttribute(EVAL_VALUE, result);\n                x.putAttribute(EVAL_VALUE, result);\n\n                return false;\n            }\n        }\n\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLUnaryExpr x) {\n        final WallConditionContext wallConditionContext = WallVisitorUtils.getWallConditionContext();\n        if (x.getOperator() == SQLUnaryOperator.Compl && wallConditionContext != null) {\n            wallConditionContext.setBitwise(true);\n        }\n\n        x.getExpr().accept(visitor);\n\n        Object val = x.getExpr().getAttribute(EVAL_VALUE);\n        if (val == EVAL_ERROR) {\n            x.putAttribute(EVAL_VALUE, EVAL_ERROR);\n            return false;\n        }\n\n        if (val == null) {\n            x.putAttribute(EVAL_VALUE, EVAL_VALUE_NULL);\n            return false;\n        }\n\n        switch (x.getOperator()) {\n            case BINARY:\n            case RAW:\n                x.putAttribute(EVAL_VALUE, val);\n                break;\n            case NOT:\n            case Not: {\n                Boolean booleanVal = castToBoolean(val);\n                if (booleanVal != null) {\n                    x.putAttribute(EVAL_VALUE, !booleanVal);\n                }\n                break;\n            }\n            case Plus:\n                x.putAttribute(EVAL_VALUE, val);\n                break;\n            case Negative:\n                Object value;\n                if (val instanceof SQLName) {\n                    value = new SQLUnaryExpr(SQLUnaryOperator.Negative, (SQLName) val);\n                } else {\n                    value = multi(val, -1);\n                }\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case Compl:\n                x.putAttribute(EVAL_VALUE, ~castToInteger(val));\n                break;\n            default:\n                break;\n        }\n\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLBinaryOpExpr x) {\n        SQLExpr left = unwrap(x.getLeft());\n        SQLExpr right = unwrap(x.getRight());\n\n        // final WallConditionContext old = wallConditionContextLocal.get();\n\n        left.accept(visitor);\n        right.accept(visitor);\n\n        final WallConditionContext wallConditionContext = WallVisitorUtils.getWallConditionContext();\n        if (x.getOperator() == SQLBinaryOperator.BooleanOr) {\n            if (wallConditionContext != null) {\n                if (Boolean.TRUE.equals(left.getAttribute(EVAL_VALUE)) || Boolean.TRUE.equals(right.getAttribute(EVAL_VALUE))) {\n                    wallConditionContext.setPartAlwayTrue(true);\n                }\n            }\n        } else if (x.getOperator() == SQLBinaryOperator.BooleanAnd) {\n            if (wallConditionContext != null) {\n                if (Boolean.FALSE.equals(left.getAttribute(EVAL_VALUE)) || Boolean.FALSE.equals(right.getAttribute(EVAL_VALUE))) {\n                    wallConditionContext.setPartAlwayFalse(true);\n                }\n            }\n        } else if (x.getOperator() == SQLBinaryOperator.BooleanXor) {\n            if (wallConditionContext != null) {\n                wallConditionContext.setXor(true);\n            }\n        } else if (x.getOperator() == SQLBinaryOperator.BitwiseAnd //\n                || x.getOperator() == SQLBinaryOperator.BitwiseNot //\n                || x.getOperator() == SQLBinaryOperator.BitwiseOr //\n                || x.getOperator() == SQLBinaryOperator.BitwiseXor) {\n            if (wallConditionContext != null) {\n                wallConditionContext.setBitwise(true);\n            }\n        }\n\n        Object leftValue = left.getAttribute(EVAL_VALUE);\n        Object rightValue = right.getAttributes().get(EVAL_VALUE);\n\n        if (x.getOperator() == SQLBinaryOperator.Like) {\n            if (isAlwayTrueLikePattern(x.getRight())) {\n                x.putAttribute(WallVisitorUtils.HAS_TRUE_LIKE, Boolean.TRUE);\n                x.putAttribute(EVAL_VALUE, Boolean.TRUE);\n                return false;\n            }\n        }\n\n        if (x.getOperator() == SQLBinaryOperator.NotLike) {\n            if (isAlwayTrueLikePattern(x.getRight())) {\n                x.putAttribute(EVAL_VALUE, Boolean.FALSE);\n                return false;\n            }\n        }\n\n        boolean leftHasValue = left.getAttributes().containsKey(EVAL_VALUE);\n        boolean rightHasValue = right.getAttributes().containsKey(EVAL_VALUE);\n\n        if ((!leftHasValue) && !rightHasValue) {\n            SQLExpr leftEvalExpr = (SQLExpr) left.getAttribute(EVAL_EXPR);\n            SQLExpr rightEvalExpr = (SQLExpr) right.getAttribute(EVAL_EXPR);\n\n            if (leftEvalExpr != null && leftEvalExpr.equals(rightEvalExpr)) {\n                switch (x.getOperator()) {\n                    case Like:\n                    case SoudsLike:\n                    case Equality:\n                    case GreaterThanOrEqual:\n                    case LessThanOrEqual:\n                    case NotLessThan:\n                    case NotGreaterThan:\n                        x.putAttribute(EVAL_VALUE, Boolean.TRUE);\n                        return false;\n                    case NotEqual:\n                    case LessThanOrGreater:\n                    case NotLike:\n                    case GreaterThan:\n                    case LessThan:\n                        x.putAttribute(EVAL_VALUE, Boolean.FALSE);\n                        return false;\n                    default:\n                        break;\n                }\n            }\n        }\n\n        if (!leftHasValue) {\n            return false;\n        }\n\n        if (!rightHasValue) {\n            return false;\n        }\n\n        if (wallConditionContext != null) {\n            wallConditionContext.setConstArithmetic(true);\n        }\n\n        leftValue = processValue(leftValue);\n        rightValue = processValue(rightValue);\n\n        if (leftValue == null || rightValue == null) {\n            return false;\n        }\n\n        Object value = null;\n        switch (x.getOperator()) {\n            case Add:\n                value = add(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case Subtract:\n                value = sub(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case Multiply:\n                value = multi(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case Divide:\n                value = div(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case RightShift:\n                value = rightShift(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case BitwiseAnd:\n                value = bitAnd(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case BitwiseOr:\n                value = bitOr(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case GreaterThan:\n                value = gt(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case GreaterThanOrEqual:\n                value = gteq(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case LessThan:\n                value = lt(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case LessThanOrEqual:\n                value = lteq(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case Is:\n                if (rightValue == EVAL_VALUE_NULL) {\n                    if (leftValue != null) {\n                        value = (leftValue == EVAL_VALUE_NULL);\n                        x.putAttribute(EVAL_VALUE, value);\n                        break;\n                    }\n                }\n                break;\n            case Equality:\n                value = eq(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case NotEqual:\n            case LessThanOrGreater:\n                value = !eq(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, value);\n                break;\n            case IsNot:\n                if (leftValue == EVAL_VALUE_NULL) {\n                    x.putAttribute(EVAL_VALUE, false);\n                } else if (leftValue != null) {\n                    x.putAttribute(EVAL_VALUE, true);\n                }\n                break;\n            case RegExp:\n            case RLike: {\n                String pattern = castToString(rightValue);\n                String input = castToString(left.getAttributes().get(EVAL_VALUE));\n                boolean matchResult = Pattern.matches(pattern, input);\n                x.putAttribute(EVAL_VALUE, matchResult);\n                break;\n            }\n            case NotRegExp:\n            case NotRLike: {\n                String pattern = castToString(rightValue);\n                String input = castToString(left.getAttributes().get(EVAL_VALUE));\n                boolean matchResult = !Pattern.matches(pattern, input);\n                x.putAttribute(EVAL_VALUE, matchResult);\n                break;\n            }\n            case Like: {\n                String pattern = castToString(rightValue);\n                String input = castToString(left.getAttributes().get(EVAL_VALUE));\n                boolean matchResult = like(input, pattern);\n                x.putAttribute(EVAL_VALUE, matchResult);\n                break;\n            }\n            case NotLike: {\n                String pattern = castToString(rightValue);\n                String input = castToString(left.getAttributes().get(EVAL_VALUE));\n                boolean matchResult = !like(input, pattern);\n                x.putAttribute(EVAL_VALUE, matchResult);\n                break;\n            }\n            case Concat: {\n                String result = leftValue.toString() + rightValue.toString();\n                x.putAttribute(EVAL_VALUE, result);\n                break;\n            }\n            case BooleanAnd: {\n                boolean first = eq(leftValue, true);\n                boolean second = eq(rightValue, true);\n                x.putAttribute(EVAL_VALUE, first && second);\n                break;\n            }\n            case BooleanOr: {\n                boolean first = eq(leftValue, true);\n                boolean second = eq(rightValue, true);\n                x.putAttribute(EVAL_VALUE, first || second);\n                break;\n            }\n            default:\n                break;\n        }\n\n        return false;\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    private static Object processValue(Object value) {\n        if (value instanceof List) {\n            List list = (List) value;\n            if (list.size() == 1) {\n                return processValue(list.get(0));\n            }\n        } else if (value instanceof Date) {\n            return ((Date) value).getTime();\n        }\n        return value;\n    }\n\n    private static boolean isAlwayTrueLikePattern(SQLExpr x) {\n        if (x instanceof SQLCharExpr) {\n            String text = ((SQLCharExpr) x).getText();\n\n            if (text.length() > 0) {\n                for (char ch : text.toCharArray()) {\n                    if (ch != '%') {\n                        return false;\n                    }\n                }\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLNumericLiteralExpr x) {\n        x.putAttribute(EVAL_VALUE, x.getNumber());\n        return false;\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLVariantRefExpr x) {\n        if (!\"?\".equals(x.getName())) {\n            return false;\n        }\n\n        Map<String, Object> attributes = x.getAttributes();\n\n        int varIndex = x.getIndex();\n\n        List<Object> parameters = visitor.getParameters();\n        if (varIndex != -1\n                && parameters != null\n                && parameters.size() > varIndex) {\n            boolean containsValue = attributes.containsKey(EVAL_VALUE);\n            if (!containsValue) {\n                Object value = parameters.get(varIndex);\n                if (value == null) {\n                    value = EVAL_VALUE_NULL;\n                }\n                attributes.put(EVAL_VALUE, value);\n            }\n        }\n\n        return false;\n    }\n\n    public static Boolean castToBoolean(Object val) {\n        if (val == null) {\n            return null;\n        }\n\n        if (val == EVAL_VALUE_NULL) {\n            return null;\n        }\n\n        if (val instanceof Boolean) {\n            return (Boolean) val;\n        }\n\n        if (val instanceof Number) {\n            return ((Number) val).intValue() > 0;\n        }\n\n        if (val instanceof String) {\n            if (\"1\".equals(val) || \"true\".equalsIgnoreCase((String) val)) {\n                return true;\n            }\n            if (\"0\".equals(val) || \"false\".equalsIgnoreCase((String) val)) {\n                return false;\n            }\n            return null;\n        }\n\n        throw new IllegalArgumentException(val.getClass() + \" not supported.\");\n    }\n\n    public static String castToString(Object val) {\n        Object value = val;\n\n        if (value == null) {\n            return null;\n        }\n\n        return value.toString();\n    }\n\n    public static Byte castToByte(Object val) {\n        if (val == null) {\n            return null;\n        }\n\n        if (val instanceof Byte) {\n            return (Byte) val;\n        }\n\n        if (val instanceof String) {\n            return Byte.parseByte((String) val);\n        }\n\n        return ((Number) val).byteValue();\n    }\n\n    public static Short castToShort(Object val) {\n        if (val == null || val == EVAL_VALUE_NULL) {\n            return null;\n        }\n\n        if (val instanceof Short) {\n            return (Short) val;\n        }\n\n        if (val instanceof String) {\n            return Short.parseShort((String) val);\n        }\n\n        return ((Number) val).shortValue();\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public static Integer castToInteger(Object val) {\n        if (val == null) {\n            return null;\n        }\n\n        if (val instanceof Integer) {\n            return (Integer) val;\n        }\n\n        if (val instanceof String) {\n            return Integer.parseInt((String) val);\n        }\n\n        if (val instanceof List) {\n            List list = (List) val;\n            if (list.size() == 1) {\n                return castToInteger(list.get(0));\n            }\n        }\n\n        if (val instanceof Boolean) {\n            if (((Boolean) val).booleanValue()) {\n                return 1;\n            } else {\n                return 0;\n            }\n        }\n\n        if (val instanceof Number) {\n            return ((Number) val).intValue();\n        }\n\n        throw new FastsqlException(\"cast error\");\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public static Long castToLong(Object val) {\n        if (val == null) {\n            return null;\n        }\n\n        if (val instanceof Long) {\n            return (Long) val;\n        }\n\n        if (val instanceof String) {\n            return Long.parseLong((String) val);\n        }\n\n        if (val instanceof List) {\n            List list = (List) val;\n            if (list.size() == 1) {\n                return castToLong(list.get(0));\n            }\n        }\n\n        if (val instanceof Boolean) {\n            if (((Boolean) val).booleanValue()) {\n                return 1L;\n            } else {\n                return 0L;\n            }\n        }\n\n        return ((Number) val).longValue();\n    }\n\n    public static Float castToFloat(Object val) {\n        if (val == null || val == EVAL_VALUE_NULL) {\n            return null;\n        }\n\n        if (val instanceof Float) {\n            return (Float) val;\n        }\n\n        return ((Number) val).floatValue();\n    }\n\n    public static Double castToDouble(Object val) {\n        if (val == null || val == EVAL_VALUE_NULL) {\n            return null;\n        }\n\n        if (val instanceof Double) {\n            return (Double) val;\n        }\n\n        return ((Number) val).doubleValue();\n    }\n\n    public static BigInteger castToBigInteger(Object val) {\n        if (val == null) {\n            return null;\n        }\n\n        if (val instanceof BigInteger) {\n            return (BigInteger) val;\n        }\n\n        if (val instanceof String) {\n            return new BigInteger((String) val);\n        }\n\n        return BigInteger.valueOf(((Number) val).longValue());\n    }\n\n    public static Number castToNumber(String val) {\n        if (val == null) {\n            return null;\n        }\n\n        try {\n            return Byte.parseByte(val);\n        } catch (NumberFormatException e) {\n        }\n\n        try {\n            return Short.parseShort(val);\n        } catch (NumberFormatException e) {\n        }\n\n        try {\n            return Integer.parseInt(val);\n        } catch (NumberFormatException e) {\n        }\n\n        try {\n            return Long.parseLong(val);\n        } catch (NumberFormatException e) {\n        }\n\n        try {\n            return Float.parseFloat(val);\n        } catch (NumberFormatException e) {\n        }\n\n        try {\n            return Double.parseDouble(val);\n        } catch (NumberFormatException e) {\n        }\n\n        try {\n            return new BigInteger(val);\n        } catch (NumberFormatException e) {\n        }\n\n        try {\n            return new BigDecimal(val);\n        } catch (NumberFormatException e) {\n            return 0;\n        }\n    }\n\n    public static Date castToDate(Object val) {\n        if (val == null) {\n            return null;\n        }\n\n        if (val instanceof Date) {\n            return (Date) val;\n        }\n\n        if (val instanceof Number) {\n            return new Date(((Number) val).longValue());\n        }\n\n        if (val instanceof String) {\n            return castToDate((String) val);\n        }\n\n        throw new FastsqlException(\"can cast to date\");\n    }\n\n    public static Date castToDate(String text) {\n        if (text == null || text.length() == 0) {\n            return null;\n        }\n\n        String format;\n\n        if (text.length() == \"yyyy-MM-dd\".length()) {\n            format = \"yyyy-MM-dd\";\n        } else {\n            format = \"yyyy-MM-dd HH:mm:ss\";\n        }\n\n        try {\n            return new SimpleDateFormat(format).parse(text);\n        } catch (ParseException e) {\n            throw new FastsqlException(\"rowFormat : \" + format + \", value : \" + text, e);\n        }\n    }\n\n    public static BigDecimal castToDecimal(Object val) {\n        if (val == null) {\n            return null;\n        }\n\n        if (val instanceof BigDecimal) {\n            return (BigDecimal) val;\n        }\n\n        if (val instanceof String) {\n            return new BigDecimal((String) val);\n        }\n\n        if (val instanceof Float) {\n            return BigDecimal.valueOf((Float) val);\n        }\n\n        if (val instanceof Double) {\n            return BigDecimal.valueOf((Double) val);\n        }\n\n        return BigDecimal.valueOf(((Number) val).longValue());\n    }\n\n    public static Object rightShift(Object a, Object b) {\n        if (a == null || b == null) {\n            return null;\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a).longValue() >> castToLong(b).longValue();\n        }\n\n        return castToInteger(a).intValue() >> castToInteger(b).intValue();\n    }\n\n    public static Object bitAnd(Object a, Object b) {\n        if (a == null || b == null) {\n            return null;\n        }\n\n        if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) {\n            return null;\n        }\n\n        if (a instanceof String) {\n            a = castToNumber((String) a);\n        }\n\n        if (b instanceof String) {\n            b = castToNumber((String) b);\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a).longValue() & castToLong(b).longValue();\n        }\n\n        return castToInteger(a).intValue() & castToInteger(b).intValue();\n    }\n\n    public static Object bitOr(Object a, Object b) {\n        if (a == null || b == null) {\n            return null;\n        }\n\n        if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) {\n            return null;\n        }\n\n        if (a instanceof String) {\n            a = castToNumber((String) a);\n        }\n\n        if (b instanceof String) {\n            b = castToNumber((String) b);\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a).longValue() | castToLong(b).longValue();\n        }\n\n        return castToInteger(a).intValue() | castToInteger(b).intValue();\n    }\n\n    public static Object div(Object a, Object b) {\n        if (a == null || b == null) {\n            return null;\n        }\n\n        if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) {\n            return null;\n        }\n\n        if (a instanceof String) {\n            a = castToNumber((String) a);\n        }\n\n        if (b instanceof String) {\n            b = castToNumber((String) b);\n        }\n\n        if (a instanceof BigDecimal || b instanceof BigDecimal) {\n            BigDecimal decimalA = castToDecimal(a);\n            BigDecimal decimalB = castToDecimal(b);\n            if (decimalB.scale() < decimalA.scale()) {\n                decimalB = decimalB.setScale(decimalA.scale());\n            }\n            try {\n                return decimalA.divide(decimalB);\n            } catch (ArithmeticException ex) {\n                return decimalA.divide(decimalB, BigDecimal.ROUND_HALF_UP);\n            }\n        }\n\n        if (a instanceof Double || b instanceof Double) {\n            Double doubleA = castToDouble(a);\n            Double doubleB = castToDouble(b);\n            if (doubleA == null || doubleB == null) {\n                return null;\n            }\n            return doubleA / doubleB;\n        }\n\n        if (a instanceof Float || b instanceof Float) {\n            Float floatA = castToFloat(a);\n            Float floatB = castToFloat(b);\n            if (floatA == null || floatB == null) {\n                return null;\n            }\n            return floatA / floatB;\n        }\n\n        if (a instanceof BigInteger || b instanceof BigInteger) {\n            return castToBigInteger(a).divide(castToBigInteger(b));\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            Long longA = castToLong(a);\n            Long longB = castToLong(b);\n            if (longB == 0) {\n                if (longA > 0) {\n                    return Double.POSITIVE_INFINITY;\n                } else if (longA < 0) {\n                    return Double.NEGATIVE_INFINITY;\n                } else {\n                    return Double.NaN;\n                }\n            }\n            return longA / longB;\n        }\n\n        if (a instanceof Integer || b instanceof Integer) {\n            Integer intA = castToInteger(a);\n            Integer intB = castToInteger(b);\n            if (intB == 0) {\n                if (intA > 0) {\n                    return Double.POSITIVE_INFINITY;\n                } else if (intA < 0) {\n                    return Double.NEGATIVE_INFINITY;\n                } else {\n                    return Double.NaN;\n                }\n            }\n            return intA / intB;\n        }\n\n        if (a instanceof Short || b instanceof Short) {\n            return castToShort(a) / castToShort(b);\n        }\n\n        if (a instanceof Byte || b instanceof Byte) {\n            return castToByte(a) / castToByte(b);\n        }\n\n        throw new IllegalArgumentException(a.getClass() + \" and \" + b.getClass() + \" not supported.\");\n    }\n\n    public static boolean gt(Object a, Object b) {\n        if (a == null || a == EVAL_VALUE_NULL) {\n            return false;\n        }\n\n        if (b == null || b == EVAL_VALUE_NULL) {\n            return true;\n        }\n\n        if (a instanceof String || b instanceof String) {\n            return castToString(a).compareTo(castToString(b)) > 0;\n        }\n\n        if (a instanceof BigDecimal || b instanceof BigDecimal) {\n            return castToDecimal(a).compareTo(castToDecimal(b)) > 0;\n        }\n\n        if (a instanceof BigInteger || b instanceof BigInteger) {\n            return castToBigInteger(a).compareTo(castToBigInteger(b)) > 0;\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a) > castToLong(b);\n        }\n\n        if (a instanceof Integer || b instanceof Integer) {\n            return castToInteger(a) > castToInteger(b);\n        }\n\n        if (a instanceof Short || b instanceof Short) {\n            return castToShort(a) > castToShort(b);\n        }\n\n        if (a instanceof Byte || b instanceof Byte) {\n            return castToByte(a) > castToByte(b);\n        }\n\n        if (a instanceof Date || b instanceof Date) {\n            Date d1 = castToDate(a);\n            Date d2 = castToDate(b);\n\n            if (d1 == d2) {\n                return false;\n            }\n\n            if (d1 == null) {\n                return false;\n            }\n\n            if (d2 == null) {\n                return true;\n            }\n\n            return d1.compareTo(d2) > 0;\n        }\n\n        throw new IllegalArgumentException(a.getClass() + \" and \" + b.getClass() + \" not supported.\");\n    }\n\n    public static boolean gteq(Object a, Object b) {\n        if (eq(a, b)) {\n            return true;\n        }\n\n        return gt(a, b);\n    }\n\n    public static boolean lt(Object a, Object b) {\n        if (a == null) {\n            return true;\n        }\n\n        if (b == null) {\n            return false;\n        }\n\n        if (a instanceof String || b instanceof String) {\n            return (castToString(a)).compareTo(castToString(b)) < 0;\n        }\n\n        if (a instanceof BigDecimal || b instanceof BigDecimal) {\n            return castToDecimal(a).compareTo(castToDecimal(b)) < 0;\n        }\n\n        if (a instanceof BigInteger || b instanceof BigInteger) {\n            return castToBigInteger(a).compareTo(castToBigInteger(b)) < 0;\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a) < castToLong(b);\n        }\n\n        if (a instanceof Integer || b instanceof Integer) {\n            Integer intA = castToInteger(a);\n            Integer intB = castToInteger(b);\n            return intA < intB;\n        }\n\n        if (a instanceof Short || b instanceof Short) {\n            return castToShort(a) < castToShort(b);\n        }\n\n        if (a instanceof Byte || b instanceof Byte) {\n            return castToByte(a) < castToByte(b);\n        }\n\n        if (a instanceof Date || b instanceof Date) {\n            Date d1 = castToDate(a);\n            Date d2 = castToDate(b);\n\n            if (d1 == d2) {\n                return false;\n            }\n\n            if (d1 == null) {\n                return true;\n            }\n\n            if (d2 == null) {\n                return false;\n            }\n\n            return d1.compareTo(d2) < 0;\n        }\n\n        throw new IllegalArgumentException(a.getClass() + \" and \" + b.getClass() + \" not supported.\");\n    }\n\n    public static boolean lteq(Object a, Object b) {\n        if (eq(a, b)) {\n            return true;\n        }\n\n        return lt(a, b);\n    }\n\n    public static boolean eq(Object a, Object b) {\n        if (a == b) {\n            return true;\n        }\n\n        if (a == null || b == null) {\n            return false;\n        }\n\n        if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) {\n            return false;\n        }\n\n        if (a.equals(b)) {\n            return true;\n        }\n\n        if (a instanceof String || b instanceof String) {\n            return castToString(a).equals(castToString(b));\n        }\n\n        if (a instanceof BigDecimal || b instanceof BigDecimal) {\n            return castToDecimal(a).compareTo(castToDecimal(b)) == 0;\n        }\n\n        if (a instanceof BigInteger || b instanceof BigInteger) {\n            return castToBigInteger(a).compareTo(castToBigInteger(b)) == 0;\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a).equals(castToLong(b));\n        }\n\n        if (a instanceof Integer || b instanceof Integer) {\n            Integer inta = castToInteger(a);\n            Integer intb = castToInteger(b);\n            if (inta == null || intb == null) {\n                return false;\n            }\n            return inta.equals(intb);\n        }\n\n        if (a instanceof Short || b instanceof Short) {\n            return castToShort(a).equals(castToShort(b));\n        }\n\n        if (a instanceof Boolean || b instanceof Boolean) {\n            return castToBoolean(a).equals(castToBoolean(b));\n        }\n\n        if (a instanceof Byte || b instanceof Byte) {\n            return castToByte(a).equals(castToByte(b));\n        }\n\n        if (a instanceof Date || b instanceof Date) {\n            Date d1 = castToDate(a);\n            Date d2 = castToDate(b);\n\n            if (d1 == d2) {\n                return true;\n            }\n\n            if (d1 == null || d2 == null) {\n                return false;\n            }\n\n            return d1.equals(d2);\n        }\n\n        throw new IllegalArgumentException(a.getClass() + \" and \" + b.getClass() + \" not supported.\");\n    }\n\n    public static Object add(Object a, Object b) {\n        if (a == null) {\n            return b;\n        }\n\n        if (b == null) {\n            return a;\n        }\n\n        if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) {\n            return EVAL_VALUE_NULL;\n        }\n\n        if (a instanceof String && !(b instanceof String)) {\n            a = castToNumber((String) a);\n        }\n\n        if (b instanceof String && !(a instanceof String)) {\n            b = castToNumber((String) b);\n        }\n\n        if (a instanceof BigDecimal || b instanceof BigDecimal) {\n            return castToDecimal(a).add(castToDecimal(b));\n        }\n\n        if (a instanceof BigInteger || b instanceof BigInteger) {\n            return castToBigInteger(a).add(castToBigInteger(b));\n        }\n\n        if (a instanceof Double || b instanceof Double) {\n            return castToDouble(a) + castToDouble(b);\n        }\n\n        if (a instanceof Float || b instanceof Float) {\n            return castToFloat(a) + castToFloat(b);\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a) + castToLong(b);\n        }\n\n        if (a instanceof Integer || b instanceof Integer) {\n            return castToInteger(a) + castToInteger(b);\n        }\n\n        if (a instanceof Short || b instanceof Short) {\n            return castToShort(a) + castToShort(b);\n        }\n\n        if (a instanceof Boolean || b instanceof Boolean) {\n            int aI = 0, bI = 0;\n            if (castToBoolean(a)) {\n                aI = 1;\n            }\n            if (castToBoolean(b)) {\n                bI = 1;\n            }\n            return aI + bI;\n        }\n\n        if (a instanceof Byte || b instanceof Byte) {\n            return castToByte(a) + castToByte(b);\n        }\n\n        if (a instanceof String && b instanceof String) {\n            return castToString(a) + castToString(b);\n        }\n\n        throw new IllegalArgumentException(a.getClass() + \" and \" + b.getClass() + \" not supported.\");\n    }\n\n    public static Object sub(Object a, Object b) {\n        if (a == null) {\n            return null;\n        }\n\n        if (b == null) {\n            return a;\n        }\n\n        if (a == EVAL_VALUE_NULL || b == EVAL_VALUE_NULL) {\n            return EVAL_VALUE_NULL;\n        }\n\n        if (a instanceof Date || b instanceof Date) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        if (a instanceof String) {\n            a = castToNumber((String) a);\n        }\n\n        if (b instanceof String) {\n            b = castToNumber((String) b);\n        }\n\n        if (a instanceof BigDecimal || b instanceof BigDecimal) {\n            return castToDecimal(a).subtract(castToDecimal(b));\n        }\n\n        if (a instanceof BigInteger || b instanceof BigInteger) {\n            return castToBigInteger(a).subtract(castToBigInteger(b));\n        }\n\n        if (a instanceof Double || b instanceof Double) {\n            return castToDouble(a) - castToDouble(b);\n        }\n\n        if (a instanceof Float || b instanceof Float) {\n            return castToFloat(a) - castToFloat(b);\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a) - castToLong(b);\n        }\n\n        if (a instanceof Integer || b instanceof Integer) {\n            return castToInteger(a) - castToInteger(b);\n        }\n\n        if (a instanceof Short || b instanceof Short) {\n            return castToShort(a) - castToShort(b);\n        }\n\n        if (a instanceof Boolean || b instanceof Boolean) {\n            int aI = 0, bI = 0;\n            if (castToBoolean(a)) {\n                aI = 1;\n            }\n            if (castToBoolean(b)) {\n                bI = 1;\n            }\n            return aI - bI;\n        }\n\n        if (a instanceof Byte || b instanceof Byte) {\n            return castToByte(a) - castToByte(b);\n        }\n\n        // return SQLEvalVisitor.EVAL_ERROR;\n        throw new IllegalArgumentException(a.getClass() + \" and \" + b.getClass() + \" not supported.\");\n    }\n\n    public static Object multi(Object a, Object b) {\n        if (a == null || b == null) {\n            return null;\n        }\n\n        if (a instanceof String) {\n            a = castToNumber((String) a);\n        }\n\n        if (b instanceof String) {\n            b = castToNumber((String) b);\n        }\n\n        if (a instanceof BigDecimal || b instanceof BigDecimal) {\n            return castToDecimal(a).multiply(castToDecimal(b));\n        }\n\n        if (a instanceof BigInteger || b instanceof BigInteger) {\n            return castToBigInteger(a).multiply(castToBigInteger(b));\n        }\n\n        if (a instanceof Double || b instanceof Double) {\n            return castToDouble(a) * castToDouble(b);\n        }\n\n        if (a instanceof Float || b instanceof Float) {\n            return castToFloat(a) * castToFloat(b);\n        }\n\n        if (a instanceof Long || b instanceof Long) {\n            return castToLong(a) * castToLong(b);\n        }\n\n        if (a instanceof Integer || b instanceof Integer) {\n            return castToInteger(a) * castToInteger(b);\n        }\n\n        if (a instanceof Short || b instanceof Short) {\n            Short shortA = castToShort(a);\n            Short shortB = castToShort(b);\n\n            if (shortA == null || shortB == null) {\n                return null;\n            }\n\n            return shortA * shortB;\n        }\n\n        if (a instanceof Byte || b instanceof Byte) {\n            return castToByte(a) * castToByte(b);\n        }\n\n        throw new IllegalArgumentException(a.getClass() + \" and \" + b.getClass() + \" not supported.\");\n    }\n\n    public static boolean like(String input, String pattern) {\n        if (pattern == null) {\n            throw new IllegalArgumentException(\"pattern is null\");\n        }\n\n        StringBuilder regexprBuilder = new StringBuilder(pattern.length() + 4);\n\n        final int STAT_NOTSET = 0;\n        final int STAT_RANGE = 1;\n        final int STAT_LITERAL = 2;\n\n        int stat = STAT_NOTSET;\n\n        int blockStart = -1;\n        for (int i = 0; i < pattern.length(); ++i) {\n            char ch = pattern.charAt(i);\n\n            if (stat == STAT_LITERAL //\n                    && (ch == '%' || ch == '_' || ch == '[')) {\n                String block = pattern.substring(blockStart, i);\n                regexprBuilder.append(\"\\\\Q\");\n                regexprBuilder.append(block);\n                regexprBuilder.append(\"\\\\E\");\n                blockStart = -1;\n                stat = STAT_NOTSET;\n            }\n\n            if (ch == '%') {\n                regexprBuilder.append(\".*\");\n            } else if (ch == '_') {\n                regexprBuilder.append('.');\n            } else if (ch == '[') {\n                if (stat == STAT_RANGE) {\n                    throw new IllegalArgumentException(\"illegal pattern : \" + pattern);\n                }\n                stat = STAT_RANGE;\n                blockStart = i;\n            } else if (ch == ']') {\n                if (stat != STAT_RANGE) {\n                    throw new IllegalArgumentException(\"illegal pattern : \" + pattern);\n                }\n                String block = pattern.substring(blockStart, i + 1);\n                regexprBuilder.append(block);\n\n                blockStart = -1;\n            } else {\n                if (stat == STAT_NOTSET) {\n                    stat = STAT_LITERAL;\n                    blockStart = i;\n                }\n\n                if (stat == STAT_LITERAL && i == pattern.length() - 1) {\n                    String block = pattern.substring(blockStart, i + 1);\n                    regexprBuilder.append(\"\\\\Q\");\n                    regexprBuilder.append(block);\n                    regexprBuilder.append(\"\\\\E\");\n                }\n            }\n        }\n        if (\"%\".equals(pattern) || \"%%\".equals(pattern)) {\n            return true;\n        }\n\n        String regexpr = regexprBuilder.toString();\n        return Pattern.matches(regexpr, input);\n    }\n\n    public static boolean visit(SQLEvalVisitor visitor, SQLIdentifierExpr x) {\n        x.putAttribute(EVAL_EXPR, x);\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLSubQueryGroupVisitor.java",
    "content": "package com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.*;\n\npublic class SQLSubQueryGroupVisitor extends SQLASTVisitorAdapter {\n    private final DbType dbType;\n\n    protected Map<Long, List<SQLSubqueryTableSource>> tableSourceMap = new LinkedHashMap<Long, List<SQLSubqueryTableSource>>();\n\n    public SQLSubQueryGroupVisitor(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public boolean visit(SQLSubqueryTableSource x) {\n        String sql = SQLUtils.toSQLString(x.getSelect(), dbType);\n        long hashCode64 = FnvHash.fnv1a_64(sql);\n        List<SQLSubqueryTableSource> list = tableSourceMap.get(hashCode64);\n        if (list == null) {\n            list = new ArrayList<SQLSubqueryTableSource>();\n            tableSourceMap.put(hashCode64, list);\n        }\n        list.add(x);\n\n        return true;\n    }\n\n    public Collection<List<SQLSubqueryTableSource>> getGroupedSubqueryTableSources() {\n        return tableSourceMap.values();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLTableAliasCollectVisitor.java",
    "content": "package com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.Collection;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class SQLTableAliasCollectVisitor extends SQLASTVisitorAdapter {\n    protected Map<Long, SQLTableSource> tableSourceMap = new LinkedHashMap<Long, SQLTableSource>();\n    protected volatile int seed;\n\n    public boolean visit(SQLLateralViewTableSource x) {\n        String alias = x.getAlias();\n        if (alias == null) {\n            return false;\n        }\n\n        long hashCode64 = FnvHash.hashCode64(alias);\n        tableSourceMap.put(hashCode64, x);\n        return true;\n    }\n\n    public boolean visit(SQLValuesTableSource x) {\n        String alias = x.getAlias();\n        if (alias == null) {\n            return false;\n        }\n\n        long hashCode64 = FnvHash.hashCode64(alias);\n        tableSourceMap.put(hashCode64, x);\n        return true;\n    }\n\n    public boolean visit(SQLUnionQueryTableSource x) {\n        String alias = x.getAlias();\n        if (alias == null) {\n            x.getUnion().accept(this);\n            return false;\n        }\n\n        long hashCode64 = FnvHash.hashCode64(alias);\n        tableSourceMap.put(hashCode64, x);\n        return true;\n    }\n\n    public boolean visit(SQLSubqueryTableSource x) {\n        String alias = x.getAlias();\n        if (alias == null) {\n            x.getSelect().accept(this);\n            return false;\n        }\n\n        long hashCode64 = FnvHash.hashCode64(alias);\n        tableSourceMap.put(hashCode64, x);\n        return true;\n    }\n\n    public boolean visit(SQLJoinTableSource x) {\n        String alias = x.getAlias();\n        if (alias == null) {\n            return true;\n        }\n        long hashCode64 = FnvHash.hashCode64(alias);\n        tableSourceMap.put(hashCode64, x);\n        return true;\n    }\n\n    public boolean visit(SQLWithSubqueryClause.Entry x) {\n        String alias = x.getAlias();\n        if (alias == null) {\n            return true;\n        }\n        long hashCode64 = FnvHash.hashCode64(alias);\n        tableSourceMap.put(hashCode64, x);\n        return true;\n    }\n\n    public boolean visit(SQLExprTableSource x) {\n        String alias = x.getAlias();\n\n        if (alias == null) {\n            SQLExpr expr = x.getExpr();\n            if (expr instanceof SQLName) {\n                long hashCode64 = ((SQLName) expr).nameHashCode64();\n                tableSourceMap.put(hashCode64, x);\n                return false;\n            }\n            return true;\n        }\n\n        return true;\n    }\n\n    public Collection<SQLTableSource> getTableSources() {\n        return tableSourceMap.values();\n    }\n\n    public SQLTableSource getTableSource(long hashCode64) {\n        return tableSourceMap.get(hashCode64);\n    }\n\n    public boolean containsTableSource(String alias) {\n        if (alias == null) {\n            return false;\n        }\n        long hashCode64 = FnvHash.hashCode64(alias);\n        return tableSourceMap.containsKey(hashCode64);\n    }\n\n    public String genAlias(int seed) {\n        String alias = null;\n        for (; seed < 100; ) {\n            String str = \"G\" + (seed++);\n            if (!containsTableSource(str)) {\n                alias = str;\n                this.seed = seed;\n                break;\n            }\n        }\n        return alias;\n    }\n\n    public int getSeed() {\n        return seed;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SQLTransformVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\n/**\n * Created by wenshao on 16/07/2017.\n */\npublic interface SQLTransformVisitor extends SQLASTVisitor {\n    String getSrcDbType();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExpr;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter;\nimport com.alibaba.druid.sql.repository.SchemaObject;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.stat.TableStat.Condition;\nimport com.alibaba.druid.stat.TableStat.Mode;\nimport com.alibaba.druid.stat.TableStat.Relationship;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.*;\n\npublic class SchemaStatVisitor extends SQLASTVisitorAdapter {\n    protected SchemaRepository repository;\n\n    protected final List<SQLName> originalTables = new ArrayList<SQLName>();\n\n    protected final HashMap<TableStat.Name, TableStat> tableStats = new LinkedHashMap<TableStat.Name, TableStat>();\n    protected final Map<Long, Column> columns = new LinkedHashMap<Long, Column>();\n    protected final List<Condition> conditions = new ArrayList<Condition>();\n    protected final Set<Relationship> relationships = new LinkedHashSet<Relationship>();\n    protected final List<Column> orderByColumns = new ArrayList<Column>();\n    protected final Set<Column> groupByColumns = new LinkedHashSet<Column>();\n    protected final List<SQLAggregateExpr> aggregateFunctions = new ArrayList<SQLAggregateExpr>();\n    protected final List<SQLMethodInvokeExpr> functions = new ArrayList<SQLMethodInvokeExpr>(2);\n\n    private List<Object> parameters;\n\n    private Mode mode;\n\n    protected DbType dbType;\n\n    public SchemaStatVisitor() {\n        this((DbType) null);\n    }\n\n    public SchemaStatVisitor(SchemaRepository repository) {\n        if (repository != null) {\n            this.dbType = repository.getDbType();\n        }\n        this.repository = repository;\n    }\n\n    public SchemaStatVisitor(DbType dbType) {\n        this(new SchemaRepository(dbType), new ArrayList<Object>());\n        this.dbType = dbType;\n    }\n\n    public SchemaStatVisitor(List<Object> parameters) {\n        this((DbType) null, parameters);\n    }\n\n    public SchemaStatVisitor(DbType dbType, List<Object> parameters) {\n        this(new SchemaRepository(dbType), parameters);\n        this.parameters = parameters;\n    }\n\n    public SchemaStatVisitor(SchemaRepository repository, List<Object> parameters) {\n        this.repository = repository;\n        this.parameters = parameters;\n        if (repository != null) {\n            DbType dbType = repository.getDbType();\n            if (dbType != null && this.dbType == null) {\n                this.dbType = dbType;\n            }\n        }\n    }\n\n    public SchemaRepository getRepository() {\n        return repository;\n    }\n\n    public void setRepository(SchemaRepository repository) {\n        this.repository = repository;\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    public void setParameters(List<Object> parameters) {\n        this.parameters = parameters;\n    }\n\n    public TableStat getTableStat(String tableName) {\n        tableName = handleName(tableName);\n\n        TableStat.Name tableNameObj = new TableStat.Name(tableName);\n        TableStat stat = tableStats.get(tableNameObj);\n        if (stat == null) {\n            stat = new TableStat();\n            tableStats.put(new TableStat.Name(tableName), stat);\n        }\n        return stat;\n    }\n\n    public TableStat getTableStat(SQLName tableName) {\n        String strName;\n        if (tableName instanceof SQLIdentifierExpr) {\n            strName = ((SQLIdentifierExpr) tableName).normalizedName();\n        } else if (tableName instanceof SQLPropertyExpr) {\n            strName = ((SQLPropertyExpr) tableName).normalizedName();\n        } else {\n            strName = tableName.toString();\n        }\n\n        long hashCode64 = tableName.hashCode64();\n\n        if (hashCode64 == FnvHash.Constants.DUAL) {\n            return null;\n        }\n\n        originalTables.add(tableName);\n\n        TableStat.Name tableNameObj = new TableStat.Name(strName, hashCode64);\n        TableStat stat = tableStats.get(tableNameObj);\n        if (stat == null) {\n            stat = new TableStat();\n            tableStats.put(new TableStat.Name(strName, hashCode64), stat);\n        }\n        return stat;\n    }\n\n    protected Column addColumn(String tableName, String columnName) {\n        Column c = new Column(tableName, columnName, dbType);\n\n        Column column = this.columns.get(c.hashCode64());\n        if (column == null && columnName != null) {\n            column = c;\n            columns.put(c.hashCode64(), c);\n        }\n        return column;\n    }\n\n    protected Column addColumn(SQLName table, String columnName) {\n        String tableName;\n        if (table instanceof SQLIdentifierExpr) {\n            tableName = ((SQLIdentifierExpr) table).normalizedName();\n        } else if (table instanceof SQLPropertyExpr) {\n            tableName = ((SQLPropertyExpr) table).normalizedName();\n        } else {\n            tableName = table.toString();\n        }\n\n        long tableHashCode64 = table.hashCode64();\n\n        long basic = tableHashCode64;\n        basic ^= '.';\n        basic *= FnvHash.PRIME;\n        long columnHashCode64 = FnvHash.hashCode64(basic, columnName);\n\n        Column column = this.columns.get(columnHashCode64);\n        if (column == null && columnName != null) {\n            column = new Column(tableName, columnName, columnHashCode64);\n            columns.put(columnHashCode64, column);\n        }\n        return column;\n    }\n\n    private String handleName(String ident) {\n        int len = ident.length();\n        if (ident.charAt(0) == '[' && ident.charAt(len - 1) == ']') {\n            ident = ident.substring(1, len - 1);\n        } else {\n            boolean flag0 = false;\n            boolean flag1 = false;\n            boolean flag2 = false;\n            boolean flag3 = false;\n            for (int i = 0; i < len; ++i) {\n                final char ch = ident.charAt(i);\n                if (ch == '\\\"') {\n                    flag0 = true;\n                } else if (ch == '`') {\n                    flag1 = true;\n                } else if (ch == ' ') {\n                    flag2 = true;\n                } else if (ch == '\\'') {\n                    flag3 = true;\n                }\n            }\n            if (flag0) {\n                ident = ident.replaceAll(\"\\\"\", \"\");\n            }\n\n            if (flag1) {\n                ident = ident.replaceAll(\"`\", \"\");\n            }\n\n            if (flag2) {\n                ident = ident.replaceAll(\" \", \"\");\n            }\n\n            if (flag3) {\n                ident = ident.replaceAll(\"'\", \"\");\n            }\n        }\n        return ident;\n    }\n\n    protected Mode getMode() {\n        return mode;\n    }\n\n    protected void setModeOrigin(SQLObject x) {\n        Mode originalMode = (Mode) x.getAttribute(\"_original_use_mode\");\n        mode = originalMode;\n    }\n\n    protected Mode setMode(SQLObject x, Mode mode) {\n        Mode oldMode = this.mode;\n        x.putAttribute(\"_original_use_mode\", oldMode);\n        this.mode = mode;\n        return oldMode;\n    }\n\n    private boolean visitOrderBy(SQLIdentifierExpr x) {\n        SQLTableSource tableSource = x.getResolvedTableSource();\n\n        if (tableSource == null\n                && x.getParent() instanceof SQLSelectOrderByItem\n                && x.getParent().getParent() instanceof SQLOrderBy\n                && x.getParent().getParent().getParent() instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x.getParent().getParent().getParent();\n            SQLSelectItem selectItem = queryBlock.findSelectItem(x.nameHashCode64());\n            if (selectItem != null) {\n                SQLExpr selectItemExpr = selectItem.getExpr();\n                if (selectItemExpr instanceof SQLIdentifierExpr) {\n                    x = (SQLIdentifierExpr) selectItemExpr;\n                } else if (selectItemExpr instanceof SQLPropertyExpr) {\n                    return visitOrderBy((SQLPropertyExpr) selectItemExpr);\n                } else {\n                    return false;\n                }\n            }\n        }\n\n        String tableName = null;\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr table = (SQLIdentifierExpr) expr;\n                tableName = table.getName();\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr table = (SQLPropertyExpr) expr;\n                tableName = table.toString();\n            } else if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;\n                if (\"table\".equalsIgnoreCase(methodInvokeExpr.getMethodName())\n                        && methodInvokeExpr.getArguments().size() == 1\n                        && methodInvokeExpr.getArguments().get(0) instanceof SQLName) {\n                    SQLName table = (SQLName) methodInvokeExpr.getArguments().get(0);\n\n                    if (table instanceof SQLPropertyExpr) {\n                        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) table;\n                        SQLIdentifierExpr owner = (SQLIdentifierExpr) propertyExpr.getOwner();\n                        if (propertyExpr.getResolvedTableSource() != null\n                                && propertyExpr.getResolvedTableSource() instanceof SQLExprTableSource) {\n                            SQLExpr resolveExpr = ((SQLExprTableSource) propertyExpr.getResolvedTableSource()).getExpr();\n                            if (resolveExpr instanceof SQLName) {\n                                tableName = resolveExpr.toString() + \".\" + propertyExpr.getName();\n                            }\n                        }\n                    }\n\n                    if (tableName == null) {\n                        tableName = table.toString();\n                    }\n                }\n            }\n        } else if (tableSource instanceof SQLWithSubqueryClause.Entry) {\n            return false;\n        } else if (tableSource instanceof SQLSubqueryTableSource) {\n            SQLSelectQueryBlock queryBlock = ((SQLSubqueryTableSource) tableSource).getSelect().getQueryBlock();\n            if (queryBlock == null) {\n                return false;\n            }\n\n            SQLSelectItem selectItem = queryBlock.findSelectItem(x.nameHashCode64());\n            if (selectItem == null) {\n                return false;\n            }\n\n            SQLExpr selectItemExpr = selectItem.getExpr();\n            SQLTableSource columnTableSource = null;\n            if (selectItemExpr instanceof SQLIdentifierExpr) {\n                columnTableSource = ((SQLIdentifierExpr) selectItemExpr).getResolvedTableSource();\n            } else if (selectItemExpr instanceof SQLPropertyExpr) {\n                columnTableSource = ((SQLPropertyExpr) selectItemExpr).getResolvedTableSource();\n            }\n\n            if (columnTableSource instanceof SQLExprTableSource && ((SQLExprTableSource) columnTableSource).getExpr() instanceof SQLName) {\n                SQLName tableExpr = (SQLName) ((SQLExprTableSource) columnTableSource).getExpr();\n                if (tableExpr instanceof SQLIdentifierExpr) {\n                    tableName = ((SQLIdentifierExpr) tableExpr).normalizedName();\n                } else if (tableExpr instanceof SQLPropertyExpr) {\n                    tableName = ((SQLPropertyExpr) tableExpr).normalizedName();\n                }\n            }\n        } else {\n            boolean skip = false;\n            for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n                if (parent instanceof SQLSelectQueryBlock) {\n                    SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom();\n\n                    if (from instanceof SQLValuesTableSource) {\n                        skip = true;\n                        break;\n                    }\n                } else if (parent instanceof SQLSelectQuery) {\n                    break;\n                }\n            }\n        }\n\n        String identName = x.getName();\n        if (tableName != null) {\n            orderByAddColumn(tableName, identName, x);\n        } else {\n            orderByAddColumn(\"UNKNOWN\", identName, x);\n        }\n        return false;\n    }\n\n    private boolean visitOrderBy(SQLPropertyExpr x) {\n        if (isSubQueryOrParamOrVariant(x)) {\n            return false;\n        }\n\n        String owner = null;\n\n        SQLTableSource tableSource = x.getResolvedTableSource();\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr tableSourceExpr = ((SQLExprTableSource) tableSource).getExpr();\n            if (tableSourceExpr instanceof SQLName) {\n                owner = tableSourceExpr.toString();\n            }\n        }\n\n        if (owner == null && x.getOwner() instanceof SQLIdentifierExpr) {\n            owner = ((SQLIdentifierExpr) x.getOwner()).getName();\n        }\n\n        if (owner == null) {\n            return false;\n        }\n\n        orderByAddColumn(owner, x.getName(), x);\n\n        return false;\n    }\n\n    private boolean visitOrderBy(SQLIntegerExpr x) {\n        SQLObject parent = x.getParent();\n        if (!(parent instanceof SQLSelectOrderByItem)) {\n            return false;\n        }\n\n        if (parent.getParent() instanceof SQLSelectQueryBlock) {\n            int selectItemIndex = x.getNumber().intValue() - 1;\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent.getParent();\n            final List<SQLSelectItem> selectList = queryBlock.getSelectList();\n\n            if (selectItemIndex < 0 || selectItemIndex >= selectList.size()) {\n                return false;\n            }\n\n            SQLExpr selectItemExpr = selectList.get(selectItemIndex).getExpr();\n            if (selectItemExpr instanceof SQLIdentifierExpr) {\n                visitOrderBy((SQLIdentifierExpr) selectItemExpr);\n            } else if (selectItemExpr instanceof SQLPropertyExpr) {\n                visitOrderBy((SQLPropertyExpr) selectItemExpr);\n            }\n        }\n\n        return false;\n    }\n\n    private void orderByAddColumn(String table, String columnName, SQLObject expr) {\n        Column column = new Column(table, columnName, dbType);\n\n        SQLObject parent = expr.getParent();\n        if (parent instanceof SQLSelectOrderByItem) {\n            SQLOrderingSpecification type = ((SQLSelectOrderByItem) parent).getType();\n            column.getAttributes().put(\"orderBy.type\", type);\n        }\n\n        orderByColumns.add(column);\n    }\n\n    protected class OrderByStatVisitor extends SQLASTVisitorAdapter {\n        private final SQLOrderBy orderBy;\n\n        public OrderByStatVisitor(SQLOrderBy orderBy) {\n            this.orderBy = orderBy;\n            for (SQLSelectOrderByItem item : orderBy.getItems()) {\n                item.getExpr().setParent(item);\n            }\n        }\n\n        public SQLOrderBy getOrderBy() {\n            return orderBy;\n        }\n\n        public boolean visit(SQLIdentifierExpr x) {\n            return visitOrderBy(x);\n        }\n\n        public boolean visit(SQLPropertyExpr x) {\n            return visitOrderBy(x);\n        }\n\n        public boolean visit(SQLIntegerExpr x) {\n            return visitOrderBy(x);\n        }\n    }\n\n    protected class MySqlOrderByStatVisitor extends MySqlASTVisitorAdapter {\n        private final SQLOrderBy orderBy;\n\n        public MySqlOrderByStatVisitor(SQLOrderBy orderBy) {\n            this.orderBy = orderBy;\n            for (SQLSelectOrderByItem item : orderBy.getItems()) {\n                item.getExpr().setParent(item);\n            }\n        }\n\n        public SQLOrderBy getOrderBy() {\n            return orderBy;\n        }\n\n        public boolean visit(SQLIdentifierExpr x) {\n            return visitOrderBy(x);\n        }\n\n        public boolean visit(SQLPropertyExpr x) {\n            return visitOrderBy(x);\n        }\n\n        public boolean visit(SQLIntegerExpr x) {\n            return visitOrderBy(x);\n        }\n    }\n\n    protected class PGOrderByStatVisitor extends PGASTVisitorAdapter {\n        private final SQLOrderBy orderBy;\n\n        public PGOrderByStatVisitor(SQLOrderBy orderBy) {\n            this.orderBy = orderBy;\n            for (SQLSelectOrderByItem item : orderBy.getItems()) {\n                item.getExpr().setParent(item);\n            }\n        }\n\n        public SQLOrderBy getOrderBy() {\n            return orderBy;\n        }\n\n        public boolean visit(SQLIdentifierExpr x) {\n            return visitOrderBy(x);\n        }\n\n        public boolean visit(SQLPropertyExpr x) {\n            return visitOrderBy(x);\n        }\n\n        public boolean visit(SQLIntegerExpr x) {\n            return visitOrderBy(x);\n        }\n    }\n\n    protected class OracleOrderByStatVisitor extends OracleASTVisitorAdapter {\n        private final SQLOrderBy orderBy;\n\n        public OracleOrderByStatVisitor(SQLOrderBy orderBy) {\n            this.orderBy = orderBy;\n            for (SQLSelectOrderByItem item : orderBy.getItems()) {\n                item.getExpr().setParent(item);\n            }\n        }\n\n        public SQLOrderBy getOrderBy() {\n            return orderBy;\n        }\n\n        public boolean visit(SQLIdentifierExpr x) {\n            return visitOrderBy(x);\n        }\n\n        public boolean visit(SQLPropertyExpr x) {\n            SQLExpr unwrapped = unwrapExpr(x);\n            if (unwrapped instanceof SQLPropertyExpr) {\n                visitOrderBy((SQLPropertyExpr) unwrapped);\n            } else if (unwrapped instanceof SQLIdentifierExpr) {\n                visitOrderBy((SQLIdentifierExpr) unwrapped);\n            }\n            return false;\n        }\n\n        public boolean visit(SQLIntegerExpr x) {\n            return visitOrderBy(x);\n        }\n    }\n\n    public boolean visit(SQLOrderBy x) {\n        final SQLASTVisitor orderByVisitor = createOrderByVisitor(x);\n\n        SQLSelectQueryBlock query = null;\n        if (x.getParent() instanceof SQLSelectQueryBlock) {\n            query = (SQLSelectQueryBlock) x.getParent();\n        }\n        if (query != null) {\n            for (SQLSelectOrderByItem item : x.getItems()) {\n                SQLExpr expr = item.getExpr();\n                if (expr instanceof SQLIntegerExpr) {\n                    int intValue = ((SQLIntegerExpr) expr).getNumber().intValue() - 1;\n                    if (intValue < query.getSelectList().size()) {\n                        SQLExpr selectItemExpr = query.getSelectList().get(intValue).getExpr();\n                        selectItemExpr.accept(orderByVisitor);\n                    }\n                } else if (expr instanceof MySqlExpr || expr instanceof OracleExpr) {\n                    continue;\n                }\n            }\n        }\n        x.accept(orderByVisitor);\n\n        for (SQLSelectOrderByItem orderByItem : x.getItems()) {\n            statExpr(\n                    orderByItem.getExpr());\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLOver x) {\n        SQLName of = x.getOf();\n        SQLOrderBy orderBy = x.getOrderBy();\n        List<SQLExpr> partitionBy = x.getPartitionBy();\n\n        if (of == null // skip if of is not null\n                && orderBy != null) {\n            orderBy.accept(this);\n        }\n\n        if (partitionBy != null) {\n            for (SQLExpr expr : partitionBy) {\n                expr.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLWindow x) {\n        SQLOver over = x.getOver();\n        if (over != null) {\n            visit(over);\n        }\n        return false;\n    }\n\n    protected SQLASTVisitor createOrderByVisitor(SQLOrderBy x) {\n        if (dbType == null) {\n            dbType = DbType.other;\n        }\n\n        final SQLASTVisitor orderByVisitor;\n        switch (dbType) {\n            case mysql:\n            case mariadb:\n            case tidb:\n            case polardbx:\n                return new MySqlOrderByStatVisitor(x);\n            case postgresql:\n            case greenplum:\n            case edb:\n                return new PGOrderByStatVisitor(x);\n            case oracle:\n                return new OracleOrderByStatVisitor(x);\n            default:\n                return new OrderByStatVisitor(x);\n        }\n    }\n\n    public Set<Relationship> getRelationships() {\n        return relationships;\n    }\n\n    public List<Column> getOrderByColumns() {\n        return orderByColumns;\n    }\n\n    public Set<Column> getGroupByColumns() {\n        return groupByColumns;\n    }\n\n    public List<Condition> getConditions() {\n        return conditions;\n    }\n\n    public List<SQLAggregateExpr> getAggregateFunctions() {\n        return aggregateFunctions;\n    }\n\n    public boolean visit(SQLBetweenExpr x) {\n        SQLObject parent = x.getParent();\n\n        SQLExpr test = x.getTestExpr();\n        SQLExpr begin = x.getBeginExpr();\n        SQLExpr end = x.getEndExpr();\n\n        statExpr(test);\n        statExpr(begin);\n        statExpr(end);\n\n        handleCondition(test, \"BETWEEN\", begin, end);\n\n        return false;\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        SQLObject parent = x.getParent();\n\n        if (parent instanceof SQLIfStatement) {\n            return true;\n        }\n\n        final SQLBinaryOperator op = x.getOperator();\n        final SQLExpr left = x.getLeft();\n        final SQLExpr right = x.getRight();\n\n        if ((op == SQLBinaryOperator.BooleanAnd || op == SQLBinaryOperator.BooleanOr)\n                && left instanceof SQLBinaryOpExpr\n                && ((SQLBinaryOpExpr) left).getOperator() == op) {\n            List<SQLExpr> groupList = SQLBinaryOpExpr.split(x, op);\n            for (int i = 0; i < groupList.size(); i++) {\n                SQLExpr item = groupList.get(i);\n                item.accept(this);\n            }\n            return false;\n        }\n\n        switch (op) {\n            case Equality:\n            case NotEqual:\n            case GreaterThan:\n            case GreaterThanOrEqual:\n            case LessThan:\n            case LessThanOrGreater:\n            case LessThanOrEqual:\n            case LessThanOrEqualOrGreaterThan:\n            case SoudsLike:\n            case Like:\n            case NotLike:\n            case Is:\n            case IsNot:\n                handleCondition(left, op.name, right);\n\n                String reverseOp = op.name;\n                switch (op) {\n                    case LessThan:\n                        reverseOp = SQLBinaryOperator.GreaterThan.name;\n                        break;\n                    case LessThanOrEqual:\n                        reverseOp = SQLBinaryOperator.GreaterThanOrEqual.name;\n                        break;\n                    case GreaterThan:\n                        reverseOp = SQLBinaryOperator.LessThan.name;\n                        break;\n                    case GreaterThanOrEqual:\n                        reverseOp = SQLBinaryOperator.LessThanOrEqual.name;\n                        break;\n                    default:\n                        break;\n                }\n                handleCondition(right, reverseOp, left);\n\n                handleRelationship(left, op.name, right);\n                break;\n            case BooleanOr: {\n                List<SQLExpr> list = SQLBinaryOpExpr.split(x, op);\n\n                for (SQLExpr item : list) {\n                    if (item instanceof SQLBinaryOpExpr) {\n                        visit((SQLBinaryOpExpr) item);\n                    } else {\n                        item.accept(this);\n                    }\n                }\n\n                return false;\n            }\n            case Modulus:\n                if (right instanceof SQLIdentifierExpr) {\n                    long hashCode64 = ((SQLIdentifierExpr) right).hashCode64();\n                    if (hashCode64 == FnvHash.Constants.ISOPEN) {\n                        left.accept(this);\n                        return false;\n                    }\n                }\n                break;\n            default:\n                break;\n        }\n\n        if (left instanceof SQLBinaryOpExpr) {\n            visit((SQLBinaryOpExpr) left);\n        } else {\n            statExpr(left);\n        }\n        statExpr(right);\n\n        return false;\n    }\n\n    protected void handleRelationship(SQLExpr left, String operator, SQLExpr right) {\n        Column leftColumn = getColumn(left);\n        if (leftColumn == null) {\n            return;\n        }\n\n        Column rightColumn = getColumn(right);\n        if (rightColumn == null) {\n            return;\n        }\n\n        Relationship relationship = new Relationship(leftColumn, rightColumn, operator);\n        this.relationships.add(relationship);\n    }\n\n    protected void handleCondition(SQLExpr expr, String operator, List<SQLExpr> values) {\n        handleCondition(expr, operator, values.toArray(new SQLExpr[values.size()]));\n    }\n\n    protected void handleCondition(SQLExpr expr, String operator, SQLExpr... valueExprs) {\n        if (expr instanceof SQLCastExpr) {\n            expr = ((SQLCastExpr) expr).getExpr();\n        } else if (expr instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) expr;\n            List<SQLExpr> arguments = func.getArguments();\n            if (func.methodNameHashCode64() == FnvHash.Constants.COALESCE\n                    && arguments.size() > 0) {\n                boolean allLiteral = true;\n                for (int i = 1; i < arguments.size(); ++i) {\n                    SQLExpr arg = arguments.get(i);\n                    if (!(arg instanceof SQLLiteralExpr)) {\n                        allLiteral = false;\n                    }\n                }\n                if (allLiteral) {\n                    expr = arguments.get(0);\n                }\n            }\n        }\n\n        Column column = getColumn(expr);\n\n        if (column == null\n                && expr instanceof SQLBinaryOpExpr\n                && valueExprs.length == 1 && valueExprs[0] instanceof SQLLiteralExpr) {\n            SQLBinaryOpExpr left = (SQLBinaryOpExpr) expr;\n            SQLLiteralExpr right = (SQLLiteralExpr) valueExprs[0];\n\n            if (left.getRight() instanceof SQLIntegerExpr && right instanceof SQLIntegerExpr) {\n                long v0 = ((SQLIntegerExpr) left.getRight()).getNumber().longValue();\n                long v1 = ((SQLIntegerExpr) right).getNumber().longValue();\n\n                SQLBinaryOperator op = left.getOperator();\n\n                long v;\n                switch (op) {\n                    case Add:\n                        v = v1 - v0;\n                        break;\n                    case Subtract:\n                        v = v1 + v0;\n                        break;\n                    default:\n                        return;\n                }\n\n                handleCondition(\n                        left.getLeft(), operator, new SQLIntegerExpr(v));\n                return;\n            }\n        }\n\n        if (column == null) {\n            return;\n        }\n\n        Condition condition = null;\n        for (Condition item : this.getConditions()) {\n            if (item.getColumn().equals(column) && item.getOperator().equals(operator)) {\n                condition = item;\n                break;\n            }\n        }\n\n        if (condition == null) {\n            condition = new Condition(column, operator);\n            this.conditions.add(condition);\n        }\n\n        for (SQLExpr item : valueExprs) {\n            Column valueColumn = getColumn(item);\n            if (valueColumn != null) {\n                continue;\n            }\n\n            Object value;\n\n            if (item instanceof SQLCastExpr) {\n                item = ((SQLCastExpr) item).getExpr();\n            }\n\n            if (item instanceof SQLMethodInvokeExpr\n                    || item instanceof SQLCurrentTimeExpr) {\n                value = item.toString();\n            } else {\n                value = SQLEvalVisitorUtils.eval(dbType, item, parameters, false);\n                if (value == SQLEvalVisitor.EVAL_VALUE_NULL) {\n                    value = null;\n                }\n            }\n\n            condition.addValue(value);\n        }\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    protected Column getColumn(SQLExpr expr) {\n        // unwrap\n        expr = unwrapExpr(expr);\n\n        if (expr instanceof SQLPropertyExpr) {\n            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n\n            SQLExpr owner = propertyExpr.getOwner();\n            String column = SQLUtils.normalize(propertyExpr.getName());\n\n            if (owner instanceof SQLName) {\n                SQLName table = (SQLName) owner;\n\n                SQLObject resolvedOwnerObject = propertyExpr.getResolvedOwnerObject();\n                if (resolvedOwnerObject instanceof SQLSubqueryTableSource\n                        || resolvedOwnerObject instanceof SQLCreateProcedureStatement\n                        || resolvedOwnerObject instanceof SQLCreateFunctionStatement\n                        || resolvedOwnerObject instanceof SQLParameter) {\n                    table = null;\n                }\n\n                if (resolvedOwnerObject instanceof SQLExprTableSource) {\n                    SQLExpr tableSourceExpr = ((SQLExprTableSource) resolvedOwnerObject).getExpr();\n                    if (tableSourceExpr instanceof SQLName) {\n                        table = (SQLName) tableSourceExpr;\n                    }\n                } else if (resolvedOwnerObject instanceof SQLValuesTableSource) {\n                    return null;\n                }\n\n                if (table != null) {\n                    String tableName;\n                    if (table instanceof SQLIdentifierExpr) {\n                        tableName = ((SQLIdentifierExpr) table).normalizedName();\n                    } else if (table instanceof SQLPropertyExpr) {\n                        tableName = ((SQLPropertyExpr) table).normalizedName();\n                    } else {\n                        tableName = table.toString();\n                    }\n\n                    long tableHashCode64 = table.hashCode64();\n\n                    if (resolvedOwnerObject instanceof SQLExprTableSource) {\n                        SchemaObject schemaObject = ((SQLExprTableSource) resolvedOwnerObject).getSchemaObject();\n                        if (schemaObject != null && schemaObject.getStatement() instanceof SQLCreateTableStatement) {\n                            SQLColumnDefinition columnDef = schemaObject.findColumn(propertyExpr.nameHashCode64());\n                            if (columnDef == null) {\n                                tableName = \"UNKNOWN\";\n                                tableHashCode64 = FnvHash.Constants.UNKNOWN;\n                            }\n                        }\n                    }\n\n                    long basic = tableHashCode64;\n                    basic ^= '.';\n                    basic *= FnvHash.PRIME;\n                    long columnHashCode64 = FnvHash.hashCode64(basic, column);\n\n                    Column columnObj = this.columns.get(columnHashCode64);\n                    if (columnObj == null) {\n                        columnObj = new Column(tableName, column, columnHashCode64);\n                        if (!(resolvedOwnerObject instanceof SQLSubqueryTableSource\n                                || resolvedOwnerObject instanceof SQLWithSubqueryClause.Entry)) {\n                            this.columns.put(columnHashCode64, columnObj);\n                        }\n                    }\n\n                    return columnObj;\n                }\n            }\n\n            return null;\n        }\n\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n            if (identifierExpr.getResolvedParameter() != null) {\n                return null;\n            }\n\n            if (identifierExpr.getResolvedTableSource() instanceof SQLSubqueryTableSource) {\n                return null;\n            }\n\n            if (identifierExpr.getResolvedDeclareItem() != null || identifierExpr.getResolvedParameter() != null) {\n                return null;\n            }\n\n            String column = identifierExpr.getName();\n\n            SQLName table = null;\n            SQLTableSource tableSource = identifierExpr.getResolvedTableSource();\n            if (tableSource instanceof SQLExprTableSource) {\n                SQLExpr tableSourceExpr = ((SQLExprTableSource) tableSource).getExpr();\n\n                if (tableSourceExpr != null && !(tableSourceExpr instanceof SQLName)) {\n                    tableSourceExpr = unwrapExpr(tableSourceExpr);\n                }\n\n                if (tableSourceExpr instanceof SQLName) {\n                    table = (SQLName) tableSourceExpr;\n                }\n            }\n\n            if (table != null) {\n                long tableHashCode64 = table.hashCode64();\n                long basic = tableHashCode64;\n                basic ^= '.';\n                basic *= FnvHash.PRIME;\n                long columnHashCode64 = FnvHash.hashCode64(basic, column);\n\n                final Column old = columns.get(columnHashCode64);\n                if (old != null) {\n                    return old;\n                }\n\n                return new Column(table.toString(), column, columnHashCode64);\n            }\n\n            return new Column(\"UNKNOWN\", column);\n        }\n\n        if (expr instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;\n            List<SQLExpr> arguments = methodInvokeExpr.getArguments();\n            long nameHash = methodInvokeExpr.methodNameHashCode64();\n            if (nameHash == FnvHash.Constants.DATE_FORMAT) {\n                if (arguments.size() == 2\n                        && arguments.get(0) instanceof SQLName\n                        && arguments.get(1) instanceof SQLCharExpr) {\n                    return getColumn(arguments.get(0));\n                }\n            }\n        }\n\n        return null;\n    }\n\n    private SQLExpr unwrapExpr(SQLExpr expr) {\n        SQLExpr original = expr;\n\n        for (int i = 0; ; i++) {\n            if (i > 1000) {\n                return null;\n            }\n\n            if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr methodInvokeExp = (SQLMethodInvokeExpr) expr;\n                if (methodInvokeExp.getArguments().size() == 1) {\n                    SQLExpr firstExpr = methodInvokeExp.getArguments().get(0);\n                    expr = firstExpr;\n                    continue;\n                }\n            }\n\n            if (expr instanceof SQLCastExpr) {\n                expr = ((SQLCastExpr) expr).getExpr();\n                continue;\n            }\n\n            if (expr instanceof SQLAllColumnExpr) {\n                SQLExpr owner = ((SQLAllColumnExpr) expr).getOwner();\n                if (owner != null) {\n                    return owner;\n                }\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n\n                SQLTableSource resolvedTableSource = propertyExpr.getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLSubqueryTableSource || resolvedTableSource instanceof SQLWithSubqueryClause.Entry) {\n                    SQLSelect select;\n                    if (resolvedTableSource instanceof SQLSubqueryTableSource) {\n                        select = ((SQLSubqueryTableSource) resolvedTableSource).getSelect();\n                    } else {\n                        select = ((SQLWithSubqueryClause.Entry) resolvedTableSource).getSubQuery();\n                    }\n\n                    SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();\n                    if (queryBlock != null) {\n                        if (queryBlock.getGroupBy() != null) {\n                            if (original.getParent() instanceof SQLBinaryOpExpr) {\n                                SQLExpr other = ((SQLBinaryOpExpr) original.getParent()).other(original);\n                                if (!SQLExprUtils.isLiteralExpr(other)) {\n                                    break;\n                                }\n                            }\n                        }\n\n                        SQLSelectItem selectItem = queryBlock.findSelectItem(propertyExpr\n                                .nameHashCode64());\n                        if (selectItem != null) {\n                            SQLExpr selectItemExpr = selectItem.getExpr();\n                            if (selectItemExpr instanceof SQLMethodInvokeExpr\n                                    && ((SQLMethodInvokeExpr) selectItemExpr).getArguments().size() == 1\n                            ) {\n                                selectItemExpr = ((SQLMethodInvokeExpr) selectItemExpr).getArguments().get(0);\n                            }\n                            if (selectItemExpr != expr) {\n                                expr = selectItemExpr;\n                                continue;\n                            }\n                        } else if (queryBlock.selectItemHasAllColumn()) {\n                            SQLTableSource allColumnTableSource = null;\n\n                            SQLTableSource from = queryBlock.getFrom();\n                            if (from instanceof SQLJoinTableSource) {\n                                SQLSelectItem allColumnSelectItem = queryBlock.findAllColumnSelectItem();\n                                if (allColumnSelectItem != null && allColumnSelectItem.getExpr() instanceof SQLPropertyExpr) {\n                                    SQLExpr owner = ((SQLPropertyExpr) allColumnSelectItem.getExpr()).getOwner();\n                                    if (owner instanceof SQLName) {\n                                        allColumnTableSource = from.findTableSource(((SQLName) owner).nameHashCode64());\n                                    }\n                                }\n                            } else {\n                                allColumnTableSource = from;\n                            }\n\n                            if (allColumnTableSource == null) {\n                                break;\n                            }\n\n                            propertyExpr = propertyExpr.clone();\n                            propertyExpr.setResolvedTableSource(allColumnTableSource);\n\n                            if (allColumnTableSource instanceof SQLExprTableSource) {\n                                propertyExpr.setOwner(((SQLExprTableSource) allColumnTableSource).getExpr().clone());\n                            }\n                            expr = propertyExpr;\n                            continue;\n                        }\n                    }\n                } else if (resolvedTableSource instanceof SQLExprTableSource) {\n                    SQLExprTableSource exprTableSource = (SQLExprTableSource) resolvedTableSource;\n                    if (exprTableSource.getSchemaObject() != null) {\n                        break;\n                    }\n\n                    SQLTableSource redirectTableSource = null;\n                    SQLExpr tableSourceExpr = exprTableSource.getExpr();\n                    if (tableSourceExpr instanceof SQLIdentifierExpr) {\n                        redirectTableSource = ((SQLIdentifierExpr) tableSourceExpr).getResolvedTableSource();\n                    } else if (tableSourceExpr instanceof SQLPropertyExpr) {\n                        redirectTableSource = ((SQLPropertyExpr) tableSourceExpr).getResolvedTableSource();\n                    }\n\n                    if (redirectTableSource == resolvedTableSource) {\n                        redirectTableSource = null;\n                    }\n\n                    if (redirectTableSource != null) {\n                        propertyExpr = propertyExpr.clone();\n                        if (redirectTableSource instanceof SQLExprTableSource) {\n                            propertyExpr.setOwner(((SQLExprTableSource) redirectTableSource).getExpr().clone());\n                        }\n                        propertyExpr.setResolvedTableSource(redirectTableSource);\n                        expr = propertyExpr;\n                        continue;\n                    }\n\n                    propertyExpr = propertyExpr.clone();\n                    propertyExpr.setOwner(tableSourceExpr);\n                    expr = propertyExpr;\n                    break;\n                }\n            }\n            break;\n        }\n\n        return expr;\n    }\n\n    @Override\n    public boolean visit(SQLTruncateStatement x) {\n        setMode(x, Mode.Delete);\n\n        for (SQLExprTableSource tableSource : x.getTableSources()) {\n            SQLName name = (SQLName) tableSource.getExpr();\n            TableStat stat = getTableStat(name);\n            stat.incrementDeleteCount();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropViewStatement x) {\n        setMode(x, Mode.Drop);\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLDropTableStatement x) {\n        setMode(x, Mode.Insert);\n\n        for (SQLExprTableSource tableSource : x.getTableSources()) {\n            SQLName name = (SQLName) tableSource.getExpr();\n            TableStat stat = getTableStat(name);\n            stat.incrementDropCount();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLInsertStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        setMode(x, Mode.Insert);\n\n        if (x.getTableName() instanceof SQLName) {\n            String ident = ((SQLName) x.getTableName()).toString();\n\n            TableStat stat = getTableStat(x.getTableName());\n            stat.incrementInsertCount();\n        }\n\n        accept(x.getColumns());\n        accept(x.getQuery());\n        if (x instanceof OracleInsertStatement) {\n            accept(((OracleInsertStatement) x).getReturning());\n        }\n\n        return false;\n    }\n\n    protected static void putAliasMap(Map<String, String> aliasMap, String name, String value) {\n        if (aliasMap == null || name == null) {\n            return;\n        }\n        aliasMap.put(name.toLowerCase(), value);\n    }\n\n    protected void accept(SQLObject x) {\n        if (x != null) {\n            x.accept(this);\n        }\n    }\n\n    protected void accept(List<? extends SQLObject> nodes) {\n        for (int i = 0, size = nodes.size(); i < size; ++i) {\n            accept(nodes.get(i));\n        }\n    }\n\n    public boolean visit(SQLSelectQueryBlock x) {\n        SQLTableSource from = x.getFrom();\n\n        setMode(x, Mode.Select);\n\n        boolean isHiveMultiInsert = false;\n        if (from == null) {\n            isHiveMultiInsert = x.getParent() != null\n                    && x.getParent().getParent() instanceof HiveInsert\n                    && x.getParent().getParent().getParent() instanceof HiveMultiInsertStatement;\n            if (isHiveMultiInsert) {\n                from = ((HiveMultiInsertStatement) x.getParent().getParent().getParent()).getFrom();\n            }\n        }\n\n        if (from == null) {\n            for (SQLSelectItem selectItem : x.getSelectList()) {\n                statExpr(\n                        selectItem.getExpr());\n            }\n            return false;\n        }\n\n//        if (x.getFrom() instanceof SQLSubqueryTableSource) {\n//            x.getFrom().accept(this);\n//            return false;\n//        }\n\n        if (from != null) {\n            from.accept(this); // 提前执行，获得aliasMap\n        }\n\n        SQLExprTableSource into = x.getInto();\n        if (into != null && into.getExpr() instanceof SQLName) {\n            SQLName intoExpr = (SQLName) into.getExpr();\n\n            boolean isParam = intoExpr instanceof SQLIdentifierExpr && isParam((SQLIdentifierExpr) intoExpr);\n\n            if (!isParam) {\n                TableStat stat = getTableStat(intoExpr);\n                if (stat != null) {\n                    stat.incrementInsertCount();\n                }\n            }\n            into.accept(this);\n        }\n\n        for (SQLSelectItem selectItem : x.getSelectList()) {\n            if (selectItem.getClass() == SQLSelectItem.class) {\n                statExpr(\n                        selectItem.getExpr());\n            } else {\n                selectItem.accept(this);\n            }\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            statExpr(where);\n        }\n\n        SQLExpr startWith = x.getStartWith();\n        if (startWith != null) {\n            statExpr(startWith);\n        }\n\n        SQLExpr connectBy = x.getConnectBy();\n        if (connectBy != null) {\n            statExpr(connectBy);\n        }\n\n        SQLSelectGroupByClause groupBy = x.getGroupBy();\n        if (groupBy != null) {\n            for (SQLExpr expr : groupBy.getItems()) {\n                statExpr(expr);\n            }\n            if (groupBy.getHaving() != null) {\n                statExpr(groupBy.getHaving());\n            }\n        }\n\n        List<SQLWindow> windows = x.getWindows();\n        if (windows != null && windows.size() > 0) {\n            for (SQLWindow window : windows) {\n                window.accept(this);\n            }\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            this.visit(orderBy);\n        }\n\n        SQLExpr first = x.getFirst();\n        if (first != null) {\n            statExpr(first);\n        }\n\n        List<SQLSelectOrderByItem> distributeBy = x.getDistributeBy();\n        if (distributeBy != null) {\n            for (SQLSelectOrderByItem item : distributeBy) {\n                statExpr(item.getExpr());\n            }\n        }\n\n        List<SQLSelectOrderByItem> sortBy = x.getSortBy();\n        if (sortBy != null) {\n            for (SQLSelectOrderByItem orderByItem : sortBy) {\n                statExpr(orderByItem.getExpr());\n            }\n        }\n\n        for (SQLExpr expr : x.getForUpdateOf()) {\n            statExpr(expr);\n        }\n\n        return false;\n    }\n\n    private static boolean isParam(SQLIdentifierExpr x) {\n        if (x.getResolvedParameter() != null\n                || x.getResolvedDeclareItem() != null) {\n            return true;\n        }\n        return false;\n    }\n\n    public void endVisit(SQLSelectQueryBlock x) {\n        setModeOrigin(x);\n    }\n\n    public boolean visit(SQLJoinTableSource x) {\n        SQLTableSource left = x.getLeft(), right = x.getRight();\n\n        left.accept(this);\n        right.accept(this);\n\n        SQLExpr condition = x.getCondition();\n        if (condition != null) {\n            condition.accept(this);\n        }\n\n        if (x.getUsing().size() > 0\n                && left instanceof SQLExprTableSource && right instanceof SQLExprTableSource) {\n            SQLExpr leftExpr = ((SQLExprTableSource) left).getExpr();\n            SQLExpr rightExpr = ((SQLExprTableSource) right).getExpr();\n\n            for (SQLExpr expr : x.getUsing()) {\n                if (expr instanceof SQLIdentifierExpr) {\n                    String name = ((SQLIdentifierExpr) expr).getName();\n                    SQLPropertyExpr leftPropExpr = new SQLPropertyExpr(leftExpr, name);\n                    SQLPropertyExpr rightPropExpr = new SQLPropertyExpr(rightExpr, name);\n\n                    leftPropExpr.setResolvedTableSource(left);\n                    rightPropExpr.setResolvedTableSource(right);\n\n                    SQLBinaryOpExpr usingCondition = new SQLBinaryOpExpr(leftPropExpr, SQLBinaryOperator.Equality, rightPropExpr);\n                    usingCondition.accept(this);\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLPropertyExpr x) {\n        Column column = null;\n        String ident = SQLUtils.normalize(x.getName());\n\n        SQLTableSource tableSource = x.getResolvedTableSource();\n\n        if (tableSource instanceof SQLSubqueryTableSource) {\n            SQLSelect subSelect = ((SQLSubqueryTableSource) tableSource).getSelect();\n            SQLSelectQueryBlock subQuery = subSelect.getQueryBlock();\n            if (subQuery != null) {\n                SQLTableSource subTableSource = subQuery.findTableSourceWithColumn(x.nameHashCode64());\n                if (subTableSource != null) {\n                    tableSource = subTableSource;\n                }\n            }\n        }\n\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr();\n\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr table = (SQLIdentifierExpr) expr;\n                SQLTableSource resolvedTableSource = table.getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLExprTableSource) {\n                    expr = ((SQLExprTableSource) resolvedTableSource).getExpr();\n                }\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr table = (SQLPropertyExpr) expr;\n                SQLTableSource resolvedTableSource = table.getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLExprTableSource) {\n                    expr = ((SQLExprTableSource) resolvedTableSource).getExpr();\n                }\n            }\n\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr table = (SQLIdentifierExpr) expr;\n\n                SQLTableSource resolvedTableSource = table.getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLWithSubqueryClause.Entry) {\n                    return false;\n                }\n\n                String tableName = table.getName();\n                SchemaObject schemaObject = ((SQLExprTableSource) tableSource).getSchemaObject();\n                if (schemaObject != null\n                        && schemaObject.getStatement() instanceof SQLCreateTableStatement\n                        && !\"*\".equals(ident)) {\n                    SQLColumnDefinition columnDef = schemaObject.findColumn(x.nameHashCode64());\n                    if (columnDef == null) {\n                        column = addColumn(\"UNKNOWN\", ident);\n                    }\n                }\n\n                if (column == null) {\n                    column = addColumn(table, ident);\n                }\n\n                if (isParentGroupBy(x)) {\n                    this.groupByColumns.add(column);\n                }\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr table = (SQLPropertyExpr) expr;\n                column = addColumn(table, ident);\n\n                if (column != null && isParentGroupBy(x)) {\n                    this.groupByColumns.add(column);\n                }\n            } else if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;\n                if (\"table\".equalsIgnoreCase(methodInvokeExpr.getMethodName())\n                        && methodInvokeExpr.getArguments().size() == 1\n                        && methodInvokeExpr.getArguments().get(0) instanceof SQLName) {\n                    SQLName table = (SQLName) methodInvokeExpr.getArguments().get(0);\n\n                    String tableName = null;\n                    if (table instanceof SQLPropertyExpr) {\n                        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) table;\n                        SQLIdentifierExpr owner = (SQLIdentifierExpr) propertyExpr.getOwner();\n                        if (propertyExpr.getResolvedTableSource() != null\n                                && propertyExpr.getResolvedTableSource() instanceof SQLExprTableSource) {\n                            SQLExpr resolveExpr = ((SQLExprTableSource) propertyExpr.getResolvedTableSource()).getExpr();\n                            if (resolveExpr instanceof SQLName) {\n                                tableName = resolveExpr.toString() + \".\" + propertyExpr.getName();\n                            }\n                        }\n                    }\n\n                    if (tableName == null) {\n                        tableName = table.toString();\n                    }\n\n                    column = addColumn(tableName, ident);\n                }\n            }\n        } else if (tableSource instanceof SQLWithSubqueryClause.Entry\n                || tableSource instanceof SQLSubqueryTableSource\n                || tableSource instanceof SQLUnionQueryTableSource\n                || tableSource instanceof SQLValuesTableSource\n                || tableSource instanceof SQLLateralViewTableSource) {\n            return false;\n        } else {\n            if (x.getResolvedProcudure() != null) {\n                return false;\n            }\n\n            if (x.getResolvedOwnerObject() instanceof SQLParameter) {\n                return false;\n            }\n\n            boolean skip = false;\n            for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n                if (parent instanceof SQLSelectQueryBlock) {\n                    SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom();\n\n                    if (from instanceof SQLValuesTableSource) {\n                        skip = true;\n                        break;\n                    }\n                } else if (parent instanceof SQLSelectQuery) {\n                    break;\n                }\n            }\n            if (!skip) {\n                column = handleUnknownColumn(ident);\n            }\n        }\n\n        if (column != null) {\n            SQLObject parent = x.getParent();\n            if (parent instanceof SQLSelectOrderByItem) {\n                parent = parent.getParent();\n                if (parent instanceof SQLIndexDefinition) {\n                    parent = parent.getParent();\n                }\n            }\n            if (parent instanceof SQLPrimaryKey) {\n                column.setPrimaryKey(true);\n            } else if (parent instanceof SQLUnique) {\n                column.setUnique(true);\n            }\n\n            setColumn(x, column);\n        }\n\n        return false;\n    }\n\n    protected boolean isPseudoColumn(long hash) {\n        return false;\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        if (isParam(x)) {\n            return false;\n        }\n\n        SQLTableSource tableSource = x.getResolvedTableSource();\n        if (x.getParent() instanceof SQLSelectOrderByItem) {\n            SQLSelectOrderByItem selectOrderByItem = (SQLSelectOrderByItem) x.getParent();\n            if (selectOrderByItem.getResolvedSelectItem() != null) {\n                return false;\n            }\n        }\n\n        if (tableSource == null\n                && (x.getResolvedParameter() != null\n                || x.getResolvedDeclareItem() != null)) {\n            return false;\n        }\n\n        long hash = x.nameHashCode64();\n        if (isPseudoColumn(hash)) {\n            return false;\n        }\n\n        if ((hash == FnvHash.Constants.LEVEL\n                || hash == FnvHash.Constants.CONNECT_BY_ISCYCLE\n                || hash == FnvHash.Constants.ROWNUM)\n                && x.getResolvedColumn() == null\n                && tableSource == null) {\n            return false;\n        }\n\n        Column column = null;\n        String ident = x.normalizedName();\n\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr();\n\n            if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) expr;\n                if (func.methodNameHashCode64() == FnvHash.Constants.ANN) {\n                    expr = func.getArguments().get(0);\n                }\n            }\n\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr table = (SQLIdentifierExpr) expr;\n                column = addColumn(table, ident);\n\n                if (column != null && isParentGroupBy(x)) {\n                    this.groupByColumns.add(column);\n                }\n            } else if (expr instanceof SQLPropertyExpr || expr instanceof SQLDbLinkExpr) {\n                String tableName;\n                if (expr instanceof SQLPropertyExpr) {\n                    tableName = ((SQLPropertyExpr) expr).normalizedName();\n                } else {\n                    tableName = expr.toString();\n                }\n\n                column = addColumn(tableName, ident);\n\n                if (column != null && isParentGroupBy(x)) {\n                    this.groupByColumns.add(column);\n                }\n            } else if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;\n                if (\"table\".equalsIgnoreCase(methodInvokeExpr.getMethodName())\n                        && methodInvokeExpr.getArguments().size() == 1\n                        && methodInvokeExpr.getArguments().get(0) instanceof SQLName) {\n                    SQLName table = (SQLName) methodInvokeExpr.getArguments().get(0);\n\n                    String tableName = null;\n                    if (table instanceof SQLPropertyExpr) {\n                        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) table;\n                        SQLIdentifierExpr owner = (SQLIdentifierExpr) propertyExpr.getOwner();\n                        if (propertyExpr.getResolvedTableSource() != null\n                                && propertyExpr.getResolvedTableSource() instanceof SQLExprTableSource) {\n                            SQLExpr resolveExpr = ((SQLExprTableSource) propertyExpr.getResolvedTableSource()).getExpr();\n                            if (resolveExpr instanceof SQLName) {\n                                tableName = resolveExpr.toString() + \".\" + propertyExpr.getName();\n                            }\n                        }\n                    }\n\n                    if (tableName == null) {\n                        tableName = table.toString();\n                    }\n\n                    column = addColumn(tableName, ident);\n                }\n            }\n        } else if (tableSource instanceof SQLWithSubqueryClause.Entry\n                || tableSource instanceof SQLSubqueryTableSource\n                || tableSource instanceof SQLLateralViewTableSource) {\n            return false;\n        } else {\n            boolean skip = false;\n            for (SQLObject parent = x.getParent(); parent != null; parent = parent.getParent()) {\n                if (parent instanceof SQLSelectQueryBlock) {\n                    SQLTableSource from = ((SQLSelectQueryBlock) parent).getFrom();\n\n                    if (from instanceof SQLValuesTableSource) {\n                        skip = true;\n                        break;\n                    }\n                } else if (parent instanceof SQLSelectQuery) {\n                    break;\n                }\n            }\n            if (x.getParent() instanceof SQLMethodInvokeExpr\n                    && ((SQLMethodInvokeExpr) x.getParent()).methodNameHashCode64() == FnvHash.Constants.ANN) {\n                skip = true;\n            }\n\n            if (!skip) {\n                column = handleUnknownColumn(ident);\n            }\n        }\n\n        if (column != null) {\n            SQLObject parent = x.getParent();\n            if (parent instanceof SQLSelectOrderByItem) {\n                parent = parent.getParent();\n                if (parent instanceof SQLIndexDefinition) {\n                    parent = parent.getParent();\n                }\n            }\n            if (parent instanceof SQLPrimaryKey) {\n                column.setPrimaryKey(true);\n            } else if (parent instanceof SQLUnique) {\n                column.setUnique(true);\n            }\n\n            setColumn(x, column);\n        }\n\n        return false;\n    }\n\n    private boolean isParentSelectItem(SQLObject parent) {\n        for (int i = 0; parent != null; parent = parent.getParent(), ++i) {\n            if (i > 100) {\n                break;\n            }\n\n            if (parent instanceof SQLSelectItem) {\n                return true;\n            }\n\n            if (parent instanceof SQLSelectQueryBlock) {\n                return false;\n            }\n        }\n        return false;\n    }\n\n    private boolean isParentGroupBy(SQLObject parent) {\n        for (; parent != null; parent = parent.getParent()) {\n            if (parent instanceof SQLSelectItem) {\n                return false;\n            }\n\n            if (parent instanceof SQLSelectGroupByClause) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private void setColumn(SQLExpr x, Column column) {\n        SQLObject current = x;\n        for (int i = 0; i < 100; ++i) {\n            SQLObject parent = current.getParent();\n\n            if (parent == null) {\n                break;\n            }\n\n            if (parent instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock query = (SQLSelectQueryBlock) parent;\n                if (query.getWhere() == current) {\n                    column.setWhere(true);\n                }\n                break;\n            }\n\n            if (parent instanceof SQLSelectGroupByClause) {\n                SQLSelectGroupByClause groupBy = (SQLSelectGroupByClause) parent;\n                if (current == groupBy.getHaving()) {\n                    column.setHaving(true);\n                } else if (groupBy.getItems().contains(current)) {\n                    column.setGroupBy(true);\n                }\n                break;\n            }\n\n            if (isParentSelectItem(parent)) {\n                column.setSelec(true);\n                break;\n            }\n\n            if (parent instanceof SQLJoinTableSource) {\n                SQLJoinTableSource join = (SQLJoinTableSource) parent;\n                if (join.getCondition() == current) {\n                    column.setJoin(true);\n                }\n                break;\n            }\n\n            current = parent;\n        }\n    }\n\n    protected Column handleUnknownColumn(String columnName) {\n        return addColumn(\"UNKNOWN\", columnName);\n    }\n\n    public boolean visit(SQLAllColumnExpr x) {\n        SQLTableSource tableSource = x.getResolvedTableSource();\n        if (tableSource == null) {\n            return false;\n        }\n\n        SQLIdentifierExpr owner = null;\n        if (x.getOwner() instanceof SQLIdentifierExpr) {\n            owner = (SQLIdentifierExpr) x.getOwner();\n        }\n        if (tableSource instanceof SQLSubqueryTableSource) {\n            SQLSelect subSelect = ((SQLSubqueryTableSource) tableSource).getSelect();\n            SQLSelectQueryBlock subQuery = subSelect.getQueryBlock();\n            if (subQuery != null && owner != null) {\n                SQLTableSource subTableSource = subQuery.findTableSourceWithColumn(owner.nameHashCode64());\n                if (subTableSource != null) {\n                    tableSource = subTableSource;\n                }\n            }\n        }\n\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr();\n\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr table = (SQLIdentifierExpr) expr;\n                SQLTableSource resolvedTableSource = table.getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLExprTableSource) {\n                    expr = ((SQLExprTableSource) resolvedTableSource).getExpr();\n                }\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr table = (SQLPropertyExpr) expr;\n                SQLTableSource resolvedTableSource = table.getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLExprTableSource) {\n                    expr = ((SQLExprTableSource) resolvedTableSource).getExpr();\n                }\n            }\n\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr table = (SQLIdentifierExpr) expr;\n\n                SQLTableSource resolvedTableSource = table.getResolvedTableSource();\n                if (resolvedTableSource instanceof SQLWithSubqueryClause.Entry) {\n                    return false;\n                }\n\n                addColumn(table, \"*\");\n            } else if (expr instanceof SQLPropertyExpr) {\n                SQLPropertyExpr table = (SQLPropertyExpr) expr;\n                addColumn(table, \"*\");\n            } else if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;\n                if (\"table\".equalsIgnoreCase(methodInvokeExpr.getMethodName())\n                        && methodInvokeExpr.getArguments().size() == 1\n                        && methodInvokeExpr.getArguments().get(0) instanceof SQLName) {\n                    SQLName table = (SQLName) methodInvokeExpr.getArguments().get(0);\n\n                    String tableName = null;\n                    if (table instanceof SQLPropertyExpr) {\n                        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) table;\n                        if (propertyExpr.getResolvedTableSource() != null\n                                && propertyExpr.getResolvedTableSource() instanceof SQLExprTableSource) {\n                            SQLExpr resolveExpr = ((SQLExprTableSource) propertyExpr.getResolvedTableSource()).getExpr();\n                            if (resolveExpr instanceof SQLName) {\n                                tableName = resolveExpr.toString() + \".\" + propertyExpr.getName();\n                            }\n                        }\n                    }\n\n                    if (tableName == null) {\n                        tableName = table.toString();\n                    }\n\n                    addColumn(tableName, \"*\");\n                }\n            }\n        }\n\n        statAllColumn(x, tableSource);\n\n        return false;\n    }\n\n    private void statAllColumn(SQLAllColumnExpr x, SQLTableSource tableSource) {\n        if (tableSource instanceof SQLExprTableSource) {\n            statAllColumn(x, (SQLExprTableSource) tableSource);\n            return;\n        }\n\n        if (tableSource instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n            statAllColumn(x, join.getLeft());\n            statAllColumn(x, join.getRight());\n        }\n    }\n\n    private void statAllColumn(SQLAllColumnExpr x, SQLExprTableSource tableSource) {\n        SQLExprTableSource exprTableSource = tableSource;\n        SQLName expr = exprTableSource.getName();\n        if (x.getOwner() instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr owner = (SQLIdentifierExpr) x.getOwner();\n            if (!tableSource.containsAlias(owner.normalizedName())) {\n                return;\n            }\n        }\n\n        SQLCreateTableStatement createStmt = null;\n\n        SchemaObject tableObject = exprTableSource.getSchemaObject();\n        if (tableObject != null) {\n            SQLStatement stmt = tableObject.getStatement();\n            if (stmt instanceof SQLCreateTableStatement) {\n                createStmt = (SQLCreateTableStatement) stmt;\n            }\n        }\n\n        if (createStmt != null\n                && createStmt.getTableElementList().size() > 0) {\n            SQLName tableName = createStmt.getName();\n            for (SQLTableElement e : createStmt.getTableElementList()) {\n                if (e instanceof SQLColumnDefinition) {\n                    SQLColumnDefinition columnDefinition = (SQLColumnDefinition) e;\n                    SQLName columnName = columnDefinition.getName();\n                    Column column = addColumn(tableName, columnName.toString());\n                    if (isParentSelectItem(x.getParent())) {\n                        column.setSelec(true);\n                    }\n                }\n            }\n        } else if (expr != null) {\n            Column column = addColumn(expr, \"*\");\n            if (isParentSelectItem(x.getParent())) {\n                column.setSelec(true);\n            }\n        }\n    }\n\n    public Map<TableStat.Name, TableStat> getTables() {\n        return tableStats;\n    }\n\n    public boolean containsTable(String tableName) {\n        return tableStats.containsKey(new TableStat.Name(tableName));\n    }\n\n    public boolean containsColumn(String tableName, String columnName) {\n        long hashCode;\n\n        int p = tableName.indexOf('.');\n        if (p != -1) {\n            SQLExpr owner = SQLUtils.toSQLExpr(tableName, dbType);\n            hashCode = new SQLPropertyExpr(owner, columnName).hashCode64();\n        } else {\n            hashCode = FnvHash.hashCode64(tableName, columnName);\n        }\n        return columns.containsKey(hashCode);\n    }\n\n    public Collection<Column> getColumns() {\n        return columns.values();\n    }\n\n    public Column getColumn(String tableName, String columnName) {\n        Column column = new Column(tableName, columnName);\n\n        return this.columns.get(column.hashCode64());\n    }\n\n    public boolean visit(SQLSelectStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        visit(x.getSelect());\n\n        return false;\n    }\n\n    public void endVisit(SQLSelectStatement x) {\n    }\n\n    @Override\n    public boolean visit(SQLWithSubqueryClause.Entry x) {\n        String alias = x.getAlias();\n        SQLWithSubqueryClause with = (SQLWithSubqueryClause) x.getParent();\n\n        SQLStatement returningStatement = x.getReturningStatement();\n        SQLExpr expr = x.getExpr();\n\n        if (Boolean.TRUE.equals(with.getRecursive())) {\n            SQLSelect select = x.getSubQuery();\n            if (select != null) {\n                select.accept(this);\n            } else {\n                returningStatement.accept(this);\n            }\n        } else {\n            SQLSelect select = x.getSubQuery();\n            if (select != null) {\n                select.accept(this);\n            } else if (expr != null) {\n                expr.accept(this);\n            } else {\n                if (returningStatement != null) {\n                    returningStatement.accept(this);\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLSubqueryTableSource x) {\n        x.getSelect().accept(this);\n        return false;\n    }\n\n    protected boolean isSimpleExprTableSource(SQLExprTableSource x) {\n        SQLExpr expr = x.getExpr();\n        return (expr instanceof SQLName && !(expr instanceof SQLAllColumnExpr)) || (expr instanceof SQLAllColumnExpr && ((SQLAllColumnExpr) expr).getOwner() != null);\n    }\n\n    public TableStat getTableStat(SQLExprTableSource tableSource) {\n        return getTableStatWithUnwrap(\n                tableSource.getExpr());\n    }\n\n    protected TableStat getTableStatWithUnwrap(SQLExpr expr) {\n        SQLExpr identExpr = null;\n\n        expr = unwrapExpr(expr);\n\n        if (expr instanceof SQLIdentifierExpr) {\n            SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;\n\n            if (identifierExpr.nameHashCode64() == FnvHash.Constants.DUAL) {\n                return null;\n            }\n\n            if (isSubQueryOrParamOrVariant(identifierExpr)) {\n                return null;\n            }\n        }\n\n        SQLTableSource tableSource = null;\n        if (expr instanceof SQLIdentifierExpr) {\n            tableSource = ((SQLIdentifierExpr) expr).getResolvedTableSource();\n        } else if (expr instanceof SQLPropertyExpr) {\n            tableSource = ((SQLPropertyExpr) expr).getResolvedTableSource();\n        } else if (expr instanceof SQLAllColumnExpr) {\n            tableSource = ((SQLAllColumnExpr) expr).getResolvedTableSource();\n        }\n\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr tableSourceExpr = ((SQLExprTableSource) tableSource).getExpr();\n            if (tableSourceExpr instanceof SQLName) {\n                identExpr = tableSourceExpr;\n            }\n        }\n\n        if (identExpr == null) {\n            identExpr = expr;\n        }\n\n        if (identExpr instanceof SQLName) {\n            return getTableStat((SQLName) identExpr);\n        }\n        return getTableStat(identExpr.toString());\n    }\n\n    public boolean visit(SQLExprTableSource x) {\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr func = (SQLMethodInvokeExpr) expr;\n            if (func.methodNameHashCode64() == FnvHash.Constants.ANN) {\n                expr = func.getArguments().get(0);\n            }\n        }\n\n        if (isSimpleExprTableSource(x)) {\n            TableStat stat = getTableStatWithUnwrap(expr);\n            if (stat == null) {\n                return false;\n            }\n\n            Mode mode = getMode();\n            if (mode != null) {\n                switch (mode) {\n                    case Delete:\n                        stat.incrementDeleteCount();\n                        break;\n                    case Insert:\n                        stat.incrementInsertCount();\n                        break;\n                    case Update:\n                        stat.incrementUpdateCount();\n                        break;\n                    case Select:\n                        stat.incrementSelectCount();\n                        break;\n                    case Merge:\n                        stat.incrementMergeCount();\n                        break;\n                    case Drop:\n                        stat.incrementDropCount();\n                        break;\n                    default:\n                        break;\n                }\n            }\n        } else {\n            accept(expr);\n        }\n\n        return false;\n    }\n\n    protected boolean isSubQueryOrParamOrVariant(SQLIdentifierExpr identifierExpr) {\n        SQLObject resolvedColumnObject = identifierExpr.getResolvedColumnObject();\n        if (resolvedColumnObject instanceof SQLWithSubqueryClause.Entry\n                || resolvedColumnObject instanceof SQLParameter\n                || resolvedColumnObject instanceof SQLDeclareItem) {\n            return true;\n        }\n\n        SQLObject resolvedOwnerObject = identifierExpr.getResolvedOwnerObject();\n        if (resolvedOwnerObject instanceof SQLSubqueryTableSource\n                || resolvedOwnerObject instanceof SQLWithSubqueryClause.Entry) {\n            return true;\n        }\n\n        return false;\n    }\n\n    protected boolean isSubQueryOrParamOrVariant(SQLPropertyExpr x) {\n        SQLObject resolvedOwnerObject = x.getResolvedOwnerObject();\n        if (resolvedOwnerObject instanceof SQLSubqueryTableSource\n                || resolvedOwnerObject instanceof SQLWithSubqueryClause.Entry) {\n            return true;\n        }\n\n        SQLExpr owner = x.getOwner();\n        if (owner instanceof SQLIdentifierExpr) {\n            if (isSubQueryOrParamOrVariant((SQLIdentifierExpr) owner)) {\n                return true;\n            }\n        }\n\n        SQLTableSource tableSource = x.getResolvedTableSource();\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;\n            if (exprTableSource.getSchemaObject() != null) {\n                return false;\n            }\n\n            SQLExpr expr = exprTableSource.getExpr();\n\n            if (expr instanceof SQLIdentifierExpr) {\n                return isSubQueryOrParamOrVariant((SQLIdentifierExpr) expr);\n            }\n\n            if (expr instanceof SQLPropertyExpr) {\n                return isSubQueryOrParamOrVariant((SQLPropertyExpr) expr);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLSelectItem x) {\n        statExpr(\n                x.getExpr());\n\n        return false;\n    }\n\n    public boolean visit(SQLSelect x) {\n        SQLWithSubqueryClause with = x.getWithSubQuery();\n        if (with != null) {\n            with.accept(this);\n        }\n\n        SQLSelectQuery query = x.getQuery();\n        if (query != null) {\n            query.accept(this);\n        }\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            accept(x.getOrderBy());\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLAggregateExpr x) {\n        this.aggregateFunctions.add(x);\n\n        accept(x.getArguments());\n        accept(x.getOrderBy());\n        accept(x.getOver());\n        return false;\n    }\n\n    public boolean visit(SQLMethodInvokeExpr x) {\n        this.functions.add(x);\n\n        accept(x.getArguments());\n        accept(x.getFrom());\n        return false;\n    }\n\n    public boolean visit(SQLUpdateStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        setMode(x, Mode.Update);\n\n        SQLTableSource tableSource = x.getTableSource();\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLName identName = ((SQLExprTableSource) tableSource).getName();\n            TableStat stat = getTableStat(identName);\n            stat.incrementUpdateCount();\n        } else {\n            tableSource.accept(this);\n        }\n\n        final SQLTableSource from = x.getFrom();\n        if (from != null) {\n            from.accept(this);\n        }\n\n        final List<SQLUpdateSetItem> items = x.getItems();\n        for (int i = 0, size = items.size(); i < size; ++i) {\n            SQLUpdateSetItem item = items.get(i);\n            visit(item);\n        }\n\n        final SQLExpr where = x.getWhere();\n        if (where != null) {\n            where.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLUpdateSetItem x) {\n        final SQLExpr column = x.getColumn();\n        if (column != null) {\n            statExpr(column);\n\n            final Column columnStat = getColumn(column);\n            if (columnStat != null) {\n                columnStat.setUpdate(true);\n            }\n        }\n\n        final SQLExpr value = x.getValue();\n        if (value != null) {\n            statExpr(value);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLDeleteStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        setMode(x, Mode.Delete);\n\n        if (x.getTableSource() instanceof SQLSubqueryTableSource) {\n            SQLSelectQuery selectQuery = ((SQLSubqueryTableSource) x.getTableSource()).getSelect().getQuery();\n            if (selectQuery instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock subQueryBlock = ((SQLSelectQueryBlock) selectQuery);\n                subQueryBlock.getWhere().accept(this);\n            }\n        }\n\n        TableStat stat = getTableStat(x.getTableName());\n        stat.incrementDeleteCount();\n\n        final SQLExpr where = x.getWhere();\n        if (where != null) {\n            where.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLInListExpr x) {\n        if (x.isNot()) {\n            handleCondition(x.getExpr(), \"NOT IN\", x.getTargetList());\n        } else {\n            handleCondition(x.getExpr(), \"IN\", x.getTargetList());\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLInSubQueryExpr x) {\n        if (x.isNot()) {\n            handleCondition(x.getExpr(), \"NOT IN\");\n        } else {\n            handleCondition(x.getExpr(), \"IN\");\n        }\n        return true;\n    }\n\n    public void endVisit(SQLDeleteStatement x) {\n    }\n\n    public void endVisit(SQLUpdateStatement x) {\n    }\n\n    public boolean visit(SQLCreateTableStatement x) {\n        SQLObject parent = x.getParent();\n        if (repository != null\n                && (parent instanceof SQLBlockStatement || parent == null)) {\n            repository.resolve(x);\n        }\n\n        for (SQLTableElement e : x.getTableElementList()) {\n            e.setParent(x);\n        }\n\n        TableStat stat = getTableStat(x.getName());\n        stat.incrementCreateCount();\n\n        accept(x.getTableElementList());\n\n        if (x.getInherits() != null) {\n            x.getInherits().accept(this);\n        }\n\n        if (x.getSelect() != null) {\n            x.getSelect().accept(this);\n            stat.incrementInsertCount();\n        }\n\n        SQLExprTableSource like = x.getLike();\n        if (like != null) {\n            like.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLColumnDefinition x) {\n        SQLName tableName = null;\n        {\n            SQLObject parent = x.getParent();\n            if (parent instanceof SQLCreateTableStatement) {\n                tableName = ((SQLCreateTableStatement) parent).getName();\n            }\n        }\n\n        if (tableName == null) {\n            return true;\n        }\n\n        String columnName = x.getName().toString();\n        Column column = addColumn(tableName, columnName);\n        if (x.getDataType() != null) {\n            column.setDataType(x.getDataType().getName());\n        }\n\n        for (SQLColumnConstraint item : x.getConstraints()) {\n            if (item instanceof SQLPrimaryKey) {\n                column.setPrimaryKey(true);\n            } else if (item instanceof SQLUnique) {\n                column.setUnique(true);\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCallStatement x) {\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLCommentStatement x) {\n    }\n\n    @Override\n    public boolean visit(SQLCommentStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLCurrentOfCursorExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddColumn x) {\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n        String table = stmt.getName().toString();\n\n        for (SQLColumnDefinition column : x.getColumns()) {\n            String columnName = SQLUtils.normalize(column.getName().toString());\n            addColumn(stmt.getName(), columnName);\n        }\n        return false;\n    }\n\n    @Override\n    public void endVisit(SQLAlterTableAddColumn x) {\n    }\n\n    @Override\n    public boolean visit(SQLRollbackStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLCreateViewStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        SQLSelect subQuery = x.getSubQuery();\n        if (subQuery != null) {\n            subQuery.accept(this);\n        }\n\n        SQLBlockStatement script = x.getScript();\n        if (script != null) {\n            script.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLAlterViewStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        x.getSubQuery().accept(this);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropForeignKey x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDisableConstraint x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableEnableConstraint x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        TableStat stat = getTableStat(x.getName());\n        stat.incrementAlterCount();\n\n        for (SQLAlterTableItem item : x.getItems()) {\n            item.setParent(x);\n            if (item instanceof SQLAlterTableAddPartition\n                    || item instanceof SQLAlterTableRenamePartition\n                    || item instanceof SQLAlterTableMergePartition\n            ) {\n                stat.incrementAddPartitionCount();\n            }\n\n            item.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropConstraint x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropCheck x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropIndexStatement x) {\n        setMode(x, Mode.DropIndex);\n        SQLExprTableSource table = x.getTableName();\n        if (table != null) {\n            SQLName name = (SQLName) table.getExpr();\n            TableStat stat = getTableStat(name);\n            stat.incrementDropIndexCount();\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateIndexStatement x) {\n        setMode(x, Mode.CreateIndex);\n\n        SQLName table = (SQLName) ((SQLExprTableSource) x.getTable()).getExpr();\n        TableStat stat = getTableStat(table);\n        stat.incrementCreateIndexCount();\n\n        for (SQLSelectOrderByItem item : x.getItems()) {\n            SQLExpr expr = item.getExpr();\n            if (expr instanceof SQLIdentifierExpr) {\n                SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;\n                String columnName = identExpr.getName();\n                addColumn(table, columnName);\n            } else if (expr instanceof SQLMethodInvokeExpr) {\n                SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) expr;\n                if (methodInvokeExpr.getArguments().size() == 1) {\n                    SQLExpr param = methodInvokeExpr.getArguments().get(0);\n                    if (param instanceof SQLIdentifierExpr) {\n                        SQLIdentifierExpr identExpr = (SQLIdentifierExpr) param;\n                        String columnName = identExpr.getName();\n                        addColumn(table, columnName);\n                    }\n                }\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLForeignKeyImpl x) {\n        for (SQLName column : x.getReferencingColumns()) {\n            column.accept(this);\n        }\n\n        SQLName table = x.getReferencedTableName();\n\n        TableStat stat = getTableStat(x.getReferencedTableName());\n        stat.incrementReferencedCount();\n        for (SQLName column : x.getReferencedColumns()) {\n            String columnName = column.getSimpleName();\n            addColumn(table, columnName);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropSequenceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropTriggerStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropUserStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLGrantStatement x) {\n        if (x.getResource() != null && (x.getResourceType() == null || x.getResourceType() == SQLObjectType.TABLE)) {\n            x.getResource().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRevokeStatement x) {\n        if (x.getResource() != null) {\n            x.getResource().accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropDatabaseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddIndex x) {\n        for (SQLSelectOrderByItem item : x.getColumns()) {\n            item.accept(this);\n        }\n\n        SQLName table = ((SQLAlterTableStatement) x.getParent()).getName();\n        TableStat tableStat = this.getTableStat(table);\n        tableStat.incrementCreateIndexCount();\n        return false;\n    }\n\n    public boolean visit(SQLCheck x) {\n        x.getExpr().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLDefault x) {\n        x.getExpr().accept(this);\n        x.getColumn().accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLCreateTriggerStatement x) {\n        SQLExprTableSource on = x.getOn();\n        on.accept(this);\n        return false;\n    }\n\n    public boolean visit(SQLDropFunctionStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLDropTableSpaceStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLDropProcedureStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRename x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLArrayExpr x) {\n        accept(x.getValues());\n\n        SQLExpr exp = x.getExpr();\n        if (exp instanceof SQLIdentifierExpr) {\n            if (((SQLIdentifierExpr) exp).getName().equals(\"ARRAY\")) {\n                return false;\n            }\n        }\n        if (exp != null) {\n            exp.accept(this);\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLOpenStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLFetchStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropMaterializedViewStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowMaterializedViewStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLRefreshMaterializedViewStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCloseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateProcedureStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        accept(x.getBlock());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateFunctionStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        accept(x.getBlock());\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLBlockStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        for (SQLParameter param : x.getParameters()) {\n            param.setParent(x);\n            param.accept(this);\n        }\n\n        for (SQLStatement stmt : x.getStatementList()) {\n            stmt.accept(this);\n        }\n\n        SQLStatement exception = x.getException();\n        if (exception != null) {\n            exception.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowTablesStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDeclareItem x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByHash x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByRange x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionByList x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionSingle x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubPartitionByHash x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLPartitionValue x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterDatabaseStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableConvertCharSet x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableReOrganizePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableCoalescePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableTruncatePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDiscardPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableImportPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAnalyzePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableCheckPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableOptimizePartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRebuildPartition x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableRepairPartition x) {\n        return false;\n    }\n\n    public boolean visit(SQLSequenceExpr x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLMergeStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        setMode(x.getUsing(), Mode.Select);\n        x.getUsing().accept(this);\n\n        setMode(x, Mode.Merge);\n\n        SQLTableSource into = x.getInto();\n        if (into instanceof SQLExprTableSource) {\n            String ident = ((SQLExprTableSource) into).getExpr().toString();\n            TableStat stat = getTableStat(ident);\n            stat.incrementMergeCount();\n        } else {\n            into.accept(this);\n        }\n\n        x.getOn().accept(this);\n\n        for (SQLMergeStatement.When when : x.getWhens()) {\n            when.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSetStatement x) {\n        return false;\n    }\n\n    public List<SQLMethodInvokeExpr> getFunctions() {\n        return this.functions;\n    }\n\n    public boolean visit(SQLCreateSequenceStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableAddConstraint x) {\n        SQLConstraint constraint = x.getConstraint();\n        if (constraint instanceof SQLUniqueConstraint) {\n            SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n            TableStat tableStat = this.getTableStat(stmt.getName());\n            tableStat.incrementCreateIndexCount();\n        }\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropIndex x) {\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n        TableStat tableStat = this.getTableStat(stmt.getName());\n        tableStat.incrementDropIndexCount();\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropPrimaryKey x) {\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n        TableStat tableStat = this.getTableStat(stmt.getName());\n        tableStat.incrementDropIndexCount();\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableDropKey x) {\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent();\n        TableStat tableStat = this.getTableStat(stmt.getName());\n        tableStat.incrementDropIndexCount();\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDescribeStatement x) {\n        SQLName tableName = x.getObject();\n\n        TableStat tableStat = this.getTableStat(x.getObject());\n\n        SQLName column = x.getColumn();\n        if (column != null) {\n            String columnName = column.toString();\n            this.addColumn(tableName, columnName);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLExplainStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        if (x.getStatement() != null) {\n            accept(x.getStatement());\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCreateMaterializedViewStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        SQLSelect query = x.getQuery();\n        if (query != null) {\n            query.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLReplaceStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        setMode(x, Mode.Replace);\n\n        SQLName tableName = x.getTableName();\n\n        TableStat stat = getTableStat(tableName);\n\n        if (stat != null) {\n            stat.incrementInsertCount();\n        }\n\n        accept(x.getColumns());\n        accept(x.getValuesList());\n        accept(x.getQuery());\n\n        return false;\n    }\n\n    protected final void statExpr(SQLExpr x) {\n        if (x == null) {\n            return;\n        }\n\n        Class<?> clazz = x.getClass();\n        if (clazz == SQLIdentifierExpr.class) {\n            visit((SQLIdentifierExpr) x);\n        } else if (clazz == SQLPropertyExpr.class) {\n            visit((SQLPropertyExpr) x);\n//        } else if (clazz == SQLAggregateExpr.class) {\n//            visit((SQLAggregateExpr) x);\n        } else if (clazz == SQLBinaryOpExpr.class) {\n            visit((SQLBinaryOpExpr) x);\n//        } else if (clazz == SQLCharExpr.class) {\n//            visit((SQLCharExpr) x);\n//        } else if (clazz == SQLNullExpr.class) {\n//            visit((SQLNullExpr) x);\n//        } else if (clazz == SQLIntegerExpr.class) {\n//            visit((SQLIntegerExpr) x);\n//        } else if (clazz == SQLNumberExpr.class) {\n//            visit((SQLNumberExpr) x);\n//        } else if (clazz == SQLMethodInvokeExpr.class) {\n//            visit((SQLMethodInvokeExpr) x);\n//        } else if (clazz == SQLVariantRefExpr.class) {\n//            visit((SQLVariantRefExpr) x);\n//        } else if (clazz == SQLBinaryOpExprGroup.class) {\n//            visit((SQLBinaryOpExprGroup) x);\n        } else if (x instanceof SQLLiteralExpr) {\n            // skip\n        } else {\n            x.accept(this);\n        }\n    }\n\n    public boolean visit(SQLAlterFunctionStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLDropSynonymStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLAlterTypeStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLAlterProcedureStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLExprStatement x) {\n        SQLExpr expr = x.getExpr();\n\n        if (expr instanceof SQLName) {\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLDropTypeStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExternalRecordFormat x) {\n        return false;\n    }\n\n    public boolean visit(SQLCreateDatabaseStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLCreateTableGroupStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLDropTableGroupStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowDatabasesStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLShowColumnsStatement x) {\n        SQLName table = x.getTable();\n\n        TableStat stat = getTableStat(table);\n        if (stat != null) {\n//            stat.incrementSh\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLShowCreateTableStatement x) {\n        SQLName table = x.getName();\n\n        if (table != null) {\n            TableStat stat = getTableStat(table);\n            if (stat != null) {\n//            stat.incrementSh\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLShowTableGroupsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableSetOption x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowCreateViewStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCreateRoleStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDropRoleStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLShowViewsStatement x) {\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLAlterTableExchangePartition x) {\n        SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            table.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLDropCatalogStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLUnionQuery x) {\n        SQLUnionOperator operator = x.getOperator();\n        List<SQLSelectQuery> relations = x.getRelations();\n        if (relations.size() > 2) {\n            for (SQLSelectQuery relation : x.getRelations()) {\n                relation.accept(this);\n            }\n            return false;\n        }\n\n        SQLSelectQuery left = x.getLeft();\n        SQLSelectQuery right = x.getRight();\n\n        boolean bracket = x.isParenthesized() && !(x.getParent() instanceof SQLUnionQueryTableSource);\n\n        if ((!bracket)\n                && left instanceof SQLUnionQuery\n                && ((SQLUnionQuery) left).getOperator() == operator\n                && !right.isParenthesized()\n                && x.getOrderBy() == null) {\n            SQLUnionQuery leftUnion = (SQLUnionQuery) left;\n\n            List<SQLSelectQuery> rights = new ArrayList<SQLSelectQuery>();\n            rights.add(right);\n\n            if (leftUnion.getRelations().size() > 2) {\n                rights.addAll(leftUnion.getRelations());\n            } else {\n                for (; ; ) {\n                    SQLSelectQuery leftLeft = leftUnion.getLeft();\n                    SQLSelectQuery leftRight = leftUnion.getRight();\n\n                    if ((!leftUnion.isParenthesized())\n                            && leftUnion.getOrderBy() == null\n                            && (!leftLeft.isParenthesized())\n                            && (!leftRight.isParenthesized())\n                            && leftLeft instanceof SQLUnionQuery\n                            && ((SQLUnionQuery) leftLeft).getOperator() == operator) {\n                        rights.add(leftRight);\n                        leftUnion = (SQLUnionQuery) leftLeft;\n                        continue;\n                    } else {\n                        rights.add(leftRight);\n                        rights.add(leftLeft);\n                    }\n                    break;\n                }\n            }\n\n            for (int i = rights.size() - 1; i >= 0; i--) {\n                SQLSelectQuery item = rights.get(i);\n                item.accept(this);\n            }\n            return false;\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLValuesTableSource x) {\n        return false;\n    }\n\n    public boolean visit(SQLAlterIndexStatement x) {\n        final SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            table.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLShowIndexesStatement x) {\n        final SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            table.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLAnalyzeTableStatement x) {\n        for (SQLExprTableSource table : x.getTables()) {\n            if (table != null) {\n                TableStat stat = getTableStat(table.getName());\n                if (stat != null) {\n                    stat.incrementAnalyzeCount();\n                }\n            }\n        }\n\n        SQLExprTableSource table = x.getTables().size() == 1 ? x.getTables().get(0) : null;\n\n        SQLPartitionRef partition = x.getPartition();\n        if (partition != null) {\n            for (SQLPartitionRef.Item item : partition.getItems()) {\n                SQLIdentifierExpr columnName = item.getColumnName();\n                columnName.setResolvedTableSource(table);\n                columnName.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLExportTableStatement x) {\n        final SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            table.accept(this);\n        }\n\n        for (SQLAssignItem item : x.getPartition()) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                ((SQLIdentifierExpr) target).setResolvedTableSource(table);\n                target.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLImportTableStatement x) {\n        final SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            table.accept(this);\n        }\n\n        for (SQLAssignItem item : x.getPartition()) {\n            final SQLExpr target = item.getTarget();\n            if (target instanceof SQLIdentifierExpr) {\n                ((SQLIdentifierExpr) target).setResolvedTableSource(table);\n                target.accept(this);\n            }\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLCreateOutlineStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        if (x.getOn() != null) {\n            x.getOn().accept(this);\n        }\n\n        if (x.getTo() != null) {\n            x.getTo().accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLDumpStatement x) {\n        if (repository != null\n                && x.getParent() == null) {\n            repository.resolve(x);\n        }\n\n        final SQLExprTableSource into = x.getInto();\n        if (into != null) {\n            into.accept(this);\n        }\n\n        final SQLSelect select = x.getSelect();\n        if (select != null) {\n            select.accept(this);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLDropOutlineStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLAlterOutlineStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLAlterTableArchivePartition x) {\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLCopyFromStatement x) {\n        SQLExprTableSource table = x.getTable();\n        if (table != null) {\n            table.accept(this);\n            for (SQLName column : x.getColumns()) {\n                addColumn(table.getName(), column.getSimpleName());\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLCloneTableStatement x) {\n        SQLExprTableSource from = x.getFrom();\n        if (from != null) {\n            TableStat stat = getTableStat(from.getName());\n            if (stat != null) {\n                stat.incrementSelectCount();\n            }\n        }\n\n        SQLExprTableSource to = x.getTo();\n        if (to != null) {\n            TableStat stat = getTableStat(to.getName());\n            if (stat != null) {\n                stat.incrementInsertCount();\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSyncMetaStatement x) {\n        return false;\n    }\n\n    public List<SQLName> getOriginalTables() {\n        return originalTables;\n    }\n\n    @Override\n    public boolean visit(SQLUnique x) {\n        for (SQLSelectOrderByItem column : x.getColumns()) {\n            column.accept(this);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLSavePointStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLShowPartitionsStmt x) {\n        setMode(x, Mode.DESC);\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/VisitorFeature.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor;\n\npublic enum VisitorFeature {\n    OutputUCase,\n    OutputPrettyFormat,\n    OutputParameterized,\n    OutputDesensitize,\n    OutputUseInsertValueClauseOriginalString,\n    OutputSkipSelectListCacheString,\n    OutputSkipInsertColumnsString,\n    OutputParameterizedQuesUnMergeInList,\n    OutputParameterizedQuesUnMergeOr,\n    OutputParameterizedQuesUnMergeAnd,\n    OutputParameterizedQuesUnMergeValuesList,\n    OutputParameterizedUnMergeShardingTable,\n    OutputParameterizedUnMergeZero,\n    OutputParameterizedUnMergeOne,\n    OutputParameterizedUnMergeIn,\n    OutputParameterizedZeroReplaceNotUseOriginalSql,\n    OutputRegForPresto,\n    /**\n     * @deprecated\n     */\n    OutputKeepParenthesisWhenNotExpr,\n\n    OutputNameQuote,\n    OutputDistributedLiteralInCreateTableStmt,\n    OutputSkipMultilineComment,\n    OutputSkipSingleLineComment;\n\n    private VisitorFeature() {\n        mask = (1 << ordinal());\n    }\n\n    public final int mask;\n\n    public static boolean isEnabled(int features, VisitorFeature feature) {\n        return (features & feature.mask) != 0;\n    }\n\n    public static int config(int features, VisitorFeature feature, boolean state) {\n        if (state) {\n            features |= feature.mask;\n        } else {\n            features &= ~feature.mask;\n        }\n\n        return features;\n    }\n\n    public static int of(VisitorFeature... features) {\n        if (features == null) {\n            return 0;\n        }\n\n        int value = 0;\n\n        for (VisitorFeature feature : features) {\n            value |= feature.mask;\n        }\n\n        return value;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Ascii.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE_NULL;\n\npublic class Ascii implements Function {\n    public static final Ascii instance = new Ascii();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().isEmpty()) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n        SQLExpr param = x.getArguments().get(0);\n        param.accept(visitor);\n\n        Object paramValue = param.getAttributes().get(EVAL_VALUE);\n        if (paramValue == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        if (paramValue == EVAL_VALUE_NULL) {\n            return EVAL_VALUE_NULL;\n        }\n\n        String strValue = paramValue.toString();\n        if (strValue.length() == 0) {\n            return 0;\n        }\n\n        int ascii = strValue.charAt(0);\n        return ascii;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Bin.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Bin implements Function {\n    public static final Bin instance = new Bin();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        if (param0Value instanceof Number) {\n            long longValue = ((Number) param0Value).longValue();\n            String result = Long.toString(longValue, 2);\n            return result;\n        }\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/BitLength.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class BitLength implements Function {\n    public static final BitLength instance = new BitLength();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        if (param0Value instanceof String) {\n            return ((String) param0Value).getBytes().length * 8;\n        }\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Char.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.math.BigDecimal;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Char implements Function {\n    public static final Char instance = new Char();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().isEmpty()) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        StringBuilder buf = new StringBuilder(x.getArguments().size());\n        for (SQLExpr param : x.getArguments()) {\n            param.accept(visitor);\n\n            Object paramValue = param.getAttributes().get(EVAL_VALUE);\n\n            if (paramValue instanceof Number) {\n                int charCode = ((Number) paramValue).intValue();\n                buf.append((char) charCode);\n            } else if (paramValue instanceof String) {\n                try {\n                    int charCode = new BigDecimal((String) paramValue).intValue();\n                    buf.append((char) charCode);\n                } catch (NumberFormatException e) {\n                }\n            } else {\n                return SQLEvalVisitor.EVAL_ERROR;\n            }\n        }\n\n        return buf.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Concat.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Concat implements Function {\n    public static final Concat instance = new Concat();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        StringBuilder buf = new StringBuilder();\n\n        for (SQLExpr item : x.getArguments()) {\n            item.accept(visitor);\n\n            Object itemValue = item.getAttribute(EVAL_VALUE);\n            if (itemValue == null) {\n                return null;\n            }\n            buf.append(itemValue.toString());\n        }\n\n        return buf.toString();\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        StringBuilder buf = new StringBuilder();\n        for (SQLExpr param : x.getArguments()) {\n            if (param instanceof SQLValuableExpr) {\n                Object val = ((SQLValuableExpr) param).getValue();\n                if (val instanceof String) {\n                    buf.append(val);\n                    continue;\n                } else if (val instanceof Integer) {\n                    buf.append(val);\n                    continue;\n                }\n            }\n\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        return buf.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/DateAdd.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_ERROR;\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class DateAdd implements Function {\n    public static final DateAdd instance = new DateAdd();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.size() != 3) {\n            return EVAL_ERROR;\n        }\n\n        for (SQLExpr arg : arguments) {\n            arg.accept(visitor);\n        }\n\n        Object v0 = arguments.get(0).getAttributes().get(EVAL_VALUE);\n        Object v1 = arguments.get(1).getAttributes().get(EVAL_VALUE);\n        Object v2 = arguments.get(2).getAttributes().get(EVAL_VALUE);\n\n        if (v0 instanceof Date\n                && v1 instanceof Integer\n                && v2 instanceof String) {\n            Date date = (Date) v0;\n            int delta = ((Integer) v1);\n\n            if (\"day\".equalsIgnoreCase((String) v2)) {\n                Calendar calendar = Calendar.getInstance();\n                calendar.setTime(date);\n                calendar.add(Calendar.DAY_OF_MONTH, delta);\n\n                return calendar.getTime();\n            }\n\n        }\n\n        SQLExpr arg = arguments.get(0);\n        arg.accept(visitor);\n        Object itemValue = arg.getAttributes().get(EVAL_VALUE);\n        if (itemValue == null) {\n            return null;\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Elt.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Elt implements Function {\n    public static final Elt instance = new Elt();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() <= 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttribute(EVAL_VALUE);\n        int param0IntValue;\n        if (!(param0Value instanceof Number)) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n        param0IntValue = ((Number) param0Value).intValue();\n\n        if (param0IntValue >= x.getArguments().size()) {\n            return SQLEvalVisitor.EVAL_VALUE_NULL;\n        }\n\n        SQLExpr item = x.getArguments().get(param0IntValue);\n        item.accept(visitor);\n\n        Object itemValue = item.getAttributes().get(EVAL_VALUE);\n        return itemValue;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Function.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\npublic interface Function {\n    Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Greatest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Greatest implements Function {\n    public static final Greatest instance = new Greatest();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        Object result = null;\n        for (SQLExpr item : x.getArguments()) {\n            item.accept(visitor);\n\n            Object itemValue = item.getAttributes().get(EVAL_VALUE);\n            if (result == null) {\n                result = itemValue;\n            } else {\n                if (SQLEvalVisitorUtils.gt(itemValue, result)) {\n                    result = itemValue;\n                }\n            }\n        }\n\n        return result;\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        List<SQLExpr> parameters = x.getArguments();\n\n        if (parameters.size() > 0) {\n            SQLExpr p0 = parameters.get(0);\n            if (p0 instanceof SQLIntegerExpr && ((SQLIntegerExpr) p0).getNumber() instanceof Integer) {\n                int val = ((SQLIntegerExpr) p0).getNumber().intValue();\n                for (int i = 1; i < parameters.size(); i++) {\n                    SQLExpr param = parameters.get(i);\n                    if (param instanceof SQLIntegerExpr && ((SQLIntegerExpr) param).getNumber() instanceof Integer) {\n                        int paramVal = ((SQLIntegerExpr) param).getNumber().intValue();\n                        if (paramVal > val) {\n                            val = paramVal;\n                        }\n                    } else {\n                        return SQLEvalVisitor.EVAL_ERROR;\n                    }\n                }\n                return val;\n            }\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Hex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.util.HexBin;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Hex implements Function {\n    public static final Hex instance = new Hex();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            throw new ParserException(\"argument's != 1, \" + x.getArguments().size());\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        if (param0Value instanceof String) {\n            byte[] bytes = ((String) param0Value).getBytes();\n            String result = HexBin.encode(bytes);\n            return result;\n        }\n\n        if (param0Value instanceof Number) {\n            long value = ((Number) param0Value).longValue();\n            String result = Long.toHexString(value).toUpperCase();\n            return result;\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/If.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_ERROR;\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class If implements Function {\n    public static final If instance = new If();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.isEmpty()) {\n            return EVAL_ERROR;\n        }\n\n        SQLExpr condition = arguments.get(0);\n        condition.accept(visitor);\n        Object itemValue = condition.getAttributes().get(EVAL_VALUE);\n        if (itemValue == null) {\n            return null;\n        }\n        if (Boolean.TRUE.equals(itemValue) || !SQLEvalVisitorUtils.eq(itemValue, 0)) {\n            SQLExpr trueExpr = arguments.get(1);\n            trueExpr.accept(visitor);\n            return trueExpr.getAttributes().get(EVAL_VALUE);\n        } else {\n            SQLExpr falseExpr = arguments.get(2);\n            falseExpr.accept(visitor);\n            return falseExpr.getAttributes().get(EVAL_VALUE);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/IfNull.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_ERROR;\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class IfNull implements Function {\n    public static final IfNull instance = new IfNull();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.size() != 2) {\n            return EVAL_ERROR;\n        }\n\n        SQLExpr condition = arguments.get(0);\n        condition.accept(visitor);\n\n        Object itemValue = condition.getAttributes().get(EVAL_VALUE);\n        if (itemValue == null) {\n            SQLExpr valueExpr = arguments.get(1);\n            valueExpr.accept(visitor);\n            return valueExpr.getAttributes().get(EVAL_VALUE);\n        } else {\n            return itemValue;\n        }\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        List<SQLExpr> arguments = x.getArguments();\n\n        if (arguments.size() != 2) {\n            return EVAL_ERROR;\n        }\n\n        SQLExpr condition = arguments.get(0);\n        SQLExpr valueExpr = arguments.get(1);\n\n        if (condition instanceof SQLValuableExpr && valueExpr instanceof SQLValuableExpr) {\n            Object itemValue = ((SQLValuableExpr) condition).getValue();\n            if (itemValue == null || itemValue == SQLEvalVisitor.EVAL_VALUE_NULL) {\n                return ((SQLValuableExpr) valueExpr).getValue();\n            } else {\n                return itemValue;\n            }\n        }\n        return EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Insert.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Insert implements Function {\n    public static final Insert instance = new Insert();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 4) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        SQLExpr param1 = x.getArguments().get(1);\n        SQLExpr param2 = x.getArguments().get(2);\n        SQLExpr param3 = x.getArguments().get(3);\n        param0.accept(visitor);\n        param1.accept(visitor);\n        param2.accept(visitor);\n        param3.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        Object param2Value = param2.getAttributes().get(EVAL_VALUE);\n        Object param3Value = param3.getAttributes().get(EVAL_VALUE);\n\n        if (!(param0Value instanceof String)) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n        if (!(param1Value instanceof Number)) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n        if (!(param2Value instanceof Number)) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n        if (!(param3Value instanceof String)) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String str = (String) param0Value;\n        int pos = ((Number) param1Value).intValue();\n        int len = ((Number) param2Value).intValue();\n        String newstr = (String) param3Value;\n\n        if (pos <= 0) {\n            return str;\n        }\n\n        if (pos == 1) {\n            if (len > str.length()) {\n                return newstr;\n            }\n            return newstr + str.substring(len);\n        }\n\n        String first = str.substring(0, pos - 1);\n        if (pos + len - 1 > str.length()) {\n            return first + newstr;\n        }\n\n        return first + newstr + str.substring(pos + len - 1);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Instr.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Instr implements Function {\n    public static final Instr instance = new Instr();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 2) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        SQLExpr param1 = x.getArguments().get(1);\n        param0.accept(visitor);\n        param1.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null || param1Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue0 = param0Value.toString();\n        String strValue1 = param1Value.toString();\n\n        int result = strValue0.indexOf(strValue1) + 1;\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Isnull.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.*;\n\npublic class Isnull implements Function {\n    public static final Isnull instance = new Isnull();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.isEmpty()) {\n            return EVAL_ERROR;\n        }\n\n        SQLExpr condition = arguments.get(0);\n        condition.accept(visitor);\n        Object itemValue = condition.getAttributes().get(EVAL_VALUE);\n        if (itemValue == EVAL_VALUE_NULL) {\n            return Boolean.TRUE;\n        } else if (itemValue == null) {\n            return null;\n        } else {\n            return Boolean.FALSE;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Lcase.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Lcase implements Function {\n    public static final Lcase instance = new Lcase();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n\n        String result = strValue.toLowerCase();\n\n        return result;\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        List<SQLExpr> arguments = x.getArguments();\n        if (arguments.size() == 1) {\n            Object p0 = ((SQLValuableExpr) arguments.get(0)).getValue();\n\n            if (p0 instanceof String) {\n                String str = (String) p0;\n                return str.toLowerCase();\n            }\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Least.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Least implements Function {\n    public static final Least instance = new Least();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        Object result = null;\n        for (SQLExpr item : x.getArguments()) {\n            item.accept(visitor);\n\n            Object itemValue = item.getAttributes().get(EVAL_VALUE);\n            if (result == null) {\n                result = itemValue;\n            } else {\n                if (SQLEvalVisitorUtils.lt(itemValue, result)) {\n                    result = itemValue;\n                }\n            }\n        }\n\n        return result;\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        List<SQLExpr> arguments = x.getArguments();\n\n        if (arguments.size() > 0) {\n            SQLExpr p0 = arguments.get(0);\n            if (p0 instanceof SQLIntegerExpr && ((SQLIntegerExpr) p0).getNumber() instanceof Integer) {\n                int val = ((SQLIntegerExpr) p0).getNumber().intValue();\n                for (int i = 1; i < arguments.size(); i++) {\n                    SQLExpr param = arguments.get(i);\n                    if (param instanceof SQLIntegerExpr && ((SQLIntegerExpr) param).getNumber() instanceof Integer) {\n                        int paramVal = ((SQLIntegerExpr) param).getNumber().intValue();\n                        if (paramVal < val) {\n                            val = paramVal;\n                        }\n                    } else {\n                        return SQLEvalVisitor.EVAL_ERROR;\n                    }\n                }\n                return val;\n            }\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Left.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Left implements Function {\n    public static final Left instance = new Left();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 2) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        SQLExpr param1 = x.getArguments().get(1);\n        param0.accept(visitor);\n        param1.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null || param1Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n        int intValue = SQLEvalVisitorUtils.castToInteger(param1Value);\n\n        if (intValue > strValue.length()) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String result = strValue.substring(0, intValue);\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Length.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Length implements Function {\n    public static final Length instance = new Length();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n\n        int result = strValue.length();\n        return result;\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        List<SQLExpr> parameters = x.getArguments();\n        if (parameters.size() == 1) {\n            Object p0 = ((SQLValuableExpr) parameters.get(0)).getValue();\n\n            if (p0 instanceof String) {\n                String str = (String) p0;\n                return str.length();\n            }\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Locate.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Locate implements Function {\n    public static final Locate instance = new Locate();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        List<SQLExpr> params = x.getArguments();\n        int paramSize = params.size();\n        if (paramSize != 2 && paramSize != 3) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = params.get(0);\n        SQLExpr param1 = params.get(1);\n        SQLExpr param2 = null;\n\n        param0.accept(visitor);\n        param1.accept(visitor);\n        if (paramSize == 3) {\n            param2 = params.get(2);\n            param2.accept(visitor);\n        }\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null || param1Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue0 = param0Value.toString();\n        String strValue1 = param1Value.toString();\n\n        if (paramSize == 2) {\n            int result = strValue1.indexOf(strValue0) + 1;\n            return result;\n        }\n\n        Object param2Value = param2.getAttributes().get(EVAL_VALUE);\n        int start = ((Number) param2Value).intValue();\n\n        int result = strValue1.indexOf(strValue0, start + 1) + 1;\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Lpad.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Lpad implements Function {\n    public static final Lpad instance = new Lpad();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        List<SQLExpr> params = x.getArguments();\n        int paramSize = params.size();\n        if (paramSize != 3) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = params.get(0);\n        SQLExpr param1 = params.get(1);\n        SQLExpr param2 = params.get(2);\n\n        param0.accept(visitor);\n        param1.accept(visitor);\n        param2.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        Object param2Value = param2.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null || param1Value == null || param2Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue0 = param0Value.toString();\n        int len = ((Number) param1Value).intValue();\n        String strValue1 = param2Value.toString();\n\n        if (strValue0.length() > len) {\n            return strValue0.substring(0, len);\n        }\n        if (strValue0.length() == len) {\n            return strValue0;\n        }\n        int needLen = len - strValue0.length();\n        StringBuilder result = new StringBuilder(len);\n        while (result.length() < needLen) {\n            result.insert(0, strValue1);\n        }\n        if (result.length() > needLen) {\n            result.delete(needLen, result.length());\n        }\n        result.append(strValue0);\n        return result.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Ltrim.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Ltrim implements Function {\n    public static final Ltrim instance = new Ltrim();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n\n        int index = -1;\n        for (int i = 0; i < strValue.length(); ++i) {\n            if (!Character.isWhitespace(strValue.charAt(i))) {\n                index = i;\n                break;\n            }\n        }\n\n        if (index <= 0) {\n            return strValue;\n        } else {\n            return strValue.substring(index);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Nil.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\npublic class Nil implements Function {\n    public static final Nil instance = new Nil();\n\n    @Override\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Now.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.Date;\n\npublic class Now implements Function {\n    public static final Now instance = new Now();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        return new Date();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/OneParamFunctions.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE_NULL;\n\npublic class OneParamFunctions implements Function {\n    public static final OneParamFunctions instance = new OneParamFunctions();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().isEmpty()) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param = x.getArguments().get(0);\n        param.accept(visitor);\n\n        Object paramValue = param.getAttributes().get(EVAL_VALUE);\n        if (paramValue == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        if (paramValue == EVAL_VALUE_NULL) {\n            return EVAL_VALUE_NULL;\n        }\n\n        String method = x.getMethodName();\n        if (\"md5\".equalsIgnoreCase(method)) {\n            String text = paramValue.toString();\n            return Utils.md5(text);\n        }\n\n        if (\"bit_count\".equalsIgnoreCase(method)) {\n            if (paramValue instanceof BigInteger) {\n                return ((BigInteger) paramValue).bitCount();\n            }\n\n            if (paramValue instanceof BigDecimal) {\n                BigDecimal decimal = (BigDecimal) paramValue;\n                BigInteger bigInt = decimal.setScale(0, BigDecimal.ROUND_HALF_UP).toBigInteger();\n                return bigInt.bitCount();\n            }\n            Long val = SQLEvalVisitorUtils.castToLong(paramValue);\n            return Long.bitCount(val);\n        }\n\n        if (\"soundex\".equalsIgnoreCase(method)) {\n            String text = paramValue.toString();\n            return soundex(text);\n        }\n\n        if (\"space\".equalsIgnoreCase(method)) {\n            int intVal = SQLEvalVisitorUtils.castToInteger(paramValue);\n            char[] chars = new char[intVal];\n            for (int i = 0; i < chars.length; ++i) {\n                chars[i] = ' ';\n            }\n            return new String(chars);\n        }\n\n        throw new UnsupportedOperationException(method);\n    }\n\n    public static String soundex(String str) {\n        if (str == null) {\n            return null;\n        }\n        str = clean(str);\n        if (str.length() == 0) {\n            return str;\n        }\n        char[] out = {'0', '0', '0', '0'};\n        char last, mapped;\n        int incount = 1, count = 1;\n        out[0] = str.charAt(0);\n        // getMappingCode() throws IllegalArgumentException\n        last = getMappingCode(str, 0);\n        while ((incount < str.length()) && (count < out.length)) {\n            mapped = getMappingCode(str, incount++);\n            if (mapped != 0) {\n                if ((mapped != '0') && (mapped != last)) {\n                    out[count++] = mapped;\n                }\n                last = mapped;\n            }\n        }\n        return new String(out);\n    }\n\n    static String clean(String str) {\n        if (str == null || str.length() == 0) {\n            return str;\n        }\n        int len = str.length();\n        char[] chars = new char[len];\n        int count = 0;\n        for (int i = 0; i < len; i++) {\n            if (Character.isLetter(str.charAt(i))) {\n                chars[count++] = str.charAt(i);\n            }\n        }\n        if (count == len) {\n            return str.toUpperCase(java.util.Locale.ENGLISH);\n        }\n        return new String(chars, 0, count).toUpperCase(java.util.Locale.ENGLISH);\n    }\n\n    private static char getMappingCode(String str, int index) {\n        // map() throws IllegalArgumentException\n        char mappedChar = map(str.charAt(index));\n        // HW rule check\n        if (index > 1 && mappedChar != '0') {\n            char hwChar = str.charAt(index - 1);\n            if ('H' == hwChar || 'W' == hwChar) {\n                char preHWChar = str.charAt(index - 2);\n                char firstCode = map(preHWChar);\n                if (firstCode == mappedChar || 'H' == preHWChar || 'W' == preHWChar) {\n                    return 0;\n                }\n            }\n        }\n        return mappedChar;\n    }\n\n    private static char map(char ch) {\n        String soundexMapping = \"01230120022455012623010202\";\n        int index = ch - 'A';\n        if (index < 0 || index >= soundexMapping.length()) {\n            throw new IllegalArgumentException(\"The character is not mapped: \" + ch);\n        }\n        return soundexMapping.charAt(index);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Replace.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://github.com/alibaba/druid/issues/5477\">Issue来源</a>\n * @see <a href=\"https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_replace\">mysql replace函数</a>\n */\npublic class Replace implements Function {\n    public static final Replace instance = new Replace();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 3) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n        List<String> list = new ArrayList<>();\n        for (SQLExpr item : x.getArguments()) {\n            item.accept(visitor);\n            Object param0Value = item.getAttributes().get(EVAL_VALUE);\n            if (param0Value == null) {\n                return SQLEvalVisitor.EVAL_ERROR;\n            }\n            String strValue = null;\n            if (param0Value != null && param0Value != SQLEvalVisitor.EVAL_VALUE_NULL) {\n                strValue = param0Value.toString();\n            }\n            list.add(strValue);\n        }\n        if (list.get(0) == null || list.get(1) == null || list.get(2) == null) {\n            return list.get(0);\n        }\n        //暂时使用java String的replace方法,mysql replace函数是不支持正则表达式的\n        return StringUtils.replaceAll(list.get(0), list.get(1), list.get(2));\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Reverse.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Reverse implements Function {\n    public static final Reverse instance = new Reverse();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n\n        StringBuilder buf = new StringBuilder();\n        for (int i = strValue.length() - 1; i >= 0; --i) {\n            buf.append(strValue.charAt(i));\n        }\n        String result = buf.toString();\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Right.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Right implements Function {\n    public static final Right instance = new Right();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 2) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        SQLExpr param1 = x.getArguments().get(1);\n        param0.accept(visitor);\n        param1.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null || param1Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n        int intValue = SQLEvalVisitorUtils.castToInteger(param1Value);\n\n        int start = strValue.length() - intValue;\n        if (start < 0) {\n            start = 0;\n        }\n        String result = strValue.substring(start, strValue.length());\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Rpad.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_rpad\">MySQL rapd</a>\n */\npublic class Rpad implements Function {\n    public static final Rpad instance = new Rpad();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        List<SQLExpr> params = x.getArguments();\n        int paramSize = params.size();\n        if (paramSize != 3) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = params.get(0);\n        SQLExpr param1 = params.get(1);\n        SQLExpr param2 = params.get(2);\n\n        param0.accept(visitor);\n        param1.accept(visitor);\n        param2.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        Object param2Value = param2.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null || param1Value == null || param2Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue0 = param0Value.toString();\n        int len = ((Number) param1Value).intValue();\n        String strValue1 = param2Value.toString();\n\n        if (strValue0.length() > len) {\n            return strValue0.substring(0, len);\n        }\n        if (strValue0.length() == len) {\n            return strValue0;\n        }\n        StringBuilder result = new StringBuilder(strValue0);\n        while (result.length() < len) {\n            result.append(strValue1);\n        }\n        if (result.length() > len) {\n            result.delete(len, result.length());\n        }\n        return result.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Substring.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Substring implements Function {\n    public static final Substring instance = new Substring();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        List<SQLExpr> params = x.getArguments();\n        int paramSize = params.size();\n\n        SQLExpr param0 = params.get(0);\n\n        SQLExpr param1;\n        if (paramSize == 1 && x.getFrom() != null) {\n            param1 = x.getFrom();\n            paramSize = 2;\n        } else if (paramSize != 2 && paramSize != 3) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        } else {\n            param1 = params.get(1);\n        }\n\n        param0.accept(visitor);\n        param1.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        Object param1Value = param1.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null || param1Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String str = param0Value.toString();\n        int index = ((Number) param1Value).intValue();\n\n        if (paramSize == 2 && x.getFor() == null) {\n            if (index <= 0) {\n                int lastIndex = str.length() + index;\n                return str.substring(lastIndex);\n            }\n\n            return str.substring(index - 1);\n        }\n\n        SQLExpr param2 = x.getFor();\n        if (param2 == null && params.size() > 2) {\n            param2 = params.get(2);\n        }\n        param2.accept(visitor);\n        Object param2Value = param2.getAttributes().get(EVAL_VALUE);\n        if (param2Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        int len = ((Number) param2Value).intValue();\n\n        String result;\n        if (index <= 0) {\n            int lastIndex = str.length() + index;\n            result = str.substring(lastIndex);\n        } else {\n            result = str.substring(index - 1);\n        }\n\n        if (len > result.length()) {\n            return result;\n        }\n        return result.substring(0, len);\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        List<SQLExpr> parameters = x.getArguments();\n        for (SQLExpr parameter : parameters) {\n            if (!(parameter instanceof SQLValuableExpr)) {\n                return null;\n            }\n        }\n\n        if (parameters.size() == 3) {\n            Object p0 = ((SQLValuableExpr) parameters.get(0)).getValue();\n            Object p1 = ((SQLValuableExpr) parameters.get(1)).getValue();\n            Object p2 = ((SQLValuableExpr) parameters.get(2)).getValue();\n\n            if (p0 instanceof Number) {\n                p0 = p0.toString();\n            }\n\n            if (p0 instanceof String\n                    && p1 instanceof Integer\n                    && p2 instanceof Integer) {\n                String str = (String) p0;\n                int beginIndex = ((Integer) p1).intValue();\n                int len = ((Integer) p2).intValue();\n                if (len < 0) {\n                    return null;\n                }\n\n                int start = beginIndex - 1, end = beginIndex - 1 + len;\n\n                if (start < 0 || start >= str.length()) {\n                    return null;\n                }\n                if (end < 0 || end >= str.length()) {\n                    return null;\n                }\n\n                if (beginIndex > 0 && len > 0) {\n                    return str.substring(start, end);\n                }\n            }\n        } else if (parameters.size() == 2) {\n            Object p0 = ((SQLValuableExpr) parameters.get(0)).getValue();\n            Object p1 = ((SQLValuableExpr) parameters.get(1)).getValue();\n\n            if (p0 instanceof String\n                    && p1 instanceof Integer) {\n                String str = (String) p0;\n                int beginIndex = ((Integer) p1).intValue();\n                if (beginIndex < 0 || beginIndex >= str.length()) {\n                    return null;\n                }\n                if (beginIndex > 0) {\n                    return str.substring(beginIndex - 1);\n                }\n            }\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/ToChar.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_ERROR;\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class ToChar implements Function {\n    public static final ToChar instance = new ToChar();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.size() != 2) {\n            return EVAL_ERROR;\n        }\n\n        for (SQLExpr arg : arguments) {\n            arg.accept(visitor);\n        }\n\n        Object v0 = arguments.get(0).getAttributes().get(EVAL_VALUE);\n        Object v1 = arguments.get(1).getAttributes().get(EVAL_VALUE);\n        if (v0 instanceof Date && v1 instanceof String) {\n            Date date = ((Date) v0);\n\n            String format = ((SQLCharExpr) arguments.get(1)).getText();\n            if (format.equals(\"yyyymmdd\")) {\n                SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyyMMdd\");\n                return dateFormat.format(date);\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/ToDate.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLCharExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_ERROR;\n\npublic class ToDate implements Function {\n    public static final ToDate instance = new ToDate();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        final List<SQLExpr> arguments = x.getArguments();\n        if (arguments.isEmpty()) {\n            return EVAL_ERROR;\n        }\n\n        if (arguments.size() == 2\n                && arguments.get(0) instanceof SQLCharExpr\n                && arguments.get(1) instanceof SQLCharExpr) {\n            String chars = ((SQLCharExpr) arguments.get(0)).getText();\n            String format = ((SQLCharExpr) arguments.get(1)).getText();\n            if (format.equals(\"yyyymmdd\")) {\n                SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyyMMdd\");\n                try {\n                    return dateFormat.parse(chars);\n                } catch (ParseException e) {\n                    // skip\n                    return false;\n                }\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Trim.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Trim implements Function {\n    public static final Trim instance = new Trim();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n        String result = strValue.trim();\n        return result;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Ucase.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\n\nimport java.util.List;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Ucase implements Function {\n    public static final Ucase instance = new Ucase();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        String strValue = param0Value.toString();\n\n        String result = strValue.toUpperCase();\n        return result;\n    }\n\n    public Object eval(SQLMethodInvokeExpr x) {\n        List<SQLExpr> parameters = x.getArguments();\n        if (parameters.size() == 1) {\n            Object p0 = ((SQLValuableExpr) parameters.get(0)).getValue();\n\n            if (p0 instanceof String) {\n                String str = (String) p0;\n                return str.toUpperCase();\n            }\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/sql/visitor/functions/Unhex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.sql.visitor.functions;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.util.HexBin;\n\nimport java.nio.charset.StandardCharsets;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_EXPR;\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class Unhex implements Function {\n    public static final Unhex instance = new Unhex();\n\n    public Object eval(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {\n        if (x.getArguments().size() != 1) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        SQLExpr param0 = x.getArguments().get(0);\n\n        if (param0 instanceof SQLMethodInvokeExpr) {\n            SQLMethodInvokeExpr paramMethodExpr = (SQLMethodInvokeExpr) param0;\n            if (paramMethodExpr.getMethodName().equalsIgnoreCase(\"hex\")) {\n                SQLExpr subParamExpr = paramMethodExpr.getArguments().get(0);\n                subParamExpr.accept(visitor);\n\n                Object param0Value = subParamExpr.getAttributes().get(EVAL_VALUE);\n                if (param0Value == null) {\n                    x.putAttribute(EVAL_EXPR, subParamExpr);\n                    return SQLEvalVisitor.EVAL_ERROR;\n                }\n\n                return param0Value;\n            }\n        }\n\n        param0.accept(visitor);\n\n        Object param0Value = param0.getAttributes().get(EVAL_VALUE);\n        if (param0Value == null) {\n            return SQLEvalVisitor.EVAL_ERROR;\n        }\n\n        if (param0Value instanceof String) {\n            byte[] bytes = HexBin.decode((String) param0Value);\n            if (bytes == null) {\n                return SQLEvalVisitor.EVAL_VALUE_NULL;\n            }\n\n            String result = new String(bytes, StandardCharsets.UTF_8);\n            return result;\n        }\n\n        return SQLEvalVisitor.EVAL_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/DataSourceMonitorable.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\n\nimport javax.management.JMException;\nimport javax.management.ObjectName;\nimport javax.management.openmbean.CompositeDataSupport;\n\nimport java.io.Closeable;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * 外部数据要想能被使用druid sql 监控和防火墙， 需要实现此接口.\n *\n * 并在初始化调用DruidDataSourceStatManager.addDataSource，close 时调用DruidDataSourceStatManager.removeDataSource\n */\npublic interface DataSourceMonitorable extends DataSourceProxy, Closeable {\n    void resetStat();\n\n    String getInitStackTrace();\n\n    CompositeDataSupport getCompositeData() throws JMException;\n\n    ObjectName getObjectName();\n\n    List<Map<String, Object>> getPoolingConnectionInfo();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.DruidDataSourceUtils;\nimport com.alibaba.druid.util.JMXUtils;\n\nimport javax.management.JMException;\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\nimport javax.management.openmbean.*;\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.reflect.Method;\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n@SuppressWarnings(\"rawtypes\")\npublic class DruidDataSourceStatManager implements DruidDataSourceStatManagerMBean {\n    private static final Lock staticLock = new ReentrantLock();\n\n    public static final String SYS_PROP_INSTANCES = \"druid.dataSources\";\n    public static final String SYS_PROP_REGISTER_SYS_PROPERTY = \"druid.registerToSysProperty\";\n\n    private static final Log LOG = LogFactory.getLog(DruidDataSourceStatManager.class);\n\n    private static final DruidDataSourceStatManager instance = new DruidDataSourceStatManager();\n\n    private final AtomicLong resetCount = new AtomicLong();\n\n    // global instances\n    private static volatile Map dataSources;\n\n    private static final String MBEAN_NAME = \"com.alibaba.druid:type=DruidDataSourceStat\";\n\n    public static DruidDataSourceStatManager getInstance() {\n        return instance;\n    }\n\n    public static void clear() {\n        staticLock.lock();\n        try {\n            Map<Object, ObjectName> dataSources = getInstances();\n\n            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n            for (Object item : dataSources.entrySet()) {\n                Map.Entry entry = (Map.Entry) item;\n                ObjectName objectName = (ObjectName) entry.getValue();\n\n                if (objectName == null) {\n                    continue;\n                }\n\n                try {\n                    mbeanServer.unregisterMBean(objectName);\n                } catch (JMException e) {\n                    LOG.error(e.getMessage(), e);\n                }\n            }\n        } finally {\n            staticLock.unlock();\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<Object, ObjectName> getInstances() {\n        Map<Object, ObjectName> tmp = dataSources;\n        if (tmp == null) {\n            staticLock.lock();\n            try {\n                if (isRegisterToSystemProperty()) {\n                    dataSources = getInstances0();\n                } else {\n                    tmp = dataSources;\n                    if (null == tmp) {\n                        dataSources = tmp = Collections.synchronizedMap(new IdentityHashMap<Object, ObjectName>());\n                    }\n                }\n            } finally {\n                staticLock.unlock();\n            }\n        }\n\n        return dataSources;\n    }\n\n    public static boolean isRegisterToSystemProperty() {\n        String value = System.getProperty(SYS_PROP_REGISTER_SYS_PROPERTY);\n        return \"true\".equals(value);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static Map<Object, ObjectName> getInstances0() {\n        Properties properties = System.getProperties();\n        Map<Object, ObjectName> instances = (Map<Object, ObjectName>) properties.get(SYS_PROP_INSTANCES);\n\n        if (instances == null) {\n            synchronized (properties) {\n                instances = (Map<Object, ObjectName>) properties.get(SYS_PROP_INSTANCES);\n\n                if (instances == null) {\n                    instances = Collections.synchronizedMap(new IdentityHashMap<Object, ObjectName>());\n                    properties.put(SYS_PROP_INSTANCES, instances);\n                }\n            }\n        }\n\n        return instances;\n    }\n\n    public static synchronized ObjectName addDataSource(Object dataSource, String name) {\n        final Map<Object, ObjectName> instances = getInstances();\n\n        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n        synchronized (instances) {\n            if (instances.size() == 0) {\n                try {\n                    ObjectName objectName = new ObjectName(MBEAN_NAME);\n                    if (!mbeanServer.isRegistered(objectName)) {\n                        mbeanServer.registerMBean(instance, objectName);\n                    }\n                } catch (JMException ex) {\n                    LOG.error(\"register mbean error\", ex);\n                }\n\n                DruidStatService.registerMBean();\n            }\n        }\n\n        ObjectName objectName = null;\n        if (name != null) {\n            try {\n                objectName = new ObjectName(\"com.alibaba.druid:type=DruidDataSource,id=\" + name);\n                mbeanServer.registerMBean(dataSource, objectName);\n            } catch (Throwable ex) {\n                LOG.error(\"register mbean error\", ex);\n                objectName = null;\n            }\n        }\n\n        if (objectName == null) {\n            try {\n                int id = System.identityHashCode(dataSource);\n                objectName = new ObjectName(\"com.alibaba.druid:type=DruidDataSource,id=\" + id);\n                mbeanServer.registerMBean(dataSource, objectName);\n            } catch (Throwable ex) {\n                LOG.error(\"register mbean error\", ex);\n                objectName = null;\n            }\n        }\n\n        instances.put(dataSource, objectName);\n        return objectName;\n    }\n\n    public static synchronized void removeDataSource(Object dataSource) {\n        Map<Object, ObjectName> instances = getInstances();\n\n        ObjectName objectName = (ObjectName) instances.remove(dataSource);\n\n        if (objectName == null) {\n            objectName = DruidDataSourceUtils.getObjectName(dataSource);\n        }\n\n        if (objectName == null) {\n            LOG.error(\"unregister mbean failed. url \" + DruidDataSourceUtils.getUrl(dataSource));\n            return;\n        }\n\n        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n\n        try {\n            mbeanServer.unregisterMBean(objectName);\n        } catch (Throwable ex) {\n            LOG.error(\"unregister mbean error\", ex);\n        }\n\n        if (instances.size() == 0) {\n            try {\n                mbeanServer.unregisterMBean(new ObjectName(MBEAN_NAME));\n            } catch (Throwable ex) {\n                LOG.error(\"unregister mbean error\", ex);\n            }\n\n            DruidStatService.unregisterMBean();\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static Set<DataSourceMonitorable> getDruidDataSourceInstances() {\n        getInstances();\n        return dataSources.keySet();\n    }\n\n    public void reset() {\n        Map<Object, ObjectName> dataSources = getInstances();\n\n        for (Object item : dataSources.keySet()) {\n            try {\n                Method method = item.getClass().getMethod(\"resetStat\");\n                method.invoke(item);\n            } catch (Exception e) {\n                LOG.error(\"resetStat error\", e);\n            }\n        }\n\n        resetCount.incrementAndGet();\n    }\n\n    public void logAndResetDataSource() {\n        Map<Object, ObjectName> dataSources = getInstances();\n\n        for (Object item : dataSources.keySet()) {\n            try {\n                Method method = item.getClass().getMethod(\"logStats\");\n                method.invoke(item);\n            } catch (Exception e) {\n                LOG.error(\"resetStat error\", e);\n            }\n        }\n\n        resetCount.incrementAndGet();\n    }\n\n    public long getResetCount() {\n        return resetCount.get();\n    }\n\n    public TabularData getDataSourceList() throws JMException {\n        CompositeType rowType = getDruidDataSourceCompositeType();\n        String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]);\n\n        TabularType tabularType = new TabularType(\"DruidDataSourceStat\", \"DruidDataSourceStat\", rowType, indexNames);\n        TabularData data = new TabularDataSupport(tabularType);\n\n        final Set<Object> dataSources = getInstances().keySet();\n        for (Object dataSource : dataSources) {\n            data.put(getCompositeData(dataSource));\n        }\n\n        return data;\n    }\n\n    public CompositeDataSupport getCompositeData(Object dataSource) throws JMException {\n        CompositeType rowType = getDruidDataSourceCompositeType();\n\n        Map<String, Object> map = DruidDataSourceUtils.getStatDataForMBean(dataSource);\n\n        return new CompositeDataSupport(rowType, map);\n    }\n\n    private static CompositeType COMPOSITE_TYPE;\n\n    public static CompositeType getDruidDataSourceCompositeType() throws JMException {\n        if (COMPOSITE_TYPE != null) {\n            return COMPOSITE_TYPE;\n        }\n\n        OpenType<?>[] indexTypes = new OpenType<?>[]{\n                // 0 - 4\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n\n                // 5 - 9\n                SimpleType.LONG, //\n                SimpleType.INTEGER, //\n                SimpleType.INTEGER, //\n                SimpleType.INTEGER, //\n                SimpleType.INTEGER, //\n\n                // 10 - 14\n                SimpleType.INTEGER, //\n                SimpleType.INTEGER, //\n                SimpleType.INTEGER, //\n                SimpleType.BOOLEAN, //\n                SimpleType.BOOLEAN, //\n\n                // 15 - 19\n                SimpleType.BOOLEAN, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n\n                // 20 - 24\n                SimpleType.STRING, //\n                SimpleType.INTEGER, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                SimpleType.LONG, //\n\n                // 25 - 29\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n\n                // 30 - 34\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                JMXUtils.getThrowableCompositeType(), //\n                JMXUtils.getThrowableCompositeType(), //\n                SimpleType.LONG, //\n\n                // 35 - 39\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n\n                // 40 - 44\n                SimpleType.DATE, //\n                SimpleType.DATE, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n\n                // 45\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n                //\n        };\n\n        String[] indexNames = {\n                // 0 - 4\n                \"Name\", //\n                \"URL\", //\n                \"CreateCount\", //\n                \"DestroyCount\", //\n                \"ConnectCount\", //\n\n                // 5 - 9\n                \"CloseCount\", //\n                \"ActiveCount\", //\n                \"PoolingCount\", //\n                \"LockQueueLength\", //\n                \"WaitThreadCount\", //\n\n                // 10 - 14\n                \"InitialSize\", //\n                \"MaxActive\", //\n                \"MinIdle\", //\n                \"PoolPreparedStatements\", //\n                \"TestOnBorrow\", //\n\n                // 15 - 19\n                \"TestOnReturn\", //\n                \"MinEvictableIdleTimeMillis\", //\n                \"ConnectErrorCount\", //\n                \"CreateTimespanMillis\", //\n                \"DbType\", //\n\n                // 20 - 24\n                \"ValidationQuery\", //\n                \"ValidationQueryTimeout\", //\n                \"DriverClassName\", //\n                \"Username\", //\n                \"RemoveAbandonedCount\", //\n\n                // 25 - 29\n                \"NotEmptyWaitCount\", //\n                \"NotEmptyWaitNanos\", //\n                \"ErrorCount\", //\n                \"ReusePreparedStatementCount\", //\n                \"StartTransactionCount\", //\n\n                // 30 - 34\n                \"CommitCount\", //\n                \"RollbackCount\", //\n                \"LastError\", //\n                \"LastCreateError\", //\n                \"PreparedStatementCacheDeleteCount\", //\n\n                // 35 - 39\n                \"PreparedStatementCacheAccessCount\", //\n                \"PreparedStatementCacheMissCount\", //\n                \"PreparedStatementCacheHitCount\", //\n                \"PreparedStatementCacheCurrentCount\", //\n                \"Version\",\n\n                // 40 - 44\n                \"LastErrorTime\",\n                \"LastCreateErrorTime\",\n                \"CreateErrorCount\",\n                \"DiscardCount\",\n                \"ExecuteQueryCount\",\n\n                // 45 -\n                \"ExecuteUpdateCount\",\n                \"InitStackTrace\",\n        };\n\n        String[] indexDescriptions = indexNames;\n        COMPOSITE_TYPE = new CompositeType(\"DataSourceStatistic\",\n                \"DataSource Statistic\",\n                indexNames,\n                indexDescriptions,\n                indexTypes);\n\n        return COMPOSITE_TYPE;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatManagerMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.TabularData;\n\npublic interface DruidDataSourceStatManagerMBean {\n    void reset();\n\n    TabularData getDataSourceList() throws JMException;\n\n    long getResetCount();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.VERSION;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.support.http.stat.WebAppStatManager;\nimport com.alibaba.druid.support.spring.stat.SpringStatManager;\nimport com.alibaba.druid.util.DruidDataSourceUtils;\nimport com.alibaba.druid.util.JdbcSqlStatUtils;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport java.sql.Driver;\nimport java.sql.DriverManager;\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * 监控相关的对外数据暴露\n * <p>\n * 1. 为了支持jndi数据源本类内部调用druid相关对象均需要反射调用,返回值也应该是Object,List&lt;Object&gt;,Map&lt;String,Object&gt;等无关于druid的类型\n * 2. 对外暴露的public方法都应该先调用init()，应该有更好的方式，暂时没想到\n *\n * @author sandzhang[sandzhangtoo@gmail.com]\n */\npublic final class DruidStatManagerFacade {\n    private static final DruidStatManagerFacade instance = new DruidStatManagerFacade();\n    private boolean resetEnable = true;\n    private final AtomicLong resetCount = new AtomicLong();\n\n    private DruidStatManagerFacade() {\n    }\n\n    public static DruidStatManagerFacade getInstance() {\n        return instance;\n    }\n\n    private Set<Object> getDruidDataSourceInstances() {\n        return DruidDataSourceStatManager.getInstances().keySet();\n    }\n\n    public Object getDruidDataSourceByName(String name) {\n        for (Object o : this.getDruidDataSourceInstances()) {\n            String itemName = DruidDataSourceUtils.getName(o);\n            if (StringUtils.equals(name, itemName)) {\n                return o;\n            }\n        }\n\n        return null;\n    }\n\n    public void resetDataSourceStat() {\n        DruidDataSourceStatManager.getInstance().reset();\n    }\n\n    public void resetSqlStat() {\n        JdbcStatManager.getInstance().reset();\n    }\n\n    public void resetAll() {\n        if (!isResetEnable()) {\n            return;\n        }\n\n        SpringStatManager.getInstance().resetStat();\n        WebAppStatManager.getInstance().resetStat();\n        resetSqlStat();\n        resetDataSourceStat();\n        resetCount.incrementAndGet();\n    }\n\n    public void logAndResetDataSource() {\n        if (!isResetEnable()) {\n            return;\n        }\n        DruidDataSourceStatManager.getInstance().logAndResetDataSource();\n    }\n\n    public boolean isResetEnable() {\n        return resetEnable;\n    }\n\n    public void setResetEnable(boolean resetEnable) {\n        this.resetEnable = resetEnable;\n    }\n\n    public Object getSqlStatById(Integer id) {\n        for (Object ds : getDruidDataSourceInstances()) {\n            Object sqlStat = DruidDataSourceUtils.getSqlStat(ds, id);\n            if (sqlStat != null) {\n                return sqlStat;\n            }\n        }\n        return null;\n    }\n\n    public Map<String, Object> getDataSourceStatData(Integer id) {\n        if (id == null) {\n            return null;\n        }\n\n        Object datasource = getDruidDataSourceById(id);\n        return datasource == null ? null : dataSourceToMapData(datasource, false);\n    }\n\n    public Object getDruidDataSourceById(Integer identity) {\n        if (identity == null) {\n            return null;\n        }\n\n        for (Object datasource : getDruidDataSourceInstances()) {\n            if (System.identityHashCode(datasource) == identity) {\n                return datasource;\n            }\n        }\n        return null;\n    }\n\n    public List<Map<String, Object>> getSqlStatDataList(Integer dataSourceId) {\n        Set<Object> dataSources = getDruidDataSourceInstances();\n\n        if (dataSourceId == null) {\n            JdbcDataSourceStat globalStat = JdbcDataSourceStat.getGlobal();\n\n            List<Map<String, Object>> sqlList = new ArrayList<Map<String, Object>>();\n\n            DruidDataSource globalStatDataSource = null;\n            for (Object datasource : dataSources) {\n                if (datasource instanceof DruidDataSource) {\n                    if (((DruidDataSource) datasource).getDataSourceStat() == globalStat) {\n                        if (globalStatDataSource == null) {\n                            globalStatDataSource = (DruidDataSource) datasource;\n                        } else {\n                            continue;\n                        }\n                    }\n                }\n                sqlList.addAll(getSqlStatDataList(datasource));\n            }\n\n            return sqlList;\n        }\n\n        for (Object datasource : dataSources) {\n            if (dataSourceId != null && dataSourceId.intValue() != System.identityHashCode(datasource)) {\n                continue;\n            }\n\n            return getSqlStatDataList(datasource);\n        }\n\n        return new ArrayList<Map<String, Object>>();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public Map<String, Object> getWallStatMap(Integer dataSourceId) {\n        Set<Object> dataSources = getDruidDataSourceInstances();\n\n        if (dataSourceId == null) {\n            Map<String, Object> map = new HashMap<String, Object>();\n\n            for (Object datasource : dataSources) {\n                Map<String, Object> wallStat = DruidDataSourceUtils.getWallStatMap(datasource);\n                map = mergeWallStat(map, wallStat);\n            }\n\n            return map;\n        }\n\n        for (Object datasource : dataSources) {\n            if (dataSourceId != null && dataSourceId.intValue() != System.identityHashCode(datasource)) {\n                continue;\n            }\n\n            return DruidDataSourceUtils.getWallStatMap(datasource);\n        }\n\n        return new HashMap<String, Object>();\n        //\n    }\n\n    /**\n     * Merges two wall stat maps into a single map.\n     *\n     * @param mapA the first wall stat map to be merged\n     * @param mapB the second wall stat map to be merged\n     * @return a new map that contains the merged wall stats from mapA and mapB\n     * @deprecated\n     */\n    public static Map mergWallStat(Map mapA, Map mapB) {\n        return mergeWallStat(mapA, mapB);\n    }\n\n    @SuppressWarnings({\"rawtypes\", \"unchecked\"})\n    public static Map mergeWallStat(Map mapA, Map mapB) {\n        if (mapA == null || mapA.size() == 0) {\n            return mapB;\n        }\n\n        if (mapB == null || mapB.size() == 0) {\n            return mapA;\n        }\n\n        Map<String, Object> newMap = new LinkedHashMap<String, Object>();\n        for (Object item : mapB.entrySet()) {\n            Map.Entry entry = (Map.Entry) item;\n            String key = (String) entry.getKey();\n            Object valueB = entry.getValue();\n            Object valueA = mapA.get(key);\n\n            if (valueA == null) {\n                newMap.put(key, valueB);\n            } else if (valueB == null) {\n                newMap.put(key, valueA);\n            } else if (\"blackList\".equals(key)) {\n                Map<String, Map<String, Object>> newSet = new HashMap<String, Map<String, Object>>();\n\n                Collection<Map<String, Object>> collectionA = (Collection<Map<String, Object>>) valueA;\n                for (Map<String, Object> blackItem : collectionA) {\n                    if (newSet.size() >= 1000) {\n                        break;\n                    }\n\n                    String sql = (String) blackItem.get(\"sql\");\n                    Map<String, Object> oldItem = newSet.get(sql);\n                    newSet.put(sql, mergeWallStat(oldItem, blackItem));\n                }\n\n                Collection<Map<String, Object>> collectionB = (Collection<Map<String, Object>>) valueB;\n                for (Map<String, Object> blackItem : collectionB) {\n                    if (newSet.size() >= 1000) {\n                        break;\n                    }\n\n                    String sql = (String) blackItem.get(\"sql\");\n                    Map<String, Object> oldItem = newSet.get(sql);\n                    newSet.put(sql, mergeWallStat(oldItem, blackItem));\n                }\n                newMap.put(key, newSet.values());\n            } else {\n                if (valueA instanceof Map && valueB instanceof Map) {\n                    Object newValue = mergeWallStat((Map) valueA, (Map) valueB);\n                    newMap.put(key, newValue);\n                } else if (valueA instanceof Set && valueB instanceof Set) {\n                    Set<Object> set = new HashSet<Object>();\n                    set.addAll((Set) valueA);\n                    set.addAll((Set) valueB);\n                    newMap.put(key, set);\n                } else if (valueA instanceof List && valueB instanceof List) {\n                    List<Map<String, Object>> mergedList = mergeNamedList((List) valueA, (List) valueB);\n                    newMap.put(key, mergedList);\n                } else if (valueA instanceof long[] && valueB instanceof long[]) {\n                    long[] arrayA = (long[]) valueA;\n                    long[] arrayB = (long[]) valueB;\n\n                    int len = arrayA.length >= arrayB.length ? arrayA.length : arrayB.length;\n                    long[] sum = new long[len];\n\n                    for (int i = 0; i < sum.length; ++i) {\n                        if (i < arrayA.length) {\n                            sum[i] += arrayA.length;\n                        }\n                        if (i < arrayB.length) {\n                            sum[i] += arrayB.length;\n                        }\n                    }\n                    newMap.put(key, sum);\n                } else if (valueA instanceof String && valueB instanceof String) {\n                    newMap.put(key, valueA);\n                } else {\n                    Object sum = SQLEvalVisitorUtils.add(valueA, valueB);\n                    newMap.put(key, sum);\n                }\n            }\n        }\n\n        return newMap;\n    }\n\n    @SuppressWarnings({\"rawtypes\", \"unchecked\"})\n    private static List<Map<String, Object>> mergeNamedList(List listA, List listB) {\n        Map<String, Map<String, Object>> mapped = new HashMap<String, Map<String, Object>>();\n        for (Object item : (List) listA) {\n            Map<String, Object> map = (Map<String, Object>) item;\n            String name = (String) map.get(\"name\");\n            mapped.put(name, map);\n        }\n\n        List<Map<String, Object>> mergedList = new ArrayList<Map<String, Object>>();\n        for (Object item : (List) listB) {\n            Map<String, Object> mapB = (Map<String, Object>) item;\n            String name = (String) mapB.get(\"name\");\n            Map<String, Object> mapA = mapped.get(name);\n\n            Map<String, Object> mergedMap = mergeWallStat(mapA, mapB);\n            mergedList.add(mergedMap);\n        }\n\n        return mergedList;\n    }\n\n    public List<Map<String, Object>> getSqlStatDataList(Object datasource) {\n        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();\n        Map<?, ?> sqlStatMap = DruidDataSourceUtils.getSqlStatMap(datasource);\n        for (Object sqlStat : sqlStatMap.values()) {\n            Map<String, Object> data = JdbcSqlStatUtils.getData(sqlStat);\n\n            long executeCount = (Long) data.get(\"ExecuteCount\");\n            long runningCount = (Long) data.get(\"RunningCount\");\n\n            if (executeCount == 0 && runningCount == 0) {\n                continue;\n            }\n\n            result.add(data);\n        }\n\n        return result;\n    }\n\n    public Map<String, Object> getSqlStatData(Integer id) {\n        if (id == null) {\n            return null;\n        }\n\n        Object sqlStat = getSqlStatById(id);\n\n        if (sqlStat == null) {\n            return null;\n        }\n\n        return JdbcSqlStatUtils.getData(sqlStat);\n    }\n\n    public List<Map<String, Object>> getDataSourceStatDataList() {\n        return getDataSourceStatDataList(false);\n    }\n\n    public List<Map<String, Object>> getDataSourceStatDataList(boolean includeSqlList) {\n        List<Map<String, Object>> datasourceList = new ArrayList<Map<String, Object>>();\n        for (Object dataSource : getDruidDataSourceInstances()) {\n            datasourceList.add(dataSourceToMapData(dataSource, includeSqlList));\n        }\n        return datasourceList;\n    }\n\n    public List<List<String>> getActiveConnStackTraceList() {\n        List<List<String>> traceList = new ArrayList<List<String>>();\n        for (Object dataSource : getDruidDataSourceInstances()) {\n            List<String> stacks = ((DruidDataSource) dataSource).getActiveConnectionStackTrace();\n            if (stacks.size() > 0) {\n                traceList.add(stacks);\n            }\n        }\n        return traceList;\n    }\n\n    public Map<String, Object> returnJSONBasicStat() {\n        Map<String, Object> dataMap = new LinkedHashMap<String, Object>();\n        dataMap.put(\"Version\", VERSION.getVersionNumber());\n        dataMap.put(\"Drivers\", getDriversData());\n        dataMap.put(\"ResetEnable\", isResetEnable());\n        dataMap.put(\"ResetCount\", getResetCount());\n        dataMap.put(\"JavaVMName\", System.getProperty(\"java.vm.name\"));\n        dataMap.put(\"JavaVersion\", System.getProperty(\"java.version\"));\n        dataMap.put(\"JavaClassPath\", System.getProperty(\"java.class.path\"));\n        dataMap.put(\"StartTime\", Utils.getStartTime());\n        return dataMap;\n    }\n\n    public long getResetCount() {\n        return resetCount.get();\n    }\n\n    private List<String> getDriversData() {\n        List<String> drivers = new ArrayList<String>();\n        for (Enumeration<Driver> e = DriverManager.getDrivers(); e.hasMoreElements(); ) {\n            Driver driver = e.nextElement();\n            drivers.add(driver.getClass().getName());\n        }\n        return drivers;\n    }\n\n    public List<Map<String, Object>> getPoolingConnectionInfoByDataSourceId(Integer id) {\n        Object datasource = getDruidDataSourceById(id);\n\n        if (datasource == null) {\n            return null;\n        }\n\n        return DruidDataSourceUtils.getPoolingConnectionInfo(datasource);\n    }\n\n    public List<String> getActiveConnectionStackTraceByDataSourceId(Integer id) {\n        Object datasource = getDruidDataSourceById(id);\n\n        if (datasource == null || !DruidDataSourceUtils.isRemoveAbandoned(datasource)) {\n            return null;\n        }\n\n        return DruidDataSourceUtils.getActiveConnectionStackTrace(datasource);\n    }\n\n    private Map<String, Object> dataSourceToMapData(Object dataSource, boolean includeSql) {\n        Map<String, Object> map = DruidDataSourceUtils.getStatData(dataSource);\n\n        if (includeSql) {\n            List<Map<String, Object>> sqlList = getSqlStatDataList(dataSource);\n            map.put(\"SQL\", sqlList);\n        }\n\n        return map;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/DruidStatService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.support.http.stat.WebAppStatManager;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.support.spring.stat.SpringStatManager;\nimport com.alibaba.druid.util.MapComparator;\nimport com.alibaba.druid.util.StringUtils;\n\nimport javax.management.JMException;\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\n\nimport java.lang.management.ManagementFactory;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\n\n/**\n * 注意：避免直接调用Druid相关对象例如DruidDataSource等，相关调用要到DruidStatManagerFacade里用反射实现\n *\n * @author sandzhang[sandzhangtoo@gmail.com]\n */\npublic final class DruidStatService implements DruidStatServiceMBean {\n    private static final Log LOG = LogFactory.getLog(DruidStatService.class);\n\n    public static final String MBEAN_NAME = \"com.alibaba.druid:type=DruidStatService\";\n\n    private static final DruidStatService instance = new DruidStatService();\n\n    private static DruidStatManagerFacade statManagerFacade = DruidStatManagerFacade.getInstance();\n\n    public static final int RESULT_CODE_SUCCESS = 1;\n    public static final int RESULT_CODE_ERROR = -1;\n\n    private static final int DEFAULT_PAGE = 1;\n    private static final int DEFAULT_PER_PAGE_COUNT = Integer.MAX_VALUE;\n    private static final String ORDER_TYPE_DESC = \"desc\";\n    private static final String ORDER_TYPE_ASC = \"asc\";\n    private static final String DEFAULT_ORDER_TYPE = ORDER_TYPE_ASC;\n    private static final String DEFAULT_ORDERBY = \"SQL\";\n\n    private DruidStatService() {\n    }\n\n    public static DruidStatService getInstance() {\n        return instance;\n    }\n\n    public boolean isResetEnable() {\n        return statManagerFacade.isResetEnable();\n    }\n\n    public void setResetEnable(boolean value) {\n        statManagerFacade.setResetEnable(value);\n    }\n\n    public String service(String url) {\n        Map<String, String> parameters = getParameters(url);\n\n        if (url.equals(\"/basic.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, statManagerFacade.returnJSONBasicStat());\n        }\n\n        if (url.equals(\"/reset-all.json\")) {\n            statManagerFacade.resetAll();\n\n            return returnJSONResult(RESULT_CODE_SUCCESS, null);\n        }\n\n        if (url.equals(\"/log-and-reset.json\")) {\n            statManagerFacade.logAndResetDataSource();\n\n            return returnJSONResult(RESULT_CODE_SUCCESS, null);\n        }\n\n        if (url.equals(\"/datasource.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, statManagerFacade.getDataSourceStatDataList());\n        }\n\n        if (url.equals(\"/activeConnectionStackTrace.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, statManagerFacade.getActiveConnStackTraceList());\n        }\n\n        if (url.startsWith(\"/datasource-\")) {\n            Integer id = StringUtils.subStringToInteger(url, \"datasource-\", \".\");\n            Object result = statManagerFacade.getDataSourceStatData(id);\n            return returnJSONResult(result == null ? RESULT_CODE_ERROR : RESULT_CODE_SUCCESS, result);\n        }\n\n        if (url.startsWith(\"/connectionInfo-\") && url.endsWith(\".json\")) {\n            Integer id = StringUtils.subStringToInteger(url, \"connectionInfo-\", \".\");\n            List<?> connectionInfoList = statManagerFacade.getPoolingConnectionInfoByDataSourceId(id);\n            return returnJSONResult(connectionInfoList == null ? RESULT_CODE_ERROR : RESULT_CODE_SUCCESS,\n                    connectionInfoList);\n        }\n\n        if (url.startsWith(\"/activeConnectionStackTrace-\") && url.endsWith(\".json\")) {\n            Integer id = StringUtils.subStringToInteger(url, \"activeConnectionStackTrace-\", \".\");\n            return returnJSONActiveConnectionStackTrace(id);\n        }\n\n        if (url.startsWith(\"/sql.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, getSqlStatDataList(parameters));\n        }\n\n        if (url.startsWith(\"/wall.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, getWallStatMap(parameters));\n        }\n\n        if (url.startsWith(\"/wall-\") && url.indexOf(\".json\") > 0) {\n            Integer dataSourceId = StringUtils.subStringToInteger(url, \"wall-\", \".json\");\n            Object result = statManagerFacade.getWallStatMap(dataSourceId);\n            return returnJSONResult(result == null ? RESULT_CODE_ERROR : RESULT_CODE_SUCCESS, result);\n        }\n\n        if (url.startsWith(\"/sql-\") && url.indexOf(\".json\") > 0) {\n            Integer id = StringUtils.subStringToInteger(url, \"sql-\", \".json\");\n            return getSqlStat(id);\n        }\n\n        if (url.startsWith(\"/weburi.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, getWebURIStatDataList(parameters));\n        }\n\n        if (url.startsWith(\"/weburi-\") && url.indexOf(\".json\") > 0) {\n            String uri = StringUtils.subString(url, \"weburi-\", \".json\", true);\n            return returnJSONResult(RESULT_CODE_SUCCESS, getWebURIStatData(uri));\n        }\n\n        if (url.startsWith(\"/webapp.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, getWebAppStatDataList(parameters));\n        }\n\n        if (url.startsWith(\"/websession.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, getWebSessionStatDataList(parameters));\n        }\n\n        if (url.startsWith(\"/websession-\") && url.indexOf(\".json\") > 0) {\n            String id = StringUtils.subString(url, \"websession-\", \".json\");\n            return returnJSONResult(RESULT_CODE_SUCCESS, getWebSessionStatData(id));\n        }\n\n        if (url.startsWith(\"/spring.json\")) {\n            return returnJSONResult(RESULT_CODE_SUCCESS, getSpringStatDataList(parameters));\n        }\n\n        if (url.startsWith(\"/spring-detail.json\")) {\n            String clazz = parameters.get(\"class\");\n            String method = parameters.get(\"method\");\n            return returnJSONResult(RESULT_CODE_SUCCESS, getSpringMethodStatData(clazz, method));\n        }\n\n        return returnJSONResult(RESULT_CODE_ERROR, \"Do not support this request, please contact with administrator.\");\n    }\n\n    private List<Map<String, Object>> getSpringStatDataList(Map<String, String> parameters) {\n        List<Map<String, Object>> array = SpringStatManager.getInstance().getMethodStatData();\n        return comparatorOrderBy(array, parameters);\n    }\n\n    private List<Map<String, Object>> getWebURIStatDataList(Map<String, String> parameters) {\n        List<Map<String, Object>> array = WebAppStatManager.getInstance().getURIStatData();\n        return comparatorOrderBy(array, parameters);\n    }\n\n    private Map<String, Object> getWebURIStatData(String uri) {\n        return WebAppStatManager.getInstance().getURIStatData(uri);\n    }\n\n    private Map<String, Object> getWebSessionStatData(String sessionId) {\n        return WebAppStatManager.getInstance().getSessionStat(sessionId);\n    }\n\n    private Map<String, Object> getSpringMethodStatData(String clazz, String method) {\n        return SpringStatManager.getInstance().getMethodStatData(clazz, method);\n    }\n\n    private List<Map<String, Object>> getWebSessionStatDataList(Map<String, String> parameters) {\n        List<Map<String, Object>> array = WebAppStatManager.getInstance().getSessionStatData();\n        return comparatorOrderBy(array, parameters);\n    }\n\n    private List<Map<String, Object>> getWebAppStatDataList(Map<String, String> parameters) {\n        List<Map<String, Object>> array = WebAppStatManager.getInstance().getWebAppStatData();\n        return comparatorOrderBy(array, parameters);\n    }\n\n    private List<Map<String, Object>> comparatorOrderBy(List<Map<String, Object>> array,\n                                                        Map<String, String> parameters) {\n        // when open the stat page before executing some sql\n        if (array == null || array.isEmpty()) {\n            return null;\n        }\n\n        // when parameters is null\n        String orderBy, orderType = null;\n        Integer page = DEFAULT_PAGE;\n        Integer perPageCount = DEFAULT_PER_PAGE_COUNT;\n        if (parameters == null) {\n            orderBy = DEFAULT_ORDERBY;\n            orderType = DEFAULT_ORDER_TYPE;\n            page = DEFAULT_PAGE;\n            perPageCount = DEFAULT_PER_PAGE_COUNT;\n        } else {\n            orderBy = parameters.get(\"orderBy\");\n            orderType = parameters.get(\"orderType\");\n            String pageParam = parameters.get(\"page\");\n            if (pageParam != null && pageParam.length() != 0) {\n                page = Integer.parseInt(pageParam);\n            }\n            String pageCountParam = parameters.get(\"perPageCount\");\n            if (pageCountParam != null && pageCountParam.length() > 0) {\n                perPageCount = Integer.parseInt(pageCountParam);\n            }\n        }\n\n        // others,such as order\n        orderBy = orderBy == null ? DEFAULT_ORDERBY : orderBy;\n        orderType = orderType == null ? DEFAULT_ORDER_TYPE : orderType;\n\n        if (!ORDER_TYPE_DESC.equals(orderType)) {\n            orderType = ORDER_TYPE_ASC;\n        }\n\n        // orderby the statData array\n        if (orderBy.trim().length() != 0) {\n            Collections.sort(array, new MapComparator<String, Object>(orderBy, ORDER_TYPE_DESC.equals(orderType)));\n        }\n\n        // page\n        int fromIndex = (page - 1) * perPageCount;\n        int toIndex = page * perPageCount;\n        if (toIndex > array.size()) {\n            toIndex = array.size();\n        }\n\n        return array.subList(fromIndex, toIndex);\n    }\n\n    private List<Map<String, Object>> getSqlStatDataList(Map<String, String> parameters) {\n        Integer dataSourceId = null;\n\n        String dataSourceIdParam = parameters.get(\"dataSourceId\");\n        if (dataSourceIdParam != null && dataSourceIdParam.length() > 0) {\n            dataSourceId = Integer.parseInt(dataSourceIdParam);\n        }\n\n        List<Map<String, Object>> array = statManagerFacade.getSqlStatDataList(dataSourceId);\n        List<Map<String, Object>> sortedArray = comparatorOrderBy(array, parameters);\n        return sortedArray;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public Map<String, Object> getWallStatMap(Map<String, String> parameters) {\n        Integer dataSourceId = null;\n\n        String dataSourceIdParam = parameters.get(\"dataSourceId\");\n        if (dataSourceIdParam != null && dataSourceIdParam.length() > 0) {\n            dataSourceId = Integer.parseInt(dataSourceIdParam);\n        }\n\n        Map<String, Object> result = statManagerFacade.getWallStatMap(dataSourceId);\n\n        if (result != null) {\n            List<Map<String, Object>> tables = (List<Map<String, Object>>) result.get(\"tables\");\n            if (tables != null) {\n                List<Map<String, Object>> sortedArray = comparatorOrderBy(tables, parameters);\n                result.put(\"tables\", sortedArray);\n            }\n\n            List<Map<String, Object>> functions = (List<Map<String, Object>>) result.get(\"functions\");\n            if (functions != null) {\n                List<Map<String, Object>> sortedArray = comparatorOrderBy(functions, parameters);\n                result.put(\"functions\", sortedArray);\n            }\n        } else {\n            result = Collections.emptyMap();\n        }\n\n        return result;\n    }\n\n    private String getSqlStat(Integer id) {\n        Map<String, Object> map = statManagerFacade.getSqlStatData(id);\n\n        if (map == null) {\n            return returnJSONResult(RESULT_CODE_ERROR, null);\n        }\n\n        DbType dbType = DbType.of((String) map.get(\"DbType\"));\n        String sql = (String) map.get(\"SQL\");\n\n        map.put(\"formattedSql\", SQLUtils.format(sql, dbType));\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);\n\n        if (!statementList.isEmpty()) {\n            SQLStatement sqlStmt = statementList.get(0);\n            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n            sqlStmt.accept(visitor);\n            map.put(\"parsedTable\", visitor.getTables().toString());\n            map.put(\"parsedFields\", visitor.getColumns().toString());\n            map.put(\"parsedConditions\", visitor.getConditions().toString());\n            map.put(\"parsedRelationships\", visitor.getRelationships().toString());\n            map.put(\"parsedOrderbycolumns\", visitor.getOrderByColumns().toString());\n        }\n\n        DateFormat format = new SimpleDateFormat(\"yyyy/MM/dd HH:mm:ss:SSS\");\n        Date maxTimespanOccurTime = (Date) map.get(\"MaxTimespanOccurTime\");\n        if (maxTimespanOccurTime != null) {\n            map.put(\"MaxTimespanOccurTime\", format.format(maxTimespanOccurTime));\n        }\n\n        return returnJSONResult(map == null ? RESULT_CODE_ERROR : RESULT_CODE_SUCCESS, map);\n    }\n\n    private String returnJSONActiveConnectionStackTrace(Integer id) {\n        List<String> result = statManagerFacade.getActiveConnectionStackTraceByDataSourceId(id);\n\n        if (result == null) {\n            return returnJSONResult(RESULT_CODE_ERROR, \"require set removeAbandoned=true\");\n        }\n        return returnJSONResult(RESULT_CODE_SUCCESS, result);\n    }\n\n    public static String returnJSONResult(int resultCode, Object content) {\n        Map<String, Object> dataMap = new LinkedHashMap<String, Object>();\n        dataMap.put(\"ResultCode\", resultCode);\n        dataMap.put(\"Content\", content);\n        return JSONUtils.toJSONString(dataMap);\n    }\n\n    public static void registerMBean() {\n        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n        try {\n            ObjectName objectName = new ObjectName(MBEAN_NAME);\n            if (!mbeanServer.isRegistered(objectName)) {\n                mbeanServer.registerMBean(instance, objectName);\n            }\n        } catch (JMException ex) {\n            LOG.error(\"register mbean error\", ex);\n        }\n    }\n\n    public static void unregisterMBean() {\n        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n\n        try {\n            mbeanServer.unregisterMBean(new ObjectName(MBEAN_NAME));\n        } catch (JMException ex) {\n            LOG.error(\"unregister mbean error\", ex);\n        }\n    }\n\n    public static Map<String, String> getParameters(String url) {\n        if (url == null || (url = url.trim()).length() == 0) {\n            return Collections.<String, String>emptyMap();\n        }\n\n        String parametersStr = StringUtils.subString(url, \"?\", null);\n        if (parametersStr == null || parametersStr.length() == 0) {\n            return Collections.<String, String>emptyMap();\n        }\n\n        String[] parametersArray = parametersStr.split(\"&\");\n        Map<String, String> parameters = new LinkedHashMap<String, String>();\n\n        for (String parameterStr : parametersArray) {\n            int index = parameterStr.indexOf(\"=\");\n            if (index <= 0) {\n                continue;\n            }\n\n            String name = parameterStr.substring(0, index);\n            String value = parameterStr.substring(index + 1);\n            parameters.put(name, value);\n        }\n        return parameters;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/DruidStatServiceMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\npublic interface DruidStatServiceMBean {\n    String service(String url);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcConnectionStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.util.Histogram;\nimport com.alibaba.druid.util.JMXUtils;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.CompositeDataSupport;\nimport javax.management.openmbean.CompositeType;\nimport javax.management.openmbean.OpenType;\nimport javax.management.openmbean.SimpleType;\n\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class JdbcConnectionStat implements JdbcConnectionStatMBean {\n    private final AtomicInteger activeCount = new AtomicInteger();\n    private final AtomicInteger activeCountMax = new AtomicInteger();\n\n    private final AtomicInteger connectingCount = new AtomicInteger();\n    private final AtomicInteger connectingMax = new AtomicInteger();\n\n    private final AtomicLong connectCount = new AtomicLong();\n    private final AtomicLong connectErrorCount = new AtomicLong();\n    private Throwable connectErrorLast;\n    private final AtomicLong connectNanoTotal = new AtomicLong(0);                       // 连接建立消耗时间总和（纳秒）\n    private final AtomicLong connectNanoMax = new AtomicLong(0);                       // 连接建立消耗最大时间（纳秒）\n\n    private final AtomicLong errorCount = new AtomicLong();\n\n    private final AtomicLong aliveNanoTotal = new AtomicLong();\n    private Throwable lastError;\n    private long lastErrorTime;\n\n    private long connectLastTime;\n\n    private final AtomicLong closeCount = new AtomicLong(0);                       // 执行Connection.close的计数\n    private final AtomicLong transactionStartCount = new AtomicLong(0);\n    private final AtomicLong commitCount = new AtomicLong(0);                       // 执行commit的计数\n    private final AtomicLong rollbackCount = new AtomicLong(0);                       // 执行rollback的计数\n\n    private final AtomicLong aliveNanoMin = new AtomicLong();\n    private final AtomicLong aliveNanoMax = new AtomicLong();\n\n    private final Histogram histogram = new Histogram(TimeUnit.SECONDS, new long[]{ //\n            1, 5, 15, 60, 300, 1800});\n\n    public JdbcConnectionStat() {\n    }\n\n    public void reset() {\n        connectingMax.set(0);\n        connectErrorCount.set(0);\n        errorCount.set(0);\n        aliveNanoTotal.set(0);\n        aliveNanoMin.set(0);\n        aliveNanoMax.set(0);\n        lastError = null;\n        lastErrorTime = 0;\n        connectLastTime = 0;\n\n        connectCount.set(0);\n        closeCount.set(0);\n        transactionStartCount.set(0);\n        commitCount.set(0);\n        rollbackCount.set(0);\n        connectNanoTotal.set(0);\n        connectNanoMax.set(0);\n\n        histogram.reset();\n    }\n\n    public void beforeConnect() {\n        int invoking = connectingCount.incrementAndGet();\n\n        for (; ; ) {\n            int max = connectingMax.get();\n            if (invoking > max) {\n                if (connectingMax.compareAndSet(max, invoking)) {\n                    break;\n                } else {\n                    continue;\n                }\n            } else {\n                break;\n            }\n        }\n\n        connectCount.incrementAndGet();\n        connectLastTime = System.currentTimeMillis();\n    }\n\n    public void afterConnected(long delta) {\n        connectingCount.decrementAndGet();\n        connectNanoTotal.addAndGet(delta);\n        for (; ; ) {\n            // connectNanoMax\n            long max = connectNanoMax.get();\n            if (delta > max) {\n                if (connectNanoMax.compareAndSet(max, delta)) {\n                    break;\n                } else {\n                    continue;\n                }\n            } else {\n                break;\n            }\n        }\n\n        activeCount.incrementAndGet();\n    }\n\n    public long getConnectNanoMax() {\n        return this.connectNanoMax.get();\n    }\n\n    public long getConnectMillisMax() {\n        return this.connectNanoMax.get() / (1000 * 1000);\n    }\n\n    public void setActiveCount(int activeCount) {\n        this.activeCount.set(activeCount);\n\n        for (; ; ) {\n            int max = activeCountMax.get();\n            if (activeCount > max) {\n                if (activeCountMax.compareAndSet(max, activeCount)) {\n                    break;\n                } else {\n                    continue;\n                }\n            } else {\n                break;\n            }\n        }\n    }\n\n    public int getActiveCount() {\n        return activeCount.get();\n    }\n\n    public int getAtiveCountMax() {\n        return this.activeCount.get();\n    }\n\n    public long getErrorCount() {\n        return errorCount.get();\n    }\n\n    public int getConnectingCount() {\n        return connectingCount.get();\n    }\n\n    public int getConnectingMax() {\n        return connectingMax.get();\n    }\n\n    public long getAliveTotal() {\n        return aliveNanoTotal.get();\n    }\n\n    public long getAliveNanoMin() {\n        return aliveNanoMin.get();\n    }\n\n    public long getAliveMillisMin() {\n        return aliveNanoMin.get() / (1000 * 1000);\n    }\n\n    public long getAliveNanoMax() {\n        return aliveNanoMax.get();\n    }\n\n    public long getAliveMillisMax() {\n        return aliveNanoMax.get() / (1000 * 1000);\n    }\n\n    public void afterClose(long aliveNano) {\n        activeCount.decrementAndGet();\n        aliveNanoTotal.addAndGet(aliveNano);\n\n        for (; ; ) {\n            long max = aliveNanoMax.get();\n            if (aliveNano > max) {\n                if (aliveNanoMax.compareAndSet(max, aliveNano)) {\n                    break;\n                } else {\n                    continue;\n                }\n            } else {\n                break;\n            }\n        }\n\n        for (; ; ) {\n            long min = aliveNanoMin.get();\n            if (min == 0 || aliveNano < min) {\n                if (aliveNanoMin.compareAndSet(min, aliveNano)) {\n                    break;\n                } else {\n                    continue;\n                }\n            } else {\n                break;\n            }\n        }\n\n        long aliveMillis = aliveNano / (1000 * 1000);\n        histogram.record(aliveMillis);\n    }\n\n    public Throwable getErrorLast() {\n        return lastError;\n    }\n\n    public Throwable getConnectErrorLast() {\n        return this.connectErrorLast;\n    }\n\n    public Date getErrorLastTime() {\n        if (lastErrorTime <= 0) {\n            return null;\n        }\n\n        return new Date(lastErrorTime);\n    }\n\n    public void connectError(Throwable error) {\n        connectErrorCount.incrementAndGet();\n        connectErrorLast = error;\n\n        errorCount.incrementAndGet();\n        lastError = error;\n        lastErrorTime = System.currentTimeMillis();\n    }\n\n    public void error(Throwable error) {\n        errorCount.incrementAndGet();\n        lastError = error;\n        lastErrorTime = System.currentTimeMillis();\n    }\n\n    @Override\n    public long getCloseCount() {\n        return this.closeCount.get();\n    }\n\n    @Override\n    public long getCommitCount() {\n        return this.commitCount.get();\n    }\n\n    @Override\n    public long getConnectCount() {\n        return connectCount.get();\n    }\n\n    @Override\n    public long getConnectMillis() {\n        return connectNanoTotal.get() / (1000 * 1000);\n    }\n\n    @Override\n    public int getActiveMax() {\n        return this.activeCountMax.get();\n    }\n\n    @Override\n    public long getRollbackCount() {\n        return rollbackCount.get();\n    }\n\n    @Override\n    public long getConnectErrorCount() {\n        return connectErrorCount.get();\n    }\n\n    @Override\n    public Date getConnectLastTime() {\n        if (connectLastTime == 0) {\n            return null;\n        }\n\n        return new Date(connectLastTime);\n    }\n\n    public void incrementConnectionCloseCount() {\n        closeCount.incrementAndGet();\n    }\n\n    public void incrementConnectionCommitCount() {\n        commitCount.incrementAndGet();\n    }\n\n    public void incrementConnectionRollbackCount() {\n        rollbackCount.incrementAndGet();\n    }\n\n    public void incrementTransactionStartCount() {\n        transactionStartCount.incrementAndGet();\n    }\n\n    public long getTransactionStartCount() {\n        return transactionStartCount.get();\n    }\n\n    public static class Entry implements EntryMBean {\n        private long id;\n        private long establishTime;\n        private long establishNano;\n        private Date connectTime;\n        private long connectTimespanNano;\n        private Exception connectStackTraceException;\n\n        private String lastSql;\n        private Exception lastStatementStatckTraceException;\n        protected Throwable lastError;\n        protected long lastErrorTime;\n        private final String dataSource;\n\n        public Entry(String dataSource, long connectionId) {\n            this.id = connectionId;\n            this.dataSource = dataSource;\n        }\n\n        public void reset() {\n            this.lastSql = null;\n            this.lastStatementStatckTraceException = null;\n            this.lastError = null;\n            this.lastErrorTime = 0;\n        }\n\n        public Date getEstablishTime() {\n            if (establishTime <= 0) {\n                return null;\n            }\n            return new Date(establishTime);\n        }\n\n        public void setEstablishTime(long establishTime) {\n            this.establishTime = establishTime;\n        }\n\n        public long getEstablishNano() {\n            return establishNano;\n        }\n\n        public void setEstablishNano(long establishNano) {\n            this.establishNano = establishNano;\n        }\n\n        public Date getConnectTime() {\n            return connectTime;\n        }\n\n        public void setConnectTime(Date connectTime) {\n            this.connectTime = connectTime;\n        }\n\n        public long getConnectTimespanNano() {\n            return connectTimespanNano;\n        }\n\n        public void setConnectTimespanNano(long connectTimespanNano) {\n            this.connectTimespanNano = connectTimespanNano;\n        }\n\n        public String getLastSql() {\n            return lastSql;\n        }\n\n        public void setLastSql(String lastSql) {\n            this.lastSql = lastSql;\n        }\n\n        public String getConnectStackTrace() {\n            if (connectStackTraceException == null) {\n                return null;\n            }\n\n            StringWriter buf = new StringWriter();\n            connectStackTraceException.printStackTrace(new PrintWriter(buf));\n            return buf.toString();\n        }\n\n        public void setConnectStackTrace(Exception connectStackTraceException) {\n            this.connectStackTraceException = connectStackTraceException;\n        }\n\n        public String getLastStatementStatckTrace() {\n            if (lastStatementStatckTraceException == null) {\n                return null;\n            }\n\n            StringWriter buf = new StringWriter();\n            lastStatementStatckTraceException.printStackTrace(new PrintWriter(buf));\n            return buf.toString();\n        }\n\n        public void setLastStatementStatckTrace(Exception lastStatementStatckTrace) {\n            this.lastStatementStatckTraceException = lastStatementStatckTrace;\n        }\n\n        public void error(Throwable lastError) {\n            this.lastError = lastError;\n            this.lastErrorTime = System.currentTimeMillis();\n        }\n\n        public Date getLastErrorTime() {\n            if (lastErrorTime <= 0) {\n                return null;\n            }\n            return new Date(lastErrorTime);\n        }\n\n        private static String[] indexNames = {\"ID\", \"ConnectTime\", \"ConnectTimespan\", \"EstablishTime\",\n                \"AliveTimespan\", \"LastSql\", \"LastError\", \"LastErrorTime\",\n                \"ConnectStatckTrace\", \"LastStatementStackTrace\", \"DataSource\"};\n        private static String[] indexDescriptions = indexNames;\n\n        public static CompositeType getCompositeType() throws JMException {\n            OpenType<?>[] indexTypes = new OpenType<?>[]{SimpleType.LONG, SimpleType.DATE, SimpleType.LONG,\n                    SimpleType.DATE, SimpleType.LONG,\n\n                    SimpleType.STRING, JMXUtils.getThrowableCompositeType(), SimpleType.DATE, SimpleType.STRING,\n                    SimpleType.STRING,\n\n                    SimpleType.STRING};\n\n            return new CompositeType(\"ConnectionStatistic\", \"Connection Statistic\", indexNames, indexDescriptions,\n                    indexTypes);\n        }\n\n        public String getDataSource() {\n            return this.dataSource;\n        }\n\n        public CompositeDataSupport getCompositeData() throws JMException {\n            Map<String, Object> map = new HashMap<String, Object>();\n\n            map.put(\"ID\", id);\n            map.put(\"ConnectTime\", getConnectTime());\n            map.put(\"ConnectTimespan\", getConnectTimespanNano() / (1000 * 1000));\n            map.put(\"EstablishTime\", getEstablishTime());\n            map.put(\"AliveTimespan\", (System.nanoTime() - getEstablishNano()) / (1000 * 1000));\n\n            map.put(\"LastSql\", getLastSql());\n            map.put(\"LastError\", JMXUtils.getErrorCompositeData(this.lastError));\n            map.put(\"LastErrorTime\", getLastErrorTime());\n            map.put(\"ConnectStatckTrace\", getConnectStackTrace());\n            map.put(\"LastStatementStackTrace\", getLastStatementStatckTrace());\n\n            map.put(\"DataSource\", this.getDataSource());\n\n            return new CompositeDataSupport(getCompositeType(), map);\n        }\n    }\n\n    public interface EntryMBean {\n        Date getEstablishTime();\n\n        long getEstablishNano();\n\n        Date getConnectTime();\n\n        long getConnectTimespanNano();\n\n        String getLastSql();\n\n        String getConnectStackTrace();\n\n        String getLastStatementStatckTrace();\n\n        Date getLastErrorTime();\n\n        void reset();\n    }\n\n    public long[] getHistorgramValues() {\n        return this.histogram.toArray();\n    }\n\n    public long[] getHistogramRanges() {\n        return this.histogram.getRanges();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcConnectionStatMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport java.util.Date;\n\npublic interface JdbcConnectionStatMBean {\n    long getConnectCount();\n\n    long getCloseCount();\n\n    int getActiveMax();\n\n    long getCommitCount();\n\n    long getRollbackCount();\n\n    long getConnectMillis();\n\n    long getConnectErrorCount();\n\n    Date getConnectLastTime();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.Constants;\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.Histogram;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.CompositeType;\nimport javax.management.openmbean.TabularData;\nimport javax.management.openmbean.TabularDataSupport;\nimport javax.management.openmbean.TabularType;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\n\npublic class JdbcDataSourceStat implements JdbcDataSourceStatMBean {\n    private static final Log LOG = LogFactory.getLog(JdbcDataSourceStat.class);\n\n    private final String name;\n    private final String url;\n    private String dbType;\n\n    private final JdbcConnectionStat connectionStat = new JdbcConnectionStat();\n    private final JdbcResultSetStat resultSetStat = new JdbcResultSetStat();\n    private final JdbcStatementStat statementStat = new JdbcStatementStat();\n\n    private int maxSqlSize = 1000;\n\n    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();\n    private final LinkedHashMap<String, JdbcSqlStat> sqlStatMap;\n\n    private final AtomicLong skipSqlCount = new AtomicLong();\n\n    private final Histogram connectionHoldHistogram = new Histogram(new long[]{ //\n            //\n            1, 10, 100, 1000, 10 * 1000, //\n            100 * 1000, 1000 * 1000\n            //\n    });\n\n    private final ConcurrentMap<Long, JdbcConnectionStat.Entry> connections = new ConcurrentHashMap<Long, JdbcConnectionStat.Entry>(\n            16,\n            0.75f,\n            1);\n\n    private final AtomicLong clobOpenCount = new AtomicLong();\n    private final AtomicLong blobOpenCount = new AtomicLong();\n    private final AtomicLong keepAliveCheckCount = new AtomicLong();\n\n    private boolean resetStatEnable = true;\n\n    private static JdbcDataSourceStat global;\n\n    static {\n        String dbType = null;\n        {\n            String property = System.getProperty(\"druid.globalDbType\");\n            if (property != null && property.length() > 0) {\n                dbType = property;\n            }\n        }\n        global = new JdbcDataSourceStat(\"Global\", \"Global\", dbType);\n    }\n\n    public static JdbcDataSourceStat getGlobal() {\n        return global;\n    }\n\n    public static void setGlobal(JdbcDataSourceStat value) {\n        global = value;\n    }\n\n    public void configFromProperties(Properties properties) {\n    }\n\n    public boolean isResetStatEnable() {\n        return resetStatEnable;\n    }\n\n    public void setResetStatEnable(boolean resetStatEnable) {\n        this.resetStatEnable = resetStatEnable;\n    }\n\n    public JdbcDataSourceStat(String name, String url) {\n        this(name, url, null);\n    }\n\n    public JdbcDataSourceStat(String name, String url, String dbType) {\n        this(name, url, dbType, null);\n    }\n\n    @SuppressWarnings(\"serial\")\n    public JdbcDataSourceStat(String name, String url, String dbType, Properties connectProperties) {\n        this.name = name;\n        this.url = url;\n        this.dbType = dbType;\n\n        if (connectProperties != null) {\n            Object arg = connectProperties.get(Constants.DRUID_STAT_SQL_MAX_SIZE);\n\n            if (arg == null) {\n                arg = System.getProperty(Constants.DRUID_STAT_SQL_MAX_SIZE);\n            }\n\n            if (arg != null) {\n                try {\n                    maxSqlSize = Integer.parseInt(arg.toString());\n                } catch (NumberFormatException ex) {\n                    LOG.error(\"maxSize parse error\", ex);\n                }\n            }\n        }\n\n        sqlStatMap = new LinkedHashMap<String, JdbcSqlStat>(16, 0.75f, false) {\n            protected boolean removeEldestEntry(Map.Entry<String, JdbcSqlStat> eldest) {\n                boolean remove = (size() > maxSqlSize);\n\n                if (remove) {\n                    JdbcSqlStat sqlStat = eldest.getValue();\n                    if (sqlStat.getRunningCount() > 0 || sqlStat.getExecuteCount() > 0) {\n                        skipSqlCount.incrementAndGet();\n                    }\n                }\n\n                return remove;\n            }\n        };\n    }\n\n    public int getMaxSqlSize() {\n        return this.maxSqlSize;\n    }\n\n    public void setMaxSqlSize(int value) {\n        if (value == this.maxSqlSize) {\n            return;\n        }\n\n        lock.writeLock().lock();\n        try {\n            if (value < this.maxSqlSize) {\n                int removeCount = this.maxSqlSize - value;\n                Iterator<Map.Entry<String, JdbcSqlStat>> iter = sqlStatMap.entrySet().iterator();\n                while (iter.hasNext()) {\n                    iter.next();\n                    if (removeCount > 0) {\n                        iter.remove();\n                        removeCount--;\n                    } else {\n                        break;\n                    }\n                }\n            }\n            this.maxSqlSize = value;\n        } finally {\n            lock.writeLock().unlock();\n        }\n    }\n\n    public String getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(String dbType) {\n        this.dbType = dbType;\n    }\n\n    public long getSkipSqlCount() {\n        return skipSqlCount.get();\n    }\n\n    public long getSkipSqlCountAndReset() {\n        return skipSqlCount.getAndSet(0);\n    }\n\n    public void reset() {\n        if (!isResetStatEnable()) {\n            return;\n        }\n\n        blobOpenCount.set(0);\n        clobOpenCount.set(0);\n\n        connectionStat.reset();\n        statementStat.reset();\n        resultSetStat.reset();\n        connectionHoldHistogram.reset();\n        skipSqlCount.set(0);\n\n        lock.writeLock().lock();\n        try {\n            Iterator<Map.Entry<String, JdbcSqlStat>> iter = sqlStatMap.entrySet().iterator();\n            while (iter.hasNext()) {\n                Map.Entry<String, JdbcSqlStat> entry = iter.next();\n                JdbcSqlStat stat = entry.getValue();\n                if (stat.getExecuteCount() == 0 && stat.getRunningCount() == 0) {\n                    stat.setRemoved(true);\n                    iter.remove();\n                } else {\n                    stat.reset();\n                }\n            }\n        } finally {\n            lock.writeLock().unlock();\n        }\n\n        for (JdbcConnectionStat.Entry connectionStat : connections.values()) {\n            connectionStat.reset();\n        }\n    }\n\n    public Histogram getConnectionHoldHistogram() {\n        return connectionHoldHistogram;\n    }\n\n    public JdbcConnectionStat getConnectionStat() {\n        return connectionStat;\n    }\n\n    public JdbcResultSetStat getResultSetStat() {\n        return resultSetStat;\n    }\n\n    public JdbcStatementStat getStatementStat() {\n        return statementStat;\n    }\n\n    @Override\n    public String getConnectionUrl() {\n        return url;\n    }\n\n    @Override\n    public TabularData getSqlList() throws JMException {\n        Map<String, JdbcSqlStat> sqlStatMap = this.getSqlStatMap();\n        CompositeType rowType = JdbcSqlStat.getCompositeType();\n        String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]);\n\n        TabularType tabularType = new TabularType(\"SqlListStatistic\", \"SqlListStatistic\", rowType, indexNames);\n        TabularData data = new TabularDataSupport(tabularType);\n\n        for (Map.Entry<String, JdbcSqlStat> entry : sqlStatMap.entrySet()) {\n            data.put(entry.getValue().getCompositeData());\n        }\n\n        return data;\n    }\n\n    public static StatFilter getStatFilter(DataSourceProxy dataSource) {\n        for (Filter filter : dataSource.getProxyFilters()) {\n            if (filter instanceof StatFilter) {\n                return (StatFilter) filter;\n            }\n        }\n\n        return null;\n    }\n\n    public JdbcSqlStat getSqlStat(int id) {\n        return getSqlStat((long) id);\n    }\n\n    public JdbcSqlStat getSqlStat(long id) {\n        lock.readLock().lock();\n        try {\n            for (Map.Entry<String, JdbcSqlStat> entry : this.sqlStatMap.entrySet()) {\n                if (entry.getValue().getId() == id) {\n                    return entry.getValue();\n                }\n            }\n\n            return null;\n        } finally {\n            lock.readLock().unlock();\n        }\n    }\n\n    public final ConcurrentMap<Long, JdbcConnectionStat.Entry> getConnections() {\n        return connections;\n    }\n\n    @Override\n    public TabularData getConnectionList() throws JMException {\n        CompositeType rowType = JdbcConnectionStat.Entry.getCompositeType();\n        String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]);\n\n        TabularType tabularType = new TabularType(\"ConnectionListStatistic\", \"ConnectionListStatistic\", rowType,\n                indexNames);\n        TabularData data = new TabularDataSupport(tabularType);\n\n        for (Map.Entry<Long, JdbcConnectionStat.Entry> entry : getConnections().entrySet()) {\n            data.put(entry.getValue().getCompositeData());\n        }\n\n        return data;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public Map<String, JdbcSqlStat> getSqlStatMap() {\n        Map<String, JdbcSqlStat> map = new LinkedHashMap<String, JdbcSqlStat>(sqlStatMap.size());\n        lock.readLock().lock();\n        try {\n            map.putAll(sqlStatMap);\n        } finally {\n            lock.readLock().unlock();\n        }\n        return map;\n    }\n\n    public List<JdbcSqlStatValue> getSqlStatMapAndReset() {\n        List<JdbcSqlStat> stats = new ArrayList<JdbcSqlStat>(sqlStatMap.size());\n        lock.writeLock().lock();\n        try {\n            Iterator<Map.Entry<String, JdbcSqlStat>> iter = sqlStatMap.entrySet().iterator();\n            while (iter.hasNext()) {\n                Map.Entry<String, JdbcSqlStat> entry = iter.next();\n                JdbcSqlStat stat = entry.getValue();\n                if (stat.getExecuteCount() == 0 && stat.getRunningCount() == 0) {\n                    stat.setRemoved(true);\n                    iter.remove();\n                } else {\n                    stats.add(entry.getValue());\n                }\n            }\n        } finally {\n            lock.writeLock().unlock();\n        }\n\n        List<JdbcSqlStatValue> values = new ArrayList<JdbcSqlStatValue>(stats.size());\n        for (JdbcSqlStat stat : stats) {\n            JdbcSqlStatValue value = stat.getValueAndReset();\n            if (value.getExecuteCount() == 0 && value.getRunningCount() == 0) {\n                continue;\n            }\n            values.add(value);\n        }\n        return values;\n    }\n\n    public List<JdbcSqlStatValue> getRuningSqlList() {\n        List<JdbcSqlStat> stats = new ArrayList<JdbcSqlStat>(sqlStatMap.size());\n        lock.readLock().lock();\n        try {\n            for (Map.Entry<String, JdbcSqlStat> entry : sqlStatMap.entrySet()) {\n                JdbcSqlStat stat = entry.getValue();\n                if (stat.getRunningCount() >= 0) {\n                    stats.add(entry.getValue());\n                }\n            }\n        } finally {\n            lock.readLock().unlock();\n        }\n\n        List<JdbcSqlStatValue> values = new ArrayList<JdbcSqlStatValue>(stats.size());\n        for (JdbcSqlStat stat : stats) {\n            JdbcSqlStatValue value = stat.getValue(false);\n            if (value.getRunningCount() > 0) {\n                values.add(value);\n            }\n        }\n        return values;\n    }\n\n    public JdbcSqlStat getSqlStat(String sql) {\n        lock.readLock().lock();\n        try {\n            return sqlStatMap.get(sql);\n        } finally {\n            lock.readLock().unlock();\n        }\n    }\n\n    public JdbcSqlStat createSqlStat(String sql) {\n        lock.writeLock().lock();\n        try {\n            JdbcSqlStat sqlStat = sqlStatMap.get(sql);\n            if (sqlStat == null) {\n                sqlStat = new JdbcSqlStat(sql);\n                sqlStat.setDbType(this.dbType);\n                sqlStat.setName(this.name);\n                sqlStatMap.put(sql, sqlStat);\n            }\n\n            return sqlStat;\n        } finally {\n            lock.writeLock().unlock();\n        }\n    }\n\n    @Override\n    public long getConnectionActiveCount() {\n        return this.connections.size();\n    }\n\n    @Override\n    public long getConnectionConnectAliveMillis() {\n        long nowNano = System.nanoTime();\n        long aliveNanoSpan = this.getConnectionStat().getAliveTotal();\n\n        for (JdbcConnectionStat.Entry connection : connections.values()) {\n            aliveNanoSpan += nowNano - connection.getEstablishNano();\n        }\n        return aliveNanoSpan / (1000 * 1000);\n    }\n\n    public long getConnectionConnectAliveMillisMax() {\n        long max = this.getConnectionStat().getAliveNanoMax();\n\n        long nowNano = System.nanoTime();\n        for (JdbcConnectionStat.Entry connection : connections.values()) {\n            long connectionAliveNano = nowNano - connection.getEstablishNano();\n            if (connectionAliveNano > max) {\n                max = connectionAliveNano;\n            }\n        }\n        return max / (1000 * 1000);\n    }\n\n    public long getConnectionConnectAliveMillisMin() {\n        long min = this.getConnectionStat().getAliveNanoMin();\n\n        long nowNano = System.nanoTime();\n        for (JdbcConnectionStat.Entry connection : connections.values()) {\n            long connectionAliveNano = nowNano - connection.getEstablishNano();\n            if (connectionAliveNano < min || min == 0) {\n                min = connectionAliveNano;\n            }\n        }\n        return min / (1000 * 1000);\n    }\n\n    public long[] getConnectionHistogramRanges() {\n        return connectionStat.getHistogramRanges();\n    }\n\n    public long[] getConnectionHistogramValues() {\n        return connectionStat.getHistorgramValues();\n    }\n\n    public long getClobOpenCount() {\n        return clobOpenCount.get();\n    }\n\n    public long getClobOpenCountAndReset() {\n        return clobOpenCount.getAndSet(0);\n    }\n\n    public void incrementClobOpenCount() {\n        clobOpenCount.incrementAndGet();\n    }\n\n    public long getBlobOpenCount() {\n        return blobOpenCount.get();\n    }\n\n    public long getBlobOpenCountAndReset() {\n        return blobOpenCount.getAndSet(0);\n    }\n\n    public void incrementBlobOpenCount() {\n        blobOpenCount.incrementAndGet();\n    }\n\n    public long getKeepAliveCheckCount() {\n        return keepAliveCheckCount.get();\n    }\n\n    public long getKeepAliveCheckCountAndReset() {\n        return keepAliveCheckCount.getAndSet(0);\n    }\n\n    public void addKeepAliveCheckCount(long delta) {\n        keepAliveCheckCount.addAndGet(delta);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStatMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.TabularData;\n\npublic interface JdbcDataSourceStatMBean {\n    void reset();\n\n    TabularData getSqlList() throws JMException;\n\n    TabularData getConnectionList() throws JMException;\n\n    String getConnectionUrl();\n\n    long getConnectionActiveCount();\n\n    long getConnectionConnectAliveMillis();\n\n    long[] getConnectionHistogramValues();\n\n    long[] getConnectionHistogramRanges();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport java.util.Date;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\n\npublic class JdbcResultSetStat implements JdbcResultSetStatMBean {\n    private final AtomicInteger openingCount = new AtomicInteger();\n    private final AtomicInteger openingMax = new AtomicInteger();\n\n    private final AtomicLong openCount = new AtomicLong();\n    private final AtomicLong errorCount = new AtomicLong();\n\n    private final AtomicLong aliveNanoTotal = new AtomicLong();\n    private final AtomicLong aliveNanoMax = new AtomicLong();\n    private final AtomicLong aliveNanoMin = new AtomicLong();\n    private Throwable lastError;\n    private long lastErrorTime;\n\n    private long lastOpenTime;\n\n    private final AtomicLong fetchRowCount = new AtomicLong(0);  // 总共读取的行数\n    private final AtomicLong closeCount = new AtomicLong(0);  // ResultSet打开的计数\n\n    public void reset() {\n        openingMax.set(0);\n        openCount.set(0);\n        errorCount.set(0);\n        aliveNanoTotal.set(0);\n        aliveNanoMax.set(0);\n        aliveNanoMin.set(0);\n        lastError = null;\n        lastErrorTime = 0;\n        lastOpenTime = 0;\n        fetchRowCount.set(0);\n        closeCount.set(0);\n    }\n\n    public void beforeOpen() {\n        int invoking = openingCount.incrementAndGet();\n\n        for (; ; ) {\n            int max = openingMax.get();\n            if (invoking > max) {\n                if (openingMax.compareAndSet(max, invoking)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        openCount.incrementAndGet();\n        lastOpenTime = System.currentTimeMillis();\n    }\n\n    public long getErrorCount() {\n        return errorCount.get();\n    }\n\n    public int getOpeningCount() {\n        return openingCount.get();\n    }\n\n    public int getOpeningMax() {\n        return openingMax.get();\n    }\n\n    public long getOpenCount() {\n        return openCount.get();\n    }\n\n    public Date getLastOpenTime() {\n        if (lastOpenTime == 0) {\n            return null;\n        }\n\n        return new Date(lastOpenTime);\n    }\n\n    public long getAliveNanoTotal() {\n        return aliveNanoTotal.get();\n    }\n\n    public long getAliveMillisTotal() {\n        return aliveNanoTotal.get() / (1000 * 1000);\n    }\n\n    public long getAliveMilisMin() {\n        return aliveNanoMin.get() / (1000 * 1000);\n    }\n\n    public long getAliveMilisMax() {\n        return aliveNanoMax.get() / (1000 * 1000);\n    }\n\n    public void afterClose(long aliveNano) {\n        openingCount.decrementAndGet();\n\n        aliveNanoTotal.addAndGet(aliveNano);\n\n        for (; ; ) {\n            long max = aliveNanoMax.get();\n            if (aliveNano > max) {\n                if (aliveNanoMax.compareAndSet(max, aliveNano)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        for (; ; ) {\n            long min = aliveNanoMin.get();\n            if (aliveNano < min) {\n                if (aliveNanoMin.compareAndSet(min, aliveNano)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n    }\n\n    public Throwable getLastError() {\n        return lastError;\n    }\n\n    public Date getLastErrorTime() {\n        if (lastErrorTime <= 0) {\n            return null;\n        }\n\n        return new Date(lastErrorTime);\n    }\n\n    public void error(Throwable error) {\n        errorCount.incrementAndGet();\n        lastError = error;\n        lastErrorTime = System.currentTimeMillis();\n    }\n\n    @Override\n    public long getHoldMillisTotal() {\n        return getAliveNanoTotal() / (1000 * 1000);\n    }\n\n    @Override\n    public long getFetchRowCount() {\n        return fetchRowCount.get();\n    }\n\n    @Override\n    public long getCloseCount() {\n        return closeCount.get();\n    }\n\n    public void addFetchRowCount(long fetchCount) {\n        fetchRowCount.addAndGet(fetchCount);\n    }\n\n    public void incrementCloseCounter() {\n        closeCount.incrementAndGet();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcResultSetStatMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface JdbcResultSetStatMBean {\n    long getHoldMillisTotal();\n\n    long getFetchRowCount();\n\n    long getOpenCount();\n\n    long getCloseCount();\n\n    int getOpeningCount();\n\n    int getOpeningMax();\n\n    long getErrorCount();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.StatementExecuteType;\nimport com.alibaba.druid.util.JMXUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.*;\n\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic final class JdbcSqlStat implements JdbcSqlStatMBean, Comparable<JdbcSqlStat> {\n    private final String sql;\n    private long sqlHash;\n    private long id;\n    private String dataSource;\n    private long executeLastStartTime;\n\n    private volatile long executeBatchSizeTotal;\n    private volatile int executeBatchSizeMax;\n\n    private volatile long executeSuccessCount;\n    private volatile long executeSpanNanoTotal;\n    private volatile long executeSpanNanoMax;\n    private volatile int runningCount;\n    private volatile int concurrentMax;\n    private volatile long resultSetHoldTimeNano;\n    private volatile long executeAndResultSetHoldTime;\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeBatchSizeTotalUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeBatchSizeTotal\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> executeBatchSizeMaxUpdater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeBatchSizeMax\");\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeSuccessCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeSuccessCount\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeSpanNanoTotalUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeSpanNanoTotal\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeSpanNanoMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeSpanNanoMax\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> runningCountUpdater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"runningCount\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> concurrentMaxUpdater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"concurrentMax\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> resultSetHoldTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"resultSetHoldTimeNano\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeAndResultSetHoldTimeUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultSetHoldTime\");\n\n    private String name;\n    private String file;\n    private String dbType;\n\n    private volatile long executeNanoSpanMaxOccurTime;\n\n    private volatile long executeErrorCount;\n    private volatile Throwable executeErrorLast;\n    private volatile long executeErrorLastTime;\n\n    private volatile long updateCount;\n    private volatile long updateCountMax;\n    private volatile long fetchRowCount;\n    private volatile long fetchRowCountMax;\n\n    private volatile long inTransactionCount;\n\n    private volatile String lastSlowParameters;\n\n    private boolean removed;\n\n    private volatile long clobOpenCount;\n    private volatile long blobOpenCount;\n    private volatile long readStringLength;\n    private volatile long readBytesLength;\n\n    private volatile long inputStreamOpenCount;\n    private volatile long readerOpenCount;\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeErrorCount\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> updateCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCount\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> updateCountMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCountMax\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> fetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCount\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> fetchRowCountMaxUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCountMax\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> inTransactionCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"inTransactionCount\");\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> clobOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"clobOpenCount\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> blobOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"blobOpenCount\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> readStringLengthUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"readStringLength\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> readBytesLengthUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"readBytesLength\");\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> inputStreamOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"inputStreamOpenCount\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> readerOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"readerOpenCount\");\n\n    private volatile long histogram_0_1;\n    private volatile long histogram_1_10;\n    private volatile int histogram_10_100;\n    private volatile int histogram_100_1000;\n    private volatile int histogram_1000_10000;\n    private volatile int histogram_10000_100000;\n    private volatile int histogram_100000_1000000;\n    private volatile int histogram_1000000_more;\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> histogram_0_1_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_0_1\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> histogram_1_10_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_1_10\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> histogram_10_100_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_10_100\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> histogram_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_100_1000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> histogram_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_1000_10000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> histogram_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_10000_100000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> histogram_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_100000_1000000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> histogram_1000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"histogram_1000000_more\");\n\n    private volatile long executeAndResultHoldTime_0_1;\n    private volatile long executeAndResultHoldTime_1_10;\n    private volatile int executeAndResultHoldTime_10_100;\n    private volatile int executeAndResultHoldTime_100_1000;\n    private volatile int executeAndResultHoldTime_1000_10000;\n    private volatile int executeAndResultHoldTime_10000_100000;\n    private volatile int executeAndResultHoldTime_100000_1000000;\n    private volatile int executeAndResultHoldTime_1000000_more;\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_0_1_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_0_1\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_1_10_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_1_10\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_10_100_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_10_100\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_100_1000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_1000_10000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_10000_100000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_100000_1000000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> executeAndResultHoldTime_1000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"executeAndResultHoldTime_1000000_more\");\n\n    private volatile long fetchRowCount_0_1;\n    private volatile long fetchRowCount_1_10;\n    private volatile long fetchRowCount_10_100;\n    private volatile int fetchRowCount_100_1000;\n    private volatile int fetchRowCount_1000_10000;\n    private volatile int fetchRowCount_10000_more;\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> fetchRowCount_0_1_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCount_0_1\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> fetchRowCount_1_10_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCount_1_10\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> fetchRowCount_10_100_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCount_10_100\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> fetchRowCount_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCount_100_1000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> fetchRowCount_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCount_1000_10000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> fetchRowCount_10000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"fetchRowCount_10000_more\");\n\n    private volatile long updateCount_0_1;\n    private volatile long updateCount_1_10;\n    private volatile long updateCount_10_100;\n    private volatile int updateCount_100_1000;\n    private volatile int updateCount_1000_10000;\n    private volatile int updateCount_10000_more;\n\n    static final AtomicLongFieldUpdater<JdbcSqlStat> updateCount_0_1_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCount_0_1\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> updateCount_1_10_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCount_1_10\");\n    static final AtomicLongFieldUpdater<JdbcSqlStat> updateCount_10_100_Updater = AtomicLongFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCount_10_100\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> updateCount_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCount_100_1000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> updateCount_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCount_1000_10000\");\n    static final AtomicIntegerFieldUpdater<JdbcSqlStat> updateCount_10000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(JdbcSqlStat.class,\n            \"updateCount_10000_more\");\n\n    public JdbcSqlStat(String sql) {\n        this.sql = sql;\n        this.id = DruidDriver.createSqlStatId();\n    }\n\n    public String getLastSlowParameters() {\n        return lastSlowParameters;\n    }\n\n    public void setLastSlowParameters(String lastSlowParameters) {\n        this.lastSlowParameters = lastSlowParameters;\n    }\n\n    public String getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(String dbType) {\n        this.dbType = dbType;\n    }\n\n    public String getDataSource() {\n        return dataSource;\n    }\n\n    public void setDataSource(String dataSource) {\n        this.dataSource = dataSource;\n    }\n\n    public static final String getContextSqlName() {\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        if (context == null) {\n            return null;\n        }\n        return context.getName();\n    }\n\n    public static final void setContextSqlName(String val) {\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        if (context == null) {\n            context = JdbcStatManager.getInstance().createStatContext();\n            JdbcStatManager.getInstance().setStatContext(context);\n        }\n\n        context.setName(val);\n    }\n\n    public static final String getContextSqlFile() {\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        if (context == null) {\n            return null;\n        }\n        return context.getFile();\n    }\n\n    public static final void setContextSqlFile(String val) {\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        if (context == null) {\n            context = JdbcStatManager.getInstance().createStatContext();\n            JdbcStatManager.getInstance().setStatContext(context);\n        }\n\n        context.setFile(val);\n    }\n\n    public static final void setContextSql(String val) {\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        if (context == null) {\n            context = JdbcStatManager.getInstance().createStatContext();\n            JdbcStatManager.getInstance().setStatContext(context);\n        }\n\n        context.setSql(val);\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getFile() {\n        return file;\n    }\n\n    public void setFile(String file) {\n        this.file = file;\n    }\n\n    public void reset() {\n        executeLastStartTime = 0;\n\n        executeBatchSizeTotalUpdater.set(this, 0);\n        executeBatchSizeMaxUpdater.set(this, 0);\n\n        executeSuccessCountUpdater.set(this, 0);\n        executeSpanNanoTotalUpdater.set(this, 0);\n        executeSpanNanoMaxUpdater.set(this, 0);\n        executeNanoSpanMaxOccurTime = 0;\n        concurrentMaxUpdater.set(this, 0);\n\n        executeErrorCountUpdater.set(this, 0);\n        executeErrorLast = null;\n        executeErrorLastTime = 0;\n\n        updateCountUpdater.set(this, 0);\n        updateCountMaxUpdater.set(this, 0);\n        fetchRowCountUpdater.set(this, 0);\n        fetchRowCountMaxUpdater.set(this, 0);\n\n        histogram_0_1_Updater.set(this, 0);\n        histogram_1_10_Updater.set(this, 0);\n        histogram_10_100_Updater.set(this, 0);\n        histogram_100_1000_Updater.set(this, 0);\n        histogram_1000_10000_Updater.set(this, 0);\n        histogram_10000_100000_Updater.set(this, 0);\n        histogram_100000_1000000_Updater.set(this, 0);\n        histogram_1000000_more_Updater.set(this, 0);\n\n        this.lastSlowParameters = null;\n        inTransactionCountUpdater.set(this, 0);\n        resultSetHoldTimeNanoUpdater.set(this, 0);\n        executeAndResultSetHoldTimeUpdater.set(this, 0);\n\n        fetchRowCount_0_1_Updater.set(this, 0);\n        fetchRowCount_1_10_Updater.set(this, 0);\n        fetchRowCount_10_100_Updater.set(this, 0);\n        fetchRowCount_100_1000_Updater.set(this, 0);\n        fetchRowCount_1000_10000_Updater.set(this, 0);\n        fetchRowCount_10000_more_Updater.set(this, 0);\n\n        updateCount_0_1_Updater.set(this, 0);\n        updateCount_1_10_Updater.set(this, 0);\n        updateCount_10_100_Updater.set(this, 0);\n        updateCount_100_1000_Updater.set(this, 0);\n        updateCount_1000_10000_Updater.set(this, 0);\n        updateCount_10000_more_Updater.set(this, 0);\n\n        executeAndResultHoldTime_0_1_Updater.set(this, 0);\n        executeAndResultHoldTime_1_10_Updater.set(this, 0);\n        executeAndResultHoldTime_10_100_Updater.set(this, 0);\n        executeAndResultHoldTime_100_1000_Updater.set(this, 0);\n        executeAndResultHoldTime_1000_10000_Updater.set(this, 0);\n        executeAndResultHoldTime_10000_100000_Updater.set(this, 0);\n        executeAndResultHoldTime_100000_1000000_Updater.set(this, 0);\n        executeAndResultHoldTime_1000000_more_Updater.set(this, 0);\n\n        blobOpenCountUpdater.set(this, 0);\n        clobOpenCountUpdater.set(this, 0);\n        readStringLengthUpdater.set(this, 0);\n        readBytesLengthUpdater.set(this, 0);\n        inputStreamOpenCountUpdater.set(this, 0);\n        readerOpenCountUpdater.set(this, 0);\n    }\n\n    public JdbcSqlStatValue getValueAndReset() {\n        return getValue(true);\n    }\n\n    public JdbcSqlStatValue getValue(boolean reset) {\n        JdbcSqlStatValue val = new JdbcSqlStatValue();\n\n        val.setDbType(dbType);\n        val.setSql(sql);\n        val.setSqlHash(getSqlHash());\n        val.setId(id);\n        val.setName(name);\n        val.setFile(file);\n        val.setExecuteLastStartTime(executeLastStartTime);\n        if (reset) {\n            executeLastStartTime = 0;\n        }\n\n        val.setExecuteBatchSizeTotal(get(this, executeBatchSizeTotalUpdater, reset));\n        val.setExecuteBatchSizeMax(get(this, executeBatchSizeMaxUpdater, reset));\n\n        val.setExecuteSuccessCount(get(this, executeSuccessCountUpdater, reset));\n        val.setExecuteSpanNanoTotal(get(this, executeSpanNanoTotalUpdater, reset));\n        val.setExecuteSpanNanoMax(get(this, executeSpanNanoMaxUpdater, reset));\n        val.setExecuteNanoSpanMaxOccurTime(executeNanoSpanMaxOccurTime);\n        if (reset) {\n            executeNanoSpanMaxOccurTime = 0;\n        }\n\n        val.setRunningCount(this.runningCount);\n\n        val.setConcurrentMax(get(this, concurrentMaxUpdater, reset));\n\n        val.setExecuteErrorCount(get(this, executeErrorCountUpdater, reset));\n\n        val.setExecuteErrorLast(executeErrorLast);\n        if (reset) {\n            executeErrorLast = null;\n        }\n\n        val.setExecuteErrorLastTime(executeErrorLastTime);\n        if (reset) {\n            executeErrorLastTime = 0;\n        }\n\n        val.setUpdateCount(get(this, updateCountUpdater, reset));\n        val.setUpdateCountMax(get(this, updateCountMaxUpdater, reset));\n        val.setFetchRowCount(get(this, fetchRowCountUpdater, reset));\n        val.setFetchRowCountMax(get(this, fetchRowCountMaxUpdater, reset));\n\n        val.histogram_0_1 = get(this, histogram_0_1_Updater, reset);\n        val.histogram_1_10 = get(this, histogram_1_10_Updater, reset);\n        val.histogram_10_100 = get(this, histogram_10_100_Updater, reset);\n        val.histogram_100_1000 = get(this, histogram_100_1000_Updater, reset);\n        val.histogram_1000_10000 = get(this, histogram_1000_10000_Updater, reset);\n        val.histogram_10000_100000 = get(this, histogram_10000_100000_Updater, reset);\n        val.histogram_100000_1000000 = get(this, histogram_100000_1000000_Updater, reset);\n        val.histogram_1000000_more = get(this, histogram_1000000_more_Updater, reset);\n\n        val.setLastSlowParameters(lastSlowParameters);\n        if (reset) {\n            lastSlowParameters = null;\n        }\n\n        val.setInTransactionCount(get(this, inTransactionCountUpdater, reset));\n        val.setResultSetHoldTimeNano(get(this, resultSetHoldTimeNanoUpdater, reset));\n        val.setExecuteAndResultSetHoldTime(get(this, executeAndResultSetHoldTimeUpdater, reset));\n\n        val.fetchRowCount_0_1 = get(this, fetchRowCount_0_1_Updater, reset);\n        val.fetchRowCount_1_10 = get(this, fetchRowCount_1_10_Updater, reset);\n        val.fetchRowCount_10_100 = get(this, fetchRowCount_10_100_Updater, reset);\n        val.fetchRowCount_100_1000 = get(this, fetchRowCount_100_1000_Updater, reset);\n        val.fetchRowCount_1000_10000 = get(this, fetchRowCount_1000_10000_Updater, reset);\n        val.fetchRowCount_10000_more = get(this, fetchRowCount_10000_more_Updater, reset);\n\n        val.updateCount_0_1 = get(this, updateCount_0_1_Updater, reset);\n        val.updateCount_1_10 = get(this, updateCount_1_10_Updater, reset);\n        val.updateCount_10_100 = get(this, updateCount_10_100_Updater, reset);\n        val.updateCount_100_1000 = get(this, updateCount_100_1000_Updater, reset);\n        val.updateCount_1000_10000 = get(this, updateCount_1000_10000_Updater, reset);\n        val.updateCount_10000_more = get(this, updateCount_10000_more_Updater, reset);\n\n        val.executeAndResultHoldTime_0_1 = get(this, executeAndResultHoldTime_0_1_Updater, reset);\n        val.executeAndResultHoldTime_1_10 = get(this, executeAndResultHoldTime_1_10_Updater, reset);\n        val.executeAndResultHoldTime_10_100 = get(this, executeAndResultHoldTime_10_100_Updater, reset);\n        val.executeAndResultHoldTime_100_1000 = get(this, executeAndResultHoldTime_100_1000_Updater, reset);\n        val.executeAndResultHoldTime_1000_10000 = get(this, executeAndResultHoldTime_1000_10000_Updater, reset);\n        val.executeAndResultHoldTime_10000_100000 = get(this, executeAndResultHoldTime_10000_100000_Updater, reset);\n        val.executeAndResultHoldTime_100000_1000000 = get(this, executeAndResultHoldTime_100000_1000000_Updater, reset);\n        val.executeAndResultHoldTime_1000000_more = get(this, executeAndResultHoldTime_1000000_more_Updater, reset);\n\n        val.setBlobOpenCount(get(this, blobOpenCountUpdater, reset));\n        val.setClobOpenCount(get(this, clobOpenCountUpdater, reset));\n        val.setReadStringLength(get(this, readStringLengthUpdater, reset));\n        val.setReadBytesLength(get(this, readBytesLengthUpdater, reset));\n        val.setInputStreamOpenCount(get(this, inputStreamOpenCountUpdater, reset));\n        val.setReaderOpenCount(get(this, readerOpenCountUpdater, reset));\n\n        return val;\n    }\n\n    public long getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public long getRunningCount() {\n        return runningCount;\n    }\n\n    public void addUpdateCount(int delta) {\n        if (delta > 0) {\n            updateCountUpdater.addAndGet(this, delta);\n        }\n        for (; ; ) {\n            long max = updateCountMaxUpdater.get(this);\n            if (delta <= max) {\n                break;\n            }\n            if (updateCountMaxUpdater.compareAndSet(this, max, delta)) {\n                break;\n            }\n        }\n\n        if (delta < 1) {\n            updateCount_0_1_Updater.incrementAndGet(this);\n        } else if (delta < 10) {\n            updateCount_1_10_Updater.incrementAndGet(this);\n        } else if (delta < 100) {\n            updateCount_10_100_Updater.incrementAndGet(this);\n        } else if (delta < 1000) {\n            updateCount_100_1000_Updater.incrementAndGet(this);\n        } else if (delta < 10000) {\n            updateCount_1000_10000_Updater.incrementAndGet(this);\n        } else {\n            updateCount_10000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public long getUpdateCount() {\n        return updateCount;\n    }\n\n    public long getUpdateCountMax() {\n        return updateCountMax;\n    }\n\n    public long getFetchRowCount() {\n        return fetchRowCount;\n    }\n\n    public long getFetchRowCountMax() {\n        return fetchRowCountMax;\n    }\n\n    public long getClobOpenCount() {\n        return clobOpenCount;\n    }\n\n    public void incrementClobOpenCount() {\n        clobOpenCountUpdater.incrementAndGet(this);\n    }\n\n    public long getBlobOpenCount() {\n        return blobOpenCount;\n    }\n\n    public void incrementBlobOpenCount() {\n        blobOpenCountUpdater.incrementAndGet(this);\n    }\n\n    public long getReadStringLength() {\n        return readStringLength;\n    }\n\n    public void addStringReadLength(long length) {\n        readStringLengthUpdater.addAndGet(this, length);\n    }\n\n    public long getReadBytesLength() {\n        return readBytesLength;\n    }\n\n    public void addReadBytesLength(long length) {\n        readBytesLengthUpdater.addAndGet(this, length);\n    }\n\n    public long getReaderOpenCount() {\n        return readerOpenCount;\n    }\n\n    public void addReaderOpenCount(int count) {\n        readerOpenCountUpdater.addAndGet(this, count);\n    }\n\n    public long getInputStreamOpenCount() {\n        return inputStreamOpenCount;\n    }\n\n    public void addInputStreamOpenCount(int count) {\n        inputStreamOpenCountUpdater.addAndGet(this, count);\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public long getSqlHash() {\n        if (sqlHash == 0) {\n            sqlHash = Utils.fnv_64(sql);\n        }\n        return sqlHash;\n    }\n\n    public Date getExecuteLastStartTime() {\n        if (executeLastStartTime <= 0) {\n            return null;\n        }\n\n        return new Date(executeLastStartTime);\n    }\n\n    public void setExecuteLastStartTime(long executeLastStartTime) {\n        this.executeLastStartTime = executeLastStartTime;\n    }\n\n    public Date getExecuteNanoSpanMaxOccurTime() {\n        if (executeNanoSpanMaxOccurTime <= 0) {\n            return null;\n        }\n        return new Date(executeNanoSpanMaxOccurTime);\n    }\n\n    public Date getExecuteErrorLastTime() {\n        if (executeErrorLastTime <= 0) {\n            return null;\n        }\n        return new Date(executeErrorLastTime);\n    }\n\n    public void addFetchRowCount(long delta) {\n        fetchRowCountUpdater.addAndGet(this, delta);\n        for (; ; ) {\n            long max = fetchRowCountMaxUpdater.get(this);\n            if (delta <= max) {\n                break;\n            }\n            if (fetchRowCountMaxUpdater.compareAndSet(this, max, delta)) {\n                break;\n            }\n        }\n\n        if (delta < 1) {\n            fetchRowCount_0_1_Updater.incrementAndGet(this);\n        } else if (delta < 10) {\n            fetchRowCount_1_10_Updater.incrementAndGet(this);\n        } else if (delta < 100) {\n            fetchRowCount_10_100_Updater.incrementAndGet(this);\n        } else if (delta < 1000) {\n            fetchRowCount_100_1000_Updater.incrementAndGet(this);\n        } else if (delta < 10000) {\n            fetchRowCount_1000_10000_Updater.incrementAndGet(this);\n        } else {\n            fetchRowCount_10000_more_Updater.incrementAndGet(this);\n        }\n\n    }\n\n    public void addExecuteBatchCount(long batchSize) {\n        executeBatchSizeTotalUpdater.addAndGet(this, batchSize);\n\n        // executeBatchSizeMax\n        for (; ; ) {\n            int current = executeBatchSizeMaxUpdater.get(this);\n            if (current >= batchSize) {\n                break;\n            }\n\n            if (executeBatchSizeMaxUpdater.compareAndSet(this, current, (int) batchSize)) {\n                break;\n            }\n        }\n    }\n\n    public long getExecuteBatchSizeTotal() {\n        return executeBatchSizeTotal;\n    }\n\n    public void incrementExecuteSuccessCount() {\n        executeSuccessCountUpdater.incrementAndGet(this);\n    }\n\n    public void incrementRunningCount() {\n        int val = runningCountUpdater.incrementAndGet(this);\n\n        for (; ; ) {\n            int max = concurrentMaxUpdater.get(this);\n            if (val <= max) {\n                break;\n            }\n\n            if (concurrentMaxUpdater.compareAndSet(this, max, val)) {\n                break;\n            }\n        }\n    }\n\n    public void decrementRunningCount() {\n        runningCountUpdater.decrementAndGet(this);\n    }\n\n    /**\n     * @deprecated Use {@link #decrementRunningCount()} instead\n     */\n    @Deprecated\n    public void decrementExecutingCount() {\n        decrementRunningCount();\n    }\n\n    public long getExecuteSuccessCount() {\n        return executeSuccessCount;\n    }\n\n    public void addExecuteTime(StatementExecuteType executeType, boolean firstResultSet, long nanoSpan) {\n        addExecuteTime(nanoSpan);\n\n        if (StatementExecuteType.ExecuteQuery != executeType && !firstResultSet) {\n            executeAndResultHoldTimeHistogramRecord(nanoSpan);\n        }\n    }\n\n    private void executeAndResultHoldTimeHistogramRecord(long nanoSpan) {\n        long millis = nanoSpan / 1000 / 1000;\n\n        if (millis < 1) {\n            executeAndResultHoldTime_0_1_Updater.incrementAndGet(this);\n        } else if (millis < 10) {\n            executeAndResultHoldTime_1_10_Updater.incrementAndGet(this);\n        } else if (millis < 100) {\n            executeAndResultHoldTime_10_100_Updater.incrementAndGet(this);\n        } else if (millis < 1000) {\n            executeAndResultHoldTime_100_1000_Updater.incrementAndGet(this);\n        } else if (millis < 10000) {\n            executeAndResultHoldTime_1000_10000_Updater.incrementAndGet(this);\n        } else if (millis < 100000) {\n            executeAndResultHoldTime_10000_100000_Updater.incrementAndGet(this);\n        } else if (millis < 1000000) {\n            executeAndResultHoldTime_100000_1000000_Updater.incrementAndGet(this);\n        } else {\n            executeAndResultHoldTime_1000000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    private void histogramRecord(long nanoSpan) {\n        long millis = nanoSpan / 1000 / 1000;\n\n        if (millis < 1) {\n            histogram_0_1_Updater.incrementAndGet(this);\n        } else if (millis < 10) {\n            histogram_1_10_Updater.incrementAndGet(this);\n        } else if (millis < 100) {\n            histogram_10_100_Updater.incrementAndGet(this);\n        } else if (millis < 1000) {\n            histogram_100_1000_Updater.incrementAndGet(this);\n        } else if (millis < 10000) {\n            histogram_1000_10000_Updater.incrementAndGet(this);\n        } else if (millis < 100000) {\n            histogram_10000_100000_Updater.incrementAndGet(this);\n        } else if (millis < 1000000) {\n            histogram_100000_1000000_Updater.incrementAndGet(this);\n        } else {\n            histogram_1000000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public void addExecuteTime(long nanoSpan) {\n        executeSpanNanoTotalUpdater.addAndGet(this, nanoSpan);\n\n        for (; ; ) {\n            long current = executeSpanNanoMaxUpdater.get(this);\n            if (current >= nanoSpan) {\n                break;\n            }\n\n            if (executeSpanNanoMaxUpdater.compareAndSet(this, current, nanoSpan)) {\n                // 可能不准确，但是绝大多数情况下都会正确，性能换取一致性\n                executeNanoSpanMaxOccurTime = System.currentTimeMillis();\n                break;\n            }\n        }\n\n        histogramRecord(nanoSpan);\n    }\n\n    public long getExecuteMillisTotal() {\n        return executeSpanNanoTotal / (1000 * 1000);\n    }\n\n    public long getExecuteMillisMax() {\n        return executeSpanNanoMax / (1000 * 1000);\n    }\n\n    public long getErrorCount() {\n        return executeErrorCount;\n    }\n\n    @Override\n    public long getExecuteBatchSizeMax() {\n        return executeBatchSizeMax;\n    }\n\n    public long getInTransactionCount() {\n        return inTransactionCount;\n    }\n\n    public void incrementInTransactionCount() {\n        inTransactionCountUpdater.incrementAndGet(this);\n    }\n\n    private static CompositeType COMPOSITE_TYPE;\n\n    public static CompositeType getCompositeType() throws JMException {\n        if (COMPOSITE_TYPE != null) {\n            return COMPOSITE_TYPE;\n        }\n\n        OpenType<?>[] indexTypes = new OpenType<?>[]{\n                // 0 - 4\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n\n                // 5 - 9\n                SimpleType.LONG, //\n                SimpleType.DATE, //\n                SimpleType.LONG, //\n                JMXUtils.getThrowableCompositeType(), //\n                SimpleType.LONG, //\n                //\n\n                // 10 - 14\n                SimpleType.LONG, //\n                SimpleType.DATE, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                //\n\n                // 15 - 19\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                //\n\n                // 20 - 24\n                SimpleType.STRING, //\n                SimpleType.DATE, //\n                SimpleType.STRING, //\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n\n                // 25 - 29\n                new ArrayType<Long>(SimpleType.LONG, true), //\n                SimpleType.STRING, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                new ArrayType<Long>(SimpleType.LONG, true), //\n\n                // 30 - 34\n                new ArrayType<Long>(SimpleType.LONG, true), //\n                new ArrayType<Long>(SimpleType.LONG, true), //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n\n                // 35 - 39\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n\n                // 40 -\n                SimpleType.LONG, //\n\n        };\n\n        String[] indexNames = {\n                // 0 - 4\n                \"ID\", //\n                \"DataSource\", //\n                \"SQL\", //\n                \"ExecuteCount\", //\n                \"ErrorCount\", //\n\n                // 5 - 9\n                \"TotalTime\", //\n                \"LastTime\", //\n                \"MaxTimespan\", //\n                \"LastError\", //\n                \"EffectedRowCount\", //\n\n                // 10 - 14\n                \"FetchRowCount\", //\n                \"MaxTimespanOccurTime\", //\n                \"BatchSizeMax\", //\n                \"BatchSizeTotal\", //\n                \"ConcurrentMax\", //\n\n                // 15 - 19\n                \"RunningCount\", //\n                \"Name\", //\n                \"File\", //\n                \"LastErrorMessage\", //\n                \"LastErrorClass\", //\n\n                // 20 - 24\n                \"LastErrorStackTrace\", //\n                \"LastErrorTime\", //\n                \"DbType\", //\n                \"InTransactionCount\", //\n                \"URL\", //\n\n                // 25 - 29\n                \"Histogram\", //\n                \"LastSlowParameters\", //\n                \"ResultSetHoldTime\", //\n                \"ExecuteAndResultSetHoldTime\", //\n                \"FetchRowCountHistogram\", //\n\n                // 30 - 34\n                \"EffectedRowCountHistogram\", //\n                \"ExecuteAndResultHoldTimeHistogram\", //\n                \"EffectedRowCountMax\", //\n                \"FetchRowCountMax\", //\n                \"ClobOpenCount\",\n\n                // 35 -\n                \"BlobOpenCount\", //\n                \"ReadStringLength\", //\n                \"ReadBytesLength\", //\n                \"InputStreamOpenCount\", //\n                \"ReaderOpenCount\", //\n\n                // 40\n                \"HASH\", //\n\n                //\n        };\n        String[] indexDescriptions = indexNames;\n        COMPOSITE_TYPE = new CompositeType(\"SqlStatistic\", \"Sql Statistic\", indexNames, indexDescriptions, indexTypes);\n\n        return COMPOSITE_TYPE;\n    }\n\n    public long getExecuteCount() {\n        return getErrorCount() + getExecuteSuccessCount();\n    }\n\n    public Map<String, Object> getData() throws JMException {\n        return getValue(false).getData();\n    }\n\n    public long[] getHistogramValues() {\n        return new long[]{\n                //\n                histogram_0_1, //\n                histogram_1_10, //\n                histogram_10_100, //\n                histogram_100_1000, //\n                histogram_1000_10000, //\n                histogram_10000_100000, //\n                histogram_100000_1000000, //\n                histogram_1000000_more //\n        };\n    }\n\n    public long getHistogramSum() {\n        long[] values = this.getHistogramValues();\n        long sum = 0;\n        for (int i = 0; i < values.length; ++i) {\n            sum += values[i];\n        }\n        return sum;\n    }\n\n    public CompositeDataSupport getCompositeData() throws JMException {\n        return new CompositeDataSupport(getCompositeType(), getData());\n    }\n\n    public Throwable getExecuteErrorLast() {\n        return executeErrorLast;\n    }\n\n    public void error(Throwable error) {\n        executeErrorCountUpdater.incrementAndGet(this);\n        executeErrorLastTime = System.currentTimeMillis();\n        executeErrorLast = error;\n\n    }\n\n    public long getResultSetHoldTimeMilis() {\n        return getResultSetHoldTimeNano() / (1000 * 1000);\n    }\n\n    public long getExecuteAndResultSetHoldTimeMilis() {\n        return getExecuteAndResultSetHoldTimeNano() / (1000 * 1000);\n    }\n\n    public long[] getFetchRowCountHistogramValues() {\n        return new long[]{\n                //\n                fetchRowCount_0_1, //\n                fetchRowCount_1_10, //\n                fetchRowCount_10_100, //\n                fetchRowCount_100_1000, //\n                fetchRowCount_1000_10000, //\n                fetchRowCount_10000_more //\n        };\n    }\n\n    public long[] getUpdateCountHistogramValues() {\n        return new long[]{\n                //\n                updateCount_0_1, //\n                updateCount_1_10, //\n                updateCount_10_100, //\n                updateCount_100_1000, //\n                updateCount_1000_10000, //\n                updateCount_10000_more //\n        };\n    }\n\n    public long[] getExecuteAndResultHoldTimeHistogramValues() {\n        return new long[]{\n                //\n                executeAndResultHoldTime_0_1, //\n                executeAndResultHoldTime_1_10, //\n                executeAndResultHoldTime_10_100, //\n                executeAndResultHoldTime_100_1000, //\n                executeAndResultHoldTime_1000_10000, //\n                executeAndResultHoldTime_10000_100000, //\n                executeAndResultHoldTime_100000_1000000, //\n                executeAndResultHoldTime_1000000_more //\n        };\n    }\n\n    public long getExecuteAndResultHoldTimeHistogramSum() {\n        long[] values = this.getExecuteAndResultHoldTimeHistogramValues();\n        long sum = 0;\n        for (int i = 0; i < values.length; ++i) {\n            sum += values[i];\n        }\n        return sum;\n    }\n\n    public long getResultSetHoldTimeNano() {\n        return resultSetHoldTimeNano;\n    }\n\n    public long getExecuteAndResultSetHoldTimeNano() {\n        return executeAndResultSetHoldTime;\n    }\n\n    public void addResultSetHoldTimeNano(long nano) {\n        resultSetHoldTimeNanoUpdater.addAndGet(this, nano);\n    }\n\n    public void addResultSetHoldTimeNano(long statementExecuteNano, long resultHoldTimeNano) {\n        resultSetHoldTimeNanoUpdater.addAndGet(this, resultHoldTimeNano);\n        executeAndResultSetHoldTimeUpdater.addAndGet(this, statementExecuteNano + resultHoldTimeNano);\n        executeAndResultHoldTimeHistogramRecord(statementExecuteNano + resultHoldTimeNano);\n        updateCount_0_1_Updater.incrementAndGet(this);\n    }\n\n    public boolean isRemoved() {\n        return removed;\n    }\n\n    public void setRemoved(boolean removed) {\n        this.removed = removed;\n    }\n\n    @Override\n    public int compareTo(JdbcSqlStat o) {\n        if (o.sqlHash == this.sqlHash) {\n            return 0;\n        }\n\n        return this.id < o.id ? -1 : 1;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcSqlStatMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport java.util.Date;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic interface JdbcSqlStatMBean {\n    String getSql();\n\n    Date getExecuteLastStartTime();\n\n    Date getExecuteNanoSpanMaxOccurTime();\n\n    Date getExecuteErrorLastTime();\n\n    long getExecuteBatchSizeTotal();\n\n    long getExecuteBatchSizeMax();\n\n    long getExecuteSuccessCount();\n\n    long getExecuteMillisTotal();\n\n    long getExecuteMillisMax();\n\n    long getErrorCount();\n\n    long getConcurrentMax();\n\n    long getRunningCount();\n\n    String getName();\n\n    String getFile();\n\n    void reset();\n\n    long getFetchRowCount();\n\n    long getUpdateCount();\n\n    long getExecuteCount();\n\n    long getId();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\nimport com.alibaba.druid.util.JMXUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport javax.management.JMException;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\n@MTable(name = \"druid_sql\")\npublic class JdbcSqlStatValue {\n    protected long id;\n\n    protected String sql;\n\n    @MField(groupBy = true, aggregate = AggregateType.None, hashFor = \"sql\", hashForType = \"sql\")\n    private long sqlHash;\n\n    @MField(aggregate = AggregateType.None)\n    protected String dataSource;\n\n    @MField(name = \"lastStartTime\", aggregate = AggregateType.Max)\n    protected long executeLastStartTime;\n\n    @MField(name = \"batchTotal\", aggregate = AggregateType.Sum)\n    protected long executeBatchSizeTotal;\n\n    @MField(name = \"batchToMax\", aggregate = AggregateType.Max)\n    protected int executeBatchSizeMax;\n\n    @MField(name = \"execSuccessCount\", aggregate = AggregateType.Sum)\n    protected long executeSuccessCount;\n\n    @MField(name = \"execNanoTotal\", aggregate = AggregateType.Sum)\n    protected long executeSpanNanoTotal;\n\n    @MField(name = \"execNanoMax\", aggregate = AggregateType.Sum)\n    protected long executeSpanNanoMax;\n\n    @MField(name = \"running\", aggregate = AggregateType.Last)\n    protected int runningCount;\n\n    @MField(aggregate = AggregateType.Max)\n    protected int concurrentMax;\n\n    @MField(name = \"rsHoldTime\", aggregate = AggregateType.Sum)\n    protected long resultSetHoldTimeNano;\n\n    @MField(name = \"execRsHoldTime\", aggregate = AggregateType.Sum)\n    protected long executeAndResultSetHoldTime;\n\n    @MField(aggregate = AggregateType.None)\n    protected String name;\n\n    @MField(aggregate = AggregateType.None)\n    protected String file;\n\n    @MField(aggregate = AggregateType.None)\n    protected String dbType;\n\n    @MField(name = \"execNanoMaxOccurTime\", aggregate = AggregateType.Max)\n    protected long executeNanoSpanMaxOccurTime;\n\n    @MField(name = \"errorCount\", aggregate = AggregateType.Sum)\n    protected long executeErrorCount;\n\n    protected Throwable executeErrorLast;\n\n    @MField(name = \"errorLastMsg\", aggregate = AggregateType.Last)\n    protected String executeErrorLastMessage;\n\n    @MField(name = \"errorLastClass\", aggregate = AggregateType.Last)\n    protected String executeErrorLastClass;\n\n    @MField(name = \"errorLastStackTrace\", aggregate = AggregateType.Last)\n    protected String executeErrorLastStackTrace;\n\n    @MField(name = \"errorLastTime\", aggregate = AggregateType.Last)\n    protected long executeErrorLastTime;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long updateCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long updateCountMax;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long fetchRowCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long fetchRowCountMax;\n\n    @MField(name = \"inTxnCount\", aggregate = AggregateType.Sum)\n    protected long inTransactionCount;\n\n    @MField(aggregate = AggregateType.Last)\n    protected String lastSlowParameters;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long clobOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long blobOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long readStringLength;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long readBytesLength;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long inputStreamOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long readerOpenCount;\n\n    @MField(name = \"h1\", aggregate = AggregateType.Sum)\n    protected long histogram_0_1;\n\n    @MField(name = \"h10\", aggregate = AggregateType.Sum)\n    protected long histogram_1_10;\n\n    @MField(name = \"h100\", aggregate = AggregateType.Sum)\n    protected int histogram_10_100;\n\n    @MField(name = \"h1000\", aggregate = AggregateType.Sum)\n    protected int histogram_100_1000;\n\n    @MField(name = \"h10000\", aggregate = AggregateType.Sum)\n    protected int histogram_1000_10000;\n\n    @MField(name = \"h100000\", aggregate = AggregateType.Sum)\n    protected int histogram_10000_100000;\n\n    @MField(name = \"h1000000\", aggregate = AggregateType.Sum)\n    protected int histogram_100000_1000000;\n\n    @MField(name = \"hmore\", aggregate = AggregateType.Sum)\n    protected int histogram_1000000_more;\n\n    public long[] getExecuteHistogram() {\n        return new long[]{histogram_0_1, //\n                histogram_1_10, //\n                histogram_10_100, //\n                histogram_100_1000, //\n                histogram_1000_10000, //\n                histogram_10000_100000, //\n                histogram_100000_1000000, //\n                histogram_1000000_more, //\n        };\n    }\n\n    @MField(name = \"eh1\", aggregate = AggregateType.Sum)\n    protected long executeAndResultHoldTime_0_1;\n\n    @MField(name = \"eh10\", aggregate = AggregateType.Sum)\n    protected long executeAndResultHoldTime_1_10;\n\n    @MField(name = \"eh100\", aggregate = AggregateType.Sum)\n    protected int executeAndResultHoldTime_10_100;\n\n    @MField(name = \"eh1000\", aggregate = AggregateType.Sum)\n    protected int executeAndResultHoldTime_100_1000;\n\n    @MField(name = \"eh10000\", aggregate = AggregateType.Sum)\n    protected int executeAndResultHoldTime_1000_10000;\n\n    @MField(name = \"eh100000\", aggregate = AggregateType.Sum)\n    protected int executeAndResultHoldTime_10000_100000;\n\n    @MField(name = \"eh1000000\", aggregate = AggregateType.Sum)\n    protected int executeAndResultHoldTime_100000_1000000;\n\n    @MField(name = \"ehmore\", aggregate = AggregateType.Sum)\n    protected int executeAndResultHoldTime_1000000_more;\n\n    public long[] getExecuteAndResultHoldHistogram() {\n        return new long[]{executeAndResultHoldTime_0_1, //\n                executeAndResultHoldTime_1_10, //\n                executeAndResultHoldTime_10_100, //\n                executeAndResultHoldTime_100_1000, //\n                executeAndResultHoldTime_1000_10000, //\n                executeAndResultHoldTime_10000_100000, //\n                executeAndResultHoldTime_100000_1000000, //\n                executeAndResultHoldTime_1000000_more, //\n        };\n    }\n\n    @MField(name = \"f1\", aggregate = AggregateType.Sum)\n    protected long fetchRowCount_0_1;\n\n    @MField(name = \"f10\", aggregate = AggregateType.Sum)\n    protected long fetchRowCount_1_10;\n\n    @MField(name = \"f100\", aggregate = AggregateType.Sum)\n    protected long fetchRowCount_10_100;\n\n    @MField(name = \"f1000\", aggregate = AggregateType.Sum)\n    protected int fetchRowCount_100_1000;\n\n    @MField(name = \"f10000\", aggregate = AggregateType.Sum)\n    protected int fetchRowCount_1000_10000;\n\n    @MField(name = \"fmore\", aggregate = AggregateType.Sum)\n    protected int fetchRowCount_10000_more;\n\n    public long[] getFetchRowHistogram() {\n        return new long[]{fetchRowCount_0_1, //\n                fetchRowCount_1_10, //\n                fetchRowCount_10_100, //\n                fetchRowCount_100_1000, //\n                fetchRowCount_1000_10000, //\n                fetchRowCount_10000_more, //\n        };\n    }\n\n    @MField(name = \"u1\", aggregate = AggregateType.Sum)\n    protected long updateCount_0_1;\n\n    @MField(name = \"u10\", aggregate = AggregateType.Sum)\n    protected long updateCount_1_10;\n\n    @MField(name = \"u100\", aggregate = AggregateType.Sum)\n    protected long updateCount_10_100;\n\n    @MField(name = \"u1000\", aggregate = AggregateType.Sum)\n    protected int updateCount_100_1000;\n\n    @MField(name = \"u10000\", aggregate = AggregateType.Sum)\n    protected int updateCount_1000_10000;\n\n    @MField(name = \"umore\", aggregate = AggregateType.Sum)\n    protected int updateCount_10000_more;\n\n    public long[] getUpdateHistogram() {\n        return new long[]{updateCount_0_1, //\n                updateCount_1_10, //\n                updateCount_10_100, //\n                updateCount_100_1000, //\n                updateCount_1000_10000, //\n                updateCount_10000_more, //\n        };\n    }\n\n    public long getExecuteCount() {\n        return executeErrorCount + executeSuccessCount;\n    }\n\n    public long getExecuteMillisMax() {\n        return executeSpanNanoMax / (1000 * 1000);\n    }\n\n    public long getExecuteMillisTotal() {\n        return executeSpanNanoTotal / (1000 * 1000);\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public void setSql(String sql) {\n        this.sql = sql;\n    }\n\n    public long getSqlHash() {\n        return sqlHash;\n    }\n\n    public void setSqlHash(long sqlHash) {\n        this.sqlHash = sqlHash;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getDataSource() {\n        return dataSource;\n    }\n\n    public void setDataSource(String dataSource) {\n        this.dataSource = dataSource;\n    }\n\n    public long getExecuteLastStartTimeMillis() {\n        return executeLastStartTime;\n    }\n\n    public Date getExecuteLastStartTime() {\n        if (executeLastStartTime <= 0) {\n            return null;\n        }\n\n        return new Date(executeLastStartTime);\n    }\n\n    public void setExecuteLastStartTime(long executeLastStartTime) {\n        this.executeLastStartTime = executeLastStartTime;\n    }\n\n    public long getExecuteBatchSizeTotal() {\n        return executeBatchSizeTotal;\n    }\n\n    public void setExecuteBatchSizeTotal(long executeBatchSizeTotal) {\n        this.executeBatchSizeTotal = executeBatchSizeTotal;\n    }\n\n    public int getExecuteBatchSizeMax() {\n        return executeBatchSizeMax;\n    }\n\n    public void setExecuteBatchSizeMax(int executeBatchSizeMax) {\n        this.executeBatchSizeMax = executeBatchSizeMax;\n    }\n\n    public long getExecuteSuccessCount() {\n        return executeSuccessCount;\n    }\n\n    public void setExecuteSuccessCount(long executeSuccessCount) {\n        this.executeSuccessCount = executeSuccessCount;\n    }\n\n    public long getExecuteSpanNanoTotal() {\n        return executeSpanNanoTotal;\n    }\n\n    public void setExecuteSpanNanoTotal(long executeSpanNanoTotal) {\n        this.executeSpanNanoTotal = executeSpanNanoTotal;\n    }\n\n    public long getExecuteSpanNanoMax() {\n        return executeSpanNanoMax;\n    }\n\n    public void setExecuteSpanNanoMax(long executeSpanNanoMax) {\n        this.executeSpanNanoMax = executeSpanNanoMax;\n    }\n\n    public int getRunningCount() {\n        return runningCount;\n    }\n\n    public void setRunningCount(int runningCount) {\n        this.runningCount = runningCount;\n    }\n\n    public int getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public void setConcurrentMax(int concurrentMax) {\n        this.concurrentMax = concurrentMax;\n    }\n\n    public long getResultSetHoldTimeNano() {\n        return resultSetHoldTimeNano;\n    }\n\n    public void setResultSetHoldTimeNano(long resultSetHoldTimeNano) {\n        this.resultSetHoldTimeNano = resultSetHoldTimeNano;\n    }\n\n    public long getExecuteAndResultSetHoldTimeNano() {\n        return executeAndResultSetHoldTime;\n    }\n\n    public void setExecuteAndResultSetHoldTime(long executeAndResultSetHoldTime) {\n        this.executeAndResultSetHoldTime = executeAndResultSetHoldTime;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getFile() {\n        return file;\n    }\n\n    public void setFile(String file) {\n        this.file = file;\n    }\n\n    public String getDbType() {\n        return dbType;\n    }\n\n    public void setDbType(String dbType) {\n        this.dbType = dbType;\n    }\n\n    public long getExecuteNanoSpanMaxOccurTimeMillis() {\n        return executeNanoSpanMaxOccurTime;\n    }\n\n    public Date getExecuteNanoSpanMaxOccurTime() {\n        if (executeNanoSpanMaxOccurTime <= 0) {\n            return null;\n        }\n        return new Date(executeNanoSpanMaxOccurTime);\n    }\n\n    public Date getExecuteErrorLastTime() {\n        if (executeErrorLastTime <= 0) {\n            return null;\n        }\n        return new Date(executeErrorLastTime);\n    }\n\n    public void setExecuteNanoSpanMaxOccurTime(long executeNanoSpanMaxOccurTime) {\n        this.executeNanoSpanMaxOccurTime = executeNanoSpanMaxOccurTime;\n    }\n\n    public long getExecuteErrorCount() {\n        return executeErrorCount;\n    }\n\n    public void setExecuteErrorCount(long executeErrorCount) {\n        this.executeErrorCount = executeErrorCount;\n    }\n\n    public Throwable getExecuteErrorLast() {\n        return executeErrorLast;\n    }\n\n    public void setExecuteErrorLast(Throwable executeErrorLast) {\n        this.executeErrorLast = executeErrorLast;\n\n        if (executeErrorLast != null) {\n            this.executeErrorLastMessage = executeErrorLast.getMessage();\n            this.executeErrorLastClass = executeErrorLast.getClass().getName();\n            this.executeErrorLastStackTrace = Utils.toString(executeErrorLast.getStackTrace());\n        }\n    }\n\n    public long getExecuteErrorLastTimeMillis() {\n        return executeErrorLastTime;\n    }\n\n    public void setExecuteErrorLastTime(long executeErrorLastTime) {\n        this.executeErrorLastTime = executeErrorLastTime;\n    }\n\n    public long getUpdateCount() {\n        return updateCount;\n    }\n\n    public void setUpdateCount(long updateCount) {\n        this.updateCount = updateCount;\n    }\n\n    public long getUpdateCountMax() {\n        return updateCountMax;\n    }\n\n    public void setUpdateCountMax(long updateCountMax) {\n        this.updateCountMax = updateCountMax;\n    }\n\n    public long getFetchRowCount() {\n        return fetchRowCount;\n    }\n\n    public void setFetchRowCount(long fetchRowCount) {\n        this.fetchRowCount = fetchRowCount;\n    }\n\n    public long getFetchRowCountMax() {\n        return fetchRowCountMax;\n    }\n\n    public void setFetchRowCountMax(long fetchRowCountMax) {\n        this.fetchRowCountMax = fetchRowCountMax;\n    }\n\n    public long getInTransactionCount() {\n        return inTransactionCount;\n    }\n\n    public void setInTransactionCount(long inTransactionCount) {\n        this.inTransactionCount = inTransactionCount;\n    }\n\n    public String getLastSlowParameters() {\n        return lastSlowParameters;\n    }\n\n    public void setLastSlowParameters(String lastSlowParameters) {\n        this.lastSlowParameters = lastSlowParameters;\n    }\n\n    public long getClobOpenCount() {\n        return clobOpenCount;\n    }\n\n    public void setClobOpenCount(long clobOpenCount) {\n        this.clobOpenCount = clobOpenCount;\n    }\n\n    public long getBlobOpenCount() {\n        return blobOpenCount;\n    }\n\n    public void setBlobOpenCount(long blobOpenCount) {\n        this.blobOpenCount = blobOpenCount;\n    }\n\n    public long getReadStringLength() {\n        return readStringLength;\n    }\n\n    public void setReadStringLength(long readStringLength) {\n        this.readStringLength = readStringLength;\n    }\n\n    public long getReadBytesLength() {\n        return readBytesLength;\n    }\n\n    public void setReadBytesLength(long readBytesLength) {\n        this.readBytesLength = readBytesLength;\n    }\n\n    public long getInputStreamOpenCount() {\n        return inputStreamOpenCount;\n    }\n\n    public void setInputStreamOpenCount(long inputStreamOpenCount) {\n        this.inputStreamOpenCount = inputStreamOpenCount;\n    }\n\n    public long getReaderOpenCount() {\n        return readerOpenCount;\n    }\n\n    public void setReaderOpenCount(long readerOpenCount) {\n        this.readerOpenCount = readerOpenCount;\n    }\n\n    public long[] getHistogramValues() {\n        return new long[]{\n                //\n                histogram_0_1, //\n                histogram_1_10, //\n                histogram_10_100, //\n                histogram_100_1000, //\n                histogram_1000_10000, //\n                histogram_10000_100000, //\n                histogram_100000_1000000, //\n                histogram_1000000_more //\n        };\n    }\n\n    public long[] getFetchRowCountHistogramValues() {\n        return new long[]{\n                //\n                fetchRowCount_0_1, //\n                fetchRowCount_1_10, //\n                fetchRowCount_10_100, //\n                fetchRowCount_100_1000, //\n                fetchRowCount_1000_10000, //\n                fetchRowCount_10000_more //\n        };\n    }\n\n    public long[] getUpdateCountHistogramValues() {\n        return new long[]{\n                //\n                updateCount_0_1, //\n                updateCount_1_10, //\n                updateCount_10_100, //\n                updateCount_100_1000, //\n                updateCount_1000_10000, //\n                updateCount_10000_more //\n        };\n    }\n\n    public long[] getExecuteAndResultHoldTimeHistogramValues() {\n        return new long[]{\n                //\n                executeAndResultHoldTime_0_1, //\n                executeAndResultHoldTime_1_10, //\n                executeAndResultHoldTime_10_100, //\n                executeAndResultHoldTime_100_1000, //\n                executeAndResultHoldTime_1000_10000, //\n                executeAndResultHoldTime_10000_100000, //\n                executeAndResultHoldTime_100000_1000000, //\n                executeAndResultHoldTime_1000000_more //\n        };\n    }\n\n    public long getResultSetHoldTimeMilis() {\n        return getResultSetHoldTimeNano() / (1000 * 1000);\n    }\n\n    public long getExecuteAndResultSetHoldTimeMilis() {\n        return getExecuteAndResultSetHoldTimeNano() / (1000 * 1000);\n    }\n\n    public Map<String, Object> getData() throws JMException {\n        Map<String, Object> map = new HashMap<String, Object>(48);\n\n        // 0 - 4\n        map.put(\"ID\", id);\n        map.put(\"DataSource\", dataSource);\n        map.put(\"SQL\", sql);\n        map.put(\"ExecuteCount\", getExecuteCount());\n        map.put(\"ErrorCount\", getExecuteErrorCount());\n\n        // 5 - 9\n        map.put(\"TotalTime\", getExecuteMillisTotal());\n        map.put(\"LastTime\", getExecuteLastStartTime());\n        map.put(\"MaxTimespan\", getExecuteMillisMax());\n        map.put(\"LastError\", JMXUtils.getErrorCompositeData(this.getExecuteErrorLast()));\n        map.put(\"EffectedRowCount\", getUpdateCount());\n\n        // 10 - 14\n        map.put(\"FetchRowCount\", getFetchRowCount());\n        map.put(\"MaxTimespanOccurTime\", getExecuteNanoSpanMaxOccurTime());\n        map.put(\"BatchSizeMax\", (long) getExecuteBatchSizeMax());\n        map.put(\"BatchSizeTotal\", getExecuteBatchSizeTotal());\n        map.put(\"ConcurrentMax\", (long) getConcurrentMax());\n\n        // 15 -\n        map.put(\"RunningCount\", (long) getRunningCount()); // 15\n        map.put(\"Name\", getName()); // 16\n        map.put(\"File\", getFile()); // 17\n\n        if (executeErrorLastMessage != null) {\n            map.put(\"LastErrorMessage\", executeErrorLastMessage); // 18\n            map.put(\"LastErrorClass\", executeErrorLastClass); // 19\n\n            map.put(\"LastErrorStackTrace\", executeErrorLastStackTrace); // 20\n            map.put(\"LastErrorTime\", new Date(executeErrorLastTime)); // 21\n        } else {\n            map.put(\"LastErrorMessage\", null);\n            map.put(\"LastErrorClass\", null);\n            map.put(\"LastErrorStackTrace\", null);\n            map.put(\"LastErrorTime\", null);\n        }\n\n        map.put(\"DbType\", dbType); // 22\n        map.put(\"URL\", null); // 23\n        map.put(\"InTransactionCount\", getInTransactionCount()); // 24\n\n        map.put(\"Histogram\", this.getHistogramValues()); // 25\n        map.put(\"LastSlowParameters\", lastSlowParameters); // 26\n        map.put(\"ResultSetHoldTime\", getResultSetHoldTimeMilis()); // 27\n        map.put(\"ExecuteAndResultSetHoldTime\", this.getExecuteAndResultSetHoldTimeMilis()); // 28\n        map.put(\"FetchRowCountHistogram\", this.getFetchRowCountHistogramValues()); // 29\n\n        map.put(\"EffectedRowCountHistogram\", this.getUpdateCountHistogramValues()); // 30\n        map.put(\"ExecuteAndResultHoldTimeHistogram\", this.getExecuteAndResultHoldTimeHistogramValues()); // 31\n        map.put(\"EffectedRowCountMax\", getUpdateCountMax()); // 32\n        map.put(\"FetchRowCountMax\", getFetchRowCountMax()); // 33\n        map.put(\"ClobOpenCount\", getClobOpenCount()); // 34\n\n        map.put(\"BlobOpenCount\", getBlobOpenCount()); // 35\n        map.put(\"ReadStringLength\", getReadStringLength()); // 36\n        map.put(\"ReadBytesLength\", getReadBytesLength()); // 37\n        map.put(\"InputStreamOpenCount\", getInputStreamOpenCount()); // 38\n        map.put(\"ReaderOpenCount\", getReaderOpenCount()); // 39\n\n        map.put(\"HASH\", getSqlHash()); // 40\n\n        return map;\n    }\n\n    public long getHistogram_0_1() {\n        return histogram_0_1;\n    }\n\n    public void setHistogram_0_1(long histogram_0_1) {\n        this.histogram_0_1 = histogram_0_1;\n    }\n\n    public long getHistogram_1_10() {\n        return histogram_1_10;\n    }\n\n    public void setHistogram_1_10(long histogram_1_10) {\n        this.histogram_1_10 = histogram_1_10;\n    }\n\n    public int getHistogram_10_100() {\n        return histogram_10_100;\n    }\n\n    public void setHistogram_10_100(int histogram_10_100) {\n        this.histogram_10_100 = histogram_10_100;\n    }\n\n    public int getHistogram_100_1000() {\n        return histogram_100_1000;\n    }\n\n    public void setHistogram_100_1000(int histogram_100_1000) {\n        this.histogram_100_1000 = histogram_100_1000;\n    }\n\n    public int getHistogram_1000_10000() {\n        return histogram_1000_10000;\n    }\n\n    public void setHistogram_1000_10000(int histogram_1000_10000) {\n        this.histogram_1000_10000 = histogram_1000_10000;\n    }\n\n    public int getHistogram_10000_100000() {\n        return histogram_10000_100000;\n    }\n\n    public void setHistogram_10000_100000(int histogram_10000_100000) {\n        this.histogram_10000_100000 = histogram_10000_100000;\n    }\n\n    public int getHistogram_100000_1000000() {\n        return histogram_100000_1000000;\n    }\n\n    public void setHistogram_100000_1000000(int histogram_100000_1000000) {\n        this.histogram_100000_1000000 = histogram_100000_1000000;\n    }\n\n    public int getHistogram_1000000_more() {\n        return histogram_1000000_more;\n    }\n\n    public void setHistogram_1000000_more(int histogram_1000000_more) {\n        this.histogram_1000000_more = histogram_1000000_more;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcStatContext.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\npublic class JdbcStatContext {\n    private String name;\n    private String file;\n    private String sql;\n    private String requestId;\n\n    private boolean traceEnable;\n\n    public JdbcStatContext() {\n    }\n\n    public boolean isTraceEnable() {\n        return traceEnable;\n    }\n\n    public void setTraceEnable(boolean traceEnable) {\n        this.traceEnable = traceEnable;\n    }\n\n    public String getRequestId() {\n        return requestId;\n    }\n\n    public void setRequestId(String requestId) {\n        this.requestId = requestId;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getFile() {\n        return file;\n    }\n\n    public void setFile(String file) {\n        this.file = file;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public void setSql(String sql) {\n        this.sql = sql;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.*;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicLong;\n\npublic final class JdbcStatManager implements JdbcStatManagerMBean {\n    private final AtomicLong sqlIdSeed = new AtomicLong(1000);\n\n    private static final JdbcStatManager instance = new JdbcStatManager();\n\n    private final JdbcConnectionStat connectionStat = new JdbcConnectionStat();\n    private final JdbcResultSetStat resultSetStat = new JdbcResultSetStat();\n    private final JdbcStatementStat statementStat = new JdbcStatementStat();\n\n    private final AtomicLong resetCount = new AtomicLong();\n\n    public final ThreadLocal<JdbcStatContext> contextLocal = new ThreadLocal<JdbcStatContext>();\n\n    private JdbcStatManager() {\n    }\n\n    public JdbcStatContext getStatContext() {\n        return contextLocal.get();\n    }\n\n    public void setStatContext(JdbcStatContext context) {\n        contextLocal.set(context);\n    }\n\n    public JdbcStatContext createStatContext() {\n        return new JdbcStatContext();\n    }\n\n    public long generateSqlId() {\n        return sqlIdSeed.incrementAndGet();\n    }\n\n    public static JdbcStatManager getInstance() {\n        return instance;\n    }\n\n    public JdbcStatementStat getStatementStat() {\n        return statementStat;\n    }\n\n    public JdbcResultSetStat getResultSetStat() {\n        return resultSetStat;\n    }\n\n    public JdbcConnectionStat getConnectionStat() {\n        return connectionStat;\n    }\n\n    private static CompositeType COMPOSITE_TYPE;\n\n    public static CompositeType getDataSourceCompositeType() throws JMException {\n        if (COMPOSITE_TYPE != null) {\n            return COMPOSITE_TYPE;\n        }\n\n        OpenType<?>[] indexTypes = new OpenType<?>[]{\n                // 0 - 4\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                new ArrayType<SimpleType<String>>(SimpleType.STRING, false), //\n                SimpleType.DATE, //\n\n                // 5 - 9\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                SimpleType.INTEGER, //\n                SimpleType.INTEGER, //\n                SimpleType.STRING, //\n\n                // 10 - 14\n                SimpleType.LONG, //\n                SimpleType.INTEGER, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n\n                // 14 - 19\n                SimpleType.DATE, //\n                SimpleType.LONG, //\n                SimpleType.DATE, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n\n                // 20 - 24\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.INTEGER, //\n\n                // 25 - 29\n                SimpleType.INTEGER, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.DATE, //\n                SimpleType.STRING, //\n\n                // 30 - 34\n                SimpleType.STRING, //\n                SimpleType.LONG, //\n                SimpleType.INTEGER, //\n                SimpleType.DATE, //\n                SimpleType.LONG, //\n\n                // 35 - 39\n                SimpleType.LONG, //\n                SimpleType.INTEGER, //\n                SimpleType.INTEGER, //\n                SimpleType.LONG, //\n                SimpleType.DATE,\n\n                // 40 - 44\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                SimpleType.DATE, //\n                SimpleType.STRING, //\n                SimpleType.STRING,\n\n                // 45 - 49\n                SimpleType.LONG, //\n                SimpleType.STRING, //\n                SimpleType.STRING, //\n                SimpleType.LONG, //\n                SimpleType.INTEGER, //\n\n                // 50 - 54\n                SimpleType.LONG, //\n                SimpleType.DATE, //\n                SimpleType.LONG, //\n                SimpleType.LONG, //\n                new ArrayType<Long>(SimpleType.LONG, true), //\n\n                // 55 -\n                new ArrayType<Long>(SimpleType.LONG, true)\n                //\n                //\n        };\n\n        String[] indexNames = {\n                // 0 - 4\n                \"ID\",\n                \"URL\",\n                \"Name\",\n                \"FilterClasses\",\n                \"CreatedTime\", //\n\n                // 5 - 9\n                \"RawUrl\",\n                \"RawDriverClassName\",\n                \"RawDriverMajorVersion\",\n                \"RawDriverMinorVersion\",\n                \"Properties\",\n\n                // 10 - 14\n                \"ConnectionActiveCount\",\n                \"ConnectionActiveCountMax\",\n                \"ConnectionCloseCount\",\n                \"ConnectionCommitCount\",\n                \"ConnectionRollbackCount\",\n\n                // 15 - 19\n                \"ConnectionConnectLastTime\",\n                \"ConnectionConnectErrorCount\",\n                \"ConnectionConnectErrorLastTime\",\n                \"ConnectionConnectErrorLastMessage\",\n                \"ConnectionConnectErrorLastStackTrace\",\n\n                // 20 - 24\n                \"StatementCreateCount\",\n                \"StatementPrepareCount\",\n                \"StatementPreCallCount\",\n                \"StatementExecuteCount\",\n                \"StatementRunningCount\",\n\n                // 25 - 29\n                \"StatementConcurrentMax\",\n                \"StatementCloseCount\",\n                \"StatementErrorCount\",\n                \"StatementLastErrorTime\",\n                \"StatementLastErrorMessage\",\n\n                // 30 - 34\n                \"StatementLastErrorStackTrace\", \"StatementExecuteMillisTotal\", \"ConnectionConnectingCount\",\n                \"StatementExecuteLastTime\",\n                \"ResultSetCloseCount\",\n\n                // 35 -39\n                \"ResultSetOpenCount\",\n                \"ResultSetOpenningCount\",\n                \"ResultSetOpenningMax\",\n                \"ResultSetFetchRowCount\",\n                \"ResultSetLastOpenTime\",\n\n                // 40 - 44\n                \"ResultSetErrorCount\",\n                \"ResultSetOpenningMillisTotal\",\n                \"ResultSetLastErrorTime\",\n                \"ResultSetLastErrorMessage\",\n                \"ResultSetLastErrorStackTrace\",\n\n                // 45 - 49\n                \"ConnectionConnectCount\",\n                \"ConnectionErrorLastMessage\",\n                \"ConnectionErrorLastStackTrace\",\n                \"ConnectionConnectMillisTotal\",\n                \"ConnectionConnectingCountMax\",\n\n                // 50 - 54\n                \"ConnectionConnectMillisMax\", //\n                \"ConnectionErrorLastTime\", //\n                \"ConnectionAliveMillisMax\", //\n                \"ConnectionAliveMillisMin\", //\n                \"ConnectionHistogram\", //\n\n                // 55 -\n                \"StatementHistogram\",\n                //\n        };\n\n        COMPOSITE_TYPE = new CompositeType(\"DataSourceStatistic\", \"DataSource Statistic\", indexNames,\n                indexNames, indexTypes);\n\n        return COMPOSITE_TYPE;\n    }\n\n    @Override\n    public TabularData getDataSourceList() throws JMException {\n        CompositeType rowType = getDataSourceCompositeType();\n        String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]);\n\n        TabularType tabularType = new TabularType(\"DataSourceStat\", \"DataSourceStat\", rowType, indexNames);\n        TabularData data = new TabularDataSupport(tabularType);\n\n        {\n            final ConcurrentMap<String, DataSourceProxyImpl> dataSources = DruidDriver.getProxyDataSources();\n            for (DataSourceProxyImpl dataSource : dataSources.values()) {\n                data.put(dataSource.getCompositeData());\n            }\n        }\n\n        final Set<DataSourceMonitorable> dataSources = DruidDataSourceStatManager.getDruidDataSourceInstances();\n        for (DataSourceMonitorable dataSource : dataSources) {\n            data.put(dataSource.getCompositeData());\n        }\n\n        return data;\n    }\n\n    @Override\n    public TabularData getSqlList() throws JMException {\n        CompositeType rowType = JdbcSqlStat.getCompositeType();\n        String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]);\n\n        TabularType tabularType = new TabularType(\"SqlListStatistic\", \"SqlListStatistic\", rowType, indexNames);\n        TabularData data = new TabularDataSupport(tabularType);\n\n        JdbcDataSourceStat globalStat = JdbcDataSourceStat.getGlobal();\n        if (globalStat != null) {\n            Map<String, JdbcSqlStat> statMap = globalStat.getSqlStatMap();\n            for (Map.Entry<String, JdbcSqlStat> entry : statMap.entrySet()) {\n                if (entry.getValue().getExecuteCount() == 0 && entry.getValue().getRunningCount() == 0) {\n                    continue;\n                }\n\n                Map<String, Object> map = entry.getValue().getData();\n                map.put(\"URL\", globalStat.getUrl());\n                data.put(new CompositeDataSupport(JdbcSqlStat.getCompositeType(), map));\n            }\n        }\n\n        for (DataSourceProxyImpl dataSource : DruidDriver.getProxyDataSources().values()) {\n            JdbcDataSourceStat druidDataSourceStat = dataSource.getDataSourceStat();\n\n            if (druidDataSourceStat == globalStat) {\n                continue;\n            }\n\n            Map<String, JdbcSqlStat> statMap = druidDataSourceStat.getSqlStatMap();\n            for (Map.Entry<String, JdbcSqlStat> entry : statMap.entrySet()) {\n                if (entry.getValue().getExecuteCount() == 0 && entry.getValue().getRunningCount() == 0) {\n                    continue;\n                }\n\n                Map<String, Object> map = entry.getValue().getData();\n                map.put(\"URL\", dataSource.getUrl());\n                data.put(new CompositeDataSupport(JdbcSqlStat.getCompositeType(), map));\n            }\n        }\n\n        for (DataSourceMonitorable dataSource : DruidDataSourceStatManager.getDruidDataSourceInstances()) {\n            JdbcDataSourceStat druidDataSourceStat = dataSource.getDataSourceStat();\n\n            if (druidDataSourceStat == globalStat) {\n                continue;\n            }\n\n            Map<String, JdbcSqlStat> statMap = druidDataSourceStat.getSqlStatMap();\n            for (Map.Entry<String, JdbcSqlStat> entry : statMap.entrySet()) {\n                if (entry.getValue().getExecuteCount() == 0 && entry.getValue().getRunningCount() == 0) {\n                    continue;\n                }\n\n                Map<String, Object> map = entry.getValue().getData();\n                map.put(\"URL\", dataSource.getUrl());\n                data.put(new CompositeDataSupport(JdbcSqlStat.getCompositeType(), map));\n            }\n        }\n\n        return data;\n    }\n\n    public TabularData getConnectionList() throws JMException {\n        CompositeType rowType = JdbcConnectionStat.Entry.getCompositeType();\n        String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]);\n\n        TabularType tabularType = new TabularType(\"ConnectionList\", \"ConnectionList\", rowType, indexNames);\n        TabularData data = new TabularDataSupport(tabularType);\n\n        final ConcurrentMap<String, DataSourceProxyImpl> dataSources = DruidDriver.getProxyDataSources();\n        for (DataSourceProxyImpl dataSource : dataSources.values()) {\n            JdbcDataSourceStat dataSourceStat = dataSource.getDataSourceStat();\n            ConcurrentMap<Long, JdbcConnectionStat.Entry> connections = dataSourceStat.getConnections();\n            for (Map.Entry<Long, JdbcConnectionStat.Entry> entry : connections.entrySet()) {\n                data.put(entry.getValue().getCompositeData());\n            }\n        }\n\n        for (DataSourceMonitorable instance : DruidDataSourceStatManager.getDruidDataSourceInstances()) {\n            JdbcDataSourceStat dataSourceStat = instance.getDataSourceStat();\n            ConcurrentMap<Long, JdbcConnectionStat.Entry> connections = dataSourceStat.getConnections();\n            for (Map.Entry<Long, JdbcConnectionStat.Entry> entry : connections.entrySet()) {\n                data.put(entry.getValue().getCompositeData());\n            }\n        }\n\n        return data;\n    }\n\n    @Override\n    public void reset() {\n        resetCount.incrementAndGet();\n\n        connectionStat.reset();\n        statementStat.reset();\n        resultSetStat.reset();\n\n        final ConcurrentMap<String, DataSourceProxyImpl> dataSources = DruidDriver.getProxyDataSources();\n        for (DataSourceProxyImpl dataSource : dataSources.values()) {\n            dataSource.getDataSourceStat().reset();\n        }\n\n        for (DataSourceMonitorable instance : DruidDataSourceStatManager.getDruidDataSourceInstances()) {\n            instance.getDataSourceStat().reset();\n        }\n    }\n\n    @Override\n    public long getResetCount() {\n        return resetCount.get();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcStatManagerFactoryBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport org.springframework.beans.factory.FactoryBean;\n\npublic class JdbcStatManagerFactoryBean implements FactoryBean {\n    @Override\n    public Object getObject() throws Exception {\n        return JdbcStatManager.getInstance();\n    }\n\n    @Override\n    public Class<?> getObjectType() {\n        return JdbcStatManager.class;\n    }\n\n    @Override\n    public boolean isSingleton() {\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcStatManagerMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.TabularData;\n\npublic interface JdbcStatManagerMBean {\n    TabularData getDataSourceList() throws JMException;\n\n    TabularData getSqlList() throws JMException;\n\n    TabularData getConnectionList() throws JMException;\n\n    void reset();\n\n    long getResetCount();\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcStatementStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.util.Histogram;\nimport com.alibaba.druid.util.JMXUtils;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.CompositeData;\n\nimport java.util.Date;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\n\npublic class JdbcStatementStat implements JdbcStatementStatMBean {\n    private final AtomicLong createCount = new AtomicLong(0);                                     // 执行createStatement的计数\n    private final AtomicLong prepareCount = new AtomicLong(0);                                     // 执行parepareStatement的计数\n    private final AtomicLong prepareCallCount = new AtomicLong(0);                                     // 执行preCall的计数\n    private final AtomicLong closeCount = new AtomicLong(0);                                     // Statement关闭的计数\n\n    private final AtomicInteger runningCount = new AtomicInteger();\n    private final AtomicInteger concurrentMax = new AtomicInteger();\n\n    private final AtomicLong count = new AtomicLong();\n    private final AtomicLong errorCount = new AtomicLong();\n\n    private final AtomicLong nanoTotal = new AtomicLong();\n\n    private Throwable lastError;\n    private long lastErrorTime;\n\n    private long lastSampleTime;\n\n    private final Histogram histogram = new Histogram(new long[]{10, 100, 1000, 1000 * 10});\n\n    public long[] getHistogramRanges() {\n        return histogram.getRanges();\n    }\n\n    public long[] getHistogramValues() {\n        return histogram.toArray();\n    }\n\n    public void reset() {\n        runningCount.set(0);\n        concurrentMax.set(0);\n        count.set(0);\n        errorCount.set(0);\n        nanoTotal.set(0);\n        lastError = null;\n        lastErrorTime = 0;\n        lastSampleTime = 0;\n\n        createCount.set(0);\n        prepareCount.set(0);\n        prepareCallCount.set(0);\n        closeCount.set(0);\n\n        histogram.reset();\n    }\n\n    public void afterExecute(long nanoSpan) {\n        runningCount.decrementAndGet();\n\n        nanoTotal.addAndGet(nanoSpan);\n\n        long millis = nanoSpan / (1000 * 1000);\n        histogram.record(millis);\n    }\n\n    public void beforeExecute() {\n        int invoking = runningCount.incrementAndGet();\n\n        for (; ; ) {\n            int max = concurrentMax.get();\n            if (invoking > max) {\n                if (concurrentMax.compareAndSet(max, invoking)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        count.incrementAndGet();\n        lastSampleTime = System.currentTimeMillis();\n    }\n\n    public long getErrorCount() {\n        return errorCount.get();\n    }\n\n    public int getRunningCount() {\n        return runningCount.get();\n    }\n\n    public int getConcurrentMax() {\n        return concurrentMax.get();\n    }\n\n    public long getExecuteCount() {\n        return count.get();\n    }\n\n    public Date getExecuteLastTime() {\n        if (lastSampleTime == 0) {\n            return null;\n        }\n\n        return new Date(lastSampleTime);\n    }\n\n    public long getNanoTotal() {\n        return nanoTotal.get();\n    }\n\n    public long getMillisTotal() {\n        return nanoTotal.get() / (1000 * 1000);\n    }\n\n    public Throwable getLastException() {\n        return lastError;\n    }\n\n    public Date getLastErrorTime() {\n        if (lastErrorTime <= 0) {\n            return null;\n        }\n\n        return new Date(lastErrorTime);\n    }\n\n    public void error(Throwable error) {\n        errorCount.incrementAndGet();\n        lastError = error;\n        lastErrorTime = System.currentTimeMillis();\n    }\n\n    @Override\n    public long getCloseCount() {\n        return closeCount.get();\n    }\n\n    @Override\n    public long getCreateCount() {\n        return createCount.get();\n    }\n\n    @Override\n    public long getExecuteMillisTotal() {\n        return this.getNanoTotal() / (1000 * 1000);\n    }\n\n    @Override\n    public long getPrepareCallCount() {\n        return prepareCallCount.get();\n    }\n\n    @Override\n    public long getPrepareCount() {\n        return prepareCount.get();\n    }\n\n    @Override\n    public long getExecuteSuccessCount() {\n        return this.getExecuteCount() - this.getErrorCount() - this.getRunningCount();\n    }\n\n    @Override\n    public CompositeData getLastError() throws JMException {\n        return JMXUtils.getErrorCompositeData(this.getLastException());\n    }\n\n    public void incrementCreateCounter() {\n        createCount.incrementAndGet();\n    }\n\n    public void incrementPrepareCallCount() {\n        prepareCallCount.incrementAndGet();\n    }\n\n    public void incrementPrepareCounter() {\n        prepareCount.incrementAndGet();\n    }\n\n    public void incrementStatementCloseCounter() {\n        closeCount.incrementAndGet();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcStatementStatMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport javax.management.JMException;\nimport javax.management.openmbean.CompositeData;\n\nimport java.util.Date;\n\npublic interface JdbcStatementStatMBean {\n    long getCreateCount();\n\n    long getPrepareCount();\n\n    long getPrepareCallCount();\n\n    long getCloseCount();\n\n    long getExecuteMillisTotal();\n\n    long getExecuteSuccessCount();\n\n    Date getLastErrorTime();\n\n    CompositeData getLastError() throws JMException;\n\n    Date getExecuteLastTime();\n\n    int getRunningCount();\n\n    int getConcurrentMax();\n\n    long getExecuteCount();\n\n    long getErrorCount();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcTraceManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\n@Deprecated\npublic class JdbcTraceManager implements JdbcTraceManagerMBean {\n    private static final JdbcTraceManager instance = new JdbcTraceManager();\n\n    public static JdbcTraceManager getInstance() {\n        return instance;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/JdbcTraceManagerMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\npublic interface JdbcTraceManagerMBean {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/stat/TableStat.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.stat;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class TableStat {\n    int selectCount;\n    int updateCount;\n    int deleteCount;\n    int insertCount;\n    int dropCount;\n    int mergeCount;\n    int createCount;\n    int alterCount;\n    int createIndexCount;\n    int dropIndexCount;\n    int referencedCount;\n    int addCount; // odps add table\n    int addPartitionCount; // odps add partition\n    int analyzeCount; // odps analyze table\n\n    public TableStat() {\n    }\n\n    public int getReferencedCount() {\n        return referencedCount;\n    }\n\n    public void incrementReferencedCount() {\n        referencedCount++;\n    }\n\n    public int getDropIndexCount() {\n        return dropIndexCount;\n    }\n\n    public void incrementDropIndexCount() {\n        this.dropIndexCount++;\n    }\n\n    public void incrementAddCount() {\n        this.addCount++;\n    }\n\n    public int getAddCount() {\n        return addCount;\n    }\n\n    public void incrementAddPartitionCount() {\n        this.addPartitionCount++;\n    }\n\n    public int getAddPartitionCount() {\n        return addPartitionCount;\n    }\n\n    public int getCreateIndexCount() {\n        return createIndexCount;\n    }\n\n    public void incrementCreateIndexCount() {\n        createIndexCount++;\n    }\n\n    public int getAlterCount() {\n        return alterCount;\n    }\n\n    public void incrementAlterCount() {\n        this.alterCount++;\n    }\n\n    public int getCreateCount() {\n        return createCount;\n    }\n\n    public void incrementCreateCount() {\n        this.createCount++;\n    }\n\n    public int getMergeCount() {\n        return mergeCount;\n    }\n\n    public void incrementMergeCount() {\n        this.mergeCount++;\n    }\n\n    public int getDropCount() {\n        return dropCount;\n    }\n\n    public void incrementDropCount() {\n        dropCount++;\n    }\n\n    public void setDropCount(int dropCount) {\n        this.dropCount = dropCount;\n    }\n\n    public int getSelectCount() {\n        return selectCount;\n    }\n\n    public void incrementSelectCount() {\n        selectCount++;\n    }\n\n    public void setSelectCount(int selectCount) {\n        this.selectCount = selectCount;\n    }\n\n    public int getUpdateCount() {\n        return updateCount;\n    }\n\n    public void incrementUpdateCount() {\n        updateCount++;\n    }\n\n    public void setUpdateCount(int updateCount) {\n        this.updateCount = updateCount;\n    }\n\n    public int getDeleteCount() {\n        return deleteCount;\n    }\n\n    public void incrementDeleteCount() {\n        this.deleteCount++;\n    }\n\n    public void setDeleteCount(int deleteCount) {\n        this.deleteCount = deleteCount;\n    }\n\n    public void incrementInsertCount() {\n        this.insertCount++;\n    }\n\n    public int getInsertCount() {\n        return insertCount;\n    }\n\n    public void setInsertCount(int insertCount) {\n        this.insertCount = insertCount;\n    }\n\n    public int getAnalyzeCount() {\n        return analyzeCount;\n    }\n\n    public void incrementAnalyzeCount() {\n        this.analyzeCount++;\n    }\n\n    public String toString() {\n        StringBuilder buf = new StringBuilder(4);\n        if (mergeCount > 0) {\n            buf.append(\"Merge\");\n        }\n        if (insertCount > 0) {\n            buf.append(\"Insert\");\n        }\n        if (updateCount > 0) {\n            buf.append(\"Update\");\n        }\n        if (selectCount > 0) {\n            buf.append(\"Select\");\n        }\n        if (deleteCount > 0) {\n            buf.append(\"Delete\");\n        }\n        if (dropCount > 0) {\n            buf.append(\"Drop\");\n        }\n        if (createCount > 0) {\n            buf.append(\"Create\");\n        }\n        if (alterCount > 0) {\n            buf.append(\"Alter\");\n        }\n        if (createIndexCount > 0) {\n            buf.append(\"CreateIndex\");\n        }\n        if (dropIndexCount > 0) {\n            buf.append(\"DropIndex\");\n        }\n        if (addCount > 0) {\n            buf.append(\"Add\");\n        }\n        if (addPartitionCount > 0) {\n            buf.append(\"AddPartition\");\n        }\n        if (analyzeCount > 0) {\n            buf.append(\"Analyze\");\n        }\n\n        return buf.toString();\n    }\n\n    public static class Name {\n        private final String name;\n        private final long hashCode64;\n\n        public Name(String name) {\n            this(name, FnvHash.hashCode64(name));\n        }\n\n        public Name(String name, long hashCode64) {\n            this.name = name;\n            this.hashCode64 = hashCode64;\n        }\n\n        public String getName() {\n            return this.name;\n        }\n\n        public int hashCode() {\n            long value = hashCode64();\n            return (int) (value ^ (value >>> 32));\n        }\n\n        public long hashCode64() {\n            return hashCode64;\n        }\n\n        public boolean equals(Object o) {\n            if (!(o instanceof Name)) {\n                return false;\n            }\n\n            Name other = (Name) o;\n            return this.hashCode64 == other.hashCode64;\n        }\n\n        public String toString() {\n            return SQLUtils.normalize(this.name);\n        }\n    }\n\n    public static class Relationship {\n        private Column left;\n        private Column right;\n        private String operator;\n\n        public Relationship(Column left, Column right, String operator) {\n            this.left = left;\n            this.right = right;\n            this.operator = operator;\n        }\n\n        public Column getLeft() {\n            return left;\n        }\n\n        public Column getRight() {\n            return right;\n        }\n\n        public String getOperator() {\n            return operator;\n        }\n\n        @Override\n        public int hashCode() {\n            final int prime = 31;\n            int result = 1;\n            result = prime * result + ((left == null) ? 0 : left.hashCode());\n            result = prime * result + ((operator == null) ? 0 : operator.hashCode());\n            result = prime * result + ((right == null) ? 0 : right.hashCode());\n            return result;\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            if (this == obj) {\n                return true;\n            }\n            if (obj == null) {\n                return false;\n            }\n            if (getClass() != obj.getClass()) {\n                return false;\n            }\n            Relationship other = (Relationship) obj;\n            if (left == null) {\n                if (other.left != null) {\n                    return false;\n                }\n            } else if (!left.equals(other.left)) {\n                return false;\n            }\n            if (operator == null) {\n                if (other.operator != null) {\n                    return false;\n                }\n            } else if (!operator.equals(other.operator)) {\n                return false;\n            }\n            if (right == null) {\n                if (other.right != null) {\n                    return false;\n                }\n            } else if (!right.equals(other.right)) {\n                return false;\n            }\n            return true;\n        }\n\n        @Override\n        public String toString() {\n            return left + \" \" + operator + \" \" + right;\n        }\n\n    }\n\n    public static class Condition {\n        private final Column column;\n        private final String operator;\n        private final List<Object> values = new ArrayList<Object>();\n\n        public Condition(Column column, String operator) {\n            this.column = column;\n            this.operator = operator;\n        }\n\n        public Column getColumn() {\n            return column;\n        }\n\n        public String getOperator() {\n            return operator;\n        }\n\n        public List<Object> getValues() {\n            return values;\n        }\n\n        public void addValue(Object value) {\n            this.values.add(value);\n        }\n\n        @Override\n        public int hashCode() {\n            final int prime = 31;\n            int result = 1;\n            result = prime * result + ((column == null) ? 0 : column.hashCode());\n            result = prime * result + ((operator == null) ? 0 : operator.hashCode());\n            return result;\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            if (this == obj) {\n                return true;\n            }\n            if (obj == null) {\n                return false;\n            }\n            if (getClass() != obj.getClass()) {\n                return false;\n            }\n            Condition other = (Condition) obj;\n            if (column == null) {\n                if (other.column != null) {\n                    return false;\n                }\n            } else if (!column.equals(other.column)) {\n                return false;\n            }\n            if (operator == null) {\n                if (other.operator != null) {\n                    return false;\n                }\n            } else if (!operator.equals(other.operator)) {\n                return false;\n            }\n            return true;\n        }\n\n        public String toString() {\n            StringBuilder buf = new StringBuilder();\n            buf.append(this.column.toString());\n            buf.append(' ');\n            buf.append(this.operator);\n\n            if (values.size() == 1) {\n                buf.append(' ');\n                buf.append(String.valueOf(this.values.get(0)));\n            } else if (values.size() > 0) {\n                buf.append(\" (\");\n                for (int i = 0; i < values.size(); ++i) {\n                    if (i != 0) {\n                        buf.append(\", \");\n                    }\n                    Object val = values.get(i);\n                    if (val instanceof String) {\n                        String jsonStr = JSONUtils.toJSONString(val);\n                        buf.append(jsonStr);\n                    } else {\n                        buf.append(String.valueOf(val));\n                    }\n                }\n                buf.append(\")\");\n            }\n\n            return buf.toString();\n        }\n    }\n\n    public static class Column {\n        private final String table;\n        private final String name;\n        private final long hashCode64;\n\n        private boolean where;\n        private boolean select;\n        private boolean groupBy;\n        private boolean having;\n        private boolean join;\n        private boolean primaryKey; // for ddl\n        private boolean unique;\n        private boolean update;\n        private Map<String, Object> attributes = new HashMap<String, Object>();\n        private transient String fullName;\n\n        /**\n         * @since 1.0.20\n         */\n        private String dataType;\n\n        public Column(String table, String name) {\n            this(table, name, null);\n        }\n\n        public Column(String table, String name, DbType dbType) {\n            this.table = table;\n            this.name = name;\n\n            int p = table.indexOf('.');\n            if (p != -1) {\n                if (dbType == null) {\n                    if (table.indexOf('`') != -1) {\n                        dbType = DbType.mysql;\n                    } else if (table.indexOf('[') != -1) {\n                        dbType = DbType.sqlserver;\n                    } else if (table.indexOf('@') != -1) {\n                        dbType = DbType.oracle;\n                    }\n                }\n                SQLExpr owner = SQLUtils.toSQLExpr(table, dbType);\n                hashCode64 = new SQLPropertyExpr(owner, name).hashCode64();\n            } else {\n                hashCode64 = FnvHash.hashCode64(table, name);\n            }\n        }\n\n        public Column(String table, String name, long hashCode64) {\n            this.table = table;\n            this.name = name;\n            this.hashCode64 = hashCode64;\n        }\n\n        public String getTable() {\n            return table;\n        }\n\n        public String getFullName() {\n            if (fullName == null) {\n                if (table == null) {\n                    fullName = name;\n                } else {\n                    fullName = table + '.' + name;\n                }\n            }\n\n            return fullName;\n        }\n\n        public long hashCode64() {\n            return hashCode64;\n        }\n\n        public boolean isWhere() {\n            return where;\n        }\n\n        public void setWhere(boolean where) {\n            this.where = where;\n        }\n\n        public boolean isSelect() {\n            return select;\n        }\n\n        public void setSelec(boolean select) {\n            this.select = select;\n        }\n\n        public boolean isGroupBy() {\n            return groupBy;\n        }\n\n        public void setGroupBy(boolean groupBy) {\n            this.groupBy = groupBy;\n        }\n\n        public boolean isHaving() {\n            return having;\n        }\n\n        public boolean isJoin() {\n            return join;\n        }\n\n        public void setJoin(boolean join) {\n            this.join = join;\n        }\n\n        public void setHaving(boolean having) {\n            this.having = having;\n        }\n\n        public boolean isPrimaryKey() {\n            return primaryKey;\n        }\n\n        public void setPrimaryKey(boolean primaryKey) {\n            this.primaryKey = primaryKey;\n        }\n\n        public boolean isUnique() {\n            return unique;\n        }\n\n        public void setUnique(boolean unique) {\n            this.unique = unique;\n        }\n\n        public boolean isUpdate() {\n            return update;\n        }\n\n        public void setUpdate(boolean update) {\n            this.update = update;\n        }\n\n        public String getName() {\n            return name;\n        }\n\n        /**\n         * @since 1.0.20\n         */\n        public String getDataType() {\n            return dataType;\n        }\n\n        /**\n         * @since 1.0.20\n         */\n        public void setDataType(String dataType) {\n            this.dataType = dataType;\n        }\n\n        public Map<String, Object> getAttributes() {\n            return attributes;\n        }\n\n        public void setAttributes(Map<String, Object> attributes) {\n            this.attributes = attributes;\n        }\n\n        public int hashCode() {\n            long hash = hashCode64();\n            return (int) (hash ^ (hash >>> 32));\n        }\n\n        public String toString() {\n            if (table != null) {\n                return SQLUtils.normalize(table) + \".\" + SQLUtils.normalize(name);\n            }\n\n            return SQLUtils.normalize(name);\n        }\n\n        public boolean equals(Object obj) {\n            if (!(obj instanceof Column)) {\n                return false;\n            }\n\n            Column column = (Column) obj;\n            return hashCode64 == column.hashCode64;\n        }\n    }\n\n    public static enum Mode {\n        Insert(1), //\n        Update(2), //\n        Delete(4), //\n        Select(8), //\n        Merge(16), //\n        Truncate(32), //\n        Alter(64), //\n        Drop(128), //\n        DropIndex(256), //\n        CreateIndex(512), //\n        Replace(1024),\n        DESC(2048);\n\n        public final int mark;\n\n        private Mode(int mark) {\n            this.mark = mark;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/calcite/CalciteMySqlNodeVisitor.java",
    "content": "package com.alibaba.druid.support.calcite;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.FastsqlException;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.util.FnvHash;\nimport org.apache.calcite.avatica.util.TimeUnit;\nimport org.apache.calcite.sql.*;\nimport org.apache.calcite.sql.fun.*;\nimport org.apache.calcite.sql.parser.SqlParserPos;\nimport org.apache.calcite.sql.parser.SqlParserUtil;\nimport org.apache.calcite.sql.type.SqlTypeName;\nimport org.apache.calcite.util.DateString;\nimport org.apache.calcite.util.TimeString;\nimport org.apache.calcite.util.TimestampString;\n\nimport java.util.*;\n\npublic class CalciteMySqlNodeVisitor extends MySqlASTVisitorAdapter {\n    static Map<Long, SqlOperator> operators = new HashMap<Long, SqlOperator>();\n\n    static {\n        List<SqlOperator> list = SqlStdOperatorTable.instance().getOperatorList();\n        for (SqlOperator op : list) {\n            long h = FnvHash.hashCode64(op.getName());\n            if (h == FnvHash.Constants.TRIM) {\n                continue;\n            }\n            operators.put(h, op);\n        }\n        operators.put(FnvHash.Constants.CEILING, SqlStdOperatorTable.CEIL);\n    }\n\n    static SqlOperator func(long hash) {\n        return operators.get(hash);\n    }\n\n    private SqlNode sqlNode;\n\n    public SqlNode getSqlNode() {\n        return sqlNode;\n    }\n\n    public boolean visit(SQLInsertStatement x) {\n        SqlNodeList keywords = new SqlNodeList(new ArrayList<SqlNode>(), SqlParserPos.ZERO);\n\n        SQLExprTableSource tableSource = (SQLExprTableSource) x.getTableSource();\n        SqlNode targetTable = convertToSqlNode(tableSource.getExpr());\n\n        SqlNode source;\n\n        SQLSelect query = x.getQuery();\n        if (query != null) {\n            query.accept(this);\n            source = sqlNode;\n        } else {\n            List<SQLInsertStatement.ValuesClause> valuesList = x.getValuesList();\n\n            SqlNode[] rows = new SqlNode[valuesList.size()];\n            for (int j = 0; j < valuesList.size(); j++) {\n                List<SQLExpr> values = valuesList.get(j).getValues();\n\n                SqlNode[] valueNodes = new SqlNode[values.size()];\n                for (int i = 0; i < values.size(); i++) {\n                    SqlNode valueNode = convertToSqlNode(values.get(i));\n                    valueNodes[i] = valueNode;\n                }\n                SqlBasicCall row = new SqlBasicCall(SqlStdOperatorTable.ROW, valueNodes, SqlParserPos.ZERO);\n                rows[j] = row;\n            }\n            source = new SqlBasicCall(SqlStdOperatorTable.VALUES, rows, SqlParserPos.ZERO);\n        }\n\n        SqlNodeList columnList = x.getColumns().size() > 0\n                ? convertToSqlNodeList(x.getColumns())\n                : null;\n\n        this.sqlNode = new SqlInsert(SqlParserPos.ZERO, keywords, targetTable, source, columnList);\n        return false;\n    }\n\n    public boolean visit(MySqlInsertStatement x) {\n        return visit((SQLInsertStatement) x);\n    }\n\n    private boolean visit(List<SQLInsertStatement.ValuesClause> valuesList) {\n        boolean isBatch = false;\n        List<SQLInsertStatement.ValuesClause> newValuesList = convertToSingleValuesIfNeed(valuesList);\n        if (newValuesList.size() < valuesList.size()) {\n            isBatch = true;\n            valuesList = newValuesList;\n        }\n\n        SqlNode[] rows = new SqlNode[valuesList.size()];\n        for (int j = 0; j < valuesList.size(); j++) {\n            List<SQLExpr> values = valuesList.get(j).getValues();\n\n            SqlNode[] valueNodes = new SqlNode[values.size()];\n            for (int i = 0; i < values.size(); i++) {\n                SqlNode valueNode = convertToSqlNode(values.get(i));\n                valueNodes[i] = valueNode;\n            }\n            SqlBasicCall row = new SqlBasicCall(SqlStdOperatorTable.ROW, valueNodes, SqlParserPos.ZERO);\n            rows[j] = row;\n        }\n\n        this.sqlNode = new SqlBasicCall(SqlStdOperatorTable.VALUES, rows, SqlParserPos.ZERO);\n\n        return isBatch;\n    }\n\n    public boolean visit(MySqlUpdateStatement x) {\n        if (x.getTableSource().getClass() != SQLExprTableSource.class) {\n            throw new UnsupportedOperationException(\"Support single table only for SqlUpdate statement of calcite.\");\n        }\n        SQLExprTableSource tableSource = (SQLExprTableSource) x.getTableSource();\n        SqlNode targetTable = convertToSqlNode(tableSource.getExpr());\n\n        List<SqlNode> columns = new ArrayList<SqlNode>();\n        List<SqlNode> values = new ArrayList<SqlNode>();\n\n        for (SQLUpdateSetItem item : x.getItems()) {\n            columns.add(convertToSqlNode(item.getColumn()));\n            values.add(convertToSqlNode(item.getValue()));\n        }\n        SqlNodeList targetColumnList = new SqlNodeList(columns, SqlParserPos.ZERO);\n        SqlNodeList sourceExpressList = new SqlNodeList(values, SqlParserPos.ZERO);\n\n        SqlNode condition = convertToSqlNode(x.getWhere());\n\n        SqlIdentifier alias = null;\n        if (x.getTableSource().getAlias() != null) {\n            alias = new SqlIdentifier(tableSource.getAlias(), SqlParserPos.ZERO);\n        }\n\n        sqlNode = new SqlUpdate(SqlParserPos.ZERO, targetTable, targetColumnList, sourceExpressList, condition, null, alias);\n\n        return false;\n    }\n\n    public boolean visit(MySqlDeleteStatement x) {\n        SQLExprTableSource tableSource = (SQLExprTableSource) x.getTableSource();\n        SqlNode targetTable = convertToSqlNode(tableSource.getExpr());\n\n        SqlNode condition = convertToSqlNode(x.getWhere());\n\n        SqlIdentifier alias = null;\n        if (x.getTableSource().getAlias() != null) {\n            alias = new SqlIdentifier(tableSource.getAlias(), SqlParserPos.ZERO);\n        }\n\n        sqlNode = new SqlDelete(SqlParserPos.ZERO, targetTable, condition, null, alias);\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnionQuery x) {\n        SqlNode[] nodes;\n        if (x.getRelations().size() > 2) {\n            nodes = new SqlNode[x.getRelations().size()];\n            for (int i = 0; i < x.getRelations().size(); i++) {\n                nodes[i] = convertToSqlNode(x.getRelations().get(i));\n            }\n        } else {\n            SqlNode left = convertToSqlNode(x.getLeft());\n            SqlNode right = convertToSqlNode(x.getRight());\n\n            nodes = new SqlNode[]{left, right};\n        }\n\n        //order by\n        SqlNodeList orderBySqlNode = null;\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            orderBySqlNode = convertOrderby(orderBy);\n        }\n\n        //limit\n        SqlNode offset = null;\n        SqlNode fetch = null;\n        SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            offset = convertToSqlNode(limit.getOffset());\n            fetch = convertToSqlNode(limit.getRowCount());\n        }\n\n        SQLUnionOperator operator = x.getOperator();\n\n        SqlNode union = null;\n        switch (operator) {\n            case UNION_ALL:\n                union = new SqlBasicCall(SqlStdOperatorTable.UNION_ALL,\n                        nodes,\n                        SqlParserPos.ZERO);\n                break;\n            case UNION:\n            case DISTINCT:\n                union = new SqlBasicCall(SqlStdOperatorTable.UNION,\n                        nodes,\n                        SqlParserPos.ZERO);\n                break;\n            case INTERSECT:\n                union = new SqlBasicCall(SqlStdOperatorTable.INTERSECT,\n                        nodes,\n                        SqlParserPos.ZERO);\n                break;\n            case EXCEPT:\n                union = new SqlBasicCall(SqlStdOperatorTable.EXCEPT,\n                        nodes,\n                        SqlParserPos.ZERO);\n                break;\n            default:\n                throw new FastsqlException(\"unsupported join type: \" + operator);\n        }\n\n        if (null == orderBy && null == offset && null == fetch) {\n            sqlNode = union;\n        } else {\n            if (orderBySqlNode == null) {\n                orderBySqlNode = SqlNodeList.EMPTY;\n            }\n            sqlNode = new SqlOrderBy(SqlParserPos.ZERO, union, orderBySqlNode, offset, fetch);\n        }\n\n        return false;\n\n    }\n\n    public boolean visit(MySqlSelectQueryBlock x) {\n        return visit((SQLSelectQueryBlock) x);\n    }\n\n    private static Map<Long, SqlTypeName> nameHashCode64SqlTypeNameMapping = new HashMap<>();\n\n    public boolean visit(SQLTableSource x) {\n        Class<?> clazz = x.getClass();\n        if (clazz == SQLJoinTableSource.class) {\n            visit((SQLJoinTableSource) x);\n        } else if (clazz == SQLExprTableSource.class) {\n            visit((SQLExprTableSource) x);\n        } else if (clazz == SQLSubqueryTableSource.class) {\n            visit((SQLSubqueryTableSource) x);\n        } else {\n            x.accept(this);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExprTableSource x) {\n        SqlIdentifier table;\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLIdentifierExpr) {\n            table = buildIdentifier((SQLIdentifierExpr) expr);\n        } else if (expr instanceof SQLPropertyExpr) {\n            table = buildIdentifier((SQLPropertyExpr) expr);\n        } else {\n            throw new FastsqlException(\"not support : \" + expr);\n        }\n\n        if (x.getAlias() != null) {\n            SqlIdentifier alias = new SqlIdentifier(x.computeAlias(), SqlParserPos.ZERO);\n            SqlBasicCall as = new SqlBasicCall(SqlStdOperatorTable.AS, new SqlNode[]{table, alias},\n                    SqlParserPos.ZERO);\n            sqlNode = as;\n        } else {\n            sqlNode = table;\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLJoinTableSource x) {\n        SQLJoinTableSource.JoinType joinType = x.getJoinType();\n\n        SqlNode left = convertToSqlNode(x.getLeft());\n        SqlNode right = convertToSqlNode(x.getRight());\n        SqlNode condition = convertToSqlNode(x.getCondition());\n\n        SqlLiteral conditionType = condition == null\n                ? JoinConditionType.NONE.symbol(SqlParserPos.ZERO)\n                : JoinConditionType.ON.symbol(SqlParserPos.ZERO);\n\n        if (condition == null && !x.getUsing().isEmpty()) {\n            List<SQLExpr> using = x.getUsing();\n            conditionType = JoinConditionType.USING.symbol(SqlParserPos.ZERO);\n            condition = convertToSqlNodeList(x.getUsing());\n        }\n\n        switch (joinType) {\n            case COMMA:\n                this.sqlNode = new SqlJoin(SqlParserPos.ZERO, left,\n                        SqlLiteral.createBoolean(false, SqlParserPos.ZERO),\n                        JoinType.COMMA.symbol(SqlParserPos.ZERO), right,\n                        JoinConditionType.NONE.symbol(SqlParserPos.ZERO),\n                        null);\n                break;\n            case JOIN:\n            case INNER_JOIN:\n                if (condition == null) {\n                    this.sqlNode = new SqlJoin(\n                            SqlParserPos.ZERO,\n                            left,\n                            SqlLiteral.createBoolean(false, SqlParserPos.ZERO),\n                            JoinType.COMMA.symbol(SqlParserPos.ZERO),\n                            right,\n                            conditionType,\n                            null\n                    );\n                } else {\n                    this.sqlNode = new SqlJoin(\n                            SqlParserPos.ZERO,\n                            left,\n                            SqlLiteral.createBoolean(false, SqlParserPos.ZERO),\n                            JoinType.INNER.symbol(SqlParserPos.ZERO),\n                            right,\n                            conditionType,\n                            condition\n                    );\n                }\n                break;\n            case LEFT_OUTER_JOIN:\n                this.sqlNode = new SqlJoin(SqlParserPos.ZERO,\n                        left,\n                        SqlLiteral.createBoolean(false, SqlParserPos.ZERO),\n                        JoinType.LEFT.symbol(SqlParserPos.ZERO),\n                        right,\n                        conditionType,\n                        condition);\n                break;\n            case RIGHT_OUTER_JOIN:\n                this.sqlNode = new SqlJoin(SqlParserPos.ZERO,\n                        left,\n                        SqlLiteral.createBoolean(false, SqlParserPos.ZERO),\n                        JoinType.RIGHT.symbol(SqlParserPos.ZERO),\n                        right,\n                        conditionType,\n                        condition);\n                break;\n            case NATURAL_JOIN:\n                this.sqlNode = new SqlJoin(\n                        SqlParserPos.ZERO,\n                        left,\n                        SqlLiteral.createBoolean(true, SqlParserPos.ZERO),\n                        JoinType.COMMA.symbol(SqlParserPos.ZERO),\n                        right,\n                        JoinConditionType.NONE.symbol(SqlParserPos.ZERO),\n                        null);\n                break;\n            case CROSS_JOIN:\n                this.sqlNode = new SqlJoin(\n                        SqlParserPos.ZERO,\n                        left,\n                        SqlLiteral.createBoolean(false, SqlParserPos.ZERO),\n                        JoinType.CROSS.symbol(SqlParserPos.ZERO),\n                        right,\n                        JoinConditionType.NONE.symbol(SqlParserPos.ZERO),\n                        null);\n                break;\n            case NATURAL_CROSS_JOIN:\n                this.sqlNode = new SqlJoin(SqlParserPos.ZERO,\n                        left,\n                        SqlLiteral.createBoolean(true, SqlParserPos.ZERO),\n                        JoinType.CROSS.symbol(SqlParserPos.ZERO),\n                        right,\n                        JoinConditionType.NONE.symbol(SqlParserPos.ZERO),\n                        null);\n                break;\n            case FULL_OUTER_JOIN:\n                this.sqlNode = new SqlJoin(\n                        SqlParserPos.ZERO,\n                        left,\n                        SqlLiteral.createBoolean(false, SqlParserPos.ZERO),\n                        JoinType.FULL.symbol(SqlParserPos.ZERO),\n                        right,\n                        condition == null\n                                ? JoinConditionType.NONE.symbol(SqlParserPos.ZERO)\n                                : conditionType,\n                        condition\n                );\n                break;\n            default:\n                throw new UnsupportedOperationException(\"unsupported : \" + joinType);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSubqueryTableSource x) {\n        sqlNode = convertToSqlNode(x.getSelect());\n\n        final String alias = x.getAlias();\n        if (alias != null) {\n            SqlIdentifier aliasIdentifier = new SqlIdentifier(alias, SqlParserPos.ZERO);\n\n            List<SQLName> columns = x.getColumns();\n\n            SqlNode[] operands;\n            if (columns.isEmpty()) {\n                operands = new SqlNode[]{sqlNode, aliasIdentifier};\n            } else {\n                operands = new SqlNode[columns.size() + 2];\n                operands[0] = sqlNode;\n                operands[1] = aliasIdentifier;\n                for (int i = 0; i < columns.size(); i++) {\n                    SQLName column = columns.get(i);\n                    operands[i + 2] = new SqlIdentifier(\n                            SQLUtils.normalize(column.getSimpleName()), SqlParserPos.ZERO);\n                }\n            }\n            sqlNode = new SqlBasicCall(SqlStdOperatorTable.AS, operands, SqlParserPos.ZERO);\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLUnionQueryTableSource x) {\n        x.getUnion().accept(this);\n\n        final String alias = x.getAlias();\n        if (alias != null) {\n            SqlIdentifier aliasIdentifier = new SqlIdentifier(alias, SqlParserPos.ZERO);\n            sqlNode = new SqlBasicCall(SqlStdOperatorTable.AS,\n                    new SqlNode[]{sqlNode, aliasIdentifier},\n                    SqlParserPos.ZERO);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLInSubQueryExpr x) {\n        SqlNode left = convertToSqlNode(x.getExpr());\n        SqlBinaryOperator subOperator = SqlStdOperatorTable.IN;\n        if (x.isNot()) {\n            subOperator = SqlStdOperatorTable.NOT_IN;\n        }\n        SqlNode right = convertToSqlNode(x.subQuery);\n\n        sqlNode = new SqlBasicCall(subOperator, new SqlNode[]{left, right}, SqlParserPos.ZERO);\n        return false;\n    }\n\n    static {\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BIT, SqlTypeName.BOOLEAN);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BOOLEAN, SqlTypeName.BOOLEAN);\n\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.TINYINT, SqlTypeName.TINYINT);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.SMALLINT, SqlTypeName.SMALLINT);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.INT, SqlTypeName.INTEGER);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.INTEGER, SqlTypeName.INTEGER);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BIGINT, SqlTypeName.BIGINT);\n\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.DECIMAL, SqlTypeName.DECIMAL);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.FLOAT, SqlTypeName.FLOAT);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.REAL, SqlTypeName.REAL);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.DOUBLE, SqlTypeName.DOUBLE);\n\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.DATE, SqlTypeName.DATE);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.TIME, SqlTypeName.TIME);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.TIMESTAMP, SqlTypeName.TIMESTAMP);\n\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.CHAR, SqlTypeName.CHAR);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.VARCHAR, SqlTypeName.VARCHAR);\n\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.BINARY, SqlTypeName.BINARY);\n        nameHashCode64SqlTypeNameMapping.put(FnvHash.Constants.VARBINARY, SqlTypeName.VARBINARY);\n    }\n\n    public boolean visit(SQLSelectQueryBlock x) {\n        SqlNodeList keywordList = null;\n        List<SqlNode> keywordNodes = new ArrayList<SqlNode>(5);\n        int option = x.getDistionOption();\n        if (option != 0) {\n            if (option == SQLSetQuantifier.DISTINCT\n                    || option == SQLSetQuantifier.DISTINCTROW) {\n                keywordNodes.add(SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO));\n            } else if (option == SQLSetQuantifier.ALL) {\n                keywordNodes.add(SqlSelectKeyword.ALL.symbol(SqlParserPos.ZERO));\n            }\n\n            keywordList = new SqlNodeList(keywordNodes, SqlParserPos.ZERO);\n        }\n\n        // select list\n        List<SqlNode> columnNodes = new ArrayList<SqlNode>(x.getSelectList().size());\n        for (SQLSelectItem selectItem : x.getSelectList()) {\n            SqlNode column = convertToSqlNode(selectItem);\n            columnNodes.add(column);\n        }\n\n        //select item\n        SqlNodeList selectList = new SqlNodeList(columnNodes, SqlParserPos.ZERO);\n\n        //from\n        SqlNode from = null;\n\n        SQLTableSource tableSource = x.getFrom();\n        if (tableSource != null) {\n            from = convertToSqlNode(tableSource);\n        }\n\n        //where\n        SqlNode where = convertToSqlNode(x.getWhere());\n\n        //order by\n        SqlNodeList orderBySqlNode = null;\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            orderBySqlNode = convertOrderby(orderBy);\n        }\n\n        //group by\n        SqlNodeList groupBySqlNode = null;\n        SqlNode having = null;\n        SQLSelectGroupByClause groupBys = x.getGroupBy();\n\n        if (groupBys != null) {\n            if (groupBys.getHaving() != null) {\n                having = convertToSqlNode(groupBys.getHaving());\n            }\n\n            if (groupBys.getItems().size() > 0) {\n                List<SqlNode> groupByNodes = new ArrayList<SqlNode>(groupBys.getItems().size());\n\n                for (SQLExpr groupBy : groupBys.getItems()) {\n                    SqlNode groupByNode = convertToSqlNode(groupBy);\n                    groupByNodes.add(groupByNode);\n                }\n                groupBySqlNode = new SqlNodeList(groupByNodes, SqlParserPos.ZERO);\n            }\n\n            SqlInternalOperator op = null;\n            if (groupBys.isWithRollUp()) {\n                op = SqlStdOperatorTable.ROLLUP;\n            } else if (groupBys.isWithCube()) {\n                op = SqlStdOperatorTable.CUBE;\n            }\n\n            if (op != null) {\n                List<SqlNode> rollupNodes = new ArrayList<SqlNode>(1);\n\n                boolean isRow = false;\n                for (SqlNode node : groupBySqlNode.getList()) {\n                    if (node instanceof SqlBasicCall && ((SqlBasicCall) node).getOperator() == SqlStdOperatorTable.ROW) {\n                        isRow = true;\n                        break;\n                    }\n                }\n\n                if (isRow) {\n                    rollupNodes.add(op.createCall(SqlParserPos.ZERO, groupBySqlNode.toArray()));\n                    groupBySqlNode = new SqlNodeList(rollupNodes, SqlParserPos.ZERO);\n                } else {\n                    rollupNodes.add(op.createCall(SqlParserPos.ZERO, groupBySqlNode));\n                    groupBySqlNode = new SqlNodeList(rollupNodes, SqlParserPos.ZERO);\n                }\n\n            }\n        }\n\n        //limit\n        SqlNode offset = null;\n        SqlNode fetch = null;\n        SQLLimit limit = x.getLimit();\n        if (limit != null) {\n            offset = convertToSqlNode(limit.getOffset());\n            fetch = convertToSqlNode(limit.getRowCount());\n        }\n\n        //hints\n        SqlNodeList hints = convertHints(x.getHints());\n\n        if (orderBy != null && x.getParent() instanceof SQLUnionQuery) {\n            this.sqlNode = new com.alibaba.druid.support.calcite.TDDLSqlSelect(\n                    SqlParserPos.ZERO,\n                    keywordList,\n                    selectList,\n                    from,\n                    where,\n                    groupBySqlNode,\n                    having,\n                    null,\n                    null,\n                    offset,\n                    fetch,\n                    hints,\n                    null\n            );\n            sqlNode = new SqlOrderBy(\n                    SqlParserPos.ZERO,\n                    sqlNode,\n                    orderBySqlNode,\n                    null,\n                    fetch\n            );\n        } else {\n            if (orderBySqlNode == null) {\n                orderBySqlNode = SqlNodeList.EMPTY;\n            }\n            if (hints == null || SqlNodeList.isEmptyList(hints)) {\n                this.sqlNode = new SqlSelect(\n                        SqlParserPos.ZERO,\n                        keywordList,\n                        selectList,\n                        from,\n                        where,\n                        groupBySqlNode,\n                        having,\n                        null,\n                        SqlNodeList.EMPTY,\n                        null,\n                        null,\n                        null\n                );\n\n                if ((!SqlNodeList.isEmptyList(orderBySqlNode))\n                        || offset != null\n                        || fetch != null\n                ) {\n                    sqlNode = new SqlOrderBy(\n                            SqlParserPos.ZERO,\n                            sqlNode,\n                            orderBySqlNode,\n                            offset,\n                            fetch\n                    );\n                }\n            } else {\n                this.sqlNode = new com.alibaba.druid.support.calcite.TDDLSqlSelect(\n                        SqlParserPos.ZERO,\n                        keywordList,\n                        selectList,\n                        from,\n                        where,\n                        groupBySqlNode,\n                        having,\n                        null,\n                        orderBySqlNode,\n                        offset,\n                        fetch,\n                        hints,\n                        null\n                );\n            }\n        }\n\n        return false;\n    }\n\n    private SqlTypeName toSqlTypeName(SQLDataType dataType) {\n        long nameHashCode64 = dataType.nameHashCode64();\n        SqlTypeName sqlTypeName = nameHashCode64SqlTypeNameMapping.get(nameHashCode64);\n        if (sqlTypeName != null) {\n            return sqlTypeName;\n        }\n\n        throw new FastsqlException(\"TODO\");\n    }\n\n    public boolean visit(SQLCastExpr x) {\n        SqlLiteral functionQualifier = null;\n\n        SqlNode sqlNode = convertToSqlNode(x.getExpr());\n\n        SQLDataType dataType = x.getDataType();\n        String typeName = dataType.getName().toUpperCase();\n        if (dataType.nameHashCode64() == FnvHash.Constants.INT) {\n            typeName = \"INTEGER\";\n        } else if (dataType.nameHashCode64() == FnvHash.Constants.NUMERIC) {\n            typeName = \"DECIMAL\";\n        }\n\n        SqlIdentifier dataTypeNode = (SqlIdentifier) convertToSqlNode(\n                new SQLIdentifierExpr(typeName));\n\n        int scale = -1;\n        int precision = -1;\n\n        List<SQLExpr> arguments = dataType.getArguments();\n        if (arguments != null && !arguments.isEmpty()) {\n            scale = ((SQLNumericLiteralExpr) arguments.get(0)).getNumber().intValue();\n            if (arguments.size() > 1) {\n                precision = ((SQLNumericLiteralExpr) arguments.get(1)).getNumber().intValue();\n            }\n        }\n\n        SqlDataTypeSpec sqlDataTypeSpec = new SqlDataTypeSpec(\n                new SqlBasicTypeNameSpec(\n                        toSqlTypeName(dataType),\n                        scale,\n                        precision,\n                        SqlParserPos.ZERO\n                ),\n                SqlParserPos.ZERO\n        );\n\n        SqlOperator sqlOperator = new SqlCastFunction();\n\n        this.sqlNode = new com.alibaba.druid.support.calcite.CalciteSqlBasicCall(\n                sqlOperator,\n                new SqlNode[]{sqlNode, sqlDataTypeSpec},\n                SqlParserPos.ZERO,\n                false,\n                functionQualifier\n        );\n        return false;\n    }\n\n    public boolean visit(SQLCaseExpr x) {\n        SQLExpr valueExpr = x.getValueExpr();\n        SqlNode nodeValue = null;\n        SqlNodeList nodeWhen = new SqlNodeList(SqlParserPos.ZERO);\n        SqlNodeList nodeThen = new SqlNodeList(SqlParserPos.ZERO);\n        if (valueExpr != null) {\n            nodeValue = convertToSqlNode(valueExpr);\n        }\n\n        List items = x.getItems();\n        int elExpr = 0;\n\n        for (int size = items.size(); elExpr < size; ++elExpr) {\n            this.visit((SQLCaseExpr.Item) items.get(elExpr));\n            if (this.sqlNode != null && this.sqlNode instanceof SqlNodeList) {\n                SqlNodeList nodeListTemp = (SqlNodeList) this.sqlNode;\n                nodeWhen.add(nodeListTemp.get(0));\n                nodeThen.add(nodeListTemp.get(1));\n            }\n        }\n        SQLExpr elseExpr = x.getElseExpr();\n        SqlNode nodeElse = convertToSqlNode(elseExpr);\n        SqlNodeList sqlNodeList = new SqlNodeList(SqlParserPos.ZERO);\n        sqlNodeList.add(nodeValue);\n        sqlNodeList.add(nodeWhen);\n        sqlNodeList.add(nodeThen);\n        sqlNodeList.add(nodeElse);\n        sqlNode = SqlCase.createSwitched(SqlParserPos.ZERO, nodeValue, nodeWhen, nodeThen, nodeElse);\n        return false;\n    }\n\n    public boolean visit(SQLCaseExpr.Item x) {\n        SQLExpr conditionExpr = x.getConditionExpr();\n        SqlNode sqlNode1 = convertToSqlNode(conditionExpr);\n        SQLExpr valueExpr = x.getValueExpr();\n        SqlNode sqlNode2 = convertToSqlNode(valueExpr);\n        SqlNodeList sqlNodeList = new SqlNodeList(SqlParserPos.ZERO);\n        sqlNodeList.add(sqlNode1);\n        sqlNodeList.add(sqlNode2);\n        sqlNode = sqlNodeList;\n        return false;\n    }\n\n    public boolean visit(SQLListExpr x) {\n        List<SQLExpr> items = x.getItems();\n        List<SqlNode> objects = new ArrayList<SqlNode>();\n        for (int i = 0; i < items.size(); i++) {\n            SQLExpr sqlExpr = items.get(i);\n            SqlNode sqlNode = convertToSqlNode(sqlExpr);\n            objects.add(sqlNode);\n        }\n        sqlNode = SqlStdOperatorTable.ROW.createCall(SqlParserPos.ZERO, objects);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelect x) {\n        SQLWithSubqueryClause with = x.getWithSubQuery();\n        if (with != null) {\n            SqlNodeList withList = new SqlNodeList(SqlParserPos.ZERO);\n            final List<SQLWithSubqueryClause.Entry> entries = with.getEntries();\n            for (SQLWithSubqueryClause.Entry entry : entries) {\n                visit(entry);\n                withList.add(sqlNode);\n            }\n            SqlNode query = convertToSqlNode(x.getQuery());\n\n            if (query instanceof SqlOrderBy) {\n                SqlOrderBy orderBy = (SqlOrderBy) query;\n\n                SqlWith w = new SqlWith(SqlParserPos.ZERO, withList, orderBy.query);\n                sqlNode = new SqlOrderBy(\n                        SqlParserPos.ZERO,\n                        w,\n                        orderBy.orderList,\n                        orderBy.offset,\n                        orderBy.fetch\n                );\n            } else {\n                sqlNode = new SqlWith(SqlParserPos.ZERO, withList, query);\n            }\n\n            if (query instanceof SqlSelect) {\n                SqlSelect select = (SqlSelect) query;\n                SqlNode fetch = select.getFetch();\n                SqlNodeList orderList = select.getOrderList();\n\n                if (fetch != null\n                        || (orderList != null && orderList.size() > 0)) {\n                    SqlNodeList orderByList = null;\n                    if (orderList != null) {\n                        orderByList = new SqlNodeList(orderList.getList(), SqlParserPos.ZERO);\n                        orderList.getList().clear();\n                    } else {\n                        orderByList = SqlNodeList.EMPTY;\n                    }\n\n                    sqlNode = new SqlOrderBy(\n                            SqlParserPos.ZERO,\n                            sqlNode,\n                            orderByList,\n                            null,\n                            fetch\n                    );\n\n                    if (fetch != null) {\n                        select.setFetch(null);\n                    }\n                }\n            }\n\n        } else {\n            sqlNode = convertToSqlNode(x.getQuery());\n        }\n\n        return false;\n    }\n\n    public boolean visit(SQLWithSubqueryClause.Entry x) {\n        SqlNodeList columnList = null;\n        final List<SQLName> columns = x.getColumns();\n        if (columns.size() > 0) {\n            columnList = new SqlNodeList(SqlParserPos.ZERO);\n            for (SQLName column : columns) {\n                columnList.add(new SqlIdentifier(column.getSimpleName(), SqlParserPos.ZERO));\n            }\n        }\n        SqlNode query = convertToSqlNode(x.getSubQuery());\n        SqlIdentifier name = new SqlIdentifier(x.getAlias(), SqlParserPos.ZERO);\n        sqlNode = new SqlWithItem(SqlParserPos.ZERO, name, columnList, query);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLSelectStatement x) {\n        SqlNode sqlNode = convertToSqlNode(x.getSelect());\n\n        if (sqlNode instanceof com.alibaba.druid.support.calcite.TDDLSqlSelect) {\n            com.alibaba.druid.support.calcite.TDDLSqlSelect select = (com.alibaba.druid.support.calcite.TDDLSqlSelect) sqlNode;\n\n            SqlNodeList headHints = convertHints(x.getHeadHintsDirect());\n            select.setHeadHints(headHints);\n            this.sqlNode = select;\n        } else {\n            this.sqlNode = sqlNode;\n        }\n\n        return false;\n    }\n\n    protected void visit(SQLSelectQuery x) {\n        Class<?> clazz = x.getClass();\n        if (clazz == MySqlSelectQueryBlock.class) {\n            visit((MySqlSelectQueryBlock) x);\n        } else if (clazz == SQLUnionQuery.class) {\n            visit((SQLUnionQuery) x);\n        } else {\n            x.accept(this);\n        }\n    }\n\n    public boolean visit(SQLAllExpr x) {\n        sqlNode = convertToSqlNode(x.getSubQuery());\n        return false;\n    }\n\n    public boolean visit(SQLAnyExpr x) {\n        sqlNode = convertToSqlNode(x.getSubQuery());\n        return false;\n    }\n\n    private boolean isSqlAllExpr(SQLExpr x) {\n        return x.getClass() == SQLAllExpr.class;\n    }\n\n    private boolean isAnyOrSomeExpr(SQLExpr x) {\n        return x.getClass() == SQLAnyExpr.class || x.getClass() == SQLSomeExpr.class;\n    }\n\n    public boolean visit(SQLSelectItem x) {\n        SQLExpr expr = x.getExpr();\n\n        if (expr instanceof SQLIdentifierExpr) {\n            visit((SQLIdentifierExpr) expr);\n        } else if (expr instanceof SQLPropertyExpr) {\n            visit((SQLPropertyExpr) expr);\n        } else if (expr instanceof SQLAggregateExpr) {\n            visit((SQLAggregateExpr) expr);\n        } else {\n            expr.accept(this);\n        } // select a + (select count(1) from b) as mm from c;\n        // select a + (select COUNT(1) from b) as 'a + (select count(1) as\n        // 'count(1)' from b)' from c;\n        String alias = x.getAlias();\n        if (alias != null && alias.length() > 0) {\n            String alias2 = x.getAlias2();\n            sqlNode = new SqlBasicCall(SqlStdOperatorTable.AS,\n                    new SqlNode[]{sqlNode, new SqlIdentifier(SQLUtils.normalize(alias2, DbType.mysql), SqlParserPos.ZERO)},\n                    SqlParserPos.ZERO);\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLIdentifierExpr x) {\n        if (x.getName().equalsIgnoreCase(\"unknown\")) {\n            sqlNode = SqlLiteral.createUnknown(SqlParserPos.ZERO);\n            return false;\n        }\n        sqlNode = buildIdentifier(x);\n        return false;\n    }\n\n    public boolean visit(SQLPropertyExpr x) {\n        sqlNode = buildIdentifier(x);\n        return false;\n    }\n\n    SqlIdentifier buildIdentifier(SQLIdentifierExpr x) {\n        return new SqlIdentifier(SQLUtils.normalize(x.getName()), SqlParserPos.ZERO);\n    }\n\n    SqlIdentifier buildIdentifier(SQLPropertyExpr x) {\n        String name = SQLUtils.normalize(x.getName());\n        if (\"*\".equals(name)) {\n            name = \"\";\n        }\n\n        SQLExpr owner = x.getOwner();\n\n        List<String> names;\n        if (owner instanceof SQLIdentifierExpr) {\n            names = Arrays.asList(((SQLIdentifierExpr) owner).normalizedName(), name);\n        } else if (owner instanceof SQLPropertyExpr) {\n            names = new ArrayList<String>();\n            buildIdentifier((SQLPropertyExpr) owner, names);\n            names.add(name);\n        } else {\n            throw new FastsqlException(\"not support : \" + owner);\n        }\n\n        return new SqlIdentifier(names, SqlParserPos.ZERO);\n    }\n\n    void buildIdentifier(SQLPropertyExpr x, List<String> names) {\n        String name = SQLUtils.normalize(x.getName());\n\n        SQLExpr owner = x.getOwner();\n        if (owner instanceof SQLIdentifierExpr) {\n            names.add(((SQLIdentifierExpr) owner).normalizedName());\n        } else if (owner instanceof SQLPropertyExpr) {\n            buildIdentifier((SQLPropertyExpr) owner, names);\n        } else {\n            throw new FastsqlException(\"not support : \" + owner);\n        }\n\n        names.add(name);\n    }\n\n    public boolean visit(SQLBinaryOpExprGroup x) {\n        SqlOperator operator = null;\n        switch (x.getOperator()) {\n            case BooleanAnd:\n                operator = SqlStdOperatorTable.AND;\n                break;\n            case BooleanOr:\n                operator = SqlStdOperatorTable.OR;\n                break;\n            default:\n                break;\n        }\n\n        final List<SQLExpr> items = x.getItems();\n        SqlNode group = null;\n        for (int i = 0; i < items.size(); i++) {\n            SQLExpr item = items.get(i);\n            final SqlNode calciteNode = convertToSqlNode(item);\n            if (group == null) {\n                group = calciteNode;\n            } else {\n                group = new SqlBasicCall(operator, new SqlNode[]{group, calciteNode}, SqlParserPos.ZERO);\n            }\n        }\n        this.sqlNode = group;\n        return false;\n    }\n\n    public boolean visit(SQLBinaryOpExpr x) {\n        SqlOperator operator = null;\n\n        SqlQuantifyOperator someOrAllOperator = null;\n\n        SqlNode left = convertToSqlNode(x.getLeft());\n\n        SQLExpr rightExpr = x.getRight();\n        SqlNode right = convertToSqlNode(rightExpr);\n\n        switch (x.getOperator()) {\n            case Equality:\n                if (isSqlAllExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.ALL_EQ;\n                } else if (isAnyOrSomeExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.SOME_EQ;\n                } else {\n                    operator = SqlStdOperatorTable.EQUALS;\n                }\n                break;\n            case GreaterThan:\n                if (isSqlAllExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.ALL_GT;\n                } else if (isAnyOrSomeExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.SOME_GT;\n                } else {\n                    operator = SqlStdOperatorTable.GREATER_THAN;\n                }\n                break;\n            case GreaterThanOrEqual:\n                if (isSqlAllExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.ALL_GE;\n                } else if (isAnyOrSomeExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.SOME_GE;\n                } else {\n                    operator = SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;\n                }\n                break;\n            case LessThan:\n                if (isSqlAllExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.ALL_LT;\n                } else if (isAnyOrSomeExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.SOME_LT;\n                } else {\n                    operator = SqlStdOperatorTable.LESS_THAN;\n                }\n                break;\n            case LessThanOrEqual:\n                if (isSqlAllExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.ALL_LE;\n                } else if (isAnyOrSomeExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.SOME_LE;\n                } else {\n                    operator = SqlStdOperatorTable.LESS_THAN_OR_EQUAL;\n                }\n                break;\n            case NotEqual:\n            case LessThanOrGreater:\n                if (isSqlAllExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.ALL_NE;\n                } else if (isAnyOrSomeExpr(rightExpr)) {\n                    someOrAllOperator = SqlStdOperatorTable.SOME_NE;\n                } else {\n                    operator = SqlStdOperatorTable.NOT_EQUALS;\n                }\n                break;\n            case Add:\n                operator = SqlStdOperatorTable.PLUS;\n                break;\n            case Subtract:\n                operator = SqlStdOperatorTable.MINUS;\n                break;\n            case Multiply:\n                operator = SqlStdOperatorTable.MULTIPLY;\n                break;\n            case Divide:\n                operator = SqlStdOperatorTable.DIVIDE;\n                break;\n            case Modulus:\n                operator = SqlStdOperatorTable.MOD;\n                break;\n            case Like:\n                operator = SqlStdOperatorTable.LIKE;\n                break;\n            case NotLike:\n                operator = SqlStdOperatorTable.NOT_LIKE;\n                break;\n            case BooleanAnd:\n                operator = SqlStdOperatorTable.AND;\n                break;\n            case BooleanOr:\n                operator = SqlStdOperatorTable.OR;\n                break;\n            case Concat:\n                operator = SqlStdOperatorTable.CONCAT;\n                break;\n            case Is: {\n                if (rightExpr instanceof SQLNullExpr) {\n                    operator = SqlStdOperatorTable.IS_NULL;\n                } else if (rightExpr instanceof SQLIdentifierExpr) {\n                    long hashCode64 = ((SQLIdentifierExpr) rightExpr).nameHashCode64();\n                    if (hashCode64 == FnvHash.Constants.JSON\n                            || hashCode64 == JSON_VALUE) {\n                        operator = SqlStdOperatorTable.IS_JSON_VALUE;\n                    } else if (hashCode64 == JSON_OBJECT) {\n                        operator = SqlStdOperatorTable.IS_JSON_OBJECT;\n                    } else if (hashCode64 == JSON_ARRAY) {\n                        operator = SqlStdOperatorTable.IS_JSON_ARRAY;\n                    } else if (hashCode64 == JSON_SCALAR) {\n                        operator = SqlStdOperatorTable.IS_JSON_SCALAR;\n                    } else if (hashCode64 == FnvHash.Constants.UNKNOWN) {\n                        operator = SqlStdOperatorTable.IS_UNKNOWN;\n                    }\n                } else if (rightExpr instanceof SQLBooleanExpr) {\n                    if (((SQLBooleanExpr) rightExpr).getValue()) {\n                        operator = SqlStdOperatorTable.IS_TRUE;\n                    } else {\n                        operator = SqlStdOperatorTable.IS_FALSE;\n                    }\n                }\n            }\n            break;\n            case IsNot:\n                if (rightExpr instanceof SQLNullExpr) {\n                    operator = SqlStdOperatorTable.IS_NOT_NULL;\n                } else if (rightExpr instanceof SQLIdentifierExpr) {\n                    long hashCode64 = ((SQLIdentifierExpr) rightExpr).nameHashCode64();\n                    if (hashCode64 == FnvHash.Constants.JSON\n                            || hashCode64 == JSON_VALUE) {\n                        operator = SqlStdOperatorTable.IS_NOT_JSON_VALUE;\n                    } else if (hashCode64 == JSON_OBJECT) {\n                        operator = SqlStdOperatorTable.IS_NOT_JSON_OBJECT;\n                    } else if (hashCode64 == JSON_ARRAY) {\n                        operator = SqlStdOperatorTable.IS_NOT_JSON_ARRAY;\n                    } else if (hashCode64 == JSON_SCALAR) {\n                        operator = SqlStdOperatorTable.IS_NOT_JSON_SCALAR;\n                    } else if (hashCode64 == FnvHash.Constants.UNKNOWN) {\n                        operator = SqlStdOperatorTable.IS_NOT_UNKNOWN;\n                    }\n                } else if (rightExpr instanceof SQLBooleanExpr) {\n                    if (((SQLBooleanExpr) rightExpr).getValue()) {\n                        operator = SqlStdOperatorTable.IS_NOT_TRUE;\n                    } else {\n                        operator = SqlStdOperatorTable.IS_NOT_FALSE;\n                    }\n                }\n                break;\n            case Escape: {\n                SqlBasicCall like = (SqlBasicCall) left;\n                sqlNode = new SqlBasicCall(like.getOperator(), new SqlNode[]{like.operands[0], like.operands[1], right},\n                        SqlParserPos.ZERO);\n                return false;\n            }\n            default:\n                throw new FastsqlException(\"not support \" + x.getOperator());\n\n        }\n\n        if (someOrAllOperator != null) {\n            this.sqlNode = new SqlBasicCall(someOrAllOperator, new SqlNode[]{left, right},\n                    SqlParserPos.ZERO);\n        } else {\n            if (operator == SqlStdOperatorTable.IS_NULL\n                    || operator == SqlStdOperatorTable.IS_NOT_NULL\n                    || operator == SqlStdOperatorTable.IS_TRUE\n                    || operator == SqlStdOperatorTable.IS_NOT_TRUE) {\n                this.sqlNode = new SqlBasicCall(operator,\n                        new SqlNode[]{left},\n                        SqlParserPos.ZERO);\n            } else {\n                this.sqlNode = new SqlBasicCall(operator,\n                        new SqlNode[]{left, right},\n                        SqlParserPos.ZERO);\n            }\n        }\n        return false;\n    }\n\n    public boolean visit(SQLBetweenExpr x) {\n        SQLExpr testExpr = x.getTestExpr();\n        SqlOperator sqlOperator = SqlStdOperatorTable.BETWEEN;\n        if (x.isNot()) {\n            sqlOperator = SqlStdOperatorTable.NOT_BETWEEN;\n        }\n        SqlNode sqlNode = convertToSqlNode(testExpr);\n        SqlNode sqlNodeBegin = convertToSqlNode(x.getBeginExpr());\n        SqlNode sqlNodeEnd = convertToSqlNode(x.getEndExpr());\n        ArrayList<SqlNode> sqlNodes = new ArrayList<SqlNode>(3);\n        sqlNodes.add(sqlNode);\n        sqlNodes.add(sqlNodeBegin);\n        sqlNodes.add(sqlNodeEnd);\n        this.sqlNode = new SqlBasicCall(sqlOperator, SqlParserUtil.toNodeArray(sqlNodes), SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLExistsExpr x) {\n        SqlOperator sqlOperator = SqlStdOperatorTable.EXISTS;\n        SqlNode sqlNode = sqlOperator.createCall(SqlParserPos.ZERO,\n                convertToSqlNode(x.getSubQuery()));\n        if (x.isNot()) {\n            sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, sqlNode);\n        }\n        this.sqlNode = sqlNode;\n        return false;\n    }\n\n    public boolean visit(SQLAllColumnExpr x) {\n        sqlNode = new SqlIdentifier(Arrays.asList(\"\"), SqlParserPos.ZERO);\n\n        return false;\n    }\n\n    public boolean visit(SQLCharExpr x) {\n        String text = x.getText();\n        text = text.replaceAll(\"\\\\\\\\\", \"\\\\\\\\\\\\\\\\\");\n        sqlNode = SqlLiteral.createCharString(text, SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLNCharExpr x) {\n        String text = x.getText();\n        text = text.replaceAll(\"\\\\\\\\\", \"\\\\\\\\\\\\\\\\\");\n        sqlNode = SqlLiteral.createCharString(text, SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLNullExpr x) {\n        sqlNode = SqlLiteral.createNull(SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLIntegerExpr x) {\n        sqlNode = SqlLiteral.createExactNumeric(x.getNumber().toString(), SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLBooleanExpr x) {\n        sqlNode = SqlLiteral.createBoolean(x.getBooleanValue(), SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLNumberExpr x) {\n        String str = x.toString();\n        if (str.indexOf('E') > 0 || str.indexOf('e') > 0) {\n            sqlNode = SqlLiteral.createApproxNumeric(str, SqlParserPos.ZERO);\n        } else {\n            sqlNode = SqlLiteral.createExactNumeric(str, SqlParserPos.ZERO);\n        }\n        return false;\n    }\n\n    public boolean visit(SQLTimestampExpr x) {\n        String literal = x.getValue();\n        int precision = 0;\n        if (literal.endsWith(\"00\")) {\n            char c3 = literal.charAt(literal.length() - 3);\n            if (c3 >= '0' && c3 <= '9') {\n                literal = literal.substring(0, literal.length() - 2);\n                precision = 3;\n            }\n        }\n        TimestampString ts = new TimestampString(literal);\n        sqlNode = SqlLiteral.createTimestamp(ts, precision, SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLDateExpr x) {\n        String literal = x.getValue();\n        DateString ds = new DateString(literal);\n        sqlNode = SqlLiteral.createDate(ds, SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLTimeExpr x) {\n        String literal = x.getValue();\n        TimeString ds = new TimeString(literal);\n        sqlNode = SqlLiteral.createTime(ds, 0, SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLCurrentTimeExpr x) {\n        sqlNode = new SqlIdentifier(x.getType().name, SqlParserPos.ZERO);\n        return false;\n    }\n\n    public boolean visit(SQLAggregateExpr x) {\n        SqlOperator functionOperator;\n\n        String methodName = x.getMethodName();\n\n        long hashCode64 = x.methodNameHashCode64();\n\n        functionOperator = func(hashCode64);\n\n        if (functionOperator == null) {\n            functionOperator = new SqlUnresolvedFunction(new SqlIdentifier(methodName, SqlParserPos.ZERO),\n                    null,\n                    null,\n                    null,\n                    null,\n                    SqlFunctionCategory.USER_DEFINED_FUNCTION);\n        }\n\n        SqlLiteral functionQualifier = null;\n\n        if (x.getOption() == SQLAggregateOption.DISTINCT) {\n            functionQualifier = SqlSelectKeyword.DISTINCT.symbol(SqlParserPos.ZERO);\n        }\n        List<SQLExpr> arguments = x.getArguments();\n        List<SqlNode> argNodes = new ArrayList<SqlNode>(arguments.size());\n        for (int i = 0, size = arguments.size(); i < size; ++i) {\n            argNodes.add(convertToSqlNode(arguments.get(i)));\n        }\n        this.sqlNode = functionOperator.createCall(functionQualifier,\n                SqlParserPos.ZERO,\n                SqlParserUtil.toNodeArray(argNodes)\n        );\n\n        SQLOrderBy orderBy = x.getOrderBy();\n        if (orderBy != null) {\n            SqlNodeList orderByItems = convertOrderby(orderBy);\n\n            this.sqlNode = SqlStdOperatorTable.WITHIN_GROUP\n                    .createCall(SqlParserPos.ZERO, this.sqlNode, orderByItems);\n        }\n\n        SQLOver over = x.getOver();\n        if (over != null) {\n            SqlNode aggNode = this.sqlNode;\n            SQLOver.WindowingBound windowingBetweenBeginBound = over.getWindowingBetweenBeginBound();\n            SQLOver.WindowingBound windowingBetweenEndBound = over.getWindowingBetweenEndBound();\n\n            boolean isRow = over.getWindowingType() != SQLOver.WindowingType.RANGE;\n            SqlNode lowerBound;\n            if (over.getWindowingBetweenBegin() != null) {\n                over.getWindowingBetweenBegin().accept(this);\n                lowerBound = SqlWindow.createPreceding(sqlNode, SqlParserPos.ZERO);\n            } else {\n                lowerBound = createSymbol(windowingBetweenBeginBound);\n            }\n            SqlNode upperBound = createSymbol(windowingBetweenEndBound);\n\n            SqlWindow window = new SqlWindow(\n                    SqlParserPos.ZERO,\n                    null,\n                    null,\n                    convertToSqlNodeList(over.getPartitionBy()),\n                    convertOrderby(over.getOrderBy()),\n                    SqlLiteral.createBoolean(isRow, SqlParserPos.ZERO),\n                    lowerBound,\n                    upperBound,\n                    null\n            );\n            sqlNode = SqlStdOperatorTable.OVER.createCall(\n                    SqlParserPos.ZERO,\n                    aggNode,\n                    window);\n        }\n\n        SQLExpr filter = x.getFilter();\n        if (filter != null) {\n            SqlNode aggNode = this.sqlNode;\n\n            filter.accept(this);\n            sqlNode = SqlStdOperatorTable.FILTER.createCall(\n                    SqlParserPos.ZERO,\n                    aggNode,\n                    sqlNode);\n        }\n\n        return false;\n    }\n\n    protected static SqlNode createSymbol(SQLOver.WindowingBound bound) {\n        if (bound == null) {\n            return null;\n        }\n\n        switch (bound) {\n            case CURRENT_ROW:\n                return SqlWindow.createCurrentRow(SqlParserPos.ZERO);\n            case UNBOUNDED_FOLLOWING:\n                return SqlWindow.createUnboundedFollowing(SqlParserPos.ZERO);\n            case UNBOUNDED_PRECEDING:\n                return SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO);\n            default:\n                return null;\n        }\n    }\n\n    public boolean visit(SQLMethodInvokeExpr x) {\n        List<SQLExpr> arguments = x.getArguments();\n        List<SqlNode> argNodes = new ArrayList<SqlNode>(arguments.size());\n\n        long nameHashCode64 = x.methodNameHashCode64();\n\n        SqlOperator functionOperator = func(nameHashCode64);\n\n        String methodName = x.getMethodName();\n\n        if (functionOperator == null) {\n            if (nameHashCode64 == FnvHash.Constants.TRIM) {\n                functionOperator = SqlStdOperatorTable.TRIM;\n                if (arguments.size() == 1) {\n                    SqlNode sqlNode = convertToSqlNode(arguments.get(0));\n\n                    this.sqlNode = new com.alibaba.druid.support.calcite.CalciteSqlBasicCall(functionOperator,\n                            new SqlNode[]{\n                                    SqlLiteral.createSymbol(SqlTrimFunction.Flag.BOTH, SqlParserPos.ZERO),\n                                    SqlCharStringLiteral.createCharString(\" \", SqlParserPos.ZERO),\n                                    sqlNode\n                            },\n                            SqlParserPos.ZERO,\n                            false,\n                            null);\n                    return false;\n                }\n\n            } else {\n                functionOperator = new SqlUnresolvedFunction(\n                        new SqlIdentifier(methodName, SqlParserPos.ZERO),\n                        null,\n                        null,\n                        null,\n                        null,\n                        SqlFunctionCategory.USER_DEFINED_FUNCTION);\n            }\n        }\n\n        SqlLiteral functionQualifier = null;\n\n        for (SQLExpr exp : arguments) {\n            argNodes.add(convertToSqlNode(exp));\n        }\n\n        if ((nameHashCode64 == FnvHash.Constants.TIMESTAMPDIFF || nameHashCode64 == FnvHash.Constants.TIMESTAMPADD)\n                && argNodes.size() > 0\n                && argNodes.get(0) instanceof SqlIdentifier\n        ) {\n            SqlIdentifier arg0 = (SqlIdentifier) argNodes.get(0);\n            TimeUnit timeUnit = TimeUnit.valueOf(arg0.toString().toUpperCase());\n            argNodes.set(0, SqlLiteral.createSymbol(timeUnit, SqlParserPos.ZERO));\n        }\n\n        this.sqlNode = new com.alibaba.druid.support.calcite.CalciteSqlBasicCall(functionOperator,\n                SqlParserUtil.toNodeArray(argNodes),\n                SqlParserPos.ZERO,\n                false,\n                functionQualifier);\n        return false;\n    }\n\n    public boolean visit(SQLInListExpr x) {\n        SqlNodeList sqlNodes = convertToSqlNodeList(x.getTargetList());\n        SqlOperator sqlOperator = x.isNot() ? SqlStdOperatorTable.NOT_IN : SqlStdOperatorTable.IN;\n        sqlNode = new SqlBasicCall(sqlOperator, new SqlNode[]{convertToSqlNode(x.getExpr()), sqlNodes},\n                SqlParserPos.ZERO);\n\n        return false;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        if (\"?\".equals(x.getName())) {\n            this.sqlNode = new SqlDynamicParam(x.getIndex(),\n                    SqlParserPos.ZERO);\n            return false;\n        } else {\n            System.out.println(\"end\");\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnaryExpr x) {\n        SQLUnaryOperator operator = x.getOperator();\n        switch (operator) {\n            case NOT:\n                this.sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO,\n                        convertToSqlNode(x.getExpr()));\n                break;\n            case Negative:\n                this.sqlNode = SqlStdOperatorTable.UNARY_MINUS.createCall(SqlParserPos.ZERO,\n                        convertToSqlNode(x.getExpr()));\n                break;\n            case Not:\n            case Compl:\n            case BINARY:\n            default:\n                super.visit(x);\n        }\n        return false;\n    }\n\n    protected SqlNodeList convertToSqlNodeList(SQLExpr expr) {\n        if (expr instanceof SQLListExpr) {\n            return convertToSqlNodeList(((SQLListExpr) expr).getItems());\n        } else {\n            List<SqlNode> nodes = new ArrayList<SqlNode>(1);\n            return new SqlNodeList(nodes, SqlParserPos.ZERO);\n        }\n    }\n\n    protected SqlNodeList convertToSqlNodeList(List<? extends SQLExpr> exprList) {\n        final int size = exprList.size();\n\n        List<SqlNode> nodes = new ArrayList<SqlNode>(size);\n        for (int i = 0; i < size; ++i) {\n            SQLExpr expr = exprList.get(i);\n            SqlNode node;\n            if (expr instanceof SQLListExpr) {\n                node = convertToSqlNodeList(((SQLListExpr) expr).getItems());\n            } else {\n                node = convertToSqlNode(expr);\n            }\n            nodes.add(node);\n        }\n\n        return new SqlNodeList(nodes, SqlParserPos.ZERO);\n    }\n\n    protected SqlNode convertToSqlNode(SQLObject ast) {\n        if (ast == null) {\n            return null;\n        }\n        CalciteMySqlNodeVisitor visitor = new CalciteMySqlNodeVisitor();\n        ast.accept(visitor);\n        return visitor.getSqlNode();\n    }\n\n    private SqlNodeList convertOrderby(SQLOrderBy orderBy) {\n        if (orderBy == null) {\n            return new SqlNodeList(new ArrayList(), SqlParserPos.ZERO);\n        }\n\n        List<SQLSelectOrderByItem> items = orderBy.getItems();\n        List<SqlNode> orderByNodes = new ArrayList<SqlNode>(items.size());\n\n        for (SQLSelectOrderByItem item : items) {\n            SqlNode node = convertToSqlNode(item.getExpr());\n            if (item.getType() == SQLOrderingSpecification.DESC) {\n                node = new SqlBasicCall(SqlStdOperatorTable.DESC, new SqlNode[]{node}, SqlParserPos.ZERO);\n            }\n            SQLSelectOrderByItem.NullsOrderType nullsOrderType = item.getNullsOrderType();\n            if (nullsOrderType != null) {\n                switch (nullsOrderType) {\n                    case NullsFirst:\n                        node = new SqlBasicCall(SqlStdOperatorTable.NULLS_FIRST, new SqlNode[]{node}, SqlParserPos.ZERO);\n                        break;\n                    case NullsLast:\n                        node = new SqlBasicCall(SqlStdOperatorTable.NULLS_LAST, new SqlNode[]{node}, SqlParserPos.ZERO);\n                        break;\n                    default:\n                        break;\n                }\n            }\n            orderByNodes.add(node);\n        }\n\n        return new SqlNodeList(orderByNodes, SqlParserPos.ZERO);\n    }\n\n    private SqlNodeList convertHints(List<SQLCommentHint> hints) {\n        if (hints == null) {\n            return null;\n        }\n\n        List<SqlNode> nodes = new ArrayList<SqlNode>(hints.size());\n\n        for (SQLCommentHint hint : hints) {\n            if (hint instanceof TDDLHint) {\n                nodes.add(convertTDDLHint((TDDLHint) hint));\n            }\n        }\n\n        return new SqlNodeList(nodes, SqlParserPos.ZERO);\n\n    }\n\n    private SqlNodeList convertTDDLHint(TDDLHint hint) {\n        List<TDDLHint.Function> functions = hint.getFunctions();\n        List<SqlNode> funNodes = new ArrayList<SqlNode>(functions.size());\n\n        for (TDDLHint.Function function : functions) {\n            String functionName = function.getName();\n\n            List<TDDLHint.Argument> arguments = function.getArguments();\n\n            SqlNode[] argNodes = new SqlNode[arguments.size()];\n            for (int i = 0; i < arguments.size(); i++) {\n                TDDLHint.Argument argument = arguments.get(i);\n                SqlNode argName = convertToSqlNode(argument.getName());\n                SqlNode argValue = convertToSqlNode(argument.getValue());\n\n                List<SqlNode> arg = new ArrayList<SqlNode>();\n                if (argName != null) {\n                    arg.add(argName);\n                }\n                if (argValue != null) {\n                    arg.add(argValue);\n                }\n\n                SqlNode argNode = null;\n                if (arg.size() == 2) {\n                    argNode = SqlStdOperatorTable.EQUALS.createCall(SqlParserPos.ZERO, arg);\n                } else if (arg.size() == 1) {\n                    argNode = argName;\n                }\n\n                argNodes[i] = argNode;\n            }\n\n            SqlNode funNode = new SqlBasicCall(\n                    new SqlUnresolvedFunction(new SqlIdentifier(functionName, SqlParserPos.ZERO), null, null,\n                            null, null, SqlFunctionCategory.USER_DEFINED_FUNCTION), argNodes,\n                    SqlParserPos.ZERO);\n\n            funNodes.add(funNode);\n        }\n\n        return new SqlNodeList(funNodes, SqlParserPos.ZERO);\n    }\n\n    /**\n     * Converts a list of SQLInsertStatement.ValuesClause objects to a single values clause if necessary.\n     *\n     * @param valuesClauseList the list of SQLInsertStatement.ValuesClause objects to be converted\n     * @return a list containing a single SQLInsertStatement.ValuesClause object if the input list contains more than one clause and they are all literals; otherwise, the original list is returned\n     */\n    public static List<SQLInsertStatement.ValuesClause> convertToSingleValuesIfNeed(List<SQLInsertStatement.ValuesClause> valuesClauseList) {\n        if (valuesClauseList.size() <= 1) {\n            return valuesClauseList;\n        }\n\n        // If they are all literals\n        for (SQLInsertStatement.ValuesClause clause : valuesClauseList) {\n            for (SQLExpr expr : clause.getValues()) {\n                if (expr instanceof SQLVariantRefExpr) {\n                    if (((SQLVariantRefExpr) expr).getName().equals(\"?\")) {\n                        continue;\n                    }\n                }\n                return valuesClauseList;\n            }\n        }\n\n        // Return only the first values clause.\n        return Arrays.asList(valuesClauseList.get(0));\n    }\n\n    public boolean visit(SQLIntervalExpr x) {\n        TimeUnit[] timeUnits = getTimeUnit(x.getUnit());\n        List<SqlNode> convertedArgs = new ArrayList<SqlNode>(2);\n        SqlIntervalQualifier unitNode = new SqlIntervalQualifier(timeUnits[0], timeUnits[1], SqlParserPos.ZERO);\n        SqlLiteral valueNode = (SqlLiteral) convertToSqlNode(x.getValue());\n        sqlNode = SqlIntervalLiteral.createInterval(1, valueNode.toValue(), unitNode, SqlParserPos.ZERO);\n        return false;\n    }\n\n    public static TimeUnit[] getTimeUnit(SQLIntervalUnit unit) {\n        TimeUnit[] timeUnits = new TimeUnit[2];\n        switch (unit) {\n            // case MICROSECOND:\n            // timeUnits[0] = TimeUnit.MICROSECOND;\n            // timeUnits[1] = TimeUnit.MICROSECOND;\n            // break;\n            case SECOND:\n                timeUnits[0] = TimeUnit.SECOND;\n                timeUnits[1] = TimeUnit.SECOND;\n                break;\n            case MINUTE:\n                timeUnits[0] = TimeUnit.MINUTE;\n                timeUnits[1] = TimeUnit.MINUTE;\n                break;\n            case HOUR:\n                timeUnits[0] = TimeUnit.HOUR;\n                timeUnits[1] = TimeUnit.HOUR;\n                break;\n            case DAY:\n                timeUnits[0] = TimeUnit.DAY;\n                timeUnits[1] = TimeUnit.DAY;\n                break;\n            case WEEK:\n                timeUnits[0] = TimeUnit.WEEK;\n                timeUnits[1] = TimeUnit.WEEK;\n                break;\n            case MONTH:\n                timeUnits[0] = TimeUnit.MONTH;\n                timeUnits[1] = TimeUnit.MONTH;\n                break;\n            case QUARTER:\n                timeUnits[0] = TimeUnit.QUARTER;\n                timeUnits[1] = TimeUnit.QUARTER;\n                break;\n            case YEAR:\n                timeUnits[0] = TimeUnit.YEAR;\n                timeUnits[1] = TimeUnit.YEAR;\n                break;\n            // case MINUTE_MICROSECOND:\n            // timeUnits[0] = TimeUnit.MINUTE;\n            // timeUnits[1] = TimeUnit.MICROSECOND;\n            // break;\n            case MINUTE_SECOND:\n                timeUnits[0] = TimeUnit.MINUTE;\n                timeUnits[1] = TimeUnit.SECOND;\n                break;\n            // case HOUR_MICROSECOND:\n            // timeUnits[0] = TimeUnit.HOUR;\n            // timeUnits[1] = TimeUnit.MICROSECOND;\n            // break;\n            case HOUR_SECOND:\n                timeUnits[0] = TimeUnit.HOUR;\n                timeUnits[1] = TimeUnit.SECOND;\n                break;\n            case HOUR_MINUTE:\n                timeUnits[0] = TimeUnit.HOUR;\n                timeUnits[1] = TimeUnit.MINUTE;\n                break;\n            // case DAY_MICROSECOND:\n            // timeUnits[0] = TimeUnit.DAY;\n            // timeUnits[1] = TimeUnit.MICROSECOND;\n            // break;\n            case DAY_SECOND:\n                timeUnits[0] = TimeUnit.DAY;\n                timeUnits[1] = TimeUnit.SECOND;\n                break;\n            case DAY_MINUTE:\n                timeUnits[0] = TimeUnit.DAY;\n                timeUnits[1] = TimeUnit.MINUTE;\n                break;\n            case DAY_HOUR:\n                timeUnits[0] = TimeUnit.DAY;\n                timeUnits[1] = TimeUnit.HOUR;\n                break;\n            case YEAR_MONTH:\n                timeUnits[0] = TimeUnit.YEAR;\n                timeUnits[1] = TimeUnit.MONTH;\n                break;\n            default:\n                throw new ParserException(\"Unsupported time unit\");\n        }\n        return timeUnits;\n    }\n\n    public boolean visit(SQLNotExpr x) {\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLIdentifierExpr) {\n            long hashCode64 = ((SQLIdentifierExpr) expr).nameHashCode64();\n            if (hashCode64 == FnvHash.Constants.UNKNOWN) {\n                sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, SqlLiteral.createUnknown(SqlParserPos.ZERO));\n                return false;\n            }\n        }\n        expr.accept(this);\n        sqlNode = SqlStdOperatorTable.NOT.createCall(SqlParserPos.ZERO, sqlNode);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLExtractExpr x) {\n        x.getValue().accept(this);\n        TimeUnit[] timeUnits = getTimeUnit(x.getUnit());\n\n        sqlNode = SqlStdOperatorTable.EXTRACT\n                .createCall(\n                        SqlParserPos.ZERO,\n                        new SqlIntervalQualifier(timeUnits[0], timeUnits[1], SqlParserPos.ZERO),\n                        sqlNode\n                );\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLGroupingSetExpr x) {\n        sqlNode = SqlStdOperatorTable.GROUPING_SETS.createCall(\n                SqlParserPos.ZERO,\n                convertToSqlNodeList(x.getParameters())\n        );\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLValuesQuery x) {\n        List<SqlNode> valuesNodes = new ArrayList<SqlNode>();\n        for (SQLExpr value : x.getValues()) {\n            valuesNodes.add(\n                    SqlStdOperatorTable.ROW.createCall(SqlParserPos.ZERO, convertToSqlNodeList(value)));\n        }\n\n        sqlNode = SqlStdOperatorTable.VALUES.createCall(SqlParserPos.ZERO, valuesNodes);\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLUnnestTableSource x) {\n        sqlNode = SqlStdOperatorTable.UNNEST\n                .createCall(\n                        SqlParserPos.ZERO,\n                        convertToSqlNodeList(x.getItems())\n                );\n\n        String alias = x.getAlias();\n        if (alias != null) {\n            sqlNode = new SqlBasicCall(\n                    SqlStdOperatorTable.AS,\n                    new SqlNode[]{sqlNode, new SqlIdentifier(alias, SqlParserPos.ZERO)},\n                    SqlParserPos.ZERO\n            );\n        }\n        return false;\n    }\n\n    @Override\n    public boolean visit(SQLDefaultExpr x) {\n        sqlNode = SqlStdOperatorTable.DEFAULT.createCall(SqlParserPos.ZERO);\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlExplainStatement x) {\n        x.getStatement().accept(this);\n        SqlNode explicandum = this.sqlNode;\n        sqlNode = new SqlExplain(\n                SqlParserPos.ZERO,\n                explicandum,\n                SqlLiteral.createSymbol(SqlExplainLevel.EXPPLAN_ATTRIBUTES, SqlParserPos.ZERO),\n                SqlLiteral.createSymbol(SqlExplain.Depth.PHYSICAL, SqlParserPos.ZERO),\n                SqlLiteral.createSymbol(SqlExplainFormat.TEXT, SqlParserPos.ZERO),\n                0\n        );\n        return false;\n    }\n\n    static long JSON_VALUE = FnvHash.fnv1a_64_lower(\"JSON VALUE\");\n    static long JSON_OBJECT = FnvHash.fnv1a_64_lower(\"JSON OBJECT\");\n    static long JSON_ARRAY = FnvHash.fnv1a_64_lower(\"JSON ARRAY\");\n    static long JSON_SCALAR = FnvHash.fnv1a_64_lower(\"JSON SCALAR\");\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/calcite/CalciteSqlBasicCall.java",
    "content": "package com.alibaba.druid.support.calcite;\n\nimport org.apache.calcite.sql.SqlBasicCall;\nimport org.apache.calcite.sql.SqlLiteral;\nimport org.apache.calcite.sql.SqlNode;\nimport org.apache.calcite.sql.SqlOperator;\nimport org.apache.calcite.sql.parser.SqlParserPos;\n\n/**\n * @author lijun.cailj 2017/11/21\n */\npublic class CalciteSqlBasicCall extends SqlBasicCall {\n    public CalciteSqlBasicCall(SqlOperator operator, SqlNode[] operands, SqlParserPos pos) {\n        super(operator, operands, pos);\n    }\n\n    public CalciteSqlBasicCall(SqlOperator operator, SqlNode[] operands, SqlParserPos pos, boolean expanded,\n                               SqlLiteral functionQualifier) {\n        super(operator, operands, pos, expanded, functionQualifier);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/calcite/TDDLSqlSelect.java",
    "content": "package com.alibaba.druid.support.calcite;\n\nimport org.apache.calcite.sql.SqlNode;\nimport org.apache.calcite.sql.SqlNodeList;\nimport org.apache.calcite.sql.SqlSelect;\nimport org.apache.calcite.sql.parser.SqlParserPos;\n\n/**\n * 扩展calcite，支持select 中的hints\n *\n * @author lijun.cailj 2017/11/29\n */\npublic class TDDLSqlSelect extends SqlSelect {\n    private SqlNodeList hints;\n    private SqlNodeList headHints;\n\n    public TDDLSqlSelect(SqlParserPos pos, SqlNodeList keywordList, SqlNodeList selectList, SqlNode from, SqlNode where,\n                         SqlNodeList groupBy, SqlNode having, SqlNodeList windowDecls, SqlNodeList orderBy,\n                         SqlNode offset, SqlNode fetch, SqlNodeList hints, SqlNodeList headHints) {\n        super(pos, keywordList, selectList, from, where, groupBy, having, windowDecls, orderBy, offset, fetch, null);\n        this.hints = hints;\n        this.headHints = headHints;\n    }\n\n    public SqlNodeList getHints() {\n        return hints;\n    }\n\n    public void setHints(SqlNodeList hints) {\n        this.hints = hints;\n    }\n\n    public SqlNodeList getHeadHints() {\n        return headHints;\n    }\n\n    public void setHeadHints(SqlNodeList headHints) {\n        this.headHints = headHints;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/clickhouse/BalancedClickhouseDriver.java",
    "content": "package com.alibaba.druid.support.clickhouse;\n\nimport ru.yandex.clickhouse.BalancedClickhouseDataSource;\n\nimport java.sql.Connection;\nimport java.sql.DriverPropertyInfo;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.Properties;\nimport java.util.logging.Logger;\n\npublic class BalancedClickhouseDriver implements java.sql.Driver {\n    private final String url;\n    private BalancedClickhouseDataSource dataSource;\n\n    public BalancedClickhouseDriver(final String url, Properties properties) {\n        this.url = url;\n        this.dataSource = new BalancedClickhouseDataSource(url, properties);\n    }\n\n    @Override\n    public Connection connect(String url, Properties info) throws SQLException {\n        if (!acceptsURL(url)) {\n            throw new SQLException(\"TODO\");\n        }\n\n        return dataSource.getConnection();\n    }\n\n    @Override\n    public boolean acceptsURL(String url) throws SQLException {\n        return this.url.equals(url);\n    }\n\n    @Override\n    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {\n        return new DriverPropertyInfo[0];\n    }\n\n    @Override\n    public int getMajorVersion() {\n        return 0;\n    }\n\n    @Override\n    public int getMinorVersion() {\n        return 0;\n    }\n\n    @Override\n    public boolean jdbcCompliant() {\n        return false;\n    }\n\n    @Override\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/clickhouse/BalancedClickhouseDriverNative.java",
    "content": "package com.alibaba.druid.support.clickhouse;\n\nimport com.github.housepower.jdbc.BalancedClickhouseDataSource;\n\nimport java.sql.Connection;\nimport java.sql.DriverPropertyInfo;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.Properties;\nimport java.util.logging.Logger;\n\npublic class BalancedClickhouseDriverNative implements java.sql.Driver {\n    private final String url;\n    private BalancedClickhouseDataSource dataSource;\n\n    public BalancedClickhouseDriverNative(final String url, Properties properties) {\n        this.url = url;\n        this.dataSource = new BalancedClickhouseDataSource(url, properties);\n    }\n\n    @Override\n    public Connection connect(String url, Properties info) throws SQLException {\n        if (!acceptsURL(url)) {\n            throw new SQLException(\"TODO\");\n        }\n\n        return dataSource.getConnection();\n    }\n\n    @Override\n    public boolean acceptsURL(String url) throws SQLException {\n        return this.url.equals(url);\n    }\n\n    @Override\n    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {\n        return new DriverPropertyInfo[0];\n    }\n\n    @Override\n    public int getMajorVersion() {\n        return 0;\n    }\n\n    @Override\n    public int getMinorVersion() {\n        return 0;\n    }\n\n    @Override\n    public boolean jdbcCompliant() {\n        return false;\n    }\n\n    @Override\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/hibernate/DruidConnectionProvider.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.hibernate;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;\nimport org.hibernate.service.spi.Configurable;\nimport org.hibernate.service.spi.Stoppable;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Map;\n\npublic class DruidConnectionProvider implements ConnectionProvider, Configurable, Stoppable {\n    private static final long serialVersionUID = 1026193803901107651L;\n\n    private DruidDataSource dataSource;\n\n    public DruidConnectionProvider() {\n        dataSource = new DruidDataSource();\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    @Override\n    public boolean isUnwrappableAs(Class unwrapType) {\n        return dataSource.isWrapperFor(unwrapType);\n    }\n\n    @Override\n    public <T> T unwrap(Class<T> unwrapType) {\n        return dataSource.unwrap(unwrapType);\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        return dataSource.getConnection();\n    }\n\n    @Override\n    public void closeConnection(Connection conn) throws SQLException {\n        conn.close();\n    }\n\n    @Override\n    public boolean supportsAggressiveRelease() {\n        return false;\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    @Override\n    public void configure(Map configurationValues) {\n        try {\n            DruidDataSourceFactory.config(dataSource, configurationValues);\n        } catch (SQLException e) {\n            throw new IllegalArgumentException(\"config error\", e);\n        }\n    }\n\n    @Override\n    public void stop() {\n        dataSource.close();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/AbstractWebStatImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http;\n\nimport com.alibaba.druid.filter.stat.StatFilterContextListenerAdapter;\nimport com.alibaba.druid.support.http.stat.WebAppStat;\nimport com.alibaba.druid.support.http.stat.WebRequestStat;\nimport com.alibaba.druid.support.http.stat.WebSessionStat;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.DruidWebUtils;\n\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpSession;\n\npublic class AbstractWebStatImpl {\n    private static final Log LOG = LogFactory.getLog(AbstractWebStatImpl.class);\n\n    public static final int DEFAULT_MAX_STAT_SESSION_COUNT = 1000 * 1;\n\n    protected WebAppStat webAppStat;\n\n    protected boolean sessionStatEnable = true;\n    protected int sessionStatMaxCount = DEFAULT_MAX_STAT_SESSION_COUNT;\n    protected boolean createSession;\n    protected boolean profileEnable;\n\n    protected String contextPath;\n\n    protected String principalSessionName;\n    protected String principalCookieName;\n    protected String realIpHeader;\n\n    protected WebStatFilterContextListener statFilterContextListener = new WebStatFilterContextListener();\n\n    public boolean isSessionStatEnable() {\n        return sessionStatEnable;\n    }\n\n    public void setSessionStatEnable(boolean sessionStatEnable) {\n        this.sessionStatEnable = sessionStatEnable;\n    }\n\n    public boolean isProfileEnable() {\n        return profileEnable;\n    }\n\n    public void setProfileEnable(boolean profileEnable) {\n        this.profileEnable = profileEnable;\n    }\n\n    public String getContextPath() {\n        return contextPath;\n    }\n\n    public int getSessionStatMaxCount() {\n        return sessionStatMaxCount;\n    }\n\n    public String getRequestURI(HttpServletRequest request) {\n        return request.getRequestURI();\n    }\n\n    public String getPrincipalSessionName() {\n        return principalSessionName;\n    }\n\n    public String getPrincipalCookieName() {\n        return principalCookieName;\n    }\n\n    public WebSessionStat getSessionStat(HttpServletRequest request) {\n        if (!isSessionStatEnable()) {\n            return null;\n        }\n\n        WebSessionStat sessionStat = null;\n        String sessionId = getSessionId(request);\n\n        if (sessionId != null) {\n            sessionStat = webAppStat.getSessionStat(sessionId, true);\n        }\n\n        if (sessionStat != null) {\n            long currentMillis = System.currentTimeMillis();\n\n            String userAgent = request.getHeader(\"user-agent\");\n\n            if (sessionStat.getCreateTimeMillis() == -1L) {\n                HttpSession session = request.getSession(false);\n\n                if (session != null) {\n                    sessionStat.setCreateTimeMillis(session.getCreationTime());\n                } else {\n                    sessionStat.setCreateTimeMillis(currentMillis);\n                }\n\n                webAppStat.computeUserAgent(userAgent);\n                webAppStat.incrementSessionCount();\n            }\n\n            sessionStat.setUserAgent(userAgent);\n\n            String ip = getRemoteAddress(request);\n\n            sessionStat.addRemoteAddress(ip);\n        }\n\n        return sessionStat;\n    }\n\n    protected String getRemoteAddress(HttpServletRequest request) {\n        String ip = null;\n        if (this.realIpHeader != null && this.realIpHeader.length() != 0) {\n            ip = request.getHeader(realIpHeader);\n        }\n        if (ip == null || ip.length() == 0) {\n            ip = DruidWebUtils.getRemoteAddr(request);\n        }\n        return ip;\n    }\n\n    public String getSessionId(HttpServletRequest httpRequest) {\n        String sessionId = null;\n\n        HttpSession session = httpRequest.getSession(createSession);\n        if (session != null) {\n            sessionId = session.getId();\n        } else {\n            Cookie[] cookies = httpRequest.getCookies();\n            if (cookies != null) {\n                for (Cookie cookie : cookies) {\n                    if (cookie.getName().equals(\"JSESSIONID\")) {\n                        sessionId = cookie.getValue();\n                        break;\n                    }\n                }\n\n                if (sessionId == null) {\n                    for (Cookie cookie : cookies) {\n                        if (cookie.getName().equals(\"JWT-SESSION\")) {\n                            sessionId = cookie.getValue();\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        return sessionId;\n    }\n\n    public String getPrincipal(HttpServletRequest httpRequest) {\n        if (principalSessionName != null) {\n            HttpSession session = httpRequest.getSession(createSession);\n            if (session == null) {\n                return null;\n            }\n\n            Object sessionValue = null;\n\n            try {\n                sessionValue = session.getAttribute(principalSessionName);\n            } catch (Exception ex) {\n                if (LOG.isErrorEnabled()) {\n                    LOG.error(\"session.getAttribute error\", ex);\n                }\n            }\n\n            if (sessionValue == null) {\n                return null;\n            }\n\n            return sessionValue.toString();\n        }\n\n        if (principalCookieName != null && httpRequest.getCookies() != null) {\n            for (Cookie cookie : httpRequest.getCookies()) {\n                if (principalCookieName.equals(cookie.getName())) {\n                    return cookie.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public static class WebStatFilterContextListener extends StatFilterContextListenerAdapter {\n        @Override\n        public void addUpdateCount(int updateCount) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.addJdbcUpdateCount(updateCount);\n            }\n        }\n\n        @Override\n        public void addFetchRowCount(int fetchRowCount) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.addJdbcFetchRowCount(fetchRowCount);\n            }\n        }\n\n        @Override\n        public void executeBefore(String sql, boolean inTransaction) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcExecuteCount();\n            }\n        }\n\n        @Override\n        public void executeAfter(String sql, long nanos, Throwable error) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.addJdbcExecuteTimeNano(nanos);\n                if (error != null) {\n                    reqStat.incrementJdbcExecuteErrorCount();\n                }\n            }\n        }\n\n        @Override\n        public void commit() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcCommitCount();\n            }\n        }\n\n        @Override\n        public void rollback() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcRollbackCount();\n            }\n        }\n\n        @Override\n        public void pool_connect() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcPoolConnectCount();\n            }\n        }\n\n        @Override\n        public void pool_close(long nanos) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcPoolCloseCount();\n            }\n        }\n\n        @Override\n        public void resultSet_open() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcResultSetOpenCount();\n            }\n        }\n\n        @Override\n        public void resultSet_close(long nanos) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcResultSetCloseCount();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/DruidWebSecurityProvider.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * Druid web console安全性控制SPI.\n *\n * 扩展此接口以匹配项目内的认证机制, 实现SSO.\n * 需要将实现类配置在META-INF/services/com.alibaba.druid.support.http.DruidWebSecurityProvider.\n */\npublic interface DruidWebSecurityProvider {\n    /**\n     * 检查用户是否未授权访问.\n     *\n     * @param request 请求\n     * @return 如果用户未授权访问true, 否则返回false。\n     */\n    boolean isNotPermit(HttpServletRequest request);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/MonitorClientContextListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http;\n\nimport com.alibaba.druid.support.monitor.MonitorClient;\n\nimport javax.servlet.ServletContextEvent;\nimport javax.servlet.ServletContextListener;\n\npublic class MonitorClientContextListener implements ServletContextListener {\n    private MonitorClient client;\n\n    @Override\n    public void contextInitialized(ServletContextEvent event) {\n        client = new MonitorClient();\n        client.start();\n    }\n\n    @Override\n    public void contextDestroyed(ServletContextEvent event) {\n        if (client != null) {\n            client.stop();\n            this.client = null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/ResourceServlet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http;\n\nimport com.alibaba.druid.support.http.util.IPAddress;\nimport com.alibaba.druid.support.http.util.IPRange;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpSession;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.ServiceLoader;\n\n@SuppressWarnings(\"serial\")\npublic abstract class ResourceServlet extends HttpServlet {\n    private static final Log LOG = LogFactory.getLog(ResourceServlet.class);\n\n    public static final String SESSION_USER_KEY = \"druid-user\";\n    public static final String PARAM_NAME_USERNAME = \"loginUsername\";\n    public static final String PARAM_NAME_PASSWORD = \"loginPassword\";\n    public static final String PARAM_NAME_ALLOW = \"allow\";\n    public static final String PARAM_NAME_DENY = \"deny\";\n    public static final String PARAM_REMOTE_ADDR = \"remoteAddress\";\n    private static final DruidWebSecurityProvider SECURITY_SPI;\n\n    static {\n        final Iterator<DruidWebSecurityProvider> providers = ServiceLoader.load(DruidWebSecurityProvider.class).iterator();\n        if (providers.hasNext()) {\n            SECURITY_SPI = providers.next();\n            LOG.info(\"use DruidWebSecurityProvider: \" + SECURITY_SPI.getClass().getName());\n        } else {\n            SECURITY_SPI = null;\n        }\n    }\n    protected final ResourceHandler handler;\n\n    public ResourceServlet(String resourcePath) {\n        handler = new ResourceHandler(resourcePath);\n    }\n\n    public void init() throws ServletException {\n        initAuthEnv();\n    }\n\n    private void initAuthEnv() {\n        String paramUserName = getInitParameter(PARAM_NAME_USERNAME);\n        if (!StringUtils.isEmpty(paramUserName)) {\n            handler.username = paramUserName;\n        }\n\n        String paramPassword = getInitParameter(PARAM_NAME_PASSWORD);\n        if (!StringUtils.isEmpty(paramPassword)) {\n            handler.password = paramPassword;\n        }\n\n        String paramRemoteAddressHeader = getInitParameter(PARAM_REMOTE_ADDR);\n        if (!StringUtils.isEmpty(paramRemoteAddressHeader)) {\n            handler.remoteAddressHeader = paramRemoteAddressHeader;\n        }\n\n        try {\n            String param = getInitParameter(PARAM_NAME_ALLOW);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.allowList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, allow : \" + getInitParameter(PARAM_NAME_ALLOW);\n            LOG.error(msg, e);\n        }\n\n        try {\n            String param = getInitParameter(PARAM_NAME_DENY);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.denyList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, deny : \" + getInitParameter(PARAM_NAME_DENY);\n            LOG.error(msg, e);\n        }\n    }\n\n    public boolean isPermittedRequest(String remoteAddress) {\n        return handler.isPermittedRequest(remoteAddress);\n    }\n\n    protected String getFilePath(String fileName) {\n        return handler.resourcePath + fileName;\n    }\n\n    protected void returnResourceFile(String fileName, String uri, HttpServletResponse response)\n            throws ServletException,\n            IOException {\n        handler.returnResourceFile(fileName, uri, response);\n    }\n\n    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        String servletPath = request.getServletPath();\n        handler.service(request, response, servletPath, new ProcessCallback() {\n            @Override\n            public String process(String url) {\n                return ResourceServlet.this.process(url);\n            }\n        });\n    }\n\n    public boolean ContainsUser(HttpServletRequest request) {\n        return handler.containsUser(request);\n    }\n\n    public boolean checkLoginParam(HttpServletRequest request) {\n        return handler.checkLoginParam(request);\n    }\n\n    public boolean isRequireAuth() {\n        return handler.isRequireAuth();\n    }\n\n    public boolean isPermittedRequest(HttpServletRequest request) {\n        return handler.isPermittedRequest(request);\n    }\n\n    protected String getRemoteAddress(HttpServletRequest request) {\n        return handler.getRemoteAddress(request);\n    }\n\n    protected abstract String process(String url);\n\n    public static interface ProcessCallback {\n        String process(String url);\n    }\n\n    public static class ResourceHandler {\n        protected String username;\n        protected String password;\n\n        protected List<IPRange> allowList = new ArrayList<IPRange>();\n        protected List<IPRange> denyList = new ArrayList<IPRange>();\n\n        protected String resourcePath;\n\n        protected String remoteAddressHeader;\n\n        public ResourceHandler(String resourcePath) {\n            this.resourcePath = resourcePath;\n        }\n\n        protected void returnResourceFile(String fileName, String uri, HttpServletResponse response)\n                throws ServletException,\n                IOException {\n            String filePath = getFilePath(fileName);\n\n            if (filePath.endsWith(\".html\")) {\n                response.setContentType(\"text/html; charset=utf-8\");\n            }\n            if (fileName.endsWith(\".jpg\")) {\n                byte[] bytes = Utils.readByteArrayFromResource(filePath);\n                if (bytes != null) {\n                    response.getOutputStream().write(bytes);\n                }\n\n                return;\n            }\n\n            String text = Utils.readFromResource(filePath);\n            if (text == null) {\n                return;\n            }\n\n            // 设置http响应头，以便在浏览器端缓存静态资源,\n            response.setHeader(\"Cache-Control\", \"max-age=36000\");\n            if (fileName.endsWith(\".css\")) {\n                response.setContentType(\"text/css;charset=utf-8\");\n            } else if (fileName.endsWith(\".js\")) {\n                response.setContentType(\"text/javascript;charset=utf-8\");\n            }\n            response.getWriter().write(text);\n        }\n\n        protected String getFilePath(String fileName) {\n            return resourcePath + fileName;\n        }\n\n        public boolean checkLoginParam(HttpServletRequest request) {\n            String usernameParam = request.getParameter(PARAM_NAME_USERNAME);\n            String passwordParam = request.getParameter(PARAM_NAME_PASSWORD);\n            if (null == username || null == password) {\n                return false;\n            } else if (username.equals(usernameParam) && password.equals(passwordParam)) {\n                return true;\n            }\n            return false;\n        }\n\n        protected String getRemoteAddress(HttpServletRequest request) {\n            String remoteAddress = null;\n\n            if (remoteAddressHeader != null) {\n                remoteAddress = request.getHeader(remoteAddressHeader);\n            }\n\n            if (remoteAddress == null) {\n                remoteAddress = request.getRemoteAddr();\n            }\n\n            return remoteAddress;\n        }\n\n        public boolean containsUser(HttpServletRequest request) {\n            HttpSession session = request.getSession(false);\n            return session != null && session.getAttribute(SESSION_USER_KEY) != null;\n        }\n\n        public boolean isRequireAuth() {\n            return username != null;\n        }\n\n        public boolean isNotLogin(final HttpServletRequest request) {\n            if (SECURITY_SPI != null) {\n                return SECURITY_SPI.isNotPermit(request);\n            }\n            return !containsUser(request) && !checkLoginParam(request);\n        }\n\n        public boolean isPermittedRequest(HttpServletRequest request) {\n            String remoteAddress = getRemoteAddress(request);\n            return isPermittedRequest(remoteAddress);\n        }\n\n        public boolean isPermittedRequest(String remoteAddress) {\n            boolean ipV6 = remoteAddress != null && remoteAddress.indexOf(':') != -1;\n\n            if (ipV6) {\n                return \"0:0:0:0:0:0:0:1\".equals(remoteAddress) || (denyList.isEmpty() && allowList.isEmpty());\n            }\n\n            IPAddress ipAddress = new IPAddress(remoteAddress);\n\n            for (IPRange range : denyList) {\n                if (range.isIPAddressInRange(ipAddress)) {\n                    return false;\n                }\n            }\n\n            if (allowList.size() > 0) {\n                for (IPRange range : allowList) {\n                    if (range.isIPAddressInRange(ipAddress)) {\n                        return true;\n                    }\n                }\n\n                return false;\n            }\n\n            return true;\n        }\n\n        public void service(\n                HttpServletRequest request,\n                HttpServletResponse response,\n                String servletPath,\n                ProcessCallback processCallback\n        ) throws ServletException, IOException {\n            String contextPath = request.getContextPath();\n            String requestURI = request.getRequestURI();\n\n            response.setCharacterEncoding(\"utf-8\");\n\n            if (contextPath == null) { // root context\n                contextPath = \"\";\n            }\n            String uri = contextPath + servletPath;\n            String path = requestURI.substring(contextPath.length() + servletPath.length());\n\n            if (!isPermittedRequest(request)) {\n                path = \"/nopermit.html\";\n                returnResourceFile(path, uri, response);\n                return;\n            }\n\n            if (\"/submitLogin\".equals(path)) {\n                String usernameParam = request.getParameter(PARAM_NAME_USERNAME);\n                String passwordParam = request.getParameter(PARAM_NAME_PASSWORD);\n                if (username.equals(usernameParam) && password.equals(passwordParam)) {\n                    request.getSession().setAttribute(SESSION_USER_KEY, username);\n                    response.getWriter().print(\"success\");\n                } else {\n                    response.getWriter().print(\"error\");\n                }\n                return;\n            }\n\n            if (isRequireAuth() //\n                    && isNotLogin(request) //\n                    && !(\"/login.html\".equals(path) //\n                    || path.startsWith(\"/css\")//\n                    || path.startsWith(\"/js\") //\n                    || path.startsWith(\"/img\"))) {\n                if (contextPath.equals(\"\") || contextPath.equals(\"/\")) {\n                    response.sendRedirect(\"/druid/login.html\");\n                } else {\n                    if (\"\".equals(path)) {\n                        response.sendRedirect(\"druid/login.html\");\n                    } else {\n                        response.sendRedirect(\"login.html\");\n                    }\n                }\n                return;\n            }\n\n            if (\"\".equals(path) || \"/\".equals(path)) {\n                returnResourceFile(\"/index.html\", uri, response);\n                return;\n            }\n\n            if (path.contains(\".json\")) {\n                String fullUrl = path;\n                if (request.getQueryString() != null && request.getQueryString().length() > 0) {\n                    fullUrl += \"?\" + request.getQueryString();\n                }\n                response.getWriter().print(processCallback.process(fullUrl));\n                return;\n            }\n\n            // find file in resources path\n\n            returnResourceFile(path, uri, response);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/StatViewFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http;\n\nimport com.alibaba.druid.stat.DruidStatService;\nimport com.alibaba.druid.support.http.util.IPRange;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.StringUtils;\n\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport java.io.IOException;\n\nimport static com.alibaba.druid.support.http.ResourceServlet.*;\n\npublic class StatViewFilter implements Filter {\n    public static final String PARAM_NAME_PATH = \"path\";\n    private static final Log LOG = LogFactory.getLog(StatViewFilter.class);\n    private String servletPath = \"/druid\";\n    private String resourcePath = \"support/http/resources\";\n\n    private ResourceHandler handler;\n    private DruidStatService statService = DruidStatService.getInstance();\n\n    @Override\n    public void init(FilterConfig config) throws ServletException {\n        if (config == null) {\n            return;\n        }\n\n        String path = config.getInitParameter(PARAM_NAME_PATH);\n        if (path != null && !path.isEmpty()) {\n            this.servletPath = path;\n        }\n\n        handler = new ResourceHandler(resourcePath);\n\n        String paramUserName = config.getInitParameter(PARAM_NAME_USERNAME);\n        if (!StringUtils.isEmpty(paramUserName)) {\n            handler.username = paramUserName;\n        }\n\n        String paramPassword = config.getInitParameter(PARAM_NAME_PASSWORD);\n        if (!StringUtils.isEmpty(paramPassword)) {\n            handler.password = paramPassword;\n        }\n\n        String paramRemoteAddressHeader = config.getInitParameter(PARAM_REMOTE_ADDR);\n        if (!StringUtils.isEmpty(paramRemoteAddressHeader)) {\n            handler.remoteAddressHeader = paramRemoteAddressHeader;\n        }\n\n        try {\n            String param = config.getInitParameter(PARAM_NAME_ALLOW);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.allowList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, allow : \" + config.getInitParameter(PARAM_NAME_ALLOW);\n            LOG.error(msg, e);\n        }\n\n        try {\n            String param = config.getInitParameter(PARAM_NAME_DENY);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.denyList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, deny : \" + config.getInitParameter(PARAM_NAME_DENY);\n            LOG.error(msg, e);\n        }\n    }\n\n    @Override\n    public void doFilter(ServletRequest request,\n                         ServletResponse response,\n                         FilterChain chain) throws IOException, ServletException {\n        HttpServletRequest httpReq = (HttpServletRequest) request;\n        HttpServletResponse httpResp = (HttpServletResponse) response;\n        String contextPath = ((HttpServletRequest) request).getContextPath();\n\n        String requestURI = httpReq.getRequestURI();\n        if (!contextPath.equals(\"\")) {\n            requestURI = requestURI.substring(((HttpServletRequest) request).getContextPath().length());\n        }\n        if (requestURI.equals(servletPath)) {\n            httpResp.sendRedirect(httpReq.getRequestURI() + '/');\n            return;\n        }\n\n        handler.service(httpReq, httpResp, servletPath, new ResourceServlet.ProcessCallback() {\n            @Override\n            public String process(String url) {\n                return statService.service(url);\n            }\n        });\n    }\n\n    @Override\n    public void destroy() {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http;\n\nimport com.alibaba.druid.stat.DruidStatService;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.management.MBeanServerConnection;\nimport javax.management.ObjectName;\nimport javax.management.remote.JMXConnector;\nimport javax.management.remote.JMXConnectorFactory;\nimport javax.management.remote.JMXServiceURL;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 注意：避免直接调用Druid相关对象例如DruidDataSource等，相关调用要到DruidStatManagerFacade里用反射实现\n *\n * @author sandzhang[sandzhangtoo@gmail.com]\n */\npublic class StatViewServlet extends ResourceServlet {\n    private static final Log LOG = LogFactory.getLog(StatViewServlet.class);\n\n    private static final long serialVersionUID = 1L;\n\n    public static final String PARAM_NAME_RESET_ENABLE = \"resetEnable\";\n\n    public static final String PARAM_NAME_JMX_URL = \"jmxUrl\";\n    public static final String PARAM_NAME_JMX_USERNAME = \"jmxUsername\";\n    public static final String PARAM_NAME_JMX_PASSWORD = \"jmxPassword\";\n\n    private DruidStatService statService = DruidStatService.getInstance();\n\n    /**\n     * web.xml中配置的jmx的连接地址\n     */\n    private String jmxUrl;\n    /**\n     * web.xml中配置的jmx的用户名\n     */\n    private String jmxUsername;\n    /**\n     * web.xml中配置的jmx的密码\n     */\n    private String jmxPassword;\n    private MBeanServerConnection conn;\n\n    public StatViewServlet() {\n        super(\"support/http/resources\");\n    }\n\n    public void init() throws ServletException {\n        super.init();\n\n        try {\n            String param = getInitParameter(PARAM_NAME_RESET_ENABLE);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                boolean resetEnable = Boolean.parseBoolean(param);\n                statService.setResetEnable(resetEnable);\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, resetEnable : \" + getInitParameter(PARAM_NAME_RESET_ENABLE);\n            LOG.error(msg, e);\n        }\n\n        // 获取jmx的连接配置信息\n        String param = readInitParam(PARAM_NAME_JMX_URL);\n        if (param != null) {\n            jmxUrl = param;\n            jmxUsername = readInitParam(PARAM_NAME_JMX_USERNAME);\n            jmxPassword = readInitParam(PARAM_NAME_JMX_PASSWORD);\n            try {\n                initJmxConn();\n            } catch (IOException e) {\n                LOG.error(\"init jmx connection error\", e);\n            }\n        }\n\n    }\n\n    /**\n     * 读取servlet中的配置参数.\n     *\n     * @param key 配置参数名\n     * @return 配置参数值，如果不存在当前配置参数，或者为配置参数长度为0，将返回null\n     */\n    private String readInitParam(String key) {\n        String value = null;\n        try {\n            String param = getInitParameter(key);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() > 0) {\n                    value = param;\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config [\" + key + \"] error\";\n            LOG.warn(msg, e);\n        }\n        return value;\n    }\n\n    /**\n     * 初始化jmx连接\n     *\n     * @throws IOException\n     */\n    private void initJmxConn() throws IOException {\n        if (jmxUrl != null) {\n            JMXServiceURL url = new JMXServiceURL(jmxUrl);\n            Map<String, String[]> env = null;\n            if (jmxUsername != null) {\n                env = new HashMap<String, String[]>();\n                String[] credentials = new String[]{jmxUsername, jmxPassword};\n                env.put(JMXConnector.CREDENTIALS, credentials);\n            }\n            JMXConnector jmxc = JMXConnectorFactory.connect(url, env);\n            conn = jmxc.getMBeanServerConnection();\n        }\n    }\n\n    /**\n     * 根据指定的url来获取jmx服务返回的内容.\n     *\n     * @param connetion jmx连接\n     * @param url       url内容\n     * @return the jmx返回的内容\n     * @throws Exception the exception\n     */\n    private String getJmxResult(MBeanServerConnection connetion, String url) throws Exception {\n        ObjectName name = new ObjectName(DruidStatService.MBEAN_NAME);\n\n        String result = (String) conn.invoke(name, \"service\", new String[]{url},\n                new String[]{String.class.getName()});\n        return result;\n    }\n\n    /**\n     * 程序首先判断是否存在jmx连接地址，如果不存在，则直接调用本地的druid服务； 如果存在，则调用远程jmx服务。在进行jmx通信，首先判断一下jmx连接是否已经建立成功，如果已经\n     * 建立成功，则直接进行通信，如果之前没有成功建立，则会尝试重新建立一遍。.\n     *\n     * @param url 要连接的服务地址\n     * @return 调用服务后返回的json字符串\n     */\n    protected String process(String url) {\n        String resp = null;\n        if (jmxUrl == null) {\n            resp = statService.service(url);\n        } else {\n            if (conn == null) {\n                // 连接在初始化时创建失败\n                try {\n                    // 尝试重新连接\n                    initJmxConn();\n                } catch (IOException e) {\n                    LOG.error(\"init jmx connection error\", e);\n                    resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR,\n                            \"init jmx connection error\" + e.getMessage());\n                }\n                if (conn != null) {\n                    // 连接成功\n                    try {\n                        resp = getJmxResult(conn, url);\n                    } catch (Exception e) {\n                        LOG.error(\"get jmx data error\", e);\n                        resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR, \"get data error:\"\n                                + e.getMessage());\n                    }\n                }\n            } else {\n                // 连接成功\n                try {\n                    resp = getJmxResult(conn, url);\n                } catch (Exception e) {\n                    LOG.error(\"get jmx data error\", e);\n                    resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR,\n                            \"get data error\" + e.getMessage());\n                }\n            }\n        }\n        return resp;\n    }\n\n    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        String contextPath = request.getContextPath();\n        String servletPath = request.getServletPath();\n        String requestURI = request.getRequestURI();\n\n        response.setCharacterEncoding(\"utf-8\");\n\n        if (contextPath == null) { // root context\n            contextPath = \"\";\n        }\n        String uri = contextPath + servletPath;\n        String path = requestURI.substring(contextPath.length() + servletPath.length());\n\n        if (\"\".equals(path)) {\n            if (contextPath.equals(\"\") || contextPath.equals(\"/\")) {\n                response.sendRedirect(\"/druid/index.html\");\n            } else {\n                response.sendRedirect(\"druid/index.html\");\n            }\n            return;\n        }\n\n        if (\"/\".equals(path)) {\n            response.sendRedirect(\"index.html\");\n            return;\n        }\n\n        super.service(request, response);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/WebStatFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http;\n\nimport com.alibaba.druid.filter.stat.StatFilterContext;\nimport com.alibaba.druid.support.http.stat.*;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.support.profile.ProfileEntryKey;\nimport com.alibaba.druid.support.profile.ProfileEntryReqStat;\nimport com.alibaba.druid.support.profile.Profiler;\nimport com.alibaba.druid.util.DruidWebUtils;\nimport com.alibaba.druid.util.PatternMatcher;\nimport com.alibaba.druid.util.ServletPathMatcher;\n\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpServletResponseWrapper;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * 用于配置Web和Druid数据源之间的管理关联监控统计\n *\n * @author wenshao [szujobs@htomail.com]\n * @author Zhangming Qi [qizhanming@gmail.com]\n */\npublic class WebStatFilter extends AbstractWebStatImpl implements Filter {\n    private static final Log LOG = LogFactory.getLog(WebStatFilter.class);\n\n    public static final String PARAM_NAME_PROFILE_ENABLE = \"profileEnable\";\n    public static final String PARAM_NAME_SESSION_STAT_ENABLE = \"sessionStatEnable\";\n    public static final String PARAM_NAME_SESSION_STAT_MAX_COUNT = \"sessionStatMaxCount\";\n    public static final String PARAM_NAME_EXCLUSIONS = \"exclusions\";\n    public static final String PARAM_NAME_PRINCIPAL_SESSION_NAME = \"principalSessionName\";\n    public static final String PARAM_NAME_PRINCIPAL_COOKIE_NAME = \"principalCookieName\";\n    public static final String PARAM_NAME_REAL_IP_HEADER = \"realIpHeader\";\n\n    /**\n     * PatternMatcher used in determining which paths to react to for a given request.\n     */\n    protected final PatternMatcher pathMatcher = ServletPathMatcher.getInstance();\n\n    private Set<String> excludesPattern;\n\n    @Override\n    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,\n            ServletException {\n        HttpServletRequest httpRequest = (HttpServletRequest) request;\n        HttpServletResponse httpResponse = (HttpServletResponse) response;\n        StatHttpServletResponseWrapper responseWrapper = new StatHttpServletResponseWrapper(httpResponse);\n\n        String requestURI = getRequestURI(httpRequest);\n\n        if (isExclusion(requestURI)) {\n            chain.doFilter(request, response);\n            return;\n        }\n\n        long startNano = System.nanoTime();\n        long startMillis = System.currentTimeMillis();\n\n        WebRequestStat requestStat = new WebRequestStat(startNano, startMillis);\n        WebRequestStat.set(requestStat);\n\n        WebSessionStat sessionStat = getSessionStat(httpRequest);\n        webAppStat.beforeInvoke();\n\n        WebURIStat uriStat = webAppStat.getURIStat(requestURI, false);\n\n        if (uriStat == null) {\n            int index = requestURI.indexOf(\";jsessionid=\");\n            if (index != -1) {\n                requestURI = requestURI.substring(0, index);\n                uriStat = webAppStat.getURIStat(requestURI, false);\n            }\n        }\n\n        if (isProfileEnable()) {\n            Profiler.initLocal();\n            Profiler.enter(requestURI, Profiler.PROFILE_TYPE_WEB);\n        }\n\n        // 第一次访问时，uriStat这里为null，是为了防止404攻击。\n        if (uriStat != null) {\n            uriStat.beforeInvoke();\n        }\n\n        // 第一次访问时，sessionId为null，如果缺省sessionCreate=false，sessionStat就为null。\n        if (sessionStat != null) {\n            sessionStat.beforeInvoke();\n        }\n\n        Throwable error = null;\n        try {\n            chain.doFilter(request, responseWrapper);\n        } catch (IOException e) {\n            error = e;\n            throw e;\n        } catch (ServletException e) {\n            error = e;\n            throw e;\n        } catch (RuntimeException e) {\n            error = e;\n            throw e;\n        } catch (Error e) {\n            error = e;\n            throw e;\n        } finally {\n            long endNano = System.nanoTime();\n            requestStat.setEndNano(endNano);\n\n            long nanos = endNano - startNano;\n            webAppStat.afterInvoke(error, nanos);\n\n            if (sessionStat == null) {\n                sessionStat = getSessionStat(httpRequest);\n                if (sessionStat != null) {\n                    sessionStat.beforeInvoke(); // 补偿\n                }\n            }\n\n            if (sessionStat != null) {\n                sessionStat.afterInvoke(error, nanos);\n                sessionStat.setPrincipal(getPrincipal(httpRequest));\n            }\n\n            if (uriStat == null) {\n                int status = responseWrapper.getStatus();\n                if (status == HttpServletResponse.SC_NOT_FOUND) {\n                    String errorUrl = contextPath + \"error_\" + status;\n                    uriStat = webAppStat.getURIStat(errorUrl, true);\n                } else {\n                    uriStat = webAppStat.getURIStat(requestURI, true);\n                }\n\n                if (uriStat != null) {\n                    uriStat.beforeInvoke(); // 补偿调用\n                }\n            }\n\n            if (uriStat != null) {\n                uriStat.afterInvoke(error, nanos);\n            }\n\n            WebRequestStat.set(null);\n\n            if (isProfileEnable()) {\n                Profiler.release(nanos);\n\n                Map<ProfileEntryKey, ProfileEntryReqStat> requestStatsMap = Profiler.getStatsMap();\n                if (uriStat != null) {\n                    uriStat.getProfiletat().record(requestStatsMap);\n                }\n                Profiler.removeLocal();\n            }\n        }\n    }\n\n    public boolean isExclusion(String requestURI) {\n        if (excludesPattern == null || requestURI == null) {\n            return false;\n        }\n\n        if (contextPath != null && requestURI.startsWith(contextPath)) {\n            requestURI = requestURI.substring(contextPath.length());\n            if (!requestURI.startsWith(\"/\")) {\n                requestURI = \"/\" + requestURI;\n            }\n        }\n\n        for (String pattern : excludesPattern) {\n            if (pathMatcher.matches(pattern, requestURI)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public void init(FilterConfig config) throws ServletException {\n        {\n            String exclusions = config.getInitParameter(PARAM_NAME_EXCLUSIONS);\n            if (exclusions != null && exclusions.trim().length() != 0) {\n                excludesPattern = new HashSet<String>(Arrays.asList(exclusions.split(\"\\\\s*,\\\\s*\")));\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_PRINCIPAL_SESSION_NAME);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() != 0) {\n                    this.principalSessionName = param;\n                }\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_PRINCIPAL_COOKIE_NAME);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() != 0) {\n                    this.principalCookieName = param;\n                }\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_SESSION_STAT_ENABLE);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                if (\"true\".equals(param)) {\n                    this.sessionStatEnable = true;\n                } else if (\"false\".equals(param)) {\n                    this.sessionStatEnable = false;\n                } else {\n                    LOG.error(\"WebStatFilter Parameter '\" + PARAM_NAME_SESSION_STAT_ENABLE + \"' config error\");\n                }\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_PROFILE_ENABLE);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                if (\"true\".equals(param)) {\n                    this.profileEnable = true;\n                } else if (\"false\".equals(param)) {\n                    this.profileEnable = false;\n                } else {\n                    LOG.error(\"WebStatFilter Parameter '\" + PARAM_NAME_PROFILE_ENABLE + \"' config error\");\n                }\n            }\n        }\n        {\n            String param = config.getInitParameter(PARAM_NAME_SESSION_STAT_MAX_COUNT);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                try {\n                    this.sessionStatMaxCount = Integer.parseInt(param);\n                } catch (NumberFormatException e) {\n                    LOG.error(\"WebStatFilter Parameter '\" + PARAM_NAME_SESSION_STAT_ENABLE + \"' config error\", e);\n                }\n            }\n        }\n\n        // realIpHeader\n        {\n            String param = config.getInitParameter(PARAM_NAME_REAL_IP_HEADER);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() != 0) {\n                    this.realIpHeader = param;\n                }\n            }\n        }\n\n        StatFilterContext.getInstance().addContextListener(statFilterContextListener);\n\n        this.contextPath = DruidWebUtils.getContextPath(config.getServletContext());\n        if (webAppStat == null) {\n            webAppStat = new WebAppStat(contextPath, this.sessionStatMaxCount);\n        }\n        WebAppStatManager.getInstance().addWebAppStatSet(webAppStat);\n    }\n\n    @Override\n    public void destroy() {\n        StatFilterContext.getInstance().removeContextListener(statFilterContextListener);\n\n        if (webAppStat != null) {\n            WebAppStatManager.getInstance().remove(webAppStat);\n        }\n    }\n\n    public void setWebAppStat(WebAppStat webAppStat) {\n        this.webAppStat = webAppStat;\n    }\n\n    public WebAppStat getWebAppStat() {\n        return webAppStat;\n    }\n\n    public WebStatFilterContextListener getStatFilterContextListener() {\n        return statFilterContextListener;\n    }\n\n    public static final class StatHttpServletResponseWrapper extends HttpServletResponseWrapper implements HttpServletResponse {\n        //初始值应该设置为：HttpServletResponse.SC_OK，而不是 0。\n        private int status = HttpServletResponse.SC_OK;\n\n        public StatHttpServletResponseWrapper(HttpServletResponse response) {\n            super(response);\n        }\n\n        public void setStatus(int statusCode) {\n            super.setStatus(statusCode);\n            this.status = statusCode;\n        }\n\n        @SuppressWarnings(\"deprecation\")\n        public void setStatus(int statusCode, String statusMessage) {\n            super.setStatus(statusCode, statusMessage);\n            this.status = statusCode;\n        }\n\n        public void sendError(int statusCode, String statusMessage) throws IOException {\n            super.sendError(statusCode, statusMessage);\n            this.status = statusCode;\n        }\n\n        public void sendError(int statusCode) throws IOException {\n            super.sendError(statusCode);\n            this.status = statusCode;\n        }\n\n        public int getStatus() {\n            return status;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebAppStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.LRUCache;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReadWriteLock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class WebAppStat {\n    private static final Log LOG = LogFactory.getLog(WebAppStat.class);\n\n    public static final int DEFAULT_MAX_STAT_URI_COUNT = 1000;\n    public static final int DEFAULT_MAX_STAT_SESSION_COUNT = 1000;\n\n    private static final ThreadLocal<WebAppStat> currentLocal = new ThreadLocal<WebAppStat>();\n\n    private volatile int maxStatUriCount = DEFAULT_MAX_STAT_URI_COUNT;\n    private volatile int maxStatSessionCount = DEFAULT_MAX_STAT_SESSION_COUNT;\n\n    private final AtomicInteger runningCount = new AtomicInteger();\n    private final AtomicInteger concurrentMax = new AtomicInteger();\n    private final AtomicLong requestCount = new AtomicLong(0);\n    private final AtomicLong sessionCount = new AtomicLong(0);\n\n    private final AtomicLong jdbcFetchRowCount = new AtomicLong();\n    private final AtomicLong jdbcUpdateCount = new AtomicLong();\n    private final AtomicLong jdbcExecuteCount = new AtomicLong();\n    private final AtomicLong jdbcExecuteTimeNano = new AtomicLong();\n\n    private final AtomicLong jdbcCommitCount = new AtomicLong();\n    private final AtomicLong jdbcRollbackCount = new AtomicLong();\n\n    private final ConcurrentMap<String, WebURIStat> uriStatMap = new ConcurrentHashMap<String, WebURIStat>(\n            16,\n            0.75f,\n            1);\n    private final LRUCache<String, WebSessionStat> sessionStatMap;\n\n    private final ReadWriteLock sessionStatLock = new ReentrantReadWriteLock();\n\n    private final AtomicLong uriStatMapFullCount = new AtomicLong();\n    private final AtomicLong uriSessionMapFullCount = new AtomicLong();\n\n    private final AtomicLong osMacOSXCount = new AtomicLong(0);\n    private final AtomicLong osWindowsCount = new AtomicLong(0);\n    private final AtomicLong osLinuxCount = new AtomicLong(0);\n    private final AtomicLong osSymbianCount = new AtomicLong(0);\n    private final AtomicLong osFreeBSDCount = new AtomicLong(0);\n    private final AtomicLong osOpenBSDCount = new AtomicLong(0);\n    private final AtomicLong osAndroidCount = new AtomicLong(0);\n\n    private final AtomicLong osWindows98Count = new AtomicLong();\n    private final AtomicLong osWindowsXPCount = new AtomicLong();\n    private final AtomicLong osWindows2000Count = new AtomicLong();\n    private final AtomicLong osWindowsVistaCount = new AtomicLong();\n    private final AtomicLong osWindows7Count = new AtomicLong();\n    private final AtomicLong osWindows8Count = new AtomicLong();\n\n    private final AtomicLong osAndroid15Count = new AtomicLong(0);\n    private final AtomicLong osAndroid16Count = new AtomicLong(0);\n    private final AtomicLong osAndroid20Count = new AtomicLong(0);\n    private final AtomicLong osAndroid21Count = new AtomicLong(0);\n    private final AtomicLong osAndroid22Count = new AtomicLong(0);\n    private final AtomicLong osAndroid23Count = new AtomicLong(0);\n    private final AtomicLong osAndroid30Count = new AtomicLong(0);\n    private final AtomicLong osAndroid31Count = new AtomicLong(0);\n    private final AtomicLong osAndroid32Count = new AtomicLong(0);\n    private final AtomicLong osAndroid40Count = new AtomicLong(0);\n    private final AtomicLong osAndroid41Count = new AtomicLong(0);\n    private final AtomicLong osAndroid42Count = new AtomicLong(0);\n    private final AtomicLong osAndroid43Count = new AtomicLong(0);\n\n    private final AtomicLong osLinuxUbuntuCount = new AtomicLong(0);\n\n    private final AtomicLong browserIECount = new AtomicLong(0);\n    private final AtomicLong browserFirefoxCount = new AtomicLong(0);\n    private final AtomicLong browserChromeCount = new AtomicLong(0);\n    private final AtomicLong browserSafariCount = new AtomicLong(0);\n    private final AtomicLong browserOperaCount = new AtomicLong(0);\n\n    private final AtomicLong browserIE5Count = new AtomicLong(0);\n    private final AtomicLong browserIE6Count = new AtomicLong(0);\n    private final AtomicLong browserIE7Count = new AtomicLong(0);\n    private final AtomicLong browserIE8Count = new AtomicLong(0);\n    private final AtomicLong browserIE9Count = new AtomicLong(0);\n    private final AtomicLong browserIE10Count = new AtomicLong(0);\n\n    private final AtomicLong browser360SECount = new AtomicLong(0);\n\n    private final AtomicLong deviceAndroidCount = new AtomicLong(0);\n    private final AtomicLong deviceIpadCount = new AtomicLong(0);\n    private final AtomicLong deviceIphoneCount = new AtomicLong(0);\n    private final AtomicLong deviceWindowsPhoneCount = new AtomicLong(0);\n\n    private final AtomicLong botCount = new AtomicLong();\n    private final AtomicLong botBaiduCount = new AtomicLong();\n    private final AtomicLong botYoudaoCount = new AtomicLong();\n    private final AtomicLong botGoogleCount = new AtomicLong();\n    private final AtomicLong botMsnCount = new AtomicLong();\n    private final AtomicLong botBingCount = new AtomicLong();\n    private final AtomicLong botSosoCount = new AtomicLong();\n    private final AtomicLong botSogouCount = new AtomicLong();\n    private final AtomicLong botYahooCount = new AtomicLong();\n\n    private String contextPath;\n\n    public static WebAppStat current() {\n        return currentLocal.get();\n    }\n\n    public void reset() {\n        concurrentMax.set(0);\n        requestCount.set(0);\n        requestCount.set(0);\n        sessionCount.set(0);\n\n        jdbcFetchRowCount.set(0);\n        jdbcUpdateCount.set(0);\n        jdbcExecuteCount.set(0);\n        jdbcExecuteTimeNano.set(0);\n        jdbcCommitCount.set(0);\n        jdbcRollbackCount.set(0);\n\n        sessionStatLock.readLock().lock();\n        try {\n            Iterator<Map.Entry<String, WebSessionStat>> iter = sessionStatMap.entrySet().iterator();\n            while (iter.hasNext()) {\n                Map.Entry<String, WebSessionStat> entry = iter.next();\n                entry.getValue().reset();\n            }\n            sessionStatMap.clear();\n        } finally {\n            sessionStatLock.readLock().unlock();\n        }\n\n        uriStatMap.clear();\n\n        uriStatMapFullCount.set(0);\n        uriSessionMapFullCount.set(0);\n\n        osMacOSXCount.set(0);\n        osWindowsCount.set(0);\n        osLinuxCount.set(0);\n        osSymbianCount.set(0);\n        osOpenBSDCount.set(0);\n        osFreeBSDCount.set(0);\n        osAndroidCount.set(0);\n\n        osWindows98Count.set(0);\n        osWindowsXPCount.set(0);\n        osWindows2000Count.set(0);\n        osWindowsVistaCount.set(0);\n        osWindows7Count.set(0);\n        osWindows8Count.set(0);\n\n        osLinuxUbuntuCount.set(0);\n\n        osAndroid15Count.set(0);\n        osAndroid16Count.set(0);\n        osAndroid20Count.set(0);\n        osAndroid21Count.set(0);\n        osAndroid22Count.set(0);\n        osAndroid23Count.set(0);\n        osAndroid30Count.set(0);\n        osAndroid31Count.set(0);\n        osAndroid32Count.set(0);\n        osAndroid40Count.set(0);\n        osAndroid41Count.set(0);\n        osAndroid42Count.set(0);\n        osAndroid43Count.set(0);\n\n        browserIE6Count.set(0);\n        browserIE7Count.set(0);\n        browserIE8Count.set(0);\n        browserIE9Count.set(0);\n        browserIE10Count.set(0);\n\n        browserIECount.set(0);\n        browserFirefoxCount.set(0);\n        browserChromeCount.set(0);\n        browserSafariCount.set(0);\n        browserOperaCount.set(0);\n\n        browser360SECount.set(0);\n\n        deviceAndroidCount.set(0);\n        deviceIpadCount.set(0);\n        deviceIphoneCount.set(0);\n        deviceWindowsPhoneCount.set(0);\n    }\n\n    public WebAppStat() {\n        this(null);\n    }\n\n    public WebAppStat(String contextPath) {\n        this(contextPath, DEFAULT_MAX_STAT_SESSION_COUNT);\n    }\n\n    public WebAppStat(String contextPath, int maxStatSessionCount) {\n        this.contextPath = contextPath;\n        this.maxStatSessionCount = maxStatSessionCount;\n\n        sessionStatMap = new LRUCache<String, WebSessionStat>(maxStatSessionCount);\n    }\n\n    public String getContextPath() {\n        return contextPath;\n    }\n\n    public void beforeInvoke() {\n        currentLocal.set(this);\n\n        int running = runningCount.incrementAndGet();\n\n        for (; ; ) {\n            int max = concurrentMax.get();\n            if (running > max) {\n                if (concurrentMax.compareAndSet(max, running)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        requestCount.incrementAndGet();\n    }\n\n    public WebURIStat getURIStat(String uri) {\n        return getURIStat(uri, false);\n    }\n\n    public WebURIStat getURIStat(String uri, boolean create) {\n        WebURIStat uriStat = uriStatMap.get(uri);\n\n        if (uriStat != null) {\n            return uriStat;\n        }\n\n        if (!create) {\n            return null;\n        }\n\n        if (uriStatMap.size() >= this.getMaxStatUriCount()) {\n            long fullCount = uriStatMapFullCount.getAndIncrement();\n\n            if (fullCount == 0) {\n                LOG.error(\"uriSessionMapFullCount is full\");\n            }\n\n            return null;\n        }\n\n        uriStatMap.putIfAbsent(uri, new WebURIStat(uri));\n        uriStat = uriStatMap.get(uri);\n\n        return uriStat;\n    }\n\n    public WebSessionStat getSessionStat(String sessionId) {\n        return getSessionStat(sessionId, false);\n    }\n\n    public Map<String, Object> getSessionStatData(String sessionId) {\n        WebSessionStat sessionStat = sessionStatMap.get(sessionId);\n\n        if (sessionStat == null) {\n            return null;\n        }\n\n        return sessionStat.getStatData();\n    }\n\n    public Map<String, Object> getURIStatData(String uri) {\n        WebURIStat uriStat = getURIStat(uri);\n\n        if (uriStat == null) {\n            return null;\n        }\n\n        return uriStat.getStatData();\n    }\n\n    public WebSessionStat getSessionStat(String sessionId, boolean create) {\n        sessionStatLock.readLock().lock();\n        try {\n            WebSessionStat uriStat = sessionStatMap.get(sessionId);\n\n            if (uriStat != null) {\n                return uriStat;\n            }\n        } finally {\n            sessionStatLock.readLock().unlock();\n        }\n\n        if (!create) {\n            return null;\n        }\n\n        sessionStatLock.writeLock().lock();\n        try {\n            WebSessionStat uriStat = sessionStatMap.get(sessionId);\n\n            if (uriStat == null) {\n                if (sessionStatMap.size() >= this.getMaxStatSessionCount()) {\n                    long fullCount = uriSessionMapFullCount.getAndIncrement();\n\n                    if (fullCount == 0) {\n                        LOG.warn(\"sessionStatMap is full\");\n                    }\n                }\n\n                WebSessionStat newStat = new WebSessionStat(sessionId);\n\n                sessionStatMap.put(sessionId, newStat);\n\n                return newStat;\n            }\n\n            return uriStat;\n        } finally {\n            sessionStatLock.writeLock().unlock();\n        }\n    }\n\n    public void afterInvoke(Throwable error, long nanoSpan) {\n        runningCount.decrementAndGet();\n        currentLocal.set(null);\n\n        WebRequestStat requestStat = WebRequestStat.current();\n        if (requestStat != null) {\n            this.addJdbcExecuteCount(requestStat.getJdbcExecuteCount());\n            this.addJdbcFetchRowCount(requestStat.getJdbcFetchRowCount());\n            this.addJdbcUpdateCount(requestStat.getJdbcUpdateCount());\n            this.addJdbcCommitCount(requestStat.getJdbcCommitCount());\n            this.addJdbcRollbackCount(requestStat.getJdbcRollbackCount());\n            this.addJdbcExecuteTimeNano(requestStat.getJdbcExecuteTimeNano());\n        }\n    }\n\n    public void incrementSessionCount() {\n        sessionCount.incrementAndGet();\n    }\n\n    public long getSessionCount() {\n        return sessionCount.get();\n    }\n\n    public void addJdbcFetchRowCount(long delta) {\n        this.jdbcFetchRowCount.addAndGet(delta);\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount.get();\n    }\n\n    public void addJdbcUpdateCount(long updateCount) {\n        this.jdbcUpdateCount.addAndGet(updateCount);\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount.get();\n    }\n\n    public void incrementJdbcExecuteCount() {\n        jdbcExecuteCount.incrementAndGet();\n    }\n\n    public void addJdbcExecuteCount(long executeCount) {\n        jdbcExecuteCount.addAndGet(executeCount);\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount.get();\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano.get();\n    }\n\n    public void addJdbcExecuteTimeNano(long nano) {\n        jdbcExecuteTimeNano.addAndGet(nano);\n    }\n\n    public void incrementJdbcCommitCount() {\n        jdbcCommitCount.incrementAndGet();\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount.get();\n    }\n\n    public void addJdbcCommitCount(long commitCount) {\n        this.jdbcCommitCount.addAndGet(commitCount);\n    }\n\n    public void incrementJdbcRollbackCount() {\n        jdbcRollbackCount.incrementAndGet();\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount.get();\n    }\n\n    public void addJdbcRollbackCount(long rollbackCount) {\n        this.jdbcRollbackCount.addAndGet(rollbackCount);\n    }\n\n    public int getMaxStatUriCount() {\n        return maxStatUriCount;\n    }\n\n    public void setMaxStatUriCount(int maxStatUriCount) {\n        this.maxStatUriCount = maxStatUriCount;\n    }\n\n    public int getMaxStatSessionCount() {\n        return maxStatSessionCount;\n    }\n\n    public void setMaxStatSessionCount(int maxStatSessionCount) {\n        this.maxStatSessionCount = maxStatSessionCount;\n    }\n\n    public int getRunningCount() {\n        return this.runningCount.get();\n    }\n\n    public long getConcurrentMax() {\n        return concurrentMax.get();\n    }\n\n    public long getRequestCount() {\n        return requestCount.get();\n    }\n\n    public Map<String, Object> getStatData() {\n        return getStatValue(false).getStatData();\n    }\n\n    public List<WebURIStatValue> getURIStatValueList(boolean reset) {\n        List<WebURIStatValue> list = new ArrayList<WebURIStatValue>(this.uriStatMap.size());\n\n        for (WebURIStat uriStat : this.uriStatMap.values()) {\n            WebURIStatValue statValue = uriStat.getValue(reset);\n\n            if (statValue.getRunningCount() == 0 && statValue.getRequestCount() == 0) {\n                continue;\n            }\n            list.add(statValue);\n        }\n\n        return list;\n    }\n\n    public List<Map<String, Object>> getURIStatDataList() {\n        List<Map<String, Object>> uriStatDataList = new ArrayList<Map<String, Object>>(this.uriStatMap.size());\n        for (WebURIStat uriStat : this.uriStatMap.values()) {\n            Map<String, Object> uriStatData = uriStat.getStatData();\n\n            int runningCount = ((Number) uriStatData.get(\"RunningCount\")).intValue();\n            long requestCount = (Long) uriStatData.get(\"RequestCount\");\n\n            if (runningCount == 0 && requestCount == 0) {\n                continue;\n            }\n\n            uriStatDataList.add(uriStatData);\n        }\n        return uriStatDataList;\n    }\n\n    public List<Map<String, Object>> getSessionStatDataList() {\n        Lock lock = sessionStatLock.readLock();\n        lock.lock();\n        try {\n            List<Map<String, Object>> sessionStatDataList = new ArrayList<Map<String, Object>>(this.sessionStatMap.size());\n            for (WebSessionStat sessionStat : this.sessionStatMap.values()) {\n                Map<String, Object> sessionStatData = sessionStat.getStatData();\n\n                int runningCount = ((Number) sessionStatData.get(\"RunningCount\")).intValue();\n                long requestCount = (Long) sessionStatData.get(\"RequestCount\");\n\n                if (runningCount == 0 && requestCount == 0) {\n                    continue;\n                }\n\n                sessionStatDataList.add(sessionStatData);\n            }\n            return sessionStatDataList;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void computeUserAgent(String userAgent) {\n        if (userAgent == null || userAgent.length() == 0) {\n            return;\n        }\n\n        // Mozilla/5.0 (compatible;\n        final int MOZILLA_COMPATIBLE_OFFSET = 25;\n\n        boolean is360SE = userAgent.endsWith(\"360SE)\");\n\n        if (is360SE) {\n            browser360SECount.incrementAndGet();\n        }\n\n        boolean isIE = userAgent.startsWith(\"MSIE\", MOZILLA_COMPATIBLE_OFFSET);\n        int iePrefixIndex = 30; // \"Mozilla/5.0 (compatible; MSIE \".length();\n\n        boolean isGoogleToolbar = false;\n\n        if (!isIE) {\n            isGoogleToolbar = userAgent.startsWith(\"GoogleToolbar\", MOZILLA_COMPATIBLE_OFFSET);\n            if (isGoogleToolbar) {\n                // MSIE\n                int tmp = userAgent.indexOf(\"IE \");\n                if (tmp != -1) {\n                    isIE = true;\n                    iePrefixIndex = tmp + 3;\n                }\n            }\n        }\n\n        if (isIE) {\n            browserIECount.incrementAndGet();\n\n            char v1 = ' ', v2 = ' ';\n            if (userAgent.length() > iePrefixIndex + 1) {\n                v1 = userAgent.charAt(iePrefixIndex);\n                v2 = userAgent.charAt(iePrefixIndex + 1);\n            } else if (userAgent.length() > iePrefixIndex) {\n                v1 = userAgent.charAt(iePrefixIndex);\n            }\n\n            switch (v1) {\n                case '5':\n                    browserIE5Count.incrementAndGet();\n                    break;\n                case '6':\n                    browserIE6Count.incrementAndGet();\n                    break;\n                case '7':\n                    browserIE7Count.incrementAndGet();\n                    break;\n                case '8':\n                    browserIE8Count.incrementAndGet();\n                    break;\n                case '9':\n                    browserIE9Count.incrementAndGet();\n                    break;\n                case '1':\n                    if (v2 == '0') {\n                        browserIE10Count.incrementAndGet();\n                    }\n                    break;\n                default:\n                    break;\n            }\n\n            osWindowsCount.incrementAndGet();\n\n            computeUserAgentIEWindowsVersion(userAgent);\n\n            if (userAgent.contains(\"Windows Phone\")) {\n                deviceWindowsPhoneCount.incrementAndGet();\n            }\n\n            return;\n        }\n\n        boolean isWindows = false;\n        boolean isMac = false;\n        boolean isIpad = false;\n        boolean isIPhone = false;\n        boolean isLinux = false;\n        boolean isX11 = false;\n        boolean isBSD = false;\n\n        if (userAgent.startsWith(\"Windows\", 13)) {\n            isWindows = true;\n        } else if (userAgent.startsWith(\"Macintosh\", 13)) {\n            isMac = true;\n        } else if (userAgent.startsWith(\"iPad\", 13)) {\n            isIpad = true;\n            isMac = true;\n        } else if (userAgent.startsWith(\"iPhone\", 13)) {\n            isIPhone = true;\n            isMac = true;\n        } else if (userAgent.startsWith(\"Linux\", 13)) {\n            isLinux = true;\n        } else if (userAgent.startsWith(\"X11\", 13)) {\n            isX11 = true;\n        }\n\n        boolean isAndroid = false;\n\n        if (isWindows) {\n            isWindows = true;\n\n            osWindowsCount.incrementAndGet();\n\n            if (userAgent.contains(\"Windows Phone\")) {\n                deviceWindowsPhoneCount.incrementAndGet();\n            }\n        } else if (isMac) {\n            isMac = true;\n            osMacOSXCount.incrementAndGet();\n            if (isIpad && userAgent.contains(\"iPad\")) {\n                deviceIpadCount.incrementAndGet();\n            } else if (isIPhone || userAgent.contains(\"iPhone\")) {\n                deviceIphoneCount.incrementAndGet();\n            }\n        } else if (isLinux) {\n            osLinuxCount.incrementAndGet();\n            isAndroid = computeUserAgentAndroid(userAgent);\n        } else if (userAgent.contains(\"Symbian\")) {\n            osSymbianCount.incrementAndGet();\n        } else if (userAgent.contains(\"Ubuntu\")) {\n            osLinuxCount.incrementAndGet();\n            osLinuxUbuntuCount.incrementAndGet();\n            isLinux = true;\n        }\n\n        if (isX11) {\n            if (userAgent.contains(\"OpenBSD\")) {\n                osOpenBSDCount.incrementAndGet();\n                isBSD = true;\n            } else if (userAgent.contains(\"FreeBSD\")) {\n                osFreeBSDCount.incrementAndGet();\n                isBSD = true;\n            } else if ((!isLinux) && userAgent.contains(\"Linux\")) {\n                osLinuxCount.incrementAndGet();\n                isLinux = true;\n            }\n        }\n\n        boolean isOpera = userAgent.startsWith(\"Opera\");\n\n        if (isOpera) {\n            if (userAgent.contains(\"Windows\")) {\n                osWindowsCount.incrementAndGet();\n            } else if (userAgent.contains(\"Linux\")) {\n                osWindowsCount.incrementAndGet();\n            } else if (userAgent.contains(\"Macintosh\")) {\n                osMacOSXCount.incrementAndGet();\n            }\n            browserOperaCount.incrementAndGet();\n            return;\n        }\n\n        if (isWindows) {\n            computeUserAgentFirefoxWindowsVersion(userAgent);\n        }\n\n        if (isWindows || isMac || isLinux || isBSD) {\n            if (userAgent.contains(\"Chrome\")) {\n                browserChromeCount.incrementAndGet();\n                return;\n            }\n\n            if ((!isAndroid) && userAgent.contains(\"Safari\")) {\n                browserSafariCount.incrementAndGet();\n                return;\n            }\n\n            if (userAgent.contains(\"Firefox\")) {\n                browserFirefoxCount.incrementAndGet();\n                return;\n            }\n        }\n\n        if (userAgent.startsWith(\"User-Agent: \")) {\n            String rest = userAgent.substring(\"User-Agent: \".length());\n            computeUserAgent(rest);\n        }\n\n        boolean isJava = userAgent.startsWith(\"Java\");\n\n        if (isJava) {\n            botCount.incrementAndGet();\n        }\n\n        if (userAgent.startsWith(\"msnbot\")) {\n            botCount.incrementAndGet();\n            botMsnCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Sosospider+\")) {\n            botCount.incrementAndGet();\n            botSosoCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Sogou\")) {\n            botCount.incrementAndGet();\n            botSogouCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"HuaweiSymantecSpider\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Yeti/\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"mahonie\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"findlinks\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Updownerbot\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"DoCoMo/\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Crawl\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"SkimBot\")) {\n            botCount.incrementAndGet();\n\n        } else if (userAgent.startsWith(\"YoudaoBot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n            botYoudaoCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"bingbot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n            botBingCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Googlebot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n            botGoogleCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Baiduspider\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n            botBaiduCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"MJ12bot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n            botBaiduCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Mail.RU/\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Yahoo!\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n            botYahooCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"KaloogaBot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"YandexBot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Ezooms/\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Exabot/\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"AhrefsBot/\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"YodaoBot/\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"BeetleBot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"archive.org_bot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"aiHitBot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"EventGuruBot\", MOZILLA_COMPATIBLE_OFFSET)) {\n            botCount.incrementAndGet();\n\n        } else if (userAgent.equals(\"Mozilla/5.0 ()\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.equals(\"\\\"Mozilla/5.0\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.equals(\"Mozilla\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.equals(\"-\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.contains(\"Spider\") || userAgent.contains(\"spider\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.contains(\"crawl\") || userAgent.contains(\"Crawl\")) {\n            botCount.incrementAndGet();\n        } else if (userAgent.contains(\"Bot\") || userAgent.contains(\"bot\")) {\n            botCount.incrementAndGet();\n        }\n\n        // Mozilla/5.0 ()\n        // Mozilla/5.0 (compatible; Mail.RU/2.0)\n        // Mozilla/5.0 (compatible; bingbot/2.0;\n        // YoudaoBot\n\n    }\n\n    private void computeUserAgentFirefoxWindowsVersion(String userAgent) {\n        if (userAgent.startsWith(\"Windows NT 5.1\", 13)) {\n            osWindowsXPCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows NT 5.1\", 25)) {\n            osWindowsXPCount.incrementAndGet();\n\n        } else if (userAgent.startsWith(\"Windows NT 6.0\", 13)) {\n            osWindowsVistaCount.incrementAndGet();\n\n        } else if (userAgent.startsWith(\"Windows NT 6.1\", 13)) {\n            osWindows7Count.incrementAndGet();\n\n        } else if (userAgent.startsWith(\"Windows NT 6.2\", 13)) {\n            osWindows8Count.incrementAndGet();\n\n        } else if (userAgent.startsWith(\"Windows NT 5.0\", 13)) {\n            osWindows2000Count.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows NT 5.0\", 25)) {\n            osWindows2000Count.incrementAndGet();\n        }\n    }\n\n    private void computeUserAgentIEWindowsVersion(String userAgent) {\n        if (userAgent.startsWith(\"Windows NT 5.1\", 35)) {\n            osWindowsXPCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows NT 5.0\", 35)) {\n            osWindows2000Count.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows NT 5.0\", 36)) {\n            osWindows2000Count.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows NT 6.0\", 35)) {\n            osWindowsVistaCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows NT 6.1\", 35)) {\n            osWindows7Count.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows NT 6.2\", 36)) {\n            osWindows8Count.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows 98\", 36)) {\n            osWindows98Count.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows 98\", 35)) {\n            osWindows98Count.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows XP\", 35)) {\n            osWindowsXPCount.incrementAndGet();\n        } else if (userAgent.startsWith(\"Windows XP\", 34)) {\n            osWindowsXPCount.incrementAndGet();\n        }\n    }\n\n    private boolean computeUserAgentAndroid(String userAgent) {\n        boolean isAndroid = userAgent.startsWith(\"Android\", 23);\n        int toffset = 31;\n        if (!isAndroid) {\n            isAndroid = userAgent.startsWith(\"Android\", 20);\n            toffset = 28;\n        }\n\n        if (isAndroid) {\n            osAndroidCount.incrementAndGet();\n            deviceAndroidCount.incrementAndGet();\n\n            if (userAgent.startsWith(\"1.5\", toffset)) {\n                osAndroid15Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"1.6\", toffset)) {\n                osAndroid16Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"2.0\", toffset)) {\n                osAndroid20Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"2.1\", toffset)) {\n                osAndroid21Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"2.2\", toffset)) {\n                osAndroid22Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"2.3.3\", toffset)) {\n                osAndroid23Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"2.3.4\", toffset)) {\n                osAndroid23Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"3.0\", toffset)) {\n                osAndroid30Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"3.1\", toffset)) {\n                osAndroid31Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"3.2\", toffset)) {\n                osAndroid32Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"4.0\", toffset)) {\n                osAndroid40Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"4.1\", toffset)) {\n                osAndroid41Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"4.2\", toffset)) {\n                osAndroid42Count.incrementAndGet();\n            } else if (userAgent.startsWith(\"4.3\", toffset)) {\n                osAndroid43Count.incrementAndGet();\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    public long getOSMacOSXCount() {\n        return osMacOSXCount.get();\n    }\n\n    public long getOSWindowsCount() {\n        return osWindowsCount.get();\n    }\n\n    public long getOSLinuxCount() {\n        return osLinuxCount.get();\n    }\n\n    public long getOSSymbianCount() {\n        return osSymbianCount.get();\n    }\n\n    public long getOSFreeBSDCount() {\n        return osFreeBSDCount.get();\n    }\n\n    public long getOSOpenBSDCount() {\n        return osOpenBSDCount.get();\n    }\n\n    public long getOSAndroidCount() {\n        return osAndroidCount.get();\n    }\n\n    public long getOSWindows98Count() {\n        return osWindows98Count.get();\n    }\n\n    public long getOSWindowsXPCount() {\n        return osWindowsXPCount.get();\n    }\n\n    public long getOSWindows2000Count() {\n        return osWindows2000Count.get();\n    }\n\n    public long getOSWindowsVistaCount() {\n        return osWindowsVistaCount.get();\n    }\n\n    public long getOSWindows7Count() {\n        return osWindows7Count.get();\n    }\n\n    public long getOSWindows8Count() {\n        return osWindows8Count.get();\n    }\n\n    public long getOSAndroid15Count() {\n        return osAndroid15Count.get();\n    }\n\n    public long getOSAndroid16Count() {\n        return osAndroid16Count.get();\n    }\n\n    public long getOSAndroid20Count() {\n        return osAndroid20Count.get();\n    }\n\n    public long getOSAndroid21Count() {\n        return osAndroid21Count.get();\n    }\n\n    public long getOSAndroid22Count() {\n        return osAndroid22Count.get();\n    }\n\n    public long getOSAndroid23Count() {\n        return osAndroid23Count.get();\n    }\n\n    public long getOSAndroid30Count() {\n        return osAndroid30Count.get();\n    }\n\n    public long getOSAndroid31Count() {\n        return osAndroid31Count.get();\n    }\n\n    public long getOSAndroid32Count() {\n        return osAndroid32Count.get();\n    }\n\n    public long getOSAndroid40Count() {\n        return osAndroid40Count.get();\n    }\n\n    public long getOSAndroid41Count() {\n        return osAndroid41Count.get();\n    }\n\n    public long getOSAndroid42Count() {\n        return osAndroid42Count.get();\n    }\n\n    public long getOSAndroid43Count() {\n        return osAndroid43Count.get();\n    }\n\n    public long getOSLinuxUbuntuCount() {\n        return osLinuxUbuntuCount.get();\n    }\n\n    public long getBrowserIECount() {\n        return browserIECount.get();\n    }\n\n    public long getBrowserFirefoxCount() {\n        return browserFirefoxCount.get();\n    }\n\n    public long getBrowserChromeCount() {\n        return browserChromeCount.get();\n    }\n\n    public long getBrowserSafariCount() {\n        return browserSafariCount.get();\n    }\n\n    public long getBrowserOperaCount() {\n        return browserOperaCount.get();\n    }\n\n    public long getBrowserIE5Count() {\n        return browserIE5Count.get();\n    }\n\n    public long getBrowserIE6Count() {\n        return browserIE6Count.get();\n    }\n\n    public long getBrowserIE7Count() {\n        return browserIE7Count.get();\n    }\n\n    public long getBrowserIE8Count() {\n        return browserIE8Count.get();\n    }\n\n    public long getBrowserIE9Count() {\n        return browserIE9Count.get();\n    }\n\n    public long getBrowserIE10Count() {\n        return browserIE10Count.get();\n    }\n\n    public long getBrowser360SECount() {\n        return browser360SECount.get();\n    }\n\n    public long getDeviceAndroidCount() {\n        return deviceAndroidCount.get();\n    }\n\n    public long getDeviceIpadCount() {\n        return deviceIpadCount.get();\n    }\n\n    public long getDeviceIphoneCount() {\n        return deviceIphoneCount.get();\n    }\n\n    public long getDeviceWindowsPhoneCount() {\n        return deviceWindowsPhoneCount.get();\n    }\n\n    public long getBotCount() {\n        return botCount.get();\n    }\n\n    public long getBotBaiduCount() {\n        return botBaiduCount.get();\n    }\n\n    public long getBotYoudaoCount() {\n        return botYoudaoCount.get();\n    }\n\n    public long getBotGoogleCount() {\n        return botGoogleCount.get();\n    }\n\n    public long getBotMsnCount() {\n        return botMsnCount.get();\n    }\n\n    public long getBotBingCount() {\n        return botBingCount.get();\n    }\n\n    public long getBotSosoCount() {\n        return botSosoCount.get();\n    }\n\n    public long getBotSogouCount() {\n        return botSogouCount.get();\n    }\n\n    public long getBotYahooCount() {\n        return botYahooCount.get();\n    }\n\n    public WebAppStatValue getStatValue(boolean reset) {\n        WebAppStatValue val = new WebAppStatValue();\n        val.setContextPath(contextPath);\n\n        val.setRunningCount(getRunningCount());\n        val.concurrentMax = get(concurrentMax, reset);\n        val.requestCount = get(requestCount, reset);\n        val.sessionCount = get(sessionCount, reset);\n        val.jdbcFetchRowCount = get(jdbcFetchRowCount, reset);\n        val.jdbcUpdateCount = get(jdbcUpdateCount, reset);\n        val.jdbcExecuteCount = get(jdbcExecuteCount, reset);\n        val.jdbcExecuteTimeNano = get(jdbcExecuteTimeNano, reset);\n        val.jdbcCommitCount = get(jdbcCommitCount, reset);\n        val.jdbcRollbackCount = get(jdbcRollbackCount, reset);\n        if (val.sessionCount < 1) {\n            return val;\n        }\n\n        val.osMacOSXCount = get(osMacOSXCount, reset);\n        val.osWindowsCount = get(osWindowsCount, reset);\n        val.osLinuxCount = get(osLinuxCount, reset);\n        val.osSymbianCount = get(osSymbianCount, reset);\n        val.osFreeBSDCount = get(osFreeBSDCount, reset);\n        val.osOpenBSDCount = get(osOpenBSDCount, reset);\n        val.osAndroidCount = get(osAndroidCount, reset);\n\n        val.osWindows98Count = get(osWindows98Count, reset);\n        val.osWindowsXPCount = get(osWindowsXPCount, reset);\n        val.osWindows2000Count = get(osWindows2000Count, reset);\n        val.osWindowsVistaCount = get(osWindowsVistaCount, reset);\n        val.osWindows7Count = get(osWindows7Count, reset);\n        val.osWindows8Count = get(osWindows8Count, reset);\n\n        val.osAndroid15Count = get(osAndroid15Count, reset);\n        val.osAndroid16Count = get(osAndroid16Count, reset);\n        val.osAndroid20Count = get(osAndroid20Count, reset);\n        val.osAndroid21Count = get(osAndroid21Count, reset);\n        val.osAndroid22Count = get(osAndroid22Count, reset);\n        val.osAndroid23Count = get(osAndroid23Count, reset);\n        val.osAndroid30Count = get(osAndroid30Count, reset);\n        val.osAndroid31Count = get(osAndroid31Count, reset);\n        val.osAndroid32Count = get(osAndroid32Count, reset);\n        val.osAndroid40Count = get(osAndroid40Count, reset);\n        val.osAndroid41Count = get(osAndroid41Count, reset);\n        val.osAndroid42Count = get(osAndroid42Count, reset);\n        val.osAndroid43Count = get(osAndroid43Count, reset);\n\n        val.osLinuxUbuntuCount = get(osLinuxUbuntuCount, reset);\n\n        val.browserIECount = get(browserIECount, reset);\n        val.browserFirefoxCount = get(browserFirefoxCount, reset);\n        val.browserChromeCount = get(browserChromeCount, reset);\n        val.browserSafariCount = get(browserSafariCount, reset);\n        val.browserOperaCount = get(browserOperaCount, reset);\n\n        val.browserIE5Count = get(browserIE5Count, reset);\n        val.browserIE6Count = get(browserIE6Count, reset);\n        val.browserIE7Count = get(browserIE7Count, reset);\n        val.browserIE8Count = get(browserIE8Count, reset);\n        val.browserIE9Count = get(browserIE9Count, reset);\n        val.browserIE10Count = get(browserIE10Count, reset);\n\n        val.browser360SECount = get(browser360SECount, reset);\n        val.deviceAndroidCount = get(deviceAndroidCount, reset);\n        val.deviceIpadCount = get(deviceIpadCount, reset);\n        val.deviceIphoneCount = get(deviceIphoneCount, reset);\n        val.deviceWindowsPhoneCount = get(deviceWindowsPhoneCount, reset);\n\n        val.botCount = get(botCount, reset);\n        val.botBaiduCount = get(botBaiduCount, reset);\n        val.botYoudaoCount = get(botYoudaoCount, reset);\n        val.botGoogleCount = get(botGoogleCount, reset);\n        val.botMsnCount = get(botMsnCount, reset);\n        val.botBingCount = get(botBingCount, reset);\n        val.botSosoCount = get(botSosoCount, reset);\n        val.botSogouCount = get(botSogouCount, reset);\n        val.botYahooCount = get(botYahooCount, reset);\n\n        return val;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebAppStatManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.util.StringUtils;\n\nimport java.util.*;\nimport java.util.concurrent.CopyOnWriteArraySet;\n\npublic class WebAppStatManager {\n    public static final String SYS_PROP_INSTANCES = \"druid.web.webAppStat\";\n\n    private static final WebAppStatManager instance = new WebAppStatManager();\n\n    private Set<Object> webAppStatSet;\n\n    public static WebAppStatManager getInstance() {\n        return instance;\n    }\n\n    public synchronized WebAppStat getWebAppStat(String contextPath) {\n        Set<Object> stats = getWebAppStatSet();\n        for (Object item : stats) {\n            if (item instanceof WebAppStat) {\n                WebAppStat stat = (WebAppStat) item;\n                if (StringUtils.equals(stat.getContextPath(), contextPath)) {\n                    return stat;\n                }\n            }\n        }\n\n        WebAppStat stat = new WebAppStat(contextPath);\n        this.addWebAppStatSet(stat);\n        return stat;\n    }\n\n    public Set<Object> getWebAppStatSet() {\n        if (webAppStatSet == null) {\n            if (DruidDataSourceStatManager.isRegisterToSystemProperty()) {\n                webAppStatSet = getWebAppStatSet0();\n            } else {\n                webAppStatSet = new CopyOnWriteArraySet<Object>();\n            }\n        }\n\n        return webAppStatSet;\n    }\n\n    public List<Map<String, Object>> getWebAppStatData() {\n        Set<Object> stats = getWebAppStatSet();\n\n        List<Map<String, Object>> statDataList = new ArrayList<Map<String, Object>>(stats.size());\n\n        for (Object stat : stats) {\n            Map<String, Object> statData = WebAppStatUtils.getStatData(stat);\n            statDataList.add(statData);\n        }\n\n        return statDataList;\n    }\n\n    public List<Map<String, Object>> getURIStatData() {\n        Set<Object> stats = getWebAppStatSet();\n\n        List<Map<String, Object>> allAppUriStatDataList = new ArrayList<Map<String, Object>>();\n\n        for (Object stat : stats) {\n            List<Map<String, Object>> uriStatDataList = WebAppStatUtils.getURIStatDataList(stat);\n            allAppUriStatDataList.addAll(uriStatDataList);\n        }\n\n        return allAppUriStatDataList;\n    }\n\n    public List<Map<String, Object>> getSessionStatData() {\n        Set<Object> stats = getWebAppStatSet();\n\n        List<Map<String, Object>> allAppUriStatDataList = new ArrayList<Map<String, Object>>();\n\n        for (Object stat : stats) {\n            List<Map<String, Object>> uriStatDataList = WebAppStatUtils.getSessionStatDataList(stat);\n            allAppUriStatDataList.addAll(uriStatDataList);\n        }\n\n        return allAppUriStatDataList;\n    }\n\n    public Map<String, Object> getSessionStat(String sessionId) {\n        Set<Object> stats = getWebAppStatSet();\n\n        for (Object stat : stats) {\n            Map<String, Object> statData = WebAppStatUtils.getSessionStatData(stat, sessionId);\n            if (statData != null) {\n                return statData;\n            }\n        }\n\n        return null;\n    }\n\n    public Map<String, Object> getURIStatData(String uri) {\n        Set<Object> stats = getWebAppStatSet();\n\n        for (Object stat : stats) {\n            Map<String, Object> statData = WebAppStatUtils.getURIStatData(stat, uri);\n            if (statData != null) {\n                return statData;\n            }\n        }\n\n        return null;\n    }\n\n    public void addWebAppStatSet(Object webAppStat) {\n        getWebAppStatSet().add(webAppStat);\n    }\n\n    public boolean remove(Object webAppStat) {\n        return getWebAppStatSet().remove(webAppStat);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static Set<Object> getWebAppStatSet0() {\n        Properties properties = System.getProperties();\n        Set<Object> webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);\n\n        if (webAppStats == null) {\n            synchronized (properties) {\n                webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);\n\n                if (webAppStats == null) {\n                    webAppStats = new CopyOnWriteArraySet<Object>();\n                    properties.put(SYS_PROP_INSTANCES, webAppStats);\n                }\n            }\n        }\n\n        return webAppStats;\n    }\n\n    public void resetStat() {\n        Set<Object> stats = getWebAppStatSet();\n\n        for (Object stat : stats) {\n            WebAppStatUtils.reset(stat);\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebAppStatUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.lang.reflect.Method;\nimport java.util.List;\nimport java.util.Map;\n\npublic class WebAppStatUtils {\n    private static final Log LOG = LogFactory.getLog(WebAppStatUtils.class);\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<String, Object> getStatData(Object webStat) {\n        if (webStat.getClass() == WebAppStat.class) {\n            return ((WebAppStat) webStat).getStatData();\n        }\n\n        try {\n            Method method = webStat.getClass().getMethod(\"getStatData\");\n            Object obj = method.invoke(webStat);\n            return (Map<String, Object>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getStatData error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static List<Map<String, Object>> getURIStatDataList(Object webStat) {\n        if (webStat.getClass() == WebAppStat.class) {\n            return ((WebAppStat) webStat).getURIStatDataList();\n        }\n\n        try {\n            Method method = webStat.getClass().getMethod(\"getURIStatDataList\");\n            Object obj = method.invoke(webStat);\n            return (List<Map<String, Object>>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getURIStatDataList error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static List<Map<String, Object>> getSessionStatDataList(Object webStat) {\n        if (webStat.getClass() == WebAppStat.class) {\n            return ((WebAppStat) webStat).getSessionStatDataList();\n        }\n\n        try {\n            Method method = webStat.getClass().getMethod(\"getSessionStatDataList\");\n            Object obj = method.invoke(webStat);\n            return (List<Map<String, Object>>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getSessionStatDataList error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<String, Object> getSessionStatData(Object webStat, String sessionId) {\n        if (webStat.getClass() == WebAppStat.class) {\n            return ((WebAppStat) webStat).getSessionStatData(sessionId);\n        }\n\n        try {\n            Method method = webStat.getClass().getMethod(\"getSessionStatData\", String.class);\n            Object obj = method.invoke(webStat, sessionId);\n            return (Map<String, Object>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getSessionStatData error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<String, Object> getURIStatData(Object webStat, String uri) {\n        if (webStat.getClass() == WebAppStat.class) {\n            return ((WebAppStat) webStat).getURIStatData(uri);\n        }\n\n        try {\n            Method method = webStat.getClass().getMethod(\"getURIStatData\", String.class);\n            Object obj = method.invoke(webStat, uri);\n            return (Map<String, Object>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getURIStatData error\", e);\n            return null;\n        }\n    }\n\n    public static void reset(Object webStat) {\n        if (webStat.getClass() == WebAppStat.class) {\n            ((WebAppStat) webStat).reset();\n            return;\n        }\n\n        try {\n            Method method = webStat.getClass().getMethod(\"reset\");\n            method.invoke(webStat);\n        } catch (Exception e) {\n            LOG.error(\"reset error\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebAppStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n@MTable(name = \"druid_webapp\")\npublic class WebAppStatValue {\n    @MField(groupBy = true, aggregate = AggregateType.None)\n    String contextPath;\n\n    @MField(aggregate = AggregateType.Last)\n    int runningCount;\n\n    @MField(aggregate = AggregateType.Max)\n    int concurrentMax;\n\n    @MField(aggregate = AggregateType.Sum)\n    long requestCount;\n\n    @MField(aggregate = AggregateType.Last)\n    long sessionCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long jdbcFetchRowCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long jdbcUpdateCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long jdbcExecuteCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long jdbcExecuteTimeNano;\n\n    @MField(aggregate = AggregateType.Sum)\n    long jdbcCommitCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long jdbcRollbackCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osMacOSXCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osWindowsCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osLinuxCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osSymbianCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osFreeBSDCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osOpenBSDCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroidCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osWindows98Count;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osWindowsXPCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osWindows2000Count;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osWindowsVistaCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osWindows7Count;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osWindows8Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid15Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid16Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid20Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid21Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid22Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid23Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid30Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid31Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid32Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid40Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid41Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid42Count;\n    @MField(aggregate = AggregateType.Sum)\n    long osAndroid43Count;\n\n    @MField(aggregate = AggregateType.Sum)\n    long osLinuxUbuntuCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long browserIECount;\n    @MField(aggregate = AggregateType.Sum)\n    long browserFirefoxCount;\n    @MField(aggregate = AggregateType.Sum)\n    long browserChromeCount;\n    @MField(aggregate = AggregateType.Sum)\n    long browserSafariCount;\n    @MField(aggregate = AggregateType.Sum)\n    long browserOperaCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long browserIE5Count;\n    @MField(aggregate = AggregateType.Sum)\n    long browserIE6Count;\n    @MField(aggregate = AggregateType.Sum)\n    long browserIE7Count;\n    @MField(aggregate = AggregateType.Sum)\n    long browserIE8Count;\n    @MField(aggregate = AggregateType.Sum)\n    long browserIE9Count;\n    @MField(aggregate = AggregateType.Sum)\n    long browserIE10Count;\n\n    @MField(aggregate = AggregateType.Sum)\n    long browser360SECount;\n    @MField(aggregate = AggregateType.Sum)\n    long deviceAndroidCount;\n    @MField(aggregate = AggregateType.Sum)\n    long deviceIpadCount;\n    @MField(aggregate = AggregateType.Sum)\n    long deviceIphoneCount;\n    @MField(aggregate = AggregateType.Sum)\n    long deviceWindowsPhoneCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    long botCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botBaiduCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botYoudaoCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botGoogleCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botMsnCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botBingCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botSosoCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botSogouCount;\n    @MField(aggregate = AggregateType.Sum)\n    long botYahooCount;\n\n    public String getContextPath() {\n        return contextPath;\n    }\n\n    public void setContextPath(String contextPath) {\n        this.contextPath = contextPath;\n    }\n\n    public int getRunningCount() {\n        return runningCount;\n    }\n\n    public void setRunningCount(int runningCount) {\n        this.runningCount = runningCount;\n    }\n\n    public int getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public void setConcurrentMax(int concurrentMax) {\n        this.concurrentMax = concurrentMax;\n    }\n\n    public long getRequestCount() {\n        return requestCount;\n    }\n\n    public void setRequestCount(long requestCount) {\n        this.requestCount = requestCount;\n    }\n\n    public long getSessionCount() {\n        return sessionCount;\n    }\n\n    public void setSessionCount(long sessionCount) {\n        this.sessionCount = sessionCount;\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount;\n    }\n\n    public void setJdbcFetchRowCount(long jdbcFetchRowCount) {\n        this.jdbcFetchRowCount = jdbcFetchRowCount;\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount;\n    }\n\n    public void setJdbcUpdateCount(long jdbcUpdateCount) {\n        this.jdbcUpdateCount = jdbcUpdateCount;\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount;\n    }\n\n    public void setJdbcExecuteCount(long jdbcExecuteCount) {\n        this.jdbcExecuteCount = jdbcExecuteCount;\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano;\n    }\n\n    public void setJdbcExecuteTimeNano(long jdbcExecuteTimeNano) {\n        this.jdbcExecuteTimeNano = jdbcExecuteTimeNano;\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount;\n    }\n\n    public void setJdbcCommitCount(long jdbcCommitCount) {\n        this.jdbcCommitCount = jdbcCommitCount;\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount;\n    }\n\n    public void setJdbcRollbackCount(long jdbcRollbackCount) {\n        this.jdbcRollbackCount = jdbcRollbackCount;\n    }\n\n    public long getOsMacOSXCount() {\n        return osMacOSXCount;\n    }\n\n    public void setOsMacOSXCount(long osMacOSXCount) {\n        this.osMacOSXCount = osMacOSXCount;\n    }\n\n    public long getOsWindowsCount() {\n        return osWindowsCount;\n    }\n\n    public void setOsWindowsCount(long osWindowsCount) {\n        this.osWindowsCount = osWindowsCount;\n    }\n\n    public long getOsLinuxCount() {\n        return osLinuxCount;\n    }\n\n    public void setOsLinuxCount(long osLinuxCount) {\n        this.osLinuxCount = osLinuxCount;\n    }\n\n    public long getOsSymbianCount() {\n        return osSymbianCount;\n    }\n\n    public void setOsSymbianCount(long osSymbianCount) {\n        this.osSymbianCount = osSymbianCount;\n    }\n\n    public long getOsFreeBSDCount() {\n        return osFreeBSDCount;\n    }\n\n    public void setOsFreeBSDCount(long osFreeBSDCount) {\n        this.osFreeBSDCount = osFreeBSDCount;\n    }\n\n    public long getOsOpenBSDCount() {\n        return osOpenBSDCount;\n    }\n\n    public void setOsOpenBSDCount(long osOpenBSDCount) {\n        this.osOpenBSDCount = osOpenBSDCount;\n    }\n\n    public long getOsAndroidCount() {\n        return osAndroidCount;\n    }\n\n    public void setOsAndroidCount(long osAndroidCount) {\n        this.osAndroidCount = osAndroidCount;\n    }\n\n    public long getOsWindows98Count() {\n        return osWindows98Count;\n    }\n\n    public void setOsWindows98Count(long osWindows98Count) {\n        this.osWindows98Count = osWindows98Count;\n    }\n\n    public long getOsWindowsXPCount() {\n        return osWindowsXPCount;\n    }\n\n    public void setOsWindowsXPCount(long osWindowsXPCount) {\n        this.osWindowsXPCount = osWindowsXPCount;\n    }\n\n    public long getOsWindows2000Count() {\n        return osWindows2000Count;\n    }\n\n    public void setOsWindows2000Count(long osWindows2000Count) {\n        this.osWindows2000Count = osWindows2000Count;\n    }\n\n    public long getOsWindowsVistaCount() {\n        return osWindowsVistaCount;\n    }\n\n    public void setOsWindowsVistaCount(long osWindowsVistaCount) {\n        this.osWindowsVistaCount = osWindowsVistaCount;\n    }\n\n    public long getOsWindows7Count() {\n        return osWindows7Count;\n    }\n\n    public void setOsWindows7Count(long osWindows7Count) {\n        this.osWindows7Count = osWindows7Count;\n    }\n\n    public long getOsWindows8Count() {\n        return osWindows8Count;\n    }\n\n    public void setOsWindows8Count(long osWindows8Count) {\n        this.osWindows8Count = osWindows8Count;\n    }\n\n    public long getOsAndroid15Count() {\n        return osAndroid15Count;\n    }\n\n    public void setOsAndroid15Count(long osAndroid15Count) {\n        this.osAndroid15Count = osAndroid15Count;\n    }\n\n    public long getOsAndroid16Count() {\n        return osAndroid16Count;\n    }\n\n    public void setOsAndroid16Count(long osAndroid16Count) {\n        this.osAndroid16Count = osAndroid16Count;\n    }\n\n    public long getOsAndroid20Count() {\n        return osAndroid20Count;\n    }\n\n    public void setOsAndroid20Count(long osAndroid20Count) {\n        this.osAndroid20Count = osAndroid20Count;\n    }\n\n    public long getOsAndroid21Count() {\n        return osAndroid21Count;\n    }\n\n    public void setOsAndroid21Count(long osAndroid21Count) {\n        this.osAndroid21Count = osAndroid21Count;\n    }\n\n    public long getOsAndroid22Count() {\n        return osAndroid22Count;\n    }\n\n    public void setOsAndroid22Count(long osAndroid22Count) {\n        this.osAndroid22Count = osAndroid22Count;\n    }\n\n    public long getOsAndroid23Count() {\n        return osAndroid23Count;\n    }\n\n    public void setOsAndroid23Count(long osAndroid23Count) {\n        this.osAndroid23Count = osAndroid23Count;\n    }\n\n    public long getOsAndroid30Count() {\n        return osAndroid30Count;\n    }\n\n    public void setOsAndroid30Count(long osAndroid30Count) {\n        this.osAndroid30Count = osAndroid30Count;\n    }\n\n    public long getOsAndroid31Count() {\n        return osAndroid31Count;\n    }\n\n    public void setOsAndroid31Count(long osAndroid31Count) {\n        this.osAndroid31Count = osAndroid31Count;\n    }\n\n    public long getOsAndroid32Count() {\n        return osAndroid32Count;\n    }\n\n    public void setOsAndroid32Count(long osAndroid32Count) {\n        this.osAndroid32Count = osAndroid32Count;\n    }\n\n    public long getOsAndroid40Count() {\n        return osAndroid40Count;\n    }\n\n    public void setOsAndroid40Count(long osAndroid40Count) {\n        this.osAndroid40Count = osAndroid40Count;\n    }\n\n    public long getOsAndroid41Count() {\n        return osAndroid41Count;\n    }\n\n    public void setOsAndroid41Count(long osAndroid41Count) {\n        this.osAndroid41Count = osAndroid41Count;\n    }\n\n    public long getOsAndroid42Count() {\n        return osAndroid42Count;\n    }\n\n    public void setOsAndroid42Count(long osAndroid42Count) {\n        this.osAndroid42Count = osAndroid42Count;\n    }\n\n    public long getOsAndroid43Count() {\n        return osAndroid43Count;\n    }\n\n    public void setOsAndroid43Count(long osAndroid43Count) {\n        this.osAndroid43Count = osAndroid43Count;\n    }\n\n    public long getOsLinuxUbuntuCount() {\n        return osLinuxUbuntuCount;\n    }\n\n    public void setOsLinuxUbuntuCount(long osLinuxUbuntuCount) {\n        this.osLinuxUbuntuCount = osLinuxUbuntuCount;\n    }\n\n    public long getBrowserIECount() {\n        return browserIECount;\n    }\n\n    public void setBrowserIECount(long browserIECount) {\n        this.browserIECount = browserIECount;\n    }\n\n    public long getBrowserFirefoxCount() {\n        return browserFirefoxCount;\n    }\n\n    public void setBrowserFirefoxCount(long browserFirefoxCount) {\n        this.browserFirefoxCount = browserFirefoxCount;\n    }\n\n    public long getBrowserChromeCount() {\n        return browserChromeCount;\n    }\n\n    public void setBrowserChromeCount(long browserChromeCount) {\n        this.browserChromeCount = browserChromeCount;\n    }\n\n    public long getBrowserSafariCount() {\n        return browserSafariCount;\n    }\n\n    public void setBrowserSafariCount(long browserSafariCount) {\n        this.browserSafariCount = browserSafariCount;\n    }\n\n    public long getBrowserOperaCount() {\n        return browserOperaCount;\n    }\n\n    public void setBrowserOperaCount(long browserOperaCount) {\n        this.browserOperaCount = browserOperaCount;\n    }\n\n    public long getBrowserIE5Count() {\n        return browserIE5Count;\n    }\n\n    public void setBrowserIE5Count(long browserIE5Count) {\n        this.browserIE5Count = browserIE5Count;\n    }\n\n    public long getBrowserIE6Count() {\n        return browserIE6Count;\n    }\n\n    public void setBrowserIE6Count(long browserIE6Count) {\n        this.browserIE6Count = browserIE6Count;\n    }\n\n    public long getBrowserIE7Count() {\n        return browserIE7Count;\n    }\n\n    public void setBrowserIE7Count(long browserIE7Count) {\n        this.browserIE7Count = browserIE7Count;\n    }\n\n    public long getBrowserIE8Count() {\n        return browserIE8Count;\n    }\n\n    public void setBrowserIE8Count(long browserIE8Count) {\n        this.browserIE8Count = browserIE8Count;\n    }\n\n    public long getBrowserIE9Count() {\n        return browserIE9Count;\n    }\n\n    public void setBrowserIE9Count(long browserIE9Count) {\n        this.browserIE9Count = browserIE9Count;\n    }\n\n    public long getBrowserIE10Count() {\n        return browserIE10Count;\n    }\n\n    public void setBrowserIE10Count(long browserIE10Count) {\n        this.browserIE10Count = browserIE10Count;\n    }\n\n    public long getBrowser360SECount() {\n        return browser360SECount;\n    }\n\n    public void setBrowser360SECount(long browser360seCount) {\n        browser360SECount = browser360seCount;\n    }\n\n    public long getDeviceAndroidCount() {\n        return deviceAndroidCount;\n    }\n\n    public void setDeviceAndroidCount(long deviceAndroidCount) {\n        this.deviceAndroidCount = deviceAndroidCount;\n    }\n\n    public long getDeviceIpadCount() {\n        return deviceIpadCount;\n    }\n\n    public void setDeviceIpadCount(long deviceIpadCount) {\n        this.deviceIpadCount = deviceIpadCount;\n    }\n\n    public long getDeviceIphoneCount() {\n        return deviceIphoneCount;\n    }\n\n    public void setDeviceIphoneCount(long deviceIphoneCount) {\n        this.deviceIphoneCount = deviceIphoneCount;\n    }\n\n    public long getDeviceWindowsPhoneCount() {\n        return deviceWindowsPhoneCount;\n    }\n\n    public void setDeviceWindowsPhoneCount(long deviceWindowsPhoneCount) {\n        this.deviceWindowsPhoneCount = deviceWindowsPhoneCount;\n    }\n\n    public long getBotCount() {\n        return botCount;\n    }\n\n    public void setBotCount(long botCount) {\n        this.botCount = botCount;\n    }\n\n    public long getBotBaiduCount() {\n        return botBaiduCount;\n    }\n\n    public void setBotBaiduCount(long botBaiduCount) {\n        this.botBaiduCount = botBaiduCount;\n    }\n\n    public long getBotYoudaoCount() {\n        return botYoudaoCount;\n    }\n\n    public void setBotYoudaoCount(long botYoudaoCount) {\n        this.botYoudaoCount = botYoudaoCount;\n    }\n\n    public long getBotGoogleCount() {\n        return botGoogleCount;\n    }\n\n    public void setBotGoogleCount(long botGoogleCount) {\n        this.botGoogleCount = botGoogleCount;\n    }\n\n    public long getBotMsnCount() {\n        return botMsnCount;\n    }\n\n    public void setBotMsnCount(long botMsnCount) {\n        this.botMsnCount = botMsnCount;\n    }\n\n    public long getBotBingCount() {\n        return botBingCount;\n    }\n\n    public void setBotBingCount(long botBingCount) {\n        this.botBingCount = botBingCount;\n    }\n\n    public long getBotSosoCount() {\n        return botSosoCount;\n    }\n\n    public void setBotSosoCount(long botSosoCount) {\n        this.botSosoCount = botSosoCount;\n    }\n\n    public long getBotSogouCount() {\n        return botSogouCount;\n    }\n\n    public void setBotSogouCount(long botSogouCount) {\n        this.botSogouCount = botSogouCount;\n    }\n\n    public long getBotYahooCount() {\n        return botYahooCount;\n    }\n\n    public void setBotYahooCount(long botYahooCount) {\n        this.botYahooCount = botYahooCount;\n    }\n\n    public long getJdbcExecuteTimeMillis() {\n        return getJdbcExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public Map<String, Object> getStatData() {\n        Map<String, Object> data = new LinkedHashMap<String, Object>();\n\n        data.put(\"ContextPath\", this.getContextPath());\n        data.put(\"RunningCount\", this.getRunningCount());\n        data.put(\"ConcurrentMax\", this.getConcurrentMax());\n        data.put(\"RequestCount\", this.getRequestCount());\n        final long sessions = this.getSessionCount();\n        data.put(\"SessionCount\", sessions);\n\n        data.put(\"JdbcCommitCount\", this.getJdbcCommitCount());\n        data.put(\"JdbcRollbackCount\", this.getJdbcRollbackCount());\n\n        data.put(\"JdbcExecuteCount\", this.getJdbcExecuteCount());\n        data.put(\"JdbcExecuteTimeMillis\", this.getJdbcExecuteTimeMillis());\n        data.put(\"JdbcFetchRowCount\", this.getJdbcFetchRowCount());\n        data.put(\"JdbcUpdateCount\", this.getJdbcUpdateCount());\n        if (sessions < 1) {\n            return data;\n        }\n        data.put(\"OSMacOSXCount\", this.getOsMacOSXCount());\n        data.put(\"OSWindowsCount\", this.getOsWindowsCount());\n        data.put(\"OSLinuxCount\", this.getOsLinuxCount());\n        data.put(\"OSSymbianCount\", this.getOsSymbianCount());\n        data.put(\"OSFreeBSDCount\", this.getOsFreeBSDCount());\n        data.put(\"OSOpenBSDCount\", this.getOsOpenBSDCount());\n        data.put(\"OSAndroidCount\", this.getOsAndroidCount());\n        data.put(\"OSWindows98Count\", this.getOsWindows98Count());\n        data.put(\"OSWindowsXPCount\", this.getOsWindowsXPCount());\n        data.put(\"OSWindows2000Count\", this.getOsWindows2000Count());\n        data.put(\"OSWindowsVistaCount\", this.getOsWindowsVistaCount());\n        data.put(\"OSWindows7Count\", this.getOsWindows7Count());\n        data.put(\"OSWindows8Count\", this.getOsWindows8Count());\n\n        data.put(\"OSAndroid15Count\", this.getOsAndroid15Count());\n        data.put(\"OSAndroid16Count\", this.getOsAndroid16Count());\n        data.put(\"OSAndroid20Count\", this.getOsAndroid20Count());\n        data.put(\"OSAndroid21Count\", this.getOsAndroid21Count());\n        data.put(\"OSAndroid22Count\", this.getOsAndroid22Count());\n        data.put(\"OSAndroid23Count\", this.getOsAndroid23Count());\n        data.put(\"OSAndroid30Count\", this.getOsAndroid30Count());\n        data.put(\"OSAndroid31Count\", this.getOsAndroid31Count());\n        data.put(\"OSAndroid32Count\", this.getOsAndroid32Count());\n        data.put(\"OSAndroid40Count\", this.getOsAndroid40Count());\n        data.put(\"OSAndroid41Count\", this.getOsAndroid41Count());\n        data.put(\"OSAndroid42Count\", this.getOsAndroid42Count());\n        data.put(\"OSAndroid43Count\", this.getOsAndroid43Count());\n        data.put(\"OSLinuxUbuntuCount\", this.getOsLinuxUbuntuCount());\n\n        data.put(\"BrowserIECount\", this.getBrowserIECount());\n        data.put(\"BrowserFirefoxCount\", this.getBrowserFirefoxCount());\n        data.put(\"BrowserChromeCount\", this.getBrowserChromeCount());\n        data.put(\"BrowserSafariCount\", this.getBrowserSafariCount());\n        data.put(\"BrowserOperaCount\", this.getBrowserOperaCount());\n\n        data.put(\"BrowserIE5Count\", this.getBrowserIE5Count());\n        data.put(\"BrowserIE6Count\", this.getBrowserIE6Count());\n        data.put(\"BrowserIE7Count\", this.getBrowserIE7Count());\n        data.put(\"BrowserIE8Count\", this.getBrowserIE8Count());\n        data.put(\"BrowserIE9Count\", this.getBrowserIE9Count());\n        data.put(\"BrowserIE10Count\", this.getBrowserIE10Count());\n\n        data.put(\"Browser360SECount\", this.getBrowser360SECount());\n        data.put(\"DeviceAndroidCount\", this.getDeviceAndroidCount());\n        data.put(\"DeviceIpadCount\", this.getDeviceIpadCount());\n        data.put(\"DeviceIphoneCount\", this.getDeviceIphoneCount());\n        data.put(\"DeviceWindowsPhoneCount\", this.getDeviceWindowsPhoneCount());\n\n        data.put(\"BotCount\", this.getBotCount());\n        data.put(\"BotBaiduCount\", this.getBotBaiduCount());\n        data.put(\"BotYoudaoCount\", this.getBotYoudaoCount());\n        data.put(\"BotGoogleCount\", this.getBotGoogleCount());\n        data.put(\"BotMsnCount\", this.getBotMsnCount());\n        data.put(\"BotBingCount\", this.getBotBingCount());\n        data.put(\"BotSosoCount\", this.getBotSosoCount());\n        data.put(\"BotSogouCount\", this.getBotSogouCount());\n        data.put(\"BotYahooCount\", this.getBotYahooCount());\n\n        return data;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebRequestStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\npublic class WebRequestStat {\n    private long startNano;\n    private long startMillis;\n    private long endNano;\n    private long jdbcCommitCount;\n    private long jdbcRollbackCount;\n    private long jdbcExecuteCount;\n    private long jdbcUpdateCount;\n    private long jdbcFetchRowCount;\n    private long jdbcExecuteNano;\n    private long jdbcExecuteErrorCount;\n\n    private long jdbcPoolConnectCount;\n    private long jdbcPoolCloseCount;\n\n    private long jdbcResultSetOpenCount;\n    private long jdbcResultSetCloseCount;\n\n    public WebRequestStat() {\n    }\n\n    public WebRequestStat(long startNano) {\n        this.startNano = startNano;\n    }\n\n    public WebRequestStat(long startNano, long startMillis) {\n        this.startNano = startNano;\n        this.startMillis = startMillis;\n    }\n\n    private static ThreadLocal<WebRequestStat> localRequestStat = new ThreadLocal<WebRequestStat>();\n\n    public static WebRequestStat current() {\n        return localRequestStat.get();\n    }\n\n    public static void set(WebRequestStat requestStat) {\n        localRequestStat.set(requestStat);\n    }\n\n    public long getStartNano() {\n        return startNano;\n    }\n\n    public void setStartNano(long startNano) {\n        this.startNano = startNano;\n    }\n\n    public long getStartMillis() {\n        return startMillis;\n    }\n\n    public void setStartMillis(long startMillis) {\n        this.startMillis = startMillis;\n    }\n\n    public long getEndNano() {\n        return endNano;\n    }\n\n    public void setEndNano(long endNano) {\n        this.endNano = endNano;\n    }\n\n    public void addJdbcUpdateCount(long count) {\n        this.jdbcUpdateCount += count;\n    }\n\n    public void addJdbcFetchRowCount(long count) {\n        this.jdbcFetchRowCount += count;\n    }\n\n    public void incrementJdbcExecuteCount() {\n        this.jdbcExecuteCount++;\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount;\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteNano;\n    }\n\n    public void addJdbcExecuteTimeNano(long nano) {\n        jdbcExecuteNano += nano;\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount;\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount;\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount;\n    }\n\n    public void incrementJdbcCommitCount() {\n        this.jdbcCommitCount++;\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount;\n    }\n\n    public void incrementJdbcRollbackCount() {\n        this.jdbcRollbackCount++;\n    }\n\n    public long getJdbcExecuteErrorCount() {\n        return jdbcExecuteErrorCount;\n    }\n\n    public void incrementJdbcExecuteErrorCount() {\n        jdbcExecuteErrorCount++;\n    }\n\n    public long getJdbcPoolConnectionOpenCount() {\n        return jdbcPoolConnectCount;\n    }\n\n    public void incrementJdbcPoolConnectCount() {\n        this.jdbcPoolConnectCount++;\n    }\n\n    public long getJdbcPoolConnectionCloseCount() {\n        return jdbcPoolCloseCount;\n    }\n\n    public void incrementJdbcPoolCloseCount() {\n        this.jdbcPoolCloseCount++;\n    }\n\n    public long getJdbcResultSetOpenCount() {\n        return jdbcResultSetOpenCount;\n    }\n\n    public void incrementJdbcResultSetOpenCount() {\n        this.jdbcResultSetOpenCount++;\n    }\n\n    public long getJdbcResultSetCloseCount() {\n        return jdbcResultSetCloseCount;\n    }\n\n    public void incrementJdbcResultSetCloseCount() {\n        this.jdbcResultSetCloseCount++;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebSessionStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class WebSessionStat {\n    private static final Log LOG = LogFactory.getLog(WebSessionStat.class);\n\n    private final String sessionId;\n\n    private volatile int runningCount;\n    private volatile int concurrentMax;\n    static final AtomicIntegerFieldUpdater<WebSessionStat> runningCountUpdater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"runningCount\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> concurrentMaxUpdater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"concurrentMax\");\n\n    private volatile long requestCount;\n    private volatile long requestErrorCount;\n    private volatile long requestTimeNano;\n\n    static final AtomicLongFieldUpdater<WebSessionStat> requestCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestCount\");\n    static final AtomicLongFieldUpdater<WebSessionStat> requestErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestErrorCount\");\n    static final AtomicLongFieldUpdater<WebSessionStat> requestTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestTimeNano\");\n\n    private volatile long jdbcFetchRowCount;\n    private volatile long jdbcUpdateCount;\n    private volatile long jdbcExecuteCount;\n    private volatile long jdbcExecuteTimeNano;\n    static final AtomicLongFieldUpdater<WebSessionStat> jdbcFetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"jdbcFetchRowCount\");\n    static final AtomicLongFieldUpdater<WebSessionStat> jdbcUpdateCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"jdbcUpdateCount\");\n    static final AtomicLongFieldUpdater<WebSessionStat> jdbcExecuteCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"jdbcExecuteCount\");\n    static final AtomicLongFieldUpdater<WebSessionStat> jdbcExecuteTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"jdbcExecuteTimeNano\");\n\n    private volatile long jdbcCommitCount;\n    private volatile long jdbcRollbackCount;\n    static final AtomicLongFieldUpdater<WebSessionStat> jdbcCommitCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"jdbcCommitCount\");\n    static final AtomicLongFieldUpdater<WebSessionStat> jdbcRollbackCountUpdater = AtomicLongFieldUpdater.newUpdater(WebSessionStat.class,\n            \"jdbcRollbackCount\");\n\n    private long createTimeMillis = -1L;\n    private volatile long lastAccessTimeMillis = -1L;\n\n    private String remoteAddresses;\n\n    private String principal;\n\n    private String userAgent;\n\n    private volatile int requestIntervalHistogram_0_1;\n    private volatile int requestIntervalHistogram_1_10;\n    private volatile int requestIntervalHistogram_10_100;\n    private volatile int requestIntervalHistogram_100_1000;\n    private volatile int requestIntervalHistogram_1000_10000;\n    private volatile int requestIntervalHistogram_10000_100000;\n    private volatile int requestIntervalHistogram_100000_1000000;\n    private volatile int requestIntervalHistogram_1000000_10000000;\n    private volatile int requestIntervalHistogram_10000000_more;\n\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_0_1_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_0_1\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_1_10_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_1_10\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_10_100_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_10_100\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_100_1000\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_1000_10000\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_10000_100000\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_100000_1000000\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_1000000_10000000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_1000000_10000000\");\n    static final AtomicIntegerFieldUpdater<WebSessionStat> requestIntervalHistogram_10000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(WebSessionStat.class,\n            \"requestIntervalHistogram_10000000_more\");\n\n    public WebSessionStat(String sessionId) {\n        super();\n        this.sessionId = sessionId;\n    }\n\n    public void reset() {\n        concurrentMaxUpdater.set(this, 0);\n        requestCountUpdater.set(this, 0);\n        requestErrorCountUpdater.set(this, 0);\n        requestTimeNanoUpdater.set(this, 0);\n\n        jdbcFetchRowCountUpdater.set(this, 0);\n        jdbcUpdateCountUpdater.set(this, 0);\n        jdbcExecuteCountUpdater.set(this, 0);\n        jdbcExecuteTimeNanoUpdater.set(this, 0);\n        jdbcCommitCountUpdater.set(this, 0);\n        jdbcRollbackCountUpdater.set(this, 0);\n\n        remoteAddresses = null;\n        principal = null;\n\n        requestIntervalHistogram_0_1_Updater.set(this, 0);\n        requestIntervalHistogram_1_10_Updater.set(this, 0);\n        requestIntervalHistogram_10_100_Updater.set(this, 0);\n        requestIntervalHistogram_100_1000_Updater.set(this, 0);\n        requestIntervalHistogram_1000_10000_Updater.set(this, 0);\n        requestIntervalHistogram_10000_100000_Updater.set(this, 0);\n        requestIntervalHistogram_100000_1000000_Updater.set(this, 0);\n        requestIntervalHistogram_1000000_10000000_Updater.set(this, 0);\n        requestIntervalHistogram_10000000_more_Updater.set(this, 0);\n    }\n\n    public String getUserAgent() {\n        return userAgent;\n    }\n\n    public void setUserAgent(String userAgent) {\n        this.userAgent = userAgent;\n    }\n\n    public String getSessionId() {\n        return sessionId;\n    }\n\n    public long getCreateTimeMillis() {\n        return createTimeMillis;\n    }\n\n    public String getPrincipal() {\n        return principal;\n    }\n\n    public void setPrincipal(String principal) {\n        this.principal = principal;\n    }\n\n    public void setCreateTimeMillis(long createTimeMillis) {\n        this.createTimeMillis = createTimeMillis;\n    }\n\n    public long getLastAccessTimeMillis() {\n        return lastAccessTimeMillis;\n    }\n\n    public String getRemoteAddress() {\n        return remoteAddresses;\n    }\n\n    public void setLastAccessTimeMillis(long lastAccessTimeMillis) {\n        if (this.lastAccessTimeMillis > 0) {\n            long interval = lastAccessTimeMillis - this.lastAccessTimeMillis;\n            requestIntervalHistogramRecord(interval);\n        }\n        this.lastAccessTimeMillis = lastAccessTimeMillis;\n    }\n\n    private void requestIntervalHistogramRecord(long nanoSpan) {\n        long millis = nanoSpan / 1000 / 1000;\n\n        if (millis < 1) {\n            requestIntervalHistogram_0_1_Updater.incrementAndGet(this);\n        } else if (millis < 10) {\n            requestIntervalHistogram_1_10_Updater.incrementAndGet(this);\n        } else if (millis < 100) {\n            requestIntervalHistogram_10_100_Updater.incrementAndGet(this);\n        } else if (millis < 1000) {\n            requestIntervalHistogram_100_1000_Updater.incrementAndGet(this);\n        } else if (millis < 10000) {\n            requestIntervalHistogram_1000_10000_Updater.incrementAndGet(this);\n        } else if (millis < 100000) {\n            requestIntervalHistogram_10000_100000_Updater.incrementAndGet(this);\n        } else if (millis < 1000000) {\n            requestIntervalHistogram_100000_1000000_Updater.incrementAndGet(this);\n        } else if (millis < 10000000) {\n            requestIntervalHistogram_1000000_10000000_Updater.incrementAndGet(this);\n        } else {\n            requestIntervalHistogram_10000000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public void beforeInvoke() {\n        int running = runningCountUpdater.incrementAndGet(this);\n\n        for (; ; ) {\n            int max = concurrentMaxUpdater.get(this);\n            if (running > max) {\n                if (concurrentMaxUpdater.compareAndSet(this, max, running)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        incrementRequestCount();\n\n        WebRequestStat requestStat = WebRequestStat.current();\n        if (requestStat != null) {\n            this.setLastAccessTimeMillis(requestStat.getStartMillis());\n        }\n    }\n\n    public void incrementRequestCount() {\n        requestCountUpdater.incrementAndGet(this);\n    }\n\n    public void afterInvoke(Throwable error, long nanos) {\n        runningCountUpdater.decrementAndGet(this);\n        reacord(nanos);\n    }\n\n    public void reacord(long nanos) {\n        requestTimeNanoUpdater.addAndGet(this, nanos);\n\n        WebRequestStat requestStat = WebRequestStat.current();\n        if (requestStat != null) {\n            this.addJdbcExecuteCount(requestStat.getJdbcExecuteCount());\n            this.addJdbcFetchRowCount(requestStat.getJdbcFetchRowCount());\n            this.addJdbcUpdateCount(requestStat.getJdbcUpdateCount());\n            this.addJdbcCommitCount(requestStat.getJdbcCommitCount());\n            this.addJdbcRollbackCount(requestStat.getJdbcRollbackCount());\n            this.addJdbcExecuteTimeNano(requestStat.getJdbcExecuteTimeNano());\n        }\n    }\n\n    public void addRemoteAddress(String ip) {\n        if (ip == null || ip.length() < 7) {\n            return;\n        }\n        if (remoteAddresses == null) {\n            this.remoteAddresses = ip;\n            return;\n        }\n        //判断ip是否已经存在需要考虑几种情况\n        //只有一个ip的情况\n        if (remoteAddresses.equals(ip)) {\n            return;\n        }\n        //是第一个ip的情况\n        if (remoteAddresses.startsWith(ip + ';')) {\n            return;\n        }\n        String addedIp = ';' + ip;\n        //是最后一个ip的情况\n        if (remoteAddresses.endsWith(addedIp)) {\n            return;\n        }\n        //ip已经添加在中间的场景\n        if (remoteAddresses.contains(';' + ip + ';')) {\n            return;\n        }\n        if (remoteAddresses.length() > 256) {\n            return;\n        }\n\n        remoteAddresses += addedIp;\n    }\n\n    public int getRunningCount() {\n        return this.runningCount;\n    }\n\n    public long getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public long getRequestCount() {\n        return requestCount;\n    }\n\n    public long getRequestErrorCount() {\n        return requestErrorCount;\n    }\n\n    public long getRequestTimeNano() {\n        return requestTimeNano;\n    }\n\n    public void addJdbcFetchRowCount(long delta) {\n        jdbcFetchRowCountUpdater.addAndGet(this, delta);\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount;\n    }\n\n    public void addJdbcUpdateCount(long updateCount) {\n        jdbcUpdateCountUpdater.addAndGet(this, updateCount);\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount;\n    }\n\n    public void incrementJdbcExecuteCount() {\n        jdbcExecuteCountUpdater.incrementAndGet(this);\n    }\n\n    public void addJdbcExecuteCount(long executeCount) {\n        jdbcExecuteCountUpdater.addAndGet(this, executeCount);\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount;\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano;\n    }\n\n    public void addJdbcExecuteTimeNano(long nano) {\n        jdbcExecuteTimeNanoUpdater.addAndGet(this, nano);\n    }\n\n    public void incrementJdbcCommitCount() {\n        jdbcCommitCountUpdater.incrementAndGet(this);\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount;\n    }\n\n    public void addJdbcCommitCount(long commitCount) {\n        jdbcCommitCountUpdater.addAndGet(this, commitCount);\n    }\n\n    public void incrementJdbcRollbackCount() {\n        jdbcRollbackCountUpdater.incrementAndGet(this);\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount;\n    }\n\n    public void addJdbcRollbackCount(long rollbackCount) {\n        jdbcRollbackCountUpdater.addAndGet(this, rollbackCount);\n    }\n\n    public long[] getRequestInterval() {\n        return new long[]{\n                //\n                requestIntervalHistogram_0_1, //\n                requestIntervalHistogram_1_10, //\n                requestIntervalHistogram_10_100, //\n                requestIntervalHistogram_100_1000, //\n                requestIntervalHistogram_1000_10000, //\n                requestIntervalHistogram_10000_100000, //\n                requestIntervalHistogram_100000_1000000, //\n                requestIntervalHistogram_1000000_10000000, //\n                requestIntervalHistogram_10000000_more //\n        };\n    }\n\n    public Map<String, Object> getStatData() {\n        return getValue(false).getStatData();\n    }\n\n    public WebSessionStatValue getValue(boolean reset) {\n        WebSessionStatValue val = new WebSessionStatValue();\n\n        val.sessionId = sessionId;\n        val.runningCount = this.getRunningCount();\n        val.concurrentMax = get(this, concurrentMaxUpdater, reset);\n        val.requestCount = get(this, requestCountUpdater, reset);\n        val.requestErrorCount = get(this, requestErrorCountUpdater, reset);\n        val.requestTimeNano = get(this, requestTimeNanoUpdater, reset);\n        val.jdbcFetchRowCount = get(this, jdbcFetchRowCountUpdater, reset);\n        val.jdbcUpdateCount = get(this, jdbcUpdateCountUpdater, reset);\n        val.jdbcExecuteCount = get(this, jdbcExecuteCountUpdater, reset);\n        val.jdbcExecuteTimeNano = get(this, jdbcExecuteTimeNanoUpdater, reset);\n        val.jdbcCommitCount = get(this, jdbcCommitCountUpdater, reset);\n        val.jdbcRollbackCount = get(this, jdbcRollbackCountUpdater, reset);\n        val.createTimeMillis = createTimeMillis;\n        val.lastAccessTimeMillis = lastAccessTimeMillis;\n        val.remoteAddress = remoteAddresses;\n        val.principal = principal;\n        val.userAgent = userAgent;\n\n        val.requestIntervalHistogram_0_1 = get(this, requestIntervalHistogram_0_1_Updater, reset);\n        val.requestIntervalHistogram_1_10 = get(this, requestIntervalHistogram_1_10_Updater, reset);\n        val.requestIntervalHistogram_10_100 = get(this, requestIntervalHistogram_10_100_Updater, reset);\n        val.requestIntervalHistogram_100_1000 = get(this, requestIntervalHistogram_100_1000_Updater, reset);\n        val.requestIntervalHistogram_1000_10000 = get(this, requestIntervalHistogram_1000_10000_Updater, reset);\n        val.requestIntervalHistogram_10000_100000 = get(this, requestIntervalHistogram_10000_100000_Updater, reset);\n        val.requestIntervalHistogram_100000_1000000 = get(this, requestIntervalHistogram_100000_1000000_Updater, reset);\n        val.requestIntervalHistogram_1000000_10000000 = get(this, requestIntervalHistogram_1000000_10000000_Updater,\n                reset);\n        val.requestIntervalHistogram_10000000_more = get(this, requestIntervalHistogram_10000000_more_Updater, reset);\n\n        return val;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebSessionStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport java.util.Date;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class WebSessionStatValue {\n    String sessionId;\n\n    int runningCount;\n    int concurrentMax;\n    long requestCount;\n    long requestErrorCount;\n    long requestTimeNano;\n    long jdbcFetchRowCount;\n    long jdbcUpdateCount;\n    long jdbcExecuteCount;\n    long jdbcExecuteTimeNano;\n    long jdbcCommitCount;\n    long jdbcRollbackCount;\n    long createTimeMillis;\n    long lastAccessTimeMillis;\n    String remoteAddress;\n    String principal;\n    String userAgent;\n\n    int requestIntervalHistogram_0_1;\n    int requestIntervalHistogram_1_10;\n    int requestIntervalHistogram_10_100;\n    int requestIntervalHistogram_100_1000;\n    int requestIntervalHistogram_1000_10000;\n    int requestIntervalHistogram_10000_100000;\n    int requestIntervalHistogram_100000_1000000;\n    int requestIntervalHistogram_1000000_10000000;\n    int requestIntervalHistogram_10000000_more;\n\n    public String getSessionId() {\n        return sessionId;\n    }\n\n    public void setSessionId(String sessionId) {\n        this.sessionId = sessionId;\n    }\n\n    public int getRunningCount() {\n        return runningCount;\n    }\n\n    public void setRunningCount(int runningCount) {\n        this.runningCount = runningCount;\n    }\n\n    public int getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public void setConcurrentMax(int concurrentMax) {\n        this.concurrentMax = concurrentMax;\n    }\n\n    public long getRequestCount() {\n        return requestCount;\n    }\n\n    public void setRequestCount(long requestCount) {\n        this.requestCount = requestCount;\n    }\n\n    public long getRequestErrorCount() {\n        return requestErrorCount;\n    }\n\n    public void setRequestErrorCount(long requestErrorCount) {\n        this.requestErrorCount = requestErrorCount;\n    }\n\n    public long getRequestTimeNano() {\n        return requestTimeNano;\n    }\n\n    public void setRequestTimeNano(long requestTimeNano) {\n        this.requestTimeNano = requestTimeNano;\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount;\n    }\n\n    public void setJdbcFetchRowCount(long jdbcFetchRowCount) {\n        this.jdbcFetchRowCount = jdbcFetchRowCount;\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount;\n    }\n\n    public void setJdbcUpdateCount(long jdbcUpdateCount) {\n        this.jdbcUpdateCount = jdbcUpdateCount;\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount;\n    }\n\n    public void setJdbcExecuteCount(long jdbcExecuteCount) {\n        this.jdbcExecuteCount = jdbcExecuteCount;\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano;\n    }\n\n    public void setJdbcExecuteTimeNano(long jdbcExecuteTimeNano) {\n        this.jdbcExecuteTimeNano = jdbcExecuteTimeNano;\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount;\n    }\n\n    public void setJdbcCommitCount(long jdbcCommitCount) {\n        this.jdbcCommitCount = jdbcCommitCount;\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount;\n    }\n\n    public void setJdbcRollbackCount(long jdbcRollbackCount) {\n        this.jdbcRollbackCount = jdbcRollbackCount;\n    }\n\n    public long getCreateTimeMillis() {\n        return createTimeMillis;\n    }\n\n    public void setCreateTimeMillis(long createTimeMillis) {\n        this.createTimeMillis = createTimeMillis;\n    }\n\n    public long getLastAccessTimeMillis() {\n        return lastAccessTimeMillis;\n    }\n\n    public void setLastAccessTimeMillis(long lastAccessTimeMillis) {\n        this.lastAccessTimeMillis = lastAccessTimeMillis;\n    }\n\n    public String getRemoteAddress() {\n        return remoteAddress;\n    }\n\n    public void setRemoteAddress(String remoteAddresses) {\n        this.remoteAddress = remoteAddresses;\n    }\n\n    public String getPrincipal() {\n        return principal;\n    }\n\n    public void setPrincipal(String principal) {\n        this.principal = principal;\n    }\n\n    public String getUserAgent() {\n        return userAgent;\n    }\n\n    public void setUserAgent(String userAgent) {\n        this.userAgent = userAgent;\n    }\n\n    public long getRequestTimeMillis() {\n        return getRequestTimeNano() / (1000 * 1000);\n    }\n\n    public Date getCreateTime() {\n        if (createTimeMillis == -1L) {\n            return null;\n        }\n\n        return new Date(createTimeMillis);\n    }\n\n    public Date getLastAccessTime() {\n        if (lastAccessTimeMillis < 0L) {\n            return null;\n        }\n\n        return new Date(lastAccessTimeMillis);\n    }\n\n    public long getJdbcExecuteTimeMillis() {\n        return getJdbcExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public long[] getRequestInterval() {\n        return new long[]{\n                //\n                requestIntervalHistogram_0_1, //\n                requestIntervalHistogram_1_10, //\n                requestIntervalHistogram_10_100, //\n                requestIntervalHistogram_100_1000, //\n                requestIntervalHistogram_1000_10000, //\n                requestIntervalHistogram_10000_100000, //\n                requestIntervalHistogram_100000_1000000, //\n                requestIntervalHistogram_1000000_10000000, //\n                requestIntervalHistogram_10000000_more //\n        };\n    }\n\n    public Map<String, Object> getStatData() {\n        Map<String, Object> data = new LinkedHashMap<String, Object>();\n\n        data.put(\"SESSIONID\", this.getSessionId());\n        data.put(\"Principal\", this.getPrincipal());\n        data.put(\"RunningCount\", this.getRunningCount());\n        data.put(\"ConcurrentMax\", this.getConcurrentMax());\n        data.put(\"RequestCount\", this.getRequestCount());\n        data.put(\"RequestTimeMillisTotal\", this.getRequestTimeMillis());\n        data.put(\"CreateTime\", this.getCreateTime());\n        data.put(\"LastAccessTime\", this.getLastAccessTime());\n        data.put(\"RemoteAddress\", this.getRemoteAddress());\n\n        data.put(\"JdbcCommitCount\", this.getJdbcCommitCount());\n        data.put(\"JdbcRollbackCount\", this.getJdbcRollbackCount());\n\n        data.put(\"JdbcExecuteCount\", this.getJdbcExecuteCount());\n        data.put(\"JdbcExecuteTimeMillis\", this.getJdbcExecuteTimeMillis());\n        data.put(\"JdbcFetchRowCount\", this.getJdbcFetchRowCount());\n        data.put(\"JdbcUpdateCount\", this.getJdbcUpdateCount());\n\n        data.put(\"UserAgent\", this.getUserAgent());\n        data.put(\"RequestInterval\", this.getRequestInterval());\n\n        return data;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebURIStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport com.alibaba.druid.support.profile.ProfileStat;\n\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class WebURIStat {\n    private final String uri;\n\n    private volatile int runningCount;\n    private volatile int concurrentMax;\n    private volatile long requestCount;\n    private volatile long requestTimeNano;\n    private volatile long requestTimeNanoMax;\n    private volatile long requestTimeNanoMaxOccurTime;\n\n    static final AtomicIntegerFieldUpdater<WebURIStat> runningCountUpdater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class,\n            \"runningCount\");\n    static final AtomicIntegerFieldUpdater<WebURIStat> concurrentMaxUpdater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class,\n            \"concurrentMax\");\n    static final AtomicLongFieldUpdater<WebURIStat> requestCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"requestCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> requestTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"requestTimeNano\");\n    static final AtomicLongFieldUpdater<WebURIStat> requestTimeNanoMaxUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"requestTimeNanoMax\");\n\n    static final AtomicLongFieldUpdater<WebURIStat> requestTimeNanoMaxOccurTimeUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"requestTimeNanoMaxOccurTime\");\n\n    private volatile long jdbcFetchRowCount;\n    private volatile long jdbcFetchRowPeak;                                                                                       // 单次请求读取行数的峰值\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcFetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcFetchRowCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcFetchRowPeakUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcFetchRowPeak\");\n\n    private volatile long jdbcUpdateCount;\n    private volatile long jdbcUpdatePeak;                                                                                         // 单次请求更新行数的峰值\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcUpdateCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcUpdateCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcUpdatePeakUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcUpdatePeak\");\n\n    private volatile long jdbcExecuteCount;\n    private volatile long jdbcExecuteErrorCount;\n    private volatile long jdbcExecutePeak;                                                                                        // 单次请求执行SQL次数的峰值\n    private volatile long jdbcExecuteTimeNano;\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcExecuteCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcExecuteCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcExecuteErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcExecuteErrorCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcExecutePeakUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcExecutePeak\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcExecuteTimeNanoUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcExecuteTimeNano\");\n\n    private volatile long jdbcCommitCount;\n    private volatile long jdbcRollbackCount;\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcCommitCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcCommitCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcRollbackCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcRollbackCount\");\n\n    private volatile long jdbcPoolConnectionOpenCount;\n    private volatile long jdbcPoolConnectionCloseCount;\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcPoolConnectionOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcPoolConnectionOpenCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcPoolConnectionCloseCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcPoolConnectionCloseCount\");\n\n    private volatile long jdbcResultSetOpenCount;\n    private volatile long jdbcResultSetCloseCount;\n\n    private volatile long errorCount;\n\n    private volatile long lastAccessTimeMillis = -1L;\n\n    private volatile ProfileStat profiletat = new ProfileStat();\n\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcResultSetOpenCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcResultSetOpenCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> jdbcResultSetCloseCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"jdbcResultSetCloseCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> errorCountUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"errorCount\");\n    static final AtomicLongFieldUpdater<WebURIStat> lastAccessTimeMillisUpdater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"lastAccessTimeMillis\");\n\n    private static final ThreadLocal<WebURIStat> currentLocal = new ThreadLocal<WebURIStat>();\n\n    private volatile long histogram_0_1;\n    private volatile long histogram_1_10;\n    private volatile long histogram_10_100;\n    private volatile long histogram_100_1000;\n    private volatile int histogram_1000_10000;\n    private volatile int histogram_10000_100000;\n    private volatile int histogram_100000_1000000;\n    private volatile int histogram_1000000_more;\n\n    static final AtomicLongFieldUpdater<WebURIStat> histogram_0_1_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_0_1\");\n    static final AtomicLongFieldUpdater<WebURIStat> histogram_1_10_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_1_10\");\n    static final AtomicLongFieldUpdater<WebURIStat> histogram_10_100_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_10_100\");\n    static final AtomicLongFieldUpdater<WebURIStat> histogram_100_1000_Updater = AtomicLongFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_100_1000\");\n    static final AtomicIntegerFieldUpdater<WebURIStat> histogram_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_1000_10000\");\n    static final AtomicIntegerFieldUpdater<WebURIStat> histogram_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_10000_100000\");\n    static final AtomicIntegerFieldUpdater<WebURIStat> histogram_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_100000_1000000\");\n    static final AtomicIntegerFieldUpdater<WebURIStat> histogram_1000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(WebURIStat.class,\n            \"histogram_1000000_more\");\n\n    public WebURIStat(String uri) {\n        super();\n        this.uri = uri;\n    }\n\n    public static WebURIStat current() {\n        return currentLocal.get();\n    }\n\n    public String getUri() {\n        return uri;\n    }\n\n    public void beforeInvoke() {\n        currentLocal.set(this);\n\n        int running = runningCountUpdater.incrementAndGet(this);\n\n        for (; ; ) {\n            int max = concurrentMaxUpdater.get(this);\n            if (running > max) {\n                if (concurrentMaxUpdater.compareAndSet(this, max, running)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        requestCountUpdater.incrementAndGet(this);\n\n        WebRequestStat requestStat = WebRequestStat.current();\n        if (requestStat != null) {\n            this.setLastAccessTimeMillis(requestStat.getStartMillis());\n        }\n    }\n\n    public void afterInvoke(Throwable error, long nanos) {\n        runningCountUpdater.decrementAndGet(this);\n        requestTimeNanoUpdater.addAndGet(this, nanos);\n\n        for (; ; ) {\n            long current = requestTimeNanoMaxUpdater.get(this);\n            if (current < nanos) {\n                if (requestTimeNanoMaxUpdater.compareAndSet(this, current, nanos)) {\n                    // 可能不准确，但是绝大多数情况下都会正确，性能换取一致性\n                    requestTimeNanoMaxOccurTime = System.currentTimeMillis();\n\n                    break;\n                } else {\n                    continue;\n                }\n            } else {\n                break;\n            }\n        }\n\n        histogramRecord(nanos);\n\n        if (error != null) {\n            errorCountUpdater.incrementAndGet(this);\n        }\n\n        {\n            WebRequestStat localStat = WebRequestStat.current();\n            if (localStat != null) {\n                {\n                    long fetchRowCount = localStat.getJdbcFetchRowCount();\n                    this.addJdbcFetchRowCount(fetchRowCount);\n\n                    for (; ; ) {\n                        long peak = jdbcFetchRowPeakUpdater.get(this);\n                        if (fetchRowCount <= peak) {\n                            break;\n                        }\n\n                        if (jdbcFetchRowPeakUpdater.compareAndSet(this, peak, fetchRowCount)) {\n                            break;\n                        }\n                    }\n                }\n                {\n                    long executeCount = localStat.getJdbcExecuteCount();\n                    this.addJdbcExecuteCount(executeCount);\n\n                    for (; ; ) {\n                        long peak = jdbcExecutePeakUpdater.get(this);\n                        if (executeCount <= peak) {\n                            break;\n                        }\n\n                        if (jdbcExecutePeakUpdater.compareAndSet(this, peak, executeCount)) {\n                            break;\n                        }\n                    }\n                }\n                {\n                    long updateCount = localStat.getJdbcUpdateCount();\n                    this.addJdbcUpdateCount(updateCount);\n\n                    for (; ; ) {\n                        long peak = jdbcUpdatePeakUpdater.get(this);\n                        if (updateCount <= peak) {\n                            break;\n                        }\n\n                        if (jdbcUpdatePeakUpdater.compareAndSet(this, peak, updateCount)) {\n                            break;\n                        }\n                    }\n                }\n\n                jdbcExecuteErrorCountUpdater.addAndGet(this, localStat.getJdbcExecuteErrorCount());\n                jdbcExecuteTimeNanoUpdater.addAndGet(this, localStat.getJdbcExecuteTimeNano());\n\n                this.addJdbcPoolConnectionOpenCount(localStat.getJdbcPoolConnectionOpenCount());\n                this.addJdbcPoolConnectionCloseCount(localStat.getJdbcPoolConnectionCloseCount());\n\n                this.addJdbcResultSetOpenCount(localStat.getJdbcResultSetOpenCount());\n                this.addJdbcResultSetCloseCount(localStat.getJdbcResultSetCloseCount());\n            }\n        }\n\n        currentLocal.set(null);\n    }\n\n    private void histogramRecord(long nanos) {\n        final long millis = nanos / 1000 / 1000;\n\n        if (millis < 1) {\n            histogram_0_1_Updater.incrementAndGet(this);\n        } else if (millis < 10) {\n            histogram_1_10_Updater.incrementAndGet(this);\n        } else if (millis < 100) {\n            histogram_10_100_Updater.incrementAndGet(this);\n        } else if (millis < 1000) {\n            histogram_100_1000_Updater.incrementAndGet(this);\n        } else if (millis < 10000) {\n            histogram_1000_10000_Updater.incrementAndGet(this);\n        } else if (millis < 100000) {\n            histogram_10000_100000_Updater.incrementAndGet(this);\n        } else if (millis < 1000000) {\n            histogram_100000_1000000_Updater.incrementAndGet(this);\n        } else {\n            histogram_1000000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public int getRunningCount() {\n        return this.runningCount;\n    }\n\n    public long getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public long getRequestCount() {\n        return requestCount;\n    }\n\n    public long getRequestTimeNano() {\n        return requestTimeNano;\n    }\n\n    public long getRequestTimeMillis() {\n        return getRequestTimeNano() / (1000 * 1000);\n    }\n\n    public void addJdbcFetchRowCount(long delta) {\n        jdbcFetchRowCountUpdater.addAndGet(this, delta);\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount;\n    }\n\n    public long getJdbcFetchRowPeak() {\n        return jdbcFetchRowPeak;\n    }\n\n    public void addJdbcUpdateCount(long updateCount) {\n        jdbcUpdateCountUpdater.addAndGet(this, updateCount);\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount;\n    }\n\n    public long getJdbcUpdatePeak() {\n        return jdbcUpdatePeak;\n    }\n\n    public void incrementJdbcExecuteCount() {\n        jdbcExecuteCountUpdater.incrementAndGet(this);\n    }\n\n    public void addJdbcExecuteCount(long executeCount) {\n        jdbcExecuteCountUpdater.addAndGet(this, executeCount);\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount;\n    }\n\n    public long getJdbcExecuteErrorCount() {\n        return jdbcExecuteErrorCount;\n    }\n\n    public long getJdbcExecutePeak() {\n        return jdbcExecutePeak;\n    }\n\n    public long getJdbcExecuteTimeMillis() {\n        return getJdbcExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano;\n    }\n\n    public void incrementJdbcCommitCount() {\n        jdbcCommitCountUpdater.incrementAndGet(this);\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount;\n    }\n\n    public void incrementJdbcRollbackCount() {\n        jdbcRollbackCountUpdater.incrementAndGet(this);\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount;\n    }\n\n    public void setLastAccessTimeMillis(long lastAccessTimeMillis) {\n        this.lastAccessTimeMillis = lastAccessTimeMillis;\n    }\n\n    public Date getLastAccessTime() {\n        if (lastAccessTimeMillis < 0L) {\n            return null;\n        }\n\n        return new Date(lastAccessTimeMillis);\n    }\n\n    public long getLastAccessTimeMillis() {\n        return lastAccessTimeMillis;\n    }\n\n    public long getErrorCount() {\n        return errorCount;\n    }\n\n    public long getJdbcPoolConnectionOpenCount() {\n        return jdbcPoolConnectionOpenCount;\n    }\n\n    public void addJdbcPoolConnectionOpenCount(long delta) {\n        jdbcPoolConnectionOpenCountUpdater.addAndGet(this, delta);\n    }\n\n    public void incrementJdbcPoolConnectionOpenCount() {\n        jdbcPoolConnectionOpenCountUpdater.incrementAndGet(this);\n    }\n\n    public long getJdbcPoolConnectionCloseCount() {\n        return jdbcPoolConnectionCloseCount;\n    }\n\n    public void addJdbcPoolConnectionCloseCount(long delta) {\n        jdbcPoolConnectionCloseCountUpdater.addAndGet(this, delta);\n    }\n\n    public void incrementJdbcPoolConnectionCloseCount() {\n        jdbcPoolConnectionCloseCountUpdater.incrementAndGet(this);\n    }\n\n    public long getJdbcResultSetOpenCount() {\n        return jdbcResultSetOpenCount;\n    }\n\n    public void addJdbcResultSetOpenCount(long delta) {\n        jdbcResultSetOpenCountUpdater.addAndGet(this, delta);\n    }\n\n    public long getJdbcResultSetCloseCount() {\n        return jdbcResultSetCloseCount;\n    }\n\n    public void addJdbcResultSetCloseCount(long delta) {\n        jdbcResultSetCloseCountUpdater.addAndGet(this, delta);\n    }\n\n    public ProfileStat getProfiletat() {\n        return profiletat;\n    }\n\n    public long[] getHistogramValues() {\n        return new long[]{\n                //\n                histogram_0_1, //\n                histogram_1_10, //\n                histogram_10_100, //\n                histogram_100_1000, //\n                histogram_1000_10000, //\n                histogram_10000_100000, //\n                histogram_100000_1000000, //\n                histogram_1000000_more //\n        };\n    }\n\n    public WebURIStatValue getValue(boolean reset) {\n        WebURIStatValue val = new WebURIStatValue();\n\n        val.setUri(uri);\n\n        val.setRunningCount(runningCount);\n        val.setConcurrentMax(get(this, concurrentMaxUpdater, reset));\n        val.setRequestCount(get(this, requestCountUpdater, reset));\n        val.setRequestTimeNano(get(this, requestTimeNanoUpdater, reset));\n        val.setRequestTimeNanoMax(get(this, requestTimeNanoMaxUpdater, reset));\n        val.setRequestTimeNanoMaxOccurTime(get(this, requestTimeNanoMaxOccurTimeUpdater, reset));\n\n        val.setJdbcFetchRowCount(get(this, jdbcFetchRowCountUpdater, reset));\n        val.setJdbcFetchRowPeak(get(this, jdbcFetchRowPeakUpdater, reset));\n\n        val.setJdbcUpdateCount(get(this, jdbcUpdateCountUpdater, reset));\n        val.setJdbcUpdatePeak(get(this, jdbcUpdatePeakUpdater, reset));\n\n        val.setJdbcExecuteCount(get(this, jdbcExecuteCountUpdater, reset));\n        val.setJdbcExecuteErrorCount(get(this, jdbcExecuteErrorCountUpdater, reset));\n        val.setJdbcExecutePeak(get(this, jdbcExecutePeakUpdater, reset));\n        val.setJdbcExecuteTimeNano(get(this, jdbcExecuteTimeNanoUpdater, reset));\n\n        val.setJdbcCommitCount(get(this, jdbcCommitCountUpdater, reset));\n        val.setJdbcRollbackCount(get(this, jdbcRollbackCountUpdater, reset));\n\n        val.setJdbcPoolConnectionOpenCount(get(this, jdbcPoolConnectionOpenCountUpdater, reset));\n        val.setJdbcPoolConnectionCloseCount(get(this, jdbcPoolConnectionCloseCountUpdater, reset));\n\n        val.setJdbcResultSetOpenCount(get(this, jdbcResultSetOpenCountUpdater, reset));\n        val.setJdbcResultSetCloseCount(get(this, jdbcResultSetCloseCountUpdater, reset));\n\n        val.setErrorCount(get(this, errorCountUpdater, reset));\n\n        val.setLastAccessTimeMillis(get(this, lastAccessTimeMillisUpdater, reset));\n\n        val.setProfileEntryStatValueList(this.getProfiletat().getStatValue(reset));\n\n        val.histogram_0_1 = get(this, histogram_0_1_Updater, reset);\n        val.histogram_1_10 = get(this, histogram_1_10_Updater, reset);\n        val.histogram_10_100 = get(this, histogram_10_100_Updater, reset);\n        val.histogram_100_1000 = get(this, histogram_100_1000_Updater, reset);\n        val.histogram_1000_10000 = get(this, histogram_1000_10000_Updater, reset);\n        val.histogram_10000_100000 = get(this, histogram_10000_100000_Updater, reset);\n        val.histogram_100000_1000000 = get(this, histogram_100000_1000000_Updater, reset);\n        val.histogram_1000000_more = get(this, histogram_1000000_more_Updater, reset);\n\n        return val;\n    }\n\n    public Map<String, Object> getStatData() {\n        return getValue(false).getStatData();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/stat/WebURIStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.stat;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\nimport com.alibaba.druid.support.profile.ProfileEntryStatValue;\n\nimport java.util.*;\n\n@MTable(name = \"druid_weburi\")\npublic class WebURIStatValue {\n    @MField(groupBy = true, aggregate = AggregateType.None)\n    protected String uri;\n\n    @MField(aggregate = AggregateType.Last)\n    protected int runningCount;\n\n    @MField(aggregate = AggregateType.Max)\n    protected int concurrentMax;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long requestCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long requestTimeNano;\n\n    @MField(aggregate = AggregateType.Max)\n    protected long requestTimeNanoMax;\n\n    @MField(aggregate = AggregateType.Last)\n    protected Date requestTimeNanoMaxOccurTime;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcFetchRowCount;\n\n    @MField(aggregate = AggregateType.Max)\n    protected long jdbcFetchRowPeak;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcUpdateCount;\n\n    @MField(aggregate = AggregateType.Max)\n    protected long jdbcUpdatePeak;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcExecuteCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcExecuteErrorCount;\n\n    @MField(aggregate = AggregateType.Max)\n    protected long jdbcExecutePeak;             // 单次请求执行SQL次数的峰值\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcExecuteTimeNano;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcCommitCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcRollbackCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcPoolConnectionOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcPoolConnectionCloseCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcResultSetOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long jdbcResultSetCloseCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    protected long errorCount;\n\n    @MField(aggregate = AggregateType.Last)\n    protected Date lastAccessTime;\n\n    private List<ProfileEntryStatValue> profileEntryStatValueList;\n\n    @MField(name = \"h1\", aggregate = AggregateType.Sum)\n    protected long histogram_0_1;\n\n    @MField(name = \"h10\", aggregate = AggregateType.Sum)\n    protected long histogram_1_10;\n\n    @MField(name = \"h100\", aggregate = AggregateType.Sum)\n    protected long histogram_10_100;\n    @MField(name = \"h1000\", aggregate = AggregateType.Sum)\n    protected long histogram_100_1000;\n\n    @MField(name = \"h10000\", aggregate = AggregateType.Sum)\n    protected int histogram_1000_10000;\n\n    @MField(name = \"h100000\", aggregate = AggregateType.Sum)\n    protected int histogram_10000_100000;\n\n    @MField(name = \"h1000000\", aggregate = AggregateType.Sum)\n    protected int histogram_100000_1000000;\n\n    @MField(name = \"hmore\", aggregate = AggregateType.Sum)\n    protected int histogram_1000000_more;\n\n    public long[] getHistogram() {\n        return new long[]{histogram_0_1, //\n                histogram_1_10, //\n                histogram_10_100, //\n                histogram_100_1000, //\n                histogram_1000_10000, //\n                histogram_10000_100000, //\n                histogram_100000_1000000, //\n                histogram_1000000_more, //\n        };\n    }\n\n    public List<ProfileEntryStatValue> getProfileEntryStatValueList() {\n        return profileEntryStatValueList;\n    }\n\n    public void setProfileEntryStatValueList(List<ProfileEntryStatValue> profileEntryStatValueList) {\n        this.profileEntryStatValueList = profileEntryStatValueList;\n    }\n\n    public String getUri() {\n        return uri;\n    }\n\n    public void setUri(String uri) {\n        this.uri = uri;\n    }\n\n    public int getRunningCount() {\n        return runningCount;\n    }\n\n    public void setRunningCount(int runningCount) {\n        this.runningCount = runningCount;\n    }\n\n    public int getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public void setConcurrentMax(int concurrentMax) {\n        this.concurrentMax = concurrentMax;\n    }\n\n    public long getRequestCount() {\n        return requestCount;\n    }\n\n    public void setRequestCount(long requestCount) {\n        this.requestCount = requestCount;\n    }\n\n    public long getRequestTimeNano() {\n        return requestTimeNano;\n    }\n\n    public void setRequestTimeNano(long requestTimeNano) {\n        this.requestTimeNano = requestTimeNano;\n    }\n\n    public long getRequestTimeNanoMax() {\n        return requestTimeNanoMax;\n    }\n\n    public void setRequestTimeNanoMax(long requestTimeNanoMax) {\n        this.requestTimeNanoMax = requestTimeNanoMax;\n    }\n\n    public Date getRequestTimeNanoMaxOccurTime() {\n        return requestTimeNanoMaxOccurTime;\n    }\n\n    public void setRequestTimeNanoMaxOccurTime(long requestTimeNanoMaxOccurTime) {\n        if (requestTimeNanoMaxOccurTime > 0) {\n            this.requestTimeNanoMaxOccurTime = new Date(requestTimeNanoMaxOccurTime);\n        } else {\n            this.requestTimeNanoMaxOccurTime = null;\n        }\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount;\n    }\n\n    public void setJdbcFetchRowCount(long jdbcFetchRowCount) {\n        this.jdbcFetchRowCount = jdbcFetchRowCount;\n    }\n\n    public long getJdbcFetchRowPeak() {\n        return jdbcFetchRowPeak;\n    }\n\n    public void setJdbcFetchRowPeak(long jdbcFetchRowPeak) {\n        this.jdbcFetchRowPeak = jdbcFetchRowPeak;\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount;\n    }\n\n    public void setJdbcUpdateCount(long jdbcUpdateCount) {\n        this.jdbcUpdateCount = jdbcUpdateCount;\n    }\n\n    public long getJdbcUpdatePeak() {\n        return jdbcUpdatePeak;\n    }\n\n    public void setJdbcUpdatePeak(long jdbcUpdatePeak) {\n        this.jdbcUpdatePeak = jdbcUpdatePeak;\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount;\n    }\n\n    public void setJdbcExecuteCount(long jdbcExecuteCount) {\n        this.jdbcExecuteCount = jdbcExecuteCount;\n    }\n\n    public long getJdbcExecuteErrorCount() {\n        return jdbcExecuteErrorCount;\n    }\n\n    public void setJdbcExecuteErrorCount(long jdbcExecuteErrorCount) {\n        this.jdbcExecuteErrorCount = jdbcExecuteErrorCount;\n    }\n\n    public long getJdbcExecutePeak() {\n        return jdbcExecutePeak;\n    }\n\n    public void setJdbcExecutePeak(long jdbcExecutePeak) {\n        this.jdbcExecutePeak = jdbcExecutePeak;\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano;\n    }\n\n    public void setJdbcExecuteTimeNano(long jdbcExecuteTimeNano) {\n        this.jdbcExecuteTimeNano = jdbcExecuteTimeNano;\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount;\n    }\n\n    public void setJdbcCommitCount(long jdbcCommitCount) {\n        this.jdbcCommitCount = jdbcCommitCount;\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount;\n    }\n\n    public void setJdbcRollbackCount(long jdbcRollbackCount) {\n        this.jdbcRollbackCount = jdbcRollbackCount;\n    }\n\n    public long getJdbcPoolConnectionOpenCount() {\n        return jdbcPoolConnectionOpenCount;\n    }\n\n    public void setJdbcPoolConnectionOpenCount(long jdbcPoolConnectionOpenCount) {\n        this.jdbcPoolConnectionOpenCount = jdbcPoolConnectionOpenCount;\n    }\n\n    public long getJdbcPoolConnectionCloseCount() {\n        return jdbcPoolConnectionCloseCount;\n    }\n\n    public void setJdbcPoolConnectionCloseCount(long jdbcPoolConnectionCloseCount) {\n        this.jdbcPoolConnectionCloseCount = jdbcPoolConnectionCloseCount;\n    }\n\n    public long getJdbcResultSetOpenCount() {\n        return jdbcResultSetOpenCount;\n    }\n\n    public void setJdbcResultSetOpenCount(long jdbcResultSetOpenCount) {\n        this.jdbcResultSetOpenCount = jdbcResultSetOpenCount;\n    }\n\n    public long getJdbcResultSetCloseCount() {\n        return jdbcResultSetCloseCount;\n    }\n\n    public void setJdbcResultSetCloseCount(long jdbcResultSetCloseCount) {\n        this.jdbcResultSetCloseCount = jdbcResultSetCloseCount;\n    }\n\n    public long getErrorCount() {\n        return errorCount;\n    }\n\n    public void setErrorCount(long errorCount) {\n        this.errorCount = errorCount;\n    }\n\n    public void setLastAccessTimeMillis(long lastAccessTimeMillis) {\n        if (lastAccessTimeMillis > 0) {\n            this.lastAccessTime = new Date(lastAccessTimeMillis);\n        } else {\n            this.lastAccessTime = null;\n        }\n    }\n\n    public long getRequestTimeMillis() {\n        return getRequestTimeNano() / (1000 * 1000);\n    }\n\n    public long getRequestTimeMillisMax() {\n        return getRequestTimeNanoMax() / (1000 * 1000);\n    }\n\n    public Date getLastAccessTime() {\n        return lastAccessTime;\n    }\n\n    public long getJdbcExecuteTimeMillis() {\n        return getJdbcExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public Map<String, Object> getStatData() {\n        Map<String, Object> data = new LinkedHashMap<String, Object>();\n\n        data.put(\"URI\", this.getUri());\n        data.put(\"RunningCount\", this.getRunningCount());\n        data.put(\"ConcurrentMax\", this.getConcurrentMax());\n        data.put(\"RequestCount\", this.getRequestCount());\n        data.put(\"RequestTimeMillis\", this.getRequestTimeMillis());\n        data.put(\"ErrorCount\", this.getErrorCount());\n        data.put(\"LastAccessTime\", this.getLastAccessTime());\n\n        data.put(\"JdbcCommitCount\", this.getJdbcCommitCount());\n        data.put(\"JdbcRollbackCount\", this.getJdbcRollbackCount());\n\n        data.put(\"JdbcExecuteCount\", this.getJdbcExecuteCount());\n        data.put(\"JdbcExecuteErrorCount\", this.getJdbcExecuteErrorCount());\n        data.put(\"JdbcExecutePeak\", this.getJdbcExecutePeak());\n        data.put(\"JdbcExecuteTimeMillis\", this.getJdbcExecuteTimeMillis());\n\n        data.put(\"JdbcFetchRowCount\", this.getJdbcFetchRowCount());\n        data.put(\"JdbcFetchRowPeak\", this.getJdbcFetchRowPeak());\n\n        data.put(\"JdbcUpdateCount\", this.getJdbcUpdateCount());\n        data.put(\"JdbcUpdatePeak\", this.getJdbcUpdatePeak());\n\n        data.put(\"JdbcPoolConnectionOpenCount\", this.getJdbcPoolConnectionOpenCount());\n        data.put(\"JdbcPoolConnectionCloseCount\", this.getJdbcPoolConnectionCloseCount());\n\n        data.put(\"JdbcResultSetOpenCount\", this.getJdbcResultSetOpenCount());\n        data.put(\"JdbcResultSetCloseCount\", this.getJdbcResultSetCloseCount());\n        data.put(\"Histogram\", this.getHistogram());\n\n        if (this.profileEntryStatValueList != null) {\n            int size = profileEntryStatValueList.size();\n            List<Map<String, Object>> profileDataList = new ArrayList<Map<String, Object>>(size);\n            for (ProfileEntryStatValue profileEntryStatValue : profileEntryStatValueList) {\n                profileDataList.add(profileEntryStatValue.getData());\n            }\n            data.put(\"Profiles\", profileDataList);\n        }\n\n        data.put(\"RequestTimeMillisMax\", this.getRequestTimeMillisMax());\n        data.put(\"RequestTimeMillisMaxOccurTime\", this.getRequestTimeNanoMaxOccurTime());\n\n        return data;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/util/IPAddress.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.util;\n\nimport java.util.NoSuchElementException;\n\n/**\n * @author Marcel Dullaart\n * @version 1.0\n */\npublic class IPAddress implements Cloneable {\n    /**\n     * IP address\n     */\n    protected int ipAddress;\n\n    public IPAddress(String ipAddressStr) {\n        ipAddress = parseIPAddress(ipAddressStr);\n    }\n\n    public IPAddress(int address) {\n        ipAddress = address;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Return the integer representation of the IP address.\n     *\n     * @return The IP address.\n     */\n    public final int getIPAddress() {\n        return ipAddress;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Return the string representation of the IP Address following the common decimal-dotted notation xxx.xxx.xxx.xxx.\n     *\n     * @return Return the string representation of the IP address.\n     */\n    public String toString() {\n        StringBuilder result = new StringBuilder();\n        int temp;\n\n        temp = ipAddress & 0x000000FF;\n        result.append(temp);\n        result.append(\".\");\n\n        temp = (ipAddress >> 8) & 0x000000FF;\n        result.append(temp);\n        result.append(\".\");\n\n        temp = (ipAddress >> 16) & 0x000000FF;\n        result.append(temp);\n        result.append(\".\");\n\n        temp = (ipAddress >> 24) & 0x000000FF;\n        result.append(temp);\n\n        return result.toString();\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Check if the IP address is belongs to a Class A IP address.\n     *\n     * @return Return <code>true</code> if the encapsulated IP address belongs to a class A IP address, otherwise\n     * returne <code>false</code>.\n     */\n    public final boolean isClassA() {\n        return (ipAddress & 0x00000001) == 0;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Check if the IP address is belongs to a Class B IP address.\n     *\n     * @return Return <code>true</code> if the encapsulated IP address belongs to a class B IP address, otherwise\n     * returne <code>false</code>.\n     */\n    public final boolean isClassB() {\n        return (ipAddress & 0x00000003) == 1;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Check if the IP address is belongs to a Class C IP address.\n     *\n     * @return Return <code>true</code> if the encapsulated IP address belongs to a class C IP address, otherwise\n     * returne <code>false</code>.\n     */\n    public final boolean isClassC() {\n        return (ipAddress & 0x00000007) == 3;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Convert a decimal-dotted notation representation of an IP address into an 32 bits interger value.\n     *\n     * @param ipAddressStr Decimal-dotted notation (xxx.xxx.xxx.xxx) of the IP address.\n     * @return Return the 32 bits integer representation of the IP address.\n     * @throws InvalidIPAddressException Throws this exception if the specified IP address is not compliant to the\n     *                                   decimal-dotted notation xxx.xxx.xxx.xxx.\n     */\n    final int parseIPAddress(String ipAddressStr) {\n        int result = 0;\n\n        if (ipAddressStr == null) {\n            throw new IllegalArgumentException();\n        }\n\n        try {\n            String tmp = ipAddressStr;\n\n            // get the 3 first numbers\n            int offset = 0;\n            for (int i = 0; i < 3; i++) {\n                // get the position of the first dot\n                int index = tmp.indexOf('.');\n\n                // if there is not a dot then the ip string representation is\n                // not compliant to the decimal-dotted notation.\n                if (index != -1) {\n                    // get the number before the dot and convert it into\n                    // an integer.\n                    String numberStr = tmp.substring(0, index);\n                    int number = Integer.parseInt(numberStr);\n                    if ((number < 0) || (number > 255)) {\n                        throw new IllegalArgumentException(\"Invalid IP Address [\" + ipAddressStr + \"]\");\n                    }\n\n                    result += number << offset;\n                    offset += 8;\n                    tmp = tmp.substring(index + 1);\n                } else {\n                    throw new IllegalArgumentException(\"Invalid IP Address [\" + ipAddressStr + \"]\");\n                }\n            }\n\n            // the remaining part of the string should be the last number.\n            if (tmp.length() > 0) {\n                int number = Integer.parseInt(tmp);\n                if ((number < 0) || (number > 255)) {\n                    throw new IllegalArgumentException(\"Invalid IP Address [\" + ipAddressStr + \"]\");\n                }\n\n                result += number << offset;\n                ipAddress = result;\n            } else {\n                throw new IllegalArgumentException(\"Invalid IP Address [\" + ipAddressStr + \"]\");\n            }\n        } catch (NoSuchElementException ex) {\n            throw new IllegalArgumentException(\"Invalid IP Address [\" + ipAddressStr + \"]\", ex);\n        } catch (NumberFormatException ex) {\n            throw new IllegalArgumentException(\"Invalid IP Address [\" + ipAddressStr + \"]\", ex);\n        }\n\n        return result;\n    }\n\n    public int hashCode() {\n        return this.ipAddress;\n    }\n\n    public boolean equals(Object another) {\n        return another instanceof IPAddress && ipAddress == ((IPAddress) another).ipAddress;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/http/util/IPRange.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.http.util;\n\n/**\n * This class represents an IP Range, which are represented by an IP address and and a subnet mask. The standards\n * describing modern routing protocols often refer to the extended-network-prefix-length rather than the subnet mask.\n * The prefix length is equal to the number of contiguous one-bits in the traditional subnet mask. This means that\n * specifying the network address 130.5.5.25 with a subnet mask of 255.255.255.0 can also be expressed as 130.5.5.25/24.\n * The prefix-length notation is more compact and easier to understand than writing out the mask in its traditional\n * dotted-decimal format.\n *\n * @author Marcel Dullaart\n * @version 1.0\n * @see IPAddress\n */\npublic class IPRange {\n    /**\n     * IP address\n     */\n    private IPAddress ipAddress;\n\n    /**\n     * IP subnet mask\n     */\n    private IPAddress ipSubnetMask;\n\n    /**\n     * extended network prefix\n     */\n    private int extendedNetworkPrefix;\n\n    public IPRange(String range) {\n        parseRange(range);\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Return the encapsulated IP address.\n     *\n     * @return The IP address.\n     */\n    public final IPAddress getIPAddress() {\n        return ipAddress;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Return the encapsulated subnet mask\n     *\n     * @return The IP range's subnet mask.\n     */\n    public final IPAddress getIPSubnetMask() {\n        return ipSubnetMask;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Return the extended extended network prefix.\n     *\n     * @return Return the extended network prefix.\n     */\n    public final int getExtendedNetworkPrefix() {\n        return extendedNetworkPrefix;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Convert the IP Range into a string representation.\n     *\n     * @return Return the string representation of the IP Address following the common format xxx.xxx.xxx.xxx/xx (IP\n     * address/extended network prefixs).\n     */\n    public String toString() {\n        return ipAddress.toString() + \"/\" + extendedNetworkPrefix;\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Parse the IP range string representation.\n     *\n     * @param range String representation of the IP range.\n     * @throws IllegalArgumentException Throws this exception if the specified range is not a valid IP network range.\n     */\n    final void parseRange(String range) {\n        if (range == null) {\n            throw new IllegalArgumentException(\"Invalid IP range\");\n        }\n\n        int index = range.indexOf('/');\n        String subnetStr = null;\n        if (index == -1) {\n            ipAddress = new IPAddress(range);\n        } else {\n            ipAddress = new IPAddress(range.substring(0, index));\n            subnetStr = range.substring(index + 1);\n        }\n\n        // try to convert the remaining part of the range into a decimal\n        // value.\n        try {\n            if (subnetStr != null) {\n                extendedNetworkPrefix = Integer.parseInt(subnetStr);\n                if ((extendedNetworkPrefix < 0) || (extendedNetworkPrefix > 32)) {\n                    throw new IllegalArgumentException(\"Invalid IP range [\" + range + \"]\");\n                }\n                ipSubnetMask = computeMaskFromNetworkPrefix(extendedNetworkPrefix);\n            }\n        } catch (NumberFormatException ex) {\n            // the remaining part is not a valid decimal value.\n            // Check if it's a decimal-dotted notation.\n            ipSubnetMask = new IPAddress(subnetStr);\n\n            // create the corresponding subnet decimal\n            extendedNetworkPrefix = computeNetworkPrefixFromMask(ipSubnetMask);\n            if (extendedNetworkPrefix == -1) {\n                throw new IllegalArgumentException(\"Invalid IP range [\" + range + \"]\", ex);\n            }\n        }\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Compute the extended network prefix from the IP subnet mask.\n     *\n     * @param mask Reference to the subnet mask IP number.\n     * @return Return the extended network prefix. Return -1 if the specified mask cannot be converted into a extended\n     * prefix network.\n     */\n    private int computeNetworkPrefixFromMask(IPAddress mask) {\n        int result = 0;\n        int tmp = mask.getIPAddress();\n\n        while ((tmp & 0x00000001) == 0x00000001) {\n            result++;\n            tmp = tmp >>> 1;\n        }\n\n        if (tmp != 0) {\n            return -1;\n        }\n\n        return result;\n    }\n\n    public static String toDecimalString(String inBinaryIpAddress) {\n        StringBuilder decimalIp = new StringBuilder();\n        String[] binary = new String[4];\n\n        for (int i = 0, c = 0; i < 32; i = i + 8, c++) {\n            binary[c] = inBinaryIpAddress.substring(i, i + 8);\n            int octet = Integer.parseInt(binary[c], 2);\n            decimalIp.append(octet);\n            if (c < 3) {\n                decimalIp.append('.');\n            }\n        }\n        return decimalIp.toString();\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Convert a extended network prefix integer into an IP number.\n     *\n     * @param prefix The network prefix number.\n     * @return Return the IP number corresponding to the extended network prefix.\n     */\n    private IPAddress computeMaskFromNetworkPrefix(int prefix) {\n        /*\n         * int subnet = 0; for (int i=0; i<prefix; i++) { subnet = subnet << 1; subnet += 1; }\n         */\n\n        StringBuilder str = new StringBuilder();\n        for (int i = 0; i < 32; i++) {\n            if (i < prefix) {\n                str.append(\"1\");\n            } else {\n                str.append(\"0\");\n            }\n        }\n\n        String decimalString = toDecimalString(str.toString());\n        return new IPAddress(decimalString);\n\n    }\n\n    // -------------------------------------------------------------------------\n\n    /**\n     * Check if the specified IP address is in the encapsulated range.\n     *\n     * @param address The IP address to be tested.\n     * @return Return <code>true</code> if the specified IP address is in the encapsulated IP range, otherwise return\n     * <code>false</code>.\n     */\n    public boolean isIPAddressInRange(IPAddress address) {\n        if (ipSubnetMask == null) {\n            return this.ipAddress.equals(address);\n        }\n\n        int result1 = address.getIPAddress() & ipSubnetMask.getIPAddress();\n        int result2 = ipAddress.getIPAddress() & ipSubnetMask.getIPAddress();\n\n        return result1 == result2;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/DruidDataSourceFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport javax.sql.DataSource;\n\nimport java.util.Map;\n\npublic class DruidDataSourceFactory implements com.ibatis.sqlmap.engine.datasource.DataSourceFactory {\n    private DataSource dataSource;\n\n    @SuppressWarnings(\"rawtypes\")\n    public void initialize(Map map) {\n        try {\n            dataSource = com.alibaba.druid.pool.DruidDataSourceFactory.createDataSource(map);\n        } catch (RuntimeException e) {\n            throw e;\n        } catch (Exception e) {\n            throw new RuntimeException(\"init data source error\", e);\n        }\n    }\n\n    public DataSource getDataSource() {\n        return dataSource;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/IbatisUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.ibatis.sqlmap.client.SqlMapExecutor;\nimport com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;\nimport com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl;\nimport com.ibatis.sqlmap.engine.scope.SessionScope;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\n\npublic class IbatisUtils {\n    private static Log LOG = LogFactory.getLog(IbatisUtils.class);\n\n    private static boolean VERSION_2_3_4;\n\n    private static Method methodGetId;\n    private static Method methodGetResource;\n    private static Field sessionField;\n\n    static {\n        try {\n            Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(\"com.ibatis.sqlmap.engine.mapping.result.AutoResultMap\");\n            Method[] methods = clazz.getMethods();\n            for (Method method : methods) {\n                if (method.getName().equals(\"setResultObjectValues\")) { // ibatis 2.3.4 add method 'setResultObjectValues'\n                    VERSION_2_3_4 = true;\n                    break;\n                }\n            }\n        } catch (Throwable e) {\n            LOG.error(\"Error while initializing\", e);\n        }\n    }\n\n    public static boolean isVersion2_3_4() {\n        return VERSION_2_3_4;\n    }\n\n    public static SqlMapExecutor setClientImpl(SqlMapExecutor session, SqlMapClientImplWrapper clientImplWrapper) {\n        if (session == null || clientImplWrapper == null) {\n            return session;\n        }\n\n        if (session.getClass() == SqlMapSessionImpl.class) {\n            SqlMapSessionImpl sessionImpl = (SqlMapSessionImpl) session;\n            set(sessionImpl, clientImplWrapper);\n        }\n\n        return session;\n    }\n\n    /**\n     * 通过反射的方式得到id，能够兼容2.3.0和2.3.4\n     *\n     * @param statement the statement object from which to retrieve the ID\n     * @return the ID as a string, or null if an error occurs or if the ID is null\n     */\n    protected static String getId(Object statement) {\n        try {\n            if (methodGetId == null) {\n                Class<?> clazz = statement.getClass();\n                methodGetId = clazz.getMethod(\"getId\");\n            }\n\n            Object returnValue = methodGetId.invoke(statement);\n\n            if (returnValue == null) {\n                return null;\n            }\n\n            return returnValue.toString();\n        } catch (Exception ex) {\n            LOG.error(\"createIdError\", ex);\n            return null;\n        }\n    }\n\n    /**\n     * 通过反射的方式得到resource，能够兼容2.3.0和2.3.4\n     *\n     * @param statement the statement object from which to retrieve the resource\n     * @return the resource as a string, or null if an error occurs\n     */\n    protected static String getResource(Object statement) {\n        try {\n            if (methodGetResource == null) {\n                methodGetResource = statement.getClass().getMethod(\"getResource\");\n            }\n\n            return (String) methodGetResource.invoke(statement);\n        } catch (Exception ex) {\n            return null;\n        }\n    }\n\n    public static void set(SqlMapSessionImpl session, SqlMapClientImpl client) {\n        if (sessionField == null) {\n            for (Field field : SqlMapSessionImpl.class.getDeclaredFields()) {\n                if (field.getName().equals(\"session\") || field.getName().equals(\"sessionScope\")) {\n                    sessionField = field;\n                    sessionField.setAccessible(true);\n                    break;\n                }\n            }\n        }\n\n        if (sessionField != null) {\n            SessionScope sessionScope;\n            try {\n                sessionScope = (SessionScope) sessionField.get(session);\n\n                if (sessionScope != null) {\n                    if (sessionScope.getSqlMapClient() != null && sessionScope.getSqlMapClient().getClass() == SqlMapClientImpl.class) {\n                        sessionScope.setSqlMapClient(client);\n                    }\n                    if (sessionScope.getSqlMapExecutor() != null && sessionScope.getSqlMapExecutor().getClass() == SqlMapClientImpl.class) {\n                        sessionScope.setSqlMapExecutor(client);\n                    }\n                    if (sessionScope.getSqlMapTxMgr() != null && sessionScope.getSqlMapTxMgr().getClass() == SqlMapClientImpl.class) {\n                        sessionScope.setSqlMapTxMgr(client);\n                    }\n                }\n            } catch (Exception e) {\n                LOG.error(e.getMessage(), e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SpringIbatisBeanNameAutoProxyCreator.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport com.ibatis.sqlmap.client.SqlMapClient;\nimport com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.aop.TargetSource;\nimport org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n@SuppressWarnings({\"serial\", \"deprecation\"})\npublic class SpringIbatisBeanNameAutoProxyCreator extends BeanNameAutoProxyCreator implements SpringIbatisBeanNameAutoProxyCreatorMBean {\n    private static final Log LOG = LogFactory.getLog(SpringIbatisBeanNameAutoProxyCreator.class);\n\n    private List<String> proxyBeanNames = new ArrayList<String>();\n\n    public List<String> getProxyBeanNames() {\n        return proxyBeanNames;\n    }\n\n    public void setProxyBeanNames(List<String> proxyBeanNames) {\n        this.proxyBeanNames = proxyBeanNames;\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    protected Object createProxy(Class beanClass, String beanName, Object[] specificInterceptors,\n                                 TargetSource targetSource) {\n        try {\n            Object target = targetSource.getTarget();\n\n            if (target instanceof SqlMapClientWrapper) {\n                proxyBeanNames.add(beanName);\n                return target;\n            }\n\n            if (target instanceof SqlMapClient) {\n                proxyBeanNames.add(beanName);\n\n                return new SqlMapClientWrapper((ExtendedSqlMapClient) target);\n            }\n\n            return super.createProxy(beanClass, beanName, specificInterceptors, targetSource);\n        } catch (Throwable ex) {\n            LOG.error(ex.getMessage(), ex);\n            return super.createProxy(beanClass, beanName, specificInterceptors, targetSource);\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SpringIbatisBeanNameAutoProxyCreatorMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport java.util.List;\n\npublic interface SpringIbatisBeanNameAutoProxyCreatorMBean {\n    List<String> getProxyBeanNames();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SpringIbatisBeanTypeAutoProxyCreator.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport com.ibatis.sqlmap.client.SqlMapClient;\nimport com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.aop.TargetSource;\nimport org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;\nimport org.springframework.beans.factory.BeanFactory;\nimport org.springframework.beans.factory.FactoryBean;\nimport org.springframework.util.PatternMatchUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 类BeanTypeAutoProxyCreator.java的实现描述：使用配置类型代替Springframework中配置名称的实现\n *\n * @author hualiang.lihl 2011-12-31 上午10:48:20\n */\n@SuppressWarnings(\"deprecation\")\npublic class SpringIbatisBeanTypeAutoProxyCreator extends AbstractAutoProxyCreator implements SpringIbatisBeanTypeAutoProxyCreatorMBean {\n    private static final Log LOG = LogFactory.getLog(SpringIbatisBeanTypeAutoProxyCreator.class);\n\n    private static final long serialVersionUID = -9094985530794052264L;\n\n    private List<String> beanNames = new ArrayList<String>();\n    private final List<String> proxyBeanNames = new ArrayList<String>();\n\n    /**\n     * Identify as bean to proxy if the bean name is in the configured list of names.\n     */\n    @SuppressWarnings(\"rawtypes\")\n    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {\n        for (String mappedName : this.beanNames) {\n            if (FactoryBean.class.isAssignableFrom(beanClass)) {\n                if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {\n                    continue;\n                }\n                mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());\n            }\n            if (isMatch(beanName, mappedName)) {\n                return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;\n            }\n        }\n        return DO_NOT_PROXY;\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    protected Object createProxy(Class beanClass, String beanName, Object[] specificInterceptors,\n                                 TargetSource targetSource) {\n        try {\n            Object target = targetSource.getTarget();\n\n            if (target instanceof SqlMapClientWrapper) {\n                proxyBeanNames.add(beanName);\n                return target;\n            }\n\n            if (target instanceof SqlMapClient) {\n                proxyBeanNames.add(beanName);\n\n                return new SqlMapClientWrapper((ExtendedSqlMapClient) target);\n            }\n\n            return super.createProxy(beanClass, beanName, specificInterceptors, targetSource);\n        } catch (Throwable ex) {\n            LOG.error(ex.getMessage(), ex);\n            return super.createProxy(beanClass, beanName, specificInterceptors, targetSource);\n        }\n    }\n\n    /**\n     * Return if the given bean name matches the mapped name.\n     * <p>\n     * The default implementation checks for \"xxx*\", \"*xxx\" and \"*xxx*\" matches, as well as direct equality. Can be\n     * overridden in subclasses.\n     *\n     * @param beanName   the bean name to check\n     * @param mappedName the name in the configured list of names\n     * @return if the names match\n     * @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)\n     */\n    protected boolean isMatch(String beanName, String mappedName) {\n        return PatternMatchUtils.simpleMatch(mappedName, beanName);\n    }\n\n    public List<String> getBeanNames() {\n        return beanNames;\n    }\n\n    public List<String> getProxyBeanNames() {\n        return proxyBeanNames;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SpringIbatisBeanTypeAutoProxyCreatorMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport java.util.List;\n\npublic interface SpringIbatisBeanTypeAutoProxyCreatorMBean {\n    List<String> getProxyBeanNames();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SqlMapClientImplWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.ibatis.common.util.PaginatedList;\nimport com.ibatis.sqlmap.client.SqlMapExecutor;\nimport com.ibatis.sqlmap.client.SqlMapSession;\nimport com.ibatis.sqlmap.client.event.RowHandler;\nimport com.ibatis.sqlmap.engine.execution.BatchException;\nimport com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;\nimport com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl;\n\nimport java.lang.reflect.Method;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n@SuppressWarnings(\"deprecation\")\npublic class SqlMapClientImplWrapper extends SqlMapClientImpl {\n    private SqlMapClientImpl raw;\n\n    private static Method getLocalSqlMapSessionMethod;\n\n    private ConcurrentMap<String, IbatisStatementInfo> statementInfoMap = new ConcurrentHashMap<String, IbatisStatementInfo>(16, 0.75f, 1);\n\n    public SqlMapClientImplWrapper(SqlMapClientImpl raw) {\n        super(raw.getDelegate());\n        this.raw = raw;\n    }\n\n    public void setLocal(String id, SqlMapExecutor executor) {\n        IbatisStatementInfo stmtInfo = statementInfoMap.get(id);\n\n        if (stmtInfo != null) {\n            JdbcSqlStat.setContextSqlName(stmtInfo.getId());\n            JdbcSqlStat.setContextSqlFile(stmtInfo.getResource());\n            return;\n        }\n\n        Object statement = null;\n        if (executor instanceof SqlMapSessionImpl) {\n            statement = ((SqlMapSessionImpl) executor).getMappedStatement(id);\n        }\n\n        if (executor instanceof SqlMapClientImpl) {\n            statement = ((SqlMapClientImpl) executor).getMappedStatement(id);\n        }\n\n        if (statement == null) {\n            return;\n        }\n\n        String stmtId = IbatisUtils.getId(statement);\n        String stmtResource = IbatisUtils.getResource(statement);\n        stmtInfo = new IbatisStatementInfo(stmtId, stmtResource);\n        statementInfoMap.putIfAbsent(id, stmtInfo);\n\n        JdbcSqlStat.setContextSqlName(stmtId);\n        JdbcSqlStat.setContextSqlFile(stmtResource);\n    }\n\n    protected SqlMapSessionWrapper getLocalSqlMapSessionWrapper() {\n        try {\n            if (getLocalSqlMapSessionMethod == null) {\n                getLocalSqlMapSessionMethod = raw.getClass().getDeclaredMethod(\n                        \"getLocalSqlMapSession\");\n                getLocalSqlMapSessionMethod.setAccessible(true);\n            }\n            SqlMapSessionImpl sessionImpl = (SqlMapSessionImpl) getLocalSqlMapSessionMethod\n                    .invoke(raw);\n            IbatisUtils.set(sessionImpl, this);\n            return new SqlMapSessionWrapper(raw, sessionImpl);\n        } catch (Exception e) {\n            throw new IllegalStateException(e.getMessage(), e);\n        }\n    }\n\n    public SqlMapSession openSession(Connection conn) {\n        SqlMapSession session = raw.openSession(conn);\n        IbatisUtils.setClientImpl(session, this);\n        return new SqlMapSessionWrapper(raw, session);\n    }\n\n    public SqlMapSession getSession() {\n        SqlMapSession session = raw.getSession();\n        IbatisUtils.setClientImpl(session, this);\n        return new SqlMapSessionWrapper(raw, session);\n    }\n\n    // /////\n    public Object insert(String id, Object param) throws SQLException {\n        return getLocalSqlMapSessionWrapper().insert(id, param);\n    }\n\n    public Object insert(String id) throws SQLException {\n        return getLocalSqlMapSessionWrapper().insert(id);\n    }\n\n    public int update(String id, Object param) throws SQLException {\n        return getLocalSqlMapSessionWrapper().update(id, param);\n    }\n\n    public int update(String id) throws SQLException {\n        return getLocalSqlMapSessionWrapper().update(id);\n    }\n\n    public int delete(String id, Object param) throws SQLException {\n        return getLocalSqlMapSessionWrapper().delete(id, param);\n    }\n\n    public int delete(String id) throws SQLException {\n        return getLocalSqlMapSessionWrapper().delete(id);\n    }\n\n    public Object queryForObject(String id, Object paramObject)\n            throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForObject(id, paramObject);\n    }\n\n    public Object queryForObject(String id) throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForObject(id);\n    }\n\n    public Object queryForObject(String id, Object paramObject,\n                                 Object resultObject) throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForObject(id, paramObject,\n                resultObject);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id, Object paramObject) throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForList(id, paramObject);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id) throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForList(id);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id, Object paramObject, int skip, int max)\n            throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForList(id, paramObject,\n                skip, max);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id, int skip, int max) throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForList(id, skip, max);\n    }\n\n    /**\n     * @deprecated All paginated list features have been deprecated\n     */\n    public PaginatedList queryForPaginatedList(String id, Object paramObject,\n                                               int pageSize) throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForPaginatedList(id,\n                paramObject, pageSize);\n    }\n\n    /**\n     * @deprecated All paginated list features have been deprecated\n     */\n    public PaginatedList queryForPaginatedList(String id, int pageSize)\n            throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForPaginatedList(id,\n                pageSize);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public Map queryForMap(String id, Object paramObject, String keyProp)\n            throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForMap(id, paramObject,\n                keyProp);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public Map queryForMap(String id, Object paramObject, String keyProp,\n                           String valueProp) throws SQLException {\n        return getLocalSqlMapSessionWrapper().queryForMap(id, paramObject,\n                keyProp, valueProp);\n    }\n\n    public void queryWithRowHandler(String id, Object paramObject,\n                                    RowHandler rowHandler) throws SQLException {\n        getLocalSqlMapSessionWrapper().queryWithRowHandler(id, paramObject,\n                rowHandler);\n    }\n\n    public void queryWithRowHandler(String id, RowHandler rowHandler)\n            throws SQLException {\n        getLocalSqlMapSessionWrapper().queryWithRowHandler(id, rowHandler);\n    }\n\n    public void startTransaction() throws SQLException {\n        getLocalSqlMapSessionWrapper().startTransaction();\n    }\n\n    public void startTransaction(int transactionIsolation) throws SQLException {\n        getLocalSqlMapSessionWrapper().startTransaction(transactionIsolation);\n    }\n\n    public void commitTransaction() throws SQLException {\n        getLocalSqlMapSessionWrapper().commitTransaction();\n    }\n\n    public void endTransaction() throws SQLException {\n        try {\n            getLocalSqlMapSessionWrapper().endTransaction();\n        } finally {\n            getLocalSqlMapSessionWrapper().close();\n        }\n    }\n\n    public void startBatch() throws SQLException {\n        getLocalSqlMapSessionWrapper().startBatch();\n    }\n\n    public int executeBatch() throws SQLException {\n        return getLocalSqlMapSessionWrapper().executeBatch();\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List executeBatchDetailed() throws SQLException, BatchException {\n        return getLocalSqlMapSessionWrapper().executeBatchDetailed();\n    }\n\n    public void setUserConnection(Connection connection) throws SQLException {\n        try {\n            getLocalSqlMapSessionWrapper().setUserConnection(connection);\n        } finally {\n            if (connection == null) {\n                getLocalSqlMapSessionWrapper().close();\n            }\n        }\n    }\n\n    public static class IbatisStatementInfo {\n        private final String id;\n        private final String resource;\n\n        public IbatisStatementInfo(String id, String resource) {\n            this.id = id;\n            this.resource = resource;\n        }\n\n        public String getId() {\n            return id;\n        }\n\n        public String getResource() {\n            return resource;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SqlMapClientWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport com.ibatis.sqlmap.client.SqlMapClient;\nimport com.ibatis.sqlmap.client.SqlMapSession;\nimport com.ibatis.sqlmap.engine.execution.SqlExecutor;\nimport com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;\nimport com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;\nimport com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactory;\nimport com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\n@SuppressWarnings(\"deprecation\")\npublic class SqlMapClientWrapper extends SqlMapExecutorWrapper implements SqlMapClient, ExtendedSqlMapClient {\n    protected final ExtendedSqlMapClient client;\n\n    public SqlMapClientWrapper(ExtendedSqlMapClient client) {\n        super(client, client);\n        this.client = client;\n\n    }\n\n    public ExtendedSqlMapClient getClient() {\n        return this.client;\n    }\n\n    public void startTransaction() throws SQLException {\n        client.startTransaction();\n    }\n\n    public void startTransaction(int transactionIsolation) throws SQLException {\n        client.startTransaction(transactionIsolation);\n    }\n\n    public void commitTransaction() throws SQLException {\n        client.commitTransaction();\n    }\n\n    public void endTransaction() throws SQLException {\n        client.endTransaction();\n    }\n\n    public void setUserConnection(Connection connection) throws SQLException {\n        client.setUserConnection(connection);\n    }\n\n    public Connection getUserConnection() throws SQLException {\n        return client.getUserConnection();\n    }\n\n    public Connection getCurrentConnection() throws SQLException {\n        return client.getCurrentConnection();\n    }\n\n    public DataSource getDataSource() {\n        return client.getDataSource();\n    }\n\n    public SqlMapSession openSession() {\n        SqlMapSession session = client.openSession();\n        IbatisUtils.setClientImpl(session, clientImplWrapper);\n        return new SqlMapSessionWrapper(client, session);\n    }\n\n    public SqlMapSession openSession(Connection conn) {\n        SqlMapSession session = client.openSession(conn);\n        IbatisUtils.setClientImpl(session, clientImplWrapper);\n        return new SqlMapSessionWrapper(client, session);\n    }\n\n    public SqlMapSession getSession() {\n        SqlMapSession session = client.getSession();\n        IbatisUtils.setClientImpl(session, clientImplWrapper);\n        return new SqlMapSessionWrapper(client, session);\n    }\n\n    public void flushDataCache() {\n        client.flushDataCache();\n    }\n\n    public void flushDataCache(String cacheId) {\n        client.flushDataCache(cacheId);\n    }\n\n    public MappedStatement getMappedStatement(String id) {\n        return client.getMappedStatement(id);\n    }\n\n    public boolean isLazyLoadingEnabled() {\n        return client.isLazyLoadingEnabled();\n    }\n\n    public boolean isEnhancementEnabled() {\n        return client.isEnhancementEnabled();\n    }\n\n    public SqlExecutor getSqlExecutor() {\n        return client.getSqlExecutor();\n    }\n\n    public SqlMapExecutorDelegate getDelegate() {\n        return client.getDelegate();\n    }\n\n    public ResultObjectFactory getResultObjectFactory() {\n        return client.getResultObjectFactory();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SqlMapExecutorWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport com.ibatis.common.util.PaginatedList;\nimport com.ibatis.sqlmap.client.SqlMapExecutor;\nimport com.ibatis.sqlmap.client.event.RowHandler;\nimport com.ibatis.sqlmap.engine.execution.BatchException;\nimport com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;\nimport com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;\n\nimport java.sql.SQLException;\nimport java.util.List;\nimport java.util.Map;\n\n@SuppressWarnings(\"deprecation\")\npublic class SqlMapExecutorWrapper implements SqlMapExecutor {\n    private SqlMapExecutor executor;\n\n    protected final SqlMapClientImpl clientImpl;\n    protected final SqlMapClientImplWrapper clientImplWrapper;\n\n    public SqlMapExecutorWrapper(ExtendedSqlMapClient client, SqlMapExecutor executor) {\n        this.executor = executor;\n\n        this.clientImpl = client.getClass() == SqlMapClientImpl.class ? (SqlMapClientImpl) client : null;\n        this.clientImplWrapper = clientImpl != null ? new SqlMapClientImplWrapper(clientImpl) : null;\n    }\n\n    public Object insert(String id, Object parameterObject) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        return executor.insert(id, parameterObject);\n    }\n\n    public Object insert(String id) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        return executor.insert(id);\n    }\n\n    public int update(String id, Object parameterObject) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        return executor.update(id, parameterObject);\n    }\n\n    public int update(String id) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.update(id);\n    }\n\n    public int delete(String id, Object parameterObject) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.delete(id, parameterObject);\n    }\n\n    public int delete(String id) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.delete(id);\n    }\n\n    public Object queryForObject(String id, Object parameterObject) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForObject(id, parameterObject);\n    }\n\n    public Object queryForObject(String id) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForObject(id);\n    }\n\n    public Object queryForObject(String id, Object parameterObject, Object resultObject) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForObject(id, parameterObject, resultObject);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id, Object parameterObject) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForList(id, parameterObject);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForList(id);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id, Object parameterObject, int skip, int max) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForList(id, parameterObject, skip, max);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List queryForList(String id, int skip, int max) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForList(id, skip, max);\n    }\n\n    public void queryWithRowHandler(String id, Object parameterObject, RowHandler rowHandler) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        executor.queryWithRowHandler(id, parameterObject, rowHandler);\n    }\n\n    public void queryWithRowHandler(String id, RowHandler rowHandler) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        executor.queryWithRowHandler(id, rowHandler);\n    }\n\n    public PaginatedList queryForPaginatedList(String id, Object parameterObject, int pageSize) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForPaginatedList(id, parameterObject, pageSize);\n    }\n\n    public PaginatedList queryForPaginatedList(String id, int pageSize) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForPaginatedList(id, pageSize);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public Map queryForMap(String id, Object parameterObject, String keyProp) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForMap(id, parameterObject, keyProp);\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public Map queryForMap(String id, Object parameterObject, String keyProp, String valueProp) throws SQLException {\n        clientImplWrapper.setLocal(id, executor);\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n\n        return executor.queryForMap(id, parameterObject, keyProp, valueProp);\n    }\n\n    public void startBatch() throws SQLException {\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        executor.startBatch();\n    }\n\n    public int executeBatch() throws SQLException {\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        return executor.executeBatch();\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public List executeBatchDetailed() throws SQLException, BatchException {\n        IbatisUtils.setClientImpl(executor, clientImplWrapper);\n        return executor.executeBatchDetailed();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/ibatis/SqlMapSessionWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.ibatis;\n\nimport com.ibatis.sqlmap.client.SqlMapSession;\nimport com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\n@SuppressWarnings(\"deprecation\")\npublic class SqlMapSessionWrapper extends SqlMapExecutorWrapper implements SqlMapSession {\n    private SqlMapSession session;\n\n    public SqlMapSessionWrapper(ExtendedSqlMapClient client, SqlMapSession session) {\n        super(client, session);\n        this.session = session;\n    }\n\n    public void startTransaction() throws SQLException {\n        session.startTransaction();\n    }\n\n    public void startTransaction(int transactionIsolation) throws SQLException {\n        session.startTransaction(transactionIsolation);\n    }\n\n    public void commitTransaction() throws SQLException {\n        session.commitTransaction();\n    }\n\n    public void endTransaction() throws SQLException {\n        session.endTransaction();\n    }\n\n    public void setUserConnection(Connection connection) throws SQLException {\n        session.setUserConnection(connection);\n    }\n\n    @Deprecated\n    public Connection getUserConnection() throws SQLException {\n        return session.getUserConnection();\n    }\n\n    public Connection getCurrentConnection() throws SQLException {\n        return session.getCurrentConnection();\n    }\n\n    public DataSource getDataSource() {\n        return session.getDataSource();\n    }\n\n    public void close() {\n        session.close();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/jakarta/AbstractWebStatImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.jakarta;\n\nimport com.alibaba.druid.filter.stat.StatFilterContextListenerAdapter;\nimport com.alibaba.druid.support.http.stat.WebAppStat;\nimport com.alibaba.druid.support.http.stat.WebRequestStat;\nimport com.alibaba.druid.support.http.stat.WebSessionStat;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.DruidWebUtils;\nimport jakarta.servlet.http.Cookie;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpSession;\n\npublic class AbstractWebStatImpl {\n    private static final Log LOG = LogFactory.getLog(AbstractWebStatImpl.class);\n\n    public static final int DEFAULT_MAX_STAT_SESSION_COUNT = 1000 * 1;\n\n    protected WebAppStat webAppStat;\n\n    protected boolean sessionStatEnable = true;\n    protected int sessionStatMaxCount = DEFAULT_MAX_STAT_SESSION_COUNT;\n    protected boolean createSession;\n    protected boolean profileEnable;\n\n    protected String contextPath;\n\n    protected String principalSessionName;\n    protected String principalCookieName;\n    protected String realIpHeader;\n\n    protected WebStatFilterContextListener statFilterContextListener = new WebStatFilterContextListener();\n\n    public boolean isSessionStatEnable() {\n        return sessionStatEnable;\n    }\n\n    public void setSessionStatEnable(boolean sessionStatEnable) {\n        this.sessionStatEnable = sessionStatEnable;\n    }\n\n    public boolean isProfileEnable() {\n        return profileEnable;\n    }\n\n    public void setProfileEnable(boolean profileEnable) {\n        this.profileEnable = profileEnable;\n    }\n\n    public String getContextPath() {\n        return contextPath;\n    }\n\n    public int getSessionStatMaxCount() {\n        return sessionStatMaxCount;\n    }\n\n    public String getRequestURI(HttpServletRequest request) {\n        return request.getRequestURI();\n    }\n\n    public String getPrincipalSessionName() {\n        return principalSessionName;\n    }\n\n    public String getPrincipalCookieName() {\n        return principalCookieName;\n    }\n\n    public WebSessionStat getSessionStat(HttpServletRequest request) {\n        if (!isSessionStatEnable()) {\n            return null;\n        }\n\n        WebSessionStat sessionStat = null;\n        String sessionId = getSessionId(request);\n\n        if (sessionId != null) {\n            sessionStat = webAppStat.getSessionStat(sessionId, true);\n        }\n\n        if (sessionStat != null) {\n            long currentMillis = System.currentTimeMillis();\n\n            String userAgent = request.getHeader(\"user-agent\");\n\n            if (sessionStat.getCreateTimeMillis() == -1L) {\n                HttpSession session = request.getSession(false);\n\n                if (session != null) {\n                    sessionStat.setCreateTimeMillis(session.getCreationTime());\n                } else {\n                    sessionStat.setCreateTimeMillis(currentMillis);\n                }\n\n                webAppStat.computeUserAgent(userAgent);\n                webAppStat.incrementSessionCount();\n            }\n\n            sessionStat.setUserAgent(userAgent);\n\n            String ip = getRemoteAddress(request);\n\n            sessionStat.addRemoteAddress(ip);\n        }\n\n        return sessionStat;\n    }\n\n    protected String getRemoteAddress(HttpServletRequest request) {\n        String ip = null;\n        if (this.realIpHeader != null && this.realIpHeader.length() != 0) {\n            ip = request.getHeader(realIpHeader);\n        }\n        if (ip == null || ip.length() == 0) {\n            ip = DruidWebUtils.getRemoteAddr(request);\n        }\n        return ip;\n    }\n\n    public String getSessionId(HttpServletRequest httpRequest) {\n        String sessionId = null;\n\n        HttpSession session = httpRequest.getSession(createSession);\n        if (session != null) {\n            sessionId = session.getId();\n        } else {\n            Cookie[] cookies = httpRequest.getCookies();\n            if (cookies != null) {\n                for (Cookie cookie : cookies) {\n                    if (cookie.getName().equals(\"JSESSIONID\")) {\n                        sessionId = cookie.getValue();\n                        break;\n                    }\n                }\n\n                if (sessionId == null) {\n                    for (Cookie cookie : cookies) {\n                        if (cookie.getName().equals(\"JWT-SESSION\")) {\n                            sessionId = cookie.getValue();\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        return sessionId;\n    }\n\n    public String getPrincipal(HttpServletRequest httpRequest) {\n        if (principalSessionName != null) {\n            HttpSession session = httpRequest.getSession(createSession);\n            if (session == null) {\n                return null;\n            }\n\n            Object sessionValue = null;\n\n            try {\n                sessionValue = session.getAttribute(principalSessionName);\n            } catch (Exception ex) {\n                if (LOG.isErrorEnabled()) {\n                    LOG.error(\"session.getAttribute error\", ex);\n                }\n            }\n\n            if (sessionValue == null) {\n                return null;\n            }\n\n            return sessionValue.toString();\n        }\n\n        if (principalCookieName != null && httpRequest.getCookies() != null) {\n            for (Cookie cookie : httpRequest.getCookies()) {\n                if (principalCookieName.equals(cookie.getName())) {\n                    return cookie.getValue();\n                }\n            }\n        }\n\n        return null;\n    }\n\n    public static class WebStatFilterContextListener extends StatFilterContextListenerAdapter {\n        @Override\n        public void addUpdateCount(int updateCount) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.addJdbcUpdateCount(updateCount);\n            }\n        }\n\n        @Override\n        public void addFetchRowCount(int fetchRowCount) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.addJdbcFetchRowCount(fetchRowCount);\n            }\n        }\n\n        @Override\n        public void executeBefore(String sql, boolean inTransaction) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcExecuteCount();\n            }\n        }\n\n        @Override\n        public void executeAfter(String sql, long nanos, Throwable error) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.addJdbcExecuteTimeNano(nanos);\n                if (error != null) {\n                    reqStat.incrementJdbcExecuteErrorCount();\n                }\n            }\n        }\n\n        @Override\n        public void commit() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcCommitCount();\n            }\n        }\n\n        @Override\n        public void rollback() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcRollbackCount();\n            }\n        }\n\n        @Override\n        public void pool_connect() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcPoolConnectCount();\n            }\n        }\n\n        @Override\n        public void pool_close(long nanos) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcPoolCloseCount();\n            }\n        }\n\n        @Override\n        public void resultSet_open() {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcResultSetOpenCount();\n            }\n        }\n\n        @Override\n        public void resultSet_close(long nanos) {\n            WebRequestStat reqStat = WebRequestStat.current();\n            if (reqStat != null) {\n                reqStat.incrementJdbcResultSetCloseCount();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/jakarta/MonitorClientContextListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.jakarta;\n\nimport com.alibaba.druid.support.monitor.MonitorClient;\nimport jakarta.servlet.ServletContextEvent;\nimport jakarta.servlet.ServletContextListener;\n\npublic class MonitorClientContextListener implements ServletContextListener {\n    private MonitorClient client;\n\n    @Override\n    public void contextInitialized(ServletContextEvent event) {\n        client = new MonitorClient();\n        client.start();\n    }\n\n    @Override\n    public void contextDestroyed(ServletContextEvent event) {\n        if (client != null) {\n            client.stop();\n            this.client = null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/jakarta/ResourceServlet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.jakarta;\n\nimport com.alibaba.druid.support.http.util.IPAddress;\nimport com.alibaba.druid.support.http.util.IPRange;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.util.Utils;\nimport jakarta.servlet.ServletException;\nimport jakarta.servlet.http.HttpServlet;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport jakarta.servlet.http.HttpSession;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\n@SuppressWarnings(\"serial\")\npublic abstract class ResourceServlet extends HttpServlet {\n    private static final Log LOG = LogFactory.getLog(ResourceServlet.class);\n\n    public static final String SESSION_USER_KEY = \"druid-user\";\n    public static final String PARAM_NAME_USERNAME = \"loginUsername\";\n    public static final String PARAM_NAME_PASSWORD = \"loginPassword\";\n    public static final String PARAM_NAME_ALLOW = \"allow\";\n    public static final String PARAM_NAME_DENY = \"deny\";\n    public static final String PARAM_REMOTE_ADDR = \"remoteAddress\";\n\n    protected final ResourceHandler handler;\n\n    public ResourceServlet(String resourcePath) {\n        handler = new ResourceHandler(resourcePath);\n    }\n\n    public void init() throws ServletException {\n        initAuthEnv();\n    }\n\n    private void initAuthEnv() {\n        String paramUserName = getInitParameter(PARAM_NAME_USERNAME);\n        if (!StringUtils.isEmpty(paramUserName)) {\n            handler.username = paramUserName;\n        }\n\n        String paramPassword = getInitParameter(PARAM_NAME_PASSWORD);\n        if (!StringUtils.isEmpty(paramPassword)) {\n            handler.password = paramPassword;\n        }\n\n        String paramRemoteAddressHeader = getInitParameter(PARAM_REMOTE_ADDR);\n        if (!StringUtils.isEmpty(paramRemoteAddressHeader)) {\n            handler.remoteAddressHeader = paramRemoteAddressHeader;\n        }\n\n        try {\n            String param = getInitParameter(PARAM_NAME_ALLOW);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.allowList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, allow : \" + getInitParameter(PARAM_NAME_ALLOW);\n            LOG.error(msg, e);\n        }\n\n        try {\n            String param = getInitParameter(PARAM_NAME_DENY);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.denyList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, deny : \" + getInitParameter(PARAM_NAME_DENY);\n            LOG.error(msg, e);\n        }\n    }\n\n    public boolean isPermittedRequest(String remoteAddress) {\n        return handler.isPermittedRequest(remoteAddress);\n    }\n\n    protected String getFilePath(String fileName) {\n        return handler.resourcePath + fileName;\n    }\n\n    protected void returnResourceFile(String fileName, String uri, HttpServletResponse response)\n            throws ServletException,\n            IOException {\n        handler.returnResourceFile(fileName, uri, response);\n    }\n\n    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        String servletPath = request.getServletPath();\n        handler.service(request, response, servletPath, new ProcessCallback() {\n            @Override\n            public String process(String url) {\n                return ResourceServlet.this.process(url);\n            }\n        });\n    }\n\n    public boolean ContainsUser(HttpServletRequest request) {\n        return handler.containsUser(request);\n    }\n\n    public boolean checkLoginParam(HttpServletRequest request) {\n        return handler.checkLoginParam(request);\n    }\n\n    public boolean isRequireAuth() {\n        return handler.isRequireAuth();\n    }\n\n    public boolean isPermittedRequest(HttpServletRequest request) {\n        return handler.isPermittedRequest(request);\n    }\n\n    protected String getRemoteAddress(HttpServletRequest request) {\n        return handler.getRemoteAddress(request);\n    }\n\n    protected abstract String process(String url);\n\n    public static interface ProcessCallback {\n        String process(String url);\n    }\n\n    public static class ResourceHandler {\n        protected String username;\n        protected String password;\n\n        protected List<IPRange> allowList = new ArrayList<IPRange>();\n        protected List<IPRange> denyList = new ArrayList<IPRange>();\n\n        protected String resourcePath;\n\n        protected String remoteAddressHeader;\n\n        public ResourceHandler(String resourcePath) {\n            this.resourcePath = resourcePath;\n        }\n\n        protected void returnResourceFile(String fileName, String uri, HttpServletResponse response)\n                throws ServletException,\n                IOException {\n            String filePath = getFilePath(fileName);\n\n            if (filePath.endsWith(\".html\")) {\n                response.setContentType(\"text/html; charset=utf-8\");\n            }\n            if (fileName.endsWith(\".jpg\")) {\n                byte[] bytes = Utils.readByteArrayFromResource(filePath);\n                if (bytes != null) {\n                    response.getOutputStream().write(bytes);\n                }\n\n                return;\n            }\n\n            String text = Utils.readFromResource(filePath);\n            if (text == null) {\n                return;\n            }\n\n            // 设置http响应头，以便在浏览器端缓存静态资源,\n            response.setHeader(\"Cache-Control\", \"max-age=36000\");\n            if (fileName.endsWith(\".css\")) {\n                response.setContentType(\"text/css;charset=utf-8\");\n            } else if (fileName.endsWith(\".js\")) {\n                response.setContentType(\"text/javascript;charset=utf-8\");\n            }\n            response.getWriter().write(text);\n        }\n\n        protected String getFilePath(String fileName) {\n            return resourcePath + fileName;\n        }\n\n        public boolean checkLoginParam(HttpServletRequest request) {\n            String usernameParam = request.getParameter(PARAM_NAME_USERNAME);\n            String passwordParam = request.getParameter(PARAM_NAME_PASSWORD);\n            if (null == username || null == password) {\n                return false;\n            } else if (username.equals(usernameParam) && password.equals(passwordParam)) {\n                return true;\n            }\n            return false;\n        }\n\n        protected String getRemoteAddress(HttpServletRequest request) {\n            String remoteAddress = null;\n\n            if (remoteAddressHeader != null) {\n                remoteAddress = request.getHeader(remoteAddressHeader);\n            }\n\n            if (remoteAddress == null) {\n                remoteAddress = request.getRemoteAddr();\n            }\n\n            return remoteAddress;\n        }\n\n        public boolean containsUser(HttpServletRequest request) {\n            HttpSession session = request.getSession(false);\n            return session != null && session.getAttribute(SESSION_USER_KEY) != null;\n        }\n\n        public boolean isRequireAuth() {\n            return username != null;\n        }\n\n        public boolean isPermittedRequest(HttpServletRequest request) {\n            String remoteAddress = getRemoteAddress(request);\n            return isPermittedRequest(remoteAddress);\n        }\n\n        public boolean isPermittedRequest(String remoteAddress) {\n            boolean ipV6 = remoteAddress != null && remoteAddress.indexOf(':') != -1;\n\n            if (ipV6) {\n                return \"0:0:0:0:0:0:0:1\".equals(remoteAddress) || (denyList.isEmpty() && allowList.isEmpty());\n            }\n\n            IPAddress ipAddress = new IPAddress(remoteAddress);\n\n            for (IPRange range : denyList) {\n                if (range.isIPAddressInRange(ipAddress)) {\n                    return false;\n                }\n            }\n\n            if (allowList.size() > 0) {\n                for (IPRange range : allowList) {\n                    if (range.isIPAddressInRange(ipAddress)) {\n                        return true;\n                    }\n                }\n\n                return false;\n            }\n\n            return true;\n        }\n\n        public void service(\n                HttpServletRequest request,\n                HttpServletResponse response,\n                String servletPath,\n                ProcessCallback processCallback\n        ) throws ServletException, IOException {\n            String contextPath = request.getContextPath();\n            String requestURI = request.getRequestURI();\n\n            response.setCharacterEncoding(\"utf-8\");\n\n            if (contextPath == null) { // root context\n                contextPath = \"\";\n            }\n            String uri = contextPath + servletPath;\n            String path = requestURI.substring(contextPath.length() + servletPath.length());\n\n            if (!isPermittedRequest(request)) {\n                path = \"/nopermit.html\";\n                returnResourceFile(path, uri, response);\n                return;\n            }\n\n            if (\"/submitLogin\".equals(path)) {\n                String usernameParam = request.getParameter(PARAM_NAME_USERNAME);\n                String passwordParam = request.getParameter(PARAM_NAME_PASSWORD);\n                if (username.equals(usernameParam) && password.equals(passwordParam)) {\n                    request.getSession().setAttribute(SESSION_USER_KEY, username);\n                    response.getWriter().print(\"success\");\n                } else {\n                    response.getWriter().print(\"error\");\n                }\n                return;\n            }\n\n            if (isRequireAuth() //\n                    && !containsUser(request)//\n                    && !checkLoginParam(request)//\n                    && !(\"/login.html\".equals(path) //\n                    || path.startsWith(\"/css\")//\n                    || path.startsWith(\"/js\") //\n                    || path.startsWith(\"/img\"))) {\n                if (contextPath.equals(\"\") || contextPath.equals(\"/\")) {\n                    response.sendRedirect(\"/druid/login.html\");\n                } else {\n                    if (\"\".equals(path)) {\n                        response.sendRedirect(\"druid/login.html\");\n                    } else {\n                        response.sendRedirect(\"login.html\");\n                    }\n                }\n                return;\n            }\n\n            if (\"\".equals(path) || \"/\".equals(path)) {\n                returnResourceFile(\"/index.html\", uri, response);\n                return;\n            }\n\n            if (path.contains(\".json\")) {\n                String fullUrl = path;\n                if (request.getQueryString() != null && request.getQueryString().length() > 0) {\n                    fullUrl += \"?\" + request.getQueryString();\n                }\n                response.getWriter().print(processCallback.process(fullUrl));\n                return;\n            }\n\n            // find file in resources path\n\n            returnResourceFile(path, uri, response);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/jakarta/StatViewFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.jakarta;\n\nimport com.alibaba.druid.stat.DruidStatService;\nimport com.alibaba.druid.support.http.util.IPRange;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.StringUtils;\nimport jakarta.servlet.*;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\n\nimport java.io.IOException;\n\nimport static com.alibaba.druid.support.jakarta.ResourceServlet.*;\n\npublic class StatViewFilter implements Filter {\n    public static final String PARAM_NAME_PATH = \"path\";\n    private static final Log LOG = LogFactory.getLog(StatViewFilter.class);\n    private String servletPath = \"/druid\";\n    private String resourcePath = \"support/http/resources\";\n\n    private ResourceHandler handler;\n    private DruidStatService statService = DruidStatService.getInstance();\n\n    @Override\n    public void init(FilterConfig config) throws ServletException {\n        if (config == null) {\n            return;\n        }\n\n        String path = config.getInitParameter(PARAM_NAME_PATH);\n        if (path != null && !path.isEmpty()) {\n            this.servletPath = path;\n        }\n\n        handler = new ResourceHandler(resourcePath);\n\n        String paramUserName = config.getInitParameter(PARAM_NAME_USERNAME);\n        if (!StringUtils.isEmpty(paramUserName)) {\n            handler.username = paramUserName;\n        }\n\n        String paramPassword = config.getInitParameter(PARAM_NAME_PASSWORD);\n        if (!StringUtils.isEmpty(paramPassword)) {\n            handler.password = paramPassword;\n        }\n\n        String paramRemoteAddressHeader = config.getInitParameter(PARAM_REMOTE_ADDR);\n        if (!StringUtils.isEmpty(paramRemoteAddressHeader)) {\n            handler.remoteAddressHeader = paramRemoteAddressHeader;\n        }\n\n        try {\n            String param = config.getInitParameter(PARAM_NAME_ALLOW);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.allowList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, allow : \" + config.getInitParameter(PARAM_NAME_ALLOW);\n            LOG.error(msg, e);\n        }\n\n        try {\n            String param = config.getInitParameter(PARAM_NAME_DENY);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                String[] items = param.split(\",\");\n\n                for (String item : items) {\n                    if (item == null || item.length() == 0) {\n                        continue;\n                    }\n\n                    IPRange ipRange = new IPRange(item);\n                    handler.denyList.add(ipRange);\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, deny : \" + config.getInitParameter(PARAM_NAME_DENY);\n            LOG.error(msg, e);\n        }\n    }\n\n    @Override\n    public void doFilter(ServletRequest request,\n                         ServletResponse response,\n                         FilterChain chain) throws IOException, ServletException {\n        HttpServletRequest httpReq = (HttpServletRequest) request;\n        HttpServletResponse httpResp = (HttpServletResponse) response;\n        String contextPath = ((HttpServletRequest) request).getContextPath();\n\n        String requestURI = httpReq.getRequestURI();\n        if (!contextPath.equals(\"\")) {\n            requestURI = requestURI.substring(((HttpServletRequest) request).getContextPath().length());\n        }\n        if (requestURI.equals(servletPath)) {\n            httpResp.sendRedirect(httpReq.getRequestURI() + '/');\n            return;\n        }\n\n        handler.service(httpReq, httpResp, servletPath, new ProcessCallback() {\n            @Override\n            public String process(String url) {\n                return statService.service(url);\n            }\n        });\n    }\n\n    @Override\n    public void destroy() {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/jakarta/StatViewServlet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.jakarta;\n\nimport com.alibaba.druid.stat.DruidStatService;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport jakarta.servlet.ServletException;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\n\nimport javax.management.MBeanServerConnection;\nimport javax.management.ObjectName;\nimport javax.management.remote.JMXConnector;\nimport javax.management.remote.JMXConnectorFactory;\nimport javax.management.remote.JMXServiceURL;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 注意：避免直接调用Druid相关对象例如DruidDataSource等，相关调用要到DruidStatManagerFacade里用反射实现\n *\n * @author sandzhang[sandzhangtoo@gmail.com]\n */\npublic class StatViewServlet extends ResourceServlet {\n    private static final Log LOG = LogFactory.getLog(StatViewServlet.class);\n\n    private static final long serialVersionUID = 1L;\n\n    public static final String PARAM_NAME_RESET_ENABLE = \"resetEnable\";\n\n    public static final String PARAM_NAME_JMX_URL = \"jmxUrl\";\n    public static final String PARAM_NAME_JMX_USERNAME = \"jmxUsername\";\n    public static final String PARAM_NAME_JMX_PASSWORD = \"jmxPassword\";\n\n    private DruidStatService statService = DruidStatService.getInstance();\n\n    /**\n     * web.xml中配置的jmx的连接地址\n     */\n    private String jmxUrl;\n    /**\n     * web.xml中配置的jmx的用户名\n     */\n    private String jmxUsername;\n    /**\n     * web.xml中配置的jmx的密码\n     */\n    private String jmxPassword;\n    private MBeanServerConnection conn;\n\n    public StatViewServlet() {\n        super(\"support/http/resources\");\n    }\n\n    public void init() throws ServletException {\n        super.init();\n\n        try {\n            String param = getInitParameter(PARAM_NAME_RESET_ENABLE);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                boolean resetEnable = Boolean.parseBoolean(param);\n                statService.setResetEnable(resetEnable);\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config error, resetEnable : \" + getInitParameter(PARAM_NAME_RESET_ENABLE);\n            LOG.error(msg, e);\n        }\n\n        // 获取jmx的连接配置信息\n        String param = readInitParam(PARAM_NAME_JMX_URL);\n        if (param != null) {\n            jmxUrl = param;\n            jmxUsername = readInitParam(PARAM_NAME_JMX_USERNAME);\n            jmxPassword = readInitParam(PARAM_NAME_JMX_PASSWORD);\n            try {\n                initJmxConn();\n            } catch (IOException e) {\n                LOG.error(\"init jmx connection error\", e);\n            }\n        }\n\n    }\n\n    /**\n     * 读取servlet中的配置参数.\n     *\n     * @param key 配置参数名\n     * @return 配置参数值，如果不存在当前配置参数，或者为配置参数长度为0，将返回null\n     */\n    private String readInitParam(String key) {\n        String value = null;\n        try {\n            String param = getInitParameter(key);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() > 0) {\n                    value = param;\n                }\n            }\n        } catch (Exception e) {\n            String msg = \"initParameter config [\" + key + \"] error\";\n            LOG.warn(msg, e);\n        }\n        return value;\n    }\n\n    /**\n     * 初始化jmx连接\n     *\n     * @throws IOException\n     */\n    private void initJmxConn() throws IOException {\n        if (jmxUrl != null) {\n            JMXServiceURL url = new JMXServiceURL(jmxUrl);\n            Map<String, String[]> env = null;\n            if (jmxUsername != null) {\n                env = new HashMap<String, String[]>();\n                String[] credentials = new String[]{jmxUsername, jmxPassword};\n                env.put(JMXConnector.CREDENTIALS, credentials);\n            }\n            JMXConnector jmxc = JMXConnectorFactory.connect(url, env);\n            conn = jmxc.getMBeanServerConnection();\n        }\n    }\n\n    /**\n     * 根据指定的url来获取jmx服务返回的内容.\n     *\n     * @param connetion jmx连接\n     * @param url       url内容\n     * @return the jmx返回的内容\n     * @throws Exception the exception\n     */\n    private String getJmxResult(MBeanServerConnection connetion, String url) throws Exception {\n        ObjectName name = new ObjectName(DruidStatService.MBEAN_NAME);\n\n        String result = (String) conn.invoke(name, \"service\", new String[]{url},\n                new String[]{String.class.getName()});\n        return result;\n    }\n\n    /**\n     * 程序首先判断是否存在jmx连接地址，如果不存在，则直接调用本地的druid服务； 如果存在，则调用远程jmx服务。在进行jmx通信，首先判断一下jmx连接是否已经建立成功，如果已经\n     * 建立成功，则直接进行通信，如果之前没有成功建立，则会尝试重新建立一遍。.\n     *\n     * @param url 要连接的服务地址\n     * @return 调用服务后返回的json字符串\n     */\n    protected String process(String url) {\n        String resp = null;\n        if (jmxUrl == null) {\n            resp = statService.service(url);\n        } else {\n            if (conn == null) {\n                // 连接在初始化时创建失败\n                try {\n                    // 尝试重新连接\n                    initJmxConn();\n                } catch (IOException e) {\n                    LOG.error(\"init jmx connection error\", e);\n                    resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR,\n                            \"init jmx connection error\" + e.getMessage());\n                }\n                if (conn != null) {\n                    // 连接成功\n                    try {\n                        resp = getJmxResult(conn, url);\n                    } catch (Exception e) {\n                        LOG.error(\"get jmx data error\", e);\n                        resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR, \"get data error:\"\n                                + e.getMessage());\n                    }\n                }\n            } else {\n                // 连接成功\n                try {\n                    resp = getJmxResult(conn, url);\n                } catch (Exception e) {\n                    LOG.error(\"get jmx data error\", e);\n                    resp = DruidStatService.returnJSONResult(DruidStatService.RESULT_CODE_ERROR,\n                            \"get data error\" + e.getMessage());\n                }\n            }\n        }\n        return resp;\n    }\n\n    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        String contextPath = request.getContextPath();\n        String servletPath = request.getServletPath();\n        String requestURI = request.getRequestURI();\n\n        response.setCharacterEncoding(\"utf-8\");\n\n        if (contextPath == null) { // root context\n            contextPath = \"\";\n        }\n        String uri = contextPath + servletPath;\n        String path = requestURI.substring(contextPath.length() + servletPath.length());\n\n        if (\"\".equals(path)) {\n            if (contextPath.equals(\"\") || contextPath.equals(\"/\")) {\n                response.sendRedirect(\"/druid/index.html\");\n            } else {\n                response.sendRedirect(\"druid/index.html\");\n            }\n            return;\n        }\n\n        if (\"/\".equals(path)) {\n            response.sendRedirect(\"index.html\");\n            return;\n        }\n\n        super.service(request, response);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/jakarta/WebStatFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.jakarta;\n\nimport com.alibaba.druid.filter.stat.StatFilterContext;\nimport com.alibaba.druid.support.http.stat.*;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.support.profile.ProfileEntryKey;\nimport com.alibaba.druid.support.profile.ProfileEntryReqStat;\nimport com.alibaba.druid.support.profile.Profiler;\nimport com.alibaba.druid.util.DruidWebUtils;\nimport com.alibaba.druid.util.PatternMatcher;\nimport com.alibaba.druid.util.ServletPathMatcher;\nimport jakarta.servlet.*;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport jakarta.servlet.http.HttpServletResponseWrapper;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * 用于配置Web和Druid数据源之间的管理关联监控统计\n *\n * @author wenshao [szujobs@htomail.com]\n * @author Zhangming Qi [qizhanming@gmail.com]\n */\npublic class WebStatFilter extends AbstractWebStatImpl implements Filter {\n    private static final Log LOG = LogFactory.getLog(WebStatFilter.class);\n\n    public static final String PARAM_NAME_PROFILE_ENABLE = \"profileEnable\";\n    public static final String PARAM_NAME_SESSION_STAT_ENABLE = \"sessionStatEnable\";\n    public static final String PARAM_NAME_SESSION_STAT_MAX_COUNT = \"sessionStatMaxCount\";\n    public static final String PARAM_NAME_EXCLUSIONS = \"exclusions\";\n    public static final String PARAM_NAME_PRINCIPAL_SESSION_NAME = \"principalSessionName\";\n    public static final String PARAM_NAME_PRINCIPAL_COOKIE_NAME = \"principalCookieName\";\n    public static final String PARAM_NAME_REAL_IP_HEADER = \"realIpHeader\";\n\n    /**\n     * PatternMatcher used in determining which paths to react to for a given request.\n     */\n    protected final PatternMatcher pathMatcher = ServletPathMatcher.getInstance();\n\n    private Set<String> excludesPattern;\n\n    @Override\n    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,\n            ServletException {\n        HttpServletRequest httpRequest = (HttpServletRequest) request;\n        HttpServletResponse httpResponse = (HttpServletResponse) response;\n        StatHttpServletResponseWrapper responseWrapper = new StatHttpServletResponseWrapper(httpResponse);\n\n        String requestURI = getRequestURI(httpRequest);\n\n        if (isExclusion(requestURI)) {\n            chain.doFilter(request, response);\n            return;\n        }\n\n        long startNano = System.nanoTime();\n        long startMillis = System.currentTimeMillis();\n\n        WebRequestStat requestStat = new WebRequestStat(startNano, startMillis);\n        WebRequestStat.set(requestStat);\n\n        WebSessionStat sessionStat = getSessionStat(httpRequest);\n        webAppStat.beforeInvoke();\n\n        WebURIStat uriStat = webAppStat.getURIStat(requestURI, false);\n\n        if (uriStat == null) {\n            int index = requestURI.indexOf(\";jsessionid=\");\n            if (index != -1) {\n                requestURI = requestURI.substring(0, index);\n                uriStat = webAppStat.getURIStat(requestURI, false);\n            }\n        }\n\n        if (isProfileEnable()) {\n            Profiler.initLocal();\n            Profiler.enter(requestURI, Profiler.PROFILE_TYPE_WEB);\n        }\n\n        // 第一次访问时，uriStat这里为null，是为了防止404攻击。\n        if (uriStat != null) {\n            uriStat.beforeInvoke();\n        }\n\n        // 第一次访问时，sessionId为null，如果缺省sessionCreate=false，sessionStat就为null。\n        if (sessionStat != null) {\n            sessionStat.beforeInvoke();\n        }\n\n        Throwable error = null;\n        try {\n            chain.doFilter(request, responseWrapper);\n        } catch (IOException e) {\n            error = e;\n            throw e;\n        } catch (ServletException e) {\n            error = e;\n            throw e;\n        } catch (RuntimeException e) {\n            error = e;\n            throw e;\n        } catch (Error e) {\n            error = e;\n            throw e;\n        } finally {\n            long endNano = System.nanoTime();\n            requestStat.setEndNano(endNano);\n\n            long nanos = endNano - startNano;\n            webAppStat.afterInvoke(error, nanos);\n\n            if (sessionStat == null) {\n                sessionStat = getSessionStat(httpRequest);\n                if (sessionStat != null) {\n                    sessionStat.beforeInvoke(); // 补偿\n                }\n            }\n\n            if (sessionStat != null) {\n                sessionStat.afterInvoke(error, nanos);\n                sessionStat.setPrincipal(getPrincipal(httpRequest));\n            }\n\n            if (uriStat == null) {\n                int status = responseWrapper.getStatus();\n                if (status == HttpServletResponse.SC_NOT_FOUND) {\n                    String errorUrl = contextPath + \"error_\" + status;\n                    uriStat = webAppStat.getURIStat(errorUrl, true);\n                } else {\n                    uriStat = webAppStat.getURIStat(requestURI, true);\n                }\n\n                if (uriStat != null) {\n                    uriStat.beforeInvoke(); // 补偿调用\n                }\n            }\n\n            if (uriStat != null) {\n                uriStat.afterInvoke(error, nanos);\n            }\n\n            WebRequestStat.set(null);\n\n            if (isProfileEnable()) {\n                Profiler.release(nanos);\n\n                Map<ProfileEntryKey, ProfileEntryReqStat> requestStatsMap = Profiler.getStatsMap();\n                if (uriStat != null) {\n                    uriStat.getProfiletat().record(requestStatsMap);\n                }\n                Profiler.removeLocal();\n            }\n        }\n    }\n\n    public boolean isExclusion(String requestURI) {\n        if (excludesPattern == null || requestURI == null) {\n            return false;\n        }\n\n        if (contextPath != null && requestURI.startsWith(contextPath)) {\n            requestURI = requestURI.substring(contextPath.length());\n            if (!requestURI.startsWith(\"/\")) {\n                requestURI = \"/\" + requestURI;\n            }\n        }\n\n        for (String pattern : excludesPattern) {\n            if (pathMatcher.matches(pattern, requestURI)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public void init(FilterConfig config) throws ServletException {\n        {\n            String exclusions = config.getInitParameter(PARAM_NAME_EXCLUSIONS);\n            if (exclusions != null && exclusions.trim().length() != 0) {\n                excludesPattern = new HashSet<String>(Arrays.asList(exclusions.split(\"\\\\s*,\\\\s*\")));\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_PRINCIPAL_SESSION_NAME);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() != 0) {\n                    this.principalSessionName = param;\n                }\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_PRINCIPAL_COOKIE_NAME);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() != 0) {\n                    this.principalCookieName = param;\n                }\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_SESSION_STAT_ENABLE);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                if (\"true\".equals(param)) {\n                    this.sessionStatEnable = true;\n                } else if (\"false\".equals(param)) {\n                    this.sessionStatEnable = false;\n                } else {\n                    LOG.error(\"WebStatFilter Parameter '\" + PARAM_NAME_SESSION_STAT_ENABLE + \"' config error\");\n                }\n            }\n        }\n\n        {\n            String param = config.getInitParameter(PARAM_NAME_PROFILE_ENABLE);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                if (\"true\".equals(param)) {\n                    this.profileEnable = true;\n                } else if (\"false\".equals(param)) {\n                    this.profileEnable = false;\n                } else {\n                    LOG.error(\"WebStatFilter Parameter '\" + PARAM_NAME_PROFILE_ENABLE + \"' config error\");\n                }\n            }\n        }\n        {\n            String param = config.getInitParameter(PARAM_NAME_SESSION_STAT_MAX_COUNT);\n            if (param != null && param.trim().length() != 0) {\n                param = param.trim();\n                try {\n                    this.sessionStatMaxCount = Integer.parseInt(param);\n                } catch (NumberFormatException e) {\n                    LOG.error(\"WebStatFilter Parameter '\" + PARAM_NAME_SESSION_STAT_ENABLE + \"' config error\", e);\n                }\n            }\n        }\n\n        // realIpHeader\n        {\n            String param = config.getInitParameter(PARAM_NAME_REAL_IP_HEADER);\n            if (param != null) {\n                param = param.trim();\n                if (param.length() != 0) {\n                    this.realIpHeader = param;\n                }\n            }\n        }\n\n        StatFilterContext.getInstance().addContextListener(statFilterContextListener);\n\n        this.contextPath = DruidWebUtils.getContextPath(config.getServletContext());\n        if (webAppStat == null) {\n            webAppStat = new WebAppStat(contextPath, this.sessionStatMaxCount);\n        }\n        WebAppStatManager.getInstance().addWebAppStatSet(webAppStat);\n    }\n\n    @Override\n    public void destroy() {\n        StatFilterContext.getInstance().removeContextListener(statFilterContextListener);\n\n        if (webAppStat != null) {\n            WebAppStatManager.getInstance().remove(webAppStat);\n        }\n    }\n\n    public void setWebAppStat(WebAppStat webAppStat) {\n        this.webAppStat = webAppStat;\n    }\n\n    public WebAppStat getWebAppStat() {\n        return webAppStat;\n    }\n\n    public WebStatFilterContextListener getStatFilterContextListener() {\n        return statFilterContextListener;\n    }\n\n    public static final class StatHttpServletResponseWrapper extends HttpServletResponseWrapper implements HttpServletResponse {\n        //初始值应该设置为：HttpServletResponse.SC_OK，而不是 0。\n        private int status = HttpServletResponse.SC_OK;\n\n        public StatHttpServletResponseWrapper(HttpServletResponse response) {\n            super(response);\n        }\n\n        public void setStatus(int statusCode) {\n            super.setStatus(statusCode);\n            this.status = statusCode;\n        }\n\n        @SuppressWarnings(\"deprecation\")\n        public void setStatus(int statusCode, String statusMessage) {\n            super.setStatus(statusCode);\n            super.setStatus(statusCode);\n            this.status = statusCode;\n        }\n\n        public void sendError(int statusCode, String statusMessage) throws IOException {\n            super.sendError(statusCode, statusMessage);\n            this.status = statusCode;\n        }\n\n        public void sendError(int statusCode) throws IOException {\n            super.sendError(statusCode);\n            this.status = statusCode;\n        }\n\n        public int getStatus() {\n            return status;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/json/JSONParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.json;\n\nimport com.alibaba.druid.sql.parser.CharTypes;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class JSONParser {\n    private String text;\n    private int index;\n    private char ch;\n\n    private Token token;\n    private String stringValue;\n    private long longValue;\n    private double doubleValue;\n\n    public JSONParser(String text) {\n        this.text = text;\n        ch = text.charAt(0);\n        nextToken();\n    }\n\n    public Object parse() {\n        if (token == Token.LBRACE) {\n            return parseMap();\n        }\n\n        if (token == Token.INT) {\n            Object value;\n            if (this.longValue >= Integer.MIN_VALUE && this.longValue <= Integer.MAX_VALUE) {\n                value = (int) this.longValue;\n            } else {\n                value = this.longValue;\n            }\n\n            nextToken();\n            return value;\n        }\n\n        if (token == Token.DOUBLE) {\n            Object value = this.doubleValue;\n            nextToken();\n            return value;\n        }\n\n        if (token == Token.STRING) {\n            Object value = this.stringValue;\n            nextToken();\n            return value;\n        }\n\n        if (token == Token.LBRACKET) {\n            return parseArray();\n        }\n\n        if (token == Token.TRUE) {\n            nextToken();\n            return true;\n        }\n\n        if (token == Token.FALSE) {\n            nextToken();\n            return false;\n        }\n\n        if (token == Token.NULL) {\n            nextToken();\n            return null;\n        }\n\n        throw new IllegalArgumentException(\"illegal token : \" + token);\n    }\n\n    public List<Object> parseArray() {\n        accept(Token.LBRACKET);\n        ArrayList<Object> list = new ArrayList<Object>();\n\n        for (; ; ) {\n            if (token == Token.RBRACKET) {\n                break;\n            }\n\n            if (token == Token.COMMA) {\n                nextToken();\n                continue;\n            }\n\n            Object item = parse();\n            list.add(item);\n        }\n\n        accept(Token.RBRACKET);\n        return list;\n    }\n\n    public Map<String, Object> parseMap() {\n        accept(Token.LBRACE);\n        Map<String, Object> map = new LinkedHashMap<String, Object>();\n\n        for (; ; ) {\n            if (token == Token.RBRACE) {\n                break;\n            }\n\n            if (token == Token.COMMA) {\n                nextToken();\n                continue;\n            }\n\n            String key;\n            {\n                if (token != Token.STRING) {\n                    throw new IllegalArgumentException(\"illegal json, \" + token + \" : \" + text);\n                }\n                key = this.stringValue;\n                nextToken();\n            }\n\n            accept(Token.COLON);\n\n            Object value = parse();\n\n            map.put(key, value);\n        }\n\n        accept(Token.RBRACE);\n        return map;\n    }\n\n    void accept(Token token) {\n        if (this.token == token) {\n            nextToken();\n            return;\n        }\n\n        throw new IllegalArgumentException(\"illegal token : \" + this.token + \", expect \" + token);\n    }\n\n    final void nextToken() {\n        if (index == Integer.MIN_VALUE) {\n            token = Token.EOF;\n            return;\n        }\n\n        for (; ; ) {\n            if (CharTypes.isWhitespace(ch)) {\n                nextChar();\n                continue;\n            }\n\n            if (index >= text.length()) {\n                token = Token.EOF;\n                return;\n            }\n\n            break;\n        }\n\n        switch (ch) {\n            case '{':\n                token = Token.LBRACE;\n                nextChar();\n                break;\n            case '}':\n                token = Token.RBRACE;\n                nextChar();\n                break;\n            case '[':\n                token = Token.LBRACKET;\n                nextChar();\n                break;\n            case ']':\n                token = Token.RBRACKET;\n                nextChar();\n                break;\n            case ',':\n                token = Token.COMMA;\n                nextChar();\n                break;\n            case ':':\n                token = Token.COLON;\n                nextChar();\n                break;\n            case '\"':\n                scanString();\n                break;\n            default:\n                if (isDigit(ch) || ch == '-') {\n                    scanDigit();\n                    return;\n                }\n\n                if (text.startsWith(\"null\", index)) {\n                    token = Token.NULL;\n                    index += 3;\n                    nextChar();\n                    return;\n                }\n\n                if (text.startsWith(\"true\", index)) {\n                    token = Token.TRUE;\n                    index += 3;\n                    nextChar();\n                    return;\n                }\n\n                if (text.startsWith(\"false\", index)) {\n                    token = Token.FALSE;\n                    index += 4;\n                    nextChar();\n                    return;\n                }\n                throw new IllegalArgumentException(\"illegal json char : \" + ch);\n        }\n    }\n\n    private void scanDigit() {\n        boolean isNegate = false;\n        if (ch == '-') {\n            isNegate = true;\n            nextChar();\n        }\n\n        int dotCount = 0;\n        StringBuilder digitBuf = new StringBuilder();\n        for (; ; ) {\n            digitBuf.append(ch);\n            nextChar();\n\n            if (ch == '.') {\n                dotCount++;\n                digitBuf.append('.');\n                nextChar();\n                continue;\n            }\n\n            if (!isDigit(ch)) {\n                break;\n            }\n        }\n\n        if (dotCount == 0) {\n            long longValue = Long.parseLong(digitBuf.toString());\n            if (isNegate) {\n                longValue = -longValue;\n            }\n            this.longValue = longValue;\n            token = Token.INT;\n        } else {\n            double doubleValue = Double.parseDouble(digitBuf.toString());\n            if (isNegate) {\n                doubleValue = -doubleValue;\n            }\n            this.doubleValue = doubleValue;\n            token = Token.DOUBLE;\n        }\n    }\n\n    private void scanString() {\n        nextChar();\n        StringBuilder strBuf = new StringBuilder();\n        for (; ; ) {\n            if (index >= text.length()) {\n                throw new IllegalArgumentException(\"illegal string : \" + strBuf);\n            }\n            if (ch == '\"') {\n                nextChar();\n                break;\n            }\n\n            if (ch == '\\\\') {\n                nextChar();\n                if (ch == '\"' || ch == '\\\\' || ch == '/') {\n                    strBuf.append(ch);\n                } else if (ch == 'n') {\n                    strBuf.append('\\n');\n                } else if (ch == 'r') {\n                    strBuf.append('\\r');\n                } else if (ch == 'b') {\n                    strBuf.append('\\b');\n                } else if (ch == 'f') {\n                    strBuf.append('\\f');\n                } else if (ch == 't') {\n                    strBuf.append('\\t');\n                } else if (ch == 'u') {\n                    nextChar();\n                    char c1 = ch;\n                    nextChar();\n                    char c2 = ch;\n                    nextChar();\n                    char c3 = ch;\n                    nextChar();\n                    char c4 = ch;\n                    int val = Integer.parseInt(new String(new char[]{c1, c2, c3, c4}), 16);\n                    strBuf.append((char) val);\n                } else {\n                    throw new IllegalArgumentException(\"illegal string : \" + strBuf);\n                }\n            } else {\n                strBuf.append(ch);\n            }\n            nextChar();\n        }\n        stringValue = strBuf.toString();\n        token = Token.STRING;\n    }\n\n    static boolean isDigit(char ch) {\n        return ch >= '0' && ch <= '9';\n    }\n\n    void nextChar() {\n        ++index;\n        if (index >= text.length()) {\n            index = Integer.MIN_VALUE;\n            return;\n        }\n\n        ch = text.charAt(index);\n    }\n\n    enum Token {\n        INT, //\n        DOUBLE, //\n        STRING, //\n        BOOLEAN, //\n        TRUE, //\n        FALSE, //\n        NULL, //\n        EOF, //\n\n        LBRACE(\"{\"), //\n        RBRACE(\"}\"), //\n        LBRACKET(\"[\"), //\n        RBRACKET(\"]\"), //\n        COMMA(\",\"), //\n        COLON(\":\");\n\n        public final String name;\n\n        Token() {\n            this(null);\n        }\n\n        Token(String name) {\n            this.name = name;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/json/JSONUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.json;\n\npublic class JSONUtils {\n    public static String toJSONString(Object o) {\n        JSONWriter writer = new JSONWriter();\n        writer.writeObject(o);\n        return writer.toString();\n    }\n\n    public static Object parse(String text) {\n        JSONParser parser = new JSONParser(text);\n        return parser.parse();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/json/JSONWriter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.json;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.util.Utils;\n\nimport javax.management.openmbean.CompositeData;\nimport javax.management.openmbean.TabularData;\n\nimport java.text.SimpleDateFormat;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.LocalTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.Map;\n\npublic class JSONWriter {\n    private final StringBuilder out;\n\n    public JSONWriter() {\n        this.out = new StringBuilder();\n    }\n\n    public void writeArrayStart() {\n        write('[');\n    }\n\n    public void writeComma() {\n        write(',');\n    }\n\n    public void writeArrayEnd() {\n        write(']');\n    }\n\n    public void writeNull() {\n        write(\"null\");\n    }\n\n    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n    public void writeObject(Object o) {\n        if (o == null) {\n            writeNull();\n            return;\n        }\n\n        if (o instanceof String) {\n            writeString((String) o);\n            return;\n        }\n\n        if (o instanceof Number) {\n            write(o.toString());\n            return;\n        }\n\n        if (o instanceof Boolean) {\n            write(o.toString());\n            return;\n        }\n\n        if (o instanceof Date) {\n            writeDate((Date) o);\n            return;\n        }\n\n        if (o instanceof LocalDate) {\n            writeLocalDate((LocalDate) o);\n            return;\n        }\n\n        if (o instanceof LocalTime) {\n            writeLocalTime((LocalTime) o);\n            return;\n        }\n\n        if (o instanceof LocalDateTime) {\n            writeLocalDateTime((LocalDateTime) o);\n            return;\n        }\n\n        if (o instanceof Collection) {\n            writeArray((Collection) o);\n            return;\n        }\n\n        if (o instanceof Throwable) {\n            writeError((Throwable) o);\n            return;\n        }\n\n        if (o instanceof int[]) {\n            int[] array = (int[]) o;\n            write('[');\n            for (int i = 0; i < array.length; ++i) {\n                if (i != 0) {\n                    write(',');\n                }\n                write(array[i]);\n            }\n            write(']');\n            return;\n        }\n\n        if (o instanceof long[]) {\n            long[] array = (long[]) o;\n            write('[');\n            for (int i = 0; i < array.length; ++i) {\n                if (i != 0) {\n                    write(',');\n                }\n                write(array[i]);\n            }\n            write(']');\n            return;\n        }\n\n        if (o instanceof TabularData) {\n            writeTabularData((TabularData) o);\n            return;\n        }\n\n        if (o instanceof CompositeData) {\n            writeCompositeData((CompositeData) o);\n            return;\n        }\n\n        if (o instanceof Map) {\n            writeMap((Map) o);\n            return;\n        }\n\n        if (o == SQLEvalVisitor.EVAL_VALUE_NULL) {\n            write(\"null\");\n            return;\n        }\n\n        throw new IllegalArgumentException(\"not support type : \" + o.getClass());\n    }\n\n    public void writeDate(Date date) {\n        if (date == null) {\n            writeNull();\n            return;\n        }\n        //SimpleDataFormat is not thread-safe, we need to make it local.\n        SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        writeString(dateFormat.format(date));\n    }\n\n    /**\n     * 写 local date\n     */\n    public void writeLocalDate(LocalDate date) {\n        if (date == null) {\n            writeNull();\n            return;\n        }\n        String formatDate = DateTimeFormatter.ofPattern(\"yyyy-MM-dd\").format(date);\n        writeString(formatDate);\n    }\n\n    /**\n     * 写 LocalTime\n     */\n    public void writeLocalTime(LocalTime time) {\n        if (time == null) {\n            writeNull();\n            return;\n        }\n        String formatTime = DateTimeFormatter.ofPattern(\"HH:mm:ss\").format(time);\n        writeString(formatTime);\n    }\n\n    /**\n     * 写 LocalTime\n     */\n    public void writeLocalDateTime(LocalDateTime dateTime) {\n        if (dateTime == null) {\n            writeNull();\n            return;\n        }\n        String formatDateTime = DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\").format(dateTime);\n        writeString(formatDateTime);\n    }\n\n    public void writeError(Throwable error) {\n        if (error == null) {\n            writeNull();\n            return;\n        }\n\n        write(\"{\\\"Class\\\":\");\n        writeString(error.getClass().getName());\n        write(\",\\\"Message\\\":\");\n        writeString(error.getMessage());\n        write(\",\\\"StackTrace\\\":\");\n        writeString(Utils.getStackTrace(error));\n        write('}');\n    }\n\n    public void writeArray(Object[] array) {\n        if (array == null) {\n            writeNull();\n            return;\n        }\n\n        write('[');\n\n        for (int i = 0; i < array.length; ++i) {\n            if (i != 0) {\n                write(',');\n            }\n            writeObject(array[i]);\n        }\n\n        write(']');\n    }\n\n    public void writeArray(Collection<Object> list) {\n        if (list == null) {\n            writeNull();\n            return;\n        }\n\n        int entryIndex = 0;\n        write('[');\n\n        for (Object entry : list) {\n            if (entryIndex != 0) {\n                write(',');\n            }\n            writeObject(entry);\n            entryIndex++;\n        }\n\n        write(']');\n    }\n\n    public void writeString(String text) {\n        if (text == null) {\n            writeNull();\n            return;\n        }\n\n        write('\"');\n        for (int i = 0; i < text.length(); ++i) {\n            char c = text.charAt(i);\n            if (c == '\"') {\n                write(\"\\\\\\\"\");\n            } else if (c == '\\n') {\n                write(\"\\\\n\");\n            } else if (c == '\\r') {\n                write(\"\\\\r\");\n            } else if (c == '\\\\') {\n                write(\"\\\\\\\\\");\n            } else if (c == '\\t') {\n                write(\"\\\\t\");\n            } else if (c < 16) {\n                write(\"\\\\u000\");\n                write(Integer.toHexString(c));\n            } else if (c < 32) {\n                write(\"\\\\u00\");\n                write(Integer.toHexString(c));\n            } else if (c >= 0x7f && c <= 0xA0) {\n                write(\"\\\\u00\");\n                write(Integer.toHexString(c));\n            } else {\n                write(c);\n            }\n        }\n        write('\"');\n    }\n\n    public void writeTabularData(TabularData tabularData) {\n        if (tabularData == null) {\n            writeNull();\n            return;\n        }\n\n        int entryIndex = 0;\n        write('[');\n\n        for (Object item : tabularData.values()) {\n            if (entryIndex != 0) {\n                write(',');\n            }\n            CompositeData row = (CompositeData) item;\n            writeCompositeData(row);\n\n            entryIndex++;\n        }\n        write(']');\n    }\n\n    public void writeCompositeData(CompositeData compositeData) {\n        if (compositeData == null) {\n            writeNull();\n            return;\n        }\n\n        int entryIndex = 0;\n        write('{');\n\n        for (Object key : compositeData.getCompositeType().keySet()) {\n            if (entryIndex != 0) {\n                write(',');\n            }\n            writeString((String) key);\n            write(':');\n            Object value = compositeData.get((String) key);\n            writeObject(value);\n            entryIndex++;\n        }\n\n        write('}');\n    }\n\n    public void writeMap(Map<String, Object> map) {\n        if (map == null) {\n            writeNull();\n            return;\n        }\n\n        int entryIndex = 0;\n        write('{');\n        for (Map.Entry<String, Object> entry : map.entrySet()) {\n            if (entryIndex != 0) {\n                write(',');\n            }\n\n            writeString(entry.getKey());\n            write(':');\n            writeObject(entry.getValue());\n\n            entryIndex++;\n        }\n\n        write('}');\n    }\n\n    protected void write(String text) {\n        out.append(text);\n    }\n\n    protected void write(char c) {\n        out.append(c);\n    }\n\n    protected void write(int c) {\n        out.append(c);\n    }\n\n    protected void write(long c) {\n        out.append(c);\n    }\n\n    @Override\n    public String toString() {\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/JakartaCommonsLoggingImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\n\npublic class JakartaCommonsLoggingImpl implements com.alibaba.druid.support.logging.Log {\n    private Log log;\n\n    private int errorCount;\n    private int warnCount;\n    private int infoCount;\n    private int debugCount;\n\n    /**\n     * @param log the Log instance to be used for logging\n     * @since 0.2.1\n     */\n    public JakartaCommonsLoggingImpl(Log log) {\n        this.log = log;\n    }\n\n    public JakartaCommonsLoggingImpl(String loggerName) {\n        log = LogFactory.getLog(loggerName);\n    }\n\n    public boolean isDebugEnabled() {\n        return log.isDebugEnabled();\n    }\n\n    public void error(String s, Throwable e) {\n        log.error(s, e);\n        errorCount++;\n    }\n\n    public void error(String s) {\n        log.error(s);\n        errorCount++;\n    }\n\n    public void debug(String s) {\n        debugCount++;\n        log.debug(s);\n    }\n\n    public void debug(String s, Throwable e) {\n        debugCount++;\n        log.debug(s, e);\n    }\n\n    public void warn(String s) {\n        log.warn(s);\n        warnCount++;\n    }\n\n    @Override\n    public void warn(String s, Throwable e) {\n        log.warn(s, e);\n        warnCount++;\n    }\n\n    @Override\n    public int getWarnCount() {\n        return warnCount;\n    }\n\n    public int getErrorCount() {\n        return errorCount;\n    }\n\n    @Override\n    public void resetStat() {\n        errorCount = 0;\n        warnCount = 0;\n        infoCount = 0;\n        debugCount++;\n    }\n\n    @Override\n    public boolean isInfoEnabled() {\n        return log.isInfoEnabled();\n    }\n\n    @Override\n    public void info(String msg) {\n        log.info(msg);\n        infoCount++;\n    }\n\n    @Override\n    public int getInfoCount() {\n        return infoCount;\n    }\n\n    @Override\n    public boolean isWarnEnabled() {\n        return log.isWarnEnabled();\n    }\n\n    public int getDebugCount() {\n        return debugCount;\n    }\n\n    @Override\n    public boolean isErrorEnabled() {\n        return log.isErrorEnabled();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/Jdk14LoggingImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\npublic class Jdk14LoggingImpl implements Log {\n    private Logger log;\n\n    private int errorCount;\n    private int warnCount;\n    private int infoCount;\n    private int debugCount;\n\n    private String loggerName;\n\n    public Jdk14LoggingImpl(String loggerName) {\n        this.loggerName = loggerName;\n        log = Logger.getLogger(loggerName);\n    }\n\n    public boolean isDebugEnabled() {\n        return log.isLoggable(Level.FINE);\n    }\n\n    public void error(String s, Throwable e) {\n        log.logp(Level.SEVERE, loggerName, Thread.currentThread().getStackTrace()[1].getMethodName(), s, e);\n        errorCount++;\n    }\n\n    public void error(String s) {\n        log.logp(Level.SEVERE, loggerName, Thread.currentThread().getStackTrace()[1].getMethodName(), s);\n        errorCount++;\n    }\n\n    public void debug(String s) {\n        debugCount++;\n        log.logp(Level.FINE, loggerName, Thread.currentThread().getStackTrace()[1].getMethodName(), s);\n    }\n\n    public void debug(String s, Throwable e) {\n        debugCount++;\n        log.logp(Level.FINE, loggerName, Thread.currentThread().getStackTrace()[1].getMethodName(), s, e);\n    }\n\n    public void warn(String s) {\n        log.logp(Level.WARNING, loggerName, Thread.currentThread().getStackTrace()[1].getMethodName(), s);\n        warnCount++;\n    }\n\n    @Override\n    public void warn(String s, Throwable e) {\n        log.logp(Level.WARNING, loggerName, Thread.currentThread().getStackTrace()[1].getMethodName(), s, e);\n        warnCount++;\n    }\n\n    @Override\n    public int getWarnCount() {\n        return warnCount;\n    }\n\n    public int getErrorCount() {\n        return errorCount;\n    }\n\n    @Override\n    public void resetStat() {\n        errorCount = 0;\n        warnCount = 0;\n        infoCount = 0;\n        debugCount = 0;\n    }\n\n    @Override\n    public boolean isInfoEnabled() {\n        return log.isLoggable(Level.INFO);\n    }\n\n    @Override\n    public void info(String msg) {\n        log.logp(Level.INFO, loggerName, Thread.currentThread().getStackTrace()[1].getMethodName(), msg);\n        infoCount++;\n    }\n\n    @Override\n    public int getInfoCount() {\n        return infoCount;\n    }\n\n    @Override\n    public boolean isWarnEnabled() {\n        return log.isLoggable(Level.WARNING);\n    }\n\n    public int getDebugCount() {\n        return debugCount;\n    }\n\n    @Override\n    public boolean isErrorEnabled() {\n        return log.isLoggable(Level.SEVERE);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/Log.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\npublic interface Log {\n    boolean isDebugEnabled();\n\n    void error(String msg, Throwable e);\n\n    void error(String msg);\n\n    boolean isInfoEnabled();\n\n    void info(String msg);\n\n    void debug(String msg);\n\n    void debug(String msg, Throwable e);\n\n    boolean isWarnEnabled();\n\n    void warn(String msg);\n\n    void warn(String msg, Throwable e);\n\n    boolean isErrorEnabled();\n\n    int getErrorCount();\n\n    int getWarnCount();\n\n    int getInfoCount();\n\n    int getDebugCount();\n\n    void resetStat();\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/Log4j2Impl.java",
    "content": "package com.alibaba.druid.support.logging;\n\nimport org.apache.logging.log4j.Level;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\n\n/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npublic class Log4j2Impl implements Log {\n    private Logger log;\n\n    private int errorCount;\n    private int warnCount;\n    private int infoCount;\n    private int debugCount;\n\n    /**\n     * @param log the Log instance to be used for logging\n     * @since 0.2.21\n     */\n    public Log4j2Impl(Logger log) {\n        this.log = log;\n    }\n\n    public Log4j2Impl(String loggerName) {\n        log = LogManager.getLogger(loggerName);\n    }\n\n    public Logger getLog() {\n        return log;\n    }\n\n    public boolean isDebugEnabled() {\n        return log.isDebugEnabled();\n    }\n\n    public void error(String s, Throwable e) {\n        errorCount++;\n        log.error(s, e);\n    }\n\n    public void error(String s) {\n        errorCount++;\n        log.error(s);\n    }\n\n    public void debug(String s) {\n        debugCount++;\n        log.debug(s);\n    }\n\n    public void debug(String s, Throwable e) {\n        debugCount++;\n        log.debug(s, e);\n    }\n\n    public void warn(String s) {\n        log.warn(s);\n        warnCount++;\n    }\n\n    public void warn(String s, Throwable e) {\n        log.warn(s, e);\n        warnCount++;\n    }\n\n    public int getWarnCount() {\n        return warnCount;\n    }\n\n    public int getErrorCount() {\n        return errorCount;\n    }\n\n    public void resetStat() {\n        errorCount = 0;\n        warnCount = 0;\n        infoCount = 0;\n        debugCount = 0;\n    }\n\n    public int getDebugCount() {\n        return debugCount;\n    }\n\n    public boolean isInfoEnabled() {\n        return log.isInfoEnabled();\n    }\n\n    public void info(String msg) {\n        infoCount++;\n        log.info(msg);\n    }\n\n    public boolean isWarnEnabled() {\n        return log.isEnabled(Level.WARN);\n    }\n\n    public boolean isErrorEnabled() {\n        return log.isErrorEnabled();\n    }\n\n    public int getInfoCount() {\n        return infoCount;\n    }\n\n    public String toString() {\n        return log.toString();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/Log4jImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\nimport org.apache.log4j.Level;\nimport org.apache.log4j.Logger;\n\npublic class Log4jImpl implements Log {\n    private static final String callerFQCN = Log4jImpl.class.getName();\n\n    private Logger log;\n\n    private int errorCount;\n    private int warnCount;\n    private int infoCount;\n    private int debugCount;\n\n    /**\n     * @param log the Log instance to be used for logging\n     * @since 0.2.21\n     */\n    public Log4jImpl(Logger log) {\n        this.log = log;\n    }\n\n    public Log4jImpl(String loggerName) {\n        log = Logger.getLogger(loggerName);\n    }\n\n    public Logger getLog() {\n        return log;\n    }\n\n    public boolean isDebugEnabled() {\n        return log.isDebugEnabled();\n    }\n\n    public void error(String s, Throwable e) {\n        errorCount++;\n        log.log(callerFQCN, Level.ERROR, s, e);\n    }\n\n    public void error(String s) {\n        errorCount++;\n        log.log(callerFQCN, Level.ERROR, s, null);\n    }\n\n    public void debug(String s) {\n        debugCount++;\n        log.log(callerFQCN, Level.DEBUG, s, null);\n    }\n\n    public void debug(String s, Throwable e) {\n        debugCount++;\n        log.log(callerFQCN, Level.DEBUG, s, e);\n    }\n\n    public void warn(String s) {\n        log.log(callerFQCN, Level.WARN, s, null);\n        warnCount++;\n    }\n\n    public void warn(String s, Throwable e) {\n        log.log(callerFQCN, Level.WARN, s, e);\n        warnCount++;\n    }\n\n    public int getWarnCount() {\n        return warnCount;\n    }\n\n    public int getErrorCount() {\n        return errorCount;\n    }\n\n    public void resetStat() {\n        errorCount = 0;\n        warnCount = 0;\n        infoCount = 0;\n        debugCount = 0;\n    }\n\n    public int getDebugCount() {\n        return debugCount;\n    }\n\n    public boolean isInfoEnabled() {\n        return log.isInfoEnabled();\n    }\n\n    public void info(String msg) {\n        infoCount++;\n        log.log(callerFQCN, Level.INFO, msg, null);\n    }\n\n    public boolean isWarnEnabled() {\n        return log.isEnabledFor(Level.WARN);\n    }\n\n    public boolean isErrorEnabled() {\n        return log.isEnabledFor(Level.ERROR);\n    }\n\n    public int getInfoCount() {\n        return infoCount;\n    }\n\n    public String toString() {\n        return log.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/LogFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\nimport java.lang.reflect.Constructor;\n\n@SuppressWarnings(\"rawtypes\")\npublic class LogFactory {\n    private static Constructor logConstructor;\n\n    static {\n        String logType = System.getProperty(\"druid.logType\");\n        if (logType != null) {\n            if (logType.equalsIgnoreCase(\"slf4j\")) {\n                tryImplementation(\"org.slf4j.Logger\", \"com.alibaba.druid.support.logging.SLF4JImpl\");\n            } else if (logType.equalsIgnoreCase(\"log4j\")) {\n                tryImplementation(\"org.apache.log4j.Logger\", \"com.alibaba.druid.support.logging.Log4jImpl\");\n            } else if (logType.equalsIgnoreCase(\"log4j2\")) {\n                tryImplementation(\"org.apache.logging.log4j.Logger\", \"com.alibaba.druid.support.logging.Log4j2Impl\");\n            } else if (logType.equalsIgnoreCase(\"commonsLog\")) {\n                tryImplementation(\"org.apache.commons.logging.LogFactory\",\n                        \"com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl\");\n            } else if (logType.equalsIgnoreCase(\"jdkLog\")) {\n                tryImplementation(\"java.util.logging.Logger\", \"com.alibaba.druid.support.logging.Jdk14LoggingImpl\");\n            }\n        }\n        // 优先选择log4j,而非Apache Common Logging. 因为后者无法设置真实Log调用者的信息\n        tryImplementation(\"org.slf4j.Logger\", \"com.alibaba.druid.support.logging.SLF4JImpl\");\n        tryImplementation(\"org.apache.log4j.Logger\", \"com.alibaba.druid.support.logging.Log4jImpl\");\n        tryImplementation(\"org.apache.logging.log4j.Logger\", \"com.alibaba.druid.support.logging.Log4j2Impl\");\n        tryImplementation(\"org.apache.commons.logging.LogFactory\",\n                \"com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl\");\n        tryImplementation(\"java.util.logging.Logger\", \"com.alibaba.druid.support.logging.Jdk14LoggingImpl\");\n\n        if (logConstructor == null) {\n            try {\n                logConstructor = NoLoggingImpl.class.getConstructor(String.class);\n            } catch (Exception e) {\n                throw new IllegalStateException(e.getMessage(), e);\n            }\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static void tryImplementation(String testClassName, String implClassName) {\n        if (logConstructor != null) {\n            return;\n        }\n\n        try {\n            Resources.classForName(testClassName);\n            Class implClass = Resources.classForName(implClassName);\n            logConstructor = implClass.getConstructor(new Class[]{String.class});\n\n            Class<?> declareClass = logConstructor.getDeclaringClass();\n            if (!Log.class.isAssignableFrom(declareClass)) {\n                logConstructor = null;\n            }\n\n            try {\n                if (null != logConstructor) {\n                    logConstructor.newInstance(LogFactory.class.getName());\n                }\n            } catch (Throwable t) {\n                logConstructor = null;\n            }\n\n        } catch (Throwable t) {\n            // skip\n        }\n    }\n\n    public static Log getLog(Class clazz) {\n        return getLog(clazz.getName());\n    }\n\n    public static Log getLog(String loggerName) {\n        try {\n            return (Log) logConstructor.newInstance(loggerName);\n        } catch (Throwable t) {\n            throw new RuntimeException(\"Error creating logger for logger '\" + loggerName + \"'.  Cause: \" + t, t);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static synchronized void selectLog4JLogging() {\n        try {\n            Resources.classForName(\"org.apache.log4j.Logger\");\n            Class implClass = Resources.classForName(\"com.alibaba.druid.support.logging.Log4jImpl\");\n            logConstructor = implClass.getConstructor(new Class[]{String.class});\n        } catch (Throwable t) {\n            //ignore\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static synchronized void selectJavaLogging() {\n        try {\n            Resources.classForName(\"java.util.logging.Logger\");\n            Class implClass = Resources.classForName(\"com.alibaba.druid.support.logging.Jdk14LoggingImpl\");\n            logConstructor = implClass.getConstructor(new Class[]{String.class});\n        } catch (Throwable t) {\n            //ignore\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\npublic class NoLoggingImpl implements Log {\n    private int infoCount;\n    private int errorCount;\n    private int warnCount;\n    private int debugCount;\n    private String loggerName;\n\n    private boolean debugEnable;\n    private boolean infoEnable = true;\n    private boolean warnEnable = true;\n    private boolean errorEnable = true;\n\n    public NoLoggingImpl(String loggerName) {\n        this.loggerName = loggerName;\n    }\n\n    public String getLoggerName() {\n        return this.loggerName;\n    }\n\n    public boolean isDebugEnabled() {\n        return debugEnable;\n    }\n\n    public void error(String s, Throwable e) {\n        if (!errorEnable) {\n            return;\n        }\n\n        error(s);\n\n        if (e != null) {\n            e.printStackTrace();\n        }\n    }\n\n    public void error(String s) {\n        errorCount++;\n        if (s != null) {\n            System.err.println(loggerName + \" : \" + s);\n        }\n    }\n\n    public void debug(String s) {\n        debugCount++;\n    }\n\n    public void debug(String s, Throwable e) {\n        debugCount++;\n    }\n\n    public void warn(String s) {\n        warnCount++;\n    }\n\n    @Override\n    public void warn(String s, Throwable e) {\n        warnCount++;\n    }\n\n    public int getErrorCount() {\n        return errorCount;\n    }\n\n    @Override\n    public int getWarnCount() {\n        return warnCount;\n    }\n\n    @Override\n    public void resetStat() {\n        errorCount = 0;\n        warnCount = 0;\n        infoCount = 0;\n        debugCount = 0;\n    }\n\n    @Override\n    public boolean isInfoEnabled() {\n        return infoEnable;\n    }\n\n    @Override\n    public void info(String s) {\n        infoCount++;\n    }\n\n    @Override\n    public boolean isWarnEnabled() {\n        return warnEnable;\n    }\n\n    public int getInfoCount() {\n        return infoCount;\n    }\n\n    public int getDebugCount() {\n        return debugCount;\n    }\n\n    public boolean isErrorEnabled() {\n        return errorEnable;\n    }\n\n    public void setErrorEnabled(boolean value) {\n        this.errorEnable = value;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/Resources.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\n/**\n * A class to simplify access to resources through the classloader.\n */\npublic final class Resources extends Object {\n    private static ClassLoader defaultClassLoader;\n\n    private Resources() {\n    }\n\n    /**\n     * Returns the default classloader (may be null).\n     *\n     * @return The default classloader\n     */\n    public static ClassLoader getDefaultClassLoader() {\n        return defaultClassLoader;\n    }\n\n    /**\n     * Sets the default classloader\n     *\n     * @param defaultClassLoader - the new default ClassLoader\n     */\n    public static void setDefaultClassLoader(ClassLoader defaultClassLoader) {\n        Resources.defaultClassLoader = defaultClassLoader;\n    }\n\n    /**\n     * Loads a class\n     *\n     * @param className - the class to load\n     * @return The loaded class\n     * @throws ClassNotFoundException If the class cannot be found (duh!)\n     */\n    public static Class<?> classForName(String className) throws ClassNotFoundException {\n        Class<?> clazz = null;\n        try {\n            clazz = getClassLoader().loadClass(className);\n        } catch (Exception e) {\n            // Ignore. Failsafe below.\n        }\n        if (clazz == null) {\n            clazz = Class.forName(className);\n        }\n        return clazz;\n    }\n\n    private static ClassLoader getClassLoader() {\n        if (defaultClassLoader != null) {\n            return defaultClassLoader;\n        } else {\n            return Thread.currentThread().getContextClassLoader();\n        }\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/logging/SLF4JImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.logging;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.slf4j.spi.LocationAwareLogger;\n\npublic class SLF4JImpl implements Log {\n    private static final String callerFQCN = SLF4JImpl.class.getName();\n    private static final Logger testLogger = LoggerFactory.getLogger(SLF4JImpl.class);\n\n    static {\n        // if the logger is not a LocationAwareLogger instance, it can not get correct stack StackTraceElement\n        // so ignore this implementation.\n        if (!(testLogger instanceof LocationAwareLogger)) {\n            throw new UnsupportedOperationException(testLogger.getClass() + \" is not a suitable logger\");\n        }\n    }\n\n    private int errorCount;\n    private int warnCount;\n    private int infoCount;\n    private int debugCount;\n    private LocationAwareLogger log;\n\n    public SLF4JImpl(LocationAwareLogger log) {\n        this.log = log;\n    }\n\n    public SLF4JImpl(String loggerName) {\n        this.log = (LocationAwareLogger) LoggerFactory.getLogger(loggerName);\n    }\n\n    @Override\n    public boolean isDebugEnabled() {\n        return log.isDebugEnabled();\n    }\n\n    @Override\n    public void error(String msg, Throwable e) {\n        log.log(null, callerFQCN, LocationAwareLogger.ERROR_INT, msg, null, e);\n        errorCount++;\n    }\n\n    @Override\n    public void error(String msg) {\n        log.log(null, callerFQCN, LocationAwareLogger.ERROR_INT, msg, null, null);\n        errorCount++;\n    }\n\n    @Override\n    public boolean isInfoEnabled() {\n        return log.isInfoEnabled();\n    }\n\n    @Override\n    public void info(String msg) {\n        infoCount++;\n        log.log(null, callerFQCN, LocationAwareLogger.INFO_INT, msg, null, null);\n    }\n\n    @Override\n    public void debug(String msg) {\n        debugCount++;\n        log.log(null, callerFQCN, LocationAwareLogger.DEBUG_INT, msg, null, null);\n    }\n\n    @Override\n    public void debug(String msg, Throwable e) {\n        debugCount++;\n        log.log(null, callerFQCN, LocationAwareLogger.DEBUG_INT, msg, null, e);\n    }\n\n    @Override\n    public boolean isWarnEnabled() {\n        return log.isWarnEnabled();\n    }\n\n    @Override\n    public boolean isErrorEnabled() {\n        return log.isErrorEnabled();\n    }\n\n    @Override\n    public void warn(String msg) {\n        log.log(null, callerFQCN, LocationAwareLogger.WARN_INT, msg, null, null);\n        warnCount++;\n    }\n\n    @Override\n    public void warn(String msg, Throwable e) {\n        log.log(null, callerFQCN, LocationAwareLogger.WARN_INT, msg, null, e);\n        warnCount++;\n    }\n\n    @Override\n    public int getErrorCount() {\n        return errorCount;\n    }\n\n    @Override\n    public int getWarnCount() {\n        return warnCount;\n    }\n\n    @Override\n    public int getInfoCount() {\n        return infoCount;\n    }\n\n    public int getDebugCount() {\n        return debugCount;\n    }\n\n    @Override\n    public void resetStat() {\n        errorCount = 0;\n        warnCount = 0;\n        infoCount = 0;\n        debugCount = 0;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/metrics/MetricCollector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.metrics;\n\npublic class MetricCollector {\n    public void collect() throws Exception {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/MonitorClient.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceStatValue;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcSqlStatValue;\nimport com.alibaba.druid.support.http.stat.WebAppStat;\nimport com.alibaba.druid.support.http.stat.WebAppStatManager;\nimport com.alibaba.druid.support.http.stat.WebAppStatValue;\nimport com.alibaba.druid.support.http.stat.WebURIStatValue;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.support.monitor.dao.MonitorDao;\nimport com.alibaba.druid.support.spring.stat.SpringMethodStatValue;\nimport com.alibaba.druid.support.spring.stat.SpringStat;\nimport com.alibaba.druid.support.spring.stat.SpringStatManager;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.util.Utils;\nimport com.alibaba.druid.wall.WallProviderStatValue;\n\nimport java.lang.management.ManagementFactory;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.util.*;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.druid.util.Utils.getBoolean;\nimport static com.alibaba.druid.util.Utils.getInteger;\n\npublic class MonitorClient {\n    private static final Log LOG = LogFactory.getLog(MonitorClient.class);\n\n    private static final long DEFAULT_TIME_BETWEEN_COLLECT = 60 * 5;\n\n    private ScheduledExecutorService scheduler;\n    private int schedulerThreadSize = 1;\n\n    private long timeBetweenSqlCollect = DEFAULT_TIME_BETWEEN_COLLECT;\n    private long timeBetweenSpringCollect = DEFAULT_TIME_BETWEEN_COLLECT;\n    private long timeBetweenWebUriCollect = DEFAULT_TIME_BETWEEN_COLLECT;\n    private TimeUnit timeUnit = TimeUnit.SECONDS;\n\n    private boolean collectSqlEnable = true;\n    private boolean collectSqlWallEnable = true;\n    private boolean collectSpringMethodEnable = true;\n    private boolean collectWebAppEnable = true;\n    private boolean collectWebURIEnable = true;\n\n    private MonitorDao dao;\n\n    private String domain;\n    private String app;\n    private String cluster;\n    private String host;\n    private String ip;\n    private int pid;\n\n    public MonitorClient() {\n        String name = ManagementFactory.getRuntimeMXBean().getName();\n\n        String[] items = name.split(\"@\");\n\n        pid = Integer.parseInt(items[0]);\n        host = items[1];\n        ip = getLocalIPAddress().getHostAddress();\n\n        configFromProperty(System.getProperties());\n    }\n\n    public void configFromProperty(Properties properties) {\n        {\n            Integer value = getInteger(properties, \"druid.monitor.client.schedulerThreadSize\");\n            if (value != null) {\n                this.setSchedulerThreadSize(value);\n            }\n        }\n\n        {\n            Integer value = getInteger(properties, \"druid.monitor.client.timeBetweenSqlCollect\");\n            if (value != null) {\n                this.setTimeBetweenSqlCollect(value);\n            }\n        }\n        {\n            Integer value = getInteger(properties, \"druid.monitor.client.timeBetweenSpringCollect\");\n            if (value != null) {\n                this.setTimeBetweenSpringCollect(value);\n            }\n        }\n        {\n            Integer value = getInteger(properties, \"druid.monitor.client.timeBetweenWebUriCollect\");\n            if (value != null) {\n                this.setTimeBetweenWebUriCollect(value);\n            }\n        }\n\n        {\n            Boolean value = getBoolean(properties, \"druid.monitor.client.collectSqlEnable\");\n            if (value != null) {\n                this.setCollectSqlEnable(value);\n            }\n        }\n\n        {\n            Boolean value = getBoolean(properties, \"druid.monitor.client.collectSqlWallEnable\");\n            if (value != null) {\n                this.setCollectSqlWallEnable(value);\n            }\n        }\n\n        {\n            Boolean value = getBoolean(properties, \"druid.monitor.client.collectSpringMethodEnable\");\n            if (value != null) {\n                this.setCollectSpringMethodEnable(value);\n            }\n        }\n\n        {\n            Boolean value = getBoolean(properties, \"druid.monitor.client.collectWebAppEnable\");\n            if (value != null) {\n                this.setCollectWebAppEnable(value);\n            }\n        }\n\n        {\n            Boolean value = getBoolean(properties, \"druid.monitor.client.collectWebURIEnable\");\n            if (value != null) {\n                this.setCollectWebURIEnable(value);\n            }\n        }\n        {\n            domain = properties.getProperty(\"druid.monitor.domain\");\n            if (StringUtils.isEmpty(domain)) {\n                domain = \"default\";\n            }\n        }\n\n        {\n            app = properties.getProperty(\"druid.monitor.app\");\n            if (StringUtils.isEmpty(app)) {\n                app = \"default\";\n            }\n        }\n\n        {\n            cluster = properties.getProperty(\"druid.monitor.cluster\");\n            if (StringUtils.isEmpty(cluster)) {\n                cluster = \"default\";\n            }\n        }\n    }\n\n    public void stop() {\n    }\n\n    public void start() {\n        checkInst();\n\n        if (scheduler == null) {\n            scheduler = new ScheduledThreadPoolExecutor(schedulerThreadSize);\n        }\n\n        scheduler.scheduleAtFixedRate(new Runnable() {\n            @Override\n            public void run() {\n                collectSql();\n            }\n        }, timeBetweenSqlCollect, timeBetweenSqlCollect, timeUnit);\n\n        scheduler.scheduleAtFixedRate(new Runnable() {\n            @Override\n            public void run() {\n                collectSpringMethod();\n            }\n        }, timeBetweenSpringCollect, timeBetweenSpringCollect, timeUnit);\n\n        scheduler.scheduleAtFixedRate(new Runnable() {\n            @Override\n            public void run() {\n                collectWebURI();\n            }\n        }, timeBetweenWebUriCollect, timeBetweenWebUriCollect, timeUnit);\n    }\n\n    public ScheduledExecutorService getScheduler() {\n        return scheduler;\n    }\n\n    public void setScheduler(ScheduledExecutorService scheduler) {\n        this.scheduler = scheduler;\n    }\n\n    public void checkInst() {\n        try {\n            dao.insertAppIfNotExits(domain, app);\n\n            dao.insertClusterIfNotExits(domain, app, cluster);\n\n            dao.insertOrUpdateInstance(domain, app, cluster, host, ip, Utils.getStartTime(), pid);\n        } catch (Exception ex) {\n            LOG.error(\"checkInst error\", ex);\n        }\n    }\n\n    @SuppressWarnings(\"resource\")\n    public void collectSql() {\n        if ((!collectSqlEnable) && !collectSqlWallEnable) {\n            return;\n        }\n\n        Set<Object> dataSources = DruidDataSourceStatManager.getInstances().keySet();\n\n        List<DruidDataSourceStatValue> statValueList = new ArrayList<DruidDataSourceStatValue>(dataSources.size());\n        List<WallProviderStatValue> wallStatValueList = new ArrayList<WallProviderStatValue>();\n\n        for (Object item : dataSources) {\n            if (!(item instanceof DruidDataSource)) {\n                continue;\n            }\n\n            DruidDataSource dataSource = (DruidDataSource) item;\n\n            if (collectSqlEnable) {\n                DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();\n                statValueList.add(statValue);\n            }\n\n            if (collectSqlWallEnable) {\n                WallProviderStatValue wallStatValue = dataSource.getWallStatValue(true);\n                if (wallStatValue != null && wallStatValue.getCheckCount() > 0) {\n                    wallStatValueList.add(wallStatValue);\n                }\n            }\n        }\n\n        MonitorContext ctx = createContext();\n\n        if (statValueList.size() > 0) {\n            dao.saveSql(ctx, statValueList);\n        }\n\n        if (wallStatValueList.size() > 0) {\n            dao.saveSqlWall(ctx, wallStatValueList);\n        }\n    }\n\n    private MonitorContext createContext() {\n        MonitorContext ctx = new MonitorContext();\n\n        ctx.setDomain(domain);\n        ctx.setApp(app);\n        ctx.setCluster(cluster);\n\n        ctx.setCollectTime(new Date());\n        ctx.setPID(pid);\n        ctx.setHost(host);\n        ctx.setCollectTime(Utils.getStartTime());\n        return ctx;\n    }\n\n    private void collectSpringMethod() {\n        if (!collectSpringMethodEnable) {\n            return;\n        }\n\n        List<SpringMethodStatValue> statValueList = new ArrayList<SpringMethodStatValue>();\n\n        Set<Object> stats = SpringStatManager.getInstance().getSpringStatSet();\n\n        for (Object item : stats) {\n            if (!(item instanceof SpringStat)) {\n                continue;\n            }\n\n            SpringStat sprintStat = (SpringStat) item;\n            statValueList.addAll(sprintStat.getStatList(true));\n        }\n\n        if (statValueList.size() > 0) {\n            MonitorContext ctx = createContext();\n            dao.saveSpringMethod(ctx, statValueList);\n        }\n    }\n\n    private void collectWebURI() {\n        if ((!collectWebAppEnable) && !collectWebURIEnable) {\n            return;\n        }\n\n        List<WebURIStatValue> webURIValueList = new ArrayList<WebURIStatValue>();\n        List<WebAppStatValue> webAppStatValueList = new ArrayList<WebAppStatValue>();\n\n        Set<Object> stats = WebAppStatManager.getInstance().getWebAppStatSet();\n\n        for (Object item : stats) {\n            if (!(item instanceof WebAppStat)) {\n                continue;\n            }\n\n            WebAppStat webAppStat = (WebAppStat) item;\n\n            if (collectWebAppEnable) {\n                WebAppStatValue webAppStatValue = webAppStat.getStatValue(true);\n                webAppStatValueList.add(webAppStatValue);\n            }\n\n            if (collectWebURIEnable) {\n                webURIValueList.addAll(webAppStat.getURIStatValueList(true));\n            }\n        }\n\n        MonitorContext ctx = createContext();\n\n        if (webURIValueList.size() > 0) {\n            dao.saveWebURI(ctx, webURIValueList);\n        }\n\n        if (webAppStatValueList.size() > 0) {\n            dao.saveWebApp(ctx, webAppStatValueList);\n        }\n    }\n\n    public List<JdbcSqlStatValue> loadSqlList(Map<String, Object> filters) {\n        return dao.loadSqlList(filters);\n    }\n\n    public MonitorDao getDao() {\n        return dao;\n    }\n\n    public void setDao(MonitorDao dao) {\n        this.dao = dao;\n    }\n\n    public long getTimeBetweenSqlCollect() {\n        return timeBetweenSqlCollect;\n    }\n\n    public void setTimeBetweenSqlCollect(long timeBetweenSqlCollect) {\n        this.timeBetweenSqlCollect = timeBetweenSqlCollect;\n    }\n\n    public long getTimeBetweenSpringCollect() {\n        return timeBetweenSpringCollect;\n    }\n\n    public void setTimeBetweenSpringCollect(long timeBetweenSpringCollect) {\n        this.timeBetweenSpringCollect = timeBetweenSpringCollect;\n    }\n\n    public long getTimeBetweenWebUriCollect() {\n        return timeBetweenWebUriCollect;\n    }\n\n    public void setTimeBetweenWebUriCollect(long timeBetweenWebUriCollect) {\n        this.timeBetweenWebUriCollect = timeBetweenWebUriCollect;\n    }\n\n    public TimeUnit getTimeUnit() {\n        return timeUnit;\n    }\n\n    public void setTimeUnit(TimeUnit timeUnit) {\n        this.timeUnit = timeUnit;\n    }\n\n    public boolean isCollectSqlEnable() {\n        return collectSqlEnable;\n    }\n\n    public void setCollectSqlEnable(boolean collectSqlEnable) {\n        this.collectSqlEnable = collectSqlEnable;\n    }\n\n    public boolean isCollectSqlWallEnable() {\n        return collectSqlWallEnable;\n    }\n\n    public void setCollectSqlWallEnable(boolean collectSqlWallEnable) {\n        this.collectSqlWallEnable = collectSqlWallEnable;\n    }\n\n    public boolean isCollectSpringMethodEnable() {\n        return collectSpringMethodEnable;\n    }\n\n    public void setCollectSpringMethodEnable(boolean collectSpringMethodEnable) {\n        this.collectSpringMethodEnable = collectSpringMethodEnable;\n    }\n\n    public boolean isCollectWebAppEnable() {\n        return collectWebAppEnable;\n    }\n\n    public void setCollectWebAppEnable(boolean collectWebAppEnable) {\n        this.collectWebAppEnable = collectWebAppEnable;\n    }\n\n    public boolean isCollectWebURIEnable() {\n        return collectWebURIEnable;\n    }\n\n    public void setCollectWebURIEnable(boolean collectWebURIEnable) {\n        this.collectWebURIEnable = collectWebURIEnable;\n    }\n\n    public int getSchedulerThreadSize() {\n        return schedulerThreadSize;\n    }\n\n    public void setSchedulerThreadSize(int schedulerThreadSize) {\n        this.schedulerThreadSize = schedulerThreadSize;\n    }\n\n    public String getDomain() {\n        return domain;\n    }\n\n    public void setDomain(String domain) {\n        this.domain = domain;\n    }\n\n    public String getApp() {\n        return app;\n    }\n\n    public void setApp(String app) {\n        this.app = app;\n    }\n\n    public String getCluster() {\n        return cluster;\n    }\n\n    public void setCluster(String cluster) {\n        this.cluster = cluster;\n    }\n\n    public String getHost() {\n        return host;\n    }\n\n    public void setHost(String host) {\n        this.host = host;\n    }\n\n    public int getPid() {\n        return pid;\n    }\n\n    public void setPid(int pid) {\n        this.pid = pid;\n    }\n\n    public static InetAddress getLocalIPAddress() {\n        try {\n            Enumeration<?> netInterfaces = NetworkInterface.getNetworkInterfaces();\n            InetAddress inetAddress = null;\n            while (netInterfaces.hasMoreElements()) {\n                NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();\n                Enumeration<?> e2 = ni.getInetAddresses();\n                while (e2.hasMoreElements()) {\n                    inetAddress = (InetAddress) e2.nextElement();\n                    if (!inetAddress.isLoopbackAddress() && !inetAddress.getHostAddress().contains(\":\")) {\n                        return inetAddress;\n                    }\n                }\n            }\n        } catch (Exception e) {\n            LOG.error(\"getLocalIP error\", e);\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/MonitorContext.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class MonitorContext {\n    public static String DEFAULT_DOMAIN;\n\n    private final Map<String, Object> attributes = new HashMap<String, Object>();\n\n    private String domain = \"default\";\n    private String app = \"default\";\n    private String cluster = \"default\";\n    private String host;\n    private int pid;\n\n    private Date collectTime;\n    private Date startTime;\n\n    public MonitorContext() {\n    }\n\n    public Date getCollectTime() {\n        return collectTime;\n    }\n\n    public void setCollectTime(Date collectTime) {\n        this.collectTime = collectTime;\n    }\n\n    public Date getStartTime() {\n        return startTime;\n    }\n\n    public void setStartTime(Date startTime) {\n        this.startTime = startTime;\n    }\n\n    public Map<String, Object> getAttributes() {\n        return attributes;\n    }\n\n    public int getPID() {\n        return pid;\n    }\n\n    public void setPID(int pid) {\n        this.pid = pid;\n    }\n\n    public String getHost() {\n        return host;\n    }\n\n    public void setHost(String host) {\n        this.host = host;\n    }\n\n    public int getPid() {\n        return pid;\n    }\n\n    public void setPid(int pid) {\n        this.pid = pid;\n    }\n\n    public String getDomain() {\n        return domain;\n    }\n\n    public void setDomain(String domain) {\n        this.domain = domain;\n    }\n\n    public String getApp() {\n        return app;\n    }\n\n    public void setApp(String app) {\n        this.app = app;\n    }\n\n    public String getCluster() {\n        return cluster;\n    }\n\n    public void setCluster(String cluster) {\n        this.cluster = cluster;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/MonitorServlet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor;\n\nimport com.alibaba.druid.support.http.ResourceServlet;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n@SuppressWarnings(\"serial\")\npublic class MonitorServlet extends ResourceServlet {\n    private String mappingPath = \"support/http/resources\";\n    private Set<String> mapping = new HashSet<String>();\n\n    public MonitorServlet() {\n        super(\"support/monitor/resources\");\n\n        mapping.add(\"/css/bootstrap.min.css\");\n        mapping.add(\"/js/bootstrap.min.js\");\n        mapping.add(\"/js/jquery.min.js\");\n    }\n\n    protected String getFilePath(String fileName) {\n        if (mapping.contains(fileName)) {\n            return mappingPath + fileName;\n        }\n\n        return super.getFilePath(fileName);\n    }\n\n    @Override\n    protected String process(String url) {\n        // data.json?type=dataSource\n        // data.json?type=sql\n        // data.json?type=webapp\n        // data.json?type=weburi\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/annotation/AggregateType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.annotation;\n\npublic enum AggregateType {\n    None, //\n    Sum, //\n    Max, //\n    Last\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/annotation/MField.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\npublic @interface MField {\n    String name() default \"\";\n\n    boolean groupBy() default false;\n\n    AggregateType aggregate();\n\n    String hashFor() default \"\";\n\n    String hashForType() default \"\";\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/annotation/MTable.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface MTable {\n    String name();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDao.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.dao;\n\nimport com.alibaba.druid.pool.DruidDataSourceStatValue;\nimport com.alibaba.druid.stat.JdbcSqlStatValue;\nimport com.alibaba.druid.support.http.stat.WebAppStatValue;\nimport com.alibaba.druid.support.http.stat.WebURIStatValue;\nimport com.alibaba.druid.support.monitor.MonitorContext;\nimport com.alibaba.druid.support.spring.stat.SpringMethodStatValue;\nimport com.alibaba.druid.wall.WallProviderStatValue;\n\nimport java.sql.SQLException;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\npublic interface MonitorDao {\n    void saveSql(MonitorContext ctx, List<DruidDataSourceStatValue> statList);\n\n    void saveSqlWall(MonitorContext ctx, List<WallProviderStatValue> statList);\n\n    void saveSpringMethod(MonitorContext ctx, List<SpringMethodStatValue> methodList);\n\n    void saveWebURI(MonitorContext ctx, List<WebURIStatValue> uriList);\n\n    void saveWebApp(MonitorContext ctx, List<WebAppStatValue> uriList);\n\n    List<JdbcSqlStatValue> loadSqlList(Map<String, Object> filters);\n\n    void insertAppIfNotExits(String domain, String app) throws SQLException;\n\n    void insertClusterIfNotExits(String domain, String app, String cluster) throws SQLException;\n\n    void insertOrUpdateInstance(String domain, String app, String cluster, String host, String ip, Date startTime,\n                                long pid) throws SQLException;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/dao/MonitorDaoJdbcImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.dao;\n\nimport com.alibaba.druid.DruidRuntimeException;\nimport com.alibaba.druid.pool.DruidDataSourceStatValue;\nimport com.alibaba.druid.stat.JdbcSqlStatValue;\nimport com.alibaba.druid.support.http.stat.WebAppStatValue;\nimport com.alibaba.druid.support.http.stat.WebURIStatValue;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.support.monitor.MonitorContext;\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\nimport com.alibaba.druid.support.monitor.entity.MonitorApp;\nimport com.alibaba.druid.support.monitor.entity.MonitorCluster;\nimport com.alibaba.druid.support.monitor.entity.MonitorInstance;\nimport com.alibaba.druid.support.spring.stat.SpringMethodStatValue;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.util.Utils;\nimport com.alibaba.druid.wall.WallFunctionStatValue;\nimport com.alibaba.druid.wall.WallProviderStatValue;\nimport com.alibaba.druid.wall.WallSqlStatValue;\nimport com.alibaba.druid.wall.WallTableStatValue;\n\nimport javax.sql.DataSource;\n\nimport java.lang.reflect.Field;\nimport java.sql.*;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\npublic class MonitorDaoJdbcImpl implements MonitorDao {\n    private static final Log LOG = LogFactory.getLog(MonitorDaoJdbcImpl.class);\n\n    private DataSource dataSource;\n\n    private BeanInfo dataSourceStatBeanInfo = new BeanInfo(\n            DruidDataSourceStatValue.class);\n    private BeanInfo sqlStatBeanInfo = new BeanInfo(\n            JdbcSqlStatValue.class);\n    private BeanInfo springMethodStatBeanInfo = new BeanInfo(\n            SpringMethodStatValue.class);\n    private BeanInfo webURIStatBeanInfo = new BeanInfo(\n            WebURIStatValue.class);\n    private BeanInfo webAppStatBeanInfo = new BeanInfo(\n            WebAppStatValue.class);\n\n    private BeanInfo wallProviderStatBeanInfo = new BeanInfo(\n            WallProviderStatValue.class);\n    private BeanInfo wallSqlStatBeanInfo = new BeanInfo(\n            WallSqlStatValue.class);\n    private BeanInfo wallTableStatBeanInfo = new BeanInfo(\n            WallTableStatValue.class);\n    private BeanInfo wallFunctionStatBeanInfo = new BeanInfo(\n            WallFunctionStatValue.class);\n\n    private ConcurrentMap<String, ConcurrentMap<Long, String>> cacheMap = new ConcurrentHashMap<String, ConcurrentMap<Long, String>>();\n\n    public MonitorDaoJdbcImpl() {\n    }\n\n    public void createTables(String dbType) {\n        String[] resources = new String[]{\"basic.sql\", //\n                \"const.sql\", //\n                \"datasource.sql\", //\n                \"springmethod.sql\", //\n                \"sql.sql\", //\n                \"webapp.sql\", //\n                \"weburi.sql\", \"wall.sql\"};\n\n        for (String item : resources) {\n            String path = \"/support/monitor/\" + dbType + \"/\" + item;\n            try {\n                String text = Utils.readFromResource(path);\n                String[] sqls = text.split(\";\");\n                for (String sql : sqls) {\n                    JdbcUtils.execute(dataSource, sql);\n                }\n            } catch (Exception ex) {\n                LOG.error(\"create table error\", ex);\n            }\n        }\n    }\n\n    public DataSource getDataSource() {\n        return dataSource;\n    }\n\n    public void setDataSource(DataSource dataSource) {\n        this.dataSource = dataSource;\n    }\n\n    @Override\n    public void saveSql(MonitorContext ctx, List<DruidDataSourceStatValue> dataSourceList) {\n        save(dataSourceStatBeanInfo, ctx, dataSourceList);\n\n        for (DruidDataSourceStatValue dataSourceStatValue : dataSourceList) {\n            List<JdbcSqlStatValue> sqlList = dataSourceStatValue.getSqlList();\n            save(sqlStatBeanInfo, ctx, sqlList);\n        }\n    }\n\n    @Override\n    public void saveSpringMethod(MonitorContext ctx, List<SpringMethodStatValue> list) {\n        save(springMethodStatBeanInfo, ctx, list);\n    }\n\n    @Override\n    public void saveWebURI(MonitorContext ctx, List<WebURIStatValue> list) {\n        save(webURIStatBeanInfo, ctx, list);\n    }\n\n    @Override\n    public void saveSqlWall(MonitorContext ctx, List<WallProviderStatValue> statList) {\n        save(wallProviderStatBeanInfo, ctx, statList);\n\n        for (WallProviderStatValue providerStat : statList) {\n            save(wallSqlStatBeanInfo, ctx, providerStat.getWhiteList());\n            save(wallSqlStatBeanInfo, ctx, providerStat.getBlackList());\n\n            save(wallTableStatBeanInfo, ctx, providerStat.getTables());\n            save(wallFunctionStatBeanInfo, ctx, providerStat.getFunctions());\n        }\n    }\n\n    @Override\n    public void saveWebApp(MonitorContext ctx, List<WebAppStatValue> list) {\n        save(webAppStatBeanInfo, ctx, list);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public List<JdbcSqlStatValue> loadSqlList(Map<String, Object> filters) {\n        return ((List<JdbcSqlStatValue>) load(sqlStatBeanInfo, filters));\n    }\n\n    static Integer getInteger(Map<String, Object> filters, String key) {\n        Object value = filters.get(key);\n\n        if (value == null) {\n            return null;\n        }\n\n        if (value instanceof Integer) {\n            return (Integer) value;\n        }\n\n        if (value instanceof Number) {\n            return ((Number) value).intValue();\n        }\n\n        if (value instanceof String) {\n            String text = (String) value;\n            if (StringUtils.isEmpty(text)) {\n                return null;\n            }\n\n            return Integer.parseInt(text);\n        }\n\n        return null;\n    }\n\n    static Date getDate(Map<String, Object> filters, String key) {\n        Object value = filters.get(key);\n\n        if (value == null) {\n            return null;\n        }\n\n        if (value instanceof Number) {\n            long millis = ((Number) value).longValue();\n            return new Date(millis);\n        }\n\n        if (value instanceof String) {\n            String text = (String) value;\n            if (StringUtils.isEmpty(text)) {\n                return null;\n            }\n\n            try {\n                return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").parse(text);\n            } catch (ParseException e) {\n                LOG.error(\"parse filter error\", e);\n                return null;\n            }\n        }\n\n        return null;\n    }\n\n    private List<?> load(BeanInfo beanInfo, Map<String, Object> filters) {\n        List<Object> list = new ArrayList<Object>();\n\n        StringBuilder buf = new StringBuilder();\n\n        buf.append(\"SELECT \");\n\n        List<FieldInfo> fields = beanInfo.getFields();\n        for (int i = 0; i < fields.size(); ++i) {\n            FieldInfo fieldInfo = fields.get(i);\n            if (i != 0) {\n                buf.append(\", \");\n            }\n\n            AggregateType aggregateType = fieldInfo.getField().getAnnotation(MField.class).aggregate();\n\n            switch (aggregateType) {\n                case Sum:\n                    buf.append(\"SUM(\");\n                    buf.append(fieldInfo.getColumnName());\n                    buf.append(\")\");\n                    break;\n                case Max:\n                    buf.append(\"MAX(\");\n                    buf.append(fieldInfo.getColumnName());\n                    buf.append(\")\");\n                    break;\n                case None:\n                case Last:\n                default:\n                    buf.append(fieldInfo.getColumnName());\n                    break;\n            }\n        }\n\n        buf.append(\"\\nFROM \");\n        buf.append(getTableName(beanInfo));\n        buf.append(\"\\nWHERE collectTime >= ? AND collectTime <= ? AND domain = ? AND app = ? AND cluster = ?\");\n\n        Date startTime = getDate(filters, \"startTime\");\n        if (startTime == null) {\n            long now = System.currentTimeMillis();\n            startTime = new Date(now - 1000 * 60 * 30); // 3 hours\n        }\n\n        Date endTime = getDate(filters, \"endTime\");\n        if (endTime == null) {\n            endTime = new Date(); // now\n        }\n\n        String domain = (String) filters.get(\"domain\");\n        if (StringUtils.isEmpty(domain)) {\n            domain = \"default\";\n        }\n        String app = (String) filters.get(\"app\");\n        if (StringUtils.isEmpty(app)) {\n            app = \"default\";\n        }\n\n        String cluster = (String) filters.get(\"cluster\");\n        if (StringUtils.isEmpty(cluster)) {\n            cluster = \"default\";\n        }\n\n        String host = (String) filters.get(\"host\");\n        if (!StringUtils.isEmpty(host)) {\n            buf.append(\"\\nAND host = ?\");\n        }\n\n        Integer pid = getInteger(filters, \"pid\");\n        if (pid != null) {\n            buf.append(\"\\nAND pid = ?\");\n        }\n\n        List<FieldInfo> groupByFields = beanInfo.getGroupByFields();\n        for (int i = 0; i < groupByFields.size(); ++i) {\n            if (i == 0) {\n                buf.append(\"\\nGROUP BY \");\n            } else {\n                buf.append(\", \");\n            }\n            FieldInfo fieldInfo = groupByFields.get(i);\n            buf.append(fieldInfo.getColumnName());\n        }\n\n        {\n            Integer offset = (Integer) filters.get(\"offset\");\n            Integer limit = (Integer) filters.get(\"limit\");\n\n            if (limit == null) {\n                limit = 1000;\n            }\n\n            buf.append(\"\\nLIMIT \");\n            if (offset != null) {\n                buf.append(offset);\n                buf.append(\", \");\n            }\n            buf.append(limit);\n        }\n\n        String sql = buf.toString();\n\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            int paramIndex = 1;\n\n            stmt.setTimestamp(paramIndex++, new Timestamp(startTime.getTime()));\n            stmt.setTimestamp(paramIndex++, new Timestamp(endTime.getTime()));\n\n            stmt.setString(paramIndex++, domain);\n            stmt.setString(paramIndex++, app);\n            stmt.setString(paramIndex++, cluster);\n\n            if (!StringUtils.isEmpty(host)) {\n                stmt.setString(paramIndex++, host);\n            }\n\n            if (pid != null) {\n                stmt.setInt(paramIndex++, pid);\n            }\n\n            rs = stmt.executeQuery();\n            while (rs.next()) {\n                Object object = createInstance(beanInfo);\n\n                for (int i = 0; i < fields.size(); ++i) {\n                    FieldInfo field = fields.get(i);\n                    readFieldValue(object, field, rs, i + 1);\n                }\n\n                list.add(object);\n            }\n\n            stmt.close();\n        } catch (SQLException ex) {\n            LOG.error(\"save sql error\", ex);\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n\n        for (FieldInfo hashField : beanInfo.getHashFields()) {\n            loadHashValue(hashField, list, filters);\n        }\n\n        return list;\n    }\n\n    protected void readFieldValue(Object object, FieldInfo field, ResultSet rs, int paramIndex) throws SQLException {\n        Class<?> fieldType = field.getFieldType();\n        Object fieldValue = null;\n        if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) {\n            fieldValue = rs.getInt(paramIndex);\n        } else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) {\n            fieldValue = rs.getLong(paramIndex);\n        } else if (fieldType.equals(String.class)) {\n            fieldValue = rs.getString(paramIndex);\n        } else if (fieldType.equals(Date.class)) {\n            Timestamp timestamp = rs.getTimestamp(paramIndex);\n            if (timestamp != null) {\n                fieldValue = new Date(timestamp.getTime());\n            }\n        } else {\n            throw new UnsupportedOperationException();\n        }\n        try {\n            field.getField().set(object, fieldValue);\n        } catch (IllegalArgumentException e) {\n            throw new DruidRuntimeException(\"set field error\" + field.getField(), e);\n        } catch (IllegalAccessException e) {\n            throw new DruidRuntimeException(\"set field error\" + field.getField(), e);\n        }\n    }\n\n    private void loadHashValue(FieldInfo hashField, List<?> list, Map<String, Object> filters) {\n        String domain = (String) filters.get(\"domain\");\n        if (StringUtils.isEmpty(domain)) {\n            domain = \"default\";\n        }\n        String app = (String) filters.get(\"app\");\n        if (StringUtils.isEmpty(app)) {\n            app = \"default\";\n        }\n\n        for (Object statValue : list) {\n            try {\n                Long hash = (Long) hashField.field.get(statValue);\n                String value = cacheGet(hashField.getHashForType(), hash);\n\n                if (value == null) {\n                    value = getConstValueFromDb(domain, app, hashField.getHashForType(), hash);\n                }\n                hashField.getHashFor().set(statValue, value);\n            } catch (IllegalArgumentException e) {\n                throw new DruidRuntimeException(\"set field error\" + hashField.getField(), e);\n            } catch (IllegalAccessException e) {\n                throw new DruidRuntimeException(\"set field error\" + hashField.getField(), e);\n            }\n        }\n    }\n\n    protected String getConstValueFromDb(String domain, String app, String type, Long hash) {\n        String sql = \"select value from druid_const where domain = ? AND app = ? and type = ? and hash = ?\";\n\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            stmt.setString(1, domain);\n            stmt.setString(2, app);\n            stmt.setString(3, type);\n            stmt.setLong(4, hash);\n\n            rs = stmt.executeQuery();\n            if (rs.next()) {\n                return rs.getString(1);\n            }\n        } catch (SQLException ex) {\n            LOG.error(\"save const error error\", ex);\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n\n        return null;\n    }\n\n    private void saveHash(FieldInfo hashField, MonitorContext ctx, List<?> list) {\n        final String hashType = hashField.getHashForType();\n\n        for (Object statValue : list) {\n            try {\n                Long hash = (Long) hashField.field.get(statValue);\n                if (!cacheContains(hashField.getHashForType(), hash)) {\n                    String value = (String) hashField.getHashFor().get(statValue);\n                    final String sql = \"insert into druid_const (domain, app, type, hash, value) values (?, ?, ?, ?, ?)\";\n                    Connection conn = null;\n                    PreparedStatement stmt = null;\n                    try {\n                        conn = dataSource.getConnection();\n                        stmt = conn.prepareStatement(sql);\n\n                        stmt.setString(1, ctx.getDomain());\n                        stmt.setString(2, ctx.getApp());\n                        stmt.setString(3, hashType);\n                        stmt.setLong(4, hash);\n                        stmt.setString(5, value);\n\n                        stmt.execute();\n                        stmt.close();\n\n                    } catch (SQLException ex) {\n                        // LOG.error(\"save const error error\", ex);\n                    } finally {\n                        JdbcUtils.close(stmt);\n                        JdbcUtils.close(conn);\n                    }\n                    cachePut(hashField.getHashForType(), hash, value);\n                }\n            } catch (IllegalArgumentException e) {\n                throw new DruidRuntimeException(\"set field error\" + hashField.getField(), e);\n            } catch (IllegalAccessException e) {\n                throw new DruidRuntimeException(\"set field error\" + hashField.getField(), e);\n            }\n        }\n    }\n\n    private void save(BeanInfo beanInfo, MonitorContext ctx, List<?> list) {\n        if (list.isEmpty()) {\n            return;\n        }\n\n        for (FieldInfo hashField : beanInfo.getHashFields()) {\n            saveHash(hashField, ctx, list);\n        }\n\n        String sql = buildInsertSql(beanInfo);\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            for (Object statValue : list) {\n                setParameterForSqlStat(beanInfo, ctx, stmt, statValue);\n                stmt.addBatch();\n            }\n\n            stmt.executeBatch();\n\n            stmt.close();\n        } catch (SQLException ex) {\n            LOG.error(\"save sql error\", ex);\n        } finally {\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    protected void setParameterForSqlStat(BeanInfo beanInfo, //\n                                          MonitorContext ctx, //\n                                          PreparedStatement stmt, //\n                                          Object sqlStat) throws SQLException {\n        int paramIndex = 1;\n\n        setParam(stmt, paramIndex++, ctx.getDomain());\n        setParam(stmt, paramIndex++, ctx.getApp());\n        setParam(stmt, paramIndex++, ctx.getCluster());\n        setParam(stmt, paramIndex++, ctx.getHost());\n        setParam(stmt, paramIndex++, ctx.getPID());\n        setParam(stmt, paramIndex++, ctx.getCollectTime());\n\n        try {\n            List<FieldInfo> fields = beanInfo.getFields();\n            for (FieldInfo field : fields) {\n                Class<?> fieldType = field.getFieldType();\n                Object value = field.getField().get(sqlStat);\n\n                if (fieldType.equals(int.class) || fieldType.equals(Integer.class)) {\n                    setParam(stmt, paramIndex, (Integer) value);\n                } else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) {\n                    setParam(stmt, paramIndex, (Long) value);\n                } else if (fieldType.equals(String.class)) {\n                    setParam(stmt, paramIndex, (String) value);\n                } else if (fieldType.equals(Date.class)) {\n                    setParam(stmt, paramIndex, (Date) value);\n                } else if (fieldType.equals(boolean.class) || fieldType.equals(Boolean.class)) {\n                    setParam(stmt, paramIndex, (Boolean) value);\n                } else {\n                    throw new UnsupportedOperationException(\"not support type : \" + fieldType);\n                }\n\n                paramIndex++;\n            }\n        } catch (RuntimeException ex) {\n            throw ex;\n        } catch (Exception ex) {\n            throw new DruidRuntimeException(\"setParam error\", ex);\n        }\n    }\n\n    public Object createInstance(BeanInfo beanInfo) {\n        try {\n            return beanInfo.getClazz().newInstance();\n        } catch (InstantiationException ex) {\n            throw new DruidRuntimeException(\"create instance error\", ex);\n        } catch (IllegalAccessException ex) {\n            throw new DruidRuntimeException(\"create instance error\", ex);\n        }\n    }\n\n    public String buildInsertSql(BeanInfo beanInfo) {\n        String sql = beanInfo.insertSql;\n\n        if (sql != null) {\n            return sql;\n        }\n\n        StringBuilder buf = new StringBuilder();\n\n        buf.append(\"INSERT INTO \") //\n                .append(getTableName(beanInfo));\n\n        buf.append(\" (domain, app, cluster, host, pid, collectTime\");\n        List<FieldInfo> fields = beanInfo.getFields();\n        for (FieldInfo field : fields) {\n            buf.append(\", \");\n            buf.append(field.getColumnName());\n        }\n        buf.append(\")\\nVALUES (?, ?, ?, ?, ?, ?\");\n        for (int i = 0; i < fields.size(); ++i) {\n            buf.append(\", ?\");\n        }\n        buf.append(\")\");\n        sql = buf.toString();\n        beanInfo.setInsertSql(sql);\n        return sql;\n    }\n\n    public String getTableName(BeanInfo beanInfo) {\n        return beanInfo.getTableName();\n    }\n\n    protected long getSqlHash(String sql) {\n        return Utils.fnv_64(sql);\n    }\n\n    static void setParam(PreparedStatement stmt, int paramIndex, String value) throws SQLException {\n        if (value == null) {\n            stmt.setNull(paramIndex, Types.VARCHAR);\n        } else {\n            stmt.setString(paramIndex, value);\n        }\n    }\n\n    static void setParam(PreparedStatement stmt, int paramIndex, Boolean value) throws SQLException {\n        if (value == null) {\n            stmt.setNull(paramIndex, Types.BOOLEAN);\n        } else {\n            stmt.setBoolean(paramIndex, value);\n        }\n    }\n\n    static void setParam(PreparedStatement stmt, int paramIndex, Long value) throws SQLException {\n        if (value == null || value == 0) {\n            stmt.setNull(paramIndex, Types.BIGINT);\n        } else {\n            stmt.setLong(paramIndex, value);\n        }\n    }\n\n    static void setParam(PreparedStatement stmt, int paramIndex, Integer value) throws SQLException {\n        if (value == null || value == 0) {\n            stmt.setNull(paramIndex, Types.INTEGER);\n        } else {\n            stmt.setInt(paramIndex, value);\n        }\n    }\n\n    static void setParam(PreparedStatement stmt, int paramIndex, Date value) throws SQLException {\n        if (value == null) {\n            stmt.setNull(paramIndex, Types.TIMESTAMP);\n        } else {\n            stmt.setTimestamp(paramIndex, new Timestamp(value.getTime()));\n        }\n    }\n\n    public static class BeanInfo {\n        private final Class<?> clazz;\n        private final List<FieldInfo> fields = new ArrayList<FieldInfo>();\n        private final List<FieldInfo> groupByFields = new ArrayList<FieldInfo>();\n        private final List<FieldInfo> hashFields = new ArrayList<FieldInfo>();\n        private final String tableName;\n\n        private String insertSql;\n\n        public BeanInfo(Class<?> clazz) {\n            this.clazz = clazz;\n\n            {\n                MTable annotation = clazz.getAnnotation(MTable.class);\n                if (annotation == null) {\n                    throw new IllegalArgumentException(clazz.getName() + \" not contains @MTable\");\n                }\n\n                tableName = annotation.name();\n            }\n\n            for (Field field : clazz.getDeclaredFields()) {\n                MField annotation = field.getAnnotation(MField.class);\n                if (annotation == null) {\n                    continue;\n                }\n\n                String columnName = annotation.name();\n                if (StringUtils.isEmpty(columnName)) {\n                    columnName = field.getName();\n                }\n\n                Field hashFor = null;\n                String hashForType = null;\n                if (!StringUtils.isEmpty(annotation.hashFor())) {\n                    try {\n                        hashFor = clazz.getDeclaredField(annotation.hashFor());\n                        hashForType = annotation.hashForType();\n                    } catch (Exception e) {\n                        throw new IllegalStateException(\"hashFor error\", e);\n                    }\n                }\n\n                FieldInfo fieldInfo = new FieldInfo(field, columnName, hashFor, hashForType);\n                fields.add(fieldInfo);\n\n                if (annotation.groupBy()) {\n                    groupByFields.add(fieldInfo);\n                }\n\n                if (hashFor != null) {\n                    hashFields.add(fieldInfo);\n                }\n            }\n        }\n\n        public String getTableName() {\n            return tableName;\n        }\n\n        public Class<?> getClazz() {\n            return clazz;\n        }\n\n        public String getInsertSql() {\n            return insertSql;\n        }\n\n        public void setInsertSql(String insertSql) {\n            this.insertSql = insertSql;\n        }\n\n        public List<FieldInfo> getFields() {\n            return fields;\n        }\n\n        public List<FieldInfo> getGroupByFields() {\n            return groupByFields;\n        }\n\n        public List<FieldInfo> getHashFields() {\n            return hashFields;\n        }\n\n    }\n\n    public boolean cacheContains(String type, Long hash) {\n        Map<Long, String> cache = cacheMap.get(type);\n        if (cache == null) {\n            return false;\n        }\n        return cache.containsKey(hash);\n    }\n\n    public String cacheGet(String type, Long hash) {\n        Map<Long, String> cache = cacheMap.get(type);\n        if (cache == null) {\n            return null;\n        }\n        return cache.get(hash);\n    }\n\n    public void cachePut(String type, Long hash, String value) {\n        ConcurrentMap<Long, String> cache = cacheMap.get(type);\n        if (cache == null) {\n            cacheMap.putIfAbsent(type, new ConcurrentHashMap<Long, String>(16, 0.75f, 1));\n            cache = cacheMap.get(type);\n        }\n        cache.putIfAbsent(hash, value);\n    }\n\n    public static class FieldInfo {\n        private final Field field;\n        private final String columnName;\n        private final Field hashFor;\n        private final String hashForType;\n\n        public FieldInfo(Field field, String columnName, Field hashFor, String hashForType) {\n            this.field = field;\n            this.columnName = columnName;\n            this.hashFor = hashFor;\n            this.hashForType = hashForType;\n\n            field.setAccessible(true);\n            if (hashFor != null) {\n                hashFor.setAccessible(true);\n            }\n        }\n\n        public String getHashForType() {\n            return hashForType;\n        }\n\n        public Field getField() {\n            return field;\n        }\n\n        public Field getHashFor() {\n            return hashFor;\n        }\n\n        public String getColumnName() {\n            return columnName;\n        }\n\n        public Class<?> getFieldType() {\n            return field.getType();\n        }\n\n    }\n\n    public void insertAppIfNotExits(String domain, String app) throws SQLException {\n        MonitorApp monitorApp = findApp(domain, app);\n        if (monitorApp != null) {\n            return;\n        }\n\n        String sql = \"insert druid_app (domain, app) values (?, ?)\";\n        JdbcUtils.execute(dataSource, sql, domain, app);\n    }\n\n    public List<MonitorApp> listApp(String domain) throws SQLException {\n        List<MonitorApp> list = new ArrayList<MonitorApp>();\n\n        String sql = \"select id, domain, app from druid_app \"\n                + \" where domain = ?\";\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            stmt.setString(1, domain);\n\n            rs = stmt.executeQuery();\n            if (rs.next()) {\n                list.add(readApp(rs));\n            }\n\n            return list;\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    public MonitorApp findApp(String domain, String app) throws SQLException {\n        String sql = \"select id, domain, app from druid_app \"\n                + \" where domain = ? and app = ?\";\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            stmt.setString(1, domain);\n            stmt.setString(2, app);\n\n            rs = stmt.executeQuery();\n            if (rs.next()) {\n                return readApp(rs);\n            }\n\n            return null;\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    private MonitorApp readApp(ResultSet rs) throws SQLException {\n        MonitorApp app = new MonitorApp();\n\n        app.setId(rs.getLong(1));\n        app.setDomain(rs.getString(2));\n        app.setApp(rs.getString(3));\n\n        return app;\n    }\n\n    public List<MonitorCluster> listCluster(String domain, String app) throws SQLException {\n        List<MonitorCluster> list = new ArrayList<MonitorCluster>();\n\n        String sql = \"select id, domain, app, cluster from druid_cluster \"\n                + \" where domain = ?\";\n\n        if (app != null) {\n            sql += \" and app = ?\";\n        }\n\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            stmt.setString(1, domain);\n            if (app != null) {\n                stmt.setString(2, app);\n            }\n\n            rs = stmt.executeQuery();\n            if (rs.next()) {\n                list.add(readCluster(rs));\n            }\n\n            return list;\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    public void insertClusterIfNotExits(String domain, String app, String cluster) throws SQLException {\n        MonitorCluster monitorApp = findCluster(domain, app, cluster);\n        if (monitorApp != null) {\n            return;\n        }\n\n        String sql = \"insert druid_cluster (domain, app, cluster) values (?, ?, ?)\";\n        JdbcUtils.execute(dataSource, sql, domain, app, cluster);\n    }\n\n    public MonitorCluster findCluster(String domain, String app, String cluster) throws SQLException {\n        String sql = \"select id, domain, app, cluster from druid_cluster \"\n                + \" where domain = ? and app = ? and cluster = ?\";\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            stmt.setString(1, domain);\n            stmt.setString(2, app);\n            stmt.setString(3, cluster);\n\n            rs = stmt.executeQuery();\n            if (rs.next()) {\n                return readCluster(rs);\n            }\n\n            return null;\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    private MonitorCluster readCluster(ResultSet rs) throws SQLException {\n        MonitorCluster app = new MonitorCluster();\n\n        app.setId(rs.getLong(1));\n        app.setDomain(rs.getString(2));\n        app.setApp(rs.getString(3));\n        app.setCluster(rs.getString(4));\n\n        return app;\n    }\n\n    public void insertOrUpdateInstance(String domain, String app, String cluster, String host, String ip,\n                                       Date startTime, long pid) throws SQLException {\n        MonitorInstance monitorInst = findInst(domain, app, cluster, host);\n        if (monitorInst == null) {\n            String sql = \"insert into druid_inst (domain, app, cluster, host, ip, lastActiveTime, lastPID) \"\n                    + \" values (?, ?, ?, ?, ?, ?, ?)\";\n            JdbcUtils.execute(dataSource, sql, domain, app, cluster, host, ip, startTime, pid);\n        } else {\n            String sql = \"update druid_inst set ip = ?, lastActiveTime = ?, lastPID = ? \"\n                    + \" where domain = ? and app = ? and cluster = ? and host = ? \";\n            JdbcUtils.execute(dataSource, sql, ip, startTime, pid, domain, app, cluster, host);\n        }\n    }\n\n    public MonitorInstance findInst(String domain, String app, String cluster, String host) throws SQLException {\n        String sql = \"select id, domain, app, cluster, host, ip, lastActiveTime, lastPID from druid_inst \"\n                + \" where domain = ? and app = ? and cluster = ? and host = ? \"\n                + \" limit 1\";\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            stmt.setString(1, domain);\n            stmt.setString(2, app);\n            stmt.setString(3, cluster);\n            stmt.setString(4, host);\n\n            rs = stmt.executeQuery();\n            if (rs.next()) {\n                return readInst(rs);\n            }\n\n            return null;\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    public List<MonitorInstance> listInst(String domain, String app, String cluster) throws SQLException {\n        List<MonitorInstance> list = new ArrayList<MonitorInstance>();\n\n        String sql = \"select id, domain, app, cluster, host, ip, lastActiveTime, lastPID from druid_inst \"\n                + \"where domain = ?\";\n\n        if (app != null) {\n            sql += \" and app = ?\";\n        }\n\n        if (cluster != null) {\n            sql += \" and cluster = ?\";\n        }\n\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n\n            int paramIndex = 1;\n            stmt.setString(paramIndex++, domain);\n\n            if (app != null) {\n                stmt.setString(paramIndex++, app);\n            }\n\n            if (cluster != null) {\n                stmt.setString(paramIndex++, cluster);\n            }\n\n            rs = stmt.executeQuery();\n            if (rs.next()) {\n                list.add(readInst(rs));\n            }\n\n            return list;\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    private MonitorInstance readInst(ResultSet rs) throws SQLException {\n        MonitorInstance inst = new MonitorInstance();\n\n        inst.setId(rs.getLong(1));\n        inst.setDomain(rs.getString(2));\n        inst.setApp(rs.getString(3));\n        inst.setCluster(rs.getString(4));\n        inst.setHost(rs.getString(5));\n\n        inst.setIp(rs.getString(6));\n        inst.setLastActiveTime(rs.getTimestamp(7));\n        inst.setLastPID(rs.getLong(8));\n\n        return inst;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/entity/MonitorApp.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.entity;\n\npublic class MonitorApp {\n    private long id;\n    private String domain;\n    private String app;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getDomain() {\n        return domain;\n    }\n\n    public void setDomain(String domain) {\n        this.domain = domain;\n    }\n\n    public String getApp() {\n        return app;\n    }\n\n    public void setApp(String app) {\n        this.app = app;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/entity/MonitorCluster.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.entity;\n\npublic class MonitorCluster {\n    private long id;\n    private String domain;\n    private String app;\n    private String cluster;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getDomain() {\n        return domain;\n    }\n\n    public void setDomain(String domain) {\n        this.domain = domain;\n    }\n\n    public String getApp() {\n        return app;\n    }\n\n    public void setApp(String app) {\n        this.app = app;\n    }\n\n    public String getCluster() {\n        return cluster;\n    }\n\n    public void setCluster(String cluster) {\n        this.cluster = cluster;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/monitor/entity/MonitorInstance.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.monitor.entity;\n\nimport java.util.Date;\n\npublic class MonitorInstance {\n    private long id;\n    private String domain;\n    private String app;\n    private String cluster;\n    private String host;\n    private String ip;\n    private Date lastActiveTime;\n    private Long lastPID;\n\n    public long getId() {\n        return id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getDomain() {\n        return domain;\n    }\n\n    public void setDomain(String domain) {\n        this.domain = domain;\n    }\n\n    public String getApp() {\n        return app;\n    }\n\n    public void setApp(String app) {\n        this.app = app;\n    }\n\n    public String getCluster() {\n        return cluster;\n    }\n\n    public void setCluster(String cluster) {\n        this.cluster = cluster;\n    }\n\n    public String getHost() {\n        return host;\n    }\n\n    public void setHost(String host) {\n        this.host = host;\n    }\n\n    public String getIp() {\n        return ip;\n    }\n\n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n\n    public Date getLastActiveTime() {\n        return lastActiveTime;\n    }\n\n    public void setLastActiveTime(Date lastActiveTime) {\n        this.lastActiveTime = lastActiveTime;\n    }\n\n    public Long getLastPID() {\n        return lastPID;\n    }\n\n    public void setLastPID(Long lastPID) {\n        this.lastPID = lastPID;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/ExportColumns.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\n\npublic class ExportColumns extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null);\n    }\n\n    public String evaluate(String sql, String dbType) {\n        try {\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.valueOf(dbType));\n            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.valueOf(dbType));\n\n            for (SQLStatement stmt : statementList) {\n                stmt.accept(visitor);\n            }\n\n            StringBuilder buf = new StringBuilder();\n\n            for (TableStat.Column column : visitor.getColumns()) {\n                if (buf.length() != 0) {\n                    buf.append(',');\n                }\n                buf.append(column.toString());\n            }\n\n            return buf.toString();\n        } catch (Throwable ex) {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/ExportConditionColumns.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\n\npublic class ExportConditionColumns extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null);\n    }\n\n    public String evaluate(String sql, String dbTypeName) {\n        DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n        try {\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);\n            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n\n            for (SQLStatement stmt : statementList) {\n                stmt.accept(visitor);\n            }\n\n            StringBuilder buf = new StringBuilder();\n\n            for (TableStat.Column column : visitor.getColumns()) {\n                if ((!column.isWhere()) && !column.isJoin()) {\n                    continue;\n                }\n\n                if (buf.length() != 0) {\n                    buf.append(',');\n                }\n                buf.append(column.toString());\n            }\n\n            return buf.toString();\n        } catch (Exception ex) {\n            System.err.println(\"error sql : \" + sql);\n            ex.printStackTrace();\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/ExportConditions.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.stat.TableStat.Condition;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ExportConditions extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null);\n    }\n\n    public String evaluate(String sql, String dbType) {\n        return evaluate(sql, dbType, null);\n    }\n\n    public String evaluate(String sql, String dbTypeName, Boolean compactValues) {\n        DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n        try {\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);\n            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n\n            for (SQLStatement stmt : statementList) {\n                stmt.accept(visitor);\n            }\n\n            List<List<Object>> rows = new ArrayList<List<Object>>();\n            List<Condition> conditions = visitor.getConditions();\n            for (int i = 0; i < conditions.size(); ++i) {\n                TableStat.Condition condition = conditions.get(i);\n                Column column = condition.getColumn();\n                String operator = condition.getOperator();\n                List<Object> values = condition.getValues();\n\n                List<Object> row = new ArrayList<Object>();\n                row.add(column.getTable());\n                row.add(column.getName());\n                row.add(operator);\n                if (values.isEmpty()) {\n                    row.add(null);\n                } else if (values.size() == 1) {\n                    if (compactValues != null && compactValues.booleanValue()) {\n                        row.add(values);\n                    } else {\n                        row.add(values.get(0));\n                    }\n                } else {\n                    row.add(values);\n                }\n                rows.add(row);\n            }\n\n            return JSONUtils.toJSONString(rows);\n        } catch (Exception ex) {\n            System.err.println(\"error sql : \" + sql);\n            ex.printStackTrace();\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/ExportSelectListColumns.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\n\npublic class ExportSelectListColumns extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null);\n    }\n\n    public String evaluate(String sql, String dbType) {\n        try {\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.valueOf(dbType));\n            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.valueOf(dbType));\n\n            for (SQLStatement stmt : statementList) {\n                stmt.accept(visitor);\n            }\n\n            StringBuilder buf = new StringBuilder();\n\n            for (TableStat.Column column : visitor.getColumns()) {\n                if (!column.isSelect()) {\n                    continue;\n                }\n\n                if (buf.length() != 0) {\n                    buf.append(',');\n                }\n                buf.append(column.toString());\n            }\n\n            return buf.toString();\n        } catch (Exception ex) {\n            System.err.println(\"error sql : \" + sql);\n            ex.printStackTrace();\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/ExportTables.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic class ExportTables extends UDF {\n    public String evaluate(String sql) throws Throwable {\n        return evaluate(sql, null, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName) throws Throwable {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName, boolean throwError) throws Throwable {\n        DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n\n        Throwable error = null;\n        try {\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);\n            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n\n            for (SQLStatement stmt : statementList) {\n                stmt.accept(visitor);\n            }\n\n            StringBuilder buf = new StringBuilder();\n\n            for (Map.Entry<TableStat.Name, TableStat> entry : visitor.getTables().entrySet()) {\n                TableStat.Name name = entry.getKey();\n\n                if (buf.length() != 0) {\n                    buf.append(',');\n                }\n                buf.append(name.toString());\n            }\n\n            return buf.toString();\n        } catch (Exception ignored) {\n            // skip\n        } catch (StackOverflowError ignored) {\n            // skip\n        }\n\n        if (throwError && error != null) {\n            throw error;\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/MetaSqlExtract.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.aliyun.odps.udf.UDF;\nimport org.apache.commons.lang.StringEscapeUtils;\n\npublic class MetaSqlExtract extends UDF {\n    public String evaluate(String xml) {\n        if (xml == null || xml.length() == 0) {\n            return null;\n        }\n\n        int p0 = xml.indexOf(\"<Query>\");\n        if (p0 == -1) {\n            return null;\n        }\n        p0 += \"<Query>\".length();\n\n        int p1 = xml.indexOf(\"</Query>\", p0);\n        if (p1 == -1) {\n            return null;\n        }\n\n        String sql = xml.substring(p0, p1);\n        int p2 = xml.indexOf(\"<![CDATA[\");\n        if (p2 != -1) {\n            if (sql.length() > \"<![CDATA[\".length() + 3) {\n                return sql.substring(\"<![CDATA[\".length(), sql.length() - 3);\n            } else {\n                return null;\n            }\n        }\n        return StringEscapeUtils.unescapeXml(sql);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlCodeStat.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsert;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsReadStatement;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitorAdapter;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.fastjson2.JSON;\nimport com.alibaba.fastjson2.JSONWriter;\nimport com.alibaba.fastjson2.annotation.JSONField;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\n\npublic class SqlCodeStat extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName) {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName, boolean throwError) {\n        DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n\n        try {\n            List<SQLStatement> stmtList = SQLUtils.parseStatements(\n                    sql,\n                    DbType.odps,\n                    SQLParserFeature.EnableMultiUnion,\n                    SQLParserFeature.EnableSQLBinaryOpExprGroup\n            );\n\n            CodeStatVisitor v = new CodeStatVisitor();\n            for (SQLStatement stmt : stmtList) {\n                stmt.accept(v);\n            }\n\n            return v.toString();\n        } catch (Exception ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            return null;\n        }\n    }\n\n    public static class SqlStat {\n        @JSONField(ordinal = 0)\n        public int statementCount;\n\n        @JSONField(ordinal = 1)\n        public int cte;\n\n        @JSONField(ordinal = 2)\n        public int union;\n\n        @JSONField(ordinal = 3)\n        public int select;\n\n        @JSONField(ordinal = 4)\n        public int groupBy;\n\n        @JSONField(ordinal = 5)\n        public int orderBy;\n\n        @JSONField(ordinal = 6)\n        public int from;\n\n        @JSONField(ordinal = 7)\n        public int join;\n\n        @JSONField(ordinal = 8)\n        public int over;\n\n        @JSONField(ordinal = 9)\n        public int subQuery;\n\n        @JSONField(ordinal = 10)\n        public int lateralView;\n\n        @JSONField(ordinal = 40)\n        public int insert;\n\n        @JSONField(ordinal = 41)\n        public int insertInto;\n\n        @JSONField(ordinal = 42)\n        public int insertOverwrite;\n\n        @JSONField(ordinal = 43)\n        public int insertSelect;\n\n        @JSONField(ordinal = 44)\n        public int insertMulti;\n\n        @JSONField(ordinal = 51)\n        public int update;\n\n        @JSONField(ordinal = 52)\n        public int delete;\n\n        @JSONField(ordinal = 60)\n        public int create;\n\n        @JSONField(ordinal = 61)\n        public int createTable;\n\n        @JSONField(ordinal = 62)\n        public int createView;\n\n        @JSONField(ordinal = 70)\n        public int drop;\n\n        @JSONField(ordinal = 71)\n        public int dropTable;\n\n        @JSONField(ordinal = 72)\n        public int dropView;\n\n        @JSONField(ordinal = 80)\n        public int set;\n\n        @JSONField(ordinal = 90)\n        public int alter;\n\n        @JSONField(ordinal = 100)\n        public int read;\n\n        @JSONField(ordinal = 200)\n        public int condition;\n\n        @JSONField(ordinal = 201)\n        public int joinCondition;\n\n        @JSONField(ordinal = 202)\n        public int valueCondition;\n\n        @JSONField(ordinal = 203)\n        public int otherCondition;\n\n        @JSONField(ordinal = 204)\n        public int limit;\n\n        @JSONField(ordinal = 300)\n        public int aggregate;\n\n        @JSONField(ordinal = 201)\n        public int functionCall;\n\n        @JSONField(ordinal = 202)\n        public int having;\n    }\n\n    static class CodeStatVisitor extends OdpsASTVisitorAdapter {\n        SqlStat stat = new SqlStat();\n\n        public void preVisit(SQLObject x) {\n            if (x instanceof SQLStatement) {\n                stat.statementCount++;\n\n                if (x instanceof SQLInsertStatement) {\n                    stat.insert++;\n\n                    SQLInsertStatement insert = (SQLInsertStatement) x;\n\n                    if (insert.getQuery() != null) {\n                        stat.insertSelect++;\n                    }\n\n                    if (insert.isOverwrite()) {\n                        stat.insertOverwrite++;\n                    } else {\n                        stat.insertInto++;\n                    }\n                } else if (x instanceof HiveMultiInsertStatement) {\n                    stat.insert++;\n                    stat.insertMulti++;\n                    stat.insertSelect++;\n                    for (HiveInsert item : ((HiveMultiInsertStatement) x).getItems()) {\n                        if (item.isOverwrite()) {\n                            stat.insertOverwrite++;\n                        } else {\n                            stat.insertInto++;\n                        }\n                    }\n                } else if (x instanceof SQLDropStatement) {\n                    stat.drop++;\n                    if (x instanceof SQLDropTableStatement) {\n                        stat.dropTable++;\n                    } else if (x instanceof SQLDropViewStatement) {\n                        stat.dropView++;\n                    }\n                } else if (x instanceof SQLCreateStatement) {\n                    stat.create++;\n                    if (x instanceof SQLCreateTableStatement) {\n                        stat.createTable++;\n                    } else if (x instanceof SQLCreateViewStatement) {\n                        stat.createView++;\n                    }\n                } else if (x instanceof SQLDeleteStatement) {\n                    stat.delete++;\n                } else if (x instanceof SQLUpdateStatement) {\n                    stat.update++;\n                } else if (x instanceof SQLSetStatement) {\n                    stat.set++;\n                } else if (x instanceof SQLAlterStatement) {\n                    stat.alter++;\n                } else if (x instanceof OdpsReadStatement) {\n                    stat.read++;\n                }\n            }\n        }\n\n        public boolean visit(SQLUnionQuery x) {\n            stat.union++;\n            return true;\n        }\n\n        public boolean visit(SQLLateralViewTableSource x) {\n            stat.lateralView++;\n            return true;\n        }\n\n        public boolean visit(OdpsSelectQueryBlock x) {\n            return visit((SQLSelectQueryBlock) x);\n        }\n\n        public boolean visit(SQLSelectQueryBlock x) {\n            stat.select++;\n            return true;\n        }\n\n        public boolean visit(SQLSelectGroupByClause x) {\n            stat.groupBy++;\n            if (x.getHaving() != null) {\n                stat.having++;\n            }\n            return true;\n        }\n\n        public boolean visit(SQLLimit x) {\n            stat.limit++;\n            return false;\n        }\n\n        public boolean visit(SQLWithSubqueryClause.Entry x) {\n            stat.cte++;\n            return true;\n        }\n\n        public boolean visit(SQLOrderBy x) {\n            stat.orderBy++;\n            return true;\n        }\n\n        public boolean visit(SQLExprTableSource x) {\n            stat.from++;\n            return true;\n        }\n\n        public boolean visit(SQLSubqueryTableSource x) {\n            stat.from++;\n            stat.subQuery++;\n            return true;\n        }\n\n        public boolean visit(SQLJoinTableSource x) {\n            if (!(x.getParent() instanceof SQLJoinTableSource)) {\n                stat.from++;\n            }\n            stat.join++;\n            return true;\n        }\n\n        public boolean visit(SQLMethodInvokeExpr x) {\n            stat.functionCall++;\n            return true;\n        }\n\n        public boolean visit(SQLAggregateExpr x) {\n            stat.aggregate++;\n            return true;\n        }\n\n        public boolean visit(SQLOver x) {\n            stat.over++;\n            return true;\n        }\n\n        public boolean visit(SQLCastExpr x) {\n            stat.functionCall++;\n            return true;\n        }\n\n        public boolean visit(SQLInListExpr x) {\n            stat.condition++;\n            return true;\n        }\n\n        public boolean visit(SQLBinaryOpExpr x) {\n            if (x.getOperator() != null && x.getOperator().isRelational()) {\n                stat.condition++;\n\n                SQLExpr left = x.getLeft();\n                SQLExpr right = x.getRight();\n\n                if (left instanceof SQLName && right instanceof SQLName) {\n                    stat.joinCondition++;\n                } else if ((left instanceof SQLName || right instanceof SQLName)\n                        && (left instanceof SQLLiteralExpr || right instanceof SQLLiteralExpr)\n                ) {\n                    stat.valueCondition++;\n                } else {\n                    stat.otherCondition++;\n                }\n            }\n            return true;\n        }\n\n        public boolean visit(SQLCaseExpr x) {\n            SQLExpr value = x.getValueExpr();\n            if (value != null) {\n                stat.condition += x.getItems().size();\n            }\n\n            if (x.getElseExpr() != null) {\n                stat.condition++;\n            }\n\n            return true;\n        }\n\n        public boolean visit(SQLExistsExpr x) {\n            stat.condition++;\n            return true;\n        }\n\n        public String toString() {\n            return JSON.toJSONString(\n                    stat,\n                    JSONWriter.Feature.PrettyFormat,\n                    JSONWriter.Feature.NotWriteDefaultValue\n            );\n        }\n\n        public java.util.Map toMap() {\n            return (java.util.Map) JSON.toJSON(stat);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlFormat.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\n\npublic class SqlFormat extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName) {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName, boolean throwError) {\n        DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n            List<SQLStatement> statementList = parser.parseStatementList();\n            return SQLUtils.toSQLString(statementList, dbType);\n        } catch (Exception ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            return sql;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlParams.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SqlParams extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName) {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName, boolean throwError) {\n        try {\n            DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n            List<Object> outParameters = new ArrayList<Object>();\n            ParameterizedOutputVisitorUtils.parameterize(sql, dbType, outParameters);\n            return JSONUtils.toJSONString(outParameters);\n        } catch (ParserException ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlParamsFill.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\n\npublic class SqlParamsFill extends UDF {\n    public String evaluate(String sql, String params) {\n        return evaluate(sql, params, null, false);\n    }\n\n    public String evaluate(String sql, String params, String dbTypeName) {\n        return evaluate(sql, params, dbTypeName, false);\n    }\n\n    public String evaluate(String sql, String params, String dbTypeName, boolean throwError) {\n        try {\n            DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n            List<Object> inputParams = (List<Object>) JSONUtils.parse(params);\n            return ParameterizedOutputVisitorUtils.restore(sql, dbType, inputParams);\n        } catch (ParserException ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlPattern.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.aliyun.odps.udf.UDF;\n\npublic class SqlPattern extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName) {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName, boolean throwError) {\n        try {\n            DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n            return ParameterizedOutputVisitorUtils.parameterize(sql, dbType);\n        } catch (ParserException ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlPatternHash.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.aliyun.odps.udf.UDF;\n\npublic class SqlPatternHash extends UDF {\n    public Long evaluate(String sql) {\n        return evaluate(sql, null, false);\n    }\n\n    public Long evaluate(String sql, String dbTypeName) {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    public Long evaluate(String sql, String dbTypeName, boolean throwError) {\n        try {\n            DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n            return ParameterizedOutputVisitorUtils.parameterizeHash(sql, dbType, null);\n        } catch (ParserException ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlSyntaxCheck.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\n\npublic class SqlSyntaxCheck extends UDF {\n    public Boolean evaluate(String sql) {\n        return evaluate(sql, null, false);\n    }\n\n    public Boolean evaluate(String sql, String dbTypeName) {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    public Boolean evaluate(String sql, String dbTypeName, boolean throwError) {\n        if (sql == null || sql.length() == 0) {\n            return null;\n        }\n\n        DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n            List<SQLStatement> statementList = parser.parseStatementList();\n            return true;\n        } catch (ParserException ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/opds/udf/SqlTypeUDF.java",
    "content": "package com.alibaba.druid.support.opds.udf;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsDeclareVariableStatement;\nimport com.alibaba.druid.sql.dialect.odps.ast.OdpsQueryAliasStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.aliyun.odps.udf.UDF;\n\nimport java.util.List;\nimport java.util.Set;\nimport java.util.TreeSet;\n\npublic class SqlTypeUDF extends UDF {\n    public String evaluate(String sql) {\n        return evaluate(sql, null, false);\n    }\n\n    public String evaluate(String sql, String dbTypeName) {\n        return evaluate(sql, dbTypeName, false);\n    }\n\n    static SQLType getSqlType(SQLAlterTableStatement stmt) {\n        List<SQLAlterTableItem> items = stmt.getItems();\n        SQLAlterTableItem item = null;\n        if (items.size() == 1) {\n            item = items.get(0);\n        } else if (items.size() > 1) {\n            item = items.get(0);\n\n            for (int i = 1; i < items.size(); i++) {\n                SQLAlterTableItem t = items.get(i);\n                if (t != null && t.getClass() != item.getClass()) {\n                    item = null;\n                    break;\n                }\n            }\n        }\n\n        SQLType sqlType = SQLType.ALTER_TABLE;\n        if (item instanceof SQLAlterTableAddPartition) {\n            sqlType = SQLType.ALTER_TABLE_ADD_PARTITION;\n        } else if (item instanceof SQLAlterTableDropPartition) {\n            sqlType = SQLType.ALTER_TABLE_DROP_PARTITION;\n        } else if (item instanceof SQLAlterTableMergePartition) {\n            sqlType = SQLType.ALTER_TABLE_MERGE_PARTITION;\n        } else if (item instanceof SQLAlterTableRenamePartition) {\n            sqlType = SQLType.ALTER_TABLE_RENAME_PARTITION;\n        } else if (item instanceof SQLAlterTableSetLifecycle) {\n            sqlType = SQLType.ALTER_TABLE_SET_LIFECYCLE;\n        } else if (item instanceof SQLAlterTableEnableLifecycle) {\n            sqlType = SQLType.ALTER_TABLE_ENABLE_LIFECYCLE;\n        } else if (item instanceof SQLAlterTableDisableLifecycle) {\n            sqlType = SQLType.ALTER_TABLE_DISABLE_LIFECYCLE;\n        } else if (item instanceof SQLAlterTableRename) {\n            sqlType = SQLType.ALTER_TABLE_RENAME;\n        } else if (item instanceof SQLAlterTableAddColumn) {\n            sqlType = SQLType.ALTER_TABLE_ADD_COLUMN;\n        } else if (item instanceof SQLAlterTableAlterColumn) {\n            sqlType = SQLType.ALTER_TABLE_ALTER_COLUMN;\n        } else if (item instanceof SQLAlterTableSetOption) {\n            sqlType = SQLType.ALTER_TABLE_SET_TBLPROPERTIES;\n        } else if (item instanceof SQLAlterTableSetComment) {\n            sqlType = SQLType.ALTER_TABLE_SET_COMMENT;\n        } else if (item instanceof SQLAlterTableRenameColumn) {\n            sqlType = SQLType.ALTER_TABLE_RENAME_COLUMN;\n        } else if (item instanceof SQLAlterTableTouch) {\n            sqlType = SQLType.ALTER_TABLE_TOUCH;\n        } else if (item instanceof SQLAlterTableChangeOwner) {\n            sqlType = SQLType.ALTER_TABLE_CHANGE_OWNER;\n        }\n        return sqlType;\n    }\n\n    static SQLType getStmtSqlType(SQLStatement stmt, SQLType sqlType) {\n        if (stmt instanceof SQLCreateTableStatement) {\n            if (((SQLCreateTableStatement) stmt).getSelect() != null) {\n                sqlType = SQLType.CREATE_TABLE_AS_SELECT;\n            } else {\n                sqlType = SQLType.CREATE_TABLE;\n            }\n        } else if (stmt instanceof HiveInsertStatement) {\n            HiveInsertStatement hiveInsert = (HiveInsertStatement) stmt;\n            sqlType = hiveInsert.isOverwrite()\n                    ? SQLType.INSERT_OVERWRITE\n                    : SQLType.INSERT_INTO;\n            if (hiveInsert.getQuery() != null) {\n                sqlType = hiveInsert.isOverwrite()\n                        ? SQLType.INSERT_OVERWRITE_SELECT\n                        : SQLType.INSERT_INTO_SELECT;\n            } else if (hiveInsert.getValuesList().size() > 0) {\n                sqlType = hiveInsert.isOverwrite()\n                        ? SQLType.INSERT_OVERWRITE_VALUES\n                        : SQLType.INSERT_INTO_VALUES;\n            }\n        } else if (stmt instanceof SQLUpdateStatement) {\n            sqlType = SQLType.UPDATE;\n        } else if (stmt instanceof SQLDeleteStatement) {\n            sqlType = SQLType.DELETE;\n        } else if (stmt instanceof SQLSelectStatement) {\n            sqlType = SQLType.SELECT;\n        } else if (stmt instanceof HiveMultiInsertStatement) {\n            sqlType = SQLType.INSERT_MULTI;\n        } else if (stmt instanceof SQLDropTableStatement) {\n            sqlType = SQLType.DROP_TABLE;\n        } else if (stmt instanceof SQLDropViewStatement) {\n            sqlType = SQLType.DROP_VIEW;\n        } else if (stmt instanceof SQLPurgeTableStatement) {\n            sqlType = SQLType.PURGE;\n        } else if (stmt instanceof SQLShowStatement) {\n            if (stmt instanceof SQLShowCatalogsStatement) {\n                sqlType = SQLType.SHOW_CATALOGS;\n            } else if (stmt instanceof SQLShowCreateTableStatement) {\n                sqlType = SQLType.SHOW_CREATE_TABLE;\n            } else if (stmt instanceof SQLShowGrantsStatement) {\n                sqlType = SQLType.SHOW_GRANTS;\n            } else if (stmt instanceof SQLShowRecylebinStatement) {\n                sqlType = SQLType.SHOW_RECYCLEBIN;\n            } else if (stmt instanceof SQLShowStatisticStmt) {\n                sqlType = SQLType.SHOW_STATISTIC;\n            } else if (stmt instanceof SQLShowStatisticListStmt) {\n                sqlType = SQLType.SHOW_STATISTIC_LIST;\n            } else if (stmt instanceof SQLShowTablesStatement) {\n                sqlType = SQLType.SHOW_TABLES;\n            } else if (stmt instanceof SQLShowUsersStatement) {\n                sqlType = SQLType.SHOW_USERS;\n            } else if (stmt instanceof SQLShowPartitionsStmt) {\n                sqlType = SQLType.SHOW_PARTITIONS;\n            } else if (sqlType == null) {\n                sqlType = SQLType.SHOW;\n            }\n        } else if (stmt instanceof OdpsQueryAliasStatement\n                || stmt instanceof OdpsDeclareVariableStatement\n        ) {\n            sqlType = SQLType.SCRIPT;\n        } else if (stmt instanceof SQLAlterTableStatement) {\n            sqlType = getSqlType((SQLAlterTableStatement) stmt);\n        }\n\n        return sqlType;\n    }\n\n    public String evaluate(String sql, String dbTypeName, boolean throwError) {\n        if (sql == null || sql.isEmpty()) {\n            return null;\n        }\n\n        DbType dbType = dbTypeName == null ? null : DbType.valueOf(dbTypeName);\n\n        SQLType sqlType = null;\n        try {\n            List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n            if (stmtList.isEmpty()) {\n                return SQLType.EMPTY.name();\n            }\n\n            int setCnt = 0, notSetCnt = 0;\n            SQLStatement notSetStmt = null;\n            for (SQLStatement stmt : stmtList) {\n                if (stmt instanceof SQLSetStatement) {\n                    setCnt++;\n                } else {\n                    notSetStmt = stmt;\n                    notSetCnt++;\n                }\n            }\n\n            if (setCnt == stmtList.size()) {\n                Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n                sqlType = lexer.scanSQLTypeV2();\n                if (sqlType != null) {\n                    return sqlType.name();\n                }\n                return SQLType.SET.name();\n            }\n\n            if (notSetCnt == 1) {\n                Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n                sqlType = lexer.scanSQLTypeV2();\n                sqlType = SqlTypeUDF.getStmtSqlType(notSetStmt, sqlType);\n            } else {\n                for (SQLStatement stmt : stmtList) {\n                    if (stmt instanceof OdpsQueryAliasStatement\n                            || stmt instanceof OdpsDeclareVariableStatement) {\n                        return SQLType.SCRIPT.name();\n                    }\n                }\n\n                Set<String> typeNameSet = new TreeSet<>();\n                for (SQLStatement stmt : stmtList) {\n                    if (stmt instanceof SQLSetStatement) {\n                        continue;\n                    }\n\n                    SQLType type = SqlTypeUDF.getStmtSqlType(stmt, null);\n                    if (type != null) {\n                        typeNameSet.add(type.name());\n                    }\n                }\n\n                if (typeNameSet.size() == 1) {\n                    return typeNameSet.stream().findFirst().get();\n                }\n\n                if (typeNameSet.size() > 0) {\n                    StringBuilder buf = new StringBuilder();\n                    for (String s : typeNameSet) {\n                        if (buf.length() != 0) {\n                            buf.append(',');\n                        }\n                        buf.append(s);\n                    }\n                    return \"MULTI:\" + buf.toString();\n                }\n                sqlType = SQLType.MULTI;\n            }\n        } catch (ParserException ex) {\n            sql = sql.trim();\n            int semiIndex = sql.indexOf(';');\n            if (semiIndex == sql.length() - 1 || semiIndex == -1 && sql.indexOf('\\n') == -1) {\n                String singleLineSqlType = getSqlTypeForSingleLineSql(sql, dbType);\n                if (singleLineSqlType != null) {\n                    return singleLineSqlType;\n                }\n            } else {\n                if (sql.lastIndexOf('\\n', semiIndex) == -1) {\n                    String firstSql = sql.substring(0, semiIndex).trim().toLowerCase();\n                    if (firstSql.startsWith(\"set \")) {\n                        String restSql = sql.substring(semiIndex + 1);\n                        return evaluate(restSql, dbTypeName, throwError);\n                    }\n                }\n            }\n\n            try {\n                Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n\n                int semiCnt = 0;\n                for_:\n                for (Token token = null; ; ) {\n                    lexer.nextToken();\n\n                    if (token == Token.VARIANT && lexer.token() == Token.COLONEQ) {\n                        return SQLType.SCRIPT.name();\n                    }\n\n                    token = lexer.token();\n                    switch (token) {\n                        case EOF:\n                        case ERROR:\n                            break for_;\n                        case SEMI:\n                            semiCnt++;\n                            break;\n                        default:\n                            break;\n                    }\n                }\n            } catch (ParserException ignored) {\n            }\n\n            sqlType = SQLType.ERROR;\n\n        } catch (Throwable ex) {\n            if (throwError) {\n                throw new IllegalArgumentException(\"error sql : \\n\" + sql, ex);\n            }\n\n            sqlType = SQLType.ERROR;\n        }\n\n        if (sqlType != null) {\n            return sqlType.name();\n        }\n\n        return SQLType.UNKNOWN.name();\n    }\n\n    private String getSqlTypeForSingleLineSql(String sql, DbType dbType) {\n        try {\n            SQLType sqlType;\n            Lexer lexer = SQLParserUtils.createLexer(sql, dbType);\n            sqlType = lexer.scanSQLTypeV2();\n            if (sqlType == null) {\n                return null;\n            }\n\n            if (sqlType == SQLType.WITH) {\n                lexer = SQLParserUtils.createLexer(sql, dbType);\n\n                int updateCnt = 0, insertCnt = 0, deleteCnt = 0;\n                for_:\n                for (Token token = null; ; ) {\n                    Token last = token;\n                    lexer.nextToken();\n                    token = lexer.token();\n\n                    if (last == Token.INSERT) {\n                        if (token == Token.OVERWRITE) {\n                            return SQLType.INSERT_OVERWRITE_SELECT.name();\n                        } else if (token == Token.INTO) {\n                            return SQLType.INSERT_INTO_SELECT.name();\n                        }\n                    }\n                    switch (token) {\n                        case EOF:\n                        case ERROR:\n                            break for_;\n                        case INSERT:\n                            insertCnt++;\n                            break;\n                        case DELETE:\n                            deleteCnt++;\n                            break;\n                        case UPDATE:\n                            updateCnt++;\n                            break;\n                        default:\n                            break;\n                    }\n                }\n                if (updateCnt == 0 && insertCnt == 0 && deleteCnt == 0) {\n                    return SQLType.SELECT.name();\n                }\n            }\n            return sqlType.name();\n        } catch (ParserException ignored) {\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/profile/ProfileEntry.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.profile;\n\npublic class ProfileEntry {\n    private final ProfileEntry parent;\n    private final ProfileEntryKey key;\n\n    private int executeCount;\n    private long executeTimeNanos;\n\n    public ProfileEntry(ProfileEntry parent, ProfileEntryKey key) {\n        this.parent = parent;\n        this.key = key;\n    }\n\n    public ProfileEntry getParent() {\n        return parent;\n    }\n\n    public ProfileEntryKey getKey() {\n        return key;\n    }\n\n    public String getParentName() {\n        return key.getParentName();\n    }\n\n    public String getName() {\n        return key.getName();\n    }\n\n    public String getType() {\n        return key.getType();\n    }\n\n    public int getExecuteCount() {\n        return executeCount;\n    }\n\n    public void incrementExecuteCount() {\n        this.executeCount++;\n    }\n\n    public long getExecuteTimeNanos() {\n        return executeTimeNanos;\n    }\n\n    public void addExecuteTimeNanos(long nanos) {\n        this.executeTimeNanos += nanos;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/profile/ProfileEntryKey.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.profile;\n\npublic class ProfileEntryKey {\n    private final String parentName;\n    private final String name;\n    private final String type;\n\n    public ProfileEntryKey(String parentName, String name, String type) {\n        this.parentName = parentName;\n        this.name = name;\n        this.type = type;\n    }\n\n    public String getParentName() {\n        return parentName;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void fillValue(ProfileEntryStatValue value) {\n        value.setParentName(parentName);\n        value.setName(name);\n        value.setType(type);\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((name == null) ? 0 : name.hashCode());\n        result = prime * result + ((parentName == null) ? 0 : parentName.hashCode());\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        ProfileEntryKey other = (ProfileEntryKey) obj;\n        if (name == null) {\n            if (other.name != null) {\n                return false;\n            }\n        } else if (!name.equals(other.name)) {\n            return false;\n        }\n        if (parentName == null) {\n            if (other.parentName != null) {\n                return false;\n            }\n        } else if (!parentName.equals(other.parentName)) {\n            return false;\n        }\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/profile/ProfileEntryReqStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.profile;\n\npublic class ProfileEntryReqStat {\n    private long executeCount;\n    private long executeTimeNanos;\n\n    public long getExecuteCount() {\n        return executeCount;\n    }\n\n    public void incrementExecuteCount() {\n        this.executeCount++;\n    }\n\n    public long getExecuteTimeNanos() {\n        return executeTimeNanos;\n    }\n\n    public void addExecuteTimeNanos(long nanos) {\n        this.executeTimeNanos += nanos;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/profile/ProfileEntryStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.profile;\n\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class ProfileEntryStat {\n    private volatile long executeCount;\n    private volatile long executeTimeNanos;\n    private static final AtomicLongFieldUpdater<ProfileEntryStat> executeCountUpdater;\n    private static final AtomicLongFieldUpdater<ProfileEntryStat> executeTimeNanosUpdater;\n\n    static {\n        executeCountUpdater = AtomicLongFieldUpdater.newUpdater(ProfileEntryStat.class, \"executeCount\");\n        executeTimeNanosUpdater = AtomicLongFieldUpdater.newUpdater(ProfileEntryStat.class, \"executeTimeNanos\");\n    }\n\n    public ProfileEntryStatValue getValue(boolean reset) {\n        ProfileEntryStatValue val = new ProfileEntryStatValue();\n\n        val.setExecuteCount(get(this, executeCountUpdater, reset));\n        val.setExecuteTimeNanos(get(this, executeTimeNanosUpdater, reset));\n\n        return val;\n    }\n\n    public long getExecuteCount() {\n        return executeCount;\n    }\n\n    public void addExecuteCount(long delta) {\n        executeCountUpdater.addAndGet(this, delta);\n    }\n\n    public long getExecuteTimeNanos() {\n        return executeTimeNanos;\n    }\n\n    public void addExecuteTimeNanos(long delta) {\n        executeTimeNanosUpdater.addAndGet(this, delta);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/profile/ProfileEntryStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.profile;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class ProfileEntryStatValue {\n    private String parentName;\n    private String name;\n    private String type;\n    private long executeCount;\n    private long executeTimeNanos;\n\n    public String getParentName() {\n        return parentName;\n    }\n\n    public void setParentName(String parentName) {\n        this.parentName = parentName;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public long getExecuteCount() {\n        return executeCount;\n    }\n\n    public void setExecuteCount(long executeCount) {\n        this.executeCount = executeCount;\n    }\n\n    public long getExecuteTimeNanos() {\n        return executeTimeNanos;\n    }\n\n    public void setExecuteTimeNanos(long executeTimeNanos) {\n        this.executeTimeNanos = executeTimeNanos;\n    }\n\n    public Map<String, Object> getData() {\n        Map<String, Object> entryData = new LinkedHashMap<String, Object>();\n\n        entryData.put(\"Name\", this.getName());\n        entryData.put(\"Parent\", this.getParentName());\n        entryData.put(\"Type\", this.getType());\n        entryData.put(\"ExecuteCount\", this.getExecuteCount());\n        entryData.put(\"ExecuteTimeMillis\", this.getExecuteTimeNanos() / 1000 / 1000);\n\n        return entryData;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/profile/ProfileStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.profile;\n\nimport java.util.*;\nimport java.util.concurrent.locks.ReadWriteLock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\n\npublic class ProfileStat {\n    private Map<ProfileEntryKey, ProfileEntryStat> entries = new LinkedHashMap<ProfileEntryKey, ProfileEntryStat>(4);\n\n    private ReadWriteLock lock = new ReentrantReadWriteLock();\n\n    public Map<ProfileEntryKey, ProfileEntryStat> getEntries() {\n        return entries;\n    }\n\n    public void record(Map<ProfileEntryKey, ProfileEntryReqStat> requestStatsMap) {\n        if (requestStatsMap == null) {\n            return;\n        }\n\n        for (Map.Entry<ProfileEntryKey, ProfileEntryReqStat> entry : requestStatsMap.entrySet()) {\n            ProfileEntryKey entryKey = entry.getKey();\n            ProfileEntryReqStat reqEntryStat = entry.getValue();\n\n            ProfileEntryStat entryStat = getProfileEntry(entryKey);\n\n            entryStat.addExecuteCount(reqEntryStat.getExecuteCount());\n            entryStat.addExecuteTimeNanos(reqEntryStat.getExecuteTimeNanos());\n        }\n    }\n\n    private ProfileEntryStat getProfileEntry(ProfileEntryKey entryKey) {\n        lock.readLock().lock();\n        try {\n            ProfileEntryStat entryStat = entries.get(entryKey);\n            if (entryStat != null) {\n                return entryStat;\n            }\n        } finally {\n            lock.readLock().unlock();\n        }\n\n        lock.writeLock().lock();\n        try {\n            ProfileEntryStat entryStat = entries.get(entryKey);\n            if (entryStat == null) {\n                entries.put(entryKey, new ProfileEntryStat());\n                entryStat = entries.get(entryKey);\n            }\n            return entryStat;\n        } finally {\n            lock.writeLock().unlock();\n        }\n    }\n\n    public List<Map<String, Object>> getStatData() {\n        List<ProfileEntryStatValue> statValueList = getStatValue(false);\n\n        int size = statValueList.size();\n        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(size);\n        for (ProfileEntryStatValue profileEntryStatValue : statValueList) {\n            list.add(profileEntryStatValue.getData());\n        }\n\n        return list;\n    }\n\n    public List<ProfileEntryStatValue> getStatValue(boolean reset) {\n        List<ProfileEntryStatValue> list = new ArrayList<ProfileEntryStatValue>();\n\n        lock.readLock().lock();\n        try {\n            for (Map.Entry<ProfileEntryKey, ProfileEntryStat> entry : entries.entrySet()) {\n                ProfileEntryStatValue entryStatValue = entry.getValue().getValue(reset);\n                entry.getKey().fillValue(entryStatValue);\n\n                list.add(entryStatValue);\n            }\n        } finally {\n            lock.readLock().unlock();\n        }\n\n        Collections.reverse(list);\n\n        return list;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/profile/Profiler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.profile;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class Profiler {\n    public static final String PROFILE_TYPE_WEB = \"WEB\";\n    public static final String PROFILE_TYPE_SPRING = \"SPRING\";\n    public static final String PROFILE_TYPE_SQL = \"SQL\";\n\n    private static ThreadLocal<Map<ProfileEntryKey, ProfileEntryReqStat>> statsMapLocal = new ThreadLocal<Map<ProfileEntryKey, ProfileEntryReqStat>>();\n\n    private static final ThreadLocal<ProfileEntry> currentLocal = new ThreadLocal<ProfileEntry>();\n\n    public static boolean isEnable() {\n        return statsMapLocal != null;\n    }\n\n    public static void enter(String name, String type) {\n        if (!isEnable()) {\n            return;\n        }\n\n        ProfileEntry parent = currentLocal.get();\n        String parentName = null;\n        if (parent != null) {\n            parentName = parent.getName();\n        }\n\n        ProfileEntryKey key = new ProfileEntryKey(parentName, name, type);\n        ProfileEntry entry = new ProfileEntry(parent, key);\n\n        currentLocal.set(entry);\n    }\n\n    public static ProfileEntry current() {\n        return currentLocal.get();\n    }\n\n    public static void release(long nanos) {\n        ProfileEntry current = currentLocal.get();\n        if (current == null) {\n            return;\n        }\n\n        currentLocal.set(current.getParent());\n\n        ProfileEntryReqStat stat = null;\n        Map<ProfileEntryKey, ProfileEntryReqStat> statsMap = statsMapLocal.get();\n        if (statsMap == null) {\n            return;\n        }\n\n        stat = statsMap.get(current.getKey());\n\n        if (stat == null) {\n            stat = new ProfileEntryReqStat();\n            statsMap.put(current.getKey(), stat);\n        }\n\n        stat.incrementExecuteCount();\n        stat.addExecuteTimeNanos(nanos);\n    }\n\n    public static Map<ProfileEntryKey, ProfileEntryReqStat> getStatsMap() {\n        return statsMapLocal.get();\n    }\n\n    public static void initLocal() {\n        statsMapLocal.set(new LinkedHashMap<ProfileEntryKey, ProfileEntryReqStat>());\n    }\n\n    public static void removeLocal() {\n        statsMapLocal.remove();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/quartz/DruidQuartzConnectionProvider.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.quartz;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.quartz.utils.ConnectionProvider;\n\nimport java.sql.SQLException;\n\npublic class DruidQuartzConnectionProvider extends DruidDataSource implements ConnectionProvider {\n    private static final long serialVersionUID = 1L;\n\n    public void initialize() throws SQLException {\n        this.init();\n    }\n\n    public void shutdown() throws SQLException {\n        this.close();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/simplejndi/DruidDataSourceConverter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.druid.support.simplejndi;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport org.osjava.sj.loader.convert.Converter;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\n/**\n * 支持simple-jndi\n * <p>配置示例：</p>\n * <pre>\n * pgDruidTest/converter=com.alibaba.druid.support.simplejndi.DruidDataSourceConverter\n * pgDruidTest/type=javax.sql.DataSource\n * pgDruidTest/driverClassName=org.postgresql.Driver\n * pgDruidTest/url=jdbc:postgresql://127.0.0.1:5432/kettleRep\n * pgDruidTest/username=postgres\n * pgDruidTest/password=postgres\n * pgDruidTest/maxActive=50\n * pgDruidTest/minIdle=10\n * pgDruidTest/initialSize=5\n * pgDruidTest/validationQuery=SELECT 1\n * pgDruidTest/maxWait=10000\n * pgDruidTest/removeabandoned=true\n * pgDruidTest/removeabandonedtimeout=60\n * pgDruidTest/logabandoned=false\n * pgDruidTest/filters=stat,config,log4j\n * pgDruidTest/connectionProperties=druid.log.stmt.executableSql=true\n * </pre>\n * date: 2016年1月31日 下午12:54:10\n *\n * @author jinjuma@yeah.net\n */\npublic class DruidDataSourceConverter implements Converter {\n    private static final Log LOG = LogFactory.getLog(DruidDataSourceConverter.class);\n\n    /**\n     * @see org.osjava.sj.loader.convert.Converter#convert(java.util.Properties, java.lang.String)\n     */\n    @Override\n    public Object convert(Properties properties, String type) {\n        try {\n            DruidDataSource dataSource = new DruidDataSource();\n            DruidDataSourceFactory.config(dataSource, properties);\n            return dataSource;\n        } catch (SQLException e) {\n            LOG.error(\"properties:\" + properties, e);\n        }\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/DruidLobCreator.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring;\n\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.springframework.jdbc.support.lob.LobCreator;\n\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\npublic class DruidLobCreator implements LobCreator {\n    @Override\n    public void setBlobAsBytes(PreparedStatement ps, int paramIndex, byte[] content) throws SQLException {\n        Blob blob = ps.getConnection().createBlob();\n        blob.setBytes(1, content);\n        ps.setBlob(paramIndex, blob);\n    }\n\n    @Override\n    public void setBlobAsBinaryStream(PreparedStatement ps,\n                                      int paramIndex,\n                                      InputStream contentStream,\n                                      int contentLength)\n            throws SQLException {\n        ps.setBlob(paramIndex, contentStream, contentLength);\n    }\n\n    @Override\n    public void setClobAsString(PreparedStatement ps, int paramIndex, String content) throws SQLException {\n        Clob clob = ps.getConnection().createClob();\n        clob.setString(1, content);\n        ps.setClob(paramIndex, clob);\n    }\n\n    @Override\n    public void setClobAsAsciiStream(PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength)\n            throws SQLException {\n        if (asciiStream != null) {\n            Clob clob = ps.getConnection().createClob();\n\n            OutputStream out = clob.setAsciiStream(1);\n\n            final int BUFFER_SIZE = 4096;\n            try {\n                byte[] buffer = new byte[BUFFER_SIZE];\n                int bytesRead = -1;\n                while ((bytesRead = asciiStream.read(buffer)) != -1) {\n                    out.write(buffer, 0, bytesRead);\n                }\n                out.flush();\n            } catch (Exception e) {\n                throw new SQLException(\"setClob error\", e);\n            } finally {\n                JdbcUtils.close(asciiStream);\n                JdbcUtils.close(out);\n            }\n\n            ps.setClob(paramIndex, clob);\n        } else {\n            ps.setClob(paramIndex, (Clob) null);\n        }\n    }\n\n    @Override\n    public void setClobAsCharacterStream(PreparedStatement ps,\n                                         int paramIndex,\n                                         Reader characterStream,\n                                         int contentLength)\n            throws SQLException {\n        ps.setClob(paramIndex, characterStream, contentLength);\n    }\n\n    @Override\n    public void close() {\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/DruidLobHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring;\n\nimport org.springframework.jdbc.support.lob.AbstractLobHandler;\nimport org.springframework.jdbc.support.lob.LobCreator;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\npublic class DruidLobHandler extends AbstractLobHandler {\n    public byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException {\n        Blob blob = rs.getBlob(columnIndex);\n\n        if (blob == null) {\n            return null;\n        }\n\n        return blob.getBytes(1, (int) blob.length());\n    }\n\n    public InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException {\n        Blob blob = rs.getBlob(columnIndex);\n\n        if (blob == null) {\n            return null;\n        }\n\n        return blob.getBinaryStream();\n    }\n\n    public String getClobAsString(ResultSet rs, int columnIndex) throws SQLException {\n        Clob clob = rs.getClob(columnIndex);\n\n        if (clob == null) {\n            return null;\n        }\n\n        return clob.getSubString(1, (int) clob.length());\n    }\n\n    public InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException {\n        Clob clob = rs.getClob(columnIndex);\n\n        if (clob == null) {\n            return null;\n        }\n\n        return clob.getAsciiStream();\n    }\n\n    public Reader getClobAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException {\n        Clob clob = rs.getClob(columnIndex);\n\n        if (clob == null) {\n            return null;\n        }\n\n        return clob.getCharacterStream();\n    }\n\n    @Override\n    public LobCreator getLobCreator() {\n        return new DruidLobCreator();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/DruidNativeJdbcExtractor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring;\n\nimport org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractorAdapter;\n\nimport java.sql.*;\n\npublic class DruidNativeJdbcExtractor extends NativeJdbcExtractorAdapter {\n    protected Connection doGetNativeConnection(Connection con) throws SQLException {\n        return (Connection) con.unwrap(Connection.class);\n    }\n\n    public Statement getNativeStatement(Statement stmt) throws SQLException {\n        return (Statement) stmt.unwrap(Statement.class);\n    }\n\n    public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException {\n        return (PreparedStatement) ps.unwrap(PreparedStatement.class);\n    }\n\n    public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException {\n        return (CallableStatement) cs.unwrap(CallableStatement.class);\n    }\n\n    public ResultSet getNativeResultSet(ResultSet rs) throws SQLException {\n        return (ResultSet) rs.unwrap(ResultSet.class);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/MBeanServerFactoryBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring;\n\nimport org.springframework.beans.factory.FactoryBean;\n\nimport javax.management.MBeanServer;\n\nimport java.lang.management.ManagementFactory;\n\npublic class MBeanServerFactoryBean implements FactoryBean {\n    public Object getObject() throws Exception {\n        return ManagementFactory.getPlatformMBeanServer();\n    }\n\n    public Class<?> getObjectType() {\n        return MBeanServer.class;\n    }\n\n    public boolean isSingleton() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/mvc/StatHandlerInterceptor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.mvc;\n\nimport com.alibaba.druid.filter.stat.StatFilterContext;\nimport com.alibaba.druid.support.http.AbstractWebStatImpl;\nimport com.alibaba.druid.support.http.stat.*;\nimport com.alibaba.druid.support.profile.ProfileEntryKey;\nimport com.alibaba.druid.support.profile.ProfileEntryReqStat;\nimport com.alibaba.druid.support.profile.Profiler;\nimport com.alibaba.druid.util.DruidWebUtils;\nimport org.springframework.beans.factory.DisposableBean;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.web.servlet.HandlerInterceptor;\nimport org.springframework.web.servlet.HandlerMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.ServletContext;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport java.util.Map;\n\npublic class StatHandlerInterceptor extends AbstractWebStatImpl implements HandlerInterceptor, InitializingBean, DisposableBean {\n    public StatHandlerInterceptor() {\n    }\n\n    @Override\n    public boolean preHandle(HttpServletRequest request,\n                             HttpServletResponse response,\n                             Object handler) throws Exception {\n        final WebAppStat webAppStat = getWebAppStat(request);\n        String requestURI = getRequestURI(request);\n\n        long startNano = System.nanoTime();\n        long startMillis = System.currentTimeMillis();\n\n        WebRequestStat requestStat = new WebRequestStat(startNano, startMillis);\n        WebRequestStat.set(requestStat);\n\n        WebSessionStat sessionStat = getSessionStat(request);\n        webAppStat.beforeInvoke();\n\n        WebURIStat uriStat = webAppStat.getURIStat(requestURI, false);\n\n        if (uriStat == null) {\n            int index = requestURI.indexOf(\";jsessionid=\");\n            if (index != -1) {\n                requestURI = requestURI.substring(0, index);\n                uriStat = webAppStat.getURIStat(requestURI, false);\n            }\n        }\n\n        if (isProfileEnable()) {\n            Profiler.initLocal();\n            Profiler.enter(requestURI, Profiler.PROFILE_TYPE_WEB);\n        }\n\n        // 第一次访问时，uriStat这里为null，是为了防止404攻击。\n        if (uriStat != null) {\n            uriStat.beforeInvoke();\n        }\n\n        // 第一次访问时，sessionId为null，如果缺省sessionCreate=false，sessionStat就为null。\n        if (sessionStat != null) {\n            sessionStat.beforeInvoke();\n        }\n\n        return true;\n    }\n\n    public WebAppStat getWebAppStat(HttpServletRequest request) {\n        if (webAppStat != null) {\n            return webAppStat;\n        }\n\n        ServletContext context = request.getSession().getServletContext();\n        String contextPath = DruidWebUtils.getContextPath(context);\n        webAppStat = WebAppStatManager.getInstance().getWebAppStat(contextPath);\n        return webAppStat;\n    }\n\n    @Override\n    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,\n                           ModelAndView modelAndView) throws Exception {\n    }\n\n    @Override\n    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,\n                                Exception error) throws Exception {\n        WebRequestStat requestStat = WebRequestStat.current();\n        long endNano = System.nanoTime();\n        requestStat.setEndNano(endNano);\n\n        WebSessionStat sessionStat = getSessionStat(request);\n        WebURIStat uriStat = WebURIStat.current();\n\n        long nanos = endNano - requestStat.getStartNano();\n        webAppStat.afterInvoke(null, nanos);\n\n        if (sessionStat == null) {\n            sessionStat = getSessionStat(request);\n            if (sessionStat != null) {\n                sessionStat.beforeInvoke(); // 补偿\n            }\n        }\n\n        if (sessionStat != null) {\n            sessionStat.afterInvoke(error, nanos);\n            sessionStat.setPrincipal(getPrincipal(request));\n        }\n\n        if (uriStat != null) {\n            uriStat.afterInvoke(error, nanos);\n        }\n\n        WebRequestStat.set(null);\n\n        if (isProfileEnable()) {\n            Profiler.release(nanos);\n\n            Map<ProfileEntryKey, ProfileEntryReqStat> requestStatsMap = Profiler.getStatsMap();\n            if (uriStat != null) {\n                uriStat.getProfiletat().record(requestStatsMap);\n            }\n            Profiler.removeLocal();\n        }\n    }\n\n    public String getRequestURI(HttpServletRequest request) {\n        return (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);\n    }\n\n    @Override\n    public void afterPropertiesSet() throws Exception {\n        StatFilterContext.getInstance().addContextListener(statFilterContextListener);\n    }\n\n    @Override\n    public void destroy() throws Exception {\n        StatFilterContext.getInstance().removeContextListener(statFilterContextListener);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/BeanTypeAutoProxyCreator.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport org.springframework.aop.TargetSource;\nimport org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;\nimport org.springframework.beans.factory.BeanFactory;\nimport org.springframework.beans.factory.FactoryBean;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.util.Assert;\nimport org.springframework.util.PatternMatchUtils;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * 类BeanTypeAutoProxyCreator.java的实现描述：使用配置类型代替Springframework中配置名称的实现\n *\n * @author hualiang.lihl 2011-12-31 上午10:48:20\n */\npublic class BeanTypeAutoProxyCreator extends AbstractAutoProxyCreator implements InitializingBean, ApplicationContextAware {\n    private static final long serialVersionUID = -9094985530794052264L;\n\n    private Class<?> targetBeanType;\n\n    private ApplicationContext context;\n\n    private List<String> beanNames = new ArrayList<String>();\n\n    /**\n     * @param targetClass the targetClass to set\n     */\n    public void setTargetBeanType(Class<?> targetClass) {\n        this.targetBeanType = targetClass;\n    }\n\n    public void setApplicationContext(ApplicationContext context) {\n        this.context = context;\n    }\n\n    /**\n     * Identify as bean to proxy if the bean name is in the configured list of names.\n     */\n    @SuppressWarnings(\"rawtypes\")\n    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {\n        for (String mappedName : this.beanNames) {\n            if (FactoryBean.class.isAssignableFrom(beanClass)) {\n                if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {\n                    continue;\n                }\n                mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());\n            }\n            if (isMatch(beanName, mappedName)) {\n                return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;\n            }\n        }\n        return DO_NOT_PROXY;\n    }\n\n    /**\n     * Return if the given bean name matches the mapped name.\n     * <p>\n     * The default implementation checks for \"xxx*\", \"*xxx\" and \"*xxx*\" matches, as well as direct equality. Can be\n     * overridden in subclasses.\n     *\n     * @param beanName   the bean name to check\n     * @param mappedName the name in the configured list of names\n     * @return if the names match\n     * @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)\n     */\n    protected boolean isMatch(String beanName, String mappedName) {\n        return PatternMatchUtils.simpleMatch(mappedName, beanName);\n    }\n\n    public void afterPropertiesSet() throws Exception {\n        Assert.notNull(targetBeanType, \"targetType cannot be null\");\n        String[] beanNames = context.getBeanNamesForType(targetBeanType);\n        Collections.addAll(this.beanNames, beanNames);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/DruidStatInterceptor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport com.alibaba.druid.filter.stat.StatFilterContext;\nimport com.alibaba.druid.filter.stat.StatFilterContextListenerAdapter;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport org.aopalliance.intercept.MethodInterceptor;\nimport org.aopalliance.intercept.MethodInvocation;\nimport org.springframework.aop.TargetSource;\nimport org.springframework.beans.factory.DisposableBean;\nimport org.springframework.beans.factory.InitializingBean;\n\nimport java.lang.reflect.Method;\n\npublic class DruidStatInterceptor implements MethodInterceptor, InitializingBean, DisposableBean {\n    public static final String PROP_NAME_PROFILE = \"druid.profile\";\n\n    private static final Log LOG = LogFactory.getLog(DruidStatInterceptor.class);\n\n    private static SpringStat springStat = new SpringStat();\n\n    private SpringMethodContextListener statContextListener = new SpringMethodContextListener();\n\n    public DruidStatInterceptor() {\n    }\n\n    @Override\n    public void afterPropertiesSet() throws Exception {\n        SpringStatManager.getInstance().addSpringStat(springStat);\n\n        StatFilterContext.getInstance().addContextListener(statContextListener);\n    }\n\n    @Override\n    public void destroy() throws Exception {\n        StatFilterContext.getInstance().removeContextListener(statContextListener);\n    }\n\n    @Override\n    public Object invoke(MethodInvocation invocation) throws Throwable {\n        SpringMethodStat lastMethodStat = SpringMethodStat.current();\n\n        SpringMethodInfo methodInfo = getMethodInfo(invocation);\n\n        SpringMethodStat methodStat = springStat.getMethodStat(methodInfo, true);\n\n        if (methodStat != null) {\n            methodStat.beforeInvoke();\n        }\n\n        long startNanos = System.nanoTime();\n\n        Throwable error = null;\n        try {\n            return invocation.proceed();\n        } catch (Throwable e) {\n            error = e;\n            throw e;\n        } finally {\n            long endNanos = System.nanoTime();\n\n            long nanos = endNanos - startNanos;\n\n            if (methodStat != null) {\n                methodStat.afterInvoke(error, nanos);\n            }\n\n            SpringMethodStat.setCurrent(lastMethodStat);\n        }\n    }\n\n    public SpringMethodInfo getMethodInfo(MethodInvocation invocation) {\n        Object thisObject = invocation.getThis();\n        Method method = invocation.getMethod();\n\n        if (thisObject == null) {\n            return new SpringMethodInfo(method.getDeclaringClass(), method);\n        }\n\n        if (method.getDeclaringClass() == thisObject.getClass()) {\n            return new SpringMethodInfo(method.getDeclaringClass(), method);\n        }\n\n        {\n            Class<?> clazz = thisObject.getClass();\n            boolean isCglibProxy = false;\n            boolean isJavassistProxy = false;\n            for (Class<?> item : clazz.getInterfaces()) {\n                if (item.getName().equals(\"net.sf.cglib.proxy.Factory\")) {\n                    isCglibProxy = true;\n                    break;\n                } else if (item.getName().equals(\"javassist.util.proxy.ProxyObject\")) {\n                    isJavassistProxy = true;\n                    break;\n                }\n            }\n\n            if (isCglibProxy || isJavassistProxy) {\n                Class<?> superClazz = clazz.getSuperclass();\n\n                return new SpringMethodInfo(superClazz, method);\n            }\n        }\n\n        Class<?> clazz = null;\n        try {\n            // 最多支持10层代理\n            for (int i = 0; i < 10; ++i) {\n                if (thisObject instanceof org.springframework.aop.framework.Advised) {\n                    TargetSource targetSource = ((org.springframework.aop.framework.Advised) thisObject).getTargetSource();\n\n                    if (targetSource == null) {\n                        break;\n                    }\n\n                    Object target = targetSource.getTarget();\n                    if (target != null) {\n                        thisObject = target;\n                    } else {\n                        clazz = targetSource.getTargetClass();\n                        break;\n                    }\n                } else {\n                    break;\n                }\n            }\n        } catch (Exception ex) {\n            LOG.error(\"getMethodInfo error\", ex);\n        }\n\n        if (clazz == null) {\n            return new SpringMethodInfo(method.getDeclaringClass(), method);\n        }\n\n        return new SpringMethodInfo(clazz, method);\n    }\n\n    static class SpringMethodContextListener extends StatFilterContextListenerAdapter {\n        @Override\n        public void addUpdateCount(int updateCount) {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.addJdbcUpdateCount(updateCount);\n            }\n        }\n\n        @Override\n        public void addFetchRowCount(int fetchRowCount) {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.addJdbcFetchRowCount(fetchRowCount);\n            }\n        }\n\n        @Override\n        public void executeBefore(String sql, boolean inTransaction) {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.incrementJdbcExecuteCount();\n            }\n        }\n\n        @Override\n        public void executeAfter(String sql, long nanos, Throwable error) {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.addJdbcExecuteTimeNano(nanos);\n                if (error != null) {\n                    springMethodStat.incrementJdbcExecuteErrorCount();\n                }\n            }\n        }\n\n        @Override\n        public void commit() {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.incrementJdbcCommitCount();\n            }\n        }\n\n        @Override\n        public void rollback() {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.incrementJdbcRollbackCount();\n            }\n        }\n\n        @Override\n        public void pool_connect() {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.incrementJdbcPoolConnectionOpenCount();\n            }\n        }\n\n        @Override\n        public void pool_close(long nanos) {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.incrementJdbcPoolConnectionCloseCount();\n            }\n        }\n\n        @Override\n        public void resultSet_open() {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.incrementJdbcResultSetOpenCount();\n            }\n        }\n\n        @Override\n        public void resultSet_close(long nanos) {\n            SpringMethodStat springMethodStat = SpringMethodStat.current();\n            if (springMethodStat != null) {\n                springMethodStat.incrementJdbcResultSetCloseCount();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport java.lang.reflect.Method;\n\npublic class SpringMethodInfo {\n    private String signature;\n\n    private Class<?> instanceClass;\n    private Method method;\n\n    public SpringMethodInfo(Class<?> instanceClass, Method method) {\n        this.instanceClass = instanceClass;\n        this.method = method;\n    }\n\n    public String getClassName() {\n        return instanceClass.getName();\n    }\n\n    public String getMethodName() {\n        return method.getName();\n    }\n\n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + instanceClass.getName().hashCode();\n        result = prime * result + method.getName().hashCode();\n        return result;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n\n        if (obj == null || !(obj instanceof SpringMethodInfo)) {\n            return false;\n        }\n\n        SpringMethodInfo other = (SpringMethodInfo) obj;\n\n        if (!instanceClass.getName().equals(other.instanceClass.getName())) {\n            return false;\n        }\n\n        if (!method.getName().equals(other.method.getName())) {\n            return false;\n        }\n\n        if (method.getParameterTypes().length != other.method.getParameterTypes().length) {\n            return false;\n        }\n\n        for (int i = 0; i < method.getParameterTypes().length; ++i) {\n            if (!method.getParameterTypes()[i].getName().equals(other.method.getParameterTypes()[i].getName())) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    public static String getMethodSignature(Method method) {\n        StringBuilder sb = new StringBuilder();\n\n        sb.append(method.getName());\n        sb.append('(');\n        Class<?>[] params = method.getParameterTypes();\n        for (int j = 0; j < params.length; j++) {\n            sb.append(params[j].getName());\n            if (j < (params.length - 1)) {\n                sb.append(',');\n            }\n        }\n        sb.append(')');\n\n        return sb.toString();\n    }\n\n    public String getSignature() {\n        if (signature == null) {\n            signature = getMethodSignature(method);\n        }\n        return signature;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport com.alibaba.druid.support.profile.Profiler;\n\nimport java.util.Date;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class SpringMethodStat {\n    private static final ThreadLocal<SpringMethodStat> currentLocal = new ThreadLocal<SpringMethodStat>();\n\n    private final SpringMethodInfo methodInfo;\n\n    private final AtomicInteger runningCount = new AtomicInteger();\n    private final AtomicInteger concurrentMax = new AtomicInteger();\n    private final AtomicLong executeCount = new AtomicLong(0);\n    private final AtomicLong executeErrorCount = new AtomicLong(0);\n    private final AtomicLong executeTimeNano = new AtomicLong();\n\n    private final AtomicLong jdbcFetchRowCount = new AtomicLong();\n    private final AtomicLong jdbcUpdateCount = new AtomicLong();\n    private final AtomicLong jdbcExecuteCount = new AtomicLong();\n    private final AtomicLong jdbcExecuteErrorCount = new AtomicLong();\n    private final AtomicLong jdbcExecuteTimeNano = new AtomicLong();\n\n    private final AtomicLong jdbcCommitCount = new AtomicLong();\n    private final AtomicLong jdbcRollbackCount = new AtomicLong();\n\n    private final AtomicLong jdbcPoolConnectionOpenCount = new AtomicLong();\n    private final AtomicLong jdbcPoolConnectionCloseCount = new AtomicLong();\n\n    private final AtomicLong jdbcResultSetOpenCount = new AtomicLong();\n    private final AtomicLong jdbcResultSetCloseCount = new AtomicLong();\n\n    private volatile Throwable lastError;\n    private volatile long lastErrorTimeMillis;\n\n    private volatile long histogram_0_1;\n    private volatile long histogram_1_10;\n    private volatile long histogram_10_100;\n    private volatile long histogram_100_1000;\n    private volatile int histogram_1000_10000;\n    private volatile int histogram_10000_100000;\n    private volatile int histogram_100000_1000000;\n    private volatile int histogram_1000000_more;\n\n    static final AtomicLongFieldUpdater<SpringMethodStat> histogram_0_1_Updater = AtomicLongFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_0_1\");\n    static final AtomicLongFieldUpdater<SpringMethodStat> histogram_1_10_Updater = AtomicLongFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_1_10\");\n    static final AtomicLongFieldUpdater<SpringMethodStat> histogram_10_100_Updater = AtomicLongFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_10_100\");\n    static final AtomicLongFieldUpdater<SpringMethodStat> histogram_100_1000_Updater = AtomicLongFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_100_1000\");\n    static final AtomicIntegerFieldUpdater<SpringMethodStat> histogram_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_1000_10000\");\n    static final AtomicIntegerFieldUpdater<SpringMethodStat> histogram_10000_100000_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_10000_100000\");\n    static final AtomicIntegerFieldUpdater<SpringMethodStat> histogram_100000_1000000_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_100000_1000000\");\n    static final AtomicIntegerFieldUpdater<SpringMethodStat> histogram_1000000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(SpringMethodStat.class,\n            \"histogram_1000000_more\");\n\n    public SpringMethodStat(SpringMethodInfo methodInfo) {\n        this.methodInfo = methodInfo;\n    }\n\n    public SpringMethodStatValue getStatValue(boolean reset) {\n        SpringMethodStatValue val = new SpringMethodStatValue();\n\n        val.setClassName(this.getMethodInfo().getClassName());\n        val.setSignature(this.getMethodInfo().getSignature());\n\n        val.setRunningCount(this.getRunningCount());\n\n        val.setConcurrentMax(get(this.concurrentMax, reset));\n        val.setExecuteCount(get(this.executeCount, reset));\n        val.setExecuteErrorCount(get(this.executeErrorCount, reset));\n        val.setExecuteTimeNano(get(this.executeTimeNano, reset));\n\n        val.setJdbcFetchRowCount(get(this.jdbcFetchRowCount, reset));\n        val.setJdbcUpdateCount(get(this.jdbcUpdateCount, reset));\n        val.setJdbcExecuteCount(get(this.jdbcExecuteCount, reset));\n        val.setJdbcExecuteErrorCount(get(this.jdbcExecuteErrorCount, reset));\n        val.setJdbcExecuteTimeNano(get(this.jdbcExecuteTimeNano, reset));\n\n        val.setJdbcCommitCount(get(this.jdbcCommitCount, reset));\n        val.setJdbcRollbackCount(get(this.jdbcRollbackCount, reset));\n\n        val.setJdbcPoolConnectionOpenCount(get(this.jdbcPoolConnectionOpenCount, reset));\n        val.setJdbcPoolConnectionCloseCount(get(this.jdbcPoolConnectionCloseCount, reset));\n\n        val.setJdbcResultSetOpenCount(get(this.jdbcResultSetOpenCount, reset));\n        val.setJdbcResultSetCloseCount(get(this.jdbcResultSetCloseCount, reset));\n\n        val.setLastError(this.lastError);\n        val.setLastErrorTimeMillis(this.lastErrorTimeMillis);\n        if (reset) {\n            this.lastError = null;\n            this.lastErrorTimeMillis = 0;\n        }\n\n        val.histogram_0_1 = get(this, histogram_0_1_Updater, reset);\n        val.histogram_1_10 = get(this, histogram_1_10_Updater, reset);\n        val.histogram_10_100 = get(this, histogram_10_100_Updater, reset);\n        val.histogram_100_1000 = get(this, histogram_100_1000_Updater, reset);\n        val.histogram_1000_10000 = get(this, histogram_1000_10000_Updater, reset);\n        val.histogram_10000_100000 = get(this, histogram_10000_100000_Updater, reset);\n        val.histogram_100000_1000000 = get(this, histogram_100000_1000000_Updater, reset);\n        val.histogram_1000000_more = get(this, histogram_1000000_more_Updater, reset);\n\n        return val;\n    }\n\n    public void reset() {\n        concurrentMax.set(0);\n        executeCount.set(0);\n        executeErrorCount.set(0);\n        executeTimeNano.set(0);\n\n        jdbcFetchRowCount.set(0);\n        jdbcUpdateCount.set(0);\n        jdbcExecuteCount.set(0);\n        jdbcExecuteErrorCount.set(0);\n        jdbcExecuteTimeNano.set(0);\n\n        jdbcCommitCount.set(0);\n        jdbcRollbackCount.set(0);\n\n        jdbcPoolConnectionOpenCount.set(0);\n        jdbcPoolConnectionCloseCount.set(0);\n\n        jdbcResultSetOpenCount.set(0);\n        jdbcResultSetCloseCount.set(0);\n\n        lastError = null;\n        lastErrorTimeMillis = 0;\n\n        histogram_0_1_Updater.set(this, 0);\n        histogram_1_10_Updater.set(this, 0);\n        histogram_10_100_Updater.set(this, 0);\n        histogram_100_1000_Updater.set(this, 0);\n        histogram_1000_10000_Updater.set(this, 0);\n        histogram_10000_100000_Updater.set(this, 0);\n        histogram_100000_1000000_Updater.set(this, 0);\n        histogram_1000000_more_Updater.set(this, 0);\n    }\n\n    public SpringMethodInfo getMethodInfo() {\n        return methodInfo;\n    }\n\n    public static SpringMethodStat current() {\n        return currentLocal.get();\n    }\n\n    public static void setCurrent(SpringMethodStat current) {\n        currentLocal.set(current);\n    }\n\n    public void beforeInvoke() {\n        currentLocal.set(this);\n\n        int running = runningCount.incrementAndGet();\n\n        for (; ; ) {\n            int max = concurrentMax.get();\n            if (running > max) {\n                if (concurrentMax.compareAndSet(max, running)) {\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n\n        executeCount.incrementAndGet();\n\n        Profiler.enter(methodInfo.getSignature(), Profiler.PROFILE_TYPE_SPRING);\n    }\n\n    public void afterInvoke(Throwable error, long nanos) {\n        runningCount.decrementAndGet();\n        executeTimeNano.addAndGet(nanos);\n        histogramRecord(nanos);\n\n        if (error != null) {\n            executeErrorCount.incrementAndGet();\n            lastError = error;\n            lastErrorTimeMillis = System.currentTimeMillis();\n        }\n\n        Profiler.release(nanos);\n    }\n\n    private void histogramRecord(long nanos) {\n        final long millis = nanos / 1000 / 1000;\n\n        if (millis < 1) {\n            histogram_0_1_Updater.incrementAndGet(this);\n        } else if (millis < 10) {\n            histogram_1_10_Updater.incrementAndGet(this);\n        } else if (millis < 100) {\n            histogram_10_100_Updater.incrementAndGet(this);\n        } else if (millis < 1000) {\n            histogram_100_1000_Updater.incrementAndGet(this);\n        } else if (millis < 10000) {\n            histogram_1000_10000_Updater.incrementAndGet(this);\n        } else if (millis < 100000) {\n            histogram_10000_100000_Updater.incrementAndGet(this);\n        } else if (millis < 1000000) {\n            histogram_100000_1000000_Updater.incrementAndGet(this);\n        } else {\n            histogram_1000000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public long[] getHistogramValues() {\n        return new long[]{\n                //\n                histogram_0_1, //\n                histogram_1_10, //\n                histogram_10_100, //\n                histogram_100_1000, //\n                histogram_1000_10000, //\n                histogram_10000_100000, //\n                histogram_100000_1000000, //\n                histogram_1000000_more //\n        };\n    }\n\n    public Throwable getLastError() {\n        return lastError;\n    }\n\n    public Date getLastErrorTime() {\n        if (lastErrorTimeMillis <= 0) {\n            return null;\n        }\n\n        return new Date(lastErrorTimeMillis);\n    }\n\n    public long getLastErrorTimeMillis() {\n        return lastErrorTimeMillis;\n    }\n\n    public int getRunningCount() {\n        return this.runningCount.get();\n    }\n\n    public int getConcurrentMax() {\n        return concurrentMax.get();\n    }\n\n    public long getExecuteCount() {\n        return executeCount.get();\n    }\n\n    public long getExecuteErrorCount() {\n        return executeErrorCount.get();\n    }\n\n    public long getExecuteTimeNano() {\n        return executeTimeNano.get();\n    }\n\n    public long getExecuteTimeMillis() {\n        return getExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public void addJdbcFetchRowCount(long delta) {\n        this.jdbcFetchRowCount.addAndGet(delta);\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount.get();\n    }\n\n    public void addJdbcUpdateCount(long updateCount) {\n        this.jdbcUpdateCount.addAndGet(updateCount);\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount.get();\n    }\n\n    public void incrementJdbcExecuteCount() {\n        jdbcExecuteCount.incrementAndGet();\n    }\n\n    public void addJdbcExecuteCount(long executeCount) {\n        jdbcExecuteCount.addAndGet(executeCount);\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount.get();\n    }\n\n    public long getJdbcExecuteErrorCount() {\n        return jdbcExecuteErrorCount.get();\n    }\n\n    public void addJdbcExecuteErrorCount(long executeCount) {\n        jdbcExecuteErrorCount.addAndGet(executeCount);\n    }\n\n    public void incrementJdbcExecuteErrorCount() {\n        jdbcExecuteErrorCount.incrementAndGet();\n    }\n\n    public long getJdbcExecuteTimeMillis() {\n        return getJdbcExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano.get();\n    }\n\n    public void addJdbcExecuteTimeNano(long nano) {\n        jdbcExecuteTimeNano.addAndGet(nano);\n    }\n\n    public void incrementJdbcCommitCount() {\n        jdbcCommitCount.incrementAndGet();\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount.get();\n    }\n\n    public void addJdbcCommitCount(long commitCount) {\n        this.jdbcCommitCount.addAndGet(commitCount);\n    }\n\n    public void incrementJdbcRollbackCount() {\n        jdbcRollbackCount.incrementAndGet();\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount.get();\n    }\n\n    public void addJdbcRollbackCount(long rollbackCount) {\n        this.jdbcRollbackCount.addAndGet(rollbackCount);\n    }\n\n    public long getJdbcPoolConnectionOpenCount() {\n        return jdbcPoolConnectionOpenCount.get();\n    }\n\n    public void addJdbcPoolConnectionOpenCount(long delta) {\n        jdbcPoolConnectionOpenCount.addAndGet(delta);\n    }\n\n    public void incrementJdbcPoolConnectionOpenCount() {\n        jdbcPoolConnectionOpenCount.incrementAndGet();\n    }\n\n    public long getJdbcPoolConnectionCloseCount() {\n        return jdbcPoolConnectionCloseCount.get();\n    }\n\n    public void addJdbcPoolConnectionCloseCount(long delta) {\n        jdbcPoolConnectionCloseCount.addAndGet(delta);\n    }\n\n    public void incrementJdbcPoolConnectionCloseCount() {\n        jdbcPoolConnectionCloseCount.incrementAndGet();\n    }\n\n    public long getJdbcResultSetOpenCount() {\n        return jdbcResultSetOpenCount.get();\n    }\n\n    public void addJdbcResultSetOpenCount(long delta) {\n        jdbcResultSetOpenCount.addAndGet(delta);\n    }\n\n    public void incrementJdbcResultSetOpenCount() {\n        jdbcResultSetOpenCount.incrementAndGet();\n    }\n\n    public long getJdbcResultSetCloseCount() {\n        return jdbcResultSetCloseCount.get();\n    }\n\n    public void addJdbcResultSetCloseCount(long delta) {\n        jdbcResultSetCloseCount.addAndGet(delta);\n    }\n\n    public void incrementJdbcResultSetCloseCount() {\n        jdbcResultSetCloseCount.incrementAndGet();\n    }\n\n    public Map<String, Object> getStatData() {\n        return getStatValue(false).getData();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/SpringMethodStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\nimport com.alibaba.druid.util.Utils;\n\nimport java.util.Date;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n@MTable(name = \"druid_springmethod\")\npublic class SpringMethodStatValue {\n    @MField(groupBy = true, aggregate = AggregateType.None)\n    private String className;\n\n    @MField(groupBy = true, aggregate = AggregateType.None)\n    private String signature;\n\n    @MField(aggregate = AggregateType.Last)\n    private int runningCount;\n\n    @MField(aggregate = AggregateType.Max)\n    private int concurrentMax;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long executeCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long executeErrorCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long executeTimeNano;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcFetchRowCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcUpdateCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcExecuteCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcExecuteErrorCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcExecuteTimeNano;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcCommitCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcRollbackCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcPoolConnectionOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcPoolConnectionCloseCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcResultSetOpenCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long jdbcResultSetCloseCount;\n\n    @MField(aggregate = AggregateType.Last)\n    private String lastErrorClass;\n\n    @MField(aggregate = AggregateType.Last)\n    private String lastErrorMessage;\n\n    @MField(aggregate = AggregateType.Last)\n    private String lastErrorStackTrace;\n\n    @MField(aggregate = AggregateType.Last)\n    private long lastErrorTimeMillis;\n\n    @MField(name = \"h1\", aggregate = AggregateType.Sum)\n    long histogram_0_1;\n\n    @MField(name = \"h10\", aggregate = AggregateType.Sum)\n    long histogram_1_10;\n\n    @MField(name = \"h100\", aggregate = AggregateType.Sum)\n    long histogram_10_100;\n\n    @MField(name = \"h1000\", aggregate = AggregateType.Sum)\n    long histogram_100_1000;\n\n    @MField(name = \"h10000\", aggregate = AggregateType.Sum)\n    int histogram_1000_10000;\n\n    @MField(name = \"h100000\", aggregate = AggregateType.Sum)\n    int histogram_10000_100000;\n\n    @MField(name = \"h1000000\", aggregate = AggregateType.Sum)\n    int histogram_100000_1000000;\n\n    @MField(name = \"hmore\", aggregate = AggregateType.Sum)\n    int histogram_1000000_more;\n\n    public String getClassName() {\n        return className;\n    }\n\n    public void setClassName(String className) {\n        this.className = className;\n    }\n\n    public String getSignature() {\n        return signature;\n    }\n\n    public void setSignature(String signature) {\n        this.signature = signature;\n    }\n\n    public int getRunningCount() {\n        return runningCount;\n    }\n\n    public void setRunningCount(int runningCount) {\n        this.runningCount = runningCount;\n    }\n\n    public int getConcurrentMax() {\n        return concurrentMax;\n    }\n\n    public void setConcurrentMax(int concurrentMax) {\n        this.concurrentMax = concurrentMax;\n    }\n\n    public long getExecuteCount() {\n        return executeCount;\n    }\n\n    public void setExecuteCount(long executeCount) {\n        this.executeCount = executeCount;\n    }\n\n    public long getExecuteErrorCount() {\n        return executeErrorCount;\n    }\n\n    public void setExecuteErrorCount(long executeErrorCount) {\n        this.executeErrorCount = executeErrorCount;\n    }\n\n    public long getExecuteTimeNano() {\n        return executeTimeNano;\n    }\n\n    public void setExecuteTimeNano(long executeTimeNano) {\n        this.executeTimeNano = executeTimeNano;\n    }\n\n    public long getJdbcFetchRowCount() {\n        return jdbcFetchRowCount;\n    }\n\n    public void setJdbcFetchRowCount(long jdbcFetchRowCount) {\n        this.jdbcFetchRowCount = jdbcFetchRowCount;\n    }\n\n    public long getJdbcUpdateCount() {\n        return jdbcUpdateCount;\n    }\n\n    public void setJdbcUpdateCount(long jdbcUpdateCount) {\n        this.jdbcUpdateCount = jdbcUpdateCount;\n    }\n\n    public long getJdbcExecuteCount() {\n        return jdbcExecuteCount;\n    }\n\n    public void setJdbcExecuteCount(long jdbcExecuteCount) {\n        this.jdbcExecuteCount = jdbcExecuteCount;\n    }\n\n    public long getJdbcExecuteErrorCount() {\n        return jdbcExecuteErrorCount;\n    }\n\n    public void setJdbcExecuteErrorCount(long jdbcExecuteErrorCount) {\n        this.jdbcExecuteErrorCount = jdbcExecuteErrorCount;\n    }\n\n    public long getJdbcExecuteTimeNano() {\n        return jdbcExecuteTimeNano;\n    }\n\n    public void setJdbcExecuteTimeNano(long jdbcExecuteTimeNano) {\n        this.jdbcExecuteTimeNano = jdbcExecuteTimeNano;\n    }\n\n    public long getJdbcCommitCount() {\n        return jdbcCommitCount;\n    }\n\n    public void setJdbcCommitCount(long jdbcCommitCount) {\n        this.jdbcCommitCount = jdbcCommitCount;\n    }\n\n    public long getJdbcRollbackCount() {\n        return jdbcRollbackCount;\n    }\n\n    public void setJdbcRollbackCount(long jdbcRollbackCount) {\n        this.jdbcRollbackCount = jdbcRollbackCount;\n    }\n\n    public long getJdbcPoolConnectionOpenCount() {\n        return jdbcPoolConnectionOpenCount;\n    }\n\n    public void setJdbcPoolConnectionOpenCount(long jdbcPoolConnectionOpenCount) {\n        this.jdbcPoolConnectionOpenCount = jdbcPoolConnectionOpenCount;\n    }\n\n    public long getJdbcPoolConnectionCloseCount() {\n        return jdbcPoolConnectionCloseCount;\n    }\n\n    public void setJdbcPoolConnectionCloseCount(long jdbcPoolConnectionCloseCount) {\n        this.jdbcPoolConnectionCloseCount = jdbcPoolConnectionCloseCount;\n    }\n\n    public long getJdbcResultSetOpenCount() {\n        return jdbcResultSetOpenCount;\n    }\n\n    public void setJdbcResultSetOpenCount(long jdbcResultSetOpenCount) {\n        this.jdbcResultSetOpenCount = jdbcResultSetOpenCount;\n    }\n\n    public long getJdbcResultSetCloseCount() {\n        return jdbcResultSetCloseCount;\n    }\n\n    public void setJdbcResultSetCloseCount(long jdbcResultSetCloseCount) {\n        this.jdbcResultSetCloseCount = jdbcResultSetCloseCount;\n    }\n\n    public void setLastError(Throwable lastError) {\n        if (lastError != null) {\n            lastErrorClass = lastError.getClass().getName();\n            lastErrorMessage = lastError.getMessage();\n            lastErrorStackTrace = Utils.toString(lastError.getStackTrace());\n        }\n    }\n\n    public long getLastErrorTimeMillis() {\n        return lastErrorTimeMillis;\n    }\n\n    public void setLastErrorTimeMillis(long lastErrorTimeMillis) {\n        this.lastErrorTimeMillis = lastErrorTimeMillis;\n    }\n\n    public long getExecuteTimeMillis() {\n        return getExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public long getJdbcExecuteTimeMillis() {\n        return getJdbcExecuteTimeNano() / (1000 * 1000);\n    }\n\n    public Date getLastErrorTime() {\n        if (lastErrorTimeMillis <= 0) {\n            return null;\n        }\n\n        return new Date(lastErrorTimeMillis);\n    }\n\n    public long[] getHistogram() {\n        return new long[]{\n                //\n                histogram_0_1, //\n                histogram_1_10, //\n                histogram_10_100, //\n                histogram_100_1000, //\n                histogram_1000_10000, //\n                histogram_10000_100000, //\n                histogram_100000_1000000, //\n                histogram_1000000_more //\n        };\n    }\n\n    public Map<String, Object> getData() {\n        Map<String, Object> data = new LinkedHashMap<String, Object>();\n\n        data.put(\"Class\", this.getClassName());\n        data.put(\"Method\", this.getSignature());\n\n        data.put(\"RunningCount\", this.getRunningCount());\n        data.put(\"ConcurrentMax\", this.getConcurrentMax());\n        data.put(\"ExecuteCount\", this.getExecuteCount());\n        data.put(\"ExecuteErrorCount\", this.getExecuteErrorCount());\n        data.put(\"ExecuteTimeMillis\", this.getExecuteTimeMillis());\n\n        data.put(\"JdbcCommitCount\", this.getJdbcCommitCount());\n        data.put(\"JdbcRollbackCount\", this.getJdbcRollbackCount());\n\n        data.put(\"JdbcPoolConnectionOpenCount\", this.getJdbcPoolConnectionOpenCount());\n        data.put(\"JdbcPoolConnectionCloseCount\", this.getJdbcPoolConnectionCloseCount());\n\n        data.put(\"JdbcResultSetOpenCount\", this.getJdbcResultSetOpenCount());\n        data.put(\"JdbcResultSetCloseCount\", this.getJdbcResultSetCloseCount());\n\n        data.put(\"JdbcExecuteCount\", this.getJdbcExecuteCount());\n        data.put(\"JdbcExecuteErrorCount\", this.getJdbcExecuteErrorCount());\n        data.put(\"JdbcExecuteTimeMillis\", this.getJdbcExecuteTimeMillis());\n        data.put(\"JdbcFetchRowCount\", this.getJdbcFetchRowCount());\n        data.put(\"JdbcUpdateCount\", this.getJdbcUpdateCount());\n\n        if (this.lastErrorClass == null) {\n            data.put(\"LastError\", null);\n        } else {\n            Map<String, Object> map = new LinkedHashMap<String, Object>(3);\n            map.put(\"Class\", lastErrorClass);\n            map.put(\"Message\", lastErrorMessage);\n            map.put(\"StackTrace\", lastErrorStackTrace);\n            data.put(\"LastError\", map);\n        }\n\n        data.put(\"LastErrorTime\", this.getLastErrorTime());\n\n        data.put(\"Histogram\", this.getHistogram());\n\n        return data;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/SpringStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\npublic class SpringStat {\n    private ConcurrentMap<SpringMethodInfo, SpringMethodStat> methodStats = new ConcurrentHashMap<SpringMethodInfo, SpringMethodStat>(16, 0.75f, 1);\n\n    public SpringStat() {\n    }\n\n    public void reset() {\n        for (SpringMethodStat stat : methodStats.values()) {\n            stat.reset();\n        }\n    }\n\n    public SpringMethodStat getMethodStat(SpringMethodInfo methodInfo, boolean create) {\n        SpringMethodStat methodStat = methodStats.get(methodInfo);\n        if (methodStat != null) {\n            return methodStat;\n        }\n\n        if (create) {\n            methodStats.putIfAbsent(methodInfo, new SpringMethodStat(methodInfo));\n            methodStat = methodStats.get(methodInfo);\n        }\n\n        return methodStat;\n    }\n\n    public List<SpringMethodStatValue> getStatList(boolean reset) {\n        List<SpringMethodStatValue> statValueList = new ArrayList<SpringMethodStatValue>(this.methodStats.size());\n\n        for (SpringMethodStat methodStat : this.methodStats.values()) {\n            SpringMethodStatValue statValue = methodStat.getStatValue(reset);\n\n            if (statValue.getRunningCount() == 0 && statValue.getExecuteCount() == 0) {\n                continue;\n            }\n\n            statValueList.add(statValue);\n        }\n\n        return statValueList;\n    }\n\n    public List<Map<String, Object>> getMethodStatDataList() {\n        List<Map<String, Object>> methodStatDataList = new ArrayList<Map<String, Object>>(this.methodStats.size());\n        for (SpringMethodStat methodStat : this.methodStats.values()) {\n            Map<String, Object> methodStatData = methodStat.getStatData();\n\n            int runningCount = ((Number) methodStatData.get(\"RunningCount\")).intValue();\n            long executeCount = (Long) methodStatData.get(\"ExecuteCount\");\n\n            if (runningCount == 0 && executeCount == 0) {\n                continue;\n            }\n\n            methodStatDataList.add(methodStatData);\n        }\n        return methodStatDataList;\n    }\n\n    public Map<String, Object> getMethodStatData(String clazz, String method) {\n        for (SpringMethodStat methodStat : this.methodStats.values()) {\n            SpringMethodInfo methodInfo = methodStat.getMethodInfo();\n            if (methodInfo.getClassName().equals(clazz)\n                    && methodInfo.getSignature().equals(method)) {\n                return methodStat.getStatData();\n            }\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/SpringStatManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport java.util.*;\nimport java.util.concurrent.CopyOnWriteArraySet;\n\npublic class SpringStatManager {\n    public static final String SYS_PROP_INSTANCES = \"druid.spring.springStat\";\n\n    private static final SpringStatManager instance = new SpringStatManager();\n\n    private Set<Object> springStatSet;\n\n    public static SpringStatManager getInstance() {\n        return instance;\n    }\n\n    public Set<Object> getSpringStatSet() {\n        if (springStatSet == null) {\n            if (DruidDataSourceStatManager.isRegisterToSystemProperty()) {\n                springStatSet = getSpringStatSetFromSysProperty();\n            } else {\n                springStatSet = new CopyOnWriteArraySet<Object>();\n            }\n        }\n\n        return springStatSet;\n    }\n\n    public void addSpringStat(Object springStat) {\n        getSpringStatSet().add(springStat);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    static Set<Object> getSpringStatSetFromSysProperty() {\n        Properties properties = System.getProperties();\n        Set<Object> webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);\n\n        if (webAppStats == null) {\n            synchronized (properties) {\n                webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);\n\n                if (webAppStats == null) {\n                    webAppStats = new CopyOnWriteArraySet<Object>();\n                    properties.put(SYS_PROP_INSTANCES, webAppStats);\n                }\n            }\n        }\n\n        return webAppStats;\n    }\n\n    public List<Map<String, Object>> getMethodStatData() {\n        Set<Object> stats = getSpringStatSet();\n\n        List<Map<String, Object>> allMethodStatDataList = new ArrayList<Map<String, Object>>();\n\n        for (Object stat : stats) {\n            List<Map<String, Object>> methodStatDataList = SpringStatUtils.getMethodStatDataList(stat);\n            if (methodStatDataList != null) {\n                allMethodStatDataList.addAll(methodStatDataList);\n            }\n        }\n\n        return allMethodStatDataList;\n    }\n\n    public Map<String, Object> getMethodStatData(String clazz, String method) {\n        Set<Object> stats = getSpringStatSet();\n\n        for (Object stat : stats) {\n            Map<String, Object> statData = SpringStatUtils.getMethodStatData(stat, clazz, method);\n            if (statData != null) {\n                return statData;\n            }\n        }\n\n        return null;\n    }\n\n    public void resetStat() {\n        Set<Object> stats = getSpringStatSet();\n\n        for (Object stat : stats) {\n            SpringStatUtils.reset(stat);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/SpringStatUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.lang.reflect.Method;\nimport java.util.List;\nimport java.util.Map;\n\npublic class SpringStatUtils {\n    private static final Log LOG = LogFactory.getLog(SpringStatUtils.class);\n\n    @SuppressWarnings(\"unchecked\")\n    public static List<Map<String, Object>> getMethodStatDataList(Object methodStat) {\n        if (methodStat.getClass() == SpringStat.class) {\n            return ((SpringStat) methodStat).getMethodStatDataList();\n        }\n\n        try {\n            Method method = methodStat.getClass().getMethod(\"getMethodStatDataList\");\n            Object obj = method.invoke(methodStat);\n            return (List<Map<String, Object>>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getMethodStatDataList error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<String, Object> getMethodStatData(Object methodStat, String clazz, String methodSignature) {\n        if (methodStat.getClass() == SpringStat.class) {\n            return ((SpringStat) methodStat).getMethodStatData(clazz, methodSignature);\n        }\n\n        try {\n            Method method = methodStat.getClass().getMethod(\"getMethodStatData\", String.class, String.class);\n            Object obj = method.invoke(methodStat, clazz, methodSignature);\n            return (Map<String, Object>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getMethodStatDataList error\", e);\n            return null;\n        }\n    }\n\n    public static void reset(Object webStat) {\n        if (webStat.getClass() == SpringStat.class) {\n            ((SpringStat) webStat).reset();\n            return;\n        }\n\n        try {\n            Method method = webStat.getClass().getMethod(\"reset\");\n            method.invoke(webStat);\n        } catch (Exception e) {\n            LOG.error(\"reset error\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/annotation/Stat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat.annotation;\n\nimport java.lang.annotation.*;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface Stat {\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/annotation/StatAnnotationAdvisor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat.annotation;\n\nimport com.alibaba.druid.support.spring.stat.DruidStatInterceptor;\nimport org.aopalliance.aop.Advice;\nimport org.springframework.aop.Pointcut;\nimport org.springframework.aop.support.AbstractPointcutAdvisor;\nimport org.springframework.aop.support.ComposablePointcut;\nimport org.springframework.aop.support.annotation.AnnotationMatchingPointcut;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.BeanFactory;\nimport org.springframework.beans.factory.BeanFactoryAware;\n\n@SuppressWarnings(\"serial\")\npublic class StatAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {\n    private Advice advice;\n    private Pointcut pointcut;\n    private DruidStatInterceptor druidStatInterceptor;\n\n    public StatAnnotationAdvisor(DruidStatInterceptor druidStatInterceptor) {\n        this.druidStatInterceptor = druidStatInterceptor;\n        this.advice = buildAdvice();\n        this.pointcut = buildPointcut();\n    }\n\n    public Pointcut getPointcut() {\n        return this.pointcut;\n    }\n\n    public Advice getAdvice() {\n        return this.advice;\n    }\n\n    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {\n        if (this.advice instanceof BeanFactoryAware) {\n            ((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);\n        }\n    }\n\n    protected Advice buildAdvice() {\n        return druidStatInterceptor;\n    }\n\n    protected Pointcut buildPointcut() {\n        Pointcut cpc = new AnnotationMatchingPointcut(Stat.class, true);\n        Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(Stat.class);\n\n        ComposablePointcut result = new ComposablePointcut(cpc).union(mpc);\n\n        return result;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/annotation/StatAnnotationBeanPostProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat.annotation;\n\nimport com.alibaba.druid.support.spring.stat.DruidStatInterceptor;\nimport org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor;\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.BeanFactory;\nimport org.springframework.beans.factory.BeanFactoryAware;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\n\n@SuppressWarnings(\"serial\")\npublic class StatAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostProcessor implements BeanFactoryAware {\n    @Autowired\n    @Qualifier(\"druid-stat-interceptor\")\n    private DruidStatInterceptor druidStatInterceptor;\n\n    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {\n        setBeforeExistingAdvisors(true);\n        StatAnnotationAdvisor advisor = new StatAnnotationAdvisor(druidStatInterceptor);\n        advisor.setBeanFactory(beanFactory);\n        this.advisor = advisor;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/config/DruidStatBeanDefinitionParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat.config;\n\nimport org.springframework.beans.factory.config.BeanDefinition;\nimport org.springframework.beans.factory.config.BeanDefinitionHolder;\nimport org.springframework.beans.factory.parsing.BeanComponentDefinition;\nimport org.springframework.beans.factory.parsing.CompositeComponentDefinition;\nimport org.springframework.beans.factory.support.BeanDefinitionBuilder;\nimport org.springframework.beans.factory.support.BeanDefinitionRegistry;\nimport org.springframework.beans.factory.xml.BeanDefinitionParser;\nimport org.springframework.beans.factory.xml.ParserContext;\nimport org.w3c.dom.Element;\n\npublic class DruidStatBeanDefinitionParser implements BeanDefinitionParser {\n    public static final String STAT_ANNOTATION_PROCESSOR_BEAN_NAME = \"com.alibaba.druid.support.spring.stat.annotation.internalStatAnnotationBeanPostProcessor\";\n    public static final String STAT_ANNOTATION_PROCESSOR_BEAN_CLASS = \"com.alibaba.druid.support.spring.stat.annotation.StatAnnotationBeanPostProcessor\";\n    public static final String STAT_ANNOTATION_ADVICE_BEAN_NAME = \"druid-stat-interceptor\";\n    public static final String STAT_ANNOTATION_ADVICE_BEAN_CLASS = \"com.alibaba.druid.support.spring.stat.DruidStatInterceptor\";\n\n    @Override\n    public BeanDefinition parse(Element element, ParserContext parserContext) {\n        Object source = parserContext.extractSource(element);\n\n        CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);\n        parserContext.pushContainingComponent(compDefinition);\n\n        BeanDefinitionRegistry registry = parserContext.getRegistry();\n\n        if (registry.containsBeanDefinition(STAT_ANNOTATION_PROCESSOR_BEAN_NAME)) {\n            parserContext.getReaderContext().error(\n                    \"Only one DruidStatBeanDefinitionParser may exist within the context.\", source);\n        } else {\n            BeanDefinitionBuilder builder = BeanDefinitionBuilder\n                    .genericBeanDefinition(STAT_ANNOTATION_PROCESSOR_BEAN_CLASS);\n            builder.getRawBeanDefinition().setSource(source);\n            registerComponent(parserContext, builder, STAT_ANNOTATION_PROCESSOR_BEAN_NAME);\n        }\n\n        if (!registry.containsBeanDefinition(STAT_ANNOTATION_ADVICE_BEAN_NAME)) {\n            BeanDefinitionBuilder builder = BeanDefinitionBuilder\n                    .genericBeanDefinition(STAT_ANNOTATION_ADVICE_BEAN_CLASS);\n            builder.getRawBeanDefinition().setSource(source);\n            registerComponent(parserContext, builder, STAT_ANNOTATION_ADVICE_BEAN_NAME);\n        }\n\n        parserContext.popAndRegisterContainingComponent();\n\n        return null;\n    }\n\n    private static void registerComponent(ParserContext parserContext, BeanDefinitionBuilder builder,\n                                          String beanName) {\n        builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);\n        parserContext.getRegistry().registerBeanDefinition(beanName, builder.getBeanDefinition());\n        BeanDefinitionHolder holder = new BeanDefinitionHolder(builder.getBeanDefinition(), beanName);\n        parserContext.registerComponent(new BeanComponentDefinition(holder));\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/support/spring/stat/config/DruidStatNamespaceHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.support.spring.stat.config;\n\nimport org.springframework.beans.factory.xml.NamespaceHandlerSupport;\n\npublic class DruidStatNamespaceHandler extends NamespaceHandlerSupport {\n    @Override\n    public void init() {\n        registerBeanDefinitionParser(\"annotation-driven\", new DruidStatBeanDefinitionParser());\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/Base64.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\n/**\n * Static methods for translating Base64 encoded strings to byte arrays and vice-versa.\n *\n * @author Josh Bloch\n * @version %I%, %G%\n * @since 1.4\n */\npublic class Base64 {\n    /**\n     * Translates the specified byte array into a Base64 string as per Preferences.put(byte[]).\n     */\n    public static String byteArrayToBase64(byte[] a) {\n        return byteArrayToBase64(a, false);\n    }\n\n    /**\n     * Translates the specified byte array into an \"alternate representation\" Base64 string. This non-standard variant\n     * uses an alphabet that does not contain the uppercase alphabetic characters, which makes it suitable for use in\n     * situations where case-folding occurs.\n     */\n    public static String byteArrayToAltBase64(byte[] a) {\n        return byteArrayToBase64(a, true);\n    }\n\n    private static String byteArrayToBase64(byte[] a, boolean alternate) {\n        int aLen = a.length;\n        int numFullGroups = aLen / 3;\n        int numBytesInPartialGroup = aLen - 3 * numFullGroups;\n        int resultLen = 4 * ((aLen + 2) / 3);\n        StringBuilder result = new StringBuilder(resultLen);\n        char[] intToAlpha = (alternate ? intToAltBase64 : intToBase64);\n\n        // Translate all full groups from byte array elements to Base64\n        int inCursor = 0;\n        for (int i = 0; i < numFullGroups; i++) {\n            int byte0 = a[inCursor++] & 0xff;\n            int byte1 = a[inCursor++] & 0xff;\n            int byte2 = a[inCursor++] & 0xff;\n            result.append(intToAlpha[byte0 >> 2]);\n            result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]);\n            result.append(intToAlpha[(byte1 << 2) & 0x3f | (byte2 >> 6)]);\n            result.append(intToAlpha[byte2 & 0x3f]);\n        }\n\n        // Translate partial group if present\n        if (numBytesInPartialGroup != 0) {\n            int byte0 = a[inCursor++] & 0xff;\n            result.append(intToAlpha[byte0 >> 2]);\n            if (numBytesInPartialGroup == 1) {\n                result.append(intToAlpha[(byte0 << 4) & 0x3f]);\n                result.append(\"==\");\n            } else {\n                // assert numBytesInPartialGroup == 2;\n                int byte1 = a[inCursor++] & 0xff;\n                result.append(intToAlpha[(byte0 << 4) & 0x3f | (byte1 >> 4)]);\n                result.append(intToAlpha[(byte1 << 2) & 0x3f]);\n                result.append('=');\n            }\n        }\n        // assert inCursor == a.length;\n        // assert result.length() == resultLen;\n        return result.toString();\n    }\n\n    /**\n     * This array is a lookup table that translates 6-bit positive integer index values into their \"Base64 Alphabet\"\n     * equivalents as specified in Table 1 of RFC 2045.\n     */\n    private static final char[] intToBase64 = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',\n            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',\n            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',\n            '3', '4', '5', '6', '7', '8', '9', '+', '/'};\n\n    /**\n     * This array is a lookup table that translates 6-bit positive integer index values into their\n     * \"Alternate Base64 Alphabet\" equivalents. This is NOT the real Base64 Alphabet as per in Table 1 of RFC 2045. This\n     * alternate alphabet does not use the capital letters. It is designed for use in environments where \"case folding\"\n     * occurs.\n     */\n    private static final char[] intToAltBase64 = {'!', '\"', '#', '$', '%', '&', '\\'', '(', ')', ',', '-', '.', ':',\n            ';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',\n            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',\n            '3', '4', '5', '6', '7', '8', '9', '+', '?'};\n\n    /**\n     * Translates the specified Base64 string (as per Preferences.get(byte[])) into a byte array.\n     */\n    public static byte[] base64ToByteArray(String s) {\n        return base64ToByteArray(s, false);\n    }\n\n    /**\n     * Translates the specified \"alternate representation\" Base64 string into a byte array.\n     */\n    public static byte[] altBase64ToByteArray(String s) {\n        return base64ToByteArray(s, true);\n    }\n\n    private static byte[] base64ToByteArray(String s, boolean alternate) {\n        byte[] alphaToInt = (alternate ? altBase64ToInt : base64ToInt);\n        int sLen = s.length();\n        int numGroups = sLen / 4;\n        if (4 * numGroups != sLen) {\n            throw new IllegalArgumentException(\"String length must be a multiple of four.\");\n        }\n        int missingBytesInLastGroup = 0;\n        int numFullGroups = numGroups;\n        if (sLen != 0) {\n            if (s.charAt(sLen - 1) == '=') {\n                missingBytesInLastGroup++;\n                numFullGroups--;\n            }\n            if (s.charAt(sLen - 2) == '=') {\n                missingBytesInLastGroup++;\n            }\n        }\n        byte[] result = new byte[3 * numGroups - missingBytesInLastGroup];\n\n        // Translate all full groups from base64 to byte array elements\n        int inCursor = 0, outCursor = 0;\n        for (int i = 0; i < numFullGroups; i++) {\n            int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);\n            int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);\n            int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);\n            int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);\n            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));\n            result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));\n            result[outCursor++] = (byte) ((ch2 << 6) | ch3);\n        }\n\n        // Translate partial group, if present\n        if (missingBytesInLastGroup != 0) {\n            int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);\n            int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);\n            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));\n\n            if (missingBytesInLastGroup == 1) {\n                int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);\n                result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));\n            }\n        }\n        // assert inCursor == s.length()-missingBytesInLastGroup;\n        // assert outCursor == result.length;\n        return result;\n    }\n\n    /**\n     * Translates the specified character, which is assumed to be in the \"Base 64 Alphabet\" into its equivalent 6-bit\n     * positive integer.\n     *\n     * @throw IllegalArgumentException or ArrayOutOfBoundsException if c is not in the Base64 Alphabet.\n     */\n    private static int base64toInt(char c, byte[] alphaToInt) {\n        int result = alphaToInt[c];\n        if (result < 0) {\n            throw new IllegalArgumentException(\"Illegal character \" + c);\n        }\n        return result;\n    }\n\n    /**\n     * This array is a lookup table that translates unicode characters drawn from the \"Base64 Alphabet\" (as specified in\n     * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64\n     * alphabet but fall within the bounds of the array are translated to -1.\n     */\n    private static final byte[] base64ToInt = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62,\n            -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7,\n            8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,\n            29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};\n\n    /**\n     * This array is the analogue of base64ToInt, but for the nonstandard variant that avoids the use of uppercase\n     * alphabetic characters.\n     */\n    private static final byte[] altBase64ToInt = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10,\n            11, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1, -1, -1,\n            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28,\n            29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 22, 23, 24, 25};\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/ConcurrentLruCache.java",
    "content": "package com.alibaba.druid.util;\n\nimport java.util.Objects;\nimport java.util.Queue;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.*;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.function.BiConsumer;\nimport java.util.function.Function;\n\n/**\n * Simple LRU (Least Recently Used) cache, bounded by a specified cache capacity.\n * This is a simplified, opinionated implementation of an LRU cache\n * It is inspired from\n * <a href=\"https://github.com/spring-projects/spring-framework/blob/main/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java\">ConcurrentLruCache</a>.\n */\n@SuppressWarnings(\"unchecked\")\npublic final class ConcurrentLruCache<K, V> {\n    private final int capacity;\n\n    private final AtomicInteger currentSize = new AtomicInteger();\n\n    private final ConcurrentMap<K, Node<K, V>> cache;\n\n    private final ReadOperations<K, V> readOperations;\n\n    private final WriteOperations writeOperations;\n\n    private final Lock evictionLock = new ReentrantLock();\n\n    /*\n     * Queue that contains all ACTIVE cache entries, ordered with least recently used entries first.\n     * Read and write operations are buffered and periodically processed to reorder the queue.\n     */\n    private final EvictionQueue<K, V> evictionQueue = new EvictionQueue<>();\n\n    private final AtomicReference<DrainStatus> drainStatus = new AtomicReference<>(DrainStatus.IDLE);\n\n    public ConcurrentLruCache(int capacity) {\n        if (capacity <= 0) {\n            throw new IllegalArgumentException(\"Capacity must be > 0\");\n        }\n        this.capacity = capacity;\n        this.cache = new ConcurrentHashMap<>(16, 0.75f, 16);\n        this.readOperations = new ReadOperations<>(this.evictionQueue);\n        this.writeOperations = new WriteOperations();\n    }\n\n    public V get(K key) {\n        final Node<K, V> node = this.cache.get(key);\n        if (node == null) {\n            return null;\n        }\n        processRead(node);\n        return node.getValue();\n    }\n\n    public V computeIfAbsent(K key, Function<K, V> generator) {\n        if (key == null) {\n            throw new IllegalArgumentException(\"key must not be null\");\n        }\n\n        final AtomicBoolean write = new AtomicBoolean(false);\n\n        Node<K, V> node =\n                cache.computeIfAbsent(key, k -> {\n                    V value = generator.apply(k);\n                    if (value == null) {\n                        throw new IllegalArgumentException(\"value must not be null\");\n                    }\n                    final CacheEntry<V> cacheEntry = new CacheEntry<>(value, CacheEntryState.ACTIVE);\n                    final Node<K, V> newNode = new Node<>(key, cacheEntry);\n                    write.set(true);\n                    return newNode;\n                });\n\n        if (write.get()) {\n            processWrite(new AddTask(node));\n        } else {\n            processRead(node);\n        }\n\n        return node.getValue();\n    }\n\n    public void forEach(BiConsumer<K, V> action) {\n        this.cache.forEach((k, kvNode) -> action.accept(k, kvNode.getValue()));\n    }\n\n    private void processRead(Node<K, V> node) {\n        boolean drainRequested = this.readOperations.recordRead(node);\n        final DrainStatus status = this.drainStatus.get();\n        if (status.shouldDrainBuffers(drainRequested)) {\n            drainOperations();\n        }\n    }\n\n    private void processWrite(Runnable task) {\n        this.writeOperations.add(task);\n        this.drainStatus.lazySet(DrainStatus.REQUIRED);\n        drainOperations();\n    }\n\n    private void drainOperations() {\n        if (this.evictionLock.tryLock()) {\n            try {\n                this.drainStatus.lazySet(DrainStatus.PROCESSING);\n                this.readOperations.drain();\n                this.writeOperations.drain();\n            } finally {\n                this.drainStatus.compareAndSet(DrainStatus.PROCESSING, DrainStatus.IDLE);\n                this.evictionLock.unlock();\n            }\n        }\n    }\n\n    public Set<K> keys() {\n        return cache.keySet();\n    }\n\n    public int size() {\n        return this.cache.size();\n    }\n\n    public void clear() {\n        this.evictionLock.lock();\n        try {\n            Node<K, V> node;\n            while ((node = this.evictionQueue.poll()) != null) {\n                this.cache.remove(node.key, node);\n                markAsRemoved(node);\n            }\n            this.readOperations.clear();\n            this.writeOperations.drainAll();\n        } finally {\n            this.evictionLock.unlock();\n        }\n    }\n\n    /*\n     * Transition the node to the {@code removed} state and decrement the current size of the cache.\n     */\n    private void markAsRemoved(Node<K, V> node) {\n        for (; ; ) {\n            CacheEntry<V> current = node.get();\n            CacheEntry<V> removed = new CacheEntry<>(current.value, CacheEntryState.REMOVED);\n            if (node.compareAndSet(current, removed)) {\n                this.currentSize.lazySet(this.currentSize.get() - 1);\n                return;\n            }\n        }\n    }\n\n    /**\n     * Determine whether the given key is present in this cache.\n     *\n     * @param key the key to check for\n     * @return {@code true} if the key is present, {@code false} if there was no matching key\n     */\n    public boolean contains(K key) {\n        return this.cache.containsKey(key);\n    }\n\n    /**\n     * Immediately remove the given key and any associated value.\n     *\n     * @param key the key to evict the entry for\n     * @return {@code true} if the key was present before,\n     * {@code false} if there was no matching key\n     */\n    public boolean remove(K key) {\n        final Node<K, V> node = this.cache.remove(key);\n        if (node == null) {\n            return false;\n        }\n        markForRemoval(node);\n        processWrite(new RemovalTask(node));\n        return true;\n    }\n\n    /*\n     * Transition the node from the {@code active} state to the {@code pending removal} state,\n     * if the transition is valid.\n     */\n    private void markForRemoval(Node<K, V> node) {\n        for (; ; ) {\n            final CacheEntry<V> current = node.get();\n            if (!current.isActive()) {\n                return;\n            }\n            final CacheEntry<V> pendingRemoval = new CacheEntry<>(current.value, CacheEntryState.PENDING_REMOVAL);\n            if (node.compareAndSet(current, pendingRemoval)) {\n                return;\n            }\n        }\n    }\n\n    /**\n     * Write operation recorded when a new entry is added to the cache.\n     */\n    private final class AddTask implements Runnable {\n        final Node<K, V> node;\n\n        AddTask(Node<K, V> node) {\n            this.node = node;\n        }\n\n        @Override\n        public void run() {\n            currentSize.lazySet(currentSize.get() + 1);\n            if (this.node.get().isActive()) {\n                evictionQueue.add(this.node);\n                evictEntries();\n            }\n        }\n\n        private void evictEntries() {\n            while (currentSize.get() > capacity) {\n                final Node<K, V> node = evictionQueue.poll();\n                if (node == null) {\n                    return;\n                }\n                cache.remove(node.key, node);\n                markAsRemoved(node);\n            }\n        }\n    }\n\n    /**\n     * Write operation recorded when an entry is removed to the cache.\n     */\n    private final class RemovalTask implements Runnable {\n        final Node<K, V> node;\n\n        RemovalTask(Node<K, V> node) {\n            this.node = node;\n        }\n\n        @Override\n        public void run() {\n            evictionQueue.remove(this.node);\n            markAsRemoved(this.node);\n        }\n    }\n\n    /*\n     * Draining status for the read/write buffers.\n     */\n    private enum DrainStatus {\n        /*\n         * No drain operation currently running.\n         */\n        IDLE {\n            @Override\n            boolean shouldDrainBuffers(boolean delayable) {\n                return !delayable;\n            }\n        },\n\n        /*\n         * A drain operation is required due to a pending write modification.\n         */\n        REQUIRED {\n            @Override\n            boolean shouldDrainBuffers(boolean delayable) {\n                return true;\n            }\n        },\n\n        /*\n         * A drain operation is in progress.\n         */\n        PROCESSING {\n            @Override\n            boolean shouldDrainBuffers(boolean delayable) {\n                return false;\n            }\n        };\n\n        /**\n         * Determine whether the buffers should be drained.\n         *\n         * @param delayable if a drain should be delayed until required\n         * @return if a drain should be attempted\n         */\n        abstract boolean shouldDrainBuffers(boolean delayable);\n    }\n\n    private enum CacheEntryState {\n        ACTIVE, PENDING_REMOVAL, REMOVED\n    }\n\n    private static class CacheEntry<V> {\n        private final V value;\n        private final CacheEntryState state;\n\n        public CacheEntry(V value, CacheEntryState state) {\n            this.value = value;\n            this.state = state;\n        }\n\n        boolean isActive() {\n            return this.state == CacheEntryState.ACTIVE;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            CacheEntry<?> that = (CacheEntry<?>) o;\n            return Objects.equals(value, that.value) && state == that.state;\n        }\n\n        @Override\n        public int hashCode() {\n            return Objects.hash(value, state);\n        }\n\n        @Override\n        public String toString() {\n            return \"CacheEntry{\" +\n                    \"value=\" + value +\n                    \", state=\" + state +\n                    '}';\n        }\n    }\n\n    private static final class ReadOperations<K, V> {\n        private static final int BUFFER_COUNT = detectNumberOfBuffers();\n\n        private static int detectNumberOfBuffers() {\n            int availableProcessors = Runtime.getRuntime().availableProcessors();\n            int nextPowerOfTwo = 1 << (Integer.SIZE - Integer.numberOfLeadingZeros(availableProcessors - 1));\n            return Math.min(4, nextPowerOfTwo);\n        }\n\n        private static final int BUFFERS_MASK = BUFFER_COUNT - 1;\n\n        private static final int MAX_PENDING_OPERATIONS = 32;\n\n        private static final int MAX_DRAIN_COUNT = 2 * MAX_PENDING_OPERATIONS;\n\n        private static final int BUFFER_SIZE = 2 * MAX_DRAIN_COUNT;\n\n        private static final int BUFFER_INDEX_MASK = BUFFER_SIZE - 1;\n\n        /*\n         * Number of operations recorded, for each buffer\n         */\n        private final AtomicLongArray recordedCount = new AtomicLongArray(BUFFER_COUNT);\n\n        /*\n         * Number of operations read, for each buffer\n         */\n        private final long[] readCount = new long[BUFFER_COUNT];\n\n        /*\n         * Number of operations processed, for each buffer\n         */\n        private final AtomicLongArray processedCount = new AtomicLongArray(BUFFER_COUNT);\n\n        private final AtomicReferenceArray<Node<K, V>>[] buffers = new AtomicReferenceArray[BUFFER_COUNT];\n\n        private final EvictionQueue<K, V> evictionQueue;\n\n        ReadOperations(EvictionQueue<K, V> evictionQueue) {\n            this.evictionQueue = evictionQueue;\n            for (int i = 0; i < BUFFER_COUNT; i++) {\n                this.buffers[i] = new AtomicReferenceArray<>(BUFFER_SIZE);\n            }\n        }\n\n        private static int getBufferIndex() {\n            return ((int) Thread.currentThread().getId()) & BUFFERS_MASK;\n        }\n\n        boolean recordRead(Node<K, V> node) {\n            int bufferIndex = getBufferIndex();\n            final long writeCount = this.recordedCount.get(bufferIndex);\n            this.recordedCount.lazySet(bufferIndex, writeCount + 1);\n            final int index = (int) (writeCount & BUFFER_INDEX_MASK);\n            this.buffers[bufferIndex].lazySet(index, node);\n            final long pending = (writeCount - this.processedCount.get(bufferIndex));\n            return (pending < MAX_PENDING_OPERATIONS);\n        }\n\n        void drain() {\n            final int start = (int) Thread.currentThread().getId();\n            final int end = start + BUFFER_COUNT;\n            for (int i = start; i < end; i++) {\n                drainReadBuffer(i & BUFFERS_MASK);\n            }\n        }\n\n        void clear() {\n            for (int i = 0; i < BUFFER_COUNT; i++) {\n                AtomicReferenceArray<Node<K, V>> buffer = this.buffers[i];\n                for (int j = 0; j < BUFFER_SIZE; j++) {\n                    buffer.lazySet(j, null);\n                }\n            }\n        }\n\n        private void drainReadBuffer(int bufferIndex) {\n            final long writeCount = this.recordedCount.get(bufferIndex);\n            for (int i = 0; i < MAX_DRAIN_COUNT; i++) {\n                final int index = (int) (this.readCount[bufferIndex] & BUFFER_INDEX_MASK);\n                final AtomicReferenceArray<Node<K, V>> buffer = this.buffers[bufferIndex];\n                final Node<K, V> node = buffer.get(index);\n                if (node == null) {\n                    break;\n                }\n                buffer.lazySet(index, null);\n                this.evictionQueue.moveToBack(node);\n                this.readCount[bufferIndex]++;\n            }\n            this.processedCount.lazySet(bufferIndex, writeCount);\n        }\n    }\n\n    private static final class WriteOperations {\n        private static final int DRAIN_THRESHOLD = 16;\n\n        private final Queue<Runnable> operations = new ConcurrentLinkedQueue<>();\n\n        public void add(Runnable task) {\n            this.operations.add(task);\n        }\n\n        public void drain() {\n            for (int i = 0; i < DRAIN_THRESHOLD; i++) {\n                final Runnable task = this.operations.poll();\n                if (task == null) {\n                    break;\n                }\n                task.run();\n            }\n        }\n\n        public void drainAll() {\n            Runnable task;\n            while ((task = this.operations.poll()) != null) {\n                task.run();\n            }\n        }\n    }\n\n    private static final class Node<K, V> extends AtomicReference<CacheEntry<V>> {\n        private static final long serialVersionUID = 6034596142966329577L;\n\n        final K key;\n        Node<K, V> prev;\n        Node<K, V> next;\n\n        Node(K key, CacheEntry<V> cacheEntry) {\n            super(cacheEntry);\n            this.key = key;\n        }\n\n        public Node<K, V> getPrevious() {\n            return this.prev;\n        }\n\n        public void setPrevious(Node<K, V> prev) {\n            this.prev = prev;\n        }\n\n        public Node<K, V> getNext() {\n            return this.next;\n        }\n\n        public void setNext(Node<K, V> next) {\n            this.next = next;\n        }\n\n        V getValue() {\n            return get().value;\n        }\n    }\n\n    private static final class EvictionQueue<K, V> {\n        Node<K, V> first;\n        Node<K, V> last;\n\n        Node<K, V> poll() {\n            if (this.first == null) {\n                return null;\n            }\n            final Node<K, V> f = this.first;\n            final Node<K, V> next = f.getNext();\n            f.setNext(null);\n\n            this.first = next;\n            if (next == null) {\n                this.last = null;\n            } else {\n                next.setPrevious(null);\n            }\n            return f;\n        }\n\n        void add(Node<K, V> e) {\n            if (contains(e)) {\n                return;\n            }\n            linkLast(e);\n        }\n\n        private boolean contains(Node<K, V> e) {\n            return (e.getPrevious() != null)\n                    || (e.getNext() != null)\n                    || (e == this.first);\n        }\n\n        private void linkLast(final Node<K, V> e) {\n            final Node<K, V> l = this.last;\n            this.last = e;\n\n            if (l == null) {\n                this.first = e;\n            } else {\n                l.setNext(e);\n                e.setPrevious(l);\n            }\n        }\n\n        private void unlink(Node<K, V> e) {\n            final Node<K, V> prev = e.getPrevious();\n            final Node<K, V> next = e.getNext();\n            if (prev == null) {\n                this.first = next;\n            } else {\n                prev.setNext(next);\n                e.setPrevious(null);\n            }\n            if (next == null) {\n                this.last = prev;\n            } else {\n                next.setPrevious(prev);\n                e.setNext(null);\n            }\n        }\n\n        void moveToBack(Node<K, V> e) {\n            if (contains(e) && e != this.last) {\n                unlink(e);\n                linkLast(e);\n            }\n        }\n\n        void remove(Node<K, V> e) {\n            if (contains(e)) {\n                unlink(e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/DaemonThreadFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * @author sandzhang [sandzhangtoo@gmail.com]\n */\npublic class DaemonThreadFactory implements ThreadFactory {\n    private AtomicInteger threadNo = new AtomicInteger(1);\n    private final String nameStart;\n    private final String nameEnd = \"]\";\n\n    public DaemonThreadFactory(String poolName) {\n        nameStart = \"[\" + poolName + \"-\";\n    }\n\n    public Thread newThread(Runnable r) {\n        String threadName = nameStart + threadNo.getAndIncrement() + nameEnd;\n        Thread newThread = new Thread(r, threadName);\n        newThread.setDaemon(true);\n        if (newThread.getPriority() != Thread.NORM_PRIORITY) {\n            newThread.setPriority(Thread.NORM_PRIORITY);\n        }\n        return newThread;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/DruidDataSourceUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport com.alibaba.druid.Constants;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.management.ObjectName;\n\nimport java.lang.reflect.Method;\nimport java.sql.SQLException;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.StringTokenizer;\n\nimport static com.alibaba.druid.util.Utils.trySetBooleanProperty;\nimport static com.alibaba.druid.util.Utils.trySetIntProperty;\nimport static com.alibaba.druid.util.Utils.trySetLongProperty;\nimport static com.alibaba.druid.util.Utils.trySetStringProperty;\n\npublic class DruidDataSourceUtils {\n    private static final Log LOG = LogFactory.getLog(DruidDataSourceUtils.class);\n\n    public static String getUrl(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getUrl();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getUrl\");\n            Object obj = method.invoke(druidDataSource);\n            return (String) obj;\n        } catch (Exception e) {\n            LOG.error(\"getUrl error\", e);\n            return null;\n        }\n    }\n\n    public static long getID(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getID();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getID\");\n            Object obj = method.invoke(druidDataSource);\n            return (Long) obj;\n        } catch (Exception e) {\n            LOG.error(\"getID error\", e);\n            return -1;\n        }\n    }\n\n    public static String getName(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getName();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getName\");\n            Object obj = method.invoke(druidDataSource);\n            return (String) obj;\n        } catch (Exception e) {\n            LOG.error(\"getUrl error\", e);\n            return null;\n        }\n    }\n\n    public static ObjectName getObjectName(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getObjectName();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getObjectName\");\n            Object obj = method.invoke(druidDataSource);\n            return (ObjectName) obj;\n        } catch (Exception e) {\n            LOG.error(\"getObjectName error\", e);\n            return null;\n        }\n    }\n\n    public static Object getSqlStat(Object druidDataSource, int sqlId) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getSqlStat(sqlId);\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getSqlStat\", int.class);\n            return method.invoke(druidDataSource, sqlId);\n        } catch (Exception e) {\n            LOG.error(\"getSqlStat error\", e);\n            return null;\n        }\n    }\n\n    public static boolean isRemoveAbandoned(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).isRemoveAbandoned();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"isRemoveAbandoned\");\n            Object obj = method.invoke(druidDataSource);\n            return (Boolean) obj;\n        } catch (Exception e) {\n            LOG.error(\"isRemoveAbandoned error\", e);\n            return false;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<String, Object> getStatDataForMBean(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getStatDataForMBean();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getStatDataForMBean\");\n            Object obj = method.invoke(druidDataSource);\n            return (Map<String, Object>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getStatDataForMBean error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<String, Object> getStatData(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getStatData();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getStatData\");\n            Object obj = method.invoke(druidDataSource);\n            return (Map<String, Object>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getStatData error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"rawtypes\")\n    public static Map getSqlStatMap(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getSqlStatMap();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getSqlStatMap\");\n            Object obj = method.invoke(druidDataSource);\n            return (Map) obj;\n        } catch (Exception e) {\n            LOG.error(\"getSqlStatMap error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings({\"rawtypes\", \"unchecked\"})\n    public static Map<String, Object> getWallStatMap(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getWallStatMap();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getWallStatMap\");\n            Object obj = method.invoke(druidDataSource);\n            return (Map) obj;\n        } catch (Exception e) {\n            LOG.error(\"getWallStatMap error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static List<Map<String, Object>> getPoolingConnectionInfo(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getPoolingConnectionInfo();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getPoolingConnectionInfo\");\n            Object obj = method.invoke(druidDataSource);\n            return (List<Map<String, Object>>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getPoolingConnectionInfo error\", e);\n            return null;\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static List<String> getActiveConnectionStackTrace(Object druidDataSource) {\n        if (druidDataSource.getClass() == DruidDataSource.class) {\n            return ((DruidDataSource) druidDataSource).getActiveConnectionStackTrace();\n        }\n\n        try {\n            Method method = druidDataSource.getClass().getMethod(\"getActiveConnectionStackTrace\");\n            Object obj = method.invoke(druidDataSource);\n            return (List<String>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getActiveConnectionStackTrace error\", e);\n            return null;\n        }\n    }\n\n    public static Integer getPropertyInt(Properties properties, String key) {\n        String value = properties.getProperty(key);\n        if (value != null) {\n            try {\n                return Integer.parseInt(value);\n            } catch (NumberFormatException ignored) {\n                 // ignore\n            }\n        }\n        return null;\n    }\n\n    public static void configFromProperties(DruidDataSource druidDataSource, Properties properties) {\n        trySetStringProperty(properties, \"druid.name\", druidDataSource::setName);\n        trySetStringProperty(properties, \"druid.url\", druidDataSource::setUrl);\n        trySetStringProperty(properties, \"druid.username\", druidDataSource::setUsername);\n        trySetStringProperty(properties, \"druid.password\", druidDataSource::setPassword);\n        trySetBooleanProperty(properties, \"druid.testWhileIdle\", druidDataSource::setTestWhileIdle);\n        trySetBooleanProperty(properties, \"druid.testOnBorrow\", druidDataSource::setTestOnBorrow);\n        {\n            String property = properties.getProperty(\"druid.validationQuery\");\n            if (property != null && property.length() > 0) {\n                druidDataSource.setValidationQuery(property);\n            }\n        }\n        trySetBooleanProperty(properties, \"druid.useGlobalDataSourceStat\", druidDataSource::setUseGlobalDataSourceStat);\n        trySetBooleanProperty(properties, \"druid.useGloalDataSourceStat\", druidDataSource::setUseGlobalDataSourceStat);\n        trySetBooleanProperty(properties, \"druid.asyncInit\", druidDataSource::setAsyncInit);\n        {\n            String property = properties.getProperty(\"druid.filters\");\n\n            if (property != null && property.length() > 0) {\n                try {\n                    druidDataSource.setFilters(property);\n                } catch (SQLException e) {\n                    LOG.error(\"setFilters error\", e);\n                }\n            }\n        }\n        trySetLongProperty(properties, Constants.DRUID_TIME_BETWEEN_LOG_STATS_MILLIS, druidDataSource::setTimeBetweenLogStatsMillis);\n        {\n            String property = properties.getProperty(Constants.DRUID_STAT_SQL_MAX_SIZE);\n            if (property != null && property.length() > 0) {\n                try {\n                    int value = Integer.parseInt(property);\n                    if (druidDataSource.getDataSourceStat() != null) {\n                        druidDataSource.getDataSourceStat().setMaxSqlSize(value);\n                    }\n                } catch (NumberFormatException e) {\n                    LOG.error(\"illegal property '\" + Constants.DRUID_STAT_SQL_MAX_SIZE + \"'\", e);\n                }\n            }\n        }\n        trySetBooleanProperty(properties, \"druid.clearFiltersEnable\", druidDataSource::setClearFiltersEnable);\n        trySetBooleanProperty(properties, \"druid.resetStatEnable\", druidDataSource::setResetStatEnable);\n        trySetIntProperty(properties, \"druid.notFullTimeoutRetryCount\", druidDataSource::setNotFullTimeoutRetryCount);\n        trySetLongProperty(properties, \"druid.timeBetweenEvictionRunsMillis\", druidDataSource::setTimeBetweenEvictionRunsMillis);\n        trySetIntProperty(properties, \"druid.maxWaitThreadCount\", druidDataSource::setMaxWaitThreadCount);\n        trySetIntProperty(properties, \"druid.maxWait\", druidDataSource::setMaxWait);\n        trySetBooleanProperty(properties, \"druid.failFast\", druidDataSource::setFailFast);\n        trySetLongProperty(properties, \"druid.phyTimeoutMillis\", druidDataSource::setPhyTimeoutMillis);\n        trySetLongProperty(properties, \"druid.phyMaxUseCount\", druidDataSource::setPhyMaxUseCount);\n        trySetLongProperty(properties, \"druid.minEvictableIdleTimeMillis\", druidDataSource::setMinEvictableIdleTimeMillis);\n        trySetLongProperty(properties, \"druid.maxEvictableIdleTimeMillis\", druidDataSource::setMaxEvictableIdleTimeMillis);\n        trySetBooleanProperty(properties, \"druid.keepAlive\", druidDataSource::setKeepAlive);\n        trySetLongProperty(properties, \"druid.keepAliveBetweenTimeMillis\", druidDataSource::setKeepAliveBetweenTimeMillis);\n        trySetBooleanProperty(properties, \"druid.poolPreparedStatements\", druidDataSource::setPoolPreparedStatements);\n        trySetBooleanProperty(properties, \"druid.initVariants\", druidDataSource::setInitVariants);\n        trySetBooleanProperty(properties, \"druid.initGlobalVariants\", druidDataSource::setInitGlobalVariants);\n        trySetBooleanProperty(properties, \"druid.useUnfairLock\", druidDataSource::setUseUnfairLock);\n        trySetStringProperty(properties, \"druid.driverClassName\", druidDataSource::setDriverClassName);\n        trySetIntProperty(properties, \"druid.initialSize\", druidDataSource::setInitialSize);\n        trySetIntProperty(properties, \"druid.minIdle\", druidDataSource::setMinIdle);\n        trySetIntProperty(properties, \"druid.maxActive\", druidDataSource::setMaxActive);\n        trySetBooleanProperty(properties, \"druid.killWhenSocketReadTimeout\", druidDataSource::setKillWhenSocketReadTimeout);\n        trySetStringProperty(properties, \"druid.connectProperties\", druidDataSource::setConnectionProperties);\n        trySetIntProperty(properties, \"druid.maxPoolPreparedStatementPerConnectionSize\",\n            druidDataSource::setMaxPoolPreparedStatementPerConnectionSize);\n        {\n            String property = properties.getProperty(\"druid.initConnectionSqls\");\n            if (property != null && property.length() > 0) {\n                try {\n                    StringTokenizer tokenizer = new StringTokenizer(property, \";\");\n                    druidDataSource.setConnectionInitSqls(Collections.list(tokenizer));\n                } catch (NumberFormatException e) {\n                    LOG.error(\"illegal property 'druid.initConnectionSqls'\", e);\n                }\n            }\n        }\n        {\n            String property = System.getProperty(\"druid.load.spifilter.skip\");\n            if (property != null && !\"false\".equals(property)) {\n                druidDataSource.setLoadSpifilterSkip(true);\n            }\n        }\n        {\n            String property = System.getProperty(\"druid.checkExecuteTime\");\n            if (property != null && !\"false\".equals(property)) {\n                druidDataSource.setCheckExecuteTime(true);\n            }\n        }\n        // new added\n        trySetIntProperty(properties, \"druid.connectionErrorRetryAttempts\", druidDataSource::setConnectionErrorRetryAttempts);\n        trySetLongProperty(properties, \"druid.timeBetweenConnectErrorMillis\", druidDataSource::setTimeBetweenConnectErrorMillis);\n        trySetBooleanProperty(properties, \"druid.breakAfterAcquireFailure\", druidDataSource::setBreakAfterAcquireFailure);\n        trySetBooleanProperty(properties, \"druid.testOnReturn\", druidDataSource::setTestOnReturn);\n        trySetBooleanProperty(properties, \"druid.removeAbandoned\", druidDataSource::setRemoveAbandoned);\n        trySetBooleanProperty(properties, \"druid.logAbandoned\", druidDataSource::setLogAbandoned);\n        trySetLongProperty(properties, \"druid.removeAbandonedTimeoutMillis\", druidDataSource::setRemoveAbandonedTimeoutMillis);\n        trySetIntProperty(properties, \"druid.validationQueryTimeout\", druidDataSource::setValidationQueryTimeout);\n        trySetIntProperty(properties, \"druid.queryTimeout\", druidDataSource::setQueryTimeout);\n        trySetIntProperty(properties, \"druid.connectTimeout\", druidDataSource::setConnectTimeout);\n        trySetIntProperty(properties, \"druid.socketTimeout\", druidDataSource::setSocketTimeout);\n        trySetIntProperty(properties, \"druid.transactionQueryTimeout\", druidDataSource::setTransactionQueryTimeout);\n        trySetIntProperty(properties, \"druid.loginTimeout\", druidDataSource::setLoginTimeout);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/DruidPasswordCallback.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport javax.security.auth.callback.PasswordCallback;\n\nimport java.util.Properties;\n\npublic class DruidPasswordCallback extends PasswordCallback {\n    private static final long serialVersionUID = 1L;\n\n    private String url;\n\n    private Properties properties;\n\n    public DruidPasswordCallback() {\n        this(\"druidDataSource password\", false);\n    }\n\n    public DruidPasswordCallback(String prompt, boolean echoOn) {\n        super(prompt, echoOn);\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public Properties getProperties() {\n        return properties;\n    }\n\n    public void setProperties(Properties properties) {\n        this.properties = properties;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/DruidWebUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport javax.servlet.GenericServlet;\nimport javax.servlet.ServletContext;\nimport javax.servlet.http.HttpServletRequest;\n\npublic class DruidWebUtils {\n    public static String getRemoteAddr(HttpServletRequest request) {\n        String ip = request.getHeader(\"x-forwarded-for\");\n        if (ip != null && ip.contains(\",\")) { //截取逗号前第一个ip视为源头ip\n            ip = ip.substring(0, ip.indexOf(\",\")).trim();\n        }\n        if (ip != null && !isValidAddress(ip)) {\n            ip = null;\n        }\n\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"Proxy-Client-IP\");\n            if (ip != null && !isValidAddress(ip)) {\n                ip = null;\n            }\n        }\n\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"WL-Proxy-Client-IP\");\n            if (ip != null && !isValidAddress(ip)) {\n                ip = null;\n            }\n        }\n\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getRemoteAddr();\n            if (ip != null && !isValidAddress(ip)) {\n                ip = null;\n            }\n        }\n\n        return ip;\n    }\n\n    public static String getRemoteAddr(jakarta.servlet.http.HttpServletRequest request) {\n        String ip = request.getHeader(\"x-forwarded-for\");\n        if (ip != null && ip.contains(\",\")) { //截取逗号前第一个ip视为源头ip\n            ip = ip.substring(0, ip.indexOf(\",\")).trim();\n        }\n        if (ip != null && !isValidAddress(ip)) {\n            ip = null;\n        }\n\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"Proxy-Client-IP\");\n            if (ip != null && !isValidAddress(ip)) {\n                ip = null;\n            }\n        }\n\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"WL-Proxy-Client-IP\");\n            if (ip != null && !isValidAddress(ip)) {\n                ip = null;\n            }\n        }\n\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getRemoteAddr();\n            if (ip != null && !isValidAddress(ip)) {\n                ip = null;\n            }\n        }\n\n        return ip;\n    }\n\n    private static boolean isValidAddress(String ip) {\n        if (ip == null) {\n            return false;\n        }\n\n        for (int i = 0; i < ip.length(); ++i) {\n            char ch = ip.charAt(i);\n            if (ch >= '0' && ch <= '9') {\n                // ignored\n            } else if (ch >= 'A' && ch <= 'F') {\n                // ignored\n            } else if (ch >= 'a' && ch <= 'f') {\n                // ignored\n            } else if (ch == '.' || ch == ':') {\n                //\n            } else {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    private static String getContextPath_2_5(ServletContext context) {\n        String contextPath = context.getContextPath();\n\n        if (contextPath == null || contextPath.length() == 0) {\n            contextPath = \"/\";\n        }\n\n        return contextPath;\n    }\n\n    private static String getContextPath_2_5(jakarta.servlet.ServletContext context) {\n        String contextPath = context.getContextPath();\n\n        if (contextPath == null || contextPath.length() == 0) {\n            contextPath = \"/\";\n        }\n\n        return contextPath;\n    }\n\n    public static String getContextPath(ServletContext context) {\n        if (context.getMajorVersion() == 2 && context.getMinorVersion() < 5) {\n            return null;\n        }\n\n        try {\n            return getContextPath_2_5(context);\n        } catch (NoSuchMethodError error) {\n            return null;\n        }\n    }\n\n    public static String getContextPath(jakarta.servlet.ServletContext context) {\n        if (context.getMajorVersion() == 2 && context.getMinorVersion() < 5) {\n            return null;\n        }\n\n        try {\n            return getContextPath_2_5(context);\n        } catch (NoSuchMethodError error) {\n            return null;\n        }\n    }\n\n    public static Boolean getBoolean(GenericServlet servlet, String key) {\n        String property = servlet.getInitParameter(key);\n        if (\"true\".equals(property)) {\n            return Boolean.TRUE;\n        } else if (\"false\".equals(property)) {\n            return Boolean.FALSE;\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/FnvHash.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.util.Arrays;\n\npublic final class FnvHash {\n    public static final long BASIC = 0xcbf29ce484222325L;\n    public static final long PRIME = 0x100000001b3L;\n\n    public static long fnv1a_64(String input) {\n        if (input == null) {\n            return 0;\n        }\n\n        long hash = BASIC;\n        for (int i = 0; i < input.length(); ++i) {\n            char c = input.charAt(i);\n            hash ^= c;\n            hash *= PRIME;\n        }\n\n        return hash;\n    }\n\n    public static long fnv1a_64(StringBuilder input) {\n        if (input == null) {\n            return 0;\n        }\n\n        long hash = BASIC;\n        for (int i = 0; i < input.length(); ++i) {\n            char c = input.charAt(i);\n            hash ^= c;\n            hash *= PRIME;\n        }\n\n        return hash;\n    }\n\n    public static long fnv1a_64(String input, int offset, int end) {\n        if (input == null) {\n            return 0;\n        }\n\n        if (input.length() < end) {\n            end = input.length();\n        }\n\n        long hash = BASIC;\n        for (int i = offset; i < end; ++i) {\n            char c = input.charAt(i);\n            hash ^= c;\n            hash *= PRIME;\n        }\n\n        return hash;\n    }\n\n    public static long fnv1a_64(byte[] input, int offset, int end) {\n        if (input == null) {\n            return 0;\n        }\n\n        if (input.length < end) {\n            end = input.length;\n        }\n\n        long hash = BASIC;\n        for (int i = offset; i < end; ++i) {\n            byte c = input[i];\n            hash ^= c;\n            hash *= PRIME;\n        }\n\n        return hash;\n    }\n\n    public static long fnv1a_64(char[] chars) {\n        if (chars == null) {\n            return 0;\n        }\n        long hash = BASIC;\n        for (int i = 0; i < chars.length; ++i) {\n            char c = chars[i];\n            hash ^= c;\n            hash *= PRIME;\n        }\n\n        return hash;\n    }\n\n    /**\n     * lower and normalized and fnv_1a_64\n     *\n     * @param name the string to calculate the hash code for\n     * @return the 64-bit hash code of the string\n     */\n    public static long hashCode64(String name) {\n        if (name == null) {\n            return 0;\n        }\n\n        boolean quote = false;\n\n        int len = name.length();\n        if (len > 2) {\n            char c0 = name.charAt(0);\n            char c1 = name.charAt(len - 1);\n            if ((c0 == '`' && c1 == '`')\n                    || (c0 == '\"' && c1 == '\"')\n                    || (c0 == '\\'' && c1 == '\\'')\n                    || (c0 == '[' && c1 == ']')) {\n                quote = true;\n            }\n        }\n        if (quote) {\n            return FnvHash.hashCode64(name, 1, len - 1);\n        } else {\n            return FnvHash.hashCode64(name, 0, len);\n        }\n    }\n\n    public static long fnv1a_64_lower(String key) {\n        long hashCode = BASIC;\n        for (int i = 0; i < key.length(); ++i) {\n            char ch = key.charAt(i);\n\n            if (ch >= 'A' && ch <= 'Z') {\n                ch = (char) (ch + 32);\n            }\n\n            hashCode ^= ch;\n            hashCode *= PRIME;\n        }\n\n        return hashCode;\n    }\n\n    public static long fnv1a_64_lower(StringBuilder key) {\n        long hashCode = BASIC;\n        for (int i = 0; i < key.length(); ++i) {\n            char ch = key.charAt(i);\n\n            if (ch >= 'A' && ch <= 'Z') {\n                ch = (char) (ch + 32);\n            }\n\n            hashCode ^= ch;\n            hashCode *= PRIME;\n        }\n\n        return hashCode;\n    }\n\n    public static long fnv1a_64_lower(long basic, StringBuilder key) {\n        long hashCode = basic;\n        for (int i = 0; i < key.length(); ++i) {\n            char ch = key.charAt(i);\n\n            if (ch >= 'A' && ch <= 'Z') {\n                ch = (char) (ch + 32);\n            }\n\n            hashCode ^= ch;\n            hashCode *= PRIME;\n        }\n\n        return hashCode;\n    }\n\n    public static long hashCode64(String key, int offset, int end) {\n        long hashCode = BASIC;\n        for (int i = offset; i < end; ++i) {\n            char ch = key.charAt(i);\n\n            if (ch >= 'A' && ch <= 'Z') {\n                ch = (char) (ch + 32);\n            }\n\n            hashCode ^= ch;\n            hashCode *= PRIME;\n        }\n\n        return hashCode;\n    }\n\n    public static long hashCode64(long basic, String name) {\n        if (name == null) {\n            return basic;\n        }\n\n        boolean quote = false;\n\n        int len = name.length();\n        if (len > 2) {\n            char c0 = name.charAt(0);\n            char c1 = name.charAt(len - 1);\n            if ((c0 == '`' && c1 == '`')\n                    || (c0 == '\"' && c1 == '\"')\n                    || (c0 == '\\'' && c1 == '\\'')\n                    || (c0 == '[' && c1 == ']')) {\n                quote = true;\n            }\n        }\n        if (quote) {\n            int offset = 1;\n            int end = len - 1;\n            for (int i = end - 1; i >= 0; --i) {\n                char ch = name.charAt(i);\n                if (ch == ' ') {\n                    end--;\n                } else {\n                    break;\n                }\n            }\n            return FnvHash.hashCode64(basic, name, offset, end);\n        } else {\n            return FnvHash.hashCode64(basic, name, 0, len);\n        }\n    }\n\n    public static long hashCode64(long basic, String key, int offset, int end) {\n        long hashCode = basic;\n        for (int i = offset; i < end; ++i) {\n            char ch = key.charAt(i);\n\n            if (ch >= 'A' && ch <= 'Z') {\n                ch = (char) (ch + 32);\n            }\n\n            hashCode ^= ch;\n            hashCode *= PRIME;\n        }\n\n        return hashCode;\n    }\n\n    public static long fnv_32_lower(String key) {\n        long hashCode = 0x811c9dc5;\n        for (int i = 0; i < key.length(); ++i) {\n            char ch = key.charAt(i);\n            if (ch == '_' || ch == '-') {\n                continue;\n            }\n\n            if (ch >= 'A' && ch <= 'Z') {\n                ch = (char) (ch + 32);\n            }\n\n            hashCode ^= ch;\n            hashCode *= 0x01000193;\n        }\n\n        return hashCode;\n    }\n\n    public static long[] fnv1a_64_lower(String[] strings, boolean sort) {\n        long[] hashCodes = new long[strings.length];\n        for (int i = 0; i < strings.length; i++) {\n            hashCodes[i] = fnv1a_64_lower(strings[i]);\n        }\n        if (sort) {\n            Arrays.sort(hashCodes);\n        }\n        return hashCodes;\n    }\n\n    /**\n     * normalized and lower and fnv1a_64_hash\n     *\n     * @param owner the owner string to include in the hash code calculation (can be null)\n     * @param name  the name string to include in the hash code calculation (can be null)\n     * @return the 64-bit hash code calculated from the owner and name strings\n     */\n    public static long hashCode64(String owner, String name) {\n        long hashCode = BASIC;\n\n        if (owner != null) {\n            String item = owner;\n\n            boolean quote = false;\n\n            int len = item.length();\n            if (len > 2) {\n                char c0 = item.charAt(0);\n                char c1 = item.charAt(len - 1);\n                if ((c0 == '`' && c1 == '`')\n                        || (c0 == '\"' && c1 == '\"')\n                        || (c0 == '\\'' && c1 == '\\'')\n                        || (c0 == '[' && c1 == ']')) {\n                    quote = true;\n                }\n            }\n\n            int start = quote ? 1 : 0;\n            int end = quote ? len - 1 : len;\n            for (int j = start; j < end; ++j) {\n                char ch = item.charAt(j);\n\n                if (ch >= 'A' && ch <= 'Z') {\n                    ch = (char) (ch + 32);\n                }\n\n                hashCode ^= ch;\n                hashCode *= PRIME;\n            }\n\n            hashCode ^= '.';\n            hashCode *= PRIME;\n        }\n\n        if (name != null) {\n            String item = name;\n\n            boolean quote = false;\n\n            int len = item.length();\n            if (len > 2) {\n                char c0 = item.charAt(0);\n                char c1 = item.charAt(len - 1);\n                if ((c0 == '`' && c1 == '`')\n                        || (c0 == '\"' && c1 == '\"')\n                        || (c0 == '\\'' && c1 == '\\'')\n                        || (c0 == '[' && c1 == ']')) {\n                    quote = true;\n                }\n            }\n\n            int start = quote ? 1 : 0;\n            int end = quote ? len - 1 : len;\n            for (int j = start; j < end; ++j) {\n                char ch = item.charAt(j);\n\n                if (ch >= 'A' && ch <= 'Z') {\n                    ch = (char) (ch + 32);\n                }\n\n                hashCode ^= ch;\n                hashCode *= PRIME;\n            }\n        }\n\n        return hashCode;\n    }\n\n    public interface Constants {\n        long HIGH_PRIORITY = fnv1a_64_lower(\"HIGH_PRIORITY\");\n        long DISTINCTROW = fnv1a_64_lower(\"DISTINCTROW\");\n        long STRAIGHT = fnv1a_64_lower(\"STRAIGHT\");\n        long STRAIGHT_JOIN = fnv1a_64_lower(\"STRAIGHT_JOIN\");\n        long SQL_SMALL_RESULT = fnv1a_64_lower(\"SQL_SMALL_RESULT\");\n        long SQL_BIG_RESULT = fnv1a_64_lower(\"SQL_BIG_RESULT\");\n        long SQL_BUFFER_RESULT = fnv1a_64_lower(\"SQL_BUFFER_RESULT\");\n        long CACHE = fnv1a_64_lower(\"CACHE\");\n        long CACHED = fnv1a_64_lower(\"CACHED\");\n        long UNCACHED = fnv1a_64_lower(\"UNCACHED\");\n        long SQL_CACHE = fnv1a_64_lower(\"SQL_CACHE\");\n        long SQL_NO_CACHE = fnv1a_64_lower(\"SQL_NO_CACHE\");\n        long SQL_CALC_FOUND_ROWS = fnv1a_64_lower(\"SQL_CALC_FOUND_ROWS\");\n        long TOP = fnv1a_64_lower(\"TOP\");\n        long OUTFILE = fnv1a_64_lower(\"OUTFILE\");\n        long SETS = fnv1a_64_lower(\"SETS\");\n        long REGEXP = fnv1a_64_lower(\"REGEXP\");\n        long RLIKE = fnv1a_64_lower(\"RLIKE\");\n        long USING = fnv1a_64_lower(\"USING\");\n        long IGNORE = fnv1a_64_lower(\"IGNORE\");\n        long FORCE = fnv1a_64_lower(\"FORCE\");\n        long CROSS = fnv1a_64_lower(\"CROSS\");\n        long NATURAL = fnv1a_64_lower(\"NATURAL\");\n        long APPLY = fnv1a_64_lower(\"APPLY\");\n        long CONNECT = fnv1a_64_lower(\"CONNECT\");\n        long START = fnv1a_64_lower(\"START\");\n        long BTREE = fnv1a_64_lower(\"BTREE\");\n        long HASH = fnv1a_64_lower(\"HASH\");\n        long DUPLICATE = fnv1a_64_lower(\"DUPLICATE\");\n        long LIST = fnv1a_64_lower(\"LIST\");\n        long NO_WAIT = fnv1a_64_lower(\"NO_WAIT\");\n        long WAIT = fnv1a_64_lower(\"WAIT\");\n        long NOWAIT = fnv1a_64_lower(\"NOWAIT\");\n        long ERRORS = fnv1a_64_lower(\"ERRORS\");\n        long VALUE = fnv1a_64_lower(\"VALUE\");\n        long OBJECT = fnv1a_64_lower(\"OBJECT\");\n        long NEXT = fnv1a_64_lower(\"NEXT\");\n        long NEXTVAL = fnv1a_64_lower(\"NEXTVAL\");\n        long CURRVAL = fnv1a_64_lower(\"CURRVAL\");\n        long PREVVAL = fnv1a_64_lower(\"PREVVAL\");\n        long PREVIOUS = fnv1a_64_lower(\"PREVIOUS\");\n        long LOW_PRIORITY = fnv1a_64_lower(\"LOW_PRIORITY\");\n        long COMMIT_ON_SUCCESS = fnv1a_64_lower(\"COMMIT_ON_SUCCESS\");\n        long ROLLBACK_ON_FAIL = fnv1a_64_lower(\"ROLLBACK_ON_FAIL\");\n        long QUEUE_ON_PK = fnv1a_64_lower(\"QUEUE_ON_PK\");\n        long TARGET_AFFECT_ROW = fnv1a_64_lower(\"TARGET_AFFECT_ROW\");\n        long COLLATE = fnv1a_64_lower(\"COLLATE\");\n        long BOOLEAN = fnv1a_64_lower(\"BOOLEAN\");\n        long SMALLINT = fnv1a_64_lower(\"SMALLINT\");\n        long MEDIUMINT = fnv1a_64_lower(\"MEDIUMINT\");\n        long SHORT = fnv1a_64_lower(\"SHORT\");\n        long TINY = fnv1a_64_lower(\"TINY\");\n        long TINYINT = fnv1a_64_lower(\"TINYINT\");\n        long CHARSET = fnv1a_64_lower(\"CHARSET\");\n        long SEMI = fnv1a_64_lower(\"SEMI\");\n        long ANTI = fnv1a_64_lower(\"ANTI\");\n        long PRIOR = fnv1a_64_lower(\"PRIOR\");\n        long NOCYCLE = fnv1a_64_lower(\"NOCYCLE\");\n        long CYCLE = fnv1a_64_lower(\"CYCLE\");\n        long CONNECT_BY_ROOT = fnv1a_64_lower(\"CONNECT_BY_ROOT\");\n\n        long DATE = fnv1a_64_lower(\"DATE\");\n        long GSON = fnv1a_64_lower(\"GSON\");\n        long NEW = fnv1a_64_lower(\"NEW\");\n        long NEWDATE = fnv1a_64_lower(\"NEWDATE\");\n        long DATETIME = fnv1a_64_lower(\"DATETIME\");\n        long TIME = fnv1a_64_lower(\"TIME\");\n        long ZONE = fnv1a_64_lower(\"ZONE\");\n        long JSON = fnv1a_64_lower(\"JSON\");\n        long TIMESTAMP = fnv1a_64_lower(\"TIMESTAMP\");\n        long TIMESTAMPTZ = fnv1a_64_lower(\"TIMESTAMPTZ\");\n        long CLOB = fnv1a_64_lower(\"CLOB\");\n        long NCLOB = fnv1a_64_lower(\"NCLOB\");\n        long TINYBLOB = fnv1a_64_lower(\"TINYBLOB\");\n        long BLOB = fnv1a_64_lower(\"BLOB\");\n        long XMLTYPE = fnv1a_64_lower(\"XMLTYPE\");\n        long BFILE = fnv1a_64_lower(\"BFILE\");\n        long UROWID = fnv1a_64_lower(\"UROWID\");\n        long ROWID = fnv1a_64_lower(\"ROWID\");\n        long REF = fnv1a_64_lower(\"REF\");\n        long INTEGER = fnv1a_64_lower(\"INTEGER\");\n        long INT = fnv1a_64_lower(\"INT\");\n        long INT24 = fnv1a_64_lower(\"INT24\");\n        long BINARY_FLOAT = fnv1a_64_lower(\"BINARY_FLOAT\");\n        long BINARY_DOUBLE = fnv1a_64_lower(\"BINARY_DOUBLE\");\n        long FLOAT = fnv1a_64_lower(\"FLOAT\");\n        long REAL = fnv1a_64_lower(\"REAL\");\n        long NUMBER = fnv1a_64_lower(\"NUMBER\");\n        long NUMERIC = fnv1a_64_lower(\"NUMERIC\");\n        long DEC = fnv1a_64_lower(\"DEC\");\n        long DECIMAL = fnv1a_64_lower(\"DECIMAL\");\n\n        long CURRENT = fnv1a_64_lower(\"CURRENT\");\n        long COUNT = fnv1a_64_lower(\"COUNT\");\n        long ROW_NUMBER = fnv1a_64_lower(\"ROW_NUMBER\");\n        long FIRST_VALUE = fnv1a_64_lower(\"FIRST_VALUE\");\n        long LAST_VALUE = fnv1a_64_lower(\"LAST_VALUE\");\n        long WM_CONCAT = fnv1a_64_lower(\"WM_CONCAT\");\n        long AVG = fnv1a_64_lower(\"AVG\");\n        long MAX = fnv1a_64_lower(\"MAX\");\n        long MIN = fnv1a_64_lower(\"MIN\");\n        long STDDEV = fnv1a_64_lower(\"STDDEV\");\n        long RANK = fnv1a_64_lower(\"RANK\");\n        long SUM = fnv1a_64_lower(\"SUM\");\n        long ARBITRARY = fnv1a_64_lower(\"ARBITRARY\");\n        long GROUP_CONCAT = fnv1a_64_lower(\"GROUP_CONCAT\");\n        long CONVERT_TZ = fnv1a_64_lower(\"CONVERT_TZ\");\n        long DEDUPLICATION = fnv1a_64_lower(\"DEDUPLICATION\");\n        long CONVERT = fnv1a_64_lower(\"CONVERT\");\n        long CHAR = fnv1a_64_lower(\"CHAR\");\n        long ENUM = fnv1a_64_lower(\"ENUM\");\n        long STRING = fnv1a_64_lower(\"STRING\");\n        long VARCHAR = fnv1a_64_lower(\"VARCHAR\");\n        long VARCHAR2 = fnv1a_64_lower(\"VARCHAR2\");\n        long NCHAR = fnv1a_64_lower(\"NCHAR\");\n        long NVARCHAR = fnv1a_64_lower(\"NVARCHAR\");\n        long NVARCHAR2 = fnv1a_64_lower(\"NVARCHAR2\");\n        long NCHAR_VARYING = fnv1a_64_lower(\"nchar varying\");\n        long VARBINARY = fnv1a_64_lower(\"VARBINARY\");\n        long TINYTEXT = fnv1a_64_lower(\"TINYTEXT\");\n        long TEXT = fnv1a_64_lower(\"TEXT\");\n        long MEDIUMTEXT = fnv1a_64_lower(\"MEDIUMTEXT\");\n        long LONGTEXT = fnv1a_64_lower(\"LONGTEXT\");\n        long TRIM = fnv1a_64_lower(\"TRIM\");\n        long LEADING = fnv1a_64_lower(\"LEADING\");\n        long BOTH = fnv1a_64_lower(\"BOTH\");\n        long TRAILING = fnv1a_64_lower(\"TRAILING\");\n        long MOD = fnv1a_64_lower(\"MOD\");\n        long MATCH = fnv1a_64_lower(\"MATCH\");\n        long AGAINST = fnv1a_64_lower(\"AGAINST\");\n        long EXTRACT = fnv1a_64_lower(\"EXTRACT\");\n        long POLYGON = fnv1a_64_lower(\"POLYGON\");\n        long CIRCLE = fnv1a_64_lower(\"CIRCLE\");\n        long LSEG = fnv1a_64_lower(\"LSEG\");\n        long POINT = fnv1a_64_lower(\"POINT\");\n        long E = fnv1a_64_lower(\"E\");\n        long BOX = fnv1a_64_lower(\"BOX\");\n        long MACADDR = fnv1a_64_lower(\"MACADDR\");\n        long INET = fnv1a_64_lower(\"INET\");\n        long CIDR = fnv1a_64_lower(\"CIDR\");\n        long POSITION = fnv1a_64_lower(\"POSITION\");\n        long DUAL = fnv1a_64_lower(\"DUAL\");\n        long LEVEL = fnv1a_64_lower(\"LEVEL\");\n        long CONNECT_BY_ISCYCLE = fnv1a_64_lower(\"CONNECT_BY_ISCYCLE\");\n        long CURRENT_TIMESTAMP = fnv1a_64_lower(\"CURRENT_TIMESTAMP\");\n        long LOCALTIMESTAMP = fnv1a_64_lower(\"LOCALTIMESTAMP\");\n        long LOCALTIME = fnv1a_64_lower(\"LOCALTIME\");\n        long SESSIONTIMEZONE = fnv1a_64_lower(\"SESSIONTIMEZONE\");\n        long DBTIMEZONE = fnv1a_64_lower(\"DBTIMEZONE\");\n        long CURRENT_DATE = fnv1a_64_lower(\"CURRENT_DATE\");\n        long CURRENT_TIME = fnv1a_64_lower(\"CURRENT_TIME\");\n        long CURTIME = fnv1a_64_lower(\"CURTIME\");\n        long CURRENT_USER = fnv1a_64_lower(\"CURRENT_USER\");\n        long FALSE = fnv1a_64_lower(\"FALSE\");\n        long TRUE = fnv1a_64_lower(\"TRUE\");\n        long LESS = fnv1a_64_lower(\"LESS\");\n        long MAXVALUE = fnv1a_64_lower(\"MAXVALUE\");\n        long OFFSET = fnv1a_64_lower(\"OFFSET\");\n        long LIMIT = fnv1a_64_lower(\"LIMIT\");\n        long RAW = fnv1a_64_lower(\"RAW\");\n        long LONG_RAW = fnv1a_64_lower(\"LONG RAW\");\n        long LONG = fnv1a_64_lower(\"LONG\");\n        long BYTE = fnv1a_64_lower(\"BYTE\");\n        long ROWNUM = fnv1a_64_lower(\"ROWNUM\");\n        long SYSDATE = fnv1a_64_lower(\"SYSDATE\");\n        long NOW = fnv1a_64_lower(\"NOW\");\n        long ADDTIME = fnv1a_64_lower(\"ADDTIME\");\n        long SUBTIME = fnv1a_64_lower(\"SUBTIME\");\n        long TIMEDIFF = fnv1a_64_lower(\"TIMEDIFF\");\n        long SQLCODE = fnv1a_64_lower(\"SQLCODE\");\n        long SQLERRM = fnv1a_64_lower(\"SQLERRM\");\n        long PRECISION = fnv1a_64_lower(\"PRECISION\");\n        long DOUBLE = fnv1a_64_lower(\"DOUBLE\");\n        long DOUBLE_PRECISION = fnv1a_64_lower(\"DOUBLE PRECISION\");\n        long WITHOUT = fnv1a_64_lower(\"WITHOUT\");\n        long BITAND = fnv1a_64_lower(\"BITAND\");\n\n        long DEFINER = fnv1a_64_lower(\"DEFINER\");\n        long EVENT = fnv1a_64_lower(\"EVENT\");\n        long RESOURCE = fnv1a_64_lower(\"RESOURCE\");\n        long RESOURCES = fnv1a_64_lower(\"RESOURCES\");\n        long FILE = fnv1a_64_lower(\"FILE\");\n        long JAR = fnv1a_64_lower(\"JAR\");\n        long PY = fnv1a_64_lower(\"PY\");\n        long ARCHIVE = fnv1a_64_lower(\"archive\");\n        long DETERMINISTIC = fnv1a_64_lower(\"DETERMINISTIC\");\n        long CONTAINS = fnv1a_64_lower(\"CONTAINS\");\n        long SQL = fnv1a_64_lower(\"SQL\");\n        long CALL = fnv1a_64_lower(\"CALL\");\n        long CHARACTER = fnv1a_64_lower(\"CHARACTER\");\n        long UNNEST = fnv1a_64_lower(\"UNNEST\");\n\n        long VALIDATE = fnv1a_64_lower(\"VALIDATE\");\n        long NOVALIDATE = fnv1a_64_lower(\"NOVALIDATE\");\n        long SIMILAR = fnv1a_64_lower(\"SIMILAR\");\n        long CASCADE = fnv1a_64_lower(\"CASCADE\");\n        long RELY = fnv1a_64_lower(\"RELY\");\n        long NORELY = fnv1a_64_lower(\"NORELY\");\n        long ROW = fnv1a_64_lower(\"ROW\");\n        long ROWS = fnv1a_64_lower(\"ROWS\");\n        long RANGE = fnv1a_64_lower(\"RANGE\");\n        long PRECEDING = fnv1a_64_lower(\"PRECEDING\");\n        long FOLLOWING = fnv1a_64_lower(\"FOLLOWING\");\n        long UNBOUNDED = fnv1a_64_lower(\"UNBOUNDED\");\n        long SIBLINGS = fnv1a_64_lower(\"SIBLINGS\");\n        long RESPECT = fnv1a_64_lower(\"RESPECT\");\n        long NULLS = fnv1a_64_lower(\"NULLS\");\n        long FIRST = fnv1a_64_lower(\"FIRST\");\n        long LAST = fnv1a_64_lower(\"LAST\");\n        long AUTO_INCREMENT = fnv1a_64_lower(\"AUTO_INCREMENT\");\n        long STORAGE = fnv1a_64_lower(\"STORAGE\");\n        long STORED = fnv1a_64_lower(\"STORED\");\n        long VIRTUAL = fnv1a_64_lower(\"VIRTUAL\");\n        long SIGNED = fnv1a_64_lower(\"SIGNED\");\n        long UNSIGNED = fnv1a_64_lower(\"UNSIGNED\");\n        long ZEROFILL = fnv1a_64_lower(\"ZEROFILL\");\n        long GLOBAL = fnv1a_64_lower(\"GLOBAL\");\n        long LOCAL = fnv1a_64_lower(\"LOCAL\");\n        long TEMPORARY = fnv1a_64_lower(\"TEMPORARY\");\n        long NONCLUSTERED = fnv1a_64_lower(\"NONCLUSTERED\");\n        long SESSION = fnv1a_64_lower(\"SESSION\");\n        long NAMES = fnv1a_64_lower(\"NAMES\");\n        long PARTIAL = fnv1a_64_lower(\"PARTIAL\");\n        long SIMPLE = fnv1a_64_lower(\"SIMPLE\");\n        long RESTRICT = fnv1a_64_lower(\"RESTRICT\");\n        long ON = fnv1a_64_lower(\"ON\");\n        long ONLINE = fnv1a_64_lower(\"ONLINE\");\n        long ACTION = fnv1a_64_lower(\"ACTION\");\n        long SEPARATOR = fnv1a_64_lower(\"SEPARATOR\");\n        long DATA = fnv1a_64_lower(\"DATA\");\n        long MIGRATE = fnv1a_64_lower(\"MIGRATE\");\n        long MAX_ROWS = fnv1a_64_lower(\"MAX_ROWS\");\n        long MIN_ROWS = fnv1a_64_lower(\"MIN_ROWS\");\n        long PACK_KEYS = fnv1a_64_lower(\"PACK_KEYS\");\n        long ENGINE = fnv1a_64_lower(\"ENGINE\");\n        long SKIP = fnv1a_64_lower(\"SKIP\");\n        long RECURSIVE = fnv1a_64_lower(\"RECURSIVE\");\n        long ROLLUP = fnv1a_64_lower(\"ROLLUP\");\n        long CUBE = fnv1a_64_lower(\"CUBE\");\n        long TEMPLATE = fnv1a_64_lower(\"TEMPLATE\");\n        long ALLOW_CONNECTIONS = fnv1a_64_lower(\"ALLOW_CONNECTIONS\");\n        long IS_TEMPLATE = fnv1a_64_lower(\"IS_TEMPLATE\");\n\n        long YEAR = fnv1a_64_lower(\"YEAR\");\n        long QUARTER = fnv1a_64_lower(\"QUARTER\");\n        long MONTH = fnv1a_64_lower(\"MONTH\");\n        long WEEK = fnv1a_64_lower(\"WEEK\");\n        long WEEKDAY = fnv1a_64_lower(\"WEEKDAY\");\n        long WEEKOFYEAR = fnv1a_64_lower(\"WEEKOFYEAR\");\n        long YEARWEEK = fnv1a_64_lower(\"YEARWEEK\");\n        long YEAR_OF_WEEK = fnv1a_64_lower(\"YEAR_OF_WEEK\");\n        long YOW = fnv1a_64_lower(\"YOW\");\n        long YEARMONTH = fnv1a_64_lower(\"YEARMONTH\");\n        long TO_TIMESTAMP = fnv1a_64_lower(\"TO_TIMESTAMP\");\n        long DAY = fnv1a_64_lower(\"DAY\");\n        long DAYOFMONTH = fnv1a_64_lower(\"DAYOFMONTH\");\n        long DAYOFWEEK = fnv1a_64_lower(\"DAYOFWEEK\");\n        long DATE_TRUNC = fnv1a_64_lower(\"DATE_TRUNC\");\n        long DAYOFYEAR = fnv1a_64_lower(\"DAYOFYEAR\");\n        long MONTH_BETWEEN = fnv1a_64_lower(\"MONTH_BETWEEN\");\n        long TIMESTAMPADD = fnv1a_64_lower(\"TIMESTAMPADD\");\n        long HOUR = fnv1a_64_lower(\"HOUR\");\n        long MINUTE = fnv1a_64_lower(\"MINUTE\");\n        long SECOND = fnv1a_64_lower(\"SECOND\");\n        long MICROSECOND = fnv1a_64_lower(\"MICROSECOND\");\n        long CURDATE = fnv1a_64_lower(\"CURDATE\");\n        long CUR_DATE = fnv1a_64_lower(\"CUR_DATE\");\n        long DATE_DIFF = fnv1a_64_lower(\"DATE_DIFF\");\n\n        long SECONDS = fnv1a_64_lower(\"SECONDS\");\n        long MINUTES = fnv1a_64_lower(\"MINUTES\");\n        long HOURS = fnv1a_64_lower(\"HOURS\");\n        long DAYS = fnv1a_64_lower(\"DAYS\");\n        long MONTHS = fnv1a_64_lower(\"MONTHS\");\n        long YEARS = fnv1a_64_lower(\"YEARS\");\n\n        long BEFORE = fnv1a_64_lower(\"BEFORE\");\n        long AFTER = fnv1a_64_lower(\"AFTER\");\n        long INSTEAD = fnv1a_64_lower(\"INSTEAD\");\n\n        long DEFERRABLE = fnv1a_64_lower(\"DEFERRABLE\");\n        long AS = fnv1a_64_lower(\"AS\");\n        long DELAYED = fnv1a_64_lower(\"DELAYED\");\n        long GO = fnv1a_64_lower(\"GO\");\n        long WAITFOR = fnv1a_64_lower(\"WAITFOR\");\n        long EXEC = fnv1a_64_lower(\"EXEC\");\n        long EXECUTE = fnv1a_64_lower(\"EXECUTE\");\n\n        long SOURCE = fnv1a_64_lower(\"SOURCE\");\n\n        long STAR = fnv1a_64_lower(\"*\");\n\n        long TO_CHAR = fnv1a_64_lower(\"TO_CHAR\");\n        long UNIX_TIMESTAMP = fnv1a_64_lower(\"UNIX_TIMESTAMP\");\n        long FROM_UNIXTIME = fnv1a_64_lower(\"FROM_UNIXTIME\");\n        long TO_UNIXTIME = fnv1a_64_lower(\"TO_UNIXTIME\");\n        long SYS_GUID = fnv1a_64_lower(\"SYS_GUID\");\n        long LAST_DAY = fnv1a_64_lower(\"LAST_DAY\");\n        long MAKEDATE = fnv1a_64_lower(\"MAKEDATE\");\n        long ASCII = fnv1a_64_lower(\"ASCII\");\n        long DAYNAME = fnv1a_64_lower(\"DAYNAME\");\n\n        long STATISTICS = fnv1a_64_lower(\"STATISTICS\");\n        long TRANSACTION = fnv1a_64_lower(\"TRANSACTION\");\n        long OFF = fnv1a_64_lower(\"OFF\");\n        long OFFLINE = fnv1a_64_lower(\"OFFLINE\");\n        long IDENTITY_INSERT = fnv1a_64_lower(\"IDENTITY_INSERT\");\n        long PASSWORD = fnv1a_64_lower(\"PASSWORD\");\n        long SOCKET = fnv1a_64_lower(\"SOCKET\");\n        long OWNER = fnv1a_64_lower(\"OWNER\");\n        long PORT = fnv1a_64_lower(\"PORT\");\n        long PUBLIC = fnv1a_64_lower(\"PUBLIC\");\n        long SYNONYM = fnv1a_64_lower(\"SYNONYM\");\n        long MATERIALIZED = fnv1a_64_lower(\"MATERIALIZED\");\n        long BITMAP = fnv1a_64_lower(\"BITMAP\");\n        long LABEL = fnv1a_64_lower(\"LABEL\");\n        long PACKAGE = fnv1a_64_lower(\"PACKAGE\");\n        long PACKAGES = fnv1a_64_lower(\"PACKAGES\");\n        long TRUNC = fnv1a_64_lower(\"TRUNC\");\n        long SYSTIMESTAMP = fnv1a_64_lower(\"SYSTIMESTAMP\");\n        long TYPE = fnv1a_64_lower(\"TYPE\");\n        long RECORD = fnv1a_64_lower(\"RECORD\");\n        long MAP = fnv1a_64_lower(\"MAP\");\n        long MAPJOIN = fnv1a_64_lower(\"MAPJOIN\");\n        long MAPPED = fnv1a_64_lower(\"MAPPED\");\n        long MAPPING = fnv1a_64_lower(\"MAPPING\");\n        long COLPROPERTIES = fnv1a_64_lower(\"COLPROPERTIES\");\n        long ONLY = fnv1a_64_lower(\"ONLY\");\n        long MEMBER = fnv1a_64_lower(\"MEMBER\");\n        long STATIC = fnv1a_64_lower(\"STATIC\");\n        long FINAL = fnv1a_64_lower(\"FINAL\");\n        long INSTANTIABLE = fnv1a_64_lower(\"INSTANTIABLE\");\n        long UNSUPPORTED = fnv1a_64_lower(\"UNSUPPORTED\");\n        long VARRAY = fnv1a_64_lower(\"VARRAY\");\n        long WRAPPED = fnv1a_64_lower(\"WRAPPED\");\n        long AUTHID = fnv1a_64_lower(\"AUTHID\");\n        long UNDER = fnv1a_64_lower(\"UNDER\");\n        long USERENV = fnv1a_64_lower(\"USERENV\");\n        long NUMTODSINTERVAL = fnv1a_64_lower(\"NUMTODSINTERVAL\");\n\n        long LATERAL = fnv1a_64_lower(\"LATERAL\");\n        long NONE = fnv1a_64_lower(\"NONE\");\n        long PARTITIONING = fnv1a_64_lower(\"PARTITIONING\");\n        long VALIDPROC = fnv1a_64_lower(\"VALIDPROC\");\n        long COMPRESS = fnv1a_64_lower(\"COMPRESS\");\n        long YES = fnv1a_64_lower(\"YES\");\n        long WMSYS = fnv1a_64_lower(\"WMSYS\");\n\n        long DEPTH = fnv1a_64_lower(\"DEPTH\");\n        long BREADTH = fnv1a_64_lower(\"BREADTH\");\n\n        long SCHEDULE = fnv1a_64_lower(\"SCHEDULE\");\n        long COMPLETION = fnv1a_64_lower(\"COMPLETION\");\n        long RENAME = fnv1a_64_lower(\"RENAME\");\n        long AT = fnv1a_64_lower(\"AT\");\n        long LANGUAGE = fnv1a_64_lower(\"LANGUAGE\");\n        long LOGFILE = fnv1a_64_lower(\"LOGFILE\");\n        long LOG = fnv1a_64_lower(\"LOG\");\n        long INITIAL_SIZE = fnv1a_64_lower(\"INITIAL_SIZE\");\n        long MAX_SIZE = fnv1a_64_lower(\"MAX_SIZE\");\n        long NODEGROUP = fnv1a_64_lower(\"NODEGROUP\");\n        long EXTENT_SIZE = fnv1a_64_lower(\"EXTENT_SIZE\");\n        long AUTOEXTEND_SIZE = fnv1a_64_lower(\"AUTOEXTEND_SIZE\");\n        long FILE_BLOCK_SIZE = fnv1a_64_lower(\"FILE_BLOCK_SIZE\");\n        long BLOCK_SIZE = fnv1a_64_lower(\"BLOCK_SIZE\");\n        long REPLICA_NUM = fnv1a_64_lower(\"REPLICA_NUM\");\n        long REPLICATION = fnv1a_64_lower(\"REPLICATION\");\n        long TABLET_SIZE = fnv1a_64_lower(\"TABLET_SIZE\");\n        long PCTFREE = fnv1a_64_lower(\"PCTFREE\");\n        long USE_BLOOM_FILTER = fnv1a_64_lower(\"USE_BLOOM_FILTER\");\n        long SERVER = fnv1a_64_lower(\"SERVER\");\n        long HOST = fnv1a_64_lower(\"HOST\");\n        long ADD = fnv1a_64_lower(\"ADD\");\n        long REMOVE = fnv1a_64_lower(\"REMOVE\");\n        long MOVE = fnv1a_64_lower(\"MOVE\");\n        long ALGORITHM = fnv1a_64_lower(\"ALGORITHM\");\n        long LINEAR = fnv1a_64_lower(\"LINEAR\");\n        long EVERY = fnv1a_64_lower(\"EVERY\");\n        long STARTS = fnv1a_64_lower(\"STARTS\");\n        long END = fnv1a_64_lower(\"END\");\n        long ENDS = fnv1a_64_lower(\"ENDS\");\n        long BINARY = fnv1a_64_lower(\"BINARY\");\n        long GEOMETRY = fnv1a_64_lower(\"GEOMETRY\");\n        long FOUND = fnv1a_64_lower(\"FOUND\");\n        long NOTFOUND = fnv1a_64_lower(\"NOTFOUND\");\n        long ROWCOUNT = fnv1a_64_lower(\"ROWCOUNT\");\n        long BULK_ROWCOUNT = fnv1a_64_lower(\"BULK_ROWCOUNT\");\n        long BULK_EXCEPTIONS = fnv1a_64_lower(\"BULK_EXCEPTIONS\");\n        long ISOPEN = fnv1a_64_lower(\"ISOPEN\");\n        long CONFLICT = fnv1a_64_lower(\"CONFLICT\");\n        long NOTHING = fnv1a_64_lower(\"NOTHING\");\n        long COMMIT = fnv1a_64_lower(\"COMMIT\");\n        long DESCRIBE = fnv1a_64_lower(\"DESCRIBE\");\n        long SQLXML = fnv1a_64_lower(\"SQLXML\");\n        long BIT = fnv1a_64_lower(\"BIT\");\n        long LONGBLOB = fnv1a_64_lower(\"LONGBLOB\");\n\n        long RS = fnv1a_64_lower(\"RS\");\n        long RR = fnv1a_64_lower(\"RR\");\n        long CS = fnv1a_64_lower(\"CS\");\n        long UR = fnv1a_64_lower(\"UR\");\n\n        long INT4 = fnv1a_64_lower(\"INT4\");\n        long VARBIT = fnv1a_64_lower(\"VARBIT\");\n        long DECODE = fnv1a_64_lower(\"DECODE\");\n        long IF = fnv1a_64_lower(\"IF\");\n        long FUNCTION = fnv1a_64_lower(\"FUNCTION\");\n        long EXTERNAL = fnv1a_64_lower(\"EXTERNAL\");\n        long SORTED = fnv1a_64_lower(\"SORTED\");\n        long CLUSTERED = fnv1a_64_lower(\"CLUSTERED\");\n        long LIFECYCLE = fnv1a_64_lower(\"LIFECYCLE\");\n        long LOCATION = fnv1a_64_lower(\"LOCATION\");\n        long PARTITIONS = fnv1a_64_lower(\"PARTITIONS\");\n        long FORMAT = fnv1a_64_lower(\"FORMAT\");\n        long ENCODE = fnv1a_64_lower(\"ENCODE\");\n\n        long SELECT = fnv1a_64_lower(\"SELECT\");\n        long DELETE = fnv1a_64_lower(\"DELETE\");\n        long UPDATE = fnv1a_64_lower(\"UPDATE\");\n        long INSERT = fnv1a_64_lower(\"INSERT\");\n        long REPLACE = fnv1a_64_lower(\"REPLACE\");\n        long TRUNCATE = fnv1a_64_lower(\"TRUNCATE\");\n        long CREATE = fnv1a_64_lower(\"CREATE\");\n        long MERGE = fnv1a_64_lower(\"MERGE\");\n        long SHOW = fnv1a_64_lower(\"SHOW\");\n        long ALTER = fnv1a_64_lower(\"ALTER\");\n        long DESC = fnv1a_64_lower(\"DESC\");\n        long SET = fnv1a_64_lower(\"SET\");\n        long MULTISET = fnv1a_64_lower(\"MULTISET\");\n        long VOLATILE = fnv1a_64_lower(\"VOLATILE\");\n        long KILL = fnv1a_64_lower(\"KILL\");\n        long MSCK = fnv1a_64_lower(\"MSCK\");\n        long USE = fnv1a_64_lower(\"USE\");\n        long ROLLBACK = fnv1a_64_lower(\"ROLLBACK\");\n        long GRANT = fnv1a_64_lower(\"GRANT\");\n        long REVOKE = fnv1a_64_lower(\"REVOKE\");\n        long DROP = fnv1a_64_lower(\"DROP\");\n        long USER = fnv1a_64_lower(\"USER\");\n\n        long USAGE = fnv1a_64_lower(\"USAGE\");\n        long PCTUSED = fnv1a_64_lower(\"PCTUSED\");\n        long OPAQUE = fnv1a_64_lower(\"OPAQUE\");\n        long INHERITS = fnv1a_64_lower(\"INHERITS\");\n        long DELIMITED = fnv1a_64_lower(\"DELIMITED\");\n        long ARRAY = fnv1a_64_lower(\"ARRAY\");\n        long SCALAR = fnv1a_64_lower(\"SCALAR\");\n        long STRUCT = fnv1a_64_lower(\"STRUCT\");\n        long TABLE = fnv1a_64_lower(\"TABLE\");\n        long UNIONTYPE = fnv1a_64_lower(\"UNIONTYPE\");\n\n        long TDDL = fnv1a_64_lower(\"TDDL\");\n        long CONCURRENTLY = fnv1a_64_lower(\"CONCURRENTLY\");\n        long TABLES = fnv1a_64_lower(\"TABLES\");\n        long ROLES = fnv1a_64_lower(\"ROLES\");\n        long NOCACHE = fnv1a_64_lower(\"NOCACHE\");\n        long NOPARALLEL = fnv1a_64_lower(\"NOPARALLEL\");\n        long EXIST = fnv1a_64_lower(\"EXIST\");\n        long EXISTS = fnv1a_64_lower(\"EXISTS\");\n        long SOUNDS = fnv1a_64_lower(\"SOUNDS\");\n        long TBLPROPERTIES = fnv1a_64_lower(\"TBLPROPERTIES\");\n        long TABLEGROUP = fnv1a_64_lower(\"TABLEGROUP\");\n        long TABLEGROUPS = fnv1a_64_lower(\"TABLEGROUPS\");\n        long DIMENSION = fnv1a_64_lower(\"DIMENSION\");\n        long OPTIONS = fnv1a_64_lower(\"OPTIONS\");\n        long OPTIMIZER = fnv1a_64_lower(\"OPTIMIZER\");\n\n        long FULLTEXT = fnv1a_64_lower(\"FULLTEXT\");\n        long SPATIAL = fnv1a_64_lower(\"SPATIAL\");\n\n        long SUBPARTITION_AVAILABLE_PARTITION_NUM = fnv1a_64_lower(\"SUBPARTITION_AVAILABLE_PARTITION_NUM\");\n        long EXTRA = fnv1a_64_lower(\"EXTRA\");\n        long DATABASES = fnv1a_64_lower(\"DATABASES\");\n        long COLUMNS = fnv1a_64_lower(\"COLUMNS\");\n        long PROCESS = fnv1a_64_lower(\"PROCESS\");\n        long PROCESSLIST = fnv1a_64_lower(\"PROCESSLIST\");\n        long MPP = fnv1a_64_lower(\"MPP\");\n        long SERDE = fnv1a_64_lower(\"SERDE\");\n        long SERDEPROPERTIES = fnv1a_64_lower(\"SERDEPROPERTIES\");\n        long SORT = fnv1a_64_lower(\"SORT\");\n        long ZORDER = fnv1a_64_lower(\"ZORDER\");\n        long FIELDS = fnv1a_64_lower(\"FIELDS\");\n        long COLLECTION = fnv1a_64_lower(\"COLLECTION\");\n        long SKEWED = fnv1a_64_lower(\"SKEWED\");\n        long SYMBOL = fnv1a_64_lower(\"SYMBOL\");\n        long LOAD = fnv1a_64_lower(\"LOAD\");\n        long VIEWS = fnv1a_64_lower(\"VIEWS\");\n        long SUBSTR = fnv1a_64_lower(\"SUBSTR\");\n        long TO_BASE64 = fnv1a_64_lower(\"TO_BASE64\");\n        long REGEXP_SUBSTR = fnv1a_64_lower(\"REGEXP_SUBSTR\");\n        long REGEXP_COUNT = fnv1a_64_lower(\"REGEXP_COUNT\");\n        long REGEXP_EXTRACT = fnv1a_64_lower(\"REGEXP_EXTRACT\");\n        long REGEXP_EXTRACT_ALL = fnv1a_64_lower(\"REGEXP_EXTRACT_ALL\");\n        long REGEXP_LIKE = fnv1a_64_lower(\"REGEXP_LIKE\");\n        long REGEXP_REPLACE = fnv1a_64_lower(\"REGEXP_REPLACE\");\n        long REGEXP_SPLIT = fnv1a_64_lower(\"REGEXP_SPLIT\");\n        long CONCAT = fnv1a_64_lower(\"CONCAT\");\n        long LCASE = fnv1a_64_lower(\"LCASE\");\n        long UCASE = fnv1a_64_lower(\"UCASE\");\n        long LOWER = fnv1a_64_lower(\"LOWER\");\n        long UPPER = fnv1a_64_lower(\"UPPER\");\n        long LENGTH = fnv1a_64_lower(\"LENGTH\");\n        long LOCATE = fnv1a_64_lower(\"LOCATE\");\n        long UDF_SYS_ROWCOUNT = fnv1a_64_lower(\"UDF_SYS_ROWCOUNT\");\n        long CHAR_LENGTH = fnv1a_64_lower(\"CHAR_LENGTH\");\n        long CHARACTER_LENGTH = fnv1a_64_lower(\"CHARACTER_LENGTH\");\n        long SUBSTRING = fnv1a_64_lower(\"SUBSTRING\");\n        long SUBSTRING_INDEX = fnv1a_64_lower(\"SUBSTRING_INDEX\");\n        long LEFT = fnv1a_64_lower(\"LEFT\");\n        long RIGHT = fnv1a_64_lower(\"RIGHT\");\n        long RTRIM = fnv1a_64_lower(\"RTRIM\");\n        long LEN = fnv1a_64_lower(\"LEN\");\n        long GREAST = fnv1a_64_lower(\"GREAST\");\n        long LEAST = fnv1a_64_lower(\"LEAST\");\n        long IFNULL = fnv1a_64_lower(\"IFNULL\");\n        long NULLIF = fnv1a_64_lower(\"NULLIF\");\n        long GREATEST = fnv1a_64_lower(\"GREATEST\");\n        long COALESCE = fnv1a_64_lower(\"COALESCE\");\n        long ISNULL = fnv1a_64_lower(\"ISNULL\");\n        long NVL = fnv1a_64_lower(\"NVL\");\n        long NVL2 = fnv1a_64_lower(\"NVL2\");\n        long TO_DATE = fnv1a_64_lower(\"TO_DATE\");\n        long DATEADD = fnv1a_64_lower(\"DATEADD\");\n        long DATE_ADD = fnv1a_64_lower(\"DATE_ADD\");\n        long ADDDATE = fnv1a_64_lower(\"ADDDATE\");\n        long DATE_SUB = fnv1a_64_lower(\"DATE_SUB\");\n        long SUBDATE = fnv1a_64_lower(\"SUBDATE\");\n        long DATE_PARSE = fnv1a_64_lower(\"DATE_PARSE\");\n        long STR_TO_DATE = fnv1a_64_lower(\"STR_TO_DATE\");\n        long CLOTHES_FEATURE_EXTRACT_V1 = fnv1a_64_lower(\"CLOTHES_FEATURE_EXTRACT_V1\");\n        long CLOTHES_ATTRIBUTE_EXTRACT_V1 = fnv1a_64_lower(\"CLOTHES_ATTRIBUTE_EXTRACT_V1\");\n\n        long GENERIC_FEATURE_EXTRACT_V1 = fnv1a_64_lower(\"GENERIC_FEATURE_EXTRACT_V1\");\n        long FACE_FEATURE_EXTRACT_V1 = fnv1a_64_lower(\"FACE_FEATURE_EXTRACT_V1\");\n        long TEXT_FEATURE_EXTRACT_V1 = fnv1a_64_lower(\"TEXT_FEATURE_EXTRACT_V1\");\n\n        long JSON_TABLE = fnv1a_64_lower(\"JSON_TABLE\");\n        long JSON_EXTRACT = fnv1a_64_lower(\"JSON_EXTRACT\");\n        long JSON_EXTRACT_SCALAR = fnv1a_64_lower(\"json_extract_scalar\");\n        long JSON_ARRAY_GET = fnv1a_64_lower(\"JSON_ARRAY_GET\");\n        long ADD_MONTHS = fnv1a_64_lower(\"ADD_MONTHS\");\n        long ABS = fnv1a_64_lower(\"ABS\");\n        long ACOS = fnv1a_64_lower(\"ACOS\");\n        long ASIN = fnv1a_64_lower(\"ASIN\");\n        long ATAN = fnv1a_64_lower(\"ATAN\");\n        long ATAN2 = fnv1a_64_lower(\"ATAN2\");\n        long COS = fnv1a_64_lower(\"COS\");\n        long FLOOR = fnv1a_64_lower(\"FLOOR\");\n        long CEIL = fnv1a_64_lower(\"CEIL\");\n        long SQRT = fnv1a_64_lower(\"SQRT\");\n        long LEAD = fnv1a_64_lower(\"LEAD\");\n        long LAG = fnv1a_64_lower(\"LAG\");\n        long CEILING = fnv1a_64_lower(\"CEILING\");\n        long POWER = fnv1a_64_lower(\"POWER\");\n        long EXP = fnv1a_64_lower(\"EXP\");\n        long LN = fnv1a_64_lower(\"LN\");\n        long LOG10 = fnv1a_64_lower(\"LOG10\");\n        long INTERVAL = fnv1a_64_lower(\"INTERVAL\");\n        long FROM_DAYS = fnv1a_64_lower(\"FROM_DAYS\");\n        long TO_DAYS = fnv1a_64_lower(\"TO_DAYS\");\n\n        long BIGINT = fnv1a_64_lower(\"BIGINT\");\n        long LONGLONG = fnv1a_64_lower(\"LONGLONG\");\n        long DISCARD = fnv1a_64_lower(\"DISCARD\");\n        long EXCHANGE = fnv1a_64_lower(\"EXCHANGE\");\n        long ROLE = fnv1a_64_lower(\"ROLE\");\n        long OVERWRITE = fnv1a_64_lower(\"OVERWRITE\");\n        long NO = fnv1a_64_lower(\"NO\");\n        long CATALOG = fnv1a_64_lower(\"CATALOG\");\n        long CATALOGS = fnv1a_64_lower(\"CATALOGS\");\n        long FUNCTIONS = fnv1a_64_lower(\"FUNCTIONS\");\n        long SCHEMAS = fnv1a_64_lower(\"SCHEMAS\");\n        long CHANGE = fnv1a_64_lower(\"CHANGE\");\n        long MODIFY = fnv1a_64_lower(\"MODIFY\");\n        long BEGIN = fnv1a_64_lower(\"BEGIN\");\n        long PATH = fnv1a_64_lower(\"PATH\");\n        long ENCRYPTION = fnv1a_64_lower(\"ENCRYPTION\");\n        long COMPRESSION = fnv1a_64_lower(\"COMPRESSION\");\n        long KEY_BLOCK_SIZE = fnv1a_64_lower(\"KEY_BLOCK_SIZE\");\n        long CHECKSUM = fnv1a_64_lower(\"CHECKSUM\");\n        long CONNECTION = fnv1a_64_lower(\"CONNECTION\");\n        long DATASOURCES = fnv1a_64_lower(\"DATASOURCES\");\n        long NODE = fnv1a_64_lower(\"NODE\");\n        long HELP = fnv1a_64_lower(\"HELP\");\n        long BROADCASTS = fnv1a_64_lower(\"BROADCASTS\");\n        long MASTER = fnv1a_64_lower(\"MASTER\");\n        long SLAVE = fnv1a_64_lower(\"SLAVE\");\n        long SQL_DELAY_CUTOFF = fnv1a_64_lower(\"SQL_DELAY_CUTOFF\");\n        long SOCKET_TIMEOUT = fnv1a_64_lower(\"SOCKET_TIMEOUT\");\n        long FORBID_EXECUTE_DML_ALL = fnv1a_64_lower(\"FORBID_EXECUTE_DML_ALL\");\n        long SCAN = fnv1a_64_lower(\"SCAN\");\n        long NOLOGFILE = fnv1a_64_lower(\"NOLOGFILE\");\n        long NOBADFILE = fnv1a_64_lower(\"NOBADFILE\");\n        long TERMINATED = fnv1a_64_lower(\"TERMINATED\");\n        long LTRIM = fnv1a_64_lower(\"LTRIM\");\n        long MISSING = fnv1a_64_lower(\"MISSING\");\n        long SUBPARTITION = fnv1a_64_lower(\"SUBPARTITION\");\n        long SUBPARTITIONS = fnv1a_64_lower(\"SUBPARTITIONS\");\n        long GENERATED = fnv1a_64_lower(\"GENERATED\");\n        long ALWAYS = fnv1a_64_lower(\"ALWAYS\");\n        long VISIBLE = fnv1a_64_lower(\"VISIBLE\");\n        long INCLUDING = fnv1a_64_lower(\"INCLUDING\");\n        long EXCLUDE = fnv1a_64_lower(\"EXCLUDE\");\n        long EXCLUDING = fnv1a_64_lower(\"EXCLUDING\");\n        long ROUTINE = fnv1a_64_lower(\"ROUTINE\");\n        long IDENTIFIED = fnv1a_64_lower(\"IDENTIFIED\");\n        long DELIMITER = fnv1a_64_lower(\"DELIMITER\");\n        long UNKNOWN = fnv1a_64_lower(\"UNKNOWN\");\n        long WEIGHT_STRING = fnv1a_64_lower(\"WEIGHT_STRING\");\n        long REVERSE = fnv1a_64_lower(\"REVERSE\");\n        long DATE_FORMAT = fnv1a_64_lower(\"DATE_FORMAT\");\n        long DAY_OF_WEEK = fnv1a_64_lower(\"DAY_OF_WEEK\");\n        long DATEDIFF = fnv1a_64_lower(\"DATEDIFF\");\n        long GET_FORMAT = fnv1a_64_lower(\"GET_FORMAT\");\n        long TIMESTAMPDIFF = fnv1a_64_lower(\"TIMESTAMPDIFF\");\n        long MONTHNAME = fnv1a_64_lower(\"MONTHNAME\");\n        long PERIOD_ADD = fnv1a_64_lower(\"PERIOD_ADD\");\n        long PERIOD_DIFF = fnv1a_64_lower(\"PERIOD_DIFF\");\n        long ROUND = fnv1a_64_lower(\"ROUND\");\n        long ROUNDROBIN = fnv1a_64_lower(\"ROUNDROBIN\");\n        long DBPARTITION = fnv1a_64_lower(\"DBPARTITION\");\n        long TBPARTITION = fnv1a_64_lower(\"TBPARTITION\");\n        long EXTPARTITION = fnv1a_64_lower(\"EXTPARTITION\");\n        long STARTWITH = fnv1a_64_lower(\"STARTWITH\");\n        long TBPARTITIONS = fnv1a_64_lower(\"TBPARTITIONS\");\n        long DBPARTITIONS = fnv1a_64_lower(\"DBPARTITIONS\");\n        long PARTITIONED = fnv1a_64_lower(\"PARTITIONED\");\n        long PARALLEL = fnv1a_64_lower(\"PARALLEL\");\n        long ALLOW = fnv1a_64_lower(\"ALLOW\");\n        long DISALLOW = fnv1a_64_lower(\"DISALLOW\");\n        long PIVOT = fnv1a_64_lower(\"PIVOT\");\n        long MODEL = fnv1a_64_lower(\"MODEL\");\n        long KEEP = fnv1a_64_lower(\"KEEP\");\n        long REFERENCE = fnv1a_64_lower(\"REFERENCE\");\n        long RETURN = fnv1a_64_lower(\"RETURN\");\n        long RETURNS = fnv1a_64_lower(\"RETURNS\");\n        long ROWTYPE = fnv1a_64_lower(\"ROWTYPE\");\n        long WINDOW = fnv1a_64_lower(\"WINDOW\");\n        long QUALIFY = fnv1a_64_lower(\"QUALIFY\");\n        long MULTIVALUE = fnv1a_64_lower(\"MULTIVALUE\");\n        long OPTIONALLY = fnv1a_64_lower(\"OPTIONALLY\");\n        long ENCLOSED = fnv1a_64_lower(\"ENCLOSED\");\n        long ESCAPED = fnv1a_64_lower(\"ESCAPED\");\n        long ESCAPE = fnv1a_64_lower(\"ESCAPE\");\n        long LINES = fnv1a_64_lower(\"LINES\");\n        long STARTING = fnv1a_64_lower(\"STARTING\");\n        long DISTRIBUTE = fnv1a_64_lower(\"DISTRIBUTE\");\n        long DISTRIBUTED = fnv1a_64_lower(\"DISTRIBUTED\");\n        long CLUSTER = fnv1a_64_lower(\"CLUSTER\");\n        long RUNNING = fnv1a_64_lower(\"RUNNING\");\n        long CLUSTERING = fnv1a_64_lower(\"CLUSTERING\");\n        long PCTVERSION = fnv1a_64_lower(\"PCTVERSION\");\n        long IDENTITY = fnv1a_64_lower(\"IDENTITY\");\n        long INCREMENT = fnv1a_64_lower(\"INCREMENT\");\n        long MINVALUE = fnv1a_64_lower(\"MINVALUE\");\n        long ANN = fnv1a_64_lower(\"ANN\");\n        long ANN_DISTANCE = fnv1a_64_lower(\"ANN_DISTANCE\");\n        long SUPPLEMENTAL = fnv1a_64_lower(\"SUPPLEMENTAL\");\n        long SUBSTITUTABLE = fnv1a_64_lower(\"SUBSTITUTABLE\");\n        long BASICFILE = fnv1a_64_lower(\"BASICFILE\");\n        long IN_MEMORY_METADATA = fnv1a_64_lower(\"IN_MEMORY_METADATA\");\n        long CURSOR_SPECIFIC_SEGMENT = fnv1a_64_lower(\"CURSOR_SPECIFIC_SEGMENT\");\n        long DEFER = fnv1a_64_lower(\"DEFER\");\n        long UNDO_LOG_LIMIT = fnv1a_64_lower(\"UNDO_LOG_LIMIT\");\n        long DBPROPERTIES = fnv1a_64_lower(\"DBPROPERTIES\");\n        long ANNINDEX = fnv1a_64_lower(\"ANNINDEX\");\n        long RTTYPE = fnv1a_64_lower(\"RTTYPE\");\n        long DISTANCE = fnv1a_64_lower(\"DISTANCE\");\n        long IDXPROPERTIES = fnv1a_64_lower(\"IDXPROPERTIES\");\n        long RECOVER = fnv1a_64_lower(\"RECOVER\");\n        long BACKUP = fnv1a_64_lower(\"BACKUP\");\n        long RESTORE = fnv1a_64_lower(\"RESTORE\");\n        long EXSTORE = fnv1a_64_lower(\"EXSTORE\");\n        long UNDO = fnv1a_64_lower(\"UNDO\");\n        long NOSCAN = fnv1a_64_lower(\"NOSCAN\");\n        long EXTENDED = fnv1a_64_lower(\"EXTENDED\");\n        long FORMATTED = fnv1a_64_lower(\"FORMATTED\");\n        long DEPENDENCY = fnv1a_64_lower(\"DEPENDENCY\");\n        long AUTHORIZATION = fnv1a_64_lower(\"AUTHORIZATION\");\n        long ANALYZE = fnv1a_64_lower(\"ANALYZE\");\n        long EXPORT = fnv1a_64_lower(\"EXPORT\");\n        long IMPORT = fnv1a_64_lower(\"IMPORT\");\n        long TABLESAMPLE = fnv1a_64_lower(\"TABLESAMPLE\");\n        long BUCKET = fnv1a_64_lower(\"BUCKET\");\n        long BUCKETS = fnv1a_64_lower(\"BUCKETS\");\n        long UNARCHIVE = fnv1a_64_lower(\"UNARCHIVE\");\n        long SEQUENCES = fnv1a_64_lower(\"SEQUENCES\");\n        long OUTLINE = fnv1a_64_lower(\"OUTLINE\");\n        long ORD = fnv1a_64_lower(\"ORD\");\n        long SPACE = fnv1a_64_lower(\"SPACE\");\n        long REPEAT = fnv1a_64_lower(\"REPEAT\");\n        long SLOW = fnv1a_64_lower(\"SLOW\");\n        long PLAN = fnv1a_64_lower(\"PLAN\");\n        long PLANCACHE = fnv1a_64_lower(\"PLANCACHE\");\n        long RECYCLEBIN = fnv1a_64_lower(\"RECYCLEBIN\");\n        long PURGE = fnv1a_64_lower(\"PURGE\");\n        long FLASHBACK = fnv1a_64_lower(\"FLASHBACK\");\n        long INPUTFORMAT = fnv1a_64_lower(\"INPUTFORMAT\");\n        long OUTPUTFORMAT = fnv1a_64_lower(\"OUTPUTFORMAT\");\n        long DUMP = fnv1a_64_lower(\"DUMP\");\n        long BROADCAST = fnv1a_64_lower(\"BROADCAST\");\n        long GROUP = fnv1a_64_lower(\"GROUP\");\n        long GROUPING = fnv1a_64_lower(\"GROUPING\");\n        long WITH = fnv1a_64_lower(\"WITH\");\n        long FROM = fnv1a_64_lower(\"FROM\");\n        long WHO = fnv1a_64_lower(\"WHO\");\n        long WHOAMI = fnv1a_64_lower(\"WHOAMI\");\n        long GRANTS = fnv1a_64_lower(\"GRANTS\");\n        long STATISTIC = fnv1a_64_lower(\"STATISTIC\");\n        long STATISTIC_LIST = fnv1a_64_lower(\"STATISTIC_LIST\");\n        long STATUS = fnv1a_64_lower(\"STATUS\");\n        long FULL = fnv1a_64_lower(\"FULL\");\n        long STATS = fnv1a_64_lower(\"STATS\");\n        long OUTLINES = fnv1a_64_lower(\"OUTLINES\");\n        long VERSION = fnv1a_64_lower(\"VERSION\");\n        long CONFIG = fnv1a_64_lower(\"CONFIG\");\n        long USERS = fnv1a_64_lower(\"USERS\");\n        long PHYSICAL_PROCESSLIST = fnv1a_64_lower(\"PHYSICAL_PROCESSLIST\");\n        long PHYSICAL = fnv1a_64_lower(\"PHYSICAL\");\n        long DISTANCEMEASURE = fnv1a_64_lower(\"DISTANCEMEASURE\");\n        long UNIT = fnv1a_64_lower(\"UNIT\");\n        long DB = fnv1a_64_lower(\"DB\");\n        long STEP = fnv1a_64_lower(\"STEP\");\n        long HEX = fnv1a_64_lower(\"HEX\");\n        long UNHEX = fnv1a_64_lower(\"UNHEX\");\n        long POLICY = fnv1a_64_lower(\"POLICY\");\n        long QUERY_TASK = fnv1a_64_lower(\"QUERY_TASK\");\n        long UUID = fnv1a_64_lower(\"UUID\");\n        long PCTTHRESHOLD = fnv1a_64_lower(\"PCTTHRESHOLD\");\n        long UNUSABLE = fnv1a_64_lower(\"UNUSABLE\");\n        long FILTER = fnv1a_64_lower(\"FILTER\");\n        long BIT_COUNT = fnv1a_64_lower(\"BIT_COUNT\");\n        long STDDEV_SAMP = fnv1a_64_lower(\"STDDEV_SAMP\");\n        long PERCENT_RANK = fnv1a_64_lower(\"PERCENT_RANK\");\n        long DENSE_RANK = fnv1a_64_lower(\"DENSE_RANK\");\n        long CUME_DIST = fnv1a_64_lower(\"CUME_DIST\");\n        long CARDINALITY = fnv1a_64_lower(\"CARDINALITY\");\n        long TRY_CAST = fnv1a_64_lower(\"TRY_CAST\");\n        long COVERING = fnv1a_64_lower(\"COVERING\");\n\n        long CHARFILTER = fnv1a_64_lower(\"CHARFILTER\");\n        long CHARFILTERS = fnv1a_64_lower(\"CHARFILTERS\");\n        long TOKENIZER = fnv1a_64_lower(\"TOKENIZER\");\n        long TOKENIZERS = fnv1a_64_lower(\"TOKENIZERS\");\n        long TOKENFILTER = fnv1a_64_lower(\"TOKENFILTER\");\n        long TOKENFILTERS = fnv1a_64_lower(\"TOKENFILTERS\");\n        long ANALYZER = fnv1a_64_lower(\"ANALYZER\");\n        long ANALYZERS = fnv1a_64_lower(\"ANALYZERS\");\n        long DICTIONARY = fnv1a_64_lower(\"DICTIONARY\");\n        long DICTIONARIES = fnv1a_64_lower(\"DICTIONARIES\");\n        long QUERY = fnv1a_64_lower(\"QUERY\");\n        long META = fnv1a_64_lower(\"META\");\n        long TRY = fnv1a_64_lower(\"TRY\");\n        long D = fnv1a_64_lower(\"D\");\n        long T = fnv1a_64_lower(\"T\");\n        long TS = fnv1a_64_lower(\"TS\");\n        long FN = fnv1a_64_lower(\"FN\");\n        long COPY = fnv1a_64_lower(\"COPY\");\n        long CREDENTIALS = fnv1a_64_lower(\"CREDENTIALS\");\n        long ACCESS_KEY_ID = fnv1a_64_lower(\"ACCESS_KEY_ID\");\n        long ACCESS_KEY_SECRET = fnv1a_64_lower(\"ACCESS_KEY_SECRET\");\n        long BERNOULLI = fnv1a_64_lower(\"BERNOULLI\");\n        long SYSTEM = fnv1a_64_lower(\"SYSTEM\");\n        long SYNC = fnv1a_64_lower(\"SYNC\");\n        long INIT = fnv1a_64_lower(\"INIT\");\n        long BD = fnv1a_64_lower(\"BD\");\n        long FORMAT_DATETIME = fnv1a_64_lower(\"FORMAT_DATETIME\");\n        long WITHIN = fnv1a_64_lower(\"WITHIN\");\n        long RULE = fnv1a_64_lower(\"RULE\");\n        long EXPLAIN = fnv1a_64_lower(\"EXPLAIN\");\n        long ISOLATION = fnv1a_64_lower(\"ISOLATION\");\n        long READ = fnv1a_64_lower(\"READ\");\n        long UNCOMMITTED = fnv1a_64_lower(\"UNCOMMITTED\");\n        long COMMITTED = fnv1a_64_lower(\"COMMITTED\");\n        long REPEATABLE = fnv1a_64_lower(\"REPEATABLE\");\n        long SERIALIZABLE = fnv1a_64_lower(\"SERIALIZABLE\");\n\n        long _LATIN1 = fnv1a_64_lower(\"_LATIN1\");\n        long _GBK = fnv1a_64_lower(\"_GBK\");\n        long _BIG5 = fnv1a_64_lower(\"_BIG5\");\n        long _UTF8 = fnv1a_64_lower(\"_UTF8\");\n        long _UTF8MB4 = fnv1a_64_lower(\"_UTF8MB4\");\n        long _UTF16 = fnv1a_64_lower(\"_UTF16\");\n        long _UTF16LE = fnv1a_64_lower(\"_UTF16LE\");\n        long _UTF32 = fnv1a_64_lower(\"_UTF32\");\n        long _UCS2 = fnv1a_64_lower(\"_UCS2\");\n        long _UJIS = fnv1a_64_lower(\"_UJIS\");\n        long X = fnv1a_64_lower(\"X\");\n        long TRANSFORM = fnv1a_64_lower(\"TRANSFORM\");\n        long NESTED = fnv1a_64_lower(\"NESTED\");\n        long RESTART = fnv1a_64_lower(\"RESTART\");\n\n        long ASOF = fnv1a_64_lower(\"ASOF\");\n        long JSON_SET = fnv1a_64_lower(\"JSON_SET\");\n        long JSONB_SET = fnv1a_64_lower(\"JSONB_SET\");\n\n        long TUNNEL = fnv1a_64_lower(\"TUNNEL\");\n        long DOWNLOAD = fnv1a_64_lower(\"DOWNLOAD\");\n        long UPLOAD = fnv1a_64_lower(\"UPLOAD\");\n        long CLONE = fnv1a_64_lower(\"CLONE\");\n        long INSTALL = fnv1a_64_lower(\"INSTALL\");\n        long UNLOAD = fnv1a_64_lower(\"UNLOAD\");\n\n        long AGGREGATE = fnv1a_64_lower(\"AGGREGATE\");\n        long UNIQUE = fnv1a_64_lower(\"UNIQUE\");\n        long PRIMARY = fnv1a_64_lower(\"PRIMARY\");\n        long THAN = fnv1a_64_lower(\"THAN\");\n        long PROPERTIES = fnv1a_64_lower(\"PROPERTIES\");\n        long SINGLE = fnv1a_64_lower(\"SINGLE\");\n        long RANDOM = fnv1a_64_lower(\"RANDOM\");\n\n        long TABLESPACE = fnv1a_64_lower(\"TABLESPACE\");\n        long DATANODE = fnv1a_64_lower(\"DATANODE\");\n        long DELTA = fnv1a_64_lower(\"DELTA\");\n        long PREFIX = fnv1a_64_lower(\"PREFIX\");\n        long NUMSTR = fnv1a_64_lower(\"NUMSTR\");\n        long NOCOMPRESS = fnv1a_64_lower(\"NOCOMPRESS\");\n        long COMPRESS_MODE = fnv1a_64_lower(\"COMPRESS_MODE\");\n        long BROKER = fnv1a_64_lower(\"BROKER\");\n        long INDEX = fnv1a_64_lower(\"INDEX\");\n        long SETPROJECT = fnv1a_64_lower(\"SETPROJECT\");\n        long NAMED_STRUCT = fnv1a_64_lower(\"NAMED_STRUCT\");\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/H2Utils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport org.h2.jdbc.JdbcConnection;\nimport org.h2.jdbcx.JdbcDataSourceFactory;\nimport org.h2.jdbcx.JdbcXAConnection;\nimport org.h2.message.TraceObject;\n\nimport javax.sql.XAConnection;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\npublic class H2Utils {\n    private static volatile Constructor<JdbcXAConnection> constructor;\n\n    private static volatile Method method;\n\n    public static final int XA_DATA_SOURCE = 13;\n\n    public static Object createJdbcDataSourceFactory() {\n        return new JdbcDataSourceFactory();\n    }\n\n    public static XAConnection createXAConnection(Object factory, Connection physicalConn) throws SQLException {\n        try {\n            if (constructor == null) {\n                constructor = JdbcXAConnection.class.getDeclaredConstructor(JdbcDataSourceFactory.class, int.class,\n                        JdbcConnection.class);\n                constructor.setAccessible(true);\n            }\n\n            int id = getNextId(XA_DATA_SOURCE);\n\n            return constructor.newInstance(factory, id, physicalConn);\n        } catch (Exception e) {\n            throw new SQLException(\"createXAConnection error\", e);\n        }\n    }\n\n    public static int getNextId(int type) throws Exception {\n        if (method == null) {\n            method = TraceObject.class.getDeclaredMethod(\"getNextId\", int.class);\n            method.setAccessible(true);\n        }\n\n        return (Integer) method.invoke(null, type);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/HexBin.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\n/**\n * format validation This class encodes/decodes hexadecimal data\n *\n * @author Jeffrey Rodriguez\n * @version $Id: HexBin.java,v 1.4 2007/07/19 04:38:32 ofung Exp $\n */\npublic final class HexBin {\n    private static final int BASE_LENGTH = 128;\n    private static final int LOOKUP_LENGTH = 16;\n    private static final byte[] HEX_NUMBER_TABLE = new byte[BASE_LENGTH];\n    private static final char[] UPPER_CHARS = new char[LOOKUP_LENGTH];\n    private static final char[] LOWER_CHARS = new char[LOOKUP_LENGTH];\n\n    static {\n        for (int i = 0; i < BASE_LENGTH; i++) {\n            HEX_NUMBER_TABLE[i] = -1;\n        }\n        for (int i = '9'; i >= '0'; i--) {\n            HEX_NUMBER_TABLE[i] = (byte) (i - '0');\n        }\n        for (int i = 'F'; i >= 'A'; i--) {\n            HEX_NUMBER_TABLE[i] = (byte) (i - 'A' + 10);\n        }\n        for (int i = 'f'; i >= 'a'; i--) {\n            HEX_NUMBER_TABLE[i] = (byte) (i - 'a' + 10);\n        }\n\n        for (int i = 0; i < 10; i++) {\n            UPPER_CHARS[i] = (char) ('0' + i);\n            LOWER_CHARS[i] = (char) ('0' + i);\n        }\n        for (int i = 10; i <= 15; i++) {\n            UPPER_CHARS[i] = (char) ('A' + i - 10);\n            LOWER_CHARS[i] = (char) ('a' + i - 10);\n        }\n    }\n\n    public static String encode(byte[] bytes) {\n        return encode(bytes, true);\n    }\n\n    public static String encode(byte[] bytes, boolean upperCase) {\n        if (bytes == null) {\n            return null;\n        }\n\n        final char[] chars = upperCase ? UPPER_CHARS : LOWER_CHARS;\n\n        char[] hex = new char[bytes.length * 2];\n        for (int i = 0; i < bytes.length; i++) {\n            int b = bytes[i] & 0xFF;\n            hex[i * 2] = chars[b >> 4];\n            hex[i * 2 + 1] = chars[b & 0xf];\n        }\n        return new String(hex);\n    }\n\n    /**\n     * Decode hex string to a byte array\n     *\n     * @param encoded encoded string\n     * @return return array of byte to encode\n     */\n    public static byte[] decode(String encoded) {\n        if (encoded == null) {\n            return null;\n        }\n\n        int lengthData = encoded.length();\n        if (lengthData % 2 != 0) {\n            return null;\n        }\n\n        char[] binaryData = encoded.toCharArray();\n        int lengthDecode = lengthData / 2;\n        byte[] decodedData = new byte[lengthDecode];\n        byte temp1, temp2;\n        char tempChar;\n        for (int i = 0; i < lengthDecode; i++) {\n            tempChar = binaryData[i * 2];\n            temp1 = (tempChar < BASE_LENGTH) ? HEX_NUMBER_TABLE[tempChar] : -1;\n            if (temp1 == -1) {\n                return null;\n            }\n            tempChar = binaryData[i * 2 + 1];\n            temp2 = (tempChar < BASE_LENGTH) ? HEX_NUMBER_TABLE[tempChar] : -1;\n            if (temp2 == -1) {\n                return null;\n            }\n            decodedData[i] = (byte) ((temp1 << 4) | temp2);\n        }\n        return decodedData;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/Histogram.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLongArray;\n\npublic class Histogram {\n    private final long[] ranges;\n    private final AtomicLongArray rangeCounters;\n\n    public Histogram(long... ranges) {\n        this.ranges = ranges;\n        this.rangeCounters = new AtomicLongArray(ranges.length + 1);\n    }\n\n    public static Histogram makeHistogram(int rangeCount) {\n        long[] rangeValues = new long[rangeCount];\n\n        for (int i = 0; i < rangeValues.length; ++i) {\n            rangeValues[i] = (long) Math.pow(10, i);\n        }\n\n        return new Histogram(rangeValues);\n    }\n\n    public Histogram(TimeUnit timeUnit, long... ranges) {\n        this.ranges = new long[ranges.length];\n        for (int i = 0; i < ranges.length; i++) {\n            this.ranges[i] = TimeUnit.MILLISECONDS.convert(ranges[i], timeUnit);\n        }\n\n        rangeCounters = new AtomicLongArray(ranges.length + 1);\n    }\n\n    public void reset() {\n        for (int i = 0; i < rangeCounters.length(); i++) {\n            rangeCounters.set(i, 0);\n        }\n    }\n\n    public void record(long millis) {\n        int index = rangeCounters.length() - 1;\n        for (int i = 0; i < ranges.length; ++i) {\n            if (millis < ranges[i]) {\n                index = i;\n                break;\n            }\n        }\n\n        rangeCounters.incrementAndGet(index);\n    }\n\n    public long get(int index) {\n        return rangeCounters.get(index);\n    }\n\n    public long[] toArray() {\n        long[] array = new long[rangeCounters.length()];\n        for (int i = 0; i < rangeCounters.length(); i++) {\n            array[i] = rangeCounters.get(i);\n        }\n        return array;\n    }\n\n    public long[] toArrayAndReset() {\n        long[] array = new long[rangeCounters.length()];\n        for (int i = 0; i < rangeCounters.length(); i++) {\n            array[i] = rangeCounters.getAndSet(i, 0);\n        }\n\n        return array;\n    }\n\n    public long[] getRanges() {\n        return ranges;\n    }\n\n    public long getValue(int index) {\n        return rangeCounters.get(index);\n    }\n\n    public long getSum() {\n        long sum = 0;\n        for (int i = 0; i < rangeCounters.length(); ++i) {\n            sum += rangeCounters.get(i);\n        }\n        return sum;\n    }\n\n    public String toString() {\n        StringBuilder buf = new StringBuilder();\n        buf.append('[');\n        for (int i = 0; i < rangeCounters.length(); ++i) {\n            if (i != 0) {\n                buf.append(',');\n            }\n            buf.append(rangeCounters.get(i));\n        }\n        buf.append(']');\n        return buf.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/HiveUtils.java",
    "content": "package com.alibaba.druid.util;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class HiveUtils {\n    private static Set<String> builtinDataTypes;\n\n    public static boolean isBuiltinDataType(String dataType) {\n        if (dataType == null) {\n            return false;\n        }\n\n        String table_lower = dataType.toLowerCase();\n\n        Set<String> dataTypes = builtinDataTypes;\n\n        if (dataTypes == null) {\n            dataTypes = new HashSet<String>();\n            loadDataTypes(dataTypes);\n            builtinDataTypes = dataTypes;\n        }\n\n        return dataTypes.contains(table_lower);\n    }\n\n    public static void loadDataTypes(Set<String> dataTypes) {\n        Utils.loadFromFile(\"META-INF/druid/parser/hive/builtin_datatypes\", dataTypes);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/JMXUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport javax.management.InstanceAlreadyExistsException;\nimport javax.management.JMException;\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\nimport javax.management.openmbean.*;\n\nimport java.lang.management.ManagementFactory;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic final class JMXUtils {\n    public static ObjectName register(String name, Object mbean) {\n        try {\n            ObjectName objectName = new ObjectName(name);\n\n            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n\n            try {\n                mbeanServer.registerMBean(mbean, objectName);\n            } catch (InstanceAlreadyExistsException ex) {\n                mbeanServer.unregisterMBean(objectName);\n                mbeanServer.registerMBean(mbean, objectName);\n            }\n\n            return objectName;\n        } catch (JMException e) {\n            throw new IllegalArgumentException(name, e);\n        }\n    }\n\n    public static void unregister(String name) {\n        try {\n            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n\n            mbeanServer.unregisterMBean(new ObjectName(name));\n        } catch (JMException e) {\n            throw new IllegalArgumentException(name, e);\n        }\n\n    }\n\n    private static final String[] THROWABLE_COMPOSITE_INDEX_NAMES = {\"message\", \"class\", \"stackTrace\"};\n    private static final String[] THROWABLE_COMPOSITE_INDEX_DESCRIPTIONS = {\"message\", \"class\", \"stackTrace\"};\n    private static final OpenType<?>[] THROWABLE_COMPOSITE_INDEX_TYPES = new OpenType<?>[]{SimpleType.STRING,\n            SimpleType.STRING, SimpleType.STRING};\n\n    private static CompositeType THROWABLE_COMPOSITE_TYPE;\n\n    public static CompositeType getThrowableCompositeType() throws JMException {\n        if (THROWABLE_COMPOSITE_TYPE == null) {\n            THROWABLE_COMPOSITE_TYPE = new CompositeType(\"Throwable\", \"Throwable\", THROWABLE_COMPOSITE_INDEX_NAMES,\n                    THROWABLE_COMPOSITE_INDEX_DESCRIPTIONS,\n                    THROWABLE_COMPOSITE_INDEX_TYPES);\n        }\n\n        return THROWABLE_COMPOSITE_TYPE;\n    }\n\n    public static CompositeData getErrorCompositeData(Throwable error) throws JMException {\n        if (error == null) {\n            return null;\n        }\n\n        Map<String, Object> map = new HashMap<String, Object>();\n\n        map.put(\"class\", error.getClass().getName());\n        map.put(\"message\", error.getMessage());\n\n        map.put(\"stackTrace\", Utils.getStackTrace(error));\n\n        return new CompositeDataSupport(getThrowableCompositeType(), map);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/JdbcConstants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport com.alibaba.druid.DbType;\n\npublic interface JdbcConstants {\n    DbType JTDS = DbType.jtds;\n\n    String MOCK = \"mock\";\n\n    DbType HSQL = DbType.hsql;\n\n    DbType DB2 = DbType.db2;\n\n    String DB2_DRIVER = \"com.ibm.db2.jcc.DB2Driver\"; // Type4\n    String DB2_DRIVER2 = \"COM.ibm.db2.jdbc.app.DB2Driver\"; // Type2\n    String DB2_DRIVER3 = \"COM.ibm.db2.jdbc.net.DB2Driver\"; // Type3\n\n    DbType POSTGRESQL = DbType.postgresql;\n    String POSTGRESQL_DRIVER = \"org.postgresql.Driver\";\n\n    DbType SYBASE = DbType.sybase;\n\n    DbType SQL_SERVER = DbType.sqlserver;\n    String SQL_SERVER_DRIVER = \"com.microsoft.jdbc.sqlserver.SQLServerDriver\";\n    String SQL_SERVER_DRIVER_SQLJDBC4 = \"com.microsoft.sqlserver.jdbc.SQLServerDriver\";\n    String SQL_SERVER_DRIVER_JTDS = \"net.sourceforge.jtds.jdbc.Driver\";\n\n    DbType ORACLE = DbType.oracle;\n    String ORACLE_DRIVER = \"oracle.jdbc.OracleDriver\";\n    String ORACLE_DRIVER2 = \"oracle.jdbc.driver.OracleDriver\";\n\n    DbType ALI_ORACLE = DbType.ali_oracle;\n    String ALI_ORACLE_DRIVER = \"com.alibaba.jdbc.AlibabaDriver\";\n\n    DbType MYSQL = DbType.mysql;\n    String MYSQL_DRIVER = \"com.mysql.jdbc.Driver\";\n    String MYSQL_DRIVER_6 = \"com.mysql.cj.jdbc.Driver\";\n    String MYSQL_DRIVER_603 = \"com.mysql.cj.api.MysqlConnection\";\n    String MYSQL_DRIVER_REPLICATE = \"com.mysql.jdbc.\";\n\n    String MARIADB = \"mariadb\";\n    String MARIADB_DRIVER = \"org.mariadb.jdbc.Driver\";\n\n    DbType TIDB = DbType.tidb;\n    String TIDB_DRIVER = \"io.tidb.bigdata.jdbc.TiDBDriver\";\n\n    DbType DERBY = DbType.derby;\n\n    String HBASE = \"hbase\";\n\n    DbType HIVE = DbType.hive;\n    String HIVE_DRIVER = \"org.apache.hive.jdbc.HiveDriver\";\n\n    DbType H2 = DbType.h2;\n    String H2_DRIVER = \"org.h2.Driver\";\n\n    DbType LEALONE = DbType.lealone;\n    String LEALONE_DRIVER = \"org.lealone.client.jdbc.JdbcDriver\";\n\n    DbType DM = DbType.dm;\n    String DM_DRIVER = \"dm.jdbc.driver.DmDriver\";\n\n    DbType KINGBASE = DbType.kingbase;\n    String KINGBASE_DRIVER = \"com.kingbase.Driver\";\n    String KINGBASE8_DRIVER = \"com.kingbase8.Driver\";\n\n    DbType GBASE = DbType.gbase;\n    String GBASE_DRIVER = \"com.gbase.jdbc.Driver\";\n\n    DbType XUGU = DbType.xugu;\n    String XUGU_DRIVER = \"com.xugu.cloudjdbc.Driver\";\n\n    DbType OCEANBASE = DbType.oceanbase;\n    DbType OCEANBASE_ORACLE = DbType.oceanbase_oracle;\n    String OCEANBASE_DRIVER = \"com.alipay.oceanbase.jdbc.Driver\";\n    String OCEANBASE_DRIVER2 = \"com.oceanbase.jdbc.Driver\";\n\n    DbType INFORMIX = DbType.informix;\n\n    /**\n     * 阿里云odps\n     */\n    DbType ODPS = DbType.odps;\n    String ODPS_DRIVER = \"com.aliyun.odps.jdbc.OdpsDriver\";\n\n    String TERADATA = \"teradata\";\n    String TERADATA_DRIVER = \"com.teradata.jdbc.TeraDriver\";\n\n    /**\n     * Log4JDBC\n     */\n    String LOG4JDBC = \"log4jdbc\";\n    String LOG4JDBC_DRIVER = \"net.sf.log4jdbc.DriverSpy\";\n\n    String PHOENIX = \"phoenix\";\n    String PHOENIX_DRIVER = \"org.apache.phoenix.jdbc.PhoenixDriver\";\n    DbType ENTERPRISEDB = DbType.edb;\n    String ENTERPRISEDB_DRIVER = \"com.edb.Driver\";\n\n    String KYLIN = \"kylin\";\n    String KYLIN_DRIVER = \"org.apache.kylin.jdbc.Driver\";\n\n    String SQLITE = \"sqlite\";\n    String SQLITE_DRIVER = \"org.sqlite.JDBC\";\n\n    String ALIYUN_ADS = \"aliyun_ads\";\n    DbType ALIYUN_DRDS = DbType.drds;\n\n    String PRESTO = \"presto\";\n    String PRESTO_DRIVER = \"com.facebook.presto.jdbc.PrestoDriver\";\n\n    String TRINO = \"trino\";\n    String TRINO_DRIVER = \"io.trino.jdbc.TrinoDriver\";\n\n    String ELASTIC_SEARCH = \"elastic_search\";\n\n    String ELASTIC_SEARCH_DRIVER = \"com.alibaba.xdriver.elastic.jdbc.ElasticDriver\";\n\n    DbType CLICKHOUSE = DbType.clickhouse;\n    String CLICKHOUSE_DRIVER = \"ru.yandex.clickhouse.ClickHouseDriver\";\n\n    String CLICKHOUSE_DRIVER_NEW = \"com.clickhouse.jdbc.ClickHouseDriver\";\n\n    String KDB = \"kdb\";\n    String KDB_DRIVER = \"com.inspur.jdbc.KdDriver\";\n\n    /**\n     * Alibaba Cloud PolarDB-Oracle 1.0\n     */\n    DbType POLARDB = DbType.polardb;\n    String POLARDB_DRIVER = \"com.aliyun.polardb.Driver\";\n    /**\n     * Alibaba Cloud PolarDB-Oracle 2.0\n     */\n    DbType POLARDB2 = DbType.polardb2;\n    String POLARDB2_DRIVER = \"com.aliyun.polardb2.Driver\";\n    /**\n     * GreenPlum\n     */\n    DbType GREENPLUM = DbType.greenplum;\n    String GREENPLUM_DRIVER = \"com.pivotal.jdbc.GreenplumDriver\";\n\n    /**\n     * oscar\n     */\n    DbType OSCAR = DbType.oscar;\n    String OSCAR_DRIVER = \"com.oscar.Driver\";\n\n    DbType TYDB = DbType.tydb;\n    String TYDB_DRIVER = \"com.dbcp.jdbc.Driver\";\n\n    String TAOS_DATA = \"com.taosdata.jdbc.TSDBDriver\";\n    String TAOS_DATA_RS = \"com.taosdata.jdbc.rs.RestfulDriver\";\n\n    String GOLDENDB_DRIVER = \"com.goldendb.jdbc.Driver\";\n\n    String GBASE8S_DRIVER = \"com.gbasedbt.jdbc.Driver\";\n\n    String OPENGAUSS_DRIVER = \"org.opengauss.Driver\";\n    String SUNDB = \"sundb\"; //科蓝数s据\n    String SUNDB_DRIVER = \"csii.sundb.jdbc.SundbDriver\";\n\n    String POLARDBX_DRIVER = \"com.alibaba.polardbx.Driver\";\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/JdbcSqlStatUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.lang.reflect.Method;\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\npublic class JdbcSqlStatUtils {\n    private static final Log LOG = LogFactory.getLog(JdbcSqlStatUtils.class);\n\n    @SuppressWarnings(\"unchecked\")\n    public static Map<String, Object> getData(Object jdbcSqlStat) {\n        try {\n            if (jdbcSqlStat.getClass() == JdbcSqlStat.class) {\n                return ((JdbcSqlStat) jdbcSqlStat).getData();\n            }\n\n            Method method = jdbcSqlStat.getClass().getMethod(\"getData\");\n            Object obj = method.invoke(jdbcSqlStat);\n            return (Map<String, Object>) obj;\n        } catch (Exception e) {\n            LOG.error(\"getData error\", e);\n            return null;\n        }\n    }\n\n    public static long[] rtrim(long[] array) {\n        int notZeroLen = array.length;\n        for (int i = array.length - 1; i >= 0; --i, notZeroLen--) {\n            if (array[i] != 0) {\n                break;\n            }\n        }\n\n        if (notZeroLen != array.length) {\n            array = Arrays.copyOf(array, notZeroLen);\n        }\n\n        return array;\n    }\n\n    public static <T> int get(T stat, AtomicIntegerFieldUpdater<T> updater, boolean reset) {\n        if (reset) {\n            return updater.getAndSet(stat, 0);\n        } else {\n            return updater.get(stat);\n        }\n    }\n\n    public static <T> long get(T stat, AtomicLongFieldUpdater<T> updater, boolean reset) {\n        if (reset) {\n            return updater.getAndSet(stat, 0);\n        } else {\n            return updater.get(stat);\n        }\n    }\n\n    public static long get(AtomicLong counter, boolean reset) {\n        if (reset) {\n            return counter.getAndSet(0);\n        } else {\n            return counter.get();\n        }\n    }\n\n    public static int get(AtomicInteger counter, boolean reset) {\n        if (reset) {\n            return counter.getAndSet(0);\n        } else {\n            return counter.get();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/JdbcUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport javax.sql.DataSource;\n\nimport java.io.Closeable;\nimport java.io.InputStream;\nimport java.io.PrintStream;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.*;\n\n/**\n * @author wenshao [szujobs@hotmail.com]\n */\npublic final class JdbcUtils implements JdbcConstants {\n    private static final Log LOG = LogFactory.getLog(JdbcUtils.class);\n\n    private static final Properties DRIVER_URL_MAPPING = new Properties();\n\n    private static Boolean mysql_driver_version_6;\n\n    private static Boolean clickhouse_driver_version_new;\n\n    static {\n        try {\n            ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();\n            if (ctxClassLoader != null) {\n                for (Enumeration<URL> e = ctxClassLoader.getResources(\"META-INF/druid-driver.properties\"); e.hasMoreElements(); ) {\n                    URL url = e.nextElement();\n\n                    Properties property = new Properties();\n\n                    InputStream is = null;\n                    try {\n                        is = url.openStream();\n                        property.load(is);\n                    } finally {\n                        JdbcUtils.close(is);\n                    }\n\n                    DRIVER_URL_MAPPING.putAll(property);\n                }\n            }\n        } catch (Exception e) {\n            LOG.error(\"load druid-driver.properties error\", e);\n        }\n    }\n\n    public static void close(Connection x) {\n        if (x == null) {\n            return;\n        }\n\n        try {\n            if (x.isClosed()) {\n                return;\n            }\n\n            x.close();\n        } catch (SQLRecoverableException e) {\n            // skip\n        } catch (Exception e) {\n            LOG.debug(\"close connection error\", e);\n        }\n    }\n\n    public static void close(Statement x) {\n        if (x == null) {\n            return;\n        }\n        try {\n            x.close();\n        } catch (Exception e) {\n            boolean printError = true;\n\n            if (e instanceof java.sql.SQLRecoverableException\n                    && \"Closed Connection\".equals(e.getMessage())\n            ) {\n                printError = false;\n            }\n\n            if (printError) {\n                LOG.debug(\"close statement error\", e);\n            }\n        }\n    }\n\n    public static void close(ResultSet x) {\n        if (x == null) {\n            return;\n        }\n        try {\n            x.close();\n        } catch (Exception e) {\n            LOG.debug(\"close result set error\", e);\n        }\n    }\n\n    public static void close(Closeable x) {\n        if (x == null) {\n            return;\n        }\n\n        try {\n            x.close();\n        } catch (Exception e) {\n            LOG.debug(\"close error\", e);\n        }\n    }\n\n    public static void close(Blob x) {\n        if (x == null) {\n            return;\n        }\n\n        try {\n            x.free();\n        } catch (Exception e) {\n            LOG.debug(\"close error\", e);\n        }\n    }\n\n    public static void close(Clob x) {\n        if (x == null) {\n            return;\n        }\n\n        try {\n            x.free();\n        } catch (Exception e) {\n            LOG.debug(\"close error\", e);\n        }\n    }\n\n    public static void printResultSet(ResultSet rs) throws SQLException {\n        printResultSet(rs, System.out);\n    }\n\n    public static void printResultSet(ResultSet rs, PrintStream out) throws SQLException {\n        printResultSet(rs, out, true, \"\\t\");\n    }\n\n    public static void printResultSet(ResultSet rs,\n                                      PrintStream out,\n                                      boolean printHeader,\n                                      String seperator) throws SQLException {\n        ResultSetMetaData metadata = rs.getMetaData();\n        int columnCount = metadata.getColumnCount();\n        if (printHeader) {\n            for (int columnIndex = 1; columnIndex <= columnCount; ++columnIndex) {\n                if (columnIndex != 1) {\n                    out.print(seperator);\n                }\n                out.print(metadata.getColumnName(columnIndex));\n            }\n        }\n\n        out.println();\n\n        while (rs.next()) {\n            for (int columnIndex = 1; columnIndex <= columnCount; ++columnIndex) {\n                if (columnIndex != 1) {\n                    out.print(seperator);\n                }\n\n                int type = metadata.getColumnType(columnIndex);\n\n                if (type == Types.VARCHAR || type == Types.CHAR || type == Types.NVARCHAR || type == Types.NCHAR) {\n                    out.print(rs.getString(columnIndex));\n                } else if (type == Types.DATE) {\n                    java.util.Date date = rs.getDate(columnIndex);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(date.toString());\n                    }\n                } else if (type == Types.BIT) {\n                    boolean value = rs.getBoolean(columnIndex);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Boolean.toString(value));\n                    }\n                } else if (type == Types.BOOLEAN) {\n                    boolean value = rs.getBoolean(columnIndex);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Boolean.toString(value));\n                    }\n                } else if (type == Types.TINYINT) {\n                    byte value = rs.getByte(columnIndex);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Byte.toString(value));\n                    }\n                } else if (type == Types.SMALLINT) {\n                    short value = rs.getShort(columnIndex);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Short.toString(value));\n                    }\n                } else if (type == Types.INTEGER) {\n                    int value = rs.getInt(columnIndex);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Integer.toString(value));\n                    }\n                } else if (type == Types.BIGINT) {\n                    long value = rs.getLong(columnIndex);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Long.toString(value));\n                    }\n                } else if (type == Types.TIMESTAMP || type == Types.TIMESTAMP_WITH_TIMEZONE) {\n                    out.print(String.valueOf(rs.getTimestamp(columnIndex)));\n                } else if (type == Types.DECIMAL) {\n                    out.print(String.valueOf(rs.getBigDecimal(columnIndex)));\n                } else if (type == Types.CLOB) {\n                    out.print(String.valueOf(rs.getString(columnIndex)));\n                } else if (type == Types.JAVA_OBJECT) {\n                    Object object = rs.getObject(columnIndex);\n\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(String.valueOf(object));\n                    }\n                } else if (type == Types.LONGVARCHAR) {\n                    Object object = rs.getString(columnIndex);\n\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(String.valueOf(object));\n                    }\n                } else if (type == Types.NULL) {\n                    out.print(\"null\");\n                } else {\n                    Object object = rs.getObject(columnIndex);\n\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        if (object instanceof byte[]) {\n                            byte[] bytes = (byte[]) object;\n                            String text = HexBin.encode(bytes);\n                            out.print(text);\n                        } else {\n                            out.print(String.valueOf(object));\n                        }\n                    }\n                }\n            }\n            out.println();\n        }\n    }\n\n    public static String getTypeName(int sqlType) {\n        switch (sqlType) {\n            case Types.ARRAY:\n                return \"ARRAY\";\n\n            case Types.BIGINT:\n                return \"BIGINT\";\n\n            case Types.BINARY:\n                return \"BINARY\";\n\n            case Types.BIT:\n                return \"BIT\";\n\n            case Types.BLOB:\n                return \"BLOB\";\n\n            case Types.BOOLEAN:\n                return \"BOOLEAN\";\n\n            case Types.CHAR:\n                return \"CHAR\";\n\n            case Types.CLOB:\n                return \"CLOB\";\n\n            case Types.DATALINK:\n                return \"DATALINK\";\n\n            case Types.DATE:\n                return \"DATE\";\n\n            case Types.DECIMAL:\n                return \"DECIMAL\";\n\n            case Types.DISTINCT:\n                return \"DISTINCT\";\n\n            case Types.DOUBLE:\n                return \"DOUBLE\";\n\n            case Types.FLOAT:\n                return \"FLOAT\";\n\n            case Types.INTEGER:\n                return \"INTEGER\";\n\n            case Types.JAVA_OBJECT:\n                return \"JAVA_OBJECT\";\n\n            case Types.LONGNVARCHAR:\n                return \"LONGNVARCHAR\";\n\n            case Types.LONGVARBINARY:\n                return \"LONGVARBINARY\";\n\n            case Types.NCHAR:\n                return \"NCHAR\";\n\n            case Types.NCLOB:\n                return \"NCLOB\";\n\n            case Types.NULL:\n                return \"NULL\";\n\n            case Types.NUMERIC:\n                return \"NUMERIC\";\n\n            case Types.NVARCHAR:\n                return \"NVARCHAR\";\n\n            case Types.REAL:\n                return \"REAL\";\n\n            case Types.REF:\n                return \"REF\";\n\n            case Types.ROWID:\n                return \"ROWID\";\n\n            case Types.SMALLINT:\n                return \"SMALLINT\";\n\n            case Types.SQLXML:\n                return \"SQLXML\";\n\n            case Types.STRUCT:\n                return \"STRUCT\";\n\n            case Types.TIME:\n                return \"TIME\";\n\n            case Types.TIMESTAMP:\n                return \"TIMESTAMP\";\n\n            case Types.TIMESTAMP_WITH_TIMEZONE:\n                return \"TIMESTAMP_WITH_TIMEZONE\";\n\n            case Types.TINYINT:\n                return \"TINYINT\";\n\n            case Types.VARBINARY:\n                return \"VARBINARY\";\n\n            case Types.VARCHAR:\n                return \"VARCHAR\";\n\n            default:\n                return \"OTHER\";\n\n        }\n    }\n\n    public static String getDriverClassName(String rawUrl) throws SQLException {\n        if (rawUrl == null) {\n            return null;\n        }\n\n        if (rawUrl.startsWith(\"jdbc:derby:\")) {\n            return \"org.apache.derby.jdbc.EmbeddedDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:mysql:\")) {\n            if (mysql_driver_version_6 == null) {\n                mysql_driver_version_6 = Utils.loadClass(\"com.mysql.cj.jdbc.Driver\") != null;\n            }\n\n            if (mysql_driver_version_6) {\n                return MYSQL_DRIVER_6;\n            } else {\n                return MYSQL_DRIVER;\n            }\n        } else if (rawUrl.startsWith(\"jdbc:log4jdbc:\")) {\n            return LOG4JDBC_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:mariadb:\")) {\n            return MARIADB_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:tidb:\")) {\n            return TIDB_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:oracle:\") //\n                || rawUrl.startsWith(\"JDBC:oracle:\")) {\n            return ORACLE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:alibaba:oracle:\")) {\n            return ALI_ORACLE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:oceanbase:\")) {\n            return OCEANBASE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:microsoft:\")) {\n            return \"com.microsoft.jdbc.sqlserver.SQLServerDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:sqlserver:\")) {\n            return \"com.microsoft.sqlserver.jdbc.SQLServerDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:sybase:Tds:\")) {\n            return \"com.sybase.jdbc2.jdbc.SybDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:jtds:\")) {\n            return \"net.sourceforge.jtds.jdbc.Driver\";\n        } else if (rawUrl.startsWith(\"jdbc:fake:\") || rawUrl.startsWith(\"jdbc:mock:\")) {\n            return \"com.alibaba.druid.mock.MockDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:postgresql:\")) {\n            return POSTGRESQL_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:edb:\")) {\n            return ENTERPRISEDB_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:odps:\")) {\n            return ODPS_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:hsqldb:\")) {\n            return \"org.hsqldb.jdbcDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:db2:\")) {\n            // Resolve the DB2 driver from JDBC URL\n            // Type2 COM.ibm.db2.jdbc.app.DB2Driver, url = jdbc:db2:databasename\n            // Type3 COM.ibm.db2.jdbc.net.DB2Driver, url = jdbc:db2:ServerIP:6789:databasename\n            // Type4 8.1+ com.ibm.db2.jcc.DB2Driver, url = jdbc:db2://ServerIP:50000/databasename\n            String prefix = \"jdbc:db2:\";\n            if (rawUrl.startsWith(prefix + \"//\")) { // Type4\n                return DB2_DRIVER; // \"com.ibm.db2.jcc.DB2Driver\";\n            } else {\n                String suffix = rawUrl.substring(prefix.length());\n                if (suffix.indexOf(':') > 0) { // Type3\n                    return DB2_DRIVER3; // COM.ibm.db2.jdbc.net.DB2Driver\n                } else { // Type2\n                    return DB2_DRIVER2; // COM.ibm.db2.jdbc.app.DB2Driver\n                }\n            }\n        } else if (rawUrl.startsWith(\"jdbc:sqlite:\")) {\n            return SQLITE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:ingres:\")) {\n            return \"com.ingres.jdbc.IngresDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:h2:\")) {\n            return H2_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:lealone:\")) {\n            return LEALONE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:mckoi:\")) {\n            return \"com.mckoi.JDBCDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:cloudscape:\")) {\n            return \"COM.cloudscape.core.JDBCDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:informix-sqli:\")) {\n            return \"com.informix.jdbc.IfxDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:timesten:\")) {\n            return \"com.timesten.jdbc.TimesTenDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:as400:\")) {\n            return \"com.ibm.as400.access.AS400JDBCDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:sapdb:\")) {\n            return \"com.sap.dbtech.jdbc.DriverSapDB\";\n        } else if (rawUrl.startsWith(\"jdbc:JSQLConnect:\")) {\n            return \"com.jnetdirect.jsql.JSQLDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:JTurbo:\")) {\n            return \"com.newatlanta.jturbo.driver.Driver\";\n        } else if (rawUrl.startsWith(\"jdbc:firebirdsql:\")) {\n            return \"org.firebirdsql.jdbc.FBDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:interbase:\")) {\n            return \"interbase.interclient.Driver\";\n        } else if (rawUrl.startsWith(\"jdbc:pointbase:\")) {\n            return \"com.pointbase.jdbc.jdbcUniversalDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:edbc:\")) {\n            return \"ca.edbc.jdbc.EdbcDriver\";\n        } else if (rawUrl.startsWith(\"jdbc:mimer:multi1:\")) {\n            return \"com.mimer.jdbc.Driver\";\n        } else if (rawUrl.startsWith(\"jdbc:dm:\")) {\n            return JdbcConstants.DM_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:kingbase:\")) {\n            return JdbcConstants.KINGBASE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:kingbase8:\")) {\n            return JdbcConstants.KINGBASE8_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:gbase:\")) {\n            return JdbcConstants.GBASE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:xugu:\")) {\n            return JdbcConstants.XUGU_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:hive:\")) {\n            return JdbcConstants.HIVE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:hive2:\")) {\n            return JdbcConstants.HIVE_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:phoenix:thin:\")) {\n            return \"org.apache.phoenix.queryserver.client.Driver\";\n        } else if (rawUrl.startsWith(\"jdbc:phoenix://\")) {\n            return JdbcConstants.PHOENIX_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:kylin:\")) {\n            return JdbcConstants.KYLIN_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:elastic:\")) {\n            return JdbcConstants.ELASTIC_SEARCH_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:clickhouse:\")) {\n            if (clickhouse_driver_version_new == null) {\n                clickhouse_driver_version_new = Utils.loadClass(JdbcConstants.CLICKHOUSE_DRIVER_NEW) != null;\n            }\n            if (clickhouse_driver_version_new) {\n                return JdbcConstants.CLICKHOUSE_DRIVER_NEW;\n            } else {\n                return JdbcConstants.CLICKHOUSE_DRIVER;\n            }\n        } else if (rawUrl.startsWith(\"jdbc:presto:\")) {\n            return JdbcConstants.PRESTO_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:trino:\")) {\n            return JdbcConstants.TRINO_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:inspur:\")) {\n            return JdbcConstants.KDB_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:polardb\")) {\n            if (rawUrl.startsWith(\"jdbc:polardb2:\")) {\n                return JdbcConstants.POLARDB2_DRIVER;\n            } else if (rawUrl.startsWith(\"jdbc:polardbx:\")) {\n                return JdbcConstants.POLARDBX_DRIVER;\n            }\n            return JdbcConstants.POLARDB_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:highgo:\")) {\n            return \"com.highgo.jdbc.Driver\";\n        } else if (rawUrl.startsWith(\"jdbc:oscar\")) {\n            return JdbcConstants.OSCAR_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:dbcp:\")) {\n            return JdbcConstants.TYDB_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:opengauss:\")) {\n            return JdbcConstants.OPENGAUSS_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:TAOS:\")) {\n            return JdbcConstants.TAOS_DATA;\n        } else if (rawUrl.startsWith(\"jdbc:TAOS-RS:\")) {\n            return JdbcConstants.TAOS_DATA_RS;\n        } else if (rawUrl.startsWith(\"jdbc:gbasedbt-sqli:\")) {\n            return JdbcConstants.GBASE8S_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:sundb:\")) {\n            return JdbcConstants.SUNDB_DRIVER;\n        } else if (rawUrl.startsWith(\"jdbc:gaussdb:\")) {\n            return \"com.huawei.gaussdb.jdbc.Driver\";\n        } else {\n            throw new SQLException(\"unknown jdbc driver : \" + rawUrl);\n        }\n    }\n\n    public static DbType getDbTypeRaw(String rawUrl, String driverClassName) {\n        if (rawUrl == null) {\n            return null;\n        }\n\n        if (rawUrl.startsWith(\"jdbc:derby:\") || rawUrl.startsWith(\"jdbc:log4jdbc:derby:\")) {\n            return DbType.derby;\n        } else if (rawUrl.startsWith(\"jdbc:mysql:\") || rawUrl.startsWith(\"jdbc:cobar:\")\n                || rawUrl.startsWith(\"jdbc:log4jdbc:mysql:\")) {\n            return DbType.mysql;\n        } else if (rawUrl.startsWith(\"jdbc:goldendb:\")) {\n            return DbType.mysql;\n        } else if (rawUrl.startsWith(\"jdbc:mariadb:\")) {\n            return DbType.mariadb;\n        } else if (rawUrl.startsWith(\"jdbc:tidb:\")) {\n            return DbType.tidb;\n        } else if (rawUrl.startsWith(\"jdbc:oracle:\") || rawUrl.startsWith(\"jdbc:log4jdbc:oracle:\")) {\n            return DbType.oracle;\n        } else if (rawUrl.startsWith(\"jdbc:alibaba:oracle:\")) {\n            return DbType.ali_oracle;\n        } else if (rawUrl.startsWith(\"jdbc:oceanbase:oracle:\")) {\n            return DbType.oceanbase_oracle;\n        } else if (rawUrl.startsWith(\"jdbc:oceanbase:\")) {\n            return DbType.oceanbase;\n        } else if (rawUrl.startsWith(\"jdbc:microsoft:\") || rawUrl.startsWith(\"jdbc:log4jdbc:microsoft:\")) {\n            return DbType.sqlserver;\n        } else if (rawUrl.startsWith(\"jdbc:sqlserver:\") || rawUrl.startsWith(\"jdbc:log4jdbc:sqlserver:\")) {\n            return DbType.sqlserver;\n        } else if (rawUrl.startsWith(\"jdbc:sybase:Tds:\") || rawUrl.startsWith(\"jdbc:log4jdbc:sybase:\")) {\n            return DbType.sybase;\n        } else if (rawUrl.startsWith(\"jdbc:jtds:\") || rawUrl.startsWith(\"jdbc:log4jdbc:jtds:\")) {\n            return DbType.jtds;\n        } else if (rawUrl.startsWith(\"jdbc:fake:\") || rawUrl.startsWith(\"jdbc:mock:\")) {\n            return DbType.mock;\n        } else if (rawUrl.startsWith(\"jdbc:postgresql:\") || rawUrl.startsWith(\"jdbc:log4jdbc:postgresql:\")) {\n            return DbType.postgresql;\n        } else if (rawUrl.startsWith(\"jdbc:edb:\")) {\n            return DbType.edb;\n        } else if (rawUrl.startsWith(\"jdbc:hsqldb:\") || rawUrl.startsWith(\"jdbc:log4jdbc:hsqldb:\")) {\n            return DbType.hsql;\n        } else if (rawUrl.startsWith(\"jdbc:odps:\")) {\n            return DbType.odps;\n        } else if (rawUrl.startsWith(\"jdbc:db2:\")) {\n            return DbType.db2;\n        } else if (rawUrl.startsWith(\"jdbc:sqlite:\")) {\n            return DbType.sqlite;\n        } else if (rawUrl.startsWith(\"jdbc:ingres:\")) {\n            return DbType.ingres;\n        } else if (rawUrl.startsWith(\"jdbc:h2:\") || rawUrl.startsWith(\"jdbc:log4jdbc:h2:\")) {\n            return DbType.h2;\n        } else if (rawUrl.startsWith(\"jdbc:lealone:\")) {\n            return DbType.lealone;\n        } else if (rawUrl.startsWith(\"jdbc:mckoi:\")) {\n            return DbType.mock;\n        } else if (rawUrl.startsWith(\"jdbc:cloudscape:\")) {\n            return DbType.cloudscape;\n        } else if (rawUrl.startsWith(\"jdbc:informix-sqli:\") || rawUrl.startsWith(\"jdbc:log4jdbc:informix-sqli:\")) {\n            return DbType.informix;\n        } else if (rawUrl.startsWith(\"jdbc:timesten:\")) {\n            return DbType.timesten;\n        } else if (rawUrl.startsWith(\"jdbc:as400:\")) {\n            return DbType.as400;\n        } else if (rawUrl.startsWith(\"jdbc:sapdb:\")) {\n            return DbType.sapdb;\n        } else if (rawUrl.startsWith(\"jdbc:JSQLConnect:\")) {\n            return DbType.JSQLConnect;\n        } else if (rawUrl.startsWith(\"jdbc:JTurbo:\")) {\n            return DbType.JTurbo;\n        } else if (rawUrl.startsWith(\"jdbc:firebirdsql:\")) {\n            return DbType.firebirdsql;\n        } else if (rawUrl.startsWith(\"jdbc:interbase:\")) {\n            return DbType.interbase;\n        } else if (rawUrl.startsWith(\"jdbc:pointbase:\")) {\n            return DbType.pointbase;\n        } else if (rawUrl.startsWith(\"jdbc:edbc:\")) {\n            return DbType.edbc;\n        } else if (rawUrl.startsWith(\"jdbc:mimer:multi1:\")) {\n            return DbType.mimer;\n        } else if (rawUrl.startsWith(\"jdbc:dm:\")) {\n            return JdbcConstants.DM;\n        } else if (rawUrl.startsWith(\"jdbc:kingbase:\") || rawUrl.startsWith(\"jdbc:kingbase8:\")) {\n            return JdbcConstants.KINGBASE;\n        } else if (rawUrl.startsWith(\"jdbc:gbase:\")) {\n            return JdbcConstants.GBASE;\n        } else if (rawUrl.startsWith(\"jdbc:xugu:\")) {\n            return JdbcConstants.XUGU;\n        } else if (rawUrl.startsWith(\"jdbc:log4jdbc:\")) {\n            return DbType.log4jdbc;\n        } else if (rawUrl.startsWith(\"jdbc:hive:\")) {\n            return DbType.hive;\n        } else if (rawUrl.startsWith(\"jdbc:hive2:\")) {\n            return DbType.hive;\n        } else if (rawUrl.startsWith(\"jdbc:phoenix:\")) {\n            return DbType.phoenix;\n        } else if (rawUrl.startsWith(\"jdbc:kylin:\")) {\n            return DbType.kylin;\n        } else if (rawUrl.startsWith(\"jdbc:elastic:\")) {\n            return DbType.elastic_search;\n        } else if (rawUrl.startsWith(\"jdbc:clickhouse:\")) {\n            return DbType.clickhouse;\n        } else if (rawUrl.startsWith(\"jdbc:presto:\")) {\n            return DbType.presto;\n        } else if (rawUrl.startsWith(\"jdbc:trino:\")) {\n            return DbType.trino;\n        } else if (rawUrl.startsWith(\"jdbc:inspur:\")) {\n            return DbType.kdb;\n        } else if (rawUrl.startsWith(\"jdbc:polardb\")) {\n            if (rawUrl.startsWith(\"jdbc:polardb2:\")) {\n                return DbType.polardb2;\n            } else if (rawUrl.startsWith(\"jdbc:polardbx:\")) {\n                return DbType.polardbx;\n            }\n            return DbType.polardb;\n        } else if (rawUrl.startsWith(\"jdbc:highgo:\")) {\n            return DbType.highgo;\n        } else if (rawUrl.startsWith(\"jdbc:pivotal:greenplum:\") || rawUrl.startsWith(\"jdbc:datadirect:greenplum:\")) {\n            return DbType.greenplum;\n        } else if (rawUrl.startsWith(\"jdbc:opengauss:\") || rawUrl.startsWith(\"jdbc:gaussdb:\") || rawUrl.startsWith(\"jdbc:dws:iam:\")) {\n            return DbType.gaussdb;\n        } else if (rawUrl.startsWith(\"jdbc:TAOS:\") || rawUrl.startsWith(\"jdbc:TAOS-RS:\")) {\n            return DbType.taosdata;\n        } else if (rawUrl.startsWith(\"jdbc:oscar:\")) {\n            return DbType.oscar;\n        } else if (rawUrl.startsWith(\"jdbc:sundb:\")) {\n            return DbType.sundb;\n        } else {\n            return null;\n        }\n    }\n\n    public static String getDbType(String rawUrl, String driverClassName) {\n        DbType dbType = getDbTypeRaw(rawUrl, driverClassName);\n\n        if (dbType == null) {\n            return null;\n        }\n\n        return dbType.name();\n    }\n\n    public static Driver createDriver(String driverClassName) throws SQLException {\n        return createDriver(null, driverClassName);\n    }\n\n    public static Driver createDriver(ClassLoader classLoader, String driverClassName) throws SQLException {\n        Class<?> clazz = null;\n        if (classLoader != null) {\n            try {\n                clazz = classLoader.loadClass(driverClassName);\n            } catch (ClassNotFoundException e) {\n                // skip\n            }\n        }\n\n        if (clazz == null) {\n            try {\n                ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();\n                if (contextLoader != null) {\n                    clazz = contextLoader.loadClass(driverClassName);\n                }\n            } catch (ClassNotFoundException e) {\n                // skip\n            }\n        }\n\n        if (clazz == null) {\n            try {\n                clazz = Class.forName(driverClassName);\n            } catch (ClassNotFoundException e) {\n                throw new SQLException(e.getMessage(), e);\n            }\n        }\n\n        try {\n            return (Driver) clazz.newInstance();\n        } catch (IllegalAccessException e) {\n            throw new SQLException(e.getMessage(), e);\n        } catch (InstantiationException e) {\n            throw new SQLException(e.getMessage(), e);\n        }\n    }\n\n    public static int executeUpdate(DataSource dataSource, String sql, Object... parameters) throws SQLException {\n        return executeUpdate(dataSource, sql, Arrays.asList(parameters));\n    }\n\n    public static int executeUpdate(DataSource dataSource, String sql, List<Object> parameters) throws SQLException {\n        Connection conn = null;\n        try {\n            conn = dataSource.getConnection();\n            return executeUpdate(conn, sql, parameters);\n        } finally {\n            close(conn);\n        }\n    }\n\n    public static int executeUpdate(Connection conn, String sql, List<Object> parameters) throws SQLException {\n        PreparedStatement stmt = null;\n\n        int updateCount;\n        try {\n            stmt = conn.prepareStatement(sql);\n\n            setParameters(stmt, parameters);\n\n            updateCount = stmt.executeUpdate();\n        } finally {\n            JdbcUtils.close(stmt);\n        }\n\n        return updateCount;\n    }\n\n    public static void execute(DataSource dataSource, String sql, Object... parameters) throws SQLException {\n        execute(dataSource, sql, Arrays.asList(parameters));\n    }\n\n    public static void execute(DataSource dataSource, String sql, List<Object> parameters) throws SQLException {\n        Connection conn = null;\n        try {\n            conn = dataSource.getConnection();\n            execute(conn, sql, parameters);\n        } finally {\n            close(conn);\n        }\n    }\n\n    public static void execute(Connection conn, String sql) throws SQLException {\n        execute(conn, sql, Collections.emptyList());\n    }\n\n    public static void execute(Connection conn, String sql, List<Object> parameters) throws SQLException {\n        PreparedStatement stmt = null;\n\n        try {\n            stmt = conn.prepareStatement(sql);\n\n            setParameters(stmt, parameters);\n\n            stmt.executeUpdate();\n        } finally {\n            JdbcUtils.close(stmt);\n        }\n    }\n\n    public static List<Map<String, Object>> executeQuery(DataSource dataSource, String sql, Object... parameters)\n            throws SQLException {\n        return executeQuery(dataSource, sql, Arrays.asList(parameters));\n    }\n\n    public static List<Map<String, Object>> executeQuery(DataSource dataSource, String sql, List<Object> parameters)\n            throws SQLException {\n        Connection conn = null;\n        try {\n            conn = dataSource.getConnection();\n            return executeQuery(conn, sql, parameters);\n        } finally {\n            close(conn);\n        }\n    }\n\n    public static List<Map<String, Object>> executeQuery(Connection conn, String sql, List<Object> parameters)\n            throws SQLException {\n        List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();\n\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            stmt = conn.prepareStatement(sql);\n\n            setParameters(stmt, parameters);\n\n            rs = stmt.executeQuery();\n\n            ResultSetMetaData rsMeta = rs.getMetaData();\n\n            while (rs.next()) {\n                Map<String, Object> row = new LinkedHashMap<String, Object>();\n\n                for (int i = 0, size = rsMeta.getColumnCount(); i < size; ++i) {\n                    String columName = rsMeta.getColumnLabel(i + 1);\n                    Object value = rs.getObject(i + 1);\n                    row.put(columName, value);\n                }\n\n                rows.add(row);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n        }\n\n        return rows;\n    }\n\n    private static void setParameters(PreparedStatement stmt, List<Object> parameters) throws SQLException {\n        for (int i = 0, size = parameters.size(); i < size; ++i) {\n            Object param = parameters.get(i);\n            stmt.setObject(i + 1, param);\n        }\n    }\n\n    public static void insertToTable(DataSource dataSource, String tableName, Map<String, Object> data)\n            throws SQLException {\n        Connection conn = null;\n        try {\n            conn = dataSource.getConnection();\n            insertToTable(conn, tableName, data);\n        } finally {\n            close(conn);\n        }\n    }\n\n    public static void insertToTable(Connection conn, String tableName, Map<String, Object> data) throws SQLException {\n        String sql = makeInsertToTableSql(tableName, data.keySet());\n        List<Object> parameters = new ArrayList<Object>(data.values());\n        execute(conn, sql, parameters);\n    }\n\n    public static String makeInsertToTableSql(String tableName, Collection<String> names) {\n        StringBuilder sql = new StringBuilder() //\n                .append(\"insert into \") //\n                .append(tableName) //\n                .append(\"(\");\n\n        int nameCount = 0;\n        for (String name : names) {\n            if (nameCount > 0) {\n                sql.append(\",\");\n            }\n            sql.append(name);\n            nameCount++;\n        }\n        sql.append(\") values (\");\n        for (int i = 0; i < nameCount; ++i) {\n            if (i != 0) {\n                sql.append(\",\");\n            }\n            sql.append(\"?\");\n        }\n        sql.append(\")\");\n\n        return sql.toString();\n    }\n\n    public static <T> void executeQuery(\n            DataSource dataSource,\n            ResultSetConsumer<T> consumer,\n            String sql,\n            Object... parameters\n    ) throws SQLException {\n        Connection conn = null;\n        PreparedStatement stmt = null;\n        ResultSet rs = null;\n        try {\n            conn = dataSource.getConnection();\n            stmt = conn.prepareStatement(sql);\n            for (int i = 0; i < parameters.length; ++i) {\n                stmt.setObject(i + 1, parameters[i]);\n            }\n            rs = stmt.executeQuery();\n            while (rs.next()) {\n                if (consumer != null) {\n                    T object = consumer.apply(rs);\n                    consumer.accept(object);\n                }\n            }\n        } finally {\n            close(rs);\n            close(stmt);\n            close(conn);\n        }\n    }\n\n    public static List<String> showTables(Connection conn, DbType dbType) throws SQLException {\n        if (isMysqlDbType(dbType)) {\n            return MySqlUtils.showTables(conn);\n        }\n\n        if (dbType == DbType.oracle || dbType == DbType.oceanbase_oracle) {\n            return OracleUtils.showTables(conn);\n        }\n\n        if (dbType == DbType.postgresql || dbType == DbType.polardb2) {\n            return PGUtils.showTables(conn);\n        }\n        throw new SQLException(\"show tables dbType not support for \" + dbType);\n    }\n\n    public static String getCreateTableScript(Connection conn, DbType dbType) throws SQLException {\n        return getCreateTableScript(conn, dbType, true, true);\n    }\n\n    public static String getCreateTableScript(Connection conn,\n                                              DbType dbType,\n                                              boolean sorted,\n                                              boolean simplify) throws SQLException {\n        if (isMysqlDbType(dbType)) {\n            return MySqlUtils.getCreateTableScript(conn, sorted, simplify);\n        }\n\n        if (dbType == DbType.oracle || dbType == DbType.oceanbase_oracle) {\n            return OracleUtils.getCreateTableScript(conn, sorted, simplify);\n        }\n\n        throw new SQLException(\"getCreateTableScript dbType not support for \" + dbType);\n    }\n\n    public static boolean isMySqlDriver(String driverClassName) {\n        return driverClassName.equals(JdbcConstants.MYSQL_DRIVER) //\n                || driverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)\n                || driverClassName.equals(JdbcConstants.MYSQL_DRIVER_603)\n                || driverClassName.equals(JdbcConstants.MYSQL_DRIVER_REPLICATE);\n    }\n\n    public static boolean isOracleDbType(String dbType) {\n        return DbType.oracle.name().equals(dbType) || //\n                DbType.oceanbase_oracle.name().equals(dbType) || //\n                DbType.ali_oracle.name().equalsIgnoreCase(dbType);\n    }\n\n    public static boolean isOracleDbType(DbType dbType) {\n        return DbType.oracle == dbType || //\n                DbType.oceanbase_oracle == dbType || //\n                DbType.ali_oracle == dbType;\n    }\n\n    public static boolean isMysqlDbType(String dbTypeName) {\n        return isMysqlDbType(\n                DbType.of(dbTypeName));\n    }\n\n    public static boolean isMysqlDbType(DbType dbType) {\n        if (dbType == null) {\n            return false;\n        }\n\n        switch (dbType) {\n            case mysql:\n            case oceanbase:\n            case ads:\n            case drds:\n            case mariadb:\n            case tidb:\n            case h2:\n            case lealone:\n            case goldendb:\n            case polardbx:\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public static boolean isPgsqlDbType(String dbTypeName) {\n        return isPgsqlDbType(\n                DbType.of(dbTypeName)\n        );\n    }\n\n    public static boolean isPgsqlDbType(DbType dbType) {\n        if (dbType == null) {\n            return false;\n        }\n\n        switch (dbType) {\n            case postgresql:\n            case edb:\n            case polardb:\n            case greenplum:\n            case gaussdb:\n            case hologres:\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public static boolean isSqlserverDbType(String dbTypeName) {\n        return isSqlserverDbType(\n                DbType.of(dbTypeName));\n    }\n\n    public static boolean isSqlserverDbType(DbType dbType) {\n        if (dbType == null) {\n            return false;\n        }\n\n        switch (dbType) {\n            case sqlserver:\n            case jtds:\n                return true;\n            default:\n                return false;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/LRUCache.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\npublic class LRUCache<K, V> extends LinkedHashMap<K, V> {\n    private static final long serialVersionUID = 1L;\n    private final int maxSize;\n\n    public LRUCache(int maxSize) {\n        this(maxSize, 16, 0.75f, false);\n    }\n\n    public LRUCache(int maxSize, int initialCapacity, float loadFactor, boolean accessOrder) {\n        super(initialCapacity, loadFactor, accessOrder);\n        this.maxSize = maxSize;\n    }\n\n    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {\n        return this.size() > this.maxSize;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/ListDG.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\n/**\n * Java: 无回路有向图(Directed Acyclic Graph)的拓扑排序\n * 该DAG图是通过邻接表实现的。\n * <p>\n * author skywang\n * date 2014/04/22\n */\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Queue;\n\npublic class ListDG {\n    public static class Edge {\n        public Object from;\n        public Object to;\n\n        public Edge(Object from, Object to) {\n            this.from = from;\n            this.to = to;\n        }\n    }\n\n    // 邻接表中表对应的链表的顶点\n    private static class ENode {\n        int ivex;       // 该边所指向的顶点的位置\n        ENode nextEdge; // 指向下一条弧的指针\n    }\n\n    // 邻接表中表的顶点\n    private static class VNode {\n        Object data;          // 顶点信息\n        ENode firstEdge;    // 指向第一条依附该顶点的弧\n    }\n\n    private List<VNode> mVexs;  // 顶点数组\n\n    /*\n     * 创建图(用已提供的矩阵)\n     *\n     * 参数说明：\n     *     vexs  -- 顶点数组\n     *     edges -- 边数组\n     */\n    public ListDG(List vexs, List<Edge> edges) {\n        // 初始化\"顶点数\"和\"边数\"\n        int vlen = vexs.size();\n        int elen = edges.size();\n\n        // 初始化\"顶点\"\n        mVexs = new ArrayList<VNode>();\n        for (int i = 0; i < vlen; i++) {\n            // 新建VNode\n            VNode vnode = new VNode();\n            vnode.data = vexs.get(i);\n            vnode.firstEdge = null;\n            // 将vnode添加到数组mVexs中\n            mVexs.add(vnode);\n        }\n\n        // 初始化\"边\"\n        for (int i = 0; i < elen; i++) {\n            // 读取边的起始顶点和结束顶点\n            Object c1 = edges.get(i).from;\n            Object c2 = edges.get(i).to;\n            // 读取边的起始顶点和结束顶点\n            int p1 = getPosition(edges.get(i).from);\n            int p2 = getPosition(edges.get(i).to);\n\n            // 初始化node1\n            ENode node1 = new ENode();\n            node1.ivex = p2;\n            // 将node1链接到\"p1所在链表的末尾\"\n            if (mVexs.get(p1).firstEdge == null) {\n                mVexs.get(p1).firstEdge = node1;\n            } else {\n                linkLast(mVexs.get(p1).firstEdge, node1);\n            }\n        }\n    }\n\n    /*\n     * 将node节点链接到list的最后\n     */\n    private void linkLast(ENode list, ENode node) {\n        ENode p = list;\n\n        while (p.nextEdge != null) {\n            p = p.nextEdge;\n        }\n        p.nextEdge = node;\n    }\n\n    /*\n     * 返回ch位置\n     */\n    private int getPosition(Object ch) {\n        for (int i = 0; i < mVexs.size(); i++) {\n            if (mVexs.get(i).data == ch) {\n                return i;\n            }\n        }\n        return -1;\n    }\n\n    /*\n     * 深度优先搜索遍历图的递归实现\n     */\n    private void DFS(int i, boolean[] visited) {\n        ENode node;\n\n        visited[i] = true;\n        node = mVexs.get(i).firstEdge;\n        while (node != null) {\n            if (!visited[node.ivex]) {\n                DFS(node.ivex, visited);\n            }\n            node = node.nextEdge;\n        }\n    }\n\n    /*\n     * 深度优先搜索遍历图\n     */\n    public void DFS() {\n        boolean[] visited = new boolean[mVexs.size()];       // 顶点访问标记\n\n        // 初始化所有顶点都没有被访问\n        for (int i = 0; i < mVexs.size(); i++) {\n            visited[i] = false;\n        }\n\n        for (int i = 0; i < mVexs.size(); i++) {\n            if (!visited[i]) {\n                DFS(i, visited);\n            }\n        }\n    }\n\n    /*\n     * 广度优先搜索（类似于树的层次遍历）\n     */\n    public void BFS() {\n        int head = 0;\n        int rear = 0;\n        int[] queue = new int[mVexs.size()];            // 辅组队列\n        boolean[] visited = new boolean[mVexs.size()];  // 顶点访问标记\n\n        for (int i = 0; i < mVexs.size(); i++) {\n            visited[i] = false;\n        }\n\n        for (int i = 0; i < mVexs.size(); i++) {\n            if (!visited[i]) {\n                visited[i] = true;\n                System.out.printf(\"%c \", mVexs.get(i).data);\n                queue[rear++] = i;  // 入队列\n            }\n\n            while (head != rear) {\n                int j = queue[head++];  // 出队列\n                ENode node = mVexs.get(j).firstEdge;\n                while (node != null) {\n                    int k = node.ivex;\n                    if (!visited[k]) {\n                        visited[k] = true;\n                        System.out.printf(\"%c \", mVexs.get(k).data);\n                        queue[rear++] = k;\n                    }\n                    node = node.nextEdge;\n                }\n            }\n        }\n    }\n\n    /*\n     * 打印矩阵队列图\n     */\n    public void print() {\n        System.out.print(\"== List Graph:\\n\");\n        for (int i = 0; i < mVexs.size(); i++) {\n            System.out.printf(\"%d(%c): \", i, mVexs.get(i).data);\n            ENode node = mVexs.get(i).firstEdge;\n            while (node != null) {\n                System.out.printf(\"%d(%c) \", node.ivex, mVexs.get(node.ivex).data);\n                node = node.nextEdge;\n            }\n        }\n    }\n\n    public boolean topologicalSort() {\n        return topologicalSort(new Object[mVexs.size()]);\n    }\n\n    /*\n     * 拓扑排序\n     *\n     * 返回值：\n     *     true 成功排序，并输入结果\n     *     false 失败(该有向图是有环的)\n     */\n    public boolean topologicalSort(Object[] tops) {\n        int index = 0;\n        int num = mVexs.size();\n        int[] ins;               // 入度数组\n        //Object[] tops;             // 拓扑排序结果数组，记录每个节点的排序后的序号。\n        Queue<Integer> queue;    // 辅组队列\n\n        ins = new int[num];\n        //tops  = new Object[num];\n        queue = new LinkedList<Integer>();\n\n        // 统计每个顶点的入度数\n        for (int i = 0; i < num; i++) {\n            ENode node = mVexs.get(i).firstEdge;\n            while (node != null) {\n                ins[node.ivex]++;\n                node = node.nextEdge;\n            }\n        }\n\n        // 将所有入度为0的顶点入队列\n        for (int i = 0; i < num; i++) {\n            if (ins[i] == 0) {\n                queue.offer(i);                  // 入队列\n            }\n        }\n\n        while (!queue.isEmpty()) {               // 队列非空\n            int j = queue.poll().intValue();     // 出队列。j是顶点的序号\n            tops[index++] = mVexs.get(j).data;   // 将该顶点添加到tops中，tops是排序结果\n            ENode node = mVexs.get(j).firstEdge; // 获取以该顶点为起点的出边队列\n\n            // 将与\"node\"关联的节点的入度减1；\n            // 若减1之后，该节点的入度为0；则将该节点添加到队列中。\n            while (node != null) {\n                // 将节点(序号为node.ivex)的入度减1。\n                ins[node.ivex]--;\n                // 若节点的入度为0，则将其\"入队列\"\n                if (ins[node.ivex] == 0) {\n                    queue.offer(node.ivex);    // 入队列\n                }\n\n                node = node.nextEdge;\n            }\n        }\n\n        if (index != num) {\n            return false;\n        }\n\n        return true;\n    }\n\n//    public static void main(String[] args) {\n//        Object[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};\n//        Edge[] edges = new Edge[]{\n//                new Edge(vexs[0], vexs[6]),\n//                new Edge(vexs[1], vexs[0]),\n//                new Edge(vexs[1], vexs[3]),\n//                new Edge(vexs[2], vexs[5]),\n//                new Edge(vexs[2], vexs[6]),\n//                new Edge(vexs[3], vexs[4]),\n//                new Edge(vexs[3], vexs[5])};\n//        ListDG pG;\n//\n//        // 自定义\"图\"(输入矩阵队列)\n//        //pG = new ListDG();\n//        // 采用已有的\"图\"\n//        pG = new ListDG(Arrays.asList(vexs), Arrays.asList(edges));\n//\n//        pG.print();   // 打印图\n//        //pG.DFS();     // 深度优先遍历\n//        //pG.BFS();     // 广度优先遍历\n//        pG.topologicalSort();     // 拓扑排序\n//    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/MapComparator.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.lang.reflect.Array;\nimport java.text.Collator;\nimport java.util.Comparator;\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * @author sandzhang[sandzhangtoo@gmail.com]\n */\npublic class MapComparator<K extends Object, V extends Object> implements Comparator<Map<K, V>> {\n    private boolean isDesc;\n    private K orderByKey;\n\n    public MapComparator(K orderByKey, boolean isDesc) {\n        this.orderByKey = orderByKey;\n        this.isDesc = isDesc;\n    }\n\n    private int compare(Number o1, Number o2) {\n        return (int) (o1.doubleValue() - o2.doubleValue());\n    }\n\n    private int compare(String o1, String o2) {\n        return Collator.getInstance().compare(o1, o2);\n    }\n\n    private int compare(Date o1, Date o2) {\n        return (int) (o1.getTime() - o2.getTime());\n    }\n\n    @Override\n    public int compare(Map<K, V> o1, Map<K, V> o2) {\n        int result = compare_0(o1, o2);\n\n        if (isDesc) {\n            result = -result;\n        }\n\n        return result;\n    }\n\n    private Object getValueByKey(Map<K, V> map, K key) {\n        if (key instanceof String) {\n            String keyStr = (String) key;\n\n            int bracketIndex = keyStr.indexOf('[');\n            if (bracketIndex > 0) {\n                Object value = map.get(keyStr.substring(0, bracketIndex));\n                if (value == null) {\n                    return null;\n                }\n\n                int p2 = keyStr.indexOf(']', bracketIndex);\n                if (p2 == -1) {\n                    return null;\n                }\n\n                String indexText = keyStr.substring(bracketIndex + 1, p2);\n                int index = Integer.parseInt(indexText);\n                if (value.getClass().isArray() && Array.getLength(value) >= index) {\n                    return Array.get(value, index);\n                }\n\n                return null;\n            }\n        }\n        return map.get(key);\n    }\n\n    private int compare_0(Map<K, V> o1, Map<K, V> o2) {\n        Object v1 = getValueByKey(o1, orderByKey);\n        Object v2 = getValueByKey(o2, orderByKey);\n\n        if (v1 == null && v2 == null) {\n            return 0;\n        }\n        if (v1 == null) {\n            return -1;\n        }\n        if (v2 == null) {\n            return 1;\n        }\n\n        if (v1 instanceof Long) {\n            return (int) (((Long) v1).longValue() - ((Number) v2).longValue());\n        }\n\n        if (v1 instanceof Number) {\n            return compare((Number) v1, (Number) v2);\n        }\n\n        if (v1 instanceof String) {\n            return compare((String) v1, (String) v2);\n        }\n\n        if (v1 instanceof Date) {\n            return compare((Date) v1, (Date) v2);\n        }\n\n        return 0;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/MySqlUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\n\nimport javax.sql.XAConnection;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.nio.charset.Charset;\nimport java.sql.*;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.time.*;\nimport java.util.*;\n\npublic class MySqlUtils {\n    static Class<?> utilClass;\n    static boolean utilClassError;\n    static boolean utilClass_isJdbc4;\n\n    static Class<?> class_5_connection;\n    static Method method_5_getPinGlobalTxToPhysicalConnection;\n    static Class<?> class_5_suspendableXAConnection;\n    static Constructor<?> constructor_5_suspendableXAConnection;\n    static Class<?> class_5_JDBC4SuspendableXAConnection;\n    static Constructor<?> constructor_5_JDBC4SuspendableXAConnection;\n    static Class<?> class_5_MysqlXAConnection;\n    static Constructor<?> constructor_5_MysqlXAConnection;\n\n    static Class<?> class_ConnectionImpl;\n    static Method method_getId;\n    static boolean method_getId_error;\n\n    static Class<?> class_6_ConnectionImpl;\n    static Method method_6_getId;\n\n    static volatile Class<?> class_6_connection;\n    static volatile Method method_6_getPropertySet;\n    static volatile Method method_6_getBooleanReadableProperty;\n    static volatile Method method_6_getValue;\n    static volatile boolean method_6_getValue_error;\n\n    static volatile Class<?> class_6_suspendableXAConnection;\n    static volatile Method method_6_getInstance;\n    static volatile boolean method_6_getInstance_error;\n    static volatile Method method_6_getInstanceXA;\n    static volatile boolean method_6_getInstanceXA_error;\n    static volatile Class<?> class_6_JDBC4SuspendableXAConnection;\n\n    public static XAConnection createXAConnection(Driver driver, Connection physicalConn) throws SQLException {\n        final int major = driver.getMajorVersion();\n        if (major == 5) {\n            if (utilClass == null && !utilClassError) {\n                try {\n                    utilClass = Class.forName(\"com.mysql.jdbc.Util\");\n\n                    Method method = utilClass.getMethod(\"isJdbc4\");\n                    utilClass_isJdbc4 = (Boolean) method.invoke(null);\n\n                    class_5_connection = Class.forName(\"com.mysql.jdbc.Connection\");\n                    method_5_getPinGlobalTxToPhysicalConnection = class_5_connection.getMethod(\"getPinGlobalTxToPhysicalConnection\");\n\n                    class_5_suspendableXAConnection = Class.forName(\"com.mysql.jdbc.jdbc2.optional.SuspendableXAConnection\");\n                    constructor_5_suspendableXAConnection = class_5_suspendableXAConnection.getConstructor(class_5_connection);\n\n                    class_5_JDBC4SuspendableXAConnection = Class.forName(\"com.mysql.jdbc.jdbc2.optional.JDBC4SuspendableXAConnection\");\n                    constructor_5_JDBC4SuspendableXAConnection = class_5_JDBC4SuspendableXAConnection.getConstructor(class_5_connection);\n\n                    class_5_MysqlXAConnection = Class.forName(\"com.mysql.jdbc.jdbc2.optional.MysqlXAConnection\");\n                    constructor_5_MysqlXAConnection = class_5_MysqlXAConnection.getConstructor(class_5_connection, boolean.class);\n                } catch (Exception ex) {\n                    ex.printStackTrace();\n                    utilClassError = true;\n                }\n            }\n\n            try {\n                boolean pinGlobTx = (Boolean) method_5_getPinGlobalTxToPhysicalConnection.invoke(physicalConn);\n                if (pinGlobTx) {\n                    if (!utilClass_isJdbc4) {\n                        return (XAConnection) constructor_5_suspendableXAConnection.newInstance(physicalConn);\n                    }\n\n                    return (XAConnection) constructor_5_JDBC4SuspendableXAConnection.newInstance(physicalConn);\n                }\n\n                return (XAConnection) constructor_5_MysqlXAConnection.newInstance(physicalConn, Boolean.FALSE);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n\n        } else if (major == 6 || major == 8) {\n            if (method_6_getValue == null && !method_6_getValue_error) {\n                try {\n                    class_6_connection = Class.forName(\"com.mysql.cj.api.jdbc.JdbcConnection\");\n                } catch (Throwable t) {\n                }\n\n                try {\n                    // maybe 8.0.11 or higher version, try again with com.mysql.cj.jdbc.JdbcConnection\n                    if (class_6_connection == null) {\n                        class_6_connection = Class.forName(\"com.mysql.cj.jdbc.JdbcConnection\");\n                        method_6_getPropertySet = class_6_connection.getMethod(\"getPropertySet\");\n                        Class<?> propertySetClass = Class.forName(\"com.mysql.cj.conf.PropertySet\");\n\n                        NoSuchMethodException noSuchMethodException = null;\n                        try {\n                            method_6_getBooleanReadableProperty = propertySetClass\n                                    .getMethod(\"getBooleanReadableProperty\", String.class);\n                            method_6_getValue = Class.forName(\"com.mysql.cj.conf.ReadableProperty\")\n                                    .getMethod(\"getValue\");\n                        } catch (NoSuchMethodException error) {\n                            noSuchMethodException = error;\n                        }\n                        if (method_6_getBooleanReadableProperty == null) {\n                            method_6_getBooleanReadableProperty = propertySetClass\n                                    .getMethod(\"getBooleanProperty\", String.class);\n                            method_6_getValue = Class.forName(\"com.mysql.cj.conf.RuntimeProperty\")\n                                    .getMethod(\"getValue\");\n                        }\n\n                    } else {\n                        method_6_getPropertySet = class_6_connection.getMethod(\"getPropertySet\");\n                        method_6_getBooleanReadableProperty = Class.forName(\"com.mysql.cj.api.conf.PropertySet\").getMethod(\"getBooleanReadableProperty\", String.class);\n                        method_6_getValue = Class.forName(\"com.mysql.cj.api.conf.ReadableProperty\").getMethod(\"getValue\");\n                    }\n                } catch (Exception ex) {\n                    ex.printStackTrace();\n                    method_6_getValue_error = true;\n                }\n            }\n\n            try {\n                // pinGlobalTxToPhysicalConnection\n                Boolean pinGlobTx = (Boolean) method_6_getValue.invoke(\n                        method_6_getBooleanReadableProperty.invoke(\n                                method_6_getPropertySet.invoke(physicalConn),\n                                \"pinGlobalTxToPhysicalConnection\"\n                        )\n                );\n\n                if (pinGlobTx != null && pinGlobTx) {\n                    try {\n                        if (method_6_getInstance == null && !method_6_getInstance_error) {\n                            class_6_suspendableXAConnection = Class.forName(\"com.mysql.cj.jdbc.SuspendableXAConnection\");\n                            method_6_getInstance = class_6_suspendableXAConnection.getDeclaredMethod(\"getInstance\", class_6_connection);\n                            method_6_getInstance.setAccessible(true);\n                        }\n                    } catch (Throwable ex) {\n                        ex.printStackTrace();\n                        method_6_getInstance_error = true;\n                    }\n                    return (XAConnection) method_6_getInstance.invoke(null, physicalConn);\n                } else {\n                    try {\n                        if (method_6_getInstanceXA == null && !method_6_getInstanceXA_error) {\n                            class_6_JDBC4SuspendableXAConnection = Class.forName(\"com.mysql.cj.jdbc.MysqlXAConnection\");\n                            method_6_getInstanceXA = class_6_JDBC4SuspendableXAConnection.getDeclaredMethod(\"getInstance\", class_6_connection, boolean.class);\n                            method_6_getInstanceXA.setAccessible(true);\n                        }\n                    } catch (Throwable ex) {\n                        ex.printStackTrace();\n                        method_6_getInstanceXA_error = true;\n                    }\n                    return (XAConnection) method_6_getInstanceXA.invoke(null, physicalConn, Boolean.FALSE);\n                }\n            } catch (InvocationTargetException e) {\n                Throwable cause = e.getCause();\n                if (cause instanceof RuntimeException) {\n                    throw (RuntimeException) cause;\n                }\n            } catch (Exception e) {\n                e.printStackTrace();\n                method_6_getInstance_error = true;\n            }\n        }\n\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public static String buildKillQuerySql(Connection connection, SQLException error) throws SQLException {\n        Long threadId = getId(connection);\n        if (threadId == null) {\n            return null;\n        }\n\n        return \"KILL QUERY \" + threadId;\n\n    }\n\n    private static Set<String> keywords;\n\n    public static boolean isKeyword(String name) {\n        if (name == null) {\n            return false;\n        }\n\n        String name_lower = name.toLowerCase();\n\n        Set<String> words = keywords;\n\n        if (words == null) {\n            words = new HashSet<String>();\n            Utils.loadFromFile(\"META-INF/druid/parser/mysql/keywords\", words);\n            keywords = words;\n        }\n\n        return words.contains(name_lower);\n    }\n\n    private static Set<String> builtinDataTypes;\n\n    public static boolean isBuiltinDataType(String dataType) {\n        if (dataType == null) {\n            return false;\n        }\n\n        String table_lower = dataType.toLowerCase();\n\n        Set<String> dataTypes = builtinDataTypes;\n\n        if (dataTypes == null) {\n            dataTypes = new HashSet<String>();\n            Utils.loadFromFile(\"META-INF/druid/parser/mysql/builtin_datatypes\", dataTypes);\n            builtinDataTypes = dataTypes;\n        }\n\n        return dataTypes.contains(table_lower);\n    }\n\n    public static List<String> showTables(Connection conn) throws SQLException {\n        List<String> tables = new ArrayList<String>();\n\n        Statement stmt = null;\n        ResultSet rs = null;\n        try {\n            stmt = conn.createStatement();\n            rs = stmt.executeQuery(\"show tables\");\n            while (rs.next()) {\n                String tableName = rs.getString(1);\n                tables.add(tableName);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n        }\n\n        return tables;\n    }\n\n    public static List<String> getTableDDL(Connection conn, List<String> tables) throws SQLException {\n        List<String> ddlList = new ArrayList<String>();\n\n        Statement stmt = null;\n        try {\n            for (String table : tables) {\n                if (stmt == null) {\n                    stmt = conn.createStatement();\n                }\n\n                if (isKeyword(table)) {\n                    table = \"`\" + table + \"`\";\n                }\n\n                ResultSet rs = null;\n                try {\n                    rs = stmt.executeQuery(\"show create table \" + table);\n                    if (rs.next()) {\n                        String ddl = rs.getString(2);\n                        ddlList.add(ddl);\n                    }\n                } finally {\n                    JdbcUtils.close(rs);\n                }\n            }\n        } finally {\n            JdbcUtils.close(stmt);\n        }\n\n        return ddlList;\n    }\n\n    public static String getCreateTableScript(Connection conn) throws SQLException {\n        return getCreateTableScript(conn, true, true);\n    }\n\n    public static String getCreateTableScript(Connection conn, boolean sorted, boolean simplify) throws SQLException {\n        List<String> tables = showTables(conn);\n        List<String> ddlList = getTableDDL(conn, tables);\n        StringBuilder buf = new StringBuilder();\n        for (String ddl : ddlList) {\n            buf.append(ddl);\n            buf.append(';');\n        }\n        String ddlScript = buf.toString();\n\n        if (!(sorted || simplify)) {\n            return ddlScript;\n        }\n\n        List stmtList = SQLUtils.parseStatements(ddlScript, DbType.mysql);\n        if (simplify) {\n            for (Object o : stmtList) {\n                if (o instanceof SQLCreateTableStatement) {\n                    SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) o;\n                    createTableStmt.simplify();\n                }\n            }\n        }\n\n        if (sorted) {\n            SQLCreateTableStatement.sort(stmtList);\n        }\n        return SQLUtils.toSQLString(stmtList, DbType.mysql);\n    }\n\n    private static transient Class class_connectionImpl;\n    private static transient boolean class_connectionImpl_Error;\n    private static transient Method method_getIO;\n    private static transient boolean method_getIO_error;\n    private static transient Class class_MysqlIO;\n    private static transient boolean class_MysqlIO_Error;\n    private static transient Method method_getLastPacketReceivedTimeMs;\n    private static transient boolean method_getLastPacketReceivedTimeMs_error;\n\n    private static volatile boolean mysqlJdbcVersion6;\n    private static transient Class classJdbc;\n    private static transient Method getIdleFor;\n    private static transient boolean getIdleForError;\n\n    public static Long getId(Object conn) {\n        if (conn == null) {\n            return null;\n        }\n\n        Class<?> clazz = conn.getClass();\n        if (class_ConnectionImpl == null) {\n            if (clazz.getName().equals(\"com.mysql.jdbc.ConnectionImpl\")) {\n                class_ConnectionImpl = clazz;\n            } else if (clazz.getName().equals(\"com.mysql.jdbc.Connection\")) { // mysql 5.0.x\n                class_ConnectionImpl = clazz;\n            } else if (clazz.getName().equals(\"com.mysql.cj.jdbc.ConnectionImpl\")) { // mysql 5.0.x\n                class_ConnectionImpl = clazz;\n            } else if (clazz.getSuperclass().getName().equals(\"com.mysql.jdbc.ConnectionImpl\")) {\n                class_ConnectionImpl = clazz.getSuperclass();\n            }\n        }\n\n        if (class_ConnectionImpl == clazz || class_ConnectionImpl == clazz.getSuperclass()) {\n            try {\n                if (method_getId == null && !method_getId_error) {\n                    Method method = class_ConnectionImpl.getDeclaredMethod(\"getId\");\n                    method.setAccessible(true);\n                    method_getId = method;\n                }\n\n                return (Long) method_getId.invoke(conn);\n            } catch (Throwable ex) {\n                method_getId_error = true;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * The <b>lastQueryFinishedTime</b>, returned from mysql8 <b>com.mysql.cj.jdbc.JdbcConnection#getIdleFor</b>,\n     * does not be updated by method <b>pingInternal</b> running for connection validation if option <b>usePingMethod</b>\n     * is true.<br>\n     * More troublesome is that <b>lastQueryFinishedTime</b> will not be set if option <b>maintainTimeStats</b>\n     * is false, so does mysql5 <b>lastPacketReceivedTimeMs</b>.\n     */\n    @Deprecated\n    public static long getLastPacketReceivedTimeMs(Connection conn) throws SQLException {\n        if (class_connectionImpl == null && !class_connectionImpl_Error) {\n            try {\n                class_connectionImpl = Utils.loadClass(\"com.mysql.jdbc.MySQLConnection\");\n                if (class_connectionImpl == null) {\n                    class_connectionImpl = Utils.loadClass(\"com.mysql.cj.MysqlConnection\");\n                    if (class_connectionImpl == null) {\n                        class_connectionImpl = Utils.loadClass(\"com.mysql.cj.api.MysqlConnection\");\n                    }\n                    if (class_connectionImpl != null) {\n                        mysqlJdbcVersion6 = true;\n                    }\n                }\n            } catch (Throwable error) {\n                class_connectionImpl_Error = true;\n            }\n        }\n\n        if (class_connectionImpl == null) {\n            return -1;\n        }\n\n        if (mysqlJdbcVersion6) {\n            if (classJdbc == null) {\n                classJdbc = Utils.loadClass(\"com.mysql.cj.jdbc.JdbcConnection\");\n            }\n\n            if (classJdbc == null) {\n                return -1;\n            }\n\n            if (getIdleFor == null && !getIdleForError) {\n                try {\n                    getIdleFor = classJdbc.getMethod(\"getIdleFor\");\n                    getIdleFor.setAccessible(true);\n                } catch (Throwable error) {\n                    getIdleForError = true;\n                }\n            }\n\n            if (getIdleFor == null) {\n                return -1;\n            }\n\n            try {\n                Object connImpl = conn.unwrap(class_connectionImpl);\n                if (connImpl == null) {\n                    return -1;\n                }\n\n                return System.currentTimeMillis()\n                        - ((Long)\n                        getIdleFor.invoke(connImpl))\n                        .longValue();\n            } catch (Exception e) {\n                throw new SQLException(\"getIdleFor error\", e);\n            }\n        } else {\n            if (method_getIO == null && !method_getIO_error) {\n                try {\n                    method_getIO = class_connectionImpl.getMethod(\"getIO\");\n                } catch (Throwable error) {\n                    method_getIO_error = true;\n                }\n            }\n\n            if (method_getIO == null) {\n                return -1;\n            }\n\n            if (class_MysqlIO == null && !class_MysqlIO_Error) {\n                try {\n                    class_MysqlIO = Utils.loadClass(\"com.mysql.jdbc.MysqlIO\");\n                } catch (Throwable error) {\n                    class_MysqlIO_Error = true;\n                }\n            }\n\n            if (class_MysqlIO == null) {\n                return -1;\n            }\n\n            if (method_getLastPacketReceivedTimeMs == null && !method_getLastPacketReceivedTimeMs_error) {\n                try {\n                    Method method = class_MysqlIO.getDeclaredMethod(\"getLastPacketReceivedTimeMs\");\n                    method.setAccessible(true);\n                    method_getLastPacketReceivedTimeMs = method;\n                } catch (Throwable error) {\n                    method_getLastPacketReceivedTimeMs_error = true;\n                }\n            }\n\n            if (method_getLastPacketReceivedTimeMs == null) {\n                return -1;\n            }\n\n            try {\n                Object connImpl = conn.unwrap(class_connectionImpl);\n                if (connImpl == null) {\n                    return -1;\n                }\n\n                Object mysqlio = method_getIO.invoke(connImpl);\n                return (Long) method_getLastPacketReceivedTimeMs.invoke(mysqlio);\n            } catch (Exception e) {\n                throw new SQLException(\"getLastPacketReceivedTimeMs error\", e);\n            }\n        }\n    }\n\n    static Class<?> class_5_CommunicationsException;\n    static Class<?> class_6_CommunicationsException;\n\n    public static Class getCommunicationsExceptionClass() {\n        if (class_5_CommunicationsException != null) {\n            return class_5_CommunicationsException;\n        }\n\n        if (class_6_CommunicationsException != null) {\n            return class_6_CommunicationsException;\n        }\n\n        class_5_CommunicationsException = Utils.loadClass(\"com.mysql.jdbc.CommunicationsException\");\n        if (class_5_CommunicationsException != null) {\n            return class_5_CommunicationsException;\n        }\n\n        class_6_CommunicationsException = Utils.loadClass(\"com.mysql.cj.jdbc.exceptions.CommunicationsException\");\n        if (class_6_CommunicationsException != null) {\n            return class_6_CommunicationsException;\n        }\n\n        return null;\n    }\n\n    public static final Charset GBK = Charset.forName(\"GBK\");\n    public static final Charset BIG5 = Charset.forName(\"BIG5\");\n    public static final Charset UTF8 = Charset.forName(\"UTF-8\");\n    public static final Charset UTF16 = Charset.forName(\"UTF-16\");\n    public static final Charset UTF32 = Charset.forName(\"UTF-32\");\n    public static final Charset ASCII = Charset.forName(\"ASCII\");\n\n    public static void loadDataTypes(Set<String> dataTypes) {\n        Utils.loadFromFile(\"META-INF/druid/parser/mysql/builtin_datatypes\", dataTypes);\n    }\n\n    private static BigInteger[] MAX_INT = {\n            new BigInteger(\"9\"),\n            new BigInteger(\"99\"),\n            new BigInteger(\"999\"),\n            new BigInteger(\"9999\"),\n            new BigInteger(\"99999\"),\n            new BigInteger(\"999999\"),\n            new BigInteger(\"9999999\"),\n            new BigInteger(\"99999999\"),\n            new BigInteger(\"999999999\"),\n            new BigInteger(\"9999999999\"),\n            new BigInteger(\"99999999999\"),\n            new BigInteger(\"999999999999\"),\n            new BigInteger(\"9999999999999\"),\n            new BigInteger(\"99999999999999\"),\n            new BigInteger(\"999999999999999\"),\n            new BigInteger(\"9999999999999999\"),\n            new BigInteger(\"99999999999999999\"),\n            new BigInteger(\"999999999999999999\"),\n            new BigInteger(\"9999999999999999999\"),\n            new BigInteger(\"99999999999999999999\"),\n            new BigInteger(\"999999999999999999999\"),\n            new BigInteger(\"9999999999999999999999\"),\n            new BigInteger(\"99999999999999999999999\"),\n            new BigInteger(\"999999999999999999999999\"),\n            new BigInteger(\"9999999999999999999999999\"),\n            new BigInteger(\"99999999999999999999999999\"),\n            new BigInteger(\"999999999999999999999999999\"),\n            new BigInteger(\"9999999999999999999999999999\"),\n            new BigInteger(\"99999999999999999999999999999\"),\n            new BigInteger(\"999999999999999999999999999999\"),\n            new BigInteger(\"9999999999999999999999999999999\"),\n            new BigInteger(\"99999999999999999999999999999999\"),\n            new BigInteger(\"999999999999999999999999999999999\"),\n            new BigInteger(\"9999999999999999999999999999999999\"),\n            new BigInteger(\"99999999999999999999999999999999999\"),\n            new BigInteger(\"999999999999999999999999999999999999\"),\n            new BigInteger(\"9999999999999999999999999999999999999\"),\n            new BigInteger(\"99999999999999999999999999999999999999\"),\n    };\n\n    private static BigInteger[] MIN_INT = {\n            new BigInteger(\"-9\"),\n            new BigInteger(\"-99\"),\n            new BigInteger(\"-999\"),\n            new BigInteger(\"-9999\"),\n            new BigInteger(\"-99999\"),\n            new BigInteger(\"-999999\"),\n            new BigInteger(\"-9999999\"),\n            new BigInteger(\"-99999999\"),\n            new BigInteger(\"-999999999\"),\n            new BigInteger(\"-9999999999\"),\n            new BigInteger(\"-99999999999\"),\n            new BigInteger(\"-999999999999\"),\n            new BigInteger(\"-9999999999999\"),\n            new BigInteger(\"-99999999999999\"),\n            new BigInteger(\"-999999999999999\"),\n            new BigInteger(\"-9999999999999999\"),\n            new BigInteger(\"-99999999999999999\"),\n            new BigInteger(\"-999999999999999999\"),\n            new BigInteger(\"-9999999999999999999\"),\n            new BigInteger(\"-99999999999999999999\"),\n            new BigInteger(\"-999999999999999999999\"),\n            new BigInteger(\"-9999999999999999999999\"),\n            new BigInteger(\"-99999999999999999999999\"),\n            new BigInteger(\"-999999999999999999999999\"),\n            new BigInteger(\"-9999999999999999999999999\"),\n            new BigInteger(\"-99999999999999999999999999\"),\n            new BigInteger(\"-999999999999999999999999999\"),\n            new BigInteger(\"-9999999999999999999999999999\"),\n            new BigInteger(\"-99999999999999999999999999999\"),\n            new BigInteger(\"-999999999999999999999999999999\"),\n            new BigInteger(\"-9999999999999999999999999999999\"),\n            new BigInteger(\"-99999999999999999999999999999999\"),\n            new BigInteger(\"-999999999999999999999999999999999\"),\n            new BigInteger(\"-9999999999999999999999999999999999\"),\n            new BigInteger(\"-99999999999999999999999999999999999\"),\n            new BigInteger(\"-999999999999999999999999999999999999\"),\n            new BigInteger(\"-9999999999999999999999999999999999999\"),\n            new BigInteger(\"-99999999999999999999999999999999999999\"),\n    };\n\n    private static BigDecimal[] MAX_DEC_1 = {\n            new BigDecimal(\"0.9\"),\n            new BigDecimal(\"9.9\"),\n            new BigDecimal(\"99.9\"),\n            new BigDecimal(\"999.9\"),\n            new BigDecimal(\"9999.9\"),\n            new BigDecimal(\"99999.9\"),\n            new BigDecimal(\"999999.9\"),\n            new BigDecimal(\"9999999.9\"),\n            new BigDecimal(\"99999999.9\"),\n            new BigDecimal(\"999999999.9\"),\n            new BigDecimal(\"9999999999.9\"),\n            new BigDecimal(\"99999999999.9\"),\n            new BigDecimal(\"999999999999.9\"),\n            new BigDecimal(\"9999999999999.9\"),\n            new BigDecimal(\"99999999999999.9\"),\n            new BigDecimal(\"999999999999999.9\"),\n            new BigDecimal(\"9999999999999999.9\"),\n            new BigDecimal(\"99999999999999999.9\"),\n            new BigDecimal(\"999999999999999999.9\"),\n            new BigDecimal(\"9999999999999999999.9\"),\n            new BigDecimal(\"99999999999999999999.9\"),\n            new BigDecimal(\"999999999999999999999.9\"),\n            new BigDecimal(\"9999999999999999999999.9\"),\n            new BigDecimal(\"99999999999999999999999.9\"),\n            new BigDecimal(\"999999999999999999999999.9\"),\n            new BigDecimal(\"9999999999999999999999999.9\"),\n            new BigDecimal(\"99999999999999999999999999.9\"),\n            new BigDecimal(\"999999999999999999999999999.9\"),\n            new BigDecimal(\"9999999999999999999999999999.9\"),\n            new BigDecimal(\"99999999999999999999999999999.9\"),\n            new BigDecimal(\"999999999999999999999999999999.9\"),\n            new BigDecimal(\"9999999999999999999999999999999.9\"),\n            new BigDecimal(\"99999999999999999999999999999999.9\"),\n            new BigDecimal(\"999999999999999999999999999999999.9\"),\n            new BigDecimal(\"9999999999999999999999999999999999.9\"),\n            new BigDecimal(\"99999999999999999999999999999999999.9\"),\n            new BigDecimal(\"999999999999999999999999999999999999.9\"),\n            new BigDecimal(\"9999999999999999999999999999999999999.9\"),\n    };\n\n    private static BigDecimal[] MIN_DEC_1 = {\n            new BigDecimal(\"-0.9\"),\n            new BigDecimal(\"-9.9\"),\n            new BigDecimal(\"-99.9\"),\n            new BigDecimal(\"-999.9\"),\n            new BigDecimal(\"-9999.9\"),\n            new BigDecimal(\"-99999.9\"),\n            new BigDecimal(\"-999999.9\"),\n            new BigDecimal(\"-9999999.9\"),\n            new BigDecimal(\"-99999999.9\"),\n            new BigDecimal(\"-999999999.9\"),\n            new BigDecimal(\"-9999999999.9\"),\n            new BigDecimal(\"-99999999999.9\"),\n            new BigDecimal(\"-999999999999.9\"),\n            new BigDecimal(\"-9999999999999.9\"),\n            new BigDecimal(\"-99999999999999.9\"),\n            new BigDecimal(\"-999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999.9\"),\n            new BigDecimal(\"-99999999999999999.9\"),\n            new BigDecimal(\"-999999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999999.9\"),\n            new BigDecimal(\"-99999999999999999999.9\"),\n            new BigDecimal(\"-999999999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999999999.9\"),\n            new BigDecimal(\"-99999999999999999999999.9\"),\n            new BigDecimal(\"-999999999999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999999999999.9\"),\n            new BigDecimal(\"-99999999999999999999999999.9\"),\n            new BigDecimal(\"-999999999999999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999999999999999.9\"),\n            new BigDecimal(\"-99999999999999999999999999999.9\"),\n            new BigDecimal(\"-999999999999999999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999999999999999999.9\"),\n            new BigDecimal(\"-99999999999999999999999999999999.9\"),\n            new BigDecimal(\"-999999999999999999999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999999999999999999999.9\"),\n            new BigDecimal(\"-99999999999999999999999999999999999.9\"),\n            new BigDecimal(\"-999999999999999999999999999999999999.9\"),\n            new BigDecimal(\"-9999999999999999999999999999999999999.9\"),\n    };\n\n    private static BigDecimal[] MAX_DEC_2 = {\n            new BigDecimal(\"0.99\"),\n            new BigDecimal(\"9.99\"),\n            new BigDecimal(\"99.99\"),\n            new BigDecimal(\"999.99\"),\n            new BigDecimal(\"9999.99\"),\n            new BigDecimal(\"99999.99\"),\n            new BigDecimal(\"999999.99\"),\n            new BigDecimal(\"9999999.99\"),\n            new BigDecimal(\"99999999.99\"),\n            new BigDecimal(\"999999999.99\"),\n            new BigDecimal(\"9999999999.99\"),\n            new BigDecimal(\"99999999999.99\"),\n            new BigDecimal(\"999999999999.99\"),\n            new BigDecimal(\"9999999999999.99\"),\n            new BigDecimal(\"99999999999999.99\"),\n            new BigDecimal(\"999999999999999.99\"),\n            new BigDecimal(\"9999999999999999.99\"),\n            new BigDecimal(\"99999999999999999.99\"),\n            new BigDecimal(\"999999999999999999.99\"),\n            new BigDecimal(\"9999999999999999999.99\"),\n            new BigDecimal(\"99999999999999999999.99\"),\n            new BigDecimal(\"999999999999999999999.99\"),\n            new BigDecimal(\"9999999999999999999999.99\"),\n            new BigDecimal(\"99999999999999999999999.99\"),\n            new BigDecimal(\"999999999999999999999999.99\"),\n            new BigDecimal(\"9999999999999999999999999.99\"),\n            new BigDecimal(\"99999999999999999999999999.99\"),\n            new BigDecimal(\"999999999999999999999999999.99\"),\n            new BigDecimal(\"9999999999999999999999999999.99\"),\n            new BigDecimal(\"99999999999999999999999999999.99\"),\n            new BigDecimal(\"999999999999999999999999999999.99\"),\n            new BigDecimal(\"9999999999999999999999999999999.99\"),\n            new BigDecimal(\"99999999999999999999999999999999.99\"),\n            new BigDecimal(\"999999999999999999999999999999999.99\"),\n            new BigDecimal(\"9999999999999999999999999999999999.99\"),\n            new BigDecimal(\"99999999999999999999999999999999999.99\"),\n            new BigDecimal(\"999999999999999999999999999999999999.99\"),\n            new BigDecimal(\"9999999999999999999999999999999999999.99\"),\n    };\n\n    private static BigDecimal[] MIN_DEC_2 = {\n            new BigDecimal(\"-0.99\"),\n            new BigDecimal(\"-9.99\"),\n            new BigDecimal(\"-99.99\"),\n            new BigDecimal(\"-999.99\"),\n            new BigDecimal(\"-9999.99\"),\n            new BigDecimal(\"-99999.99\"),\n            new BigDecimal(\"-999999.99\"),\n            new BigDecimal(\"-9999999.99\"),\n            new BigDecimal(\"-99999999.99\"),\n            new BigDecimal(\"-999999999.99\"),\n            new BigDecimal(\"-9999999999.99\"),\n            new BigDecimal(\"-99999999999.99\"),\n            new BigDecimal(\"-999999999999.99\"),\n            new BigDecimal(\"-9999999999999.99\"),\n            new BigDecimal(\"-99999999999999.99\"),\n            new BigDecimal(\"-999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999.99\"),\n            new BigDecimal(\"-99999999999999999.99\"),\n            new BigDecimal(\"-999999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999999.99\"),\n            new BigDecimal(\"-99999999999999999999.99\"),\n            new BigDecimal(\"-999999999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999999999.99\"),\n            new BigDecimal(\"-99999999999999999999999.99\"),\n            new BigDecimal(\"-999999999999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999999999999.99\"),\n            new BigDecimal(\"-99999999999999999999999999.99\"),\n            new BigDecimal(\"-999999999999999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999999999999999.99\"),\n            new BigDecimal(\"-99999999999999999999999999999.99\"),\n            new BigDecimal(\"-999999999999999999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999999999999999999.99\"),\n            new BigDecimal(\"-99999999999999999999999999999999.99\"),\n            new BigDecimal(\"-999999999999999999999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999999999999999999999.99\"),\n            new BigDecimal(\"-99999999999999999999999999999999999.99\"),\n            new BigDecimal(\"-999999999999999999999999999999999999.99\"),\n            new BigDecimal(\"-9999999999999999999999999999999999999.99\"),\n    };\n\n    public static BigDecimal decimal(BigDecimal value, int precision, int scale) {\n        int v_scale = value.scale();\n\n        int v_precision;\n        if (v_scale > scale) {\n            value = value.setScale(scale, BigDecimal.ROUND_HALF_UP);\n            v_precision = value.precision();\n        } else {\n            v_precision = value.precision();\n        }\n\n        int v_ints = v_precision - v_scale;\n        int ints = precision - scale;\n\n        if (v_precision > precision || v_ints > ints) {\n            boolean sign = value.signum() > 0;\n\n            if (scale == 1) {\n                return sign ? MAX_DEC_1[ints] : MIN_DEC_1[ints];\n            }\n\n            if (scale == 2) {\n                return sign ? MAX_DEC_2[ints] : MIN_DEC_2[ints];\n            }\n\n            return new BigDecimal(\n                    sign ? MAX_INT[precision - 1] : MIN_INT[precision - 1],\n                    scale\n            );\n        }\n\n        return value;\n    }\n\n    public static boolean isNumber(String str) {\n        if (str == null || str.length() == 0) {\n            return false;\n        }\n\n        char c0 = str.charAt(0);\n\n        boolean dot = false, expr = false;\n\n        int i = 0;\n        if (c0 == '+' || c0 == '-') {\n            i++;\n        }\n\n        for (; i < str.length(); ++i) {\n            char ch = str.charAt(i);\n            if (ch == '.') {\n                if (dot || expr) {\n                    return false;\n                } else {\n                    dot = true;\n                    continue;\n                }\n            }\n\n            if (ch == 'e' || ch == 'E') {\n                if (expr) {\n                    return false;\n                } else {\n                    expr = true;\n                }\n\n                if (i < str.length() - 1) {\n                    char next = str.charAt(i + 1);\n                    if (next == '+' || next == '-') {\n                        i++;\n                    }\n                    continue;\n                } else {\n                    return false;\n                }\n            }\n\n            if (ch < '0' || ch > '9') {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    public static DateFormat toJavaFormat(String fmt, TimeZone timeZone) {\n        DateFormat dateFormat = toJavaFormat(fmt);\n        if (dateFormat == null) {\n            return null;\n        }\n\n        if (timeZone != null) {\n            dateFormat.setTimeZone(timeZone);\n        }\n\n        return dateFormat;\n    }\n\n    public static DateFormat toJavaFormat(String fmt) {\n        if (fmt == null) {\n            return null;\n        }\n\n        StringBuilder buf = new StringBuilder();\n\n        for (int i = 0, len = fmt.length(); i < len; ++i) {\n            char ch = fmt.charAt(i);\n            if (ch == '%') {\n                if (i + 1 == len) {\n                    return null;\n                }\n\n                char next_ch = fmt.charAt(++i);\n                switch (next_ch) {\n                    case 'a':\n                        buf.append(\"EEE\");\n                        break;\n                    case 'b':\n                        buf.append(\"MMM\");\n                        break;\n                    case 'c':\n                        buf.append(\"M\");\n                        break;\n                    case 'd':\n                        buf.append(\"dd\");\n                        break;\n                    case 'e':\n                        buf.append(\"d\");\n                        break;\n                    case 'f':\n                        buf.append(\"SSS000\");\n                        break;\n                    case 'H':\n                    case 'k':\n                        buf.append(\"HH\");\n                        break;\n                    case 'h':\n                    case 'l':\n                    case 'I':\n                        buf.append(\"hh\");\n                        break;\n                    case 'i':\n                        buf.append(\"mm\");\n                        break;\n                    case 'M':\n                        buf.append(\"MMMMM\");\n                        break;\n                    case 'm':\n                        buf.append(\"MM\");\n                        break;\n                    case 'p':\n                        buf.append('a');\n                        break;\n                    case 'r':\n                        buf.append(\"hh:mm:ss a\");\n                        break;\n                    case 's':\n                    case 'S':\n                        buf.append(\"ss\");\n                        break;\n                    case 'T':\n                        buf.append(\"HH:mm:ss\");\n                        break;\n                    case 'W':\n                        buf.append(\"EEEEE\");\n                        break;\n                    case 'w':\n                        buf.append(\"u\");\n                        break;\n                    case 'Y':\n                        buf.append(\"yyyy\");\n                        break;\n                    case 'y':\n                        buf.append(\"yy\");\n                        break;\n                    default:\n                        return null;\n                }\n\n            } else {\n                buf.append(ch);\n            }\n        }\n\n        try {\n            return new SimpleDateFormat(buf.toString(), Locale.ENGLISH);\n        } catch (IllegalArgumentException ex) {\n            // skip\n            return null;\n        }\n    }\n\n    public static java.util.Date parseDate(String str, TimeZone timeZone) {\n        if (str == null) {\n            return null;\n        }\n\n        final int length = str.length();\n        if (length < 8) {\n            return null;\n        }\n\n        ZoneId zoneId = timeZone == null\n                ? ZoneId.systemDefault()\n                : timeZone.toZoneId();\n\n        char y0 = str.charAt(0);\n        char y1 = str.charAt(1);\n        char y2 = str.charAt(2);\n        char y3 = str.charAt(3);\n\n        char M0 = 0, M1 = 0, d0 = 0, d1 = 0;\n        char h0 = 0, h1 = 0, m0 = 0, m1 = 0, s0 = 0, s1 = 0, S0 = '0', S1 = '0', S2 = '0';\n\n        final char c4 = str.charAt(4);\n        final char c5 = str.charAt(5);\n        final char c6 = str.charAt(6);\n        final char c7 = str.charAt(7);\n        char c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18;\n\n        int nanos = 0;\n        switch (length) {\n            case 8:\n                // yyyyMMdd\n                if (c4 == '-' && c6 == '-') {\n                    M0 = '0';\n                    M1 = c5;\n                    d0 = '0';\n                    d1 = c7;\n                } else if (y2 == ':' && c5 == ':') {\n                    h0 = y0;\n                    h1 = y1;\n                    m0 = y3;\n                    m1 = c4;\n                    s0 = c6;\n                    s1 = c7;\n\n                    y0 = '1';\n                    y1 = '9';\n                    y2 = '7';\n                    y3 = '0';\n                    M0 = '0';\n                    M1 = '1';\n                    d0 = '0';\n                    d1 = '1';\n                } else {\n                    M0 = c4;\n                    M1 = c5;\n                    d0 = c6;\n                    d1 = c7;\n                }\n                break;\n            case 9:\n                // yyyy-M-dd or yyyy-MM-d\n                c8 = str.charAt(8);\n\n                if (c4 != '-') {\n                    return null;\n                }\n\n                if (c6 == '-') {\n                    M0 = '0';\n                    M1 = c5;\n                    d0 = c7;\n                    d1 = c8;\n                } else if (c7 == '-') {\n                    M0 = c5;\n                    M1 = c6;\n                    d0 = '0';\n                    d1 = c8;\n                } else {\n                    return null;\n                }\n                break;\n            case 10:\n                c8 = str.charAt(8);\n                c9 = str.charAt(9);\n                // yyyy-MM-dd\n                if (c4 != '-' || c7 != '-') {\n                    return null;\n                }\n\n                M0 = c5;\n                M1 = c6;\n                d0 = c8;\n                d1 = c9;\n                break;\n            case 14:\n                c8 = str.charAt(8);\n                c9 = str.charAt(9);\n                c10 = str.charAt(10);\n                c11 = str.charAt(11);\n                c12 = str.charAt(12);\n                c13 = str.charAt(13);\n\n                if (c8 == ' ') {\n                    // yyyy-M-d H:m:s\n                    if (c4 == '-' && c6 == '-' & c10 == ':' && c12 == ':') {\n                        M0 = '0';\n                        M1 = c5;\n                        d0 = '0';\n                        d1 = c7;\n                        h0 = '0';\n                        h1 = c9;\n                        m0 = '0';\n                        m1 = c11;\n                        s0 = '0';\n                        s1 = c13;\n                    } else {\n                        return null;\n                    }\n                } else {\n                    // yyyyMMddHHmmss\n                    M0 = c4;\n                    M1 = c5;\n                    d0 = c6;\n                    d1 = c7;\n                    h0 = c8;\n                    h1 = c9;\n                    m0 = c10;\n                    m1 = c11;\n                    s0 = c12;\n                    s1 = c13;\n                }\n                break;\n            case 15:\n            case 16:\n            case 17:\n            case 18:\n            case 19:\n            case 20:\n            case 21:\n            case 22:\n            case 23:\n            case 29:\n                if (length == 19 || length == 23 || length == 29) {\n                    c8 = str.charAt(8);\n                    c9 = str.charAt(9);\n                    c10 = str.charAt(10);\n                    c11 = str.charAt(11);\n                    c12 = str.charAt(12);\n                    c13 = str.charAt(13);\n                    c14 = str.charAt(14);\n                    c15 = str.charAt(15);\n                    c16 = str.charAt(16);\n                    c17 = str.charAt(17);\n                    c18 = str.charAt(18);\n\n                    // yyyy-MM-dd HH:mm:ss\n                    // yyyy-MM-dd HH.mm.ss\n                    if (c4 == '-' && c7 == '-'\n                            && (c10 == ' ' || c10 == 'T')\n                            && ((c13 == ':' && c16 == ':') || (c13 == '.' && c16 == '.'))) {\n                        M0 = c5;\n                        M1 = c6;\n                        d0 = c8;\n                        d1 = c9;\n                        h0 = c11;\n                        h1 = c12;\n                        m0 = c14;\n                        m1 = c15;\n                        s0 = c17;\n                        s1 = c18;\n\n                        // yyyy-MM-dd HH:mm:ss.SSS\n                        if (length == 23) {\n                            final char c19 = str.charAt(19);\n                            final char c20 = str.charAt(20);\n                            final char c21 = str.charAt(21);\n                            final char c22 = str.charAt(22);\n\n                            if (c19 == '.') {\n                                S0 = c20;\n                                S1 = c21;\n                                S2 = c22;\n                            } else if (c19 == ' ' && c20 == 'U' && c21 == 'T' && c22 == 'C') {\n                                // skip\n                                zoneId = ZoneOffset.UTC;\n                            } else {\n                                return null;\n                            }\n                        } else if (length == 29) {\n                            final char c19 = str.charAt(19);\n                            final char c20 = str.charAt(20);\n                            final char c21 = str.charAt(21);\n                            final char c22 = str.charAt(22);\n\n                            if (c19 == '.') {\n                                S0 = c20;\n                                S1 = c21;\n                                S2 = c22;\n                            } else {\n                                return null;\n                            }\n\n                            final char c23 = str.charAt(23);\n                            final char c24 = str.charAt(24);\n                            final char c25 = str.charAt(25);\n                            final char c26 = str.charAt(26);\n                            final char c27 = str.charAt(27);\n                            final char c28 = str.charAt(28);\n\n                            if (c23 < '0' || c23 > '9'\n                                    || c24 < '0' || c24 > '9'\n                                    || c25 < '0' || c25 > '9'\n                                    || c26 < '0' || c26 > '9'\n                                    || c27 < '0' || c27 > '9'\n                                    || c28 < '0' || c28 > '9') {\n                                return null;\n                            }\n\n                            nanos = (c23 - '0') * 100000\n                                    + (c24 - '0') * 10000\n                                    + (c25 - '0') * 1000\n                                    + (c26 - '0') * 100\n                                    + (c27 - '0') * 10\n                                    + (c28 - '0');\n                        }\n\n                        break;\n                    }\n                }\n\n                if (c4 != '-') {\n                    return null;\n                }\n\n                int offset;\n                if (c6 == '-') {\n                    M0 = '0';\n                    M1 = c5;\n                    offset = 7;\n                } else if (c7 == '-') {\n                    M0 = c5;\n                    M1 = c6;\n                    offset = 8;\n                } else {\n                    return null;\n                }\n\n            {\n                char n0 = str.charAt(offset);\n                char n1, n2;\n\n                if ((n1 = str.charAt(offset + 1)) == ' ' || n1 == 'T') {\n                    d0 = '0';\n                    d1 = n0;\n                    offset += 2;\n                } else if ((n2 = str.charAt(offset + 2)) == ' ' || n2 == 'T') {\n                    d0 = n0;\n                    d1 = n1;\n                    offset += 3;\n                } else {\n                    return null;\n                }\n            }\n\n            {\n                char n0 = str.charAt(offset);\n                char n1, n2;\n\n                if ((n1 = str.charAt(offset + 1)) == ':') {\n                    h0 = '0';\n                    h1 = n0;\n                    offset += 2;\n                } else if ((n2 = str.charAt(offset + 2)) == ':') {\n                    h0 = n0;\n                    h1 = n1;\n                    offset += 3;\n                } else {\n                    return null;\n                }\n            }\n\n            {\n                char n0 = str.charAt(offset);\n                char n1, n2;\n\n                if ((n1 = str.charAt(offset + 1)) == ':') {\n                    m0 = '0';\n                    m1 = n0;\n                    offset += 2;\n                } else if (offset + 2 < length && (n2 = str.charAt(offset + 2)) == ':') {\n                    m0 = n0;\n                    m1 = n1;\n                    offset += 3;\n                } else {\n                    return null;\n                }\n            }\n\n            if (offset == length - 1) {\n                s0 = '0';\n                s1 = str.charAt(offset);\n            } else if (offset == length - 2) {\n                char n0 = str.charAt(offset);\n                char n1 = str.charAt(offset + 1);\n                if (n1 == '.') {\n                    s0 = '0';\n                    s1 = n0;\n                } else {\n                    s0 = n0;\n                    s1 = n1;\n                }\n            } else {\n                char x0 = str.charAt(length - 1);\n                char x1 = str.charAt(length - 2);\n                char x2 = str.charAt(length - 3);\n                char x3 = str.charAt(length - 4);\n\n                int lastOff;\n                if (x0 == '.') {\n                    // skip\n                    lastOff = length - 2;\n                } else if (x1 == '.') {\n                    S2 = x0;\n                    lastOff = length - 3;\n                } else if (x2 == '.') {\n                    S1 = x1;\n                    S2 = x0;\n                    lastOff = length - 4;\n                } else if (x3 == '.') {\n                    S0 = x2;\n                    S1 = x1;\n                    S2 = x0;\n                    lastOff = length - 5;\n                } else if ((x2 == '+' || x2 == '-') && length == offset + 5) {\n                    String zoneIdStr = new String(new char[]{x2, x1, x0});\n                    zoneId = ZoneId.of(zoneIdStr);\n                    lastOff = length - 4;\n                } else {\n                    return null;\n                }\n\n                char k0 = str.charAt(lastOff);\n                char k1 = str.charAt(lastOff - 1);\n                char k2 = str.charAt(lastOff - 2);\n                if (k1 == ':') {\n                    s0 = '0';\n                    s1 = k0;\n                } else if (k2 == ':') {\n                    s1 = k0;\n                    s0 = k1;\n                } else {\n                    return null;\n                }\n            }\n            break;\n            default:\n                return null;\n        }\n\n        if (y0 < '0' || y0 > '9'\n                || y1 < '0' || y1 > '9'\n                || y2 < '0' || y2 > '9'\n                || y3 < '0' || y3 > '9') {\n            return null;\n        }\n        int year = (y0 - '0') * 1000\n                + (y1 - '0') * 100\n                + (y2 - '0') * 10\n                + (y3 - '0');\n        if (year < 1970) {\n            return null;\n        }\n\n        if (M0 < '0' || M0 > '1') {\n            return null;\n        }\n        if (M1 < '0' || M1 > '9') {\n            return null;\n        }\n        int month = (M0 - '0') * 10 + (M1 - '0');\n        if (month < 1 || month > 12) {\n            return null;\n        }\n\n        if (d0 < '0' || d0 > '9') {\n            return null;\n        }\n        if (d1 < '0' || d1 > '9') {\n            return null;\n        }\n        int dayOfMonth = (d0 - '0') * 10 + (d1 - '0');\n        if (dayOfMonth < 1) {\n            return null;\n        }\n\n        final int maxDayOfMonth;\n        switch (month) {\n            case 2:\n                maxDayOfMonth = 29;\n                break;\n            case 4:\n            case 6:\n            case 9:\n            case 11:\n                maxDayOfMonth = 30;\n                break;\n            default:\n                maxDayOfMonth = 31;\n                break;\n        }\n        if (dayOfMonth > maxDayOfMonth) {\n            return null;\n        }\n\n        ZonedDateTime zdt;\n        if (h0 == 0) {\n            zdt = LocalDate\n                    .of(year, month, dayOfMonth)\n                    .atStartOfDay(zoneId);\n        } else {\n            int hour = (h0 - '0') * 10 + (h1 - '0');\n            int minute = (m0 - '0') * 10 + (m1 - '0');\n            int second = (s0 - '0') * 10 + (s1 - '0');\n            int nanoSecond = ((S0 - '0') * 100 + (S1 - '0') * 10 + (S2 - '0')) * 1000000 + nanos;\n\n            if (hour >= 24 || minute > 60 || second > 61) {\n                return null;\n            }\n\n            zdt = LocalDateTime\n                    .of(year, month, dayOfMonth, hour, minute, second, nanoSecond)\n                    .atZone(zoneId);\n        }\n\n        return java.util.Date.from(\n                zdt.toInstant()\n        );\n    }\n\n    public static long parseMillis(byte[] str, TimeZone timeZone) {\n        if (str == null) {\n            throw new IllegalArgumentException(\"str not be null\");\n        }\n\n        return parseMillis(str, 0, str.length, timeZone);\n    }\n\n    public static long parseMillis(final byte[] str, final int off, final int len, final TimeZone timeZone) {\n        ZoneId zoneId = timeZone == null\n                ? ZoneId.systemDefault()\n                : timeZone.toZoneId();\n\n        return parseDateTime(str, off, len, zoneId)\n                .toInstant()\n                .toEpochMilli();\n    }\n\n    public static ZonedDateTime parseDateTime(final byte[] str, final int off, final int len, ZoneId zoneId) {\n        if (str == null) {\n            throw new IllegalArgumentException(\"str not be null\");\n        }\n\n        if (len < 8) {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n\n        byte y0 = str[off];\n        byte y1 = str[off + 1];\n        byte y2 = str[off + 2];\n        byte y3 = str[off + 3];\n\n        byte M0 = 0, M1 = 0, d0 = 0, d1 = 0;\n        byte h0 = 0, h1 = 0, m0 = 0, m1 = 0, s0 = 0, s1 = 0, S0 = '0', S1 = '0', S2 = '0';\n\n        final byte c4 = str[off + 4];\n        final byte c5 = str[off + 5];\n        final byte c6 = str[off + 6];\n        final byte c7 = str[off + 7];\n        byte c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18;\n\n        int nanos = 0;\n        switch (len) {\n            case 8:\n                // yyyyMMdd\n                if (c4 == '-' && c6 == '-') {\n                    M0 = '0';\n                    M1 = c5;\n                    d0 = '0';\n                    d1 = c7;\n                } else if (y2 == ':' && c5 == ':') {\n                    h0 = y0;\n                    h1 = y1;\n                    m0 = y3;\n                    m1 = c4;\n                    s0 = c6;\n                    s1 = c7;\n\n                    y0 = '1';\n                    y1 = '9';\n                    y2 = '7';\n                    y3 = '0';\n                    M0 = '0';\n                    M1 = '1';\n                    d0 = '0';\n                    d1 = '1';\n                } else {\n                    M0 = c4;\n                    M1 = c5;\n                    d0 = c6;\n                    d1 = c7;\n                }\n                break;\n            case 9:\n                // yyyy-M-dd or yyyy-MM-d\n                c8 = str[off + 8];\n\n                if (c4 != '-') {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n\n                if (c6 == '-') {\n                    M0 = '0';\n                    M1 = c5;\n                    d0 = c7;\n                    d1 = c8;\n                } else if (c7 == '-') {\n                    M0 = c5;\n                    M1 = c6;\n                    d0 = '0';\n                    d1 = c8;\n                } else {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n                break;\n            case 10:\n                c8 = str[off + 8];\n                c9 = str[off + 9];\n                // yyyy-MM-dd\n                if (c4 != '-' || c7 != '-') {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n\n                M0 = c5;\n                M1 = c6;\n                d0 = c8;\n                d1 = c9;\n                break;\n            case 14:\n                c8 = str[off + 8];\n                c9 = str[off + 9];\n                c10 = str[off + 10];\n                c11 = str[off + 11];\n                c12 = str[off + 12];\n                c13 = str[off + 13];\n\n                if (c8 == ' ') {\n                    // yyyy-M-d H:m:s\n                    if (c4 == '-' && c6 == '-' & c10 == ':' && c12 == ':') {\n                        M0 = '0';\n                        M1 = c5;\n                        d0 = '0';\n                        d1 = c7;\n                        h0 = '0';\n                        h1 = c9;\n                        m0 = '0';\n                        m1 = c11;\n                        s0 = '0';\n                        s1 = c13;\n                    } else {\n                        throw new IllegalArgumentException(new String(str, UTF8));\n                    }\n                } else {\n                    // yyyyMMddHHmmss\n                    M0 = c4;\n                    M1 = c5;\n                    d0 = c6;\n                    d1 = c7;\n                    h0 = c8;\n                    h1 = c9;\n                    m0 = c10;\n                    m1 = c11;\n                    s0 = c12;\n                    s1 = c13;\n                }\n                break;\n            case 15:\n            case 16:\n            case 17:\n            case 18:\n            case 19:\n            case 20:\n            case 21:\n            case 22:\n            case 23:\n            case 26:\n            case 27:\n            case 28:\n            case 29:\n                if (len == 19 || len >= 23) {\n                    c8 = str[off + 8];\n                    c9 = str[off + 9];\n                    c10 = str[off + 10];\n                    c11 = str[off + 11];\n                    c12 = str[off + 12];\n                    c13 = str[off + 13];\n                    c14 = str[off + 14];\n                    c15 = str[off + 15];\n                    c16 = str[off + 16];\n                    c17 = str[off + 17];\n                    c18 = str[off + 18];\n\n                    // yyyy-MM-dd HH:mm:ss\n                    if (c4 == '-' && c7 == '-'\n                            && (c10 == ' ' || c10 == 'T')\n                            && c13 == ':' && c16 == ':') {\n                        M0 = c5;\n                        M1 = c6;\n                        d0 = c8;\n                        d1 = c9;\n                        h0 = c11;\n                        h1 = c12;\n                        m0 = c14;\n                        m1 = c15;\n                        s0 = c17;\n                        s1 = c18;\n\n                        if (len == 19) {\n                            break;\n                        }\n\n                        // yyyy-MM-dd HH:mm:ss.SSS\n                        final byte c19 = str[off + 19];\n                        final byte c20 = str[off + 20];\n                        final byte c21 = str[off + 21];\n                        final byte c22 = str[off + 22];\n\n                        if (len == 23) {\n                            if (c19 == '.') {\n                                S0 = c20;\n                                S1 = c21;\n                                S2 = c22;\n                            } else if (c19 == ' ' && c20 == 'U' && c21 == 'T' && c22 == 'C') {\n                                // skip\n                                zoneId = ZoneOffset.UTC;\n                            } else {\n                                throw new IllegalArgumentException(new String(str, UTF8));\n                            }\n                            break;\n                        }\n\n                        if (c19 == '.') {\n                            S0 = c20;\n                            S1 = c21;\n                            S2 = c22;\n                        } else {\n                            throw new IllegalArgumentException(new String(str, UTF8));\n                        }\n\n                        if (len == 29) {\n                            final byte c23 = str[off + 23];\n                            final byte c24 = str[off + 24];\n                            final byte c25 = str[off + 25];\n                            final byte c26 = str[off + 26];\n                            final byte c27 = str[off + 27];\n                            final byte c28 = str[off + 28];\n\n                            if (c23 < '0' || c23 > '9'\n                                    || c24 < '0' || c24 > '9'\n                                    || c25 < '0' || c25 > '9'\n                                    || c26 < '0' || c26 > '9'\n                                    || c27 < '0' || c27 > '9'\n                                    || c28 < '0' || c28 > '9') {\n                                throw new IllegalArgumentException(new String(str, UTF8));\n                            }\n\n                            nanos = (c23 - '0') * 100000\n                                    + (c24 - '0') * 10000\n                                    + (c25 - '0') * 1000\n                                    + (c26 - '0') * 100\n                                    + (c27 - '0') * 10\n                                    + (c28 - '0');\n                        } else if (len == 28) {\n                            final byte c23 = str[off + 23];\n                            final byte c24 = str[off + 24];\n                            final byte c25 = str[off + 25];\n                            final byte c26 = str[off + 26];\n                            final byte c27 = str[off + 27];\n\n                            if (c23 < '0' || c23 > '9'\n                                    || c24 < '0' || c24 > '9'\n                                    || c25 < '0' || c25 > '9'\n                                    || c26 < '0' || c26 > '9'\n                                    || c27 < '0' || c27 > '9') {\n                                throw new IllegalArgumentException(new String(str, UTF8));\n                            }\n\n                            nanos = (c23 - '0') * 100000\n                                    + (c24 - '0') * 10000\n                                    + (c25 - '0') * 1000\n                                    + (c26 - '0') * 100\n                                    + (c27 - '0') * 10;\n                        } else if (len == 27) {\n                            final byte c23 = str[off + 23];\n                            final byte c24 = str[off + 24];\n                            final byte c25 = str[off + 25];\n                            final byte c26 = str[off + 26];\n\n                            if (c23 < '0' || c23 > '9'\n                                    || c24 < '0' || c24 > '9'\n                                    || c25 < '0' || c25 > '9'\n                                    || c26 < '0' || c26 > '9') {\n                                throw new IllegalArgumentException(new String(str, UTF8));\n                            }\n\n                            nanos = (c23 - '0') * 100000\n                                    + (c24 - '0') * 10000\n                                    + (c25 - '0') * 1000\n                                    + (c26 - '0') * 100;\n                        } else if (len == 26) {\n                            final byte c23 = str[off + 23];\n                            final byte c24 = str[off + 24];\n                            final byte c25 = str[off + 25];\n\n                            if (c23 < '0' || c23 > '9'\n                                    || c24 < '0' || c24 > '9'\n                                    || c25 < '0' || c25 > '9') {\n                                throw new IllegalArgumentException(new String(str, UTF8));\n                            }\n\n                            nanos = (c23 - '0') * 100000\n                                    + (c24 - '0') * 10000\n                                    + (c25 - '0') * 1000;\n                        }\n\n                        break;\n                    }\n                }\n\n                if (c4 != '-') {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n\n                int off2;\n                if (c6 == '-') {\n                    M0 = '0';\n                    M1 = c5;\n                    off2 = off + 7;\n                } else if (c7 == '-') {\n                    M0 = c5;\n                    M1 = c6;\n                    off2 = off + 8;\n                } else {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n\n            {\n                byte n0 = str[off2];\n                byte n1, n2;\n\n                if ((n1 = str[off2 + 1]) == ' ' || n1 == 'T') {\n                    d0 = '0';\n                    d1 = n0;\n                    off2 += 2;\n                } else if ((n2 = str[off2 + 2]) == ' ' || n2 == 'T') {\n                    d0 = n0;\n                    d1 = n1;\n                    off2 += 3;\n                } else {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n            }\n\n            {\n                byte n0 = str[off2];\n                byte n1, n2;\n\n                if ((n1 = str[off2 + 1]) == ':') {\n                    h0 = '0';\n                    h1 = n0;\n                    off2 += 2;\n                } else if ((n2 = str[off2 + 2]) == ':') {\n                    h0 = n0;\n                    h1 = n1;\n                    off2 += 3;\n                } else {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n            }\n\n            {\n                byte n0 = str[off2];\n                byte n1, n2;\n\n                if ((n1 = str[off2 + 1]) == ':') {\n                    m0 = '0';\n                    m1 = n0;\n                    off2 += 2;\n                } else if (off2 + 2 < off + len && (n2 = str[off2 + 2]) == ':') {\n                    m0 = n0;\n                    m1 = n1;\n                    off2 += 3;\n                } else {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n            }\n\n            if (off2 == off + len - 1) {\n                s0 = '0';\n                s1 = str[off2];\n            } else if (off2 == off + len - 2) {\n                byte n0 = str[off2];\n                byte n1 = str[off2 + 1];\n                if (n1 == '.') {\n                    s0 = '0';\n                    s1 = n0;\n                } else {\n                    s0 = n0;\n                    s1 = n1;\n                }\n            } else {\n                byte x0 = str[off + len - 1];\n                byte x1 = str[off + len - 2];\n                byte x2 = str[off + len - 3];\n                byte x3 = str[off + len - 4];\n\n                int lastOff;\n                if (x0 == '.') {\n                    // skip\n                    lastOff = off + len - 2;\n                } else if (x1 == '.') {\n                    S0 = x0;\n                    lastOff = off + len - 3;\n                } else if (x2 == '.') {\n                    S0 = x1;\n                    S1 = x0;\n                    lastOff = off + len - 4;\n                } else if (x3 == '.') {\n                    S0 = x2;\n                    S1 = x1;\n                    S2 = x0;\n                    lastOff = off + len - 5;\n                } else {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n\n                byte k0 = str[lastOff];\n                byte k1 = str[lastOff - 1];\n                byte k2 = str[lastOff - 2];\n                if (k1 == ':') {\n                    s0 = '0';\n                    s1 = k0;\n                } else if (k2 == ':') {\n                    s1 = k0;\n                    s0 = k1;\n                } else {\n                    throw new IllegalArgumentException(new String(str, UTF8));\n                }\n            }\n            break;\n            default:\n                throw new IllegalArgumentException(new String(str, UTF8));\n        }\n\n        if (y0 < '0' || y0 > '9'\n                || y1 < '0' || y1 > '9'\n                || y2 < '0' || y2 > '9'\n                || y3 < '0' || y3 > '9') {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n        int year = (y0 - '0') * 1000\n                + (y1 - '0') * 100\n                + (y2 - '0') * 10\n                + (y3 - '0');\n\n        if (M0 < '0' || M0 > '1') {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n        if (M1 < '0' || M1 > '9') {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n        int month = (M0 - '0') * 10 + (M1 - '0');\n        if (month < 1 || month > 12) {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n\n        if (d0 < '0' || d0 > '9') {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n        if (d1 < '0' || d1 > '9') {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n        int dayOfMonth = (d0 - '0') * 10 + (d1 - '0');\n        if (dayOfMonth < 1) {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n\n        final int maxDayOfMonth;\n        switch (month) {\n            case 2:\n                maxDayOfMonth = 29;\n                break;\n            case 4:\n            case 6:\n            case 9:\n            case 11:\n                maxDayOfMonth = 30;\n                break;\n            default:\n                maxDayOfMonth = 31;\n                break;\n        }\n        if (dayOfMonth > maxDayOfMonth) {\n            throw new IllegalArgumentException(new String(str, UTF8));\n        }\n\n        ZonedDateTime zdt;\n        if (h0 == 0) {\n            zdt = LocalDate\n                    .of(year, month, dayOfMonth)\n                    .atStartOfDay(zoneId);\n        } else {\n            int hour = (h0 - '0') * 10 + (h1 - '0');\n            int minute = (m0 - '0') * 10 + (m1 - '0');\n            int second = (s0 - '0') * 10 + (s1 - '0');\n            int nanoSecond = ((S0 - '0') * 100 + (S1 - '0') * 10 + (S2 - '0')) * 1000000 + nanos;\n\n            if (hour > 24 || minute > 60 || second > 61) {\n                throw new IllegalArgumentException(new String(str, UTF8));\n            }\n\n            zdt = LocalDateTime\n                    .of(year, month, dayOfMonth, hour, minute, second, nanoSecond)\n                    .atZone(zoneId);\n        }\n\n        return zdt;\n    }\n\n    private static final String[] parseFormats = new String[]{\n            \"HH:mm:ss\",\n            \"yyyyMMdd\",\n            \"yyyyMMddHHmmss\",\n            \"yyyy-M-d\",\n            \"yyyy-M-d H:m:s\",\n            \"yyyy-M-d H:m:s.S\",\n            \"yyyy-M-d'T'H:m:s\",\n            \"yyyy-M-d'T'H:m:s.S\",\n            \"yyyy-MM-d\",\n            \"yyyy-MM-dd HH:mm:ss\",\n            \"yyyy-MM-dd HH:mm:ss.SSS\",\n            \"yyyy-MM-dd'T'HH:mm:ss\",\n            \"yyyy-MM-dd'T'HH:mm:ss.SSS\",\n    };\n    private static final long[] parseFormatCodes;\n\n    static {\n        long[] codes = new long[parseFormats.length];\n        for (int i = 0; i < parseFormats.length; i++) {\n            codes[i] = FnvHash.fnv1a_64(parseFormats[i]);\n        }\n        Arrays.sort(codes);\n        parseFormatCodes = codes;\n    }\n\n    public static boolean isSupportParseDateformat(String str) {\n        if (str == null) {\n            return false;\n        }\n        return Arrays.binarySearch(parseFormatCodes, FnvHash.fnv1a_64(str)) >= 0;\n    }\n\n    public static TimeZone parseTimeZone(String str) {\n        if (\"SYSTEM\".equalsIgnoreCase(str)) {\n            return TimeZone.getDefault();\n        }\n\n        return TimeZone.getTimeZone(str);\n    }\n\n    public static String utf32(String hex) {\n        byte[] bytes = HexBin.decode(hex);\n        if (bytes.length == 2) {\n            return new String(bytes, UTF16);\n        }\n        return new String(bytes, UTF32);\n    }\n\n    public static String utf16(String hex) {\n        if (hex.length() % 2 == 1) {\n            char[] chars = new char[hex.length() + 1];\n            chars[0] = '0';\n            hex.getChars(0, hex.length(), chars, 1);\n            hex = new String(chars);\n        }\n\n        byte[] bytes = HexBin.decode(hex);\n        if (bytes == null) {\n            return null;\n        }\n        return new String(bytes, UTF16);\n    }\n\n    public static String utf8(String hex) {\n        byte[] bytes = HexBin.decode(hex);\n        return new String(bytes, UTF8);\n    }\n\n    public static String gbk(String hex) {\n        byte[] bytes = HexBin.decode(hex);\n        return new String(bytes, GBK);\n    }\n\n    public static String big5(String hex) {\n        byte[] bytes = HexBin.decode(hex);\n        return new String(bytes, BIG5);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/OdpsUtils.java",
    "content": "package com.alibaba.druid.util;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\n\npublic class OdpsUtils {\n    public static final SQLDialect DIALECT = SQLDialect.of(DbType.odps);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/OracleUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport oracle.jdbc.OracleConnection;\nimport oracle.jdbc.OracleResultSet;\nimport oracle.jdbc.OracleStatement;\nimport oracle.jdbc.driver.T4CXAConnection;\nimport oracle.jdbc.internal.OraclePreparedStatement;\nimport oracle.jdbc.xa.client.OracleXAConnection;\nimport oracle.sql.ROWID;\n\nimport javax.sql.XAConnection;\nimport javax.transaction.xa.XAException;\n\nimport java.sql.*;\nimport java.util.*;\n\npublic class OracleUtils {\n    private static final Log LOG = LogFactory.getLog(OracleUtils.class);\n\n    public static XAConnection OracleXAConnection(Connection oracleConnection) throws XAException {\n        String oracleConnectionClassName = oracleConnection.getClass().getName();\n        if (\"oracle.jdbc.driver.T4CConnection\".equals(oracleConnectionClassName)) {\n            return new T4CXAConnection(oracleConnection);\n        } else {\n            return new OracleXAConnection(oracleConnection);\n        }\n    }\n\n    public static int getRowPrefetch(PreparedStatement stmt) throws SQLException {\n        OracleStatement oracleStmt = stmt.unwrap(OracleStatement.class);\n\n        if (oracleStmt == null) {\n            return -1;\n        }\n\n        return oracleStmt.getRowPrefetch();\n    }\n\n    public static void setRowPrefetch(PreparedStatement stmt, int value) throws SQLException {\n        OracleStatement oracleStmt = stmt.unwrap(OracleStatement.class);\n        if (oracleStmt != null) {\n            oracleStmt.setRowPrefetch(value);\n        }\n    }\n\n    public static void enterImplicitCache(PreparedStatement stmt) throws SQLException {\n        oracle.jdbc.internal.OraclePreparedStatement oracleStmt = unwrapInternal(stmt);\n        if (oracleStmt != null) {\n            oracleStmt.enterImplicitCache();\n        }\n    }\n\n    public static void exitImplicitCacheToClose(PreparedStatement stmt) throws SQLException {\n        oracle.jdbc.internal.OraclePreparedStatement oracleStmt = unwrapInternal(stmt);\n        if (oracleStmt != null) {\n            oracleStmt.exitImplicitCacheToClose();\n        }\n    }\n\n    public static void exitImplicitCacheToActive(PreparedStatement stmt) throws SQLException {\n        oracle.jdbc.internal.OraclePreparedStatement oracleStmt = unwrapInternal(stmt);\n        if (oracleStmt != null) {\n            oracleStmt.exitImplicitCacheToActive();\n        }\n    }\n\n    public static OraclePreparedStatement unwrapInternal(PreparedStatement stmt) throws SQLException {\n        if (stmt instanceof OraclePreparedStatement) {\n            return (OraclePreparedStatement) stmt;\n        }\n\n        OraclePreparedStatement unwrapped = stmt.unwrap(OraclePreparedStatement.class);\n\n        if (unwrapped == null) {\n            LOG.error(\"can not unwrap statement : \" + stmt.getClass());\n        }\n\n        return unwrapped;\n    }\n\n    public static short getVersionNumber(DruidPooledConnection conn) throws SQLException {\n        oracle.jdbc.internal.OracleConnection oracleConn = (oracle.jdbc.internal.OracleConnection) unwrap(conn);\n        return oracleConn.getVersionNumber();\n    }\n\n    public static void setDefaultRowPrefetch(Connection conn, int value) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        oracleConn.setDefaultRowPrefetch(value);\n    }\n\n    public static int getDefaultRowPrefetch(Connection conn, int value) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        return oracleConn.getDefaultRowPrefetch();\n    }\n\n    public static boolean getImplicitCachingEnabled(Connection conn) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        return oracleConn.getImplicitCachingEnabled();\n    }\n\n    public static int getStatementCacheSize(Connection conn) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        return oracleConn.getStatementCacheSize();\n    }\n\n    public static void purgeImplicitCache(Connection conn) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        oracleConn.purgeImplicitCache();\n    }\n\n    public static void setImplicitCachingEnabled(Connection conn, boolean cache) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        oracleConn.setImplicitCachingEnabled(cache);\n    }\n\n    public static void setStatementCacheSize(Connection conn, int size) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        oracleConn.setStatementCacheSize(size);\n    }\n\n    public static int pingDatabase(Connection conn) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        return oracleConn.pingDatabase();\n    }\n\n    public static void openProxySession(Connection conn, int type, java.util.Properties prop) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        oracleConn.openProxySession(type, prop);\n    }\n\n    public static int getDefaultExecuteBatch(Connection conn) throws SQLException {\n        OracleConnection oracleConn = unwrap(conn);\n        return oracleConn.getDefaultExecuteBatch();\n    }\n\n    public static OracleConnection unwrap(Connection conn) throws SQLException {\n        if (conn instanceof OracleConnection) {\n            return (OracleConnection) conn;\n        }\n\n        return conn.unwrap(OracleConnection.class);\n    }\n\n    public static ROWID getROWID(ResultSet rs, int columnIndex) throws SQLException {\n        OracleResultSet oracleResultSet = rs.unwrap(OracleResultSet.class);\n        return oracleResultSet.getROWID(columnIndex);\n    }\n\n    private static Set<String> builtinFunctions;\n\n    public static boolean isBuiltinFunction(String function) {\n        if (function == null) {\n            return false;\n        }\n\n        String function_lower = function.toLowerCase();\n\n        Set<String> functions = builtinFunctions;\n\n        if (functions == null) {\n            functions = new HashSet<String>();\n            Utils.loadFromFile(\"META-INF/druid/parser/oracle/builtin_functions\", functions);\n            builtinFunctions = functions;\n        }\n\n        return functions.contains(function_lower);\n    }\n\n    private static Set<String> builtinTables;\n\n    public static boolean isBuiltinTable(String table) {\n        if (table == null) {\n            return false;\n        }\n\n        String table_lower = table.toLowerCase();\n\n        Set<String> tables = builtinTables;\n\n        if (tables == null) {\n            tables = new HashSet<String>();\n            Utils.loadFromFile(\"META-INF/druid/parser/oracle/builtin_tables\", tables);\n            builtinTables = tables;\n        }\n\n        return tables.contains(table_lower);\n    }\n\n    private static Set<String> keywords;\n\n    public static boolean isKeyword(String name) {\n        if (name == null) {\n            return false;\n        }\n\n        String name_lower = name.toLowerCase();\n\n        Set<String> words = keywords;\n\n        if (words == null) {\n            words = new HashSet<String>();\n            Utils.loadFromFile(\"META-INF/druid/parser/oracle/keywords\", words);\n            keywords = words;\n        }\n\n        return words.contains(name_lower);\n    }\n\n    public static List<String> showTables(Connection conn) throws SQLException {\n        List<String> tables = new ArrayList<String>();\n\n        Statement stmt = null;\n        ResultSet rs = null;\n        try {\n            stmt = conn.createStatement();\n            rs = stmt.executeQuery(\"select table_name from user_tables\");\n            while (rs.next()) {\n                String tableName = rs.getString(1);\n                tables.add(tableName);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n        }\n\n        return tables;\n    }\n\n    public static List<String> getTableDDL(Connection conn, String... tables) throws SQLException {\n        return getTableDDL(conn, Arrays.asList(tables));\n    }\n\n    public static List<String> getTableDDL(Connection conn, List<String> tables) throws SQLException {\n        List<String> ddlList = new ArrayList<String>();\n\n        PreparedStatement pstmt = null;\n        ResultSet rs = null;\n        try {\n            StringBuilder sql = new StringBuilder();\n            sql.append(\"select DBMS_METADATA.GET_DDL('TABLE', TABLE_NAME) FROM user_tables\");\n\n            if (tables.size() > 0) {\n                sql.append(\" WHERE TABLE_NAME IN (\");\n                for (int i = 0; i < tables.size(); ++i) {\n                    if (i != 0) {\n                        sql.append(\", ?\");\n                    } else {\n                        sql.append(\"?\");\n                    }\n                }\n                sql.append(\")\");\n            }\n            pstmt = conn.prepareStatement(sql.toString());\n            for (int i = 0; i < tables.size(); ++i) {\n                pstmt.setString(i + 1, tables.get(i));\n            }\n            rs = pstmt.executeQuery();\n            while (rs.next()) {\n                String ddl = rs.getString(1);\n                ddlList.add(ddl);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(pstmt);\n        }\n\n        return ddlList;\n    }\n\n    public static String getCreateTableScript(Connection conn) throws SQLException {\n        return getCreateTableScript(conn, true, true);\n    }\n\n    public static String getCreateTableScript(Connection conn, boolean sorted, boolean simplify) throws SQLException {\n        List<String> ddlList = OracleUtils.getTableDDL(conn);\n\n        StringBuilder buf = new StringBuilder();\n        for (String ddl : ddlList) {\n            buf.append(ddl);\n            buf.append(';');\n        }\n\n        String ddlScript = buf.toString();\n\n        if (!(sorted || simplify)) {\n            return ddlScript;\n        }\n\n        List stmtList = SQLUtils.parseStatements(ddlScript, DbType.oracle);\n        if (simplify) {\n            for (Object o : stmtList) {\n                if (o instanceof SQLCreateTableStatement) {\n                    SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) o;\n                    createTableStmt.simplify();\n                }\n            }\n        }\n\n        if (sorted) {\n            SQLCreateTableStatement.sort(stmtList);\n        }\n        return SQLUtils.toSQLString(stmtList, DbType.oracle);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/PGUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport org.postgresql.core.BaseConnection;\nimport org.postgresql.xa.PGXAConnection;\n\nimport javax.sql.XAConnection;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.*;\n\npublic class PGUtils {\n    public static XAConnection createXAConnection(Connection physicalConn) throws SQLException {\n        return new PGXAConnection((BaseConnection) physicalConn);\n    }\n\n    public static List<String> showTables(Connection conn) throws SQLException {\n        List<String> tables = new ArrayList<String>();\n\n        Statement stmt = null;\n        ResultSet rs = null;\n        try {\n            stmt = conn.createStatement();\n            rs = stmt.executeQuery(\"SELECT tablename FROM pg_catalog.pg_tables where schemaname not in ('pg_catalog', 'information_schema', 'sys')\");\n            while (rs.next()) {\n                String tableName = rs.getString(1);\n                tables.add(tableName);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n        }\n\n        return tables;\n    }\n\n    private static Set<String> keywords;\n\n    public static boolean isKeyword(String name) {\n        if (name == null) {\n            return false;\n        }\n\n        String name_lower = name.toLowerCase();\n\n        Set<String> words = keywords;\n\n        if (words == null) {\n            words = new HashSet<String>();\n            Utils.loadFromFile(\"META-INF/druid/parser/postgresql/keywords\", words);\n            keywords = words;\n        }\n\n        return words.contains(name_lower);\n    }\n\n    private static final long[] pseudoColumnHashCodes;\n\n    static {\n        long[] array = {\n                FnvHash.Constants.CURRENT_TIMESTAMP\n        };\n        Arrays.sort(array);\n        pseudoColumnHashCodes = array;\n    }\n\n    public static boolean isPseudoColumn(long hash) {\n        return Arrays.binarySearch(pseudoColumnHashCodes, hash) >= 0;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/PatternMatcher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\n/**\n * Interface for components that can match source strings against a specified pattern string.\n * Different implementations can support different pattern types, for example, Ant style path expressions, or regular\n * expressions, or other types of text based patterns.\n *\n * @since 0.2.6\n */\npublic interface PatternMatcher {\n    /**\n     * Returns <code>true</code> if the given <code>source</code> matches the specified <code>pattern</code>,\n     * <code>false</code> otherwise.\n     *\n     * @param pattern the pattern to match against\n     * @param source  the source to match\n     * @return <code>true</code> if the given <code>source</code> matches the specified <code>pattern</code>,\n     * <code>false</code> otherwise.\n     */\n    boolean matches(String pattern, String source);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/ResultSetConsumer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\n/**\n * Created by wenshao on 03/06/2017.\n */\npublic interface ResultSetConsumer<T> {\n    T apply(ResultSet rs) throws SQLException;\n\n    void accept(T object);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/ServletPathMatcher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\npublic class ServletPathMatcher implements PatternMatcher {\n    private static final ServletPathMatcher INSTANCE = new ServletPathMatcher();\n\n    public static ServletPathMatcher getInstance() {\n        return INSTANCE;\n    }\n\n    private ServletPathMatcher() {\n    }\n\n    /**\n     * <p>\n     * three type: endsWithMatch(eg. /xxx*=/xxx/xyz), startsWithMatch(eg.\n     * *.xxx=abc.xxx), equals(eg. /xxx=/xxx).\n     * </p>\n     * <b>Notice</b>: *xxx* will match *xxxyyyy. endsWithMatch first.\n     */\n    @Override\n    public boolean matches(String pattern, String source) {\n        if (pattern == null || source == null) {\n            return false;\n        }\n        pattern = pattern.trim();\n        source = source.trim();\n        if (pattern.endsWith(\"*\")) {\n            // pattern: /druid* source:/druid/index.html\n            int length = pattern.length() - 1;\n            if (source.length() >= length) {\n                if (pattern.substring(0, length).equals(\n                        source.substring(0, length))) {\n                    return true;\n                }\n            }\n        } else if (pattern.startsWith(\"*\")) {\n            // pattern: *.html source:/xx/xx.html\n            int length = pattern.length() - 1;\n            if (source.length() >= length\n                    && source.endsWith(pattern.substring(1))) {\n                return true;\n            }\n        } else if (pattern.contains(\"*\")) {\n            // pattern:  /druid/*/index.html source:/druid/admin/index.html\n            int start = pattern.indexOf(\"*\");\n            int end = pattern.lastIndexOf(\"*\");\n            if (source.startsWith(pattern.substring(0, start))\n                    && source.endsWith(pattern.substring(end + 1))) {\n                return true;\n            }\n        } else {\n            // pattern: /druid/index.html source:/druid/index.html\n            if (pattern.equals(source)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/StringUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.Calendar;\nimport java.util.TimeZone;\n\n/**\n * @author sandzhang[sandzhangtoo@gmail.com]\n */\npublic class StringUtils {\n    private static final Log LOG = LogFactory.getLog(StringUtils.class);\n\n    private StringUtils() {\n    }\n\n    /**\n     * Example: subString(\"12345\",\"1\",\"4\")=23\n     *\n     * @param src   the source string from which to extract the substring\n     * @param start the starting point of the substring\n     * @param to    the ending point of the substring\n     * @return the extracted substring converted to an Integer, or null if any of the input strings is null\n     */\n    public static Integer subStringToInteger(String src, String start, String to) {\n        return stringToInteger(subString(src, start, to));\n    }\n\n    /**\n     * Example: subString(\"abcd\",\"a\",\"c\")=\"b\"\n     *\n     * @param src   the source string from which to extract the substring\n     * @param start null while start from index=0\n     * @param to    null while to index=src.length\n     * @return the extracted substring, or null if any of the input strings is null\n     */\n    public static String subString(String src, String start, String to) {\n        return subString(src, start, to, false);\n    }\n\n    /**\n     * Example: subString(\"abcdc\",\"a\",\"c\",true)=\"bcd\"\n     *\n     * @param src    the source string from which to extract the substring\n     * @param start  null while start from index=0\n     * @param to     null while to index=src.length\n     * @param toLast true while to index=src.lastIndexOf(to)\n     * @return the extracted substring, or null if any of the input strings is null, or if the start/end points are invalid\n     */\n    public static String subString(String src, String start, String to, boolean toLast) {\n        int indexFrom = start == null ? 0 : src.indexOf(start);\n        int indexTo;\n        if (to == null) {\n            indexTo = src.length();\n        } else {\n            indexTo = toLast ? src.lastIndexOf(to) : src.indexOf(to);\n        }\n        if (indexFrom < 0 || indexTo < 0 || indexFrom > indexTo) {\n            return null;\n        }\n\n        if (null != start) {\n            indexFrom += start.length();\n        }\n\n        return src.substring(indexFrom, indexTo);\n    }\n\n    /**\n     * Converts a string representation of an integer to an Integer object.\n     *\n     * @param in the input string to be converted (can be null)\n     * @return the Integer object parsed from the input string, or null if the input is null, empty, or not a valid integer\n     */\n    public static Integer stringToInteger(String in) {\n        if (in == null) {\n            return null;\n        }\n        in = in.trim();\n        if (in.length() == 0) {\n            return null;\n        }\n\n        try {\n            return Integer.parseInt(in);\n        } catch (NumberFormatException e) {\n            LOG.warn(\"stringToInteger fail,string=\" + in, e);\n            return null;\n        }\n    }\n\n    public static boolean equals(String a, String b) {\n        if (a == null) {\n            return b == null;\n        }\n        return a.equals(b);\n    }\n\n    public static boolean equalsIgnoreCase(String a, String b) {\n        if (a == null) {\n            return b == null;\n        }\n        return a.equalsIgnoreCase(b);\n    }\n\n    public static boolean isEmpty(CharSequence value) {\n        return value == null || value.length() == 0;\n    }\n\n    public static int lowerHashCode(String text) {\n        if (text == null) {\n            return 0;\n        }\n//        return text.toLowerCase().hashCode();\n        int h = 0;\n        for (int i = 0; i < text.length(); ++i) {\n            char ch = text.charAt(i);\n            if (ch >= 'A' && ch <= 'Z') {\n                ch = (char) (ch + 32);\n            }\n\n            h = 31 * h + ch;\n        }\n        return h;\n    }\n\n    public static boolean isNumber(String str) {\n        if (str == null || str.length() == 0) {\n            return false;\n        }\n        int sz = str.length();\n        boolean hasExp = false;\n        boolean hasDecPoint = false;\n        boolean allowSigns = false;\n        boolean foundDigit = false;\n        // deal with any possible sign up front\n        int start = (str.charAt(0) == '-') ? 1 : 0;\n        if (sz > start + 1) {\n            if (str.charAt(start) == '0' && str.charAt(start + 1) == 'x') {\n                int i = start + 2;\n                if (i == sz) {\n                    return false; // str == \"0x\"\n                }\n                // checking hex (it can't be anything else)\n                for (; i < str.length(); i++) {\n                    char ch = str.charAt(i);\n                    if ((ch < '0' || ch > '9')\n                            && (ch < 'a' || ch > 'f')\n                            && (ch < 'A' || ch > 'F')) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n        }\n        sz--; // don't want to loop to the last char, check it afterwords\n        // for type qualifiers\n        int i = start;\n        // loop to the next to last char or to the last char if we need another digit to\n        // make a valid number (e.g. chars[0..5] = \"1234E\")\n        while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {\n            char ch = str.charAt(i);\n            if (ch >= '0' && ch <= '9') {\n                foundDigit = true;\n                allowSigns = false;\n\n            } else if (ch == '.') {\n                if (hasDecPoint || hasExp) {\n                    // two decimal points or dec in exponent\n                    return false;\n                }\n                hasDecPoint = true;\n            } else if (ch == 'e' || ch == 'E') {\n                // we've already taken care of hex.\n                if (hasExp) {\n                    // two E's\n                    return false;\n                }\n                if (!foundDigit) {\n                    return false;\n                }\n                hasExp = true;\n                allowSigns = true;\n            } else if (ch == '+' || ch == '-') {\n                if (!allowSigns) {\n                    return false;\n                }\n                allowSigns = false;\n                foundDigit = false; // we need a digit after the E\n            } else {\n                return false;\n            }\n            i++;\n        }\n        if (i < str.length()) {\n            char ch = str.charAt(i);\n\n            if (ch >= '0' && ch <= '9') {\n                // no type qualifier, OK\n                return true;\n            }\n            if (ch == 'e' || ch == 'E') {\n                // can't have an E at the last byte\n                return false;\n            }\n            if (!allowSigns\n                    && (ch == 'd'\n                    || ch == 'D'\n                    || ch == 'f'\n                    || ch == 'F')) {\n                return foundDigit;\n            }\n            if (ch == 'l'\n                    || ch == 'L') {\n                // not allowing L with an exponent\n                return foundDigit && !hasExp;\n            }\n            // last character is illegal\n            return false;\n        }\n        // allowSigns is true iff the val ends in 'E'\n        // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass\n        return !allowSigns && foundDigit;\n    }\n\n    public static boolean isNumber(char[] chars) {\n        if (chars == null || chars.length == 0) {\n            return false;\n        }\n        int sz = chars.length;\n        boolean hasExp = false;\n        boolean hasDecPoint = false;\n        boolean allowSigns = false;\n        boolean foundDigit = false;\n        // deal with any possible sign up front\n        int start = (chars[0] == '-') ? 1 : 0;\n        if (sz > start + 1) {\n            if (chars[start] == '0' && chars[start + 1] == 'x') {\n                int i = start + 2;\n                if (i == sz) {\n                    return false; // str == \"0x\"\n                }\n                // checking hex (it can't be anything else)\n                for (; i < chars.length; i++) {\n                    char ch = chars[i];\n                    if ((ch < '0' || ch > '9')\n                            && (ch < 'a' || ch > 'f')\n                            && (ch < 'A' || ch > 'F')) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n        }\n        sz--; // don't want to loop to the last char, check it afterwords\n        // for type qualifiers\n        int i = start;\n        // loop to the next to last char or to the last char if we need another digit to\n        // make a valid number (e.g. chars[0..5] = \"1234E\")\n        while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {\n            char ch = chars[i];\n            if (ch >= '0' && ch <= '9') {\n                foundDigit = true;\n                allowSigns = false;\n\n            } else if (ch == '.') {\n                if (hasDecPoint || hasExp) {\n                    // two decimal points or dec in exponent\n                    return false;\n                }\n                hasDecPoint = true;\n            } else if (ch == 'e' || ch == 'E') {\n                // we've already taken care of hex.\n                if (hasExp) {\n                    // two E's\n                    return false;\n                }\n                if (!foundDigit) {\n                    return false;\n                }\n                hasExp = true;\n                allowSigns = true;\n            } else if (ch == '+' || ch == '-') {\n                if (!allowSigns) {\n                    return false;\n                }\n                allowSigns = false;\n                foundDigit = false; // we need a digit after the E\n            } else {\n                return false;\n            }\n            i++;\n        }\n        if (i < chars.length) {\n            char ch = chars[i];\n            if (ch >= '0' && ch <= '9') {\n                // no type qualifier, OK\n                return true;\n            }\n            if (ch == 'e' || ch == 'E') {\n                // can't have an E at the last byte\n                return false;\n            }\n            if (!allowSigns\n                    && (ch == 'd'\n                    || ch == 'D'\n                    || ch == 'f'\n                    || ch == 'F')) {\n                return foundDigit;\n            }\n            if (ch == 'l'\n                    || ch == 'L') {\n                // not allowing L with an exponent\n                return foundDigit && !hasExp;\n            }\n\n            if (ch == '.') {\n                return true;\n            }\n            // last character is illegal\n            return false;\n        }\n        // allowSigns is true iff the val ends in 'E'\n        // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass\n        return !allowSigns && foundDigit;\n    }\n\n    public static String formatDateTime19(long millis, TimeZone timeZone) {\n        Calendar cale = timeZone == null\n                ? Calendar.getInstance()\n                : Calendar.getInstance(timeZone);\n        cale.setTimeInMillis(millis);\n\n        int year = cale.get(Calendar.YEAR);\n        int month = cale.get(Calendar.MONTH) + 1;\n        int dayOfMonth = cale.get(Calendar.DAY_OF_MONTH);\n        int hour = cale.get(Calendar.HOUR_OF_DAY);\n        int minute = cale.get(Calendar.MINUTE);\n        int second = cale.get(Calendar.SECOND);\n\n        char[] chars = new char[19];\n        chars[0] = (char) (year / 1000 + '0');\n        chars[1] = (char) ((year / 100) % 10 + '0');\n        chars[2] = (char) ((year / 10) % 10 + '0');\n        chars[3] = (char) (year % 10 + '0');\n        chars[4] = '-';\n        chars[5] = (char) (month / 10 + '0');\n        chars[6] = (char) (month % 10 + '0');\n        chars[7] = '-';\n        chars[8] = (char) (dayOfMonth / 10 + '0');\n        chars[9] = (char) (dayOfMonth % 10 + '0');\n        chars[10] = ' ';\n        chars[11] = (char) (hour / 10 + '0');\n        chars[12] = (char) (hour % 10 + '0');\n        chars[13] = ':';\n        chars[14] = (char) (minute / 10 + '0');\n        chars[15] = (char) (minute % 10 + '0');\n        chars[16] = ':';\n        chars[17] = (char) (second / 10 + '0');\n        chars[18] = (char) (second % 10 + '0');\n        return new String(chars);\n    }\n\n    public static String removeNameQuotes(String s) {\n        if (s == null || s.length() <= 1) {\n            return null;\n        }\n        int len = s.length();\n        char c0 = s.charAt(0);\n        char last = s.charAt(len - 1);\n\n        if (c0 == last && (c0 == '`' || c0 == '\\'' || c0 == '\\\"')) {\n            return s.substring(1, len - 1);\n        }\n        return s;\n    }\n\n    public static String replaceAll(String s, String src, String dest) {\n        if (s == null || src == null || dest == null || src.length() == 0) {\n            return s;\n        }\n        int pos = s.indexOf(src);\n        if (pos < 0) {\n            return s;\n        }\n        int capacity = dest.length() > src.length() ? s.length() * 2 : s.length();\n        StringBuilder sb = new StringBuilder(capacity);\n        int writen = 0;\n        for (; pos >= 0; ) {\n            sb.append(s, writen, pos);\n            sb.append(dest);\n            writen = pos + src.length();\n            pos = s.indexOf(src, writen);\n        }\n        sb.append(s, writen, s.length());\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/TransactionInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class TransactionInfo {\n    private final long id;\n    private final List<String> sqlList = new ArrayList<String>(4);\n    private final long startTimeMillis;\n    private long endTimeMillis;\n\n    public TransactionInfo(long id) {\n        this.id = id;\n        this.startTimeMillis = System.currentTimeMillis();\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    public List<String> getSqlList() {\n        return sqlList;\n    }\n\n    public long getStartTimeMillis() {\n        return startTimeMillis;\n    }\n\n    public long getEndTimeMillis() {\n        return endTimeMillis;\n    }\n\n    public void setEndTimeMillis() {\n        if (endTimeMillis == 0) {\n            endTimeMillis = System.currentTimeMillis();\n        }\n    }\n\n    public void setEndTimeMillis(long endTimeMillis) {\n        this.endTimeMillis = endTimeMillis;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/Utils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util;\n\nimport java.io.*;\nimport java.lang.management.ManagementFactory;\nimport java.nio.charset.StandardCharsets;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.util.function.Consumer;\n\npublic class Utils {\n    public static final int DEFAULT_BUFFER_SIZE = 1024 * 4;\n\n    public static String read(InputStream in) {\n        if (in == null) {\n            return null;\n        }\n\n        InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);\n        return read(reader);\n    }\n\n    public static Properties loadProperties(String resource) {\n        Properties properties = new Properties();\n        try (InputStream in = Utils.class.getClassLoader().getResourceAsStream(resource)) {\n            if (in != null) {\n                properties.load(in);\n            }\n        } catch (IOException ignore) {\n            // ignored\n        }\n        return properties;\n    }\n\n    public static List<String> readLines(String resource) {\n        List<String> lines = new ArrayList<>();\n        InputStream in = Utils.class.getClassLoader().getResourceAsStream(resource);\n        if (in != null) {\n            try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {\n                for (;;) {\n                    String line = reader.readLine();\n                    if (line == null) {\n                        break;\n                    }\n                    lines.add(line);\n                }\n            } catch (IOException ignore) {\n                // ignored\n            }\n        }\n        return lines;\n    }\n\n    public static String readFromResource(String resource) throws IOException {\n        if (resource == null\n                || resource.isEmpty()\n                || resource.contains(\"..\")\n                || resource.contains(\"?\")\n                || resource.contains(\":\")) {\n            return null;\n        }\n\n        InputStream in = null;\n        try {\n            in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);\n            if (in == null) {\n                in = Utils.class.getResourceAsStream(resource);\n            }\n\n            if (in == null) {\n                return null;\n            }\n\n            String text = Utils.read(in);\n            return text;\n        } finally {\n            JdbcUtils.close(in);\n        }\n    }\n\n    public static byte[] readByteArrayFromResource(String resource) throws IOException {\n        if (resource == null\n                || resource.isEmpty()\n                || resource.contains(\"..\")\n                || resource.contains(\"?\")\n                || resource.contains(\":\")) {\n            return null;\n        }\n\n        InputStream in = null;\n        try {\n            in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);\n            if (in == null) {\n                return null;\n            }\n\n            return readByteArray(in);\n        } finally {\n            JdbcUtils.close(in);\n        }\n    }\n\n    public static byte[] readByteArray(InputStream input) throws IOException {\n        if (input == null) {\n            return null;\n        }\n        ByteArrayOutputStream output = new ByteArrayOutputStream();\n        copy(input, output);\n        byte[] bytes = output.toByteArray();\n        output.close();\n        return bytes;\n    }\n\n    public static long copy(InputStream input, OutputStream output) throws IOException {\n        final int EOF = -1;\n\n        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];\n\n        long count = 0;\n        int n = 0;\n        while (EOF != (n = input.read(buffer))) {\n            output.write(buffer, 0, n);\n            count += n;\n        }\n        return count;\n    }\n\n    public static String read(Reader reader) {\n        if (reader == null) {\n            return null;\n        }\n\n        try {\n            StringWriter writer = new StringWriter();\n\n            char[] buffer = new char[DEFAULT_BUFFER_SIZE];\n            int n = 0;\n            while (-1 != (n = reader.read(buffer))) {\n                writer.write(buffer, 0, n);\n            }\n\n            return writer.toString();\n        } catch (IOException ex) {\n            throw new IllegalStateException(\"read error\", ex);\n        }\n    }\n\n    public static String read(Reader reader, int length) {\n        if (reader == null) {\n            return null;\n        }\n\n        try {\n            char[] buffer = new char[length];\n\n            int offset = 0;\n            int rest = length;\n            int len;\n            while ((len = reader.read(buffer, offset, rest)) != -1) {\n                rest -= len;\n                offset += len;\n\n                if (rest == 0) {\n                    break;\n                }\n            }\n\n            return new String(buffer, 0, length - rest);\n        } catch (IOException ex) {\n            throw new IllegalStateException(\"read error\", ex);\n        }\n    }\n\n    public static String toString(java.util.Date date) {\n        if (date == null) {\n            return null;\n        }\n        return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\")\n                .format(date);\n    }\n\n    public static String getStackTrace(Throwable ex) {\n        StringWriter buf = new StringWriter();\n        ex.printStackTrace(new PrintWriter(buf));\n        return buf.toString();\n    }\n\n    public static String toString(StackTraceElement[] stackTrace) {\n        StringBuilder buf = new StringBuilder();\n        for (StackTraceElement item : stackTrace) {\n            buf.append(item.toString());\n            buf.append(\"\\n\");\n        }\n        return buf.toString();\n    }\n\n    static void trySetIntProperty(Properties properties, String key, Consumer<Integer> setter) {\n        if (properties == null) {\n            return;\n        }\n        if (key == null || setter == null) {\n            return;\n        }\n        String property = properties.getProperty(key);\n        if (property != null && property.length() > 0) {\n            try {\n                int value = Integer.parseInt(property);\n                setter.accept(value);\n            } catch (NumberFormatException ignored) {\n                // ignore\n            }\n        }\n    }\n\n    static void trySetLongProperty(Properties properties, String key, Consumer<Long> setter) {\n        if (properties == null) {\n            return;\n        }\n        if (key == null || setter == null) {\n            return;\n        }\n        String property = properties.getProperty(key);\n        if (property != null && property.length() > 0) {\n            try {\n                long value = Long.parseLong(property);\n                setter.accept(value);\n            } catch (NumberFormatException ignored) {\n                // ignore\n            }\n        }\n    }\n    static void trySetStringProperty(Properties properties, String key, Consumer<String> setter) {\n        if (properties == null) {\n            return;\n        }\n        if (key == null || setter == null) {\n            return;\n        }\n        String value = properties.getProperty(key);\n        if (value != null) {\n            setter.accept(value);\n        }\n    }\n    static void trySetBooleanProperty(Properties properties, String key, Consumer<Boolean> setter) {\n        if (properties == null) {\n            return;\n        }\n        if (key == null || setter == null) {\n            return;\n        }\n        Boolean value = getBoolean(properties, key);\n        if (value != null) {\n            setter.accept(value);\n        }\n    }\n    public static Boolean getBoolean(Properties properties, String key) {\n        String property = properties.getProperty(key);\n        if (\"true\".equals(property)) {\n            return Boolean.TRUE;\n        } else if (\"false\".equals(property)) {\n            return Boolean.FALSE;\n        }\n        return null;\n    }\n\n    public static Integer getInteger(Properties properties, String key) {\n        String property = properties.getProperty(key);\n\n        if (property == null) {\n            return null;\n        }\n        try {\n            return Integer.parseInt(property);\n        } catch (NumberFormatException ex) {\n            // skip\n        }\n        return null;\n    }\n\n    public static Long getLong(Properties properties, String key) {\n        String property = properties.getProperty(key);\n\n        if (property == null) {\n            return null;\n        }\n        try {\n            return Long.parseLong(property);\n        } catch (NumberFormatException ex) {\n            // skip\n        }\n        return null;\n    }\n\n    public static Class<?> loadClass(String className) {\n        Class<?> clazz = null;\n\n        if (className == null) {\n            return null;\n        }\n\n        try {\n            return Class.forName(className);\n        } catch (ClassNotFoundException e) {\n            // skip\n        }\n\n        ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();\n        if (ctxClassLoader != null) {\n            try {\n                clazz = ctxClassLoader.loadClass(className);\n            } catch (ClassNotFoundException e) {\n                // skip\n            }\n        }\n\n        return clazz;\n    }\n\n    private static Date startTime;\n\n    public static final Date getStartTime() {\n        if (startTime == null) {\n            startTime = new Date(ManagementFactory.getRuntimeMXBean().getStartTime());\n        }\n        return startTime;\n    }\n\n    public static long murmurhash2_64(String text) {\n        final byte[] bytes = text.getBytes();\n        return murmurhash2_64(bytes, bytes.length, 0xe17a1465);\n    }\n\n    /**\n     * murmur hash 2.0, The murmur hash is a relatively fast hash function from http://murmurhash.googlepages.com/ for\n     * platforms with efficient multiplication.\n     *\n     * @author Viliam Holub\n     */\n    public static long murmurhash2_64(final byte[] data, int length, int seed) {\n        final long m = 0xc6a4a7935bd1e995L;\n        final int r = 47;\n\n        long h = (seed & 0xffffffffL) ^ (length * m);\n\n        int length8 = length / 8;\n\n        for (int i = 0; i < length8; i++) {\n            final int i8 = i * 8;\n            long k = ((long) data[i8 + 0] & 0xff) //\n                    + (((long) data[i8 + 1] & 0xff) << 8) //\n                    + (((long) data[i8 + 2] & 0xff) << 16)//\n                    + (((long) data[i8 + 3] & 0xff) << 24) //\n                    + (((long) data[i8 + 4] & 0xff) << 32)//\n                    + (((long) data[i8 + 5] & 0xff) << 40)//\n                    + (((long) data[i8 + 6] & 0xff) << 48) //\n                    + (((long) data[i8 + 7] & 0xff) << 56);\n\n            k *= m;\n            k ^= k >>> r;\n            k *= m;\n\n            h ^= k;\n            h *= m;\n        }\n\n        switch (length % 8) {\n            case 7:\n                h ^= (long) (data[(length & ~7) + 6] & 0xff) << 48;\n            case 6:\n                h ^= (long) (data[(length & ~7) + 5] & 0xff) << 40;\n            case 5:\n                h ^= (long) (data[(length & ~7) + 4] & 0xff) << 32;\n            case 4:\n                h ^= (long) (data[(length & ~7) + 3] & 0xff) << 24;\n            case 3:\n                h ^= (long) (data[(length & ~7) + 2] & 0xff) << 16;\n            case 2:\n                h ^= (long) (data[(length & ~7) + 1] & 0xff) << 8;\n            case 1:\n                h ^= (long) (data[length & ~7] & 0xff);\n                h *= m;\n        }\n\n        h ^= h >>> r;\n        h *= m;\n        h ^= h >>> r;\n\n        return h;\n    }\n\n    public static byte[] md5Bytes(String text) {\n        MessageDigest msgDigest = null;\n\n        try {\n            msgDigest = MessageDigest.getInstance(\"MD5\");\n        } catch (NoSuchAlgorithmException e) {\n            throw new IllegalStateException(\"System doesn't support MD5 algorithm.\");\n        }\n\n        msgDigest.update(text.getBytes());\n\n        byte[] bytes = msgDigest.digest();\n\n        return bytes;\n    }\n\n    public static String md5(String text) {\n        byte[] bytes = md5Bytes(text);\n        return HexBin.encode(bytes, false);\n    }\n\n    public static void putLong(byte[] b, int off, long val) {\n        b[off + 7] = (byte) (val >>> 0);\n        b[off + 6] = (byte) (val >>> 8);\n        b[off + 5] = (byte) (val >>> 16);\n        b[off + 4] = (byte) (val >>> 24);\n        b[off + 3] = (byte) (val >>> 32);\n        b[off + 2] = (byte) (val >>> 40);\n        b[off + 1] = (byte) (val >>> 48);\n        b[off + 0] = (byte) (val >>> 56);\n    }\n\n    public static boolean equals(Object a, Object b) {\n        return (a == b) || (a != null && a.equals(b));\n    }\n\n    public static String hex(int hash) {\n        byte[] bytes = new byte[4];\n\n        bytes[3] = (byte) (hash);\n        bytes[2] = (byte) (hash >>> 8);\n        bytes[1] = (byte) (hash >>> 16);\n        bytes[0] = (byte) (hash >>> 24);\n\n        char[] chars = new char[8];\n        for (int i = 0; i < 4; ++i) {\n            byte b = bytes[i];\n\n            int a = b & 0xFF;\n            int b0 = a >> 4;\n            int b1 = a & 0xf;\n\n            chars[i * 2] = (char) (b0 + (b0 < 10 ? 48 : 55));\n            chars[i * 2 + 1] = (char) (b1 + (b1 < 10 ? 48 : 55));\n        }\n\n        return new String(chars);\n    }\n\n    public static String hex(long hash) {\n        byte[] bytes = new byte[8];\n\n        bytes[7] = (byte) (hash);\n        bytes[6] = (byte) (hash >>> 8);\n        bytes[5] = (byte) (hash >>> 16);\n        bytes[4] = (byte) (hash >>> 24);\n        bytes[3] = (byte) (hash >>> 32);\n        bytes[2] = (byte) (hash >>> 40);\n        bytes[1] = (byte) (hash >>> 48);\n        bytes[0] = (byte) (hash >>> 56);\n\n        char[] chars = new char[16];\n        for (int i = 0; i < 8; ++i) {\n            byte b = bytes[i];\n\n            int a = b & 0xFF;\n            int b0 = a >> 4;\n            int b1 = a & 0xf;\n\n            chars[i * 2] = (char) (b0 + (b0 < 10 ? 48 : 55));\n            chars[i * 2 + 1] = (char) (b1 + (b1 < 10 ? 48 : 55));\n        }\n\n        return new String(chars);\n    }\n\n    public static String hex_t(long hash) {\n        byte[] bytes = new byte[8];\n\n        bytes[7] = (byte) (hash);\n        bytes[6] = (byte) (hash >>> 8);\n        bytes[5] = (byte) (hash >>> 16);\n        bytes[4] = (byte) (hash >>> 24);\n        bytes[3] = (byte) (hash >>> 32);\n        bytes[2] = (byte) (hash >>> 40);\n        bytes[1] = (byte) (hash >>> 48);\n        bytes[0] = (byte) (hash >>> 56);\n\n        char[] chars = new char[18];\n        chars[0] = 'T';\n        chars[1] = '_';\n        for (int i = 0; i < 8; ++i) {\n            byte b = bytes[i];\n\n            int a = b & 0xFF;\n            int b0 = a >> 4;\n            int b1 = a & 0xf;\n\n            chars[i * 2 + 2] = (char) (b0 + (b0 < 10 ? 48 : 55));\n            chars[i * 2 + 3] = (char) (b1 + (b1 < 10 ? 48 : 55));\n        }\n\n        return new String(chars);\n    }\n\n    public static long fnv_64(String input) {\n        return FnvHash.fnv1a_64(input);\n    }\n\n    public static long fnv_64_lower(String key) {\n        return FnvHash.fnv1a_64_lower(key);\n    }\n\n    public static long fnv_32_lower(String key) {\n        return FnvHash.fnv_32_lower(key);\n    }\n\n    public static void loadFromFile(String path, Set<String> set) {\n        InputStream is = null;\n        BufferedReader reader = null;\n        try {\n            is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);\n            reader = new BufferedReader(new InputStreamReader(is));\n            for (; ; ) {\n                String line = reader.readLine();\n                if (line == null) {\n                    break;\n                }\n\n                line = line.trim().toLowerCase();\n\n                if (line.length() == 0) {\n                    continue;\n                }\n                set.add(line);\n            }\n        } catch (Exception ex) {\n            // skip\n        } finally {\n            JdbcUtils.close(is);\n            JdbcUtils.close(reader);\n        }\n    }\n\n    /**\n     * Returns a default value if the object passed is {@code null}.\n     */\n    public static <T> T getIfNull(final T object, final T defaultValue) {\n        return object != null ? object : defaultValue;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/jdbc/ConnectionBase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util.jdbc;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\npublic abstract class ConnectionBase implements Connection {\n    private boolean autoCommit = true;\n    private String catalog;\n    private int transactionIsolation;\n    private int holdability;\n    private Map<String, Class<?>> typeMap = new HashMap<String, Class<?>>();\n    private SQLWarning warnings;\n    private boolean readOnly;\n\n    private String url;\n    private Properties info;\n\n    public ConnectionBase(String url, Properties info) {\n        this.url = url;\n        this.info = info;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public Properties getConnectProperties() {\n        return info;\n    }\n\n    @Override\n    public void setAutoCommit(boolean autoCommit) throws SQLException {\n        this.autoCommit = autoCommit;\n    }\n\n    @Override\n    public boolean getAutoCommit() throws SQLException {\n        return autoCommit;\n    }\n\n    @Override\n    public void setCatalog(String catalog) throws SQLException {\n        checkState();\n        this.catalog = catalog;\n    }\n\n    @Override\n    public String getCatalog() throws SQLException {\n        return catalog;\n    }\n\n    public void checkState() throws SQLException {\n    }\n\n    @Override\n    public void setTransactionIsolation(int level) throws SQLException {\n        checkState();\n        this.transactionIsolation = level;\n    }\n\n    @Override\n    public int getTransactionIsolation() throws SQLException {\n        return transactionIsolation;\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        return warnings;\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        this.warnings = null;\n    }\n\n    public void setWarnings(SQLWarning warnings) {\n        this.warnings = warnings;\n    }\n\n    @Override\n    public Map<String, Class<?>> getTypeMap() throws SQLException {\n        return typeMap;\n    }\n\n    @Override\n    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {\n        this.typeMap = map;\n    }\n\n    @Override\n    public void setHoldability(int holdability) throws SQLException {\n        this.holdability = holdability;\n    }\n\n    @Override\n    public int getHoldability() {\n        return holdability;\n    }\n\n    @Override\n    public void setReadOnly(boolean readOnly) throws SQLException {\n        this.readOnly = readOnly;\n    }\n\n    @Override\n    public boolean isReadOnly() throws SQLException {\n        return readOnly;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/jdbc/LocalResultSet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util.jdbc;\n\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class LocalResultSet extends ResultSetBase {\n    private int rowIndex = -1;\n    private List<Object[]> rows = new ArrayList<Object[]>();\n\n    public LocalResultSet(Statement statement) {\n        super(statement);\n    }\n\n    public List<Object[]> getRows() {\n        return rows;\n    }\n\n    @Override\n    public synchronized boolean next() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        if (rowIndex < rows.size() - 1) {\n            rowIndex++;\n            return true;\n        }\n        return false;\n    }\n\n    public Object getObjectInternal(int columnIndex) {\n        Object[] row = rows.get(rowIndex);\n        return row[columnIndex - 1];\n    }\n\n    @Override\n    public synchronized boolean previous() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        if (rowIndex > 0) {\n            rowIndex--;\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public void updateObject(int columnIndex, Object x) throws SQLException {\n        Object[] row = rows.get(rowIndex);\n        row[columnIndex - 1] = x;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/jdbc/PreparedStatementBase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util.jdbc;\n\nimport com.alibaba.druid.mock.MockParameterMetaData;\nimport com.alibaba.druid.mock.MockResultSetMetaData;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.List;\n\npublic abstract class PreparedStatementBase extends StatementBase implements PreparedStatement {\n    private List<Object> parameters = new ArrayList<Object>();\n\n    private MockParameterMetaData metadata = new MockParameterMetaData();\n\n    private MockResultSetMetaData resultSetMetaData = new MockResultSetMetaData();\n\n    public PreparedStatementBase(Connection connection) {\n        super(connection);\n    }\n\n    public List<Object> getParameters() {\n        return parameters;\n    }\n\n    @Override\n    public void setNull(int parameterIndex, int sqlType) throws SQLException {\n        parameters.add(parameterIndex - 1, null);\n    }\n\n    @Override\n    public void setBoolean(int parameterIndex, boolean x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setByte(int parameterIndex, byte x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setShort(int parameterIndex, short x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setInt(int parameterIndex, int x) throws SQLException {\n        for (int i = parameters.size(); i < parameterIndex; ++i) {\n            parameters.add(null);\n        }\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setLong(int parameterIndex, long x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setFloat(int parameterIndex, float x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setDouble(int parameterIndex, double x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setString(int parameterIndex, String x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setBytes(int parameterIndex, byte[] x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setDate(int parameterIndex, Date x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setTime(int parameterIndex, Time x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void clearParameters() throws SQLException {\n        checkOpen();\n\n        parameters.clear();\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void addBatch() throws SQLException {\n        checkOpen();\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {\n        parameters.add(parameterIndex - 1, reader);\n    }\n\n    @Override\n    public void setRef(int parameterIndex, Ref x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, Blob x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Clob x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setArray(int parameterIndex, Array x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException {\n        checkOpen();\n\n        return resultSetMetaData;\n    }\n\n    @Override\n    public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {\n        parameters.add(parameterIndex - 1, null);\n    }\n\n    @Override\n    public void setURL(int parameterIndex, URL x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public ParameterMetaData getParameterMetaData() throws SQLException {\n        checkOpen();\n        return metadata;\n    }\n\n    @Override\n    public void setRowId(int parameterIndex, RowId x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setNString(int parameterIndex, String value) throws SQLException {\n        parameters.add(parameterIndex - 1, value);\n    }\n\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {\n        parameters.add(parameterIndex - 1, value);\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, NClob value) throws SQLException {\n        parameters.add(parameterIndex - 1, value);\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Reader value, long length) throws SQLException {\n        parameters.add(parameterIndex - 1, value);\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {\n        parameters.add(parameterIndex - 1, inputStream);\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {\n        parameters.add(parameterIndex - 1, reader);\n    }\n\n    @Override\n    public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {\n        parameters.add(parameterIndex - 1, xmlObject);\n    }\n\n    @Override\n    public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {\n        parameters.add(parameterIndex - 1, reader);\n    }\n\n    @Override\n    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {\n        parameters.add(parameterIndex - 1, x);\n    }\n\n    @Override\n    public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {\n        parameters.add(parameterIndex - 1, reader);\n    }\n\n    @Override\n    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {\n        parameters.add(parameterIndex - 1, value);\n    }\n\n    @Override\n    public void setClob(int parameterIndex, Reader reader) throws SQLException {\n        parameters.add(parameterIndex - 1, reader);\n    }\n\n    @Override\n    public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {\n        parameters.add(parameterIndex - 1, inputStream);\n    }\n\n    @Override\n    public void setNClob(int parameterIndex, Reader reader) throws SQLException {\n        parameters.add(parameterIndex - 1, reader);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/jdbc/ResultSetBase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util.jdbc;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.Map;\n\npublic abstract class ResultSetBase implements ResultSet {\n    protected boolean closed;\n    protected boolean wasNull;\n    private SQLWarning warning;\n    private String cursorName;\n    private int fetchSize;\n    private int fetchDirection;\n\n    protected Statement statement;\n    protected ResultSetMetaData metaData;\n\n    public ResultSetBase(Statement statement) {\n        super();\n        this.statement = statement;\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        return closed;\n    }\n\n    @Override\n    public void updateNString(int columnIndex, String x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateNString(String columnLabel, String x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, NClob x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, NClob x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public NClob getNClob(int columnIndex) throws SQLException {\n        return (NClob) getObject(columnIndex);\n    }\n\n    @Override\n    public NClob getNClob(String columnLabel) throws SQLException {\n        return (NClob) getObject(columnLabel);\n    }\n\n    @Override\n    public SQLXML getSQLXML(int columnIndex) throws SQLException {\n        return (SQLXML) getObject(columnIndex);\n    }\n\n    @Override\n    public SQLXML getSQLXML(String columnLabel) throws SQLException {\n        return (SQLXML) getObject(columnLabel);\n    }\n\n    @Override\n    public void updateSQLXML(int columnIndex, SQLXML x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateSQLXML(String columnLabel, SQLXML x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public String getNString(int columnIndex) throws SQLException {\n        return (String) getObject(columnIndex);\n    }\n\n    @Override\n    public String getNString(String columnLabel) throws SQLException {\n        return (String) getObject(columnLabel);\n    }\n\n    @Override\n    public Reader getNCharacterStream(int columnIndex) throws SQLException {\n        return (Reader) getObject(columnIndex);\n    }\n\n    @Override\n    public Reader getNCharacterStream(String columnLabel) throws SQLException {\n        return (Reader) getObject(columnLabel);\n    }\n\n    @Override\n    public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateNCharacterStream(String columnLabel, Reader x, long length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader x, long length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, InputStream x, long length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, InputStream x, long length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Reader x, long length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Reader x, long length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, Reader x, long length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, Reader x, long length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateNCharacterStream(String columnLabel, Reader x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, InputStream x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, InputStream x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Reader x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Reader x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateNClob(int columnIndex, Reader x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateNClob(String columnLabel, Reader x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (iface == null) {\n            return null;\n        }\n\n        if (iface.isInstance(this)) {\n            return (T) this;\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == null) {\n            return false;\n        }\n\n        return iface.isInstance(this);\n    }\n\n    @Override\n    public void close() throws SQLException {\n        this.closed = true;\n    }\n\n    @Override\n    public boolean wasNull() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return wasNull;\n    }\n\n    public Object getObjectInternal(int columnIndex) throws SQLException {\n        if (this.getMetaData() != null) {\n            String columnName = this.getMetaData().getColumnName(columnIndex);\n            return getObject(columnName);\n        }\n\n        return null;\n    }\n\n    @Override\n    public Object getObject(int columnIndex) throws SQLException {\n        Object obj = getObjectInternal(columnIndex);\n\n        wasNull = (obj == null);\n\n        return obj;\n    }\n\n    @Override\n    public Object getObject(String columnLabel) throws SQLException {\n        return getObject(findColumn(columnLabel));\n    }\n\n    @Override\n    public int findColumn(String columnLabel) throws SQLException {\n        return Integer.parseInt(columnLabel);\n    }\n\n    @Override\n    public Reader getCharacterStream(int columnIndex) throws SQLException {\n        return (Reader) getObject(columnIndex);\n    }\n\n    @Override\n    public Reader getCharacterStream(String columnLabel) throws SQLException {\n        return (Reader) getObject(columnLabel);\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {\n        return (BigDecimal) getObject(columnIndex);\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String columnLabel) throws SQLException {\n        return getBigDecimal(findColumn(columnLabel));\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        warning = null;\n    }\n\n    public void setWarning(SQLWarning warning) {\n        this.warning = warning;\n    }\n\n    @Override\n    public String getCursorName() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return cursorName;\n    }\n\n    public void setCursorName(String cursorName) {\n        this.cursorName = cursorName;\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return warning;\n    }\n\n    @Override\n    public void setFetchDirection(int direction) throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        this.fetchDirection = direction;\n    }\n\n    @Override\n    public int getFetchDirection() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return fetchDirection;\n    }\n\n    @Override\n    public void setFetchSize(int rows) throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        this.fetchSize = rows;\n    }\n\n    @Override\n    public int getFetchSize() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return fetchSize;\n    }\n\n    @Override\n    public boolean rowUpdated() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean rowInserted() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean rowDeleted() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public void updateNull(int columnIndex) throws SQLException {\n        updateObject(columnIndex, null);\n    }\n\n    @Override\n    public void updateBoolean(int columnIndex, boolean x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateByte(int columnIndex, byte x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateShort(int columnIndex, short x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateInt(int columnIndex, int x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateLong(int columnIndex, long x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateFloat(int columnIndex, float x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateDouble(int columnIndex, double x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateString(int columnIndex, String x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBytes(int columnIndex, byte[] x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateDate(int columnIndex, Date x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateTime(int columnIndex, Time x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateNull(String columnLabel) throws SQLException {\n        updateObject(columnLabel, null);\n    }\n\n    @Override\n    public void updateBoolean(String columnLabel, boolean x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateByte(String columnLabel, byte x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateShort(String columnLabel, short x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateInt(String columnLabel, int x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateLong(String columnLabel, long x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateFloat(String columnLabel, float x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateDouble(String columnLabel, double x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateString(String columnLabel, String x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBytes(String columnLabel, byte[] x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateDate(String columnLabel, Date x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateTime(String columnLabel, Time x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException {\n        updateObject(columnLabel, reader);\n    }\n\n    @Override\n    public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateObject(String columnLabel, Object x) throws SQLException {\n        updateObject(findColumn(columnLabel), x);\n    }\n\n    @Override\n    public void insertRow() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n    }\n\n    @Override\n    public void updateRow() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n    }\n\n    @Override\n    public void deleteRow() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n    }\n\n    @Override\n    public void refreshRow() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n    }\n\n    @Override\n    public void cancelRowUpdates() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n    }\n\n    @Override\n    public void moveToInsertRow() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n    }\n\n    @Override\n    public void moveToCurrentRow() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n    }\n\n    @Override\n    public Statement getStatement() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n        return statement;\n    }\n\n    @Override\n    public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException {\n        return getObject(columnIndex);\n    }\n\n    @Override\n    public Ref getRef(int columnIndex) throws SQLException {\n        return (Ref) getObject(columnIndex);\n    }\n\n    @Override\n    public Blob getBlob(int columnIndex) throws SQLException {\n        return (Blob) getObject(columnIndex);\n    }\n\n    @Override\n    public Clob getClob(int columnIndex) throws SQLException {\n        return (Clob) getObject(columnIndex);\n    }\n\n    @Override\n    public Array getArray(int columnIndex) throws SQLException {\n        return (Array) getObject(columnIndex);\n    }\n\n    @Override\n    public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {\n        return getObject(columnLabel);\n    }\n\n    @Override\n    public Ref getRef(String columnLabel) throws SQLException {\n        return (Ref) getObject(columnLabel);\n    }\n\n    @Override\n    public Blob getBlob(String columnLabel) throws SQLException {\n        return (Blob) getObject(columnLabel);\n    }\n\n    @Override\n    public Clob getClob(String columnLabel) throws SQLException {\n        return (Clob) getObject(columnLabel);\n    }\n\n    @Override\n    public Array getArray(String columnLabel) throws SQLException {\n        return (Array) getObject(columnLabel);\n    }\n\n    @Override\n    public Date getDate(int columnIndex, Calendar cal) throws SQLException {\n        return (Date) getObject(columnIndex);\n    }\n\n    @Override\n    public Date getDate(String columnLabel, Calendar cal) throws SQLException {\n        return (Date) getObject(columnLabel);\n    }\n\n    @Override\n    public Time getTime(int columnIndex, Calendar cal) throws SQLException {\n        return (Time) getObject(columnIndex);\n    }\n\n    @Override\n    public Time getTime(String columnLabel, Calendar cal) throws SQLException {\n        return (Time) getObject(columnLabel);\n    }\n\n    @Override\n    public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {\n        return (Timestamp) getObject(columnIndex);\n    }\n\n    @Override\n    public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {\n        return (Timestamp) getObject(columnLabel);\n    }\n\n    @Override\n    public URL getURL(int columnIndex) throws SQLException {\n        return (URL) getObject(columnIndex);\n    }\n\n    @Override\n    public URL getURL(String columnLabel) throws SQLException {\n        return (URL) getObject(columnLabel);\n    }\n\n    @Override\n    public void updateRef(int columnIndex, Ref x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateRef(String columnLabel, Ref x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateBlob(int columnIndex, Blob x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateBlob(String columnLabel, Blob x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateClob(int columnIndex, Clob x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateClob(String columnLabel, Clob x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public void updateArray(int columnIndex, Array x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateArray(String columnLabel, Array x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public RowId getRowId(int columnIndex) throws SQLException {\n        return (RowId) getObject(columnIndex);\n    }\n\n    @Override\n    public RowId getRowId(String columnLabel) throws SQLException {\n        return (RowId) getObject(columnLabel);\n    }\n\n    @Override\n    public void updateRowId(int columnIndex, RowId x) throws SQLException {\n        updateObject(columnIndex, x);\n    }\n\n    @Override\n    public void updateRowId(String columnLabel, RowId x) throws SQLException {\n        updateObject(columnLabel, x);\n    }\n\n    @Override\n    public int getHoldability() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n\n        return 0;\n    }\n\n    @Override\n    public String getString(int columnIndex) throws SQLException {\n        return (String) getObject(columnIndex);\n    }\n\n    @Override\n    public boolean getBoolean(int columnIndex) throws SQLException {\n        Object obj = getObject(columnIndex);\n\n        if (obj == null) {\n            return false;\n        }\n\n        return (Boolean) obj;\n    }\n\n    @Override\n    public byte getByte(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.byteValue();\n    }\n\n    @Override\n    public short getShort(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.shortValue();\n    }\n\n    @Override\n    public int getInt(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.intValue();\n    }\n\n    @Override\n    public long getLong(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.longValue();\n    }\n\n    @Override\n    public float getFloat(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.floatValue();\n    }\n\n    @Override\n    public double getDouble(int columnIndex) throws SQLException {\n        Number number = (Number) getObject(columnIndex);\n\n        if (number == null) {\n            return 0;\n        }\n\n        return number.doubleValue();\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {\n        return (BigDecimal) getObject(columnIndex);\n    }\n\n    @Override\n    public byte[] getBytes(int columnIndex) throws SQLException {\n        return (byte[]) getObject(columnIndex);\n    }\n\n    @Override\n    public Date getDate(int columnIndex) throws SQLException {\n        return (Date) getObject(columnIndex);\n    }\n\n    @Override\n    public Time getTime(int columnIndex) throws SQLException {\n        return (Time) getObject(columnIndex);\n    }\n\n    @Override\n    public Timestamp getTimestamp(int columnIndex) throws SQLException {\n        return (Timestamp) getObject(columnIndex);\n    }\n\n    @Override\n    public InputStream getAsciiStream(int columnIndex) throws SQLException {\n        return (InputStream) getObject(columnIndex);\n    }\n\n    @Override\n    public InputStream getUnicodeStream(int columnIndex) throws SQLException {\n        return (InputStream) getObject(columnIndex);\n    }\n\n    @Override\n    public InputStream getBinaryStream(int columnIndex) throws SQLException {\n        return (InputStream) getObject(columnIndex);\n    }\n\n    @Override\n    public String getString(String columnLabel) throws SQLException {\n        return getString(findColumn(columnLabel));\n    }\n\n    @Override\n    public boolean getBoolean(String columnLabel) throws SQLException {\n        return getBoolean(findColumn(columnLabel));\n    }\n\n    @Override\n    public byte getByte(String columnLabel) throws SQLException {\n        return getByte(findColumn(columnLabel));\n    }\n\n    @Override\n    public short getShort(String columnLabel) throws SQLException {\n        return getShort(findColumn(columnLabel));\n    }\n\n    @Override\n    public int getInt(String columnLabel) throws SQLException {\n        return getInt(findColumn(columnLabel));\n    }\n\n    @Override\n    public long getLong(String columnLabel) throws SQLException {\n        return getLong(findColumn(columnLabel));\n    }\n\n    @Override\n    public float getFloat(String columnLabel) throws SQLException {\n        return getFloat(findColumn(columnLabel));\n    }\n\n    @Override\n    public double getDouble(String columnLabel) throws SQLException {\n        return getDouble(findColumn(columnLabel));\n    }\n\n    @Override\n    public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {\n        return getBigDecimal(findColumn(columnLabel), scale);\n    }\n\n    @Override\n    public byte[] getBytes(String columnLabel) throws SQLException {\n        return getBytes(findColumn(columnLabel));\n    }\n\n    @Override\n    public Date getDate(String columnLabel) throws SQLException {\n        return getDate(findColumn(columnLabel));\n    }\n\n    @Override\n    public Time getTime(String columnLabel) throws SQLException {\n        return getTime(findColumn(columnLabel));\n    }\n\n    @Override\n    public Timestamp getTimestamp(String columnLabel) throws SQLException {\n        return getTimestamp(findColumn(columnLabel));\n    }\n\n    @Override\n    public InputStream getAsciiStream(String columnLabel) throws SQLException {\n        return getAsciiStream(findColumn(columnLabel));\n    }\n\n    @Override\n    public InputStream getUnicodeStream(String columnLabel) throws SQLException {\n        return getUnicodeStream(findColumn(columnLabel));\n    }\n\n    @Override\n    public InputStream getBinaryStream(String columnLabel) throws SQLException {\n        return getBinaryStream(findColumn(columnLabel));\n    }\n\n    @Override\n    public boolean isBeforeFirst() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean isAfterLast() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n        return false;\n    }\n\n    @Override\n    public boolean isFirst() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean isLast() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public void beforeFirst() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n    }\n\n    @Override\n    public void afterLast() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n    }\n\n    @Override\n    public boolean first() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean last() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public int getRow() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return 0;\n    }\n\n    @Override\n    public boolean absolute(int row) throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean relative(int rows) throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return false;\n    }\n\n    @Override\n    public int getType() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return 0;\n    }\n\n    @Override\n    public int getConcurrency() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        return 0;\n    }\n\n    @Override\n    public ResultSetMetaData getMetaData() throws SQLException {\n        if (closed) {\n            throw new SQLException(\"resultSet closed\");\n        }\n\n        return metaData;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/jdbc/ResultSetMetaDataBase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util.jdbc;\n\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class ResultSetMetaDataBase implements ResultSetMetaData {\n    public ResultSetMetaDataBase() {\n    }\n\n    private final List<ColumnMetaData> columns = new ArrayList<ColumnMetaData>();\n\n    public List<ColumnMetaData> getColumns() {\n        return columns;\n    }\n\n    public int findColumn(String columnName) throws SQLException {\n        for (int i = 0; i < columns.size(); ++i) {\n            ColumnMetaData column = columns.get(i);\n            if (column.getColumnName().equals(columnName)) {\n                return i + 1;\n            }\n        }\n\n        throw new SQLException(\"column '\" + columnName + \"' not found.\");\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (isWrapperFor(iface)) {\n            return (T) this;\n        }\n        return null;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == null) {\n            return false;\n        }\n\n        return iface.isAssignableFrom(this.getClass());\n\n    }\n\n    @Override\n    public int getColumnCount() throws SQLException {\n        return columns.size();\n    }\n\n    @Override\n    public boolean isAutoIncrement(int column) throws SQLException {\n        return getColumn(column).isAutoIncrement();\n    }\n\n    @Override\n    public boolean isCaseSensitive(int column) throws SQLException {\n        return getColumn(column).isCaseSensitive();\n    }\n\n    @Override\n    public boolean isSearchable(int column) throws SQLException {\n        return getColumn(column).isSearchable();\n    }\n\n    @Override\n    public boolean isCurrency(int column) throws SQLException {\n        return getColumn(column).isCurrency();\n    }\n\n    @Override\n    public int isNullable(int column) throws SQLException {\n        return getColumn(column).getNullable();\n    }\n\n    @Override\n    public boolean isSigned(int column) throws SQLException {\n        return getColumn(column).isSigned();\n    }\n\n    @Override\n    public int getColumnDisplaySize(int column) throws SQLException {\n        return getColumn(column).getColumnDisplaySize();\n    }\n\n    @Override\n    public String getColumnLabel(int column) throws SQLException {\n        return getColumn(column).getColumnLabel();\n    }\n\n    public ColumnMetaData getColumn(int column) {\n        return columns.get(column - 1);\n    }\n\n    @Override\n    public String getColumnName(int column) throws SQLException {\n        return getColumn(column).getColumnName();\n    }\n\n    @Override\n    public String getSchemaName(int column) throws SQLException {\n        return getColumn(column).getSchemaName();\n    }\n\n    @Override\n    public int getPrecision(int column) throws SQLException {\n        return getColumn(column).getPrecision();\n    }\n\n    @Override\n    public int getScale(int column) throws SQLException {\n        return getColumn(column).getScale();\n    }\n\n    @Override\n    public String getTableName(int column) throws SQLException {\n        return getColumn(column).getTableName();\n    }\n\n    @Override\n    public String getCatalogName(int column) throws SQLException {\n        return getColumn(column).getCatalogName();\n    }\n\n    @Override\n    public int getColumnType(int column) throws SQLException {\n        return getColumn(column).getColumnType();\n    }\n\n    @Override\n    public String getColumnTypeName(int column) throws SQLException {\n        return getColumn(column).getColumnTypeName();\n    }\n\n    @Override\n    public boolean isReadOnly(int column) throws SQLException {\n        return getColumn(column).isReadOnly();\n    }\n\n    @Override\n    public boolean isWritable(int column) throws SQLException {\n        return getColumn(column).isWritable();\n    }\n\n    @Override\n    public boolean isDefinitelyWritable(int column) throws SQLException {\n        return getColumn(column).isDefinitelyWritable();\n    }\n\n    @Override\n    public String getColumnClassName(int column) throws SQLException {\n        return getColumn(column).getColumnClassName();\n    }\n\n    public static class ColumnMetaData {\n        private boolean autoIncrement;\n        private boolean caseSensitive;\n        private boolean searchable;\n        private boolean currency;\n        private int nullable;\n        private boolean signed;\n        private int columnDisplaySize;\n        private String columnLabel;\n        private String columnName;\n        private String schemaName;\n        private int precision;\n        private int scale;\n        private String tableName;\n        private String catalogName;\n        private int columnType;\n        private String columnTypeName;\n        private boolean readOnly;\n        private boolean writable;\n        private boolean definitelyWritable;\n        private String columnClassName;\n\n        public boolean isAutoIncrement() {\n            return autoIncrement;\n        }\n\n        public void setAutoIncrement(boolean autoIncrement) {\n            this.autoIncrement = autoIncrement;\n        }\n\n        public boolean isCaseSensitive() {\n            return caseSensitive;\n        }\n\n        public void setCaseSensitive(boolean caseSensitive) {\n            this.caseSensitive = caseSensitive;\n        }\n\n        public boolean isSearchable() {\n            return searchable;\n        }\n\n        public void setSearchable(boolean searchable) {\n            this.searchable = searchable;\n        }\n\n        public boolean isCurrency() {\n            return currency;\n        }\n\n        public void setCurrency(boolean currency) {\n            this.currency = currency;\n        }\n\n        public int getNullable() {\n            return nullable;\n        }\n\n        public void setNullable(int nullable) {\n            this.nullable = nullable;\n        }\n\n        public boolean isSigned() {\n            return signed;\n        }\n\n        public void setSigned(boolean signed) {\n            this.signed = signed;\n        }\n\n        public int getColumnDisplaySize() {\n            return columnDisplaySize;\n        }\n\n        public void setColumnDisplaySize(int columnDisplaySize) {\n            this.columnDisplaySize = columnDisplaySize;\n        }\n\n        public String getColumnLabel() {\n            return columnLabel;\n        }\n\n        public void setColumnLabel(String columnLabel) {\n            this.columnLabel = columnLabel;\n        }\n\n        public String getColumnName() {\n            return columnName;\n        }\n\n        public void setColumnName(String columnName) {\n            this.columnName = columnName;\n        }\n\n        public String getSchemaName() {\n            return schemaName;\n        }\n\n        public void setSchemaName(String schemaName) {\n            this.schemaName = schemaName;\n        }\n\n        public int getPrecision() {\n            return precision;\n        }\n\n        public void setPrecision(int precision) {\n            this.precision = precision;\n        }\n\n        public int getScale() {\n            return scale;\n        }\n\n        public void setScale(int scale) {\n            this.scale = scale;\n        }\n\n        public String getTableName() {\n            return tableName;\n        }\n\n        public void setTableName(String tableName) {\n            this.tableName = tableName;\n        }\n\n        public String getCatalogName() {\n            return catalogName;\n        }\n\n        public void setCatalogName(String catalogName) {\n            this.catalogName = catalogName;\n        }\n\n        public int getColumnType() {\n            return columnType;\n        }\n\n        public void setColumnType(int columnType) {\n            this.columnType = columnType;\n        }\n\n        public String getColumnTypeName() {\n            return columnTypeName;\n        }\n\n        public void setColumnTypeName(String columnTypeName) {\n            this.columnTypeName = columnTypeName;\n        }\n\n        public boolean isReadOnly() {\n            return readOnly;\n        }\n\n        public void setReadOnly(boolean readOnly) {\n            this.readOnly = readOnly;\n        }\n\n        public boolean isWritable() {\n            return writable;\n        }\n\n        public void setWritable(boolean writable) {\n            this.writable = writable;\n        }\n\n        public boolean isDefinitelyWritable() {\n            return definitelyWritable;\n        }\n\n        public void setDefinitelyWritable(boolean definitelyWritable) {\n            this.definitelyWritable = definitelyWritable;\n        }\n\n        public String getColumnClassName() {\n            return columnClassName;\n        }\n\n        public void setColumnClassName(String columnClassName) {\n            this.columnClassName = columnClassName;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/jdbc/StatementBase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util.jdbc;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockConnectionClosedException;\n\nimport java.sql.*;\n\npublic abstract class StatementBase implements Statement {\n    private Connection connection;\n    private int fetchDirection;\n    private int fetchSize;\n    private int resultSetType;\n    private int resultSetConcurrency;\n    private int resultSetHoldability;\n    private int maxFieldSize;\n    private int maxRows;\n    private int queryTimeout;\n    private boolean escapeProcessing;\n    private String cursorName;\n    private SQLWarning warnings;\n    private int updateCount;\n    protected boolean closed;\n    private boolean poolable;\n\n    protected ResultSet generatedKeys;\n    protected ResultSet resultSet;\n\n    public StatementBase(Connection connection) {\n        super();\n        this.connection = connection;\n    }\n\n    public Connection getConnection() throws SQLException {\n        return connection;\n    }\n\n    public void setConnection(Connection connection) {\n        this.connection = connection;\n    }\n\n    protected void checkOpen() throws SQLException {\n        if (closed) {\n            throw new SQLException();\n        }\n\n        if (this.connection != null) {\n            if (this.connection instanceof MockConnection) {\n                ((MockConnection) this.connection).checkState();\n            } else if (this.connection.isClosed()) {\n                throw new MockConnectionClosedException();\n            }\n        }\n    }\n\n    @Override\n    public void setFetchDirection(int direction) throws SQLException {\n        checkOpen();\n\n        this.fetchDirection = direction;\n    }\n\n    @Override\n    public int getFetchDirection() throws SQLException {\n        checkOpen();\n        return fetchDirection;\n    }\n\n    @Override\n    public void setFetchSize(int rows) throws SQLException {\n        checkOpen();\n        this.fetchSize = rows;\n    }\n\n    @Override\n    public int getFetchSize() throws SQLException {\n        checkOpen();\n        return fetchSize;\n    }\n\n    public int getResultSetType() throws SQLException {\n        checkOpen();\n\n        return resultSetType;\n    }\n\n    public void setResultSetType(int resultType) {\n        this.resultSetType = resultType;\n    }\n\n    public void setResultSetConcurrency(int resultSetConcurrency) {\n        this.resultSetConcurrency = resultSetConcurrency;\n    }\n\n    @Override\n    public int getResultSetConcurrency() throws SQLException {\n        checkOpen();\n        return resultSetConcurrency;\n    }\n\n    @Override\n    public int getResultSetHoldability() throws SQLException {\n        checkOpen();\n        return resultSetHoldability;\n    }\n\n    public void setResultSetHoldability(int resultSetHoldability) {\n        this.resultSetHoldability = resultSetHoldability;\n    }\n\n    @Override\n    public int getMaxFieldSize() throws SQLException {\n        checkOpen();\n\n        return maxFieldSize;\n    }\n\n    @Override\n    public void setMaxFieldSize(int max) throws SQLException {\n        checkOpen();\n\n        this.maxFieldSize = max;\n    }\n\n    @Override\n    public int getMaxRows() throws SQLException {\n        checkOpen();\n\n        return maxRows;\n    }\n\n    @Override\n    public void setMaxRows(int max) throws SQLException {\n        checkOpen();\n\n        this.maxRows = max;\n    }\n\n    @Override\n    public void setEscapeProcessing(boolean enable) throws SQLException {\n        checkOpen();\n        this.escapeProcessing = enable;\n    }\n\n    public boolean isEscapeProcessing() {\n        return escapeProcessing;\n    }\n\n    @Override\n    public int getQueryTimeout() throws SQLException {\n        checkOpen();\n        return queryTimeout;\n    }\n\n    @Override\n    public void setQueryTimeout(int seconds) throws SQLException {\n        checkOpen();\n        this.queryTimeout = seconds;\n    }\n\n    @Override\n    public void setCursorName(String name) throws SQLException {\n        checkOpen();\n\n        cursorName = name;\n    }\n\n    public String getCursorName() {\n        return cursorName;\n    }\n\n    @Override\n    public SQLWarning getWarnings() throws SQLException {\n        checkOpen();\n\n        return warnings;\n    }\n\n    @Override\n    public void clearWarnings() throws SQLException {\n        checkOpen();\n\n        warnings = null;\n    }\n\n    public void setWarning(SQLWarning warning) {\n        this.warnings = warning;\n    }\n\n    @Override\n    public int getUpdateCount() throws SQLException {\n        checkOpen();\n\n        return updateCount;\n    }\n\n    public void setUpdateCount(int updateCount) {\n        this.updateCount = updateCount;\n    }\n\n    @Override\n    public void close() throws SQLException {\n        this.closed = true;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        if (isWrapperFor(iface)) {\n            return (T) this;\n        }\n\n        return null;\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        if (iface == null) {\n            return false;\n        }\n\n        if (iface == this.getClass() || iface.isInstance(this)) {\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean isPoolable() throws SQLException {\n        checkOpen();\n        return poolable;\n    }\n\n    public void setPoolable(boolean poolable) throws SQLException {\n        checkOpen();\n        this.poolable = poolable;\n    }\n\n    public void closeOnCompletion() throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    public boolean isCloseOnCompletion() throws SQLException {\n        throw new SQLFeatureNotSupportedException();\n    }\n\n    @Override\n    public boolean isClosed() throws SQLException {\n        return closed;\n    }\n\n    @Override\n    public boolean getMoreResults() throws SQLException {\n        checkOpen();\n\n        return false;\n    }\n\n    @Override\n    public void addBatch(String sql) throws SQLException {\n        checkOpen();\n    }\n\n    @Override\n    public void clearBatch() throws SQLException {\n        checkOpen();\n    }\n\n    @Override\n    public ResultSet getGeneratedKeys() throws SQLException {\n        checkOpen();\n        return this.generatedKeys;\n    }\n\n    public void setGeneratedKeys(ResultSet generatedKeys) {\n        this.generatedKeys = generatedKeys;\n    }\n\n    @Override\n    public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {\n        checkOpen();\n        return 0;\n    }\n\n    @Override\n    public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {\n        checkOpen();\n        return 0;\n    }\n\n    @Override\n    public int executeUpdate(String sql, String[] columnNames) throws SQLException {\n        checkOpen();\n        return 0;\n    }\n\n    @Override\n    public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {\n        checkOpen();\n        return false;\n    }\n\n    @Override\n    public boolean execute(String sql, int[] columnIndexes) throws SQLException {\n        checkOpen();\n        return false;\n    }\n\n    @Override\n    public boolean execute(String sql, String[] columnNames) throws SQLException {\n        checkOpen();\n        return false;\n    }\n\n    @Override\n    public ResultSet getResultSet() throws SQLException {\n        checkOpen();\n\n        return resultSet;\n    }\n\n    @Override\n    public int[] executeBatch() throws SQLException {\n        checkOpen();\n\n        return new int[0];\n    }\n\n    @Override\n    public boolean getMoreResults(int current) throws SQLException {\n        checkOpen();\n        return false;\n    }\n\n    public void setWarnings(SQLWarning warnings) {\n        this.warnings = warnings;\n    }\n\n    public void setResultSet(ResultSet resultSet) {\n        this.resultSet = resultSet;\n    }\n\n    @Override\n    public boolean execute(String sql) throws SQLException {\n        checkOpen();\n\n        return false;\n    }\n\n    @Override\n    public ResultSet executeQuery(String sql) throws SQLException {\n        return null;\n    }\n\n    @Override\n    public int executeUpdate(String sql) throws SQLException {\n        return 0;\n    }\n\n    @Override\n    public void cancel() throws SQLException {\n        checkOpen();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/util/lang/Consumer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.util.lang;\n\n/**\n * Created by wenshao on 20/06/2017.\n */\npublic interface Consumer<T> {\n    void accept(T t);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/Violation.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\npublic interface Violation {\n    int getErrorCode();\n\n    String getMessage();\n\n    String toString();\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallCheckResult.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\npublic class WallCheckResult {\n    private final List<SQLStatement> statementList;\n    private final Map<String, WallSqlTableStat> tableStats;\n\n    private final List<Violation> violations;\n\n    private final Map<String, WallSqlFunctionStat> functionStats;\n\n    private final boolean syntaxError;\n\n    private final WallSqlStat sqlStat;\n\n    private String sql;\n\n    private List<WallUpdateCheckItem> updateCheckItems;\n\n    public WallCheckResult() {\n        this(null);\n    }\n\n    public WallCheckResult(WallSqlStat sqlStat, List<SQLStatement> stmtList) {\n        if (sqlStat != null) {\n            tableStats = sqlStat.getTableStats();\n            violations = sqlStat.getViolations();\n            functionStats = sqlStat.getFunctionStats();\n            statementList = stmtList;\n            syntaxError = sqlStat.isSyntaxError();\n        } else {\n            tableStats = Collections.emptyMap();\n            violations = Collections.emptyList();\n            functionStats = Collections.emptyMap();\n            statementList = stmtList;\n            syntaxError = false;\n        }\n        this.sqlStat = sqlStat;\n    }\n\n    public WallCheckResult(WallSqlStat sqlStat) {\n        this(sqlStat, Collections.<SQLStatement>emptyList());\n    }\n\n    public WallCheckResult(WallSqlStat sqlStat, List<Violation> violations, Map<String, WallSqlTableStat> tableStats,\n                           Map<String, WallSqlFunctionStat> functionStats, List<SQLStatement> statementList,\n                           boolean syntaxError) {\n        this.sqlStat = sqlStat;\n        this.tableStats = tableStats;\n        this.violations = violations;\n        this.functionStats = functionStats;\n        this.statementList = statementList;\n        this.syntaxError = syntaxError;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public void setSql(String sql) {\n        this.sql = sql;\n    }\n\n    public List<Violation> getViolations() {\n        return violations;\n    }\n\n    public List<SQLStatement> getStatementList() {\n        return statementList;\n    }\n\n    public Map<String, WallSqlTableStat> getTableStats() {\n        return tableStats;\n    }\n\n    public Map<String, WallSqlFunctionStat> getFunctionStats() {\n        return functionStats;\n    }\n\n    public boolean isSyntaxError() {\n        return syntaxError;\n    }\n\n    public WallSqlStat getSqlStat() {\n        return sqlStat;\n    }\n\n    public List<WallUpdateCheckItem> getUpdateCheckItems() {\n        return updateCheckItems;\n    }\n\n    public void setUpdateCheckItems(List<WallUpdateCheckItem> updateCheckItems) {\n        this.updateCheckItems = updateCheckItems;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallConfig.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\n\nimport java.util.*;\nimport java.util.concurrent.ConcurrentSkipListSet;\n\nimport static com.alibaba.druid.util.Utils.getBoolean;\nimport static com.alibaba.druid.util.Utils.getInteger;\nimport static com.alibaba.druid.wall.spi.WallVisitorUtils.loadResource;\n\npublic class WallConfig implements WallConfigMBean {\n    private boolean noneBaseStatementAllow;\n\n    private boolean callAllow = true;\n    private boolean selectAllow = true;\n    private boolean selectIntoAllow = true;\n    private boolean selectIntoOutfileAllow;\n    private boolean selectWhereAlwayTrueCheck = true;\n    private boolean selectHavingAlwayTrueCheck = true;\n    private boolean selectUnionCheck = true;\n    private boolean selectMinusCheck = true;\n    private boolean selectExceptCheck = true;\n    private boolean selectIntersectCheck = true;\n    private boolean createTableAllow = true;\n    private boolean dropTableAllow = true;\n    private boolean alterTableAllow = true;\n    private boolean renameTableAllow = true;\n    private boolean hintAllow = true;\n    private boolean lockTableAllow = true;\n    private boolean startTransactionAllow = true;\n    private boolean blockAllow = true;\n\n    private boolean conditionAndAlwayTrueAllow = true;\n    private boolean conditionAndAlwayFalseAllow;\n    private boolean conditionDoubleConstAllow;\n    private boolean conditionLikeTrueAllow = true;\n\n    private boolean selectAllColumnAllow = true;\n\n    private boolean deleteAllow = true;\n    private boolean deleteWhereAlwayTrueCheck = true;\n    private boolean deleteWhereNoneCheck;\n\n    private boolean updateAllow = true;\n    private boolean updateWhereAlwayTrueCheck = true;\n    private boolean updateWhereNoneCheck;\n\n    private boolean insertAllow = true;\n    private boolean mergeAllow = true;\n    private boolean minusAllow = true;\n    private boolean intersectAllow = true;\n    private boolean replaceAllow = true;\n    private boolean setAllow = true;\n    private boolean commitAllow = true;\n    private boolean rollbackAllow = true;\n    private boolean useAllow = true;\n\n    private boolean multiStatementAllow;\n\n    private boolean truncateAllow = true;\n\n    private boolean commentAllow;\n    private boolean strictSyntaxCheck = true;\n    private boolean constArithmeticAllow = true;\n    private boolean limitZeroAllow;\n\n    private boolean describeAllow = true;\n    private boolean showAllow = true;\n\n    private boolean schemaCheck = true;\n    private boolean tableCheck = true;\n    private boolean functionCheck = true;\n    private boolean objectCheck = true;\n    private boolean variantCheck = true;\n\n    private boolean mustParameterized;\n\n    private boolean doPrivilegedAllow;\n\n    protected final Set<String> denyFunctions = new ConcurrentSkipListSet<String>();\n    protected final Set<String> denyTables = new ConcurrentSkipListSet<String>();\n    protected final Set<String> denySchemas = new ConcurrentSkipListSet<String>();\n    protected final Set<String> denyVariants = new ConcurrentSkipListSet<String>();\n    protected final Set<String> denyObjects = new ConcurrentSkipListSet<String>();\n\n    protected final Set<String> permitFunctions = new ConcurrentSkipListSet<String>();\n    protected final Set<String> permitTables = new ConcurrentSkipListSet<String>();\n    protected final Set<String> permitSchemas = new ConcurrentSkipListSet<String>();\n    protected final Set<String> permitVariants = new ConcurrentSkipListSet<String>();\n\n    protected final Set<String> readOnlyTables = new ConcurrentSkipListSet<String>();\n\n    private String dir;\n\n    private boolean inited;\n\n    private String tenantTablePattern;\n    private String tenantColumn;\n    private TenantCallBack tenantCallBack;\n\n    private boolean wrapAllow = true;\n    private boolean metadataAllow = true;\n\n    private boolean conditionOpXorAllow;\n    private boolean conditionOpBitwiseAllow = true;\n\n    private boolean caseConditionConstAllow;\n\n    private boolean completeInsertValuesCheck;\n    private int insertValuesCheckSize = 3;\n\n    private int selectLimit = -1;\n\n    protected Map<String, Set<String>> updateCheckColumns = new HashMap<String, Set<String>>();\n    protected WallUpdateCheckHandler updateCheckHandler;\n\n    public WallConfig() {\n        this.configFromProperties(System.getProperties());\n    }\n\n    public boolean isCaseConditionConstAllow() {\n        return caseConditionConstAllow;\n    }\n\n    public void setCaseConditionConstAllow(boolean caseConditionConstAllow) {\n        this.caseConditionConstAllow = caseConditionConstAllow;\n    }\n\n    public boolean isConditionDoubleConstAllow() {\n        return conditionDoubleConstAllow;\n    }\n\n    public void setConditionDoubleConstAllow(boolean conditionDoubleConstAllow) {\n        this.conditionDoubleConstAllow = conditionDoubleConstAllow;\n    }\n\n    public boolean isConditionLikeTrueAllow() {\n        return conditionLikeTrueAllow;\n    }\n\n    public void setConditionLikeTrueAllow(boolean conditionLikeTrueAllow) {\n        this.conditionLikeTrueAllow = conditionLikeTrueAllow;\n    }\n\n    public boolean isLimitZeroAllow() {\n        return limitZeroAllow;\n    }\n\n    public void setLimitZeroAllow(boolean limitZero) {\n        this.limitZeroAllow = limitZero;\n    }\n\n    public boolean isUseAllow() {\n        return useAllow;\n    }\n\n    public void setUseAllow(boolean useAllow) {\n        this.useAllow = useAllow;\n    }\n\n    public boolean isCommitAllow() {\n        return commitAllow;\n    }\n\n    public void setCommitAllow(boolean commitAllow) {\n        this.commitAllow = commitAllow;\n    }\n\n    public boolean isRollbackAllow() {\n        return rollbackAllow;\n    }\n\n    public void setRollbackAllow(boolean rollbackAllow) {\n        this.rollbackAllow = rollbackAllow;\n    }\n\n    public boolean isIntersectAllow() {\n        return intersectAllow;\n    }\n\n    public void setIntersectAllow(boolean intersectAllow) {\n        this.intersectAllow = intersectAllow;\n    }\n\n    public boolean isMinusAllow() {\n        return minusAllow;\n    }\n\n    public void setMinusAllow(boolean minusAllow) {\n        this.minusAllow = minusAllow;\n    }\n\n    public boolean isConditionOpXorAllow() {\n        return conditionOpXorAllow;\n    }\n\n    public void setConditionOpXorAllow(boolean conditionOpXorAllow) {\n        this.conditionOpXorAllow = conditionOpXorAllow;\n    }\n\n    public String getTenantTablePattern() {\n        return tenantTablePattern;\n    }\n\n    public void setTenantTablePattern(String tenantTablePattern) {\n        this.tenantTablePattern = tenantTablePattern;\n    }\n\n    public String getTenantColumn() {\n        return tenantColumn;\n    }\n\n    public void setTenantColumn(String tenantColumn) {\n        this.tenantColumn = tenantColumn;\n    }\n\n    public TenantCallBack getTenantCallBack() {\n        return tenantCallBack;\n    }\n\n    public void setTenantCallBack(TenantCallBack tenantCallBack) {\n        this.tenantCallBack = tenantCallBack;\n    }\n\n    public boolean isMetadataAllow() {\n        return metadataAllow;\n    }\n\n    public void setMetadataAllow(boolean metadataAllow) {\n        this.metadataAllow = metadataAllow;\n    }\n\n    public boolean isWrapAllow() {\n        return wrapAllow;\n    }\n\n    public void setWrapAllow(boolean wrapAllow) {\n        this.wrapAllow = wrapAllow;\n    }\n\n    public boolean isDoPrivilegedAllow() {\n        return doPrivilegedAllow;\n    }\n\n    public void setDoPrivilegedAllow(boolean doPrivilegedAllow) {\n        this.doPrivilegedAllow = doPrivilegedAllow;\n    }\n\n    public boolean isSelectAllColumnAllow() {\n        return selectAllColumnAllow;\n    }\n\n    public void setSelectAllColumnAllow(boolean selectAllColumnAllow) {\n        this.selectAllColumnAllow = selectAllColumnAllow;\n    }\n\n    public boolean isInited() {\n        return inited;\n    }\n\n    public WallConfig(String dir) {\n        this();\n        this.dir = dir;\n        this.init();\n    }\n\n    public String getDir() {\n        return dir;\n    }\n\n    public void setDir(String dir) {\n        this.dir = dir;\n    }\n\n    public final void init() {\n        loadConfig(dir);\n    }\n\n    public void loadConfig(String dir) {\n        if (dir.endsWith(\"/\")) {\n            dir = dir.substring(0, dir.length() - 1);\n        }\n\n        loadResource(this.denyVariants, dir + \"/deny-variant.txt\");\n        loadResource(this.denySchemas, dir + \"/deny-schema.txt\");\n        loadResource(this.denyFunctions, dir + \"/deny-function.txt\");\n        loadResource(this.denyTables, dir + \"/deny-table.txt\");\n        loadResource(this.denyObjects, dir + \"/deny-object.txt\");\n        loadResource(this.readOnlyTables, dir + \"/readonly-table.txt\");\n\n        loadResource(this.permitFunctions, dir + \"/permit-function.txt\");\n        loadResource(this.permitTables, dir + \"/permit-table.txt\");\n        loadResource(this.permitSchemas, dir + \"/permit-schema.txt\");\n        loadResource(this.permitVariants, dir + \"/permit-variant.txt\");\n    }\n\n    public boolean isNoneBaseStatementAllow() {\n        return noneBaseStatementAllow;\n    }\n\n    public void setNoneBaseStatementAllow(boolean noneBaseStatementAllow) {\n        this.noneBaseStatementAllow = noneBaseStatementAllow;\n    }\n\n    /**\n     * allow mysql describe statement\n     *\n     * @return true if the describe command is allowed, false otherwise\n     * @since 0.2.10\n     */\n    public boolean isDescribeAllow() {\n        return describeAllow;\n    }\n\n    /**\n     * set allow mysql describe statement\n     *\n     * @since 0.2.10\n     */\n    public void setDescribeAllow(boolean describeAllow) {\n        this.describeAllow = describeAllow;\n    }\n\n    public boolean isShowAllow() {\n        return showAllow;\n    }\n\n    public void setShowAllow(boolean showAllow) {\n        this.showAllow = showAllow;\n    }\n\n    public boolean isTruncateAllow() {\n        return truncateAllow;\n    }\n\n    public void setTruncateAllow(boolean truncateAllow) {\n        this.truncateAllow = truncateAllow;\n    }\n\n    public boolean isSelectIntoAllow() {\n        return selectIntoAllow;\n    }\n\n    public void setSelectIntoAllow(boolean selectIntoAllow) {\n        this.selectIntoAllow = selectIntoAllow;\n    }\n\n    public boolean isSelectIntoOutfileAllow() {\n        return selectIntoOutfileAllow;\n    }\n\n    public void setSelectIntoOutfileAllow(boolean selectIntoOutfileAllow) {\n        this.selectIntoOutfileAllow = selectIntoOutfileAllow;\n    }\n\n    public boolean isCreateTableAllow() {\n        return createTableAllow;\n    }\n\n    public void setCreateTableAllow(boolean createTableAllow) {\n        this.createTableAllow = createTableAllow;\n    }\n\n    public boolean isDropTableAllow() {\n        return dropTableAllow;\n    }\n\n    public void setDropTableAllow(boolean dropTableAllow) {\n        this.dropTableAllow = dropTableAllow;\n    }\n\n    public boolean isAlterTableAllow() {\n        return alterTableAllow;\n    }\n\n    public void setAlterTableAllow(boolean alterTableAllow) {\n        this.alterTableAllow = alterTableAllow;\n    }\n\n    public boolean isRenameTableAllow() {\n        return renameTableAllow;\n    }\n\n    public void setRenameTableAllow(boolean renameTableAllow) {\n        this.renameTableAllow = renameTableAllow;\n    }\n\n    public boolean isSelectUnionCheck() {\n        return selectUnionCheck;\n    }\n\n    public void setSelectUnionCheck(boolean selectUnionCheck) {\n        this.selectUnionCheck = selectUnionCheck;\n    }\n\n    public boolean isSelectMinusCheck() {\n        return selectMinusCheck;\n    }\n\n    public void setSelectMinusCheck(boolean selectMinusCheck) {\n        this.selectMinusCheck = selectMinusCheck;\n    }\n\n    public boolean isSelectExceptCheck() {\n        return selectExceptCheck;\n    }\n\n    public void setSelectExceptCheck(boolean selectExceptCheck) {\n        this.selectExceptCheck = selectExceptCheck;\n    }\n\n    public boolean isSelectIntersectCheck() {\n        return selectIntersectCheck;\n    }\n\n    public void setSelectIntersectCheck(boolean selectIntersectCheck) {\n        this.selectIntersectCheck = selectIntersectCheck;\n    }\n\n    public boolean isDeleteAllow() {\n        return deleteAllow;\n    }\n\n    public void setDeleteAllow(boolean deleteAllow) {\n        this.deleteAllow = deleteAllow;\n    }\n\n    public boolean isDeleteWhereNoneCheck() {\n        return deleteWhereNoneCheck;\n    }\n\n    public void setDeleteWhereNoneCheck(boolean deleteWhereNoneCheck) {\n        this.deleteWhereNoneCheck = deleteWhereNoneCheck;\n    }\n\n    public boolean isUpdateAllow() {\n        return updateAllow;\n    }\n\n    public void setUpdateAllow(boolean updateAllow) {\n        this.updateAllow = updateAllow;\n    }\n\n    public boolean isUpdateWhereNoneCheck() {\n        return updateWhereNoneCheck;\n    }\n\n    public void setUpdateWhereNoneCheck(boolean updateWhereNoneCheck) {\n        this.updateWhereNoneCheck = updateWhereNoneCheck;\n    }\n\n    public boolean isInsertAllow() {\n        return insertAllow;\n    }\n\n    public void setInsertAllow(boolean insertAllow) {\n        this.insertAllow = insertAllow;\n    }\n\n    public boolean isReplaceAllow() {\n        return replaceAllow;\n    }\n\n    public void setReplaceAllow(boolean replaceAllow) {\n        this.replaceAllow = replaceAllow;\n    }\n\n    public boolean isSetAllow() {\n        return setAllow;\n    }\n\n    public void setSetAllow(boolean value) {\n        this.setAllow = value;\n    }\n\n    public boolean isMergeAllow() {\n        return mergeAllow;\n    }\n\n    public void setMergeAllow(boolean mergeAllow) {\n        this.mergeAllow = mergeAllow;\n    }\n\n    public boolean isMultiStatementAllow() {\n        return multiStatementAllow;\n    }\n\n    public void setMultiStatementAllow(boolean multiStatementAllow) {\n        this.multiStatementAllow = multiStatementAllow;\n    }\n\n    public boolean isSchemaCheck() {\n        return schemaCheck;\n    }\n\n    public void setSchemaCheck(boolean schemaCheck) {\n        this.schemaCheck = schemaCheck;\n    }\n\n    public boolean isTableCheck() {\n        return tableCheck;\n    }\n\n    public void setTableCheck(boolean tableCheck) {\n        this.tableCheck = tableCheck;\n    }\n\n    public boolean isFunctionCheck() {\n        return functionCheck;\n    }\n\n    public void setFunctionCheck(boolean functionCheck) {\n        this.functionCheck = functionCheck;\n    }\n\n    public boolean isVariantCheck() {\n        return variantCheck;\n    }\n\n    public void setVariantCheck(boolean variantCheck) {\n        this.variantCheck = variantCheck;\n    }\n\n    public boolean isObjectCheck() {\n        return objectCheck;\n    }\n\n    public void setObjectCheck(boolean objectCheck) {\n        this.objectCheck = objectCheck;\n    }\n\n    // ///////////////////\n\n    public boolean isCommentAllow() {\n        return commentAllow;\n    }\n\n    public void setCommentAllow(boolean commentAllow) {\n        this.commentAllow = commentAllow;\n    }\n\n    public boolean isStrictSyntaxCheck() {\n        return strictSyntaxCheck;\n    }\n\n    public void setStrictSyntaxCheck(boolean strictSyntaxCheck) {\n        this.strictSyntaxCheck = strictSyntaxCheck;\n    }\n\n    public boolean isConstArithmeticAllow() {\n        return constArithmeticAllow;\n    }\n\n    public void setConstArithmeticAllow(boolean constArithmeticAllow) {\n        this.constArithmeticAllow = constArithmeticAllow;\n    }\n\n    public Set<String> getDenyFunctions() {\n        return denyFunctions;\n    }\n\n    public Set<String> getDenyTables() {\n        return denyTables;\n    }\n\n    public Set<String> getDenySchemas() {\n        return denySchemas;\n    }\n\n    public Set<String> getDenyVariants() {\n        return denyVariants;\n    }\n\n    public Set<String> getDenyObjects() {\n        return denyObjects;\n    }\n\n    public Set<String> getReadOnlyTables() {\n        return readOnlyTables;\n    }\n\n    public void addReadOnlyTable(String tableName) {\n        this.readOnlyTables.add(tableName);\n    }\n\n    public boolean isReadOnly(String tableName) {\n        return this.readOnlyTables.contains(tableName);\n    }\n\n    public Set<String> getPermitFunctions() {\n        return permitFunctions;\n    }\n\n    public Set<String> getPermitTables() {\n        return permitTables;\n    }\n\n    public Set<String> getPermitSchemas() {\n        return permitSchemas;\n    }\n\n    public Set<String> getPermitVariants() {\n        return permitVariants;\n    }\n\n    public boolean isMustParameterized() {\n        return mustParameterized;\n    }\n\n    public void setMustParameterized(boolean mustParameterized) {\n        this.mustParameterized = mustParameterized;\n    }\n\n    public boolean isDenyObjects(String name) {\n        if (!objectCheck) {\n            return false;\n        }\n\n        name = WallVisitorUtils.form(name);\n        return denyObjects.contains(name);\n    }\n\n    public boolean isDenySchema(String name) {\n        if (!schemaCheck) {\n            return false;\n        }\n\n        name = WallVisitorUtils.form(name);\n        return this.denySchemas.contains(name);\n    }\n\n    public boolean isDenyFunction(String name) {\n        if (!functionCheck) {\n            return false;\n        }\n\n        name = WallVisitorUtils.form(name);\n        return this.denyFunctions.contains(name);\n    }\n\n    public boolean isCallAllow() {\n        return callAllow;\n    }\n\n    public void setCallAllow(boolean callAllow) {\n        this.callAllow = callAllow;\n    }\n\n    public boolean isHintAllow() {\n        return hintAllow;\n    }\n\n    public void setHintAllow(boolean hintAllow) {\n        this.hintAllow = hintAllow;\n    }\n\n    public interface TenantCallBack {\n        public static enum StatementType {\n            SELECT, UPDATE, INSERT, DELETE\n        }\n\n        Object getTenantValue(StatementType statementType, String tableName);\n\n        String getTenantColumn(StatementType statementType, String tableName);\n\n        /**\n         * 返回resultset隐藏列名\n\n         * @param tableName tableName\n         */\n        String getHiddenColumn(String tableName);\n\n        /**\n         * resultset返回值中如果包含tenantColumn的回调函数\n         *\n         * @param value tenantColumn对应的值\n         */\n        void filterResultsetTenantColumn(Object value);\n    }\n\n    public boolean isSelectAllow() {\n        return selectAllow;\n    }\n\n    public void setSelectAllow(boolean selectAllow) {\n        this.selectAllow = selectAllow;\n    }\n\n    /**\n     * @deprecated use {@link WallConfig#isSelectAllow()}\n     */\n    @Deprecated\n    public boolean isSelelctAllow() {\n        return isSelectAllow();\n    }\n\n    /**\n     * @deprecated use {@link WallConfig#setSelectAllow(boolean)}\n     */\n    @Deprecated\n    public void setSelelctAllow(boolean selelctAllow) {\n        this.setSelectAllow(selelctAllow);\n    }\n\n    public boolean isSelectWhereAlwayTrueCheck() {\n        return selectWhereAlwayTrueCheck;\n    }\n\n    public void setSelectWhereAlwayTrueCheck(boolean selectWhereAlwayTrueCheck) {\n        this.selectWhereAlwayTrueCheck = selectWhereAlwayTrueCheck;\n    }\n\n    public boolean isSelectHavingAlwayTrueCheck() {\n        return selectHavingAlwayTrueCheck;\n    }\n\n    public void setSelectHavingAlwayTrueCheck(boolean selectHavingAlwayTrueCheck) {\n        this.selectHavingAlwayTrueCheck = selectHavingAlwayTrueCheck;\n    }\n\n    public boolean isConditionAndAlwayTrueAllow() {\n        return conditionAndAlwayTrueAllow;\n    }\n\n    public void setConditionAndAlwayTrueAllow(boolean conditionAndAlwayTrueAllow) {\n        this.conditionAndAlwayTrueAllow = conditionAndAlwayTrueAllow;\n    }\n\n    public boolean isConditionAndAlwayFalseAllow() {\n        return conditionAndAlwayFalseAllow;\n    }\n\n    public void setConditionAndAlwayFalseAllow(boolean conditionAndAlwayFalseAllow) {\n        this.conditionAndAlwayFalseAllow = conditionAndAlwayFalseAllow;\n    }\n\n    public boolean isDeleteWhereAlwayTrueCheck() {\n        return deleteWhereAlwayTrueCheck;\n    }\n\n    public void setDeleteWhereAlwayTrueCheck(boolean deleteWhereAlwayTrueCheck) {\n        this.deleteWhereAlwayTrueCheck = deleteWhereAlwayTrueCheck;\n    }\n\n    /**\n     * @deprecated use {@link WallConfig#isUpdateWhereAlwayTrueCheck()}\n     */\n    @Deprecated\n    public boolean isUpdateWhereAlayTrueCheck() {\n        return updateWhereAlwayTrueCheck;\n    }\n\n    /**\n     * @deprecated use {@link WallConfig#setUpdateWhereAlwayTrueCheck(boolean)}\n     */\n    @Deprecated\n    public void setUpdateWhereAlayTrueCheck(boolean updateWhereAlwayTrueCheck) {\n        this.updateWhereAlwayTrueCheck = updateWhereAlwayTrueCheck;\n    }\n\n    public boolean isUpdateWhereAlwayTrueCheck() {\n        return updateWhereAlwayTrueCheck;\n    }\n    public void setUpdateWhereAlwayTrueCheck(boolean updateWhereAlwayTrueCheck) {\n        this.updateWhereAlwayTrueCheck = updateWhereAlwayTrueCheck;\n    }\n\n    /**\n     * @deprecated Sine 1.2.24, use {@link WallConfig#isConditionOpBitwiseAllow()} instead.\n     */\n    @Deprecated\n    public boolean isConditionOpBitwseAllow() {\n        return isConditionOpBitwiseAllow();\n    }\n\n    /**\n     *\n     * @deprecated Sine 1.2.24, use {@link WallConfig#setConditionOpBitwiseAllow(boolean)} instead.\n     */\n    @Deprecated\n    public void setConditionOpBitwseAllow(boolean conditionOpBitwseAllow) {\n        setConditionOpBitwiseAllow(conditionOpBitwseAllow);\n    }\n\n    /**\n     * @since 1.2.24\n     */\n    public boolean isConditionOpBitwiseAllow() {\n        return conditionOpBitwiseAllow;\n    }\n\n    /**\n     * @since 1.2.24\n     */\n    public void setConditionOpBitwiseAllow(boolean conditionOpBitwiseAllow) {\n        this.conditionOpBitwiseAllow = conditionOpBitwiseAllow;\n    }\n\n    public void setInited(boolean inited) {\n        this.inited = inited;\n    }\n\n    public boolean isLockTableAllow() {\n        return lockTableAllow;\n    }\n\n    public void setLockTableAllow(boolean lockTableAllow) {\n        this.lockTableAllow = lockTableAllow;\n    }\n\n    public boolean isStartTransactionAllow() {\n        return startTransactionAllow;\n    }\n\n    public void setStartTransactionAllow(boolean startTransactionAllow) {\n        this.startTransactionAllow = startTransactionAllow;\n    }\n\n    public boolean isCompleteInsertValuesCheck() {\n        return completeInsertValuesCheck;\n    }\n\n    public void setCompleteInsertValuesCheck(boolean completeInsertValuesCheck) {\n        this.completeInsertValuesCheck = completeInsertValuesCheck;\n    }\n\n    public int getInsertValuesCheckSize() {\n        return insertValuesCheckSize;\n    }\n\n    public void setInsertValuesCheckSize(int insertValuesCheckSize) {\n        this.insertValuesCheckSize = insertValuesCheckSize;\n    }\n\n    public boolean isBlockAllow() {\n        return blockAllow;\n    }\n\n    public void setBlockAllow(boolean blockAllow) {\n        this.blockAllow = blockAllow;\n    }\n\n    public int getSelectLimit() {\n        return selectLimit;\n    }\n\n    public void setSelectLimit(int selectLimit) {\n        this.selectLimit = selectLimit;\n    }\n\n    public void configFromProperties(Properties properties) {\n        {\n            String propertyValue = properties.getProperty(\"druid.wall.tenantColumn\");\n            if (propertyValue != null) {\n                this.setTenantColumn(propertyValue);\n            }\n        }\n        {\n            Boolean propertyValue = getBoolean(properties, \"druid.wall.selectAllow\");\n            //Compatible with previous property\n            if (propertyValue == null) {\n                propertyValue = getBoolean(properties, \"druid.wall.selelctAllow\");\n            }\n            if (propertyValue != null) {\n                this.setSelectAllow(propertyValue);\n            }\n        }\n        {\n            Boolean propertyValue = getBoolean(properties, \"druid.wall.updateAllow\");\n            if (propertyValue != null) {\n                this.setUpdateAllow(propertyValue);\n            }\n        }\n        {\n            Boolean propertyValue = getBoolean(properties, \"druid.wall.deleteAllow\");\n            if (propertyValue != null) {\n                this.setDeleteAllow(propertyValue);\n            }\n        }\n        {\n            Boolean propertyValue = getBoolean(properties, \"druid.wall.insertAllow\");\n            if (propertyValue != null) {\n                this.setInsertAllow(propertyValue);\n            }\n        }\n        {\n            Boolean propertyValue = getBoolean(properties, \"druid.wall.multiStatementAllow\");\n            if (propertyValue != null) {\n                this.setMultiStatementAllow(propertyValue);\n            }\n        }\n        {\n            Integer propertyValue = getInteger(properties, \"druid.wall.selectLimit\");\n            if (propertyValue != null) {\n                this.setSelectLimit(propertyValue);\n            }\n        }\n        {\n            String propertyValue = properties.getProperty(\"druid.wall.updateCheckColumns\");\n            if (propertyValue != null) {\n                String[] items = propertyValue.split(\",\");\n                for (String item : items) {\n                    addUpdateCheckColumns(item);\n                }\n            }\n        }\n        {\n            Boolean propertyValue = getBoolean(properties, \"druid.wall.updateWhereNoneCheck\");\n            if (propertyValue != null) {\n                this.setUpdateWhereNoneCheck(propertyValue);\n            }\n        }\n        {\n            Boolean propertyValue = getBoolean(properties, \"druid.wall.deleteWhereNoneCheck\");\n            if (propertyValue != null) {\n                this.setDeleteWhereNoneCheck(propertyValue);\n            }\n        }\n    }\n\n    /**\n     *\n     * @deprecated Since 1.2.24, use {@link WallConfig#addUpdateCheckColumns(String)} instead.\n     */\n    @Deprecated\n    public void addUpdateCheckCoumns(String columnInfo) {\n        addUpdateCheckColumns(columnInfo);\n    }\n\n    /**\n     * @since 1.2.24\n     */\n    public void addUpdateCheckColumns(String columnInfo) {\n        String[] items = columnInfo.split(\"\\\\.\");\n        if (items.length != 2) {\n            return;\n        }\n        String table = SQLUtils.normalize(items[0]).toLowerCase();\n        String column = SQLUtils.normalize(items[1]).toLowerCase();\n        Set<String> columns = this.updateCheckColumns.get(table);\n        if (columns == null) {\n            columns = new LinkedHashSet<String>();\n            updateCheckColumns.put(table, columns);\n        }\n        columns.add(column);\n    }\n\n    public boolean isUpdateCheckTable(String tableName) {\n        if (updateCheckColumns.isEmpty()) {\n            return false;\n        }\n        String tableNameLower = SQLUtils.normalize(tableName).toLowerCase();\n        return updateCheckColumns.containsKey(tableNameLower);\n    }\n\n    public Set<String> getUpdateCheckTable(String tableName) {\n        if (updateCheckColumns.isEmpty()) {\n            return null;\n        }\n        String tableNameLower = SQLUtils.normalize(tableName).toLowerCase();\n        return updateCheckColumns.get(tableNameLower);\n    }\n\n    public WallUpdateCheckHandler getUpdateCheckHandler() {\n        return updateCheckHandler;\n    }\n\n    public void setUpdateCheckHandler(WallUpdateCheckHandler updateCheckHandler) {\n        this.updateCheckHandler = updateCheckHandler;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallConfigMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.util.Set;\n\npublic interface WallConfigMBean {\n    boolean isInited();\n\n    String getDir();\n\n    void setDir(String dir);\n\n    void init();\n\n    void loadConfig(String dir);\n\n    boolean isNoneBaseStatementAllow();\n\n    void setNoneBaseStatementAllow(boolean noneBaseStatementAllow);\n\n    boolean isTruncateAllow();\n\n    void setTruncateAllow(boolean truncateAllow);\n\n    boolean isSelelctAllow();\n\n    void setSelelctAllow(boolean selelctAllow);\n\n    boolean isSelectIntoAllow();\n\n    void setSelectIntoAllow(boolean selectIntoAllow);\n\n    boolean isSelectIntoOutfileAllow();\n\n    void setSelectIntoOutfileAllow(boolean selectIntoOutfileAllow);\n\n    boolean isSelectUnionCheck();\n\n    void setSelectUnionCheck(boolean selectUnionCheck);\n\n    boolean isSelectWhereAlwayTrueCheck();\n\n    void setSelectWhereAlwayTrueCheck(boolean selectWhereAlwayTrueCheck);\n\n    boolean isSelectHavingAlwayTrueCheck();\n\n    void setSelectHavingAlwayTrueCheck(boolean selectHavingAlwayTrueCheck);\n\n    boolean isDeleteAllow();\n\n    void setDeleteAllow(boolean deleteAllow);\n\n    boolean isDeleteWhereAlwayTrueCheck();\n\n    void setDeleteWhereAlwayTrueCheck(boolean deleteWhereAlwayTrueCheck);\n\n    boolean isUpdateAllow();\n\n    void setUpdateAllow(boolean updateAllow);\n\n    boolean isUpdateWhereAlayTrueCheck();\n\n    void setUpdateWhereAlayTrueCheck(boolean updateWhereAlayTrueCheck);\n\n    boolean isInsertAllow();\n\n    void setInsertAllow(boolean insertAllow);\n\n    boolean isMergeAllow();\n\n    void setMergeAllow(boolean mergeAllow);\n\n    boolean isMultiStatementAllow();\n\n    void setMultiStatementAllow(boolean multiStatementAllow);\n\n    boolean isSchemaCheck();\n\n    void setSchemaCheck(boolean schemaCheck);\n\n    boolean isTableCheck();\n\n    void setTableCheck(boolean tableCheck);\n\n    boolean isFunctionCheck();\n\n    void setFunctionCheck(boolean functionCheck);\n\n    boolean isVariantCheck();\n\n    void setVariantCheck(boolean variantCheck);\n\n    boolean isObjectCheck();\n\n    void setObjectCheck(boolean objectCheck);\n\n    boolean isCommentAllow();\n\n    void setCommentAllow(boolean commentAllow);\n\n    Set<String> getDenyFunctions();\n\n    Set<String> getDenyTables();\n\n    Set<String> getDenySchemas();\n\n    Set<String> getDenyVariants();\n\n    Set<String> getDenyObjects();\n\n    Set<String> getReadOnlyTables();\n\n    boolean isDenyObjects(String name);\n\n    boolean isDenySchema(String name);\n\n    boolean isDenyFunction(String name);\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallContext.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.DbType;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class WallContext {\n    private static final ThreadLocal<WallContext> contextLocal = new ThreadLocal<WallContext>();\n\n    private WallSqlStat sqlStat;\n    private Map<String, WallSqlTableStat> tableStats;\n    private Map<String, WallSqlFunctionStat> functionStats;\n    private final DbType dbType;\n    private int commentCount;\n    private int warnings;\n    private int unionWarnings;\n    private int updateNoneConditionWarnings;\n    private int deleteNoneConditionWarnings;\n    private int likeNumberWarnings;\n\n    private List<WallUpdateCheckItem> wallUpdateCheckItems;\n\n    public WallContext(String dbType) {\n        this(DbType.of(dbType));\n    }\n\n    public WallContext(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    public void incrementFunctionInvoke(String tableName) {\n        if (functionStats == null) {\n            functionStats = new HashMap<String, WallSqlFunctionStat>();\n        }\n\n        String lowerCaseName = tableName.toLowerCase();\n\n        WallSqlFunctionStat stat = functionStats.get(lowerCaseName);\n        if (stat == null) {\n            if (functionStats.size() > 100) {\n                return;\n            }\n\n            stat = new WallSqlFunctionStat();\n            functionStats.put(tableName, stat);\n        }\n\n        stat.incrementInvokeCount();\n    }\n\n    public WallSqlTableStat getTableStat(String tableName) {\n        if (tableStats == null) {\n            tableStats = new HashMap<String, WallSqlTableStat>(2);\n        }\n\n        String lowerCaseName = tableName.toLowerCase();\n\n        WallSqlTableStat stat = tableStats.get(lowerCaseName);\n        if (stat == null) {\n            if (tableStats.size() > 100) {\n                return null;\n            }\n\n            stat = new WallSqlTableStat();\n            tableStats.put(tableName, stat);\n        }\n        return stat;\n    }\n\n    public static WallContext createIfNotExists(DbType dbType) {\n        WallContext context = contextLocal.get();\n        if (context == null) {\n            context = new WallContext(dbType);\n            contextLocal.set(context);\n        }\n        return context;\n    }\n\n    public static WallContext create(String dbType) {\n        return create(DbType.of(dbType));\n    }\n\n    public static WallContext create(DbType dbType) {\n        WallContext context = new WallContext(dbType);\n        contextLocal.set(context);\n        return context;\n    }\n\n    public static WallContext current() {\n        return contextLocal.get();\n    }\n\n    public static void clearContext() {\n        contextLocal.remove();\n    }\n\n    public static void setContext(WallContext context) {\n        contextLocal.set(context);\n    }\n\n    public WallSqlStat getSqlStat() {\n        return sqlStat;\n    }\n\n    public void setSqlStat(WallSqlStat sqlStat) {\n        this.sqlStat = sqlStat;\n    }\n\n    public Map<String, WallSqlTableStat> getTableStats() {\n        return tableStats;\n    }\n\n    public Map<String, WallSqlFunctionStat> getFunctionStats() {\n        return functionStats;\n    }\n\n    public DbType getDbType() {\n        return dbType;\n    }\n\n    public int getCommentCount() {\n        return commentCount;\n    }\n\n    public void incrementCommentCount() {\n        if (this.commentCount == 0) {\n            this.warnings++;\n        }\n        this.commentCount++;\n    }\n\n    public int getWarnings() {\n        return warnings;\n    }\n\n    public void incrementWarnings() {\n        this.warnings++;\n    }\n\n    public int getLikeNumberWarnings() {\n        return likeNumberWarnings;\n    }\n\n    public void incrementLikeNumberWarnings() {\n        if (likeNumberWarnings == 0) {\n            this.warnings++;\n        }\n        likeNumberWarnings++;\n    }\n\n    public int getUnionWarnings() {\n        return unionWarnings;\n    }\n\n    public void incrementUnionWarnings() {\n        if (this.unionWarnings == 0) {\n            this.incrementWarnings();\n        }\n        this.unionWarnings++;\n    }\n\n    public int getUpdateNoneConditionWarnings() {\n        return updateNoneConditionWarnings;\n    }\n\n    public void incrementUpdateNoneConditionWarnings() {\n        // if (this.updateNoneConditionWarnings == 0) {\n        // this.incrementWarnings();\n        // }\n        this.updateNoneConditionWarnings++;\n    }\n\n    public int getDeleteNoneConditionWarnings() {\n        return deleteNoneConditionWarnings;\n    }\n\n    public void incrementDeleteNoneConditionWarnings() {\n        // if (this.deleteNoneConditionWarnings == 0) {\n        // this.incrementWarnings();\n        // }\n        this.deleteNoneConditionWarnings++;\n    }\n\n    public List<WallUpdateCheckItem> getWallUpdateCheckItems() {\n        return wallUpdateCheckItems;\n    }\n\n    public void setWallUpdateCheckItems(List<WallUpdateCheckItem> wallUpdateCheckItems) {\n        this.wallUpdateCheckItems = wallUpdateCheckItems;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallDenyStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.util.Date;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\npublic class WallDenyStat {\n    private volatile long denyCount;\n\n    private volatile long lastDenyTimeMillis;\n\n    private volatile long resetCount;\n\n    static final AtomicLongFieldUpdater<WallDenyStat> denyCountUpdater = AtomicLongFieldUpdater.newUpdater(WallDenyStat.class,\n            \"denyCount\");\n\n    static final AtomicLongFieldUpdater<WallDenyStat> resetCountUpdater = AtomicLongFieldUpdater.newUpdater(WallDenyStat.class,\n            \"resetCount\");\n\n    public long incrementAndGetDenyCount() {\n        lastDenyTimeMillis = System.currentTimeMillis();\n        return denyCountUpdater.incrementAndGet(this);\n    }\n\n    public long getDenyCount() {\n        return denyCount;\n    }\n\n    public Date getLastDenyTime() {\n        if (lastDenyTimeMillis <= 0) {\n            return null;\n        }\n        return new Date(lastDenyTimeMillis);\n    }\n\n    public void reset() {\n        lastDenyTimeMillis = 0;\n        denyCount = 0;\n        resetCountUpdater.incrementAndGet(this);\n    }\n\n    public long getResetCount() {\n        return this.resetCount;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.VERSION;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.proxy.jdbc.*;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLValuableExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.ServletPathMatcher;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.wall.WallConfig.TenantCallBack;\nimport com.alibaba.druid.wall.WallConfig.TenantCallBack.StatementType;\nimport com.alibaba.druid.wall.spi.*;\nimport com.alibaba.druid.wall.violation.SyntaxErrorViolation;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.*;\n\nimport static com.alibaba.druid.util.Utils.getBoolean;\n\npublic class WallFilter extends FilterAdapter implements WallFilterMBean {\n    private static final Log LOG = LogFactory.getLog(WallFilter.class);\n\n    private volatile boolean inited;\n\n    private volatile WallProvider provider;\n\n    private volatile String dbTypeName;\n\n    private volatile WallConfig config;\n\n    private volatile boolean logViolation;\n    private volatile boolean throwException = true;\n\n    public static final String ATTR_SQL_STAT = \"wall.sqlStat\";\n    public static final String ATTR_UPDATE_CHECK_ITEMS = \"wall.updateCheckItems\";\n\n    public WallFilter() {\n        this(System.getProperties());\n    }\n\n    public WallFilter(final Properties properties) {\n        if (properties != null) {\n            configFromProperties(properties);\n        }\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n        {\n            Boolean value = getBoolean(properties, \"druid.wall.logViolation\");\n            if (value != null) {\n                this.logViolation = value;\n            }\n        }\n        {\n            Boolean value = getBoolean(properties, \"druid.wall.throwException\");\n            if (value != null) {\n                this.throwException = value;\n            }\n        }\n\n        if (this.config != null) {\n            this.config.configFromProperties(properties);\n        }\n    }\n\n    @Override\n    public synchronized void init(DataSourceProxy dataSource) {\n        if (this.inited) {\n            return;\n        }\n\n        if (dataSource == null) {\n            LOG.error(\"dataSource should not be null\");\n            return;\n        }\n\n        if (this.dbTypeName == null || this.dbTypeName.trim().length() == 0) {\n            if (dataSource.getDbType() != null) {\n                this.dbTypeName = dataSource.getDbType();\n            } else {\n                this.dbTypeName = JdbcUtils.getDbType(dataSource.getRawJdbcUrl(), \"\");\n            }\n        }\n\n        if (dbTypeName == null) {\n            dbTypeName = JdbcUtils.getDbType(dataSource.getUrl(), null);\n        }\n\n        provider = initWallProvider(dataSource, dbTypeName, config);\n        this.config = provider.getConfig();\n        provider.setName(dataSource.getName());\n        this.inited = true;\n    }\n\n    protected WallProvider initWallProvider(DataSourceProxy dataSource, String dbTypeName, WallConfig config) {\n        return initWallProviderInternal(dataSource, dbTypeName, config);\n    }\n\n    static WallProvider initWallProviderInternal(DataSourceProxy dataSource, String dbTypeName, WallConfig config) {\n        WallProvider provider = null;\n        DbType dbType = DbType.of(dbTypeName);\n        if (dbType == null) {\n            provider = initWallProviderWithSPI(dataSource, config, dbType);\n            if (provider == null) {\n                throw new IllegalStateException(\"dbType not support : \" + dbTypeName + \", url \" + dataSource.getUrl());\n            }\n            return provider;\n        }\n        switch (dbType) {\n            case mysql:\n            case oceanbase:\n            case drds:\n            case mariadb:\n            case tidb:\n            case h2:\n            case lealone:\n            case presto:\n            case trino:\n            case supersql:\n            case polardbx:\n                if (config == null) {\n                    config = new WallConfig(MySqlWallProvider.DEFAULT_CONFIG_DIR);\n                }\n\n                provider = new MySqlWallProvider(config);\n                break;\n            case oracle:\n            case ali_oracle:\n            case oceanbase_oracle:\n            case polardb2:\n            //case dm:\n                if (config == null) {\n                    config = new WallConfig(OracleWallProvider.DEFAULT_CONFIG_DIR);\n                }\n\n                provider = new OracleWallProvider(config);\n                break;\n            case sqlserver:\n            case jtds:\n                if (config == null) {\n                    config = new WallConfig(SQLServerWallProvider.DEFAULT_CONFIG_DIR);\n                }\n\n                provider = new SQLServerWallProvider(config);\n                break;\n            case postgresql:\n            case edb:\n            case polardb:\n            case greenplum:\n            case gaussdb:\n                if (config == null) {\n                    config = new WallConfig(PGWallProvider.DEFAULT_CONFIG_DIR);\n                }\n\n                provider = new PGWallProvider(config);\n                break;\n            case db2:\n                if (config == null) {\n                    config = new WallConfig(DB2WallProvider.DEFAULT_CONFIG_DIR);\n                }\n\n                provider = new DB2WallProvider(config);\n                break;\n            case sqlite:\n                if (config == null) {\n                    config = new WallConfig(SQLiteWallProvider.DEFAULT_CONFIG_DIR);\n                }\n\n                provider = new SQLiteWallProvider(config);\n                break;\n            case clickhouse:\n                if (config == null) {\n                    config = new WallConfig(CKWallProvider.DEFAULT_CONFIG_DIR);\n                }\n                provider = new CKWallProvider(config);\n                break;\n            default:\n                provider = initWallProviderWithSPI(dataSource, config, dbType);\n                if (provider == null) {\n                    throw new IllegalStateException(\"dbType not support : \" + dbType + \", url \" + dataSource.getUrl());\n                }\n        }\n        return provider;\n    }\n\n    static WallProvider initWallProviderWithSPI(DataSourceProxy dataSource, WallConfig config, DbType dbType) {\n        List<WallProviderCreator> wallProviderCreatorList = new ArrayList<>();\n        ServiceLoader<WallProviderCreator> providerCreators = ServiceLoader.load(WallProviderCreator.class);\n        providerCreators.forEach((wallProviderCreator) -> {\n            wallProviderCreatorList.add(wallProviderCreator);\n        });\n        //sort wallProviderCreatorList\n        Collections.sort(wallProviderCreatorList, (o1, o2) -> {\n            return Integer.compare(o1.getOrder(), o2.getOrder());\n        });\n        for (WallProviderCreator providerCreator : wallProviderCreatorList) {\n            WallProvider wallProvider = providerCreator.createWallConfig(dataSource, config, dbType);\n            if (wallProvider != null) {\n                LOG.debug(\"use wallProvider \" + wallProvider.getClass().getName() + \" from \" + providerCreator.getClass().getName());\n                return wallProvider;\n            }\n        }\n        return null;\n    }\n\n    public String getDbType() {\n        return dbTypeName;\n    }\n\n    public void setDbType(String dbType) {\n        this.dbTypeName = dbType;\n    }\n\n    public void setDbType(DbType dbType) {\n        if (dbType == null) {\n            this.dbTypeName = null;\n        } else {\n            this.dbTypeName = dbType.name();\n        }\n    }\n\n    public boolean isLogViolation() {\n        return logViolation;\n    }\n\n    public void setLogViolation(boolean logViolation) {\n        this.logViolation = logViolation;\n    }\n\n    public boolean isThrowException() {\n        return throwException;\n    }\n\n    public void setThrowException(boolean throwException) {\n        this.throwException = throwException;\n    }\n\n    public void clearProviderCache() {\n        if (provider != null) {\n            provider.clearCache();\n        }\n    }\n\n    public Set<String> getProviderWhiteList() {\n        if (provider == null) {\n            return Collections.emptySet();\n        }\n\n        return provider.getWhiteList();\n    }\n\n    public WallProvider getProvider() {\n        return provider;\n    }\n\n    public WallConfig getConfig() {\n        return config;\n    }\n\n    public void setConfig(WallConfig config) {\n        this.config = config;\n    }\n\n    public void setTenantColumn(String tenantColumn) {\n        if (this.config == null) {\n            throw new IllegalStateException(\"WallFilter config is not set, call setConfig() or init() first\");\n        }\n        this.config.setTenantColumn(tenantColumn);\n    }\n\n    public String getTenantColumn() {\n        if (config == null) {\n            return null;\n        }\n        return this.config.getTenantColumn();\n    }\n\n    public boolean isInited() {\n        return inited;\n    }\n\n    @Override\n    public void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            chain.statement_addBatch(statement, sql);\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public void preparedStatement_addBatch(FilterChain chain, PreparedStatementProxy statement) throws SQLException {\n        chain.preparedStatement_addBatch(statement);\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            PreparedStatementProxy stmt = chain.connection_prepareStatement(connection, sql);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int autoGeneratedKeys) throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            PreparedStatementProxy stmt = chain.connection_prepareStatement(connection, sql, autoGeneratedKeys);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            PreparedStatementProxy stmt = chain.connection_prepareStatement(connection, sql, resultSetType,\n                    resultSetConcurrency);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int resultSetType, int resultSetConcurrency,\n                                                              int resultSetHoldability) throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            PreparedStatementProxy stmt = chain.connection_prepareStatement(connection, sql, resultSetType,\n                    resultSetConcurrency, resultSetHoldability);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, int[] columnIndexes) throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            PreparedStatementProxy stmt = chain.connection_prepareStatement(connection, sql, columnIndexes);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                              String sql, String[] columnNames) throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            PreparedStatementProxy stmt = chain.connection_prepareStatement(connection, sql, columnNames);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql)\n            throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            CallableStatementProxy stmt = chain.connection_prepareCall(connection, sql);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency)\n            throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            CallableStatementProxy stmt = chain.connection_prepareCall(connection, sql, resultSetType,\n                    resultSetConcurrency);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,\n                                                         int resultSetType, int resultSetConcurrency,\n                                                         int resultSetHoldability) throws SQLException {\n        String dbType = connection.getDirectDataSource().getDbType();\n        WallContext context = WallContext.create(dbType);\n        try {\n            WallCheckResult result = checkInternal(sql);\n            context.setWallUpdateCheckItems(result.getUpdateCheckItems());\n            sql = result.getSql();\n            CallableStatementProxy stmt = chain.connection_prepareCall(connection, sql, resultSetType,\n                    resultSetConcurrency, resultSetHoldability);\n            setSqlStatAttribute(stmt);\n            return stmt;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    // //////////////\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        WallContext originalContext = WallContext.current();\n        try {\n            createWallContext(statement);\n            sql = check(sql);\n            boolean firstResult = chain.statement_execute(statement, sql);\n            if (!firstResult) {\n                int updateCount = statement.getUpdateCount();\n                statExecuteUpdate(updateCount);\n            } else {\n                setSqlStatAttribute(statement);\n            }\n            return firstResult;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            if (originalContext != null) {\n                WallContext.setContext(originalContext);\n            } else {\n                WallContext.clearContext();\n            }\n        }\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            boolean firstResult = chain.statement_execute(statement, sql, autoGeneratedKeys);\n            if (!firstResult) {\n                int updateCount = statement.getUpdateCount();\n                statExecuteUpdate(updateCount);\n            } else {\n                setSqlStatAttribute(statement);\n            }\n            return firstResult;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            boolean firstResult = chain.statement_execute(statement, sql, columnIndexes);\n            if (!firstResult) {\n                int updateCount = statement.getUpdateCount();\n                statExecuteUpdate(updateCount);\n            } else {\n                setSqlStatAttribute(statement);\n            }\n            return firstResult;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            boolean firstResult = chain.statement_execute(statement, sql, columnNames);\n            if (!firstResult) {\n                int updateCount = statement.getUpdateCount();\n                statExecuteUpdate(updateCount);\n            } else {\n                setSqlStatAttribute(statement);\n            }\n            return firstResult;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public int[] statement_executeBatch(FilterChain chain, StatementProxy statement) throws SQLException {\n        WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);\n        try {\n            int[] updateCounts = chain.statement_executeBatch(statement);\n            int updateCount = 0;\n            for (int count : updateCounts) {\n                if (count > 0) {\n                    updateCount += count;\n                }\n            }\n\n            if (sqlStat != null) {\n                provider.addUpdateCount(sqlStat, updateCount);\n            }\n\n            return updateCounts;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)\n            throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            ResultSetProxy resultSetProxy = chain.statement_executeQuery(statement, sql);\n            preprocessResultSet(resultSetProxy);\n            return resultSetProxy;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            int updateCount = chain.statement_executeUpdate(statement, sql);\n            statExecuteUpdate(updateCount);\n            return updateCount;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n            throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            int updateCount = chain.statement_executeUpdate(statement, sql, autoGeneratedKeys);\n            statExecuteUpdate(updateCount);\n            return updateCount;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n            throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            int updateCount = chain.statement_executeUpdate(statement, sql, columnIndexes);\n            statExecuteUpdate(updateCount);\n            return updateCount;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    public String getDbType(StatementProxy statement) {\n        return statement.getConnectionProxy().getDirectDataSource().getDbType();\n    }\n\n    private WallContext createWallContext(StatementProxy statement) {\n        String dbType = getDbType(statement);\n        return WallContext.create(dbType);\n    }\n\n    @Override\n    public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n            throws SQLException {\n        createWallContext(statement);\n        try {\n            sql = check(sql);\n            int updateCount = chain.statement_executeUpdate(statement, sql, columnNames);\n            statExecuteUpdate(updateCount);\n            return updateCount;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount();\n            throw ex;\n        } finally {\n            WallContext.clearContext();\n        }\n    }\n\n    @Override\n    public boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement) throws SQLException {\n        try {\n            wallUpdateCheck(statement);\n\n            boolean firstResult = chain.preparedStatement_execute(statement);\n\n            if (!firstResult) {\n                WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);\n                int updateCount = statement.getUpdateCount();\n                if (sqlStat != null) {\n                    provider.addUpdateCount(sqlStat, updateCount);\n                }\n            }\n\n            return firstResult;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount(statement);\n            throw ex;\n        }\n    }\n\n    @Override\n    public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)\n            throws SQLException {\n        try {\n            ResultSetProxy resultSetProxy = chain.preparedStatement_executeQuery(statement);\n            preprocessResultSet(resultSetProxy);\n            return resultSetProxy;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount(statement);\n            throw ex;\n        }\n    }\n\n    @Override\n    public int preparedStatement_executeUpdate(FilterChain chain,\n                                               PreparedStatementProxy statement) throws SQLException {\n        try {\n            wallUpdateCheck(statement);\n\n            int updateCount = chain.preparedStatement_executeUpdate(statement);\n            WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);\n            if (sqlStat != null) {\n                provider.addUpdateCount(sqlStat, updateCount);\n            }\n            return updateCount;\n        } catch (SQLException ex) {\n            incrementExecuteErrorCount(statement);\n            throw ex;\n        }\n    }\n\n    private void wallUpdateCheck(PreparedStatementProxy statement) throws SQLException {\n        Map<Integer, JdbcParameter> parameterMap = statement.getParameters();\n        List<WallUpdateCheckItem> wallUpdateCheckItems = (List<WallUpdateCheckItem>) statement.getAttribute(ATTR_UPDATE_CHECK_ITEMS);\n        if (wallUpdateCheckItems != null) {\n            for (WallUpdateCheckItem item : wallUpdateCheckItems) {\n                Object setValue;\n                if (item.value instanceof SQLValuableExpr) {\n                    setValue = ((SQLValuableExpr) item.value).getValue();\n                } else if (item.value instanceof SQLVariantRefExpr) {\n                    int index = ((SQLVariantRefExpr) item.value).getIndex();\n                    JdbcParameter parameter = parameterMap.get(index);\n                    if (parameter != null) {\n                        setValue = parameter.getValue();\n                    } else {\n                        setValue = null;\n                    }\n                } else {\n                    setValue = null;\n                }\n\n                List<Object> filtersValues = new ArrayList<Object>(item.filterValues.size());\n                for (SQLExpr filterValueExpr : item.filterValues) {\n                    Object filterValue;\n                    if (filterValueExpr instanceof SQLValuableExpr) {\n                        filterValue = ((SQLValuableExpr) filterValueExpr).getValue();\n                    } else if (filterValueExpr instanceof SQLVariantRefExpr) {\n                        int index = ((SQLVariantRefExpr) filterValueExpr).getIndex();\n                        JdbcParameter parameter = parameterMap.get(index);\n                        if (parameter != null) {\n                            filterValue = parameter.getValue();\n                        } else {\n                            filterValue = null;\n                        }\n                    } else {\n                        filterValue = null;\n                    }\n                    filtersValues.add(filterValue);\n                }\n\n                boolean valid = config.updateCheckHandler.check(item.tableName, item.columnName, setValue, filtersValues);\n                if (!valid) {\n                    throw new SQLException(\"wall update check failed.\");\n                }\n            }\n        }\n    }\n\n    @Override\n    public ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException {\n        ResultSetProxy resultSetProxy = chain.statement_getResultSet(statement);\n        preprocessResultSet(resultSetProxy);\n        return resultSetProxy;\n    }\n\n    @Override\n    public ResultSetProxy statement_getGeneratedKeys(FilterChain chain, StatementProxy statement) throws SQLException {\n        ResultSetProxy resultSetProxy = chain.statement_getGeneratedKeys(statement);\n        preprocessResultSet(resultSetProxy);\n        return resultSetProxy;\n    }\n\n    public void setSqlStatAttribute(StatementProxy stmt) {\n        WallContext context = WallContext.current();\n        if (context == null) {\n            return;\n        }\n\n        WallSqlStat sqlStat = context.getSqlStat();\n        if (sqlStat == null) {\n            return;\n        }\n\n        stmt.putAttribute(ATTR_SQL_STAT, sqlStat);\n\n        List<WallUpdateCheckItem> wallUpdateCheckItems = context.getWallUpdateCheckItems();\n        if (wallUpdateCheckItems != null) {\n            stmt.putAttribute(ATTR_UPDATE_CHECK_ITEMS, wallUpdateCheckItems);\n        }\n    }\n\n    public void statExecuteUpdate(int updateCount) {\n        WallContext context = WallContext.current();\n        if (context == null) {\n            return;\n        }\n\n        WallSqlStat sqlStat = context.getSqlStat();\n        if (sqlStat == null) {\n            return;\n        }\n\n        if (updateCount > 0) {\n            provider.addUpdateCount(sqlStat, updateCount);\n        }\n    }\n\n    public void incrementExecuteErrorCount(PreparedStatementProxy statement) {\n        WallSqlStat sqlStat = (WallSqlStat) statement.getAttribute(ATTR_SQL_STAT);\n        if (sqlStat != null) {\n            sqlStat.incrementAndGetExecuteErrorCount();\n        }\n    }\n\n    public void incrementExecuteErrorCount() {\n        WallContext context = WallContext.current();\n        if (context == null) {\n            return;\n        }\n\n        WallSqlStat sqlStat = context.getSqlStat();\n        if (sqlStat == null) {\n            return;\n        }\n\n        sqlStat.incrementAndGetExecuteErrorCount();\n    }\n\n    public String check(String sql) throws SQLException {\n        return checkInternal(sql)\n                .getSql();\n    }\n\n    private WallCheckResult checkInternal(String sql) throws SQLException {\n        WallCheckResult checkResult = provider.check(sql);\n        List<Violation> violations = checkResult.getViolations();\n\n        if (violations.size() > 0) {\n            Violation firstViolation = violations.get(0);\n            if (isLogViolation()) {\n                LOG.error(\"sql injection violation, dbType \"\n                        + getDbType()\n                        + \", druid-version \"\n                        + VERSION.getVersionNumber()\n                        + \", \"\n                        + firstViolation.getMessage() + \" : \" + sql);\n            }\n\n            if (throwException) {\n                if (violations.get(0) instanceof SyntaxErrorViolation) {\n                    SyntaxErrorViolation violation = (SyntaxErrorViolation) violations.get(0);\n                    throw new SQLException(\"sql injection violation, dbType \"\n                            + getDbType()\n                            + \", druid-version \"\n                            + VERSION.getVersionNumber()\n                            + \", \"\n                            + firstViolation.getMessage() + \" : \" + sql,\n                            violation.getException());\n                } else {\n                    throw new SQLException(\"sql injection violation, dbType \"\n                            + getDbType()\n                            + \", druid-version \"\n                            + VERSION.getVersionNumber()\n                            + \", \"\n                            + firstViolation.getMessage()\n                            + \" : \" + sql);\n                }\n            }\n        }\n\n        return checkResult;\n    }\n\n    @Override\n    public boolean isWrapperFor(FilterChain chain, Wrapper wrapper, Class<?> iface) throws SQLException {\n        if (config.isDoPrivilegedAllow() && WallProvider.ispPrivileged()) {\n            return chain.isWrapperFor(wrapper, iface);\n        }\n\n        return this.provider.getConfig().isWrapAllow() && chain.isWrapperFor(wrapper, iface);\n    }\n\n    @Override\n    public <T> T unwrap(FilterChain chain, Wrapper wrapper, Class<T> iface) throws SQLException {\n        if (config.isDoPrivilegedAllow() && WallProvider.ispPrivileged()) {\n            return chain.unwrap(wrapper, iface);\n        }\n\n        if (!this.provider.getConfig().isWrapAllow()) {\n            return null;\n        }\n\n        return chain.unwrap(wrapper, iface);\n    }\n\n    @Override\n    public DatabaseMetaData connection_getMetaData(FilterChain chain, ConnectionProxy connection) throws SQLException {\n        if (config.isDoPrivilegedAllow() && WallProvider.ispPrivileged()) {\n            return chain.connection_getMetaData(connection);\n        }\n\n        if (!this.provider.getConfig().isMetadataAllow()) {\n            if (isLogViolation()) {\n                LOG.error(\"not support method : Connection.getMetaData\");\n            }\n\n            if (throwException) {\n                throw new WallSQLException(\"not support method : Connection.getMetaData\");\n            }\n        }\n\n        return chain.connection_getMetaData(connection);\n    }\n\n    @Override\n    public void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        chain.resultSet_close(resultSet);\n        int fetchRowCount = resultSet.getFetchRowCount();\n\n        WallSqlStat sqlStat = (WallSqlStat) resultSet.getStatementProxy().getAttribute(ATTR_SQL_STAT);\n        if (sqlStat != null) {\n            provider.addFetchRowCount(sqlStat, fetchRowCount);\n        }\n    }\n\n    // ////////////////\n\n    @Override\n    public int resultSet_findColumn(FilterChain chain, ResultSetProxy resultSet, String columnLabel)\n            throws SQLException {\n        int physicalColumn = chain.resultSet_findColumn(resultSet, columnLabel);\n        List<Integer> hiddenColumns = resultSet.getHiddenColumns();\n        if (hiddenColumns != null && hiddenColumns.contains(physicalColumn)) {\n            throw new SQLException(\"Column '\" + columnLabel + \"' not found\", \"S0022\");\n        }\n        return resultSet.getLogicColumn(physicalColumn);\n    }\n\n    @Override\n    public Array resultSet_getArray(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getArray(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getAsciiStream(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getBigDecimal(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public BigDecimal resultSet_getBigDecimal(FilterChain chain, ResultSetProxy resultSet, int columnIndex, int scale)\n            throws SQLException {\n        return chain.resultSet_getBigDecimal(resultSet, resultSet.getPhysicalColumn(columnIndex), scale);\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getBinaryStream(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getBlob(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public boolean resultSet_getBoolean(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getBoolean(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public byte resultSet_getByte(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getByte(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getBytes(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.io.Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getCharacterStream(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getClob(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getDate(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.sql.Date resultSet_getDate(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Calendar cal)\n            throws SQLException {\n        return chain.resultSet_getDate(resultSet, resultSet.getPhysicalColumn(columnIndex), cal);\n    }\n\n    @Override\n    public double resultSet_getDouble(FilterChain chain,\n                                      ResultSetProxy resultSet,\n                                      int columnIndex) throws SQLException {\n        return chain.resultSet_getDouble(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public float resultSet_getFloat(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getFloat(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public int resultSet_getInt(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getInt(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public long resultSet_getLong(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getLong(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.io.Reader resultSet_getNCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getNCharacterStream(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public NClob resultSet_getNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getNClob(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public String resultSet_getNString(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getNString(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain,\n                                      ResultSetProxy resultSet,\n                                      int columnIndex) throws SQLException {\n        return chain.resultSet_getObject(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public <T> T resultSet_getObject(FilterChain chain,\n                                     ResultSetProxy resultSet,\n                                     int columnIndex,\n                                     Class<T> type) throws SQLException {\n        return chain.resultSet_getObject(resultSet, resultSet.getPhysicalColumn(columnIndex), type);\n    }\n\n    @Override\n    public Object resultSet_getObject(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                      java.util.Map<String, Class<?>> map) throws SQLException {\n        return chain.resultSet_getObject(resultSet, resultSet.getPhysicalColumn(columnIndex), map);\n    }\n\n    @Override\n    public Ref resultSet_getRef(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getRef(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public RowId resultSet_getRowId(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getRowId(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public SQLXML resultSet_getSQLXML(FilterChain chain,\n                                      ResultSetProxy resultSet,\n                                      int columnIndex) throws SQLException {\n        return chain.resultSet_getSQLXML(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public short resultSet_getShort(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        return chain.resultSet_getShort(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public String resultSet_getString(FilterChain chain,\n                                      ResultSetProxy resultSet,\n                                      int columnIndex) throws SQLException {\n        return chain.resultSet_getString(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getTime(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.sql.Time resultSet_getTime(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Calendar cal)\n            throws SQLException {\n        return chain.resultSet_getTime(resultSet, resultSet.getPhysicalColumn(columnIndex), cal);\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getTimestamp(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.sql.Timestamp resultSet_getTimestamp(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                                     Calendar cal) throws SQLException {\n        return chain.resultSet_getTimestamp(resultSet, resultSet.getPhysicalColumn(columnIndex), cal);\n    }\n\n    @Override\n    public java.net.URL resultSet_getURL(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getURL(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public java.io.InputStream resultSet_getUnicodeStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex)\n            throws SQLException {\n        return chain.resultSet_getUnicodeStream(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public void resultSet_updateArray(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Array x)\n            throws SQLException {\n        chain.resultSet_updateArray(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                            java.io.InputStream x) throws SQLException {\n        chain.resultSet_updateAsciiStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                            java.io.InputStream x, int length) throws SQLException {\n        chain.resultSet_updateAsciiStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x, length);\n    }\n\n    @Override\n    public void resultSet_updateAsciiStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                            java.io.InputStream x, long length) throws SQLException {\n        chain.resultSet_updateAsciiStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x, length);\n    }\n\n    @Override\n    public void resultSet_updateBigDecimal(FilterChain chain, ResultSetProxy resultSet, int columnIndex, BigDecimal x)\n            throws SQLException {\n        chain.resultSet_updateBigDecimal(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                             java.io.InputStream x) throws SQLException {\n        chain.resultSet_updateBinaryStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                             java.io.InputStream x, int length) throws SQLException {\n        chain.resultSet_updateBinaryStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x, length);\n    }\n\n    @Override\n    public void resultSet_updateBinaryStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                             java.io.InputStream x, long length) throws SQLException {\n        chain.resultSet_updateBinaryStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x, length);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                     InputStream inputStream) throws SQLException {\n        chain.resultSet_updateBlob(resultSet, resultSet.getPhysicalColumn(columnIndex), inputStream);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                     InputStream inputStream, long length) throws SQLException {\n        chain.resultSet_updateBlob(resultSet, resultSet.getPhysicalColumn(columnIndex), inputStream, length);\n    }\n\n    @Override\n    public void resultSet_updateBlob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Blob x)\n            throws SQLException {\n        chain.resultSet_updateBlob(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateBoolean(FilterChain chain, ResultSetProxy resultSet, int columnIndex, boolean x)\n            throws SQLException {\n        chain.resultSet_updateBoolean(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateByte(FilterChain chain, ResultSetProxy resultSet, int columnIndex, byte x)\n            throws SQLException {\n        chain.resultSet_updateByte(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateBytes(FilterChain chain, ResultSetProxy resultSet, int columnIndex, byte[] x)\n            throws SQLException {\n        chain.resultSet_updateBytes(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                                java.io.Reader x) throws SQLException {\n        chain.resultSet_updateCharacterStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                                java.io.Reader x, int length) throws SQLException {\n        chain.resultSet_updateCharacterStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x, length);\n    }\n\n    @Override\n    public void resultSet_updateCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                                java.io.Reader x, long length) throws SQLException {\n        chain.resultSet_updateCharacterStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x, length);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Clob x)\n            throws SQLException {\n        chain.resultSet_updateClob(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader)\n            throws SQLException {\n        chain.resultSet_updateClob(resultSet, resultSet.getPhysicalColumn(columnIndex), reader);\n    }\n\n    @Override\n    public void resultSet_updateClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader,\n                                     long length) throws SQLException {\n        chain.resultSet_updateClob(resultSet, resultSet.getPhysicalColumn(columnIndex), reader, length);\n    }\n\n    @Override\n    public void resultSet_updateDate(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Date x)\n            throws SQLException {\n        chain.resultSet_updateDate(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateDouble(FilterChain chain, ResultSetProxy resultSet, int columnIndex, double x)\n            throws SQLException {\n        chain.resultSet_updateDouble(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateFloat(FilterChain chain, ResultSetProxy resultSet, int columnIndex, float x)\n            throws SQLException {\n        chain.resultSet_updateFloat(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateInt(FilterChain chain, ResultSetProxy resultSet, int columnIndex, int x)\n            throws SQLException {\n        chain.resultSet_updateInt(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateLong(FilterChain chain, ResultSetProxy resultSet, int columnIndex, long x)\n            throws SQLException {\n        chain.resultSet_updateLong(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                                 java.io.Reader x) throws SQLException {\n        chain.resultSet_updateNCharacterStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateNCharacterStream(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                                 java.io.Reader x, long length) throws SQLException {\n        chain.resultSet_updateNCharacterStream(resultSet, resultSet.getPhysicalColumn(columnIndex), x, length);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, NClob nClob)\n            throws SQLException {\n        chain.resultSet_updateNClob(resultSet, resultSet.getPhysicalColumn(columnIndex), nClob);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader)\n            throws SQLException {\n        chain.resultSet_updateNClob(resultSet, resultSet.getPhysicalColumn(columnIndex), reader);\n    }\n\n    @Override\n    public void resultSet_updateNClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Reader reader,\n                                      long length) throws SQLException {\n        chain.resultSet_updateNClob(resultSet, resultSet.getPhysicalColumn(columnIndex), reader, length);\n    }\n\n    @Override\n    public void resultSet_updateNString(FilterChain chain, ResultSetProxy resultSet, int columnIndex, String nString)\n            throws SQLException {\n        chain.resultSet_updateNString(resultSet, resultSet.getPhysicalColumn(columnIndex), nString);\n    }\n\n    @Override\n    public void resultSet_updateNull(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException {\n        chain.resultSet_updateNull(resultSet, resultSet.getPhysicalColumn(columnIndex));\n    }\n\n    @Override\n    public void resultSet_updateObject(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Object x)\n            throws SQLException {\n        chain.resultSet_updateObject(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateObject(FilterChain chain, ResultSetProxy resultSet, int columnIndex, Object x,\n                                       int scaleOrLength) throws SQLException {\n        chain.resultSet_updateObject(resultSet, resultSet.getPhysicalColumn(columnIndex), x, scaleOrLength);\n    }\n\n    @Override\n    public void resultSet_updateRef(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Ref x)\n            throws SQLException {\n        chain.resultSet_updateRef(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateRowId(FilterChain chain, ResultSetProxy resultSet, int columnIndex, RowId x)\n            throws SQLException {\n        chain.resultSet_updateRowId(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateShort(FilterChain chain, ResultSetProxy resultSet, int columnIndex, short x)\n            throws SQLException {\n        chain.resultSet_updateShort(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateSQLXML(FilterChain chain, ResultSetProxy resultSet, int columnIndex, SQLXML xmlObject)\n            throws SQLException {\n        chain.resultSet_updateSQLXML(resultSet, resultSet.getPhysicalColumn(columnIndex), xmlObject);\n    }\n\n    @Override\n    public void resultSet_updateString(FilterChain chain, ResultSetProxy resultSet, int columnIndex, String x)\n            throws SQLException {\n        chain.resultSet_updateString(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateTime(FilterChain chain, ResultSetProxy resultSet, int columnIndex, java.sql.Time x)\n            throws SQLException {\n        chain.resultSet_updateTime(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public void resultSet_updateTimestamp(FilterChain chain, ResultSetProxy resultSet, int columnIndex,\n                                          java.sql.Timestamp x) throws SQLException {\n        chain.resultSet_updateTimestamp(resultSet, resultSet.getPhysicalColumn(columnIndex), x);\n    }\n\n    @Override\n    public boolean resultSet_next(FilterChain chain, ResultSetProxy resultSet) throws SQLException {\n        boolean hasNext = chain.resultSet_next(resultSet);\n        TenantCallBack callback = provider.getConfig().getTenantCallBack();\n        if (callback != null && hasNext) {\n            List<Integer> tenantColumns = (List<Integer>) resultSet.getAttribute(ATTR_TENANT_COLUMNS);\n            if (tenantColumns != null && tenantColumns.size() > 0) {\n                for (Integer columnIndex : tenantColumns) {\n                    Object value = resultSet.getResultSetRaw().getObject(columnIndex);\n                    callback.filterResultsetTenantColumn(value);\n                }\n            }\n        }\n        return hasNext;\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnCount(FilterChain chain,\n                                                ResultSetMetaDataProxy metaData) throws SQLException {\n        int count = chain.resultSetMetaData_getColumnCount(metaData);\n        return count - metaData.getResultSetProxy().getHiddenColumnCount();\n    }\n\n    @Override\n    public boolean resultSetMetaData_isAutoIncrement(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isAutoIncrement(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public boolean resultSetMetaData_isCaseSensitive(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isCaseSensitive(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public boolean resultSetMetaData_isSearchable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isSearchable(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public boolean resultSetMetaData_isCurrency(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isCurrency(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public int resultSetMetaData_isNullable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isNullable(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public boolean resultSetMetaData_isSigned(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isSigned(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnDisplaySize(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnDisplaySize(metaData,\n                metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnLabel(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnLabel(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnName(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public String resultSetMetaData_getSchemaName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getSchemaName(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public int resultSetMetaData_getPrecision(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getPrecision(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public int resultSetMetaData_getScale(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getScale(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public String resultSetMetaData_getTableName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getTableName(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public String resultSetMetaData_getCatalogName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getCatalogName(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public int resultSetMetaData_getColumnType(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnType(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnTypeName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnTypeName(metaData,\n                metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public boolean resultSetMetaData_isReadOnly(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isReadOnly(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public boolean resultSetMetaData_isWritable(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isWritable(metaData, metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public boolean resultSetMetaData_isDefinitelyWritable(FilterChain chain,\n                                                          ResultSetMetaDataProxy metaData,\n                                                          int column)\n            throws SQLException {\n        return chain.resultSetMetaData_isDefinitelyWritable(metaData,\n                metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    @Override\n    public String resultSetMetaData_getColumnClassName(FilterChain chain, ResultSetMetaDataProxy metaData, int column)\n            throws SQLException {\n        return chain.resultSetMetaData_getColumnClassName(metaData,\n                metaData.getResultSetProxy().getPhysicalColumn(column));\n    }\n\n    public long getViolationCount() {\n        return this.provider.getViolationCount();\n    }\n\n    public void resetViolationCount() {\n        this.provider.reset();\n    }\n\n    public void clearWhiteList() {\n        this.provider.clearCache();\n    }\n\n    public boolean checkValid(String sql) {\n        return provider.checkValid(sql);\n    }\n\n    private static final String ATTR_TENANT_COLUMNS = \"wall.tenantColumns\";\n\n    private void preprocessResultSet(ResultSetProxy resultSet) throws SQLException {\n        if (resultSet == null) {\n            return;\n        }\n\n        ResultSetMetaData metaData = resultSet.getResultSetRaw().getMetaData();\n        if (metaData == null) {\n            return;\n        }\n\n        TenantCallBack tenantCallBack = provider.getConfig().getTenantCallBack();\n        String tenantTablePattern = provider.getConfig().getTenantTablePattern();\n        if (tenantCallBack == null && (tenantTablePattern == null || tenantTablePattern.length() == 0)) {\n            return;\n        }\n\n        Map<Integer, Integer> logicColumnMap = new HashMap<Integer, Integer>();\n        Map<Integer, Integer> physicalColumnMap = new HashMap<Integer, Integer>();\n        List<Integer> hiddenColumns = new ArrayList<Integer>();\n        List<Integer> tenantColumns = new ArrayList<Integer>();\n        for (int physicalColumn = 1, logicColumn = 1; physicalColumn <= metaData.getColumnCount(); physicalColumn++) {\n            boolean isHidden = false;\n            String tableName = metaData.getTableName(physicalColumn);\n\n            String hiddenColumn = null;\n            String tenantColumn = null;\n            if (tenantCallBack != null) {\n                tenantColumn = tenantCallBack.getTenantColumn(StatementType.SELECT, tableName);\n                hiddenColumn = tenantCallBack.getHiddenColumn(tableName);\n            }\n\n            if (StringUtils.isEmpty(hiddenColumn) || StringUtils.isEmpty(tenantColumn)) {\n                if (tableName == null || ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                    if (StringUtils.isEmpty(hiddenColumn)) {\n                        hiddenColumn = provider.getConfig().getTenantColumn();\n                    }\n\n                    if (StringUtils.isEmpty(tenantColumn)) {\n                        tenantColumn = provider.getConfig().getTenantColumn();\n                    }\n                }\n            }\n\n            if (!StringUtils.isEmpty(hiddenColumn)) {\n                String columnName = metaData.getColumnName(physicalColumn);\n                if (hiddenColumn.equalsIgnoreCase(columnName)) {\n                    hiddenColumns.add(physicalColumn);\n                    isHidden = true;\n                }\n            }\n            if (!isHidden) {\n                logicColumnMap.put(logicColumn, physicalColumn);\n                physicalColumnMap.put(physicalColumn, logicColumn);\n                logicColumn++;\n            }\n\n            if (!StringUtils.isEmpty(tenantColumn)\n                    && tenantColumn.equalsIgnoreCase(metaData.getColumnName(physicalColumn))) {\n                tenantColumns.add(physicalColumn);\n            }\n        }\n\n        if (hiddenColumns.size() > 0) {\n            resultSet.setLogicColumnMap(logicColumnMap);\n            resultSet.setPhysicalColumnMap(physicalColumnMap);\n            resultSet.setHiddenColumns(hiddenColumns);\n        }\n        if (tenantColumns.size() > 0) {\n            resultSet.putAttribute(ATTR_TENANT_COLUMNS, tenantColumns);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallFilterMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.sql.SQLException;\nimport java.util.Set;\n\npublic interface WallFilterMBean {\n    String getDbType();\n\n    boolean isLogViolation();\n\n    void setLogViolation(boolean logViolation);\n\n    boolean isThrowException();\n\n    void setThrowException(boolean throwException);\n\n    boolean isInited();\n\n    void clearProviderCache();\n\n    Set<String> getProviderWhiteList();\n\n    String check(String sql) throws SQLException;\n\n    long getViolationCount();\n\n    void resetViolationCount();\n\n    void clearWhiteList();\n\n    boolean checkValid(String sql);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallFunctionStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class WallFunctionStat {\n    private volatile long invokeCount;\n    static final AtomicLongFieldUpdater<WallFunctionStat> invokeCountUpdater = AtomicLongFieldUpdater.newUpdater(WallFunctionStat.class,\n            \"invokeCount\");\n\n    public long getInvokeCount() {\n        return invokeCount;\n    }\n\n    public void incrementInvokeCount() {\n        invokeCountUpdater.incrementAndGet(this);\n    }\n\n    public void addSqlFunctionStat(WallSqlFunctionStat sqlFunctionStat) {\n        this.invokeCount += sqlFunctionStat.getInvokeCount();\n    }\n\n    public String toString() {\n        return \"{\\\"invokeCount\\\":\" + invokeCount + \"}\";\n    }\n\n    public Map<String, Object> toMap() {\n        Map<String, Object> map = new HashMap<String, Object>();\n        map.put(\"invokeCount\", invokeCount);\n        return map;\n    }\n\n    public WallFunctionStatValue getStatValue(boolean reset) {\n        WallFunctionStatValue statValue = new WallFunctionStatValue();\n        statValue.setInvokeCount(get(this, invokeCountUpdater, reset));\n        return statValue;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallFunctionStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n@MTable(name = \"druid_wall_function\")\npublic class WallFunctionStatValue {\n    @MField(groupBy = true, aggregate = AggregateType.None)\n    private String name;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long invokeCount;\n\n    public WallFunctionStatValue() {\n    }\n\n    public WallFunctionStatValue(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public long getInvokeCount() {\n        return invokeCount;\n    }\n\n    public void setInvokeCount(long invokeCount) {\n        this.invokeCount = invokeCount;\n    }\n\n    public Map<String, Object> toMap() {\n        Map<String, Object> map = new LinkedHashMap<String, Object>(2);\n        map.put(\"name\", name);\n        map.put(\"invokeCount\", invokeCount);\n        return map;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallProvider.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlHintStatement;\nimport com.alibaba.druid.sql.parser.*;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.alibaba.druid.util.ConcurrentLruCache;\nimport com.alibaba.druid.util.Utils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\nimport com.alibaba.druid.wall.violation.ErrorCode;\nimport com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;\nimport com.alibaba.druid.wall.violation.SyntaxErrorViolation;\n\nimport java.security.PrivilegedAction;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic abstract class WallProvider {\n    private String name;\n\n    private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>(\n            1,\n            0.75f,\n            1);\n\n    private boolean whiteListEnable = true;\n\n    /**\n     * 8k\n     */\n    private static final int MAX_SQL_LENGTH = 8192;\n\n    private static final int WHITE_SQL_MAX_SIZE = 1024;\n\n    // public for testing\n    public static final int BLACK_SQL_MAX_SIZE = 256;\n\n    private static final int MERGED_SQL_CACHE_SIZE = 256;\n\n    private boolean blackListEnable = true;\n\n    private final ConcurrentLruCache<String, WallSqlStat> whiteList = new ConcurrentLruCache<>(WHITE_SQL_MAX_SIZE);\n    private final ConcurrentLruCache<String, WallSqlStat> blackList = new ConcurrentLruCache<>(BLACK_SQL_MAX_SIZE);\n    private final ConcurrentLruCache<String, MergedSqlResult> mergedSqlCache = new ConcurrentLruCache<>(MERGED_SQL_CACHE_SIZE);\n\n    protected final WallConfig config;\n\n    private static final ThreadLocal<Boolean> privileged = new ThreadLocal<Boolean>();\n\n    private final ConcurrentMap<String, WallFunctionStat> functionStats = new ConcurrentHashMap<String, WallFunctionStat>(\n            16,\n            0.75f,\n            1);\n    private final ConcurrentMap<String, WallTableStat> tableStats = new ConcurrentHashMap<String, WallTableStat>(\n            16,\n            0.75f,\n            1);\n\n    public final WallDenyStat commentDeniedStat = new WallDenyStat();\n\n    protected DbType dbType;\n    protected final AtomicLong checkCount = new AtomicLong();\n    protected final AtomicLong hardCheckCount = new AtomicLong();\n    protected final AtomicLong whiteListHitCount = new AtomicLong();\n    protected final AtomicLong blackListHitCount = new AtomicLong();\n    protected final AtomicLong syntaxErrorCount = new AtomicLong();\n    protected final AtomicLong violationCount = new AtomicLong();\n    protected final AtomicLong violationEffectRowCount = new AtomicLong();\n\n    public WallProvider(WallConfig config) {\n        this.config = config;\n    }\n\n    public WallProvider(WallConfig config, String dbType) {\n        this(config, DbType.of(dbType));\n    }\n\n    public WallProvider(WallConfig config, DbType dbType) {\n        this.config = config;\n        this.dbType = dbType;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Map<String, Object> getAttributes() {\n        return attributes;\n    }\n\n    public void reset() {\n        this.checkCount.set(0);\n        this.hardCheckCount.set(0);\n        this.violationCount.set(0);\n        this.whiteListHitCount.set(0);\n        this.blackListHitCount.set(0);\n        this.clearWhiteList();\n        this.clearBlackList();\n        this.functionStats.clear();\n        this.tableStats.clear();\n    }\n\n    public ConcurrentMap<String, WallTableStat> getTableStats() {\n        return this.tableStats;\n    }\n\n    public ConcurrentMap<String, WallFunctionStat> getFunctionStats() {\n        return this.functionStats;\n    }\n\n    public WallSqlStat getSqlStat(String sql) {\n        WallSqlStat sqlStat = this.getWhiteSql(sql);\n\n        if (sqlStat == null) {\n            sqlStat = this.getBlackSql(sql);\n        }\n\n        return sqlStat;\n    }\n\n    public WallTableStat getTableStat(String tableName) {\n        String lowerCaseName = tableName.toLowerCase();\n        if (lowerCaseName.startsWith(\"`\") && lowerCaseName.endsWith(\"`\")) {\n            lowerCaseName = lowerCaseName.substring(1, lowerCaseName.length() - 1);\n        }\n\n        return getTableStatWithLowerName(lowerCaseName);\n    }\n\n    public void addUpdateCount(WallSqlStat sqlStat, long updateCount) {\n        sqlStat.addUpdateCount(updateCount);\n\n        Map<String, WallSqlTableStat> sqlTableStats = sqlStat.getTableStats();\n        if (sqlTableStats == null) {\n            return;\n        }\n\n        for (Map.Entry<String, WallSqlTableStat> entry : sqlTableStats.entrySet()) {\n            String tableName = entry.getKey();\n            WallTableStat tableStat = this.getTableStat(tableName);\n            if (tableStat == null) {\n                continue;\n            }\n\n            WallSqlTableStat sqlTableStat = entry.getValue();\n\n            if (sqlTableStat.getDeleteCount() > 0) {\n                tableStat.addDeleteDataCount(updateCount);\n            } else if (sqlTableStat.getUpdateCount() > 0) {\n                tableStat.addUpdateDataCount(updateCount);\n            } else if (sqlTableStat.getInsertCount() > 0) {\n                tableStat.addInsertDataCount(updateCount);\n            }\n        }\n    }\n\n    public void addFetchRowCount(WallSqlStat sqlStat, long fetchRowCount) {\n        sqlStat.addAndFetchRowCount(fetchRowCount);\n\n        Map<String, WallSqlTableStat> sqlTableStats = sqlStat.getTableStats();\n        if (sqlTableStats == null) {\n            return;\n        }\n\n        for (Map.Entry<String, WallSqlTableStat> entry : sqlTableStats.entrySet()) {\n            String tableName = entry.getKey();\n            WallTableStat tableStat = this.getTableStat(tableName);\n            if (tableStat == null) {\n                continue;\n            }\n\n            WallSqlTableStat sqlTableStat = entry.getValue();\n\n            if (sqlTableStat.getSelectCount() > 0) {\n                tableStat.addFetchRowCount(fetchRowCount);\n            }\n        }\n    }\n\n    public WallTableStat getTableStatWithLowerName(String lowerCaseName) {\n        WallTableStat stat = tableStats.get(lowerCaseName);\n        if (stat == null) {\n            if (tableStats.size() > 10000) {\n                return null;\n            }\n\n            tableStats.putIfAbsent(lowerCaseName, new WallTableStat());\n            stat = tableStats.get(lowerCaseName);\n        }\n        return stat;\n    }\n\n    public WallFunctionStat getFunctionStat(String functionName) {\n        String lowerCaseName = functionName.toLowerCase();\n        return getFunctionStatWithLowerName(lowerCaseName);\n    }\n\n    public WallFunctionStat getFunctionStatWithLowerName(String lowerCaseName) {\n        WallFunctionStat stat = functionStats.get(lowerCaseName);\n        if (stat == null) {\n            if (functionStats.size() > 10000) {\n                return null;\n            }\n\n            functionStats.putIfAbsent(lowerCaseName, new WallFunctionStat());\n            stat = functionStats.get(lowerCaseName);\n        }\n        return stat;\n    }\n\n    public WallConfig getConfig() {\n        return config;\n    }\n\n    public WallSqlStat addWhiteSql(String sql, Map<String, WallSqlTableStat> tableStats,\n                                   Map<String, WallSqlFunctionStat> functionStats, boolean syntaxError) {\n        if (!whiteListEnable) {\n            WallSqlStat stat = new WallSqlStat(tableStats, functionStats, syntaxError);\n            return stat;\n        }\n\n        String mergedSql = getMergedSqlNullableIfParameterizeError(sql);\n        if (mergedSql == null) {\n            WallSqlStat stat = new WallSqlStat(tableStats, functionStats, syntaxError);\n            stat.incrementAndGetExecuteCount();\n            return stat;\n        }\n\n        WallSqlStat wallSqlStat = whiteList.computeIfAbsent(mergedSql, key -> {\n            WallSqlStat newStat = new WallSqlStat(tableStats, functionStats, syntaxError);\n            newStat.setSample(sql);\n            return newStat;\n        });\n\n        wallSqlStat.incrementAndGetExecuteCount();\n        return wallSqlStat;\n    }\n\n    public WallSqlStat addBlackSql(String sql, Map<String, WallSqlTableStat> tableStats,\n                                   Map<String, WallSqlFunctionStat> functionStats, List<Violation> violations,\n                                   boolean syntaxError) {\n        if (!blackListEnable) {\n            return new WallSqlStat(tableStats, functionStats, violations, syntaxError);\n        }\n\n        String mergedSql = getMergedSqlNullableIfParameterizeError(sql);\n        WallSqlStat wallSqlStat = blackList.computeIfAbsent(Utils.getIfNull(mergedSql, sql),\n                key -> {\n                    WallSqlStat wallStat = new WallSqlStat(tableStats, functionStats, violations, syntaxError);\n                    wallStat.setSample(sql);\n                    return wallStat;\n                });\n\n        wallSqlStat.incrementAndGetExecuteCount();\n        return wallSqlStat;\n    }\n\n    private String getMergedSqlNullableIfParameterizeError(String sql) {\n        MergedSqlResult mergedSqlResult = mergedSqlCache.get(sql);\n        if (mergedSqlResult != null) {\n            return mergedSqlResult.mergedSql;\n        }\n        try {\n            String mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType);\n            if (sql.length() < MAX_SQL_LENGTH) {\n                mergedSqlCache.computeIfAbsent(sql, key -> MergedSqlResult.success(mergedSql));\n            }\n            return mergedSql;\n        } catch (Exception ex) {\n            // skip\n            mergedSqlCache.computeIfAbsent(sql, key -> MergedSqlResult.FAILED);\n            return null;\n        }\n    }\n\n    public Set<String> getWhiteList() {\n        Set<String> hashSet = new HashSet<>();\n        Set<String> whiteListKeys = whiteList.keys();\n        if (!whiteListKeys.isEmpty()) {\n            hashSet.addAll(whiteListKeys);\n        }\n        return Collections.unmodifiableSet(hashSet);\n    }\n\n    public Set<String> getSqlList() {\n        Set<String> hashSet = new HashSet<>();\n        Set<String> whiteListKeys = whiteList.keys();\n        if (!whiteListKeys.isEmpty()) {\n            hashSet.addAll(whiteListKeys);\n        }\n\n        Set<String> blackMergedListKeys = blackList.keys();\n        if (!blackMergedListKeys.isEmpty()) {\n            hashSet.addAll(blackMergedListKeys);\n        }\n\n        return Collections.unmodifiableSet(hashSet);\n    }\n\n    public Set<String> getBlackList() {\n        Set<String> hashSet = new HashSet<>();\n        Set<String> blackMergedListKeys = blackList.keys();\n        if (!blackMergedListKeys.isEmpty()) {\n            hashSet.addAll(blackMergedListKeys);\n        }\n        return Collections.unmodifiableSet(hashSet);\n    }\n\n    public void clearCache() {\n        whiteList.clear();\n        blackList.clear();\n        mergedSqlCache.clear();\n    }\n\n    public void clearWhiteList() {\n        whiteList.clear();\n    }\n\n    public void clearBlackList() {\n        blackList.clear();\n    }\n\n    public WallSqlStat getWhiteSql(String sql) {\n        String cacheKey = Utils.getIfNull(getMergedSqlNullableIfParameterizeError(sql), sql);\n        return whiteList.get(cacheKey);\n    }\n\n    public WallSqlStat getBlackSql(String sql) {\n        String cacheKey = Utils.getIfNull(getMergedSqlNullableIfParameterizeError(sql), sql);\n        return blackList.get(cacheKey);\n    }\n\n    public boolean whiteContains(String sql) {\n        return getWhiteSql(sql) != null;\n    }\n\n    public abstract SQLStatementParser createParser(String sql);\n\n    public abstract WallVisitor createWallVisitor();\n\n    public abstract ExportParameterVisitor createExportParameterVisitor();\n\n    public boolean checkValid(String sql) {\n        WallContext originalContext = WallContext.current();\n\n        try {\n            WallContext.create(dbType);\n            WallCheckResult result = checkInternal(sql);\n            return result\n                    .getViolations()\n                    .isEmpty();\n        } finally {\n            if (originalContext == null) {\n                WallContext.clearContext();\n            }\n        }\n    }\n\n    public void incrementCommentDeniedCount() {\n        this.commentDeniedStat.incrementAndGetDenyCount();\n    }\n\n    public boolean checkDenyFunction(String functionName) {\n        if (functionName == null) {\n            return true;\n        }\n\n        functionName = functionName.toLowerCase();\n\n        return !getConfig().getDenyFunctions().contains(functionName);\n\n    }\n\n    public boolean checkDenySchema(String schemaName) {\n        if (schemaName == null) {\n            return true;\n        }\n\n        if (!this.config.isSchemaCheck()) {\n            return true;\n        }\n\n        schemaName = schemaName.toLowerCase();\n        return !getConfig().getDenySchemas().contains(schemaName);\n\n    }\n\n    public boolean checkDenyTable(String tableName) {\n        if (tableName == null) {\n            return true;\n        }\n\n        tableName = WallVisitorUtils.form(tableName);\n        return !getConfig().getDenyTables().contains(tableName);\n\n    }\n\n    public boolean checkReadOnlyTable(String tableName) {\n        if (tableName == null) {\n            return true;\n        }\n\n        tableName = WallVisitorUtils.form(tableName);\n        return !getConfig().isReadOnly(tableName);\n\n    }\n\n    public WallDenyStat getCommentDenyStat() {\n        return this.commentDeniedStat;\n    }\n\n    public WallCheckResult check(String sql) {\n        WallContext originalContext = WallContext.current();\n\n        try {\n            WallContext.createIfNotExists(dbType);\n            return checkInternal(sql);\n        } finally {\n            if (originalContext == null) {\n                WallContext.clearContext();\n            }\n        }\n    }\n\n    private WallCheckResult checkInternal(String sql) {\n        checkCount.incrementAndGet();\n\n        WallContext context = WallContext.current();\n\n        if (config.isDoPrivilegedAllow() && ispPrivileged()) {\n            WallCheckResult checkResult = new WallCheckResult();\n            checkResult.setSql(sql);\n            return checkResult;\n        }\n\n        // first step, check whiteList\n        boolean mulltiTenant = config.getTenantTablePattern() != null && config.getTenantTablePattern().length() > 0;\n        if (!mulltiTenant) {\n            WallCheckResult checkResult = checkWhiteAndBlackList(sql);\n            if (checkResult != null) {\n                checkResult.setSql(sql);\n                return checkResult;\n            }\n        }\n\n        hardCheckCount.incrementAndGet();\n        final List<Violation> violations = new ArrayList<Violation>();\n        List<SQLStatement> statementList = new ArrayList<SQLStatement>();\n        boolean syntaxError = false;\n        boolean endOfComment = false;\n        try {\n            SQLStatementParser parser = createParser(sql);\n            parser.getLexer().setCommentHandler(WallCommentHandler.instance);\n\n            if (!config.isCommentAllow()) {\n                parser.getLexer().setAllowComment(false); // deny comment\n            }\n            if (!config.isCompleteInsertValuesCheck()) {\n                parser.setParseCompleteValues(false);\n                parser.setParseValuesSize(config.getInsertValuesCheckSize());\n            }\n            if (config.isHintAllow()) {\n                parser.config(SQLParserFeature.StrictForWall, false);\n            }\n            parser.parseStatementList(statementList);\n\n            final Token lastToken = parser.getLexer().token();\n            if (lastToken != Token.EOF && config.isStrictSyntaxCheck()) {\n                violations.add(new IllegalSQLObjectViolation(ErrorCode.SYNTAX_ERROR, \"not terminal sql, token \"\n                        + lastToken, sql));\n            }\n            endOfComment = parser.getLexer().isEOF();\n        } catch (NotAllowCommentException e) {\n            violations.add(new IllegalSQLObjectViolation(ErrorCode.COMMENT_STATEMENT_NOT_ALLOW, \"comment not allow\", sql));\n            incrementCommentDeniedCount();\n        } catch (ParserException e) {\n            syntaxErrorCount.incrementAndGet();\n            syntaxError = true;\n            if (config.isStrictSyntaxCheck()) {\n                violations.add(new SyntaxErrorViolation(e, sql));\n            }\n        } catch (Exception e) {\n            if (config.isStrictSyntaxCheck()) {\n                violations.add(new SyntaxErrorViolation(e, sql));\n            }\n        }\n\n        if (statementList.size() > 1 && !config.isMultiStatementAllow()) {\n            violations.add(new IllegalSQLObjectViolation(ErrorCode.MULTI_STATEMENT, \"multi-statement not allow\", sql));\n        }\n\n        WallVisitor visitor = createWallVisitor();\n        visitor.setSqlEndOfComment(endOfComment);\n\n        if (statementList.size() > 0) {\n            boolean lastIsHint = false;\n            for (int i = 0; i < statementList.size(); i++) {\n                SQLStatement stmt = statementList.get(i);\n                if ((i == 0 || lastIsHint) && stmt instanceof MySqlHintStatement) {\n                    lastIsHint = true;\n                    continue;\n                }\n                try {\n                    stmt.accept(visitor);\n                } catch (ParserException e) {\n                    violations.add(new SyntaxErrorViolation(e, sql));\n                }\n            }\n        }\n\n        if (visitor.getViolations().size() > 0) {\n            violations.addAll(visitor.getViolations());\n        }\n\n        Map<String, WallSqlTableStat> tableStat = context.getTableStats();\n\n        boolean updateCheckHandlerEnable = false;\n        {\n            WallUpdateCheckHandler updateCheckHandler = config.getUpdateCheckHandler();\n            if (updateCheckHandler != null) {\n                for (SQLStatement stmt : statementList) {\n                    if (stmt instanceof SQLUpdateStatement) {\n                        SQLUpdateStatement updateStmt = (SQLUpdateStatement) stmt;\n                        SQLName table = updateStmt.getTableName();\n                        if (table != null) {\n                            String tableName = table.getSimpleName();\n                            Set<String> updateCheckColumns = config.getUpdateCheckTable(tableName);\n                            if (updateCheckColumns != null && updateCheckColumns.size() > 0) {\n                                updateCheckHandlerEnable = true;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        WallSqlStat sqlStat = null;\n        if (violations.size() > 0) {\n            violationCount.incrementAndGet();\n\n            if ((!updateCheckHandlerEnable) && sql.length() < MAX_SQL_LENGTH) {\n                sqlStat = addBlackSql(sql, tableStat, context.getFunctionStats(), violations, syntaxError);\n            }\n        } else {\n            if ((!updateCheckHandlerEnable) && sql.length() < MAX_SQL_LENGTH) {\n                boolean selectLimit = false;\n                if (config.getSelectLimit() > 0) {\n                    for (SQLStatement stmt : statementList) {\n                        if (stmt instanceof SQLSelectStatement) {\n                            selectLimit = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (!selectLimit) {\n                    sqlStat = addWhiteSql(sql, tableStat, context.getFunctionStats(), syntaxError);\n                }\n            }\n        }\n\n        if (sqlStat == null && updateCheckHandlerEnable) {\n            sqlStat = new WallSqlStat(tableStat, context.getFunctionStats(), violations, syntaxError);\n        }\n\n        Map<String, WallSqlTableStat> tableStats = null;\n        Map<String, WallSqlFunctionStat> functionStats = null;\n        if (context != null) {\n            tableStats = context.getTableStats();\n            functionStats = context.getFunctionStats();\n            recordStats(tableStats, functionStats);\n        }\n\n        WallCheckResult result;\n        if (sqlStat != null) {\n            context.setSqlStat(sqlStat);\n            result = new WallCheckResult(sqlStat, statementList);\n        } else {\n            result = new WallCheckResult(null, violations, tableStats, functionStats, statementList, syntaxError);\n        }\n\n        String resultSql;\n        if (visitor.isSqlModified()) {\n            resultSql = SQLUtils.toSQLString(statementList, dbType);\n        } else {\n            resultSql = sql;\n        }\n        result.setSql(resultSql);\n\n        result.setUpdateCheckItems(visitor.getUpdateCheckItems());\n\n        return result;\n    }\n\n    private WallCheckResult checkWhiteAndBlackList(String sql) {\n        if (config.getUpdateCheckHandler() != null) {\n            return null;\n        }\n\n        // check white list first\n        if (whiteListEnable) {\n            WallSqlStat sqlStat = getWhiteSql(sql);\n            if (sqlStat != null) {\n                whiteListHitCount.incrementAndGet();\n                sqlStat.incrementAndGetExecuteCount();\n\n                if (sqlStat.isSyntaxError()) {\n                    syntaxErrorCount.incrementAndGet();\n                }\n\n                recordStats(sqlStat.getTableStats(), sqlStat.getFunctionStats());\n                WallContext context = WallContext.current();\n                if (context != null) {\n                    context.setSqlStat(sqlStat);\n                }\n                return new WallCheckResult(sqlStat);\n            }\n        }\n\n        // check black list\n        if (blackListEnable) {\n            WallSqlStat sqlStat = getBlackSql(sql);\n            if (sqlStat != null) {\n                blackListHitCount.incrementAndGet();\n                violationCount.incrementAndGet();\n\n                if (sqlStat.isSyntaxError()) {\n                    syntaxErrorCount.incrementAndGet();\n                }\n\n                sqlStat.incrementAndGetExecuteCount();\n                recordStats(sqlStat.getTableStats(), sqlStat.getFunctionStats());\n\n                return new WallCheckResult(sqlStat);\n            }\n        }\n\n        return null;\n    }\n\n    void recordStats(Map<String, WallSqlTableStat> tableStats, Map<String, WallSqlFunctionStat> functionStats) {\n        if (tableStats != null) {\n            for (Map.Entry<String, WallSqlTableStat> entry : tableStats.entrySet()) {\n                String tableName = entry.getKey();\n                WallSqlTableStat sqlTableStat = entry.getValue();\n                WallTableStat tableStat = getTableStat(tableName);\n                if (tableStat != null) {\n                    tableStat.addSqlTableStat(sqlTableStat);\n                }\n            }\n        }\n        if (functionStats != null) {\n            for (Map.Entry<String, WallSqlFunctionStat> entry : functionStats.entrySet()) {\n                String tableName = entry.getKey();\n                WallSqlFunctionStat sqlTableStat = entry.getValue();\n                WallFunctionStat functionStat = getFunctionStatWithLowerName(tableName);\n                if (functionStat != null) {\n                    functionStat.addSqlFunctionStat(sqlTableStat);\n                }\n            }\n        }\n    }\n\n    public static boolean ispPrivileged() {\n        Boolean value = privileged.get();\n        if (value == null) {\n            return false;\n        }\n\n        return value;\n    }\n\n    public static <T> T doPrivileged(PrivilegedAction<T> action) {\n        final Boolean original = privileged.get();\n        privileged.set(Boolean.TRUE);\n        try {\n            return action.run();\n        } finally {\n            privileged.set(original);\n        }\n    }\n\n    private static final ThreadLocal<Object> tenantValueLocal = new ThreadLocal<Object>();\n\n    public static void setTenantValue(Object value) {\n        tenantValueLocal.set(value);\n    }\n\n    public static Object getTenantValue() {\n        return tenantValueLocal.get();\n    }\n\n    public long getWhiteListHitCount() {\n        return whiteListHitCount.get();\n    }\n\n    public long getBlackListHitCount() {\n        return blackListHitCount.get();\n    }\n\n    public long getSyntaxErrorCount() {\n        return syntaxErrorCount.get();\n    }\n\n    public long getCheckCount() {\n        return checkCount.get();\n    }\n\n    public long getViolationCount() {\n        return violationCount.get();\n    }\n\n    public long getHardCheckCount() {\n        return hardCheckCount.get();\n    }\n\n    public long getViolationEffectRowCount() {\n        return violationEffectRowCount.get();\n    }\n\n    public void addViolationEffectRowCount(long rowCount) {\n        violationEffectRowCount.addAndGet(rowCount);\n    }\n\n    public static class WallCommentHandler implements Lexer.CommentHandler {\n        public static final WallCommentHandler instance = new WallCommentHandler();\n\n        @Override\n        public boolean handle(Token lastToken, String comment) {\n            if (lastToken == null) {\n                return false;\n            }\n\n            switch (lastToken) {\n                case SELECT:\n                case INSERT:\n                case DELETE:\n                case UPDATE:\n                case TRUNCATE:\n                case SET:\n                case CREATE:\n                case ALTER:\n                case DROP:\n                case SHOW:\n                case REPLACE:\n                    return true;\n                default:\n                    break;\n            }\n\n            WallContext context = WallContext.current();\n            if (context != null) {\n                context.incrementCommentCount();\n            }\n\n            return false;\n        }\n    }\n\n    public WallProviderStatValue getStatValue(boolean reset) {\n        WallProviderStatValue statValue = new WallProviderStatValue();\n\n        statValue.setName(name);\n        statValue.setCheckCount(get(checkCount, reset));\n        statValue.setHardCheckCount(get(hardCheckCount, reset));\n        statValue.setViolationCount(get(violationCount, reset));\n        statValue.setViolationEffectRowCount(get(violationEffectRowCount, reset));\n        statValue.setBlackListHitCount(get(blackListHitCount, reset));\n        statValue.setWhiteListHitCount(get(whiteListHitCount, reset));\n        statValue.setSyntaxErrorCount(get(syntaxErrorCount, reset));\n\n        for (Map.Entry<String, WallTableStat> entry : this.tableStats.entrySet()) {\n            String tableName = entry.getKey();\n            WallTableStat tableStat = entry.getValue();\n\n            WallTableStatValue tableStatValue = tableStat.getStatValue(reset);\n\n            if (tableStatValue.getTotalExecuteCount() == 0) {\n                continue;\n            }\n\n            tableStatValue.setName(tableName);\n\n            statValue.getTables().add(tableStatValue);\n        }\n\n        for (Map.Entry<String, WallFunctionStat> entry : this.functionStats.entrySet()) {\n            String functionName = entry.getKey();\n            WallFunctionStat functionStat = entry.getValue();\n\n            WallFunctionStatValue functionStatValue = functionStat.getStatValue(reset);\n\n            if (functionStatValue.getInvokeCount() == 0) {\n                continue;\n            }\n            functionStatValue.setName(functionName);\n\n            statValue.getFunctions().add(functionStatValue);\n        }\n\n        whiteList.forEach((sql, sqlStat) -> {\n            WallSqlStatValue sqlStatValue = sqlStat.getStatValue(reset);\n\n            if (sqlStatValue.getExecuteCount() == 0) {\n                return;\n            }\n\n            sqlStatValue.setSql(sql);\n\n            long sqlHash = sqlStat.getSqlHash();\n            if (sqlHash == 0) {\n                sqlHash = Utils.fnv_64(sql);\n                sqlStat.setSqlHash(sqlHash);\n            }\n            sqlStatValue.setSqlHash(sqlHash);\n\n            statValue.getWhiteList().add(sqlStatValue);\n        });\n\n        blackList.forEach((sql, sqlStat) -> {\n            WallSqlStatValue sqlStatValue = sqlStat.getStatValue(reset);\n\n            if (sqlStatValue.getExecuteCount() == 0) {\n                return;\n            }\n\n            sqlStatValue.setSql(sql);\n            statValue.getBlackList().add(sqlStatValue);\n        });\n\n        return statValue;\n    }\n\n    public Map<String, Object> getStatsMap() {\n        return getStatValue(false).toMap();\n    }\n\n    public boolean isWhiteListEnable() {\n        return whiteListEnable;\n    }\n\n    public void setWhiteListEnable(boolean whiteListEnable) {\n        this.whiteListEnable = whiteListEnable;\n    }\n\n    public boolean isBlackListEnable() {\n        return blackListEnable;\n    }\n\n    public void setBlackListEnable(boolean blackListEnable) {\n        this.blackListEnable = blackListEnable;\n    }\n\n    private static class MergedSqlResult {\n        public static final MergedSqlResult FAILED = new MergedSqlResult(null);\n\n        final String mergedSql;\n\n        MergedSqlResult(String mergedSql) {\n            this.mergedSql = mergedSql;\n        }\n\n        public static MergedSqlResult success(String mergedSql) {\n            return new MergedSqlResult(mergedSql);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallProviderCreator.java",
    "content": "package com.alibaba.druid.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\n\n/**\n * @author lizongbo\n * @since 1.2.22\n */\npublic interface WallProviderCreator {\n    /**\n     * @param dataSource mabye exists wall config\n     * @param config     maybe null\n     * @param dbType     maybe null\n     * @return\n     */\n    WallProvider createWallConfig(DataSourceProxy dataSource, WallConfig config, DbType dbType);\n\n    default int getOrder() {\n        return 0;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallProviderStatLogger.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.util.Properties;\n\npublic interface WallProviderStatLogger {\n    void log(WallProviderStatValue statValue);\n\n    void configFromProperties(Properties properties);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallProviderStatLoggerAdapter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.util.Properties;\n\npublic abstract class WallProviderStatLoggerAdapter implements WallProviderStatLogger {\n    public WallProviderStatLoggerAdapter() {\n    }\n\n    @Override\n    public void log(WallProviderStatValue statValue) {\n    }\n\n    @Override\n    public void configFromProperties(Properties properties) {\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallProviderStatLoggerImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\n\nimport java.util.Map;\nimport java.util.Properties;\n\npublic class WallProviderStatLoggerImpl extends WallProviderStatLoggerAdapter implements WallProviderStatLogger {\n    private static Log LOG = LogFactory.getLog(WallProviderStatLoggerImpl.class);\n\n    private Log logger = LOG;\n\n    @Override\n    public void configFromProperties(Properties properties) {\n        if (properties == null) {\n            return;\n        }\n\n        String property = properties.getProperty(\"druid.stat.loggerName\");\n        if (property != null && property.length() > 0) {\n            setLoggerName(property);\n        }\n    }\n\n    public void setLoggerName(String loggerName) {\n        logger = LogFactory.getLog(loggerName);\n    }\n\n    public void setLogger(Log logger) {\n        if (logger == null) {\n            throw new IllegalArgumentException(\"logger can not be null\");\n        }\n        this.logger = logger;\n    }\n\n    public boolean isLogEnable() {\n        return logger.isInfoEnabled();\n    }\n\n    public void log(String value) {\n        logger.info(value);\n    }\n\n    @Override\n    public void log(WallProviderStatValue statValue) {\n        if (!isLogEnable()) {\n            return;\n        }\n\n        Map<String, Object> map = statValue.toMap();\n        String text = JSONUtils.toJSONString(map);\n\n        log(text);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallProviderStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@MTable(name = \"druid_wall\")\npublic class WallProviderStatValue {\n    @MField(aggregate = AggregateType.None)\n    private String name;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long checkCount;\n    @MField(aggregate = AggregateType.Sum)\n    private long hardCheckCount;\n    @MField(aggregate = AggregateType.Sum)\n    private long violationCount;\n    @MField(aggregate = AggregateType.Sum)\n    private long whiteListHitCount;\n    @MField(aggregate = AggregateType.Sum)\n    private long blackListHitCount;\n    @MField(aggregate = AggregateType.Sum)\n    private long syntaxErrorCount;\n    @MField(aggregate = AggregateType.Sum)\n    private long violationEffectRowCount;\n\n    private final List<WallTableStatValue> tables = new ArrayList<WallTableStatValue>();\n    private final List<WallFunctionStatValue> functions = new ArrayList<WallFunctionStatValue>();\n\n    private final List<WallSqlStatValue> whiteList = new ArrayList<WallSqlStatValue>();\n    private final List<WallSqlStatValue> blackList = new ArrayList<WallSqlStatValue>();\n\n    public WallProviderStatValue() {\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public long getCheckCount() {\n        return checkCount;\n    }\n\n    public void setCheckCount(long checkCount) {\n        this.checkCount = checkCount;\n    }\n\n    public long getHardCheckCount() {\n        return hardCheckCount;\n    }\n\n    public void setHardCheckCount(long hardCheckCount) {\n        this.hardCheckCount = hardCheckCount;\n    }\n\n    public long getViolationCount() {\n        return violationCount;\n    }\n\n    public void setViolationCount(long violationCount) {\n        this.violationCount = violationCount;\n    }\n\n    public long getWhiteListHitCount() {\n        return whiteListHitCount;\n    }\n\n    public void setWhiteListHitCount(long whiteListHitCount) {\n        this.whiteListHitCount = whiteListHitCount;\n    }\n\n    public long getBlackListHitCount() {\n        return blackListHitCount;\n    }\n\n    public void setBlackListHitCount(long blackListHitCount) {\n        this.blackListHitCount = blackListHitCount;\n    }\n\n    public long getSyntaxErrorCount() {\n        return syntaxErrorCount;\n    }\n\n    public void setSyntaxErrorCount(long syntaxErrorCount) {\n        this.syntaxErrorCount = syntaxErrorCount;\n    }\n\n    public long getViolationEffectRowCount() {\n        return violationEffectRowCount;\n    }\n\n    public void setViolationEffectRowCount(long violationEffectRowCount) {\n        this.violationEffectRowCount = violationEffectRowCount;\n    }\n\n    public List<WallTableStatValue> getTables() {\n        return tables;\n    }\n\n    public List<WallFunctionStatValue> getFunctions() {\n        return functions;\n    }\n\n    public List<WallSqlStatValue> getWhiteList() {\n        return whiteList;\n    }\n\n    public List<WallSqlStatValue> getBlackList() {\n        return blackList;\n    }\n\n    public Map<String, Object> toMap() {\n        Map<String, Object> info = new LinkedHashMap<String, Object>();\n\n        info.put(\"checkCount\", this.getCheckCount());\n        info.put(\"hardCheckCount\", this.getHardCheckCount());\n        info.put(\"violationCount\", this.getViolationCount());\n        info.put(\"violationEffectRowCount\", this.getViolationEffectRowCount());\n        info.put(\"blackListHitCount\", this.getBlackListHitCount());\n        info.put(\"blackListSize\", this.getBlackList().size());\n        info.put(\"whiteListHitCount\", this.getWhiteListHitCount());\n        info.put(\"whiteListSize\", this.getWhiteList().size());\n        info.put(\"syntaxErrorCount\", this.getSyntaxErrorCount());\n\n        {\n            List<Map<String, Object>> tables = new ArrayList<Map<String, Object>>(this.tables.size());\n            for (WallTableStatValue tableStatValue : this.tables) {\n                Map<String, Object> statMap = tableStatValue.toMap();\n                tables.add(statMap);\n            }\n            info.put(\"tables\", tables);\n        }\n\n        {\n            List<Map<String, Object>> functions = new ArrayList<Map<String, Object>>();\n            for (WallFunctionStatValue funStatValue : this.functions) {\n                Map<String, Object> statMap = funStatValue.toMap();\n                functions.add(statMap);\n            }\n            info.put(\"functions\", functions);\n        }\n\n        {\n            List<Map<String, Object>> blackList = new ArrayList<Map<String, Object>>(this.blackList.size());\n            for (WallSqlStatValue sqlStatValue : this.blackList) {\n                blackList.add(sqlStatValue.toMap());\n            }\n            info.put(\"blackList\", blackList);\n        }\n\n        {\n            List<Map<String, Object>> whiteList = new ArrayList<Map<String, Object>>(this.whiteList.size());\n            for (WallSqlStatValue sqlStatValue : this.whiteList) {\n                whiteList.add(sqlStatValue.toMap());\n            }\n            info.put(\"whiteList\", whiteList);\n        }\n\n        return info;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallSQLException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.sql.SQLException;\n\npublic class WallSQLException extends SQLException {\n    private static final long serialVersionUID = 1L;\n\n    public WallSQLException(String reason, Throwable cause) {\n        super(reason, cause);\n    }\n\n    public WallSQLException(String reason) {\n        super(reason);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallSqlFunctionStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\npublic class WallSqlFunctionStat {\n    private int invokeCount;\n\n    public int getInvokeCount() {\n        return invokeCount;\n    }\n\n    public void incrementInvokeCount() {\n        this.invokeCount++;\n    }\n\n    public void addInvokeCount(int value) {\n        this.invokeCount += value;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallSqlStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class WallSqlStat {\n    private volatile long executeCount;\n    private volatile long executeErrorCount;\n    private volatile long fetchRowCount;\n    private volatile long updateCount;\n\n    static final AtomicLongFieldUpdater<WallSqlStat> executeCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,\n            \"executeCount\");\n    static final AtomicLongFieldUpdater<WallSqlStat> executeErrorCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,\n            \"executeErrorCount\");\n\n    static final AtomicLongFieldUpdater<WallSqlStat> fetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,\n            \"fetchRowCount\");\n    static final AtomicLongFieldUpdater<WallSqlStat> updateCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,\n            \"updateCount\");\n    private final Map<String, WallSqlTableStat> tableStats;\n\n    private final List<Violation> violations;\n\n    private final Map<String, WallSqlFunctionStat> functionStats;\n\n    private final boolean syntaxError;\n\n    private String sample;\n\n    private long sqlHash;\n\n    public WallSqlStat(Map<String, WallSqlTableStat> tableStats, Map<String, WallSqlFunctionStat> functionStats,\n                       boolean syntaxError) {\n        this(tableStats, functionStats, Collections.<Violation>emptyList(), syntaxError);\n    }\n\n    public WallSqlStat(Map<String, WallSqlTableStat> tableStats, Map<String, WallSqlFunctionStat> functionStats,\n                       List<Violation> violations, boolean syntaxError) {\n        this.violations = violations;\n        this.tableStats = tableStats;\n        this.functionStats = functionStats;\n        this.syntaxError = syntaxError;\n    }\n\n    public long getSqlHash() {\n        return sqlHash;\n    }\n\n    public void setSqlHash(long sqlHash) {\n        this.sqlHash = sqlHash;\n    }\n\n    public String getSample() {\n        return sample;\n    }\n\n    public void setSample(String sample) {\n        this.sample = sample;\n    }\n\n    public long incrementAndGetExecuteCount() {\n        return executeCountUpdater.incrementAndGet(this);\n    }\n\n    public long incrementAndGetExecuteErrorCount() {\n        return executeErrorCountUpdater.incrementAndGet(this);\n    }\n\n    public long getExecuteCount() {\n        return executeCount;\n    }\n\n    public long getExecuteErrorCount() {\n        return executeErrorCount;\n    }\n\n    public long addAndFetchRowCount(long delta) {\n        return fetchRowCountUpdater.addAndGet(this, delta);\n    }\n\n    public long getEffectRowCount() {\n        return fetchRowCount;\n    }\n\n    public long getUpdateCount() {\n        return updateCount;\n    }\n\n    public void addUpdateCount(long delta) {\n        updateCountUpdater.addAndGet(this, delta);\n    }\n\n    public Map<String, WallSqlTableStat> getTableStats() {\n        return tableStats;\n    }\n\n    public Map<String, WallSqlFunctionStat> getFunctionStats() {\n        return functionStats;\n    }\n\n    public List<Violation> getViolations() {\n        return violations;\n    }\n\n    public boolean isSyntaxError() {\n        return syntaxError;\n    }\n\n    public WallSqlStatValue getStatValue(boolean reset) {\n        final WallSqlStatValue statValue = new WallSqlStatValue();\n\n        statValue.setExecuteCount(get(this, executeCountUpdater, reset));\n        statValue.setExecuteErrorCount(get(this, executeErrorCountUpdater, reset));\n        statValue.setFetchRowCount(get(this, fetchRowCountUpdater, reset));\n        statValue.setUpdateCount(get(this, updateCountUpdater, reset));\n        statValue.setSyntaxError(this.syntaxError);\n        statValue.setSqlSample(sample);\n        if (violations.size() > 0) {\n            String violationMessage = violations.get(0).getMessage();\n            statValue.setViolationMessage(violationMessage);\n        }\n\n        return statValue;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallSqlStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n@MTable(name = \"druid_wall_sql\")\npublic class WallSqlStatValue {\n    private String sql;\n\n    @MField(groupBy = true, aggregate = AggregateType.None, hashFor = \"sql\", hashForType = \"sql\")\n    private long sqlHash;\n\n    private String sqlSample;\n\n    @MField(groupBy = true, aggregate = AggregateType.None, hashFor = \"sqlSample\", hashForType = \"sqlSample\")\n    private long sqlSampleHash;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long executeCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long executeErrorCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long fetchRowCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long updateCount;\n\n    @MField(aggregate = AggregateType.Last)\n    private boolean syntaxError;\n\n    @MField(aggregate = AggregateType.Last)\n    private String violationMessage;\n\n    public WallSqlStatValue() {\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public void setSql(String sql) {\n        this.sql = sql;\n    }\n\n    public long getSqlHash() {\n        return sqlHash;\n    }\n\n    public void setSqlHash(long sqlHash) {\n        this.sqlHash = sqlHash;\n    }\n\n    public String getSqlSample() {\n        return sqlSample;\n    }\n\n    public void setSqlSample(String sqlSample) {\n        this.sqlSample = sqlSample;\n    }\n\n    public long getExecuteCount() {\n        return executeCount;\n    }\n\n    public void setExecuteCount(long executeCount) {\n        this.executeCount = executeCount;\n    }\n\n    public long getFetchRowCount() {\n        return fetchRowCount;\n    }\n\n    public void setFetchRowCount(long fetchRowCount) {\n        this.fetchRowCount = fetchRowCount;\n    }\n\n    public long getUpdateCount() {\n        return updateCount;\n    }\n\n    public void setUpdateCount(long updateCount) {\n        this.updateCount = updateCount;\n    }\n\n    public boolean isSyntaxError() {\n        return syntaxError;\n    }\n\n    public void setSyntaxError(boolean syntaxError) {\n        this.syntaxError = syntaxError;\n    }\n\n    public String getViolationMessage() {\n        return violationMessage;\n    }\n\n    public void setViolationMessage(String violationMessage) {\n        this.violationMessage = violationMessage;\n    }\n\n    public long getExecuteErrorCount() {\n        return executeErrorCount;\n    }\n\n    public void setExecuteErrorCount(long executeErrorCount) {\n        this.executeErrorCount = executeErrorCount;\n    }\n\n    public Map<String, Object> toMap() {\n        Map<String, Object> sqlStatMap = new LinkedHashMap<String, Object>();\n        sqlStatMap.put(\"sql\", sql);\n        if (!sql.equals(sqlSample)) {\n            sqlStatMap.put(\"sample\", sqlSample);\n        }\n        sqlStatMap.put(\"executeCount\", getExecuteCount());\n\n        if (executeErrorCount > 0) {\n            sqlStatMap.put(\"executeErrorCount\", executeErrorCount);\n        }\n\n        if (fetchRowCount > 0) {\n            sqlStatMap.put(\"fetchRowCount\", fetchRowCount);\n        }\n\n        if (updateCount > 0) {\n            sqlStatMap.put(\"updateCount\", updateCount);\n        }\n\n        if (violationMessage != null) {\n            sqlStatMap.put(\"violationMessage\", violationMessage);\n        }\n\n        return sqlStatMap;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallSqlTableStat.java",
    "content": "package com.alibaba.druid.wall;\n\n/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npublic class WallSqlTableStat {\n    private int selectCount;\n    private int selectIntoCount;\n    private int insertCount;\n    private int updateCount;\n    private int deleteCount;\n    private int truncateCount;\n    private int createCount;\n    private int alterCount;\n    private int dropCount;\n    private int replaceCount;\n    private int showCount;\n\n    private String sample;\n\n    public String getSample() {\n        return sample;\n    }\n\n    public void setSample(String sample) {\n        this.sample = sample;\n    }\n\n    public int getReplaceCount() {\n        return replaceCount;\n    }\n\n    public int incrementReplaceCount() {\n        return replaceCount++;\n    }\n\n    public void addReplaceCount(int value) {\n        this.replaceCount += value;\n    }\n\n    public int getSelectCount() {\n        return selectCount;\n    }\n\n    public void incrementSelectCount() {\n        this.selectCount++;\n    }\n\n    public void addSelectCount(int value) {\n        this.selectCount += value;\n    }\n\n    public int getSelectIntoCount() {\n        return selectIntoCount;\n    }\n\n    public void incrementSelectIntoCount() {\n        this.selectIntoCount++;\n    }\n\n    public void addSelectIntoCount(int value) {\n        this.selectIntoCount += value;\n    }\n\n    public int getInsertCount() {\n        return insertCount;\n    }\n\n    public void incrementInsertCount() {\n        this.insertCount++;\n    }\n\n    public void addInsertCount(int value) {\n        this.insertCount += value;\n    }\n\n    public int getUpdateCount() {\n        return updateCount;\n    }\n\n    public void incrementUpdateCount() {\n        this.updateCount++;\n    }\n\n    public void addUpdateCount(int value) {\n        this.deleteCount += value;\n    }\n\n    public int getDeleteCount() {\n        return deleteCount;\n    }\n\n    public void incrementDeleteCount() {\n        this.deleteCount++;\n    }\n\n    public void addDeleteCount(int value) {\n        this.deleteCount += value;\n    }\n\n    public int getTruncateCount() {\n        return truncateCount;\n    }\n\n    public void incrementTruncateCount() {\n        this.truncateCount++;\n    }\n\n    public void addTruncateCount(int value) {\n        this.truncateCount += value;\n    }\n\n    public int getCreateCount() {\n        return createCount;\n    }\n\n    public void incrementCreateCount() {\n        this.createCount++;\n    }\n\n    public void addCreateCount(int value) {\n        this.createCount += value;\n    }\n\n    public int getAlterCount() {\n        return alterCount;\n    }\n\n    public void incrementAlterCount() {\n        this.alterCount++;\n    }\n\n    public void addAlterCount(int value) {\n        this.alterCount += value;\n    }\n\n    public int getDropCount() {\n        return dropCount;\n    }\n\n    public void incrementDropCount() {\n        this.dropCount++;\n    }\n\n    public void addDropCount(int value) {\n        this.dropCount += value;\n    }\n\n    public int getShowCount() {\n        return showCount;\n    }\n\n    public void incrementShowCount() {\n        this.showCount++;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallTableStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.support.json.JSONUtils;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicIntegerFieldUpdater;\nimport java.util.concurrent.atomic.AtomicLongFieldUpdater;\n\nimport static com.alibaba.druid.util.JdbcSqlStatUtils.get;\n\npublic class WallTableStat {\n    private volatile long selectCount;\n    private volatile long selectIntoCount;\n    private volatile long insertCount;\n    private volatile long updateCount;\n    private volatile long deleteCount;\n    private volatile long truncateCount;\n    private volatile long createCount;\n    private volatile long alterCount;\n    private volatile long dropCount;\n    private volatile long replaceCount;\n    private volatile long deleteDataCount;\n    private volatile long updateDataCount;\n    private volatile long insertDataCount;\n    private volatile long fetchRowCount;\n\n    static final AtomicLongFieldUpdater<WallTableStat> selectCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"selectCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> selectIntoCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"selectIntoCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> insertCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"insertCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> updateCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> deleteCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> truncateCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"truncateCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> createCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"createCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> alterCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"alterCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> dropCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"dropCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> replaceCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"replaceCount\");\n\n    static final AtomicLongFieldUpdater<WallTableStat> deleteDataCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteDataCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> insertDataCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"insertDataCount\");\n    static final AtomicLongFieldUpdater<WallTableStat> updateDataCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateDataCount\");\n\n    static final AtomicLongFieldUpdater<WallTableStat> fetchRowCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"fetchRowCount\");\n\n    private volatile long fetchRowCount_0_1;\n    private volatile long fetchRowCount_1_10;\n    private volatile long fetchRowCount_10_100;\n    private volatile int fetchRowCount_100_1000;\n    private volatile int fetchRowCount_1000_10000;\n    private volatile int fetchRowCount_10000_more;\n\n    static final AtomicLongFieldUpdater<WallTableStat> fetchRowCount_0_1_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"fetchRowCount_0_1\");\n    static final AtomicLongFieldUpdater<WallTableStat> fetchRowCount_1_10_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"fetchRowCount_1_10\");\n    static final AtomicLongFieldUpdater<WallTableStat> fetchRowCount_10_100_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"fetchRowCount_10_100\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> fetchRowCount_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"fetchRowCount_100_1000\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> fetchRowCount_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"fetchRowCount_1000_10000\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> fetchRowCount_10000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"fetchRowCount_10000_more\");\n\n    private volatile long updateDataCount_0_1;\n    private volatile long updateDataCount_1_10;\n    private volatile long updateDataCount_10_100;\n    private volatile int updateDataCount_100_1000;\n    private volatile int updateDataCount_1000_10000;\n    private volatile int updateDataCount_10000_more;\n\n    static final AtomicLongFieldUpdater<WallTableStat> updateDataCount_0_1_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateDataCount_0_1\");\n    static final AtomicLongFieldUpdater<WallTableStat> updateDataCount_1_10_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateDataCount_1_10\");\n    static final AtomicLongFieldUpdater<WallTableStat> updateDataCount_10_100_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateDataCount_10_100\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> updateDataCount_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateDataCount_100_1000\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> updateDataCount_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateDataCount_1000_10000\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> updateDataCount_10000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"updateDataCount_10000_more\");\n\n    private volatile long deleteDataCount_0_1;\n    private volatile long deleteDataCount_1_10;\n    private volatile long deleteDataCount_10_100;\n    private volatile int deleteDataCount_100_1000;\n    private volatile int deleteDataCount_1000_10000;\n    private volatile int deleteDataCount_10000_more;\n\n    static final AtomicLongFieldUpdater<WallTableStat> deleteDataCount_0_1_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteDataCount_0_1\");\n    static final AtomicLongFieldUpdater<WallTableStat> deleteDataCount_1_10_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteDataCount_1_10\");\n    static final AtomicLongFieldUpdater<WallTableStat> deleteDataCount_10_100_Updater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteDataCount_10_100\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> deleteDataCount_100_1000_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteDataCount_100_1000\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> deleteDataCount_1000_10000_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteDataCount_1000_10000\");\n    static final AtomicIntegerFieldUpdater<WallTableStat> deleteDataCount_10000_more_Updater = AtomicIntegerFieldUpdater.newUpdater(WallTableStat.class,\n            \"deleteDataCount_10000_more\");\n\n    public WallTableStat() {\n    }\n\n    public long getSelectCount() {\n        return selectCount;\n    }\n\n    public long getSelectIntoCount() {\n        return selectIntoCount;\n    }\n\n    public long getInsertCount() {\n        return insertCount;\n    }\n\n    public long getUpdateCount() {\n        return updateCount;\n    }\n\n    public long getDeleteCount() {\n        return deleteCount;\n    }\n\n    public long getTruncateCount() {\n        return truncateCount;\n    }\n\n    public long getCreateCount() {\n        return createCount;\n    }\n\n    public long getAlterCount() {\n        return alterCount;\n    }\n\n    public long getDropCount() {\n        return dropCount;\n    }\n\n    public long getReplaceCount() {\n        return replaceCount;\n    }\n\n    public long getDeleteDataCount() {\n        return this.deleteDataCount;\n    }\n\n    public long[] getDeleteDataCountHistogramValues() {\n        return new long[]{\n                //\n                deleteDataCount_0_1, //\n                deleteDataCount_1_10, //\n                deleteDataCount_10_100, //\n                deleteDataCount_100_1000, //\n                deleteDataCount_1000_10000, //\n                deleteDataCount_10000_more //\n        };\n    }\n\n    public void addDeleteDataCount(long delta) {\n        deleteDataCountUpdater.addAndGet(this, delta);\n\n        if (delta < 1) {\n            deleteDataCount_0_1_Updater.incrementAndGet(this);\n        } else if (delta < 10) {\n            deleteDataCount_1_10_Updater.incrementAndGet(this);\n        } else if (delta < 100) {\n            deleteDataCount_10_100_Updater.incrementAndGet(this);\n        } else if (delta < 1000) {\n            deleteDataCount_100_1000_Updater.incrementAndGet(this);\n        } else if (delta < 10000) {\n            deleteDataCount_1000_10000_Updater.incrementAndGet(this);\n        } else {\n            deleteDataCount_10000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public long getUpdateDataCount() {\n        return this.updateDataCount;\n    }\n\n    public long[] getUpdateDataCountHistogramValues() {\n        return new long[]{\n                //\n                updateDataCount_0_1, //\n                updateDataCount_1_10, //\n                updateDataCount_10_100, //\n                updateDataCount_100_1000, //\n                updateDataCount_1000_10000, //\n                updateDataCount_10000_more //\n        };\n    }\n\n    public long getInsertDataCount() {\n        return this.insertDataCount;\n    }\n\n    public void addInsertDataCount(long delta) {\n        insertDataCountUpdater.addAndGet(this, delta);\n    }\n\n    public void addUpdateDataCount(long delta) {\n        updateDataCountUpdater.addAndGet(this, delta);\n\n        if (delta < 1) {\n            updateDataCount_0_1_Updater.incrementAndGet(this);\n        } else if (delta < 10) {\n            updateDataCount_1_10_Updater.incrementAndGet(this);\n        } else if (delta < 100) {\n            updateDataCount_10_100_Updater.incrementAndGet(this);\n        } else if (delta < 1000) {\n            updateDataCount_100_1000_Updater.incrementAndGet(this);\n        } else if (delta < 10000) {\n            updateDataCount_1000_10000_Updater.incrementAndGet(this);\n        } else {\n            updateDataCount_10000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public long getFetchRowCount() {\n        return fetchRowCount;\n    }\n\n    public long[] getFetchRowCountHistogramValues() {\n        return new long[]{\n                //\n                fetchRowCount_0_1, //\n                fetchRowCount_1_10, //\n                fetchRowCount_10_100, //\n                fetchRowCount_100_1000, //\n                fetchRowCount_1000_10000, //\n                fetchRowCount_10000_more //\n        };\n    }\n\n    public void addFetchRowCount(long delta) {\n        fetchRowCountUpdater.addAndGet(this, delta);\n\n        if (delta < 1) {\n            fetchRowCount_0_1_Updater.incrementAndGet(this);\n        } else if (delta < 10) {\n            fetchRowCount_1_10_Updater.incrementAndGet(this);\n        } else if (delta < 100) {\n            fetchRowCount_10_100_Updater.incrementAndGet(this);\n        } else if (delta < 1000) {\n            fetchRowCount_100_1000_Updater.incrementAndGet(this);\n        } else if (delta < 10000) {\n            fetchRowCount_1000_10000_Updater.incrementAndGet(this);\n        } else {\n            fetchRowCount_10000_more_Updater.incrementAndGet(this);\n        }\n    }\n\n    public void addSqlTableStat(WallSqlTableStat stat) {\n        {\n            long val = stat.getSelectCount();\n            if (val > 0) {\n                selectCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getSelectIntoCount();\n            if (val > 0) {\n                selectIntoCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getInsertCount();\n            if (val > 0) {\n                insertCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getUpdateCount();\n            if (val > 0) {\n                updateCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getDeleteCount();\n            if (val > 0) {\n                deleteCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getAlterCount();\n            if (val > 0) {\n                alterCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getTruncateCount();\n            if (val > 0) {\n                truncateCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getCreateCount();\n            if (val > 0) {\n                createCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getDropCount();\n            if (val > 0) {\n                dropCountUpdater.addAndGet(this, val);\n            }\n        }\n        {\n            long val = stat.getReplaceCount();\n            if (val > 0) {\n                replaceCountUpdater.addAndGet(this, val);\n            }\n        }\n    }\n\n    public String toString() {\n        Map<String, Object> map = toMap();\n\n        return JSONUtils.toJSONString(map);\n    }\n\n    public Map<String, Object> toMap() {\n        Map<String, Object> map = new LinkedHashMap<String, Object>();\n        return toMap(map);\n    }\n\n    public WallTableStatValue getStatValue(boolean reset) {\n        WallTableStatValue statValue = new WallTableStatValue();\n\n        statValue.setSelectCount(get(this, selectCountUpdater, reset));\n        statValue.setDeleteCount(get(this, deleteCountUpdater, reset));\n        statValue.setInsertCount(get(this, insertCountUpdater, reset));\n        statValue.setUpdateCount(get(this, updateCountUpdater, reset));\n        statValue.setAlterCount(get(this, alterCountUpdater, reset));\n        statValue.setDropCount(get(this, dropCountUpdater, reset));\n        statValue.setCreateCount(get(this, createCountUpdater, reset));\n        statValue.setTruncateCount(get(this, truncateCountUpdater, reset));\n        statValue.setReplaceCount(get(this, replaceCountUpdater, reset));\n        statValue.setDeleteDataCount(get(this, deleteDataCountUpdater, reset));\n        statValue.setFetchRowCount(get(this, fetchRowCountUpdater, reset));\n        statValue.setUpdateDataCount(get(this, updateDataCountUpdater, reset));\n\n        statValue.fetchRowCount_0_1 = get(this, fetchRowCount_0_1_Updater, reset);\n        statValue.fetchRowCount_1_10 = get(this, fetchRowCount_1_10_Updater, reset);\n        statValue.fetchRowCount_10_100 = get(this, fetchRowCount_10_100_Updater, reset);\n        statValue.fetchRowCount_100_1000 = get(this, fetchRowCount_100_1000_Updater, reset);\n        statValue.fetchRowCount_1000_10000 = get(this, fetchRowCount_1000_10000_Updater, reset);\n        statValue.fetchRowCount_10000_more = get(this, fetchRowCount_10000_more_Updater, reset);\n\n        statValue.updateDataCount_0_1 = get(this, updateDataCount_0_1_Updater, reset);\n        statValue.updateDataCount_1_10 = get(this, updateDataCount_1_10_Updater, reset);\n        statValue.updateDataCount_10_100 = get(this, updateDataCount_10_100_Updater, reset);\n        statValue.updateDataCount_100_1000 = get(this, updateDataCount_100_1000_Updater, reset);\n        statValue.updateDataCount_1000_10000 = get(this, updateDataCount_1000_10000_Updater, reset);\n        statValue.updateDataCount_10000_more = get(this, updateDataCount_10000_more_Updater, reset);\n\n        statValue.deleteDataCount_0_1 = get(this, deleteDataCount_0_1_Updater, reset);\n        statValue.deleteDataCount_1_10 = get(this, deleteDataCount_1_10_Updater, reset);\n        statValue.deleteDataCount_10_100 = get(this, deleteDataCount_10_100_Updater, reset);\n        statValue.deleteDataCount_100_1000 = get(this, deleteDataCount_100_1000_Updater, reset);\n        statValue.deleteDataCount_1000_10000 = get(this, deleteDataCount_1000_10000_Updater, reset);\n        statValue.deleteDataCount_10000_more = get(this, deleteDataCount_10000_more_Updater, reset);\n\n        return statValue;\n    }\n\n    public Map<String, Object> toMap(Map<String, Object> map) {\n        return getStatValue(false).toMap(map);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallTableStatValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.support.monitor.annotation.AggregateType;\nimport com.alibaba.druid.support.monitor.annotation.MField;\nimport com.alibaba.druid.support.monitor.annotation.MTable;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n@MTable(name = \"druid_wall_table\")\npublic class WallTableStatValue {\n    @MField(aggregate = AggregateType.None)\n    private String name;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long selectCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long selectIntoCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long insertCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long updateCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long deleteCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long truncateCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long createCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long alterCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long dropCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long replaceCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long deleteDataCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long updateDataCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long insertDataCount;\n\n    @MField(aggregate = AggregateType.Sum)\n    private long fetchRowCount;\n\n    @MField(name = \"f1\", aggregate = AggregateType.Sum)\n    protected long fetchRowCount_0_1;\n\n    @MField(name = \"f10\", aggregate = AggregateType.Sum)\n    protected long fetchRowCount_1_10;\n\n    @MField(name = \"f100\", aggregate = AggregateType.Sum)\n    protected long fetchRowCount_10_100;\n\n    @MField(name = \"f1000\", aggregate = AggregateType.Sum)\n    protected int fetchRowCount_100_1000;\n\n    @MField(name = \"f10000\", aggregate = AggregateType.Sum)\n    protected int fetchRowCount_1000_10000;\n\n    @MField(name = \"fmore\", aggregate = AggregateType.Sum)\n    protected int fetchRowCount_10000_more;\n\n    @MField(name = \"u1\", aggregate = AggregateType.Sum)\n    protected long updateDataCount_0_1;\n\n    @MField(name = \"u10\", aggregate = AggregateType.Sum)\n    protected long updateDataCount_1_10;\n\n    @MField(name = \"u100\", aggregate = AggregateType.Sum)\n    protected long updateDataCount_10_100;\n\n    @MField(name = \"u1000\", aggregate = AggregateType.Sum)\n    protected int updateDataCount_100_1000;\n\n    @MField(name = \"u10000\", aggregate = AggregateType.Sum)\n    protected int updateDataCount_1000_10000;\n\n    @MField(name = \"umore\", aggregate = AggregateType.Sum)\n    protected int updateDataCount_10000_more;\n\n    @MField(name = \"del_1\", aggregate = AggregateType.Sum)\n    protected long deleteDataCount_0_1;\n\n    @MField(name = \"del_10\", aggregate = AggregateType.Sum)\n    protected long deleteDataCount_1_10;\n\n    @MField(name = \"del_100\", aggregate = AggregateType.Sum)\n    protected long deleteDataCount_10_100;\n\n    @MField(name = \"del_1000\", aggregate = AggregateType.Sum)\n    protected int deleteDataCount_100_1000;\n\n    @MField(name = \"del_10000\", aggregate = AggregateType.Sum)\n    protected int deleteDataCount_1000_10000;\n\n    @MField(name = \"del_more\", aggregate = AggregateType.Sum)\n    protected int deleteDataCount_10000_more;\n\n    public long[] getDeleteDataHistogram() {\n        return new long[]{deleteDataCount_0_1, //\n                deleteDataCount_1_10, //\n                deleteDataCount_10_100, //\n                deleteDataCount_100_1000, //\n                deleteDataCount_1000_10000, //\n                deleteDataCount_10000_more, //\n        };\n    }\n\n    public WallTableStatValue() {\n        this(null);\n    }\n\n    public WallTableStatValue(String name) {\n        this.name = name;\n    }\n\n    public long[] getFetchRowHistogram() {\n        return new long[]{fetchRowCount_0_1, //\n                fetchRowCount_1_10, //\n                fetchRowCount_10_100, //\n                fetchRowCount_100_1000, //\n                fetchRowCount_1000_10000, //\n                fetchRowCount_10000_more, //\n        };\n    }\n\n    public long getTotalExecuteCount() {\n        return selectCount //\n                + selectIntoCount //\n                + insertCount //\n                + updateCount //\n                + deleteCount //\n                + truncateCount //\n                + createCount //\n                + dropCount //\n                + replaceCount;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public long getSelectCount() {\n        return selectCount;\n    }\n\n    public void setSelectCount(long selectCount) {\n        this.selectCount = selectCount;\n    }\n\n    public long getSelectIntoCount() {\n        return selectIntoCount;\n    }\n\n    public void setSelectIntoCount(long selectIntoCount) {\n        this.selectIntoCount = selectIntoCount;\n    }\n\n    public long getInsertCount() {\n        return insertCount;\n    }\n\n    public void setInsertCount(long insertCount) {\n        this.insertCount = insertCount;\n    }\n\n    public long getUpdateCount() {\n        return updateCount;\n    }\n\n    public void setUpdateCount(long updateCount) {\n        this.updateCount = updateCount;\n    }\n\n    public long getDeleteCount() {\n        return deleteCount;\n    }\n\n    public void setDeleteCount(long deleteCount) {\n        this.deleteCount = deleteCount;\n    }\n\n    public long getTruncateCount() {\n        return truncateCount;\n    }\n\n    public void setTruncateCount(long truncateCount) {\n        this.truncateCount = truncateCount;\n    }\n\n    public long getCreateCount() {\n        return createCount;\n    }\n\n    public void setCreateCount(long createCount) {\n        this.createCount = createCount;\n    }\n\n    public long getAlterCount() {\n        return alterCount;\n    }\n\n    public void setAlterCount(long alterCount) {\n        this.alterCount = alterCount;\n    }\n\n    public long getDropCount() {\n        return dropCount;\n    }\n\n    public void setDropCount(long dropCount) {\n        this.dropCount = dropCount;\n    }\n\n    public long getReplaceCount() {\n        return replaceCount;\n    }\n\n    public void setReplaceCount(long replaceCount) {\n        this.replaceCount = replaceCount;\n    }\n\n    public long getDeleteDataCount() {\n        return deleteDataCount;\n    }\n\n    public void setDeleteDataCount(long deleteDataCount) {\n        this.deleteDataCount = deleteDataCount;\n    }\n\n    public long getUpdateDataCount() {\n        return updateDataCount;\n    }\n\n    public long[] getUpdateDataHistogram() {\n        return new long[]{updateDataCount_0_1, //\n                updateDataCount_1_10, //\n                updateDataCount_10_100, //\n                updateDataCount_100_1000, //\n                updateDataCount_1000_10000, //\n                updateDataCount_10000_more, //\n        };\n    }\n\n    public void setUpdateDataCount(long updateDataCount) {\n        this.updateDataCount = updateDataCount;\n    }\n\n    public long getInsertDataCount() {\n        return insertDataCount;\n    }\n\n    public void setInsertDataCount(long insertDataCount) {\n        this.insertDataCount = insertDataCount;\n    }\n\n    public long getFetchRowCount() {\n        return fetchRowCount;\n    }\n\n    public void setFetchRowCount(long fetchRowCount) {\n        this.fetchRowCount = fetchRowCount;\n    }\n\n    public Map<String, Object> toMap() {\n        Map<String, Object> map = new LinkedHashMap<String, Object>();\n        toMap(map);\n        return map;\n    }\n\n    public Map<String, Object> toMap(Map<String, Object> map) {\n        map.put(\"name\", name);\n\n        if (selectCount > 0) {\n            map.put(\"selectCount\", selectCount);\n        }\n        if (deleteCount > 0) {\n            map.put(\"deleteCount\", deleteCount);\n        }\n        if (insertCount > 0) {\n            map.put(\"insertCount\", insertCount);\n        }\n        if (updateCount > 0) {\n            map.put(\"updateCount\", updateCount);\n        }\n        if (alterCount > 0) {\n            map.put(\"alterCount\", alterCount);\n        }\n        if (dropCount > 0) {\n            map.put(\"dropCount\", dropCount);\n        }\n        if (createCount > 0) {\n            map.put(\"createCount\", createCount);\n        }\n        if (truncateCount > 0) {\n            map.put(\"truncateCount\", truncateCount);\n        }\n        if (replaceCount > 0) {\n            map.put(\"replaceCount\", replaceCount);\n        }\n        if (deleteDataCount > 0) {\n            map.put(\"deleteDataCount\", deleteDataCount);\n            map.put(\"deleteDataCountHistogram\", getDeleteDataHistogram());\n        }\n        if (fetchRowCount > 0) {\n            map.put(\"fetchRowCount\", fetchRowCount);\n            map.put(\"fetchRowCountHistogram\", getFetchRowHistogram());\n        }\n        if (updateDataCount > 0) {\n            map.put(\"updateDataCount\", updateDataCount);\n            map.put(\"updateDataCountHistogram\", getUpdateDataHistogram());\n        }\n        return map;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallUpdateCheckHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport java.util.List;\n\n/**\n * Created by wenshao on 13/08/2017.\n */\npublic interface WallUpdateCheckHandler {\n    boolean check(String table, String column, Object setValue, List<Object> filterValues);\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallUpdateCheckItem.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.sql.ast.SQLExpr;\n\nimport java.util.List;\n\n/**\n * Created by wenshao on 14/08/2017.\n */\npublic class WallUpdateCheckItem {\n    public final String tableName;\n    public final String columnName;\n    public final SQLExpr value;\n    public final List<SQLExpr> filterValues;\n\n    public WallUpdateCheckItem(String tableName, String columnName, SQLExpr value, List<SQLExpr> filterValues) {\n        this.tableName = tableName;\n        this.columnName = columnName;\n        this.value = value;\n        this.filterValues = filterValues;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.wall.spi.*;\n\npublic class WallUtils {\n    public static boolean isValidateDB2(String sql) {\n        DB2WallProvider provider = new DB2WallProvider();\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidateDB2(String sql, WallConfig config) {\n        DB2WallProvider provider = new DB2WallProvider(config);\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidatePostgres(String sql) {\n        PGWallProvider provider = new PGWallProvider();\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidatePostgres(String sql, WallConfig config) {\n        PGWallProvider provider = new PGWallProvider(config);\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidateMySql(String sql) {\n        MySqlWallProvider provider = new MySqlWallProvider();\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidateMySql(String sql, WallConfig config) {\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidateOracle(String sql) {\n        OracleWallProvider provider = new OracleWallProvider();\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidateOracle(String sql, WallConfig config) {\n        OracleWallProvider provider = new OracleWallProvider(config);\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidateSqlServer(String sql) {\n        SQLServerWallProvider provider = new SQLServerWallProvider();\n        return provider.checkValid(sql);\n    }\n\n    public static boolean isValidateSqlServer(String sql, WallConfig config) {\n        SQLServerWallProvider provider = new SQLServerWallProvider(config);\n        return provider.checkValid(sql);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/WallVisitor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\nimport com.alibaba.druid.wall.violation.ErrorCode;\nimport com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;\n\nimport java.util.List;\n\npublic interface WallVisitor extends SQLASTVisitor {\n    WallConfig getConfig();\n\n    WallProvider getProvider();\n\n    List<Violation> getViolations();\n\n    void addViolation(Violation violation);\n\n    boolean isDenyTable(String name);\n\n    default String toSQL(SQLObject obj) {\n        return SQLUtils.toSQLString(obj, getDbType());\n    }\n\n    boolean isSqlModified();\n\n    void setSqlModified(boolean sqlModified);\n\n    DbType getDbType();\n\n    boolean isSqlEndOfComment();\n\n    void setSqlEndOfComment(boolean sqlEndOfComment);\n\n    void addWallUpdateCheckItem(WallUpdateCheckItem item);\n\n    List<WallUpdateCheckItem> getUpdateCheckItems();\n\n    default boolean visit(SQLPropertyExpr x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLInListExpr x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLBinaryOpExpr x) {\n        return WallVisitorUtils.check(this, x);\n    }\n\n    default boolean visit(SQLMethodInvokeExpr x) {\n        WallVisitorUtils.checkFunction(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLSelectQueryBlock x) {\n        WallVisitorUtils.checkSelect(this, x);\n\n        return true;\n    }\n\n    default boolean visit(SQLSelectGroupByClause x) {\n        WallVisitorUtils.checkHaving(this, x.getHaving());\n        return true;\n    }\n\n    @Override\n    default boolean visit(SQLSelectItem x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLJoinTableSource x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLCreateTableStatement x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLAlterTableStatement x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLDropTableStatement x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLUpdateStatement x) {\n        WallVisitorUtils.initWallTopStatementContext();\n        WallVisitorUtils.checkUpdate(this, x);\n\n        return true;\n    }\n\n    default void endVisit(SQLUpdateStatement x) {\n        WallVisitorUtils.clearWallTopStatementContext();\n    }\n\n    default boolean visit(SQLInsertStatement x) {\n        WallVisitorUtils.initWallTopStatementContext();\n        WallVisitorUtils.checkInsert(this, x);\n\n        return true;\n    }\n\n    default void endVisit(SQLInsertStatement x) {\n        WallVisitorUtils.clearWallTopStatementContext();\n    }\n\n    default boolean visit(SQLDeleteStatement x) {\n        WallVisitorUtils.checkDelete(this, x);\n        return true;\n    }\n\n    default void preVisit(SQLObject x) {\n        WallVisitorUtils.preVisitCheck(this, x);\n    }\n\n    @Override\n    default boolean visit(SQLSelectStatement x) {\n        WallConfig config = getConfig();\n        if (!config.isSelectAllow()) {\n            this.getViolations()\n                    .add(new IllegalSQLObjectViolation(ErrorCode.SELECT_NOT_ALLOW, \"select not allow\",\n                            this.toSQL(x)));\n            return false;\n        }\n\n        WallVisitorUtils.initWallTopStatementContext();\n\n        int selectLimit = config.getSelectLimit();\n        if (selectLimit >= 0) {\n            SQLSelect select = x.getSelect();\n            PagerUtils.limit(select, getDbType(), 0, selectLimit, true);\n            setSqlModified(true);\n        }\n        return true;\n    }\n\n    default void endVisit(SQLSelectStatement x) {\n        WallVisitorUtils.clearWallTopStatementContext();\n    }\n\n    default boolean visit(SQLExprTableSource x) {\n        WallVisitorUtils.check(this, x);\n\n        if (x.getExpr() instanceof SQLName) {\n            return false;\n        }\n\n        return true;\n    }\n\n    default boolean visit(SQLIdentifierExpr x) {\n        WallConfig config = getConfig();\n        String name = x.getName();\n        name = WallVisitorUtils.form(name);\n        if (config.isVariantCheck() && config.getDenyVariants().contains(name)) {\n            getViolations().add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY, \"variable not allow : \" + name,\n                    toSQL(x)));\n        }\n        return true;\n    }\n\n    default boolean visit(SQLUnionQuery x) {\n        return WallVisitorUtils.checkUnion(this, x);\n    }\n\n    default void endVisit(SQLDeleteStatement x) {\n        WallVisitorUtils.clearWallTopStatementContext();\n    }\n\n    default boolean visit(SQLLimit x) {\n        if (x.getRowCount() instanceof SQLNumericLiteralExpr) {\n            WallContext context = WallContext.current();\n\n            int rowCount = ((SQLNumericLiteralExpr) x.getRowCount()).getNumber().intValue();\n            if (rowCount == 0) {\n                if (context != null) {\n                    context.incrementWarnings();\n                }\n\n                if (!getProvider().getConfig().isLimitZeroAllow()) {\n                    this.getViolations().add(new IllegalSQLObjectViolation(ErrorCode.LIMIT_ZERO, \"limit row 0\",\n                            this.toSQL(x)));\n                }\n            }\n        }\n        return true;\n    }\n\n    default boolean visit(SQLCreateTriggerStatement x) {\n        return false;\n    }\n\n    default boolean visit(SQLSetStatement x) {\n        return false;\n    }\n\n    default boolean visit(SQLCallStatement x) {\n        return false;\n    }\n\n    default boolean visit(SQLCommentHint x) {\n        if (x instanceof TDDLHint) {\n            return false;\n        }\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    default boolean visit(SQLShowCreateTableStatement x) {\n        String tableName = (x.getName()).getSimpleName();\n        WallContext context = WallContext.current();\n        if (context != null) {\n            WallSqlTableStat tableStat = context.getTableStat(tableName);\n            if (tableStat != null) {\n                tableStat.incrementShowCount();\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/CKWallProvider.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.clickhouse.parser.CKStatementParser;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class CKWallProvider extends WallProvider {\n    public static final String DEFAULT_CONFIG_DIR = \"META-INF/druid/wall/clickhouse\";\n\n    public CKWallProvider() {\n        this(new WallConfig(DEFAULT_CONFIG_DIR));\n    }\n\n    public CKWallProvider(WallConfig config) {\n        super(config, DbType.clickhouse);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return new CKStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return new ClickhouseWallVisitor(this);\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return new CKExportParameterVisitor();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/ClickhouseWallVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class ClickhouseWallVisitor extends WallVisitorBase implements WallVisitor, PGASTVisitor {\n    public ClickhouseWallVisitor(WallProvider provider) {\n        super(provider);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.clickhouse;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/DB2WallProvider.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class DB2WallProvider extends WallProvider {\n    public static final String DEFAULT_CONFIG_DIR = \"META-INF/druid/wall/db2\";\n\n    public DB2WallProvider() {\n        this(new WallConfig(DEFAULT_CONFIG_DIR));\n    }\n\n    public DB2WallProvider(WallConfig config) {\n        super(config, DbType.db2);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return new DB2StatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return new DB2WallVisitor(this);\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return new DB2ExportParameterVisitor();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/DB2WallVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class DB2WallVisitor extends WallVisitorBase implements WallVisitor, DB2ASTVisitor {\n    public DB2WallVisitor(WallProvider provider) {\n        super(provider);\n    }\n\n    @Override\n    public boolean isDenyTable(String name) {\n        if (!config.isTableCheck()) {\n            return false;\n        }\n\n        name = WallVisitorUtils.form(name);\n        if (name.startsWith(\"v$\") || name.startsWith(\"v_$\")) {\n            return true;\n        }\n        return !this.provider.checkDenyTable(name);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.db2;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/MySqlWallProvider.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class MySqlWallProvider extends WallProvider {\n    public static final String DEFAULT_CONFIG_DIR = \"META-INF/druid/wall/mysql\";\n\n    public MySqlWallProvider() {\n        this(new WallConfig(DEFAULT_CONFIG_DIR));\n    }\n\n    public MySqlWallProvider(WallConfig config) {\n        super(config, DbType.mysql);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return new MySqlStatementParser(\n                sql,\n                SQLParserFeature.EnableSQLBinaryOpExprGroup,\n                SQLParserFeature.StrictForWall\n        );\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return new MySqlWallVisitor(this);\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return new MySqlExportParameterVisitor();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils.WallTopStatementContext;\nimport com.alibaba.druid.wall.violation.ErrorCode;\nimport com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;\n\npublic class MySqlWallVisitor extends WallVisitorBase implements WallVisitor, MySqlASTVisitor {\n    public MySqlWallVisitor(WallProvider provider) {\n        super(provider);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.mysql;\n    }\n\n    @Override\n    public boolean visit(MySqlSelectQueryBlock x) {\n        WallVisitorUtils.checkSelect(this, x);\n        return true;\n    }\n\n    @Override\n    public boolean visit(MySqlDeleteStatement x) {\n        WallVisitorUtils.checkReadOnly(this, x.getFrom());\n        return visit((SQLDeleteStatement) x);\n    }\n\n    @Override\n    public boolean visit(MySqlUpdateStatement x) {\n        return visit((SQLUpdateStatement) x);\n    }\n\n    @Override\n    public boolean visit(MySqlInsertStatement x) {\n        return visit((SQLInsertStatement) x);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return true;\n    }\n\n    public boolean visit(SQLPropertyExpr x) {\n        if (x.getOwner() instanceof SQLVariantRefExpr) {\n            SQLVariantRefExpr varExpr = (SQLVariantRefExpr) x.getOwner();\n            SQLObject parent = x.getParent();\n            String varName = varExpr.getName();\n            if (varName.equalsIgnoreCase(\"@@session\") || varName.equalsIgnoreCase(\"@@global\")) {\n                if (!(parent instanceof SQLSelectItem) && !(parent instanceof SQLAssignItem)) {\n                    violations.add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY,\n                            \"variable in condition not allow\", toSQL(x)));\n                    return false;\n                }\n\n                if (!checkVar(x.getParent(), x.getName())) {\n                    boolean isTop = WallVisitorUtils.isTopNoneFromSelect(this, x);\n                    if (!isTop) {\n                        boolean allow = true;\n                        if (isDeny(varName)\n                                && (WallVisitorUtils.isWhereOrHaving(x) || WallVisitorUtils.checkSqlExpr(varExpr))) {\n                            allow = false;\n                        }\n\n                        if (!allow) {\n                            violations.add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY,\n                                    \"variable not allow : \" + x.getName(),\n                                    toSQL(x)));\n                        }\n                    }\n                }\n                return false;\n            }\n        }\n\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n\n    public boolean checkVar(SQLObject parent, String varName) {\n        if (varName == null) {\n            return false;\n        }\n\n        if (varName.equals(\"?\")) {\n            return true;\n        }\n\n        if (!config.isVariantCheck()) {\n            return true;\n        }\n\n        if (varName.startsWith(\"@@\")) {\n            if (!(parent instanceof SQLSelectItem) && !(parent instanceof SQLAssignItem)) {\n                return false;\n            }\n\n            varName = varName.substring(2);\n        }\n\n        if (config.getPermitVariants().contains(varName)) {\n            return true;\n        }\n\n        return false;\n    }\n\n    public boolean isDeny(String varName) {\n        if (varName.startsWith(\"@@\")) {\n            varName = varName.substring(2);\n        }\n\n        varName = varName.toLowerCase();\n        return config.getDenyVariants().contains(varName);\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        String varName = x.getName();\n        if (varName == null) {\n            return false;\n        }\n\n        if (varName.startsWith(\"@@\") && !checkVar(x.getParent(), x.getName())) {\n            final WallTopStatementContext topStatementContext = WallVisitorUtils.getWallTopStatementContext();\n            if (topStatementContext != null\n                    && (topStatementContext.fromSysSchema() || topStatementContext.fromSysTable())) {\n                return false;\n            }\n\n            boolean isTop = WallVisitorUtils.isTopNoneFromSelect(this, x);\n            if (!isTop) {\n                boolean allow = true;\n                if (isDeny(varName) && (WallVisitorUtils.isWhereOrHaving(x) || WallVisitorUtils.checkSqlExpr(x))) {\n                    allow = false;\n                }\n\n                if (!allow) {\n                    violations.add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY, \"variable not allow : \"\n                            + x.getName(), toSQL(x)));\n                }\n            }\n        }\n\n        return false;\n    }\n\n    @Override\n    public boolean visit(MySqlOutFileExpr x) {\n        if (!config.isSelectIntoOutfileAllow() && !WallVisitorUtils.isTopSelectOutFile(x)) {\n            violations.add(new IllegalSQLObjectViolation(ErrorCode.INTO_OUTFILE, \"into out file not allow\", toSQL(x)));\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean isDenyTable(String name) {\n        if (!config.isTableCheck()) {\n            return false;\n        }\n\n        return !this.provider.checkDenyTable(name);\n    }\n\n    @Override\n    public boolean visit(MySqlCreateTableStatement x) {\n        WallVisitorUtils.check(this, x);\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/OracleWallProvider.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class OracleWallProvider extends WallProvider {\n    public static final String DEFAULT_CONFIG_DIR = \"META-INF/druid/wall/oracle\";\n\n    public OracleWallProvider() {\n        this(new WallConfig(DEFAULT_CONFIG_DIR));\n    }\n\n    public OracleWallProvider(WallConfig config) {\n        super(config, DbType.oracle);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return new OracleStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return new OracleWallVisitor(this);\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return new OracleExportParameterVisitor();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.InsertIntoClause;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\nimport com.alibaba.druid.wall.violation.ErrorCode;\nimport com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;\n\npublic class OracleWallVisitor extends WallVisitorBase implements WallVisitor, OracleASTVisitor {\n    public OracleWallVisitor(WallProvider provider) {\n        super(provider);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.oracle;\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        String name = x.getName();\n        name = WallVisitorUtils.form(name);\n        if (config.isVariantCheck() && config.getDenyVariants().contains(name)) {\n            getViolations().add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY, \"variable not allow : \" + name,\n                    toSQL(x)));\n        }\n        return true;\n    }\n\n    public boolean visit(OracleSelectTableReference x) {\n        return WallVisitorUtils.check(this, x);\n    }\n\n    @Override\n    public boolean isDenyTable(String name) {\n        if (!config.isTableCheck()) {\n            return false;\n        }\n\n        name = WallVisitorUtils.form(name);\n        if (name.startsWith(\"v$\") || name.startsWith(\"v_$\")) {\n            return true;\n        }\n        return !this.provider.checkDenyTable(name);\n    }\n\n    public boolean visit(InsertIntoClause x) {\n        WallVisitorUtils.checkInsert(this, x);\n\n        return true;\n    }\n\n    public boolean visit(OracleMultiInsertStatement x) {\n        if (!config.isInsertAllow()) {\n            this.getViolations().add(new IllegalSQLObjectViolation(ErrorCode.INSERT_NOT_ALLOW, \"insert not allow\",\n                    this.toSQL(x)));\n            return false;\n        }\n        WallVisitorUtils.initWallTopStatementContext();\n\n        return true;\n    }\n\n    public void endVisit(OracleMultiInsertStatement x) {\n        WallVisitorUtils.clearWallTopStatementContext();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/PGWallProvider.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class PGWallProvider extends WallProvider {\n    public static final String DEFAULT_CONFIG_DIR = \"META-INF/druid/wall/postgres\";\n\n    public PGWallProvider() {\n        this(new WallConfig(DEFAULT_CONFIG_DIR));\n    }\n\n    public PGWallProvider(WallConfig config) {\n        super(config, DbType.postgresql);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return new PGSQLStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return new com.alibaba.druid.wall.spi.PGWallVisitor(this);\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return new PGExportParameterVisitor();\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class PGWallVisitor extends WallVisitorBase implements WallVisitor, PGASTVisitor {\n    public PGWallVisitor(WallProvider provider) {\n        super(provider);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.postgresql;\n    }\n\n    @Override\n    public boolean isDenyTable(String name) {\n        if (!config.isTableCheck()) {\n            return false;\n        }\n\n        name = WallVisitorUtils.form(name);\n        if (name.startsWith(\"v$\") || name.startsWith(\"v_$\")) {\n            return true;\n        }\n        return !this.provider.checkDenyTable(name);\n    }\n\n    @Override\n    public boolean visit(PGSelectQueryBlock x) {\n        WallVisitorUtils.checkSelect(this, x);\n        return true;\n    }\n\n    @Override\n    public boolean visit(PGDeleteStatement x) {\n        WallVisitorUtils.checkReadOnly(this, x.getFrom());\n        return visit((SQLDeleteStatement) x);\n    }\n\n    @Override\n    public boolean visit(PGUpdateStatement x) {\n        return visit((SQLUpdateStatement) x);\n    }\n\n    @Override\n    public boolean visit(PGInsertStatement x) {\n        return visit((SQLInsertStatement) x);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.MSSQLServerExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\n/**\n * SQLServerProvider\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-17\n */\npublic class SQLServerWallProvider extends WallProvider {\n    public static final String DEFAULT_CONFIG_DIR = \"META-INF/druid/wall/sqlserver\";\n\n    public SQLServerWallProvider() {\n        this(new WallConfig(DEFAULT_CONFIG_DIR));\n    }\n\n    public SQLServerWallProvider(WallConfig config) {\n        super(config, DbType.sqlserver);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return new SQLServerStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return new com.alibaba.druid.wall.spi.SQLServerWallVisitor(this);\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return new MSSQLServerExportParameterVisitor();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils.WallTopStatementContext;\nimport com.alibaba.druid.wall.violation.ErrorCode;\nimport com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;\n\npublic class SQLServerWallVisitor extends WallVisitorBase implements WallVisitor, SQLServerASTVisitor {\n    public SQLServerWallVisitor(WallProvider provider) {\n        super(provider);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.sqlserver;\n    }\n\n    @Override\n    public boolean isDenyTable(String name) {\n        if (!config.isTableCheck()) {\n            return false;\n        }\n\n        return !this.provider.checkDenyTable(name);\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        // String name = x.getName();\n        // name = WallVisitorUtils.form(name);\n        // if (config.isVariantCheck() && config.getDenyVariants().contains(name)) {\n        // getViolations().add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY, \"variable not allow : \" + name,\n        // toSQL(x)));\n        // }\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLMethodInvokeExpr x) {\n        if (x.getParent() instanceof SQLExprTableSource) {\n            WallVisitorUtils.checkFunctionInTableSource(this, x);\n        }\n\n        WallVisitorUtils.checkFunction(this, x);\n\n        return true;\n    }\n\n    @Override\n    public boolean visit(SQLServerExecStatement x) {\n        return false;\n    }\n\n    public boolean visit(SQLVariantRefExpr x) {\n        String varName = x.getName();\n        if (varName == null) {\n            return false;\n        }\n\n        if (config.isVariantCheck() && varName.startsWith(\"@@\")) {\n            final WallTopStatementContext topStatementContext = WallVisitorUtils.getWallTopStatementContext();\n            if (topStatementContext != null\n                    && (topStatementContext.fromSysSchema() || topStatementContext.fromSysTable())) {\n                return false;\n            }\n\n            boolean allow = true;\n            if (isDeny(varName) && (WallVisitorUtils.isWhereOrHaving(x) || WallVisitorUtils.checkSqlExpr(x))) {\n                allow = false;\n            }\n\n            if (!allow) {\n                violations.add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY, \"variable not allow : \"\n                        + x.getName(), toSQL(x)));\n            }\n        }\n\n        return false;\n    }\n\n    public boolean isDeny(String varName) {\n        if (varName.startsWith(\"@@\")) {\n            varName = varName.substring(2);\n        }\n\n        return config.getDenyVariants().contains(varName);\n    }\n\n    @Override\n    public boolean visit(SQLServerObjectReferenceExpr x) {\n        return false;\n    }\n\n    public boolean visit(SQLServerSelectQueryBlock x) {\n        WallVisitorUtils.checkSelect(this, x);\n        return true;\n    }\n    @Override\n    public boolean visit(SQLServerUpdateStatement x) {\n        return visit((SQLUpdateStatement) x);\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/SQLiteWallProvider.java",
    "content": "package com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.sqlite.parser.SQLiteStatementParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.ExportParameterizedOutputVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class SQLiteWallProvider extends WallProvider {\n    public static final String DEFAULT_CONFIG_DIR = \"META-INF/druid/wall/sqlite\";\n\n    public SQLiteWallProvider() {\n        this(new WallConfig(DEFAULT_CONFIG_DIR));\n    }\n\n    public SQLiteWallProvider(WallConfig config) {\n        super(config, DbType.sqlite);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return new SQLiteStatementParser(sql, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return new SQLiteWallVisitor(this);\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return new ExportParameterizedOutputVisitor();\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/SQLiteWallVisitor.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.dialect.sqlite.visitor.SQLiteASTVisitor;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class SQLiteWallVisitor extends WallVisitorBase implements WallVisitor, SQLiteASTVisitor {\n    public SQLiteWallVisitor(WallProvider provider) {\n        super(provider);\n    }\n\n    @Override\n    public DbType getDbType() {\n        return DbType.sqlite;\n    }\n\n    public boolean visit(SQLIdentifierExpr x) {\n        return true;\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/WallVisitorBase.java",
    "content": "package com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.wall.*;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic abstract class WallVisitorBase implements WallVisitor {\n    protected final WallConfig config;\n    protected final WallProvider provider;\n    protected final List<Violation> violations = new ArrayList<Violation>();\n    protected boolean sqlModified;\n    protected boolean sqlEndOfComment;\n    protected List<WallUpdateCheckItem> updateCheckItems;\n\n    public WallVisitorBase(WallProvider provider) {\n        this.config = provider.getConfig();\n        this.provider = provider;\n    }\n\n    @Override\n    public boolean isSqlModified() {\n        return sqlModified;\n    }\n\n    @Override\n    public void setSqlModified(boolean sqlModified) {\n        this.sqlModified = sqlModified;\n    }\n\n    @Override\n    public WallProvider getProvider() {\n        return provider;\n    }\n\n    @Override\n    public WallConfig getConfig() {\n        return config;\n    }\n\n    public void addViolation(Violation violation) {\n        this.violations.add(violation);\n    }\n\n    @Override\n    public List<Violation> getViolations() {\n        return violations;\n    }\n\n    @Override\n    public boolean isSqlEndOfComment() {\n        return this.sqlEndOfComment;\n    }\n\n    @Override\n    public void setSqlEndOfComment(boolean sqlEndOfComment) {\n        this.sqlEndOfComment = sqlEndOfComment;\n    }\n\n    public void addWallUpdateCheckItem(WallUpdateCheckItem item) {\n        if (updateCheckItems == null) {\n            updateCheckItems = new ArrayList<WallUpdateCheckItem>();\n        }\n        updateCheckItems.add(item);\n    }\n\n    public List<WallUpdateCheckItem> getUpdateCheckItems() {\n        return updateCheckItems;\n    }\n\n    public boolean isDenyTable(String name) {\n        if (!config\n                .isTableCheck()) {\n            return false;\n        }\n\n        return !provider.checkDenyTable(name);\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.spi;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.*;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.expr.SQLCaseExpr.Item;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExecuteImmediateStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement;\nimport com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitor;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.sql.visitor.functions.Nil;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.util.FnvHash;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.ServletPathMatcher;\nimport com.alibaba.druid.util.StringUtils;\nimport com.alibaba.druid.wall.*;\nimport com.alibaba.druid.wall.WallConfig.TenantCallBack;\nimport com.alibaba.druid.wall.WallConfig.TenantCallBack.StatementType;\nimport com.alibaba.druid.wall.violation.ErrorCode;\nimport com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.net.URL;\nimport java.util.*;\n\nimport static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE;\n\npublic class WallVisitorUtils {\n    private static final Log LOG = LogFactory.getLog(WallVisitorUtils.class);\n\n    public static final String HAS_TRUE_LIKE = \"hasTrueLike\";\n\n    public static final String[] whiteHints = {\"LOCAL\", \"TEMPORARY\", \"SQL_NO_CACHE\", \"SQL_CACHE\", \"HIGH_PRIORITY\",\n            \"LOW_PRIORITY\", \"STRAIGHT_JOIN\", \"SQL_BUFFER_RESULT\", \"SQL_BIG_RESULT\", \"SQL_SMALL_RESULT\", \"DELAYED\"};\n\n    public static void check(WallVisitor visitor, SQLInListExpr x) {\n    }\n\n    public static boolean check(WallVisitor visitor, SQLBinaryOpExpr x) {\n        if (x.getOperator() == SQLBinaryOperator.BooleanOr\n                || x.getOperator() == SQLBinaryOperator.BooleanAnd) {\n            List<SQLExpr> groupList = SQLBinaryOpExpr.split(x);\n            for (SQLExpr item : groupList) {\n                item.accept(visitor);\n            }\n            return false;\n        }\n\n        if (x.getOperator() == SQLBinaryOperator.Add\n                || x.getOperator() == SQLBinaryOperator.Concat) {\n            List<SQLExpr> groupList = SQLBinaryOpExpr.split(x);\n            if (groupList.size() >= 4) {\n                int chrCount = 0;\n                for (int i = 0; i < groupList.size(); ++i) {\n                    SQLExpr item = groupList.get(i);\n                    if (item instanceof SQLMethodInvokeExpr) {\n                        SQLMethodInvokeExpr methodExpr = (SQLMethodInvokeExpr) item;\n                        String methodName = methodExpr.getMethodName().toLowerCase();\n                        if (\"chr\".equals(methodName) || \"char\".equals(methodName)) {\n                            if (methodExpr.getArguments().get(0) instanceof SQLLiteralExpr) {\n                                chrCount++;\n                            }\n                        }\n                    } else if (item instanceof SQLCharExpr) {\n                        if (((SQLCharExpr) item).getText().length() > 5) {\n                            chrCount = 0;\n                            continue;\n                        }\n                    }\n\n                    if (chrCount >= 4) {\n                        addViolation(visitor, ErrorCode.EVIL_CONCAT, \"evil concat\", x);\n                        break;\n                    }\n                }\n            }\n        }\n\n        return true;\n    }\n\n    public static boolean check(WallVisitor visitor, SQLBinaryOpExprGroup x) {\n        return true;\n    }\n\n    public static void check(WallVisitor visitor, SQLCreateTableStatement x) {\n        String tableName = x.getName().getSimpleName();\n        WallContext context = WallContext.current();\n        if (context != null) {\n            WallSqlTableStat tableStat = context.getTableStat(tableName);\n            if (tableStat != null) {\n                tableStat.incrementCreateCount();\n            }\n        }\n    }\n\n    public static void check(WallVisitor visitor, SQLAlterTableStatement x) {\n        String tableName = x.getName().getSimpleName();\n        WallContext context = WallContext.current();\n        if (context != null) {\n            WallSqlTableStat tableStat = context.getTableStat(tableName);\n            if (tableStat != null) {\n                tableStat.incrementAlterCount();\n            }\n        }\n    }\n\n    public static void check(WallVisitor visitor, SQLDropTableStatement x) {\n        for (SQLExprTableSource item : x.getTableSources()) {\n            SQLExpr expr = item.getExpr();\n            String tableName = ((SQLName) expr).getSimpleName();\n            WallContext context = WallContext.current();\n            if (context != null) {\n                WallSqlTableStat tableStat = context.getTableStat(tableName);\n                if (tableStat != null) {\n                    tableStat.incrementDropCount();\n                }\n            }\n        }\n    }\n\n    public static void check(WallVisitor visitor, SQLSelectItem x) {\n        SQLExpr expr = x.getExpr();\n\n        if (expr instanceof SQLVariantRefExpr) {\n            if (!isTopSelectItem(expr) && \"@\".equals(((SQLVariantRefExpr) expr).getName())) {\n                addViolation(visitor, ErrorCode.EVIL_NAME, \"@ not allow\", x);\n            }\n        }\n\n        if (visitor.getConfig().isSelectAllColumnAllow()) {\n            return;\n        }\n\n        if (expr instanceof SQLAllColumnExpr //\n                && x.getParent() instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x.getParent();\n            SQLTableSource from = queryBlock.getFrom();\n\n            if (from instanceof SQLExprTableSource) {\n                addViolation(visitor, ErrorCode.SELECT_NOT_ALLOW, \"'SELECT *' not allow\", x);\n            }\n        }\n    }\n\n    public static void check(WallVisitor visitor, SQLPropertyExpr x) {\n        checkSchema(visitor, x.getOwner());\n    }\n\n    public static void checkInsert(WallVisitor visitor, SQLInsertInto x) {\n        checkReadOnly(visitor, x.getTableSource());\n\n        if (!visitor.getConfig().isInsertAllow()) {\n            addViolation(visitor, ErrorCode.INSERT_NOT_ALLOW, \"insert not allow\", x);\n        }\n\n        checkInsertForMultiTenant(visitor, x);\n    }\n\n    /**\n     *\n     * @deprecated use {@link WallVisitorUtils#checkSelect(WallVisitor, SQLSelectQueryBlock)}\n     */\n    @Deprecated\n    public static void checkSelelct(WallVisitor visitor, SQLSelectQueryBlock x) {\n        checkSelect(visitor, x);\n    }\n    public static void checkSelect(WallVisitor visitor, SQLSelectQueryBlock x) {\n        if (x.getInto() != null) {\n            checkReadOnly(visitor, x.getInto());\n        }\n\n        final WallConfig config = visitor.getConfig();\n        if (!config.isSelectIntoAllow() && x.getInto() != null) {\n            addViolation(visitor, ErrorCode.SELECT_INTO_NOT_ALLOW, \"select into not allow\", x);\n            return;\n        }\n\n        List<SQLCommentHint> hints = x.getHintsDirect();\n        if (hints != null\n                && x.getParent() instanceof SQLUnionQuery\n                && x == ((SQLUnionQuery) x.getParent()).getRight()\n        ) {\n            for (SQLCommentHint hint : hints) {\n                String text = hint.getText();\n                if (text.startsWith(\"!\")) {\n                    addViolation(visitor, ErrorCode.UNION, \"union select hint not allow\", x);\n                    return;\n                }\n            }\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            checkCondition(visitor, x.getWhere());\n\n            Object whereValue = getConditionValue(visitor, where, config.isSelectWhereAlwayTrueCheck());\n\n            if (Boolean.TRUE.equals(whereValue)) {\n                if (config.isSelectWhereAlwayTrueCheck() && visitor.isSqlEndOfComment() && isSimpleConstExpr(where)) {\n                    addViolation(visitor, ErrorCode.ALWAYS_TRUE, \"select alway true condition not allow\", x);\n                }\n            }\n        }\n        checkSelectForMultiTenant(visitor, x);\n        // checkConditionForMultiTenant(visitor, x.getWhere(), x);\n    }\n\n    public static void checkHaving(WallVisitor visitor, SQLExpr x) {\n        if (x == null) {\n            return;\n        }\n\n        if (Boolean.TRUE.equals(getConditionValue(visitor, x, visitor.getConfig().isSelectHavingAlwayTrueCheck()))) {\n            if (visitor.getConfig().isSelectHavingAlwayTrueCheck()\n                    && visitor.isSqlEndOfComment()\n                    && isSimpleConstExpr(x)) {\n                addViolation(visitor, ErrorCode.ALWAYS_TRUE, \"having alway true condition not allow\", x);\n            }\n        }\n    }\n\n    public static void checkDelete(WallVisitor visitor, SQLDeleteStatement x) {\n        checkReadOnly(visitor, x.getTableSource());\n\n        WallConfig config = visitor.getConfig();\n        if (!config.isDeleteAllow()) {\n            addViolation(visitor, ErrorCode.INSERT_NOT_ALLOW, \"delete not allow\", x);\n            return;\n        }\n\n        boolean hasUsing = false;\n\n        if (x instanceof MySqlDeleteStatement) {\n            hasUsing = x.getUsing() != null;\n        }\n\n        boolean isJoinTableSource = x.getTableSource() instanceof SQLJoinTableSource;\n        if (x.getWhere() == null && (!hasUsing) && !isJoinTableSource) {\n            WallContext context = WallContext.current();\n            if (context != null) {\n                context.incrementDeleteNoneConditionWarnings();\n            }\n\n            if (config.isDeleteWhereNoneCheck()) {\n                addViolation(visitor, ErrorCode.NONE_CONDITION, \"delete none condition not allow\", x);\n                return;\n            }\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where != null) {\n            checkCondition(visitor, where);\n\n            if (Boolean.TRUE.equals(getConditionValue(visitor, where, config.isDeleteWhereAlwayTrueCheck()))) {\n                if (config.isDeleteWhereAlwayTrueCheck() && visitor.isSqlEndOfComment() && isSimpleConstExpr(where)) {\n                    addViolation(visitor, ErrorCode.ALWAYS_TRUE, \"delete alway true condition not allow\", x);\n                }\n            }\n        }\n\n        // checkConditionForMultiTenant(visitor, x.getWhere(), x);\n    }\n\n    private static boolean isSimpleConstExpr(SQLExpr sqlExpr) {\n        List<SQLExpr> parts = getParts(sqlExpr);\n        if (parts.isEmpty()) {\n            return false;\n        }\n\n        for (SQLExpr part : parts) {\n            if (isFirst(part)) {\n                Object evalValue = part.getAttribute(EVAL_VALUE);\n                if (evalValue == null) {\n                    if (part instanceof SQLBooleanExpr) {\n                        evalValue = ((SQLBooleanExpr) part).getBooleanValue();\n                    } else if (part instanceof SQLNumericLiteralExpr) {\n                        evalValue = ((SQLNumericLiteralExpr) part).getNumber();\n                    } else if (part instanceof SQLCharExpr) {\n                        evalValue = ((SQLCharExpr) part).getText();\n                    } else if (part instanceof SQLNCharExpr) {\n                        evalValue = ((SQLNCharExpr) part).getText();\n                    }\n                }\n                Boolean result = SQLEvalVisitorUtils.castToBoolean(evalValue);\n                if (result != null && result) {\n                    return true;\n                }\n            }\n            boolean isSimpleConstExpr = false;\n            if (part == sqlExpr || part instanceof SQLLiteralExpr) {\n                isSimpleConstExpr = true;\n            } else if (part instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) part;\n\n                if (binaryOpExpr.getOperator() == SQLBinaryOperator.Equality\n                        || binaryOpExpr.getOperator() == SQLBinaryOperator.NotEqual\n                        || binaryOpExpr.getOperator() == SQLBinaryOperator.GreaterThan) {\n                        isSimpleConstExpr = true;\n                }\n            }\n\n            if (isSimpleConstExpr) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private static void checkCondition(WallVisitor visitor, SQLExpr x) {\n        if (x == null) {\n            return;\n        }\n\n        if (visitor.getConfig().isMustParameterized()) {\n            ExportParameterVisitor exportParameterVisitor = visitor.getProvider().createExportParameterVisitor();\n            x.accept(exportParameterVisitor);\n\n            if (exportParameterVisitor.getParameters().size() > 0) {\n                addViolation(visitor, ErrorCode.NOT_PARAMETERIZED, \"sql must parameterized\", x);\n            }\n        }\n\n    }\n\n    private static void checkJoinSelectForMultiTenant(WallVisitor visitor, SQLJoinTableSource join,\n                                                      SQLSelectQueryBlock x) {\n        TenantCallBack tenantCallBack = visitor.getConfig().getTenantCallBack();\n        String tenantTablePattern = visitor.getConfig().getTenantTablePattern();\n        if (tenantCallBack == null && (tenantTablePattern == null || tenantTablePattern.length() == 0)) {\n            return;\n        }\n\n        SQLTableSource right = join.getRight();\n        if (right instanceof SQLExprTableSource) {\n            SQLExpr tableExpr = ((SQLExprTableSource) right).getExpr();\n\n            if (tableExpr instanceof SQLIdentifierExpr) {\n                String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n\n                String alias = null;\n                String tenantColumn = null;\n                if (tenantCallBack != null) {\n                    tenantColumn = tenantCallBack.getTenantColumn(StatementType.SELECT, tableName);\n                }\n\n                if (StringUtils.isEmpty(tenantColumn)\n                        && ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                    tenantColumn = visitor.getConfig().getTenantColumn();\n                }\n\n                if (!StringUtils.isEmpty(tenantColumn)) {\n                    alias = right.getAlias();\n                    if (alias == null) {\n                        alias = tableName;\n                    }\n\n                    SQLExpr item = null;\n                    if (alias != null) {\n                        item = new SQLPropertyExpr(new SQLIdentifierExpr(alias), tenantColumn);\n                    } else {\n                        item = new SQLIdentifierExpr(tenantColumn);\n                    }\n                    SQLSelectItem selectItem = new SQLSelectItem(item);\n                    x.getSelectList().add(selectItem);\n                    visitor.setSqlModified(true);\n                }\n            }\n        }\n    }\n\n    private static boolean isSelectStatmentForMultiTenant(SQLSelectQueryBlock queryBlock) {\n        SQLObject parent = queryBlock.getParent();\n        while (parent != null) {\n            if (parent instanceof SQLUnionQuery) {\n                SQLObject x = parent;\n                parent = x.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (!(parent instanceof SQLSelect)) {\n            return false;\n        }\n\n        parent = parent.getParent();\n        if (parent instanceof SQLSelectStatement) {\n            return true;\n        }\n\n        return false;\n    }\n\n    private static void checkSelectForMultiTenant(WallVisitor visitor, SQLSelectQueryBlock x) {\n        TenantCallBack tenantCallBack = visitor.getConfig().getTenantCallBack();\n        String tenantTablePattern = visitor.getConfig().getTenantTablePattern();\n        if (tenantCallBack == null && (tenantTablePattern == null || tenantTablePattern.length() == 0)) {\n            return;\n        }\n\n        if (x == null) {\n            throw new IllegalStateException(\"x is null\");\n        }\n\n        if (!isSelectStatmentForMultiTenant(x)) {\n            return;\n        }\n\n        SQLTableSource tableSource = x.getFrom();\n        String alias = null;\n        String matchTableName = null;\n        String tenantColumn = null;\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr tableExpr = ((SQLExprTableSource) tableSource).getExpr();\n\n            if (tableExpr instanceof SQLIdentifierExpr) {\n                String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n\n                if (tenantCallBack != null) {\n                    tenantColumn = tenantCallBack.getTenantColumn(StatementType.SELECT, tableName);\n                }\n\n                if (StringUtils.isEmpty(tenantColumn)\n                        && ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                    tenantColumn = visitor.getConfig().getTenantColumn();\n                }\n\n                if (!StringUtils.isEmpty(tenantColumn)) {\n                    matchTableName = tableName;\n                    alias = tableSource.getAlias();\n                }\n            }\n        } else if (tableSource instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n            if (join.getLeft() instanceof SQLExprTableSource) {\n                SQLExpr tableExpr = ((SQLExprTableSource) join.getLeft()).getExpr();\n\n                if (tableExpr instanceof SQLIdentifierExpr) {\n                    String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n\n                    if (tenantCallBack != null) {\n                        tenantColumn = tenantCallBack.getTenantColumn(StatementType.SELECT, tableName);\n                    }\n\n                    if (StringUtils.isEmpty(tenantColumn)\n                            && ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                        tenantColumn = visitor.getConfig().getTenantColumn();\n                    }\n\n                    if (!StringUtils.isEmpty(tenantColumn)) {\n                        matchTableName = tableName;\n                        alias = join.getLeft().getAlias();\n\n                        if (alias == null) {\n                            alias = tableName;\n                        }\n                    }\n                }\n                checkJoinSelectForMultiTenant(visitor, join, x);\n            } else {\n                checkJoinSelectForMultiTenant(visitor, join, x);\n            }\n        }\n\n        if (matchTableName == null) {\n            return;\n        }\n\n        SQLExpr item = null;\n        if (alias != null) {\n            item = new SQLPropertyExpr(new SQLIdentifierExpr(alias), tenantColumn);\n        } else {\n            item = new SQLIdentifierExpr(tenantColumn);\n        }\n        SQLSelectItem selectItem = new SQLSelectItem(item);\n        x.getSelectList().add(selectItem);\n        visitor.setSqlModified(true);\n    }\n\n    private static void checkUpdateForMultiTenant(WallVisitor visitor, SQLUpdateStatement x) {\n        TenantCallBack tenantCallBack = visitor.getConfig().getTenantCallBack();\n        String tenantTablePattern = visitor.getConfig().getTenantTablePattern();\n        if (tenantCallBack == null && (tenantTablePattern == null || tenantTablePattern.length() == 0)) {\n            return;\n        }\n\n        if (x == null) {\n            throw new IllegalStateException(\"x is null\");\n        }\n\n        SQLTableSource tableSource = x.getTableSource();\n        String alias = null;\n        String matchTableName = null;\n        String tenantColumn = null;\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr tableExpr = ((SQLExprTableSource) tableSource).getExpr();\n            if (tableExpr instanceof SQLIdentifierExpr) {\n                String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n\n                if (tenantCallBack != null) {\n                    tenantColumn = tenantCallBack.getTenantColumn(StatementType.UPDATE, tableName);\n                }\n                if (StringUtils.isEmpty(tenantColumn)\n                        && ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                    tenantColumn = visitor.getConfig().getTenantColumn();\n                }\n\n                if (!StringUtils.isEmpty(tenantColumn)) {\n                    matchTableName = tableName;\n                    alias = tableSource.getAlias();\n                }\n            }\n        }\n\n        if (matchTableName == null) {\n            return;\n        }\n\n        SQLExpr item = null;\n        if (alias != null) {\n            item = new SQLPropertyExpr(new SQLIdentifierExpr(alias), tenantColumn);\n        } else {\n            item = new SQLIdentifierExpr(tenantColumn);\n        }\n        SQLExpr value = generateTenantValue(visitor, alias, StatementType.UPDATE, matchTableName);\n\n        SQLUpdateSetItem updateSetItem = new SQLUpdateSetItem();\n        updateSetItem.setColumn(item);\n        updateSetItem.setValue(value);\n\n        x.addItem(updateSetItem);\n        visitor.setSqlModified(true);\n    }\n\n    private static void checkInsertForMultiTenant(WallVisitor visitor, SQLInsertInto x) {\n        TenantCallBack tenantCallBack = visitor.getConfig().getTenantCallBack();\n        String tenantTablePattern = visitor.getConfig().getTenantTablePattern();\n        if (tenantCallBack == null && (tenantTablePattern == null || tenantTablePattern.length() == 0)) {\n            return;\n        }\n\n        if (x == null) {\n            throw new IllegalStateException(\"x is null\");\n        }\n\n        SQLExprTableSource tableSource = x.getTableSource();\n        String alias = null;\n        String matchTableName = null;\n        String tenantColumn = null;\n        SQLExpr tableExpr = tableSource.getExpr();\n        if (tableExpr instanceof SQLIdentifierExpr) {\n            String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n\n            if (tenantCallBack != null) {\n                tenantColumn = tenantCallBack.getTenantColumn(StatementType.INSERT, tableName);\n            }\n            if (StringUtils.isEmpty(tenantColumn)\n                    && ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                tenantColumn = visitor.getConfig().getTenantColumn();\n            }\n\n            if (!StringUtils.isEmpty(tenantColumn)) {\n                matchTableName = tableName;\n                alias = tableSource.getAlias();\n            }\n        }\n\n        if (matchTableName == null) {\n            return;\n        }\n\n        SQLExpr item = null;\n        if (alias != null) {\n            item = new SQLPropertyExpr(new SQLIdentifierExpr(alias), tenantColumn);\n        } else {\n            item = new SQLIdentifierExpr(tenantColumn);\n        }\n        SQLExpr value = generateTenantValue(visitor, alias, StatementType.INSERT, matchTableName);\n\n        // add insert item and value\n        x.getColumns().add(item);\n\n        List<ValuesClause> valuesClauses = null;\n        ValuesClause valuesClause = null;\n        if (x instanceof MySqlInsertStatement) {\n            valuesClauses = x.getValuesList();\n        } else if (x instanceof SQLServerInsertStatement) {\n            valuesClauses = x.getValuesList();\n        } else {\n            valuesClause = x.getValues();\n        }\n\n        if (valuesClauses != null && valuesClauses.size() > 0) {\n            for (ValuesClause clause : valuesClauses) {\n                clause.addValue(value);\n            }\n        }\n        if (valuesClause != null) {\n            valuesClause.addValue(value);\n        }\n\n        // insert .. select\n        SQLSelect select = x.getQuery();\n        if (select != null) {\n            List<SQLSelectQueryBlock> queryBlocks = splitSQLSelectQuery(select.getQuery());\n            for (SQLSelectQueryBlock queryBlock : queryBlocks) {\n                queryBlock.getSelectList().add(new SQLSelectItem(value));\n            }\n        }\n\n        visitor.setSqlModified(true);\n    }\n\n    private static List<SQLSelectQueryBlock> splitSQLSelectQuery(SQLSelectQuery x) {\n        List<SQLSelectQueryBlock> groupList = new ArrayList<SQLSelectQueryBlock>();\n        Stack<SQLSelectQuery> stack = new Stack<SQLSelectQuery>();\n\n        stack.push(x);\n        do {\n            SQLSelectQuery query = stack.pop();\n            if (query instanceof SQLSelectQueryBlock) {\n                groupList.add((SQLSelectQueryBlock) query);\n            } else if (query instanceof SQLUnionQuery) {\n                SQLUnionQuery unionQuery = (SQLUnionQuery) query;\n                stack.push(unionQuery.getLeft());\n                stack.push(unionQuery.getRight());\n            }\n        } while (!stack.empty());\n        return groupList;\n    }\n\n    @Deprecated\n    public static void checkConditionForMultiTenant(WallVisitor visitor, SQLExpr x, SQLObject parent) {\n        String tenantTablePattern = visitor.getConfig().getTenantTablePattern();\n        if (tenantTablePattern == null || tenantTablePattern.length() == 0) {\n            return;\n        }\n\n        if (parent == null) {\n            throw new IllegalStateException(\"parent is null\");\n        }\n\n        String alias = null;\n        SQLTableSource tableSource;\n        StatementType statementType = null;\n        if (parent instanceof SQLDeleteStatement) {\n            tableSource = ((SQLDeleteStatement) parent).getTableSource();\n            statementType = StatementType.DELETE;\n        } else if (parent instanceof SQLUpdateStatement) {\n            tableSource = ((SQLUpdateStatement) parent).getTableSource();\n            statementType = StatementType.UPDATE;\n        } else if (parent instanceof SQLSelectQueryBlock) {\n            tableSource = ((SQLSelectQueryBlock) parent).getFrom();\n            statementType = StatementType.SELECT;\n        } else {\n            throw new IllegalStateException(\"not support parent : \" + parent.getClass());\n        }\n\n        String matchTableName = null;\n        if (tableSource instanceof SQLExprTableSource) {\n            SQLExpr tableExpr = ((SQLExprTableSource) tableSource).getExpr();\n\n            if (tableExpr instanceof SQLIdentifierExpr) {\n                String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n                if (ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                    matchTableName = tableName;\n                    alias = tableSource.getAlias();\n                }\n            }\n        } else if (tableSource instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n            if (join.getLeft() instanceof SQLExprTableSource) {\n                SQLExpr tableExpr = ((SQLExprTableSource) join.getLeft()).getExpr();\n\n                if (tableExpr instanceof SQLIdentifierExpr) {\n                    String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n                    if (ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                        matchTableName = tableName;\n                        alias = join.getLeft().getAlias();\n                    }\n                }\n\n                checkJoinConditionForMultiTenant(visitor, join, false, statementType);\n            } else {\n                checkJoinConditionForMultiTenant(visitor, join, true, statementType);\n            }\n        }\n\n        if (matchTableName == null) {\n            return;\n        }\n\n        SQLBinaryOpExpr tenantCondition = createTenantCondition(visitor, alias, statementType, matchTableName);\n\n        SQLExpr condition;\n        if (x == null) {\n            condition = tenantCondition;\n        } else {\n            condition = new SQLBinaryOpExpr(tenantCondition, SQLBinaryOperator.BooleanAnd, x);\n        }\n\n        if (parent instanceof SQLDeleteStatement) {\n            SQLDeleteStatement deleteStmt = (SQLDeleteStatement) parent;\n            deleteStmt.setWhere(condition);\n            visitor.setSqlModified(true);\n        } else if (parent instanceof SQLUpdateStatement) {\n            SQLUpdateStatement updateStmt = (SQLUpdateStatement) parent;\n            updateStmt.setWhere(condition);\n            visitor.setSqlModified(true);\n        } else if (parent instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;\n            queryBlock.setWhere(condition);\n            visitor.setSqlModified(true);\n        }\n    }\n\n    @Deprecated\n    public static void checkJoinConditionForMultiTenant(WallVisitor visitor, SQLJoinTableSource join,\n                                                        boolean checkLeft, StatementType statementType) {\n        String tenantTablePattern = visitor.getConfig().getTenantTablePattern();\n        if (tenantTablePattern == null || tenantTablePattern.length() == 0) {\n            return;\n        }\n\n        SQLExpr condition = join.getCondition();\n\n        SQLTableSource right = join.getRight();\n        if (right instanceof SQLExprTableSource) {\n            SQLExpr tableExpr = ((SQLExprTableSource) right).getExpr();\n\n            if (tableExpr instanceof SQLIdentifierExpr) {\n                String tableName = ((SQLIdentifierExpr) tableExpr).getName();\n                if (ServletPathMatcher.getInstance().matches(tenantTablePattern, tableName)) {\n                    String alias = right.getAlias();\n                    if (alias == null) {\n                        alias = tableName;\n                    }\n                    SQLBinaryOpExpr tenantCondition = createTenantCondition(visitor, alias, statementType, tableName);\n\n                    if (condition == null) {\n                        condition = tenantCondition;\n                    } else {\n                        condition = new SQLBinaryOpExpr(tenantCondition, SQLBinaryOperator.BooleanAnd, condition);\n                    }\n                }\n            }\n        }\n\n        if (condition != join.getCondition()) {\n            join.setCondition(condition);\n            visitor.setSqlModified(true);\n        }\n    }\n\n    @Deprecated\n    private static SQLBinaryOpExpr createTenantCondition(WallVisitor visitor, String alias,\n                                                         StatementType statementType, String tableName) {\n        SQLExpr left, right;\n        if (alias != null) {\n            left = new SQLPropertyExpr(new SQLIdentifierExpr(alias), visitor.getConfig().getTenantColumn());\n        } else {\n            left = new SQLIdentifierExpr(visitor.getConfig().getTenantColumn());\n        }\n        right = generateTenantValue(visitor, alias, statementType, tableName);\n\n        SQLBinaryOpExpr tenantCondition = new SQLBinaryOpExpr(left, SQLBinaryOperator.Equality, right);\n        return tenantCondition;\n    }\n\n    private static SQLExpr generateTenantValue(WallVisitor visitor, String alias, StatementType statementType,\n                                               String tableName) {\n        SQLExpr value;\n        TenantCallBack callBack = visitor.getConfig().getTenantCallBack();\n        if (callBack != null) {\n            WallProvider.setTenantValue(callBack.getTenantValue(statementType, tableName));\n        }\n\n        Object tenantValue = WallProvider.getTenantValue();\n        if (tenantValue instanceof Number) {\n            value = new SQLNumberExpr((Number) tenantValue);\n        } else if (tenantValue instanceof String) {\n            value = new SQLCharExpr((String) tenantValue);\n        } else {\n            throw new IllegalStateException(\"tenant value not support type \" + tenantValue);\n        }\n\n        return value;\n    }\n\n    public static void checkReadOnly(WallVisitor visitor, SQLTableSource tableSource) {\n        if (tableSource instanceof SQLExprTableSource) {\n            String tableName = null;\n            SQLExpr tableNameExpr = ((SQLExprTableSource) tableSource).getExpr();\n            if (tableNameExpr instanceof SQLName) {\n                tableName = ((SQLName) tableNameExpr).getSimpleName();\n            }\n\n            boolean readOnlyValid = visitor.getProvider().checkReadOnlyTable(tableName);\n            if (!readOnlyValid) {\n                addViolation(visitor, ErrorCode.READ_ONLY, \"table readonly : \" + tableName, tableSource);\n            }\n        } else if (tableSource instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) tableSource;\n\n            checkReadOnly(visitor, join.getLeft());\n            checkReadOnly(visitor, join.getRight());\n        }\n    }\n\n    public static void checkUpdate(WallVisitor visitor, SQLUpdateStatement x) {\n        checkReadOnly(visitor, x.getTableSource());\n\n        WallConfig config = visitor.getConfig();\n        if (!config.isUpdateAllow()) {\n            addViolation(visitor, ErrorCode.UPDATE_NOT_ALLOW, \"update not allow\", x);\n            return;\n        }\n\n        SQLExpr where = x.getWhere();\n        if (where == null) {\n            WallContext context = WallContext.current();\n            if (context != null) {\n                context.incrementUpdateNoneConditionWarnings();\n            }\n\n            if (config.isUpdateWhereNoneCheck()) {\n                if (x instanceof MySqlUpdateStatement) {\n                    MySqlUpdateStatement mysqlUpdate = (MySqlUpdateStatement) x;\n                    if (mysqlUpdate.getLimit() == null) {\n                        addViolation(visitor, ErrorCode.NONE_CONDITION, \"update none condition not allow\", x);\n                        return;\n                    }\n                } else {\n                    addViolation(visitor, ErrorCode.NONE_CONDITION, \"update none condition not allow\", x);\n                    return;\n                }\n            }\n        } else {\n            checkCondition(visitor, where);\n\n            if (Boolean.TRUE.equals(getConditionValue(visitor, where, config.isUpdateWhereAlwayTrueCheck()))) {\n                if (config.isUpdateWhereAlwayTrueCheck() && visitor.isSqlEndOfComment() && isSimpleConstExpr(where)) {\n                    addViolation(visitor, ErrorCode.ALWAYS_TRUE, \"update alway true condition not allow\", x);\n                }\n            }\n\n            SQLName table = x.getTableName();\n            if (table == null) {\n                return;\n            }\n\n            String tableName = table.getSimpleName();\n            Set<String> updateCheckColumns = config.getUpdateCheckTable(tableName);\n            boolean isUpdateCheckTable = updateCheckColumns != null && !updateCheckColumns.isEmpty();\n\n            WallUpdateCheckHandler updateCheckHandler = config.getUpdateCheckHandler();\n            if (isUpdateCheckTable && updateCheckHandler != null) {\n                String checkColumn = updateCheckColumns.iterator().next();\n\n                SQLExpr valueExpr = null;\n                for (SQLUpdateSetItem item : x.getItems()) {\n                    if (item.columnMatch(checkColumn)) {\n                        valueExpr = item.getValue();\n                        break;\n                    }\n                }\n\n                if (valueExpr != null) {\n                    List<SQLExpr> conditions;\n                    if (where instanceof SQLBinaryOpExpr) {\n                        conditions = SQLBinaryOpExpr.split((SQLBinaryOpExpr) where, SQLBinaryOperator.BooleanAnd);\n                    } else if (where instanceof SQLBinaryOpExprGroup) {\n                        conditions = new ArrayList<SQLExpr>();\n                        for (SQLExpr each : ((SQLBinaryOpExprGroup) where).getItems()) {\n                            if (each instanceof SQLBinaryOpExpr) {\n                                conditions.addAll(SQLBinaryOpExpr.split((SQLBinaryOpExpr) each, SQLBinaryOperator.BooleanAnd));\n                            } else if (each instanceof SQLInListExpr) {\n                                conditions.add(each);\n                            }\n                        }\n                    } else {\n                        conditions = new ArrayList<SQLExpr>();\n                        conditions.add(where);\n                    }\n\n                    List<SQLExpr> filterValueExprList = new ArrayList<SQLExpr>();\n                    for (SQLExpr condition : conditions) {\n                        if (condition instanceof SQLBinaryOpExpr) {\n                            SQLBinaryOpExpr binaryCondition = (SQLBinaryOpExpr) condition;\n                            if (binaryCondition.getOperator() == SQLBinaryOperator.Equality\n                                    && binaryCondition.conditionContainsColumn(checkColumn)) {\n                                SQLExpr left = binaryCondition.getLeft();\n                                SQLExpr right = binaryCondition.getRight();\n\n                                if (left instanceof SQLValuableExpr || left instanceof SQLVariantRefExpr) {\n                                    filterValueExprList.add(left);\n                                } else if (right instanceof SQLValuableExpr || right instanceof SQLVariantRefExpr) {\n                                    filterValueExprList.add(right);\n                                }\n                            }\n                        } else if (condition instanceof SQLInListExpr) {\n                            SQLInListExpr listExpr = (SQLInListExpr) condition;\n                            if (listExpr.getExpr() instanceof SQLIdentifierExpr) {\n                                SQLIdentifierExpr nameExpr = (SQLIdentifierExpr) listExpr.getExpr();\n                                if (nameExpr.getName().equals(checkColumn)) {\n                                    filterValueExprList.addAll(((SQLInListExpr) condition).getTargetList());\n                                }\n                            }\n                        }\n                    }\n\n                    boolean allValue = valueExpr instanceof SQLValuableExpr;\n                    if (allValue) {\n                        for (SQLExpr filterValue : filterValueExprList) {\n                            if (!(filterValue instanceof SQLValuableExpr)) {\n                                allValue = false;\n                                break;\n                            }\n                        }\n                    }\n\n                    if (allValue) {\n                        Object setValue = ((SQLValuableExpr) valueExpr).getValue();\n                        List<Object> filterValues = new ArrayList<Object>(filterValueExprList.size());\n                        for (SQLExpr expr : filterValueExprList) {\n                            filterValues.add(((SQLValuableExpr) expr).getValue());\n                        }\n                        filterValues = new ArrayList(new HashSet(filterValues));\n                        boolean validate = updateCheckHandler.check(tableName, checkColumn, setValue, filterValues);\n                        if (!validate) {\n                            visitor.addViolation(new IllegalSQLObjectViolation(ErrorCode.UPDATE_CHECK_FAIL, \"update check failed.\", visitor.toSQL(x)));\n                        }\n                    } else {\n                        visitor.addWallUpdateCheckItem(new WallUpdateCheckItem(tableName, checkColumn, valueExpr, filterValueExprList));\n                    }\n                    //updateCheckHandler.check(tableName, checkColumn)\n                }\n            }\n        }\n\n        checkUpdateForMultiTenant(visitor, x);\n    }\n\n    public static Object getValue(WallVisitor visitor, SQLBinaryOpExprGroup x) {\n        List<SQLExpr> groupList = x.getItems();\n\n        if (x.getOperator() == SQLBinaryOperator.BooleanOr) {\n            return getValue_or(visitor, groupList);\n        }\n\n        if (x.getOperator() == SQLBinaryOperator.BooleanAnd) {\n            return getValue_and(visitor, groupList);\n        }\n\n        return null;\n    }\n\n    public static Object getValue(WallVisitor visitor, SQLBinaryOpExpr x) {\n        if (x.getOperator() == SQLBinaryOperator.BooleanOr) {\n            List<SQLExpr> groupList = SQLBinaryOpExpr.split(x);\n\n            return getValue_or(visitor, groupList);\n        }\n\n        if (x.getOperator() == SQLBinaryOperator.BooleanAnd) {\n            List<SQLExpr> groupList = SQLBinaryOpExpr.split(x);\n            return getValue_and(visitor, groupList);\n        }\n\n        boolean checkCondition = visitor != null\n                && (!visitor.getConfig().isConstArithmeticAllow()\n                || !visitor.getConfig().isConditionOpBitwiseAllow() || !visitor.getConfig().isConditionOpXorAllow());\n\n        if (x.getLeft() instanceof SQLName) {\n            if (x.getRight() instanceof SQLName) {\n                if (x.getLeft().toString().equalsIgnoreCase(x.getRight().toString())) {\n                    switch (x.getOperator()) {\n                        case Equality:\n                        case Like:\n                            return Boolean.TRUE;\n                        case NotEqual:\n                        case GreaterThan:\n                        case GreaterThanOrEqual:\n                        case LessThan:\n                        case LessThanOrEqual:\n                        case LessThanOrGreater:\n                        case NotLike:\n                            return Boolean.FALSE;\n                        default:\n                            break;\n                    }\n                }\n            } else if (!checkCondition) {\n                switch (x.getOperator()) {\n                    case Equality:\n                    case NotEqual:\n                    case GreaterThan:\n                    case GreaterThanOrEqual:\n                    case LessThan:\n                    case LessThanOrEqual:\n                    case LessThanOrGreater:\n                        return null;\n                    default:\n                        break;\n                }\n            }\n        }\n\n        if (x.getLeft() instanceof SQLValuableExpr && x.getRight() instanceof SQLValuableExpr) {\n            Object leftValue = ((SQLValuableExpr) x.getLeft()).getValue();\n            Object rightValue = ((SQLValuableExpr) x.getRight()).getValue();\n            if (x.getOperator() == SQLBinaryOperator.Equality) {\n                boolean evalValue = SQLEvalVisitorUtils.eq(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, evalValue);\n                return evalValue;\n            } else if (x.getOperator() == SQLBinaryOperator.NotEqual) {\n                boolean evalValue = SQLEvalVisitorUtils.eq(leftValue, rightValue);\n                x.putAttribute(EVAL_VALUE, !evalValue);\n                return !evalValue;\n            }\n        }\n\n        Object leftResult = getValue(visitor, x.getLeft());\n        Object rightResult = getValue(visitor, x.getRight());\n\n        if (x.getOperator() == SQLBinaryOperator.Like && leftResult instanceof String && leftResult.equals(rightResult)) {\n            addViolation(visitor, ErrorCode.SAME_CONST_LIKE, \"same const like\", x);\n        }\n\n        if (x.getOperator() == SQLBinaryOperator.Like || x.getOperator() == SQLBinaryOperator.NotLike) {\n            WallContext context = WallContext.current();\n            if (context != null) {\n                if (rightResult instanceof Number || leftResult instanceof Number) {\n                    context.incrementLikeNumberWarnings();\n                }\n            }\n        }\n        if (false && leftResult == null && rightResult == null) {\n            return null;\n        }\n        DbType dbType = null;\n        WallContext wallContext = WallContext.current();\n        if (wallContext != null) {\n            dbType = wallContext.getDbType();\n        }\n\n        return eval(visitor, dbType, x, Collections.emptyList());\n    }\n\n    private static Object getValue_or(WallVisitor visitor, List<SQLExpr> groupList) {\n        int falseCount = 0;\n        for (int i = groupList.size() - 1; i >= 0; --i) {\n            SQLExpr item = groupList.get(i);\n            Object result = getValue(visitor, item);\n            final Boolean booleanVal = SQLEvalVisitorUtils.castToBoolean(result);\n            if (booleanVal != null && booleanVal.booleanValue()) {\n                final WallConditionContext wallContext = WallVisitorUtils.getWallConditionContext();\n                if (wallContext != null && !isFirst(item)) {\n                    wallContext.setPartAlwayTrue(true);\n                }\n                return true;\n            }\n\n            if (Boolean.FALSE.equals(booleanVal)) {\n                falseCount++;\n            }\n        }\n\n        if (falseCount == groupList.size()) {\n            return false;\n        }\n\n        return null;\n    }\n\n    private static Object getValue_and(WallVisitor visitor, List<SQLExpr> groupList) {\n        int dalConst = 0;\n        int trueCount = 0;\n        int falseCount = 0;\n        for (int i = groupList.size() - 1; i >= 0; --i) {\n            SQLExpr item = groupList.get(i);\n            Object result = getValue(visitor, item);\n            Boolean booleanVal = SQLEvalVisitorUtils.castToBoolean(result);\n\n            if (Boolean.TRUE.equals(booleanVal)) {\n                final WallConditionContext wallContext = WallVisitorUtils.getWallConditionContext();\n                if (wallContext != null && !isFirst(item)) {\n                    wallContext.setPartAlwayTrue(true);\n                }\n                dalConst++;\n                trueCount++;\n            } else if (Boolean.FALSE.equals(booleanVal)) {\n                final WallConditionContext wallContext = WallVisitorUtils.getWallConditionContext();\n                if (wallContext != null && !isFirst(item)) {\n                    wallContext.setPartAlwayFalse(true);\n                }\n                falseCount++;\n                dalConst++;\n            } else {\n                dalConst = 0;\n            }\n\n            if (dalConst == 2 && visitor != null && !visitor.getConfig().isConditionDoubleConstAllow()) {\n                addViolation(visitor, ErrorCode.DOUBLE_CONST_CONDITION, \"double const condition\", item);\n            }\n        }\n\n        if (falseCount > 0) {\n            return false;\n        } else if (trueCount == groupList.size()) {\n            return true;\n        }\n        return null;\n    }\n\n    public static SQLExpr getFirst(SQLExpr x) {\n        if (x instanceof SQLBinaryOpExpr) {\n            SQLBinaryOpExpr binary = (SQLBinaryOpExpr) x;\n            if (binary.getOperator() == SQLBinaryOperator.BooleanAnd\n                    || binary.getOperator() == SQLBinaryOperator.BooleanOr) {\n                return getFirst(((SQLBinaryOpExpr) x).getLeft());\n            }\n        }\n\n        return x;\n    }\n\n    public static List<SQLExpr> getParts(SQLExpr x) {\n        List<SQLExpr> exprs = new ArrayList<SQLExpr>();\n        exprs.add(x);\n\n        while (true) {\n            List<SQLExpr> tmp = partExpr(exprs);\n\n            if (tmp.size() == exprs.size()) {\n                break;\n            }\n            exprs = tmp;\n        }\n\n        return exprs;\n    }\n\n    public static List<SQLExpr> partExpr(List<SQLExpr> exprs) {\n        List<SQLExpr> partList = new ArrayList<SQLExpr>();\n\n        for (SQLExpr x : exprs) {\n            if (x instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr binary = (SQLBinaryOpExpr) x;\n                if (binary.getOperator() == SQLBinaryOperator.BooleanAnd\n                        || binary.getOperator() == SQLBinaryOperator.BooleanOr) {\n                    partList.add(((SQLBinaryOpExpr) x).getLeft());\n                    partList.add(((SQLBinaryOpExpr) x).getRight());\n\n                    continue;\n                }\n            }\n            partList.add(x);\n        }\n        return partList;\n    }\n\n    public static boolean isFirst(SQLObject x) {\n        if (x == null) {\n            return true;\n        }\n\n        for (; ; ) {\n            SQLObject parent = x.getParent();\n            if (!(parent instanceof SQLExpr)) {\n                return true;\n            }\n\n            if (parent instanceof SQLBinaryOpExprGroup) {\n                if (x != ((SQLBinaryOpExprGroup) parent).getItems().get(0)) {\n                    return false;\n                }\n            }\n\n            if (parent instanceof SQLBinaryOpExpr) {\n                SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) parent;\n                if (x == binaryExpr.getRight()) {\n                    return false;\n                }\n            }\n            x = parent;\n        }\n    }\n\n    private static boolean hasWhere(SQLSelectQuery selectQuery) {\n        if (selectQuery instanceof SQLSelectQueryBlock) {\n            return ((SQLSelectQueryBlock) selectQuery).getWhere() != null;\n        } else if (selectQuery instanceof SQLUnionQuery) {\n            SQLUnionQuery union = (SQLUnionQuery) selectQuery;\n            return hasWhere(union.getLeft()) || hasWhere(union.getRight());\n        }\n        return false;\n    }\n\n    public static boolean checkSqlExpr(SQLExpr x) { // check groupby, orderby, limit\n        if (x == null) {\n            return false;\n        }\n\n        SQLObject obj = x;\n        for (; ; ) {\n            SQLObject parent = obj.getParent();\n\n            if (parent == null) {\n                return false;\n            }\n\n            if (parent instanceof SQLSelectGroupByClause) {\n                return true;\n            } else if (parent instanceof SQLOrderBy) {\n                return true;\n            } else if (parent instanceof SQLLimit) {\n                return true;\n            } else if (parent instanceof MySqlOrderingExpr) {\n                return true;\n            }\n\n            obj = parent;\n        }\n    }\n\n    public static boolean isWhereOrHaving(SQLObject x) {\n        if (x == null) {\n            return false;\n        }\n\n        for (; ; ) {\n            SQLObject parent = x.getParent();\n\n            if (parent == null) {\n                return false;\n            }\n\n            if (parent instanceof SQLJoinTableSource) {\n                SQLJoinTableSource joinTableSource = (SQLJoinTableSource) parent;\n                if (joinTableSource.getCondition() == x) {\n                    return true;\n                }\n\n            }\n\n            if (parent instanceof SQLUnionQuery) {\n                SQLUnionQuery union = (SQLUnionQuery) parent;\n                if (union.getRight() == x && hasWhere(union.getLeft())) {\n                    return true;\n                }\n            }\n\n            if (parent instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock query = (SQLSelectQueryBlock) parent;\n                if (query.getWhere() == x) {\n                    return true;\n                }\n            }\n\n            if (parent instanceof SQLDeleteStatement) {\n                SQLDeleteStatement delete = (SQLDeleteStatement) parent;\n                if (delete.getWhere() == x) {\n                    return true;\n                } else {\n                    return false;\n                }\n            }\n\n            if (parent instanceof SQLUpdateStatement) {\n                SQLUpdateStatement update = (SQLUpdateStatement) parent;\n                if (update.getWhere() == x) {\n                    return true;\n                } else {\n                    return false;\n                }\n            }\n\n            if (parent instanceof SQLSelectGroupByClause) {\n                SQLSelectGroupByClause groupBy = (SQLSelectGroupByClause) parent;\n                if (x == groupBy.getHaving()) {\n                    return true;\n                } else {\n                    return false;\n                }\n            }\n\n            x = parent;\n        }\n    }\n\n    public static class WallTopStatementContext {\n        private boolean fromSysTable;\n        private boolean fromSysSchema;\n\n        private boolean fromPermitTable;\n\n        public boolean fromSysTable() {\n            return fromSysTable;\n        }\n\n        public void setFromSysTable(boolean fromSysTable) {\n            this.fromSysTable = fromSysTable;\n        }\n\n        public boolean fromSysSchema() {\n            return fromSysSchema;\n        }\n\n        public void setFromSysSchema(boolean fromSysSchema) {\n            this.fromSysSchema = fromSysSchema;\n        }\n\n        public boolean fromPermitTable() {\n            return fromPermitTable;\n        }\n\n        public void setFromPermitTable(boolean fromPermitTable) {\n            this.fromPermitTable = fromPermitTable;\n        }\n    }\n\n    public static class WallConditionContext {\n        private boolean partAlwayTrue;\n        private boolean partAlwayFalse;\n        private boolean constArithmetic;\n        private boolean xor;\n        private boolean bitwise;\n\n        public boolean hasPartAlwayTrue() {\n            return partAlwayTrue;\n        }\n\n        public void setPartAlwayTrue(boolean partAllowTrue) {\n            this.partAlwayTrue = partAllowTrue;\n        }\n\n        public boolean hasPartAlwayFalse() {\n            return partAlwayFalse;\n        }\n\n        public void setPartAlwayFalse(boolean partAlwayFalse) {\n            this.partAlwayFalse = partAlwayFalse;\n        }\n\n        public boolean hasConstArithmetic() {\n            return constArithmetic;\n        }\n\n        public void setConstArithmetic(boolean constArithmetic) {\n            this.constArithmetic = constArithmetic;\n        }\n\n        public boolean hasXor() {\n            return xor;\n        }\n\n        public void setXor(boolean xor) {\n            this.xor = xor;\n        }\n\n        public boolean hasBitwise() {\n            return bitwise;\n        }\n\n        public void setBitwise(boolean bitwise) {\n            this.bitwise = bitwise;\n        }\n\n    }\n\n    private static ThreadLocal<WallConditionContext> wallConditionContextLocal = new ThreadLocal<WallConditionContext>();\n    private static ThreadLocal<WallTopStatementContext> wallTopStatementContextLocal = new ThreadLocal<WallTopStatementContext>();\n\n    public static WallConditionContext getWallConditionContext() {\n        return wallConditionContextLocal.get();\n    }\n\n    public static WallTopStatementContext getWallTopStatementContext() {\n        return wallTopStatementContextLocal.get();\n    }\n\n    public static void clearWallTopStatementContext() {\n        wallTopStatementContextLocal.set(null);\n    }\n\n    public static void initWallTopStatementContext() {\n        wallTopStatementContextLocal.set(new WallTopStatementContext());\n    }\n\n    public static Object getConditionValue(WallVisitor visitor, SQLExpr x, boolean alwayTrueCheck) {\n        final WallConditionContext old = wallConditionContextLocal.get();\n        try {\n            wallConditionContextLocal.set(new WallConditionContext());\n            final Object value = getValue(visitor, x);\n\n            final WallConditionContext current = wallConditionContextLocal.get();\n            WallContext context = WallContext.current();\n            if (context != null) {\n                if (current.hasPartAlwayTrue() || Boolean.TRUE.equals(value)) {\n                    if (!isFirst(x)) {\n                        context.incrementWarnings();\n                    }\n                }\n            }\n\n            if (current.hasPartAlwayTrue()\n                    && !visitor.getConfig().isConditionAndAlwayTrueAllow()) {\n                addViolation(visitor, ErrorCode.ALWAYS_TRUE, \"part alway true condition not allow\", x);\n            }\n\n            if (current.hasPartAlwayFalse()\n                    && !visitor.getConfig().isConditionAndAlwayFalseAllow()) {\n                addViolation(visitor, ErrorCode.ALWAYS_FALSE, \"part alway false condition not allow\", x);\n            }\n\n            if (current.hasConstArithmetic()\n                    && !visitor.getConfig().isConstArithmeticAllow()) {\n                addViolation(visitor, ErrorCode.CONST_ARITHMETIC, \"const arithmetic not allow\", x);\n            }\n\n            if (current.hasXor() && !visitor.getConfig().isConditionOpXorAllow()) {\n                addViolation(visitor, ErrorCode.XOR, \" allow\", x);\n            }\n\n            if (current.hasBitwise() && !visitor.getConfig().isConditionOpBitwiseAllow()) {\n                addViolation(visitor, ErrorCode.BITWISE, \"bitwise operator not allow\", x);\n            }\n\n            return value;\n        } finally {\n            wallConditionContextLocal.set(old);\n        }\n    }\n\n    public static Object getValueFromAttributes(WallVisitor visitor, SQLObject sqlObject) {\n        if (sqlObject == null) {\n            return null;\n        }\n\n        if (visitor != null && visitor.getConfig().isConditionLikeTrueAllow()\n                && sqlObject.getAttributes().containsKey(HAS_TRUE_LIKE)) {\n            return null;\n        }\n        return sqlObject.getAttribute(EVAL_VALUE);\n    }\n\n    public static Object getValue(SQLExpr x) {\n        return getValue(null, x);\n    }\n\n    public static Object getValue(WallVisitor visitor, SQLExpr x) {\n        if (x != null && x.containsAttribute(EVAL_VALUE)) {\n            return getValueFromAttributes(visitor, x);\n        }\n\n        if (x instanceof SQLBinaryOpExpr) {\n            return getValue(visitor, (SQLBinaryOpExpr) x);\n        }\n\n        if (x instanceof SQLBinaryOpExprGroup) {\n            return getValue(visitor, (SQLBinaryOpExprGroup) x);\n        }\n\n        if (x instanceof SQLBooleanExpr) {\n            return ((SQLBooleanExpr) x).getBooleanValue();\n        }\n\n        if (x instanceof SQLNumericLiteralExpr) {\n            return ((SQLNumericLiteralExpr) x).getNumber();\n        }\n\n        if (x instanceof SQLCharExpr) {\n            return ((SQLCharExpr) x).getText();\n        }\n\n        if (x instanceof SQLNCharExpr) {\n            return ((SQLNCharExpr) x).getText();\n        }\n\n        if (x instanceof SQLNotExpr) {\n            Object result = getValue(visitor, ((SQLNotExpr) x).getExpr());\n            if (result instanceof Boolean) {\n                return !((Boolean) result).booleanValue();\n            }\n        }\n\n        if (x instanceof SQLQueryExpr) {\n            if (isSimpleCountTableSource(visitor, ((SQLQueryExpr) x).getSubQuery())) {\n                return Integer.valueOf(1);\n            }\n\n            if (isSimpleCaseTableSource(visitor, ((SQLQueryExpr) x).getSubQuery())) {\n                SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) ((SQLQueryExpr) x).getSubQuery().getQuery();\n                SQLCaseExpr caseExpr = (SQLCaseExpr) queryBlock.getSelectList().get(0).getExpr();\n\n                Object result = getValue(caseExpr);\n\n                if (visitor != null && !visitor.getConfig().isCaseConditionConstAllow()) {\n                    boolean leftIsName = false;\n                    if (x.getParent() instanceof SQLBinaryOpExpr) {\n                        SQLExpr left = ((SQLBinaryOpExpr) x.getParent()).getLeft();\n                        if (left instanceof SQLName) {\n                            leftIsName = true;\n                        }\n                    }\n\n                    if (!leftIsName && result != null) {\n                        addViolation(visitor, ErrorCode.CONST_CASE_CONDITION, \"const case condition\", caseExpr);\n                    }\n                }\n\n                return result;\n            }\n        }\n\n        DbType dbType = null;\n        if (visitor != null) {\n            dbType = visitor.getDbType();\n        }\n\n        if (x instanceof SQLMethodInvokeExpr //\n                || x instanceof SQLBetweenExpr //\n                || x instanceof SQLInListExpr //\n                || x instanceof SQLUnaryExpr //\n        ) {\n            return eval(visitor, dbType, x, Collections.emptyList());\n        }\n\n        if (x instanceof SQLCaseExpr) {\n            if (visitor != null && !visitor.getConfig().isCaseConditionConstAllow()) {\n                SQLCaseExpr caseExpr = (SQLCaseExpr) x;\n\n                boolean leftIsName = false;\n                if (caseExpr.getParent() instanceof SQLBinaryOpExpr) {\n                    SQLExpr left = ((SQLBinaryOpExpr) caseExpr.getParent()).getLeft();\n                    if (left instanceof SQLName) {\n                        leftIsName = true;\n                    }\n                }\n\n                if (!leftIsName && caseExpr.getValueExpr() == null && caseExpr.getItems().size() > 0) {\n                    SQLCaseExpr.Item item = caseExpr.getItems().get(0);\n                    Object conditionVal = getValue(visitor, item.getConditionExpr());\n                    Object itemVal = getValue(visitor, item.getValueExpr());\n                    if (conditionVal instanceof Boolean && itemVal != null) {\n                        addViolation(visitor, ErrorCode.CONST_CASE_CONDITION, \"const case condition\", caseExpr);\n                    }\n                }\n            }\n\n            return eval(visitor, dbType, x, Collections.emptyList());\n        }\n\n        return null;\n    }\n\n    public static Object eval(WallVisitor wallVisitor, DbType dbType, SQLObject sqlObject, List<Object> parameters) {\n        SQLEvalVisitor visitor = SQLEvalVisitorUtils.createEvalVisitor(dbType);\n        visitor.setParameters(parameters);\n        visitor.registerFunction(\"rand\", Nil.instance);\n        visitor.registerFunction(\"sin\", Nil.instance);\n        visitor.registerFunction(\"cos\", Nil.instance);\n        visitor.registerFunction(\"asin\", Nil.instance);\n        visitor.registerFunction(\"acos\", Nil.instance);\n        sqlObject.accept(visitor);\n\n        if (sqlObject instanceof SQLNumericLiteralExpr) {\n            return ((SQLNumericLiteralExpr) sqlObject).getNumber();\n        }\n        return getValueFromAttributes(wallVisitor, sqlObject);\n    }\n\n    public static boolean isSimpleCountTableSource(WallVisitor visitor, SQLTableSource tableSource) {\n        if (!(tableSource instanceof SQLSubqueryTableSource)) {\n            return false;\n        }\n\n        SQLSubqueryTableSource subQuery = (SQLSubqueryTableSource) tableSource;\n\n        return isSimpleCountTableSource(visitor, subQuery.getSelect());\n    }\n\n    public static boolean isSimpleCountTableSource(WallVisitor visitor, SQLSelect select) {\n        SQLSelectQuery query = select.getQuery();\n\n        if (query instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n\n            boolean allawTrueWhere = false;\n\n            if (queryBlock.getWhere() == null) {\n                allawTrueWhere = true;\n            } else {\n                Object whereValue = getValue(visitor, queryBlock.getWhere());\n                if (whereValue instanceof Boolean) {\n                    if (((Boolean) whereValue).booleanValue()) {\n                        allawTrueWhere = true;\n                    } else {\n                        return false;\n                    }\n                }\n            }\n            boolean simpleCount = false;\n            if (queryBlock.getSelectList().size() == 1) {\n                SQLExpr selectItemExpr = queryBlock.getSelectList().get(0).getExpr();\n                if (selectItemExpr instanceof SQLAggregateExpr) {\n                    if (((SQLAggregateExpr) selectItemExpr)\n                            .methodNameHashCode64() == FnvHash.Constants.COUNT) {\n                        simpleCount = true;\n                    }\n                }\n            }\n\n            if (allawTrueWhere && simpleCount) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static boolean isSimpleCaseTableSource(WallVisitor visitor, SQLSelect select) {\n        SQLSelectQuery query = select.getQuery();\n\n        if (query instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n\n            if (queryBlock.getWhere() != null) {\n                Object whereValue = getValue(visitor, queryBlock.getWhere());\n                if (whereValue instanceof Boolean) {\n                    if (!((Boolean) whereValue).booleanValue()) {\n                        return false;\n                    }\n                }\n            }\n            boolean simpleCase = false;\n            if (queryBlock.getSelectList().size() == 1) {\n                SQLExpr selectItemExpr = queryBlock.getSelectList().get(0).getExpr();\n                if (selectItemExpr instanceof SQLCaseExpr) {\n                    simpleCase = true;\n                }\n            }\n\n            if (simpleCase) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    public static void checkFunctionInTableSource(WallVisitor visitor, SQLMethodInvokeExpr x) {\n        final WallTopStatementContext topStatementContext = wallTopStatementContextLocal.get();\n        if (topStatementContext != null && (topStatementContext.fromSysSchema || topStatementContext.fromSysTable)) {\n            return;\n        }\n\n        checkSchema(visitor, x.getOwner());\n\n        String methodName = x.getMethodName().toLowerCase();\n        if (!visitor.getProvider().checkDenyTable(methodName)) {\n            if (isTopStatementWithTableSource(x) || isFirstSelectTableSource(x)) {\n                if (topStatementContext != null) {\n                    topStatementContext.setFromSysSchema(Boolean.TRUE);\n                    clearViolation(visitor);\n                }\n            }\n        }\n    }\n\n    public static void checkFunction(WallVisitor visitor, SQLMethodInvokeExpr x) {\n        final WallTopStatementContext topStatementContext = wallTopStatementContextLocal.get();\n        if (topStatementContext != null && (topStatementContext.fromSysSchema || topStatementContext.fromSysTable)) {\n            return;\n        }\n\n        String methodName = x.getMethodName().toLowerCase();\n        SQLExpr owner = x.getOwner();\n\n        WallProvider provider = visitor.getProvider();\n\n        if (!visitor.getConfig().isFunctionCheck()) {\n            return;\n        }\n\n        WallContext context = WallContext.current();\n        if (context != null) {\n            context.incrementFunctionInvoke(methodName);\n        }\n\n        if (owner != null) {\n            String fullName = (owner.toString() + '.' + methodName).toLowerCase();\n            if (provider.getConfig().getPermitFunctions().contains(fullName)) {\n                return;\n            }\n\n            checkSchema(visitor, owner);\n        }\n\n        if (provider.checkDenyFunction(methodName)) {\n            return;\n        }\n\n        boolean isTopNoneFrom = isTopNoneFromSelect(visitor, x);\n        if (isTopNoneFrom) {\n            return;\n        }\n\n        if (isTopFromDenySchema(visitor, x)) {\n            return;\n        }\n\n        boolean isShow = x.getParent() instanceof MySqlShowGrantsStatement;\n        if (isShow) {\n            return;\n        }\n\n        if (isWhereOrHaving(x) || checkSqlExpr(x)) {\n            addViolation(visitor, ErrorCode.FUNCTION_DENY, \"deny function : \" + methodName, x);\n        }\n\n    }\n\n    public static SQLSelectQueryBlock getQueryBlock(SQLObject x) {\n        if (x == null) {\n            return null;\n        }\n\n        if (x instanceof SQLSelectQueryBlock) {\n            return (SQLSelectQueryBlock) x;\n        }\n\n        SQLObject parent = x.getParent();\n\n        if (parent instanceof SQLExpr) {\n            return getQueryBlock(parent);\n        }\n\n        if (parent instanceof SQLSelectItem) {\n            return getQueryBlock(parent);\n        }\n\n        if (parent instanceof SQLSelectQueryBlock) {\n            return (SQLSelectQueryBlock) parent;\n        }\n\n        return null;\n    }\n\n    public static boolean isTopNoneFromSelect(WallVisitor visitor, SQLObject x) {\n        for (; ; ) {\n            if ((x.getParent() instanceof SQLExpr) || (x.getParent() instanceof Item)) {\n                x = x.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (!(x.getParent() instanceof SQLSelectItem)) {\n            return false;\n        }\n\n        SQLSelectItem item = (SQLSelectItem) x.getParent();\n\n        if (!(item.getParent() instanceof SQLSelectQueryBlock)) {\n            return false;\n        }\n\n        SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) item.getParent();\n        if (!queryBlockFromIsNull(visitor, queryBlock)) {\n            return false;\n        }\n\n        if (!(queryBlock.getParent() instanceof SQLSelect)) {\n            return false;\n        }\n\n        SQLSelect select = (SQLSelect) queryBlock.getParent();\n\n        if (!(select.getParent() instanceof SQLSelectStatement)) {\n            return false;\n        }\n\n        SQLSelectStatement stmt = (SQLSelectStatement) select.getParent();\n\n        return stmt.getParent() == null;\n    }\n\n    private static boolean isTopFromDenySchema(WallVisitor visitor, SQLMethodInvokeExpr x) {\n        SQLObject parent = x.getParent();\n        for (; ; ) {\n            if (parent instanceof SQLExpr || parent instanceof Item || parent instanceof SQLSelectItem) {\n                parent = parent.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (parent instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;\n            if (!(queryBlock.getParent() instanceof SQLSelect)) {\n                return false;\n            }\n\n            SQLSelect select = (SQLSelect) queryBlock.getParent();\n\n            if (!(select.getParent() instanceof SQLSelectStatement)) {\n                return false;\n            }\n\n            SQLSelectStatement stmt = (SQLSelectStatement) select.getParent();\n\n            if (stmt.getParent() != null) {\n                return false;\n            }\n\n            SQLTableSource from = queryBlock.getFrom();\n            if (from instanceof SQLExprTableSource) {\n                SQLExpr fromExpr = ((SQLExprTableSource) from).getExpr();\n                if (fromExpr instanceof SQLName) {\n                    String fromTableName = fromExpr.toString();\n                    return visitor.isDenyTable(fromTableName);\n                }\n            }\n\n            return false;\n        }\n\n        return false;\n    }\n\n    private static boolean checkSchema(WallVisitor visitor, SQLExpr x) {\n        final WallTopStatementContext topStatementContext = wallTopStatementContextLocal.get();\n        if (topStatementContext != null && (topStatementContext.fromSysSchema || topStatementContext.fromSysTable)) {\n            return true;\n        }\n\n        if (x instanceof SQLName) {\n            String owner = ((SQLName) x).getSimpleName();\n            owner = WallVisitorUtils.form(owner);\n            if (isInTableSource(x) && !visitor.getProvider().checkDenySchema(owner)) {\n                if (!isTopStatementWithTableSource(x) && !isFirstSelectTableSource(x) && !isFirstInSubQuery(x)) {\n                    SQLObject parent = x.getParent();\n                    while (parent != null && !(parent instanceof SQLStatement)) {\n                        parent = parent.getParent();\n                    }\n\n                    boolean sameToTopSelectSchema = false;\n                    if (parent instanceof SQLSelectStatement) {\n                        SQLSelectStatement selectStmt = (SQLSelectStatement) parent;\n                        SQLSelectQuery query = selectStmt.getSelect().getQuery();\n                        if (query instanceof SQLSelectQueryBlock) {\n                            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n                            SQLTableSource from = queryBlock.getFrom();\n\n                            while (from instanceof SQLJoinTableSource) {\n                                from = ((SQLJoinTableSource) from).getLeft();\n                            }\n                            if (from instanceof SQLExprTableSource) {\n                                SQLExpr expr = ((SQLExprTableSource) from).getExpr();\n                                if (expr instanceof SQLPropertyExpr) {\n                                    SQLExpr schemaExpr = ((SQLPropertyExpr) expr).getOwner();\n                                    if (schemaExpr instanceof SQLIdentifierExpr) {\n                                        String schema = ((SQLIdentifierExpr) schemaExpr).getName();\n                                        schema = form(schema);\n                                        if (schema.equalsIgnoreCase(owner)) {\n                                            sameToTopSelectSchema = true;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if (!sameToTopSelectSchema) {\n                        addViolation(visitor, ErrorCode.SCHEMA_DENY, \"deny schema : \" + owner, x);\n                    }\n                } else {\n                    if (topStatementContext != null) {\n                        topStatementContext.setFromSysSchema(Boolean.TRUE);\n                        clearViolation(visitor);\n                    }\n                }\n                return true;\n            }\n\n            if (visitor.getConfig().isDenyObjects(owner)) {\n                addViolation(visitor, ErrorCode.OBJECT_DENY, \"deny object : \" + owner, x);\n                return true;\n            }\n        }\n\n        // if (ownerExpr instanceof SQLPropertyExpr) {\n        if (x instanceof SQLPropertyExpr) {\n            return checkSchema(visitor, ((SQLPropertyExpr) x).getOwner());\n        }\n\n        return true;\n    }\n\n    private static boolean isInTableSource(SQLObject x) {\n        for (; ; ) {\n            if (x instanceof SQLExpr) {\n                x = x.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (x instanceof SQLExprTableSource) {\n            return true;\n        }\n        return false;\n    }\n\n    private static boolean isFirstInSubQuery(SQLObject x) {\n        for (; ; ) {\n            if (x instanceof SQLExpr) {\n                x = x.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (!(x instanceof SQLExprTableSource)) {\n            return false;\n        }\n\n        SQLSelect sqlSelect = null;\n        SQLObject parent = x.getParent();\n        while (parent != null) {\n            if (parent instanceof SQLSelect) {\n                sqlSelect = (SQLSelect) parent;\n                break;\n            }\n\n            x = parent;\n            parent = x.getParent();\n        }\n\n        if (sqlSelect == null) {\n            return false;\n        }\n\n        parent = sqlSelect.getParent();\n        if (!(parent instanceof SQLInSubQueryExpr && isFirst(parent))) {\n            return false;\n        }\n\n        SQLInSubQueryExpr sqlInSubQueryExpr = (SQLInSubQueryExpr) parent;\n        if (!(sqlInSubQueryExpr.getParent() instanceof SQLSelectQueryBlock)) {\n            return false;\n        }\n\n        SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) sqlInSubQueryExpr.getParent();\n        if (!(queryBlock.getParent() instanceof SQLSelect)) {\n            return false;\n        }\n\n        SQLSelect select = (SQLSelect) queryBlock.getParent();\n        if (!(select.getParent() instanceof SQLSelectStatement)) {\n            return false;\n        }\n\n        SQLSelectStatement stmt = (SQLSelectStatement) select.getParent();\n        return stmt.getParent() == null;\n    }\n\n    private static boolean isFirstSelectTableSource(SQLObject x) {\n        for (; ; ) {\n            if (x instanceof SQLExpr) {\n                x = x.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (!(x instanceof SQLExprTableSource)) {\n            return false;\n        }\n\n        SQLSelectQueryBlock queryBlock = null;\n        SQLObject parent = x.getParent();\n        while (parent != null) {\n            // if (parent instanceof SQLJoinTableSource) {\n            // SQLJoinTableSource join = (SQLJoinTableSource) parent;\n            // if (join.getRight() == x && hasTableSource(join.getLeft())) {\n            // return false;\n            // }\n            // }\n\n            if (parent instanceof SQLSelectQueryBlock) {\n                queryBlock = (SQLSelectQueryBlock) parent;\n                break;\n            }\n\n            x = parent;\n            parent = x.getParent();\n        }\n\n        if (queryBlock == null) {\n            return false;\n        }\n\n        boolean isWhereQueryExpr = false;\n        boolean isSelectItem = false;\n        do {\n            x = parent;\n            parent = parent.getParent();\n            if (parent instanceof SQLUnionQuery) {\n                SQLUnionQuery union = (SQLUnionQuery) parent;\n                if (union.getRight() == x && hasTableSource(union.getLeft())) {\n                    return false;\n                }\n            } else if (parent instanceof SQLQueryExpr || parent instanceof SQLInSubQueryExpr\n                    || parent instanceof SQLExistsExpr) {\n                isWhereQueryExpr = isWhereOrHaving(parent);\n            } else if (parent instanceof SQLSelectItem) {\n                isSelectItem = true;\n            } else if ((isWhereQueryExpr || isSelectItem) && parent instanceof SQLSelectQueryBlock) {\n                if (hasTableSource((SQLSelectQueryBlock) parent)) {\n                    return false;\n                }\n            }\n\n        } while (parent != null);\n\n        return true;\n    }\n\n    private static boolean hasTableSource(SQLSelectQuery x) {\n        if (x instanceof SQLUnionQuery) {\n            SQLUnionQuery union = (SQLUnionQuery) x;\n            return hasTableSource(union.getLeft()) || hasTableSource(union.getRight());\n        } else if (x instanceof SQLSelectQueryBlock) {\n            return hasTableSource(((SQLSelectQueryBlock) x).getFrom());\n        }\n\n        return false;\n    }\n\n    private static boolean hasTableSource(SQLTableSource x) {\n        if (x == null) {\n            return false;\n        }\n\n        if (x instanceof SQLExprTableSource) {\n            SQLExpr fromExpr = ((SQLExprTableSource) x).getExpr();\n            if (fromExpr instanceof SQLName) {\n                String name = fromExpr.toString();\n                name = form(name);\n                if (name.equalsIgnoreCase(\"DUAL\")) {\n                    return false;\n                }\n            }\n            return true;\n        } else if (x instanceof SQLJoinTableSource) {\n            SQLJoinTableSource join = (SQLJoinTableSource) x;\n            return hasTableSource(join.getLeft()) || hasTableSource(join.getRight());\n        } else if (x instanceof SQLSubqueryTableSource) {\n            return hasTableSource(((SQLSubqueryTableSource) x).getSelect().getQuery());\n        }\n\n        return false;\n    }\n\n    private static boolean isTopStatementWithTableSource(SQLObject x) {\n        for (; ; ) {\n            if (x instanceof SQLExpr) {\n                x = x.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (x instanceof SQLExprTableSource) {\n            x = x.getParent();\n\n            if (x instanceof SQLStatement) {\n                x = x.getParent();\n                if (x == null) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    private static boolean isTopSelectItem(SQLObject x) {\n        for (; ; ) {\n            if ((x.getParent() instanceof SQLExpr) || (x.getParent() instanceof Item)) {\n                x = x.getParent();\n            } else {\n                break;\n            }\n        }\n\n        if (!(x.getParent() instanceof SQLSelectItem)) {\n            return false;\n        }\n\n        SQLSelectItem item = (SQLSelectItem) x.getParent();\n        return isTopSelectStatement(item.getParent());\n    }\n\n    private static boolean isTopSelectStatement(SQLObject x) {\n        if (!(x instanceof SQLSelectQueryBlock)) {\n            return false;\n        }\n\n        SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x;\n        if (!(queryBlock.getParent() instanceof SQLSelect)) {\n            return false;\n        }\n\n        SQLSelect select = (SQLSelect) queryBlock.getParent();\n        if (!(select.getParent() instanceof SQLSelectStatement)) {\n            return false;\n        }\n\n        SQLSelectStatement stmt = (SQLSelectStatement) select.getParent();\n        return stmt.getParent() == null;\n    }\n\n    public static boolean isTopSelectOutFile(MySqlOutFileExpr x) {\n        if (!(x.getParent() instanceof SQLExprTableSource)) {\n            return false;\n        }\n        SQLExprTableSource tableSource = (SQLExprTableSource) x.getParent();\n        return isTopSelectStatement(tableSource.getParent());\n    }\n\n    public static boolean check(WallVisitor visitor, SQLExprTableSource x) {\n        final WallTopStatementContext topStatementContext = wallTopStatementContextLocal.get();\n\n        SQLExpr expr = x.getExpr();\n        if (expr instanceof SQLPropertyExpr) {\n            boolean checkResult = checkSchema(visitor, ((SQLPropertyExpr) expr).getOwner());\n            if (!checkResult) {\n                return false;\n            }\n        }\n\n        if (expr instanceof SQLName) {\n            String tableName = ((SQLName) expr).getSimpleName();\n\n            WallContext context = WallContext.current();\n            if (context != null) {\n                WallSqlTableStat tableStat = context.getTableStat(tableName);\n                if (tableStat != null) {\n                    SQLObject parent = x.getParent();\n\n                    while (parent instanceof SQLTableSource) {\n                        parent = parent.getParent();\n                    }\n\n                    if (parent instanceof SQLSelectQueryBlock) {\n                        SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;\n                        if (x == queryBlock.getInto()) {\n                            tableStat.incrementSelectIntoCount();\n                        } else {\n                            tableStat.incrementSelectCount();\n                        }\n                    } else if (parent instanceof SQLTruncateStatement) {\n                        tableStat.incrementTruncateCount();\n                    } else if (parent instanceof SQLInsertStatement) {\n                        tableStat.incrementInsertCount();\n                    } else if (parent instanceof SQLDeleteStatement) {\n                        tableStat.incrementDeleteCount();\n                    } else if (parent instanceof SQLUpdateStatement) {\n                        tableStat.incrementUpdateCount();\n                    } else if (parent instanceof SQLReplaceStatement) {\n                        tableStat.incrementReplaceCount();\n                    }\n                }\n            }\n\n            if (topStatementContext != null && (topStatementContext.fromSysSchema || topStatementContext.fromSysTable)) {\n                return true;\n            }\n\n            if (visitor.isDenyTable(tableName)\n                    && !(topStatementContext != null && topStatementContext.fromPermitTable())) {\n                if (isTopStatementWithTableSource(x) || isFirstSelectTableSource(x)) {\n                    if (topStatementContext != null) {\n                        topStatementContext.setFromSysTable(Boolean.TRUE);\n                        clearViolation(visitor);\n                    }\n                    return false;\n                }\n\n                boolean isTopNoneFrom = isTopNoneFromSelect(visitor, x);\n                if (isTopNoneFrom) {\n                    return false;\n                }\n\n                addViolation(visitor, ErrorCode.TABLE_DENY, \"deny table : \" + tableName, x);\n                return false;\n            }\n\n            if (visitor.getConfig().getPermitTables().contains(tableName)) {\n                if (isFirstSelectTableSource(x)) {\n                    if (topStatementContext != null) {\n                        topStatementContext.setFromPermitTable(Boolean.TRUE);\n                    }\n                    return false;\n                }\n            }\n        }\n\n        return true;\n    }\n\n    private static void addViolation(WallVisitor visitor, int errorCode, String message, SQLObject x) {\n        visitor.addViolation(new IllegalSQLObjectViolation(errorCode, message, visitor.toSQL(x)));\n    }\n\n    private static void clearViolation(WallVisitor visitor) {\n        visitor.getViolations().clear();\n    }\n\n    public static boolean checkUnion(WallVisitor visitor, SQLUnionQuery x) {\n        if (x.getRelations().size() > 2) {\n            for (int i = 0; i < x.getRelations().size(); i++) {\n                SQLSelectQuery item = x.getRelations().get(i);\n                if (item instanceof SQLSelectQueryBlock && queryBlockFromIsNull(visitor, item)) {\n                    continue;\n                }\n\n                item.accept(visitor);\n            }\n            return false;\n        }\n\n        {\n            SQLUnionOperator operator = x.getOperator();\n            SQLSelectQuery left = x.getLeft();\n            SQLSelectQuery right = x.getRight();\n\n            boolean bracket = x.isParenthesized() && !(x.getParent() instanceof SQLUnionQueryTableSource);\n\n            if ((!bracket)\n                    && left instanceof SQLUnionQuery\n                    && ((SQLUnionQuery) left).getOperator() == operator\n                    && !right.isParenthesized()\n                    && x.getOrderBy() == null) {\n                SQLUnionQuery leftUnion = (SQLUnionQuery) left;\n\n                List<SQLSelectQuery> rights = new ArrayList<SQLSelectQuery>();\n                rights.add(right);\n\n                for (; ; ) {\n                    SQLSelectQuery leftLeft = leftUnion.getLeft();\n                    SQLSelectQuery leftRight = leftUnion.getRight();\n\n                    if ((!leftUnion.isParenthesized())\n                            && leftUnion.getOrderBy() == null\n                            && (!leftLeft.isParenthesized())\n                            && (!leftRight.isParenthesized())\n                            && leftLeft instanceof SQLUnionQuery\n                            && ((SQLUnionQuery) leftLeft).getOperator() == operator) {\n                        rights.add(leftRight);\n                        leftUnion = (SQLUnionQuery) leftLeft;\n                        continue;\n                    } else {\n                        rights.add(leftRight);\n                        rights.add(leftLeft);\n                    }\n                    break;\n                }\n\n                for (int i = rights.size() - 1; i >= 0; i--) {\n                    SQLSelectQuery item = rights.get(i);\n\n                    if (item instanceof SQLSelectQueryBlock && queryBlockFromIsNull(visitor, item)) {\n                        continue;\n                    }\n\n                    item.accept(visitor);\n                }\n                return false;\n            }\n        }\n\n        if (x.getOperator() == SQLUnionOperator.MINUS && !visitor.getConfig().isMinusAllow()) {\n            addViolation(visitor, ErrorCode.INTERSET_NOT_ALLOW, \"minus not allow\", x);\n            return true;\n        }\n\n        if (x.getOperator() == SQLUnionOperator.INTERSECT && !visitor.getConfig().isIntersectAllow()) {\n            addViolation(visitor, ErrorCode.INTERSET_NOT_ALLOW, \"intersect not allow\", x);\n            return true;\n        }\n\n        if (!WallVisitorUtils.queryBlockFromIsNull(visitor, x.getLeft())\n                && WallVisitorUtils.queryBlockFromIsNull(visitor, x.getRight())) {\n            boolean isTopUpdateStatement = false;\n            boolean isTopInsertStatement = false;\n            SQLObject selectParent = x.getParent();\n            while (selectParent instanceof SQLSelectQuery //\n                    || selectParent instanceof SQLJoinTableSource //\n                    || selectParent instanceof SQLSubqueryTableSource //\n                    || selectParent instanceof SQLSelect) {\n                selectParent = selectParent.getParent();\n            }\n\n            if (selectParent instanceof SQLUpdateStatement) {\n                isTopUpdateStatement = true;\n            }\n\n            if (selectParent instanceof SQLInsertStatement) {\n                isTopInsertStatement = true;\n            }\n\n            if (isTopUpdateStatement || isTopInsertStatement) {\n                return true;\n            }\n\n            if (x.getLeft() instanceof SQLSelectQueryBlock) {\n                SQLSelectQueryBlock left = (SQLSelectQueryBlock) x.getLeft();\n                SQLTableSource tableSource = left.getFrom();\n                if (left.getWhere() == null && tableSource != null && tableSource instanceof SQLExprTableSource) {\n                    return true;\n                }\n            }\n\n            WallContext context = WallContext.current();\n            if (context != null) {\n                context.incrementUnionWarnings();\n            }\n\n            if (((x.getOperator() == SQLUnionOperator.UNION || x.getOperator() == SQLUnionOperator.UNION_ALL || x.getOperator() == SQLUnionOperator.DISTINCT)\n                    && visitor.getConfig().isSelectUnionCheck() && visitor.isSqlEndOfComment())\n                    || (x.getOperator() == SQLUnionOperator.MINUS && visitor.getConfig().isSelectMinusCheck())\n                    || (x.getOperator() == SQLUnionOperator.INTERSECT && visitor.getConfig().isSelectIntersectCheck())\n                    || (x.getOperator() == SQLUnionOperator.EXCEPT && visitor.getConfig().isSelectExceptCheck())) {\n                addViolation(visitor, ErrorCode.UNION,\n                        x.getOperator().toString() + \" query not contains 'from clause'\", x);\n            }\n        }\n\n        return true;\n    }\n\n    public static boolean queryBlockFromIsNull(WallVisitor visitor, SQLSelectQuery query) {\n        return queryBlockFromIsNull(visitor, query, true);\n    }\n\n    public static boolean queryBlockFromIsNull(WallVisitor visitor, SQLSelectQuery query, boolean checkSelectConst) {\n        if (query instanceof SQLSelectQueryBlock) {\n            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query;\n            SQLTableSource from = queryBlock.getFrom();\n\n            if (queryBlock.getSelectList().size() < 1) {\n                return false;\n            }\n\n            if (from == null) {\n                boolean itemIsConst = true;\n                boolean itemHasAlias = false;\n                for (SQLSelectItem item : queryBlock.getSelectList()) {\n                    if (item.getExpr() instanceof SQLIdentifierExpr || item.getExpr() instanceof SQLPropertyExpr) {\n                        itemIsConst = false;\n                        break;\n                    }\n                    if (item.getAlias() != null) {\n                        itemHasAlias = true;\n                        break;\n                    }\n                }\n                if (itemIsConst && !itemHasAlias) {\n                    return true;\n                } else {\n                    return false;\n                }\n            }\n\n            if (from instanceof SQLExprTableSource) {\n                SQLExpr fromExpr = ((SQLExprTableSource) from).getExpr();\n                if (fromExpr instanceof SQLName) {\n                    String name = fromExpr.toString();\n\n                    name = form(name);\n\n                    if (name.equalsIgnoreCase(\"DUAL\")) {\n                        return true;\n                    }\n                }\n            }\n\n            if (queryBlock.getSelectList().size() == 1\n                    && queryBlock.getSelectList().get(0).getExpr() instanceof SQLAllColumnExpr) {\n                if (from instanceof SQLSubqueryTableSource) {\n                    SQLSelectQuery subQuery = ((SQLSubqueryTableSource) from).getSelect().getQuery();\n                    if (queryBlockFromIsNull(visitor, subQuery)) {\n                        return true;\n                    }\n                }\n            }\n\n            if (checkSelectConst) {\n                SQLExpr where = queryBlock.getWhere();\n                if (where != null) {\n                    Object whereValue = getValue(visitor, where);\n                    if (Boolean.TRUE.equals(whereValue)) {\n                        boolean allIsConst = true;\n                        for (SQLSelectItem item : queryBlock.getSelectList()) {\n                            if (getValue(visitor, item.getExpr()) == null) {\n                                allIsConst = false;\n                                break;\n                            }\n                        }\n                        if (allIsConst) {\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n\n        return false;\n    }\n\n    public static String form(String name) {\n        if (name.startsWith(\"\\\"\") && name.endsWith(\"\\\"\")) {\n            name = name.substring(1, name.length() - 1);\n        }\n\n        if (name.startsWith(\"'\") && name.endsWith(\"'\")) {\n            name = name.substring(1, name.length() - 1);\n        }\n\n        if (name.startsWith(\"`\") && name.endsWith(\"`\")) {\n            name = name.substring(1, name.length() - 1);\n        }\n\n        name = name.toLowerCase();\n        return name;\n    }\n\n    public static void loadResource(Set<String> names, String resource) {\n        try {\n            boolean hasResource = false;\n            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();\n            if (classLoader != null) {\n                Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources(resource);\n                while (e.hasMoreElements()) {\n                    URL url = e.nextElement();\n                    InputStream in = null;\n                    try {\n                        in = url.openStream();\n                        readFromInputStream(names, in);\n\n                        hasResource = true;\n                    } finally {\n                        JdbcUtils.close(in);\n                    }\n                }\n            }\n\n            // for aliyun odps\n            if (!hasResource) {\n                if (!resource.startsWith(\"/\")) {\n                    resource = \"/\" + resource;\n                }\n\n                InputStream in = null;\n                try {\n                    in = WallVisitorUtils.class.getResourceAsStream(resource);\n                    if (in != null) {\n                        readFromInputStream(names, in);\n                    }\n                } finally {\n                    JdbcUtils.close(in);\n                }\n            }\n        } catch (IOException e) {\n            LOG.error(\"load oracle deny tables errror\", e);\n        }\n    }\n\n    private static void readFromInputStream(Set<String> names, InputStream in) throws IOException {\n        BufferedReader reader = null;\n        try {\n            reader = new BufferedReader(new InputStreamReader(in));\n            for (; ; ) {\n                String line = reader.readLine();\n                if (line == null) {\n                    break;\n                }\n                line = line.trim();\n                if (line.length() > 0) {\n                    line = line.toLowerCase();\n                    names.add(line);\n                }\n            }\n        } finally {\n            JdbcUtils.close(reader);\n        }\n    }\n\n    public static void preVisitCheck(WallVisitor visitor, SQLObject x) {\n        WallConfig config = visitor.getProvider().getConfig();\n\n        if (!(x instanceof SQLStatement)) {\n            return;\n        }\n\n        boolean allow = false;\n        int errorCode;\n        String denyMessage;\n        if (x instanceof SQLCommentStatement) {\n            return;\n        } else if (x instanceof SQLInsertStatement) {\n            allow = config.isInsertAllow();\n            denyMessage = \"insert not allow\";\n            errorCode = ErrorCode.INSERT_NOT_ALLOW;\n        } else if (x instanceof SQLSelectStatement) {\n            allow = true;\n            denyMessage = \"select not allow\";\n            errorCode = ErrorCode.SELECT_NOT_ALLOW;\n        } else if (x instanceof SQLDeleteStatement) {\n            allow = config.isDeleteAllow();\n            denyMessage = \"delete not allow\";\n            errorCode = ErrorCode.DELETE_NOT_ALLOW;\n        } else if (x instanceof SQLUpdateStatement) {\n            allow = config.isUpdateAllow();\n            denyMessage = \"update not allow\";\n            errorCode = ErrorCode.UPDATE_NOT_ALLOW;\n        } else if (x instanceof OracleMultiInsertStatement\n                || x instanceof OracleMultiInsertStatement.InsertIntoClause) {\n            allow = true;\n            denyMessage = \"multi-insert not allow\";\n            errorCode = ErrorCode.INSERT_NOT_ALLOW;\n        } else if (x instanceof SQLMergeStatement) {\n            allow = config.isMergeAllow();\n            denyMessage = \"merge not allow\";\n            errorCode = ErrorCode.MERGE_NOT_ALLOW;\n        } else if (x instanceof SQLCallStatement\n                || x instanceof SQLServerExecStatement\n                || x instanceof OracleExecuteImmediateStatement) {\n            allow = config.isCallAllow();\n            denyMessage = \"call not allow\";\n            errorCode = ErrorCode.CALL_NOT_ALLOW;\n        } else if (x instanceof SQLTruncateStatement) {\n            allow = config.isTruncateAllow();\n            denyMessage = \"truncate not allow\";\n            errorCode = ErrorCode.TRUNCATE_NOT_ALLOW;\n        } else if (x instanceof SQLCreateStatement) {\n            allow = config.isCreateTableAllow();\n            denyMessage = \"create table not allow\";\n            errorCode = ErrorCode.CREATE_TABLE_NOT_ALLOW;\n        } else if (x instanceof MySqlRenameTableStatement) {\n            allow = config.isRenameTableAllow();\n            denyMessage = \"rename table not allow\";\n            errorCode = ErrorCode.RENAME_TABLE_NOT_ALLOW;\n        } else if (x instanceof SQLAlterStatement) {\n            allow = config.isAlterTableAllow();\n            denyMessage = \"alter table not allow\";\n            errorCode = ErrorCode.ALTER_TABLE_NOT_ALLOW;\n        } else if (x instanceof SQLDropStatement) {\n            allow = config.isDropTableAllow();\n            denyMessage = \"drop table not allow\";\n            errorCode = ErrorCode.DROP_TABLE_NOT_ALLOW;\n        } else if (x instanceof SQLSetStatement) {\n            allow = config.isSetAllow();\n            denyMessage = \"set not allow\";\n            errorCode = ErrorCode.SET_NOT_ALLOW;\n        } else if (x instanceof SQLReplaceStatement) {\n            allow = config.isReplaceAllow();\n            denyMessage = \"replace not allow\";\n            errorCode = ErrorCode.REPLACE_NOT_ALLOW;\n        } else if (x instanceof SQLDescribeStatement\n                || (x instanceof MySqlExplainStatement && ((MySqlExplainStatement) x).isDescribe())) {\n            allow = config.isDescribeAllow();\n            denyMessage = \"describe not allow\";\n            errorCode = ErrorCode.DESC_NOT_ALLOW;\n        } else if (x instanceof SQLShowStatement) {\n            allow = config.isShowAllow();\n            denyMessage = \"show not allow\";\n            errorCode = ErrorCode.SHOW_NOT_ALLOW;\n        } else if (x instanceof SQLCommitStatement) {\n            allow = config.isCommitAllow();\n            denyMessage = \"commit not allow\";\n            errorCode = ErrorCode.COMMIT_NOT_ALLOW;\n        } else if (x instanceof SQLRollbackStatement) {\n            allow = config.isRollbackAllow();\n            denyMessage = \"rollback not allow\";\n            errorCode = ErrorCode.ROLLBACK_NOT_ALLOW;\n        } else if (x instanceof SQLUseStatement) {\n            allow = config.isUseAllow();\n            denyMessage = \"use not allow\";\n            errorCode = ErrorCode.USE_NOT_ALLOW;\n        } else if (x instanceof MySqlHintStatement) {\n            allow = config.isHintAllow();\n            denyMessage = \"hint not allow\";\n            errorCode = ErrorCode.HINT_NOT_ALLOW;\n        } else if (x instanceof SQLLockTableStatement) {\n            allow = config.isLockTableAllow();\n            denyMessage = \"lock table not allow\";\n            errorCode = ErrorCode.LOCK_TABLE_NOT_ALLOW;\n        } else if (x instanceof SQLStartTransactionStatement) {\n            allow = config.isStartTransactionAllow();\n            denyMessage = \"start transaction not allow\";\n            errorCode = ErrorCode.START_TRANSACTION_NOT_ALLOW;\n        } else if (x instanceof SQLBlockStatement) {\n            allow = config.isBlockAllow();\n            denyMessage = \"block statement not allow\";\n            errorCode = ErrorCode.BLOCK_NOT_ALLOW;\n        } else if (x instanceof SQLExplainStatement\n                || x instanceof MySqlOptimizeStatement\n                || x instanceof SQLRefreshMaterializedViewStatement\n        ) {\n            allow = true;\n            errorCode = 0;\n            denyMessage = null;\n        } else {\n            allow = config.isNoneBaseStatementAllow();\n            errorCode = ErrorCode.NONE_BASE_STATEMENT_NOT_ALLOW;\n            denyMessage = x.getClass() + \" not allow\";\n        }\n\n        if (!allow) {\n            addViolation(visitor, errorCode, denyMessage, x);\n        }\n    }\n\n    public static void check(WallVisitor visitor, SQLCommentHint x) {\n        if (!visitor.getConfig().isHintAllow()) {\n            addViolation(visitor, ErrorCode.EVIL_HINTS, \"hint not allow\", x);\n            return;\n        }\n\n        String text = x.getText();\n        text = text.trim();\n        if (text.startsWith(\"!\")) {\n            text = text.substring(1).trim();\n        }\n\n        if (text.length() == 0) {\n            return;\n        }\n\n        int pos = 0;\n        for (; pos < text.length(); pos++) {\n            char ch = text.charAt(pos);\n            if (ch >= '0' && ch <= '9') {\n                continue;\n            } else {\n                break;\n            }\n        }\n\n        if (pos == 5) {\n            text = text.substring(5);\n            text = text.trim();\n        }\n\n        text = text.toUpperCase();\n\n        boolean isWhite = false;\n        for (String hint : whiteHints) {\n            if (text.equals(hint)) {\n                isWhite = true;\n                break;\n            }\n        }\n\n        if (!isWhite) {\n            if (text.startsWith(\"FORCE INDEX\") || text.startsWith(\"IGNORE INDEX\")) {\n                isWhite = true;\n            }\n        }\n\n        if (!isWhite) {\n            if (text.startsWith(\"SET\")) {\n                SQLStatementParser parser = new MySqlStatementParser(text);\n                List<SQLStatement> statementList = parser.parseStatementList();\n                if (statementList != null && statementList.size() > 0) {\n                    SQLStatement statement = statementList.get(0);\n                    if (statement instanceof SQLSetStatement) {\n                        isWhite = true;\n                    }\n                }\n            }\n        }\n\n        if ((!isWhite) && visitor.getDbType() == DbType.oracle) {\n            if (text.startsWith(\"+\")) {\n                isWhite = true;\n            }\n        }\n\n        if (!isWhite) {\n            addViolation(visitor, ErrorCode.EVIL_HINTS, \"hint not allow\", x);\n        }\n    }\n\n    public static void check(WallVisitor visitor, SQLJoinTableSource x) {\n        SQLExpr condition = x.getCondition();\n        if (condition instanceof SQLName) {\n            addViolation(visitor, ErrorCode.INVALID_JOIN_CONDITION, \"invalid join condition\", x);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/violation/ErrorCode.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.violation;\n\npublic interface ErrorCode {\n    public static final int SYNTAX_ERROR = 1001;\n    public static final int SELECT_NOT_ALLOW = 1002;\n    public static final int SELECT_INTO_NOT_ALLOW = 1003;\n    public static final int INSERT_NOT_ALLOW = 1004;\n    public static final int DELETE_NOT_ALLOW = 1005;\n    public static final int UPDATE_NOT_ALLOW = 1006;\n    public static final int MINUS_NOT_ALLOW = 1007;\n    public static final int INTERSET_NOT_ALLOW = 1008;\n    public static final int MERGE_NOT_ALLOW = 1009;\n    public static final int REPLACE_NOT_ALLOW = 1010;\n\n    public static final int HINT_NOT_ALLOW = 1400;\n\n    public static final int CALL_NOT_ALLOW = 1300;\n    public static final int COMMIT_NOT_ALLOW = 1301;\n    public static final int ROLLBACK_NOT_ALLOW = 1302;\n    public static final int START_TRANSACTION_NOT_ALLOW = 1303;\n    public static final int BLOCK_NOT_ALLOW = 1304;\n\n    public static final int SET_NOT_ALLOW = 1200;\n    public static final int DESC_NOT_ALLOW = 1201;\n    public static final int SHOW_NOT_ALLOW = 1202;\n    public static final int USE_NOT_ALLOW = 1203;\n\n    public static final int NONE_BASE_STATEMENT_NOT_ALLOW = 1999;\n\n    public static final int TRUNCATE_NOT_ALLOW = 1100;\n    public static final int CREATE_TABLE_NOT_ALLOW = 1101;\n    public static final int ALTER_TABLE_NOT_ALLOW = 1102;\n    public static final int DROP_TABLE_NOT_ALLOW = 1103;\n    public static final int COMMENT_STATEMENT_NOT_ALLOW = 1104;\n    public static final int RENAME_TABLE_NOT_ALLOW = 1105;\n    public static final int LOCK_TABLE_NOT_ALLOW = 1106;\n\n    public static final int LIMIT_ZERO = 2200;\n    public static final int MULTI_STATEMENT = 2201;\n\n    public static final int FUNCTION_DENY = 2001;\n    public static final int SCHEMA_DENY = 2002;\n    public static final int VARIANT_DENY = 2003;\n    public static final int TABLE_DENY = 2004;\n    public static final int OBJECT_DENY = 2005;\n\n    public static final int ALWAYS_TRUE = 2100;\n    public static final int CONST_ARITHMETIC = 2101;\n    public static final int XOR = 2102;\n    public static final int BITWISE = 2103;\n    public static final int NONE_CONDITION = 2104;\n    public static final int LIKE_NUMBER = 2105;\n    public static final int EMPTY_QUERY_HAS_CONDITION = 2106;\n    public static final int DOUBLE_CONST_CONDITION = 2107;\n    public static final int SAME_CONST_LIKE = 2108;\n    public static final int CONST_CASE_CONDITION = 2109;\n    public static final int EVIL_HINTS = 2110;\n    public static final int EVIL_NAME = 2111;\n    public static final int EVIL_CONCAT = 2112;\n    public static final int ALWAYS_FALSE = 2113;\n\n    public static final int NOT_PARAMETERIZED = 2200;\n    public static final int MULTI_TENANT = 2201;\n\n    public static final int INTO_OUTFILE = 3000;\n\n    public static final int READ_ONLY = 4000;\n    public static final int UNION = 5000;\n    public static final int INVALID_JOIN_CONDITION = 6000;\n\n    public static final int COMPOUND = 8000;\n\n    public static final int UPDATE_CHECK_FAIL = 9000;\n\n    public static final int OTHER = 9999;\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/violation/IllegalSQLObjectViolation.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.violation;\n\nimport com.alibaba.druid.wall.Violation;\n\npublic class IllegalSQLObjectViolation implements Violation {\n    private final String message;\n    private final String sqlPart;\n    private final int errorCode;\n\n    public IllegalSQLObjectViolation(int errorCode, String message, String sqlPart) {\n        this.errorCode = errorCode;\n        this.message = message;\n        this.sqlPart = sqlPart;\n    }\n\n    public String getSqlPart() {\n        return sqlPart;\n    }\n\n    public String toString() {\n        return this.sqlPart;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    @Override\n    public int getErrorCode() {\n        return errorCode;\n    }\n\n}\n"
  },
  {
    "path": "core/src/main/java/com/alibaba/druid/wall/violation/SyntaxErrorViolation.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.wall.violation;\n\nimport com.alibaba.druid.wall.Violation;\n\npublic class SyntaxErrorViolation implements Violation {\n    private final Exception exception;\n\n    private final String sql;\n\n    public SyntaxErrorViolation(Exception exception, String sql) {\n        super();\n        this.exception = exception;\n        this.sql = sql;\n    }\n\n    public String toString() {\n        return this.sql;\n    }\n\n    public Exception getException() {\n        return exception;\n    }\n\n    public String getSql() {\n        return sql;\n    }\n\n    public String getMessage() {\n        if (exception == null) {\n            return \"syntax error\";\n        }\n\n        return \"syntax error: \" + exception.getMessage();\n    }\n\n    @Override\n    public int getErrorCode() {\n        return ErrorCode.SYNTAX_ERROR;\n    }\n}\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/athena/dialect.properties",
    "content": "quote=',\"\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/bigquery/builtin_datatypes",
    "content": "BOOL\nBYTES\nDATE\nDATETIME\nTIME\nTIMESTAMP\nINTERVAL\nRANGE\nSTRING\nINT64\nNUMERIC\nBIGNUMERIC\nFLOAT64\nARRAY\nSTRUCT\nGEOGRAPHY\nJSON"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/bigquery/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/clickhouse/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/doris/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/doris/keywords",
    "content": "ADD\nALL\nALTER\nANALYZE\nAND\nARRAY\nAS\nASC\nBETWEEN\nBIGINT\nBITMAP\nBOTH\nBY\nCASE\nCHAR\nCHARACTER\nCHECK\nCOLLATE\nCOLUMN\nCOMPACTION\nCONVERT\nCREATE\nCROSS\nCUBE\nCURRENT_DATE\nCURRENT_TIME\nCURRENT_TIMESTAMP\nCURRENT_USER\nCURRENT_ROLE\nDATABASE\nDATABASES\nDECIMAL\nDECIMALV2\nDECIMAL32\nDECIMAL64\nDECIMAL128\nDEFAULT\nDELETE\nDENSE_RANK\nDESC\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nDUAL\nDEFERRED\nELSE\nEXCEPT\nEXISTS\nEXPLAIN\nFALSE\nFIRST_VALUE\nFLOAT\nFOR\nFORCE\nFROM\nFULL\nFUNCTION\nGRANT\nGROUP\nGROUPS\nGROUPING\nGROUPING_ID\nHAVING\nHLL\nHOST\nIF\nIGNORE\nIN\nINDEX\nINFILE\nINNER\nINSERT\nINT\nINTEGER\nINTERSECT\nINTO\nIS\nIMMEDIATE\nJOIN\nJSON\nKEY\nKEYS\nKILL\nLAG\nLARGEINT\nLAST_VALUE\nLATERAL\nLEAD\nLEFT\nLIKE\nLIMIT\nLOAD\nLOCALTIME\nLOCALTIMESTAMP\nMAXVALUE\nMINUS\nMOD\nNTILE\nNOT\nNULL\nON\nOR\nORDER\nOUTER\nOUTFILE\nOVER\nPARTITION\nPERCENTILE\nPRIMARY\nPROCEDURE\nQUALIFY\nRANGE\nRANK\nREAD\nREGEXP\nRELEASE\nRENAME\nREPLACE\nREVOKE\nRIGHT\nRLIKE\nROW\nROWS\nROW_NUMBER\nSCHEMA\nSCHEMAS\nSELECT\nSET\nSET_VAR\nSHOW\nSMALLINT\nSYSTEM\nTABLE\nTERMINATED\nTEXT\nTHEN\nTINYINT\nTO\nTRUE\nUNION\nUNIQUE\nUNSIGNED\nUPDATE\nUSE\nUSING\nVALUES\nVARCHAR\nWHEN\nWHERE\nWITH"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/h2/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/hive/alias_keywords",
    "content": "ALL\nALTER\nAND\nARRAY\nAS\nAUTHORIZATION\nBETWEEN\nBIGINT\nBINARY\nBOOLEAN\nBOTH\nBY\nCASE\nCAST\nCHAR\nCOLUMN\nCONF\nCREATE\nCROSS\nCUBE\nCURRENT\nCURRENT_DATE\nCURRENT_TIMESTAMP\nCURSOR\nDATABASE\nDATE\nDECIMAL\nDELETE\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nELSE\nEND\nEXCHANGE\nEXISTS\nEXTENDED\nEXTERNAL\nFALSE\nFETCH\nFLOAT\nFOLLOWING\nFOR\nFROM\nFULL\nFUNCTION\nGRANT\nGROUP\nGROUPING\nHAVING\nIF\nIMPORT\nIN\nINNER\nINSERT\nINT\nINTERSECT\nINTERVAL\nINTO\nIS\nJOIN\nLATERAL\nLEFT\nLESS\nLIKE\nLOCAL\nMACRO\nMAP\nMORE\nNONE\nNOT\nNULL\nOF\nON\nOR\nORDER\nOUT\nOUTER\nOVER\nPARTIALSCAN\nPARTITION\nPERCENT\nPRECEDING\nPRESERVE\nPROCEDURE\nRANGE\nREADS\nREDUCE\nREVOKE\nRIGHT\nROLLUP\nROW\nROWS\nSELECT\nSET\nSMALLINT\nTABLE\nTABLESAMPLE\nTHEN\nTIMESTAMP\nTO\nTRANSFORM\nTRIGGER\nTRUE\nTRUNCATE\nUNBOUNDED\nUNION\nUNIQUEJOIN\nUPDATE\nUSER\nUSING\nUTC_TMESTAMP\nVALUES\nVARCHAR\nWHEN\nWHERE\nWINDOW\nWITH\nCOMMIT\nONLY\nREGEXP\nRLIKE\nROLLBACK\nSTART\nCACHE\nCONSTRAINT\nFOREIGN\nPRIMARY\nREFERENCES\nEXCEPT\nEXTRACT\nFLOOR\nGROUPING\nINTEGER\nMINUS\nPRECISION\nMERGE\nANY\nAPPLICATION\nDEC\nNUMERIC\nSYNC\nTIME\nTIMESTAMPLOCALTZ\nUNIQUE\nCOMPACTIONID\nCONNECTOR\nCONNECTORS\nCONVERT\nDDL\nFORCE\nLEADING\nOLDER\nPKFK_JOIN\nPREPARE\nQUALIFY\nREAL\nSOME\nTHAN\nTRAILING"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/hive/builtin_datatypes",
    "content": "TINYINT\nSMALLINT\nMEDIUMINT\nINT\nINTEGER\nBIGINT\nDECIMAL\nNUMERIC\nFLOAT\nDOUBLE\nDATE\nDATETIME\nTIMESTAMP\nINTERVAL\nSTRING\nVARCHAR\nCHAR\nBOOLEAN\nBINARY\nARRAY\nMAP\nSTRUCT\nUNIONTYPE"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/hive/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/hive/keywords",
    "content": "ALL\nALTER\nAND\nARRAY\nAS\nAUTHORIZATION\nBETWEEN\nBIGINT\nBINARY\nBOOLEAN\nBOTH\nBY\nCASE\nCAST\nCHAR\nCOLUMN\nCONF\nCREATE\nCROSS\nCUBE\nCURRENT\nCURRENT_DATE\nCURRENT_TIMESTAMP\nCURSOR\nDATABASE\nDATE\nDECIMAL\nDELETE\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nELSE\nEND\nEXCHANGE\nEXISTS\nEXTENDED\nEXTERNAL\nFALSE\nFETCH\nFLOAT\nFOLLOWING\nFOR\nFROM\nFULL\nFUNCTION\nGRANT\nGROUP\nGROUPING\nHAVING\nIF\nIMPORT\nIN\nINNER\nINSERT\nINT\nINTERSECT\nINTERVAL\nINTO\nIS\nJOIN\nLATERAL\nLEFT\nLESS\nLIKE\nLOCAL\nMACRO\nMAP\nMORE\nNONE\nNOT\nNULL\nOF\nON\nOR\nORDER\nOUT\nOUTER\nOVER\nPARTIALSCAN\nPARTITION\nPERCENT\nPRECEDING\nPRESERVE\nPROCEDURE\nRANGE\nREADS\nREDUCE\nREVOKE\nRIGHT\nROLLUP\nROW\nROWS\nSELECT\nSET\nSMALLINT\nTABLE\nTABLESAMPLE\nTHEN\nTIMESTAMP\nTO\nTRANSFORM\nTRIGGER\nTRUE\nTRUNCATE\nUNBOUNDED\nUNION\nUNIQUEJOIN\nUPDATE\nUSER\nUSING\nUTC_TMESTAMP\nVALUES\nVARCHAR\nWHEN\nWHERE\nWINDOW\nWITH\nCOMMIT\nONLY\nREGEXP\nRLIKE\nROLLBACK\nSTART\nCACHE\nCONSTRAINT\nFOREIGN\nPRIMARY\nREFERENCES\nEXCEPT\nEXTRACT\nFLOOR\nGROUPING\nINTEGER\nMINUS\nPRECISION\nMERGE\nANY\nAPPLICATION\nDEC\nNUMERIC\nSYNC\nTIME\nTIMESTAMPLOCALTZ\nUNIQUE\nCOMPACTIONID\nCONNECTOR\nCONNECTORS\nCONVERT\nDDL\nFORCE\nLEADING\nOLDER\nPKFK_JOIN\nPREPARE\nQUALIFY\nREAL\nSOME\nTHAN\nTRAILING"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/hologres/alias_keywords",
    "content": "abs\nall\nallocate\nanalyse\nanalyze\nand\nany\nare\narray\narray_agg\narray_max_cardinality\nas\nasensitive\nasymmetric\natomic\nauthorization\navg\nbegin_frame\nbegin_partition\nbinary\nbit_length\nblob\nboth\nby\ncall\ncardinality\ncase\ncast\nceil\nceiling\ncharacter_length\nchar_length\ncheck\nclob\ncollate\ncollect\ncolumn\nconcurrently\ncondition\nconnect\nconstraint\nconvert\ncorr\ncorresponding\ncount\ncovar_pop\ncovar_samp\ncreate\ncross\ncume_dist\ncurrent_catalog\ncurrent_date\ncurrent_default_transform_group\ncurrent_path\ncurrent_role\ncurrent_row\ncurrent_schema\ncurrent_time\ncurrent_timestamp\ncurrent_transform_group_for_type\ncurrent_user\ndatalink\ndate\ndefault\ndeferrable\ndense_rank\nderef\ndesc\ndescribe\ndeterministic\ndisconnect\ndistinct\ndlnewcopy\ndlpreviouscopy\ndlurlcomplete\ndlurlcompleteonly\ndlurlcompletewrite\ndlurlpath\ndlurlpathonly\ndlurlpathwrite\ndlurlscheme\ndlurlserver\ndlvalue\ndo\ndynamic\nelement\nelse\nend\nend-exec\nend_frame\nend_partition\nevery\nexcept\nexception\nexec\nexp\nfalse\nfetch\nfinal\nfirst_value\nfloor\nfor\nforeign\nframe_row\nfree\nfreeze\nfrom\nfull\nfusion\nget\ngrant\ngroup\ngroups\nhaving\nilike\nin\nindicator\ninner\nintersect\nintersection\ninto\ninstantiable\nis\nisnull\njoin\nlag\nlast_value\nlateral\nlead\nleading\nleft\nlike\nlike_regex\nlimit\nln\nlocaltime\nlocaltimestamp\nlower\nmax\nmax_cardinality\nmerge\nmin\nmod\nmodifies\nmultiset\nnatural\nnclob\nnormalize\nnot\nnotnull\nnth_value\nntile\nnull\noccurrences_regex\noctet_length\noid\noffset\non\nonly\nopen\nor\norder\nouter\nover\noverlaps\nparameter\npercent\npercentile_cont\npercentile_disc\npercent_rank\nperiod\nplacing\nportion\nposition_regex\npower\nprecedes\nprimary\nrank\nreads\nreferences\nregr_avgx\nregr_avgy\nregr_count\nregr_intercept\nregr_r2\nregr_slope\nregr_sxx\nregr_sxy\nregr_syy\nresult\nreturn\nreturning\nright\nrow_number\nscope\nselect\nsensitive\nsession_user\nsimilar\nsome\nspecific\nspecifictype\nsqlcode\nsqlerror\nsqlexception\nsqlstate\nsqlwarning\nsqrt\nstatic\nstddev_pop\nstddev_samp\nsubmultiset\nsubstring_regex\nsucceeds\nsum\nsymmetric\nsystem_time\nsystem_user\ntable\ntablesample\nthen\ntimezone_hour\ntimezone_minute\nto\ntrailing\ntranslate\ntranslate_regex\ntranslation\ntrim_array\ntrue\nuescape\nunion\nunique\nunnest\nupper\nuser\nusing\nvalue_of\nvarbinary\nvariadic\nvar_pop\nvar_samp\nverbose\nversioning\nwhen\nwhenever\nwhere\nwidth_bucket\nwindow\nwith\nxmlagg\nxmlbinary\nxmlcast\nxmlcomment\nxmldocument\nxmliterate\nxmlquery\nxmltext\nxmlvalidate"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/hologres/dialect.properties",
    "content": "quote=\"\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/hologres/keywords",
    "content": "abs\nall\nallocate\nanalyse\nanalyze\nand\nany\nare\narray\narray_agg\narray_max_cardinality\nas\nasensitive\nasymmetric\natomic\nauthorization\navg\nbegin_frame\nbegin_partition\nbinary\nbit_length\nblob\nboth\nby\ncall\ncardinality\ncase\ncast\nceil\nceiling\ncharacter_length\nchar_length\ncheck\nclob\ncollate\ncollect\ncolumn\nconcurrently\ncondition\nconnect\nconstraint\nconvert\ncorr\ncorresponding\ncount\ncovar_pop\ncovar_samp\ncreate\ncross\ncume_dist\ncurrent_catalog\ncurrent_date\ncurrent_default_transform_group\ncurrent_path\ncurrent_role\ncurrent_row\ncurrent_schema\ncurrent_time\ncurrent_timestamp\ncurrent_transform_group_for_type\ncurrent_user\ndatalink\ndate\ndefault\ndeferrable\ndense_rank\nderef\ndesc\ndescribe\ndeterministic\ndisconnect\ndistinct\ndlnewcopy\ndlpreviouscopy\ndlurlcomplete\ndlurlcompleteonly\ndlurlcompletewrite\ndlurlpath\ndlurlpathonly\ndlurlpathwrite\ndlurlscheme\ndlurlserver\ndlvalue\ndo\ndynamic\nelement\nelse\nend\nend-exec\nend_frame\nend_partition\nevery\nexcept\nexception\nexec\nexp\nfalse\nfetch\nfinal\nfirst_value\nfloor\nfor\nforeign\nframe_row\nfree\nfreeze\nfrom\nfull\nfusion\nget\ngrant\ngroup\ngroups\nhaving\nilike\nin\nindicator\ninner\nintersect\nintersection\ninto\ninstantiable\nis\nisnull\njoin\nlag\nlast_value\nlateral\nlead\nleading\nleft\nlike\nlike_regex\nlimit\nln\nlocaltime\nlocaltimestamp\nlower\nmax\nmax_cardinality\nmerge\nmin\nmod\nmodifies\nmultiset\nnatural\nnclob\nnormalize\nnot\nnotnull\nnth_value\nntile\nnull\noccurrences_regex\noctet_length\noid\noffset\non\nonly\nopen\nor\norder\nouter\nover\noverlaps\nparameter\npercent\npercentile_cont\npercentile_disc\npercent_rank\nperiod\nplacing\nportion\nposition_regex\npower\nprecedes\nprimary\nrank\nreads\nreferences\nregr_avgx\nregr_avgy\nregr_count\nregr_intercept\nregr_r2\nregr_slope\nregr_sxx\nregr_sxy\nregr_syy\nresult\nreturn\nreturning\nright\nrow_number\nscope\nselect\nsensitive\nsession_user\nsimilar\nsome\nspecific\nspecifictype\nsqlcode\nsqlerror\nsqlexception\nsqlstate\nsqlwarning\nsqrt\nstatic\nstddev_pop\nstddev_samp\nsubmultiset\nsubstring_regex\nsucceeds\nsum\nsymmetric\nsystem_time\nsystem_user\ntable\ntablesample\nthen\ntimezone_hour\ntimezone_minute\nto\ntrailing\ntranslate\ntranslate_regex\ntranslation\ntrim_array\ntrue\nuescape\nunion\nunique\nunnest\nupper\nuser\nusing\nvalue_of\nvarbinary\nvariadic\nvar_pop\nvar_samp\nverbose\nversioning\nwhen\nwhenever\nwhere\nwidth_bucket\nwindow\nwith\nxmlagg\nxmlbinary\nxmlcast\nxmlcomment\nxmldocument\nxmliterate\nxmlquery\nxmltext\nxmlvalidate"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/impala/alias_keywords",
    "content": "ALL\nALTER\nAND\nARRAY\nAS\nAUTHORIZATION\nBETWEEN\nBIGINT\nBINARY\nBOOLEAN\nBOTH\nBY\nCASE\nCAST\nCHAR\nCOLUMN\nCONF\nCREATE\nCROSS\nCUBE\nCURRENT\nCURRENT_DATE\nCURRENT_TIMESTAMP\nCURSOR\nDATABASE\nDATE\nDECIMAL\nDELETE\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nELSE\nEND\nEXCHANGE\nEXISTS\nEXTENDED\nEXTERNAL\nFALSE\nFETCH\nFLOAT\nFOLLOWING\nFOR\nFROM\nFULL\nFUNCTION\nGRANT\nGROUP\nGROUPING\nHAVING\nIF\nIMPORT\nIN\nINNER\nINSERT\nINT\nINTERSECT\nINTERVAL\nINTO\nIS\nJOIN\nLATERAL\nLEFT\nLESS\nLIKE\nLOCAL\nMACRO\nMAP\nMORE\nNONE\nNOT\nNULL\nOF\nON\nOR\nORDER\nOUT\nOUTER\nOVER\nPARTIALSCAN\nPARTITION\nPERCENT\nPRECEDING\nPRESERVE\nPROCEDURE\nRANGE\nREADS\nREDUCE\nREVOKE\nRIGHT\nROLLUP\nROW\nROWS\nSELECT\nSET\nSMALLINT\nTABLE\nTABLESAMPLE\nTHEN\nTIMESTAMP\nTO\nTRANSFORM\nTRIGGER\nTRUE\nTRUNCATE\nUNBOUNDED\nUNION\nUNIQUEJOIN\nUPDATE\nUSER\nUSING\nUTC_TMESTAMP\nVALUES\nVARCHAR\nWHEN\nWHERE\nWINDOW\nWITH\nCOMMIT\nONLY\nREGEXP\nRLIKE\nROLLBACK\nSTART\nCACHE\nCONSTRAINT\nFOREIGN\nPRIMARY\nREFERENCES\nEXCEPT\nEXTRACT\nFLOOR\nGROUPING\nINTEGER\nMINUS\nPRECISION\nMERGE\nANY\nAPPLICATION\nDEC\nNUMERIC\nSYNC\nTIME\nTIMESTAMPLOCALTZ\nUNIQUE\nCOMPACTIONID\nCONNECTOR\nCONNECTORS\nCONVERT\nDDL\nFORCE\nLEADING\nOLDER\nPKFK_JOIN\nPREPARE\nQUALIFY\nREAL\nSOME\nTHAN\nTRAILING"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/impala/builtin_datatypes",
    "content": "TINYINT\nSMALLINT\nMEDIUMINT\nINT\nINTEGER\nBIGINT\nDECIMAL\nNUMERIC\nFLOAT\nDOUBLE\nDATE\nDATETIME\nTIMESTAMP\nINTERVAL\nSTRING\nVARCHAR\nCHAR\nBOOLEAN\nBINARY\nARRAY\nMAP\nSTRUCT\nUNIONTYPE"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/impala/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/impala/keywords",
    "content": "ALL\nALTER\nAND\nARRAY\nAS\nAUTHORIZATION\nBETWEEN\nBIGINT\nBINARY\nBOOLEAN\nBOTH\nBY\nCASE\nCAST\nCHAR\nCOLUMN\nCONF\nCREATE\nCROSS\nCUBE\nCURRENT\nCURRENT_DATE\nCURRENT_TIMESTAMP\nCURSOR\nDATABASE\nDATE\nDECIMAL\nDELETE\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nELSE\nEND\nEXCHANGE\nEXISTS\nEXTENDED\nEXTERNAL\nFALSE\nFETCH\nFLOAT\nFOLLOWING\nFOR\nFROM\nFULL\nFUNCTION\nGRANT\nGROUP\nGROUPING\nHAVING\nIF\nIMPORT\nIN\nINNER\nINSERT\nINT\nINTERSECT\nINTERVAL\nINTO\nIS\nJOIN\nLATERAL\nLEFT\nLESS\nLIKE\nLOCAL\nMACRO\nMAP\nMORE\nNONE\nNOT\nNULL\nOF\nON\nOR\nORDER\nOUT\nOUTER\nOVER\nPARTIALSCAN\nPARTITION\nPERCENT\nPRECEDING\nPRESERVE\nPROCEDURE\nRANGE\nREADS\nREDUCE\nREVOKE\nRIGHT\nROLLUP\nROW\nROWS\nSELECT\nSET\nSMALLINT\nTABLE\nTABLESAMPLE\nTHEN\nTIMESTAMP\nTO\nTRANSFORM\nTRIGGER\nTRUE\nTRUNCATE\nUNBOUNDED\nUNION\nUNIQUEJOIN\nUPDATE\nUSER\nUSING\nUTC_TMESTAMP\nVALUES\nVARCHAR\nWHEN\nWHERE\nWINDOW\nWITH\nCOMMIT\nONLY\nREGEXP\nRLIKE\nROLLBACK\nSTART\nCACHE\nCONSTRAINT\nFOREIGN\nPRIMARY\nREFERENCES\nEXCEPT\nEXTRACT\nFLOOR\nGROUPING\nINTEGER\nMINUS\nPRECISION\nMERGE\nANY\nAPPLICATION\nDEC\nNUMERIC\nSYNC\nTIME\nTIMESTAMPLOCALTZ\nUNIQUE\nCOMPACTIONID\nCONNECTOR\nCONNECTORS\nCONVERT\nDDL\nFORCE\nLEADING\nOLDER\nPKFK_JOIN\nPREPARE\nQUALIFY\nREAL\nSOME\nTHAN\nTRAILING"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/mysql/builtin_datatypes",
    "content": "INTEGER\nTINYINT\nSMALLINT\nMEDIUMINT\nINT\nBIGINT\nDECIMAL\nNUMERIC\nFLOAT\nDOUBLE\nBIT\nDATE\nDATETIME\nTIMESTAMP\nTIME\nYEAR\nCHAR\nVARCHAR\nNCHAR\nNVARCHAR\nBINARY\nVARBINARY\nMEDIUMBLOB\nBLOB\nBLOB\nLONGBLOB\nTINYTEXT\nMEDIUMTEXT\nTEXT\nLONGTEXT\nENUM\nSET"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/mysql/dialect.properties",
    "content": "quote=`,\",'\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/mysql/keywords",
    "content": "accessible\nadd\nafter\nagainst\naggregate\nall\nalter\nalways\nanalyse\nanalyze\nand\nany\nas\nasc\nascii\nasensitive\nat\nauto_increment\navg\navg_row_length\nbackup\nbefore\nbegin\nbetween\nbigint\nbinary\nbinlog\nbit\nblob\nblock\nbool\nboolean\nboth\nbtree\nby\nbyte\ncache\ncall\ncascade\ncascaded\ncase\nchain\nchange\nchanged\nchannel\nchar\ncharacter\ncharset\ncheck\nchecksum\ncipher\nclose\ncoalesce\ncollate\ncollation\ncolumn\ncolumns\ncomment\ncommit\ncommitted\ncompact\ncompletion\ncompressed\ncompression\nconcurrent\ncondition\nconnection\nconsistent\nconstraint\ncontains\ncontext\ncontinue\nconvert\ncpu\ncreate\ncross\ncube\ncurrent\ncurrent_date\ncurrent_time\ncurrent_timestamp\ncurrent_user\ncursor\ndatabase\ndatabases\ndate\ndatetime\nday\ndeallocate\ndec\ndecimal\ndeclare\ndefault\ndefiner\ndelayed\ndelete\ndesc\ndescribe\ndeterministic\ndiagnostics\ndirectory\ndisable\ndiscard\ndisk\ndistinct\ndistinctrow\ndiv\ndo\ndouble\ndrop\ndual\ndumpfile\nduplicate\ndynamic\neach\nelse\nelseif\nenable\nenclosed\nencryption\nend\nends\nengine\nengines\nenum\nerror\nerrors\nescape\nescaped\nevent\nevents\nevery\nexchange\nexecute\nexists\nexit\nexpansion\nexplain\nexport\nextended\nextent_size\nfalse\nfast\nfaults\nfetch\nfields\nfilter\nfirst\nfixed\nfloat\nfloat4\nfloat8\nflush\nfor\nforce\nforeign\nformat\nfound\nfrom\nfull\nfulltext\nfunction\ngeneral\ngenerated\ngeometry\ngeometrycollection\nget\ngrant\ngrants\ngroup\ngroup_replication\nhandler\nhaving\nhigh_priority\nhost\nhosts\nhour\nhour_microsecond\nhour_minute\nhour_second\nidentified\nif\nignore\nimport\nin\nindex\nindexes\ninfile\ninner\ninout\ninsensitive\ninsert\ninstall\nint\nint1\nint2\nint3\nint4\nint8\ninteger\ninterval\ninto\nio\nio_after_gtids\nio_before_gtids\nio_thread\nipc\nis\nisolation\nissuer\niterate\njoin\njson\nkey\nkeys\nkill\nleading\nleave\nleaves\nleft\nless\nlike\nlimit\nlinear\nlines\nlinestring\nlist\nload\nlocal\nlocaltime\nlocaltimestamp\nlock\nlocks\nlogfile\nlogs\nlong\nlongblob\nlongtext\nloop\nlow_priority\nmatch\nmaxvalue\nmax_connections_per_hour\nmax_queries_per_hour\nmax_rows\nmax_size\nmax_statement_time\nmax_updates_per_hour\nmax_user_connections\nmedium\nmediumblob\nmediumint\nmediumtext\nmerge\nmicrosecond\nmiddleint\nmigrate\nminute\nminute_microsecond\nminute_second\nminvalue\nmod\nmodifies\nmodify\nmonth\nmultilinestring\nmultipoint\nmultipolygon\nmutex\nmysql_errno\nnational\nnatural\nnchar\nndb\nndbcluster\nnever\nnew\nnext\nno\nnodegroup\nnonblocking\nnone\nnot\nno_wait\nno_write_to_binlog\nnull\nnumber\nnumeric\nnvarchar\noffset\non\none\nonly\nopen\noptimize\noptimizer_costs\noption\noptionally\noptions\nor\norder\nout\nouter\noutfile\npack_keys\npage\nparser\nparse_gcol_expr\npartial\npartition\npartitioning\npartitions\npassword\nphase\nplugin\nplugins\nplugin_dir\npolygon\nprecedes\nprecision\nprepare\npreserve\nprev\nprimary\nprivileges\nprocedure\nprocesslist\npurge\nquarter\nquery\nrange\nread\nreads\nread_only\nread_write\nreal\nrebuild\nrecover\nredofile\nredo_buffer_size\nredundant\nreferences\nregexp\nrelay\nrelaylog\nrelay_log_file\nrelay_log_pos\nrelay_thread\nrelease\nreload\nremove\nrename\nreorganize\nrepair\nrepeat\nrepeatable\nreplace\nreplicate_do_db\nreplicate_do_table\nreplicate_ignore_db\nreplicate_ignore_table\nreplicate_rewrite_db\nreplicate_wild_do_table\nreplicate_wild_ignore_table\nreplication\nrequire\nreset\nresignal\nrestore\nrestrict\nresume\nreturn\nreturned_sqlstate\nreturns\nreverse\nrevoke\nright\nrlike\nrollback\nrollup\nrotate\nroutine\nrow\nrows\nrow_count\nrow_format\nrtree\nsavepoint\nschedule\nschema\nschemas\nsecond\nsecond_microsecond\nsecurity\nselect\nsensitive\nseparator\nserial\nserializable\nserver\nsession\nset\nshare\nshow\nshutdown\nsignal\nsigned\nslave\nslow\nsmallint\nsnapshot\nsome\nsoname\nsounds\nsource\nspatial\nspecific\nsql\nsqlexception\nsqlstate\nsqlwarning\nsql_after_mts_gaps\nsql_before_gtids\nsql_big_result\nsql_buffer_result\nsql_cache\nsql_calc_found_rows\nsql_no_cache\nsql_small_result\nssl\nstacked\nstarting\nstarts\nstats_auto_recalc\nstats_persistent\nstats_sample_pages\nstop\nstorage\nstored\nstraight_join\nstring\nsubclass_origin\nsubpartition\nsubpartitions\nsuper\nsuspend\nswaps\nswitches\ntable\ntables\ntablespace\ntemporary\ntemptable\nterminated\ntext\nthan\nthen\ntime\ntimestamp\ntimestampadd\ntimestampdiff\ntinyblob\ntinyint\ntinytext\nto\ntrailing\ntransaction\ntrigger\ntriggers\ntrue\ntruncate\ntype\ntypes\nuncommitted\nundefined\nundo\nundofile\nundo_buffer_size\nunicode\nuninstall\nunion\nunique\nunknown\nunlock\nunsigned\nuntil\nupdate\nupgrade\nusage\nuse\nuser\nuse_frm\nusing\nutc_date\nutc_time\nutc_timestamp\nvalidation\nvalues\nvarbinary\nvarchar\nvarcharacter\nvariables\nvarying\nview\nvirtual\nwait\nwarnings\nweek\nweight_string\nwhen\nwhere\nwhile\nwith\nwithout\nwork\nwrapper\nwrite\nx509\nxa\nxml\nxor\nyear_month\nzerofill\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/odps/alias_keywords",
    "content": "ALL\nALTER\nARRAY\nAS\nAUTHORIZATION\nBETWEEN\nBIGINT\nBINARY\nBOOLEAN\nBOTH\nBY\nCREATE\nCURRENT_DATE\nCURRENT_TIMESTAMP\nCURSOR\nDATE\nDECIMAL\nDELETE\nDESCRIBE\nDOUBLE\nDROP\nEXISTS\nEXTERNAL\nFALSE\nFETCH\nFLOAT\nFOR\nFULL\nGRANT\nGROUP\nGROUPING\nIMPORT\nIN\nINSERT\nINT\nINTERSECT\nINTO\nIS\nLATERAL\nLEFT\nLIKE\nLOCAL\nNONE\nNULL\nOF\nORDER\nOUT\nOUTER\nPARTITION\nPERCENT\nPROCEDURE\nRANGE\nREADS\nREVOKE\nRIGHT\nROLLUP\nROW\nROWS\nSET\nSMALLINT\nTABLE\nTIMESTAMP\nTO\nTRIGGER\nTRUE\nTRUNCATE\nUNION\nUPDATE\nUSING\nVALUES\nWITH\nWINDOW\nNATURAL\nFUNCTION"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/odps/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/odps/keywords",
    "content": "AND\nOR\nNOT\nLIKE\nIF\nHAVING\nFROM\nSELECT\nDISTINCT\nUNIQUEJOIN\nPRESERVE\nJOIN\nON\nCOLUMN\nCHAR\nVARCHAR\nTABLESAMPLE\nCAST\nMACRO\nEXTENDED\nCASE\nWHEN\nTHEN\nELSE\nEND\nCROSS\nUNBOUNDED\nPRECEDING\nFOLLOWING\nCURRENT\nPARTIALSCAN\nOVER\nWHERE\nBIGINT\nBINARY\nBOOLEAN\nCURRENT_DATE\nCURRENT_TIMESTAMP\nDATE\nDOUBLE\nFLOAT\nINT\nSMALLINT\nTIMESTAMP\nFUNCTION"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/oracle/builtin_aggreagte_functions",
    "content": "AVG\nCOLLECT\nCORR\nCOUNT\nCOVAR_POP\nCOVAR_SAMP\nCUME_DIST\nDENSE_RANK\nFIRST\nGROUP_ID\nGROUPING\nGROUPING_ID\nLAST\nMAX\nMEDIAN\nMIN\nPERCENTILE_CONT\nPERCENTILE_DISC\nPERCENT_RANK\nRANK\nSTATS_BINOMIAL_TEST\nSTATS_CROSSTAB\nSTATS_F_TEST\nSTATS_KS_TEST\nSTATS_MODE\nSTATS_MW_TEST\nSTATS_ONE_WAY_ANOVA\nSTATS_T_TEST_*\nSTATS_WSR_TEST\nSTDDEV\nSTDDEV_POP\nSTDDEV_SAMP\nSUM\nVAR_POP\nVAR_SAMP\nVARIANCE"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/oracle/builtin_functions",
    "content": "ABS\nACOS\nASIN\nATAN\nATAN2\nBITAND\nCEIL\nCOS\nCOSH\nEXP\nFLOOR\nLEN\nLN\nLOG\nMOD\nNANVL\nPOWER\nREMAINDER\nROUND\nSIGN\nSIN\nSINH\nSQRT\nTAN\nTANH\nTRUNC\nWIDTH_BUCKET\n\nCHR\nNCHR\nCHAR\nNCHAR\nCONCAT\nINITCAP\nLOWER\nLPAD\nLTRIM\nNLS_INITCAP\nNLS_LOWER\nNLSSORT\nNLS_UPPER\nREGEXP_REPLACE\nREGEXP_SUBSTR\nREPLACE\nRPAD\nRTRIM\nSOUNDEX\nSUBSTR\nTRANSLATE\nTREAT\nTRIM\nUPPER\n\nNLS_CHARSET_DECL_LEN\nNLS_CHARSET_ID\nNLS_CHARSET_NAME\n\nASCII\nINSTR\nINSTRB\nLENGTH\nLENGTHB\nREGEXP_INSTR\n\nADD_MONTHS\nCURRENT_DATE\nCURRENT_TIMESTAMP\nDBTIMEZONE\nEXTRACT\nFROM_TZ\nLAST_DAY\nLOCALTIMESTAMP\nMONTHS_BETWEEN\nNEW_TIME\nNEXT_DAY\nNUMTODSINTERVAL\nNUMTOYMINTERVAL\nROUND\nSESSIONTIMEZONE\nSYS_EXTRACT_UTC\nSYSDATE\nSYSTIMESTAMP\nTO_CHAR\nTO_TIMESTAMP\nTO_TIMESTAMP_TZ\nTO_DSINTERVAL\nTO_YMINTERVAL\nTRUNC\nTZ_OFFSET\n\nGREATEST\nLEAST\n\nASCIISTR\nBIN_TO_NUM\nCAST\nCHARTOROWID\nCOMPOSE\nCONVERT\nDECOMPOSE\nHEXTORAW\nNUMTODSINTERVAL\nNUMTOYMINTERVAL\nRAWTOHEX\nRAWTONHEX\nROWIDTOCHAR\nROWIDTONCHAR\nSCN_TO_TIMESTAMP\nTIMESTAMP_TO_SCN\nTO_BINARY_DOUBLE\nTO_BINARY_FLOAT\nTO_CHAR\nTO_CLOB\nTO_DATE\nTO_DSINTERVAL\nTO_LOB\nTO_MULTI_BYTE\nTO_NCHAR\nTO_NCLOB\nTO_NUMBER\nTO_DSINTERVAL\nTO_SINGLE_BYTE\nTO_TIMESTAMP\nTO_TIMESTAMP_TZ\nTO_YMINTERVAL\nTO_YMINTERVAL\nTRANSLATE\nUNISTR\n\nBFILENAME\nEMPTY_BLOB\nEMPTY_CLOB\n\nCARDINALITY\nCOLLECT\nPOWERMULTISET\nPOWERMULTISET_BY_CARDINALITY\nSET\n\nSYS_CONNECT_BY_PATH\n\nCLUSTER_ID\nCLUSTER_PROBABILITY\nCLUSTER_SET\nFEATURE_ID\nFEATURE_SET\nFEATURE_VALUE\nPREDICTION\nPREDICTION_COST\nPREDICTION_DETAILS\nPREDICTION_PROBABILITY\nPREDICTION_SET\n\nAPPENDCHILDXML\nDELETEXML\nDEPTH\nEXTRACT\nEXISTSNODE\nEXTRACTVALUE\nINSERTCHILDXML\nINSERTXMLBEFORE\nPATH\nSYS_DBURIGEN\nSYS_XMLAGG\nSYS_XMLGEN\nUPDATEXML\nXMLAGG\nXMLCDATA\nXMLCOLATTVAL\nXMLCOMMENT\nXMLCONCAT\nXMLFOREST\nXMLPARSE\nXMLPI\nXMLQUERY\nXMLROOT\nXMLSEQUENCE\nXMLSERIALIZE\nXMLTABLE\nXMLTRANSFORM\n\nDECODE\nDUMP\nORA_HASH\nVSIZE\n\nCOALESCE\nLNNVL\nNULLIF\nNVL\nNVL2\n\nSYS_CONTEXT\nSYS_GUID\nSYS_TYPEID\nUID\nUSER\nUSERENV\n\nAVG\nCOLLECT\nCORR\nCOUNT\nCOVAR_POP\nCOVAR_SAMP\nCUME_DIST\nDENSE_RANK\nFIRST\nGROUP_ID\nGROUPING\nGROUPING_ID\nLAST\nMAX\nMEDIAN\nMIN\nPERCENTILE_CONT\nPERCENTILE_DISC\nPERCENT_RANK\nRANK\nSTATS_BINOMIAL_TEST\nSTATS_CROSSTAB\nSTATS_F_TEST\nSTATS_KS_TEST\nSTATS_MODE\nSTATS_MW_TEST\nSTATS_ONE_WAY_ANOVA\nSTATS_WSR_TEST\nSTDDEV\nSTDDEV_POP\nSTDDEV_SAMP\nSUM\nVAR_POP\nVAR_SAMP\nVARIANCE\n\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/oracle/builtin_tables",
    "content": "all_all_tables\nall_apply\nall_apply_change_handlers\nall_apply_conflict_columns\nall_apply_dml_handlers\nall_apply_enqueue\nall_apply_error\nall_apply_error_messages\nall_apply_execute\nall_apply_key_columns\nall_apply_parameters\nall_apply_progress\nall_apply_table_columns\nall_arguments\nall_assemblies\nall_associations\nall_audit_policies\nall_audit_policy_columns\nall_aw_ps\nall_aws\nall_base_table_mviews\nall_capture\nall_capture_extra_attributes\nall_capture_parameters\nall_capture_prepared_database\nall_capture_prepared_schemas\nall_capture_prepared_tables\nall_catalog\nall_change_propagation_sets\nall_change_propagations\nall_change_sets\nall_change_sources\nall_change_tables\nall_cluster_hash_expressions\nall_clusters\nall_col_comments\nall_col_pending_stats\nall_col_privs\nall_col_privs_made\nall_col_privs_recd\nall_coll_types\nall_cons_columns\nall_cons_obj_columns\nall_constraints\nall_context\nall_cube_attr_visibility\nall_cube_attributes\nall_cube_build_processes\nall_cube_calculated_members\nall_cube_dim_levels\nall_cube_dim_models\nall_cube_dim_view_columns\nall_cube_dim_views\nall_cube_dimensionality\nall_cube_dimensions\nall_cube_hier_levels\nall_cube_hier_view_columns\nall_cube_hier_views\nall_cube_hierarchies\nall_cube_measures\nall_cube_view_columns\nall_cube_views\nall_cubes\nall_db_links\nall_def_audit_opts\nall_dependencies\nall_dequeue_queues\nall_dim_attributes\nall_dim_child_of\nall_dim_hierarchies\nall_dim_join_key\nall_dim_level_key\nall_dim_levels\nall_dimensions\nall_directories\nall_edition_comments\nall_editioning_view_cols\nall_editioning_view_cols_ae\nall_editioning_views\nall_editioning_views_ae\nall_editions\nall_encrypted_columns\nall_errors\nall_errors_ae\nall_evaluation_context_tables\nall_evaluation_context_vars\nall_evaluation_contexts\nall_external_locations\nall_external_tables\nall_file_group_export_info\nall_file_group_files\nall_file_group_tables\nall_file_group_tablespaces\nall_file_group_versions\nall_file_groups\nall_histograms\nall_identifiers\nall_ind_columns\nall_ind_expressions\nall_ind_partitions\nall_ind_pending_stats\nall_ind_statistics\nall_ind_subpartitions\nall_indexes\nall_indextype_arraytypes\nall_indextype_comments\nall_indextype_operators\nall_indextypes\nall_internal_triggers\nall_java_arguments\nall_java_classes\nall_java_compiler_options\nall_java_derivations\nall_java_fields\nall_java_implements\nall_java_inners\nall_java_layouts\nall_java_methods\nall_java_ncomps\nall_java_resolvers\nall_java_throws\nall_jobs\nall_join_ind_columns\nall_libraries\nall_lob_partitions\nall_lob_subpartitions\nall_lob_templates\nall_lobs\nall_log_group_columns\nall_log_groups\nall_measure_folder_contents\nall_measure_folders\nall_method_params\nall_method_results\nall_mining_model_attributes\nall_mining_model_settings\nall_mining_models\nall_mview_aggregates\nall_mview_analysis\nall_mview_comments\nall_mview_detail_partition\nall_mview_detail_relations\nall_mview_detail_subpartition\nall_mview_joins\nall_mview_keys\nall_mview_logs\nall_mview_refresh_times\nall_mviews\nall_nested_table_cols\nall_nested_tables\nall_obj_colattrs\nall_object_tables\nall_objects\nall_objects_ae\nall_opancillary\nall_oparguments\nall_opbindings\nall_operator_comments\nall_operators\nall_outline_hints\nall_outlines\nall_part_col_statistics\nall_part_histograms\nall_part_indexes\nall_part_key_columns\nall_part_lobs\nall_part_tables\nall_partial_drop_tabs\nall_pending_conv_tables\nall_plsql_object_settings\nall_policies\nall_policy_contexts\nall_policy_groups\nall_procedures\nall_propagation\nall_published_columns\nall_queue_schedules\nall_queue_subscribers\nall_queue_tables\nall_queues\nall_refresh\nall_refresh_children\nall_refresh_dependencies\nall_refs\nall_registered_mviews\nall_registry_banners\nall_rewrite_equivalences\nall_rule_set_rules\nall_rule_sets\nall_rules\nall_scheduler_chain_rules\nall_scheduler_chain_steps\nall_scheduler_chains\nall_scheduler_credentials\nall_scheduler_db_dests\nall_scheduler_dests\nall_scheduler_external_dests\nall_scheduler_file_watchers\nall_scheduler_global_attribute\nall_scheduler_group_members\nall_scheduler_groups\nall_scheduler_job_args\nall_scheduler_job_classes\nall_scheduler_job_dests\nall_scheduler_job_log\nall_scheduler_job_run_details\nall_scheduler_jobs\nall_scheduler_notifications\nall_scheduler_program_args\nall_scheduler_programs\nall_scheduler_remote_databases\nall_scheduler_remote_jobstate\nall_scheduler_running_chains\nall_scheduler_running_jobs\nall_scheduler_schedules\nall_scheduler_window_details\nall_scheduler_window_groups\nall_scheduler_window_log\nall_scheduler_windows\nall_scheduler_wingroup_members\nall_sec_relevant_cols\nall_secondary_objects\nall_sequences\nall_services\nall_source\nall_source_ae\nall_source_tables\nall_sqlj_type_attrs\nall_sqlj_type_methods\nall_sqlj_types\nall_sqlset\nall_sqlset_binds\nall_sqlset_plans\nall_sqlset_references\nall_sqlset_statements\nall_stat_extensions\nall_stored_settings\nall_streams_columns\nall_streams_global_rules\nall_streams_message_consumers\nall_streams_message_rules\nall_streams_newly_supported\nall_streams_rules\nall_streams_schema_rules\nall_streams_stmt_handlers\nall_streams_stmts\nall_streams_table_rules\nall_streams_transform_function\nall_streams_unsupported\nall_subpart_col_statistics\nall_subpart_histograms\nall_subpart_key_columns\nall_subpartition_templates\nall_subscribed_columns\nall_subscribed_tables\nall_subscriptions\nall_sumdelta\nall_sync_capture\nall_sync_capture_prepared_tabs\nall_sync_capture_tables\nall_synonyms\nall_tab_col_statistics\nall_tab_cols\nall_tab_columns\nall_tab_comments\nall_tab_histgrm_pending_stats\nall_tab_histograms\nall_tab_modifications\nall_tab_partitions\nall_tab_pending_stats\nall_tab_privs\nall_tab_privs_made\nall_tab_privs_recd\nall_tab_stat_prefs\nall_tab_statistics\nall_tab_stats_history\nall_tab_subpartitions\nall_tables\nall_trigger_cols\nall_trigger_ordering\nall_triggers\nall_tstz_tab_cols\nall_tstz_tables\nall_type_attrs\nall_type_methods\nall_type_versions\nall_types\nall_unused_col_tabs\nall_updatable_columns\nall_users\nall_ustats\nall_varrays\nall_views\nall_views_ae\nall_warning_settings\nall_xml_indexes\nall_xml_schemas\nall_xml_tab_cols\nall_xml_tables\nall_xml_view_cols\nall_xml_views\nall_xstream_inbound\nall_xstream_inbound_progress\nall_xstream_outbound\nall_xstream_outbound_progress\nall_xstream_rules\naudit_actions\ncat\ncatalog\nchained_rows\nchange_propagation_sets\nchange_propagations\nchange_sets\nchange_sources\nchange_tables\nclient_result_cache_stats$\nclu\ncol\ncols\ndatabase_properties\ndba_2pc_neighbors\ndba_2pc_pending\ndba_addm_fdg_breakdown\ndba_addm_findings\ndba_addm_instances\ndba_addm_system_directives\ndba_addm_task_directives\ndba_addm_tasks\ndba_advisor_actions\ndba_advisor_commands\ndba_advisor_def_parameters\ndba_advisor_definitions\ndba_advisor_dir_definitions\ndba_advisor_dir_instances\ndba_advisor_dir_task_inst\ndba_advisor_exec_parameters\ndba_advisor_execution_types\ndba_advisor_executions\ndba_advisor_fdg_breakdown\ndba_advisor_finding_names\ndba_advisor_findings\ndba_advisor_journal\ndba_advisor_log\ndba_advisor_object_types\ndba_advisor_objects\ndba_advisor_parameters\ndba_advisor_rationale\ndba_advisor_recommendations\ndba_advisor_sqla_rec_sum\ndba_advisor_sqla_tables\ndba_advisor_sqla_wk_map\ndba_advisor_sqla_wk_stmts\ndba_advisor_sqlplans\ndba_advisor_sqlstats\ndba_advisor_sqlw_journal\ndba_advisor_sqlw_parameters\ndba_advisor_sqlw_stmts\ndba_advisor_sqlw_sum\ndba_advisor_sqlw_tables\ndba_advisor_sqlw_templates\ndba_advisor_tasks\ndba_advisor_templates\ndba_advisor_usage\ndba_alert_history\ndba_all_tables\ndba_application_roles\ndba_apply\ndba_apply_change_handlers\ndba_apply_conflict_columns\ndba_apply_dml_handlers\ndba_apply_enqueue\ndba_apply_error\ndba_apply_error_messages\ndba_apply_execute\ndba_apply_instantiated_global\ndba_apply_instantiated_objects\ndba_apply_instantiated_schemas\ndba_apply_key_columns\ndba_apply_object_dependencies\ndba_apply_parameters\ndba_apply_progress\ndba_apply_spill_txn\ndba_apply_table_columns\ndba_apply_value_dependencies\ndba_aq_agent_privs\ndba_aq_agents\ndba_arguments\ndba_assemblies\ndba_associations\ndba_attribute_transformations\ndba_audit_exists\ndba_audit_mgmt_clean_events\ndba_audit_mgmt_cleanup_jobs\ndba_audit_mgmt_config_params\ndba_audit_mgmt_last_arch_ts\ndba_audit_object\ndba_audit_policies\ndba_audit_policy_columns\ndba_audit_session\ndba_audit_statement\ndba_audit_trail\ndba_auto_segadv_ctl\ndba_auto_segadv_summary\ndba_autotask_client\ndba_autotask_client_history\ndba_autotask_client_job\ndba_autotask_job_history\ndba_autotask_operation\ndba_autotask_schedule\ndba_autotask_task\ndba_autotask_window_clients\ndba_autotask_window_history\ndba_aw_ps\ndba_aws\ndba_base_table_mviews\ndba_blockers\ndba_capture\ndba_capture_extra_attributes\ndba_capture_parameters\ndba_capture_prepared_database\ndba_capture_prepared_schemas\ndba_capture_prepared_tables\ndba_catalog\ndba_change_notification_regs\ndba_clu_columns\ndba_cluster_hash_expressions\ndba_clusters\ndba_col_comments\ndba_col_pending_stats\ndba_col_privs\ndba_coll_types\ndba_common_audit_trail\ndba_comparison\ndba_comparison_columns\ndba_comparison_row_dif\ndba_comparison_scan\ndba_comparison_scan_values\ndba_connect_role_grantees\ndba_cons_obj_columns\ndba_constraints\ndba_context\ndba_cpool_info\ndba_cpu_usage_statistics\ndba_cq_notification_queries\ndba_cube_attr_visibility\ndba_cube_attributes\ndba_cube_build_processes\ndba_cube_calculated_members\ndba_cube_dim_levels\ndba_cube_dim_models\ndba_cube_dim_view_columns\ndba_cube_dim_views\ndba_cube_dimensionality\ndba_cube_dimensions\ndba_cube_hier_levels\ndba_cube_hier_view_columns\ndba_cube_hier_views\ndba_cube_hierarchies\ndba_cube_measures\ndba_cube_view_columns\ndba_cube_views\ndba_cubes\ndba_data_files\ndba_datapump_jobs\ndba_datapump_sessions\ndba_db_links\ndba_ddl_locks\ndba_dependencies\ndba_dim_attributes\ndba_dim_child_of\ndba_dim_hierarchies\ndba_dim_join_key\ndba_dim_level_key\ndba_dim_levels\ndba_dimensions\ndba_directories\ndba_dml_locks\ndba_dmt_free_space\ndba_dmt_used_extents\ndba_edition_comments\ndba_editioning_view_cols\ndba_editioning_view_cols_ae\ndba_editioning_views\ndba_editioning_views_ae\ndba_editions\ndba_enabled_aggregations\ndba_enabled_traces\ndba_encrypted_columns\ndba_epg_dad_authorization\ndba_errors\ndba_errors_ae\ndba_evaluation_context_tables\ndba_evaluation_context_vars\ndba_evaluation_contexts\ndba_exp_files\ndba_exp_objects\ndba_exp_version\ndba_extents\ndba_external_locations\ndba_external_tables\ndba_feature_usage_statistics\ndba_fga_audit_trail\ndba_file_group_export_info\ndba_file_group_files\ndba_file_group_tables\ndba_file_group_tablespaces\ndba_file_group_versions\ndba_file_groups\ndba_flashback_archive\ndba_flashback_archive_tables\ndba_flashback_archive_ts\ndba_flashback_txn_report\ndba_flashback_txn_state\ndba_free_space\ndba_free_space_coalesced\ndba_high_water_mark_statistics\ndba_hist_active_sess_history\ndba_hist_baseline\ndba_hist_baseline_details\ndba_hist_baseline_metadata\ndba_hist_baseline_template\ndba_hist_bg_event_summary\ndba_hist_buffer_pool_stat\ndba_hist_buffered_queues\ndba_hist_buffered_subscribers\ndba_hist_cluster_intercon\ndba_hist_colored_sql\ndba_hist_comp_iostat\ndba_hist_cr_block_server\ndba_hist_current_block_server\ndba_hist_database_instance\ndba_hist_datafile\ndba_hist_db_cache_advice\ndba_hist_dispatcher\ndba_hist_dlm_misc\ndba_hist_dyn_remaster_stats\ndba_hist_enqueue_stat\ndba_hist_event_histogram\ndba_hist_event_name\ndba_hist_filemetric_history\ndba_hist_filestatxs\ndba_hist_ic_client_stats\ndba_hist_ic_device_stats\ndba_hist_inst_cache_transfer\ndba_hist_instance_recovery\ndba_hist_interconnect_pings\ndba_hist_iostat_detail\ndba_hist_iostat_filetype\ndba_hist_iostat_filetype_name\ndba_hist_iostat_function\ndba_hist_iostat_function_name\ndba_hist_java_pool_advice\ndba_hist_latch\ndba_hist_latch_children\ndba_hist_latch_misses_summary\ndba_hist_latch_name\ndba_hist_latch_parent\ndba_hist_librarycache\ndba_hist_log\ndba_hist_mem_dynamic_comp\ndba_hist_memory_resize_ops\ndba_hist_memory_target_advice\ndba_hist_metric_name\ndba_hist_mttr_target_advice\ndba_hist_mutex_sleep\ndba_hist_optimizer_env\ndba_hist_osstat\ndba_hist_osstat_name\ndba_hist_parameter\ndba_hist_parameter_name\ndba_hist_persistent_qmn_cache\ndba_hist_persistent_queues\ndba_hist_persistent_subs\ndba_hist_pga_target_advice\ndba_hist_pgastat\ndba_hist_plan_operation_name\ndba_hist_plan_option_name\ndba_hist_process_mem_summary\ndba_hist_resource_limit\ndba_hist_rowcache_summary\ndba_hist_rsrc_consumer_group\ndba_hist_rsrc_plan\ndba_hist_rule_set\ndba_hist_seg_stat\ndba_hist_seg_stat_obj\ndba_hist_service_name\ndba_hist_service_stat\ndba_hist_service_wait_class\ndba_hist_sess_time_stats\ndba_hist_sessmetric_history\ndba_hist_sga\ndba_hist_sga_target_advice\ndba_hist_sgastat\ndba_hist_shared_pool_advice\ndba_hist_shared_server_summary\ndba_hist_snap_error\ndba_hist_snapshot\ndba_hist_sql_bind_metadata\ndba_hist_sql_plan\ndba_hist_sql_summary\ndba_hist_sql_workarea_hstgrm\ndba_hist_sqlbind\ndba_hist_sqlcommand_name\ndba_hist_sqlstat\ndba_hist_sqltext\ndba_hist_stat_name\ndba_hist_streams_apply_sum\ndba_hist_streams_capture\ndba_hist_streams_pool_advice\ndba_hist_sys_time_model\ndba_hist_sysmetric_history\ndba_hist_sysmetric_summary\ndba_hist_sysstat\ndba_hist_system_event\ndba_hist_tablespace_stat\ndba_hist_tbspc_space_usage\ndba_hist_tempfile\ndba_hist_tempstatxs\ndba_hist_thread\ndba_hist_toplevelcall_name\ndba_hist_undostat\ndba_hist_waitclassmet_history\ndba_hist_waitstat\ndba_hist_wr_control\ndba_histograms\ndba_identifiers\ndba_ind_columns\ndba_ind_expressions\ndba_ind_partitions\ndba_ind_pending_stats\ndba_ind_statistics\ndba_ind_subpartitions\ndba_indexes\ndba_indextype_arraytypes\ndba_indextype_comments\ndba_indextype_operators\ndba_indextypes\ndba_internal_triggers\ndba_java_arguments\ndba_java_classes\ndba_java_compiler_options\ndba_java_derivations\ndba_java_fields\ndba_java_implements\ndba_java_inners\ndba_java_layouts\ndba_java_methods\ndba_java_ncomps\ndba_java_policy\ndba_java_resolvers\ndba_java_throws\ndba_jobs\ndba_jobs_running\ndba_join_ind_columns\ndba_kgllock\ndba_libraries\ndba_lmt_free_space\ndba_lmt_used_extents\ndba_lob_partitions\ndba_lob_subpartitions\ndba_lob_templates\ndba_lobs\ndba_lock\ndba_lock_internal\ndba_locks\ndba_log_group_columns\ndba_log_groups\ndba_logmnr_log\ndba_logmnr_purged_log\ndba_logmnr_session\ndba_logstdby_events\ndba_logstdby_history\ndba_logstdby_log\ndba_logstdby_not_unique\ndba_logstdby_parameters\ndba_logstdby_progress\ndba_logstdby_skip\ndba_logstdby_skip_transaction\ndba_logstdby_unsupported\ndba_logstdby_unsupported_table\ndba_measure_folder_contents\ndba_measure_folders\ndba_method_params\ndba_method_results\ndba_mining_model_attributes\ndba_mining_model_settings\ndba_mining_models\ndba_mview_aggregates\ndba_mview_analysis\ndba_mview_comments\ndba_mview_detail_partition\ndba_mview_detail_relations\ndba_mview_detail_subpartition\ndba_mview_joins\ndba_mview_keys\ndba_mview_log_filter_cols\ndba_mview_logs\ndba_mview_refresh_times\ndba_mviews\ndba_nested_table_cols\ndba_nested_tables\ndba_network_acl_privileges\ndba_network_acls\ndba_obj_audit_opts\ndba_obj_colattrs\ndba_object_size\ndba_object_tables\ndba_objects\ndba_objects_ae\ndba_opancillary\ndba_oparguments\ndba_opbindings\ndba_operator_comments\ndba_operators\ndba_optstat_operations\ndba_orphan_key_table\ndba_outline_hints\ndba_outlines\ndba_outstanding_alerts\ndba_parallel_execute_chunks\ndba_parallel_execute_tasks\ndba_part_col_statistics\ndba_part_histograms\ndba_part_indexes\ndba_part_key_columns\ndba_part_lobs\ndba_part_tables\ndba_partial_drop_tabs\ndba_pending_conv_tables\ndba_pending_transactions\ndba_plsql_object_settings\ndba_policies\ndba_policy_contexts\ndba_policy_groups\ndba_priv_audit_opts\ndba_procedures\ndba_profiles\ndba_propagation\ndba_proxies\ndba_published_columns\ndba_queue_schedules\ndba_queue_subscribers\ndba_queue_tables\ndba_queues\ndba_rchild\ndba_recoverable_script\ndba_recoverable_script_blocks\ndba_recoverable_script_errors\ndba_recoverable_script_hist\ndba_recoverable_script_params\ndba_recyclebin\ndba_redefinition_errors\ndba_redefinition_objects\ndba_refresh\ndba_refresh_children\ndba_refs\ndba_registered_archived_log\ndba_registered_mview_groups\ndba_registered_mviews\ndba_registry\ndba_registry_hierarchy\ndba_registry_history\ndba_registry_log\ndba_repair_table\ndba_resource_incarnations\ndba_resumable\ndba_rewrite_equivalences\ndba_rgroup\ndba_role_privs\ndba_roles\ndba_rollback_segs\ndba_rsrc_categories\ndba_rsrc_consumer_group_privs\ndba_rsrc_consumer_groups\ndba_rsrc_group_mappings\ndba_rsrc_io_calibrate\ndba_rsrc_manager_system_privs\ndba_rsrc_mapping_priority\ndba_rsrc_plan_directives\ndba_rsrc_plans\ndba_rule_set_rules\ndba_rule_sets\ndba_rules\ndba_scheduler_chain_rules\ndba_scheduler_chain_steps\ndba_scheduler_chains\ndba_scheduler_credentials\ndba_scheduler_db_dests\ndba_scheduler_dests\ndba_scheduler_external_dests\ndba_scheduler_file_watchers\ndba_scheduler_global_attribute\ndba_scheduler_group_members\ndba_scheduler_groups\ndba_scheduler_job_args\ndba_scheduler_job_classes\ndba_scheduler_job_dests\ndba_scheduler_job_log\ndba_scheduler_job_roles\ndba_scheduler_job_run_details\ndba_scheduler_jobs\ndba_scheduler_notifications\ndba_scheduler_program_args\ndba_scheduler_programs\ndba_scheduler_remote_databases\ndba_scheduler_remote_jobstate\ndba_scheduler_running_chains\ndba_scheduler_running_jobs\ndba_scheduler_schedules\ndba_scheduler_window_details\ndba_scheduler_window_groups\ndba_scheduler_window_log\ndba_scheduler_windows\ndba_scheduler_wingroup_members\ndba_sec_relevant_cols\ndba_secondary_objects\ndba_segments\ndba_segments_old\ndba_sequences\ndba_server_registry\ndba_services\ndba_source\ndba_source_ae\ndba_source_tables\ndba_sql_management_config\ndba_sql_patches\ndba_sql_plan_baselines\ndba_sql_profiles\ndba_sqlj_type_attrs\ndba_sqlj_type_methods\ndba_sqlj_types\ndba_sqlset\ndba_sqlset_binds\ndba_sqlset_plans\ndba_sqlset_references\ndba_sqlset_statements\ndba_sqltune_binds\ndba_sqltune_plans\ndba_sqltune_rationale_plan\ndba_sqltune_statistics\ndba_sscr_capture\ndba_sscr_restore\ndba_stat_extensions\ndba_stmt_audit_opts\ndba_stored_settings\ndba_streams_add_column\ndba_streams_administrator\ndba_streams_columns\ndba_streams_delete_column\ndba_streams_global_rules\ndba_streams_keep_columns\ndba_streams_message_consumers\ndba_streams_message_rules\ndba_streams_newly_supported\ndba_streams_rename_column\ndba_streams_rename_schema\ndba_streams_rename_table\ndba_streams_rules\ndba_streams_schema_rules\ndba_streams_split_merge\ndba_streams_split_merge_hist\ndba_streams_stmt_handlers\ndba_streams_stmts\ndba_streams_table_rules\ndba_streams_tp_component\ndba_streams_tp_component_link\ndba_streams_tp_component_stat\ndba_streams_tp_database\ndba_streams_tp_path_bottleneck\ndba_streams_tp_path_stat\ndba_streams_transform_function\ndba_streams_transformations\ndba_streams_unsupported\ndba_subpart_col_statistics\ndba_subpart_histograms\ndba_subpart_key_columns\ndba_subpartition_templates\ndba_subscr_registrations\ndba_subscribed_columns\ndba_subscribed_tables\ndba_subscriptions\ndba_sync_capture\ndba_sync_capture_prepared_tabs\ndba_sync_capture_tables\ndba_synonyms\ndba_sys_privs\ndba_tab_col_statistics\ndba_tab_cols\ndba_tab_columns\ndba_tab_comments\ndba_tab_histgrm_pending_stats\ndba_tab_histograms\ndba_tab_modifications\ndba_tab_partitions\ndba_tab_pending_stats\ndba_tab_privs\ndba_tab_statistics\ndba_tab_stat_prefs\ndba_tab_stats_history\ndba_tab_subpartitions\ndba_tables\ndba_tablespace_groups\ndba_tablespace_thresholds\ndba_tablespace_usage_metrics\ndba_tablespaces\ndba_temp_files\ndba_temp_free_space\ndba_thresholds\ndba_transformations\ndba_trigger_cols\ndba_trigger_ordering\ndba_triggers\ndba_ts_quotas\ndba_tsm_destination\ndba_tsm_source\ndba_tstz_tab_cols\ndba_tstz_tables\ndba_tune_mview\ndba_type_attrs\ndba_type_methods\ndba_type_versions\ndba_types\ndba_undo_extents\ndba_unused_col_tabs\ndba_updatable_columns\ndba_users\ndba_users_with_defpwd\ndba_ustats\ndba_varrays\ndba_views\ndba_views_ae\ndba_waiters\ndba_wallet_acls\ndba_warning_settings\ndba_workload_captures\ndba_workload_connection_map\ndba_workload_filters\ndba_workload_replay_divergence\ndba_workload_replays\ndba_xml_indexes\ndba_xml_schemas\ndba_xml_tab_cols\ndba_xml_tables\ndba_xml_view_cols\ndba_xml_views\ndba_xstream_administrator\ndba_xstream_inbound\ndba_xstream_inbound_progress\ndba_xstream_out_support_mode\ndba_xstream_outbound\ndba_xstream_outbound_progress\ndba_xstream_rules\ndbfs_content\ndbfs_content_properties\ndbms_alert_info\ndbms_lock_allocated\ndeptree\ndict\ndict_columns\ndictionary\ndm_user_models\ndocument_links\nerror_size\nexceptions\nflashback_transaction_query\nglobal_name\nhs_all_caps\nhs_all_dd\nhs_all_inits\nhs_base_caps\nhs_base_dd\nhs_class_caps\nhs_class_dd\nhs_class_init\nhs_fds_class\nhs_fds_inst\nhs_inst_caps\nhs_inst_dd\nhs_inst_init\nideptree\nind\nindex_histogram\nindex_stats\nlogstdby_unsupported_tables\nmap_object\nnls_database_parameters\nnls_instance_parameters\nnls_session_parameters\nobj\npath_view\nplan_table\npluggable_set_check\nproduct_component_version\nproxy_users\npstubtbl\npublic_dependency\npublicsyn\nqueue_privileges\nrecyclebin\nreport_components\nreport_files\nreport_formats\nresource_cost\nresource_map\nresource_view\nrole_role_privs\nrole_sys_privs\nrole_tab_privs\nscheduler_batch_errors\nseq\nsession_context\nsession_privs\nsession_roles\nsource_size\nstmt_audit_option_map\nsyn\nsynonyms\nsys_objects\nsyscatalog\nsysfiles\nsyssegobj\nsystem_privilege_map\ntab\ntable_privilege_map\ntabquotas\ntabs\ntrusted_servers\nts_pitr_check\nts_pitr_objects_to_be_dropped\nuni_pluggable_set_check\nuser_addm_fdg_breakdown\nuser_addm_findings\nuser_addm_instances\nuser_addm_tasks\nuser_advisor_actions\nuser_advisor_dir_task_inst\nuser_advisor_exec_parameters\nuser_advisor_executions\nuser_advisor_fdg_breakdown\nuser_advisor_findings\nuser_advisor_journal\nuser_advisor_log\nuser_advisor_objects\nuser_advisor_parameters\nuser_advisor_rationale\nuser_advisor_recommendations\nuser_advisor_sqla_rec_sum\nuser_advisor_sqla_tables\nuser_advisor_sqla_wk_map\nuser_advisor_sqla_wk_stmts\nuser_advisor_sqlplans\nuser_advisor_sqlstats\nuser_advisor_sqlw_journal\nuser_advisor_sqlw_parameters\nuser_advisor_sqlw_stmts\nuser_advisor_sqlw_sum\nuser_advisor_sqlw_tables\nuser_advisor_sqlw_templates\nuser_advisor_tasks\nuser_advisor_templates\nuser_all_tables\nuser_aq_agent_privs\nuser_arguments\nuser_assemblies\nuser_associations\nuser_attribute_transformations\nuser_audit_object\nuser_audit_policies\nuser_audit_policy_columns\nuser_audit_session\nuser_audit_statement\nuser_audit_trail\nuser_aw_ps\nuser_aws\nuser_base_table_mviews\nuser_catalog\nuser_change_notification_regs\nuser_clu_columns\nuser_cluster_hash_expressions\nuser_clusters\nuser_col_comments\nuser_col_pending_stats\nuser_col_privs\nuser_col_privs_made\nuser_col_privs_recd\nuser_coll_types\nuser_comparison\nuser_comparison_columns\nuser_comparison_row_dif\nuser_comparison_scan\nuser_comparison_scan_values\nuser_cons_columns\nuser_cons_obj_columns\nuser_constraints\nuser_cq_notification_queries\nuser_cube_attr_visibility\nuser_cube_attributes\nuser_cube_build_processes\nuser_cube_calculated_members\nuser_cube_dim_levels\nuser_cube_dim_models\nuser_cube_dim_view_columns\nuser_cube_dim_views\nuser_cube_dimensionality\nuser_cube_dimensions\nuser_cube_hier_levels\nuser_cube_hier_view_columns\nuser_cube_hier_views\nuser_cube_hierarchies\nuser_cube_measures\nuser_cube_view_columns\nuser_cube_views\nuser_cubes\nuser_datapump_jobs\nuser_db_links\nuser_dbfs_hs_files\nuser_dependencies\nuser_dim_attributes\nuser_dim_child_of\nuser_dim_hierarchies\nuser_dim_join_key\nuser_dim_level_key\nuser_dim_levels\nuser_dimensions\nuser_editioning_view_cols\nuser_editioning_view_cols_ae\nuser_editioning_views\nuser_editioning_views_ae\nuser_encrypted_columns\nuser_epg_dad_authorization\nuser_errors\nuser_errors_ae\nuser_evaluation_context_tables\nuser_evaluation_context_vars\nuser_evaluation_contexts\nuser_extents\nuser_external_locations\nuser_external_tables\nuser_file_group_export_info\nuser_file_group_files\nuser_file_group_tables\nuser_file_group_tablespaces\nuser_file_group_versions\nuser_file_groups\nuser_flashback_archive\nuser_flashback_archive_tables\nuser_flashback_txn_report\nuser_flashback_txn_state\nuser_free_space\nuser_histograms\nuser_identifiers\nuser_ind_columns\nuser_ind_expressions\nuser_ind_partitions\nuser_ind_pending_stats\nuser_ind_statistics\nuser_ind_subpartitions\nuser_indexes\nuser_indextype_arraytypes\nuser_indextype_comments\nuser_indextype_operators\nuser_indextypes\nuser_internal_triggers\nuser_java_arguments\nuser_java_classes\nuser_java_compiler_options\nuser_java_derivations\nuser_java_fields\nuser_java_implements\nuser_java_inners\nuser_java_layouts\nuser_java_methods\nuser_java_ncomps\nuser_java_policy\nuser_java_resolvers\nuser_java_throws\nuser_jobs\nuser_join_ind_columns\nuser_libraries\nuser_lob_partitions\nuser_lob_subpartitions\nuser_lob_templates\nuser_lobs\nuser_log_group_columns\nuser_log_groups\nuser_measure_folder_contents\nuser_measure_folders\nuser_method_params\nuser_method_results\nuser_mining_model_attributes\nuser_mining_model_settings\nuser_mining_models\nuser_mview_aggregates\nuser_mview_analysis\nuser_mview_comments\nuser_mview_detail_partition\nuser_mview_detail_relations\nuser_mview_detail_subpartition\nuser_mview_joins\nuser_mview_keys\nuser_mview_logs\nuser_mview_refresh_times\nuser_mviews\nuser_nested_table_cols\nuser_nested_tables\nuser_network_acl_privileges\nuser_obj_audit_opts\nuser_obj_colattrs\nuser_object_size\nuser_object_tables\nuser_objects\nuser_objects_ae\nuser_opancillary\nuser_oparguments\nuser_opbindings\nuser_operator_comments\nuser_operators\nuser_outline_hints\nuser_outlines\nuser_parallel_execute_chunks\nuser_parallel_execute_tasks\nuser_part_col_statistics\nuser_part_histograms\nuser_part_indexes\nuser_part_key_columns\nuser_part_lobs\nuser_part_tables\nuser_partial_drop_tabs\nuser_password_limits\nuser_pending_conv_tables\nuser_plsql_object_settings\nuser_policies\nuser_policy_contexts\nuser_policy_groups\nuser_procedures\nuser_proxies\nuser_published_columns\nuser_queue_schedules\nuser_queue_subscribers\nuser_queue_tables\nuser_queues\nuser_recyclebin\nuser_refresh\nuser_refresh_children\nuser_refs\nuser_registered_mviews\nuser_registry\nuser_resource_limits\nuser_resumable\nuser_rewrite_equivalences\nuser_role_privs\nuser_rsrc_consumer_group_privs\nuser_rsrc_manager_system_privs\nuser_rule_set_rules\nuser_rule_sets\nuser_rules\nuser_scheduler_chain_rules\nuser_scheduler_chain_steps\nuser_scheduler_chains\nuser_scheduler_credentials\nuser_scheduler_db_dests\nuser_scheduler_dests\nuser_scheduler_file_watchers\nuser_scheduler_group_members\nuser_scheduler_groups\nuser_scheduler_job_args\nuser_scheduler_job_dests\nuser_scheduler_job_log\nuser_scheduler_job_run_details\nuser_scheduler_jobs\nuser_scheduler_notifications\nuser_scheduler_program_args\nuser_scheduler_programs\nuser_scheduler_remote_jobstate\nuser_scheduler_running_chains\nuser_scheduler_running_jobs\nuser_scheduler_schedules\nuser_sec_relevant_cols\nuser_secondary_objects\nuser_segments\nuser_sequences\nuser_source\nuser_source_ae\nuser_source_tables\nuser_sqlj_type_attrs\nuser_sqlj_type_methods\nuser_sqlj_types\nuser_sqlset\nuser_sqlset_binds\nuser_sqlset_plans\nuser_sqlset_references\nuser_sqlset_statements\nuser_sqltune_binds\nuser_sqltune_plans\nuser_sqltune_rationale_plan\nuser_sqltune_statistics\nuser_stat_extensions\nuser_stored_settings\nuser_subpart_col_statistics\nuser_subpart_histograms\nuser_subpart_key_columns\nuser_subpartition_templates\nuser_subscr_registrations\nuser_subscribed_columns\nuser_subscribed_tables\nuser_subscriptions\nuser_synonyms\nuser_sys_privs\nuser_tab_col_statistics\nuser_tab_cols\nuser_tab_columns\nuser_tab_comments\nuser_tab_histgrm_pending_stats\nuser_tab_histograms\nuser_tab_modifications\nuser_tab_partitions\nuser_tab_pending_stats\nuser_tab_privs\nuser_tab_privs_made\nuser_tab_privs_recd\nuser_tab_stat_prefs\nuser_tab_statistics\nuser_tab_stats_history\nuser_tab_subpartitions\nuser_tables\nuser_tablespaces\nuser_transformations\nuser_trigger_cols\nuser_trigger_ordering\nuser_triggers\nuser_ts_quotas\nuser_tstz_tab_cols\nuser_tstz_tables\nuser_tune_mview\nuser_type_attrs\nuser_type_methods\nuser_type_versions\nuser_types\nuser_unused_col_tabs\nuser_updatable_columns\nuser_users\nuser_ustats\nuser_varrays\nuser_views\nuser_views_ae\nuser_warning_settings\nuser_xml_indexes\nuser_xml_schemas\nuser_xml_tab_cols\nuser_xml_tables\nuser_xml_view_cols\nuser_xml_views\nxs_session_roles"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/oracle/dialect.properties",
    "content": "quote=',\"\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/oracle/keywords",
    "content": "access\nadd\nall\nalter\nand\nany\nas\nasc\naudit\nbetween\nby\nchar\ncheck\ncluster\ncolumn\ncolumn_value\ncomment\ncompress\nconnect\ncreate\ncurrent\ndate\ndecimal\ndefault\ndelete\ndesc\ndistinct\ndrop\nelse\nexclusive\nexists\nfile\nfloat\nfor\nfrom\ngrant\ngroup\nhaving\nidentified\nimmediate\nin\nincrement\nindex\ninitial\ninsert\ninteger\nintersect\ninto\nis\nlevel\nlike\nlock\nlong\nmaxextents\nminus\nmlslabel\nmode\nmodify\nnested_table_id\nnoaudit\nnocompress\nnot\nnowait\nnull\nnumber\nof\noffline\non\nonline\noption\nor\norder\npctfree\nprior\npublic\nraw\nrename\nresource\nrevoke\nrow\nrowid\nrownum\nrows\nselect\nsession\nset\nshare\nsize\nsmallint\nstart\nsuccessful\nsynonym\nsysdate\ntable\nthen\nto\ntrigger\nuid\nunion\nunique\nupdate\nuser\nvalidate\nvalues\nvarchar\nvarchar2\nview\nwhenever\nwhere\nwith"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/postgresql/keywords",
    "content": "abs\nall\nallocate\nanalyse\nanalyze\nand\nany\nare\narray\narray_agg\narray_max_cardinality\nas\nasensitive\nasymmetric\natomic\nauthorization\navg\nbegin_frame\nbegin_partition\nbinary\nbit_length\nblob\nboth\nby\ncall\ncardinality\ncase\ncast\nceil\nceiling\ncharacter_length\nchar_length\ncheck\nclob\ncollate\ncollect\ncolumn\nconcurrently\ncondition\nconnect\nconstraint\nconvert\ncorr\ncorresponding\ncount\ncovar_pop\ncovar_samp\ncreate\ncross\ncume_dist\ncurrent_catalog\ncurrent_date\ncurrent_default_transform_group\ncurrent_path\ncurrent_role\ncurrent_row\ncurrent_schema\ncurrent_time\ncurrent_timestamp\ncurrent_transform_group_for_type\ncurrent_user\ndatalink\ndate\ndefault\ndeferrable\ndense_rank\nderef\ndesc\ndescribe\ndeterministic\ndisconnect\ndistinct\ndlnewcopy\ndlpreviouscopy\ndlurlcomplete\ndlurlcompleteonly\ndlurlcompletewrite\ndlurlpath\ndlurlpathonly\ndlurlpathwrite\ndlurlscheme\ndlurlserver\ndlvalue\ndo\ndynamic\nelement\nelse\nend\nend-exec\nend_frame\nend_partition\nevery\nexcept\nexception\nexec\nexp\nfalse\nfetch\nfinal\nfirst_value\nfloor\nfor\nforeign\nframe_row\nfree\nfreeze\nfrom\nfull\nfusion\nget\ngrant\ngroup\ngroups\nhaving\nilike\nin\nindicator\ninner\nintersect\nintersection\ninto\ninstantiable\nis\nisnull\njoin\nlag\nlast_value\nlateral\nlead\nleading\nleft\nlike\nlike_regex\nlimit\nln\nlocaltime\nlocaltimestamp\nlower\nmax\nmax_cardinality\nmerge\nmin\nmod\nmodifies\nmultiset\nnatural\nnclob\nnormalize\nnot\nnotnull\nnth_value\nntile\nnull\noccurrences_regex\noctet_length\noid\noffset\non\nonly\nopen\nor\norder\nouter\nover\noverlaps\nparameter\npercent\npercentile_cont\npercentile_disc\npercent_rank\nperiod\nplacing\nportion\nposition_regex\npower\nprecedes\nprimary\nrank\nreads\nreferences\nregr_avgx\nregr_avgy\nregr_count\nregr_intercept\nregr_r2\nregr_slope\nregr_sxx\nregr_sxy\nregr_syy\nresult\nreturn\nreturning\nright\nrow_number\nscope\nselect\nsensitive\nsession_user\nsimilar\nsome\nspecific\nspecifictype\nsqlcode\nsqlerror\nsqlexception\nsqlstate\nsqlwarning\nsqrt\nstatic\nstddev_pop\nstddev_samp\nsubmultiset\nsubstring_regex\nsucceeds\nsum\nsymmetric\nsystem_time\nsystem_user\ntable\ntablesample\nthen\ntimezone_hour\ntimezone_minute\nto\ntrailing\ntranslate\ntranslate_regex\ntranslation\ntrim_array\ntrue\nuescape\nunion\nunique\nunnest\nupper\nuser\nusing\nvalue_of\nvarbinary\nvariadic\nvar_pop\nvar_samp\nverbose\nversioning\nwhen\nwhenever\nwhere\nwidth_bucket\nwindow\nwith\nxmlagg\nxmlbinary\nxmlcast\nxmlcomment\nxmldocument\nxmliterate\nxmlquery\nxmltext\nxmlvalidate"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/spark/alias_keywords",
    "content": "ALL\nALTER\nAND\nANY\nARRAY\nAS\nAT\nAUTHORIZATION\nBETWEEN\nBIGINT\nBINARY\nBOOLEAN\nBOTH\nBY\nCASE\nCAST\nCHAR\nCHARACTER\nCHECK\nCONSTRAINT\nCREATE\nCROSS\nCUBE\nCURRENT\nCURRENT_DATE\nCURRENT_TIME\nCURRENT_TIMESTAMP\nCURRENT_USER\nDATE\nDEC\nDECIMAL\nDELETE\nDESC\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nELSE\nEND\nESCAPE\nEXCEPT\nEXISTS\nEXTRACT\nFALSE\nFETCH\nFILTER\nFLOAT\nFOR\nFOREIGN\nFROM\nFULL\nFUNCTION\nGENERATED\nGLOBAL\nGRANT\nGROUP\nGROUPING\nHAVING\nIF\nIN\nINNER\nINSERT\nINT\nINTEGER\nINTERSECT\nINTERVAL\nINTO\nIS\nJOIN\nLATERAL\nLEADING\nLEFT\nLIKE\nLOCAL\nNOT\nNULL\nNUMERIC\nOF\nOFFSET\nON\nONLY\nOR\nORDER\nOUTER\nOVERLAPS\nOVERLAY\nPARTITION\nPERCENTILE_CONT\nPERCENTILE_DISC\nPOSITION\nPRIMARY\nPROCEDURE\nRANGE\nREAL\nREFERENCES\nREVOKE\nRIGHT\nROLLBACK\nROLLUP\nROW\nROWS\nSELECT\nSESSION_USER\nSET\nSMALLINT\nSOME\nSTART\nSTRING\nSTRUCT\nSUBSTR\nSUBSTRING\nSYSTEM_TIME\nSYSTEM_VERSION\nTABLE\nTABLESAMPLE\nTHEN\nTIME\nTIMESTAMP\nTINYINT\nTO\nTRAILING\nTRANSFORM\nTRUE\nTRUNCATE\nUNION\nUNIQUE\nUNKNOWN\nUNPIVOT\nUPDATE\nUSER\nUSING\nVALUES\nVARCHAR\nVIEW\nWHEN\nWHERE\nWINDOW\nWITH\nWITHIN"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/spark/builtin_datatypes",
    "content": "TINYINT\nSMALLINT\nMEDIUMINT\nINT\nINTEGER\nBIGINT\nDECIMAL\nNUMERIC\nFLOAT\nDOUBLE\nDATE\nDATETIME\nTIMESTAMP\nINTERVAL\nSTRING\nVARCHAR\nCHAR\nBOOLEAN\nBINARY\nARRAY\nMAP\nSTRUCT\nUNIONTYPE"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/spark/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/spark/keywords",
    "content": "ALL\nALTER\nAND\nANY\nARRAY\nAS\nAT\nAUTHORIZATION\nBETWEEN\nBIGINT\nBINARY\nBOOLEAN\nBOTH\nBY\nCASE\nCAST\nCHAR\nCHARACTER\nCHECK\nCONSTRAINT\nCREATE\nCROSS\nCUBE\nCURRENT\nCURRENT_DATE\nCURRENT_TIME\nCURRENT_TIMESTAMP\nCURRENT_USER\nDATE\nDEC\nDECIMAL\nDELETE\nDESC\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nELSE\nEND\nESCAPE\nEXCEPT\nEXISTS\nEXTRACT\nFALSE\nFETCH\nFILTER\nFLOAT\nFOR\nFOREIGN\nFROM\nFULL\nFUNCTION\nGENERATED\nGLOBAL\nGRANT\nGROUP\nGROUPING\nHAVING\nIF\nIN\nINNER\nINSERT\nINT\nINTEGER\nINTERSECT\nINTERVAL\nINTO\nIS\nJOIN\nLATERAL\nLEADING\nLEFT\nLIKE\nLOCAL\nNOT\nNULL\nNUMERIC\nOF\nOFFSET\nON\nONLY\nOR\nORDER\nOUTER\nOVERLAPS\nOVERLAY\nPARTITION\nPERCENTILE_CONT\nPERCENTILE_DISC\nPOSITION\nPRIMARY\nPROCEDURE\nRANGE\nREAL\nREFERENCES\nREVOKE\nRIGHT\nROLLBACK\nROLLUP\nROW\nROWS\nSELECT\nSESSION_USER\nSET\nSMALLINT\nSOME\nSTART\nSTRING\nSTRUCT\nSUBSTR\nSUBSTRING\nSYSTEM_TIME\nSYSTEM_VERSION\nTABLE\nTABLESAMPLE\nTHEN\nTIME\nTIMESTAMP\nTINYINT\nTO\nTRAILING\nTRANSFORM\nTRUE\nTRUNCATE\nUNION\nUNIQUE\nUNKNOWN\nUNPIVOT\nUPDATE\nUSER\nUSING\nVALUES\nVARCHAR\nVIEW\nWHEN\nWHERE\nWINDOW\nWITH\nWITHIN"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/sqlite/builtin_datatypes",
    "content": "INTEGER\nINT\nTINYINT\nSMALLINT\nMEDIUMINT\nBIGINT\nREAL\nDOUBLE\nFLOAT\nNUMERIC\nDECIMAL\nTEXT\nVARCHAR\nCHAR\nNCHAR\nNVARCHAR\nCLOB\nBLOB\nBOOLEAN\nDATE\nDATETIME\nTIMESTAMP\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/sqlite/dialect.properties",
    "content": "quote=\",`,[\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/sqlserver/dialect.properties",
    "content": "quote=[,\"\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/starrocks/dialect.properties",
    "content": "quote=`\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/starrocks/keywords",
    "content": "ADD\nALL\nALTER\nANALYZE\nAND\nARRAY\nAS\nASC\nBETWEEN\nBIGINT\nBITMAP\nBOTH\nBY\nCASE\nCHAR\nCHARACTER\nCHECK\nCOLLATE\nCOLUMN\nCOMPACTION\nCONVERT\nCREATE\nCROSS\nCUBE\nCURRENT_DATE\nCURRENT_TIME\nCURRENT_TIMESTAMP\nCURRENT_USER\nCURRENT_ROLE\nDATABASE\nDATABASES\nDECIMAL\nDECIMALV2\nDECIMAL32\nDECIMAL64\nDECIMAL128\nDEFAULT\nDELETE\nDENSE_RANK\nDESC\nDESCRIBE\nDISTINCT\nDOUBLE\nDROP\nDUAL\nDEFERRED\nELSE\nEXCEPT\nEXISTS\nEXPLAIN\nFALSE\nFIRST_VALUE\nFLOAT\nFOR\nFORCE\nFROM\nFULL\nFUNCTION\nGRANT\nGROUP\nGROUPS\nGROUPING\nGROUPING_ID\nHAVING\nHLL\nHOST\nIF\nIGNORE\nIN\nINDEX\nINFILE\nINNER\nINSERT\nINT\nINTEGER\nINTERSECT\nINTO\nIS\nIMMEDIATE\nJOIN\nJSON\nKEY\nKEYS\nKILL\nLAG\nLARGEINT\nLAST_VALUE\nLATERAL\nLEAD\nLEFT\nLIKE\nLIMIT\nLOAD\nLOCALTIME\nLOCALTIMESTAMP\nMAXVALUE\nMINUS\nMOD\nNTILE\nNOT\nNULL\nON\nOR\nORDER\nOUTER\nOUTFILE\nOVER\nPARTITION\nPERCENTILE\nPRIMARY\nPROCEDURE\nQUALIFY\nRANGE\nRANK\nREAD\nREGEXP\nRELEASE\nRENAME\nREPLACE\nREVOKE\nRIGHT\nRLIKE\nROW\nROWS\nROW_NUMBER\nSCHEMA\nSCHEMAS\nSELECT\nSET\nSET_VAR\nSHOW\nSMALLINT\nSYSTEM\nTABLE\nTERMINATED\nTEXT\nTHEN\nTINYINT\nTO\nTRUE\nUNION\nUNIQUE\nUNSIGNED\nUPDATE\nUSE\nUSING\nVALUES\nVARCHAR\nWHEN\nWHERE\nWITH"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/parser/synapse/dialect.properties",
    "content": "quote=[,\"\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/clickhouse/deny-function.txt",
    "content": "file"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/clickhouse/deny-schema.txt",
    "content": "system"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/mysql/deny-function.txt",
    "content": "version\nload_file\ndatabase\nschema\nuser\nsystem_user\nsession_user\nbenchmark\ncurrent_user\nsleep\nxmltype\nreceive_message"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/mysql/deny-schema.txt",
    "content": "information_schema\nmysql\nperformance_schema"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/mysql/deny-variant.txt",
    "content": "basedir\nversion_compile_os\nversion\ndatadir"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/mysql/permit-function.txt",
    "content": "abs\nacos\nadddate\naddtime\naes_decrypt\naes_encrypt\nascii\nasin\natan\natan2\navg\nbin\nbinary\nbit_and\nbit_count\nbit_length\nbit_or\nbit_xor\ncast\nceil\nceiling\nchar_length\nchar\ncharacter_length\ncharset\ncoalesce\ncoercibility\ncollation\ncompress\nconcat_ws\nconcat\nconv\nconvert_tz\nconvert\ncos\ncot\ncount(distinct)\ncount\ncrc32\ncurdate\ncurrent_date\ncurrent_time\ncurrent_timestamp\ncurtime\ndate_add\ndate_format\ndate_sub\ndate\ndatediff\nday\ndayname\ndayofmonth\ndayofweek\ndayofyear\ndecode\ndefault\ndegrees\ndes_decrypt\ndes_encrypt\ndiv\nelt\nencode\nencrypt\nexp\nexport_set\nextract\nextractvalue\nfield\nfind_in_set\nfloor\nformat\nfound_rows\nfrom_base64\nfrom_days\nfrom_unixtime\nget_format\ngreatest\ngroup_concat\ngtid_subset\ngtid_subtract\nhex\nhour\nif\nifnull\ninet_aton\ninet_ntoa\ninet6_aton\ninet6_ntoa\ninsert\ninstr\ninterval\nis_free_lock\nis_ipv4_compat\nis_ipv4_mapped\nis_ipv4\nis_ipv6\nis_used_lock\nlast_day\nlast_insert_id\nlcase\nleast\nleft\nlength\nln\nlocaltime\nlocaltimestamp\nlocate\nlog10\nlog2\nlog\nlower\nlpad\nltrim\nmake_set\nmakedate\nmaketime\nmaster_pos_wait\nmatch\nmax\nmd5\nmicrosecond\nmid\nmin\nminute\nmod\nmonth\nmonthname\nname_const\nnot\nnow\nnullif\noct\noctet_length\nold_password\nord\npassword\nperiod_add\nperiod_diff\npi\nposition\npow\npower\nprocedure\nquarter\nquote\nradians\nrand\nregexp\nrelease_lock\nrepeat\nreplace\nreverse\nright\nrlike\nround\nrow_count\nrpad\nrtrim\nsec_to_time\nsecond\nsha1\nsha2\nsign\nsin\nsleep\nsoundex\nsounds\nspace\nsqrt\nstd\nstddev_pop\nstddev_samp\nstddev\nstr_to_date\nstrcmp\nsubdate\nsubstr\nsubstring_index\nsubstring\nsubtime\nsum\nsysdate\ntan\ntime_format\ntime_to_sec\ntime\ntimediff\ntimestamp\ntimestampadd\ntimestampdiff\nto_base64\nto_days\nto_seconds\ntrim\ntruncate\nucase\nuncompress\nuncompressed_length\nunhex\nunix_timestamp\nupdatexml\nupper\nutc_date\nutc_time\nutc_timestamp\nuuid_short\nuuid\nvalidate_password_strength\nvalues\nvar_pop\nvar_samp\nvariance\nwait_until_sql_thread_after_gtids\nweek\nweekday\nweekofyear\nweight_string\nyear\nyearweek"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/mysql/permit-variant.txt",
    "content": "auto_increment_increment\nauto_increment_offset\nautocommit\nautomatic_sp_privileges\ncharacter_set_client\ncharacter_set_database\ncharacter_set_connection\ncharacter_set_results\ncharacter-set-server\ncollation_connection\ncollation_database\ncollation-server\ninsert_id\nlast_insert_id\nread_only\nsql_auto_is_null\nsql_big_selects\nsql_big_tables\nsql_mode\ntx_isolation\nwarning_count\nidentity"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/oracle/deny-function.txt",
    "content": "SYS_CONTEXT\nUSERENV\nSYS_TYPEID"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/oracle/deny-object.txt",
    "content": "APEX_CUSTOM_AUTH\nAPEX_APPLICATION\nAPEX_ITEM\nAPEX_UTIL\nCTX_ADM\nCTX_CLS\nCTX_DDL\nCTX_DOC\nCTX_ENTITY\nCTX_OUTPUT\nCTX_QUERY\nCTX_REPORT\nCTX_THES\nCTX_ULEXER\nDBMS_ADDM\nDBMS_ADVANCED_REWRITE\nDBMS_ADVISOR\nDBMS_ALERT\nDBMS_APPLICATION_INFO\nDBMS_APPLY_ADM\nDBMS_AQ\nDBMS_AQADM\nDBMS_AQELM\nDBMS_AQIN\nDBMS_ASSERT\nDBMS_AUDIT_MGMT\nDBMS_AUTO_SQLTUNE\nDBMS_AUTO_TASK_ADMIN\nDBMS_AUTO_TASK_IMMEDIATE\nDBMS_AW_STATS\nDBMS_CAPTURE_ADM\nDBMS_CDC_PUBLISH\nDBMS_CDC_SUBSCRIBE\nDBMS_COMPARISON\nDBMS_COMPRESSION\nDBMS_CONNECTION_POOL\nDBMS_CQ_NOTIFICATION\nDBMS_CRYPTO\nDBMS_CSX_ADMIN\nDBMS_CUBE\nDBMS_CUBE_ADVISE\nDBMS_CUBE_LOG\nDBMS_DATA_MINING\nDBMS_DATA_MINING_TRANSFORM\nDBMS_DATAPUMP\nDBMS_DBFS_CONTENT\nDBMS_DBFS_CONTENT_SPI\nDBMS_DBFS_HS\nDBMS_DBFS_SFS\nDBMS_DB_VERSION\nDBMS_DEBUG\nDBMS_DDL\nDBMS_DEFER\nDBMS_DEFER_QUERY\nDBMS_DEFER_SYS\nDBMS_DESCRIBE\nDBMS_DG\nDBMS_DIMENSION\nDBMS_DST\nDBMS_DISTRIBUTED_TRUST_ADMIN\nDBMS_EDITIONS_UTILITIES\nDBMS_EPG\nDBMS_ERRLOG\nDBMS_EXPFIL\nDBMS_FGA\nDBMS_FILE_GROUP\nDBMS_FILE_TRANSFER\nDBMS_FLASHBACK\nDBMS_FLASHBACK_ARCHIVE\nDBMS_FREQUENT_ITEMSET\nDBMS_HM\nDBMS_HPROF\nDBMS_HS_PARALLEL\nDBMS_HS_PASSTHROUGH\nDBMS_IOT\nDBMS_JAVA\nDBMS_JOB\nDBMS_LDAP\nDBMS_LDAP_UTL\nDBMS_LIBCACHE\nDBMS_LOB\nDBMS_LOCK\nDBMS_LOGMNR\nDBMS_LOGMNR_D\nDBMS_LOGSTDBY\nDBMS_METADATA\nDBMS_METADATA_DIFF\nDBMS_MGD_ID_UTL\nDBMS_MGWADM\nDBMS_MGWMSG\nDBMS_MONITOR\nDBMS_MVIEW\nDBMS_NETWORK_ACL_ADMIN\nDBMS_NETWORK_ACL_UTILITY\nDBMS_OBFUSCATION_TOOLKIT\nDBMS_ODCI\nDBMS_OFFLINE_OG\nDBMS_OUTLN\nDBMS_OUTPUT\nDBMS_PARALLEL_EXECUTE\nDBMS_PCLXUTIL\nDBMS_PIPE\nDBMS_PREDICTIVE_ANALYTICS\nDBMS_PREPROCESSOR\nDBMS_PROFILER\nDBMS_PROPAGATION_ADM\nDBMS_RANDOM\nDBMS_RECTIFIER_DIFF\nDBMS_REDEFINITION\nDBMS_REFRESH\nDBMS_REPAIR\nDBMS_REPCAT\nDBMS_REPCAT_ADMIN\nDBMS_REPCAT_INSTANTIATE\nDBMS_REPCAT_RGT\nDBMS_REPUTIL\nDBMS_RESCONFIG\nDBMS_RESOURCE_MANAGER\nDBMS_RESOURCE_MANAGER_PRIVS\nDBMS_RESULT_CACHE\nDBMS_RESUMABLE\nDBMS_RLMGR\nDBMS_RLS\nDBMS_ROWID\nDBMS_RULE\nDBMS_RULE_ADM\nDBMS_SCHEDULER\nDBMS_SERVER_ALERT\nDBMS_SERVICE\nDBMS_SESSION\nDBMS_SHARED_POOL\nDBMS_SPACE\nDBMS_SPACE_ADMIN\nDBMS_SPM\nDBMS_SQL\nDBMS_SQLDIAG\nDBMS_SQLPA\nDBMS_SQLTUNE\nDBMS_STAT_FUNCS\nDBMS_STATS\nDBMS_STORAGE_MAP\nDBMS_STREAMS\nDBMS_STREAMS_ADM\nDBMS_STREAMS_ADVISOR_ADM\nDBMS_STREAMS_AUTH\nDBMS_STREAMS_HANDLER_ADM\nDBMS_STREAMS_MESSAGING\nDBMS_STREAMS_TABLESPACE_ADM\nDBMS_TDB\nDBMS_TRACE\nDBMS_TRANSACTION\nDBMS_TRANSFORM\nDBMS_TTS\nDBMS_TYPES\nDBMS_UTILITY\nDBMS_WARNING\nDBMS_WM\nDBMS_WORKLOAD_CAPTURE\nDBMS_WORKLOAD_REPLAY\nDBMS_WORKLOAD_REPOSITORY\nDBMS_XA\nDBMS_XDB\nDBMS_XDB_ADMIN\nDBMS_XDB_VERSION\nDBMS_XDBRESOURCE\nDBMS_XDBT\nDBMS_XDBZ\nDBMS_XEVENT\nDBMS_XMLDOM\nDBMS_XMLGEN\nDBMS_XMLINDEX\nDBMS_XMLPARSER\nDBMS_XMLQUERY\nDBMS_XMLSAVE\nDBMS_XMLSCHEMA\nDBMS_XMLSTORE\nDBMS_XMLTRANSLATIONS\nDBMS_XPLAN\nDBMS_XSLPROCESSOR\nDEBUG_EXTPROC\nHTF\nHTP\nORD_DICOM\nORD_DICOM_ADMIN\nOWA_CACHE\nOWA_COOKIE\nOWA_CUSTOM\nOWA_IMAGE\nOWA_OPT_LOCK\nOWA_PATTERN\nOWA_SEC\nOWA_TEXT\nOWA_UTIL\nSDO_CS\nSDO_CSW_PROCESS\nSDO_GCDR\nSDO_GEOM\nSDO_GEOR\nSDO_GEOR_ADMIN\nSDO_GEOR_UTL\nSDO_LRS\nSDO_MIGRATE\nSDO_NET\nSDO_NET_MEM\nSDO_OLS\nSDO_PC_PKG\nSDO_SAM\nSDO_TIN_PKG\nSDO_TOPO\nSDO_TOPO_MAP\nSDO_TUNE\nSDO_UTIL\nSDO_WFS_LOCK\nSDO_WFS_PROCESS\nSEM_APIS\nSEM_PERF\nSEM_RDFCTX\nSEM_RDFSA\nUTL_COLL\nUTL_COMPRESS\nUTL_ENCODE\nUTL_FILE\nUTL_HTTP\nUTL_I18N\nUTL_INADDR\nUTL_IDENT\nUTL_LMS\nUTL_MAIL\nUTL_MATCH\nUTL_NLA\nUTL_RAW\nUTL_RECOMP\nUTL_REF\nUTL_SMTP\nUTL_SPADV\nUTL_TCP\nUTL_URL\nSYS\nSYSTEM"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/oracle/deny-schema.txt",
    "content": "SYS\nSYSTEM"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/oracle/deny-table.txt",
    "content": "ALL_ALL_TABLES\nALL_APPLY\nALL_APPLY_CHANGE_HANDLERS\nALL_APPLY_CONFLICT_COLUMNS\nALL_APPLY_DML_HANDLERS\nALL_APPLY_ENQUEUE\nALL_APPLY_ERROR\nALL_APPLY_ERROR_MESSAGES\nALL_APPLY_EXECUTE\nALL_APPLY_KEY_COLUMNS\nALL_APPLY_PARAMETERS\nALL_APPLY_PROGRESS\nALL_APPLY_TABLE_COLUMNS\nALL_ARGUMENTS\nALL_ASSEMBLIES\nALL_ASSOCIATIONS\nALL_AUDIT_POLICIES\nALL_AUDIT_POLICY_COLUMNS\nALL_AW_PS\nALL_AWS\nALL_BASE_TABLE_MVIEWS\nALL_CAPTURE\nALL_CAPTURE_EXTRA_ATTRIBUTES\nALL_CAPTURE_PARAMETERS\nALL_CAPTURE_PREPARED_DATABASE\nALL_CAPTURE_PREPARED_SCHEMAS\nALL_CAPTURE_PREPARED_TABLES\nALL_CATALOG\nALL_CHANGE_PROPAGATION_SETS\nALL_CHANGE_PROPAGATIONS\nALL_CHANGE_SETS\nALL_CHANGE_SOURCES\nALL_CHANGE_TABLES\nALL_CLUSTER_HASH_EXPRESSIONS\nALL_CLUSTERS\nALL_COL_COMMENTS\nALL_COL_PENDING_STATS\nALL_COL_PRIVS\nALL_COL_PRIVS_MADE\nALL_COL_PRIVS_RECD\nALL_COLL_TYPES\nALL_CONS_COLUMNS\nALL_CONS_OBJ_COLUMNS\nALL_CONSTRAINTS\nALL_CONTEXT\nALL_CUBE_ATTR_VISIBILITY\nALL_CUBE_ATTRIBUTES\nALL_CUBE_BUILD_PROCESSES\nALL_CUBE_CALCULATED_MEMBERS\nALL_CUBE_DIM_LEVELS\nALL_CUBE_DIM_MODELS\nALL_CUBE_DIM_VIEW_COLUMNS\nALL_CUBE_DIM_VIEWS\nALL_CUBE_DIMENSIONALITY\nALL_CUBE_DIMENSIONS\nALL_CUBE_HIER_LEVELS\nALL_CUBE_HIER_VIEW_COLUMNS\nALL_CUBE_HIER_VIEWS\nALL_CUBE_HIERARCHIES\nALL_CUBE_MEASURES\nALL_CUBE_VIEW_COLUMNS\nALL_CUBE_VIEWS\nALL_CUBES\nALL_DB_LINKS\nALL_DEF_AUDIT_OPTS\nALL_DEPENDENCIES\nALL_DEQUEUE_QUEUES\nALL_DIM_ATTRIBUTES\nALL_DIM_CHILD_OF\nALL_DIM_HIERARCHIES\nALL_DIM_JOIN_KEY\nALL_DIM_LEVEL_KEY\nALL_DIM_LEVELS\nALL_DIMENSIONS\nALL_DIRECTORIES\nALL_EDITION_COMMENTS\nALL_EDITIONING_VIEW_COLS\nALL_EDITIONING_VIEW_COLS_AE\nALL_EDITIONING_VIEWS\nALL_EDITIONING_VIEWS_AE\nALL_EDITIONS\nALL_ENCRYPTED_COLUMNS\nALL_ERRORS\nALL_ERRORS_AE\nALL_EVALUATION_CONTEXT_TABLES\nALL_EVALUATION_CONTEXT_VARS\nALL_EVALUATION_CONTEXTS\nALL_EXTERNAL_LOCATIONS\nALL_EXTERNAL_TABLES\nALL_FILE_GROUP_EXPORT_INFO\nALL_FILE_GROUP_FILES\nALL_FILE_GROUP_TABLES\nALL_FILE_GROUP_TABLESPACES\nALL_FILE_GROUP_VERSIONS\nALL_FILE_GROUPS\nALL_HISTOGRAMS\nALL_IDENTIFIERS\nALL_IND_COLUMNS\nALL_IND_EXPRESSIONS\nALL_IND_PARTITIONS\nALL_IND_PENDING_STATS\nALL_IND_STATISTICS\nALL_IND_SUBPARTITIONS\nALL_INDEXES\nALL_INDEXTYPE_ARRAYTYPES\nALL_INDEXTYPE_COMMENTS\nALL_INDEXTYPE_OPERATORS\nALL_INDEXTYPES\nALL_INTERNAL_TRIGGERS\nALL_JAVA_ARGUMENTS\nALL_JAVA_CLASSES\nALL_JAVA_COMPILER_OPTIONS\nALL_JAVA_DERIVATIONS\nALL_JAVA_FIELDS\nALL_JAVA_IMPLEMENTS\nALL_JAVA_INNERS\nALL_JAVA_LAYOUTS\nALL_JAVA_METHODS\nALL_JAVA_NCOMPS\nALL_JAVA_RESOLVERS\nALL_JAVA_THROWS\nALL_JOBS\nALL_JOIN_IND_COLUMNS\nALL_LIBRARIES\nALL_LOB_PARTITIONS\nALL_LOB_SUBPARTITIONS\nALL_LOB_TEMPLATES\nALL_LOBS\nALL_LOG_GROUP_COLUMNS\nALL_LOG_GROUPS\nALL_MEASURE_FOLDER_CONTENTS\nALL_MEASURE_FOLDERS\nALL_METHOD_PARAMS\nALL_METHOD_RESULTS\nALL_MINING_MODEL_ATTRIBUTES\nALL_MINING_MODEL_SETTINGS\nALL_MINING_MODELS\nALL_MVIEW_AGGREGATES\nALL_MVIEW_ANALYSIS\nALL_MVIEW_COMMENTS\nALL_MVIEW_DETAIL_PARTITION\nALL_MVIEW_DETAIL_RELATIONS\nALL_MVIEW_DETAIL_SUBPARTITION\nALL_MVIEW_JOINS\nALL_MVIEW_KEYS\nALL_MVIEW_LOGS\nALL_MVIEW_REFRESH_TIMES\nALL_MVIEWS\nALL_NESTED_TABLE_COLS\nALL_NESTED_TABLES\nALL_OBJ_COLATTRS\nALL_OBJECT_TABLES\nALL_OBJECTS\nALL_OBJECTS_AE\nALL_OPANCILLARY\nALL_OPARGUMENTS\nALL_OPBINDINGS\nALL_OPERATOR_COMMENTS\nALL_OPERATORS\nALL_OUTLINE_HINTS\nALL_OUTLINES\nALL_PART_COL_STATISTICS\nALL_PART_HISTOGRAMS\nALL_PART_INDEXES\nALL_PART_KEY_COLUMNS\nALL_PART_LOBS\nALL_PART_TABLES\nALL_PARTIAL_DROP_TABS\nALL_PENDING_CONV_TABLES\nALL_PLSQL_OBJECT_SETTINGS\nALL_POLICIES\nALL_POLICY_CONTEXTS\nALL_POLICY_GROUPS\nALL_PROCEDURES\nALL_PROPAGATION\nALL_PUBLISHED_COLUMNS\nALL_QUEUE_SCHEDULES\nALL_QUEUE_SUBSCRIBERS\nALL_QUEUE_TABLES\nALL_QUEUES\nALL_REFRESH\nALL_REFRESH_CHILDREN\nALL_REFRESH_DEPENDENCIES\nALL_REFS\nALL_REGISTERED_MVIEWS\nALL_REGISTRY_BANNERS\nALL_REWRITE_EQUIVALENCES\nALL_RULE_SET_RULES\nALL_RULE_SETS\nALL_RULES\nALL_SCHEDULER_CHAIN_RULES\nALL_SCHEDULER_CHAIN_STEPS\nALL_SCHEDULER_CHAINS\nALL_SCHEDULER_CREDENTIALS\nALL_SCHEDULER_DB_DESTS\nALL_SCHEDULER_DESTS\nALL_SCHEDULER_EXTERNAL_DESTS\nALL_SCHEDULER_FILE_WATCHERS\nALL_SCHEDULER_GLOBAL_ATTRIBUTE\nALL_SCHEDULER_GROUP_MEMBERS\nALL_SCHEDULER_GROUPS\nALL_SCHEDULER_JOB_ARGS\nALL_SCHEDULER_JOB_CLASSES\nALL_SCHEDULER_JOB_DESTS\nALL_SCHEDULER_JOB_LOG\nALL_SCHEDULER_JOB_RUN_DETAILS\nALL_SCHEDULER_JOBS\nALL_SCHEDULER_NOTIFICATIONS\nALL_SCHEDULER_PROGRAM_ARGS\nALL_SCHEDULER_PROGRAMS\nALL_SCHEDULER_REMOTE_DATABASES\nALL_SCHEDULER_REMOTE_JOBSTATE\nALL_SCHEDULER_RUNNING_CHAINS\nALL_SCHEDULER_RUNNING_JOBS\nALL_SCHEDULER_SCHEDULES\nALL_SCHEDULER_WINDOW_DETAILS\nALL_SCHEDULER_WINDOW_GROUPS\nALL_SCHEDULER_WINDOW_LOG\nALL_SCHEDULER_WINDOWS\nALL_SCHEDULER_WINGROUP_MEMBERS\nALL_SEC_RELEVANT_COLS\nALL_SECONDARY_OBJECTS\nALL_SEQUENCES\nALL_SERVICES\nALL_SOURCE\nALL_SOURCE_AE\nALL_SOURCE_TABLES\nALL_SQLJ_TYPE_ATTRS\nALL_SQLJ_TYPE_METHODS\nALL_SQLJ_TYPES\nALL_SQLSET\nALL_SQLSET_BINDS\nALL_SQLSET_PLANS\nALL_SQLSET_REFERENCES\nALL_SQLSET_STATEMENTS\nALL_STAT_EXTENSIONS\nALL_STORED_SETTINGS\nALL_STREAMS_COLUMNS\nALL_STREAMS_GLOBAL_RULES\nALL_STREAMS_MESSAGE_CONSUMERS\nALL_STREAMS_MESSAGE_RULES\nALL_STREAMS_NEWLY_SUPPORTED\nALL_STREAMS_RULES\nALL_STREAMS_SCHEMA_RULES\nALL_STREAMS_STMT_HANDLERS\nALL_STREAMS_STMTS\nALL_STREAMS_TABLE_RULES\nALL_STREAMS_TRANSFORM_FUNCTION\nALL_STREAMS_UNSUPPORTED\nALL_SUBPART_COL_STATISTICS\nALL_SUBPART_HISTOGRAMS\nALL_SUBPART_KEY_COLUMNS\nALL_SUBPARTITION_TEMPLATES\nALL_SUBSCRIBED_COLUMNS\nALL_SUBSCRIBED_TABLES\nALL_SUBSCRIPTIONS\nALL_SUMDELTA\nALL_SYNC_CAPTURE\nALL_SYNC_CAPTURE_PREPARED_TABS\nALL_SYNC_CAPTURE_TABLES\nALL_SYNONYMS\nALL_TAB_COL_STATISTICS\nALL_TAB_COLS\nALL_TAB_COLUMNS\nALL_TAB_COMMENTS\nALL_TAB_HISTGRM_PENDING_STATS\nALL_TAB_HISTOGRAMS\nALL_TAB_MODIFICATIONS\nALL_TAB_PARTITIONS\nALL_TAB_PENDING_STATS\nALL_TAB_PRIVS\nALL_TAB_PRIVS_MADE\nALL_TAB_PRIVS_RECD\nALL_TAB_STAT_PREFS\nALL_TAB_STATISTICS\nALL_TAB_STATS_HISTORY\nALL_TAB_SUBPARTITIONS\nALL_TABLES\nALL_TRIGGER_COLS\nALL_TRIGGER_ORDERING\nALL_TRIGGERS\nALL_TSTZ_TAB_COLS\nALL_TSTZ_TABLES\nALL_TYPE_ATTRS\nALL_TYPE_METHODS\nALL_TYPE_VERSIONS\nALL_TYPES\nALL_UNUSED_COL_TABS\nALL_UPDATABLE_COLUMNS\nALL_USERS\nALL_USTATS\nALL_VARRAYS\nALL_VIEWS\nALL_VIEWS_AE\nALL_WARNING_SETTINGS\nALL_XML_INDEXES\nALL_XML_SCHEMAS\nALL_XML_TAB_COLS\nALL_XML_TABLES\nALL_XML_VIEW_COLS\nALL_XML_VIEWS\nALL_XSTREAM_INBOUND\nALL_XSTREAM_INBOUND_PROGRESS\nALL_XSTREAM_OUTBOUND\nALL_XSTREAM_OUTBOUND_PROGRESS\nALL_XSTREAM_RULES\nAUDIT_ACTIONS\nCAT\nCATALOG\nCHAINED_ROWS\nCHANGE_PROPAGATION_SETS\nCHANGE_PROPAGATIONS\nCHANGE_SETS\nCHANGE_SOURCES\nCHANGE_TABLES\nCLIENT_RESULT_CACHE_STATS$\nCLU\nCOL\nCOLS\nDATABASE_PROPERTIES\nDBA_2PC_NEIGHBORS\nDBA_2PC_PENDING\nDBA_ADDM_FDG_BREAKDOWN\nDBA_ADDM_FINDINGS\nDBA_ADDM_INSTANCES\nDBA_ADDM_SYSTEM_DIRECTIVES\nDBA_ADDM_TASK_DIRECTIVES\nDBA_ADDM_TASKS\nDBA_ADVISOR_ACTIONS\nDBA_ADVISOR_COMMANDS\nDBA_ADVISOR_DEF_PARAMETERS\nDBA_ADVISOR_DEFINITIONS\nDBA_ADVISOR_DIR_DEFINITIONS\nDBA_ADVISOR_DIR_INSTANCES\nDBA_ADVISOR_DIR_TASK_INST\nDBA_ADVISOR_EXEC_PARAMETERS\nDBA_ADVISOR_EXECUTION_TYPES\nDBA_ADVISOR_EXECUTIONS\nDBA_ADVISOR_FDG_BREAKDOWN\nDBA_ADVISOR_FINDING_NAMES\nDBA_ADVISOR_FINDINGS\nDBA_ADVISOR_JOURNAL\nDBA_ADVISOR_LOG\nDBA_ADVISOR_OBJECT_TYPES\nDBA_ADVISOR_OBJECTS\nDBA_ADVISOR_PARAMETERS\nDBA_ADVISOR_RATIONALE\nDBA_ADVISOR_RECOMMENDATIONS\nDBA_ADVISOR_SQLA_REC_SUM\nDBA_ADVISOR_SQLA_TABLES\nDBA_ADVISOR_SQLA_WK_MAP\nDBA_ADVISOR_SQLA_WK_STMTS\nDBA_ADVISOR_SQLPLANS\nDBA_ADVISOR_SQLSTATS\nDBA_ADVISOR_SQLW_JOURNAL\nDBA_ADVISOR_SQLW_PARAMETERS\nDBA_ADVISOR_SQLW_STMTS\nDBA_ADVISOR_SQLW_SUM\nDBA_ADVISOR_SQLW_TABLES\nDBA_ADVISOR_SQLW_TEMPLATES\nDBA_ADVISOR_TASKS\nDBA_ADVISOR_TEMPLATES\nDBA_ADVISOR_USAGE\nDBA_ALERT_HISTORY\nDBA_ALL_TABLES\nDBA_APPLICATION_ROLES\nDBA_APPLY\nDBA_APPLY_CHANGE_HANDLERS\nDBA_APPLY_CONFLICT_COLUMNS\nDBA_APPLY_DML_HANDLERS\nDBA_APPLY_ENQUEUE\nDBA_APPLY_ERROR\nDBA_APPLY_ERROR_MESSAGES\nDBA_APPLY_EXECUTE\nDBA_APPLY_INSTANTIATED_GLOBAL\nDBA_APPLY_INSTANTIATED_OBJECTS\nDBA_APPLY_INSTANTIATED_SCHEMAS\nDBA_APPLY_KEY_COLUMNS\nDBA_APPLY_OBJECT_DEPENDENCIES\nDBA_APPLY_PARAMETERS\nDBA_APPLY_PROGRESS\nDBA_APPLY_SPILL_TXN\nDBA_APPLY_TABLE_COLUMNS\nDBA_APPLY_VALUE_DEPENDENCIES\nDBA_AQ_AGENT_PRIVS\nDBA_AQ_AGENTS\nDBA_ARGUMENTS\nDBA_ASSEMBLIES\nDBA_ASSOCIATIONS\nDBA_ATTRIBUTE_TRANSFORMATIONS\nDBA_AUDIT_EXISTS\nDBA_AUDIT_MGMT_CLEAN_EVENTS\nDBA_AUDIT_MGMT_CLEANUP_JOBS\nDBA_AUDIT_MGMT_CONFIG_PARAMS\nDBA_AUDIT_MGMT_LAST_ARCH_TS\nDBA_AUDIT_OBJECT\nDBA_AUDIT_POLICIES\nDBA_AUDIT_POLICY_COLUMNS\nDBA_AUDIT_SESSION\nDBA_AUDIT_STATEMENT\nDBA_AUDIT_TRAIL\nDBA_AUTO_SEGADV_CTL\nDBA_AUTO_SEGADV_SUMMARY\nDBA_AUTOTASK_CLIENT\nDBA_AUTOTASK_CLIENT_HISTORY\nDBA_AUTOTASK_CLIENT_JOB\nDBA_AUTOTASK_JOB_HISTORY\nDBA_AUTOTASK_OPERATION\nDBA_AUTOTASK_SCHEDULE\nDBA_AUTOTASK_TASK\nDBA_AUTOTASK_WINDOW_CLIENTS\nDBA_AUTOTASK_WINDOW_HISTORY\nDBA_AW_PS\nDBA_AWS\nDBA_BASE_TABLE_MVIEWS\nDBA_BLOCKERS\nDBA_CAPTURE\nDBA_CAPTURE_EXTRA_ATTRIBUTES\nDBA_CAPTURE_PARAMETERS\nDBA_CAPTURE_PREPARED_DATABASE\nDBA_CAPTURE_PREPARED_SCHEMAS\nDBA_CAPTURE_PREPARED_TABLES\nDBA_CATALOG\nDBA_CHANGE_NOTIFICATION_REGS\nDBA_CLU_COLUMNS\nDBA_CLUSTER_HASH_EXPRESSIONS\nDBA_CLUSTERS\nDBA_COL_COMMENTS\nDBA_COL_PENDING_STATS\nDBA_COL_PRIVS\nDBA_COLL_TYPES\nDBA_COMMON_AUDIT_TRAIL\nDBA_COMPARISON\nDBA_COMPARISON_COLUMNS\nDBA_COMPARISON_ROW_DIF\nDBA_COMPARISON_SCAN\nDBA_COMPARISON_SCAN_VALUES\nDBA_CONNECT_ROLE_GRANTEES\nDBA_CONS_OBJ_COLUMNS\nDBA_CONSTRAINTS\nDBA_CONTEXT\nDBA_CPOOL_INFO\nDBA_CPU_USAGE_STATISTICS\nDBA_CQ_NOTIFICATION_QUERIES\nDBA_CUBE_ATTR_VISIBILITY\nDBA_CUBE_ATTRIBUTES\nDBA_CUBE_BUILD_PROCESSES\nDBA_CUBE_CALCULATED_MEMBERS\nDBA_CUBE_DIM_LEVELS\nDBA_CUBE_DIM_MODELS\nDBA_CUBE_DIM_VIEW_COLUMNS\nDBA_CUBE_DIM_VIEWS\nDBA_CUBE_DIMENSIONALITY\nDBA_CUBE_DIMENSIONS\nDBA_CUBE_HIER_LEVELS\nDBA_CUBE_HIER_VIEW_COLUMNS\nDBA_CUBE_HIER_VIEWS\nDBA_CUBE_HIERARCHIES\nDBA_CUBE_MEASURES\nDBA_CUBE_VIEW_COLUMNS\nDBA_CUBE_VIEWS\nDBA_CUBES\nDBA_DATA_FILES\nDBA_DATAPUMP_JOBS\nDBA_DATAPUMP_SESSIONS\nDBA_DB_LINKS\nDBA_DDL_LOCKS\nDBA_DEPENDENCIES\nDBA_DIM_ATTRIBUTES\nDBA_DIM_CHILD_OF\nDBA_DIM_HIERARCHIES\nDBA_DIM_JOIN_KEY\nDBA_DIM_LEVEL_KEY\nDBA_DIM_LEVELS\nDBA_DIMENSIONS\nDBA_DIRECTORIES\nDBA_DML_LOCKS\nDBA_DMT_FREE_SPACE\nDBA_DMT_USED_EXTENTS\nDBA_EDITION_COMMENTS\nDBA_EDITIONING_VIEW_COLS\nDBA_EDITIONING_VIEW_COLS_AE\nDBA_EDITIONING_VIEWS\nDBA_EDITIONING_VIEWS_AE\nDBA_EDITIONS\nDBA_ENABLED_AGGREGATIONS\nDBA_ENABLED_TRACES\nDBA_ENCRYPTED_COLUMNS\nDBA_EPG_DAD_AUTHORIZATION\nDBA_ERRORS\nDBA_ERRORS_AE\nDBA_EVALUATION_CONTEXT_TABLES\nDBA_EVALUATION_CONTEXT_VARS\nDBA_EVALUATION_CONTEXTS\nDBA_EXP_FILES\nDBA_EXP_OBJECTS\nDBA_EXP_VERSION\nDBA_EXTENTS\nDBA_EXTERNAL_LOCATIONS\nDBA_EXTERNAL_TABLES\nDBA_FEATURE_USAGE_STATISTICS\nDBA_FGA_AUDIT_TRAIL\nDBA_FILE_GROUP_EXPORT_INFO\nDBA_FILE_GROUP_FILES\nDBA_FILE_GROUP_TABLES\nDBA_FILE_GROUP_TABLESPACES\nDBA_FILE_GROUP_VERSIONS\nDBA_FILE_GROUPS\nDBA_FLASHBACK_ARCHIVE\nDBA_FLASHBACK_ARCHIVE_TABLES\nDBA_FLASHBACK_ARCHIVE_TS\nDBA_FLASHBACK_TXN_REPORT\nDBA_FLASHBACK_TXN_STATE\nDBA_FREE_SPACE\nDBA_FREE_SPACE_COALESCED\nDBA_HIGH_WATER_MARK_STATISTICS\nDBA_HIST_ACTIVE_SESS_HISTORY\nDBA_HIST_BASELINE\nDBA_HIST_BASELINE_DETAILS\nDBA_HIST_BASELINE_METADATA\nDBA_HIST_BASELINE_TEMPLATE\nDBA_HIST_BG_EVENT_SUMMARY\nDBA_HIST_BUFFER_POOL_STAT\nDBA_HIST_BUFFERED_QUEUES\nDBA_HIST_BUFFERED_SUBSCRIBERS\nDBA_HIST_CLUSTER_INTERCON\nDBA_HIST_COLORED_SQL\nDBA_HIST_COMP_IOSTAT\nDBA_HIST_CR_BLOCK_SERVER\nDBA_HIST_CURRENT_BLOCK_SERVER\nDBA_HIST_DATABASE_INSTANCE\nDBA_HIST_DATAFILE\nDBA_HIST_DB_CACHE_ADVICE\nDBA_HIST_DISPATCHER\nDBA_HIST_DLM_MISC\nDBA_HIST_DYN_REMASTER_STATS\nDBA_HIST_ENQUEUE_STAT\nDBA_HIST_EVENT_HISTOGRAM\nDBA_HIST_EVENT_NAME\nDBA_HIST_FILEMETRIC_HISTORY\nDBA_HIST_FILESTATXS\nDBA_HIST_IC_CLIENT_STATS\nDBA_HIST_IC_DEVICE_STATS\nDBA_HIST_INST_CACHE_TRANSFER\nDBA_HIST_INSTANCE_RECOVERY\nDBA_HIST_INTERCONNECT_PINGS\nDBA_HIST_IOSTAT_DETAIL\nDBA_HIST_IOSTAT_FILETYPE\nDBA_HIST_IOSTAT_FILETYPE_NAME\nDBA_HIST_IOSTAT_FUNCTION\nDBA_HIST_IOSTAT_FUNCTION_NAME\nDBA_HIST_JAVA_POOL_ADVICE\nDBA_HIST_LATCH\nDBA_HIST_LATCH_CHILDREN\nDBA_HIST_LATCH_MISSES_SUMMARY\nDBA_HIST_LATCH_NAME\nDBA_HIST_LATCH_PARENT\nDBA_HIST_LIBRARYCACHE\nDBA_HIST_LOG\nDBA_HIST_MEM_DYNAMIC_COMP\nDBA_HIST_MEMORY_RESIZE_OPS\nDBA_HIST_MEMORY_TARGET_ADVICE\nDBA_HIST_METRIC_NAME\nDBA_HIST_MTTR_TARGET_ADVICE\nDBA_HIST_MUTEX_SLEEP\nDBA_HIST_OPTIMIZER_ENV\nDBA_HIST_OSSTAT\nDBA_HIST_OSSTAT_NAME\nDBA_HIST_PARAMETER\nDBA_HIST_PARAMETER_NAME\nDBA_HIST_PERSISTENT_QMN_CACHE\nDBA_HIST_PERSISTENT_QUEUES\nDBA_HIST_PERSISTENT_SUBS\nDBA_HIST_PGA_TARGET_ADVICE\nDBA_HIST_PGASTAT\nDBA_HIST_PLAN_OPERATION_NAME\nDBA_HIST_PLAN_OPTION_NAME\nDBA_HIST_PROCESS_MEM_SUMMARY\nDBA_HIST_RESOURCE_LIMIT\nDBA_HIST_ROWCACHE_SUMMARY\nDBA_HIST_RSRC_CONSUMER_GROUP\nDBA_HIST_RSRC_PLAN\nDBA_HIST_RULE_SET\nDBA_HIST_SEG_STAT\nDBA_HIST_SEG_STAT_OBJ\nDBA_HIST_SERVICE_NAME\nDBA_HIST_SERVICE_STAT\nDBA_HIST_SERVICE_WAIT_CLASS\nDBA_HIST_SESS_TIME_STATS\nDBA_HIST_SESSMETRIC_HISTORY\nDBA_HIST_SGA\nDBA_HIST_SGA_TARGET_ADVICE\nDBA_HIST_SGASTAT\nDBA_HIST_SHARED_POOL_ADVICE\nDBA_HIST_SHARED_SERVER_SUMMARY\nDBA_HIST_SNAP_ERROR\nDBA_HIST_SNAPSHOT\nDBA_HIST_SQL_BIND_METADATA\nDBA_HIST_SQL_PLAN\nDBA_HIST_SQL_SUMMARY\nDBA_HIST_SQL_WORKAREA_HSTGRM\nDBA_HIST_SQLBIND\nDBA_HIST_SQLCOMMAND_NAME\nDBA_HIST_SQLSTAT\nDBA_HIST_SQLTEXT\nDBA_HIST_STAT_NAME\nDBA_HIST_STREAMS_APPLY_SUM\nDBA_HIST_STREAMS_CAPTURE\nDBA_HIST_STREAMS_POOL_ADVICE\nDBA_HIST_SYS_TIME_MODEL\nDBA_HIST_SYSMETRIC_HISTORY\nDBA_HIST_SYSMETRIC_SUMMARY\nDBA_HIST_SYSSTAT\nDBA_HIST_SYSTEM_EVENT\nDBA_HIST_TABLESPACE_STAT\nDBA_HIST_TBSPC_SPACE_USAGE\nDBA_HIST_TEMPFILE\nDBA_HIST_TEMPSTATXS\nDBA_HIST_THREAD\nDBA_HIST_TOPLEVELCALL_NAME\nDBA_HIST_UNDOSTAT\nDBA_HIST_WAITCLASSMET_HISTORY\nDBA_HIST_WAITSTAT\nDBA_HIST_WR_CONTROL\nDBA_HISTOGRAMS\nDBA_IDENTIFIERS\nDBA_IND_COLUMNS\nDBA_IND_EXPRESSIONS\nDBA_IND_PARTITIONS\nDBA_IND_PENDING_STATS\nDBA_IND_STATISTICS\nDBA_IND_SUBPARTITIONS\nDBA_INDEXES\nDBA_INDEXTYPE_ARRAYTYPES\nDBA_INDEXTYPE_COMMENTS\nDBA_INDEXTYPE_OPERATORS\nDBA_INDEXTYPES\nDBA_INTERNAL_TRIGGERS\nDBA_JAVA_ARGUMENTS\nDBA_JAVA_CLASSES\nDBA_JAVA_COMPILER_OPTIONS\nDBA_JAVA_DERIVATIONS\nDBA_JAVA_FIELDS\nDBA_JAVA_IMPLEMENTS\nDBA_JAVA_INNERS\nDBA_JAVA_LAYOUTS\nDBA_JAVA_METHODS\nDBA_JAVA_NCOMPS\nDBA_JAVA_POLICY\nDBA_JAVA_RESOLVERS\nDBA_JAVA_THROWS\nDBA_JOBS\nDBA_JOBS_RUNNING\nDBA_JOIN_IND_COLUMNS\nDBA_KGLLOCK\nDBA_LIBRARIES\nDBA_LMT_FREE_SPACE\nDBA_LMT_USED_EXTENTS\nDBA_LOB_PARTITIONS\nDBA_LOB_SUBPARTITIONS\nDBA_LOB_TEMPLATES\nDBA_LOBS\nDBA_LOCK\nDBA_LOCK_INTERNAL\nDBA_LOCKS\nDBA_LOG_GROUP_COLUMNS\nDBA_LOG_GROUPS\nDBA_LOGMNR_LOG\nDBA_LOGMNR_PURGED_LOG\nDBA_LOGMNR_SESSION\nDBA_LOGSTDBY_EVENTS\nDBA_LOGSTDBY_HISTORY\nDBA_LOGSTDBY_LOG\nDBA_LOGSTDBY_NOT_UNIQUE\nDBA_LOGSTDBY_PARAMETERS\nDBA_LOGSTDBY_PROGRESS\nDBA_LOGSTDBY_SKIP\nDBA_LOGSTDBY_SKIP_TRANSACTION\nDBA_LOGSTDBY_UNSUPPORTED\nDBA_LOGSTDBY_UNSUPPORTED_TABLE\nDBA_MEASURE_FOLDER_CONTENTS\nDBA_MEASURE_FOLDERS\nDBA_METHOD_PARAMS\nDBA_METHOD_RESULTS\nDBA_MINING_MODEL_ATTRIBUTES\nDBA_MINING_MODEL_SETTINGS\nDBA_MINING_MODELS\nDBA_MVIEW_AGGREGATES\nDBA_MVIEW_ANALYSIS\nDBA_MVIEW_COMMENTS\nDBA_MVIEW_DETAIL_PARTITION\nDBA_MVIEW_DETAIL_RELATIONS\nDBA_MVIEW_DETAIL_SUBPARTITION\nDBA_MVIEW_JOINS\nDBA_MVIEW_KEYS\nDBA_MVIEW_LOG_FILTER_COLS\nDBA_MVIEW_LOGS\nDBA_MVIEW_REFRESH_TIMES\nDBA_MVIEWS\nDBA_NESTED_TABLE_COLS\nDBA_NESTED_TABLES\nDBA_NETWORK_ACL_PRIVILEGES\nDBA_NETWORK_ACLS\nDBA_OBJ_AUDIT_OPTS\nDBA_OBJ_COLATTRS\nDBA_OBJECT_SIZE\nDBA_OBJECT_TABLES\nDBA_OBJECTS\nDBA_OBJECTS_AE\nDBA_OPANCILLARY\nDBA_OPARGUMENTS\nDBA_OPBINDINGS\nDBA_OPERATOR_COMMENTS\nDBA_OPERATORS\nDBA_OPTSTAT_OPERATIONS\nDBA_ORPHAN_KEY_TABLE\nDBA_OUTLINE_HINTS\nDBA_OUTLINES\nDBA_OUTSTANDING_ALERTS\nDBA_PARALLEL_EXECUTE_CHUNKS\nDBA_PARALLEL_EXECUTE_TASKS\nDBA_PART_COL_STATISTICS\nDBA_PART_HISTOGRAMS\nDBA_PART_INDEXES\nDBA_PART_KEY_COLUMNS\nDBA_PART_LOBS\nDBA_PART_TABLES\nDBA_PARTIAL_DROP_TABS\nDBA_PENDING_CONV_TABLES\nDBA_PENDING_TRANSACTIONS\nDBA_PLSQL_OBJECT_SETTINGS\nDBA_POLICIES\nDBA_POLICY_CONTEXTS\nDBA_POLICY_GROUPS\nDBA_PRIV_AUDIT_OPTS\nDBA_PROCEDURES\nDBA_PROFILES\nDBA_PROPAGATION\nDBA_PROXIES\nDBA_PUBLISHED_COLUMNS\nDBA_QUEUE_SCHEDULES\nDBA_QUEUE_SUBSCRIBERS\nDBA_QUEUE_TABLES\nDBA_QUEUES\nDBA_RCHILD\nDBA_RECOVERABLE_SCRIPT\nDBA_RECOVERABLE_SCRIPT_BLOCKS\nDBA_RECOVERABLE_SCRIPT_ERRORS\nDBA_RECOVERABLE_SCRIPT_HIST\nDBA_RECOVERABLE_SCRIPT_PARAMS\nDBA_RECYCLEBIN\nDBA_REDEFINITION_ERRORS\nDBA_REDEFINITION_OBJECTS\nDBA_REFRESH\nDBA_REFRESH_CHILDREN\nDBA_REFS\nDBA_REGISTERED_ARCHIVED_LOG\nDBA_REGISTERED_MVIEW_GROUPS\nDBA_REGISTERED_MVIEWS\nDBA_REGISTRY\nDBA_REGISTRY_HIERARCHY\nDBA_REGISTRY_HISTORY\nDBA_REGISTRY_LOG\nDBA_REPAIR_TABLE\nDBA_RESOURCE_INCARNATIONS\nDBA_RESUMABLE\nDBA_REWRITE_EQUIVALENCES\nDBA_RGROUP\nDBA_ROLE_PRIVS\nDBA_ROLES\nDBA_ROLLBACK_SEGS\nDBA_RSRC_CATEGORIES\nDBA_RSRC_CONSUMER_GROUP_PRIVS\nDBA_RSRC_CONSUMER_GROUPS\nDBA_RSRC_GROUP_MAPPINGS\nDBA_RSRC_IO_CALIBRATE\nDBA_RSRC_MANAGER_SYSTEM_PRIVS\nDBA_RSRC_MAPPING_PRIORITY\nDBA_RSRC_PLAN_DIRECTIVES\nDBA_RSRC_PLANS\nDBA_RULE_SET_RULES\nDBA_RULE_SETS\nDBA_RULES\nDBA_SCHEDULER_CHAIN_RULES\nDBA_SCHEDULER_CHAIN_STEPS\nDBA_SCHEDULER_CHAINS\nDBA_SCHEDULER_CREDENTIALS\nDBA_SCHEDULER_DB_DESTS\nDBA_SCHEDULER_DESTS\nDBA_SCHEDULER_EXTERNAL_DESTS\nDBA_SCHEDULER_FILE_WATCHERS\nDBA_SCHEDULER_GLOBAL_ATTRIBUTE\nDBA_SCHEDULER_GROUP_MEMBERS\nDBA_SCHEDULER_GROUPS\nDBA_SCHEDULER_JOB_ARGS\nDBA_SCHEDULER_JOB_CLASSES\nDBA_SCHEDULER_JOB_DESTS\nDBA_SCHEDULER_JOB_LOG\nDBA_SCHEDULER_JOB_ROLES\nDBA_SCHEDULER_JOB_RUN_DETAILS\nDBA_SCHEDULER_JOBS\nDBA_SCHEDULER_NOTIFICATIONS\nDBA_SCHEDULER_PROGRAM_ARGS\nDBA_SCHEDULER_PROGRAMS\nDBA_SCHEDULER_REMOTE_DATABASES\nDBA_SCHEDULER_REMOTE_JOBSTATE\nDBA_SCHEDULER_RUNNING_CHAINS\nDBA_SCHEDULER_RUNNING_JOBS\nDBA_SCHEDULER_SCHEDULES\nDBA_SCHEDULER_WINDOW_DETAILS\nDBA_SCHEDULER_WINDOW_GROUPS\nDBA_SCHEDULER_WINDOW_LOG\nDBA_SCHEDULER_WINDOWS\nDBA_SCHEDULER_WINGROUP_MEMBERS\nDBA_SEC_RELEVANT_COLS\nDBA_SECONDARY_OBJECTS\nDBA_SEGMENTS\nDBA_SEGMENTS_OLD\nDBA_SEQUENCES\nDBA_SERVER_REGISTRY\nDBA_SERVICES\nDBA_SOURCE\nDBA_SOURCE_AE\nDBA_SOURCE_TABLES\nDBA_SQL_MANAGEMENT_CONFIG\nDBA_SQL_PATCHES\nDBA_SQL_PLAN_BASELINES\nDBA_SQL_PROFILES\nDBA_SQLJ_TYPE_ATTRS\nDBA_SQLJ_TYPE_METHODS\nDBA_SQLJ_TYPES\nDBA_SQLSET\nDBA_SQLSET_BINDS\nDBA_SQLSET_PLANS\nDBA_SQLSET_REFERENCES\nDBA_SQLSET_STATEMENTS\nDBA_SQLTUNE_BINDS\nDBA_SQLTUNE_PLANS\nDBA_SQLTUNE_RATIONALE_PLAN\nDBA_SQLTUNE_STATISTICS\nDBA_SSCR_CAPTURE\nDBA_SSCR_RESTORE\nDBA_STAT_EXTENSIONS\nDBA_STMT_AUDIT_OPTS\nDBA_STORED_SETTINGS\nDBA_STREAMS_ADD_COLUMN\nDBA_STREAMS_ADMINISTRATOR\nDBA_STREAMS_COLUMNS\nDBA_STREAMS_DELETE_COLUMN\nDBA_STREAMS_GLOBAL_RULES\nDBA_STREAMS_KEEP_COLUMNS\nDBA_STREAMS_MESSAGE_CONSUMERS\nDBA_STREAMS_MESSAGE_RULES\nDBA_STREAMS_NEWLY_SUPPORTED\nDBA_STREAMS_RENAME_COLUMN\nDBA_STREAMS_RENAME_SCHEMA\nDBA_STREAMS_RENAME_TABLE\nDBA_STREAMS_RULES\nDBA_STREAMS_SCHEMA_RULES\nDBA_STREAMS_SPLIT_MERGE\nDBA_STREAMS_SPLIT_MERGE_HIST\nDBA_STREAMS_STMT_HANDLERS\nDBA_STREAMS_STMTS\nDBA_STREAMS_TABLE_RULES\nDBA_STREAMS_TP_COMPONENT\nDBA_STREAMS_TP_COMPONENT_LINK\nDBA_STREAMS_TP_COMPONENT_STAT\nDBA_STREAMS_TP_DATABASE\nDBA_STREAMS_TP_PATH_BOTTLENECK\nDBA_STREAMS_TP_PATH_STAT\nDBA_STREAMS_TRANSFORM_FUNCTION\nDBA_STREAMS_TRANSFORMATIONS\nDBA_STREAMS_UNSUPPORTED\nDBA_SUBPART_COL_STATISTICS\nDBA_SUBPART_HISTOGRAMS\nDBA_SUBPART_KEY_COLUMNS\nDBA_SUBPARTITION_TEMPLATES\nDBA_SUBSCR_REGISTRATIONS\nDBA_SUBSCRIBED_COLUMNS\nDBA_SUBSCRIBED_TABLES\nDBA_SUBSCRIPTIONS\nDBA_SYNC_CAPTURE\nDBA_SYNC_CAPTURE_PREPARED_TABS\nDBA_SYNC_CAPTURE_TABLES\nDBA_SYNONYMS\nDBA_SYS_PRIVS\nDBA_TAB_COL_STATISTICS\nDBA_TAB_COLS\nDBA_TAB_COLUMNS\nDBA_TAB_COMMENTS\nDBA_TAB_HISTGRM_PENDING_STATS\nDBA_TAB_HISTOGRAMS\nDBA_TAB_MODIFICATIONS\nDBA_TAB_PARTITIONS\nDBA_TAB_PENDING_STATS\nDBA_TAB_PRIVS\nDBA_TAB_STATISTICS\nDBA_TAB_STAT_PREFS\nDBA_TAB_STATS_HISTORY\nDBA_TAB_SUBPARTITIONS\nDBA_TABLES\nDBA_TABLESPACE_GROUPS\nDBA_TABLESPACE_THRESHOLDS\nDBA_TABLESPACE_USAGE_METRICS\nDBA_TABLESPACES\nDBA_TEMP_FILES\nDBA_TEMP_FREE_SPACE\nDBA_THRESHOLDS\nDBA_TRANSFORMATIONS\nDBA_TRIGGER_COLS\nDBA_TRIGGER_ORDERING\nDBA_TRIGGERS\nDBA_TS_QUOTAS\nDBA_TSM_DESTINATION\nDBA_TSM_SOURCE\nDBA_TSTZ_TAB_COLS\nDBA_TSTZ_TABLES\nDBA_TUNE_MVIEW\nDBA_TYPE_ATTRS\nDBA_TYPE_METHODS\nDBA_TYPE_VERSIONS\nDBA_TYPES\nDBA_UNDO_EXTENTS\nDBA_UNUSED_COL_TABS\nDBA_UPDATABLE_COLUMNS\nDBA_USERS\nDBA_USERS_WITH_DEFPWD\nDBA_USTATS\nDBA_VARRAYS\nDBA_VIEWS\nDBA_VIEWS_AE\nDBA_WAITERS\nDBA_WALLET_ACLS\nDBA_WARNING_SETTINGS\nDBA_WORKLOAD_CAPTURES\nDBA_WORKLOAD_CONNECTION_MAP\nDBA_WORKLOAD_FILTERS\nDBA_WORKLOAD_REPLAY_DIVERGENCE\nDBA_WORKLOAD_REPLAYS\nDBA_XML_INDEXES\nDBA_XML_SCHEMAS\nDBA_XML_TAB_COLS\nDBA_XML_TABLES\nDBA_XML_VIEW_COLS\nDBA_XML_VIEWS\nDBA_XSTREAM_ADMINISTRATOR\nDBA_XSTREAM_INBOUND\nDBA_XSTREAM_INBOUND_PROGRESS\nDBA_XSTREAM_OUT_SUPPORT_MODE\nDBA_XSTREAM_OUTBOUND\nDBA_XSTREAM_OUTBOUND_PROGRESS\nDBA_XSTREAM_RULES\nDBFS_CONTENT\nDBFS_CONTENT_PROPERTIES\nDBMS_ALERT_INFO\nDBMS_LOCK_ALLOCATED\nDEPTREE\nDICT\nDICT_COLUMNS\nDICTIONARY\nDM_USER_MODELS\nDOCUMENT_LINKS\nERROR_SIZE\nEXCEPTIONS\nFLASHBACK_TRANSACTION_QUERY\nGLOBAL_NAME\nHS_ALL_CAPS\nHS_ALL_DD\nHS_ALL_INITS\nHS_BASE_CAPS\nHS_BASE_DD\nHS_CLASS_CAPS\nHS_CLASS_DD\nHS_CLASS_INIT\nHS_FDS_CLASS\nHS_FDS_INST\nHS_INST_CAPS\nHS_INST_DD\nHS_INST_INIT\nIDEPTREE\nIND\nINDEX_HISTOGRAM\nINDEX_STATS\nLOGSTDBY_UNSUPPORTED_TABLES\nMAP_OBJECT\nNLS_DATABASE_PARAMETERS\nNLS_INSTANCE_PARAMETERS\nNLS_SESSION_PARAMETERS\nOBJ\nPATH_VIEW\nPLAN_TABLE\nPLUGGABLE_SET_CHECK\nPRODUCT_COMPONENT_VERSION\nPROXY_USERS\nPSTUBTBL\nPUBLIC_DEPENDENCY\nPUBLICSYN\nQUEUE_PRIVILEGES\nRECYCLEBIN\nREPORT_COMPONENTS\nREPORT_FILES\nREPORT_FORMATS\nRESOURCE_COST\nRESOURCE_MAP\nRESOURCE_VIEW\nROLE_ROLE_PRIVS\nROLE_SYS_PRIVS\nROLE_TAB_PRIVS\nSCHEDULER_BATCH_ERRORS\nSEQ\nSESSION_CONTEXT\nSESSION_PRIVS\nSESSION_ROLES\nSOURCE_SIZE\nSTMT_AUDIT_OPTION_MAP\nSYN\nSYNONYMS\nSYS_OBJECTS\nSYSCATALOG\nSYSFILES\nSYSSEGOBJ\nSYSTEM_PRIVILEGE_MAP\nTAB\nTABLE_PRIVILEGE_MAP\nTABQUOTAS\nTABS\nTRUSTED_SERVERS\nTS_PITR_CHECK\nTS_PITR_OBJECTS_TO_BE_DROPPED\nUNI_PLUGGABLE_SET_CHECK\nUSER_ADDM_FDG_BREAKDOWN\nUSER_ADDM_FINDINGS\nUSER_ADDM_INSTANCES\nUSER_ADDM_TASKS\nUSER_ADVISOR_ACTIONS\nUSER_ADVISOR_DIR_TASK_INST\nUSER_ADVISOR_EXEC_PARAMETERS\nUSER_ADVISOR_EXECUTIONS\nUSER_ADVISOR_FDG_BREAKDOWN\nUSER_ADVISOR_FINDINGS\nUSER_ADVISOR_JOURNAL\nUSER_ADVISOR_LOG\nUSER_ADVISOR_OBJECTS\nUSER_ADVISOR_PARAMETERS\nUSER_ADVISOR_RATIONALE\nUSER_ADVISOR_RECOMMENDATIONS\nUSER_ADVISOR_SQLA_REC_SUM\nUSER_ADVISOR_SQLA_TABLES\nUSER_ADVISOR_SQLA_WK_MAP\nUSER_ADVISOR_SQLA_WK_STMTS\nUSER_ADVISOR_SQLPLANS\nUSER_ADVISOR_SQLSTATS\nUSER_ADVISOR_SQLW_JOURNAL\nUSER_ADVISOR_SQLW_PARAMETERS\nUSER_ADVISOR_SQLW_STMTS\nUSER_ADVISOR_SQLW_SUM\nUSER_ADVISOR_SQLW_TABLES\nUSER_ADVISOR_SQLW_TEMPLATES\nUSER_ADVISOR_TASKS\nUSER_ADVISOR_TEMPLATES\nUSER_ALL_TABLES\nUSER_AQ_AGENT_PRIVS\nUSER_ARGUMENTS\nUSER_ASSEMBLIES\nUSER_ASSOCIATIONS\nUSER_ATTRIBUTE_TRANSFORMATIONS\nUSER_AUDIT_OBJECT\nUSER_AUDIT_POLICIES\nUSER_AUDIT_POLICY_COLUMNS\nUSER_AUDIT_SESSION\nUSER_AUDIT_STATEMENT\nUSER_AUDIT_TRAIL\nUSER_AW_PS\nUSER_AWS\nUSER_BASE_TABLE_MVIEWS\nUSER_CATALOG\nUSER_CHANGE_NOTIFICATION_REGS\nUSER_CLU_COLUMNS\nUSER_CLUSTER_HASH_EXPRESSIONS\nUSER_CLUSTERS\nUSER_COL_COMMENTS\nUSER_COL_PENDING_STATS\nUSER_COL_PRIVS\nUSER_COL_PRIVS_MADE\nUSER_COL_PRIVS_RECD\nUSER_COLL_TYPES\nUSER_COMPARISON\nUSER_COMPARISON_COLUMNS\nUSER_COMPARISON_ROW_DIF\nUSER_COMPARISON_SCAN\nUSER_COMPARISON_SCAN_VALUES\nUSER_CONS_COLUMNS\nUSER_CONS_OBJ_COLUMNS\nUSER_CONSTRAINTS\nUSER_CQ_NOTIFICATION_QUERIES\nUSER_CUBE_ATTR_VISIBILITY\nUSER_CUBE_ATTRIBUTES\nUSER_CUBE_BUILD_PROCESSES\nUSER_CUBE_CALCULATED_MEMBERS\nUSER_CUBE_DIM_LEVELS\nUSER_CUBE_DIM_MODELS\nUSER_CUBE_DIM_VIEW_COLUMNS\nUSER_CUBE_DIM_VIEWS\nUSER_CUBE_DIMENSIONALITY\nUSER_CUBE_DIMENSIONS\nUSER_CUBE_HIER_LEVELS\nUSER_CUBE_HIER_VIEW_COLUMNS\nUSER_CUBE_HIER_VIEWS\nUSER_CUBE_HIERARCHIES\nUSER_CUBE_MEASURES\nUSER_CUBE_VIEW_COLUMNS\nUSER_CUBE_VIEWS\nUSER_CUBES\nUSER_DATAPUMP_JOBS\nUSER_DB_LINKS\nUSER_DBFS_HS_FILES\nUSER_DEPENDENCIES\nUSER_DIM_ATTRIBUTES\nUSER_DIM_CHILD_OF\nUSER_DIM_HIERARCHIES\nUSER_DIM_JOIN_KEY\nUSER_DIM_LEVEL_KEY\nUSER_DIM_LEVELS\nUSER_DIMENSIONS\nUSER_EDITIONING_VIEW_COLS\nUSER_EDITIONING_VIEW_COLS_AE\nUSER_EDITIONING_VIEWS\nUSER_EDITIONING_VIEWS_AE\nUSER_ENCRYPTED_COLUMNS\nUSER_EPG_DAD_AUTHORIZATION\nUSER_ERRORS\nUSER_ERRORS_AE\nUSER_EVALUATION_CONTEXT_TABLES\nUSER_EVALUATION_CONTEXT_VARS\nUSER_EVALUATION_CONTEXTS\nUSER_EXTENTS\nUSER_EXTERNAL_LOCATIONS\nUSER_EXTERNAL_TABLES\nUSER_FILE_GROUP_EXPORT_INFO\nUSER_FILE_GROUP_FILES\nUSER_FILE_GROUP_TABLES\nUSER_FILE_GROUP_TABLESPACES\nUSER_FILE_GROUP_VERSIONS\nUSER_FILE_GROUPS\nUSER_FLASHBACK_ARCHIVE\nUSER_FLASHBACK_ARCHIVE_TABLES\nUSER_FLASHBACK_TXN_REPORT\nUSER_FLASHBACK_TXN_STATE\nUSER_FREE_SPACE\nUSER_HISTOGRAMS\nUSER_IDENTIFIERS\nUSER_IND_COLUMNS\nUSER_IND_EXPRESSIONS\nUSER_IND_PARTITIONS\nUSER_IND_PENDING_STATS\nUSER_IND_STATISTICS\nUSER_IND_SUBPARTITIONS\nUSER_INDEXES\nUSER_INDEXTYPE_ARRAYTYPES\nUSER_INDEXTYPE_COMMENTS\nUSER_INDEXTYPE_OPERATORS\nUSER_INDEXTYPES\nUSER_INTERNAL_TRIGGERS\nUSER_JAVA_ARGUMENTS\nUSER_JAVA_CLASSES\nUSER_JAVA_COMPILER_OPTIONS\nUSER_JAVA_DERIVATIONS\nUSER_JAVA_FIELDS\nUSER_JAVA_IMPLEMENTS\nUSER_JAVA_INNERS\nUSER_JAVA_LAYOUTS\nUSER_JAVA_METHODS\nUSER_JAVA_NCOMPS\nUSER_JAVA_POLICY\nUSER_JAVA_RESOLVERS\nUSER_JAVA_THROWS\nUSER_JOBS\nUSER_JOIN_IND_COLUMNS\nUSER_LIBRARIES\nUSER_LOB_PARTITIONS\nUSER_LOB_SUBPARTITIONS\nUSER_LOB_TEMPLATES\nUSER_LOBS\nUSER_LOG_GROUP_COLUMNS\nUSER_LOG_GROUPS\nUSER_MEASURE_FOLDER_CONTENTS\nUSER_MEASURE_FOLDERS\nUSER_METHOD_PARAMS\nUSER_METHOD_RESULTS\nUSER_MINING_MODEL_ATTRIBUTES\nUSER_MINING_MODEL_SETTINGS\nUSER_MINING_MODELS\nUSER_MVIEW_AGGREGATES\nUSER_MVIEW_ANALYSIS\nUSER_MVIEW_COMMENTS\nUSER_MVIEW_DETAIL_PARTITION\nUSER_MVIEW_DETAIL_RELATIONS\nUSER_MVIEW_DETAIL_SUBPARTITION\nUSER_MVIEW_JOINS\nUSER_MVIEW_KEYS\nUSER_MVIEW_LOGS\nUSER_MVIEW_REFRESH_TIMES\nUSER_MVIEWS\nUSER_NESTED_TABLE_COLS\nUSER_NESTED_TABLES\nUSER_NETWORK_ACL_PRIVILEGES\nUSER_OBJ_AUDIT_OPTS\nUSER_OBJ_COLATTRS\nUSER_OBJECT_SIZE\nUSER_OBJECT_TABLES\nUSER_OBJECTS\nUSER_OBJECTS_AE\nUSER_OPANCILLARY\nUSER_OPARGUMENTS\nUSER_OPBINDINGS\nUSER_OPERATOR_COMMENTS\nUSER_OPERATORS\nUSER_OUTLINE_HINTS\nUSER_OUTLINES\nUSER_PARALLEL_EXECUTE_CHUNKS\nUSER_PARALLEL_EXECUTE_TASKS\nUSER_PART_COL_STATISTICS\nUSER_PART_HISTOGRAMS\nUSER_PART_INDEXES\nUSER_PART_KEY_COLUMNS\nUSER_PART_LOBS\nUSER_PART_TABLES\nUSER_PARTIAL_DROP_TABS\nUSER_PASSWORD_LIMITS\nUSER_PENDING_CONV_TABLES\nUSER_PLSQL_OBJECT_SETTINGS\nUSER_POLICIES\nUSER_POLICY_CONTEXTS\nUSER_POLICY_GROUPS\nUSER_PROCEDURES\nUSER_PROXIES\nUSER_PUBLISHED_COLUMNS\nUSER_QUEUE_SCHEDULES\nUSER_QUEUE_SUBSCRIBERS\nUSER_QUEUE_TABLES\nUSER_QUEUES\nUSER_RECYCLEBIN\nUSER_REFRESH\nUSER_REFRESH_CHILDREN\nUSER_REFS\nUSER_REGISTERED_MVIEWS\nUSER_REGISTRY\nUSER_RESOURCE_LIMITS\nUSER_RESUMABLE\nUSER_REWRITE_EQUIVALENCES\nUSER_ROLE_PRIVS\nUSER_RSRC_CONSUMER_GROUP_PRIVS\nUSER_RSRC_MANAGER_SYSTEM_PRIVS\nUSER_RULE_SET_RULES\nUSER_RULE_SETS\nUSER_RULES\nUSER_SCHEDULER_CHAIN_RULES\nUSER_SCHEDULER_CHAIN_STEPS\nUSER_SCHEDULER_CHAINS\nUSER_SCHEDULER_CREDENTIALS\nUSER_SCHEDULER_DB_DESTS\nUSER_SCHEDULER_DESTS\nUSER_SCHEDULER_FILE_WATCHERS\nUSER_SCHEDULER_GROUP_MEMBERS\nUSER_SCHEDULER_GROUPS\nUSER_SCHEDULER_JOB_ARGS\nUSER_SCHEDULER_JOB_DESTS\nUSER_SCHEDULER_JOB_LOG\nUSER_SCHEDULER_JOB_RUN_DETAILS\nUSER_SCHEDULER_JOBS\nUSER_SCHEDULER_NOTIFICATIONS\nUSER_SCHEDULER_PROGRAM_ARGS\nUSER_SCHEDULER_PROGRAMS\nUSER_SCHEDULER_REMOTE_JOBSTATE\nUSER_SCHEDULER_RUNNING_CHAINS\nUSER_SCHEDULER_RUNNING_JOBS\nUSER_SCHEDULER_SCHEDULES\nUSER_SEC_RELEVANT_COLS\nUSER_SECONDARY_OBJECTS\nUSER_SEGMENTS\nUSER_SEQUENCES\nUSER_SOURCE\nUSER_SOURCE_AE\nUSER_SOURCE_TABLES\nUSER_SQLJ_TYPE_ATTRS\nUSER_SQLJ_TYPE_METHODS\nUSER_SQLJ_TYPES\nUSER_SQLSET\nUSER_SQLSET_BINDS\nUSER_SQLSET_PLANS\nUSER_SQLSET_REFERENCES\nUSER_SQLSET_STATEMENTS\nUSER_SQLTUNE_BINDS\nUSER_SQLTUNE_PLANS\nUSER_SQLTUNE_RATIONALE_PLAN\nUSER_SQLTUNE_STATISTICS\nUSER_STAT_EXTENSIONS\nUSER_STORED_SETTINGS\nUSER_SUBPART_COL_STATISTICS\nUSER_SUBPART_HISTOGRAMS\nUSER_SUBPART_KEY_COLUMNS\nUSER_SUBPARTITION_TEMPLATES\nUSER_SUBSCR_REGISTRATIONS\nUSER_SUBSCRIBED_COLUMNS\nUSER_SUBSCRIBED_TABLES\nUSER_SUBSCRIPTIONS\nUSER_SYNONYMS\nUSER_SYS_PRIVS\nUSER_TAB_COL_STATISTICS\nUSER_TAB_COLS\nUSER_TAB_COLUMNS\nUSER_TAB_COMMENTS\nUSER_TAB_HISTGRM_PENDING_STATS\nUSER_TAB_HISTOGRAMS\nUSER_TAB_MODIFICATIONS\nUSER_TAB_PARTITIONS\nUSER_TAB_PENDING_STATS\nUSER_TAB_PRIVS\nUSER_TAB_PRIVS_MADE\nUSER_TAB_PRIVS_RECD\nUSER_TAB_STAT_PREFS\nUSER_TAB_STATISTICS\nUSER_TAB_STATS_HISTORY\nUSER_TAB_SUBPARTITIONS\nUSER_TABLES\nUSER_TABLESPACES\nUSER_TRANSFORMATIONS\nUSER_TRIGGER_COLS\nUSER_TRIGGER_ORDERING\nUSER_TRIGGERS\nUSER_TS_QUOTAS\nUSER_TSTZ_TAB_COLS\nUSER_TSTZ_TABLES\nUSER_TUNE_MVIEW\nUSER_TYPE_ATTRS\nUSER_TYPE_METHODS\nUSER_TYPE_VERSIONS\nUSER_TYPES\nUSER_UNUSED_COL_TABS\nUSER_UPDATABLE_COLUMNS\nUSER_USERS\nUSER_USTATS\nUSER_VARRAYS\nUSER_VIEWS\nUSER_VIEWS_AE\nUSER_WARNING_SETTINGS\nUSER_XML_INDEXES\nUSER_XML_SCHEMAS\nUSER_XML_TAB_COLS\nUSER_XML_TABLES\nUSER_XML_VIEW_COLS\nUSER_XML_VIEWS\nXS_SESSION_ROLES"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/oracle/deny-variant.txt",
    "content": "USER\nUID"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/oracle/permit-function.txt",
    "content": "abs\nacos\nasin\natan\natan2\nbitand\nceil\ncos\ncosh\nexp\nfloor\nln\nlog\nmod\nnanvl\npower\nremainder\nround\nsign\nsin\nsinh\nsqrt\ntan\ntanh\ntrunc\nwidth_bucket\n\nCHR\nCONCAT\nINITCAP\nLOWER\nLPAD\nLTRIM\nNLS_INITCAP\nNLS_LOWER\nNLSSORT\nNLS_UPPER\nREGEXP_REPLACE\nREGEXP_SUBSTR\nREPLACE\nRPAD\nRTRIM\nSOUNDEX\nSUBSTR\nTRANSLATE\nTREAT\nTRIM\nUPPER\n\nNLS_CHARSET_DECL_LEN\nNLS_CHARSET_ID\nNLS_CHARSET_NAME\n\nASCII\nINSTR\nLENGTH\nREGEXP_INSTR\n\nADD_MONTHS\nCURRENT_DATE\nCURRENT_TIMESTAMP\nDBTIMEZONE\nEXTRACT\nFROM_TZ\nLAST_DAY\nLOCALTIMESTAMP\nMONTHS_BETWEEN\nNEW_TIME\nNEXT_DAY\nNUMTODSINTERVAL\nNUMTOYMINTERVAL\nROUND\nSESSIONTIMEZONE\nSYS_EXTRACT_UTC\nSYSDATE\nSYSTIMESTAMP\nTO_CHAR\nTO_TIMESTAMP\nTO_TIMESTAMP_TZ\nTO_DSINTERVAL\nTO_YMINTERVAL\nTRUNC\nTZ_OFFSET\n\nGREATEST\nLEAST\n\nASCIISTR\nBIN_TO_NUM\nCAST\nCHARTOROWID\nCOMPOSE\nCONVERT\nDECOMPOSE\nHEXTORAW\nNUMTODSINTERVAL\nNUMTOYMINTERVAL\nRAWTOHEX\nRAWTONHEX\nROWIDTOCHAR\nROWIDTONCHAR\nSCN_TO_TIMESTAMP\nTIMESTAMP_TO_SCN\nTO_BINARY_DOUBLE\nTO_BINARY_FLOAT\nTO_CHAR\nTO_CLOB\nTO_DATE\nTO_DSINTERVAL\nTO_LOB\nTO_MULTI_BYTE\nTO_NCHAR\nTO_NCLOB\nTO_NUMBER\nTO_DSINTERVAL\nTO_SINGLE_BYTE\nTO_TIMESTAMP\nTO_TIMESTAMP_TZ\nTO_YMINTERVAL\nTO_YMINTERVAL\nTRANSLATE\nUNISTR\n\nBFILENAME\nEMPTY_BLOB\nEMPTY_CLOB\n\nCARDINALITY\nCOLLECT\nPOWERMULTISET\nPOWERMULTISET_BY_CARDINALITY\nSET\n\nSYS_CONNECT_BY_PATH\n\nCLUSTER_ID\nCLUSTER_PROBABILITY\nCLUSTER_SET\nFEATURE_ID\nFEATURE_SET\nFEATURE_VALUE\nPREDICTION\nPREDICTION_BOUNDS\nPREDICTION_COST\nPREDICTION_DETAILS\nPREDICTION_PROBABILITY\nPREDICTION_SET\n\nDECODE\nDUMP\nORA_HASH\nVSIZE\n\nCOALESCE\nLNNVL\nNULLIF\nNVL\nNVL2\n\nDBMS_LOB.SUBSTR\nDBMS_LOB.TRIM\nDBMS_LOB.INSTR\nDBMS_LOB.COMPARE"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/postgres/deny-function.txt",
    "content": "current_catalog\ncurrent_database\ncurrent_query\ncurrent_schema\ncurrent_schemas\ncurrent_user\ninet_client_addr\ninet_client_port\ninet_server_addr\ninet_server_port\npg_backend_pid\npg_conf_load_time\npg_is_other_temp_schema\npg_listening_channels\npg_my_temp_schema\npg_postmaster_start_time\npg_trigger_depth\nsession_user\nuser\nversion\npg_sleep\npg_sleep_for\npg_sleep_until\ncurrent_setting\nset_config\n\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/postgres/deny-table.txt",
    "content": "pg_database"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/sqlserver/deny-function.txt",
    "content": "db_name\ncol_name\nuser_name\nhost_name\nis_srvrolemember\nis_member\nopendatasource\nopenrowset\nopenquery\nhas_dbaccess\nsp_executesql\npg_sleep\nuser\nsystem_user"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/sqlserver/deny-object.txt",
    "content": ""
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/sqlserver/deny-schema.txt",
    "content": "master\nsys\nsysobjects\nsysdatabases\ninformation_schema"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/sqlserver/deny-table.txt",
    "content": "sysaltfiles\nsyslockinfo\nsyscacheobjects\nsyslogins\nsyscharsets\nsysmessages\nsysconfigures\nsysoledbusers\nsyscurconfigs\nsysperfinfo\nsysdatabases\nsysprocesses\nsysdevices\nsysremotelogins\nsyslanguages\nsysservers\nsyscolumns\nsysindexkeys\nsyscomments\nsysmembers\nsysconstraints\nsysobjects\nsysdepends\nsyspermissions\nsysfilegroups\nsysprotects\nsysfiles\nsysreferences\nsysforeignkeys\nsystypes\nsysfulltextcatalogs\nsysusers\nsysindexes\nsysalerts\nsysjobsteps\nsyscategories\nsysnotifications\nsysdownloadlist\nsysoperators\nsysjobhistory\nsystargetservergroupmembers\nsysjobs\nsystargetservergroups\nsysjobschedules\nsystargetservers\nsysjobservers\nsystaskids\nbackupfile\nrestorefile\nbackupmediafamily\nrestorefilegroup\nbackupmediaset\nrestorehistory\nbackupset\nsysdatabases\nsysservers\nsysreplicationalerts\nmsagent_parameters\nmspublisher_databases\nmsagent_profiles\nmsreplication_objects\nmsarticles\nmsreplication_subscriptions\nmsdistpublishers\nmsrepl_commands\nmsdistributiondbs\nmsrepl_errors\nmsdistribution_agents\nmsrepl_originators\nmsdistribution_history\nmsrepl_transactions\nmsdistributor\nmsrepl_version\nmslogreader_agents\nmssnapshot_agents\nmslogreader_history\nmssnapshot_history\nmsmerge_agents\nmssubscriber_info\nmsmerge_history\nmssubscriber_schedule\nmsmerge_subscriptions\nmssubscriptions\nmspublication_access\nmssubscription_properties\nmspublications\nmsmerge_contents\nsysmergearticles\nmsmerge_delete_conflicts\nsysmergepublications\nmsmerge_genhistory\nsysmergeschemachange\nmsmerge_replinfo\nsysmergesubscriptions\nmsmerge_tombstone\nsysmergesubsetfilters\nsysarticles\nsyspublications\nsysarticleupdates\nsyssubscriptions"
  },
  {
    "path": "core/src/main/resources/META-INF/druid/wall/sqlserver/deny-variant.txt",
    "content": "servername\nversion\nuser\nsystem_user"
  },
  {
    "path": "core/src/main/resources/META-INF/druid-driver.properties",
    "content": "jdbc:derby:=org.apache.derby.jdbc.EmbeddedDriver\njdbc:mysql:=com.mysql.jdbc.Driver\njdbc:log4jdbc:=net.sf.log4jdbc.DriverSpy\njdbc:oracle:=oracle.jdbc.driver.OracleDriver\njdbc:microsoft:=com.microsoft.jdbc.sqlserver.SQLServerDriver\njdbc:jtds:=net.sourceforge.jtds.jdbc.Driver\njdbc:postgresql:=org.postgresql.Driver\njdbc:fake:=com.alibaba.druid.mock.MockDriver\njdbc:hsqldb:=org.hsqldb.jdbcDriver\njdbc:db2:=COM.ibm.db2.jdbc.app.DB2Driver\njdbc:sqlite:=org.sqlite.JDBC\njdbc:ingres:=com.ingres.jdbc.IngresDriver\njdbc:h2:=org.h2.Driver\njdbc:mckoi:=com.mckoi.JDBCDriver\njdbc:clickhouse:=ru.yandex.clickhouse.ClickHouseDriver\njdbc:highgo:=com.highgo.jdbc.Driver\n"
  },
  {
    "path": "core/src/main/resources/META-INF/druid-filter.properties",
    "content": "druid.filters.default=com.alibaba.druid.filter.stat.StatFilter\ndruid.filters.stat=com.alibaba.druid.filter.stat.StatFilter\ndruid.filters.mergeStat=com.alibaba.druid.filter.stat.MergeStatFilter\ndruid.filters.counter=com.alibaba.druid.filter.stat.StatFilter\ndruid.filters.encoding=com.alibaba.druid.filter.encoding.EncodingConvertFilter\ndruid.filters.log4j=com.alibaba.druid.filter.logging.Log4jFilter\ndruid.filters.log4j2=com.alibaba.druid.filter.logging.Log4j2Filter\ndruid.filters.slf4j=com.alibaba.druid.filter.logging.Slf4jLogFilter\ndruid.filters.commonlogging=com.alibaba.druid.filter.logging.CommonsLogFilter\ndruid.filters.commonLogging=com.alibaba.druid.filter.logging.CommonsLogFilter\ndruid.filters.wall=com.alibaba.druid.wall.WallFilter\ndruid.filters.config=com.alibaba.druid.filter.config.ConfigFilter\ndruid.filters.haRandomValidator=com.alibaba.druid.pool.ha.selector.RandomDataSourceValidateFilter\ndruid.filters.mysql8DateTime=com.alibaba.druid.filter.mysql8datetime.MySQL8DateTimeSqlTypeFilter\n"
  },
  {
    "path": "core/src/main/resources/META-INF/services/java.sql.Driver",
    "content": "com.alibaba.druid.proxy.DruidDriver\ncom.alibaba.druid.mock.MockDriver"
  },
  {
    "path": "core/src/main/resources/META-INF/spring.handlers",
    "content": "http\\://www.alibaba.com/schema/stat=com.alibaba.druid.support.spring.stat.config.DruidStatNamespaceHandler"
  },
  {
    "path": "core/src/main/resources/META-INF/spring.schemas",
    "content": "http\\://www.alibaba.com/schema/stat.xsd=META-INF/stat.xsd"
  },
  {
    "path": "core/src/main/resources/META-INF/stat.xsd",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsd:schema xmlns=\"http://www.alibaba.com/schema/stat\"\n            xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n            xmlns:beans=\"http://www.springframework.org/schema/beans\"\n            targetNamespace=\"http://www.alibaba.com/schema/stat\"\n            elementFormDefault=\"qualified\"\n            attributeFormDefault=\"unqualified\">\n\n    <xsd:import namespace=\"http://www.springframework.org/schema/beans\"/>\n\n    <xsd:element name=\"annotation-driven\">\n        <xsd:annotation/>\n        <xsd:complexType>\n        </xsd:complexType>\n    </xsd:element>\n\n</xsd:schema>  "
  },
  {
    "path": "core/src/main/resources/support/http/resources/activeConnectionStackTrace.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid ActiveConnection StackTrace</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n\n</head>\n<body onload=\"init();\">\n\n<div class=\"container-fluid\">\n    <h2>ActiveConnection StackTrace for Datasource\n        <a href=\"activeConnectionStackTrace-{datasourceId}.json\" target=\"_blank\">[View JSON API]</a>\n    </h2>\n    <div id=\"activeConnectionStackTraceDiv\">\n\n    </div>\n</div>\n<script type=\"text/javascript\">\n    function init() {\n        druid.common.buildHead(7);\n    }\n\n    $.namespace(\"druid.activeConnectionStackTrace\");\n    druid.activeConnectionStackTrace = function () {\n        var datasourceId = druid.common.getUrlVar(\"datasourceId\");\n        return {\n            init: function () {\n                druid.activeConnectionStackTrace.ajaxRequestForActiveConnectionStackTrace();\n                var time2 = setInterval(\"druid.activeConnectionStackTrace.ajaxRequestForActiveConnectionStackTrace();\", 8000);\n            },\n\n            ajaxRequestForActiveConnectionStackTrace: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: 'activeConnectionStackTrace-' + datasourceId + '.json',\n                    success: function (data) {\n                        var conntionStackTraceList = data.Content;\n                        if (conntionStackTraceList == null)\n                            return;\n\n                        var content = [];\n\n                        for (var i = 0; i < conntionStackTraceList.length; i++) {\n                            if (i > 0) {\n                                content.push(\"<br>\");\n                            }\n                            var conntionStackTrace = conntionStackTraceList[i];\n                            content.push(\"<textarea rows='15' style='width:680px;' >\");\n                            content.push(conntionStackTrace);\n                            content.push(\"</textarea>\");\n                        }\n                        $(\"#activeConnectionStackTraceDiv\").html(content.join(\"\"));\n                    },\n                    dataType: \"json\"\n                });\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.activeConnectionStackTrace.init();\n    });\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/api.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Stat JSON API</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script>\n        function init() {\n            druid.common.buildHead(8);\n        }\n    </script>\n</head>\n<body onload=\"init();\">\n\n<div class=\"container\">\n    <h3>\n        JSON API\n    </h3>\n    <table class=\"table table-bordered responsive-utilities\" style=\"background-color: #fff\">\n        <thead>\n        <tr>\n            <th width=\"250px\" class=\"td_lable\">Name</th>\n            <th>Description</th>\n        </tr>\n        </thead>\n        <tr>\n            <td class=\"td_lable\"><a href=\"basic.json\" target=\"_blank\">basic.json</a></td>\n            <td>basic info.</td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\"><a href=\"datasource.json\" target=\"_blank\">datasource.json</a></td>\n            <td>DatsSourceStat List</td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\">datasource-{id}.json</td>\n            <td>DatasourceStat for id={id},id is DatsSourceStat.ID<br/>\n                Example: druid/datasource-1.json\n            </td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\">activeConnectionStackTrace-{datasourceId}.json</td>\n            <td>StrackTrace for activeConnection in datasource which datasource.id={datasourceId},id is\n                DatsSourceStat.ID<br/>\n                Required: set removeAbandoned=true<br/>\n                Example: druid/activeConnectionStackTrace-1.json\n            </td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\"><a href=\"sql.json\" target=\"_blank\">sql.json</a></td>\n            <td>SqlStat for id={id} ,id is SqlStat.ID<br/>\n                Example: druid/sql-1.json\n            </td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\"><a href=\"wall.json\" target=\"_blank\">WallStat.json</a></td>\n            <td>WallStat List</td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\">wall-{id}.json</td>\n            <td>WallStat for id={id},id is DatsSourceStat.ID<br/>\n                Example: druid/wall-1.json\n            </td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\"><a href=\"basic.json\" target=\"_blank\">basic.json</a></td>\n            <td></td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\"><a href=\"weburi.json\" target=\"_blank\">weburi.json</a></td>\n            <td>\n            </td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\"><a href=\"websession.json\" target=\"_blank\">websession.json</a></td>\n            <td>\n            </td>\n        </tr>\n        <tr>\n            <td class=\"td_lable\"><a href=\"reset-all.json\" target=\"_blank\">reset-all.json</a></td>\n            <td> Reset all stat</td>\n        </tr>\n    </table>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/connectionInfo.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Spring Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                Pooling Connection Info List for Datasource-<span id=\"datasourceId\"></span>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered table-striped\">\n                <thead>\n                <tr>\n                    <th width=\"50\">ID</th>\n                    <th width=\"50\" title=\"UseCount\">UseCnt</th>\n                    <th width=\"50\" title=\"KeepAliveCheckCount\">KACheckCnt</th>\n                    <th width=\"150\">LastActiveTime</th>\n                    <th width=\"150\">ConnectTime</th>\n                    <th width=\"50\">Holdability</th>\n                    <th width=\"50\" title=\"Transaction Isolation\">TranIsolation</th>\n                    <th width=\"50\">AutoCommit</th>\n                    <th width=\"50\">ReadOnly</th>\n                    <th>\n                        Pscache<br/>\n                        <table>\n                            <thead>\n                            <tr>\n                                <th>sql</th>\n                                <th width=\"50\" title=\"DefaultRowPrefetch\">dfRowPrefetch</th>\n                                <th width=\"50\">rowPrefetch</th>\n                                <th width=\"50\">hitCount</th>\n                            </tr>\n                            </thead>\n                        </table>\n                    </th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n        </div>\n    </div>\n</div>\n\n<script type=\"text/javascript\">\n    $.namespace(\"druid.connectionInfo\");\n    druid.connectionInfo = function () {\n        var datasourceId = druid.common.getUrlVar(\"datasourceId\");\n        return {\n            init: function () {\n                $(\"#datasourceId\").html(datasourceId);\n                druid.common.buildHead(1);\n                druid.connectionInfo.ajaxRequestForBasicInfo();\n                setInterval(\"druid.connectionInfo.ajaxRequestForBasicInfo();\", 10000);\n            },\n\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: 'connectionInfo-' + datasourceId + '.json',\n                    success: function (data) {\n                        druid.connectionInfo.handleAjaxResult(data);\n                        druid.lang.trigger();\n                    },\n                    dataType: \"json\"\n                });\n            },\n\n            handleAjaxResult: function (data) {\n                var statList = data.Content;\n                if (statList == null) return;\n\n                var sqlStatTable = document.getElementById(\"dataTable\");\n                while (sqlStatTable.rows.length > 1) {\n                    sqlStatTable.deleteRow(1);\n                }\n\n                var html = \"\";\n                for (var i = 0; i < statList.length; i++) {\n                    var stat = statList[i];\n                    var newRow = sqlStatTable.insertRow(-1);\n                    html += \"<tr>\";\n                    html += \"<td>\" + stat.connectionId + \"</td>\";\n                    html += \"<td>\" + stat.useCount + \"</td>\";\n                    html += \"<td>\" + stat.keepAliveCheckCount + \"</td>\";\n\n                    if (stat.lastActiveTime)\n                        html += \"<td>\" + stat.lastActiveTime + \"</td>\";\n                    else\n                        html += \"<td></td>\";\n\n                    html += \"<td>\" + stat.connectTime + \"</td>\";\n                    html += \"<td>\" + stat.holdability + \"</td>\";\n                    html += \"<td>\" + stat.transactionIsolation + \"</td>\";\n                    html += \"<td>\" + stat.autoCommit + \"</td>\";\n                    html += \"<td>\" + stat.readoOnly + \"</td>\";\n                    if (stat.pscache)\n                        html += \"<td>\" + druid.connectionInfo.getPsCacheInfo(stat.pscache) + \"</td>\";\n                    else\n                        html += \"<td></td>\";\n                    html += \"</tr>\";\n                }\n                $(\"#dataTable tbody\").html(html);\n                druid.common.stripes();\n            },\n\n            getPsCacheInfo: function (pscache) {\n                var result = '<table cellspacing=\"1\" cellpadding=\"5\" width=\"100%\">';\n                for (var i = 0; i < pscache.length; i++) {\n                    var stmt = pscache[i];\n                    result += '<tr>';\n                    result += '<td>' + stmt.sql + \"</td>\";\n                    result += '<td width=\"50\">' + stmt.defaultRowPrefetch + \"</td>\";\n                    result += '<td width=\"50\">' + stmt.rowPrefetch + \"</td>\";\n                    result += '<td width=\"50\">' + stmt.hitCount + \"</td>\";\n                    result += '</tr>';\n                }\n\n                result += \"</table>\";\n                return result;\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.connectionInfo.init();\n    });\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/css/style.css",
    "content": "\nbody {\n    font-size: 12px;\n    padding-top: 36px;\n    padding-bottom: 40px;\n}\n\n.nav {\n    margin-bottom: 5px;\n}\n\na {\n    cursor: pointer;\n}\n\n#dataTable th > a {\n    color: #555555;\n}\n\n#dataTable th {\n    background-color: #E5E5E5;\n    border-bottom-color: #FFC40D;\n    color: #555555;\n    cursor: pointer;\n}\n\n.footer {\n    background-color: #F5F5F5;\n    border-top: 1px solid #E5E5E5;\n    margin-top: 10px;\n    padding: 20px 0;\n}\n\n.td_lable {\n    font-weight: bold;\n    width: 340px;\n    min-width: 25px;\n    background-color: #E5E5E5;\n}\n\n\n.striped {\n    background-color: #fff;\n}\n\n#dataTable1 th > a {\n    color: #555555;\n}\n\n#dataTable1 th {\n    background-color: #E5E5E5;\n    border-bottom-color: #FFC40D;\n    color: #555555;\n    cursor: pointer;\n}\n\n\n#dataTable2 th > a {\n    color: #555555;\n}\n\n#dataTable2 th {\n    background-color: #E5E5E5;\n    border-bottom-color: #FFC40D;\n    color: #555555;\n    cursor: pointer;\n}\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/datasource.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid DataSourceStat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script src=\"js/doT.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"js/bootstrap.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                DataSourceStat List\n                <a href=\"datasource.json\" target=\"_blank\">View JSON API</a>\n            </h3>\n            <div class=\"alert alert-error clearfix\"\n                 style=\"margin-bottom: 5px;width: 195px; padding: 2px 15px 2px 10px;\">(*) property for user to setup\n            </div>\n        </div>\n    </div>\n</div>\n<script id=\"datasource-tmpl\" type=\"text/template\">\n    <ul class=\"nav nav-tabs\" id=\"datasourceTab\">\n        {{~ it.Content :datasourceNow:i }}\n        <li class=\"{{=i==0?'active':''}}\" id=\"datasourceTab-li-{{=i}}\">\n            <a href=\"datasource.html#dstab{{=datasourceNow.Identity}}\">{{=datasourceNow.Name}}</a>\n        </li>\n        {{~ }}\n    </ul>\n    <div class=\"tab-content\">\n        {{~ it.Content :datasourceNow:i }}\n        <div class=\"tab-pane {{=i==0?'active':''}}\" id=\"dstab{{=datasourceNow.Identity}}\">\n            <h4>\n                Basic Info For {{=datasourceNow.Name}}<a href=\"datasource-{{=datasourceNow.Identity}}.json\"\n                                                         target=\"_blank\">View JSON API</a>\n            </h4>\n            <table class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tbody>\n                    <tr>\n                        <td valign=\"top\" class=\"td_lable\" style=\"min-wdith:100px\" > *  <span class=\"lang\"  langKey=\"UserName\">UserName</span></td>\n                        <td style=\"min-wdith:300px\" width=\"60%\">{{=datasourceNow.UserName}}</td>\n                        <td  class=\"lang\"  langKey=\"UserNameDesc\" style=\"min-wdith:150px\">Specify the username used when creating a new connection.</td>\n                    </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"URL\">URL</span></td>\n                    <td>{{=datasourceNow.URL}}</td>\n                    <td class=\"lang\" langKey=\"URLDesc\">The JDBC driver connection URL</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"DbType\">DbType</span></td>\n                    <td>{{=datasourceNow.DbType}}</td>\n                    <td class=\"lang\" langKey=\"DbTypeDesc\">database type</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\"\n                                                               langKey=\"DriverClassName\">DriverClassName</span></td>\n                    <td>{{=datasourceNow.DriverClassName}}</td>\n                    <td class=\"lang\" langKey=\"DriverClassNameDesc\">The fully qualifed name of the JDBC driver class</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\"\n                                                               langKey=\"FilterClassNames\">FilterClassNames</span></td>\n                    <td>{{=datasourceNow.FilterClassNames}}</td>\n                    <td class=\"lang\" langKey=\"FilterClassNamesDesc\">All the fully qualifed name of the filter classes\n                    </td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"TestOnBorrow\">TestOnBorrow</span>\n                    </td>\n                    <td>{{=datasourceNow.TestOnBorrow}}</td>\n                    <td class=\"lang\" langKey=\"TestOnBorrowDesc\"> Test or not when borrow a connection</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"TestWhileIdle\">TestWhileIdle</span>\n                    </td>\n                    <td>{{=datasourceNow.TestWhileIdle}}</td>\n                    <td class=\"lang\" langKey=\"TestWhileIdleDesc\">Test or not when a connection is idle for a while</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"TestOnReturn\">TestOnReturn</span>\n                    </td>\n                    <td>{{=datasourceNow.TestOnReturn}}</td>\n                    <td class=\"lang\" langKey=\"TestOnReturnDesc\">Test or not when return a connection</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"InitialSize\">InitialSize</span>\n                    </td>\n                    <td>{{=datasourceNow.InitialSize}}</td>\n                    <td class=\"lang\" langKey=\"InitialSizeDesc\">The size of datasource connections to create when initial\n                        a datasource\n                    </td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"MinIdle\">MinIdle</span></td>\n                    <td>{{=datasourceNow.MinIdle}}</td>\n                    <td class=\"lang\" langKey=\"MinIdleDesc\">The minimum number of connections a pool should hold.</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"MaxActive\">MaxActive</span></td>\n                    <td>{{=datasourceNow.MaxActive}}</td>\n                    <td class=\"lang\" langKey=\"MaxActiveDesc\">The maximum number of connections for a pool</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"QueryTimeout\">QueryTimeout</span>\n                    </td>\n                    <td>{{=datasourceNow.QueryTimeout}}</td>\n                    <td class=\"lang\" langKey=\"QueryTimeoutDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"TransactionQueryTimeout\">TransactionQueryTimeout</span>\n                    </td>\n                    <td>{{=datasourceNow.TransactionQueryTimeout}}</td>\n                    <td class=\"lang\" langKey=\"TransactionQueryTimeoutDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"LoginTimeout\">LoginTimeout</span>\n                    </td>\n                    <td>{{=datasourceNow.LoginTimeout}}</td>\n                    <td class=\"lang\" langKey=\"LoginTimeoutDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"ValidConnectionCheckerClassName\">ValidConnectionCheckerClassName</span>\n                    </td>\n                    <td>{{=datasourceNow.ValidConnectionCheckerClassName}}</td>\n                    <td class=\"lang\" langKey=\"ValidConnectionCheckerClassNameDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"ExceptionSorterClassName\">ExceptionSorterClassName</span>\n                    </td>\n                    <td>{{=datasourceNow.ExceptionSorterClassName}}</td>\n                    <td class=\"lang\" langKey=\"ExceptionSorterClassNameDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"DefaultAutoCommit\">DefaultAutoCommit</span>\n                    </td>\n                    <td>{{=datasourceNow.DefaultAutoCommit}}</td>\n                    <td class=\"lang\" langKey=\"DefaultAutoCommitDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\"\n                                                               langKey=\"DefaultReadOnly\">DefaultReadOnly</span></td>\n                    <td>{{=datasourceNow.DefaultReadOnly}}</td>\n                    <td class=\"lang\" langKey=\"DefaultReadOnlyDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"DefaultTransactionIsolation\">DefaultTransactionIsolation</span>\n                    </td>\n                    <td>{{=datasourceNow.DefaultTransactionIsolation}}</td>\n                    <td class=\"lang\" langKey=\"DefaultTransactionIsolationDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"MinEvictableIdleTimeMillis\">MinEvictableIdleTimeMillis</span>\n                    </td>\n                    <td>{{=datasourceNow.MinEvictableIdleTimeMillis}}</td>\n                    <td class=\"lang\" langKey=\"MinEvictableIdleTimeMillis\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"MaxEvictableIdleTimeMillis\">MaxEvictableIdleTimeMillis</span>\n                    </td>\n                    <td>{{=datasourceNow.MaxEvictableIdleTimeMillis}}</td>\n                    <td class=\"lang\" langKey=\"MaxEvictableIdleTimeMillis\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"KeepAlive\">KeepAlive</span></td>\n                    <td>{{=datasourceNow.KeepAlive}}</td>\n                    <td class=\"lang\" langKey=\"KeepAlive\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"FailFast\">FailFast</span></td>\n                    <td>{{=datasourceNow.FailFast}}</td>\n                    <td class=\"lang\" langKey=\"FailFast\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"PoolPreparedStatements\">PoolPreparedStatements</span>\n                    </td>\n                    <td>{{=datasourceNow.PoolPreparedStatements}}</td>\n                    <td class=\"lang\" langKey=\"PoolPreparedStatements\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\"\n                                                               langKey=\"MaxPoolPreparedStatementPerConnectionSize\">MaxPoolPreparedStatementPerConnectionSize</span>\n                    </td>\n                    <td>{{=datasourceNow.MaxPoolPreparedStatementPerConnectionSize}}</td>\n                    <td class=\"lang\" langKey=\"MaxPoolPreparedStatementPerConnectionSize\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"MaxWait\">MaxWait</span></td>\n                    <td>{{=datasourceNow.MaxWait}}</td>\n                    <td class=\"lang\" langKey=\"MaxWait\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"MaxWaitThreadCount\">MaxWaitThreadCount</span>\n                    </td>\n                    <td>{{=datasourceNow.MaxWaitThreadCount}}</td>\n                    <td class=\"lang\" langKey=\"MaxWaitThreadCount\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"LogDifferentThread\">LogDifferentThread</span>\n                    </td>\n                    <td>{{=datasourceNow.LogDifferentThread}}</td>\n                    <td class=\"lang\" langKey=\"LogDifferentThread\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"UseUnfairLock\">UseUnfairLock</span>\n                    </td>\n                    <td>{{=datasourceNow.UseUnfairLock}}</td>\n                    <td class=\"lang\" langKey=\"UseUnfairLock\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"InitGlobalVariants\">InitGlobalVariants</span>\n                    </td>\n                    <td>{{=datasourceNow.InitGlobalVariants}}</td>\n                    <td class=\"lang\" langKey=\"InitGlobalVariants\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"> * <span class=\"lang\" langKey=\"InitVariants\">InitVariants</span>\n                    </td>\n                    <td>{{=datasourceNow.InitVariants}}</td>\n                    <td class=\"lang\" langKey=\"InitVariants\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"NotEmptyWaitCount\">NotEmptyWaitCount</span></td>\n                    <td>{{=datasourceNow.NotEmptyWaitCount}}</td>\n                    <td class=\"lang\" langKey=\"NotEmptyWaitCountDesc\">Total times for wait to get a connection</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"NotEmptyWaitMillis\">NotEmptyWaitMillis</span></td>\n                    <td>{{=datasourceNow.NotEmptyWaitMillis}}</td>\n                    <td class=\"lang\" langKey=\"NotEmptyWaitMillisDesc\">Total millins for wait to get a connection</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"WaitThreadCount\">WaitThreadCount</span></td>\n                    <td>{{=datasourceNow.WaitThreadCount}}</td>\n                    <td class=\"lang\" langKey=\"WaitThreadCountDesc\">The current waiting thread count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"StartTransactionCount\">StartTransactionCount</span>\n                    </td>\n                    <td>{{=datasourceNow.StartTransactionCount}}</td>\n                    <td class=\"lang\" langKey=\"StartTransactionCountDesc\">The count of start transaction</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"TransactionHistogram\">TransactionHistogram</span>\n                    </td>\n                    <td>{{=datasourceNow.TransactionHistogram}}</td>\n                    <td class=\"lang\" langKey=\"TransactionHistogramDesc\">The histogram values of transaction time, [0-1\n                        ms, 1-10 ms, 10-100 ms, 100-1 s, 1-10 s, 10-100 s, >100 s]\n                    </td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"PoolingCount\">PoolingCount</span></td>\n                    <td>{{=datasourceNow.PoolingCount}}</td>\n                    <td class=\"lang\" langKey=\"PoolingCountDesc\">The current usefull connection count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"PoolingPeak\">PoolingPeak</span></td>\n                    <td>{{=datasourceNow.PoolingPeak}}</td>\n                    <td class=\"lang\" langKey=\"PoolingPeakDesc\">The usefull connection peak count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"PoolingPeakTime\">PoolingPeakTime</span></td>\n                    <td>{{=datasourceNow.PoolingPeakTime}}</td>\n                    <td class=\"lang\" langKey=\"PoolingPeakTimeDesc\">The usefull connection peak time</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ActiveCount\">ActiveCount</span></td>\n                    <td>{{=datasourceNow.ActiveCount}}</td>\n                    <td class=\"lang\" langKey=\"ActiveCountDesc\">The current active connection count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ActivePeak\">ActivePeak</span></td>\n                    <td>{{=datasourceNow.ActivePeak}}</td>\n                    <td class=\"lang\" langKey=\"ActivePeakDesc\">The current active connection peak count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ActivePeakTime\">ActivePeakTime</span>\n                    </td>\n                    <td>{{=datasourceNow.ActivePeakTime}}</td>\n                    <td class=\"lang\" langKey=\"ActivePeakTimeDesc\">The active connection peak time</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"LogicConnectCount\">LogicConnectCount</span></td>\n                    <td>{{=datasourceNow.LogicConnectCount}}</td>\n                    <td class=\"lang\" langKey=\"LogicConnectCountDesc\">Total connect times from datasource</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"LogicCloseCount\">LogicCloseCount</span></td>\n                    <td>{{=datasourceNow.LogicCloseCount}}</td>\n                    <td class=\"lang\" langKey=\"LogicCloseCountDesc\">Total close connect times from datasource</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"LogicConnectErrorCount\">LogicConnectErrorCount</span>\n                    </td>\n                    <td>{{=datasourceNow.LogicConnectErrorCount}}</td>\n                    <td class=\"lang\" langKey=\"LogicConnectErrorCountDesc\">Total connect error times</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"DiscardCount\">DiscardCount</span></td>\n                    <td>{{=datasourceNow.DiscardCount}}</td>\n                    <td class=\"lang\" langKey=\"DiscardCountDesc\">Discard connection count with validate fail</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"RecycleErrorCount\">RecycleErrorCount</span></td>\n                    <td>{{=datasourceNow.RecycleErrorCount}}</td>\n                    <td class=\"lang\" langKey=\"RecycleErrorCount\">Total connect error times</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"PhysicalConnectCount\">PhysicalConnectCount</span>\n                    </td>\n                    <td>{{=datasourceNow.PhysicalConnectCount}}</td>\n                    <td class=\"lang\" langKey=\"PhysicalConnectCountDesc\">Create physical connnection count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"PhysicalCloseCount\">PhysicalCloseCount</span></td>\n                    <td>{{=datasourceNow.PhysicalCloseCount}}</td>\n                    <td class=\"lang\" langKey=\"PhysicalCloseCountDesc\">Close physical connnection count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"PhysicalConnectErrorCount\">PhysicalConnectErrorCount</span>\n                    </td>\n                    <td>{{=datasourceNow.PhysicalConnectErrorCount}}</td>\n                    <td class=\"lang\" langKey=\"PhysicalConnectErrorCountDesc\">Total physical connect error times</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ExecuteCount\">ExecuteCount</span></td>\n                    <td>{{=datasourceNow.ExecuteCount}}</td>\n                    <td class=\"lang\" langKey=\"ExecuteCountDesc\">Total Execute Count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"ExecuteQueryCount\">ExecuteQueryCount</span></td>\n                    <td>{{=datasourceNow.ExecuteQueryCount}}</td>\n                    <td class=\"lang\" langKey=\"ExecuteQueryCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"ExecuteUpdateCount\">ExecuteUpdateCount</span></td>\n                    <td>{{=datasourceNow.ExecuteUpdateCount}}</td>\n                    <td class=\"lang\" langKey=\"ExecuteUpdateCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"ExecuteBatchCount\">ExecuteBatchCount</span></td>\n                    <td>{{=datasourceNow.ExecuteBatchCount}}</td>\n                    <td class=\"lang\" langKey=\"ExecuteBatchCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ErrorCount\">ErrorCount</span></td>\n                    <td>{{=datasourceNow.ErrorCount}}</td>\n                    <td class=\"lang\" langKey=\"ErrorCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"CommitCount\">CommitCount</span></td>\n                    <td>{{=datasourceNow.CommitCount}}</td>\n                    <td class=\"lang\" langKey=\"CommitCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"RollbackCount\">RollbackCount</span>\n                    </td>\n                    <td>{{=datasourceNow.RollbackCount}}</td>\n                    <td class=\"lang\" langKey=\"RollbackCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"PreparedStatementOpenCount\">PSOpenCount</span>\n                    </td>\n                    <td>{{=datasourceNow.PreparedStatementOpenCount}}</td>\n                    <td class=\"lang\" langKey=\"PreparedStatementOpenCount\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"PreparedStatementClosedCount\">PSClosedCount</span>\n                    </td>\n                    <td>{{=datasourceNow.PreparedStatementClosedCount}}</td>\n                    <td class=\"lang\" langKey=\"PreparedStatementClosedCount\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"PSCacheAccessCount\">PSCacheAccessCount</span></td>\n                    <td>{{=datasourceNow.PSCacheAccessCount}}</td>\n                    <td class=\"lang\" langKey=\"PSCacheAccessCountDesc\">PerpareStatement access count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"PSCacheHitCount\">PSCacheHitCount</span></td>\n                    <td>{{=datasourceNow.PSCacheHitCount}}</td>\n                    <td class=\"lang\" langKey=\"PSCacheHitCountDesc\">PerpareStatement hit count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\"\n                                                            langKey=\"PSCacheMissCount\">PSCacheMissCount</span></td>\n                    <td>{{=datasourceNow.PSCacheMissCount}}</td>\n                    <td class=\"lang\" langKey=\"PSCacheMissCountDesc\">PerpareStatement miss count</td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ConnectionHoldTimeHistogram\">ConnectionHoldTimeHistogram</span>\n                    </td>\n                    <td>{{=datasourceNow.ConnectionHoldTimeHistogram}}</td>\n                    <td class=\"lang\" langKey=\"ConnectionHoldTimeHistogramDesc\">The histogram values of connection hold\n                        time, [0-1 ms, 1-10 ms, 10-100 ms, 100ms-1s, 1-10 s, 10-100 s, 100-1000 s, >1000 s]\n                    </td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ClobOpenCount\">ClobOpenCount</span>\n                    </td>\n                    <td>{{=datasourceNow.ClobOpenCount}}</td>\n                    <td class=\"lang\" langKey=\"ClobOpenCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"BlobOpenCount\">BlobOpenCount</span>\n                    </td>\n                    <td>{{=datasourceNow.BlobOpenCount}}</td>\n                    <td class=\"lang\" langKey=\"BlobOpenCountDesc\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"KeepAliveCheckCount\">KeepAliveCheckCount</span>\n                    </td>\n                    <td>{{=datasourceNow.KeepAliveCheckCount}}</td>\n                    <td class=\"lang\" langKey=\"KeepAliveCheckCount\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"ActiveConnectionStackTrace\">ActiveConnection StackTrace</span>\n                    </td>\n                    <td>\n                        <a href=\"activeConnectionStackTrace.html?datasourceId={{=datasourceNow.Identity}}\">View</a>\n                    </td>\n                    <td>\n                        StackTrace for active Connection.\n                        <a href=\"activeConnectionStackTrace-{{=datasourceNow.Identity}}.json\" target=\"_blank\">[View JSON\n                            API]</a>\n                    </td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"PollingConnectionInfo\">PollingConnection Info</span>\n                    </td>\n                    <td>\n                        <a href=\"connectionInfo.html?datasourceId={{=datasourceNow.Identity}}\">View</a>\n                    </td>\n                    <td>\n                        Info for polling connection.\n                        <a href=\"connectionInfo-{{=datasourceNow.Identity}}.json\" target=\"_blank\">[View JSON API]</a>\n                    </td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable\"><span class=\"lang\" langKey=\"SQLList\">SQL List</span></td>\n                    <td>\n                        <a href=\"sql.html?dataSourceId={{=datasourceNow.Identity}}\">View</a>\n                    </td>\n                    <td>\n                        Info for SQL.\n                        <a href=\"sql.json?dataSourceId={{=datasourceNow.Identity}}\" target=\"_blank\">[View JSON API]</a>\n                    </td>\n                </tr>\n                </tbody>\n            </table>\n        </div>\n        {{~ }}\n    </div>\n</script>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.datasource\");\n    druid.datasource = function () {\n\n        return {\n            init: function () {\n                druid.common.buildHead(1);\n                this.ajaxRequestForBasicInfo();\n            },\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: \"datasource.json\",\n                    success: function (data) {\n\n                        var tmpl = $('#datasource-tmpl').html();\n                        var doTtmpl = doT.template(tmpl);\n                        var contentHtml = doTtmpl(data);\n\n                        $(\".span12 h3\").after(contentHtml);\n                        $(\".tab-content tr:contains(undefined)\").hide();\n                        $('#datasourceTab a').click(function (e) {\n                            e.preventDefault();\n                            $(this).tab('show');\n                        });\n                        druid.lang.trigger();\n                    },\n                    dataType: \"json\"\n                });\n            }\n\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.datasource.init();\n    });\n    window.initPage = druid.datasource.ajaxRequestForBasicInfo;\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/header.html",
    "content": "<div class=\"navbar-fixed-top\" style=\"left:unset;right:0px;top:20px;margin-right:20px;z-index:1100;\">\n    <a class=\"langSelector\" langNow=\"0\">English</a> | <a class=\"langSelector\" langNow=\"1\">中文</a>\n</div>\n<div class=\"navbar navbar-fixed-top\">\n    <div class=\"navbar-inner\">\n        <div class=\"container\">\n            <a href=\"https://github.com/alibaba/druid/wiki\" target=\"_blank\" class=\"brand lang\" langKey=\"\">Druid\n                Monitor</a>\n            <div class=\"nav-collapse\">\n                <ul class=\"nav\">\n                    <li><a href=\"index.html\" class=\"lang\" langKey=\"Index\">Index</a></li>\n                    <li><a href=\"datasource.html\" class=\"lang\" langKey=\"DataSource\">DataSource</a></li>\n                    <li><a href=\"sql.html\" class=\"lang\" langKey=\"SQL\">SQL</a></li>\n                    <li><a href=\"wall.html\" class=\"lang\" langKey=\"Wall\">Wall</a></li>\n                    <li><a href=\"webapp.html\" class=\"lang\" langKey=\"WebApp\">WebApp</a></li>\n                    <li><a href=\"weburi.html\" class=\"lang\" langKey=\"WebURI\">WebURI</a></li>\n                    <li><a href=\"websession.html\" class=\"lang\" langKey=\"Web Session\">Web Session</a></li>\n                    <li><a href=\"spring.html\" class=\"lang\" langKey=\"Spring\">Spring</a></li>\n                    <li><a href=\"api.html\" class=\"lang\" langKey=\"JSON API\">JSON API</a></li>\n                </ul>\n                <a langKey=\"ResetAll\" class=\"btn btn-primary lang\"\n                   href=\"javascript:druid.common.ajaxRequestForReset();\">Reset All</a>\n                <a langKey=\"LogAndReset\" class=\"btn btn-primary lang\"\n                   href=\"javascript:druid.common.ajaxRequestForLogAndReset();\">Log And Reset</a>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title class=\"lang\" langKey=\"xxxx\">Druid Stat Index</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container\">\n    <h3>\n        Stat Index\n        <a href=\"basic.json\" target=\"_blank\" class=\"lang\" langKey=\"ViewJSONAPI\">View JSON API</a>\n    </h3>\n    <table id=\"dataTable\" style=\"background-color: #fff\" class=\"table table-bordered responsive-utilities\">\n        <tr>\n            <td valign=\"top\" class=\"td_lable lang\" langKey=\"StartTime\" style=\"min-width:80px\">StartTime</td>\n            <td id=\"StartTime\"></td>\n        </tr>\n        <tr>\n            <td valign=\"top\" width=\"100\" class=\"td_lable lang\" langKey=\"Version\">\n                Version\n            </td>\n            <td id=\"DruidVersion\" width=\"90%\"></td>\n        </tr>\n        <tr>\n            <td valign=\"top\" class=\"td_lable lang\" langKey=\"Drivers\"> Drivers</td>\n            <td id=\"DruidDrivers\"></td>\n        </tr>\n        <tr>\n            <td valign=\"top\" class=\"td_lable lang\" langKey=\"ResetEnable\"> ResetEnable</td>\n            <td id=\"ResetEnable\"></td>\n        </tr>\n        <tr>\n            <td valign=\"top\" class=\"td_lable lang\" langKey=\"ResetCount\"> ResetCount</td>\n            <td id=\"ResetCount\"></td>\n        </tr>\n        <tr>\n            <td valign=\"top\" class=\"td_lable lang\" langKey=\"JavaVersion\"> JavaVersion</td>\n            <td id=\"JavaVersion\"></td>\n        </tr>\n        <tr>\n            <td valign=\"top\" class=\"td_lable lang\" langKey=\"JavaVMName\"> JavaVMName</td>\n            <td id=\"JavaVMName\"></td>\n        </tr>\n        <tr>\n            <td valign=\"top\" class=\"td_lable lang\" langKey=\"JavaClassPath\"> JavaClassPath</td>\n            <td id=\"JavaClassPath\"></td>\n        </tr>\n    </table>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.index\");\n    druid.index = function () {\n        return {\n            init: function () {\n                druid.common.buildHead(0);\n                this.ajaxRequestForBasicInfo();\n            },\n\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: \"basic.json\",\n                    success: function (data) {\n                        $(\"#DruidVersion\").text(data.Content.Version)\n                        var driversList = data.Content.Drivers;\n                        if (driversList) {\n                            var driverHtml = '';\n                            for (var i = 0; i < driversList.length; i++) {\n                                var driver = driversList[i];\n                                driverHtml += driver + '<br/>';\n                            }\n                            $(\"#DruidDrivers\").html(driverHtml);\n                        }\n                        $(\"#ResetEnable\").text(data.Content.ResetEnable)\n                        $(\"#ResetCount\").text(data.Content.ResetCount)\n                        $(\"#JavaVersion\").text(data.Content.JavaVersion)\n                        $(\"#JavaVMName\").text(data.Content.JavaVMName)\n                        var splittor = /^[a-zA-Z]:\\\\/g.test(data.Content.JavaClassPath) ? \";\" : \":\";\n                        var arr = data.Content.JavaClassPath.split(splittor);\n                        $(\"#JavaClassPath\").html(\"<div>size:\" +  arr.length +\"</div>\" + arr.join(\"<br/>\"))\n                        $(\"#StartTime\").text(data.Content.StartTime)\n\n                        druid.lang.trigger();\n                    },\n                    dataType: \"json\"\n                });\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.index.init();\n    });\n    \n    window.initPage = druid.index.ajaxRequestForBasicInfo;\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/js/common.js",
    "content": "$.namespace(\"druid.common\");\n\ndruid.common = function () {\n    var statViewOrderBy = '';\n    var statViewOrderBy_old = '';\n    var statViewOrderType = 'asc';\n    var isOrderRequest = false;\n\n    // only one page for now\n    var sqlViewPage = 1;\n    var sqlViewPerPageCount = 1000000;\n\n    return {\n        init: function () {\n            this.buildFooter();\n            druid.lang.init();\n        },\n\n        buildHead: function (index) {\n            $.get('header.html', function (html) {\n                $(document.body).prepend(html);\n                druid.lang.trigger();\n                $(\".navbar .nav li\").eq(index).addClass(\"active\");\n            }, \"html\");\n\n        },\n\n        buildFooter: function () {\n\n            var html = '<footer class=\"footer\">' +\n                '    \t\t<div class=\"container\">' +\n                '<a href=\"https://render.alipay.com/p/s/taobaonpm_click/druid_banner_click\" target=\"new\"><img src=\"https://render.alipay.com/p/s/taobaonpm_click/druid_banner\"></a><br/>' +\n                '\tpowered by <a href=\"https://github.com/alibaba/\" target=\"_blank\">Alibaba</a> & sandzhang & <a href=\"http://melin.iteye.com/\" target=\"_blank\">melin</a> & <a href=\"https://github.com/shrekwang\" target=\"_blank\">shrek.wang</a>' +\n                '\t\t\t</div>' +\n                ' </footer>';\n            $(document.body).append(html);\n        },\n\n        ajaxRequestForReset: function () {\n            if (!confirm(\"Are you sure to reset all stat? It'll clear all stat data !\")) {\n                return;\n            }\n\n            $.ajax({\n                type: 'POST',\n                url: \"reset-all.json\",\n                success: function (data) {\n                    if (data.ResultCode == 1) {\n                        alert(\"already reset all stat\");\n                    }\n                    if (window.initPage) {\n                        window.initPage();\n                    }\n                },\n                dataType: \"json\"\n            });\n        },\n\n        ajaxRequestForLogAndReset: function () {\n            if (!confirm(\"Are you sure to reset data source stat? It'll clear and log all stat data !\")) {\n                return;\n            }\n\n            $.ajax({\n                type: 'POST',\n                url: \"log-and-reset.json\",\n                success: function (data) {\n                    if (data.ResultCode == 1) {\n                        alert(\"already reset all stat\");\n                    }\n                    if (window.initPage) {\n                        window.initPage();\n                    }\n                },\n                dataType: \"json\"\n            });\n        },\n\n        getAjaxUrl: function (uri) {\n            var result = uri;\n\n            if (statViewOrderBy != undefined)\n                result += 'orderBy=' + statViewOrderBy + '&';\n\n            if (statViewOrderType != undefined)\n                result += 'orderType=' + statViewOrderType + '&';\n\n            if (sqlViewPage != undefined)\n                result += 'page=' + sqlViewPage + '&';\n\n            if (sqlViewPerPageCount != undefined)\n                result += 'perPageCount=' + sqlViewPerPageCount + '&';\n\n            return result;\n        },\n\n        resetSortMark: function () {\n            var divObj = document.getElementById('th-' + statViewOrderBy);\n            var old_divObj = document.getElementById('th-' + statViewOrderBy_old);\n            var replaceToStr = '';\n            if (old_divObj) {\n                var html = old_divObj.innerHTML;\n                if (statViewOrderBy_old.indexOf('[') > 0)\n                    replaceToStr = '-';\n                html = html.replace('▲', replaceToStr);\n                html = html.replace('▼', replaceToStr);\n                old_divObj.innerHTML = html\n            }\n            if (divObj) {\n                var html = divObj.innerHTML;\n                if (statViewOrderBy.indexOf('[') > 0)\n                    html = '';\n\n                if (statViewOrderType == 'asc') {\n                    html += '▲';\n                } else if (statViewOrderType == 'desc') {\n                    html += '▼';\n                }\n                divObj.innerHTML = html;\n            }\n            isOrderRequest = true;\n\n            this.ajaxRequestForBasicInfo();\n            return false;\n        },\n\n        setOrderBy: function (orderBy) {\n            if (statViewOrderBy != orderBy) {\n                statViewOrderBy_old = statViewOrderBy;\n                statViewOrderBy = orderBy;\n                statViewOrderType = 'desc';\n                druid.common.resetSortMark();\n                return;\n            }\n\n            statViewOrderBy_old = statViewOrderBy;\n\n            if (statViewOrderType == 'asc')\n                statViewOrderType = 'desc'\n            else\n                statViewOrderType = 'asc';\n\n            druid.common.resetSortMark();\n        },\n\n        ajaxuri: \"\",\n        handleCallback: null,\n        handleAjaxResult: function (data) {\n            druid.common.handleCallback(data);\n            if (!isOrderRequest) {\n                druid.lang.trigger();\n            }\n        },//ajax 处理函数\n        ajaxRequestForBasicInfo: function () {\n            $.ajax({\n                type: 'POST',\n                url: druid.common.getAjaxUrl(druid.common.ajaxuri),\n                success: function (data) {\n                    druid.common.handleAjaxResult(data);\n                },\n                dataType: \"json\"\n            });\n        },\n\n        subSqlString: function (sql, len) {\n            if (sql == undefined || sql == null) {\n                return '';\n            }\n\n            if (sql.length <= len)\n                return sql;\n            return sql.substr(0, len) + '...';\n        },\n\n        stripes: function () {\n            $(\"#dataTable tbody tr\").each(function () {\n                $(this).removeClass(\"striped\");\n            });\n            $(\"#dataTable tbody tr:even\").each(function () {\n                $(this).addClass(\"striped\");\n            });\n        },\n\n        getUrlVar: function (name) {\n            var vars = {};\n            var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {\n                vars[key] = value;\n            });\n            return vars[name];\n        }\n    }\n}();\n\n$(document).ready(function () {\n    druid.common.init();\n});\n\nfunction replace(data) {\n    if ((!data) || data === undefined) {\n        return '';\n    } else {\n        return format(data);\n    }\n}\n\nfunction format(s) {\n    var str = s += '';\n    return str.replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, \"$1,\");\n}\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/js/doT.js",
    "content": "// doT.js\n// 2011, Laura Doktorova, https://github.com/olado/doT\n// Licensed under the MIT license.\n\n(function () {\n    \"use strict\";\n\n    var doT = {\n        version: '1.0.17',\n        templateSettings: {\n            evaluate: /\\{\\{([\\s\\S]+?\\}?)\\}\\}/g,\n            interpolate: /\\{\\{=([\\s\\S]+?)\\}\\}/g,\n            encode: /\\{\\{!([\\s\\S]+?)\\}\\}/g,\n            use: /\\{\\{#([\\s\\S]+?)\\}\\}/g,\n            useParams: /(^|[^\\w$])def(?:\\.|\\[[\\'\\\"])([\\w$\\.]+)(?:[\\'\\\"]\\])?\\s*\\:\\s*([\\w$\\.]+|\\\"[^\\\"]+\\\"|\\'[^\\']+\\'|\\{[^\\}]+\\})/g,\n            define: /\\{\\{##\\s*([\\w\\.$]+)\\s*(\\:|=)([\\s\\S]+?)#\\}\\}/g,\n            defineParams: /^\\s*([\\w$]+):([\\s\\S]+)/,\n            conditional: /\\{\\{\\?(\\?)?\\s*([\\s\\S]*?)\\s*\\}\\}/g,\n            iterate: /\\{\\{~\\s*(?:\\}\\}|([\\s\\S]+?)\\s*\\:\\s*([\\w$]+)\\s*(?:\\:\\s*([\\w$]+))?\\s*\\}\\})/g,\n            varname: 'it',\n            strip: true,\n            append: true,\n            selfcontained: false\n        },\n        template: undefined, //fn, compile template\n        compile: undefined  //fn, for express\n    };\n\n    if (typeof module !== 'undefined' && module.exports) {\n        module.exports = doT;\n    } else if (typeof define === 'function' && define.amd) {\n        define(function () {\n            return doT;\n        });\n    } else {\n        (function () {\n            return this || (0, eval)('this');\n        }()).doT = doT;\n    }\n\n    function encodeHTMLSource() {\n        var encodeHTMLRules = {\"&\": \"&#38;\", \"<\": \"&#60;\", \">\": \"&#62;\", '\"': '&#34;', \"'\": '&#39;', \"/\": '&#47;'},\n            matchHTML = /&(?!#?\\w+;)|<|>|\"|'|\\//g;\n        return function () {\n            return this ? this.replace(matchHTML, function (m) {\n                return encodeHTMLRules[m] || m;\n            }) : this;\n        };\n    }\n\n    String.prototype.encodeHTML = encodeHTMLSource();\n\n    var startend = {\n        append: {start: \"'+(\", end: \")+'\", endencode: \"||'').toString().encodeHTML()+'\"},\n        split: {start: \"';out+=(\", end: \");out+='\", endencode: \"||'').toString().encodeHTML();out+='\"}\n    }, skip = /$^/;\n\n    function resolveDefs(c, block, def) {\n        return ((typeof block === 'string') ? block : block.toString())\n            .replace(c.define || skip, function (m, code, assign, value) {\n                if (code.indexOf('def.') === 0) {\n                    code = code.substring(4);\n                }\n                if (!(code in def)) {\n                    if (assign === ':') {\n                        if (c.defineParams) value.replace(c.defineParams, function (m, param, v) {\n                            def[code] = {arg: param, text: v};\n                        });\n                        if (!(code in def)) def[code] = value;\n                    } else {\n                        new Function(\"def\", \"def['\" + code + \"']=\" + value)(def);\n                    }\n                }\n                return '';\n            })\n            .replace(c.use || skip, function (m, code) {\n                if (c.useParams) code = code.replace(c.useParams, function (m, s, d, param) {\n                    if (def[d] && def[d].arg && param) {\n                        var rw = (d + \":\" + param).replace(/'|\\\\/g, '_');\n                        def.__exp = def.__exp || {};\n                        def.__exp[rw] = def[d].text.replace(new RegExp(\"(^|[^\\\\w$])\" + def[d].arg + \"([^\\\\w$])\", \"g\"), \"$1\" + param + \"$2\");\n                        return s + \"def.__exp['\" + rw + \"']\";\n                    }\n                });\n                var v = new Function(\"def\", \"return \" + code)(def);\n                return v ? resolveDefs(c, v, def) : v;\n            });\n    }\n\n    function unescape(code) {\n        return code.replace(/\\\\('|\\\\)/g, \"$1\").replace(/[\\r\\t\\n]/g, ' ');\n    }\n\n    doT.template = function (tmpl, c, def) {\n        c = c || doT.templateSettings;\n        var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0, indv,\n            str = (c.use || c.define) ? resolveDefs(c, tmpl, def || {}) : tmpl;\n\n        str = (\"var out='\" + (c.strip ? str.replace(/(^|\\r|\\n)\\t* +| +\\t*(\\r|\\n|$)/g, ' ')\n                .replace(/\\r|\\n|\\t|\\/\\*[\\s\\S]*?\\*\\//g, '') : str)\n                .replace(/'|\\\\/g, '\\\\$&')\n                .replace(c.interpolate || skip, function (m, code) {\n                    return cse.start + unescape(code) + cse.end;\n                })\n                .replace(c.encode || skip, function (m, code) {\n                    needhtmlencode = true;\n                    return cse.start + unescape(code) + cse.endencode;\n                })\n                .replace(c.conditional || skip, function (m, elsecase, code) {\n                    return elsecase ?\n                        (code ? \"';}else if(\" + unescape(code) + \"){out+='\" : \"';}else{out+='\") :\n                        (code ? \"';if(\" + unescape(code) + \"){out+='\" : \"';}out+='\");\n                })\n                .replace(c.iterate || skip, function (m, iterate, vname, iname) {\n                    if (!iterate) return \"';} } out+='\";\n                    sid += 1;\n                    indv = iname || \"i\" + sid;\n                    iterate = unescape(iterate);\n                    return \"';var arr\" + sid + \"=\" + iterate + \";if(arr\" + sid + \"){var \" + vname + \",\" + indv + \"=-1,l\" + sid + \"=arr\" + sid + \".length-1;while(\" + indv + \"<l\" + sid + \"){\"\n                        + vname + \"=arr\" + sid + \"[\" + indv + \"+=1];out+='\";\n                })\n                .replace(c.evaluate || skip, function (m, code) {\n                    return \"';\" + unescape(code) + \"out+='\";\n                })\n            + \"';return out;\")\n            .replace(/\\n/g, '\\\\n').replace(/\\t/g, '\\\\t').replace(/\\r/g, '\\\\r')\n            .replace(/(\\s|;|\\}|^|\\{)out\\+='';/g, '$1').replace(/\\+''/g, '')\n            .replace(/(\\s|;|\\}|^|\\{)out\\+=''\\+/g, '$1out+=');\n\n        if (needhtmlencode && c.selfcontained) {\n            str = \"String.prototype.encodeHTML=(\" + encodeHTMLSource.toString() + \"());\" + str;\n        }\n        try {\n            return new Function(c.varname, str);\n        } catch (e) {\n            if (typeof console !== 'undefined') console.log(\"Could not create a template function: \" + str);\n            throw e;\n        }\n    };\n\n    doT.compile = function (tmpl, def) {\n        return doT.template(tmpl, null, def);\n    };\n}());\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/js/lang.js",
    "content": "$.namespace(\"druid.lang\");\ndruid.lang = function () {\n    var LANG_EN = 0;\n    var LANG_CN = 1;\n    var lang = {\n        'Index': ['Index', '首页'],\n        'DataSource': ['DataSource', '数据源'],\n        'SQL': ['SQL', 'SQL监控'],\n        'Wall': ['Wall', 'SQL防火墙'],\n        'WebApp': ['WebApp', 'Web应用'],\n        'WebURI': ['WebURI', 'URI监控'],\n        'Web Session': ['Web Session', 'Session监控'],\n        'Spring': ['Spring', 'Spring监控'],\n        'JSON API': ['JSON API', 'JSON API'],\n        'ResetAll': ['Reset All', '重置'],\n        'LogAndReset': ['Log And Reset', '记录日志并重置'],\n\n        'StatIndex': ['Stat Index', '统计索引'],\n        'ViewJSONAPI': ['View JSON API', '查看JSON API'],\n        'Version': ['Version', '版本'],\n        'Drivers': ['Drivers', '驱动'],\n        'ResetEnable': ['ResetEnable', '是否允许重置'],\n        'ResetCount': ['ResetCount', '重置次数'],\n        'JavaVersion': ['JavaVersion', 'Java版本'],\n        'JavaVMName': ['JavaVMName', 'JVM名称'],\n        'JavaClassPath': ['JavaClassPath', 'classpath路径'],\n        'StartTime': ['StartTime', '启动时间'],\n\n        'DataSourceStatList': ['DataSourceStat List', '数据源列表'],\n        'UserName': ['UserName', '用户名'],\n        'URL': ['URL', '连接地址'],\n        'DbType': ['DbType', '数据库类型'],\n        'DriverClassName': ['DriverClassName', '驱动类名'],\n        'FilterClassNames': ['FilterClassNames', 'filter类名'],\n        'TestOnBorrow': ['TestOnBorrow', '获取连接时检测'],\n        'TestWhileIdle': ['TestWhileIdle', '空闲时检测'],\n        'TestOnReturn': ['TestOnReturn', '连接放回连接池时检测'],\n        'InitialSize': ['InitialSize', '初始化连接大小'],\n        'MinIdle': ['MinIdle', '最小空闲连接数'],\n        'MaxActive': ['MaxActive', '最大连接数'],\n        'QueryTimeout': ['QueryTimeout', '查询超时时间'],\n        'TransactionQueryTimeout': ['TransactionQueryTimeout', '事务查询超时时间'],//\n        'LoginTimeout': ['LoginTimeout', '登录超时时间'],//\n        'ValidConnectionCheckerClassName': ['ValidConnectionCheckerClassName', '连接有效性检查类名'],\n        'ExceptionSorterClassName': ['ExceptionSorterClassName', 'ExceptionSorter类名'],//\n        'DefaultAutoCommit': ['DefaultAutoCommit', '默认autocommit设置'],\n        'DefaultReadOnly': ['DefaultReadOnly', '默认只读设置'],\n        'DefaultTransactionIsolation': ['DefaultTransactionIsolation', '默认事务隔离'],//\n        'NotEmptyWaitCount': ['NotEmptyWaitCount', '累计总次数'],//\n        'NotEmptyWaitMillis': ['NotEmptyWaitMillis', '等待总时长'],//\n        'WaitThreadCount': ['WaitThreadCount', '等待线程数量'],\n        'StartTransactionCount': ['StartTransactionCount', '事务启动数'],//\n        'TransactionHistogram': ['TransactionHistogram', '事务时间分布'],//\n        'PoolingCount': ['PoolingCount', '池中连接数'],//\n        'PoolingPeak': ['PoolingPeak', '池中连接数峰值'],//\n        'PoolingPeakTime': ['PoolingPeakTime', '池中连接数峰值时间'],////\n        'ActiveCount': ['ActiveCount', '活跃连接数'],\n        'ActivePeak': ['ActivePeak', '活跃连接数峰值'],//\n        'ActivePeakTime': ['ActivePeakTime', '活跃连接数峰值时间'],\n        'LogicConnectCount': ['LogicConnectCount', '逻辑连接打开次数'],\n        'LogicCloseCount': ['LogicCloseCount', '逻辑连接关闭次数'],\n        'LogicConnectErrorCount': ['LogicConnectErrorCount', '逻辑连接错误次数'],\n        'PhysicalConnectCount': ['PhysicalConnectCount', '物理连接打开次数'],\n        'PhysicalCloseCount': ['PhysicalCloseCount', '物理关闭数量'],\n        'PhysicalConnectErrorCount': ['PhysicalConnectErrorCount', '物理连接错误次数'],\n        'DiscardCount': ['DiscardCount', '校验失败废弃连接数'],\n        'ExecuteCount': ['ExecuteCount (Total)', '执行数(总共)'],\n        'ErrorCount': ['ErrorCount', '错误数'],\n        'CommitCount': ['CommitCount', '提交数'],\n        'RollbackCount': ['RollbackCount', '回滚数'],\n        'PSCacheAccessCount': ['PSCacheAccessCount', 'PSCache访问次数'],\n        'PSCacheHitCount': ['PSCacheHitCount', 'PSCache命中次数'],\n        'PSCacheMissCount': ['PSCacheMissCount', 'PSCache不命中次数'],//\n        'ConnectionHoldTimeHistogram': ['ConnectionHoldTimeHistogram', '连接持有时间分布'],\n        'ClobOpenCount': ['ClobOpenCount', 'Clob打开次数'],\n        'BlobOpenCount': ['BlobOpenCount', 'Blob打开次数'],\n        'KeepAliveCheckCount': ['KeepAliveCheckCount', 'KeepAlive检测次数'],\n        'ActiveConnectionStackTrace': ['ActiveConnection StackTrace', '活跃连接堆栈查看'],\n        'PollingConnectionInfo': ['PollingConnection Info', '连接池中连接信息'],\n        'SQLList': ['SQL List', 'sql列表'],\n\n        'UserNameDesc': ['Specify the username used when creating a new connection.', '指定建立连接时使用的用户名'],\n        'URLDesc': ['The JDBC driver connection URL', 'JDBC连接字符串'],\n        'DbTypeDesc': ['database type', '数据库类型'],\n        'DriverClassNameDesc': ['The fully qualifed name of the JDBC driver class', 'JDBC驱动的类名'],\n        'FilterClassNamesDesc': ['All the fully qualifed name of the filter classes', 'filter的类名'],\n        'TestOnBorrowDesc': ['\tTest or not when borrow a connection', '是否在获得连接后检测其可用性'],\n        'TestWhileIdleDesc': ['Test or not when a connection is idle for a while', '是否在连接空闲一段时间后检测其可用性'],\n        'TestOnReturnDesc': ['Test or not when return a connection', '是否在连接放回连接池后检测其可用性'],\n        'InitialSizeDesc': ['The size of datasource connections to create when initial a datasource', '连接池建立时创建的初始化连接数'],\n        'MinIdleDesc': ['The minimum number of connections a pool should hold. ', '连接池中最小的活跃连接数'],\n        'MaxActiveDesc': ['The maximum number of connections for a pool', '连接池中最大的活跃连接数'],\n        'QueryTimeoutDesc': ['', '查询超时时间'],\n        'TransactionQueryTimeoutDesc': ['', '事务查询超时时间'],\n        'LoginTimeoutDesc': ['', ''],///\n        'ValidConnectionCheckerClassNameDesc': ['', ''],\n        'ExceptionSorterClassNameDesc': ['', ''],\n        'DefaultAutoCommitDesc': ['', ''],\n        'DefaultReadOnlyDesc': ['', ''],\n        'DefaultTransactionIsolationDesc': ['', ''],\n        'NotEmptyWaitCountDesc': ['Total times for wait to get a connection', '获取连接时累计等待多少次'],//\n        'NotEmptyWaitMillisDesc': ['Total millis for wait to get a connection', '获取连接时累计等待多长时间'],\n        'WaitThreadCountDesc': ['The current waiting thread count', '当前等待获取连接的线程数'],\n        'StartTransactionCountDesc': ['The count of start transaction', '事务开始的个数'],\n        'TransactionHistogramDesc': ['The histogram values of transaction time, [0-1 ms, 1-10 ms, 10-100 ms, 100-1 s, 1-10 s, 10-100 s, >100 s]', '事务运行时间分布，分布区间为[0-1 ms, 1-10 ms, 10-100 ms, 100-1 s, 1-10 s, 10-100 s, >100 s]'],\n        'PoolingCountDesc': ['The current usefull connection count', '当前连接池中的数目'],//\n        'PoolingPeakDesc': ['The usefull connection peak count', '连接池中数目的峰值'],\n        'PoolingPeakTimeDesc': ['The usefull connection peak time', '连接池数目峰值出现的时间'],\n        'ActiveCountDesc': ['The current active connection count', '当前连接池中活跃连接数'],\n        'ActivePeakDesc': ['The current active connection peak count', '连接池中活跃连接数峰值'],\n        'ActivePeakTimeDesc': ['The active connection peak time', '活跃连接池峰值出现的时间'],\n        'LogicConnectCountDesc': ['Total connect times from datasource', '产生的逻辑连接建立总数'],\n        'LogicCloseCountDesc': ['Total close connect times from datasource', '产生的逻辑连接关闭总数'],\n        'LogicConnectErrorCountDesc': ['Total connect error times', '产生的逻辑连接出错总数'],\n        'RecycleErrorCount': ['Logic Connection Recycle Count', '逻辑连接回收重用次数'],\n        'PhysicalConnectCountDesc': ['Create physical connnection count', '产生的物理连接建立总数'],\n        'PhysicalCloseCountDesc': ['Close physical connnection count', '产生的物理关闭总数'],\n        'DiscardCountDesc': ['Discard connection count with validate fail', '校验连接失败丢弃连接次数'],\n        'PhysicalConnectErrorCountDesc': ['Total physical connect error times', '产生的物理连接失败总数'],\n        'ExecuteCountDesc': ['', ''],\n        'ErrorCountDesc': ['', ''],\n        'CommitCountDesc': ['', '事务提交次数'],\n        'RollbackCountDesc': ['', '事务回滚次数'],\n        'PSCacheAccessCountDesc': ['PerpareStatement access count', 'PSCache访问总数'],\n        'PSCacheHitCountDesc': ['PerpareStatement hit count', 'PSCache命中次数'],\n        'PSCacheMissCountDesc': ['PerpareStatement miss count', 'PSCache不命中次数'],//\n        'PreparedStatementOpenCount': ['Real PreparedStatement Open Count', '真实PreparedStatement打开次数'],//\n        'PreparedStatementClosedCount': ['Real PreparedStatement Closed Count', '真实PreparedStatement关闭次数'],//\n        'ConnectionHoldTimeHistogramDesc': ['The histogram values of connection hold time, [0-1 ms, 1-10 ms, 10-100 ms, 100ms-1s, 1-10 s, 10-100 s, 100-1000 s, >1000 s]', '连接持有时间分布，分布区间为[0-1 ms, 1-10 ms, 10-100 ms, 100ms-1s, 1-10 s, 10-100 s, 100-1000 s, >1000 s]'],\n        'ClobOpenCountDesc': ['', 'Clob打开数'],\n        'BlobOpenCountDesc': ['', 'Blob打开数'],\n        /**spring-detail*/\n        'Class': ['Class', 'Class'],\n        'Method': ['Method', 'Method'],\n        'ExecuteErrorCount': ['ExecuteErrorCount', '执行出错数'],\n        'ExecuteTimeMillis': ['ExecuteTimeMillis', '执行时间'],\n        'RunningCount': ['RunningCount', '执行中'],\n        'ConcurrentMax': ['ConcurrentMax', '最大并发'],\n        'JdbcExecuteCount': ['JdbcExecuteCount', 'Jdbc执行数'],\n        'JdbcExecuteErrorCount': ['JdbcExecErrorCount', 'Jdbc出错数'],\n        'JdbcExecuteTimeMillis': ['JdbcExecTimeMillis', 'Jdbc时间'],\n        'JdbcCommitCount': ['CommitCount', '事务提交数'],\n        'JdbcRollbackCount': ['RollbackCount', '事务回滚数'],\n        'JdbcFetchRowCount': ['FetchRowCount', '读取行数'],\n        'JdbcUpdateCount': ['UpdateCount', '更新行数'],\n        'JdbcPoolConnectionOpenCount': ['JdbcPoolConnectionOpenCount', '连接池获取连接次数'],\n        'JdbcPoolConnectionCloseCount': ['JdbcPoolConnectionCloseCount', '连接池关闭连接次数'],\n        'JdbcResultSetOpenCount': ['JdbcResultSetOpenCount', 'ResultSet打开次数'],\n        'JdbcResultSetCloseCount': ['JdbcResultSetCloseCount', 'ResultSet关闭次数'],\n        /**sql-detail*/\n        'ParseView': ['ParseView', '解析信息'],//\n        'Tables': [' Tables', '表'],\n        'Fields': ['Fields', '字段'],\n        'Coditions': ['Coditions', '条件'],\n        'Relationships': ['Relationships', '关联'],\n        'OrderByColumns': ['OrderByColumns', '排序字段'],\n        'LastSlowView': ['LastSlowView', '最后慢查询'],\n        'MaxTimespan': ['MaxTimespan', '最慢'],\n        'MaxTimespanOccurTime': ['MaxTimespanOccurTime', '最慢发生时间'],\n        'LastSlowParameters': ['LastSlowParameters', '最后慢查询参数'],\n        'LastErrorView': ['LastErrorView', '最后错误视图'],\n        'LastErrorMessage': ['LastErrorMessage', '最后错误信息'],\n        'LastErrorClass': ['LastErrorClass', '最后错误类'],\n        'LastErrorTime': ['LastErrorTime', '最后错误时间'],\n        'LastErrorStackTrace': ['LastErrorStackTrace', '最后错误堆栈'],\n        'OtherView': ['OtherView', '其他信息'],\n        'BatchSizeMax': ['BatchSizeMax', '批处理最大值'],////\n        'BatchSizeTotal': ['BatchSizeTotal', '批处理总数'],//\n        'ReaderOpenCount': ['ReaderOpenCount', 'reader打开次数'],//\n        'InputStreamOpenCount': ['InputStreamOpenCount', 'inputstream打开次数'],\n        'ReadStringLength': ['ReadStringLength', '读取字符串长度'],//\n        'ReadBytesLength': ['ReadBytesLength', '读取字节长度'],//\n\n        'ExecHisto': ['ExecHisto', '执行时间分布'],\n        'ExecRsHisto': ['ExecRsHisto', '执行+RS时分布'],\n        'FetchRowHisto': ['FetchRowHisto', '读取行分布'],\n        'UpdateHisto': ['UpdateHisto', '更新行分布'],\n        'DeleteHisto': ['DeleteHisto', '删除行分布'],\n        'InTransactionCount': ['Txn', '事务执行'],\n        'MaxTimespanDesc': ['Execute Time Millis Max', '最慢的执行耗时'],\n        'InTransactionCountDesc': ['Execute In Transaction Count', '在事务中运行的次数'],\n\n        'count1ms': ['count of 0-1 ms', '0-1毫秒次数'],\n        'count10ms': ['count of 1-10 ms', '1-10毫秒次数'],\n        'count100ms': ['count of 10-100 ms', '10-100毫秒次数'],\n        'count1s': ['count of 100ms-1s', '100-1000毫秒次数'],\n        'count10s': ['count of 1-10 s', '1-10秒次数'],\n        'count100s': ['count of 10-100 s', '10-100秒次数'],\n        'count1000s': ['count of 100-1000 s', '100-1000秒次数'],\n        'countBg1000s': ['count of >1000 s', '大于1000秒次数'],\n\n        'fetch0': ['count of 0 FetchRow', '读取行数为0'],\n        'fetch9': ['count of 1-9 FetchRow', '读取行数1-9'],\n        'fetch99': ['count of 10-99 FetchRow', '读取行数10-99'],\n        'fetch999': ['count of 100-999 FetchRow', '读取行数100-999'],\n        'fetch9999': ['count of 1000-9999 FetchRow', '读取行数1000-9999'],\n        'fetch99999': ['count of >9999 FetchRow', '读取行数大于9999'],\n\n        'update0': ['count of 0 UpdateCount', '更新行数为0'],\n        'update9': ['count of 1-9 UpdateCount', '更新行数1-9'],\n        'update99': ['count of 10-99 UpdateCount', '更新行数10-99'],\n        'update999': ['count of 100-999 UpdateCount', '更新行数100-999'],\n        'update9999': ['count of 1000-9999 UpdateCount', '更新行数1000-9999'],\n        'update99999': ['count of >9999 UpdateCount', '更新行数大于9999'],\n        /**wall*/\n        'CheckCount': ['CheckCount', '检查次数'],\n        'HardCheckCount': ['HardCheckCount', '硬检查次数'],\n        'ViolationCount': ['ViolationCount', '非法次数'],\n        'BlackListHitCount': ['BlackListHitCount', '黑名单命中次数'],\n        'BlackListSize': ['BlackListSize', '黑名单长度'],\n        'WhiteListHitCount': ['WhiteListHitCount', '白名单命中次数'],\n        'WhiteListSize': ['WhiteListSize', '白名单长度'],\n        'SyntaxErrrorCount': ['SyntaxErrrorCount', '语法错误次数'],\n        'TableName': ['TableName', '表名'],\n        'TableNumber': ['Number', '序号'],\n\n        'Sample': ['Sample', '样本'],\n        'ExecuteCount': ['ExecuteCount', '执行数'],\n        'FetchRowCount': ['FetchRowCount', '读取行数'],\n        'SQLUpdateCount': ['UpdateCount', '更新行数'],\n\n        'SelectCount': ['SelectCount', 'Select数'],\n        'SelectIntoCount': ['SelectIntoCount', 'SelectInto数'],\n        'InsertCount': ['InsertCount', 'Insert数'],\n        'UpdateCount': ['UpdateCount', 'Update数'],\n        'DeleteCount': ['DeleteCount', 'Delete数'],\n        'TruncateCount': ['TruncateCount', 'Truncate数'],\n        'CreateCount': ['CreateCount', 'Create数'],\n        'AlterCount': ['AlterCount', 'Alter数'],\n        'DropCount': ['DropCount', 'Drop数'],\n        'ReplaceCount': ['ReplaceCount', 'Replace数'],\n        'DeleteDataCount': ['DeleteDataCount', '删除数据行数'],\n        'UpdateDataCount': ['UpdateDataCount', '更新数据行数'],\n        'FetchRowCount': ['FetchRowCount', '读取行数'],\n        'WallStat': ['Wall Stat', '防御统计'],\n        'TableStat': ['Table Stat', '表访问统计'],\n        'FunctionStat': ['Function Stat', '函数调用统计'],\n        'SQLStatWhiteList': ['SQL Stat - White List', 'SQL防御统计 - 白名单'],\n        'SQLStatBlackList': ['SQL Stat - Black List', 'SQL防御统计 - 黑名单'],\n        /**session-detail*/\n        'PrincipalOnly': ['Principal Only', 'Principal过滤'],\n        'SESSIONID': ['SESSIONID', 'SESSIONID'],\n        'UserAgent': ['UserAgent', 'UserAgent'],\n        'Principal': ['Principal', 'Principal'],\n        'CreateTime': ['CreateTime', '创建时间'],\n        'LastAccessTime': ['LastAccessTime', '最后访问时间'],\n        'RemoteAddress': ['RemoteAddress', '访问ip地址'],\n        'RequestCount': ['RequestCount', '请求次数'],\n        'RequestTimeMillisTotal': ['RequestTimeMillisTotal', '总共请求时间'],\n        'RequestInterval': ['RequestInterval', '请求间隔'],\n        /**weburi-detail*/\n        'RefreshPeriod': ['Refresh Period', '刷新时间'],\n        'SuspendRefresh': ['Suspend Refresh', '暂停刷新'],\n        'RequestTimeMillis': ['RequestTimeMillisTotal', '请求时间（和）'],\n        'RequestTimeMillisMax': ['RequestTimeMillisMax', '请求最慢（单次）'],\n        'RequestTimeMillisMaxOccurTime': ['RequestTimeMillisMaxOccurTime', '请求最慢发生时间'],\n        'JdbcExecutePeak': ['JdbcExecutePeak', 'jdbc执行峰值'],\n        'JdbcFetchRowPeak': ['JdbcFetchRowPeak', 'jdbc查询取回行数峰值'],\n        'JdbcUpdatePeak': ['JdbcUpdatePeak', 'jdbc更新峰值'],\n        'Histogram': ['Histogram', '区间分布']\n\n    };\n\n    var COOKIE_LANG_NAME = \"cookie_lang\";\n\n    function log(str) {\n        if (typeof (console) != 'undefined' && typeof (console.log) != 'undefined') {\n            console.log(str);\n        } else {\n            $('body').append('<input type=\"hidden\" value=\"' + str + \" />\");\n        }\n    }\n\n    function setCookie(name, value, expires, path, domain, secure) {\n        var expDays = expires * 24 * 60 * 60 * 1000;\n        var expDate = new Date();\n        expDate.setTime(expDate.getTime() + expDays);\n        var expString = ((expires == null) ? \"\" : (\";expires=\" + expDate.toGMTString()));\n        var pathString = ((path == null) ? \"\" : (\";path=\" + path));\n        var domainString = ((domain == null) ? \"\" : (\";domain=\" + domain));\n        var secureString = ((secure == true) ? \";secure\" : \"\");\n        document.cookie = name + \"=\" + escape(value) + expString + pathString + domainString + secureString;\n    }\n\n    function getCookie(name) {\n        var result = null;\n        var myCookie = document.cookie + \";\";\n        var searchName = name + \"=\";\n        var startOfCookie = myCookie.indexOf(searchName);\n        var endOfCookie;\n        if (startOfCookie != -1) {\n            startOfCookie += searchName.length;\n            endOfCookie = myCookie.indexOf(\";\", startOfCookie);\n            result = unescape(myCookie.substring(startOfCookie, endOfCookie));\n        }\n        return result;\n    }\n\n    function setText($obj) {\n        var key = $obj.attr('langKey');\n        if (typeof (lang[key]) != 'undefined') {\n            var text = lang[key][druid.lang.langNow];\n            $obj.text(lang[key][druid.lang.langNow]);\n        } else {\n            log('key [' + key + '] not found');\n        }\n    }\n\n    function setTitle($obj) {\n        var key = $obj.attr('langKey');\n        if (typeof (lang[key]) != 'undefined') {\n            var title = lang[key][druid.lang.langNow];\n            $obj.attr('title', title);\n        } else {\n            log('key [' + key + '] not found');\n        }\n    }\n\n    return {\n        langNow: LANG_CN,\n        EVENT_LOAD_FINISHED: 'loadFinished',\n        init: function (langNow) {\n            if (typeof (langNow) != 'undefined') {\n                this.setLangType(langNow);\n            } else {\n                var langInCookie = getCookie(COOKIE_LANG_NAME);\n                if (langInCookie == LANG_CN || langInCookie == LANG_EN) {\n                    this.setLangType(langInCookie);\n                }\n            }\n            $(document).on(this.EVENT_LOAD_FINISHED, '.lang', function () {\n                log('load lang');\n                setText($(this));\n            });\n            $(document).on(this.EVENT_LOAD_FINISHED, '.langTitle', function () {\n                log('load title');\n                setTitle($(this));\n            });\n            this.trigger();\n\n            $(document).on('click', '.langSelector', function () {\n                var langSelected = $(this).attr('langNow');\n                druid.lang.setLangType(langSelected);\n                druid.lang.trigger();\n                return false;\n            });\n        },\n        setLangType: function (langNow) {\n            this.langNow = langNow;\n            setCookie(COOKIE_LANG_NAME, langNow, 30, '/');\n        },\n        getLangType: function () {\n            return this.langNow;\n        },\n        show: function ($parent) {\n            var $obj;\n            var $objTitle;\n            if ($parent) {\n                $obj = $parent.find('.lang');\n                $objTitle = $parent.find('.langTitle');\n            } else {\n                $obj = $('.lang');\n                $objTitle = $('.langTitle');\n            }\n            $obj.each(function () {\n                setText($(this));\n            });\n            $objTitle.each(function () {\n                setTitle($(this));\n            });\n        },\n        trigger: function () {\n            log('to load lang now');\n            $('.lang').trigger(this.EVENT_LOAD_FINISHED);//触发语言显示事件\n            $('.langTitle').trigger(this.EVENT_LOAD_FINISHED);//触发语言显示事件\n        }\n    }\n}();\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/login.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>druid monitor</title>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\">\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <style type=\"text/css\">\n        /* Override some defaults */\n        html, body {\n            background-color: #eee;\n        }\n\n        body {\n            padding-top: 40px;\n        }\n\n        .container {\n            width: 300px;\n        }\n\n        /* The white background content wrapper */\n        .container > .content {\n            background-color: #fff;\n            padding: 20px;\n            margin: 0 -20px;\n            -webkit-border-radius: 10px 10px 10px 10px;\n            -moz-border-radius: 10px 10px 10px 10px;\n            border-radius: 10px 10px 10px 10px;\n            -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .15);\n            -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, .15);\n            box-shadow: 0 1px 2px rgba(0, 0, 0, .15);\n        }\n\n        .login-form {\n            margin-left: 65px;\n        }\n\n        legend {\n            margin-right: -50px;\n            font-weight: bold;\n            color: #404040;\n        }\n\n    </style>\n\n</head>\n<body>\n<div class=\"container\">\n    <div class=\"content\">\n        <div class=\"row\">\n            <div class=\"login-form\">\n                <h2>Login</h2>\n                <form id=\"loginForm\" method=\"post\" autocomplete=\"off\">\n                    <fieldset>\n                        <div id=\"alertInfo\" class=\"alert alert-error clearfix\"\n                             style=\"margin-bottom: 5px;width: 195px; padding: 2px 15px 2px 10px;display: none;\">\n                            The username or password you entered is incorrect.\n                        </div>\n                        <div class=\"clearfix\">\n                            <input type=\"text\" placeholder=\"用户名\" name=\"loginUsername\" autofocus=\"autofocus\">\n                        </div>\n                        <div class=\"clearfix\">\n                            <input type=\"password\" placeholder=\"密码\" name=\"loginPassword\">\n                        </div>\n                        <button id=\"loginBtn\" class=\"btn btn-primary\" type=\"button\">Sign in</button>\n                        <button class=\"btn\" type=\"reset\">Reset</button>\n                    </fieldset>\n                </form>\n            </div>\n        </div>\n    </div>\n</div> <!-- /container -->\n<script type=\"text/javascript\">\n    $.namespace(\"druid.login\");\n    druid.login = function () {\n        return {\n            login: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: \"submitLogin\",\n                    data: $(\"#loginForm\").serialize(),\n                    success: function (data) {\n                        if (\"success\" == data)\n                            location.href = \"index.html\";\n                        else {\n                            $(\"#alertInfo\").show();\n                            $(\"#loginForm\")[0].reset();\n                            $(\"input[name=loginUsername]\").focus();\n                        }\n                    },\n                    dataType: \"text\"\n                });\n            },\n            unamecr: function (e) {\n                if (e.which == 13) { // enter key event\n                    $(\"input[name=loginPassword]\").focus();\n                }\n            },\n            upasscr: function (e) {\n                if (e.which == 13) { // enter key event\n                    $(\"#loginBtn\").click();\n                }\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        $(\"#loginBtn\").click(druid.login.login);\n        $(\"input[name=loginUsername]\").keypress(druid.login.unamecr);\n        $(\"input[name=loginPassword]\").keypress(druid.login.upasscr);\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "core/src/main/resources/support/http/resources/nopermit.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title></title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n</head>\n<body>\n<br/>\n<div id=\"main\">\n    <h2>Sorry, you are not permitted to view this page.</h2>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/spring-detail.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Spring Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                Spring View\n                <a id=\"viewJsonApi\" target=\"_blank\">View JSON API</a>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tr>\n                    <td class='td_lable lang' langKey=\"Class\"> Class</td>\n                    <td id=\"Class\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"Method\"> Method</td>\n                    <td id=\"Method\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"ExecuteCount\"> ExecuteCount</td>\n                    <td id=\"ExecuteCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"ExecuteErrorCount\"> ExecuteErrorCount</td>\n                    <td id=\"ExecuteErrorCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"ExecuteTimeMillis\"> ExecuteTimeMillis</td>\n                    <td id=\"ExecuteTimeMillis\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"RunningCount\"> RunningCount</td>\n                    <td id=\"RunningCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"ConcurrentMax\"> ConcurrentMax</td>\n                    <td id=\"ConcurrentMax\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcExecuteCount\"> JdbcExecuteCount</td>\n                    <td id=\"JdbcExecuteCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcExecuteErrorCount\"> JdbcExecuteErrorCount</td>\n                    <td id=\"JdbcExecuteErrorCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcExecuteTimeMillis\"> JdbcExecuteTimeMillis</td>\n                    <td id=\"JdbcExecuteTimeMillis\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcCommitCount\"> JdbcCommitCount</td>\n                    <td id=\"JdbcCommitCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcRollbackCount\"> JdbcRollbackCount</td>\n                    <td id=\"JdbcRollbackCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcFetchRowCount\"> JdbcFetchRowCount</td>\n                    <td id=\"JdbcFetchRowCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcUpdateCount\"> JdbcUpdateCount</td>\n                    <td id=\"JdbcUpdateCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcPoolConnectionOpenCount\"> JdbcPoolConnectionOpenCount</td>\n                    <td id=\"JdbcPoolConnectionOpenCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcPoolConnectionCloseCount\"> JdbcPoolConnectionCloseCount</td>\n                    <td id=\"JdbcPoolConnectionCloseCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcResultSetOpenCount\"> JdbcResultSetOpenCount</td>\n                    <td id=\"JdbcResultSetOpenCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable lang' langKey=\"JdbcResultSetCloseCount\"> JdbcResultSetCloseCount</td>\n                    <td id=\"JdbcResultSetCloseCount\"></td>\n                </tr>\n            </table>\n            <div class=\"container\">\n                <a class=\"btn btn-primary\" href=\"javascript:window.close();\">Close</a>\n            </div>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.springdetail\");\n    druid.springdetail = function () {\n        var clazz = druid.common.getUrlVar(\"class\");\n        var method = druid.common.getUrlVar(\"method\");\n        return {\n            init: function () {\n                druid.common.buildHead(7);\n                this.ajaxRequestForBasicInfo();\n                $(\"#viewJsonApi\").attr(\"href\", 'spring-detail.json?class=' + clazz + '&method=' + method);\n            },\n\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: 'spring-detail.json?class=' + clazz + '&method=' + method,\n                    success: function (data) {\n                        var stat = data.Content;\n                        if (stat == null)\n                            return;\n\n                        $(\"#Class\").text(stat.Class)\n                        $(\"#Method\").text(stat.Method)\n                        $(\"#ExecuteCount\").text(stat.ExecuteCount)\n                        $(\"#ExecuteErrorCount\").text(stat.ExecuteErrorCount)\n                        $(\"#ExecuteTimeMillis\").text(stat.ExecuteTimeMillis)\n                        $(\"#RunningCount\").text(stat.RunningCount)\n                        $(\"#ConcurrentMax\").text(stat.ConcurrentMax)\n                        $(\"#JdbcExecuteCount\").text(stat.JdbcExecuteCount)\n                        $(\"#JdbcExecuteErrorCount\").text(stat.JdbcExecuteErrorCount)\n                        $(\"#JdbcExecuteTimeMillis\").text(stat.JdbcExecuteTimeMillis)\n                        $(\"#JdbcCommitCount\").text(stat.JdbcCommitCount)\n                        $(\"#JdbcRollbackCount\").text(stat.JdbcRollbackCount)\n                        $(\"#JdbcFetchRowCount\").text(stat.JdbcFetchRowCount)\n                        $(\"#JdbcUpdateCount\").text(stat.JdbcUpdateCount)\n\n                        $(\"#JdbcPoolConnectionOpenCount\").text(stat.JdbcPoolConnectionOpenCount)\n                        $(\"#JdbcPoolConnectionCloseCount\").text(stat.JdbcPoolConnectionCloseCount)\n                        $(\"#JdbcResultSetOpenCount\").text(stat.JdbcResultSetOpenCount)\n                        $(\"#JdbcResultSetCloseCount\").text(stat.JdbcResultSetCloseCount)\n                    },\n                    dataType: \"json\"\n                });\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.springdetail.init();\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "core/src/main/resources/support/http/resources/spring.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Spring Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                Spring Stat\n                <a href=\"spring.json\" target=\"_blank\">View JSON API</a>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered table-striped responsive-utilities\">\n                <thead>\n                <tr>\n                    <th>N</th>\n                    <th><a id=\"th-Class\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"Class\">Class</a></th>\n                    <th><a id=\"th-Method\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"Method\">Method</a></th>\n                    <th><a id=\"th-ExecuteCount\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"ExecuteCount\">ExecuteCount</a>\n                    </th>\n                    <th><a id=\"th-ExecuteTimeMillis\" href=\"javascript:void(0);\" class=\"lang\"\n                           langKey=\"ExecuteTimeMillis\">ExecuteTimeMillis</a></th>\n                    <th><a id=\"th-RunningCount\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"RunningCount\">RunningCount</a>\n                    </th>\n                    <th><a id=\"th-ConcurrentMax\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"ConcurrentMax\">ConcurrentMax</a>\n                    </th>\n                    <th><a id=\"th-JdbcExecuteCount\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"JdbcExecuteCount\">JdbcExecuteCount</a>\n                    </th>\n                    <th><a id=\"th-JdbcExecuteTimeMillis\" href=\"javascript:void(0);\" class=\"lang\"\n                           langKey=\"JdbcExecuteTimeMillis\">JdbcExecuteTimeMillis</a></th>\n                    <th><a id=\"th-JdbcCommitCount\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"JdbcCommitCount\">JdbcCommitCount</a>\n                    </th>\n                    <th><a id=\"th-JdbcRollbackCount\" href=\"javascript:void(0);\" class=\"lang\"\n                           langKey=\"JdbcRollbackCount\">JdbcRollbackCount</a></th>\n                    <th><a id=\"th-JdbcFetchRowCount\" href=\"javascript:void(0);\" class=\"lang\"\n                           langKey=\"JdbcFetchRowCount\">JdbcFetchRowCount</a></th>\n                    <th><a id=\"th-JdbcUpdateCount\" href=\"javascript:void(0);\" class=\"lang\" langKey=\"JdbcUpdateCount\">JdbcUpdateCount</a>\n                    </th>\n                    <th align=\"left\" width=\"100\"><span class=\"lang\" langKey=\"Histogram\">Histogram</span> <br/>[\n                        <a id=\"th-Histogram[0]\" class=\"langTitle\" langKey=\"count1ms\" title=\"count of '0-1 ms'\">-</a>\n                        <a id=\"th-Histogram[1]\" class=\"langTitle\" langKey=\"count10ms\" title=\"count of '1-10 ms'\">-</a>\n                        <a id=\"th-Histogram[2]\" class=\"langTitle\" langKey=\"count100ms\"\n                           title=\"count of '10-100 ms'\">-</a>\n                        <a id=\"th-Histogram[3]\" class=\"langTitle\" langKey=\"count1s\" title=\"count of '100ms-1 s'\">-</a>\n                        <a id=\"th-Histogram[4]\" class=\"langTitle\" langKey=\"count10s\" title=\"count of '1-10 s'\">-</a>\n                        <a id=\"th-Histogram[5]\" class=\"langTitle\" langKey=\"count100s\" title=\"count of '10-100 s'\">-</a>\n                        <a id=\"th-Histogram[6]\" class=\"langTitle\" langKey=\"count1000s\"\n                           title=\"count of '100-1000 s'\">-</a>\n                        <a id=\"th-Histogram[7]\" class=\"langTitle\" langKey=\"countBg1000s\"\n                           title=\"count of '> 1000 s'\">-</a> ]\n                    </th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.spring\");\n    druid.spring = function () {\n        return {\n            init: function () {\n                $(\"#dataTable th a\").click(function (obj) {\n                    druid.common.setOrderBy(obj.target.id.substring(3))\n                })\n                druid.common.buildHead(7);\n                druid.common.ajaxuri = 'spring.json?';\n                druid.common.handleAjaxResult = druid.spring.handleAjaxResult;\n                druid.common.ajaxRequestForBasicInfo();\n                setInterval(\"druid.common.ajaxRequestForBasicInfo();\", 10000);\n            },\n\n            handleAjaxResult: function (data) {\n                var statList = data.Content;\n                if (statList == null) return;\n\n                var sqlStatTable = document.getElementById(\"dataTable\");\n                while (sqlStatTable.rows.length > 1) {\n                    sqlStatTable.deleteRow(1);\n                }\n\n                var html = \"\";\n                for (var i = 0; i < statList.length; i++) {\n                    var stat = statList[i];\n                    var newRow = sqlStatTable.insertRow(-1);\n                    html += \"<tr>\";\n                    html += \"<td>\" + (i + 1) + \"</td>\";\n                    html += \"<td>\" + stat.Class + \"</td>\";\n                    html += \"<td>\" + '<a target=\"_blank\" href=\"spring-detail.html?class=' + stat.Class + '&method=' + stat.Method + '\">' + stat.Method + '</a>' + \"</td>\";\n                    html += \"<td>\" + replace(stat.ExecuteCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.ExecuteTimeMillis) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RunningCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.ConcurrentMax) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcExecuteCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcExecuteTimeMillis) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcCommitCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcRollbackCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcFetchRowCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcUpdateCount) + \"</td>\";\n                    html += \"<td>\" + '[' + stat.Histogram + ']' + \"</td>\";\n                    html += \"</tr>\";\n                }\n                $(\"#dataTable tbody\").html(html);\n                druid.common.stripes();\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.spring.init();\n    });\n    window.initPage = druid.common.ajaxRequestForBasicInfo;\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/sql-detail.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid SQL Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                FULL SQL\n                <a id=\"viewJsonApi\" target=\"_blank\">View JSON API</a>\n            </h3>\n            <h5 id=\"fullSql\"></h5>\n            <h2> Format View:</h2>\n            <textarea style='width:99%;height:120px;;border:1px #A8C7CE solid;line-height:20px;font-size:12px;'\n                      id=\"formattedSql\">\n\t\t\t\t\t  \t</textarea>\n            <br/>\n            <br/>\n            <h3>ParseView:</h3>\n            <table class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\" Tables\"> Tables</td>\n                    <td id=\"parsedtable\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"Fields\">Fields</td>\n                    <td id=\"parsedfields\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"Coditions\">Coditions</td>\n                    <td id=\"parsedConditions\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"Relationships\">Relationships</td>\n                    <td id=\"parsedRelationships\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"OrderByColumns\">OrderByColumns</td>\n                    <td id=\"parsedOrderbycolumns\"></td>\n                </tr>\n            </table>\n            <h3>LastSlowView:</h3>\n            <table class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"MaxTimespan\">MaxTimespan</td>\n                    <td id=\"MaxTimespan\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"MaxTimespanOccurTime\">MaxTimespanOccurTime\n                    </td>\n                    <td id=\"MaxTimespanOccurTime\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"LastSlowParameters\">LastSlowParameters</td>\n                    <td id=\"LastSlowParameters\"></td>\n                </tr>\n            </table>\n            <h3>LastErrorView:</h3>\n            <table class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"LastErrorMessage\">LastErrorMessage</td>\n                    <td id=\"LastErrorMessage\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"LastErrorClass\">LastErrorClass</td>\n                    <td id=\"LastErrorClass\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"LastErrorTime\">LastErrorTime</td>\n                    <td id=\"LastErrorTime\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"LastErrorStackTrace\">LastErrorStackTrace</td>\n                    <td id=\"LastErrorStackTrace\"></td>\n                </tr>\n            </table>\n            <h3>OtherView:</h3>\n            <table class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"BatchSizeMax\">BatchSizeMax</td>\n                    <td id=\"BatchSizeMax\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"BatchSizeTotal\">BatchSizeTotal</td>\n                    <td id=\"BatchSizeTotal\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"BlobOpenCount\">BlobOpenCount</td>\n                    <td id=\"BlobOpenCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"ClobOpenCount\">ClobOpenCount</td>\n                    <td id=\"ClobOpenCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"ReaderOpenCount\">ReaderOpenCount</td>\n                    <td id=\"ReaderOpenCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"InputStreamOpenCount\">InputStreamOpenCount\n                    </td>\n                    <td id=\"InputStreamOpenCount\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"ReadStringLength\">ReadStringLength</td>\n                    <td id=\"ReadStringLength\"></td>\n                </tr>\n                <tr>\n                    <td class='td_lable' width='130' class=\"lang\" langKey=\"ReadBytesLength\">ReadBytesLength</td>\n                    <td id=\"ReadBytesLength\"></td>\n                </tr>\n            </table>\n            <div class=\"container\">\n                <a class=\"btn btn-primary\" href=\"javascript:window.close();\">Close</a>\n            </div>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.sqlDetail\");\n    druid.sqlDetail = function () {\n        var sqlId = druid.common.getUrlVar(\"sqlId\");\n        return {\n            init: function () {\n                druid.common.buildHead(2);\n                this.ajaxRequestForBasicInfo();\n                $(\"#viewJsonApi\").attr(\"href\", 'sql-' + sqlId + '.json');\n            },\n\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: 'sql-' + sqlId + '.json',\n                    success: function (data) {\n                        var sqlInfo = data.Content;\n                        if (sqlInfo == null)\n                            return;\n\n                        var sql = sqlInfo.SQL;\n                        if (sql != null) {\n                            sql = sql.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n                        } else {\n                            sql = '';\n                        }\n\n                        $(\"#fullSql\").text(sql)\n                        $(\"#formattedSql\").text(sqlInfo.formattedSql)\n                        $(\"#parsedtable\").text(sqlInfo.parsedTable)\n                        $(\"#parsedfields\").text(sqlInfo.parsedFields)\n                        $(\"#parsedConditions\").text(sqlInfo.parsedConditions)\n                        $(\"#parsedRelationships\").text(sqlInfo.parsedRelationships)\n                        $(\"#parsedOrderbycolumns\").text(sqlInfo.parsedOrderbycolumns)\n\n                        $(\"#MaxTimespanOccurTime\").text(sqlInfo.MaxTimespanOccurTime)\n                        $(\"#LastSlowParameters\").text(sqlInfo.LastSlowParameters)\n                        $(\"#MaxTimespan\").text(sqlInfo.MaxTimespan)\n\n                        $(\"#LastErrorMessage\").text(sqlInfo.LastErrorMessage)\n                        $(\"#LastErrorClass\").text(sqlInfo.LastErrorClass)\n                        $(\"#LastErrorTime\").text(sqlInfo.LastErrorTime)\n                        $(\"#LastErrorStackTrace\").text(sqlInfo.LastErrorStackTrace)\n\n                        $(\"#BatchSizeMax\").text(sqlInfo.BatchSizeMax)\n                        $(\"#BatchSizeTotal\").text(sqlInfo.BatchSizeTotal)\n                        $(\"#BlobOpenCount\").text(sqlInfo.BlobOpenCount)\n                        $(\"#ClobOpenCount\").text(sqlInfo.ClobOpenCount)\n                        $(\"#InputStreamOpenCount\").text(sqlInfo.InputStreamOpenCount)\n                        $(\"#ReaderOpenCount\").text(sqlInfo.ReaderOpenCount)\n                        $(\"#ReadStringLength\").text(sqlInfo.ReadStringLength)\n                        $(\"#ReadBytesLength\").text(sqlInfo.ReadBytesLength)\n\n                        druid.lang.trigger();\n                    },\n                    dataType: \"json\"\n                });\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.sqlDetail.init();\n    });\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/sql.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid SQL Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/bootstrap.min.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                SQL Stat\n                <a href=\"sql.json\" target=\"_blank\">View JSON API</a>\n                <span class=\"pull-right\" style=\"font-size: 16px; margin-right: 20px;\">\n                    <label langkey=\"RefreshPeriod\" class=\"lang\" style=\"display: inline;\"\n                            for=\"refreshSecondsSelect\">Refresh Period</label>\n                    <select id=\"refreshSecondsSelect\" class=\"refresh-seconds-select btn\" style=\"width:80px;\"\n                            onchange=\"javascript:druid.sql.refreshSeconds=parseInt(this.options[this.options.selectedIndex].value);\">\n                        <option value=\"5\">5s</option>\n                        <option value=\"10\" selected=\"selected\">10s</option>\n                        <option value=\"20\">20s</option>\n                        <option value=\"30\">30s</option>\n                        <option value=\"60\">60s</option>\n                    </select>\n                    <a id=\"btnSuspendRefresh\" langkey=\"SuspendRefresh\" class=\"btn btn-primary lang\"\n                        href=\"javascript:druid.sql.switchSuspendRefresh();\">Suspend Refresh</a>\n                </span>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered table-striped responsive-utilities\">\n                <thead>\n                <tr>\n                    <th width=\"10\">N</th>\n                    <th><a id=\"th-SQL\">SQL</a></th>\n                    <th><a id=\"th-Name\">数据源</a></th>\n                    <th width=\"50\"><a id=\"th-ExecuteCount\" class=\"lang\" langKey=\"ExecuteCount\">ExecCount</a></th>\n                    <th width=\"60\"><a id=\"th-TotalTime\" class=\"lang\" langKey=\"ExecuteTimeMillis\">ExecTime</a></th>\n                    <th width=\"50\" class=\"langTitle\" langKey=\"MaxTimespanDesc\" title=\"Execute Time Millis Max\"><a\n                            id=\"th-MaxTimespan\" class=\"lang\" langKey=\"MaxTimespan\">ExecMax</a></th>\n                    <th width=\"60\" class=\"langTitle\" langKey=\"InTransactionCountDesc\"\n                        title=\"Execute In Transaction Count\"><a id=\"th-InTransactionCount\" class=\"lang\"\n                                                                langKey=\"InTransactionCount\">Txn</a></th>\n                    <th width=\"50\"><a id=\"th-ErrorCount\" class=\"lang\" langKey=\"ErrorCount\">Error</a></th>\n                    <th width=\"60\"><a id=\"th-EffectedRowCount\" class=\"lang\" langKey=\"JdbcUpdateCount\">Update</a></th>\n                    <th width=\"60\"><a id=\"th-FetchRowCount\" class=\"lang\" langKey=\"JdbcFetchRowCount\">FetchRow</a></th>\n                    <th width=\"50\"><a id=\"th-RunningCount\" class=\"lang\" langKey=\"RunningCount\">Running</a></th>\n                    <th width=\"60\"><a id=\"th-ConcurrentMax\" class=\"lang\" langKey=\"ConcurrentMax\">Concurrent</a></th>\n                    <th align=\"left\" width=\"100\"><span class=\"lang\" langKey=\"ExecHisto\">ExecHisto</span> <br/>[\n                        <a id=\"th-Histogram[0]\" class=\"langTitle\" langKey=\"count1ms\" title=\"count of '0-1 ms'\">-</a>\n                        <a id=\"th-Histogram[1]\" class=\"langTitle\" langKey=\"count10ms\" title=\"count of '1-10 ms'\">-</a>\n                        <a id=\"th-Histogram[2]\" class=\"langTitle\" langKey=\"count100ms\"\n                           title=\"count of '10-100 ms'\">-</a>\n                        <a id=\"th-Histogram[3]\" class=\"langTitle\" langKey=\"count1s\" title=\"count of '100ms-1 s'\">-</a>\n                        <a id=\"th-Histogram[4]\" class=\"langTitle\" langKey=\"count10s\" title=\"count of '1-10 s'\">-</a>\n                        <a id=\"th-Histogram[5]\" class=\"langTitle\" langKey=\"count100s\" title=\"count of '10-100 s'\">-</a>\n                        <a id=\"th-Histogram[6]\" class=\"langTitle\" langKey=\"count1000s\"\n                           title=\"count of '100-1000 s'\">-</a>\n                        <a id=\"th-Histogram[7]\" class=\"langTitle\" langKey=\"countBg1000s\"\n                           title=\"count of '> 1000 s'\">-</a> ]\n                    </th>\n                    <th align=\"left\" width=\"100\"><span class=\"lang\" langKey=\"ExecRsHisto\">ExecRsHisto</span> <br/>[\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[0]\" class=\"langTitle\" langKey=\"count1ms\"\n                           title=\"count of '0-1 ms'\">-</a>\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[1]\" class=\"langTitle\" langKey=\"count10ms\"\n                           title=\"count of '1-10 ms'\">-</a>\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[2]\" class=\"langTitle\" langKey=\"count100ms\"\n                           title=\"count of '10-100 ms'\">-</a>\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[3]\" class=\"langTitle\" langKey=\"count1s\"\n                           title=\"count of '100ms-1s'\">-</a>\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[4]\" class=\"langTitle\" langKey=\"count10s\"\n                           title=\"count of '1-10 s'\">-</a>\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[5]\" class=\"langTitle\" langKey=\"count100s\"\n                           title=\"count of '10-100 s'\">-</a>\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[6]\" class=\"langTitle\" langKey=\"count1000s\"\n                           title=\"count of '100-1000 s'\">-</a>\n                        <a id=\"th-ExecuteAndResultHoldTimeHistogram[7]\" class=\"langTitle\" langKey=\"countBg1000s\"\n                           title=\"count of '> 1000 s'\">-</a> ]\n                    </th>\n                    <th align=\"left\" width=\"100\"><span class=\"lang\" langKey=\"FetchRowHisto\">FetchRowHisto</span> <br/>[\n                        <a id=\"th-FetchRowCountHistogram[0]\" class=\"langTitle\" langKey=\"fetch0\"\n                           title=\"count of '0 FetchRow'\">-</a>\n                        <a id=\"th-FetchRowCountHistogram[1]\" class=\"langTitle\" langKey=\"fetch9\"\n                           title=\"count of '1-9 FetchRow'\">-</a>\n                        <a id=\"th-FetchRowCountHistogram[2]\" class=\"langTitle\" langKey=\"fetch99\"\n                           title=\"count of '10-99 FetchRow'\">-</a>\n                        <a id=\"th-FetchRowCountHistogram[3]\" class=\"langTitle\" langKey=\"fetch999\"\n                           title=\"count of '100-999 FetchRow'\">-</a>\n                        <a id=\"th-FetchRowCountHistogram[4]\" class=\"langTitle\" langKey=\"fetch9999\"\n                           title=\"count of '1000-9999 FetchRow'\">-</a>\n                        <a id=\"th-FetchRowCountHistogram[5]\" class=\"langTitle\" langKey=\"fetch99999\"\n                           title=\"count of '> 9999 FetchRow'\">-</a> ]\n                    </th>\n                    <th align=\"left\" width=\"100\"><span class=\"lang\" langKey=\"UpdateHisto\">UpdateHisto</span> <br/>[\n                        <a id=\"th-EffectedRowCountHistogram[0]\" class=\"langTitle\" langKey=\"update0\"\n                           title=\"count of '0 UpdateCount'\">-</a>\n                        <a id=\"th-EffectedRowCountHistogram[1]\" class=\"langTitle\" langKey=\"update9\"\n                           title=\"count of '1-9 UpdateCount'\">-</a>\n                        <a id=\"th-EffectedRowCountHistogram[2]\" class=\"langTitle\" langKey=\"update99\"\n                           title=\"count of '10-99 UpdateCount'\">-</a>\n                        <a id=\"th-EffectedRowCountHistogram[3]\" class=\"langTitle\" langKey=\"update999\"\n                           title=\"count of '100-999 UpdateCount'\">-</a>\n                        <a id=\"th-EffectedRowCountHistogram[4]\" class=\"langTitle\" langKey=\"update9999\"\n                           title=\"count of '1000-9999 UpdateCount'\">-</a>\n                        <a id=\"th-EffectedRowCountHistogram[5]\" class=\"langTitle\" langKey=\"update99999\"\n                           title=\"count of '> 9999 UpdateCount'\">-</a> ]\n                    </th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.sql\");\n    druid.sql = function () {\n        var dataSourceId = druid.common.getUrlVar(\"dataSourceId\");\n        return {\n            init: function () {\n                $(\"#dataTable th a\").click(function (obj) {\n                    druid.common.setOrderBy(obj.target.id.substring(3))\n                })\n                druid.common.buildHead(2);\n                druid.common.ajaxuri = dataSourceId ? 'sql.json?dataSourceId=' + dataSourceId + '&' : 'sql.json?';\n                druid.common.handleCallback = druid.sql.handleAjaxResult;\n                druid.common.setOrderBy(\"SQL\");\n                druid.sql.controlRefresh();\n            },\n            controlRefresh: function () {\n                var FIVE = 10;\n                if (!druid.sql.refreshSeconds) {\n                    druid.sql.refreshSeconds = FIVE;\n                }\n                if (!druid.sql.suspendedSeconds) {\n                    druid.sql.suspendedSeconds = 0;\n                }\n                druid.sql.suspendedSeconds += FIVE;\n                if (!druid.sql.disableAutoRefresh) {\n                    if (druid.sql.suspendedSeconds >= druid.sql.refreshSeconds) {\n                        druid.sql.suspendedSeconds = 0;\n                        druid.common.ajaxRequestForBasicInfo();\n                    }\n                }\n                setTimeout(druid.sql.controlRefresh, FIVE * 1000);\n            },\n            switchSuspendRefresh: function () {\n                druid.sql.disableAutoRefresh = !druid.sql.disableAutoRefresh;\n                if (druid.sql.disableAutoRefresh) {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-warning\").removeClass(\"btn-primary\");\n                } else {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-primary\").removeClass(\"btn-warning\");\n                }\n            },\n            disableAutoRefresh: false,\n            refreshSeconds: 10,\n            suspendedSeconds: 0,\n\n            handleAjaxResult: function (data) {\n                var sqlStatList = data.Content;\n                var sqlStatTable = document.getElementById(\"dataTable\");\n                while (sqlStatTable.rows.length > 1) {\n                    sqlStatTable.deleteRow(1);\n                }\n                if (sqlStatList == null) return;\n                var html = \"\";\n                for (var i = 0; i < sqlStatList.length; i++) {\n                    var stat = sqlStatList[i], statSQL = stat.SQL;\n                    if (statSQL == null || statSQL == undefined) {\n                        continue;\n                    }\n                    var newStatSQL = statSQL.replace(/\\\"/g, \"'\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n                    var newRow = sqlStatTable.insertRow(-1);\n                    html += \"<tr>\";\n                    html += \"<td>\" + (i + 1) + \"</td>\";\n                    html += \"<td>\" + '<a data-dismiss=\"alert\"  title=\"' + newStatSQL + '\" target=\"_blank\" href=\"sql-detail.html?sqlId=' + stat.ID + '\">' + druid.common.subSqlString(stat.SQL, 60) + '</a>' + \"</td>\";\n                    html += \"<td>\" + replace(stat.Name) + \"</td>\";\n                    html += \"<td>\" + replace(stat.ExecuteCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.TotalTime) + \"</td>\";\n\n                    var lastSlowHtml = stat.MaxTimespan;\n                    if (stat.LastSlowParameters != null && stat.LastSlowParameters.length > 0) {\n                        lastSlowHtml = '<a target=\"_blank\" style=\"color:red\" href=\"sql-detail.html?sqlId=' + stat.ID + '\">' + stat.MaxTimespan + '</a>';\n                    }\n                    html += \"<td>\" + replace(lastSlowHtml) + \"</td>\";\n                    html += \"<td>\" + replace(stat.InTransactionCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.ErrorCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.EffectedRowCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.FetchRowCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RunningCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.ConcurrentMax) + \"</td>\";\n                    html += \"<td>\" + '[' + stat.Histogram + ']' + \"</td>\";\n                    html += \"<td>\" + '[' + stat.ExecuteAndResultHoldTimeHistogram + ']' + \"</td>\";\n                    html += \"<td>\" + '[' + stat.FetchRowCountHistogram + ']' + \"</td>\";\n                    html += \"<td>\" + '[' + stat.EffectedRowCountHistogram + ']' + \"</td>\";\n                    html += \"</tr>\";\n                }\n                $(\"#dataTable tbody\").html(html);\n                druid.common.stripes();\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.sql.init();\n    });\n    window.initPage = druid.common.ajaxRequestForBasicInfo;\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/wall.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid DataSourceStat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <style type=\"text/css\">\n        #dataTable td {\n            min-width: 80px;\n        }\n    </style>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"js/bootstrap.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3 class=\"lang\" langKey=\"WallStat\">\n                Wall Stat <a href=\"wall.json\" target=\"_blank\">View JSON API</a>\n                <span class=\"pull-right\" style=\"font-size: 16px; margin-right: 20px;\">\n                    <label langkey=\"RefreshPeriod\" class=\"lang\" style=\"display: inline;\"\n                            for=\"refreshSecondsSelect\">Refresh Period</label>\n                    <select id=\"refreshSecondsSelect\" class=\"refresh-seconds-select btn\" style=\"width:80px;\"\n                            onchange=\"javascript:druid.wall.refreshSeconds=parseInt(this.options[this.options.selectedIndex].value);\">\n                        <option value=\"5\">5s</option>\n                        <option value=\"10\" selected=\"selected\">10s</option>\n                        <option value=\"20\">20s</option>\n                        <option value=\"30\">30s</option>\n                        <option value=\"60\">60s</option>\n                    </select>\n                    <a id=\"btnSuspendRefresh\" langkey=\"SuspendRefresh\" class=\"btn btn-primary lang\"\n                        href=\"javascript:druid.wall.switchSuspendRefresh();\">Suspend Refresh</a>\n                </span>\n            </h3>\n            <table id=\"dataTable\" style=\"background-color: #fff\"\n                   class=\"table table-bordered responsive-utilities\">\n                <tr>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"CheckCount\">\n                        CheckCount\n                    </td>\n                    <td id=\"CheckCount\"></td>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"HardCheckCount\">\n                        HardCheckCount\n                    </td>\n                    <td id=\"HardCheckCount\"></td>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"ViolationCount\">\n                        ViolationCount\n                    </td>\n                    <td id=\"ViolationCount\"></td>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"SyntaxErrrorCount\">\n                        SyntaxErrrorCount\n                    </td>\n                    <td id=\"SyntaxErrrorCount\"></td>\n                </tr>\n                <tr>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"BlackListHitCount\">\n                        BlackListHitCount\n                    </td>\n                    <td id=\"BlackListHitCount\"></td>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"BlackListSize\">\n                        BlackListSize\n                    </td>\n                    <td id=\"BlackListSize\"></td>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"WhiteListHitCount\">\n                        WhiteListHitCount\n                    </td>\n                    <td id=\"WhiteListHitCount\"></td>\n                    <td valign=\"top\" class=\"td_lable lang\" langKey=\"WhiteListSize\">\n                        WhiteListSize\n                    </td>\n                    <td id=\"WhiteListSize\"></td>\n                </tr>\n            </table>\n\n            <h3 class=\"lang\" langKey=\"TableStat\">Table Stat</h3>\n            <table id=\"dataTable1\" style=\"background-color: #fff\"\n                   class=\"table table-bordered table-striped responsive-utilities\">\n                <thead>\n                <tr>\n                    <th class=\"td_lable\" style=\"min-width: 10px\"><a id=\"th-TableNumber\" class=\"lang\"\n                                            langKey=\"TableNumber\">TableNumber</a></th>\n                    <th class=\"td_lable\"><a id=\"th-tableName\" class=\"lang\"\n                                            langKey=\"TableName\">TableName</a></th>\n                    <th class=\"td_lable\"><a id=\"th-selectCount\" class=\"lang\"\n                                            langKey=\"SelectCount\">SelectCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-selectIntoCount\" class=\"lang\"\n                                            langKey=\"SelectIntoCount\">SelectCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-insertCount\" class=\"lang\"\n                                            langKey=\"InsertCount\">InsertCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-updateCount\" class=\"lang\"\n                                            langKey=\"UpdateCount\">UpdateCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-deleteCount\" class=\"lang\"\n                                            langKey=\"DeleteCount\">DeleteCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-truncateCount\" class=\"lang\"\n                                            langKey=\"TruncateCount\">TruncateCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-createCount\" class=\"lang\"\n                                            langKey=\"CreateCount\">CreateCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-alterCount\" class=\"lang\"\n                                            langKey=\"AlterCount\">AlterCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-dropCount\" class=\"lang\"\n                                            langKey=\"DropCount\">DropCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-replaceCount\" class=\"lang\"\n                                            langKey=\"ReplaceCount\">ReplaceCount</a></th>\n                    <th class=\"td_lable\"><a id=\"th-deleteDataCount\" class=\"lang\"\n                                            langKey=\"DeleteDataCount\">DeleteDataCount</a></th>\n                    <th class=\"td_lable\" align=\"left\" style=\"min-width:40px\"><span class=\"lang\" langKey=\"DeleteHisto\">DeleteDataHisto</span> <br/>[\n                        <a id=\"th-deleteDataCountHistogram[0]\" class=\"langTitle\" langKey=\"delete0\"\n                           title=\"count of '0 DeleteCount'\">-</a>\n                        <a id=\"th-deleteDataCountHistogram[1]\" class=\"langTitle\" langKey=\"delete9\"\n                           title=\"count of '1-9 DeleteCount'\">-</a>\n                        <a id=\"th-deleteDataCountHistogram[2]\" class=\"langTitle\" langKey=\"delete99\"\n                           title=\"count of '10-99 DeleteCount'\">-</a>\n                        <a id=\"th-deleteDataCountHistogram[3]\" class=\"langTitle\" langKey=\"delete999\"\n                           title=\"count of '100-999 DeleteCount'\">-</a>\n                        <a id=\"th-deleteDataCountHistogram[4]\" class=\"langTitle\" langKey=\"delete9999\"\n                           title=\"count of '1000-9999 DeleteCount'\">-</a>\n                        <a id=\"th-deleteDataCountHistogram[5]\" class=\"langTitle\" langKey=\"delete99999\"\n                           title=\"count of '> 9999 DeleteCount'\">-</a> ]\n                    </th>\n                    <th class=\"td_lable\"><a id=\"th-UpdateDataCount\" class=\"lang\"\n                                            langKey=\"UpdateDataCount\">UpdateDataCount</a></th>\n                    <th class=\"td_lable\" align=\"left\" style=\"min-width:40px\"><span class=\"lang\" langKey=\"UpdateHisto\">UpdateDataHisto</span> <br/>[\n                        <a id=\"th-updateDataCountHistogram[0]\" class=\"langTitle\" langKey=\"update0\"\n                           title=\"count of '0 UpdateCount'\">-</a>\n                        <a id=\"th-updateDataCountHistogram[1]\" class=\"langTitle\" langKey=\"update9\"\n                           title=\"count of '1-9 UpdateCount'\">-</a>\n                        <a id=\"th-updateDataCountHistogram[2]\" class=\"langTitle\" langKey=\"update99\"\n                           title=\"count of '10-99 UpdateCount'\">-</a>\n                        <a id=\"th-updateDataCountHistogram[3]\" class=\"langTitle\" langKey=\"update999\"\n                           title=\"count of '100-999 UpdateCount'\">-</a>\n                        <a id=\"th-updateDataCountHistogram[4]\" class=\"langTitle\" langKey=\"update9999\"\n                           title=\"count of '1000-9999 UpdateCount'\">-</a>\n                        <a id=\"th-updateDataCountHistogram[5]\" class=\"langTitle\" langKey=\"update99999\"\n                           title=\"count of '> 9999 UpdateCount'\">-</a> ]\n                    </th>\n                    <th class=\"td_lable\"><a id=\"th-FetchRowCount\" class=\"lang\"\n                                            langKey=\"FetchRowCount\">FetchRowCount</a></th>\n                    <th class=\"td_lable\" align=\"left\" style=\"min-width:40px\"><span class=\"lang\" langKey=\"FetchRowHisto\">FetchRowHisto</span> <br/>[\n                        <a id=\"th-fetchRowCountHistogram[0]\" class=\"langTitle\" langKey=\"fetch0\"\n                           title=\"count of '0 FetchRow'\">-</a>\n                        <a id=\"th-fetchRowCountHistogram[1]\" class=\"langTitle\" langKey=\"fetch9\"\n                           title=\"count of '1-9 FetchRow'\">-</a>\n                        <a id=\"th-fetchRowCountHistogram[2]\" class=\"langTitle\" langKey=\"fetch99\"\n                           title=\"count of '10-99 FetchRow'\">-</a>\n                        <a id=\"th-fetchRowCountHistogram[3]\" class=\"langTitle\" langKey=\"fetch999\"\n                           title=\"count of '100-999 FetchRow'\">-</a>\n                        <a id=\"th-fetchRowCountHistogram[4]\" class=\"langTitle\" langKey=\"fetch9999\"\n                           title=\"count of '1000-9999 FetchRow'\">-</a>\n                        <a id=\"th-fetchRowCountHistogram[5]\" class=\"langTitle\" langKey=\"fetch99999\"\n                           title=\"count of '> 9999 FetchRow'\">-</a> ]\n                    </th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n\n            <h3 class=\"lang\" langKey=\"FunctionStat\">Function Stat</h3>\n            <table id=\"dataTable2\" style=\"background-color: #fff\"\n                   class=\"table table-bordered responsive-utilities\">\n                <thead>\n                <tr>\n                    <th class=\"td_lable\">Function Name</th>\n                    <th class=\"td_lable\"><a id=\"th-invokeCount\"\n                                            href=\"javascript:void(0);\">InvokeCount</a></th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n\n            <h3 class=\"lang\" langKey=\"SQLStatWhiteList\">SQL Stat - White List</h3>\n            <table id=\"dataTable3\" style=\"background-color: #fff\"\n                   class=\"table table-bordered responsive-utilities\">\n                <thead>\n                <tr>\n                    <th class=\"td_lable\" style=\"width: 12px;\"><span id=\"WhiteListNumber\" class=\"lang\"\n                                                                    langKey=\"TableNumber\">TableNumber</span></th>\n                    <th class=\"td_lable\">SQL</th>\n                    <th class=\"td_lable\"><span id=\"WhiteListSample\" class=\"lang\" langKey=\"Sample\">Sample</span></th>\n                    <th class=\"td_lable\" style=\"width: 30px;\"><span id=\"WhiteListExecuteCount\" class=\"lang\"\n                                                                    langKey=\"ExecuteCount\">ExecuteCount</span></th>\n                    <th class=\"td_lable\" style=\"width: 40px;\"><span id=\"WhiteListExecuteErrorCount\" class=\"lang\"\n                                                                    langKey=\"ExecuteErrorCount\">ExecuteErrorCount</span>\n                    </th>\n                    <th class=\"td_lable\" style=\"width: 30px;\"><span id=\"WhiteListFetchRowCount\" class=\"lang\"\n                                                                    langKey=\"FetchRowCount\">FetchRowCount</span></th>\n                    <th class=\"td_lable\" style=\"width: 30px;\"><span id=\"WhiteListUpdateCount\" class=\"lang\"\n                                                                    langKey=\"SQLUpdateCount\">UpdateCount</span></th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n\n            <h3 class=\"lang\" langKey=\"SQLStatBlackList\">SQL Stat - Black List</h3>\n            <table id=\"dataTable4\" style=\"background-color: #fff\"\n                   class=\"table table-bordered responsive-utilities\">\n                <thead>\n                <tr>\n                    <th class=\"td_lable\" style=\"width: 50px;\"><span id=\"BlackListNumber\" class=\"lang\"\n                                                                    langKey=\"TableNumber\">TableNumber</span></th>\n                    <th class=\"td_lable\">SQL</th>\n                    <th class=\"td_lable\"><span id=\"BlackListSample\" class=\"lang\" langKey=\"Sample\">Sample</span></th>\n                    <th class=\"td_lable\" style=\"width: 50px;\"><span id=\"violationMessage\" class=\"lang\"\n                                                                    langKey=\"violationMessage\">violationMessage</span>\n                    </th>\n                    <th class=\"td_lable\" style=\"width: 50px;\"><span id=\"BlackListExecuteCount\" class=\"lang\"\n                                                                    langKey=\"ExecuteCount\">ExecuteCount</span></th>\n                    <th class=\"td_lable\" style=\"width: 50px;\"><span id=\"BlackListFetchRowCount\" class=\"lang\"\n                                                                    langKey=\"FetchRowCount\">FetchRowCount</span></th>\n                    <th class=\"td_lable\" style=\"width: 50px;\"><span id=\"BlackListUpdateCount\" class=\"lang\"\n                                                                    langKey=\"SQLUpdateCount\">UpdateCount</span></th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.datasource\");\n    druid.wall = function () {\n        return {\n            init: function () {\n                $(\"#dataTable1 th a\").click(function (obj) {\n                    druid.common.setOrderBy(obj.target.id.substring(3))\n                })\n                $(\"#dataTable2 th a\").click(function (obj) {\n                    druid.common.setOrderBy(obj.target.id.substring(3))\n                })\n                druid.common.buildHead(3);\n\n                druid.common.ajaxuri = 'wall.json?';\n                druid.common.handleCallback = druid.wall.handleAjaxResult;\n                druid.common.ajaxRequestForBasicInfo();\n                setInterval(\"druid.common.ajaxRequestForBasicInfo();\", 10000);\n            },\n            switchSuspendRefresh: function () {\n                druid.wall.disableAutoRefresh = !druid.wall.disableAutoRefresh;\n                if (druid.wall.disableAutoRefresh) {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-warning\").removeClass(\"btn-primary\");\n                } else {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-primary\").removeClass(\"btn-warning\");\n                }\n            },\n            disableAutoRefresh: false,\n            refreshSeconds: 10,\n            suspendedSeconds: 0,\n            handleAjaxResult: function (data) {\n                $(\"#CheckCount\").text(replace(data.Content.checkCount))\n                $(\"#HardCheckCount\").text(replace(data.Content.hardCheckCount))\n                $(\"#ViolationCount\").text(replace(data.Content.violationCount))\n                $(\"#BlackListHitCount\")\n                    .text(replace(data.Content.blackListHitCount))\n                $(\"#BlackListSize\").text(replace(data.Content.blackListSize))\n                $(\"#WhiteListHitCount\")\n                    .text(replace(data.Content.whiteListHitCount))\n                $(\"#WhiteListSize\").text(replace(data.Content.whiteListSize))\n                $(\"#SyntaxErrrorCount\")\n                    .text(replace(data.Content.syntaxErrrorCount))\n\n                var html = \"\";\n                var tables = data.Content.tables;\n                if (tables) {\n                    for (var i = 0; i < tables.length; i++) {\n                        var table = tables[i];\n                        html += \"<tr>\";\n                        html += \"<td>\" + (i + 1) + \"</td>\";\n                        html += \"<td>\" + table.name + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.selectCount) + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.selectIntoCount) + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.insertCount) + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.updateCount) + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.deleteCount) + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.truncateCount) + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.createCount) + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.alterCount)\n                            + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.dropCount)\n                            + \"</td>\";\n                        html += \"<td>\"\n                            + replace(table.replaceCount) + \"</td>\";\n                        html += \"<td>\" + replace(table.deleteDataCount) + \"</td>\";\n                        if (table.deleteDataCountHistogram === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + '[' + table.deleteDataCountHistogram + ']' + \"</td>\";\n                        }\n                        html += \"<td>\" + replace(table.updateDataCount) + \"</td>\";\n                        if (table.updateDataCountHistogram === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + '[' + table.updateDataCountHistogram + ']' + \"</td>\";\n                        }\n                        html += \"<td>\" + replace(table.fetchRowCount) + \"</td>\";\n                        if (table.fetchRowCountHistogram === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + '[' + table.fetchRowCountHistogram + ']' + \"</td>\";\n                        }\n\n                        html += \"</tr>\";\n                    }\n                    $(\"#dataTable1 tbody\").html(html);\n                }\n\n                html = \"\";\n                var functions = data.Content.functions;\n                if (functions) {\n                    for (var i = 0; i < functions.length; i++) {\n                        var fun = functions[i];\n                        html += \"<tr>\";\n                        html += \"<td>\" + fun.name + \"</td>\";\n                        html += \"<td>\" + fun.invokeCount + \"</td>\";\n                        html += \"</tr>\";\n                    }\n                    $(\"#dataTable2 tbody\").html(html);\n                }\n\n                html = \"\";\n                var whiteList = data.Content.whiteList;\n                if (whiteList) {\n                    for (var i = 0; i < whiteList.length; ++i) {\n                        var white = whiteList[i];\n                        if (white.sql != null) {\n                            white.sql = white.sql.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n                        }\n\n                        html += \"<tr>\";\n                        html += \"<td>\" + (i + 1) + \"</td>\";\n                        html += '<td style=\"word-break:break-all\">' + white.sql + \"</td>\";\n\n                        if (white.sample === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += '<td style=\"word-break:break-all\">'\n                                + white.sample + \"</td>\";\n                        }\n\n                        if (white.executeCount === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + white.executeCount + \"</td>\";\n                        }\n\n                        if (white.executeErrorCount === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + white.executeErrorCount + \"</td>\";\n                        }\n\n                        if (white.fetchRowCount === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + white.fetchRowCount + \"</td>\";\n                        }\n\n                        if (white.updateCount === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + white.updateCount + \"</td>\";\n                        }\n                        html += \"</tr>\";\n                    }\n                    $(\"#dataTable3 tbody\").html(html);\n                }\n\n                html = \"\";\n                var blackList = data.Content.blackList;\n                if (blackList) {\n                    for (var i = 0; i < blackList.length; ++i) {\n                        var black = blackList[i];\n                        if (black.sql != null) {\n                            black.sql = black.sql.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n                        }\n\n                        html += \"<tr>\";\n                        html += \"<td>\" + (i + 1) + \"</td>\";\n                        html += '<td style=\"word-break:break-all\">' + black.sql + \"</td>\";\n\n                        if (black.sample === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += '<td style=\"word-break:break-all\">'\n                                + black.sample + \"</td>\";\n                        }\n\n                        if (black.violationMessage === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + black.violationMessage + \"</td>\";\n                        }\n\n                        if (black.executeCount === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + black.executeCount + \"</td>\";\n                        }\n\n                        if (black.fetchRowCount === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + black.fetchRowCount + \"</td>\";\n                        }\n\n                        if (black.updateCount === undefined) {\n                            html += \"<td></td>\";\n                        } else {\n                            html += \"<td>\" + black.updateCount + \"</td>\";\n                        }\n                    }\n                    $(\"#dataTable4 tbody\").html(html);\n                }\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.wall.init();\n    });\n    window.initPage = druid.common.ajaxRequestForBasicInfo;\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/webapp.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid WebApp Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script src=\"js/doT.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"js/bootstrap.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                WebAppStat List\n                <a href=\"webapp.json\" target=\"_blank\">View JSON API</a>\n            </h3>\n        </div>\n    </div>\n</div>\n<script type=\"text/template\" id=\"webapp-template\">\n    {{~ it.content :contextNow:i  }}\n    <ul class=\"nav nav-tabs\" style=\"margin-bottom:3px;\" id=\"datasourceTab{{=i}}\">\n        <li class=\"active\">\n            <a href=\"webapp.html#dstab/{{=contextNow.ContextPath}}\">WebApp-{{=contextNow.ContextPath}}</a>\n        </li>\n    </ul>\n    <div class=\"tab-content\">\n        <div class=\"tab-pane active\" id=\"dstab/{{=contextNow.ContextPath}}\">\n            <table class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tbody>\n                <tr>\n                {{ var i=0;for(var key in contextNow ) { }}\n                {{? (i++)%4 == 0 }}\n                </tr><tr>\n                {{?}}\n                    <td valign=\"top\" class=\"td_lable lang\" style=\"min-width:80px\" langKey=\"{{=key}}\">{{=key}}</td>\n                    <td style=\"min-width:80px\">{{=contextNow[key]}}</td>\n                {{ } }}\n                </tr>\n                </tbody>\n            </table>\n        </div>\n    </div>\n    {{~ }}\n</script>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.datasource\");\n    druid.datasource = function () {\n\n        return {\n            init: function () {\n                druid.common.buildHead(4);\n                this.ajaxRequestForBasicInfo();\n            },\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: \"webapp.json\",\n                    success: function (data) {\n                        $(\".nav-tabs,.tab-content\").remove();\n                        var datasourceList = data.Content;\n\n                        var tmpl = $('#webapp-template').html();\n                        var contents = {'content': datasourceList};\n                        var doTtmpl = doT.template(tmpl);\n                        var contentHtml = doTtmpl(contents);\n\n                        $(\".span12 h3\").after(contentHtml);\n\n                        $('#datasourceTab a').click(function (e) {\n                            e.preventDefault();\n                            $(this).tab('show');\n                        });\n                        druid.lang.trigger();\n                    },\n                    dataType: \"json\"\n                });\n            }\n\n\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.datasource.init();\n    });\n    window.initPage = druid.datasource.ajaxRequestForBasicInfo;\n        \n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/websession-detail.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Web Session Stat</title>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                Web Session View\n                <a id=\"viewJsonApi\" target=\"_blank\">View JSON API</a>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"SESSIONID\" width='130'> SESSIONID</td>\n                    <td id=\"SESSIONID\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"UserAgent\"> UserAgent</td>\n                    <td id=\"UserAgent\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"Principal\"> Principal</td>\n                    <td id=\"Principal\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"CreateTime\"> CreateTime</td>\n                    <td id=\"CreateTime\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"LastAccessTime\"> LastAccessTime</td>\n                    <td id=\"LastAccessTime\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RemoteAddress\"> RemoteAddress</td>\n                    <td id=\"RemoteAddress\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RequestCount\"> RequestCount</td>\n                    <td id=\"RequestCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RequestTimeMillisTotal\"> RequestTimeMillisTotal</td>\n                    <td id=\"RequestTimeMillisTotal\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RequestInterval\"> RequestInterval</td>\n                    <td id=\"RequestInterval\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RunningCount\"> RunningCount</td>\n                    <td id=\"RunningCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"ConcurrentMax\"> ConcurrentMax</td>\n                    <td id=\"ConcurrentMax\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcExecuteCount\"> JdbcExecuteCount</td>\n                    <td id=\"JdbcExecuteCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcExecuteTimeMillis\"> JdbcExecuteTimeMillis</td>\n                    <td id=\"JdbcExecuteTimeMillis\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcCommitCount\"> JdbcCommitCount</td>\n                    <td id=\"JdbcCommitCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcRollbackCount\"> JdbcRollbackCount</td>\n                    <td id=\"JdbcRollbackCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcFetchRowCount\"> JdbcFetchRowCount</td>\n                    <td id=\"JdbcFetchRowCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcUpdateCount\"> JdbcUpdateCount</td>\n                    <td id=\"JdbcUpdateCount\"></td>\n                    <td></td>\n                </tr>\n            </table>\n            <div class=\"container\">\n                <a class=\"btn btn-primary\" href=\"javascript:window.close();\">Close</a>\n            </div>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.websessiondetail\");\n    druid.websessiondetail = function () {\n        var sessionId = druid.common.getUrlVar(\"sessionId\");\n        return {\n            init: function () {\n                druid.common.buildHead(6);\n                this.ajaxRequestForBasicInfo();\n                $(\"#viewJsonApi\").attr(\"href\", 'websession-' + sessionId + '.json');\n            },\n\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: 'websession-' + sessionId + '.json',\n                    success: function (data) {\n                        if (data.Content == null)\n                            return;\n                        $(\"#SESSIONID\").text(data.Content.SESSIONID)\n                        if (data.Content.Principal) {\n                            $(\"#Principal\").text(data.Content.Principal)\n                        }\n\n                        $(\"#CreateTime\").text(data.Content.CreateTime)\n                        $(\"#LastAccessTime\").text(data.Content.LastAccessTime)\n                        $(\"#UserAgent\").text(data.Content.UserAgent)\n                        $(\"#RemoteAddress\").text(data.Content.RemoteAddress)\n                        $(\"#RequestCount\").text(data.Content.RequestCount)\n                        $(\"#RequestTimeMillisTotal\").text(data.Content.RequestTimeMillisTotal)\n                        $(\"#RunningCount\").text(data.Content.RunningCount)\n                        $(\"#ConcurrentMax\").text(data.Content.ConcurrentMax)\n                        $(\"#JdbcExecuteCount\").text(data.Content.JdbcExecuteCount)\n                        $(\"#JdbcExecuteTimeMillis\").text(data.Content.JdbcExecuteTimeMillis)\n                        $(\"#JdbcCommitCount\").text(data.Content.JdbcCommitCount)\n                        $(\"#JdbcRollbackCount\").text(data.Content.JdbcRollbackCount)\n                        $(\"#JdbcFetchRowCount\").text(data.Content.JdbcFetchRowCount)\n                        $(\"#JdbcUpdateCount\").text(data.Content.JdbcUpdateCount)\n                        var html = '[';\n                        html += '<a title=\"count of < 1 ms\">' + data.Content.RequestInterval[0] + '</a>';\n                        html += ', <a title=\"count of 1 - 10 ms\">' + data.Content.RequestInterval[1] + '</a>';\n                        html += ', <a title=\"count of 10 - 100 ms\">' + data.Content.RequestInterval[2] + '</a>';\n                        html += ', <a title=\"count of 100 - 1000 ms\">' + data.Content.RequestInterval[3] + '</a>';\n                        html += ', <a title=\"count of 1 - 10 s\">' + data.Content.RequestInterval[4] + '</a>';\n                        html += ', <a title=\"count of 10 - 100 s\">' + data.Content.RequestInterval[5] + '</a>';\n                        html += ', <a title=\"count of 100 - 1000 s\">' + data.Content.RequestInterval[6] + '</a>';\n                        html += ', <a title=\"count of 1000 - 10000 s\">' + data.Content.RequestInterval[7] + '</a>';\n                        html += ', <a title=\"count of > 10000 s\">' + data.Content.RequestInterval[8] + '</a>';\n                        html += ']';\n                        $(\"#RequestInterval\").html(html);\n                    },\n                    dataType: \"json\"\n                });\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.websessiondetail.init();\n    });\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/websession.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Web Session Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                Web Session Stat\n                <a href=\"websession.json\" target=\"_blank\">View JSON API</a>\n                <span class=\"pull-right\" style=\"font-size: 16px; margin-right: 20px;\">\n          \t\t\t\t\t\t<label class=\"lang\" style=\"display: inline; cursor: pointer;\">\n          \t\t\t\t\t\t\t<input type=\"checkbox\" id=\"principalOnlyCheck\" style=\"margin-top: 0px;\">\n          \t\t\t\t\t\t\t<span langkey=\"PrincipalOnly\" class=\"lang\">Principal Only</span>\n          \t\t\t\t\t\t\t<span> | </span>\n          \t\t\t\t\t\t</label>\n          \t\t\t\t\t\t<label langkey=\"RefreshPeriod\" class=\"lang\" style=\"display: inline;\"\n                                       for=\"refreshSecondsSelect\">Refresh Period</label>\n          \t\t\t\t\t\t<select id=\"refreshSecondsSelect\" class=\"refresh-seconds-select btn\" style=\"width:80px;\"\n                                        onchange=\"javascript:druid.websession.refreshSeconds=parseInt(this.options[this.options.selectedIndex].value);\">\n          \t\t\t\t\t\t\t<option value=\"5\">5s</option>\n          \t\t\t\t\t\t\t<option value=\"10\" selected=\"selected\">10s</option>\n          \t\t\t\t\t\t\t<option value=\"20\">20s</option>\n          \t\t\t\t\t\t\t<option value=\"30\">30s</option>\n          \t\t\t\t\t\t\t<option value=\"60\">60s</option>\n          \t\t\t\t\t\t</select>\n          \t\t\t\t\t\t<a id=\"btnSuspendRefresh\" langkey=\"SuspendRefresh\" class=\"btn btn-primary lang\"\n                                   href=\"javascript:druid.websession.switchSuspendRefresh();\">Suspend Refresh</a>\n          \t\t\t\t\t</span>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered table-striped\">\n                <thead>\n                <tr>\n                    <th>N</th>\n                    <th><a id=\"th-SESSIONID\" class=\"lang\" langKey=\"SESSIONID\">SESSIONID</a></th>\n                    <th><a id=\"th-Principal\" class=\"lang\" langKey=\"Principal\">Principal</a></th>\n                    <th><a id=\"th-CreateTime\" class=\"lang\" langKey=\"CreateTime\">CreateTime</a></th>\n                    <th><a id=\"th-LastAccessTime\" class=\"lang\" langKey=\"LastAccessTime\">LastAccessTime</a></th>\n                    <th><a id=\"th-RemoteAddress\" class=\"lang\" langKey=\"RemoteAddress\">RemoteAddress</a></th>\n                    <th><a id=\"th-RequestCount\" class=\"lang\" langKey=\"RequestCount\">RequestCount</a></th>\n                    <th><a id=\"th-RequestTimeMillisTotal\" class=\"lang\" langKey=\"RequestTimeMillisTotal\">RequestTimeMillisTotal</a>\n                    </th>\n                    <th><a id=\"th-RunningCount\" class=\"lang\" langKey=\"RunningCount\">RunningCount</a></th>\n                    <th><a id=\"th-ConcurrentMax\" class=\"lang\" langKey=\"ConcurrentMax\">ConcurrentMax</a></th>\n                    <th><a id=\"th-JdbcExecuteCount\" class=\"lang\" langKey=\"JdbcExecuteCount\">JdbcExecuteCount</a></th>\n                    <th><a id=\"th-JdbcExecuteTimeMillis\" class=\"lang\" langKey=\"JdbcExecuteTimeMillis\">JdbcExecuteTimeMillis</a>\n                    </th>\n                    <th><a id=\"th-JdbcCommitCount\" class=\"lang\" langKey=\"JdbcCommitCount\">JdbcCommitCount</a></th>\n                    <th><a id=\"th-JdbcRollbackCount\" class=\"lang\" langKey=\"JdbcRollbackCount\">JdbcRollbackCount</a></th>\n                    <th><a id=\"th-JdbcFetchRowCount\" class=\"lang\" langKey=\"JdbcFetchRowCount\">JdbcFetchRowCount</a></th>\n                    <th><a id=\"th-JdbcUpdateCount\" class=\"lang\" langKey=\"JdbcUpdateCount\">JdbcUpdateCount</a></th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.websession\");\n    druid.websession = function () {\n        return {\n            init: function () {\n                $(\"#dataTable th a\").click(function (obj) {\n                    druid.common.setOrderBy(obj.target.id.substring(3))\n                })\n                $(\"#principalOnlyCheck\").change(function (obj) {\n                    druid.common.ajaxRequestForBasicInfo();\n                });\n                druid.common.buildHead(6);\n                druid.common.ajaxuri = 'websession.json?';\n                druid.common.handleCallback = druid.websession.handleAjaxResult;\n                druid.websession.controlRefresh();\n            },\n            controlRefresh: function () {\n                var FIVE = 5;\n                if (!druid.websession.refreshSeconds) {\n                    druid.websession.refreshSeconds = FIVE;\n                }\n                if (!druid.websession.suspendedSeconds) {\n                    druid.websession.suspendedSeconds = 0;\n                }\n                druid.websession.suspendedSeconds += FIVE;\n                if (!druid.websession.disableAutoRefresh) {\n                    if (druid.websession.suspendedSeconds >= druid.websession.refreshSeconds) {\n                        druid.websession.suspendedSeconds = 0;\n                        druid.common.ajaxRequestForBasicInfo();\n                    }\n                }\n                setTimeout(druid.websession.controlRefresh, FIVE * 1000);\n            },\n            switchSuspendRefresh: function () {\n                druid.websession.disableAutoRefresh = !druid.websession.disableAutoRefresh;\n                if (druid.websession.disableAutoRefresh) {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-warning\").removeClass(\"btn-primary\");\n                } else {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-primary\").removeClass(\"btn-warning\");\n                }\n            },\n            disableAutoRefresh: false,\n            refreshSeconds: 5,\n            suspendedSeconds: 0,\n\n            handleAjaxResult: function (data) {\n                var statList = data.Content;\n                if (statList == null) return;\n\n                var sqlStatTable = document.getElementById(\"dataTable\");\n                while (sqlStatTable.rows.length > 1) {\n                    sqlStatTable.deleteRow(1);\n                }\n\n                var html = \"\";\n                var principalOnlyChecked = document.getElementById(\"principalOnlyCheck\").checked;\n                for (var i = 0; i < statList.length; i++) {\n                    var stat = statList[i];\n                    if (principalOnlyChecked && !stat.Principal) {\n                        continue;\n                    }\n                    var newRow = sqlStatTable.insertRow(-1);\n                    html += \"<tr>\";\n                    html += \"<td>\" + (i + 1) + \"</td>\";\n                    html += \"<td>\" + '<a target=\"_blank\" href=\"websession-detail.html?sessionId=' + stat.SESSIONID + '\">' + stat.SESSIONID + '</a>';\n                    if (stat.Principal) {\n                        html += \"<td>\" + stat.Principal + \"</td>\";\n                    } else {\n                        html += \"<td></td>\";\n                    }\n                    html += \"<td>\" + replace(stat.CreateTime) + \"</td>\";\n                    html += \"<td>\" + replace(stat.LastAccessTime) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RemoteAddress) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RequestCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RequestTimeMillisTotal) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RunningCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.ConcurrentMax) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcExecuteCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcExecuteTimeMillis) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcCommitCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcRollbackCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcFetchRowCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcUpdateCount) + \"</td>\";\n                    html += \"</tr>\";\n                }\n                $(\"#dataTable tbody\").html(html);\n                druid.common.stripes();\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.websession.init();\n    });\n    window.initPage = druid.common.ajaxRequestForBasicInfo;\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/weburi-detail.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Web URI Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                Web URI View\n                <a id=\"viewJsonApi\" target=\"_blank\">View JSON API</a>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered\" style=\"background-color: #fff\">\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"URI\"> URI</td>\n                    <td id=\"URI\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RequestCount\"> RequestCount</td>\n                    <td id=\"RequestCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RequestTimeMillis\"> RequestTimeMillis</td>\n                    <td id=\"RequestTimeMillis\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"LastAccessTime\"> LastAccessTime</td>\n                    <td id=\"LastAccessTime\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"RunningCount\"> RunningCount</td>\n                    <td id=\"RunningCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"ConcurrentMax\"> ConcurrentMax</td>\n                    <td id=\"ConcurrentMax\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcExecuteCount\"> JdbcExecuteCount</td>\n                    <td id=\"JdbcExecuteCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcExecuteErrorCount\"> JdbcExecuteErrorCount</td>\n                    <td id=\"JdbcExecuteErrorCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcExecutePeak\"> JdbcExecutePeak</td>\n                    <td id=\"JdbcExecutePeak\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcExecuteTimeMillis\"> JdbcExecuteTimeMillis</td>\n                    <td id=\"JdbcExecuteTimeMillis\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcCommitCount\"> JdbcCommitCount</td>\n                    <td id=\"JdbcCommitCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcRollbackCount\"> JdbcRollbackCount</td>\n                    <td id=\"JdbcRollbackCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcFetchRowCount\"> JdbcFetchRowCount</td>\n                    <td id=\"JdbcFetchRowCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcFetchRowPeak\"> JdbcFetchRowPeak</td>\n                    <td id=\"JdbcFetchRowPeak\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcUpdateCount\"> JdbcUpdateCount</td>\n                    <td id=\"JdbcUpdateCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcUpdatePeak\"> JdbcUpdatePeak</td>\n                    <td id=\"JdbcUpdatePeak\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcPoolConnectionOpenCount\"> JdbcPoolConnectionOpenCount</td>\n                    <td id=\"JdbcPoolConnectionOpenCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcPoolConnectionCloseCount\"> JdbcPoolConnectionCloseCount</td>\n                    <td id=\"JdbcPoolConnectionCloseCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcResultSetOpenCount\"> JdbcResultSetOpenCount</td>\n                    <td id=\"JdbcResultSetOpenCount\"></td>\n                    <td></td>\n                </tr>\n                <tr>\n                    <td class=\"td_lable lang\" langKey=\"JdbcResultSetCloseCount\"> JdbcResultSetCloseCount</td>\n                    <td id=\"JdbcResultSetCloseCount\"></td>\n                    <td></td>\n                </tr>\n            </table>\n\n            <h3>Profiles</h3>\n            <table id=\"profileDataTable\" class=\"table table-bordered table-striped responsive-utilities\">\n                <thead>\n                <tr>\n                    <th>N</th>\n                    <th><a id=\"th-Name\">Name</a></th>\n                    <th>ParentName</th>\n                    <th>Type</th>\n                    <th>ExecuteCount</th>\n                    <th>ExecuteTimeMillis</th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n            <div class=\"container\">\n                <a class=\"btn btn-primary\" href=\"javascript:window.close();\">Close</a>\n            </div>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.weburidetail\");\n    druid.weburidetail = function () {\n        var uri = druid.common.getUrlVar(\"uri\");\n        return {\n            init: function () {\n                druid.common.buildHead(5);\n                this.ajaxRequestForBasicInfo();\n                $(\"#viewJsonApi\").attr(\"href\", 'weburi-' + encodeURI(uri) + '.json');\n            },\n\n            ajaxRequestForBasicInfo: function () {\n                $.ajax({\n                    type: 'POST',\n                    url: 'weburi-' + encodeURI(uri) + '.json',\n                    success: function (data) {\n                        if (data.Content == null)\n                            return;\n                        $(\"#URI\").text(data.Content.URI);\n                        $(\"#RequestCount\").text(data.Content.RequestCount);\n                        $(\"#RequestTimeMillis\").text(data.Content.RequestTimeMillis);\n                        $(\"#LastAccessTime\").text(data.Content.LastAccessTime);\n                        $(\"#RunningCount\").text(data.Content.RunningCount);\n                        $(\"#ConcurrentMax\").text(data.Content.ConcurrentMax);\n                        $(\"#JdbcExecuteCount\").text(data.Content.JdbcExecuteCount);\n                        $(\"#JdbcExecuteErrorCount\").text(data.Content.JdbcExecuteErrorCount);\n                        $(\"#JdbcExecutePeak\").text(data.Content.JdbcExecutePeak);\n                        $(\"#JdbcExecuteTimeMillis\").text(data.Content.JdbcExecuteTimeMillis);\n                        $(\"#JdbcCommitCount\").text(data.Content.JdbcCommitCount);\n                        $(\"#JdbcRollbackCount\").text(data.Content.JdbcRollbackCount);\n                        $(\"#JdbcFetchRowCount\").text(data.Content.JdbcFetchRowCount);\n                        $(\"#JdbcFetchRowPeak\").text(data.Content.JdbcFetchRowPeak);\n                        $(\"#JdbcUpdateCount\").text(data.Content.JdbcUpdateCount);\n                        $(\"#JdbcUpdatePeak\").text(data.Content.JdbcUpdatePeak);\n                        $(\"#JdbcPoolConnectionOpenCount\").text(data.Content.JdbcPoolConnectionOpenCount);\n                        $(\"#JdbcPoolConnectionCloseCount\").text(data.Content.JdbcPoolConnectionCloseCount);\n                        $(\"#JdbcResultSetOpenCount\").text(data.Content.JdbcResultSetOpenCount);\n                        $(\"#JdbcResultSetCloseCount\").text(data.Content.JdbcResultSetCloseCount);\n\n                        var profiles = data.Content.Profiles;\n                        if (profiles == null) {\n                            return;\n                        }\n\n                        var profileDataTable = document.getElementById(\"profileDataTable\");\n                        while (profileDataTable.rows.length > 1) {\n                            profileDataTable.deleteRow(1);\n                        }\n\n                        var html = \"\";\n                        for (var i = 0; i < profiles.length; i++) {\n                            var stat = profiles[i];\n                            var newRow = profileDataTable.insertRow(-1);\n                            html += \"<tr>\";\n                            html += \"<td>\" + (i + 1) + \"</td>\";\n                            html += \"<td>\" + stat.Name + \"</td>\";\n                            if (stat.Parent == null) {\n                                html += \"<td> </td>\";\n                            } else {\n                                html += \"<td>\" + stat.Parent + \"</td>\";\n                            }\n\n                            html += \"<td>\" + stat.Type + \"</td>\";\n                            html += \"<td>\" + stat.ExecuteCount + \"</td>\";\n                            html += \"<td>\" + stat.ExecuteTimeMillis + \"</td>\";\n                            html += \"</tr>\";\n                        }\n                        $(\"#profileDataTable tbody\").html(html);\n                        druid.lang.trigger();\n                    },\n                    dataType: \"json\"\n                });\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.weburidetail.init();\n    });\n</script>\n</body>\n</html>\n\n"
  },
  {
    "path": "core/src/main/resources/support/http/resources/weburi.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid Web URI Stat</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <link href=\"css/style.css\" type=\"text/css\" rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n    <script src=\"js/lang.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n    <script src=\"js/common.js\" type=\"text/javascript\" charset=\"utf8\"></script>\n</head>\n<body>\n\n<div class=\"container-fluid\">\n    <div class=\"row-fluid\">\n        <div class=\"span12\">\n            <h3>\n                Web URI Stat\n                <a href=\"weburi.json\" target=\"_blank\">View JSON API</a>\n                <span class=\"pull-right\" style=\"font-size: 16px; margin-right: 20px;\">\n          \t\t\t\t\t\t<label langkey=\"RefreshPeriod\" class=\"lang\" style=\"display: inline;\"\n                                       for=\"refreshSecondsSelect\">Refresh Period</label>\n          \t\t\t\t\t\t<select id=\"refreshSecondsSelect\" class=\"refresh-seconds-select btn\" style=\"width:80px;\"\n                                        onchange=\"javascript:druid.weburi.refreshSeconds=parseInt(this.options[this.options.selectedIndex].value);\">\n          \t\t\t\t\t\t\t<option value=\"5\" selected=\"selected\">5s</option>\n          \t\t\t\t\t\t\t<option value=\"10\">10s</option>\n          \t\t\t\t\t\t\t<option value=\"20\">20s</option>\n          \t\t\t\t\t\t\t<option value=\"30\">30s</option>\n          \t\t\t\t\t\t\t<option value=\"60\">60s</option>\n          \t\t\t\t\t\t</select>\n          \t\t\t\t\t\t<a id=\"btnSuspendRefresh\" langkey=\"SuspendRefresh\" class=\"btn btn-primary lang\"\n                                   href=\"javascript:druid.weburi.switchSuspendRefresh();\">Suspend Refresh</a>\n          \t\t\t\t\t</span>\n            </h3>\n            <table id=\"dataTable\" class=\"table table-bordered table-striped responsive-utilities\">\n                <thead>\n                <tr>\n                    <th width=\"12\">N</th>\n\n                    <th style=\"min-width:140px;max-width:400px\"><a id=\"th-URI\" class=\"lang\" langKey=\"URI\">URI</a></th>\n                    <th width=\"48\"><a id=\"th-RequestCount\" class=\"lang\" langKey=\"RequestCount\">RequestCount</a></th>\n                    <th width=\"100\"><a id=\"th-RequestTimeMillis\" class=\"lang\" langKey=\"RequestTimeMillis\">RequestTimeMillis</a></th>\n                    <th width=\"100\"><a id=\"th-RequestTimeMillisMax\" class=\"lang\"\n                           langKey=\"RequestTimeMillisMax\">RequestTimeMillisMax</a></th>\n                    <th width=\"48\"><a id=\"th-RunningCount\" class=\"lang\" langKey=\"RunningCount\">RunningCount</a></th>\n                    <th width=\"48\"><a id=\"th-ConcurrentMax\" class=\"lang\" langKey=\"ConcurrentMax\">ConcurrentMax</a></th>\n                    <th width=\"64\"><a id=\"th-JdbcExecuteCount\" class=\"lang\" langKey=\"JdbcExecuteCount\">JdbcExecuteCount</a></th>\n                    <th width=\"64\"><a id=\"th-JdbcExecuteErrorCount\" class=\"lang\" langKey=\"JdbcExecuteErrorCount\">JdbcExecuteErrorCount</a>\n                    </th>\n                    <th width=\"80\"><a id=\"th-JdbcExecuteTimeMillis\" class=\"lang\" langKey=\"JdbcExecuteTimeMillis\">JdbcExecuteTimeMillis</a>\n                    </th>\n                    <th width=\"60\"><a id=\"th-JdbcCommitCount\" class=\"lang\" langKey=\"JdbcCommitCount\">JdbcCommitCount</a></th>\n                    <th width=\"60\"><a id=\"th-JdbcRollbackCount\" class=\"lang\" langKey=\"JdbcRollbackCount\">JdbcRollbackCount</a></th>\n                    <th width=\"48\"><a id=\"th-JdbcFetchRowCount\" class=\"lang\" langKey=\"JdbcFetchRowCount\">JdbcFetchRowCount</a></th>\n                    <th width=\"48\"><a id=\"th-JdbcUpdateCount\" class=\"lang\" langKey=\"JdbcUpdateCount\">JdbcUpdateCount</a></th>\n                    <th align=\"left\" width=\"100\"><span class=\"lang\" langKey=\"Histogram\">Histogram</span> <br/>[\n                        <a id=\"th-Histogram[0]\" class=\"langTitle\" langKey=\"count1ms\" title=\"count of '0-1 ms'\">-</a>\n                        <a id=\"th-Histogram[1]\" class=\"langTitle\" langKey=\"count10ms\" title=\"count of '1-10 ms'\">-</a>\n                        <a id=\"th-Histogram[2]\" class=\"langTitle\" langKey=\"count100ms\"\n                           title=\"count of '10-100 ms'\">-</a>\n                        <a id=\"th-Histogram[3]\" class=\"langTitle\" langKey=\"count1s\" title=\"count of '100ms-1 s'\">-</a>\n                        <a id=\"th-Histogram[4]\" class=\"langTitle\" langKey=\"count10s\" title=\"count of '1-10 s'\">-</a>\n                        <a id=\"th-Histogram[5]\" class=\"langTitle\" langKey=\"count100s\" title=\"count of '10-100 s'\">-</a>\n                        <a id=\"th-Histogram[6]\" class=\"langTitle\" langKey=\"count1000s\"\n                           title=\"count of '100-1000 s'\">-</a>\n                        <a id=\"th-Histogram[7]\" class=\"langTitle\" langKey=\"countBg1000s\"\n                           title=\"count of '> 1000 s'\">-</a> ]\n                    </th>\n                </tr>\n                </thead>\n                <tbody></tbody>\n            </table>\n        </div>\n    </div>\n</div>\n<script type=\"text/javascript\">\n    $.namespace(\"druid.weburi\");\n    druid.weburi = function () {\n        return {\n            init: function () {\n                $(\"#dataTable th a\").click(function (obj) {\n                    druid.common.setOrderBy(obj.target.id.substring(3))\n                })\n                druid.common.buildHead(5);\n                druid.common.ajaxuri = 'weburi.json?';\n                druid.common.handleCallback = druid.weburi.handleAjaxResult;\n                druid.common.setOrderBy(\"URI\");\n                druid.weburi.controlRefresh();\n            },\n            controlRefresh: function () {\n                var FIVE = 5;\n                if (!druid.weburi.refreshSeconds) {\n                    druid.weburi.refreshSeconds = FIVE;\n                }\n                if (!druid.weburi.suspendedSeconds) {\n                    druid.weburi.suspendedSeconds = 0;\n                }\n                druid.weburi.suspendedSeconds += FIVE;\n                if (!druid.weburi.disableAutoRefresh) {\n                    if (druid.weburi.suspendedSeconds >= druid.weburi.refreshSeconds) {\n                        druid.weburi.suspendedSeconds = 0;\n                        druid.common.ajaxRequestForBasicInfo();\n                    }\n                }\n                setTimeout(druid.weburi.controlRefresh, FIVE * 1000);\n            },\n            switchSuspendRefresh: function () {\n                druid.weburi.disableAutoRefresh = !druid.weburi.disableAutoRefresh;\n                if (druid.weburi.disableAutoRefresh) {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-warning\").removeClass(\"btn-primary\");\n                } else {\n                    $(\"#btnSuspendRefresh\").addClass(\"btn-primary\").removeClass(\"btn-warning\");\n                }\n            },\n            disableAutoRefresh: false,\n            refreshSeconds: 5,\n            suspendedSeconds: 0,\n\n            handleAjaxResult: function (data) {\n                var statList = data.Content;\n                var sqlStatTable = document.getElementById(\"dataTable\");\n                while (sqlStatTable.rows.length > 1) {\n                    sqlStatTable.deleteRow(1);\n                }\n                if (statList == null) return;\n                var html = \"\";\n                for (var i = 0; i < statList.length; i++) {\n                    var stat = statList[i];\n                    var newRow = sqlStatTable.insertRow(-1);\n                    html += \"<tr>\";\n                    html += \"<td>\" + (i + 1) + \"</td>\";\n                    html += \"<td>\" + '<a target=\"_blank\" href=\"weburi-detail.html?uri=' + encodeURI(stat.URI) + '\">' + druid.common.subSqlString(stat.URI, 64) + '</a>' + \"</td>\";\n                    html += \"<td>\" + replace(stat.RequestCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RequestTimeMillis) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RequestTimeMillisMax) + \"</td>\";\n                    html += \"<td>\" + replace(stat.RunningCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.ConcurrentMax) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcExecuteCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcExecuteErrorCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcExecuteTimeMillis) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcCommitCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcRollbackCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcFetchRowCount) + \"</td>\";\n                    html += \"<td>\" + replace(stat.JdbcUpdateCount) + \"</td>\";\n                    html += \"<td>\" + '[' + stat.Histogram + ']' + \"</td>\";\n                    html += \"</tr>\";\n                }\n                $(\"#dataTable tbody\").html(html);\n                druid.common.stripes();\n            }\n        }\n    }();\n\n    $(document).ready(function () {\n        druid.weburi.init();\n    });\n    window.initPage = druid.common.ajaxRequestForBasicInfo;\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/basic.sql",
    "content": "create table druid_domain\n(\n    id     bigint(20) AUTO_INCREMENT NOT NULL,\n    domain varchar(45) NOT NULL,\n    PRIMARY KEY (id),\n    UNIQUE INDEX (domain)\n);\n\ninsert into druid_domain (domain)\nvalues ('default');\n\ncreate table druid_app\n(\n    id     bigint(20) AUTO_INCREMENT NOT NULL,\n    domain varchar(45) NOT NULL,\n    app    varchar(45) NOT NULL,\n    PRIMARY KEY (id),\n    UNIQUE (domain, app)\n);\n\ninsert into druid_app (domain, app)\nvalues ('default', 'default');\n\ncreate table druid_cluster\n(\n    id      bigint(20) AUTO_INCREMENT NOT NULL,\n    domain  varchar(45) NOT NULL,\n    app     varchar(45) NOT NULL,\n    cluster varchar(45) NOT NULL,\n    PRIMARY KEY (id),\n    UNIQUE (domain, app, cluster)\n);\n\ninsert into druid_cluster (domain, app, cluster)\nvalues ('default', 'default', 'default');\n\ncreate table druid_inst\n(\n    id             bigint(20) AUTO_INCREMENT NOT NULL,\n    app            varchar(45)  NOT NULL,\n    domain         varchar(45)  NOT NULL,\n    cluster        varchar(45)  NOT NULL,\n    host           varchar(128) NOT NULL,\n    ip             varchar(32)  NOT NULL,\n    lastActiveTime datetime     NOT NULL,\n    lastPID        bigint(20) NOT NULL,\n    PRIMARY KEY (id),\n    UNIQUE (domain, app, cluster, host)\n);"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/const.sql",
    "content": "CREATE TABLE druid_const\n(\n    id     bigint(20) AUTO_INCREMENT NOT NULL,\n    domain varchar(45) NOT NULL,\n    app    varchar(45) NOT NULL,\n    type   varchar(45) NOT NULL,\n    hash   bigint(20) NOT NULL,\n    value  text,\n    PRIMARY KEY (id),\n    UNIQUE (domain, app, type, hash)\n)"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/datasource.sql",
    "content": "CREATE TABLE druid_datasource\n(\n    id                        bigint(20) AUTO_INCREMENT NOT NULL,\n    domain                    varchar(45) NOT NULL,\n    app                       varchar(45) NOT NULL,\n    cluster                   varchar(45) NOT NULL,\n    host                      varchar(128),\n    pid                       int(10) NOT NULL,\n    collectTime               datetime    NOT NULL,\n    name                      varchar(256),\n    dbType                    varchar(256),\n    driverClassName           varchar(256),\n    activeCount               int(10),\n    activePeak                int(10),\n    activePeakTime            bigint(20),\n    poolingCount              int(10),\n    poolingPeak               int(10),\n    poolingPeakTime           bigint(20),\n    connectCount              bigint(20),\n    closeCount                bigint(20),\n    waitThreadCount           bigint(20),\n    notEmptyWaitCount         bigint(20),\n    notEmptyWaitNanos         bigint(20),\n    logicConnectErrorCount    bigint(20),\n    physicalConnectCount      bigint(20),\n    physicalCloseCount        bigint(20),\n    physicalConnectErrorCount bigint(20),\n    executeCount              bigint(20),\n    errorCount                bigint(20),\n    commitCount               bigint(20),\n    rollbackCount             bigint(20),\n    pstmtCacheHitCount        bigint(20),\n    pstmtCacheMissCount       bigint(20),\n    startTransactionCount     bigint(20),\n    txn_0_1                   bigint(20),\n    txn_1_10                  bigint(20),\n    txn_10_100                bigint(20),\n    txn_100_1000              bigint(20),\n    txn_1000_10000            bigint(20),\n    txn_10000_100000          bigint(20),\n    txn_more                  bigint(20),\n    clobOpenCount             bigint(20),\n    blobOpenCount             bigint(20),\n    sqlSkipCount              bigint(20),\n    PRIMARY KEY (id)\n);\n\nCREATE INDEX druid_datasource_index ON druid_datasource (collectTime, domain, app);"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/springmethod.sql",
    "content": "CREATE TABLE druid_springmethod\n(\n    id                           bigint(20) AUTO_INCREMENT NOT NULL,\n    domain                       varchar(45) NOT NULL,\n    app                          varchar(45) NOT NULL,\n    cluster                      varchar(45) NOT NULL,\n    host                         varchar(128),\n    pid                          int(10) NOT NULL,\n    collectTime                  datetime    NOT NULL,\n    className                    varchar(256),\n    signature                    varchar(256),\n    runningCount                 int(10),\n    concurrentMax                int(10),\n    executeCount                 bigint(20),\n    executeErrorCount            bigint(20),\n    executeTimeNano              bigint(20),\n    jdbcFetchRowCount            bigint(20),\n    jdbcUpdateCount              bigint(20),\n    jdbcExecuteCount             bigint(20),\n    jdbcExecuteErrorCount        bigint(20),\n    jdbcExecuteTimeNano          bigint(20),\n    jdbcCommitCount              bigint(20),\n    jdbcRollbackCount            bigint(20),\n    jdbcPoolConnectionOpenCount  bigint(20),\n    jdbcPoolConnectionCloseCount bigint(20),\n    jdbcResultSetOpenCount       bigint(20),\n    jdbcResultSetCloseCount      bigint(20),\n    lastErrorClass               varchar(256),\n    lastErrorMessage             varchar(256),\n    lastErrorStackTrace          varchar(256),\n    lastErrorTimeMillis          bigint(20),\n    h1                           bigint(20),\n    h10                          bigint(20),\n    h100                         bigint(20),\n    h1000                        bigint(20),\n    h10000                       int(10),\n    h100000                      int(10),\n    h1000000                     int(10),\n    hmore                        int(10),\n    PRIMARY KEY (id)\n);\n\nCREATE INDEX druid_springmethod_index ON druid_springmethod (collectTime, domain, app);"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/sql.sql",
    "content": "CREATE TABLE druid_sql\n(\n    id                   bigint(20) AUTO_INCREMENT NOT NULL,\n    domain               varchar(45) NOT NULL,\n    app                  varchar(45) NOT NULL,\n    cluster              varchar(45) NOT NULL,\n    host                 varchar(128),\n    pid                  int(10) NOT NULL,\n    collectTime          datetime    NOT NULL,\n    sqlHash              bigint(20),\n    dataSource           varchar(256),\n    lastStartTime        bigint(20),\n    batchTotal           bigint(20),\n    batchToMax           int(10),\n    execSuccessCount     bigint(20),\n    execNanoTotal        bigint(20),\n    execNanoMax          bigint(20),\n    running              int(10),\n    concurrentMax        int(10),\n    rsHoldTime           bigint(20),\n    execRsHoldTime       bigint(20),\n    name                 varchar(256),\n    file                 varchar(256),\n    dbType               varchar(256),\n    execNanoMaxOccurTime bigint(20),\n    errorCount           bigint(20),\n    errorLastMsg         varchar(256),\n    errorLastClass       varchar(256),\n    errorLastStackTrace  varchar(256),\n    errorLastTime        bigint(20),\n    updateCount          bigint(20),\n    updateCountMax       bigint(20),\n    fetchRowCount        bigint(20),\n    fetchRowCountMax     bigint(20),\n    inTxnCount           bigint(20),\n    lastSlowParameters   varchar(256),\n    clobOpenCount        bigint(20),\n    blobOpenCount        bigint(20),\n    readStringLength     bigint(20),\n    readBytesLength      bigint(20),\n    inputStreamOpenCount bigint(20),\n    readerOpenCount      bigint(20),\n    h1                   bigint(20),\n    h10                  bigint(20),\n    h100                 int(10),\n    h1000                int(10),\n    h10000               int(10),\n    h100000              int(10),\n    h1000000             int(10),\n    hmore                int(10),\n    eh1                  bigint(20),\n    eh10                 bigint(20),\n    eh100                int(10),\n    eh1000               int(10),\n    eh10000              int(10),\n    eh100000             int(10),\n    eh1000000            int(10),\n    ehmore               int(10),\n    f1                   bigint(20),\n    f10                  bigint(20),\n    f100                 bigint(20),\n    f1000                int(10),\n    f10000               int(10),\n    fmore                int(10),\n    u1                   bigint(20),\n    u10                  bigint(20),\n    u100                 bigint(20),\n    u1000                int(10),\n    u10000               int(10),\n    umore                int(10),\n    PRIMARY KEY (id)\n);\n\nCREATE INDEX druid_sql_index ON druid_sql (collectTime, domain, app);"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/wall.sql",
    "content": "CREATE TABLE druid_wall\n(\n    id                      bigint(20) NOT NULL AUTO_INCREMENT,\n    domain                  varchar(45) NOT NULL,\n    app                     varchar(45) NOT NULL,\n    cluster                 varchar(45) NOT NULL,\n    host                    varchar(128),\n    pid                     int(10) NOT NULL,\n    collectTime             datetime    NOT NULL,\n    name                    varchar(256),\n    checkCount              bigint(20),\n    hardCheckCount          bigint(20),\n    violationCount          bigint(20),\n    whiteListHitCount       bigint(20),\n    blackListHitCount       bigint(20),\n    syntaxErrorCount        bigint(20),\n    violationEffectRowCount bigint(20),\n    PRIMARY KEY (id)\n);\nCREATE INDEX druid_wall_index ON druid_wall (collectTime, domain, app);\n\nCREATE TABLE druid_wall_sql\n(\n    id               bigint(20) NOT NULL AUTO_INCREMENT,\n    domain           varchar(45) NOT NULL,\n    app              varchar(45) NOT NULL,\n    cluster          varchar(45) NOT NULL,\n    host             varchar(128),\n    pid              int(10) NOT NULL,\n    collectTime      datetime    NOT NULL,\n    sqlHash          bigint(20),\n    sqlSHash         bigint(20),\n    sqlSampleHash    bigint(20),\n    executeCount     bigint(20),\n    fetchRowCount    bigint(20),\n    updateCount      bigint(20),\n    syntaxError      int(1),\n    violationMessage varchar(256),\n    PRIMARY KEY (id)\n);\nCREATE INDEX druid_wall_sql_index ON druid_wall_sql (collectTime, domain, app);\n\nCREATE TABLE druid_wall_table\n(\n    id              bigint(20) NOT NULL AUTO_INCREMENT,\n    domain          varchar(45) NOT NULL,\n    app             varchar(45) NOT NULL,\n    cluster         varchar(45) NOT NULL,\n    host            varchar(128),\n    pid             int(10) NOT NULL,\n    collectTime     datetime    NOT NULL,\n    name            varchar(256),\n    selectCount     bigint(20),\n    selectIntoCount bigint(20),\n    insertCount     bigint(20),\n    updateCount     bigint(20),\n    deleteCount     bigint(20),\n    truncateCount   bigint(20),\n    createCount     bigint(20),\n    alterCount      bigint(20),\n    dropCount       bigint(20),\n    replaceCount    bigint(20),\n    deleteDataCount bigint(20),\n    updateDataCount bigint(20),\n    insertDataCount bigint(20),\n    fetchRowCount   bigint(20),\n    PRIMARY KEY (id)\n);\nCREATE INDEX druid_wall_table_index ON druid_wall_table (collectTime, domain, app);\n\nCREATE TABLE druid_wall_function\n(\n    id          bigint(20) NOT NULL AUTO_INCREMENT,\n    domain      varchar(45) NOT NULL,\n    app         varchar(45) NOT NULL,\n    cluster     varchar(45) NOT NULL,\n    host        varchar(128),\n    pid         int(10) NOT NULL,\n    collectTime datetime    NOT NULL,\n    name        varchar(256),\n    invokeCount bigint(20),\n    PRIMARY KEY (id)\n);\nCREATE INDEX druid_wall_function_index ON druid_wall_function (collectTime, domain, app);"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/webapp.sql",
    "content": "CREATE TABLE druid_webapp\n(\n    id                      bigint(20) AUTO_INCREMENT NOT NULL,\n    domain                  varchar(45) NOT NULL,\n    app                     varchar(45) NOT NULL,\n    cluster                 varchar(45) NOT NULL,\n    host                    varchar(128),\n    pid                     int(10) NOT NULL,\n    collectTime             datetime    NOT NULL,\n    contextPath             varchar(256),\n    runningCount            int(10),\n    concurrentMax           int(10),\n    requestCount            bigint(20),\n    sessionCount            bigint(20),\n    jdbcFetchRowCount       bigint(20),\n    jdbcUpdateCount         bigint(20),\n    jdbcExecuteCount        bigint(20),\n    jdbcExecuteTimeNano     bigint(20),\n    jdbcCommitCount         bigint(20),\n    jdbcRollbackCount       bigint(20),\n    osMacOSXCount           bigint(20),\n    osWindowsCount          bigint(20),\n    osLinuxCount            bigint(20),\n    osSymbianCount          bigint(20),\n    osFreeBSDCount          bigint(20),\n    osOpenBSDCount          bigint(20),\n    osAndroidCount          bigint(20),\n    osWindows98Count        bigint(20),\n    osWindowsXPCount        bigint(20),\n    osWindows2000Count      bigint(20),\n    osWindowsVistaCount     bigint(20),\n    osWindows7Count         bigint(20),\n    osWindows8Count         bigint(20),\n    osAndroid15Count        bigint(20),\n    osAndroid16Count        bigint(20),\n    osAndroid20Count        bigint(20),\n    osAndroid21Count        bigint(20),\n    osAndroid22Count        bigint(20),\n    osAndroid23Count        bigint(20),\n    osAndroid30Count        bigint(20),\n    osAndroid31Count        bigint(20),\n    osAndroid32Count        bigint(20),\n    osAndroid40Count        bigint(20),\n    osAndroid41Count        bigint(20),\n    osAndroid42Count        bigint(20),\n    osAndroid43Count        bigint(20),\n    osLinuxUbuntuCount      bigint(20),\n    browserIECount          bigint(20),\n    browserFirefoxCount     bigint(20),\n    browserChromeCount      bigint(20),\n    browserSafariCount      bigint(20),\n    browserOperaCount       bigint(20),\n    browserIE5Count         bigint(20),\n    browserIE6Count         bigint(20),\n    browserIE7Count         bigint(20),\n    browserIE8Count         bigint(20),\n    browserIE9Count         bigint(20),\n    browserIE10Count        bigint(20),\n    browser360SECount       bigint(20),\n    deviceAndroidCount      bigint(20),\n    deviceIpadCount         bigint(20),\n    deviceIphoneCount       bigint(20),\n    deviceWindowsPhoneCount bigint(20),\n    botCount                bigint(20),\n    botBaiduCount           bigint(20),\n    botYoudaoCount          bigint(20),\n    botGoogleCount          bigint(20),\n    botMsnCount             bigint(20),\n    botBingCount            bigint(20),\n    botSosoCount            bigint(20),\n    botSogouCount           bigint(20),\n    botYahooCount           bigint(20),\n    PRIMARY KEY (id)\n);\n\nCREATE INDEX druid_webapp_index ON druid_webapp (collectTime, domain, app);"
  },
  {
    "path": "core/src/main/resources/support/monitor/mysql/weburi.sql",
    "content": "CREATE TABLE druid_weburi\n(\n    id                           bigint(20) AUTO_INCREMENT NOT NULL,\n    domain                       varchar(45) NOT NULL,\n    app                          varchar(45) NOT NULL,\n    cluster                      varchar(45) NOT NULL,\n    host                         varchar(128),\n    pid                          int(10) NOT NULL,\n    collectTime                  datetime    NOT NULL,\n    uri                          varchar(256),\n    runningCount                 int(10),\n    concurrentMax                int(10),\n    requestCount                 bigint(20),\n    requestTimeNano              bigint(20),\n    jdbcFetchRowCount            bigint(20),\n    jdbcFetchRowPeak             bigint(20),\n    jdbcUpdateCount              bigint(20),\n    jdbcUpdatePeak               bigint(20),\n    jdbcExecuteCount             bigint(20),\n    jdbcExecuteErrorCount        bigint(20),\n    jdbcExecutePeak              bigint(20),\n    jdbcExecuteTimeNano          bigint(20),\n    jdbcCommitCount              bigint(20),\n    jdbcRollbackCount            bigint(20),\n    jdbcPoolConnectionOpenCount  bigint(20),\n    jdbcPoolConnectionCloseCount bigint(20),\n    jdbcResultSetOpenCount       bigint(20),\n    jdbcResultSetCloseCount      bigint(20),\n    errorCount                   bigint(20),\n    lastAccessTime               datetime,\n    h1                           bigint(20),\n    h10                          bigint(20),\n    h100                         bigint(20),\n    h1000                        bigint(20),\n    h10000                       int(10),\n    h100000                      int(10),\n    h1000000                     int(10),\n    hmore                        int(10),\n    PRIMARY KEY (id)\n);\n\nCREATE INDEX druid_weburi_index ON druid_weburi (collectTime, domain, app);"
  },
  {
    "path": "core/src/main/resources/support/monitor/resources/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <title>Druid-Monitor</title>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf8\"/>\n    <link href='css/bootstrap.min.css' rel=\"stylesheet\"/>\n    <script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n</head>\n<body>\n\n</body>\n</html>"
  },
  {
    "path": "core/src/main/resources/tpcds/create_tables.sql",
    "content": "drop table if exists call_center_text;\ncreate table call_center_text\n(\n    cc_call_center_sk int,\n    cc_call_center_id string,\n    cc_rec_start_date string,\n    cc_rec_end_date   string,\n    cc_closed_date_sk int,\n    cc_open_date_sk   int,\n    cc_name           string,\n    cc_class          string,\n    cc_employees      int,\n    cc_sq_ft          int,\n    cc_hours          string,\n    cc_manager        string,\n    cc_mkt_id         int,\n    cc_mkt_class      string,\n    cc_mkt_desc       string,\n    cc_market_manager string,\n    cc_division       int,\n    cc_division_name  string,\n    cc_company        int,\n    cc_company_name   string,\n    cc_street_number  string,\n    cc_street_name    string,\n    cc_street_type    string,\n    cc_suite_number   string,\n    cc_city           string,\n    cc_county         string,\n    cc_state          string,\n    cc_zip            string,\n    cc_country        string,\n    cc_gmt_offset     double,\n    cc_tax_percentage double\n)\n;\ndrop table if exists call_center;\ncreate table call_center\nas (select *\n    from call_center_text)\n;\ndrop table if exists call_center_text;\n\ndrop table if exists catalog_page_text;\ncreate table catalog_page_text\n(\n    cp_catalog_page_sk     int,\n    cp_catalog_page_id     string,\n    cp_start_date_sk       int,\n    cp_end_date_sk         int,\n    cp_department          string,\n    cp_catalog_number      int,\n    cp_catalog_page_number int,\n    cp_description         string,\n    cp_type                string\n)\n;\ndrop table if exists catalog_page;\ncreate table catalog_page\nas (select *\n    from catalog_page_text)\n;\ndrop table if exists catalog_page_text;\n\ndrop table if exists catalog_returns_text;\ncreate table catalog_returns_text\n(\n    cr_returned_date_sk      int,\n    cr_returned_time_sk      int,\n    cr_item_sk               int,\n    cr_refunded_customer_sk  int,\n    cr_refunded_cdemo_sk     int,\n    cr_refunded_hdemo_sk     int,\n    cr_refunded_addr_sk      int,\n    cr_returning_customer_sk int,\n    cr_returning_cdemo_sk    int,\n    cr_returning_hdemo_sk    int,\n    cr_returning_addr_sk     int,\n    cr_call_center_sk        int,\n    cr_catalog_page_sk       int,\n    cr_ship_mode_sk          int,\n    cr_warehouse_sk          int,\n    cr_reason_sk             int,\n    cr_order_number          int,\n    cr_return_quantity       int,\n    cr_return_amount         double,\n    cr_return_tax            double,\n    cr_return_amt_inc_tax    double,\n    cr_fee                   double,\n    cr_return_ship_cost      double,\n    cr_refunded_cash         double,\n    cr_reversed_charge       double,\n    cr_store_credit          double,\n    cr_net_loss              double\n)\n;\ndrop table if exists catalog_returns;\ncreate table catalog_returns\nas (select *\n    from catalog_returns_text)\n;\ndrop table if exists catalog_returns_text;\n\n\ndrop table if exists catalog_sales_text;\ncreate table catalog_sales_text\n(\n    cs_sold_date_sk          int,\n    cs_sold_time_sk          int,\n    cs_ship_date_sk          int,\n    cs_bill_customer_sk      int,\n    cs_bill_cdemo_sk         int,\n    cs_bill_hdemo_sk         int,\n    cs_bill_addr_sk          int,\n    cs_ship_customer_sk      int,\n    cs_ship_cdemo_sk         int,\n    cs_ship_hdemo_sk         int,\n    cs_ship_addr_sk          int,\n    cs_call_center_sk        int,\n    cs_catalog_page_sk       int,\n    cs_ship_mode_sk          int,\n    cs_warehouse_sk          int,\n    cs_item_sk               int,\n    cs_promo_sk              int,\n    cs_order_number          int,\n    cs_quantity              int,\n    cs_wholesale_cost        double,\n    cs_list_price            double,\n    cs_sales_price           double,\n    cs_ext_discount_amt      double,\n    cs_ext_sales_price       double,\n    cs_ext_wholesale_cost    double,\n    cs_ext_list_price        double,\n    cs_ext_tax               double,\n    cs_coupon_amt            double,\n    cs_ext_ship_cost         double,\n    cs_net_paid              double,\n    cs_net_paid_inc_tax      double,\n    cs_net_paid_inc_ship     double,\n    cs_net_paid_inc_ship_tax double,\n    cs_net_profit            double\n)\n;\ndrop table if exists catalog_sales;\ncreate table catalog_sales\nas (select *\n    from catalog_sales_text)\n;\ndrop table if exists catalog_sales_text;\n\ndrop table if exists customer_text;\ncreate table customer_text\n(\n    c_customer_sk          int,\n    c_customer_id          string,\n    c_current_cdemo_sk     int,\n    c_current_hdemo_sk     int,\n    c_current_addr_sk      int,\n    c_first_shipto_date_sk int,\n    c_first_sales_date_sk  int,\n    c_salutation           string,\n    c_first_name           string,\n    c_last_name            string,\n    c_preferred_cust_flag  string,\n    c_birth_day            int,\n    c_birth_month          int,\n    c_birth_year           int,\n    c_birth_country        string,\n    c_login                string,\n    c_email_address        string,\n    c_last_review_date     string\n)\n;\ndrop table if exists customer;\ncreate table customer\nas (select *\n    from customer_text)\n;\ndrop table if exists customer_text;\n\n\ndrop table if exists customer_address_text;\ncreate table customer_address_text\n(\n    ca_address_sk    int,\n    ca_address_id    string,\n    ca_street_number string,\n    ca_street_name   string,\n    ca_street_type   string,\n    ca_suite_number  string,\n    ca_city          string,\n    ca_county        string,\n    ca_state         string,\n    ca_zip           string,\n    ca_country       string,\n    ca_gmt_offset    double,\n    ca_location_type string\n)\n;\ndrop table if exists customer_address;\ncreate table customer_address\nas (select *\n    from customer_address_text)\n;\ndrop table if exists customer_address_text;\n\ndrop table if exists customer_demographics_text;\ncreate table customer_demographics_text\n(\n    cd_demo_sk            int,\n    cd_gender             string,\n    cd_marital_status     string,\n    cd_education_status   string,\n    cd_purchase_estimate  int,\n    cd_credit_rating      string,\n    cd_dep_count          int,\n    cd_dep_employed_count int,\n    cd_dep_college_count  int\n)\n;\ndrop table if exists customer_demographics;\ncreate table customer_demographics\nas (select *\n    from customer_demographics_text)\n;\ndrop table if exists customer_demographics_text;\n\ndrop table if exists date_dim_text;\ncreate table date_dim_text\n(\n    d_date_sk           int,\n    d_date_id           string,\n    d_date              string,\n    d_month_seq         int,\n    d_week_seq          int,\n    d_quarter_seq       int,\n    d_year              int,\n    d_dow               int,\n    d_moy               int,\n    d_dom               int,\n    d_qoy               int,\n    d_fy_year           int,\n    d_fy_quarter_seq    int,\n    d_fy_week_seq       int,\n    d_day_name          string,\n    d_quarter_name      string,\n    d_holiday           string,\n    d_weekend           string,\n    d_following_holiday string,\n    d_first_dom         int,\n    d_last_dom          int,\n    d_same_day_ly       int,\n    d_same_day_lq       int,\n    d_current_day       string,\n    d_current_week      string,\n    d_current_month     string,\n    d_current_quarter   string,\n    d_current_year      string\n)\n;\ndrop table if exists date_dim;\ncreate table date_dim\nas (select *\n    from date_dim_text)\n;\ndrop table if exists date_dim_text;\n\ndrop table if exists household_demographics_text;\ncreate table household_demographics_text\n(\n    hd_demo_sk        int,\n    hd_income_band_sk int,\n    hd_buy_potential  string,\n    hd_dep_count      int,\n    hd_vehicle_count  int\n)\n;\ndrop table if exists household_demographics;\ncreate table household_demographics\nas (select *\n    from household_demographics_text)\n;\ndrop table if exists household_demographics_text;\n\ndrop table if exists income_band_text;\ncreate table income_band_text\n(\n    ib_income_band_sk int,\n    ib_lower_bound    int,\n    ib_upper_bound    int\n)\n;\ndrop table if exists income_band;\ncreate table income_band\nas (select *\n    from income_band_text)\n;\ndrop table if exists income_band_text;\n\ndrop table if exists inventory_text;\ncreate table inventory_text\n(\n    inv_date_sk          int,\n    inv_item_sk          int,\n    inv_warehouse_sk     int,\n    inv_quantity_on_hand bigint\n)\n;\ndrop table if exists inventory;\ncreate table inventory\nas (select *\n    from inventory_text)\n;\ndrop table if exists inventory_text;\n\ndrop table if exists item_text;\ncreate table item_text\n(\n    i_item_sk        int,\n    i_item_id        string,\n    i_rec_start_date string,\n    i_rec_end_date   string,\n    i_item_desc      string,\n    i_current_price  double,\n    i_wholesale_cost double,\n    i_brand_id       int,\n    i_brand          string,\n    i_class_id       int,\n    i_class          string,\n    i_category_id    int,\n    i_category       string,\n    i_manufact_id    int,\n    i_manufact       string,\n    i_size           string,\n    i_formulation    string,\n    i_color          string,\n    i_units          string,\n    i_container      string,\n    i_manager_id     int,\n    i_product_name   string\n)\n;\ndrop table if exists item;\ncreate table item\nas (select *\n    from item_text)\n;\ndrop table if exists item_text;\n\ndrop table if exists promotion_text;\ncreate table promotion_text\n(\n    p_promo_sk        int,\n    p_promo_id        string,\n    p_start_date_sk   int,\n    p_end_date_sk     int,\n    p_item_sk         int,\n    p_cost            double,\n    p_response_target int,\n    p_promo_name      string,\n    p_channel_dmail   string,\n    p_channel_email   string,\n    p_channel_catalog string,\n    p_channel_tv      string,\n    p_channel_radio   string,\n    p_channel_press   string,\n    p_channel_event   string,\n    p_channel_demo    string,\n    p_channel_details string,\n    p_purpose         string,\n    p_discount_active string\n)\n;\ndrop table if exists promotion;\ncreate table promotion\nas (select *\n    from promotion_text)\n;\ndrop table if exists promotion_text;\n\ndrop table if exists reason_text;\ncreate table reason_text\n(\n    r_reason_sk   int,\n    r_reason_id   string,\n    r_reason_desc string\n)\n;\ndrop table if exists reason;\ncreate table reason\nas (select *\n    from reason_text)\n;\ndrop table if exists reason_text;\n\ndrop table if exists ship_mode_text;\ncreate table ship_mode_text\n(\n    sm_ship_mode_sk int,\n    sm_ship_mode_id string,\n    sm_type         string,\n    sm_code         string,\n    sm_carrier      string,\n    sm_contract     string\n)\n;\ndrop table if exists ship_mode;\ncreate table ship_mode\nas (select *\n    from ship_mode_text)\n;\ndrop table if exists ship_mode_text;\n\ndrop table if exists store_text;\ncreate table store_text\n(\n    s_store_sk         int,\n    s_store_id         string,\n    s_rec_start_date   string,\n    s_rec_end_date     string,\n    s_closed_date_sk   int,\n    s_store_name       string,\n    s_number_employees int,\n    s_floor_space      int,\n    s_hours            string,\n    s_manager          string,\n    s_market_id        int,\n    s_geography_class  string,\n    s_market_desc      string,\n    s_market_manager   string,\n    s_division_id      int,\n    s_division_name    string,\n    s_company_id       int,\n    s_company_name     string,\n    s_street_number    string,\n    s_street_name      string,\n    s_street_type      string,\n    s_suite_number     string,\n    s_city             string,\n    s_county           string,\n    s_state            string,\n    s_zip              string,\n    s_country          string,\n    s_gmt_offset       double,\n    s_tax_precentage   double\n)\n;\ndrop table if exists store;\ncreate table store\nas (select *\n    from store_text)\n;\ndrop table if exists store_text;\n\ndrop table if exists store_returns_text;\ncreate table store_returns_text\n(\n    sr_returned_date_sk   int,\n    sr_return_time_sk     int,\n    sr_item_sk            int,\n    sr_customer_sk        int,\n    sr_cdemo_sk           int,\n    sr_hdemo_sk           int,\n    sr_addr_sk            int,\n    sr_store_sk           int,\n    sr_reason_sk          int,\n    sr_ticket_number      int,\n    sr_return_quantity    int,\n    sr_return_amt         double,\n    sr_return_tax         double,\n    sr_return_amt_inc_tax double,\n    sr_fee                double,\n    sr_return_ship_cost   double,\n    sr_refunded_cash      double,\n    sr_reversed_charge    double,\n    sr_store_credit       double,\n    sr_net_loss           double\n)\n;\ndrop table if exists store_returns;\ncreate table store_returns\nas (select *\n    from store_returns_text)\n;\ndrop table if exists store_returns_text;\n\ndrop table if exists store_sales_text;\ncreate table store_sales_text\n(\n    ss_sold_date_sk       int,\n    ss_sold_time_sk       int,\n    ss_item_sk            int,\n    ss_customer_sk        int,\n    ss_cdemo_sk           int,\n    ss_hdemo_sk           int,\n    ss_addr_sk            int,\n    ss_store_sk           int,\n    ss_promo_sk           int,\n    ss_ticket_number      int,\n    ss_quantity           int,\n    ss_wholesale_cost     double,\n    ss_list_price         double,\n    ss_sales_price        double,\n    ss_ext_discount_amt   double,\n    ss_ext_sales_price    double,\n    ss_ext_wholesale_cost double,\n    ss_ext_list_price     double,\n    ss_ext_tax            double,\n    ss_coupon_amt         double,\n    ss_net_paid           double,\n    ss_net_paid_inc_tax   double,\n    ss_net_profit         double\n)\n;\ndrop table if exists store_sales;\ncreate table store_sales\nas (select *\n    from store_sales_text)\n;\ndrop table if exists store_sales_text;\n\ndrop table if exists time_dim_text;\ncreate table time_dim_text\n(\n    t_time_sk   int,\n    t_time_id   string,\n    t_time      int,\n    t_hour      int,\n    t_minute    int,\n    t_second    int,\n    t_am_pm     string,\n    t_shift     string,\n    t_sub_shift string,\n    t_meal_time string\n)\n;\ndrop table if exists time_dim;\ncreate table time_dim\nas (select *\n    from time_dim_text)\n;\ndrop table if exists time_dim_text;\n\ndrop table if exists warehouse_text;\ncreate table warehouse_text\n(\n    w_warehouse_sk    int,\n    w_warehouse_id    string,\n    w_warehouse_name  string,\n    w_warehouse_sq_ft int,\n    w_street_number   string,\n    w_street_name     string,\n    w_street_type     string,\n    w_suite_number    string,\n    w_city            string,\n    w_county          string,\n    w_state           string,\n    w_zip             string,\n    w_country         string,\n    w_gmt_offset      double\n)\n;\ndrop table if exists warehouse;\ncreate table warehouse\nas (select *\n    from warehouse_text)\n;\ndrop table if exists warehouse_text;\n\ndrop table if exists web_page_text;\ncreate table web_page_text\n(\n    wp_web_page_sk      int,\n    wp_web_page_id      string,\n    wp_rec_start_date   string,\n    wp_rec_end_date     string,\n    wp_creation_date_sk int,\n    wp_access_date_sk   int,\n    wp_autogen_flag     string,\n    wp_customer_sk      int,\n    wp_url              string,\n    wp_type             string,\n    wp_char_count       int,\n    wp_link_count       int,\n    wp_image_count      int,\n    wp_max_ad_count     int\n)\n;\ndrop table if exists web_page;\ncreate table web_page\nas (select *\n    from web_page_text)\n;\ndrop table if exists web_page_text;\n\ndrop table if exists web_returns_text;\ncreate table web_returns_text\n(\n    wr_returned_date_sk      int,\n    wr_returned_time_sk      int,\n    wr_item_sk               int,\n    wr_refunded_customer_sk  int,\n    wr_refunded_cdemo_sk     int,\n    wr_refunded_hdemo_sk     int,\n    wr_refunded_addr_sk      int,\n    wr_returning_customer_sk int,\n    wr_returning_cdemo_sk    int,\n    wr_returning_hdemo_sk    int,\n    wr_returning_addr_sk     int,\n    wr_web_page_sk           int,\n    wr_reason_sk             int,\n    wr_order_number          int,\n    wr_return_quantity       int,\n    wr_return_amt            double,\n    wr_return_tax            double,\n    wr_return_amt_inc_tax    double,\n    wr_fee                   double,\n    wr_return_ship_cost      double,\n    wr_refunded_cash         double,\n    wr_reversed_charge       double,\n    wr_account_credit        double,\n    wr_net_loss              double\n)\n;\ndrop table if exists web_returns;\ncreate table web_returns\nas (select *\n    from web_returns_text)\n;\ndrop table if exists web_returns_text;\n\ndrop table if exists web_sales_text;\ncreate table web_sales_text\n(\n    ws_sold_date_sk          int,\n    ws_sold_time_sk          int,\n    ws_ship_date_sk          int,\n    ws_item_sk               int,\n    ws_bill_customer_sk      int,\n    ws_bill_cdemo_sk         int,\n    ws_bill_hdemo_sk         int,\n    ws_bill_addr_sk          int,\n    ws_ship_customer_sk      int,\n    ws_ship_cdemo_sk         int,\n    ws_ship_hdemo_sk         int,\n    ws_ship_addr_sk          int,\n    ws_web_page_sk           int,\n    ws_web_site_sk           int,\n    ws_ship_mode_sk          int,\n    ws_warehouse_sk          int,\n    ws_promo_sk              int,\n    ws_order_number          int,\n    ws_quantity              int,\n    ws_wholesale_cost        double,\n    ws_list_price            double,\n    ws_sales_price           double,\n    ws_ext_discount_amt      double,\n    ws_ext_sales_price       double,\n    ws_ext_wholesale_cost    double,\n    ws_ext_list_price        double,\n    ws_ext_tax               double,\n    ws_coupon_amt            double,\n    ws_ext_ship_cost         double,\n    ws_net_paid              double,\n    ws_net_paid_inc_tax      double,\n    ws_net_paid_inc_ship     double,\n    ws_net_paid_inc_ship_tax double,\n    ws_net_profit            double\n)\n;\ndrop table if exists web_sales;\ncreate table web_sales\nas (select *\n    from web_sales_text)\n;\ndrop table if exists web_sales_text;\n\ndrop table if exists web_site_text;\ncreate table web_site_text\n(\n    web_site_sk        int,\n    web_site_id        string,\n    web_rec_start_date string,\n    web_rec_end_date   string,\n    web_name           string,\n    web_open_date_sk   int,\n    web_close_date_sk  int,\n    web_class          string,\n    web_manager        string,\n    web_mkt_id         int,\n    web_mkt_class      string,\n    web_mkt_desc       string,\n    web_market_manager string,\n    web_company_id     int,\n    web_company_name   string,\n    web_street_number  string,\n    web_street_name    string,\n    web_street_type    string,\n    web_suite_number   string,\n    web_city           string,\n    web_county         string,\n    web_state          string,\n    web_zip            string,\n    web_country        string,\n    web_gmt_offset     double,\n    web_tax_percentage double\n)\n;\ndrop table if exists web_site;\ncreate table web_site\nas (select *\n    from web_site_text)\n;\ndrop table if exists web_site_text;\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query01.sql",
    "content": "WITH customer_total_return AS (SELECT sr_customer_sk     AS ctr_customer_sk,\n                                      sr_store_sk        AS ctr_store_sk,\n                                      sum(SR_RETURN_AMT) AS ctr_total_return\n                               FROM store_returns,\n                                    date_dim\n                               WHERE sr_returned_date_sk = d_date_sk\n                                 AND d_year = 2000\n                               GROUP BY sr_customer_sk, sr_store_sk)\nSELECT c_customer_id\nFROM customer_total_return ctr1,\n     store,\n     customer\nWHERE ctr1.ctr_total_return > (SELECT avg(ctr_total_return) * 1.2\n                               FROM customer_total_return ctr2\n                               WHERE ctr1.ctr_store_sk = ctr2.ctr_store_sk)\n  AND s_store_sk = ctr1.ctr_store_sk\n  AND s_state = 'TN'\n  AND ctr1.ctr_customer_sk = c_customer_sk\nORDER BY c_customer_id LIMIT 100"
  },
  {
    "path": "core/src/main/resources/tpcds/query02.sql",
    "content": "WITH wscs AS (SELECT sold_date_sk, sales_price\n              FROM (SELECT ws_sold_date_sk AS sold_date_sk, ws_ext_sales_price AS sales_price\n                    FROM web_sales\n                    UNION ALL\n                    SELECT cs_sold_date_sk AS sold_date_sk, cs_ext_sales_price AS sales_price\n                    FROM catalog_sales) x),\n     wswscs AS (SELECT d_week_seq\n                     , sum(CASE\n                               WHEN d_day_name = 'Sunday' THEN sales_price\n                               ELSE NULL\n             END) AS sun_sales\n                     , sum(CASE\n                               WHEN d_day_name = 'Monday' THEN sales_price\n                               ELSE NULL\n             END) AS mon_sales\n                     , sum(CASE\n                               WHEN d_day_name = 'Tuesday' THEN sales_price\n                               ELSE NULL\n             END) AS tue_sales\n                     , sum(CASE\n                               WHEN d_day_name = 'Wednesday' THEN sales_price\n                               ELSE NULL\n             END) AS wed_sales\n                     , sum(CASE\n                               WHEN d_day_name = 'Thursday' THEN sales_price\n                               ELSE NULL\n             END) AS thu_sales\n                     , sum(CASE\n                               WHEN d_day_name = 'Friday' THEN sales_price\n                               ELSE NULL\n             END) AS fri_sales\n                     , sum(CASE\n                               WHEN d_day_name = 'Saturday' THEN sales_price\n                               ELSE NULL\n             END) AS sat_sales\n                FROM wscs,\n                     date_dim\n                WHERE d_date_sk = sold_date_sk\n                GROUP BY d_week_seq)\nSELECT d_week_seq1\n     , round(sun_sales1 / sun_sales2, 2)\n     , round(mon_sales1 / mon_sales2, 2)\n     , round(tue_sales1 / tue_sales2, 2)\n     , round(wed_sales1 / wed_sales2, 2)\n     , round(thu_sales1 / thu_sales2, 2)\n     , round(fri_sales1 / fri_sales2, 2)\n     , round(sat_sales1 / sat_sales2, 2)\nFROM (SELECT wswscs.d_week_seq AS d_week_seq1\n           , sun_sales         AS sun_sales1\n           , mon_sales         AS mon_sales1\n           , tue_sales         AS tue_sales1\n           , wed_sales         AS wed_sales1\n           , thu_sales         AS thu_sales1\n           , fri_sales         AS fri_sales1\n           , sat_sales         AS sat_sales1\n      FROM wswscs,\n           date_dim\n      WHERE date_dim.d_week_seq = wswscs.d_week_seq\n        AND d_year = 2001) y,\n     (SELECT wswscs.d_week_seq AS d_week_seq2\n           , sun_sales         AS sun_sales2\n           , mon_sales         AS mon_sales2\n           , tue_sales         AS tue_sales2\n           , wed_sales         AS wed_sales2\n           , thu_sales         AS thu_sales2\n           , fri_sales         AS fri_sales2\n           , sat_sales         AS sat_sales2\n      FROM wswscs,\n           date_dim\n      WHERE date_dim.d_week_seq = wswscs.d_week_seq\n        AND d_year = 2001 + 1) z\nWHERE d_week_seq1 = d_week_seq2 - 53\nORDER BY d_week_seq1"
  },
  {
    "path": "core/src/main/resources/tpcds/query03.sql",
    "content": "SELECT dt.d_year, item.i_brand_id AS brand_id, item.i_brand AS brand, sum(ss_ext_sales_price) AS sum_agg\nFROM date_dim dt,\n     store_sales,\n     item\nWHERE dt.d_date_sk = store_sales.ss_sold_date_sk\n  AND store_sales.ss_item_sk = item.i_item_sk\n  AND item.i_manufact_id = 128\n  AND dt.d_moy = 11\nGROUP BY dt.d_year, item.i_brand, item.i_brand_id\nORDER BY dt.d_year, sum_agg DESC, brand_id LIMIT 100"
  },
  {
    "path": "core/src/main/resources/tpcds/query04.sql",
    "content": "with year_total as (select c_customer_id                                                                      customer_id\n                         , c_first_name                                                                       customer_first_name\n                         , c_last_name                                                                        customer_last_name\n                         , c_preferred_cust_flag                                                              customer_preferred_cust_flag\n                         , c_birth_country                                                                    customer_birth_country\n                         , c_login                                                                            customer_login\n                         , c_email_address                                                                    customer_email_address\n                         , d_year                                                                             dyear\n                         , sum(\n                ((ss_ext_list_price - ss_ext_wholesale_cost - ss_ext_discount_amt) + ss_ext_sales_price) / 2) year_total\n                         , 's'                                                                                sale_type\n                    from customer\n                       , store_sales\n                       , date_dim\n                    where c_customer_sk = ss_customer_sk\n                      and ss_sold_date_sk = d_date_sk\n                    group by c_customer_id\n                           , c_first_name\n                           , c_last_name\n                           , c_preferred_cust_flag\n                           , c_birth_country\n                           , c_login\n                           , c_email_address\n                           , d_year\n                    union all\n                    select c_customer_id         customer_id\n                         , c_first_name          customer_first_name\n                         , c_last_name           customer_last_name\n                         , c_preferred_cust_flag customer_preferred_cust_flag\n                         , c_birth_country       customer_birth_country\n                         , c_login               customer_login\n                         , c_email_address       customer_email_address\n                         , d_year                dyear\n                         , sum((\n                            ((cs_ext_list_price - cs_ext_wholesale_cost - cs_ext_discount_amt) + cs_ext_sales_price) /\n                            2))                  year_total\n                         , 'c'                   sale_type\n                    from customer\n                       , catalog_sales\n                       , date_dim\n                    where c_customer_sk = cs_bill_customer_sk\n                      and cs_sold_date_sk = d_date_sk\n                    group by c_customer_id\n                           , c_first_name\n                           , c_last_name\n                           , c_preferred_cust_flag\n                           , c_birth_country\n                           , c_login\n                           , c_email_address\n                           , d_year\n                    union all\n                    select c_customer_id         customer_id\n                         , c_first_name          customer_first_name\n                         , c_last_name           customer_last_name\n                         , c_preferred_cust_flag customer_preferred_cust_flag\n                         , c_birth_country       customer_birth_country\n                         , c_login               customer_login\n                         , c_email_address       customer_email_address\n                         , d_year                dyear\n                         , sum((\n                            ((ws_ext_list_price - ws_ext_wholesale_cost - ws_ext_discount_amt) + ws_ext_sales_price) /\n                            2))                  year_total\n                         , 'w'                   sale_type\n                    from customer\n                       , web_sales\n                       , date_dim\n                    where c_customer_sk = ws_bill_customer_sk\n                      and ws_sold_date_sk = d_date_sk\n                    group by c_customer_id\n                           , c_first_name\n                           , c_last_name\n                           , c_preferred_cust_flag\n                           , c_birth_country\n                           , c_login\n                           , c_email_address\n                           , d_year)\nselect t_s_secyear.customer_id\n     , t_s_secyear.customer_first_name\n     , t_s_secyear.customer_last_name\n     , t_s_secyear.customer_preferred_cust_flag\nfrom year_total t_s_firstyear\n   , year_total t_s_secyear\n   , year_total t_c_firstyear\n   , year_total t_c_secyear\n   , year_total t_w_firstyear\n   , year_total t_w_secyear\nwhere t_s_secyear.customer_id = t_s_firstyear.customer_id\n  and t_s_firstyear.customer_id = t_c_secyear.customer_id\n  and t_s_firstyear.customer_id = t_c_firstyear.customer_id\n  and t_s_firstyear.customer_id = t_w_firstyear.customer_id\n  and t_s_firstyear.customer_id = t_w_secyear.customer_id\n  and t_s_firstyear.sale_type = 's'\n  and t_c_firstyear.sale_type = 'c'\n  and t_w_firstyear.sale_type = 'w'\n  and t_s_secyear.sale_type = 's'\n  and t_c_secyear.sale_type = 'c'\n  and t_w_secyear.sale_type = 'w'\n  and t_s_firstyear.dyear = 2001\n  and t_s_secyear.dyear = 2001 + 1\n  and t_c_firstyear.dyear = 2001\n  and t_c_secyear.dyear = 2001 + 1\n  and t_w_firstyear.dyear = 2001\n  and t_w_secyear.dyear = 2001 + 1\n  and t_s_firstyear.year_total > 0\n  and t_c_firstyear.year_total > 0\n  and t_w_firstyear.year_total > 0\n  and case when t_c_firstyear.year_total > 0 then t_c_secyear.year_total / t_c_firstyear.year_total else null end\n    > case when t_s_firstyear.year_total > 0 then t_s_secyear.year_total / t_s_firstyear.year_total else null end\n  and case when t_c_firstyear.year_total > 0 then t_c_secyear.year_total / t_c_firstyear.year_total else null end\n    > case when t_w_firstyear.year_total > 0 then t_w_secyear.year_total / t_w_firstyear.year_total else null end\norder by t_s_secyear.customer_id\n       , t_s_secyear.customer_first_name\n       , t_s_secyear.customer_last_name\n       , t_s_secyear.customer_preferred_cust_flag limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query05.sql",
    "content": "WITH ssr AS (SELECT s_store_id\n                  , sum(sales_price) AS sales\n                  , sum(profit)      AS profit\n                  , sum(return_amt)  AS returns\n                  , sum(net_loss)    AS profit_loss\n             FROM (SELECT ss_store_sk              AS store_sk\n                        , ss_sold_date_sk          AS date_sk\n                        , ss_ext_sales_price       AS sales_price\n                        , ss_net_profit            AS profit\n                        , CAST(0 AS decimal(7, 2)) AS return_amt\n                        , CAST(0 AS decimal(7, 2)) AS net_loss\n                   FROM store_sales\n                   UNION ALL\n                   SELECT sr_store_sk              AS store_sk\n                        , sr_returned_date_sk      AS date_sk\n                        , CAST(0 AS decimal(7, 2)) AS sales_price\n                        , CAST(0 AS decimal(7, 2)) AS profit\n                        , sr_return_amt            AS return_amt\n                        , sr_net_loss              AS net_loss\n                   FROM store_returns) salesreturns,\n                  date_dim,\n                  store\n             WHERE date_sk = d_date_sk\n               AND d_date BETWEEN CAST('2000-08-23' AS date) AND date_add(CAST('2000-08-23' AS date), 14)\n               AND store_sk = s_store_sk\n             GROUP BY s_store_id),\n     csr AS (SELECT cp_catalog_page_id\n                  , sum(sales_price) AS sales\n                  , sum(profit)      AS profit\n                  , sum(return_amt)  AS returns\n                  , sum(net_loss)    AS profit_loss\n             FROM (SELECT cs_catalog_page_sk       AS page_sk\n                        , cs_sold_date_sk          AS date_sk\n                        , cs_ext_sales_price       AS sales_price\n                        , cs_net_profit            AS profit\n                        , CAST(0 AS decimal(7, 2)) AS return_amt\n                        , CAST(0 AS decimal(7, 2)) AS net_loss\n                   FROM catalog_sales\n                   UNION ALL\n                   SELECT cr_catalog_page_sk       AS page_sk\n                        , cr_returned_date_sk      AS date_sk\n                        , CAST(0 AS decimal(7, 2)) AS sales_price\n                        , CAST(0 AS decimal(7, 2)) AS profit\n                        , cr_return_amount         AS return_amt\n                        , cr_net_loss              AS net_loss\n                   FROM catalog_returns) salesreturns,\n                  date_dim,\n                  catalog_page\n             WHERE date_sk = d_date_sk\n               AND d_date BETWEEN CAST('2000-08-23' AS date) AND date_add(CAST('2000-08-23' AS date), 14)\n               AND page_sk = cp_catalog_page_sk\n             GROUP BY cp_catalog_page_id),\n     wsr AS (SELECT web_site_id\n                  , sum(sales_price) AS sales\n                  , sum(profit)      AS profit\n                  , sum(return_amt)  AS returns\n                  , sum(net_loss)    AS profit_loss\n             FROM (SELECT ws_web_site_sk           AS wsr_web_site_sk\n                        , ws_sold_date_sk          AS date_sk\n                        , ws_ext_sales_price       AS sales_price\n                        , ws_net_profit            AS profit\n                        , CAST(0 AS decimal(7, 2)) AS return_amt\n                        , CAST(0 AS decimal(7, 2)) AS net_loss\n                   FROM web_sales\n                   UNION ALL\n                   SELECT ws_web_site_sk           AS wsr_web_site_sk\n                        , wr_returned_date_sk      AS date_sk\n                        , CAST(0 AS decimal(7, 2)) AS sales_price\n                        , CAST(0 AS decimal(7, 2)) AS profit\n                        , wr_return_amt            AS return_amt\n                        , wr_net_loss              AS net_loss\n                   FROM web_returns\n                            LEFT JOIN web_sales\n                                      ON wr_item_sk = ws_item_sk\n                                          AND wr_order_number = ws_order_number) salesreturns,\n                  date_dim,\n                  web_site\n             WHERE date_sk = d_date_sk\n               AND d_date BETWEEN CAST('2000-08-23' AS date) AND date_add(CAST('2000-08-23' AS date), 14)\n               AND wsr_web_site_sk = web_site_sk\n             GROUP BY web_site_id)\nSELECT channel\n     , id\n     , sum(sales)   AS sales\n     , sum(returns) AS returns\n     , sum(profit)  AS profit\nFROM (SELECT 'store channel'             AS channel\n           , concat('store', s_store_id) AS id\n           , sales\n           , returns\n           , profit - profit_loss        AS profit\n      FROM ssr\n      UNION ALL\n      SELECT 'catalog channel'                          AS channel\n           , concat('catalog_page', cp_catalog_page_id) AS id\n           , sales\n           , returns\n           , profit - profit_loss                       AS profit\n      FROM csr\n      UNION ALL\n      SELECT 'web channel'                   AS channel\n           , concat('web_site', web_site_id) AS id\n           , sales\n           , returns\n           , profit - profit_loss            AS profit\n      FROM wsr) x\nGROUP BY ROLLUP (channel, id)\nORDER BY channel, id LIMIT 100"
  },
  {
    "path": "core/src/main/resources/tpcds/query06.sql",
    "content": "select a.ca_state state, count(*) cnt\nfrom customer_address a\n   , customer c\n   , store_sales s\n   , date_dim d\n   , item i\nwhere a.ca_address_sk = c.c_current_addr_sk\n  and c.c_customer_sk = s.ss_customer_sk\n  and s.ss_sold_date_sk = d.d_date_sk\n  and s.ss_item_sk = i.i_item_sk\n  and d.d_month_seq =\n      (select distinct (d_month_seq)\n       from date_dim\n       where d_year = 2001\n         and d_moy = 1)\n  and i.i_current_price > 1.2 *\n                          (select avg(j.i_current_price)\n                           from item j\n                           where j.i_category = i.i_category)\ngroup by a.ca_state\nhaving count(*) >= 10\norder by cnt limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query07.sql",
    "content": "select i_item_id,\n       avg(ss_quantity)    agg1,\n       avg(ss_list_price)  agg2,\n       avg(ss_coupon_amt)  agg3,\n       avg(ss_sales_price) agg4\nfrom store_sales,\n     customer_demographics,\n     date_dim,\n     item,\n     promotion\nwhere ss_sold_date_sk = d_date_sk\n  and ss_item_sk = i_item_sk\n  and ss_cdemo_sk = cd_demo_sk\n  and ss_promo_sk = p_promo_sk\n  and cd_gender = 'M'\n  and cd_marital_status = 'S'\n  and cd_education_status = 'College'\n  and (p_channel_email = 'N' or p_channel_event = 'N')\n  and d_year = 2000\ngroup by i_item_id\norder by i_item_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query08.sql",
    "content": "select s_store_name\n     , sum(ss_net_profit)\nfrom store_sales\n   , date_dim\n   , store\n   , (select ca_zip\n      from (SELECT substr(ca_zip, 1, 5) ca_zip\n            FROM customer_address\n            WHERE substr(ca_zip, 1, 5) IN (\n                                           '24128', '76232', '65084', '87816', '83926', '77556',\n                                           '20548', '26231', '43848', '15126', '91137',\n                                           '61265', '98294', '25782', '17920', '18426',\n                                           '98235', '40081', '84093', '28577', '55565',\n                                           '17183', '54601', '67897', '22752', '86284',\n                                           '18376', '38607', '45200', '21756', '29741',\n                                           '96765', '23932', '89360', '29839', '25989',\n                                           '28898', '91068', '72550', '10390', '18845',\n                                           '47770', '82636', '41367', '76638', '86198',\n                                           '81312', '37126', '39192', '88424', '72175',\n                                           '81426', '53672', '10445', '42666', '66864',\n                                           '66708', '41248', '48583', '82276', '18842',\n                                           '78890', '49448', '14089', '38122', '34425',\n                                           '79077', '19849', '43285', '39861', '66162',\n                                           '77610', '13695', '99543', '83444', '83041',\n                                           '12305', '57665', '68341', '25003', '57834',\n                                           '62878', '49130', '81096', '18840', '27700',\n                                           '23470', '50412', '21195', '16021', '76107',\n                                           '71954', '68309', '18119', '98359', '64544',\n                                           '10336', '86379', '27068', '39736', '98569',\n                                           '28915', '24206', '56529', '57647', '54917',\n                                           '42961', '91110', '63981', '14922', '36420',\n                                           '23006', '67467', '32754', '30903', '20260',\n                                           '31671', '51798', '72325', '85816', '68621',\n                                           '13955', '36446', '41766', '68806', '16725',\n                                           '15146', '22744', '35850', '88086', '51649',\n                                           '18270', '52867', '39972', '96976', '63792',\n                                           '11376', '94898', '13595', '10516', '90225',\n                                           '58943', '39371', '94945', '28587', '96576',\n                                           '57855', '28488', '26105', '83933', '25858',\n                                           '34322', '44438', '73171', '30122', '34102',\n                                           '22685', '71256', '78451', '54364', '13354',\n                                           '45375', '40558', '56458', '28286', '45266',\n                                           '47305', '69399', '83921', '26233', '11101',\n                                           '15371', '69913', '35942', '15882', '25631',\n                                           '24610', '44165', '99076', '33786', '70738',\n                                           '26653', '14328', '72305', '62496', '22152',\n                                           '10144', '64147', '48425', '14663', '21076',\n                                           '18799', '30450', '63089', '81019', '68893',\n                                           '24996', '51200', '51211', '45692', '92712',\n                                           '70466', '79994', '22437', '25280', '38935',\n                                           '71791', '73134', '56571', '14060', '19505',\n                                           '72425', '56575', '74351', '68786', '51650',\n                                           '20004', '18383', '76614', '11634', '18906',\n                                           '15765', '41368', '73241', '76698', '78567',\n                                           '97189', '28545', '76231', '75691', '22246',\n                                           '51061', '90578', '56691', '68014', '51103',\n                                           '94167', '57047', '14867', '73520', '15734',\n                                           '63435', '25733', '35474', '24676', '94627',\n                                           '53535', '17879', '15559', '53268', '59166',\n                                           '11928', '59402', '33282', '45721', '43933',\n                                           '68101', '33515', '36634', '71286', '19736',\n                                           '58058', '55253', '67473', '41918', '19515',\n                                           '36495', '19430', '22351', '77191', '91393',\n                                           '49156', '50298', '87501', '18652', '53179',\n                                           '18767', '63193', '23968', '65164', '68880',\n                                           '21286', '72823', '58470', '67301', '13394',\n                                           '31016', '70372', '67030', '40604', '24317',\n                                           '45748', '39127', '26065', '77721', '31029',\n                                           '31880', '60576', '24671', '45549', '13376',\n                                           '50016', '33123', '19769', '22927', '97789',\n                                           '46081', '72151', '15723', '46136', '51949',\n                                           '68100', '96888', '64528', '14171', '79777',\n                                           '28709', '11489', '25103', '32213', '78668',\n                                           '22245', '15798', '27156', '37930', '62971',\n                                           '21337', '51622', '67853', '10567', '38415',\n                                           '15455', '58263', '42029', '60279', '37125',\n                                           '56240', '88190', '50308', '26859', '64457',\n                                           '89091', '82136', '62377', '36233', '63837',\n                                           '58078', '17043', '30010', '60099', '28810',\n                                           '98025', '29178', '87343', '73273', '30469',\n                                           '64034', '39516', '86057', '21309', '90257',\n                                           '67875', '40162', '11356', '73650', '61810',\n                                           '72013', '30431', '22461', '19512', '13375',\n                                           '55307', '30625', '83849', '68908', '26689',\n                                           '96451', '38193', '46820', '88885', '84935',\n                                           '69035', '83144', '47537', '56616', '94983',\n                                           '48033', '69952', '25486', '61547', '27385',\n                                           '61860', '58048', '56910', '16807', '17871',\n                                           '35258', '31387', '35458', '35576')\n            intersect\n            select ca_zip\n            from (SELECT substr(ca_zip, 1, 5) ca_zip, count(*) cnt\n                  FROM customer_address,\n                       customer\n                  WHERE ca_address_sk = c_current_addr_sk\n                    and c_preferred_cust_flag = 'Y'\n                  group by ca_zip\n                  having count(*) > 10) A1) A2) V1\nwhere ss_store_sk = s_store_sk\n  and ss_sold_date_sk = d_date_sk\n  and d_qoy = 2\n  and d_year = 1998\n  and (substr(s_zip, 1, 2) = substr(V1.ca_zip, 1, 2))\ngroup by s_store_name\norder by s_store_name limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query09.sql",
    "content": "select case\n           when (select count(*)\n                 from store_sales\n                 where ss_quantity between 1 and 20) > 74129\n               then (select avg(ss_ext_discount_amt)\n                     from store_sales\n                     where ss_quantity between 1 and 20)\n           else (select avg(ss_net_paid)\n                 from store_sales\n                 where ss_quantity between 1 and 20) end   bucket1,\n       case\n           when (select count(*)\n                 from store_sales\n                 where ss_quantity between 21 and 40) > 122840\n               then (select avg(ss_ext_discount_amt)\n                     from store_sales\n                     where ss_quantity between 21 and 40)\n           else (select avg(ss_net_paid)\n                 from store_sales\n                 where ss_quantity between 21 and 40) end  bucket2,\n       case\n           when (select count(*)\n                 from store_sales\n                 where ss_quantity between 41 and 60) > 56580\n               then (select avg(ss_ext_discount_amt)\n                     from store_sales\n                     where ss_quantity between 41 and 60)\n           else (select avg(ss_net_paid)\n                 from store_sales\n                 where ss_quantity between 41 and 60) end  bucket3,\n       case\n           when (select count(*)\n                 from store_sales\n                 where ss_quantity between 61 and 80) > 10097\n               then (select avg(ss_ext_discount_amt)\n                     from store_sales\n                     where ss_quantity between 61 and 80)\n           else (select avg(ss_net_paid)\n                 from store_sales\n                 where ss_quantity between 61 and 80) end  bucket4,\n       case\n           when (select count(*)\n                 from store_sales\n                 where ss_quantity between 81 and 100) > 165306\n               then (select avg(ss_ext_discount_amt)\n                     from store_sales\n                     where ss_quantity between 81 and 100)\n           else (select avg(ss_net_paid)\n                 from store_sales\n                 where ss_quantity between 81 and 100) end bucket5\nfrom reason\nwhere r_reason_sk = 1\n\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query10.sql",
    "content": "select cd_gender,\n       cd_marital_status,\n       cd_education_status,\n       count(*) cnt1,\n       cd_purchase_estimate,\n       count(*) cnt2,\n       cd_credit_rating,\n       count(*) cnt3,\n       cd_dep_count,\n       count(*) cnt4,\n       cd_dep_employed_count,\n       count(*) cnt5,\n       cd_dep_college_count,\n       count(*) cnt6\nfrom customer c,\n     customer_address ca,\n     customer_demographics\nwhere c.c_current_addr_sk = ca.ca_address_sk\n  and ca_county in ('Rush County', 'Toole County', 'Jefferson County', 'Dona Ana County', 'La Porte County')\n  and cd_demo_sk = c.c_current_cdemo_sk\n  and exists(select *\n             from store_sales,\n                  date_dim\n             where c.c_customer_sk = ss_customer_sk\n               and ss_sold_date_sk = d_date_sk\n               and d_year = 2002\n               and d_moy between 1 and 1 + 3)\n  and (exists(select *\n              from web_sales,\n                   date_dim\n              where c.c_customer_sk = ws_bill_customer_sk\n                and ws_sold_date_sk = d_date_sk\n                and d_year = 2002\n                and d_moy between 1 ANd 1 + 3) or\n       exists(select *\n              from catalog_sales,\n                   date_dim\n              where c.c_customer_sk = cs_ship_customer_sk\n                and cs_sold_date_sk = d_date_sk\n                and d_year = 2002\n                and d_moy between 1 and 1 + 3))\ngroup by cd_gender,\n         cd_marital_status,\n         cd_education_status,\n         cd_purchase_estimate,\n         cd_credit_rating,\n         cd_dep_count,\n         cd_dep_employed_count,\n         cd_dep_college_count\norder by cd_gender,\n         cd_marital_status,\n         cd_education_status,\n         cd_purchase_estimate,\n         cd_credit_rating,\n         cd_dep_count,\n         cd_dep_employed_count,\n         cd_dep_college_count limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query11.sql",
    "content": "with year_total as (select c_customer_id                                customer_id\n                         , c_first_name                                 customer_first_name\n                         , c_last_name                                  customer_last_name\n                         , c_preferred_cust_flag                        customer_preferred_cust_flag\n                         , c_birth_country                              customer_birth_country\n                         , c_login                                      customer_login\n                         , c_email_address                              customer_email_address\n                         , d_year                                       dyear\n                         , sum(ss_ext_list_price - ss_ext_discount_amt) year_total\n                         , 's'                                          sale_type\n                    from customer\n                       , store_sales\n                       , date_dim\n                    where c_customer_sk = ss_customer_sk\n                      and ss_sold_date_sk = d_date_sk\n                    group by c_customer_id\n                           , c_first_name\n                           , c_last_name\n                           , c_preferred_cust_flag\n                           , c_birth_country\n                           , c_login\n                           , c_email_address\n                           , d_year\n                    union all\n                    select c_customer_id                                customer_id\n                         , c_first_name                                 customer_first_name\n                         , c_last_name                                  customer_last_name\n                         , c_preferred_cust_flag                        customer_preferred_cust_flag\n                         , c_birth_country                              customer_birth_country\n                         , c_login                                      customer_login\n                         , c_email_address                              customer_email_address\n                         , d_year                                       dyear\n                         , sum(ws_ext_list_price - ws_ext_discount_amt) year_total\n                         , 'w'                                          sale_type\n                    from customer\n                       , web_sales\n                       , date_dim\n                    where c_customer_sk = ws_bill_customer_sk\n                      and ws_sold_date_sk = d_date_sk\n                    group by c_customer_id\n                           , c_first_name\n                           , c_last_name\n                           , c_preferred_cust_flag\n                           , c_birth_country\n                           , c_login\n                           , c_email_address\n                           , d_year)\nselect t_s_secyear.customer_id\n     , t_s_secyear.customer_first_name\n     , t_s_secyear.customer_last_name\n     , t_s_secyear.customer_preferred_cust_flag\nfrom year_total t_s_firstyear\n   , year_total t_s_secyear\n   , year_total t_w_firstyear\n   , year_total t_w_secyear\nwhere t_s_secyear.customer_id = t_s_firstyear.customer_id\n  and t_s_firstyear.customer_id = t_w_secyear.customer_id\n  and t_s_firstyear.customer_id = t_w_firstyear.customer_id\n  and t_s_firstyear.sale_type = 's'\n  and t_w_firstyear.sale_type = 'w'\n  and t_s_secyear.sale_type = 's'\n  and t_w_secyear.sale_type = 'w'\n  and t_s_firstyear.dyear = 2001\n  and t_s_secyear.dyear = 2001 + 1\n  and t_w_firstyear.dyear = 2001\n  and t_w_secyear.dyear = 2001 + 1\n  and t_s_firstyear.year_total > 0\n  and t_w_firstyear.year_total > 0\n  and case when t_w_firstyear.year_total > 0 then t_w_secyear.year_total / t_w_firstyear.year_total else 0.0 end\n    > case when t_s_firstyear.year_total > 0 then t_s_secyear.year_total / t_s_firstyear.year_total else 0.0 end\norder by t_s_secyear.customer_id\n       , t_s_secyear.customer_first_name\n       , t_s_secyear.customer_last_name\n       , t_s_secyear.customer_preferred_cust_flag limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query12.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , i_category\n     , i_class\n     , i_current_price\n     , sum(ws_ext_sales_price) as                                   itemrevenue\n     , sum(ws_ext_sales_price) * 100 / sum(sum(ws_ext_sales_price)) over (partition by i_class) as revenueratio\nfrom web_sales\n   , item\n   , date_dim\nwhere ws_item_sk = i_item_sk\n  and i_category in ('Sports', 'Books', 'Home')\n  and ws_sold_date_sk = d_date_sk\n  and d_date between cast('1999-02-22' as date)\n    and date_add(cast('1999-02-22' as date), 30)\ngroup by i_item_id\n       , i_item_desc\n       , i_category\n       , i_class\n       , i_current_price\norder by i_category\n       , i_class\n       , i_item_id\n       , i_item_desc\n       , revenueratio limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query13.sql",
    "content": "select avg(ss_quantity)\n     , avg(ss_ext_sales_price)\n     , avg(ss_ext_wholesale_cost)\n     , sum(ss_ext_wholesale_cost)\nfrom store_sales\n   , store\n   , customer_demographics\n   , household_demographics\n   , customer_address\n   , date_dim\nwhere s_store_sk = ss_store_sk\n  and ss_sold_date_sk = d_date_sk\n  and d_year = 2001\n  and ((ss_hdemo_sk = hd_demo_sk\n    and cd_demo_sk = ss_cdemo_sk\n    and cd_marital_status = 'M'\n    and cd_education_status = 'Advanced Degree'\n    and ss_sales_price between 100.00 and 150.00\n    and hd_dep_count = 3\n           ) or\n       (ss_hdemo_sk = hd_demo_sk\n           and cd_demo_sk = ss_cdemo_sk\n           and cd_marital_status = 'S'\n           and cd_education_status = 'College'\n           and ss_sales_price between 50.00 and 100.00\n           and hd_dep_count = 1\n           ) or\n       (ss_hdemo_sk = hd_demo_sk\n           and cd_demo_sk = ss_cdemo_sk\n           and cd_marital_status = 'W'\n           and cd_education_status = '2 yr Degree'\n           and ss_sales_price between 150.00 and 200.00\n           and hd_dep_count = 1\n           ))\n  and ((ss_addr_sk = ca_address_sk\n    and ca_country = 'United States'\n    and ca_state in ('TX', 'OH', 'TX')\n    and ss_net_profit between 100 and 200\n           ) or\n       (ss_addr_sk = ca_address_sk\n           and ca_country = 'United States'\n           and ca_state in ('OR', 'NM', 'KY')\n           and ss_net_profit between 150 and 300\n           ) or\n       (ss_addr_sk = ca_address_sk\n           and ca_country = 'United States'\n           and ca_state in ('VA', 'TX', 'MS')\n           and ss_net_profit between 50 and 250\n           ))\n\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query14.sql",
    "content": "with cross_items as\n         (select i_item_sk ss_item_sk\n          from item,\n               (select iss.i_brand_id    brand_id\n                     , iss.i_class_id    class_id\n                     , iss.i_category_id category_id\n                from store_sales\n                   , item iss\n                   , date_dim d1\n                where ss_item_sk = iss.i_item_sk\n                  and ss_sold_date_sk = d1.d_date_sk\n                  and d1.d_year between 1999 AND 1999 + 2\n                intersect\n                select ics.i_brand_id\n                     , ics.i_class_id\n                     , ics.i_category_id\n                from catalog_sales\n                   , item ics\n                   , date_dim d2\n                where cs_item_sk = ics.i_item_sk\n                  and cs_sold_date_sk = d2.d_date_sk\n                  and d2.d_year between 1999 AND 1999 + 2\n                intersect\n                select iws.i_brand_id\n                     , iws.i_class_id\n                     , iws.i_category_id\n                from web_sales\n                   , item iws\n                   , date_dim d3\n                where ws_item_sk = iws.i_item_sk\n                  and ws_sold_date_sk = d3.d_date_sk\n                  and d3.d_year between 1999 AND 1999 + 2)\n          where i_brand_id = brand_id\n            and i_class_id = class_id\n            and i_category_id = category_id),\n     avg_sales as\n         (select avg(quantity * list_price) average_sales\n          from (select ss_quantity   quantity\n                     , ss_list_price list_price\n                from store_sales\n                   , date_dim\n                where ss_sold_date_sk = d_date_sk\n                  and d_year between 1999 and 1999 + 2\n                union all\n                select cs_quantity   quantity\n                     , cs_list_price list_price\n                from catalog_sales\n                   , date_dim\n                where cs_sold_date_sk = d_date_sk\n                  and d_year between 1999 and 1999 + 2\n                union all\n                select ws_quantity   quantity\n                     , ws_list_price list_price\n                from web_sales\n                   , date_dim\n                where ws_sold_date_sk = d_date_sk\n                  and d_year between 1999 and 1999 + 2) x)\nselect channel, i_brand_id, i_class_id, i_category_id, sum(sales), sum(number_sales)\nfrom (select 'store'                          channel\n           , i_brand_id\n           , i_class_id\n           , i_category_id\n           , sum(ss_quantity * ss_list_price) sales\n           , count(*)                         number_sales\n      from store_sales\n         , item\n         , date_dim\n      where ss_item_sk in (select ss_item_sk from cross_items)\n        and ss_item_sk = i_item_sk\n        and ss_sold_date_sk = d_date_sk\n        and d_year = 1999 + 2\n        and d_moy = 11\n      group by i_brand_id, i_class_id, i_category_id\n      having sum(ss_quantity * ss_list_price) > (select average_sales from avg_sales)\n      union all\n      select 'catalog'                        channel,\n             i_brand_id,\n             i_class_id,\n             i_category_id,\n             sum(cs_quantity * cs_list_price) sales,\n             count(*)                         number_sales\n      from catalog_sales\n         , item\n         , date_dim\n      where cs_item_sk in (select ss_item_sk from cross_items)\n        and cs_item_sk = i_item_sk\n        and cs_sold_date_sk = d_date_sk\n        and d_year = 1999 + 2\n        and d_moy = 11\n      group by i_brand_id, i_class_id, i_category_id\n      having sum(cs_quantity * cs_list_price) > (select average_sales from avg_sales)\n      union all\n      select 'web'                            channel,\n             i_brand_id,\n             i_class_id,\n             i_category_id,\n             sum(ws_quantity * ws_list_price) sales,\n             count(*)                         number_sales\n      from web_sales\n         , item\n         , date_dim\n      where ws_item_sk in (select ss_item_sk from cross_items)\n        and ws_item_sk = i_item_sk\n        and ws_sold_date_sk = d_date_sk\n        and d_year = 1999 + 2\n        and d_moy = 11\n      group by i_brand_id, i_class_id, i_category_id\n      having sum(ws_quantity * ws_list_price) > (select average_sales from avg_sales)) y\ngroup by rollup (channel, i_brand_id, i_class_id, i_category_id)\norder by channel, i_brand_id, i_class_id, i_category_id limit 100;\nwith cross_items as\n         (select i_item_sk ss_item_sk\n          from item,\n               (select iss.i_brand_id    brand_id\n                     , iss.i_class_id    class_id\n                     , iss.i_category_id category_id\n                from store_sales\n                   , item iss\n                   , date_dim d1\n                where ss_item_sk = iss.i_item_sk\n                  and ss_sold_date_sk = d1.d_date_sk\n                  and d1.d_year between 1999 AND 1999 + 2\n                intersect\n                select ics.i_brand_id\n                     , ics.i_class_id\n                     , ics.i_category_id\n                from catalog_sales\n                   , item ics\n                   , date_dim d2\n                where cs_item_sk = ics.i_item_sk\n                  and cs_sold_date_sk = d2.d_date_sk\n                  and d2.d_year between 1999 AND 1999 + 2\n                intersect\n                select iws.i_brand_id\n                     , iws.i_class_id\n                     , iws.i_category_id\n                from web_sales\n                   , item iws\n                   , date_dim d3\n                where ws_item_sk = iws.i_item_sk\n                  and ws_sold_date_sk = d3.d_date_sk\n                  and d3.d_year between 1999 AND 1999 + 2) x\n          where i_brand_id = brand_id\n            and i_class_id = class_id\n            and i_category_id = category_id),\n     avg_sales as\n         (select avg(quantity * list_price) average_sales\n          from (select ss_quantity   quantity\n                     , ss_list_price list_price\n                from store_sales\n                   , date_dim\n                where ss_sold_date_sk = d_date_sk\n                  and d_year between 1999 and 1999 + 2\n                union all\n                select cs_quantity   quantity\n                     , cs_list_price list_price\n                from catalog_sales\n                   , date_dim\n                where cs_sold_date_sk = d_date_sk\n                  and d_year between 1999 and 1999 + 2\n                union all\n                select ws_quantity   quantity\n                     , ws_list_price list_price\n                from web_sales\n                   , date_dim\n                where ws_sold_date_sk = d_date_sk\n                  and d_year between 1999 and 1999 + 2) x)\nselect *\nfrom (select 'store'                          channel\n           , i_brand_id\n           , i_class_id\n           , i_category_id\n           , sum(ss_quantity * ss_list_price) sales\n           , count(*)                         number_sales\n      from store_sales\n         , item\n         , date_dim\n      where ss_item_sk in (select ss_item_sk from cross_items)\n        and ss_item_sk = i_item_sk\n        and ss_sold_date_sk = d_date_sk\n        and d_week_seq = (select d_week_seq\n                          from date_dim\n                          where d_year = 1999 + 1\n                            and d_moy = 12\n                            and d_dom = 11)\n      group by i_brand_id, i_class_id, i_category_id\n      having sum(ss_quantity * ss_list_price) > (select average_sales from avg_sales)) this_year,\n     (select 'store'                          channel_2\n           , i_brand_id    as                 i_brand_id_2\n           , i_class_id    as                 i_class_id_2\n           , i_category_id as                 i_category_id_2\n           , sum(ss_quantity * ss_list_price) sales_2\n           , count(*)                         number_sales_2\n      from store_sales\n         , item\n         , date_dim\n      where ss_item_sk in (select ss_item_sk from cross_items)\n        and ss_item_sk = i_item_sk\n        and ss_sold_date_sk = d_date_sk\n        and d_week_seq = (select d_week_seq\n                          from date_dim\n                          where d_year = 1999\n                            and d_moy = 12\n                            and d_dom = 11)\n      group by i_brand_id, i_class_id, i_category_id\n      having sum(ss_quantity * ss_list_price) > (select average_sales from avg_sales)) last_year\nwhere this_year.i_brand_id = last_year.i_brand_id_2\n  and this_year.i_class_id = last_year.i_class_id_2\n  and this_year.i_category_id = last_year.i_category_id_2\norder by this_year.channel, this_year.i_brand_id, this_year.i_class_id, this_year.i_category_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query15.sql",
    "content": "select ca_zip\n     , sum(cs_sales_price)\nfrom catalog_sales\n   , customer\n   , customer_address\n   , date_dim\nwhere cs_bill_customer_sk = c_customer_sk\n  and c_current_addr_sk = ca_address_sk\n  and (substr(ca_zip, 1, 5) in ('85669', '86197', '88274', '83405', '86475',\n                                '85392', '85460', '80348', '81792')\n    or ca_state in ('CA', 'WA', 'GA')\n    or cs_sales_price > 500)\n  and cs_sold_date_sk = d_date_sk\n  and d_qoy = 2\n  and d_year = 2001\ngroup by ca_zip\norder by ca_zip limit 100"
  },
  {
    "path": "core/src/main/resources/tpcds/query16.sql",
    "content": "select count(distinct cs_order_number) as order_count\n     , sum(cs_ext_ship_cost)           as total_shipping_cost\n     , sum(cs_net_profit)              as total_net_profit\nfrom catalog_sales cs1\n   , date_dim\n   , customer_address\n   , call_center\nwhere d_date between cast('2002-2-01' as date) and\n    date_add(cast('2002-2-01' as date), 60)\n  and cs1.cs_ship_date_sk = d_date_sk\n  and cs1.cs_ship_addr_sk = ca_address_sk\n  and ca_state = 'GA'\n  and cs1.cs_call_center_sk = cc_call_center_sk\n  and cc_county in ('Williamson County', 'Williamson County', 'Williamson County', 'Williamson County',\n                    'Williamson County'\n    )\n  and exists(select *\n             from catalog_sales cs2\n             where cs1.cs_order_number = cs2.cs_order_number\n               and cs1.cs_warehouse_sk <> cs2.cs_warehouse_sk)\n  and not exists(select *\n                 from catalog_returns cr1\n                 where cs1.cs_order_number = cr1.cr_order_number)\norder by count(distinct cs_order_number) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query17.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , s_state\n     , count(ss_quantity)                                        as store_sales_quantitycount\n     , avg(ss_quantity)                                          as store_sales_quantityave\n     , stddev_samp(ss_quantity)                                  as store_sales_quantitystdev\n     , stddev_samp(ss_quantity) / avg(ss_quantity)               as store_sales_quantitycov\n     , count(sr_return_quantity)                                 as store_returns_quantitycount\n     , avg(sr_return_quantity)                                   as store_returns_quantityave\n     , stddev_samp(sr_return_quantity)                           as store_returns_quantitystdev\n     , stddev_samp(sr_return_quantity) / avg(sr_return_quantity) as store_returns_quantitycov\n     , count(cs_quantity)                                        as catalog_sales_quantitycount\n     , avg(cs_quantity)                                          as catalog_sales_quantityave\n     , stddev_samp(cs_quantity)                                  as catalog_sales_quantitystdev\n     , stddev_samp(cs_quantity) / avg(cs_quantity)               as catalog_sales_quantitycov\nfrom store_sales\n   , store_returns\n   , catalog_sales\n   , date_dim d1\n   , date_dim d2\n   , date_dim d3\n   , store\n   , item\nwhere d1.d_quarter_name = '2001Q1'\n  and d1.d_date_sk = ss_sold_date_sk\n  and i_item_sk = ss_item_sk\n  and s_store_sk = ss_store_sk\n  and ss_customer_sk = sr_customer_sk\n  and ss_item_sk = sr_item_sk\n  and ss_ticket_number = sr_ticket_number\n  and sr_returned_date_sk = d2.d_date_sk\n  and d2.d_quarter_name in ('2001Q1', '2001Q2', '2001Q3')\n  and sr_customer_sk = cs_bill_customer_sk\n  and sr_item_sk = cs_item_sk\n  and cs_sold_date_sk = d3.d_date_sk\n  and d3.d_quarter_name in ('2001Q1', '2001Q2', '2001Q3')\ngroup by i_item_id\n       , i_item_desc\n       , s_state\norder by i_item_id\n       , i_item_desc\n       , s_state limit 100"
  },
  {
    "path": "core/src/main/resources/tpcds/query18.sql",
    "content": "select i_item_id,\n       ca_country,\n       ca_state,\n       ca_county,\n       avg(cast(cs_quantity as decimal(12, 2)))      agg1,\n       avg(cast(cs_list_price as decimal(12, 2)))    agg2,\n       avg(cast(cs_coupon_amt as decimal(12, 2)))    agg3,\n       avg(cast(cs_sales_price as decimal(12, 2)))   agg4,\n       avg(cast(cs_net_profit as decimal(12, 2)))    agg5,\n       avg(cast(c_birth_year as decimal(12, 2)))     agg6,\n       avg(cast(cd1.cd_dep_count as decimal(12, 2))) agg7\nfrom catalog_sales,\n     customer_demographics cd1,\n     customer_demographics cd2,\n     customer,\n     customer_address,\n     date_dim,\n     item\nwhere cs_sold_date_sk = d_date_sk\n  and cs_item_sk = i_item_sk\n  and cs_bill_cdemo_sk = cd1.cd_demo_sk\n  and cs_bill_customer_sk = c_customer_sk\n  and cd1.cd_gender = 'F'\n  and cd1.cd_education_status = 'Unknown'\n  and c_current_cdemo_sk = cd2.cd_demo_sk\n  and c_current_addr_sk = ca_address_sk\n  and c_birth_month in (1, 6, 8, 9, 12, 2)\n  and d_year = 1998\n  and ca_state in ('MS', 'IN', 'ND', 'OK', 'NM', 'VA', 'MS')\ngroup by rollup (i_item_id, ca_country, ca_state, ca_county)\norder by ca_country,\n         ca_state,\n         ca_county,\n         i_item_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query19.sql",
    "content": "select i_brand_id              brand_id,\n       i_brand                 brand,\n       i_manufact_id,\n       i_manufact,\n       sum(ss_ext_sales_price) ext_price\nfrom date_dim,\n     store_sales,\n     item,\n     customer,\n     customer_address,\n     store\nwhere d_date_sk = ss_sold_date_sk\n  and ss_item_sk = i_item_sk\n  and i_manager_id = 8\n  and d_moy = 11\n  and d_year = 1998\n  and ss_customer_sk = c_customer_sk\n  and c_current_addr_sk = ca_address_sk\n  and substr(ca_zip, 1, 5) <> substr(s_zip, 1, 5)\n  and ss_store_sk = s_store_sk\ngroup by i_brand\n       , i_brand_id\n       , i_manufact_id\n       , i_manufact\norder by ext_price desc\n       , i_brand\n       , i_brand_id\n       , i_manufact_id\n       , i_manufact limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query20.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , i_category\n     , i_class\n     , i_current_price\n     , sum(cs_ext_sales_price) as                                   itemrevenue\n     , sum(cs_ext_sales_price) * 100 / sum(sum(cs_ext_sales_price)) over (partition by i_class) as revenueratio\nfrom catalog_sales\n   , item\n   , date_dim\nwhere cs_item_sk = i_item_sk\n  and i_category in ('Sports', 'Books', 'Home')\n  and cs_sold_date_sk = d_date_sk\n  and d_date between cast('1999-02-22' as date)\n    and date_add(cast('1999-02-22' as date), 30)\ngroup by i_item_id\n       , i_item_desc\n       , i_category\n       , i_class\n       , i_current_price\norder by i_category\n       , i_class\n       , i_item_id\n       , i_item_desc\n       , revenueratio limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query21.sql",
    "content": "select *\nfrom (select w_warehouse_name\n           , i_item_id\n           , sum(case\n                     when (cast(d_date as date) < cast('2000-03-11' as date))\n                         then inv_quantity_on_hand\n                     else 0 end) as inv_before\n           , sum(case\n                     when (cast(d_date as date) >= cast('2000-03-11' as date))\n                         then inv_quantity_on_hand\n                     else 0 end) as inv_after\n      from inventory\n         , warehouse\n         , item\n         , date_dim\n      where i_current_price between 0.99 and 1.49\n        and i_item_sk = inv_item_sk\n        and inv_warehouse_sk = w_warehouse_sk\n        and inv_date_sk = d_date_sk\n        and d_date between date_sub(cast('2000-03-11' as date), 30)\n          and date_add(cast('2000-03-11' as date), 30)\n      group by w_warehouse_name, i_item_id) x\nwhere (case\n           when inv_before > 0\n               then inv_after / inv_before\n           else null\n    end) between 2.0 / 3.0 and 3.0 / 2.0\norder by w_warehouse_name\n       , i_item_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query22.sql",
    "content": "select i_product_name\n     , i_brand\n     , i_class\n     , i_category\n     , avg(inv_quantity_on_hand) qoh\nfrom inventory\n   , date_dim\n   , item\nwhere inv_date_sk = d_date_sk\n  and inv_item_sk = i_item_sk\n  and d_month_seq between 1200 and 1200 + 11\ngroup by rollup (i_product_name\n       , i_brand\n       , i_class\n       , i_category)\norder by qoh, i_product_name, i_brand, i_class, i_category limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query23.sql",
    "content": "with frequent_ss_items as\n         (select substr(i_item_desc, 1, 30) itemdesc, i_item_sk item_sk, d_date solddate, count(*) cnt\n          from store_sales\n             , date_dim\n             , item\n          where ss_sold_date_sk = d_date_sk\n            and ss_item_sk = i_item_sk\n            and d_year in (2000, 2000 + 1, 2000 + 2, 2000 + 3)\n          group by substr(i_item_desc, 1, 30), i_item_sk, d_date\n          having count(*) > 4),\n     max_store_sales as\n         (select max(csales) tpcds_cmax\n          from (select c_customer_sk, sum(ss_quantity * ss_sales_price) csales\n                from store_sales\n                   , customer\n                   , date_dim\n                where ss_customer_sk = c_customer_sk\n                  and ss_sold_date_sk = d_date_sk\n                  and d_year in (2000, 2000 + 1, 2000 + 2, 2000 + 3)\n                group by c_customer_sk)),\n     best_ss_customer as\n         (select c_customer_sk, sum(ss_quantity * ss_sales_price) ssales\n          from store_sales\n             , customer\n          where ss_customer_sk = c_customer_sk\n          group by c_customer_sk\n          having sum(ss_quantity * ss_sales_price) > (50 / 100.0) * (select *\n                                                                     from max_store_sales))\nselect sum(sales)\nfrom (select cs_quantity * cs_list_price sales\n      from catalog_sales\n         , date_dim\n      where d_year = 2000\n        and d_moy = 2\n        and cs_sold_date_sk = d_date_sk\n        and cs_item_sk in (select item_sk from frequent_ss_items)\n        and cs_bill_customer_sk in (select c_customer_sk from best_ss_customer)\n      union all\n      select ws_quantity * ws_list_price sales\n      from web_sales\n         , date_dim\n      where d_year = 2000\n        and d_moy = 2\n        and ws_sold_date_sk = d_date_sk\n        and ws_item_sk in (select item_sk from frequent_ss_items)\n        and ws_bill_customer_sk in (select c_customer_sk from best_ss_customer)) limit 100;\nwith frequent_ss_items as\n         (select substr(i_item_desc, 1, 30) itemdesc, i_item_sk item_sk, d_date solddate, count(*) cnt\n          from store_sales\n             , date_dim\n             , item\n          where ss_sold_date_sk = d_date_sk\n            and ss_item_sk = i_item_sk\n            and d_year in (2000, 2000 + 1, 2000 + 2, 2000 + 3)\n          group by substr(i_item_desc, 1, 30), i_item_sk, d_date\n          having count(*) > 4),\n     max_store_sales as\n         (select max(csales) tpcds_cmax\n          from (select c_customer_sk, sum(ss_quantity * ss_sales_price) csales\n                from store_sales\n                   , customer\n                   , date_dim\n                where ss_customer_sk = c_customer_sk\n                  and ss_sold_date_sk = d_date_sk\n                  and d_year in (2000, 2000 + 1, 2000 + 2, 2000 + 3)\n                group by c_customer_sk)),\n     best_ss_customer as\n         (select c_customer_sk, sum(ss_quantity * ss_sales_price) ssales\n          from store_sales\n             , customer\n          where ss_customer_sk = c_customer_sk\n          group by c_customer_sk\n          having sum(ss_quantity * ss_sales_price) > (50 / 100.0) * (select *\n                                                                     from max_store_sales))\nselect c_last_name, c_first_name, sales\nfrom (select c_last_name, c_first_name, sum(cs_quantity * cs_list_price) sales\n      from catalog_sales\n         , customer\n         , date_dim\n      where d_year = 2000\n        and d_moy = 2\n        and cs_sold_date_sk = d_date_sk\n        and cs_item_sk in (select item_sk from frequent_ss_items)\n        and cs_bill_customer_sk in (select c_customer_sk from best_ss_customer)\n        and cs_bill_customer_sk = c_customer_sk\n      group by c_last_name, c_first_name\n      union all\n      select c_last_name, c_first_name, sum(ws_quantity * ws_list_price) sales\n      from web_sales\n         , customer\n         , date_dim\n      where d_year = 2000\n        and d_moy = 2\n        and ws_sold_date_sk = d_date_sk\n        and ws_item_sk in (select item_sk from frequent_ss_items)\n        and ws_bill_customer_sk in (select c_customer_sk from best_ss_customer)\n        and ws_bill_customer_sk = c_customer_sk\n      group by c_last_name, c_first_name)\norder by c_last_name, c_first_name, sales limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query24.sql",
    "content": "with ssales as\n         (select c_last_name\n               , c_first_name\n               , s_store_name\n               , ca_state\n               , s_state\n               , i_color\n               , i_current_price\n               , i_manager_id\n               , i_units\n               , i_size\n               , sum(ss_net_paid) netpaid\n          from store_sales\n             , store_returns\n             , store\n             , item\n             , customer\n             , customer_address\n          where ss_ticket_number = sr_ticket_number\n            and ss_item_sk = sr_item_sk\n            and ss_customer_sk = c_customer_sk\n            and ss_item_sk = i_item_sk\n            and ss_store_sk = s_store_sk\n            and c_current_addr_sk = ca_address_sk\n            and c_birth_country <> upper(ca_country)\n            and s_zip = ca_zip\n            and s_market_id = 8\n          group by c_last_name\n                 , c_first_name\n                 , s_store_name\n                 , ca_state\n                 , s_state\n                 , i_color\n                 , i_current_price\n                 , i_manager_id\n                 , i_units\n                 , i_size)\nselect c_last_name\n     , c_first_name\n     , s_store_name\n     , sum(netpaid) paid\nfrom ssales\nwhere i_color = 'pale'\ngroup by c_last_name\n       , c_first_name\n       , s_store_name\nhaving sum(netpaid) > (select 0.05 * avg(netpaid)\n                       from ssales)\norder by c_last_name\n       , c_first_name\n       , s_store_name\n;\nwith ssales as\n         (select c_last_name\n               , c_first_name\n               , s_store_name\n               , ca_state\n               , s_state\n               , i_color\n               , i_current_price\n               , i_manager_id\n               , i_units\n               , i_size\n               , sum(ss_net_paid) netpaid\n          from store_sales\n             , store_returns\n             , store\n             , item\n             , customer\n             , customer_address\n          where ss_ticket_number = sr_ticket_number\n            and ss_item_sk = sr_item_sk\n            and ss_customer_sk = c_customer_sk\n            and ss_item_sk = i_item_sk\n            and ss_store_sk = s_store_sk\n            and c_current_addr_sk = ca_address_sk\n            and c_birth_country <> upper(ca_country)\n            and s_zip = ca_zip\n            and s_market_id = 8\n          group by c_last_name\n                 , c_first_name\n                 , s_store_name\n                 , ca_state\n                 , s_state\n                 , i_color\n                 , i_current_price\n                 , i_manager_id\n                 , i_units\n                 , i_size)\nselect c_last_name\n     , c_first_name\n     , s_store_name\n     , sum(netpaid) paid\nfrom ssales\nwhere i_color = 'chiffon'\ngroup by c_last_name\n       , c_first_name\n       , s_store_name\nhaving sum(netpaid) > (select 0.05 * avg(netpaid)\n                       from ssales)\norder by c_last_name\n       , c_first_name\n       , s_store_name\n\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query25.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , s_store_id\n     , s_store_name\n     , sum(ss_net_profit) as store_sales_profit\n     , sum(sr_net_loss)   as store_returns_loss\n     , sum(cs_net_profit) as catalog_sales_profit\nfrom store_sales\n   , store_returns\n   , catalog_sales\n   , date_dim d1\n   , date_dim d2\n   , date_dim d3\n   , store\n   , item\nwhere d1.d_moy = 4\n  and d1.d_year = 2001\n  and d1.d_date_sk = ss_sold_date_sk\n  and i_item_sk = ss_item_sk\n  and s_store_sk = ss_store_sk\n  and ss_customer_sk = sr_customer_sk\n  and ss_item_sk = sr_item_sk\n  and ss_ticket_number = sr_ticket_number\n  and sr_returned_date_sk = d2.d_date_sk\n  and d2.d_moy between 4 and 10\n  and d2.d_year = 2001\n  and sr_customer_sk = cs_bill_customer_sk\n  and sr_item_sk = cs_item_sk\n  and cs_sold_date_sk = d3.d_date_sk\n  and d3.d_moy between 4 and 10\n  and d3.d_year = 2001\ngroup by i_item_id\n       , i_item_desc\n       , s_store_id\n       , s_store_name\norder by i_item_id\n       , i_item_desc\n       , s_store_id\n       , s_store_name limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query26.sql",
    "content": "select i_item_id,\n       avg(cs_quantity)    agg1,\n       avg(cs_list_price)  agg2,\n       avg(cs_coupon_amt)  agg3,\n       avg(cs_sales_price) agg4\nfrom catalog_sales,\n     customer_demographics,\n     date_dim,\n     item,\n     promotion\nwhere cs_sold_date_sk = d_date_sk\n  and cs_item_sk = i_item_sk\n  and cs_bill_cdemo_sk = cd_demo_sk\n  and cs_promo_sk = p_promo_sk\n  and cd_gender = 'M'\n  and cd_marital_status = 'S'\n  and cd_education_status = 'College'\n  and (p_channel_email = 'N' or p_channel_event = 'N')\n  and d_year = 2000\ngroup by i_item_id\norder by i_item_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query27.sql",
    "content": "select i_item_id,\n       s_state,\n       grouping(s_state)   g_state,\n       avg(ss_quantity)    agg1,\n       avg(ss_list_price)  agg2,\n       avg(ss_coupon_amt)  agg3,\n       avg(ss_sales_price) agg4\nfrom store_sales,\n     customer_demographics,\n     date_dim,\n     store,\n     item\nwhere ss_sold_date_sk = d_date_sk\n  and ss_item_sk = i_item_sk\n  and ss_store_sk = s_store_sk\n  and ss_cdemo_sk = cd_demo_sk\n  and cd_gender = 'M'\n  and cd_marital_status = 'S'\n  and cd_education_status = 'College'\n  and d_year = 2002\n  and s_state in ('TN', 'TN', 'TN', 'TN', 'TN', 'TN')\ngroup by rollup (i_item_id, s_state)\norder by i_item_id\n       , s_state limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query28.sql",
    "content": "select *\nfrom (select avg(ss_list_price)            B1_LP\n           , count(ss_list_price)          B1_CNT\n           , count(distinct ss_list_price) B1_CNTD\n      from store_sales\n      where ss_quantity between 0 and 5\n        and (ss_list_price between 8 and 8 + 10\n          or ss_coupon_amt between 459 and 459 + 1000\n          or ss_wholesale_cost between 57 and 57 + 20)) B1,\n     (select avg(ss_list_price)            B2_LP\n           , count(ss_list_price)          B2_CNT\n           , count(distinct ss_list_price) B2_CNTD\n      from store_sales\n      where ss_quantity between 6 and 10\n        and (ss_list_price between 90 and 90 + 10\n          or ss_coupon_amt between 2323 and 2323 + 1000\n          or ss_wholesale_cost between 31 and 31 + 20)) B2,\n     (select avg(ss_list_price)            B3_LP\n           , count(ss_list_price)          B3_CNT\n           , count(distinct ss_list_price) B3_CNTD\n      from store_sales\n      where ss_quantity between 11 and 15\n        and (ss_list_price between 142 and 142 + 10\n          or ss_coupon_amt between 12214 and 12214 + 1000\n          or ss_wholesale_cost between 79 and 79 + 20)) B3,\n     (select avg(ss_list_price)            B4_LP\n           , count(ss_list_price)          B4_CNT\n           , count(distinct ss_list_price) B4_CNTD\n      from store_sales\n      where ss_quantity between 16 and 20\n        and (ss_list_price between 135 and 135 + 10\n          or ss_coupon_amt between 6071 and 6071 + 1000\n          or ss_wholesale_cost between 38 and 38 + 20)) B4,\n     (select avg(ss_list_price)            B5_LP\n           , count(ss_list_price)          B5_CNT\n           , count(distinct ss_list_price) B5_CNTD\n      from store_sales\n      where ss_quantity between 21 and 25\n        and (ss_list_price between 122 and 122 + 10\n          or ss_coupon_amt between 836 and 836 + 1000\n          or ss_wholesale_cost between 17 and 17 + 20)) B5,\n     (select avg(ss_list_price)            B6_LP\n           , count(ss_list_price)          B6_CNT\n           , count(distinct ss_list_price) B6_CNTD\n      from store_sales\n      where ss_quantity between 26 and 30\n        and (ss_list_price between 154 and 154 + 10\n          or ss_coupon_amt between 7326 and 7326 + 1000\n          or ss_wholesale_cost between 7 and 7 + 20)) B6 limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query29.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , s_store_id\n     , s_store_name\n     , sum(ss_quantity)        as store_sales_quantity\n     , sum(sr_return_quantity) as store_returns_quantity\n     , sum(cs_quantity)        as catalog_sales_quantity\nfrom store_sales\n   , store_returns\n   , catalog_sales\n   , date_dim d1\n   , date_dim d2\n   , date_dim d3\n   , store\n   , item\nwhere d1.d_moy = 9\n  and d1.d_year = 1999\n  and d1.d_date_sk = ss_sold_date_sk\n  and i_item_sk = ss_item_sk\n  and s_store_sk = ss_store_sk\n  and ss_customer_sk = sr_customer_sk\n  and ss_item_sk = sr_item_sk\n  and ss_ticket_number = sr_ticket_number\n  and sr_returned_date_sk = d2.d_date_sk\n  and d2.d_moy between 9 and 9 + 3\n  and d2.d_year = 1999\n  and sr_customer_sk = cs_bill_customer_sk\n  and sr_item_sk = cs_item_sk\n  and cs_sold_date_sk = d3.d_date_sk\n  and d3.d_year in (1999, 1999 + 1, 1999 + 2)\ngroup by i_item_id\n       , i_item_desc\n       , s_store_id\n       , s_store_name\norder by i_item_id\n       , i_item_desc\n       , s_store_id\n       , s_store_name limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query30.sql",
    "content": "with customer_total_return as\n         (select wr_returning_customer_sk as ctr_customer_sk\n                  ,\n                 ca_state                 as ctr_state,\n                 sum(wr_return_amt)       as ctr_total_return\n          from web_returns\n             , date_dim\n             , customer_address\n          where wr_returned_date_sk = d_date_sk\n            and d_year = 2002\n            and wr_returning_addr_sk = ca_address_sk\n          group by wr_returning_customer_sk\n                 , ca_state)\nselect c_customer_id\n     , c_salutation\n     , c_first_name\n     , c_last_name\n     , c_preferred_cust_flag\n     , c_birth_day\n     , c_birth_month\n     , c_birth_year\n     , c_birth_country\n     , c_login\n     , c_email_address\n     , c_last_review_date\n     , ctr_total_return\nfrom customer_total_return ctr1\n   , customer_address\n   , customer\nwhere ctr1.ctr_total_return > (select avg(ctr_total_return) * 1.2\n                               from customer_total_return ctr2\n                               where ctr1.ctr_state = ctr2.ctr_state)\n  and ca_address_sk = c_current_addr_sk\n  and ca_state = 'GA'\n  and ctr1.ctr_customer_sk = c_customer_sk\norder by c_customer_id, c_salutation, c_first_name, c_last_name, c_preferred_cust_flag\n       , c_birth_day, c_birth_month, c_birth_year, c_birth_country, c_login, c_email_address\n       , c_last_review_date, ctr_total_return limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query31.sql",
    "content": "with ss as\n         (select ca_county, d_qoy, d_year, sum(ss_ext_sales_price) as store_sales\n          from store_sales,\n               date_dim,\n               customer_address\n          where ss_sold_date_sk = d_date_sk\n            and ss_addr_sk = ca_address_sk\n          group by ca_county, d_qoy, d_year),\n     ws as\n         (select ca_county, d_qoy, d_year, sum(ws_ext_sales_price) as web_sales\n          from web_sales,\n               date_dim,\n               customer_address\n          where ws_sold_date_sk = d_date_sk\n            and ws_bill_addr_sk = ca_address_sk\n          group by ca_county, d_qoy, d_year)\nselect ss1.ca_county\n     , ss1.d_year\n     , ws2.web_sales / ws1.web_sales     web_q1_q2_increase\n     , ss2.store_sales / ss1.store_sales store_q1_q2_increase\n     , ws3.web_sales / ws2.web_sales     web_q2_q3_increase\n     , ss3.store_sales / ss2.store_sales store_q2_q3_increase\nfrom ss ss1\n   , ss ss2\n   , ss ss3\n   , ws ws1\n   , ws ws2\n   , ws ws3\nwhere ss1.d_qoy = 1\n  and ss1.d_year = 2000\n  and ss1.ca_county = ss2.ca_county\n  and ss2.d_qoy = 2\n  and ss2.d_year = 2000\n  and ss2.ca_county = ss3.ca_county\n  and ss3.d_qoy = 3\n  and ss3.d_year = 2000\n  and ss1.ca_county = ws1.ca_county\n  and ws1.d_qoy = 1\n  and ws1.d_year = 2000\n  and ws1.ca_county = ws2.ca_county\n  and ws2.d_qoy = 2\n  and ws2.d_year = 2000\n  and ws1.ca_county = ws3.ca_county\n  and ws3.d_qoy = 3\n  and ws3.d_year = 2000\n  and case when ws1.web_sales > 0 then ws2.web_sales / ws1.web_sales else null end\n    > case when ss1.store_sales > 0 then ss2.store_sales / ss1.store_sales else null end\n  and case when ws2.web_sales > 0 then ws3.web_sales / ws2.web_sales else null end\n    > case when ss2.store_sales > 0 then ss3.store_sales / ss2.store_sales else null end\norder by ss1.ca_county\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query32.sql",
    "content": "select sum(cs_ext_discount_amt) as excess_discount_amount\nfrom catalog_sales\n   , item\n   , date_dim\nwhere i_manufact_id = 977\n  and i_item_sk = cs_item_sk\n  and d_date between '2000-01-27' and\n    date_add(cast('2000-01-27' as date), 90)\n  and d_date_sk = cs_sold_date_sk\n  and cs_ext_discount_amt\n    > (select 1.3 * avg(cs_ext_discount_amt)\n       from catalog_sales\n          , date_dim\n       where cs_item_sk = i_item_sk\n         and d_date between '2000-01-27' and\n           date_add(cast('2000-01-27' as date), 90)\n         and d_date_sk = cs_sold_date_sk)\n    limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query33.sql",
    "content": "with ss as (select i_manufact_id,\n                   sum(ss_ext_sales_price) total_sales\n            from store_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_manufact_id in (select i_manufact_id\n                                    from item\n                                    where i_category in ('Electronics'))\n              and ss_item_sk = i_item_sk\n              and ss_sold_date_sk = d_date_sk\n              and d_year = 1998\n              and d_moy = 5\n              and ss_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_manufact_id),\n     cs as (select i_manufact_id,\n                   sum(cs_ext_sales_price) total_sales\n            from catalog_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_manufact_id in (select i_manufact_id\n                                    from item\n                                    where i_category in ('Electronics'))\n              and cs_item_sk = i_item_sk\n              and cs_sold_date_sk = d_date_sk\n              and d_year = 1998\n              and d_moy = 5\n              and cs_bill_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_manufact_id),\n     ws as (select i_manufact_id,\n                   sum(ws_ext_sales_price) total_sales\n            from web_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_manufact_id in (select i_manufact_id\n                                    from item\n                                    where i_category in ('Electronics'))\n              and ws_item_sk = i_item_sk\n              and ws_sold_date_sk = d_date_sk\n              and d_year = 1998\n              and d_moy = 5\n              and ws_bill_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_manufact_id)\nselect i_manufact_id, sum(total_sales) total_sales\nfrom (select *\n      from ss\n      union all\n      select *\n      from cs\n      union all\n      select *\n      from ws) tmp1\ngroup by i_manufact_id\norder by total_sales limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query34.sql",
    "content": "select c_last_name\n     , c_first_name\n     , c_salutation\n     , c_preferred_cust_flag\n     , ss_ticket_number\n     , cnt\nfrom (select ss_ticket_number\n           , ss_customer_sk\n           , count(*) cnt\n      from store_sales,\n           date_dim,\n           store,\n           household_demographics\n      where store_sales.ss_sold_date_sk = date_dim.d_date_sk\n        and store_sales.ss_store_sk = store.s_store_sk\n        and store_sales.ss_hdemo_sk = household_demographics.hd_demo_sk\n        and (date_dim.d_dom between 1 and 3 or date_dim.d_dom between 25 and 28)\n        and (household_demographics.hd_buy_potential = '>10000' or\n             household_demographics.hd_buy_potential = 'Unknown')\n        and household_demographics.hd_vehicle_count > 0\n        and (case\n                 when household_demographics.hd_vehicle_count > 0\n                     then household_demographics.hd_dep_count / household_demographics.hd_vehicle_count\n                 else null\n          end) > 1.2\n        and date_dim.d_year in (1999, 1999 + 1, 1999 + 2)\n        and store.s_county in ('Williamson County', 'Williamson County', 'Williamson County', 'Williamson County',\n                               'Williamson County', 'Williamson County', 'Williamson County', 'Williamson County')\n      group by ss_ticket_number, ss_customer_sk) dn,\n     customer\nwhere ss_customer_sk = c_customer_sk\n  and cnt between 15 and 20\norder by c_last_name, c_first_name, c_salutation, c_preferred_cust_flag desc, ss_ticket_number\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query35.sql",
    "content": "select ca_state,\n       cd_gender,\n       cd_marital_status,\n       cd_dep_count,\n       count(*) cnt1,\n       min(cd_dep_count),\n       max(cd_dep_count),\n       avg(cd_dep_count),\n       cd_dep_employed_count,\n       count(*) cnt2,\n       min(cd_dep_employed_count),\n       max(cd_dep_employed_count),\n       avg(cd_dep_employed_count),\n       cd_dep_college_count,\n       count(*) cnt3,\n       min(cd_dep_college_count),\n       max(cd_dep_college_count),\n       avg(cd_dep_college_count)\nfrom customer c,\n     customer_address ca,\n     customer_demographics\nwhere c.c_current_addr_sk = ca.ca_address_sk\n  and cd_demo_sk = c.c_current_cdemo_sk\n  and exists(select *\n             from store_sales,\n                  date_dim\n             where c.c_customer_sk = ss_customer_sk\n               and ss_sold_date_sk = d_date_sk\n               and d_year = 2002\n               and d_qoy < 4)\n  and (exists(select *\n              from web_sales,\n                   date_dim\n              where c.c_customer_sk = ws_bill_customer_sk\n                and ws_sold_date_sk = d_date_sk\n                and d_year = 2002\n                and d_qoy < 4) or\n       exists(select *\n              from catalog_sales,\n                   date_dim\n              where c.c_customer_sk = cs_ship_customer_sk\n                and cs_sold_date_sk = d_date_sk\n                and d_year = 2002\n                and d_qoy < 4))\ngroup by ca_state,\n         cd_gender,\n         cd_marital_status,\n         cd_dep_count,\n         cd_dep_employed_count,\n         cd_dep_college_count\norder by ca_state,\n         cd_gender,\n         cd_marital_status,\n         cd_dep_count,\n         cd_dep_employed_count,\n         cd_dep_college_count limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query36.sql",
    "content": "select sum(ss_net_profit) / sum(ss_ext_sales_price) as gross_margin\n     , i_category\n     , i_class\n     , grouping(i_category) + grouping(i_class)     as lochierarchy\n     , rank()                                          over (\n \tpartition by grouping(i_category)+grouping(i_class),\n \tcase when grouping(i_class) = 0 then i_category end \n \torder by sum(ss_net_profit)/sum(ss_ext_sales_price) asc) as rank_within_parent\nfrom store_sales\n   , date_dim d1\n   , item\n   , store\nwhere d1.d_year = 2001\n  and d1.d_date_sk = ss_sold_date_sk\n  and i_item_sk = ss_item_sk\n  and s_store_sk = ss_store_sk\n  and s_state in ('TN', 'TN', 'TN', 'TN',\n                  'TN', 'TN', 'TN', 'TN')\ngroup by rollup (i_category, i_class)\norder by lochierarchy desc\n       , case when lochierarchy = 0 then i_category end\n       , rank_within_parent limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query37.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , i_current_price\nfrom item,\n     inventory,\n     date_dim,\n     catalog_sales\nwhere i_current_price between 68 and 68 + 30\n  and inv_item_sk = i_item_sk\n  and d_date_sk = inv_date_sk\n  and d_date between cast('2000-02-01' as date) and date_add(cast('2000-02-01' as date), 60)\n  and i_manufact_id in (677, 940, 694, 808)\n  and inv_quantity_on_hand between 100 and 500\n  and cs_item_sk = i_item_sk\ngroup by i_item_id, i_item_desc, i_current_price\norder by i_item_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query38.sql",
    "content": "select count(*)\nfrom (select distinct c_last_name, c_first_name, d_date\n      from store_sales,\n           date_dim,\n           customer\n      where store_sales.ss_sold_date_sk = date_dim.d_date_sk\n        and store_sales.ss_customer_sk = customer.c_customer_sk\n        and d_month_seq between 1200 and 1200 + 11\n      intersect\n      select distinct c_last_name, c_first_name, d_date\n      from catalog_sales,\n           date_dim,\n           customer\n      where catalog_sales.cs_sold_date_sk = date_dim.d_date_sk\n        and catalog_sales.cs_bill_customer_sk = customer.c_customer_sk\n        and d_month_seq between 1200 and 1200 + 11\n      intersect\n      select distinct c_last_name, c_first_name, d_date\n      from web_sales,\n           date_dim,\n           customer\n      where web_sales.ws_sold_date_sk = date_dim.d_date_sk\n        and web_sales.ws_bill_customer_sk = customer.c_customer_sk\n        and d_month_seq between 1200 and 1200 + 11) hot_cust limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query39.sql",
    "content": "with inv as\n         (select w_warehouse_name\n               , w_warehouse_sk\n               , i_item_sk\n               , d_moy\n               , stdev\n               , mean\n               , case mean when 0 then null else stdev / mean end cov\n          from (select w_warehouse_name\n                     , w_warehouse_sk\n                     , i_item_sk\n                     , d_moy\n                     , stddev_samp(inv_quantity_on_hand) stdev\n                     , avg(inv_quantity_on_hand)         mean\n                from inventory\n                   , item\n                   , warehouse\n                   , date_dim\n                where inv_item_sk = i_item_sk\n                  and inv_warehouse_sk = w_warehouse_sk\n                  and inv_date_sk = d_date_sk\n                  and d_year = 2001\n                group by w_warehouse_name, w_warehouse_sk, i_item_sk, d_moy) foo\n          where case mean when 0 then 0 else stdev / mean end > 1)\nselect inv1.w_warehouse_sk\n     , inv1.i_item_sk\n     , inv1.d_moy\n     , inv1.mean\n     , inv1.cov\n     , inv2.w_warehouse_sk as w_warehouse_sk_2\n     , inv2.i_item_sk      as i_item_sk_2\n     , inv2.d_moy          as d_moy_2\n     , inv2.mean           as mean_2\n     , inv2.cov            as cov_2\nfrom inv inv1,\n     inv inv2\nwhere inv1.i_item_sk = inv2.i_item_sk\n  and inv1.w_warehouse_sk = inv2.w_warehouse_sk\n  and inv1.d_moy = 1\n  and inv2.d_moy = 1 + 1\norder by inv1.w_warehouse_sk, inv1.i_item_sk, inv1.d_moy, inv1.mean, inv1.cov\n       , d_moy_2, mean_2, cov_2\n;\nwith inv as\n         (select w_warehouse_name\n               , w_warehouse_sk\n               , i_item_sk\n               , d_moy\n               , stdev\n               , mean\n               , case mean when 0 then null else stdev / mean end cov\n          from (select w_warehouse_name\n                     , w_warehouse_sk\n                     , i_item_sk\n                     , d_moy\n                     , stddev_samp(inv_quantity_on_hand) stdev\n                     , avg(inv_quantity_on_hand)         mean\n                from inventory\n                   , item\n                   , warehouse\n                   , date_dim\n                where inv_item_sk = i_item_sk\n                  and inv_warehouse_sk = w_warehouse_sk\n                  and inv_date_sk = d_date_sk\n                  and d_year = 2001\n                group by w_warehouse_name, w_warehouse_sk, i_item_sk, d_moy) foo\n          where case mean when 0 then 0 else stdev / mean end > 1)\nselect inv1.w_warehouse_sk\n     , inv1.i_item_sk\n     , inv1.d_moy\n     , inv1.mean\n     , inv1.cov\n     , inv2.w_warehouse_sk as w_warehouse_sk_2\n     , inv2.i_item_sk      as i_item_sk_2\n     , inv2.d_moy          as d_moy_2\n     , inv2.mean           as mean_2\n     , inv2.cov            as cov_2\nfrom inv inv1,\n     inv inv2\nwhere inv1.i_item_sk = inv2.i_item_sk\n  and inv1.w_warehouse_sk = inv2.w_warehouse_sk\n  and inv1.d_moy = 1\n  and inv2.d_moy = 1 + 1\n  and inv1.cov > 1.5\norder by inv1.w_warehouse_sk, inv1.i_item_sk, inv1.d_moy, inv1.mean, inv1.cov\n       , d_moy_2, mean_2, cov_2\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query40.sql",
    "content": "select w_state\n     , i_item_id\n     , sum(case\n               when (cast(d_date as date) < cast('2000-03-11' as date))\n                   then cs_sales_price - coalesce(cr_refunded_cash, 0)\n               else 0 end) as sales_before\n     , sum(case\n               when (cast(d_date as date) >= cast('2000-03-11' as date))\n                   then cs_sales_price - coalesce(cr_refunded_cash, 0)\n               else 0 end) as sales_after\nfrom catalog_sales\n         left outer join catalog_returns on\n    (cs_order_number = cr_order_number\n        and cs_item_sk = cr_item_sk)\n   , warehouse\n   , item\n   , date_dim\nwhere i_current_price between 0.99 and 1.49\n  and i_item_sk = cs_item_sk\n  and cs_warehouse_sk = w_warehouse_sk\n  and cs_sold_date_sk = d_date_sk\n  and d_date between date_sub(cast('2000-03-11' as date), 30)\n    and date_add(cast('2000-03-11' as date), 30)\ngroup by w_state, i_item_id\norder by w_state, i_item_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query41.sql",
    "content": "select distinct(i_product_name)\nfrom item i1\nwhere i_manufact_id between 738 and 738 + 40\n  and (select count(*) as item_cnt\n       from item\n       where (i_manufact = i1.i_manufact and\n              ((i_category = 'Women' and\n                (i_color = 'powder' or i_color = 'khaki') and\n                (i_units = 'Ounce' or i_units = 'Oz') and\n                (i_size = 'medium' or i_size = 'extra large')\n                   ) or\n               (i_category = 'Women' and\n                (i_color = 'brown' or i_color = 'honeydew') and\n                (i_units = 'Bunch' or i_units = 'Ton') and\n                (i_size = 'N/A' or i_size = 'small')\n                   ) or\n               (i_category = 'Men' and\n                (i_color = 'floral' or i_color = 'deep') and\n                (i_units = 'N/A' or i_units = 'Dozen') and\n                (i_size = 'petite' or i_size = 'large')\n                   ) or\n               (i_category = 'Men' and\n                (i_color = 'light' or i_color = 'cornflower') and\n                (i_units = 'Box' or i_units = 'Pound') and\n                (i_size = 'medium' or i_size = 'extra large')\n                   )))\n          or (i_manufact = i1.i_manufact and\n              ((i_category = 'Women' and\n                (i_color = 'midnight' or i_color = 'snow') and\n                (i_units = 'Pallet' or i_units = 'Gross') and\n                (i_size = 'medium' or i_size = 'extra large')\n                   ) or\n               (i_category = 'Women' and\n                (i_color = 'cyan' or i_color = 'papaya') and\n                (i_units = 'Cup' or i_units = 'Dram') and\n                (i_size = 'N/A' or i_size = 'small')\n                   ) or\n               (i_category = 'Men' and\n                (i_color = 'orange' or i_color = 'frosted') and\n                (i_units = 'Each' or i_units = 'Tbl') and\n                (i_size = 'petite' or i_size = 'large')\n                   ) or\n               (i_category = 'Men' and\n                (i_color = 'forest' or i_color = 'ghost') and\n                (i_units = 'Lb' or i_units = 'Bundle') and\n                (i_size = 'medium' or i_size = 'extra large')\n                   )))) > 0\norder by i_product_name limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query42.sql",
    "content": "select dt.d_year\n     , item.i_category_id\n     , item.i_category\n     , sum(ss_ext_sales_price)\nfrom date_dim dt\n   , store_sales\n   , item\nwhere dt.d_date_sk = store_sales.ss_sold_date_sk\n  and store_sales.ss_item_sk = item.i_item_sk\n  and item.i_manager_id = 1\n  and dt.d_moy = 11\n  and dt.d_year = 2000\ngroup by dt.d_year\n       , item.i_category_id\n       , item.i_category\norder by sum(ss_ext_sales_price) desc, dt.d_year\n       , item.i_category_id\n       , item.i_category limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query43.sql",
    "content": "select s_store_name,\n       s_store_id,\n       sum(case when (d_day_name = 'Sunday') then ss_sales_price else null end)    sun_sales,\n       sum(case when (d_day_name = 'Monday') then ss_sales_price else null end)    mon_sales,\n       sum(case when (d_day_name = 'Tuesday') then ss_sales_price else null end)   tue_sales,\n       sum(case when (d_day_name = 'Wednesday') then ss_sales_price else null end) wed_sales,\n       sum(case when (d_day_name = 'Thursday') then ss_sales_price else null end)  thu_sales,\n       sum(case when (d_day_name = 'Friday') then ss_sales_price else null end)    fri_sales,\n       sum(case when (d_day_name = 'Saturday') then ss_sales_price else null end)  sat_sales\nfrom date_dim,\n     store_sales,\n     store\nwhere d_date_sk = ss_sold_date_sk\n  and s_store_sk = ss_store_sk\n  and s_gmt_offset = -5\n  and d_year = 2000\ngroup by s_store_name, s_store_id\norder by s_store_name, s_store_id, sun_sales, mon_sales, tue_sales, wed_sales, thu_sales, fri_sales, sat_sales limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query44.sql",
    "content": "select asceding.rnk, i1.i_product_name best_performing, i2.i_product_name worst_performing\nfrom (select *\n      from (select item_sk, rank() over (order by rank_col asc) rnk\n            from (select ss_item_sk item_sk, avg(ss_net_profit) rank_col\n                  from store_sales ss1\n                  where ss_store_sk = 4\n                  group by ss_item_sk\n                  having avg(ss_net_profit) > 0.9 * (select avg(ss_net_profit) rank_col\n                                                     from store_sales\n                                                     where ss_store_sk = 4\n                                                       and ss_addr_sk is null\n                                                     group by ss_store_sk)) V1) V11\n      where rnk < 11) asceding,\n     (select *\n      from (select item_sk, rank() over (order by rank_col desc) rnk\n            from (select ss_item_sk item_sk, avg(ss_net_profit) rank_col\n                  from store_sales ss1\n                  where ss_store_sk = 4\n                  group by ss_item_sk\n                  having avg(ss_net_profit) > 0.9 * (select avg(ss_net_profit) rank_col\n                                                     from store_sales\n                                                     where ss_store_sk = 4\n                                                       and ss_addr_sk is null\n                                                     group by ss_store_sk)) V2) V21\n      where rnk < 11) descending,\n     item i1,\n     item i2\nwhere asceding.rnk = descending.rnk\n  and i1.i_item_sk = asceding.item_sk\n  and i2.i_item_sk = descending.item_sk\norder by asceding.rnk limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query45.sql",
    "content": "select ca_zip, ca_city, sum(ws_sales_price)\nfrom web_sales,\n     customer,\n     customer_address,\n     date_dim,\n     item\nwhere ws_bill_customer_sk = c_customer_sk\n  and c_current_addr_sk = ca_address_sk\n  and ws_item_sk = i_item_sk\n  and (substr(ca_zip, 1, 5) in ('85669', '86197', '88274', '83405', '86475', '85392', '85460', '80348', '81792')\n    or\n       i_item_id in (select i_item_id\n                     from item\n                     where i_item_sk in (2, 3, 5, 7, 11, 13, 17, 19, 23, 29))\n    )\n  and ws_sold_date_sk = d_date_sk\n  and d_qoy = 2\n  and d_year = 2001\ngroup by ca_zip, ca_city\norder by ca_zip, ca_city limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query46.sql",
    "content": "select c_last_name\n     , c_first_name\n     , ca_city\n     , bought_city\n     , ss_ticket_number\n     , amt\n     , profit\nfrom (select ss_ticket_number\n           , ss_customer_sk\n           , ca_city            bought_city\n           , sum(ss_coupon_amt) amt\n           , sum(ss_net_profit) profit\n      from store_sales,\n           date_dim,\n           store,\n           household_demographics,\n           customer_address\n      where store_sales.ss_sold_date_sk = date_dim.d_date_sk\n        and store_sales.ss_store_sk = store.s_store_sk\n        and store_sales.ss_hdemo_sk = household_demographics.hd_demo_sk\n        and store_sales.ss_addr_sk = customer_address.ca_address_sk\n        and (household_demographics.hd_dep_count = 4 or\n             household_demographics.hd_vehicle_count = 3)\n        and date_dim.d_dow in (6, 0)\n        and date_dim.d_year in (1999, 1999 + 1, 1999 + 2)\n        and store.s_city in ('Fairview', 'Midway', 'Fairview', 'Fairview', 'Fairview')\n      group by ss_ticket_number, ss_customer_sk, ss_addr_sk, ca_city) dn,\n     customer,\n     customer_address current_addr\nwhere ss_customer_sk = c_customer_sk\n  and customer.c_current_addr_sk = current_addr.ca_address_sk\n  and current_addr.ca_city <> bought_city\norder by c_last_name\n       , c_first_name\n       , ca_city\n       , bought_city\n       , ss_ticket_number limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query47.sql",
    "content": "with v1 as (select i_category,\n                   i_brand,\n                   s_store_name,\n                   s_company_name,\n                   d_year,\n                   d_moy,\n                   sum(ss_sales_price)      sum_sales,\n                   avg(sum(ss_sales_price)) over (partition by i_category, i_brand,\n                     s_store_name, s_company_name, d_year)\n          avg_monthly_sales, rank() over (partition by i_category, i_brand,\n                     s_store_name, s_company_name\n           order by d_year, d_moy) rn\n            from item,\n                 store_sales,\n                 date_dim,\n                 store\n            where ss_item_sk = i_item_sk\n              and ss_sold_date_sk = d_date_sk\n              and ss_store_sk = s_store_sk\n              and (\n                        d_year = 1999 or\n                        (d_year = 1999 - 1 and d_moy = 12) or\n                        (d_year = 1999 + 1 and d_moy = 1)\n                )\n            group by i_category, i_brand,\n                     s_store_name, s_company_name,\n                     d_year, d_moy),\n     v2 as (select v1.i_category\n                 , v1.i_brand\n                 , v1.s_store_name\n                 , v1.s_company_name\n                 , v1.d_year\n                 , v1.d_moy\n                 , v1.avg_monthly_sales\n                 , v1.sum_sales\n                 , v1_lag.sum_sales  psum\n                 , v1_lead.sum_sales nsum\n            from v1,\n                 v1 v1_lag,\n                 v1 v1_lead\n            where v1.i_category = v1_lag.i_category\n              and v1.i_category = v1_lead.i_category\n              and v1.i_brand = v1_lag.i_brand\n              and v1.i_brand = v1_lead.i_brand\n              and v1.s_store_name = v1_lag.s_store_name\n              and v1.s_store_name = v1_lead.s_store_name\n              and v1.s_company_name = v1_lag.s_company_name\n              and v1.s_company_name = v1_lead.s_company_name\n              and v1.rn = v1_lag.rn + 1\n              and v1.rn = v1_lead.rn - 1)\nselect *\nfrom v2\nwhere d_year = 1999\n  and avg_monthly_sales > 0\n  and case when avg_monthly_sales > 0 then abs(sum_sales - avg_monthly_sales) / avg_monthly_sales else null end > 0.1\norder by sum_sales - avg_monthly_sales, 3 limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query48.sql",
    "content": "select sum(ss_quantity)\nfrom store_sales,\n     store,\n     customer_demographics,\n     customer_address,\n     date_dim\nwhere s_store_sk = ss_store_sk\n  and ss_sold_date_sk = d_date_sk\n  and d_year = 2000\n  and (\n        (\n                    cd_demo_sk = ss_cdemo_sk\n                and\n                    cd_marital_status = 'M'\n                and\n                    cd_education_status = '4 yr Degree'\n                and\n                    ss_sales_price between 100.00 and 150.00\n            )\n        or\n        (\n                    cd_demo_sk = ss_cdemo_sk\n                and\n                    cd_marital_status = 'D'\n                and\n                    cd_education_status = '2 yr Degree'\n                and\n                    ss_sales_price between 50.00 and 100.00\n            )\n        or\n        (\n                    cd_demo_sk = ss_cdemo_sk\n                and\n                    cd_marital_status = 'S'\n                and\n                    cd_education_status = 'College'\n                and\n                    ss_sales_price between 150.00 and 200.00\n            )\n    )\n  and (\n        (\n                    ss_addr_sk = ca_address_sk\n                and\n                    ca_country = 'United States'\n                and\n                    ca_state in ('CO', 'OH', 'TX')\n                and ss_net_profit between 0 and 2000\n            )\n        or\n        (ss_addr_sk = ca_address_sk\n            and\n         ca_country = 'United States'\n            and\n         ca_state in ('OR', 'MN', 'KY')\n            and ss_net_profit between 150 and 3000\n            )\n        or\n        (ss_addr_sk = ca_address_sk\n            and\n         ca_country = 'United States'\n            and\n         ca_state in ('VA', 'CA', 'MS')\n            and ss_net_profit between 50 and 25000\n            )\n    )\n\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query49.sql",
    "content": "select 'web' as channel\n     , web.item\n     , web.return_ratio\n     , web.return_rank\n     , web.currency_rank\nfrom (select item\n           , return_ratio\n           , currency_ratio\n           , rank() over (order by return_ratio) as return_rank\n \t,rank() over (order by currency_ratio) as currency_rank\n      from (select ws.ws_item_sk                                              as item\n                 , (cast(sum(coalesce(wr.wr_return_quantity, 0)) as decimal(15, 4)) /\n                    cast(sum(coalesce(ws.ws_quantity, 0)) as decimal(15, 4))) as return_ratio\n                 , (cast(sum(coalesce(wr.wr_return_amt, 0)) as decimal(15, 4)) /\n                    cast(sum(coalesce(ws.ws_net_paid, 0)) as decimal(15, 4))) as currency_ratio\n            from web_sales ws\n                     left outer join web_returns wr\n                                     on (ws.ws_order_number = wr.wr_order_number and\n                                         ws.ws_item_sk = wr.wr_item_sk)\n               , date_dim\n            where wr.wr_return_amt > 10000\n              and ws.ws_net_profit > 1\n              and ws.ws_net_paid > 0\n              and ws.ws_quantity > 0\n              and ws_sold_date_sk = d_date_sk\n              and d_year = 2001\n              and d_moy = 12\n            group by ws.ws_item_sk) in_web) web\nwhere (\n                  web.return_rank <= 10\n              or\n                  web.currency_rank <= 10\n          )\nunion\nselect 'catalog' as channel\n     , catalog.item\n     , catalog.return_ratio\n     , catalog.return_rank\n     , catalog.currency_rank\nfrom (select item\n           , return_ratio\n           , currency_ratio\n           , rank() over (order by return_ratio) as return_rank\n \t,rank() over (order by currency_ratio) as currency_rank\n      from (select cs.cs_item_sk                                              as item\n                 , (cast(sum(coalesce(cr.cr_return_quantity, 0)) as decimal(15, 4)) /\n                    cast(sum(coalesce(cs.cs_quantity, 0)) as decimal(15, 4))) as return_ratio\n                 , (cast(sum(coalesce(cr.cr_return_amount, 0)) as decimal(15, 4)) /\n                    cast(sum(coalesce(cs.cs_net_paid, 0)) as decimal(15, 4))) as currency_ratio\n            from catalog_sales cs\n                     left outer join catalog_returns cr\n                                     on (cs.cs_order_number = cr.cr_order_number and\n                                         cs.cs_item_sk = cr.cr_item_sk)\n               , date_dim\n            where cr.cr_return_amount > 10000\n              and cs.cs_net_profit > 1\n              and cs.cs_net_paid > 0\n              and cs.cs_quantity > 0\n              and cs_sold_date_sk = d_date_sk\n              and d_year = 2001\n              and d_moy = 12\n            group by cs.cs_item_sk) in_cat) catalog\nwhere\n    (\n    catalog.return_rank <= 10\n   or\n    catalog.currency_rank <=10\n    )\nunion\nselect 'store' as channel\n     , store.item\n     , store.return_ratio\n     , store.return_rank\n     , store.currency_rank\nfrom (select item\n           , return_ratio\n           , currency_ratio\n           , rank() over (order by return_ratio) as return_rank\n \t,rank() over (order by currency_ratio) as currency_rank\n      from (select sts.ss_item_sk                                              as item\n                 , (cast(sum(coalesce(sr.sr_return_quantity, 0)) as decimal(15, 4)) /\n                    cast(sum(coalesce(sts.ss_quantity, 0)) as decimal(15, 4))) as return_ratio\n                 , (cast(sum(coalesce(sr.sr_return_amt, 0)) as decimal(15, 4)) /\n                    cast(sum(coalesce(sts.ss_net_paid, 0)) as decimal(15, 4))) as currency_ratio\n            from store_sales sts\n                     left outer join store_returns sr\n                                     on (sts.ss_ticket_number = sr.sr_ticket_number and sts.ss_item_sk = sr.sr_item_sk)\n               , date_dim\n            where sr.sr_return_amt > 10000\n              and sts.ss_net_profit > 1\n              and sts.ss_net_paid > 0\n              and sts.ss_quantity > 0\n              and ss_sold_date_sk = d_date_sk\n              and d_year = 2001\n              and d_moy = 12\n            group by sts.ss_item_sk) in_store) store\nwhere (\n                  store.return_rank <= 10\n              or\n                  store.currency_rank <= 10\n          )\norder by 1, 4, 5 limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query50.sql",
    "content": "select s_store_name\n     , s_company_id\n     , s_street_number\n     , s_street_name\n     , s_street_type\n     , s_suite_number\n     , s_city\n     , s_county\n     , s_state\n     , s_zip\n     , sum(case when (sr_returned_date_sk - ss_sold_date_sk <= 30) then 1 else 0 end) as \"30_days\"\n     , sum(case\n               when (sr_returned_date_sk - ss_sold_date_sk > 30) and\n                    (sr_returned_date_sk - ss_sold_date_sk <= 60) then 1\n               else 0 end)                                                            as \"31_60_days\"\n     , sum(case\n               when (sr_returned_date_sk - ss_sold_date_sk > 60) and\n                    (sr_returned_date_sk - ss_sold_date_sk <= 90) then 1\n               else 0 end)                                                            as \"61_90_days\"\n     , sum(case\n               when (sr_returned_date_sk - ss_sold_date_sk > 90) and\n                    (sr_returned_date_sk - ss_sold_date_sk <= 120) then 1\n               else 0 end)                                                            as \"91_120_days\"\n     , sum(case when (sr_returned_date_sk - ss_sold_date_sk > 120) then 1 else 0 end) as above120_days\nfrom store_sales\n   , store_returns\n   , store\n   , date_dim d1\n   , date_dim d2\nwhere d2.d_year = 2001\n  and d2.d_moy = 8\n  and ss_ticket_number = sr_ticket_number\n  and ss_item_sk = sr_item_sk\n  and ss_sold_date_sk = d1.d_date_sk\n  and sr_returned_date_sk = d2.d_date_sk\n  and ss_customer_sk = sr_customer_sk\n  and ss_store_sk = s_store_sk\ngroup by s_store_name\n       , s_company_id\n       , s_street_number\n       , s_street_name\n       , s_street_type\n       , s_suite_number\n       , s_city\n       , s_county\n       , s_state\n       , s_zip\norder by s_store_name\n       , s_company_id\n       , s_street_number\n       , s_street_name\n       , s_street_type\n       , s_suite_number\n       , s_city\n       , s_county\n       , s_state\n       , s_zip limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query51.sql",
    "content": "WITH web_v1 as (select ws_item_sk item_sk,\n                       d_date,\n                       sum(sum(ws_sales_price))\n                                  over (partition by ws_item_sk order by d_date rows between unbounded preceding and current row) cume_sales\n                from web_sales\n                   , date_dim\n                where ws_sold_date_sk = d_date_sk\n                  and d_month_seq between 1200 and 1200 + 11\n                  and ws_item_sk is not NULL\n                group by ws_item_sk, d_date),\n     store_v1 as (select ss_item_sk item_sk,\n                         d_date,\n                         sum(sum(ss_sales_price))\n                                    over (partition by ss_item_sk order by d_date rows between unbounded preceding and current row) cume_sales\n                  from store_sales\n                     , date_dim\n                  where ss_sold_date_sk = d_date_sk\n                    and d_month_seq between 1200 and 1200 + 11\n                    and ss_item_sk is not NULL\n                  group by ss_item_sk, d_date)\nselect *\nfrom (select item_sk\n           , d_date\n           , web_sales\n           , store_sales\n           , max(web_sales)\n        over\n          (partition by item_sk order by d_date rows between unbounded preceding and current row) web_cumulative\n     ,max(store_sales)\n            over (partition by item_sk order by d_date rows between unbounded preceding and current row) store_cumulative\n      from (select case when web.item_sk is not null then web.item_sk else store.item_sk end item_sk\n                 , case when web.d_date is not null then web.d_date else store.d_date end    d_date\n                 , web.cume_sales                                                            web_sales\n                 , store.cume_sales                                                          store_sales\n            from web_v1 web\n                     full outer join store_v1 store on (web.item_sk = store.item_sk\n                and web.d_date = store.d_date)) x) y\nwhere web_cumulative > store_cumulative\norder by item_sk\n       , d_date limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query52.sql",
    "content": "select dt.d_year\n     , item.i_brand_id         brand_id\n     , item.i_brand            brand\n     , sum(ss_ext_sales_price) ext_price\nfrom date_dim dt\n   , store_sales\n   , item\nwhere dt.d_date_sk = store_sales.ss_sold_date_sk\n  and store_sales.ss_item_sk = item.i_item_sk\n  and item.i_manager_id = 1\n  and dt.d_moy = 11\n  and dt.d_year = 2000\ngroup by dt.d_year\n       , item.i_brand\n       , item.i_brand_id\norder by dt.d_year\n       , ext_price desc\n       , brand_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query53.sql",
    "content": "select *\nfrom (select i_manufact_id,\n             sum(ss_sales_price)      sum_sales,\n             avg(sum(ss_sales_price)) over (partition by i_manufact_id) avg_quarterly_sales\n      from item,\n           store_sales,\n           date_dim,\n           store\n      where ss_item_sk = i_item_sk\n        and ss_sold_date_sk = d_date_sk\n        and ss_store_sk = s_store_sk\n        and d_month_seq in\n            (1200, 1200 + 1, 1200 + 2, 1200 + 3, 1200 + 4, 1200 + 5, 1200 + 6, 1200 + 7, 1200 + 8, 1200 + 9, 1200 + 10,\n             1200 + 11)\n        and ((i_category in ('Books', 'Children', 'Electronics') and\n              i_class in ('personal', 'portable', 'reference', 'self-help') and\n              i_brand in ('scholaramalgamalg #14', 'scholaramalgamalg #7',\n                          'exportiunivamalg #9', 'scholaramalgamalg #9'))\n          or (i_category in ('Women', 'Music', 'Men') and\n              i_class in ('accessories', 'classical', 'fragrances', 'pants') and\n              i_brand in ('amalgimporto #1', 'edu packscholar #1', 'exportiimporto #1',\n                          'importoamalg #1')))\n      group by i_manufact_id, d_qoy) tmp1\nwhere case\n          when avg_quarterly_sales > 0\n              then abs(sum_sales - avg_quarterly_sales) / avg_quarterly_sales\n          else null end > 0.1\norder by avg_quarterly_sales,\n         sum_sales,\n         i_manufact_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query54.sql",
    "content": "with my_customers as (select distinct c_customer_sk\n                                    , c_current_addr_sk\n                      from (select cs_sold_date_sk     sold_date_sk,\n                                   cs_bill_customer_sk customer_sk,\n                                   cs_item_sk          item_sk\n                            from catalog_sales\n                            union all\n                            select ws_sold_date_sk     sold_date_sk,\n                                   ws_bill_customer_sk customer_sk,\n                                   ws_item_sk          item_sk\n                            from web_sales) cs_or_ws_sales,\n                           item,\n                           date_dim,\n                           customer\n                      where sold_date_sk = d_date_sk\n                        and item_sk = i_item_sk\n                        and i_category = 'Women'\n                        and i_class = 'maternity'\n                        and c_customer_sk = cs_or_ws_sales.customer_sk\n                        and d_moy = 12\n                        and d_year = 1998)\n   , my_revenue as (select c_customer_sk,\n                           sum(ss_ext_sales_price) as revenue\n                    from my_customers,\n                         store_sales,\n                         customer_address,\n                         store,\n                         date_dim\n                    where c_current_addr_sk = ca_address_sk\n                      and ca_county = s_county\n                      and ca_state = s_state\n                      and ss_sold_date_sk = d_date_sk\n                      and c_customer_sk = ss_customer_sk\n                      and d_month_seq between (select distinct d_month_seq + 1\n                                               from date_dim\n                                               where d_year = 1998\n                                                 and d_moy = 12)\n                        and (select distinct d_month_seq + 3\n                             from date_dim\n                             where d_year = 1998\n                               and d_moy = 12)\n                    group by c_customer_sk)\n   , segments as\n    (select cast((revenue / 50) as int) as segment\n     from my_revenue)\nselect segment, count(*) as num_customers, segment * 50 as segment_base\nfrom segments\ngroup by segment\norder by segment, num_customers limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query55.sql",
    "content": "select i_brand_id              brand_id,\n       i_brand                 brand,\n       sum(ss_ext_sales_price) ext_price\nfrom date_dim,\n     store_sales,\n     item\nwhere d_date_sk = ss_sold_date_sk\n  and ss_item_sk = i_item_sk\n  and i_manager_id = 28\n  and d_moy = 11\n  and d_year = 1999\ngroup by i_brand, i_brand_id\norder by ext_price desc, i_brand_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query56.sql",
    "content": "with ss as (select i_item_id, sum(ss_ext_sales_price) total_sales\n            from store_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_item_id in (select i_item_id\n                                from item\n                                where i_color in ('slate', 'blanched', 'burnished'))\n              and ss_item_sk = i_item_sk\n              and ss_sold_date_sk = d_date_sk\n              and d_year = 2001\n              and d_moy = 2\n              and ss_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_item_id),\n     cs as (select i_item_id, sum(cs_ext_sales_price) total_sales\n            from catalog_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_item_id in (select i_item_id\n                                from item\n                                where i_color in ('slate', 'blanched', 'burnished'))\n              and cs_item_sk = i_item_sk\n              and cs_sold_date_sk = d_date_sk\n              and d_year = 2001\n              and d_moy = 2\n              and cs_bill_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_item_id),\n     ws as (select i_item_id, sum(ws_ext_sales_price) total_sales\n            from web_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_item_id in (select i_item_id\n                                from item\n                                where i_color in ('slate', 'blanched', 'burnished'))\n              and ws_item_sk = i_item_sk\n              and ws_sold_date_sk = d_date_sk\n              and d_year = 2001\n              and d_moy = 2\n              and ws_bill_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_item_id)\nselect i_item_id, sum(total_sales) total_sales\nfrom (select *\n      from ss\n      union all\n      select *\n      from cs\n      union all\n      select *\n      from ws) tmp1\ngroup by i_item_id\norder by total_sales limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query57.sql",
    "content": "with v1 as (select i_category,\n                   i_brand,\n                   cc_name,\n                   d_year,\n                   d_moy,\n                   sum(cs_sales_price)      sum_sales,\n                   avg(sum(cs_sales_price)) over (partition by i_category, i_brand,\n                     cc_name, d_year)\n          avg_monthly_sales, rank() over (partition by i_category, i_brand,\n                     cc_name\n           order by d_year, d_moy) rn\n            from item,\n                 catalog_sales,\n                 date_dim,\n                 call_center\n            where cs_item_sk = i_item_sk\n              and cs_sold_date_sk = d_date_sk\n              and cc_call_center_sk = cs_call_center_sk\n              and (\n                        d_year = 1999 or\n                        (d_year = 1999 - 1 and d_moy = 12) or\n                        (d_year = 1999 + 1 and d_moy = 1)\n                )\n            group by i_category, i_brand,\n                     cc_name, d_year, d_moy),\n     v2 as (select v1.i_category\n                 , v1.i_brand\n                 , v1.cc_name\n                 , v1.d_year\n                 , v1.d_moy\n                 , v1.avg_monthly_sales\n                 , v1.sum_sales\n                 , v1_lag.sum_sales  psum\n                 , v1_lead.sum_sales nsum\n            from v1,\n                 v1 v1_lag,\n                 v1 v1_lead\n            where v1.i_category = v1_lag.i_category\n              and v1.i_category = v1_lead.i_category\n              and v1.i_brand = v1_lag.i_brand\n              and v1.i_brand = v1_lead.i_brand\n              and v1.cc_name = v1_lag.cc_name\n              and v1.cc_name = v1_lead.cc_name\n              and v1.rn = v1_lag.rn + 1\n              and v1.rn = v1_lead.rn - 1)\nselect *\nfrom v2\nwhere d_year = 1999\n  and avg_monthly_sales > 0\n  and case when avg_monthly_sales > 0 then abs(sum_sales - avg_monthly_sales) / avg_monthly_sales else null end > 0.1\norder by sum_sales - avg_monthly_sales, 3 limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query58.sql",
    "content": "with ss_items as\n         (select i_item_id               item_id\n               , sum(ss_ext_sales_price) ss_item_rev\n          from store_sales\n             , item\n             , date_dim\n          where ss_item_sk = i_item_sk\n            and d_date in (select d_date\n                           from date_dim\n                           where d_week_seq = (select d_week_seq\n                                               from date_dim\n                                               where d_date = '2000-01-03'))\n            and ss_sold_date_sk = d_date_sk\n          group by i_item_id),\n     cs_items as\n         (select i_item_id               item_id\n               , sum(cs_ext_sales_price) cs_item_rev\n          from catalog_sales\n             , item\n             , date_dim\n          where cs_item_sk = i_item_sk\n            and d_date in (select d_date\n                           from date_dim\n                           where d_week_seq = (select d_week_seq\n                                               from date_dim\n                                               where d_date = '2000-01-03'))\n            and cs_sold_date_sk = d_date_sk\n          group by i_item_id),\n     ws_items as\n         (select i_item_id               item_id\n               , sum(ws_ext_sales_price) ws_item_rev\n          from web_sales\n             , item\n             , date_dim\n          where ws_item_sk = i_item_sk\n            and d_date in (select d_date\n                           from date_dim\n                           where d_week_seq = (select d_week_seq\n                                               from date_dim\n                                               where d_date = '2000-01-03'))\n            and ws_sold_date_sk = d_date_sk\n          group by i_item_id)\nselect ss_items.item_id\n     , ss_item_rev\n     , ss_item_rev / ((ss_item_rev + cs_item_rev + ws_item_rev) / 3) * 100 ss_dev\n     , cs_item_rev\n     , cs_item_rev / ((ss_item_rev + cs_item_rev + ws_item_rev) / 3) * 100 cs_dev\n     , ws_item_rev\n     , ws_item_rev / ((ss_item_rev + cs_item_rev + ws_item_rev) / 3) * 100 ws_dev\n     , (ss_item_rev + cs_item_rev + ws_item_rev) / 3                       average\nfrom ss_items,\n     cs_items,\n     ws_items\nwhere ss_items.item_id = cs_items.item_id\n  and ss_items.item_id = ws_items.item_id\n  and ss_item_rev between 0.9 * cs_item_rev and 1.1 * cs_item_rev\n  and ss_item_rev between 0.9 * ws_item_rev and 1.1 * ws_item_rev\n  and cs_item_rev between 0.9 * ss_item_rev and 1.1 * ss_item_rev\n  and cs_item_rev between 0.9 * ws_item_rev and 1.1 * ws_item_rev\n  and ws_item_rev between 0.9 * ss_item_rev and 1.1 * ss_item_rev\n  and ws_item_rev between 0.9 * cs_item_rev and 1.1 * cs_item_rev\norder by item_id\n       , ss_item_rev limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query59.sql",
    "content": "with wss as\n         (select d_week_seq,\n                 ss_store_sk,\n                 sum(case when (d_day_name = 'Sunday') then ss_sales_price else null end)    sun_sales,\n                 sum(case when (d_day_name = 'Monday') then ss_sales_price else null end)    mon_sales,\n                 sum(case when (d_day_name = 'Tuesday') then ss_sales_price else null end)   tue_sales,\n                 sum(case when (d_day_name = 'Wednesday') then ss_sales_price else null end) wed_sales,\n                 sum(case when (d_day_name = 'Thursday') then ss_sales_price else null end)  thu_sales,\n                 sum(case when (d_day_name = 'Friday') then ss_sales_price else null end)    fri_sales,\n                 sum(case when (d_day_name = 'Saturday') then ss_sales_price else null end)  sat_sales\n          from store_sales,\n               date_dim\n          where d_date_sk = ss_sold_date_sk\n          group by d_week_seq, ss_store_sk)\nselect s_store_name1\n     , s_store_id1\n     , d_week_seq1\n     , sun_sales1 / sun_sales2\n     , mon_sales1 / mon_sales2\n     , tue_sales1 / tue_sales2\n     , wed_sales1 / wed_sales2\n     , thu_sales1 / thu_sales2\n     , fri_sales1 / fri_sales2\n     , sat_sales1 / sat_sales2\nfrom (select s_store_name   s_store_name1\n           , wss.d_week_seq d_week_seq1\n           , s_store_id     s_store_id1\n           , sun_sales      sun_sales1\n           , mon_sales      mon_sales1\n           , tue_sales      tue_sales1\n           , wed_sales      wed_sales1\n           , thu_sales      thu_sales1\n           , fri_sales      fri_sales1\n           , sat_sales      sat_sales1\n      from wss,\n           store,\n           date_dim d\n      where d.d_week_seq = wss.d_week_seq\n        and ss_store_sk = s_store_sk\n        and d_month_seq between 1212 and 1212 + 11) y,\n     (select s_store_name   s_store_name2\n           , wss.d_week_seq d_week_seq2\n           , s_store_id     s_store_id2\n           , sun_sales      sun_sales2\n           , mon_sales      mon_sales2\n           , tue_sales      tue_sales2\n           , wed_sales      wed_sales2\n           , thu_sales      thu_sales2\n           , fri_sales      fri_sales2\n           , sat_sales      sat_sales2\n      from wss,\n           store,\n           date_dim d\n      where d.d_week_seq = wss.d_week_seq\n        and ss_store_sk = s_store_sk\n        and d_month_seq between 1212 + 12 and 1212 + 23) x\nwhere s_store_id1 = s_store_id2\n  and d_week_seq1 = d_week_seq2 - 52\norder by s_store_name1, s_store_id1, d_week_seq1 limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query60.sql",
    "content": "with ss as (select i_item_id,\n                   sum(ss_ext_sales_price) total_sales\n            from store_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_item_id in (select i_item_id\n                                from item\n                                where i_category in ('Music'))\n              and ss_item_sk = i_item_sk\n              and ss_sold_date_sk = d_date_sk\n              and d_year = 1998\n              and d_moy = 9\n              and ss_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_item_id),\n     cs as (select i_item_id,\n                   sum(cs_ext_sales_price) total_sales\n            from catalog_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_item_id in (select i_item_id\n                                from item\n                                where i_category in ('Music'))\n              and cs_item_sk = i_item_sk\n              and cs_sold_date_sk = d_date_sk\n              and d_year = 1998\n              and d_moy = 9\n              and cs_bill_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_item_id),\n     ws as (select i_item_id,\n                   sum(ws_ext_sales_price) total_sales\n            from web_sales,\n                 date_dim,\n                 customer_address,\n                 item\n            where i_item_id in (select i_item_id\n                                from item\n                                where i_category in ('Music'))\n              and ws_item_sk = i_item_sk\n              and ws_sold_date_sk = d_date_sk\n              and d_year = 1998\n              and d_moy = 9\n              and ws_bill_addr_sk = ca_address_sk\n              and ca_gmt_offset = -5\n            group by i_item_id)\nselect i_item_id\n     , sum(total_sales) total_sales\nfrom (select *\n      from ss\n      union all\n      select *\n      from cs\n      union all\n      select *\n      from ws) tmp1\ngroup by i_item_id\norder by i_item_id\n       , total_sales limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query61.sql",
    "content": "select promotions, total, cast(promotions as decimal(15, 4)) / cast(total as decimal(15, 4)) * 100\nfrom (select sum(ss_ext_sales_price) promotions\n      from store_sales\n         , store\n         , promotion\n         , date_dim\n         , customer\n         , customer_address\n         , item\n      where ss_sold_date_sk = d_date_sk\n        and ss_store_sk = s_store_sk\n        and ss_promo_sk = p_promo_sk\n        and ss_customer_sk = c_customer_sk\n        and ca_address_sk = c_current_addr_sk\n        and ss_item_sk = i_item_sk\n        and ca_gmt_offset = -5\n        and i_category = 'Jewelry'\n        and (p_channel_dmail = 'Y' or p_channel_email = 'Y' or p_channel_tv = 'Y')\n        and s_gmt_offset = -5\n        and d_year = 1998\n        and d_moy = 11) promotional_sales,\n     (select sum(ss_ext_sales_price) total\n      from store_sales\n         , store\n         , date_dim\n         , customer\n         , customer_address\n         , item\n      where ss_sold_date_sk = d_date_sk\n        and ss_store_sk = s_store_sk\n        and ss_customer_sk = c_customer_sk\n        and ca_address_sk = c_current_addr_sk\n        and ss_item_sk = i_item_sk\n        and ca_gmt_offset = -5\n        and i_category = 'Jewelry'\n        and s_gmt_offset = -5\n        and d_year = 1998\n        and d_moy = 11) all_sales\norder by promotions, total limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query62.sql",
    "content": "select substr(w_warehouse_name, 1, 20)\n     , sm_type\n     , web_name\n     , sum(case when (ws_ship_date_sk - ws_sold_date_sk <= 30) then 1 else 0 end) as \"30_days \"\n     , sum(case\n               when (ws_ship_date_sk - ws_sold_date_sk > 30) and\n                    (ws_ship_date_sk - ws_sold_date_sk <= 60) then 1\n               else 0 end)                                                        as \"31_60_days \"\n     , sum(case\n               when (ws_ship_date_sk - ws_sold_date_sk > 60) and\n                    (ws_ship_date_sk - ws_sold_date_sk <= 90) then 1\n               else 0 end)                                                        as \"61_90_days \"\n     , sum(case\n               when (ws_ship_date_sk - ws_sold_date_sk > 90) and\n                    (ws_ship_date_sk - ws_sold_date_sk <= 120) then 1\n               else 0 end)                                                        as \"91_120_days\"\n     , sum(case when (ws_ship_date_sk - ws_sold_date_sk > 120) then 1 else 0 end) as above120_days\nfrom web_sales\n   , warehouse\n   , ship_mode\n   , web_site\n   , date_dim\nwhere d_month_seq between 1200 and 1200 + 11\n  and ws_ship_date_sk = d_date_sk\n  and ws_warehouse_sk = w_warehouse_sk\n  and ws_ship_mode_sk = sm_ship_mode_sk\n  and ws_web_site_sk = web_site_sk\ngroup by substr(w_warehouse_name, 1, 20)\n       , sm_type\n       , web_name\norder by substr(w_warehouse_name, 1, 20)\n       , sm_type\n       , web_name limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query63.sql",
    "content": "select *\nfrom (select i_manager_id\n           , sum(ss_sales_price)      sum_sales\n           , avg(sum(ss_sales_price)) over (partition by i_manager_id) avg_monthly_sales\n      from item\n         , store_sales\n         , date_dim\n         , store\n      where ss_item_sk = i_item_sk\n        and ss_sold_date_sk = d_date_sk\n        and ss_store_sk = s_store_sk\n        and d_month_seq in\n            (1200, 1200 + 1, 1200 + 2, 1200 + 3, 1200 + 4, 1200 + 5, 1200 + 6, 1200 + 7, 1200 + 8, 1200 + 9, 1200 + 10,\n             1200 + 11)\n        and ((i_category in ('Books', 'Children', 'Electronics')\n          and i_class in ('personal', 'portable', 'reference', 'self-help')\n          and i_brand in ('scholaramalgamalg #14', 'scholaramalgamalg #7',\n                          'exportiunivamalg #9', 'scholaramalgamalg #9'))\n          or (i_category in ('Women', 'Music', 'Men')\n              and i_class in ('accessories', 'classical', 'fragrances', 'pants')\n              and i_brand in ('amalgimporto #1', 'edu packscholar #1', 'exportiimporto #1',\n                              'importoamalg #1')))\n      group by i_manager_id, d_moy) tmp1\nwhere case when avg_monthly_sales > 0 then abs(sum_sales - avg_monthly_sales) / avg_monthly_sales else null end > 0.1\norder by i_manager_id\n       , avg_monthly_sales\n       , sum_sales limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query64.sql",
    "content": "with cs_ui as\n         (select cs_item_sk\n               , sum(cs_ext_list_price)                                       as sale\n               , sum(cr_refunded_cash + cr_reversed_charge + cr_store_credit) as refund\n          from catalog_sales\n             , catalog_returns\n          where cs_item_sk = cr_item_sk\n            and cs_order_number = cr_order_number\n          group by cs_item_sk\n          having sum(cs_ext_list_price) > 2 * sum(cr_refunded_cash + cr_reversed_charge + cr_store_credit)),\n     cross_sales as\n         (select i_product_name         product_name\n               , i_item_sk              item_sk\n               , s_store_name           store_name\n               , s_zip                  store_zip\n               , ad1.ca_street_number   b_street_number\n               , ad1.ca_street_name     b_street_name\n               , ad1.ca_city            b_city\n               , ad1.ca_zip             b_zip\n               , ad2.ca_street_number   c_street_number\n               , ad2.ca_street_name     c_street_name\n               , ad2.ca_city            c_city\n               , ad2.ca_zip             c_zip\n               , d1.d_year as           syear\n               , d2.d_year as           fsyear\n               , d3.d_year              s2year\n               , count(*)               cnt\n               , sum(ss_wholesale_cost) s1\n               , sum(ss_list_price)     s2\n               , sum(ss_coupon_amt)     s3\n          FROM store_sales\n             , store_returns\n             , cs_ui\n             , date_dim d1\n             , date_dim d2\n             , date_dim d3\n             , store\n             , customer\n             , customer_demographics cd1\n             , customer_demographics cd2\n             , promotion\n             , household_demographics hd1\n             , household_demographics hd2\n             , customer_address ad1\n             , customer_address ad2\n             , income_band ib1\n             , income_band ib2\n             , item\n          WHERE ss_store_sk = s_store_sk\n            AND ss_sold_date_sk = d1.d_date_sk\n            AND ss_customer_sk = c_customer_sk\n            AND ss_cdemo_sk = cd1.cd_demo_sk\n            AND ss_hdemo_sk = hd1.hd_demo_sk\n            AND ss_addr_sk = ad1.ca_address_sk\n            and ss_item_sk = i_item_sk\n            and ss_item_sk = sr_item_sk\n            and ss_ticket_number = sr_ticket_number\n            and ss_item_sk = cs_ui.cs_item_sk\n            and c_current_cdemo_sk = cd2.cd_demo_sk\n            AND c_current_hdemo_sk = hd2.hd_demo_sk\n            AND c_current_addr_sk = ad2.ca_address_sk\n            and c_first_sales_date_sk = d2.d_date_sk\n            and c_first_shipto_date_sk = d3.d_date_sk\n            and ss_promo_sk = p_promo_sk\n            and hd1.hd_income_band_sk = ib1.ib_income_band_sk\n            and hd2.hd_income_band_sk = ib2.ib_income_band_sk\n            and cd1.cd_marital_status <> cd2.cd_marital_status\n            and i_color in ('purple', 'burlywood', 'indian', 'spring', 'floral', 'medium')\n            and i_current_price between 64 and 64 + 10\n            and i_current_price between 64 + 1 and 64 + 15\n          group by i_product_name\n                 , i_item_sk\n                 , s_store_name\n                 , s_zip\n                 , ad1.ca_street_number\n                 , ad1.ca_street_name\n                 , ad1.ca_city\n                 , ad1.ca_zip\n                 , ad2.ca_street_number\n                 , ad2.ca_street_name\n                 , ad2.ca_city\n                 , ad2.ca_zip\n                 , d1.d_year\n                 , d2.d_year\n                 , d3.d_year)\nselect cs1.product_name\n     , cs1.store_name\n     , cs1.store_zip\n     , cs1.b_street_number\n     , cs1.b_street_name\n     , cs1.b_city\n     , cs1.b_zip\n     , cs1.c_street_number\n     , cs1.c_street_name\n     , cs1.c_city\n     , cs1.c_zip\n     , cs1.syear\n     , cs1.cnt\n     , cs1.s1    as s11\n     , cs1.s2    as s21\n     , cs1.s3    as s31\n     , cs2.s1    as s12\n     , cs2.s2    as s22\n     , cs2.s3    as s32\n     , cs2.syear as syear_2\n     , cs2.cnt   as cnt_2\nfrom cross_sales cs1,\n     cross_sales cs2\nwhere cs1.item_sk = cs2.item_sk\n  and cs1.syear = 1999\n  and cs2.syear = 1999 + 1\n  and cs2.cnt <= cs1.cnt\n  and cs1.store_name = cs2.store_name\n  and cs1.store_zip = cs2.store_zip\norder by cs1.product_name\n       , cs1.store_name\n       , cnt_2\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query65.sql",
    "content": "select s_store_name,\n       i_item_desc,\n       sc.revenue,\n       i_current_price,\n       i_wholesale_cost,\n       i_brand\nfrom store,\n     item,\n     (select ss_store_sk, avg(revenue) as ave\n      from (select ss_store_sk,\n                   ss_item_sk,\n                   sum(ss_sales_price) as revenue\n            from store_sales,\n                 date_dim\n            where ss_sold_date_sk = d_date_sk\n              and d_month_seq between 1176 and 1176 + 11\n            group by ss_store_sk, ss_item_sk) sa\n      group by ss_store_sk) sb,\n     (select ss_store_sk, ss_item_sk, sum(ss_sales_price) as revenue\n      from store_sales,\n           date_dim\n      where ss_sold_date_sk = d_date_sk\n        and d_month_seq between 1176 and 1176 + 11\n      group by ss_store_sk, ss_item_sk) sc\nwhere sb.ss_store_sk = sc.ss_store_sk\n  and sc.revenue <= 0.1 * sb.ave\n  and s_store_sk = sc.ss_store_sk\n  and i_item_sk = sc.ss_item_sk\norder by s_store_name, i_item_desc limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query66.sql",
    "content": "select w_warehouse_name\n     , w_warehouse_sq_ft\n     , w_city\n     , w_county\n     , w_state\n     , w_country\n     , ship_carriers\n     , year\n     , sum (jan_sales) as jan_sales\n     , sum (feb_sales) as feb_sales\n     , sum (mar_sales) as mar_sales\n     , sum (apr_sales) as apr_sales\n     , sum (may_sales) as may_sales\n     , sum (jun_sales) as jun_sales\n     , sum (jul_sales) as jul_sales\n     , sum (aug_sales) as aug_sales\n     , sum (sep_sales) as sep_sales\n     , sum (oct_sales) as oct_sales\n     , sum (nov_sales) as nov_sales\n     , sum (dec_sales) as dec_sales\n     , sum (jan_sales/w_warehouse_sq_ft) as jan_sales_per_sq_foot\n     , sum (feb_sales/w_warehouse_sq_ft) as feb_sales_per_sq_foot\n     , sum (mar_sales/w_warehouse_sq_ft) as mar_sales_per_sq_foot\n     , sum (apr_sales/w_warehouse_sq_ft) as apr_sales_per_sq_foot\n     , sum (may_sales/w_warehouse_sq_ft) as may_sales_per_sq_foot\n     , sum (jun_sales/w_warehouse_sq_ft) as jun_sales_per_sq_foot\n     , sum (jul_sales/w_warehouse_sq_ft) as jul_sales_per_sq_foot\n     , sum (aug_sales/w_warehouse_sq_ft) as aug_sales_per_sq_foot\n     , sum (sep_sales/w_warehouse_sq_ft) as sep_sales_per_sq_foot\n     , sum (oct_sales/w_warehouse_sq_ft) as oct_sales_per_sq_foot\n     , sum (nov_sales/w_warehouse_sq_ft) as nov_sales_per_sq_foot\n     , sum (dec_sales/w_warehouse_sq_ft) as dec_sales_per_sq_foot\n     , sum (jan_net) as jan_net\n     , sum (feb_net) as feb_net\n     , sum (mar_net) as mar_net\n     , sum (apr_net) as apr_net\n     , sum (may_net) as may_net\n     , sum (jun_net) as jun_net\n     , sum (jul_net) as jul_net\n     , sum (aug_net) as aug_net\n     , sum (sep_net) as sep_net\n     , sum (oct_net) as oct_net\n     , sum (nov_net) as nov_net\n     , sum (dec_net) as dec_net\nfrom (\n    select\n    w_warehouse_name\n        , w_warehouse_sq_ft\n        , w_city\n        , w_county\n        , w_state\n        , w_country\n        , concat('DHL', ',', 'BARIAN') as ship_carriers\n        , d_year as year\n        , sum (case when d_moy = 1\n    then ws_ext_sales_price* ws_quantity else 0 end) as jan_sales\n        , sum (case when d_moy = 2\n    then ws_ext_sales_price* ws_quantity else 0 end) as feb_sales\n        , sum (case when d_moy = 3\n    then ws_ext_sales_price* ws_quantity else 0 end) as mar_sales\n        , sum (case when d_moy = 4\n    then ws_ext_sales_price* ws_quantity else 0 end) as apr_sales\n        , sum (case when d_moy = 5\n    then ws_ext_sales_price* ws_quantity else 0 end) as may_sales\n        , sum (case when d_moy = 6\n    then ws_ext_sales_price* ws_quantity else 0 end) as jun_sales\n        , sum (case when d_moy = 7\n    then ws_ext_sales_price* ws_quantity else 0 end) as jul_sales\n        , sum (case when d_moy = 8\n    then ws_ext_sales_price* ws_quantity else 0 end) as aug_sales\n        , sum (case when d_moy = 9\n    then ws_ext_sales_price* ws_quantity else 0 end) as sep_sales\n        , sum (case when d_moy = 10\n    then ws_ext_sales_price* ws_quantity else 0 end) as oct_sales\n        , sum (case when d_moy = 11\n    then ws_ext_sales_price* ws_quantity else 0 end) as nov_sales\n        , sum (case when d_moy = 12\n    then ws_ext_sales_price* ws_quantity else 0 end) as dec_sales\n        , sum (case when d_moy = 1\n    then ws_net_paid * ws_quantity else 0 end) as jan_net\n        , sum (case when d_moy = 2\n    then ws_net_paid * ws_quantity else 0 end) as feb_net\n        , sum (case when d_moy = 3\n    then ws_net_paid * ws_quantity else 0 end) as mar_net\n        , sum (case when d_moy = 4\n    then ws_net_paid * ws_quantity else 0 end) as apr_net\n        , sum (case when d_moy = 5\n    then ws_net_paid * ws_quantity else 0 end) as may_net\n        , sum (case when d_moy = 6\n    then ws_net_paid * ws_quantity else 0 end) as jun_net\n        , sum (case when d_moy = 7\n    then ws_net_paid * ws_quantity else 0 end) as jul_net\n        , sum (case when d_moy = 8\n    then ws_net_paid * ws_quantity else 0 end) as aug_net\n        , sum (case when d_moy = 9\n    then ws_net_paid * ws_quantity else 0 end) as sep_net\n        , sum (case when d_moy = 10\n    then ws_net_paid * ws_quantity else 0 end) as oct_net\n        , sum (case when d_moy = 11\n    then ws_net_paid * ws_quantity else 0 end) as nov_net\n        , sum (case when d_moy = 12\n    then ws_net_paid * ws_quantity else 0 end) as dec_net\n    from\n    web_sales\n        , warehouse\n        , date_dim\n        , time_dim\n        , ship_mode\n    where\n    ws_warehouse_sk = w_warehouse_sk\n    and ws_sold_date_sk = d_date_sk\n    and ws_sold_time_sk = t_time_sk\n    and ws_ship_mode_sk = sm_ship_mode_sk\n    and d_year = 2001\n    and t_time between 30838 and 30838+28800\n    and sm_carrier in ('DHL', 'BARIAN')\n    group by\n    w_warehouse_name\n        , w_warehouse_sq_ft\n        , w_city\n        , w_county\n        , w_state\n        , w_country\n        , d_year\n    union all\n    select\n    w_warehouse_name\n        , w_warehouse_sq_ft\n        , w_city\n        , w_county\n        , w_state\n        , w_country\n        , concat('DHL', ',', 'BARIAN') as ship_carriers\n        , d_year as year\n        , sum (case when d_moy = 1\n    then cs_sales_price* cs_quantity else 0 end) as jan_sales\n        , sum (case when d_moy = 2\n    then cs_sales_price* cs_quantity else 0 end) as feb_sales\n        , sum (case when d_moy = 3\n    then cs_sales_price* cs_quantity else 0 end) as mar_sales\n        , sum (case when d_moy = 4\n    then cs_sales_price* cs_quantity else 0 end) as apr_sales\n        , sum (case when d_moy = 5\n    then cs_sales_price* cs_quantity else 0 end) as may_sales\n        , sum (case when d_moy = 6\n    then cs_sales_price* cs_quantity else 0 end) as jun_sales\n        , sum (case when d_moy = 7\n    then cs_sales_price* cs_quantity else 0 end) as jul_sales\n        , sum (case when d_moy = 8\n    then cs_sales_price* cs_quantity else 0 end) as aug_sales\n        , sum (case when d_moy = 9\n    then cs_sales_price* cs_quantity else 0 end) as sep_sales\n        , sum (case when d_moy = 10\n    then cs_sales_price* cs_quantity else 0 end) as oct_sales\n        , sum (case when d_moy = 11\n    then cs_sales_price* cs_quantity else 0 end) as nov_sales\n        , sum (case when d_moy = 12\n    then cs_sales_price* cs_quantity else 0 end) as dec_sales\n        , sum (case when d_moy = 1\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as jan_net\n        , sum (case when d_moy = 2\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as feb_net\n        , sum (case when d_moy = 3\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as mar_net\n        , sum (case when d_moy = 4\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as apr_net\n        , sum (case when d_moy = 5\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as may_net\n        , sum (case when d_moy = 6\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as jun_net\n        , sum (case when d_moy = 7\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as jul_net\n        , sum (case when d_moy = 8\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as aug_net\n        , sum (case when d_moy = 9\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as sep_net\n        , sum (case when d_moy = 10\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as oct_net\n        , sum (case when d_moy = 11\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as nov_net\n        , sum (case when d_moy = 12\n    then cs_net_paid_inc_tax * cs_quantity else 0 end) as dec_net\n    from\n    catalog_sales\n        , warehouse\n        , date_dim\n        , time_dim\n        , ship_mode\n    where\n    cs_warehouse_sk = w_warehouse_sk\n    and cs_sold_date_sk = d_date_sk\n    and cs_sold_time_sk = t_time_sk\n    and cs_ship_mode_sk = sm_ship_mode_sk\n    and d_year = 2001\n    and t_time between 30838 AND 30838+28800\n    and sm_carrier in ('DHL', 'BARIAN')\n    group by\n    w_warehouse_name\n        , w_warehouse_sq_ft\n        , w_city\n        , w_county\n        , w_state\n        , w_country\n        , d_year\n    ) x\ngroup by\n    w_warehouse_name\n        , w_warehouse_sq_ft\n        , w_city\n        , w_county\n        , w_state\n        , w_country\n        , ship_carriers\n        , year\norder by w_warehouse_name\n    limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query67.sql",
    "content": "select *\nfrom (select i_category\n           , i_class\n           , i_brand\n           , i_product_name\n           , d_year\n           , d_qoy\n           , d_moy\n           , s_store_id\n           , sumsales\n           , rank() over (partition by i_category order by sumsales desc) rk\n      from (select i_category\n                 , i_class\n                 , i_brand\n                 , i_product_name\n                 , d_year\n                 , d_qoy\n                 , d_moy\n                 , s_store_id\n                 , sum(coalesce(ss_sales_price * ss_quantity, 0)) sumsales\n            from store_sales\n               , date_dim\n               , store\n               , item\n            where ss_sold_date_sk = d_date_sk\n              and ss_item_sk = i_item_sk\n              and ss_store_sk = s_store_sk\n              and d_month_seq between 1200 and 1200 + 11\n            group by rollup (i_category, i_class, i_brand, i_product_name, d_year, d_qoy, d_moy, s_store_id)) dw1) dw2\nwhere rk <= 100\norder by i_category\n       , i_class\n       , i_brand\n       , i_product_name\n       , d_year\n       , d_qoy\n       , d_moy\n       , s_store_id\n       , sumsales\n       , rk limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query68.sql",
    "content": "select c_last_name\n     , c_first_name\n     , ca_city\n     , bought_city\n     , ss_ticket_number\n     , extended_price\n     , extended_tax\n     , list_price\nfrom (select ss_ticket_number\n           , ss_customer_sk\n           , ca_city                 bought_city\n           , sum(ss_ext_sales_price) extended_price\n           , sum(ss_ext_list_price)  list_price\n           , sum(ss_ext_tax)         extended_tax\n      from store_sales\n         , date_dim\n         , store\n         , household_demographics\n         , customer_address\n      where store_sales.ss_sold_date_sk = date_dim.d_date_sk\n        and store_sales.ss_store_sk = store.s_store_sk\n        and store_sales.ss_hdemo_sk = household_demographics.hd_demo_sk\n        and store_sales.ss_addr_sk = customer_address.ca_address_sk\n        and date_dim.d_dom between 1 and 2\n        and (household_demographics.hd_dep_count = 4 or\n             household_demographics.hd_vehicle_count = 3)\n        and date_dim.d_year in (1999, 1999 + 1, 1999 + 2)\n        and store.s_city in ('Fairview', 'Midway')\n      group by ss_ticket_number\n             , ss_customer_sk\n             , ss_addr_sk, ca_city) dn\n   , customer\n   , customer_address current_addr\nwhere ss_customer_sk = c_customer_sk\n  and customer.c_current_addr_sk = current_addr.ca_address_sk\n  and current_addr.ca_city <> bought_city\norder by c_last_name\n       , ss_ticket_number limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query69.sql",
    "content": "select cd_gender,\n       cd_marital_status,\n       cd_education_status,\n       count(*) cnt1,\n       cd_purchase_estimate,\n       count(*) cnt2,\n       cd_credit_rating,\n       count(*) cnt3\nfrom customer c,\n     customer_address ca,\n     customer_demographics\nwhere c.c_current_addr_sk = ca.ca_address_sk\n  and ca_state in ('KY', 'GA', 'NM')\n  and cd_demo_sk = c.c_current_cdemo_sk\n  and exists(select *\n             from store_sales,\n                  date_dim\n             where c.c_customer_sk = ss_customer_sk\n               and ss_sold_date_sk = d_date_sk\n               and d_year = 2001\n               and d_moy between 4 and 4 + 2)\n  and (not exists(select *\n                  from web_sales,\n                       date_dim\n                  where c.c_customer_sk = ws_bill_customer_sk\n                    and ws_sold_date_sk = d_date_sk\n                    and d_year = 2001\n                    and d_moy between 4 and 4 + 2) and\n       not exists(select *\n                  from catalog_sales,\n                       date_dim\n                  where c.c_customer_sk = cs_ship_customer_sk\n                    and cs_sold_date_sk = d_date_sk\n                    and d_year = 2001\n                    and d_moy between 4 and 4 + 2))\ngroup by cd_gender,\n         cd_marital_status,\n         cd_education_status,\n         cd_purchase_estimate,\n         cd_credit_rating\norder by cd_gender,\n         cd_marital_status,\n         cd_education_status,\n         cd_purchase_estimate,\n         cd_credit_rating limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query70.sql",
    "content": "select sum(ss_net_profit)                     as total_sum\n     , s_state\n     , s_county\n     , grouping(s_state) + grouping(s_county) as lochierarchy\n     , rank()                                    over (\n \tpartition by grouping(s_state)+grouping(s_county),\n \tcase when grouping(s_county) = 0 then s_state end \n \torder by sum(ss_net_profit) desc) as rank_within_parent\nfrom store_sales\n   , date_dim d1\n   , store\nwhere d1.d_month_seq between 1200 and 1200 + 11\n  and d1.d_date_sk = ss_sold_date_sk\n  and s_store_sk = ss_store_sk\n  and s_state in\n      (select s_state\n       from (select s_state as s_state,\n                    rank()     over ( partition by s_state order by sum(ss_net_profit) desc) as ranking\n             from store_sales,\n                  store,\n                  date_dim\n             where d_month_seq between 1200 and 1200 + 11\n               and d_date_sk = ss_sold_date_sk\n               and s_store_sk = ss_store_sk\n             group by s_state) tmp1\n       where ranking <= 5)\ngroup by rollup (s_state, s_county)\norder by lochierarchy desc\n       , case when lochierarchy = 0 then s_state end\n       , rank_within_parent limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query71.sql",
    "content": "select i_brand_id     brand_id,\n       i_brand        brand,\n       t_hour,\n       t_minute,\n       sum(ext_price) ext_price\nfrom item,\n     (select ws_ext_sales_price as ext_price,\n             ws_sold_date_sk    as sold_date_sk,\n             ws_item_sk         as sold_item_sk,\n             ws_sold_time_sk    as time_sk\n      from web_sales,\n           date_dim\n      where d_date_sk = ws_sold_date_sk\n        and d_moy = 11\n        and d_year = 1999\n      union all\n      select cs_ext_sales_price as ext_price,\n             cs_sold_date_sk    as sold_date_sk,\n             cs_item_sk         as sold_item_sk,\n             cs_sold_time_sk    as time_sk\n      from catalog_sales,\n           date_dim\n      where d_date_sk = cs_sold_date_sk\n        and d_moy = 11\n        and d_year = 1999\n      union all\n      select ss_ext_sales_price as ext_price,\n             ss_sold_date_sk    as sold_date_sk,\n             ss_item_sk         as sold_item_sk,\n             ss_sold_time_sk    as time_sk\n      from store_sales,\n           date_dim\n      where d_date_sk = ss_sold_date_sk\n        and d_moy = 11\n        and d_year = 1999) tmp,\n     time_dim\nwhere sold_item_sk = i_item_sk\n  and i_manager_id = 1\n  and time_sk = t_time_sk\n  and (t_meal_time = 'breakfast' or t_meal_time = 'dinner')\ngroup by i_brand, i_brand_id, t_hour, t_minute\norder by ext_price desc, i_brand_id\n\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query72.sql",
    "content": "select i_item_desc\n     , w_warehouse_name\n     , d1.d_week_seq\n     , sum(case when p_promo_sk is null then 1 else 0 end)     no_promo\n     , sum(case when p_promo_sk is not null then 1 else 0 end) promo\n     , count(*)                                                total_cnt\nfrom catalog_sales\n         join inventory on (cs_item_sk = inv_item_sk)\n         join warehouse on (w_warehouse_sk = inv_warehouse_sk)\n         join item on (i_item_sk = cs_item_sk)\n         join customer_demographics on (cs_bill_cdemo_sk = cd_demo_sk)\n         join household_demographics on (cs_bill_hdemo_sk = hd_demo_sk)\n         join date_dim d1 on (cs_sold_date_sk = d1.d_date_sk)\n         join date_dim d2 on (inv_date_sk = d2.d_date_sk)\n         join date_dim d3 on (cs_ship_date_sk = d3.d_date_sk)\n         left outer join promotion on (cs_promo_sk = p_promo_sk)\n         left outer join catalog_returns on (cr_item_sk = cs_item_sk and cr_order_number = cs_order_number)\nwhere d1.d_week_seq = d2.d_week_seq\n  and inv_quantity_on_hand < cs_quantity\n  and d3.d_date > date_add(cast(d1.d_date as date), 5)\n  and hd_buy_potential = '>10000'\n  and d1.d_year = 1999\n  and cd_marital_status = 'D'\ngroup by i_item_desc, w_warehouse_name, d1.d_week_seq\norder by total_cnt desc, i_item_desc, w_warehouse_name, d_week_seq limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query73.sql",
    "content": "select c_last_name\n     , c_first_name\n     , c_salutation\n     , c_preferred_cust_flag\n     , ss_ticket_number\n     , cnt\nfrom (select ss_ticket_number\n           , ss_customer_sk\n           , count(*) cnt\n      from store_sales,\n           date_dim,\n           store,\n           household_demographics\n      where store_sales.ss_sold_date_sk = date_dim.d_date_sk\n        and store_sales.ss_store_sk = store.s_store_sk\n        and store_sales.ss_hdemo_sk = household_demographics.hd_demo_sk\n        and date_dim.d_dom between 1 and 2\n        and (household_demographics.hd_buy_potential = '>10000' or\n             household_demographics.hd_buy_potential = 'Unknown')\n        and household_demographics.hd_vehicle_count > 0\n        and case\n                when household_demographics.hd_vehicle_count > 0 then\n                        household_demographics.hd_dep_count / household_demographics.hd_vehicle_count\n                else null end > 1\n        and date_dim.d_year in (1999, 1999 + 1, 1999 + 2)\n        and store.s_county in ('Williamson County', 'Franklin Parish', 'Bronx County', 'Orange County')\n      group by ss_ticket_number, ss_customer_sk) dj,\n     customer\nwhere ss_customer_sk = c_customer_sk\n  and cnt between 1 and 5\norder by cnt desc, c_last_name asc\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query74.sql",
    "content": "with year_total as (select c_customer_id customer_id\n                         , c_first_name  customer_first_name\n                         , c_last_name   customer_last_name\n                         , d_year\n    as year\n   , sum (ss_net_paid) year_total\n   , 's' sale_type\nfrom customer\n        , store_sales\n        , date_dim\nwhere c_customer_sk = ss_customer_sk\n  and ss_sold_date_sk = d_date_sk\n  and d_year in (2001\n    , 2001+1)\ngroup by c_customer_id\n        , c_first_name\n        , c_last_name\n        , d_year\nunion all\nselect c_customer_id customer_id\n     , c_first_name  customer_first_name\n     , c_last_name   customer_last_name\n     , d_year as year\n       ,sum(ws_net_paid) year_total\n       ,'w' sale_type\nfrom customer\n        , web_sales\n        , date_dim\nwhere c_customer_sk = ws_bill_customer_sk\n  and ws_sold_date_sk = d_date_sk\n  and d_year in (2001\n    , 2001+1)\ngroup by c_customer_id\n        , c_first_name\n        , c_last_name\n        , d_year\n    )\nselect t_s_secyear.customer_id,\n       t_s_secyear.customer_first_name,\n       t_s_secyear.customer_last_name\nfrom year_total t_s_firstyear\n   , year_total t_s_secyear\n   , year_total t_w_firstyear\n   , year_total t_w_secyear\nwhere t_s_secyear.customer_id = t_s_firstyear.customer_id\n  and t_s_firstyear.customer_id = t_w_secyear.customer_id\n  and t_s_firstyear.customer_id = t_w_firstyear.customer_id\n  and t_s_firstyear.sale_type = 's'\n  and t_w_firstyear.sale_type = 'w'\n  and t_s_secyear.sale_type = 's'\n  and t_w_secyear.sale_type = 'w'\n  and t_s_firstyear.year = 2001\n  and t_s_secyear.year = 2001 + 1\n  and t_w_firstyear.year = 2001\n  and t_w_secyear.year = 2001 + 1\n  and t_s_firstyear.year_total > 0\n  and t_w_firstyear.year_total > 0\n  and case when t_w_firstyear.year_total > 0 then t_w_secyear.year_total / t_w_firstyear.year_total else null end\n    > case when t_s_firstyear.year_total > 0 then t_s_secyear.year_total / t_s_firstyear.year_total else null end\norder by 1, 1, 1 limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query75.sql",
    "content": "WITH all_sales AS (SELECT d_year\n                        , i_brand_id\n                        , i_class_id\n                        , i_category_id\n                        , i_manufact_id\n                        , SUM(sales_cnt) AS sales_cnt\n                        , SUM(sales_amt) AS sales_amt\n                   FROM (SELECT d_year\n                              , i_brand_id\n                              , i_class_id\n                              , i_category_id\n                              , i_manufact_id\n                              , cs_quantity - COALESCE(cr_return_quantity, 0)        AS sales_cnt\n                              , cs_ext_sales_price - COALESCE(cr_return_amount, 0.0) AS sales_amt\n                         FROM catalog_sales\n                                  JOIN item ON i_item_sk = cs_item_sk\n                                  JOIN date_dim ON d_date_sk = cs_sold_date_sk\n                                  LEFT JOIN catalog_returns ON (cs_order_number = cr_order_number\n                             AND cs_item_sk = cr_item_sk)\n                         WHERE i_category = 'Books'\n                         UNION\n                         SELECT d_year\n                              , i_brand_id\n                              , i_class_id\n                              , i_category_id\n                              , i_manufact_id\n                              , ss_quantity - COALESCE(sr_return_quantity, 0)     AS sales_cnt\n                              , ss_ext_sales_price - COALESCE(sr_return_amt, 0.0) AS sales_amt\n                         FROM store_sales\n                                  JOIN item ON i_item_sk = ss_item_sk\n                                  JOIN date_dim ON d_date_sk = ss_sold_date_sk\n                                  LEFT JOIN store_returns ON (ss_ticket_number = sr_ticket_number\n                             AND ss_item_sk = sr_item_sk)\n                         WHERE i_category = 'Books'\n                         UNION\n                         SELECT d_year\n                              , i_brand_id\n                              , i_class_id\n                              , i_category_id\n                              , i_manufact_id\n                              , ws_quantity - COALESCE(wr_return_quantity, 0)     AS sales_cnt\n                              , ws_ext_sales_price - COALESCE(wr_return_amt, 0.0) AS sales_amt\n                         FROM web_sales\n                                  JOIN item ON i_item_sk = ws_item_sk\n                                  JOIN date_dim ON d_date_sk = ws_sold_date_sk\n                                  LEFT JOIN web_returns ON (ws_order_number = wr_order_number\n                             AND ws_item_sk = wr_item_sk)\n                         WHERE i_category = 'Books') sales_detail\n                   GROUP BY d_year, i_brand_id, i_class_id, i_category_id, i_manufact_id)\nSELECT prev_yr.d_year AS prev_year\n     , curr_yr.d_year AS year\n                          ,curr_yr.i_brand_id\n                          ,curr_yr.i_class_id\n                          ,curr_yr.i_category_id\n                          ,curr_yr.i_manufact_id\n                          ,prev_yr.sales_cnt AS prev_yr_cnt\n                          ,curr_yr.sales_cnt AS curr_yr_cnt\n                          ,curr_yr.sales_cnt-prev_yr.sales_cnt AS sales_cnt_diff\n                          ,curr_yr.sales_amt-prev_yr.sales_amt AS sales_amt_diff\nFROM all_sales curr_yr, all_sales prev_yr\nWHERE curr_yr.i_brand_id=prev_yr.i_brand_id\n  AND curr_yr.i_class_id=prev_yr.i_class_id\n  AND curr_yr.i_category_id=prev_yr.i_category_id\n  AND curr_yr.i_manufact_id=prev_yr.i_manufact_id\n  AND curr_yr.d_year=2002\n  AND prev_yr.d_year=2002-1\n  AND CAST (curr_yr.sales_cnt AS DECIMAL (17\n    , 2))/ CAST (prev_yr.sales_cnt AS DECIMAL (17\n    , 2))\n    <0.9\nORDER BY sales_cnt_diff\n    limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query76.sql",
    "content": "select channel, col_name, d_year, d_qoy, i_category, COUNT(*) sales_cnt, SUM(ext_sales_price) sales_amt\nFROM (SELECT 'store' as channel, 'ss_store_sk' col_name, d_year, d_qoy, i_category, ss_ext_sales_price ext_sales_price\n      FROM store_sales,\n           item,\n           date_dim\n      WHERE ss_store_sk IS NULL\n        AND ss_sold_date_sk = d_date_sk\n        AND ss_item_sk = i_item_sk\n      UNION ALL\n      SELECT 'web' as              channel,\n             'ws_ship_customer_sk' col_name,\n             d_year,\n             d_qoy,\n             i_category,\n             ws_ext_sales_price    ext_sales_price\n      FROM web_sales,\n           item,\n           date_dim\n      WHERE ws_ship_customer_sk IS NULL\n        AND ws_sold_date_sk = d_date_sk\n        AND ws_item_sk = i_item_sk\n      UNION ALL\n      SELECT 'catalog' as       channel,\n             'cs_ship_addr_sk'  col_name,\n             d_year,\n             d_qoy,\n             i_category,\n             cs_ext_sales_price ext_sales_price\n      FROM catalog_sales,\n           item,\n           date_dim\n      WHERE cs_ship_addr_sk IS NULL\n        AND cs_sold_date_sk = d_date_sk\n        AND cs_item_sk = i_item_sk) foo\nGROUP BY channel, col_name, d_year, d_qoy, i_category\nORDER BY channel, col_name, d_year, d_qoy, i_category limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query77.sql",
    "content": "with ss as\n         (select s_store_sk,\n                 sum(ss_ext_sales_price) as sales,\n                 sum(ss_net_profit)      as profit\n          from store_sales,\n               date_dim,\n               store\n          where ss_sold_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n            and ss_store_sk = s_store_sk\n          group by s_store_sk)\n        ,\n     sr as\n         (select s_store_sk,\n                 sum(sr_return_amt) as returns,\n                 sum(sr_net_loss)   as profit_loss\n          from store_returns,\n               date_dim,\n               store\n          where sr_returned_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n            and sr_store_sk = s_store_sk\n          group by s_store_sk),\n     cs as\n         (select cs_call_center_sk,\n                 sum(cs_ext_sales_price) as sales,\n                 sum(cs_net_profit)      as profit\n          from catalog_sales,\n               date_dim\n          where cs_sold_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n          group by cs_call_center_sk),\n     cr as\n         (select cr_call_center_sk,\n                 sum(cr_return_amount) as returns,\n                 sum(cr_net_loss)      as profit_loss\n          from catalog_returns,\n               date_dim\n          where cr_returned_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n          group by cr_call_center_sk),\n     ws as\n         (select wp_web_page_sk,\n                 sum(ws_ext_sales_price) as sales,\n                 sum(ws_net_profit)      as profit\n          from web_sales,\n               date_dim,\n               web_page\n          where ws_sold_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n            and ws_web_page_sk = wp_web_page_sk\n          group by wp_web_page_sk),\n     wr as\n         (select wp_web_page_sk,\n                 sum(wr_return_amt) as returns,\n                 sum(wr_net_loss)   as profit_loss\n          from web_returns,\n               date_dim,\n               web_page\n          where wr_returned_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n            and wr_web_page_sk = wp_web_page_sk\n          group by wp_web_page_sk)\nselect channel\n     , id\n     , sum(sales)   as sales\n     , sum(returns) as returns\n     , sum(profit)  as profit\nfrom (select 'store channel'                     as channel\n           , ss.s_store_sk                       as id\n           , sales\n           , coalesce(returns, 0)                as returns\n           , (profit - coalesce(profit_loss, 0)) as profit\n      from ss\n               left join sr\n                         on ss.s_store_sk = sr.s_store_sk\n      union all\n      select 'catalog channel'      as channel\n           , cs_call_center_sk      as id\n           , sales\n           , returns\n           , (profit - profit_loss) as profit\n      from cs\n         , cr\n      union all\n      select 'web channel'                       as channel\n           , ws.wp_web_page_sk                   as id\n           , sales\n           , coalesce(returns, 0)                   returns\n           , (profit - coalesce(profit_loss, 0)) as profit\n      from ws\n               left join wr\n                         on ws.wp_web_page_sk = wr.wp_web_page_sk) x\ngroup by rollup (channel, id)\norder by channel\n       , id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query78.sql",
    "content": "with ws as\n         (select d_year AS              ws_sold_year,\n                 ws_item_sk,\n                 ws_bill_customer_sk    ws_customer_sk,\n                 sum(ws_quantity)       ws_qty,\n                 sum(ws_wholesale_cost) ws_wc,\n                 sum(ws_sales_price)    ws_sp\n          from web_sales\n                   left join web_returns on wr_order_number = ws_order_number and ws_item_sk = wr_item_sk\n                   join date_dim on ws_sold_date_sk = d_date_sk\n          where wr_order_number is null\n          group by d_year, ws_item_sk, ws_bill_customer_sk),\n     cs as\n         (select d_year AS              cs_sold_year,\n                 cs_item_sk,\n                 cs_bill_customer_sk    cs_customer_sk,\n                 sum(cs_quantity)       cs_qty,\n                 sum(cs_wholesale_cost) cs_wc,\n                 sum(cs_sales_price)    cs_sp\n          from catalog_sales\n                   left join catalog_returns on cr_order_number = cs_order_number and cs_item_sk = cr_item_sk\n                   join date_dim on cs_sold_date_sk = d_date_sk\n          where cr_order_number is null\n          group by d_year, cs_item_sk, cs_bill_customer_sk),\n     ss as\n         (select d_year AS              ss_sold_year,\n                 ss_item_sk,\n                 ss_customer_sk,\n                 sum(ss_quantity)       ss_qty,\n                 sum(ss_wholesale_cost) ss_wc,\n                 sum(ss_sales_price)    ss_sp\n          from store_sales\n                   left join store_returns on sr_ticket_number = ss_ticket_number and ss_item_sk = sr_item_sk\n                   join date_dim on ss_sold_date_sk = d_date_sk\n          where sr_ticket_number is null\n          group by d_year, ss_item_sk, ss_customer_sk)\nselect ss_sold_year,\n       ss_item_sk,\n       ss_customer_sk,\n       round(ss_qty / (coalesce(ws_qty, 0) + coalesce(cs_qty, 0)), 2) ratio,\n       ss_qty                                                         store_qty,\n       ss_wc                                                          store_wholesale_cost,\n       ss_sp                                                          store_sales_price,\n       coalesce(ws_qty, 0) + coalesce(cs_qty, 0)                      other_chan_qty,\n       coalesce(ws_wc, 0) + coalesce(cs_wc, 0)                        other_chan_wholesale_cost,\n       coalesce(ws_sp, 0) + coalesce(cs_sp, 0)                        other_chan_sales_price\nfrom ss\n         left join ws on (ws_sold_year = ss_sold_year and ws_item_sk = ss_item_sk and ws_customer_sk = ss_customer_sk)\n         left join cs on (cs_sold_year = ss_sold_year and cs_item_sk = ss_item_sk and cs_customer_sk = ss_customer_sk)\nwhere (coalesce(ws_qty, 0) > 0 or coalesce(cs_qty, 0) > 0)\n  and ss_sold_year = 2000\norder by ss_sold_year, ss_item_sk, ss_customer_sk,\n         ss_qty desc, ss_wc desc, ss_sp desc,\n         other_chan_qty,\n         other_chan_wholesale_cost,\n         other_chan_sales_price,\n         round(ss_qty / (coalesce(ws_qty + cs_qty, 1)), 2) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query79.sql",
    "content": "select c_last_name,\n       c_first_name,\n       substr(s_city, 1, 30),\n       ss_ticket_number,\n       amt,\n       profit\nfrom (select ss_ticket_number\n           , ss_customer_sk\n           , store.s_city\n           , sum(ss_coupon_amt) amt\n           , sum(ss_net_profit) profit\n      from store_sales,\n           date_dim,\n           store,\n           household_demographics\n      where store_sales.ss_sold_date_sk = date_dim.d_date_sk\n        and store_sales.ss_store_sk = store.s_store_sk\n        and store_sales.ss_hdemo_sk = household_demographics.hd_demo_sk\n        and (household_demographics.hd_dep_count = 6 or household_demographics.hd_vehicle_count > 2)\n        and date_dim.d_dow = 1\n        and date_dim.d_year in (1999, 1999 + 1, 1999 + 2)\n        and store.s_number_employees between 200 and 295\n      group by ss_ticket_number, ss_customer_sk, ss_addr_sk, store.s_city) ms,\n     customer\nwhere ss_customer_sk = c_customer_sk\norder by c_last_name, c_first_name, substr(s_city, 1, 30), profit limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query80.sql",
    "content": "with ssr as\n         (select s_store_id                                    as store_id,\n                 sum(ss_ext_sales_price)                       as sales,\n                 sum(coalesce(sr_return_amt, 0))               as returns,\n                 sum(ss_net_profit - coalesce(sr_net_loss, 0)) as profit\n          from store_sales\n                   left outer join store_returns on\n              (ss_item_sk = sr_item_sk and ss_ticket_number = sr_ticket_number),\n               date_dim,\n               store,\n               item,\n               promotion\n          where ss_sold_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n            and ss_store_sk = s_store_sk\n            and ss_item_sk = i_item_sk\n            and i_current_price > 50\n            and ss_promo_sk = p_promo_sk\n            and p_channel_tv = 'N'\n          group by s_store_id)\n        ,\n     csr as\n         (select cp_catalog_page_id                            as catalog_page_id,\n                 sum(cs_ext_sales_price)                       as sales,\n                 sum(coalesce(cr_return_amount, 0))            as returns,\n                 sum(cs_net_profit - coalesce(cr_net_loss, 0)) as profit\n          from catalog_sales\n                   left outer join catalog_returns on\n              (cs_item_sk = cr_item_sk and cs_order_number = cr_order_number),\n               date_dim,\n               catalog_page,\n               item,\n               promotion\n          where cs_sold_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n            and cs_catalog_page_sk = cp_catalog_page_sk\n            and cs_item_sk = i_item_sk\n            and i_current_price > 50\n            and cs_promo_sk = p_promo_sk\n            and p_channel_tv = 'N'\n          group by cp_catalog_page_id)\n        ,\n     wsr as\n         (select web_site_id,\n                 sum(ws_ext_sales_price)                       as sales,\n                 sum(coalesce(wr_return_amt, 0))               as returns,\n                 sum(ws_net_profit - coalesce(wr_net_loss, 0)) as profit\n          from web_sales\n                   left outer join web_returns on\n              (ws_item_sk = wr_item_sk and ws_order_number = wr_order_number),\n               date_dim,\n               web_site,\n               item,\n               promotion\n          where ws_sold_date_sk = d_date_sk\n            and d_date between cast('2000-08-23' as date)\n              and date_add(cast('2000-08-23' as date), 30)\n            and ws_web_site_sk = web_site_sk\n            and ws_item_sk = i_item_sk\n            and i_current_price > 50\n            and ws_promo_sk = p_promo_sk\n            and p_channel_tv = 'N'\n          group by web_site_id)\nselect channel\n     , id\n     , sum(sales)   as sales\n     , sum(returns) as returns\n     , sum(profit)  as profit\nfrom (select 'store channel'           as channel\n           , concat('store', store_id) as id\n           , sales\n           , returns\n           , profit\n      from ssr\n      union all\n      select 'catalog channel'                       as channel\n           , concat('catalog_page', catalog_page_id) as id\n           , sales\n           , returns\n           , profit\n      from csr\n      union all\n      select 'web channel'                   as channel\n           , concat('web_site', web_site_id) as id\n           , sales\n           , returns\n           , profit\n      from wsr) x\ngroup by rollup (channel, id)\norder by channel\n       , id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query81.sql",
    "content": "with customer_total_return as\n         (select cr_returning_customer_sk   as ctr_customer_sk\n                  ,\n                 ca_state                   as ctr_state,\n                 sum(cr_return_amt_inc_tax) as ctr_total_return\n          from catalog_returns\n             , date_dim\n             , customer_address\n          where cr_returned_date_sk = d_date_sk\n            and d_year = 2000\n            and cr_returning_addr_sk = ca_address_sk\n          group by cr_returning_customer_sk\n                 , ca_state)\nselect c_customer_id\n     , c_salutation\n     , c_first_name\n     , c_last_name\n     , ca_street_number\n     , ca_street_name\n     , ca_street_type\n     , ca_suite_number\n     , ca_city\n     , ca_county\n     , ca_state\n     , ca_zip\n     , ca_country\n     , ca_gmt_offset\n     , ca_location_type\n     , ctr_total_return\nfrom customer_total_return ctr1\n   , customer_address\n   , customer\nwhere ctr1.ctr_total_return > (select avg(ctr_total_return) * 1.2\n                               from customer_total_return ctr2\n                               where ctr1.ctr_state = ctr2.ctr_state)\n  and ca_address_sk = c_current_addr_sk\n  and ca_state = 'GA'\n  and ctr1.ctr_customer_sk = c_customer_sk\norder by c_customer_id, c_salutation, c_first_name, c_last_name, ca_street_number, ca_street_name\n       , ca_street_type, ca_suite_number, ca_city, ca_county, ca_state, ca_zip, ca_country, ca_gmt_offset\n       , ca_location_type, ctr_total_return limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query82.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , i_current_price\nfrom item,\n     inventory,\n     date_dim,\n     store_sales\nwhere i_current_price between 62 and 62 + 30\n  and inv_item_sk = i_item_sk\n  and d_date_sk = inv_date_sk\n  and d_date between cast('2000-05-25' as date) and date_add(cast('2000-05-25' as date), 60)\n  and i_manufact_id in (129, 270, 821, 423)\n  and inv_quantity_on_hand between 100 and 500\n  and ss_item_sk = i_item_sk\ngroup by i_item_id, i_item_desc, i_current_price\norder by i_item_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query83.sql",
    "content": "with sr_items as\n         (select i_item_id               item_id,\n                 sum(sr_return_quantity) sr_item_qty\n          from store_returns,\n               item,\n               date_dim\n          where sr_item_sk = i_item_sk\n            and d_date in\n                (select d_date\n                 from date_dim\n                 where d_week_seq in\n                       (select d_week_seq\n                        from date_dim\n                        where d_date in ('2000-06-30', '2000-09-27', '2000-11-17')))\n            and sr_returned_date_sk = d_date_sk\n          group by i_item_id),\n     cr_items as\n         (select i_item_id               item_id,\n                 sum(cr_return_quantity) cr_item_qty\n          from catalog_returns,\n               item,\n               date_dim\n          where cr_item_sk = i_item_sk\n            and d_date in\n                (select d_date\n                 from date_dim\n                 where d_week_seq in\n                       (select d_week_seq\n                        from date_dim\n                        where d_date in ('2000-06-30', '2000-09-27', '2000-11-17')))\n            and cr_returned_date_sk = d_date_sk\n          group by i_item_id),\n     wr_items as\n         (select i_item_id               item_id,\n                 sum(wr_return_quantity) wr_item_qty\n          from web_returns,\n               item,\n               date_dim\n          where wr_item_sk = i_item_sk\n            and d_date in\n                (select d_date\n                 from date_dim\n                 where d_week_seq in\n                       (select d_week_seq\n                        from date_dim\n                        where d_date in ('2000-06-30', '2000-09-27', '2000-11-17')))\n            and wr_returned_date_sk = d_date_sk\n          group by i_item_id)\nselect sr_items.item_id\n     , sr_item_qty\n     , sr_item_qty / (sr_item_qty + cr_item_qty + wr_item_qty) / 3.0 * 100 sr_dev\n     , cr_item_qty\n     , cr_item_qty / (sr_item_qty + cr_item_qty + wr_item_qty) / 3.0 * 100 cr_dev\n     , wr_item_qty\n     , wr_item_qty / (sr_item_qty + cr_item_qty + wr_item_qty) / 3.0 * 100 wr_dev\n     , (sr_item_qty + cr_item_qty + wr_item_qty) / 3.0                     average\nfrom sr_items\n   , cr_items\n   , wr_items\nwhere sr_items.item_id = cr_items.item_id\n  and sr_items.item_id = wr_items.item_id\norder by sr_items.item_id\n       , sr_item_qty limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query84.sql",
    "content": "select c_customer_id                                         as customer_id\n     , concat(c_last_name, ', ', coalesce(c_first_name, '')) as customername\nfrom customer\n   , customer_address\n   , customer_demographics\n   , household_demographics\n   , income_band\n   , store_returns\nwhere ca_city = 'Edgewood'\n  and c_current_addr_sk = ca_address_sk\n  and ib_lower_bound >= 38128\n  and ib_upper_bound <= 38128 + 50000\n  and ib_income_band_sk = hd_income_band_sk\n  and cd_demo_sk = c_current_cdemo_sk\n  and hd_demo_sk = c_current_hdemo_sk\n  and sr_cdemo_sk = cd_demo_sk\norder by c_customer_id limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query85.sql",
    "content": "select substr(r_reason_desc, 1, 20)\n     , avg(ws_quantity)\n     , avg(wr_refunded_cash)\n     , avg(wr_fee)\nfrom web_sales,\n     web_returns,\n     web_page,\n     customer_demographics cd1,\n     customer_demographics cd2,\n     customer_address,\n     date_dim,\n     reason\nwhere ws_web_page_sk = wp_web_page_sk\n  and ws_item_sk = wr_item_sk\n  and ws_order_number = wr_order_number\n  and ws_sold_date_sk = d_date_sk\n  and d_year = 2000\n  and cd1.cd_demo_sk = wr_refunded_cdemo_sk\n  and cd2.cd_demo_sk = wr_returning_cdemo_sk\n  and ca_address_sk = wr_refunded_addr_sk\n  and r_reason_sk = wr_reason_sk\n  and (\n        (\n                    cd1.cd_marital_status = 'M'\n                and\n                    cd1.cd_marital_status = cd2.cd_marital_status\n                and\n                    cd1.cd_education_status = 'Advanced Degree'\n                and\n                    cd1.cd_education_status = cd2.cd_education_status\n                and\n                    ws_sales_price between 100.00 and 150.00\n            )\n        or\n        (\n                    cd1.cd_marital_status = 'S'\n                and\n                    cd1.cd_marital_status = cd2.cd_marital_status\n                and\n                    cd1.cd_education_status = 'College'\n                and\n                    cd1.cd_education_status = cd2.cd_education_status\n                and\n                    ws_sales_price between 50.00 and 100.00\n            )\n        or\n        (\n                    cd1.cd_marital_status = 'W'\n                and\n                    cd1.cd_marital_status = cd2.cd_marital_status\n                and\n                    cd1.cd_education_status = '2 yr Degree'\n                and\n                    cd1.cd_education_status = cd2.cd_education_status\n                and\n                    ws_sales_price between 150.00 and 200.00\n            )\n    )\n  and (\n        (\n                    ca_country = 'United States'\n                and\n                    ca_state in ('IN', 'OH', 'NJ')\n                and ws_net_profit between 100 and 200\n            )\n        or\n        (\n                    ca_country = 'United States'\n                and\n                    ca_state in ('WI', 'CT', 'KY')\n                and ws_net_profit between 150 and 300\n            )\n        or\n        (\n                    ca_country = 'United States'\n                and\n                    ca_state in ('LA', 'IA', 'AR')\n                and ws_net_profit between 50 and 250\n            )\n    )\ngroup by r_reason_desc\norder by substr(r_reason_desc, 1, 20)\n       , avg(ws_quantity)\n       , avg(wr_refunded_cash)\n       , avg(wr_fee) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query86.sql",
    "content": "select sum(ws_net_paid)                         as total_sum\n     , i_category\n     , i_class\n     , grouping(i_category) + grouping(i_class) as lochierarchy\n     , rank()                                      over (\n \tpartition by grouping(i_category)+grouping(i_class),\n \tcase when grouping(i_class) = 0 then i_category end \n \torder by sum(ws_net_paid) desc) as rank_within_parent\nfrom web_sales\n   , date_dim d1\n   , item\nwhere d1.d_month_seq between 1200 and 1200 + 11\n  and d1.d_date_sk = ws_sold_date_sk\n  and i_item_sk = ws_item_sk\ngroup by rollup (i_category, i_class)\norder by lochierarchy desc,\n         case when lochierarchy = 0 then i_category end,\n         rank_within_parent limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query87.sql",
    "content": "select count(*)\nfrom ((select distinct c_last_name, c_first_name, d_date\n       from store_sales,\n            date_dim,\n            customer\n       where store_sales.ss_sold_date_sk = date_dim.d_date_sk\n         and store_sales.ss_customer_sk = customer.c_customer_sk\n         and d_month_seq between 1200 and 1200 + 11)\n      except\n      (select distinct c_last_name, c_first_name, d_date\n       from catalog_sales,\n            date_dim,\n            customer\n       where catalog_sales.cs_sold_date_sk = date_dim.d_date_sk\n         and catalog_sales.cs_bill_customer_sk = customer.c_customer_sk\n         and d_month_seq between 1200 and 1200 + 11)\n      except\n      (select distinct c_last_name, c_first_name, d_date\n       from web_sales,\n            date_dim,\n            customer\n       where web_sales.ws_sold_date_sk = date_dim.d_date_sk\n         and web_sales.ws_bill_customer_sk = customer.c_customer_sk\n         and d_month_seq between 1200 and 1200 + 11)) cool_cust\n\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query88.sql",
    "content": "select *\nfrom (select count(*) h8_30_to_9\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 8\n        and time_dim.t_minute >= 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s1,\n     (select count(*) h9_to_9_30\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 9\n        and time_dim.t_minute < 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s2,\n     (select count(*) h9_30_to_10\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 9\n        and time_dim.t_minute >= 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s3,\n     (select count(*) h10_to_10_30\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 10\n        and time_dim.t_minute < 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s4,\n     (select count(*) h10_30_to_11\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 10\n        and time_dim.t_minute >= 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s5,\n     (select count(*) h11_to_11_30\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 11\n        and time_dim.t_minute < 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s6,\n     (select count(*) h11_30_to_12\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 11\n        and time_dim.t_minute >= 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s7,\n     (select count(*) h12_to_12_30\n      from store_sales,\n           household_demographics,\n           time_dim,\n           store\n      where ss_sold_time_sk = time_dim.t_time_sk\n        and ss_hdemo_sk = household_demographics.hd_demo_sk\n        and ss_store_sk = s_store_sk\n        and time_dim.t_hour = 12\n        and time_dim.t_minute < 30\n        and ((household_demographics.hd_dep_count = 4 and household_demographics.hd_vehicle_count <= 4 + 2) or\n             (household_demographics.hd_dep_count = 2 and household_demographics.hd_vehicle_count <= 2 + 2) or\n             (household_demographics.hd_dep_count = 0 and household_demographics.hd_vehicle_count <= 0 + 2))\n        and store.s_store_name = 'ese') s8\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query89.sql",
    "content": "select *\nfrom (select i_category,\n             i_class,\n             i_brand,\n             s_store_name,\n             s_company_name,\n             d_moy,\n             sum(ss_sales_price)      sum_sales,\n             avg(sum(ss_sales_price)) over (partition by i_category, i_brand, s_store_name, s_company_name)\n         avg_monthly_sales\n      from item,\n           store_sales,\n           date_dim,\n           store\n      where ss_item_sk = i_item_sk\n        and ss_sold_date_sk = d_date_sk\n        and ss_store_sk = s_store_sk\n        and d_year in (1999)\n        and ((i_category in ('Books', 'Electronics', 'Sports') and\n              i_class in ('computers', 'stereo', 'football')\n                 )\n          or (i_category in ('Men', 'Jewelry', 'Women') and\n              i_class in ('shirts', 'birdal', 'dresses')\n                 ))\n      group by i_category, i_class, i_brand,\n               s_store_name, s_company_name, d_moy) tmp1\nwhere case when (avg_monthly_sales <> 0) then (abs(sum_sales - avg_monthly_sales) / avg_monthly_sales) else null end >\n      0.1\norder by sum_sales - avg_monthly_sales, s_store_name limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query90.sql",
    "content": "select cast(amc as decimal(15, 4)) / cast(pmc as decimal(15, 4)) am_pm_ratio\nfrom (select count(*) amc\n      from web_sales,\n           household_demographics,\n           time_dim,\n           web_page\n      where ws_sold_time_sk = time_dim.t_time_sk\n        and ws_ship_hdemo_sk = household_demographics.hd_demo_sk\n        and ws_web_page_sk = web_page.wp_web_page_sk\n        and time_dim.t_hour between 8 and 8 + 1\n        and household_demographics.hd_dep_count = 6\n        and web_page.wp_char_count between 5000 and 5200) at1,\n     (select count(*) pmc\n      from web_sales,\n           household_demographics,\n           time_dim,\n           web_page\n      where ws_sold_time_sk = time_dim.t_time_sk\n        and ws_ship_hdemo_sk = household_demographics.hd_demo_sk\n        and ws_web_page_sk = web_page.wp_web_page_sk\n        and time_dim.t_hour between 19 and 19 + 1\n        and household_demographics.hd_dep_count = 6\n        and web_page.wp_char_count between 5000 and 5200) pt\norder by am_pm_ratio limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query91.sql",
    "content": "select cc_call_center_id Call_Center,\n       cc_name           Call_Center_Name,\n       cc_manager        Manager,\n       sum(cr_net_loss)  Returns_Loss\nfrom call_center,\n     catalog_returns,\n     date_dim,\n     customer,\n     customer_address,\n     customer_demographics,\n     household_demographics\nwhere cr_call_center_sk = cc_call_center_sk\n  and cr_returned_date_sk = d_date_sk\n  and cr_returning_customer_sk = c_customer_sk\n  and cd_demo_sk = c_current_cdemo_sk\n  and hd_demo_sk = c_current_hdemo_sk\n  and ca_address_sk = c_current_addr_sk\n  and d_year = 1998\n  and d_moy = 11\n  and ((cd_marital_status = 'M' and cd_education_status = 'Unknown')\n    or (cd_marital_status = 'W' and cd_education_status = 'Advanced Degree'))\n  and hd_buy_potential like 'Unknown%'\n  and ca_gmt_offset = -7\ngroup by cc_call_center_id, cc_name, cc_manager, cd_marital_status, cd_education_status\norder by sum(cr_net_loss) desc\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query92.sql",
    "content": "select sum(ws_ext_discount_amt) as Excess_Discount_Amount\nfrom web_sales\n   , item\n   , date_dim\nwhere i_manufact_id = 350\n  and i_item_sk = ws_item_sk\n  and d_date between '2000-01-27' and\n    date_add(cast('2000-01-27' as date), 90)\n  and d_date_sk = ws_sold_date_sk\n  and ws_ext_discount_amt\n    > (SELECT 1.3 * avg(ws_ext_discount_amt)\n       FROM web_sales\n          , date_dim\n       WHERE ws_item_sk = i_item_sk\n         and d_date between '2000-01-27' and\n           date_add(cast('2000-01-27' as date), 90)\n         and d_date_sk = ws_sold_date_sk)\norder by sum(ws_ext_discount_amt) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query93.sql",
    "content": "select ss_customer_sk\n     , sum(act_sales) sumsales\nfrom (select ss_item_sk\n           , ss_ticket_number\n           , ss_customer_sk\n           , case\n                 when sr_return_quantity is not null then (ss_quantity - sr_return_quantity) * ss_sales_price\n                 else (ss_quantity * ss_sales_price) end act_sales\n      from store_sales\n               left outer join store_returns on (sr_item_sk = ss_item_sk\n          and sr_ticket_number = ss_ticket_number)\n         , reason\n      where sr_reason_sk = r_reason_sk\n        and r_reason_desc = 'reason 28') t\ngroup by ss_customer_sk\norder by sumsales, ss_customer_sk limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query94.sql",
    "content": "select count(distinct ws_order_number) as order_count\n     , sum(ws_ext_ship_cost)           as total_shipping_cost\n     , sum(ws_net_profit)              as total_net_profit\nfrom web_sales ws1\n   , date_dim\n   , customer_address\n   , web_site\nwhere d_date between cast('1999-2-01' as date) and\n    date_add(cast('1999-2-01' as date), 60)\n  and ws1.ws_ship_date_sk = d_date_sk\n  and ws1.ws_ship_addr_sk = ca_address_sk\n  and ca_state = 'IL'\n  and ws1.ws_web_site_sk = web_site_sk\n  and web_company_name = 'pri'\n  and exists(select *\n             from web_sales ws2\n             where ws1.ws_order_number = ws2.ws_order_number\n               and ws1.ws_warehouse_sk <> ws2.ws_warehouse_sk)\n  and not exists(select *\n                 from web_returns wr1\n                 where ws1.ws_order_number = wr1.wr_order_number)\norder by count(distinct ws_order_number) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query95.sql",
    "content": "with ws_wh as\n         (select ws1.ws_order_number, ws1.ws_warehouse_sk wh1, ws2.ws_warehouse_sk wh2\n          from web_sales ws1,\n               web_sales ws2\n          where ws1.ws_order_number = ws2.ws_order_number\n            and ws1.ws_warehouse_sk <> ws2.ws_warehouse_sk)\nselect count(distinct ws_order_number) as order_count\n     , sum(ws_ext_ship_cost)           as total_shipping_cost\n     , sum(ws_net_profit)              as total_net_profit\nfrom web_sales ws1\n   , date_dim\n   , customer_address\n   , web_site\nwhere d_date between '1999-2-01' and\n    date_add(cast('1999-2-01' as date), 60)\n  and ws1.ws_ship_date_sk = d_date_sk\n  and ws1.ws_ship_addr_sk = ca_address_sk\n  and ca_state = 'IL'\n  and ws1.ws_web_site_sk = web_site_sk\n  and web_company_name = 'pri'\n  and ws1.ws_order_number in (select ws_order_number\n                              from ws_wh)\n  and ws1.ws_order_number in (select wr_order_number\n                              from web_returns,\n                                   ws_wh\n                              where wr_order_number = ws_wh.ws_order_number)\norder by count(distinct ws_order_number) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query96.sql",
    "content": "select count(*)\nfrom store_sales\n   , household_demographics\n   , time_dim\n   , store\nwhere ss_sold_time_sk = time_dim.t_time_sk\n  and ss_hdemo_sk = household_demographics.hd_demo_sk\n  and ss_store_sk = s_store_sk\n  and time_dim.t_hour = 20\n  and time_dim.t_minute >= 30\n  and household_demographics.hd_dep_count = 7\n  and store.s_store_name = 'ese'\norder by count(*) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query97.sql",
    "content": "with ssci as (select ss_customer_sk customer_sk\n                   , ss_item_sk     item_sk\n              from store_sales,\n                   date_dim\n              where ss_sold_date_sk = d_date_sk\n                and d_month_seq between 1200 and 1200 + 11\n              group by ss_customer_sk\n                     , ss_item_sk),\n     csci as (select cs_bill_customer_sk customer_sk\n                   , cs_item_sk          item_sk\n              from catalog_sales,\n                   date_dim\n              where cs_sold_date_sk = d_date_sk\n                and d_month_seq between 1200 and 1200 + 11\n              group by cs_bill_customer_sk\n                     , cs_item_sk)\nselect sum(case when ssci.customer_sk is not null and csci.customer_sk is null then 1 else 0 end)     store_only\n     , sum(case when ssci.customer_sk is null and csci.customer_sk is not null then 1 else 0 end)     catalog_only\n     , sum(case when ssci.customer_sk is not null and csci.customer_sk is not null then 1 else 0 end) store_and_catalog\nfrom ssci\n         full outer join csci on (ssci.customer_sk = csci.customer_sk\n    and ssci.item_sk = csci.item_sk) limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query98.sql",
    "content": "select i_item_id\n     , i_item_desc\n     , i_category\n     , i_class\n     , i_current_price\n     , sum(ss_ext_sales_price) as                                   itemrevenue\n     , sum(ss_ext_sales_price) * 100 / sum(sum(ss_ext_sales_price)) over (partition by i_class) as revenueratio\nfrom store_sales\n   , item\n   , date_dim\nwhere ss_item_sk = i_item_sk\n  and i_category in ('Sports', 'Books', 'Home')\n  and ss_sold_date_sk = d_date_sk\n  and d_date between cast('1999-02-22' as date)\n    and date_add(cast('1999-02-22' as date), 30)\ngroup by i_item_id\n       , i_item_desc\n       , i_category\n       , i_class\n       , i_current_price\norder by i_category\n       , i_class\n       , i_item_id\n       , i_item_desc\n       , revenueratio\n"
  },
  {
    "path": "core/src/main/resources/tpcds/query99.sql",
    "content": "select substr(w_warehouse_name, 1, 20)\n     , sm_type\n     , cc_name\n     , sum(case when (cs_ship_date_sk - cs_sold_date_sk <= 30) then 1 else 0 end) as \"30_days\"\n     , sum(case\n               when (cs_ship_date_sk - cs_sold_date_sk > 30) and\n                    (cs_ship_date_sk - cs_sold_date_sk <= 60) then 1\n               else 0 end)                                                        as \"31_60_days\"\n     , sum(case\n               when (cs_ship_date_sk - cs_sold_date_sk > 60) and\n                    (cs_ship_date_sk - cs_sold_date_sk <= 90) then 1\n               else 0 end)                                                        as \"61_90_days\"\n     , sum(case\n               when (cs_ship_date_sk - cs_sold_date_sk > 90) and\n                    (cs_ship_date_sk - cs_sold_date_sk <= 120) then 1\n               else 0 end)                                                        as \"91_120_days\"\n     , sum(case when (cs_ship_date_sk - cs_sold_date_sk > 120) then 1 else 0 end) as above120_days\nfrom catalog_sales\n   , warehouse\n   , ship_mode\n   , call_center\n   , date_dim\nwhere d_month_seq between 1200 and 1200 + 11\n  and cs_ship_date_sk = d_date_sk\n  and cs_warehouse_sk = w_warehouse_sk\n  and cs_ship_mode_sk = sm_ship_mode_sk\n  and cs_call_center_sk = cc_call_center_sk\ngroup by substr(w_warehouse_name, 1, 20)\n       , sm_type\n       , cc_name\norder by substr(w_warehouse_name, 1, 20)\n       , sm_type\n       , cc_name limit 100\n"
  },
  {
    "path": "core/src/main/resources/tpch/create_tables.sql",
    "content": "create table nation\n(\n    N_NATIONKEY INT,\n    N_NAME      STRING,\n    N_REGIONKEY INT,\n    N_COMMENT   STRING,\n    primary key (N_NATIONKEY)\n);\n\ncreate table lineitem\n(\n    L_ORDERKEY      INT,\n    L_PARTKEY       INT,\n    L_SUPPKEY       INT,\n    L_LINENUMBER    INT,\n    L_QUANTITY      DOUBLE,\n    L_EXTENDEDPRICE DOUBLE,\n    L_DISCOUNT      DOUBLE,\n    L_TAX           DOUBLE,\n    L_RETURNFLAG    STRING,\n    L_LINESTATUS    STRING,\n    L_SHIPDATE      STRING,\n    L_COMMITDATE    STRING,\n    L_RECEIPTDATE   STRING,\n    L_SHIPINSTRUCT  STRING,\n    L_SHIPMODE      STRING,\n    L_COMMENT       STRING,\n    primary key (L_ORDERKEY, L_PARTKEY, L_SUPPKEY, L_LINENUMBER)\n);\n\ncreate table orders\n(\n    O_ORDERKEY      INT,\n    O_CUSTKEY       INT,\n    O_ORDERSTATUS   STRING,\n    O_TOTALPRICE    DOUBLE,\n    O_ORDERDATE     STRING,\n    O_ORDERPRIORITY STRING,\n    O_CLERK         STRING,\n    O_SHIPPRIORITY  INT,\n    O_COMMENT       STRING,\n    primary key (O_ORDERKEY)\n);\n\ncreate table supplier\n(\n    S_SUPPKEY   INT,\n    S_NAME      STRING,\n    S_ADDRESS   STRING,\n    S_NATIONKEY INT,\n    S_PHONE     STRING,\n    S_ACCTBAL   DOUBLE,\n    S_COMMENT   STRING,\n    primary key (S_SUPPKEY)\n);\n\ncreate table partsupp\n(\n    PS_PARTKEY    INT,\n    PS_SUPPKEY    INT,\n    PS_AVAILQTY   INT,\n    PS_SUPPLYCOST DOUBLE,\n    PS_COMMENT    STRING,\n    primary key (PS_PARTKEY, PS_SUPPKEY)\n);\n\ncreate table customer\n(\n    C_CUSTKEY    INT,\n    C_NAME       STRING,\n    C_ADDRESS    STRING,\n    C_NATIONKEY  INT,\n    C_PHONE      STRING,\n    C_ACCTBAL    DOUBLE,\n    C_MKTSEGMENT STRING,\n    C_COMMENT    STRING,\n    primary key (C_CUSTKEY)\n);\n\ncreate table part\n(\n    P_PARTKEY     INT,\n    P_NAME        STRING,\n    P_MFGR        STRING,\n    P_BRAND       STRING,\n    P_TYPE        STRING,\n    P_SIZE        INT,\n    P_CONTAINER   STRING,\n    P_RETAILPRICE DOUBLE,\n    P_COMMENT     STRING,\n    primary key (P_PARTKEY)\n);\n\ncreate table region\n(\n    R_REGIONKEY INT,\n    R_NAME      STRING,\n    R_COMMENT   STRING,\n    primary key (R_REGIONKEY)\n);\n"
  },
  {
    "path": "core/src/main/resources/tpch/insert_lineitem_200.sql",
    "content": "insert into lineitem\nVALUES (1, 15519, 785, 1, 17, 24386.67, 0.04, 0.02, 'N', 'O', '1996-03-13', '1996-02-12', '1996-03-22',\n        'DELIVER IN PERSON', 'TRUCK', 'egular courts above the'),\n       (1, 6731, 732, 2, 36, 58958.28, 0.09, 0.06, 'N', 'O', '1996-04-12', '1996-02-28', '1996-04-20',\n        'TAKE BACK RETURN', 'MAIL', 'ly final dependencies: slyly bold '),\n       (1, 6370, 371, 3, 8, 10210.96, 0.10, 0.02, 'N', 'O', '1996-01-29', '1996-03-05', '1996-01-31',\n        'TAKE BACK RETURN', 'REG AIR', 'riously. regular, express dep'),\n       (1, 214, 465, 4, 28, 31197.88, 0.09, 0.06, 'N', 'O', '1996-04-21', '1996-03-30', '1996-05-16', 'NONE', 'AIR',\n        'lites. fluffily even de'),\n       (1, 2403, 160, 5, 24, 31329.60, 0.10, 0.04, 'N', 'O', '1996-03-30', '1996-03-14', '1996-04-01', 'NONE', 'FOB',\n        ' pending foxes. slyly re'),\n       (1, 1564, 67, 6, 32, 46897.92, 0.07, 0.02, 'N', 'O', '1996-01-30', '1996-02-07', '1996-02-03',\n        'DELIVER IN PERSON', 'MAIL', 'arefully slyly ex'),\n       (2, 10617, 138, 1, 38, 58049.18, 0.00, 0.05, 'N', 'O', '1997-01-28', '1997-01-14', '1997-02-02',\n        'TAKE BACK RETURN', 'RAIL', 'ven requests. deposits breach a'),\n       (3, 430, 181, 1, 45, 59869.35, 0.06, 0.00, 'R', 'F', '1994-02-02', '1994-01-04', '1994-02-23', 'NONE', 'AIR',\n        'ongside of the furiously brave acco'),\n       (3, 1904, 658, 2, 49, 88489.10, 0.10, 0.00, 'R', 'F', '1993-11-09', '1993-12-20', '1993-11-24',\n        'TAKE BACK RETURN', 'RAIL', ' unusual accounts. eve'),\n       (3, 12845, 370, 3, 27, 47461.68, 0.06, 0.07, 'A', 'F', '1994-01-16', '1993-11-22', '1994-01-23',\n        'DELIVER IN PERSON', 'SHIP', 'nal foxes wake. '),\n       (3, 2938, 191, 4, 2, 3681.86, 0.01, 0.06, 'A', 'F', '1993-12-04', '1994-01-07', '1994-01-01', 'NONE', 'TRUCK',\n        'y. fluffily pending d'),\n       (3, 18310, 115, 5, 28, 34392.68, 0.04, 0.00, 'R', 'F', '1993-12-14', '1994-01-10', '1994-01-01',\n        'TAKE BACK RETURN', 'FOB', 'ages nag slyly pending'),\n       (3, 6215, 984, 6, 26, 29151.46, 0.10, 0.02, 'A', 'F', '1993-10-29', '1993-12-18', '1993-11-04',\n        'TAKE BACK RETURN', 'RAIL', 'ges sleep after the caref'),\n       (4, 8804, 579, 1, 30, 51384.00, 0.03, 0.08, 'N', 'O', '1996-01-10', '1995-12-14', '1996-01-18',\n        'DELIVER IN PERSON', 'REG AIR', '- quickly regular packages sleep. idly'),\n       (5, 10857, 858, 1, 15, 26517.75, 0.02, 0.04, 'R', 'F', '1994-10-31', '1994-08-31', '1994-11-20', 'NONE', 'AIR',\n        'ts wake furiously '),\n       (5, 12393, 394, 2, 26, 33940.14, 0.07, 0.08, 'R', 'F', '1994-10-16', '1994-09-25', '1994-10-19', 'NONE', 'FOB',\n        'sts use slyly quickly special instruc'),\n       (5, 3754, 8, 3, 50, 82887.50, 0.08, 0.03, 'A', 'F', '1994-08-08', '1994-10-13', '1994-08-26',\n        'DELIVER IN PERSON', 'AIR', 'eodolites. fluffily unusual'),\n       (6, 13964, 228, 1, 37, 69484.52, 0.08, 0.03, 'A', 'F', '1992-04-27', '1992-05-15', '1992-05-02',\n        'TAKE BACK RETURN', 'TRUCK', 'p furiously special foxes'),\n       (7, 18206, 11, 1, 12, 13490.40, 0.07, 0.03, 'N', 'O', '1996-05-07', '1996-03-13', '1996-06-03',\n        'TAKE BACK RETURN', 'FOB', 'ss pinto beans wake against th'),\n       (7, 14525, 790, 2, 9, 12955.68, 0.08, 0.08, 'N', 'O', '1996-02-01', '1996-03-02', '1996-02-19',\n        'TAKE BACK RETURN', 'SHIP', 'es. instructions'),\n       (7, 9478, 997, 3, 46, 63823.62, 0.10, 0.07, 'N', 'O', '1996-01-15', '1996-03-27', '1996-02-03', 'COLLECT COD',\n        'MAIL', ' unusual reques'),\n       (7, 16308, 309, 4, 28, 34280.40, 0.03, 0.04, 'N', 'O', '1996-03-21', '1996-04-08', '1996-04-20', 'NONE', 'FOB',\n        '. slyly special requests haggl'),\n       (7, 15190, 986, 5, 38, 41997.22, 0.08, 0.01, 'N', 'O', '1996-02-11', '1996-02-24', '1996-02-18',\n        'DELIVER IN PERSON', 'TRUCK', 'ns haggle carefully ironic deposits. bl'),\n       (7, 7926, 184, 6, 35, 64187.20, 0.06, 0.03, 'N', 'O', '1996-01-16', '1996-02-23', '1996-01-22',\n        'TAKE BACK RETURN', 'FOB', 'jole. excuses wake carefully alongside of '),\n       (7, 15724, 255, 7, 5, 8198.60, 0.04, 0.02, 'N', 'O', '1996-02-10', '1996-03-26', '1996-02-13', 'NONE', 'FOB',\n        'ithely regula'),\n       (32, 8271, 788, 1, 28, 33019.56, 0.05, 0.08, 'N', 'O', '1995-10-23', '1995-08-27', '1995-10-26',\n        'TAKE BACK RETURN', 'TRUCK', 'sleep quickly. req'),\n       (32, 19793, 63, 2, 32, 54809.28, 0.02, 0.00, 'N', 'O', '1995-08-14', '1995-10-07', '1995-08-27', 'COLLECT COD',\n        'AIR', 'lithely regular deposits. fluffily '),\n       (32, 4417, 672, 3, 2, 2642.82, 0.09, 0.02, 'N', 'O', '1995-08-07', '1995-10-07', '1995-08-23',\n        'DELIVER IN PERSON', 'AIR', ' express accounts wake according to the'),\n       (32, 275, 776, 4, 4, 4701.08, 0.09, 0.03, 'N', 'O', '1995-08-04', '1995-10-01', '1995-09-03', 'NONE', 'REG AIR',\n        'e slyly final pac'),\n       (32, 8582, 841, 5, 44, 65585.52, 0.05, 0.06, 'N', 'O', '1995-08-28', '1995-08-20', '1995-09-14',\n        'DELIVER IN PERSON', 'AIR', 'symptotes nag according to the ironic depo'),\n       (32, 1162, 414, 6, 6, 6378.96, 0.04, 0.03, 'N', 'O', '1995-07-21', '1995-09-23', '1995-07-25', 'COLLECT COD',\n        'RAIL', ' gifts cajole carefully.'),\n       (33, 6134, 903, 1, 31, 32244.03, 0.09, 0.04, 'A', 'F', '1993-10-29', '1993-12-19', '1993-11-08', 'COLLECT COD',\n        'TRUCK', 'ng to the furiously ironic package'),\n       (33, 6052, 565, 2, 32, 30657.60, 0.02, 0.05, 'A', 'F', '1993-12-09', '1994-01-04', '1993-12-28', 'COLLECT COD',\n        'MAIL', 'gular theodolites'),\n       (33, 13747, 11, 3, 5, 8303.70, 0.05, 0.03, 'A', 'F', '1993-12-09', '1993-12-25', '1993-12-23',\n        'TAKE BACK RETURN', 'AIR', '. stealthily bold exc'),\n       (33, 3392, 393, 4, 41, 53110.99, 0.09, 0.00, 'R', 'F', '1993-11-09', '1994-01-24', '1993-11-11',\n        'TAKE BACK RETURN', 'MAIL', 'unusual packages doubt caref'),\n       (34, 8837, 96, 1, 13, 22695.79, 0.00, 0.07, 'N', 'O', '1998-10-23', '1998-09-14', '1998-11-06', 'NONE',\n        'REG AIR', 'nic accounts. deposits are alon'),\n       (34, 8942, 201, 2, 22, 40720.68, 0.08, 0.06, 'N', 'O', '1998-10-09', '1998-10-16', '1998-10-12', 'NONE', 'FOB',\n        'thely slyly p'),\n       (34, 16955, 488, 3, 6, 11231.70, 0.02, 0.06, 'N', 'O', '1998-10-30', '1998-09-20', '1998-11-05', 'NONE', 'FOB',\n        'ar foxes sleep '),\n       (35, 45, 296, 1, 24, 22680.96, 0.02, 0.00, 'N', 'O', '1996-02-21', '1996-01-03', '1996-03-18',\n        'TAKE BACK RETURN', 'FOB', ', regular tithe'),\n       (35, 16194, 461, 2, 34, 37746.46, 0.06, 0.08, 'N', 'O', '1996-01-22', '1996-01-06', '1996-01-27',\n        'DELIVER IN PERSON', 'RAIL', 's are carefully against the f'),\n       (35, 12090, 877, 3, 7, 7014.63, 0.06, 0.04, 'N', 'O', '1996-01-19', '1995-12-22', '1996-01-29', 'NONE', 'MAIL',\n        ' the carefully regular '),\n       (35, 8518, 777, 4, 25, 35662.75, 0.06, 0.05, 'N', 'O', '1995-11-26', '1995-12-25', '1995-12-21',\n        'DELIVER IN PERSON', 'SHIP', ' quickly unti'),\n       (35, 11992, 515, 5, 34, 64735.66, 0.08, 0.06, 'N', 'O', '1995-11-08', '1996-01-15', '1995-11-26', 'COLLECT COD',\n        'MAIL', '. silent, unusual deposits boost'),\n       (35, 3077, 331, 6, 28, 27441.96, 0.03, 0.02, 'N', 'O', '1996-02-01', '1995-12-24', '1996-02-28', 'COLLECT COD',\n        'RAIL', 'ly alongside of '),\n       (36, 11977, 978, 1, 42, 79336.74, 0.09, 0.00, 'N', 'O', '1996-02-03', '1996-01-21', '1996-02-23', 'COLLECT COD',\n        'SHIP', ' careful courts. special '),\n       (37, 2263, 516, 1, 40, 46610.40, 0.09, 0.03, 'A', 'F', '1992-07-21', '1992-08-01', '1992-08-15', 'NONE',\n        'REG AIR', 'luffily regular requests. slyly final acco'),\n       (37, 12679, 204, 2, 39, 62075.13, 0.05, 0.02, 'A', 'F', '1992-07-02', '1992-08-18', '1992-07-28',\n        'TAKE BACK RETURN', 'RAIL', 'the final requests. ca'),\n       (37, 1291, 543, 3, 43, 51268.47, 0.05, 0.08, 'A', 'F', '1992-07-10', '1992-07-06', '1992-08-02',\n        'DELIVER IN PERSON', 'TRUCK', 'iously ste'),\n       (38, 17584, 119, 1, 44, 66069.52, 0.04, 0.02, 'N', 'O', '1996-09-29', '1996-11-17', '1996-09-30', 'COLLECT COD',\n        'MAIL', 's. blithely unusual theodolites am'),\n       (39, 232, 983, 1, 44, 49818.12, 0.09, 0.06, 'N', 'O', '1996-11-14', '1996-12-15', '1996-12-12', 'COLLECT COD',\n        'RAIL', 'eodolites. careful'),\n       (39, 18659, 464, 2, 26, 41018.90, 0.08, 0.04, 'N', 'O', '1996-11-04', '1996-10-20', '1996-11-20', 'NONE', 'FOB',\n        'ckages across the slyly silent'),\n       (39, 6784, 553, 3, 46, 77775.88, 0.06, 0.08, 'N', 'O', '1996-09-26', '1996-12-19', '1996-10-26',\n        'DELIVER IN PERSON', 'AIR', 'he carefully e'),\n       (39, 2059, 312, 4, 32, 30753.60, 0.07, 0.05, 'N', 'O', '1996-10-02', '1996-12-19', '1996-10-14', 'COLLECT COD',\n        'MAIL', 'heodolites sleep silently pending foxes. ac'),\n       (39, 5452, 963, 5, 43, 58370.35, 0.01, 0.01, 'N', 'O', '1996-10-17', '1996-11-14', '1996-10-26', 'COLLECT COD',\n        'MAIL', 'yly regular i'),\n       (39, 9437, 697, 6, 40, 53857.20, 0.06, 0.05, 'N', 'O', '1996-12-08', '1996-10-22', '1997-01-01', 'COLLECT COD',\n        'AIR', 'quickly ironic fox'),\n       (64, 8596, 597, 1, 21, 31596.39, 0.05, 0.02, 'R', 'F', '1994-09-30', '1994-09-18', '1994-10-26',\n        'DELIVER IN PERSON', 'REG AIR', 'ch slyly final, thin platelets.'),\n       (65, 5970, 481, 1, 26, 48775.22, 0.03, 0.03, 'A', 'F', '1995-04-20', '1995-04-25', '1995-05-13', 'NONE', 'TRUCK',\n        'pending deposits nag even packages. ca'),\n       (65, 7382, 897, 2, 22, 28366.36, 0.00, 0.05, 'N', 'O', '1995-07-17', '1995-06-04', '1995-07-19', 'COLLECT COD',\n        'FOB', ' ideas. special, r'),\n       (65, 139, 390, 3, 21, 21821.73, 0.09, 0.07, 'N', 'O', '1995-07-06', '1995-05-14', '1995-07-31',\n        'DELIVER IN PERSON', 'RAIL', 'bove the even packages. accounts nag carefu'),\n       (66, 11512, 774, 1, 31, 44128.81, 0.00, 0.08, 'R', 'F', '1994-02-19', '1994-03-11', '1994-02-20',\n        'TAKE BACK RETURN', 'RAIL', 'ut the unusual accounts sleep at the bo'),\n       (66, 17349, 350, 2, 41, 51919.94, 0.04, 0.07, 'A', 'F', '1994-02-21', '1994-03-01', '1994-03-18', 'COLLECT COD',\n        'AIR', ' regular de'),\n       (67, 2164, 921, 1, 4, 4264.64, 0.09, 0.04, 'N', 'O', '1997-04-17', '1997-01-31', '1997-04-20', 'NONE', 'SHIP',\n        ' cajole thinly expres'),\n       (67, 2020, 525, 2, 12, 11064.24, 0.09, 0.05, 'N', 'O', '1997-01-27', '1997-02-21', '1997-02-22', 'NONE',\n        'REG AIR', ' even packages cajole'),\n       (67, 17360, 628, 3, 5, 6386.80, 0.03, 0.07, 'N', 'O', '1997-02-20', '1997-02-12', '1997-02-21',\n        'DELIVER IN PERSON', 'TRUCK', 'y unusual packages thrash pinto '),\n       (67, 8752, 753, 4, 44, 73073.00, 0.08, 0.06, 'N', 'O', '1997-03-18', '1997-01-29', '1997-04-13',\n        'DELIVER IN PERSON', 'RAIL', 'se quickly above the even, express reques'),\n       (67, 4062, 825, 5, 23, 22219.38, 0.05, 0.07, 'N', 'O', '1997-04-19', '1997-02-14', '1997-05-06',\n        'DELIVER IN PERSON', 'REG AIR', 'ly regular deposit'),\n       (67, 17831, 99, 6, 29, 50716.07, 0.02, 0.05, 'N', 'O', '1997-01-25', '1997-01-27', '1997-01-27',\n        'DELIVER IN PERSON', 'FOB', 'ultipliers '),\n       (68, 707, 958, 1, 3, 4823.10, 0.05, 0.02, 'N', 'O', '1998-07-04', '1998-06-05', '1998-07-21', 'NONE', 'RAIL',\n        'fully special instructions cajole. furious'),\n       (68, 17518, 320, 2, 46, 66033.46, 0.02, 0.05, 'N', 'O', '1998-06-26', '1998-06-07', '1998-07-05', 'NONE', 'MAIL',\n        ' requests are unusual, regular pinto '),\n       (68, 3498, 752, 3, 46, 64468.54, 0.04, 0.05, 'N', 'O', '1998-08-13', '1998-07-08', '1998-08-29', 'NONE', 'RAIL',\n        'egular dependencies affix ironically along '),\n       (68, 9473, 251, 4, 20, 27649.40, 0.07, 0.01, 'N', 'O', '1998-06-27', '1998-05-23', '1998-07-02', 'NONE',\n        'REG AIR', ' excuses integrate fluffily '),\n       (68, 8276, 535, 5, 27, 31975.29, 0.03, 0.06, 'N', 'O', '1998-06-19', '1998-06-25', '1998-06-29',\n        'DELIVER IN PERSON', 'SHIP', 'ccounts. deposits use. furiously'),\n       (68, 10257, 518, 6, 30, 35017.50, 0.05, 0.06, 'N', 'O', '1998-08-11', '1998-07-11', '1998-08-14', 'NONE', 'RAIL',\n        'oxes are slyly blithely fin'),\n       (68, 13925, 189, 7, 41, 75395.72, 0.09, 0.08, 'N', 'O', '1998-06-24', '1998-06-27', '1998-07-06', 'NONE', 'SHIP',\n        'eposits nag special ideas. furiousl'),\n       (69, 11521, 783, 1, 48, 68760.96, 0.01, 0.07, 'A', 'F', '1994-08-17', '1994-08-11', '1994-09-08', 'NONE',\n        'TRUCK', 'regular epitaphs. carefully even ideas hag'),\n       (69, 10418, 939, 2, 32, 42509.12, 0.08, 0.06, 'A', 'F', '1994-08-24', '1994-08-17', '1994-08-31', 'NONE',\n        'REG AIR', 's sleep carefully bold, '),\n       (69, 13727, 517, 3, 17, 27892.24, 0.09, 0.00, 'A', 'F', '1994-07-02', '1994-07-07', '1994-07-03',\n        'TAKE BACK RETURN', 'AIR', 'final, pending instr'),\n       (69, 3751, 258, 4, 3, 4964.25, 0.09, 0.04, 'R', 'F', '1994-06-06', '1994-07-27', '1994-06-15', 'NONE', 'MAIL',\n        ' blithely final d'),\n       (69, 9207, 726, 5, 42, 46880.40, 0.07, 0.04, 'R', 'F', '1994-07-31', '1994-07-26', '1994-08-28',\n        'DELIVER IN PERSON', 'REG AIR', 'tect regular, speci'),\n       (69, 1851, 103, 6, 23, 40315.55, 0.05, 0.00, 'A', 'F', '1994-10-03', '1994-08-06', '1994-10-24', 'NONE', 'SHIP',\n        'nding accounts ca'),\n       (70, 6413, 926, 1, 8, 10555.28, 0.03, 0.08, 'R', 'F', '1994-01-12', '1994-02-27', '1994-01-14',\n        'TAKE BACK RETURN', 'FOB', 'ggle. carefully pending dependenc'),\n       (70, 19616, 155, 2, 13, 19962.93, 0.06, 0.06, 'A', 'F', '1994-03-03', '1994-02-13', '1994-03-26', 'COLLECT COD',\n        'AIR', 'lyly special packag'),\n       (70, 17981, 783, 3, 1, 1898.98, 0.03, 0.05, 'R', 'F', '1994-01-26', '1994-03-05', '1994-01-28',\n        'TAKE BACK RETURN', 'RAIL', 'quickly. fluffily unusual theodolites c'),\n       (70, 4574, 83, 4, 11, 16264.27, 0.01, 0.05, 'A', 'F', '1994-03-17', '1994-03-17', '1994-03-27', 'NONE', 'MAIL',\n        'alongside of the deposits. fur'),\n       (70, 3714, 221, 5, 37, 59855.27, 0.09, 0.04, 'R', 'F', '1994-02-13', '1994-03-16', '1994-02-21', 'COLLECT COD',\n        'MAIL', 'n accounts are. q'),\n       (70, 5566, 332, 6, 19, 27959.64, 0.06, 0.03, 'A', 'F', '1994-01-26', '1994-02-17', '1994-02-06',\n        'TAKE BACK RETURN', 'SHIP', ' packages wake pending accounts.'),\n       (71, 6194, 195, 1, 25, 27504.75, 0.09, 0.07, 'N', 'O', '1998-04-10', '1998-04-22', '1998-04-11', 'COLLECT COD',\n        'FOB', 'ckly. slyly'),\n       (71, 6592, 361, 2, 3, 4495.77, 0.09, 0.07, 'N', 'O', '1998-05-23', '1998-04-03', '1998-06-02', 'COLLECT COD',\n        'SHIP', 'y. pinto beans haggle after the'),\n       (71, 3444, 204, 3, 45, 60634.80, 0.00, 0.07, 'N', 'O', '1998-02-23', '1998-03-20', '1998-03-24',\n        'DELIVER IN PERSON', 'SHIP', ' ironic packages believe blithely a'),\n       (71, 9665, 925, 4, 33, 51963.78, 0.00, 0.01, 'N', 'O', '1998-04-12', '1998-03-20', '1998-04-15', 'NONE', 'FOB',\n        ' serve quickly fluffily bold deposi'),\n       (71, 10326, 587, 5, 39, 48216.48, 0.08, 0.06, 'N', 'O', '1998-01-29', '1998-04-07', '1998-02-18',\n        'DELIVER IN PERSON', 'RAIL', 'l accounts sleep across the pack'),\n       (71, 19564, 103, 6, 34, 50441.04, 0.04, 0.01, 'N', 'O', '1998-03-05', '1998-04-22', '1998-03-30',\n        'DELIVER IN PERSON', 'TRUCK', 's cajole. '),\n       (96, 12308, 95, 1, 23, 28066.90, 0.10, 0.06, 'A', 'F', '1994-07-19', '1994-06-29', '1994-07-25',\n        'DELIVER IN PERSON', 'TRUCK', 'ep-- carefully reg'),\n       (96, 13539, 540, 2, 30, 43575.90, 0.01, 0.06, 'R', 'F', '1994-06-03', '1994-05-29', '1994-06-22',\n        'DELIVER IN PERSON', 'TRUCK', 'e quickly even ideas. furiou'),\n       (97, 11948, 210, 1, 13, 24179.22, 0.00, 0.02, 'R', 'F', '1993-04-01', '1993-04-04', '1993-04-08', 'NONE',\n        'TRUCK', 'ayers cajole against the furiously'),\n       (97, 4957, 212, 2, 37, 68892.15, 0.02, 0.06, 'A', 'F', '1993-04-13', '1993-03-30', '1993-04-14',\n        'DELIVER IN PERSON', 'SHIP', 'ic requests boost carefully quic'),\n       (97, 7770, 542, 3, 19, 31877.63, 0.06, 0.08, 'R', 'F', '1993-05-14', '1993-03-05', '1993-05-25',\n        'TAKE BACK RETURN', 'RAIL', 'gifts. furiously ironic packages cajole. '),\n       (98, 4022, 23, 1, 28, 25928.56, 0.06, 0.07, 'A', 'F', '1994-12-24', '1994-10-25', '1995-01-16', 'COLLECT COD',\n        'REG AIR', ' pending, regular accounts s'),\n       (98, 10975, 756, 2, 1, 1885.97, 0.00, 0.00, 'A', 'F', '1994-12-01', '1994-12-12', '1994-12-15',\n        'DELIVER IN PERSON', 'TRUCK', '. unusual instructions against'),\n       (98, 4471, 472, 3, 14, 19256.58, 0.05, 0.02, 'A', 'F', '1994-12-30', '1994-11-22', '1995-01-27', 'COLLECT COD',\n        'AIR', ' cajole furiously. blithely ironic ideas '),\n       (98, 16718, 719, 4, 10, 16347.10, 0.03, 0.03, 'A', 'F', '1994-10-23', '1994-11-08', '1994-11-09', 'COLLECT COD',\n        'RAIL', ' carefully. quickly ironic ideas'),\n       (99, 8712, 487, 1, 10, 16207.10, 0.02, 0.01, 'A', 'F', '1994-05-18', '1994-06-03', '1994-05-23', 'COLLECT COD',\n        'RAIL', 'kages. requ'),\n       (99, 12377, 378, 2, 5, 6446.85, 0.02, 0.07, 'R', 'F', '1994-05-06', '1994-05-28', '1994-05-20',\n        'TAKE BACK RETURN', 'RAIL', 'ests cajole fluffily waters. blithe'),\n       (99, 13409, 199, 3, 42, 55540.80, 0.02, 0.02, 'A', 'F', '1994-04-19', '1994-05-18', '1994-04-20', 'NONE', 'RAIL',\n        'kages are fluffily furiously ir'),\n       (99, 10834, 95, 4, 36, 62813.88, 0.09, 0.02, 'A', 'F', '1994-07-04', '1994-04-17', '1994-07-30',\n        'DELIVER IN PERSON', 'AIR', 'slyly. slyly e'),\n       (100, 6203, 204, 1, 28, 31057.60, 0.04, 0.05, 'N', 'O', '1998-05-08', '1998-05-13', '1998-06-07', 'COLLECT COD',\n        'TRUCK', 'sts haggle. slowl'),\n       (100, 11598, 860, 2, 22, 33210.98, 0.00, 0.07, 'N', 'O', '1998-06-24', '1998-04-12', '1998-06-29',\n        'DELIVER IN PERSON', 'SHIP', 'nto beans alongside of the fi'),\n       (100, 4615, 870, 3, 46, 69902.06, 0.03, 0.04, 'N', 'O', '1998-05-02', '1998-04-10', '1998-05-22',\n        'TAKE BACK RETURN', 'SHIP', 'ular accounts. even'),\n       (100, 3803, 310, 4, 14, 23895.20, 0.06, 0.03, 'N', 'O', '1998-05-22', '1998-05-01', '1998-06-03', 'COLLECT COD',\n        'MAIL', 'y. furiously ironic ideas gr'),\n       (100, 5344, 110, 5, 37, 46225.58, 0.05, 0.00, 'N', 'O', '1998-03-06', '1998-04-16', '1998-03-31',\n        'TAKE BACK RETURN', 'TRUCK', 'nd the quickly s'),\n       (101, 11829, 613, 1, 49, 85300.18, 0.10, 0.00, 'N', 'O', '1996-06-21', '1996-05-27', '1996-06-29',\n        'DELIVER IN PERSON', 'REG AIR', 'ts-- final packages sleep furiousl'),\n       (101, 16334, 133, 2, 36, 45011.88, 0.00, 0.01, 'N', 'O', '1996-05-19', '1996-05-01', '1996-06-04',\n        'DELIVER IN PERSON', 'AIR', 'tes. blithely pending dolphins x-ray f'),\n       (101, 13842, 632, 3, 12, 21070.08, 0.06, 0.02, 'N', 'O', '1996-03-29', '1996-04-20', '1996-04-12', 'COLLECT COD',\n        'MAIL', '. quickly regular'),\n       (102, 8892, 409, 1, 37, 66632.93, 0.06, 0.00, 'N', 'O', '1997-07-24', '1997-08-02', '1997-08-07',\n        'TAKE BACK RETURN', 'SHIP', 'ully across the ideas. final deposit'),\n       (102, 16924, 723, 2, 34, 62591.28, 0.03, 0.08, 'N', 'O', '1997-08-09', '1997-07-28', '1997-08-26',\n        'TAKE BACK RETURN', 'SHIP', 'eposits cajole across'),\n       (102, 18233, 502, 3, 25, 28780.75, 0.01, 0.01, 'N', 'O', '1997-07-31', '1997-07-24', '1997-08-17', 'NONE',\n        'RAIL', 'bits. ironic accoun'),\n       (102, 6116, 885, 4, 15, 15331.65, 0.07, 0.07, 'N', 'O', '1997-06-02', '1997-07-13', '1997-06-04',\n        'DELIVER IN PERSON', 'SHIP', 'final packages. carefully even excu'),\n       (103, 19466, 274, 1, 6, 8312.76, 0.03, 0.05, 'N', 'O', '1996-10-11', '1996-07-25', '1996-10-28', 'NONE', 'FOB',\n        'cajole. carefully ex'),\n       (103, 1043, 295, 2, 37, 34929.48, 0.02, 0.07, 'N', 'O', '1996-09-17', '1996-07-27', '1996-09-20',\n        'TAKE BACK RETURN', 'MAIL', 'ies. quickly ironic requests use blithely'),\n       (103, 2844, 845, 3, 23, 40177.32, 0.01, 0.04, 'N', 'O', '1996-09-11', '1996-09-18', '1996-09-26', 'NONE', 'FOB',\n        'ironic accou'),\n       (103, 2903, 408, 4, 32, 57788.80, 0.01, 0.07, 'N', 'O', '1996-07-30', '1996-08-06', '1996-08-04', 'NONE', 'RAIL',\n        'kages doze. special, regular deposit'),\n       (128, 10683, 944, 1, 38, 60559.84, 0.06, 0.01, 'A', 'F', '1992-09-01', '1992-08-27', '1992-10-01',\n        'TAKE BACK RETURN', 'FOB', ' cajole careful'),\n       (129, 287, 538, 1, 46, 54614.88, 0.08, 0.02, 'R', 'F', '1993-02-15', '1993-01-24', '1993-03-05', 'COLLECT COD',\n        'TRUCK', 'uietly bold theodolites. fluffil'),\n       (129, 18517, 518, 2, 36, 51678.36, 0.01, 0.02, 'A', 'F', '1992-11-25', '1992-12-25', '1992-12-09',\n        'TAKE BACK RETURN', 'REG AIR', 'packages are care'),\n       (129, 3945, 199, 3, 33, 61015.02, 0.04, 0.06, 'A', 'F', '1993-01-08', '1993-02-14', '1993-01-29', 'COLLECT COD',\n        'SHIP', 'sts nag bravely. fluffily'),\n       (129, 13514, 41, 4, 34, 48535.34, 0.00, 0.01, 'R', 'F', '1993-01-29', '1993-02-14', '1993-02-10', 'COLLECT COD',\n        'MAIL', 'quests. express ideas'),\n       (129, 3138, 898, 5, 24, 24987.12, 0.06, 0.00, 'A', 'F', '1992-12-07', '1993-01-02', '1992-12-11',\n        'TAKE BACK RETURN', 'FOB', 'uests. foxes cajole slyly after the ca'),\n       (129, 7705, 477, 6, 22, 35479.40, 0.06, 0.01, 'R', 'F', '1993-02-15', '1993-01-31', '1993-02-24', 'COLLECT COD',\n        'SHIP', 'e. fluffily regular '),\n       (129, 16857, 390, 7, 1, 1773.85, 0.05, 0.04, 'R', 'F', '1993-01-26', '1993-01-08', '1993-02-24',\n        'DELIVER IN PERSON', 'FOB', 'e carefully blithely bold dolp'),\n       (130, 12882, 883, 1, 14, 25128.32, 0.08, 0.05, 'A', 'F', '1992-08-15', '1992-07-25', '1992-09-13', 'COLLECT COD',\n        'RAIL', ' requests. final instruction'),\n       (130, 174, 425, 2, 48, 51560.16, 0.03, 0.02, 'R', 'F', '1992-07-01', '1992-07-12', '1992-07-24', 'NONE', 'AIR',\n        'lithely alongside of the regu'),\n       (130, 1186, 187, 3, 18, 19569.24, 0.04, 0.08, 'A', 'F', '1992-07-04', '1992-06-14', '1992-07-29',\n        'DELIVER IN PERSON', 'MAIL', ' slyly ironic decoys abou'),\n       (130, 11564, 348, 4, 13, 19182.28, 0.09, 0.02, 'R', 'F', '1992-06-26', '1992-07-29', '1992-07-05', 'NONE', 'FOB',\n        ' pending dolphins sleep furious'),\n       (130, 6913, 426, 5, 31, 56417.21, 0.06, 0.05, 'R', 'F', '1992-09-01', '1992-07-18', '1992-09-02',\n        'TAKE BACK RETURN', 'RAIL', 'thily about the ruth'),\n       (131, 16751, 18, 1, 45, 75048.75, 0.10, 0.02, 'R', 'F', '1994-09-14', '1994-09-02', '1994-10-04', 'NONE', 'FOB',\n        'ironic, bold accounts. careful'),\n       (131, 4426, 935, 2, 50, 66521.00, 0.02, 0.04, 'A', 'F', '1994-09-17', '1994-08-10', '1994-09-21', 'NONE', 'SHIP',\n        'ending requests. final, ironic pearls slee'),\n       (131, 18903, 172, 3, 4, 7287.60, 0.04, 0.03, 'A', 'F', '1994-09-20', '1994-08-30', '1994-09-23', 'COLLECT COD',\n        'REG AIR', ' are carefully slyly i'),\n       (132, 14045, 310, 1, 18, 17262.72, 0.00, 0.08, 'R', 'F', '1993-07-10', '1993-08-05', '1993-07-13', 'NONE',\n        'TRUCK', 'ges. platelets wake furio'),\n       (132, 11906, 907, 2, 43, 78169.70, 0.01, 0.08, 'R', 'F', '1993-09-01', '1993-08-16', '1993-09-22', 'NONE',\n        'TRUCK', 'y pending theodolites'),\n       (132, 11442, 443, 3, 32, 43310.08, 0.04, 0.04, 'A', 'F', '1993-07-12', '1993-08-05', '1993-08-05', 'COLLECT COD',\n        'TRUCK', 'd instructions hagg'),\n       (132, 2809, 566, 4, 23, 39371.40, 0.10, 0.00, 'A', 'F', '1993-06-16', '1993-08-27', '1993-06-23',\n        'DELIVER IN PERSON', 'AIR', 'refully blithely bold acco'),\n       (133, 10344, 605, 1, 27, 33867.18, 0.00, 0.02, 'N', 'O', '1997-12-21', '1998-02-23', '1997-12-27',\n        'TAKE BACK RETURN', 'MAIL', 'yly even gifts after the sl'),\n       (133, 17628, 430, 2, 12, 18547.44, 0.02, 0.06, 'N', 'O', '1997-12-02', '1998-01-15', '1997-12-29',\n        'DELIVER IN PERSON', 'REG AIR', 'ts cajole fluffily quickly i'),\n       (133, 11735, 519, 3, 29, 47755.17, 0.09, 0.08, 'N', 'O', '1998-02-28', '1998-01-30', '1998-03-09',\n        'DELIVER IN PERSON', 'RAIL', ' the carefully regular theodoli'),\n       (133, 8986, 761, 4, 11, 20844.78, 0.06, 0.01, 'N', 'O', '1998-03-21', '1998-01-15', '1998-04-04',\n        'DELIVER IN PERSON', 'REG AIR', 'e quickly across the dolphins'),\n       (134, 65, 66, 1, 21, 20266.26, 0.00, 0.03, 'A', 'F', '1992-07-17', '1992-07-08', '1992-07-26', 'COLLECT COD',\n        'SHIP', 's. quickly regular'),\n       (134, 16465, 998, 2, 35, 48351.10, 0.06, 0.07, 'A', 'F', '1992-08-23', '1992-06-01', '1992-08-24', 'NONE',\n        'MAIL', 'ajole furiously. instructio'),\n       (134, 18826, 363, 3, 26, 45365.32, 0.09, 0.06, 'A', 'F', '1992-06-20', '1992-07-12', '1992-07-16', 'NONE',\n        'RAIL', ' among the pending depos'),\n       (134, 14401, 402, 4, 47, 61823.80, 0.05, 0.00, 'A', 'F', '1992-08-16', '1992-07-06', '1992-08-28', 'NONE',\n        'REG AIR', 's! carefully unusual requests boost careful'),\n       (134, 3518, 519, 5, 12, 17058.12, 0.05, 0.02, 'A', 'F', '1992-07-03', '1992-06-01', '1992-07-11', 'COLLECT COD',\n        'TRUCK', 'nts are quic'),\n       (134, 13311, 575, 6, 12, 14691.72, 0.00, 0.00, 'A', 'F', '1992-08-08', '1992-07-07', '1992-08-20',\n        'TAKE BACK RETURN', 'FOB', 'lyly regular pac'),\n       (135, 10821, 822, 1, 47, 81395.54, 0.06, 0.08, 'N', 'O', '1996-02-18', '1996-01-01', '1996-02-25', 'COLLECT COD',\n        'RAIL', 'ctions wake slyly abo'),\n       (135, 19835, 643, 2, 21, 36851.43, 0.00, 0.07, 'N', 'O', '1996-02-11', '1996-01-12', '1996-02-13',\n        'DELIVER IN PERSON', 'SHIP', ' deposits believe. furiously regular p'),\n       (135, 15751, 547, 3, 33, 55002.75, 0.02, 0.00, 'N', 'O', '1996-01-03', '1995-11-21', '1996-02-01',\n        'TAKE BACK RETURN', 'MAIL', 'ptotes boost slowly care'),\n       (135, 6701, 958, 4, 34, 54661.80, 0.02, 0.03, 'N', 'O', '1996-01-12', '1996-01-19', '1996-02-05', 'NONE',\n        'TRUCK', 'counts doze against the blithely ironi'),\n       (135, 13625, 152, 5, 20, 30772.40, 0.01, 0.04, 'N', 'O', '1996-01-25', '1995-11-20', '1996-02-09', 'NONE',\n        'MAIL', 'theodolites. quickly p'),\n       (135, 11500, 284, 6, 13, 18349.50, 0.04, 0.02, 'N', 'O', '1995-11-12', '1995-12-22', '1995-11-17', 'NONE', 'FOB',\n        'nal ideas. final instr'),\n       (160, 1479, 982, 1, 36, 49696.92, 0.07, 0.01, 'N', 'O', '1997-03-11', '1997-03-11', '1997-03-20', 'COLLECT COD',\n        'MAIL', 'old, ironic deposits are quickly abov'),\n       (160, 8639, 898, 2, 22, 34047.86, 0.00, 0.04, 'N', 'O', '1997-02-18', '1997-03-05', '1997-03-05', 'COLLECT COD',\n        'RAIL', 'ncies about the request'),\n       (160, 2008, 513, 3, 34, 30940.00, 0.01, 0.05, 'N', 'O', '1997-01-31', '1997-03-13', '1997-02-14', 'NONE', 'FOB',\n        'st sleep even gifts. dependencies along'),\n       (161, 10281, 62, 1, 19, 22634.32, 0.01, 0.01, 'A', 'F', '1994-12-13', '1994-11-19', '1994-12-26',\n        'DELIVER IN PERSON', 'TRUCK', ', regular sheaves sleep along'),\n       (162, 18929, 466, 1, 2, 3695.84, 0.02, 0.01, 'N', 'O', '1995-09-02', '1995-06-17', '1995-09-08', 'COLLECT COD',\n        'FOB', 'es! final somas integrate'),\n       (163, 16755, 554, 1, 43, 71885.25, 0.01, 0.00, 'N', 'O', '1997-09-19', '1997-11-19', '1997-10-03', 'COLLECT COD',\n        'REG AIR', 'al, bold dependencies wake. iron'),\n       (163, 12071, 72, 2, 13, 12779.91, 0.01, 0.04, 'N', 'O', '1997-11-11', '1997-10-18', '1997-12-07',\n        'DELIVER IN PERSON', 'TRUCK', 'inal requests. even pinto beans hag'),\n       (163, 3682, 936, 3, 27, 42813.36, 0.04, 0.08, 'N', 'O', '1997-12-26', '1997-11-28', '1998-01-05', 'COLLECT COD',\n        'REG AIR', 'ously express dependen'),\n       (163, 19265, 535, 4, 5, 5921.30, 0.02, 0.00, 'N', 'O', '1997-11-17', '1997-10-09', '1997-12-05',\n        'DELIVER IN PERSON', 'TRUCK', ' must belie'),\n       (163, 12609, 872, 5, 12, 18259.20, 0.10, 0.00, 'N', 'O', '1997-12-18', '1997-10-26', '1997-12-22', 'COLLECT COD',\n        'TRUCK', 'ly blithe accounts cajole '),\n       (163, 19083, 622, 6, 20, 20041.60, 0.00, 0.07, 'N', 'O', '1997-09-27', '1997-11-15', '1997-10-07',\n        'TAKE BACK RETURN', 'FOB', 'tructions integrate b'),\n       (164, 9131, 391, 1, 26, 27043.38, 0.09, 0.04, 'A', 'F', '1993-01-04', '1992-11-21', '1993-01-07', 'NONE', 'RAIL',\n        's. blithely special courts are blithel'),\n       (164, 1849, 352, 2, 24, 42020.16, 0.05, 0.05, 'R', 'F', '1992-12-22', '1992-11-27', '1993-01-06', 'NONE', 'AIR',\n        'side of the slyly unusual theodolites. f'),\n       (164, 12551, 338, 3, 38, 55614.90, 0.03, 0.06, 'R', 'F', '1992-12-04', '1992-11-23', '1993-01-02',\n        'TAKE BACK RETURN', 'AIR', 'counts cajole fluffily regular packages. b'),\n       (164, 1753, 5, 4, 32, 52952.00, 0.05, 0.01, 'R', 'F', '1992-12-21', '1992-12-23', '1992-12-28', 'COLLECT COD',\n        'RAIL', 'ts wake again'),\n       (164, 14751, 280, 5, 43, 71627.25, 0.06, 0.01, 'R', 'F', '1992-11-26', '1993-01-03', '1992-12-08', 'COLLECT COD',\n        'RAIL', 'y carefully regular dep'),\n       (164, 10890, 891, 6, 27, 48624.03, 0.10, 0.04, 'R', 'F', '1992-12-23', '1993-01-16', '1993-01-10',\n        'DELIVER IN PERSON', 'AIR', 'ayers wake carefully a'),\n       (164, 304, 555, 7, 23, 27698.90, 0.09, 0.04, 'A', 'F', '1992-11-03', '1992-12-02', '1992-11-12', 'NONE',\n        'REG AIR', 'ress packages haggle ideas. blithely spec'),\n       (165, 3318, 825, 1, 3, 3663.93, 0.01, 0.08, 'R', 'F', '1993-03-29', '1993-03-06', '1993-04-12',\n        'DELIVER IN PERSON', 'REG AIR', 'riously requests. depos'),\n       (165, 16163, 962, 2, 43, 46403.88, 0.08, 0.05, 'R', 'F', '1993-02-27', '1993-04-19', '1993-03-03',\n        'DELIVER IN PERSON', 'TRUCK', 'jole slyly according '),\n       (165, 5852, 618, 3, 15, 26367.75, 0.00, 0.05, 'R', 'F', '1993-04-10', '1993-03-29', '1993-05-01', 'COLLECT COD',\n        'SHIP', ' bold packages mainta'),\n       (165, 13919, 446, 4, 49, 89812.59, 0.07, 0.06, 'A', 'F', '1993-02-20', '1993-04-02', '1993-03-10', 'COLLECT COD',\n        'REG AIR', 'uses sleep slyly ruthlessly regular a'),\n       (165, 15509, 775, 5, 27, 38461.50, 0.01, 0.04, 'R', 'F', '1993-04-27', '1993-03-04', '1993-05-13', 'NONE',\n        'MAIL', 'around the ironic, even orb'),\n       (166, 6489, 2, 1, 37, 51632.76, 0.09, 0.03, 'N', 'O', '1995-11-16', '1995-10-17', '1995-12-13', 'NONE', 'MAIL',\n        'lar frays wake blithely a'),\n       (166, 16637, 638, 2, 13, 20197.19, 0.09, 0.05, 'N', 'O', '1995-11-09', '1995-11-18', '1995-11-14', 'COLLECT COD',\n        'SHIP', 'fully above the blithely fina'),\n       (166, 9966, 226, 3, 41, 76914.36, 0.07, 0.03, 'N', 'O', '1995-11-13', '1995-11-07', '1995-12-08', 'COLLECT COD',\n        'FOB', 'hily along the blithely pending fo'),\n       (166, 4503, 758, 4, 8, 11260.00, 0.05, 0.02, 'N', 'O', '1995-12-30', '1995-11-29', '1996-01-29',\n        'DELIVER IN PERSON', 'RAIL', 'e carefully bold '),\n       (167, 10118, 119, 1, 28, 28787.08, 0.06, 0.01, 'R', 'F', '1993-02-19', '1993-02-16', '1993-03-03',\n        'DELIVER IN PERSON', 'TRUCK', 'sly during the u'),\n       (167, 17156, 424, 2, 27, 28975.05, 0.09, 0.00, 'R', 'F', '1993-05-01', '1993-03-31', '1993-05-31',\n        'TAKE BACK RETURN', 'FOB', 'eans affix furiously-- packages'),\n       (192, 9702, 221, 1, 23, 37069.10, 0.00, 0.00, 'N', 'O', '1998-02-05', '1998-02-06', '1998-03-07',\n        'TAKE BACK RETURN', 'AIR', 'ly pending theodolites haggle quickly fluf'),\n       (192, 16137, 936, 2, 20, 21062.60, 0.07, 0.01, 'N', 'O', '1998-03-13', '1998-02-02', '1998-03-31',\n        'TAKE BACK RETURN', 'REG AIR', 'tes. carefu'),\n       (192, 11026, 549, 3, 15, 14055.30, 0.09, 0.01, 'N', 'O', '1998-01-30', '1998-02-10', '1998-02-23',\n        'TAKE BACK RETURN', 'TRUCK', 'he ironic requests haggle about'),\n       (192, 19640, 448, 4, 2, 3119.28, 0.06, 0.02, 'N', 'O', '1998-03-06', '1998-02-03', '1998-03-24', 'COLLECT COD',\n        'SHIP', 's. dependencies nag furiously alongside'),\n       (192, 8292, 809, 5, 25, 30007.25, 0.02, 0.03, 'N', 'O', '1998-02-15', '1998-01-11', '1998-03-17', 'COLLECT COD',\n        'TRUCK', '. carefully regular'),\n       (192, 14101, 366, 6, 45, 45679.50, 0.00, 0.05, 'N', 'O', '1998-03-11', '1998-01-09', '1998-04-03', 'NONE',\n        'MAIL', 'equests. ideas sleep idea'),\n       (193, 9264, 524, 1, 9, 10559.34, 0.06, 0.06, 'A', 'F', '1993-09-17', '1993-10-08', '1993-09-30', 'COLLECT COD',\n        'TRUCK', 'against the fluffily regular d'),\n       (193, 15396, 192, 2, 15, 19670.85, 0.02, 0.07, 'R', 'F', '1993-11-22', '1993-10-09', '1993-12-05',\n        'TAKE BACK RETURN', 'SHIP', 'ffily. regular packages d'),\n       (193, 9388, 648, 3, 23, 29839.74, 0.06, 0.05, 'A', 'F', '1993-08-21', '1993-10-11', '1993-09-02',\n        'DELIVER IN PERSON', 'TRUCK', 'ly even accounts wake blithely bold'),\n       (194, 260, 511, 1, 17, 19724.42, 0.05, 0.04, 'R', 'F', '1992-05-24', '1992-05-22', '1992-05-30', 'COLLECT COD',\n        'AIR', ' regular deposi'),\n       (194, 18353, 622, 2, 1, 1271.35, 0.04, 0.06, 'R', 'F', '1992-04-30', '1992-05-18', '1992-05-23', 'NONE',\n        'REG AIR', ' regular theodolites. regular, iron'),\n       (194, 6600, 369, 3, 13, 19585.80, 0.08, 0.08, 'A', 'F', '1992-05-07', '1992-06-18', '1992-05-10', 'NONE', 'AIR',\n        'about the blit'),\n       (194, 14515, 516, 4, 36, 51462.36, 0.00, 0.05, 'R', 'F', '1992-05-21', '1992-05-18', '1992-05-27',\n        'TAKE BACK RETURN', 'RAIL', 'pecial packages wake after the slyly r'),\n       (194, 5618, 129, 5, 8, 12188.88, 0.04, 0.00, 'R', 'F', '1992-07-06', '1992-06-25', '1992-07-11', 'COLLECT COD',\n        'FOB', 'uriously unusual excuses'),\n       (194, 14899, 164, 6, 16, 29022.24, 0.06, 0.03, 'A', 'F', '1992-05-14', '1992-06-14', '1992-05-21',\n        'TAKE BACK RETURN', 'TRUCK', 'y regular requests. furious')"
  },
  {
    "path": "core/src/main/resources/tpch/q1.sql",
    "content": "-- database: presto; groups: tpch; tables: lineitem\nSELECT l_returnflag,\n       l_linestatus,\n       sum(l_quantity)                                       AS sum_qty,\n       sum(l_extendedprice)                                  AS sum_base_price,\n       sum(l_extendedprice * (1 - l_discount))               AS sum_disc_price,\n       sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,\n       avg(l_quantity)                                       AS avg_qty,\n       avg(l_extendedprice)                                  AS avg_price,\n       avg(l_discount)                                       AS avg_disc,\n       count(*)                                              AS count_order\nFROM lineitem\nWHERE l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY\nGROUP BY l_returnflag,\n         l_linestatus\nORDER BY l_returnflag,\n         l_linestatus\n"
  },
  {
    "path": "core/src/main/resources/tpch/q10.sql",
    "content": "-- database: presto; groups: tpch; tables: customer,orders,lineitem,nation\nSELECT c_custkey,\n       c_name,\n       sum(l_extendedprice * (1 - l_discount)) AS revenue,\n       c_acctbal,\n       n_name,\n       c_address,\n       c_phone,\n       c_comment\nFROM customer,\n     orders,\n     lineitem,\n     nation\nWHERE c_custkey = o_custkey\n  AND l_orderkey = o_orderkey\n  AND o_orderdate >= DATE '1993-10-01'\n  AND o_orderdate < DATE '1993-10-01' + INTERVAL '3' MONTH\n  AND l_returnflag = 'R'\n  AND c_nationkey = n_nationkey\nGROUP BY c_custkey,\n         c_name,\n         c_acctbal,\n         c_phone,\n         n_name,\n         c_address,\n         c_comment\nORDER BY revenue DESC LIMIT 20\n"
  },
  {
    "path": "core/src/main/resources/tpch/q11.sql",
    "content": "SELECT ps_partkey,\n       sum(ps_supplycost * ps_availqty) AS value\nFROM\n    partsupp,\n    supplier,\n    nation\nWHERE\n    ps_suppkey = s_suppkey\n  AND s_nationkey = n_nationkey\n  AND n_name = 'GERMANY'\nGROUP BY\n    ps_partkey\nHAVING\n    sum (ps_supplycost * ps_availqty)\n     > (\n    SELECT sum (ps_supplycost * ps_availqty) * 0.0001\n    FROM\n    partsupp\n     , supplier\n     , nation\n    WHERE\n    ps_suppkey = s_suppkey\n   AND s_nationkey = n_nationkey\n   AND n_name = 'GERMANY'\n    )\nORDER BY\n    value DESC\n"
  },
  {
    "path": "core/src/main/resources/tpch/q12.sql",
    "content": "-- database: presto; groups: tpch; tables: orders,lineitem\nSELECT l_shipmode,\n       sum(CASE\n               WHEN o_orderpriority = '1-URGENT'\n                   OR o_orderpriority = '2-HIGH'\n                   THEN 1\n               ELSE 0\n           END) AS high_line_count,\n       sum(CASE\n               WHEN o_orderpriority <> '1-URGENT'\n                   AND o_orderpriority <> '2-HIGH'\n                   THEN 1\n               ELSE 0\n           END) AS low_line_count\nFROM orders,\n     lineitem\nWHERE o_orderkey = l_orderkey\n  AND l_shipmode IN ('MAIL', 'SHIP')\n  AND l_commitdate < l_receiptdate\n  AND l_shipdate < l_commitdate\n  AND l_receiptdate >= DATE '1994-01-01'\n  AND l_receiptdate < DATE '1994-01-01' + INTERVAL '1' YEAR\nGROUP BY l_shipmode\nORDER BY l_shipmode\n"
  },
  {
    "path": "core/src/main/resources/tpch/q13.sql",
    "content": "-- database: presto; groups: tpch; tables: customer\nSELECT c_count,\n       count(*) AS custdist\nFROM (SELECT c_custkey,\n             count(o_orderkey)\n      FROM customer\n               LEFT OUTER JOIN orders ON\n                  c_custkey = o_custkey\n              AND o_comment NOT LIKE '%special%requests%'\n      GROUP BY c_custkey) AS c_orders (c_custkey, c_count)\nGROUP BY c_count\nORDER BY custdist DESC,\n         c_count DESC\n"
  },
  {
    "path": "core/src/main/resources/tpch/q14.sql",
    "content": "-- database: presto; groups: tpch; tables: lineitem,part\nSELECT 100.00 * sum(CASE\n                        WHEN p_type LIKE 'PROMO%'\n                            THEN l_extendedprice * (1 - l_discount)\n                        ELSE 0\n    END) / sum(l_extendedprice * (1 - l_discount)) AS promo_revenue\nFROM lineitem,\n     part\nWHERE l_partkey = p_partkey\n  AND l_shipdate >= DATE '1995-09-01'\n  AND l_shipdate < DATE '1995-09-01' + INTERVAL '1' MONTH\n"
  },
  {
    "path": "core/src/main/resources/tpch/q15.sql",
    "content": "WITH revenue0 AS\n         (SELECT l_suppkey AS supplier_no, sum(l_extendedprice * (1 - l_discount)) AS total_revenue\n          FROM lineitem\n          WHERE date_parse(l_shipdate, '%Y-%m-%d %H:%i:%s') >= DATE '1993-01-01'\n            AND date_parse(l_shipdate, '%Y-%m-%d %H:%i:%s') < DATE '1993-01-01' + interval '3' month\n          GROUP BY l_suppkey)\nSELECT s_suppkey, s_name, s_address, s_phone, total_revenue\nFROM supplier_rcfile_string,\n     revenue0\nWHERE s_suppkey = supplier_no\n  AND total_revenue IN (SELECT max(total_revenue)\n                        FROM revenue0)\nORDER BY s_suppkey"
  },
  {
    "path": "core/src/main/resources/tpch/q16.sql",
    "content": "-- database: presto; groups: tpch; tables: partsupp,part,supplier\nSELECT p_brand,\n       p_type,\n       p_size,\n       count(DISTINCT ps_suppkey) AS supplier_cnt\nFROM partsupp,\n     part\nWHERE p_partkey = ps_partkey\n  AND p_brand <> 'Brand#45'\n  AND p_type NOT LIKE 'MEDIUM POLISHED%'\n  AND p_size IN (49, 14, 23, 45, 19, 3, 36, 9)\n  AND ps_suppkey NOT IN (SELECT s_suppkey\n                         FROM supplier\n                         WHERE s_comment LIKE '%Customer%Complaints%')\nGROUP BY p_brand,\n         p_type,\n         p_size\nORDER BY supplier_cnt DESC,\n         p_brand,\n         p_type,\n         p_size\n"
  },
  {
    "path": "core/src/main/resources/tpch/q17.sql",
    "content": "-- database: presto; groups: tpch; tables: lineitem,part\nSELECT sum(l_extendedprice) / 7.0 AS avg_yearly\nFROM lineitem,\n     part\nWHERE p_partkey = l_partkey\n  AND p_brand = 'Brand#23'\n  AND p_container = 'MED BOX'\n  AND l_quantity < (SELECT 0.2 * avg(l_quantity)\n                    FROM lineitem\n                    WHERE l_partkey = p_partkey)\n"
  },
  {
    "path": "core/src/main/resources/tpch/q18.sql",
    "content": "-- database: presto; groups: tpch, big_query; tables: customer,orders,lineitem\nSELECT c_name,\n       c_custkey,\n       o_orderkey,\n       o_orderdate,\n       o_totalprice,\n       sum(l_quantity)\nFROM customer,\n     orders,\n     lineitem\nWHERE o_orderkey IN (SELECT l_orderkey\n                     FROM lineitem\n                     GROUP BY l_orderkey\n                     HAVING sum(l_quantity) > 300)\n  AND c_custkey = o_custkey\n  AND o_orderkey = l_orderkey\nGROUP BY c_name,\n         c_custkey,\n         o_orderkey,\n         o_orderdate,\n         o_totalprice\nORDER BY o_totalprice DESC,\n         o_orderdate LIMIT 100\n"
  },
  {
    "path": "core/src/main/resources/tpch/q19.sql",
    "content": "-- database: presto;  groups: tpch; tables: lineitem,part\nSELECT sum(l_extendedprice * (1 - l_discount)) AS revenue\nFROM lineitem,\n     part\nWHERE (\n            p_partkey = l_partkey\n        AND p_brand = 'Brand#12'\n        AND p_container IN ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG')\n        AND l_quantity >= 1 AND l_quantity <= 1 + 10\n        AND p_size BETWEEN 1 AND 5\n        AND l_shipmode IN ('AIR', 'AIR REG')\n        AND l_shipinstruct = 'DELIVER IN PERSON'\n    )\n   OR (\n            p_partkey = l_partkey\n        AND p_brand = 'Brand#23'\n        AND p_container IN ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK')\n        AND l_quantity >= 10 AND l_quantity <= 10 + 10\n        AND p_size BETWEEN 1 AND 10\n        AND l_shipmode IN ('AIR', 'AIR REG')\n        AND l_shipinstruct = 'DELIVER IN PERSON'\n    )\n   OR (\n            p_partkey = l_partkey\n        AND p_brand = 'Brand#34'\n        AND p_container IN ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG')\n        AND l_quantity >= 20 AND l_quantity <= 20 + 10\n        AND p_size BETWEEN 1 AND 15\n        AND l_shipmode IN ('AIR', 'AIR REG')\n        AND l_shipinstruct = 'DELIVER IN PERSON'\n    )\n"
  },
  {
    "path": "core/src/main/resources/tpch/q2.sql",
    "content": "-- database: presto; groups: tpch; tables: part,supplier,partsupp,nation,region\nSELECT s_acctbal,\n       s_name,\n       n_name,\n       p_partkey,\n       p_mfgr,\n       s_address,\n       s_phone,\n       s_comment\nFROM part,\n     supplier,\n     partsupp,\n     nation,\n     region\nWHERE p_partkey = ps_partkey\n  AND s_suppkey = ps_suppkey\n  AND p_size = 15\n  AND p_type LIKE '%BRASS'\n  AND s_nationkey = n_nationkey\n  AND n_regionkey = r_regionkey\n  AND r_name = 'EUROPE'\n  AND ps_supplycost = (SELECT min(ps_supplycost)\n                       FROM partsupp,\n                            supplier,\n                            nation,\n                            region\n                       WHERE p_partkey = ps_partkey\n                         AND s_suppkey = ps_suppkey\n                         AND s_nationkey = n_nationkey\n                         AND n_regionkey = r_regionkey\n                         AND r_name = 'EUROPE')\nORDER BY s_acctbal DESC,\n         n_name,\n         s_name,\n         p_partkey LIMIT 100\n"
  },
  {
    "path": "core/src/main/resources/tpch/q20.sql",
    "content": "-- database: presto; groups: tpch; tables: supplier,nation,partsupp,lineitem,part\nSELECT s_name,\n       s_address\nFROM supplier,\n     nation\nWHERE s_suppkey IN (SELECT ps_suppkey\n                    FROM partsupp\n                    WHERE ps_partkey IN (SELECT p_partkey\n                                         FROM part\n                                         WHERE p_name LIKE 'forest%')\n                      AND ps_availqty > (SELECT 0.5 * sum(l_quantity)\n                                         FROM lineitem\n                                         WHERE l_partkey = ps_partkey\n                                           AND l_suppkey = ps_suppkey\n                                           AND l_shipdate >=\n    date ('1994-01-01')\n  AND l_shipdate\n    < date ('1994-01-01') + interval '1' YEAR\n    )\n    )\n  AND s_nationkey = n_nationkey\n  AND n_name = 'CANADA'\nORDER BY s_name\n"
  },
  {
    "path": "core/src/main/resources/tpch/q21.sql",
    "content": "-- database: presto; groups: tpch,big_query; tables: supplier,lineitem,orders,nation\nSELECT s_name,\n       count(*) AS numwait\nFROM supplier,\n     lineitem l1,\n     orders,\n     nation\nWHERE s_suppkey = l1.l_suppkey\n  AND o_orderkey = l1.l_orderkey\n  AND o_orderstatus = 'F'\n  AND l1.l_receiptdate > l1.l_commitdate\n  AND exists(\n        SELECT *\n        FROM lineitem l2\n        WHERE l2.l_orderkey = l1.l_orderkey\n          AND l2.l_suppkey <> l1.l_suppkey\n    )\n  AND NOT exists(\n        SELECT *\n        FROM lineitem l3\n        WHERE l3.l_orderkey = l1.l_orderkey\n          AND l3.l_suppkey <> l1.l_suppkey\n          AND l3.l_receiptdate > l3.l_commitdate\n    )\n  AND s_nationkey = n_nationkey\n  AND n_name = 'SAUDI ARABIA'\nGROUP BY s_name\nORDER BY numwait DESC,\n         s_name LIMIT 100\n"
  },
  {
    "path": "core/src/main/resources/tpch/q22.sql",
    "content": "-- database: presto; groups: tpch; tables: orders,customer\nSELECT cntrycode,\n       count(*)       AS numcust,\n       sum(c_acctbal) AS totacctbal\nFROM (SELECT substr(c_phone, 1, 2) AS cntrycode,\n             c_acctbal\n      FROM customer\n      WHERE substr(c_phone, 1, 2) IN\n            ('13', '31', '23', '29', '30', '18', '17')\n        AND c_acctbal > (SELECT avg(c_acctbal)\n                         FROM customer\n                         WHERE c_acctbal > 0.00\n                           AND substr(c_phone, 1, 2) IN\n                               ('13', '31', '23', '29', '30', '18', '17'))\n        AND NOT exists(\n              SELECT *\n              FROM orders\n              WHERE o_custkey = c_custkey\n          )) AS custsale\nGROUP BY cntrycode\nORDER BY cntrycode\n"
  },
  {
    "path": "core/src/main/resources/tpch/q3.sql",
    "content": "-- database: presto; groups: tpch; tables: customer,orders,lineitem\nSELECT l_orderkey,\n       sum(l_extendedprice * (1 - l_discount)) AS revenue,\n       o_orderdate,\n       o_shippriority\nFROM customer,\n     orders,\n     lineitem\nWHERE c_mktsegment = 'BUILDING'\n  AND c_custkey = o_custkey\n  AND l_orderkey = o_orderkey\n  AND o_orderdate < DATE '1995-03-15'\n  AND l_shipdate > DATE '1995-03-15'\nGROUP BY l_orderkey,\n         o_orderdate,\n         o_shippriority\nORDER BY revenue DESC,\n         o_orderdate LIMIT 10\n"
  },
  {
    "path": "core/src/main/resources/tpch/q4.sql",
    "content": "-- database: presto; groups: tpch; tables: orders,lineitem\nSELECT o_orderpriority,\n       count(*) AS order_count\nFROM orders\nWHERE o_orderdate >= DATE '1993-07-01'\n  AND o_orderdate < DATE '1993-07-01' + INTERVAL '3' MONTH\n  AND EXISTS(\n        SELECT *\n        FROM lineitem\n        WHERE l_orderkey = o_orderkey\n          AND l_commitdate < l_receiptdate\n    )\nGROUP BY o_orderpriority\nORDER BY o_orderpriority\n"
  },
  {
    "path": "core/src/main/resources/tpch/q5.sql",
    "content": "-- database: presto; groups: big_query, tpch; tables: customer,orders,lineitem,supplier,nation,region\nSELECT n_name,\n       sum(l_extendedprice * (1 - l_discount)) AS revenue\nFROM customer,\n     orders,\n     lineitem,\n     supplier,\n     nation,\n     region\nWHERE c_custkey = o_custkey\n  AND l_orderkey = o_orderkey\n  AND l_suppkey = s_suppkey\n  AND c_nationkey = s_nationkey\n  AND s_nationkey = n_nationkey\n  AND n_regionkey = r_regionkey\n  AND r_name = 'ASIA'\n  AND o_orderdate >= DATE '1994-01-01'\n  AND o_orderdate < DATE '1994-01-01' + INTERVAL '1' YEAR\nGROUP BY n_name\nORDER BY revenue DESC\n"
  },
  {
    "path": "core/src/main/resources/tpch/q6.sql",
    "content": "-- database: presto; groups: tpch; tables: lineitem\nSELECT sum(l_extendedprice * l_discount) AS revenue\nFROM lineitem\nWHERE l_shipdate >= DATE '1994-01-01'\n  AND l_shipdate < DATE '1994-01-01' + INTERVAL '1' YEAR\n  AND l_discount BETWEEN decimal '0.06' - decimal '0.01'\n  AND decimal '0.06' + decimal '0.01'\n  AND l_quantity\n    < 24\n"
  },
  {
    "path": "core/src/main/resources/tpch/q7.sql",
    "content": "-- database: presto; groups: tpch; tables: supplier,lineitem,orders,customer,nation\nSELECT supp_nation,\n       cust_nation,\n       l_year,\n       sum(volume) AS revenue\nFROM (SELECT n1.n_name                          AS supp_nation,\n             n2.n_name                          AS cust_nation,\n             extract(YEAR FROM l_shipdate)      AS l_year,\n             l_extendedprice * (1 - l_discount) AS volume\n      FROM supplier,\n           lineitem,\n           orders,\n           customer,\n           nation n1,\n           nation n2\n      WHERE s_suppkey = l_suppkey\n        AND o_orderkey = l_orderkey\n        AND c_custkey = o_custkey\n        AND s_nationkey = n1.n_nationkey\n        AND c_nationkey = n2.n_nationkey\n        AND (\n              (n1.n_name = 'FRANCE' AND n2.n_name = 'GERMANY')\n              OR (n1.n_name = 'GERMANY' AND n2.n_name = 'FRANCE')\n          )\n        AND l_shipdate BETWEEN DATE '1995-01-01' AND DATE '1996-12-31') AS shipping\nGROUP BY supp_nation,\n         cust_nation,\n         l_year\nORDER BY supp_nation,\n         cust_nation,\n         l_year\n"
  },
  {
    "path": "core/src/main/resources/tpch/q8.sql",
    "content": "-- database: presto; groups: tpch, big_query; tables: part,supplier,lineitem,orders,customer,nation\nSELECT o_year,\n       sum(CASE\n               WHEN nation = 'BRAZIL'\n                   THEN volume\n               ELSE 0\n           END) / sum(volume) AS mkt_share\nFROM (SELECT extract(YEAR FROM o_orderdate)     AS o_year,\n             l_extendedprice * (1 - l_discount) AS volume,\n             n2.n_name                          AS nation\n      FROM part,\n           supplier,\n           lineitem,\n           orders,\n           customer,\n           nation n1,\n           nation n2,\n           region\n      WHERE p_partkey = l_partkey\n        AND s_suppkey = l_suppkey\n        AND l_orderkey = o_orderkey\n        AND o_custkey = c_custkey\n        AND c_nationkey = n1.n_nationkey\n        AND n1.n_regionkey = r_regionkey\n        AND r_name = 'AMERICA'\n        AND s_nationkey = n2.n_nationkey\n        AND o_orderdate BETWEEN DATE '1995-01-01' AND DATE '1996-12-31'\n        AND p_type = 'ECONOMY ANODIZED STEEL') AS all_nations\nGROUP BY o_year\nORDER BY o_year\n"
  },
  {
    "path": "core/src/main/resources/tpch/q9.sql",
    "content": "-- database: presto; groups: tpch, big_query; tables: part,supplier,lineitem,partsupp,orders,nation\nSELECT nation,\n       o_year,\n       sum(amount) AS sum_profit\nFROM (SELECT n_name                                                          AS nation,\n             extract(YEAR FROM o_orderdate)                                  AS o_year,\n             l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity AS amount\n      FROM part,\n           supplier,\n           lineitem,\n           partsupp,\n           orders,\n           nation\n      WHERE s_suppkey = l_suppkey\n        AND ps_suppkey = l_suppkey\n        AND ps_partkey = l_partkey\n        AND p_partkey = l_partkey\n        AND o_orderkey = l_orderkey\n        AND s_nationkey = n_nationkey\n        AND p_name LIKE '%green%') AS profit\nGROUP BY nation,\n         o_year\nORDER BY nation,\n         o_year DESC\n"
  },
  {
    "path": "core/src/main/scripts/druidStat.bat",
    "content": "@echo off\n\nrem Copyright 1999-2011 Alibaba Group Holding Ltd.\nrem \nrem Licensed under the Apache License, Version 2.0 (the \"License\");\nrem you may not use this file except in compliance with the License.\nrem You may obtain a copy of the License at\nrem \nrem      http://www.apache.org/licenses/LICENSE-2.0\nrem \nrem Unless required by applicable law or agreed to in writing, software\nrem distributed under the License is distributed on an \"AS IS\" BASIS,\nrem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nrem See the License for the specific language governing permissions and\nrem limitations under the License.\n\n\nset _RUNJAVA=\"%JAVA_HOME%\\bin\\java.exe\"\nset _TOOLSJAR=\"%JAVA_HOME%\\lib\\tools.jar\"\n\n%_RUNJAVA% -classpath \"./druid-0.2.6.jar;%_TOOLSJAR%\" com.alibaba.druid.support.console.DruidStat %*\n"
  },
  {
    "path": "core/src/main/scripts/druidStat.sh",
    "content": "#!/bin/sh\n\nif [ -z \"$JAVA_HOME\" ] ; then\n  echo \"Error: JAVA_HOME is not defined.\"\n  exit 1\nfi\n\n\"$JAVA_HOME/bin/java\" -Dfile.encoding=\"UTF-8\" -cp \"./druid-0.2.6.jar:$JAVA_HOME/lib/tools.jar\" com.alibaba.druid.support.console.DruidStat  $@\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/Bug_for_alibank.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport com.alibaba.druid.support.json.JSONUtils;\nimport org.junit.jupiter.api.Test;\n\npublic class Bug_for_alibank {\n    @Test\n    public void test_bug() throws Exception {\n        String jsonStrz = \"{\\\"addContact\\\":[{\\\"address\\\":\\\"=\\\\\\\\\\\\\\\\\\\\\\'\\'\\\\&quot;);|]*{%0d%0a&lt;%00\\\"}]}\";\n        System.out.println(jsonStrz);\n        Object o = JSONUtils.parse(jsonStrz.replaceAll(\"\\\\\\\\\", \"\"));\n        System.out.println(JSONUtils.toJSONString(o));\n        System.out.println(System.getProperty(\"java.vendor\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/DBCPTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\n\npublic class DBCPTest {\n    @Test\n    public void test_max() throws Exception {\n        Class.forName(\"com.alibaba.druid.mock.MockDriver\");\n\n        final BasicDataSource dataSource = new BasicDataSource();\n//        final DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setInitialSize(3);\n        dataSource.setMaxActive(20);\n        dataSource.setMaxIdle(20);\n        dataSource.setDriverClassName(\"com.alibaba.druid.mock.MockDriver\");\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        final int THREAD_COUNT = 200;\n        final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT);\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        Thread[] threads = new Thread[THREAD_COUNT];\n        for (int i = 0; i < THREAD_COUNT; ++i) {\n            threads[i] = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n                        for (int i = 0; i < 1000; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            Thread.sleep(1);\n                            conn.close();\n                        }\n                    } catch (Exception e) {\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n            threads[i].start();\n        }\n\n        startLatch.countDown();\n\n        endLatch.await();\n\n//        System.out.println(dataSource.getNumIdle());\n        System.out.println(MockDriver.instance.getConnections().size());\n        System.out.println(MockDriver.instance.getConnectionCloseCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/DbTestCase.java",
    "content": "package com.alibaba.druid;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\n/**\n * Created by wenshao on 18/05/2017.\n */\npublic abstract class DbTestCase {\n    protected DruidDataSource dataSource;\n\n    protected final String resource;\n\n    public DbTestCase(String resource) {\n        this.resource = resource;\n    }\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        this.dataSource = createDataSourceFromResource(resource);\n    }\n\n    static DruidDataSource createDataSourceFromResource(String resource) throws IOException {\n        Properties properties = new Properties();\n\n        InputStream configStream = null;\n        try {\n            configStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);\n            properties.load(configStream);\n        } finally {\n            JdbcUtils.close(configStream);\n        }\n\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.configFromPropeties(properties);\n        return dataSource;\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    public Connection getConnection() throws SQLException {\n        return dataSource.getConnection();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/DragoonMetaInfTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.net.URL;\nimport java.util.Enumeration;\nimport java.util.Properties;\n\npublic class DragoonMetaInfTest {\n    @Test\n    public void test_0() throws Exception {\n        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();\n        Enumeration<URL> e = classLoader.getResources(\"META-INF/dragoon-filter.properties\");\n        while (e.hasMoreElements()) {\n            URL url = e.nextElement();\n            InputStream is = url.openStream();\n            Properties properties = new Properties();\n            try {\n                properties.load(is);\n            } finally {\n                is.close();\n            }\n        }\n    }\n\n    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;\n\n    public static long copyLarge(Reader input, Writer output) throws IOException {\n        char[] buffer = new char[DEFAULT_BUFFER_SIZE];\n        long count = 0;\n        int n = 0;\n        while (-1 != (n = input.read(buffer))) {\n            output.write(buffer, 0, n);\n            count += n;\n        }\n        return count;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/LockTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\npublic class LockTest {\n    @Test\n    public void test_0() throws Exception {\n        Lock lock = new ReentrantLock();\n\n        lock.lock();\n        lock.unlock();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/PoolTestCase.java",
    "content": "package com.alibaba.druid;\n\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\n\npublic class PoolTestCase {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestForZY.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class TestForZY {\n    public void foo() throws Exception {\n        Map<String, Map.Entry<String, Boolean>> m = new HashMap<String, Map.Entry<String, Boolean>>();\n    }\n\n    public static class A<T> {\n        private T value;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestHibernateCRUDWithTransactional.java",
    "content": "package com.alibaba.druid;\n\n/**\n * author yinheli [yinheli@gmail.com]\n * date 2012-11-26 下午11:35\n */\npublic class TestHibernateCRUDWithTransactional {\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestHistogram.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport org.junit.jupiter.api.Test;\npublic class TestHistogram {\n    @Test\n    public void test_histogram() throws Exception {\n        int val = 4;\n        for (int i = 0; i < 10; ++i) {\n            val *= 4;\n            System.out.println(val);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestIdel3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.ObjectName;\n\nimport java.lang.management.ManagementFactory;\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestIdel3 {\n    @Test\n    public void test_idle2() throws Exception {\n        MockDriver driver = new MockDriver();\n\n        final DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(14);\n        dataSource.setMaxIdle(14);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(3 * 100); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(18 * 10); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n\n        ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource,\n                new ObjectName(\"com.alibaba:type=DataSource\"));\n\n        // 第一次创建连接\n        {\n            assertEquals(0, dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(dataSource.getInitialSize(), dataSource.getCreateCount());\n            assertEquals(dataSource.getInitialSize(), driver.getConnections().size());\n            assertEquals(1, dataSource.getActiveCount());\n\n            conn.close();\n            assertEquals(0, dataSource.getDestroyCount());\n            assertEquals(2, driver.getConnections().size());\n            assertEquals(2, dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n        }\n\n        {\n            // 并发创建14个\n            int count = 14;\n            Connection[] connections = new Connection[count];\n            for (int i = 0; i < count; ++i) {\n                connections[i] = dataSource.getConnection();\n                assertEquals(i + 1, dataSource.getActiveCount());\n            }\n\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(count, driver.getConnections().size());\n\n            // 全部关闭\n            for (int i = 0; i < count; ++i) {\n                connections[i].close();\n                assertEquals(count - i - 1, dataSource.getActiveCount());\n            }\n\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(14, driver.getConnections().size());\n        }\n\n        concurrent(dataSource, 100, 1000);\n        concurrent(dataSource, 1, 1000 * 1000);\n        Thread.sleep(1000 * 10);\n        concurrent(dataSource, 1, 1000 * 1000);\n        Thread.sleep(1000 * 10);\n        concurrent(dataSource, 1000, 1000 * 1000);\n\n        assertEquals(driver.getConnections().size(), dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        // 连续打开关闭单个连接\n        for (int i = 0; i < 1000; ++i) {\n            assertEquals(0, dataSource.getActiveCount());\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(1, dataSource.getActiveCount());\n\n            Thread.sleep(10);\n            conn.close();\n        }\n        // assertEquals(2, dataSource.getPoolingCount());\n\n        Thread.sleep(1000 * 100);\n        dataSource.close();\n    }\n\n    private void concurrent(final DruidDataSource dataSource, int threadCount, final int loopCount)\n            throws InterruptedException {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        Thread[] threads = new Thread[threadCount];\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i] = new Thread(\"thread-\" + i) {\n                public void run() {\n                    try {\n                        startLatch.await();\n                        for (int i = 0; i < loopCount; ++i) {\n                            Connection conn = null;\n\n                            conn = dataSource.getConnection();\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n        }\n\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i].start();\n        }\n        startLatch.countDown();\n        System.out.println(\"concurrent start...\");\n        endLatch.await();\n        System.out.println(\"concurrent end\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestLRU.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.LinkedHashMap;\n\npublic class TestLRU {\n    @Test\n    public void test_lru() throws Exception {\n        LinkedHashMap<Integer, Object> cache = new LinkedHashMap<Integer, Object>(100, 0.75f, true);\n\n        cache.put(2, \"22\");\n        cache.put(3, \"33\");\n\n        System.out.println(cache);\n\n        cache.put(2, \"22\");\n\n        System.out.println(cache);\n        cache.get(3);\n        System.out.println(cache);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestLockCount.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestLockCount {\n    @Test\n    public void test_current() throws Exception {\n        DataSource dataSource = new DataSource();\n\n        final int threadCount = 10;\n        final int loopCount = 1000 * 1000 * 1000;\n        concurrent(dataSource, threadCount, loopCount);\n        long result = (long) threadCount * ((long) loopCount);\n\n        assertEquals(result, dataSource.getCount());\n        assertEquals(result, dataSource.getC0());\n        assertEquals(result, dataSource.getC1());\n        assertEquals(result, dataSource.getC2());\n        assertEquals(result, dataSource.getC3());\n        assertEquals(result, dataSource.getC4());\n        assertEquals(result, dataSource.getC5());\n        assertEquals(result, dataSource.getC6());\n        assertEquals(result, dataSource.getC7());\n        assertEquals(result, dataSource.getC8());\n        assertEquals(result, dataSource.getC9());\n\n        assertEquals(result, dataSource.getC10());\n        assertEquals(result, dataSource.getC11());\n        assertEquals(result, dataSource.getC12());\n        assertEquals(result, dataSource.getC13());\n        assertEquals(result, dataSource.getC14());\n        assertEquals(result, dataSource.getC15());\n        assertEquals(result, dataSource.getC16());\n        assertEquals(result, dataSource.getC17());\n        assertEquals(result, dataSource.getC18());\n        assertEquals(result, dataSource.getC19());\n    }\n\n    private void concurrent(final DataSource dataSource, int threadCount, final int loopCount)\n            throws InterruptedException {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        Thread[] threads = new Thread[threadCount];\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i] = new Thread(\"thread-\" + i) {\n                public void run() {\n                    try {\n                        startLatch.await();\n                        for (int i = 0; i < loopCount; ++i) {\n                            dataSource.increment();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n        }\n\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i].start();\n        }\n        startLatch.countDown();\n        System.out.println(\"concurrent start...\");\n        endLatch.await();\n        System.out.println(\"concurrent end\");\n    }\n\n    private static class DataSource {\n        private long c0;\n        private long c1;\n        private long c2;\n        private long c3;\n        private long c4;\n        private long c5;\n        private long c6;\n        private long c7;\n        private long c8;\n        private long c9;\n        private long c10;\n        private long c11;\n        private long c12;\n        private long c13;\n        private long c14;\n        private long c15;\n        private long c16;\n        private long c17;\n        private long c18;\n        private long c19;\n        private final Lock lock = new ReentrantLock();\n\n        public long getCount() {\n            return c1;\n        }\n\n        public long getC0() {\n            return c0;\n        }\n\n        public long getC1() {\n            return c1;\n        }\n\n        public long getC2() {\n            return c2;\n        }\n\n        public long getC3() {\n            return c3;\n        }\n\n        public long getC4() {\n            return c4;\n        }\n\n        public long getC5() {\n            return c5;\n        }\n\n        public long getC6() {\n            return c6;\n        }\n\n        public long getC7() {\n            return c7;\n        }\n\n        public long getC8() {\n            return c8;\n        }\n\n        public long getC9() {\n            return c9;\n        }\n\n        public long getC10() {\n            return c10;\n        }\n\n        public long getC11() {\n            return c11;\n        }\n\n        public long getC12() {\n            return c12;\n        }\n\n        public long getC13() {\n            return c13;\n        }\n\n        public long getC14() {\n            return c14;\n        }\n\n        public long getC15() {\n            return c15;\n        }\n\n        public long getC16() {\n            return c16;\n        }\n\n        public long getC17() {\n            return c17;\n        }\n\n        public long getC18() {\n            return c18;\n        }\n\n        public long getC19() {\n            return c19;\n        }\n\n        public void increment() {\n            lock.lock();\n            try {\n                c0++;\n                c1++;\n                c2++;\n                c3++;\n                c4++;\n                c5++;\n                c6++;\n                c7++;\n                c8++;\n                c9++;\n                c10++;\n                c11++;\n                c12++;\n                c13++;\n                c14++;\n                c15++;\n                c16++;\n                c17++;\n                c18++;\n                c19++;\n            } finally {\n                lock.unlock();\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestOracle.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOracle {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private String SQL;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        // jdbcUrl = \"jdbc:oracle:thin:@10.20.149.85:1521:ocnauto\";\n        // user = \"alibaba\";\n        // password = \"ccbuauto\";\n        // SQL = \"SELECT * FROM WP_ORDERS WHERE ID = ?\";\n\n        jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:xx\";\n        user = \"a\";\n        password = \"b\";\n        SQL = \"SELECT * FROM AV_INFO WHERE ID = ?\";\n\n        driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_o() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(50);\n        dataSource.setUseOracleImplicitCache(true);\n        // dataSource.setConnectionProperties(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache=true\");\n\n        for (int i = 1; i <= 1; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            int rowNum = i + 1; // (i % 50) + 1;\n            String sql = SQL + \" AND ROWNUM <= \" + rowNum;\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.setInt(1, 61);\n            ResultSet rs = stmt.executeQuery();\n            int rowCount = 0;\n            while (rs.next()) {\n                rowCount++;\n            }\n            assertEquals(true, rowCount > 0);\n            // Assert.isTrue(!rs.isClosed());\n            rs.close();\n            // Assert.isTrue(!stmt.isClosed());\n            stmt.close();\n\n            conn.close();\n\n        }\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestOraclePing.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport oracle.jdbc.OracleConnection;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\npublic class TestOraclePing {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private String SQL;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        // jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        // user = \"alibaba\";\n        // password = \"ccbuauto\";\n        // SQL = \"SELECT * FROM WP_ORDERS WHERE ID = ?\";\n\n        jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ointest3\";\n        user = \"alibaba\";\n        password = \"deYcR7facWSJtCuDpm2r\";\n        SQL = \"SELECT * FROM AV_INFO WHERE ID = ?\";\n\n        driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_o() throws Exception {\n        Class.forName(driverClass);\n\n        Connection conn = DriverManager.getConnection(jdbcUrl, user, password);\n\n        OracleConnection oracleConn = (OracleConnection) conn;\n\n        for (int i = 0; i < 10; ++i) {\n            ping_1000(oracleConn);\n            select_1000(oracleConn);\n        }\n\n        conn.close();\n    }\n\n    private void ping_1000(OracleConnection oracleConn) throws SQLException {\n        long startMillis = System.currentTimeMillis();\n        final int COUNT = 10000;\n        for (int i = 0; i < COUNT; ++i) {\n            pring(oracleConn);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"ping : \" + millis);\n    }\n\n    private void select_1000(OracleConnection oracleConn) throws SQLException {\n        long startMillis = System.currentTimeMillis();\n        final int COUNT = 10000;\n        for (int i = 0; i < COUNT; ++i) {\n            select(oracleConn);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"select : \" + millis);\n    }\n\n    public void pring(OracleConnection oracleConn) throws SQLException {\n        oracleConn.pingDatabase(1000);\n    }\n\n    public void select(OracleConnection oracleConn) throws SQLException {\n        Statement stmt = oracleConn.createStatement();\n        stmt.execute(\"SELECT 1 FROM DUAL\");\n        stmt.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestReplaceLicense.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.*;\n\npublic class TestReplaceLicense {\n    private String license;\n    private String lineSeparator;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(\"License.txt\");\n        Reader reader = new InputStreamReader(is);\n        license = Utils.read(reader);\n        reader.close();\n        System.out.println(license);\n\n        lineSeparator = \"\\n\"; // (String) java.security.AccessController.doPrivileged(new\n        // sun.security.action.GetPropertyAction(\"line.separator\"));\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        File file = new File(\"/usr/alibaba/workspace/druid\");\n        listFile(file);\n    }\n\n    public void listFile(File file) throws Exception {\n        if (file.isDirectory()) {\n            for (File child : file.listFiles()) {\n                listFile(child);\n            }\n        } else {\n            if (file.getName().endsWith(\".java\")) {\n                listJavaFile(file);\n            }\n        }\n    }\n\n    public void listJavaFile(File file) throws Exception {\n        FileInputStream in = new FileInputStream(file);\n        InputStreamReader reader = new InputStreamReader(in, \"utf-8\");\n        String content = Utils.read(reader);\n        reader.close();\n\n        if (!content.startsWith(license)) {\n            String newContent;\n            int index = content.indexOf(\"package \");\n            if (index != -1) {\n                newContent = license + lineSeparator + content.substring(index);\n            } else {\n                newContent = license + lineSeparator + content;\n            }\n            FileOutputStream out = new FileOutputStream(file);\n            Writer writer = new OutputStreamWriter(out, \"utf-8\");\n            writer.write(newContent);\n            writer.close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestRollBack.java",
    "content": "package com.alibaba.druid;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.mchange.v2.c3p0.ComboPooledDataSource;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.nutz.dao.Chain;\nimport org.nutz.dao.Cnd;\nimport org.nutz.dao.Dao;\nimport org.nutz.dao.Sqls;\nimport org.nutz.dao.impl.NutDao;\nimport org.nutz.trans.Atom;\nimport org.nutz.trans.Trans;\n\nimport java.beans.PropertyVetoException;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npublic class TestRollBack {\n    static ComboPooledDataSource c3p0;\n    static DruidDataSource druid;\n    static Dao dao_c3p0;\n    static Dao dao_druid;\n\n//    static String url = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n//    static String user = \"alibaba\";\n//    static String password = \"ccbuauto\";\n//    static String driver = \"oracle.jdbc.driver.OracleDriver\";\n\n    static String url = \"jdbc:jtds:sqlserver://a.b.c.d:1433/druid_db\";\n    static String user = \"sa\";\n    static String password = \"hello123\";\n    static String driver = \"net.sourceforge.jtds.jdbc.Driver\";\n\n//  jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n//  user = \"alibaba\";\n//  password = \"ccbuauto\";\n\n    @BeforeAll\n    public static void init() throws PropertyVetoException, SQLException {\n        c3p0 = new ComboPooledDataSource();\n        //c3p0.setDriverClass(\"oracle.jdbc.driver.OracleDriver\");\n        c3p0.setDriverClass(driver);\n        c3p0.setJdbcUrl(url);\n        c3p0.setUser(user);\n        c3p0.setPassword(password);\n\n        druid = new DruidDataSource();\n        druid.setUrl(url);\n        druid.setUsername(user);\n        druid.setPassword(password);\n        druid.setFilters(\"stat,trace,encoding\");\n        druid.setDefaultAutoCommit(false);\n\n        dao_c3p0 = new NutDao(c3p0);\n        dao_druid = new NutDao(druid);\n        if (!dao_c3p0.exists(\"msg\")) {\n            dao_c3p0.execute(Sqls.create(\"create table msg(message varchar(5))\")); // 字段长度5\n        }\n    }\n\n    @AfterAll\n    public static void destroy() {\n        c3p0.close();\n        druid.close();\n    }\n\n    @BeforeEach\n    public void before() {\n        // 清空所有数据\n        dao_c3p0.clear(\"msg\");\n    }\n\n    @Test\n    public void test_c3p0() {\n        try {\n            // 将两条插入语句包裹在一个事务内执行,第一条可以正常插入,第二条超过字段长度,会抛异常,事务会回滚\n            Trans.exec(new Atom() {\n                @Override\n                public void run() {\n                    dao_c3p0.insert(\"msg\", Chain.make(\"message\", \"abc\"));\n                    dao_c3p0.insert(\"msg\", Chain.make(\"message\", \"1234567\"));\n                }\n            });\n        } catch (Exception e) {\n        }\n        // abc也跟着回滚了\n        assertNull(dao_c3p0.fetch(\"msg\", Cnd.where(\"message\", \"=\", \"abc\")));\n    }\n\n    @Test\n    public void test_druid() {\n        try {\n            Trans.exec(new Atom() {\n                @Override\n                public void run() {\n                    dao_druid.insert(\"msg\", Chain.make(\"message\", \"abc\"));\n                    dao_druid.insert(\"msg\", Chain.make(\"message\", \"1234567\"));\n                }\n            });\n        } catch (Exception e) {\n            // e.printStackTrace(); // 把这里的异常打印出来\n        }\n        // abc插了进去,没有回滚\n        assertNotNull(dao_druid.fetch(\"msg\", Cnd.where(\"message\", \"=\", \"abc\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestSqlServer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\n\npublic class TestSqlServer {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private String SQL;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        // jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        // user = \"alibaba\";\n        // password = \"ccbuauto\";\n        // SQL = \"SELECT * FROM WP_ORDERS WHERE ID = ?\";\n\n        jdbcUrl = \"jdbc:jtds:sqlserver://a.b.c.d:1433/druid_db\";\n        user = \"sa\";\n        password = \"hello123\";\n        SQL = \"SELECT * FROM AV_INFO WHERE ID = ?\";\n\n        driverClass = \"net.sourceforge.jtds.jdbc.Driver\";\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        Class.forName(driverClass);\n\n        Connection conn = DriverManager.getConnection(jdbcUrl, user, password);\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestTraceFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcTraceManager;\nimport com.alibaba.druid.util.JMXUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\n@SuppressWarnings(\"deprecation\")\npublic class TestTraceFilter {\n    @Test\n    public void test_loop() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setFilters(\"stat,trace\");\n        dataSource.setUrl(\"jdbc:mock:\");\n\n        JMXUtils.register(\"com.alibaba.dragoon:type=JdbcTraceManager\", JdbcTraceManager.getInstance());\n\n        for (int i = 0; i < 1000; ++i) {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            ResultSet rs = stmt.executeQuery(\"SELECT 1\");\n            rs.next();\n            rs.close();\n            stmt.close();\n            conn.close();\n\n            Thread.sleep(1000);\n        }\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/TestUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid;\n\nimport com.alibaba.druid.util.Utils;\n\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\n\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.lang.management.ManagementFactory;\n\npublic class TestUtil {\n    public static long getYoungGC() {\n        try {\n            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n            ObjectName objectName;\n            if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=ParNew\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=ParNew\");\n            } else if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=Copy\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=Copy\");\n            } else {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=PS Scavenge\");\n            }\n\n            return (Long) mbeanServer.getAttribute(objectName, \"CollectionCount\");\n        } catch (Exception e) {\n            throw new RuntimeException(\"error\");\n        }\n    }\n\n    public static long getFullGC() {\n        try {\n            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n            ObjectName objectName;\n\n            if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=ConcurrentMarkSweep\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=ConcurrentMarkSweep\");\n            } else if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=MarkSweepCompact\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=MarkSweepCompact\");\n            } else {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=PS MarkSweep\");\n            }\n\n            return (Long) mbeanServer.getAttribute(objectName, \"CollectionCount\");\n        } catch (Exception e) {\n            throw new RuntimeException(\"error\");\n        }\n    }\n\n    public static String getResource(String path) {\n        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();\n        try (Reader reader = new InputStreamReader(\n                contextClassLoader\n                        .getResourceAsStream(path), \"UTF-8\")\n        ) {\n            return Utils.read(reader);\n        } catch (IOException ignored) {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/FnvHashTest.java",
    "content": "package com.alibaba.druid.benckmark;\n\nimport com.alibaba.druid.util.FnvHash;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FnvHashTest {\n    static String sql = \"SELECT id, item_id, rule_id, tag_id, ext , gmt_create, gmt_modified FROM wukong_preview_item_tag WHERE item_id = ? AND rule_id = ?\";\n    static char[] chars = sql.toCharArray();\n\n    @Test\n    public void test_perf_fnv() throws Exception {\n        for (int i = 0; i < 5; ++i) {\n//            perf_hashCode64(sql); // 168\n            perf_hashCode64(chars); // 169\n        }\n    }\n\n    public long perf_hashCode64(String sql) {\n        long val = 0;\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            val = FnvHash.fnv1a_64(sql);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n        return val;\n    }\n\n    public long perf_hashCode64(char[] sql) {\n        long val = 0;\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            val = FnvHash.fnv1a_64(sql);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n        return val;\n    }\n\n    @Test\n    public void test_fnv_hash_1a() throws Exception {\n        assertEquals(FnvHash.fnv1a_64(\"bcd\"), FnvHash.fnv1a_64(\"abcde\", 1, 4));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/TPCDS.java",
    "content": "package com.alibaba.druid.benckmark;\n\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport java.io.InputStream;\n\npublic class TPCDS {\n    private static String ddl;\n    private static String[] QUERIES = new String[99];\n\n    static {\n        for (int i = 1; i <= 99; ++i) {\n            String num = (i < 10 ? \"0\" : \"\") + i;\n            String path = \"tpcds/query\" + num + \".sql\";\n            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);\n            String sql = Utils.read(is);\n            QUERIES[i - 1] = sql;\n            JdbcUtils.close(is);\n        }\n        {\n            String path = \"tpcds/create_tables.sql\";\n            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);\n            ddl = Utils.read(is);\n            JdbcUtils.close(is);\n        }\n    }\n\n    public static String getQuery(int index) {\n        return QUERIES[index - 1];\n    }\n\n    public static String getDDL() {\n        return ddl;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/TPCH.java",
    "content": "package com.alibaba.druid.benckmark;\n\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport java.io.InputStream;\n\npublic class TPCH {\n    private static final String insert_lineitem_200;\n    private static String ddl;\n    private static String[] QUERIES = new String[22];\n\n    static {\n        for (int i = 1; i <= 22; ++i) {\n            String path = \"tpch/q\" + i + \".sql\";\n            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);\n            String sql = Utils.read(is);\n            QUERIES[i - 1] = sql;\n            JdbcUtils.close(is);\n        }\n        {\n            String path = \"tpch/create_tables.sql\";\n            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);\n            ddl = Utils.read(is);\n            JdbcUtils.close(is);\n        }\n        {\n            String path = \"tpch/insert_lineitem_200.sql\";\n            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);\n            insert_lineitem_200 = Utils.read(is);\n            JdbcUtils.close(is);\n        }\n    }\n\n    public static String getQuery(int index) {\n        return QUERIES[index - 1];\n    }\n\n    public static String getDDL() {\n        return ddl;\n    }\n\n    public static String getInsertLineitem200() {\n        return insert_lineitem_200;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/AsyncClose.java",
    "content": "package com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.text.NumberFormat;\n\npublic class AsyncClose {\n    public static void main(String[] args) throws Exception {\n        Class.forName(\"com.alibaba.druid.mock.MockDriver\");\n        DataSource ds = createDruid();\n        System.out.println(\"init done\");\n\n        for (int i = 0; i < 10; ++i) {\n            perf(ds);\n        }\n\n        System.out.println(\"query done\");\n    }\n\n    public static void perf(DataSource ds) throws Exception {\n        long start = System.currentTimeMillis();\n        final int count = 1000 * 1000;\n        for (int i = 0; i < count; ++i) {\n            Connection conn = ds.getConnection();\n\n            PreparedStatement ps = conn.prepareStatement(\"select 1\");\n\n            ResultSet rs = ps.executeQuery();\n            while (rs.next()) {\n                // Intentionally empty loop\n            }\n\n            rs.close();\n            ps.close();\n            conn.close();\n        }\n        long millis = System.currentTimeMillis() - start;\n\n        System.out.println(\"millis \" + millis + \", qps \" + NumberFormat.getInstance().format(1000 * 1000 * 1000 / millis));\n    }\n\n    public static DataSource createDruid() throws Exception {\n        DruidDataSource ds = new DruidDataSource();\n        ds.setUrl(\"jdbc:fake:dragoon_v25masterdb\");\n        ds.setUsername(\"tddl5\");\n        ds.setPassword(\"tddl5\");\n        ds.setFilters(\"stat\");\n//         ds.setAsyncCloseConnectionEnable(true);\n        ds.init();\n\n        return ds;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Case0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.jolbox.bonecp.BoneCPDataSource;\nimport com.mchange.v2.c3p0.ComboPooledDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.text.NumberFormat;\n\npublic class Case0 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 1;\n    private int minIdle = 3;\n    private int maxIdle = 8;\n    private int maxActive = 8;\n    private String validationQuery = \"SELECT 1\";\n    private boolean testOnBorrow;\n\n    private long minEvictableIdleTimeMillis = 3000;\n    public final int LOOP_COUNT = 5;\n    public final int COUNT = 1000 * 1000 * 1;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        user = \"dragoon25\";\n        password = \"dragoon25\";\n        driverClass = \"com.alibaba.druid.mock.MockDriver\";\n\n//        jdbcUrl = \"jdbc:mysql://a.b.c.d:3306/masterdb\";\n//        user = \"x\";\n//        password = \"x\";\n    }\n\n    @Test\n    public void test_druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"druid\");\n        }\n        System.out.println();\n    }\n\n    public void f_test_1() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"dbcp\");\n        }\n        System.out.println();\n    }\n\n    public void f_test_2() throws Exception {\n        BoneCPDataSource dataSource = new BoneCPDataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinConnectionsPerPartition(minIdle);\n        dataSource.setMaxConnectionsPerPartition(maxIdle);\n\n        dataSource.setDriverClass(driverClass);\n        dataSource.setJdbcUrl(jdbcUrl);\n        // dataSource.setPoolPreparedStatements(true);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setConnectionTestStatement(validationQuery);\n        dataSource.setPartitionCount(1);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"boneCP\");\n        }\n        System.out.println();\n    }\n\n    public void f_test_c3p0() throws Exception {\n        ComboPooledDataSource dataSource = new ComboPooledDataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinPoolSize(minIdle);\n        dataSource.setMaxPoolSize(maxIdle);\n\n        dataSource.setDriverClass(driverClass);\n        dataSource.setJdbcUrl(jdbcUrl);\n        // dataSource.setPoolPreparedStatements(true);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUser(user);\n        dataSource.setPassword(password);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"c3p0\");\n        }\n        System.out.println();\n    }\n\n    public void f_test_tomcat_jdbc() throws Exception {\n        org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxActive(maxIdle);\n\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        // dataSource.setPoolPreparedStatements(true);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"tomcat-jdbc\");\n        }\n        System.out.println();\n    }\n\n    private void p0(DataSource dataSource, String name) throws SQLException {\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n\n        for (int i = 0; i < COUNT; ++i) {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n//            ResultSet rs = stmt.executeQuery(\"SELECT 1\");\n//            rs.close();\n//            stmt.close();\n            conn.close();\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(name + \" millis : \" + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \"\n                + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Case1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.jolbox.bonecp.BoneCPDataSource;\nimport com.mchange.v2.c3p0.ComboPooledDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.ThreadInfo;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport java.text.NumberFormat;\nimport java.util.Properties;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * TestOnBo 类Case1.java的实现描述：TODO 类实现描述\n *\n * @author admin 2011-5-28 下午03:47:40\n */\npublic class Case1 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 10;\n    private int minPoolSize = 10;\n    private int maxPoolSize = 50;\n    private int maxActive = 50;\n    private String validationQuery = \"SELECT 1\";\n    private int threadCount = 5;\n    private int loopCount = 10;\n    final int LOOP_COUNT = 1000 * 1 * 1 / threadCount;\n\n    private static AtomicLong physicalConnStat = new AtomicLong();\n\n    public static class TestDriver extends MockDriver {\n        public static TestDriver instance = new TestDriver();\n\n        public boolean acceptsURL(String url) throws SQLException {\n            if (url.startsWith(\"jdbc:test:\")) {\n                return true;\n            }\n            return super.acceptsURL(url);\n        }\n\n        public Connection connect(String url, Properties info) throws SQLException {\n            physicalConnStat.incrementAndGet();\n            return super.connect(\"jdbc:mock:case1\", info);\n        }\n    }\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DriverManager.registerDriver(TestDriver.instance);\n\n        user = \"dragoon25\";\n        password = \"dragoon25\";\n\n        // jdbcUrl = \"jdbc:h2:mem:\";\n        // driverClass = \"org.h2.Driver\";\n        jdbcUrl = \"jdbc:test:case1:\";\n        driverClass = \"com.alibaba.druid.benckmark.pool.Case1$TestDriver\";\n\n        physicalConnStat.set(0);\n    }\n\n    @Test\n    public void test_druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minPoolSize);\n        dataSource.setMaxIdle(maxPoolSize);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(false);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_dbcp() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minPoolSize);\n        dataSource.setMaxIdle(maxPoolSize);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setTestOnBorrow(false);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"dbcp\", threadCount);\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_bonecp() throws Exception {\n        BoneCPDataSource dataSource = new BoneCPDataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinConnectionsPerPartition(minPoolSize);\n        dataSource.setMaxConnectionsPerPartition(maxPoolSize);\n\n        dataSource.setDriverClass(driverClass);\n        dataSource.setJdbcUrl(jdbcUrl);\n        dataSource.setStatementsCacheSize(100);\n        dataSource.setServiceOrder(\"LIFO\");\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        // dataSource.setConnectionTestStatement(\"SELECT 1\");\n        dataSource.setPartitionCount(1);\n        dataSource.setAcquireIncrement(5);\n        dataSource.setIdleConnectionTestPeriod(0L);\n        // dataSource.setDisableConnectionTracking(true);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"boneCP\", threadCount);\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_c3p0() throws Exception {\n        ComboPooledDataSource dataSource = new ComboPooledDataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinPoolSize(minPoolSize);\n        dataSource.setMaxPoolSize(maxPoolSize);\n\n        dataSource.setDriverClass(driverClass);\n        dataSource.setJdbcUrl(jdbcUrl);\n        // dataSource.setPoolPreparedStatements(true);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUser(user);\n        dataSource.setPassword(password);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"c3p0\", threadCount);\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_tomcat_jdbc() throws Exception {\n        org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();\n        // dataSource.(10);\n        dataSource.setMaxIdle(maxPoolSize);\n        dataSource.setMinIdle(minPoolSize);\n        dataSource.setMaxActive(maxPoolSize);\n\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        // dataSource.setPoolPreparedStatements(true);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"tomcat-jdbc\", threadCount);\n        }\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        final CountDownLatch dumpLatch = new CountDownLatch(1);\n\n        Thread[] threads = new Thread[threadCount];\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n\n                    try {\n                        dumpLatch.await();\n                    } catch (InterruptedException e) {\n                        e.printStackTrace();\n                    }\n                }\n            };\n            threads[i] = thread;\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long[] threadIdArray = new long[threads.length];\n        for (int i = 0; i < threads.length; ++i) {\n            threadIdArray[i] = threads[i].getId();\n        }\n        ThreadInfo[] threadInfoArray = ManagementFactory.getThreadMXBean().getThreadInfo(threadIdArray);\n\n        dumpLatch.countDown();\n\n        long blockedCount = 0;\n        long waitedCount = 0;\n        for (int i = 0; i < threadInfoArray.length; ++i) {\n            ThreadInfo threadInfo = threadInfoArray[i];\n            blockedCount += threadInfo.getBlockedCount();\n            waitedCount += threadInfo.getWaitedCount();\n        }\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \"; YGC \" + ygc + \" FGC \" + fullGC\n                + \" blocked \"\n                + NumberFormat.getInstance().format(blockedCount) //\n                + \" waited \" + NumberFormat.getInstance().format(waitedCount) + \" physicalConn \"\n                + physicalConnStat.get());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Case2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.jolbox.bonecp.BoneCPDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.ThreadInfo;\nimport java.sql.Connection;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * TestOnBo 类Case1.java的实现描述：TODO 类实现描述\n *\n * @author admin 2011-5-28 下午03:47:40\n */\npublic class Case2 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 10;\n    private int minPoolSize = 10;\n    private int maxPoolSize = 50;\n    private int maxActive = 50;\n    private String validationQuery = \"SELECT 1\";\n    private int threadCount = 100;\n    private int executeCount = 4;\n    final int LOOP_COUNT = (1000 * 100) / executeCount;\n    private boolean testOnBorrow = true;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        user = \"dragoon25\";\n        password = \"dragoon25\";\n        driverClass = \"com.alibaba.druid.mock.MockDriver\";\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minPoolSize);\n        dataSource.setMaxIdle(maxPoolSize);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n\n        for (int i = 0; i < executeCount; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minPoolSize);\n        dataSource.setMaxIdle(maxPoolSize);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setTestOnBorrow(testOnBorrow);\n\n        for (int i = 0; i < executeCount; ++i) {\n            p0(dataSource, \"dbcp\", threadCount);\n        }\n        System.out.println();\n    }\n\n    // 当testOnBorrow为true时，BoneCP的处理策略不一样，所以略过\n    public void f_test_2() throws Exception {\n        BoneCPDataSource dataSource = new BoneCPDataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinConnectionsPerPartition(minPoolSize);\n        dataSource.setMaxConnectionsPerPartition(maxPoolSize);\n\n        dataSource.setDriverClass(driverClass);\n        dataSource.setJdbcUrl(jdbcUrl);\n        dataSource.setStatementsCacheSize(100);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setConnectionTestStatement(\"SELECT 1\");\n        dataSource.setPartitionCount(1);\n        dataSource.setAcquireIncrement(5);\n        dataSource.setIdleConnectionTestPeriod(0L);\n        // dataSource.setDisableConnectionTracking(true);\n\n        for (int i = 0; i < executeCount; ++i) {\n            p0(dataSource, \"boneCP\", threadCount);\n        }\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        final AtomicLong blockedStat = new AtomicLong();\n        final AtomicLong waitedStat = new AtomicLong();\n\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        long threadId = Thread.currentThread().getId();\n\n                        long startBlockedCount, startWaitedCount;\n                        {\n                            ThreadInfo threadInfo = ManagementFactory.getThreadMXBean().getThreadInfo(threadId);\n                            startBlockedCount = threadInfo.getBlockedCount();\n                            startWaitedCount = threadInfo.getWaitedCount();\n                        }\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            conn.close();\n                        }\n\n                        ThreadInfo threadInfo = ManagementFactory.getThreadMXBean().getThreadInfo(threadId);\n                        long blockedCount = threadInfo.getBlockedCount() - startBlockedCount;\n                        long waitedCount = threadInfo.getWaitedCount() - startWaitedCount;\n\n                        blockedStat.addAndGet(blockedCount);\n                        waitedStat.addAndGet(waitedCount);\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC\n                + \" blockedCount \" + blockedStat.get() + \" waitedCount \" + waitedStat.get());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Case3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.jolbox.bonecp.BoneCPDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.text.NumberFormat;\nimport java.util.Properties;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Case3 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 1;\n    private int minIdle = 1;\n    private int maxIdle = 14;\n    private int maxActive = 14;\n    private int maxWait = -1;\n    private String validationQuery = \"SELECT 1\"; // \"SELECT 1\";\n    private int threadCount = 10;\n    private int TEST_COUNT = 3;\n    final int LOOP_COUNT = 1000 * 100;\n    private boolean testOnBorrow;\n    private String connectionProperties = \"\";        // \"bigStringTryClob=true;clientEncoding=GBK;defaultRowPrefetch=50;serverEncoding=ISO-8859-1\";\n    private String sql = \"SELECT 1\";\n    private long timeBetweenEvictionRunsMillis = 60000;\n    private long minEvictableIdleTimeMillis = 60000;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        user = \"dragoon25\";\n        password = \"dragoon25\";\n        driverClass = \"com.alibaba.druid.mock.MockDriver\";\n        // connectionProperties = \"connectSleep=3;executeSleep=1\";\n\n        // jdbcUrl = \"jdbc:mysql://a.b.c.d:3306/druid2\";\n        // user = \"root\";\n        // password = \"root\";\n        // driverClass = \"com.mysql.jdbc.Driver\";\n    }\n\n    @Test\n    public void test_perf() throws Exception {\n        for (int i = 0; i < 5; ++i) {\n            druid();\n            dbcp();\n            // boneCP();\n        }\n    }\n\n    public void boneCP() throws Exception {\n        BoneCPDataSource dataSource = new BoneCPDataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinConnectionsPerPartition(minIdle);\n        dataSource.setMaxConnectionsPerPartition(maxIdle);\n\n        dataSource.setDriverClass(driverClass);\n        dataSource.setJdbcUrl(jdbcUrl);\n        // dataSource.setPoolPreparedStatements(true);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setConnectionTestStatement(validationQuery);\n        dataSource.setPartitionCount(1);\n        Properties connectionProperties = new Properties();\n        connectionProperties.put(\"connectSleep\", \"3\");\n        connectionProperties.put(\"executeSleep\", \"1\");\n        dataSource.setDriverProperties(connectionProperties);\n\n        for (int i = 0; i < TEST_COUNT; ++i) {\n            p0(dataSource, \"boneCP\", threadCount);\n        }\n        System.out.println();\n    }\n\n    public void druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setConnectionProperties(connectionProperties);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n\n        for (int i = 0; i < TEST_COUNT; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n        }\n        dataSource.close();\n        System.out.println();\n    }\n\n    public void dbcp() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setConnectionProperties(connectionProperties);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n\n        for (int i = 0; i < TEST_COUNT; ++i) {\n            p0(dataSource, \"dbcp\", threadCount);\n        }\n        // dataSource.close();\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final AtomicInteger count = new AtomicInteger();\n        final AtomicInteger errorCount = new AtomicInteger();\n\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            Statement stmt = conn.createStatement();\n                            ResultSet rs = stmt.executeQuery(sql);\n                            while (rs.next()) {\n                                rs.getInt(1);\n                            }\n                            rs.close();\n                            stmt.close();\n\n                            conn.close();\n                            count.incrementAndGet();\n                        }\n                    } catch (Throwable ex) {\n                        errorCount.incrementAndGet();\n                        ex.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        assertEquals(LOOP_COUNT * threadCount, count.get());\n        Thread.sleep(1);\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/CaseKylin_Oracle.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\n\npublic class CaseKylin_Oracle {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 1;\n    private int minIdle = 1;\n    private int maxIdle = 14;\n    private int maxActive = 14;\n    private int maxWait = 60000;\n    private String validationQuery;                                 // \"SELECT 1\";\n    private int threadCount = 15;\n    private int TEST_COUNT = 3;\n    final int LOOP_COUNT = 1000 * 100;\n    private boolean testWhileIdle = true;\n    private boolean testOnBorrow = true;\n    private boolean testOnReturn;\n\n    private boolean removeAbandoned = true;\n    private int removeAbandonedTimeout = 180;\n    private long timeBetweenEvictionRunsMillis = 60000;\n    private long minEvictableIdleTimeMillis = 1800000;\n    private int numTestsPerEvictionRun = 20;\n    private String validateQuery;\n\n    private String oracleDriverClass = \"com.alibaba.china.jdbc.SimpleDriver\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        // jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        // user = \"dragoon25\";\n        // password = \"dragoon25\";\n        // driverClass = \"com.alibaba.druid.mock.MockDriver\";\n\n        // jdbcUrl = \"jdbc:mysql://a.b.c.d:3306/druid2\";\n        // user = \"root\";\n        // password = \"root\";\n        // driverClass = \"com.mysql.jdbc.Driver\";\n\n        jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        user = \"alibaba\";\n        password = \"ccbuauto\";\n        driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_perf() throws Exception {\n        for (int i = 0; i < 5; ++i) {\n            druid();\n            dbcp();\n        }\n    }\n\n    public void druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setFilters(\"encoding\");\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setTestOnBorrow(testWhileIdle);\n        dataSource.setTestOnBorrow(testOnReturn);\n        dataSource.setRemoveAbandoned(removeAbandoned);\n        dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n        dataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\n        dataSource.setValidationQuery(validateQuery);\n\n        for (int i = 0; i < TEST_COUNT; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n        }\n        System.out.println();\n    }\n\n    public void dbcp() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(oracleDriverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setTestOnBorrow(testWhileIdle);\n        dataSource.setTestOnBorrow(testOnReturn);\n        dataSource.setRemoveAbandoned(removeAbandoned);\n        dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n        dataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\n        dataSource.setValidationQuery(validateQuery);\n\n        for (int i = 0; i < TEST_COUNT; ++i) {\n            p0(dataSource, \"dbcp\", threadCount);\n        }\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1 FROM DUAL\");\n                            ResultSet rs = stmt.executeQuery();\n                            rs.next();\n                            rs.getInt(1);\n                            rs.close();\n                            stmt.close();\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/CaseKylin_mysql.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\n\npublic class CaseKylin_mysql {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 1;\n    private int minIdle = 1;\n    private int maxIdle = 20;\n    private int maxActive = 20;\n    private int maxWait = 60000;\n    private String validationQuery;      // \"SELECT 1\";\n    private int threadCount = 15;\n    private int TEST_COUNT = 3;\n    final int LOOP_COUNT = 1000 * 100;\n    private boolean testWhileIdle = true;\n    private boolean testOnBorrow;\n    private boolean testOnReturn;\n\n    private boolean removeAbandoned = true;\n    private int removeAbandonedTimeout = 180;\n    private long timeBetweenEvictionRunsMillis = 60000;\n    private long minEvictableIdleTimeMillis = 1800000;\n    private int numTestsPerEvictionRun = 20;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        // jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        // user = \"dragoon25\";\n        // password = \"dragoon25\";\n        // driverClass = \"com.alibaba.druid.mock.MockDriver\";\n\n        jdbcUrl = \"jdbc:mysql://a.b.c.d:3306/druid2\";\n        user = \"root\";\n        password = \"root\";\n        driverClass = \"com.mysql.jdbc.Driver\";\n\n        // jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        // user = \"alibaba\";\n        // password = \"ccbuauto\";\n        // driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_perf() throws Exception {\n        for (int i = 0; i < 5; ++i) {\n            druid();\n            dbcp();\n        }\n    }\n\n    public void druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setTestOnBorrow(testWhileIdle);\n        dataSource.setTestOnBorrow(testOnReturn);\n        dataSource.setRemoveAbandoned(removeAbandoned);\n        dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n        dataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\n\n        for (int i = 0; i < TEST_COUNT; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n        }\n        System.out.println();\n    }\n\n    public void dbcp() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setTestOnBorrow(testWhileIdle);\n        dataSource.setTestOnBorrow(testOnReturn);\n        dataSource.setRemoveAbandoned(removeAbandoned);\n        dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n        dataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\n\n        for (int i = 0; i < TEST_COUNT; ++i) {\n            p0(dataSource, \"dbcp\", threadCount);\n        }\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1 FROM DUAL\");\n                            ResultSet rs = stmt.executeQuery();\n                            rs.next();\n                            rs.getInt(1);\n                            rs.close();\n                            stmt.close();\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/CaseKylin_mysql_idle_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\n\npublic class CaseKylin_mysql_idle_1 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 1;\n    private int minIdle = 1;\n    private int maxIdle = 20;\n    private int maxActive = 20;\n    private int maxWait = 60000;\n    private String validationQuery;     // \"SELECT 1\";\n    private int threadCount = 15;\n    private int TEST_COUNT = 3;\n    final int LOOP_COUNT = 1000 * 10;\n    private boolean testWhileIdle = true;\n    private boolean testOnBorrow;\n    private boolean testOnReturn;\n\n    private boolean removeAbandoned = true;\n    private int removeAbandonedTimeout = 180;\n    private long timeBetweenEvictionRunsMillis = 60000;\n    private long minEvictableIdleTimeMillis = 1800000;\n    private int numTestsPerEvictionRun = 20;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        // jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        // user = \"dragoon25\";\n        // password = \"dragoon25\";\n        // driverClass = \"com.alibaba.druid.mock.MockDriver\";\n\n        jdbcUrl = \"jdbc:mysql://a.b.c.d:8066/amoeba\";\n        user = \"root\";\n        password = \"12345\";\n        driverClass = \"com.mysql.jdbc.Driver\";\n\n        // jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        // user = \"alibaba\";\n        // password = \"ccbuauto\";\n        // driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_perf() throws Exception {\n        druid();\n    }\n\n    public void druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setTestOnBorrow(testWhileIdle);\n        dataSource.setTestOnBorrow(testOnReturn);\n        dataSource.setRemoveAbandoned(removeAbandoned);\n        dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n        dataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\n\n        p0(dataSource, \"druid\", threadCount);\n\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n\n            long seconds = (System.currentTimeMillis() - startMillis) / 1000L;\n            System.out.println(\"seconds : \" + seconds);\n        }\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1 FROM DUAL\");\n                            ResultSet rs = stmt.executeQuery();\n                            rs.next();\n                            rs.getInt(1);\n                            rs.close();\n                            stmt.close();\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/CaseKylin_mysql_idle_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\n\npublic class CaseKylin_mysql_idle_2 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 1;\n    private int minIdle = 1;\n    private int maxIdle = 20;\n    private int maxActive = 20;\n    private int maxWait = 60000;\n    private String validationQuery;     // \"SELECT 1\";\n    private int threadCount = 15;\n    private int TEST_COUNT = 3;\n    final int LOOP_COUNT = 10 * 1;\n    private boolean testWhileIdle = true;\n    private boolean testOnBorrow;\n    private boolean testOnReturn;\n\n    private boolean removeAbandoned = true;\n    private int removeAbandonedTimeout = 180;\n    private long timeBetweenEvictionRunsMillis = 60 * 10;\n    private long minEvictableIdleTimeMillis = 1800 * 10;\n    private int numTestsPerEvictionRun = 20;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        user = \"dragoon25\";\n        password = \"dragoon25\";\n        driverClass = \"com.alibaba.druid.mock.MockDriver\";\n\n        MockDriver.instance.setIdleTimeCount(50 * 60 * 10);\n\n        // jdbcUrl = \"jdbc:mysql://a.b.c.d:8066/amoeba\";\n        // user = \"root\";\n        // password = \"12345\";\n        // driverClass = \"com.mysql.jdbc.Driver\";\n\n        // jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        // user = \"alibaba\";\n        // password = \"ccbuauto\";\n        // driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_perf() throws Exception {\n        druid();\n    }\n\n    public void druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setTestOnBorrow(testWhileIdle);\n        dataSource.setTestOnBorrow(testOnReturn);\n        dataSource.setRemoveAbandoned(removeAbandoned);\n        dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);\n        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n        dataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\n\n        p0(dataSource, \"druid\", threadCount);\n\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n\n            long seconds = (System.currentTimeMillis() - startMillis) / 1000L;\n            System.out.println(\"seconds : \" + seconds);\n        }\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\");\n                            ResultSet rs = stmt.executeQuery();\n                            rs.next();\n                            rs.getInt(1);\n                            rs.close();\n                            stmt.close();\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Case_Concurrent_50.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\n\npublic class Case_Concurrent_50 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize;\n    private int minIdle = 3;\n    private int maxIdle = 5;\n    private int maxActive = 10;\n    private String validationQuery = \"SELECT 1\";\n    private boolean testOnBorrow;\n\n    private long minEvictableIdleTimeMillis = 3000;\n    public final int LOOP_COUNT = 5;\n    public final int COUNT = 1000 * 10;\n\n    private final int THREAD_COUNT = 50;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        jdbcUrl = \"jdbc:fake:dragoon_v25masterdb\";\n        user = \"dragoon25\";\n        password = \"dragoon25\";\n        driverClass = \"com.alibaba.druid.mock.MockDriver\";\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        final DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxWait(6000);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"druid\");\n        }\n\n        System.out.println();\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minIdle);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"dbcp\");\n        }\n\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name) throws Exception {\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n\n        final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT);\n        for (int i = 0; i < THREAD_COUNT; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        for (int i = 0; i < COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            Statement stmt = conn.createStatement();\n                            ResultSet rs = stmt.executeQuery(\"SELECT 1\");\n                            Thread.sleep(0, 1000 * 100);\n                            rs.close();\n                            stmt.close();\n                            conn.close();\n                        }\n\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n            thread.start();\n        }\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(name + \" millis : \" + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \"\n                + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Oracle_Case0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.jolbox.bonecp.BoneCPDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.text.NumberFormat;\n\npublic class Oracle_Case0 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int initialSize = 1;\n    private int minPoolSize = 1;\n    private int maxPoolSize = 2;\n    private int maxActive = 2;\n    private String validationQuery = \"SELECT 1 FROM DUAL\";\n\n    public final int LOOP_COUNT = 5;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        user = \"alibaba\";\n        password = \"ccbuauto\";\n        driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minPoolSize);\n        dataSource.setMaxIdle(maxPoolSize);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(true);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"druid\");\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setInitialSize(initialSize);\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMinIdle(minPoolSize);\n        dataSource.setMaxIdle(maxPoolSize);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(true);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"dbcp\");\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        BoneCPDataSource dataSource = new BoneCPDataSource();\n        // dataSource.(10);\n        // dataSource.setMaxActive(50);\n        dataSource.setMinConnectionsPerPartition(minPoolSize);\n        dataSource.setMaxConnectionsPerPartition(maxPoolSize);\n\n        dataSource.setDriverClass(driverClass);\n        dataSource.setJdbcUrl(jdbcUrl);\n        // dataSource.setPoolPreparedStatements(true);\n        // dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setConnectionTestStatement(validationQuery);\n        dataSource.setPartitionCount(1);\n\n        for (int i = 0; i < LOOP_COUNT; ++i) {\n            p0(dataSource, \"boneCP\");\n        }\n        System.out.println();\n    }\n\n    private void p0(DataSource dataSource, String name) throws SQLException {\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n\n        final int COUNT = 1000 * 1;\n        for (int i = 0; i < COUNT; ++i) {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1 FROM DUAL\");\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(name + \" millis : \" + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \"\n                + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Oracle_Case3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.util.Assert;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\n\npublic class Oracle_Case3 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int maxIdle = 40;\n    private int maxActive = 50;\n    private int maxWait = 5000;\n    private String validationQuery = \"SELECT 1 FROM DUAL\";\n    private int threadCount = 40;\n    private int loopCount = 5;\n    final int LOOP_COUNT = 1000 * 10;\n    private boolean testOnBorrow = true;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n        user = \"alibaba\";\n        password = \"ccbuauto\";\n        driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"dbcp\", threadCount);\n        }\n        System.out.println();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            Statement stmt = conn.createStatement();\n                            ResultSet rs = stmt.executeQuery(\"SELECT 1 FROM DUAL\");\n                            rs.next();\n                            // Assert.isTrue(!rs.isClosed());\n                            rs.close();\n                            // Assert.isTrue(!stmt.isClosed());\n                            stmt.close();\n                            Assert.isTrue(stmt.isClosed());\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/Oracle_Case4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.util.Assert;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.text.NumberFormat;\nimport java.util.concurrent.CountDownLatch;\n\npublic class Oracle_Case4 {\n    private String jdbcUrl;\n    private String user;\n    private String password;\n    private String driverClass;\n    private int maxIdle = 40;\n    private int maxActive = 50;\n    private int maxWait = 5000;\n    private String validationQuery = \"SELECT 1 FROM DUAL\";\n    private int threadCount = 1;\n    private int loopCount = 5;\n    final int LOOP_COUNT = 1000 * 1;\n    private boolean testOnBorrow;\n    private boolean preparedStatementCache = true;\n    private int preparedStatementCacheSize = 50;\n    private String properties = \"defaultRowPrefetch=50\";\n\n    private String SQL;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n//         jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ocnauto\";\n//         user = \"alibaba\";\n//         password = \"ccbuauto\";\n//         SQL = \"SELECT * FROM WP_ORDERS WHERE ID = ?\";\n\n        jdbcUrl = \"jdbc:oracle:thin:@a.b.c.d:1521:ointest3\";\n        user = \"alibaba\";\n        password = \"deYcR7facWSJtCuDpm2r\";\n        SQL = \"SELECT * FROM AV_INFO WHERE ID = ?\";\n\n        driverClass = \"oracle.jdbc.driver.OracleDriver\";\n    }\n\n    @Test\n    public void test_druid() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(preparedStatementCache);\n        dataSource.setMaxOpenPreparedStatements(preparedStatementCacheSize);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setConnectionProperties(properties);\n        dataSource.setUseOracleImplicitCache(true);\n        dataSource.init();\n\n        // printAV_INFO(dataSource);\n        // printTables(dataSource);\n        // printWP_ORDERS(dataSource);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"druid\", threadCount);\n        }\n        System.out.println();\n    }\n\n    @Test\n    public void test_dbcp() throws Exception {\n        final BasicDataSource dataSource = new BasicDataSource();\n\n        dataSource.setMaxActive(maxActive);\n        dataSource.setMaxIdle(maxIdle);\n        dataSource.setMaxWait(maxWait);\n        dataSource.setPoolPreparedStatements(preparedStatementCache);\n        dataSource.setMaxOpenPreparedStatements(preparedStatementCacheSize);\n        dataSource.setDriverClassName(driverClass);\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setValidationQuery(validationQuery);\n        dataSource.setTestOnBorrow(testOnBorrow);\n        dataSource.setConnectionProperties(properties);\n\n//        printAV_INFO(dataSource);\n\n        for (int i = 0; i < loopCount; ++i) {\n            p0(dataSource, \"dbcp\", threadCount);\n        }\n        System.out.println();\n    }\n\n    private void printWP_ORDERS(DruidDataSource dataSource) throws SQLException {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(\"SELECT * FROM WP_ORDERS\");\n\n        JdbcUtils.printResultSet(rs);\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    private void printAV_INFO(DataSource dataSource) throws SQLException {\n        String sql = \"SELECT DISTINCT ID FROM AV_INFO WHERE ROWNUM <= 10\";\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(sql);\n\n        JdbcUtils.printResultSet(rs);\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    protected void printTables(DruidDataSource dataSource) throws SQLException {\n        Connection conn = dataSource.getConnection();\n\n        ResultSet rs = conn.getMetaData().getTables(null, \"ALIBABA\", null, new String[]{\"TABLE\"});\n        JdbcUtils.printResultSet(rs);\n        rs.close();\n\n        conn.close();\n    }\n\n    private void p0(final DataSource dataSource, String name, int threadCount) throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n\n                            int mod = i % 500;\n\n                            String sql = SQL; // + \" AND ROWNUM <= \" + (mod + 1);\n                            PreparedStatement stmt = conn.prepareStatement(sql);\n                            stmt.setInt(1, 61);\n                            ResultSet rs = stmt.executeQuery();\n                            int rowCount = 0;\n                            while (rs.next()) {\n                                rowCount++;\n                            }\n                            // Assert.isTrue(!rs.isClosed());\n                            rs.close();\n                            // Assert.isTrue(!stmt.isClosed());\n                            stmt.close();\n                            Assert.isTrue(stmt.isClosed());\n                            conn.close();\n                            Assert.isTrue(conn.isClosed());\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    }\n                    endLatch.countDown();\n                }\n            };\n            thread.start();\n        }\n        long startMillis = System.currentTimeMillis();\n        long startYGC = TestUtil.getYoungGC();\n        long startFullGC = TestUtil.getFullGC();\n        startLatch.countDown();\n        endLatch.await();\n\n        long millis = System.currentTimeMillis() - startMillis;\n        long ygc = TestUtil.getYoungGC() - startYGC;\n        long fullGC = TestUtil.getFullGC() - startFullGC;\n\n        System.out.println(\"thread \" + threadCount + \" \" + name + \" millis : \"\n                + NumberFormat.getInstance().format(millis) + \", YGC \" + ygc + \" FGC \" + fullGC);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/druid/DruidCase0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.pool.druid;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\npublic class DruidCase0 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setMaxActive(8);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(1000 * 60 * 5);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_benchmark() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        for (int i = 0; i < 5; ++i) {\n            long startMillis = System.currentTimeMillis();\n            benchmark();\n            long millis = System.currentTimeMillis() - startMillis;\n\n            System.out.println(\"millis : \" + millis);\n            // 1043\n        }\n    }\n\n    public void benchmark() throws Exception {\n        for (int i = 0; i < 1000 * 1000 * 10; ++i) {\n            Connection conn = dataSource.getConnection();\n//            Statement stmt = conn.createStatement();\n//            ResultSet rs = stmt.executeQuery(\"select 1\");\n//            rs.close();\n//            stmt.close();\n\n            PreparedStatement pstmt = conn.prepareStatement(\"select 1\");\n            ResultSet rs = pstmt.executeQuery();\n//            rs.next();\n//            rs.getInt(1);\n//            rs.getInt(1);\n            rs.close();\n            pstmt.close();\n            conn.close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/pool/model/TableOperator.java",
    "content": "package com.alibaba.druid.benckmark.pool.model;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\npublic class TableOperator {\n    private DataSource dataSource;\n\n    public void setDataSource(DataSource dataSource) {\n        this.dataSource = dataSource;\n    }\n\n    private static final int COUNT = 2;\n\n    public TableOperator() {\n    }\n\n    public void insert() throws Exception {\n        StringBuilder ddl = new StringBuilder();\n        ddl.append(\"INSERT INTO t_big (\");\n        for (int i = 0; i < COUNT; ++i) {\n            if (i != 0) {\n                ddl.append(\", \");\n            }\n            ddl.append(\"F\" + i);\n        }\n        ddl.append(\") VALUES (\");\n        for (int i = 0; i < COUNT; ++i) {\n            if (i != 0) {\n                ddl.append(\", \");\n            }\n            ddl.append(\"?\");\n        }\n        ddl.append(\")\");\n\n        Connection conn = dataSource.getConnection();\n\n        // System.out.println(ddl.toString());\n        try {\n            PreparedStatement stmt = conn.prepareStatement(ddl.toString());\n\n            for (int i = 0; i < COUNT; ++i) {\n                stmt.setInt(i + 1, i);\n            }\n\n            stmt.execute();\n            stmt.close();\n        } finally {\n            conn.close();\n        }\n    }\n\n    public void dropTable() throws SQLException {\n        Connection conn = dataSource.getConnection();\n        try {\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE t_big\");\n            stmt.close();\n        } finally {\n            conn.close();\n        }\n    }\n\n    public void createTable() throws SQLException {\n        StringBuilder ddl = new StringBuilder();\n        ddl.append(\"CREATE TABLE t_big (FID INT AUTO_INCREMENT PRIMARY KEY \");\n        for (int i = 0; i < COUNT; ++i) {\n            ddl.append(\", \");\n            ddl.append(\"F\" + i);\n            ddl.append(\" BIGINT NULL\");\n        }\n        ddl.append(\")\");\n\n        Connection conn = dataSource.getConnection();\n        try {\n            Statement stmt = conn.createStatement();\n            stmt.addBatch(\"DROP TABLE IF EXISTS t_big\");\n            stmt.addBatch(ddl.toString());\n            stmt.executeBatch();\n            stmt.close();\n        } finally {\n            conn.close();\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/BenchmarkCase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy;\n\npublic abstract class BenchmarkCase {\n    private final String name;\n\n    public BenchmarkCase(String name) {\n        super();\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setUp(SQLExecutor sqlExec) throws Exception {\n    }\n\n    public abstract void execute(SQLExecutor sqlExec) throws Exception;\n\n    public void tearDown(SQLExecutor sqlExec) throws Exception {\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/BenchmarkExecutor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy;\n\nimport javax.management.MBeanServer;\nimport javax.management.ObjectName;\n\nimport java.lang.management.ManagementFactory;\nimport java.text.NumberFormat;\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class BenchmarkExecutor {\n    private int loopCount = 1000;\n    private int executeCount = 10;\n\n    private final List<SQLExecutor> sqlExecList = new ArrayList<SQLExecutor>();\n    private final List<BenchmarkCase> caseList = new ArrayList<BenchmarkCase>();\n\n    public int getExecuteCount() {\n        return executeCount;\n    }\n\n    public void setExecuteCount(int executeCount) {\n        this.executeCount = executeCount;\n    }\n\n    public List<BenchmarkCase> getCaseList() {\n        return caseList;\n    }\n\n    public List<SQLExecutor> getSqlExecutors() {\n        return sqlExecList;\n    }\n\n    public int getLoopCount() {\n        return loopCount;\n    }\n\n    public void setLoopCount(int loopCount) {\n        this.loopCount = loopCount;\n    }\n\n    public void execute() {\n        for (BenchmarkCase benchmarkCase : caseList) {\n            Map<SQLExecutor, List<Result>> sumList = new LinkedHashMap<SQLExecutor, List<Result>>();\n            for (SQLExecutor sqlExec : sqlExecList) {\n                // 预先执行一次\n                {\n                    Result result = executeLoop(sqlExec, benchmarkCase);\n                    handleResult(sqlExec, result);\n                    System.out.println();\n                }\n\n                List<Result> resultList = new ArrayList<Result>();\n\n                for (int i = 0; i < executeCount; ++i) {\n                    Result result = executeLoop(sqlExec, benchmarkCase);\n                    resultList.add(result);\n                    handleResult(sqlExec, result);\n                }\n                System.out.println();\n                sumList.put(sqlExec, resultList);\n            }\n\n            for (Map.Entry<SQLExecutor, List<Result>> entry : sumList.entrySet()) {\n                handleResultSummary(entry.getKey(), benchmarkCase, entry.getValue());\n            }\n            System.out.println();\n\n        }\n    }\n\n    public void handleResultSummary(SQLExecutor sqlExec, BenchmarkCase benchmarkCase, List<Result> resultList) {\n        int millis = 0;\n        int youngGC = 0;\n        int fullGC = 0;\n        for (Result result : resultList) {\n            millis += result.getMillis();\n            youngGC += result.getYoungGC();\n            fullGC += result.getFullGC();\n        }\n\n        NumberFormat format = NumberFormat.getInstance();\n        System.out.println(\"SUM\\t\" + benchmarkCase.getName() + \"\\t\" + sqlExec.getName() + \"\\t\" + format.format(millis)\n                + \"\\tYoungGC \" + youngGC + \"\\tFullGC \" + fullGC);\n    }\n\n    public void handleResult(SQLExecutor sqlExec, Result result) {\n        if (result.getError() != null) {\n            result.getError().printStackTrace();\n            return;\n        }\n        NumberFormat format = NumberFormat.getInstance();\n        System.out.println(result.getName() + \"\\t\" + sqlExec.getName() + \"\\t\" + format.format(result.getMillis())\n                + \"\\tYoungGC \" + result.getYoungGC() + \"\\tFullGC \" + result.getFullGC());\n    }\n\n    private Result executeLoop(SQLExecutor sqlExec, BenchmarkCase benchmarkCase) {\n        try {\n            benchmarkCase.setUp(sqlExec);\n        } catch (Exception e) {\n            throw new RuntimeException(\"setup error\", e);\n        }\n\n        long startMillis = System.currentTimeMillis();\n        long startYoungGC = getYoungGC();\n        long startFullGC = getFullGC();\n\n        Throwable error = null;\n        try {\n            for (int i = 0; i < loopCount; ++i) {\n                benchmarkCase.execute(sqlExec);\n            }\n\n        } catch (Throwable e) {\n            error = e;\n        }\n        long time = System.currentTimeMillis() - startMillis;\n        long youngGC = getYoungGC() - startYoungGC;\n        long fullGC = getFullGC() - startFullGC;\n\n        Result result = new Result();\n        result.setName(benchmarkCase.getName());\n        result.setMillis(time);\n        result.setYoungGC(youngGC);\n        result.setFullGC(fullGC);\n        result.setError(error);\n\n        try {\n            benchmarkCase.tearDown(sqlExec);\n        } catch (Exception e) {\n            throw new RuntimeException(\"tearDown error\", e);\n        }\n\n        return result;\n    }\n\n    public long getYoungGC() {\n        try {\n            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n            ObjectName objectName;\n            if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=ParNew\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=ParNew\");\n            } else if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=Copy\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=Copy\");\n            } else {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=PS Scavenge\");\n            }\n\n            return (Long) mbeanServer.getAttribute(objectName, \"CollectionCount\");\n        } catch (Exception e) {\n            throw new RuntimeException(\"error\");\n        }\n    }\n\n    public long getFullGC() {\n        try {\n            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n            ObjectName objectName;\n\n            if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=ConcurrentMarkSweep\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=ConcurrentMarkSweep\");\n            } else if (mbeanServer.isRegistered(new ObjectName(\"java.lang:type=GarbageCollector,name=MarkSweepCompact\"))) {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=MarkSweepCompact\");\n            } else {\n                objectName = new ObjectName(\"java.lang:type=GarbageCollector,name=PS MarkSweep\");\n            }\n\n            return (Long) mbeanServer.getAttribute(objectName, \"CollectionCount\");\n        } catch (Exception e) {\n            throw new RuntimeException(\"error\");\n        }\n    }\n\n    public static class Result {\n        private String name;\n        private long millis;\n        private long youngGC;\n        private long fullGC;\n        private Throwable error;\n\n        public String getName() {\n            return name;\n        }\n\n        public void setName(String name) {\n            this.name = name;\n        }\n\n        public long getMillis() {\n            return millis;\n        }\n\n        public void setMillis(long millis) {\n            this.millis = millis;\n        }\n\n        public long getYoungGC() {\n            return youngGC;\n        }\n\n        public void setYoungGC(long youngGC) {\n            this.youngGC = youngGC;\n        }\n\n        public long getFullGC() {\n            return fullGC;\n        }\n\n        public void setFullGC(long fullGC) {\n            this.fullGC = fullGC;\n        }\n\n        public Throwable getError() {\n            return error;\n        }\n\n        public void setError(Throwable error) {\n            this.error = error;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/DirectSQLExecutor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\n\npublic class DirectSQLExecutor extends SQLExecutor {\n    private final String jdbcUrl;\n    private final String user;\n    private final String password;\n    private final String driverClassName;\n\n    public DirectSQLExecutor(String name, String jdbcUrl, String user, String password) {\n        super(name);\n\n        this.jdbcUrl = jdbcUrl;\n        this.user = user;\n        this.password = password;\n\n        try {\n            driverClassName = getDriverClassName(jdbcUrl);\n            Class.forName(driverClassName);\n        } catch (Exception ex) {\n            throw new IllegalStateException(ex.getMessage(), ex);\n        }\n    }\n\n    public String getDriverClassName(String url) throws SQLException {\n        if (url.startsWith(\"jdbc:derby:\")) {\n            return \"org.apache.derby.jdbc.EmbeddedDriver\";\n        } else if (url.startsWith(\"jdbc:mysql:\")) {\n            return \"com.mysql.jdbc.Driver\";\n        } else if (url.startsWith(\"jdbc:oracle:\")) {\n            return \"oracle.jdbc.driver.OracleDriver\";\n        } else if (url.startsWith(\"jdbc:microsoft:\")) {\n            return \"com.microsoft.jdbc.sqlserver.SQLServerDriver\";\n        } else if (url.startsWith(\"jdbc:jtds:\")) {\n            return \"net.sourceforge.jtds.jdbc.Driver\";\n        } else if (url.startsWith(\"jdbc:fake:\")) {\n            return \"com.alibaba.druid.mock.MockDriver\";\n        } else if (url.startsWith(\"jdbc:wrap-jdbc:\")) {\n            return \"com.alibaba.druid.proxy.DruidDriver\";\n        } else {\n            throw new SQLException(\"unkow jdbc driver\");\n        }\n    }\n\n    @Override\n    public Connection getConnection() throws SQLException {\n        return DriverManager.getConnection(jdbcUrl, user, password);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/DruidBenchmarkTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy;\n\nimport com.alibaba.druid.benckmark.proxy.sqlcase.SelectNow;\nimport org.junit.jupiter.api.Test;\n\npublic class DruidBenchmarkTest {\n    @Test\n    public void test_druid_benchmark() throws Exception {\n        BenchmarkExecutor executor = new BenchmarkExecutor();\n        executor.getSqlExecutors().add(createExecutorDirect());\n        executor.getSqlExecutors().add(createExecutorDruid());\n\n        executor.setExecuteCount(10);\n        executor.setLoopCount(1000 * 100);\n        executor.getCaseList().add(new SelectNow());\n        // executor.getCaseList().add(new SelectSysUser());\n        // executor.getCaseList().add(new Select1());\n        // executor.getCaseList().add(new SelectEmptyTable());\n\n        executor.execute();\n    }\n\n    public DirectSQLExecutor createExecutorDirect() {\n        String name = \"direct\";\n        String jdbcUrl = \"jdbc:mysql://a.b.c.d/dragoon_v25masterdb?useUnicode=true&characterEncoding=UTF-8\";\n        String user = \"dragoon25\";\n        String password = \"dragoon25\";\n        return new DirectSQLExecutor(name, jdbcUrl, user, password);\n    }\n\n    public DirectSQLExecutor createExecutorDruid() {\n        String name = \"druid\";\n        String jdbcUrl = \"jdbc:wrap-jdbc:filters=default:name=benchmark:jdbc:mysql://a.b.c.d/dragoon_v25masterdb?useUnicode=true&characterEncoding=UTF-8\";\n        String user = \"dragoon25\";\n        String password = \"dragoon25\";\n        return new DirectSQLExecutor(name, jdbcUrl, user, password);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/SQLExecutor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\npublic abstract class SQLExecutor {\n    private final String name;\n\n    public SQLExecutor(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public abstract Connection getConnection() throws SQLException;\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/TestAtomicPerformance.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class TestAtomicPerformance {\n    @Test\n    public void test_0() throws Exception {\n        AtomicInteger count = new AtomicInteger();\n        for (int i = 0; i < 5; ++i) {\n            perf(count);\n        }\n        System.out.println();\n        for (int i = 0; i < 5; ++i) {\n            perf2(count);\n        }\n    }\n\n    private void perf(AtomicInteger count) {\n        long startMillis = System.currentTimeMillis();\n\n        count.set(0);\n        for (int i = 0; i < 1000 * 1000 * 100; ++i) {\n            int value = count.get();\n            count.compareAndSet(value, value + 1);\n        }\n\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis \" + millis);\n    }\n\n    private void perf2(AtomicInteger count) {\n        long startMillis = System.currentTimeMillis();\n\n        count.set(0);\n        for (int i = 0; i < 1000 * 1000 * 100; ++i) {\n            int value = count.get();\n            count.weakCompareAndSet(value, value + 1);\n        }\n\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"weak millis \" + millis);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/sqlcase/Select1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy.sqlcase;\n\nimport com.alibaba.druid.benckmark.proxy.BenchmarkCase;\nimport com.alibaba.druid.benckmark.proxy.SQLExecutor;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Select1 extends BenchmarkCase {\n    private String sql;\n    private Connection conn;\n\n    public Select1() {\n        super(\"Select1\");\n\n        sql = \"SELECT 1\";\n    }\n\n    @Override\n    public void setUp(SQLExecutor sqlExec) throws Exception {\n        conn = sqlExec.getConnection();\n    }\n\n    @Override\n    public void execute(SQLExecutor sqlExec) throws Exception {\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(sql);\n        int rowCount = 0;\n        int value = 0;\n        while (rs.next()) {\n            value = rs.getInt(1);\n            rowCount++;\n        }\n        assertEquals(1, value);\n        assertEquals(1, rowCount);\n        rs.close();\n        stmt.close();\n    }\n\n    @Override\n    public void tearDown(SQLExecutor sqlExec) throws Exception {\n        conn.close();\n        conn = null;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/sqlcase/SelectEmptyTable.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy.sqlcase;\n\nimport com.alibaba.druid.benckmark.proxy.BenchmarkCase;\nimport com.alibaba.druid.benckmark.proxy.SQLExecutor;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SelectEmptyTable extends BenchmarkCase {\n    private String sql;\n    private Connection conn;\n    private String tableName;\n\n    private String createTableSql;\n    private String dropTableSql;\n\n    public SelectEmptyTable() {\n        super(\"SelectEmptyTable\");\n\n        tableName = \"T_\" + System.currentTimeMillis();\n\n        createTableSql = \"CREATE TABLE \" + tableName\n                + \"(F1 INT, F2 INT, F3 INT, F4 INT, F5 INT, F6 INT, F7 INT, F8 INT, F9 INT)\";\n        dropTableSql = \"DROP TABLE \" + tableName;\n        sql = \"SELECT * FROM T_\" + tableName;\n    }\n\n    @Override\n    public void setUp(SQLExecutor sqlExec) throws Exception {\n        conn = sqlExec.getConnection();\n\n        Statement stmt = null;\n        try {\n            stmt = conn.createStatement();\n            stmt.execute(createTableSql);\n        } finally {\n            JdbcUtils.close(stmt);\n        }\n    }\n\n    @Override\n    public void execute(SQLExecutor sqlExec) throws Exception {\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(sql);\n        int rowCount = 0;\n        int value = 0;\n        while (rs.next()) {\n            value = rs.getInt(1);\n            rowCount++;\n        }\n        assertEquals(1, value);\n        assertEquals(1, rowCount);\n        rs.close();\n        stmt.close();\n    }\n\n    @Override\n    public void tearDown(SQLExecutor sqlExec) throws Exception {\n        Statement stmt = null;\n        try {\n            stmt = conn.createStatement();\n            stmt.execute(dropTableSql);\n        } finally {\n            JdbcUtils.close(stmt);\n        }\n\n        conn.close();\n        conn = null;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/sqlcase/SelectNow.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy.sqlcase;\n\nimport com.alibaba.druid.benckmark.proxy.BenchmarkCase;\nimport com.alibaba.druid.benckmark.proxy.SQLExecutor;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SelectNow extends BenchmarkCase {\n    private String sql;\n    private Connection conn;\n\n    public SelectNow() {\n        super(\"SelectNow\");\n\n        sql = \"SELECT NOW()\";\n    }\n\n    @Override\n    public void setUp(SQLExecutor sqlExec) throws Exception {\n        conn = sqlExec.getConnection();\n    }\n\n    @Override\n    public void execute(SQLExecutor sqlExec) throws Exception {\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(sql);\n        int rowCount = 0;\n        Date now = null;\n        while (rs.next()) {\n            now = rs.getTimestamp(1);\n            rowCount++;\n        }\n        assertNotNull(now);\n        assertEquals(1, rowCount);\n        rs.close();\n        stmt.close();\n    }\n\n    @Override\n    public void tearDown(SQLExecutor sqlExec) throws Exception {\n        conn.close();\n        conn = null;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/proxy/sqlcase/SelectSysUser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.proxy.sqlcase;\n\nimport com.alibaba.druid.benckmark.proxy.BenchmarkCase;\nimport com.alibaba.druid.benckmark.proxy.SQLExecutor;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SelectSysUser extends BenchmarkCase {\n    private String sql;\n    private Connection conn;\n\n    public SelectSysUser() {\n        super(\"Dragoon-SelectSysUser\");\n\n        sql = \"SELECT * FROM sys_user s\";\n    }\n\n    @Override\n    public void setUp(SQLExecutor sqlExec) throws Exception {\n        conn = sqlExec.getConnection();\n    }\n\n    @Override\n    public void execute(SQLExecutor sqlExec) throws Exception {\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(sql);\n        int rowCount = 0;\n        int value = 0;\n        while (rs.next()) {\n            value = rs.getInt(1);\n            rowCount++;\n        }\n        assertEquals(1, value);\n        assertEquals(1, rowCount);\n        rs.close();\n        stmt.close();\n    }\n\n    @Override\n    public void tearDown(SQLExecutor sqlExec) throws Exception {\n        conn.close();\n        conn = null;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/MySqlInsertBenchmark.java",
    "content": "package com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class MySqlInsertBenchmark {\n    static String sql = \"INSERT INTO test_table VALUES (1, '1', '2017-10-10', true, false, '2017-10-10 10:10:10', '10:10:10', 1.111, null);\";\n    List<SQLStatement> stmtList;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n    }\n\n    @Test\n    public void test_perf() throws Exception {\n        for (int i = 0; i < 5; ++i) {\n            perf();\n//            perf_toString(); // 425\n        }\n    }\n\n    public void perf_toString() {\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            SQLUtils.toMySqlString(stmtList.get(0));\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n    }\n\n    public void perf() {\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            List<SQLStatement> stmt = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n//            stmt.toString();\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/MySqlInsertBenchmark_2.java",
    "content": "package com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class MySqlInsertBenchmark_2 {\n    static String sql = \"INSERT INTO test_table VALUES (1, '1', '2017-10-10', true, false, '2017-10-10 10:10:10', '10:10:10', 1.111, NULL), (2, '2', '2017-10-10', true, false, '2017-10-10 10:10:10', '10:10:10', 2.222, NULL)\" +\n            \", (2, '2', '2017-09-09', true, false, '2017-10-10 10:10:10', '10:10:10', 3.333, NULL)\" +\n            \", (3, '3', '2017-10-10', true, false, '2017-10-10 10:10:10', '11:11:11', 4.333, NULL)\" +\n            \", (4, '4', '2017-10-10', true, false, '2017-10-10 10:10:10', '11:11:11', 4.333, NULL)\" +\n            \", (5, '5', '2017-10-10', true, false, '2017-10-10 10:10:10', '11:11:11', 4.333, NULL);\";\n    List<SQLStatement> stmtList;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL);\n        parser.config(SQLParserFeature.KeepInsertValueClauseOriginalString, true);\n        stmtList = parser.parseStatementList();\n    }\n\n    @Test\n    public void test_perf() throws Exception {\n        System.out.println(sql);\n        for (int i = 0; i < 5; ++i) {\n//            perf(); // 5043\n            perf_toString(); // 2101\n//            perf_toString_featured(); // 7493\n        }\n    }\n\n    public void perf() {\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            List<SQLStatement> stmt = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n//            stmt.toString();\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n    }\n\n    public void perf_keepInsertValueClauseStrinng() {\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL);\n            parser.config(SQLParserFeature.KeepInsertValueClauseOriginalString, true);\n            List<SQLStatement> stmtList = parser.parseStatementList();\n//            stmt.toString();\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n    }\n\n    public void perf_toString() {\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            SQLUtils.toMySqlString(stmtList.get(0));\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n    }\n\n    public void perf_toString_featured() {\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000 * 10; ++i) {\n            SQLUtils.toMySqlString(stmtList.get(0), VisitorFeature.OutputUseInsertValueClauseOriginalString);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n        System.out.println(\"millis : \" + millis);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.test.TestUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport java.lang.management.ManagementFactory;\nimport java.util.List;\n\npublic class MySqlPerfMain {\n    public static void main(String[] args) throws Exception {\n        System.out.println(System.getProperty(\"java.vm.name\") + \" \" + System.getProperty(\"java.runtime.version\"));\n        List<String> arguments = ManagementFactory.getRuntimeMXBean().getInputArguments();\n        System.out.println(arguments);\n\n        String sql = Utils.readFromResource(\"benchmark/sql/ob_sql.txt\");\n\n        for (int i = 0; i < 10; ++i) {\n            perfMySql(sql);\n        }\n    }\n\n    static long perfMySql(String sql) {\n        long startYGC = TestUtils.getYoungGC();\n        long startYGCTime = TestUtils.getYoungGCTime();\n        long startFGC = TestUtils.getFullGC();\n\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1; ++i) {\n            execMySql(sql);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n\n        long ygc = TestUtils.getYoungGC() - startYGC;\n        long ygct = TestUtils.getYoungGCTime() - startYGCTime;\n        long fgc = TestUtils.getFullGC() - startFGC;\n\n        System.out.println(\"MySql\\t\" + millis + \", ygc \" + ygc + \", ygct \" + ygct + \", fgc \" + fgc);\n        return millis;\n    }\n\n    static String execMySql(String sql) {\n        StringBuilder out = new StringBuilder();\n        MySqlOutputVisitor visitor = new MySqlOutputVisitor(out);\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        // for (SQLStatement statement : statementList) {\n        // statement.accept(visitor);\n        // visitor.println();\n        // }\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_schemaStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.test.TestUtils;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.lang.management.ManagementFactory;\nimport java.util.List;\n\npublic class MySqlPerfMain_schemaStat {\n    public static void main(String[] args) throws Exception {\n        System.out.println(System.getProperty(\"java.vm.name\") + \" \" + System.getProperty(\"java.runtime.version\"));\n        List<String> arguments = ManagementFactory.getRuntimeMXBean().getInputArguments();\n        System.out.println(arguments);\n\n        String sql = \"select * from t \";\n        for (int i = 0; i < 300; ++i) {\n            if (i == 0) {\n                sql += \" WHERE \";\n            } else {\n                sql += \" OR \";\n            }\n            sql += (\" id = \" + i);\n        }\n\n        for (int i = 0; i < 10; ++i) {\n            perfMySql(sql);\n        }\n    }\n\n    static long perfMySql(String sql) {\n        long startYGC = TestUtils.getYoungGC();\n        long startYGCTime = TestUtils.getYoungGCTime();\n        long startFGC = TestUtils.getFullGC();\n\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 100 * 1; ++i) {\n            execMySql(sql);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n\n        long ygc = TestUtils.getYoungGC() - startYGC;\n        long ygct = TestUtils.getYoungGCTime() - startYGCTime;\n        long fgc = TestUtils.getFullGC() - startFGC;\n\n        System.out.println(\"MySql\\t\" + millis + \", ygc \" + ygc + \", ygct \" + ygct + \", fgc \" + fgc);\n        return millis;\n    }\n\n    static String execMySql(String sql) {\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n\n        for (SQLStatement stmt : statementList) {\n            stmt.accept(statVisitor);\n        }\n        // for (SQLStatement statement : statementList) {\n        // statement.accept(visitor);\n        // visitor.println();\n        // }\n        return \"\";\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.test.TestUtils;\n\nimport java.lang.management.ManagementFactory;\nimport java.util.List;\n\npublic class MySqlPerfMain_select {\n    public static void main(String[] args) throws Exception {\n        System.out.println(System.getProperty(\"java.vm.name\") + \" \" + System.getProperty(\"java.runtime.version\"));\n        List<String> arguments = ManagementFactory.getRuntimeMXBean().getInputArguments();\n        System.out.println(arguments);\n\n        String sql = \"SELECT ID, NAME, AGE FROM USER WHERE ID = ?\";\n//        String sql = \"SELECT student_name, \"\n//                + \"GROUP_CONCAT(DISTINCT test_score \"\n//                + \"    ORDER BY test_score DESC SEPARATOR ' ') \"\n//                + \"FROM student \"\n//                + \"GROUP BY student_name\";\n\n        for (int i = 0; i < 10; ++i) {\n            perfMySql(sql); // 831 810\n        }\n    }\n\n    static long perfMySql(String sql) {\n        long startYGC = TestUtils.getYoungGC();\n        long startYGCTime = TestUtils.getYoungGCTime();\n        long startFGC = TestUtils.getFullGC();\n\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            execMySql(sql);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n\n        long ygc = TestUtils.getYoungGC() - startYGC;\n        long ygct = TestUtils.getYoungGCTime() - startYGCTime;\n        long fgc = TestUtils.getFullGC() - startFGC;\n\n        System.out.println(\"MySql\\t\" + millis + \", ygc \" + ygc + \", ygct \" + ygct + \", fgc \" + fgc);\n        return millis;\n    }\n\n    static void execMySql(String sql) {\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n\n        // StringBuilder out = new StringBuilder();\n        // MySqlOutputVisitor visitor = new MySqlOutputVisitor(out);\n//        MySqlASTVisitorAdapter visitor = new MySqlASTVisitorAdapter();\n//\n//        for (SQLStatement statement : statementList) {\n//            statement.accept(visitor);\n//        }\n        // out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_visitor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.test.TestUtils;\n\nimport java.lang.management.ManagementFactory;\nimport java.util.List;\n\npublic class MySqlPerfMain_visitor {\n    public static void main(String[] args) throws Exception {\n        System.out.println(System.getProperty(\"java.vm.name\") + \" \" + System.getProperty(\"java.runtime.version\"));\n        List<String> arguments = ManagementFactory.getRuntimeMXBean().getInputArguments();\n        System.out.println(arguments);\n\n        String sql = \"SELECT ID, NAME, AGE FROM USER WHERE ID = ?\";\n\n        for (int i = 0; i < 5; ++i) {\n            perfMySql(sql);\n        }\n    }\n\n    static long perfMySql(String sql) {\n        long startYGC = TestUtils.getYoungGC();\n        long startYGCTime = TestUtils.getYoungGCTime();\n        long startFGC = TestUtils.getFullGC();\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000 * 1; ++i) {\n            execMySql(statementList);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n\n        long ygc = TestUtils.getYoungGC() - startYGC;\n        long ygct = TestUtils.getYoungGCTime() - startYGCTime;\n        long fgc = TestUtils.getFullGC() - startFGC;\n\n        System.out.println(\"MySql\\t\" + millis + \", ygc \" + ygc + \", ygct \" + ygct + \", fgc \" + fgc);\n        return millis;\n    }\n\n    static void execMySql(List<SQLStatement> statementList) {\n        MySqlASTVisitor visitor = new MySqlSchemaStatVisitor();\n\n        for (SQLStatement statement : statementList) {\n            statement.accept(visitor);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.test.TestUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class MySqlPerfTest {\n    private String sql;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        sql = \"SELECT * FROM T\";\n        sql = \"SELECT ID, NAME, AGE FROM USER WHERE ID = ?\";\n\n//        sql = Utils.readFromResource(\"benchmark/sql/ob_sql.txt\");\n    }\n\n    @Test\n    public void test_pert() throws Exception {\n        for (int i = 0; i < 10; ++i) {\n            perfMySql(sql);\n        }\n    }\n\n    long perfMySql(String sql) {\n        long startYGC = TestUtils.getYoungGC();\n        long startYGCTime = TestUtils.getYoungGCTime();\n        long startFGC = TestUtils.getFullGC();\n\n        long startMillis = System.currentTimeMillis();\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            execMySql(sql);\n        }\n        long millis = System.currentTimeMillis() - startMillis;\n\n        long ygc = TestUtils.getYoungGC() - startYGC;\n        long ygct = TestUtils.getYoungGCTime() - startYGCTime;\n        long fgc = TestUtils.getFullGC() - startFGC;\n\n        System.out.println(\"MySql\\t\" + millis + \", ygc \" + ygc + \", ygct \" + ygct + \", fgc \" + fgc);\n        return millis;\n    }\n\n    private String execMySql(String sql) {\n        StringBuilder out = new StringBuilder();\n        MySqlOutputVisitor visitor = new MySqlOutputVisitor(out);\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        // for (SQLStatement statement : statementList) {\n        // statement.accept(visitor);\n        // visitor.println();\n        // }\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java",
    "content": "package com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.fastjson2.JSON;\nimport com.alibaba.fastjson2.JSONWriter;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Created by kaiwang.ckw on 15/05/2017.\n */\npublic class SqlHolder {\n    private String text;\n    private DbType dialect;\n\n    private boolean parsed;\n    public SQLStatement ast;\n\n    private boolean isParam;\n\n    public static SQLSelectListCache selectListCache = new SQLSelectListCache(JdbcConstants.MYSQL);\n\n    static {\n        selectListCache.add(\"select id as id,    gmt_create as gmtCreate,    gmt_modified as gmtModified,    name as name,    owner as owner,    type as type,    statement as statement,    datasource as datasource,    meta as meta,    param_file as paramFile,    sharable as sharable,    data_type as dataType,    status as status,    config as config,    project_id as projectId,    plugins as plugins,    field_compare as fieldCompare,    field_ext as fieldExt,    openx as openx   from\");\n        selectListCache.add(\"SELECT id, dispute_id, buyer_id, seller_id, total_fee, refund_fee, max_apply_goods_fee, apply_goods_fee, apply_carriage_fee, refund_goods_fee, refund_carriage_fee, refund_point, refund_coupon, refund_return_point, refund_cash, real_deduct_refund_point, real_refund_return_point, refund_return_commission, gmt_create, gmt_modified, attributes, attributes_cc FROM\");\n//        selectListCache.add(\"select `auction_relation`.`id`,`auction_relation`.`item_id`,`auction_relation`.`sku_id`,`auction_relation`.`user_id`,`auction_relation`.`target_id`,`auction_relation`.`extra_id`,`auction_relation`.`type`,`auction_relation`.`target_type`,`auction_relation`.`type_attr`,`auction_relation`.`status`,`auction_relation`.`target_user_id`,`auction_relation`.`options`,`auction_relation`.`features`,`auction_relation`.`version`,`auction_relation`.`sub_type`,`auction_relation`.`gmt_create`,`auction_relation`.`gmt_modified` from\");\n//        selectListCache.add(\"SELECT biz_order_id, value_type, key_value, gmt_create, gmt_modified\\n\" +\n//                \"\\t, attribute_cc, buyer_id\\n\" +\n//                \"FROM\");\n//        selectListCache.add(\"SELECT biz_order_id, value_type, key_value, gmt_create, gmt_modified\\n\" +\n//                \"\\t, attribute_cc, buyer_id\\n\" +\n//                \"FROM\");\n//        selectListCache.add(\"SELECT sub_logistics_order_id, consign_time, attribute_cc, attributes, out_logistics_id\\n\" +\n//                \"\\t, parent_id, gmt_create, gmt_modified, detail_order_id, is_last\\n\" +\n//                \"\\t, ship_amount, buyer_id, seller_id, ship_status, step_order_id\\n\" +\n//                \"FROM\");\n        selectListCache.add(\"SELECT biz_order_id, out_order_id, seller_nick, buyer_nick, seller_id\\n\" +\n                \"\\t, buyer_id, auction_id, auction_title, auction_price, buy_amount\\n\" +\n                \"\\t, biz_type, sub_biz_type, fail_reason, pay_status, logistics_status\\n\" +\n                \"\\t, out_trade_status, snap_path, gmt_create, status\\n\" +\n                \"\\t, ifnull(buyer_rate_status, 4) AS buyer_rate_status\\n\" +\n                \"\\t, ifnull(seller_rate_status, 4) AS seller_rate_status, auction_pict_url\\n\" +\n                \"\\t, seller_memo, buyer_memo, seller_flag, buyer_flag, buyer_message_path\\n\" +\n                \"\\t, refund_status, attributes, attributes_cc, gmt_modified, ip\\n\" +\n                \"\\t, end_time, pay_time, is_main, is_detail, point_rate\\n\" +\n                \"\\t, parent_id, adjust_fee, discount_fee, refund_fee, confirm_paid_fee\\n\" +\n                \"\\t, cod_status, trade_tag, shop_id, sync_version, options\\n\" +\n                \"\\t, ignore_sold_quantity, from_group, attribute1, attribute2, attribute3\\n\" +\n                \"\\t, attribute4, attribute11\\n\" +\n                \"FROM\");\n        selectListCache.add(\"select `member_cart`.`CART_ID`,`member_cart`.`SKU_ID`,`member_cart`.`ITEM_ID`,`member_cart`.`QUANTITY`,`member_cart`.`USER_ID`,`member_cart`.`SELLER_ID`,`member_cart`.`STATUS`,`member_cart`.`EXT_STATUS`,`member_cart`.`TYPE`,`member_cart`.`SUB_TYPE`,`member_cart`.`GMT_CREATE`,`member_cart`.`GMT_MODIFIED`,`member_cart`.`ATTRIBUTE`,`member_cart`.`ATTRIBUTE_CC`,`member_cart`.`EX2` from\");\n    }\n\n    public static SqlHolder of(String sql) {\n        return new SqlHolder(sql);\n    }\n\n    SqlHolder(String text) {\n        this(text, DbType.mysql);\n    }\n\n    public SqlHolder(String text, DbType dbType, boolean isParam) {\n        this(text, dbType);\n        this.isParam = isParam;\n    }\n\n    SqlHolder(String text, DbType dbType) {\n        if (dbType != DbType.mysql) {\n            throw new IllegalArgumentException(\"only mysql is\");\n        }\n\n        this.text = text;\n        this.dialect = dbType;\n    }\n\n    public String format() {\n        try {\n            return SQLUtils.format(text, dialect);\n        } catch (ParserException e) {\n            throw new UnsupportedOperationException(e);\n        }\n    }\n\n    public void ensureParsed() {\n        if (parsed) {\n            return;\n        }\n\n//        if (text.equals(\"select @@session.tx_read_only\")) {\n//            SQLSelect select = new SQLSelect();\n//            MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock();\n//            queryBlock.addSelectItem(new SQLPropertyExpr(new SQLVariantRefExpr(\"@@session\"), \"tx_read_only\"));\n//            select.setQuery(queryBlock);\n//\n//            ast = new SQLSelectStatement(select);\n//            parsed = true;\n//            return;\n//        }\n\n        // ast = SQLUtils.parseStatements(text, dialect).get(0);\n        SQLParserFeature[] features;\n\n        if (isParam) {\n            features = new SQLParserFeature[]{SQLParserFeature.EnableSQLBinaryOpExprGroup, SQLParserFeature.OptimizedForParameterized};\n        } else {\n            features = new SQLParserFeature[]{SQLParserFeature.EnableSQLBinaryOpExprGroup,\n                    SQLParserFeature.OptimizedForParameterized,\n                    SQLParserFeature.UseInsertColumnsCache\n            };\n        }\n\n        try {\n            MySqlStatementParser parser = new MySqlStatementParser(text, features);\n            parser.setSelectListCache(selectListCache);\n            ast = parser.parseStatement();\n        } catch (ParserException e) {\n            throw new UnsupportedOperationException(e);\n        }\n        parsed = true;\n    }\n\n    // returns rewritten sql, or original string object if not rewritten\n    public String select() {\n        ensureParsed();\n\n        SQLStatement stmt = ast;\n        if (stmt instanceof SQLSelectStatement) {\n            boolean rewritten = StatementConverter.rewriteSelect((SQLSelectStatement) stmt);\n            if (rewritten) {\n                return SQLUtils.toMySqlString(stmt);\n            } else {\n                return text;\n            }\n        } else {\n            SQLSelectStatement selectStatement = StatementConverter.rewrite(stmt);\n            if (stmt == selectStatement) {\n                return text;\n            } else {\n                return SQLUtils.toMySqlString(selectStatement);\n            }\n        }\n    }\n\n    public String parameterize() {\n        return parameterize(null, null);\n    }\n\n    public String parameterize(Set<String> physicalNames) {\n        ensureParsed();\n        return Templates.parameterize(ast, physicalNames, null);\n    }\n\n    public String parameterize(Set<String> physicalNames, List<Object> params) {\n        ensureParsed();\n\n//        if (text.equals(\"select @@session.tx_read_only\")) {\n//            return text;\n//        }\n\n        return Templates.parameterize(ast, physicalNames, params);\n    }\n\n    public String getParams() {\n        ensureParsed();\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, JdbcConstants.MYSQL);\n        List<Object> parameters = new ArrayList<Object>();\n        visitor.setParameterized(true);\n        visitor.setParameterizedMergeInList(true);\n        visitor.setParameters(parameters);\n        ast.accept(visitor);\n        String params = JSON.toJSONString(parameters, JSONWriter.Feature.WriteClassName);\n        params = StringUtils.replace(params, \"\\\"\", \"\\\\\\\"\");\n        return params;\n    }\n\n    public String getSqlItems(String db) {\n        Map<String, LinkedHashSet<String>> itemMap = new HashMap<String, LinkedHashSet<String>>();\n        try {\n            SchemaStatVisitor schemaStatVisitor = new MySqlSchemaStatVisitor();\n            ast.accept(schemaStatVisitor);\n            List<TableStat.Condition> conditionList = schemaStatVisitor.getConditions();\n            for (TableStat.Condition condition : conditionList) {\n                String tableName = condition.getColumn().getTable();\n                LinkedHashSet<String> condLinkedSet = itemMap.get(tableName);\n                if (condLinkedSet == null) {\n                    condLinkedSet = new LinkedHashSet<String>();\n                    itemMap.put(tableName, condLinkedSet);\n                }\n                TableStat.Column column = condition.getColumn();\n                String upperClnName = column.toString().toUpperCase();\n                String finalClnName = filterChar(db, upperClnName);\n                condLinkedSet.add(finalClnName);\n            }\n        } catch (Exception ex) {\n        }\n        if (itemMap.isEmpty()) {\n            return null;\n        }\n        StringBuilder resSb = new StringBuilder();\n        for (Map.Entry<String, LinkedHashSet<String>> entry : itemMap.entrySet()) {\n            resSb.append(StringUtils.join(entry.getValue(), \",\")).append(\",\");\n        }\n        return resSb.substring(0, resSb.length() - 1);\n    }\n\n    public static String filterChar(String db, String name) {\n        String resName;\n        if (StringUtils.isNotBlank(name)) {\n            String[] names = name.split(\"\\\\.\");\n            StringBuilder nameSb = new StringBuilder();\n            boolean isFirst = true;\n            int size = names.length;\n            int k = 0;\n            for (String n : names) {\n                String tempN = n;\n                if (n.startsWith(\"`\") && n.endsWith(\"`\")) {\n                    tempN = n.substring(1, n.length() - 1);\n                }\n                if (k == size - 1) {\n                    nameSb.append(tempN).append(\".\");\n                } else if (isFirst) {\n                    if (!n.startsWith(db)) {\n                        nameSb.append(convert(tempN)).append(\".\");\n                    }\n                    isFirst = false;\n                } else {\n                    nameSb.append(convert(tempN)).append(\".\");\n                }\n                k++;\n            }\n            resName = nameSb.substring(0, nameSb.length() - 1);\n        } else {\n            resName = name;\n        }\n        return db + \".\" + resName;\n    }\n\n    public static String convert(String tableName) {\n        if (StringUtils.isBlank(tableName)) {\n            return tableName;\n        }\n        int len = tableName.length();\n        int k = -1;\n        int min = Math.min(4, len);\n        for (int i = 1; i <= min; i++) {\n            String ch = String.valueOf(tableName.charAt(len - i));\n            boolean isNum = StringUtils.isNumeric(ch);\n            if (isNum) {\n                k = i;\n            } else {\n                break;\n            }\n        }\n\n        if (k != -1) {\n            tableName = tableName.substring(0, len - k);\n            if (tableName.endsWith(\"_\")) {\n                tableName = tableName.substring(0, tableName.length() - 1);\n            }\n        }\n        int idx = tableName.lastIndexOf(\"_\");\n        if (idx == -1 || (tableName.length() - 1 == idx)) {\n            return tableName;\n        }\n        String num = tableName.substring(idx + 1);\n        boolean isNum = StringUtils.isNumeric(num);\n        if (isNum) {\n            return tableName.substring(0, idx);\n        }\n        return tableName;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/StatementConverter.java",
    "content": "package com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\n\n/**\n * Created by kaiwang.ckw on 15/05/2017.\n */\npublic class StatementConverter {\n    // remove 'for update' from 'select ... for update'\n    public static boolean rewriteSelect(SQLSelectStatement stmt) {\n        SQLSelectQuery q = stmt.getSelect().getQuery();\n        if (q instanceof MySqlSelectQueryBlock) {\n            MySqlSelectQueryBlock qb = (MySqlSelectQueryBlock) q;\n            if (qb.isForUpdate()) {\n                qb.setForUpdate(false);\n                return true;\n            }\n        }\n        return false;\n    }\n\n    // construct a 'select' from other types of dml\n    public static SQLSelectStatement rewrite(SQLStatement stmt) {\n        SQLSelectStatement selectStmt;\n        if (stmt instanceof SQLSelectStatement) {\n            throw new RuntimeException(\"please use rewriteSelect which does ast modification instead of construction\");\n        } else if (stmt instanceof SQLUpdateStatement) {\n            SQLTableSource tableSource = ((SQLUpdateStatement) stmt).getTableSource();\n            SQLExpr where = ((SQLUpdateStatement) stmt).getWhere();\n            DbType dbType = ((SQLUpdateStatement) stmt).getDbType();\n            selectStmt = buildSelect(tableSource, where, dbType);\n        } else if (stmt instanceof SQLDeleteStatement) {\n            SQLTableSource tableSource = ((SQLDeleteStatement) stmt).getTableSource();\n            SQLExpr where = ((SQLDeleteStatement) stmt).getWhere();\n            DbType dbType = ((SQLDeleteStatement) stmt).getDbType();\n            selectStmt = buildSelect(tableSource, where, dbType);\n        } else if (stmt instanceof SQLInsertStatement) {\n            SQLSelect sqlSelect = ((SQLInsertStatement) stmt).getQuery();\n            if (sqlSelect != null) {\n                selectStmt = new SQLSelectStatement();\n                selectStmt.setSelect(sqlSelect);\n            } else {\n                throw new UnsupportedOperationException(\"only insert..select.. is supported\");\n            }\n        } else if (stmt instanceof SQLReplaceStatement) {\n            SQLQueryExpr sqlQueryExpr = ((SQLReplaceStatement) stmt).getQuery();\n            if (sqlQueryExpr != null) {\n                SQLSelect sqlSelect = ((SQLReplaceStatement) stmt).getQuery().getSubQuery();\n                selectStmt = new SQLSelectStatement();\n                selectStmt.setSelect(sqlSelect);\n            } else {\n                throw new UnsupportedOperationException(\"only replace..select.. is supported\");\n            }\n        } else {\n            throw new UnsupportedOperationException(\"only select/update/delete/insert/replace are supported\");\n        }\n        return selectStmt;\n    }\n\n    // build 'select * from ...'\n    static SQLSelectStatement buildSelect(SQLTableSource tableSource, SQLExpr where, DbType dbType) {\n        SQLSelectQueryBlock sqlSelectQuery = new SQLSelectQueryBlock();\n        sqlSelectQuery.addSelectItem(new SQLSelectItem(new SQLAllColumnExpr()));\n        sqlSelectQuery.setWhere(where);\n        sqlSelectQuery.setFrom(tableSource);\n        tableSource.setParent(sqlSelectQuery);\n\n        SQLSelect sqlSelect = new SQLSelect();\n        sqlSelect.setQuery(sqlSelectQuery);\n\n        SQLSelectStatement selectStmt = new SQLSelectStatement();\n        selectStmt.setSelect(sqlSelect);\n        selectStmt.setDbType(dbType);\n\n        return selectStmt;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/sql/Templates.java",
    "content": "package com.alibaba.druid.benckmark.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Created by kaiwang.ckw on 15/05/2017.\n */\npublic class Templates {\n    public static final String UNKNOWN = \"UNKNOWN\";\n\n    public static String parameterize(SQLStatement ast, Set<String> physicalNames, List<Object> params) {\n        List<Object> parameters = null;\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = new MySqlOutputVisitor(out);\n        visitor.setParameterized(true);\n        visitor.setParameterizedMergeInList(true);\n        if (physicalNames != null) {\n            visitor.setExportTables(true);\n        }\n        if (params != null) {\n            parameters = new ArrayList<Object>();\n            visitor.setParameters(parameters);\n        }\n        visitor.setPrettyFormat(false);\n        ast.accept(visitor);\n\n        if (physicalNames != null) {\n            Set<String> tableSet = visitor.getTables();\n            if (tableSet != null) {\n                physicalNames.addAll(tableSet);\n            }\n        }\n        if (params != null) {\n            if (!parameters.isEmpty()) {\n                params.addAll(parameters);\n            }\n        }\n\n        String sqlTemplate = out.toString();\n        return sqlTemplate;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/wall/WallBenchmarkTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.wall;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport org.junit.jupiter.api.Test;\n\npublic class WallBenchmarkTest {\n    WallProvider provider = new OracleWallProvider();\n\n    public static final int COUNT = 1000 * 1000;\n\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT t1.department_id, t2.*\\n\" +\n                \"FROM hr_info t1, TABLE(t1.people) t2\\n\" +\n                \"WHERE t2.department_id = t1.department_id;\";\n        for (int i = 0; i < 10; ++i) {\n            provider.clearCache();\n            long startMillis = System.currentTimeMillis();\n            perf(sql);\n            long millis = System.currentTimeMillis() - startMillis;\n            System.out.println(\"millis : \" + millis);\n        }\n    }\n\n    public void perf(String sql) {\n        for (int i = 0; i < COUNT; ++i) {\n            provider.check(sql);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/wall/WallBenchmarkTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.wall;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Random;\n\npublic class WallBenchmarkTest1 {\n    static Random r = new Random();\n    WallProvider provider = new MySqlWallProvider();\n\n    public static final int COUNT = 1000 * 1000;\n\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT t1.department_id, t2.*\\n\" +\n                \"FROM hr_info t1, x2 t2\\n\" +\n                \"WHERE t2.department_id = t1.department_id\";\n        for (int i = 0; i < 10; ++i) {\n            provider.clearCache();\n            long startMillis = System.currentTimeMillis();\n            perf(sql);\n            long millis = System.currentTimeMillis() - startMillis;\n            System.out.println(\"millis : \" + millis);\n        }\n    }\n\n    public void perf(String sql) {\n        for (int i = 0; i < COUNT; ++i) {\n            String text = genRandomSql();\n            provider.check(text);\n        }\n    }\n\n    private String genRandomSql() {\n        int result1 = r.nextInt(65535);\n        int result2 = r.nextInt(65535);\n        String result = Integer.toBinaryString(result1) + \"\" + Integer.toBinaryString(result2);\n        StringBuilder sb = new StringBuilder(\"select \");\n        for (int i = 0; i < result.length(); i++) {\n            if (result.charAt(i) == '1') {\n                String tempString = \"col\" + (i + 1) + \",\";\n                sb.append(tempString);\n            }\n        }\n        sb.delete(sb.length() - 1, sb.length());\n        sb.append(\" from sqlinject\");\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/wall/WallBenchmarkTest_mysql.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.wall;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\npublic class WallBenchmarkTest_mysql {\n    WallProvider provider = new MySqlWallProvider();\n\n    public static final int COUNT = 1000 * 1000;\n\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT t1.department_id, t2.*\\n\" +\n                \"FROM hr_info t1, x2 t2\\n\" +\n                \"WHERE t2.department_id = t1.department_id\";\n        for (int i = 0; i < 10; ++i) {\n            provider.clearCache();\n            long startMillis = System.currentTimeMillis();\n            perf(sql);\n            long millis = System.currentTimeMillis() - startMillis;\n            System.out.println(\"millis : \" + millis);\n        }\n    }\n\n    public void perf(String sql) {\n        for (int i = 0; i < COUNT; ++i) {\n            String text = sql + \" AND FID = \" + i;\n            provider.check(text);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/benckmark/wall/WallBenchmarkTest_mysql_concurrent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.benckmark.wall;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.CountDownLatch;\n\npublic class WallBenchmarkTest_mysql_concurrent {\n    WallProvider provider = new MySqlWallProvider();\n\n    public static final int COUNT = 1000 * 10;\n\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT t1.department_id, t2.*\\n\" +\n                \"FROM hr_info t1, x2 t2\\n\" +\n                \"WHERE t2.department_id = t1.department_id\";\n        for (int i = 0; i < 10; ++i) {\n            provider.clearCache();\n            long startMillis = System.currentTimeMillis();\n            perf(sql, 10);\n            long millis = System.currentTimeMillis() - startMillis;\n            System.out.println(\"millis : \" + millis);\n        }\n    }\n\n    public void perf(final String sql, int threadCount) {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch latch = new CountDownLatch(threadCount);\n        for (int i = 0; i < threadCount; ++i) {\n            final int seed = i * 1000 * 1000 * 100;\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.await();\n                        for (int i = 0; i < COUNT; ++i) {\n                            int id = seed + i;\n                            String text = sql + \" AND FID = \" + id;\n                            provider.check(text);\n                        }\n                    } catch (InterruptedException e) {\n                        e.printStackTrace();\n                    } finally {\n                        latch.countDown();\n                    }\n                }\n            };\n            thread.setName(\"perf-\" + i);\n            thread.start();\n        }\n\n        startLatch.countDown();\n\n        try {\n            latch.await();\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/AlipayUseCaseTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/**\n * AlipayUseCaseTest\n *\n * @author xiusiyan\n * @version 1.0, Mar 15, 2012\n * @see\n */\npublic class AlipayUseCaseTest {\n    /**\n     * @throws java.lang.Exception\n     */\n    @BeforeEach\n    public void setUp() throws Exception {\n    }\n\n    /**\n     * @throws java.lang.Exception\n     */\n    @AfterEach\n    public void tearDown() throws Exception {\n    }\n\n    @Test\n    public void test() {\n        // TODO\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/OrTest.java",
    "content": "package com.alibaba.druid.bvt;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class OrTest {\n    @Test\n    public void test_xx() throws Exception {\n        String sql = \"select * from t where not match('', '') or (c > 0 and d > 0)\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, (DbType) null);\n        SQLStatement stmt = stmtList.get(0);\n        System.out.println(stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/BugSqlParserIllegalWhere.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.fastjson2.JSON;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 此测试类用于检测试sql中where拼错导致SQL无效， 但经SQLStatementParser解析却丢失where的严复问题.\n *\n * @author qxo\n */\npublic class BugSqlParserIllegalWhere {\n    @Test\n    public void test4deleteWhere() throws Exception {\n        Object[][] samples = {\n                    {\"update test_tab1 set b= 1 swhere a=1\", false},\n                    {\"select * from test_tab1 swhere  a=1\", false},\n                    {\"delete from test_tab1 \\n swhere  a=1\", false},\n                    {\"delete from test_tab1 where a=1\", true},\n                    {\"delete from test_tab1 \\n where a=1     \\n\", true}\n                };\n\n        for (final Object[] arr : samples) {\n            String sql = (String) arr[0];\n            final boolean ok = Boolean.TRUE.equals(arr[1]);\n            try {\n                System.out.println(\"before sql:\" + sql);\n                final StringBuilder out = new StringBuilder();\n                final ExportParameterVisitor visitor = new OracleExportParameterVisitor(out);\n                visitor.setParameterizedMergeInList(true);\n                SQLStatementParser parser = new OracleStatementParser(sql);\n                final SQLStatement parseStatement = parser.parseStatement();\n                parseStatement.accept(visitor);\n                final List<Object> plist = visitor.getParameters();\n                sql = out.toString();\n                System.out.println(\"after sql:\" + sql);\n                System.out.println(\"params: \" + plist);\n                assertEquals(\"[1]\", JSON.toJSONString(plist));\n                assertTrue(Pattern.compile(\"(?i)(^|\\\\s+)where(\\\\s+|$)\").matcher(sql).find());\n                if (!ok) {\n                    fail();\n                }\n            } catch (ParserException ex) {\n                if (ok) {\n                    fail();\n                } else {\n                    ex.printStackTrace();\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_happyday517.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_happyday517 extends PoolTestCase {\n    private DruidDataSource dataSource;\n    private MockDriver driver;\n    private int originalDataSourceCount;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        originalDataSourceCount = DruidDataSourceStatManager.getInstance().getDataSourceList().size();\n\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat,trace,log4j,encoding\");\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        assertEquals(originalDataSourceCount, DruidDataSourceStatManager.getInstance().getDataSourceList().size());\n\n        super.tearDown();\n    }\n\n    public void test_for_happyday517_0() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);\n\n        MockStatement mockStmt = stmt.unwrap(MockStatement.class);\n\n        assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, mockStmt.getResultSetType());\n        assertEquals(ResultSet.CONCUR_UPDATABLE, mockStmt.getResultSetConcurrency());\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_for_happyday517_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE,\n                ResultSet.CLOSE_CURSORS_AT_COMMIT);\n\n        MockStatement mockStmt = stmt.unwrap(MockStatement.class);\n\n        assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, mockStmt.getResultSetType());\n        assertEquals(ResultSet.CONCUR_UPDATABLE, mockStmt.getResultSetConcurrency());\n        assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, mockStmt.getResultSetHoldability());\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_for_happyday517_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 1\";\n        Statement stmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);\n\n        MockPreparedStatement mockStmt = stmt.unwrap(MockPreparedStatement.class);\n\n        assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, mockStmt.getResultSetType());\n        assertEquals(ResultSet.CONCUR_UPDATABLE, mockStmt.getResultSetConcurrency());\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_for_happyday517_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 1\";\n        Statement stmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE,\n                ResultSet.CLOSE_CURSORS_AT_COMMIT);\n\n        MockPreparedStatement mockStmt = stmt.unwrap(MockPreparedStatement.class);\n\n        assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, mockStmt.getResultSetType());\n        assertEquals(ResultSet.CONCUR_UPDATABLE, mockStmt.getResultSetConcurrency());\n        assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, mockStmt.getResultSetHoldability());\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_for_happyday517_4() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 1\";\n        Statement stmt = conn.prepareCall(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);\n\n        Statement mockStmt = stmt.unwrap(Statement.class);\n\n        assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, mockStmt.getResultSetType());\n        assertEquals(ResultSet.CONCUR_UPDATABLE, mockStmt.getResultSetConcurrency());\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_for_happyday517_5() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 1\";\n        Statement stmt = conn.prepareCall(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE,\n                ResultSet.CLOSE_CURSORS_AT_COMMIT);\n\n        Statement mockStmt = stmt.unwrap(Statement.class);\n\n        assertEquals(ResultSet.TYPE_SCROLL_SENSITIVE, mockStmt.getResultSetType());\n        assertEquals(ResultSet.CONCUR_UPDATABLE, mockStmt.getResultSetConcurrency());\n        assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, mockStmt.getResultSetHoldability());\n\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_happyday517_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DataTruncation;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_happyday517_2 {\n    private DruidDataSource dataSource;\n    private MockDriver driver;\n\n    final DataTruncation exception = new java.sql.DataTruncation(0, true, true, 0, 0);\n\n    private int originalDataSourceCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        originalDataSourceCount = DruidDataSourceStatManager.getInstance().getDataSourceList().size();\n\n        final MockPreparedStatement mockStatement = new MockPreparedStatement(null, null) {\n            public boolean execute() throws SQLException {\n                throw exception;\n            }\n        };\n\n        driver = new MockDriver() {\n            public Connection connect(String url, Properties info) throws SQLException {\n                super.connect(url, info);\n                return new MockConnection(driver, url, info) {\n                    public PreparedStatement prepareStatement(String sql) throws SQLException {\n                        return mockStatement;\n                    }\n                };\n            }\n        };\n        dataSource = new DruidDataSource();\n        dataSource.setDriver(driver);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat,trace,log4j,encoding\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        assertEquals(originalDataSourceCount, DruidDataSourceStatManager.getInstance().getDataSourceList().size());\n    }\n\n    @Test\n    public void test_bug() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"insert into message.dbo.TempSMS(sms) values ('333')\");\n\n        Exception error = null;\n        try {\n            stmt.execute();\n        } catch (SQLException ex) {\n            error = ex;\n        }\n\n        assertTrue(exception == error);\n\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_happyday517_3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_happyday517_3 {\n    private DruidDataSource dataSource;\n    private MockDriver driver;\n\n    private int originalDataSourceCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        originalDataSourceCount = DruidDataSourceStatManager.getInstance().getDataSourceList().size();\n\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setDriver(driver);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat,trace,log4j,encoding\");\n        dataSource.setDefaultAutoCommit(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        assertEquals(originalDataSourceCount, DruidDataSourceStatManager.getInstance().getDataSourceList().size());\n    }\n\n    @Test\n    public void test_bug() throws Exception {\n        Connection conn = dataSource.getConnection();\n        assertEquals(false, conn.getAutoCommit());\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_order.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_order {\n    @Test\n    public void test_bug_for_xuershan() throws Exception {\n        String sql = \"select * from order\";\n        String format = SQLUtils.formatMySql(sql);\n        String expected = \"SELECT *\\nFROM order\";\n        assertEquals(expected, format);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_qianbi.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser;\nimport com.alibaba.druid.sql.dialect.odps.visitor.OdpsOutputVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_qianbi {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"insert into table lol select detail(sellerid,id) as count1,sum(sellerid) as sum1 from ctu_trade_paid_done.time('natural','1d','1h') \"\n                + \"where match(auctionTitle,\\\"男鞋\\\\n中石化&加油卡\\\\n中石化&充值卡\\\\n中石化&冲值卡\\\\n中石化&代冲\\\\n中石化&代充\\\\n中国石化&加油卡\\\\n中国石化&充值卡\\\\n中国石化&冲值卡\\\\n中国石化&代冲\\\\n中国石化&代充\\\",\\\"\\\\n\\\")\";\n\n        String expected = \"INSERT INTO TABLE lol\\n\" +\n                \"SELECT detail(sellerid, id) AS count1, sum(sellerid) AS sum1\\n\" +\n                \"FROM ctu_trade_paid_done:time('natural', '1d', '1h')\\n\" +\n                \"WHERE match(auctionTitle, '男鞋\\\\n中石化&加油卡\\\\n中石化&充值卡\\\\n中石化&冲值卡\\\\n中石化&代冲\\\\n中石化&代充\\\\n中国石化&加油卡\\\\n中国石化&充值卡\\\\n中国石化&冲值卡\\\\n中国石化&代冲\\\\n中国石化&代充', '\\\\n');\\n\";\n\n        StringBuilder out = new StringBuilder();\n        OdpsOutputVisitor visitor = new OdpsOutputVisitor(out);\n        OdpsStatementParser parser = new OdpsStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        for (SQLStatement statement : statementList) {\n            statement.accept(visitor);\n            visitor.print(\";\");\n            visitor.println();\n        }\n\n        // System.out.println(out.toString());\n\n        assertEquals(expected, out.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_ruiyi.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_ruiyi {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"insert into icshall_guide(id,gmt_create,gmt_modified,subject,content,cat_id)\"\n                + \"values (8,now(),now(),\\\"Why my payment is deducted incorrectly?/ Why my payment is deducted twice?\\\",\"\n                + \"\\\"{\\\\\\\"id\\\\\\\":1,\\\\\\\"title\\\\\\\":\\\\\\\"Have you contacted your card issuer to double check instead of only checking online?\\\\\\\",\"\n                + \"\\\\\\\"type\\\\\\\":\\\\\\\"START\\\\\\\",\"\n                + \"\\\\\\\"currentLevel\\\\\\\":1,\"\n                + \"\\\\\\\"name\\\\\\\":\\\\\\\"name1\\\\\\\",\"\n                + \"\\\\\\\"values\\\\\\\":[{\\\\\\\"id\\\\\\\":2,\"\n                + \"\\\\\\\"title\\\\\\\":\\\\\\\"Yes\\\\\\\",\"\n                + \"\\\\\\\"type\\\\\\\":\\\\\\\"MIDWAY\\\\\\\",\"\n                + \"\\\\\\\"currentLevel\\\\\\\":2,\"\n                + \"\\\\\\\"value\\\\\\\":1,\"\n                + \"\\\\\\\"childs\\\\\\\":[{\\\\\\\"id\\\\\\\":3,\"\n                + \"\\\\\\\"title\\\\\\\":\\\\\\\"If it is deducted twice, please contact the online service with the official bank statement.\\\\\\\",\"\n                + \"\\\\\\\"type\\\\\\\":\\\\\\\"END\\\\\\\",\" + \"\\\\\\\"currentLevel\\\\\\\":3}]},\" + \"{\\\\\\\"id\\\\\\\":4,\"\n                + \"\\\\\\\"title\\\\\\\":\\\\\\\"No\\\\\\\",\" + \"\\\\\\\"type\\\\\\\":\\\\\\\"MIDWAY\\\\\\\",\" + \"\\\\\\\"currentLevel\\\\\\\":2,\"\n                + \"\\\\\\\"value\\\\\\\":1,\" + \"\\\\\\\"childs\\\\\\\":[{\\\\\\\"id\\\\\\\":5,\"\n                + \"\\\\\\\"title\\\\\\\":\\\\\\\"Please contact your card issuer to double confirm.\\\\\\\",\"\n                + \"\\\\\\\"type\\\\\\\":\\\\\\\"END\\\\\\\",\" + \"\\\\\\\"currentLevel\\\\\\\":3}]}]}\\\",607)\";\n\n        String expected = \"INSERT INTO icshall_guide (id, gmt_create, gmt_modified, subject, content\\n\" +\n                \"\\t, cat_id)\\n\" +\n                \"VALUES (8, now(), now(), 'Why my payment is deducted incorrectly?/ Why my payment is deducted twice?', '{\\\"id\\\":1,\\\"title\\\":\\\"Have you contacted your card issuer to double check instead of only checking online?\\\",\\\"type\\\":\\\"START\\\",\\\"currentLevel\\\":1,\\\"name\\\":\\\"name1\\\",\\\"values\\\":[{\\\"id\\\":2,\\\"title\\\":\\\"Yes\\\",\\\"type\\\":\\\"MIDWAY\\\",\\\"currentLevel\\\":2,\\\"value\\\":1,\\\"childs\\\":[{\\\"id\\\":3,\\\"title\\\":\\\"If it is deducted twice, please contact the online service with the official bank statement.\\\",\\\"type\\\":\\\"END\\\",\\\"currentLevel\\\":3}]},{\\\"id\\\":4,\\\"title\\\":\\\"No\\\",\\\"type\\\":\\\"MIDWAY\\\",\\\"currentLevel\\\":2,\\\"value\\\":1,\\\"childs\\\":[{\\\"id\\\":5,\\\"title\\\":\\\"Please contact your card issuer to double confirm.\\\",\\\"type\\\":\\\"END\\\",\\\"currentLevel\\\":3}]}]}'\\n\" +\n                \"\\t, 607);\\n\";\n\n        StringBuilder out = new StringBuilder();\n        MySqlOutputVisitor visitor = new MySqlOutputVisitor(out);\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        for (SQLStatement statement : statementList) {\n            statement.accept(visitor);\n            visitor.print(\";\");\n            visitor.println();\n        }\n\n        //System.out.println(out.toString());\n\n        assertEquals(expected, out.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_wdw1206.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\npublic class Bug_for_wdw1206 {\n    private ClassLoader ctxClassLoader;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        ctxClassLoader = Thread.currentThread().getContextClassLoader();\n        Thread.currentThread().setContextClassLoader(null);\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n        dataSource.setPoolPreparedStatements(false);\n        dataSource.setTestOnBorrow(true);\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        Thread.currentThread().setContextClassLoader(ctxClassLoader);\n\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_nullCtxClassLoader() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_weizhi.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_weizhi {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"insert into aaa values(1,2,'这是个反斜杠\\\\\\\\');\";\n\n        String expected = \"INSERT INTO aaa\\nVALUES (1, 2, '这是个反斜杠\\\\\\\\');\";\n\n        assertEquals(expected, SQLUtils.formatMySql(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Bug_for_xuershan.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_xuershan {\n    private DruidDataSource dataSource;\n    private MockDriver driver;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        driver = new MockDriver() {\n            public ResultSet createResultSet(MockPreparedStatement stmt) {\n                return null;\n            }\n        };\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setDriver(driver);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_bug_for_xuershan() throws Exception {\n        String sql = \"select 1\";\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.execute();\n        assertNull(stmt.getResultSet());\n        stmt.close();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1576.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 03/02/2017.\n */\npublic class Issue1576 {\n    private final DbType dbType = JdbcConstants.ORACLE;\n\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"select * from t whe id = 1\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n\n        Exception error = null;\n        try {\n            parser.parseStatement();\n        } catch (Exception ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1645.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 22/03/2017.\n */\npublic class Issue1645 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"explain extended select * from foo\";\n        String formatedSql = SQLUtils.format(sql, JdbcConstants.MYSQL);\n        assertEquals(\"EXPLAIN EXTENDED SELECT *\\n\" +\n                \"FROM foo\", formatedSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1654.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 23/03/2017.\n */\npublic class Issue1654 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"ALTER TABLE db_manage.zcy_gpcatalog_node_t ADD INDEX index_code USING BTREE (code);\";\n        String formatedSql = SQLUtils.format(sql, JdbcConstants.MYSQL);\n        assertEquals(\"ALTER TABLE db_manage.zcy_gpcatalog_node_t\\n\" +\n                \"\\tADD INDEX index_code USING BTREE (code);\", formatedSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1695.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue1695 {\n    @Test\n    public void test_for_mysql() throws Exception {\n        String sql = \"select ht.* from t_books ht\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t_books ht\", result);\n    }\n\n    @Test\n    public void test_for_pg() throws Exception {\n        String sql = \"select ht.* from t_books ht\";\n        String result = PagerUtils.count(sql, JdbcConstants.POSTGRESQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t_books ht\", result);\n    }\n\n    @Test\n    public void test_for_oracle() throws Exception {\n        String sql = \"select ht.* from t_books ht\";\n        String result = PagerUtils.count(sql, JdbcConstants.ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t_books ht\", result);\n    }\n\n    @Test\n    public void test_for_sqlserver() throws Exception {\n        String sql = \"select ht.* from t_books ht\";\n        String result = PagerUtils.count(sql, JdbcConstants.SQL_SERVER);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t_books ht\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1737.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.fastjson2.JSON;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 25/06/2017.\n */\npublic class Issue1737 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"select * from test_tab1 where name='name' and id in  ('A','B')\";\n        final StringBuilder out = new StringBuilder();\n        final ExportParameterVisitor visitor = new OracleExportParameterVisitor(out);\n        visitor.setParameterizedMergeInList(true);\n        SQLStatementParser parser = new OracleStatementParser(sql);\n        final SQLStatement parseStatement = parser.parseStatement();\n        parseStatement.accept(visitor);\n        final List<Object> plist = visitor.getParameters();\n        sql = out.toString();\n        System.out.println(\"src:\" + sql);\n        System.out.println(\"sql:\" + sql);\n        System.out.println(\" params: \" + JSON.toJSONString(plist));\n\n        assertEquals(\"[\\\"name\\\",[\\\"A\\\",\\\"B\\\"]]\", JSON.toJSONString(plist));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1759.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 12/07/2017.\n */\npublic class Issue1759 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"COMMENT ON COLUMN \\\"TB_CRM_MATERIAL\\\".\\\"INVALID_TIME\\\" IS '生效时间'\";\n\n        OracleStatementParser parser = new OracleStatementParser(sql);\n        SQLStatement statement = parser.parseStatement(); // 分号之后多语句忽略\n        OracleWallProvider provider = new OracleWallProvider();\n\n        WallCheckResult result1 = provider.check(sql);\n\n        assertTrue(result1.getViolations().isEmpty());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1762.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 25/06/2017.\n */\npublic class Issue1762 {\n    private final DbType dbType = DbType.mysql;\n\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"-- table-name-bean-name:some --\\n\" +\n                \"CREATE TABLE `some_table` (\\n\" +\n                \"  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键'\\n\" +\n                \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        SQLStatement stmt = stmtList.get(0);\n        List<String> beforeComments = stmt.getBeforeCommentsDirect();\n        assertNotNull(beforeComments);\n        assertEquals(1, beforeComments.size());\n        assertEquals(\"-- table-name-bean-name:some --\", beforeComments.get(0));\n\n        assertEquals(\"-- table-name-bean-name:some --\\n\" +\n                \"CREATE TABLE `some_table` (\\n\" +\n                \"\\t`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键'\\n\" +\n                \")\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"-- table-name-bean-name:some --\\n\" +\n                \"create table `some_table` (\\n\" +\n                \"\\t`id` bigint(20) unsigned not null auto_increment comment '主键'\\n\" +\n                \")\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(1, visitor.getTables().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1769.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlExportParameterVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 25/06/2017.\n */\npublic class Issue1769 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"SELECT id FROM test WHERE type = 9 AND name = ? AND orderId in (1, 2, 3);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        StringBuilder out = new StringBuilder();\n        MySqlExportParameterVisitor v = new MySqlExportParameterVisitor(out);\n        v.setParameterized(true);\n        v.setShardingSupport(false);\n        v.setPrettyFormat(false);\n        stmt.accept(v);\n\n        System.out.println(v.getParameters());\n        System.out.println(v.getTables());\n        assertEquals(\"SELECT id FROM test WHERE type = ? AND name = ? AND orderId IN (?);\", out.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1865.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue1865 {\n    @Test\n    public void test_for_select() throws Exception {\n        final DbType dbType = JdbcConstants.MYSQL;\n\n        String sql = \"select * from t where id = 2 and name = 'wenshao'\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n        SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatement();\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n\n        assertTrue(queryBlock.removeCondition(\"name = 'wenshao'\"));\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WHERE id = 2\", stmt.toString());\n\n        assertTrue(\n                queryBlock.removeCondition(\"id = 2\"));\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\", stmt.toString());\n        queryBlock.addCondition(\"id = 3\");\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WHERE id = 3\", stmt.toString());\n    }\n\n    @Test\n    public void test_for_select_group() throws Exception {\n        final DbType dbType = JdbcConstants.MYSQL;\n\n        String sql = \"select * from t where id = 2 and name = 'wenshao'\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n        SQLSelectStatement stmt = (SQLSelectStatement) parser.parseStatement();\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n\n        assertTrue(queryBlock.removeCondition(\"name = 'wenshao'\"));\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WHERE id = 2\", stmt.toString());\n\n        assertTrue(\n                queryBlock.removeCondition(\"id = 2\"));\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\", stmt.toString());\n    }\n\n    @Test\n    public void test_for_delete() throws Exception {\n        final DbType dbType = JdbcConstants.MYSQL;\n\n        String sql = \"delete from t where id = 2 and name = 'wenshao'\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n        SQLDeleteStatement stmt = (SQLDeleteStatement) parser.parseStatement();\n\n        assertTrue(stmt.removeCondition(\"name = 'wenshao'\"));\n\n        assertEquals(\"DELETE FROM t\\n\" +\n                \"WHERE id = 2\", stmt.toString());\n\n        assertTrue(\n                stmt.removeCondition(\"id = 2\"));\n\n        assertEquals(\"DELETE FROM t\", stmt.toString());\n\n        stmt.addCondition(\"id = 3\");\n        assertEquals(\"DELETE FROM t\\n\" +\n                \"WHERE id = 3\", stmt.toString());\n    }\n\n    @Test\n    public void test_for_delete_group() throws Exception {\n        final DbType dbType = JdbcConstants.MYSQL;\n\n        String sql = \"delete from t where id = 2 and name = 'wenshao'\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n        SQLDeleteStatement stmt = (SQLDeleteStatement) parser.parseStatement();\n\n        assertTrue(stmt.removeCondition(\"name = 'wenshao'\"));\n\n        assertEquals(\"DELETE FROM t\\n\" +\n                \"WHERE id = 2\", stmt.toString());\n\n        assertTrue(\n                stmt.removeCondition(\"id = 2\"));\n\n        assertEquals(\"DELETE FROM t\", stmt.toString());\n\n        stmt.addCondition(\"id = 3\");\n        assertEquals(\"DELETE FROM t\\n\" +\n                \"WHERE id = 3\", stmt.toString());\n    }\n\n    @Test\n    public void test_for_update() throws Exception {\n        final DbType dbType = JdbcConstants.MYSQL;\n\n        String sql = \"update t set val = ? where id = 2 and name = 'wenshao'\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n        SQLUpdateStatement stmt = (SQLUpdateStatement) parser.parseStatement();\n\n        assertTrue(stmt.removeCondition(\"name = 'wenshao'\"));\n\n        assertEquals(\"UPDATE t\\n\" +\n                \"SET val = ?\\n\" +\n                \"WHERE id = 2\", stmt.toString());\n\n        assertTrue(\n                stmt.removeCondition(\"id = 2\"));\n\n        assertEquals(\"UPDATE t\\n\" +\n                \"SET val = ?\", stmt.toString());\n\n        stmt.addCondition(\"id = 3\");\n        assertEquals(\"UPDATE t\\n\" +\n                \"SET val = ?\\n\" +\n                \"WHERE id = 3\", stmt.toString());\n    }\n\n    @Test\n    public void test_for_update_group() throws Exception {\n        final DbType dbType = JdbcConstants.MYSQL;\n\n        String sql = \"update t set val = ? where id = 2 and name = 'wenshao'\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, SQLParserFeature.EnableSQLBinaryOpExprGroup);\n        SQLUpdateStatement stmt = (SQLUpdateStatement) parser.parseStatement();\n\n        assertTrue(stmt.removeCondition(\"name = 'wenshao'\"));\n\n        assertEquals(\"UPDATE t\\n\" +\n                \"SET val = ?\\n\" +\n                \"WHERE id = 2\", stmt.toString());\n\n        assertTrue(\n                stmt.removeCondition(\"id = 2\"));\n\n        assertEquals(\"UPDATE t\\n\" +\n                \"SET val = ?\", stmt.toString());\n\n        stmt.addCondition(\"id = 3\");\n        assertEquals(\"UPDATE t\\n\" +\n                \"SET val = ?\\n\" +\n                \"WHERE id = 3\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1898.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n/**\n * Created by wenshao on 14/08/2017.\n */\npublic class Issue1898 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"SELECT 0 bSomething\";\n        String formatted = com.alibaba.druid.sql.SQLUtils.format(sql, \"mysql\");\n//        assertNotEquals(\"SELECT b'Something'\", formatted);\n        assertEquals(\"SELECT 0 AS bSomething\", formatted);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1912.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitor;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue1912 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"select a from t\";\n        SQLStatementParser parser = new SQLStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        final Map<String, String> columnMapping = new HashMap<String, String>();\n        columnMapping.put(\"a\", \"b\");\n\n        SQLASTVisitor visitor = new SQLASTVisitorAdapter() {\n            public boolean visit(SQLIdentifierExpr x) {\n                String destColumn = columnMapping.get(x.getName());\n                if (destColumn != null) {\n                    x.setName(destColumn);\n                }\n\n                return super.visit(x);\n            }\n        };\n        stmt.accept(visitor);\n\n        assertEquals(\"SELECT b\\n\" +\n                \"FROM t\", SQLUtils.toSQLString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1935.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\npublic class Issue1935 {\n    @Test\n    public void test_for_issue() throws Exception {\n        DbType DBTYPE = JdbcConstants.MYSQL;\n        //String sql = \"select name, course ,scole from student inner join scole on student.id = scole.sd_id where course = '数学' limit 10;\";\n        //sql = \"select name,course,sum(scole) as total from student where student.id in (select sd_id from scole where name='aaa') and scole in (1,2,3) group by name HAVING total <60 order by scole desc limit 10 ,2 \";\n        String sql = \"select name from  student where id in (select sd_id from scole where scole < 60 order by scole asc) or id = 2 order by name desc\";\n        String format = SQLUtils.format(sql, DBTYPE);\n        //System.out.println(\"formated sql :  \" + format);\n        List<SQLStatement> list = SQLUtils.parseStatements(sql, DBTYPE);\n\n        for (int i = 0; i < list.size(); i++) {\n            SQLStatement stmt = list.get(i);\n            MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n            stmt.accept(visitor);\n\n            //获取操作方法名称,依赖于表名称\n            System.out.println(\"涉及到的所有表 : \" + visitor.getTables());\n            Map<TableStat.Name, TableStat> table_map = visitor.getTables();\n            for (Map.Entry<TableStat.Name, TableStat> entry : table_map.entrySet()) {\n                TableStat.Name name = entry.getKey();\n                name.getName();\n                //存储表的调度次数，包括select ，update等\n                TableStat ts = entry.getValue();\n\n            }\n            //获取字段名称\n            System.out.println(visitor.getParameters());\n            //获取列名\n            System.out.println(\"查询的列信息 : \" + visitor.getColumns());\n            Collection<TableStat.Column> cc = visitor.getColumns();\n            //column 存储了表名，列名，以及列是出现的位置，where，select，groupby ，order\n            for (TableStat.Column column : cc) {\n                // Intentionally left empty\n            }\n            System.out.println(\"conditions : \" + visitor.getConditions());\n            List<TableStat.Condition> conditions = visitor.getConditions();\n            System.out.println(\"----------------------------\");\n            for (TableStat.Condition cond : conditions) {\n                System.out.println(\"column : \" + cond.getColumn());\n                System.out.println(\"operator : \" + cond.getOperator());\n                System.out.println(\"values  : \" + cond.getValues());\n\n                System.out.println(\"----------------------------\");\n            }\n            System.out.println(\"group by : \" + visitor.getGroupByColumns());\n            System.out.println(\"order by : \" + visitor.getOrderByColumns());\n            System.out.println(\"relations ships  : \" + visitor.getRelationships());\n\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue1994.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;\nimport com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue1994 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"INSERT INTO MKTG_H_EXEC_RESULT_FACT\\n\" +\n                \"(THE_DATE, AREA_ID, SCENE_ID, MKTG_CNT, MKTG_SUC_CNT\\n\" +\n                \", TASK_CNT, TASK_F_CNT, TASK_F_SUC_CNT, CON_CNT, CON_SUC_CNT)\\n\" +\n                \"SELECT TRUNC(SYSDATE), T1.AREA_ID\\n\" +\n                \", RTRIM(TO_CHAR(T2.PID))\\n\" +\n                \", SUM(T1.MKTG_CNT), SUM(T1.MKTG_SUC_CNT)\\n\" +\n                \", SUM(T1.TASK_CNT), SUM(T1.TASK_F_CNT)\\n\" +\n                \", SUM(T1.TASK_F_SUC_CNT), SUM(T1.CON_CNT)\\n\" +\n                \", SUM(T1.CON_SUC_CNT)\\n\" +\n                \"FROM MKTG_H_EXEC_RESULT_FACT T1, (\\n\" +\n                \"SELECT DISTINCT MKTG_PLAN_LVL1_ID AS PID, MKTG_PLAN_LVL4_ID AS SCENE_ID\\n\" +\n                \"FROM DMN_MKTG_PLAN_TYPE\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT DISTINCT MKTG_PLAN_LVL2_ID AS PID, MKTG_PLAN_LVL4_ID AS SCENE_ID\\n\" +\n                \"FROM DMN_MKTG_PLAN_TYPE_TWO\\n\" +\n                \"WHERE MKTG_PLAN_LVL2_ID <> MKTG_PLAN_LVL4_ID\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT DISTINCT MKTG_PLAN_LVL3_ID AS PID, MKTG_PLAN_LVL4_ID AS SCENE_ID\\n\" +\n                \"FROM DMN_MKTG_PLAN_TYPE\\n\" +\n                \"WHERE MKTG_PLAN_LVL3_ID <> MKTG_PLAN_LVL4_ID\\n\" +\n                \") T2\\n\" +\n                \"WHERE T1.THE_DATE = TRUNC(SYSDATE)\\n\" +\n                \"AND T1.SCENE_ID = T2.SCENE_ID\\n\" +\n                \"GROUP BY T1.AREA_ID, RTRIM(TO_CHAR(T2.PID))\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        System.out.println(stmt);\n\n        SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ORACLE);\n        stmt.accept(statVisitor);\n\n        System.out.println(\"columns : \" + statVisitor.getColumns());\n\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"THE_DATE\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"AREA_ID\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"SCENE_ID\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"MKTG_CNT\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"MKTG_SUC_CNT\"));\n\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"TASK_CNT\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"TASK_F_CNT\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"TASK_F_SUC_CNT\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"CON_CNT\"));\n        assertTrue(statVisitor.containsColumn(\"MKTG_H_EXEC_RESULT_FACT\", \"CON_SUC_CNT\"));\n\n        assertTrue(statVisitor.containsColumn(\"DMN_MKTG_PLAN_TYPE\", \"MKTG_PLAN_LVL1_ID\"));\n        assertTrue(statVisitor.containsColumn(\"DMN_MKTG_PLAN_TYPE\", \"MKTG_PLAN_LVL4_ID\"));\n        assertTrue(statVisitor.containsColumn(\"DMN_MKTG_PLAN_TYPE_TWO\", \"MKTG_PLAN_LVL2_ID\"));\n        assertTrue(statVisitor.containsColumn(\"DMN_MKTG_PLAN_TYPE_TWO\", \"MKTG_PLAN_LVL4_ID\"));\n        assertTrue(statVisitor.containsColumn(\"DMN_MKTG_PLAN_TYPE\", \"MKTG_PLAN_LVL3_ID\"));\n\n        OracleInsertStatement insertStmt = (OracleInsertStatement) stmt;\n        OracleSelectQueryBlock queryBlock = (OracleSelectQueryBlock) insertStmt.getQuery().getQueryBlock();\n\n        SQLSelectItem selectItem = queryBlock.getSelectList().get(0);\n        assertEquals(\"TRUNC(SYSDATE)\", selectItem.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue2002.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\npublic class Issue2002 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"select id,sum(uv[1]) uv1,sum(uv[2]) uv2\\n\" +\n                \"from xxxxx where a in\\n\" +\n                \"                     (  \\n\" +\n                \"                        ?\\n\" +\n                \"                     ) \\n\" +\n                \" and ta->'taAge' ??|\\n\" +\n                \"                 \\n\" +\n                \"                         '{  \\n\" +\n                \"                            1\\n\" +\n                \"                         , \\n\" +\n                \"                            2\\n\" +\n                \"                         , \\n\" +\n                \"                            3\\n\" +\n                \"                         }' \\n\" +\n                \"group by id\";\n\n        StatFilter filter = new StatFilter();\n        filter.setMergeSql(true);\n        String psql = filter.mergeSql(sql, JdbcConstants.POSTGRESQL);\n        System.out.println(psql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue2015.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue2015 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"update t set a=1,b=2 where a > 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n\n        StringBuilder buf = new StringBuilder();\n        stmtList.get(0).output(buf);\n        assertEquals(\"UPDATE t\\n\" +\n                \"SET a = 1, b = 2\\n\" +\n                \"WHERE a > 1\", buf.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue2049.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 12/07/2017.\n */\npublic class Issue2049 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select * from emp a,dmp b;\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n\n        SQLSelectStatement stmt = (SQLSelectStatement) stmtList.get(0);\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n        SQLJoinTableSource joinTableSource = (SQLJoinTableSource) queryBlock.getFrom();\n\n        assertEquals(\"a\", joinTableSource.getLeft().getAlias());\n        assertEquals(\"b\", joinTableSource.getRight().getAlias());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue2876.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue2876 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT CONCAT(\\\"'\\\",b.PRIMARY_ID,\\\"'\\\") \\n\" +\n                \"FROM s_user_session_attributes a \\n\" +\n                \"LEFT JOIN s_user_session b ON a.SESSION_PRIMARY_ID=b.PRIMARY_ID \\n\" +\n                \"WHERE a.ATTRIBUTE_NAME='KAPTCHA_SESSION_KEY' AND b.LAST_ACCESS_TIME <= 1540429945459\";\n\n        System.out.println(sql);\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n\n        SQLSelectStatement stmt = (SQLSelectStatement) stmtList.get(0);\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n        SQLJoinTableSource joinTableSource = (SQLJoinTableSource) queryBlock.getFrom();\n\n        assertEquals(\"a\", joinTableSource.getLeft().getAlias());\n        assertEquals(\"b\", joinTableSource.getRight().getAlias());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue3929.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue3929 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"replace into table1 (id,name) values('1','aa'),('2','bb')\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"replace into table1 (id, name)\\n\" +\n                \"values ('1', 'aa'), ('2', 'bb')\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue3952.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue3952 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select\\n\" +\n                \"  d.id,\\n\" +\n                \"  b.contract_date as                              contractDate,\\n\" +\n                \"  d.contract_no,\\n\" +\n                \"  d.brand_code    as                              brandCode,\\n\" +\n                \"  d.num,\\n\" +\n                \"  (SELECT COALESCE(sum(num1), 0)  FROM tc_order_record  WHERE tc_order_record.contract_no = d.contract_no)  orderSumNum,\\n\" +\n                \"  (SELECT (COALESCE(d.num, 0) - COALESCE(sum(num1), 0))  FROM tc_order_record  WHERE tc_order_record.contract_no = d.contract_no) avai\\n\" +\n                \"from tc_contract_detail as d left join tc_contract_base  b on d.contract_no = b.contract_no\\n\" +\n                \"where b.data_transfer_flag = '3' and if('' != '', d.contract_no = '', 1 = 1)\\n\" +\n                \"      and if('' != '', d.brand_code = '', 1 = 1) and if(NULL != '', b.contract_date >= NULL, 1 = 1) and if(NULL != '',   b.contract_date <= NULL, 1 = 1)\\n\" +\n                \"order by b.contract_date desc, d.id desc\\n\" +\n                \"limit 10\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"select d.id, b.contract_date as contractDate, d.contract_no, d.brand_code as brandCode, d.num\\n\" +\n                \"\\t, (\\n\" +\n                \"\\t\\tselect COALESCE(sum(num1), 0)\\n\" +\n                \"\\t\\tfrom tc_order_record\\n\" +\n                \"\\t\\twhere tc_order_record.contract_no = d.contract_no\\n\" +\n                \"\\t) as orderSumNum\\n\" +\n                \"\\t, (\\n\" +\n                \"\\t\\tselect (COALESCE(d.num, 0) - COALESCE(sum(num1), 0))\\n\" +\n                \"\\t\\tfrom tc_order_record\\n\" +\n                \"\\t\\twhere tc_order_record.contract_no = d.contract_no\\n\" +\n                \"\\t) as avai\\n\" +\n                \"from tc_contract_detail d\\n\" +\n                \"\\tleft join tc_contract_base b on d.contract_no = b.contract_no\\n\" +\n                \"where b.data_transfer_flag = '3'\\n\" +\n                \"\\tand if('' != '', d.contract_no = '', 1 = 1)\\n\" +\n                \"\\tand if('' != '', d.brand_code = '', 1 = 1)\\n\" +\n                \"\\tand if(null != '', b.contract_date >= null, 1 = 1)\\n\" +\n                \"\\tand if(null != '', b.contract_date <= null, 1 = 1)\\n\" +\n                \"order by b.contract_date desc, d.id desc\\n\" +\n                \"limit 10\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue4067.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue4067 {\n    @Test\n    public void test_for_issue() throws Exception {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(\"desc bi.aaa\", DbType.hive);\n        SQLStatement stmt = stmtList.get(0);\n        SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(DbType.hive);\n        stmt.accept(statVisitor);\n        assertEquals(1, statVisitor.getTables().size());\n        TableStat tableStat = statVisitor.getTableStat(\"bi.aa\");\n        assertEquals(0, tableStat.getDropIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue4071.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue4071 {\n    @Test\n    public void test_for_issue() throws Exception {\n        assertEquals(\"\", new SQLSelectStatement().toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue4253.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.nio.charset.StandardCharsets;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 03/02/2017.\n */\npublic class Issue4253 {\n    private final DbType dbType = JdbcConstants.ORACLE;\n\n    @Test\n    public void test_for_issue() throws Exception {\n        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(\"bvt/parser/oracle-62.txt\");\n        Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);\n        String input = Utils.read(reader);\n        JdbcUtils.close(reader);\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(input, dbType);\n        Exception error = null;\n        try {\n            parser.parseStatement();\n        } catch (Exception ex) {\n            ex.printStackTrace();\n            error = ex;\n            error.printStackTrace();\n        }\n        assertNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue5763.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @Author lizongbo\n * @see <a href=\"https://github.com/alibaba/druid/issues/5763\">...</a>\n */\npublic class Issue5763 {\n    @Test\n    public void test_for_clone() throws Exception {\n        String sql = \"select user.col from user use index(a)\";\n        SQLStatement origin = SQLUtils.parseSingleMysqlStatement(sql);\n        System.out.println(\"origin = \" + origin);\n\n        SQLStatement clone = origin.clone();\n        System.out.println(\"clone = \" + clone);\n        assertEquals(origin.toString(), clone.toString());\n        assertEquals(origin, clone);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue5845.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n *\n */\npublic class Issue5845 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"delete from table01 t where t.id=1\";\n        List<DbType> dbTypes = new ArrayList<>();\n        for (DbType dbType : DbType.values()) {\n            try {\n                String mergeSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType);\n                System.out.println(dbType + \"==\" + mergeSql);\n                dbTypes.add(dbType);\n            } catch (Exception e) {\n                System.out.println(dbType + \"==\" + e.getMessage());\n            }\n        }\n        for (DbType dbT : dbTypes) {\n            System.out.println(\"DbType.\" + dbT + \",\");\n        }\n        for (DbType dbType : new DbType[]{DbType.db2,\n            DbType.postgresql,\n            DbType.oracle,\n            DbType.mysql,\n            DbType.mariadb,\n            DbType.oceanbase,\n            DbType.edb,\n            DbType.elastic_search,\n            DbType.drds,\n            DbType.oceanbase_oracle,\n            DbType.greenplum,\n            DbType.gaussdb,\n            DbType.tidb,\n            DbType.goldendb, }) {\n            String mergeSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType);\n            System.out.println(dbType + \"==\" + mergeSql);\n            dbTypes.add(dbType);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue5847.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n/**\n *\n */\npublic class Issue5847 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"-- 执行SQLUtils.format(sql, DbType.dm)结果，外层括号被剔除，该sql在dm库执行失败\\n\"\n            + \"SELECT *\\n\"\n            + \"FROM tb_test\\n\"\n            + \"LIMIT 10 OFFSET ( (2 - 1) * 1 *( 3 + 5) )\";\n\n        sql = \"select a.*, (a.swanav-lead(a.swanav,1,null::numeric) over w)/lead(a.swanav,1,null::numeric) over w as roe_lag\\n\";\n        sql = \"select a.*, ((a.swanav-lead(a.swanav,1,null::numeric) over w)/lead(a.swanav,1,null::numeric) over w) as roe_lag\\n\";\n        sql = \"select * from aaa \"\n\n       + \"group by to_char((CreateDate || ' ' || cast(HourArgment as VARCHAR) || ':00:00')::TIMESTAMP, 'YYYY-MM-DD HH24')\";\n\n        for (DbType dbType : new DbType[]{\n            //DbType.db2,\n            DbType.postgresql,\n//            DbType.oracle,\n//            DbType.mysql,\n//            DbType.mariadb,\n//            DbType.oceanbase,\n//            DbType.edb,\n//            DbType.elastic_search,\n//            DbType.drds,\n//            DbType.oceanbase_oracle,\n//            DbType.greenplum,\n//            DbType.gaussdb,\n//            DbType.tidb,\n//            DbType.goldendb,\n            //DbType.dm,\n        }) {\n            try {\n               // String mergeSql = SQLUtils.format(sql, dbType);\n                List<SQLStatement> list = SQLUtils.parseStatements(sql, dbType);\n                System.out.println(dbType + \"==\" + list);\n                SQLBinaryOpExpr fff;\n            } catch (Exception e) {\n                System.out.println(dbType + \"==\" + e.getMessage());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue_4094.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * https://github.com/alibaba/druid/issues/4094\n */\npublic class Issue_4094 {\n    @Test\n    public void test_betweent_lost() {\n        // 此sql可以正常执行\n        String sql = \"SELECT B.CUSTOMER_ID customerId,B.CN_NAME NAME,OPENING_DATE,CLOSING_DATE,count(A.OPENING_DATE) over (partition BY B.CUSTOMER_ID ORDER BY trunc(A.OPENING_DATE,'mm') RANGE BETWEEN interval '3' month (4) preceding AND CURRENT ROW) AS createCount,count(A.CLOSING_DATE) over (partition BY B.CUSTOMER_ID ORDER BY trunc(NVL(A.CLOSING_DATE,SYSDATE),'mm') RANGE BETWEEN interval '3' month (4) preceding AND CURRENT ROW) AS cancelCount,row_number () over (partition BY B.CUSTOMER_ID ORDER BY trunc(A.OPENING_DATE) DESC) AS row_flg FROM account_info A,CUSTOMER_INFO B WHERE A.CUSTOMER_ID=B.CUSTOMER_ID\";\n        String format = SQLUtils.format(sql, DbType.oracle);\n        assertEquals(\"SELECT B.CUSTOMER_ID AS customerId, B.CN_NAME AS NAME, OPENING_DATE, CLOSING_DATE\\n\"\n                + \"\\t, count(A.OPENING_DATE) OVER (PARTITION BY B.CUSTOMER_ID ORDER BY trunc(A.OPENING_DATE, 'mm') RANGE  \"\n                + \"BETWEEN INTERVAL '3' MONTH(4) PRECEDING AND CURRENT ROW) AS createCount\\n\"\n                + \"\\t, count(A.CLOSING_DATE) OVER (PARTITION BY B.CUSTOMER_ID ORDER BY trunc(NVL(A.CLOSING_DATE, SYSDATE),\"\n                + \" 'mm') RANGE  BETWEEN INTERVAL '3' MONTH(4) PRECEDING AND CURRENT ROW) AS cancelCount\\n\"\n                + \"\\t, row_number() OVER (PARTITION BY B.CUSTOMER_ID ORDER BY trunc(A.OPENING_DATE) DESC) AS row_flg\\n\"\n                + \"FROM account_info A, CUSTOMER_INFO B\\n\"\n                + \"WHERE A.CUSTOMER_ID = B.CUSTOMER_ID\", format);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue_4190.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue_4190 {\n    @Test\n    public void test_1() {\n        String sql = \"select Ülke, İsim\\n\"\n                + \" from [Örnek VeriTabanı].dbo.[MÜŞteri Bilgisi]\";\n        SQLStatement actual = SQLUtils.parseSingleStatement(sql, DbType.sqlserver);\n        assertNotNull(actual);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue_685.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;\nimport org.junit.jupiter.api.Test;\n\npublic class Issue_685 {\n    @Test\n    public void test_for_issue() throws Exception {\n        OracleStatementParser parser = new OracleStatementParser(\"select upper(*) from aa order by now()\");\n        SQLStatement st = parser.parseStatement();\n        st.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue_697.java",
    "content": "package com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue_697 {\n    @Test\n    public void test_for_issue() throws Exception {\n        String sql = \"insert into tag_rule_detail(id, gmt_create, gmt_modified, group_id, priority, rule_condition, rule_action) values(1010102, now(), now(), 10101, 0, 'flow=''trustLogin''', 'be:login,dev:pc, env:web, type:trust_login, from:$loginfrom, result:true') ;\\n\"\n                + \"insert into tag_rule_detail(id, gmt_create, gmt_modified, group_id, priority, rule_condition, rule_action) values(1010103, now(), now(), 10101, 0, 'flow=''Ctr''', 'be:login,dev:pc, env:web, type:ctr, from:$loginfrom, result:true') ;\";\n\n        String expected = \"INSERT INTO tag_rule_detail (id, gmt_create, gmt_modified, group_id, priority\\n\" +\n                \"\\t, rule_condition, rule_action)\\n\" +\n                \"VALUES (1010102, now(), now(), 10101, 0\\n\" +\n                \"\\t, 'flow=''trustLogin''', 'be:login,dev:pc, env:web, type:trust_login, from:$loginfrom, result:true');\\n\" +\n                \"\\n\" +\n                \"INSERT INTO tag_rule_detail (id, gmt_create, gmt_modified, group_id, priority\\n\" +\n                \"\\t, rule_condition, rule_action)\\n\" +\n                \"VALUES (1010103, now(), now(), 10101, 0\\n\" +\n                \"\\t, 'flow=''Ctr''', 'be:login,dev:pc, env:web, type:ctr, from:$loginfrom, result:true');\";\n\n        assertEquals(expected, SQLUtils.formatMySql(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/bug/Issue_728.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.bug;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue_728 {\n    @Test\n    public void test1() throws Exception {\n        String sql = \"select * from city_list where city_id = 3-1\";\n\n        WallConfig config = new WallConfig();\n        config.setConstArithmeticAllow(false);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test2() throws Exception {\n        String sql = \"SELECT * from city_list where 2 = case when 2=1 then 1 else 2 END\";\n\n        WallConfig config = new WallConfig();\n        config.setCaseConditionConstAllow(false);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test3() throws Exception {\n        String sql = \"SELECT * from city_list where city_id = 1 & 2\";\n\n        WallConfig config = new WallConfig();\n        config.setConditionOpBitwiseAllow(false);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/ClearFilterTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.filter.encoding.EncodingConvertFilter;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ClearFilterTest extends PoolTestCase {\n    public void test_filters() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        assertEquals(0, dataSource.getProxyFilters().size());\n        dataSource.setFilters(\"encoding\");\n        assertEquals(1, dataSource.getProxyFilters().size());\n        dataSource.setFilters(\"!stat\");\n        assertEquals(1, dataSource.getProxyFilters().size());\n        assertEquals(StatFilter.class.getName(), dataSource.getFilterClassNames().get(0));\n        dataSource.setClearFiltersEnable(false);\n        dataSource.setFilters(\"!encoding\");\n        assertEquals(StatFilter.class.getName(), dataSource.getFilterClassNames().get(0));\n        assertEquals(EncodingConvertFilter.class.getName(), dataSource.getFilterClassNames().get(1));\n\n        dataSource.setConnectionProperties(\"druid.clearFiltersEnable=false\");\n        assertFalse(dataSource.isClearFiltersEnable());\n\n        dataSource.setConnectionProperties(\"druid.clearFiltersEnable=true\");\n        assertTrue(dataSource.isClearFiltersEnable());\n\n        dataSource.setConnectionProperties(\"druid.clearFiltersEnable=xx\"); // no change\n        assertTrue(dataSource.isClearFiltersEnable());\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/EncodingConvertFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.encoding.EncodingConvertFilter;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EncodingConvertFilterTest {\n    private DruidDataSource dataSource;\n\n    private static String CLIENT_ENCODING = \"UTF-8\";\n    private static String SERVER_ENCODING = \"ISO-8859-1\";\n\n    private static String text = \"中华人民共和国\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"encoding\");\n\n        dataSource.setDriver(new MockDriver() {\n            public ResultSet createResultSet(MockPreparedStatement stmt) {\n                return new MyResultSet(stmt);\n            }\n\n            public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n                return new MyResultSet(stmt);\n            }\n        });\n\n        dataSource.getConnectProperties().put(\"clientEncoding\", CLIENT_ENCODING);\n        dataSource.getConnectProperties().put(\"serverEncoding\", SERVER_ENCODING);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        assertTrue(dataSource.isInited());\n\n        EncodingConvertFilter filter = (EncodingConvertFilter) dataSource.getProxyFilters().get(0);\n\n        DruidPooledConnection conn = dataSource.getConnection();\n\n        final String PARAM_VALUE = \"中国\";\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setString(1, PARAM_VALUE);\n\n        MockPreparedStatement raw = stmt.unwrap(MockPreparedStatement.class);\n\n        String param1 = (String) raw.getParameters().get(0);\n\n        assertEquals(PARAM_VALUE, new String(param1.getBytes(SERVER_ENCODING), CLIENT_ENCODING));\n        assertFalse(param1.equals(PARAM_VALUE));\n\n        ResultSet rs = stmt.executeQuery();\n\n        MyResultSet rawRs = rs.unwrap(MyResultSet.class);\n        rawRs.setValue(filter.encode((ConnectionProxy) conn.getConnection(), text));\n\n        rs.next();\n\n        assertEquals(text, rs.getString(1));\n\n        rs.close();\n        stmt.close();\n\n        conn.close();\n    }\n\n    public static class MyResultSet extends MockResultSet {\n        private String value;\n\n        public MyResultSet(Statement statement) {\n            super(statement);\n        }\n\n        public String getObject(int index) throws SQLException {\n            return getString(index);\n        }\n\n        public String getString(int columnIndex) throws SQLException {\n            return value;\n        }\n\n        public String getValue() {\n            return value;\n        }\n\n        public void setValue(String value) {\n            this.value = value;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/EncodingConvertFilterTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.encoding.EncodingConvertFilter;\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.mock.MockResultSetMetaData;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\nimport com.alibaba.druid.util.jdbc.ResultSetMetaDataBase.ColumnMetaData;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.Reader;\nimport java.io.StringReader;\nimport java.sql.CallableStatement;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.sql.Types;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EncodingConvertFilterTest2 {\n    private DruidDataSource dataSource;\n\n    private static String CLIENT_ENCODING = \"UTF-8\";\n    private static String SERVER_ENCODING = \"ISO-8859-1\";\n\n    private static String text = \"中华人民共和国\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"encoding\");\n\n        dataSource.setDriver(new MockDriver() {\n            public ResultSet createResultSet(MockPreparedStatement stmt) {\n                return new MyResultSet(stmt);\n            }\n\n            public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n                return new MyResultSet(stmt);\n            }\n        });\n\n        dataSource.getConnectProperties().put(\"clientEncoding\", CLIENT_ENCODING);\n        dataSource.getConnectProperties().put(\"serverEncoding\", SERVER_ENCODING);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        assertTrue(dataSource.isInited());\n\n        EncodingConvertFilter filter = (EncodingConvertFilter) dataSource.getProxyFilters().get(0);\n\n        DruidPooledConnection conn = dataSource.getConnection();\n\n        final String PARAM_VALUE = \"中国\";\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.setString(1, PARAM_VALUE);\n\n        MockCallableStatement raw = stmt.unwrap(MockCallableStatement.class);\n\n        stmt.execute();\n        String param1 = (String) raw.getParameters().get(0);\n\n        String C_TEXT = new String(param1.getBytes(SERVER_ENCODING), CLIENT_ENCODING);\n        assertEquals(PARAM_VALUE, C_TEXT);\n        assertFalse(param1.equals(PARAM_VALUE));\n\n        MyResultSet rawRs = new MyResultSet(raw);\n\n        rawRs.setValue(filter.encode((ConnectionProxy) conn.getConnection(), text));\n\n        raw.getOutParameters().add(rawRs);\n\n        ResultSet rs = (ResultSet) stmt.getObject(1);\n\n        rs.next();\n\n        assertEquals(text, rs.getString(1));\n        assertEquals(text, rs.getString(\"1\"));\n        assertEquals(text, rs.getObject(1));\n        assertEquals(text, rs.getObject(\"1\"));\n        assertEquals(text, rs.getObject(1, Collections.<String, Class<?>>emptyMap()));\n        assertEquals(text, rs.getObject(\"1\", Collections.<String, Class<?>>emptyMap()));\n\n        assertEquals(text, rs.getString(2));\n        assertEquals(text, rs.getString(\"2\"));\n        assertEquals(text, rs.getObject(2));\n        assertEquals(text, rs.getObject(\"2\"));\n        assertEquals(text, rs.getObject(2, Collections.<String, Class<?>>emptyMap()));\n        assertEquals(text, rs.getObject(\"2\", Collections.<String, Class<?>>emptyMap()));\n\n        assertEquals(text, rs.getString(3));\n        assertEquals(text, rs.getString(\"3\"));\n        assertEquals(text, rs.getObject(3));\n        assertEquals(text, rs.getObject(\"3\"));\n        assertEquals(text, rs.getObject(3, Collections.<String, Class<?>>emptyMap()));\n        assertEquals(text, rs.getObject(\"3\", Collections.<String, Class<?>>emptyMap()));\n\n        assertEquals(text, rs.getString(4));\n        assertEquals(text, rs.getString(\"4\"));\n        assertEquals(text, rs.getObject(4));\n        assertEquals(text, rs.getObject(\"4\"));\n        assertEquals(text, rs.getObject(4, Collections.<String, Class<?>>emptyMap()));\n        assertEquals(text, rs.getObject(\"4\", Collections.<String, Class<?>>emptyMap()));\n\n        stmt.registerOutParameter(2, Types.VARCHAR);\n        stmt.registerOutParameter(3, Types.CLOB);\n        raw.getOutParameters().add(param1);\n        raw.getOutParameters().add(param1);\n\n        assertEquals(C_TEXT, stmt.getString(4));\n        assertEquals(C_TEXT, stmt.getString(\"4\"));\n        assertEquals(C_TEXT, stmt.getObject(4));\n        assertEquals(C_TEXT, stmt.getObject(\"4\"));\n        assertEquals(C_TEXT, stmt.getObject(4, Collections.<String, Class<?>>emptyMap()));\n        assertEquals(C_TEXT, stmt.getObject(\"4\", Collections.<String, Class<?>>emptyMap()));\n\n        assertEquals(C_TEXT, stmt.getString(5));\n        assertEquals(C_TEXT, stmt.getString(\"5\"));\n        assertEquals(C_TEXT, stmt.getObject(5));\n        assertEquals(C_TEXT, stmt.getObject(\"5\"));\n        assertEquals(C_TEXT, stmt.getObject(5, Collections.<String, Class<?>>emptyMap()));\n        assertEquals(C_TEXT, stmt.getObject(\"5\", Collections.<String, Class<?>>emptyMap()));\n\n        stmt.setObject(1, C_TEXT);\n        assertEquals(param1, raw.getParameters().get(0));\n\n        stmt.setObject(2, new StringReader(C_TEXT));\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(1)));\n\n        stmt.setCharacterStream(3, new StringReader(C_TEXT));\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(2)));\n\n        stmt.setCharacterStream(4, new StringReader(C_TEXT), C_TEXT.length());\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(3)));\n\n        stmt.setCharacterStream(5, new StringReader(C_TEXT), (long) C_TEXT.length());\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(4)));\n\n        stmt.setObject(6, C_TEXT, Types.VARCHAR);\n        assertEquals(param1, raw.getParameters().get(5));\n        stmt.setObject(7, new StringReader(C_TEXT), Types.VARCHAR);\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(6)));\n\n        stmt.setObject(8, C_TEXT, Types.VARCHAR, 0);\n        assertEquals(param1, raw.getParameters().get(7));\n        stmt.setObject(9, new StringReader(C_TEXT), Types.VARCHAR, 0);\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(8)));\n\n        stmt.setObject(10, 1, Types.INTEGER);\n        assertEquals(1, raw.getParameters().get(9));\n\n        stmt.setObject(11, 2, Types.INTEGER, 0);\n        assertEquals(2, raw.getParameters().get(10));\n\n        stmt.setObject(12, 3);\n        assertEquals(3, raw.getParameters().get(11));\n\n        stmt.setObject(\"13\", C_TEXT, Types.VARCHAR);\n        assertEquals(param1, raw.getParameters().get(12));\n        stmt.setObject(\"14\", new StringReader(C_TEXT), Types.VARCHAR);\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(13)));\n\n        stmt.setObject(\"15\", C_TEXT, Types.VARCHAR, 0);\n        assertEquals(param1, raw.getParameters().get(14));\n        stmt.setObject(\"16\", new StringReader(C_TEXT), Types.VARCHAR, 0);\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(15)));\n\n        stmt.setObject(\"17\", 1, Types.INTEGER);\n        assertEquals(1, raw.getParameters().get(16));\n\n        stmt.setObject(\"18\", 2, Types.INTEGER, 0);\n        assertEquals(2, raw.getParameters().get(17));\n\n        stmt.setObject(\"19\", 3);\n        assertEquals(3, raw.getParameters().get(18));\n\n        stmt.setCharacterStream(\"20\", new StringReader(C_TEXT));\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(19)));\n\n        stmt.setCharacterStream(\"21\", new StringReader(C_TEXT), C_TEXT.length());\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(20)));\n\n        stmt.setCharacterStream(\"22\", new StringReader(C_TEXT), (long) C_TEXT.length());\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(21)));\n\n        stmt.setObject(\"23\", C_TEXT);\n        assertEquals(param1, raw.getParameters().get(22));\n\n        stmt.setObject(\"24\", new StringReader(C_TEXT));\n        assertEquals(param1, Utils.read((Reader) raw.getParameters().get(23)));\n\n        stmt.setObject(\"25\", 1, Types.INTEGER);\n        assertEquals(1, raw.getParameters().get(24));\n\n        stmt.setObject(\"26\", 2, Types.INTEGER, 0);\n        assertEquals(2, raw.getParameters().get(25));\n\n        stmt.setObject(\"27\", 3);\n        assertEquals(3, raw.getParameters().get(26));\n\n        rs.close();\n        stmt.close();\n\n        conn.close();\n    }\n\n    public static class MyResultSet extends MockResultSet {\n        private String value;\n        private MockResultSetMetaData meta = new MockResultSetMetaData();\n\n        public MyResultSet(Statement statement) {\n            super(statement);\n            {\n                ColumnMetaData column = new ColumnMetaData();\n                column.setColumnType(Types.VARCHAR);\n                meta.getColumns().add(column);\n            }\n            {\n                ColumnMetaData column = new ColumnMetaData();\n                column.setColumnType(Types.LONGVARCHAR);\n                meta.getColumns().add(column);\n            }\n            {\n                ColumnMetaData column = new ColumnMetaData();\n                column.setColumnType(Types.CHAR);\n                meta.getColumns().add(column);\n            }\n            {\n                ColumnMetaData column = new ColumnMetaData();\n                column.setColumnType(Types.CLOB);\n                meta.getColumns().add(column);\n            }\n        }\n\n        public String getObject(int index) throws SQLException {\n            return getString(index);\n        }\n\n        public String getString(int columnIndex) throws SQLException {\n            return value;\n        }\n\n        public String getValue() {\n            return value;\n        }\n\n        public void setValue(String value) {\n            this.value = value;\n        }\n\n        @Override\n        public ResultSetMetaData getMetaData() {\n            return meta;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainImplTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockNClob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.NClob;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Types;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainImplTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat,log4j,wall,encoding\");\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n        });\n        dataSource.setDbType(\"mysql\");\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_size() {\n        assertEquals(dataSource.getProxyFilters().size(), new FilterChainImpl(dataSource).getFilterSize());\n    }\n\n    @Test\n    public void test_unwrap() throws Exception {\n        assertNull(new FilterChainImpl(dataSource).unwrap(null, null));\n    }\n\n    @Test\n    public void test_unwrap_5() throws Exception {\n        assertNull(new FilterChainImpl(dataSource).wrap((ConnectionProxy) dataSource.getConnection().getConnection(),\n                (Clob) null));\n    }\n\n    @Test\n    public void test_unwrap_6() throws Exception {\n        Connection conn = dataSource.getConnection();\n        assertTrue(new FilterChainImpl(dataSource).wrap((ConnectionProxy) dataSource.getConnection().getConnection(),\n                new MockNClob()) instanceof NClob);\n        conn.close();\n    }\n\n    @Test\n    public void test_unwrap_8() throws Exception {\n        Connection conn = dataSource.getConnection();\n        assertTrue(new FilterChainImpl(dataSource).wrap((ConnectionProxy) dataSource.getConnection().getConnection(),\n                (Clob) new MockNClob()) instanceof NClob);\n        conn.close();\n    }\n\n    @Test\n    public void test_unwrap_7() throws Exception {\n        assertNull(new FilterChainImpl(dataSource).wrap((ConnectionProxy) dataSource.getConnection().getConnection(),\n                (NClob) null));\n    }\n\n    @Test\n    public void test_unwrap_9() throws Exception {\n        assertNull(new FilterChainImpl(dataSource).wrap((StatementProxy) null, (NClob) null));\n    }\n\n    @Test\n    public void test_getUnicodeStream() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getUnicodeStream(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getUnicodeStream_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getUnicodeStream(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRef() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getRef(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRef_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getRef(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getArray() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getArray(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getArray_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getArray(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getURL() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getURL(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getURL_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getURL(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRowId() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getRowId(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRowId_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getRowId(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNClob() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getNClob(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNClob_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getNClob(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getSQLXML() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getSQLXML(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getSQLXML_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getSQLXML(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNString() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getNString(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNString_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getNString(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNCharacterStream() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getNCharacterStream(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNCharacterStream_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getNCharacterStream(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getObject(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getObject_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        assertNull(rs.getObject(\"1\"));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainImplTest2.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.CallableStatement;\nimport java.sql.Connection;\nimport java.sql.Types;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainImplTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat,log4j,wall,encoding\");\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n        });\n        dataSource.setDbType(\"mysql\");\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_getURL() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getURL(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getURL_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getURL(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getString() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getString(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getString_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getString(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBoolean() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertFalse(stmt.getBoolean(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBoolean_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertFalse(stmt.getBoolean(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getByte() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getByte(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getByte_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getByte(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getShort() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getShort(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getShort_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getShort(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getInt() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getInt(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getInt_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getInt(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getLong() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getLong(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getLong_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertEquals(0, stmt.getLong(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getFloat() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertTrue(0F == stmt.getFloat(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getFloat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertTrue(0F == stmt.getFloat(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getDouble() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertTrue(0D == stmt.getDouble(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getDouble_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertTrue(0D == stmt.getDouble(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBytes() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getBytes(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBytes_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getBytes(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getDate() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getDate(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getDate_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getDate(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTime() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTime(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTime_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTime(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTimestamp() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTimestamp(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTimestamp_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTimestamp(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBigDecimal() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getBigDecimal(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBigDecimal_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getBigDecimal(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRef() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getRef(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRef_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getRef(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBlob() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getBlob(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getBlob_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getBlob(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getArray() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getArray(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getArray_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getArray(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getDate_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getDate(1, null));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getDate_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getDate(\"1\", null));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTime_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTime(1, null));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTime_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTime(\"1\", null));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTimestamp_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTimestamp(1, null));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getTimestamp_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getTimestamp(\"1\", null));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRowId() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getRowId(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getRowId_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getRowId(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNClob() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getNClob(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNClob_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getNClob(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getSQLXML() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getSQLXML(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getSQLXML_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getSQLXML(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNString() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getNString(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNString_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getNString(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNCharacterStream() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getNCharacterStream(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getNCharacterStream_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getNCharacterStream(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getCharacterStream() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getCharacterStream(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getCharacterStream_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getCharacterStream(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getObject(1));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getObject_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getObject(\"1\"));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getObject_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getObject(1, Collections.<String, Class<?>>emptyMap()));\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getObject_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.registerOutParameter(1, Types.VARCHAR);\n\n        assertNull(stmt.getObject(\"1\", Collections.<String, Class<?>>emptyMap()));\n\n        stmt.close();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainImplTest3.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.sql.Types;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainImplTest3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat,log4j,wall,encoding\");\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n        });\n        dataSource.setDbType(\"mysql\");\n\n        dataSource.setDriver(new MockDriver() {\n            public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n                return null;\n            }\n\n            public MockStatement createMockStatement(MockConnection conn) {\n                return new MockStatement(conn) {\n                    public ResultSet getResultSet() throws SQLException {\n                        return null;\n                    }\n                };\n            }\n        });\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_executeQuery() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        assertNull(stmt.executeQuery());\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeQuery_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareCall(\"select ?\");\n        stmt.setNull(1, Types.VARCHAR);\n        assertNull(stmt.executeQuery());\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeQuery_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n        assertNull(stmt.executeQuery(\"select 1\"));\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"select 1\");\n        assertNull(stmt.getResultSet());\n        stmt.close();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainTest_Clob.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockClob;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ClobProxy;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxyImpl;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Clob;\nimport java.sql.SQLException;\nimport java.util.Collections;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainTest_Clob {\n    private DruidDataSource dataSource;\n    private StatementProxy statement;\n    private MockResultSet mockResultSet;\n\n    private int invokeCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        ConnectionProxyImpl conn = new ConnectionProxyImpl(dataSource, null, new Properties(), 0);\n        statement = new StatementProxyImpl(conn, null, 1);\n\n        mockResultSet = new MockResultSet(null) {\n            public Object getObject(int columnIndex) throws SQLException {\n                invokeCount++;\n                return new MockClob();\n            }\n        };\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        invokeCount = 0;\n    }\n\n    @Test\n    public void test_resultSet_getClob() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.resultSet_getClob(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1);\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getClob_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.resultSet_getClob(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\");\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1);\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\");\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_2() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1, Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_3() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\", Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainTest_Clob_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.mock.MockClob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ClobProxy;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Clob;\nimport java.sql.SQLException;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainTest_Clob_2 {\n    private DruidDataSource dataSource;\n    private CallableStatementProxy statement;\n\n    private int invokeCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        MockCallableStatement mockStmt = new MockCallableStatement(null, \"\") {\n            @Override\n            public Object getObject(int parameterIndex) throws SQLException {\n                invokeCount++;\n                return new MockClob();\n            }\n        };\n\n        statement = new CallableStatementProxyImpl(new ConnectionProxyImpl(null, null, null, 0), mockStmt, \"\", 1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        invokeCount = 0;\n    }\n\n    @Test\n    public void test_getClob() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.callableStatement_getClob(statement, 1);\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getClob_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.callableStatement_getClob(statement, \"1\");\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, 1);\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, \"1\");\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_2() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, 1, Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_3() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, \"1\", Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ClobProxy);\n        assertEquals(1, invokeCount);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainTest_NClob.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockNClob;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.NClobProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxyImpl;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Clob;\nimport java.sql.SQLException;\nimport java.util.Collections;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainTest_NClob {\n    private DruidDataSource dataSource;\n    private StatementProxy statement;\n    private MockResultSet mockResultSet;\n\n    private int invokeCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        ConnectionProxyImpl conn = new ConnectionProxyImpl(dataSource, null, new Properties(), 0);\n        statement = new StatementProxyImpl(conn, null, 1);\n\n        mockResultSet = new MockResultSet(null) {\n            public Object getObject(int columnIndex) throws SQLException {\n                invokeCount++;\n                return new MockNClob();\n            }\n        };\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        invokeCount = 0;\n    }\n\n    @Test\n    public void test_resultSet_getClob() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.resultSet_getClob(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1);\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getClob_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.resultSet_getClob(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\");\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1);\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\");\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_2() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1, Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_3() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\", Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainTest_NClob_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.mock.MockNClob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.NClobProxy;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Clob;\nimport java.sql.SQLException;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainTest_NClob_2 {\n    private DruidDataSource dataSource;\n    private CallableStatementProxy statement;\n\n    private int invokeCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        MockCallableStatement mockStmt = new MockCallableStatement(null, \"\") {\n            @Override\n            public Object getObject(int parameterIndex) throws SQLException {\n                invokeCount++;\n                return new MockNClob();\n            }\n        };\n\n        statement = new CallableStatementProxyImpl(new ConnectionProxyImpl(null, null, null, 0), mockStmt, \"\", 1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        invokeCount = 0;\n    }\n\n    @Test\n    public void test_getClob() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.callableStatement_getClob(statement, 1);\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getClob_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = chain.callableStatement_getClob(statement, \"1\");\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, 1);\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, \"1\");\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_2() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, 1, Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_3() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        Clob clob = (Clob) chain.callableStatement_getObject(statement, \"1\", Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof NClobProxy);\n        assertEquals(1, invokeCount);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainTest_ResultSet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxyImpl;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainTest_ResultSet {\n    private DruidDataSource dataSource;\n    private StatementProxy statement;\n    private MockResultSet mockResultSet;\n\n    private int invokeCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        statement = new StatementProxyImpl(null, null, 1);\n\n        mockResultSet = new MockResultSet(null) {\n            public Object getObject(int columnIndex) throws SQLException {\n                invokeCount++;\n                return new MockResultSet(null);\n            }\n        };\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        invokeCount = 0;\n    }\n\n    @Test\n    public void test_resultSet_getObject() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1);\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\");\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_2() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), 1, Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_resultSet_getObject_3() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.resultSet_getObject(new ResultSetProxyImpl(statement, mockResultSet, 1, null), \"1\", Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterChainTest_ResultSet_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Collections;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterChainTest_ResultSet_2 {\n    private DruidDataSource dataSource;\n    private CallableStatementProxy statement;\n\n    private int invokeCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        ConnectionProxyImpl conn = new ConnectionProxyImpl(dataSource, null, new Properties(), 0);\n        MockCallableStatement mockStmt = new MockCallableStatement(null, \"\") {\n            @Override\n            public Object getObject(int parameterIndex) throws SQLException {\n                invokeCount++;\n                return new MockResultSet(null);\n            }\n        };\n\n        statement = new CallableStatementProxyImpl(conn, mockStmt, \"\", 1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        invokeCount = 0;\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.callableStatement_getObject(statement, 1);\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_1() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.callableStatement_getObject(statement, \"1\");\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_2() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.callableStatement_getObject(statement, 1, Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n\n    @Test\n    public void test_getObject_3() throws Exception {\n        FilterChainImpl chain = new FilterChainImpl(dataSource);\n\n        ResultSet clob = (ResultSet) chain.callableStatement_getObject(statement, \"1\", Collections.<String, Class<?>>emptyMap());\n\n        assertTrue(clob instanceof ResultSetProxy);\n        assertEquals(1, invokeCount);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterDatasourceConnectAndRecycleFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterDatasourceConnectAndRecycleFilterTest {\n    TestFilter filter = new TestFilter();\n    List<Filter> filterList = new ArrayList<Filter>();\n    private DruidDataSource dataSource = new DruidDataSource();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        filterList.add(filter);\n        dataSource.setProxyFilters(filterList);\n        dataSource.setUrl(\"jdbc:mock:\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test() throws Exception {\n        assertEquals(0, filter.getDataSourceConnectCount());\n        assertEquals(0, filter.getDataSourceRecycleCount());\n        Connection conn = dataSource.getConnection();\n        assertEquals(1, filter.getDataSourceConnectCount());\n        assertEquals(0, filter.getDataSourceRecycleCount());\n        conn.close();\n        assertEquals(1, filter.getDataSourceConnectCount());\n        assertEquals(1, filter.getDataSourceRecycleCount());\n    }\n\n    public static class TestFilter extends FilterAdapter {\n        private AtomicLong dataSourceConnectCount = new AtomicLong();\n        private AtomicLong dataSourceRecycleCount = new AtomicLong();\n\n        @Override\n        public void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection connection) throws SQLException {\n            chain.dataSource_recycle(connection);\n            dataSourceRecycleCount.incrementAndGet();\n        }\n\n        @Override\n        public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource,\n                                                              long maxWaitMillis) throws SQLException {\n            dataSourceConnectCount.incrementAndGet();\n            return chain.dataSource_connect(dataSource, maxWaitMillis);\n        }\n\n        public long getDataSourceConnectCount() {\n            return dataSourceConnectCount.get();\n        }\n\n        public long getDataSourceRecycleCount() {\n            return dataSourceRecycleCount.get();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/FilterManagerTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterManager;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.ArrayList;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FilterManagerTest {\n    static {\n        ClassLoader current = Thread.currentThread().getContextClassLoader();\n        try {\n            Thread.currentThread().setContextClassLoader(null);\n\n            assertNotNull(FilterManager.getFilter(\"stat\"));\n        } finally {\n            Thread.currentThread().setContextClassLoader(current);\n        }\n    }\n\n    @Test\n    public void test_instance() throws Exception {\n        new FilterManager();\n    }\n\n    @Test\n    public void test_loadFilter() throws Exception {\n        Exception error = null;\n\n        try {\n            FilterManager.loadFilter(new ArrayList<Filter>(), ErrorFilter.class.getName());\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_loadFilter_2() throws Exception {\n        Exception error = null;\n\n        try {\n            FilterManager.loadFilter(new ArrayList<Filter>(), ErrorFilter.class.getName());\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    public static class ErrorFilter extends FilterAdapter {\n        public ErrorFilter() {\n            throw new RuntimeException();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/MySQL8DateTimeSqlTypeFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.mysql8datetime.MySQL8DateTimeSqlTypeFilter;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.sql.Timestamp;\nimport java.time.LocalDateTime;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * lizongbo\n */\npublic class MySQL8DateTimeSqlTypeFilterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"mysql8DateTime\");\n\n        dataSource.setDriver(new MockDriver() {\n            public ResultSet createResultSet(MockPreparedStatement stmt) {\n                return new MyResultSet(stmt);\n            }\n\n            public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n                return new MyResultSet(stmt);\n            }\n        });\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_mysql8datetime() throws Exception {\n        assertTrue(dataSource.isInited());\n\n        MySQL8DateTimeSqlTypeFilter filter = (MySQL8DateTimeSqlTypeFilter) dataSource.getProxyFilters().get(0);\n\n        DruidPooledConnection conn = dataSource.getConnection();\n\n        final String PARAM_VALUE = \"中国\";\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        stmt.setString(1, PARAM_VALUE);\n\n        ResultSet rs = stmt.executeQuery();\n        MyResultSet rawRs = rs.unwrap(MyResultSet.class);\n\n        rs.next();\n        Object obj1 = rs.getObject(1);\n        System.out.println(obj1.getClass() + \"|\" + obj1);\n        assertEquals(Timestamp.class, obj1.getClass());\n        Object obj2 = rs.getObject(\"cc\");\n        System.out.println(obj2.getClass() + \"|\" + obj2);\n        assertEquals(Timestamp.class, obj2.getClass());\n\n        rs.close();\n        stmt.close();\n\n        conn.close();\n    }\n\n    public static class MyResultSet extends MockResultSet {\n        public MyResultSet(Statement statement) {\n            super(statement);\n        }\n\n        @Override\n        public Object getObject(int index) throws SQLException {\n            return LocalDateTime.now();\n        }\n\n        @Override\n        public Object getObject(String columnLabel) throws SQLException {\n            return LocalDateTime.now();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/ReuseStatFilterTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\npublic class ReuseStatFilterTest {\n    private DruidDataSource dataSourceA;\n    private DruidDataSource dataSourceB;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSourceA = new DruidDataSource();\n        dataSourceB = new DruidDataSource();\n\n        dataSourceA.setUrl(\"jdbc:mock:xxx_A\");\n        dataSourceB.setUrl(\"jdbc:mock:xxx_B\");\n\n        StatFilter filter = new StatFilter();\n\n        dataSourceA.getProxyFilters().add(filter);\n        dataSourceB.getProxyFilters().add(filter);\n\n        dataSourceA.init();\n        dataSourceB.init();\n    }\n\n    @Test\n    public void test_execute() throws Exception {\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSourceA);\n        JdbcUtils.close(dataSourceB);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/Slf4jFilterTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.logging.Slf4jLogFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Slf4jFilterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"slf4j\");\n        dataSource.setDbType(\"mysql\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_slf4j() throws Exception {\n        dataSource.init();\n\n        Slf4jLogFilter filter = dataSource.unwrap(Slf4jLogFilter.class);\n        assertNotNull(filter);\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterAfterResetTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterAfterResetTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        final String sql = \"SELECT 1\";\n        assertTrue(dataSource.isInited());\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertNull(sqlStat);\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n\n            sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n            assertNotNull(sqlStat);\n\n            assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum(), \"first failed\");\n\n            rs.close();\n\n            assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum(), \"second failed\");\n\n            stmt.close();\n\n            conn.close();\n\n            assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum());\n        }\n\n        JdbcStatManager.getInstance().reset();\n\n        assertFalse(sqlStat.isRemoved());\n         JdbcStatManager.getInstance().reset();\n         assertTrue(sqlStat.isRemoved());\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            conn.close();\n        }\n\n        assertNotSame(sqlStat, dataSource.getDataSourceStat().getSqlStat(sql));\n\n        {\n            assertEquals(0, sqlStat.getExecuteAndResultHoldTimeHistogramSum());\n        }\n\n        sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterBuildSlowParameterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.mock.MockBlob;\nimport com.alibaba.druid.mock.MockClob;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockNClob;\nimport com.alibaba.druid.mock.MockRowId;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.nutz.lang.util.ByteInputStream;\n\nimport java.math.BigDecimal;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Time;\nimport java.sql.Types;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterBuildSlowParameterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setConnectionProperties(\"druid.stat.slowSqlMillis=1\");\n\n        MockDriver driver = new MockDriver() {\n            public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n                try {\n                    Thread.sleep(2);\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n                return super.executeQuery(stmt, sql);\n            }\n        };\n\n        dataSource.setDriver(driver);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_buildSlowSql() throws Exception {\n        long currentMillis = System.currentTimeMillis();\n        String sql = \"select ?, ?, ?, ?, ?\";\n\n        SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        Date date = new Date(System.currentTimeMillis());\n        String dateText = dateFormat.format(date);\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            stmt.setBoolean(1, true);\n            stmt.setInt(2, 123);\n            stmt.setLong(3, 10001);\n            stmt.setTimestamp(4, new java.sql.Timestamp(currentMillis));\n            stmt.setDate(5, new java.sql.Date(currentMillis));\n\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n\n            stmt.close();\n\n            conn.close();\n\n            // //////\n\n            JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n            assertNotNull(sqlStat);\n\n            String slowParameters = sqlStat.getLastSlowParameters();\n            assertNotNull(slowParameters);\n\n            List<Object> parameters = (List<Object>) JSONUtils.parse(slowParameters);\n            assertEquals(5, parameters.size());\n\n            assertEquals(true, parameters.get(0));\n            assertEquals(123, parameters.get(1));\n            assertEquals(10001, parameters.get(2));\n            assertEquals(dateText, parameters.get(3));\n            assertEquals(dateText, parameters.get(4));\n        }\n\n        currentMillis = System.currentTimeMillis();\n        date = new Date(System.currentTimeMillis());\n        dateText = dateFormat.format(date);\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            stmt.setBoolean(1, false);\n            stmt.setInt(2, 234);\n            stmt.setLong(3, 10002);\n            stmt.setTimestamp(4, new java.sql.Timestamp(currentMillis));\n            stmt.setDate(5, new java.sql.Date(currentMillis));\n\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n\n            stmt.close();\n\n            conn.close();\n\n            // //////\n\n            JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n            assertNotNull(sqlStat);\n\n            String slowParameters = sqlStat.getLastSlowParameters();\n            assertNotNull(slowParameters);\n\n            List<Object> parameters = (List<Object>) JSONUtils.parse(slowParameters);\n            assertEquals(5, parameters.size());\n\n            assertEquals(false, parameters.get(0));\n            assertEquals(234, parameters.get(1));\n            assertEquals(10002, parameters.get(2));\n            assertEquals(dateText, parameters.get(3));\n            assertEquals(dateText, parameters.get(4));\n        }\n\n        {\n            StringBuilder buf = new StringBuilder();\n            for (int i = 0; i < 10; ++i) {\n                buf.append(\"abcdefghijklmnABCDEFGHIJKLMN1234567890!@#$%^&*(\");\n            }\n\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            stmt.setNull(1, Types.VARCHAR);\n            stmt.setString(2, buf.toString());\n            stmt.setClob(3, new MockClob());\n            stmt.setNClob(4, new MockNClob());\n            stmt.setBlob(5, new MockBlob());\n\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n\n            stmt.close();\n\n            conn.close();\n\n            // //////\n\n            JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n            assertNotNull(sqlStat);\n\n            String slowParameters = sqlStat.getLastSlowParameters();\n            assertNotNull(slowParameters);\n\n            List<Object> parameters = (List<Object>) JSONUtils.parse(slowParameters);\n            assertEquals(5, parameters.size());\n\n            assertEquals(null, parameters.get(0));\n            assertEquals(buf.substring(0, 97) + \"...\", parameters.get(1));\n            assertEquals(\"<Clob>\", parameters.get(2));\n            assertEquals(\"<NClob>\", parameters.get(3));\n            assertEquals(\"<Blob>\", parameters.get(4));\n        }\n        {\n            StringBuilder buf = new StringBuilder();\n            for (int i = 0; i < 10; ++i) {\n                buf.append(\"中国abcdefghijklmnABCDEFGHIJKLMN1234567890!@#$%^&*(\");\n            }\n\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            stmt.setBinaryStream(1, new ByteInputStream(new byte[0]));\n            stmt.setString(2, buf.toString());\n            stmt.setTime(3, new Time(currentMillis));\n            stmt.setBigDecimal(4, new BigDecimal(\"56789.123\"));\n            stmt.setRowId(5, new MockRowId());\n\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n\n            stmt.close();\n\n            conn.close();\n\n            // //////\n\n            JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n            assertNotNull(sqlStat);\n\n            String slowParameters = sqlStat.getLastSlowParameters();\n            assertNotNull(slowParameters);\n\n            List<Object> parameters = (List<Object>) JSONUtils.parse(slowParameters);\n            assertEquals(5, parameters.size());\n\n            assertEquals(\"<InputStream>\", parameters.get(0));\n            assertEquals(buf.substring(0, 97) + \"...\", parameters.get(1));\n            assertEquals(dateText, parameters.get(2));\n            assertEquals(56789.123, parameters.get(3));\n            assertEquals(\"<com.alibaba.druid.mock.MockRowId>\", parameters.get(4));\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterClobTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.mock.MockClob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ClobProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterClobTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_clob() throws Exception {\n        String sql = \"select ?\";\n\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n\n        MockClob clob = new MockClob();\n        stmt.setClob(1, clob);\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        assertTrue(rs.getObject(1) instanceof ClobProxy);\n        rs.close();\n\n        stmt.close();\n\n        conn.close();\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n        assertNotNull(sqlStat);\n\n        assertEquals(1, sqlStat.getClobOpenCount());\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getClobOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterExecErrorTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterExecErrorTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)\n                    throws SQLException {\n                throw new SQLException();\n            }\n        });\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getReadStringLength());\n\n        try {\n            stmt.executeQuery();\n        } catch (SQLException eror) {\n        } finally {\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n\n        assertEquals(1, sqlStat.getErrorCount());\n        assertEquals(0, sqlStat.getRunningCount());\n\n        sqlStat.reset();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterExecuteFirstResultSetTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterExecuteFirstResultSetTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n\n        MockDriver driver = new MockDriver() {\n            public MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql) {\n                return new MyMockPreparedStatement(conn, sql);\n            }\n        };\n\n        dataSource.setDriver(driver);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        assertTrue(dataSource.isInited());\n        final String sql = \"select 1\";\n\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        boolean firstResult = stmt.execute();\n        assertTrue(firstResult);\n\n        ResultSet rs = stmt.getResultSet();\n        rs.next();\n        rs.close();\n\n        stmt.close();\n\n        conn.close();\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(1, sqlStat.getHistogramSum());\n\n        assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum());\n    }\n\n    static class MyMockPreparedStatement extends MockPreparedStatement {\n        public MyMockPreparedStatement(MockConnection conn, String sql) {\n            super(conn, sql);\n        }\n\n        public boolean execute() throws SQLException {\n            return true;\n        }\n\n        public ResultSet getResultSet() throws SQLException {\n            return getConnection().getDriver().executeQuery(this, getSql());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterExecuteTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterExecuteTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n\n        MockDriver driver = new MockDriver() {\n            public MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql) {\n                return new MyMockPreparedStatement(conn, sql);\n            }\n        };\n\n        dataSource.setDriver(driver);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        assertTrue(dataSource.isInited());\n        final String sql = \"update x\";\n\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n\n        assertEquals(0, dataSource.getDataSourceStat().getSqlStat(sql).getExecuteAndResultHoldTimeHistogramSum());\n\n        boolean firstResult = stmt.execute();\n        assertFalse(firstResult);\n\n        stmt.close();\n\n        conn.close();\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(1, sqlStat.getHistogramSum());\n\n        assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum());\n    }\n\n    static class MyMockPreparedStatement extends MockPreparedStatement {\n        public MyMockPreparedStatement(MockConnection conn, String sql) {\n            super(conn, sql);\n        }\n\n        public boolean execute() throws SQLException {\n            return false;\n        }\n\n        public int getUpdateCount() throws SQLException {\n            return 100;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterOpenBlobCountTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.mock.MockBlob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Blob;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterOpenBlobCountTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return new MockBlob();\n            }\n\n            @Override\n            public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, String columnLabel)\n                    throws SQLException {\n                return new MockBlob();\n            }\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getBlobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getBlob(1);\n        rs.getBlob(2);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(2, sqlStat.getBlobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getBlobOpenCount());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getBlobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getBlob(\"1\");\n        rs.getBlob(\"2\");\n        rs.getBlob(\"3\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(3, sqlStat.getBlobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getBlobOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterOpenBlobCountTest2.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.mock.MockBlob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterOpenBlobCountTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return new MockBlob();\n            }\n\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel)\n                    throws SQLException {\n                return new MockBlob();\n            }\n\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n                return new MockBlob();\n            }\n\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n                return new MockBlob();\n            }\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getBlobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(1);\n        rs.getObject(2);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(2, sqlStat.getBlobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getBlobOpenCount());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getBlobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(\"1\");\n        rs.getObject(\"2\");\n        rs.getObject(\"3\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(3, sqlStat.getBlobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getBlobOpenCount());\n    }\n\n    @Test\n    public void test_stat_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getBlobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(1, Collections.<String, Class<?>>emptyMap());\n        rs.getObject(2, Collections.<String, Class<?>>emptyMap());\n        rs.getObject(3, Collections.<String, Class<?>>emptyMap());\n        rs.getObject(4, Collections.<String, Class<?>>emptyMap());\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(4, sqlStat.getBlobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getBlobOpenCount());\n    }\n\n    @Test\n    public void test_stat_4() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getBlobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(\"1\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"2\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"3\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"4\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"5\", Collections.<String, Class<?>>emptyMap());\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(5, sqlStat.getBlobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getBlobOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterOpenClobCountTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.mock.MockClob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ClobProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterOpenClobCountTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public Clob resultSet_getClob(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return new ClobProxyImpl(result.getStatementProxy().getConnectionProxy().getDirectDataSource(),\n                        result.getStatementProxy().getConnectionProxy(), new MockClob());\n            }\n\n            @Override\n            public Clob resultSet_getClob(FilterChain chain, ResultSetProxy result, String columnLabel)\n                    throws SQLException {\n                return new ClobProxyImpl(result.getStatementProxy().getConnectionProxy().getDirectDataSource(),\n                        result.getStatementProxy().getConnectionProxy(), new MockClob());\n            }\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getClobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getClob(1);\n        rs.getClob(2);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(2, sqlStat.getClobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getClobOpenCount());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getClobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getClob(\"1\");\n        rs.getClob(\"2\");\n        rs.getClob(\"3\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(3, sqlStat.getClobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getClobOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterOpenClobCountTest2.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.mock.MockClob;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ClobProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterOpenClobCountTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return new ClobProxyImpl(result.getStatementProxy().getConnectionProxy().getDirectDataSource(),\n                        result.getStatementProxy().getConnectionProxy(), new MockClob());\n            }\n\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel)\n                    throws SQLException {\n                return new ClobProxyImpl(result.getStatementProxy().getConnectionProxy().getDirectDataSource(),\n                        result.getStatementProxy().getConnectionProxy(), new MockClob());\n            }\n\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n                return new ClobProxyImpl(result.getStatementProxy().getConnectionProxy().getDirectDataSource(),\n                        result.getStatementProxy().getConnectionProxy(), new MockClob());\n            }\n\n            @Override\n            public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnIndex,\n                                              java.util.Map<String, Class<?>> map) throws SQLException {\n                return new ClobProxyImpl(result.getStatementProxy().getConnectionProxy().getDirectDataSource(),\n                        result.getStatementProxy().getConnectionProxy(), new MockClob());\n            }\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getClobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(1);\n        rs.getObject(2);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(2, sqlStat.getClobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getClobOpenCount());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getClobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(\"1\");\n        rs.getObject(\"2\");\n        rs.getObject(\"3\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(3, sqlStat.getClobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getClobOpenCount());\n    }\n\n    @Test\n    public void test_stat_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getClobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(1, Collections.<String, Class<?>>emptyMap());\n        rs.getObject(2, Collections.<String, Class<?>>emptyMap());\n        rs.getObject(3, Collections.<String, Class<?>>emptyMap());\n        rs.getObject(4, Collections.<String, Class<?>>emptyMap());\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(4, sqlStat.getClobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getClobOpenCount());\n    }\n\n    @Test\n    public void test_stat_4() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getClobOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getObject(\"1\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"2\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"3\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"4\", Collections.<String, Class<?>>emptyMap());\n        rs.getObject(\"5\", Collections.<String, Class<?>>emptyMap());\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(5, sqlStat.getClobOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getClobOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterOpenInputStreamCountTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.ByteArrayInputStream;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterOpenInputStreamCountTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public java.io.InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return new ByteArrayInputStream(new byte[0]);\n            }\n\n            @Override\n            public java.io.InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n                    throws SQLException {\n                return new ByteArrayInputStream(new byte[0]);\n            }\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getBinaryStream(1);\n        rs.getBinaryStream(2);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(2, sqlStat.getInputStreamOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getBinaryStream(\"1\");\n        rs.getBinaryStream(\"2\");\n        rs.getBinaryStream(\"3\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(3, sqlStat.getInputStreamOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterOpenInputStreamCountTest2.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.ByteArrayInputStream;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterOpenInputStreamCountTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public java.io.InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result,\n                                                                int columnIndex) throws SQLException {\n                return new ByteArrayInputStream(new byte[0]);\n            }\n\n            @Override\n            public java.io.InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result,\n                                                                String columnLabel) throws SQLException {\n                return new ByteArrayInputStream(new byte[0]);\n            }\n\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getAsciiStream(1);\n        rs.getAsciiStream(2);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(2, sqlStat.getInputStreamOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getAsciiStream(\"1\");\n        rs.getAsciiStream(\"2\");\n        rs.getAsciiStream(\"3\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(3, sqlStat.getInputStreamOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getInputStreamOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterOpenReaderCountTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.nutz.lang.stream.StringReader;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterOpenReaderCountTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public java.io.Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return new StringReader(\"\");\n            }\n\n            @Override\n            public java.io.Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel)\n                    throws SQLException {\n                return new StringReader(\"\");\n            }\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getReaderOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getCharacterStream(1);\n        rs.getCharacterStream(2);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(2, sqlStat.getReaderOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getReaderOpenCount());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getReaderOpenCount());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getCharacterStream(\"1\");\n        rs.getCharacterStream(\"2\");\n        rs.getCharacterStream(\"3\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(3, sqlStat.getReaderOpenCount());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getReaderOpenCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadBytesLengthTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterReadBytesLengthTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return new byte[6];\n            }\n\n            @Override\n            public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, String columnIndex)\n                    throws SQLException {\n                return new byte[7];\n            }\n        });\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getReadStringLength());\n        assertEquals(0, sqlStat.getReadBytesLength());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getBytes(1);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(0, sqlStat.getReadStringLength());\n        assertEquals(6, sqlStat.getReadBytesLength());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getReadStringLength());\n        assertEquals(0, sqlStat.getReadBytesLength());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getReadStringLength());\n        assertEquals(0, sqlStat.getReadBytesLength());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getBytes(\"1\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(0, sqlStat.getReadStringLength());\n        assertEquals(7, sqlStat.getReadBytesLength());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getReadStringLength());\n        assertEquals(0, sqlStat.getReadBytesLength());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterReadStringLengthTest.java",
    "content": "package com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterReadStringLengthTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public String resultSet_getString(FilterChain chain, ResultSetProxy result, int columnIndex)\n                    throws SQLException {\n                return \"123456\";\n            }\n\n            @Override\n            public String resultSet_getString(FilterChain chain, ResultSetProxy result, String columnIndex)\n                    throws SQLException {\n                return \"1234567\";\n            }\n        });\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getReadStringLength());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getString(1);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(6, sqlStat.getReadStringLength());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getReadStringLength());\n    }\n\n    @Test\n    public void test_stat_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 'x'\";\n        PreparedStatement stmt = conn.prepareStatement(\"select 'x'\");\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertEquals(0, sqlStat.getReadStringLength());\n\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.getString(\"1\");\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(7, sqlStat.getReadStringLength());\n\n        sqlStat.reset();\n        assertEquals(0, sqlStat.getReadStringLength());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/StatFilterResultSetMultiCloseTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterResultSetMultiCloseTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n\n        dataSource.init();\n    }\n\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    public void test_stat() throws Exception {\n        final String sql = \"SELECT 1\";\n        assertTrue(dataSource.isInited());\n\n        JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n\n        assertNull(sqlStat);\n\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.close();\n\n        sqlStat = dataSource.getDataSourceStat().getSqlStat(sql);\n        assertNotNull(sqlStat);\n\n        assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum(), \"first failed\");\n\n        rs.close();\n\n        assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum(), \"second failed\");\n\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(1, sqlStat.getExecuteAndResultHoldTimeHistogramSum());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigFilterTest.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.config.ConfigFileGenerator;\nimport com.alibaba.druid.filter.config.ConfigFilter;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\n/**\n * @author Jonas Yang\n */\npublic class ConfigFilterTest extends ConfigFileGenerator {\n    String encryptedString = \"OJfUm6WCHi7EuXqE6aEc+Po2xFrAGBeSNy8O2jWhV2FTG8/5kbRRr2rjNKhptlevm/03Y0048P7h88gdUOXAYg==\";\n\n    @Test\n    public void testInitRemoteConfigFile() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setFilters(\"config\");\n        dataSource.setConnectionProperties(\"config.file=file://\" + this.filePath);\n        try {\n            dataSource.init();\n\n            assertEquals(\"test1\", dataSource.getUsername(), \"The username is \" + dataSource.getUsername());\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void testInitRemoteConfigFileBySystemProperty() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setFilters(\"config\");\n\n        System.setProperty(ConfigFilter.SYS_PROP_CONFIG_FILE, \"file://\" + this.filePath);\n        try {\n            dataSource.init();\n\n            assertEquals(\"test1\", dataSource.getUsername(), \"The username is \" + dataSource.getUsername());\n        } finally {\n            System.clearProperty(ConfigFilter.SYS_PROP_CONFIG_FILE);\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void testInitInvalidRemoteConfigFile() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setFilters(\"config\");\n        dataSource.setConnectionProperties(\"config.file=abcdef\");\n\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (IllegalArgumentException e) {\n            error = e;\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void testInitDecrypt() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setDriver(MockDriver.instance);\n        dataSource.setUrl(\"\");\n        dataSource.setUsername(\"test\");\n        dataSource.setPassword(encryptedString);\n        dataSource.setFilters(\"config\");\n        dataSource.setConnectionProperties(\"config.decrypt=true\");\n\n        try {\n            dataSource.init();\n            assertEquals(\"xiaoyu\", dataSource.getPassword(), \"The password is \" + dataSource.getPassword() + \", is not xiaoyu\");\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void testInitRemoteConfigAndDecrypt() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setFilters(\"config\");\n        dataSource.setConnectionProperties(\"config.decrypt=true;config.file=\" + \"file://\" + this.filePath);\n        try {\n            dataSource.init();\n\n            assertEquals(\"xiaoyu\", dataSource.getPassword(), \"The password is \" + dataSource.getPassword());\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void testNormalInit() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:oracle:thin:@\");\n\n        try {\n            dataSource.init();\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void testInvalidInit() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setDriver(MockDriver.instance);\n        dataSource.setFilters(\"config\");\n        dataSource.setConnectionProperties(\"config.file=abcdefeg\");\n\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (IllegalArgumentException e) {\n            error = e;\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigFilterTest1.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.config.ConfigFilter;\nimport com.alibaba.druid.filter.config.ConfigTools;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigFilterTest1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"config\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_decrypt() throws Exception {\n        String plainPassword = \"abcdefg1234567890\";\n\n        dataSource.setPassword(ConfigTools.encrypt(plainPassword));\n\n        assertFalse(plainPassword.equals(dataSource.getPassword()));\n\n        dataSource.addConnectionProperty(ConfigFilter.CONFIG_DECRYPT, \"true\");\n\n        dataSource.init();\n\n        assertEquals(plainPassword, dataSource.getPassword());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigFilterTest2.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.config.ConfigFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigFilterTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setFilters(\"config\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_decrypt() throws Exception {\n        dataSource.addConnectionProperty(ConfigFilter.CONFIG_FILE, \"bvt/config/config-0.properties\");\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        dataSource.init();\n\n        assertEquals(\"jdbc:mock:config-0\", dataSource.getUrl());\n        assertEquals(false, dataSource.isTestOnBorrow());\n        assertEquals(10, dataSource.getMaxActive());\n    }\n\n    @Test\n    public void test_decrypt1() throws Exception {\n        dataSource.addConnectionProperty(ConfigFilter.CONFIG_FILE, \"bvt/config/config-1.properties\");\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        dataSource.init();\n\n        assertEquals(\"jdbc:mock:config-1\", dataSource.getUrl());\n        assertEquals(false, dataSource.isTestOnBorrow());\n        assertEquals(11, dataSource.getMaxActive());\n        assertEquals(3, dataSource.getProxyFilters().size());\n    }\n\n    @Test\n    public void test_decrypt2() throws Exception {\n        dataSource.addConnectionProperty(ConfigFilter.CONFIG_FILE, \"bvt/config/config-2.properties\");\n        dataSource.addConnectionProperty(ConfigFilter.CONFIG_DECRYPT, \"true\");\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        dataSource.init();\n\n        assertEquals(\"jdbc:mock:config-2\", dataSource.getUrl());\n        assertEquals(false, dataSource.isTestOnBorrow());\n        assertEquals(12, dataSource.getMaxActive());\n        assertEquals(\"abcdefg1234567890\", dataSource.getPassword());\n    }\n\n    @Test\n    public void test_decrypt3() throws Exception {\n        dataSource.addConnectionProperty(ConfigFilter.CONFIG_FILE, \"bvt/config/config-3.properties\");\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        dataSource.init();\n\n        assertEquals(\"jdbc:mock:config-3\", dataSource.getUrl());\n        assertEquals(false, dataSource.isTestOnBorrow());\n        assertEquals(13, dataSource.getMaxActive());\n        assertEquals(\"abcdefg1234567890\", dataSource.getPassword());\n    }\n\n    @Test\n    public void test_decrypt4() throws Exception {\n        String file = Thread.currentThread().getContextClassLoader().getResource(\"bvt/config/config-3.properties\").getFile();\n        dataSource.addConnectionProperty(ConfigFilter.CONFIG_FILE, \"file://\" + file);\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        dataSource.init();\n\n        assertEquals(\"jdbc:mock:config-3\", dataSource.getUrl());\n        assertEquals(false, dataSource.isTestOnBorrow());\n        assertEquals(13, dataSource.getMaxActive());\n        assertEquals(\"abcdefg1234567890\", dataSource.getPassword());\n    }\n\n    @Test\n    public void test_decrypt5() throws Exception {\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        try {\n            String file = Thread.currentThread().getContextClassLoader().getResource(\"bvt/config/config-2.properties\").getFile();\n            System.setProperty(ConfigFilter.SYS_PROP_CONFIG_FILE, \"file://\" + file);\n            System.setProperty(ConfigFilter.SYS_PROP_CONFIG_DECRYPT, \"true\");\n\n            dataSource.init();\n\n            assertEquals(\"jdbc:mock:config-2\", dataSource.getUrl());\n            assertEquals(false, dataSource.isTestOnBorrow());\n            assertEquals(12, dataSource.getMaxActive());\n            assertEquals(\"abcdefg1234567890\", dataSource.getPassword());\n        } finally {\n            System.clearProperty(ConfigFilter.SYS_PROP_CONFIG_FILE);\n            System.clearProperty(ConfigFilter.SYS_PROP_CONFIG_DECRYPT);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigFilterTest3.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.config.ConfigFilter;\nimport com.alibaba.druid.filter.config.ConfigTools;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigFilterTest3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setFilters(\"config\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        String password = \"abcdefg1234\";\n        String[] keys = ConfigTools.genKeyPair(1024);\n\n        File file = File.createTempFile(\"MyTest\", Long.toString(System.nanoTime()));\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xx0\");\n        properties.put(DruidDataSourceFactory.PROP_USERNAME, \"sa\");\n        properties.put(DruidDataSourceFactory.PROP_PASSWORD, ConfigTools.encrypt(keys[0], password));\n        properties.put(ConfigFilter.CONFIG_DECRYPT, \"true\");\n        properties.store(new FileOutputStream(file), \"\");\n\n        dataSource.getConnectProperties().put(ConfigFilter.CONFIG_KEY, keys[1]);\n        dataSource.getConnectProperties().put(ConfigFilter.CONFIG_FILE, \"file://\" + file.getAbsolutePath());\n\n        dataSource.init();\n\n        assertEquals(\"jdbc:mock:xx0\", dataSource.getUrl());\n        assertEquals(\"sa\", dataSource.getUsername());\n        assertEquals(password, dataSource.getPassword());\n    }\n\n    @Test\n    public void test_sys_property() throws Exception {\n        String password = \"abcdefg1234\";\n        String[] keys = ConfigTools.genKeyPair(1024);\n\n        File file = File.createTempFile(\"MyTest\", Long.toString(System.nanoTime()));\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xx0\");\n        properties.put(DruidDataSourceFactory.PROP_USERNAME, \"sa\");\n        properties.put(DruidDataSourceFactory.PROP_PASSWORD, ConfigTools.encrypt(keys[0], password));\n        properties.put(ConfigFilter.CONFIG_DECRYPT, \"true\");\n        properties.store(new FileOutputStream(file), \"\");\n\n        System.getProperties().put(ConfigFilter.SYS_PROP_CONFIG_KEY, keys[1]);\n        System.getProperties().put(ConfigFilter.SYS_PROP_CONFIG_FILE, \"file://\" + file.getAbsolutePath());\n\n        try {\n            dataSource.init();\n\n            assertEquals(\"jdbc:mock:xx0\", dataSource.getUrl());\n            assertEquals(\"sa\", dataSource.getUsername());\n            assertEquals(password, dataSource.getPassword());\n        } finally {\n            System.clearProperty(ConfigFilter.SYS_PROP_CONFIG_KEY);\n            System.clearProperty(ConfigFilter.SYS_PROP_CONFIG_FILE);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigFilterTest4.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.config.ConfigFilter;\nimport com.alibaba.druid.filter.config.ConfigTools;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigFilterTest4 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setFilters(\"config\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        String password = \"abcdefg1234\";\n        String[] keys = ConfigTools.genKeyPair(1024);\n\n        File file = File.createTempFile(\"MyTest\", Long.toString(System.nanoTime()));\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xx0\");\n        properties.put(DruidDataSourceFactory.PROP_USERNAME, \"sa\");\n        properties.put(DruidDataSourceFactory.PROP_PASSWORD, ConfigTools.encrypt(keys[0], password));\n        properties.put(ConfigFilter.CONFIG_DECRYPT, \"true\");\n        properties.store(new FileOutputStream(file), \"\");\n\n        dataSource.getConnectProperties().put(ConfigFilter.CONFIG_KEY, keys[1]);\n        dataSource.getConnectProperties().put(ConfigFilter.CONFIG_FILE, \"file://\" + file.getAbsolutePath());\n\n        dataSource.init();\n\n        assertEquals(\"jdbc:mock:xx0\", dataSource.getUrl());\n        assertEquals(\"sa\", dataSource.getUsername());\n        assertEquals(password, dataSource.getPassword());\n    }\n\n    @Test\n    public void test_sys_property() throws Exception {\n        String password = \"abcdefg1234\";\n        String[] keys = ConfigTools.genKeyPair(1024);\n\n        File file = File.createTempFile(\"MyTest\", Long.toString(System.nanoTime()));\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xx0\");\n        properties.put(DruidDataSourceFactory.PROP_USERNAME, \"sa\");\n        properties.put(DruidDataSourceFactory.PROP_PASSWORD, ConfigTools.encrypt(keys[0], password));\n        properties.put(ConfigFilter.CONFIG_DECRYPT, \"true\");\n        properties.store(new FileOutputStream(file), \"\");\n\n        System.getProperties().put(ConfigFilter.SYS_PROP_CONFIG_KEY, keys[1]);\n        System.getProperties().put(ConfigFilter.SYS_PROP_CONFIG_FILE, \"file://\" + file.getAbsolutePath());\n\n        try {\n            dataSource.init();\n\n            assertEquals(\"jdbc:mock:xx0\", dataSource.getUrl());\n            assertEquals(\"sa\", dataSource.getUsername());\n            assertEquals(password, dataSource.getPassword());\n        } finally {\n            System.clearProperty(ConfigFilter.SYS_PROP_CONFIG_KEY);\n            System.clearProperty(ConfigFilter.SYS_PROP_CONFIG_FILE);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigFilterTest5.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.config.ConfigFilter;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigFilterTest5 {\n    @Test\n    public void test_loadClassPath() throws Exception {\n        ConfigFilter filter = new ConfigFilter();\n        assertNotNull(filter.loadConfig(\"classpath:bvt/config/config-0.properties\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigFilterTest6.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.config.ConfigFilter;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Driver;\nimport java.util.List;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigFilterTest6 {\n    @Test\n    public void testInitFastFail() {\n        ConfigFilter filter = new ConfigFilter();\n        IllegalArgumentException exception =\n                assertThrows(IllegalArgumentException.class, () -> filter.init(new DataSourceProxyImpl()));\n        assertEquals(\"ConfigLoader only support DruidDataSource\", exception.getMessage());\n    }\n\n    static class DataSourceProxyImpl implements DataSourceProxy {\n        @Override\n        public JdbcDataSourceStat getDataSourceStat() {\n            return null;\n        }\n\n        @Override\n        public long getDataSourceId() {\n            return 0;\n        }\n\n        @Override\n        public String getName() {\n            return null;\n        }\n\n        @Override\n        public String getDbType() {\n            return null;\n        }\n\n        @Override\n        public Driver getRawDriver() {\n            return null;\n        }\n\n        @Override\n        public String getUrl() {\n            return null;\n        }\n\n        @Override\n        public String getRawJdbcUrl() {\n            return null;\n        }\n\n        @Override\n        public List<Filter> getProxyFilters() {\n            return null;\n        }\n\n        @Override\n        public long createConnectionId() {\n            return 0;\n        }\n\n        @Override\n        public long createStatementId() {\n            return 0;\n        }\n\n        @Override\n        public long createResultSetId() {\n            return 0;\n        }\n\n        @Override\n        public long createMetaDataId() {\n            return 0;\n        }\n\n        @Override\n        public long createTransactionId() {\n            return 0;\n        }\n\n        @Override\n        public Properties getConnectProperties() {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/config/ConfigToolsTest.java",
    "content": "package com.alibaba.druid.bvt.filter.config;\n\nimport com.alibaba.druid.filter.config.ConfigTools;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Random;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigToolsTest {\n    @Test\n    public void test_0() throws Exception {\n        String plainText = \"abcdef\";\n        String cipherText = ConfigTools.encrypt(plainText);\n        String decipherText = ConfigTools.decrypt(cipherText);\n\n        assertEquals(plainText, decipherText);\n    }\n\n    @Test\n    public void test_genKeys() throws Exception {\n        String plainText = Long.toString(new Random().nextLong());\n        String[] keys = ConfigTools.genKeyPair(512);\n\n        String cipherText = ConfigTools.encrypt(keys[0], plainText);\n        assertEquals(plainText, ConfigTools.decrypt(keys[1], cipherText));\n    }\n\n    @Test\n    public void test_genKeys1024() throws Exception {\n        String plainText = Long.toString(new Random().nextLong());\n        String[] keys = ConfigTools.genKeyPair(1024);\n\n        String cipherText = ConfigTools.encrypt(keys[0], plainText);\n        assertEquals(plainText, ConfigTools.decrypt(keys[1], cipherText));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest.java",
    "content": "package com.alibaba.druid.bvt.filter.log;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\npublic class LogFilterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:derby:classpath:petstore-db\");\n        dataSource.setFilters(\"log4j\");\n    }\n\n    @Test\n    public void test_select() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        for (int i = 0; i < 10; ++i) {\n            ResultSet rs = stmt.executeQuery(\"SELECT * FROM ITEM WHERE LISTPRICE > 10\");\n            rs.close();\n        }\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest2.java",
    "content": "package com.alibaba.druid.bvt.filter.log;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\npublic class LogFilterTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:derby:classpath:petstore-db\");\n        dataSource.setFilters(\"log4j\");\n    }\n\n    @Test\n    public void test_select() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT * FROM ITEM WHERE LISTPRICE > 10\");\n\n        for (int i = 0; i < 10; ++i) {\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n        }\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest3.java",
    "content": "package com.alibaba.druid.bvt.filter.log;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\npublic class LogFilterTest3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        System.setProperty(\"druid.log.stmt.executableSql\", \"true\");\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:derby:classpath:petstore-db\");\n        dataSource.setFilters(\"log4j,slf4j\");\n    }\n\n    @Test\n    public void test_select() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT * FROM ITEM WHERE LISTPRICE > ?\");\n        stmt.setInt(1, 10);\n\n        for (int i = 0; i < 10; ++i) {\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n        }\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        System.clearProperty(\"druid.log.stmt.executableSql\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest4.java",
    "content": "package com.alibaba.druid.bvt.filter.log;\n\nimport com.alibaba.druid.filter.logging.Log4jFilter;\nimport com.alibaba.druid.filter.logging.LogFilter;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LogFilterTest4 {\n    @Test\n    public void test_properties() throws Exception {\n        LogFilter filter = new Log4jFilter();\n\n        assertEquals(true, filter.isConnectionLogEnabled());\n        assertEquals(true, filter.isStatementLogEnabled());\n        assertEquals(false, filter.isStatementExecutableSqlLogEnable());\n        assertEquals(true, filter.isResultSetLogEnabled());\n    }\n\n    @Test\n    public void test_properties_1() throws Exception {\n        System.setProperty(\"druid.log.conn\", \"false\");\n        System.setProperty(\"druid.log.stmt\", \"false\");\n        System.setProperty(\"druid.log.rs\", \"false\");\n        System.setProperty(\"druid.log.stmt.executableSql\", \"true\");\n\n        try {\n            LogFilter filter = new Log4jFilter();\n\n            assertEquals(false, filter.isConnectionLogEnabled());\n            assertEquals(false, filter.isStatementLogEnabled());\n            assertEquals(true, filter.isStatementExecutableSqlLogEnable());\n            assertEquals(false, filter.isResultSetLogEnabled());\n\n            Properties properties = new Properties();\n            properties.setProperty(\"druid.log.conn\", \"true\");\n            properties.setProperty(\"druid.log.stmt\", \"true\");\n            properties.setProperty(\"druid.log.rs\", \"true\");\n            properties.setProperty(\"druid.log.stmt.executableSql\", \"false\");\n\n            filter.configFromProperties(properties);\n\n            assertEquals(true, filter.isConnectionLogEnabled());\n            assertEquals(true, filter.isStatementLogEnabled());\n            assertEquals(false, filter.isStatementExecutableSqlLogEnable());\n            assertEquals(true, filter.isResultSetLogEnabled());\n        } finally {\n            System.clearProperty(\"druid.log.conn\");\n            System.clearProperty(\"druid.log.stmt\");\n            System.clearProperty(\"druid.log.rs\");\n            System.clearProperty(\"druid.log.stmt.executableSql\");\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/log/LogFilterTest5.java",
    "content": "package com.alibaba.druid.bvt.filter.log;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\npublic class LogFilterTest5 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        try {\n            dataSource = new DruidDataSource();\n            dataSource.setUrl(\"jdbc:derby:classpath:petstore-db\");\n            dataSource.setFilters(\"log4j2\");\n        } catch (Throwable ignored) {\n        }\n    }\n\n    @Test\n    public void test_select() throws Exception {\n        if (dataSource == null) {\n            return;\n        }\n\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT * FROM ITEM WHERE LISTPRICE > 10\");\n\n        for (int i = 0; i < 10; ++i) {\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n        }\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/log/Slf4jLogFilterTest.java",
    "content": "package com.alibaba.druid.bvt.filter.log;\n\nimport com.alibaba.druid.filter.logging.Slf4jLogFilter;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Slf4jLogFilterTest {\n    @Test\n    public void test_slf4j() throws Exception {\n        Slf4jLogFilter filter = new Slf4jLogFilter();\n        assertEquals(\"druid.sql.DataSource\", filter.getDataSourceLoggerName());\n        assertEquals(\"druid.sql.Connection\", filter.getConnectionLoggerName());\n        assertEquals(\"druid.sql.Statement\", filter.getStatementLoggerName());\n        assertEquals(\"druid.sql.ResultSet\", filter.getResultSetLoggerName());\n\n        filter.setDataSourceLoggerName(\"x.sql.DataSource\");\n        filter.setConnectionLoggerName(\"x.sql.Connection\");\n        filter.setStatementLoggerName(\"x.sql.Statement\");\n        filter.setResultSetLoggerName(\"x.sql.ResultSet\");\n\n        assertEquals(\"x.sql.DataSource\", filter.getDataSourceLoggerName());\n        assertEquals(\"x.sql.Connection\", filter.getConnectionLoggerName());\n        assertEquals(\"x.sql.Statement\", filter.getStatementLoggerName());\n        assertEquals(\"x.sql.ResultSet\", filter.getResultSetLoggerName());\n\n        filter.setDataSourceLogger(LoggerFactory.getLogger(\"y.sql.DataSource\"));\n        filter.setConnectionLogger(LoggerFactory.getLogger(\"y.sql.Connection\"));\n        filter.setStatementLogger(LoggerFactory.getLogger(\"y.sql.Statement\"));\n        filter.setResultSetLogger(LoggerFactory.getLogger(\"y.sql.ResultSet\"));\n\n        assertEquals(\"y.sql.DataSource\", filter.getDataSourceLoggerName());\n        assertEquals(\"y.sql.Connection\", filter.getConnectionLoggerName());\n        assertEquals(\"y.sql.Statement\", filter.getStatementLoggerName());\n        assertEquals(\"y.sql.ResultSet\", filter.getResultSetLoggerName());\n\n        filter.isDataSourceLogEnabled();\n        filter.isConnectionLogEnabled();\n        filter.isConnectionLogErrorEnabled();\n        filter.isStatementLogEnabled();\n        filter.isStatementLogErrorEnabled();\n        filter.isResultSetLogEnabled();\n        filter.isResultSetLogErrorEnabled();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/BigSqlTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BigSqlTest {\n    @Test\n    public void test_true() throws Exception {\n        String sql = \"SELECT c from sbtest where id=0\";\n\n        for (int i = 0; i < 10000; i++) {\n            sql += \" or id=0\";\n        }\n        WallConfig config = new WallConfig();\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_true2() throws Exception {\n        String sql = \"SELECT c from sbtest where id=0\";\n\n        for (int i = 0; i < 10000; i++) {\n            sql += \" and id=0\";\n        }\n        WallConfig config = new WallConfig();\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/BitwiseAndTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BitwiseAndTest {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * from t where (id = 1) & 2\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setConditionOpBitwiseAllow(false);\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * from t where (id = 1) & 2\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/BitwiseInvertTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BitwiseInvertTest {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * from t where ~2\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setConditionOpBitwiseAllow(false);\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * from t where ~2\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/BitwiseOrTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BitwiseOrTest {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * from t where (id = 1) | 2\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setConditionOpBitwiseAllow(false);\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * from t where (id = 1) | 2\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/BitwiseXorTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BitwiseXorTest {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * from t where (id = 1) ^ (1=1)\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setConditionOpBitwiseAllow(false);\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * from t where (id = 1) ^ (1=1)\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/BooleanXorTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BooleanXorTest {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * from t where id = 1 XOR id = 2\"));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setConditionOpXorAllow(true);\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * from t where id = 1 XOR id = 2\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/ConstantArithmeticCheckTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConstantArithmeticCheckTest {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * from t where 3 - 1\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setConstArithmeticAllow(false);\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * from t where  3 - 1\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/CountTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CountTest {\n    @Test\n    public void test_isTrue() throws Exception {\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"(select count(*) from t) > 0\")));\n        assertEquals(Boolean.TRUE,\n                WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"(select count(*) from t) >= 0\")));\n        assertEquals(Boolean.FALSE,\n                WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"(select count(*) from t) < 0\")));\n        assertEquals(Boolean.TRUE,\n                WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"NOT (select count(*) from t) < 0\")));\n\n        //\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/DoPrivilegedTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.security.PrivilegedAction;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DoPrivilegedTest {\n    @Test\n    public void test_0() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(\"select @@version_compile_os FROM X\"));\n    }\n\n    @Test\n    public void test_0_0() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"select * FROM X where version=@@version_compile_os\"));\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        final WallConfig config = new WallConfig();\n        config.setDoPrivilegedAllow(true);\n\n        WallProvider.doPrivileged(new PrivilegedAction<Object>() {\n            @Override\n            public Object run() {\n                assertTrue(WallUtils.isValidateMySql(\"select @@version_compile_os FROM X\", config));\n                return null;\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/IdentEqualsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class IdentEqualsTest {\n    private String sql = \"select * from t where FID = 1 OR id = id\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/IdentEqualsTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class IdentEqualsTest1 {\n    private String sql = \"select * from t where FID = 1 OR not (id != id)\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/IntersectTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class IntersectTest {\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setMinusAllow(false);\n        assertFalse(WallUtils.isValidateOracle(//\n                \"SELECT * FROM A MINUS SELECT * FROM B\", config));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(//\n                \"SELECT * FROM A MINUS SELECT * FROM B\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/LikeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LikeTest {\n    @Test\n    public void test_isTrue() throws Exception {\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"f1 like '%'\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"f1 like '%%'\")));\n        assertEquals(null, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"a1 = b1 AND f1 like '%%'\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"a1 = b1 OR f1 like '%%'\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/MinusTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MinusTest {\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setIntersectAllow(false);\n        assertFalse(WallUtils.isValidateOracle(//\n                \"SELECT * FROM A Intersect SELECT * FROM B\", config));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(//\n                \"SELECT * FROM A Intersect SELECT * FROM B\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/MustParameterizedTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MustParameterizedTest {\n    private String sql = \"select * from t where id = 3\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setMustParameterized(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/MustParameterizedTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MustParameterizedTest1 {\n    private String sql = \"select * from t where id = 3 + 5\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setMustParameterized(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/MustParameterizedTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MustParameterizedTest2 {\n    private String sql = \"select * from t where id in (3, 5)\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setMustParameterized(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/MustParameterizedTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MustParameterizedTest3 {\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setMustParameterized(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"select * from t where id  = (3 + 5 - 2 - 1)\", config));\n        assertFalse(WallUtils.isValidateMySql(\"select * from t where id  != id + 3\", config));\n        assertFalse(WallUtils.isValidateMySql(\"delete from t where id  != id + 3\", config));\n        assertFalse(WallUtils.isValidateMySql(\"delete from t where id = 'aa' + 'bbb'\", config));\n        assertTrue(WallUtils.isValidateMySql(\"select * from t where id  = ? ORDER BY 1\", config));\n        assertTrue(WallUtils.isValidateMySql(\"select 1, 2, 3 from t where id  = ?\", config));\n        assertFalse(WallUtils.isValidateMySql(\"select 1, 2, 3 from t where id  = 7\", config));\n        assertTrue(WallUtils.isValidateMySql(\"select 1, 2, 3 from t where id  = ? union select * from t\", config));\n        assertFalse(WallUtils.isValidateMySql(\"select 1, 2, 3 from t where id  = ? union select 1, 2, 3 --\", config));\n        assertFalse(WallUtils.isValidateMySql(\"select 1, 2, 3 from t where id  = ? union select * from t fid = fid\", config));\n        assertFalse(WallUtils.isValidateMySql(\"select 1, 2, 3 from t where id  = ? union select * from t fid > 5\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/MustParameterizedTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MustParameterizedTest4 {\n    private String sql = \"select * from t where id not in (3, 5)\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setMustParameterized(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/NoMatchDbWallProvider.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class NoMatchDbWallProvider extends WallProvider {\n    public NoMatchDbWallProvider(WallConfig config) {\n        super(config);\n    }\n\n    public NoMatchDbWallProvider(WallConfig config, DbType dbType) {\n        super(config, dbType);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return null;\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return null;\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/NullWallProvider.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.ExportParameterVisitor;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallVisitor;\n\npublic class NullWallProvider extends WallProvider {\n    public NullWallProvider(WallConfig config) {\n        super(config);\n    }\n\n    public NullWallProvider(WallConfig config, DbType dbType) {\n        super(config, dbType);\n    }\n\n    @Override\n    public SQLStatementParser createParser(String sql) {\n        return null;\n    }\n\n    @Override\n    public WallVisitor createWallVisitor() {\n        return null;\n    }\n\n    @Override\n    public ExportParameterVisitor createExportParameterVisitor() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/PGDenyFunctionTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PGDenyFunctionTest {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidatePostgres(//\n                \"select * from t where fid = 1 union SELECT current_catalog() from t where id = ?\"));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setFunctionCheck(false);\n        assertTrue(WallUtils.isValidatePostgres(//\n                \"SELECT current_catalog() from t where id = ?\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/PGWallTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PGWallTest {\n    @Test\n    public void test_false() throws Exception {\n        assertTrue(WallUtils.isValidatePostgres(//\n                \"select wm_concat(article_id) over() from t_nds_web_article\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/StrictSyntaxCheckTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StrictSyntaxCheckTest {\n    @Test\n    public void test_syntax() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT SELECT\")); // 部分永真\n    }\n\n    @Test\n    public void test_syntax_1() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setStrictSyntaxCheck(false);\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT SELECT\", config)); // 部分永真\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TAEWallTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class TAEWallTest {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select * from t where 1=1 AND status = 1\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where status = 1 OR 1=1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantDeleteTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TenantDeleteTest {\n    private String sql = \"DELETE FROM orders WHERE FID = ?\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider.setTenantValue(123);\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n\n        WallProvider.setTenantValue(\"test\");\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(\"DELETE FROM orders\" +\n                \"\\nWHERE FID = ?\", resultSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantInsertTest.java",
    "content": "/*\n * Copyright 2013 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// Created on 2013-10-17\n// $Id$\n\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author kiki\n */\npublic class TenantInsertTest {\n    private WallConfig config = new WallConfig();\n    private WallConfig config_callback = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n\n        config_callback.setTenantCallBack(new TenantTestCallBack());\n    }\n\n    @Test\n    public void testMySql3() throws Exception {\n        String insert_sql = \"INSERT INTO orders (ID, NAME) VALUES (1, \\\"KIKI\\\")\";\n        String expect_sql = \"INSERT INTO orders (ID, NAME, tenant)\\n\" +\n                \"VALUES (1, 'KIKI', 123)\";\n        {\n            MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n\n        {\n            WallProvider.setTenantValue(123);\n            MySqlWallProvider provider = new MySqlWallProvider(config);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n\n    }\n\n    @Test\n    public void testMySql4() throws Exception {\n        String insert_sql = \"INSERT INTO orders (ID, NAME) VALUES (1, \\\"KIKI\\\"), (1, \\\"CICI\\\")\";\n        String expect_sql = \"INSERT INTO orders (ID, NAME, tenant)\\n\" +\n                \"VALUES (1, 'KIKI', 123),\\n\" +\n                \"\\t(1, 'CICI', 123)\";\n\n        {\n            MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n\n        {\n            WallProvider.setTenantValue(123);\n            MySqlWallProvider provider = new MySqlWallProvider(config);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n\n    }\n\n    @Test\n    public void testMySql5() throws Exception {\n        String insert_sql = \"INSERT INTO orders (ID, NAME) SELECT ID, NAME FROM temp WHERE age = 18\";\n        String expect_sql = \"INSERT INTO orders (ID, NAME, tenant)\" +\n                \"\\nSELECT ID, NAME, 123\" +\n                \"\\nFROM temp\" +\n                \"\\nWHERE age = 18\";\n\n        {\n            MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n\n        {\n            WallProvider.setTenantValue(123);\n            MySqlWallProvider provider = new MySqlWallProvider(config);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n    }\n\n    @Test\n    public void testMySql6() throws Exception {\n        String insert_sql = \"INSERT INTO orders (ID, NAME) SELECT ID, NAME FROM temp1 WHERE age = 18 UNION SELECT ID, NAME FROM temp2 UNION ALL SELECT ID, NAME FROM temp3\";\n        String expect_sql = \"INSERT INTO orders (ID, NAME, tenant)\\n\" +\n                \"SELECT ID, NAME, 123\\n\" +\n                \"FROM temp1\\n\" +\n                \"WHERE age = 18\\n\" +\n                \"UNION\\n\" +\n                \"SELECT ID, NAME, 123\\n\" +\n                \"FROM temp2\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT ID, NAME, 123\\n\" +\n                \"FROM temp3\";\n\n        {\n            MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n\n        {\n            WallProvider.setTenantValue(123);\n            MySqlWallProvider provider = new MySqlWallProvider(config);\n            WallCheckResult checkResult = provider.check(insert_sql);\n            assertEquals(0, checkResult.getViolations().size());\n\n            String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n            assertEquals(expect_sql, resultSql);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantSelectTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TenantSelectTest {\n    private String sql = \"SELECT ID, NAME FROM orders WHERE FID = ?\";\n    private String expect_sql = \"SELECT ID, NAME, tenant\" +\n            \"\\nFROM orders\" +\n            \"\\nWHERE FID = ?\";\n\n    private WallConfig config = new WallConfig();\n    private WallConfig config_callback = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n\n        config_callback.setTenantCallBack(new TenantTestCallBack());\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider.setTenantValue(123);\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n\n    @Test\n    public void testMySql2() throws Exception {\n        MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantSelectTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TenantSelectTest2 {\n    private String sql = \"SELECT ID, NAME FROM orders WHERE FID = ? OR FID = ?\";\n    private String expect_sql = \"SELECT ID, NAME, tenant\" +\n            \"\\nFROM orders\" +\n            \"\\nWHERE FID = ?\" +\n            \"\\n\\tOR FID = ?\";\n\n    private WallConfig config = new WallConfig();\n    private WallConfig config_callback = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n\n        config_callback.setTenantCallBack(new TenantTestCallBack());\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider.setTenantValue(123);\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n\n    @Test\n    public void testMySql2() throws Exception {\n        MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantSelectTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TenantSelectTest3 {\n    private String sql = \"SELECT ID, NAME \" +\n            \"FROM orders o inner join users u ON o.userid = u.id \" +\n            \"WHERE FID = ? OR FID = ?\";\n    private String expect_sql = \"SELECT ID, NAME, u.tenant, o.tenant\" +\n            \"\\nFROM orders o\" +\n            \"\\n\\tINNER JOIN users u ON o.userid = u.id\" +\n            \"\\nWHERE FID = ?\" +\n            \"\\n\\tOR FID = ?\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallConfig config = new WallConfig();\n        WallConfig config_callback = new WallConfig();\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n\n        config_callback.setTenantCallBack(new TenantTestCallBack());\n\n        WallProvider.setTenantValue(123);\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n\n    @Test\n    public void testMySql2() throws Exception {\n        WallConfig config = new WallConfig();\n        WallConfig config_callback = new WallConfig();\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n\n        config_callback.setTenantCallBack(new TenantTestCallBack());\n\n        MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantSelectTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TenantSelectTest4 {\n    private String sql = \"SELECT a.*,b.name \" +\n            \"FROM vote_info a left join vote_item b on a.item_id=b.id \" +\n            \"where 1=1 limit 1,10\";\n    private String expect_sql = \"SELECT a.*, b.name, b.tenant, a.tenant\" +\n            \"\\nFROM vote_info a\" +\n            \"\\n\\tLEFT JOIN vote_item b ON a.item_id = b.id\" +\n            \"\\nWHERE 1 = 1\" +\n            \"\\nLIMIT 1, 10\";\n\n    private WallConfig config = new WallConfig();\n    private WallConfig config_callback = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n\n        config_callback.setTenantCallBack(new TenantTestCallBack());\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider.setTenantValue(123);\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n        config.setSelectWhereAlwayTrueCheck(false);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n\n        provider.reset();\n        config.setSelectWhereAlwayTrueCheck(true);\n        checkResult = provider.check(sql);\n        assertEquals(1, checkResult.getViolations().size());\n    }\n\n    @Test\n    public void testMySql2() throws Exception {\n        MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n        provider.getConfig().setSelectWhereAlwayTrueCheck(false);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n\n        provider.reset();\n        provider.getConfig().setSelectWhereAlwayTrueCheck(true);\n        checkResult = provider.check(sql);\n        assertEquals(1, checkResult.getViolations().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantTestCallBack.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig.TenantCallBack;\n\npublic class TenantTestCallBack implements TenantCallBack {\n    @Override\n    public Object getTenantValue(StatementType statementType, String tableName) {\n        return 123;\n    }\n\n    @Override\n    public String getTenantColumn(StatementType statementType, String tableName) {\n        return \"tenant\";\n    }\n\n    @Override\n    public String getHiddenColumn(String tableName) {\n        return \"tenant\";\n    }\n\n    @Override\n    public void filterResultsetTenantColumn(Object value) {\n        System.out.println(value);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantUpdateTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TenantUpdateTest {\n    private String sql = \"UPDATE T_USER SET FNAME = ? WHERE FID = ?\";\n    private String expect_sql = \"UPDATE T_USER\" +\n            \"\\nSET FNAME = ?, tenant = 123\" +\n            \"\\nWHERE FID = ?\";\n\n    private WallConfig config = new WallConfig();\n    private WallConfig config_callback = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setTenantTablePattern(\"*\");\n        config.setTenantColumn(\"tenant\");\n\n        config_callback.setTenantCallBack(new TenantTestCallBack());\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider.setTenantValue(123);\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n\n    @Test\n    public void testMySql2() throws Exception {\n        WallProvider.setTenantValue(123);\n        MySqlWallProvider provider = new MySqlWallProvider(config_callback);\n        WallCheckResult checkResult = provider.check(sql);\n        assertEquals(0, checkResult.getViolations().size());\n\n        String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), JdbcConstants.MYSQL);\n        assertEquals(expect_sql, resultSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/Test01WallProviderCreator.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallProviderCreator;\n\npublic class Test01WallProviderCreator implements WallProviderCreator {\n    private static final Log LOG = LogFactory.getLog(Test01WallProviderCreator.class);\n    @Override\n    public WallProvider createWallConfig(DataSourceProxy dataSource, WallConfig config, DbType dbType) {\n        if (dbType == null) {\n            NullWallProvider nullWallProvider = new NullWallProvider(config);\n            LOG.warn(\"dbType is null so return NullWallProvider|\" + nullWallProvider);\n            return nullWallProvider;\n        }\n        return null;\n    }\n\n    @Override\n    public int getOrder() {\n        return 200;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/Test02WallProviderCreator.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallProviderCreator;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\n\npublic class Test02WallProviderCreator implements WallProviderCreator {\n    private static final Log LOG = LogFactory.getLog(Test02WallProviderCreator.class);\n\n    @Override\n    public WallProvider createWallConfig(DataSourceProxy dataSource, WallConfig config, DbType dbType) {\n        LOG.warn(\"dbType is nomatch so return NoMatchDbWallProvider\" + config + \"|\" + dbType);\n        if (config == null) {\n            config = new WallConfig(MySqlWallProvider.DEFAULT_CONFIG_DIR);\n        }\n        return new NoMatchDbWallProvider(config, dbType);\n    }\n\n    @Override\n    public int getOrder() {\n        return 100;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallAllowSelectAllColumnDefaultTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallAllowSelectAllColumnDefaultTest {\n    private String sql = \"select * from t where fid = ?\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallAllowSelectAllColumnTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallAllowSelectAllColumnTest {\n    private String sql = \"select * from t where fid = ?\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setSelectAllColumnAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallAllowSelectAllColumnTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallAllowSelectAllColumnTest1 {\n    private String sql = \"select count(*) from t where fid = ?\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setSelectAllColumnAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallAllowSelectAllColumnTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallAllowSelectAllColumnTest2 {\n    private String sql = \"select * from (select id, name from t where fid = ?) as a\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setSelectAllColumnAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallAlterTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallAlterTest_0 {\n    private String sql = \"alter index idx_t1 rebuild\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setUpdateAllow(true);\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallCallTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，被攻击者用于测试当前SQL拥有多少字段\n *\n * @author wenshao\n */\npublic class WallCallTest {\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(\"{ call INTERFACE_DATA_EXTRACTION.INVOICE_INFO(?,?,?)}\"));\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"{ call INTERFACE_DATA_EXTRACTION.INVOICE_INFO(?,?,?)}\"));\n    }\n\n    @Test\n    public void testSqlServer() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"{ call INTERFACE_DATA_EXTRACTION.INVOICE_INFO(?,?,?)}\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallCommentTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallCommentTest {\n    @Test\n    public void testORACLE() throws Exception {\n        String sql = \"SELECT F1, F2 FROM ABC --test\";\n\n        OracleWallProvider provider = new OracleWallProvider();\n        assertFalse(provider.checkValid(sql));\n\n        assertEquals(1, provider.getCommentDenyStat().getDenyCount());\n    }\n\n    @Test\n    public void testmysql() throws Exception {\n        String sql = \"SELECT F1, F2 FROM ABC -- test\";\n\n        MySqlWallProvider provider = new MySqlWallProvider();\n        assertFalse(provider.checkValid(sql));\n\n        assertEquals(1, provider.getCommentDenyStat().getDenyCount());\n    }\n\n    @Test\n    public void testsqlserver() throws Exception {\n        String sql = \"SELECT F1, F2 FROM ABC --test\";\n\n        SQLServerWallProvider provider = new SQLServerWallProvider();\n        assertFalse(provider.checkValid(sql));\n\n        assertEquals(1, provider.getCommentDenyStat().getDenyCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallConfigTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallConfigTest {\n    @Test\n    public void test_selectAllow() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.selelctAllow\", \"true\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertTrue(config.isSelectAllow());\n    }\n\n    @Test\n    public void test_selectAllow_false() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.selelctAllow\", \"false\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertFalse(config.isSelectAllow());\n    }\n\n    @Test\n    public void test_deleteAllow() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.deleteAllow\", \"true\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertTrue(config.isDeleteAllow());\n    }\n\n    @Test\n    public void test_deleteAllow_false() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.deleteAllow\", \"false\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertFalse(config.isDeleteAllow());\n    }\n\n    @Test\n    public void test_updateAllow() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.updateAllow\", \"true\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertTrue(config.isUpdateAllow());\n    }\n\n    @Test\n    public void test_updateAllow_false() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.updateAllow\", \"false\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertFalse(config.isUpdateAllow());\n    }\n\n    @Test\n    public void test_insertAllow() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.insertAllow\", \"true\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertTrue(config.isInsertAllow());\n    }\n\n    @Test\n    public void test_insertAllow_false() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.wall.insertAllow\", \"false\");\n        WallConfig config = new WallConfig();\n        config.configFromProperties(properties);\n\n        assertFalse(config.isInsertAllow());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDeleteTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测\n *\n * @author wenshao\n */\npublic class WallDeleteTest {\n    private String sql = \"DELETE FROM T WHERE F1 = ?\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setDeleteAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDeleteWhereTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallDeleteWhereTest {\n    private String sql = \"DELETE FROM T WHERE 1 = 1\";\n    private String sql2 = \"DELETE FROM T WHERE id = 0 and 1 = 1\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql));\n        assertTrue(WallUtils.isValidateMySql(sql2));\n\n        final WallConfig wallConfig = new WallConfig();\n        wallConfig.setDeleteWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateMySql(sql, wallConfig));\n        wallConfig.setDeleteWhereAlwayTrueCheck(true);\n        assertFalse(WallUtils.isValidateMySql(sql, wallConfig));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n        assertTrue(WallUtils.isValidateOracle(sql2));\n\n        final WallConfig wallConfig = new WallConfig();\n        wallConfig.setDeleteWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateOracle(sql, wallConfig));\n        wallConfig.setDeleteWhereAlwayTrueCheck(true);\n        assertFalse(WallUtils.isValidateOracle(sql, wallConfig));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDeleteWhereTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallDeleteWhereTest1 {\n    private String sql = \"DELETE FROM T\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n\n    @Test\n    public void testMySql_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDeleteWhereNoneCheck(true);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDeleteWhereNoneCheck(true);\n\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDeleteWhereTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallDeleteWhereTest2 {\n    private String sql = \"DELETE FROM T WHERE id = 0 or 1 = 1 --\";\n    private String sql1 = \"DELETE FROM T WHERE id = 0 or 1 = 1 #and c=1\";\n\n    @Test\n    public void test_check_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDeleteWhereAlwayTrueCheck(true);\n        config.setCommentAllow(true);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n        assertFalse(WallUtils.isValidateMySql(sql1, config));\n\n        config.setDeleteWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        assertTrue(WallUtils.isValidateMySql(sql1, config));\n    }\n\n    @Test\n    public void test_check_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDeleteWhereAlwayTrueCheck(false);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setCommentAllow(true);\n\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        assertTrue(WallUtils.isValidateMySql(sql1, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenySchemaTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallDenySchemaTest {\n    @Test\n    public void testORACLE() throws Exception {\n        String sql = \"SELECT * FROM T UNION SELECT F1, F2 FROM ALL_ALL_TABLES\";\n\n        OracleWallProvider provider = new OracleWallProvider();\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenyTableTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallDenyTableTest {\n    @Test\n    public void testORACLE() throws Exception {\n        String sql = \"SELECT *FROM T UNION SELECT F1, F2 FROM SYS.ABC\";\n\n        OracleWallProvider provider = new OracleWallProvider();\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDropTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，被攻击者用于测试当前SQL拥有多少字段\n *\n * @author wenshao\n */\npublic class WallDropTest {\n    @Test\n    public void testMySql() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDropTableAllow(false);\n        assertFalse(WallUtils.isValidateMySql(\"DROP TABLE T1\", config));\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDropTableAllow(false);\n        assertFalse(WallUtils.isValidateOracle(\"DROP TABLE T1\", config));\n    }\n\n    @Test\n    public void testMySql_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(\"DROP TABLE T1\"));\n    }\n\n    @Test\n    public void testOracle_true() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"DROP TABLE T1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDropTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallDropTest1 {\n    private String sql = \"DROP TABLE T1\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setDropTableAllow(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDropTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallDropTest2 {\n    private String sql = \"DROP PROCEDURE IF EXISTS CP_PayCalc1\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setDropTableAllow(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallFilterConfigSpiForNoMatchDbTypeTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallFilterConfigSpiForNoMatchDbTypeTest {\n    private DruidDataSource dataSource;\n    private WallFilter wallFilter;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setDriverClassName(\"com.alibaba.druid.mock.MockDriver\");\n        dataSource.setUrl(\"jdbc:derby:memory:spring-test;create=true\");\n        dataSource.setFilters(\"wall\");\n        dataSource.init();\n\n        wallFilter = (WallFilter) dataSource.getProxyFilters().get(0);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wallFilter() throws Exception {\n        System.out.println(\"wallFilter= \" + wallFilter);\n        System.out.println(\"wallFilter.getConfig()= \" + wallFilter.getConfig());\n        assertNotNull(wallFilter.getConfig());\n        System.out.println(\"wallFilter.getConfig()= \" + wallFilter.getProvider().getClass());\n        assertTrue(wallFilter.getProvider() instanceof NoMatchDbWallProvider);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallFilterConfigSpiForNullDbTypeTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallFilterConfigSpiForNullDbTypeTest {\n    private DruidDataSource dataSource;\n    private WallFilter wallFilter;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setDriverClassName(\"com.alibaba.druid.mock.MockDriver\");\n        dataSource.setUrl(\"jdbc:nodb:mem:wall_test;\");\n        dataSource.setFilters(\"wall\");\n        dataSource.init();\n\n        wallFilter = (WallFilter) dataSource.getProxyFilters().get(0);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wallFilter() throws Exception {\n        // With correct SPI ordering, Test02WallProviderCreator (order=100) takes\n        // precedence over Test01WallProviderCreator (order=200)\n        assertNotNull(wallFilter.getConfig());\n        assertTrue(wallFilter.getProvider() instanceof NoMatchDbWallProvider);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallFilterTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallFilterTest {\n    private DruidDataSource dataSource;\n    private WallFilter wallFilter;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:h2:mem:wall_test;\");\n        dataSource.setFilters(\"wall\");\n        dataSource.init();\n\n        wallFilter = (WallFilter) dataSource.getProxyFilters().get(0);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wallFilter() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE t (FID INTEGER, FNAME VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getCreateCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            for (int i = 0; i < 10; ++i) {\n                stmt.execute(\"INSERT INTO t (FID, FNAME) VALUES (\" + i + \", 'a\" + i + \"')\");\n            }\n            stmt.close();\n            conn.close();\n        }\n        {\n            String sql = \"SELECT * FROM T\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(10, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DELETE from t where FID = 0\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DELETE from t where FID = 1 OR FID = 2\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(3, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"update t SET fname = 'xx' where FID = 3 OR FID = 4\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(2, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ? OR FID = ?\");\n            stmt.setInt(1, 3);\n            stmt.setInt(2, 4);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(4, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ? OR FID = ?\");\n            stmt.setInt(1, 3);\n            stmt.setInt(2, 4);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(6, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ?\");\n\n            stmt.setInt(1, 3);\n            stmt.addBatch();\n\n            stmt.setInt(1, 4);\n            stmt.addBatch();\n\n            stmt.executeBatch();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(8, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"truncate table t\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getTruncateCount());\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"drop table t\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getDropCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallFilterTest2.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallFilterTest2 {\n    private DruidDataSource dataSource;\n    private WallFilter wallFilter;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:h2:mem:wall_test;\");\n        dataSource.setFilters(\"wall\");\n        dataSource.setDbType(JdbcConstants.MARIADB);\n        dataSource.init();\n\n        wallFilter = (WallFilter) dataSource.getProxyFilters().get(0);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wallFilter() throws Exception {\n        assertEquals(JdbcConstants.MARIADB, wallFilter.getDbType());\n        assertFalse(wallFilter.isLogViolation());\n        wallFilter.setLogViolation(true);\n        assertTrue(wallFilter.isLogViolation());\n        wallFilter.setLogViolation(false);\n        assertFalse(wallFilter.isLogViolation());\n\n        assertTrue(wallFilter.isThrowException());\n        wallFilter.setThrowException(false);\n        assertFalse(wallFilter.isThrowException());\n        wallFilter.setThrowException(true);\n        assertTrue(wallFilter.isThrowException());\n\n        wallFilter.clearProviderCache();\n        wallFilter.getProviderWhiteList();\n        assertTrue(wallFilter.isInited());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE t (FID INTEGER, FNAME VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getCreateCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            String sql = \"INSERT INTO t (FID, FNAME) VALUES (?, ?)\";\n\n            for (int i = 0; i < 10; ++i) {\n                PreparedStatement stmt = conn.prepareStatement(sql, Statement.NO_GENERATED_KEYS);\n                stmt.setInt(1, i + 10);\n                stmt.setString(2, \"a\" + (i + 10));\n                stmt.execute();\n                stmt.close();\n            }\n\n            conn.close();\n        }\n        assertEquals(10, wallFilter.getProvider().getTableStat(\"t\").getInsertCount());\n        assertEquals(10, wallFilter.getProvider().getTableStat(\"t\").getInsertDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            String sql = \"INSERT INTO t (FID, FNAME) VALUES (?, ?)\";\n\n            PreparedStatement stmt = conn.prepareStatement(sql, Statement.NO_GENERATED_KEYS);\n            for (int i = 0; i < 10; ++i) {\n                stmt.setInt(1, i + 20);\n                stmt.setString(2, \"a\" + (i + 20));\n                stmt.addBatch();\n            }\n            stmt.executeBatch();\n            stmt.close();\n\n            conn.close();\n        }\n        assertEquals(11, wallFilter.getProvider().getTableStat(\"t\").getInsertCount());\n        assertEquals(20, wallFilter.getProvider().getTableStat(\"t\").getInsertDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            for (int i = 0; i < 10; ++i) {\n                stmt.addBatch(\"INSERT INTO t (FID, FNAME) VALUES (\" + i + \", 'a\" + i + \"')\");\n            }\n            stmt.executeBatch();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(21, wallFilter.getProvider().getTableStat(\"t\").getInsertCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n        {\n            String sql = \"SELECT * FROM T\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(30, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(60, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, new int[0]);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(70, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, new String[0]);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(80, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareCall(sql);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(90, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(100, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(130, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            stmt.execute(sql, Statement.NO_GENERATED_KEYS);\n            ResultSet rs = stmt.getResultSet();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(140, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            stmt.execute(sql, new int[0]);\n            ResultSet rs = stmt.getResultSet();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(150, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            stmt.execute(sql, new String[0]);\n            ResultSet rs = stmt.getResultSet();\n            while (rs.next()) {\n                // Process result set rows\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(160, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 0\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 1 OR FID = 2\", Statement.NO_GENERATED_KEYS);\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(3, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 3\", new int[0]);\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(4, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 4\", new String[0]);\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(5, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"DELETE from t where FID = ?\");\n            stmt.setInt(1, 5);\n            stmt.executeUpdate();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(6, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"update t SET fname = 'xx' where FID = 13 OR FID = 14\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(2, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ? OR FID = ?\");\n            stmt.setInt(1, 13);\n            stmt.setInt(2, 14);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(4, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ? OR FID = ?\");\n            stmt.setInt(1, 13);\n            stmt.setInt(2, 14);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(6, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ?\");\n\n            stmt.setInt(1, 13);\n            stmt.addBatch();\n\n            stmt.setInt(1, 14);\n            stmt.addBatch();\n\n            stmt.executeBatch();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(8, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"truncate table t\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getTruncateCount());\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"drop table t\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getDropCount());\n\n        assertEquals(0, wallFilter.getViolationCount());\n        wallFilter.resetViolationCount();\n        wallFilter.checkValid(\"select 1\");\n        assertEquals(0, wallFilter.getViolationCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallFilterTest3.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallFilterTest3 {\n    private DruidDataSource dataSource;\n    private WallFilter wallFilter;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:h2:mem:wall_test;\");\n        // dataSource.setFilters(\"wall\");\n        dataSource.setDbType(JdbcConstants.MARIADB);\n\n        WallConfig config = new WallConfig();\n        config.setTenantCallBack(new TenantTestCallBack());\n\n        wallFilter = new WallFilter();\n        wallFilter.setConfig(config);\n        wallFilter.setDbType(JdbcConstants.MARIADB);\n        List<Filter> filters = new LinkedList<Filter>();\n        filters.add(wallFilter);\n        dataSource.setProxyFilters(filters);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wallFilter() throws Exception {\n        assertEquals(JdbcConstants.MARIADB, wallFilter.getDbType());\n        assertFalse(wallFilter.isLogViolation());\n        wallFilter.setLogViolation(true);\n        assertTrue(wallFilter.isLogViolation());\n        wallFilter.setLogViolation(false);\n        assertFalse(wallFilter.isLogViolation());\n\n        assertTrue(wallFilter.isThrowException());\n        wallFilter.setThrowException(false);\n        assertFalse(wallFilter.isThrowException());\n        wallFilter.setThrowException(true);\n        assertTrue(wallFilter.isThrowException());\n\n        wallFilter.clearProviderCache();\n        wallFilter.getProviderWhiteList();\n        assertTrue(wallFilter.isInited());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE t (FID INTEGER, FNAME VARCHAR(50), TENANT VARCHAR(32))\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getCreateCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            String sql = \"INSERT INTO t (FID, FNAME) VALUES (?, ?)\";\n\n            for (int i = 0; i < 10; ++i) {\n                PreparedStatement stmt = conn.prepareStatement(sql, Statement.NO_GENERATED_KEYS);\n                stmt.setInt(1, i + 10);\n                stmt.setString(2, \"a\" + (i + 10));\n                stmt.execute();\n                stmt.close();\n            }\n\n            conn.close();\n        }\n        assertEquals(10, wallFilter.getProvider().getTableStat(\"t\").getInsertCount());\n        assertEquals(10, wallFilter.getProvider().getTableStat(\"t\").getInsertDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            String sql = \"INSERT INTO t (FID, FNAME) VALUES (?, ?)\";\n\n            PreparedStatement stmt = conn.prepareStatement(sql, Statement.NO_GENERATED_KEYS);\n            for (int i = 0; i < 10; ++i) {\n                stmt.setInt(1, i + 20);\n                stmt.setString(2, \"a\" + (i + 20));\n                stmt.addBatch();\n            }\n            stmt.executeBatch();\n            stmt.close();\n\n            conn.close();\n        }\n        assertEquals(11, wallFilter.getProvider().getTableStat(\"t\").getInsertCount());\n        assertEquals(20, wallFilter.getProvider().getTableStat(\"t\").getInsertDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            for (int i = 0; i < 10; ++i) {\n                stmt.addBatch(\"INSERT INTO t (FID, FNAME) VALUES (\" + i + \", 'a\" + i + \"')\");\n            }\n            stmt.executeBatch();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(21, wallFilter.getProvider().getTableStat(\"t\").getInsertCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n        {\n            String sql = \"SELECT * FROM T\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(30, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(60, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, new int[0]);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(70, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql, new String[0]);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(80, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareCall(sql);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(90, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(100, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T\";\n\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(130, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            stmt.execute(sql, Statement.NO_GENERATED_KEYS);\n            ResultSet rs = stmt.getResultSet();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(140, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            stmt.execute(sql, new int[0]);\n            ResultSet rs = stmt.getResultSet();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(150, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            String sql = \"SELECT * FROM T LIMIT 10\";\n\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            stmt.execute(sql, new String[0]);\n            ResultSet rs = stmt.getResultSet();\n            while (rs.next()) {\n                // intentionally empty - just iterating through results\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(160, wallFilter.getProvider().getTableStat(\"t\").getFetchRowCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 0\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 1 OR FID = 2\", Statement.NO_GENERATED_KEYS);\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(3, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 3\", new int[0]);\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(4, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.executeUpdate(\"DELETE from t where FID = 4\", new String[0]);\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(5, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"DELETE from t where FID = ?\");\n            stmt.setInt(1, 5);\n            stmt.executeUpdate();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(6, wallFilter.getProvider().getTableStat(\"t\").getDeleteDataCount());\n        assertEquals(0, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"update t SET fname = 'xx' where FID = 13 OR FID = 14\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(2, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ? OR FID = ?\");\n            stmt.setInt(1, 13);\n            stmt.setInt(2, 14);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(4, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ? OR FID = ?\");\n            stmt.setInt(1, 13);\n            stmt.setInt(2, 14);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(6, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"update t SET fname = 'xx' where FID = ?\");\n\n            stmt.setInt(1, 13);\n            stmt.addBatch();\n\n            stmt.setInt(1, 14);\n            stmt.addBatch();\n\n            stmt.executeBatch();\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(8, wallFilter.getProvider().getTableStat(\"t\").getUpdateDataCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"truncate table t\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getTruncateCount());\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"drop table t\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(1, wallFilter.getProvider().getTableStat(\"t\").getDropCount());\n\n        assertEquals(0, wallFilter.getViolationCount());\n        wallFilter.resetViolationCount();\n        wallFilter.checkValid(\"select 1\");\n        assertEquals(0, wallFilter.getViolationCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallHavingTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallHavingTest {\n    private String sql = \"SELECT F1, COUNT(*) FROM T GROUP BY F1 HAVING COUNT(*) OR 1 = 1\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallHavingTest6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallHavingTest6 {\n    private String sql = \"SELECT region, SUM(population), SUM(area) FROM bbc GROUP BY region HAVING SUM(area)>1000000 or 1 = 1 --\";\n\n    private String sql1 = \"SELECT region, SUM(population), SUM(area) FROM bbc GROUP BY region HAVING SUM(area)>1000000 or 1 = 1 #and c=1\";\n\n    @Test\n    public void test_check_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectHavingAlwayTrueCheck(true);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setCommentAllow(true);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n        assertFalse(WallUtils.isValidateMySql(sql1, config));\n    }\n\n    @Test\n    public void test_check_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectHavingAlwayTrueCheck(false);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setCommentAllow(true);\n\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        assertTrue(WallUtils.isValidateMySql(sql1, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallInsertTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallInsertTest {\n    private String sql = \"INSERT INTO T (F1, F2) VALUES (1, 2)\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setInsertAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallInsertTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallInsertTest2 {\n    private String sql = \"INSERT INTO T (F1, F2) VALUES (1, 2)\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setInsertAllow(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallLineCommentTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallLineCommentTest {\n    private String sql = \"select f1 from t -- \";\n\n    @Test\n    public void testOracle() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallMultiLineCommentTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallMultiLineCommentTest {\n    private String sql = \"select f1 from t where a=1 /* and b=1 */\";\n\n    @Test\n    public void testOracle() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallMultiStatementTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 测试禁止多条语句执行的场景\n *\n * @author admin\n */\npublic class WallMultiStatementTest {\n    private String sql = \"SELECT email FROM members WHERE email = 'x'; UPDATE members SET email = 'steve@unixwiz.net' WHERE email = 'bob@example.com';\";\n\n    @Test\n    public void testOracle() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallProviderTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallProviderStatValue;\nimport com.alibaba.druid.wall.WallSqlStat;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallProviderTest {\n    @Test\n    public void test_getSqlStat() throws Exception {\n        String whiteSql_1 = \"select * from t1 where fid = 1\";\n        String whiteSql_2 = \"select * from t1 where fid = 2\";\n        String blackSql_1 = \"select * from t2 where len(fid) = 1 OR 1 = 1\";\n        String blackSql_2 = \"select * from t2 where len(fid) = 2 OR 1 = 1\";\n\n        MySqlWallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(whiteSql_1));\n        assertTrue(provider.checkValid(whiteSql_2));\n        assertEquals(1, provider.getSqlList().size());\n\n        assertFalse(provider.checkValid(blackSql_1));\n        assertFalse(provider.checkValid(blackSql_2));\n        assertEquals(2, provider.getSqlList().size());\n\n        assertNotNull(provider.getSqlStat(whiteSql_1));\n        assertNotNull(provider.getSqlStat(blackSql_1));\n\n        assertSame(provider.getSqlStat(blackSql_1), provider.getSqlStat(blackSql_2));\n\n        WallSqlStat whiteStat_1 = provider.getSqlStat(whiteSql_1);\n        WallSqlStat whiteStat_2 = provider.getSqlStat(whiteSql_2);\n        assertSame(whiteStat_1, whiteStat_2);\n        provider.addFetchRowCount(whiteStat_1, 3);\n        WallTableStat wallTableStat = provider.getTableStat(\"t1\");\n        assertNotNull(wallTableStat);\n        assertEquals(3, wallTableStat.getFetchRowCount());\n\n        assertTrue(provider.checkValid(whiteSql_1));\n        assertTrue(provider.checkValid(whiteSql_2));\n\n        assertFalse(provider.checkValid(blackSql_1));\n        assertFalse(provider.checkValid(blackSql_2));\n\n        for (int i = 1000; i < 1000 * 2; ++i) {\n            String sql_x = \"select * from t1 where fid = \" + i;\n            assertTrue(provider.checkValid(sql_x));\n            assertSame(whiteStat_1, provider.getSqlStat(sql_x));\n        }\n\n        assertEquals(1, provider.getWhiteList().size());\n        assertEquals(2, provider.getSqlList().size());\n\n        assertFalse(provider.checkValid(\"slelc\"));\n\n        {\n            WallProviderStatValue statValue = provider.getStatValue(true);\n            assertNotNull(statValue);\n\n            assertEquals(2, statValue.getTables().size());\n            assertEquals(1, statValue.getFunctions().size());\n\n            assertEquals(1009, statValue.getCheckCount());\n            assertEquals(3, statValue.getBlackListHitCount());\n            assertEquals(3, statValue.getHardCheckCount());\n            assertEquals(1, statValue.getSyntaxErrorCount());\n            assertEquals(5, statValue.getViolationCount());\n            assertEquals(1003, statValue.getWhiteListHitCount());\n\n            assertEquals(1, statValue.getWhiteList().size());\n            assertEquals(2, statValue.getBlackList().size());\n        }\n\n        {\n            WallProviderStatValue statValue = provider.getStatValue(true);\n            assertNotNull(statValue);\n\n            assertEquals(0, statValue.getTables().size());\n            assertEquals(0, statValue.getFunctions().size());\n\n            assertEquals(0, statValue.getCheckCount());\n            assertEquals(0, statValue.getBlackListHitCount());\n            assertEquals(0, statValue.getHardCheckCount());\n            assertEquals(0, statValue.getSyntaxErrorCount());\n            assertEquals(0, statValue.getViolationCount());\n            assertEquals(0, statValue.getWhiteListHitCount());\n\n            assertEquals(0, statValue.getWhiteList().size());\n            assertEquals(0, statValue.getBlackList().size());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallReadOnlyTest {\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.addReadOnlyTable(\"members\");\n    }\n\n    private String sql = \"SELECT F1, F2 members\";\n    private String insert_sql = \"INSERT INTO members (FID, FNAME) VALUES (?, ?)\";\n    private String update_sql = \"UPDATE members SET FNAME = ? WHERe FID = ?\";\n    private String delete_sql = \"DELETE members WHERE FID = ?\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        assertFalse(WallUtils.isValidateMySql(insert_sql, config));\n        assertFalse(WallUtils.isValidateMySql(update_sql, config));\n        assertFalse(WallUtils.isValidateMySql(delete_sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n        assertFalse(WallUtils.isValidateOracle(insert_sql, config));\n        assertFalse(WallUtils.isValidateOracle(update_sql, config));\n        assertFalse(WallUtils.isValidateOracle(delete_sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallReadOnlyTest2 {\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.addReadOnlyTable(\"members\");\n    }\n\n    private String sql = \"SELECT F1, F2 members\";\n    private String insert_sql = \"INSERT INTO members (FID, FNAME) VALUES (?, ?)\";\n    private String update_sql = \"UPDATE members SET FNAME = ? WHERe FID = ?\";\n    private String delete_sql = \"DELETE members WHERE FID = ?\";\n\n    @Test\n    public void testMySql() throws Exception {\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n        assertTrue(provider.checkValid(sql));\n\n        assertFalse(provider.checkValid(insert_sql));\n        assertFalse(provider.checkValid(update_sql));\n        assertFalse(provider.checkValid(delete_sql));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        OracleWallProvider provider = new OracleWallProvider(config);\n        assertTrue(provider.checkValid(sql));\n\n        assertFalse(provider.checkValid(insert_sql));\n        assertFalse(provider.checkValid(update_sql));\n        assertFalse(provider.checkValid(delete_sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSQLExceptionTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallSQLException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallSQLExceptionTest {\n    @Test\n    public void test_wall() throws Exception {\n        WallSQLException ex = new WallSQLException(\"\", new RuntimeException());\n        assertEquals(\"\", ex.getMessage());\n        assertNotNull(ex.getCause());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectIntoTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallSelectIntoTest {\n    private String sql = \"SELECT F1, F2 INTO T2 FROM T1\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectIntoTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallSelectIntoTest1 {\n    private String sql = \"SELECT F1, F2 INTO T2 FROM T1\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setSelectIntoAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectLimitTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.DB2WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallSelectLimitTest {\n    private String sql = \"select * from t\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setSelectLimit(1000);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"LIMIT 1000\", resultSql);\n    }\n\n    @Test\n    public void testDB2() throws Exception {\n        WallProvider provider = new DB2WallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"FETCH FIRST 1000 ROWS ONLY\", resultSql);\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT TOP 1000 *\\n\" +\n                \"FROM t\", resultSql);\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WHERE ROWNUM <= 1000\", resultSql);\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"LIMIT 1000\", resultSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectLimitTest_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.DB2WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallSelectLimitTest_2 {\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setSelectLimit(1000);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        String sql = \"select * from t limit 10\";\n        WallProvider provider = new MySqlWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"LIMIT 0, 10\", resultSql);\n    }\n\n    @Test\n    public void testMySql_0() throws Exception {\n        String sql = \"select * from t\";\n        WallProvider provider = new MySqlWallProvider(config);\n        {\n            WallCheckResult checkResult = provider.check(sql);\n            String resultSql = checkResult.getSql();\n            System.out.println(resultSql);\n            assertEquals(\"SELECT *\\n\" +\n                    \"FROM t\\n\" +\n                    \"LIMIT 1000\", resultSql);\n        }\n        {\n            WallCheckResult checkResult = provider.check(sql);\n            String resultSql = checkResult.getSql();\n            System.out.println(resultSql);\n            assertEquals(\"SELECT *\\n\" +\n                    \"FROM t\\n\" +\n                    \"LIMIT 1000\", resultSql);\n        }\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        String sql = \"select * from t limit 10\";\n        WallProvider provider = new PGWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"LIMIT 10 OFFSET 0\", resultSql);\n    }\n\n    @Test\n    public void testDB2() throws Exception {\n        String sql = PagerUtils.limit(\"select * from t\", JdbcConstants.DB2, 0, 10);\n        WallProvider provider = new DB2WallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"FETCH FIRST 10 ROWS ONLY\", resultSql);\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        String sql = PagerUtils.limit(\"select * from t\", JdbcConstants.SQL_SERVER, 0, 10);\n        WallProvider provider = new SQLServerWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT TOP 10 *\\n\" +\n                \"FROM t\", resultSql);\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        String sql = PagerUtils.limit(\"select * from t\", JdbcConstants.ORACLE, 0, 10);\n        WallProvider provider = new OracleWallProvider(config);\n        WallCheckResult checkResult = provider.check(sql);\n        String resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WHERE ROWNUM <= 10\", resultSql);\n\n        sql = PagerUtils.limit(\"select * from t\", JdbcConstants.OCEANBASE_ORACLE, 0, 10);\n        provider = new OracleWallProvider(config);\n        checkResult = provider.check(sql);\n        resultSql = checkResult.getSql();\n        System.out.println(resultSql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WHERE ROWNUM <= 10\", resultSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallSelectWhereTest {\n    private String sql = \"SELECT F1, F2  from t WHERE 1 = 1\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql));\n        final WallConfig config = new WallConfig();\n        config.setSelectWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n\n        config.setSelectWhereAlwayTrueCheck(true);\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n        final WallConfig config = new WallConfig();\n        config.setSelectWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        config.setSelectWhereAlwayTrueCheck(true);\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallSelectWhereTest0 {\n    private String sql = \"SELECT F1, F2 from t WHERE 1 = 1 AND F1 = ?\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallSelectWhereTest1 {\n    @Test\n    public void testMySql_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(\"SELECT F1, F2 from t WHERE 1 = 1 AND FID = ?\"));\n    }\n\n    @Test\n    public void testORACLE_true() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"SELECT F1, F2 from t WHERE 1 = 1 AND FID = ?\"));\n    }\n\n    @Test\n    public void testMySql_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"SELECT F1, F2 from t WHERE 1 = 1 AND FID = ? OR 1 = 1\"));\n    }\n\n    @Test\n    public void testORACLE_false() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(\"SELECT F1, F2 from t WHERE 1 = 1 AND FID = ? OR 1 = 1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallSelectWhereTest2 {\n    private String sql = \"SELECT F1, F2  from t WHERE 1 = 1 AND FID = ?\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallSelectWhereTest3 {\n    private String sql = \"select * from t WHERE FID = 256 AND CHR(67)||CHR(65)||CHR(84) = 'CAT'\";\n\n    @Test\n    public void testMySql() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setConditionAndAlwayFalseAllow(true);\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Where条件\n *\n * @author wenshao\n */\npublic class WallSelectWhereTest4 {\n    private String sql = \"select * from t WHERE FID = 256 OR CHR(67)||CHR(65)||CHR(84) = 'CAT'\";\n\n//    public void testMySql() throws Exception {\n//        assertFalse(WallUtils.isValidateMySql(sql));\n//    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallSelectWhereTest5 {\n    private String sql = \"select * from t WHERE FID = 256 OR CONCAT(CHR(67)||CHR(65)||CHR(84), '-DOG') = 'CAT-DOG'\";\n\n//    public void testMySql() throws Exception {\n//        assertFalse(WallUtils.isValidateMySql(sql));\n//    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallSelectWhereTest6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallSelectWhereTest6 {\n    private String sql = \"SELECT * FROM T WHERE id = 0 or 1 = 1 --\";\n\n    private String sql1 = \"SELECT * FROM T WHERE id = 0 or 1 = 1 #and c=1\";\n\n    @Test\n    public void test_check_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectWhereAlwayTrueCheck(true);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setCommentAllow(true);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n        assertFalse(WallUtils.isValidateMySql(sql1, config));\n\n        config.setSelectWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_check_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectWhereAlwayTrueCheck(false);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setCommentAllow(true);\n\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        assertTrue(WallUtils.isValidateMySql(sql1, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTestWhereAlwaysTrue.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.DB2WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTestWhereAlwaysTrue {\n    private String[] sqls = new String[]{\n            \"select * from T where a=1 or 1=1\",\n            \"update T set name='N' where a=1 or 1=1\",\n            \"delete from T where a=1 or 1=1\",\n            \"update T set name='N' where 1=1\",\n            \"delete from T where 1=1\",\n            \"select * from T where 1=1\",\n            \"update T set name='N' where 1=1 \",\n            \"delete from T where 1=1 \",\n            \"select * from T where 1=1 \",\n            \"update T set name='N' where 0=1 or 2=2\",\n            \"delete from T  where 0=1 or 2=2\",\n            \"select * from T where 0=1 or 2=2\",\n    };\n\n    private String[] okSqls = new String[]{\n            \"delete from T where a=1\",\n            \"delete from T where a=1 \",\n            \"update T set name='N' where a=1\",\n            \"update T set name='N' where a=1 \",\n            \"select * from T where a=1\",\n            \"select * from T where a=1 \",\n    };\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    protected void doTest(final WallProvider provider) {\n        final WallConfig config = provider.getConfig();\n        config.setDeleteWhereAlwayTrueCheck(true);\n        //config.setUpdateWhereAlwayTrueCheck(true);\n        config.setSelectWhereAlwayTrueCheck(true);\n        for (final String sql : sqls) {\n            assertFalse(provider.checkValid(sql), sql);\n            final WallTableStat tableStat = provider.getTableStat(\"t\");\n            if (sql.startsWith(\"delete\")) {\n                assertTrue(tableStat.getDeleteCount() > 0);\n            }\n        }\n        for (final String sql : okSqls) {\n            assertTrue(provider.checkValid(sql), sql);\n        }\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        final WallProvider provider = new MySqlWallProvider();\n        doTest(provider);\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        final WallProvider provider = new OracleWallProvider();\n        doTest(provider);\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        final WallProvider provider = new PGWallProvider();\n        doTest(provider);\n    }\n\n    @Test\n    public void testDB2Server() throws Exception {\n        final WallProvider provider = new DB2WallProvider();\n        doTest(provider);\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        final WallProvider provider = new SQLServerWallProvider();\n        doTest(provider);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_WhiteList.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_WhiteList {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        for (int i = 0; i < 3001; ++i) {\n            String sql = \"select * from t where id = \" + i;\n            assertTrue(provider.checkValid(sql));\n        }\n\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(3001, tableStat.getSelectCount());\n        assertEquals(0, provider.getBlackListHitCount());\n        assertEquals(3000, provider.getWhiteListHitCount());\n        assertEquals(1, provider.getWhiteList().size());\n        assertEquals(3001, provider.getCheckCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_WhiteList_disable.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_WhiteList_disable {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.setBlackListEnable(false);\n        provider.setWhiteListEnable(false);\n\n        for (int i = 0; i < 301; ++i) {\n            String sql = \"select * from t where id = \" + i;\n            assertTrue(provider.checkValid(sql));\n        }\n\n        for (int i = 0; i < 301; ++i) {\n            String sql = \"select * from t where id = \" + i + \" OR 1 = 1\";\n            assertFalse(provider.checkValid(sql));\n        }\n\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(602, tableStat.getSelectCount());\n        assertEquals(0, provider.getBlackListHitCount());\n        assertEquals(0, provider.getWhiteListHitCount());\n        assertEquals(0, provider.getWhiteList().size());\n        assertEquals(602, provider.getCheckCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_alter_table.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_alter_table {\n    @Test\n    public void testMySql() throws Exception {\n        String sql = \"alter table t add column fname varchar(50)\";\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setAlterTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getAlterCount());\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        String sql = \"alter table t add (fname varchar(50))\";\n        WallProvider provider = new OracleWallProvider();\n        provider.getConfig().setAlterTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getAlterCount());\n    }\n\n//    public void testPG() throws Exception {\n//        WallProvider provider = new PGWallProvider();\n//        provider.getConfig().setAlterTableAllow(true);\n//\n//        assertTrue(provider.checkValid(sql));\n//        WallTableStat tableStat = provider.getTableStat(\"t\");\n//        assertEquals(1, tableStat.getAlterCount());\n//    }\n//\n//    public void testSQLServer() throws Exception {\n//        WallProvider provider = new SQLServerWallProvider();\n//        provider.getConfig().setAlterTableAllow(true);\n//\n//        assertTrue(provider.checkValid(sql));\n//        WallTableStat tableStat = provider.getTableStat(\"t\");\n//        assertEquals(1, tableStat.getAlterCount());\n//    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_blackList_1.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_blackList_1 {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        for (int i = 0; i < 1001; ++i) {\n            String sql = \"select * from t where id = \" + i + \" OR 1 = 1\";\n            assertFalse(provider.checkValid(sql));\n        }\n\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1001, tableStat.getSelectCount());\n        assertEquals(1000, provider.getBlackListHitCount());\n        assertEquals(0, provider.getWhiteListHitCount());\n        assertEquals(0, provider.getWhiteList().size());\n        assertEquals(1, provider.getBlackList().size());\n        assertEquals(1001, provider.getCheckCount());\n    }\n\n    @Test\n    public void testMysql2() {\n        WallProvider provider = new MySqlWallProvider();\n\n        for (int i = 0; i < 1001; ++i) {\n            String sql = \"select * from t where field_\" + i + \" = \" + i + \" OR 1 = 1\";\n            assertFalse(provider.checkValid(sql));\n        }\n\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1001, tableStat.getSelectCount());\n        assertEquals(0, provider.getBlackListHitCount());\n        assertEquals(0, provider.getWhiteListHitCount());\n        assertEquals(0, provider.getWhiteList().size());\n        assertEquals(WallProvider.BLACK_SQL_MAX_SIZE, provider.getBlackList().size());\n        assertEquals(1001, provider.getCheckCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_blackList_syntaxError.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_blackList_syntaxError {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"select xx * x *\";\n        assertFalse(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"t\");\n            assertEquals(0, tableStat.getSelectCount());\n            assertEquals(0, provider.getBlackListHitCount());\n            assertEquals(0, provider.getWhiteListHitCount());\n            assertEquals(0, provider.getWhiteList().size());\n            assertEquals(1, provider.getBlackList().size());\n            assertEquals(1, provider.getCheckCount());\n            assertEquals(1, provider.getSyntaxErrorCount());\n            assertEquals(1, provider.getHardCheckCount());\n        }\n\n        assertFalse(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"t\");\n            assertEquals(0, tableStat.getSelectCount());\n            assertEquals(1, provider.getBlackListHitCount());\n            assertEquals(0, provider.getWhiteListHitCount());\n            assertEquals(0, provider.getWhiteList().size());\n            assertEquals(1, provider.getBlackList().size());\n            assertEquals(2, provider.getCheckCount());\n            assertEquals(2, provider.getSyntaxErrorCount());\n            assertEquals(1, provider.getHardCheckCount());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_blacklist.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_blacklist {\n    private String sql = \"select * from t where id = ? and 1 = 1\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        for (int i = 0; i < 10; ++i) {\n            assertTrue(provider.checkValid(sql));\n        }\n\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(10, tableStat.getSelectCount());\n        assertEquals(9, provider.getWhiteListHitCount());\n        assertEquals(0, provider.getBlackListHitCount());\n\n        provider.reset();\n        provider.getConfig().setConditionAndAlwayTrueAllow(false);\n        for (int i = 0; i < 10; ++i) {\n            assertFalse(provider.checkValid(sql));\n        }\n        tableStat = provider.getTableStat(\"t\");\n        assertEquals(10, tableStat.getSelectCount());\n        assertEquals(0, provider.getWhiteListHitCount());\n        assertEquals(9, provider.getBlackListHitCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_create_table.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_create_table {\n    private String sql = \"create table t (fid int, fname varchar(50))\";\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCreateTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getCreateCount());\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        provider.getConfig().setCreateTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getCreateCount());\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        provider.getConfig().setCreateTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getCreateCount());\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        provider.getConfig().setCreateTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_delete.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_delete {\n    private String sql = \"delete from T where fid = ?\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDeleteCount());\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDeleteCount());\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDeleteCount());\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDeleteCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_drop_table.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_drop_table {\n    private String sql = \"drop table t\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setDropTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDropCount());\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        provider.getConfig().setDropTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDropCount());\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        provider.getConfig().setDropTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDropCount());\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        provider.getConfig().setDropTableAllow(true);\n\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getDropCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_function_stats.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallFunctionStat;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_function_stats {\n    private String sql = \"select len(fname), len(fdesc) from t\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"t\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n        {\n            WallFunctionStat functionStat = provider.getFunctionStat(\"len\");\n            assertEquals(2, functionStat.getInvokeCount());\n        }\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"t\");\n            assertEquals(2, tableStat.getSelectCount());\n        }\n        {\n            WallFunctionStat functionStat = provider.getFunctionStat(\"len\");\n            assertEquals(4, functionStat.getInvokeCount());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_insert.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_insert {\n    private String sql = \"insert into t (fid, fname) values (?, ?)\";\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getInsertCount());\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getInsertCount());\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getInsertCount());\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getInsertCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_select.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_select {\n    private String sql = \"select * from t where id = ?\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getSelectCount());\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getSelectCount());\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getSelectCount());\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getSelectCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_select_1.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_select_1 {\n    private String sql = \"SELECT b.* FROM lhwbbs_posts_reply a LEFT JOIN lhwbbs_posts b ON a.pid=b.pid WHERE a.rpid=? AND b.disabled=? ORDER BY a.pid DESC\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts_reply\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts_reply\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts_reply\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts_reply\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n        {\n            WallTableStat tableStat = provider.getTableStat(\"lhwbbs_posts\");\n            assertEquals(1, tableStat.getSelectCount());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_select_2.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_select_2\n {\n    private String sql = \"SELECT *\\n\" +\n            \"FROM `t`\\n\" +\n            \"WHERE `t`.`col1` = '1'\\n\" +\n            \"    AND `t`.`col2` = 0\\n\" +\n            \"    AND CONCAT(t.col3, '_', t.col4) IN ('abc_def')\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        assertTrue(provider.checkValid(sql));\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        assertTrue(provider.checkValid(sql));\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_select_into.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_select_into {\n    private String sql = \"select * into x from t where id = ?\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n\n        {\n            WallTableStat tableStat = provider.getTableStat(\"t\");\n            assertEquals(1, tableStat.getSelectCount());\n            assertEquals(0, tableStat.getSelectIntoCount());\n        }\n        {\n            WallTableStat tableStat = provider.getTableStat(\"x\");\n            assertEquals(0, tableStat.getSelectCount());\n            assertEquals(1, tableStat.getSelectIntoCount());\n        }\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getSelectCount());\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getSelectCount());\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getSelectCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_statMap.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.stat.DruidStatManagerFacade;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collection;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_statMap {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider providerA = new MySqlWallProvider();\n\n        {\n            String sql = \"select * from t where len(fname1) = 1 OR 1 = 1\";\n            assertFalse(providerA.checkValid(sql));\n            providerA.addViolationEffectRowCount(10);\n        }\n\n        WallProvider providerB = new MySqlWallProvider();\n        {\n            String sql = \"select * from t where len(fname2) = 2 OR 1 = 1\";\n            assertFalse(providerB.checkValid(sql));\n            providerB.addViolationEffectRowCount(11);\n        }\n\n        WallProvider providerC = new MySqlWallProvider();\n        {\n            String sql = \"select * from t where len(fname2) = 2 OR 1 = 1\";\n            assertFalse(providerC.checkValid(sql));\n            providerC.addViolationEffectRowCount(12);\n        }\n\n        Map<String, Object> statMapA = providerA.getStatsMap();\n        Map<String, Object> statMapB = providerB.getStatsMap();\n        Map<String, Object> statMapC = providerC.getStatsMap();\n\n        System.out.println(JSONUtils.toJSONString(statMapA));\n        System.out.println(JSONUtils.toJSONString(statMapB));\n        System.out.println(JSONUtils.toJSONString(statMapC));\n\n        Map<String, Object> statMapMerged = DruidStatManagerFacade.mergeWallStat(statMapA, statMapB);\n        System.out.println(JSONUtils.toJSONString(statMapMerged));\n\n        assertEquals(2L, statMapMerged.get(\"checkCount\"));\n        assertEquals(21L, statMapMerged.get(\"violationEffectRowCount\"));\n        assertEquals(2, ((Collection<Map<String, Object>>) statMapMerged.get(\"blackList\")).size());\n\n        statMapMerged = DruidStatManagerFacade.mergeWallStat(statMapMerged, statMapC);\n        System.out.println(JSONUtils.toJSONString(statMapMerged));\n        assertEquals(2, ((Collection<Map<String, Object>>) statMapMerged.get(\"blackList\")).size());\n        assertEquals(33L, statMapMerged.get(\"violationEffectRowCount\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_update.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\nimport com.alibaba.druid.wall.spi.PGWallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_update {\n    private String sql = \"update t set fname = ? where fid = ?\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getUpdateCount());\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallProvider provider = new OracleWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getUpdateCount());\n    }\n\n    @Test\n    public void testPG() throws Exception {\n        WallProvider provider = new PGWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getUpdateCount());\n    }\n\n    @Test\n    public void testSQLServer() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        assertTrue(provider.checkValid(sql));\n        WallTableStat tableStat = provider.getTableStat(\"t\");\n        assertEquals(1, tableStat.getUpdateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_whiteList_syntaxError.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallContext;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.WallTableStat;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallStatTest_whiteList_syntaxError {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        WallContext.clearContext();\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setStrictSyntaxCheck(false);\n\n        String sql = \"select xx * x *\";\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"t\");\n            assertEquals(0, tableStat.getSelectCount());\n            assertEquals(0, provider.getBlackListHitCount());\n            assertEquals(0, provider.getWhiteListHitCount());\n            assertEquals(0, provider.getWhiteList().size());\n            assertEquals(0, provider.getBlackList().size());\n            assertEquals(1, provider.getCheckCount());\n            assertEquals(1, provider.getSyntaxErrorCount());\n            assertEquals(1, provider.getHardCheckCount());\n        }\n\n        assertTrue(provider.checkValid(sql));\n        {\n            WallTableStat tableStat = provider.getTableStat(\"t\");\n            assertEquals(0, tableStat.getSelectCount());\n            assertEquals(0, provider.getBlackListHitCount());\n            assertEquals(0, provider.getWhiteListHitCount());\n            assertEquals(0, provider.getWhiteList().size());\n            assertEquals(0, provider.getBlackList().size());\n            assertEquals(2, provider.getCheckCount());\n            assertEquals(2, provider.getSyntaxErrorCount());\n            assertEquals(2, provider.getHardCheckCount());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallTruncateTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallTruncateTest {\n    private String sql = \"TRUNCATE TABLE T1\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        //config.setTruncateAllow(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        WallConfig config = new WallConfig();\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        WallConfig config = new WallConfig();\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n\n    @Test\n    public void testMySql_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setTruncateAllow(false);\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setTruncateAllow(false);\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallTruncateTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallTruncateTest1 {\n    private String sql = \"TRUNCATE TABLE T1\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setTruncateAllow(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，被攻击者用于测试当前SQL拥有多少字段\n *\n * @author wenshao\n */\npublic class WallUnionTest {\n    private static final String UNION_SQL1 = \"select f1, f2 from t where f1=1 union select 1, 2\";\n    private static final String UNION_SQL2 = \"select f1, f2 from t where f1=1 union select 1, 2 --\";\n\n    @Test\n    public void testMySql() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(false);\n        config.setCommentAllow(true);\n        assertTrue(WallUtils.isValidateMySql(UNION_SQL1, config));\n        assertTrue(WallUtils.isValidateMySql(UNION_SQL2, config));\n\n        config.setSelectUnionCheck(true);\n        config.setCommentAllow(false);\n        assertFalse(WallUtils.isValidateMySql(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateMySql(UNION_SQL2, config));\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(false);\n        config.setCommentAllow(true);\n        assertTrue(WallUtils.isValidateOracle(UNION_SQL1, config));\n        assertTrue(WallUtils.isValidateOracle(UNION_SQL2, config));\n\n        config.setSelectUnionCheck(true);\n        config.setCommentAllow(false);\n        assertFalse(WallUtils.isValidateOracle(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateOracle(UNION_SQL2, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，被攻击者用于测试当前SQL拥有多少字段\n *\n * @author wenshao\n */\npublic class WallUnionTest2 {\n    public static final String UNION_SQL1 = \"select f1, f2 from t where f1 = 1 union select 1, 2 where 1 = 1\";\n    public static final String UNION_SQL2 = \"select f1, f2 from t where f1 = 1 union select 1, 2 where 1 = 1 --\";\n\n    @Test\n    public void testMySql() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(true);\n        config.setSelectWhereAlwayTrueCheck(true);\n        config.setCommentAllow(true);\n        assertFalse(WallUtils.isValidateMySql(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateMySql(UNION_SQL2, config));\n\n        config.setSelectUnionCheck(false);\n        config.setSelectWhereAlwayTrueCheck(false);\n        config.setCommentAllow(false);\n        assertTrue(WallUtils.isValidateMySql(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateMySql(UNION_SQL2, config));\n    }\n\n    @Test\n    public void testOracle() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(true);\n        config.setSelectWhereAlwayTrueCheck(true);\n        config.setCommentAllow(true);\n        assertFalse(WallUtils.isValidateOracle(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateOracle(UNION_SQL2, config));\n\n        config.setSelectUnionCheck(false);\n        config.setSelectWhereAlwayTrueCheck(false);\n        config.setCommentAllow(false);\n        assertTrue(WallUtils.isValidateOracle(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateOracle(UNION_SQL2, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，被攻击者用于测试当前SQL拥有多少字段\n *\n * @author wenshao\n */\npublic class WallUnionTest3 {\n    @Test\n    public void testMySql() throws Exception {\n//        assertFalse(WallUtils.isValidateMySql(\"SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,'x'\"));\n//        assertFalse(WallUtils.isValidateMySql(\"SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,'x';\"));\n        assertFalse(WallUtils.isValidateMySql(\"SELECT id, product FROM test.test t LIMIT 0,0 UNION ALL SELECT 1,'x'/*,10 ;\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUnionTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，被攻击者用于测试当前SQL拥有多少字段\n *\n * @author wenshao\n */\npublic class WallUnionTest4 {\n    public static final String UNION_SQL1 = \"SELECT id, product FROM T1 t where id=1 UNION (SELECT * FROM (SELECT 1,'x') X)\";\n    public static final String UNION_SQL2 = \"SELECT id, product FROM T1 t where id=1 UNION (SELECT * FROM (SELECT 1,'x') X) -- \";\n\n    @Test\n    public void testMySql() throws Exception {\n        final WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(true);\n        assertFalse(WallUtils.isValidateMySql(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateMySql(UNION_SQL2, config));\n\n        config.setSelectUnionCheck(false);\n        config.setSelectWhereAlwayTrueCheck(false);\n        config.setCommentAllow(true);\n        assertTrue(WallUtils.isValidateMySql(UNION_SQL1, config));\n        assertTrue(WallUtils.isValidateMySql(UNION_SQL2, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        final WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(true);\n        assertFalse(WallUtils.isValidateOracle(UNION_SQL1, config));\n        assertFalse(WallUtils.isValidateOracle(UNION_SQL2, config));\n\n        config.setSelectUnionCheck(false);\n        config.setSelectWhereAlwayTrueCheck(false);\n        config.setCommentAllow(true);\n        assertTrue(WallUtils.isValidateOracle(UNION_SQL1, config));\n        assertTrue(WallUtils.isValidateOracle(UNION_SQL2, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateCheckTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallUpdateCheckHandler;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 13/08/2017.\n */\npublic class WallUpdateCheckTest {\n    private MySqlWallProvider wallProvider = new MySqlWallProvider();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Properties properties = new Properties();\n        properties.put(\"druid.wall.updateCheckColumns\", \"t_orders.status\");\n        wallProvider.getConfig().configFromProperties(properties);\n    }\n\n    @Test\n    public void test_update_check_handler() throws Exception {\n        {\n            WallCheckResult result = wallProvider.check(\"update t_orders set status = 3 where id = 3 and status = 4\");\n            assertTrue(result.getViolations().isEmpty());\n        }\n        wallProvider.getConfig().setUpdateCheckHandler(new WallUpdateCheckHandler() {\n            @Override\n            public boolean check(String table, String column, Object setValue, List<Object> filterValues) {\n                return false;\n            }\n        });\n        {\n            WallCheckResult result = wallProvider.check(\"update t_orders set status = 3 where id = 3 and status = 4\");\n            assertTrue(result.getViolations().size() > 0);\n        }\n        wallProvider.getConfig().setUpdateCheckHandler(new WallUpdateCheckHandler() {\n            @Override\n            public boolean check(String table, String column, Object setValue, List<Object> filterValues) {\n                return true;\n            }\n        });\n        {\n            WallCheckResult result = wallProvider.check(\"update t_orders set status = 3 where id = 3 and status = 4\");\n            assertTrue(result.getViolations().isEmpty());\n        }\n        assertEquals(0, wallProvider.getWhiteListHitCount());\n        assertEquals(0, wallProvider.getBlackListHitCount());\n        wallProvider.getConfig().setUpdateCheckHandler(new WallUpdateCheckHandler() {\n            @Override\n            public boolean check(String table, String column, Object setValue, List<Object> filterValues) {\n                //增加对in语句的支持， status in (1, 2) 应该返回的filterValue为1和2\n                assertTrue(filterValues.size() == 2);\n                return true;\n            }\n        });\n        {\n            WallCheckResult result = wallProvider.check(\"update t_orders set status = 3 where id = 3 and status in (1, 2)\");\n            assertTrue(result.getViolations().isEmpty());\n        }\n        {\n            WallCheckResult result = wallProvider.check(\"update t_orders set status = 3 where id = 3 and status = 3 and status in (3, 4)\");\n            assertTrue(result.getViolations().isEmpty());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallUpdateTest {\n    private String sql = \"UPDATE T_USER SET FNAME = ? WHERE FID = ?\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setDeleteAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallUpdateTest1 {\n    private String sql = \"UPDATE T_USER SET FNAME = ? WHERE FID = ?\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setUpdateAllow(false);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallUpdateTest2 {\n    private String sql = \"UPDATE T_USER SET FNAME = ?\";\n\n    @Test\n    public void testMySql_true() throws Exception {\n        WallConfig config = new WallConfig();\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE_true() throws Exception {\n        WallConfig config = new WallConfig();\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n\n    @Test\n    public void testMySql_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setUpdateAllow(false);\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setUpdateAllow(false);\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测\n *\n * @author wenshao\n */\npublic class WallUpdateTest3 {\n    private String sql = \"UPDATE T_USER SET FNAME = ? WHERE 1 = 1\";\n    private String sql2 = \"UPDATE T_USER SET FNAME = ? WHERE id = 1 or 1 = 1\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setUpdateAllow(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        config.setUpdateWhereAlwayTrueCheck(true);\n        config.setConditionAndAlwayTrueAllow(false);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n        assertFalse(WallUtils.isValidateMySql(sql2, config));\n\n        config.setUpdateWhereAlwayTrueCheck(false);\n        config.setConditionAndAlwayTrueAllow(true);\n        assertTrue(WallUtils.isValidateMySql(sql2, config));\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        config.setUpdateWhereAlwayTrueCheck(true);\n        config.setConditionAndAlwayTrueAllow(false);\n\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n        assertFalse(WallUtils.isValidateOracle(sql2, config));\n\n        config.setUpdateWhereAlwayTrueCheck(false);\n        config.setConditionAndAlwayTrueAllow(true);\n        assertTrue(WallUtils.isValidateOracle(sql2, config));\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallUpdateTest4 {\n    private String sql = \"UPDATE T_USER SET FNAME = ? WHERE FID = ? OR 1 = 1\";\n\n    private WallConfig config = new WallConfig();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        config.setUpdateAllow(true);\n    }\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateWhereTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景，检测可疑的Having条件\n *\n * @author wenshao\n */\npublic class WallUpdateWhereTest {\n    private String sql = \"UPDATE T SET F1 = 0 WHERE 1 = 1\";\n    private String sql2 = \"UPDATE T SET F1 = 0 WHERE id=0 and 1 = 1\";\n\n    @Test\n    public void testMySql() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(sql));\n        assertTrue(WallUtils.isValidateMySql(sql2));\n        final WallConfig config = new WallConfig();\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setUpdateWhereAlwayTrueCheck(true);\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n        assertTrue(WallUtils.isValidateMySql(sql2, config));\n\n        config.setConditionAndAlwayTrueAllow(false);\n        config.setUpdateWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        assertFalse(WallUtils.isValidateMySql(sql2, config));\n    }\n\n    @Test\n    public void testORACLE() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(sql));\n        assertTrue(WallUtils.isValidateOracle(sql2));\n        final WallConfig config = new WallConfig();\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setUpdateWhereAlwayTrueCheck(true);\n        assertFalse(WallUtils.isValidateOracle(sql, config));\n        assertTrue(WallUtils.isValidateOracle(sql2, config));\n\n        config.setConditionAndAlwayTrueAllow(false);\n        config.setUpdateWhereAlwayTrueCheck(false);\n        assertTrue(WallUtils.isValidateOracle(sql, config));\n        assertFalse(WallUtils.isValidateOracle(sql2, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallUpdateWhereTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author wenshao\n */\npublic class WallUpdateWhereTest1 {\n    private String sql = \"update wx_shop set shop_view = shop_view + 1 where id = 118 OR 69=69 LIMIT 100 --\";\n    private String sql1 = \"update wx_shop set shop_view = shop_view + 1 where id = 118 OR 69=69 LIMIT 100 #and c=1\";\n\n    @Test\n    public void test_check_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setUpdateWhereAlwayTrueCheck(true);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setCommentAllow(true);\n\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n        assertFalse(WallUtils.isValidateMySql(sql1, config));\n    }\n\n    @Test\n    public void test_check_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setUpdateWhereAlwayTrueCheck(false);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setCommentAllow(true);\n\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n        assertTrue(WallUtils.isValidateMySql(sql1, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallVisitorUtilsLargeOrTest.java",
    "content": "package com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallVisitorUtilsLargeOrTest {\n    @Test\n    public void test_largeOr() throws Exception {\n        StringBuilder buf = new StringBuilder();\n        buf.append(\"ID = 1\");\n        for (int i = 2; i <= 1000 * 10; ++i) {\n            buf.append(\" OR ID = \" + i);\n        }\n\n        assertEquals(null, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(buf.toString())));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/WallVisitorUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.wall.spi.WallVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WallVisitorUtilsTest {\n    @Test\n    public void test_isTrue() throws Exception {\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"1 != 2\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"1 != 2 AND 2 = 2\")));\n        assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"1 != 2 AND 2 != 2\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"23 = 23\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"NOT 23 != 23\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"f1 like '%'\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"f1 like '%%'\")));\n        assertEquals(null, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"a1 = b1 AND f1 like '%%'\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"a1 = b1 OR f1 like '%%'\")));\n\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"1 < 2\")));\n        assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"2 < 2\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"2 <= 2\")));\n\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"2 > 1\")));\n        assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"2 > 2\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"2 >= 2\")));\n\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"len('44') > 0\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"len('44') >= 2\")));\n\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"(select count(*) from t) > 0\")));\n        assertEquals(Boolean.TRUE,\n                WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"(select count(*) from t) >= 0\")));\n        assertEquals(Boolean.FALSE,\n                WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"(select count(*) from t) < 0\")));\n        assertEquals(Boolean.TRUE,\n                WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"NOT (select count(*) from t) < 0\")));\n\n        //\n    }\n\n    @Test\n    public void test_chr() throws Exception {\n        assertEquals(\"CAT\", WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"CHR(67)||CHR(65)||CHR(84)\")));\n        assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr(\"CHR(67)||CHR(65)||CHR(84) = 'CAT'\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallDescribteTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问Oracle系统对象\n *\n * @author admin\n */\npublic class MySqlWallDescribteTest {\n    @Test\n    public void test_allow() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDescribeAllow(true);\n\n        assertTrue(WallUtils.isValidateMySql(\"describe t\", config));\n    }\n\n    @Test\n    public void test_not_allow() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setDescribeAllow(false);\n\n        assertFalse(WallUtils.isValidateMySql(\"describe t\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallLimitTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问MySql系统函数\n *\n * @author admin\n */\npublic class MySqlWallLimitTest {\n    @Test\n    public void test_permitTable() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"SELECT * FROM T LIMIT 0\"));\n        assertFalse(WallUtils.isValidateMySql(\"SELECT * FROM T LIMIT 10, 0\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallLoadDataInfileTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问MySql系统函数\n *\n * @author admin\n */\npublic class MySqlWallLoadDataInfileTest {\n    @Test\n    public void test_permit_stmt() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"load data infile 'c:/boot.ini' into table foo\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallPermitFunctionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallPermitFunctionTest {\n    @Test\n    public void test_permitTable() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"SELECT *FROM T UNION SELECT User,Password FROM mysql.user\"));\n        assertFalse(WallUtils.isValidateMySql(\"SELECT *FROM T UNION SELECT User,Password FROM `mysql`.`user`\"));\n        assertFalse(WallUtils.isValidateMySql(\"SELECT *FROM T UNION SELECT User,Password FROM \\\"mysql\\\".\\\"user\\\"\"));\n        assertFalse(WallUtils.isValidateMySql(\"SELECT *FROM T UNION SELECT User,Password FROM MYSQL.USER\"));\n    }\n\n    @Test\n    public void test_permitTable_subquery() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(\"select * from(SELECT User,Password FROM mysql.user) a\"));\n        assertTrue(WallUtils.isValidateMySql(\"select * from(SELECT User,Password FROM `mysql`.`user`) a\"));\n        assertTrue(WallUtils.isValidateMySql(\"select * from(SELECT User,Password FROM \\\"mysql\\\".\\\"user\\\") a\"));\n        assertTrue(WallUtils.isValidateMySql(\"select * from(SELECT User,Password FROM MYSQL.USER) a\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallPermitTableTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallPermitTableTest {\n    @Test\n    public void test_default_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(\"select * from t union select benchmark( 500000, sha1( 'test' ) ) FROM X\"));\n    }\n\n    @Test\n    public void test_default_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"select * from t where fid = 1 union select benchmark( 500000, sha1( 'test' ) ) FROM X\"));\n    }\n\n    @Test\n    public void test_allow() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setTableCheck(false);\n\n        assertTrue(WallUtils.isValidateMySql(\"select benchmark( 500000, sha1( 'test' ) ) FROM X\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallPermitVariantTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问Oracle系统对象\n *\n * @author admin\n */\npublic class MySqlWallPermitVariantTest {\n    private String sql = \"select * FROM X where id=1 or version=@@version_compile_os\";\n\n    @Test\n    public void test_allow() throws Exception {\n        MySqlWallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setVariantCheck(false);\n\n        assertTrue(provider.checkValid(sql));\n    }\n\n    @Test\n    public void test_not_allow() throws Exception {\n        MySqlWallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setVariantCheck(true);\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest {\n    @Test\n    public void testWall() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(\"SELECT * FROM X where id=1 and 1!=1 union select 14,13,12,11,10,@@version_compile_os,8,7,6,5,4,3,2,1 FROM X\"));\n        assertTrue(WallUtils.isValidateMySql(\"select '@@version_compile_os' FROM X\"));\n\n        assertFalse(WallUtils.isValidateMySql(\"SELECT * FROM X where id=1 and 1!=1 union select hex(load_file(0x633A2F77696E646F77732F7265706169722F73616D))\"));\n        assertTrue(WallUtils.isValidateMySql(\"select hex(load_file(0x633A2F77696E646F77732F7265706169722F73616D))\"));\n        assertTrue(WallUtils.isValidateMySql(\"select 'hex(load_file(0x633A2F77696E646F77732F7265706169722F73616D))'\"));\n\n        assertFalse(WallUtils.isValidateMySql(\"select * from t where fid = 1 union select 15,version() FROM X\"));\n        assertTrue(WallUtils.isValidateMySql(\"select 15,version() FROM X\"));\n        assertTrue(WallUtils.isValidateMySql(\"select 15,'version'\"));\n\n        assertFalse(WallUtils.isValidateMySql(\"SELECT *FROM T UNION select 1 from information_schema.columns\"));\n        assertTrue(WallUtils.isValidateMySql(\"select 'information_schema.columns'\"));\n\n        assertFalse(WallUtils.isValidateMySql(\"SELECT *FROM T UNION select 1 from mysql.user\"));\n        assertTrue(WallUtils.isValidateMySql(\"select 'mysql.user'\"));\n\n        assertFalse(WallUtils.isValidateMySql(\"select * FROM T WHERE id = 1 AND select 0x3C3F706870206576616C28245F504F53545B2763275D293F3E into outfile '\\\\www\\\\edu\\\\1.php'\"));\n        assertTrue(WallUtils.isValidateMySql(\"select 'outfile'\"));\n\n        //assertFalse(WallUtils.isValidateMySql(\"select f1, f2 from t where c1=1 union select 1, 2\"));\n\n        assertFalse(WallUtils.isValidateMySql(\"select c1 from t where 1=1 or id =1\"));\n        assertFalse(WallUtils.isValidateMySql(\"select c1 from t where id =1 or 1=1\"));\n        assertFalse(WallUtils.isValidateMySql(\"select c1 from t where id =1 || 1=1\"));\n\n        WallConfig config = new WallConfig();\n        config.setHintAllow(false);\n        assertFalse(WallUtils.isValidateMySql(\n                \"select * from person where id = '3'/**/union select v,b,a from (select 1,2,4/*! ,database() as b,user() as a,version() as v*/) a where '1'<>''\",\n                config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest1 {\n    @Test\n    public void test_stuff() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select count(*) from (select DATE_FORMAT(staydate,'%m月') as month,sum(a) as addnum,sum(q) as quitnum from (select staydate,1 as a,0 as q from add_person union all select quitdate,0 as a,1 as q from quit_person) t where  (DATE_FORMAT(staydate,'%Y')= ? )  group by DATE_FORMAT(staydate,'%Y-%m'))\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest10.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest10 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT t.*,a.param_id FROM lhwtag AS t RIGHT JOIN lhwtag_relation AS a USING(`tag_id`) WHERE a.`type_id`=1 AND a.`param_id` IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') ORDER BY t.`content_count`\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest100.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest100 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or substr(bin(97>>6), -1, 1) = 1\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest101.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest101 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or substr(bin(97>>6), -1, 1)\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest102.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest102 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or substr(bin(97>>5), -1, 1)\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest103.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest103 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or 97 & 1\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest104.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest104 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or 97 | 1\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest105.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest105 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or binary true\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest106.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest106 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or bin(1) = 1\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest107.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest107 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or bin(94) = 1011110\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest108.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest108 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * \\u0009 from t where id = ? or bin(94) = 1011110\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest109.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest109 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or 97 between 79 and 126\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest11.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest11 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT *, MATCH(question_content_fulltext) \" +\n                        \"AGAINST('2015431867 2636826089 3807520117 2796321160 2615920174' IN BOOLEAN MODE) AS score \" +\n                        \"FROM aws_question \" +\n                        \"WHERE MATCH(question_content_fulltext) \" +\n                        \"   AGAINST('2015431867 2636826089 3807520117 2796321160 2615920174' IN BOOLEAN MODE)  \" +\n                        \"ORDER BY score DESC, agree_count DESC LIMIT 10\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest110.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest110 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or 1 NOT between 79 and 126\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest111.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest111 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or 1 IN (1,2,3)\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest112.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest112 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or 4 NOT IN (1,2,3)\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest113.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest113 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or md5('a') = '0cc175b9c0f1b6a831c399e269772661'\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest114.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest114 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or BIT_COUNT(29) = 4\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest115.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest115 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or BIT_COUNT(b'101010') = 3\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest116.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest116 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or BIT_COUNT(3.5) = 1\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest117.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest117 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or SOUNDEX('Hello') = 'H400'\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest118.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest118 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or SPACE(6) = '      '\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest119.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest119 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin' AND 5376=3420 AND 'XSDD'='XSDD'\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest12.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest12 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT a.* FROM lhwbbs_threads a  \" +\n                        \"WHERE 1 AND a.disabled=0 AND a.ifupload&1=1  \" +\n                        \"ORDER BY a.created_time DESC  LIMIT 0,100\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest120.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest120 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin%' AND SLEEP(5) AND '%'=''\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest121.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest121 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin%' AND (SELECT 6384 FROM(SELECT COUNT(*),CONCAT(0x3a64686c3a,(SELECT (CASE WHEN (3252 = 3252) THEN 1 ELSE 0 END)),0x3a766f723a,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a) AND '%'=''\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest122.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest122 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin%' AND 4667=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||CHR(115)||CHR(114)||CHR(110)||CHR(58)||(SELECT (CASE WHEN (4667=4667) THEN 1 ELSE 0 END) FROM DUAL)||CHR(58)||CHR(106)||CHR(112)||CHR(122)||CHR(58)||CHR(62))) FROM DUAL) AND '%'=''\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest123.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest123 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin'||(SELECT 'tLrl' FROM DUAL WHERE 3240=3240 AND 5014=3795 )||''\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest124.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest124 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin' AND 5859=5666 AND 'Cuqo' LIKE 'Cuqo'\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest125.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest125 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin' AND 5963=CONVERT(INT,(CHAR(58)+CHAR(108)+CHAR(105)+CHAR(112)+CHAR(58)+(SELECT (CASE WHEN (5963=5963) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(58)+CHAR(117)+CHAR(107)+CHAR(114)+CHAR(58))) AND 'bSho' LIKE 'bSho'\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest126.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest126 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin'+(SELECT 'NtTK' WHERE 8000=8000 UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL#'\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest127.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest127 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like '-1079%' OR (8868=8022) AND '%'=''\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest128.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest128 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"SELECT name, '******' password, createTime from user where name like 'admin' AND (CASE WHEN (7885=7885) THEN 1 ELSE 0 END)\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest129.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport java.net.URLDecoder;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest129 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        assertTrue(provider.checkValid(\"select * from t where id = 1\"));\n\n        String sql = \"select * from t where id = \";\n        sql += URLDecoder.decode(\"999999.9%0A%2F*!30000union%0Aall%0Aselect%0A0x31303235343830303536%2Cconcat%280x7e%2C0x27%2C%28Select%0A%40%40version%29%2C0x27%2C0x7e%29%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536*%2F--\");\n\n        System.out.println(sql);\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest13.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest13 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT index_privacy AS index,msgboard_privacy AS messageboard,\" +\n                        \"photos_privacy AS photos,diary_privacy AS diary,\" +\n                        \"owrite_privacy AS weibo \" +\n                        \"FROM pw_ouserdata WHERE uid= ?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest130.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport java.net.URLDecoder;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest130 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        assertTrue(provider.checkValid(\"select * from t where id = 1\"));\n\n        String sql = \"select * from t where id = \";\n        sql += URLDecoder.decode(\"999999.9%0A%2F*!30000union%0Aall%0Aselect%0A0x31303235343830303536%2Cconcat%280x7e%2C0x27%2C%28Select%0A%40%40version%29%2C0x27%2C0x7e%29%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536%2C0x31303235343830303536*%2F\");\n\n        System.out.println(sql);\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest131.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest131 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(true);\n\n        assertFalse(provider.checkValid(\"select * from t where id = 1 /*!30000union all select 2*/\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest132.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest132 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(true);\n\n        assertFalse(provider.checkValid(\"select * from t where id = 1 UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10;\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest133.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest133 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(\"select * from t where id = 1 \"\n                + \"UNION SELECT @ from t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest134.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest134 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSelectUnionCheck(true);\n        assertTrue(provider.checkValid(\"SELECT 1 FROM dual WHERE 1 = '1'''''''''''''UNION SELECT '2';\"));\n        assertFalse(provider.checkValid(\"SELECT 1 FROM t WHERE 1 = '1'''''''''''''UNION SELECT '2' --;\")); //end of comment --> false\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest135.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest135 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(\"SELECT * FROM Users WHERE id = '1' AND MID(VERSION(),1,1) = '5';\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest136.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest136 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(\"SELECT * FROM Users WHERE id = '1' AND MID(@@VERSION,1,1) = '5';\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest137.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest137 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(\"select bi.title from bbt_item_chd_3 bi \"\n                + \"where bi.title = '具8\\\\'\\\\'/200mm迷OK-6295'\"\n                + \"  and bi.item_id <> null and bi.nick = '营店'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest138.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest138 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"INSERT INTO T01_CHECKIN_CUSTOMER\"\n                + \"(WEB_USER_ID,NAME,COUNTRY,PROVINCE,CITY\"\n                + \",POSTCODE,PHONE,FAX,EMAIL,ADDRESS,FIRST_NAME,LAST_NAME,sex) \"\n                + \"select 2,null,'4225',null,'beijing','','1','','1223@123.com','beijing','booking','test',null \"//\n                + \"from dual \"\n                + \"where not exists   (\"//\n                + \"    select EMAIL\"\n                + \"    from T01_CHECKIN_CUSTOMER\"\n                + \"    where WEB_USER_ID=2 and EMAIL='1223@123.com'\"\n                + \")\";\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest139.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest139 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"select count(1) as total \"//\n                + \" from (\"\n                + \"    select '' buyer_nick from dual \"\n                + \"    where 1=0  \"//\n                + \"    union \"\n                + \"    select distinct buyer_nick \"//\n                + \"    from sys_info.orders \"//\n                + \"    where 1=1  and receiver_district in ('平谷区')\"\n                + \") a \"\n                + \"inner join (\"\n                + \"    select buyer_nick from (\"//\n                + \"        select distinct buyer_nick \"//\n                + \"        from sys_info.orders \"\n                + \"        where 1=1  and created > '2013-07-28' \"//\n                + \"    ) recent_days \"\n                + \"inner join (\"\n                + \"    select distinct buyer_nick \"\n                + \"    from sys_info.orders \"\n                + \"    where 1=1  and seller_nick in ('创维官方旗舰店') \"\n                + \"    ) seller_nick using(buyer_nick) \"//\n                + \") b using(buyer_nick)\";\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest14.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest14 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT index_privacy AS index,info_privacy AS ?,msgboard_privacy AS messageboard,photos_privacy AS photos,\" +\n                        \"diary_privacy AS diary,owrite_privacy AS weibo \" +\n                        \"FROM pw_ouserdata WHERE uid= ?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest140.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest140 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"SELECT name, '******' password, createTime from user \"\n                + \"where name like 'admin%' \"//\n                + \"    AND 8600=CONVERT(INT,(SELECT CHAR(113)+CHAR(118)+CHAR(100)+CHAR(114)+CHAR(113)+(SELECT (CASE WHEN (8600=8600) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(113)+CHAR(118)+CHAR(98)+CHAR(97)+CHAR(113))) AND '%'=''\";\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest141.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest141 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"SELECT name, '******' password, createTime from user where length(name) = 999999.9 or ascii(substring((database()),1,1))=127\";\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest142.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest142 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"SELECT * FROM `my_crons` WHERE 1 AND nextrun = '0' \";\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest143.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest143 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"SELECT\"\n                + \" `Extent1`.`ID`, \"\n                + \" `Extent1`.`State`, \"\n                + \" `Extent1`.`CreateTime`, \"\n                + \" `Extent1`.`UpdateTime`, \"\n                + \" `Extent1`.`OpeningBank`, \"\n                + \" `Extent1`.`BankAccount`, \"\n                + \" `Extent1`.`BankAccountName`, \"\n                + \" `Extent1`.`Zone`, \"\n                + \" `Extent1`.`AccountantMobile`, \"\n                + \" `Extent1`.`IsPublic`\"\n                + \" FROM `paybank` AS `Extent1`\"\n                + \" WHERE (`Extent1`.`State` > -1)\"\n                + \" AND ((`Extent1`.`Zone`) = (CASE WHEN (1 IS  NULL) THEN (1)  ELSE (1) END))\";\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest144.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest144 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"select min(id) from wx_interact where activityid=1008 group by true_name,mobile having rand()<1\";\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest145.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest145 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"SHOW FULL TABLES WHERE Table_type != 'VIEW'\";\n        assertTrue(\n                provider.checkValid(sql)\n        );\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest146.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest146 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"ALTER TABLE project_measures\\n\" +\n                \"        DROP COLUMN diff_value_1,\\n\" +\n                \"        DROP COLUMN diff_value_2,\\n\" +\n                \"        DROP COLUMN diff_value_3,\\n\" +\n                \"        ADD COLUMN variation_value_1 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_2 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_3 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_4 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_5 DECIMAL(30, 20) NULL DEFAULT NULL\";\n        assertTrue(\n                provider.checkValid(sql)\n        );\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest147_optimize.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest147_optimize {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"optimize table table1\";\n        assertTrue(\n                provider.checkValid(sql)\n        );\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest148.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest148 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"select * from TABLENAME cfgdatasou0_ where cfgdatasou0_.type=? and cfgdatasou0_.module_name=? and cfgdatasou0_.node_type=? or cfgdatasou0_.type=? and cfgdatasou0_.module_name=? and cfgdatasou0_.node_type=? or cfgdatasou0_.type=? and cfgdatasou0_.module_name=? and cfgdatasou0_.node_type=?\";\n\n        assertTrue(\n                provider.checkValid(sql)\n        );\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest149.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest149 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        String sql = \"select t1.teacher_id from teacher_1 t1 left join teacher_2 t2 on t1.teacher_id\";\n\n        assertFalse(\n                provider.checkValid(sql)\n        );\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest15.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest15 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT m.*, m.icon AS micon, md.uid as md.uid, md.lastmsg,md.postnum,\" +\n                        \"md.rvrc,md.money,md.credit,md.currency,md.lastvisit,md.thisvisit,\" +\n                        \"md.onlinetime,md.lastpost,md.todaypost, md.monthpost,md.onlineip,\" +\n                        \"md.uploadtime,md.uploadnum,md.starttime,md.pwdctime,md.monoltime,\" +\n                        \"md.digests,md.f_num,md.creditpop, md.jobnum,md.lastgrab,md.follows,md.fans,\" +\n                        \"md.newfans,md.newreferto,md.newcomment,md.postcheck,md.punch, mi.customdata \" +\n                        \"FROM pw_members m \" +\n                        \"   LEFT JOIN pw_memberdata md ON m.uid=md.uid \" +\n                        \"   LEFT JOIN pw_memberinfo mi ON mi.uid=m.uid \" +\n                        \"WHERE m.uid IN (?)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest150.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest150 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setSelectLimit(100);\n\n        String sql = \"select\\n\" +\n                \"a.main_card_no as card_no, a.city, a.bussiness_type, 'main' as card_type,\\n\" +\n                \"c.company_name as company, a.status_flag,\\n\" +\n                \"a.card_balance as balance from oil_card_main a left join oil_company c on c.company_id=a.company_id\\n\" +\n                \"\\n\" +\n                \"union all\\n\" +\n                \"\\n\" +\n                \"select\\n\" +\n                \"b.card_no,b.city,b.bussiness_type,'secon' as card_type,c.company_name as company,\\n\" +\n                \"b.status_flag,b.card_balance as balance\\n\" +\n                \"from oil_card_associate b left join oil_card_main a\\n\" +\n                \"on a.main_card_no = b.main_card_no\\n\" +\n                \"left join oil_company c on c.company_id=a.company_id\";\n\n//        assertTrue(\n//                provider.checkValid(sql)\n//        );\n\n        WallCheckResult result = provider.check(sql);\n        assertEquals(0, result.getViolations().size());\n        String wsql = result\n                .getStatementList().get(0).toString();\n\n        assertEquals(\"SELECT a.main_card_no AS card_no, a.city, a.bussiness_type, 'main' AS card_type, c.company_name AS company\\n\" +\n                \"\\t, a.status_flag, a.card_balance AS balance\\n\" +\n                \"FROM oil_card_main a\\n\" +\n                \"\\tLEFT JOIN oil_company c ON c.company_id = a.company_id\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT b.card_no, b.city, b.bussiness_type, 'secon' AS card_type, c.company_name AS company\\n\" +\n                \"\\t, b.status_flag, b.card_balance AS balance\\n\" +\n                \"FROM oil_card_associate b\\n\" +\n                \"\\tLEFT JOIN oil_card_main a ON a.main_card_no = b.main_card_no\\n\" +\n                \"\\tLEFT JOIN oil_company c ON c.company_id = a.company_id\\n\" +\n                \"LIMIT 100\", wsql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest151_update.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest151_update {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setSelectLimit(100);\n\n        String sql = \"update twogradeestate set layarea=layarea+97.0, selfarea=selfarea-97.0, sysmoddate='2016-12-21' where tgeid='0012002'\";\n\n        WallCheckResult result = provider.check(sql);\n        assertEquals(0, result.getViolations().size());\n        String wsql = result\n                .getStatementList().get(0).toString();\n\n        assertEquals(\"UPDATE twogradeestate\\n\" +\n                \"SET layarea = layarea + 97.0, selfarea = selfarea - 97.0, sysmoddate = '2016-12-21'\\n\" +\n                \"WHERE tgeid = '0012002'\", wsql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest152.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest152 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setSelectLimit(100);\n\n        String sql = \"SELECT version FROM schema_migrations\";\n\n//        assertTrue(\n//                provider.checkValid(sql)\n//        );\n\n        WallCheckResult result = provider.check(sql);\n        assertEquals(0, result.getViolations().size());\n        String wsql = result\n                .getStatementList().get(0).toString();\n\n        assertEquals(\"SELECT version\\n\" +\n                \"FROM schema_migrations\\n\" +\n                \"LIMIT 100\", wsql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest16.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest16 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * FROM lhwbbs_threads_cate_index FORCE INDEX(PRIMARY) WHERE cid=? AND disabled=? ORDER BY tid DESC LIMIT ?,?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest17.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest17 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"DELETE FROM as_home_notification WHERE uid>? AND new=? AND dateline<?-?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest18.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest18 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SET character_set_connection=gbk,character_set_results=gbk,character_set_client=binary\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest19.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest19 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select @@basedir\"));\n    }\n\n    @Test\n    public void test_true2() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select @@basedir FROM X\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * FROM X where id=1 and dir=@@basedir\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest2 {\n    @Test\n    public void test_stuff() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select * from person_qingjia \" +\n                        \"where isxiao=1  \" +\n                        \"and ((starttime between 2013-01-15 and 2013-01-15)\" +\n                        \"        or (endtime between 2013-01- 15 and 2013-01-15)\" +\n                        \") \" +\n                        \"order by xiaojiatime desc\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest20.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest20 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SET sql_mode=?,NAMES ?,CHARACTER SET utf8,CHARACTER_SET_RESULTS=utf8,COLLATION_CONNECTION=?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest21.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest21 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select * from t where 1=1 AND status = 1\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where status = 1 OR 1=1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest22.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest22 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT count(*) AS num FROM hkapp_goods WHERE  1=1  AND status=1 AND level=1\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT count(*) AS num FROM hkapp_goods WHERE  status=1 AND level=1 OR 1=1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest23.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest23 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select count(*) total from utao_goods where 1=1  and pprice between 0 and 99999 and state=1\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select count(*) total from utao_goods where pprice between 0 and 99999 and state=1 or 1=1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest24.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest24 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT count(*) AS num FROM hkapp_goods WHERE  1=1  AND status=1 AND level=1 AND xxx = 1\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT count(*) AS num FROM hkapp_goods WHERE  status=1 AND level=1 AND xxx = 1 OR 1=1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest25.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest25 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"update test.dml_health_check set id=? limit ?\"));\n    }\n\n    @Test\n    public void test_true_1() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"update test.dml_health_check set id=?\"));\n    }\n\n    @Test\n    public void test_true_2() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setUpdateWhereNoneCheck(true);\n        assertTrue(WallUtils.isValidateMySql(//\n                \"update test.dml_health_check set id=? limit ?\", config));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setUpdateWhereNoneCheck(true);\n\n        assertFalse(WallUtils.isValidateMySql(//\n                \"update test.dml_health_check set id=?\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest26.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest26 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"delete from cmsdj_feed where DATEDIFF(DATE(cd_addtime),?)<=-?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest27.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest27 {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR hex('abc') = '616263'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest28.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest28 {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR hex(123) = '7B'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest29.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest29 {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR UNHEX('4D7953514C') = 'MySQL'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest3 {\n    @Test\n    public void test_stuff() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT COUNT(p.id) FROM TB_PRO p\" +\n                        \"        INNER JOIN   TB_Db  b ON b.id =p.dbid \" +\n                        \"        WHERE p.index_status='0' AND p.sc=?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest30.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest30 {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR UNHEX(HEX('MySQL')) = 'MySQL'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest31.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest31 {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR UNHEX(HEX(FNAME)) = FNAME\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest32.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest32 {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR NOT(UNHEX(HEX(FNAME)) != FNAME)\"));\n    }\n\n    @Test\n    public void test_false_1() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR NOT(UNHEX(HEX(FNAME)) > FNAME)\"));\n    }\n\n    @Test\n    public void test_false_2() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR NOT(UNHEX(HEX(FNAME)) < FNAME)\"));\n    }\n\n    @Test\n    public void test_false_3() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from t where FID = 1 OR NOT(UNHEX(HEX(FNAME)) NOT LIKE FNAME)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest33.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest33 {\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"DELETE FROM lhwdesign_data WHERE data_id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?\"));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setStrictSyntaxCheck(false);\n        assertTrue(WallUtils.isValidateMySql(//\n                \"DELETE FROM lhwdesign_data WHERE data_id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest34.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest34 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT @@sql_big_selects\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest35.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest35 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"REPLACE INTO `test2tb` VALUES \" +\n                        \"('51', '6714105741', '亦美珊不掉正品隐形文胸安全硅胶文胸 小胸聚拢比基尼<span class=H>游泳</span>衣泳装', 'http://img03.taobaocdn.com/bao/uploaded/i3/16011019585534199/T1cnlaXA8bXXXXXXXX_!!0-item_pic.jpg', 'liqiang198163', 'c', '25.00', '20.00', '1000.00', '76', '529', '4.86', '4.91', '4.90', '0.00', '4.80', '2878', '77', '12', '15');\"));\n\n        assertEquals(1, provider.getTableStat(\"test2tb\").getReplaceCount());\n        System.out.println(JSONUtils.toJSONString(provider.getStatsMap()));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest36.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest36 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"select *  FROM `13452845947`   WHERE gpstime < (now()-90) order by gpstime desc\"));\n\n        assertEquals(1, provider.getTableStat(\"13452845947\").getSelectCount());\n        System.out.println(JSONUtils.toJSONString(provider.getStatsMap()));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest37.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest37 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"call partnerAttribute(3061975048797781,105385028,5,@ret)\"));\n\n        assertEquals(0, provider.getTableStats().size());\n        System.out.println(JSONUtils.toJSONString(provider.getStatsMap()));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest38.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest38 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"/* mysql-connector-java-5.1.20 ( Revision: tonci.grgin@oracle.com-20111003110438-qfydx066wsbydkbw ) */SELECT @@session.auto_increment_increment\"));\n\n        assertEquals(0, provider.getTableStats().size());\n        System.out.println(JSONUtils.toJSONString(provider.getStatsMap()));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest39.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest39 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"COMMIT\"));\n\n        assertEquals(0, provider.getTableStats().size());\n        System.out.println(JSONUtils.toJSONString(provider.getStatsMap()));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest4 {\n    @Test\n    public void test_stuff() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SSELECT a.*,b.name FROM vote_info a left join vote_item b on a.item_id=b.id where a.id<10 or 1=1 limit 1,10\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest40.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest40 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setUseAllow(false);\n\n        assertFalse(provider.checkValid(//\n                \"use huaianapp\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"use huaianapp\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest41.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest41 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM pw_pushdata WHERE invokepieceid= '49'  AND ifverify=0 AND starttime<= '1364976942'  ORDER BY vieworder DESC,starttime DESC  LIMIT 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest42.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest42 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT COUNT(1) AS count FROM `team` \" +\n                        \"WHERE `team_type` = 'normal'  AND `city_id` IN (0,10) \" +\n                        \"AND (begin_time <= '1364832000')AND (end_time > '1364873430')AND (( title like '%%' ))AND (( `team_price` > '151' AND `team_price` <= '200'))AND ((now_number >= min_number)OR (end_time > '1364832000'))AND (group_id = 9 OR sub_id = 9)\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest43.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest43 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setConditionAndAlwayTrueAllow(false);\n        assertFalse(provider.checkValid(//\n                \"SELECT COUNT(1) AS count FROM `team` \" +\n                        \"WHERE `team_type` = 'normal' AND 1 = 1 AND `city_id` IN (0,10)\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setConditionAndAlwayTrueAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT COUNT(1) AS count FROM `team` \" +\n                        \"WHERE `team_type` = 'normal' AND 1 = 1 AND `city_id` IN (0,10)\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false2() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT COUNT(1) AS count FROM `team` \" +\n                        \"WHERE `team_type` = 'normal' AND 1 = 2 AND `city_id` IN (0,10)\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_true2() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setConditionAndAlwayFalseAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT COUNT(1) AS count FROM `team` \" +\n                        \"WHERE `team_type` = 'normal' AND 1 = 2 AND `city_id` IN (0,10)\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest44.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest44 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM pw_pushdata WHERE invokepieceid= '49'  AND ifverify=0 AND starttime<= '1365331510'  ORDER BY vieworder DESC,starttime DESC  LIMIT 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest45.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest45 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT @1119453529t_processID, @1119453529t_ret\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest46.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest46 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"select aid,subject,dateline from www_subject where subject like '%%' order by aid desc limit 30;\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest47.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest47 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"update Fans,\" +\n                        \" (select 361659 as ToID, 5 as Score \" +\n                        \"   union all select 382885 as ToID, 2 as Score\" +\n                        \"   union all select 407537 as ToID, 6 as Score) temp  \" +\n                        \"set Fans.score = Fans.score+temp.Score \" +\n                        \"where Fans.FansID = 382885 and Fans.UserID = temp.ToID\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest48.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest48 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"select sum(size) as total \" +\n                        \"from file \" +\n                        \"join file_to_post on file_to_post.file_id = file.id \" +\n                        \"join notice on file_to_post.post_id = notice.id \" +\n                        \"where profile_id = 18544 and file.url like '%/notice/%/file' AND EXTRACT(month FROM file.modified) = EXTRACT(month FROM now()) and EXTRACT(year FROM file.modified) = EXTRACT(year FROM now())\"));\n\n        assertEquals(3, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest49.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest49 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"select temp.*, u.CanComment, u.CanBeShared, \" +\n                        \"   u.CanForward, COALESCE(b.UserID,0) as isBlocked, \" +\n                        \"   COALESCE(f.UserID,0) as Followed, COALESCE(ff.UserID,0) as IsFollowed, \" +\n                        \"   COALESCE(ul.UserID,0) as liked, \" +\n                        \"   COALESCE(fff.UserID,0) as RIsFollowed \" +\n                        \"from \" + \"(select 281319 as UserID, 0  as RUserID, 7797549 as PicID \" +\n                        \"   union all \" +\n                        \"   select 55608 as UserID, 0  as RUserID, 7797527 as PicID \" +\n                        \"   union all \" +\n                        \"   select 281319 as UserID, 0  as RUserID, 7797233 as PicID \" +\n                        \"   union all \" +\n                        \"   select 281319 as UserID, 0  as RUserID, 7797221 as PicID \" +\n                        \"   union all select 281319 as UserID, 0  as RUserID, 7797217 as PicID \" +\n                        \"   union all select 281319 as UserID, 0  as RUserID, 7797189 as PicID \" +\n                        \"   union all select 12271 as UserID, 0  as RUserID, 7796057 as PicID \" +\n                        \"   union all select 401697 as UserID, 494381  as RUserID, 7795057 as PicID \" +\n                        \"   union all select 401697 as UserID, 470693  as RUserID, 7795041 as PicID \" +\n                        \"   union all select 401697 as UserID, 470693  as RUserID, 7795039 as PicID) temp     \" +\n                        \"left join Users as u on u.UserID = temp.UserID   \" +\n                        \"left join BlockUser as b on b.UserID = temp.UserID and b.BlockUserID = 281319 \" +\n                        \"left join Fans as f on f.FansID = temp.UserID and f.UserID = 281319   \" +\n                        \"left join Fans as ff ON ff.FansID = 281319 and ff.UserID = temp.UserID   \" +\n                        \"left join Fans as fff ON fff.FansID = 281319 and fff.UserID = temp.RUserID   \" +\n                        \"left join UserLikes as ul on ul.PicID = temp.PicID and ul.UserID = 281319\"));\n\n        assertEquals(4, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest5 {\n    @Test\n    public void test_stuff() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select * from tbl_product WHERE delFlag=0 AND cateId = 40 OR EXTRACTVALUE(1,CONCAT(0x7c,database(),0x7c)) order by sort desc, productId desc limit 20,20\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest50.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest50 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SHOW /*  113.97.255.240 */ GLOBAL VARIABLES LIKE 'ft\\\\_min\\\\_word\\\\_len'\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest51.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest51 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"REPLACE /* SearchMySQL::update Wikiadmin */ INTO `wiki_searchindex` (si_page,si_title,si_text) VALUES ('15',' u8e5858d u8e8b4a3 u8e5a3b0 u8e6988e')\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest52.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest52 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setLimitZeroAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"select * from t limit 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"select * from t limit 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest53.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest53 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setLimitZeroAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"select * from t limit 0,0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"select * from t limit 0,0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest54.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest54 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(false);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT *FROM T UNION select `ENGINE`, `SUPPORT` from information_schema.Engines\"));\n\n        assertEquals(2, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT *FROM T UNION select `ENGINE`, `SUPPORT` from information_schema.Engines\"));\n\n        assertEquals(2, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest55.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest55 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT USER()\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_true_1() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT USER() FROM DUAL\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_true_2() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT USER() FROM X\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"select * from t where fid = 1 union SELECT USER() FROM X\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest56.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest56 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SHOW GRANTS FOR CURRENT_USER()\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest57.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest57 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT @@version\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_true_1() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT @@version FROM DUAL\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_true_2() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT @@version FROM X\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM X where id=1 and 1!=1 union select @@version\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest58.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest58 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(false);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT COUNT(*) FROM information_schema.processlist \" +\n                        \"WHERE user <> 'replication' AND id <> CONNECTION_ID() \" +\n                        \"AND time > 60 AND command <> 'Sleep'\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest59.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest59 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT * FROM mysql.proc \" +\n                        \"WHERE 1=1 AND db LIKE 'dsmessagedb001'\" +\n                        \" AND name LIKE 'Proc_getRemindinfoByRemindFlag'\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest6 {\n    @Test\n    public void test_stuff() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT a.* FROM vote_info a where a.id<10 or (id <5 or 1=1) limit 1,10\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest60.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest60 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"show create table `mysql`.`help_relation`\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest61.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest61 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT * FROM `information_schema`.`columns` WHERE TABLE_NAME='aaaa' AND TABLE_SCHEMA='xxxx'\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T \" +\n                        \"UNION \" +\n                        \"SELECT * FROM `information_schema`.`columns` WHERE TABLE_NAME='aaaa' AND TABLE_SCHEMA='xxxx'\"));\n\n        assertEquals(2, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest62.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest62 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"select temp.*, u.CanComment, u.CanBeShared, u.CanForward, COALESCE(b.UserID,0) as isBlocked\" +\n                        \"   , COALESCE(f.UserID,0) as Followed, COALESCE(ff.UserID,0) as IsFollowed\" +\n                        \"   , COALESCE(ul.UserID,0) as liked, COALESCE(fff.UserID,0) as RIsFollowed \" +\n                        \"from (select 294765 as UserID, 0  as RUserID, 7785977 as PicID \" +\n                        \"       union all select 294765 as UserID, 0  as RUserID, 7780341 as PicID) temp     \" +\n                        \"left join Users as u on u.UserID = temp.UserID   \" +\n                        \"left join BlockUser as b on b.UserID = temp.UserID and b.BlockUserID = 294765     \" +\n                        \"left join Fans as f on f.FansID = temp.UserID and f.UserID = 294765   \" +\n                        \"left join Fans as ff ON ff.FansID = 294765 and ff.UserID = temp.UserID   \" +\n                        \"left join Fans as fff ON fff.FansID = 294765 and fff.UserID = temp.RUserID   \" +\n                        \"left join UserLikes as ul on ul.PicID = temp.PicID and ul.UserID = 294765\"));\n\n        assertEquals(4, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n        provider.getConfig().setSelectUnionCheck(true);\n        String sql = \"SELECT 1, 2, 3\" +\n                \" UNION ALL SELECT  a  from tt where c=1\" +\n                \" UNION ALL SELECT 2 FROM dual --\";\n        assertFalse(provider.checkValid(sql));\n\n        sql = \"SELECT a from t where c=1 UNION ALL SELECT 2 FROM dual --\";\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest63.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest63 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n        provider.getConfig().setSelectUnionCheck(false);\n        provider.setBlackListEnable(false);\n        provider.setWhiteListEnable(false);\n\n        final String sql1 = \"SELECT FID, FNAME FROM T WHERE C=1 UNION SELECT 1, 'AAA'\";\n        assertTrue(provider.checkValid(sql1));\n        final String sql2 = \"SELECT FID, FNAME FROM T WHERE C=1 UNION SELECT 1, 'AAA' --\";\n        assertFalse(provider.checkValid(sql2));\n\n        assertEquals(1, provider.getTableStats().size());\n\n        provider.reset();\n        provider.getConfig().setCommentAllow(true);\n        provider.getConfig().setSelectUnionCheck(false);\n\n        assertTrue(provider.checkValid(sql2));\n\n        assertTrue(provider.checkValid(sql2));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest64.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest64 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertFalse(provider.checkValid(//\n                \"SELECT email, passwd, login_id, full_name\" +\n                        \" FROM members\" +\n                        \" WHERE member_id = 3 AND 1=(SELECT COUNT(*) FROM tabname);'\"));\n\n        assertEquals(2, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest65.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest65 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        WallConfig config = provider.getConfig();\n        config.setSchemaCheck(true);\n        assertFalse(provider.checkValid(//\n                \"SELECT email, passwd, login_id, full_name\" +\n                        \" FROM test1.members\" +\n                        \" WHERE member_id = 3 OR 0<(SELECT COUNT(*) FROM tabname);\"));\n\n        assertEquals(2, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest66.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest66 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT LOGFILE_GROUP_NAME, FILE_NAME, TOTAL_EXTENTS, INITIAL_SIZE, ENGINE, EXTRA \" +\n                        \"FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'UNDO LOG' AND FILE_NAME IS NOT NULL \" +\n                        \"AND LOGFILE_GROUP_NAME IN (\" +\n                        \"   SELECT DISTINCT LOGFILE_GROUP_NAME FROM INFORMATION_SCHEMA.FILES \" +\n                        \"       WHERE FILE_TYPE = 'DATAFILE' \" +\n                        \"           AND TABLESPACE_NAME IN (\" +\n                        \"               SELECT DISTINCT TABLESPACE_NAME FROM INFORMATION_SCHEMA.PARTITIONS \" +\n                        \"               WHERE TABLE_SCHEMA IN ('stat'))\" +\n                        \") \" +\n                        \"GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE \" +\n                        \"ORDER BY LOGFILE_GROUP_NAME\"));\n\n        assertEquals(2, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest67.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest67 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT c.table_name, column_name, column_type, is_nullable, column_key\" +\n                        \"   , column_default, extra, collation_name, character_set_name, column_comment \" +\n                        \"FROM information_schema.columns c \" +\n                        \"INNER JOIN (\" +\n                        \"   SELECT table_schema, table_name \" +\n                        \"   FROM information_schema.tables \" +\n                        \"   WHERE LOWER(table_schema) = LOWER('sp5035d3d0b2d4a')\" +\n                        \") t ON t.table_name COLLATE utf8_bin = c.table_name COLLATE utf8_bin \" +\n                        \"WHERE LOWER(c.table_schema) = LOWER('sp5035d3d0b2d4a') \" +\n                        \"   AND ('Y' = '' OR LOWER(c.table_name) IN ('leader01_weibo')) \" +\n                        \"ORDER BY t.table_name\"));\n\n        assertEquals(2, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest68.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest68 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT * FROM `information_schema`.`ROUTINES` \" +\n                        \"WHERE `information_schema`.`ROUTINES`.`ROUTINE_SCHEMA` = 'mzsg_g001'\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest69.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest69 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"select * from T--\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest7.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest7 {\n    @Test\n    public void test_stuff() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT a.* FROM vote_info a where a.id<10 and (id <5 or 1=1) limit 1,10\")); // 部分永真\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest70.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest70 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"select * from T/**/\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest71.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest71 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"update order_return set return_goods_money =0.00 ,return_other_money = 8--149.00, return_total_fee = ifnull(return_shipping,0)+ifnull(return_other_discount,0)+0.00--149.00-0.00,return_goods_amount=1,return_real_money=0.00 where id=1319\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false1() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertFalse(provider.checkValid(//\n                \"select * from order_return where return_goods_money =0.00 ,return_other_money = 8--149.00, return_total_fee = ifnull(return_shipping,0)+ifnull(return_other_discount,0)+0.00--149.00-0.00,return_goods_amount=1,return_real_money=0.00\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest72.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest72 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"select * from t /**/ where fid = 123 AND 1=1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n\n        provider.reset();\n        provider.getConfig().setCommentAllow(false);\n        assertFalse(provider.checkValid(//\n                \"select * from t /**/ where fid = 123 AND 1=1 --\")); //FIXME /**/\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest73.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest73 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"DELETE FROM D1 USING PCHS_DETAIL D1 \" +\n                        \"   INNER JOIN (\" +\n                        \"       SELECT D.DETAIL_UID \" +\n                        \"       FROM PCHS_DETAIL D \" +\n                        \"           INNER JOIN PCHS_BILL B ON D.BILL_UID=B.BILL_UID \" +\n                        \"       WHERE B.COM_UID='0892E8A38EF83AB6B9E25C25D8085486' \" +\n                        \"       LIMIT 1000 \" +\n                        \"   ) D2 ON D1.DETAIL_UID=D2.DETAIL_UID\"));\n\n        assertEquals(3, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest74.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest74 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        final String sql = \"select _t0.`ownUser` as _c0, _t0.`showTime` as _c1, _t0.`showType` as _c2, \" +\n                \"   _t0.`itemId` as _c3, _t0.`queueId` as _c4 \" +\n                \"from `itemshow_queue` as _t0 \" +\n                \"where ( _t0.`isShowed` = 'F' and _t0.`showTime` <= ? ) \" +\n                \"   and _t0.`ownUser` in ( \" +\n                \"       select _t0.`userId` as _c0 from `users_top` as _t0 \" +\n                \"       where ( 1 = 1 ) \" +\n                \"       ) \" +\n                \"order by _t0.`showTime` asc \" +\n                \"limit 1000 offset 8000\";\n        provider.getConfig().setSelectWhereAlwayTrueCheck(true);\n        assertFalse(provider.checkValid(sql));\n\n        assertEquals(2, provider.getTableStats().size());\n\n        provider.getConfig().setSelectWhereAlwayTrueCheck(false);\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest75.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest75 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertFalse(provider.checkValid(//\n                \"UPDATE friends_a SET requests='-^B}q^A(X \\\\0\\\\0\\\\0176403924cdatetime\\\\ndatetime\\\\nq^BU\\\\n^G--\\\\Z^K:5^Hw.-Rq^CX \\\\0\\\\0\\\\0942515122h^BU\\\\n^G--^X^G^^$\\\\n^NӅRq^DX \\\\0\\\\0\\\\0760857294h^BU\\\\n^G-- ^F8+ ---Rq^EX \\\\0\\\\0\\\\0207000491h^BU\\\\n^G--^X^E^_^L^F-$-Rq^FX \\\\0\\\\0\\\\0281067699h^BU\\\\n^G--^B^O^C-^A<13>Rq^GX \\\\0\\\\0\\\\0941678014h^BU\\\\n^G--^\\\\^W^N^W^F-$-Rq^HX \\\\0\\\\0\\\\0840070155h^BU\\\\n^G--^\\\\^L\\\\n6^D*ʅRq X \\\\0\\\\0\\\\0468440035h^BU\\\\n^G--^V^W*^N^Bp^K-Rq\\\\nU 169240315h^BU\\\\n^G--^W^U^W1^D-m-Rq^KX \\\\0\\\\0\\\\0199411251h^BU\\\\n^G--^V^W%^^^A---Rq^LU 210660648h^BU\\\\n^G--^\\\\^W^Y-^F\\\\Zd-Rq\\\\rU 262672217h^BU\\\\n^G--\\\\Z^V2:^O^U--Rq^NX \\\\0\\\\0\\\\0952838443h^BU\\\\n^G--^\\\\^W!7\\\\r-{-Rq^OX \\\\0\\\\0\\\\0263642777h^BU\\\\n^G--^B^U/^D^G-̅Rq^PX \\\\0\\\\0\\\\0286685152h^BU\\\\n^G--^W^T3,^Ggs-Rq^QU 290976173h^BU\\\\n^G--^\\\\^V)^X^D---Rq^RX \\\\0\\\\0\\\\0825427842h^BU\\\\n^G--\\\\Z^V;^Q^N- -Rq^SX \\\\0\\\\0\\\\0399352674h^BU\\\\n^G--^\\\\^V-0^KC\\\\0-Rq^TX \\\\0\\\\0\\\\0429293778h^BU\\\\n^G--^Y^U ^]^C-��Rq^UX \\\\0\\\\0\\\\0796702973h^BU\\\\n^G--^Y^S^U#^F\\\\\\\\^W-Rq^Vu.'\"//\n                        + \",friends='-^B}q^A(X \\\\0\\\\0\\\\0288854421cdatetime\\\\ndatetime\\\\nq^BU\\\\n^G--^[^N38^L6---q^CX \\\\0\\\\0\\\\0307943786h^BU\\\\n^G--^F^V7 ^D---Rq^DX \\\\0\\\\0\\\\0290783072NX \\\\0\\\\0\\\\0498070760NX \\\\0\\\\0\\\\0457575155NX \\\\0\\\\0\\\\0304215892h^BU\\\\n^G--^F^W^L+^L---Rq^EX \\\\0\\\\0\\\\0300254457h^BU\\\\n^G--^F^G$)^A---Rq^FX \\\\0\\\\0\\\\0252042226h^BU\\\\n^G-- ^R8\\\\r ----q^GX \\\\0\\\\0\\\\0697110711NX \\\\0\\\\0\\\\0809118053h^BU\\\\n^G-- ^L^H^O\\\\0ɲ-Rq^HX \\\\0\\\\0\\\\0293303495h^BU\\\\n^G-- ^T!.^B/ʅRq X \\\\0\\\\0\\\\0302651538h^BU\\\\n^G--^G^P)^C^Fn---q\\\\nU 888879887h^BU\\\\n^G--^H^W.*^G---Rq^KX \\\\0\\\\0\\\\0240865621h^BU\\\\n^G--^G\\\\n2;\\\\n---Rq^LU 300728616h^BU\\\\n^G--^A^L^N8\\\\0\\\\'\"\n                        + \"--Rq\\\\rX \\\\0\\\\0\\\\0856456443NX \\\\0\\\\0\\\\0302371154h^BU\\\\n^G--^A^Q^R^^\\\\0---Rq^NX \\\\0\\\\0\\\\0696458616h^BU\\\\n^G--^G\\\\n98\\\\n---Rq^OU 297082613NX \\\\0\\\\0\\\\0811281930h^BU\\\\n^G--\\\\n^Q^P^X^L^OɅRq^PU 300986758h^BU\\\\n^G--^F^F\\\\r3^G-$-Rq^QU 276325435h^BU\\\\n^G--^B^P^P^T^E^N8-Rq^RX \\\\0\\\\0\\\\0299082034h^BU\\\\n^G--^H^W^_^Q^D<--Rq^SX \\\\0\\\\0\\\\0171238051h^BU\\\\n^G--\\\\n\\\\r)^S^Dܢ-Rq^TX \\\\0\\\\0\\\\0780724792h^BU\\\\n^G--\\\\n^N+ ^F*>-Rq^UX \\\\0\\\\0\\\\0893552392h^BU\\\\n^G--\\\\n^N^_-^K^L--Rq^VX \\\\0\\\\0\\\\0590290136h^BU\\\\n^G-- \\\\r^Y0\\\\r --Rq^WX \\\\0\\\\0\\\\0302913387h^BU\\\\n^G--^C^K#,\\\\0^X9-Rq^XX \\\\0\\\\0\\\\0252736446NX \\\\0\\\\0\\\\0302360033h^BU\\\\n^G--^C^O^A^^^H-[-Rq^YU 276564368h^BU\\\\n^G--\\\\n\\\\r:+^K-q-Rq\\\\ZX \\\\0\\\\0\\\\0296693715h^BU\\\\n^G-- ^G^[/^A-F-Rq^[X \\\\0\\\\0\\\\0223225019h^BU\\\\n^G-- ^S^X^C\\\\07\\\\Z-Rq^\\\\X \\\\0\\\\0\\\\0232453764h^BU\\\\n^G--^_\\\\r3^V\\\\0---Rq^]U 297276051h^BU\\\\n^G--^C^K/4^K-؅Rq^^X \\\\0\\\\0\\\\0184978889NX \\\\0\\\\0\\\\0813351784h^BU\\\\n^G--^H^H%^X^E&^S-Rq^_X \\\\0\\\\0\\\\03028705\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest76.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest76 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR GREATEST(2,0) = 2\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest77.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest77 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR LEAST(2,0) = 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest78.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest78 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR LEAST(2,1,9,8) = 1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest79.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest79 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR LEAST(2,1,9,8) = 1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest8.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest8 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT a.* FROM vote_info a where 1=1 AND FID = ?\")); // AND永真不拦截\n    }\n\n    @Test\n    public void test_false_1() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT a.* FROM vote_info a where FID = ? OR 1=1\")); // 永真，拦截\n    }\n\n    @Test\n    public void test_false_2() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT a.* FROM vote_info a where FID = ? OR (FID = ? OR 1=1)\")); // 永真，拦截\n    }\n\n    @Test\n    public void test_false_3() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT a.* FROM vote_info a where FID = ? OR (1=1 or FID = ?)\")); // 永真，拦截\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest80.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest80 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR FID LIKE 1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR FID LIKE 1 --\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest81.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest81 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setStrictSyntaxCheck(false);\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = '\\\\'a' OR LEAST(2,1,9,8) = 1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest82.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest82 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setStrictSyntaxCheck(false);\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = '\\0a' OR LEAST(2,1,9,8) = 1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest83.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest83 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"alter table rms.rms_Person_Event drop foreign key FKA382487726D72F65\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest84.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest84 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"CREATE INDEX part_of_name ON customer (name(10));\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest85.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest85 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"CREATE TABLE lookup (id INT) ENGINE = MEMORY;\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest86.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest86 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"CREATE INDEX id_index ON lookup (id) USING BTREE;\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"lookup\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest87.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest87 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"CREATE VIEW test.v AS SELECT * FROM t;\"));\n\n        assertEquals(2, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest88.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest88 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"DROP INDEX `PRIMARY` ON t;\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest89.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest89 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"select login('', '', 'guest', '47ea3937793101011caaa5dd88d3bcae926526624796b8a26a9615e8d3bea6b4', 'iPad3,4', 'unknown'),     '', (select max(num) from accounts) +  @@auto_increment_increment\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"accounts\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest9.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest9 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"REPLACE INTO lhwonline_guest (`ip`, `created_time`, `modify_time`, `fid`, `tid`, `request`)\" +\n                        \"\\nVALUES ('1', '1364366764', '1364368276', '0', '3436'\" +\n                        \"\\n    , 'bbs/read/run')\")); // 前置永真\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest90.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest90 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        //FIXME 不知此测试用例的真实意图\n        assertFalse(provider.checkValid(//\n                \"select * from (select t10006_men_xing_jia_ge_fen_lei.bian_hao as \\\"bian_hao\\\", \" +\n                        \"   t10006_men_xing_jia_ge_fen_lei.ming_cheng as \\\"ming_cheng\\\" \" +\n                        \"from t10006_men_xing_jia_ge_fen_lei where 1=1 ) as tables where 1=1 order by tables.bian_hao\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t10006_men_xing_jia_ge_fen_lei\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest91.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest91 {\n    private WallProvider initWallProvider() {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setStrictSyntaxCheck(false);\n        provider.getConfig().setMultiStatementAllow(true);\n        provider.getConfig().setConditionAndAlwayTrueAllow(true);\n        provider.getConfig().setNoneBaseStatementAllow(true);\n        provider.getConfig().setLimitZeroAllow(true);\n        provider.getConfig().setConditionDoubleConstAllow(true);\n\n        provider.getConfig().setCommentAllow(true);\n        provider.getConfig().setSelectUnionCheck(false);\n\n        return provider;\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT t.session_id,t.voip_send,t.voip_rece,t.appid,t.begin_time,substring_index(t1.callbackUrl,':',1) AS servicetype, SUBSTRING_INDEX(substring_index(t1.callbackUrl,'/',3),'/',-1) AS hostname, CASE WHEN SUBSTR(t1.callbackUrl,-2)='**' THEN REPLACE(t1.callbackUrl,'**','OfflineMsgNotify') ELSE t1.callbackUrl END AS url FROM `im_session_info` t INNER JOIN ccp_application t1 ON t.appid=t1.appId WHERE t.end_time IS NULL AND ((DATABASE()='openser' AND t1.`status`=2) OR ((DATABASE()<>'openser') AND t1.`status` IN (1,2,3))) AND INSTR(t1.funInfo,'1004')>0 AND (0=0 OR (0>0 AND t.id<0)) ORDER BY t.id DESC LIMIT 100; \";\n            SQLUtils.parseStatements(sql, DbType.mysql);\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false1() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT * FROM `group` WHERE group.nickname like '%' AND 8709=IF(((66+67)>222),SLEEP(5),8709) AND 'Ttyv' LIKE 'Ttyv%' OR group.fullname like '%' AND 8709=IF(((66+67)>222),SLEEP(5),8709) AND 'Ttyv' LIKE 'Ttyv%'\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false2() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT user.id,user.name FROM `user` WHERE user.name like '%' AND 7961=IF(((27+33)>159),SLEEP(5),7961) AND 'dewN' LIKE 'dewN%' AND user.activated = 1\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false3() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT * FROM mp_Sites WHERE SiteID = -1 OR -1 = -1 -- ORDER BY SiteID LIMIT 1 \";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false4() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select cid,title,id,img,fan from duoduo_mall where cid = cid and 1=1 -- order by sort desc limit 17 \";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false5() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select count(1) as cot from w36ma_picking where (picking_no='' or ''='') and (DATE_FORMAT(create_time,'%Y-%m-%d') = '' or ''='') --\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false6() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \" select pg.*,an1.w36ma_name as create_name, an2.w36ma_name as print_name, an2.w36ma_name as receive_name, an2.w36ma_name as products_name, an2.w36ma_name as warehouse_name from w36ma_picking as pg left join iweb_admin as an1 on pg.create_name_id=an1.id left join iweb_admin as an2 on pg.print_name_id=an2.id left join iweb_admin as an3 on pg.receive_name_id=an3.id left join iweb_admin as an4 on pg.products_name_id=an4.id left join iweb_admin as an5 on pg.warehouse_name_id=an5.id where (pg.picking_no='' or ''='') and (DATE_FORMAT(pg.create_time,'%Y-%m-%d') = '' or ''='') -- limit 0,20 \";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false7() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select sysuser0_.sysuser_id as sysuser1_163_, sysuser0_.sysuser_name as sysuser2_163_, sysuser0_.sysuser_loginname as sysuser3_163_, sysuser0_.sysuser_password as sysuser4_163_, sysuser0_.sysuser_mobilenum as sysuser5_163_, sysuser0_.sysuser_email as sysuser6_163_, sysuser0_.sysuser_phonenum as sysuser7_163_, sysuser0_.sysuser_createtime as sysuser8_163_, sysuser0_.sysuser_lastupdate as sysuser9_163_, sysuser0_.sysuser_status as sysuser10_163_, sysuser0_.sysuser_loginip as sysuser11_163_, sysuser0_.sysuser_interfacesn as sysuser12_163_, sysuser0_.customer_customer_id as customer13_163_, sysuser0_.role_role_id as role14_163_ from sysuser sysuser0_ where sysuser0_.sysuser_status=1 and sysuser0_.role_role_id=5 and sysuser0_.sysuser_loginname='sms_bftl2' and USER()=USER() and 'EYrc'='EYrc'\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false8() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select sum(payment_ft) from order_goods where order_id=72353 AND (SELECT 3791 FROM(SELECT COUNT(*),CONCAT(CHAR(58,110,106,120,58),(SELECT (CASE WHEN (3791=3791) THEN 1 ELSE 0 END)),CHAR(58,116,116,113,58),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false10() {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select count(*) from messages a where a.id in (2 and 1 AND 9881=IF((ORD(MID((IFNULL(CAST(DATABASE() AS CHAR),0x20)),6,1))>117),SLEEP(5),9881)) and a.message <> 'hello' and a.message like 'Little'\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false11() {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select * from messages where id=1 limit (select count(*) from products group by concat(version(),0x27202020,floor(rand(0)*2-1)));\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false12() {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select * from dede_admin where id=1 order by if((ascii(substr(user(),1,1))>95),1,2);\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false13() {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select * from dede_admin where id=1 limit if((ascii(substr(user(),1,1))>95),1,0);\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true1() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT *, DATABASE(), NOW() AS a_now FROM `acp_globalauth` WHERE `username` = 'info@nyip.cn'\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true2() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"DELETE SYS_ACCNBAL WHERE ISNULL(AMTN_Y,0)=0 AND ISNULL(AMTN_B,0)=0 AND ISNULL(AMTN_D,0)=0 AND ISNULL(AMTN_C,0)=0\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select * from (select '已结算' as JSFare,TB_LogisticsCostSettle.s_id,TB_LogisticsCostSettle.XSD_billsn,TB_LogisticsCostSettle.OrderDD_list,TB_LogisticsCostSettle.OrderId_list,TBShop.ShopName,TB_LogisticsCostSettle.consign_time,TB_LogisticsCostSettle.Logistics_ID,TB_LogisticsCompanySet.Company,isnull(TB_LogisticsCostSettle.TBFareMoney,0.00)TBFareMoney,TB_LogisticsCostSettle.TBProdSJZNNumber,isnull(TB_LogisticsCostSettle.SJLogisticsCostMoney,0.00)LogisticsCostMoney,isnull(TB_LogisticsCostSettle.SJLogisticsCostMoney,0.00)SJLogisticsCostMoney,isnull(TB_LogisticsCostSettle.SJLogisticsCostMoney,0)-isnull(TB_LogisticsCostSettle.TBJSFareMoney,0) as NotMoney,TB_LogisticsCostSettle.TBAddressee,TB_LogisticsCostSettle.TBAddress,TB_LogisticsCostSettle.TBMobile,TB_LogisticsCostSettle.TBLinephone,TB_LogisticsCostSettle.TBJSFareMoney,TB_LogisticsCostSettle.Express,TB_LogisticsCostSettle.Fhuser_list,TB_LogisticsCostSettle.LogisticsCost_billsn,dbo.F_GetLogisticsFKDMoney(TB_LogisticsCostSettle.s_id,TB_LogisticsCostSettle.LogisticsCost_billsn) fkdmoney,isnull(TB_LogisticsCostSettle.TBFareMoney,0)-isnull(TB_LogisticsCostSettle.SJLogisticsCostMoney,0) LogisticsProfitMoney,isnull(TB_LogisticsCostSettle.IsEnterFare,0)IsEnterFare from TB_LogisticsCostSettle left join TBShop on TB_LogisticsCostSettle.TBShop_ID=TBShop.ShopID left join TB_LogisticsCompanySet on TB_LogisticsCostSettle.Logistics_ID=TB_LogisticsCompanySet.s_ID where isnull(TB_LogisticsCostSettle.IsEnterFare,0)=1 or (isnull(TB_LogisticsCostSettle.IsEnterFare,0)=2 and isnull(TB_LogisticsCostSettle.SJLogisticsCostMoney,0)-isnull(TB_LogisticsCostSettle.TBJSFareMoney,0)>0))MTwhere 1=1and MT.consign_time>='2013-04-28 00:00:00' and MT.consign_time<='2013-05-28 23:59:59'\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false9() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select  PROJECT_NAME, TABLE_NAME, EXPORT_COLUMNS, CURRENT_TIMESTAMP() start_time from (SELECT PROJECT_NAME, TABLE_NAME, EXPORT_COLUMNS, @rank := @rank + 1 AS rank FROM (  SELECT  PROJECT_NAME,  TABLE_NAME,  (   SELECT   CASE   WHEN GROUP_CONCAT(COLUMN_name) LIKE 'ID,%' THEN   SUBSTR(    GROUP_CONCAT(COLUMN_name),    4   )   ELSE   GROUP_CONCAT(COLUMN_name)   END   FROM   Information_schema.`COLUMNS` A   WHERE   A.table_name = B.TABLE_NAME   ORDER BY   ORDINAL_POSITION  ) EXPORT_COLUMNS  FROM  ETL_EXPORT b   ORDER BY  PROJECT_NAME,  TABLE_NAME ) tmp, (SELECT @rank := 0) a) b WHERE rank='2';\";\n            assertFalse(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select  PROJECT_NAME, TABLE_NAME, EXPORT_COLUMNS, CURRENT_TIMESTAMP() start_time, case when type=1 then ' where day_id = 20130101 '  when type=2 and substr('20130101','7,2')='01' then 'where month_id=201301 ' else 'where 3=5 ' end export_where_data from (SELECT PROJECT_NAME, TABLE_NAME, EXPORT_COLUMNS, type, @rank := @rank + 1 AS rank FROM (  SELECT  PROJECT_NAME,  TABLE_NAME,  type,  (   SELECT   CASE   WHEN GROUP_CONCAT(COLUMN_name) LIKE 'ID,%' THEN   SUBSTR(    GROUP_CONCAT(COLUMN_name),    4   )   ELSE   GROUP_CONCAT(COLUMN_name)   END   FROM   Information_schema.`COLUMNS` A   WHERE   A.table_name = concat(B.TABLE_NAME,'_','201301')   ORDER BY   ORDINAL_POSITION  ) EXPORT_COLUMNS  FROM  ETL_EXPORT b  where project_name in ('acc')  ORDER BY  PROJECT_NAME,  TABLE_NAME ) tmp, (SELECT @rank := 0) a) b WHERE rank='3';\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true4() {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT 10006, @\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true5() {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select * from view_featureWarm where 1 = 1 and MaterialID in (select Materialid from material where Code like '%%' and name like '%%' and specs like '%%') and sumbalcqty <> 0\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT CONVERT(load_file(concat(@@datadir, 'sandbox', '/', 'ccp_application', '.frm')) USING utf8) AS source\";\n            assertTrue(provider.checkValid(sql));\n        }\n\n        {\n            String sql = \"select c.COLUMN_NAME, COLUMNPROPERTY(OBJECT_ID(c.TABLE_SCHEMA + '.' + c.TABLE_NAME), c.COLUMN_NAME, 'IsIdentity') from sys.KEY_COLUMN_USAGE c join sys.TABLE_CONSTRAINTS p on p.CONSTRAINT_NAME = c.CONSTRAINT_NAME where c.TABLE_NAME = @p1 and c.TABLE_SCHEMA = @p2 and p.TABLE_SCHEMA = @p2 and p.CONSTRAINT_TYPE = 'PRIMARY KEY'\";\n            assertTrue(provider.checkValid(sql));\n        }\n\n        {\n            String sql = \"SELECT user_name(), @@MAX_PRECISION, is_member('db_owner'), permissions(), DatabasePropertyEx(db_name(), N'collation'), SERVERPROPERTY('IsFullTextInstalled'), schema_name()\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select col.name, col.column_id, st.name as DT_name, schema_name(st.schema_id) as DT_schema, col.max_length, col.precision, col.scale, bt.name as BT_name, col.collation_name, col.is_nullable, col.is_ansi_padded, col.is_rowguidcol, col.is_identity, case when(idc.column_id is null) then null else CONVERT(nvarchar(40), idc.seed_value) end, case when(idc.column_id is null) then null else CONVERT(nvarchar(40), idc.increment_value) end, CONVERT(bit, case when(cmc.column_id is null) then 0 else 1 end) as is_computed, convertToSqlNode(bit, ColumnProperty(col.object_id, col.name, N'IsIdNotForRepl')) as IsIdNotForRepl, col.is_replicated, col.is_non_sql_subscribed, col.is_merge_published, col.is_dts_replicated, col.rule_object_id, robj.name as Rul_name, schema_name(robj.schema_id) as Rul_schema, col.default_object_id, OBJECTPROPERTY(col.default_object_id, N'IsDefaultCnst') as is_defcnst, dobj.name as def_name, schema_name(dobj.schema_id) as def_schema, CONVERT(bit, case when (ftc.column_id is null) then 0 else 1 end) as is_FullTextCol, col_name(col.object_id, ftc.type_column_id) FT_type_column, ftc.language_id as FT_language_id, case when(cmc.column_id is null) then null else cmc.definition end as formular, case when(cmc.column_id is null) then null else cmc.is_persisted end as is_persisted, defCst.definition, COLUMNPROPERTY(col.object_id, col.name, 'IsDeterministic') as IsDeterministic, xmlcoll.name as xmlSchema_name, schema_name(xmlcoll.schema_id) as xmlSchema_schema, col.is_xml_document, col.is_sparse, col.is_column_set from sys.columns col left outer join sys.types st on st.user_type_id = col.user_type_id left outer join sys.types bt on bt.user_type_id = col.system_type_id left outer join sys.objects robj on robj.object_id = col.rule_object_id and robj.type = 'R' left outer join sys.objects dobj on dobj.object_id = col.default_object_id and dobj.type = 'D' left outer join sys.default_constraints defCst on defCst.parent_object_id = col.object_id and defCst.parent_column_id = col.column_id left outer join sys.identity_columns idc o\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT * FROM `www_subject` WHERE subject like '哎%' or subject like '%' ORDER BY aid desc LIMIT 30 \";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT COUNT(*) FROM syscolumns WHERE id=OBJECT_ID(N'taobao_order') AND name='r3_billtype'\";\n            assertTrue(provider.checkValid(sql));\n        }\n\n        {\n            String sql = \"select col.name, st.name as DT_name, case when (st.name in ('nchar', 'nvarchar') and (col.max_length > 0)) then col.max_length / 2 else col.max_length end, col.precision, col.scale, bt.name as BT_name, col.is_nullable, col.is_identity,col.is_rowguidcol, OBJECTPROPERTY(col.default_object_id, N'IsDefaultCnst') as is_defcnst, CONVERT(bit, case when(cmc.column_id is null) then 0 else 1 end) as is_computed, case when(cmc.column_id is null) then null else cmc.definition end as formular, col.collation_name, col.system_type_id from nowshop.sys.all_columns col left outer join nowshop.sys.types st on st.user_type_id = col.user_type_id left outer join nowshop.sys.types bt on bt.user_type_id = col.system_type_id left outer join nowshop.sys.identity_columns idc on idc.object_id = col.object_id and idc.column_id = col.column_id left outer join nowshop.sys.computed_columns cmc on cmc.object_id = col.object_id and cmc.column_id = col.column_id where col.object_id = object_id(N'nowshop.dbo.hr_shop') order by col.column_id\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select * from tb_product_word where name='' or CONCAT(name,style)='' or CONCAT(shop,style)='' or CONCAT(ename,style)=''\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT * FROM `oammxncom2014`.`ecs_free_bank` where 1 and 1='1'\";\n            assertFalse(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT * FROM `oammxncom2014`.`ecs_free_bank` where 1 or 1='1'\";\n            assertFalse(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT * FROM `oammxncom2014`.`ecs_free_bank` where true or 1='1'\";\n            assertFalse(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT * FROM `oammxncom2014`.`ecs_free_bank` where 'a' or 1='1'\";\n            assertFalse(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT * FROM `oammxncom2014`.`ecs_free_bank` where id=1 or 1='1' --\";\n            SQLUtils.parseStatements(sql, DbType.mysql);\n            assertFalse(provider.checkValid(sql));\n        }\n//        {\n//            String sql = \"SELECT * FROM `oammxncom2014`.`ecs_free_bank` where id=1 or true --\";\n//            assertFalse(provider.checkValid(sql));\n//        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest92.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest92 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = 40 OR 1 = (SELECT (CASE WHEN (4484=4484) THEN 1 ELSE 0 END))\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest93.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest93 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"desc tablename\"));\n\n        assertEquals(0, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest94.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest94 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"select * from test having 1=1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n\n        provider.reset();\n        provider.getConfig().setSelectHavingAlwayTrueCheck(false);\n        assertTrue(provider.checkValid(//\n                \"select * from test having 1=1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest95.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest95 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        assertFalse(provider.checkValid(//\n                \"select * from test /*!40101fff*/\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest96.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest96 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"insert into darenai_stat_url SET user='nologin',ip='58.101.223.183',reffer='http://item.taobao.com/item.htm?spm=a230r.1.14.419.KDVewC&amp;id=17052767689',url='/d/jingpinhui?spm=2013.1.0.0.zr4nLz&amp;ac=shop&amp;imageid=1019937265&amp;s=1259538&amp;s=1259538',shopnick='零利润3232',time=NOW()\";\n\n        assertTrue(provider.checkValid(//\n                sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest97.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest97 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or ascii(141) = 49\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest98.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest98 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or ascii(0x7F) = 127\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest99.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest99 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setCommentAllow(false);\n\n        String sql = \"select * from t where id = ? or substr(bin(97>>7), -1, 1) = 0\";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_comment.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_comment {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(true);\n\n        assertTrue(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? #AND 1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setCommentAllow(false);\n\n        assertTrue(provider.checkValid(\"/* this is comment */ SELECT id FROM t \"));\n        assertTrue(provider.checkValid(\"-- this is comment \\n SELECT * FROM t\"));\n        assertTrue(provider.checkValid(\"#this is comment \\n SELECT * FROM t\"));\n\n        assertTrue(provider.checkValid(\"/*!40101fff*/ select * from t\"));\n        assertFalse(provider.checkValid(\"select * from t/*!40101fff*/\"));\n\n        assertTrue(provider.checkValid(\"SELECT * FROM t where a=1 #this is comment \\n and b=1\"));\n        assertTrue(provider.checkValid(\"SELECT * FROM t where a=1 -- this is comment \\n and c=1\"));\n        assertTrue(provider.checkValid(\"SELECT * FROM t where a=1 /* this is comment */ and d=1\"));\n\n        assertFalse(provider.checkValid(\"SELECT * FROM t where a=1 #and c=1 \\n and e=1\"));\n        assertFalse(provider.checkValid(\"SELECT * FROM t where a=1 -- AND c=1 \\n and f=1\"));\n        assertFalse(provider.checkValid(\"SELECT * FROM t where a=1 /* and c=1 */ and g=1\"));\n\n        assertFalse(provider.checkValid(\"SELECT * FROM t where a=1 #and c=1 \"));\n        assertFalse(provider.checkValid(\"SELECT * FROM t where a=1 -- and c=1\"));\n        assertFalse(provider.checkValid(\"SELECT * FROM t where a=1 /* and c=1 */\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_concat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest_concat {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"select * from tb_product_word where name='' or CONCAT(name,style)='' or CONCAT(shop,style)=''  or CONCAT(ename,style)=''\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"tb_product_word\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_having.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_having {\n    @Test\n    public void test_having() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select id, count(*) from t group by id having 1 = 1\"));\n    }\n\n    @Test\n    public void test_having_true_first() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"select id, count(*) from t group by id having 1 = 1 AND count(*) > 2\"));\n    }\n\n    @Test\n    public void test_having_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"select id, count(*) from t group by id having count(*) > 2 OR 1 = 1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_hint.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest_hint {\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(false);\n        String sql = \"select * from person where id = '3'/**/union select 0,1,v from (select 1,2,user/*!() as v*/) a where '1'<>''\";\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_false_1() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(false);\n        config.setMultiStatementAllow(true);\n        String sql = \"select * from person where id = '3'/**/union select 0,1,v from (select 1,2,user/*!() as v*/) a where '1'<>''\";\n        assertFalse(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        String sql = \"SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2\";\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void test_true_1() throws Exception {\n        String sql = \"/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */\";\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void test_true_2() throws Exception {\n        String sql = \"/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */\";\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void test_true_3() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(true);\n        config.setMultiStatementAllow(true);\n        String sql = \" /*!50003 CREATE*/ /*!50020  /*!50003 PROCEDURE `top_calculate_customer_update`(in update_time DATETIME)\"\n                + \" DETERMINISTIC\"\n                + \" BEGIN\"\n                + \" DECLARE done INT DEFAULT FALSE;\"\n                + \" DECLARE c_receiver_city,c_receiver_district,c_receiver_address VARCHAR(200);\"\n                + \" DECLARE c_last_updated DATETIME;\"\n                + \" DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\"\n                + \" insert into top_calculate_customer_log (execute_time,info) values (now(),'update table top_taobao_order_customer_mid begin');\"\n                + \" update top_tmp_order_middle_last_sync set status = 'wait', last_sync = update_time where plat_form = 'taobao' and status = 'blocking';\"\n                + \" END */*/\";\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_true_4() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(true);\n        config.setMultiStatementAllow(true);\n        String sql = \"LOCK TABLES `m_rpt_adgroupeffect` READ /*!32311 LOCAL */\";\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_true_5() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(true);\n        config.setMultiStatementAllow(true);\n        String sql = \"DROP TABLE IF EXISTS `item_similarity`;\"//\n                + \"\\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\"//\n                + \"\\n/*!40101 SET character_set_client = utf8 */;\"\n                + \"\\nCREATE TABLE `item_similarity` (\"//\n                + \" `id` bigint(20) unsigned NOT NULL, \"//\n                + \" `sellerId` bigint(20) DEFAULT NULL,\"//\n                + \" PRIMARY KEY (`id`)\"\n                + \" ) ENGINE=InnoDB DEFAULT CHARSET=utf8;\"//\n                + \" \\n/*!40101 SET character_set_client = @saved_cs_client */;\";\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_true_6() throws Exception {\n        String sql = \"START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */\";\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void test_true_7() throws Exception {\n        String sql = \"LOCK TABLES `m_rpt_adgroupeffect` READ /*!32311 LOCAL */\";\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void test_true_8() throws Exception {\n        String sql = \"SET SQL_QUOTE_SHOW_CREATE=1/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */\";\n        assertTrue(WallUtils.isValidateMySql(sql));\n    }\n\n    @Test\n    public void test_true_9() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(true);\n        config.setMultiStatementAllow(true);\n        String sql = \"CREATE TABLE `session` (\"//\n                + \" `sess_id` varchar(128) NOT NULL,\"//\n                + \" `created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',\"//\n                + \" `changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',\"//\n                + \" `ip` varchar(40) NOT NULL,\"//\n                + \" `vars` mediumtext NOT NULL,\"//\n                + \" PRIMARY KEY(`sess_id`),\"//\n                + \" INDEX `changed_index` (`changed`)\"//\n                + \") /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */ \";\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_true_10() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(true);\n        config.setMultiStatementAllow(true);\n        config.setNoneBaseStatementAllow(true);\n        String sql = \"CREATE DATABASE `newsfocus` /*!40100 COLLATE 'big5_chinese_ci' */ \";\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n\n    @Test\n    public void test_true_11() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setHintAllow(true);\n        config.setMultiStatementAllow(true);\n        config.setNoneBaseStatementAllow(true);\n        String sql = \"EXPLAIN /*!40100 EXTENDED */ SELECT * FROM trade_order_header WHERE id = ?\";\n        assertTrue(WallUtils.isValidateMySql(sql, config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_if.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_if {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR IF(1>2,2,3) = 3\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_ifnull_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_ifnull_1 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR ISNULL(1) = 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_ifnull_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_ifnull_2 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertFalse(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR IFNULL(CAST(CURRENT_USER() AS CHAR))\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_like_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_like_1 {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n\n        assertTrue(provider.checkValid(//\n                \"SELECT * FROM T WHERE FID = ? OR FID LIKE 1\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_sqlmap.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_sqlmap {\n    @Test\n    public void test_false() throws Exception {\n        WallProvider provider = new MySqlWallProvider();\n        provider.getConfig().setSchemaCheck(true);\n\n        assertFalse(provider.checkValid(//\n                \"SELECT email, passwd, login_id, full_name\" +\n                        \" FROM members\" +\n                        \" 'W'=UPPER(MID(@@version_compile_os,1,1))\"));\n\n        assertEquals(1, provider.getTableStats().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_union.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlWallTest_union {\n    @Test\n    public void testUnion() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(true);\n\n        assertFalse(WallUtils.isValidateMySql(\"select f1, f2 from t where id=1 union select 1, 2\", config)); // not end of comment\n        assertFalse(WallUtils.isValidateMySql(\"select f1, f2 from t where id=1 union select 1, 2 --\", config));\n\n        assertTrue(WallUtils.isValidateMySql(\"select f1, f2 from t union select 1, 2\", config)); // no where\n\n        assertFalse(WallUtils.isValidateMySql(\"select f1, f2 from t where id=1 union select null, '1', 2 --\", config));\n\n        assertTrue(WallUtils.isValidateMySql(\"select f1, f2 from t where id=1 union select c1, c2\", config)); //union select item is not const\n\n        assertTrue(WallUtils.isValidateMySql(\"SELECT typeid, typename FROM (SELECT typeid, typename FROM materialtype UNION ALL SELECT ? AS typeid, ? AS typename) a ORDER BY typeid\",\n                config)); // union select item has alias\n\n        assertFalse(WallUtils.isValidateMySql(\"select f1, f2 from (select 1 as f1, 2 as f2) t union select 'u1', 'u2' --\", config)); // from is subQuery\n\n        assertTrue(WallUtils.isValidateMySql(\"select f1, f2 from t where id=1 union select 'u1' as u1, 'u2' as u2\", config)); // union select item has alias\n    }\n\n    @Test\n    public void testUnion2() throws Exception {\n//        assertFalse(\n//                WallUtils.isValidateMySql(\"SELECT name, surname FROM users WHERE name='' UNION SELECT @@version, 'string1'\")\n//        );\n\n        assertFalse(\n                WallUtils.isValidateMySql(\"SELECT name, surname FROM users WHERE name='' UNION SELECT /*! @@version,*/ 'string1'\")\n        );\n\n        assertFalse(\n                WallUtils.isValidateMySql(\"SELECT name, surname FROM users WHERE name=' ' UNION SELECT /*! (select table_name FROM information_schema.tables limit 1,1),*/ 'string1'\")\n        );\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_var.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_var {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT @@GLOBAL.sql_mode\"));\n    }\n\n    @Test\n    public void test_true_1() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT @@SESSION.sql_mode;\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * FROM T WHERE @@SESSION.sql_mode = 'ANSI'\"));\n    }\n\n    @Test\n    public void test_true2() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"SELECT * FROM T WHERE @@sql_mode = 'ANSI'\"));\n    }\n\n    @Test\n    public void test_false_1() throws Exception {\n        assertFalse(WallUtils.isValidateMySql(//\n                \"SELECT * FROM T WHERE @@basedir = 'ANSI'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest_var_autoincrement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class MySqlWallTest_var_autoincrement {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateMySql(//\n                \"/* mysql-connector-java-5.? ( Revision: bzr.revision-id ) */SELECT @@session.auto_increment_increment\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MysqlWallTest_rename_table.java",
    "content": "package com.alibaba.druid.bvt.filter.wall.mysql;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MysqlWallTest_rename_table {\n    @Test\n    public void test_true() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setRenameTableAllow(true);\n        assertTrue(WallUtils.isValidateMySql(\"RENAME TABLE t1 TO t2\", config));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setRenameTableAllow(false);\n        assertFalse(WallUtils.isValidateMySql(\"RENAME TABLE t1 TO t2\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallPermitFunctionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问Oracle系统对象\n *\n * @author admin\n */\npublic class OracleWallPermitFunctionTest {\n    @Test\n    public void test_permitTable() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(\"select * from t where fid = 1 union select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from X\"));\n    }\n\n    @Test\n    public void test_permitTable_allow() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setFunctionCheck(false);\n        assertTrue(WallUtils.isValidateOracle(\"select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from X\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallPermitObjectTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问Oracle系统对象\n *\n * @author admin\n */\npublic class OracleWallPermitObjectTest {\n    @Test\n    public void test_permitTable() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(\"select  sys.LinxReadFile('c:/boot.ini') from dual\"));\n        assertFalse(WallUtils.isValidateOracle(\"select  sys.LinxRunCMD('cmd /c net user linx /add') from dual\"));\n        assertFalse(WallUtils.isValidateOracle(\"select utl_inaddr.get_host_address from DUAL\"));\n        assertFalse(WallUtils.isValidateOracle(\"select TO_CHAR(utl_inaddr.get_host_address) from DUAL\"));\n        assertFalse(WallUtils.isValidateOracle(\"SELECT SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT'.PUT(:P1));\"));\n        assertFalse(WallUtils.isValidateOracle(\"select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES()\"));\n    }\n\n    @Test\n    public void test_permitTable_allow() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setObjectCheck(false);\n        assertTrue(WallUtils.isValidateOracle(\"select  sys.LinxReadFile('c:/boot.ini') from dual\", config));\n        assertTrue(WallUtils.isValidateOracle(\"select  sys.LinxRunCMD('cmd /c net user linx /add') from dual\", config));\n        assertTrue(WallUtils.isValidateOracle(\"select utl_inaddr.get_host_address from DUAL\", config));\n        assertTrue(WallUtils.isValidateOracle(\"select TO_CHAR(utl_inaddr.get_host_address) from DUAL\", config));\n        assertTrue(WallUtils.isValidateOracle(\"SELECT SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT'.PUT(:P1));\", config));\n        assertTrue(WallUtils.isValidateOracle(\"select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES()\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallPermitSchemaTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallPermitSchemaTest {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"select banner from sys.v_$version where rownum=1\"));\n        assertTrue(WallUtils.isValidateOracle(\"select banner from sys.v where rownum=1\"));\n    }\n\n    @Test\n    public void test_false() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select banner from sys.v_$version where rownum=1\"));\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select banner from sys.v where rownum=1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallPermitTableTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallPermitTableTest {\n    @Test\n    public void test_permitTable() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select * from TAB\"));\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select * from tab\"));\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select * from SYS.TAB\"));\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select * from SYS.\\\"TAB\\\"\"));\n\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select * from all_users\"));\n    }\n\n    @Test\n    public void test_permitTable_subquery() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"select * from(select * from TAB) a\"));\n        assertTrue(WallUtils.isValidateOracle(\"select * from(select * from tab) a\"));\n        assertTrue(WallUtils.isValidateOracle(\"select * from(select * from SYS.TAB) a\"));\n        assertTrue(WallUtils.isValidateOracle(\"select * from(select * from SYS.\\\"TAB\\\") a\"));\n    }\n\n    @Test\n    public void test_permitTable_join() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"select * from t1, TAB\"));\n        assertTrue(WallUtils.isValidateOracle(\"select * from t1, tab\"));\n        assertTrue(WallUtils.isValidateOracle(\"select * from t1, SYS.TAB\"));\n        assertTrue(WallUtils.isValidateOracle(\"select * from t1, SYS.\\\"TAB\\\"\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallPermitVariantTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问Oracle系统对象\n *\n * @author admin\n */\npublic class OracleWallPermitVariantTest {\n    @Test\n    public void test_permitTable() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setVariantCheck(false);\n\n        assertTrue(WallUtils.isValidateOracle(\"select UID from dual\", config));\n        assertTrue(WallUtils.isValidateOracle(\"select USER from dual\", config));\n        assertTrue(WallUtils.isValidateOracle(\"select user from dual\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallPermitVariantTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问Oracle系统对象\n *\n * @author admin\n */\npublic class OracleWallPermitVariantTest2 {\n    @Test\n    public void test_permitTable() throws Exception {\n        assertFalse(WallUtils.isValidateOracle(\"select UID from dual\"));\n        assertFalse(WallUtils.isValidateOracle(\"select USER from dual\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.TestUtil;\nimport com.alibaba.druid.sql.PGTest;\nimport com.alibaba.druid.wall.Violation;\nimport com.alibaba.druid.wall.WallCheckResult;\nimport com.alibaba.druid.wall.spi.OracleWallProvider;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallResourceTest extends PGTest {\n    public void test_0() throws Exception {\n        exec_test(\"bvt/wall/oracle/oracle-01.sql\");\n    }\n\n    public void test_2() throws Exception {\n        exec_test(\"bvt/wall/oracle/oracle-02.sql\");\n    }\n\n    public void exec_test(String resource) throws Exception {\n        String sql = TestUtil.getResource(resource);\n        OracleWallProvider provider = new OracleWallProvider();\n\n        WallCheckResult checkResult = provider.check(sql);\n        List<Violation> violations = checkResult.getViolations();\n        if (!violations.isEmpty()) {\n            fail(violations.get(0).getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest {\n    @Test\n    public void testWall() throws Exception {\n        WallConfig config = new WallConfig();\n        config.setSelectUnionCheck(true);\n        config.setCommentAllow(false);\n        assertFalse(WallUtils.isValidateOracle(\"select f1, f2 from t where c=1 union select 1, 2\", config));\n        assertFalse(WallUtils.isValidateOracle(\"select f1, f2 from t where c=1 union select 1, 2 --\", config));\n\n        config.setSelectUnionCheck(false);\n        config.setCommentAllow(true);\n        assertTrue(WallUtils.isValidateOracle(\"select f1, f2 from t where c=1 union select 1, 2\", config));\n        assertTrue(WallUtils.isValidateOracle(\"select f1, f2 from t where c=1 union select 1, 2 --\", config));\n\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select * from TAB\"));\n        assertFalse(WallUtils.isValidateOracle(\"SELECT * FROM T UNION select * from ALL_TABLES where (1=1 or (1+1)=2) and (4=8 or 1=1)\"));\n    }\n\n    @Test\n    public void testWall_1() throws Exception {\n        WallConfig config = new WallConfig();\n\n        assertTrue(\n                WallUtils.isValidateOracle(\"select/*+QUERY_TIMEOUT(600000000)*/ * from test_number\", config));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest1 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"SELECT DICT_ID,NAME,VALUE,STATUS FROM T_EBM_DICT WHERE T_EBM_DICT.PID=10 OR T_EBM_DICT.PID=11\"));\n        assertTrue(WallUtils.isValidateMySql(\"SELECT DICT_ID,NAME,VALUE,STATUS FROM T_EBM_DICT WHERE T_EBM_DICT.PID=10 OR T_EBM_DICT.PID=11\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest10.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest10 {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"select\\n\" +\n                        \"tpl.projectname as 项目名称,\\n\" +\n                        \"tpl.address as 项目地址,\\n\" +\n                        \"tpl.transactor as 联系人,\\n\" +\n                        \"tpl.transactor_tel as 联系人电话,\\n\" +\n                        \"dbms_lob.substr(wmsys.wm_concat(\\n\" +\n                        \"case when (tap.type = 'LESS_THIS_MONTH_SALARY' AND tap.month = '4') then '4月份'\\n\" +\n                        \"when (tap.type = 'LESS_THIS_MONTH_SALARY' AND tap.month = '5') then '5月份'\\n\" +\n                        \"when (tap.type = 'LESS_THIS_MONTH_SALARY' AND tap.month = '6') then '6月份'\\n\" +\n                        \"else null end\\n\" +\n                        \")) as YA,\\n\" +\n                        \"dbms_lob.substr(wmsys.wm_concat(\\n\" +\n                        \"case when tap.type = 'NO_PAY_MONTH' AND tap.month = '4' then '4月份'\\n\" +\n                        \"when tap.type = 'NO_PAY_MONTH' AND tap.month = '5' then '5月份'\\n\" +\n                        \"when tap.type = 'NO_PAY_MONTH' AND tap.month = '6' then '6月份'\\n\" +\n                        \"else null end\\n\" +\n                        \")) as YB,\\n\" +\n                        \"dbms_lob.substr(wmsys.wm_concat(\\n\" +\n                        \"case when tap.type = 'SALARY_DATA_MONTH' AND tap.month = '4' then '4月份'\\n\" +\n                        \"when tap.type = 'SALARY_DATA_MONTH' AND tap.month = '5' then '5月份'\\n\" +\n                        \"when tap.type = 'SALARY_DATA_MONTH' AND tap.month = '6' then '6月份'\\n\" +\n                        \"else null end\\n\" +\n                        \")) as YC\\n\" +\n                        \"from t_alert_project tap\\n\" +\n                        \"inner join t_project_list tpl on tpl.projectid = tap.projectid\\n\" +\n                        \"where tap.month in ('4','5','6')\\n\" +\n                        \"group by\\n\" +\n                        \"tpl.projectname,\\n\" +\n                        \"tpl.address,\\n\" +\n                        \"tpl.transactor,\\n\" +\n                        \"tpl.transactor_tel\\n\" +\n                        \"order by tpl.projectname\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest2 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateOracle(\"CREATE SEQUENCE projects_seq START WITH 10000\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest3 {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"CREATE TRIGGER \\\"AO_4AEACD_WEBHOOK_D367380484\\\" \"\n                        + \"BEFORE INSERT\"//\n                        + \"    ON \\\"AO_4AEACD_WEBHOOK_DAO\\\"   FOR EACH ROW \"//\n                        + \"BEGIN\"//\n                        + \"    SELECT \\\"AO_4AEACD_WEBHOOK_DAO_ID_SEQ\\\".NEXTVAL INTO :NEW.\\\"ID\\\" FROM DUAL;\"//\n                        + \"END;\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest4 {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"select sequence_name from all_sequences  \"\n                        + \"union select synonym_name\"\n                        + \"   from all_synonyms us, all_sequences asq\"\n                        + \"  where asq.sequence_name = us.table_name\"\n                        + \"    and asq.sequence_owner = us.table_owner\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest5 {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"DROP TRIGGER \\\"AO_4AEACD_WEBHOOK_D367380484\\\"\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest6 {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"select *\"\n                        + \"  from (SELECT Distinct notice.NSERIAL,\"\n                        + \"                        unit.CUNIT_name,\"\n                        + \"                        us.CUSER_name,\"\n                        + \"                        to_char(notice.DCREATE, 'yyyy-mm-dd') DCREATE,\"\n                        + \"                        notice.csubject,\"\n                        + \"                        notice.ccontent\"\n                        + \"          From mewp_notice_info notice, bas_user us, bas_unit unit\"\n                        + \"          Left Join bas_area xsArea\"\n                        + \"            On unit.ccounty_code = xsArea.Carea_Code\"\n                        + \"          Left Join bas_area pqArea\"\n                        + \"            On unit.cpiece_code = pqArea.Carea_Code\"\n                        + \"          Left Join bas_area xzArea\"\n                        + \"            On unit.cctown_code = xzArea.Carea_Code\"\n                        + \"          Left Join bas_area czArea\"\n                        + \"            On unit.cvillage_code = czArea.Carea_Code\"\n                        + \"         Where notice.cunit_code = unit.cunit_code\"\n                        + \"           And notice.cuser_id = us.cuser_code\"\n                        + \"           And notice.nstate = 4\"\n                        + \"           And (notice.nrole = '****' or notice.nrole = '202')\"\n                        + \"           and notice.cunit_code in\"\n                        + \"               (select 'CP0008'\"\n                        + \"                  from dual\"\n                        + \"                union\"\n                        + \"                select Distinct t.cunit_code\"\n                        + \"                  from bas_unit t, bas_area us\"\n                        + \"                 where t.ccounty_code = us.carea_code\"\n                        + \"                   and t.ccounty_code = 'CP'\"\n                        + \"                   and t.ctype = '201'\"\n                        + \"                union\"\n                        + \"                select Distinct auser.cunit_code\"\n                        + \"                  from bas_user auser, bas_user_role ur\"\n                        + \"                 where auser.cuser_code = ur.cuser_code\"\n                        + \"                   and (ur.nrole_id = '1' or ur.nrole_id = '20'))\"\n                        + \"         order by DCREATE desc)\"\n                        + \" where rownum <= 30\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest7.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest7 {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"begin\\n\"\n                        + \"end\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n\n    @Test\n    public void test_insert_all() throws Exception {\n        String sql = //\n                \"INSERT ALL\\n\" +\n                        \"  INTO mytable (column1, column2, column_n) VALUES (expr1, expr2, expr_n)\\n\" +\n                        \"  INTO mytable (column1, column2, column_n) VALUES (expr1, expr2, expr_n)\\n\" +\n                        \"  INTO mytable (column1, column2, column_n) VALUES (expr1, expr2, expr_n)\\n\" +\n                        \"SELECT * FROM dual;\";\n\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n\n    @Test\n    public void test_lock() throws Exception {\n        String sql = //\n                \"LOCK TABLE \\\"SFXT\\\".\\\"FLYWAY_SCHEMA_HISTORY\\\" IN EXCLUSIVE MODE\";\n\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest8_alter_rebuild.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest8_alter_rebuild {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"alter index idx_t1 rebuild\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest9_exists.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.oracle;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleWallTest9_exists {\n    @Test\n    public void test_true() throws Exception {\n        String sql = //\n                \"select *\\n\" +\n                        \"  from V v\\n\" +\n                        \" where  v.u_id in (select id from U where wx_b = 1)\\n\" +\n                        \"   and not exists (select 1 from M where code = v.code)\\n\" +\n                        \"   and rownum < 1000\";\n        assertTrue(WallUtils.isValidateOracle(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/pg/PGWallTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.pg;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class PGWallTest1 {\n    @Test\n    public void test_wall() throws Exception {\n        assertTrue(WallUtils.isValidatePostgres(//\n                \"select pg_encoding_to_char(encoding) from pg_database where datname = current_database()\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/pg/PGWallTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.pg;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class PGWallTest2 {\n    @Test\n    public void test_wall() throws Exception {\n        assertTrue(WallUtils.isValidatePostgres(//\n                \"select u.id, (\\n\" +\n                        \"\\tWITH RECURSIVE users AS (\\n\" +\n                        \"\\t\\tselect id from t_user limit 1\\n\" +\n                        \"\\t) select id from users\\n\" +\n                        \") from t_user u \\n\" +\n                        \"limit 1;\"));\n    }\n\n    @Test\n    public void test_wall_2() throws Exception {\n        assertTrue(WallUtils.isValidatePostgres(//\n                \"select 1 from t_user u\\n\" +\n                        \"join (\\n\" +\n                        \"\\tWITH RECURSIVE users AS (\\n\" +\n                        \"\\t\\tselect id from t_user limit 1\\n\" +\n                        \"\\t) select id from users\\n\" +\n                        \") t on u.id = t.id;\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallPermitFunctionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallPermitFunctionTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallPermitFunctionTest {\n    /*\n     * (non-Javadoc)\n     * @see junit.framework.TestCase#setUp()\n     */\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    /*\n     * (non-Javadoc)\n     * @see junit.framework.TestCase#tearDown()\n     */\n    @AfterEach\n    protected void tearDown() throws Exception {\n    }\n\n    @Test\n    public void test01() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT user_name() FROM X;\"));\n    }\n\n    public final void test_sp_addsrvrolemenber() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"EXEC master.dbo.sp_addsrvrolemember ‘user’, ‘sysadmin\"));\n    }\n\n    public final void test_sp_helpdb() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"EXEC sp_helpdb master\"));\n        assertTrue(WallUtils.isValidateSqlServer(\"EXEC sp_helpdb pubs\"));\n    }\n\n    public final void test_sp_droplogin() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"EXEC sp_droplogin ‘user’;\"));\n    }\n\n    public final void test_sp_addlogin() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"EXEC sp_addlogin ‘user’, ‘pass’; \"));\n    }\n\n    public final void test_db_name() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT DB_NAME() FROM X\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT DB_NAME(0) FROM X; \"));\n    }\n\n    public final void test_host_name() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT HOST_NAME() FROM X\"));\n    }\n\n    /**\n     * 测试权限结构\n     *\n     * @throws Exception\n     */\n    @Test\n    public void test_is_srvrolemember() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘sysadmin’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘dbcreator’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘bulkadmin’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘diskadmin’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘processadmin’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘serveradmin’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘setupadmin’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘securityadmin’) FROM X;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘sysadmin’) FROM X; \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"select * from t where fid = 1 UNION SELECT is_srvrolemember(‘sysadmin’, ‘sa’) FROM X; \"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallPermitObjectTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallPermitObjectTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallPermitObjectTest {\n    /*\n     * (non-Javadoc)\n     * @see junit.framework.TestCase#setUp()\n     */\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    /*\n     * (non-Javadoc)\n     * @see junit.framework.TestCase#tearDown()\n     */\n    @AfterEach\n    protected void tearDown() throws Exception {\n    }\n\n    @Test\n    public void test_user() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"SELECT user;\"));\n    }\n\n    @Test\n    public void test_user2() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT id from T where 1=1 and 1!=1 union select user;\"));\n    }\n\n    @Test\n    public void test_system_user() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"SELECT system_user;\"));\n    }\n\n    @Test\n    public void test_system_user2() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT id from T where 1=1 and 1!=1 union select system_user;\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallPermitSchemaTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallPermitSchemaTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallPermitSchemaTest {\n    /* (non-Javadoc)\n     * @see junit.framework.TestCase#setUp()\n     */\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    /* (non-Javadoc)\n     * @see junit.framework.TestCase#tearDown()\n     */\n    @AfterEach\n    protected void tearDown() throws Exception {\n    }\n\n    @Test\n    public void test_master() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name, password FROM master..sysxlogins\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT permission_name FROM master..fn_my_permissions(null, ‘DATABASE’); \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT permission_name FROM master..fn_my_permissions(null, ‘SERVER’); \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT permission_name FROM master..fn_my_permissions(‘master..syslogins’, ‘OBJECT’);\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT permission_name FROM master..fn_my_permissions(‘sa’, ‘USER’);\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE denylogin = 0;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE hasaccess = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE isntname = 0;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE isntgroup = 0;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE sysadmin = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE securityadmin = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE serveradmin = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE setupadmin = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE processadmin = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE diskadmin = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE dbcreator = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE bulkadmin = 1;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name, master.dbo.fn_varbintohexstr(password) FROM master..sysxlogins\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master..syscolumns, master..sysobjects WHERE master..syscolumns.id=master..sysobjects.id AND master..sysobjects.name=’sometable’; \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..sysobjects WHERE xtype = ‘U’; — use xtype = ‘V’ for views SELECT name FROM someotherdb..sysobjects WHERE xtype = ‘U’; \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins WHERE sysadmin = ’1′ \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..sysdatabases;\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT TOP 1 name FROM (SELECT TOP 9 name FROM master..syslogins ORDER BY name ASC) sq ORDER BY name DESC \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name + ‘-’ + master.sys.fn_varbintohexstr(password_hash) from master.sys.sql_logins\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT loginame FROM master..sysprocesses WHERE spid = @@SPID\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name FROM master..syslogins\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT *FROM T UNION SELECT name, password_hash FROM master.sys.sql_logins\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallPermitTableTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试访问SQLServer系统表\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallPermitTableTest {\n    @Test\n    public void test01() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT * FROM T UNION select * from sysObjects\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT * FROM T UNION select * from sysdatabases\"));\n    }\n\n    @Test\n    public void test03() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT * FROM T UNION SELECT sysobjects.name as tablename, syscolumns.name as columnname FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id WHERE sysobjects.xtype = ‘U’ AND syscolumns.name LIKE ‘%PASSWORD%’ \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT * FROM T UNION SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = ‘mytable’);\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest {\n    /*\n     * (non-Javadoc)\n     * @see junit.framework.TestCase#setUp()\n     */\n    @BeforeEach\n    protected void setUp() throws Exception {\n    }\n\n    /*\n     * (non-Javadoc)\n     * @see junit.framework.TestCase#tearDown()\n     */\n    @AfterEach\n    protected void tearDown() throws Exception {\n    }\n\n    @Test\n    public void test_stuff() throws Exception {\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT * from table where version = @@version\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT 1 — comment\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"SELECT * from t where a=1 /* and b=1*/\"));\n        assertFalse(WallUtils.isValidateSqlServer(\"WAITFOR DELAY ’0:0:5′ \"));\n        assertFalse(WallUtils.isValidateSqlServer(\"BULK INSERT mydata FROM ‘c:boot.ini’;\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_0 {\n    private WallProvider initWallProvider() {\n        WallProvider provider = new SQLServerWallProvider();\n\n        provider.getConfig().setStrictSyntaxCheck(false);\n        provider.getConfig().setMultiStatementAllow(true);\n        provider.getConfig().setConditionAndAlwayTrueAllow(true);\n        provider.getConfig().setNoneBaseStatementAllow(true);\n        provider.getConfig().setLimitZeroAllow(true);\n        provider.getConfig().setConditionDoubleConstAllow(true);\n\n        provider.getConfig().setCommentAllow(true);\n        provider.getConfig().setSelectUnionCheck(false);\n\n        return provider;\n    }\n\n    @Test\n    public void test_false() {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT KL_ArticleContent,KL_ArticleTitle FROM dbo.KL_Article WHERE KL_ArticleId =13 And (Select Top 1 unicode(substring(isNull(cast(name as varchar(8000)),char(32)),7,1)) From (Select Top 9 [dbid],[name] From master..sysdatabases Order by [dbid] desc) T Order by [dbid]) between 105 and 105\";\n            assertFalse(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT KL_ArticleContent,KL_ArticleTitle FROM dbo.KL_Article WHERE KL_ArticleId =13 and (select unicode(substring(isNull(cast(db_name() as varchar(8000)),char(32)),1,1))) between 105 and 108\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false1() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select OrderId,Order_Time,oResult,oState,show_Exp_Num,Is_Exp_Print,sel_Exp_Id,Order_Th,Th_Audit_Time,Th_Delay_Days from Pro_Order_List where OrderId='2012110125252' AND HOST_NAME()=HOST_NAME() AND 'kbwg'='kbwg'\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false2() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT characteristic.columnname + '|' + RTRIM(characteristic.rpid) as rpid ,\"\n                    + \" characteristic.columnname, characteristic.chnname \"\n                    + \"FROM characteristic\"\n                    + \"     inner join content_sort\"\n                    + \"         on characteristic.rpid = content_sort.rpid and content_sort.opid = 2\"\n                    + \"WHERE (characteristic.columnname IN (\"\n                    + \"         SELECT name FROM syscolumns\"\n                    + \"         WHERE (id =(SELECT id FROM sysobjects WHERE (name = 'content')))\"\n                    + \"                 AND (name NOT IN ('billid', 'itemno', 'tableid', 'rpid'))\"\n                    + \"         ))\"\n                    + \"     AND (characteristic.closed = 0)\"\n                    + \"ORDER BY content_sort.sort, characteristic.code\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_false3() throws Exception {\n        WallProvider provider = initWallProvider();\n\n        {\n            String sql = \"SELECT rpid, columnname, chnname, type, textfield\"\n                    + \"     , valuefield, ddlbtable, ddlbwhere, ddlbsort, datatype \"//\n                    + \"FROM characteristic \"//\n                    + \"WHERE (closed = 0)\"\n                    + \"     AND ((SELECT COUNT(*) FROM sysobjects WHERE (id IN (SELECT id FROM syscolumns WHERE name = columnname)) AND (name = 'content')) > 0) ORDER BY code\";\n            assertFalse(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true2() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select Fg.name as TableFg, dsp.name as TexImageFg, FtCat.name as FulltextCatalog, OBJECTPROPERTY(tbl.object_id, 'TableTextInRowLimit') as TextInrowLimit, OBJECTPROPERTY(tbl.object_id, 'IsIndexable'), user_name(tbl.principal_id) as DirectOwner, tbl.is_replicated, tbl.lock_escalation_desc from sys.tables tbl left outer join sys.data_spaces dsp on dsp.data_space_id = tbl.lob_data_space_id left outer join (sys.fulltext_indexes fti inner join sys.fulltext_catalogs FtCat on FtCat.fulltext_catalog_id = fti.fulltext_catalog_id ) on fti.object_id = tbl.object_id inner join (sys.indexes idx inner join sys.data_spaces Fg on (idx.index_id = 0 or idx.index_id = 1) and Fg.data_space_id = idx.data_space_id) on idx.object_id = tbl.object_id and (idx.index_id = 0 or idx.index_id = 1) where tbl.object_id = is_member(N'dbo.nqh_TelOrder') \";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true3() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select '' relation,count(*) addr,0 cha_id,'' cha_name,0 icon,'' motto from (   select distinct master.relation relation from character INNER JOIN   master ON character.cha_id = master.cha_id1 where master.cha_id2 = 11272   ) cc union select master.relation relation,count(character.mem_addr) addr,0   cha_id,'' cha_name,1 icon,'' motto from character INNER JOIN master ON   character.cha_id = master.cha_id1 where master.cha_id2 = 11272 group by relation   union select master.relation relation,character.mem_addr addr,character.cha_id   cha_id,character.cha_name cha_name,character.icon icon,character.motto motto   from character INNER JOIN master ON character.cha_id = master.cha_id1   where master.cha_id2 = 11272 order by relation,cha_id,icon\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true4() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT tableid, chnname \"//\n                    + \"FROM r_temptable \"//\n                    + \"INNER JOIN  sys_func_pwr ss ON r_temptable.tableid = ss.mainid \"//\n                    + \"INNER JOIN  sys_func_pwr sys ON ss.parentid = sys.funcid  \"\n                    + \"WHERE (ismaintable = 1)  and  1=1  and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 550) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 551) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 391) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 552) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 393) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 396) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 4628) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 4836) AND (functype = 8) AND (Closed = 0))) and (r_temptable.tableid NOT IN (SELECT DISTINCT mainid FROM sys_func_pwr WHERE (parentid = 394) AND (functype = 8) AND (Closed = 0))) and ss.funcid <> 4298 and ss.funcid <> 7441 AND (ss.funcid IN  (SELECT DISTINCT funcid FROM sys_func_pwr  WHERE (functype = 8) AND (Closed = 0)  ))  ORDER BY sys.sortflag ,ss.sortflag \";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true5() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT ROW_NUMBER() OVER (ORDER BY a.Account) rowno,  a.Account, a.TrueName, a.UserType, a.RegisterDate, SUM(ISNULL(b.O_PVCreditTotal,0)) pvvalue FROM (                                      SELECT M.Account, Mi.TrueName,M.PVCredits, M.RegisterDate, M.UserType FROM dbo.Members M                                      LEFT JOIN dbo.MembersInfo MI ON M.UID = MI.UID                                      WHERE Spreader='JWJ6789') a LEFT JOIN                                      (                                      SELECT SYS_Order.*, dbo.Members.Account FROM dbo.SYS_Order                                       LEFT JOIN dbo.Members ON dbo.SYS_Order.O_UserID = dbo.Members.UID                                      WHERE O_Status <> 0 AND O_Opratedatetime BETWEEN '2013-7-01' AND '2013-8-01'                                       UNION                                      SELECT SYS_Order_BusinessCenter.*, dbo.Members.Account FROM dbo.SYS_Order_BusinessCenter                                       LEFT JOIN dbo.Members ON dbo.SYS_Order_BusinessCenter.O_UserID = dbo.Members.UID                                      WHERE O_Status <> 0 AND O_Opratedatetime BETWEEN '2013-7-01' AND '2013-8-01'                                       ) b ON a.Account = b.principal GROUP BY a.Account, a.TrueName, a.UserType, a.RegisterDate HAVING a.Account LIKE '%%' OR (a.TrueName LIKE '%%' OR ISNULL(a.TrueName,'') LIKE '%%')\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true6() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select count(1) from [Tiger_Help] where 1 = 1 and id = 1\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true7() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select objjc,objname,pwd,servadd from wfp..wfpsys_user where objname in(select name from master..sysdatabases) \";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true8() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"select last_batch,spid=cast(spid as varchar(20)),(SELECT text FROM sys.dm_exec_sql_text(sql_handle)) AS query_text,(SELECT text FROM sys.dm_exec_sql_text(context_info)) AS query_text1,* from master..sysprocesses where dbid=db_id('heecerp') order by master..sysprocesses.last_batch desc\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = initWallProvider();\n        {\n            String sql = \"SELECT COUNT(*) FROM syscolumns WHERE id=is_member(N'taobao_order') AND name='r3_billtype'\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT 'Server[@Name=' + quotename(CAST(serverproperty(N'Servername') AS sysname),'''') + ']' + '/Collation[@Name=' + quotename(cl.name,'''') + ']' AS [Urn], cl.name AS [Name], CAST(COLLATIONPROPERTY(name, 'CodePage') AS int) AS [CodePage], CAST(COLLATIONPROPERTY(name, 'LCID') AS int) AS [LocaleID], CAST(COLLATIONPROPERTY(name, 'ComparisonStyle') AS int) AS [ComparisonStyle], cl.description AS [Description], CAST(COLLATIONPROPERTY(name, 'Version') AS int) AS [CollationVersion] FROM sys.fn_helpcollations() cl ORDER BY [Name] ASC\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT bp.Class_desc, bp.Permission_name, bp.Type, bp.Covering_permission_name, bp.Parent_class_desc, bp.Parent_covering_permission_name FROM sys.fn_builtin_permissions(null) as bp order by bp.class_desc\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select isExist = case when exists(select * from dbo.sysobjects where id = object_id ('SYS_LOG_2005')) then 1 else 0 end\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select length from syscolumns(nolock) where id = is_member('boat') and (name in ('boat_bag','skill_state'))\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select c.COLUMN_NAME, COLUMNPROPERTY(is_member(c.TABLE_SCHEMA + '.' + c.TABLE_NAME), c.COLUMN_NAME, 'IsIdentity') from INFORMATION_SCHEMA.KEY_COLUMN_USAGE c join INFORMATION_SCHEMA.TABLE_CONSTRAINTS p on p.CONSTRAINT_NAME = c.CONSTRAINT_NAME where c.TABLE_NAME = @p1 and c.TABLE_SCHEMA = @p2 and p.TABLE_SCHEMA = @p2 and p.CONSTRAINT_TYPE = 'PRIMARY KEY'\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"INSERT INTO tempdep SELECT tbl.object_id AS [ID], tbl.name AS [Name], SCHEMA_NAME(tbl.schema_id) AS [Schema], db_name(), 3 FROM sys.tables AS tbl WHERE (tbl.name=@_msparam_0 and SCHEMA_NAME(tbl.schema_id)=@_msparam_1)INSERT INTO tempdep SELECT tbl.object_id AS [ID], tbl.name AS [Name], SCHEMA_NAME(tbl.schema_id) AS [Schema], db_name(), 3 FROM sys.tables AS tbl WHERE (tbl.name=@_msparam_2 and SCHEMA_NAME(tbl.schema_id)=@_msparam_3)INSERT INTO tempdep SELECT tbl.object_id AS [ID], tbl.name AS [Name], SCHEMA_NAME(tbl.schema_id) AS [Schema], db_name(), 3 FROM sys.tables AS tbl WHERE (tbl.name=@_msparam_4 and SCHEMA_NAME(tbl.schema_id)=@_msparam_5)INSERT INTO tempdep SELECT tbl.object_id AS [ID], tbl.name AS [Name], SCHEMA_NAME(tbl.schema_id) AS [Schema], db_name(), 3 FROM sys.tables AS tbl WHERE (tbl.name=@_msparam_6 and SCHEMA_NAME(tbl.schema_id)=@_msparam_7)INSERT INTO tempdep SELECT tbl.object_id AS [ID], tbl.name AS [Name], SCHEMA_NAME(tbl.schema_id) AS [Schema], db_name(), 3 FROM sys.tables AS tbl WHERE (tbl.name=@_msparam_8 and SCHEMA_NAME(tbl.schema_id)=@_msparam_9)\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select c.COLUMN_NAME, COLUMNPROPERTY(is_member(c.TABLE_SCHEMA + '.' + c.TABLE_NAME), c.COLUMN_NAME, 'IsIdentity') from sys.KEY_COLUMN_USAGE c join sys.TABLE_CONSTRAINTS p on p.CONSTRAINT_NAME = c.CONSTRAINT_NAME where c.TABLE_NAME = @p1 and c.TABLE_SCHEMA = @p2 and p.TABLE_SCHEMA = @p2 and p.CONSTRAINT_TYPE = 'PRIMARY KEY'\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT user_name(), @@MAX_PRECISION, is_member('db_owner'), permissions(), DatabasePropertyEx(db_name(), N'collation'), SERVERPROPERTY('IsFullTextInstalled'), schema_name()\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select col.name, col.column_id, st.name as DT_name, schema_name(st.schema_id) as DT_schema, col.max_length, col.precision, col.scale, bt.name as BT_name, col.collation_name, col.is_nullable, col.is_ansi_padded, col.is_rowguidcol, col.is_identity, case when(idc.column_id is null) then null else CONVERT(nvarchar(40), idc.seed_value) end, case when(idc.column_id is null) then null else CONVERT(nvarchar(40), idc.increment_value) end, CONVERT(bit, case when(cmc.column_id is null) then 0 else 1 end) as is_computed, convert(bit, ColumnProperty(col.object_id, col.name, N'IsIdNotForRepl')) as IsIdNotForRepl, col.is_replicated, col.is_non_sql_subscribed, col.is_merge_published, col.is_dts_replicated, col.rule_object_id, robj.name as Rul_name, schema_name(robj.schema_id) as Rul_schema, col.default_object_id, OBJECTPROPERTY(col.default_object_id, N'IsDefaultCnst') as is_defcnst, dobj.name as def_name, schema_name(dobj.schema_id) as def_schema, CONVERT(bit, case when (ftc.column_id is null) then 0 else 1 end) as is_FullTextCol, col_name(col.object_id, ftc.type_column_id) FT_type_column, ftc.language_id as FT_language_id, case when(cmc.column_id is null) then null else cmc.definition end as formular, case when(cmc.column_id is null) then null else cmc.is_persisted end as is_persisted, defCst.definition, COLUMNPROPERTY(col.object_id, col.name, 'IsDeterministic') as IsDeterministic, xmlcoll.name as xmlSchema_name, schema_name(xmlcoll.schema_id) as xmlSchema_schema, col.is_xml_document, col.is_sparse, col.is_column_set from sys.columns col left outer join sys.types st on st.user_type_id = col.user_type_id left outer join sys.types bt on bt.user_type_id = col.system_type_id left outer join sys.objects robj on robj.object_id = col.rule_object_id and robj.type = 'R' left outer join sys.objects dobj on dobj.object_id = col.default_object_id and dobj.type = 'D' left outer join sys.default_constraints defCst on defCst.parent_object_id = col.object_id and defCst.parent_column_id = col.column_id left outer join sys.identity_columns idc o\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT * FROM `www_subject` WHERE subject like '哎%' or subject like '%' ORDER BY aid desc LIMIT 30 \";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"SELECT COUNT(*) FROM syscolumns WHERE id=is_member(N'taobao_order') AND name='r3_billtype'\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select col.name, st.name as DT_name, case when (st.name in ('nchar', 'nvarchar') and (col.max_length > 0)) then col.max_length / 2 else col.max_length end, col.precision, col.scale, bt.name as BT_name, col.is_nullable, col.is_identity,col.is_rowguidcol, OBJECTPROPERTY(col.default_object_id, N'IsDefaultCnst') as is_defcnst, CONVERT(bit, case when(cmc.column_id is null) then 0 else 1 end) as is_computed, case when(cmc.column_id is null) then null else cmc.definition end as formular, col.collation_name, col.system_type_id from nowshop.sys.all_columns col left outer join nowshop.sys.types st on st.user_type_id = col.user_type_id left outer join nowshop.sys.types bt on bt.user_type_id = col.system_type_id left outer join nowshop.sys.identity_columns idc on idc.object_id = col.object_id and idc.column_id = col.column_id left outer join nowshop.sys.computed_columns cmc on cmc.object_id = col.object_id and cmc.column_id = col.column_id where col.object_id = is_member(N'nowshop.dbo.hr_shop') order by col.column_id\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"update dbo.dml_health_check set name='123' where id=is_member(N'taobao_order')\";\n            assertFalse(provider.checkValid(sql));\n        }\n        {\n            String sql = \"update master.dbo.dml_health_check set id=1\";\n            assertTrue(provider.checkValid(sql));\n        }\n        {\n            String sql = \"select * from tb_product_word where name='' or CONCAT(name,style)='' or CONCAT(shop,style)='' or CONCAT(ename,style)=''\";\n            assertTrue(provider.checkValid(sql));\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_1 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"SELECT @ret\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_10.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @see\n */\npublic class SQLServerWallTest_10 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        String sql = \"select top 50 * FROM [V_Goods_WithAvailableStockQuantity] where Status='����' and (Code like '%mu%' ESCAPE '\\' or Model like '%mu%' ESCAPE '\\' or Spec like '%mu%' ESCAPE '\\' or BarCode like '%mu%' ESCAPE '\\' or ProductName like '%mu%' ESCAPE '\\' or dbo.F_GetPY(ProductName) like '%mu%' ESCAPE '\\') \";\n\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_11.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @see\n */\npublic class SQLServerWallTest_11 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        provider.getConfig().setCommentAllow(true);\n\n        String sql = \"SELECT KL_ArticleContent,KL_ArticleTitle \"\n                + \"FROM dbo.KL_Article \"\n                + \"WHERE KL_ArticleId =-4731 \"//\n                + \"UNION ALL \"//\n                + \"SELECT (SELECT TOP 1 CHAR(58)+CHAR(108)+CHAR(107)+CHAR(103)+CHAR(58)+ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32))+CHAR(58)+CHAR(109)+CHAR(122)+CHAR(104)+CHAR(58) FROM sys.sql_logins WHERE ISNULL(name,CHAR(32)) NOT IN (SELECT TOP 0 ISNULL(name,CHAR(32)) FROM sys.sql_logins ORDER BY 1) ORDER BY 1),NULL-- \";\n\n        assertFalse(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_12.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @see\n */\npublic class SQLServerWallTest_12 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n        provider.getConfig().setCommentAllow(true);\n\n        String sql = \"EXEC master..xp_msver\";\n\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_2 {\n    @Test\n    public void test_true() throws Exception {\n        assertTrue(WallUtils.isValidateSqlServer(\"rollback\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_3 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        assertFalse(provider.checkValid(//\n                \"select * from t where LEN(HOST_NAME()) > 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_4 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"insert into t (fid, name) values (1, HOST_NAME())\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_5 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        assertFalse(provider.checkValid(//\n                \"delete t where LEN(HOST_NAME()) > 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_6 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        assertFalse(provider.checkValid(//\n                \"update t set fid = 1 where LEN(HOST_NAME()) > 0\"));\n\n        assertEquals(1, provider.getTableStats().size());\n        assertTrue(provider.getTableStats().containsKey(\"t\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_7.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_7 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        provider.getConfig().setSelectHavingAlwayTrueCheck(true);\n\n        assertTrue(provider.checkValid(//\n                \"select * from (select top 3000 jol.id as primaryKeyIds, jo.orderNo as 委托单号, bm.custname as 委托方名称, manuCustInfo.custname as 出证方, jo.chkerDate as 委托日期, bcc.connectName as 联系人, bcc.mobile as  电话,jol.barcode as 样品条码, jol.name as 样品名称,  jol.qtysub as 套件数量,jol.OnlyCode as 唯一识别码,jol.manufacture as 制造厂商,jol.sprc as 规格型号, jol.outno as 出厂编号, djod.name as 任务状态, djoc.name  委托类别, dct.name as 证书类型,bdp.organ_name as 分配室组, jol.task_id as 任务ID, be.user_name as 检定人员, verifyUser.user_name as 核验员, checkUser.user_name as 批准员, jol.ddate 交款日期,cjcs.name as 缴款状态, jc.moneys as 应收费, jc.moneystotal as 实收费, be.organ_id from jl_OrderList jol left outer join jl_CheckList jc on jol.checkList_id = jc.id left outer join jl_Order jo on jol.orderid = jo.id left outer join ba_dptinfo bdp on jol.dptid = bdp.id left outer join jl_Task jt on jol.task_id = jt.id left outer join ba_manucustinfo bm on jo.entrustCustId = bm.id left outer join ba_manucustinfo manuCustInfo on jo.custid = manuCustInfo.id left outer join ba_custconnect bcc on jo.linkPerson = bcc.id left outer join ba_employeeinfo be on jt.jdUserId = be.id left outer join ba_employeeinfo verifyUser on jt.verifyUser = verifyUser.id left outer join ba_employeeinfo checkUser on jt.checkUser = checkUser.id left outer join dict_jl_order_doType djod on jol.dotypeid = djod.id left outer join dict_jl_order_class djoc on jo.orderclassid = djoc.id left outer join dict_certificate_type dct on jt.certificatetype = dct.id left outer join dict_jl_chargestatus cjcs on jol.chargestatus = cjcs.id where jol.id >= (select min(primaryKeyId) from (select top  3000 jol.id as primaryKeyId from  jl_OrderList jol left outer join jl_CheckList jc on jol.checkList_id = jc.id left outer join jl_Order jo on jol.orderid = jo.id left outer join ba_dptinfo bdp on jol.dptid = bdp.id left outer join jl_Task jt on jol.task_id = jt.id left outer join ba_manucustinfo bm on jo.entrustCustId = bm.id left outer join ba_manucustinfo manuCustInfo on jo.custid = manuCustInfo.id left outer join ba_custconnect bcc on jo.linkPerson = bcc.id left outer join ba_employeeinfo be on jt.jdUserId = be.id left outer join ba_employeeinfo verifyUser on jt.verifyUser = verifyUser.id left outer join ba_employeeinfo checkUser on jt.checkUser = checkUser.id left outer join dict_jl_order_doType djod on jol.dotypeid = djod.id left outer join dict_jl_order_class djoc on jo.orderclassid = djoc.id left outer join dict_certificate_type dct on jt.certificatetype = dct.id left outer join dict_jl_chargestatus cjcs on jol.chargestatus = cjcs.id where jo.chkerDate >= ? and jo.chkerDate <= ? and jol.ddate >= ? order by jol.id desc, jo.id DESC) as T)  and jo.chkerDate >= ? and jo.chkerDate <= ? and jol.ddate >= ? order by jol.id asc, jo.id DESC) as T1 order by T1.primaryKeyIds desc\"));\n\n//        assertEquals(12, provider.getTableStats().size());\n//        assertTrue(provider.getTableStats().containsKey(\"jl_OrderList\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_8.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @author RaymondXiu\n * @version 1.0, 2012-3-18\n * @see\n */\npublic class SQLServerWallTest_8 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        provider.getConfig().setMustParameterized(true);\n\n        assertFalse(provider.checkValid(\"select * from t where fid = 1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/filter/wall/sqlserver/SQLServerWallTest_9.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.filter.wall.sqlserver;\n\nimport com.alibaba.druid.wall.WallProvider;\nimport com.alibaba.druid.wall.spi.SQLServerWallProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * SQLServerWallTest\n *\n * @see\n */\npublic class SQLServerWallTest_9 {\n    @Test\n    public void test_true() throws Exception {\n        WallProvider provider = new SQLServerWallProvider();\n\n        String sql = \"SELECT s.id FROM snapshots s \"\n                + \"WHERE s.scope='PRJ'\"//\n                + \" and s.qualifier IN ('TRK', 'BRC')\"//\n                + \" AND status='P'\"\n                + \" AND islast=0\"\n                + \" AND NOT EXISTS (select m.id from project_measures m WHERE m.snapshot_id=s.id)\";\n\n        assertTrue(provider.checkValid(sql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/hibernate/HibernateCRUDTest.java",
    "content": "package com.alibaba.druid.bvt.hibernate;\n\nimport com.alibaba.druid.bvt.hibernate.entity.Sample;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.hibernate.Session;\nimport org.hibernate.SessionFactory;\nimport org.hibernate.Transaction;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.orm.hibernate4.LocalSessionFactoryBean;\n\nimport java.io.IOException;\nimport java.util.Date;\nimport java.util.Properties;\n\n/**\n * @author yinheli [yinheli@gmail.com]\n * @date 2012-11-26 下午11:41\n */\npublic class HibernateCRUDTest {\n    private static final Logger log = LoggerFactory.getLogger(HibernateCRUDTest.class);\n\n    private DruidDataSource dataSource;\n\n    private SessionFactory sessionFactory;\n\n    @BeforeEach\n    public void setUp() throws Exception {\n        /*init dataSource*/\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:h2:file:~/.h2/HibernateCRUDTest;AUTO_SERVER=TRUE\");\n        dataSource.setUsername(\"sa\");\n        dataSource.setPassword(\"\");\n        dataSource.setDefaultAutoCommit(false);\n        dataSource.setFilters(\"log4j\");\n\n        /*init sessionFactory*/\n        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();\n        factoryBean.setDataSource(dataSource);\n\n        Properties prop = new Properties();\n        prop.put(\"hibernate.show_sql\", \"true\");\n        //prop.put(\"hibernate.format_sql\", \"true\");\n        prop.put(\"hibernate.hbm2ddl.auto\", \"create\");\n        prop.put(\"hibernate.dialect\", \"org.hibernate.dialect.H2Dialect\");\n        factoryBean.setHibernateProperties(prop);\n        factoryBean.setAnnotatedClasses(new Class<?>[]{Sample.class});\n\n        try {\n            factoryBean.afterPropertiesSet();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        sessionFactory = factoryBean.getObject();\n    }\n\n    @AfterEach\n    public void tearDown() throws Exception {\n        sessionFactory.close();\n        JdbcUtils.close(dataSource);\n    }\n\n    private void doCreate(Session session) {\n        Sample sample = new Sample();\n        sample.setId(1L);\n        sample.setDesc(\"sample\");\n        sample.setCreateTime(new Date());\n        session.save(sample);\n    }\n\n    private void doGet(Session session) {\n        Sample sample = (Sample) session.get(Sample.class, 1L);\n        log.debug(\"**sample:{}\", sample);\n        assert sample != null;\n    }\n\n    private void doUpdate(Session session) {\n        Sample sample = (Sample) session.get(Sample.class, 1L);\n        assert sample != null;\n        sample.setDesc(\"update sample\");\n        sample.setUpdateTime(new Date());\n        session.update(sample);\n    }\n\n    private void doDelete(Session session) {\n        Sample sample = (Sample) session.get(Sample.class, 1L);\n        assert sample != null;\n        session.delete(sample);\n    }\n\n    /*-------- test start --------*/\n\n    @Test\n    public void test_create() {\n        Session session = null;\n        try {\n            session = sessionFactory.openSession();\n            doCreate(session);\n        } finally {\n            if (session != null) {\n                session.close();\n            }\n        }\n    }\n\n    @Test\n    public void test_get() {\n        Session session = null;\n        try {\n            session = sessionFactory.openSession();\n            doCreate(session);\n            doGet(session);\n        } finally {\n            if (session != null) {\n                session.close();\n            }\n        }\n    }\n\n    @Test\n    public void test_update() {\n        Session session = null;\n        try {\n            session = sessionFactory.openSession();\n            doCreate(session);\n            doUpdate(session);\n        } finally {\n            if (session != null) {\n                session.close();\n            }\n        }\n    }\n\n    @Test\n    public void test_delete() {\n        Session session = null;\n        try {\n            session = sessionFactory.openSession();\n            doCreate(session);\n            doDelete(session);\n        } finally {\n            if (session != null) {\n                session.close();\n            }\n        }\n    }\n\n    @Test\n    public void test_transactional_create() {\n        Session session = null;\n        Transaction tran = null;\n        try {\n            session = sessionFactory.openSession();\n            tran = session.beginTransaction();\n            doCreate(session);\n        } finally {\n            if (tran != null) {\n                tran.commit();\n            }\n            if (session != null) {\n                session.close();\n            }\n        }\n    }\n\n    @Test\n    public void test_transactional_update() {\n        Session session = null;\n        Transaction tran = null;\n        try {\n            session = sessionFactory.openSession();\n            tran = session.beginTransaction();\n            doCreate(session);\n            doUpdate(session);\n        } finally {\n            if (tran != null) {\n                tran.commit();\n            }\n            if (session != null) {\n                session.close();\n            }\n        }\n    }\n\n    @Test\n    public void test_transactional_delete() {\n        Session session = null;\n        Transaction tran = null;\n        try {\n            session = sessionFactory.openSession();\n            tran = session.beginTransaction();\n            doCreate(session);\n            doDelete(session);\n        } finally {\n            if (tran != null) {\n                tran.commit();\n            }\n            if (session != null) {\n                session.close();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/hibernate/entity/Sample.java",
    "content": "package com.alibaba.druid.bvt.hibernate.entity;\n\nimport javax.persistence.Entity;\nimport javax.persistence.Id;\nimport javax.persistence.Table;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * @author yinheli [yinheli@gmail.com]\n */\n@Entity\n@Table(name = \"SAMPLE\")\npublic class Sample implements Serializable {\n    @Id\n    private Long id;\n\n    private String name;\n\n    private String desc;\n\n    private Date createTime;\n\n    private Date updateTime;\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n\n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Date getUpdateTime() {\n        return updateTime;\n    }\n\n    public void setUpdateTime(Date updateTime) {\n        this.updateTime = updateTime;\n    }\n\n    @Override\n    public String toString() {\n        return \"Sample{\" +\n                \"createTime=\" + createTime +\n                \", id=\" + id +\n                \", name='\" + name + '\\'' +\n                \", desc='\" + desc + '\\'' +\n                \", updateTime=\" + updateTime +\n                '}';\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/jmx/DupRegisterTest.java",
    "content": "package com.alibaba.druid.bvt.jmx;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.MBeanServer;\n\nimport java.lang.management.ManagementFactory;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DupRegisterTest {\n    private DruidDataSource dataSource;\n\n    @Test\n    public void test_0() throws Exception {\n        dataSource.init();\n\n        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();\n        mbeanServer.registerMBean(dataSource, dataSource.getObjectName());\n        assertTrue(mbeanServer.isRegistered(dataSource.getObjectName()));\n    }\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMinEvictableIdleTimeMillis(10);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/jmx/JMXExporterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.jmx;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\nimport javax.management.ObjectName;\n\nimport java.lang.management.ManagementFactory;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class JMXExporterTest {\n    @Test\n    public void test_export() throws Exception {\n        String file = \"com/alibaba/druid/jmx/spring_stat_export.xml\";\n\n        ObjectName objectName = new ObjectName(\"com.alibaba.druid:type=JdbcStatManager\");\n\n        assertFalse(ManagementFactory.getPlatformMBeanServer().isRegistered(objectName)); // before jmx register\n\n        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(file);\n\n        assertTrue(ManagementFactory.getPlatformMBeanServer().isRegistered(objectName)); // after jmx register\n\n        context.close();\n\n        assertFalse(ManagementFactory.getPlatformMBeanServer().isRegistered(objectName));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/log/LoggerTest.java",
    "content": "package com.alibaba.druid.bvt.log;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\nimport java.security.PrivilegedAction;\nimport java.sql.Connection;\nimport java.util.Enumeration;\nimport java.util.HashSet;\nimport java.util.Set;\n\npublic class LoggerTest {\n    private static java.security.ProtectionDomain DOMAIN;\n\n    private ClassLoader contextClassLoader;\n    private DruidDataSource dataSource;\n\n    static {\n        DOMAIN = (java.security.ProtectionDomain) java.security.AccessController.doPrivileged(new PrivilegedAction<Object>() {\n            public Object run() {\n                return TestLoader.class.getProtectionDomain();\n            }\n        });\n    }\n\n    public static class TestLoader extends ClassLoader {\n        private ClassLoader loader;\n\n        private Set<String> definedSet = new HashSet<String>();\n\n        public TestLoader() {\n            super(null);\n            loader = DruidDriver.class.getClassLoader();\n        }\n\n        public URL getResource(String name) {\n            return loader.getResource(name);\n        }\n\n        public Enumeration<URL> getResources(String name) throws IOException {\n            return loader.getResources(name);\n        }\n\n        public Class<?> loadClass(String name) throws ClassNotFoundException {\n            if (name.startsWith(\"java\")) {\n                return loader.loadClass(name);\n            }\n\n            if (definedSet.contains(name)) {\n                return super.loadClass(name);\n            }\n\n            String resourceName = name.replace('.', '/') + \".class\";\n            InputStream is = loader.getResourceAsStream(resourceName);\n            if (is == null) {\n                throw new ClassNotFoundException();\n            }\n            try {\n                byte[] bytes = Utils.readByteArray(is);\n                this.defineClass(name, bytes, 0, bytes.length, DOMAIN);\n                definedSet.add(name);\n            } catch (IOException e) {\n                throw new ClassNotFoundException(e.getMessage(), e);\n            }\n            try {\n                is.close();\n            } catch (IOException e) {\n                // TODO Auto-generated catch block\n                e.printStackTrace();\n            }\n\n            Class<?> clazz = super.loadClass(name);\n\n            return clazz;\n        }\n    }\n\n    @Test\n    public void test_log() throws Exception {\n        TestLoader classLoader = new TestLoader();\n\n        Thread.currentThread().setContextClassLoader(classLoader);\n        dataSource = new DruidDataSource();\n        dataSource.setFilters(\"log\");\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        contextClassLoader = Thread.currentThread().getContextClassLoader();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        Thread.currentThread().setContextClassLoader(contextClassLoader);\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/mock/MockExecuteTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.mock;\n\nimport com.alibaba.druid.PoolTestCase;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.sql.Timestamp;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MockExecuteTest extends PoolTestCase {\n    public void test_0() throws Exception {\n        Connection conn = DriverManager.getConnection(\"jdbc:mock:\");\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(\"SELECT 2\");\n        assertTrue(rs.next());\n        assertEquals(2, rs.getInt(1));\n        rs.close();\n\n        stmt.close();\n        conn.close();\n    }\n\n    public void test_1() throws Exception {\n        Connection conn = DriverManager.getConnection(\"jdbc:mock:\");\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(\"SELECT NULL\");\n        assertTrue(rs.next());\n        assertEquals(0, rs.getInt(1));\n        assertEquals(null, rs.getObject(1));\n        rs.close();\n\n        stmt.close();\n        conn.close();\n    }\n\n    public void test_2() throws Exception {\n        Connection conn = DriverManager.getConnection(\"jdbc:mock:\");\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(\"SELECT NOW()\");\n        assertTrue(rs.next());\n        assertTrue(rs.getObject(1) instanceof Timestamp);\n        rs.close();\n\n        stmt.close();\n        conn.close();\n    }\n\n    public void test_3() throws Exception {\n        Connection conn = DriverManager.getConnection(\"jdbc:mock:\");\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(\"SELECT NOW() FROM DUAL\");\n        assertTrue(rs.next());\n        assertTrue(rs.getObject(1) instanceof Timestamp);\n        rs.close();\n\n        stmt.close();\n        conn.close();\n    }\n\n    public void test_4() throws Exception {\n        Connection conn = DriverManager.getConnection(\"jdbc:mock:\");\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(\"SELECT 'ABCDE' FROM DUAL\");\n        assertTrue(rs.next());\n        assertEquals(\"ABCDE\", rs.getString(1));\n        rs.close();\n\n        stmt.close();\n        conn.close();\n    }\n\n    public void test_5() throws Exception {\n        Connection conn = DriverManager.getConnection(\"jdbc:mock:\");\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(\"SELECT true FROM DUAL\");\n        assertTrue(rs.next());\n        assertEquals(true, rs.getBoolean(1));\n\n        rs.close();\n\n        stmt.close();\n        conn.close();\n    }\n\n    public void test_6() throws Exception {\n        Connection conn = DriverManager.getConnection(\"jdbc:mock:\");\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(\"SELECT false FROM DUAL\");\n        assertTrue(rs.next());\n        assertEquals(false, rs.getBoolean(1));\n\n        rs.close();\n\n        stmt.close();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/mock/MockResultSetMetaDataTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.mock;\n\nimport com.alibaba.druid.mock.MockResultSetMetaData;\nimport com.alibaba.druid.util.jdbc.ResultSetMetaDataBase;\nimport com.alibaba.druid.util.jdbc.ResultSetMetaDataBase.ColumnMetaData;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.sql.Date;\nimport java.sql.ResultSetMetaData;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MockResultSetMetaDataTest {\n    @Test\n    public void test_resultSet_metadata() throws Exception {\n        MockResultSetMetaData meta = new MockResultSetMetaData();\n        assertTrue(meta.isWrapperFor(MockResultSetMetaData.class));\n        assertFalse(meta.isWrapperFor(BigDecimal.class));\n        assertTrue(meta.unwrap(MockResultSetMetaData.class) instanceof MockResultSetMetaData);\n        assertTrue(meta.unwrap(ResultSetMetaDataBase.class) instanceof MockResultSetMetaData);\n        assertTrue(meta.unwrap(ResultSetMetaData.class) instanceof MockResultSetMetaData);\n        assertTrue(meta.unwrap(null) == null);\n        assertTrue(meta.unwrap(java.sql.ResultSetMetaData.class) != null);\n        assertTrue(meta.unwrap(Object.class) != null);\n        assertTrue(meta.unwrap(Date.class) == null);\n\n        ColumnMetaData column = new ColumnMetaData();\n        meta.getColumns().add(column);\n\n        meta.isAutoIncrement(1);\n        meta.isCaseSensitive(1);\n        meta.isSearchable(1);\n        meta.isCurrency(1);\n        meta.isNullable(1);\n        meta.isSigned(1);\n        meta.getColumnDisplaySize(1);\n        meta.getColumnLabel(1);\n        meta.getSchemaName(1);\n        meta.getPrecision(1);\n        meta.getScale(1);\n        meta.getTableName(1);\n        meta.getCatalogName(1);\n        meta.getColumnTypeName(1);\n        meta.isReadOnly(1);\n        meta.isWritable(1);\n        meta.isDefinitelyWritable(1);\n        meta.getColumnClassName(1);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/AsyncInitTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class AsyncInitTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setAsyncInit(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialSize(10);\n        dataSource.setMaxActive(10);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_async_init() throws Exception {\n        dataSource.init();\n\n        for (int i = 0; i < 1000; ++i) {\n            if (dataSource.getPoolingCount() == dataSource.getInitialSize()) {\n                break;\n            }\n            Thread.sleep(10);\n        }\n        assertEquals(10, dataSource.getPoolingCount());\n        assertEquals(10, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/AsyncInitTest_1_scheduler.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class AsyncInitTest_1_scheduler extends PoolTestCase {\n    private DruidDataSource dataSource;\n    private ScheduledExecutorService scheduler;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setAsyncInit(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialSize(10);\n        dataSource.setMaxActive(10);\n\n        scheduler = Executors.newScheduledThreadPool(2);\n        dataSource.setCreateScheduler(scheduler);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_async_init() throws Exception {\n        dataSource.init();\n\n        for (int i = 0; i < 1000; ++i) {\n            if (dataSource.getPoolingCount() == dataSource.getInitialSize()) {\n                break;\n            }\n            Thread.sleep(10);\n        }\n        assertEquals(10, dataSource.getPoolingCount());\n        assertEquals(10, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/Bug_for_dupCloseStmtError.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockConnectionClosedException;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DataSourceMonitorable;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Bug_for_dupCloseStmtError extends PoolTestCase {\n    protected DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n        dataSource.setPoolPreparedStatements(false);\n        dataSource.setTestOnBorrow(true);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        for (DataSourceMonitorable dataSource : DruidDataSourceStatManager.getDruidDataSourceInstances()) {\n            JdbcUtils.close(dataSource);\n        }\n\n        super.tearDown();\n    }\n\n    public void test_2() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n            stmt.setString(1, \"xx\");\n\n            MockConnection mockConn = conn.unwrap(MockConnection.class);\n            mockConn.close();\n\n            MockConnectionClosedException error = null;\n            try {\n                stmt.execute();\n            } catch (MockConnectionClosedException ex) {\n                error = ex;\n            }\n\n            assertNotNull(error);\n\n            conn.close();\n            stmt.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(0, dataSource.getDupCloseCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/CallableStatmentTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.CallableStatement;\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CallableStatmentTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setFilters(\"log4j\");\n\n        dataSource.setDriver(new MockDriver() {\n            public MockCallableStatement createMockCallableStatement(MockConnection conn, String sql) {\n                return new MyMockCallableStatement(conn, sql);\n            }\n        });\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connect() throws Exception {\n        MockCallableStatement rawStmt = null;\n        MockResultSet rawRs = null;\n        {\n            Connection conn = dataSource.getConnection();\n\n            CallableStatement stmt = conn.prepareCall(\"select 1\");\n            stmt.execute();\n            rawStmt = stmt.unwrap(MockCallableStatement.class);\n\n            ResultSet rs = (ResultSet) stmt.getObject(0);\n\n            rawRs = rs.unwrap(MockResultSet.class);\n\n            rs.next();\n\n            rs.close();\n            stmt.close();\n\n            assertFalse(rawStmt.isClosed());\n            assertTrue(rawRs.isClosed());\n\n            rawRs = rs.unwrap(MockResultSet.class);\n            assertNotNull(rawRs);\n\n            conn.close();\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            CallableStatement stmt = conn.prepareCall(\"select 1\");\n            stmt.execute();\n\n            assertSame(rawStmt, stmt.unwrap(MockCallableStatement.class));\n            assertFalse(rawStmt.isClosed());\n\n            stmt.getObject(0);\n\n            ResultSet rs = (ResultSet) stmt.getObject(0);\n            rs.next();\n            rs.close();\n\n            stmt.close();\n\n            conn.close();\n        }\n    }\n\n    public static class MyMockCallableStatement extends MockCallableStatement {\n        public MyMockCallableStatement(MockConnection conn, String sql) {\n            super(conn, sql);\n        }\n\n        public Object getObject(int index) throws SQLException {\n            return this.getConnection().getDriver().createResultSet(this);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/Case0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Case0 extends PoolTestCase {\n    public void test_0() throws Exception {\n        final DruidDataSource dataSource = new DruidDataSource();\n\n        dataSource.setDriver(new MockDriver() {\n        });\n        dataSource.setUrl(\"jdbc:mock:\");\n\n        dataSource.setMinIdle(0);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n\n        Connection conn1 = dataSource.getConnection();\n        Connection conn2 = dataSource.getConnection();\n\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch completeLatch = new CountDownLatch(1);\n        final AtomicInteger waitCount = new AtomicInteger();\n        Thread t = new Thread() {\n            public void run() {\n                try {\n                    startLatch.countDown();\n                    waitCount.incrementAndGet();\n                    Connection conn = dataSource.getConnection();\n                    waitCount.decrementAndGet();\n                    conn.close();\n\n                    completeLatch.countDown();\n                } catch (Exception e) {\n                    e.printStackTrace();\n                }\n            }\n        };\n        t.start();\n\n        startLatch.await();\n        assertFalse(completeLatch.await(1, TimeUnit.SECONDS));\n        conn1.close();\n        assertTrue(completeLatch.await(1, TimeUnit.SECONDS));\n        conn2.close();\n        assertTrue(completeLatch.await(1, TimeUnit.SECONDS));\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/Case1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\npublic class Case1 extends PoolTestCase {\n    public void test_f() throws Exception {\n        final DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setTimeBetweenConnectErrorMillis(100);\n\n        final long startTime = System.currentTimeMillis();\n        final long okTime = startTime + 1000 * 1;\n\n        dataSource.setDriver(new MockDriver() {\n            @Override\n            public Connection connect(String url, Properties info) throws SQLException {\n                if (System.currentTimeMillis() < okTime) {\n                    throw new SQLException();\n                }\n\n                return super.connect(url, info);\n            }\n        });\n        dataSource.setUrl(\"jdbc:mock:\");\n\n        dataSource.setMinIdle(0);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        Connection conn = dataSource.getConnection();\n        conn.close();\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/Case2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.util.JMXUtils;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 类Case2.java的实现描述：TODO 类实现描述\n *\n * @author admin 2011-5-4 下午02:45:21\n */\npublic class Case2 extends PoolTestCase {\n    public void test_singleThread() throws Exception {\n        Class.forName(\"com.alibaba.druid.mock.MockDriver\");\n\n        Properties properties = new Properties();\n        properties.put(\"maxActive\", \"100\");\n        properties.put(\"maxIdle\", \"30\");\n        properties.put(\"maxWait\", \"10000\");\n        properties.put(\"url\", \"jdbc:mock:\");\n        properties.put(\"filters\", \"stat\");\n        properties.put(\"validationQuery\", \"SELECT 1\");\n        DruidDataSource dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n        JMXUtils.register(\"com.alibaba.druid:type=DruidDataSource\", dataSource);\n\n        final int COUNT = 10;\n\n        assertEquals(0, dataSource.getCreateCount());\n        assertEquals(0, dataSource.getDestroyCount());\n        assertEquals(0, dataSource.getPoolingCount());\n\n        Connection[] connections = new Connection[COUNT];\n        for (int i = 0; i < COUNT; ++i) {\n            connections[i] = dataSource.getConnection();\n        }\n\n        for (int i = 0; i < COUNT; ++i) {\n            connections[i].close();\n        }\n\n        assertEquals(0, dataSource.getDestroyCount());\n\n        dataSource.close();\n        assertEquals(dataSource.getCreateCount(), dataSource.getDestroyCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/Case3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Case3 extends PoolTestCase {\n    // public void test_0() throws Exception {\n    // DruidDataSource dataSource = new DruidDataSource();\n    // dataSource.setUrl(\"jdbc:mock:xxx\");\n    // dataSource.setPoolPreparedStatements(true);\n    // dataSource.close();\n    // }\n    //\n    // public void test_1() throws Exception {\n    // DruidDataSource dataSource = new DruidDataSource();\n    // dataSource.setUrl(\"jdbc:mock:xxx\");\n    //\n    // Connection conn = dataSource.getConnection();\n    // Statement stmt = conn.createStatement();\n    // ResultSet rs = stmt.executeQuery(\"SELECT 1\");\n    // rs.next();\n    //\n    // conn.close();\n    //\n    // assertEquals(true, stmt.isClosed());\n    // assertEquals(true, rs.isClosed());\n    //\n    // rs.close();\n    // stmt.close();\n    //\n    // dataSource.close();\n    // }\n\n    public void test_2() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        String sql = \"SELECT 1\";\n\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        Statement mockStmt = stmt.unwrap(Statement.class);\n        assertEquals(false, mockStmt.isClosed());\n\n        conn.close();\n\n        assertEquals(true, mockStmt.isClosed());\n\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        rs.close();\n        stmt.close();\n\n        SQLException error = null;\n        try {\n            stmt.execute(\"SELECT 1\");\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ClosedTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DataSourceClosedException;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ClosedTest extends PoolTestCase {\n    public void test_close() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        dataSource.close();\n\n        DataSourceClosedException error = null;\n\n        try {\n            dataSource.getConnection();\n        } catch (DataSourceClosedException ex) {\n            error = ex;\n        }\n\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigErrorTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(true);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connect() throws Exception {\n        Field field = DruidDataSource.class.getDeclaredField(\"LOG\");\n        field.setAccessible(true);\n        Log LOG = (Log) field.get(null);\n\n        LOG.resetStat();\n\n        assertEquals(0, LOG.getErrorCount());\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        assertEquals(1, LOG.getErrorCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigErrorTest2 extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:wrap-jdbc:jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setTestOnReturn(false);\n        dataSource.setTestWhileIdle(false);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connect() throws Exception {\n        Field field = DruidDataSource.class.getDeclaredField(\"LOG\");\n        field.setAccessible(true);\n        Log LOG = (Log) field.get(null);\n\n        LOG.resetStat();\n\n        assertEquals(0, LOG.getErrorCount());\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        assertTrue(LOG.getErrorCount() >= 1);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigErrorTest3 extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mysql:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setTestOnReturn(false);\n        dataSource.setTestWhileIdle(false);\n        dataSource.setInitialSize(0);\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connect() throws Exception {\n        Field field = DruidDataSource.class.getDeclaredField(\"LOG\");\n        field.setAccessible(true);\n        Log LOG = (Log) field.get(null);\n\n        LOG.resetStat();\n\n        assertEquals(0, LOG.getErrorCount());\n        dataSource.init();\n        assertEquals(0, LOG.getErrorCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTestMysql.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConfigErrorTestMysql extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mysql:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(0);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        super.tearDown();\n    }\n\n    public void test_success() throws Exception {\n        dataSource.setTestWhileIdle(true);\n\n        Field field = DruidDataSource.class.getDeclaredField(\"LOG\");\n        dataSource.setValidationQuery(\"select 1\");\n        field.setAccessible(true);\n        Log LOG = (Log) field.get(null);\n\n        LOG.resetStat();\n\n        assertEquals(0, LOG.getWarnCount());\n        dataSource.init();\n        assertEquals(0, LOG.getWarnCount());\n    }\n\n    public void test_warn() throws Exception {\n        dataSource.setTestWhileIdle(false);\n\n        Field field = DruidDataSource.class.getDeclaredField(\"LOG\");\n        field.setAccessible(true);\n        Log LOG = (Log) field.get(null);\n\n        LOG.resetStat();\n\n        assertEquals(0, LOG.getWarnCount());\n        dataSource.init();\n        assertEquals(0, LOG.getWarnCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/CreateSchedulerTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CreateSchedulerTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n    private ScheduledExecutorService createScheduler;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        createScheduler = Executors.newScheduledThreadPool(1);\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDestroyScheduler(createScheduler);\n        dataSource.setMinEvictableIdleTimeMillis(10);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        createScheduler.shutdown();\n\n        super.tearDown();\n    }\n\n    public void test_connectAndClose() throws Exception {\n        Connection[] connections = new Connection[8];\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i] = dataSource.getConnection();\n        }\n\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i].close();\n        }\n\n        Thread.sleep(100);\n        assertEquals(0, dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/CreateSchedulerTest_directCreate.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\n\npublic class CreateSchedulerTest_directCreate extends PoolTestCase {\n    private DruidDataSource[] dataSources;\n    private ScheduledExecutorService createScheduler;\n    private ScheduledExecutorService destroyScheduler;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        createScheduler = Executors.newScheduledThreadPool(1);\n        destroyScheduler = Executors.newScheduledThreadPool(1);\n\n        dataSources = new DruidDataSource[8];\n        for (int i = 0; i < dataSources.length; ++i) {\n            DruidDataSource dataSource = new DruidDataSource();\n            dataSource.setUrl(\"jdbc:mock:xxx\");\n            dataSource.setDriver(new SlowDriver());\n            dataSource.setCreateScheduler(createScheduler);\n            dataSource.setDestroyScheduler(destroyScheduler);\n            dataSource.setMinEvictableIdleTimeMillis(10);\n            dataSource.setTimeBetweenEvictionRunsMillis(10);\n            dataSource.setFilters(\"log4j\");\n            dataSource.setName(\"ds_\" + i);\n\n            dataSources[i] = dataSource;\n        }\n    }\n\n    protected void tearDown() throws Exception {\n        for (int i = 0; i < dataSources.length; ++i) {\n            JdbcUtils.close(dataSources[i]);\n        }\n\n        createScheduler.shutdown();\n\n        super.tearDown();\n    }\n\n    public void test_connectAndClose() throws Exception {\n        Thread[] threads = new Thread[32];\n        final CountDownLatch latch = new CountDownLatch(threads.length);\n        for (int i = 0; i < threads.length; ++i) {\n            final int threadId = i;\n            int dataSourceIndex = i % dataSources.length;\n            final DruidDataSource dataSource = dataSources[dataSourceIndex];\n            Thread thread = new Thread(new Task(dataSource, latch), \"thread-\" + threadId);\n            threads[i] = thread;\n        }\n\n        for (int i = 0; i < threads.length; ++i) {\n            threads[i].start();\n            Thread.sleep(10);\n        }\n\n        latch.await();\n    }\n\n    public static class SlowDriver extends MockDriver {\n        public MockConnection createMockConnection(MockDriver driver, String url, Properties connectProperties) {\n            try {\n                Thread.sleep(1000 * 1);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n            return super.createMockConnection(driver, url, connectProperties);\n        }\n    }\n\n    public static class Task implements Runnable {\n        private final DruidDataSource dataSource;\n        private final CountDownLatch latch;\n\n        public Task(DruidDataSource dataSource, CountDownLatch latch) {\n            this.dataSource = dataSource;\n            this.latch = latch;\n        }\n\n        @Override\n        public void run() {\n            try {\n                for (int i = 0; i < 4; ++i) {\n                    Connection conn = null;\n                    try {\n                        conn = dataSource.getConnection();\n                    } catch (SQLException e) {\n                        e.printStackTrace();\n                    } finally {\n                        JdbcUtils.close(conn);\n                    }\n                }\n            } finally {\n                latch.countDown();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DataSourceDisableExceptionTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DataSourceDisableException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DataSourceDisableExceptionTest extends PoolTestCase {\n    public void test_0() throws Exception {\n        DataSourceDisableException ex = new DataSourceDisableException();\n        assertEquals(null, ex.getMessage());\n    }\n\n    public void test_1() throws Exception {\n        DataSourceDisableException ex = new DataSourceDisableException(\"XXX\");\n        assertEquals(\"XXX\", ex.getMessage());\n    }\n\n    public void test_2() throws Exception {\n        DataSourceDisableException ex = new DataSourceDisableException(new IllegalStateException());\n        assertTrue(ex.getCause() instanceof IllegalStateException);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DestorySchedulerTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DestorySchedulerTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n    private ScheduledExecutorService destroyScheduler;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        destroyScheduler = Executors.newScheduledThreadPool(1);\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDestroyScheduler(destroyScheduler);\n        dataSource.setMinEvictableIdleTimeMillis(10);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        destroyScheduler.shutdown();\n\n        super.tearDown();\n    }\n\n    public void test_connectAndClose() throws Exception {\n        Connection[] connections = new Connection[8];\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i] = dataSource.getConnection();\n        }\n\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i].close();\n        }\n\n        Thread.sleep(100);\n        assertEquals(0, dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidConnectionHolderTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.mysql.jdbc.Driver;\n\nimport java.sql.SQLException;\n\npublic class DruidConnectionHolderTest extends PoolTestCase {\n    Driver driver;\n    private DruidDataSource dataSource;\n\n    private Class exceptionClass;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        driver = new Driver();\n\n        if (driver.getMajorVersion() == 5) {\n            exceptionClass = Class.forName(\"com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException\");\n\n            dataSource = new DruidDataSource();\n            dataSource.setUrl(\"jdbc:mock:xxx\");\n            dataSource.setTestOnBorrow(false);\n            dataSource.setInitialSize(1);\n            dataSource.getProxyFilters().add(new FilterAdapter() {\n                public int connection_getTransactionIsolation(FilterChain chain, ConnectionProxy connection)\n                        throws SQLException {\n                    throw createSyntaxException();\n                }\n            });\n        }\n    }\n\n    protected SQLException createSyntaxException() {\n        try {\n            return (SQLException) exceptionClass.newInstance();\n        } catch (Exception e) {\n            throw new IllegalStateException();\n        }\n    }\n\n    protected void tearDown() throws Exception {\n        if (dataSource != null) {\n            dataSource.close();\n        }\n\n        super.tearDown();\n    }\n\n    public void test_mysqlSyntaxError() throws Exception {\n        if (driver.getMajorVersion() == 5) {\n            dataSource.init();\n\n            dataSource.getConnection();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidConnectionHolderTest2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.GetConnectionTimeoutException;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidConnectionHolderTest2 extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public int connection_getTransactionIsolation(FilterChain chain, ConnectionProxy connection)\n                    throws SQLException {\n                throw new SQLException();\n            }\n        });\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_mysqlSyntaxError() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.getConnection(100);\n        } catch (GetConnectionTimeoutException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidConnectionHolderTest3.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.GetConnectionTimeoutException;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidConnectionHolderTest3 extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public int connection_getTransactionIsolation(FilterChain chain, ConnectionProxy connection)\n                    throws SQLException {\n                throw new MySQLException();\n            }\n        });\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_mysqlSyntaxError() throws Exception {\n        {\n            Exception error = null;\n            try {\n                dataSource.init();\n            } catch (MySQLException e) {\n                error = e;\n            }\n            assertNotNull(error);\n        }\n\n        assertEquals(0, dataSource.getPoolingCount());\n\n        Exception error = null;\n        try {\n            dataSource.getConnection(100);\n        } catch (GetConnectionTimeoutException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    public static class MySQLException extends SQLException {\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidConnectionHolderTest4.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidConnectionHolder;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\n\nimport java.lang.reflect.Field;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidConnectionHolderTest4 extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_toString() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection();\n\n        DruidConnectionHolder holder = conn.getConnectionHolder();\n\n        Field field = DruidConnectionHolder.class.getDeclaredField(\"statementPool\");\n        field.setAccessible(true);\n        assertNull(field.get(holder));\n\n        holder.toString();\n\n        assertNull(field.get(holder));\n\n        holder.getStatementPool();\n\n        assertNotNull(field.get(holder));\n\n        holder.toString();\n\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n        stmt.execute();\n        stmt.close();\n\n        conn.close();\n\n        assertEquals(1, holder.getStatementPool().size());\n\n        holder.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceAsyncCloseTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnectionClosedException;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class DruidDataSourceAsyncCloseTest {\n    protected DruidDataSource dataSource;\n    protected ExecutorService executor;\n\n    @BeforeEach\n    public void setUp() {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        executor = Executors.newFixedThreadPool(2);\n    }\n\n    @AfterEach\n    public void tearDown() {\n        JdbcUtils.close(dataSource);\n        executor.shutdownNow();\n    }\n\n    @Test\n    public void test() throws Exception {\n        int count = 1024 * 16;\n        final CountDownLatch latch = new CountDownLatch(count);\n\n        for (int i = 0; i < count; i++) {\n            DruidPooledConnection connection = dataSource.getConnection();\n            Runnable task = () -> {\n                try {\n                    SQLException ex = new MockConnectionClosedException();\n                    connection.handleException(ex);\n                } catch (SQLException ignored) {\n                    // ignored\n                } finally {\n                    JdbcUtils.close(connection);\n                    latch.countDown();\n                }\n            };\n            executor.submit(task);\n        }\n        latch.await();\n\n        assertEquals(0, dataSource.getActiveCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceC3P0AdapterTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSourceC3P0Adapter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLFeatureNotSupportedException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceC3P0AdapterTest {\n    private DruidDataSourceC3P0Adapter dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSourceC3P0Adapter();\n        dataSource.setJdbcUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialPoolSize(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn_1() throws Exception {\n        Connection conn = dataSource.getConnection(null, null);\n        conn.close();\n    }\n\n    @Test\n    public void test_getDriverClass() throws Exception {\n        assertNull(dataSource.getDriverClass());\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        assertEquals(MockDriver.class.getName(), dataSource.getDriverClass());\n        assertEquals(MockDriver.instance, dataSource.getDriver());\n    }\n\n    @Test\n    public void test_getJdbcUrl() throws Exception {\n        assertEquals(\"jdbc:mock:xxx\", dataSource.getJdbcUrl());\n    }\n\n    @Test\n    public void test_getParentLogger_err() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.getParentLogger();\n        } catch (SQLFeatureNotSupportedException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_propertyCycle() throws Exception {\n        dataSource.setPropertyCycle(3);\n        assertEquals(3, dataSource.getPropertyCycle());\n    }\n\n    @Test\n    public void test_acquireIncrement() throws Exception {\n        dataSource.setAcquireIncrement(4);\n        assertEquals(4, dataSource.getAcquireIncrement());\n    }\n\n    @Test\n    public void test_overrideDefaultPassword() throws Exception {\n        dataSource.setOverrideDefaultPassword(\"x2\");\n        assertEquals(\"x2\", dataSource.getOverrideDefaultPassword());\n    }\n\n    @Test\n    public void test_overrideDefaultUser() throws Exception {\n        dataSource.setOverrideDefaultUser(\"x1\");\n        assertEquals(\"x1\", dataSource.getOverrideDefaultUser());\n    }\n\n    @Test\n    public void test_factoryClassLocation() throws Exception {\n        dataSource.setFactoryClassLocation(\"x3\");\n        assertEquals(\"x3\", dataSource.getFactoryClassLocation());\n    }\n\n    @Test\n    public void test_maxConnectionAge() throws Exception {\n        dataSource.setMaxConnectionAge(123);\n        assertEquals(123, dataSource.getMaxConnectionAge());\n    }\n\n    @Test\n    public void test_connectionCustomizerClassName() throws Exception {\n        dataSource.setConnectionCustomizerClassName(\"x4\");\n        assertEquals(\"x4\", dataSource.getConnectionCustomizerClassName());\n    }\n\n    @Test\n    public void test_maxIdleTimeExcessConnections() throws Exception {\n        dataSource.setMaxIdleTimeExcessConnections(101);\n        assertEquals(101, dataSource.getMaxIdleTimeExcessConnections());\n    }\n\n    @Test\n    public void test_maxAdministrativeTaskTime() throws Exception {\n        dataSource.setMaxAdministrativeTaskTime(102);\n        assertEquals(102, dataSource.getMaxAdministrativeTaskTime());\n    }\n\n    @Test\n    public void test_userOverridesAsString() throws Exception {\n        dataSource.setUserOverridesAsString(\"x5\");\n        assertEquals(\"x5\", dataSource.getUserOverridesAsString());\n    }\n\n    @Test\n    public void test_usesTraditionalReflectiveProxies() throws Exception {\n        dataSource.setUsesTraditionalReflectiveProxies(true);\n        assertEquals(true, dataSource.isUsesTraditionalReflectiveProxies());\n    }\n\n    @Test\n    public void test_forceIgnoreUnresolvedTransactions() throws Exception {\n        dataSource.setForceIgnoreUnresolvedTransactions(true);\n        assertEquals(true, dataSource.isForceIgnoreUnresolvedTransactions());\n    }\n\n    @Test\n    public void test_automaticTestTable() throws Exception {\n        dataSource.setAutomaticTestTable(\"x6\");\n        assertEquals(\"x6\", dataSource.getAutomaticTestTable());\n    }\n\n    @Test\n    public void test_connectionTesterClassName() throws Exception {\n        dataSource.setConnectionTesterClassName(\"x6\");\n        assertEquals(\"x6\", dataSource.getConnectionTesterClassName());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceConverterTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.osjava.sj.SimpleContext;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceConverterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        String osName = System.getProperty(\"os.name\");\n\n        String root = DruidDataSourceConverterTest.class\n                .getResource(\"/com/alibaba/druid/pool/simplejndi/\").toString();\n        if (root.startsWith(\"file:/\")) {\n            root = root.substring(\"file://\".length() - 1);\n        }\n\n        if (osName.toLowerCase().indexOf(\"win\") == -1) {\n            root = \"/\" + root;\n        }\n        Properties props = new Properties();\n        props.put(\"org.osjava.sj.root\", root);\n        props.put(\"java.naming.factory.initial\",\n                \"org.osjava.sj.SimpleContextFactory\");\n        props.put(\"org.osjava.sj.delimiter\", \"/\");\n        javax.naming.Context ctx = new SimpleContext(props);\n        dataSource = (DruidDataSource) ctx.lookup(\"jdbc/druidTest\");\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn() throws Exception {\n        assertEquals(true, dataSource.isInited());\n        Connection conn = dataSource.getConnection();\n        assertEquals(1, dataSource.getActiveCount());\n        conn.close();\n        assertEquals(0, dataSource.getActiveCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceDecryptTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * @author Jonas Yang\n */\npublic class DruidDataSourceDecryptTest {\n    @Test\n    public void testDecrypt() throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:oracle:thin:@\");\n        dataSource.setUsername(\"xiaoyu\");\n        dataSource.setPassword(\"OJfUm6WCHi7EuXqE6aEc+Po2xFrAGBeSNy8O2jWhV2FTG8/5kbRRr2rjNKhptlevm/03Y0048P7h88gdUOXAYg==\");\n        dataSource.setFilters(\"config\");\n        dataSource.setConnectionProperties(\"config.decrypt=true\");\n\n        try {\n            dataSource.init();\n            assertEquals(\"xiaoyu\", dataSource.getPassword(), \"The password is \" + dataSource.getPassword());\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceFactoryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.naming.Reference;\nimport javax.naming.StringRefAddr;\nimport javax.sql.DataSource;\n\nimport java.util.Hashtable;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceFactoryTest {\n    private DruidDataSource dataSource;\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_factory() throws Exception {\n        DruidDataSourceFactory factory = new DruidDataSourceFactory();\n\n        Reference ref = new Reference(DataSource.class.getName());\n        ref.add(new StringRefAddr(DruidDataSourceFactory.PROP_REMOVEABANDONED, \"true\"));\n        ref.add(new StringRefAddr(DruidDataSourceFactory.PROP_MAXACTIVE, \"20\"));\n\n        ref.add(new StringRefAddr(DruidDataSourceFactory.PROP_SOCKET_TIMEOUT, \"30000\"));\n\n        ref.add(new StringRefAddr(DruidDataSourceFactory.PROP_CONNECT_TIMEOUT, \"15000\"));\n\n        Hashtable<String, String> env = new Hashtable<String, String>();\n\n        dataSource = (DruidDataSource) factory.getObjectInstance(ref, null, null, env);\n\n        assertTrue(dataSource.isRemoveAbandoned());\n        assertEquals(20, dataSource.getMaxActive());\n        assertEquals(30000, dataSource.getSocketTimeout());\n        assertEquals(15000, dataSource.getConnectTimeout());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceFactoryTest0.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceFactoryTest0 {\n    @Test\n    public void test_factory_null() throws Exception {\n        DruidDataSourceFactory factory = new DruidDataSourceFactory();\n        assertNull(factory.getObjectInstance(null, null, null, null));\n    }\n\n    @Test\n    public void test_factory_null_1() throws Exception {\n        DruidDataSourceFactory factory = new DruidDataSourceFactory();\n        assertNull(factory.getObjectInstance(new Object(), null, null, null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceFactoryTest1.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceFactoryTest1 {\n    @Test\n    public void test_NONE() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_DEFAULTTRANSACTIONISOLATION, \"NONE\");\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertEquals(Connection.TRANSACTION_NONE, dataSource.getDefaultTransactionIsolation().intValue());\n\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_READ_COMMITTED() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_DEFAULTTRANSACTIONISOLATION, \"READ_COMMITTED\");\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertEquals(Connection.TRANSACTION_READ_COMMITTED,\n                    dataSource.getDefaultTransactionIsolation().intValue());\n\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_READ_UNCOMMITTED() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_DEFAULTTRANSACTIONISOLATION, \"READ_UNCOMMITTED\");\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED,\n                    dataSource.getDefaultTransactionIsolation().intValue());\n\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_REPEATABLE_READ() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_DEFAULTTRANSACTIONISOLATION, \"REPEATABLE_READ\");\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertEquals(Connection.TRANSACTION_REPEATABLE_READ,\n                    dataSource.getDefaultTransactionIsolation().intValue());\n\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_SERIALIZABLE() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_DEFAULTTRANSACTIONISOLATION, \"SERIALIZABLE\");\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertEquals(Connection.TRANSACTION_SERIALIZABLE,\n                    dataSource.getDefaultTransactionIsolation().intValue());\n\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_other() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_DEFAULTTRANSACTIONISOLATION, \"xxx\");\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertEquals(-1, dataSource.getDefaultTransactionIsolation().intValue());\n\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_integer() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_DEFAULTTRANSACTIONISOLATION,\n                Integer.toString(Connection.TRANSACTION_SERIALIZABLE));\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertEquals(Connection.TRANSACTION_SERIALIZABLE,\n                    dataSource.getDefaultTransactionIsolation().intValue());\n\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_init() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_INIT, \"true\");\n\n        DruidDataSource dataSource = null;\n\n        try {\n            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n            assertEquals(\"jdbc:mock:xxx\", dataSource.getUrl());\n            assertTrue(dataSource.isInited());\n        } finally {\n            JdbcUtils.close(dataSource);\n        }\n    }\n\n    @Test\n    public void test_getObjectInstance() throws Exception {\n        assertNull(new DruidDataSourceFactory().getObjectInstance(null, null, null, null));\n    }\n\n    @Test\n    public void test_getObjectInstance_1() throws Exception {\n        assertNull(new DruidDataSourceFactory().getObjectInstance(new Object(), null, null, null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceFactoryTest2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceFactoryTest2 {\n    private DruidDataSource dataSource;\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_factory() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_POOLPREPAREDSTATEMENTS, \"false\");\n        properties.put(DruidDataSourceFactory.PROP_MAXOPENPREPAREDSTATEMENTS, \"100\");\n\n        dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n\n        assertFalse(dataSource.isPoolPreparedStatements());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceFilterTest {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_filter() throws Exception {\n        System.out.println(System.nanoTime() / (1000 * 1000));\n        DruidDataSource dataSource = new DruidDataSource();\n\n        assertEquals(0, dataSource.getProxyFilters().size());\n\n        dataSource.setFilters(\"stat\");\n\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        dataSource.close();\n    }\n\n    @Test\n    public void test_filter_3() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n\n        assertEquals(0, dataSource.getProxyFilters().size());\n\n        dataSource.setFilters(\"stat\");\n         JdbcStatManager.getInstance().reset();\n         dataSource.init();\n        JdbcDataSourceStat dataSourceStat = dataSource.getDataSourceStat();\n//        assertEquals(1, JdbcStatManager.getInstance().getDataSources().size());\n//        JdbcDataSourceStat dataSourceStat = JdbcStatManager.getInstance().getDataSources().values().iterator().next();\n\n        assertEquals(0, dataSourceStat.getConnectionStat().getConnectCount());\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        for (int i = 0; i < 2; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(1, dataSourceStat.getConnectionStat().getConnectCount());\n            assertEquals(0, dataSourceStat.getConnectionStat().getCloseCount());\n\n            conn.close();\n\n            assertEquals(1, dataSourceStat.getConnectionStat().getConnectCount());\n            assertEquals(0, dataSourceStat.getConnectionStat().getCloseCount()); // logic\n            // close不会导致计数器＋1\n        }\n\n        assertEquals(1, DruidDataSourceStatManager.getInstance().getDataSourceList().size());\n\n        dataSource.close();\n\n        assertEquals(1, dataSourceStat.getConnectionStat().getConnectCount());\n        assertEquals(1, dataSourceStat.getConnectionStat().getCloseCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceShrinkTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class DruidDataSourceShrinkTest {\n    protected DruidDataSource dataSource;\n    protected ExecutorService executor;\n\n    @BeforeEach\n    public void setUp() {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMinIdle(1);\n\n        executor = Executors.newFixedThreadPool(2);\n    }\n\n    @AfterEach\n    public void tearDown() {\n        JdbcUtils.close(dataSource);\n        executor.shutdownNow();\n    }\n\n    @Test\n    public void test() throws Exception {\n        for (int i = 0; i < 100; i++) {\n            dataSource.fill();\n            assertEquals(8, dataSource.getPoolingCount());\n            dataSource.shrink(false, false);\n            assertEquals(dataSource.getMinIdle(), dataSource.getPoolingCount());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_getInitStackTrace() {\n        String stackTrace = dataSource.getInitStackTrace();\n        assertTrue(stackTrace.indexOf(\"com.alibaba.druid.bvt.pool.DruidDataSourceTest.setUp\") != -1);\n    }\n\n    @Test\n    public void test_restart() throws Exception {\n        assertEquals(true, dataSource.isInited());\n        {\n            Connection conn = dataSource.getConnection();\n            assertEquals(1, dataSource.getActiveCount());\n\n            Exception error = null;\n            try {\n                dataSource.restart();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n            assertEquals(true, dataSource.isInited());\n\n            conn.close();\n            dataSource.restart();\n        }\n\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(false, dataSource.isInited());\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest1.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        dataSource.setOracle(true);\n\n        dataSource.init();\n\n        Exception error = null;\n        try {\n            dataSource.setOracle(false);\n        } catch (IllegalStateException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_transactionQueryTimeout() throws Exception {\n        dataSource.setTransactionQueryTimeout(123456);\n\n        assertEquals(123456, dataSource.getTransactionQueryTimeout());\n    }\n\n    @Test\n    public void test_dupCloseLogEnable() throws Exception {\n        assertFalse(dataSource.isDupCloseLogEnable());\n\n        dataSource.setDupCloseLogEnable(true);\n\n        assertTrue(dataSource.isDupCloseLogEnable());\n    }\n\n    @Test\n    public void test_getClosedPreparedStatementCount() throws Exception {\n        assertEquals(0, dataSource.getClosedPreparedStatementCount());\n        assertEquals(0, dataSource.getPreparedStatementCount());\n\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n        stmt.close();\n\n        assertEquals(1, dataSource.getPreparedStatementCount());\n        assertEquals(1, dataSource.getClosedPreparedStatementCount());\n    }\n\n    @Test\n    public void test_getDriverMajorVersion() throws Exception {\n        assertEquals(-1, dataSource.getDriverMajorVersion());\n        dataSource.init();\n        assertEquals(0, dataSource.getDriverMajorVersion());\n    }\n\n    @Test\n    public void test_getDriverMinorVersion() throws Exception {\n        assertEquals(-1, dataSource.getDriverMinorVersion());\n        dataSource.init();\n        assertEquals(0, dataSource.getDriverMinorVersion());\n    }\n\n    @Test\n    public void test_getExceptionSorterClassName() throws Exception {\n        assertNull(dataSource.getExceptionSorterClassName());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest10.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class DruidDataSourceTest10 {\n    DruidDataSource ds;\n\n    @BeforeEach\n    public void setup() {\n        ds = new DruidDataSource();\n    }\n\n    @AfterEach\n    public void tearDown() {\n        JdbcUtils.close(ds);\n        ds = null;\n    }\n\n    @Test\n    public void test() throws Exception {\n        ds.setSocketTimeout(10);\n        ds.setConnectTimeout(20);\n\n        DruidDataSource ds1 = (DruidDataSource) ds.clone();\n        assertEquals(ds.getConnectTimeout(), ds1.getConnectTimeout());\n        assertEquals(ds.getSocketTimeout(), ds1.getSocketTimeout());\n    }\n\n    @Test\n    public void test1() throws Exception {\n        ds.setUrl(\"jdbc:mysql://127.0.0.1:3306/xxx?connectTimeout=3000&socketTimeout=6000\");\n        ds.init();\n        assertEquals(3000, ds.getConnectTimeout());\n        assertEquals(6000, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_is_zero() throws Exception {\n        ds.setUrl(\"jdbc:mysql://127.0.0.1:3306/xxx?connectTimeout=0&socketTimeout=0\");\n        ds.init();\n        assertEquals(0, ds.getConnectTimeout());\n        assertEquals(0, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test_timeout_is_zero_default() throws Exception {\n        ds.setUrl(\"jdbc:mysql://127.0.0.1:3306/xxx\");\n        ds.init();\n        assertEquals(0, ds.getConnectTimeout());\n        assertEquals(0, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_is_zero2() throws Exception {\n        ds.setUrl(\"jdbc:mysql://127.0.0.1:3306/xxx\");\n        ds.setConnectTimeout(-1);\n        ds.setSocketTimeout(-1);\n        ds.init();\n        assertEquals(-1, ds.getConnectTimeout());\n        assertEquals(-1, ds.getSocketTimeout());\n    }\n\n    /**\n     * @throws Exception\n     * @see <a href=\"https://github.com/alibaba/druid/issues/5396\">...</a>\n     */\n    @Test\n    public void test_timeout_in_loadbalance() throws Exception {\n        ds.setUrl(\n            \"jdbc:mysql:loadbalance://localhost:3306,localhost:3310/test?connectTimeout=98&socketTimeout=99&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(98, ds.getConnectTimeout());\n        assertEquals(99, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_is_zero_in_loadbalance() throws Exception {\n        ds.setUrl(\n            \"jdbc:mysql:loadbalance://localhost:3306,localhost:3310/test?connectTimeout=0&socketTimeout=0&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(0, ds.getConnectTimeout());\n        assertEquals(0, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_in_replication() throws Exception {\n        ds.setUrl(\n            \"jdbc:mysql:replication://localhost:3306,localhost:3310/test?connectTimeout=0&socketTimeout=0&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(0, ds.getConnectTimeout());\n        assertEquals(0, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_in_mariadb() throws Exception {\n        ds.setUrl(\n            \"jdbc:mariadb://localhost:3306/test?connectTimeout=0&socketTimeout=0&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(0, ds.getConnectTimeout());\n        assertEquals(0, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_in_mariadb_loadbalance() throws Exception {\n        ds.setUrl(\n            \"jdbc:mariadb:loadbalance://localhost:3306,localhost:3310/test?connectTimeout=0&socketTimeout=0&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(0, ds.getConnectTimeout());\n        assertEquals(0, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test_timeout_in_mariadb_replication() throws Exception {\n        ds.setUrl(\n            \"jdbc:mariadb:replication://localhost:3306,localhost:3310/test?connectTimeout=0&socketTimeout=0&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(0, ds.getConnectTimeout());\n        assertEquals(0, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_in_mariadb2() throws Exception {\n        ds.setUrl(\n            \"jdbc:mariadb://localhost:3306/test?connectTimeout=1&socketTimeout=2&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(1, ds.getConnectTimeout());\n        assertEquals(2, ds.getSocketTimeout());\n    }\n    @Test\n    public void test_timeout_in_mariadb_loadbalance2() throws Exception {\n        ds.setUrl(\n            \"jdbc:mariadb:loadbalance://localhost:3306,localhost:3310/test?connectTimeout=3&socketTimeout=4&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(3, ds.getConnectTimeout());\n        assertEquals(4, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test_timeout_in_mariadb_replication2() throws Exception {\n        ds.setUrl(\n            \"jdbc:mariadb:replication://localhost:3306,localhost:3310/test?connectTimeout=5&socketTimeout=6&loadBalanceConnectionGroup=first&ha.enableJMX=true\");\n        ds.init();\n        assertEquals(5, ds.getConnectTimeout());\n        assertEquals(6, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test2() throws Exception {\n        Properties properties = new Properties();\n        properties.put(\"connectTimeout\", \"3000\");\n        properties.put(\"socketTimeout\", \"6000\");\n        ds.setConnectProperties(properties);\n        ds.setUrl(\"jdbc:mysql://127.0.0.1:3306/xxx\");\n        ds.init();\n        assertEquals(3000, ds.getConnectTimeout());\n        assertEquals(6000, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test3() throws Exception {\n        ds.setConnectionProperties(\"connectTimeout=3000;socketTimeout=6000\");\n        ds.setUrl(\"jdbc:mysql://127.0.0.1:3306/xxx\");\n        ds.init();\n        assertEquals(3000, ds.getConnectTimeout());\n        assertEquals(6000, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test4() throws Exception {\n        ds.setConnectionProperties(\"connectTimeout=3000;socketTimeout=6000\");\n        ds.setDriver(MockDriver.instance);\n        ds.init();\n        assertEquals(3000, ds.getConnectTimeout());\n        assertEquals(6000, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test5() throws Exception {\n        ds.setDriver(MockDriver.instance);\n        ds.setUrl(\"jdbc:mock:xxx?connectTimeout=3000&socketTimeout=6000\");\n        ds.init();\n        assertEquals(3000, ds.getConnectTimeout());\n        assertEquals(6000, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test6() throws Exception {\n        ds.setConnectionProperties(\"socketTimeout=6000\");\n        ds.setDriver(MockDriver.instance);\n        ds.init();\n        assertEquals(6000, ds.getSocketTimeout());\n    }\n\n    @Test\n    public void test7() throws Exception {\n        ds.setDriver(MockDriver.instance);\n        ds.setUrl(\"jdbc:mock:xxx?socketTimeout=6000\");\n        ds.init();\n        assertEquals(6000, ds.getSocketTimeout());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setMinIdle(100);\n        dataSource.setMaxActive(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (IllegalArgumentException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest3.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\nimport java.util.concurrent.CountDownLatch;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试并发初始化\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest3 {\n    private DruidDataSource dataSource;\n    private volatile Exception error;\n    private volatile Exception errorB;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                try {\n                    Thread.sleep(Long.MAX_VALUE);\n                } catch (InterruptedException e) {\n                    // skip\n                }\n                return null;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        final CountDownLatch startedLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(1);\n\n        Thread threadA = new Thread(\"A\") {\n            public void run() {\n                try {\n                    startedLatch.countDown();\n                    dataSource.init();\n                } catch (SQLException e) {\n                    error = e;\n                } finally {\n                    endLatch.countDown();\n                }\n            }\n        };\n        threadA.start();\n\n        startedLatch.await();\n\n        Thread.sleep(10);\n\n        assertFalse(dataSource.isInited());\n\n        final CountDownLatch startedLatchB = new CountDownLatch(1);\n        final CountDownLatch endLatchB = new CountDownLatch(1);\n        Thread threadB = new Thread(\"B\") {\n            public void run() {\n                try {\n                    startedLatchB.countDown();\n                    dataSource.init();\n                } catch (SQLException e) {\n                    errorB = e;\n                } finally {\n                    endLatchB.countDown();\n                }\n            }\n        };\n        threadB.start();\n        startedLatchB.await();\n\n        threadB.interrupt();\n        endLatchB.await();\n\n        assertNotNull(errorB);\n        assertTrue(errorB.getCause() instanceof InterruptedException);\n\n        threadA.interrupt();\n\n        endLatch.await();\n        endLatchB.await();\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getCreateErrorCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest4.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ExceptionSorter;\nimport com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest4 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_getTransactionThresholdMillis() {\n        assertEquals(0, dataSource.getTransactionThresholdMillis());\n\n        dataSource.setTransactionThresholdMillis(100);\n\n        assertEquals(100, dataSource.getTransactionThresholdMillis());\n    }\n\n    @Test\n    public void test_getTransactionHistogramRanges() {\n        assertNotNull(dataSource.getTransactionHistogramRanges());\n    }\n\n    @Test\n    public void test_getTransactionHistogramRanges_1() {\n        assertEquals(6, dataSource.getTransactionHistogramRanges().length);\n    }\n\n    @Test\n    public void test_setValidConnectionCheckerClassName() throws Exception {\n        assertNull(dataSource.getValidConnectionChecker());\n        dataSource.setValidConnectionCheckerClassName(MySqlValidConnectionChecker.class.getName());\n        assertNotNull(dataSource.getValidConnectionChecker());\n    }\n\n    @Test\n    public void test_setMinIdle() throws Exception {\n        assertEquals(0, dataSource.getMinIdle());\n        dataSource.init();\n        dataSource.setMinIdle(1);\n        assertEquals(1, dataSource.getMinIdle());\n    }\n\n    @Test\n    public void test_setMinIdle_error() throws Exception {\n        assertEquals(0, dataSource.getMinIdle());\n        dataSource.init();\n        Exception error = null;\n        try {\n            dataSource.setMinIdle(100);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n        assertEquals(0, dataSource.getMinIdle());\n    }\n\n    @Test\n    public void test_setExceptionSorter_error() throws Exception {\n        dataSource.setExceptionSorter(\"xx\");\n    }\n\n    @Test\n    public void test_setExceptionSorter_error2() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.setExceptionSorter(MyExceptionSorter.class.getName());\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_getParentLogger() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.getParentLogger();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    private class MyExceptionSorter implements ExceptionSorter {\n        @Override\n        public boolean isExceptionFatal(SQLException e) {\n            return false;\n        }\n\n        @Override\n        public void configFromProperties(Properties properties) {\n            // TODO Auto-generated method stub\n\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest5.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest5 {\n    private DruidDataSource dataSource;\n\n    private final AtomicBoolean validate = new AtomicBoolean(true);\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        validate.set(true);\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n\n        dataSource.setValidConnectionChecker(new ValidConnectionCheckerAdapter() {\n            @Override\n            public boolean isValidConnection(Connection c, String query, int validationQueryTimeout) {\n                return validate.get();\n            }\n        });\n    }\n\n    public void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testValidate() throws Exception {\n        validate.set(false);\n\n        Exception error = null;\n        try {\n            dataSource.getConnection();\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        validate.set(true);\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n\n    @Test\n    public void testValidate_1() throws Exception {\n        validate.set(false);\n\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        validate.set(true);\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n\n    @Test\n    public void testValidate_3() throws Exception {\n        validate.set(false);\n\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        validate.set(true);\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest6.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.util.DruidPasswordCallback;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.security.auth.callback.NameCallback;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest6 {\n    private DruidDataSource dataSource;\n\n    private final AtomicInteger errorCount = new AtomicInteger();\n    private final AtomicInteger returnEmptyCount = new AtomicInteger();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        returnEmptyCount.set(0);\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(true);\n        dataSource.setInitialSize(1);\n        dataSource.setValidationQuery(\"select 1\");\n        dataSource.setValidationQueryTimeout(10);\n        dataSource.setQueryTimeout(100);\n\n        dataSource.setUserCallback(new NameCallback(\"xx\") {\n        });\n\n        dataSource.setPasswordCallback(new DruidPasswordCallback() {\n            @Override\n            public char[] getPassword() {\n                return \"xx\".toCharArray();\n            }\n        });\n\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)\n                    throws SQLException {\n                if (errorCount.get() > 0) {\n                    errorCount.decrementAndGet();\n                    throw new RuntimeException();\n                }\n\n                if (returnEmptyCount.get() > 0) {\n                    returnEmptyCount.decrementAndGet();\n                    return new ResultSetProxyImpl(statement, new MockResultSet(statement), 0, sql);\n                }\n\n                return chain.statement_executeQuery(statement, sql);\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testValidate() throws Exception {\n        returnEmptyCount.set(1);\n\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (SQLException e) {\n            error = e;\n        }\n        // 'SELECT 1' for connection validation will skip all filters, so error is null.\n        assertNull(error);\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = null;\n            ResultSet rs = null;\n            try {\n                stmt = conn.createStatement();\n                rs = stmt.executeQuery(\"select 1\");\n                // rs.next() should return false as result set is empty.\n                if (!rs.next()) {\n                    throw new SQLException(\"result is empty\");\n                }\n            } catch (SQLException e) {\n                error = e;\n            } finally {\n                JdbcUtils.close(rs);\n                JdbcUtils.close(stmt);\n            }\n            conn.close();\n        }\n        assertNotNull(error);\n\n        {\n            returnEmptyCount.set(1);\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        {\n            returnEmptyCount.set(1);\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        {\n            errorCount.set(1);\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n        assertEquals(100, stmt.getQueryTimeout());\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest7.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest7 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                throw new RuntimeException();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testInitError() throws Exception {\n        assertEquals(0, dataSource.getCreateErrorCount());\n        Throwable error = null;\n        try {\n            dataSource.init();\n        } catch (RuntimeException e) {\n            error = e;\n        }\n        assertNotNull(error);\n        assertTrue(dataSource.getCreateErrorCount() > 0);\n\n        dataSource.getCompositeData();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest8.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest8 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                throw new Error();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testInitError() throws Exception {\n        assertEquals(0, dataSource.getCreateErrorCount());\n        Throwable error = null;\n        try {\n            dataSource.init();\n        } catch (Throwable e) {\n            error = e;\n        }\n        assertNotNull(error);\n        assertTrue(dataSource.getCreateErrorCount() > 0);\n\n        dataSource.getCompositeData();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest9_phyMaxUseCount.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest9_phyMaxUseCount {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialSize(1);\n        dataSource.setPhyMaxUseCount(10);\n\n        assertEquals(10, dataSource.getPhyMaxUseCount());\n\n        Properties properties = new Properties();\n        properties.put(\"druid.phyMaxUseCount\", \"20\");\n        dataSource.configFromPropeties(properties);\n        assertEquals(20, dataSource.getPhyMaxUseCount());\n\n        properties.put(\"druid.phyMaxUseCount\", \"10\");\n        dataSource.configFromPropeties(properties);\n        assertEquals(10, dataSource.getPhyMaxUseCount());\n\n        dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_for_phyMaxUseCount() throws Exception {\n        Connection phyConn = null;\n        for (int i = 0; i < 100; ++i) {\n            DruidPooledConnection conn = dataSource.getConnection();\n            if (i % 10 == 0) {\n                if (conn.getConnection() == phyConn) {\n                    throw new IllegalStateException();\n                }\n            }\n\n            phyConn = conn.getConnection();\n            conn.close();\n//            System.out.println(i);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTestValidConnectionChecker.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ValidConnectionChecker;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * 给对象 {@link DruidDataSource} 已经设置了自定义的 validConnectionChecker的情况下,\n * 使用MySQL等已知的Driver的时候, 会用内置的checker覆盖自定义的checker.\n * 由于测试用例{@link DruidDataSourceTest5}使用的是mock driver, 导致并不能测试自定义checker被修改的问题.\n * 此处单独列出Test Case. 由于需要用到真实的MySQL Driver, 以main函数方式提供测试用例.\n * 如需运行此用例, 请先修改连接信息.\n */\npublic class DruidDataSourceTestValidConnectionChecker {\n    public static void main(String[] args) throws SQLException {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        ValidConnectionChecker checker = new ValidConnectionChecker() {\n            @Override\n            public boolean isValidConnection(Connection c, String query, int validationQueryTimeout) throws Exception {\n                return true;\n            }\n\n            @Override\n            public void configFromProperties(Properties properties) {\n            }\n        };\n\n        // 运行测试用例之前请先修改连接信息.\n        String jdbcUrl = \"jdbc:mysql://localhost:3306/test\";\n        String user = \"test\";\n        String password = \"test\";\n\n        assertTrue(false, \"运行此用例之前请先修改上面的连接信息, 并注释此行\");\n\n        String driverClass = \"com.mysql.jdbc.Driver\";\n\n        dataSource.setUrl(jdbcUrl);\n        dataSource.setUsername(user);\n        dataSource.setPassword(password);\n        dataSource.setDriverClassName(driverClass);\n\n        dataSource.setValidConnectionChecker(checker);\n        assertEquals(checker, dataSource.getValidConnectionChecker());\n\n        dataSource.init();\n\n        // 已经设置了自定义的validConnectionChecker的情况下, 即使加载了MySQL Driver之后checker对象也不应该发生变化.\n        assertEquals(checker, dataSource.getValidConnectionChecker());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_autocommit.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_autocommit {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(true);\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                ConnectionProxy conn = chain.connection_connect(info);\n                conn.setAutoCommit(false);\n                return conn;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertTrue(conn.getAutoCommit());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_autocommit2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_autocommit2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(false);\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                ConnectionProxy conn = chain.connection_connect(info);\n                conn.setAutoCommit(true);\n                return conn;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertFalse(conn.getAutoCommit());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_autocommit3.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_autocommit3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(false);\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                ConnectionProxy conn = chain.connection_connect(info);\n                conn.setAutoCommit(false);\n                return conn;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertFalse(conn.getAutoCommit());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_autocommit4.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_autocommit4 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(true);\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                ConnectionProxy conn = chain.connection_connect(info);\n                conn.setAutoCommit(true);\n                return conn;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertTrue(conn.getAutoCommit());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_clearCache.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_clearCache {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_clearStatementCache() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select 1, 2\");\n            stmt.close();\n            conn.close();\n        }\n        assertEquals(2, dataSource.getCachedPreparedStatementCount());\n\n        dataSource.clearStatementCache();\n\n        assertEquals(0, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_closeError.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_closeError {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public void connection_close(FilterChain chain, ConnectionProxy connection) throws SQLException {\n                throw new SQLException();\n            }\n        });\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_closeError() throws Exception {\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_createError.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试createError\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_createError {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(true);\n        dataSource.setInitialSize(1);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                throw new SQLException();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_enable.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DataSourceDisableException;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_enable {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxWait(1000);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_disable() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n        assertTrue(dataSource.isEnable());\n\n        dataSource.setEnable(false);\n\n        assertFalse(dataSource.isEnable());\n\n        dataSource.shrink();\n\n        Exception error = null;\n        try {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        } catch (DataSourceDisableException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_disable_() throws Exception {\n        dataSource.setEnable(false);\n\n        assertFalse(dataSource.isEnable());\n\n        Exception error = null;\n        try {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        } catch (DataSourceDisableException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_exceptionSorter.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ExceptionSorter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_exceptionSorter {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setDriver(new MockDriver() {\n            public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n                throw new SQLException();\n            }\n        });\n        dataSource.setExceptionSorter(new ExceptionSorter() {\n            @Override\n            public boolean isExceptionFatal(SQLException e) {\n                return true;\n            }\n\n            @Override\n            public void configFromProperties(Properties properties) {\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_event_error() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n            try {\n                stmt.executeQuery();\n            } catch (SQLException e) {\n            }\n\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        long createCount = dataSource.getCreateCount();\n        assertTrue(createCount == 2 || createCount == 3);\n//        long discardCount = dataSource.getDiscardCount();\n//        assertTrue(createCount == discardCount || createCount - 1 == discardCount, \"createCount : \" + createCount + \", discardCount\" + discardCount\n//);\n//        assertEquals(1, dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_exceptionSorter_extend.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.vendor.MySqlExceptionSorter;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverPropertyInfo;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.Properties;\nimport java.util.logging.Logger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试exceptionSorter_extend\n *\n * @author xiaoying [caohongxi001@gmail.com]\n */\npublic class DruidDataSourceTest_exceptionSorter_extend {\n    public static class SubDriver extends com.mysql.jdbc.Driver {\n        /**\n         * Construct a new driver and register it with DriverManager\n         *\n         * @throws SQLException if a database error occurs.\n         */\n        public SubDriver() throws SQLException {\n        }\n    }\n\n    public static class SubDriver1 implements java.sql.Driver {\n        /**\n         * Construct a new driver and register it with DriverManager\n         *\n         * @throws SQLException if a database error occurs.\n         */\n        public SubDriver1() throws SQLException {\n        }\n\n        @Override\n        public Connection connect(String url, Properties info) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public boolean acceptsURL(String url) throws SQLException {\n            return false;\n        }\n\n        @Override\n        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {\n            return new DriverPropertyInfo[0];\n        }\n\n        @Override\n        public int getMajorVersion() {\n            return 0;\n        }\n\n        @Override\n        public int getMinorVersion() {\n            return 0;\n        }\n\n        @Override\n        public boolean jdbcCompliant() {\n            return false;\n        }\n\n        @Override\n        public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n            return null;\n        }\n    }\n\n    /**\n     * 测试继承自com.mysql.jdbc.Driver的子类可以设置sorter\n     *\n     * @throws Exception\n     */\n    @Test\n    public void testExceptionSorter() throws Exception {\n        DruidDataSource dataSource1 = new DruidDataSource();\n        try {\n            dataSource1.setDriverClassName(SubDriver.class.getName());\n            dataSource1.init();\n            assertNotNull(dataSource1.getExceptionSorter());\n            assertEquals(MySqlExceptionSorter.class.getName(), dataSource1.getExceptionSorter().getClass().getName());\n        } finally {\n            JdbcUtils.close(dataSource1);\n        }\n    }\n\n    /**\n     * 测试实现自java.sql.Driver的类未设置sorter\n     *\n     * @throws Exception\n     */\n    @Test\n    public void testExceptionSorterNull() throws Exception {\n        DruidDataSource dataSource1 = new DruidDataSource();\n        try {\n            dataSource1.setDriverClassName(SubDriver1.class.getName());\n            dataSource1.init();\n            assertEquals(null, dataSource1.getExceptionSorter(), \"sorter is not null\");\n        } finally {\n            JdbcUtils.close(dataSource1);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_fill.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_fill {\n    private DruidDataSource dataSource;\n\n    private int maxActive = 10;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMaxActive(maxActive);\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_fill_0() throws Exception {\n        int fillCount = dataSource.fill(3);\n        assertEquals(3, fillCount);\n    }\n\n    @Test\n    public void test_fill_1() throws Exception {\n        int fillCount = dataSource.fill(1000);\n        assertEquals(maxActive, fillCount);\n    }\n\n    @Test\n    public void test_fill_2() throws Exception {\n        int fillCount = dataSource.fill(maxActive);\n        assertEquals(maxActive, fillCount);\n    }\n\n    @Test\n    public void test_fill_3() throws Exception {\n        int fillCount = dataSource.fill();\n        assertEquals(maxActive, fillCount);\n    }\n\n    @Test\n    public void test_fill_5() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.fill(-1);\n        } catch (IllegalArgumentException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_fill2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_fill2 {\n    private DruidDataSource dataSource;\n\n    private int maxActive = 100;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMaxActive(maxActive);\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_fill() throws Exception {\n        final AtomicLong errorCount = new AtomicLong();\n\n        final int THREAD_COUNT = 100;\n        final CountDownLatch startLatch = new CountDownLatch(THREAD_COUNT);\n        final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT);\n        Thread[] threads = new Thread[THREAD_COUNT];\n        for (int i = 0; i < THREAD_COUNT; ++i) {\n            threads[i] = new Thread(\"thread-\" + i) {\n                public void run() {\n                    startLatch.countDown();\n                    try {\n                        Connection conn = dataSource.getConnection();\n                        Thread.sleep(2);\n                        conn.close();\n                    } catch (Exception e) {\n                        errorCount.incrementAndGet();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n            threads[i].start();\n        }\n\n        startLatch.await(1000, TimeUnit.MILLISECONDS);\n\n        final CountDownLatch fillLatch = new CountDownLatch(THREAD_COUNT);\n        final AtomicLong fillErrorCount = new AtomicLong();\n        final AtomicLong fillCount = new AtomicLong();\n        Thread fillThread = new Thread() {\n            public void run() {\n                try {\n                    int count = dataSource.fill();\n                    fillCount.getAndSet(count);\n                } catch (Exception e) {\n                    fillErrorCount.incrementAndGet();\n                } finally {\n                    fillLatch.countDown();\n                }\n            }\n        };\n        fillThread.start();\n\n        fillLatch.await(1000, TimeUnit.MILLISECONDS);\n\n        assertEquals(0, fillErrorCount.get());\n\n        for (int i = 0; i < 100; ++i) {\n            endLatch.await(100, TimeUnit.MILLISECONDS);\n            if (fillCount.get() > 0 || dataSource.isFull()) {\n                break;\n            }\n        }\n        assertTrue(dataSource.isFull(), \"not full\");\n//        assertTrue(fillCount.get() > 0, \"fillCount zero\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_getConnection.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_getConnection {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn_ok() throws Exception {\n        Connection conn = dataSource.getConnection(null, null);\n        conn.close();\n    }\n\n    @Test\n    public void test_conn_user_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.getConnection(\"a\", null);\n        } catch (UnsupportedOperationException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_conn_password_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.getConnection(null, \"a\");\n        } catch (UnsupportedOperationException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_getConnection_2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_getConnection_2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn_ok() throws Exception {\n        {\n            Connection conn = dataSource.getConnection(\"usr1\", \"pwd1\");\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection(\"usr1\", \"pwd1\");\n            conn.close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_getPooledConnection.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockStatementBase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.ConnectionEvent;\nimport javax.sql.ConnectionEventListener;\nimport javax.sql.PooledConnection;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_getPooledConnection {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setDriver(new MockDriver() {\n            public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException {\n                throw new SQLException();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn() throws Exception {\n        PooledConnection conn = dataSource.getPooledConnection();\n        conn.close();\n    }\n\n    @Test\n    public void test_conn_1() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.getPooledConnection(null, null);\n        } catch (UnsupportedOperationException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_event_error() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getPooledConnection();\n\n        final AtomicInteger errorCount = new AtomicInteger();\n        conn.addConnectionEventListener(new ConnectionEventListener() {\n            @Override\n            public void connectionErrorOccurred(ConnectionEvent event) {\n                errorCount.incrementAndGet();\n            }\n\n            @Override\n            public void connectionClosed(ConnectionEvent event) {\n            }\n        });\n\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n        try {\n            stmt.executeQuery();\n        } catch (SQLException e) {\n        }\n\n        assertEquals(1, errorCount.get());\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_getPoolingPeakTime.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_getPoolingPeakTime {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        assertNull(dataSource.getPoolingPeakTime());\n        assertNull(dataSource.getActivePeakTime());\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        assertNotNull(dataSource.getPoolingPeakTime());\n        assertNotNull(dataSource.getActivePeakTime());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_getProperties.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_getProperties {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getConnectProperties().put(\"user\", \"jobs\");\n        dataSource.getConnectProperties().put(\"password\", \"xxx\");\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        assertEquals(-1, dataSource.getProperties().indexOf(\"xxx\"));\n        assertEquals(true, dataSource.getProperties().indexOf(\"******\") != -1);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_initSql.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_initSql {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        List<Object> sqlList = new ArrayList<Object>();\n        sqlList.add(\"select 123\");\n        sqlList.add(null);\n        sqlList.add(\"\");\n\n        dataSource.setConnectionInitSqls(sqlList);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testDefault() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n\n        assertEquals(\"select 123\", mockConn.getLastSql());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_initSql_factory.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_initSql_factory {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Properties properties = new Properties();\n        properties.put(DruidDataSourceFactory.PROP_URL, \"jdbc:mock:xxx\");\n        properties.put(DruidDataSourceFactory.PROP_INITCONNECTIONSQLS, \";;select 123\");\n        dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testDefault() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n\n        assertEquals(\"select 123\", mockConn.getLastSql());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_initSqls.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_initSqls {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialSize(1);\n        dataSource.setDefaultReadOnly(true);\n        dataSource.setDefaultTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);\n        dataSource.setDefaultCatalog(\"c123\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testDefault() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(true, conn.isReadOnly());\n        assertEquals(Connection.TRANSACTION_SERIALIZABLE, conn.getTransactionIsolation());\n        assertEquals(\"c123\", conn.getCatalog());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_interrupt.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_interrupt {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource() {\n            protected void createAndStartCreatorThread() {\n                return;\n            }\n        };\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(true);\n        dataSource.setInitialSize(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(1);\n        final AtomicInteger errorCount = new AtomicInteger();\n        Thread thread = new Thread() {\n            public void run() {\n                try {\n                    startLatch.countDown();\n                    // not wait createConnectionThread latch as it is null: createAndStartCreatorThread method is mocked.\n                    dataSource.init();\n                    Thread.sleep(1000);\n                } catch (Exception e) {\n                    errorCount.incrementAndGet();\n                } finally {\n                    endLatch.countDown();\n                }\n            }\n        };\n        thread.setDaemon(true);\n        thread.start();\n\n        startLatch.await();\n\n        Thread.sleep(10);\n\n        assertEquals(0, errorCount.get());\n\n        thread.interrupt();\n\n        endLatch.await();\n        assertEquals(1, errorCount.get());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_interrupt2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_interrupt2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(true);\n        dataSource.setInitialSize(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        dataSource.getLock().lock();\n\n        try {\n            final CountDownLatch startLatch = new CountDownLatch(1);\n            final CountDownLatch endLatch = new CountDownLatch(1);\n            final AtomicInteger errorCount = new AtomicInteger();\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        startLatch.countDown();\n                        dataSource.getConnection();\n                    } catch (Exception e) {\n                        errorCount.incrementAndGet();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n            thread.setDaemon(true);\n            thread.start();\n\n            startLatch.await();\n\n            Thread.sleep(10);\n\n            assertEquals(0, errorCount.get());\n\n            thread.interrupt();\n\n            endLatch.await();\n            assertEquals(1, errorCount.get());\n        } finally {\n            dataSource.getLock().unlock();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_interrupt3.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_interrupt3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setDefaultAutoCommit(true);\n        dataSource.setMaxActive(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        Connection conn = dataSource.getConnection();\n\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(1);\n        final AtomicInteger errorCount = new AtomicInteger();\n        Thread thread = new Thread() {\n            public void run() {\n                try {\n                    startLatch.countDown();\n                    dataSource.getConnection();\n                } catch (Exception e) {\n                    errorCount.incrementAndGet();\n                } finally {\n                    endLatch.countDown();\n                }\n            }\n        };\n        thread.setDaemon(true);\n        thread.start();\n\n        startLatch.await();\n\n        Thread.sleep(10);\n\n        assertEquals(0, errorCount.get());\n\n        thread.interrupt();\n\n        endLatch.await();\n        assertEquals(1, errorCount.get());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_lastCreateError.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_lastCreateError {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n                throw new SQLException();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        assertNull(dataSource.getLastCreateError());\n        assertNull(dataSource.getLastCreateErrorTime());\n        assertEquals(0, dataSource.getLastCreateErrorTimeMillis());\n\n        Exception error = null;\n        try {\n            dataSource.getConnection(100);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertNotNull(dataSource.getLastCreateError());\n        assertNotNull(dataSource.getLastCreateErrorTime());\n        assertEquals(true, dataSource.getLastCreateErrorTimeMillis() > 0);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_lastError.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_lastError {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public void connection_setAutoCommit(FilterChain chain, ConnectionProxy connection, boolean autoCommit)\n                    throws SQLException {\n                throw new SQLException();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        assertNull(dataSource.getLastError());\n        assertNull(dataSource.getLastErrorTime());\n        assertEquals(0, dataSource.getLastErrorTimeMillis());\n\n        Connection conn = dataSource.getConnection();\n\n        Exception error = null;\n        try {\n            conn.setAutoCommit(false);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertNotNull(dataSource.getLastError());\n        assertNotNull(dataSource.getLastErrorTime());\n        assertEquals(true, dataSource.getLastErrorTimeMillis() > 0);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_loadSysPropertyFilter.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_loadSysPropertyFilter {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:wrap-jdbc:filters=stat,log4j:jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        System.clearProperty(\"druid.filters\");\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        dataSource.init();\n\n        assertEquals(2, dataSource.getProxyFilters().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_maxActive1.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_maxActive1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setInitialSize(3);\n        dataSource.setMaxActive(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (IllegalArgumentException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_maxActive2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试maxActive < 0\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_maxActive2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setMaxActive(-1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (IllegalArgumentException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_maxActive3.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_maxActive3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setMinIdle(100);\n        dataSource.setMaxActive(10);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (IllegalArgumentException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_maxActive4.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_maxActive4 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setMinIdle(4);\n        dataSource.setMaxActive(8);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        dataSource.init();\n        Exception error = null;\n        try {\n            dataSource.setMaxActive(2);\n        } catch (IllegalArgumentException e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_maxWait.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_maxWait {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(1);\n        dataSource.setMaxWait(30);\n        dataSource.setInitialSize(1);\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_maxWait() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        final AtomicInteger errorCount = new AtomicInteger();\n        final CountDownLatch endLatch = new CountDownLatch(2);\n\n        Thread t1 = new Thread(\"t-1\") {\n            public void run() {\n                try {\n                    dataSource.getConnection();\n                } catch (Exception e) {\n                    errorCount.incrementAndGet();\n                } finally {\n                    endLatch.countDown();\n                }\n            }\n        };\n\n        Thread t2 = new Thread(\"t-2\") {\n            public void run() {\n                try {\n                    dataSource.getConnection();\n                } catch (Exception e) {\n                    errorCount.incrementAndGet();\n                } finally {\n                    endLatch.countDown();\n                }\n            }\n        };\n\n        t1.start();\n        t2.start();\n\n        Thread.sleep(10);\n        t1.interrupt();\n\n        endLatch.await();\n\n        assertEquals(2, errorCount.get());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试maxActive < 0\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_notEmptyWait {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setMaxActive(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n            assertEquals(1, dataSource.getNotEmptyWaitCount());\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n            assertEquals(1, dataSource.getNotEmptyWaitCount()); // notEmptyWaitCount没有增长\n        }\n\n        Connection conn = dataSource.getConnection();\n\n        final int THREAD_COUNT = 10;\n        final CountDownLatch startLatch = new CountDownLatch(THREAD_COUNT);\n        final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT);\n        Thread[] threads = new Thread[THREAD_COUNT];\n        for (int i = 0; i < THREAD_COUNT; ++i) {\n            threads[i] = new Thread(\"thread-\" + i) {\n                public void run() {\n                    startLatch.countDown();\n                    try {\n                        Connection conn = dataSource.getConnection();\n                        Thread.sleep(1);\n                        conn.close();\n                    } catch (Exception e) {\n                        //e.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n            threads[i].start();\n        }\n\n        startLatch.await(10, TimeUnit.MILLISECONDS);\n\n        for (int i = 0; i < 100; ++i) {\n            if (dataSource.getNotEmptyWaitThreadCount() == 10) {\n                break;\n            }\n            Thread.sleep(10);\n        }\n\n        assertEquals(10, dataSource.getNotEmptyWaitThreadCount());\n        assertEquals(10, dataSource.getNotEmptyWaitThreadPeak());\n\n        conn.close();\n\n        endLatch.await(100, TimeUnit.MILLISECONDS);\n\n        Thread.sleep(10);\n//        assertEquals(0, dataSource.getNotEmptyWaitThreadCount());\n        assertEquals(10, dataSource.getNotEmptyWaitThreadPeak());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_notEmptyWait2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.time.LocalDateTime;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_notEmptyWait2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(1);\n\n        dataSource.setMaxWaitThreadCount(10);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_maxWaitThread() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        Connection conn = dataSource.getConnection();\n        final AtomicLong errorCount = new AtomicLong();\n\n        final int THREAD_COUNT = 10;\n        final CountDownLatch startLatch = new CountDownLatch(THREAD_COUNT);\n        final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT);\n        Thread[] threads = new Thread[THREAD_COUNT];\n        for (int i = 0; i < THREAD_COUNT; ++i) {\n            threads[i] = new Thread(\"thread-\" + i) {\n                public void run() {\n                    startLatch.countDown();\n                    try {\n                        System.out.println(Thread.currentThread() + \" \" + LocalDateTime.now() + \" begin \");\n                        Connection conn = dataSource.getConnection();\n                        Thread.sleep(2);\n                        System.out.println(Thread.currentThread() + \" \" + LocalDateTime.now() + \" getConnection== \" + conn);\n                        conn.close();\n                    } catch (Exception e) {\n                         e.printStackTrace();\n                        errorCount.incrementAndGet();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n            threads[i].start();\n        }\n\n        startLatch.await(100, TimeUnit.MILLISECONDS);\n\n        final CountDownLatch errorThreadEndLatch = new CountDownLatch(THREAD_COUNT);\n        final AtomicLong maxWaitErrorCount = new AtomicLong();\n        Thread errorThread = new Thread() {\n            public void run() {\n                try {\n                    Connection conn = dataSource.getConnection();\n                    Thread.sleep(1);\n                    conn.close();\n                } catch (Exception e) {\n                    maxWaitErrorCount.incrementAndGet();\n                } finally {\n                    errorThreadEndLatch.countDown();\n                }\n            }\n        };\n        errorThread.start();\n\n        errorThreadEndLatch.await(100, TimeUnit.MILLISECONDS);\n\n        assertEquals(0, maxWaitErrorCount.get()); //因为最大超时没有设置，所以线程一直循环进不到maxWaitErrorCount加1的逻辑了\n        assertTrue(dataSource.getNotEmptySignalCount() > 0);\n\n        conn.close();\n\n        System.out.println(Thread.currentThread() + \" \" + LocalDateTime.now() + \"释放了连接\");\n        endLatch.await(100, TimeUnit.MILLISECONDS);\n        assertEquals(0, errorCount.get());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_oracle.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_oracle {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setDbType(\"oracle\");\n        dataSource.setDriver(new MockDriver() {\n            @Override\n            public int getMajorVersion() {\n                return 11;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        dataSource.init();\n        assertTrue(dataSource.isOracle());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_oracle2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_oracle2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setDbType(\"oracle\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setDriver(new MockDriver() {\n            @Override\n            public int getMajorVersion() {\n                return 10;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        assertNull(dataSource.getConnectProperties().get(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\"));\n        dataSource.init();\n        assertTrue(dataSource.isOracle());\n        assertEquals(\"true\", dataSource.getConnectProperties().get(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\"));\n\n        dataSource.setUseOracleImplicitCache(false);\n        assertNull(dataSource.getConnectProperties().get(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\"));\n\n        dataSource.setUseOracleImplicitCache(true);\n        dataSource.setUseOracleImplicitCache(true);\n        assertEquals(\"true\", dataSource.getConnectProperties().get(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\"));\n\n        dataSource.setUseOracleImplicitCache(false);\n        assertNull(dataSource.getConnectProperties().get(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\"));\n        dataSource.setDriver(null);\n\n        dataSource.setUseOracleImplicitCache(true);\n        assertNull(dataSource.getConnectProperties().get(\"oracle.jdbc.FreeMemoryOnEnterImplicitCache\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_oracle3.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.vendor.OracleValidConnectionChecker;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_oracle3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:oracle:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        dataSource.init();\n        assertTrue(dataSource.isOracle());\n        assertTrue(dataSource.getValidConnectionChecker() instanceof OracleValidConnectionChecker);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_oracle_error.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试minIdle > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_oracle_error {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setDbType(\"oracle\");\n        dataSource.setDriver(new MockDriver() {\n            @Override\n            public int getMajorVersion() {\n                return 9;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.init();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_recycle.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Statement;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_recycle {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_recycle() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection();\n        conn.setAutoCommit(false);\n        conn.setReadOnly(false);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"select 1\");\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_recycle2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_recycle2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public void connection_rollback(FilterChain chain, ConnectionProxy connection) throws SQLException {\n                throw new SQLException();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_recycle() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"select 1\");\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_recycle_error() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection();\n        conn.setAutoCommit(false);\n        conn.setReadOnly(false);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"select 1\");\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n\n        Exception error = null;\n        try {\n            conn.close();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNull(error);\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    public void f_test_recycle_error_interrupt() throws Exception {\n        final AtomicReference<Exception> errorRef = new AtomicReference<Exception>();\n\n        final CountDownLatch closeBeforeLatch = new CountDownLatch(1);\n        final CountDownLatch lockLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(1);\n\n        Thread thread = new Thread() {\n            public void run() {\n                try {\n                    DruidPooledConnection conn = dataSource.getConnection();\n                    conn.setAutoCommit(false);\n                    conn.setReadOnly(false);\n\n                    Statement stmt = conn.createStatement();\n                    stmt.execute(\"select 1\");\n\n                    assertEquals(0, dataSource.getPoolingCount());\n                    assertEquals(1, dataSource.getActiveCount());\n\n                    closeBeforeLatch.countDown();\n                    lockLatch.await();\n\n                    conn.close();\n                } catch (Exception e) {\n                    errorRef.set(e);\n                } finally {\n                    endLatch.countDown();\n                }\n            }\n        };\n        thread.start();\n\n        assertTrue(closeBeforeLatch.await(1, TimeUnit.SECONDS));\n\n        dataSource.getLock().lock();\n        lockLatch.countDown();\n\n        Thread.sleep(10);\n\n        thread.interrupt();\n\n        assertTrue(endLatch.await(1, TimeUnit.MINUTES));\n\n        Exception error = errorRef.get();\n        assertNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_testOnBorrowFailed.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.PooledConnection;\n\nimport java.sql.Connection;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_testOnBorrowFailed {\n    private DruidDataSource dataSource;\n\n    private AtomicInteger validCount = new AtomicInteger();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(true);\n        dataSource.setValidationQuery(\"select 'x'\");\n        dataSource.setValidConnectionChecker(new ValidConnectionCheckerAdapter() {\n            @Override\n            public boolean isValidConnection(Connection c, String query, int validationQueryTimeout) {\n                int count = validCount.getAndIncrement();\n\n                if (count == 0) {\n                    return true;\n                }\n\n                if (count == 1) {\n                    return false;\n                }\n\n                return true;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn() throws Exception {\n        PooledConnection conn = dataSource.getPooledConnection();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n        assertEquals(1, dataSource.getDiscardCount());\n        assertEquals(2, dataSource.getConnectCount());\n        assertEquals(1, dataSource.getCloseCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_testOnWhileIdleFailed.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.sql.PooledConnection;\n\nimport java.sql.Connection;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_testOnWhileIdleFailed {\n    private DruidDataSource dataSource;\n\n    private AtomicInteger validCount = new AtomicInteger();\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTimeBetweenEvictionRunsMillis(20);\n        dataSource.setValidationQuery(\"select 'x'\");\n        dataSource.setValidConnectionChecker(new ValidConnectionCheckerAdapter() {\n            @Override\n            public boolean isValidConnection(Connection c, String query, int validationQueryTimeout) {\n                int count = validCount.getAndIncrement();\n\n                if (count == 0) {\n                    return true;\n                }\n\n                if (count == 1) {\n                    return false;\n                }\n\n                return true;\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn() throws Exception {\n        {\n            PooledConnection conn = dataSource.getPooledConnection();\n            conn.close();\n        }\n\n        assertEquals(1, validCount.get()); // createValidate\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getCreateCount());\n        assertEquals(0, dataSource.getDiscardCount());\n        assertEquals(1, dataSource.getConnectCount());\n        assertEquals(1, dataSource.getCloseCount());\n\n        Thread.sleep(21);\n\n        {\n            PooledConnection conn = dataSource.getPooledConnection();\n            conn.close();\n        }\n\n        assertEquals(3, validCount.get()); // createValidate\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n        assertEquals(1, dataSource.getDiscardCount());\n        assertEquals(3, dataSource.getConnectCount());\n        assertEquals(2, dataSource.getCloseCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_tryGet.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceTest_tryGet {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMaxActive(1);\n        dataSource.setInitialSize(1);\n        dataSource.setTestOnBorrow(false);\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        DruidPooledConnection conn1 = this.dataSource.tryGetConnection();\n        assertNotNull(conn1);\n\n        DruidPooledConnection conn2 = this.dataSource.tryGetConnection();\n        assertNull(conn2);\n\n        conn1.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidDataSourceTest_wrapDriverFilters.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试defaultAutoCommit\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class DruidDataSourceTest_wrapDriverFilters {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        System.setProperty(\"druid.filters\", \"stat,log4j\");\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        System.clearProperty(\"druid.filters\");\n    }\n\n    @Test\n    public void test_autoCommit() throws Exception {\n        dataSource.init();\n\n        assertEquals(2, dataSource.getProxyFilters().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledCallableStatementTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledCallableStatement;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.CallableStatement;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledCallableStatementTest {\n    private DruidDataSource dataSource;\n\n    private boolean throwError = true;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            public boolean callableStatement_wasNull(FilterChain chain, CallableStatementProxy statement)\n                    throws SQLException {\n                if (throwError) {\n                    throw new SQLException();\n                } else {\n                    return chain.callableStatement_wasNull(statement);\n                }\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wasNull_noerror() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select 1\");\n        stmt.execute();\n\n        throwError = false;\n        stmt.wasNull();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_wasNull_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select 1\");\n        stmt.execute();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.wasNull();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        Connection conn = dataSource.getConnection();\n        DruidPooledCallableStatement stmt = (DruidPooledCallableStatement) conn.prepareCall(\"select 1\");\n        stmt.execute();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getObject(1, String.class);\n        } catch (SQLFeatureNotSupportedException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_getObject_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        DruidPooledCallableStatement stmt = (DruidPooledCallableStatement) conn.prepareCall(\"select 1\");\n        stmt.execute();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getObject(\"1\", String.class);\n        } catch (SQLFeatureNotSupportedException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_wrap() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select 1\");\n\n        assertNotNull(stmt.unwrap(CallableStatement.class));\n        assertEquals(MockCallableStatement.class, stmt.unwrap(CallableStatement.class).getClass());\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_wrap_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select 1\");\n\n        assertNotNull(stmt.unwrap(PreparedStatement.class));\n        assertEquals(MockCallableStatement.class, stmt.unwrap(CallableStatement.class).getClass());\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_wrap_2() throws Exception {\n        dataSource.getProxyFilters().clear();\n\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"select 1\");\n\n        assertNotNull(stmt.unwrap(PreparedStatement.class));\n        assertEquals(MockCallableStatement.class, stmt.unwrap(CallableStatement.class).getClass());\n\n        stmt.close();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledConnectionTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Savepoint;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledConnectionTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_rollback() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.rollback();\n\n        Savepoint savepoint = conn.setSavepoint(\"xx\");\n        conn.rollback(savepoint);\n\n        conn.close();\n    }\n\n    @Test\n    public void test_rollback_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.setAutoCommit(false);\n\n        conn.close();\n        conn.rollback();\n        conn.rollback(null);\n    }\n\n    @Test\n    public void test_getOwnerThread() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        assertEquals(Thread.currentThread(), conn.getOwnerThread());\n\n        conn.close();\n    }\n\n    @Test\n    public void test_isDiable() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        assertEquals(false, conn.isDisable());\n\n        conn.close();\n\n        assertEquals(true, conn.isDisable());\n    }\n\n    @Test\n    public void test_dupClose() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        conn.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_disable() throws Exception {\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        conn.disable();\n        assertEquals(true, conn.isDisable());\n\n        assertEquals(1, dataSource.getActiveCount());\n\n        conn.close();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledConnectionTest1.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledConnectionTest1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        conn.close();\n\n        Exception error = null;\n        try {\n            conn.handleException(new RuntimeException());\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_handleException_1() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        Exception error = null;\n        try {\n            conn.handleException(new RuntimeException());\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        conn.close();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_closePoolableStatement() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        DruidPooledPreparedStatement stmt = (DruidPooledPreparedStatement) conn.prepareStatement(\"select 1\");\n        conn.close();\n        conn.closePoolableStatement(stmt);\n    }\n\n    @Test\n    public void test_dup_close() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        conn.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_recycle() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        int defaultIsolation = conn.getTransactionIsolation();\n        conn.setTransactionIsolation(defaultIsolation + 1);\n\n        conn.close();\n        conn.recycle();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        conn = (DruidPooledConnection) dataSource.getConnection();\n        assertEquals(defaultIsolation, conn.getTransactionIsolation());\n        conn.close();\n    }\n\n    @Test\n    public void test_recycle_2() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        int defaultIsolation = conn.getTransactionIsolation();\n        conn.setTransactionIsolation(defaultIsolation + 1);\n\n        conn.recycle();\n        conn.recycle();\n        conn.close();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        conn = (DruidPooledConnection) dataSource.getConnection();\n        assertEquals(defaultIsolation, conn.getTransactionIsolation());\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledConnectionTest2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledConnectionTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setKeepConnectionUnderlyingTransactionIsolation(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_conn() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        conn.close();\n\n        Exception error = null;\n        try {\n            conn.handleException(new RuntimeException());\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_handleException_1() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        Exception error = null;\n        try {\n            conn.handleException(new RuntimeException());\n        } catch (SQLException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        conn.close();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_closePoolableStatement() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        DruidPooledPreparedStatement stmt = (DruidPooledPreparedStatement) conn.prepareStatement(\"select 1\");\n        conn.close();\n        conn.closePoolableStatement(stmt);\n    }\n\n    @Test\n    public void test_dup_close() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        conn.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_recycle() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        int defaultIsolation = conn.getTransactionIsolation();\n        conn.setTransactionIsolation(defaultIsolation + 1);\n\n        conn.close();\n        conn.recycle();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        conn = (DruidPooledConnection) dataSource.getConnection();\n        assertEquals(defaultIsolation + 1, conn.getTransactionIsolation());\n        conn.close();\n    }\n\n    @Test\n    public void test_recycle_2() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        int defaultIsolation = conn.getTransactionIsolation();\n        conn.setTransactionIsolation(defaultIsolation + 1);\n\n        conn.recycle();\n        conn.recycle();\n        conn.close();\n\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        conn = (DruidPooledConnection) dataSource.getConnection();\n        assertEquals(defaultIsolation + 1, conn.getTransactionIsolation());\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledConnectionTest_prepareError.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledConnectionTest_prepareError {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                                      String sql) throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                                      String sql, int autoGeneratedKeys)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                                      String sql, int resultSetType,\n                                                                      int resultSetConcurrency) throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                                      String sql, int resultSetType,\n                                                                      int resultSetConcurrency, int resultSetHoldability)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                                      String sql, int[] columnIndexes)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,\n                                                                      String sql, String[] columnNames)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection,\n                                                                 String sql) throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection,\n                                                                 String sql, int resultSetType, int resultSetConcurrency)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection,\n                                                                 String sql, int resultSetType,\n                                                                 int resultSetConcurrency, int resultSetHoldability)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_prepare_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareStatement(\"select 1\");\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepare_error_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareStatement(\"select 1\", 0, 0);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepare_error_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareStatement(\"select 1\", 0, 0, 0);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepare_error_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareStatement(\"select 1\", 0);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepare_error_4() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareStatement(\"select 1\", new int[0]);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepare_error_5() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareStatement(\"select 1\", new String[0]);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepareCall_error_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareCall(\"select 1\");\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepareCall_error_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareCall(\"select 1\", 0, 0);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n\n    @Test\n    public void test_prepareCall_error_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            conn.prepareCall(\"select 1\", 0, 0, 0);\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledPreparedStatementTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledPreparedStatementTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_hitCount() throws Exception {\n        String sql = \"select ?\";\n        {\n            Connection conn = dataSource.getConnection();\n            DruidPooledPreparedStatement stmt = (DruidPooledPreparedStatement) conn.prepareStatement(sql);\n\n            assertEquals(0, stmt.getFetchSize());\n            assertEquals(0, stmt.getFetchDirection());\n            assertEquals(0, stmt.getMaxRows());\n            assertEquals(0, stmt.getMaxFieldSize());\n            assertEquals(0, stmt.getQueryTimeout());\n            assertEquals(sql, stmt.getSql());\n\n            stmt.setFetchSize(1);\n            stmt.setFetchDirection(2);\n            stmt.setMaxRows(3);\n            stmt.setMaxFieldSize(4);\n            stmt.setQueryTimeout(5);\n\n            assertEquals(1, stmt.getFetchSize());\n            assertEquals(2, stmt.getFetchDirection());\n            assertEquals(3, stmt.getMaxRows());\n            assertEquals(4, stmt.getMaxFieldSize());\n            assertEquals(5, stmt.getQueryTimeout());\n\n            stmt.setString(1, \"xx\");\n            ResultSet rs = stmt.executeQuery();\n            assertTrue(rs.next());\n            assertFalse(rs.next());\n            rs.close();\n            conn.close();\n\n            assertEquals(0, stmt.getHitCount());\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            DruidPooledPreparedStatement stmt = (DruidPooledPreparedStatement) conn.prepareStatement(sql);\n\n            assertEquals(0, stmt.getFetchSize());\n            assertEquals(0, stmt.getFetchDirection());\n            assertEquals(0, stmt.getMaxRows());\n            assertEquals(0, stmt.getMaxFieldSize());\n            assertEquals(0, stmt.getQueryTimeout());\n\n            stmt.setString(1, \"xx\");\n            ResultSet rs = stmt.executeQuery();\n            assertTrue(rs.next());\n            assertFalse(rs.next());\n            rs.close();\n            conn.close();\n\n            assertEquals(1, stmt.getHitCount());\n            assertNotNull(stmt.getKey());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledPreparedStatementTest1.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.ParameterMetaData;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledPreparedStatementTest1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n\n        dataSource.getProxyFilters().add(new FilterAdapter() {\n            @Override\n            public boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public int preparedStatement_executeUpdate(FilterChain chain, PreparedStatementProxy statement)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            public void preparedStatement_clearParameters(FilterChain chain, PreparedStatementProxy statement)\n                    throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public int[] statement_executeBatch(FilterChain chain, StatementProxy statement) throws SQLException {\n                throw new SQLException();\n            }\n\n            @Override\n            public ParameterMetaData preparedStatement_getParameterMetaData(FilterChain chain, PreparedStatementProxy statement)\n                    throws SQLException {\n                throw new SQLException();\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_execute_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.execute();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_executeQuery_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeQuery();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_executeUpdate_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeUpdate();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_clearParameter_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.clearParameters();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_executeBatch_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeBatch();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n\n    @Test\n    public void test_getParameterMetaData_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getParameterMetaData();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledResultSetTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLFeatureNotSupportedException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledResultSetTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testWrap() throws Exception {\n        String sql = \"select ?\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        ResultSet rs = stmt.executeQuery();\n\n        ResultSet raw = rs.unwrap(ResultSet.class);\n\n        assertTrue(raw instanceof MockResultSet);\n\n        rs.close();\n\n        conn.close();\n    }\n\n    @Test\n    public void test_notSupport() throws Exception {\n        String sql = \"select ?\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        DruidPooledResultSet rs = (DruidPooledResultSet) stmt.executeQuery();\n\n        Exception error = null;\n        try {\n            rs.getObject(1, String.class);\n        } catch (SQLFeatureNotSupportedException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        rs.close();\n\n        conn.close();\n    }\n\n    @Test\n    public void test_notSupport_1() throws Exception {\n        String sql = \"select ?\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        DruidPooledResultSet rs = (DruidPooledResultSet) stmt.executeQuery();\n\n        Exception error = null;\n        try {\n            rs.getObject(\"1\", String.class);\n        } catch (SQLFeatureNotSupportedException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        rs.close();\n\n        conn.close();\n    }\n\n    @Test\n    public void test_rowCount() throws Exception {\n        String sql = \"select ?\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        DruidPooledResultSet rs = (DruidPooledResultSet) stmt.executeQuery();\n\n        assertEquals(true, rs.next());\n        assertEquals(false, rs.next());\n\n        assertEquals(1, rs.getFetchRowCount());\n\n        assertEquals(true, rs.previous());\n        assertEquals(false, rs.previous());\n\n        assertEquals(1, rs.getFetchRowCount());\n\n        assertEquals(true, rs.next());\n        assertEquals(false, rs.next());\n\n        assertEquals(1, rs.getFetchRowCount());\n\n        assertFalse(rs.rowUpdated());\n\n        rs.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledResultSetTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledResultSetTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testWrap() throws Exception {\n        String sql = \"select ?\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        ResultSet rs = stmt.executeQuery();\n\n        ResultSet raw = rs.unwrap(ResultSet.class);\n\n        assertTrue(raw instanceof MockResultSet);\n\n        rs.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledStatementTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledStatement;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.sql.SQLWarning;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidPooledStatementTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.getProxyFilters().add(new ErrorFilter());\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_executeQuery_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeQuery(\"select 1\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_executeUpdate_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeUpdate(\"select 1\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_executeUpdate_error_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeUpdate(\"select 1\", Statement.RETURN_GENERATED_KEYS);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_executeUpdate_error_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeUpdate(\"select 1\", new int[0]);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_executeUpdate_error_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeUpdate(\"select 1\", new String[0]);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_execute_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.execute(\"select 1\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_execute_error_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.execute(\"select 1\", Statement.RETURN_GENERATED_KEYS);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_execute_error_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.execute(\"select 1\", new int[0]);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_execute_error_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.execute(\"select 1\", new String[0]);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getMaxFieldSize_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getMaxFieldSize();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_setMaxFieldSize_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.setMaxFieldSize(0);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getMaxRows_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getMaxRows();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_setMaxRows_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.setMaxRows(0);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_setEscapeProcessing_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.setEscapeProcessing(true);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getQueryTimeout_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getQueryTimeout();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_setQueryTimeout_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.setQueryTimeout(-1);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_cancel_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.cancel();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getWarnings_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getWarnings();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_clearWarnings_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.clearWarnings();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_setCursorName_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.setCursorName(null);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getResultSet_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getResultSet();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getDataSourceStat().getResultSetStat().getOpenCount());\n    }\n\n    @Test\n    public void test_getUpdateCount_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getUpdateCount();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getMoreResults_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getMoreResults();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_setFetchDirection_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.setFetchDirection(0);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getFetchDirection_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getFetchDirection();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_setFetchSize_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.setFetchSize(0);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getFetchSize_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getFetchSize();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getResultSetConcurrency_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getResultSetConcurrency();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getResultSetType_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getResultSetType();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_addBatch_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.addBatch(\"select 1\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_clearBatch_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.clearBatch();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_executeBatch_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.executeBatch();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getMoreResults_error_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getMoreResults(0);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getGeneratedKeys_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getGeneratedKeys();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_getResultSetHoldability_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.getResultSetHoldability();\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(1, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_closeOnCompletion_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        DruidPooledStatement stmt = (DruidPooledStatement) conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.closeOnCompletion();\n        } catch (SQLFeatureNotSupportedException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    @Test\n    public void test_isCloseOnCompletion_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        DruidPooledStatement stmt = (DruidPooledStatement) conn.createStatement();\n\n        assertEquals(0, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getErrorCount());\n\n        Exception error = null;\n        try {\n            stmt.isCloseOnCompletion();\n        } catch (SQLFeatureNotSupportedException e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(0, dataSource.getErrorCount());\n\n        stmt.close();\n        conn.close();\n\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n\n    private final class ErrorFilter extends FilterAdapter {\n        @Override\n        public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql,\n                                           int autoGeneratedKeys) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql,\n                                           String[] columnNames) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int[] columnIndexes)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String[] columnNames)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getMaxFieldSize(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getMaxRows(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_setMaxFieldSize(FilterChain chain, StatementProxy statement, int max) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_setMaxRows(FilterChain chain, StatementProxy statement, int max) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_setEscapeProcessing(FilterChain chain, StatementProxy statement, boolean enable)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getQueryTimeout(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_setQueryTimeout(FilterChain chain, StatementProxy statement, int seconds)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_cancel(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public SQLWarning statement_getWarnings(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_clearWarnings(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_setCursorName(FilterChain chain, StatementProxy statement, String name)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getUpdateCount(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public boolean statement_getMoreResults(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_setFetchDirection(FilterChain chain, StatementProxy statement, int value)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getFetchDirection(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getFetchSize(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_setFetchSize(FilterChain chain, StatementProxy statement, int value) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getResultSetConcurrency(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getResultSetType(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public void statement_clearBatch(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int[] statement_executeBatch(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public boolean statement_getMoreResults(FilterChain chain, StatementProxy statement, int current)\n                throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public ResultSetProxy statement_getGeneratedKeys(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n\n        @Override\n        public int statement_getResultSetHoldability(FilterChain chain, StatementProxy statement) throws SQLException {\n            throw new SQLException();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/DumpTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npublic class DumpTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testWrap() throws Exception {\n        String sql = \"select ?\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.close();\n\n        conn.close();\n\n        dataSource.dump();\n    }\n\n    @Test\n    public void testToString() throws Exception {\n        {\n            String sql = \"select ?\";\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.setString(1, \"xxx\");\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n\n            conn.close();\n        }\n\n        String sql = \"select ?, ?\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        stmt.setInt(2, 33);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.close();\n\n        conn.close();\n\n        dataSource.toString();\n    }\n\n    @Test\n    public void test_getPoolingConnectionInfo() throws Exception {\n        String sql = \"select ?, ?\";\n        Connection conn = dataSource.getConnection();\n        Connection conn1 = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        stmt.setInt(2, 33);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.close();\n\n        conn.close();\n        conn1.close();\n\n        List<Map<String, Object>> poolingList = dataSource.getPoolingConnectionInfo();\n        assertEquals(2, poolingList.size());\n    }\n\n    @Test\n    public void test_getStatData() throws Exception {\n        String sql = \"select ?, ?\";\n        Connection conn = dataSource.getConnection();\n        Connection conn1 = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setString(1, \"xxx\");\n        stmt.setInt(2, 33);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        rs.close();\n\n        conn.close();\n        conn1.close();\n\n        Map<String, Object> statData = dataSource.getStatData();\n        assertEquals(2, statData.get(\"PoolingCount\"));\n        assertEquals(2, statData.get(\"PoolingPeak\"));\n        assertEquals(2L, statData.get(\"LogicConnectCount\"));\n        assertEquals(2L, statData.get(\"LogicCloseCount\"));\n        assertEquals(0L, statData.get(\"LogicConnectErrorCount\"));\n\n        assertEquals(1, dataSource.getSqlStatMap().size());\n        JdbcSqlStat sqlStat = dataSource.getSqlStatMap().get(sql);\n        assertNotNull(sqlStat);\n        assertNotNull(dataSource.getSqlStat(sqlStat.getId()));\n        assertNotNull(dataSource.getSqlStat((int) sqlStat.getId()));\n    }\n\n    @Test\n    public void test_getReference() throws Exception {\n        dataSource.getReference();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ExceptionSorterTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.vendor.MockExceptionSorter;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ExceptionSorterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(true);\n        dataSource.setDbType(\"mysql\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setFilters(\"stat\");\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_exceptionSorter() throws Exception {\n        assertTrue(dataSource.getExceptionSorter() instanceof MockExceptionSorter,\n                dataSource.getExceptionSorterClassName());\n\n        Connection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n\n        PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n\n        stmt.execute();\n\n        mockConn.close();\n\n        Exception stmtClosedError = null;\n        try {\n            stmt.close();\n        } catch (Exception ex) {\n            stmtClosedError = ex;\n        }\n        assertNotNull(stmtClosedError);\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/FullTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FullTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_restart() throws Exception {\n        assertEquals(false, dataSource.isFull());\n        dataSource.fill();\n\n        assertEquals(true, dataSource.isFull());\n        Connection conn = dataSource.getConnection();\n        assertEquals(true, dataSource.isFull());\n        conn.close();\n        assertEquals(true, dataSource.isFull());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/HoldableUnsupportTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\n\npublic class HoldableUnsupportTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        Filter filter = new FilterAdapter() {\n            @Override\n            public int connection_getHoldability(FilterChain chain, ConnectionProxy connection) throws SQLException {\n                throw new UnsupportedOperationException();\n            }\n        };\n        dataSource.getProxyFilters().add(filter);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        Connection[] connections = new Connection[8];\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i] = dataSource.getConnection();\n        }\n\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i].close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/InitExceptionThrowTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\npublic class InitExceptionThrowTest {\n    private DruidDataSource dataSource = new DruidDataSource();\n\n    private int connectCount;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource.setInitExceptionThrow(false);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new MockDriver() {\n            public Connection connect(String url, Properties info) throws SQLException {\n                if (connectCount++ < 1) {\n                    throw new SQLException(\"\");\n                }\n                return super.connect(url, info);\n            }\n        });\n        dataSource.setInitialSize(2);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_pool() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/Issue4316.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Issue4316 {\n    @Test\n    public void test_0() throws Exception {\n//        DruidDataSource druidDataSource = new DruidDataSource();\n//        druidDataSource.setUsername(\"\");\n//        druidDataSource.setPassword(\"\");\n//        druidDataSource.setUrl(\"jdbc:mock:xxx\");\n//        druidDataSource.setValidationQuery(\"select 1\");\n//        druidDataSource.setMinEvictableIdleTimeMillis(100000);\n//        druidDataSource.setMaxEvictableIdleTimeMillis(DruidDataSource.DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS);\n//        druidDataSource.setKeepAliveBetweenTimeMillis(120000);\n//        druidDataSource.setMinIdle(2);\n//        druidDataSource.setTimeBetweenEvictionRunsMillis(70000);\n//        druidDataSource.setKeepAlive(true);\n//        DruidPooledConnection connection1 = druidDataSource.getConnection();\n//        DruidPooledConnection connection2 = druidDataSource.getConnection();\n//        connection2.close();\n//        Thread.sleep(95000);\n//        connection1.close();\n//        Thread.sleep(140000);\n//        DruidPooledConnection connection3 = druidDataSource.getConnection();\n//        DruidPooledConnection connection4 = druidDataSource.getConnection();\n//        assertFalse(connection3.getConnectionHolder() == connection4.getConnectionHolder());\n//        connection3.close();\n//        connection4.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/JdbcDataSourceStatTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.Constants;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class JdbcDataSourceStatTest {\n    @Test\n    public void test_max() throws Exception {\n        JdbcDataSourceStat stat = new JdbcDataSourceStat(\"\", \"\");\n\n        for (int i = 0; i < 1000 * 10; ++i) {\n            stat.createSqlStat(\"select \" + i);\n        }\n\n        assertEquals(1000, stat.getSqlStatMap().size());\n    }\n\n    @Test\n    public void test_max_10() throws Exception {\n        Properties connectProperties = new Properties();\n        connectProperties.put(Constants.DRUID_STAT_SQL_MAX_SIZE, 10);\n        JdbcDataSourceStat stat = new JdbcDataSourceStat(\"\", \"\", \"mysql\", connectProperties);\n\n        for (int i = 0; i < 1000 * 1; ++i) {\n            stat.createSqlStat(\"select \" + i);\n        }\n\n        assertEquals(10, stat.getSqlStatMap().size());\n    }\n\n    @Test\n    public void test_max_10_str() throws Exception {\n        Properties connectProperties = new Properties();\n        connectProperties.put(Constants.DRUID_STAT_SQL_MAX_SIZE, \"10\");\n        JdbcDataSourceStat stat = new JdbcDataSourceStat(\"\", \"\", \"mysql\", connectProperties);\n\n        for (int i = 0; i < 1000 * 1; ++i) {\n            stat.createSqlStat(\"select \" + i);\n        }\n\n        assertEquals(10, stat.getSqlStatMap().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/KeepAliveTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 21/01/2017.\n */\npublic class KeepAliveTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:x1\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMinIdle(10);\n        dataSource.setMaxActive(20);\n//        dataSource.setMinEvictableIdleTimeMillis(30000);\n//        dataSource.setMaxEvictableIdleTimeMillis(30000);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setFilters(\"log4j\");\n        dataSource.setValidationQuery(\"select 1\");\n\n        Properties properties = new Properties();\n        properties.put(\"druid.keepAlive\", \"true\");\n        dataSource.configFromPropeties(properties);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_keepAlive() throws Exception {\n        dataSource.init();\n\n        for (int i = 0; i < 100; ++i) {\n            int poolingCount = dataSource.getPoolingCount();\n            if (poolingCount >= dataSource.getMinIdle()) {\n                break;\n            } else {\n                System.out.println(\"poolingCount : \" + poolingCount);\n            }\n            Thread.sleep(10 * 1);\n        }\n        assertEquals(dataSource.getMinIdle(), dataSource.getPoolingCount());\n        assertTrue(dataSource.isKeepAlive());\n\n        Connection[] connections = new Connection[dataSource.getMaxActive()];\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i] = dataSource.getConnection();\n        }\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i].close();\n        }\n        // assertEquals(dataSource.getMaxActive(), dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/KeepAliveTest_scheduler.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.Properties;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 21/01/2017.\n */\npublic class KeepAliveTest_scheduler {\n    private DruidDataSource dataSource;\n    private ScheduledExecutorService scheduler;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        scheduler = Executors.newScheduledThreadPool(10);\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:x1\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMinIdle(10);\n        dataSource.setMaxActive(20);\n//        dataSource.setMinEvictableIdleTimeMillis(30000);\n//        dataSource.setMaxEvictableIdleTimeMillis(30000);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setFilters(\"log4j\");\n        dataSource.setValidationQuery(\"select 1\");\n\n        Properties properties = new Properties();\n        properties.put(\"druid.keepAlive\", \"true\");\n        dataSource.configFromPropeties(properties);\n        dataSource.setCreateScheduler(scheduler);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_keepAlive() throws Exception {\n        dataSource.init();\n\n        for (int i = 0; i < 1000; ++i) {\n            if (dataSource.getMinIdle() == dataSource.getPoolingCount()) {\n                break;\n            }\n            Thread.sleep(10 * 1);\n        }\n        assertEquals(dataSource.getMinIdle(), dataSource.getPoolingCount());\n        assertTrue(dataSource.isKeepAlive());\n\n        Connection[] connections = new Connection[dataSource.getMaxActive()];\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i] = dataSource.getConnection();\n        }\n        for (int i = 0; i < connections.length; ++i) {\n            connections[i].close();\n        }\n        // assertEquals(dataSource.getMaxActive(), dataSource.getPoolingCount());\n\n        // Thread.sleep(1000 * 1000);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/LastActiveTest_0.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidConnectionHolder;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class LastActiveTest_0 {\n    private DruidDataSource dataSource;\n    private Field field;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.setMinIdle(0);\n        dataSource.setMaxActive(100);\n        dataSource.init();\n\n        field = DruidPooledConnection.class.getDeclaredField(\"holder\");\n        field.setAccessible(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        long t0, t1;\n        {\n            DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n            t0 = getLastActiveTime(conn);\n            PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n            Thread.sleep(2);\n            stmt.execute();\n\n            stmt.close();\n            conn.close();\n        }\n        Thread.sleep(1000);\n        {\n            DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n            t1 = getLastActiveTime(conn);\n            PreparedStatement stmt = conn.prepareStatement(\"select 1\");\n            Thread.sleep(2);\n            stmt.execute();\n\n            stmt.close();\n            conn.close();\n        }\n        assertNotEquals(t0, t1);\n    }\n\n    private long getLastActiveTime(DruidPooledConnection conn) throws IllegalAccessException {\n        DruidConnectionHolder holder = (DruidConnectionHolder) field.get(conn);\n        return holder.getLastActiveTimeMillis();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/LockFairTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.locks.ReentrantLock;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LockFairTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_fair() throws Exception {\n        assertEquals(false, ((ReentrantLock) dataSource.getLock()).isFair());\n        dataSource.setMaxWait(100);\n\n        assertEquals(false, ((ReentrantLock) dataSource.getLock()).isFair());\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n        dataSource.setMaxWait(110);\n\n        assertEquals(false, ((ReentrantLock) dataSource.getLock()).isFair());\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        dataSource.setMaxWait(0);\n\n        assertEquals(false, ((ReentrantLock) dataSource.getLock()).isFair());\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n    }\n\n    @Test\n    public void test_fair_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        assertEquals(false, ((ReentrantLock) dataSource.getLock()).isFair());\n        dataSource.setMaxWait(100);\n\n        assertEquals(false, ((ReentrantLock) dataSource.getLock()).isFair());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ManagedDataSourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ManagedDataSourceTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    public void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n    }\n\n    @AfterEach\n    public void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_managed() throws Exception {\n        DriverManager.getConnection(\"jdbc:mock:aaa\");\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        {\n            dataSource.setEnable(false);\n            SQLException error = null;\n            try {\n                dataSource.getConnection();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        dataSource.setEnable(true);\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/MaxWaitTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MaxWaitTest {\n    protected DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:driver\");\n        dataSource.setMaxWait(100);\n        dataSource.setDriver(new MockDriver() {\n            @Override\n            public Connection connect(String url, Properties info) throws SQLException {\n                try {\n                    Thread.sleep(1000);\n                } catch (InterruptedException e) {\n                    // skip\n                }\n                return super.connect(url, info);\n            }\n        });\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wait() throws Exception {\n        Exception error = null;\n        try {\n            DruidPooledConnection conn = dataSource.getConnection();\n            conn.close();\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        assertTrue(error.getMessage().contains(\"createElapseMillis \"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/OnFatalErrorMaxActiveTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidAbstractDataSource;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OnFatalErrorMaxActiveTest extends PoolTestCase {\n    protected DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n        dataSource.setOnFatalErrorMaxActive(1);\n    }\n\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    public void test_for_fatalError() throws Exception {\n        Field field = DruidAbstractDataSource.class.getDeclaredField(\"onFatalError\");\n        field.setAccessible(true);\n\n        SQLException faltalError = null;\n        for (int i = 0; i < 2; i++) {\n            faltalError = new SQLException();\n            Connection conn = dataSource.getConnection();\n            Method method = DruidDataSource.class.getDeclaredMethod(\"handleFatalError\", DruidPooledConnection.class, SQLException.class, String.class);\n            method.setAccessible(true);\n            method.invoke(dataSource, conn.unwrap(DruidPooledConnection.class), faltalError, \"select 'x'\");\n            conn.close();\n        }\n\n        Connection conn_0 = dataSource.getConnection();\n        assertTrue(dataSource.isOnFatalError());\n\n        SQLException error = null;\n        try {\n            Connection conn_1 = dataSource.getConnection();\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertTrue(error.getMessage().startsWith(\"onFatalError, activeCount 1, onFatalErrorMaxActive 1\"));\n        System.out.println(error.getMessage());\n        assertNotNull(error.getCause());\n        assertSame(faltalError, error.getCause());\n\n        Statement stmt = conn_0.createStatement();\n        ResultSet rs = stmt.executeQuery(\"select 1\");\n        assertFalse(dataSource.isOnFatalError());\n        rs.close();\n        stmt.close();\n        conn_0.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/OnFatalErrorMaxActiveTest_1.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidAbstractDataSource;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OnFatalErrorMaxActiveTest_1 extends PoolTestCase {\n    protected DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n        dataSource.setOnFatalErrorMaxActive(1);\n    }\n\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    public void test_for_fatalError() throws Exception {\n        Field field = DruidAbstractDataSource.class.getDeclaredField(\"onFatalError\");\n        field.setAccessible(true);\n\n        SQLException faltalError = null;\n        for (int i = 0; i < 2; i++) {\n            faltalError = new SQLException();\n            Connection conn = dataSource.getConnection();\n\n            Method method = DruidDataSource.class.getDeclaredMethod(\"handleFatalError\", DruidPooledConnection.class, SQLException.class, String.class);\n            method.setAccessible(true);\n            method.invoke(dataSource, conn.unwrap(DruidPooledConnection.class), faltalError, \"select 'x'\");\n            conn.close();\n        }\n\n        Connection conn_0 = dataSource.getConnection();\n        assertTrue(dataSource.isOnFatalError());\n\n        SQLException error = null;\n        try {\n            Connection conn_1 = dataSource.getConnection();\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertTrue(error.getMessage().startsWith(\"onFatalError, activeCount 1, onFatalErrorMaxActive 1\"));\n        System.out.println(error.getMessage());\n        assertNotNull(error.getCause());\n        assertSame(faltalError, error.getCause());\n\n        Statement stmt = conn_0.createStatement();\n        ResultSet rs = stmt.executeQuery(\"select 1\");\n        assertFalse(dataSource.isOnFatalError());\n        rs.close();\n        stmt.close();\n        conn_0.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PSCacheTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PSCacheTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:x1\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(10);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_noTxn() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 1\";\n\n        PreparedStatement stmt0 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;\n        stmt0.close();\n\n        PreparedStatement stmt1 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;\n\n        assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());\n        assertSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same\n\n        PreparedStatement stmt2 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;\n\n        assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not same\n\n        stmt1.close();\n        stmt2.close();\n\n        conn.close();\n    }\n\n    @Test\n    public void test_txn() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        conn.setAutoCommit(false);\n\n        String sql = \"select 1\";\n\n        PreparedStatement stmt0 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;\n        stmt0.close();\n\n        PreparedStatement stmt1 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;\n\n        assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());\n        assertSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same\n\n        PreparedStatement stmt2 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;\n\n        assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not same\n\n        stmt1.close();\n        stmt2.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PSCacheTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PSCacheTest1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:x1\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(10);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_noTxn() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n\n            String sql = \"select 1\";\n\n            PreparedStatement stmt0 = conn.prepareStatement(sql);\n            DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;\n            stmt0.close();\n\n            PreparedStatement stmt1 = conn.prepareStatement(sql);\n            DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;\n\n            assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());\n            assertSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same\n\n            PreparedStatement stmt2 = conn.prepareStatement(sql);\n            DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;\n\n            assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not\n            // same\n\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n\n            conn.setAutoCommit(false);\n\n            String sql = \"select 1\";\n\n            PreparedStatement stmt0 = conn.prepareStatement(sql);\n            DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;\n            stmt0.close();\n\n            PreparedStatement stmt1 = conn.prepareStatement(sql);\n            DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;\n\n            assertEquals(1, pooledStmt1.getPreparedStatementHolder().getInUseCount());\n            assertSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt0.getPreparedStatementHolder()); // same\n\n            PreparedStatement stmt2 = conn.prepareStatement(sql);\n            DruidPooledPreparedStatement pooledStmt2 = (DruidPooledPreparedStatement) stmt2;\n\n            assertNotSame(pooledStmt1.getPreparedStatementHolder(), pooledStmt2.getPreparedStatementHolder()); // not\n            // same\n\n            stmt1.close();\n            stmt2.close();\n\n            conn.close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PSCacheTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PSCacheTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:x1\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(10);\n        dataSource.setSharePreparedStatements(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        String sql = \"select 1\";\n\n        {\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.close();\n        }\n\n        PreparedStatement stmt0 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;\n\n        assertEquals(1, pooledStmt0.getPreparedStatementHolder().getInUseCount());\n\n        PreparedStatement stmt1 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;\n\n        assertSame(pooledStmt0.getPreparedStatementHolder(), pooledStmt1.getPreparedStatementHolder());\n\n        stmt0.close();\n        stmt1.close();\n\n        conn.close();\n    }\n\n    @Test\n    public void test_txn() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        conn.setAutoCommit(true);\n\n        String sql = \"select 1\";\n\n        {\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.close();\n        }\n\n        PreparedStatement stmt0 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt0 = (DruidPooledPreparedStatement) stmt0;\n\n        assertEquals(1, pooledStmt0.getPreparedStatementHolder().getInUseCount());\n\n        PreparedStatement stmt1 = conn.prepareStatement(sql);\n        DruidPooledPreparedStatement pooledStmt1 = (DruidPooledPreparedStatement) stmt1;\n\n        assertSame(pooledStmt0.getPreparedStatementHolder(), pooledStmt1.getPreparedStatementHolder());\n\n        stmt0.close();\n        stmt1.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PSCacheTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidConnectionHolder;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.pool.PreparedStatementHolder;\nimport com.alibaba.druid.pool.PreparedStatementPool;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PSCacheTest3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:x1\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(3);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_pscache() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection();\n\n        DruidConnectionHolder holder = conn.getConnectionHolder();\n        PreparedStatementPool stmtPool = holder.getStatementPool();\n\n        final String sql_0 = \"select 0\";\n        final String sql_1 = \"select 1\";\n        final String sql_2 = \"select 2\";\n        final String sql_3 = \"select 3\";\n        final String sql_4 = \"select 4\";\n\n        assertEquals(0, stmtPool.size());\n\n        PreparedStatementHolder stmtHoler_0;\n        PreparedStatementHolder stmtHoler_1;\n        PreparedStatementHolder stmtHoler_2;\n        PreparedStatementHolder stmtHoler_3;\n        PreparedStatementHolder stmtHoler_4;\n\n        // sql_0连续执行两次\n        {\n            DruidPooledPreparedStatement stmt_0 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_0);\n\n            assertFalse(stmt_0.getPreparedStatementHolder().isPooling());\n\n            stmt_0.close();\n            assertEquals(1, stmtPool.size());\n            assertTrue(stmt_0.getPreparedStatementHolder().isPooling());\n        }\n        {\n            DruidPooledPreparedStatement stmt_0 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_0);\n            assertEquals(1, stmtPool.size());\n            assertTrue(stmt_0.getPreparedStatementHolder().isInUse());\n            assertTrue(stmt_0.getPreparedStatementHolder().isPooling());\n\n            stmt_0.close();\n\n            assertFalse(stmt_0.getPreparedStatementHolder().isInUse());\n            assertTrue(stmt_0.getPreparedStatementHolder().isPooling());\n            assertEquals(1, stmtPool.size());\n        }\n\n        DruidPooledPreparedStatement stmt_0 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_0);\n\n        stmtHoler_0 = stmt_0.getPreparedStatementHolder();\n\n        assertTrue(stmtHoler_0.isInUse());\n        assertTrue(stmtHoler_0.isPooling());\n\n        stmt_0.execute();\n\n        {\n            DruidPooledPreparedStatement stmt_1 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n            assertEquals(1, stmtPool.size());\n\n            stmtHoler_1 = stmt_1.getPreparedStatementHolder();\n\n            assertTrue(stmt_1.getPreparedStatementHolder().isInUse());\n            assertFalse(stmt_1.getPreparedStatementHolder().isPooling());\n\n            stmt_1.close();\n\n            assertFalse(stmt_1.getPreparedStatementHolder().isInUse());\n            assertTrue(stmt_1.getPreparedStatementHolder().isPooling());\n            assertTrue(stmt_1.getPreparedStatementHolder().isPooling());\n            assertEquals(2, stmtPool.size());\n        }\n\n        assertTrue(stmtHoler_0.isPooling());\n        assertTrue(stmtHoler_1.isPooling());\n\n        {\n            DruidPooledPreparedStatement stmt_2 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_2);\n            assertEquals(2, stmtPool.size());\n\n            stmtHoler_2 = stmt_2.getPreparedStatementHolder();\n\n            assertTrue(stmt_2.getPreparedStatementHolder().isInUse());\n            assertFalse(stmt_2.getPreparedStatementHolder().isPooling());\n\n            stmt_2.close();\n\n            assertFalse(stmt_2.getPreparedStatementHolder().isInUse());\n            assertTrue(stmt_2.getPreparedStatementHolder().isPooling());\n            assertTrue(stmt_2.getPreparedStatementHolder().isPooling());\n            assertEquals(3, stmtPool.size());\n        }\n\n        assertTrue(stmtHoler_0.isPooling());\n        assertTrue(stmtHoler_1.isPooling());\n        assertTrue(stmtHoler_2.isPooling());\n\n        {\n            DruidPooledPreparedStatement stmt_3 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_3);\n            assertEquals(3, stmtPool.size());\n\n            stmtHoler_3 = stmt_3.getPreparedStatementHolder();\n\n            assertTrue(stmt_3.getPreparedStatementHolder().isInUse());\n            assertFalse(stmt_3.getPreparedStatementHolder().isPooling());\n\n            stmt_3.close();\n\n            assertFalse(stmt_3.getPreparedStatementHolder().isInUse());\n            assertTrue(stmt_3.getPreparedStatementHolder().isPooling());\n            assertTrue(stmt_3.getPreparedStatementHolder().isPooling());\n            assertEquals(3, stmtPool.size());\n        }\n\n        assertFalse(stmtHoler_0.isPooling());\n        assertTrue(stmtHoler_1.isPooling());\n        assertTrue(stmtHoler_2.isPooling());\n        assertTrue(stmtHoler_3.isPooling());\n\n        {\n            DruidPooledPreparedStatement stmt_4 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_4);\n            assertEquals(3, stmtPool.size());\n\n            stmtHoler_4 = stmt_4.getPreparedStatementHolder();\n\n            assertTrue(stmt_4.getPreparedStatementHolder().isInUse());\n            assertFalse(stmt_4.getPreparedStatementHolder().isPooling());\n\n            stmt_4.close();\n\n            assertFalse(stmt_4.getPreparedStatementHolder().isInUse());\n            assertTrue(stmt_4.getPreparedStatementHolder().isPooling());\n            assertTrue(stmt_4.getPreparedStatementHolder().isPooling());\n            assertEquals(3, stmtPool.size());\n        }\n\n        assertFalse(stmtHoler_0.isPooling());\n        assertFalse(stmtHoler_1.isPooling());\n        assertTrue(stmtHoler_2.isPooling());\n        assertTrue(stmtHoler_3.isPooling());\n        assertTrue(stmtHoler_4.isPooling());\n\n        stmt_0.close();\n\n        assertTrue(stmtHoler_0.isPooling());\n        assertFalse(stmtHoler_1.isPooling());\n        assertFalse(stmtHoler_2.isPooling());\n        assertTrue(stmtHoler_3.isPooling());\n        assertTrue(stmtHoler_4.isPooling());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PSCacheTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.*;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PSCacheTest4 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:x1\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(50);\n        dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_pscache() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection();\n\n        DruidConnectionHolder holder = conn.getConnectionHolder();\n        PreparedStatementPool stmtPool = holder.getStatementPool();\n\n        final String sql_0 = \"select 0\";\n        final String sql_1 = \"select 1\";\n\n        assertEquals(0, stmtPool.size());\n\n        PreparedStatementHolder stmtHoler_0;\n        PreparedStatementHolder stmtHoler_1_A;\n        PreparedStatementHolder stmtHoler_1_B;\n        PreparedStatementHolder stmtHoler_1_C;\n\n        DruidPooledPreparedStatement stmt_0;\n        DruidPooledPreparedStatement stmt_1_A;\n        DruidPooledPreparedStatement stmt_1_B;\n        DruidPooledPreparedStatement stmt_1_C;\n        DruidPooledPreparedStatement stmt_1_D;\n        DruidPooledPreparedStatement stmt_1_E;\n        DruidPooledPreparedStatement stmt_1_F;\n        DruidPooledPreparedStatement stmt_1_G;\n        DruidPooledPreparedStatement stmt_1_H;\n\n        DruidPooledResultSet rs_0;\n        DruidPooledResultSet rs_1_A;\n        DruidPooledResultSet rs_1_B;\n        DruidPooledResultSet rs_1_C;\n        DruidPooledResultSet rs_1_D;\n        DruidPooledResultSet rs_1_E;\n        DruidPooledResultSet rs_1_F;\n        DruidPooledResultSet rs_1_G;\n        DruidPooledResultSet rs_1_H;\n\n        stmt_0 = (DruidPooledPreparedStatement) conn.prepareStatement(sql_0);\n        rs_0 = (DruidPooledResultSet) stmt_0.executeQuery();\n\n        assertTrue(stmt_0.getPreparedStatementHolder().isInUse());\n\n        stmt_1_A = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_A = (DruidPooledResultSet) stmt_1_A.executeQuery();\n\n        assertTrue(stmt_0.getPreparedStatementHolder().isInUse());\n        assertTrue(stmt_1_A.getPreparedStatementHolder().isInUse());\n\n        stmt_1_B = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_B = (DruidPooledResultSet) stmt_1_B.executeQuery();\n        rs_1_B.close();\n        stmt_1_B.close();\n\n        assertTrue(stmt_0.getPreparedStatementHolder().isInUse());\n        assertTrue(stmt_1_A.getPreparedStatementHolder().isInUse());\n        assertFalse(stmt_1_B.getPreparedStatementHolder().isInUse());\n\n        stmt_1_C = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_C = (DruidPooledResultSet) stmt_1_C.executeQuery();\n        rs_1_C.close();\n        stmt_1_C.close();\n\n        assertTrue(stmt_0.getPreparedStatementHolder().isInUse());\n        assertTrue(stmt_1_A.getPreparedStatementHolder().isInUse());\n        assertFalse(stmt_1_B.getPreparedStatementHolder().isInUse());\n        assertFalse(stmt_1_C.getPreparedStatementHolder().isInUse());\n\n        stmt_1_D = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_D = (DruidPooledResultSet) stmt_1_D.executeQuery();\n        rs_1_D.close();\n        stmt_1_D.close();\n\n        assertTrue(stmt_0.getPreparedStatementHolder().isInUse());\n        assertTrue(stmt_1_A.getPreparedStatementHolder().isInUse());\n        assertFalse(stmt_1_B.getPreparedStatementHolder().isInUse());\n        assertFalse(stmt_1_C.getPreparedStatementHolder().isInUse());\n        assertFalse(stmt_1_D.getPreparedStatementHolder().isInUse());\n\n        stmt_1_E = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_E = (DruidPooledResultSet) stmt_1_E.executeQuery();\n        rs_1_E.close();\n        stmt_1_E.close();\n\n        rs_1_A.close();\n        stmt_1_A.close();\n\n        stmt_1_F = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_F = (DruidPooledResultSet) stmt_1_F.executeQuery();\n        rs_1_F.close();\n        stmt_1_F.close();\n\n        stmt_1_G = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_G = (DruidPooledResultSet) stmt_1_G.executeQuery();\n\n        stmt_1_H = (DruidPooledPreparedStatement) conn.prepareStatement(sql_1);\n        rs_1_H = (DruidPooledResultSet) stmt_1_H.executeQuery();\n        rs_1_H.close();\n        stmt_1_H.close();\n\n        rs_1_G.close();\n        stmt_1_G.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ParamTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ParamTest {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_default() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n\n        assertEquals(0, dataSource.getProxyFilters().size());\n\n        dataSource.setFilters(\"stat\");\n         JdbcStatManager.getInstance().reset();\n         dataSource.init();\n        JdbcDataSourceStat stat = dataSource.getDataSourceStat();\n\n        assertEquals(0, stat.getConnectionStat().getConnectCount());\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        for (int i = 0; i < 2; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(1, stat.getConnectionStat().getConnectCount());\n            assertEquals(0, stat.getConnectionStat().getCloseCount());\n\n            conn.close();\n\n            assertEquals(1, stat.getConnectionStat().getConnectCount());\n            assertEquals(0, stat.getConnectionStat().getCloseCount()); // logic\n            // close不会导致计数器＋1\n        }\n\n        dataSource.close();\n\n        // assertEquals(0, JdbcStatManager.getInstance().getDataSources().size());\n\n        assertEquals(1, stat.getConnectionStat().getConnectCount());\n        assertEquals(1, stat.getConnectionStat().getCloseCount());\n        JdbcStatManager.getInstance().reset();\n        assertEquals(1, stat.getConnectionStat().getConnectCount());\n        assertEquals(1, stat.getConnectionStat().getCloseCount());\n    }\n\n    @Test\n    public void test_zero() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n        dataSource.setInitialSize(0);\n        dataSource.setMinIdle(0);\n        dataSource.setMaxIdle(0);\n\n        Exception error = null;\n        try {\n            dataSource.setMaxActive(0);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n\n        assertEquals(0, dataSource.getProxyFilters().size());\n\n        dataSource.setFilters(\"stat\");\n         JdbcStatManager.getInstance().reset();\n         // DruidDataSourceStatManager.clear();\n        // assertEquals(0, JdbcStatManager.getInstance().getDataSources().size());\n\n        assertEquals(1, dataSource.getProxyFilters().size());\n\n        dataSource.getConnection();\n\n        dataSource.close();\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n        dataSource.setInitialSize(10);\n        dataSource.setMaxActive(10);\n        dataSource.setMinIdle(0);\n        dataSource.setMaxIdle(10);\n\n        dataSource.setFilters(\"stat\");\n        assertEquals(1, dataSource.getProxyFilters().size());\n        JdbcStatManager.getInstance().reset();\n        dataSource.init();\n        JdbcDataSourceStat stat = dataSource.getDataSourceStat();\n\n        assertEquals(10, stat.getConnectionStat().getConnectCount());\n\n        for (int i = 0; i < 10; ++i) {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        assertEquals(10, stat.getConnectionStat().getConnectCount());\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PasswordCallbackTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.util.DruidPasswordCallback;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PasswordCallbackTest {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n\n        TestPasswordCallback passwordCallback = new TestPasswordCallback();\n        dataSource.setPasswordCallback(passwordCallback);\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        assertEquals(dataSource.getUrl(), passwordCallback.getUrl());\n        assertEquals(dataSource.getConnectProperties(), passwordCallback.getProperties());\n\n        dataSource.close();\n    }\n\n    public static class TestPasswordCallback extends DruidPasswordCallback {\n        private static final long serialVersionUID = 1L;\n\n        private Properties properties;\n\n        public TestPasswordCallback() {\n            super(\"test\", false);\n        }\n\n        public TestPasswordCallback(String prompt, boolean echoOn) {\n            super(prompt, echoOn);\n        }\n\n        public Properties getProperties() {\n            return properties;\n        }\n\n        public void setProperties(Properties properties) {\n            this.properties = properties;\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PreparedStatementKeyTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\nimport com.alibaba.druid.pool.PreparedStatementPool.MethodType;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PreparedStatementKeyTest {\n    @Test\n    public void test_0() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103);\n        assertEquals(101, k1.getResultSetType());\n        assertEquals(102, k1.getResultSetConcurrency());\n        assertEquals(103, k1.getResultSetHoldability());\n    }\n\n    @Test\n    public void test_eq() throws Exception {\n        assertEquals(new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103),\n                new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103));\n    }\n\n    @Test\n    public void test_not_eq() throws Exception {\n        assertFalse(\n                new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103).equals(\n                        new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 201, 102, 103)));\n    }\n\n    @Test\n    public void test_not_eq_1() throws Exception {\n        assertFalse(\n                new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103).equals(\n                        new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 202, 103)));\n    }\n\n    @Test\n    public void test_not_eq_2() throws Exception {\n        assertFalse(\n                new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103).equals(\n                        new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 203)));\n    }\n\n    @Test\n    public void test_not_eq_3() throws Exception {\n        assertFalse(\n                new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103).equals(\n                        new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M2, 101, 102, 103)));\n    }\n\n    @Test\n    public void test_not_eq_4() throws Exception {\n        assertFalse(\n                new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103).equals(\n                        new PreparedStatementKey(\"select 'a'\", \"c2\", MethodType.M1, 101, 102, 103)));\n    }\n\n    @Test\n    public void test_not_eq_5() throws Exception {\n        assertFalse(\n                new PreparedStatementKey(\"select 'a'\", \"c1\", MethodType.M1, 101, 102, 103).equals(\n                        new PreparedStatementKey(\"select 'b'\", \"c1\", MethodType.M1, 101, 102, 103)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/PreparedStatementProxyImplTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.Types;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PreparedStatementProxyImplTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setInitialSize(1);\n        dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_setObject() throws Exception {\n        String sql = \"insert t values(?, ?, ?, ?, ?,  ?, ?, ?, ?, ?)\";\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.setObject(1, (byte) 1);\n        stmt.setObject(2, (short) 1);\n        stmt.setObject(3, (int) 1);\n        stmt.setObject(4, (long) 1);\n        stmt.setObject(5, (float) 1);\n\n        stmt.setObject(6, (double) 1);\n        stmt.setObject(7, new BigDecimal(1));\n        stmt.setObject(8, true);\n        stmt.setObject(9, \"xxx\");\n        stmt.setObject(10, new java.sql.Date(System.currentTimeMillis()));\n\n        stmt.setObject(11, new java.util.Date(System.currentTimeMillis()));\n        stmt.setObject(12, new java.sql.Timestamp(System.currentTimeMillis()));\n        stmt.setObject(13, new java.sql.Time(System.currentTimeMillis()));\n\n        stmt.execute();\n\n        PreparedStatementProxy stmtProxy = stmt.unwrap(PreparedStatementProxy.class);\n        assertNotNull(stmtProxy);\n\n        assertEquals(Types.TINYINT, stmtProxy.getParameter(0).getSqlType());\n        assertEquals(Types.SMALLINT, stmtProxy.getParameter(1).getSqlType());\n        assertEquals(Types.INTEGER, stmtProxy.getParameter(2).getSqlType());\n        assertEquals(Types.BIGINT, stmtProxy.getParameter(3).getSqlType());\n        assertEquals(Types.FLOAT, stmtProxy.getParameter(4).getSqlType());\n\n        assertEquals(Types.DOUBLE, stmtProxy.getParameter(5).getSqlType());\n        assertEquals(Types.DECIMAL, stmtProxy.getParameter(6).getSqlType());\n        assertEquals(Types.BOOLEAN, stmtProxy.getParameter(7).getSqlType());\n        assertEquals(Types.VARCHAR, stmtProxy.getParameter(8).getSqlType());\n        assertEquals(Types.DATE, stmtProxy.getParameter(9).getSqlType());\n\n        assertEquals(Types.DATE, stmtProxy.getParameter(10).getSqlType());\n        assertEquals(Types.TIMESTAMP, stmtProxy.getParameter(11).getSqlType());\n        assertEquals(Types.TIME, stmtProxy.getParameter(12).getSqlType());\n\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/RegisterTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class RegisterTest {\n    @Test\n    public void test() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.init();\n\n        assertTrue(dataSource.isMbeanRegistered());\n\n        dataSource.registerMbean();\n        assertTrue(dataSource.isMbeanRegistered());\n\n        dataSource.unregisterMbean();\n        assertFalse(dataSource.isMbeanRegistered());\n        assertFalse(dataSource.isMbeanRegistered());\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/SavepointTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Savepoint;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SavepointTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setInitialSize(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_multi_savepoint() throws Exception {\n        Connection conn = dataSource.getConnection();\n        MockConnection physicalConn = conn.unwrap(MockConnection.class);\n\n        assertEquals(true, conn.getAutoCommit());\n        assertEquals(true, physicalConn.getAutoCommit());\n\n        conn.setAutoCommit(false);\n\n        assertEquals(false, conn.getAutoCommit());\n        assertEquals(false, physicalConn.getAutoCommit());\n\n        Savepoint[] savepoints = new Savepoint[100];\n        for (int i = 0; i < savepoints.length; ++i) {\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"insert t (\" + i + \")\");\n            stmt.close();\n            savepoints[i] = conn.setSavepoint();\n\n            assertEquals(i + 1, physicalConn.getSavepoints().size());\n            for (int j = 0; j <= i; ++j) {\n                assertTrue(physicalConn.getSavepoints().contains(savepoints[j]));\n            }\n        }\n\n        // rollback single\n        conn.rollback(savepoints[99]);\n        assertEquals(99, physicalConn.getSavepoints().size());\n\n        // release single\n        conn.releaseSavepoint(savepoints[97]);\n        assertEquals(98, physicalConn.getSavepoints().size());\n\n        // rollback multi\n        conn.rollback(savepoints[90]);\n        assertEquals(90, physicalConn.getSavepoints().size());\n\n        // rollback all\n        conn.rollback();\n        assertEquals(0, physicalConn.getSavepoints().size());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/SlowSqlMillisTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SlowSqlMillisTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setTestOnReturn(false);\n        dataSource.setTestWhileIdle(false);\n        dataSource.setConnectionProperties(\"druid.stat.slowSqlMillis=500\");\n        dataSource.setFilters(\"stat\");\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        StatFilter filter = (StatFilter) dataSource.getProxyFilters().get(0);\n        assertEquals(500, filter.getSlowSqlMillis());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/SlowSqlMillisTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SlowSqlMillisTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setTestOnReturn(false);\n        dataSource.setTestWhileIdle(false);\n        System.setProperty(\"druid.stat.slowSqlMillis\", \"500\");\n        dataSource.setFilters(\"stat\");\n\n        {\n            StatFilter filter = (StatFilter) dataSource.getProxyFilters().get(0);\n            assertEquals(3000, filter.getSlowSqlMillis());\n        }\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        System.clearProperty(\"druid.stat.slowSqlMillis\");\n        dataSource.close();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        StatFilter filter = (StatFilter) dataSource.getProxyFilters().get(0);\n        assertEquals(500, filter.getSlowSqlMillis());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/SpringIbatisFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.spring.IUserService;\nimport com.alibaba.druid.spring.User;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.DruidStatService;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SpringIbatisFilterTest {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_spring() throws Exception {\n        DruidDataSourceStatManager.clear();\n        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(\n                \"com/alibaba/druid/pool/ibatis/spring-config-ibatis.xml\");\n\n        DataSource dataSource = (DataSource) context.getBean(\"dataSource\");\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE sequence_seed (value INTEGER, name VARCHAR(50) PRIMARY KEY)\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE t_User (id BIGINT PRIMARY KEY, name VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            conn.setAutoCommit(false);\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"insert into sequence_seed (value ,name) values (0, 'druid-spring-test')\");\n            stmt.close();\n            conn.commit();\n            conn.close();\n        }\n\n        // user-service\n        IUserService service = (IUserService) context.getBean(\"user-service\");\n        User user = new User();\n        user.setName(\"xx\");\n        service.addUser(user);\n\n        TestFilter filter = (TestFilter) context.getBean(\"test-filter\");\n        assertEquals(2, filter.getConnectCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE sequence_seed\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE t_User\");\n            stmt.close();\n            conn.close();\n        }\n\n        assertTrue(DruidDataSourceStatManager.getInstance().getDataSourceList().size() >= 1);\n\n        Map<String, Object> wallStats = DruidStatService.getInstance().getWallStatMap(Collections.<String, String>emptyMap());\n\n        System.out.println(\"wall-stats : \" + JSONUtils.toJSONString(wallStats));\n\n        context.close();\n         DruidDataSourceStatManager.clear();\n    }\n\n    public static class TestFilter extends FilterAdapter {\n        private AtomicLong connectCount = new AtomicLong();\n\n        @Override\n        public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException {\n            connectCount.incrementAndGet();\n            return chain.connection_connect(info);\n        }\n\n        public long getConnectCount() {\n            return connectCount.get();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/SpringMybatisFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.spring.User;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.apache.ibatis.annotations.Insert;\nimport org.apache.ibatis.annotations.Param;\nimport org.apache.ibatis.annotations.Select;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SpringMybatisFilterTest {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_spring() throws Exception {\n        DruidDataSourceStatManager.clear();\n        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(\n                \"com/alibaba/druid/pool/mybatis/spring-config-mybatis.xml\");\n\n        DataSource dataSource = (DataSource) context.getBean(\"dataSource\");\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE sequence_seed (value INTEGER, name VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE t_User (id BIGINT, name VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            conn.setAutoCommit(false);\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"insert into sequence_seed (value ,name) values (0, 'druid-spring-test')\");\n            stmt.close();\n            conn.commit();\n            conn.close();\n        }\n\n        UserMapper userMapper = (UserMapper) context.getBean(\"userMapper\");\n\n        {\n            User user = new User();\n            user.setName(\"xx\");\n\n            userMapper.addUser(user);\n        }\n\n        {\n            userMapper.errorSelect(1);\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE sequence_seed\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE t_User\");\n            stmt.close();\n            conn.close();\n        }\n\n        context.close();\n         DruidDataSourceStatManager.clear();\n    }\n\n    public static interface UserMapper {\n        @Insert(value = \"insert into t_User (id, name) values (#{user.id}, #{user.name})\")\n        void addUser(@Param(\"user\") User user);\n\n        @Select(value = \"delete from t_User where id = #{id}\")\n        void errorSelect(@Param(\"id\") long id);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestActiveTrace.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestActiveTrace {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        dataSource = new DruidDataSource();\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setRemoveAbandonedTimeoutMillis(100);\n        dataSource.setLogAbandoned(true);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_activeTrace() throws Exception {\n        for (int i = 0; i < 1000; ++i) {\n            dataSource.shrink();\n\n            Connection conn = dataSource.getConnection();\n            conn.close();\n            // sleep 10ms for checking stability, see https://github.com/alibaba/druid/issues/5620\n            Thread.sleep(10);\n            // assertEquals(1, dataSource.getPoolingCount());\n            dataSource.shrink();\n            assertEquals(0, dataSource.getPoolingCount(), \"createCount : \" + dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveConnections().size());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestClone.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestClone extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n\n        dataSource.setUsername(\"xxx1\");\n        dataSource.setPassword(\"ppp\");\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setMaxOpenPreparedStatements(30);\n    }\n\n    public void test_clone() throws Exception {\n        Connection conn_0 = dataSource.getConnection();\n        Connection conn_1 = dataSource.getConnection();\n        Connection conn_2 = dataSource.getConnection();\n\n        DruidDataSource clone = (DruidDataSource) dataSource.clone();\n        clone.init();\n\n        Connection conn_3 = dataSource.getConnection();\n        Connection conn_4 = dataSource.getConnection();\n        Connection conn_5 = dataSource.getConnection();\n\n        conn_3.close();\n        conn_4.close();\n        conn_5.close();\n\n        dataSource.close();\n\n        assertEquals(dataSource.getUrl(), clone.getUrl());\n        assertEquals(dataSource.getUsername(), clone.getUsername());\n        assertEquals(dataSource.getPassword(), clone.getPassword());\n        assertEquals(dataSource.getFilterClassNames(), clone.getFilterClassNames());\n        assertEquals(dataSource.getMaxOpenPreparedStatements(), clone.getMaxOpenPreparedStatements());\n\n        PreparedStatement ps_0 = conn_0.prepareStatement(\"select 1\");\n        ResultSet rs = ps_0.executeQuery();\n        rs.next();\n        rs.close();\n        ps_0.close();\n\n        // dataSource is closed, but connections is not closed\n        assertFalse(conn_0.isClosed());\n        assertFalse(conn_1.isClosed());\n        assertFalse(conn_2.isClosed());\n\n        MockConnection mockConn_0 = conn_0.unwrap(MockConnection.class);\n        MockConnection mockConn_1 = conn_1.unwrap(MockConnection.class);\n        MockConnection mockConn_2 = conn_2.unwrap(MockConnection.class);\n\n        assertFalse(mockConn_0.isClosed());\n        assertFalse(mockConn_1.isClosed());\n        assertFalse(mockConn_2.isClosed());\n\n        conn_0.close(); // no error\n        conn_1.close(); // no error\n        conn_2.close(); // no error\n\n        // real connection already closed\n        assertTrue(mockConn_0.isClosed());\n        assertTrue(mockConn_1.isClosed());\n        assertTrue(mockConn_2.isClosed());\n\n        // now is new dataSource;\n        dataSource = clone;\n\n        Connection conn_6 = dataSource.getConnection();\n        Connection conn_7 = dataSource.getConnection();\n        Connection conn_8 = dataSource.getConnection();\n\n        conn_6.close();\n        conn_7.close();\n        conn_8.close();\n    }\n\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        super.tearDown();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestClose_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestClose_0 extends PoolTestCase {\n    public void test_close() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        String sql = \"SELECT 1\";\n\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        conn.close();\n\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        rs.close();\n        stmt.close();\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestClose_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestClose_1 extends PoolTestCase {\n    public void test_close() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        String sql = \"SELECT 1\";\n\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        assertEquals(false, rs.isClosed());\n\n        assertEquals(false, stmt.isClosed());\n        stmt.close();\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        PreparedStatement stmt2 = conn.prepareStatement(sql);\n        assertEquals(true, stmt.isClosed());\n\n        assertEquals(stmt.unwrap(MockStatement.class), stmt2.unwrap(MockStatement.class));\n\n        conn.close();\n\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        rs.close();\n        stmt.close();\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestClose_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.CallableStatement;\nimport java.sql.Connection;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestClose_2 extends PoolTestCase {\n    public void test_close() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        String sql = \"SELECT 1\";\n\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(sql);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n        assertEquals(false, rs.isClosed());\n\n        assertEquals(false, stmt.isClosed());\n        stmt.close();\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        CallableStatement stmt2 = conn.prepareCall(sql);\n        assertEquals(true, stmt.isClosed());\n\n        assertEquals(stmt.unwrap(MockStatement.class), stmt2.unwrap(MockStatement.class));\n\n        conn.close();\n\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        rs.close();\n        stmt.close();\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestConnectError.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Properties;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestConnectError {\n    private DruidDataSource dataSource;\n    private MockDriver driver;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        driver = new MockDriver() {\n            private AtomicInteger count = new AtomicInteger();\n\n            public Connection connect(String url, Properties info) throws SQLException {\n                // create first connection successfully.\n                if (count.getAndIncrement() % 2 == 0) {\n                    throw new SQLException();\n                }\n\n                try {\n                    Thread.sleep(10);\n                } catch (InterruptedException e) {\n                    throw new SQLException();\n                }\n\n                return super.connect(url, info);\n            }\n        };\n        DruidDataSourceStatManager.clear();\n\n        dataSource = new DruidDataSource();\n        dataSource.setDriver(driver);\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setRemoveAbandonedTimeoutMillis(1000 * 180);\n        dataSource.setLogAbandoned(true);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000);\n        dataSource.setMaxActive(20);\n        dataSource.setUrl(\"jdbc:mock:TestConnectError\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect_error() throws Exception {\n        assertEquals(0, dataSource.getCreateErrorCount());\n\n        int count = 10;\n        Connection[] connections = new Connection[count];\n        for (int i = 0; i < count; ++i) {\n            connections[i] = dataSource.getConnection();\n        }\n\n        for (int i = 0; i < count; ++i) {\n            connections[i].close();\n        }\n\n        assertEquals(10, dataSource.getCreateErrorCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestConnectTimeout.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.time.LocalDateTime;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestConnectTimeout {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUsername(\"xxx1\");\n        dataSource.setPassword(\"ppp\");\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setMaxOpenPreparedStatements(30);\n        dataSource.setMaxActive(4);\n        dataSource.setMaxWait(50000); //时间灵敏度不够，容易导致单测失败，因此调大一点\n        dataSource.setMinIdle(0);\n        dataSource.setInitialSize(1);\n        dataSource.init();\n    }\n\n    @Test\n    public void testConnectTimeout() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n            dataSource.shrink();\n            assertEquals(0, dataSource.getPoolingCount());\n        }\n\n        final List<Connection> connections = new ArrayList<Connection>();\n        for (int i = 0; i < 3; ++i) {\n            Connection conn = dataSource.getConnection();\n            connections.add(conn);\n        }\n\n        final AtomicLong errorCount = new AtomicLong();\n        final int THREAD_COUNT = 10;\n        final CountDownLatch latch = new CountDownLatch(THREAD_COUNT);\n        for (int i = 0; i < THREAD_COUNT; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        for (int i = 0; i < 100; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            System.out.println(LocalDateTime.now() + \" : \" + Thread.currentThread() + \" \" + conn);\n                            Thread.sleep(1);\n                            conn.close();\n                        }\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                        errorCount.incrementAndGet();\n                    } finally {\n                        latch.countDown();\n                    }\n                }\n            };\n            thread.start();\n        }\n\n        latch.await();\n        assertEquals(0, errorCount.get());\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestDefault.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestDefault {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_close() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        String sql = \"SELECT 1\";\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n\n            assertEquals(0, conn.getHoldability());\n            assertEquals(false, conn.isReadOnly());\n            assertEquals(0, conn.getTransactionIsolation());\n\n            conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            conn.setReadOnly(false);\n            conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);\n\n            conn.close();\n\n            assertEquals(true, stmt.isClosed());\n            assertEquals(true, rs.isClosed());\n\n            rs.close();\n            stmt.close();\n        }\n\n        Connection conn = dataSource.getConnection();\n\n        assertEquals(0, conn.getHoldability());\n        assertEquals(false, conn.isReadOnly());\n        assertEquals(0, conn.getTransactionIsolation());\n\n        conn.close();\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestDisable.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DataSourceDisableException;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestDisable {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMaxWait(500); // 加上最大等待时间，防止出现无限等待导致单测卡死的情况\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_close() throws Exception {\n        final int threadCount = 100;\n        Thread[] threads = new Thread[threadCount];\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i] = new Thread(\"thread-\" + i) {\n                public void run() {\n                    try {\n                        System.out.println(\"wait for start \" + getName());\n                        startLatch.await();\n                        Connection conn = dataSource.getConnection();\n                        System.out.println(\"getConnection start \" + getName());\n                    } catch (DataSourceDisableException e) {\n                        // skip\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n        }\n\n        startLatch.countDown();\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i].start();\n        }\n        Thread.sleep(1000);\n\n        new Thread(\"close thread\") {\n            public void run() {\n                System.out.println(\"setEnable \" + getName());\n                dataSource.setEnable(false);\n            }\n        }.start();\n\n        endLatch.await();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestDruidDataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestDruidDataSource {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        Class.forName(\"com.alibaba.druid.mock.MockDriver\");\n\n        dataSource.setInitialSize(10);\n        dataSource.setMaxActive(10);\n        dataSource.setDriverClassName(\"com.alibaba.druid.mock.MockDriver\");\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        assertEquals(0, dataSource.getConnectCount());\n        assertEquals(0, dataSource.getConnectErrorCount());\n        assertEquals(0, dataSource.getCloseCount());\n        assertEquals(0, dataSource.getPoolingCount());\n\n        Connection conn = dataSource.getConnection();\n\n        assertTrue(conn instanceof DruidPooledConnection);\n\n        assertEquals(1, dataSource.getConnectCount());\n        assertEquals(0, dataSource.getConnectErrorCount());\n        assertEquals(0, dataSource.getCloseCount());\n        assertEquals(0, dataSource.getRecycleCount());\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(9, dataSource.getPoolingCount());\n\n        conn.close();\n\n        assertEquals(1, dataSource.getConnectCount());\n        assertEquals(0, dataSource.getConnectErrorCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(10, dataSource.getPoolingCount());\n\n        conn.close(); // 重复close\n\n        assertEquals(1, dataSource.getConnectCount());\n        assertEquals(0, dataSource.getConnectErrorCount());\n        assertEquals(1, dataSource.getCloseCount());\n        assertEquals(1, dataSource.getRecycleCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestGetUpdateCount.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestGetUpdateCount {\n    private DruidDataSource dataSource;\n    private MockDriver driver;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        driver = new MockDriver() {\n            @Override\n            public MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql) {\n                return new MyPreparedStatement(conn, sql);\n            }\n        };\n\n        // /////////////////////////////\n\n        dataSource = new DruidDataSource();\n\n        dataSource.setDriver(driver);\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setMaxOpenPreparedStatements(30);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_executeQuery() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n\n        MyPreparedStatement myStmt = stmt.unwrap(MyPreparedStatement.class);\n\n        assertNull(myStmt.updateCount);\n\n        stmt.setString(1, \"xxx\");\n        ResultSet rs = stmt.executeQuery();\n\n        assertEquals(-1, myStmt.updateCount.intValue());\n\n        rs.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"update t set id = ?\");\n\n        MyPreparedStatement myStmt = stmt.unwrap(MyPreparedStatement.class);\n\n        assertNull(myStmt.updateCount);\n\n        stmt.setString(1, \"xxx\");\n        stmt.execute();\n\n        assertNotNull(myStmt.updateCount);\n\n        assertEquals(1, stmt.getUpdateCount());\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute_multi() throws Exception {\n        MyPreparedStatement myStmtA = null;\n        MyPreparedStatement myStmtB = null;\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(\"update t set id = ?\");\n\n            myStmtA = stmt.unwrap(MyPreparedStatement.class);\n\n            assertNull(myStmtA.updateCount);\n\n            stmt.setString(1, \"xxx\");\n            stmt.execute();\n\n            assertNotNull(myStmtA.updateCount);\n\n            assertEquals(1, stmt.getUpdateCount());\n\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(\"update t set id = ?\");\n\n            myStmtB = stmt.unwrap(MyPreparedStatement.class);\n            assertSame(myStmtA, myStmtB);\n            assertNotNull(myStmtB.updateCount);\n\n            stmt.setString(1, \"xxx\");\n            stmt.execute();\n\n            assertNotNull(myStmtB.updateCount);\n\n            assertEquals(1, stmt.getUpdateCount());\n\n            stmt.close();\n            conn.close();\n        }\n    }\n\n    public static class MyPreparedStatement extends MockPreparedStatement {\n        Integer updateCount;\n\n        public MyPreparedStatement(MockConnection conn, String sql) {\n            super(conn, sql);\n        }\n\n        public boolean execute() throws SQLException {\n            updateCount = null;\n            return false;\n        }\n\n        public ResultSet executeQuery() throws SQLException {\n            updateCount = -1;\n            return super.executeQuery();\n        }\n\n        @Override\n        public int getUpdateCount() throws SQLException {\n            if (updateCount != null) {\n                throw new SQLException(\"illegal state\");\n            }\n\n            updateCount = 1;\n            return updateCount;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestGraceShutdown.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DataSourceDisableException;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport java.sql.Connection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestGraceShutdown extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n         DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMaxWait(5);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n    }\n\n    public void test_close() throws Exception {\n        final int threadCount = 100;\n        Thread[] threads = new Thread[threadCount];\n        final CountDownLatch startLatch = new CountDownLatch(1);\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i] = new Thread(\"thread-\" + i) {\n                public void run() {\n                    try {\n                        startLatch.await();\n                        Connection conn = dataSource.getConnection();\n                    } catch (DataSourceDisableException ex) {\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n        }\n\n        startLatch.countDown();\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i].start();\n        }\n        Thread.sleep(5000);\n\n        final CountDownLatch closeLatch = new CountDownLatch(1);\n        new Thread(\"close thread\") {\n            public void run() {\n                System.out.println(\"执行close start\");\n                dataSource.close();\n                closeLatch.countDown();\n            }\n        }.start();\n\n        closeLatch.await();\n        assertTrue(endLatch.await(60, TimeUnit.SECONDS));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestH2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestH2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:h2:mem:\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(10);\n\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_h2() throws Exception {\n        assertSame(JdbcUtils.H2, DbType.of(dataSource.getDbType()));\n\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT ?\");\n\n        stmt.setString(1, \"xxxx\");\n\n        ResultSet rs = stmt.executeQuery();\n\n        rs.next();\n        assertEquals(\"xxxx\", rs.getString(1));\n\n        rs.close();\n\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestIdle.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DataSourceMonitorable;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.openmbean.TabularData;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestIdle {\n    private DruidDataSource dataSource;\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        TabularData dataSourceList = DruidDataSourceStatManager.getInstance().getDataSourceList();\n        if (dataSourceList.size() > 0) {\n            DataSourceMonitorable first = DruidDataSourceStatManager.getInstance().getDruidDataSourceInstances().iterator().next();\n            System.out.println(first.getInitStackTrace());\n        }\n        assertEquals(0, dataSourceList.size());\n    }\n\n    @Test\n    public void test_idle() throws Exception {\n        MockDriver driver = new MockDriver();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(2);\n        dataSource.setMaxActive(4);\n        // dataSource.setMaxIdle(4);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(50 * 1);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n\n        {\n            assertEquals(0, dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(dataSource.getInitialSize(), dataSource.getCreateCount());\n            assertEquals(dataSource.getInitialSize(), driver.getConnections().size());\n            assertEquals(1, dataSource.getActiveCount());\n\n            conn.close();\n            assertEquals(0, dataSource.getDestroyCount());\n            assertEquals(dataSource.getInitialSize(), driver.getConnections().size());\n            assertEquals(0, dataSource.getActiveCount());\n        }\n\n        {\n            int count = 4;\n            Connection[] connections = new Connection[4];\n            for (int i = 0; i < count; ++i) {\n                connections[i] = dataSource.getConnection();\n                assertEquals(i + 1, dataSource.getActiveCount());\n            }\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(4, driver.getConnections().size());\n            for (int i = 0; i < count; ++i) {\n                connections[i].close();\n                assertEquals(count - i - 1, dataSource.getActiveCount());\n            }\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(4, driver.getConnections().size());\n\n            Thread.sleep(dataSource.getMinEvictableIdleTimeMillis() * 2);\n            assertEquals(dataSource.getMinIdle(), driver.getConnections().size());\n        }\n\n        System.out.println(\"----------raw close all connection\");\n        for (MockConnection rawConn : driver.getConnections()) {\n            rawConn.close();\n        }\n\n        Thread.sleep(dataSource.getMinEvictableIdleTimeMillis() * 2);\n        assertEquals(0, driver.getConnections().size());\n        assertEquals(1, dataSource.getPoolingCount());\n        {\n            Connection conn = dataSource.getConnection();\n            assertEquals(1, dataSource.getActiveCount());\n            assertEquals(dataSource.getMinIdle(), driver.getConnections().size());\n            conn.close();\n            assertEquals(dataSource.getMinIdle(), driver.getConnections().size());\n            assertEquals(0, dataSource.getActiveCount());\n        }\n\n        {\n            int count = 4;\n            Connection[] connections = new Connection[4];\n            for (int i = 0; i < count; ++i) {\n                connections[i] = dataSource.getConnection();\n                assertEquals(i + 1, dataSource.getActiveCount());\n            }\n            assertEquals(4, driver.getConnections().size());\n            for (int i = 0; i < count; ++i) {\n                connections[i].close();\n                assertEquals(count - i - 1, dataSource.getActiveCount());\n            }\n            assertEquals(4, driver.getConnections().size());\n            assertEquals(0, dataSource.getActiveCount(), \"activeCount not zero\");\n\n            dataSource.shrink();\n            assertEquals(0, dataSource.getActiveCount(), \"activeCount not zero\");\n            assertEquals(dataSource.getMinIdle(), driver.getConnections().size(), \"minIdle not equal physical\");\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestIdle2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestIdle2 {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_idle2() throws Exception {\n        MockDriver driver = new MockDriver();\n\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(14);\n        dataSource.setMaxActive(14);\n        dataSource.setMaxIdle(14);\n        dataSource.setMinIdle(14);\n        dataSource.setMinEvictableIdleTimeMillis(50 * 1);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n\n        {\n            assertEquals(0, dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(dataSource.getInitialSize(), dataSource.getCreateCount());\n            assertEquals(dataSource.getInitialSize(), driver.getConnections().size());\n            assertEquals(1, dataSource.getActiveCount());\n\n            conn.close();\n            assertEquals(0, dataSource.getDestroyCount());\n            assertEquals(true, dataSource.getPoolingCount() == driver.getConnections().size());\n            assertEquals(0, dataSource.getActiveCount());\n        }\n\n        String text = dataSource.toString();\n        System.out.println(text);\n\n        {\n            int count = 14;\n            Connection[] connections = new Connection[count];\n            for (int i = 0; i < count; ++i) {\n                connections[i] = dataSource.getConnection();\n                assertEquals(i + 1, dataSource.getActiveCount());\n            }\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(count, driver.getConnections().size());\n            for (int i = 0; i < count; ++i) {\n                connections[i].close();\n                assertEquals(count - i - 1, dataSource.getActiveCount());\n            }\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(14, driver.getConnections().size());\n        }\n\n        for (int i = 0; i < 100; ++i) {\n            assertEquals(0, dataSource.getActiveCount());\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(1, dataSource.getActiveCount());\n\n            Thread.sleep(1);\n            conn.close();\n        }\n        assertEquals(true, dataSource.getPoolingCount() == dataSource.getMaxActive());\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestIdle3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.ObjectName;\n\nimport java.lang.management.ManagementFactory;\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestIdle3 {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_idle2() throws Exception {\n        MockDriver driver = new MockDriver();\n\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(14);\n        dataSource.setMaxIdle(14);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(30 * 100); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(18 * 100); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n\n        ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource,\n                new ObjectName(\n                        \"com.alibaba:type=DataSource,name=mysql\"));\n        ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource,\n                new ObjectName(\n                        \"com.alibaba:type=DataSource,name=oracle\"));\n\n        // 第一次创建连接\n        {\n            assertEquals(0, dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(dataSource.getInitialSize(), dataSource.getCreateCount());\n            assertEquals(dataSource.getInitialSize(), driver.getConnections().size());\n            assertEquals(1, dataSource.getActiveCount());\n\n            conn.close();\n            assertEquals(0, dataSource.getDestroyCount());\n            assertEquals(1, driver.getConnections().size());\n            assertEquals(1, dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n        }\n\n        {\n            // 并发创建14个\n            int count = 14;\n            Connection[] connections = new Connection[count];\n            for (int i = 0; i < count; ++i) {\n                connections[i] = dataSource.getConnection();\n                assertEquals(i + 1, dataSource.getActiveCount());\n            }\n\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(count, driver.getConnections().size());\n\n            // 全部关闭\n            for (int i = 0; i < count; ++i) {\n                connections[i].close();\n                assertEquals(count - i - 1, dataSource.getActiveCount());\n            }\n\n            assertEquals(dataSource.getMaxActive(), dataSource.getCreateCount());\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(14, driver.getConnections().size());\n        }\n\n        // 连续打开关闭单个连接\n        for (int i = 0; i < 1000; ++i) {\n            assertEquals(0, dataSource.getActiveCount());\n            Connection conn = dataSource.getConnection();\n\n            assertEquals(1, dataSource.getActiveCount());\n\n            Thread.sleep(10);\n            conn.close();\n        }\n        assertEquals(true, dataSource.getPoolingCount() == 2 || dataSource.getPoolingCount() == 1);\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestLogLongTimeTransaction.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestLogLongTimeTransaction {\n    private DruidDataSource dataSource;\n    private MockDriver driver;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        driver = new MockDriver() {\n            protected ResultSet executeQuery(MockStatement stmt, String sql) throws SQLException {\n                try {\n                    Thread.sleep(2);\n                } catch (InterruptedException e) {\n                    // TODO Auto-generated catch block\n                    e.printStackTrace();\n                }\n                return super.executeQuery(stmt, sql);\n            }\n        };\n\n        dataSource = new DruidDataSource();\n        dataSource.setDriver(driver);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat,trace,log4j,encoding\");\n        dataSource.setTransactionThresholdMillis(1);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        conn.setAutoCommit(false);\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(\"SELECT 1\");\n        rs.next();\n        rs.close();\n        stmt.close();\n        conn.commit();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOnBorrowFileAndNameTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.util.Iterator;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOnBorrowFileAndNameTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setName(\"com.alibaba.dragoon.monitor\");\n        dataSource.setMinIdle(0);\n        dataSource.setPoolPreparedStatements(false);\n        dataSource.setTestOnBorrow(true);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        String sql = \"SELECT NOW()\";\n\n        JdbcSqlStat.setContextSqlName(\"select_now\");\n        JdbcSqlStat.setContextSqlFile(\"test_file\");\n\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        conn.close();\n\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        rs.close();\n        stmt.close();\n\n        dataSource.shrink();\n\n        JdbcStatManager.getInstance().getDataSourceList();\n        assertTrue(DruidDataSourceStatManager.getInstance().getDataSourceList().size() >= 1);\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlList().size());\n\n        Iterator<JdbcSqlStat> iterator = dataSource.getDataSourceStat().getSqlStatMap().values().iterator();\n        JdbcSqlStat sql_0 = iterator.next();\n\n        // there are no JdbcSqlStat of 'SELECT 1' as connection validation will skip all filters now.\n        // assertEquals(\"SELECT 1\", sql_0.getSql());\n        // assertNull(sql_0.getFile());\n        // assertNull(sql_0.getName());\n\n        assertEquals(\"SELECT NOW()\", sql_0.getSql());\n        assertEquals(\"test_file\", sql_0.getFile());\n        assertEquals(\"select_now\", sql_0.getName());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOraclePrefetch.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.PreparedStatementHolder;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport oracle.jdbc.OracleConnection;\nimport oracle.jdbc.internal.OraclePreparedStatement;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOraclePrefetch {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setOracle(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setConnectionProperties(\"defaultRowPrefetch=50\");\n//        dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        String sql = \"SELECT 1\";\n\n        OracleConnection oracleConn;\n        OraclePreparedStatement oracleStmt;\n        PreparedStatementHolder stmtHolder;\n        {\n            Connection conn = dataSource.getConnection();\n\n            {\n                oracleConn = conn.unwrap(OracleConnection.class);\n                assertEquals(50, oracleConn.getDefaultRowPrefetch());\n            }\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            oracleStmt = stmt.unwrap(OraclePreparedStatement.class);\n            assertEquals(50, oracleStmt.getRowPrefetch());\n\n            assertTrue(stmt.isWrapperFor(PreparedStatementHolder.class));\n            stmtHolder = stmt.unwrap(PreparedStatementHolder.class);\n            assertNotNull(stmtHolder);\n            assertEquals(0, stmtHolder.getHitCount());\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            {\n                OracleConnection oracleConn2 = conn.unwrap(OracleConnection.class);\n                assertEquals(50, oracleConn2.getDefaultRowPrefetch());\n                assertSame(oracleConn, oracleConn2);\n            }\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            {\n                PreparedStatementHolder stmtHolder2 = stmt.unwrap(PreparedStatementHolder.class);\n                assertSame(stmtHolder2, stmtHolder);\n                assertEquals(1, stmtHolder.getHitCount());\n            }\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n            {\n                OraclePreparedStatement oracleStmt2 = stmt.unwrap(OraclePreparedStatement.class);\n                assertSame(oracleStmt, oracleStmt2);\n                assertEquals(2, oracleStmt.getRowPrefetch());\n            }\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOracleWall.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOracleWall {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setOracle(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setConnectionProperties(\"defaultRowPrefetch=50\");\n        dataSource.setFilters(\"stat,wall\");\n        dataSource.setDbType(\"oracle\");\n        // dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        String sql = \"SELECT 1\";\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOracleWall2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOracleWall2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        WallFilter wall = new WallFilter();\n        wall.setConfig(new WallConfig());\n        wall.getConfig().setWrapAllow(false);\n\n        dataSource.setOracle(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setConnectionProperties(\"defaultRowPrefetch=50\");\n        dataSource.setFilters(\"stat\");\n        dataSource.getProxyFilters().add(wall);\n        dataSource.setDbType(\"oracle\");\n        // dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        String sql = \"SELECT 1\";\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n            assertNotNull(conn.unwrap(DruidPooledConnection.class));\n\n            assertFalse(conn.isWrapperFor(oracle.jdbc.OracleConnection.class));\n            assertNull(conn.unwrap(oracle.jdbc.OracleConnection.class));\n\n            assertFalse(conn.isWrapperFor(java.sql.Connection.class));\n            assertNull(conn.unwrap(java.sql.Connection.class));\n\n            // /////////////\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            assertNull(stmt.unwrap(oracle.jdbc.OraclePreparedStatement.class));\n            assertFalse(stmt.isWrapperFor(oracle.jdbc.OraclePreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(DruidPooledPreparedStatement.class));\n            assertNotNull(stmt.unwrap(DruidPooledPreparedStatement.class));\n\n            assertFalse(stmt.isWrapperFor(java.sql.PreparedStatement.class));\n            assertNull(stmt.unwrap(java.sql.PreparedStatement.class));\n\n            ResultSet rs = stmt.executeQuery();\n\n            assertNull(rs.unwrap(oracle.jdbc.OracleResultSet.class));\n            assertFalse(rs.isWrapperFor(oracle.jdbc.OracleResultSet.class));\n\n            assertTrue(rs.isWrapperFor(DruidPooledResultSet.class));\n            assertNotNull(rs.unwrap(DruidPooledResultSet.class));\n\n            assertFalse(rs.isWrapperFor(java.sql.ResultSet.class));\n            assertNull(rs.unwrap(java.sql.ResultSet.class));\n\n            rs.next();\n\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        for (int i = 0; i < 10; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOracleWall3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOracleWall3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        WallFilter wall = new WallFilter();\n        wall.setConfig(new WallConfig());\n        wall.getConfig().setWrapAllow(true);\n\n        dataSource.setOracle(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setConnectionProperties(\"defaultRowPrefetch=50\");\n        dataSource.setFilters(\"stat\");\n        dataSource.getProxyFilters().add(wall);\n        dataSource.setDbType(\"oracle\");\n        // dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        String sql = \"SELECT 1\";\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n            assertNotNull(conn.unwrap(DruidPooledConnection.class));\n\n            assertTrue(conn.isWrapperFor(oracle.jdbc.OracleConnection.class));\n            assertNotNull(conn.unwrap(oracle.jdbc.OracleConnection.class));\n\n            assertTrue(conn.isWrapperFor(java.sql.Connection.class));\n            assertNotNull(conn.unwrap(java.sql.Connection.class));\n\n            // /////////////\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            assertNotNull(stmt.unwrap(oracle.jdbc.OraclePreparedStatement.class));\n            assertTrue(stmt.isWrapperFor(oracle.jdbc.OraclePreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(DruidPooledPreparedStatement.class));\n            assertNotNull(stmt.unwrap(DruidPooledPreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(java.sql.PreparedStatement.class));\n            assertNotNull(stmt.unwrap(java.sql.PreparedStatement.class));\n\n            ResultSet rs = stmt.executeQuery();\n\n            assertNotNull(rs.unwrap(oracle.jdbc.OracleResultSet.class));\n            assertTrue(rs.isWrapperFor(oracle.jdbc.OracleResultSet.class));\n\n            assertTrue(rs.isWrapperFor(DruidPooledResultSet.class));\n            assertNotNull(rs.unwrap(DruidPooledResultSet.class));\n\n            assertTrue(rs.isWrapperFor(java.sql.ResultSet.class));\n            assertNotNull(rs.unwrap(java.sql.ResultSet.class));\n\n            rs.next();\n\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        for (int i = 0; i < 10; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOracleWallJdbc3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport com.alibaba.druid.test.util.OracleMockDriverJdbc3;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.WallFilter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOracleWallJdbc3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        WallFilter wall = new WallFilter();\n        wall.setConfig(new WallConfig());\n        wall.getConfig().setWrapAllow(true);\n\n        dataSource.setOracle(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new OracleMockDriverJdbc3());\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setConnectionProperties(\"defaultRowPrefetch=50\");\n        dataSource.setFilters(\"stat\");\n        dataSource.getProxyFilters().add(wall);\n        dataSource.setDbType(\"oracle\");\n        // dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        String sql = \"SELECT 1\";\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n            assertNotNull(conn.unwrap(DruidPooledConnection.class));\n\n            assertTrue(conn.isWrapperFor(oracle.jdbc.OracleConnection.class));\n            assertNotNull(conn.unwrap(oracle.jdbc.OracleConnection.class));\n\n            assertTrue(conn.isWrapperFor(java.sql.Connection.class));\n            assertNotNull(conn.unwrap(java.sql.Connection.class));\n\n            // /////////////\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            assertNotNull(stmt.unwrap(oracle.jdbc.OraclePreparedStatement.class));\n            assertTrue(stmt.isWrapperFor(oracle.jdbc.OraclePreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(DruidPooledPreparedStatement.class));\n            assertNotNull(stmt.unwrap(DruidPooledPreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(java.sql.PreparedStatement.class));\n            assertNotNull(stmt.unwrap(java.sql.PreparedStatement.class));\n\n            ResultSet rs = stmt.executeQuery();\n\n            assertNotNull(rs.unwrap(oracle.jdbc.OracleResultSet.class));\n            assertTrue(rs.isWrapperFor(oracle.jdbc.OracleResultSet.class));\n\n            assertTrue(rs.isWrapperFor(DruidPooledResultSet.class));\n            assertNotNull(rs.unwrap(DruidPooledResultSet.class));\n\n            assertTrue(rs.isWrapperFor(java.sql.ResultSet.class));\n            assertNotNull(rs.unwrap(java.sql.ResultSet.class));\n\n            rs.next();\n\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        for (int i = 0; i < 10; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOracleWrap.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOracleWrap {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setOracle(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setConnectionProperties(\"defaultRowPrefetch=50\");\n        dataSource.setDbType(\"oracle\");\n        // dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        String sql = \"SELECT 1\";\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n            assertNotNull(conn.unwrap(DruidPooledConnection.class));\n\n            assertTrue(conn.isWrapperFor(oracle.jdbc.OracleConnection.class));\n            assertNotNull(conn.unwrap(oracle.jdbc.OracleConnection.class));\n\n            assertTrue(conn.isWrapperFor(java.sql.Connection.class));\n            assertNotNull(conn.unwrap(java.sql.Connection.class));\n\n            // /////////////\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            assertNotNull(stmt.unwrap(oracle.jdbc.OraclePreparedStatement.class));\n            assertTrue(stmt.isWrapperFor(oracle.jdbc.OraclePreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(DruidPooledPreparedStatement.class));\n            assertNotNull(stmt.unwrap(DruidPooledPreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(java.sql.PreparedStatement.class));\n            assertNotNull(stmt.unwrap(java.sql.PreparedStatement.class));\n\n            ResultSet rs = stmt.executeQuery();\n\n            assertNotNull(rs.unwrap(oracle.jdbc.OracleResultSet.class));\n            assertTrue(rs.isWrapperFor(oracle.jdbc.OracleResultSet.class));\n\n            assertTrue(rs.isWrapperFor(DruidPooledResultSet.class));\n            assertNotNull(rs.unwrap(DruidPooledResultSet.class));\n\n            assertTrue(rs.isWrapperFor(java.sql.ResultSet.class));\n            assertNotNull(rs.unwrap(java.sql.ResultSet.class));\n\n            rs.next();\n\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        for (int i = 0; i < 10; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestOracleWrap2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport com.alibaba.druid.test.util.OracleMockDriverJdbc3;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestOracleWrap2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setOracle(true);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new OracleMockDriverJdbc3());\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setConnectionProperties(\"defaultRowPrefetch=50\");\n        dataSource.setDbType(\"oracle\");\n        // dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        String sql = \"SELECT 1\";\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n            assertNotNull(conn.unwrap(DruidPooledConnection.class));\n\n            assertTrue(conn.isWrapperFor(oracle.jdbc.OracleConnection.class));\n            assertNotNull(conn.unwrap(oracle.jdbc.OracleConnection.class));\n\n            assertTrue(conn.isWrapperFor(java.sql.Connection.class));\n            assertNotNull(conn.unwrap(java.sql.Connection.class));\n\n            // /////////////\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            assertNotNull(stmt.unwrap(oracle.jdbc.OraclePreparedStatement.class));\n            assertTrue(stmt.isWrapperFor(oracle.jdbc.OraclePreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(DruidPooledPreparedStatement.class));\n            assertNotNull(stmt.unwrap(DruidPooledPreparedStatement.class));\n\n            assertTrue(stmt.isWrapperFor(java.sql.PreparedStatement.class));\n            assertNotNull(stmt.unwrap(java.sql.PreparedStatement.class));\n\n            ResultSet rs = stmt.executeQuery();\n\n            assertNotNull(rs.unwrap(oracle.jdbc.OracleResultSet.class));\n            assertTrue(rs.isWrapperFor(oracle.jdbc.OracleResultSet.class));\n\n            assertTrue(rs.isWrapperFor(DruidPooledResultSet.class));\n            assertNotNull(rs.unwrap(DruidPooledResultSet.class));\n\n            assertTrue(rs.isWrapperFor(java.sql.ResultSet.class));\n            assertNotNull(rs.unwrap(java.sql.ResultSet.class));\n\n            rs.next();\n\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        for (int i = 0; i < 10; ++i) {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestPoolPreparedStatement.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestPoolPreparedStatement {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(10); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(true);\n//        ((StatFilter) dataSource.getProxyFilters().get(0)).setMaxSqlStatCount(100);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_removeAbandoned() throws Exception {\n        MockPreparedStatement raw;\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT ?\");\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT ?\");\n            assertTrue(raw == stmt.unwrap(MockPreparedStatement.class));\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestPoolPreparedStatement2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestPoolPreparedStatement2 {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(10); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(false);\n        dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);\n\n//        ((StatFilter) dataSource.getProxyFilters().get(0)).setMaxSqlStatCount(100);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_stmtCache() throws Exception {\n        for (int j = 0; j < 10; ++j) {\n            for (int i = 0; i < 10; ++i) {\n                Connection conn = dataSource.getConnection();\n                String sql = \"SELECT\" + i;\n                PreparedStatement stmt = conn.prepareStatement(sql);\n                stmt.execute();\n                stmt.close();\n                conn.close();\n            }\n        }\n\n        dataSource.setPoolPreparedStatements(true);\n\n        for (int j = 0; j < 10; ++j) {\n            for (int i = 0; i < 10; ++i) {\n                Connection conn = dataSource.getConnection();\n                String sql = \"SELECT\" + i;\n                PreparedStatement stmt = conn.prepareStatement(sql);\n                stmt.execute();\n                stmt.close();\n                conn.close();\n            }\n        }\n\n        for (int i = 0; i < 10 * 1; ++i) {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT \" + i);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n\n        Connection conn = dataSource.getConnection();\n        DruidPooledConnection poolableConn = conn.unwrap(DruidPooledConnection.class);\n        assertNotNull(poolableConn);\n\n        assertEquals(dataSource.getMaxPoolPreparedStatementPerConnectionSize(),\n                poolableConn.getConnectionHolder().getStatementPool().getMap().size());\n\n        conn.close();\n\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestRemoveAbandoned.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestRemoveAbandoned {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        driver = new MockDriver();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(10); // 180 / 10\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setRemoveAbandonedTimeoutMillis(10);\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_removeAbandoned() throws Exception {\n        Connection conn = dataSource.getConnection();\n        assertEquals(1, dataSource.getActiveCount());\n        assertEquals(0, dataSource.getPoolingCount());\n\n        // 超时之后，连接自动关闭\n        Thread.sleep(100);\n        assertTrue(conn.isClosed());\n\n        assertEquals(1, dataSource.getRemoveAbandonedCount());\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestRemoveAbandoned2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestRemoveAbandoned2 {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        driver = new MockDriver();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(1000 * 300); // 180 / 10\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setRemoveAbandonedTimeoutMillis(0);\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_removeAbandoned() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n\n        Thread abandonThread = new Thread(\"abandoned\") {\n            public void run() {\n                for (; ; ) {\n                    dataSource.removeAbandoned();\n                    if (Thread.interrupted()) {\n                        break;\n                    }\n                }\n            }\n        };\n\n        abandonThread.start();\n\n        for (int i = 0; i < 1000 * 100; ++i) {\n            DruidPooledConnection conn = dataSource.getConnection();\n            conn.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        abandonThread.interrupt();\n\n        System.out.println(\"removeAbandondedCount : \" + dataSource.getRemoveAbandonedCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestSharePreparedStatements.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestSharePreparedStatements {\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_sharePreparedStatements() throws Exception {\n        // sharePreparedStatements\n\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMaxPoolPreparedStatementPerConnectionSize(30);\n\n        String sql = \"SELECT 1\";\n\n        MockPreparedStatement mockStmt = null;\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            mockStmt = stmt.unwrap(MockPreparedStatement.class);\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            assertEquals(mockStmt, stmt.unwrap(MockPreparedStatement.class));\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n            conn.setAutoCommit(false);\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            assertSame(mockStmt, stmt.unwrap(MockPreparedStatement.class));\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        {\n            Connection conn = dataSource.getConnection();\n            conn.setAutoCommit(false);\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            assertSame(mockStmt, stmt.unwrap(MockPreparedStatement.class));\n            ResultSet rs = stmt.executeQuery();\n            rs.next();\n            rs.close();\n            stmt.close();\n\n            conn.close();\n        }\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TestStat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestStat {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setName(\"com.alibaba.dragoon.monitor\");\n        dataSource.setMinIdle(0);\n        dataSource.setPoolPreparedStatements(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        String sql = \"SELECT 1\";\n\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        ResultSet rs = stmt.executeQuery();\n        rs.next();\n\n        conn.close();\n\n        assertEquals(true, stmt.isClosed());\n        assertEquals(true, rs.isClosed());\n\n        rs.close();\n        stmt.close();\n\n        dataSource.shrink();\n\n        JdbcStatManager.getInstance().getDataSourceList();\n        assertEquals(1, DruidDataSourceStatManager.getInstance().getDataSourceList().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TimeBetweenLogStatsMillisTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TimeBetweenLogStatsMillisTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTimeBetweenLogStatsMillis(1000);\n        // dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        assertEquals(true, dataSource.isResetStatEnable());\n        dataSource.init();\n        assertEquals(1000, dataSource.getTimeBetweenLogStatsMillis());\n        assertEquals(false, dataSource.isResetStatEnable());\n        dataSource.resetStat();\n        assertEquals(0, dataSource.getResetCount());\n        dataSource.setConnectionProperties(\"druid.resetStatEnable=true\");\n        assertEquals(true, dataSource.isResetStatEnable());\n\n        dataSource.setConnectionProperties(\"druid.resetStatEnable=false\");\n        assertEquals(false, dataSource.isResetStatEnable());\n\n        dataSource.setConnectionProperties(\"druid.resetStatEnable=xxx\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TimeBetweenLogStatsMillisTest2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TimeBetweenLogStatsMillisTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        System.setProperty(\"druid.timeBetweenLogStatsMillis\", \"1000\");\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        System.clearProperty(\"druid.timeBetweenLogStatsMillis\");\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        dataSource.init();\n        assertEquals(1000, dataSource.getTimeBetweenLogStatsMillis());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TimeBetweenLogStatsMillisTest3.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TimeBetweenLogStatsMillisTest3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        System.setProperty(\"druid.timeBetweenLogStatsMillis\", \"10\");\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        System.clearProperty(\"druid.timeBetweenLogStatsMillis\");\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        dataSource.init();\n        for (int i = 0; i < 10; ++i) {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n            stmt.setString(1, \"aaa\");\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n            stmt.close();\n            conn.close();\n\n            Thread.sleep(10);\n        }\n        assertEquals(10, dataSource.getTimeBetweenLogStatsMillis());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/TransactionTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\npublic class TransactionTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_txn() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        conn.setAutoCommit(false);\n        for (int i = 0; i < 100; ++i) {\n            PreparedStatement stmt = conn.prepareStatement(\"select + \" + (i % 10));\n            stmt.executeUpdate();\n            stmt.close();\n        }\n        conn.commit();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UnwrapTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class UnwrapTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(true);\n        dataSource.setInitialSize(1);\n        dataSource.setValidationQuery(\"select 1\");\n        dataSource.setValidationQueryTimeout(10);\n        dataSource.setQueryTimeout(100);\n\n        dataSource.setFilters(\"log4j\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_unwrap() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n        assertNotNull(conn.unwrap(DruidPooledConnection.class));\n        assertSame(conn, conn.unwrap(DruidPooledConnection.class));\n\n        assertTrue(conn.isWrapperFor(MockConnection.class));\n        assertNotNull(conn.unwrap(MockConnection.class));\n\n        PreparedStatement stmt = conn.prepareStatement(\"select ?\");\n\n        assertTrue(stmt.isWrapperFor(Statement.class));\n        assertNotNull(stmt.unwrap(Statement.class));\n\n        assertTrue(stmt.isWrapperFor(PreparedStatement.class));\n        assertNotNull(stmt.unwrap(PreparedStatement.class));\n\n        assertTrue(stmt.isWrapperFor(StatementProxy.class));\n        assertNotNull(stmt.unwrap(StatementProxy.class));\n\n        assertTrue(stmt.isWrapperFor(PreparedStatementProxy.class));\n        assertNotNull(stmt.unwrap(PreparedStatementProxy.class));\n\n        assertTrue(stmt.isWrapperFor(PreparedStatementProxyImpl.class));\n        assertNotNull(stmt.unwrap(PreparedStatementProxyImpl.class));\n\n        assertTrue(stmt.isWrapperFor(MockPreparedStatement.class));\n        assertNotNull(stmt.unwrap(MockPreparedStatement.class));\n\n        stmt.setObject(1, \"aaa\");\n        ResultSet rs = stmt.executeQuery();\n\n        assertTrue(rs.isWrapperFor(ResultSet.class));\n        assertNotNull(rs.unwrap(ResultSet.class));\n\n        assertTrue(rs.isWrapperFor(ResultSetProxy.class));\n        assertNotNull(rs.unwrap(ResultSetProxy.class));\n\n        assertTrue(rs.isWrapperFor(ResultSetProxyImpl.class));\n        assertNotNull(rs.unwrap(ResultSetProxyImpl.class));\n\n        assertTrue(rs.isWrapperFor(MockResultSet.class));\n        assertNotNull(rs.unwrap(MockResultSet.class));\n\n        rs.close();\n\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UnwrapTest2.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxyImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class UnwrapTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(true);\n        dataSource.setInitialSize(1);\n        dataSource.setValidationQuery(\"select 1\");\n        dataSource.setValidationQueryTimeout(10);\n        dataSource.setQueryTimeout(100);\n\n        dataSource.setFilters(\"mergeStat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_unwrap() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n        assertNotNull(conn.unwrap(DruidPooledConnection.class));\n        assertSame(conn, conn.unwrap(DruidPooledConnection.class));\n\n        assertTrue(conn.isWrapperFor(MockConnection.class));\n        assertNotNull(conn.unwrap(MockConnection.class));\n\n        Statement stmt = conn.createStatement();\n\n        assertTrue(stmt.isWrapperFor(Statement.class));\n        assertNotNull(stmt.unwrap(Statement.class));\n\n        assertTrue(stmt.isWrapperFor(StatementProxy.class));\n        assertNotNull(stmt.unwrap(StatementProxy.class));\n\n        assertTrue(stmt.isWrapperFor(StatementProxyImpl.class));\n        assertNotNull(stmt.unwrap(StatementProxyImpl.class));\n\n        assertTrue(stmt.isWrapperFor(MockStatement.class));\n        assertNotNull(stmt.unwrap(MockStatement.class));\n\n        ResultSet rs = stmt.executeQuery(\"select 1\");\n\n        assertTrue(rs.isWrapperFor(ResultSet.class));\n        assertNotNull(rs.unwrap(ResultSet.class));\n\n        assertTrue(rs.isWrapperFor(ResultSetProxy.class));\n        assertNotNull(rs.unwrap(ResultSetProxy.class));\n\n        assertTrue(rs.isWrapperFor(ResultSetProxyImpl.class));\n        assertNotNull(rs.unwrap(ResultSetProxyImpl.class));\n\n        assertTrue(rs.isWrapperFor(MockResultSet.class));\n        assertNotNull(rs.unwrap(MockResultSet.class));\n\n        rs.close();\n\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UnwrapTest_filter.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.filter.logging.Log4jFilter;\nimport com.alibaba.druid.filter.logging.LogFilter;\nimport com.alibaba.druid.filter.stat.MergeStatFilter;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class UnwrapTest_filter extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(true);\n        dataSource.setInitialSize(1);\n        dataSource.setValidationQuery(\"select 1\");\n        dataSource.setValidationQueryTimeout(10);\n        dataSource.setQueryTimeout(100);\n\n        dataSource.setFilters(\"mergeStat,log4j\");\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_unwrap() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        assertTrue(dataSource.isWrapperFor(StatFilter.class));\n        assertNotNull(dataSource.unwrap(StatFilter.class));\n\n        assertTrue(dataSource.isWrapperFor(MergeStatFilter.class));\n        assertNotNull(dataSource.unwrap(MergeStatFilter.class));\n\n        assertTrue(dataSource.isWrapperFor(LogFilter.class));\n        assertNotNull(dataSource.unwrap(LogFilter.class));\n\n        assertTrue(dataSource.isWrapperFor(Log4jFilter.class));\n        assertNotNull(dataSource.unwrap(Log4jFilter.class));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UrlNotSetTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class UrlNotSetTest {\n    protected DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setMaxWait(10);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_wait() throws Exception {\n        Exception error = null;\n        try {\n            DruidPooledConnection conn = dataSource.getConnection();\n            assertNull(conn);\n            //conn.close();\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        //assertEquals(\"url not set\", error.getMessage());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UserPasswordVersionTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 这个场景测试initialSize > maxActive\n *\n * @author wenshao [szujobs@hotmail.com]\n */\npublic class UserPasswordVersionTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setUsername(\"u0\");\n        dataSource.setPassword(\"p0\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(30);\n        dataSource.setMaxWait(30);\n        dataSource.setInitialSize(1);\n        dataSource.setMinIdle(3);\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_maxWait() throws Exception {\n        ExecutorService executor = Executors.newFixedThreadPool(10);\n        final CountDownLatch latch0 = new CountDownLatch(1);\n        executor.submit(\n                () -> {\n                    try {\n                        DruidPooledConnection[] connections = new DruidPooledConnection[10];\n                        for (int i = 0; i < connections.length; i++) {\n                            connections[i] = dataSource.getConnection();\n                        }\n                        for (int i = 0; i < connections.length; i++) {\n                            connections[i].close();\n                        }\n                        assertEquals(connections.length, dataSource.getPoolingCount());\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                    } finally {\n                        latch0.countDown();\n                    }\n                }\n        );\n        latch0.await();\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        assertEquals(0, conn.getConnectionHolder().getUserPasswordVersion());\n\n        final CountDownLatch latch1 = new CountDownLatch(1);\n        executor.submit(() -> {\n            try {\n                Properties properties = new Properties();\n                properties.put(\"druid.username\", \"u1\");\n                properties.put(\"druid.password\", \"p1\");\n                dataSource.configFromProperties(properties);\n            } catch (Exception e) {\n                e.printStackTrace();\n            } finally {\n                latch1.countDown();\n            }\n        });\n        latch1.await();\n\n        assertEquals(9, dataSource.getPoolingCount());\n        assertEquals(1, dataSource.getActiveCount());\n\n        conn.close();\n\n        assertEquals(9, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n\n        DruidPooledConnection conn1 = dataSource.getConnection();\n        assertEquals(1, conn1.getConnectionHolder().getUserPasswordVersion());\n        conn1.close();\n\n        assertEquals(9, dataSource.getPoolingCount());\n        assertEquals(0, dataSource.getActiveCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UsingDefaultLockModeBenchmarkTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.openjdk.jmh.annotations.*;\nimport org.openjdk.jmh.runner.Runner;\nimport org.openjdk.jmh.runner.RunnerException;\nimport org.openjdk.jmh.runner.options.Options;\nimport org.openjdk.jmh.runner.options.OptionsBuilder;\n\nimport java.sql.Connection;\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@BenchmarkMode(Mode.AverageTime)\n@Warmup(iterations = 1, time = 3)\n@Measurement(iterations = 3, time = 3)\n// Threads.MAX means using Runtime.getRuntime().availableProcessors().\n@Threads(Threads.MAX)\n@Fork(1)\n@OutputTimeUnit(TimeUnit.SECONDS)\n@State(Scope.Benchmark)\npublic class UsingDefaultLockModeBenchmarkTest {\n    private DruidDataSource dataSource;\n\n    @Setup(Level.Trial)\n    public void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        dataSource = new DruidDataSource();\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setRemoveAbandonedTimeoutMillis(100);\n        dataSource.setLogAbandoned(true);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new SlowDriver());\n        int poolSize = Runtime.getRuntime().availableProcessors() / 2;\n        dataSource.setMaxActive(poolSize);\n        dataSource.setInitialSize(poolSize);\n        dataSource.setMaxWait(2000);\n        dataSource.init();\n    }\n\n    public static class SlowDriver extends MockDriver {\n        public MockConnection createMockConnection(MockDriver driver, String url, Properties connectProperties) {\n            try {\n                Thread.sleep(1000 * 1);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n            return super.createMockConnection(driver, url, connectProperties);\n        }\n    }\n\n    @TearDown(Level.Trial)\n    public void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Benchmark\n    public void test_activeTrace() throws Exception {\n        int count = 1000_00;\n        int i = 0;\n        try {\n            for (; i < count; ++i) {\n                Connection conn = dataSource.getConnection();\n                assertNotNull(conn);\n                conn.close();\n                assertTrue(conn.isClosed());\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            assertEquals(count, i);\n        }\n    }\n\n    public static void main(String[] args) throws RunnerException {\n        Options options = new OptionsBuilder()\n                .include(UsingDefaultLockModeBenchmarkTest.class.getSimpleName())\n                .build();\n        new Runner(options).run();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UsingFairLockBenchmarkTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.openjdk.jmh.annotations.*;\nimport org.openjdk.jmh.runner.Runner;\nimport org.openjdk.jmh.runner.RunnerException;\nimport org.openjdk.jmh.runner.options.Options;\nimport org.openjdk.jmh.runner.options.OptionsBuilder;\n\nimport java.sql.Connection;\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@BenchmarkMode(Mode.AverageTime)\n@Warmup(iterations = 1, time = 3)\n@Measurement(iterations = 3, time = 3)\n// Threads.MAX means using Runtime.getRuntime().availableProcessors().\n@Threads(Threads.MAX)\n@Fork(1)\n@OutputTimeUnit(TimeUnit.SECONDS)\n@State(Scope.Benchmark)\npublic class UsingFairLockBenchmarkTest {\n    private DruidDataSource dataSource;\n\n    @Setup(Level.Trial)\n    public void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        dataSource = new DruidDataSource();\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setRemoveAbandonedTimeoutMillis(100);\n        dataSource.setLogAbandoned(true);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new SlowDriver());\n        int poolSize = Runtime.getRuntime().availableProcessors() / 2;\n        dataSource.setMaxActive(poolSize);\n        dataSource.setInitialSize(poolSize);\n        dataSource.setMaxWait(2000);\n        dataSource.setUseUnfairLock(false);\n        dataSource.init();\n    }\n\n    public static class SlowDriver extends MockDriver {\n        public MockConnection createMockConnection(MockDriver driver, String url, Properties connectProperties) {\n            try {\n                Thread.sleep(1000 * 1);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n            return super.createMockConnection(driver, url, connectProperties);\n        }\n    }\n\n    @TearDown(Level.Trial)\n    public void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Benchmark\n    public void test_activeTrace() throws Exception {\n        int count = 1000_00;\n        int i = 0;\n        try {\n            for (; i < count; ++i) {\n                Connection conn = dataSource.getConnection();\n                assertNotNull(conn);\n                conn.close();\n                assertTrue(conn.isClosed());\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            assertEquals(count, i);\n        }\n    }\n\n    public static void main(String[] args) throws RunnerException {\n        Options options = new OptionsBuilder()\n                .include(UsingFairLockBenchmarkTest.class.getSimpleName())\n                .build();\n        new Runner(options).run();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/UsingUnfairLockBenchmarkTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.openjdk.jmh.annotations.*;\nimport org.openjdk.jmh.runner.Runner;\nimport org.openjdk.jmh.runner.RunnerException;\nimport org.openjdk.jmh.runner.options.Options;\nimport org.openjdk.jmh.runner.options.OptionsBuilder;\n\nimport java.sql.Connection;\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@BenchmarkMode(Mode.AverageTime)\n@Warmup(iterations = 1, time = 3)\n@Measurement(iterations = 3, time = 3)\n// Threads.MAX means using Runtime.getRuntime().availableProcessors().\n@Threads(Threads.MAX)\n@Fork(1)\n@OutputTimeUnit(TimeUnit.SECONDS)\n@State(Scope.Benchmark)\npublic class UsingUnfairLockBenchmarkTest {\n    private DruidDataSource dataSource;\n\n    @Setup(Level.Trial)\n    public void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        dataSource = new DruidDataSource();\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setRemoveAbandonedTimeoutMillis(100);\n        dataSource.setLogAbandoned(true);\n        dataSource.setTimeBetweenEvictionRunsMillis(10);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000);\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(new SlowDriver());\n        int poolSize = Runtime.getRuntime().availableProcessors() / 2;\n        dataSource.setMaxActive(poolSize);\n        dataSource.setInitialSize(poolSize);\n        dataSource.setMaxWait(2000);\n        dataSource.setUseUnfairLock(true);\n        dataSource.init();\n    }\n\n    public static class SlowDriver extends MockDriver {\n        public MockConnection createMockConnection(MockDriver driver, String url, Properties connectProperties) {\n            try {\n                Thread.sleep(1000 * 1);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n            return super.createMockConnection(driver, url, connectProperties);\n        }\n    }\n\n    @TearDown(Level.Trial)\n    public void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Benchmark\n    public void test_activeTrace() throws Exception {\n        int count = 1000_00;\n        int i = 0;\n        try {\n            for (; i < count; ++i) {\n                Connection conn = dataSource.getConnection();\n                assertNotNull(conn);\n                conn.close();\n                assertTrue(conn.isClosed());\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        } finally {\n            assertEquals(count, i);\n        }\n    }\n\n    public static void main(String[] args) throws RunnerException {\n        Options options = new OptionsBuilder()\n                .include(UsingUnfairLockBenchmarkTest.class.getSimpleName())\n                .build();\n        new Runner(options).run();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ValidationQueryLogDB2Test.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ValidationQueryLogDB2Test extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDbType(JdbcConstants.DB2);\n        dataSource.setDriver(new MockDriver() {\n            public int getMajorVersion() {\n                return 10;\n            }\n        });\n        dataSource.setValidationQuery(\"SELECT 'x'\");\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_oracle() throws Exception {\n        Field field = DruidDataSource.class.getDeclaredField(\"LOG\");\n        field.setAccessible(true);\n        Log log = (Log) field.get(null);\n        log.resetStat();\n\n        Connection conn = dataSource.getConnection();\n\n        conn.close();\n\n        assertEquals(1, log.getErrorCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/ValidationQueryLogTest.java",
    "content": "package com.alibaba.druid.bvt.pool;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ValidationQueryLogTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDbType(JdbcConstants.ORACLE);\n        dataSource.setDriver(new MockDriver() {\n            public int getMajorVersion() {\n                return 10;\n            }\n        });\n        dataSource.setValidationQuery(\"SELECT 'x'\");\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_oracle() throws Exception {\n        Field field = DruidDataSource.class.getDeclaredField(\"LOG\");\n        field.setAccessible(true);\n        Log log = (Log) field.get(null);\n        log.resetStat();\n\n        Connection conn = dataSource.getConnection();\n\n        conn.close();\n\n        assertEquals(1, log.getErrorCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/adapter/DruidDataSourceC3P0AdapterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.adapter;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSourceC3P0Adapter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceC3P0AdapterTest extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSourceC3P0Adapter dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n        DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSourceC3P0Adapter();\n        dataSource.setJdbcUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialPoolSize(1);\n        dataSource.setMaxPoolSize(2);\n        dataSource.setMinPoolSize(1);\n        dataSource.setMaxIdleTime(300); // 300 / 10\n        dataSource.setIdleConnectionTestPeriod(180); // 180 / 10\n        dataSource.setTestConnectionOnCheckout(false);\n        dataSource.setPreferredTestQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_basic() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/adapter/DruidDataSourceC3P0AdapterTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.adapter;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceC3P0Adapter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport javax.sql.DataSource;\n\nimport java.io.Closeable;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceC3P0AdapterTest2 extends PoolTestCase {\n    public void test_0() throws Exception {\n        DruidDataSourceStatManager.clear();\n        DruidDataSourceC3P0Adapter dataSource = new DruidDataSourceC3P0Adapter();\n        dataSource.setJdbcUrl(\"jdbc:mock:xxx\");\n\n        dataSource.setLogWriter(dataSource.getLogWriter());\n        dataSource.setLoginTimeout(dataSource.getLoginTimeout());\n\n        assertTrue(dataSource.isWrapperFor(DruidDataSourceC3P0Adapter.class));\n        assertTrue(dataSource.isWrapperFor(DruidDataSource.class));\n        assertTrue(dataSource.isWrapperFor(DataSource.class));\n        assertFalse(dataSource.isWrapperFor(null));\n\n        assertNotNull(dataSource.unwrap(DruidDataSourceC3P0Adapter.class));\n        assertNotNull(dataSource.unwrap(DruidDataSource.class));\n        assertNotNull(dataSource.unwrap(DataSource.class));\n        assertNull(dataSource.unwrap(null));\n\n        dataSource.setProperties(dataSource.getProperties());\n        dataSource.setUser(dataSource.getUser());\n        dataSource.setPassword(dataSource.getPassword());\n        dataSource.setCheckoutTimeout(dataSource.getCheckoutTimeout());\n        dataSource.setAutoCommitOnClose(dataSource.isAutoCommitOnClose());\n        dataSource.setIdleConnectionTestPeriod(dataSource.getIdleConnectionTestPeriod());\n        dataSource.setInitialPoolSize(dataSource.getInitialPoolSize());\n        dataSource.setMaxIdleTime(dataSource.getMaxIdleTime());\n        dataSource.setMaxPoolSize(dataSource.getMaxPoolSize());\n        dataSource.setMinPoolSize(dataSource.getMinPoolSize());\n        dataSource.setTestConnectionOnCheckout(dataSource.isTestConnectionOnCheckout());\n        dataSource.setTestConnectionOnCheckin(dataSource.isTestConnectionOnCheckin());\n        dataSource.setPreferredTestQuery(dataSource.getPreferredTestQuery());\n        dataSource.setProxyFilters(dataSource.getProxyFilters());\n        dataSource.getDataSourceName();\n        dataSource.getNumConnections();\n        dataSource.getNumIdleConnections();\n        dataSource.getNumBusyConnections();\n        dataSource.getNumUnclosedOrphanedConnections();\n        dataSource.getNumConnectionsDefaultUser();\n        dataSource.getNumIdleConnectionsDefaultUser();\n        dataSource.getNumBusyConnectionsDefaultUser();\n        dataSource.getMaxStatementsPerConnection();\n        dataSource.getMaxStatements();\n        dataSource.setUnreturnedConnectionTimeout(dataSource.getUnreturnedConnectionTimeout());\n        dataSource.isDebugUnreturnedConnectionStackTraces();\n        dataSource.setAcquireRetryAttempts(dataSource.getAcquireRetryAttempts());\n        dataSource.setAcquireRetryDelay(dataSource.getAcquireRetryDelay());\n        dataSource.setBreakAfterAcquireFailure(dataSource.isBreakAfterAcquireFailure());\n        dataSource.isEnable();\n        dataSource.shrink();\n        dataSource.getWaitThreadCount();\n        dataSource.getLockQueueLength();\n\n        dataSource.close();\n    }\n\n    protected void tearDown() throws Exception {\n        for (Closeable dataSource : DruidDataSourceStatManager.getDruidDataSourceInstances()) {\n            dataSource.close();\n        }\n\n        super.tearDown();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/ConnectionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\npublic class ConnectionTest extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        driver = new MockDriver();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        super.tearDown();\n    }\n\n    public void test_prepare() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY,\n                ResultSet.HOLD_CURSORS_OVER_COMMIT);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare3() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new int[0]);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare4() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new String[0]);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare5() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", Statement.RETURN_GENERATED_KEYS);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepareCall() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareCall(\"SELECT 1\");\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepareCall1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepareCall2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY,\n                ResultSet.HOLD_CURSORS_OVER_COMMIT);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_create() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_create1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement(ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_create2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement(ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY,\n                ResultSet.HOLD_CURSORS_OVER_COMMIT);\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/ConnectionTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectionTest2 extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n         DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.resetStat();\n        assertEquals(0, dataSource.getCreateCount());\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n        super.tearDown();\n    }\n\n    public void test_prepare() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY,\n                ResultSet.HOLD_CURSORS_OVER_COMMIT);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare3() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new int[0]);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare4() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new String[0]);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepare5() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", Statement.RETURN_GENERATED_KEYS);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepareCall() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareCall(\"SELECT 1\");\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepareCall1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_prepareCall2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY,\n                ResultSet.HOLD_CURSORS_OVER_COMMIT);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_create() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_create1() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement(ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);\n        stmt.close();\n\n        conn.close();\n    }\n\n    public void test_create2() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement(ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY,\n                ResultSet.HOLD_CURSORS_OVER_COMMIT);\n        stmt.close();\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/ConnectionTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatContext;\nimport com.alibaba.druid.stat.JdbcStatManager;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectionTest3 extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n         DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat,trace\");\n\n        JdbcStatContext context = new JdbcStatContext();\n        context.setTraceEnable(true);\n        JdbcStatManager.getInstance().setStatContext(context);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n        JdbcStatManager.getInstance().setStatContext(null);\n        super.tearDown();\n    }\n\n    public void test_basic() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n\n        conn.getTransactionInfo();\n        conn.getMetaData();\n        conn.setReadOnly(true);\n        assertEquals(true, conn.isReadOnly());\n\n        conn.setCatalog(\"xxx\");\n        assertEquals(\"xxx\", conn.getCatalog());\n\n        conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n        assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn.getTransactionIsolation());\n\n        conn.getWarnings();\n        conn.clearWarnings();\n        conn.getTypeMap();\n        conn.setTypeMap(null);\n\n        conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);\n        assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, conn.getHoldability());\n\n        conn.setSavepoint();\n        conn.setSavepoint(\"savepoint\");\n        conn.rollback();\n        {\n            Exception error = null;\n            try {\n                conn.rollback(null);\n            } catch (SQLException e) {\n                error = e;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                conn.releaseSavepoint(null);\n            } catch (SQLException e) {\n                error = e;\n            }\n            assertNotNull(error);\n        }\n        conn.createBlob();\n        conn.createClob();\n        conn.createNClob();\n        conn.createSQLXML();\n        conn.isValid(200);\n        conn.setClientInfo(new Properties());\n        conn.setClientInfo(\"xx\", \"11\");\n        conn.getClientInfo(\"xx\");\n        conn.getClientInfo();\n\n        conn.createArrayOf(\"int\", new Object[0]);\n        conn.createStruct(\"int\", new Object[0]);\n\n        conn.addConnectionEventListener(null);\n        conn.removeConnectionEventListener(null);\n        conn.addStatementEventListener(null);\n        conn.removeStatementEventListener(null);\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/ConnectionTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidStatementConnection;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatContext;\nimport com.alibaba.druid.stat.JdbcStatManager;\n\nimport java.sql.Connection;\nimport java.sql.Date;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectionTest4 extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n         DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat,trace\");\n        dataSource.setPoolPreparedStatements(true);\n\n        JdbcStatContext context = new JdbcStatContext();\n        context.setTraceEnable(true);\n        JdbcStatManager.getInstance().setStatContext(context);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n        JdbcStatManager.getInstance().setStatContext(null);\n        super.tearDown();\n    }\n\n    public void test_basic() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        assertNull(conn.unwrap(Date.class));\n        assertNull(conn.unwrap(null));\n        Connection statementConn = ((ConnectionProxy) conn.getConnection()).getRawObject();\n        assertTrue(statementConn instanceof DruidStatementConnection);\n        assertEquals(((DruidStatementConnection) statementConn).getConnection(), conn.unwrap(Connection.class));\n\n        assertEquals(false, conn.isWrapperFor(null));\n        assertEquals(true, conn.isWrapperFor(DruidPooledConnection.class));\n        assertEquals(true, conn.isWrapperFor(Connection.class));\n\n        assertEquals(\"SELECT 1\", conn.nativeSQL(\"SELECT 1\"));\n\n        conn.toString();\n\n        conn.close();\n        conn.toString();\n    }\n\n    public void test_prepareStatement_error() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(\"SELECT 1\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_error2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_error3() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                        ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_error4() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(null, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                        ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_error5() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(null, new int[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_error6() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(\"SELECT 1\", new int[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_error7() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(\"SELECT 1\", new String[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_error8() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(\"SELECT 1\", 0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        MockPreparedStatement raw = null;\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY);\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.close();\n        }\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY);\n            assertSame(raw, stmt.unwrap(MockPreparedStatement.class));\n            stmt.close();\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        MockPreparedStatement raw = null;\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.close();\n        }\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY,\n                    ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            assertSame(raw, stmt.unwrap(MockPreparedStatement.class));\n            stmt.close();\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        MockPreparedStatement raw = null;\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new int[0]);\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.close();\n        }\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new int[0]);\n            assertEquals(raw, stmt.unwrap(MockPreparedStatement.class));\n            stmt.close();\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_3() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        MockPreparedStatement raw = null;\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new String[0]);\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.close();\n        }\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", new String[0]);\n            assertEquals(raw, stmt.unwrap(MockPreparedStatement.class));\n            stmt.close();\n        }\n\n        conn.close();\n    }\n\n    public void test_prepareStatement_4() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        MockPreparedStatement raw = null;\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", 0);\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.close();\n        }\n        {\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\", 0);\n            assertEquals(raw, stmt.unwrap(MockPreparedStatement.class));\n            stmt.close();\n        }\n\n        conn.close();\n    }\n\n    public void test_preCall_error() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.prepareCall(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                        ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_preCall_error_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.prepareCall(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_preCall_error_2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.prepareCall(\"SELECT 1\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_prepCall() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        MockPreparedStatement raw = null;\n        {\n            PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.close();\n        }\n        {\n            PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            assertEquals(raw, stmt.unwrap(MockPreparedStatement.class));\n            stmt.close();\n        }\n\n        conn.close();\n    }\n\n    public void test_prepCall_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        MockPreparedStatement raw = null;\n        {\n            PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY);\n            raw = stmt.unwrap(MockPreparedStatement.class);\n            stmt.close();\n        }\n        {\n            PreparedStatement stmt = conn.prepareCall(\"SELECT 1\", ResultSet.TYPE_FORWARD_ONLY,\n                    ResultSet.CONCUR_READ_ONLY);\n            assertEquals(raw, stmt.unwrap(MockPreparedStatement.class));\n            stmt.close();\n        }\n\n        conn.getConnectionHolder().toString();\n        conn.getConnectionHolder().setLastActiveTimeMillis(0);\n        conn.getConnectionHolder().toString();\n        conn.getConnectionHolder().getUseCount();\n        conn.getConnectionHolder().getTimeMillis();\n\n        conn.close();\n    }\n\n    public void test_create() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.createStatement();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_create_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,\n                        ResultSet.HOLD_CURSORS_OVER_COMMIT);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_create_2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_setAutoCommit() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getAutoCommit();\n        conn.setAutoCommit(true);\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.setAutoCommit(false);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_commit() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.commit();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_rollback() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.setAutoCommit(false);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"SELECT 1\");\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.rollback();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_rollback_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.rollback(null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_releaseSavepoint_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n        {\n            SQLException error = null;\n            try {\n                conn.releaseSavepoint(null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_addListenerError() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n        {\n            Exception error = null;\n            try {\n                conn.addConnectionEventListener(null);\n            } catch (IllegalStateException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_addListenerError2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n        {\n            Exception error = null;\n            try {\n                conn.addStatementEventListener(null);\n            } catch (IllegalStateException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_removeConnectionEventListener() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n        {\n            Exception error = null;\n            try {\n                conn.removeConnectionEventListener(null);\n            } catch (IllegalStateException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_removeStatementEventListener() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n        {\n            Exception error = null;\n            try {\n                conn.removeStatementEventListener(null);\n            } catch (IllegalStateException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_checkOpen_error() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n        {\n            Exception error = null;\n            try {\n                conn.checkState();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/ConnectionTest5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatContext;\nimport com.alibaba.druid.stat.JdbcStatManager;\n\nimport javax.sql.ConnectionEvent;\nimport javax.sql.ConnectionEventListener;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectionTest5 extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n         DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(true);\n        dataSource.setTestOnReturn(true);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat,trace\");\n\n        JdbcStatContext context = new JdbcStatContext();\n        context.setTraceEnable(true);\n        JdbcStatManager.getInstance().setStatContext(context);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n        JdbcStatManager.getInstance().setStatContext(null);\n        super.tearDown();\n    }\n\n    public void test_basic() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        conn.close();\n\n        assertEquals(true, dataSource.isResetStatEnable());\n        dataSource.setResetStatEnable(false);\n        assertEquals(false, dataSource.isResetStatEnable());\n        assertEquals(1, dataSource.getConnectCount());\n        dataSource.resetStat();\n        assertEquals(1, dataSource.getConnectCount());\n\n        dataSource.setResetStatEnable(true);\n        dataSource.resetStat();\n        assertEquals(0, dataSource.getConnectCount());\n    }\n\n    public void test_handleException() throws Exception {\n        DruidPooledConnection conn = (DruidPooledConnection) dataSource.getConnection();\n        conn.close();\n\n        SQLException error = new SQLException();\n        try {\n            conn.handleException(error);\n        } catch (SQLException ex) {\n            assertEquals(error, ex);\n        }\n    }\n\n    public void test_handleException_2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        conn.getConnection().close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.handleException(new RuntimeException());\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_handleException_3() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        conn.getConnection().close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.handleException(new RuntimeException());\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        conn.close();\n    }\n\n    public void test_handleException_4() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        conn.getConnection().close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.prepareStatement(\"SELECT 1\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        assertEquals(true, conn.isClosed());\n    }\n\n    public void test_handleException_5() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        conn.addConnectionEventListener(new ConnectionEventListener() {\n            @Override\n            public void connectionClosed(ConnectionEvent event) {\n            }\n\n            @Override\n            public void connectionErrorOccurred(ConnectionEvent event) {\n            }\n\n        });\n        conn.close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.handleException(new RuntimeException());\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n    }\n\n    public void test_setClientInfo() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        conn.close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.setClientInfo(\"name\", \"xxx\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n    }\n\n    public void test_setClientInfo_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        conn.close();\n\n        {\n            SQLException error = null;\n            try {\n                conn.setClientInfo(new Properties());\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/DataSourceTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker;\nimport com.alibaba.druid.pool.vendor.NullExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatContext;\nimport com.alibaba.druid.stat.JdbcStatManager;\n\nimport javax.security.auth.callback.PasswordCallback;\n\nimport java.sql.SQLException;\nimport java.util.Collections;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DataSourceTest3 extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n         DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(true);\n        dataSource.setTestOnReturn(true);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n\n        JdbcStatContext context = new JdbcStatContext();\n        context.setTraceEnable(true);\n        JdbcStatManager.getInstance().setStatContext(context);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n        JdbcStatManager.getInstance().setStatContext(null);\n        super.tearDown();\n    }\n\n    public void test_prepareStatement_error() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        {\n            Exception error = null;\n            try {\n                dataSource.setUsername(\"xxx\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_error_1() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setPoolPreparedStatements(false);\n    }\n\n    public void test_change_maxWait() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        conn.close();\n        dataSource.setMaxWait(1);\n    }\n\n    public void test_change_minIdle() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setMinIdle(1);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    public void test_error_4() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setMaxIdle(1);\n    }\n\n    public void test_error_5() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setInitialSize(dataSource.getInitialSize());\n\n        {\n            Exception error = null;\n            try {\n                dataSource.setInitialSize(10);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_error_6() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setMaxActive(1);\n    }\n\n    public void test_error_7() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setPassword(dataSource.getPassword());\n        dataSource.setPassword(\"xx\");\n    }\n\n    public void test_change_connectProperties() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setConnectProperties(new Properties());\n    }\n\n    public void test_change_connectProperties_2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setConnectionProperties(\"x=12;;\");\n    }\n\n    public void test_getValidConnectionCheckerClassName() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.getValidConnectionCheckerClassName();\n    }\n\n    public void test_setConnectionInitSqls() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.setConnectionInitSqls(null);\n    }\n\n    public void test_setConnectionProperties() throws Exception {\n        dataSource.setConnectionProperties(null);\n        dataSource.setLogWriter(null);\n        dataSource.getLogWriter();\n\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n    }\n\n    public void test_error_10() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        {\n            Exception error = null;\n            try {\n                dataSource.addConnectionProperty(\"x\", \"11\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_error_11() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        dataSource.getUrl();\n\n        {\n            Exception error = null;\n            try {\n                dataSource.setUrl(\"x\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_setConnectionInitSqls_2() throws Exception {\n        dataSource.setConnectionInitSqls(Collections.emptyList());\n        dataSource.setConnectionInitSqls(Collections.singleton(null));\n    }\n\n    public void test_ValidConnectionChecker() throws Exception {\n        dataSource.getValidConnectionCheckerClassName();\n        dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker());\n        assertEquals(MySqlValidConnectionChecker.class.getName(),\n                dataSource.getValidConnectionCheckerClassName());\n    }\n\n    public void test_setConnectionInitSqls_1() throws Exception {\n        dataSource.setConnectionInitSqls(Collections.emptyList());\n        dataSource.setConnectionInitSqls(Collections.singleton(null));\n    }\n\n    public static class MyPasswordCallbackClassName extends PasswordCallback {\n        public MyPasswordCallbackClassName() {\n            super(\"password\", false);\n        }\n\n        /**\n         *\n         */\n        private static final long serialVersionUID = 1L;\n    }\n\n    public void test_setPasswordCallbackClassName() throws Exception {\n        dataSource.setPasswordCallbackClassName(MyPasswordCallbackClassName.class.getName());\n    }\n\n    public void test_error_12() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        {\n            Exception error = null;\n            try {\n                dataSource.setDriverClassName(\"\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_setExceptionSorter() throws Exception {\n        dataSource.setExceptionSorter(NullExceptionSorter.class.getName());\n    }\n\n    public void test_setProxyFilters() throws Exception {\n        dataSource.setProxyFilters(null);\n        dataSource.setFilters(null);\n        dataSource.setFilters(\"\");\n    }\n\n    public void test_error_validateConnection() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.close();\n\n        {\n            Exception error = null;\n            try {\n                dataSource.validateConnection(conn);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_error_validateConnection_2() throws Exception {\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n\n        conn.getConnection().close();\n\n        {\n            Exception error = null;\n            try {\n                dataSource.validateConnection(conn);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    public void test_error_validateConnection_3() throws Exception {\n        dataSource.setValidationQuery(null);\n        dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker());\n\n        DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);\n        dataSource.validateConnection(conn);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/DruidDataSourceFactoryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.pool.DruidDataSourceFactory;\nimport org.junit.jupiter.api.Test;\n\nimport javax.naming.RefAddr;\nimport javax.naming.Reference;\n\nimport java.util.Hashtable;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceFactoryTest {\n    @SuppressWarnings(\"serial\")\n    @Test\n    public void test_factory() throws Exception {\n        DruidDataSourceFactory factory = new DruidDataSourceFactory();\n\n        assertNull(factory.getObjectInstance(null, null, null, null));\n        assertNull(factory.getObjectInstance(new Reference(\"javax.sql.Date\"), null, null, null));\n\n        Reference ref = new Reference(\"javax.sql.DataSource\");\n        ref.add(new RefAddr(\"user\") {\n            @Override\n            public Object getContent() {\n                return null;\n            }\n\n        });\n        ref.add(new RefAddr(\"defaultReadOnly\") {\n            @Override\n            public Object getContent() {\n                return Boolean.TRUE;\n            }\n\n        });\n\n        factory.getObjectInstance(ref, null, null, new Hashtable<Object, Object>());\n    }\n\n    @Test\n    public void test_createDataSource() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(\"defaultAutoCommit\", \"true\");\n        properties.setProperty(\"defaultReadOnly\", \"true\");\n        properties.setProperty(\"defaultTransactionIsolation\", \"NONE\");\n        properties.setProperty(\"defaultCatalog\", \"cn\");\n        properties.setProperty(\"driverClassName\", \"com.alibaba.druid.mock.MockDriver\");\n        properties.setProperty(\"maxActive\", \"8\");\n        properties.setProperty(\"maxIdle\", \"8\");\n        properties.setProperty(\"minIdle\", \"3\");\n        properties.setProperty(\"initialSize\", \"1\");\n        properties.setProperty(\"maxWait\", \"-1\");\n        properties.setProperty(\"testOnBorrow\", \"true\");\n        properties.setProperty(\"testOnReturn\", \"true\");\n        properties.setProperty(\"timeBetweenEvictionRunsMillis\", \"3000\");\n        properties.setProperty(\"numTestsPerEvictionRun\", \"1\");\n        properties.setProperty(\"minEvictableIdleTimeMillis\", \"10000\");\n        properties.setProperty(\"testWhileIdle\", \"true\");\n        properties.setProperty(\"password\", \"xxx\");\n        properties.setProperty(\"url\", \"jdbc:mock:xxx\");\n        properties.setProperty(\"username\", \"user\");\n        properties.setProperty(\"validationQuery\", \"select 1\");\n        properties.setProperty(\"validationQueryTimeout\", \"30\");\n        properties.setProperty(\"initConnectionSqls\", \"select 1\");\n        properties.setProperty(\"accessToUnderlyingConnectionAllowed\", \"true\");\n        properties.setProperty(\"removeAbandoned\", \"true\");\n        properties.setProperty(\"removeAbandonedTimeout\", \"30\");\n        properties.setProperty(\"logAbandoned\", \"true\");\n        properties.setProperty(\"poolPreparedStatements\", \"true\");\n        properties.setProperty(\"maxOpenPreparedStatements\", \"200\");\n        properties.setProperty(\"connectionProperties\", \"x=1;y=2;;\");\n        properties.setProperty(\"filters\", \"stat;trace\");\n        properties.setProperty(\"exceptionSorter\", \"com.alibaba.druid.pool.vendor.NullExceptionSorter\");\n        properties.setProperty(\"exception-sorter-class-name\", \"com.alibaba.druid.pool.vendor.NullExceptionSorter\");\n\n        DruidDataSourceFactory.createDataSource(properties);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/MaxEvictableIdleTimeMillisTest.java",
    "content": "package com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.GetConnectionTimeoutException;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MaxEvictableIdleTimeMillisTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(50);\n        dataSource.setMinIdle(5);\n        dataSource.setMinEvictableIdleTimeMillis(10);\n        dataSource.setMaxEvictableIdleTimeMillis(100);\n        dataSource.setMaxWait(20);\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.setMaxEvictableIdleTimeMillis(1);\n        } catch (Exception ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertEquals(100, dataSource.getMaxEvictableIdleTimeMillis());\n    }\n\n    @Test\n    public void test_error2() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.setMaxEvictableIdleTimeMillis(1);\n        } catch (Exception ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertEquals(100, dataSource.getMaxEvictableIdleTimeMillis());\n    }\n\n    @Test\n    public void test_max() throws Exception {\n        connect(10);\n\n        assertEquals(10, dataSource.getPoolingCount());\n        Thread.sleep(20);\n        dataSource.shrink(true);\n        assertEquals(5, dataSource.getPoolingCount());\n\n        Thread.sleep(100);\n        dataSource.shrink(true);\n        assertEquals(0, dataSource.getPoolingCount());\n    }\n\n    public int connect(int count) throws Exception {\n        int successCount = 0;\n        Connection[] connections = new Connection[count];\n        for (int i = 0; i < count; ++i) {\n            try {\n                connections[i] = dataSource.getConnection();\n                successCount++;\n            } catch (GetConnectionTimeoutException e) {\n                // skip\n            }\n        }\n\n        for (int i = 0; i < count; ++i) {\n            JdbcUtils.close(connections[i]);\n        }\n\n        return successCount;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/MaxEvictableIdleTimeMillisTest2.java",
    "content": "package com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MaxEvictableIdleTimeMillisTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(50);\n        dataSource.setMinIdle(5);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            dataSource.setMinEvictableIdleTimeMillis(20);\n            dataSource.setMaxEvictableIdleTimeMillis(30);\n            dataSource.setMinEvictableIdleTimeMillis(100);\n            dataSource.setMaxWait(20);\n            dataSource.init();\n        } catch (Exception ex) {\n            error = ex;\n            ex.printStackTrace();\n        }\n        assertNotNull(error);\n        assertTrue(dataSource.isInited());\n        assertEquals(30, dataSource.getMaxEvictableIdleTimeMillis());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/MaxPhyTimeMillisTest.java",
    "content": "package com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.GetConnectionTimeoutException;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MaxPhyTimeMillisTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(50);\n        dataSource.setMinIdle(5);\n        dataSource.setMinEvictableIdleTimeMillis(10);\n        dataSource.setPhyTimeoutMillis(100);\n        dataSource.setMaxWait(20);\n        dataSource.init();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_max() throws Exception {\n        connect(10);\n\n        assertEquals(10, dataSource.getPoolingCount());\n        Thread.sleep(20);\n        dataSource.shrink(true);\n        assertEquals(5, dataSource.getPoolingCount());\n\n        Thread.sleep(100);\n        dataSource.shrink(true);\n        assertEquals(0, dataSource.getPoolingCount());\n    }\n\n    public int connect(int count) throws Exception {\n        int successCount = 0;\n        Connection[] connections = new Connection[count];\n        for (int i = 0; i < count; ++i) {\n            try {\n                connections[i] = dataSource.getConnection();\n                successCount++;\n            } catch (GetConnectionTimeoutException e) {\n                // skip\n            }\n        }\n\n        for (int i = 0; i < count; ++i) {\n            JdbcUtils.close(connections[i]);\n        }\n\n        return successCount;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableCallableStatementTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidConnectionHolder;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledCallableStatement;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\nimport com.alibaba.druid.pool.PreparedStatementHolder;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PoolableCallableStatementTest {\n    private DruidDataSource dataSource = new DruidDataSource();\n    protected DruidPooledConnection conn;\n    protected MockCallableStatement raw;\n    protected DruidPooledCallableStatement stmt;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        MockConnection mockConn = new MockConnection();\n        DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn, 0);\n        conn = new DruidPooledConnection(connHolder);\n        raw = new MockCallableStatement(null, null);\n        stmt = new DruidPooledCallableStatement(conn, new PreparedStatementHolder(new PreparedStatementKey(\"\", null,\n                null, 0, 0,\n                0), raw)) {\n            protected SQLException checkException(Throwable error) throws SQLException {\n                if (error instanceof SQLException) {\n                    return (SQLException) error;\n                }\n\n                return new SQLException(error);\n            }\n        };\n\n        assertEquals(0, raw.getOutParameters().size());\n        stmt.registerOutParameter(1, Types.INTEGER);\n        assertEquals(1, raw.getOutParameters().size());\n\n        stmt.registerOutParameter(2, Types.DECIMAL, 10);\n        assertEquals(2, raw.getOutParameters().size());\n    }\n\n    @Test\n    public void test_executeQuery_large() throws Exception {\n        for (int i = 0; i < 1000 * 1000; ++i) {\n            ResultSet rs = stmt.executeQuery();\n            rs.close();\n        }\n    }\n\n    @Test\n    public void test_basic() throws Exception {\n        assertEquals(raw, stmt.getCallableStatementRaw());\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_callableStmt() throws Exception {\n        assertTrue(stmt.wasNull() == false);\n        stmt.getString(1);\n        assertTrue(stmt.wasNull());\n        stmt.getBoolean(1);\n        stmt.getByte(1);\n        stmt.getShort(1);\n        stmt.getInt(1);\n        stmt.getLong(1);\n        stmt.getFloat(1);\n        stmt.getDouble(1);\n        stmt.getBigDecimal(1);\n        stmt.getBigDecimal(1, 1);\n        stmt.getBytes(1);\n        stmt.getDate(1);\n        stmt.getTime(1);\n        stmt.getTimestamp(1);\n        stmt.getObject(1);\n        stmt.getRef(1);\n        stmt.getBlob(1);\n\n        stmt.getString(\"1\");\n        stmt.getBoolean(\"1\");\n        stmt.getByte(\"1\");\n        stmt.getShort(\"1\");\n        stmt.getInt(\"1\");\n        stmt.getLong(\"1\");\n        stmt.getFloat(\"1\");\n        stmt.getDouble(\"1\");\n        stmt.getBigDecimal(\"1\");\n        stmt.getBytes(\"1\");\n        stmt.getDate(\"1\");\n        stmt.getTime(\"1\");\n        stmt.getTimestamp(\"1\");\n        stmt.getObject(\"1\");\n        stmt.getRef(\"1\");\n        stmt.getBlob(\"1\");\n    }\n\n    @Test\n    public void test_getByLabel_error() {\n        {\n            SQLException error = null;\n            try {\n                stmt.getTimestamp(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // ////////////////\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getString(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBoolean(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getByte(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getShort(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getInt(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getLong(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getFloat(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDouble(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBigDecimal(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBytes(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDate(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTime(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTimestamp(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getObject(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getRef(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBlob(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_get_error() {\n        {\n            SQLException error = null;\n            try {\n                stmt.getString(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBoolean(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getByte(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getShort(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getInt(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getLong(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getFloat(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDouble(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBigDecimal(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBigDecimal(0, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBytes(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDate(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTime(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getObject(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getRef(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getBlob(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n    }\n\n    @Test\n    public void test_getNClob() throws Exception {\n        stmt.getNClob(1);\n        stmt.getNClob(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getNClob(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getNClob(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getNString() throws Exception {\n        stmt.getNString(1);\n        stmt.getNString(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getNString(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getNString(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getNCharacterStream() throws Exception {\n        stmt.getNCharacterStream(1);\n        stmt.getNCharacterStream(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getNCharacterStream(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getNCharacterStream(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getCharacterStream() throws Exception {\n        stmt.getCharacterStream(1);\n        stmt.getCharacterStream(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getCharacterStream(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getCharacterStream(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateCharacterStream_2() throws Exception {\n        stmt.setCharacterStream(1, (Reader) null, 1L);\n        stmt.setCharacterStream(\"1\", (Reader) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCharacterStream(\"0\", (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCharacterStream(0, (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNClob() throws Exception {\n        stmt.setNClob(1, (Reader) null);\n        stmt.setNClob(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNClob(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNClob(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setClob() throws Exception {\n        stmt.setClob(1, (Reader) null);\n        stmt.setClob(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setClob(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setClob(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNCharacterStream() throws Exception {\n        stmt.setNCharacterStream(1, (Reader) null);\n        stmt.setNCharacterStream(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNCharacterStream(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNCharacterStream(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setCharacterStream() throws Exception {\n        stmt.setCharacterStream(1, (Reader) null);\n        stmt.setCharacterStream(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCharacterStream(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCharacterStream(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBinaryStream() throws Exception {\n        stmt.setBinaryStream(1, (InputStream) null);\n        stmt.setBinaryStream(\"1\", (InputStream) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBinaryStream(\"0\", (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBinaryStream(0, (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBinaryStream_1() throws Exception {\n        stmt.setBinaryStream(1, (InputStream) null, 1);\n        stmt.setBinaryStream(\"1\", (InputStream) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBinaryStream(\"0\", (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBinaryStream(0, (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBinaryStream_2() throws Exception {\n        stmt.setBinaryStream(1, (InputStream) null, 1L);\n        stmt.setBinaryStream(\"1\", (InputStream) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBinaryStream(\"0\", (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBinaryStream(0, (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setAsciiStream() throws Exception {\n        stmt.setAsciiStream(1, (InputStream) null);\n        stmt.setAsciiStream(\"1\", (InputStream) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setAsciiStream(\"0\", (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setAsciiStream(0, (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBlob() throws Exception {\n        stmt.setBlob(1, (InputStream) null);\n        stmt.setBlob(\"1\", (InputStream) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBlob(\"0\", (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBlob(0, (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setClob_1() throws Exception {\n        stmt.setClob(1, (Clob) null);\n        stmt.setClob(\"1\", (Clob) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setClob(\"0\", (Clob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setClob(0, (Clob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setClob_2() throws Exception {\n        stmt.setClob(1, (Reader) null, 1L);\n        stmt.setClob(\"1\", (Reader) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setClob(\"0\", (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setClob(0, (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setAsciiStream_1() throws Exception {\n        stmt.setAsciiStream(1, (InputStream) null, 1L);\n        stmt.setAsciiStream(\"1\", (InputStream) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setAsciiStream(\"0\", (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setAsciiStream(0, (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNull() throws Exception {\n        stmt.setNull(1, Types.INTEGER, \"Int\");\n        stmt.setNull(\"1\", Types.INTEGER, \"Int\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNull(\"0\", Types.INTEGER, \"Int\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNull(0, Types.INTEGER, \"Int\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setTimestamp() throws Exception {\n        stmt.setTimestamp(1, (Timestamp) null);\n        stmt.setTimestamp(\"1\", (Timestamp) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTimestamp(\"0\", (Timestamp) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTimestamp(0, (Timestamp) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setTimestamp_1() throws Exception {\n        stmt.setTimestamp(1, (Timestamp) null, null);\n        stmt.setTimestamp(\"1\", (Timestamp) null, null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTimestamp(\"0\", (Timestamp) null, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTimestamp(0, (Timestamp) null, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setTime() throws Exception {\n        stmt.setTime(1, (Time) null);\n        stmt.setTime(\"1\", (Time) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTime(\"0\", (Time) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTime(0, (Time) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setTime_1() throws Exception {\n        stmt.setTime(1, (Time) null, null);\n        stmt.setTime(\"1\", (Time) null, null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTime(\"0\", (Time) null, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTime(0, (Time) null, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setDate() throws Exception {\n        stmt.setDate(1, (Date) null);\n        stmt.setDate(\"1\", (Date) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDate(\"0\", (Date) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDate(0, (Date) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setDate_1() throws Exception {\n        stmt.setDate(1, (Date) null, null);\n        stmt.setDate(\"1\", (Date) null, null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDate(\"0\", (Date) null, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDate(0, (Date) null, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setCharacterStream_1() throws Exception {\n        stmt.setCharacterStream(1, (Reader) null, 1);\n        stmt.setCharacterStream(\"1\", (Reader) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCharacterStream(\"0\", (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCharacterStream(0, (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setObject() throws Exception {\n        stmt.setObject(1, null);\n        stmt.setObject(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setObject(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setObject(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setObject_1() throws Exception {\n        stmt.setObject(1, null, Types.INTEGER);\n        stmt.setObject(\"1\", null, Types.INTEGER);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setObject(\"0\", null, Types.INTEGER);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setObject(0, null, Types.INTEGER);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setObject_2() throws Exception {\n        stmt.setObject(1, null, Types.INTEGER, 2);\n        stmt.setObject(\"1\", null, Types.INTEGER, 2);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setObject(\"0\", null, Types.INTEGER, 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setObject(0, null, Types.INTEGER, 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setAsciiStream_2() throws Exception {\n        stmt.setAsciiStream(1, (InputStream) null, 1);\n        stmt.setAsciiStream(\"1\", (InputStream) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setAsciiStream(\"0\", (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setAsciiStream(0, (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBytes() throws Exception {\n        stmt.setBytes(1, null);\n        stmt.setBytes(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBytes(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBytes(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setString() throws Exception {\n        stmt.setString(1, null);\n        stmt.setString(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setString(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setString(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBigDecimal() throws Exception {\n        stmt.setBigDecimal(1, null);\n        stmt.setBigDecimal(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBigDecimal(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBigDecimal(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setDouble() throws Exception {\n        stmt.setDouble(1, 1.0D);\n        stmt.setDouble(\"1\", 1.0D);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDouble(\"0\", 1.0D);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDouble(0, 1.0D);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setFloat() throws Exception {\n        stmt.setFloat(1, 1.0F);\n        stmt.setFloat(\"1\", 1.0F);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setFloat(\"0\", 1.0F);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setFloat(0, 1.0F);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setLong() throws Exception {\n        stmt.setLong(1, 2);\n        stmt.setLong(\"1\", 2);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setLong(\"0\", 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setLong(0, 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setInt() throws Exception {\n        stmt.setInt(1, 2);\n        stmt.setInt(\"1\", 2);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setInt(\"0\", 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setInt(0, 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setShort() throws Exception {\n        stmt.setShort(1, Short.MAX_VALUE);\n        stmt.setShort(\"1\", Short.MAX_VALUE);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setShort(\"0\", Short.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setShort(0, Short.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setByte() throws Exception {\n        stmt.setByte(1, Byte.MAX_VALUE);\n        stmt.setByte(\"1\", Byte.MAX_VALUE);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setByte(\"0\", Byte.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setByte(0, Byte.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getClob() throws Exception {\n        stmt.getClob(1);\n        stmt.getClob(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getClob(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getClob(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getArray() throws Exception {\n        stmt.getArray(1);\n        stmt.getArray(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getArray(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getArray(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getDate() throws Exception {\n        stmt.getDate(1);\n        stmt.getDate(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDate(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDate(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getDate_1() throws Exception {\n        stmt.getDate(1, null);\n        stmt.getDate(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDate(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getDate(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getTime() throws Exception {\n        stmt.getTime(1);\n        stmt.getTime(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTime(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTime(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getTime_1() throws Exception {\n        stmt.getTime(1, null);\n        stmt.getTime(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTime(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTime(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getTimestamp() throws Exception {\n        stmt.getTimestamp(1);\n        stmt.getTimestamp(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTimestamp(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTimestamp(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getTimestamp_1() throws Exception {\n        stmt.getTimestamp(1, null);\n        stmt.getTimestamp(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTimestamp(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getTimestamp(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getURL() throws Exception {\n        stmt.getURL(1);\n        stmt.getURL(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getURL(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getURL(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBlob_1() throws Exception {\n        stmt.setBlob(1, (Blob) null);\n        stmt.setBlob(\"1\", (Blob) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBlob(\"0\", (Blob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBlob(0, (Blob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setSQLXML() throws Exception {\n        stmt.setSQLXML(1, (SQLXML) null);\n        stmt.setSQLXML(\"1\", (SQLXML) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setSQLXML(\"0\", (SQLXML) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setSQLXML(0, (SQLXML) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getSQLXML() throws Exception {\n        stmt.getSQLXML(1);\n        stmt.getSQLXML(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getSQLXML(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getSQLXML(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBlob_2() throws Exception {\n        stmt.setBlob(1, (InputStream) null, 1L);\n        stmt.setBlob(\"1\", (InputStream) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBlob(\"0\", (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBlob(0, (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNClob_1() throws Exception {\n        stmt.setNClob(1, (Reader) null, 1L);\n        stmt.setNClob(\"1\", (Reader) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNClob(\"0\", (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNClob(0, (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNCharacterStream_1() throws Exception {\n        stmt.setNCharacterStream(1, (Reader) null, 1L);\n        stmt.setNCharacterStream(\"1\", (Reader) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNCharacterStream(\"0\", (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNCharacterStream(0, (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setRowId() throws Exception {\n        stmt.setRowId(1, (RowId) null);\n        stmt.setRowId(\"1\", (RowId) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setRowId(\"0\", (RowId) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setRowId(0, (RowId) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getRowId() throws Exception {\n        stmt.getRowId(1);\n        stmt.getRowId(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getRowId(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getRowId(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNString() throws Exception {\n        stmt.setNString(1, (String) null);\n        stmt.setNString(\"1\", (String) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNString(\"0\", (String) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNString(0, (String) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        stmt.getObject(1, (java.util.Map) null);\n        stmt.getObject(\"1\", (java.util.Map) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getObject(0, (java.util.Map) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getObject(\"0\", (java.util.Map) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBoolean() throws Exception {\n        stmt.setBoolean(1, true);\n        stmt.setBoolean(\"1\", true);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBoolean(\"0\", true);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBoolean(0, true);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setURL() throws Exception {\n        stmt.setURL(1, null);\n        stmt.setURL(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setURL(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setURL(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNClob_2() throws Exception {\n        stmt.setNClob(1, (NClob) null);\n        stmt.setNClob(\"1\", (NClob) null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNClob(\"0\", (NClob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNClob(0, (NClob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNull_1() throws Exception {\n        stmt.setNull(1, Types.INTEGER);\n        stmt.setNull(\"1\", Types.INTEGER);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNull(\"0\", Types.INTEGER);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNull(0, Types.INTEGER);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_registerOutParameter() throws Exception {\n        stmt.registerOutParameter(1, Types.INTEGER, \"Int\");\n        stmt.registerOutParameter(\"1\", Types.INTEGER, \"Int\");\n\n        {\n            SQLException error = null;\n            try {\n                stmt.registerOutParameter(\"0\", Types.INTEGER, \"Int\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.registerOutParameter(0, Types.INTEGER, \"Int\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_registerOutParameter_1() throws Exception {\n        stmt.registerOutParameter(1, Types.INTEGER, 2);\n        stmt.registerOutParameter(\"1\", Types.INTEGER, 2);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.registerOutParameter(\"0\", Types.INTEGER, 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.registerOutParameter(0, Types.INTEGER, 2);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_registerOutParameter_2() throws Exception {\n        stmt.registerOutParameter(1, Types.INTEGER);\n        stmt.registerOutParameter(\"1\", Types.INTEGER);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.registerOutParameter(\"0\", Types.INTEGER);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.registerOutParameter(0, Types.INTEGER);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolablePreparedStatementTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidConnectionHolder;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\nimport com.alibaba.druid.pool.PreparedStatementHolder;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.sql.Date;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.sql.Types;\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PoolablePreparedStatementTest {\n    protected MockPreparedStatement raw;\n    protected DruidPooledPreparedStatement stmt;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        MockConnection mockConn = new MockConnection();\n        DruidConnectionHolder connHolder = new DruidConnectionHolder(dataSource, mockConn, 0);\n        DruidPooledConnection conn = new DruidPooledConnection(connHolder);\n\n        raw = new MockPreparedStatement(null, null);\n        stmt = new DruidPooledPreparedStatement(conn, new PreparedStatementHolder(new PreparedStatementKey(\"\", null,\n                null, 0, 0,\n                0), raw)) {\n            protected SQLException checkException(Throwable error) throws SQLException {\n                if (error instanceof SQLException) {\n                    return (SQLException) error;\n                }\n\n                return new SQLException(error);\n            }\n        };\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        stmt.clearParameters();\n        assertEquals(0, raw.getParameters().size());\n    }\n\n    @Test\n    public void test_basic() throws Exception {\n        assertEquals(raw, stmt.getRawPreparedStatement());\n        assertEquals(raw, stmt.getRawStatement());\n    }\n\n    @Test\n    public void test_setBoolean() throws Exception {\n        stmt.setBoolean(1, true);\n\n        assertEquals(Boolean.TRUE, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBoolean(0, true);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setNull() throws Exception {\n        stmt.setNull(1, Types.INTEGER);\n\n        assertEquals(null, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setNull(0, Types.INTEGER);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setByte() throws Exception {\n        stmt.setByte(1, (byte) 23);\n\n        assertEquals(new Byte((byte) 23), raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setByte(0, Byte.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setShort() throws Exception {\n        stmt.setShort(1, Short.MAX_VALUE);\n\n        assertEquals(new Short(Short.MAX_VALUE), raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setShort(0, Short.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setInt() throws Exception {\n        stmt.setInt(1, Integer.MAX_VALUE);\n\n        assertEquals(new Integer(Integer.MAX_VALUE), raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setInt(0, Integer.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setLong() throws Exception {\n        stmt.setLong(1, Long.MAX_VALUE);\n\n        assertEquals(new Long(Long.MAX_VALUE), raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setLong(0, Long.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setFloat() throws Exception {\n        stmt.setFloat(1, Float.MAX_VALUE);\n\n        assertEquals(new Float(Float.MAX_VALUE), raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setFloat(0, Float.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setDouble() throws Exception {\n        stmt.setDouble(1, Double.MAX_VALUE);\n\n        assertEquals(new Double(Double.MAX_VALUE), raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDouble(0, Double.MAX_VALUE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBigDecimal() throws Exception {\n        stmt.setBigDecimal(1, BigDecimal.TEN);\n\n        assertEquals(BigDecimal.TEN, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBigDecimal(0, BigDecimal.TEN);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setString() throws Exception {\n        stmt.setString(1, \"中国\");\n\n        assertEquals(\"中国\", raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setString(0, \"中国\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBytes() throws Exception {\n        byte[] bytes = \"中国\".getBytes();\n        stmt.setBytes(1, bytes);\n\n        assertEquals(true, Arrays.equals(bytes, (byte[]) raw.getParameters().get(0)));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBytes(0, bytes);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setDate() throws Exception {\n        Date value = new Date(System.currentTimeMillis());\n        stmt.setDate(1, value);\n\n        assertEquals(value, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setDate(0, value);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setTimestamp() throws Exception {\n        Timestamp value = new Timestamp(System.currentTimeMillis());\n        stmt.setTimestamp(1, value);\n\n        assertEquals(value, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setTimestamp(0, value);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setAsciiStream() throws Exception {\n        InputStream value = null;\n        stmt.setAsciiStream(1, value);\n\n        assertEquals(value, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setAsciiStream(0, value);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_setUnicodeStream() throws Exception {\n        InputStream value = null;\n        stmt.setUnicodeStream(1, value, 0);\n\n        assertEquals(value, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setUnicodeStream(0, value, 0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setBinaryStream() throws Exception {\n        InputStream value = null;\n        stmt.setBinaryStream(1, value, 0);\n\n        assertEquals(value, raw.getParameters().get(0));\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setBinaryStream(0, value, 0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateCharacterStream_2() throws Exception {\n        stmt.setCharacterStream(1, (Reader) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCharacterStream(0, (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setRef() throws Exception {\n        stmt.setRef(1, null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setRef(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_setArray() throws Exception {\n        stmt.setArray(1, null);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setArray(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableStatementTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.pool.DruidPooledStatement;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PoolableStatementTest {\n    protected Statement raw;\n    protected DruidPooledStatement stmt;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        raw = new MockStatement(null);\n        stmt = new DruidPooledStatement(null, raw) {\n            protected SQLException checkException(Throwable error) throws SQLException {\n                if (error instanceof SQLException) {\n                    return (SQLException) error;\n                }\n\n                return new SQLException(error);\n            }\n        };\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n    }\n\n    @Test\n    public void test_basic() throws Exception {\n        assertEquals(raw, stmt.getStatement());\n        assertEquals(null, stmt.getPoolableConnection());\n        assertEquals(null, stmt.getConnection());\n        assertEquals(false, stmt.isPoolable());\n        stmt.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableStatementTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledStatement;\nimport com.alibaba.druid.pool.vendor.NullExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatContext;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.CallableStatement;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PoolableStatementTest2 {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat,trace\");\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setExceptionSorterClassName(null);\n\n        assertTrue(dataSource.getExceptionSorter() instanceof NullExceptionSorter);\n        dataSource.setExceptionSorterClassName(\"\");\n        assertTrue(dataSource.getExceptionSorter() instanceof NullExceptionSorter);\n\n        JdbcStatContext context = new JdbcStatContext();\n        context.setTraceEnable(true);\n        JdbcStatManager.getInstance().setStatContext(context);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        assertEquals(true, dataSource.getCreateTimespanNano() > 0);\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n        JdbcStatManager.getInstance().setStatContext(null);\n    }\n\n    @Test\n    public void test_dupClose() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n        stmt.close();\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n        stmt.executeUpdate(\"SET @VAR = 1\");\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeUpdate(\"SET @VAR = 1\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute(\"SET @VAR = 1\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeQuery_error() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeQuery(\"SELECT 1\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_setEscapeProcessing() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setEscapeProcessing(true);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setEscapeProcessing(true);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getMaxFieldSize() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setMaxFieldSize(23);\n        assertEquals(23, stmt.getMaxFieldSize());\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getMaxFieldSize();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setMaxFieldSize(23);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_QueryTimeout() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setQueryTimeout(33);\n        assertEquals(33, stmt.getQueryTimeout());\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getQueryTimeout();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setQueryTimeout(23);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_MaxRows() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setMaxRows(44);\n        assertEquals(44, stmt.getMaxRows());\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getMaxRows();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setMaxRows(23);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_FetchDirection() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setFetchDirection(144);\n        assertEquals(144, stmt.getFetchDirection());\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getFetchDirection();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setFetchDirection(23);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_FetchSize() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setFetchSize(144);\n        assertEquals(144, stmt.getFetchSize());\n\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getFetchSize();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setFetchSize(23);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_cancel() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.cancel();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.cancel();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getWarnings() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getWarnings();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getWarnings();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_clearWarnings() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.clearWarnings();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.clearWarnings();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_setCursorName() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setCursorName(\"c_name\");\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setCursorName(\"c_name\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getResultSet() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getResultSet();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getResultSet();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getUpdateCount() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getUpdateCount();\n        stmt.executeQuery(\"select 1\");\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getUpdateCount();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getMoreResults() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getMoreResults();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getMoreResults();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getResultSetConcurrency() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getResultSetConcurrency();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getResultSetConcurrency();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getResultSetType() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getResultSetType();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getResultSetType();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_addBatch() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.addBatch(\"select 1\");\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.addBatch(\"select 1\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_clearBatch() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.clearBatch();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.clearBatch();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeBatch() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.executeBatch();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeBatch();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getMoreResults_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getMoreResults(1);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getMoreResults(1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getGeneratedKeys() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getGeneratedKeys();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getGeneratedKeys();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getResultSetHoldability() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.getResultSetHoldability();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getResultSetHoldability();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.execute(\"SELECT 1\", new String[0]);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute(\"SELECT 1\", new String[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.execute(\"SELECT 1\", new int[0]);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute(\"SELECT 1\", new int[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.execute(\"SELECT 1\", Statement.NO_GENERATED_KEYS);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute(\"SELECT 1\", Statement.NO_GENERATED_KEYS);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.executeUpdate(\"SELECT 1\", new String[0]);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute(\"SELECT 1\", new String[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_2() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.executeUpdate(\"SELECT 1\", new int[0]);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute(\"SELECT 1\", new int[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.executeUpdate(\"SELECT 1\", Statement.NO_GENERATED_KEYS);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute(\"SELECT 1\", Statement.NO_GENERATED_KEYS);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getMeta() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"SELELCT 1\");\n\n        stmt.getMetaData();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getMetaData();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_getParameterMetaData() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"SELELCT 1\");\n\n        stmt.getParameterMetaData();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.getParameterMetaData();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_wasNull() throws Exception {\n        Connection conn = dataSource.getConnection();\n        CallableStatement stmt = conn.prepareCall(\"SELELCT 1\");\n\n        stmt.wasNull();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.wasNull();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeQuery() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\");\n\n        stmt.executeQuery();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeQuery();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_4() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\");\n\n        stmt.executeQuery();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeUpdate();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_execute_3() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"SELELCT 1\");\n\n        stmt.execute();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.execute();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_clearParameters() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"SELELCT 1\");\n\n        stmt.clearParameters();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.clearParameters();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_addBatch_1() throws Exception {\n        Connection conn = dataSource.getConnection();\n        PreparedStatement stmt = conn.prepareStatement(\"SELELCT 1\");\n\n        stmt.addBatch();\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.addBatch();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_5() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.executeUpdate(\"SET 1\", Statement.RETURN_GENERATED_KEYS);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeUpdate(\"SET 1\", Statement.RETURN_GENERATED_KEYS);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_6() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.executeUpdate(\"SET 1\", new String[0]);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeUpdate(\"SET 1\", new String[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_executeUpdate_7() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.executeUpdate(\"SET 1\", new int[0]);\n        ((DruidPooledStatement) stmt).getStatement().close();\n\n        {\n            SQLException error = null;\n            try {\n                stmt.executeUpdate(\"SET 1\", new int[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_setPoolable() throws Exception {\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n\n        stmt.setPoolable(true);\n\n        {\n            SQLException error = null;\n            try {\n                stmt.setPoolable(false);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableStatementTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidPooledStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\n\npublic class PoolableStatementTest3 {\n    @Test\n    public void test_clearResultSetError() throws Exception {\n        final MockResultSet rs = new MockResultSet(null) {\n            public void close() throws SQLException {\n                throw new SQLException();\n            }\n        };\n\n        DruidPooledStatement stmt = new DruidPooledStatement(null, null) {\n            public void close() throws SQLException {\n                addResultSetTrace(rs);\n                clearResultSet();\n            }\n        };\n        stmt.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/PoolableWrapperTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.PoolableWrapper;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PoolableWrapperTest {\n    @Test\n    public void test_isWrapper() throws Exception {\n        PoolableWrapper wrapper = new PoolableWrapper(new MockConnection());\n\n        assertEquals(false, wrapper.isWrapperFor(null));\n        assertEquals(true, wrapper.isWrapperFor(PoolableWrapper.class));\n        assertEquals(true, wrapper.isWrapperFor(MockConnection.class));\n    }\n\n    @Test\n    public void test_unwrap() throws Exception {\n        PoolableWrapper wrapper = new PoolableWrapper(new MockConnection());\n\n        assertNull(wrapper.unwrap(null));\n        assertEquals(true, wrapper.unwrap(PoolableWrapper.class) != null);\n        assertEquals(true, wrapper.unwrap(MockConnection.class) != null);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/PreparedStatementKeyTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.pool.DruidConnectionHolder;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey;\nimport com.alibaba.druid.pool.PreparedStatementHolder;\nimport com.alibaba.druid.pool.PreparedStatementPool;\nimport com.alibaba.druid.pool.PreparedStatementPool.MethodType;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PreparedStatementKeyTest {\n    @Test\n    public void test_equals_0() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", \"c1\", MethodType.M1);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x1\", \"c2\", MethodType.M1);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x1\", \"c3\", MethodType.M1);\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_2() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", \"c1\", MethodType.M1);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x2\", \"c1\", MethodType.M1);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x3\", \"c1\", MethodType.M1);\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_3() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", \"c1\", MethodType.M1);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x1\", \"c1\", MethodType.M2);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x1\", \"c1\", MethodType.M3);\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_4() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", \"c1\", MethodType.M1);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x1\", \"c2\", MethodType.M1);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x1\", null, MethodType.M1);\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_5() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", null, MethodType.M1);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x1\", null, MethodType.M2);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x1\", null, MethodType.M3);\n\n        k1.hashCode();\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_6() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", null, MethodType.M1);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x2\", null, MethodType.M1);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x3\", null, MethodType.M1);\n\n        k1.hashCode();\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_7() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", null, MethodType.M1, 0, 0);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x1\", null, MethodType.M1, 1, 0);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x2\", null, MethodType.M1, 0, 1);\n\n        k1.hashCode();\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_8() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", null, MethodType.M1, 0, 0, 0);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x1\", null, MethodType.M1, 0, 0, 1);\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x2\", null, MethodType.M1, 0, 1, 0);\n\n        k1.hashCode();\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_equals_9() throws Exception {\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", null, MethodType.M1, 2);\n        PreparedStatementKey k2 = new PreparedStatementKey(\"x1\", null, MethodType.M1, new int[]{});\n        PreparedStatementKey k3 = new PreparedStatementKey(\"x2\", null, MethodType.M1, new String[]{});\n\n        k1.hashCode();\n\n        assertFalse(k1.equals(k2));\n        assertFalse(k1.equals(k3));\n        assertFalse(k2.equals(k1));\n        assertFalse(k2.equals(k3));\n        assertFalse(k3.equals(k2));\n        assertFalse(k3.equals(k1));\n    }\n\n    @Test\n    public void test_contains() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        MockConnection conn = new MockConnection();\n        PreparedStatementKey k1 = new PreparedStatementKey(\"x1\", \"c1\", MethodType.M1);\n\n        PreparedStatementPool pool = new PreparedStatementPool(new DruidConnectionHolder(dataSource, conn, 0));\n        MockPreparedStatement raw = new MockPreparedStatement(null, null);\n        pool.put(new PreparedStatementHolder(k1, raw));\n\n        assertTrue(pool.get(k1) != null);\n        assertTrue(pool.get(k1) != null);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/ResultSetTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport com.alibaba.druid.pool.DruidPooledStatement;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.NClob;\nimport java.sql.Ref;\nimport java.sql.SQLException;\nimport java.sql.SQLXML;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ResultSetTest {\n    private DruidPooledStatement stmt;\n    private MockResultSet raw;\n    private DruidPooledResultSet resultSet;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        stmt = new DruidPooledStatement(null, null) {\n            protected SQLException checkException(Throwable error) throws SQLException {\n                if (error instanceof SQLException) {\n                    return (SQLException) error;\n                }\n\n                return new SQLException(error);\n            }\n        };\n\n        raw = new MockResultSet(null);\n        raw.getRows().add(new Object[]{null});\n        resultSet = new DruidPooledResultSet(stmt, raw);\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_get() throws Exception {\n        assertTrue(stmt == resultSet.getPoolableStatement());\n        assertTrue(raw == resultSet.getRawResultSet());\n\n        assertTrue(resultSet.next());\n        assertTrue(resultSet.wasNull() == false);\n        resultSet.getString(1);\n        assertTrue(resultSet.wasNull());\n        resultSet.getBoolean(1);\n        resultSet.getByte(1);\n        resultSet.getShort(1);\n        resultSet.getInt(1);\n        resultSet.getLong(1);\n        resultSet.getFloat(1);\n        resultSet.getDouble(1);\n        resultSet.getBigDecimal(1);\n        resultSet.getBigDecimal(1, 1);\n        resultSet.getBytes(1);\n        resultSet.getDate(1);\n        resultSet.getTime(1);\n        resultSet.getTimestamp(1);\n        resultSet.getAsciiStream(1);\n        resultSet.getUnicodeStream(1);\n        resultSet.getBinaryStream(1);\n\n        resultSet.getString(\"1\");\n        resultSet.getBoolean(\"1\");\n        resultSet.getByte(\"1\");\n        resultSet.getShort(\"1\");\n        resultSet.getInt(\"1\");\n        resultSet.getLong(\"1\");\n        resultSet.getFloat(\"1\");\n        resultSet.getDouble(\"1\");\n        resultSet.getBigDecimal(\"1\");\n        resultSet.getBigDecimal(\"1\", 1);\n        resultSet.getBytes(\"1\");\n        resultSet.getDate(\"1\");\n        resultSet.getTime(\"1\");\n        resultSet.getTimestamp(\"1\");\n        resultSet.getAsciiStream(\"1\");\n        resultSet.getUnicodeStream(\"1\");\n        resultSet.getBinaryStream(\"1\");\n    }\n\n    @Test\n    public void test_set() throws Exception {\n        long currentMillis = System.currentTimeMillis();\n\n        assertTrue(resultSet.next());\n\n        resultSet.updateNull(1);\n        assertNull(resultSet.getString(1));\n        resultSet.updateBoolean(1, true);\n        assertEquals(true, resultSet.getBoolean(1));\n\n        resultSet.updateByte(1, (byte) 12);\n        assertEquals(12, resultSet.getByte(1));\n\n        resultSet.updateShort(1, (short) 23);\n        assertEquals(23, resultSet.getShort(1));\n\n        resultSet.updateInt(1, 34);\n        assertEquals(34, resultSet.getInt(1));\n\n        resultSet.updateLong(1, 45);\n        assertEquals(45, resultSet.getLong(1));\n\n        resultSet.updateFloat(1, 1.0F);\n        assertEquals(true, 1.0F == resultSet.getFloat(1));\n\n        resultSet.updateDouble(1, 2.0D);\n        assertEquals(true, 2.0D == resultSet.getDouble(1));\n\n        resultSet.updateBigDecimal(1, new BigDecimal(\"33\"));\n        assertEquals(new BigDecimal(\"33\"), resultSet.getBigDecimal(1));\n\n        resultSet.updateString(1, \"xxx\");\n        assertEquals(\"xxx\", resultSet.getString(1));\n\n        resultSet.updateBytes(1, new byte[0]);\n        assertEquals(0, resultSet.getBytes(1).length);\n\n        resultSet.updateDate(1, new java.sql.Date(currentMillis));\n        assertEquals(new java.sql.Date(currentMillis), resultSet.getDate(1));\n\n        resultSet.updateTime(1, new java.sql.Time(1000));\n        assertEquals(new java.sql.Time(1000), resultSet.getTime(1));\n\n        resultSet.updateTimestamp(1, new java.sql.Timestamp(currentMillis));\n        assertEquals(new java.sql.Timestamp(currentMillis), resultSet.getTimestamp(1));\n    }\n\n    @Test\n    public void test_set_error() throws Exception {\n        long currentMillis = System.currentTimeMillis();\n\n        assertTrue(resultSet.next());\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNull(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBoolean(0, true);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateByte(0, (byte) 12);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateShort(0, (short) 23);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateInt(0, 34);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateLong(0, 45);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateFloat(0, 1.0F);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateDouble(0, 2.0D);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBigDecimal(0, new BigDecimal(\"33\"));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateString(0, \"xxx\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBytes(0, new byte[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateDate(0, new java.sql.Date(currentMillis));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateTime(0, new java.sql.Time(1000));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateTimestamp(0, new java.sql.Timestamp(currentMillis));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n    }\n\n    @Test\n    public void test_setByName() throws Exception {\n        long currentMillis = System.currentTimeMillis();\n\n        assertTrue(resultSet.next());\n\n        resultSet.updateNull(\"1\");\n        assertNull(resultSet.getString(1));\n        resultSet.updateBoolean(\"1\", true);\n        assertEquals(true, resultSet.getBoolean(\"1\"));\n\n        resultSet.updateByte(\"1\", (byte) 12);\n        assertEquals(12, resultSet.getByte(\"1\"));\n\n        resultSet.updateShort(\"1\", (short) 23);\n        assertEquals(23, resultSet.getShort(\"1\"));\n\n        resultSet.updateInt(\"1\", 34);\n        assertEquals(34, resultSet.getInt(\"1\"));\n\n        resultSet.updateLong(\"1\", 45);\n        assertEquals(45, resultSet.getLong(\"1\"));\n\n        resultSet.updateFloat(\"1\", 1.0F);\n        assertEquals(true, 1.0F == resultSet.getFloat(\"1\"));\n\n        resultSet.updateDouble(\"1\", 2.0D);\n        assertEquals(true, 2.0D == resultSet.getDouble(\"1\"));\n\n        resultSet.updateBigDecimal(\"1\", new BigDecimal(\"33\"));\n        assertEquals(new BigDecimal(\"33\"), resultSet.getBigDecimal(\"1\"));\n\n        resultSet.updateString(\"1\", \"xxx\");\n        assertEquals(\"xxx\", resultSet.getString(\"1\"));\n\n        resultSet.updateBytes(\"1\", new byte[0]);\n        assertEquals(0, resultSet.getBytes(\"1\").length);\n\n        resultSet.updateDate(\"1\", new java.sql.Date(currentMillis));\n        assertEquals(new java.sql.Date(currentMillis), resultSet.getDate(\"1\"));\n\n        resultSet.updateTime(\"1\", new java.sql.Time(1000));\n        assertEquals(new java.sql.Time(1000), resultSet.getTime(\"1\"));\n\n        resultSet.updateTimestamp(\"1\", new java.sql.Timestamp(currentMillis));\n        assertEquals(new java.sql.Timestamp(currentMillis), resultSet.getTimestamp(\"1\"));\n    }\n\n    @Test\n    public void test_updateByLabel_error() throws Exception {\n        long currentMillis = System.currentTimeMillis();\n\n        assertTrue(resultSet.next());\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNull(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBoolean(\"0\", true);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateByte(\"0\", (byte) 12);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateShort(\"0\", (short) 23);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateInt(\"0\", 34);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateLong(\"0\", 45);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateFloat(\"0\", 1.0F);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateDouble(\"0\", 2.0D);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBigDecimal(\"0\", new BigDecimal(\"33\"));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateString(\"0\", \"xxx\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBytes(\"0\", new byte[0]);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateDate(\"0\", new java.sql.Date(currentMillis));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateTime(\"0\", new java.sql.Time(1000));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateTimestamp(\"0\", new java.sql.Timestamp(currentMillis));\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n    }\n\n    @Test\n    public void test_updateBinaryStream() throws Exception {\n        resultSet.next();\n\n        resultSet.updateBinaryStream(1, (InputStream) null);\n        resultSet.updateBinaryStream(\"1\", (InputStream) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBinaryStream(\"0\", (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBinaryStream(0, (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateBinaryStream_2() throws Exception {\n        resultSet.next();\n\n        resultSet.updateBinaryStream(1, (InputStream) null, 1L);\n        resultSet.updateBinaryStream(\"1\", (InputStream) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBinaryStream(\"0\", (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBinaryStream(0, (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateCharacterStream() throws Exception {\n        resultSet.next();\n\n        resultSet.updateCharacterStream(1, (Reader) null);\n        resultSet.updateCharacterStream(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateCharacterStream(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateCharacterStream(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_update_blob() throws Exception {\n        resultSet.next();\n\n        resultSet.updateBlob(1, (InputStream) null);\n        resultSet.updateBlob(\"1\", (InputStream) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBlob(\"0\", (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBlob(0, (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_update_clob() throws Exception {\n        resultSet.next();\n\n        resultSet.updateClob(1, (Reader) null);\n        resultSet.updateClob(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateClob(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateClob(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_update_nclob() throws Exception {\n        resultSet.next();\n\n        resultSet.updateNClob(1, (Reader) null);\n        resultSet.updateNClob(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNClob(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNClob(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_update_nclob_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateNClob(1, (Reader) null, 1);\n        resultSet.updateNClob(\"1\", (Reader) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNClob(\"0\", (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNClob(0, (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_update_clob_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateClob(1, (Reader) null, 1);\n        resultSet.updateClob(\"1\", (Reader) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateClob(\"0\", (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateClob(0, (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_update_blob_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateBlob(1, (InputStream) null, 1);\n        resultSet.updateBlob(\"1\", (InputStream) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBlob(\"0\", (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBlob(0, (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateCharacterStream_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateCharacterStream(1, (Reader) null, 1);\n        resultSet.updateCharacterStream(\"1\", (Reader) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateCharacterStream(\"0\", (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateCharacterStream(0, (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateAsciiStream_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateAsciiStream(1, (InputStream) null, 1);\n        resultSet.updateAsciiStream(\"1\", (InputStream) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateAsciiStream(\"0\", (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateAsciiStream(0, (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateAsciiStream_2() throws Exception {\n        resultSet.next();\n\n        resultSet.updateAsciiStream(1, (InputStream) null, 1L);\n        resultSet.updateAsciiStream(\"1\", (InputStream) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateAsciiStream(\"0\", (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateAsciiStream(0, (InputStream) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateBinaryStream_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateBinaryStream(1, (InputStream) null, 1);\n        resultSet.updateBinaryStream(\"1\", (InputStream) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBinaryStream(\"0\", (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBinaryStream(0, (InputStream) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateAsciiStream() throws Exception {\n        resultSet.next();\n\n        resultSet.updateAsciiStream(1, (InputStream) null);\n        resultSet.updateAsciiStream(\"1\", (InputStream) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateAsciiStream(\"0\", (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateAsciiStream(0, (InputStream) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateNCharacterStream() throws Exception {\n        resultSet.next();\n\n        resultSet.updateNCharacterStream(1, (Reader) null);\n        resultSet.updateNCharacterStream(\"1\", (Reader) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNCharacterStream(\"0\", (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNCharacterStream(0, (Reader) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateNCharacterStream_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateNCharacterStream(1, (Reader) null, 1);\n        resultSet.updateNCharacterStream(\"1\", (Reader) null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNCharacterStream(\"0\", (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNCharacterStream(0, (Reader) null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateSQLXML() throws Exception {\n        resultSet.next();\n\n        resultSet.updateSQLXML(1, (SQLXML) null);\n        resultSet.updateSQLXML(\"1\", (SQLXML) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateSQLXML(\"0\", (SQLXML) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateSQLXML(0, (SQLXML) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_get_error() throws Exception {\n        {\n            SQLException error = null;\n            try {\n                resultSet.getString(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBoolean(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getByte(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getShort(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getInt(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getLong(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getFloat(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getDouble(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBigDecimal(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBigDecimal(0, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBytes(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getDate(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTime(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTimestamp(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getAsciiStream(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getUnicodeStream(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBinaryStream(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // ////////////////\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getString(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBoolean(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getByte(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getShort(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getInt(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getLong(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getFloat(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getDouble(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBigDecimal(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBigDecimal(\"0\", 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBytes(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getDate(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTime(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTimestamp(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getAsciiStream(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getUnicodeStream(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBinaryStream(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getSQLXML() throws Exception {\n        resultSet.next();\n\n        resultSet.getSQLXML(1);\n        resultSet.getSQLXML(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getSQLXML(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getSQLXML(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getNClob() throws Exception {\n        resultSet.next();\n\n        resultSet.getNClob(1);\n        resultSet.getNClob(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getNClob(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getNClob(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getNString() throws Exception {\n        resultSet.next();\n\n        resultSet.getNString(1);\n        resultSet.getNString(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getNString(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getNString(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getNCharacterStream() throws Exception {\n        resultSet.next();\n\n        resultSet.getNCharacterStream(1);\n        resultSet.getNCharacterStream(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getNCharacterStream(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getNCharacterStream(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getCharacterStream() throws Exception {\n        resultSet.next();\n\n        resultSet.getCharacterStream(1);\n        resultSet.getCharacterStream(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getCharacterStream(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getCharacterStream(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateCharacterStream_2() throws Exception {\n        resultSet.next();\n\n        resultSet.updateCharacterStream(1, (Reader) null, 1L);\n        resultSet.updateCharacterStream(\"1\", (Reader) null, 1L);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateCharacterStream(\"0\", (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateCharacterStream(0, (Reader) null, 1L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getURL() throws Exception {\n        resultSet.next();\n\n        resultSet.getURL(1);\n        resultSet.getURL(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getURL(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getURL(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getRowId() throws Exception {\n        resultSet.next();\n\n        resultSet.getRowId(1);\n        resultSet.getRowId(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getRowId(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getRowId(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getObject_1() throws Exception {\n        resultSet.next();\n\n        resultSet.getObject(1);\n        resultSet.getObject(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getObject(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getObject(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getTimestamp() throws Exception {\n        resultSet.next();\n\n        resultSet.getTimestamp(1, null);\n        resultSet.getTimestamp(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTimestamp(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTimestamp(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getTime() throws Exception {\n        resultSet.next();\n\n        resultSet.getTime(1, null);\n        resultSet.getTime(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTime(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getTime(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getDate() throws Exception {\n        resultSet.next();\n\n        resultSet.getDate(1, null);\n        resultSet.getDate(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getDate(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getDate(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getArray() throws Exception {\n        resultSet.next();\n\n        resultSet.getArray(1);\n        resultSet.getArray(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getArray(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getArray(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getClob() throws Exception {\n        resultSet.next();\n\n        resultSet.getClob(1);\n        resultSet.getClob(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getClob(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getClob(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getBlob() throws Exception {\n        resultSet.next();\n\n        resultSet.getBlob(1);\n        resultSet.getBlob(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBlob(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getBlob(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getRef() throws Exception {\n        resultSet.next();\n\n        resultSet.getRef(1);\n        resultSet.getRef(\"1\");\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getRef(0);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getRef(\"0\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getObject() throws Exception {\n        resultSet.next();\n\n        resultSet.getObject(1, (java.util.Map) null);\n        resultSet.getObject(\"1\", (java.util.Map) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getObject(0, (java.util.Map) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getObject(\"0\", (java.util.Map) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateNClob() throws Exception {\n        resultSet.next();\n\n        resultSet.updateNClob(1, (NClob) null);\n        resultSet.updateNClob(\"1\", (NClob) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNClob(0, (NClob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNClob(\"0\", (NClob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateNString() throws Exception {\n        resultSet.next();\n\n        resultSet.updateNString(1, null);\n        resultSet.updateNString(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNString(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateNString(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateRowId() throws Exception {\n        resultSet.next();\n\n        resultSet.updateRowId(1, null);\n        resultSet.updateRowId(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateRowId(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateRowId(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateArray() throws Exception {\n        resultSet.next();\n\n        resultSet.updateArray(1, null);\n        resultSet.updateArray(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateArray(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateArray(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateClob() throws Exception {\n        resultSet.next();\n\n        resultSet.updateClob(1, (Clob) null);\n        resultSet.updateClob(\"1\", (Clob) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateClob(0, (Clob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateClob(\"0\", (Clob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateBlob() throws Exception {\n        resultSet.next();\n\n        resultSet.updateBlob(1, (Blob) null);\n        resultSet.updateBlob(\"1\", (Blob) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBlob(0, (Blob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateBlob(\"0\", (Blob) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateRef() throws Exception {\n        resultSet.next();\n\n        resultSet.updateRef(1, (Ref) null);\n        resultSet.updateRef(\"1\", (Ref) null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateRef(0, (Ref) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateRef(\"0\", (Ref) null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateObject() throws Exception {\n        resultSet.next();\n\n        resultSet.updateObject(1, null);\n        resultSet.updateObject(\"1\", null);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateObject(0, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateObject(\"0\", null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateObject_1() throws Exception {\n        resultSet.next();\n\n        resultSet.updateObject(1, null, 1);\n        resultSet.updateObject(\"1\", null, 1);\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateObject(0, null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateObject(\"0\", null, 1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/ResultSetTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.pool.DruidPooledResultSet;\nimport com.alibaba.druid.pool.DruidPooledStatement;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ResultSetTest2 {\n    private DruidPooledStatement stmt;\n    private MockResultSet raw;\n    private DruidPooledResultSet resultSet;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        stmt = new DruidPooledStatement(null, null) {\n            protected SQLException checkException(Throwable error) throws SQLException {\n                if (error instanceof SQLException) {\n                    return (SQLException) error;\n                }\n\n                return new SQLException(error);\n            }\n        };\n\n        raw = new MockResultSet(null);\n        raw.getRows().add(new Object[]{null});\n        resultSet = new DruidPooledResultSet(stmt, raw);\n    }\n\n    @Test\n    public void test_rowDeleted() throws Exception {\n        resultSet.rowDeleted();\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.rowDeleted();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_rowInserted() throws Exception {\n        resultSet.rowInserted();\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.rowInserted();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_rowUpdated() throws Exception {\n        resultSet.rowInserted();\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.rowUpdated();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getConcurrency() throws Exception {\n        resultSet.getConcurrency();\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getConcurrency();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getType() throws Exception {\n        resultSet.getType();\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getType();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_FetchSize() throws Exception {\n        resultSet.setFetchSize(10);\n        assertEquals(10, resultSet.getFetchSize());\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getFetchSize();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            SQLException error = null;\n            try {\n                resultSet.setFetchSize(10);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_FetchDirection() throws Exception {\n        resultSet.setFetchDirection(ResultSet.FETCH_REVERSE);\n        assertEquals(ResultSet.FETCH_REVERSE, resultSet.getFetchDirection());\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getFetchDirection();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            SQLException error = null;\n            try {\n                resultSet.setFetchDirection(ResultSet.FETCH_REVERSE);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getHoldability() throws Exception {\n        resultSet.getHoldability();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getHoldability();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getStatement() throws Exception {\n        resultSet.getStatement();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                raw.getStatement();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_moveToCurrentRow() throws Exception {\n        resultSet.moveToCurrentRow();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.moveToCurrentRow();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_moveToInsertRow() throws Exception {\n        resultSet.moveToInsertRow();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.moveToInsertRow();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_cancelRowUpdates() throws Exception {\n        resultSet.cancelRowUpdates();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.cancelRowUpdates();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_refreshRow() throws Exception {\n        resultSet.refreshRow();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.refreshRow();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_deleteRow() throws Exception {\n        resultSet.deleteRow();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.deleteRow();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_updateRow() throws Exception {\n        resultSet.updateRow();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.updateRow();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_insertRow() throws Exception {\n        resultSet.insertRow();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.insertRow();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_previous() throws Exception {\n        resultSet.previous();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.previous();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_relative() throws Exception {\n        resultSet.relative(1);\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.relative(1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_absolute() throws Exception {\n        resultSet.absolute(1);\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.absolute(1);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_next() throws Exception {\n        resultSet.next();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.next();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_wasNull() throws Exception {\n        resultSet.wasNull();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.wasNull();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_isBeforeFirst() throws Exception {\n        resultSet.isBeforeFirst();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.isBeforeFirst();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_isAfterLast() throws Exception {\n        resultSet.isAfterLast();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.isAfterLast();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_isFirst() throws Exception {\n        resultSet.isFirst();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.isFirst();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_isLast() throws Exception {\n        resultSet.isLast();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.isLast();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_beforeFirst() throws Exception {\n        resultSet.beforeFirst();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.beforeFirst();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_first() throws Exception {\n        resultSet.first();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.first();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_afterLast() throws Exception {\n        resultSet.afterLast();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.afterLast();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_last() throws Exception {\n        resultSet.last();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.last();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getRow() throws Exception {\n        resultSet.getRow();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getRow();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getWarnings() throws Exception {\n        resultSet.getWarnings();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getWarnings();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_clearWarnings() throws Exception {\n        resultSet.clearWarnings();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.clearWarnings();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getCursorName() throws Exception {\n        resultSet.getCursorName();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getCursorName();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getMetaData() throws Exception {\n        resultSet.getMetaData();\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.getMetaData();\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_findColumn() throws Exception {\n        resultSet.findColumn(\"1\");\n\n        raw.close();\n\n        {\n            SQLException error = null;\n            try {\n                resultSet.findColumn(\"xxxx\");\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_closeError() throws Exception {\n        MockResultSet mock = new MockResultSet(null) {\n            public void close() throws SQLException {\n                throw new SQLException();\n            }\n        };\n\n        DruidPooledResultSet rs = new DruidPooledResultSet(stmt, mock);\n\n        SQLException error = null;\n        try {\n            rs.close();\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/TestCommit.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestCommit {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        DruidDataSourceStatManager.clear();\n        driver = new MockDriver();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat\");\n        dataSource.setRemoveAbandoned(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        assertEquals(true, dataSource.getCreateTimespanNano() > 0);\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_prepare() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        {\n            DruidPooledConnection wrap = conn.unwrap(DruidPooledConnection.class);\n            assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n            assertNotNull(wrap);\n        }\n\n        {\n            Statement wrap = conn.unwrap(Statement.class);\n            assertTrue(!conn.isWrapperFor(Statement.class));\n            assertNull(wrap);\n        }\n\n        conn.setAutoCommit(false);\n        conn.setAutoCommit(false);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"SELECT 1\");\n        stmt.close();\n        assertEquals(1, dataSource.getActiveConnectionStackTrace().size());\n        assertEquals(1, dataSource.getActiveConnections().size());\n        conn.rollback();\n        conn.close();\n\n        assertEquals(1, dataSource.getStartTransactionCount());\n        assertEquals(0, dataSource.getCommitCount());\n        assertEquals(1, dataSource.getRollbackCount());\n\n        assertEquals(0, dataSource.getActiveConnectionStackTrace().size());\n        assertEquals(0, dataSource.getActiveConnections().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/TestDataSourceBasic.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.NullExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.Date;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestDataSourceBasic extends PoolTestCase {\n    private MockDriver driver;\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        driver = new MockDriver();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDriver(driver);\n        dataSource.setInitialSize(1);\n        dataSource.setMaxActive(2);\n        dataSource.setMaxIdle(2);\n        dataSource.setMinIdle(1);\n        dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10\n        dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10\n        dataSource.setTestWhileIdle(true);\n        dataSource.setTestOnBorrow(false);\n        dataSource.setValidationQuery(\"SELECT 1\");\n        dataSource.setFilters(\"stat,trace\");\n        dataSource.setRemoveAbandoned(true);\n        dataSource.setExceptionSorterClassName(null);\n\n        assertTrue(dataSource.getExceptionSorter() instanceof NullExceptionSorter);\n        dataSource.setExceptionSorterClassName(\"\");\n        assertTrue(dataSource.getExceptionSorter() instanceof NullExceptionSorter);\n    }\n\n    protected void tearDown() throws Exception {\n        if (dataSource.getCreateCount() > 0) {\n            assertEquals(true, dataSource.getCreateTimespanNano() > 0);\n        }\n        dataSource.close();\n        DruidDataSourceStatManager.clear();\n        super.tearDown();\n    }\n\n    public void test_toCompositeData() throws Exception {\n        Connection conn = dataSource.getConnection();\n        conn.close();\n        dataSource.getCompositeData();\n    }\n\n    public void test_prepare() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        {\n            DruidPooledConnection wrap = conn.unwrap(DruidPooledConnection.class);\n            assertTrue(conn.isWrapperFor(DruidPooledConnection.class));\n            assertNotNull(wrap);\n        }\n\n        {\n            Statement wrap = conn.unwrap(Statement.class);\n            assertTrue(!conn.isWrapperFor(Statement.class));\n            assertNull(wrap);\n        }\n\n        conn.setAutoCommit(false);\n        conn.setAutoCommit(false);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"SELECT 1\");\n        stmt.close();\n\n        assertEquals(1, dataSource.getActiveConnectionStackTrace().size());\n        assertEquals(1, dataSource.getActiveConnections().size());\n        conn.commit();\n        conn.close();\n\n        assertEquals(1, dataSource.getStartTransactionCount());\n        assertEquals(1, dataSource.getCommitCount());\n        assertEquals(0, dataSource.getRollbackCount());\n\n        assertEquals(0, dataSource.getActiveConnectionStackTrace().size());\n        assertEquals(0, dataSource.getActiveConnections().size());\n    }\n\n    public void test_wrap() throws Exception {\n        assertTrue(!dataSource.isWrapperFor(Date.class));\n        assertTrue(!dataSource.isWrapperFor(null));\n        assertTrue(dataSource.isWrapperFor(DataSource.class));\n\n        assertTrue(dataSource.unwrap(Date.class) == null);\n        assertTrue(dataSource.unwrap(null) == null);\n        assertTrue(dataSource.unwrap(DataSource.class) != null);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/basic/TestDataSourceBasic2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.basic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.ExceptionSorter;\nimport com.alibaba.druid.pool.JDBC4ValidConnectionChecker;\nimport com.alibaba.druid.stat.DataSourceMonitorable;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\n\nimport java.util.Arrays;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class TestDataSourceBasic2 extends PoolTestCase {\n    public void test_0() throws Exception {\n        DruidDataSourceStatManager.clear();\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n\n        dataSource.setBreakAfterAcquireFailure(true);\n        assertEquals(true, dataSource.isBreakAfterAcquireFailure());\n\n        dataSource.setConnectionErrorRetryAttempts(234);\n        assertEquals(234, dataSource.getConnectionErrorRetryAttempts());\n\n        dataSource.setMaxPoolPreparedStatementPerConnectionSize(234);\n        assertEquals(234, dataSource.getMaxPoolPreparedStatementPerConnectionSize());\n\n        dataSource.incrementDupCloseCount();\n        assertEquals(1, dataSource.getDupCloseCount());\n\n        dataSource.setValidConnectionChecker(null);\n        dataSource.setValidConnectionCheckerClassName(null);\n        assertNotNull(dataSource.getValidConnectionChecker());\n        assertTrue(dataSource.getValidConnectionChecker() instanceof JDBC4ValidConnectionChecker);\n\n        dataSource.addConnectionProperty(\"user\", \"ljw\");\n        assertEquals(1, dataSource.getConnectProperties().size());\n\n        assertEquals(0, dataSource.getConnectionInitSqls().size());\n        dataSource.setConnectionInitSqls(Arrays.<Object>asList(\"SELECT 1\", null, \"\"));\n        assertEquals(1, dataSource.getConnectionInitSqls().size());\n\n        assertEquals(500, dataSource.getTimeBetweenConnectErrorMillis());\n        assertEquals(234, dataSource.getMaxOpenPreparedStatements());\n        assertEquals(300, dataSource.getRemoveAbandonedTimeout());\n        dataSource.setRemoveAbandonedTimeout(400);\n        assertEquals(400, dataSource.getRemoveAbandonedTimeout());\n        assertEquals(400 * 1000, dataSource.getRemoveAbandonedTimeoutMillis());\n        assertEquals(3, dataSource.getNumTestsPerEvictionRun());\n        dataSource.setNumTestsPerEvictionRun(4);\n        assertEquals(4, dataSource.getNumTestsPerEvictionRun());\n\n        dataSource.setMaxWaitThreadCount(4);\n        assertEquals(4, dataSource.getMaxWaitThreadCount());\n\n        dataSource.setValidationQueryTimeout(4);\n        assertEquals(4, dataSource.getValidationQueryTimeout());\n\n        dataSource.setAccessToUnderlyingConnectionAllowed(true);\n        assertEquals(true, dataSource.isAccessToUnderlyingConnectionAllowed());\n\n        dataSource.setDefaultReadOnly(true);\n        assertEquals(Boolean.TRUE, dataSource.getDefaultReadOnly());\n\n        dataSource.setDefaultTransactionIsolation(10);\n        assertEquals(Integer.valueOf(10), dataSource.getDefaultTransactionIsolation());\n\n        dataSource.setDefaultCatalog(\"xxx\");\n        assertEquals(\"xxx\", dataSource.getDefaultCatalog());\n\n        dataSource.setPasswordCallbackClassName(null);\n        dataSource.setUserCallback(null);\n\n        assertEquals(0, dataSource.getQueryTimeout());\n        dataSource.setQueryTimeout(10001);\n        assertEquals(10001, dataSource.getQueryTimeout());\n\n        assertEquals(-1, dataSource.getMaxWait());\n        dataSource.setMaxWait(10001);\n        assertEquals(10001, dataSource.getMaxWait());\n\n        assertEquals(8, dataSource.getMaxIdle());\n        dataSource.setMaxIdle(3);\n        assertEquals(3, dataSource.getMaxIdle());\n\n        assertEquals(0, dataSource.getLoginTimeout());\n        dataSource.setLoginTimeout(30);\n        assertEquals(30, dataSource.getLoginTimeout());\n\n        assertEquals(null, dataSource.getUsername());\n        dataSource.setUsername(\"ljw\");\n        assertEquals(\"ljw\", dataSource.getUsername());\n\n        assertEquals(null, dataSource.getPassword());\n        dataSource.setPassword(\"xxx\");\n        assertEquals(\"xxx\", dataSource.getPassword());\n\n        dataSource.setConnectProperties(new Properties());\n        assertEquals(0, dataSource.getConnectProperties().size());\n        dataSource.setConnectionProperties(\"a=1;b=2;c\");\n        assertEquals(3, dataSource.getConnectProperties().size());\n\n        dataSource.setExceptionSorter((ExceptionSorter) null);\n\n        dataSource.close();\n    }\n\n    protected void tearDown() throws Exception {\n        for (DataSourceMonitorable dataSource : DruidDataSourceStatManager.getDruidDataSourceInstances()) {\n            dataSource.close();\n        }\n\n        super.tearDown();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/dynamic/ConnectPropertiesChangeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.dynamic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectPropertiesChangeTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    private Log dataSourceLog;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        Field logField = DruidDataSource.class.getDeclaredField(\"LOG\");\n        logField.setAccessible(true);\n        dataSourceLog = (Log) logField.get(null);\n\n        dataSourceLog.resetStat();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setConnectionProperties(\"a=3;b=4\");\n        dataSource.setFilters(\"stat\");\n        dataSource.init();\n\n        assertEquals(1, dataSourceLog.getInfoCount());\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connectPropertiesChange() throws Exception {\n        assertEquals(2, dataSource.getConnectProperties().size());\n\n        assertEquals(\"3\", dataSource.getConnectProperties().getProperty(\"a\"));\n        assertEquals(\"4\", dataSource.getConnectProperties().getProperty(\"b\"));\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        dataSource.setConnectionProperties(\"a=3;b=4\");\n        assertEquals(1, dataSourceLog.getInfoCount());\n\n        dataSource.setConnectionProperties(\"b=5;c=6\");\n        assertEquals(2, dataSourceLog.getInfoCount());\n\n        assertEquals(2, dataSource.getConnectProperties().size());\n\n        assertEquals(\"5\", dataSource.getConnectProperties().getProperty(\"b\"));\n        assertEquals(\"6\", dataSource.getConnectProperties().getProperty(\"c\"));\n\n        StatFilter filter = dataSource.unwrap(StatFilter.class);\n        assertNotNull(filter);\n        assertFalse(filter.isMergeSql());\n\n        dataSource.setConnectionProperties(\"b=5;c=6;druid.stat.mergeSql=true\");\n\n        assertTrue(filter.isMergeSql());\n\n        assertEquals(3, dataSource.getConnectProperties().size());\n\n        assertEquals(\"true\", dataSource.getConnectProperties().getProperty(\"druid.stat.mergeSql\"));\n        assertEquals(\"5\", dataSource.getConnectProperties().getProperty(\"b\"));\n        assertEquals(\"6\", dataSource.getConnectProperties().getProperty(\"c\"));\n\n        dataSource.setConnectionProperties(\"b=5;c=6;druid.stat.mergeSql=false\");\n\n        assertFalse(filter.isMergeSql());\n\n        assertEquals(\"false\", dataSource.getConnectProperties().getProperty(\"druid.stat.mergeSql\"));\n        assertEquals(\"5\", dataSource.getConnectProperties().getProperty(\"b\"));\n        assertEquals(\"6\", dataSource.getConnectProperties().getProperty(\"c\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/dynamic/ConnectPropertiesChangeTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.dynamic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectPropertiesChangeTest1 extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    private Log dataSourceLog;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        Field logField = DruidDataSource.class.getDeclaredField(\"LOG\");\n        logField.setAccessible(true);\n        dataSourceLog = (Log) logField.get(null);\n\n        dataSourceLog.resetStat();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setConnectionProperties(\"druid.filters=stat;druid.stat.sql.MaxSize=234\");\n        dataSource.init();\n\n        assertEquals(1, dataSourceLog.getInfoCount());\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connectPropertiesChange() throws Exception {\n        assertEquals(2, dataSource.getConnectProperties().size());\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n\n        StatFilter filter = dataSource.unwrap(StatFilter.class);\n        assertNotNull(filter);\n        assertFalse(filter.isMergeSql());\n        assertEquals(234, dataSource.getDataSourceStat().getMaxSqlSize());\n\n        dataSource.setConnectionProperties(\"druid.stat.mergeSql=true;druid.stat.sql.MaxSize=456\");\n        assertEquals(456, dataSource.getDataSourceStat().getMaxSqlSize());\n\n        assertTrue(filter.isMergeSql());\n\n        assertEquals(2, dataSource.getConnectProperties().size());\n\n        assertEquals(\"true\", dataSource.getConnectProperties().getProperty(\"druid.stat.mergeSql\"));\n\n        dataSource.setConnectionProperties(\"druid.stat.mergeSql=false\");\n\n        assertFalse(filter.isMergeSql());\n\n        assertEquals(\"false\", dataSource.getConnectProperties().getProperty(\"druid.stat.mergeSql\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/dynamic/DruidDataSourceStatLoggerImplTest.java",
    "content": "package com.alibaba.druid.bvt.pool.dynamic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceStatLogger;\nimport com.alibaba.druid.pool.DruidDataSourceStatLoggerImpl;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDataSourceStatLoggerImplTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    private Log statLog;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        Field logField = DruidDataSourceStatLoggerImpl.class.getDeclaredField(\"LOG\");\n        logField.setAccessible(true);\n        statLog = (Log) logField.get(null);\n\n        statLog.resetStat();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setConnectionProperties(\"a=3;b=4\");\n        dataSource.setFilters(\"stat\");\n        dataSource.init();\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connectPropertiesChange() throws Exception {\n        assertTrue(dataSource.isWrapperFor(DruidDataSourceStatLogger.class));\n        assertTrue(dataSource.isWrapperFor(DruidDataSourceStatLoggerImpl.class));\n        DruidDataSourceStatLoggerImpl loggerImpl = dataSource.unwrap(DruidDataSourceStatLoggerImpl.class);\n        assertSame(statLog, loggerImpl.getLogger());\n\n        dataSource.setConnectionProperties(\"druid.stat.loggerName=xxx\");\n        assertNotSame(statLog, loggerImpl.getLogger());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/dynamic/MaxActiveChangeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.dynamic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.GetConnectionTimeoutException;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MaxActiveChangeTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setMaxActive(3);\n        dataSource.setMinIdle(2);\n        dataSource.setMinEvictableIdleTimeMillis(1000 * 60 * 5);\n        dataSource.setMaxWait(20);\n        dataSource.init();\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_maxActive() throws Exception {\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(1, connect(1));\n            assertEquals(1, dataSource.getPoolingCount());\n        }\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(2, connect(2));\n            assertEquals(2, dataSource.getPoolingCount());\n        }\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(3, connect(3));\n            assertEquals(3, dataSource.getPoolingCount());\n        }\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(3, connect(4));\n            assertEquals(3, dataSource.getPoolingCount());\n        }\n\n        dataSource.setMaxActive(5);\n\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(5, connect(5));\n            assertEquals(5, dataSource.getPoolingCount());\n        }\n\n        dataSource.shrink();\n        assertEquals(2, dataSource.getPoolingCount());\n\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(5, connect(5));\n            assertEquals(5, dataSource.getPoolingCount());\n        }\n\n        assertEquals(5, dataSource.getPoolingCount());\n        dataSource.setMaxActive(3);\n\n        assertEquals(5, dataSource.getPoolingCount());\n\n        dataSource.shrink();\n        assertEquals(2, dataSource.getPoolingCount());\n\n        // 确保收缩之后不会再长上去\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(3, connect(5));\n            assertEquals(3, dataSource.getPoolingCount());\n        }\n\n        dataSource.setMaxActive(2);\n        dataSource.shrink();\n        assertEquals(2, dataSource.getPoolingCount());\n\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(2, connect(3));\n            assertEquals(2, dataSource.getPoolingCount());\n        }\n\n        dataSource.setMinIdle(1);\n        dataSource.setMaxActive(1);\n        dataSource.shrink();\n        assertEquals(1, dataSource.getPoolingCount());\n\n        for (int i = 0; i < 10; ++i) {\n            assertEquals(1, connect(2));\n            assertEquals(1, dataSource.getPoolingCount());\n        }\n\n        Exception error = null;\n        try {\n            dataSource.setMaxActive(0);\n        } catch (IllegalArgumentException e) {\n            error = e;\n        }\n        assertNotNull(error);\n        assertEquals(1, dataSource.getMaxActive());\n    }\n\n    public int connect(int count) throws Exception {\n        int successCount = 0;\n        Connection[] connections = new Connection[count];\n        for (int i = 0; i < count; ++i) {\n            try {\n                connections[i] = dataSource.getConnection();\n                successCount++;\n            } catch (GetConnectionTimeoutException e) {\n                // skip\n            }\n        }\n\n        for (int i = 0; i < count; ++i) {\n            JdbcUtils.close(connections[i]);\n        }\n\n        return successCount;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/dynamic/PoolPreparedStatementsChangeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.dynamic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PoolPreparedStatementsChangeTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    private Log dataSourceLog;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        Field logField = DruidDataSource.class.getDeclaredField(\"LOG\");\n        logField.setAccessible(true);\n        dataSourceLog = (Log) logField.get(null);\n\n        dataSourceLog.resetStat();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.init();\n\n        assertEquals(1, dataSourceLog.getInfoCount());\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connectPropertiesChange() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        assertEquals(false, dataSource.isPoolPreparedStatements());\n\n        dataSource.setPoolPreparedStatements(true);\n\n        assertEquals(true, dataSource.isPoolPreparedStatements());\n\n        String sql = \"select ?\";\n\n        assertEquals(0, dataSource.getCachedPreparedStatementCount());\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.setString(1, \"xxx\");\n            ResultSet rs = stmt.executeQuery();\n\n            rs.close();\n\n            conn.close();\n        }\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n        assertEquals(1, dataSource.getCachedPreparedStatementAccessCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.setString(1, \"xxx\");\n            ResultSet rs = stmt.executeQuery();\n\n            rs.close();\n\n            conn.close();\n        }\n        assertEquals(1, dataSource.getCachedPreparedStatementCount());\n        assertEquals(2, dataSource.getCachedPreparedStatementAccessCount());\n\n        dataSource.setPoolPreparedStatements(false);\n        assertEquals(0, dataSource.getCachedPreparedStatementCount());\n        assertEquals(2, dataSource.getCachedPreparedStatementAccessCount());\n\n        {\n            Connection conn = dataSource.getConnection();\n\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.setString(1, \"xxx\");\n            ResultSet rs = stmt.executeQuery();\n\n            rs.close();\n\n            conn.close();\n        }\n        assertEquals(0, dataSource.getCachedPreparedStatementCount());\n        assertEquals(2, dataSource.getCachedPreparedStatementAccessCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/dynamic/SqlSkipCountTest.java",
    "content": "package com.alibaba.druid.bvt.pool.dynamic;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSourceStatValue;\nimport com.alibaba.druid.support.logging.Log;\n\nimport java.lang.reflect.Field;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SqlSkipCountTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    private Log dataSourceLog;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        Field logField = DruidDataSource.class.getDeclaredField(\"LOG\");\n        logField.setAccessible(true);\n        dataSourceLog = (Log) logField.get(null);\n\n        dataSourceLog.resetStat();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setTestOnBorrow(false);\n        dataSource.setFilters(\"stat\");\n        dataSource.init();\n\n        assertEquals(1, dataSourceLog.getInfoCount());\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void test_connectPropertiesChange() throws Exception {\n        for (int i = 0; i < 2000; ++i) {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select \" + i);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        {\n            DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();\n            assertEquals(1000, statValue.getSqlList().size());\n            assertEquals(1000, statValue.getSqlSkipCount());\n        }\n\n        dataSource.setConnectionProperties(\"druid.stat.sql.MaxSize=2000\");\n        for (int i = 0; i < 2000; ++i) {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select \" + i);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        {\n            DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();\n            assertEquals(2000, statValue.getSqlList().size());\n            assertEquals(0, statValue.getSqlSkipCount());\n        }\n        {\n            DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();\n            assertEquals(0, statValue.getSqlList().size());\n            assertEquals(0, statValue.getSqlSkipCount());\n        }\n\n        dataSource.setConnectionProperties(\"druid.stat.sql.MaxSize=2000\");\n        for (int i = 0; i < 2000; ++i) {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select \" + i);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        {\n            DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();\n            assertEquals(2000, statValue.getSqlList().size());\n            assertEquals(0, statValue.getSqlSkipCount());\n        }\n\n        dataSource.setConnectionProperties(\"druid.stat.sql.MaxSize=100\");\n        for (int i = 0; i < 2000; ++i) {\n            Connection conn = dataSource.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"select \" + i);\n            stmt.execute();\n            stmt.close();\n            conn.close();\n        }\n        {\n            DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();\n            assertEquals(100, statValue.getSqlList().size());\n            assertEquals(1900, statValue.getSqlSkipCount());\n        }\n        {\n            DruidDataSourceStatValue statValue = dataSource.getStatValueAndReset();\n            assertEquals(0, statValue.getSqlList().size());\n            assertEquals(0, statValue.getSqlSkipCount());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OceanBaseOracleExceptionSorterTest.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OceanBaseOracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OceanBaseOracleExceptionSorterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OceanBaseOracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setFilters(\"log4j\");\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        PreparedStatement pstmt = conn.prepareStatement(sql);\n        pstmt.setFetchSize(1000);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        boolean fatal = false;\n        try {\n            conn.handleException(exception);\n        } catch (SQLException ex) {\n            fatal = true;\n        }\n        assertTrue(fatal);\n\n        pstmt.close();\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setFilters(\"log4j\");\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        PreparedStatement pstmt = conn.prepareStatement(sql);\n        pstmt.setFetchSize(1000);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        boolean fatal = false;\n        try {\n            conn.handleException(exception);\n        } catch (SQLException ex) {\n            fatal = true;\n        }\n        assertTrue(fatal);\n\n        pstmt.close();\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_closeConn.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_closeConn {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        PreparedStatement pstmt = conn.prepareStatement(sql);\n        pstmt.setFetchSize(1000);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        assertEquals(1, dataSource.getActiveCount());\n        conn.close();\n        assertEquals(0, dataSource.getActiveCount());\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_closeConn_1.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_closeConn_1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        conn.prepareStatement(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_closeConn_2.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_closeConn_2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        conn.setAutoCommit(false);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_closeConn_3.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_closeConn_3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        conn.setAutoCommit(false);\n        conn.setReadOnly(false);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_closeConnectFailedDatasource.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidDataSource.CreateConnectionThread;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriverConnectFailed;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.lang.Thread.State;\nimport java.sql.SQLException;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_closeConnectFailedDatasource {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriverConnectFailed());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setMaxActive(1);\n        dataSource.setMaxWait(1000);\n\n        OracleMockDriverConnectFailed.CONNECT_BARIER.reset();\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        Thread connectFailedThread = new Thread() {\n            public void run() {\n                try {\n                    dataSource.getConnection();\n                } catch (SQLException e) {\n                     e.printStackTrace();\n                }\n            }\n        };\n        connectFailedThread.start();\n\n        OracleMockDriverConnectFailed.CONNECT_BARIER.await(100, TimeUnit.MILLISECONDS);\n        dataSource.close();\n\n        // waiting for createConnectionThread terminated.\n        CreateConnectionThread thread = (CreateConnectionThread) ReflectionTestUtils.getField(dataSource, \"createConnectionThread\");\n        for (int i = 0; i < 10 && State.TERMINATED != thread.getState(); i++) {\n            Thread.sleep(1000);\n        }\n        assertEquals(State.TERMINATED, thread.getState());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_closeStmt.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_closeStmt {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        PreparedStatement pstmt = conn.prepareStatement(sql);\n        pstmt.setFetchSize(1000);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException closedErrror = null;\n        try {\n            pstmt.close();\n        } catch (SQLException ex) {\n            closedErrror = ex;\n        }\n        assertNotNull(closedErrror);\n        assertSame(exception, closedErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_commit.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_commit {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        conn.setAutoCommit(false);\n\n        conn.prepareStatement(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        Exception commitError = null;\n        try {\n            conn.commit();\n        } catch (Exception ex) {\n            commitError = ex;\n        }\n        assertNotNull(commitError);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertTrue(dataSource.getPoolingCount() >= 1);\n        assertTrue(dataSource.getCreateCount() >= 2);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_concurrent.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.concurrent.CountDownLatch;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_concurrent {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n        dataSource.setMaxActive(1);\n        dataSource.setMaxWait(1000 * 100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        final CountDownLatch latch_0 = new CountDownLatch(1);\n\n        Thread errorThread = new Thread() {\n            public void run() {\n                try {\n                    Connection conn = dataSource.getConnection();\n\n                    latch_0.countDown();\n\n                    MockConnection mockConn = conn.unwrap(MockConnection.class);\n                    assertNotNull(mockConn);\n\n                    SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n                    mockConn.setError(exception);\n\n                    try {\n                        conn.createStatement();\n                    } catch (SQLException ex) {\n                        // ex.printStackTrace();\n                    }\n                    conn.close();\n                } catch (Exception error) {\n                    error.printStackTrace();\n                }\n            }\n        };\n        errorThread.start();\n\n        final CountDownLatch workLatch = new CountDownLatch(2);\n        final CountDownLatch workCompleteLatch = new CountDownLatch(2);\n        for (int i = 0; i < 2; ++i) {\n            Thread thread = new Thread() {\n                public void run() {\n                    try {\n                        for (int i = 0; i < 1000; ++i) {\n                            workLatch.countDown();\n                            Connection conn = dataSource.getConnection();\n                            conn.close();\n                        }\n                    } catch (Exception ex) {\n                        ex.printStackTrace();\n                    } finally {\n                        workCompleteLatch.countDown();\n                    }\n                }\n            };\n            thread.start();\n        }\n        workLatch.await();\n\n        latch_0.countDown();\n\n        workCompleteLatch.await();\n\n        assertEquals(2001, dataSource.getConnectCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_rollback.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_rollback {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        conn.setAutoCommit(false);\n\n        PreparedStatement stmt = conn.prepareStatement(sql);\n        stmt.execute();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        Exception rollbackError = null;\n        try {\n            conn.rollback();\n        } catch (Exception ex) {\n            rollbackError = ex;\n        }\n        assertNotNull(rollbackError);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertTrue(dataSource.getPoolingCount() >= 1);\n        assertTrue(dataSource.getCreateCount() >= 2);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_setCatalog.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_setCatalog {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        Exception setError = null;\n        try {\n            conn.setCatalog(\"xxx\");\n        } catch (Exception ex) {\n            setError = ex;\n        }\n        assertNotNull(setError);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_setIsolationLevel.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_setIsolationLevel {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        Exception setError = null;\n        try {\n            conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);\n        } catch (Exception ex) {\n            setError = ex;\n        }\n        assertNotNull(setError);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_setReadOnly.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_setReadOnly {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"slf4j\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        Exception setError = null;\n        try {\n            conn.setReadOnly(true);\n        } catch (Exception ex) {\n            setError = ex;\n        }\n        assertNotNull(setError);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(1, dataSource.getDiscardCount());\n        assertEquals(0, dataSource.getActiveCount());\n        assertTrue(dataSource.getPoolingCount() >= 1);\n        assertTrue(dataSource.getCreateCount() >= 2);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_setSavepoint.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_setSavepoint {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        Exception setError = null;\n        try {\n            conn.setSavepoint();\n        } catch (Exception ex) {\n            setError = ex;\n        }\n        assertNotNull(setError);\n\n        // assert that shrink will not call emptySignal at this time.\n        dataSource.shrink(true, false);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertEquals(1, dataSource.getPoolingCount());\n        assertEquals(2, dataSource.getCreateCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_setSavepointWithName.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_setSavepointWithName {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setFilters(\"log4j\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n\n            assertEquals(0, dataSource.getActiveCount());\n            assertEquals(1, dataSource.getPoolingCount());\n            assertEquals(1, dataSource.getCreateCount());\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        Exception setError = null;\n        try {\n            conn.setSavepoint(\"xxx\");\n        } catch (Exception ex) {\n            setError = ex;\n        }\n        assertNotNull(setError);\n\n        conn.close();\n\n        {\n            Connection conn2 = dataSource.getConnection();\n            conn2.close();\n        }\n        assertEquals(0, dataSource.getActiveCount());\n        assertTrue(dataSource.getPoolingCount() >= 1);\n        assertTrue(dataSource.getCreateCount() >= 2);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_addBatch.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_addBatch {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.addBatch(sql);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_cancel.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_cancel {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.cancel();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_clearBatch.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_clearBatch {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.addBatch(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.clearBatch();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_clearWarrnings.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_clearWarrnings {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.clearWarnings();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_execute.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_execute {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.execute(sql);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_executeBatch.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_executeBatch {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.addBatch(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.executeBatch();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_executeQuery.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_executeQuery {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.executeQuery(sql);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_executeUpdate.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_executeUpdate {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.executeUpdate(sql);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_executeUpdate_1.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_executeUpdate_1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_executeUpdate_2.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_executeUpdate_2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.executeUpdate(sql, new int[0]);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_executeUpdate_3.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_executeUpdate_3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.executeUpdate(sql, new String[0]);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_execute_1.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_execute_1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.execute(sql, Statement.RETURN_GENERATED_KEYS);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_execute_2.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_execute_2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.execute(sql, new int[0]);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_execute_3.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_execute_3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException execErrror = null;\n        try {\n            stmt.execute(sql, new String[0]);\n        } catch (SQLException ex) {\n            execErrror = ex;\n        }\n        assertNotNull(execErrror);\n        assertSame(exception, execErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getFetchDirection.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getFetchDirection {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getFetchDirection();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getFetchSize.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getFetchSize {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getFetchSize();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getGeneratedKeys.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getGeneratedKeys {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getMaxRows();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getMaxField.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getMaxField {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getMaxFieldSize();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getMaxRows.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getMaxRows {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getMaxRows();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getMoreResults.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getMoreResults {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getMoreResults();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getMoreResults_1.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getMoreResults_1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getMoreResults(1);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getQueryTimeout.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getQueryTimeout {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getQueryTimeout();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getResultSet.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getResultSet {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getResultSet();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getResultSetConcurrency.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getResultSetConcurrency {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getResultSetConcurrency();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getResultSetHoldability.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getResultSetHoldability {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getResultSetHoldability();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getResultSetType.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getResultSetType {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getResultSetType();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getUpdateCount.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getUpdateCount {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getUpdateCount();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_getWarrnings.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_getWarrnings {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(sql);\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.getWarnings();\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_setCursorName.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_setCursorName {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.setCursorName(\"mycur\");\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_setEscapeProcessing.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_setEscapeProcessing {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.setEscapeProcessing(true);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_setFetchDirection.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_setFetchDirection {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.setFetchDirection(ResultSet.FETCH_FORWARD);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_setFetchSize.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_setFetchSize {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.setFetchSize(10);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_setMaxField.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_setMaxField {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.setMaxFieldSize(10);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_setMaxRows.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_setMaxRows {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n        @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        DruidDataSourceStatManager.clear();\n    }\n\n    @Test\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.setMaxRows(10);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorterTest_stmt_setQueryTimeout.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorterTest_stmt_setQueryTimeout extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n    @Override\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        super.tearDown();\n    }\n\n    public void test_connect() throws Exception {\n        String sql = \"SELECT 1\";\n        {\n            DruidPooledConnection conn = dataSource.getConnection();\n\n            PreparedStatement pstmt = conn.prepareStatement(sql);\n            pstmt.execute();\n            pstmt.close();\n            conn.close();\n        }\n\n        DruidPooledConnection conn = dataSource.getConnection();\n        MockConnection mockConn = conn.unwrap(MockConnection.class);\n        assertNotNull(mockConn);\n\n        Statement stmt = conn.createStatement();\n\n        SQLException exception = new SQLException(\"xx\", \"xxx\", 28);\n        mockConn.setError(exception);\n\n        SQLException stmtErrror = null;\n        try {\n            stmt.setQueryTimeout(10);\n        } catch (SQLException ex) {\n            stmtErrror = ex;\n        }\n        assertNotNull(stmtErrror);\n        assertSame(exception, stmtErrror);\n\n        SQLException commitError = null;\n        try {\n            conn.commit();\n        } catch (SQLException ex) {\n            commitError = ex;\n        }\n\n        assertNotNull(commitError);\n        assertSame(exception, commitError.getCause());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorter_userDefined.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorter_userDefined extends PoolTestCase {\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        System.setProperty(\"druid.oracle.fatalErrorCodes\", \"1,2,3,a,\");\n    }\n\n    protected void tearDown() throws Exception {\n        System.clearProperty(\"druid.oracle.fatalErrorCodes\");\n\n        super.tearDown();\n    }\n\n    public void test_userDefinedErrorCodes() throws Exception {\n        OracleExceptionSorter sorter = new OracleExceptionSorter();\n        assertEquals(3, sorter.getFatalErrorCodes().size());\n        assertTrue(sorter.getFatalErrorCodes().contains(1));\n        assertTrue(sorter.getFatalErrorCodes().contains(2));\n        assertTrue(sorter.getFatalErrorCodes().contains(3));\n\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 1)));\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 2)));\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 3)));\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 4)));\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 28)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorter_userDefined_1.java",
    "content": "package com.alibaba.druid.bvt.pool.exception;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.vendor.OracleExceptionSorter;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.test.util.OracleMockDriver;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OracleExceptionSorter_userDefined_1 extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n         JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n\n        dataSource.setExceptionSorter(new OracleExceptionSorter());\n\n        dataSource.setDriver(new OracleMockDriver());\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setPoolPreparedStatements(true);\n        dataSource.setMaxOpenPreparedStatements(100);\n    }\n\n    @Override\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n\n        super.tearDown();\n    }\n\n    public void test_userDefinedErrorCodes() throws Exception {\n        dataSource.init();\n\n        dataSource.setConnectionProperties(\"druid.oracle.fatalErrorCodes=1,2,3,a,\");\n\n        OracleExceptionSorter sorter = (OracleExceptionSorter) dataSource.getExceptionSorter();\n        assertEquals(3, sorter.getFatalErrorCodes().size());\n        assertTrue(sorter.getFatalErrorCodes().contains(1));\n        assertTrue(sorter.getFatalErrorCodes().contains(2));\n        assertTrue(sorter.getFatalErrorCodes().contains(3));\n\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 1)));\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 2)));\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 3)));\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 4)));\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"xx\", \"xx\", 28)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/profile/FailFastTest.java",
    "content": "package com.alibaba.druid.bvt.pool.profile;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DataSourceNotAvailableException;\nimport com.alibaba.druid.pool.DruidDataSource;\n\nimport java.sql.SQLException;\nimport java.util.Properties;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FailFastTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    private AtomicInteger index = new AtomicInteger();\n    private CountDownLatch latch = new CountDownLatch(1);\n\n    @SuppressWarnings(\"serial\")\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidDataSource() {\n            public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {\n                if (index.get() > 2) {\n                    return super.createPhysicalConnection();\n                }\n\n                index.incrementAndGet();\n                try {\n                    latch.await();\n                } catch (InterruptedException e) {\n                    // TODO Auto-generated catch block\n                    e.printStackTrace();\n                }\n                SQLException ex = new SQLException();\n                setCreateError(ex);\n                throw ex;\n            }\n        };\n\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMaxWait(1000 * 1000);\n\n        Properties properties = new Properties();\n        properties.setProperty(\"druid.failFast\", \"true\");\n        dataSource.configFromPropeties(properties);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        super.tearDown();\n    }\n\n    public void testDefault() throws Exception {\n        assertTrue(dataSource.isFailFast());\n\n        final AtomicReference<SQLException> errorHolder = new AtomicReference<SQLException>(null);\n        final CountDownLatch connectStartLatch = new CountDownLatch(1);\n        final CountDownLatch connectEndLatch = new CountDownLatch(1);\n        Thread connectThread = new Thread() {\n            public void run() {\n                connectStartLatch.countDown();\n                try {\n                    dataSource.getConnection();\n                } catch (SQLException e) {\n                    errorHolder.set(e);\n                } finally {\n                    connectEndLatch.countDown();\n                }\n            }\n        };\n        connectThread.setName(\"ConnectThread\");\n        connectThread.start();\n\n        connectStartLatch.await();\n\n        latch.countDown();\n        connectEndLatch.await(3, TimeUnit.SECONDS);\n        SQLException ex = errorHolder.get();\n        assertTrue(ex instanceof DataSourceNotAvailableException);\n\n        for (int i = 0; i < 300; ++i) {\n            if (!dataSource.isFailContinuous()) {\n                break;\n            }\n            Thread.sleep(100 * 1);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/profile/ProfileEnableTest.java",
    "content": "package com.alibaba.druid.bvt.pool.profile;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\npublic class ProfileEnableTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMaxWait(1000);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void testDefault() throws Exception {\n        for (int i = 0; i < 10; ++i) {\n            DruidPooledConnection conn = dataSource.getConnection();\n            System.out.println(\"physicalConnectNanoSpan : \" + conn.getPhysicalConnectNanoSpan());\n            System.out.println(\"physicalConnectionUsedCount : \" + conn.getPhysicalConnectionUsedCount());\n            System.out.println(\"connectNotEmptyWaitNanos : \" + conn.getConnectNotEmptyWaitNanos());\n            conn.close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/property/PropertyTest_filters.java",
    "content": "package com.alibaba.druid.bvt.pool.property;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PropertyTest_filters extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    public void test_stat() {\n        System.setProperty(\"druid.filters\", \"stat\");\n        dataSource = new DruidDataSource();\n        assertEquals(1, dataSource.getProxyFilters().size());\n        assertEquals(\"com.alibaba.druid.filter.stat.StatFilter\", dataSource.getFilterClassNames().get(0));\n    }\n\n    public void test_false() {\n        System.setProperty(\"druid.filters\", \"\");\n        dataSource = new DruidDataSource();\n        assertEquals(0, dataSource.getProxyFilters().size());\n\n        assertNull(dataSource.getWallStatMap());\n    }\n\n    protected void tearDown() throws Exception {\n        System.clearProperty(\"druid.filters\");\n        JdbcUtils.close(dataSource);\n\n        super.tearDown();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/property/PropertyTest_testOnBorrow.java",
    "content": "package com.alibaba.druid.bvt.pool.property;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PropertyTest_testOnBorrow {\n    private DruidDataSource dataSource;\n\n    @Test\n    public void test_true() {\n        System.setProperty(\"druid.testOnBorrow\", \"true\");\n        dataSource = new DruidDataSource();\n        assertTrue(dataSource.isTestOnBorrow());\n    }\n\n    @Test\n    public void test_false() {\n        System.setProperty(\"druid.testOnBorrow\", \"false\");\n        dataSource = new DruidDataSource();\n        assertFalse(dataSource.isTestOnBorrow());\n\n        assertNull(dataSource.getWallStatMap());\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        System.clearProperty(\"druid.testOnBorrow\");\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/property/PropertyTest_testWhileIdle.java",
    "content": "package com.alibaba.druid.bvt.pool.property;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PropertyTest_testWhileIdle {\n    private DruidDataSource dataSource;\n\n    @Test\n    public void test_true() {\n        System.setProperty(\"druid.testWhileIdle\", \"true\");\n        dataSource = new DruidDataSource();\n        assertTrue(dataSource.isTestWhileIdle());\n    }\n\n    @Test\n    public void test_false() {\n        System.setProperty(\"druid.testWhileIdle\", \"false\");\n        dataSource = new DruidDataSource();\n        assertFalse(dataSource.isTestWhileIdle());\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        System.clearProperty(\"druid.testWhileIdle\");\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/property/PropertyTest_useGlobalDataSourceStat.java",
    "content": "package com.alibaba.druid.bvt.pool.property;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PropertyTest_useGlobalDataSourceStat {\n    private DruidDataSource dataSource;\n\n    @Test\n    public void test_true() {\n        System.setProperty(\"druid.useGlobalDataSourceStat\", \"true\");\n        dataSource = new DruidDataSource();\n        assertTrue(dataSource.isUseGlobalDataSourceStat());\n    }\n\n    @Test\n    public void test_false() {\n        System.setProperty(\"druid.useGlobalDataSourceStat\", \"false\");\n        dataSource = new DruidDataSource();\n        assertFalse(dataSource.isUseGlobalDataSourceStat());\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        System.clearProperty(\"druid.useGlobalDataSourceStat\");\n        JdbcUtils.close(dataSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/property/PropertyTest_validationQuery.java",
    "content": "package com.alibaba.druid.bvt.pool.property;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PropertyTest_validationQuery extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    public void test_validationQuery() {\n        System.setProperty(\"druid.validationQuery\", \"select 1\");\n        dataSource = new DruidDataSource();\n        assertEquals(\"select 1\", dataSource.getValidationQuery());\n    }\n\n    protected void tearDown() throws Exception {\n        System.clearProperty(\"druid.validationQuery\");\n        JdbcUtils.close(dataSource);\n\n        super.tearDown();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/InformixExceptionSorterTest.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.InformixExceptionSorter;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class InformixExceptionSorterTest extends PoolTestCase {\n    public void test_informix() throws Exception {\n        InformixExceptionSorter sorter = new InformixExceptionSorter();\n        assertEquals(false, sorter.isExceptionFatal(new SQLException()));\n\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -710)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79716)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79730)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79734)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79735)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79736)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79756)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79757)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79758)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79759)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79760)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79788)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79811)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79812)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79836)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79837)));\n        assertEquals(true, sorter.isExceptionFatal(new SQLException(\"\", \"\", -79879)));\n        assertEquals(false, sorter.isExceptionFatal(new SQLException(\"\", \"\", 100)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/MSSQLValidConnectionCheckerTest.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.pool.vendor.MSSQLValidConnectionChecker;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MSSQLValidConnectionCheckerTest extends PoolTestCase {\n    public void test_0() throws Exception {\n        MSSQLValidConnectionChecker checker = new MSSQLValidConnectionChecker();\n\n        MockConnection conn = new MockConnection();\n\n        assertTrue(checker.isValidConnection(conn, \"select 1\", 10));\n    }\n\n    public void test_closed() throws Exception {\n        MSSQLValidConnectionChecker checker = new MSSQLValidConnectionChecker();\n\n        MockConnection conn = new MockConnection();\n\n        conn.close();\n        assertFalse(checker.isValidConnection(conn, \"select 1\", 10));\n    }\n\n    public void test_error() throws Exception {\n        MSSQLValidConnectionChecker checker = new MSSQLValidConnectionChecker();\n\n        MockConnection conn = new MockConnection();\n        conn.setError(new SQLException());\n\n        SQLException error = null;\n        try {\n            checker.isValidConnection(conn, \"select 1\", 10);\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertSame(error, conn.getError());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySQLValidConnectionCheckerTest.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.vendor.MySqlValidConnectionChecker;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLValidConnectionCheckerTest extends PoolTestCase {\n    private DruidDataSource dataSource;\n\n    protected void setUp() throws Exception {\n        System.setProperty(\"druid.mysql.usePingMethod\", \"false\");\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setDbType(\"mysql\");\n        dataSource.setValidationQuery(\"select 1\");\n        dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker());\n        dataSource.setInitialSize(1);\n        dataSource.setTestOnBorrow(true);\n    }\n\n    protected void tearDown() throws Exception {\n        dataSource.close();\n\n        System.clearProperty(\"druid.mysql.usePingMethod\");\n    }\n\n    public void test_connect() throws Exception {\n        {\n            Connection conn = dataSource.getConnection();\n            conn.close();\n        }\n\n        MySqlValidConnectionChecker checker = (MySqlValidConnectionChecker) dataSource.getValidConnectionChecker();\n        assertFalse(checker.isUsePingMethod());\n\n        dataSource.setConnectionProperties(\"druid.mysql.usePingMethod=true\");\n\n        assertTrue(checker.isUsePingMethod());\n\n        Connection conn = dataSource.getConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.MySqlExceptionSorter;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlExceptionSorterTest extends PoolTestCase {\n    public void test_true() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"\", \"\", 1040)));\n    }\n\n    public void test_true_1() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"\", \"\", 1042)));\n    }\n\n    public void test_true_2() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"\", \"08xx\", 0)));\n    }\n\n    public void test_false_2() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"\", null, 0)));\n    }\n\n    public void test_false() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"\", \"\", -10001)));\n    }\n\n    public void test_false_1() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"\", \"\", -8000)));\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"\", \"\", -9100)));\n    }\n\n//    public void test_true_3() throws Exception {\n//        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n//        Class clazz = Class.forName(\"new com.mysql.jdbc.CommunicationsException\");\n//        clazz.getConstructor()\n//        assertTrue(sorter.isExceptionFatal(new com.mysql.jdbc.CommunicationsException(null, 0, 0, null)));\n//    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest_1.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.MySqlExceptionSorter;\nimport com.alibaba.druid.util.MySqlUtils;\n\nimport java.lang.reflect.Constructor;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 18/07/2017.\n */\npublic class MySqlExceptionSorterTest_1 extends PoolTestCase {\n    public void test_0() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n\n        Class clazz = MySqlUtils.getCommunicationsExceptionClass();\n\n        if (\"com.mysql.jdbc.CommunicationsException\".equals(clazz.getName())) {\n            Constructor constructor = null;\n            for (Constructor item : clazz.getConstructors()) {\n                if (item.getParameterTypes().length == 4) {\n                    constructor = item;\n                    break;\n                }\n            }\n\n            SQLException rootException = new SQLException(\n                    new SQLException(\"Could not retrieve transition read-only status server\",\n                            (Exception) constructor.newInstance(null, 0, 0, null)\n                    )\n            );\n\n            assertTrue(sorter.isExceptionFatal(rootException));\n        } else {\n            Constructor constructor = null;\n            for (Constructor item : clazz.getConstructors()) {\n                if (item.getParameterTypes().length == 2) {\n                    constructor = item;\n                    break;\n                }\n            }\n\n            SQLException rootException = new SQLException(\n                    new SQLException(\"Could not retrieve transition read-only status server\",\n                            (Exception) constructor.newInstance(null, null)\n                    )\n            );\n\n            assertTrue(sorter.isExceptionFatal(rootException));\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest_2.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.MySqlExceptionSorter;\n\nimport java.net.SocketTimeoutException;\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 18/07/2017.\n */\npublic class MySqlExceptionSorterTest_2 extends PoolTestCase {\n    public void test_0() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n\n        SQLException rootException = new SQLException(\n                new SQLException(\"Could not retrieve transition read-only status server\",\n                        new SocketTimeoutException()\n                )\n        );\n\n        assertTrue(sorter.isExceptionFatal(rootException));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/MySqlExceptionSorterTest_oceanbase.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.MySqlExceptionSorter;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlExceptionSorterTest_oceanbase extends PoolTestCase {\n    public void test_true() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        SQLException exception = new SQLException(\"\", \"\", -9000);\n        assertTrue(sorter.isExceptionFatal(exception));\n    }\n\n    public void test_true_1() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"\", \"\", -10000)));\n    }\n\n    public void test_false() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"\", \"\", -10001)));\n    }\n\n    public void test_false_1() throws Exception {\n        MySqlExceptionSorter sorter = new MySqlExceptionSorter();\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"\", \"\", -8000)));\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"\", \"\", -9100)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/PGExceptionSorterTest.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.PGExceptionSorter;\nimport org.postgresql.util.GT;\nimport org.postgresql.util.PSQLException;\nimport org.postgresql.util.PSQLState;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PGExceptionSorterTest extends PoolTestCase {\n    public void test_pg() throws Exception {\n        PGExceptionSorter exSorter = new PGExceptionSorter();\n\n        PSQLException ex = new PSQLException(GT.tr(\"Expected an EOF from server, got: {0}\", new Integer(0)),\n                PSQLState.COMMUNICATION_ERROR);\n        assertTrue(exSorter.isExceptionFatal(ex));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/SybaseExceptionSorterTest.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.vendor.SybaseExceptionSorter;\n\nimport java.sql.SQLException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SybaseExceptionSorterTest extends PoolTestCase {\n    public void test_false() throws Exception {\n        SybaseExceptionSorter sorter = new SybaseExceptionSorter();\n        assertFalse(sorter.isExceptionFatal(new SQLException()));\n    }\n\n    public void test_false_2() throws Exception {\n        SybaseExceptionSorter sorter = new SybaseExceptionSorter();\n        assertFalse(sorter.isExceptionFatal(new SQLException(\"xxx\")));\n    }\n\n    public void test_true() throws Exception {\n        SybaseExceptionSorter sorter = new SybaseExceptionSorter();\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"JZ0C0\")));\n    }\n\n    public void test_true_1() throws Exception {\n        SybaseExceptionSorter sorter = new SybaseExceptionSorter();\n        assertTrue(sorter.isExceptionFatal(new SQLException(\"JZ0C1\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/vendor/ValidConnectionCheckerAdapterTest.java",
    "content": "package com.alibaba.druid.bvt.pool.vendor;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.ValidConnectionCheckerAdapter;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ValidConnectionCheckerAdapterTest extends PoolTestCase {\n    public void test_adapter() throws Exception {\n        ValidConnectionCheckerAdapter adapter = new ValidConnectionCheckerAdapter();\n        adapter.configFromProperties(System.getProperties());\n        assertTrue(adapter.isValidConnection(null, null, 10));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/xa/H2XATest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.pool.xa;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.xa.DruidXADataSource;\nimport com.alibaba.druid.util.JdbcUtils;\n\nimport javax.sql.XAConnection;\n\npublic class H2XATest extends PoolTestCase {\n    private DruidXADataSource dataSource;\n\n    protected void setUp() throws Exception {\n        super.setUp();\n\n        dataSource = new DruidXADataSource();\n        dataSource.setMinIdle(1);\n        dataSource.setUrl(\"jdbc:h2:mem:test;\");\n        dataSource.setTestOnBorrow(false);\n\n        JdbcUtils.execute(dataSource, \"CREATE TABLE user (id INT, name VARCHAR(40))\");\n    }\n\n    protected void tearDown() throws Exception {\n        JdbcUtils.execute(dataSource, \"DROP TABLE user\");\n        JdbcUtils.close(dataSource);\n\n        super.tearDown();\n    }\n\n    public void test_0() throws Exception {\n        XAConnection conn = dataSource.getXAConnection();\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/pool/xa/JtdsXAConnectionTest.java",
    "content": "package com.alibaba.druid.bvt.pool.xa;\n\nimport com.alibaba.druid.PoolTestCase;\nimport com.alibaba.druid.pool.xa.JtdsXAConnection;\nimport com.alibaba.druid.pool.xa.JtdsXAResource;\nimport net.sourceforge.jtds.jdbc.JtdsConnection;\n\nimport java.lang.reflect.Constructor;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class JtdsXAConnectionTest extends PoolTestCase {\n    public void test_jtds() throws Exception {\n        Constructor<JtdsConnection> constrcutor = JtdsConnection.class.getDeclaredConstructor();\n        constrcutor.setAccessible(true);\n        JtdsConnection jtdsConn = constrcutor.newInstance();\n        JtdsXAConnection xaConn = new JtdsXAConnection(jtdsConn);\n        assertSame(jtdsConn, xaConn.getConnection());\n\n        JtdsXAResource xaResource = (JtdsXAResource) xaConn.getXAResource();\n        assertTrue(xaResource.isSameRM(xaResource));\n        assertFalse(xaResource.isSameRM(null));\n\n        {\n            Exception error = null;\n            try {\n                xaResource.commit(null, true);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                xaResource.start(null, 0);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                xaResource.end(null, 0);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                xaResource.forget(null);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                xaResource.rollback(null);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        xaResource.recover(0);\n        {\n            Exception error = null;\n            try {\n                xaResource.prepare(null);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        xaConn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/AllStatisticTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.openmbean.TabularData;\n\nimport java.math.BigDecimal;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class AllStatisticTest {\n    String url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=statTest:jdbc:derby:classpath:petstore-db\";\n\n    private AtomicLong fetchRowCout = new AtomicLong();\n\n    Connection globalConnection;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager stat = JdbcStatManager.getInstance();\n\n        stat.reset();\n\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(url);\n\n        int size = stat.getConnectionList().size();\n        assertTrue(size >= 1);\n        conn.close();\n\n        TabularData connectionList = stat.getConnectionList();\n\n        assertEquals(connectionList.size(), size - 1);\n\n        stat.reset();\n\n        globalConnection = DriverManager.getConnection(url);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(globalConnection);\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_stmt() throws Exception {\n        // ////////////////////////\n\n        f1();\n        f2();\n        f3();\n    }\n\n    public void f1() throws Exception {\n        Statement pstmt = null;\n        ResultSet rs = null;\n\n        try {\n            pstmt = globalConnection.createStatement();\n            rs = pstmt.executeQuery(\"SELECT * FROM ITEM WHERE LISTPRICE > 10\");\n            while (rs.next()) {\n                fetchRowCout.incrementAndGet();\n                rs.getObject(1);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(pstmt);\n        }\n    }\n\n    public void f2() throws Exception {\n        Connection conn = null;\n        Statement pstmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(url);\n\n            pstmt = conn.createStatement();\n            rs = pstmt.executeQuery(\"SELECT * FROM ITxEM WHERE LISTPRICE > 10\");\n            while (rs.next()) {\n                fetchRowCout.incrementAndGet();\n                rs.getObject(1);\n            }\n        } catch (SQLException ex) {\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    public void f3() throws Exception {\n        Connection conn = null;\n        PreparedStatement pstmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(url);\n\n            pstmt = conn.prepareStatement(\"SELECT * FROM ITEM WHERE LISTPRICE > ?\");\n            pstmt.setBigDecimal(1, new BigDecimal(10));\n            rs = pstmt.executeQuery();\n            while (rs.next()) {\n                fetchRowCout.incrementAndGet();\n                rs.getObject(1);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/BasicTypeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BasicTypeTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=basicType:jdbc:derby:memory:basicTypeTestDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createDDL();\n\n        conn.close();\n    }\n\n    private void createDDL() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_BASIC_TYPE (F1 FLOAT, F2 DOUBLE, F3 REAL, F4 DATE, F5 TIME, F6 SMALLINT, F7 SMALLINT, F8 INTEGER, F9 BIGINT, F10 DECIMAL(9,2), F11 TIMESTAMP, F12 BLOB, F13 VARCHAR(256), F14 VARCHAR(256), F15 VARCHAR(256), F16 VARCHAR(256), F17 SMALLINT)\");\n        stmt.execute(\"CREATE PROCEDURE BASIC_CALL_0(INOUT F1 FLOAT, INOUT F2 DOUBLE, INOUT F3 REAL, INOUT F4 DATE, INOUT F5 TIME, INOUT F6 SMALLINT, INOUT F7 SMALLINT, INOUT F8 INTEGER, INOUT F9 BIGINT, INOUT F10 DECIMAL(9,2), INOUT F11 TIMESTAMP, INOUT F12 VARCHAR(128) FOR BIT DATA, INOUT F13 VARCHAR(256), INOUT F14 VARCHAR(256), INOUT F15 VARCHAR(256), INOUT F16 VARCHAR(256), INOUT F17 SMALLINT) \"\n                + \"LANGUAGE JAVA PARAMETER STYLE JAVA EXTERNAL NAME '\"\n                + BasicTypeTest.class.getName()\n                + \".basic_process_0' \" + \"DYNAMIC RESULT SETS 1\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_BASIC_TYPE\");\n        stmt.execute(\"DROP PROCEDURE BASIC_CALL_0\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n\n        DruidDriver.getProxyDataSources().clear();\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_basicType() throws Exception {\n        Connection conn = null;\n        PreparedStatement pstmt = null;\n        CallableStatement cstmt = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n            conn.rollback();\n\n            pstmt = conn.prepareStatement(\"INSERT INTO T_BASIC_TYPE (F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\");\n            pstmt.getParameterMetaData();\n\n            pstmt.setFloat(1, 1F);\n            pstmt.setDouble(2, 2.1D);\n            pstmt.setFloat(3, 2.1F);\n            pstmt.setDate(4, new java.sql.Date(System.currentTimeMillis()));\n            pstmt.setDate(4, new java.sql.Date(System.currentTimeMillis()), Calendar.getInstance());\n            pstmt.setTime(5, new java.sql.Time(System.currentTimeMillis()));\n            pstmt.setTime(5, new java.sql.Time(System.currentTimeMillis()), Calendar.getInstance());\n            pstmt.setByte(6, (byte) 33);\n            pstmt.setShort(7, (short) 44);\n            pstmt.setInt(8, 55);\n            pstmt.setLong(9, 66);\n            pstmt.setBigDecimal(10, new BigDecimal(\"77\"));\n            pstmt.setTimestamp(11, new java.sql.Timestamp(System.currentTimeMillis()));\n            pstmt.setTimestamp(11, new java.sql.Timestamp(System.currentTimeMillis()), Calendar.getInstance());\n            pstmt.setBytes(12, new byte[100]);\n            pstmt.setAsciiStream(13, null);\n            pstmt.setAsciiStream(14, null, 0);\n            pstmt.setAsciiStream(14, null, 0L);\n            pstmt.setCharacterStream(15, null);\n            pstmt.setCharacterStream(16, null, 0);\n            pstmt.setCharacterStream(16, null, 0L);\n            pstmt.setNull(16, Types.VARCHAR);\n            pstmt.setNull(16, Types.VARCHAR, \"VARCHAR\");\n            pstmt.setObject(16, null, Types.VARCHAR);\n            pstmt.setObject(16, null, Types.VARCHAR, 0);\n            pstmt.setBoolean(17, true);\n            pstmt.execute();\n            pstmt.clearParameters();\n            JdbcUtils.close(pstmt);\n\n            stmt = conn.createStatement();\n            stmt.close();\n\n            stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);\n            stmt.close();\n\n            stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE,\n                    ResultSet.CLOSE_CURSORS_AT_COMMIT);\n            stmt.setQueryTimeout(stmt.getQueryTimeout());\n            stmt.setEscapeProcessing(true);\n            stmt.clearBatch();\n            stmt.clearWarnings();\n            stmt.setCursorName(\"demo_cur\");\n\n            conn.setAutoCommit(false);\n            Savepoint point = conn.setSavepoint();\n            point = conn.setSavepoint(\"save_point\");\n\n            rs = stmt.executeQuery(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17 FROM T_BASIC_TYPE\");\n            rs.next();\n            rs.getFloat(1);\n            rs.getDouble(2);\n            rs.getFloat(3);\n            rs.getDate(4);\n            rs.getDate(4, Calendar.getInstance());\n            rs.getTime(5);\n            rs.getTime(5, Calendar.getInstance());\n            rs.getByte(6);\n            rs.getShort(7);\n            rs.getInt(8);\n            rs.getLong(9);\n            rs.getBigDecimal(10);\n            rs.getBigDecimal(10, 2);\n            rs.getTimestamp(11);\n            rs.getTimestamp(11, Calendar.getInstance());\n            rs.getBytes(12);\n            rs.getBlob(12).free();\n            rs.getString(13);\n            rs.getAsciiStream(13);\n            rs.getCharacterStream(14);\n            rs.getObject(15, new HashMap<String, Class<?>>());\n\n            rs.getHoldability();\n\n            rs.updateFloat(1, 2F);\n            rs.updateDouble(2, 2D);\n            rs.updateDate(4, new java.sql.Date(System.currentTimeMillis()));\n            rs.updateTime(5, new java.sql.Time(System.currentTimeMillis()));\n            rs.updateByte(6, (byte) 6);\n            rs.updateShort(7, (short) 77);\n            rs.updateInt(8, 77);\n            rs.updateLong(9, 99);\n            rs.updateBigDecimal(10, new BigDecimal(\"10\"));\n            rs.updateTimestamp(11, new java.sql.Timestamp(System.currentTimeMillis()));\n            rs.updateBytes(12, new byte[300]);\n            rs.updateBinaryStream(12, null);\n            rs.updateBinaryStream(12, null, 0);\n            rs.updateBinaryStream(12, null, 0L);\n            rs.updateString(13, \"13x\");\n            rs.updateAsciiStream(13, null);\n            rs.updateAsciiStream(13, null, 0);\n            rs.updateAsciiStream(13, null, 0L);\n            rs.updateCharacterStream(14, null);\n            rs.updateCharacterStream(14, null, 0);\n            rs.updateCharacterStream(14, null, 0L);\n            rs.updateNull(14);\n            rs.updateObject(15, \"object\");\n            rs.updateObject(15, \"object\", 0);\n            rs.updateBoolean(17, false);\n            rs.updateRow();\n\n            JdbcUtils.close(rs);\n//            conn.rollback(point);\n            conn.setAutoCommit(true);\n\n            rs = stmt.executeQuery(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17 FROM T_BASIC_TYPE\");\n            rs.next();\n            rs.getFloat(\"F1\");\n            rs.getDouble(\"F2\");\n            rs.getFloat(\"F3\");\n            rs.getDate(\"F4\");\n            rs.getDate(\"F4\", Calendar.getInstance());\n            rs.getTime(\"F5\");\n            rs.getTime(\"F5\", Calendar.getInstance());\n            rs.getByte(\"F6\");\n            rs.getShort(\"F7\");\n            rs.getInt(\"F8\");\n            rs.getLong(\"F9\");\n            rs.getBigDecimal(\"F10\");\n            rs.getBigDecimal(\"F10\", 2);\n            rs.getTimestamp(\"F11\");\n            rs.getTimestamp(\"F11\", Calendar.getInstance());\n            rs.getBytes(\"F12\");\n            rs.getBlob(\"F12\");\n            rs.getString(\"F13\");\n            rs.getAsciiStream(\"F13\");\n            rs.getCharacterStream(\"F14\");\n            rs.getObject(\"F15\", new HashMap<String, Class<?>>());\n\n            rs.updateFloat(\"F1\", 2F);\n            rs.updateDouble(\"F2\", 2D);\n            rs.updateDate(\"F4\", new java.sql.Date(System.currentTimeMillis()));\n            rs.updateTime(\"F5\", new java.sql.Time(System.currentTimeMillis()));\n            rs.updateByte(\"F6\", (byte) 6);\n            rs.updateShort(\"F7\", (short) 77);\n            rs.updateInt(\"F8\", 77);\n            rs.updateLong(\"F9\", 99);\n            rs.updateBigDecimal(\"F10\", new BigDecimal(\"10\"));\n            rs.updateTimestamp(\"F11\", new java.sql.Timestamp(System.currentTimeMillis()));\n            rs.updateBytes(\"F12\", new byte[300]);\n            rs.updateBinaryStream(\"F12\", null);\n            rs.updateBinaryStream(\"F12\", null, 0);\n            rs.updateBinaryStream(\"F12\", null, 0L);\n            rs.updateString(\"F13\", \"13x\");\n            rs.updateAsciiStream(\"F13\", null);\n            rs.updateAsciiStream(\"F13\", null, 0);\n            rs.updateAsciiStream(\"F13\", null, 0L);\n            rs.updateCharacterStream(\"F14\", null);\n            rs.updateCharacterStream(\"F14\", null, 0);\n            rs.updateCharacterStream(\"F14\", null, 0L);\n            rs.updateNull(\"F14\");\n            rs.updateObject(\"F15\", \"object\");\n            rs.updateObject(\"F15\", \"object\", 0);\n            rs.updateBoolean(\"F17\", false);\n            rs.cancelRowUpdates();\n            rs.deleteRow();\n\n            assertEquals(12, rs.findColumn(\"F12\"));\n            JdbcUtils.close(rs);\n\n            pstmt = conn.prepareStatement(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16 FROM T_BASIC_TYPE\");\n            JdbcUtils.close(pstmt);\n\n            pstmt = conn.prepareStatement(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16 FROM T_BASIC_TYPE\",\n                    new int[]{1, 2});\n            JdbcUtils.close(pstmt);\n\n            pstmt = conn.prepareStatement(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16 FROM T_BASIC_TYPE\",\n                    new String[]{\"F1\", \"F2\"});\n            JdbcUtils.close(pstmt);\n\n            pstmt = conn.prepareStatement(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16 FROM T_BASIC_TYPE\",\n                    Statement.RETURN_GENERATED_KEYS);\n            JdbcUtils.close(pstmt);\n\n            pstmt = conn.prepareStatement(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16 FROM T_BASIC_TYPE\",\n                    ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);\n            pstmt.executeQuery().close();\n            JdbcUtils.close(pstmt);\n\n            pstmt = conn.prepareStatement(\"SELECT F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16 FROM T_BASIC_TYPE\",\n                    ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE,\n                    ResultSet.CLOSE_CURSORS_AT_COMMIT);\n            JdbcUtils.close(pstmt);\n\n            cstmt = conn.prepareCall(\"CALL BASIC_CALL_0(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\");\n            cstmt.registerOutParameter(1, Types.FLOAT);\n            cstmt.registerOutParameter(2, Types.DOUBLE);\n            cstmt.registerOutParameter(3, Types.FLOAT);\n            cstmt.registerOutParameter(4, Types.DATE);\n            cstmt.registerOutParameter(5, Types.TIME);\n\n            cstmt.registerOutParameter(6, Types.TINYINT);\n            cstmt.registerOutParameter(7, Types.SMALLINT);\n            cstmt.registerOutParameter(8, Types.INTEGER);\n            cstmt.registerOutParameter(9, Types.BIGINT);\n            cstmt.registerOutParameter(10, Types.DECIMAL);\n            cstmt.registerOutParameter(10, Types.DECIMAL, 2);\n            try {\n                cstmt.registerOutParameter(10, Types.DECIMAL, \"DECIMAL\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            cstmt.registerOutParameter(11, Types.TIMESTAMP);\n            cstmt.registerOutParameter(12, Types.BINARY);\n            cstmt.registerOutParameter(13, Types.VARCHAR);\n            cstmt.registerOutParameter(14, Types.VARCHAR);\n            cstmt.registerOutParameter(15, Types.VARCHAR);\n\n            cstmt.registerOutParameter(16, Types.VARCHAR);\n            cstmt.registerOutParameter(17, Types.BOOLEAN);\n\n            //\n            try {\n                cstmt.registerOutParameter(\"F2\", Types.DECIMAL);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.registerOutParameter(\"F2\", Types.DECIMAL, 2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.registerOutParameter(\"F2\", Types.DECIMAL, \"DECIMAL\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            // cstmt.registerOutParameter(18, Types.OTHER);\n\n            cstmt.setFloat(1, 1F);\n            cstmt.setDouble(2, 2.1D);\n            cstmt.setFloat(3, 2.1F);\n            cstmt.setDate(4, new java.sql.Date(System.currentTimeMillis()));\n            cstmt.setDate(4, new java.sql.Date(System.currentTimeMillis()), Calendar.getInstance());\n            cstmt.setTime(5, new java.sql.Time(System.currentTimeMillis()));\n            cstmt.setTime(5, new java.sql.Time(System.currentTimeMillis()), Calendar.getInstance());\n            cstmt.setByte(6, (byte) 33);\n            cstmt.setShort(7, (short) 44);\n            cstmt.setInt(8, 55);\n            cstmt.setLong(9, 66);\n            cstmt.setBigDecimal(10, new BigDecimal(\"77\"));\n            cstmt.setTimestamp(11, new java.sql.Timestamp(System.currentTimeMillis()));\n            cstmt.setTimestamp(11, new java.sql.Timestamp(System.currentTimeMillis()), Calendar.getInstance());\n            cstmt.setBinaryStream(12, null);\n            cstmt.setBinaryStream(12, null, 0);\n            cstmt.setBinaryStream(12, null, 0L);\n            cstmt.setBytes(12, new byte[100]);\n            cstmt.setAsciiStream(13, null);\n            cstmt.setAsciiStream(14, null, 0);\n            cstmt.setAsciiStream(14, null, 0L);\n            cstmt.setString(15, null);\n            cstmt.setCharacterStream(15, null);\n            cstmt.setCharacterStream(16, null, 0);\n            cstmt.setCharacterStream(16, null, 0L);\n            cstmt.setNull(16, Types.VARCHAR);\n            cstmt.setObject(16, null, Types.VARCHAR);\n            cstmt.setBoolean(17, true);\n\n            try {\n                cstmt.setFloat(\"F1\", 1F);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setDouble(\"F2\", 2.1D);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setFloat(\"F3\", 2.1F);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setDate(\"F4\", new java.sql.Date(System.currentTimeMillis()));\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setDate(\"F4\", new java.sql.Date(System.currentTimeMillis()), Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setTime(\"F5\", new java.sql.Time(System.currentTimeMillis()));\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setTime(\"F5\", new java.sql.Time(System.currentTimeMillis()), Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setByte(\"F6\", (byte) 33);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setShort(\"F7\", (short) 44);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setInt(\"F8\", 55);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setLong(\"F9\", 66);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setBigDecimal(\"F10\", new BigDecimal(\"77\"));\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setTimestamp(\"F11\", new java.sql.Timestamp(System.currentTimeMillis()));\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setTimestamp(\"F11\", new java.sql.Timestamp(System.currentTimeMillis()), Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setBytes(\"F12\", new byte[100]);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setBinaryStream(\"F12\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setBinaryStream(\"F12\", null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setBinaryStream(\"F12\", null, 0L);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setAsciiStream(\"F13\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setAsciiStream(\"F14\", null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setAsciiStream(\"F14\", null, 0L);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setCharacterStream(\"F15\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setCharacterStream(\"F16\", null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setCharacterStream(\"F16\", null, 0L);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setString(\"F16\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setObject(\"F16\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setObject(\"F16\", null, Types.VARCHAR);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setNull(\"F16\", Types.VARCHAR);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setBoolean(\"F17\", true);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            cstmt.execute();\n\n            try {\n                cstmt.getFloat(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getDouble(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getFloat(3);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getDate(4);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getDate(4, Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTime(5);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTime(5, Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getByte(6);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getShort(7);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getInt(8);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getLong(9);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBigDecimal(10);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBigDecimal(10, 2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTimestamp(11);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTimestamp(11, Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBytes(12);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBlob(12).free();\n            } catch (SQLException ex) {\n            }\n            try {\n                cstmt.getString(13);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getCharacterStream(14);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getObject(15);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getObject(15, new HashMap<String, Class<?>>());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBoolean(17);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            // /\n\n            try {\n                cstmt.getFloat(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getDouble(\"F2\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getFloat(\"F3\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getDate(\"F4\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getDate(\"F4\", Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTime(\"F5\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTime(\"F5\", Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getByte(\"F6\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getShort(\"F7\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getInt(\"F8\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getLong(\"F9\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBigDecimal(\"F10\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTimestamp(\"F11\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getTimestamp(\"F11\", Calendar.getInstance());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBytes(\"F12\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBlob(\"F12\").free();\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getString(\"F13\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getCharacterStream(\"F14\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getObject(\"F15\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getObject(\"F15\", new HashMap<String, Class<?>>());\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getBoolean(\"F17\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            cstmt.wasNull();\n\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(cstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    public static void basic_process_0(double[] p1, double[] p2, float[] p3, java.sql.Date[] p4, java.sql.Time[] p5,\n                                       short[] p6, short[] p7, int[] p8, long[] p9, BigDecimal[] p10,\n                                       java.sql.Timestamp[] p11, byte[][] p12, String[] p13, String[] p14,\n                                       String[] p15, String[] p16, short[] P17, ResultSet[] p18) {\n        // stmt.execute(\"CREATE TABLE T_BASIC_TYPE (F1 FLOAT, F2 DOUBLE, F3\n        // REAL, F4 DATE,\n        // F5 TIME, F6 SMALLINT, F7 SMALLINT, F8 INTEGER, F9 BIGINT, F10\n        // DECIMAL(9,2),\n        // F11 TIMESTAMP, F12 BLOB, F13 VARCHAR(256), F14 VARCHAR(256), F15\n        // VARCHAR(256), F16 VARCHAR(256), F17 SMALLINT)\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/BatchReadTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BatchReadTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=batchReadTest:jdbc:derby:memory:batchDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        JdbcStatManager.getInstance();\n\n        createTable();\n\n        conn.close();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_USER (ID INTEGER, NAME VARCHAR(50), BIRTHDATE TIMESTAMP)\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_USER\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n\n        DruidDriver.getProxyDataSources().clear();\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_stmt_batch() throws Exception {\n        Connection conn = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            stmt = conn.createStatement();\n\n            stmt.isClosed();\n            stmt.isPoolable();\n\n            stmt.addBatch(\"INSERT INTO T_USER (ID, NAME, BIRTHDATE) VALUES (1, 'A', NULL)\");\n            stmt.addBatch(\"INSERT INTO T_USER (ID, NAME, BIRTHDATE) VALUES (2, 'B', NULL)\");\n            stmt.executeBatch();\n\n            for (; ; ) {\n                boolean moreResults = stmt.getMoreResults();\n\n                if (moreResults) {\n                    rs = stmt.getResultSet();\n                    JdbcUtils.printResultSet(rs, System.out);\n                    JdbcUtils.close(rs);\n                    continue;\n                }\n\n                int updateCount = stmt.getUpdateCount();\n                if (updateCount == -1) {\n                    break;\n                }\n            }\n\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n\n    @Test\n    public void test_pstmt_batch() throws Exception {\n        Connection conn = null;\n        Statement stmt = null;\n        PreparedStatement pstmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            stmt = conn.createStatement();\n\n            pstmt = conn.prepareStatement(\"INSERT INTO T_USER (ID, NAME, BIRTHDATE) VALUES (?, ?, ?)\");\n\n            pstmt.setInt(1, 1);\n            pstmt.setString(2, \"A\");\n            pstmt.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()));\n            pstmt.addBatch();\n\n            pstmt.setInt(1, 2);\n            pstmt.setString(2, \"B\");\n            pstmt.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()));\n            pstmt.addBatch();\n\n            int[] updateCounts = pstmt.executeBatch();\n\n            assertArrayEquals(new int[]{1, 1}, updateCounts);\n\n            pstmt.setFetchDirection(stmt.getFetchDirection());\n            pstmt.setFetchSize(pstmt.getFetchSize());\n            ResultSet keys = stmt.getGeneratedKeys();\n            JdbcUtils.close(keys);\n\n            // just call\n            stmt.getConnection();\n            stmt.setMaxFieldSize(stmt.getMaxFieldSize());\n            stmt.setMaxRows(stmt.getMaxRows());\n            stmt.getQueryTimeout();\n            stmt.getResultSetConcurrency();\n            stmt.getResultSetHoldability();\n            stmt.getResultSetType();\n            stmt.setPoolable(true);\n            stmt.getWarnings();\n\n            pstmt.getMetaData();\n            pstmt.getParameterMetaData();\n            pstmt.getWarnings();\n\n            stmt.execute(\"SELECT * FROM T_USER\");\n            for (; ; ) {\n                rs = stmt.getResultSet();\n\n                rs.getWarnings();\n\n                if (rs != null) {\n                    JdbcUtils.printResultSet(rs, System.out);\n                    JdbcUtils.close(rs);\n                }\n\n                if ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1)) {\n                    break;\n                }\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/BlobTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.ByteArrayInputStream;\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BlobTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=demo:jdbc:derby:memory:blobTestDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createTable();\n\n        conn.close();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_BLOB (ID INTEGER, DATA BLOB)\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_BLOB\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n\n        DruidDriver.getProxyDataSources().clear();\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_blob() throws Exception {\n        Connection conn = null;\n        PreparedStatement pstmt = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            conn.setCatalog(conn.getCatalog());\n            conn.setClientInfo(conn.getClientInfo());\n            conn.setHoldability(conn.getHoldability());\n            conn.setReadOnly(conn.isReadOnly());\n            conn.setTransactionIsolation(conn.getTransactionIsolation());\n            conn.setTypeMap(conn.getTypeMap());\n\n            pstmt = conn.prepareStatement(\"INSERT INTO T_BLOB (ID, DATA) VALUES (?, ?)\");\n\n            Blob blob = conn.createBlob();\n\n            blob.setBytes(1, new byte[100]);\n\n            pstmt.setInt(1, 1);\n            pstmt.setBlob(2, blob);\n\n            int updateCount = pstmt.executeUpdate();\n            assertEquals(1, updateCount);\n\n            pstmt.setInt(1, 2);\n            pstmt.setBlob(2, new ByteArrayInputStream(\"XBCSDasdfasdfasfasfF\".getBytes()));\n            updateCount = pstmt.executeUpdate();\n            assertEquals(1, updateCount);\n\n            pstmt.setInt(1, 2);\n            pstmt.setBlob(2, new ByteArrayInputStream(\"XBCSDasdfasdfasfasfF\".getBytes()), 20);\n            updateCount = pstmt.executeUpdate();\n            assertEquals(1, updateCount);\n\n            stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE,\n                    ResultSet.CLOSE_CURSORS_AT_COMMIT);\n\n            conn.nativeSQL(\"SELECT ID, DATA FROM T_BLOB\");\n            // //////\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            rs.getStatement(); // just call\n            while (rs.next()) {\n                Blob readBlob = rs.getBlob(2);\n                readBlob.length();\n                readBlob.getBinaryStream(1, 10).close();\n                readBlob.getBinaryStream().close();\n                readBlob.free();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.getBinaryStream(2).close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.getBinaryStream(\"DATA\").close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.getBytes(2);\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                Blob x = conn.createBlob();\n                x.setBytes(1, new byte[100]);\n                rs.updateBlob(2, x);\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                Blob x = conn.createBlob();\n                x.setBytes(1, new byte[100]);\n                rs.updateBlob(\"DATA\", x);\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.updateBlob(\"DATA\", new ByteArrayInputStream(new byte[100]));\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.updateBlob(2, new ByteArrayInputStream(new byte[100]));\n            }\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.updateBlob(\"DATA\", new ByteArrayInputStream(new byte[100]), 100);\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.updateBlob(2, new ByteArrayInputStream(new byte[100]), 100);\n            }\n            JdbcUtils.close(rs);\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/CallStatementTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CallStatementTest {\n    /**\n     * Procedures that should be created before the tests are run and dropped when the tests have finished. First\n     * element in each row is the name of the procedure, second element is SQL which creates it.\n     */\n    private static final String[] PROCEDURES = {\n            \"CREATE PROCEDURE RETRIEVE_DYNAMIC_RESULTS(number INT) \"\n                    + \"LANGUAGE JAVA PARAMETER STYLE JAVA EXTERNAL NAME '\" + CallStatementTest.class.getName()\n                    + \".retrieveDynamicResults' \" + \"DYNAMIC RESULT SETS 4\",\n\n            \"CREATE PROCEDURE RETRIEVE_CLOSED_RESULT() LANGUAGE JAVA \" + \"PARAMETER STYLE JAVA EXTERNAL NAME '\"\n                    + CallStatementTest.class.getName() + \".retrieveClosedResult' \" + \"DYNAMIC RESULT SETS 1\",\n\n            \"CREATE PROCEDURE RETRIEVE_EXTERNAL_RESULT(\"\n                    + \"DBNAME VARCHAR(128), DBUSER VARCHAR(128), DBPWD VARCHAR(128)) LANGUAGE JAVA \"\n                    + \"PARAMETER STYLE JAVA EXTERNAL NAME '\" + CallStatementTest.class.getName()\n                    + \".retrieveExternalResult' \" + \"DYNAMIC RESULT SETS 1\",\n\n            \"CREATE PROCEDURE PROC_WITH_SIDE_EFFECTS(ret INT) LANGUAGE JAVA \" + \"PARAMETER STYLE JAVA EXTERNAL NAME '\"\n                    + CallStatementTest.class.getName() + \".procWithSideEffects' \" + \"DYNAMIC RESULT SETS 2\",\n\n            \"CREATE PROCEDURE NESTED_RESULT_SETS(proctext VARCHAR(128)) LANGUAGE JAVA \"\n                    + \"PARAMETER STYLE JAVA EXTERNAL NAME '\" + CallStatementTest.class.getName()\n                    + \".nestedDynamicResultSets' \" + \"DYNAMIC RESULT SETS 6\"\n\n    };\n\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=demo:jdbc:derby:memory:callableStatementDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createTable();\n\n        conn.close();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_CLOB (ID INTEGER, DATA CLOB)\");\n\n        for (int i = 0; i < PROCEDURES.length; i++) {\n            stmt.execute(PROCEDURES[i]);\n        }\n\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_CLOB\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_precall() throws Exception {\n        f_testExecuteQueryWithNoDynamicResultSets();\n        f_testExecuteQueryWithNoDynamicResultSets_callable();\n    }\n\n    public void f_testExecuteQueryWithNoDynamicResultSets() throws SQLException {\n        Connection connect = DriverManager.getConnection(create_url);\n        Statement stmt = connect.createStatement();\n        SQLException error = null;\n        try {\n            stmt.executeQuery(\"CALL RETRIEVE_DYNAMIC_RESULTS(0)\");\n        } catch (SQLException sqle) {\n            error = sqle;\n        }\n\n        assertNotNull(error);\n        stmt.close();\n        connect.close();\n    }\n\n    public void f_testExecuteQueryWithNoDynamicResultSets_callable() throws SQLException {\n        Connection connect = DriverManager.getConnection(create_url);\n        CallableStatement cs = connect.prepareCall(\"CALL RETRIEVE_DYNAMIC_RESULTS(?)\");\n        cs.setInt(1, 0);\n        SQLException error = null;\n        try {\n            cs.executeQuery();\n            fail(\"executeQuery() didn't fail.\");\n        } catch (SQLException sqle) {\n            error = sqle;\n        }\n        assertNotNull(error);\n        cs.close();\n        connect.close();\n    }\n\n    public static void retrieveClosedResult(ResultSet[] closed) throws SQLException {\n        Connection connect = DriverManager.getConnection(create_url);\n        closed[0] = connect.createStatement().executeQuery(\"VALUES(1)\");\n        closed[0].close();\n        connect.close();\n    }\n\n    public static void retrieveExternalResult(String dbName, String user, String password, ResultSet[] external)\n            throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n\n        external[0] = conn.createStatement().executeQuery(\"VALUES(1)\");\n    }\n\n    public static void selectRows(int p1, ResultSet[] data) throws SQLException {\n        System.out.println(\"selectRows - 1 arg - 1 rs\");\n\n        Connection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n        PreparedStatement ps = conn.prepareStatement(\"select * from t1 where i = ?\");\n        ps.setInt(1, p1);\n        data[0] = ps.executeQuery();\n        conn.close();\n    }\n\n    public static void selectRows(int p1, int p2, ResultSet[] data1, ResultSet[] data2) throws SQLException {\n        System.out.println(\"selectRows - 2 arg - 2 rs\");\n\n        Connection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n        PreparedStatement ps = conn.prepareStatement(\"select * from t1 where i = ?\");\n        ps.setInt(1, p1);\n        data1[0] = ps.executeQuery();\n\n        ps = conn.prepareStatement(\"select * from t1 where i >= ?\");\n        ps.setInt(1, p2);\n        data2[0] = ps.executeQuery();\n\n        if (p2 == 99) {\n            data2[0].close();\n        }\n\n        // return no results\n        if (p2 == 199) {\n            data1[0].close();\n            data1[0] = null;\n            data2[0].close();\n            data2[0] = null;\n        }\n\n        // swap results\n        if (p2 == 299) {\n            ResultSet rs = data1[0];\n            data1[0] = data2[0];\n            data2[0] = rs;\n        }\n\n        conn.close();\n    }\n\n    // select all rows from a table\n    public static void selectRows(String table, ResultSet[] rs) throws SQLException {\n        Connection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n        Statement stmt = conn.createStatement();\n        rs[0] = stmt.executeQuery(\"SELECT * FROM \" + table);\n        conn.close();\n    }\n\n    public static void fivejp(ResultSet[] data1, ResultSet[] data2, ResultSet[] data3, ResultSet[] data4,\n                              ResultSet[] data5) throws SQLException {\n        Connection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n\n        PreparedStatement ps1 = conn.prepareStatement(\"select * from MRS.FIVERS where i > ?\");\n        ps1.setInt(1, 1);\n        data1[0] = ps1.executeQuery();\n\n        PreparedStatement ps2 = conn.prepareStatement(\"select * from MRS.FIVERS  where i > ?\");\n        ps2.setInt(1, 2);\n        data2[0] = ps2.executeQuery();\n\n        PreparedStatement ps3 = conn.prepareStatement(\"select * from MRS.FIVERS  where i > ?\");\n        ps3.setInt(1, 3);\n        data3[0] = ps3.executeQuery();\n\n        PreparedStatement ps4 = conn.prepareStatement(\"select * from MRS.FIVERS  where i > ?\");\n        ps4.setInt(1, 4);\n        data4[0] = ps4.executeQuery();\n\n        PreparedStatement ps5 = conn.prepareStatement(\"select * from MRS.FIVERS  where i > ?\");\n        ps5.setInt(1, 5);\n        data5[0] = ps5.executeQuery();\n\n        conn.close();\n    }\n\n    public static void parameter1(int a, String b, String c, java.sql.ResultSet[] rs) throws SQLException {\n        System.out.print(\"PT1 a=\" + a);\n        if (b == null) {\n            System.out.println(\" b = null\");\n        } else {\n            System.out.print(\" b=<\" + b + \">(\" + b.length() + \")\");\n        }\n        if (c == null) {\n            System.out.println(\" c = null\");\n        } else {\n            System.out.print(\" c=<\" + c + \">(\" + c.length() + \")\");\n        }\n\n        System.out.println(\"\");\n\n        Connection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n        PreparedStatement ps = conn.prepareStatement(\"insert into PT1 values (?, ?, ?)\");\n        ps.setInt(1, a);\n        ps.setString(2, b);\n        ps.setString(3, c);\n        ps.executeUpdate();\n        ps.close();\n        ps = conn.prepareStatement(\"select a,b, length(b), c, length(c) from PT1 where a = ?\");\n        ps.setInt(1, a);\n        rs[0] = ps.executeQuery();\n        conn.close();\n    }\n\n    public static void parameter2(int a, java.math.BigDecimal b, java.math.BigDecimal c, java.sql.ResultSet[] rs)\n            throws SQLException {\n        Connection conn = DriverManager.getConnection(\"jdbc:default:connection\");\n        PreparedStatement ps = conn.prepareStatement(\"insert into PT1 values (?, ?, ?)\");\n        ps.setInt(1, a);\n        ps.setString(2, b.toString());\n        ps.setString(3, c.toString());\n        ps.executeUpdate();\n        ps.close();\n        ps = conn.prepareStatement(\"select a,b,c from PT1 where a = ?\");\n        ps.setInt(1, a);\n        rs[0] = ps.executeQuery();\n        conn.close();\n    }\n\n    public static void retrieveDynamicResults(int number, ResultSet[] rs1, ResultSet[] rs2, ResultSet[] rs3,\n                                              ResultSet[] rs4) throws SQLException {\n        Connection c = DriverManager.getConnection(\"jdbc:default:connection\");\n        if (number > 0) {\n            rs1[0] = c.createStatement().executeQuery(\"VALUES(1)\");\n        }\n        if (number > 1) {\n            rs2[0] = c.createStatement().executeQuery(\"VALUES(1)\");\n        }\n        if (number > 2) {\n            rs3[0] = c.createStatement().executeQuery(\"VALUES(1)\");\n        }\n        if (number > 3) {\n            rs4[0] = c.createStatement().executeQuery(\"VALUES(1)\");\n        }\n        c.close();\n    }\n\n    public static void outparams1(int[] p1, int p2) {\n        p1[0] = p2 * 2;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/CallableStatementProxyImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.FilterEventAdapter;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.CallableStatementProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.*;\nimport java.util.Calendar;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CallableStatementProxyImplTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_call() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        DataSourceProxy dataSource = new DataSourceProxyImpl(null, config);\n\n        FilterEventAdapter filter = new FilterEventAdapter() {\n        };\n        filter.init(dataSource);\n\n        config.getFilters().add(filter);\n\n        String sql = \"CALL P_0(?, ?)\";\n        CallableStatementProxyImpl rawCallStatement = new FakeCallableStatement(new ConnectionProxyImpl(null, null, null, 0), null, sql, 1001);\n\n        ConnectionProxy connection = new ConnectionProxyImpl(dataSource, null, new Properties(), 1001);\n        CallableStatementProxyImpl cstmt = new CallableStatementProxyImpl(connection, rawCallStatement, sql, 2001);\n\n        cstmt.registerOutParameter(1, Types.VARCHAR);\n        cstmt.registerOutParameter(1, Types.VARCHAR, \"VARCHAR\");\n        cstmt.registerOutParameter(1, Types.VARCHAR, 3);\n\n        cstmt.registerOutParameter(\"1\", Types.VARCHAR);\n        cstmt.registerOutParameter(\"1\", Types.VARCHAR, \"VARCHAR\");\n        cstmt.registerOutParameter(\"1\", Types.VARCHAR, 3);\n\n        cstmt.setBoolean(\"1\", true);\n        cstmt.setByte(\"1\", (byte) 0);\n        cstmt.setShort(\"1\", (short) 0);\n        cstmt.setInt(\"1\", 0);\n        cstmt.setLong(\"1\", 0);\n        cstmt.setFloat(\"1\", 0);\n        cstmt.setDouble(\"1\", 0);\n        cstmt.setBigDecimal(\"1\", new BigDecimal(\"111\"));\n        cstmt.setString(\"1\", \"X\");\n        cstmt.setURL(\"1\", null);\n        cstmt.setSQLXML(\"1\", null);\n        cstmt.setBytes(\"1\", null);\n        cstmt.setDate(\"1\", null);\n        cstmt.setDate(\"1\", null, Calendar.getInstance());\n        cstmt.setTime(\"1\", null);\n        cstmt.setTime(\"1\", null, Calendar.getInstance());\n        cstmt.setTimestamp(\"1\", null);\n        cstmt.setTimestamp(\"1\", null, Calendar.getInstance());\n        cstmt.setAsciiStream(\"1\", null);\n        cstmt.setAsciiStream(\"1\", null, 0);\n        cstmt.setAsciiStream(\"1\", null, 0L);\n        cstmt.setBinaryStream(\"1\", null);\n        cstmt.setBinaryStream(\"1\", null, 0);\n        cstmt.setBinaryStream(\"1\", null, 0L);\n        cstmt.setObject(\"1\", null);\n        cstmt.setObject(\"1\", null, Types.VARCHAR);\n        cstmt.setObject(\"1\", null, Types.VARCHAR, 3);\n        cstmt.setCharacterStream(\"1\", null);\n        cstmt.setCharacterStream(\"1\", null, 0);\n        cstmt.setCharacterStream(\"1\", null, 0L);\n        cstmt.setNull(\"1\", Types.VARCHAR);\n        cstmt.setNull(\"1\", Types.VARCHAR, \"VARCHAR\");\n        cstmt.setRowId(\"1\", null);\n        cstmt.setNString(\"1\", null);\n        cstmt.setNCharacterStream(\"1\", null);\n        cstmt.setNCharacterStream(\"1\", null, 0);\n        cstmt.setNClob(\"1\", (NClob) null);\n        cstmt.setNClob(\"1\", (Reader) null);\n        cstmt.setNClob(\"1\", (Reader) null, 0);\n        cstmt.setClob(\"1\", (Clob) null);\n        cstmt.setClob(\"1\", (Reader) null);\n        cstmt.setClob(\"1\", (Reader) null, 0);\n        cstmt.setBlob(\"1\", (Blob) null);\n        cstmt.setBlob(\"1\", (InputStream) null);\n        cstmt.setBlob(\"1\", (InputStream) null, 0);\n\n        cstmt.setURL(1, null);\n        cstmt.setSQLXML(1, null);\n\n        cstmt.setArray(1, null);\n        cstmt.setNCharacterStream(1, null);\n        cstmt.setNCharacterStream(1, null, 0);\n        cstmt.setNClob(1, (NClob) null);\n        cstmt.setNClob(1, (Reader) null);\n        cstmt.setNClob(1, (Reader) null, 0);\n        cstmt.setNString(1, null);\n        cstmt.setObject(1, null);\n        cstmt.setRef(1, null);\n        cstmt.setRowId(1, null);\n        cstmt.setUnicodeStream(1, null, 0);\n\n        cstmt.getClob(1);\n        cstmt.getClob(\"1\");\n        cstmt.cancel();\n\n        cstmt.getResultSet();\n    }\n\n    private static final class FakeCallableStatement extends CallableStatementProxyImpl {\n        private FakeCallableStatement(ConnectionProxy connection, CallableStatement statement, String sql, long id) {\n            super(connection, statement, sql, id);\n        }\n\n        @Override\n        public ResultSet getResultSet() throws SQLException {\n            return null;\n        }\n\n        @Override\n        public void cancel() throws SQLException {\n        }\n\n        @Override\n        public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {\n        }\n\n        @Override\n        public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {\n        }\n\n        @Override\n        public void registerOutParameter(String parameterIndex, int sqlType, String typeName) throws SQLException {\n        }\n\n        @Override\n        public void registerOutParameter(String parameterIndex, int sqlType) throws SQLException {\n        }\n\n        @Override\n        public void registerOutParameter(String parameterIndex, int sqlType, int scale) throws SQLException {\n        }\n\n        @Override\n        public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {\n        }\n\n        @Override\n        public Clob getClob(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public void setRowId(int parameterIndex, RowId x) throws SQLException {\n        }\n\n        @Override\n        public void setRef(int parameterIndex, Ref x) throws SQLException {\n        }\n\n        @Override\n        public void setObject(int parameterIndex, Object x) throws SQLException {\n        }\n\n        @Override\n        public void setNString(int parameterIndex, String x) throws SQLException {\n        }\n\n        @Override\n        public void setNCharacterStream(int parameterIndex, Reader x) throws SQLException {\n        }\n\n        @Override\n        public void setNCharacterStream(int parameterIndex, Reader x, long length) throws SQLException {\n        }\n\n        @Override\n        public void setNClob(int parameterIndex, NClob x) throws SQLException {\n        }\n\n        @Override\n        public void setNClob(int parameterIndex, Reader x) throws SQLException {\n        }\n\n        @Override\n        public void setNClob(int parameterIndex, Reader x, long length) throws SQLException {\n        }\n\n        @Override\n        public void setArray(int parameterIndex, Array x) throws SQLException {\n        }\n\n        @Override\n        public void setURL(int parameterIndex, URL x) throws SQLException {\n        }\n\n        @Override\n        public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {\n        }\n\n        @Override\n        public java.net.URL getURL(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public void setSQLXML(int parameterIndex, SQLXML x) throws SQLException {\n        }\n\n        @Override\n        public void setURL(String parameterName, java.net.URL val) throws SQLException {\n        }\n\n        @Override\n        public void setNull(String parameterName, int sqlType) throws SQLException {\n        }\n\n        @Override\n        public void setBoolean(String parameterName, boolean x) throws SQLException {\n        }\n\n        @Override\n        public void setByte(String parameterName, byte x) throws SQLException {\n        }\n\n        @Override\n        public void setShort(String parameterName, short x) throws SQLException {\n        }\n\n        @Override\n        public void setInt(String parameterName, int x) throws SQLException {\n        }\n\n        @Override\n        public void setLong(String parameterName, long x) throws SQLException {\n        }\n\n        @Override\n        public void setFloat(String parameterName, float x) throws SQLException {\n        }\n\n        @Override\n        public void setDouble(String parameterName, double x) throws SQLException {\n        }\n\n        @Override\n        public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {\n        }\n\n        @Override\n        public void setString(String parameterName, String x) throws SQLException {\n        }\n\n        @Override\n        public void setBytes(String parameterName, byte[] x) throws SQLException {\n        }\n\n        @Override\n        public void setDate(String parameterName, java.sql.Date x) throws SQLException {\n        }\n\n        @Override\n        public void setTime(String parameterName, java.sql.Time x) throws SQLException {\n        }\n\n        @Override\n        public void setTimestamp(String parameterName, java.sql.Timestamp x) throws SQLException {\n        }\n\n        @Override\n        public void setAsciiStream(String parameterName, java.io.InputStream x, int length) throws SQLException {\n        }\n\n        @Override\n        public void setBinaryStream(String parameterName, java.io.InputStream x, int length) throws SQLException {\n        }\n\n        @Override\n        public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {\n        }\n\n        @Override\n        public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {\n        }\n\n        @Override\n        public void setObject(String parameterName, Object x) throws SQLException {\n        }\n\n        @Override\n        public void setCharacterStream(String parameterName, java.io.Reader reader, int length) throws SQLException {\n        }\n\n        @Override\n        public void setDate(String parameterName, java.sql.Date x, Calendar cal) throws SQLException {\n        }\n\n        @Override\n        public void setTime(String parameterName, java.sql.Time x, Calendar cal) throws SQLException {\n        }\n\n        @Override\n        public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal) throws SQLException {\n        }\n\n        @Override\n        public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {\n        }\n\n        @Override\n        public String getString(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public boolean getBoolean(String parameterName) throws SQLException {\n            return true;\n        }\n\n        @Override\n        public byte getByte(String parameterName) throws SQLException {\n            return 0;\n        }\n\n        @Override\n        public short getShort(String parameterName) throws SQLException {\n            return 0;\n        }\n\n        @Override\n        public int getInt(String parameterName) throws SQLException {\n            return 0;\n        }\n\n        @Override\n        public long getLong(String parameterName) throws SQLException {\n            return 0;\n        }\n\n        @Override\n        public float getFloat(String parameterName) throws SQLException {\n            return 0;\n        }\n\n        @Override\n        public double getDouble(String parameterName) throws SQLException {\n            return 0;\n        }\n\n        @Override\n        public byte[] getBytes(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.sql.Date getDate(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.sql.Time getTime(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.sql.Timestamp getTimestamp(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public Object getObject(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public BigDecimal getBigDecimal(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public Object getObject(String parameterName, java.util.Map<String, Class<?>> map) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public Ref getRef(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public Blob getBlob(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public Clob getClob(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public Array getArray(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.sql.Date getDate(String parameterName, Calendar cal) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.sql.Time getTime(String parameterName, Calendar cal) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.sql.Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.net.URL getURL(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public RowId getRowId(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public RowId getRowId(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public void setRowId(String parameterName, RowId x) throws SQLException {\n        }\n\n        @Override\n        public void setNString(String parameterName, String value) throws SQLException {\n        }\n\n        @Override\n        public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {\n        }\n\n        @Override\n        public void setNClob(String parameterName, NClob value) throws SQLException {\n        }\n\n        @Override\n        public void setClob(String parameterName, Reader reader, long length) throws SQLException {\n        }\n\n        @Override\n        public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {\n        }\n\n        @Override\n        public void setNClob(String parameterName, Reader reader, long length) throws SQLException {\n        }\n\n        @Override\n        public NClob getNClob(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public NClob getNClob(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {\n        }\n\n        @Override\n        public SQLXML getSQLXML(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public SQLXML getSQLXML(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public String getNString(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public String getNString(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.io.Reader getNCharacterStream(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.io.Reader getNCharacterStream(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.io.Reader getCharacterStream(int parameterIndex) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public java.io.Reader getCharacterStream(String parameterName) throws SQLException {\n            return null;\n        }\n\n        @Override\n        public void setBlob(String parameterName, Blob x) throws SQLException {\n        }\n\n        @Override\n        public void setClob(String parameterName, Clob x) throws SQLException {\n        }\n\n        @Override\n        public void setAsciiStream(String parameterName, java.io.InputStream x, long length) throws SQLException {\n        }\n\n        @Override\n        public void setBinaryStream(String parameterName, java.io.InputStream x, long length) throws SQLException {\n        }\n\n        @Override\n        public void setCharacterStream(String parameterName, java.io.Reader reader, long length) throws SQLException {\n        }\n\n        @Override\n        public void setAsciiStream(String parameterName, java.io.InputStream x) throws SQLException {\n        }\n\n        @Override\n        public void setBinaryStream(String parameterName, java.io.InputStream x) throws SQLException {\n        }\n\n        @Override\n        public void setCharacterStream(String parameterName, java.io.Reader reader) throws SQLException {\n        }\n\n        @Override\n        public void setNCharacterStream(String parameterName, Reader value) throws SQLException {\n        }\n\n        @Override\n        public void setClob(String parameterName, Reader reader) throws SQLException {\n        }\n\n        @Override\n        public void setBlob(String parameterName, InputStream inputStream) throws SQLException {\n        }\n\n        @Override\n        public void setNClob(String parameterName, Reader reader) throws SQLException {\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/ClobTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.ClobProxy;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.StringReader;\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ClobTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=clobTest:jdbc:derby:memory:clobTestDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createTable();\n\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n\n        DruidDriver.getProxyDataSources().clear();\n         JdbcStatManager.getInstance().reset();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_CLOB (ID INTEGER, DATA CLOB)\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_CLOB\");\n        stmt.close();\n        conn.close();\n    }\n\n    @Test\n    public void test_clob() throws Exception {\n        Connection conn = null;\n        PreparedStatement pstmt = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            pstmt = conn.prepareStatement(\"INSERT INTO T_CLOB (ID, DATA) VALUES (?, ?)\");\n\n            Clob clob = conn.createClob();\n\n            ClobProxy clobWrapper = (ClobProxy) clob;\n            assertNotNull(clobWrapper.getConnectionWrapper());\n            clob.setAsciiStream(1);\n            clob.setCharacterStream(1);\n\n            clob.setString(1, \"ABCAAAAAAAAAAA\");\n            clob.setString(1, \"ABCAAAAAAAAAAA\", 1, 5);\n\n            pstmt.setInt(1, 1);\n            pstmt.setClob(2, clob);\n            int updateCount = pstmt.executeUpdate();\n            assertEquals(1, updateCount);\n\n            pstmt.setInt(1, 1);\n            pstmt.setClob(2, new StringReader(\"XXXXXXX\"));\n            updateCount = pstmt.executeUpdate();\n            assertEquals(1, updateCount);\n\n            pstmt.setInt(1, 1);\n            pstmt.setClob(2, new StringReader(\"ABCAAAAAAAAAAABCAAAAAAAAAAAAABCAAAAAAAAAAABCAAAAAAAAAAAA\"),\n                    \"ABCAAAAAAAAAAABCAAAAAAAAAAAAABCAAAAAAAAAAABCAAAAAAAAAAAA\".length());\n            updateCount = pstmt.executeUpdate();\n            assertEquals(1, updateCount);\n\n            stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE,\n                    ResultSet.CLOSE_CURSORS_AT_COMMIT);\n\n            // //////\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            rs.getStatement(); // just call\n            while (rs.next()) {\n                Clob readClob = rs.getClob(2);\n                readClob.length();\n                readClob.position(\"abc\", 1);\n                readClob.getCharacterStream().close();\n                readClob.getAsciiStream().close();\n                readClob.getCharacterStream(1, 1).close();\n                readClob.getSubString(1, 2);\n                readClob.truncate(2);\n                readClob.free();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.getCharacterStream(2).close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.getCharacterStream(\"DATA\").close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                Clob searchstr = conn.createClob();\n                searchstr.setString(1, \"AB\");\n                Clob x = rs.getClob(\"DATA\");\n                x.position(searchstr, 1);\n                x.free();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.getAsciiStream(2).close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.getAsciiStream(\"DATA\").close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                Clob x = conn.createClob();\n                x.setString(1, \"XXSDDSLF\");\n                rs.updateClob(2, x);\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                Clob x = conn.createClob();\n                x.setString(1, \"XXSDDSLF\");\n                rs.updateClob(\"DATA\", x);\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.updateClob(2, new StringReader(\"XDSFLA\"));\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.updateClob(\"DATA\", new StringReader(\"XDSFLA\"));\n            }\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.updateClob(2, new StringReader(\"XDSFLA\"), \"XDSFLA\".length());\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_CLOB\");\n            while (rs.next()) {\n                rs.updateClob(\"DATA\", new StringReader(\"XDSFLA\"), \"XDSFLA\".length());\n            }\n            JdbcUtils.close(rs);\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/CommonsLogFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.logging.CommonsLogFilter;\nimport com.alibaba.druid.filter.logging.LogFilter;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.apache.commons.logging.impl.Log4JLogger;\nimport org.apache.log4j.Priority;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CommonsLogFilterTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_logger() throws Exception {\n        CommonsLogFilter filter = new CommonsLogFilter();\n\n        filter.setDataSourceLoggerName(\"_datasource_name_\");\n        filter.setConnectionLoggerName(\"_connection_name_\");\n        filter.setStatementLoggerName(\"_statement_name_\");\n        filter.setResultSetLoggerName(\"_resultset_name_\");\n\n        assertEquals(filter.getDataSourceLoggerName(), \"_datasource_name_\");\n        assertEquals(filter.getConnectionLoggerName(), \"_connection_name_\");\n        assertEquals(filter.getStatementLoggerName(), \"_statement_name_\");\n        assertEquals(filter.getResultSetLoggerName(), \"_resultset_name_\");\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", true));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", true));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", true));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", true));\n\n        assertEquals(filter.getDataSourceLoggerName(), \"_datasoure_\");\n        assertEquals(filter.getConnectionLoggerName(), \"_connection_\");\n        assertEquals(filter.getStatementLoggerName(), \"_statement_\");\n        assertEquals(filter.getResultSetLoggerName(), \"_resultset_\");\n\n        setLogEnableAll(filter, true);\n\n        assertTrue(filter.isDataSourceLogEnabled());\n\n        assertTrue(filter.isConnectionLogEnabled());\n        assertTrue(filter.isConnectionLogErrorEnabled());\n        assertTrue(filter.isConnectionConnectBeforeLogEnabled());\n        assertTrue(filter.isConnectionConnectAfterLogEnabled());\n        assertTrue(filter.isConnectionCloseAfterLogEnabled());\n        assertTrue(filter.isConnectionCommitAfterLogEnabled());\n        assertTrue(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertTrue(filter.isStatementLogEnabled());\n        assertTrue(filter.isStatementLogErrorEnabled());\n        assertTrue(filter.isStatementCreateAfterLogEnabled());\n        assertTrue(filter.isStatementCloseAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertTrue(filter.isStatementLogErrorEnabled());\n        assertTrue(filter.isStatementParameterSetLogEnabled());\n        assertTrue(filter.isStatementPrepareAfterLogEnabled());\n        assertTrue(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertTrue(filter.isResultSetLogEnabled());\n        assertTrue(filter.isResultSetLogErrorEnabled());\n        assertTrue(filter.isResultSetCloseAfterLogEnabled());\n        assertTrue(filter.isResultSetNextAfterLogEnabled());\n        assertTrue(filter.isResultSetOpenAfterLogEnabled());\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", false));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", false));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", false));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", false));\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogEnabled());\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n\n        // ////////////////////////////////////////\n        // ////////////////////////////////////////\n        // ////////////////////////////////////////\n\n        setLogEnableAll(filter, false);\n\n        // ////\n\n        filter.setDataSourceLogger(null);\n        filter.setConnectionLogger(null);\n        filter.setStatementLogger(null);\n        filter.setResultSetLogger(null);\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", false));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", false));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", false));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", false));\n\n        filter.setStatementLogErrorEnabled(true);\n        assertFalse(filter.isStatementLogErrorEnabled());\n        filter.setStatementLogErrorEnabled(false);\n        assertFalse(filter.isStatementLogErrorEnabled());\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogEnabled());\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n\n        // //\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", true));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", true));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", true));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", true));\n\n        assertFalse(filter.isConnectionLogEnabled());\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isResultSetLogEnabled());\n\n        assertFalse(filter.isStatementLogErrorEnabled());\n        filter.setStatementLogErrorEnabled(true);\n        assertTrue(filter.isStatementLogErrorEnabled());\n        filter.setStatementLogErrorEnabled(false);\n\n        filter.setConnectionLogEnabled(true);\n        filter.setStatementLogEnabled(true);\n        filter.setResultSetLogEnabled(true);\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n    }\n\n    @SuppressWarnings(\"serial\")\n    public static class FakeLogger extends Log4JLogger {\n        private boolean enable;\n\n        public FakeLogger(String name, boolean enable) {\n            super(name);\n            this.enable = enable;\n        }\n\n        public boolean isDebugEnabled() {\n            return this.enable;\n        }\n\n        public boolean isErrorEnabled() {\n            return this.enable;\n        }\n\n        public boolean isEnabledFor(Priority level) {\n            return this.enable;\n        }\n    }\n\n    private void setLogEnableAll(LogFilter logFilter, boolean enable) {\n        logFilter.setDataSourceLogEnabled(enable);\n\n        logFilter.setConnectionLogEnabled(enable);\n        logFilter.setConnectionLogErrorEnabled(enable);\n        logFilter.setConnectionRollbackAfterLogEnabled(enable);\n        logFilter.setConnectionConnectBeforeLogEnabled(enable);\n        logFilter.setConnectionConnectAfterLogEnabled(enable);\n        logFilter.setConnectionCommitAfterLogEnabled(enable);\n        logFilter.setConnectionCloseAfterLogEnabled(enable);\n\n        logFilter.setStatementLogEnabled(enable);\n        logFilter.setStatementLogErrorEnabled(enable);\n        logFilter.setStatementCreateAfterLogEnabled(enable);\n        logFilter.setStatementExecuteAfterLogEnabled(enable);\n        logFilter.setStatementExecuteBatchAfterLogEnabled(enable);\n        logFilter.setStatementExecuteQueryAfterLogEnabled(enable);\n        logFilter.setStatementExecuteUpdateAfterLogEnabled(enable);\n        logFilter.setStatementPrepareCallAfterLogEnabled(enable);\n        logFilter.setStatementPrepareAfterLogEnabled(enable);\n        logFilter.setStatementCloseAfterLogEnabled(enable);\n        logFilter.setStatementParameterSetLogEnabled(enable);\n\n        logFilter.setResultSetLogEnabled(enable);\n        logFilter.setResultSetOpenAfterLogEnabled(enable);\n        logFilter.setResultSetNextAfterLogEnabled(enable);\n        logFilter.setResultSetLogErrorEnabled(enable);\n        logFilter.setResultSetCloseAfterLogEnabled(enable);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/ConnectionProxyImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.FilterEventAdapter;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLClientInfoException;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectionProxyImplTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_connection() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        DataSourceProxy dataSource = new DataSourceProxyImpl(null, config);\n\n        FilterEventAdapter filter = new FilterEventAdapter() {\n        };\n        filter.init(dataSource);\n\n        ConnectionProxyImpl rawConnection = new ConnectionProxyImpl(null, null, new Properties(), 0) {\n            public void setClientInfo(String name, String value) throws SQLClientInfoException {\n            }\n        };\n\n        ConnectionProxyImpl connection = new ConnectionProxyImpl(dataSource, rawConnection, new Properties(), 1001);\n\n        connection.setClientInfo(\"name\", null);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/ConnectionStatisticTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.stat.JdbcConnectionStat;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectionStatisticTest {\n    @Test\n    public void test_connection_stat() throws Exception {\n        JdbcConnectionStat.Entry stat = new JdbcConnectionStat.Entry(null, 1001L);\n        assertEquals(null, stat.getEstablishTime());\n        assertEquals(null, stat.getConnectStackTrace());\n        assertEquals(null, stat.getLastStatementStatckTrace());\n\n        stat.setLastStatementStatckTrace(new Exception());\n        assertNotNull(stat.getLastStatementStatckTrace());\n\n        stat.error(new Exception());\n        assertNotNull(stat.getLastErrorTime());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/ConnectionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ConnectionTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=demo:jdbc:derby:memory:connectionTestDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createTable();\n\n        conn.close();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_BLOB (ID INTEGER, DATA BLOB)\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_BLOB\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_connection() throws Exception {\n        Connection conn = null;\n        PreparedStatement pstmt = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            conn.setCatalog(conn.getCatalog());\n            conn.setClientInfo(conn.getClientInfo());\n            conn.setHoldability(conn.getHoldability());\n            conn.setReadOnly(conn.isReadOnly());\n            conn.setTransactionIsolation(conn.getTransactionIsolation());\n            conn.setTypeMap(conn.getTypeMap());\n\n            try {\n                conn.setClientInfo(\"name\", \"value\");\n            } catch (SQLClientInfoException ex) {\n            }\n\n            try {\n                conn.createArrayOf(\"VARCHAR\", new String[]{\"A\", \"B\"});\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                conn.createNClob();\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                conn.createSQLXML();\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                conn.createStruct(\"VARCHAR\", new String[]{\"A\", \"B\"});\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            conn.setAutoCommit(false);\n            Savepoint savePoint = conn.setSavepoint(\"XX\");\n            conn.releaseSavepoint(savePoint);\n\n            pstmt = conn.prepareStatement(\"INSERT INTO T_BLOB (ID, DATA) VALUES (?, ?)\");\n\n            Blob blob = conn.createBlob();\n\n            blob.setBytes(1, new byte[100]);\n\n            pstmt.setInt(1, 1);\n            pstmt.setBlob(2, blob);\n\n            int updateCount = pstmt.executeUpdate();\n            assertEquals(1, updateCount);\n\n            stmt = conn.createStatement();\n\n            conn.nativeSQL(\"SELECT ID, DATA FROM T_BLOB\");\n            // //////\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            rs.getStatement(); // just call\n            while (rs.next()) {\n                Blob readBlob = rs.getBlob(2);\n                readBlob.length();\n                readBlob.getBinaryStream(1, 100).close();\n                readBlob.getBinaryStream().close();\n                readBlob.free();\n                try {\n                    rs.getUnicodeStream(1).close();\n                } catch (SQLFeatureNotSupportedException ex) {\n                }\n                try {\n                    rs.getUnicodeStream(\"DATA\").close();\n                } catch (SQLFeatureNotSupportedException ex) {\n                }\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.getBinaryStream(2).close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.getBinaryStream(\"DATA\").close();\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.getBytes(2);\n            }\n            JdbcUtils.close(rs);\n\n            rs = stmt.executeQuery(\"SELECT ID, DATA FROM T_BLOB\");\n            while (rs.next()) {\n                rs.getBytes(\"DATA\");\n            }\n            JdbcUtils.close(rs);\n\n            conn.setAutoCommit(true);\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/CounterFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CounterFilterTest {\n    String sql = \"SELECT 1\";\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_countFilter() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        config.setUrl(\"\");\n\n        DataSourceProxyImpl dataSource = new DataSourceProxyImpl(null, config);\n        JdbcDataSourceStat dataSourceStat = dataSource.getDataSourceStat();\n\n        StatFilter filter = new StatFilter();\n        filter.init(dataSource);\n\n        dataSourceStat.reset();\n\n        assertNull(StatFilter.getStatFilter(dataSource));\n        assertNull(dataSourceStat.getSqlStat(Integer.MAX_VALUE));\n        assertNull(dataSourceStat.getConnectionStat().getConnectLastTime());\n\n        FilterChain chain = new FilterChainImpl(dataSource) {\n            public ConnectionProxy connection_connect(Properties info) throws SQLException {\n                throw new SQLException();\n            }\n        };\n\n        Exception error = null;\n        try {\n            filter.connection_connect(chain, new Properties());\n        } catch (SQLException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertEquals(1, dataSourceStat.getConnectionStat().getConnectErrorCount());\n        assertNotNull(dataSourceStat.getConnectionStat().getConnectLastTime());\n    }\n\n    @Test\n    public void test_count_filter() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        config.setUrl(\"\");\n        config.setRawUrl(\"jdbc:mock:\");\n\n        StatFilter filter = new StatFilter();\n\n        MockDriver driver = new MockDriver();\n        DataSourceProxyImpl dataSource = new DataSourceProxyImpl(driver, config);\n\n        filter.init(dataSource);\n        config.getFilters().add(filter);\n\n        Connection conn = dataSource.connect(null);\n\n        Statement stmt = conn.createStatement();\n        ResultSetProxy rs = (ResultSetProxy) stmt.executeQuery(sql);\n        rs.close();\n        stmt.close();\n\n        conn.close();\n        conn.close();\n\n        dataSource.getCompositeData();\n        dataSource.getProperties();\n        dataSource.getDataSourceMBeanDomain();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/DriverTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxy;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Driver;\nimport java.sql.DriverManager;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DriverTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_driver() throws Exception {\n        String url_0 = \"jdbc:wrap-jdbc:filters=default:name=driverTest:jdbc:derby:memory:driverTestDB;create=true\";\n        String url_1 = \"jdbc:wrap-jdbc:filters=counter:name=driverTest:jdbc:derby:memory:driverTestDB;create=true\";\n        String url_2 = \"jdbc:wrap-jdbc:filters=log4j:name=driverTest:jdbc:derby:memory:driverTestDB;create=true\";\n        String url_3 = \"jdbc:wrap-jdbc:filters=commonLogging:name=driverTest:jdbc:derby:memory:driverTestDB;create=true\";\n        String url_4 = \"jdbc:wrap-jdbc:driver=org.apache.derby.jdbc.EmbeddedDriver:filters=commonLogging:name=driverTest:jdbc:derby:memory:driverTestDB;create=true\";\n\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection connection = DriverManager.getConnection(url_0);\n        connection.close();\n\n        Driver driver = DriverManager.getDriver(url_0);\n\n        DruidDriver driverWrapper = (DruidDriver) driver;\n\n        assertEquals(4, driverWrapper.getMajorVersion());\n        assertEquals(0, driverWrapper.getMinorVersion());\n        assertEquals(true, driverWrapper.jdbcCompliant());\n\n        assertTrue(driverWrapper.getConnectCount() > 0);\n\n        assertNotNull(DruidDriver.getInstance());\n\n        assertEquals(\"jdbc:wrap-jdbc:\", driverWrapper.getAcceptPrefix());\n\n        assertTrue(driverWrapper.getDataSourceUrls().length > 0);\n\n        driverWrapper.getPropertyInfo(url_0, new Properties());\n\n        assertFalse(driverWrapper.acceptsURL(null));\n        assertFalse(driverWrapper.acceptsURL(\"xxx\"));\n        assertTrue(driverWrapper.acceptsURL(url_1));\n\n        Connection connection_1 = DriverManager.getConnection(url_1);\n        ConnectionProxy connection_wrapper_1 = connection_1.unwrap(ConnectionProxy.class);\n        DataSourceProxy dataSource_1 = connection_wrapper_1.getDirectDataSource();\n        assertEquals(1, dataSource_1.getProxyFilters().size());\n\n        {\n            Connection connection_2 = DriverManager.getConnection(url_2);\n            ConnectionProxy connection_wrapper_2 = connection_2.unwrap(ConnectionProxy.class);\n            DataSourceProxy dataSource_2 = connection_wrapper_2.getDirectDataSource();\n            assertEquals(1, dataSource_2.getProxyFilters().size());\n        }\n\n        {\n            Connection connection_3 = DriverManager.getConnection(url_3);\n            ConnectionProxy connection_wrapper_3 = connection_3.unwrap(ConnectionProxy.class);\n            DataSourceProxy dataSource_3 = connection_wrapper_3.getDirectDataSource();\n            assertEquals(1, dataSource_3.getProxyFilters().size());\n        }\n\n        {\n            Connection connection_4 = DriverManager.getConnection(url_4);\n            ConnectionProxy connection_wrapper_4 = connection_4.unwrap(ConnectionProxy.class);\n            DataSourceProxy dataSource_4 = connection_wrapper_4.getDirectDataSource();\n            dataSource_4.getProxyFilters().toString();\n            assertEquals(1, dataSource_4.getProxyFilters().size());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/DruidDriverTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.FilterAdapter;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDriverTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    public static class PublicJdbcFilterAdapter extends FilterAdapter {\n        public PublicJdbcFilterAdapter() {\n        }\n\n    }\n\n    static class PrivateJdbcFilterAdapter extends FilterAdapter {\n        private PrivateJdbcFilterAdapter() {\n        }\n    }\n\n    public static class InitErrorJdbcFilterAdapter extends FilterAdapter {\n        public InitErrorJdbcFilterAdapter() throws InstantiationException {\n            throw new InstantiationException(\"init error\");\n        }\n\n    }\n\n    static class PrivateDriver extends MockDriver {\n        private PrivateDriver() {\n        }\n    }\n\n    public static class InitErrorDriver extends MockDriver {\n        public InitErrorDriver() throws InstantiationException {\n            throw new InstantiationException(\"init error\");\n        }\n    }\n\n    @Test\n    public void test_registerDriver() throws Exception {\n        assertFalse(DruidDriver.registerDriver(null));\n    }\n\n    @Test\n    public void test_getRawDriverClassName() throws Exception {\n        String className = JdbcUtils.getDriverClassName(\"jdbc:mysql:\");\n        if (className.equals(\"com.mysql.jdbc.Driver\")) {\n            assertEquals(\"com.mysql.jdbc.Driver\", JdbcUtils.getDriverClassName(\"jdbc:mysql:\"));\n        } else {\n            assertEquals(\"com.mysql.cj.jdbc.Driver\", JdbcUtils.getDriverClassName(\"jdbc:mysql:\"));\n        }\n\n        assertEquals(\"oracle.jdbc.OracleDriver\", JdbcUtils.getDriverClassName(\"jdbc:oracle:\"));\n        assertEquals(\"com.microsoft.jdbc.sqlserver.SQLServerDriver\",\n                JdbcUtils.getDriverClassName(\"jdbc:microsoft:\"));\n        assertEquals(\"org.postgresql.Driver\", JdbcUtils.getDriverClassName(\"jdbc:postgresql:xx\"));\n        assertEquals(\"net.sourceforge.jtds.jdbc.Driver\", JdbcUtils.getDriverClassName(\"jdbc:jtds:\"));\n        {\n            Exception error = null;\n            try {\n                JdbcUtils.getDriverClassName(\"jdbc:xxx:\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n\n    @Test\n    public void test_getRawDriver() throws Exception {\n        DruidDriver driver = new DruidDriver();\n        assertNotNull(driver.createDriver(MockDriver.class.getName()));\n\n        {\n            Exception error = null;\n            try {\n                driver.createDriver(null);\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                driver.createDriver(PrivateDriver.class.getName());\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            Exception error = null;\n            try {\n                driver.createDriver(InitErrorDriver.class.getName());\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n    }\n\n    @Test\n    public void test_driver_wrap() throws Exception {\n        DruidDriver driver = new DruidDriver();\n\n        {\n            ConnectionProxyImpl conn = (ConnectionProxyImpl) driver.connect(\"jdbc:wrap-jdbc:filters=:name=driverWrapperTest:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                    new Properties());\n            assertEquals(0, conn.getDirectDataSource().getProxyFilters().size());\n            conn.close();\n        }\n        {\n            ConnectionProxyImpl conn = (ConnectionProxyImpl) driver.connect(\"jdbc:wrap-jdbc:filters=,:name=driverWrapperTest:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                    new Properties());\n            assertEquals(0, conn.getDirectDataSource().getProxyFilters().size());\n            conn.close();\n        }\n        {\n            ConnectionProxyImpl conn = (ConnectionProxyImpl) driver.connect(\"jdbc:wrap-jdbc:filters=,:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                    new Properties());\n            assertEquals(0, conn.getDirectDataSource().getProxyFilters().size());\n            conn.close();\n        }\n        {\n            ConnectionProxyImpl conn = (ConnectionProxyImpl) driver.connect(\"jdbc:wrap-jdbc:filters=,:name=:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                    new Properties());\n            assertEquals(0, conn.getDirectDataSource().getProxyFilters().size());\n            conn.close();\n        }\n        {\n            ConnectionProxyImpl conn = (ConnectionProxyImpl) driver.connect(\"jdbc:wrap-jdbc:driver=:filters=,:name=driverWrapperTest:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                    new Properties());\n            assertEquals(0, conn.getDirectDataSource().getProxyFilters().size());\n            conn.close();\n        }\n        {\n            ConnectionProxyImpl conn = (ConnectionProxyImpl) driver.connect(\"jdbc:wrap-jdbc:name=driverWrapperTest:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                    new Properties());\n            assertEquals(0, conn.getDirectDataSource().getProxyFilters().size());\n            conn.close();\n        }\n        {\n            ConnectionProxyImpl conn = (ConnectionProxyImpl) driver.connect(\"jdbc:wrap-jdbc:filters=\"\n                            + PublicJdbcFilterAdapter.class.getName()\n                            + \":name=driverWrapperTest:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                    new Properties());\n            assertEquals(1, conn.getDirectDataSource().getProxyFilters().size());\n            conn.close();\n        }\n        {\n            Exception error = null;\n            try {\n                driver.connect(\"jdbc:wrap-jdbc:filters=\" + PrivateJdbcFilterAdapter.class.getName()\n                                + \":name=driverWrapperTest:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                        new Properties()).close();\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                driver.connect(\"jdbc:wrap-jdbc:filters=\" + InitErrorJdbcFilterAdapter.class.getName()\n                                + \":name=driverWrapperTest:jdbc:derby:memory:driverWrapperTestDB;create=true\",\n                        new Properties()).close();\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/InsertValues.java",
    "content": "package com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.JdbcParameter;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 12/07/2017.\n */\npublic class InsertValues {\n    @Test\n    public void test_insert_values() throws Exception {\n        String sql = \"insert into t (f0, f1, f2, f3, f4) values \";\n        for (int i = 0; i < 1000; ++i) {\n            if (i != 0) {\n                sql += \", (?, ?, ?, ?, ?)\";\n            } else {\n                sql += \"(?, ?, ?, ?, ?)\";\n            }\n        }\n\n        MockPreparedStatement mockPstmt = new MockPreparedStatement(new MockConnection(), sql);\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        DataSourceProxyImpl ds = new DataSourceProxyImpl(null, config);\n        ConnectionProxyImpl conn = new ConnectionProxyImpl(ds, null, null, 0);\n        PreparedStatementProxyImpl proxy = new PreparedStatementProxyImpl(conn, mockPstmt, sql, 0);\n\n        Field field = PreparedStatementProxyImpl.class.getDeclaredField(\"parameters\");\n        field.setAccessible(true);\n        JdbcParameter[] params = (JdbcParameter[]) field.get(proxy);\n        assertEquals(5000, params.length);\n\n        proxy.setInt(1000, 3);\n        proxy.setInt(1001, 3);\n        proxy.setInt(1002, 3);\n        proxy.setInt(1003, 3);\n        proxy.setInt(1004, 3);\n        proxy.setInt(1005, 3);\n        proxy.setInt(1005, 3);\n        proxy.setInt(1006, 3);\n        proxy.setInt(1007, 3);\n        proxy.setInt(1008, 3);\n        proxy.setInt(1009, 3);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/InsertValues_1.java",
    "content": "package com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.jdbc.JdbcParameter;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 12/07/2017.\n */\npublic class InsertValues_1 {\n    @Test\n    public void test_insert_values() throws Exception {\n        String sql = \"insert into t (f0, f1, f2, f3, f4) values ('????????????????????????', '????????????????????????', '????????????????????????', '????????????????????????', '????????????????????????')\";\n\n        PreparedStatementProxyImpl proxy = new PreparedStatementProxyImpl(null, null, sql, 0);\n\n        Field field = PreparedStatementProxyImpl.class.getDeclaredField(\"parameters\");\n        field.setAccessible(true);\n        JdbcParameter[] params = (JdbcParameter[]) field.get(proxy);\n        assertEquals(0, params.length);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/InsertValues_2.java",
    "content": "package com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.jdbc.JdbcParameter;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 12/07/2017.\n */\npublic class InsertValues_2 {\n    @Test\n    public void test_insert_values() throws Exception {\n        String sql = \"insert into t (f0, f1, f2, f3, f4) values (\\\"????????????????????????\\\", \\\"????????????????????????\\\", \\\"????????????????????????\\\", \\\"????????????????????????\\\", \\\"????????????????????????\\\")\";\n\n        PreparedStatementProxyImpl proxy = new PreparedStatementProxyImpl(null, null, sql, 0);\n\n        Field field = PreparedStatementProxyImpl.class.getDeclaredField(\"parameters\");\n        field.setAccessible(true);\n        JdbcParameter[] params = (JdbcParameter[]) field.get(proxy);\n        assertEquals(0, params.length);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/JdbcFilterEventAdapterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.filter.FilterEventAdapter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.pool.DruidPooledConnection;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.*;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class JdbcFilterEventAdapterTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_filterEventAdapter() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        DataSourceProxy dataSource = new DataSourceProxyImpl(null, config);\n\n        FilterEventAdapter filter = new FilterEventAdapter() {\n        };\n\n        String sql = \"SELECT * FROM PATROL\";\n        ConnectionProxy connection = new ConnectionProxyImpl(dataSource, null, new Properties(), 1001);\n        final PreparedStatementProxy statement = new PreparedStatementProxyImpl(connection, null, sql, 1002);\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql) throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql) throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql) throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, int autoGeneratedKeys)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, Statement.NO_GENERATED_KEYS);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, int autoGeneratedKeys)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, Statement.NO_GENERATED_KEYS);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, int autoGeneratedKeys)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, Statement.NO_GENERATED_KEYS);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, int[] columnIndexes)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, new int[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, int[] columnIndexes)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, new int[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, int[] columnIndexes)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, new int[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, String[] columnNames)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, new String[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, String[] columnNames)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, new String[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean statement_execute(StatementProxy statement, String sql, String[] columnNames)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_execute(chain, statement, sql, new String[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int[] statement_executeBatch(StatementProxy statement) throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeBatch(chain, statement);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int[] statement_executeBatch(StatementProxy statement) throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeBatch(chain, statement);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int[] statement_executeBatch(StatementProxy statement) throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeBatch(chain, statement);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy statement_executeQuery(StatementProxy statement, String sql) throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeQuery(chain, statement, sql);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy statement_executeQuery(StatementProxy statement, String sql) throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeQuery(chain, statement, sql);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy statement_executeQuery(StatementProxy statement, String sql) throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeQuery(chain, statement, sql);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int preparedStatement_executeUpdate(PreparedStatementProxy statement) throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_executeUpdate(chain, statement);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int preparedStatement_executeUpdate(PreparedStatementProxy statement) throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_executeUpdate(chain, statement);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int preparedStatement_executeUpdate(PreparedStatementProxy statement) throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_executeUpdate(chain, statement);\n            } catch (Error ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql) throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql) throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql) throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql);\n            } catch (Error ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, int autoGeneratedKeys)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, Statement.NO_GENERATED_KEYS);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, int autoGeneratedKeys)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, Statement.NO_GENERATED_KEYS);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, int autoGeneratedKeys)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, Statement.NO_GENERATED_KEYS);\n            } catch (Error ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, int[] columnIndexes)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, new int[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, int[] columnIndexes)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, new int[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, int[] columnIndexes)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, new int[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, String[] columnNames)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, new String[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, String[] columnNames)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, new String[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public int statement_executeUpdate(StatementProxy statement, String sql, String[] columnNames)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.statement_executeUpdate(chain, statement, sql, new String[0]);\n            } catch (Throwable ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // ///////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy statement_getGeneratedKeys(StatementProxy statement) throws SQLException {\n                    return null;\n                }\n            };\n\n            filter.statement_getGeneratedKeys(chain, statement);\n        }\n\n        {\n            final ResultSetProxy resultSet = new ResultSetProxyImpl(statement, null, 2001, null);\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy statement_getGeneratedKeys(StatementProxy statement) throws SQLException {\n                    return resultSet;\n                }\n            };\n\n            filter.statement_getGeneratedKeys(chain, statement);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean preparedStatement_execute(PreparedStatementProxy statement) throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_execute(chain, statement);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean preparedStatement_execute(PreparedStatementProxy statement) throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_execute(chain, statement);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public boolean preparedStatement_execute(PreparedStatementProxy statement) throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_execute(chain, statement);\n            } catch (Error ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy preparedStatement_executeQuery(PreparedStatementProxy statement)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_executeQuery(chain, statement);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy preparedStatement_executeQuery(PreparedStatementProxy statement)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_executeQuery(chain, statement);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public ResultSetProxy preparedStatement_executeQuery(PreparedStatementProxy statement)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.preparedStatement_executeQuery(chain, statement);\n            } catch (Error ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public void dataSource_recycle(DruidPooledConnection connection) throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.dataSource_releaseConnection(chain, null);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public void dataSource_recycle(DruidPooledConnection connection) throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.dataSource_releaseConnection(chain, null);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public void dataSource_recycle(DruidPooledConnection connection) throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.dataSource_releaseConnection(chain, null);\n            } catch (Error ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        // //////////////////////////\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public DruidPooledConnection dataSource_connect(DruidDataSource dataSource, long maxWaitMillis)\n                        throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.dataSource_getConnection(chain, null, 0L);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public DruidPooledConnection dataSource_connect(DruidDataSource dataSource, long maxWaitMillis)\n                        throws SQLException {\n                    throw new RuntimeException();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.dataSource_getConnection(chain, null, 0L);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            FilterChain chain = new FilterChainImpl(new DataSourceProxyImpl(null, config)) {\n                public DruidPooledConnection dataSource_connect(DruidDataSource dataSource, long maxWaitMillis)\n                        throws SQLException {\n                    throw new Error();\n                }\n            };\n\n            Throwable error = null;\n            try {\n                filter.dataSource_getConnection(chain, null, 0L);\n            } catch (Error ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/JdbcUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.mock.MockResultSetMetaData;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.sql.Types;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class JdbcUtilsTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_print() throws Exception {\n        final AtomicInteger nextCount = new AtomicInteger(2);\n\n        final MockResultSetMetaData rsMeta = new MockResultSetMetaData() {\n            private int[] types = new int[]{Types.DATE, Types.BIT, Types.BOOLEAN, Types.TINYINT,\n\n                    Types.SMALLINT, Types.INTEGER, Types.CLOB, Types.LONGVARCHAR, Types.OTHER,\n\n                    Types.VARCHAR, Types.CHAR, Types.NVARCHAR, Types.NCHAR\n\n            };\n\n            @Override\n            public int getColumnCount() throws SQLException {\n                return types.length;\n            }\n\n            @Override\n            public int getColumnType(int column) throws SQLException {\n                return types[column - 1];\n            }\n\n            @Override\n            public String getColumnName(int column) throws SQLException {\n                return \"C\" + column;\n            }\n        };\n\n        MockResultSet rs = new MockResultSet(null) {\n            @Override\n            public boolean next() throws SQLException {\n                return nextCount.getAndDecrement() > 0;\n            }\n\n            @Override\n            public ResultSetMetaData getMetaData() throws SQLException {\n                return rsMeta;\n            }\n\n            @Override\n            public java.sql.Date getDate(int columnIndex) throws SQLException {\n                return new java.sql.Date(System.currentTimeMillis());\n            }\n\n            @Override\n            public boolean wasNull() throws SQLException {\n                if (nextCount.get() == 1) {\n                    return true;\n                }\n                return false;\n            }\n\n            public Object getObject(int columnIndex) throws SQLException {\n                return null;\n            }\n        };\n\n        JdbcUtils.printResultSet(rs);\n    }\n\n    @Test\n    public void test_close() throws Exception {\n        JdbcUtils.close((Connection) null);\n        JdbcUtils.close((Statement) null);\n        JdbcUtils.close((ResultSet) null);\n\n        JdbcUtils.close(new MockConnection() {\n            @Override\n            public void close() throws SQLException {\n                throw new SQLException();\n            }\n        });\n        JdbcUtils.close(new MockStatement(null) {\n            @Override\n            public void close() throws SQLException {\n                throw new SQLException();\n            }\n        });\n        JdbcUtils.close(new MockResultSet(null) {\n            @Override\n            public void close() throws SQLException {\n                throw new SQLException();\n            }\n        });\n        JdbcUtils.close(new Closeable() {\n            @Override\n            public void close() throws IOException {\n                throw new IOException();\n            }\n        });\n        JdbcUtils.close(new Closeable() {\n            @Override\n            public void close() throws IOException {\n            }\n        });\n        JdbcUtils.close((Closeable) null);\n\n        new JdbcUtils();\n    }\n\n    @Test\n    public void test_getTypeName() {\n        JdbcUtils.getTypeName(Types.ARRAY);\n        JdbcUtils.getTypeName(Types.BIGINT);\n        JdbcUtils.getTypeName(Types.BINARY);\n        JdbcUtils.getTypeName(Types.BIT);\n        JdbcUtils.getTypeName(Types.BLOB);\n        JdbcUtils.getTypeName(Types.BOOLEAN);\n        JdbcUtils.getTypeName(Types.CHAR);\n        JdbcUtils.getTypeName(Types.CLOB);\n        JdbcUtils.getTypeName(Types.DATALINK);\n        JdbcUtils.getTypeName(Types.DATE);\n        JdbcUtils.getTypeName(Types.DECIMAL);\n        JdbcUtils.getTypeName(Types.DISTINCT);\n        JdbcUtils.getTypeName(Types.DOUBLE);\n        JdbcUtils.getTypeName(Types.FLOAT);\n        JdbcUtils.getTypeName(Types.INTEGER);\n        JdbcUtils.getTypeName(Types.JAVA_OBJECT);\n        JdbcUtils.getTypeName(Types.LONGNVARCHAR);\n        JdbcUtils.getTypeName(Types.LONGVARBINARY);\n        JdbcUtils.getTypeName(Types.NCHAR);\n        JdbcUtils.getTypeName(Types.NCLOB);\n        JdbcUtils.getTypeName(Types.NULL);\n        JdbcUtils.getTypeName(Types.NUMERIC);\n        JdbcUtils.getTypeName(Types.NVARCHAR);\n        JdbcUtils.getTypeName(Types.REAL);\n        JdbcUtils.getTypeName(Types.REF);\n        JdbcUtils.getTypeName(Types.ROWID);\n        JdbcUtils.getTypeName(Types.SMALLINT);\n        JdbcUtils.getTypeName(Types.SQLXML);\n        JdbcUtils.getTypeName(Types.STRUCT);\n        JdbcUtils.getTypeName(Types.TIME);\n        JdbcUtils.getTypeName(Types.TIMESTAMP);\n        JdbcUtils.getTypeName(Types.TINYINT);\n        JdbcUtils.getTypeName(Types.VARBINARY);\n        JdbcUtils.getTypeName(Types.VARCHAR);\n        JdbcUtils.getTypeName(Types.OTHER);\n    }\n\n    @Test\n    public void test_read() throws Exception {\n        {\n            Exception error = null;\n            try {\n                Utils.read(new Reader() {\n                    @Override\n                    public int read(char[] cbuf, int off, int len) throws IOException {\n                        throw new IOException();\n                    }\n\n                    @Override\n                    public void close() throws IOException {\n                        throw new IOException();\n                    }\n\n                });\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        {\n            Exception error = null;\n            try {\n                Utils.read(new Reader() {\n                    @Override\n                    public int read(char[] cbuf, int off, int len) throws IOException {\n                        throw new IOException();\n                    }\n\n                    @Override\n                    public void close() throws IOException {\n                        throw new IOException();\n                    }\n\n                }, 0);\n            } catch (RuntimeException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        {\n            String text = Utils.read(new Reader() {\n                @Override\n                public int read(char[] cbuf, int off, int len) throws IOException {\n                    return -1;\n                }\n\n                @Override\n                public void close() throws IOException {\n                    throw new IOException();\n                }\n\n            }, 1);\n            assertEquals(\"\", text);\n        }\n        {\n            String text = Utils.read(new Reader() {\n                @Override\n                public int read(char[] cbuf, int off, int len) throws IOException {\n                    for (int i = off; i < len; ++i) {\n                        cbuf[i] = 'A';\n                    }\n                    return len;\n                }\n\n                @Override\n                public void close() throws IOException {\n                    throw new IOException();\n                }\n\n            }, 2);\n            assertEquals(\"AA\", text);\n        }\n        {\n            Reader reader = new Reader() {\n                @Override\n                public int read(char[] cbuf, int off, int len) throws IOException {\n                    cbuf[off] = 'A';\n                    return 1;\n                }\n\n                @Override\n                public void close() throws IOException {\n                    throw new IOException();\n                }\n\n            };\n            String text = Utils.read(reader, 2);\n            assertEquals(\"AA\", text);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/Log4j2FilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.logging.Log4j2Filter;\nimport com.alibaba.druid.filter.logging.LogFilter;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.apache.log4j.Priority;\nimport org.apache.logging.log4j.Level;\nimport org.apache.logging.log4j.Logger;\nimport org.apache.logging.log4j.Marker;\nimport org.apache.logging.log4j.message.EntryMessage;\nimport org.apache.logging.log4j.message.Message;\nimport org.apache.logging.log4j.message.MessageFactory;\nimport org.apache.logging.log4j.util.MessageSupplier;\nimport org.apache.logging.log4j.util.Supplier;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Log4j2FilterTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_logger() throws Exception {\n        Log4j2Filter filter = null;\n        try {\n            filter = new Log4j2Filter();\n        } catch (Throwable ignored) {\n            return;\n        }\n\n        filter.setDataSourceLoggerName(\"_datasource_name_\");\n        filter.setConnectionLoggerName(\"_connection_name_\");\n        filter.setStatementLoggerName(\"_statement_name_\");\n        filter.setResultSetLoggerName(\"_resultset_name_\");\n\n        assertEquals(filter.getDataSourceLoggerName(), \"_datasource_name_\");\n        assertEquals(filter.getConnectionLoggerName(), \"_connection_name_\");\n        assertEquals(filter.getStatementLoggerName(), \"_statement_name_\");\n        assertEquals(filter.getResultSetLoggerName(), \"_resultset_name_\");\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", true));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", true));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", true));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", true));\n\n        assertEquals(filter.getDataSourceLoggerName(), \"_datasoure_\");\n        assertEquals(filter.getConnectionLoggerName(), \"_connection_\");\n        assertEquals(filter.getStatementLoggerName(), \"_statement_\");\n        assertEquals(filter.getResultSetLoggerName(), \"_resultset_\");\n\n        setLogDisableAll(filter, true);\n\n        assertTrue(filter.isDataSourceLogEnabled());\n\n        assertTrue(filter.isConnectionLogErrorEnabled());\n        assertTrue(filter.isConnectionConnectBeforeLogEnabled());\n        assertTrue(filter.isConnectionConnectAfterLogEnabled());\n        assertTrue(filter.isConnectionCloseAfterLogEnabled());\n        assertTrue(filter.isConnectionCommitAfterLogEnabled());\n        assertTrue(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertTrue(filter.isStatementLogEnabled());\n        assertTrue(filter.isStatementLogErrorEnabled());\n        assertTrue(filter.isStatementCreateAfterLogEnabled());\n        assertTrue(filter.isStatementCloseAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertTrue(filter.isStatementLogErrorEnabled());\n        assertTrue(filter.isStatementParameterSetLogEnabled());\n        assertTrue(filter.isStatementPrepareAfterLogEnabled());\n        assertTrue(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertTrue(filter.isResultSetLogEnabled());\n        assertTrue(filter.isResultSetLogErrorEnabled());\n        assertTrue(filter.isResultSetCloseAfterLogEnabled());\n        assertTrue(filter.isResultSetNextAfterLogEnabled());\n        assertTrue(filter.isResultSetOpenAfterLogEnabled());\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", false));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", false));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", false));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", false));\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n\n        // //////////////////////////////////////\n\n        setLogDisableAll(filter, false);\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", false));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", false));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", false));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", false));\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n\n        // //\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", true));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", true));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", true));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", true));\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n    }\n\n    private void setLogDisableAll(LogFilter logFilter, boolean enable) {\n        logFilter.setDataSourceLogEnabled(enable);\n\n        logFilter.setConnectionLogEnabled(enable);\n        logFilter.setConnectionLogErrorEnabled(enable);\n        logFilter.setConnectionRollbackAfterLogEnabled(enable);\n        logFilter.setConnectionConnectBeforeLogEnabled(enable);\n        logFilter.setConnectionConnectAfterLogEnabled(enable);\n        logFilter.setConnectionCommitAfterLogEnabled(enable);\n        logFilter.setConnectionCloseAfterLogEnabled(enable);\n\n        logFilter.setStatementLogEnabled(enable);\n        logFilter.setStatementLogErrorEnabled(enable);\n        logFilter.setStatementCreateAfterLogEnabled(enable);\n        logFilter.setStatementExecuteAfterLogEnabled(enable);\n        logFilter.setStatementExecuteBatchAfterLogEnabled(enable);\n        logFilter.setStatementExecuteQueryAfterLogEnabled(enable);\n        logFilter.setStatementExecuteUpdateAfterLogEnabled(enable);\n        logFilter.setStatementPrepareCallAfterLogEnabled(enable);\n        logFilter.setStatementPrepareAfterLogEnabled(enable);\n        logFilter.setStatementCloseAfterLogEnabled(enable);\n\n        logFilter.setResultSetLogEnabled(enable);\n        logFilter.setResultSetOpenAfterLogEnabled(enable);\n        logFilter.setResultSetNextAfterLogEnabled(enable);\n        logFilter.setResultSetLogErrorEnabled(enable);\n        logFilter.setResultSetCloseAfterLogEnabled(enable);\n    }\n\n    public static class FakeLogger implements Logger {\n        private boolean enable;\n        private String name;\n\n        public FakeLogger(String name, boolean enable) {\n            this.name = name;\n            this.enable = enable;\n        }\n\n        public boolean isDebugEnabled() {\n            return this.enable;\n        }\n\n        public boolean isEnabledFor(Priority level) {\n            return this.enable;\n        }\n\n        @Override\n        public void catching(Level level, Throwable t) {\n        }\n\n        @Override\n        public void catching(Throwable t) {\n        }\n\n        @Override\n        public void debug(Marker marker, Message msg) {\n        }\n\n        @Override\n        public void debug(Marker marker, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void debug(Marker marker, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void debug(Marker marker, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void debug(Marker marker, CharSequence message) {\n        }\n\n        @Override\n        public void debug(Marker marker, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void debug(Marker marker, Object message) {\n        }\n\n        @Override\n        public void debug(Marker marker, Object message, Throwable t) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object... params) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Throwable t) {\n        }\n\n        @Override\n        public void debug(Marker marker, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void debug(Marker marker, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void debug(Message msg) {\n        }\n\n        @Override\n        public void debug(Message msg, Throwable t) {\n        }\n\n        @Override\n        public void debug(MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void debug(MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void debug(CharSequence message) {\n        }\n\n        @Override\n        public void debug(CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void debug(Object message) {\n        }\n\n        @Override\n        public void debug(Object message, Throwable t) {\n        }\n\n        @Override\n        public void debug(String message) {\n        }\n\n        @Override\n        public void debug(String message, Object... params) {\n        }\n\n        @Override\n        public void debug(String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void debug(String message, Throwable t) {\n        }\n\n        @Override\n        public void debug(Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void debug(Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void debug(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void debug(String message, Object p0) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void debug(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void entry() {\n        }\n\n        @Override\n        public void entry(Object... params) {\n        }\n\n        @Override\n        public void error(Marker marker, Message msg) {\n        }\n\n        @Override\n        public void error(Marker marker, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void error(Marker marker, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void error(Marker marker, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void error(Marker marker, CharSequence message) {\n        }\n\n        @Override\n        public void error(Marker marker, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void error(Marker marker, Object message) {\n        }\n\n        @Override\n        public void error(Marker marker, Object message, Throwable t) {\n        }\n\n        @Override\n        public void error(Marker marker, String message) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object... params) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Throwable t) {\n        }\n\n        @Override\n        public void error(Marker marker, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void error(Marker marker, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void error(Message msg) {\n        }\n\n        @Override\n        public void error(Message msg, Throwable t) {\n        }\n\n        @Override\n        public void error(MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void error(MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void error(CharSequence message) {\n        }\n\n        @Override\n        public void error(CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void error(Object message) {\n        }\n\n        @Override\n        public void error(Object message, Throwable t) {\n        }\n\n        @Override\n        public void error(String message) {\n        }\n\n        @Override\n        public void error(String message, Object... params) {\n        }\n\n        @Override\n        public void error(String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void error(String message, Throwable t) {\n        }\n\n        @Override\n        public void error(Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void error(Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void error(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void error(String message, Object p0) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void error(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void exit() {\n        }\n\n        @Override\n        public <R> R exit(R result) {\n            return null;\n        }\n\n        @Override\n        public void fatal(Marker marker, Message msg) {\n        }\n\n        @Override\n        public void fatal(Marker marker, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Marker marker, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void fatal(Marker marker, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Marker marker, CharSequence message) {\n        }\n\n        @Override\n        public void fatal(Marker marker, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Marker marker, Object message) {\n        }\n\n        @Override\n        public void fatal(Marker marker, Object message, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object... params) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Marker marker, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void fatal(Marker marker, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Message msg) {\n        }\n\n        @Override\n        public void fatal(Message msg, Throwable t) {\n        }\n\n        @Override\n        public void fatal(MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void fatal(MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void fatal(CharSequence message) {\n        }\n\n        @Override\n        public void fatal(CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Object message) {\n        }\n\n        @Override\n        public void fatal(Object message, Throwable t) {\n        }\n\n        @Override\n        public void fatal(String message) {\n        }\n\n        @Override\n        public void fatal(String message, Object... params) {\n        }\n\n        @Override\n        public void fatal(String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void fatal(String message, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void fatal(Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void fatal(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void fatal(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public Level getLevel() {\n            return null;\n        }\n\n        @Override\n        public MessageFactory getMessageFactory() {\n            return null;\n        }\n\n        @Override\n        public String getName() {\n            return name;\n        }\n\n        @Override\n        public void info(Marker marker, Message msg) {\n        }\n\n        @Override\n        public void info(Marker marker, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void info(Marker marker, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void info(Marker marker, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void info(Marker marker, CharSequence message) {\n        }\n\n        @Override\n        public void info(Marker marker, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void info(Marker marker, Object message) {\n        }\n\n        @Override\n        public void info(Marker marker, Object message, Throwable t) {\n        }\n\n        @Override\n        public void info(Marker marker, String message) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object... params) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Throwable t) {\n        }\n\n        @Override\n        public void info(Marker marker, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void info(Marker marker, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void info(Message msg) {\n        }\n\n        @Override\n        public void info(Message msg, Throwable t) {\n        }\n\n        @Override\n        public void info(MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void info(MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void info(CharSequence message) {\n        }\n\n        @Override\n        public void info(CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void info(Object message) {\n        }\n\n        @Override\n        public void info(Object message, Throwable t) {\n        }\n\n        @Override\n        public void info(String message) {\n        }\n\n        @Override\n        public void info(String message, Object... params) {\n        }\n\n        @Override\n        public void info(String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void info(String message, Throwable t) {\n        }\n\n        @Override\n        public void info(Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void info(Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void info(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void info(String message, Object p0) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void info(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public boolean isDebugEnabled(Marker marker) {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isEnabled(Level level) {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isEnabled(Level level, Marker marker) {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isErrorEnabled() {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isErrorEnabled(Marker marker) {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isFatalEnabled() {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isFatalEnabled(Marker marker) {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isInfoEnabled() {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isInfoEnabled(Marker marker) {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isTraceEnabled() {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isTraceEnabled(Marker marker) {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isWarnEnabled() {\n            return this.enable;\n        }\n\n        @Override\n        public boolean isWarnEnabled(Marker marker) {\n            return this.enable;\n        }\n\n        @Override\n        public void log(Level level, Marker marker, Message msg) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, CharSequence message) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, Object message) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, Object message, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object... params) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Message msg) {\n        }\n\n        @Override\n        public void log(Level level, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void log(Level level, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, CharSequence message) {\n        }\n\n        @Override\n        public void log(Level level, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Object message) {\n        }\n\n        @Override\n        public void log(Level level, Object message, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, String message) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object... params) {\n        }\n\n        @Override\n        public void log(Level level, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void log(Level level, String message, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void log(Level level, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void log(Level level, Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void log(Level level, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void printf(Level level, Marker marker, String format, Object... params) {\n        }\n\n        @Override\n        public void printf(Level level, String format, Object... params) {\n        }\n\n        @Override\n        public <T extends Throwable> T throwing(Level level, T t) {\n            return null;\n        }\n\n        @Override\n        public <T extends Throwable> T throwing(T t) {\n            return null;\n        }\n\n        @Override\n        public void trace(Marker marker, Message msg) {\n        }\n\n        @Override\n        public void trace(Marker marker, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void trace(Marker marker, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void trace(Marker marker, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void trace(Marker marker, CharSequence message) {\n        }\n\n        @Override\n        public void trace(Marker marker, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void trace(Marker marker, Object message) {\n        }\n\n        @Override\n        public void trace(Marker marker, Object message, Throwable t) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object... params) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Throwable t) {\n        }\n\n        @Override\n        public void trace(Marker marker, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void trace(Marker marker, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void trace(Message msg) {\n        }\n\n        @Override\n        public void trace(Message msg, Throwable t) {\n        }\n\n        @Override\n        public void trace(MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void trace(MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void trace(CharSequence message) {\n        }\n\n        @Override\n        public void trace(CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void trace(Object message) {\n        }\n\n        @Override\n        public void trace(Object message, Throwable t) {\n        }\n\n        @Override\n        public void trace(String message) {\n        }\n\n        @Override\n        public void trace(String message, Object... params) {\n        }\n\n        @Override\n        public void trace(String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void trace(String message, Throwable t) {\n        }\n\n        @Override\n        public void trace(Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void trace(Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void trace(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void trace(String message, Object p0) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void trace(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public EntryMessage traceEntry() {\n            return null;\n        }\n\n        @Override\n        public EntryMessage traceEntry(String format, Object... params) {\n            return null;\n        }\n\n        @Override\n        public EntryMessage traceEntry(Supplier<?>... paramSuppliers) {\n            return null;\n        }\n\n        @Override\n        public EntryMessage traceEntry(String format, Supplier<?>... paramSuppliers) {\n            return null;\n        }\n\n        @Override\n        public EntryMessage traceEntry(Message message) {\n            return null;\n        }\n\n        @Override\n        public void traceExit() {\n        }\n\n        @Override\n        public <R> R traceExit(R result) {\n            return null;\n        }\n\n        @Override\n        public <R> R traceExit(String format, R result) {\n            return null;\n        }\n\n        @Override\n        public void traceExit(EntryMessage message) {\n        }\n\n        @Override\n        public <R> R traceExit(EntryMessage message, R result) {\n            return null;\n        }\n\n        @Override\n        public <R> R traceExit(Message message, R result) {\n            return null;\n        }\n\n        @Override\n        public void warn(Marker marker, Message msg) {\n        }\n\n        @Override\n        public void warn(Marker marker, Message msg, Throwable t) {\n        }\n\n        @Override\n        public void warn(Marker marker, MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void warn(Marker marker, MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void warn(Marker marker, CharSequence message) {\n        }\n\n        @Override\n        public void warn(Marker marker, CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void warn(Marker marker, Object message) {\n        }\n\n        @Override\n        public void warn(Marker marker, Object message, Throwable t) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object... params) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Throwable t) {\n        }\n\n        @Override\n        public void warn(Marker marker, Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void warn(Marker marker, Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void warn(Message msg) {\n        }\n\n        @Override\n        public void warn(Message msg, Throwable t) {\n        }\n\n        @Override\n        public void warn(MessageSupplier msgSupplier) {\n        }\n\n        @Override\n        public void warn(MessageSupplier msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void warn(CharSequence message) {\n        }\n\n        @Override\n        public void warn(CharSequence message, Throwable t) {\n        }\n\n        @Override\n        public void warn(Object message) {\n        }\n\n        @Override\n        public void warn(Object message, Throwable t) {\n        }\n\n        @Override\n        public void warn(String message) {\n        }\n\n        @Override\n        public void warn(String message, Object... params) {\n        }\n\n        @Override\n        public void warn(String message, Supplier<?>... paramSuppliers) {\n        }\n\n        @Override\n        public void warn(String message, Throwable t) {\n        }\n\n        @Override\n        public void warn(Supplier<?> msgSupplier) {\n        }\n\n        @Override\n        public void warn(Supplier<?> msgSupplier, Throwable t) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void warn(Marker marker, String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n\n        @Override\n        public void warn(String message, Object p0) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2, Object p3) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2, Object p3, Object p4) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {\n        }\n\n        @Override\n        public void warn(String message, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/Log4jFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.logging.Log4jFilter;\nimport com.alibaba.druid.filter.logging.LogFilter;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.apache.log4j.Logger;\nimport org.apache.log4j.Priority;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Log4jFilterTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_logger() throws Exception {\n        Log4jFilter filter = new Log4jFilter();\n\n        filter.setDataSourceLoggerName(\"_datasource_name_\");\n        filter.setConnectionLoggerName(\"_connection_name_\");\n        filter.setStatementLoggerName(\"_statement_name_\");\n        filter.setResultSetLoggerName(\"_resultset_name_\");\n\n        assertEquals(filter.getDataSourceLoggerName(), \"_datasource_name_\");\n        assertEquals(filter.getConnectionLoggerName(), \"_connection_name_\");\n        assertEquals(filter.getStatementLoggerName(), \"_statement_name_\");\n        assertEquals(filter.getResultSetLoggerName(), \"_resultset_name_\");\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", true));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", true));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", true));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", true));\n\n        assertEquals(filter.getDataSourceLoggerName(), \"_datasoure_\");\n        assertEquals(filter.getConnectionLoggerName(), \"_connection_\");\n        assertEquals(filter.getStatementLoggerName(), \"_statement_\");\n        assertEquals(filter.getResultSetLoggerName(), \"_resultset_\");\n\n        setLogDisableAll(filter, true);\n\n        assertTrue(filter.isDataSourceLogEnabled());\n\n        assertTrue(filter.isConnectionLogErrorEnabled());\n        assertTrue(filter.isConnectionConnectBeforeLogEnabled());\n        assertTrue(filter.isConnectionConnectAfterLogEnabled());\n        assertTrue(filter.isConnectionCloseAfterLogEnabled());\n        assertTrue(filter.isConnectionCommitAfterLogEnabled());\n        assertTrue(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertTrue(filter.isStatementLogEnabled());\n        assertTrue(filter.isStatementLogErrorEnabled());\n        assertTrue(filter.isStatementCreateAfterLogEnabled());\n        assertTrue(filter.isStatementCloseAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertTrue(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertTrue(filter.isStatementLogErrorEnabled());\n        assertTrue(filter.isStatementParameterSetLogEnabled());\n        assertTrue(filter.isStatementPrepareAfterLogEnabled());\n        assertTrue(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertTrue(filter.isResultSetLogEnabled());\n        assertTrue(filter.isResultSetLogErrorEnabled());\n        assertTrue(filter.isResultSetCloseAfterLogEnabled());\n        assertTrue(filter.isResultSetNextAfterLogEnabled());\n        assertTrue(filter.isResultSetOpenAfterLogEnabled());\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", false));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", false));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", false));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", false));\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n\n        // //////////////////////////////////////\n\n        setLogDisableAll(filter, false);\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", false));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", false));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", false));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", false));\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n\n        // //\n\n        // ////\n\n        filter.setDataSourceLogger(new FakeLogger(\"_datasoure_\", true));\n        filter.setConnectionLogger(new FakeLogger(\"_connection_\", true));\n        filter.setStatementLogger(new FakeLogger(\"_statement_\", true));\n        filter.setResultSetLogger(new FakeLogger(\"_resultset_\", true));\n\n        assertFalse(filter.isDataSourceLogEnabled());\n\n        assertFalse(filter.isConnectionLogErrorEnabled());\n        assertFalse(filter.isConnectionConnectBeforeLogEnabled());\n        assertFalse(filter.isConnectionConnectAfterLogEnabled());\n        assertFalse(filter.isConnectionCloseAfterLogEnabled());\n        assertFalse(filter.isConnectionCommitAfterLogEnabled());\n        assertFalse(filter.isConnectionRollbackAfterLogEnabled());\n\n        assertFalse(filter.isStatementLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementCreateAfterLogEnabled());\n        assertFalse(filter.isStatementCloseAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteBatchAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteQueryAfterLogEnabled());\n        assertFalse(filter.isStatementExecuteUpdateAfterLogEnabled());\n        assertFalse(filter.isStatementLogErrorEnabled());\n        assertFalse(filter.isStatementParameterSetLogEnabled());\n        assertFalse(filter.isStatementPrepareAfterLogEnabled());\n        assertFalse(filter.isStatementPrepareCallAfterLogEnabled());\n\n        assertFalse(filter.isResultSetLogEnabled());\n        assertFalse(filter.isResultSetLogErrorEnabled());\n        assertFalse(filter.isResultSetCloseAfterLogEnabled());\n        assertFalse(filter.isResultSetNextAfterLogEnabled());\n        assertFalse(filter.isResultSetOpenAfterLogEnabled());\n    }\n\n    private void setLogDisableAll(LogFilter logFilter, boolean enable) {\n        logFilter.setDataSourceLogEnabled(enable);\n\n        logFilter.setConnectionLogEnabled(enable);\n        logFilter.setConnectionLogErrorEnabled(enable);\n        logFilter.setConnectionRollbackAfterLogEnabled(enable);\n        logFilter.setConnectionConnectBeforeLogEnabled(enable);\n        logFilter.setConnectionConnectAfterLogEnabled(enable);\n        logFilter.setConnectionCommitAfterLogEnabled(enable);\n        logFilter.setConnectionCloseAfterLogEnabled(enable);\n\n        logFilter.setStatementLogEnabled(enable);\n        logFilter.setStatementLogErrorEnabled(enable);\n        logFilter.setStatementCreateAfterLogEnabled(enable);\n        logFilter.setStatementExecuteAfterLogEnabled(enable);\n        logFilter.setStatementExecuteBatchAfterLogEnabled(enable);\n        logFilter.setStatementExecuteQueryAfterLogEnabled(enable);\n        logFilter.setStatementExecuteUpdateAfterLogEnabled(enable);\n        logFilter.setStatementPrepareCallAfterLogEnabled(enable);\n        logFilter.setStatementPrepareAfterLogEnabled(enable);\n        logFilter.setStatementCloseAfterLogEnabled(enable);\n\n        logFilter.setResultSetLogEnabled(enable);\n        logFilter.setResultSetOpenAfterLogEnabled(enable);\n        logFilter.setResultSetNextAfterLogEnabled(enable);\n        logFilter.setResultSetLogErrorEnabled(enable);\n        logFilter.setResultSetCloseAfterLogEnabled(enable);\n    }\n\n    public static class FakeLogger extends Logger {\n        private boolean enable;\n\n        public FakeLogger(String name, boolean enable) {\n            super(name);\n            this.enable = enable;\n        }\n\n        public boolean isDebugEnabled() {\n            return this.enable;\n        }\n\n        public boolean isEnabledFor(Priority level) {\n            return this.enable;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/LogFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.FilterChainImpl;\nimport com.alibaba.druid.filter.logging.CommonsLogFilter;\nimport com.alibaba.druid.filter.logging.Log4jFilter;\nimport com.alibaba.druid.filter.logging.LogFilter;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.mock.MockRef;\nimport com.alibaba.druid.mock.MockResultSet;\nimport com.alibaba.druid.mock.MockResultSetMetaData;\nimport com.alibaba.druid.mock.MockRowId;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxy;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.StatementProxy;\nimport com.alibaba.druid.proxy.jdbc.StatementProxyImpl;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.*;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LogFilterTest {\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_logFilter_0() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        config.setRawUrl(\"jdbc:mock:\");\n        DataSourceProxyImpl dataSource = new DataSourceProxyImpl(new MockDriver(), config);\n\n        Log4jFilter log4jFilter = new Log4jFilter();\n        log4jFilter.init(dataSource);\n        config.getFilters().add(log4jFilter);\n        setLogDisableAll(log4jFilter, true);\n\n        CommonsLogFilter commonLogFilter = new CommonsLogFilter() {\n            @Override\n            public boolean isDataSourceLogEnabled() {\n                return true;\n            }\n\n            @Override\n            public boolean isConnectionLogEnabled() {\n                return true;\n            }\n\n            @Override\n            public boolean isStatementLogEnabled() {\n                return true;\n            }\n\n            @Override\n            public boolean isResultSetLogEnabled() {\n                return true;\n            }\n\n            @Override\n            public boolean isResultSetLogErrorEnabled() {\n                return true;\n            }\n\n            @Override\n            public boolean isResultSetNextAfterLogEnabled() {\n                return true;\n            }\n        };\n        commonLogFilter.init(dataSource);\n        config.getFilters().add(commonLogFilter);\n\n        setLogDisableAll(commonLogFilter, false);\n        executeSQL(dataSource);\n    }\n\n    @Test\n    public void test_logFilter_1() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        config.setRawUrl(\"jdbc:mock:\");\n        DataSourceProxyImpl dataSource = new DataSourceProxyImpl(new MockDriver(), config);\n\n        Log4jFilter log4jFilter = new Log4jFilter();\n        log4jFilter.init(dataSource);\n        config.getFilters().add(log4jFilter);\n        setLogDisableAll(log4jFilter, true);\n\n        CommonsLogFilter commonLogFilter = new CommonsLogFilter() {\n            @Override\n            public boolean isDataSourceLogEnabled() {\n                return false;\n            }\n\n            @Override\n            public boolean isConnectionLogEnabled() {\n                return false;\n            }\n\n            @Override\n            public boolean isStatementLogEnabled() {\n                return false;\n            }\n\n            @Override\n            public boolean isResultSetLogEnabled() {\n                return false;\n            }\n\n            @Override\n            public boolean isResultSetLogErrorEnabled() {\n                return false;\n            }\n\n            @Override\n            public boolean isResultSetNextAfterLogEnabled() {\n                return false;\n            }\n        };\n        commonLogFilter.init(dataSource);\n        config.getFilters().add(commonLogFilter);\n\n        setLogDisableAll(commonLogFilter, true);\n        executeSQL(dataSource);\n    }\n\n    @Test\n    public void test_logFilter_2() throws Exception {\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        config.setRawUrl(\"jdbc:mock:\");\n        DataSourceProxyImpl dataSource = new DataSourceProxyImpl(new MockDriver(), config);\n\n        Log4jFilter log4jFilter = new Log4jFilter();\n        {\n            log4jFilter.init(dataSource);\n            setLogDisableAll(log4jFilter, true);\n            config.getFilters().add(log4jFilter);\n        }\n\n        CommonsLogFilter logFilter = new CommonsLogFilter();\n        {\n            logFilter.init(dataSource);\n            setLogDisableAll(logFilter, true);\n            config.getFilters().add(logFilter);\n        }\n\n        final MockResultSetMetaData rsMeta = new MockResultSetMetaData() {\n            private int[] types = new int[]{Types.BLOB, Types.CLOB, Types.NCLOB, Types.BINARY, Types.OTHER};\n\n            @Override\n            public int getColumnCount() throws SQLException {\n                return types.length;\n            }\n\n            @Override\n            public int getColumnType(int column) throws SQLException {\n                return types[column - 1];\n            }\n\n        };\n\n        ConnectionProxy conn = (ConnectionProxy) dataSource.connect(new Properties());\n\n        {\n            StatementProxy stmt = (StatementProxy) conn.createStatement();\n            MockResultSet rs = new MockResultSet(null) {\n                @Override\n                public ResultSetMetaData getMetaData() throws SQLException {\n                    return rsMeta;\n                }\n\n                @Override\n                public boolean next() throws SQLException {\n                    return true;\n                }\n\n                @Override\n                public Object getObject(int columnIndex) throws SQLException {\n                    if (columnIndex == 5) {\n                        throw new SQLException();\n                    }\n                    return null;\n                }\n            };\n\n            FilterChainImpl chain = new FilterChainImpl(dataSource);\n            chain.resultSet_next(new ResultSetProxyImpl(stmt, rs, 1001, null));\n        }\n        {\n            final MockResultSet rs = new MockResultSet(null) {\n                @Override\n                public ResultSetMetaData getMetaData() throws SQLException {\n                    throw new SQLException();\n                }\n            };\n\n            StatementProxy stmt = new StatementProxyImpl(conn, new MockStatement(conn) {\n                public ResultSet getResultSet() throws SQLException {\n                    return rs;\n                }\n            }, 0);\n\n            FilterChainImpl chain = new FilterChainImpl(dataSource);\n            chain.statement_getResultSet(stmt);\n        }\n        {\n            StatementProxy stmt = (StatementProxy) conn.createStatement();\n            MockResultSet rs = new MockResultSet(null) {\n                @Override\n                public ResultSetMetaData getMetaData() throws SQLException {\n                    return rsMeta;\n                }\n\n                @Override\n                public boolean next() throws SQLException {\n                    return true;\n                }\n\n                @Override\n                public Object getObject(int columnIndex) throws SQLException {\n                    if (columnIndex == 5) {\n                        throw new SQLException();\n                    }\n                    return null;\n                }\n            };\n\n            {\n                logFilter.setResultSetLogEnabled(false);\n                FilterChainImpl chain = new FilterChainImpl(dataSource);\n                chain.resultSet_next(new ResultSetProxyImpl(stmt, rs, 1001, null));\n            }\n            {\n                logFilter.setResultSetNextAfterLogEnabled(false);\n                FilterChainImpl chain = new FilterChainImpl(dataSource);\n                chain.resultSet_next(new ResultSetProxyImpl(stmt, rs, 1001, null));\n            }\n        }\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    private void executeSQL(DataSourceProxyImpl dataSource) throws SQLException {\n        String sql = \"SELECT 1\";\n\n        Connection conn = dataSource.connect(new Properties());\n        conn.commit();\n        conn.rollback();\n\n        Statement stmt = conn.createStatement();\n        stmt.execute(sql);\n        stmt.addBatch(sql);\n        stmt.executeBatch();\n        stmt.executeQuery(sql);\n        stmt.executeUpdate(sql);\n        stmt.cancel();\n\n        PreparedStatement pstmt = conn.prepareStatement(sql);\n        pstmt.setArray(1, null);\n        pstmt.setAsciiStream(2, null);\n        pstmt.setBigDecimal(3, null);\n        pstmt.setBinaryStream(4, null);\n        pstmt.setBlob(5, conn.createBlob());\n        pstmt.setByte(6, (byte) 1);\n        pstmt.setBytes(7, new byte[1]);\n        pstmt.setCharacterStream(8, null);\n        pstmt.setClob(9, conn.createClob());\n        pstmt.setDate(10, null);\n        pstmt.setFloat(11, 1F);\n        pstmt.setInt(12, 1);\n        pstmt.setLong(13, 1L);\n        pstmt.setNCharacterStream(14, null);\n        pstmt.setNClob(15, conn.createNClob());\n        pstmt.setNString(16, null);\n        pstmt.setNull(17, Types.VARCHAR);\n        pstmt.setObject(18, null);\n        pstmt.setRef(19, new MockRef());\n        pstmt.setRowId(20, new MockRowId());\n        pstmt.setShort(21, (short) 1);\n        pstmt.setSQLXML(22, conn.createSQLXML());\n        pstmt.setString(23, \"\");\n        pstmt.setTime(24, null);\n        pstmt.setTimestamp(25, null);\n        pstmt.setUnicodeStream(26, null, 0);\n        pstmt.setURL(27, null);\n\n        pstmt.execute();\n        pstmt.addBatch();\n        pstmt.executeBatch();\n        pstmt.executeQuery();\n        pstmt.executeUpdate();\n\n        conn.prepareCall(sql);\n\n        ResultSet rs = stmt.executeQuery(sql);\n        rs.next();\n        rs.close();\n\n        {\n            Exception error = null;\n            try {\n                stmt.execute(MockStatement.ERROR_SQL);\n            } catch (SQLException ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        stmt.close();\n        pstmt.close();\n        conn.close();\n    }\n\n    private void setLogDisableAll(LogFilter logFilter, boolean enable) {\n        logFilter.setDataSourceLogEnabled(enable);\n\n        logFilter.setConnectionLogErrorEnabled(enable);\n        logFilter.setConnectionRollbackAfterLogEnabled(enable);\n        logFilter.setConnectionConnectBeforeLogEnabled(enable);\n        logFilter.setConnectionConnectAfterLogEnabled(enable);\n        logFilter.setConnectionCommitAfterLogEnabled(enable);\n        logFilter.setConnectionCloseAfterLogEnabled(enable);\n\n        logFilter.setStatementLogEnabled(enable);\n        logFilter.setStatementLogErrorEnabled(enable);\n        logFilter.setStatementCreateAfterLogEnabled(enable);\n        logFilter.setStatementExecuteAfterLogEnabled(enable);\n        logFilter.setStatementExecuteBatchAfterLogEnabled(enable);\n        logFilter.setStatementExecuteQueryAfterLogEnabled(enable);\n        logFilter.setStatementExecuteUpdateAfterLogEnabled(enable);\n        logFilter.setStatementPrepareCallAfterLogEnabled(enable);\n        logFilter.setStatementPrepareAfterLogEnabled(enable);\n        logFilter.setStatementCloseAfterLogEnabled(enable);\n        logFilter.setStatementParameterSetLogEnabled(enable);\n\n        logFilter.setResultSetLogEnabled(enable);\n        logFilter.setResultSetOpenAfterLogEnabled(enable);\n        logFilter.setResultSetNextAfterLogEnabled(enable);\n        logFilter.setResultSetLogErrorEnabled(enable);\n        logFilter.setResultSetCloseAfterLogEnabled(enable);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/PrecallTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PrecallTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=preCallTest:jdbc:derby:memory:preCallDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createTable();\n\n        conn.close();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_USER (ID INTEGER, NAME VARCHAR(50), BIRTHDATE TIMESTAMP)\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_USER\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n\n        DruidDriver.getProxyDataSources().clear();\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_precall() throws Exception {\n        Connection conn = null;\n        CallableStatement cstmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            cstmt = conn.prepareCall(\"CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)\", ResultSet.FETCH_FORWARD,\n                    ResultSet.CONCUR_READ_ONLY);\n            cstmt.close();\n\n            cstmt = conn.prepareCall(\"CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)\", ResultSet.FETCH_FORWARD,\n                    ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);\n            cstmt.close();\n\n            cstmt = conn.prepareCall(\"CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)\");\n\n            try {\n                cstmt.setObject(1, null);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                cstmt.setObject(1, null, Types.VARCHAR);\n            } catch (SQLDataException ex) {\n            }\n\n            try {\n                cstmt.setURL(1, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setURL(\"F1\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setSQLXML(1, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setSQLXML(\"F1\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setRowId(1, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setRowId(\"F1\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNString(1, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setNString(\"F1\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setBlob(1, (Blob) null);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                cstmt.setBlob(\"F1\", (Blob) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setBlob(1, (InputStream) null);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                cstmt.setBlob(\"F1\", (InputStream) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setBlob(1, (InputStream) null, 0);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                cstmt.setBlob(\"F1\", (InputStream) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setClob(1, (Clob) null);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                cstmt.setClob(\"F1\", (Clob) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setClob(1, (Reader) null);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                cstmt.setClob(\"F1\", (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setClob(1, (Reader) null, 0);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                cstmt.setClob(\"F1\", (Reader) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNClob(1, (NClob) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setNClob(\"F1\", (NClob) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNClob(1, (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setNClob(\"F1\", (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNClob(1, (Reader) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setNClob(\"F1\", (Reader) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNCharacterStream(1, (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setNCharacterStream(\"F1\", (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNCharacterStream(1, (Reader) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.setNCharacterStream(\"F1\", (Reader) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNull(\"F1\", Types.VARCHAR);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.setNull(\"F1\", Types.VARCHAR, \"VARCHAR\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getRef(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getRef(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getClob(1);\n            } catch (SQLException ex) {\n            }\n            try {\n                cstmt.getClob(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getArray(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getArray(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getURL(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getURL(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getSQLXML(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getSQLXML(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getRowId(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getRowId(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getNClob(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getNClob(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getNString(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getNString(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                cstmt.getNCharacterStream(1);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                cstmt.getNCharacterStream(\"F1\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            cstmt.setString(1, \"derby.locks.deadlockTimeout\");\n            cstmt.setString(2, \"10\");\n\n            cstmt.execute();\n\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(cstmt);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/PreparedStatementProxyImplGetParametersTest.java",
    "content": "package com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.jdbc.JdbcParameter;\nimport com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PreparedStatementProxyImplGetParametersTest {\n    private String url = \"jdbc:wrap-jdbc:filters=default:name=driverTest:jdbc:mock:xxx\";\n    private Connection conn;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        conn = DriverManager.getConnection(url);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(conn);\n    }\n\n    @Test\n    public void test_get_parameters() throws Exception {\n        final PreparedStatementProxy stmt = (PreparedStatementProxy) conn.prepareStatement(\"select 1\");\n\n        {\n            Map<Integer, JdbcParameter> paramMap = stmt.getParameters();\n            assertNotNull(paramMap);\n            assertEquals(paramMap.size(), 0);\n        }\n        stmt.setInt(1, 1);\n        {\n            Map<Integer, JdbcParameter> paramMap1 = stmt.getParameters();\n            assertNotNull(paramMap1);\n\n            Map<Integer, JdbcParameter> paramMap2 = stmt.getParameters();\n            assertNotNull(paramMap2);\n\n            assertSame(paramMap1, paramMap2);\n            assertEquals(paramMap1.size(), 1);\n        }\n        stmt.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/PreparedStatementTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.Reader;\nimport java.sql.*;\nimport java.util.Calendar;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PreparedStatementTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=preparedStatementTest:jdbc:derby:memory:preparedStatementTestDB;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createTable();\n\n        conn.close();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_PRE_STMT_TEST (ID SMALLINT, NAME VARCHAR(50), BIRTHDATE TIMESTAMP)\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_PRE_STMT_TEST\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n\n        DruidDriver.getProxyDataSources().clear();\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_pstmt() throws Exception {\n        Connection conn = null;\n        PreparedStatement pstmt = null;\n        PreparedStatement pstmt2 = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            pstmt = conn.prepareStatement(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (?, ?, ?)\",\n                    Statement.RETURN_GENERATED_KEYS);\n\n            pstmt.setShort(1, (short) 1);\n            pstmt.setString(2, \"A\");\n            pstmt.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()));\n            pstmt.execute();\n\n            pstmt.setShort(1, (short) 2);\n            pstmt.setString(2, \"B\");\n            pstmt.setNull(3, Types.TIMESTAMP);\n            pstmt.execute();\n\n            pstmt.setShort(1, (short) 3);\n            pstmt.setString(2, \"C\");\n            pstmt.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()), Calendar.getInstance());\n            pstmt.execute();\n\n            pstmt.setShort(1, (short) 3);\n            pstmt.setString(2, \"C\");\n            pstmt.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()), Calendar.getInstance());\n            try {\n                pstmt.setArray(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setObject(2, null);\n            } catch (SQLDataException ex) {\n            }\n            try {\n                pstmt.setNCharacterStream(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setNCharacterStream(2, null, 0L);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setNClob(2, (NClob) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setNClob(2, (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setNClob(2, null, 0L);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setNString(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setRef(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setRowId(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setSQLXML(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setURL(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                pstmt.setUnicodeStream(2, null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            pstmt.execute();\n\n            pstmt2 = conn.prepareStatement(\"SELECT * FROM T_PRE_STMT_TEST ORDER BY 2\", ResultSet.TYPE_SCROLL_SENSITIVE,\n                    ResultSet.CONCUR_UPDATABLE);\n            rs = pstmt2.executeQuery();\n            rs.getCursorName();\n            rs.clearWarnings();\n            rs.isBeforeFirst();\n            rs.isAfterLast();\n            rs.isFirst();\n            rs.isLast();\n            rs.setFetchDirection(rs.getFetchDirection());\n            rs.setFetchSize(rs.getFetchSize());\n            rs.getConcurrency();\n            rs.getRow();\n            rs.relative(1);\n            rs.absolute(1);\n\n            rs.next();\n\n            rs.rowDeleted();\n            rs.rowInserted();\n            rs.rowUpdated();\n\n            rs.previous();\n            rs.beforeFirst();\n            rs.afterLast();\n            rs.absolute(1);\n\n            rs.first();\n            rs.last();\n            rs.close();\n\n            pstmt2 = conn.prepareStatement(\"SELECT * FROM T_PRE_STMT_TEST ORDER BY 2\", ResultSet.TYPE_SCROLL_SENSITIVE,\n                    ResultSet.CONCUR_UPDATABLE);\n            rs = pstmt2.executeQuery();\n            rs.first();\n            rs.last();\n            rs.close();\n\n            pstmt2 = conn.prepareStatement(\"SELECT * FROM T_PRE_STMT_TEST ORDER BY 2\", ResultSet.TYPE_SCROLL_SENSITIVE,\n                    ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT);\n            rs = pstmt2.executeQuery();\n            rs.first();\n            rs.last();\n            rs.close();\n\n            pstmt2 = conn.prepareStatement(\"SELECT * FROM T_PRE_STMT_TEST ORDER BY 2\", new int[]{1});\n            rs = pstmt2.executeQuery();\n            JdbcUtils.printResultSet(rs, System.out);\n            rs.close();\n\n            pstmt2 = conn.prepareStatement(\"SELECT * FROM T_PRE_STMT_TEST ORDER BY 2\", new String[]{\"ID\"});\n            rs = pstmt2.executeQuery();\n            JdbcUtils.printResultSet(rs, System.out);\n            rs.close();\n\n            pstmt2 = conn.prepareStatement(\"SELECT * FROM T_PRE_STMT_TEST ORDER BY 2\", new String[]{\"ID\"});\n            rs = pstmt2.executeQuery();\n            try {\n                rs.getArray(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getArray(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getNCharacterStream(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getNCharacterStream(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getNClob(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getNClob(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getNString(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getNString(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getRowId(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getRowId(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getSQLXML(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getSQLXML(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            JdbcUtils.printResultSet(rs, System.out);\n            rs.close();\n\n            pstmt2 = conn.prepareStatement(\"SELECT * FROM T_PRE_STMT_TEST ORDER BY 2\",\n                    ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);\n            rs = pstmt2.executeQuery();\n            rs.next();\n            try {\n                rs.refreshRow();\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.insertRow();\n            } catch (SQLException ex) {\n            }\n            try {\n                rs.moveToCurrentRow();\n            } catch (SQLException ex) {\n            }\n            try {\n                rs.moveToInsertRow();\n            } catch (SQLException ex) {\n            }\n\n            try {\n                rs.getURL(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.getURL(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateArray(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateArray(\"NAME\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateNCharacterStream(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateNCharacterStream(\"NAME\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateNCharacterStream(2, null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateNCharacterStream(\"NAME\", null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateNClob(2, (NClob) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateNClob(\"NAME\", (NClob) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateNClob(2, (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateNClob(\"NAME\", (Reader) null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateNClob(2, (Reader) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateNClob(\"NAME\", (Reader) null, 0);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateNString(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateNString(\"NAME\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.getRef(2);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.getRef(\"NAME\");\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateRef(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateRef(\"NAME\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateRowId(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateRowId(\"NAME\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            try {\n                rs.updateSQLXML(2, null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            try {\n                rs.updateSQLXML(\"NAME\", null);\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n            JdbcUtils.printResultSet(rs, System.out);\n            rs.close();\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(pstmt);\n            JdbcUtils.close(pstmt2);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/ProxyDriverTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ProxyDriverTest {\n    @Test\n    public void test_connect() throws Exception {\n        String url = \"jdbc:wrap-jdbc:filters=default:name=clobTest:jdbc:derby:memory:clobTestDB;create=true\";\n        Connection conn = DriverManager.getConnection(url);\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/ResultSetProxyImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.logging.Log4jFilter;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.mock.MockDriver;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.ResultSetProxy;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.Reader;\nimport java.sql.Connection;\nimport java.sql.NClob;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ResultSetProxyImplTest {\n    String sql = \"SELECT 1\";\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_resultset() throws Exception {\n        MockDriver driver = new MockDriver();\n        DataSourceProxyConfig config = new DataSourceProxyConfig();\n        config.setUrl(\"\");\n        config.setRawUrl(\"jdbc:mock:\");\n        DataSourceProxyImpl dataSource = new DataSourceProxyImpl(driver, config);\n\n        {\n            StatFilter filter = new StatFilter();\n            filter.init(dataSource);\n            config.getFilters().add(filter);\n        }\n        {\n            Log4jFilter filter = new Log4jFilter();\n            filter.init(dataSource);\n            config.getFilters().add(filter);\n        }\n\n        Connection conn = dataSource.connect(null);\n\n        conn.setClientInfo(\"name\", null);\n\n        Statement stmt = conn.createStatement();\n        ResultSetProxy rs = (ResultSetProxy) stmt.executeQuery(sql);\n\n        rs.insertRow();\n        rs.refreshRow();\n        rs.moveToInsertRow();\n        rs.moveToCurrentRow();\n        rs.next();\n\n        rs.updateRef(1, null);\n        rs.updateArray(1, null);\n        rs.updateRowId(1, null);\n        rs.updateNString(1, null);\n        rs.updateNClob(1, (NClob) null);\n        rs.updateNClob(1, (Reader) null);\n        rs.updateNClob(1, (Reader) null, 0);\n        rs.updateSQLXML(1, null);\n        rs.updateNCharacterStream(1, null);\n        rs.updateNCharacterStream(1, null, 0);\n\n        rs.getArray(\"1\");\n        rs.updateRef(\"1\", null);\n        rs.updateArray(\"1\", null);\n        rs.updateRowId(\"1\", null);\n        rs.updateNString(\"1\", null);\n        rs.updateNClob(\"1\", (NClob) null);\n        rs.updateNClob(\"1\", (Reader) null);\n        rs.updateNClob(\"1\", (Reader) null, 0);\n        rs.updateSQLXML(\"1\", null);\n        rs.updateNCharacterStream(\"1\", null);\n        rs.updateNCharacterStream(\"1\", null, 0);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/SchemaReadTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.PrintStream;\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SchemaReadTest {\n    private static String url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=demo:jdbc:derby:classpath:petstore-db\";\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_schema() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(url);\n\n            assertTrue(conn.isReadOnly());\n\n            // just call\n            conn.getHoldability();\n            conn.getTransactionIsolation();\n            conn.getWarnings();\n            conn.getTypeMap();\n            conn.getAutoCommit();\n            conn.getCatalog();\n            conn.getClientInfo();\n            conn.getClientInfo(\"xx\");\n\n            DatabaseMetaData metadata = conn.getMetaData();\n            {\n                ResultSet tableTypes = metadata.getTableTypes();\n                JdbcUtils.printResultSet(tableTypes, System.out);\n                JdbcUtils.close(tableTypes);\n            }\n            {\n                conn.setAutoCommit(false);\n                ResultSet tables = metadata.getTables(null, null, null, null);\n                JdbcUtils.printResultSet(tables, System.out);\n                conn.commit();\n                conn.setAutoCommit(true);\n                JdbcUtils.close(tables);\n            }\n\n            {\n                ResultSet tables = metadata.getTables(null, null, null, null);\n                while (tables.next()) {\n                    String schema = tables.getString(2);\n                    String tableName = tables.getString(3);\n                    String sql = \"SELECT * FROM \" + schema + \".\" + tableName;\n\n                    stmt = conn.createStatement();\n\n                    rs = stmt.executeQuery(sql);\n                    JdbcUtils.printResultSet(rs, System.out);\n\n                    JdbcUtils.close(rs);\n                    assertTrue(rs.isClosed());\n                    JdbcUtils.close(stmt);\n                    assertTrue(stmt.isClosed());\n                }\n                JdbcUtils.close(tables);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n            assertTrue(conn.isClosed());\n        }\n    }\n\n    @Test\n    public void test_schema2() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(url);\n\n            assertTrue(conn.isReadOnly());\n\n            // just call\n            conn.getHoldability();\n            conn.getTransactionIsolation();\n            conn.getWarnings();\n            conn.getTypeMap();\n            conn.getAutoCommit();\n            conn.getCatalog();\n            conn.getClientInfo();\n            conn.getClientInfo(\"xx\");\n            conn.isValid(10);\n\n            DatabaseMetaData metadata = conn.getMetaData();\n            {\n                ResultSet tableTypes = metadata.getTableTypes();\n                printResultSetUseColumnName(tableTypes, System.out);\n                JdbcUtils.close(tableTypes);\n            }\n            {\n                conn.setAutoCommit(false);\n                ResultSet tables = metadata.getTables(null, null, null, null);\n                printResultSetUseColumnName(tables, System.out);\n                conn.commit();\n                conn.setAutoCommit(true);\n                JdbcUtils.close(tables);\n            }\n\n            {\n                ResultSet tables = metadata.getTables(null, null, null, null);\n                while (tables.next()) {\n                    String schema = tables.getString(2);\n                    String tableName = tables.getString(3);\n                    String sql = \"SELECT * FROM \" + schema + \".\" + tableName;\n\n                    stmt = conn.createStatement();\n\n                    rs = stmt.executeQuery(sql);\n                    printResultSetUseColumnName(rs, System.out);\n\n                    JdbcUtils.close(rs);\n                    assertTrue(rs.isClosed());\n                    JdbcUtils.close(stmt);\n                    assertTrue(stmt.isClosed());\n                }\n                JdbcUtils.close(tables);\n            }\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n            assertTrue(conn.isClosed());\n        }\n    }\n\n    public static void printResultSetUseColumnName(ResultSet rs, PrintStream out) throws SQLException {\n        ResultSetMetaData metadata = rs.getMetaData();\n        int columnCount = metadata.getColumnCount();\n        for (int columnIndex = 1; columnIndex <= columnCount; ++columnIndex) {\n            if (columnIndex != 1) {\n                out.print('\\t');\n            }\n            out.print(metadata.getColumnName(columnIndex));\n        }\n\n        out.println();\n\n        while (rs.next()) {\n            for (int columnIndex = 1; columnIndex <= columnCount; ++columnIndex) {\n                if (columnIndex != 1) {\n                    out.print('\\t');\n                }\n\n                String columnName = metadata.getColumnName(columnIndex);\n                int type = metadata.getColumnType(columnIndex);\n\n                if (type == Types.VARCHAR || type == Types.CHAR || type == Types.NVARCHAR || type == Types.NCHAR) {\n                    out.print(rs.getString(columnName));\n                } else if (type == Types.DATE) {\n                    Date date = rs.getDate(columnName);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(date.toString());\n                    }\n                } else if (type == Types.BIT) {\n                    boolean value = rs.getBoolean(columnName);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Boolean.toString(value));\n                    }\n                } else if (type == Types.BOOLEAN) {\n                    boolean value = rs.getBoolean(columnName);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Boolean.toString(value));\n                    }\n                } else if (type == Types.TINYINT) {\n                    byte value = rs.getByte(columnName);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Byte.toString(value));\n                    }\n                } else if (type == Types.SMALLINT) {\n                    short value = rs.getShort(columnName);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Short.toString(value));\n                    }\n                } else if (type == Types.INTEGER) {\n                    int value = rs.getInt(columnName);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Integer.toString(value));\n                    }\n                } else if (type == Types.BIGINT) {\n                    long value = rs.getLong(columnName);\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(Long.toString(value));\n                    }\n                } else if (type == Types.TIMESTAMP) {\n                    out.print(String.valueOf(rs.getTimestamp(columnName)));\n                } else if (type == Types.DECIMAL) {\n                    out.print(String.valueOf(rs.getBigDecimal(columnName)));\n                } else if (type == Types.CLOB) {\n                    out.print(String.valueOf(rs.getString(columnName)));\n                } else if (type == Types.JAVA_OBJECT) {\n                    Object objec = rs.getObject(columnName);\n\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(String.valueOf(objec));\n                    }\n                } else if (type == Types.LONGVARCHAR) {\n                    Object objec = rs.getString(columnName);\n\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(String.valueOf(objec));\n                    }\n                } else {\n                    Object objec = rs.getObject(columnName);\n\n                    if (rs.wasNull()) {\n                        out.print(\"null\");\n                    } else {\n                        out.print(String.valueOf(objec));\n                    }\n                }\n            }\n            out.println();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/SqlStatisticTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SqlStatisticTest {\n    @Test\n    public void test_sql_stat() throws Exception {\n        JdbcSqlStat stat = new JdbcSqlStat(\"SELECT * FROM t_user\");\n        assertEquals(null, stat.getExecuteLastStartTime());\n        assertEquals(null, stat.getExecuteNanoSpanMaxOccurTime());\n        assertEquals(null, stat.getExecuteErrorLastTime());\n\n        stat.error(new Exception());\n        assertNotNull(stat.getExecuteErrorLast());\n        assertNotNull(stat.getExecuteErrorLastTime());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/StatementTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatementTest {\n    private static String create_url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=statementTest:jdbc:derby:memory:statementTest;create=true\";\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        Connection conn = DriverManager.getConnection(create_url);\n\n        createTable();\n\n        conn.close();\n    }\n\n    private void createTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"CREATE TABLE T_PRE_STMT_TEST (ID INTEGER GENERATED BY DEFAULT AS IDENTITY, NAME VARCHAR(50), BIRTHDATE TIMESTAMP)\");\n        stmt.close();\n        conn.close();\n    }\n\n    private void dropTable() throws SQLException {\n        Connection conn = DriverManager.getConnection(create_url);\n        Statement stmt = conn.createStatement();\n        stmt.execute(\"DROP TABLE T_PRE_STMT_TEST\");\n        stmt.close();\n        conn.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dropTable();\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_stmt() throws Exception {\n        Connection conn = null;\n        Statement stmt = null;\n        ResultSet rs = null;\n\n        try {\n            conn = DriverManager.getConnection(create_url);\n\n            stmt = conn.createStatement();\n            stmt.execute(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (1, 'A', NULL)\");\n            stmt.execute(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (11, 'A1', NULL)\",\n                    Statement.NO_GENERATED_KEYS);\n            stmt.execute(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (12, 'A2', NULL)\", new int[]{1});\n            stmt.execute(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (12, 'A3', NULL)\",\n                    new String[]{\"ID\"});\n            stmt.executeUpdate(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (2, 'B', NULL)\");\n            stmt.executeUpdate(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (3, 'C', NULL)\",\n                    Statement.NO_GENERATED_KEYS);\n            stmt.executeUpdate(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (4, 'D', NULL)\",\n                    new int[]{1});\n            stmt.executeUpdate(\"INSERT INTO T_PRE_STMT_TEST (ID, NAME, BIRTHDATE) VALUES (5, 'E', NULL)\",\n                    new String[]{\"ID\"});\n            try {\n                stmt.cancel();\n            } catch (SQLFeatureNotSupportedException ex) {\n            }\n\n            stmt.execute(\"SELECT * FROM T_PRE_STMT_TEST\");\n            assertFalse(stmt.getMoreResults(Statement.CLOSE_CURRENT_RESULT));\n        } finally {\n            JdbcUtils.close(rs);\n            JdbcUtils.close(stmt);\n            JdbcUtils.close(conn);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/StatisticTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcConnectionStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatisticTest {\n    @Test\n    public void test_stat() throws Exception {\n        JdbcConnectionStat stat = new JdbcConnectionStat();\n        assertEquals(null, stat.getConnectLastTime());\n        stat.setActiveCount(1);\n        assertEquals(1, stat.getActiveMax());\n        stat.setActiveCount(2);\n        assertEquals(2, stat.getActiveMax());\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/WrapImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy;\n\nimport com.alibaba.druid.filter.FilterChain;\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl;\nimport com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.DriverManager;\nimport java.sql.Statement;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class WrapImplTest {\n    private static String url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j,encoding,null:name=demo:jdbc:derby:classpath:petstore-db\";\n\n    @Test\n    public void test_clone() throws Exception {\n        Class.forName(\"com.alibaba.druid.proxy.DruidDriver\");\n\n        DruidDriver driver = (DruidDriver) DriverManager.getDriver(url);\n\n        ConnectionProxyImpl connection = (ConnectionProxyImpl) driver.connect(url, new Properties());\n\n        connection.getRawObject();\n\n        FilterChain filterChain = (FilterChain) connection.createChain();\n        filterChain.cloneChain();\n\n        DataSourceProxyImpl dataSource = (DataSourceProxyImpl) connection.getDirectDataSource();\n        dataSource.getId();\n        assertEquals(4, dataSource.getProxyFilters().size());\n        assertEquals(4, dataSource.getFilterClasses().length);\n        assertNotNull(dataSource.getCreatedTime());\n        assertTrue(dataSource.getCreatedTime().getTime() != 0);\n        assertEquals(\"org.apache.derby.jdbc.EmbeddedDriver\", dataSource.getRawDriverClassName());\n\n        assertEquals(url, dataSource.getUrl());\n        assertEquals(\"jdbc:derby:classpath:petstore-db\", dataSource.getRawUrl());\n        assertEquals(10, dataSource.getRawDriverMajorVersion());\n        assertEquals(12, dataSource.getRawDriverMinorVersion());\n\n        Class<?> mysql5ConnectionClass = Utils.loadClass(\"com.mysql.jdbc.Connection\");\n        if (mysql5ConnectionClass != null) {\n            assertFalse(connection.isWrapperFor(mysql5ConnectionClass));\n        }\n        assertTrue(connection.isWrapperFor(ConnectionProxyImpl.class));\n        assertTrue(connection.isWrapperFor(org.apache.derby.impl.jdbc.EmbedConnection.class));\n        assertNotNull(connection.unwrap(ConnectionProxyImpl.class));\n        assertNull(connection.unwrap(null));\n\n        org.apache.derby.impl.jdbc.EmbedConnection derbyConnection = connection.unwrap(org.apache.derby.impl.jdbc.EmbedConnection.class);\n        assertNotNull(derbyConnection);\n\n        Statement statement = connection.createStatement();\n        if (mysql5ConnectionClass != null) {\n            assertFalse(statement.isWrapperFor(Class.forName(\"com.mysql.jdbc.Statement\")));\n        }\n        assertFalse(statement.isWrapperFor(null));\n        assertTrue(statement.isWrapperFor(org.apache.derby.impl.jdbc.EmbedStatement.class));\n\n        org.apache.derby.impl.jdbc.EmbedStatement rayStatement = statement.unwrap(org.apache.derby.impl.jdbc.EmbedStatement.class);\n        assertNotNull(rayStatement);\n        statement.close();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DruidDriver.getProxyDataSources().clear();\n        JdbcStatManager.getInstance().reset();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/fake/DruidDriverTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.fake;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidDriverTest {\n    @Test\n    public void test_0() throws Exception {\n        String url = \"jdbc:wrap-jdbc:filters=default,commonLogging,log4j:name=preCallTest:jdbc:fake:c1\";\n        Properties info = new Properties();\n        DruidDriver driver = new DruidDriver();\n        Connection conn = driver.connect(url, info);\n        assertNotNull(conn);\n        assertEquals(\"c1\", conn.getCatalog());\n\n        conn.setCatalog(\"c2\");\n        assertEquals(\"c2\", conn.getCatalog());\n\n        conn.setTransactionIsolation(100);\n        assertEquals(100, conn.getTransactionIsolation());\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/fake/FakeDriverTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.fake;\n\nimport com.alibaba.druid.mock.MockDriver;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FakeDriverTest {\n    @Test\n    public void test_0() throws Exception {\n        String url = \"jdbc:fake:x1\";\n        Properties info = new Properties();\n\n        String sql = \"SELECT 1\";\n\n        MockDriver driver = new MockDriver();\n\n        Connection conn = driver.connect(url, info);\n        Statement stmt = conn.createStatement();\n\n        ResultSet rs = stmt.executeQuery(sql);\n        assertEquals(true, rs.next());\n        assertEquals(1, rs.getInt(1));\n\n        conn.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/ClobTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.DruidDataSourceStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.*;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ClobTest {\n    protected int dataSourceListSize;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSourceListSize = DruidDataSourceStatManager.getInstance().getDataSourceList().size();\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        assertEquals(dataSourceListSize, DruidDataSourceStatManager.getInstance().getDataSourceList().size());\n    }\n\n    @Test\n    public void test_clob() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n        dataSource.setFilters(\"stat\");\n        dataSource.setUrl(\"jdbc:mock:\");\n\n        Connection conn = dataSource.getConnection();\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(\"SELECT NULL\");\n\n        assertTrue(rs.next());\n\n        {\n            Clob x = rs.getClob(1);\n            assertNull(x);\n        }\n\n        {\n            NClob x = rs.getNClob(1);\n            assertNull(x);\n        }\n\n        {\n            Blob x = rs.getBlob(1);\n            assertNull(x);\n        }\n\n        {\n            SQLXML x = rs.getSQLXML(1);\n            assertNull(x);\n        }\n\n        {\n            String x = rs.getString(1);\n            assertNull(x);\n        }\n\n        assertNull(rs.getRowId(1));\n        assertNull(rs.getBigDecimal(1));\n        assertNull(rs.getObject(1));\n\n        rs.close();\n        stmt.close();\n        conn.close();\n\n        dataSource.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/GlobalStatTest0.java",
    "content": "package com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class GlobalStatTest0 {\n    private DruidDataSource dataSourceA;\n    private DruidDataSource dataSourceB;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSourceA = new DruidDataSource();\n        dataSourceA.setUrl(\"jdbc:mock:xx_A\");\n        dataSourceA.setFilters(\"stat\");\n        dataSourceA.setUseGlobalDataSourceStat(true);\n\n        dataSourceB = new DruidDataSource();\n        dataSourceB.setUrl(\"jdbc:mock:xx_A\");\n        dataSourceB.setFilters(\"stat\");\n        dataSourceB.setUseGlobalDataSourceStat(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSourceA);\n        JdbcUtils.close(dataSourceB);\n\n        JdbcDataSourceStat.setGlobal(null);\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Test\n    public void test_execute() throws Exception {\n        {\n            Connection conn = dataSourceA.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\");\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Empty loop\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSourceB.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\");\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Empty loop\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        assertSame(JdbcDataSourceStat.getGlobal(), dataSourceA.getDataSourceStat());\n        assertSame(JdbcDataSourceStat.getGlobal(), dataSourceB.getDataSourceStat());\n\n        assertEquals(1, JdbcStatManager.getInstance().getSqlList().size());\n        String json = JSONUtils.toJSONString(JdbcStatManager.getInstance().getSqlList());\n        List<Map<String, Object>> sqlList = (List<Map<String, Object>>) JSONUtils.parse(json);\n        Map<String, Object> sqlInfo = sqlList.get(0);\n        assertNotNull(sqlInfo);\n//        assertEquals(JdbcConstants.MOCK, sqlInfo.get(\"DbType\"));\n        assertEquals(2, sqlInfo.get(\"ExecuteCount\"));\n        assertEquals(2, sqlInfo.get(\"FetchRowCount\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/GlobalStatTest1.java",
    "content": "package com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcDataSourceStat;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class GlobalStatTest1 {\n    private DruidDataSource dataSourceA;\n    private DruidDataSource dataSourceB;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSourceA = new DruidDataSource();\n        dataSourceA.setUrl(\"jdbc:mock:xx_A\");\n        dataSourceA.setFilters(\"stat\");\n        dataSourceA.setUseGlobalDataSourceStat(true);\n\n        dataSourceB = new DruidDataSource();\n        dataSourceB.setUrl(\"jdbc:mock:xx_A\");\n        dataSourceB.setFilters(\"stat\");\n        dataSourceB.setUseGlobalDataSourceStat(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSourceA);\n        JdbcUtils.close(dataSourceB);\n\n        JdbcDataSourceStat.setGlobal(null);\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_execute() throws Exception {\n        {\n            Connection conn = dataSourceA.getConnection();\n            Statement stmt = conn.createStatement();\n            ResultSet rs = stmt.executeQuery(\"SELECT 1\");\n            while (rs.next()) {\n                // Empty loop\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSourceB.getConnection();\n            PreparedStatement stmt = conn.prepareStatement(\"SELECT 1\");\n            ResultSet rs = stmt.executeQuery();\n            while (rs.next()) {\n                // Empty loop\n            }\n            rs.close();\n            stmt.close();\n            conn.close();\n        }\n\n        assertSame(JdbcDataSourceStat.getGlobal(), dataSourceA.getDataSourceStat());\n        assertSame(JdbcDataSourceStat.getGlobal(), dataSourceB.getDataSourceStat());\n\n        assertEquals(1, JdbcStatManager.getInstance().getSqlList().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"mergeStat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        for (int i = 0; i < 100; ++i) {\n            String sql = \"select * from t where id = \" + i;\n            Connection conn = dataSource.getConnection();\n\n            Statement stmt = conn.createStatement();\n            stmt.execute(sql);\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"mergeStat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        {\n            String sql = \"select * from t where id = 3 or id = 5 or id = 7\";\n            Connection conn = dataSource.getConnection();\n\n            Statement stmt = conn.createStatement();\n            stmt.execute(sql);\n            stmt.close();\n\n            conn.close();\n        }\n\n        {\n            String sql = \"select * from t where id = 122 or id = 55\";\n            Connection conn = dataSource.getConnection();\n\n            Statement stmt = conn.createStatement();\n            stmt.execute(sql);\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap()\n                .size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStreamReader;\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"mergeStat\");\n        dataSource.setDbType(\"postgresql\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        String sqllist = Utils.read(new InputStreamReader(this.getClass().getResourceAsStream(\"/bvt/parser/postgresql/16.txt\")));\n        String[] ss = sqllist.split(\"--------------------\");\n        for (String sql : ss) {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(sql);\n            stmt.close();\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap()\n                .size());\n        System.out.println(dataSource.getDataSourceStat().getSqlStatMap().keySet().iterator().next());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.openmbean.TabularData;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest_tddl {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        TabularData sqlList = JdbcStatManager.getInstance().getSqlList();\n        if (sqlList.size() > 0) {\n            for (Object item : JdbcStatManager.getInstance().getSqlList().values()) {\n                String text = JSONUtils.toJSONString(item);\n                System.out.println(text);\n            }\n        }\n        JdbcStatManager.getInstance().reset();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setDbType(\"mysql\");\n\n//        {\n//            Connection conn = dataSource.getConnection();\n//            {\n//                Statement stmt = conn.createStatement();\n//                stmt.execute(\"select 1\");\n//            }\n//            conn.close();\n//            System.out.println(conn.getClass().getName());\n//        }\n        dataSource.setFilters(\"mergeStat\");\n\n        Connection conn = dataSource.getConnection();\n        {\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"select 1\");\n            System.out.println(stmt.getClass().getName());\n        }\n        conn.close();\n        System.out.println(conn.getClass().getName());\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        for (int i = 0; i < 100; ++i) {\n            String tableName = \"t_\" + i;\n            String sql = \"select * from \" + tableName + \" where \" + tableName + \".id = \" + i;\n            Connection conn = dataSource.getConnection();\n\n            Statement stmt = conn.createStatement();\n            stmt.execute(sql);\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(2, dataSource.getDataSourceStat().getSqlStatMap().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.openmbean.TabularData;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest_tddl_1 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        TabularData sqlList = JdbcStatManager.getInstance().getSqlList();\n        if (sqlList.size() > 0) {\n            for (Object item : JdbcStatManager.getInstance().getSqlList().values()) {\n                String text = JSONUtils.toJSONString(item);\n                System.out.println(text);\n            }\n        }\n        JdbcStatManager.getInstance().reset();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"mergeStat\");\n        dataSource.setDbType(\"mysql\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        for (int i = 1000; i < 2000; ++i) {\n            String tableName = \"t\" + i;\n            String sql = \"select * from \" + tableName + \" where \" + tableName + \".id = \" + i;\n            Connection conn = dataSource.getConnection();\n\n            Statement stmt = conn.createStatement();\n            stmt.execute(sql);\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.openmbean.TabularData;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest_tddl_2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        TabularData sqlList = JdbcStatManager.getInstance().getSqlList();\n        if (sqlList.size() > 0) {\n            for (Object item : JdbcStatManager.getInstance().getSqlList().values()) {\n                String text = JSONUtils.toJSONString(item);\n                System.out.println(text);\n            }\n        }\n        JdbcStatManager.getInstance().reset();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"mergeStat\");\n        dataSource.setDbType(\"mysql\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        for (int i = 1000; i < 2000; ++i) {\n            String tableName = \"t\" + i;\n            String sql = \"insert into \" + tableName + \" (fid, fname) values (?, ?)\";\n            Connection conn = dataSource.getConnection();\n\n            Statement stmt = conn.createStatement();\n            stmt.execute(sql);\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest_tddl_3 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"mergeStat\");\n        dataSource.setDbType(\"mysql\");\n        dataSource.setConnectionProperties(\"druid.useGloalDataSourceStat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        for (int i = 1000; i < 2000; ++i) {\n            String tableName = \"t_\" + i;\n\n            Connection conn = dataSource.getConnection();\n\n            String sql = \"update \" + tableName + \" SET a = ? WHERE b = ?\";\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.setString(1, \"aaa\");\n            stmt.setInt(1, 2);\n            stmt.execute();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.openmbean.TabularData;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MergeStatFilterTest_tddl_4 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        TabularData sqlList = JdbcStatManager.getInstance().getSqlList();\n        if (sqlList.size() > 0) {\n            for (Object item : JdbcStatManager.getInstance().getSqlList().values()) {\n                String text = JSONUtils.toJSONString(item);\n                System.out.println(text);\n            }\n        }\n        JdbcStatManager.getInstance().reset();\n\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xx\");\n        dataSource.setFilters(\"mergeStat\");\n        dataSource.setDbType(\"mysql\");\n        dataSource.setConnectionProperties(\"druid.useGloalDataSourceStat\");\n        dataSource.setPoolPreparedStatements(true);\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        JdbcUtils.close(dataSource);\n        JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        for (int i = 1000; i < 2000; ++i) {\n            String tableName = \"t_\" + i;\n\n            Connection conn = dataSource.getConnection();\n\n            String sql = \"update \" + tableName + \" SET a = ? WHERE b = ?\";\n            PreparedStatement stmt = conn.prepareStatement(sql);\n            stmt.setString(1, \"aaa\");\n            stmt.setInt(1, 2);\n            stmt.execute();\n            stmt.close();\n\n            conn.close();\n        }\n\n        assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterConcurrentTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcSqlStat;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\nimport java.util.concurrent.CountDownLatch;\n\npublic class StatFilterConcurrentTest {\n    private DruidDataSource dataSource;\n    private StatFilter statFilter;\n    private int LOOP_COUNT = 1000 * 1;\n\n    @BeforeEach\n    public void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:xxx\");\n        dataSource.setMaxActive(100);\n\n        statFilter = new StatFilter();\n        dataSource.getProxyFilters().add(statFilter);\n        dataSource.setConnectionProperties(\"executeSleep=1\");\n    }\n\n    @AfterEach\n    public void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        concurrent(100);\n        for (JdbcSqlStat sqlStat : dataSource.getDataSourceStat().getSqlStatMap().values()) {\n            System.out.println(sqlStat.getConcurrentMax());\n        }\n    }\n\n    public void concurrent(int threadCount) throws Exception {\n        Thread[] threads = new Thread[threadCount];\n        final CountDownLatch endLatch = new CountDownLatch(threadCount);\n\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i] = new Thread() {\n                public void run() {\n                    try {\n                        for (int i = 0; i < LOOP_COUNT; ++i) {\n                            Connection conn = dataSource.getConnection();\n                            Statement stmt = conn.createStatement();\n                            stmt.executeUpdate(\"select 1\");\n                            stmt.close();\n                            conn.close();\n                        }\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                    } finally {\n                        endLatch.countDown();\n                    }\n                }\n            };\n        }\n\n        for (int i = 0; i < threadCount; ++i) {\n            threads[i].start();\n        }\n        endLatch.await();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.proxy.DruidDriver;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport com.alibaba.druid.support.json.JSONUtils;\nimport org.junit.jupiter.api.Test;\n\nimport javax.management.openmbean.CompositeData;\nimport javax.management.openmbean.TabularData;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.ResultSet;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterTest {\n    public void setUp() throws Exception {\n        JdbcStatManager.getInstance().reset();\n    }\n\n    public void tearDown() throws Exception {\n         JdbcStatManager.getInstance().reset();\n        DruidDriver.getProxyDataSources().clear();\n         JdbcStatManager.getInstance().reset();\n    }\n\n    @Test\n    public void test_stat() throws Exception {\n        String url = \"jdbc:wrap-jdbc:filters=default:jdbc:mock:xx\";\n        Connection conn = DriverManager.getConnection(url);\n\n        Statement stmt = conn.createStatement();\n        ResultSet rs = stmt.executeQuery(\"SELECT 1\");\n        while (rs.next()) {\n            rs.getInt(1);\n        }\n        rs.close();\n        stmt.close();\n\n        conn.close();\n\n        TabularData sqlList = JdbcStatManager.getInstance().getSqlList();\n        assertEquals(true, sqlList.size() > 0);\n\n        int count = 0;\n        for (Object item : sqlList.values()) {\n            CompositeData row = (CompositeData) item;\n            if (url.equals((String) row.get(\"URL\"))) {\n                count++;\n            }\n            long[] histogram = (long[]) row.get(\"Histogram\");\n            assertEquals(0L, histogram[histogram.length - 1]);\n        }\n        assertEquals(true, count > 0);\n\n        System.out.println(JSONUtils.toJSONString(sqlList));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.stat.JdbcStatContext;\nimport com.alibaba.druid.stat.JdbcStatManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\n\npublic class StatFilterTest2 {\n    private DruidDataSource dataSource;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        dataSource = new DruidDataSource();\n        dataSource.setUrl(\"jdbc:mock:\");\n        dataSource.setFilters(\"stat\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        dataSource.close();\n    }\n\n    @Test\n    public void test_0() throws Exception {\n        Connection conn = dataSource.getConnection();\n\n        Statement stmt = conn.createStatement();\n\n        setStatSql(\"Select ?\");\n        stmt.execute(\"select 1\");\n\n        stmt.close();\n\n        conn.close();\n    }\n\n    public static final void setStatSql(String val) {\n        JdbcStatContext context = JdbcStatManager.getInstance().getStatContext();\n        if (context == null) {\n            context = JdbcStatManager.getInstance().createStatContext();\n            JdbcStatManager.getInstance().setStatContext(context);\n        }\n\n        context.setSql(val);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/StatFilterTest3.java",
    "content": "package com.alibaba.druid.bvt.proxy.filter;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StatFilterTest3 {\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_dbType() throws Exception {\n        StatFilter filter = new StatFilter();\n\n        assertFalse(filter.isMergeSql());\n\n        filter.setDbType(\"mysql\");\n        filter.setMergeSql(true);\n\n        assertTrue(filter.isMergeSql());\n        assertEquals(DbType.mysql, filter.getDbType());\n\n        assertEquals(\"SELECT ?\\nLIMIT ?\", filter.mergeSql(\"select 'x' limit 1\"));\n    }\n\n    @Test\n    public void test_dbType_error() throws Exception {\n        StatFilter filter = new StatFilter();\n        filter.setDbType(\"mysql\");\n        filter.setMergeSql(true);\n\n        assertEquals(DbType.mysql, filter.getDbType());\n\n        assertEquals(\"sdafawer asf \", filter.mergeSql(\"sdafawer asf \"));\n    }\n\n    @Test\n    public void test_merge() throws Exception {\n        StatFilter filter = new StatFilter();\n        filter.setDbType(\"mysql\");\n        filter.setMergeSql(false);\n\n        assertEquals(DbType.mysql, filter.getDbType());\n\n        assertEquals(\"select 'x' limit 1\", filter.mergeSql(\"select 'x' limit 1\"));\n    }\n\n    @Test\n    public void test_merge_pg() throws Exception {\n        StatFilter filter = new StatFilter();\n        filter.setDbType(JdbcConstants.POSTGRESQL);\n        filter.setMergeSql(true);\n\n        assertEquals(JdbcConstants.POSTGRESQL, filter.getDbType());\n\n        assertEquals(\"DROP TABLE IF EXISTS test_site_data_select_111;\\n\" +\n                \"CREATE TABLE test_site_data_select_111\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM postman_trace_info_one\\n\" +\n                \"WHERE lng > ?\\n\" +\n                \"\\tAND lat > ?\\n\" +\n                \"\\tAND site_id = ?;\", filter.mergeSql(\"drop table if exists test_site_data_select_111; create table test_site_data_select_111 AS select * from postman_trace_info_one  where lng>0 and lat>0  and site_id='17814' ;\", JdbcConstants.POSTGRESQL));\n    }\n\n    @Test\n    public void test_merge_oracle() throws Exception {\n        StatFilter filter = new StatFilter();\n        filter.setDbType(DbType.oceanbase_oracle);\n        filter.setMergeSql(true);\n\n        filter.mergeSql(\"insert into t(f1, f2) values (1, 2)\", DbType.oceanbase_oracle);\n    }\n\n    @Test\n    public void test_merge_nodbtype() throws Exception {\n        StatFilter filter = new StatFilter();\n\n        assertFalse(filter.isMergeSql());\n\n        filter.setMergeSql(true);\n\n        assertTrue(filter.isMergeSql());\n        assertNull(filter.getDbType());\n\n        assertEquals(\"SELECT *\\n\" +\n                        \"FROM temp.test\\n\" +\n                        \"ORDER BY id DESC\\n\" +\n                        \"LIMIT ?\",\n                filter.mergeSql(\"select * from temp.test order by id desc limit 1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/encoding/CharsetConvertTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter.encoding;\n\nimport com.alibaba.druid.filter.encoding.CharsetConvert;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.UnsupportedEncodingException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author gang.su\n */\npublic class CharsetConvertTest {\n    private static final String CLIENT_ENCODEING = \"gbk\";\n    private static final String SERVER_ENCODEING = \"utf-8\";\n    public CharsetConvert charsetConvert = new CharsetConvert(CLIENT_ENCODEING, SERVER_ENCODEING);\n\n    @Test\n    public void testIsEmpty() {\n        assertTrue(charsetConvert.isEmpty(null));\n        assertTrue(charsetConvert.isEmpty(\"\"));\n        assertTrue(!charsetConvert.isEmpty(\"a\"));\n    }\n\n    @Test\n    public void testEncoding() {\n        String s = \"你好\";\n        String es = \"\";\n        String ds = \"\";\n        try {\n            es = new String(s.getBytes(CLIENT_ENCODEING), SERVER_ENCODEING);\n            ds = new String(s.getBytes(SERVER_ENCODEING), CLIENT_ENCODEING);\n\n            assertEquals(es, charsetConvert.encode(s));\n            assertEquals(ds, charsetConvert.decode(s));\n        } catch (UnsupportedEncodingException e) {\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/filter/encoding/CharsetParameterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.filter.encoding;\n\nimport com.alibaba.druid.filter.encoding.CharsetParameter;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author gang.su\n */\n@Deprecated\npublic class CharsetParameterTest {\n    @Test\n    public void testQ() {\n        CharsetParameter c = new CharsetParameter();\n        c.setClientEncoding(\"1\");\n        c.setServerEncoding(\"2\");\n        assertEquals(\"1\", c.getClientEncoding());\n        assertEquals(\"2\", c.getServerEncoding());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/proxy/utils/DruidLoaderUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.proxy.utils;\n\nimport com.alibaba.druid.bvt.proxy.DruidDriverTest.PublicJdbcFilterAdapter;\nimport com.alibaba.druid.filter.Filter;\nimport com.alibaba.druid.filter.FilterManager;\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * druidLoader util 测试\n *\n * @author gang.su\n */\npublic class DruidLoaderUtilsTest {\n    @Test\n    public void testLoadFilter() throws SQLException {\n        List<Filter> filters = new ArrayList<Filter>();\n        // log4j\n        String filterItem = \"log4j\";\n        FilterManager.loadFilter(filters, filterItem);\n        Filter filterConfig = filters.get(0);\n        assertNotNull(filterConfig);\n        assertEquals(\"com.alibaba.druid.filter.logging.Log4jFilter\", filterConfig.getClass().getName());\n        // stat\n        filterItem = \"stat\";\n        filters.clear();\n        FilterManager.loadFilter(filters, filterItem);\n        filterConfig = filters.get(0);\n        assertNotNull(filterConfig);\n        assertEquals(\"com.alibaba.druid.filter.stat.StatFilter\", filterConfig.getClass().getName());\n        // default\n        filterItem = \"default\";\n        filters.clear();\n        FilterManager.loadFilter(filters, filterItem);\n        filterConfig = filters.get(0);\n        assertNotNull(filterConfig);\n        assertEquals(\"com.alibaba.druid.filter.stat.StatFilter\", filterConfig.getClass().getName());\n        // counter\n        filterItem = \"stat\";\n        filters.clear();\n        FilterManager.loadFilter(filters, filterItem);\n        filterConfig = filters.get(0);\n        assertNotNull(filterConfig);\n        assertEquals(\"com.alibaba.druid.filter.stat.StatFilter\", filterConfig.getClass().getName());\n        // commonLogging\n        filterItem = \"commonLogging\";\n        filters.clear();\n        FilterManager.loadFilter(filters, filterItem);\n        filterConfig = filters.get(0);\n        assertNotNull(filterConfig);\n        assertEquals(\"com.alibaba.druid.filter.logging.CommonsLogFilter\", filterConfig.getClass().getName());\n        // encoding\n        filterItem = \"encoding\";\n        filters.clear();\n        FilterManager.loadFilter(filters, filterItem);\n        filterConfig = filters.get(0);\n        assertNotNull(filterConfig);\n        assertEquals(\"com.alibaba.druid.filter.encoding.EncodingConvertFilter\",\n                filterConfig.getClass().getName());\n        // 判定重复\n        filterItem = \"stat\";\n        filters.clear();\n        FilterManager.loadFilter(filters, filterItem);\n        filterItem = \"default\";\n        FilterManager.loadFilter(filters, filterItem);\n        for (Iterator<Filter> iterator = filters.iterator(); iterator.hasNext(); ) {\n            Filter filter = (Filter) iterator.next();\n            System.out.println(filter.getClass().getName());\n        }\n        // default\n    }\n\n    public void twest_loadClass() throws Exception {\n        assertEquals(null, Utils.loadClass(null));\n        assertEquals(null, Utils.loadClass(\"xxx\"));\n        assertEquals(PublicJdbcFilterAdapter.class,\n                Utils.loadClass(PublicJdbcFilterAdapter.class.getName()));\n        assertNull(Utils.loadClass(null));\n        assertNull(Utils.loadClass(\"\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/spring/DruidJdbcExtractorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.spring;\n\nimport com.alibaba.druid.mock.MockCallableStatement;\nimport com.alibaba.druid.mock.MockConnection;\nimport com.alibaba.druid.mock.MockPreparedStatement;\nimport com.alibaba.druid.mock.MockStatement;\nimport com.alibaba.druid.pool.DruidDataSource;\nimport com.alibaba.druid.support.spring.DruidNativeJdbcExtractor;\nimport org.junit.jupiter.api.Test;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.Statement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DruidJdbcExtractorTest {\n    @Test\n    public void test_spring() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        try {\n            DruidNativeJdbcExtractor extractor = new DruidNativeJdbcExtractor();\n\n            dataSource.setUrl(\"jdbc:mock:xx1\");\n            Connection conn = dataSource.getConnection();\n            assertEquals(true, extractor.getNativeConnection(conn) instanceof MockConnection);\n\n            Statement stmt = conn.createStatement();\n            assertEquals(true, extractor.getNativeConnectionFromStatement(stmt) instanceof MockConnection);\n            assertEquals(true, extractor.getNativeStatement(stmt) instanceof MockStatement);\n\n            stmt.close();\n\n            PreparedStatement preStmt = conn.prepareStatement(\"select 1\");\n            assertEquals(true, extractor.getNativeConnectionFromStatement(preStmt) instanceof MockConnection);\n            assertEquals(true, extractor.getNativeStatement(preStmt) instanceof MockPreparedStatement);\n            assertEquals(true, extractor.getNativePreparedStatement(preStmt) instanceof MockPreparedStatement);\n            preStmt.close();\n\n            PreparedStatement callStmt = conn.prepareCall(\"select 1\");\n            assertEquals(true, extractor.getNativeConnectionFromStatement(callStmt) instanceof MockConnection);\n            assertEquals(true, extractor.getNativeStatement(callStmt) instanceof MockCallableStatement);\n            assertEquals(true, extractor.getNativePreparedStatement(callStmt) instanceof MockCallableStatement);\n            callStmt.close();\n\n            conn.close();\n        } finally {\n            dataSource.close();\n        }\n    }\n\n    @Test\n    public void test_spring_filter() throws Exception {\n        DruidDataSource dataSource = new DruidDataSource();\n\n        try {\n            DruidNativeJdbcExtractor extractor = new DruidNativeJdbcExtractor();\n\n            dataSource.setUrl(\"jdbc:mock:xx1\");\n            dataSource.setFilters(\"stat\");\n            Connection conn = dataSource.getConnection();\n            assertEquals(true, extractor.getNativeConnection(conn) instanceof MockConnection);\n\n            Statement stmt = conn.createStatement();\n            assertEquals(true, extractor.getNativeConnectionFromStatement(stmt) instanceof MockConnection);\n            assertEquals(true, extractor.getNativeStatement(stmt) instanceof MockStatement);\n\n            stmt.close();\n\n            PreparedStatement preStmt = conn.prepareStatement(\"select 1\");\n            assertEquals(true, extractor.getNativeConnectionFromStatement(preStmt) instanceof MockConnection);\n            assertEquals(true, extractor.getNativeStatement(preStmt) instanceof MockPreparedStatement);\n            assertEquals(true, extractor.getNativePreparedStatement(preStmt) instanceof MockPreparedStatement);\n            preStmt.close();\n\n            PreparedStatement callStmt = conn.prepareCall(\"select 1\");\n            assertEquals(true, extractor.getNativeConnectionFromStatement(callStmt) instanceof MockConnection);\n            assertEquals(true, extractor.getNativeStatement(callStmt) instanceof MockCallableStatement);\n            assertEquals(true, extractor.getNativePreparedStatement(callStmt) instanceof MockCallableStatement);\n            callStmt.close();\n\n            conn.close();\n        } finally {\n            dataSource.close();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/spring/SpringMethodInfoTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.spring;\n\nimport com.alibaba.druid.support.spring.stat.SpringMethodInfo;\nimport com.alibaba.druid.support.spring.stat.SpringMethodStat;\nimport com.alibaba.druid.support.spring.stat.SpringStat;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SpringMethodInfoTest {\n    @Test\n    public void test_equals() throws Exception {\n        SpringMethodInfo b1 = new SpringMethodInfo(B.class, B.class.getMethod(\"f\", int.class));\n        SpringMethodInfo c = new SpringMethodInfo(C.class, C.class.getMethod(\"f\", int.class));\n        SpringMethodInfo b2 = new SpringMethodInfo(B.class, B.class.getMethod(\"f\", int.class));\n\n        assertFalse(b1.equals(c));\n        assertTrue(b1.equals(b1));\n        assertTrue(b1.equals(b2));\n\n        assertEquals(B.class.getName(), b1.getClassName());\n        assertEquals(C.class.getName(), c.getClassName());\n    }\n\n    @Test\n    public void test_get() throws Exception {\n        SpringStat springStat = new SpringStat();\n\n        SpringMethodInfo b1 = new SpringMethodInfo(B.class, B.class.getMethod(\"f\", int.class));\n        SpringMethodInfo b2 = new SpringMethodInfo(B.class, B.class.getMethod(\"f\", int.class));\n\n        SpringMethodStat methodStat1 = springStat.getMethodStat(b1, true);\n        SpringMethodStat methodStat2 = springStat.getMethodStat(b2, true);\n        assertSame(methodStat1, methodStat2);\n    }\n\n    public static class A {\n        public void f(int i) {\n        }\n    }\n\n    public static class B extends A {\n    }\n\n    public static class C extends A {\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/spring/SqlMapClientWrapperTest.java",
    "content": "package com.alibaba.druid.bvt.spring;\n\nimport com.alibaba.druid.spring.User;\nimport com.alibaba.druid.support.ibatis.SqlMapClientWrapper;\nimport com.ibatis.sqlmap.client.event.RowHandler;\nimport com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SqlMapClientWrapperTest {\n    private ClassPathXmlApplicationContext context;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        context = new ClassPathXmlApplicationContext(\"com/alibaba/druid/pool/ibatis/spring-config-ibatis-1.xml\");\n        DataSource dataSource = (DataSource) context.getBean(\"dataSource\");\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE sequence_seed (value INTEGER, name VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE t_User (id BIGINT, name VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DataSource dataSource = (DataSource) context.getBean(\"dataSource\");\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE sequence_seed\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE t_User\");\n            stmt.close();\n            conn.close();\n        }\n        context.close();\n    }\n\n    @Test\n    public void test_wrap() throws Exception {\n        SqlMapClientImpl client = (SqlMapClientImpl) context.getBean(\"master-sqlMapClient\");\n        assertNotNull(client);\n\n        SqlMapClientWrapper wrapper = new SqlMapClientWrapper(client);\n\n        wrapper.insert(\"User.insert\", new User(12345678, \"aaa\"));\n        {\n            Exception error = null;\n            try {\n                wrapper.insert(\"User.insert\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        wrapper.update(\"User.update\", new User(12345678, \"bbb\"));\n        {\n            Exception error = null;\n            try {\n                wrapper.update(\"User.update\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        assertNotNull((User) wrapper.queryForObject(\"User.select\"));\n        assertNotNull((User) wrapper.queryForObject(\"User.select\", Collections.emptyMap()));\n        assertNotNull((User) wrapper.queryForObject(\"User.select\", Collections.emptyMap(), new User()));\n\n        assertEquals(1, wrapper.queryForList(\"User.select\").size());\n        assertEquals(1, wrapper.queryForList(\"User.select\", Collections.emptyMap()).size());\n        assertEquals(1, wrapper.queryForList(\"User.select\", Collections.emptyMap(), 0, 2).size());\n\n        wrapper.queryWithRowHandler(\"User.select\", new RowHandler() {\n            @Override\n            public void handleRow(Object valueObject) {\n            }\n        });\n        wrapper.queryWithRowHandler(\"User.select\", Collections.emptyMap(), new RowHandler() {\n            @Override\n            public void handleRow(Object valueObject) {\n            }\n        });\n\n        assertEquals(1, wrapper.queryForPaginatedList(\"User.select\", 10).size());\n        assertEquals(1, wrapper.queryForPaginatedList(\"User.select\", Collections.emptyMap(), 10).size());\n\n        assertNotNull(wrapper.queryForMap(\"User.select\", Collections.emptyMap(), \"id\"));\n        assertNotNull(wrapper.queryForMap(\"User.select\", Collections.emptyMap(), \"id\", \"name\"));\n\n        wrapper.delete(\"User.delete\", 12345678L);\n        {\n            Exception error = null;\n            try {\n                wrapper.delete(\"User.delete\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        wrapper.startBatch();\n        wrapper.executeBatch();\n        wrapper.executeBatchDetailed();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/spring/SqlMapExecutorWrapperTest.java",
    "content": "package com.alibaba.druid.bvt.spring;\n\nimport com.alibaba.druid.support.ibatis.SqlMapClientWrapper;\nimport com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\nimport java.sql.Connection;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SqlMapExecutorWrapperTest {\n    private ClassPathXmlApplicationContext context;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        context = new ClassPathXmlApplicationContext(\"com/alibaba/druid/pool/ibatis/spring-config-ibatis.xml\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        context.close();\n    }\n\n    @Test\n    public void test_wrap() throws Exception {\n        SqlMapClientImpl client = (SqlMapClientImpl) context.getBean(\"master-sqlMapClient\");\n        assertNotNull(client);\n\n        SqlMapClientWrapper wrapper = new SqlMapClientWrapper(client);\n        wrapper.getClient();\n        wrapper.startTransaction();\n        wrapper.endTransaction();\n        wrapper.startTransaction(Connection.TRANSACTION_NONE);\n        wrapper.endTransaction();\n        wrapper.setUserConnection(wrapper.getUserConnection());\n        wrapper.getCurrentConnection();\n        wrapper.getDataSource();\n        wrapper.openSession().close();\n        wrapper.openSession(wrapper.getCurrentConnection()).close();\n        wrapper.getSession();\n        wrapper.flushDataCache();\n        Exception error = null;\n        try {\n            wrapper.flushDataCache(null);\n        } catch (Exception ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        wrapper.startTransaction();\n        wrapper.commitTransaction();\n\n        wrapper.getMappedStatement(\"Sequence.getValue\");\n\n        wrapper.isEnhancementEnabled();\n        wrapper.isLazyLoadingEnabled();\n\n        wrapper.getSqlExecutor();\n\n        wrapper.getDelegate();\n\n        wrapper.getResultObjectFactory();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/spring/SqlMapExecutorWrapperTest_2.java",
    "content": "package com.alibaba.druid.bvt.spring;\n\nimport com.alibaba.druid.spring.User;\nimport com.alibaba.druid.support.ibatis.SqlMapExecutorWrapper;\nimport com.ibatis.sqlmap.client.event.RowHandler;\nimport com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\nimport javax.sql.DataSource;\n\nimport java.sql.Connection;\nimport java.sql.Statement;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SqlMapExecutorWrapperTest_2 {\n    private ClassPathXmlApplicationContext context;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        context = new ClassPathXmlApplicationContext(\"com/alibaba/druid/pool/ibatis/spring-config-ibatis.xml\");\n        DataSource dataSource = (DataSource) context.getBean(\"dataSource\");\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE sequence_seed (value INTEGER, name VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"CREATE TABLE t_User (id BIGINT, name VARCHAR(50))\");\n            stmt.close();\n            conn.close();\n        }\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        DataSource dataSource = (DataSource) context.getBean(\"dataSource\");\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE sequence_seed\");\n            stmt.close();\n            conn.close();\n        }\n        {\n            Connection conn = dataSource.getConnection();\n            Statement stmt = conn.createStatement();\n            stmt.execute(\"DROP TABLE t_User\");\n            stmt.close();\n            conn.close();\n        }\n        context.close();\n    }\n\n    @Test\n    public void test_wrap() throws Exception {\n        SqlMapClientImpl client = (SqlMapClientImpl) context.getBean(\"master-sqlMapClient\");\n        assertNotNull(client);\n\n        SqlMapExecutorWrapper wrapper = new SqlMapExecutorWrapper(client, client);\n\n        wrapper.insert(\"User.insert\", new User(12345678, \"aaa\"));\n        {\n            Exception error = null;\n            try {\n                wrapper.insert(\"User.insert\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n        wrapper.update(\"User.update\", new User(12345678, \"bbb\"));\n        {\n            Exception error = null;\n            try {\n                wrapper.update(\"User.update\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        assertNotNull((User) wrapper.queryForObject(\"User.select\"));\n        assertNotNull((User) wrapper.queryForObject(\"User.select\", Collections.emptyMap()));\n        assertNotNull((User) wrapper.queryForObject(\"User.select\", Collections.emptyMap(), new User()));\n\n        assertEquals(1, wrapper.queryForList(\"User.select\").size());\n        assertEquals(1, wrapper.queryForList(\"User.select\", Collections.emptyMap()).size());\n        assertEquals(1, wrapper.queryForList(\"User.select\", Collections.emptyMap(), 0, 2).size());\n\n        wrapper.queryWithRowHandler(\"User.select\", new RowHandler() {\n            @Override\n            public void handleRow(Object valueObject) {\n            }\n        });\n        wrapper.queryWithRowHandler(\"User.select\", Collections.emptyMap(), new RowHandler() {\n            @Override\n            public void handleRow(Object valueObject) {\n            }\n        });\n\n        assertEquals(1, wrapper.queryForPaginatedList(\"User.select\", 10).size());\n        assertEquals(1, wrapper.queryForPaginatedList(\"User.select\", Collections.emptyMap(), 10).size());\n\n        assertNotNull(wrapper.queryForMap(\"User.select\", Collections.emptyMap(), \"id\"));\n        assertNotNull(wrapper.queryForMap(\"User.select\", Collections.emptyMap(), \"id\", \"name\"));\n\n        wrapper.delete(\"User.delete\", 12345678L);\n        {\n            Exception error = null;\n            try {\n                wrapper.delete(\"User.delete\");\n            } catch (Exception ex) {\n                error = ex;\n            }\n            assertNotNull(error);\n        }\n\n        wrapper.startBatch();\n        wrapper.executeBatch();\n        wrapper.executeBatchDetailed();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/spring/SqlMapSessionWrapperTest.java",
    "content": "package com.alibaba.druid.bvt.spring;\n\nimport com.alibaba.druid.support.ibatis.SqlMapSessionWrapper;\nimport com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;\nimport com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SqlMapSessionWrapperTest {\n    private ClassPathXmlApplicationContext context;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        context = new ClassPathXmlApplicationContext(\"com/alibaba/druid/pool/ibatis/spring-config-ibatis.xml\");\n    }\n\n    @AfterEach\n    protected void tearDown() throws Exception {\n        context.close();\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Test\n    public void test_wrap() throws Exception {\n        SqlMapClientImpl client = (SqlMapClientImpl) context.getBean(\"master-sqlMapClient\");\n        assertNotNull(client);\n\n        SqlMapSessionImpl session = new SqlMapSessionImpl(client);\n        SqlMapSessionWrapper wrapper = new SqlMapSessionWrapper(client, session);\n\n        wrapper.startTransaction();\n        wrapper.commitTransaction();\n        wrapper.getDataSource();\n        wrapper.getCurrentConnection();\n        wrapper.getUserConnection();\n        wrapper.close();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/BigOrTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class BigOrTest {\n    @Test\n    public void testBigOr() throws Exception {\n        StringBuilder buf = new StringBuilder();\n        buf.append(\"SELECT * FROM T WHERE FID = ?\");\n        for (int i = 0; i < 10000; ++i) {\n            buf.append(\" OR FID = \" + i);\n        }\n        String sql = buf.toString();\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, (DbType) null);\n        String text = SQLUtils.toSQLString(stmtList.get(0));\n        //System.out.println(text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/CompatibleTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CompatibleTest {\n    @Test\n    public void test_for_issue_3986() throws Exception {\n        String sql = \"select 1 from dual;\";\n\n        List<SQLStatement> stmts = SQLUtils.parseStatements(sql, \"mysql\");\n        assertEquals(1, stmts.size());\n        assertEquals(\"select 1\\n\" +\n                \"from dual;\", stmts.get(0).toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/CreateCompareTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 18/07/2017.\n */\npublic class CreateCompareTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"create table t7 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id) REFERENCES t6 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t2 (\\n\" +\n                \"\\tint bigint\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t9 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id) REFERENCES t8 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t6 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id) REFERENCES t5 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t8 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id) REFERENCES t7 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t4 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id) REFERENCES t2 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t5 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id) REFERENCES t4 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t3 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id) REFERENCES t2 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t0 (\\n\" +\n                \"\\tint bigint\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"create table t1 (\\n\" +\n                \"\\tint bigint\\n\" +\n                \");\";\n\n        List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);\n\n        SQLCreateTableStatement.sort(stmtList);\n\n        assertEquals(\"t9\", ((SQLCreateTableStatement) stmtList.get(9)).getName().getSimpleName());\n        assertEquals(\"t3\", ((SQLCreateTableStatement) stmtList.get(8)).getName().getSimpleName());\n        assertEquals(\"t0\", ((SQLCreateTableStatement) stmtList.get(7)).getName().getSimpleName());\n        assertEquals(\"t1\", ((SQLCreateTableStatement) stmtList.get(6)).getName().getSimpleName());\n        assertEquals(\"t8\", ((SQLCreateTableStatement) stmtList.get(5)).getName().getSimpleName());\n        assertEquals(\"t7\", ((SQLCreateTableStatement) stmtList.get(4)).getName().getSimpleName());\n        assertEquals(\"t6\", ((SQLCreateTableStatement) stmtList.get(3)).getName().getSimpleName());\n        assertEquals(\"t5\", ((SQLCreateTableStatement) stmtList.get(2)).getName().getSimpleName());\n        assertEquals(\"t4\", ((SQLCreateTableStatement) stmtList.get(1)).getName().getSimpleName());\n        assertEquals(\"t2\", ((SQLCreateTableStatement) stmtList.get(0)).getName().getSimpleName());\n\n        String sortedSql = SQLUtils.toSQLString(stmtList, JdbcConstants.ORACLE);\n        System.out.println(sortedSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/CreateCompareTest_1.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 18/07/2017.\n */\npublic class CreateCompareTest_1 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE XT_DJ_XT (\\n\" +\n                \"\\tXTBH varchar(20) NOT NULL,\\n\" +\n                \"\\tXTDM varchar(20) NOT NULL,\\n\" +\n                \"\\tXTMC varchar(200) NOT NULL,\\n\" +\n                \"\\tXTBB varchar(20),\\n\" +\n                \"\\tKQSJ datetime NOT NULL,\\n\" +\n                \"\\tYXSJQ datetime NOT NULL,\\n\" +\n                \"\\tYXSJZ datetime,\\n\" +\n                \"\\tYXBZ char(1),\\n\" +\n                \"\\tXTMS varchar(200),\\n\" +\n                \"\\tCONSTRAINT PK_XT_DJ_XT PRIMARY KEY (XTBH)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE XT_DM_GN (\\n\" +\n                \"\\tGNDM varchar(20) NOT NULL,\\n\" +\n                \"\\tGNQQH varchar(20) NOT NULL,\\n\" +\n                \"\\tGNMC varchar(200) NOT NULL,\\n\" +\n                \"\\tSJGNDM varchar(20),\\n\" +\n                \"\\tCDBZ char(1),\\n\" +\n                \"\\tPLXH bigint,\\n\" +\n                \"\\tLJDZ varchar(200),\\n\" +\n                \"\\tYXBZ char(1),\\n\" +\n                \"\\tGNMS varchar(200),\\n\" +\n                \"\\tDYZB varchar(20),\\n\" +\n                \"\\tCDTB varchar(100),\\n\" +\n                \"\\tDXBZ char(1),\\n\" +\n                \"\\tCONSTRAINT PK_XT_DM_GN PRIMARY KEY (GNDM)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE XT_DJ_YHCD (\\n\" +\n                \"\\tCDBH varchar(20) NOT NULL,\\n\" +\n                \"\\tYHBH varchar(20),\\n\" +\n                \"\\tGNBH varchar(20),\\n\" +\n                \"\\tPLXH bigint,\\n\" +\n                \"\\tXTBH varchar(20),\\n\" +\n                \"\\tCONSTRAINT PK_XT_DJ_YHCD PRIMARY KEY (CDBH),\\n\" +\n                \"\\tFOREIGN KEY (GNBH) REFERENCES XT_DJ_GN (GNBH),\\n\" +\n                \"\\tFOREIGN KEY (YHBH) REFERENCES XT_DJ_YH (YHBH)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE XT_DJ_YH (\\n\" +\n                \"\\tYHBH varchar(20) NOT NULL,\\n\" +\n                \"\\tXTBH varchar(20) NOT NULL,\\n\" +\n                \"\\tYHDM varchar(20) NOT NULL,\\n\" +\n                \"\\tDLMM varchar(20) NOT NULL,\\n\" +\n                \"\\tYHMC varchar(200) NOT NULL,\\n\" +\n                \"\\tCJYH varchar(20),\\n\" +\n                \"\\tCJSJ datetime,\\n\" +\n                \"\\tYHBZ char(1) DEFAULT '1',\\n\" +\n                \"\\tYXBZ char(1),\\n\" +\n                \"\\tYHMS varchar(200),\\n\" +\n                \"\\tTSBZ char(1),\\n\" +\n                \"\\tCONSTRAINT PK_XT_DJ_YH PRIMARY KEY (YHBH),\\n\" +\n                \"\\tFOREIGN KEY (XTBH) REFERENCES XT_DJ_XT (XTBH)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE XT_DJ_GN (\\n\" +\n                \"\\tGNBH varchar(20) NOT NULL,\\n\" +\n                \"\\tXTBH varchar(20),\\n\" +\n                \"\\tGNDM varchar(20) NOT NULL,\\n\" +\n                \"\\tGNMC varchar(200) NOT NULL,\\n\" +\n                \"\\tSJGNBH varchar(20),\\n\" +\n                \"\\tCDBZ char(1),\\n\" +\n                \"\\tPLXH bigint,\\n\" +\n                \"\\tFWKZBZ char(1),\\n\" +\n                \"\\tYXBZ char(1),\\n\" +\n                \"\\tLJDZ varchar(200),\\n\" +\n                \"\\tCONSTRAINT PK_XT_DJ_GN PRIMARY KEY (GNBH),\\n\" +\n                \"\\tFOREIGN KEY (XTBH) REFERENCES XT_DJ_XT (XTBH),\\n\" +\n                \"\\tFOREIGN KEY (GNDM) REFERENCES XT_DM_GN (GNDM)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"\\n\" +\n                \"\\n\" +\n                \"\\n\";\n\n        List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);\n\n        SQLCreateTableStatement.sort(stmtList);\n\n        assertEquals(\"XT_DJ_XT\", ((SQLCreateTableStatement) stmtList.get(0)).getName().getSimpleName());\n        assertEquals(\"XT_DM_GN\", ((SQLCreateTableStatement) stmtList.get(1)).getName().getSimpleName());\n        assertEquals(\"XT_DJ_YH\", ((SQLCreateTableStatement) stmtList.get(2)).getName().getSimpleName());\n        assertEquals(\"XT_DJ_GN\", ((SQLCreateTableStatement) stmtList.get(3)).getName().getSimpleName());\n        assertEquals(\"XT_DJ_YHCD\", ((SQLCreateTableStatement) stmtList.get(4)).getName().getSimpleName());\n\n        String sortedSql = SQLUtils.toSQLString(stmtList, JdbcConstants.ORACLE);\n        System.out.println(sortedSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/CreateCompareTest_cycle.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 18/07/2017.\n */\npublic class CreateCompareTest_cycle {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE t0 (\\n\" +\n                \"\\tint bigint\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t1 (\\n\" +\n                \"\\tint bigint\\n\" +\n                \");\\n\" +\n                \"CREATE TABLE t2 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t1 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t3 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t2 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t4 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t3 (id),\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t4 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t5 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t4 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t6 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t5 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t7 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t6 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t8 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t7 (id)\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE TABLE t9 (\\n\" +\n                \"\\tint bigint,\\n\" +\n                \"\\tFOREIGN KEY (id)\\n\" +\n                \"\\t\\tREFERENCES t8 (id)\\n\" +\n                \");\";\n\n        List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);\n\n        SQLCreateTableStatement.sort(stmtList);\n\n        String sortedSql = SQLUtils.toSQLString(stmtList, JdbcConstants.ORACLE);\n        System.out.println(sortedSql);\n\n        assertEquals(\"t0\", ((SQLCreateTableStatement) stmtList.get(9)).getName().getSimpleName());\n        assertEquals(\"t9\", ((SQLCreateTableStatement) stmtList.get(8)).getName().getSimpleName());\n        assertEquals(\"t8\", ((SQLCreateTableStatement) stmtList.get(7)).getName().getSimpleName());\n        assertEquals(\"t7\", ((SQLCreateTableStatement) stmtList.get(6)).getName().getSimpleName());\n        assertEquals(\"t6\", ((SQLCreateTableStatement) stmtList.get(5)).getName().getSimpleName());\n        assertEquals(\"t5\", ((SQLCreateTableStatement) stmtList.get(4)).getName().getSimpleName());\n        assertEquals(\"t4\", ((SQLCreateTableStatement) stmtList.get(3)).getName().getSimpleName());\n        assertEquals(\"t3\", ((SQLCreateTableStatement) stmtList.get(2)).getName().getSimpleName());\n        assertEquals(\"t2\", ((SQLCreateTableStatement) stmtList.get(1)).getName().getSimpleName());\n        assertEquals(\"t1\", ((SQLCreateTableStatement) stmtList.get(0)).getName().getSimpleName());\n\n        assertEquals(\"t4\", ((SQLAlterTableStatement) stmtList.get(10)).getName().getSimpleName());\n\n        assertEquals(11, stmtList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/CreateDatabaseTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CreateDatabaseTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE DATABASE mydb\";\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, null);\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE DATABASE mydb\", SQLUtils.toSQLString(stmt, (DbType) null));\n    }\n\n    @Test\n    public void test_mysql() throws Exception {\n        String sql = \"CREATE DATABASE mydb\";\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcUtils.MYSQL);\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE DATABASE mydb\", SQLUtils.toSQLString(stmt, JdbcUtils.MYSQL));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/DistinctTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DistinctTest {\n    private String sql = \"select count(distinct *) from t\";\n\n    @Test\n    public void test_mysql() throws Exception {\n        assertEquals(\"SELECT count(DISTINCT *)\\nFROM t\", SQLUtils.format(sql, JdbcUtils.MYSQL));\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        assertEquals(\"SELECT count(DISTINCT *)\\nFROM t\", SQLUtils.format(sql, JdbcUtils.ORACLE));\n    }\n\n    @Test\n    public void test_oracle_unique() throws Exception {\n        assertEquals(\"SELECT count(UNIQUE *)\\nFROM t\",\n                SQLUtils.format(\"select count(unique *) from t\", JdbcUtils.ORACLE));\n    }\n\n    @Test\n    public void test_postgres() throws Exception {\n        assertEquals(\"SELECT count(DISTINCT *)\\nFROM t\", SQLUtils.format(sql, JdbcUtils.POSTGRESQL));\n    }\n\n    @Test\n    public void test_sql92() throws Exception {\n        assertEquals(\"SELECT count(DISTINCT *)\\nFROM t\", SQLUtils.format(sql, (DbType) null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest2.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest2 {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"INTERVAL '30.12345' SECOND(2, 4)\";\n        String sql_c = \"INTERVAL '30.12345' SECOND(2, 3)\";\n        OracleIntervalExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (OracleIntervalExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (OracleIntervalExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (OracleIntervalExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_OracleDate.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLDateExpr;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_OracleDate {\n    @Test\n    public void test_eq() throws Exception {\n        SQLDateExpr exprA = new SQLDateExpr();\n        SQLDateExpr exprB = new SQLDateExpr();\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n        assertEquals(exprA, exprB);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_OracleTimestampExpr.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLTimestampExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_OracleTimestampExpr {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"TIMESTAMP '' AT TIME ZONE ''\";\n        String sql_c = \"TIMESTAMP '' AT TIME ZONE 'a'\";\n        SQLTimestampExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLTimestampExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLTimestampExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLTimestampExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLTimestampExpr(), new SQLTimestampExpr());\n        assertEquals(new SQLTimestampExpr().hashCode(), new SQLTimestampExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_SQLSelectQueryBlock.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_SQLSelectQueryBlock {\n    @Test\n    public void test_eq() throws Exception {\n        SQLSelectQueryBlock exprA = new SQLSelectQueryBlock();\n        SQLSelectQueryBlock exprB = new SQLSelectQueryBlock();\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n        assertEquals(exprA, exprB);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_aggreate.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_aggreate {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"count(*)\";\n        String sql_c = \"count(id)\";\n        SQLAggregateExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLAggregateExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLAggregateExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLAggregateExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLAggregateExpr(null), new SQLAggregateExpr(null));\n        assertEquals(new SQLAggregateExpr(null).hashCode(), new SQLAggregateExpr(null).hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_aggreate_over.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_aggreate_over {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"count(*) OVER (ORDER BY f1)\";\n        String sql_c = \"count(id) OVER (ORDER BY f2)\";\n        SQLAggregateExpr exprA, exprB, exprC;\n        {\n            SQLExprParser parser = new SQLExprParser(sql);\n            exprA = (SQLAggregateExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new SQLExprParser(sql);\n            exprB = (SQLAggregateExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new SQLExprParser(sql_c);\n            exprC = (SQLAggregateExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLAggregateExpr(null), new SQLAggregateExpr(null));\n        assertEquals(new SQLAggregateExpr(null).hashCode(), new SQLAggregateExpr(null).hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_any.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLAnyExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_any {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"any(select id from t)\";\n        String sql_c = \"any(select id from t1)\";\n        SQLAnyExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLAnyExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLAnyExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLAnyExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLAnyExpr(), new SQLAnyExpr());\n        assertEquals(new SQLAnyExpr().hashCode(), new SQLAnyExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_between.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_between {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"x between 1 AND 2\";\n        String sql_c = \"x between 1 AND 3\";\n        SQLBetweenExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLBetweenExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLBetweenExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLBetweenExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLBetweenExpr(), new SQLBetweenExpr());\n        assertEquals(new SQLBetweenExpr().hashCode(), new SQLBetweenExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_binary.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_binary {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"b'01010'\";\n        String sql_c = \"b'010101'\";\n        SQLBinaryExpr exprA, exprB, exprC;\n        {\n            SQLExprParser parser = new MySqlExprParser(sql);\n            exprA = (SQLBinaryExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new MySqlExprParser(sql);\n            exprB = (SQLBinaryExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new MySqlExprParser(sql_c);\n            exprC = (SQLBinaryExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLBinaryExpr(), new SQLBinaryExpr());\n        assertEquals(new SQLBinaryExpr().hashCode(), new SQLBinaryExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_binaryOp.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_binaryOp {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"a > b\";\n        String sql_c = \"a > 2\";\n        SQLBinaryOpExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLBinaryOpExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLBinaryOpExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLBinaryOpExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLBinaryOpExpr(), new SQLBinaryOpExpr());\n        assertEquals(new SQLBinaryOpExpr().hashCode(), new SQLBinaryOpExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_boolean.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLBooleanExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_boolean {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"true\";\n        String sql_c = \"false\";\n        SQLBooleanExpr exprA, exprB, exprC;\n        {\n            SQLExprParser parser = new MySqlExprParser(sql);\n            exprA = (SQLBooleanExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new MySqlExprParser(sql);\n            exprB = (SQLBooleanExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new MySqlExprParser(sql_c);\n            exprC = (SQLBooleanExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLBooleanExpr(), new SQLBooleanExpr());\n        assertEquals(new SQLBooleanExpr().hashCode(), new SQLBooleanExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_case.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLCaseExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_case {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"case x when 1 then 0 else 2 end\";\n        String sql_c = \"case x when 2 then 0 else 2 end\";\n        SQLCaseExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLCaseExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLCaseExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLCaseExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLCaseExpr(), new SQLCaseExpr());\n        assertEquals(new SQLCaseExpr().hashCode(), new SQLCaseExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_cast.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLDataTypeImpl;\nimport com.alibaba.druid.sql.ast.expr.SQLCastExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_cast {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"cast(a as varchar(50))\";\n        String sql_c = \"cast(b as varchar(50))\";\n        SQLCastExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLCastExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLCastExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLCastExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLCastExpr(), new SQLCastExpr());\n        assertEquals(new SQLCastExpr().hashCode(), new SQLCastExpr().hashCode());\n\n        assertEquals(new SQLDataTypeImpl(), new SQLDataTypeImpl());\n        assertEquals(new SQLDataTypeImpl().hashCode(), new SQLDataTypeImpl().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_cursor.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_cursor {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"CURSOR(select id from t)\";\n        String sql_c = \"CURSOR(select id from t1)\";\n        OracleCursorExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (OracleCursorExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (OracleCursorExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (OracleCursorExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new OracleCursorExpr(), new OracleCursorExpr());\n        assertEquals(new OracleCursorExpr().hashCode(), new OracleCursorExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_dbLink.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLDbLinkExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_dbLink {\n    @Test\n    public void test_eq() throws Exception {\n        String sql = \"a@b\";\n        String sql_c = \"a@c\";\n        SQLDbLinkExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLDbLinkExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLDbLinkExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLDbLinkExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLDbLinkExpr(), new SQLDbLinkExpr());\n        assertEquals(new SQLDbLinkExpr().hashCode(), new SQLDbLinkExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_exists.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLExistsExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_exists {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"exists (select 1)\";\n        String sql_c = \"not exists (select 1)\";\n        SQLExistsExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLExistsExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLExistsExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLExistsExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLExistsExpr(), new SQLExistsExpr());\n        assertEquals(new SQLExistsExpr().hashCode(), new SQLExistsExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_extract_mysql.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLExtractExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_extract_mysql {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"EXTRACT (YEAR FROM x)\";\n        String sql_c = \"EXTRACT (MONTH FROM y)\";\n        SQLExtractExpr exprA, exprB, exprC;\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql);\n            exprA = (SQLExtractExpr) parser.expr();\n        }\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql);\n            exprB = (SQLExtractExpr) parser.expr();\n        }\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql_c);\n            exprC = (SQLExtractExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLExtractExpr(), new SQLExtractExpr());\n        assertEquals(new SQLExtractExpr().hashCode(), new SQLExtractExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_extract_oracle.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_extract_oracle {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"EXTRACT(MONTH FROM x)\";\n        String sql_c = \"EXTRACT(MONTH FROM 7)\";\n        SQLMethodInvokeExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLMethodInvokeExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLMethodInvokeExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLMethodInvokeExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLMethodInvokeExpr(), new SQLMethodInvokeExpr());\n        assertEquals(new SQLMethodInvokeExpr().hashCode(), new SQLMethodInvokeExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_groupSet.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLGroupingSetExpr;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_groupSet {\n    @Test\n    public void test_eq() throws Exception {\n        SQLGroupingSetExpr exprA = new SQLGroupingSetExpr();\n        SQLGroupingSetExpr exprB = new SQLGroupingSetExpr();\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n        assertEquals(exprA, exprB);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_inList.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLInListExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_inList {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"x in (1, 2, 3)\";\n        String sql_c = \"x not in (1, 2, 3)\";\n        SQLInListExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLInListExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLInListExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLInListExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLInListExpr(), new SQLInListExpr());\n        assertEquals(new SQLInListExpr().hashCode(), new SQLInListExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_inquery.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_inquery {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"fstate in (select state from t_status)\";\n        String sql_c = \"fstate_c in (select state from t_status)\";\n        SQLInSubQueryExpr exprA, exprB, exprC;\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql);\n            exprA = (SQLInSubQueryExpr) parser.expr();\n        }\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql);\n            exprB = (SQLInSubQueryExpr) parser.expr();\n        }\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql_c);\n            exprC = (SQLInSubQueryExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_inquery_mysql.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_inquery_mysql {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"fstate in (select state from t_status)\";\n        String sql_c = \"fstate_c in (select state from t_status)\";\n        SQLInSubQueryExpr exprA, exprB, exprC;\n        {\n            SQLExprParser parser = new SQLExprParser(sql);\n            exprA = (SQLInSubQueryExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new SQLExprParser(sql);\n            exprB = (SQLInSubQueryExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new SQLExprParser(sql_c);\n            exprC = (SQLInSubQueryExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLInSubQueryExpr(), new SQLInSubQueryExpr());\n        assertEquals(new SQLInSubQueryExpr().hashCode(), new SQLInSubQueryExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_inquery_oracle.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_inquery_oracle {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"fstate in (select state from t_status)\";\n        String sql_c = \"fstate_c in (select state from t_status)\";\n        SQLInSubQueryExpr exprA, exprB, exprC;\n        {\n            SQLExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLInSubQueryExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLInSubQueryExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLInSubQueryExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLInSubQueryExpr(), new SQLInSubQueryExpr());\n        assertEquals(new SQLInSubQueryExpr().hashCode(), new SQLInSubQueryExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_interval_mysql.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIntervalExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_interval_mysql {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"INTERVAL 3 YEAR\";\n        String sql_c = \"INTERVAL 3 MONTH\";\n        SQLIntervalExpr exprA, exprB, exprC;\n        {\n            SQLExprParser parser = new MySqlExprParser(sql);\n            exprA = (SQLIntervalExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new MySqlExprParser(sql);\n            exprB = (SQLIntervalExpr) parser.expr();\n        }\n        {\n            SQLExprParser parser = new MySqlExprParser(sql_c);\n            exprC = (SQLIntervalExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLIntervalExpr(), new SQLIntervalExpr());\n        assertEquals(new SQLIntervalExpr().hashCode(), new SQLIntervalExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_not.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLNotExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_not {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"not f1 = f2\";\n        String sql_c = \"not f1 = f3\";\n        SQLNotExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLNotExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLNotExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLNotExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLNotExpr(), new SQLNotExpr());\n        assertEquals(new SQLNotExpr().hashCode(), new SQLNotExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_not_2.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLNotExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_not_2 {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"NOT A=1 AND NOT B=1\";\n        SQLNotExpr exprA, exprB;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            SQLBinaryOpExpr binaryEpr = (SQLBinaryOpExpr) parser.expr();\n            exprA = (SQLNotExpr) binaryEpr.getLeft();\n            exprB = (SQLNotExpr) binaryEpr.getRight();\n        }\n\n        assertNotNull(exprA);\n        assertNotNull(exprB);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_number.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLNumberExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_number {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"3.5\";\n        String sql_c = \"3.51\";\n        SQLNumberExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLNumberExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLNumberExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLNumberExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLNumberExpr(), new SQLNumberExpr());\n        assertEquals(new SQLNumberExpr().hashCode(), new SQLNumberExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_orderBy.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLOrderBy;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_orderBy {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"ORDER BY f1\";\n        String sql_c = \"ORDER BY f2\";\n        SQLOrderBy exprA, exprB, exprC;\n        {\n            SQLExprParser parser = new SQLExprParser(sql);\n            exprA = (SQLOrderBy) parser.parseOrderBy();\n        }\n        {\n            SQLExprParser parser = new SQLExprParser(sql);\n            exprB = (SQLOrderBy) parser.parseOrderBy();\n        }\n        {\n            SQLExprParser parser = new SQLExprParser(sql_c);\n            exprC = (SQLOrderBy) parser.parseOrderBy();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLOrderBy(), new SQLOrderBy());\n        assertEquals(new SQLOrderBy().hashCode(), new SQLOrderBy().hashCode());\n\n        assertEquals(new SQLSelectOrderByItem(), new SQLSelectOrderByItem());\n        assertEquals(new SQLSelectOrderByItem().hashCode(), new SQLSelectOrderByItem().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_query.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLQueryExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_query {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"(select id from t)\";\n        String sql_c = \"(select id from t1)\";\n        SQLQueryExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLQueryExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLQueryExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLQueryExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLQueryExpr(), new SQLQueryExpr());\n        assertEquals(new SQLQueryExpr().hashCode(), new SQLQueryExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_select.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_select {\n    @Test\n    public void test_eq_select() throws Exception {\n        List stmtsA = SQLUtils.parseStatements(\"select * from a\", JdbcConstants.ODPS);\n        List stmtsB = SQLUtils.parseStatements(\"select * from b\", JdbcConstants.ODPS);\n        SQLSelect selectA = ((SQLSelectStatement) stmtsA.get(0)).getSelect();\n        SQLSelect selectB = ((SQLSelectStatement) stmtsB.get(0)).getSelect();\n        boolean eq = selectA.equals(selectB);\n        assertFalse(eq);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_some.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLSomeExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_some {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"some(select id from t)\";\n        String sql_c = \"some(select id from t1)\";\n        SQLSomeExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLSomeExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLSomeExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLSomeExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLSomeExpr(), new SQLSomeExpr());\n        assertEquals(new SQLSomeExpr().hashCode(), new SQLSomeExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_unary.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLUnaryExpr;\nimport com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_unary {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"-a\";\n        String sql_c = \"-(a+1 + +(b+1))\";\n        SQLUnaryExpr exprA, exprB, exprC;\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprA = (SQLUnaryExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql);\n            exprB = (SQLUnaryExpr) parser.expr();\n        }\n        {\n            OracleExprParser parser = new OracleExprParser(sql_c);\n            exprC = (SQLUnaryExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLUnaryExpr(), new SQLUnaryExpr());\n        assertEquals(new SQLUnaryExpr().hashCode(), new SQLUnaryExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/EqualTest_unary_mysql.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLUnaryExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EqualTest_unary_mysql {\n    @Test\n    public void test_exits() throws Exception {\n        String sql = \"-a\";\n        String sql_c = \"-(a+1 + +(b+1))\";\n        SQLUnaryExpr exprA, exprB, exprC;\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql);\n            exprA = (SQLUnaryExpr) parser.expr();\n        }\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql);\n            exprB = (SQLUnaryExpr) parser.expr();\n        }\n        {\n            MySqlExprParser parser = new MySqlExprParser(sql_c);\n            exprC = (SQLUnaryExpr) parser.expr();\n        }\n        assertEquals(exprA, exprB);\n        assertNotEquals(exprA, exprC);\n        assertTrue(exprA.equals(exprA));\n        assertFalse(exprA.equals(new Object()));\n        assertEquals(exprA.hashCode(), exprB.hashCode());\n\n        assertEquals(new SQLUnaryExpr(), new SQLUnaryExpr());\n        assertEquals(new SQLUnaryExpr().hashCode(), new SQLUnaryExpr().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/ExportParameterInTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.fastjson2.JSON;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 23/11/2016.\n */\npublic class ExportParameterInTest {\n    DbType dbType = JdbcConstants.MYSQL;\n\n    @Test\n    public void test_exportParameter() throws Exception {\n        String sql = \"select * from t_user where oid = '102' and uid in (1, 2, 3)\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        StringBuilder out = new StringBuilder();\n        List<Object> parameters = new ArrayList<Object>();\n        SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, dbType);\n        visitor.setParameterized(true);\n        visitor.setParameterizedMergeInList(true);\n        visitor.setParameters(parameters);\n\n        stmt.accept(visitor);\n\n        System.out.println(out);\n        System.out.println(JSON.toJSONString(parameters));\n\n        restore(out.toString(), parameters);\n    }\n\n    public void restore(String sql, List<Object> parameters) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, dbType);\n        visitor.setParameters(parameters);\n        stmt.accept(visitor);\n\n        System.out.println(out);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/ExportParameterShardingTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.fastjson2.JSON;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 23/11/2016.\n */\npublic class ExportParameterShardingTest {\n    DbType dbType = JdbcConstants.MYSQL;\n\n    @Test\n    public void test_exportParameter() throws Exception {\n        String sql = \"select * from t_user_0000 where oid = 1001\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, dbType);\n        visitor.setParameterized(true);\n        visitor.setParameterizedMergeInList(true);\n        List<Object> parameters = visitor.getParameters();\n        //visitor.setParameters(parameters);\n\n        stmt.accept(visitor);\n\n        System.out.println(out);\n        System.out.println(JSON.toJSONString(parameters));\n\n        String restoredSql = restore(out.toString(), parameters);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t_user_0000\\n\" +\n                \"WHERE oid = 1001\", restoredSql);\n    }\n\n    public String restore(String sql, List<Object> parameters) {\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        StringBuilder out = new StringBuilder();\n        SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, dbType);\n        visitor.setInputParameters(parameters);\n\n        visitor.addTableMapping(\"t_user\", \"t_user_0000\");\n\n        stmt.accept(visitor);\n\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/FirstCommentTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FirstCommentTest {\n    @Test\n    public void test_first_commnet() throws Exception {\n        String sql = \"/*test sql*/select age from user where name = 'xx';\";\n        Lexer lexer = new MySqlLexer(sql);\n        lexer.setKeepComments(true);\n        lexer.nextToken();\n        List<String> comments = lexer.readAndResetComments();\n        assertEquals(\"/*test sql*/\", comments.get(0));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/GetParentTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLObject;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\npublic class GetParentTest {\n    @Test\n    public void test() {\n        SQLObject obj1 = new SQLIdentifierExpr(\"1\");\n        SQLObject obj2 = new SQLIdentifierExpr(\"2\");\n        obj2.setParent(obj1);\n        SQLObject obj3 = new SQLIdentifierExpr(\"3\");\n        obj3.setParent(obj2);\n        assertEquals(obj2, obj3.getParent(1));\n        assertEquals(obj1, obj3.getParent(2));\n        assertNull(obj3.getParent(3));\n        assertNull(obj3.getParent(4));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/GroupingSetsTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class GroupingSetsTest {\n    @Test\n    public void test_groupingSets() throws Exception {\n        String sql = \"SELECT brand, size, sum(sales) FROM items_sold GROUP BY GROUPING SETS ((brand), (size), ());\";\n\n        String result = SQLUtils.format(sql, (DbType) null);\n\n        assertEquals(\"SELECT brand, size, sum(sales)\"\n                + \"\\nFROM items_sold\"\n                + \"\\nGROUP BY GROUPING SETS ((brand), (size), ());\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/HashTest_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HashTest_0 {\n    @Test\n    public void test_issue() throws Exception {\n        assertEquals(new SQLIdentifierExpr(\"a\").nameHashCode64(),\n                new SQLIdentifierExpr(\"A\").nameHashCode64());\n    }\n\n    @Test\n    public void test_issue_1() throws Exception {\n        assertEquals(new SQLIdentifierExpr(\"a\").nameHashCode64(),\n                new SQLIdentifierExpr(\"`A`\").nameHashCode64());\n    }\n\n    @Test\n    public void test_issue_2() throws Exception {\n        assertEquals(new SQLIdentifierExpr(\"\\\"a\\\"\").nameHashCode64(),\n                new SQLIdentifierExpr(\"`A`\").nameHashCode64());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/HashTest_1_propertyExpr.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.util.FnvHash;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HashTest_1_propertyExpr {\n    @Test\n    public void test_issue() throws Exception {\n        assertEquals(new SQLPropertyExpr(\"t\", \"a\").nameHashCode64(),\n                new SQLPropertyExpr(\"t\", \"A\").nameHashCode64());\n    }\n\n    @Test\n    public void test_issue_1() throws Exception {\n        assertEquals(new SQLPropertyExpr(\"t\", \"a\").nameHashCode64(),\n                new SQLPropertyExpr(\"t\", \"`A`\").nameHashCode64());\n    }\n\n    @Test\n    public void test_issue_2() throws Exception {\n        assertEquals(new SQLPropertyExpr(\"t\", \"\\\"a\\\"\").nameHashCode64(),\n                new SQLPropertyExpr(\"t\", \"`A`\").nameHashCode64());\n    }\n\n    @Test\n    public void test_issue_3() throws Exception {\n        assertEquals(new SQLPropertyExpr(\"ESCROW\", \"HT_TASK_TRADE_HISTORY_NEW\").nameHashCode64(),\n                new SQLPropertyExpr(\"\\\"ESCROW\\\"\", \"\\\"HT_TASK_TRADE_HISTORY_NEW\\\"\").nameHashCode64());\n    }\n\n    @Test\n    public void test_issue_4() throws Exception {\n        assertEquals(new SQLPropertyExpr(\"ESCROW\", \"HT_TASK_TRADE_HISTORY_NEW\").hashCode64(),\n                new SQLPropertyExpr(\"\\\"ESCROW\\\"\", \"\\\"HT_TASK_TRADE_HISTORY_NEW\\\"\").hashCode64());\n    }\n\n    @Test\n    public void test_issue_5() throws Exception {\n        assertEquals(\n                FnvHash.fnv1a_64_lower(\"a.b\"),\n                new SQLPropertyExpr(\"\\\"a\\\"\", \"\\\"b\\\"\")\n                        .hashCode64()\n        );\n    }\n\n    @Test\n    public void test_issue_6() throws Exception {\n        assertEquals(\n                FnvHash.fnv1a_64_lower(\"ESCROW.HT_TASK_TRADE_HISTORY_NEW\"),\n                new SQLPropertyExpr(\"\\\"ESCROW\\\"\", \"\\\"HT_TASK_TRADE_HISTORY_NEW\\\"\").hashCode64());\n    }\n\n    @Test\n    public void test_changeOwner() throws Exception {\n        SQLIdentifierExpr table = new SQLIdentifierExpr(\"t1\");\n        SQLPropertyExpr column = new SQLPropertyExpr(table, \"f0\");\n\n        assertEquals(FnvHash.hashCode64(\"t1\"), table.hashCode64());\n        assertEquals(FnvHash.hashCode64(\"t1.f0\"), column.hashCode64());\n\n        table.setName(\"t2\");\n\n        assertEquals(FnvHash.hashCode64(\"t2\"), table.hashCode64());\n        assertEquals(FnvHash.hashCode64(\"t2.f0\"), column.hashCode64());\n\n        column.setName(\"f1\");\n\n        assertEquals(FnvHash.hashCode64(\"t2.f1\"), column.hashCode64());\n    }\n\n    //ESCROW.HT_TASK_TRADE_HISTORY_NEW\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_alterTable.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_alterTable {\n    String sql = \"ALTER TABLE user DROP INDEX pk_user;\";\n\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping_createTable() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"ALTER TABLE user_01\\n\" +\n                \"\\tDROP INDEX pk_user;\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"ALTER TABLE user_01\\n\" +\n                \"\\tDROP INDEX pk_user;\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"ALTER TABLE user_01\\n\" +\n                \"\\tDROP INDEX pk_user;\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"ALTER TABLE user_01\\n\" +\n                \"\\tDROP INDEX pk_user;\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"ALTER TABLE user_01\\n\" +\n                \"\\tDROP INDEX pk_user;\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"ALTER TABLE user_01\\n\" +\n                \"\\tDROP INDEX pk_user;\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_createTable.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_createTable {\n    String sql = \"create table user (\\n\" +\n            \"source_key int,\\n\" +\n            \"source_value varchar(32),\\n\" +\n            \"primary key(source_key)\\n\" +\n            \");\";\n\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping_createTable() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"CREATE TABLE user_01 (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"CREATE TABLE user_01 (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"CREATE TABLE user_01 (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"CREATE TABLE user_01 (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"CREATE TABLE user_01 (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"CREATE TABLE user_01 (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_createTable_2.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_createTable_2 {\n    String sql = \"create table database_source.table_source(\\n\" +\n            \"source_key int,\\n\" +\n            \"source_value varchar(32),\\n\" +\n            \"primary key(source_key)\\n\" +\n            \");\";\n\n    Map<String, String> mapping = Collections.singletonMap(\"database_source.table_source\", \"database_target.table_target\");\n\n    @Test\n    public void test_mapping_createTable() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"CREATE TABLE database_target.table_target (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"CREATE TABLE database_target.table_target (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"CREATE TABLE database_target.table_target (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"CREATE TABLE database_target.table_target (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"CREATE TABLE database_target.table_target (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n\n    @Test\n    public void test_mapping_createTable_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"CREATE TABLE database_target.table_target (\\n\" +\n                \"\\tsource_key int,\\n\" +\n                \"\\tsource_value varchar(32),\\n\" +\n                \"\\tPRIMARY KEY (source_key)\\n\" +\n                \");\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_delete.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_delete {\n    private String sql = \"delete from user\";\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"DELETE FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"DELETE FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"DELETE FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"DELETE FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"DELETE FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"DELETE FROM user_01\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_drop.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_drop {\n    private String sql = \"drop table user\";\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"DROP TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"DROP TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"DROP TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"DROP TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"DROP TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"DROP TABLE user_01\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_insert.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_insert {\n    private String sql = \"insert into user (id, name) values (123, 'abc')\";\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"INSERT INTO user_01 (id, name)\\n\" +\n                \"VALUES (123, 'abc')\", result);\n    }\n\n    @Test\n    public void test_mapping_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"INSERT INTO user_01 (id, name)\\n\" +\n                \"VALUES (123, 'abc')\", result);\n    }\n\n    @Test\n    public void test_mapping_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"INSERT INTO user_01 (id, name)\\n\" +\n                \"VALUES (123, 'abc')\", result);\n    }\n\n    @Test\n    public void test_mapping_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"INSERT INTO user_01 (id, name)\\n\" +\n                \"VALUES (123, 'abc')\", result);\n    }\n\n    @Test\n    public void test_mapping_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"INSERT INTO user_01 (id, name)\\n\" +\n                \"VALUES (123, 'abc')\", result);\n    }\n\n    @Test\n    public void test_mapping_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"INSERT INTO user_01 (id, name)\\n\" +\n                \"VALUES (123, 'abc')\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_select.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_select {\n    String sql = \"select * from user\";\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_odps() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ODPS, mapping);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM user_01\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_truncate.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_truncate {\n    private String sql = \"truncate table user\";\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"TRUNCATE TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"TRUNCATE TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"TRUNCATE TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"TRUNCATE TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"TRUNCATE TABLE user_01\", result);\n    }\n\n    @Test\n    public void test_mapping_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"TRUNCATE TABLE user_01\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MappingTest_update.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/9/25.\n */\npublic class MappingTest_update {\n    private String sql = \"update user set f1 = 1 where id = 3\";\n    Map<String, String> mapping = Collections.singletonMap(\"user\", \"user_01\");\n\n    @Test\n    public void test_mapping() throws Exception {\n        String result = SQLUtils.refactor(sql, null, mapping);\n        assertEquals(\"UPDATE user_01\\n\" +\n                \"SET f1 = 1\\n\" +\n                \"WHERE id = 3\", result);\n    }\n\n    @Test\n    public void test_mapping_mysql() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.MYSQL, mapping);\n        assertEquals(\"UPDATE user_01\\n\" +\n                \"SET f1 = 1\\n\" +\n                \"WHERE id = 3\", result);\n    }\n\n    @Test\n    public void test_mapping_pg() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.POSTGRESQL, mapping);\n        assertEquals(\"UPDATE user_01\\n\" +\n                \"SET f1 = 1\\n\" +\n                \"WHERE id = 3\", result);\n    }\n\n    @Test\n    public void test_mapping_oracle() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.ORACLE, mapping);\n        assertEquals(\"UPDATE user_01\\n\" +\n                \"SET f1 = 1\\n\" +\n                \"WHERE id = 3\", result);\n    }\n\n    @Test\n    public void test_mapping_sqlserver() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.SQL_SERVER, mapping);\n        assertEquals(\"UPDATE user_01\\n\" +\n                \"SET f1 = 1\\n\" +\n                \"WHERE id = 3\", result);\n    }\n\n    @Test\n    public void test_mapping_db2() throws Exception {\n        String result = SQLUtils.refactor(sql, JdbcConstants.DB2, mapping);\n        assertEquals(\"UPDATE user_01\\n\" +\n                \"SET f1 = 1\\n\" +\n                \"WHERE id = 3\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MybatisTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MybatisTest {\n    private String sql = \"select * from t where id = #{id}\";\n\n    @Test\n    public void test_mysql() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = #{id}\", SQLUtils.format(sql, JdbcUtils.MYSQL));\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = #{id}\", SQLUtils.format(sql, JdbcUtils.OCEANBASE));\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = #{id}\", SQLUtils.format(sql, JdbcUtils.ORACLE));\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = #{id}\", SQLUtils.format(sql, JdbcUtils.OCEANBASE_ORACLE));\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = #{id}\", SQLUtils.format(sql, JdbcUtils.ALI_ORACLE));\n    }\n\n    @Test\n    public void test_postgres() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = #{id}\", SQLUtils.format(sql, JdbcUtils.POSTGRESQL));\n    }\n\n    @Test\n    public void test_sql92() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = #{id}\", SQLUtils.format(sql, (DbType) null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/MybatisTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MybatisTest2 {\n    private String sql = \"select * from t where id = ${id}\";\n\n    @Test\n    public void test_mysql() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = ${id}\", SQLUtils.format(sql, JdbcUtils.MYSQL));\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = ${id}\", SQLUtils.format(sql, JdbcUtils.OCEANBASE));\n    }\n\n    @Test\n    public void test_oracle() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = ${id}\", SQLUtils.format(sql, JdbcUtils.ORACLE));\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = ${id}\", SQLUtils.format(sql, JdbcUtils.OCEANBASE_ORACLE));\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = ${id}\", SQLUtils.format(sql, JdbcUtils.ALI_ORACLE));\n    }\n\n    @Test\n    public void test_postgres() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = ${id}\", SQLUtils.format(sql, JdbcUtils.POSTGRESQL));\n    }\n\n    @Test\n    public void test_sql92() throws Exception {\n        assertEquals(\"SELECT *\\nFROM t\\nWHERE id = ${id}\", SQLUtils.format(sql, (DbType) null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/OverTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class OverTest {\n    @Test\n    public void test_over() throws Exception {\n        String sql = \"SELECT SalesOrderID, ProductID, OrderQty\" +\n                \"    ,SUM(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Total'\" +\n                \"    ,AVG(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Avg'\" +\n                \"    ,COUNT(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Count'\" +\n                \"    ,MIN(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Min'\" +\n                \"    ,MAX(OrderQty) OVER(PARTITION BY SalesOrderID) AS 'Max' \" +\n                \"FROM Sales.SalesOrderDetail \" +\n                \"WHERE SalesOrderID IN(43659,43664);\";\n\n        SQLStatementParser parser = new SQLStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = new SchemaStatVisitor();\n        statemen.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(1, visitor.getTables().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Count_MySql_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Count_MySql_0 {\n    @Test\n    public void test_mysql_0() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_mysql_1() throws Exception {\n        String sql = \"select id, name from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_mysql_2() throws Exception {\n        String sql = \"select id, name from t order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_mysql_3() throws Exception {\n        String sql = \"select distinct id from t order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(DISTINCT id)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_mysql_4() throws Exception {\n        String sql = \"select distinct a.col1,a.col2 from test a\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(DISTINCT a.col1, a.col2)\\n\" +\n                \"FROM test a\", result);\n    }\n\n    @Test\n    public void test_mysql_group_0() throws Exception {\n        String sql = \"select type, count(*) from t group by type\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT type, count(*)\\n\" +\n                \"\\tFROM t\\n\" +\n                \"\\tGROUP BY type\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n\n    @Test\n    public void test_mysql_union_0() throws Exception {\n        String sql = \"select id, name from t1 union select id, name from t2 order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"\\tUNION\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t2\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n\n    @Test\n    public void test_mysql_select() throws Exception {\n        SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils.parseStatements(\"select * from t\", JdbcConstants.MYSQL).get(0);\n        PagerUtils.limit(stmt.getSelect(), stmt.getDbType(), 10, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"LIMIT 10, 10\", stmt.toString());\n    }\n\n    @Test\n    public void test_mysql_groupBy() throws Exception {\n        String countSql = PagerUtils.count(\" SELECT * FROM order_biz GROUP BY product_id\", DbType.mysql);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT 1\\n\" +\n                \"\\tFROM order_biz\\n\" +\n                \"\\tGROUP BY product_id\\n\" +\n                \") ALIAS_COUNT\", countSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Count_Oracle_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Count_Oracle_0 {\n    @Test\n    public void test_oracle_0() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n        result = PagerUtils.count(sql, JdbcConstants.OCEANBASE_ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_oracle_1() throws Exception {\n        String sql = \"select id, name from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n        result = PagerUtils.count(sql, JdbcConstants.OCEANBASE_ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_oracle_2() throws Exception {\n        String sql = \"select id, name from t order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n        result = PagerUtils.count(sql, JdbcConstants.OCEANBASE_ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_oracle_group_0() throws Exception {\n        String sql = \"select type, count(*) from t group by type\";\n        String result = PagerUtils.count(sql, JdbcConstants.ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT type, count(*)\\n\" +\n                \"\\tFROM t\\n\" +\n                \"\\tGROUP BY type\\n\" +\n                \") ALIAS_COUNT\", result);\n\n        result = PagerUtils.count(sql, JdbcConstants.OCEANBASE_ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT type, count(*)\\n\" +\n                \"\\tFROM t\\n\" +\n                \"\\tGROUP BY type\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n\n    @Test\n    public void test_oracle_union_0() throws Exception {\n        String sql = \"select id, name from t1 union select id, name from t2 order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"\\tUNION\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t2\\n\" +\n                \") ALIAS_COUNT\", result);\n\n        result = PagerUtils.count(sql, JdbcConstants.OCEANBASE_ORACLE);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"\\tUNION\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t2\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Count_PG_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Count_PG_0 {\n    @Test\n    public void test_pg_0() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.POSTGRESQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_pg_1() throws Exception {\n        String sql = \"select id, name from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.POSTGRESQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_pg_2() throws Exception {\n        String sql = \"select id, name from t order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.POSTGRESQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_pg_3() throws Exception {\n        String sql = \"select * from test where shape.STIntersects(geometry::STGeomFromText('POLYGON ((86610.054 86610.054,112372.95799999963 88785.5940000005,112372.91199999955 88675.996999999508,86610.054 86610.054))',0))=1;\";\n        String countSql = PagerUtils.count(sql, JdbcConstants.POSTGRESQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM test\\n\" +\n                \"WHERE shape.STIntersects(geometry::STGeomFromText('POLYGON ((86610.054 86610.054,112372.95799999963 88785.5940000005,112372.91199999955 88675.996999999508,86610.054 86610.054))', 0)) = 1\", countSql);\n\n        String limitSql = PagerUtils.limit(sql, JdbcConstants.POSTGRESQL, 100, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM test\\n\" +\n                \"WHERE shape.STIntersects(geometry::STGeomFromText('POLYGON ((86610.054 86610.054,112372.95799999963 88785.5940000005,112372.91199999955 88675.996999999508,86610.054 86610.054))', 0)) = 1\\n\" +\n                \"LIMIT 10 OFFSET 100\", limitSql);\n    }\n\n    @Test\n    public void test_pg_group_0() throws Exception {\n        String sql = \"select type, count(*) from t group by type\";\n        String result = PagerUtils.count(sql, JdbcConstants.POSTGRESQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT type, count(*)\\n\" +\n                \"\\tFROM t\\n\" +\n                \"\\tGROUP BY type\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n\n    @Test\n    public void test_pg_union_0() throws Exception {\n        String sql = \"select id, name from t1 union select id, name from t2 order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.POSTGRESQL);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"\\tUNION\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t2\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Count_SQLServer_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Count_SQLServer_0 {\n    @Test\n    public void test_sqlserver_0() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.SQL_SERVER);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_sqlserver_1() throws Exception {\n        String sql = \"select id, name from t\";\n        String result = PagerUtils.count(sql, JdbcConstants.SQL_SERVER);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_sqlserver_2() throws Exception {\n        String sql = \"select id, name from t order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.SQL_SERVER);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM t\", result);\n    }\n\n    @Test\n    public void test_sqlserver_group_0() throws Exception {\n        String sql = \"select type, count(*) from t group by type\";\n        String result = PagerUtils.count(sql, JdbcConstants.SQL_SERVER);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT type, count(*)\\n\" +\n                \"\\tFROM t\\n\" +\n                \"\\tGROUP BY type\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n\n    @Test\n    public void test_sqlserver_union_0() throws Exception {\n        String sql = \"select id, name from t1 union select id, name from t2 order by id\";\n        String result = PagerUtils.count(sql, JdbcConstants.SQL_SERVER);\n        assertEquals(\"SELECT COUNT(*)\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"\\tUNION\\n\" +\n                \"\\tSELECT id, name\\n\" +\n                \"\\tFROM t2\\n\" +\n                \") ALIAS_COUNT\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_1.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_SQLServer_1 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \"select * from t1 union select * from t2\";\n        String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 20, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT XX.*, ROW_NUMBER() OVER () AS ROWNUM\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT *\\n\" +\n                \"\\t\\tFROM t1\\n\" +\n                \"\\t\\tUNION\\n\" +\n                \"\\t\\tSELECT *\\n\" +\n                \"\\t\\tFROM t2\\n\" +\n                \"\\t) XX\\n\" +\n                \") XXX\\n\" +\n                \"WHERE ROWNUM > 20\\n\" +\n                \"\\tAND ROWNUM <= 30\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_2.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_SQLServer_2 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \"select * from t1 union select * from t2\";\n        String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 0, 10);\n        assertEquals(\"SELECT TOP 10 XX.*\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT *\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"\\tUNION\\n\" +\n                \"\\tSELECT *\\n\" +\n                \"\\tFROM t2\\n\" +\n                \") XX\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_3.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_SQLServer_3 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \"select * from t1 where id > 1\";\n        String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 0, 10);\n        assertEquals(\"SELECT TOP 10 *\"\n                + \"\\nFROM t1\"\n                + \"\\nWHERE id > 1\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_4.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_SQLServer_4 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \"select * from t1 where id > 1\";\n        String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 100, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT *, ROW_NUMBER() AS ROWNUM\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"\\tWHERE id > 1\\n\" +\n                \") XX\\n\" +\n                \"WHERE ROWNUM > 100\\n\" +\n                \"\\tAND ROWNUM <= 110\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_5.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_SQLServer_5 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \" select * from test t with (nolock)\";\n        String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 0, 10);\n        assertEquals(\"SELECT TOP 10 *\"\n                + \"\\nFROM test t WITH (nolock)\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_SQLServer_6.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_SQLServer_6 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \"SELECT t.name USER_NAME, t.xxx FROM t_sd_users t ORDER BY t.name ASC\";\n        String result = PagerUtils.limit(sql, JdbcConstants.SQL_SERVER, 10, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT t.name AS USER_NAME, t.xxx, ROW_NUMBER() OVER (ORDER BY t.name ASC) AS ROWNUM\\n\" +\n                \"\\tFROM t_sd_users t\\n\" +\n                \") XX\\n\" +\n                \"WHERE ROWNUM > 10\\n\" +\n                \"\\tAND ROWNUM <= 20\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_db2_0 {\n    @Test\n    public void test_mysql_0() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.DB2, 0, 10);\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM t\" +\n                \"\\nFETCH FIRST 10 ROWS ONLY\", result);\n    }\n\n    @Test\n    public void test_mysql_1() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.DB2, 10, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT *, ROW_NUMBER() OVER () AS ROWNUM\\n\" +\n                \"\\tFROM t\\n\" +\n                \") XX\\n\" +\n                \"WHERE ROWNUM > 10\\n\" +\n                \"\\tAND ROWNUM <= 20\", result);\n    }\n\n    @Test\n    public void test_mysql_2() throws Exception {\n        String sql = \"select * from t where age > 100\";\n        String result = PagerUtils.limit(sql, JdbcConstants.DB2, 20, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT *, ROW_NUMBER() OVER () AS ROWNUM\\n\" +\n                \"\\tFROM t\\n\" +\n                \"\\tWHERE age > 100\\n\" +\n                \") XX\\n\" +\n                \"WHERE ROWNUM > 20\\n\" +\n                \"\\tAND ROWNUM <= 30\", result);\n    }\n\n    @Test\n    public void test_mysql_3() throws Exception {\n        String sql = \"select id, name, salary from t order by id, name\";\n        String result = PagerUtils.limit(sql, JdbcConstants.DB2, 20, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT id, name, salary, ROW_NUMBER() OVER (ORDER BY id, name) AS ROWNUM\\n\" +\n                \"\\tFROM t\\n\" +\n                \") XX\\n\" +\n                \"WHERE ROWNUM > 20\\n\" +\n                \"\\tAND ROWNUM <= 30\", result);\n    }\n\n    @Test\n    public void test_fetch_order() {\n        String sql = \"SELECT t.CUSTNAME AS custname\\n\" +\n                \"FROM CPS_LOAN_INFO t WHERE t.DEL_FLAG = 0\\n\" +\n                \"ORDER BY t.CREATE_TIME DESC\";\n\n        String limitSql = PagerUtils.limit(sql, JdbcConstants.DB2, 0, 20);\n        int fetchRowIndex = limitSql.indexOf(\"FETCH FIRST\");\n        int orderIndex = limitSql.indexOf(\"ORDER BY\");\n        assertTrue(fetchRowIndex > orderIndex);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_db2_1.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_db2_1 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \"select * from t1 union select * from t2\";\n        String result = PagerUtils.limit(sql, JdbcConstants.DB2, 20, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT XX.*, ROW_NUMBER() OVER () AS ROWNUM\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT *\\n\" +\n                \"\\t\\tFROM t1\\n\" +\n                \"\\t\\tUNION\\n\" +\n                \"\\t\\tSELECT *\\n\" +\n                \"\\t\\tFROM t2\\n\" +\n                \"\\t) XX\\n\" +\n                \") XXX\\n\" +\n                \"WHERE ROWNUM > 20\\n\" +\n                \"\\tAND ROWNUM <= 30\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_h2_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_h2_0 {\n    @Test\n    public void test_db2_union() throws Exception {\n        String sql = \"select * from t1 union select * from t2\";\n        String result = PagerUtils.limit(\"SELECT * FROM test\", JdbcUtils.H2, 0, 10);\n        System.out.println(result);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM test\\n\" +\n                \"LIMIT 10\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_hive_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.PagerUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_hive_0 {\n    @Test\n    public void test_hive_0() throws Exception {\n        String result = PagerUtils.limit(\"SELECT * FROM test\", DbType.hive, 0, 10);\n        System.out.println(result);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM test\\n\" +\n                \"LIMIT 10\", result);\n    }\n\n    @Test\n    public void test_odps_0() throws Exception {\n        String result = PagerUtils.limit(\"SELECT * FROM test\", DbType.odps, 0, 10);\n        System.out.println(result);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM test\\n\" +\n                \"LIMIT 10\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_mysql_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_mysql_0 {\n    @Test\n    public void test_mysql_0() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 0, 10);\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM t\" +\n                \"\\nLIMIT 10\", result);\n    }\n\n    @Test\n    public void test_mysql_1() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 10, 10);\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM t\" +\n                \"\\nLIMIT 10, 10\", result);\n    }\n\n    @Test\n    public void test_mysql_2() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 20, 10);\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM t\" +\n                \"\\nLIMIT 20, 10\", result);\n    }\n\n    @Test\n    public void test_mysql_3() throws Exception {\n        String sql = \"select id, name, salary from t order by id, name\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 20, 10);\n        assertEquals(\"SELECT id, name, salary\" +\n                \"\\nFROM t\" +\n                \"\\nORDER BY id, name\" +\n                \"\\nLIMIT 20, 10\", result);\n    }\n\n    @Test\n    public void test_mysql_4() throws Exception {\n        String sql = \"SELECT *\\n\" +\n                \"FROM test.a\\n\" +\n                \"WHERE a.field0 = 0\\n\" +\n                \"\\tAND (a.field1 LIKE BINARY '1'\\n\" +\n                \"\\tOR a.field2 = 2)\\n\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 0, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM test.a\\n\" +\n                \"WHERE a.field0 = 0\\n\" +\n                \"\\tAND (a.field1 LIKE BINARY '1'\\n\" +\n                \"\\t\\tOR a.field2 = 2)\\n\" +\n                \"LIMIT 10\", result);\n    }\n\n    @Test\n    public void test_mysql_5() throws Exception {\n        String sql = \" SELECT * FROM order_biz GROUP BY product_id\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 0, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM order_biz\\n\" +\n                \"GROUP BY product_id\\n\" +\n                \"LIMIT 10\", result);\n    }\n\n    @Test\n    public void test_mysql_6() throws Exception {\n        String sql = \"select * from t limit 10\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 0, 100, true);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"LIMIT 0, 10\", result);\n    }\n\n    @Test\n    public void test_mysql_7() throws Exception {\n        String sql = \"select * from t limit 1000, 1000\";\n        String result = PagerUtils.limit(sql, JdbcConstants.MYSQL, 0, 100, true);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"LIMIT 0, 100\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_mysql_question_placeholder.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelect;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_mysql_question_placeholder {\n    @Test\n    public void testQuestionLimitPlaceholder1() {\n        String sql = \"select * from test_table limit ?\";\n        String expected = \"select * from test_table limit 0, ?\";\n        testQuestionLimitPlaceholderInternal(expected, sql);\n    }\n\n    @Test\n    public void testQuestionLimitPlaceholder2() {\n        String sql = \"select * from test_table limit 0, ?\";\n        String expected = \"select * from test_table limit 0, ?\";\n        testQuestionLimitPlaceholderInternal(expected, sql);\n    }\n\n    private void testQuestionLimitPlaceholderInternal(String expected, String sql) {\n        List<SQLStatement> statements;\n        try {\n            statements = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        } catch (ParserException e) {\n            fail(e.getMessage());\n            return;\n        }\n        if (statements == null || statements.isEmpty()) {\n            fail(\"no sql found!\");\n            return;\n        }\n        if (statements.size() != 1) {\n            fail(\"sql not support count : \" + sql);\n            return;\n        }\n        SQLSelectStatement statement = (SQLSelectStatement) statements.get(0);\n        if (!(statement instanceof SQLSelectStatement)) {\n            fail(\"sql not support count : \" + sql);\n            return;\n        }\n        SQLSelect select = statement.getSelect();\n        PagerUtils.limit(select, JdbcConstants.MYSQL, 0, 200, true);\n        SQLUtils.FormatOption options = new SQLUtils.FormatOption();\n        options.setPrettyFormat(false);\n        options.setUppCase(false);\n        assertEquals(expected, SQLUtils.toSQLString(select, JdbcConstants.MYSQL, options));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_oracle_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_Limit_oracle_0 {\n    @Test\n    public void test_oracle_oderby_0() throws Exception {\n        String sql = \"select * from t order by id\";\n        String result = PagerUtils.limit(sql, JdbcConstants.ORACLE, 0, 10);\n        assertEquals(\"SELECT XX.*, ROWNUM AS RN\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT *\\n\" +\n                \"\\tFROM t\\n\" +\n                \"\\tORDER BY id\\n\" +\n                \") XX\\n\" +\n                \"WHERE ROWNUM <= 10\", result);\n    }\n\n    @Test\n    public void test_oracle_0() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.ORACLE, 0, 10);\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM t\" +\n                \"\\nWHERE ROWNUM <= 10\", result);\n    }\n\n    @Test\n    public void test_oracle_1() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.ORACLE, 10, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT XX.*, ROWNUM AS RN\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT *\\n\" +\n                \"\\t\\tFROM t\\n\" +\n                \"\\t) XX\\n\" +\n                \"\\tWHERE ROWNUM <= 20\\n\" +\n                \") XXX\\n\" +\n                \"WHERE RN > 10\", result);\n    }\n\n    @Test\n    public void test_oracle_2() throws Exception {\n        String sql = \"select * from t\";\n        String result = PagerUtils.limit(sql, JdbcConstants.ORACLE, 20, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT XX.*, ROWNUM AS RN\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT *\\n\" +\n                \"\\t\\tFROM t\\n\" +\n                \"\\t) XX\\n\" +\n                \"\\tWHERE ROWNUM <= 30\\n\" +\n                \") XXX\\n\" +\n                \"WHERE RN > 20\", result);\n    }\n\n    @Test\n    public void test_oracle_3() throws Exception {\n        String sql = \"select id, name, salary from t order by id, name\";\n        String result = PagerUtils.limit(sql, JdbcConstants.ORACLE, 20, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT XX.*, ROWNUM AS RN\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT id, name, salary\\n\" +\n                \"\\t\\tFROM t\\n\" +\n                \"\\t\\tORDER BY id, name\\n\" +\n                \"\\t) XX\\n\" +\n                \"\\tWHERE ROWNUM <= 30\\n\" +\n                \") XXX\\n\" +\n                \"WHERE RN > 20\", result);\n    }\n\n    @Test\n    public void test_oracle_4() throws Exception {\n        String sql = \"SELECT TO_CHAR(ADD_MONTHS(TO_DATE('2014', 'yyyy'), (ROWNUM) * 12), 'yyyy') as YEAR\\n\" +\n                \"FROM DUAL\\n\" +\n                \"CONNECT BY ROWNUM <=\\n\" +\n                \"months_between(to_date(to_char(sysdate,'yyyy'),'yyyy') ,\\n\" +\n                \"to_date('2014', 'yyyy')) / 12\";\n\n        String result = PagerUtils.limit(sql, JdbcConstants.ORACLE, 20, 10);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT XX.*, ROWNUM AS RN\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT TO_CHAR(ADD_MONTHS(TO_DATE('2014', 'yyyy'), ROWNUM * 12), 'yyyy') AS YEAR\\n\" +\n                \"\\t\\tFROM DUAL\\n\" +\n                \"\\t\\tCONNECT BY ROWNUM <= months_between(to_date(to_char(SYSDATE, 'yyyy'), 'yyyy'), to_date('2014', 'yyyy')) / 12\\n\" +\n                \"\\t) XX\\n\" +\n                \"\\tWHERE ROWNUM <= 30\\n\" +\n                \") XXX\\n\" +\n                \"WHERE RN > 20\", result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_Limit_presto_0.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.PagerUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 分页工具类的单元测试，presto SQL类型的\n *\n * @author zhangcanlong\n * @date 2022/02/08\n */\npublic class PagerUtilsTest_Limit_presto_0 {\n    @Test\n    public void test_presto_0() throws Exception {\n        String result = PagerUtils.limit(\"SELECT * FROM test\", DbType.presto, 0, 10);\n        System.out.println(result);\n        String sureResult = \"SELECT *\\n\" + \"FROM test\\n\" + \" LIMIT 10\";\n        assertEquals(sureResult, result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_hasUnorderedLimit.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_hasUnorderedLimit {\n    @Test\n    public void test_false() throws Exception {\n        String sql = \" select * from test t order by id limit 3\";\n        assertFalse(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.MYSQL));\n    }\n\n    @Test\n    public void test_false_1() throws Exception {\n        String sql = \" select * from test t\";\n        assertFalse(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.MYSQL));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        String sql = \" select * from test t limit 3\";\n        assertTrue(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.MYSQL));\n    }\n\n    @Test\n    public void test_true_subquery() throws Exception {\n        String sql = \"select * from(select * from test t limit 3) x\";\n        assertTrue(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.MYSQL));\n    }\n\n    @Test\n    public void test_true_subquery_2() throws Exception {\n        String sql = \"select * from (select * from test t order by id desc) z limit 100\";\n        assertFalse(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.MYSQL));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/PagerUtilsTest_hasUnorderedLimit_oracle.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.PagerUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class PagerUtilsTest_hasUnorderedLimit_oracle {\n    @Test\n    public void test_false() throws Exception {\n        String sql = \"SELECT *\" +\n                \"\\nFROM (SELECT XX.*, ROWNUM AS RN\" +\n                \"\\n\\tFROM (SELECT id, name, salary\" +\n                \"\\n\\t\\tFROM t\" +\n                \"\\n\\t\\tORDER BY id, name\" +\n                \"\\n\\t\\t) XX\" +\n                \"\\n\\tWHERE ROWNUM <= 30\" +\n                \"\\n\\t) XXX\" +\n                \"\\nWHERE RN > 20\";\n        assertFalse(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.ORACLE));\n    }\n\n    @Test\n    public void test_false_1() throws Exception {\n        String sql = \" select * from test t\";\n        assertFalse(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.ORACLE));\n    }\n\n    @Test\n    public void test_true() throws Exception {\n        String sql = \"SELECT *\" +\n                \"\\nFROM t\" +\n                \"\\nWHERE ROWNUM <= 10\";\n        assertTrue(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.ORACLE));\n    }\n\n    @Test\n    public void test_true_1() throws Exception {\n        String sql = \"select * from (select * from t where id > 1 ) where rownum < 1000\";\n        assertTrue(PagerUtils.hasUnorderedLimit(sql, JdbcConstants.ORACLE));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/ReplaceTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLMergeStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class ReplaceTest {\n    @Test\n    public void test_when() {\n        SQLMergeStatement.WhenInsert when = new SQLMergeStatement.WhenInsert();\n        when.addColumn(new SQLIdentifierExpr(\"id\"));\n        when.addColumn(new SQLIdentifierExpr(\"id2\"));\n        SQLIdentifierExpr current_timestamp_identifier1 = new SQLIdentifierExpr(\"current_timestamp\");\n        SQLIdentifierExpr current_timestamp_identifier2 = new SQLIdentifierExpr(\"current_timestamp\");\n        when.addValue(current_timestamp_identifier1);\n        when.addValue(current_timestamp_identifier2);\n        SQLMethodInvokeExpr current_timestamp_method1 = new SQLMethodInvokeExpr(\"current_timestamp\");\n        SQLMethodInvokeExpr current_timestamp_method2 = new SQLMethodInvokeExpr(\"current_timestamp\");\n        SQLUtils.replaceInParent(current_timestamp_identifier1, current_timestamp_method1);\n        SQLUtils.replaceInParent(current_timestamp_identifier2, current_timestamp_method2);\n        assertEquals(current_timestamp_method1, when.getValues().get(0));\n        assertEquals(current_timestamp_method2, when.getValues().get(1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLASTOutputVisitorSplitRefactorTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class SQLASTOutputVisitorSplitRefactorTest {\n    @Test\n    public void test_roundTripStable_forBinaryGroupAndBetween_mysql() {\n        String sql = \"select * from t where (a between 1 and 2) and (b = 3 or b = 4)\";\n        assertRoundTripStable(sql, DbType.mysql);\n    }\n\n    @Test\n    public void test_roundTripStable_forBinaryGroupAndBetween_oracle() {\n        String sql = \"select * from dual where (a = 1 or b = 2) and c between 3 and 4\";\n        assertRoundTripStable(sql, DbType.oracle);\n    }\n\n    @Test\n    public void test_roundTripStable_forComplexDmlBoundary_mysql() {\n        String sql = \"update t set c = c + 1 where (a = 1 or a = 2 or a = 3) and d between 10 and 20\";\n        assertRoundTripStable(sql, DbType.mysql);\n    }\n\n    private void assertRoundTripStable(String sql, DbType dbType) {\n        SQLStatement stmt = SQLUtils.parseSingleStatement(sql, dbType);\n        String first = SQLUtils.toSQLString(stmt, dbType);\n\n        SQLStatement reparsed = SQLUtils.parseSingleStatement(first, dbType);\n        String second = SQLUtils.toSQLString(reparsed, dbType);\n\n        assertEquals(first, second);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLASTVisitorAdapterTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLOver;\nimport com.alibaba.druid.sql.ast.expr.*;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\nimport org.junit.jupiter.api.Test;\n\npublic class SQLASTVisitorAdapterTest {\n    @Test\n    public void test_adapter() throws Exception {\n        SQLASTVisitorAdapter adapter = new SQLASTVisitorAdapter();\n        new SQLBinaryOpExpr().accept(adapter);\n        new SQLInListExpr().accept(adapter);\n        new SQLSelectQueryBlock().accept(adapter);\n        new SQLDropTableStatement().accept(adapter);\n        new SQLCreateTableStatement().accept(adapter);\n        new SQLDeleteStatement().accept(adapter);\n        new SQLCurrentOfCursorExpr().accept(adapter);\n        new SQLInsertStatement().accept(adapter);\n        new SQLUpdateStatement().accept(adapter);\n        new SQLNotNullConstraint().accept(adapter);\n        new SQLMethodInvokeExpr().accept(adapter);\n        new SQLCallStatement().accept(adapter);\n        new SQLSomeExpr().accept(adapter);\n        new SQLAnyExpr().accept(adapter);\n        new SQLAllExpr().accept(adapter);\n        new SQLDefaultExpr().accept(adapter);\n        new SQLCommentStatement().accept(adapter);\n        new SQLDropViewStatement().accept(adapter);\n        new SQLSavePointStatement().accept(adapter);\n        new SQLReleaseSavePointStatement().accept(adapter);\n        new SQLCreateDatabaseStatement().accept(adapter);\n        new SQLAlterTableDropIndex().accept(adapter);\n        new SQLOver().accept(adapter);\n        new SQLWithSubqueryClause().accept(adapter);\n        new SQLAlterTableAlterColumn().accept(adapter);\n        new SQLAlterTableStatement().accept(adapter);\n        new SQLAlterTableDisableConstraint().accept(adapter);\n        new SQLAlterTableEnableConstraint().accept(adapter);\n        new SQLColumnCheck().accept(adapter);\n        new SQLExprHint().accept(adapter);\n        new SQLAlterTableDropConstraint().accept(adapter);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLASTVisitorInheritanceHierarchyTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class SQLASTVisitorInheritanceHierarchyTest {\n    @Test\n    public void test_withEntryDelegatesToTableSourceHooks() {\n        SQLStatement stmt = SQLUtils.parseSingleStatement(\n                \"with cte as (select 1 as id) select * from cte\",\n                DbType.mysql\n        );\n\n        WithEntryDelegationVisitor visitor = new WithEntryDelegationVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(1, visitor.withEntryVisitBySpecificMethod);\n        assertEquals(1, visitor.withEntryVisitByTableSourceHook);\n        assertEquals(1, visitor.withEntryEndVisitByTableSourceHook);\n    }\n\n    private static class WithEntryDelegationVisitor extends SQLASTVisitorAdapter {\n        int withEntryVisitBySpecificMethod;\n        int withEntryVisitByTableSourceHook;\n        int withEntryEndVisitByTableSourceHook;\n\n        @Override\n        public boolean visit(SQLWithSubqueryClause.Entry x) {\n            withEntryVisitBySpecificMethod++;\n            return super.visit(x);\n        }\n\n        @Override\n        public boolean visitTableSource(SQLTableSource x) {\n            if (x instanceof SQLWithSubqueryClause.Entry) {\n                withEntryVisitByTableSourceHook++;\n            }\n            return true;\n        }\n\n        @Override\n        public void endVisitTableSource(SQLTableSource x) {\n            if (x instanceof SQLWithSubqueryClause.Entry) {\n                withEntryEndVisitByTableSourceHook++;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLASTVisitorInterfaceOptimizationTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class SQLASTVisitorInterfaceOptimizationTest {\n    @Test\n    public void test_tableSourceDelegation_forJoinTraversal() {\n        SQLStatement stmt = SQLUtils.parseSingleStatement(\n                \"select * from t1 join t2 on t1.id = t2.id\",\n                DbType.mysql\n        );\n\n        TableSourceDelegationVisitor visitor = new TableSourceDelegationVisitor();\n        stmt.accept(visitor);\n\n        assertTrue(visitor.tableSourceVisitCount >= 3);\n        assertEquals(visitor.tableSourceVisitCount, visitor.tableSourceEndVisitCount);\n    }\n\n    @Test\n    public void test_specificVisitOverride_keepsCompatibility() {\n        SQLStatement stmt = SQLUtils.parseSingleStatement(\"select * from t\", DbType.mysql);\n\n        SpecificVisitCompatibilityVisitor visitor = new SpecificVisitCompatibilityVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(1, visitor.exprTableSourceVisitCount);\n        assertTrue(visitor.tableSourceVisitCount <= 1);\n    }\n\n    private static class TableSourceDelegationVisitor extends SQLASTVisitorAdapter {\n        int tableSourceVisitCount;\n        int tableSourceEndVisitCount;\n\n        @Override\n        public boolean visitTableSource(SQLTableSource x) {\n            tableSourceVisitCount++;\n            return true;\n        }\n\n        @Override\n        public void endVisitTableSource(SQLTableSource x) {\n            tableSourceEndVisitCount++;\n        }\n    }\n\n    private static class SpecificVisitCompatibilityVisitor extends SQLASTVisitorAdapter {\n        int exprTableSourceVisitCount;\n        int tableSourceVisitCount;\n\n        @Override\n        public boolean visit(SQLExprTableSource x) {\n            exprTableSourceVisitCount++;\n            return true;\n        }\n\n        @Override\n        public boolean visitTableSource(SQLTableSource x) {\n            tableSourceVisitCount++;\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLCommentStatementTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.test.TestUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLCommentStatementTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"COMMENT on table t1 IS 'xxx'\";\n\n        SQLStatementParser parser = new SQLStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n\n        String text = TestUtils.outputSqlServer(stmt);\n\n        assertEquals(\"COMMENT ON TABLE t1 IS 'xxx'\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLDialectTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLDialect;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class SQLDialectTest {\n    @Test\n    public void odps() {\n        DbType dbType = DbType.odps;\n        SQLDialect dialect = SQLDialect.of(dbType);\n        assertEquals(dbType, dialect.getDbType());\n        assertTrue(SQLDialect.Quote.isValidQuota(dialect.getQuoteChars(), SQLDialect.Quote.BACK_QUOTE));\n\n        assertFalse(dialect.isKeyword(\"\"));\n        assertTrue(dialect.isKeyword(\"AND\"));\n\n        assertTrue(dialect.isAliasKeyword(\"ALTER\"));\n        assertFalse(dialect.isAliasKeyword(\"AND\"));\n    }\n\n    @Test\n    public void hive() {\n        DbType dbType = DbType.hive;\n        SQLDialect dialect = SQLDialect.of(dbType);\n        assertEquals(dbType, dialect.getDbType());\n\n        assertTrue(dialect.isBuiltInDataType(\"TIMESTAMP\"));\n    }\n\n    @Test\n    public void mysql() {\n        DbType dbType = DbType.mysql;\n        SQLDialect dialect = SQLDialect.of(dbType);\n        assertEquals(dbType, dialect.getDbType());\n\n        assertFalse(dialect.isKeyword(\"\"));\n        assertTrue(dialect.isKeyword(\"zerofill\"));\n    }\n\n    @Test\n    public void oracle() {\n        DbType dbType = DbType.oracle;\n        SQLDialect dialect = SQLDialect.of(dbType);\n        assertEquals(dbType, dialect.getDbType());\n\n        assertFalse(dialect.isKeyword(\"\"));\n        assertTrue(dialect.isKeyword(\"whenever\"));\n    }\n\n    @Test\n    public void postgresql() {\n        DbType dbType = DbType.postgresql;\n        SQLDialect dialect = SQLDialect.of(dbType);\n        assertEquals(dbType, dialect.getDbType());\n        assertTrue(SQLDialect.Quote.isValidQuota(dialect.getQuoteChars(), SQLDialect.Quote.DOUBLE_QUOTE));\n\n        assertFalse(dialect.isKeyword(\"\"));\n        assertTrue(dialect.isKeyword(\"asymmetric\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLJoinTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 03/08/2017.\n */\npublic class SQLJoinTest {\n    @Test\n    public void test_0() throws Exception {\n        SQLSelectStatement stmt = (SQLSelectStatement)\n                SQLUtils.parseStatements(\"select a.* from t_user a inner join t_group b on a.gid = b.id\", JdbcConstants.ORACLE)\n                        .get(0);\n\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n        assertNotNull(queryBlock);\n\n        SQLJoinTableSource join = (SQLJoinTableSource) queryBlock.getFrom();\n        assertTrue(join.match(\"a\", \"b\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLParseExceptionTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.parser.SQLParseException;\nimport org.junit.jupiter.api.Test;\n\n@SuppressWarnings(\"deprecation\")\npublic class SQLParseExceptionTest {\n    @Test\n    public void test_new() throws Exception {\n        new SQLParseException();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLParserUtilsDialectDispatchTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class SQLParserUtilsDialectDispatchTest {\n    private static final String DIALECT = \"mysql\";\n\n    @Test\n    public void test_registeredProvider_hasPriority() {\n        SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n        SQLParserUtils.registerDialectParserProvider(DIALECT, new MarkerProvider());\n        try {\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(\"select 1\", DbType.mysql);\n            assertTrue(parser instanceof MarkerStatementParser);\n        } finally {\n            SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n        }\n    }\n\n    @Test\n    public void test_missingProvider_fallbackToBuiltinDispatch() {\n        SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(\"select 1\", DbType.mysql);\n        assertEquals(MySqlStatementParser.class, parser.getClass());\n    }\n\n    @Test\n    public void test_unregisterProvider_resumeBuiltinDispatch() {\n        SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n        SQLParserUtils.registerDialectParserProvider(DIALECT, new MarkerProvider());\n        SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(\"select 1\", DbType.mysql);\n        assertEquals(MySqlStatementParser.class, parser.getClass());\n    }\n\n    @Test\n    public void test_concurrentRegisterAndLookup_keepValidProviderState() throws ExecutionException, InterruptedException {\n        SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n        ExecutorService executor = Executors.newFixedThreadPool(4);\n        try {\n            List<Callable<Void>> tasks = new ArrayList<Callable<Void>>();\n            tasks.add(new Callable<Void>() {\n                @Override\n                public Void call() {\n                    for (int i = 0; i < 200; i++) {\n                        SQLParserUtils.registerDialectParserProvider(DIALECT, new MarkerProvider());\n                    }\n                    return null;\n                }\n            });\n            tasks.add(new Callable<Void>() {\n                @Override\n                public Void call() {\n                    for (int i = 0; i < 200; i++) {\n                        SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n                    }\n                    return null;\n                }\n            });\n            tasks.add(new Callable<Void>() {\n                @Override\n                public Void call() {\n                    for (int i = 0; i < 400; i++) {\n                        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(\"select 1\", DbType.mysql);\n                        assertNotNull(parser);\n                        assertTrue(parser instanceof MarkerStatementParser || parser instanceof MySqlStatementParser);\n                    }\n                    return null;\n                }\n            });\n\n            List<Future<Void>> futures = executor.invokeAll(tasks);\n            for (Future<Void> future : futures) {\n                future.get();\n            }\n        } finally {\n            SQLParserUtils.unregisterDialectParserProvider(DIALECT);\n            executor.shutdownNow();\n        }\n\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(\"select 1\", DbType.mysql);\n        assertEquals(MySqlStatementParser.class, parser.getClass());\n    }\n\n    private static class MarkerProvider implements SQLParserUtils.DialectParserProvider {\n        @Override\n        public SQLStatementParser createSQLStatementParser(String sql, DbType dbType, SQLParserFeature... features) {\n            return new MarkerStatementParser(sql, dbType);\n        }\n\n        @Override\n        public SQLExprParser createExprParser(String sql, DbType dbType, SQLParserFeature... features) {\n            return null;\n        }\n\n        @Override\n        public Lexer createLexer(String sql, DbType dbType, SQLParserFeature... features) {\n            return null;\n        }\n    }\n\n    private static class MarkerStatementParser extends SQLStatementParser {\n        MarkerStatementParser(String sql, DbType dbType) {\n            super(new SQLExprParser(sql, dbType));\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLParserUtilsTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLType;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class SQLParserUtilsTest {\n    @Test\n    public void test_0() throws Exception {\n        assertEquals(\n                SQLType.SET_PROJECT,\n                SQLParserUtils.getSQLTypeV2(\"setproject odps.sql.allow.fullscan=true;\", DbType.odps));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLResourceTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.apache.commons.io.FileUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.net.URL;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Arrays;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.function.IntFunction;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class SQLResourceTest {\n    protected static final String DELIMITER_LONG = \"------------------------------------------------------------------------------------------------------------------------\";\n    protected static final String DELIMITER_SHORT = \"--------------------\";\n\n    protected final DbType dbType;\n\n    public SQLResourceTest(DbType dbType) {\n        this.dbType = dbType;\n    }\n\n    protected File dir(String path) {\n        URL resource = SQLResourceTest.class.getResource(SQLResourceTest.class.getSimpleName() + \".class\");\n        String classPath = resource.toString();\n        if (classPath.startsWith(\"file:\")) {\n            classPath = classPath.substring(\"file:\".length());\n        }\n\n        String filePath = SQLResourceTest.class.getName().replace('.', '/') + \".class\";\n        assertTrue(classPath.endsWith(filePath));\n        String root = classPath.substring(0, classPath.length() - filePath.length() - 1);\n\n        return new File(new File(root), path);\n    }\n\n    public void fileParse(String path) throws Exception {\n        File dir = dir(path);\n        File[] files = dir.listFiles();\n        Arrays.sort(files, Comparator.comparing(File::getName));\n\n        for (File file : files) {\n            if (file.getName().equals(\".DS_Store\")) {\n                continue;\n            }\n            System.out.println(DELIMITER_LONG);\n            System.out.println(\"## BEGIN parse sql, file \" + file);\n            System.out.println(DELIMITER_LONG);\n\n            String sql = FileUtils.readFileToString(file, StandardCharsets.UTF_8);\n            System.out.println(sql);\n            System.out.println(DELIMITER_SHORT);\n\n            SQLStatementParser stmtParser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n\n            List<SQLStatement> stmtList;\n            try {\n                stmtList = stmtParser.parseStatementList();\n            } catch (ParserException e) {\n                throw new ParserException(\"parse error, file \" + file, e);\n            }\n\n            String output = SQLUtils.toSQLString(stmtList, dbType);\n            System.out.println(output);\n\n            SQLStatementParser stmtParser2 = SQLParserUtils.createSQLStatementParser(output, dbType);\n            List<SQLStatement> stmtList2 = stmtParser2.parseStatementList();\n            String output2 = SQLUtils.toSQLString(stmtList2, dbType);\n\n            assertEquals(output, output2);\n        }\n    }\n\n    public void fileTest(int start, int end, IntFunction<String> pathF) throws Exception {\n        ClassLoader tcl = Thread.currentThread().getContextClassLoader();\n        for (int fileIndex = start; fileIndex < end; fileIndex++) {\n            String path = pathF.apply(fileIndex);\n            URL resource = tcl.getResource(path);\n            if (resource == null) {\n                break;\n            }\n\n            File file = new File(resource.getFile());\n            if (!file.exists()) {\n                break;\n            }\n\n            fileTest(file);\n        }\n    }\n\n    protected void fileTest(File file) throws IOException {\n        System.out.println(DELIMITER_LONG);\n        System.out.println();\n        System.out.println(\"## BEGIN parse sql, file \" + file);\n        System.out.println(DELIMITER_LONG);\n        System.out.println();\n\n        String string = FileUtils.readFileToString(file, StandardCharsets.UTF_8);\n        String[] tests = string.split(DELIMITER_LONG);\n        for (int i = 0; i < tests.length; i++) {\n            String test = tests[i].trim();\n            String[] parts = test.split(DELIMITER_SHORT);\n            assertEquals(2, parts.length);\n\n            String sql = parts[0].trim();\n            String expected = parts[1].trim().replaceAll(\"\\r\\n\", \"\\n\");\n\n            System.out.println();\n            System.out.println(sql);\n            System.out.println();\n            System.out.println(DELIMITER_SHORT + \" \" + file.getName() + \" [\" + (i + 1) + \"/\" + tests.length + \"] \" + dbType);\n            System.out.println();\n\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n            SQLStatement stmt = parser.parseStatement();\n            assertEquals(Token.EOF, parser.getLexer().token(), parser.getLexer().info());\n            String result = SQLUtils.toSQLString(stmt, dbType).trim();\n            assertEquals(expected, result);\n\n            System.out.println(result);\n            System.out.println();\n            System.out.println(DELIMITER_LONG);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLSelectListCacheTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLSelectListCache;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLSelectListCacheTest {\n    @Test\n    public void test_selectListCache() throws Exception {\n        SQLSelectListCache selectListCache = new SQLSelectListCache(JdbcConstants.MYSQL);\n        selectListCache.add(\"SELECT `mtk_p_mg`.`id` AS `id`, `mtk_p_mg`.`gmt_create` AS `gmtCreate`, `mtk_p_mg`.`gmt_modified` AS `gmtModified`, `mtk_p_mg`.`target` AS `target`, `mtk_p_mg`.`msg_id` AS `msgId` , `mtk_p_mg`.`uuid` AS `uuid`, `mtk_p_mg`.`app_key` AS `appKey`, `mtk_p_mg`.`utdid` AS `utdid`, `mtk_p_mg`.`digest` AS `digest`, `mtk_p_mg`.`content` AS `content` , `mtk_p_mg`.`user_info` AS `userInfo`, `mtk_p_mg`.`status` AS `status`, `mtk_p_mg`.`mesg_status` AS `mesgStatus`, `mtk_p_mg`.`start_time` AS `startTime`, `mtk_p_mg`.`expired` AS `expired` , `mtk_p_mg`.`online` AS `online`, `mtk_p_mg`.`gmt_commit` AS `gmtCommit`, `mtk_p_mg`.`extra_info` AS `extraInfo`, `mtk_p_mg`.`auto_commit` AS `autoCommit`, `mtk_p_mg`.`task_id` AS `taskId` , `mtk_p_mg`.`msg_type` AS `msgType`, `mtk_p_mg`.`push_user_token` AS `pushUserToken`, `mtk_p_mg`.`tb_app_device_token` AS `tbAppDeviceToken`, `mtk_p_mg`.`sdk_version` AS `sdkVersion`, `mtk_p_mg`.`biz_ext_info` AS `bizExtInfo` FROM\");\n\n        String sql = \"SELECT `mtk_p_mg`.`id` AS `id`, `mtk_p_mg`.`gmt_create` AS `gmtCreate`, `mtk_p_mg`.`gmt_modified` AS `gmtModified`, `mtk_p_mg`.`target` AS `target`, `mtk_p_mg`.`msg_id` AS `msgId` , `mtk_p_mg`.`uuid` AS `uuid`, `mtk_p_mg`.`app_key` AS `appKey`, `mtk_p_mg`.`utdid` AS `utdid`, `mtk_p_mg`.`digest` AS `digest`, `mtk_p_mg`.`content` AS `content` , `mtk_p_mg`.`user_info` AS `userInfo`, `mtk_p_mg`.`status` AS `status`, `mtk_p_mg`.`mesg_status` AS `mesgStatus`, `mtk_p_mg`.`start_time` AS `startTime`, `mtk_p_mg`.`expired` AS `expired` , `mtk_p_mg`.`online` AS `online`, `mtk_p_mg`.`gmt_commit` AS `gmtCommit`, `mtk_p_mg`.`extra_info` AS `extraInfo`, `mtk_p_mg`.`auto_commit` AS `autoCommit`, `mtk_p_mg`.`task_id` AS `taskId` , `mtk_p_mg`.`msg_type` AS `msgType`, `mtk_p_mg`.`push_user_token` AS `pushUserToken`, `mtk_p_mg`.`tb_app_device_token` AS `tbAppDeviceToken`, `mtk_p_mg`.`sdk_version` AS `sdkVersion`, `mtk_p_mg`.`biz_ext_info` AS `bizExtInfo` FROM mtk_p_mg `mtk_p_mg` FORCE INDEX (idx_targetid) WHERE `mtk_p_mg`.`target` = ? ORDER BY `mtk_p_mg`.`id` DESC LIMIT ?, ?\";\n        SQLStatementParser statementParser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL);\n        statementParser.setSelectListCache(selectListCache);\n\n        List<SQLStatement> statementList = statementParser.parseStatementList();\n        assertEquals(1, statementList.size());\n\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"SELECT `mtk_p_mg`.`id` AS `id`, `mtk_p_mg`.`gmt_create` AS `gmtCreate`, `mtk_p_mg`.`gmt_modified` AS `gmtModified`, `mtk_p_mg`.`target` AS `target`, `mtk_p_mg`.`msg_id` AS `msgId`\\n\" +\n                \"\\t, `mtk_p_mg`.`uuid` AS `uuid`, `mtk_p_mg`.`app_key` AS `appKey`, `mtk_p_mg`.`utdid` AS `utdid`, `mtk_p_mg`.`digest` AS `digest`, `mtk_p_mg`.`content` AS `content`\\n\" +\n                \"\\t, `mtk_p_mg`.`user_info` AS `userInfo`, `mtk_p_mg`.`status` AS `status`, `mtk_p_mg`.`mesg_status` AS `mesgStatus`, `mtk_p_mg`.`start_time` AS `startTime`, `mtk_p_mg`.`expired` AS `expired`\\n\" +\n                \"\\t, `mtk_p_mg`.`online` AS `online`, `mtk_p_mg`.`gmt_commit` AS `gmtCommit`, `mtk_p_mg`.`extra_info` AS `extraInfo`, `mtk_p_mg`.`auto_commit` AS `autoCommit`, `mtk_p_mg`.`task_id` AS `taskId`\\n\" +\n                \"\\t, `mtk_p_mg`.`msg_type` AS `msgType`, `mtk_p_mg`.`push_user_token` AS `pushUserToken`, `mtk_p_mg`.`tb_app_device_token` AS `tbAppDeviceToken`, `mtk_p_mg`.`sdk_version` AS `sdkVersion`, `mtk_p_mg`.`biz_ext_info` AS `bizExtInfo`\\n\" +\n                \"FROM mtk_p_mg `mtk_p_mg` FORCE INDEX (idx_targetid)\\n\" +\n                \"WHERE `mtk_p_mg`.`target` = ?\\n\" +\n                \"ORDER BY `mtk_p_mg`.`id` DESC\\n\" +\n                \"LIMIT ?, ?\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLSelectQueryBlockTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLSelectQueryBlockTest {\n    private final DbType dbType = JdbcConstants.MYSQL;\n    private SchemaRepository repository;\n\n    @BeforeEach\n    protected void setUp() throws Exception {\n        repository = new SchemaRepository(dbType);\n    }\n\n    @Test\n    public void test_findTableSource() throws Exception {\n        repository.console(\"create table t_emp(emp_id bigint, name varchar(20));\");\n        repository.console(\"create table t_org(org_id bigint, name varchar(20));\");\n\n        String sql = \"SELECT emp_id, a.name AS emp_name, org_id, b.name AS org_name\\n\" +\n                \"FROM t_emp a\\n\" +\n                \"\\tINNER JOIN t_org b ON a.emp_id = b.org_id\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n\n        SQLSelectStatement stmt = (SQLSelectStatement) stmtList.get(0);\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n\n        // 大小写不敏感\n        assertNotNull(queryBlock.findTableSource(\"A\"));\n        assertSame(queryBlock.findTableSource(\"a\"), queryBlock.findTableSource(\"A\"));\n\n        assertNull(queryBlock.findTableSourceWithColumn(\"emp_id\"));\n\n        // 使用repository做column resolve\n        repository.resolve(stmt);\n\n        assertNotNull(queryBlock.findTableSourceWithColumn(\"emp_id\"));\n\n        SQLExprTableSource tableSource = (SQLExprTableSource) queryBlock.findTableSourceWithColumn(\"emp_id\");\n        assertNotNull(tableSource.getSchemaObject());\n\n        SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement) tableSource.getSchemaObject().getStatement();\n        assertNotNull(createTableStmt);\n\n        SQLSelectItem selectItem = queryBlock.findSelectItem(\"org_name\");\n        assertNotNull(selectItem);\n        SQLPropertyExpr selectItemExpr = (SQLPropertyExpr) selectItem.getExpr();\n        SQLColumnDefinition column = selectItemExpr.getResolvedColumn();\n        assertNotNull(column);\n        assertEquals(\"name\", column.getName().toString());\n        assertEquals(\"t_org\", (((SQLCreateTableStatement) column.getParent()).getName().toString()));\n\n        assertSame(queryBlock.findTableSource(\"B\"), selectItemExpr.getResolvedTableSource());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLUtilsGetAllTokensTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Test for SQLUtils.getAllTokens method\n */\npublic class SQLUtilsGetAllTokensTest {\n    @Test\n    public void test() {\n        String sql = \"select id, name, age from users where age > 18 and status = 'active'\";\n\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        // Display all tokens with details\n        System.out.println(\"=== All Tokens Encountered During Parsing ===\");\n        System.out.println(\"SQL: \" + sql);\n        System.out.println(\"Total tokens: \" + tokens.size());\n        System.out.println();\n\n        for (int i = 0; i < tokens.size(); i++) {\n            SQLUtils.TokenInfo tokenPair = tokens.get(i);\n            int position = tokenPair.getPos();\n            Token token = tokenPair.getToken();\n            String stringVal = tokenPair.getStringVal();\n\n            // Extract the actual text from SQL for this token\n            if (position < sql.length()) {\n                int endPos = position + 1;\n                while (endPos < sql.length() && !Character.isWhitespace(sql.charAt(endPos))) {\n                    endPos++;\n                }\n            }\n\n            System.out.printf(\"[%2d] Pos: %2d, Token: %-20s, Text: '%s'\",\n                    i, position, token, stringVal);\n\n            System.out.println();\n        }\n\n        System.out.println();\n    }\n    @Test\n    public void test_getAllTokens_mysql() throws Exception {\n        String sql = \"SELECT id, name FROM user WHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n        assertEquals(Token.SELECT, tokens.get(0).getToken());\n\n        // Check if specific tokens exist\n        boolean hasFrom = false;\n        boolean hasWhere = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.FROM) {\n                hasFrom = true;\n            }\n            if (info.getToken() == Token.WHERE) {\n                hasWhere = true;\n            }\n        }\n        assertTrue(hasFrom);\n        assertTrue(hasWhere);\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        // Print tokens for debugging\n        System.out.println(\"MySQL Tokens: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_oracle() throws Exception {\n        String sql = \"SELECT * FROM employees WHERE salary > 5000 ORDER BY name\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.oracle);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n        assertEquals(Token.SELECT, tokens.get(0).getToken());\n\n        boolean hasFrom = false;\n        boolean hasWhere = false;\n        boolean hasOrder = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.FROM) {\n                hasFrom = true;\n            }\n            if (info.getToken() == Token.WHERE) {\n                hasWhere = true;\n            }\n            if (info.getToken() == Token.ORDER) {\n                hasOrder = true;\n            }\n        }\n        assertTrue(hasFrom);\n        assertTrue(hasWhere);\n        assertTrue(hasOrder);\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        System.out.println(\"Oracle Tokens: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_with_string_dbType() throws Exception {\n        String sql = \"INSERT INTO users (id, name) VALUES (1, 'test')\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, \"mysql\");\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n        assertEquals(Token.INSERT, tokens.get(0).getToken());\n\n        boolean hasInto = false;\n        boolean hasValues = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.INTO) {\n                hasInto = true;\n            }\n            if (info.getToken() == Token.VALUES) {\n                hasValues = true;\n            }\n        }\n        assertTrue(hasInto);\n        assertTrue(hasValues);\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        System.out.println(\"String DbType Tokens: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_with_stringVal() throws Exception {\n        String sql = \"SELECT name FROM users WHERE id = 123\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n\n        // Print tokens for debugging\n        System.out.println(\"Tokens with stringVal: \" + tokens);\n\n        // Check for identifier 'name'\n        boolean foundName = false;\n        boolean foundUsers = false;\n        boolean foundId = false;\n        boolean found123 = false;\n\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.IDENTIFIER && \"name\".equals(info.getStringVal())) {\n                foundName = true;\n            }\n            if (info.getToken() == Token.IDENTIFIER && \"users\".equalsIgnoreCase(info.getStringVal())) {\n                foundUsers = true;\n            }\n            if (info.getToken() == Token.IDENTIFIER && \"id\".equals(info.getStringVal())) {\n                foundId = true;\n            }\n            if (info.getToken() == Token.LITERAL_INT && \"123\".equals(info.getStringVal())) {\n                found123 = true;\n            }\n        }\n\n        assertTrue(foundName, \"Should find identifier 'name'\");\n        assertTrue(foundUsers, \"Should find identifier 'users'\");\n        assertTrue(foundId, \"Should find identifier 'id'\");\n        assertTrue(found123, \"Should find literal int '123'\");\n    }\n\n    @Test\n    public void test_getAllTokens_postgresql() throws Exception {\n        String sql = \"UPDATE products SET price = 100 WHERE category = 'electronics'\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.postgresql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n        assertEquals(Token.UPDATE, tokens.get(0).getToken());\n\n        boolean hasSet = false;\n        boolean hasWhere = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.SET) {\n                hasSet = true;\n            }\n            if (info.getToken() == Token.WHERE) {\n                hasWhere = true;\n            }\n        }\n        assertTrue(hasSet);\n        assertTrue(hasWhere);\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        System.out.println(\"PostgreSQL Tokens: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_empty_sql() throws Exception {\n        String sql = \"\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertEquals(0, tokens.size());\n    }\n\n    @Test\n    public void test_getAllTokens_null_sql() throws Exception {\n        String sql = null;\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertEquals(0, tokens.size());\n    }\n\n    @Test\n    public void test_getAllTokens_complex_sql() throws Exception {\n        String sql = \"SELECT u.id, u.name, COUNT(o.id) AS order_count \" +\n                \"FROM users u \" +\n                \"LEFT JOIN orders o ON u.id = o.user_id \" +\n                \"WHERE u.status = 'active' \" +\n                \"GROUP BY u.id, u.name \" +\n                \"HAVING COUNT(o.id) > 5 \" +\n                \"ORDER BY order_count DESC \" +\n                \"LIMIT 10\";\n\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n        assertEquals(Token.SELECT, tokens.get(0).getToken());\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        System.out.println(\"Complex SQL Tokens count: \" + tokens.size());\n        System.out.println(\"Complex SQL Tokens: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_create_table() throws Exception {\n        String sql = \"CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100))\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n        assertEquals(Token.CREATE, tokens.get(0).getToken());\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        System.out.println(\"Create Table Tokens: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_delete() throws Exception {\n        String sql = \"DELETE FROM users WHERE id = 5\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n        assertEquals(Token.DELETE, tokens.get(0).getToken());\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        System.out.println(\"Delete Tokens: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_with_position() throws Exception {\n        String sql = \"SELECT id FROM users WHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify that positions are being captured\n        for (SQLUtils.TokenInfo info : tokens) {\n            // Position should be >= 0\n            assertTrue(info.getPos() >= 0, \"Token position should be >= 0\");\n        }\n\n        // Verify the first token is SELECT\n        assertEquals(Token.SELECT, tokens.get(0).getToken());\n        // Position should be > 0 since it's the position after reading the token\n        assertTrue(tokens.get(0).getPos() > 0, \"First token position should be > 0\");\n\n        // Positions should generally increase\n        // Just verify the last token has a position >= first token\n        assertTrue(tokens.get(tokens.size() - 1).getPos() >= tokens.get(0).getPos(), \"Last token position should be >= first token position\");\n\n        System.out.println(\"Tokens with positions: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_filter_line_comment() throws Exception {\n        String sql = \"SELECT id FROM users -- this is a comment\\nWHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify no LINE_COMMENT tokens in the result\n        for (SQLUtils.TokenInfo info : tokens) {\n            assertFalse(info.getToken() == Token.LINE_COMMENT, \"Should not contain LINE_COMMENT tokens\");\n        }\n\n        // Verify essential tokens are still present\n        boolean hasSelect = false;\n        boolean hasFrom = false;\n        boolean hasWhere = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.SELECT) {\n                hasSelect = true;\n            }\n            if (info.getToken() == Token.FROM) {\n                hasFrom = true;\n            }\n            if (info.getToken() == Token.WHERE) {\n                hasWhere = true;\n            }\n        }\n        assertTrue(hasSelect, \"Should contain SELECT token\");\n        assertTrue(hasFrom, \"Should contain FROM token\");\n        assertTrue(hasWhere, \"Should contain WHERE token\");\n\n        System.out.println(\"Tokens after filtering line comment: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_filter_multi_line_comment() throws Exception {\n        String sql = \"SELECT id /* this is a\\nmulti-line comment */ FROM users WHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify no MULTI_LINE_COMMENT tokens in the result\n        for (SQLUtils.TokenInfo info : tokens) {\n            assertFalse(info.getToken() == Token.MULTI_LINE_COMMENT, \"Should not contain MULTI_LINE_COMMENT tokens\");\n        }\n\n        // Verify essential tokens are still present\n        boolean hasSelect = false;\n        boolean hasFrom = false;\n        boolean hasWhere = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.SELECT) {\n                hasSelect = true;\n            }\n            if (info.getToken() == Token.FROM) {\n                hasFrom = true;\n            }\n            if (info.getToken() == Token.WHERE) {\n                hasWhere = true;\n            }\n        }\n        assertTrue(hasSelect, \"Should contain SELECT token\");\n        assertTrue(hasFrom, \"Should contain FROM token\");\n        assertTrue(hasWhere, \"Should contain WHERE token\");\n\n        System.out.println(\"Tokens after filtering multi-line comment: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_filter_hint() throws Exception {\n        String sql = \"SELECT /*+ INDEX(users idx_age) */ id FROM users WHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify no HINT tokens in the result\n        for (SQLUtils.TokenInfo info : tokens) {\n            assertFalse(info.getToken() == Token.HINT, \"Should not contain HINT tokens\");\n        }\n\n        // Verify essential tokens are still present\n        boolean hasSelect = false;\n        boolean hasFrom = false;\n        boolean hasWhere = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.SELECT) {\n                hasSelect = true;\n            }\n            if (info.getToken() == Token.FROM) {\n                hasFrom = true;\n            }\n            if (info.getToken() == Token.WHERE) {\n                hasWhere = true;\n            }\n        }\n        assertTrue(hasSelect, \"Should contain SELECT token\");\n        assertTrue(hasFrom, \"Should contain FROM token\");\n        assertTrue(hasWhere, \"Should contain WHERE token\");\n\n        System.out.println(\"Tokens after filtering hint: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_filter_mixed_comments() throws Exception {\n        String sql = \"SELECT id, -- select id column\\n\" +\n                \"       name /* and name column */ FROM users -- from users table\\n\" +\n                \"WHERE age > 18 /* age filter */\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify no comment tokens in the result\n        for (SQLUtils.TokenInfo info : tokens) {\n            assertFalse(info.getToken() == Token.LINE_COMMENT, \"Should not contain LINE_COMMENT tokens\");\n            assertFalse(info.getToken() == Token.MULTI_LINE_COMMENT, \"Should not contain MULTI_LINE_COMMENT tokens\");\n            assertFalse(info.getToken() == Token.HINT, \"Should not contain HINT tokens\");\n        }\n\n        // Verify essential tokens are still present\n        boolean hasSelect = false;\n        boolean hasFrom = false;\n        boolean hasWhere = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.SELECT) {\n                hasSelect = true;\n            }\n            if (info.getToken() == Token.FROM) {\n                hasFrom = true;\n            }\n            if (info.getToken() == Token.WHERE) {\n                hasWhere = true;\n            }\n        }\n        assertTrue(hasSelect, \"Should contain SELECT token\");\n        assertTrue(hasFrom, \"Should contain FROM token\");\n        assertTrue(hasWhere, \"Should contain WHERE token\");\n\n        System.out.println(\"Tokens after filtering mixed comments: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_oracle_with_comments() throws Exception {\n        String sql = \"SELECT * FROM employees -- get all employees\\n\" +\n                \"WHERE salary > 5000 /* high salary */ ORDER BY name\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.oracle);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify no comment tokens in the result\n        for (SQLUtils.TokenInfo info : tokens) {\n            assertFalse(info.getToken() == Token.LINE_COMMENT, \"Should not contain LINE_COMMENT tokens\");\n            assertFalse(info.getToken() == Token.MULTI_LINE_COMMENT, \"Should not contain MULTI_LINE_COMMENT tokens\");\n        }\n\n        assertEquals(Token.SELECT, tokens.get(0).getToken());\n        assertEquals(Token.EOF, tokens.get(tokens.size() - 1).getToken());\n\n        System.out.println(\"Oracle tokens after filtering comments: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_keepComments_true() throws Exception {\n        String sql = \"SELECT id FROM users -- this is a comment\\nWHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql, true);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify LINE_COMMENT token is present when keepComments=true\n        boolean hasLineComment = false;\n        for (SQLUtils.TokenInfo info : tokens) {\n            if (info.getToken() == Token.LINE_COMMENT) {\n                hasLineComment = true;\n                break;\n            }\n        }\n        assertTrue(hasLineComment, \"Should contain LINE_COMMENT token when keepComments=true\");\n\n        System.out.println(\"Tokens with keepComments=true: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_keepComments_false() throws Exception {\n        String sql = \"SELECT id FROM users -- this is a comment\\nWHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokens = SQLUtils.getAllTokens(sql, DbType.mysql, false);\n\n        assertNotNull(tokens);\n        assertTrue(tokens.size() > 0);\n\n        // Verify no LINE_COMMENT tokens when keepComments=false\n        for (SQLUtils.TokenInfo info : tokens) {\n            assertFalse(info.getToken() == Token.LINE_COMMENT, \"Should not contain LINE_COMMENT tokens when keepComments=false\");\n        }\n\n        System.out.println(\"Tokens with keepComments=false: \" + tokens);\n    }\n\n    @Test\n    public void test_getAllTokens_keepComments_multiLine() throws Exception {\n        String sql = \"SELECT id /* comment */ FROM users WHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokensWithComments = SQLUtils.getAllTokens(sql, DbType.mysql, true);\n        List<SQLUtils.TokenInfo> tokensWithoutComments = SQLUtils.getAllTokens(sql, DbType.mysql, false);\n\n        assertNotNull(tokensWithComments);\n        assertNotNull(tokensWithoutComments);\n\n        // Verify tokensWithComments contains MULTI_LINE_COMMENT\n        boolean hasMultiLineComment = false;\n        for (SQLUtils.TokenInfo info : tokensWithComments) {\n            if (info.getToken() == Token.MULTI_LINE_COMMENT) {\n                hasMultiLineComment = true;\n                break;\n            }\n        }\n        assertTrue(hasMultiLineComment, \"Should contain MULTI_LINE_COMMENT when keepComments=true\");\n\n        // Verify tokensWithoutComments does not contain MULTI_LINE_COMMENT\n        for (SQLUtils.TokenInfo info : tokensWithoutComments) {\n            assertFalse(info.getToken() == Token.MULTI_LINE_COMMENT, \"Should not contain MULTI_LINE_COMMENT when keepComments=false\");\n        }\n\n        // Verify tokensWithComments has more tokens than tokensWithoutComments\n        assertTrue(tokensWithComments.size() > tokensWithoutComments.size(), \"Token list with comments should be larger\");\n\n        System.out.println(\"Tokens with comments count: \" + tokensWithComments.size());\n        System.out.println(\"Tokens without comments count: \" + tokensWithoutComments.size());\n    }\n\n    @Test\n    public void test_getAllTokens_keepComments_hint() throws Exception {\n        String sql = \"SELECT /*+ INDEX(users idx_age) */ id FROM users WHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokensWithHints = SQLUtils.getAllTokens(sql, DbType.mysql, true);\n        List<SQLUtils.TokenInfo> tokensWithoutHints = SQLUtils.getAllTokens(sql, DbType.mysql, false);\n\n        assertNotNull(tokensWithHints);\n        assertNotNull(tokensWithoutHints);\n\n        // Verify tokensWithHints contains HINT\n        boolean hasHint = false;\n        for (SQLUtils.TokenInfo info : tokensWithHints) {\n            if (info.getToken() == Token.HINT) {\n                hasHint = true;\n                break;\n            }\n        }\n        assertTrue(hasHint, \"Should contain HINT when keepComments=true\");\n\n        // Verify tokensWithoutHints does not contain HINT\n        for (SQLUtils.TokenInfo info : tokensWithoutHints) {\n            assertFalse(info.getToken() == Token.HINT, \"Should not contain HINT when keepComments=false\");\n        }\n\n        System.out.println(\"Tokens with hint: \" + tokensWithHints);\n        System.out.println(\"Tokens without hint: \" + tokensWithoutHints);\n    }\n\n    @Test\n    public void test_getAllTokens_keepComments_stringDbType() throws Exception {\n        String sql = \"SELECT id FROM users -- comment\\nWHERE age > 18\";\n        List<SQLUtils.TokenInfo> tokensWithComments = SQLUtils.getAllTokens(sql, \"mysql\", true);\n        List<SQLUtils.TokenInfo> tokensWithoutComments = SQLUtils.getAllTokens(sql, \"mysql\", false);\n\n        assertNotNull(tokensWithComments);\n        assertNotNull(tokensWithoutComments);\n\n        // Verify keepComments parameter works with String dbType\n        boolean hasLineComment = false;\n        for (SQLUtils.TokenInfo info : tokensWithComments) {\n            if (info.getToken() == Token.LINE_COMMENT) {\n                hasLineComment = true;\n                break;\n            }\n        }\n        assertTrue(hasLineComment, \"Should contain LINE_COMMENT when keepComments=true with String dbType\");\n\n        for (SQLUtils.TokenInfo info : tokensWithoutComments) {\n            assertFalse(info.getToken() == Token.LINE_COMMENT, \"Should not contain LINE_COMMENT when keepComments=false with String dbType\");\n        }\n\n        System.out.println(\"String dbType - Tokens with comments: \" + tokensWithComments.size());\n        System.out.println(\"String dbType - Tokens without comments: \" + tokensWithoutComments.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SQLUtilsLevenshteinTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsLevenshteinTest {\n    @Test\n    public void test_identicalSQL() {\n        String sql1 = \"SELECT id, name FROM users WHERE age > 18\";\n        String sql2 = \"SELECT id, name FROM users WHERE age > 18\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        assertEquals(0, distance, \"Identical SQL should have distance 0\");\n    }\n\n    @Test\n    public void test_differentIdentifiers() {\n        String sql1 = \"SELECT id, name FROM users WHERE age > 18\";\n        String sql2 = \"SELECT id, name FROM customers WHERE age > 18\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // 'users' vs 'customers' - should count as 1 difference\n        assertTrue(distance > 0, \"Different table names should have distance > 0\");\n        assertEquals(1, distance, \"Should have distance of 1 for one different identifier\");\n    }\n\n    @Test\n    public void test_differentLiterals() {\n        String sql1 = \"SELECT * FROM users WHERE age > 18\";\n        String sql2 = \"SELECT * FROM users WHERE age > 21\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // 18 vs 21 - should count as 1 difference\n        assertEquals(1, distance, \"Different literal values should have distance of 1\");\n    }\n\n    @Test\n    public void test_insertionDeletion() {\n        String sql1 = \"SELECT id FROM users\";\n        String sql2 = \"SELECT id, name FROM users\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // Added ', name' - should be 2 tokens (COMMA and IDENTIFIER)\n        assertEquals(2, distance, \"Insertion should increase distance\");\n    }\n\n    @Test\n    public void test_completelyDifferentSQL() {\n        String sql1 = \"SELECT * FROM users\";\n        String sql2 = \"DELETE FROM products WHERE id = 1\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // Completely different SQL statements\n        assertTrue(distance > 5, \"Completely different SQL should have large distance\");\n    }\n\n    @Test\n    public void test_sameStructureDifferentValues() {\n        String sql1 = \"SELECT id, name, age FROM users WHERE status = 'active'\";\n        String sql2 = \"SELECT id, name, age FROM users WHERE status = 'inactive'\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // Only 'active' vs 'inactive' is different\n        assertEquals(1, distance, \"Only string value difference should have distance of 1\");\n    }\n\n    @Test\n    public void test_crossDialect() {\n        String sql1 = \"SELECT id, name FROM users WHERE age > 18\";\n        String sql2 = \"SELECT id, name FROM users WHERE age > 18\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.oracle);\n\n        // Same SQL, different dialects should still have distance 0\n        assertEquals(0, distance, \"Same SQL with different dialects should have distance 0\");\n    }\n\n    @Test\n    public void test_multipleChanges() {\n        String sql1 = \"SELECT id FROM users WHERE age > 18 AND status = 'active'\";\n        String sql2 = \"SELECT name FROM customers WHERE age > 21 AND status = 'inactive'\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // Changes: id->name, users->customers, 18->21, active->inactive\n        // That's 4 token differences\n        assertEquals(4, distance, \"Multiple changes should accumulate\");\n    }\n\n    @Test\n    public void test_emptySQL() {\n        String sql1 = \"\";\n        String sql2 = \"SELECT * FROM users\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // Empty SQL should have distance equal to number of tokens in second SQL\n        assertTrue(distance > 0, \"Empty SQL should have positive distance\");\n    }\n\n    @Test\n    public void test_whitespaceVariation() {\n        String sql1 = \"SELECT id,name FROM users\";\n        String sql2 = \"SELECT   id  ,  name   FROM   users\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // Whitespace should not matter - tokens are the same\n        assertEquals(0, distance, \"Whitespace variation should not affect distance\");\n    }\n\n    @Test\n    public void test_caseVariation() {\n        String sql1 = \"SELECT id FROM users\";\n        String sql2 = \"select id from users\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        // Keywords are case-insensitive in SQL\n        assertEquals(0, distance, \"Case variation in keywords should not affect distance\");\n    }\n\n    @Test\n    public void test_complexQuery() {\n        String sql1 = \"SELECT u.id, u.name, o.total \" +\n                \"FROM users u JOIN orders o ON u.id = o.user_id \" +\n                \"WHERE u.age > 18 AND o.status = 'completed'\";\n\n        String sql2 = \"SELECT u.id, u.name, o.total \" +\n                \"FROM users u JOIN orders o ON u.id = o.user_id \" +\n                \"WHERE u.age > 18 AND o.status = 'completed'\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        assertEquals(0, distance, \"Identical complex queries should have distance 0\");\n    }\n\n    @Test\n    public void test_numericLiterals() {\n        String sql1 = \"SELECT * FROM products WHERE price > 100.50\";\n        String sql2 = \"SELECT * FROM products WHERE price > 100.50\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        assertEquals(0, distance, \"Same numeric literals should have distance 0\");\n    }\n\n    @Test\n    public void test_differentNumericLiterals() {\n        String sql1 = \"SELECT * FROM products WHERE price > 100.50\";\n        String sql2 = \"SELECT * FROM products WHERE price > 200.75\";\n\n        int distance = SQLUtils.calculateTokenLevenshteinDistance(sql1, DbType.mysql, sql2, DbType.mysql);\n\n        assertEquals(1, distance, \"Different numeric literals should have distance 1\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SchemaTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\npublic class SchemaTest {\n    @Test\n    public void test_schema() {\n        SchemaRepository repository = new SchemaRepository(DbType.gaussdb);\n        repository.acceptDDL(\"create table test.test(a int) partition by list (dt) (partition p1 values(20251111))\");\n        String sql = \"alter table test.test truncate partition for (to_date('${day}')-1);\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.gaussdb);\n        SQLStatement sqlStatement = parser.parseStatement();\n        repository.accept(sqlStatement);\n        assertNotNull(((SQLAlterTableStatement) sqlStatement).getTableSource().getSchemaObject());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/ShardingUnwrapTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 13/08/2017.\n */\npublic class ShardingUnwrapTest {\n    SQLASTOutputVisitor visitor = new SQLASTOutputVisitor(new StringBuilder());\n\n    @Test\n    public void test_sharding_unwrap() throws Exception {\n        assertEquals(\"t_like_count\", visitor.unwrapShardingTable(\"t_like_count0057\"));\n        assertEquals(\"t_like_count\", visitor.unwrapShardingTable(\"`t_like_count0057`\"));\n        assertEquals(\"t_like_count\", visitor.unwrapShardingTable(\"\\\"t_like_count0057\\\"\"));\n    }\n\n    @Test\n    public void test_sharding_unwrap_2() throws Exception {\n        assertEquals(\"t_like_count\", visitor.unwrapShardingTable(\"t_like_count_0057\"));\n        assertEquals(\"t_like_count\", visitor.unwrapShardingTable(\"`t_like_count_0057`\"));\n        assertEquals(\"t_like_count\", visitor.unwrapShardingTable(\"\\\"t_like_count_0057\\\"\"));\n    }\n\n    @Test\n    public void test_sharding_unwrap_3() throws Exception {\n        assertEquals(\"fc_sms\", visitor.unwrapShardingTable(\"fc_sms_0011_201704\"));\n    }\n\n    @Test\n    public void test_sharding_unwrap_4() throws Exception {\n        assertEquals(\"ads_tb_sycm_eff_slr_itm_1d_s015_p\", visitor.unwrapShardingTable(\"ads_tb_sycm_eff_slr_itm_1d_s015_p033\"));\n    }\n\n    @Test\n    public void test_sharding_unwrap_5() throws Exception {\n        assertEquals(\"t\", visitor.unwrapShardingTable(\"t_00\"));\n        assertEquals(\"t\", visitor.unwrapShardingTable(\"t_1\"));\n    }\n    //\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SimplifyTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLName;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SimplifyTest {\n    @Test\n    public void test_simplify_column() throws Exception {\n        SQLColumnDefinition column = new SQLColumnDefinition();\n\n        column.setName(\"`a`\");\n\n        SQLName name_0 = column.getName();\n        column.simplify();\n\n        assertNotSame(name_0, column.getName());\n        assertEquals(\"a\", column.getName().getSimpleName());\n\n        name_0 = column.getName();\n        column.simplify();\n        assertSame(name_0, column.getName());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SourceLocationTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class SourceLocationTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"\\nselect getdate()\";\n        DbType[] dbTypes = new DbType[]{DbType.mysql, DbType.oracle, DbType.db2, DbType.odps};\n        for (DbType dbType : dbTypes) {\n            SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils\n                    .parseSingleStatement(\n                            sql,\n                            dbType,\n                            SQLParserFeature.KeepSourceLocation\n                    );\n\n            SQLExpr expr = stmt.getSelect().getQueryBlock().getSelectList().get(0).getExpr();\n            assertEquals(2, expr.getSourceLine());\n            assertEquals(8, expr.getSourceColumn(), dbType.name());\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SplitTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 04/06/2017.\n */\npublic class SplitTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"((1 + 2) + (3 + 4) + 5) + ((6 + 7) + (8 + 9) + 10)\";\n//        sql = \"(1 + 2) + (3 + 4)\";\n        SQLBinaryOpExpr expr = (SQLBinaryOpExpr) new SQLExprParser(sql).expr();\n\n        List<SQLExpr> items = SQLBinaryOpExpr.split(expr);\n\n        System.out.println(sql);\n        System.out.println(items);\n\n        assertEquals(10, items.size());\n        for (int i = 0; i < 10; ++i) {\n            SQLExpr item = items.get(i);\n            assertEquals(Integer.toString(i + 1), SQLUtils.toSQLString(item));\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SplitTest2.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 04/06/2017.\n */\npublic class SplitTest2 {\n    @Test\n    public void test_0() throws Exception {\n        int count = 10;\n        String sql = \"\";\n\n        for (int i = 0; i < count; ++i) {\n            if (sql.length() != 0) {\n                sql += \" + \";\n            }\n\n            sql += Integer.toString(i);\n        }\n//        sql = \"(1 + 2) + (3 + 4)\";\n        SQLBinaryOpExpr expr = (SQLBinaryOpExpr) new SQLExprParser(sql).expr();\n\n        List<SQLExpr> items = SQLBinaryOpExpr.split(expr);\n\n        System.out.println(sql);\n        System.out.println(items);\n\n        assertEquals(count, items.size());\n        for (int i = 0; i < count; ++i) {\n            SQLExpr item = items.get(i);\n            assertEquals(Integer.toString(i), SQLUtils.toSQLString(item));\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/SymbolTableTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.parser.SymbolTable;\nimport com.alibaba.druid.util.FnvHash;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SymbolTableTest {\n    @Test\n    public void test_symbols() throws Exception {\n        SymbolTable symbols = new SymbolTable(65535);\n\n        String[] strings = new String[10];\n        for (int i = 0; i < strings.length; ++i) {\n            String str = \"abc\" + i;\n            strings[i] = str;\n            symbols.addSymbol(str, FnvHash.fnv1a_64(str));\n        }\n\n        for (int i = 0; i < strings.length; ++i) {\n            String str = strings[i];\n            long hash = FnvHash.fnv1a_64(str);\n            String symbol = symbols.findSymbol(hash);\n            assertSame(str, symbol);\n        }\n        {\n            byte[] bytes = \"kkk#abc0#aa\".getBytes();\n            long hash = FnvHash.fnv1a_64(bytes, 4, 8);\n            String symbol = symbols.addSymbol(bytes, 4, 8, hash);\n            assertSame(strings[0], symbol);\n        }\n\n        byte[] bytes = \"xab#time:3333\".getBytes();\n        System.out.println(indexOfTime(bytes, 1));\n        System.out.println(\"xab#time:3333\".indexOf(\"#time\"));\n    }\n\n    public static int indexOfTime(byte[] bytes, int fromIndex) {\n        int end = bytes.length - 5;\n        for (int i = fromIndex; i < end; ++i) {\n            if (bytes[i] == '#'\n                    && bytes[i + 1] == 't'\n                    && bytes[i + 2] == 'i'\n                    && bytes[i + 3] == 'm'\n                    && bytes[i + 4] == 'e') {\n                return i;\n            }\n        }\n\n        return -1;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/TestNewSpout.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.parser.SymbolTable;\nimport com.alibaba.druid.util.FnvHash;\n\nimport java.nio.charset.Charset;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * Created by yunning on 16/7/10.\n */\npublic class TestNewSpout {\n    public static int indexOf_nsharp(byte[] bytes, int fromIndex) {\n        int end = bytes.length - 2;\n        for (int i = fromIndex; i < end; ++i) {\n            if (bytes[i] == '\\n'\n                    && bytes[i + 1] == '#') {\n                return i;\n            }\n        }\n\n        return -1;\n    }\n\n    public static int indexOf_nReturn(byte[] bytes, int fromIndex) {\n        for (int i = fromIndex; i < bytes.length; ++i) {\n            if (bytes[i] == '\\n') {\n                return i;\n            }\n        }\n\n        return -1;\n    }\n\n    public static int indexOfTime(byte[] bytes, int fromIndex) {\n        int end = bytes.length - 5;\n        for (int i = fromIndex; i < end; ++i) {\n            if (bytes[i] == '#'\n                    && bytes[i + 1] == 't'\n                    && bytes[i + 2] == 'i'\n                    && bytes[i + 3] == 'm'\n                    && bytes[i + 4] == 'e') {\n                return i;\n            }\n        }\n\n        return -1;\n    }\n\n    public static final SymbolTable dbSymbols = new SymbolTable(1024 * 256);\n\n    public static String substring(byte[] bytes, int from, int to) {\n        int newLength = to - from;\n        byte[] copy = new byte[newLength];\n        System.arraycopy(bytes, from, copy, 0, newLength);\n        return new String(copy, Charset.forName(\"UTF-8\"));\n    }\n\n    public static void main(String[] args) throws Exception {\n        final String datass = \"#time:1470191976686205\\n\" +\n                \"#user@host:monitor[monitor] @ [127.0.0.1]\\n\" +\n                \"#db:test\\n\" +\n                \"#table_name:aa\\n\" +\n                \"set session time_zone='+08:00';\\n\" +\n                \"#query_time:0.000028123456789987654321\\n\" +\n                \"#lock_time:0.000000\\n\" +\n                \"#rows_sent:0\\n\" +\n                \"#rows_examined:0\\n\" +\n                \"#rows_affected:0\\n\" +\n                \"#innodb_pages_read:1\\n\" +\n                \"#innodb_pages_io_read:2\\n\" +\n                \"#id:55438\\n\" +\n                \"#time:1470191976686207\\n\" +\n                \"#user@host:monitor[monitor] @ [127.0.0.1]\\n\" +\n                \"#db:test\\n\" +\n                \"#table_name:aa\\n\" +\n                \"#time:1470191976686206\\n\" +\n                \"#user@host:monitor[monitor] @ [127.0.0.1]\\n\" +\n                \"#db:test\\n\" +\n                \"#table_name:aa\\n\" +\n                \"set session time_zone='+0800';\\n\" +\n                \"#query_time:0.000028123456789987654322\\n\" +\n                \"#lock_time:0.000000\\n\" +\n                \"#rows_sent:0\\n\" +\n                \"#rows_examined:0\\n\" +\n                \"#rows_affected:0\\n\" +\n                \"#innodb_pages_read:0\\n\" +\n                \"#innodb_pages_io_read:0\\n\" +\n                \"#id:123\";\n\n        byte[] datas = datass.getBytes();\n        long start = System.currentTimeMillis();\n        for (int i = 0; i < 1; i++) {\n            final int len = datas.length;\n            int offset = indexOfTime(datas, 0);\n            long now = System.nanoTime();\n            while (offset != -1) {\n                int rowOffset = offset;\n                int k = 0;\n                final int[] offsets = new int[12];\n                boolean isNoFirst = false;\n                while (rowOffset != -1 && k < 12) {\n                    if (isNoFirst && rowOffset + 5 <= len - 1) {\n                        if (datas[rowOffset + 2] == 't' &&\n                                datas[rowOffset + 3] == 'i' &&\n                                datas[rowOffset + 4] == 'm' &&\n                                datas[rowOffset + 5] == 'e') {\n                            break;\n                        }\n                    }\n                    offsets[k] = rowOffset;\n                    rowOffset = indexOf_nsharp(datas, rowOffset + 1);\n                    k = k + 1;\n                    isNoFirst = true;\n                }\n                offset = rowOffset == -1 ? -1 : indexOfTime(datas, rowOffset + 1);\n                if (k < 12) {\n                    continue;\n                }\n                SqlInfo sqlInfo = new SqlInfo();\n                //  sqlInfo.setHostName(hostName);\n\n                boolean isError = false;\n                String sql = null;\n\n                //time\n                int currItemOffset = offsets[0];\n                int nextItemOffset = offsets[1];\n                           /* String item = datas.substring(currItemOffset + 6, nextItemOffset);\n                            long itemTime = Long.parseLong(item);*/\n                long itemTime = MathUtil.str2Long(datas, currItemOffset + 6, nextItemOffset);\n                System.out.println(\"TIME : \" + itemTime);\n                if (itemTime < 0 || itemTime > 2000000000000000L) {\n                    // Handle invalid time value\n                }\n                sqlInfo.setTime(itemTime);\n\n                //user@host\n                currItemOffset = offsets[1];\n                nextItemOffset = offsets[2];\n                String item = substring(datas, currItemOffset + 12, nextItemOffset);\n                System.out.println(\"user@host : \" + item);\n//                sqlInfo.setUserHost(item);\n\n                //db\n                currItemOffset = offsets[2];\n                nextItemOffset = offsets[3];\n                int dbOffset = currItemOffset + 5;\n                int dbLen = nextItemOffset - dbOffset;\n                long dbHash = FnvHash.fnv1a_64(datas, dbOffset, nextItemOffset);\n                String db = dbSymbols.addSymbol(datas, dbOffset, dbLen, dbHash);\n\n                //  String db = substring(datas, currItemOffset + 5, nextItemOffset);\n                System.out.println(\"db : \" + db);\n                if (dbLen > 0 && SqlUtil.filterDbs.indexOf(db) != -1) {\n//                    sqlInfo.setNotValiDB(true);\n                } else {\n                    // Handle the valid case\n                }\n\n                //table_name\n                currItemOffset = offsets[3];\n                nextItemOffset = offsets[4];\n                int tsqlPos = currItemOffset + 13;\n                int idx2 = indexOf_nReturn(datas, tsqlPos);\n                String table = substring(datas, tsqlPos, idx2);\n                sql = substring(datas, idx2 + 1, nextItemOffset);\n                System.out.println(\"table : \" + table + \" : \" + sql);\n\n                int totalLen = sql.length();\n                if (totalLen < 9 ||\n                        totalLen >= 8000) {\n                    // sqlInfo.setParseRes(0);\n                } else {\n                    // Handle the valid case\n                }\n\n                //query_time\n                currItemOffset = offsets[4];\n                nextItemOffset = offsets[5];\n                int rtBound = Math.min(nextItemOffset - currItemOffset, 24);\n                double itemRt = MathUtil.str2Double(datas, currItemOffset + 13, currItemOffset + rtBound);\n                sqlInfo.setQueryTime(itemRt);\n\n                //lock_time\n                currItemOffset = offsets[5];\n                nextItemOffset = offsets[6];\n                int lockTimeBound = Math.min(nextItemOffset - currItemOffset, 23);\n                double itemLockTime = MathUtil.str2Double(datas, currItemOffset + 12, currItemOffset + lockTimeBound);\n                sqlInfo.setLockTime(itemLockTime);\n\n                //rows_sent\n                currItemOffset = offsets[6];\n                nextItemOffset = offsets[7];\n                long itemRowsSent = MathUtil.str2Long(datas, currItemOffset + 12, nextItemOffset);\n                if (itemRowsSent < 0 || itemRowsSent > 1000000000) {\n                    // Handle invalid value\n                }\n//                sqlInfo.setRowsSent(itemRowsSent);\n\n                //rows_examined\n                currItemOffset = offsets[7];\n                nextItemOffset = offsets[8];\n                long itemRowsExam = MathUtil.str2Long(datas, currItemOffset + 16, nextItemOffset);\n                if (itemRowsExam < 0 || itemRowsExam > 1000000000) {\n                    // Handle invalid value\n                }\n//                sqlInfo.setRowsExamined(itemRowsExam);\n\n                //rows_affected\n                currItemOffset = offsets[8];\n                nextItemOffset = offsets[9];\n                long itemRowsAffected = MathUtil.str2Long(datas, currItemOffset + 16, nextItemOffset);\n                if (itemRowsAffected < 0 || itemRowsAffected > 1000000000) {\n                    // Handle invalid value\n                }\n                sqlInfo.setRowsAffected(itemRowsAffected);\n\n                //innodb_pages_read\n                currItemOffset = offsets[9];\n                nextItemOffset = offsets[10];\n                long itemPageRead = MathUtil.str2Long(datas, currItemOffset + 20, nextItemOffset);\n                if (itemPageRead < 0 || itemPageRead > 1000000000) {\n                    // Handle invalid value\n                }\n                sqlInfo.setInnodbPagesRead(itemPageRead);\n\n                //innodb_pages_io_read\n                currItemOffset = offsets[10];\n                nextItemOffset = offsets[11];\n                long itemPageIORead = MathUtil.str2Long(datas, currItemOffset + 23, nextItemOffset);\n                if (itemPageIORead < 0 || itemPageIORead > 1000000000) {\n                    // Handle invalid value\n                }\n//                sqlInfo.setInnodbPagesIoRead(itemPageIORead);\n                // currItemOffset = nextItemOffset;\n\n                            /*nextItemOffset = datas.indexOf(\"\\n#\", currItemOffset + 1);\n                            if (nextItemOffset >= end) {\n                                return null;\n                            }\n                            itemEnd = nextItemOffset == -1 ? end : nextItemOffset;\n                            item = datas.substring(currItemOffset + 1, itemEnd);\n                            sqlInfo.setId(Long.parseLong(item.trim().substring(4)));\n                            num++;*/\n                // sqlInfo.setId(0);\n            }\n\n        }\n\n        System.out.println(System.currentTimeMillis() - start);\n    }\n\n    static class SqlInfo {\n        private long innodbPagesRead;\n        private long time;\n        private double queryTime;\n        private double lockTime;\n        public long rowsAffected;\n\n        public long getInnodbPagesRead() {\n            return innodbPagesRead;\n        }\n\n        public void setInnodbPagesRead(long innodbPagesRead) {\n            this.innodbPagesRead = innodbPagesRead;\n        }\n\n        public long getTime() {\n            return time;\n        }\n\n        public void setTime(long time) {\n            this.time = time;\n        }\n\n        public void setQueryTime(double queryTime) {\n            this.queryTime = queryTime;\n        }\n\n        public void setLockTime(double lockTime) {\n            this.lockTime = lockTime;\n        }\n\n        public void setRowsAffected(long rowsAffected) {\n            this.rowsAffected = rowsAffected;\n        }\n    }\n\n    static class MathUtil {\n        public static long str2Long(byte[] data, int start, int end) {\n            long value = 0;\n            for (int i = start; i < end; ++i) {\n                byte ch = data[i];\n                if (ch == '.') {\n                    break;\n                }\n                int digit = data[i] - '0';\n                value = value * 10 + digit;\n            }\n            return value;\n        }\n\n        public static double str2Double(byte[] data, int start, int end) {\n            long value = 0;\n            long power = 0;\n            for (int i = start; i < end; ++i) {\n                byte ch = data[i];\n                if (ch == '.') {\n                    power = 1;\n                    continue;\n                }\n                int digit = ch - '0';\n                value = value * 10 + digit;\n                power *= 10;\n            }\n            double doubleValue = (double) value;\n            if (power == 0) {\n                return doubleValue;\n            } else {\n                return doubleValue / power;\n            }\n        }\n    }\n\n    static class SqlUtil {\n        public static Set<String> filterDb = new HashSet<String>();\n\n        private static int[] orders = new int[]{2, 3, 0, 1};\n\n        static {\n            filterDb.add(\"DRC\");\n            filterDb.add(\"INFORMATION_SCHEMA\");\n            filterDb.add(\"INNODB_MEMCACHE\");\n            filterDb.add(\"MYSQL\");\n            filterDb.add(\"PERFORMANCE_SCHEMA\");\n            filterDb.add(\"RECYCLE_BIN\");\n            filterDb.add(\"ROCKSDB\");\n            filterDb.add(\"TEST\");\n            filterDb.add(\"DRC\".toLowerCase());\n            filterDb.add(\"INFORMATION_SCHEMA\".toLowerCase());\n            filterDb.add(\"INNODB_MEMCACHE\".toLowerCase());\n            filterDb.add(\"MYSQL\".toLowerCase());\n            filterDb.add(\"PERFORMANCE_SCHEMA\".toLowerCase());\n            filterDb.add(\"RECYCLE_BIN\".toLowerCase());\n            filterDb.add(\"ROCKSDB\".toLowerCase());\n            filterDb.add(\"TEST\".toLowerCase());\n        }\n\n        public static final String filterDbs = org.apache.commons.lang3.StringUtils.join(SqlUtil.filterDb, \",\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/UnsignedBigIntTest.java",
    "content": "package com.alibaba.druid.bvt.sql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class UnsignedBigIntTest {\n    @Test\n    public void test_mysqlUnsignedBitInt() throws Exception {\n        String sql = \"SELECT a from b where c <> 1 LIMIT 18446744073709551615 OFFSET 0\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement sqlStatement = parser.parseStatement();\n        StringBuilder sb = new StringBuilder();\n        MySqlOutputVisitor visitor = new MySqlOutputVisitor(sb);\n        visitor.setPrettyFormat(false);\n        sqlStatement.accept(visitor);\n        assertEquals(\"SELECT a FROM b WHERE c <> 1 LIMIT 18446744073709551615 OFFSET 0\", sb.toString());\n    }\n\n    @Test\n    public void test_postgresqlUnsignedBitInt() {\n        String sql = \"SELECT a from b where c <> 1 LIMIT 18446744073709551615 OFFSET 1\";\n        PGSQLStatementParser parser = new PGSQLStatementParser(sql);\n        SQLStatement sqlStatement = parser.parseStatement();\n        StringBuilder sb = new StringBuilder();\n        PGOutputVisitor visitor = new PGOutputVisitor(sb);\n        visitor.setPrettyFormat(false);\n        sqlStatement.accept(visitor);\n        assertEquals(\"SELECT a FROM b WHERE c <> 1 LIMIT 18446744073709551615 OFFSET 1\", sb.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/ast/SQLDropTableStatementTest.java",
    "content": "package com.alibaba.druid.bvt.sql.ast;\n\nimport com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class SQLDropTableStatementTest {\n    @Test\n    public void test_0() throws Exception {\n        SQLDropTableStatement stmt = new SQLDropTableStatement();\n        stmt.addTableSource(\"abc\");\n        assertEquals(stmt, stmt.clone());\n        assertEquals(stmt.hashCode(), stmt.clone().hashCode());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/athena/AthenaResourceTest.java",
    "content": "package com.alibaba.druid.bvt.sql.athena;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class AthenaResourceTest extends SQLResourceTest {\n    public AthenaResourceTest() {\n        super(DbType.athena);\n    }\n\n    @Test\n    public void athena_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/athena/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/AggregateTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\npublic class AggregateTest {\n    @Test\n    public void test_agg() {\n        String sql = \"SELECT lag(date(d,'Asia/Jakarta')) over(partition by id order by n) FROM t1\";\n        SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils.parseSingleStatement(sql, DbType.bigquery);\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n        SQLAggregateExpr expr = (SQLAggregateExpr) queryBlock.getSelectList().get(0).getExpr();\n        assertSame(expr, expr.getArgument(0).getParent());\n    }\n\n    @Test\n    public void test_agg_1() {\n        String sql = \"SELECT xx(date(d,'Asia/Jakarta')) over(partition by id order by n) FROM t1\";\n        SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils.parseSingleStatement(sql, DbType.bigquery);\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n        SQLAggregateExpr expr = (SQLAggregateExpr) queryBlock.getSelectList().get(0).getExpr();\n        assertSame(expr, expr.getArgument(0).getParent());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/BigQueryCommentTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class BigQueryCommentTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT id\\n\" +\n                \"    , updatedTimestamp as updated_timestamp\\n\" +\n                \"    , event_timestamp\\n\" +\n                \"\\n\" +\n                \"    -- comment1 --\\n\" +\n                \"    , current_timestamp() as last_modified_timestamp\\n\" +\n                \"    , execution_time as load_timestamp\\n\" +\n                \"\\n\" +\n                \"    -- comment2   \\n\" +\n                \"    -- comment3\\n\" +\n                \"    , row_number() over(partition by pid, orderId, status order by event_timestamp desc) rn\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE\\n\" +\n                \"    -- comment4\\n\" +\n                \"    et >= TIMESTAMP(date_sub(fact_start_date, interval 2 day))\\n\" +\n                \"AND\\n\" +\n                \"    et < TIMESTAMP(fact_end_date)\";\n\n        SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils.parseSingleStatement(\n                sql,\n                DbType.bigquery,\n                SQLParserFeature.KeepComments\n        );\n        SQLSelectQueryBlock queryBlock = stmt.getSelect().getQueryBlock();\n        assertEquals(6, queryBlock.getSelectList().size());\n\n        assertEquals(\"SELECT id, updatedTimestamp AS updated_timestamp, event_timestamp -- comment1 --\\n\" +\n                \"\\t, current_timestamp() AS last_modified_timestamp, execution_time AS load_timestamp -- comment2\\n\" +\n                \"\\t-- comment3\\n\" +\n                \"\\t, row_number() OVER (PARTITION BY pid, orderId, status ORDER BY event_timestamp DESC) AS rn\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE -- comment4\\n\" +\n                \"et >= TIMESTAMP(date_sub(fact_start_date, INTERVAL 2 DAY))\\n\" +\n                \"\\tAND et < TIMESTAMP(fact_end_date)\", SQLUtils.toSQLString(stmt, DbType.bigquery));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/BigQueryDataTypeTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLDataType;\nimport com.alibaba.druid.sql.parser.SQLExprParser;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class BigQueryDataTypeTest {\n    @Test\n    public void testDataType() {\n        String sql = \"ANY TYPE\";\n        SQLExprParser exprParser = SQLParserUtils.createExprParser(sql, DbType.bigquery);\n        SQLDataType dataType = exprParser.parseDataType(false);\n        assertEquals(sql, dataType.getName());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/BigQueryDirTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\n\npublic class BigQueryDirTest extends SQLResourceTest {\n    public BigQueryDirTest() {\n        super(DbType.bigquery);\n    }\n\n    protected File dir(String path) {\n        return new File(path);\n    }\n\n    @Disabled\n    @Test\n    public void dirTest() throws Exception {\n//        File dir = new File(\"/Users/wenshao/Downloads/goto_1894_sql\");\n//        File dir = new File(\"/Users/wenshao/Downloads/BigQuery\");\n//        File[] files = dir.listFiles();\n//        Arrays.sort(files, Comparator.comparing(e -> e.getName().toLowerCase()));\n//        for (File file : files) {\n//            if (file.getName().equals(\".DS_Store\")) {\n//                continue;\n//            }\n//\n//            System.out.println(file.getAbsolutePath());\n//            String sql = FileUtils.readFileToString(file, StandardCharsets.UTF_8);\n//            try {\n//                SQLUtils.parseStatements(sql, DbType.bigquery);\n//                file.delete();\n//            } catch (Exception e) {\n//                e.printStackTrace();\n//            }\n//        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/BigQueryEnhancedTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCallStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateFunctionStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateProcedureStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSetStatement;\nimport com.alibaba.druid.sql.dialect.bigquery.ast.BigQueryExportDataStatement;\nimport com.alibaba.druid.sql.dialect.bigquery.visitor.BigQuerySchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BigQueryEnhancedTest {\n    private static final DbType DB_TYPE = DbType.bigquery;\n\n    private SQLStatement parseOne(String sql) {\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DB_TYPE);\n        SQLStatement stmt = parser.parseStatement();\n        return stmt;\n    }\n\n    private List<SQLStatement> parseList(String sql) {\n        return SQLUtils.parseStatements(sql, DB_TYPE);\n    }\n\n    @Test\n    public void testCreateSchema() {\n        SQLStatement stmt = parseOne(\"CREATE SCHEMA my_project.my_dataset\");\n        assertInstanceOf(SQLCreateDatabaseStatement.class, stmt);\n    }\n\n    @Test\n    public void testCreateSchemaIfNotExists() {\n        SQLStatement stmt = parseOne(\"CREATE SCHEMA IF NOT EXISTS my_project.my_dataset OPTIONS(location = 'us')\");\n        SQLCreateDatabaseStatement createDb = (SQLCreateDatabaseStatement) stmt;\n        assertTrue(createDb.isIfNotExists());\n        assertNotNull(createDb.getOptions().get(\"location\"));\n    }\n\n    @Test\n    public void testCreateProcedure() {\n        String sql = \"CREATE OR REPLACE PROCEDURE my_proj.my_ds.my_proc(x INT64, y STRING)\\n\"\n                + \"BEGIN\\n  SELECT x;\\nEND\";\n        SQLStatement stmt = parseOne(sql);\n        assertInstanceOf(SQLCreateProcedureStatement.class, stmt);\n        SQLCreateProcedureStatement proc = (SQLCreateProcedureStatement) stmt;\n        assertTrue(proc.isOrReplace());\n        assertEquals(2, proc.getParameters().size());\n    }\n\n    @Test\n    public void testCreateFunction() {\n        String sql = \"CREATE TEMP FUNCTION add_one(x INT64) RETURNS INT64 AS (x + 1)\";\n        SQLStatement stmt = parseOne(sql);\n        assertInstanceOf(SQLCreateFunctionStatement.class, stmt);\n        SQLCreateFunctionStatement func = (SQLCreateFunctionStatement) stmt;\n        assertTrue(func.isTemporary());\n        assertEquals(1, func.getParameters().size());\n    }\n\n    @Test\n    public void testCreateOrReplaceFunction() {\n        String sql = \"CREATE OR REPLACE FUNCTION my_udf(a STRING) RETURNS STRING LANGUAGE js AS \\\"\\\"\\\"\\n  return a;\\n\\\"\\\"\\\"\";\n        SQLStatement stmt = parseOne(sql);\n        assertInstanceOf(SQLCreateFunctionStatement.class, stmt);\n        SQLCreateFunctionStatement func = (SQLCreateFunctionStatement) stmt;\n        assertTrue(func.isOrReplace());\n        assertEquals(\"js\", func.getLanguage());\n    }\n\n    @Test\n    public void testCreateFunctionIfNotExists() {\n        String sql = \"CREATE FUNCTION IF NOT EXISTS my_func(x INT64) RETURNS INT64 AS (x * 2)\";\n        SQLStatement stmt = parseOne(sql);\n        assertInstanceOf(SQLCreateFunctionStatement.class, stmt);\n        SQLCreateFunctionStatement func = (SQLCreateFunctionStatement) stmt;\n        assertTrue(func.isIfNotExists());\n    }\n\n    @Test\n    public void testExportData() {\n        String sql = \"EXPORT DATA OPTIONS (uri = 'gs://bucket/*.csv', format = 'CSV') AS (SELECT * FROM t)\";\n        SQLStatement stmt = parseOne(sql);\n        assertInstanceOf(BigQueryExportDataStatement.class, stmt);\n        BigQueryExportDataStatement exportStmt = (BigQueryExportDataStatement) stmt;\n        assertEquals(2, exportStmt.getOptions().size());\n        assertNotNull(exportStmt.getAsSelect());\n    }\n\n    @Test\n    public void testExportDataWithConnection() {\n        String sql = \"EXPORT DATA WITH CONNECTION my_conn OPTIONS (uri = 'gs://bucket/*.csv') AS (SELECT 1)\";\n        SQLStatement stmt = parseOne(sql);\n        assertInstanceOf(BigQueryExportDataStatement.class, stmt);\n        BigQueryExportDataStatement exportStmt = (BigQueryExportDataStatement) stmt;\n        assertNotNull(exportStmt.getConnection());\n    }\n\n    @Test\n    public void testCallStatement() {\n        String sql = \"CALL my_project.my_dataset.my_proc(1, 'hello')\";\n        SQLStatement stmt = parseOne(sql);\n        assertInstanceOf(SQLCallStatement.class, stmt);\n    }\n\n    @Test\n    public void testSetStatement() {\n        SQLStatement stmt = parseOne(\"SET x = 5\");\n        assertInstanceOf(SQLSetStatement.class, stmt);\n    }\n\n    @Test\n    public void testSchemaStatVisitor() {\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DB_TYPE);\n        assertInstanceOf(BigQuerySchemaStatVisitor.class, visitor);\n\n        String sql = \"SELECT a, b FROM my_project.my_dataset.my_table WHERE c > 1\";\n        SQLStatement stmt = parseOne(sql);\n        stmt.accept(visitor);\n        assertEquals(1, visitor.getTables().size());\n        assertTrue(visitor.getColumns().size() >= 2);\n    }\n\n    @Test\n    public void testDataTypeAliases() {\n        // BigQuery supports type aliases like INT, INTEGER, FLOAT, DECIMAL, BOOLEAN\n        String sql = \"CREATE TABLE t (a INT64, b FLOAT64, c NUMERIC, d BOOL, e STRING, f BYTES, g JSON, h GEOGRAPHY)\";\n        SQLStatement stmt = parseOne(sql);\n        String output = SQLUtils.toSQLString(stmt, DB_TYPE);\n        assertNotNull(output);\n        // Round-trip parse should succeed\n        SQLStatement stmt2 = parseOne(output);\n        assertEquals(SQLUtils.toSQLString(stmt, DB_TYPE), SQLUtils.toSQLString(stmt2, DB_TYPE));\n    }\n\n    @Test\n    public void testComplexCreateTable() {\n        String sql = \"CREATE TABLE t (\\n\"\n                + \"  id INT64 NOT NULL,\\n\"\n                + \"  data STRUCT<name STRING, value FLOAT64>,\\n\"\n                + \"  tags ARRAY<STRING>,\\n\"\n                + \"  PRIMARY KEY (id) NOT ENFORCED\\n\"\n                + \") PARTITION BY DATE(created_at) CLUSTER BY name OPTIONS (description = 'test')\";\n        SQLStatement stmt = parseOne(sql);\n        String output = SQLUtils.toSQLString(stmt, DB_TYPE);\n        assertTrue(output.contains(\"PARTITION BY\"));\n        assertTrue(output.contains(\"CLUSTER BY\"));\n        assertTrue(output.contains(\"OPTIONS\"));\n    }\n\n    @Test\n    public void testProceduralBlock() {\n        String sql = \"BEGIN\\n  DECLARE x INT64 DEFAULT 0;\\n  SET x = 10;\\n  IF x > 5 THEN\\n    SELECT x;\\n  END IF;\\nEND\";\n        List<SQLStatement> stmts = parseList(sql);\n        assertEquals(1, stmts.size());\n        String output = SQLUtils.toSQLString(stmts, DB_TYPE);\n        assertTrue(output.contains(\"DECLARE\"));\n        assertTrue(output.contains(\"SET\"));\n        assertTrue(output.contains(\"IF\"));\n    }\n\n    @Test\n    public void testExecuteImmediate() {\n        String sql = \"EXECUTE IMMEDIATE 'SELECT ?' INTO result USING 42 AS x\";\n        SQLStatement stmt = parseOne(sql);\n        String output = SQLUtils.toSQLString(stmt, DB_TYPE);\n        assertTrue(output.contains(\"EXECUTE IMMEDIATE\"));\n        assertTrue(output.contains(\"INTO result\"));\n        assertTrue(output.contains(\"USING 42 AS x\"));\n    }\n\n    @Test\n    public void testMergeStatement() {\n        String sql = \"MERGE INTO t USING s ON t.id = s.id \"\n                + \"WHEN MATCHED THEN UPDATE SET t.val = s.val \"\n                + \"WHEN NOT MATCHED THEN INSERT (id, val) VALUES (s.id, s.val)\";\n        SQLStatement stmt = parseOne(sql);\n        String output = SQLUtils.toSQLString(stmt, DB_TYPE);\n        assertTrue(output.contains(\"MERGE INTO\"));\n        assertTrue(output.contains(\"WHEN MATCHED\"));\n        assertTrue(output.contains(\"WHEN NOT MATCHED\"));\n    }\n\n    @Test\n    public void testTruncateTable() {\n        SQLStatement stmt = parseOne(\"TRUNCATE TABLE my_project.my_dataset.my_table\");\n        String output = SQLUtils.toSQLString(stmt, DB_TYPE);\n        assertTrue(output.contains(\"TRUNCATE TABLE\"));\n    }\n\n    @Test\n    public void testExportDataRoundTrip() {\n        String sql = \"EXPORT DATA OPTIONS (uri = 'gs://bucket/data', format = 'JSON') AS (SELECT * FROM t)\";\n        SQLStatement stmt = parseOne(sql);\n        String output = SQLUtils.toSQLString(stmt, DB_TYPE).trim();\n        // Round-trip\n        SQLStatement stmt2 = parseOne(output);\n        String output2 = SQLUtils.toSQLString(stmt2, DB_TYPE).trim();\n        assertEquals(output, output2);\n    }\n\n    @Test\n    public void testCreateProcedureRoundTrip() {\n        String sql = \"CREATE PROCEDURE my_proc(x INT64) BEGIN SELECT x; END\";\n        SQLStatement stmt = parseOne(sql);\n        String output = SQLUtils.toSQLString(stmt, DB_TYPE).trim();\n        // Verify no IS keyword\n        assertFalse(output.contains(\"\\nIS\\n\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/BigQueryNameTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.FnvHash;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class BigQueryNameTest {\n    @Test\n    public void name() {\n        String str = \"`a.b.c`\";\n        SQLExpr expr = SQLUtils.toSQLExpr(str, DbType.bigquery);\n        assertTrue(expr instanceof SQLPropertyExpr);\n        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n        assertEquals(\"c\", propertyExpr.getName());\n    }\n\n    @Test\n    public void name1() {\n        String str = \"`a-x.b.c`\";\n        SQLExpr expr = SQLUtils.toSQLExpr(str, DbType.bigquery);\n        assertTrue(expr instanceof SQLPropertyExpr);\n        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n        assertEquals(\"c\", propertyExpr.getName());\n        assertTrue(propertyExpr.getOwner() instanceof SQLPropertyExpr);\n        SQLExpr ownerOwner = ((SQLPropertyExpr) propertyExpr.getOwner()).getOwner();\n        assertTrue(ownerOwner instanceof SQLIdentifierExpr);\n        assertEquals(\"a-x\", ((SQLIdentifierExpr) ownerOwner).getName());\n        assertEquals(\"`a-x`.b.c\", SQLUtils.toSQLString(expr, DbType.bigquery));\n        assertEquals(FnvHash.fnv1a_64_lower(\"a-x\"), ((SQLIdentifierExpr) ownerOwner).hashCode64());\n    }\n\n    @Test\n    public void name2() {\n        String str = \"`a-x`.b.c\";\n        SQLExpr expr = SQLUtils.toSQLExpr(str, DbType.bigquery, SQLParserFeature.IgnoreNameQuotes);\n        assertTrue(expr instanceof SQLPropertyExpr);\n        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n        assertEquals(\"c\", propertyExpr.getName());\n        assertTrue(propertyExpr.getOwner() instanceof SQLPropertyExpr);\n        SQLExpr ownerOwner = ((SQLPropertyExpr) propertyExpr.getOwner()).getOwner();\n        assertTrue(ownerOwner instanceof SQLIdentifierExpr);\n        assertEquals(\"a-x\", ((SQLIdentifierExpr) ownerOwner).getName());\n        assertEquals(\"`a-x`.b.c\", SQLUtils.toSQLString(expr, DbType.bigquery));\n        assertEquals(FnvHash.fnv1a_64_lower(\"a-x\"), ((SQLIdentifierExpr) ownerOwner).hashCode64());\n    }\n\n    @Test\n    public void name3() {\n        String str = \"`a-x`.b.c\";\n        SQLExpr expr = SQLUtils.toSQLExpr(str, DbType.bigquery, SQLParserFeature.IgnoreNameQuotes);\n        assertTrue(expr instanceof SQLPropertyExpr);\n        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n        assertEquals(\"c\", propertyExpr.getName());\n        assertTrue(propertyExpr.getOwner() instanceof SQLPropertyExpr);\n        SQLExpr ownerOwner = ((SQLPropertyExpr) propertyExpr.getOwner()).getOwner();\n        assertTrue(ownerOwner instanceof SQLIdentifierExpr);\n        assertEquals(\"a-x\", ((SQLIdentifierExpr) ownerOwner).getName());\n        assertEquals(\"`a-x`.b.c\", SQLUtils.toSQLString(expr, DbType.bigquery));\n        assertEquals(FnvHash.fnv1a_64_lower(\"a-x\"), ((SQLIdentifierExpr) ownerOwner).hashCode64());\n    }\n\n    @Test\n    public void nameView() {\n        String str = \"create view `a-x.b.c` as select 1;\";\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) SQLUtils.parseSingleStatement(str, DbType.bigquery);\n        SQLExpr expr = stmt.getName();\n        assertTrue(expr instanceof SQLPropertyExpr);\n        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n        assertEquals(\"c\", propertyExpr.getName());\n        assertTrue(propertyExpr.getOwner() instanceof SQLPropertyExpr);\n        SQLExpr ownerOwner = ((SQLPropertyExpr) propertyExpr.getOwner()).getOwner();\n        assertTrue(ownerOwner instanceof SQLIdentifierExpr);\n        assertEquals(\"a-x\", ((SQLIdentifierExpr) ownerOwner).getName());\n        assertEquals(\"`a-x`.b.c\", SQLUtils.toSQLString(expr, DbType.bigquery));\n    }\n\n    @Test\n    public void nameView1() {\n        String str = \"create view `a-x.b.c` as select `interval` from t;\";\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) SQLUtils.parseSingleStatement(\n                str, DbType.bigquery,\n                SQLParserFeature.IgnoreNameQuotes);\n        SQLExpr expr = stmt.getName();\n        assertTrue(expr instanceof SQLPropertyExpr);\n        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n        assertEquals(\"c\", propertyExpr.getName());\n        assertTrue(propertyExpr.getOwner() instanceof SQLPropertyExpr);\n        SQLExpr ownerOwner = ((SQLPropertyExpr) propertyExpr.getOwner()).getOwner();\n        assertTrue(ownerOwner instanceof SQLIdentifierExpr);\n        assertEquals(\"a-x\", ((SQLIdentifierExpr) ownerOwner).getName());\n        assertEquals(\"`a-x`.b.c\", SQLUtils.toSQLString(expr, DbType.bigquery));\n    }\n\n    @Test\n    public void select1() {\n        String str = \"select * from a-x.b.c\";\n        SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils.parseSingleStatement(\n                str, DbType.bigquery,\n                SQLParserFeature.IgnoreNameQuotes);\n        SQLExpr expr = ((SQLExprTableSource) stmt.getSelect().getQueryBlock().getFrom()).getExpr();\n        assertTrue(expr instanceof SQLPropertyExpr);\n        SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;\n        assertEquals(\"c\", propertyExpr.getName());\n        assertTrue(propertyExpr.getOwner() instanceof SQLPropertyExpr);\n        SQLExpr ownerOwner = ((SQLPropertyExpr) propertyExpr.getOwner()).getOwner();\n        assertTrue(ownerOwner instanceof SQLIdentifierExpr);\n        assertEquals(\"a-x\", ((SQLIdentifierExpr) ownerOwner).getName());\n        assertEquals(\"`a-x`.b.c\", SQLUtils.toSQLString(expr, DbType.bigquery));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/BigQueryResourceTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class BigQueryResourceTest extends SQLResourceTest {\n    public BigQueryResourceTest() {\n        super(DbType.bigquery);\n    }\n\n    @Test\n    public void bigquery_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/bigquery/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/BigQuerySchemaTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport org.junit.jupiter.api.Test;\n\npublic class BigQuerySchemaTest {\n    @Test\n    public void test_schema() {\n    String sql =\n        \"CREATE TABLE IF NOT EXISTS `a-b-c.d.e` (\\n\"\n            + \"    feature_name string,\\n\"\n            + \"    feature_value float64,\\n\"\n            + \"    feature_bindings string,\\n\"\n            + \"    event_timestamp timestamp,\\n\"\n            + \"    load_timestamp timestamp,\\n\"\n            + \"    feature_end_timestamp timestamp,\\n\"\n            + \"    )\\n\"\n            + \"    PARTITION BY date(event_timestamp)\\n\"\n            + \"    ;\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.bigquery);\n        SQLStatement sqlStatement = parser.parseStatement();\n        SchemaRepository schemaRepository = new SchemaRepository(DbType.bigquery);\n        schemaRepository.accept(sqlStatement);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/bigquery/UnnestTest.java",
    "content": "package com.alibaba.druid.bvt.sql.bigquery;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLUnnestTableSource;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class UnnestTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT 1\\n\" +\n                \"FROM t1 pt\\n\" +\n                \"LEFT OUTER JOIN t2 cl\\n\" +\n                \"ON pt.driver_id = cl.driver_id\\n\" +\n                \"    AND pt.order_id = cl.order_no\\n\" +\n                \"LEFT OUTER JOIN UNNEST(v_list) v_type\\n\" +\n                \"LEFT OUTER JOIN UNNEST(r_list) d_id\";\n        SQLSelectStatement stmt = (SQLSelectStatement) SQLUtils.parseSingleStatement(sql, DbType.bigquery);\n        SQLTableSource from = stmt.getSelect().getQueryBlock().getFrom();\n        assertTrue(from instanceof SQLJoinTableSource);\n        SQLJoinTableSource join = (SQLJoinTableSource) from;\n        assertTrue(join.getRight() instanceof SQLUnnestTableSource);\n\n        SQLJoinTableSource left = (SQLJoinTableSource) join.getLeft();\n        assertTrue(left.getRight() instanceof SQLUnnestTableSource);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderDeleteTest.java",
    "content": "package com.alibaba.druid.bvt.sql.builder;\n\nimport com.alibaba.druid.sql.builder.SQLBuilderFactory;\nimport com.alibaba.druid.sql.builder.SQLDeleteBuilder;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BuilderDeleteTest {\n    @Test\n    public void test_0() throws Exception {\n        SQLDeleteBuilder builder = SQLBuilderFactory.createDeleteBuilder(JdbcConstants.MYSQL);\n\n        builder.from(\"mytable\")\n                .whereAnd(\"f1 > 0\");\n\n        String sql = builder.toString();\n        System.out.println(sql);\n        assertEquals(\"DELETE FROM mytable\"\n                + \"\\nWHERE f1 > 0\", sql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderSelectTest.java",
    "content": "package com.alibaba.druid.bvt.sql.builder;\n\nimport com.alibaba.druid.sql.builder.SQLBuilderFactory;\nimport com.alibaba.druid.sql.builder.SQLSelectBuilder;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BuilderSelectTest {\n    @Test\n    public void test_0() throws Exception {\n        SQLSelectBuilder builder = SQLBuilderFactory.createSelectSQLBuilder(JdbcConstants.MYSQL);\n\n        builder.from(\"mytable\");\n        builder.select(\"f1\", \"f2\", \"f3 F3\", \"count(*) cnt\");\n        builder.groupBy(\"f1\");\n        builder.having(\"count(*) > 1\");\n        builder.orderBy(\"f1\", \"f2 desc\");\n        builder.whereAnd(\"f1 > 0\");\n\n        String sql = builder.toString();\n        System.out.println(sql);\n        assertEquals(\"SELECT f1, f2, f3 AS F3, count(*) AS cnt\\n\" +\n                \"FROM mytable\\n\" +\n                \"WHERE f1 > 0\\n\" +\n                \"GROUP BY f1\\n\" +\n                \"HAVING count(*) > 1\\n\" +\n                \"ORDER BY f1, f2 DESC\", sql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/builder/BuilderUpdateTest.java",
    "content": "package com.alibaba.druid.bvt.sql.builder;\n\nimport com.alibaba.druid.sql.builder.SQLBuilderFactory;\nimport com.alibaba.druid.sql.builder.SQLUpdateBuilder;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class BuilderUpdateTest {\n    @Test\n    public void test_0() throws Exception {\n        SQLUpdateBuilder builder = SQLBuilderFactory.createUpdateBuilder(JdbcConstants.MYSQL);\n\n        builder //\n                .from(\"mytable\") //\n                .whereAnd(\"f1 > 0\") //\n                .set(\"f1 = f1 + 1\", \"f2 = ?\");\n\n        String sql = builder.toString();\n        System.out.println(sql);\n        assertEquals(\"UPDATE mytable\"\n                + \"\\nSET f1 = f1 + 1, f2 = ?\"\n                + \"\\nWHERE f1 > 0\", sql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/canal/CanalSQLSchemaTest.java",
    "content": "package com.alibaba.druid.bvt.sql.canal;\n\nimport com.alibaba.druid.sql.repository.SchemaObject;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class CanalSQLSchemaTest {\n    @Test\n    public void testSimple() throws Throwable {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n        String sql1 = \"CREATE TABLE `table_x1` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, \"\n                + \"`key1` longtext NOT NULL COMMENT 'key1', `value1` longtext NOT NULL COMMENT 'value1', PRIMARY KEY (`id`) )\"\n                + \"ENGINE=InnoDB DEFAULT CHARSET=utf8mb4\";\n        String sql2 = \" CREATE TABLE IF NOT EXISTS `table_x1` ( `id` bigint(20) NOT NULL AUTO_INCREMENT,\"\n                + \"`key1` longtext NOT NULL COMMENT 'key1',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4\";\n        repository.console(sql1);\n        repository.console(sql2);\n        repository.setDefaultSchema(\"test\");\n        SchemaObject table = repository.findTable(\"table_x1\");\n        assertTrue(\n                table.findColumn(\"value1\") != null);\n    }\n\n    @Test\n    public void test_block_format() throws Throwable {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n        String sql = \" CREATE TABLE `parent` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\"\n                + \"`created_at` timestamp NULL DEFAULT NULL, \" + \"PRIMARY KEY (`id`)\"\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 BLOCK_FORMAT=ENCRYPTED\";\n        repository.console(sql);\n        repository.setDefaultSchema(\"test\");\n        SchemaObject table = repository.findTable(\"parent\");\n        assertTrue(table.findColumn(\"id\") != null);\n    }\n\n    @Test\n    public void test_json_index() throws Throwable {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n        String sql = \" CREATE TABLE `articles` ( \\n\" +\n                \" \\t`article_id` bigint NOT NULL AUTO_INCREMENT, \\n\" +\n                \" \\t`tags` json DEFAULT NULL, PRIMARY KEY (`article_id`), \\n\" +\n                \" \\tKEY `articles_tags` (\\n\" +\n                \" \\t\\t(\\n\" +\n                \" \\t\\t\\tcast(json_extract(`tags`,_utf8mb4'$[*]') \\n\" +\n                \" \\t\\t\\t\\tas char(40) array)\\n\" +\n                \" \\t\\t)\\n\" +\n                \" \\t)\\n\" +\n                \" ) ENGINE=InnoDB AUTO_INCREMENT=1054 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci\";\n        repository.console(sql);\n        repository.setDefaultSchema(\"test\");\n        SchemaObject table = repository.findTable(\"articles\");\n        assertTrue(table.findColumn(\"article_id\") != null);\n    }\n\n    @Test\n    public void test_invisible() throws Throwable {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n        String sql = \" CREATE TABLE `proposal_order_info` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\"\n                + \"`created_at` timestamp NULL DEFAULT NULL, \" + \"PRIMARY KEY (`id`) , \"\n                + \"KEY `idx_create_time` (`created_at`) /*!80000 INVISIBLE */\"\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 BLOCK_FORMAT=ENCRYPTED\";\n        repository.console(sql);\n        repository.setDefaultSchema(\"test\");\n        SchemaObject table = repository.findTable(\"proposal_order_info\");\n        assertTrue(table.findColumn(\"id\") != null);\n    }\n\n    @Test\n    public void test_persistent() throws Throwable {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n        String sql = \" create table example_vc_tbl( c1 int not null auto_increment primary key,\"\n                + \"c2 varchar(70), vc1 int as (length(c2)) virtual,\"\n                + \"DIM_SUM varchar(128) AS (MD5(UPPER(CONCAT(c2, c1)))) PERSISTENT)\";\n        repository.console(sql);\n        repository.setDefaultSchema(\"test\");\n        SchemaObject table = repository.findTable(\"example_vc_tbl\");\n        assertTrue(table.findColumn(\"DIM_SUM\") != null);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CKArrayJoinTest.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class CKArrayJoinTest {\n    @Test\n    public void test_array_join_basic() {\n        String sql = \"SELECT arr, a FROM test_table ARRAY JOIN arr AS a\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.clickhouse);\n        List<SQLStatement> stmts = parser.parseStatementList();\n        assertEquals(1, stmts.size());\n        SQLSelectStatement stmt = (SQLSelectStatement) stmts.get(0);\n        SQLJoinTableSource join = (SQLJoinTableSource) stmt.getSelect().getQueryBlock().getFrom();\n        assertEquals(\"ARRAY JOIN\", join.getJoinType().name);\n        SQLParseAssertUtil.assertParseSql(sql, DbType.clickhouse);\n    }\n\n    @Test\n    public void test_left_array_join() {\n        String sql = \"SELECT * FROM test_table LEFT ARRAY JOIN arr AS a\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.clickhouse);\n        List<SQLStatement> stmts = parser.parseStatementList();\n        assertEquals(1, stmts.size());\n        SQLSelectStatement stmt = (SQLSelectStatement) stmts.get(0);\n        SQLJoinTableSource join = (SQLJoinTableSource) stmt.getSelect().getQueryBlock().getFrom();\n        assertEquals(\"LEFT ARRAY JOIN\", join.getJoinType().name);\n        SQLParseAssertUtil.assertParseSql(sql, DbType.clickhouse);\n    }\n\n    @Test\n    public void test_array_join_with_array_literal() {\n        String sql = \"SELECT * FROM test_table ARRAY JOIN arr AS a, [1,2,3] AS b\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.clickhouse);\n        List<SQLStatement> stmts = parser.parseStatementList();\n        assertEquals(1, stmts.size());\n        SQLParseAssertUtil.assertParseSql(sql, DbType.clickhouse);\n    }\n\n    @Test\n    public void test_array_join_with_array_map() {\n        String sql = \"SELECT s, arr, a, mapped FROM arrays_test ARRAY JOIN arr AS a, arrayMap(x -> x + 1, arr) AS mapped\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.clickhouse);\n        List<SQLStatement> stmts = parser.parseStatementList();\n        assertEquals(1, stmts.size());\n        SQLParseAssertUtil.assertParseSql(sql, DbType.clickhouse);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CKCloneNpe.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class CKCloneNpe {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE test_local (  \\n\"\n                + \"`test_list` Array(UInt64)) \\n\"\n                + \"ENGINE = MergeTree()\";\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.clickhouse);\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(1, statementList.size());\n        assertTrue(stmt instanceof SQLCreateTableStatement);\n        stmt.clone();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CKResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class CKResourceTest extends SQLResourceTest {\n    public CKResourceTest() {\n        super(DbType.clickhouse);\n    }\n\n    @Test\n    public void clickhouse_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/clickhouse/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CK_select_0.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CK_select_0 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT date, transactionChannel, tranactionType FROM preComp_3All_20180322 limit 1,10\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.clickhouse);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"preComp_3All_20180322\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        assertEquals(\"SELECT date, transactionChannel, tranactionType\\n\" +\n                        \"FROM preComp_3All_20180322\\n\" +\n                        \"LIMIT 1, 10\", //\n                output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        assertEquals(\"SELECT date, transactionChannel, tranactionType\\n\" +\n                \"FROM preComp_3All_20180322\\n\" +\n                \"LIMIT ?, ?\", psql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CK_select_1.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CK_select_1 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT * FROM limit_by ORDER BY id, val LIMIT 2 BY id\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.clickhouse);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"limit_by\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        assertEquals(\"SELECT *\\n\" +\n                        \"FROM limit_by\\n\" +\n                        \"ORDER BY id, val\\n\" +\n                        \"LIMIT 2 BY id\", //\n                output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM limit_by\\n\" +\n                \"ORDER BY id, val\\n\" +\n                \"LIMIT ? BY id\", psql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CK_select_2.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CK_select_2 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select a from cluster('test', view( select a from t1))\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.clickhouse);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"t1\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        assertEquals(\"SELECT a\\n\" +\n                        \"FROM cluster('test', view(\\n\" +\n                        \"\\tSELECT a\\n\" +\n                        \"\\tFROM t1\\n\" +\n                        \"))\", //\n                output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        assertEquals(\"SELECT a\\n\" +\n                \"FROM cluster(?, view(\\n\" +\n                \"\\tSELECT a\\n\" +\n                \"\\tFROM t1\\n\" +\n                \"))\", psql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CK_select_3.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CK_select_3 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT name, c FROM test WHERE c NOT ILIKE 'a%'\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.clickhouse);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"test\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        assertEquals(\"SELECT name, c\\n\" +\n        \"FROM test\\n\" +\n        \"WHERE c NOT ILIKE 'a%'\", output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        assertEquals(\"SELECT name, c\\n\" +\n        \"FROM test\\n\" +\n        \"WHERE c NOT ILIKE ?\", psql);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT name, c FROM test WHERE c ILIKE 'a%'\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.clickhouse);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"test\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        assertEquals(\"SELECT name, c\\n\" +\n        \"FROM test\\n\" +\n        \"WHERE c ILIKE 'a%'\", output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        assertEquals(\"SELECT name, c\\n\" +\n        \"FROM test\\n\" +\n        \"WHERE c ILIKE ?\", psql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/CK_update_0.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.clickhouse.parser.CKStatementParser;\nimport com.alibaba.druid.sql.dialect.clickhouse.visitor.CKStatVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CK_update_0 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"alter table tb1 ON CLUSTER 'cluster' update A=1,B=1,C=2  where ID = 1;\"\n            + \"alter table tb1 ON CLUSTER cluster update A=3,B=4,C=5  where ID = 2;\";\n        CKStatementParser parser = new CKStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(statementList);\n        assertEquals(2, statementList.size());\n\n        CKStatVisitor visitor = new CKStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"tb1\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        System.out.println(\"output : \" + output);\n        assertEquals(\"ALTER TABLE tb1 ON CLUSTER 'cluster' UPDATE A = 1, B = 1, C = 2 WHERE ID = 1;\", //\n            output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        System.out.println(\"psql : \" + psql);\n        assertEquals(\"ALTER TABLE tb1 ON CLUSTER ? UPDATE A = ?, B = ?, C = ? WHERE ID = ?;\", psql);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"alter table tb1 update A=1,B=1,C=2  where ID = 1;\"\n            + \"alter table tb1 update A=3,B=4,C=5  where ID = 2;\";\n        CKStatementParser parser = new CKStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(statementList);\n        assertEquals(2, statementList.size());\n\n        CKStatVisitor visitor = new CKStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"tb1\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        System.out.println(\"output : \" + output);\n        assertEquals(\"ALTER TABLE tb1 UPDATE A = 1, B = 1, C = 2 WHERE ID = 1;\", //\n            output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        System.out.println(\"psql : \" + psql);\n        assertEquals(\"ALTER TABLE tb1 UPDATE A = ?, B = ?, C = ? WHERE ID = ?;\", psql);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n            String sql = \"alter table tb1 ON CLUSTER cluster update A=1,B=1,C=2 IN PARTITION partition_id where ID = 1;\"\n            + \"alter table tb1 ON CLUSTER cluster update A=3,B=4,C=5 IN PARTITION partition_id where ID = 2;\";\n        CKStatementParser parser = new CKStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(2, statementList.size());\n\n        CKStatVisitor visitor = new CKStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"test_3.Tables : \" + visitor.getTables());\n        System.out.println(\"test_3.fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"tb1\"));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, DbType.clickhouse);\n        System.out.println(\"output : \" + output);\n        assertEquals(\"ALTER TABLE tb1 ON CLUSTER cluster UPDATE A = 1, B = 1, C = 2 IN PARTITION partition_id WHERE ID = 1;\", //\n            output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.clickhouse);\n        System.out.println(\"psql : \" + psql);\n        assertEquals(\"ALTER TABLE tb1 ON CLUSTER ? UPDATE A = ?, B = ?, C = ? IN PARTITION ? WHERE ID = ?;\", psql);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"update tb1 set A=1,B=1,C=2 IN aaa where ID = 1;\";\n        MySqlStatementParser mp = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = mp.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(statementList);\n\n        String output = SQLUtils.toSQLString(stmt, DbType.mysql);\n        System.out.println(\"output : \" + output);\n        assertEquals(\"UPDATE tb1\\n\"\n                + \"SET A = 1, B = 1, C = 2 IN (aaa)\\n\"\n                + \"WHERE ID = 1;\", //\n            output);\n\n        String psql = ParameterizedOutputVisitorUtils.parameterize(sql, DbType.mysql);\n        System.out.println(\"psql : \" + psql);\n        assertEquals(\"UPDATE tb1\\n\"\n            + \"SET A = ?, B = ?, C = ? IN (aaa)\\n\"\n            + \"WHERE ID = ?;\", psql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/clickhouse/issues/Issue5933.java",
    "content": "package com.alibaba.druid.bvt.sql.clickhouse.issues;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://github.com/alibaba/druid/issues/5933\" >Issue来源</a>\n * @see <a href=\"https://clickhouse.com/docs/en/sql-reference/statements/select/array-join\">ARRAY JOIN Clause</a>\n */\npublic class Issue5933 {\n    @Test\n    public void test_parse_arrauy_join_0() {\n        for (DbType dbType : new DbType[]{DbType.clickhouse}) {\n            for (String sql : new String[]{\n                \"SELECT * FROM base_customized_cost \"\n                    + \"ARRAY JOIN split.service AS service \"\n                    + \"WHERE capture_time >= DATE('2024-04-01') \"\n                    + \"AND capture_time < DATE('2024-05-01') LIMIT 100;\",\n            }) {\n                System.out.println(\"最原始SQL===\" + sql);\n                SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n                List<SQLStatement> statementList = parser.parseStatementList();\n                System.out.println(statementList);\n                assertEquals(1, statementList.size());\n                SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n                SQLJoinTableSource sts = (SQLJoinTableSource) stmt.getSelect().getQueryBlock().getFrom();\n                System.out.println(\"JOIN类型 \" + sts.getJoinType());\n                assertEquals(\"ARRAY JOIN\", sts.getJoinType().name);\n                assertEquals(\"SELECT *\\n\"\n                    + \"FROM base_customized_cost\\n\"\n                    + \"\\tARRAY JOIN split.service AS service\\n\"\n                    + \"WHERE capture_time >= DATE('2024-04-01')\\n\"\n                    + \"\\tAND capture_time < DATE('2024-05-01')\\n\"\n                    + \"LIMIT 100;\", stmt.toString());\n                SQLParseAssertUtil.assertParseSql(sql, dbType);\n            }\n        }\n    }\n\n    @Test\n    public void test_parse_arrauy_join_all() {\n        for (DbType dbType : new DbType[]{DbType.clickhouse}) {\n            for (String sql : new String[]{\n                \"SELECT s, arr\\n\"\n                    + \"FROM arrays_test\\n\"\n                    + \"LEFT ARRAY JOIN arr;\",\n                \"SELECT s, arr\\n\"\n                    + \"FROM arrays_test\\n\"\n                    + \"ARRAY JOIN arr;\",\n                \"SELECT s, arr\\n\"\n                    + \"FROM arrays_test\\n\"\n                    + \"LEFT ARRAY JOIN arr;\",\n                \"SELECT s, arr, a\\n\"\n                    + \"FROM arrays_test\\n\"\n                    + \"ARRAY JOIN arr AS a;\",\n                \"SELECT s, arr_external\\n\"\n                    + \"FROM arrays_test\\n\"\n                    + \"ARRAY JOIN [1, 2, 3] AS arr_external;\",\n                \"SELECT s, arr, a, num, mapped\\n\"\n                    + \"FROM arrays_test\\n\"\n                    + \"ARRAY JOIN arr AS a, arrayEnumerate(arr) AS num, arrayMap(x -> x + 1, arr) AS mapped;\",\n                \"SELECT s, arr, a, num, arrayEnumerate(arr)\\n\"\n                    + \"FROM arrays_test\\n\"\n                    + \"ARRAY JOIN arr AS a, arrayEnumerate(arr) AS num;\",\n                \"SELECT s, arr, a, b\\n\"\n                    + \"FROM arrays_test ARRAY JOIN arr as a, [['a','b'],['c']] as b\\n\"\n                    + \"SETTINGS enable_unaligned_array_join = 1;\",\n                \"SELECT s, `nest.x`, `nest.y`\\n\"\n                    + \"FROM nested_test\\n\"\n                    + \"ARRAY JOIN nest;\",\n                \"SELECT s, `nest.x`, `nest.y`\\n\"\n                    + \"FROM nested_test\\n\"\n                    + \"ARRAY JOIN `nest.x`, `nest.y`;\",\n                \"SELECT s, `nest.x`, `nest.y`\\n\"\n                    + \"FROM nested_test\\n\"\n                    + \"ARRAY JOIN `nest.x`;\",\n                \"SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`\\n\"\n                    + \"FROM nested_test\\n\"\n                    + \"ARRAY JOIN nest AS n;\",\n                \"SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`, num\\n\"\n                    + \"FROM nested_test\\n\"\n                    + \"ARRAY JOIN nest AS n, arrayEnumerate(`nest.x`) AS num;\",\n                \"SELECT arrayJoin([1, 2, 3] AS src) AS dst, 'Hello', src\",\n            }) {\n                System.out.println(\"最原始SQL===\" + sql);\n                SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n                List<SQLStatement> statementList = parser.parseStatementList();\n                System.out.println(statementList);\n                assertEquals(1, statementList.size());\n                SQLParseAssertUtil.assertParseSql(sql, dbType);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DALParserTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * (created at 2011-5-20)\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DALParserTest {\n    @Test\n    public void testdesc() throws Exception {\n        String sql = \"desc tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement desc = parser.parseDescribe();\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(desc);\n        assertEquals(\"DESC tb1\", output);\n    }\n\n    @Test\n    public void testdesc_1() throws Exception {\n        String sql = \"desc db.tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement desc = parser.parseDescribe();\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(desc);\n        assertEquals(\"DESC db.tb1\", output);\n    }\n\n    @Test\n    public void testdesc_2() throws Exception {\n        String sql = \"describe db.tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement desc = parser.parseDescribe();\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(desc);\n        assertEquals(\"DESC db.tb1\", output);\n    }\n\n    @Test\n    public void testSet_1() throws Exception {\n        String sql = \"seT sysVar1 = ? \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET sysVar1 = ?\", output);\n    }\n\n    @Test\n    public void testSet_2() throws Exception {\n        String sql = \"SET `sysVar1` = ?, @@gloBal . `var2` :=1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET `sysVar1` = ?, @@global.`var2` = 1\", output);\n    }\n\n    @Test\n    public void testSet_3() throws Exception {\n        String sql = \"SET @usrVar1 := ?, @@`var2` =1, @@var3:=?, @'var\\\\'3'=?\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET @usrVar1 = ?, @@`var2` = 1, @@var3 = ?, @'var\\\\'3' = ?\", output);\n    }\n\n    @Test\n    public void testSet_4() throws Exception {\n        String sql = \"SET GLOBAL var1=1, SESSION var2:=2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET @@global.var1 = 1, @@session.var2 = 2\", output);\n    }\n\n    @Test\n    public void testSet_5() throws Exception {\n        String sql = \"SET @@GLOBAL. var1=1, SESSION var2:=2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLSetStatement set = (SQLSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET @@global.var1 = 1, @@session.var2 = 2\", output);\n    }\n\n    @Test\n    public void testSetTxn_0() throws Exception {\n        String sql = \"SET transaction ISOLATION LEVEL READ UNCOMMITTED\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlSetTransactionStatement set = (MySqlSetTransactionStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED\", output);\n    }\n\n    @Test\n    public void testSetTxn_1() throws Exception {\n        String sql = \"SET global transaction ISOLATION LEVEL READ COMMITTED\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlSetTransactionStatement set = (MySqlSetTransactionStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED\", output);\n    }\n\n    @Test\n    public void testSetTxn_2() throws Exception {\n        String sql = \"SET transaction ISOLATION LEVEL REPEATABLE READ \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlSetTransactionStatement set = (MySqlSetTransactionStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ\", output);\n    }\n\n    @Test\n    public void testSetTxn_3() throws Exception {\n        String sql = \"SET session transaction ISOLATION LEVEL SERIALIZABLE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlSetTransactionStatement set = (MySqlSetTransactionStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE\", output);\n    }\n\n    @Test\n    public void test_setNames() throws Exception {\n        String sql = \"SET names default \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement set = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET NAMES DEFAULT\", output);\n    }\n\n    @Test\n    public void test_setNames_1() throws Exception {\n        String sql = \"SET NAMEs 'utf8' collatE \\\"latin1_danish_ci\\\" \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement set = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET NAMES 'utf8' COLLATE \\\"latin1_danish_ci\\\"\", output);\n    }\n\n    @Test\n    public void test_setNames_2() throws Exception {\n        String sql = \"SET NAMEs utf8 \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement set = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET NAMES utf8\", output);\n    }\n\n    @Test\n    public void test_setCharSet() throws Exception {\n        String sql = \"SET CHARACTEr SEt 'utf8'  \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement set = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET CHARACTER SET 'utf8'\", output);\n    }\n\n    @Test\n    public void test_setCharSet_1() throws Exception {\n        String sql = \"SET CHARACTEr SEt DEFaULT  \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement set = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(set);\n        assertEquals(\"SET CHARACTER SET DEFAULT\", output);\n    }\n\n    @Test\n    public void test_show_authors() throws Exception {\n        String sql = \"shoW authors \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowAuthorsStatement show = (MySqlShowAuthorsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW AUTHORS\", output);\n    }\n\n    @Test\n    public void test_show_binaryLogs() throws Exception {\n        String sql = \"SHOW BINARY LOGS \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowBinaryLogsStatement show = (MySqlShowBinaryLogsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW BINARY LOGS\", output);\n    }\n\n    @Test\n    public void test_show_masterLogs() throws Exception {\n        String sql = \"SHOW MASTER LOGS \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowMasterLogsStatement show = (MySqlShowMasterLogsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW MASTER LOGS\", output);\n    }\n\n    @Test\n    public void test_show_collation() throws Exception {\n        String sql = \"SHOW collation\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCollationStatement show = (MySqlShowCollationStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW COLLATION\", output);\n    }\n\n    @Test\n    public void test_show_collation_1() throws Exception {\n        String sql = \"SHOW Collation like 'var1'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCollationStatement show = (MySqlShowCollationStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW COLLATION LIKE 'var1'\", output);\n    }\n\n    @Test\n    public void test_show_collation_2() throws Exception {\n        String sql = \"SHOW COLLATION WHERE `Default` = 'Yes'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCollationStatement show = (MySqlShowCollationStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW COLLATION WHERE `Default` = 'Yes'\", output);\n    }\n\n    @Test\n    public void test_show_collation_3() throws Exception {\n        String sql = \"SHOW collation where Collation like 'big5%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCollationStatement show = (MySqlShowCollationStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW COLLATION WHERE Collation LIKE 'big5%'\", output);\n    }\n\n    @Test\n    public void test_binaryLog() throws Exception {\n        String sql = \"SHOW binlog events in 'a' from 1 limit 1,2  \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowBinLogEventsStatement show = (MySqlShowBinLogEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW BINLOG EVENTS IN 'a' FROM 1 LIMIT 1, 2\", output);\n    }\n\n    @Test\n    public void test_binaryLog_1() throws Exception {\n        String sql = \"SHOW binlog events from 1 limit 1,2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowBinLogEventsStatement show = (MySqlShowBinLogEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW BINLOG EVENTS FROM 1 LIMIT 1, 2\", output);\n    }\n\n    @Test\n    public void test_binaryLog_2() throws Exception {\n        String sql = \"SHOW binlog events \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowBinLogEventsStatement show = (MySqlShowBinLogEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW BINLOG EVENTS\", output);\n    }\n\n    @Test\n    public void test_show_character_set() throws Exception {\n        String sql = \"SHOW CHARACTER SET like 'var' \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCharacterSetStatement show = (MySqlShowCharacterSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CHARACTER SET LIKE 'var'\", output);\n    }\n\n    @Test\n    public void test_show_character_set2() throws Exception {\n        String sql = \"SHOW CHARSET\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCharacterSetStatement show = (MySqlShowCharacterSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CHARACTER SET\", output);\n    }\n\n    @Test\n    public void test_show_character_set3() throws Exception {\n        String sql = \"SHOW CHARSET like 'utf8'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCharacterSetStatement show = (MySqlShowCharacterSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CHARACTER SET LIKE 'utf8'\", output);\n    }\n\n    @Test\n    public void test_show_character_set_1() throws Exception {\n        String sql = \"SHOW CHARACTER SET where Charset = 'big5'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCharacterSetStatement show = (MySqlShowCharacterSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CHARACTER SET WHERE Charset = 'big5'\", output);\n    }\n\n    @Test\n    public void test_show_character_set_2() throws Exception {\n        String sql = \"SHOW CHARACTER SET\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCharacterSetStatement show = (MySqlShowCharacterSetStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CHARACTER SET\", output);\n    }\n\n    @Test\n    public void test_show_columns() throws Exception {\n        String sql = \"SHOW full columns from tb1 from db1 like 'var' \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowColumnsStatement show = (SQLShowColumnsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FULL COLUMNS FROM db1.tb1 LIKE 'var'\", output);\n    }\n\n    @Test\n    public void test_show_columns_1() throws Exception {\n        String sql = \"show columns from events where Field = 'name'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowColumnsStatement show = (SQLShowColumnsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW COLUMNS FROM events WHERE Field = 'name'\", output);\n    }\n\n    @Test\n    public void test_show_columns_2() throws Exception {\n        String sql = \"SHOW COLUMNS FROM City\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowColumnsStatement show = (SQLShowColumnsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW COLUMNS FROM City\", output);\n    }\n\n    @Test\n    public void test_show_columns_3() throws Exception {\n        String sql = \"SHOW full columns from db1.tb1 like 'var' \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowColumnsStatement show = (SQLShowColumnsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FULL COLUMNS FROM db1.tb1 LIKE 'var'\", output);\n    }\n\n    @Test\n    public void test_show_columns_4() throws Exception {\n        String sql = \"SHOW full columns from tb1 from db1 where count(col)>10 \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowColumnsStatement show = (SQLShowColumnsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FULL COLUMNS FROM db1.tb1 WHERE count(col) > 10\", output);\n    }\n\n    @Test\n    public void test_show_contributors() throws Exception {\n        String sql = \"SHOW contributors\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowContributorsStatement show = (MySqlShowContributorsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CONTRIBUTORS\", output);\n    }\n\n    @Test\n    public void test_show_create_database() throws Exception {\n        String sql = \"SHOW CREATE DATABASE db_name\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCreateDatabaseStatement show = (MySqlShowCreateDatabaseStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE DATABASE db_name\", output);\n    }\n\n    @Test\n    public void test_show_create_database_2() throws Exception {\n        String sql = \"SHOW CREATE SCHEMA IF NOT EXISTS db1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCreateDatabaseStatement show = (MySqlShowCreateDatabaseStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE DATABASE IF NOT EXISTS db1\", output);\n    }\n\n    @Test\n    public void test_show_create_event() throws Exception {\n        String sql = \"SHOW CREATE event db_name\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCreateEventStatement show = (MySqlShowCreateEventStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE EVENT db_name\", output);\n    }\n\n    @Test\n    public void test_show_create_function() throws Exception {\n        String sql = \"SHOW CREATE function x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCreateFunctionStatement show = (MySqlShowCreateFunctionStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE FUNCTION x\", output);\n    }\n\n    @Test\n    public void test_show_create_PROCEDURE() throws Exception {\n        String sql = \"SHOW CREATE PROCEDURE x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCreateProcedureStatement show = (MySqlShowCreateProcedureStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE PROCEDURE x\", output);\n    }\n\n    @Test\n    public void test_show_create_table() throws Exception {\n        String sql = \"SHOW CREATE table x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowCreateTableStatement show = (SQLShowCreateTableStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE TABLE x\", output);\n    }\n\n    @Test\n    public void test_show_create_table_2() throws Exception {\n        String sql = \"SHOW CREATE table db.tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowCreateTableStatement show = (SQLShowCreateTableStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE TABLE db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_create_table_3() throws Exception {\n        String sql = \"SHOW ALL CREATE table catalog.db.tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowCreateTableStatement show = (SQLShowCreateTableStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ALL CREATE TABLE catalog.db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_create_trigger() throws Exception {\n        String sql = \"SHOW CREATE trigger x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowCreateTriggerStatement show = (MySqlShowCreateTriggerStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE TRIGGER x\", output);\n    }\n\n    @Test\n    public void test_show_create_view() throws Exception {\n        String sql = \"SHOW CREATE VIEW x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowCreateViewStatement show = (SQLShowCreateViewStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW CREATE VIEW x\", output);\n    }\n\n    @Test\n    public void test_show_databases() throws Exception {\n        String sql = \"SHOW DATABASES\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowDatabasesStatement show = (SQLShowDatabasesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DATABASES\", output);\n    }\n\n    @Test\n    public void test_show_databases_1() throws Exception {\n        String sql = \"SHOW DATABASES LIKE 'a%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowDatabasesStatement show = (SQLShowDatabasesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DATABASES LIKE 'a%'\", output);\n    }\n\n    @Test\n    public void test_show_databases_2() throws Exception {\n        String sql = \"SHOW DATABASES WHERE `Database` = 'mysql'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowDatabasesStatement show = (SQLShowDatabasesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DATABASES WHERE `Database` = 'mysql'\", output);\n    }\n\n    @Test\n    public void test_show_engine() throws Exception {\n        String sql = \"SHOW ENGINE INNODB STATUS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEngineStatement show = (MySqlShowEngineStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ENGINE INNODB STATUS\", output);\n    }\n\n    @Test\n    public void test_show_engine_1() throws Exception {\n        String sql = \"SHOW ENGINE PERFORMANCE_SCHEMA STATUS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEngineStatement show = (MySqlShowEngineStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ENGINE PERFORMANCE_SCHEMA STATUS\", output);\n    }\n\n    @Test\n    public void test_show_engine_2() throws Exception {\n        String sql = \"SHOW ENGINE INNODB mutex\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEngineStatement show = (MySqlShowEngineStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ENGINE INNODB MUTEX\", output);\n    }\n\n    @Test\n    public void test_show_engines() throws Exception {\n        String sql = \"SHOW ENGINES\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEnginesStatement show = (MySqlShowEnginesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ENGINES\", output);\n    }\n\n    @Test\n    public void test_show_engines_1() throws Exception {\n        String sql = \"SHOW STORAGE ENGINES\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEnginesStatement show = (MySqlShowEnginesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW STORAGE ENGINES\", output);\n    }\n\n    @Test\n    public void test_show_errors() throws Exception {\n        String sql = \"SHOW COUNT(*) ERRORS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowErrorsStatement show = (MySqlShowErrorsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW COUNT(*) ERRORS\", output);\n    }\n\n    @Test\n    public void test_show_errors_1() throws Exception {\n        String sql = \"SHOW ERRORS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowErrorsStatement show = (MySqlShowErrorsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ERRORS\", output);\n    }\n\n    @Test\n    public void test_show_errors_2() throws Exception {\n        String sql = \"SHOW ERRORS limit 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowErrorsStatement show = (MySqlShowErrorsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ERRORS LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_errors_3() throws Exception {\n        String sql = \"SHOW ERRORS limit 1, 2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowErrorsStatement show = (MySqlShowErrorsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW ERRORS LIMIT 1, 2\", output);\n    }\n\n    @Test\n    public void test_show_events() throws Exception {\n        String sql = \"SHOW EVENTS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEventsStatement show = (MySqlShowEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW EVENTS\", output);\n    }\n\n    @Test\n    public void test_show_events_1() throws Exception {\n        String sql = \"SHOW EVENTS from x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEventsStatement show = (MySqlShowEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW EVENTS FROM x\", output);\n    }\n\n    @Test\n    public void test_show_events_2() throws Exception {\n        String sql = \"SHOW EVENTS in x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEventsStatement show = (MySqlShowEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW EVENTS FROM x\", output);\n    }\n\n    @Test\n    public void test_show_events_3() throws Exception {\n        String sql = \"SHOW EVENTS in x like '%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEventsStatement show = (MySqlShowEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW EVENTS FROM x LIKE '%'\", output);\n    }\n\n    @Test\n    public void test_show_events_4() throws Exception {\n        String sql = \"SHOW EVENTS in x where 1 = 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowEventsStatement show = (MySqlShowEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW EVENTS FROM x WHERE 1 = 1\", output);\n    }\n\n    @Test\n    public void test_show_function_code() throws Exception {\n        String sql = \"SHOW function code x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowFunctionCodeStatement show = (MySqlShowFunctionCodeStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FUNCTION CODE x\", output);\n    }\n\n    @Test\n    public void test_show_function_status() throws Exception {\n        String sql = \"SHOW function status like '%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowFunctionStatusStatement show = (MySqlShowFunctionStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FUNCTION STATUS LIKE '%'\", output);\n    }\n\n    @Test\n    public void test_show_function_status_1() throws Exception {\n        String sql = \"SHOW function status where 1 = 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowFunctionStatusStatement show = (MySqlShowFunctionStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FUNCTION STATUS WHERE 1 = 1\", output);\n    }\n\n    @Test\n    public void test_show_function_status_2() throws Exception {\n        String sql = \"SHOW function status \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowFunctionStatusStatement show = (MySqlShowFunctionStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FUNCTION STATUS\", output);\n    }\n\n    @Test\n    public void test_show_grants() throws Exception {\n        String sql = \"SHOW GRANTS FOR 'root'@'localhost';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowGrantsStatement show = (MySqlShowGrantsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW GRANTS FOR 'root'@'localhost';\", output);\n    }\n\n    @Test\n    public void test_show_grants_1() throws Exception {\n        String sql = \"SHOW GRANTS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowGrantsStatement show = (MySqlShowGrantsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW GRANTS\", output);\n    }\n\n    @Test\n    public void test_show_grants_2() throws Exception {\n        String sql = \"SHOW GRANTS FOR CURRENT_USER\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowGrantsStatement show = (MySqlShowGrantsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW GRANTS FOR CURRENT_USER\", output);\n    }\n\n    @Test\n    public void test_show_grants_3() throws Exception {\n        String sql = \"SHOW GRANTS FOR CURRENT_USER()\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowGrantsStatement show = (MySqlShowGrantsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW GRANTS FOR CURRENT_USER()\", output);\n    }\n\n    @Test\n    public void test_show_index() throws Exception {\n        String sql = \"SHOW index from tb1 from db\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowIndexesStatement show = (SQLShowIndexesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW INDEX FROM db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_index_1() throws Exception {\n        String sql = \"SHOW index in tb1 in db\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowIndexesStatement show = (SQLShowIndexesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW INDEX FROM db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_index_2() throws Exception {\n        String sql = \"SHOW index in db.tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowIndexesStatement show = (SQLShowIndexesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW INDEX FROM db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_key() throws Exception {\n        String sql = \"SHOW keys from tb1 from db\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowIndexesStatement show = (SQLShowIndexesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW KEYS FROM db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_key_1() throws Exception {\n        String sql = \"SHOW keys in tb1 in db\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowIndexesStatement show = (SQLShowIndexesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW KEYS FROM db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_key_2() throws Exception {\n        String sql = \"SHOW keys in db.tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowIndexesStatement show = (SQLShowIndexesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW KEYS FROM db.tb1\", output);\n    }\n\n    @Test\n    public void test_show_key_3() throws Exception {\n        String sql = \"SHOW KEYS FROM tb1 IN db1 where maxlength = 2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowIndexesStatement show = (SQLShowIndexesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW KEYS FROM db1.tb1 WHERE maxlength = 2\", output);\n    }\n\n    @Test\n    public void test_master_status() throws Exception {\n        String sql = \"SHOW MASTER STATUS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowMasterStatusStatement show = (MySqlShowMasterStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW MASTER STATUS\", output);\n    }\n\n    @Test\n    public void test_open_tables() throws Exception {\n        String sql = \"SHOW OPEN TABLES\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowOpenTablesStatement show = (MySqlShowOpenTablesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW OPEN TABLES\", output);\n    }\n\n    @Test\n    public void test_open_tables_1() throws Exception {\n        String sql = \"SHOW OPEN TABLES FROM mysql\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowOpenTablesStatement show = (MySqlShowOpenTablesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW OPEN TABLES FROM mysql\", output);\n    }\n\n    @Test\n    public void test_open_tables_2() throws Exception {\n        String sql = \"SHOW OPEN TABLES in mysql\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowOpenTablesStatement show = (MySqlShowOpenTablesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW OPEN TABLES FROM mysql\", output);\n    }\n\n    @Test\n    public void test_open_tables_3() throws Exception {\n        String sql = \"SHOW OPEN TABLES in mysql like '%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowOpenTablesStatement show = (MySqlShowOpenTablesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW OPEN TABLES FROM mysql LIKE '%'\", output);\n    }\n\n    @Test\n    public void test_open_tables_4() throws Exception {\n        String sql = \"SHOW OPEN TABLES in mysql where 1 = 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowOpenTablesStatement show = (MySqlShowOpenTablesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW OPEN TABLES FROM mysql WHERE 1 = 1\", output);\n    }\n\n    @Test\n    public void test_show_open_plugins() throws Exception {\n        String sql = \"SHOW plugins\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowPluginsStatement show = (MySqlShowPluginsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PLUGINS\", output);\n    }\n\n    @Test\n    public void test_show_PRIVILEGES() throws Exception {\n        String sql = \"SHOW PRIVILEGES\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowPrivilegesStatement show = (MySqlShowPrivilegesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PRIVILEGES\", output);\n    }\n\n    @Test\n    public void test_show_dblock() throws Exception {\n        String sql = \"SHOW dblock\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MysqlShowDbLockStatement show = (MysqlShowDbLockStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DBLOCK\", output);\n    }\n\n    @Test\n    public void test_show_htc() throws Exception {\n        String sql = \"SHOW htc\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MysqlShowHtcStatement show = (MysqlShowHtcStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW HTC\", output);\n    }\n\n    @Test\n    public void test_show_Stc() throws Exception {\n        String sql = \"SHOW Stc\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MysqlShowStcStatement show = (MysqlShowStcStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW STC\", output);\n    }\n\n    @Test\n    public void test_show_Stc_1() throws Exception {\n        String sql = \"SHOW Stc his\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MysqlShowStcStatement show = (MysqlShowStcStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW STC HIS\", output);\n    }\n\n    @Test\n    public void test_show_procedure_code() throws Exception {\n        String sql = \"SHOW procedure code x\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcedureCodeStatement show = (MySqlShowProcedureCodeStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROCEDURE CODE x\", output);\n    }\n\n    @Test\n    public void test_show_procedure_status() throws Exception {\n        String sql = \"SHOW procedure status like '%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcedureStatusStatement show = (MySqlShowProcedureStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROCEDURE STATUS LIKE '%'\", output);\n    }\n\n    @Test\n    public void test_show_procedure_status_1() throws Exception {\n        String sql = \"SHOW procedure status where 1 = 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcedureStatusStatement show = (MySqlShowProcedureStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROCEDURE STATUS WHERE 1 = 1\", output);\n    }\n\n    @Test\n    public void test_show_procedure_status_2() throws Exception {\n        String sql = \"SHOW procedure status \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcedureStatusStatement show = (MySqlShowProcedureStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROCEDURE STATUS\", output);\n    }\n\n    @Test\n    public void test_show_processList() throws Exception {\n        String sql = \"SHOW processlist \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcessListStatement show = (MySqlShowProcessListStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROCESSLIST\", output);\n    }\n\n    @Test\n    public void test_show_processList_1() throws Exception {\n        String sql = \"SHOW full processlist \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcessListStatement show = (MySqlShowProcessListStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FULL PROCESSLIST\", output);\n    }\n\n    @Test\n    public void test_show_processList_2() throws Exception {\n        String sql = \"SHOW processlist where id = 3\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcessListStatement show = (MySqlShowProcessListStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        assertEquals(\"SHOW PROCESSLIST WHERE id = 3\", show.toString());\n        assertEquals(\"show processlist where id = 3\", show.toLowerCaseString());\n    }\n\n    @Test\n    public void test_show_processList_3() throws Exception {\n        String sql = \"SHOW processlist order by id desc\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcessListStatement show = (MySqlShowProcessListStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        assertEquals(\"SHOW PROCESSLIST ORDER BY id DESC\", show.toString());\n        assertEquals(\"show processlist order by id desc\", show.toLowerCaseString());\n    }\n\n    @Test\n    public void test_show_processList_4() throws Exception {\n        String sql = \"SHOW processlist limit 3, 4\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProcessListStatement show = (MySqlShowProcessListStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        assertEquals(\"SHOW PROCESSLIST LIMIT 3, 4\", show.toString());\n        assertEquals(\"show processlist limit 3, 4\", show.toLowerCaseString());\n    }\n\n    @Test\n    public void test_show_profiles() throws Exception {\n        String sql = \"SHOW profiles\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProfilesStatement show = (MySqlShowProfilesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROFILES\", output);\n    }\n\n    @Test\n    public void test_show_profile() throws Exception {\n        String sql = \"SHOW profile\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProfileStatement show = (MySqlShowProfileStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROFILE\", output);\n    }\n\n    @Test\n    public void test_show_profile_1() throws Exception {\n        String sql = \"SHOW profile all,block io,context switches,cpu,ipc,memory, page faults,source,swaps for query 2 limit 1 offset 2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowProfileStatement show = (MySqlShowProfileStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PROFILE ALL, BLOCK IO, CONTEXT SWITCHES, CPU, IPC, MEMORY, PAGE FAULTS, SOURCE, SWAPS FOR QUERY 2 LIMIT 1 OFFSET 2\", output);\n    }\n\n    @Test\n    public void test_show_relayLogEvents() throws Exception {\n        String sql = \"SHOW RELAYLOG EVENTS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowRelayLogEventsStatement show = (MySqlShowRelayLogEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW RELAYLOG EVENTS\", output);\n    }\n\n    @Test\n    public void test_show_relayLogEvents_1() throws Exception {\n        String sql = \"SHOW RELAYLOG EVENTS IN 'x' from 3 limit 5,6\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowRelayLogEventsStatement show = (MySqlShowRelayLogEventsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW RELAYLOG EVENTS IN 'x' FROM 3 LIMIT 5, 6\", output);\n    }\n\n    @Test\n    public void test_show_slaveHosts() throws Exception {\n        String sql = \"SHOW SLAVE HOSTS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowSlaveHostsStatement show = (MySqlShowSlaveHostsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW SLAVE HOSTS\", output);\n    }\n\n    @Test\n    public void test_show_slaveStatus() throws Exception {\n        String sql = \"SHOW SLAVE Status\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowSlaveStatusStatement show = (MySqlShowSlaveStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW SLAVE STATUS\", output);\n    }\n\n    @Test\n    public void test_show_status() throws Exception {\n        String sql = \"SHOW STATUS LIKE 'Key%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowStatusStatement show = (MySqlShowStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW STATUS LIKE 'Key%'\", output);\n    }\n\n    @Test\n    public void test_show_slow() throws Exception {\n        String sql = \"SHOW SLOW WHERE 1=1 ORDER BY A LIMIT 10\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowSlowStatement show = (MySqlShowSlowStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW SLOW WHERE 1 = 1 ORDER BY A LIMIT 10\", output);\n    }\n\n    @Test\n    public void test_show_slow_1() throws Exception {\n        String sql = \"SHOW PHYSICAL_SLOW WHERE 1=1 ORDER BY A LIMIT 10\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowSlowStatement show = (MySqlShowSlowStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PHYSICAL_SLOW WHERE 1 = 1 ORDER BY A LIMIT 10\", output);\n    }\n\n    @Test\n    public void test_show_sequence() throws Exception {\n        String sql = \"SHOW SEQUENCES WHERE 1=1 ORDER BY A LIMIT 10\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowSequencesStatement show = (MySqlShowSequencesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW SEQUENCES WHERE 1 = 1 ORDER BY A LIMIT 10\", output);\n    }\n\n    @Test\n    public void test_show_rule() throws Exception {\n        String sql = \"SHOW RULE FROM A WHERE 1=1 ORDER BY A LIMIT 10\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowRuleStatement show = (MySqlShowRuleStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW RULE FROM A WHERE 1 = 1 ORDER BY A LIMIT 10\", output);\n    }\n\n    @Test\n    public void test_show_rule_1() throws Exception {\n        String sql = \"SHOW FULL RULE FROM A WHERE 1=1 ORDER BY A LIMIT 10\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowRuleStatement show = (MySqlShowRuleStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FULL RULE FROM A WHERE 1 = 1 ORDER BY A LIMIT 10\", output);\n    }\n\n    @Test\n    public void test_show_table_status() throws Exception {\n        String sql = \"SHOW TABLE STATUS FROM mysql\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTableStatusStatement show = (MySqlShowTableStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TABLE STATUS FROM mysql\", output);\n    }\n\n    @Test\n    public void test_show_table_status_1() throws Exception {\n        String sql = \"SHOW TABLE STATUS LIKE 'test%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTableStatusStatement show = (MySqlShowTableStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TABLE STATUS LIKE 'test%'\", output);\n    }\n\n    @Test\n    public void test_show_table_status_2() throws Exception {\n        String sql = \"SHOW TABLE STATUS FROM testdb.test_group LIKE 'test%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTableStatusStatement show = (MySqlShowTableStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TABLE STATUS FROM testdb.test_group LIKE 'test%'\", output);\n    }\n\n    @Test\n    public void test_show_table_status_3() throws Exception {\n        String sql = \"SHOW TABLE STATUS FROM testdb.test_group WHERE schema_name = 'ss' or schema_name = 'ss1'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTableStatusStatement show = (MySqlShowTableStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TABLE STATUS FROM testdb.test_group WHERE schema_name = 'ss'\\n\"\n                + \"OR schema_name = 'ss1'\", output);\n    }\n\n    @Test\n    public void test_show_table_status_4() throws Exception {\n        String sql = \"SHOW TABLE STATUS IN testdb.test_group WHERE schema_name = 'ss' or schema_name = 'ss1'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTableStatusStatement show = (MySqlShowTableStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TABLE STATUS FROM testdb.test_group WHERE schema_name = 'ss'\\n\"\n                + \"OR schema_name = 'ss1'\", output);\n    }\n\n    @Test\n    public void test_show_database_status() throws Exception {\n        String sql = \"SHOW DATABASE STATUS LIKE foo\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowDatabaseStatusStatement show = (MySqlShowDatabaseStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DATABASE STATUS LIKE foo\", output);\n    }\n\n    @Test\n    public void test_show_database_status_1() throws Exception {\n        String sql = \"SHOW DATABASE STATUS WHERE 1 = 1 ORDER BY a LIMIT 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowDatabaseStatusStatement show = (MySqlShowDatabaseStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DATABASE STATUS WHERE 1 = 1 ORDER BY a LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_triggers() throws Exception {\n        String sql = \"SHOW TRIGGERS LIKE 'acc%'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTriggersStatement show = (MySqlShowTriggersStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TRIGGERS LIKE 'acc%'\", output);\n    }\n\n    @Test\n    public void test_show_partitions() throws Exception {\n        String sql = \"SHOW PARTITIONS from a\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement show = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PARTITIONS FROM a\", output);\n    }\n\n    @Test\n    public void test_show_partitions_2() throws Exception {\n        String sql = \"SHOW PARTITIONS a\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement show = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW PARTITIONS FROM a\", output);\n    }\n\n    @Test\n    public void test_show_tables_1() throws Exception {\n        String sql = \"SHOW FULL TABLES from a\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowTablesStatement show = (SQLShowTablesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FULL TABLES FROM a\", output);\n    }\n\n    @Test\n    public void test_show_tables_2() throws Exception {\n        String sql = \"SHOW FULL TABLES LIKE a\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowTablesStatement show = (SQLShowTablesStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW FULL TABLES LIKE a\", output);\n    }\n\n    @Test\n    public void test_show_trace_01() throws Exception {\n        String sql = \"SHOW TRACE WHERE 1=1 order by a limit 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTraceStatement show = (MySqlShowTraceStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TRACE WHERE 1 = 1 ORDER BY a LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_trace_02() throws Exception {\n        String sql = \"SHOW TRACE WHERE 1=1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTraceStatement show = (MySqlShowTraceStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TRACE WHERE 1 = 1\", output);\n    }\n\n    @Test\n    public void test_show_trace_03() throws Exception {\n        String sql = \"SHOW TRACE WHERE 1=1 limit 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTraceStatement show = (MySqlShowTraceStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TRACE WHERE 1 = 1 LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_topology_01() throws Exception {\n        String sql = \"SHOW TOPOLOGY T1 WHERE 1=1 limit 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTopologyStatement show = (MySqlShowTopologyStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TOPOLOGY FROM T1 WHERE 1 = 1 LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_triggers_1() throws Exception {\n        String sql = \"SHOW triggers in db where strcmp('test1', 'test2')\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowTriggersStatement show = (MySqlShowTriggersStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW TRIGGERS FROM db WHERE strcmp('test1', 'test2')\", output);\n    }\n\n    @Test\n    public void test_show_broadcast_1() throws Exception {\n        String sql = \"SHOW broadcasts WHERE 1=1 order by a limit 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowBroadcastsStatement show = (MySqlShowBroadcastsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW BROADCASTS WHERE 1 = 1 ORDER BY a LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_ds_1() throws Exception {\n        String sql = \"SHOW DS WHERE 1=1 order by a limit 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowDsStatement show = (MySqlShowDsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DS WHERE 1 = 1 ORDER BY a LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_dbstatus_1() throws Exception {\n        String sql = \"SHOW ddl status WHERE 1=1 order by a limit 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowDdlStatusStatement show = (MySqlShowDdlStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW DDL STATUS WHERE 1 = 1 ORDER BY a LIMIT 1\", output);\n    }\n\n    @Test\n    public void test_show_variants() throws Exception {\n        String sql = \"SHOW VARIABLES LIKE '%size%';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowVariantsStatement show = (SQLShowVariantsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW VARIABLES LIKE '%size%';\", output);\n    }\n\n    @Test\n    public void test_show_variants_1() throws Exception {\n        String sql = \"SHOW GLOBAL VARIABLES LIKE '%size%';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowVariantsStatement show = (SQLShowVariantsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW GLOBAL VARIABLES LIKE '%size%';\", output);\n    }\n\n    @Test\n    public void test_show_variants_2() throws Exception {\n        String sql = \"SHOW SESSION VARIABLES LIKE '%size%';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLShowVariantsStatement show = (SQLShowVariantsStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(show);\n        assertEquals(\"SHOW SESSION VARIABLES LIKE '%size%';\", output);\n    }\n\n    @Test\n    public void test_plancache_1() throws Exception {\n        String sql = \"SHOW PLANCACHE status\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlShowPlanCacheStatusStatement stmt = (MySqlShowPlanCacheStatusStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW PLANCACHE STATUS\", output);\n    }\n\n    @Test\n    public void test_plancache_2() throws Exception {\n        String sql = \"DISABLED PLANCACHE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlDisabledPlanCacheStatement stmt = (MySqlDisabledPlanCacheStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DISABLED PLANCACHE\", output);\n    }\n\n    @Test\n    public void test_plancache_3() throws Exception {\n        String sql = \"CLEAR PLANCACHE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlClearPlanCacheStatement stmt = (MySqlClearPlanCacheStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CLEAR PLANCACHE\", output);\n    }\n\n    @Test\n    public void test_plancache_4() throws Exception {\n        String sql = \"UPDATE PLANCACHE SELECT A FROM T1 where t1.a = 1 TO SELECT B2 FROM T2 where t2.a = 2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlUpdatePlanCacheStatement stmt = (MySqlUpdatePlanCacheStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"UPDATE PLANCACHE SELECT A\\n\"\n                + \"FROM T1\\n\"\n                + \"WHERE t1.a = 1\\n\"\n                + \" TO \\n\"\n                + \"SELECT B2\\n\"\n                + \"FROM T2\\n\"\n                + \"WHERE t2.a = 2\", output);\n    }\n\n    @Test\n    public void test_plancache_5() throws Exception {\n        String sql = \"EXPLAIN PLANCACHE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        MySqlExplainPlanCacheStatement stmt = (MySqlExplainPlanCacheStatement) parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"EXPLAIN PLANCACHE\", output);\n    }\n\n//\n//    public void testShow() throws Exception {\n//\n//        sql =\n//                \"SHOW profile all,block io,context switches,cpu,ipc,memory,\"\n//                        + \"page faults,source,swaps for query 2 limit 1 offset 2\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW PROFILE ALL, BLOCK IO, CONTEXT SWITCHES, CPU, IPC, MEMORY, \"\n//                            + \"PAGE FAULTS, SOURCE, SWAPS FOR QUERY 2 LIMIT 2, 1\", output);\n//\n//        sql = \"SHOW profile\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW PROFILE\", output);\n//\n//        sql = \"SHOW profile all,block io,context switches,cpu,ipc,\" + \"memory,page faults,source,swaps for query 2\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW PROFILE ALL, BLOCK IO, CONTEXT SWITCHES, CPU, IPC, \"\n//                            + \"MEMORY, PAGE FAULTS, SOURCE, SWAPS FOR QUERY 2\", output);\n//\n//        sql = \"SHOW profile all for query 2\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW PROFILE ALL FOR QUERY 2\", output);\n//\n//        sql = \"SHOW slave hosts\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SLAVE HOSTS\", output);\n//\n//        sql = \"SHOW slave status\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SLAVE STATUS\", output);\n//\n//        sql = \"SHOW global status like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW GLOBAL STATUS LIKE 'expr'\", output);\n//\n//        sql = \"SHOW global status where ${abc}\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW GLOBAL STATUS WHERE ${abc}\", output);\n//\n//        sql = \"SHOW session status like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION STATUS LIKE 'expr'\", output);\n//\n//        sql = \"SHOW session status where ?\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION STATUS WHERE ?\", output);\n//\n//        sql = \"SHOW status like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION STATUS LIKE 'expr'\", output);\n//\n//        sql = \"SHOW status where 0b10^b'11'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION STATUS WHERE b'10' ^ b'11'\", output);\n//\n//        sql = \"SHOW status\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION STATUS\", output);\n//\n//        sql = \"SHOW global status\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW GLOBAL STATUS\", output);\n//\n//        sql = \"SHOW session status\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION STATUS\", output);\n//\n//        sql = \"SHOW table status from db like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLE STATUS FROM db LIKE 'expr'\", output);\n//\n//        sql = \"SHOW table status in db where (select a)>(select b)\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLE STATUS FROM db WHERE (SELECT a) > (SELECT b)\", output);\n//\n//        sql = \"SHOW table status from db where id1=a||b\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLE STATUS FROM db WHERE id1 = a OR b\", output);\n//\n//        sql = \"SHOW table status \";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLE STATUS\", output);\n//\n//        sql = \"SHOW tables from db like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLES FROM db LIKE 'expr'\", output);\n//\n//        sql = \"SHOW tables in db where !a\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLES FROM db WHERE ! a\", output);\n//\n//        sql = \"SHOW tables like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLES LIKE 'expr'\", output);\n//\n//        sql = \"SHOW tables where log((select a))=b\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLES WHERE LOG(SELECT a) = b\", output);\n//\n//        sql = \"SHOW tables \";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TABLES\", output);\n//\n//        sql = \"SHOW full tables from db like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW FULL TABLES FROM db LIKE 'expr'\", output);\n//\n//        sql = \"SHOW full tables in db where id1=abs((select a))\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW FULL TABLES FROM db WHERE id1 = ABS(SELECT a)\", output);\n//\n//        sql = \"SHOW full tables \";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW FULL TABLES\", output);\n//\n//        sql = \"SHOW triggers from db like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TRIGGERS FROM db LIKE 'expr'\", output);\n//\n//        sql = \"SHOW triggers in db where strcmp('test1','test2')\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TRIGGERS FROM db WHERE STRCMP('test1', 'test2')\", output);\n//\n//        sql = \"SHOW triggers \";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW TRIGGERS\", output);\n//\n//        sql = \"SHOW global variables like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW GLOBAL VARIABLES LIKE 'expr'\", output);\n//\n//        sql = \"SHOW global variables where ~a is null\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW GLOBAL VARIABLES WHERE ~ a IS NULL\", output);\n//\n//        sql = \"SHOW session variables like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION VARIABLES LIKE 'expr'\", output);\n//\n//        sql = \"SHOW session variables where a*b+1=c\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION VARIABLES WHERE a * b + 1 = c\", output);\n//\n//        sql = \"SHOW variables like 'expr'\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION VARIABLES LIKE 'expr'\", output);\n//\n//        sql = \"SHOW variables where a&&b\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION VARIABLES WHERE a AND b\", output);\n//\n//        sql = \"SHOW variables\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION VARIABLES\", output);\n//\n//        sql = \"SHOW global variables\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW GLOBAL VARIABLES\", output);\n//\n//        sql = \"SHOW session variables\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW SESSION VARIABLES\", output);\n//\n//        sql = \"SHOW warnings limit 1,2 \";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW WARNINGS LIMIT 1, 2\", output);\n//\n//        sql = \"SHOW warnings\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW WARNINGS\", output);\n//\n//        sql = \"SHOW count(*) warnings\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DALParser(lexer, new SQLExprParser(lexer));\n//        show = (DALShowStatement) parser.show();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(show, sql);\n//        assertEquals(\"SHOW COUNT(*) WARNINGS\", output);\n//    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DDLParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * (created at 2011-7-18)\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author <a href=\"mailto:danping.yudp@alibaba-inc.com\">YU Danping</a>\n */\npublic class DDLParserTest {\n    @Test\n    public void testTruncate() throws Exception {\n        String sql = \"Truncate table tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"TRUNCATE TABLE tb1\", output);\n    }\n\n    @Test\n    public void testTruncate_1() throws Exception {\n        String sql = \"Truncate tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"TRUNCATE TABLE tb1\", output);\n    }\n\n    @Test\n    public void testAlterTable_0() throws Exception {\n        String sql = \"alTer ignore table tb_name\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER IGNORE TABLE tb_name\", output);\n    }\n\n    @Test\n    public void testAlterTable_1() throws Exception {\n        String sql = \"alTer table tb_name\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE tb_name\", output);\n    }\n\n    @Test\n    public void testAlterTable_2() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD COLUMN `name` VARCHAR(45) NULL  AFTER `fid` ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tADD COLUMN `name` VARCHAR(45) NULL AFTER `fid`;\", output);\n    }\n\n    @Test\n    public void testAlterTable_3() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` DROP COLUMN `name` ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tDROP COLUMN `name`;\", output);\n    }\n\n    @Test\n    public void test_createTable_0() throws Exception {\n        String sql = \"crEate temporary tabLe if not exists tb_name (fid int)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"CREATE TEMPORARY TABLE IF NOT EXISTS tb_name (\\n\\tfid int\\n)\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"create temporary table if not exists tb_name (\\n\\tfid int\\n)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_createTable_1() throws Exception {\n        String sql = \"crEate tabLe if not exists tb_name (fid int)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS tb_name (\\n\\tfid int\\n)\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"create table if not exists tb_name (\\n\\tfid int\\n)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_createIndex_0() throws Exception {\n        String sql = \"create index `idx1` ON tb1 (`fname` ASC) ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE INDEX `idx1` ON tb1 (`fname` ASC);\", output);\n    }\n\n    @Test\n    public void test_createIndex_1() throws Exception {\n        String sql = \"create unique index `idx1` ON tb1 (`fname` desc) ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE INDEX `idx1` ON tb1 (`fname` DESC);\", output);\n    }\n\n    @Test\n    public void test_createIndex_2() throws Exception {\n        String sql = \"CREATE INDEX id_index ON lookup (id) USING BTREE;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE INDEX id_index ON lookup (id) USING BTREE;\", output);\n    }\n\n    @Test\n    public void test_createIndex_3() throws Exception {\n        String sql = \"crEate index index_name using hash on tb(col(id))\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE INDEX index_name ON tb (col(id)) USING HASH\", output);\n    }\n\n    @Test\n    public void test_createIndex_4() throws Exception {\n        String sql = \"crEate spatial index index_name on tb(col(id))\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE SPATIAL INDEX index_name ON tb (col(id))\", output);\n    }\n\n    @Test\n    public void test_drop_index_0() throws Exception {\n        String sql = \"drop index index_name on tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP INDEX index_name ON tb1\", output);\n    }\n\n    @Test\n    public void test_drop_index_1() throws Exception {\n        String sql = \"DROP INDEX `PRIMARY` ON t;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP INDEX `PRIMARY` ON t;\", output);\n    }\n\n    @Test\n    public void test_drop_table_0() throws Exception {\n        String sql = \"DROP TEMPORARY TABLE IF EXISTS tb1, tb2, tb3 RESTRICT\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP TEMPORARY TABLE IF EXISTS tb1, tb2, tb3 RESTRICT\", output);\n    }\n\n    @Test\n    public void test_drop_table_1() throws Exception {\n        String sql = \"DROP TEMPORARY TABLE IF EXISTS tb1, tb2, tb3 CASCADE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP TEMPORARY TABLE IF EXISTS tb1, tb2, tb3 CASCADE\", output);\n    }\n\n    @Test\n    public void test_drop_table_2() throws Exception {\n        String sql = \"DROP TABLE t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP TABLE t1\", output);\n    }\n\n    @Test\n    public void test_rename_0() throws Exception {\n        String sql = \"RENAME TABLE current_db.tbl_name TO other_db.tbl_name\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"RENAME TABLE current_db.tbl_name TO other_db.tbl_name\", output);\n    }\n\n    @Test\n    public void test_rename_1() throws Exception {\n        String sql = \"rename table tb1 to ntb1,tb2 to ntb2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"RENAME TABLE tb1 TO ntb1, tb2 TO ntb2\", output);\n    }\n\n    @Test\n    public void test_drop_view_1() throws Exception {\n        String sql = \"DROP VIEW IF EXISTS tb1, tb2, tb3 CASCADE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP VIEW IF EXISTS tb1, tb2, tb3 CASCADE\", output);\n    }\n\n    @Test\n    public void test_drop_view_2() throws Exception {\n        String sql = \"DROP VIEW t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP VIEW t1\", output);\n    }\n    // public void testDDLStmt() throws Exception {\n    //\n    // sql = \"rename table tb1 to ntb1,tb2 to ntb2\";\n    // lexer = new SQLLexer(sql);\n    // parser = new DDLParser(lexer, new SQLExprParser(lexer));\n    // dst = parser.ddlStmt();\n    // output = output2MySQL(dst, sql);\n    // assertEquals(\"RENAME TABLE tb1 TO ntb1, tb2 TO ntb2\", output);\n    //\n    // sql = \"rename table tb1 to ntb1\";\n    // lexer = new SQLLexer(sql);\n    // parser = new DDLParser(lexer, new SQLExprParser(lexer));\n    // dst = parser.ddlStmt();\n    // output = output2MySQL(dst, sql);\n    // assertEquals(\"RENAME TABLE tb1 TO ntb1\", output);\n    // }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DMLCallParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * (created at 2011-7-18)\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author <a href=\"mailto:danping.yudp@alibaba-inc.com\">YU Danping</a>\n */\n\npublic class DMLCallParserTest {\n    @Test\n    public void testCall_0() throws Exception {\n        String sql = \"call p(?,?)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CALL p(?, ?)\", output);\n    }\n\n    @Test\n    public void testCall_1() throws Exception {\n        String sql = \"call p(@var1,'@var2',var3)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CALL p(@var1, '@var2', var3)\", output);\n    }\n\n    @Test\n    public void testCall_2() throws Exception {\n        String sql = \"call p()\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CALL p()\", output);\n    }\n\n//    public void testCall() throws SQLSyntaxErrorException {\n//        String sql = \"call p(?,?) \";\n//        SQLLexer lexer = new SQLLexer(sql);\n//        DMLCallParser parser = new DMLCallParser(lexer, new SQLExprParser(lexer));\n//        DMLCallStatement calls = parser.call();\n//        parser.match(Token.EOF);\n//        String output = output2MySQL(calls, sql);\n//        assertEquals(\"CALL p(?, ?)\", output);\n//\n//        sql = \"call p(@var1,'@var2',var3)\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DMLCallParser(lexer, new SQLExprParser(lexer));\n//        calls = parser.call();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(calls, sql);\n//        assertEquals(\"CALL p(@var1, '@var2', var3)\", output);\n//\n//        sql = \"call p()\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DMLCallParser(lexer, new SQLExprParser(lexer));\n//        calls = parser.call();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(calls, sql);\n//        assertEquals(\"CALL p()\", output);\n//\n//        sql = \"call p(?)\";\n//        lexer = new SQLLexer(sql);\n//        parser = new DMLCallParser(lexer, new SQLExprParser(lexer));\n//        calls = parser.call();\n//        parser.match(Token.EOF);\n//        output = output2MySQL(calls, sql);\n//        assertEquals(\"CALL p(?)\", output);\n//    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DMLDeleteParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DMLDeleteParserTest {\n    @Test\n    public void testDelete_0() throws Exception {\n        String sql = \"deLetE LOW_PRIORITY from id1.id , id using t1 a where col1 =? \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE LOW_PRIORITY FROM id1.id, id\\n\" +\n                \"USING t1 a\\n\" +\n                \"WHERE col1 = ?\", output);\n    }\n\n    @Test\n    public void testDelete_1() throws Exception {\n        String sql = \"deLetE from id1.id  using t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE FROM id1.id\" +\n                \"\\nUSING t1\", output);\n    }\n\n    @Test\n    public void testDelete_2() throws Exception {\n        String sql = \"delete from offer.*,wp_image.* using offer a,wp_image b where a.member_id=b.member_id and a.member_id='abc' \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE FROM offer.*, wp_image.*\\n\" +\n                \"USING offer a, wp_image b\\n\" +\n                \"WHERE a.member_id = b.member_id\\n\" +\n                \"\\tAND a.member_id = 'abc'\", output);\n    }\n\n    @Test\n    public void testDelete_3() throws Exception {\n        String sql = \"deLetE from id1.id where col1='adf' limit 1,?\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE FROM id1.id\\n\" +\n                \"WHERE col1 = 'adf'\\n\" +\n                \"LIMIT 1, ?\", output);\n    }\n\n    @Test\n    public void testDelete_4() throws Exception {\n        String sql = \"deLetE from id where col1='adf' ordEr by d liMit ? offset 2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE FROM id\\n\" +\n                \"WHERE col1 = 'adf'\\n\" +\n                \"ORDER BY d\\n\" +\n                \"LIMIT ? OFFSET 2\", output);\n    }\n\n    @Test\n    public void testDelete_5() throws Exception {\n        String sql = \"deLetE id.* from t1,t2 where col1='adf'            and col2=1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE id.*\\n\" +\n                \"FROM t1, t2\\n\" +\n                \"WHERE col1 = 'adf'\\n\" +\n                \"\\tAND col2 = 1\", output);\n    }\n\n    @Test\n    public void testDelete_6() throws Exception {\n        String sql = \"deLetE id,id.t from t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE id, id.t\\n\" +\n                \"FROM t1\", output);\n    }\n\n    @Test\n    public void testDelete_7() throws Exception {\n        String sql = \"deLetE from t1 where t1.id1='abc' order by a limit 5\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE FROM t1\\n\" +\n                \"WHERE t1.id1 = 'abc'\\n\" +\n                \"ORDER BY a\\n\" +\n                \"LIMIT 5\", output);\n    }\n\n    @Test\n    public void testDelete_8() throws Exception {\n        String sql = \"deLetE from t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE FROM t1\", output);\n    }\n\n    @Test\n    public void testDelete_9() throws Exception {\n        String sql = \"deLetE ignore tb1.*,id1.t from t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE IGNORE tb1.*, id1.t\\n\" +\n                \"FROM t1\", output);\n    }\n\n    @Test\n    public void testDelete_10() throws Exception {\n        String sql = \"deLetE quick tb1.*,id1.t from t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DELETE QUICK tb1.*, id1.t\\n\" +\n                \"FROM t1\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DMLInsertParserTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DMLInsertParserTest {\n    @Test\n    public void testInsert_0() throws Exception {\n        String sql = \"insErt HIGH_PRIORITY intO test.t1 seT t1.id1=?, id2 := '123'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT HIGH_PRIORITY INTO test.t1 (t1.id1, id2)\\n\" +\n                \"VALUES (?, '123')\", output);\n    }\n\n    @Test\n    public void testInsert_1() throws Exception {\n        String sql = \"insErt  IGNORE test.t1 seT t1.id1:=? oN dupLicatE key UPDATE ex.col1=?, col2=12\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT IGNORE INTO test.t1 (t1.id1)\\nVALUES (?)\" +\n                \"\\nON DUPLICATE KEY UPDATE ex.col1 = ?, col2 = 12\", output);\n    }\n\n    @Test\n    public void testInsert_2() throws Exception {\n        String sql = \"insErt t1 value (123,?) oN dupLicatE key UPDATE ex.col1=?\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT INTO t1\\nVALUES (123, ?)\\nON DUPLICATE KEY UPDATE ex.col1 = ?\", output);\n    }\n\n    @Test\n    public void testInsert_3() throws Exception {\n        String sql = \"insErt LOW_PRIORITY t1 valueS (12e-2,1,2), (?),(default)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT LOW_PRIORITY INTO t1\\nVALUES (12e-2, 1, 2),\" +\n                \"\\n\\t(?),\" +\n                \"\\n\\t(DEFAULT)\", output);\n    }\n\n    @Test\n    public void testInsert_4() throws Exception {\n        String sql = \"insErt LOW_PRIORITY t1 select id from t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT LOW_PRIORITY INTO t1\\nSELECT id\\nFROM t1\", output);\n    }\n\n    @Test\n    public void testInsert_5() throws Exception {\n        String sql = \"insErt LOW_PRIORITY t1 (select id from t1) oN dupLicatE key UPDATE ex.col1=?, col2=12\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT LOW_PRIORITY INTO t1\\n\" +\n                        \"(SELECT id\\n\" +\n                        \"FROM t1)\\n\" +\n                        \"ON DUPLICATE KEY UPDATE ex.col1 = ?, col2 = 12\",\n                output);\n    }\n\n    @Test\n    public void testInsert_6() throws Exception {\n        String sql = \"insErt LOW_PRIORITY t1 (t1.col1) valueS (123),('12''34')\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT LOW_PRIORITY INTO t1 (t1.col1)\\nVALUES (123),\" +\n                \"\\n\\t('12''34')\", output);\n    }\n\n    @Test\n    public void testInsert_8() throws Exception {\n        String sql = \"insErt LOW_PRIORITY t1 (col1, t1.col2) select id from t3 oN dupLicatE key UPDATE ex.col1=?\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT LOW_PRIORITY INTO t1 (col1, t1.col2)\\nSELECT id\\nFROM t3\" +\n                        \"\\nON DUPLICATE KEY UPDATE ex.col1 = ?\",\n                output);\n    }\n\n    @Test\n    public void testInsert_9() throws Exception {\n        String sql = \"insErt LOW_PRIORITY IGNORE intO t1 (col1) ( select id from t3) \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT LOW_PRIORITY IGNORE INTO t1 (col1)\\nSELECT id\\nFROM t3\", output);\n    }\n\n    @Test\n    public void test_date() throws Exception {\n        SimpleDateFormat fmt = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        Date date = fmt.parse(\"0000-00-00 00:00:00\");\n        System.out.printf(fmt.format(date));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DMLInsertParserTest_Special.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DMLInsertParserTest_Special {\n    @Test\n    public void testInsert_7() throws Exception {\n        String sql = \"insErt LOW_PRIORITY t1 (col1, t1.col2) VALUE (123,'123\\\\'4') oN dupLicatE key UPDATE ex.col1=?\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"INSERT LOW_PRIORITY INTO t1 (col1, t1.col2)\\nVALUES (123, '123''4')\" +\n                        \"\\nON DUPLICATE KEY UPDATE ex.col1 = ?\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DMLReplaceParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DMLReplaceParserTest {\n    @Test\n    public void testReplace_0() throws Exception {\n        String sql = \"ReplaCe LOW_PRIORITY intO test.t1 seT t1.id1:=?, id2='123'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO test.t1 (t1.id1, id2)\\nVALUES (?, '123')\", output);\n    }\n\n    @Test\n    public void testReplace_1() throws Exception {\n        String sql = \"ReplaCe   test.t1 seT t1.id1:=? \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE INTO test.t1 (t1.id1)\\nVALUES (?)\", output);\n    }\n\n    @Test\n    public void testReplace_2() throws Exception {\n        String sql = \"ReplaCe t1 value (123,?) \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE INTO t1\\nVALUES (123, ?)\", output);\n    }\n\n    @Test\n    public void testReplace_3() throws Exception {\n        String sql = \"ReplaCe LOW_PRIORITY t1 valueS (12e-2), (?)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO t1\\nVALUES (12e-2), (?)\", output);\n    }\n\n    @Test\n    public void testReplace_4() throws Exception {\n        String sql = \"ReplaCe LOW_PRIORITY t1 select id from t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO t1\\n\\tSELECT id\\n\\tFROM t1\", output);\n    }\n\n    @Test\n    public void testReplace_5() throws Exception {\n        String sql = \"ReplaCe delayed t1 select id from t1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE DELAYED INTO t1\\n\\tSELECT id\\n\\tFROM t1\", output);\n    }\n\n    @Test\n    public void testReplace_6() throws Exception {\n        String sql = \"ReplaCe LOW_PRIORITY t1 (select id from t1) \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO t1\\n\\tSELECT id\\n\\tFROM t1\", output);\n    }\n\n    @Test\n    public void testReplace_7() throws Exception {\n        String sql = \"ReplaCe LOW_PRIORITY t1 (t1.col1) valueS (123),('12''34')\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO t1 (t1.col1)\\nVALUES (123), ('12''34')\", output);\n    }\n\n    @Test\n    public void testReplace_8() throws Exception {\n        String sql = \"ReplaCe LOW_PRIORITY t1 (col1, t1.col2) VALUE (123,'123\\\\'4') \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO t1 (col1, t1.col2)\\nVALUES (123, '123''4')\", output);\n    }\n\n    @Test\n    public void testReplace_9() throws Exception {\n        String sql = \"REPLACE LOW_PRIORITY t1 (col1, t1.col2) select id from t3 \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO t1 (col1, t1.col2)\\n\\tSELECT id\\n\\tFROM t3\", output);\n    }\n\n    @Test\n    public void testReplace_10() throws Exception {\n        String sql = \"replace LOW_PRIORITY  intO t1 (col1) ( select id from t3) \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"REPLACE LOW_PRIORITY INTO t1 (col1)\\n\" +\n                \"\\t(SELECT id\\n\" +\n                \"\\tFROM t3)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DMLSelectParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DMLSelectParserTest {\n    @Test\n    public void test_union_0() throws Exception {\n        String sql = \"(select id from t1) union all (select id from t2) union all (select id from t3) ordeR By d desC limit 1 offset ?\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"(SELECT id\\n\" +\n                \"FROM t1)\\n\" +\n                \"UNION ALL\\n\" +\n                \"(SELECT id\\n\" +\n                \"FROM t2)\\n\" +\n                \"UNION ALL\\n\" +\n                \"(SELECT id\\n\" +\n                \"FROM t3)\\n\" +\n                \"ORDER BY d DESC\\n\" +\n                \"LIMIT 1 OFFSET ?\", output);\n    }\n\n    @Test\n    public void test_union_1() throws Exception {\n        String sql = \"(select id from t1) union  select id from t2 order by id union aLl (select id from t3) ordeR By d asC\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"(SELECT id\\n\" +\n                \"FROM t1)\\n\" +\n                \"UNION\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM t2\\n\" +\n                \"ORDER BY id\\n\" +\n                \"UNION ALL\\n\" +\n                \"(SELECT id\\n\" +\n                \"FROM t3)\\n\" +\n                \"ORDER BY d ASC\", output);\n    }\n\n    @Test\n    public void test_union_2() throws Exception {\n        String sql = \"(select id from t1) union distInct (select id from t2) union  select id from t3\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"(SELECT id\\n\" +\n                \"FROM t1)\\n\" +\n                \"UNION DISTINCT\\n\" +\n                \"(SELECT id\\n\" +\n                \"FROM t2)\\n\" +\n                \"UNION\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM t3\", output);\n    }\n\n    @Test\n    public void test_select_0() throws Exception {\n        String sql = \"SELect t1.id , t2.* from t1, test.t2 where test.t1.id=1 and t1.id=test.t2.id\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT t1.id, t2.*\\n\" +\n                \"FROM t1, test.t2\\n\" +\n                \"WHERE test.t1.id = 1\\n\" +\n                \"\\tAND t1.id = test.t2.id\", output);\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        String sql = \"select * from  offer  a  straight_join wp_image b use key for join(t1,t2) on a.member_id=b.member_id inner join product_visit c where a.member_id=c.member_id and c.member_id='abc' \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM offer a\" +\n                \"\\n\\tSTRAIGHT_JOIN wp_image b USE INDEX FOR JOIN (t1, t2) ON a.member_id = b.member_id\" +\n                \"\\n\\tINNER JOIN product_visit c\" +\n                \"\\nWHERE a.member_id = c.member_id\\n\" +\n                \"\\tAND c.member_id = 'abc'\", output);\n    }\n\n    @Test\n    public void test_select_2() throws Exception {\n        String sql = \"SELect all tb1.id,tb2.id from tb1,tb2 where tb1.id2=tb2.id2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT ALL tb1.id, tb2.id\\n\" +\n                \"FROM tb1, tb2\\n\" +\n                \"WHERE tb1.id2 = tb2.id2\", output);\n    }\n\n    @Test\n    public void test_select_3() throws Exception {\n        String sql = \"SELect distinct high_priority tb1.id,tb2.id from tb1,tb2 where tb1.id2=tb2.id2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT DISTINCT HIGH_PRIORITY tb1.id, tb2.id\\nFROM tb1, tb2\\nWHERE tb1.id2 = tb2.id2\",\n                output);\n    }\n\n    @Test\n    public void test_select_4() throws Exception {\n        String sql = \"SELect distinctrow high_priority sql_small_result tb1.id,tb2.id from tb1,tb2 where tb1.id2=tb2.id2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT DISTINCTROW HIGH_PRIORITY SQL_SMALL_RESULT tb1.id, tb2.id\\nFROM tb1, tb2\\nWHERE tb1.id2 = tb2.id2\",\n                output);\n    }\n\n    @Test\n    public void test_select_5() throws Exception {\n        String sql = \"SELect  sql_cache id1,id2 from tb1,tb2 where tb1.id1=tb2.id1 \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT SQL_CACHE id1, id2\\nFROM tb1, tb2\\nWHERE tb1.id1 = tb2.id1\", output);\n    }\n\n    @Test\n    public void test_select_6() throws Exception {\n        String sql = \"SELect distinct high_priority tb1.id,tb2.id from tb1,tb2 where tb1.id2=tb2.id2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT DISTINCT HIGH_PRIORITY tb1.id, tb2.id\\nFROM tb1, tb2\\nWHERE tb1.id2 = tb2.id2\",\n                output);\n    }\n\n    @Test\n    public void test_select_7() throws Exception {\n        String sql = \"SELect distinctrow high_priority sql_small_result tb1.id,tb2.id \"\n                + \"from tb1,tb2 where tb1.id2=tb2.id2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT DISTINCTROW HIGH_PRIORITY SQL_SMALL_RESULT tb1.id, tb2.id\\nFROM tb1, tb2\\nWHERE tb1.id2 = tb2.id2\",\n                output);\n    }\n\n    @Test\n    public void test_select_8() throws Exception {\n        String sql = \"SELect  sql_cache id1,id2 from tb1,tb2 where tb1.id1=tb2.id1 \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT SQL_CACHE id1, id2\\nFROM tb1, tb2\\nWHERE tb1.id1 = tb2.id1\", output);\n    }\n\n    @Test\n    public void test_select_9() throws Exception {\n        String sql = \"SELect  sql_cache id1,max(id2) from tb1 group by id1 having id1>10 order by id3 desc\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT SQL_CACHE id1, max(id2)\\nFROM tb1\\nGROUP BY id1\\nHAVING id1 > 10\\nORDER BY id3 DESC\",\n                output);\n    }\n\n    @Test\n    public void test_select_10() throws Exception {\n        String sql = \"SELect  SQL_BUFFER_RESULT tb1.id1,id2 from tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT SQL_BUFFER_RESULT tb1.id1, id2\\nFROM tb1\", output);\n    }\n\n    @Test\n    public void test_select_11() throws Exception {\n        String sql = \"SELect  SQL_no_cache tb1.id1,id2 from tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT SQL_NO_CACHE tb1.id1, id2\\nFROM tb1\", output);\n    }\n\n    @Test\n    public void test_select_12() throws Exception {\n        String sql = \"SELect  SQL_CALC_FOUND_ROWS tb1.id1,id2 from tb1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT SQL_CALC_FOUND_ROWS tb1.id1, id2\\nFROM tb1\", output);\n    }\n\n    @Test\n    public void test_select_13() throws Exception {\n        String sql = \"SELect 1+1 \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT 1 + 1\", output);\n    }\n\n    @Test\n    public void test_select_14() throws Exception {\n        String sql = \"SELect t1.* from tb \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT t1.*\\nFROM tb\", output);\n    }\n\n    @Test\n    public void test_select_15() throws Exception {\n        String sql = \"SELect distinct high_priority straight_join sql_big_result sql_cache tb1.id,tb2.id \"\n                + \"from tb1,tb2 where tb1.id2=tb2.id2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT DISTINCT HIGH_PRIORITY STRAIGHT_JOIN SQL_BIG_RESULT\"\n                + \" SQL_CACHE tb1.id, tb2.id\\nFROM tb1, tb2\\nWHERE tb1.id2 = tb2.id2\", output);\n    }\n\n    @Test\n    public void test_select_16() throws Exception {\n        String sql = \"SELect distinct id1,id2 from tb1,tb2 where tb1.id1=tb2.id2 for update\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT DISTINCT id1, id2\\nFROM tb1, tb2\\nWHERE tb1.id1 = tb2.id2\\nFOR UPDATE\", output);\n    }\n\n    @Test\n    public void test_select_17() throws Exception {\n        String sql = \"SELect distinct id1,id2 from tb1,tb2 where tb1.id1=tb2.id2 lock in share mode\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT DISTINCT id1, id2\\nFROM tb1, tb2\\nWHERE tb1.id1 = tb2.id2\\nLOCK IN SHARE MODE\",\n                output);\n    }\n\n    @Test\n    public void test_select_18() throws Exception {\n        String sql = \"SELect t1.id , t2.* from t1, test.t2 where test.t1.id='中''‘文' and t1.id=test.t2.id\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT t1.id, t2.*\\nFROM t1, test.t2\\nWHERE test.t1.id = '中''‘文'\\n\\tAND t1.id = test.t2.id\",\n                output);\n    }\n\n    @Test\n    public void test_select_19() throws Exception {\n        String sql = \"select * from  offer  a  straight_join wp_image b force index for join(t1,t2) on a.member_id=b.member_id inner join product_visit c where a.member_id=c.member_id and c.member_id='abc' \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM offer a\" +\n                \"\\n\\tSTRAIGHT_JOIN wp_image b FORCE INDEX FOR JOIN (t1, t2) ON a.member_id = b.member_id\" +\n                \"\\n\\tINNER JOIN product_visit c\" +\n                \"\\nWHERE a.member_id = c.member_id\" +\n                \"\\n\\tAND c.member_id = 'abc'\", output);\n    }\n\n    @Test\n    public void test_select_20() throws Exception {\n        String sql = \"select * from  offer  a  straight_join wp_image b ignore index for join(t1,t2) on a.member_id=b.member_id inner join product_visit c where a.member_id=c.member_id and c.member_id='abc' \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM offer a\" +\n                \"\\n\\tSTRAIGHT_JOIN wp_image b IGNORE INDEX FOR JOIN (t1, t2) ON a.member_id = b.member_id\" +\n                \"\\n\\tINNER JOIN product_visit c\" +\n                \"\\nWHERE a.member_id = c.member_id\" +\n                \"\\n\\tAND c.member_id = 'abc'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/DMLUpdateParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DMLUpdateParserTest {\n    @Test\n    public void test_update_0() throws Exception {\n        String sql = \"upDate LOw_PRIORITY IGNORE test.t1 sEt t1.col1=?, col2=DefaulT\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"UPDATE LOW_PRIORITY IGNORE test.t1\\nSET t1.col1 = ?, col2 = DEFAULT\", output);\n    }\n\n    @Test\n    public void test_update_1() throws Exception {\n        String sql = \"upDate  IGNORE (t1) set col2=DefaulT order bY t1.col2 \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"UPDATE IGNORE t1\\nSET col2 = DEFAULT\\nORDER BY t1.col2\", output);\n    }\n\n    @Test\n    public void test_update_2() throws Exception {\n        String sql = \"upDate   (test.t1) SET col2=DefaulT order bY t1.col2 limit ? offset 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"UPDATE test.t1\\nSET col2 = DEFAULT\\nORDER BY t1.col2\\nLIMIT ? OFFSET 1\", output);\n    }\n\n    @Test\n    public void test_update_3() throws Exception {\n        String sql = \"upDate LOW_PRIORITY  t1, test.t2 SET col2=DefaulT , col2='123''4'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"UPDATE LOW_PRIORITY t1, test.t2\\nSET col2 = DEFAULT, col2 = '123''4'\", output);\n    }\n\n    @Test\n    public void test_update_4() throws Exception {\n        String sql = \"upDate LOW_PRIORITY  t1, test.t2 SET col2:=DefaulT , col2='123''4' where id='a'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"UPDATE LOW_PRIORITY t1, test.t2\\nSET col2 = DEFAULT, col2 = '123''4'\\nWHERE id = 'a'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HintsTest {\n    @Test\n    public void test_hints_0() throws Exception {\n        String sql = \"CREATE /*!32302 TEMPORARY */ TABLE t (a INT);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE /*!32302 TEMPORARY */ TABLE t (\\n\\ta INT\\n);\", output);\n    }\n\n    @Test\n    public void test_hints_1() throws Exception {\n        String sql = \"SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SELECT /*! STRAIGHT_JOIN */ col1\\nFROM table1, table2\", output);\n    }\n\n    @Test\n    public void test_hints_none() throws Exception {\n        String sql = \"SELECT /* STRAIGHT_JOIN */ col1 FROM table1,table2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\n            \"SELECT /* STRAIGHT_JOIN */\\n\" + \"\\tcol1\\n\" + \"FROM table1, table2\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/LiteralHexadecimalTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * (created at 2011-11-11)\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.ast.expr.SQLHexExpr;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author <a href=\"mailto:shuo.qius@alibaba-inc.com\">QIU Shuo</a>\n */\npublic class LiteralHexadecimalTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"x'E982B1E7A195275C73'\";\n        SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();\n        assertEquals(\"邱硕'\\\\s\", new String(hex.toBytes(), \"utf-8\"));\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"x'0D0A'\";\n        SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();\n        assertEquals(\"\\r\\n\", new String(hex.toBytes(), \"utf-8\"));\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"X'4D7953514C'\";\n        SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();\n        assertEquals(\"MySQL\", new String(hex.toBytes(), \"utf-8\"));\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"0x5061756c\";\n        SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();\n        assertEquals(\"Paul\", new String(hex.toBytes(), \"utf-8\"));\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"0x41\";\n        SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();\n        assertEquals(\"A\", new String(hex.toBytes(), \"utf-8\"));\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"0x636174\";\n        SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();\n        assertEquals(\"cat\", new String(hex.toBytes(), \"utf-8\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/cobar/MTSParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.cobar;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MTSParserTest {\n    @Test\n    public void test_mts_0() throws Exception {\n        String sql = \"  savepoint xx\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SAVEPOINT xx\", output);\n    }\n\n    @Test\n    public void test_mts_1() throws Exception {\n        String sql = \"  savepoint SAVEPOINT\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SAVEPOINT SAVEPOINT\", output);\n    }\n\n    @Test\n    public void test_mts_2() throws Exception {\n        String sql = \"  savepoInt `select`\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SAVEPOINT `select`\", output);\n    }\n\n    @Test\n    public void test_mts_3() throws Exception {\n        String sql = \"Release sAVEPOINT xx   \";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"RELEASE SAVEPOINT xx\", output);\n    }\n\n    @Test\n    public void test_rollback_0() throws Exception {\n        String sql = \"rollBack to x1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ROLLBACK TO x1\", output);\n    }\n\n    @Test\n    public void test_rollback_1() throws Exception {\n        String sql = \"rollBack work to x1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ROLLBACK TO x1\", output);\n    }\n\n    @Test\n    public void test_rollback_2() throws Exception {\n        String sql = \"rollBack work to savepoint x1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ROLLBACK TO x1\", output);\n    }\n\n    @Test\n    public void test_lockTable() throws Exception {\n        String sql = \"LOCK TABLES t1 READ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"LOCK TABLES t1 READ;\", output);\n    }\n\n    @Test\n    public void test_lockTable_1() throws Exception {\n        String sql = \"LOCK TABLES t2 READ LOCAL;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"LOCK TABLES t2 READ LOCAL;\", output);\n    }\n\n    @Test\n    public void test_unlockTable() throws Exception {\n        String sql = \"UNLOCK TABLES\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"UNLOCK TABLES\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/databricks/DatabricksResourceTest.java",
    "content": "package com.alibaba.druid.bvt.sql.databricks;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class DatabricksResourceTest extends SQLResourceTest {\n    public DatabricksResourceTest() {\n        super(DbType.databricks);\n    }\n\n    @Test\n    public void databricks_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/databricks/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2AlterTableTest_1_setNotNull.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2AlterTableTest_1_setNotNull {\n    @Test\n    public void test_alter_constraint() throws Exception {\n        String sql = \"alter table T_ORG alter column ORG_NAME set not null\";\n        SQLStatement stmt = SQLUtils.parseStatements(sql, JdbcConstants.DB2).get(0);\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"ALTER TABLE T_ORG\\n\" +\n                \"\\tALTER COLUMN ORG_NAME SET NOT NULL\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2AlterTableTest_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2AlterTableTest_2 {\n    @Test\n    public void test_alter_constraint() throws Exception {\n        String sql = \"alter table audit.SQLHIS alter column  EXPLAINMSG set data type VARCHAR(255)\";\n        SQLStatement stmt = SQLUtils.parseStatements(sql, JdbcConstants.DB2).get(0);\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.DB2);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE audit.SQLHIS\\n\" +\n                \"\\tALTER COLUMN EXPLAINMSG SET DATA TYPE VARCHAR(255)\", stmt.toString());\n\n        assertEquals(\"alter table audit.SQLHIS\\n\" +\n                \"\\talter column EXPLAINMSG set data type VARCHAR(255)\", stmt.toLowerCaseString());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2AlterTableTest_drop_pk.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2AlterTableTest_drop_pk {\n    @Test\n    public void test_alter_constraint() throws Exception {\n        String sql = \"alter table supplier drop primary key;\";\n        SQLStatement stmt = SQLUtils.parseStatements(sql, JdbcConstants.DB2).get(0);\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"ALTER TABLE supplier\\n\" +\n                \"\\tDROP PRIMARY KEY;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_01.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_01 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE MK.KPI_AREA_SORT_FACT_LATN_ID_MID\\n\" +\n                \"(\\n\" +\n                \"LATN_ID INTEGER,\\n\" +\n                \"BUREAU_KEY INTEGER,\\n\" +\n                \"ADD_SUM BIGINT,\\n\" +\n                \"USER_ACCT BIGINT,\\n\" +\n                \"USER_ACCT_LY BIGINT,\\n\" +\n                \"TYPE_ID INTEGER\\n\" +\n                \")\\n\" +\n                \"DATA CAPTURE NONE\\n\" +\n                \"IN WH_APP_TEMP\\n\" +\n                \"PARTITIONING KEY\\n\" +\n                \"(LATN_ID,BUREAU_KEY,ADD_SUM\\n\" +\n                \") USING HASHING;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(6, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"MK.KPI_AREA_SORT_FACT_LATN_ID_MID\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"CREATE TABLE MK.KPI_AREA_SORT_FACT_LATN_ID_MID (\\n\" +\n                        \"\\tLATN_ID INTEGER,\\n\" +\n                        \"\\tBUREAU_KEY INTEGER,\\n\" +\n                        \"\\tADD_SUM BIGINT,\\n\" +\n                        \"\\tUSER_ACCT BIGINT,\\n\" +\n                        \"\\tUSER_ACCT_LY BIGINT,\\n\" +\n                        \"\\tTYPE_ID INTEGER\\n\" +\n                        \")\\n\" +\n                        \"DATA CAPTURE NONE\\n\" +\n                        \"IN WH_APP_TEMP\\n\" +\n                        \"PARTITION BY HASH (LATN_ID, BUREAU_KEY, ADD_SUM);\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table MK.KPI_AREA_SORT_FACT_LATN_ID_MID (\\n\" +\n                        \"\\tLATN_ID INTEGER,\\n\" +\n                        \"\\tBUREAU_KEY INTEGER,\\n\" +\n                        \"\\tADD_SUM BIGINT,\\n\" +\n                        \"\\tUSER_ACCT BIGINT,\\n\" +\n                        \"\\tUSER_ACCT_LY BIGINT,\\n\" +\n                        \"\\tTYPE_ID INTEGER\\n\" +\n                        \")\\n\" +\n                        \"DATA CAPTURE NONE\\n\" +\n                        \"IN WH_APP_TEMP\\n\" +\n                        \"partition by hash (LATN_ID, BUREAU_KEY, ADD_SUM);\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_02.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_02 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"   CREATE TABLE DSN8A10.DEPT\\n\" +\n                \"     (DEPTNO   CHAR(3)     NOT NULL,\\n\" +\n                \"      DEPTNAME VARCHAR(36) NOT NULL,\\n\" +\n                \"      MGRNO    CHAR(6)             ,\\n\" +\n                \"      ADMRDEPT CHAR(3)     NOT NULL,\\n\" +\n                \"      LOCATION CHAR(16)            ,\\n\" +\n                \"      PRIMARY KEY(DEPTNO)          )\\n\" +\n                \"     IN DSN8D10A.DSN8S10D;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"DSN8A10.DEPT\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"CREATE TABLE DSN8A10.DEPT (\\n\" +\n                        \"\\tDEPTNO CHAR(3) NOT NULL,\\n\" +\n                        \"\\tDEPTNAME VARCHAR(36) NOT NULL,\\n\" +\n                        \"\\tMGRNO CHAR(6),\\n\" +\n                        \"\\tADMRDEPT CHAR(3) NOT NULL,\\n\" +\n                        \"\\tLOCATION CHAR(16),\\n\" +\n                        \"\\tPRIMARY KEY (DEPTNO)\\n\" +\n                        \")\\n\" +\n                        \"IN DSN8D10A.DSN8S10D;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table DSN8A10.DEPT (\\n\" +\n                        \"\\tDEPTNO CHAR(3) not null,\\n\" +\n                        \"\\tDEPTNAME VARCHAR(36) not null,\\n\" +\n                        \"\\tMGRNO CHAR(6),\\n\" +\n                        \"\\tADMRDEPT CHAR(3) not null,\\n\" +\n                        \"\\tLOCATION CHAR(16),\\n\" +\n                        \"\\tprimary key (DEPTNO)\\n\" +\n                        \")\\n\" +\n                        \"IN DSN8D10A.DSN8S10D;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_03.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_03 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"   CREATE TABLE DSN8A10.PROJ\\n\" +\n                \"     (PROJNO   CHAR(6)      NOT NULL,\\n\" +\n                \"      PROJNAME VARCHAR(24)  NOT NULL,\\n\" +\n                \"      DEPTNO   CHAR(3)      NOT NULL,\\n\" +\n                \"      RESPEMP  CHAR(6)      NOT NULL,\\n\" +\n                \"      PRSTAFF  DECIMAL(5,2)         ,\\n\" +\n                \"      PRSTDATE DATE                 ,\\n\" +\n                \"      PRENDATE DATE                 ,\\n\" +\n                \"      MAJPROJ  CHAR(6)      NOT NULL)\\n\" +\n                \"     IN DATABASE DSN8D10A\\n\" +\n                \"     VALIDPROC DSN8EAPR;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(8, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"DSN8A10.PROJ\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"CREATE TABLE DSN8A10.PROJ (\\n\" +\n                        \"\\tPROJNO CHAR(6) NOT NULL,\\n\" +\n                        \"\\tPROJNAME VARCHAR(24) NOT NULL,\\n\" +\n                        \"\\tDEPTNO CHAR(3) NOT NULL,\\n\" +\n                        \"\\tRESPEMP CHAR(6) NOT NULL,\\n\" +\n                        \"\\tPRSTAFF DECIMAL(5, 2),\\n\" +\n                        \"\\tPRSTDATE DATE,\\n\" +\n                        \"\\tPRENDATE DATE,\\n\" +\n                        \"\\tMAJPROJ CHAR(6) NOT NULL\\n\" +\n                        \")\\n\" +\n                        \"IN DATABASE DSN8D10A\\n\" +\n                        \"VALIDPROC DSN8EAPR;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table DSN8A10.PROJ (\\n\" +\n                        \"\\tPROJNO CHAR(6) not null,\\n\" +\n                        \"\\tPROJNAME VARCHAR(24) not null,\\n\" +\n                        \"\\tDEPTNO CHAR(3) not null,\\n\" +\n                        \"\\tRESPEMP CHAR(6) not null,\\n\" +\n                        \"\\tPRSTAFF DECIMAL(5, 2),\\n\" +\n                        \"\\tPRSTDATE DATE,\\n\" +\n                        \"\\tPRENDATE DATE,\\n\" +\n                        \"\\tMAJPROJ CHAR(6) not null\\n\" +\n                        \")\\n\" +\n                        \"IN DATABASE DSN8D10A\\n\" +\n                        \"VALIDPROC DSN8EAPR;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_04.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_04 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE CUSTOMER\\n\" +\n                \"          (CUSTOMERNUM      INTEGER,\\n\" +\n                \"           CUSTOMERNAME     VARCHAR(80),\\n\" +\n                \"           ADDRESS          VARCHAR(200),\\n\" +\n                \"           CITY             VARCHAR(50),\\n\" +\n                \"           COUNTRY          VARCHAR(50),\\n\" +\n                \"           CODE             VARCHAR(15),\\n\" +\n                \"           CUSTOMERNUMDIM   INTEGER)\\n\" +\n                \"           COMPRESS YES;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"CUSTOMER\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"CREATE TABLE CUSTOMER (\\n\" +\n                        \"\\tCUSTOMERNUM INTEGER,\\n\" +\n                        \"\\tCUSTOMERNAME VARCHAR(80),\\n\" +\n                        \"\\tADDRESS VARCHAR(200),\\n\" +\n                        \"\\tCITY VARCHAR(50),\\n\" +\n                        \"\\tCOUNTRY VARCHAR(50),\\n\" +\n                        \"\\tCODE VARCHAR(15),\\n\" +\n                        \"\\tCUSTOMERNUMDIM INTEGER\\n\" +\n                        \")\\n\" +\n                        \"COMPRESS YES;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table CUSTOMER (\\n\" +\n                        \"\\tCUSTOMERNUM INTEGER,\\n\" +\n                        \"\\tCUSTOMERNAME VARCHAR(80),\\n\" +\n                        \"\\tADDRESS VARCHAR(200),\\n\" +\n                        \"\\tCITY VARCHAR(50),\\n\" +\n                        \"\\tCOUNTRY VARCHAR(50),\\n\" +\n                        \"\\tCODE VARCHAR(15),\\n\" +\n                        \"\\tCUSTOMERNUMDIM INTEGER\\n\" +\n                        \")\\n\" +\n                        \"compress yes;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_05.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_05 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE MK.M_DM_BASE_CHARGE_TMP1\\n\" +\n                \"(PROD_ID BIGINT,\\n\" +\n                \"ITEM_ID SMALLINT,\\n\" +\n                \"CHARGE BIGINT,\\n\" +\n                \"PAGES BIGINT,\\n\" +\n                \"DURATION BIGINT,\\n\" +\n                \"BILLING_DURATION BIGINT\\n\" +\n                \") DATA CAPTURE NONE\\n\" +\n                \"IN MK_APP_TEMP\\n\" +\n                \"INDEX IN WH_INDEX1\\n\" +\n                \"PARTITIONING KEY\\n\" +\n                \"(PROD_ID\\n\" +\n                \") USING HASHING\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(6, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"MK.M_DM_BASE_CHARGE_TMP1\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"CREATE TABLE MK.M_DM_BASE_CHARGE_TMP1 (\\n\" +\n                        \"\\tPROD_ID BIGINT,\\n\" +\n                        \"\\tITEM_ID SMALLINT,\\n\" +\n                        \"\\tCHARGE BIGINT,\\n\" +\n                        \"\\tPAGES BIGINT,\\n\" +\n                        \"\\tDURATION BIGINT,\\n\" +\n                        \"\\tBILLING_DURATION BIGINT\\n\" +\n                        \")\\n\" +\n                        \"DATA CAPTURE NONE\\n\" +\n                        \"IN MK_APP_TEMP\\n\" +\n                        \"INDEX IN WH_INDEX1\\n\" +\n                        \"PARTITION BY HASH (PROD_ID)\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table MK.M_DM_BASE_CHARGE_TMP1 (\\n\" +\n                        \"\\tPROD_ID BIGINT,\\n\" +\n                        \"\\tITEM_ID SMALLINT,\\n\" +\n                        \"\\tCHARGE BIGINT,\\n\" +\n                        \"\\tPAGES BIGINT,\\n\" +\n                        \"\\tDURATION BIGINT,\\n\" +\n                        \"\\tBILLING_DURATION BIGINT\\n\" +\n                        \")\\n\" +\n                        \"DATA CAPTURE NONE\\n\" +\n                        \"IN MK_APP_TEMP\\n\" +\n                        \"INDEX IN WH_INDEX1\\n\" +\n                        \"partition by hash (PROD_ID)\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_06.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_06 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE AUDIT.test ( ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1 ))\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"AUDIT.test\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"CREATE TABLE AUDIT.test (\\n\" +\n                        \"\\tID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1)\\n\" +\n                        \")\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table AUDIT.test (\\n\" +\n                        \"\\tID INTEGER not null generated always as identity (start with 1, increment by 1)\\n\" +\n                        \")\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_07.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_07 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE EMPLOYEE\\n\" +\n                \"  (EMPNO      INTEGER GENERATED ALWAYS AS IDENTITY\\n\" +\n                \"              PRIMARY KEY NOT NULL,\\n\" +\n                \"   NAME       CHAR(30) NOT NULL,\\n\" +\n                \"   SALARY     DECIMAL(7,2) NOT NULL,\\n\" +\n                \"   WORKDEPT   SMALLINT);\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"EMPLOYEE\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"CREATE TABLE EMPLOYEE (\\n\" +\n                        \"\\tEMPNO INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY,\\n\" +\n                        \"\\tNAME CHAR(30) NOT NULL,\\n\" +\n                        \"\\tSALARY DECIMAL(7, 2) NOT NULL,\\n\" +\n                        \"\\tWORKDEPT SMALLINT\\n\" +\n                        \");\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table EMPLOYEE (\\n\" +\n                        \"\\tEMPNO INTEGER primary key not null generated always as identity,\\n\" +\n                        \"\\tNAME CHAR(30) not null,\\n\" +\n                        \"\\tSALARY DECIMAL(7, 2) not null,\\n\" +\n                        \"\\tWORKDEPT SMALLINT\\n\" +\n                        \");\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_08.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2CreateTableTest_08 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE test.EAST_JRG_0911 \\n\" +\n                \"AS ( SELECT * FROM test.EAST_JRGJXXB a WHERE 1=2 ) \\n\" +\n                \"WITH NO DATA\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"test.EAST_JRG_0911\"));\n\n        assertEquals(\"CREATE TABLE test.EAST_JRG_0911\\n\" +\n                        \"AS\\n\" +\n                        \"(SELECT *\\n\" +\n                        \"FROM test.EAST_JRGJXXB a\\n\" +\n                        \"WHERE 1 = 2)\\n\" +\n                        \"WITH NO DATA\",\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"create table test.EAST_JRG_0911\\n\" +\n                        \"as\\n\" +\n                        \"(select *\\n\" +\n                        \"from test.EAST_JRGJXXB a\\n\" +\n                        \"where 1 = 2)\\n\" +\n                        \"with no data\",\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2DropSequenceTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2DropSequenceTest_0 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"drop sequence sales1_seq\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"A\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"A\", \"F_0201\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"DROP SEQUENCE sales1_seq\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"drop sequence sales1_seq\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2InsertTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2InsertTest_0 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"insert into t (id,name) values (?,?), (?,?), (?,?)\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t\", \"id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t\", \"name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"INSERT INTO t (id, name)\\n\" +\n                        \"VALUES (?, ?), (?, ?), (?, ?)\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2InsertTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2InsertTest_1 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"INSERT INTO MK.KPI_AREA_SORT_FACT_LATN_ID_MID\\n\" +\n                \"SELECT LATN_ID,BUREAU_KEY,\\n\" +\n                \"       SUM(ADD_SUM),\\n\" +\n                \"       SUM(USER_ACCT),\\n\" +\n                \"       SUM(USER_ACCT_LY),\\n\" +\n                \"       1 \\n\" +\n                \"  FROM (\\n\" +\n                \"SELECT LATN_ID,\\n\" +\n                \"  CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\\n\" +\n                \"       SUM(COALESCE(USER_CNT_ADD, 0)) ADD_SUM, \\n\" +\n                \"       0 USER_ACCT,\\n\" +\n                \"       0 USER_ACCT_LY\\n\" +\n                \"  FROM MK.M_USER_COUNT_FACT_CDMA\\n\" +\n                \" WHERE THE_DATE BETWEEN SUBSTR('{THISMONTH}', 1, 4) || '-01-01' AND '{THISMONTH}'\\n\" +\n                \"   AND PAG_FLAG = 0\\n\" +\n                \" GROUP BY LATN_ID,\\n\" +\n                \"  CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\\n\" +\n                \"\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT LATN_ID,\\n\" +\n                \"  CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\\n\" +\n                \"       0 ADD_SUM,\\n\" +\n                \"       SUM(COALESCE(USER_CNT_AMOUNT, 0)) USER_ACCT, \\n\" +\n                \"       0 USER_ACCT_LY\\n\" +\n                \"  FROM MK.M_USER_COUNT_FACT_CDMA\\n\" +\n                \" WHERE THE_DATE = '{THISMONTH}'\\n\" +\n                \"   AND PAG_FLAG = 0\\n\" +\n                \" GROUP BY LATN_ID,\\n\" +\n                \"  CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\\n\" +\n                \"  \\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT LATN_ID,\\n\" +\n                \"  CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\\n\" +\n                \"       0 ADD_SUM,\\n\" +\n                \"       0 USER_ACCT,\\n\" +\n                \"       SUM(COALESCE(USER_CNT_AMOUNT, 0)) USER_ACCT_LY  \\n\" +\n                \"  FROM MK.M_USER_COUNT_FACT_CDMA\\n\" +\n                \" WHERE THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) || '-01-01') - 1 MONTHS\\n\" +\n                \"   AND PAG_FLAG = 0 \\n\" +\n                \" GROUP BY LATN_ID,\\n\" +\n                \"  CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\\n\" +\n                \") T\\n\" +\n                \"GROUP BY LATN_ID,BUREAU_KEY\\n\" +\n                \" WITH UR\\n\" +\n                \";\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(11, visitor.getColumns().size());\n        assertEquals(4, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"MK.KPI_AREA_SORT_FACT_LATN_ID_MID\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"MK.M_USER_COUNT_FACT_CDMA\", \"LATN_ID\")));\n//         assertTrue(visitor.getColumns().contains(new Column(\"t\", \"name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"INSERT INTO MK.KPI_AREA_SORT_FACT_LATN_ID_MID\\n\" +\n                        \"SELECT LATN_ID, BUREAU_KEY, SUM(ADD_SUM)\\n\" +\n                        \"\\t, SUM(USER_ACCT), SUM(USER_ACCT_LY)\\n\" +\n                        \"\\t, 1\\n\" +\n                        \"FROM (\\n\" +\n                        \"\\tSELECT LATN_ID\\n\" +\n                        \"\\t\\t, CASE\\n\" +\n                        \"\\t\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\t\\tEND AS BUREAU_KEY, SUM(COALESCE(USER_CNT_ADD, 0)) AS ADD_SUM\\n\" +\n                        \"\\t\\t, 0 AS USER_ACCT, 0 AS USER_ACCT_LY\\n\" +\n                        \"\\tFROM MK.M_USER_COUNT_FACT_CDMA\\n\" +\n                        \"\\tWHERE THE_DATE BETWEEN SUBSTR('{THISMONTH}', 1, 4) CONCAT '-01-01' AND '{THISMONTH}'\\n\" +\n                        \"\\t\\tAND PAG_FLAG = 0\\n\" +\n                        \"\\tGROUP BY LATN_ID, CASE\\n\" +\n                        \"\\t\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\t\\tEND\\n\" +\n                        \"\\tUNION ALL\\n\" +\n                        \"\\tSELECT LATN_ID\\n\" +\n                        \"\\t\\t, CASE\\n\" +\n                        \"\\t\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\t\\tEND AS BUREAU_KEY, 0 AS ADD_SUM\\n\" +\n                        \"\\t\\t, SUM(COALESCE(USER_CNT_AMOUNT, 0)) AS USER_ACCT\\n\" +\n                        \"\\t\\t, 0 AS USER_ACCT_LY\\n\" +\n                        \"\\tFROM MK.M_USER_COUNT_FACT_CDMA\\n\" +\n                        \"\\tWHERE THE_DATE = '{THISMONTH}'\\n\" +\n                        \"\\t\\tAND PAG_FLAG = 0\\n\" +\n                        \"\\tGROUP BY LATN_ID, CASE\\n\" +\n                        \"\\t\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\t\\tEND\\n\" +\n                        \"\\tUNION ALL\\n\" +\n                        \"\\tSELECT LATN_ID\\n\" +\n                        \"\\t\\t, CASE\\n\" +\n                        \"\\t\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\t\\tEND AS BUREAU_KEY, 0 AS ADD_SUM, 0 AS USER_ACCT\\n\" +\n                        \"\\t\\t, SUM(COALESCE(USER_CNT_AMOUNT, 0)) AS USER_ACCT_LY\\n\" +\n                        \"\\tFROM MK.M_USER_COUNT_FACT_CDMA\\n\" +\n                        \"\\tWHERE THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) CONCAT '-01-01') - 1 MONTHS\\n\" +\n                        \"\\t\\tAND PAG_FLAG = 0\\n\" +\n                        \"\\tGROUP BY LATN_ID, CASE\\n\" +\n                        \"\\t\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\t\\tEND\\n\" +\n                        \") T\\n\" +\n                        \"GROUP BY LATN_ID, BUREAU_KEY\\n\" +\n                        \"WITH UR;\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2MergeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2MergeTest extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"MERGE INTO product AS T \"\n                + \"      USING sales AS S\"\n                + \"    ON S.id = T.id\"\n                + \"  WHEN MATCHED THEN UPDATE SET inventory = T.inventory - S.sold;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"sales\"));\n        assertTrue(visitor.containsTable(\"product\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"MERGE INTO product T\\n\" +\n                        \"USING sales S ON S.id = T.id\\n\" +\n                        \"WHEN MATCHED THEN UPDATE\\n\" +\n                        \"SET inventory = T.inventory - S.sold;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"merge into product T\\n\" +\n                        \"using sales S on S.id = T.id\\n\" +\n                        \"when matched then update\\n\" +\n                        \"set inventory = T.inventory - S.sold;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2ResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\n\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2ResourceTest extends OracleTest {\n    public void test_0() throws Exception {\n        exec_test(\"bvt/parser/db2-0.txt\");\n    }\n\n    public void exec_test(String resource) throws Exception {\n        System.out.println(resource);\n        InputStream is = null;\n\n        is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);\n        Reader reader = new InputStreamReader(is, \"UTF-8\");\n        String input = Utils.read(reader);\n        JdbcUtils.close(reader);\n        String[] items = input.split(\"---------------------------\");\n        String sql = items[0].trim();\n        String expect = null;\n        if (items.length > 1) {\n            expect = items[1];\n            expect = expect.trim();\n            expect = expect.replaceAll(\"\\\\r\\\\n\", \"\\n\");\n        }\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n\n        // assertEquals(1, statementList.size());\n\n        System.out.println(sql);\n\n        print(statementList);\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n\n        for (int i = 0, size = statementList.size(); i < size; ++i) {\n            SQLStatement statement = statementList.get(i);\n            statement.accept(visitor);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n\n        System.out.println();\n        System.out.println();\n\n        if (statementList.size() == 1) {\n            SQLStatement stmt = statementList.get(0);\n            if (expect != null && !expect.isEmpty()) {\n                String actual = stmt.toString();\n                assertEquals(expect, actual.trim());\n            }\n        } else {\n            if (expect != null && !expect.isEmpty()) {\n                assertEquals(expect, SQLUtils.toSQLString(statementList, DbType.oracle));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2ResourceTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class DB2ResourceTest2 extends SQLResourceTest {\n    public DB2ResourceTest2() {\n        super(DbType.db2);\n    }\n\n    @Test\n    public void test() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/db2/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_0 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT * FROM DSN81010.EMP;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"SELECT *\"\n                        + \"\\nFROM DSN81010.EMP;\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_1 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT * FROM DSN81010.EMP FETCH FIRST 5 ROWS ONLY;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"SELECT *\"\n                        + \"\\nFROM DSN81010.EMP\"\n                        + \"\\nFETCH FIRST 5 ROWS ONLY;\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_10.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_10 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select * from ( select inner2_.*, rownumber() over(order by order of inner2_) as rownumber_ from (\"\n                + \"     select tsuserstb0_.USERID as USERID1_1_, tsuserstb0_.CREASTAF as CREASTAF2_1_, tsuserstb0_.CREATIME as CREATIME3_1_\"\n                + \"         , tsuserstb0_.LOCORGNO as LOCORGNO4_1_, tsuserstb0_.PWDMODIFYTIME as PWDMODIF5_1_, tsuserstb0_.REMARK01 as REMARK6_1_\"\n                + \"         , tsuserstb0_.REMARK02 as REMARK7_1_, tsuserstb0_.STAORGNO as STAORGNO8_1_, tsuserstb0_.UPDASTAF as UPDASTAF9_1_\"\n                + \"         , tsuserstb0_.UPDATIME as UPDATIM10_1_, tsuserstb0_.USERNAME as USERNAM11_1_, tsuserstb0_.USERPWD as USERPWD12_1_\"\n                + \"         , tsuserstb0_.USERSTATE as USERSTA13_1_ from TS_USERSTB tsuserstb0_ fetch first 20 rows only ) as inner2_ \"\n                + \") as inner1_\"\n                + \" where rownumber_ > 10 order by rownumber_\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(13, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"TS_USERSTB\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT *\\n\" +\n                        \"FROM (\\n\" +\n                        \"\\tSELECT inner2_.*, rownumber() OVER (ORDER BY order OF inner2_) AS rownumber_\\n\" +\n                        \"\\tFROM (\\n\" +\n                        \"\\t\\tSELECT tsuserstb0_.USERID AS USERID1_1_, tsuserstb0_.CREASTAF AS CREASTAF2_1_, tsuserstb0_.CREATIME AS CREATIME3_1_, tsuserstb0_.LOCORGNO AS LOCORGNO4_1_, tsuserstb0_.PWDMODIFYTIME AS PWDMODIF5_1_\\n\" +\n                        \"\\t\\t\\t, tsuserstb0_.REMARK01 AS REMARK6_1_, tsuserstb0_.REMARK02 AS REMARK7_1_, tsuserstb0_.STAORGNO AS STAORGNO8_1_, tsuserstb0_.UPDASTAF AS UPDASTAF9_1_, tsuserstb0_.UPDATIME AS UPDATIM10_1_\\n\" +\n                        \"\\t\\t\\t, tsuserstb0_.USERNAME AS USERNAM11_1_, tsuserstb0_.USERPWD AS USERPWD12_1_, tsuserstb0_.USERSTATE AS USERSTA13_1_\\n\" +\n                        \"\\t\\tFROM TS_USERSTB tsuserstb0_\\n\" +\n                        \"\\t\\tFETCH FIRST 20 ROWS ONLY\\n\" +\n                        \"\\t) inner2_\\n\" +\n                        \") inner1_\\n\" +\n                        \"WHERE rownumber_ > 10\\n\" +\n                        \"ORDER BY rownumber_\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select *\\n\" +\n                        \"from (\\n\" +\n                        \"\\tselect inner2_.*, rownumber() over (order by order of inner2_) as rownumber_\\n\" +\n                        \"\\tfrom (\\n\" +\n                        \"\\t\\tselect tsuserstb0_.USERID as USERID1_1_, tsuserstb0_.CREASTAF as CREASTAF2_1_, tsuserstb0_.CREATIME as CREATIME3_1_, tsuserstb0_.LOCORGNO as LOCORGNO4_1_, tsuserstb0_.PWDMODIFYTIME as PWDMODIF5_1_\\n\" +\n                        \"\\t\\t\\t, tsuserstb0_.REMARK01 as REMARK6_1_, tsuserstb0_.REMARK02 as REMARK7_1_, tsuserstb0_.STAORGNO as STAORGNO8_1_, tsuserstb0_.UPDASTAF as UPDASTAF9_1_, tsuserstb0_.UPDATIME as UPDATIM10_1_\\n\" +\n                        \"\\t\\t\\t, tsuserstb0_.USERNAME as USERNAM11_1_, tsuserstb0_.USERPWD as USERPWD12_1_, tsuserstb0_.USERSTATE as USERSTA13_1_\\n\" +\n                        \"\\t\\tfrom TS_USERSTB tsuserstb0_\\n\" +\n                        \"\\t\\tfetch first 20 rows only\\n\" +\n                        \"\\t) inner2_\\n\" +\n                        \") inner1_\\n\" +\n                        \"where rownumber_ > 10\\n\" +\n                        \"order by rownumber_\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_11.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_11 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT A.F_0201, A.F_0301, A.F_0802, A.F_2100\"\n                + \"\\nFROM A, B\"\n                + \"\\nWHERE B.F_2211 = '5'\"\n                + \"\\n    AND A.F_0301 = B.F_0301\"\n                + \"    AND Substr(B.F_0815, 1, 4) concat  Substr ( B.F_0815,5,2 ) > A.F_0802\"\n                + \"    AND A.F_2100 > 0\"\n                + \"\\nUNION\"\n                + \"\\nSELECT A.F_0201, A.F_0301, A.F_0802, A.F_2100\"\n                + \"\\nFROM A\"\n                + \"\\nWHERE A.F_0301 NOT IN (SELECT F_0301\"\n                + \"\\n        FROM B)\"\n                + \"\\n    AND A.F_2100 > 0\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(6, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"A\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"A\", \"F_0201\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT A.F_0201, A.F_0301, A.F_0802, A.F_2100\\n\" +\n                        \"FROM A, B\\n\" +\n                        \"WHERE B.F_2211 = '5'\\n\" +\n                        \"\\tAND A.F_0301 = B.F_0301\\n\" +\n                        \"\\tAND Substr(B.F_0815, 1, 4) CONCAT Substr(B.F_0815, 5, 2) > A.F_0802\\n\" +\n                        \"\\tAND A.F_2100 > 0\\n\" +\n                        \"UNION\\n\" +\n                        \"SELECT A.F_0201, A.F_0301, A.F_0802, A.F_2100\\n\" +\n                        \"FROM A\\n\" +\n                        \"WHERE A.F_0301 NOT IN (\\n\" +\n                        \"\\t\\tSELECT F_0301\\n\" +\n                        \"\\t\\tFROM B\\n\" +\n                        \"\\t)\\n\" +\n                        \"\\tAND A.F_2100 > 0\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select A.F_0201, A.F_0301, A.F_0802, A.F_2100\\n\" +\n                        \"from A, B\\n\" +\n                        \"where B.F_2211 = '5'\\n\" +\n                        \"\\tand A.F_0301 = B.F_0301\\n\" +\n                        \"\\tand Substr(B.F_0815, 1, 4) concat Substr(B.F_0815, 5, 2) > A.F_0802\\n\" +\n                        \"\\tand A.F_2100 > 0\\n\" +\n                        \"union\\n\" +\n                        \"select A.F_0201, A.F_0301, A.F_0802, A.F_2100\\n\" +\n                        \"from A\\n\" +\n                        \"where A.F_0301 not in (\\n\" +\n                        \"\\t\\tselect F_0301\\n\" +\n                        \"\\t\\tfrom B\\n\" +\n                        \"\\t)\\n\" +\n                        \"\\tand A.F_2100 > 0\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_12.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_12 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT * FROM TASK_POLICE_QUERY_BATCH WHERE STATUS = '0' ORDER BY PRIORITY FETCH FIRST 100 ROWS ONLY\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"TASK_POLICE_QUERY_BATCH\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"TASK_POLICE_QUERY_BATCH\", \"STATUS\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"TASK_POLICE_QUERY_BATCH\", \"*\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"TASK_POLICE_QUERY_BATCH\", \"PRIORITY\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT *\"\n                        + \"\\nFROM TASK_POLICE_QUERY_BATCH\"\n                        + \"\\nWHERE STATUS = '0'\"\n                        + \"\\nORDER BY PRIORITY\"\n                        + \"\\nFETCH FIRST 100 ROWS ONLY\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select *\"\n                        + \"\\nfrom TASK_POLICE_QUERY_BATCH\"\n                        + \"\\nwhere STATUS = '0'\"\n                        + \"\\norder by PRIORITY\"\n                        + \"\\nfetch first 100 rows only\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_13.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_13 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT WORKDEPT, EMPNO, SALARY, BONUS, COMM \"//\n                + \" FROM DSN8B10.EMP\"//\n                + \" WHERE WORKDEPT IN ('D11','D21')\"\n                + \" FOR UPDATE;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN8B10.EMP\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT WORKDEPT, EMPNO, SALARY, BONUS, COMM\"\n                        + \"\\nFROM DSN8B10.EMP\"\n                        + \"\\nWHERE WORKDEPT IN ('D11', 'D21')\"\n                        + \"\\nFOR UPDATE;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select WORKDEPT, EMPNO, SALARY, BONUS, COMM\"\n                        + \"\\nfrom DSN8B10.EMP\"\n                        + \"\\nwhere WORKDEPT in ('D11', 'D21')\"\n                        + \"\\nfor update;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_14.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_14 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT (NEXTVAL FOR TEST_SEQ) FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT TEST_SEQ.NEXTVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select TEST_SEQ.nextval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_15.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_15 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT (PREVVAL FOR TEST_SEQ) FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT TEST_SEQ.PREVVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select TEST_SEQ.prevval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_16.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_16 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT (CURRVAL FOR TEST_SEQ) FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT TEST_SEQ.CURRVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select TEST_SEQ.currval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_17.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_17 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT (NEXT VALUE FOR EMPNO) FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT EMPNO.NEXTVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select EMPNO.nextval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_18.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_18 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT (PREVIOUS VALUE FOR EMPNO) FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT EMPNO.PREVVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select EMPNO.prevval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_19.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_19 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT EMPNO.CURRVAL FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT EMPNO.CURRVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select EMPNO.currval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_2 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT CTRYNUM, FMS_INSTANCE_CD FROM DBEFMSDR.FMSA_O_WW_CTRY_AG WHERE ACCT_YR=? WITH UR\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DBEFMSDR.FMSA_O_WW_CTRY_AG\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"DBEFMSDR.FMSA_O_WW_CTRY_AG\", \"CTRYNUM\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"SELECT CTRYNUM, FMS_INSTANCE_CD\"\n                        + \"\\nFROM DBEFMSDR.FMSA_O_WW_CTRY_AG\"//\n                        + \"\\nWHERE ACCT_YR = ?\"//\n                        + \"\\nWITH UR\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_20.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_20 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT EMPNO.PREVVAL FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT EMPNO.PREVVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select EMPNO.prevval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_21.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_21 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT EMPNO.nextval FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT EMPNO.NEXTVAL\"\n                        + \"\\nFROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select EMPNO.nextval\"\n                        + \"\\nfrom SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_22.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_22 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT ID,IDENTITY,BUSICODE\"\n                + \" FROM BUSINESS_ENTERPRISE_BUSIINFO\"\n                + \" WHERE SYSCODE= '603'\"\n                + \" ORDER BY INTIME desc\"\n                + \" FETCH first 1 rows only\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"BUSINESS_ENTERPRISE_BUSIINFO\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"BUSINESS_ENTERPRISE_BUSIINFO\", \"ID\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"BUSINESS_ENTERPRISE_BUSIINFO\", \"IDENTITY\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"BUSINESS_ENTERPRISE_BUSIINFO\", \"BUSICODE\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"BUSINESS_ENTERPRISE_BUSIINFO\", \"SYSCODE\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"BUSINESS_ENTERPRISE_BUSIINFO\", \"INTIME\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT ID, IDENTITY, BUSICODE\"\n                        + \"\\nFROM BUSINESS_ENTERPRISE_BUSIINFO\"\n                        + \"\\nWHERE SYSCODE = '603'\"\n                        + \"\\nORDER BY INTIME DESC\"\n                        + \"\\nFETCH FIRST 1 ROWS ONLY\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select ID, IDENTITY, BUSICODE\"\n                        + \"\\nfrom BUSINESS_ENTERPRISE_BUSIINFO\"\n                        + \"\\nwhere SYSCODE = '603'\"\n                        + \"\\norder by INTIME desc\"\n                        + \"\\nfetch first 1 rows only\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_23.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_23 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select current date,current timestamp from dual\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertFalse(visitor.getTables().containsKey(new TableStat.Name(\"dual\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT CURRENT DATE, CURRENT TIMESTAMP\\n\" +\n                        \"FROM dual\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select CURRENT DATE, CURRENT TIMESTAMP\\n\" +\n                        \"from dual\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_24.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_24 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT BANK_CODE, CONN_LOCATION_TYPE,\\n\" +\n                \"OUTER_KEYLABEL_NAME, INNER_KEYLABEL_NAME,\\n\" +\n                \"DESC, COMMENT, STATUS, DB_TIMESTAMP\\n\" +\n                \"FROM EGL_SYS_KEYLABEL_CONVERT_DEF\\n\" +\n                \"WHERE STATUS='1'\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toDB2String(stmt));\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(8, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"EGL_SYS_KEYLABEL_CONVERT_DEF\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT BANK_CODE, CONN_LOCATION_TYPE, OUTER_KEYLABEL_NAME, INNER_KEYLABEL_NAME, DESC\\n\" +\n                        \"\\t, COMMENT, STATUS, DB_TIMESTAMP\\n\" +\n                        \"FROM EGL_SYS_KEYLABEL_CONVERT_DEF\\n\" +\n                        \"WHERE STATUS = '1'\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select BANK_CODE, CONN_LOCATION_TYPE, OUTER_KEYLABEL_NAME, INNER_KEYLABEL_NAME, DESC\\n\" +\n                        \"\\t, COMMENT, STATUS, DB_TIMESTAMP\\n\" +\n                        \"from EGL_SYS_KEYLABEL_CONVERT_DEF\\n\" +\n                        \"where STATUS = '1'\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_25_concat.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_25_concat extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select ID, AUTHORITY_TYPE from t_authority a where authority_type like CONCAT('%', ?)\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        System.out.println(stmt.getSelect().getQuery());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t_authority\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT ID, AUTHORITY_TYPE\\n\" +\n                        \"FROM t_authority a\\n\" +\n                        \"WHERE authority_type LIKE CONCAT('%', ?)\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select ID, AUTHORITY_TYPE\\n\" +\n                        \"from t_authority a\\n\" +\n                        \"where authority_type like CONCAT('%', ?)\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_26.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_26 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT LATN_ID,\\n\" +\n                \"CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\\n\" +\n                \"SUM(COALESCE(ADD_USER_CNT, 0)) ADD_SUM,\\n\" +\n                \"0 USER_ACCT,\\n\" +\n                \"0 USER_ACCT_LY\\n\" +\n                \"FROM MK.M_BROAD_BAND_USER_FACT\\n\" +\n                \"WHERE THE_DATE BETWEEN SUBSTR('{THISMONTH}', 1, 4) || '-01-01' AND '{THISMONTH}'\\n\" +\n                \"GROUP BY LATN_ID,\\n\" +\n                \"CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT LATN_ID,\\n\" +\n                \"CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\\n\" +\n                \"0 ADD_SUM,\\n\" +\n                \"SUM(COALESCE(BILL_USER_CNT, 0)) USER_ACCT,\\n\" +\n                \"0 USER_ACCT_LY\\n\" +\n                \"FROM MK.M_BROAD_BAND_USER_FACT\\n\" +\n                \"WHERE THE_DATE = '{THISMONTH}'\\n\" +\n                \"GROUP BY LATN_ID,\\n\" +\n                \"CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT LATN_ID,\\n\" +\n                \"CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\\n\" +\n                \"0 ADD_SUM,\\n\" +\n                \"0 USER_ACCT,\\n\" +\n                \"SUM(COALESCE(BILL_USER_CNT, 0)) USER_ACCT_LY\\n\" +\n                \"FROM MK.M_BROAD_BAND_USER_FACT\\n\" +\n                \"WHERE THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) || '-01-01') - 1 MONTHS\\n\" +\n                \"GROUP BY LATN_ID,\\n\" +\n                \"CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        System.out.println(stmt.getSelect().getQuery());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(3, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"MK.M_BROAD_BAND_USER_FACT\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT LATN_ID\\n\" +\n                        \"\\t, CASE\\n\" +\n                        \"\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\tEND AS BUREAU_KEY, SUM(COALESCE(ADD_USER_CNT, 0)) AS ADD_SUM\\n\" +\n                        \"\\t, 0 AS USER_ACCT, 0 AS USER_ACCT_LY\\n\" +\n                        \"FROM MK.M_BROAD_BAND_USER_FACT\\n\" +\n                        \"WHERE THE_DATE BETWEEN SUBSTR('{THISMONTH}', 1, 4) CONCAT '-01-01' AND '{THISMONTH}'\\n\" +\n                        \"GROUP BY LATN_ID, CASE\\n\" +\n                        \"\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\tEND\\n\" +\n                        \"UNION ALL\\n\" +\n                        \"SELECT LATN_ID\\n\" +\n                        \"\\t, CASE\\n\" +\n                        \"\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\tEND AS BUREAU_KEY, 0 AS ADD_SUM\\n\" +\n                        \"\\t, SUM(COALESCE(BILL_USER_CNT, 0)) AS USER_ACCT\\n\" +\n                        \"\\t, 0 AS USER_ACCT_LY\\n\" +\n                        \"FROM MK.M_BROAD_BAND_USER_FACT\\n\" +\n                        \"WHERE THE_DATE = '{THISMONTH}'\\n\" +\n                        \"GROUP BY LATN_ID, CASE\\n\" +\n                        \"\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\tEND\\n\" +\n                        \"UNION ALL\\n\" +\n                        \"SELECT LATN_ID\\n\" +\n                        \"\\t, CASE\\n\" +\n                        \"\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\tEND AS BUREAU_KEY, 0 AS ADD_SUM, 0 AS USER_ACCT\\n\" +\n                        \"\\t, SUM(COALESCE(BILL_USER_CNT, 0)) AS USER_ACCT_LY\\n\" +\n                        \"FROM MK.M_BROAD_BAND_USER_FACT\\n\" +\n                        \"WHERE THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) CONCAT '-01-01') - 1 MONTHS\\n\" +\n                        \"GROUP BY LATN_ID, CASE\\n\" +\n                        \"\\t\\tWHEN BUREAU_KEY = 116 THEN 46\\n\" +\n                        \"\\t\\tELSE BUREAU_KEY\\n\" +\n                        \"\\tEND\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select LATN_ID\\n\" +\n                        \"\\t, case\\n\" +\n                        \"\\t\\twhen BUREAU_KEY = 116 then 46\\n\" +\n                        \"\\t\\telse BUREAU_KEY\\n\" +\n                        \"\\tend as BUREAU_KEY, sum(COALESCE(ADD_USER_CNT, 0)) as ADD_SUM\\n\" +\n                        \"\\t, 0 as USER_ACCT, 0 as USER_ACCT_LY\\n\" +\n                        \"from MK.M_BROAD_BAND_USER_FACT\\n\" +\n                        \"where THE_DATE between SUBSTR('{THISMONTH}', 1, 4) concat '-01-01' and '{THISMONTH}'\\n\" +\n                        \"group by LATN_ID, case\\n\" +\n                        \"\\t\\twhen BUREAU_KEY = 116 then 46\\n\" +\n                        \"\\t\\telse BUREAU_KEY\\n\" +\n                        \"\\tend\\n\" +\n                        \"union all\\n\" +\n                        \"select LATN_ID\\n\" +\n                        \"\\t, case\\n\" +\n                        \"\\t\\twhen BUREAU_KEY = 116 then 46\\n\" +\n                        \"\\t\\telse BUREAU_KEY\\n\" +\n                        \"\\tend as BUREAU_KEY, 0 as ADD_SUM\\n\" +\n                        \"\\t, sum(COALESCE(BILL_USER_CNT, 0)) as USER_ACCT\\n\" +\n                        \"\\t, 0 as USER_ACCT_LY\\n\" +\n                        \"from MK.M_BROAD_BAND_USER_FACT\\n\" +\n                        \"where THE_DATE = '{THISMONTH}'\\n\" +\n                        \"group by LATN_ID, case\\n\" +\n                        \"\\t\\twhen BUREAU_KEY = 116 then 46\\n\" +\n                        \"\\t\\telse BUREAU_KEY\\n\" +\n                        \"\\tend\\n\" +\n                        \"union all\\n\" +\n                        \"select LATN_ID\\n\" +\n                        \"\\t, case\\n\" +\n                        \"\\t\\twhen BUREAU_KEY = 116 then 46\\n\" +\n                        \"\\t\\telse BUREAU_KEY\\n\" +\n                        \"\\tend as BUREAU_KEY, 0 as ADD_SUM, 0 as USER_ACCT\\n\" +\n                        \"\\t, sum(COALESCE(BILL_USER_CNT, 0)) as USER_ACCT_LY\\n\" +\n                        \"from MK.M_BROAD_BAND_USER_FACT\\n\" +\n                        \"where THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) concat '-01-01') - 1 months\\n\" +\n                        \"group by LATN_ID, case\\n\" +\n                        \"\\t\\twhen BUREAU_KEY = 116 then 46\\n\" +\n                        \"\\t\\telse BUREAU_KEY\\n\" +\n                        \"\\tend\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_27_interval.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_27_interval extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT current date + 1 YEAR, current date + 3 YEARS + 2 MONTHS + 15 DAYS, current time + 5 HOURS - 3 MINUTES + 10 SECONDS from sysibm.sysdummy1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        System.out.println(stmt.getSelect().getQuery());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"sysibm.sysdummy1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT CURRENT DATE + 1 AS YEAR\\n\" +\n                        \"\\t, CURRENT DATE + 3 YEARS + 2 MONTHS + 15 DAYS\\n\" +\n                        \"\\t, CURRENT TIME + 5 HOURS - 3 MINUTES + 10 SECONDS\\n\" +\n                        \"FROM sysibm.sysdummy1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select CURRENT DATE + 1 as YEAR\\n\" +\n                        \"\\t, CURRENT DATE + 3 years + 2 months + 15 days\\n\" +\n                        \"\\t, CURRENT TIME + 5 hours - 3 minutes + 10 seconds\\n\" +\n                        \"from sysibm.sysdummy1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_28.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_28 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select a from (select b from d)\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        assertEquals(\"SELECT a\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT b\\n\" +\n                \"\\tFROM d\\n\" +\n                \")\", stmt.getSelect().toString());\n\n        assertEquals(\"(\\n\" +\n                \"\\tSELECT b\\n\" +\n                \"\\tFROM d\\n\" +\n                \")\", stmt.getSelect().getQueryBlock().getFrom().toString());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"d\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT a\\n\" +\n                        \"FROM (\\n\" +\n                        \"\\tSELECT b\\n\" +\n                        \"\\tFROM d\\n\" +\n                        \")\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select a\\n\" +\n                        \"from (\\n\" +\n                        \"\\tselect b\\n\" +\n                        \"\\tfrom d\\n\" +\n                        \")\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_29.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_29 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select to_char(current date - 7 day ,'yyyymmdd') from sysibm.dual\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        assertEquals(\"SELECT to_char(CURRENT DATE - 7 DAYS, 'yyyymmdd')\\n\" +\n                \"FROM sysibm.dual\", stmt.getSelect().toString());\n\n        assertEquals(\"sysibm.dual\", stmt.getSelect().getQueryBlock().getFrom().toString());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"sysibm.dual\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT to_char(CURRENT DATE - 7 DAYS, 'yyyymmdd')\\n\" +\n                        \"FROM sysibm.dual\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select to_char(CURRENT DATE - 7 days, 'yyyymmdd')\\n\" +\n                        \"from sysibm.dual\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_3 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select * from t for read only\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"SELECT *\"\n                        + \"\\nFROM t\"//\n                        + \"\\nFOR READ ONLY\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_30.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_30 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT CURRENT TIME FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        assertEquals(\"SELECT CURRENT TIME\\n\" +\n                \"FROM SYSIBM.SYSDUMMY1\", stmt.getSelect().toString());\n\n        assertEquals(\"SYSIBM.SYSDUMMY1\", stmt.getSelect().getQueryBlock().getFrom().toString());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"SYSIBM.SYSDUMMY1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT CURRENT TIME\\n\" +\n                        \"FROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select CURRENT TIME\\n\" +\n                        \"from SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_31.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_31 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select rtrim(current_server), rtrim(current schema), rtrim(current_user) from sysibm.sysdummy1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        assertEquals(\"SELECT rtrim(current_server), rtrim(CURRENT SCHEMA)\\n\" +\n                \"\\t, rtrim(current_user)\\n\" +\n                \"FROM sysibm.sysdummy1\", stmt.getSelect().toString());\n\n        assertEquals(\"sysibm.sysdummy1\", stmt.getSelect().getQueryBlock().getFrom().toString());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"sysibm.sysdummy1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT rtrim(current_server), rtrim(CURRENT SCHEMA)\\n\" +\n                        \"\\t, rtrim(current_user)\\n\" +\n                        \"FROM sysibm.sysdummy1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select rtrim(current_server), rtrim(CURRENT SCHEMA)\\n\" +\n                        \"\\t, rtrim(current_user)\\n\" +\n                        \"from sysibm.sysdummy1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_32.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_32 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT CURRENT DATE FROM SYSIBM.SYSDUMMY1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        assertEquals(\"SELECT CURRENT DATE\\n\" +\n                \"FROM SYSIBM.SYSDUMMY1\", stmt.getSelect().toString());\n\n        assertEquals(\"SYSIBM.SYSDUMMY1\", stmt.getSelect().getQueryBlock().getFrom().toString());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"sysibm.sysdummy1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT CURRENT DATE\\n\" +\n                        \"FROM SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select CURRENT DATE\\n\" +\n                        \"from SYSIBM.SYSDUMMY1\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_33.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_33 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT CURRENT_DATE -2 DAY FROM SYSIBM.SYSDUMMY1;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        assertEquals(\"SYSIBM.SYSDUMMY1\", stmt.getSelect().getQueryBlock().getFrom().toString());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"sysibm.sysdummy1\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT CURRENT_DATE - 2 DAYS\\n\" +\n                        \"FROM SYSIBM.SYSDUMMY1;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select CURRENT_DATE - 2 days\\n\" +\n                        \"from SYSIBM.SYSDUMMY1;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_34.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_34 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT * INTO Persons_backup FROM Persons\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n        assertEquals(\"Persons\", stmt.getSelect().getQueryBlock().getFrom().toString());\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"Persons_backup\"));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"DSN8B10.EMP\", \"WORKDEPT\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT *\\n\" +\n                        \"INTO Persons_backup\\n\" +\n                        \"FROM Persons\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"select *\\n\" +\n                        \"into Persons_backup\\n\" +\n                        \"from Persons\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_35_lockRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_35_lockRequest extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT KEYID, KEYVALUE FROM KEYIDS WHERE KEYID = ? FOR READ ONLY WITH RS USE AND KEEP UPDATE LOCKS;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"KEYIDS\")));\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"KEYIDS\", \"KEYVALUE\")));\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"KEYIDS\", \"KEYVALUE\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"SELECT KEYID, KEYVALUE\"\n                        + \"\\nFROM KEYIDS\"\n                        + \"\\nWHERE KEYID = ?\"\n                        + \"\\nFOR READ ONLY\"\n                        + \"\\nWITH RS\"\n                        + \"\\nUSE AND KEEP UPDATE LOCKS;\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_4 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select * from t OPTIMIZE FOR 10 ROWS\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"SELECT *\"\n                        + \"\\nFROM t\"//\n                        + \"\\nOPTIMIZE FOR 10\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_5 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT * FROM (SELECT TEMP_TAB.*,ROWNUMBER() OVER() AS IDX FROM (SELECT\"\n                + \"            DISTINCT  ( OH.ORDER_ID )\"\n                + \"        FROM\"\n                + \"            ORDER_HEADER OH,\"\n                + \"            ORDER_ITEM OI,\"\n                + \"            ORDER_PAYMENT_PERFERENCE OPP,\"\n                + \"            ORDER_SHIPMENT_PERFERENCE OSP\"\n                + \"        WHERE\"\n                + \"            OH.ORDER_ID = OI.ORDER_ID\"\n                + \"        AND OH.ORDER_ID = OPP.ORDER_ID\"\n                + \"        AND OH.ORDER_ID = OSP.ORDER_ID\"\n                + \"             \"\n                + \"                AND OH.ORDER_ID = ? ) AS TEMP_TAB ) AS TEMP_TAB_WITH_IDX \"//\n                + \" WHERE TEMP_TAB_WITH_IDX.IDX > 0 AND TEMP_TAB_WITH_IDX.IDX <= 20\"\n                + \"\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(4, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(4, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"ORDER_HEADER\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"ORDER_HEADER\", \"ORDER_ID\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"SELECT *\\n\" +\n                        \"FROM (\\n\" +\n                        \"\\tSELECT TEMP_TAB.*, ROWNUMBER() OVER () AS IDX\\n\" +\n                        \"\\tFROM (\\n\" +\n                        \"\\t\\tSELECT DISTINCT OH.ORDER_ID\\n\" +\n                        \"\\t\\tFROM ORDER_HEADER OH, ORDER_ITEM OI, ORDER_PAYMENT_PERFERENCE OPP, ORDER_SHIPMENT_PERFERENCE OSP\\n\" +\n                        \"\\t\\tWHERE OH.ORDER_ID = OI.ORDER_ID\\n\" +\n                        \"\\t\\t\\tAND OH.ORDER_ID = OPP.ORDER_ID\\n\" +\n                        \"\\t\\t\\tAND OH.ORDER_ID = OSP.ORDER_ID\\n\" +\n                        \"\\t\\t\\tAND OH.ORDER_ID = ?\\n\" +\n                        \"\\t) TEMP_TAB\\n\" +\n                        \") TEMP_TAB_WITH_IDX\\n\" +\n                        \"WHERE TEMP_TAB_WITH_IDX.IDX > 0\\n\" +\n                        \"\\tAND TEMP_TAB_WITH_IDX.IDX <= 20\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_6 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT all id FROM DSN81010.EMP;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT ALL id\"\n                        + \"\\nFROM DSN81010.EMP;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n        assertEquals(\"select all id\"\n                        + \"\\nfrom DSN81010.EMP;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_7.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_7 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT distinct id FROM DSN81010.EMP;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT DISTINCT id\"\n                        + \"\\nFROM DSN81010.EMP;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n        assertEquals(\"select distinct id\"\n                        + \"\\nfrom DSN81010.EMP;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_8.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_8 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SELECT unique id FROM DSN81010.EMP where id = 1;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT UNIQUE id\"\n                        + \"\\nFROM DSN81010.EMP\"\n                        + \"\\nWHERE id = 1;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n        assertEquals(\"select unique id\"\n                        + \"\\nfrom DSN81010.EMP\"\n                        + \"\\nwhere id = 1;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_9.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_9 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"select tsuserstb0_.USERID as USERID1_1_, tsuserstb0_.CREASTAF as CREASTAF2_1_\"\n                + \" , tsuserstb0_.CREATIME as CREATIME3_1_, tsuserstb0_.LOCORGNO as LOCORGNO4_1_\"\n                + \" , tsuserstb0_.PWDMODIFYTIME as PWDMODIF5_1_, tsuserstb0_.REMARK01 as REMARK6_1_\"\n                + \" , tsuserstb0_.REMARK02 as REMARK7_1_, tsuserstb0_.STAORGNO as STAORGNO8_1_\"\n                + \" , tsuserstb0_.UPDASTAF as UPDASTAF9_1_, tsuserstb0_.UPDATIME as UPDATIM10_1_, tsuserstb0_.USERNAME as USERNAM11_1_\"\n                + \" , tsuserstb0_.USERPWD as USERPWD12_1_, tsuserstb0_.USERSTATE as USERSTA13_1_\"\n                + \" from TS_USERSTB tsuserstb0_ fetch first 10 rows only\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(13, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"TS_USERSTB\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SELECT tsuserstb0_.USERID AS USERID1_1_, tsuserstb0_.CREASTAF AS CREASTAF2_1_, tsuserstb0_.CREATIME AS CREATIME3_1_, tsuserstb0_.LOCORGNO AS LOCORGNO4_1_, tsuserstb0_.PWDMODIFYTIME AS PWDMODIF5_1_\"\n                        + \"\\n\\t, tsuserstb0_.REMARK01 AS REMARK6_1_, tsuserstb0_.REMARK02 AS REMARK7_1_, tsuserstb0_.STAORGNO AS STAORGNO8_1_, tsuserstb0_.UPDASTAF AS UPDASTAF9_1_, tsuserstb0_.UPDATIME AS UPDATIM10_1_\"\n                        + \"\\n\\t, tsuserstb0_.USERNAME AS USERNAM11_1_, tsuserstb0_.USERPWD AS USERPWD12_1_, tsuserstb0_.USERSTATE AS USERSTA13_1_\"\n                        + \"\\nFROM TS_USERSTB tsuserstb0_\"\n                        + \"\\nFETCH FIRST 10 ROWS ONLY\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n        assertEquals(\"select tsuserstb0_.USERID as USERID1_1_, tsuserstb0_.CREASTAF as CREASTAF2_1_, tsuserstb0_.CREATIME as CREATIME3_1_, tsuserstb0_.LOCORGNO as LOCORGNO4_1_, tsuserstb0_.PWDMODIFYTIME as PWDMODIF5_1_\"\n                        + \"\\n\\t, tsuserstb0_.REMARK01 as REMARK6_1_, tsuserstb0_.REMARK02 as REMARK7_1_, tsuserstb0_.STAORGNO as STAORGNO8_1_, tsuserstb0_.UPDASTAF as UPDASTAF9_1_, tsuserstb0_.UPDATIME as UPDATIM10_1_\"\n                        + \"\\n\\t, tsuserstb0_.USERNAME as USERNAM11_1_, tsuserstb0_.USERPWD as USERPWD12_1_, tsuserstb0_.USERSTATE as USERSTA13_1_\"\n                        + \"\\nfrom TS_USERSTB tsuserstb0_\"\n                        + \"\\nfetch first 10 rows only\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_hierarchical_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SelectTest_hierarchical_1 extends MysqlTest {\n    protected final DbType dbType = JdbcConstants.DB2;\n\n    public void test_0() throws Exception {\n        String sql = \"SELECT last_name, employee_id, manager_id, LEVEL\\n\" +\n                \"      FROM employees\\n\" +\n                \"      START WITH employee_id = 100\\n\" +\n                \"      CONNECT BY PRIOR employee_id = manager_id\\n\" +\n                \"      ORDER SIBLINGS BY last_name;\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        SQLStatement stmt = stmtList.get(0);\n\n        {\n            String result = SQLUtils.toSQLString(stmt, dbType);\n            assertEquals(\"SELECT last_name, employee_id, manager_id, LEVEL\\n\" +\n                    \"FROM employees\\n\" +\n                    \"START WITH employee_id = 100\\n\" +\n                    \"CONNECT BY PRIOR employee_id = manager_id\\n\" +\n                    \"ORDER SIBLINGS BY last_name;\", result);\n        }\n        {\n            String result = SQLUtils.toSQLString(stmt, dbType, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"select last_name, employee_id, manager_id, LEVEL\\n\" +\n                    \"from employees\\n\" +\n                    \"start with employee_id = 100\\n\" +\n                    \"connect by prior employee_id = manager_id\\n\" +\n                    \"order siblings by last_name;\", result);\n        }\n\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t_basic_store\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SetTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SetTest_0 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"set current schema = 'PAYROLL'\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SET CURRENT SCHEMA = 'PAYROLL'\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n        assertEquals(\"set CURRENT SCHEMA = 'PAYROLL'\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SetTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SetTest_1 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SET :HVL = CURRENT PATH;\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SET :HVL = CURRENT PATH;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n        assertEquals(\"set :HVL = CURRENT PATH;\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SetTest_2_schema.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2SetTest_2_schema extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"SET SCHEMA RICK\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"DSN81010.EMP\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"SET SCHEMA = RICK\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n        assertEquals(\"set SCHEMA = RICK\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2TruncateTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2TruncateTest extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"TRUNCATE TASK_AICSFSM_QUERY_BATCH_TEMP IMMEDIATE\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"TASK_AICSFSM_QUERY_BATCH_TEMP\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"A\", \"F_0201\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"TRUNCATE TABLE TASK_AICSFSM_QUERY_BATCH_TEMP IMMEDIATE\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"truncate table TASK_AICSFSM_QUERY_BATCH_TEMP immediate\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2TruncateTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2TruncateTest2 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"TRUNCATE TABLE INVENTORY IGNORE DELETE TRIGGERS DROP STORAGE IMMEDIATE\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"INVENTORY\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"A\", \"F_0201\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"TRUNCATE TABLE INVENTORY DROP STORAGE IGNORE DELETE TRIGGERS IMMEDIATE\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"truncate table INVENTORY drop storage ignore delete triggers immediate\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2TruncateTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2TruncateTest3 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"TRUNCATE TABLE INVENTORY REUSE STORAGE RESTRICT WHEN DELETE TRIGGERS\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"INVENTORY\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"A\", \"F_0201\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"TRUNCATE TABLE INVENTORY REUSE STORAGE RESTRICT WHEN DELETE TRIGGERS\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"truncate table INVENTORY reuse storage restrict when delete triggers\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2TruncateTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2TruncateTest4 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"TRUNCATE TABLE INVENTORY REUSE STORAGE IGNORE DELETE TRIGGERS IMMEDIATE\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"INVENTORY\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"A\", \"F_0201\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"TRUNCATE TABLE INVENTORY REUSE STORAGE IGNORE DELETE TRIGGERS IMMEDIATE\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"truncate table INVENTORY reuse storage ignore delete triggers immediate\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2TruncateTest5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2TruncateTest5 extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"TRUNCATE TABLE INVENTORY REUSE STORAGE IGNORE DELETE TRIGGERS CONTINUE IDENTITY IMMEDIATE\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"INVENTORY\")));\n\n//         assertTrue(visitor.getColumns().contains(new Column(\"A\", \"F_0201\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        assertEquals(\"TRUNCATE TABLE INVENTORY REUSE STORAGE IGNORE DELETE TRIGGERS IMMEDIATE\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2));\n\n        assertEquals(\"truncate table INVENTORY reuse storage ignore delete triggers immediate\", //\n                SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2Values_Test.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.db2;\n\nimport com.alibaba.druid.sql.DB2Test;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;\nimport com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DB2Values_Test extends DB2Test {\n    public void test_0() throws Exception {\n        String sql = \"values 1\";\n\n        DB2StatementParser parser = new DB2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"first_name\")));\n        // assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"full_name\")));\n\n        String output = SQLUtils.toSQLString(stmt, JdbcConstants.DB2);\n        assertEquals(\"VALUES (1)\", //\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/derby/DerbySelectTest.java",
    "content": "package com.alibaba.druid.bvt.sql.derby;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\npublic class DerbySelectTest {\n    @Test\n    public void test_for_derby() throws Exception {\n        String sql = \"select * from sys_user offset ? rows fetch next ? rows only\";\n\n        SQLUtils.parseSingleStatement(sql, DbType.derby);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_CreateTableTest.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_CreateTableTest {\n    private final DbType dbType = DbType.dm;\n\n    @Test\n    public void test_create_table_basic() {\n        String sql = \"CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(100) NOT NULL, status INT DEFAULT 0)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_table_with_constraints() {\n        String sql = \"CREATE TABLE t1 (\" +\n                \"id INT NOT NULL, \" +\n                \"name VARCHAR(100), \" +\n                \"dept_id INT, \" +\n                \"CONSTRAINT pk_t1 PRIMARY KEY (id), \" +\n                \"CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES dept(id)\" +\n                \")\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_table_identity() {\n        // DM official: IDENTITY [(seed, increment)]\n        String sql = \"CREATE TABLE t1 (id INT IDENTITY(1, 1) PRIMARY KEY, name VARCHAR(100))\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_identity_no_args() {\n        // DM: IDENTITY without arguments (defaults to seed=1, increment=1)\n        String sql = \"CREATE TABLE t1 (id INT IDENTITY PRIMARY KEY, name VARCHAR(100))\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_auto_increment() {\n        String sql = \"CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100))\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_if_not_exists() {\n        String sql = \"CREATE TABLE IF NOT EXISTS t1 (id INT, name VARCHAR(100))\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_table_as_select() {\n        String sql = \"CREATE TABLE t2 AS SELECT id, name FROM t1 WHERE status = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_with_comment() {\n        String sql = \"CREATE TABLE t1 (id INT COMMENT 'primary key', name VARCHAR(100) COMMENT 'user name')\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_with_tablespace() {\n        String sql = \"CREATE TABLE t1 (id INT, name VARCHAR(100)) TABLESPACE ts1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_with_check() {\n        String sql = \"CREATE TABLE t1 (id INT, age INT, CONSTRAINT chk_age CHECK (age >= 0 AND age <= 150))\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_table_dm_types() {\n        // DM-specific data types\n        String sql = \"CREATE TABLE t1 (\" +\n                \"id BIGINT, \" +\n                \"tiny_val TINYINT, \" +\n                \"small_val SMALLINT, \" +\n                \"float_val DOUBLE PRECISION, \" +\n                \"txt TEXT, \" +\n                \"bin_data BLOB, \" +\n                \"char_data CLOB, \" +\n                \"ts TIMESTAMP\" +\n                \")\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_with_unique() {\n        String sql = \"CREATE TABLE t1 (id INT, email VARCHAR(200), CONSTRAINT uk_email UNIQUE (email))\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_table_default_on_null() {\n        String sql = \"CREATE TABLE t1 (id INT, name VARCHAR(100) DEFAULT 'unknown' NOT NULL)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    // ========== Partition clause tests ==========\n\n    @Test\n    public void test_create_table_partition_by_hash() {\n        String sql = \"CREATE TABLE t1 (id INT, name VARCHAR(100)) PARTITION BY HASH (id)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_partition_by_range() {\n        String sql = \"CREATE TABLE t1 (id INT, created_date DATE) PARTITION BY RANGE (created_date)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_partition_by_list() {\n        String sql = \"CREATE TABLE t1 (id INT, region VARCHAR(50)) PARTITION BY LIST (region)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_table_partition_by_hash_multi_columns() {\n        String sql = \"CREATE TABLE t1 (id INT, dept_id INT, name VARCHAR(100)) PARTITION BY HASH (id, dept_id)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_DDLTest.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_DDLTest {\n    private final DbType dbType = DbType.dm;\n\n    @Test\n    public void test_drop_table() {\n        String sql = \"DROP TABLE IF EXISTS t1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_alter_table_add_column() {\n        String sql = \"ALTER TABLE t1 ADD COLUMN age INT\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_alter_table_drop_column() {\n        String sql = \"ALTER TABLE t1 DROP COLUMN age\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_create_index() {\n        String sql = \"CREATE INDEX idx_name ON t1 (name)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_unique_index() {\n        String sql = \"CREATE UNIQUE INDEX idx_id ON t1 (id)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_drop_index() {\n        String sql = \"DROP INDEX idx_name\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_truncate_table() {\n        String sql = \"TRUNCATE TABLE t1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_view() {\n        String sql = \"CREATE VIEW v1 AS SELECT id, name FROM t1 WHERE status = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_create_or_replace_view() {\n        String sql = \"CREATE OR REPLACE VIEW v1 AS SELECT id, name FROM t1 WHERE status = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_DeleteTest.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_DeleteTest {\n    private final DbType dbType = DbType.dm;\n\n    @Test\n    public void test_delete_basic() {\n        String sql = \"DELETE FROM t1 WHERE id = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_delete_with_alias() {\n        String sql = \"DELETE FROM t1 a WHERE a.status = 0\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_delete_with_subquery() {\n        String sql = \"DELETE FROM t1 WHERE id IN (SELECT aid FROM t2 WHERE status = 0)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_InsertTest.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_InsertTest {\n    private final DbType dbType = DbType.dm;\n\n    @Test\n    public void test_insert_values() {\n        String sql = \"INSERT INTO t1 (id, name, status) VALUES (1, 'test', 1)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_insert_multi_values() {\n        String sql = \"INSERT INTO t1 (id, name) VALUES (1, 'a'), (2, 'b'), (3, 'c')\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_insert_select() {\n        String sql = \"INSERT INTO t1 (id, name) SELECT id, name FROM t2 WHERE status = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_insert_with_alias() {\n        String sql = \"INSERT INTO t1 a (id, name) VALUES (1, 'test')\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_MergeTest_0.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLMergeStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_MergeTest_0 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"MERGE INTO sys_user_online a using (select count(1) co from sys_user_online \" +\n                \"where sessionid = ?) b on (b.co <> 0) when matched then update set login_name = ?, dept_name = ?, ipaddr = ?, login_location = ?, browser = ?, os = ?, status = ?, start_timestamp = ?, last_access_time = ?, expire_time = ? where sessionid = ? when not matched then insert(SESSIONID, LOGIN_NAME, DEPT_NAME, IPADDR,LOGIN_LOCATION, BROWSER, OS, STATUS, START_TIMESTAMP, LAST_ACCESS_TIME, EXPIRE_TIME) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\";\n//\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.dm);\n        SQLMergeStatement stmt = (SQLMergeStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"MERGE INTO sys_user_online a\\n\" +\n                        \"USING (\\n\" +\n                        \"\\tSELECT count(1) AS co\\n\" +\n                        \"\\tFROM sys_user_online\\n\" +\n                        \"\\tWHERE sessionid = ?\\n\" +\n                        \") b ON (b.co <> 0)\\n\" +\n                        \"WHEN MATCHED THEN UPDATE\\n\" +\n                        \"SET login_name = ?,\\n\" +\n                        \"\\tdept_name = ?,\\n\" +\n                        \"\\tipaddr = ?,\\n\" +\n                        \"\\tlogin_location = ?,\\n\" +\n                        \"\\tbrowser = ?,\\n\" +\n                        \"\\tos = ?,\\n\" +\n                        \"\\tstatus = ?,\\n\" +\n                        \"\\tstart_timestamp = ?,\\n\" +\n                        \"\\tlast_access_time = ?,\\n\" +\n                        \"\\texpire_time = ?\\n\" +\n                        \"WHERE sessionid = ?\\n\" +\n                        \"WHEN NOT MATCHED THEN INSERT (\\n\" +\n                        \"\\tSESSIONID, LOGIN_NAME, DEPT_NAME, IPADDR, LOGIN_LOCATION,\\n\" +\n                        \"\\tBROWSER, OS, STATUS, START_TIMESTAMP, LAST_ACCESS_TIME,\\n\" +\n                        \"\\tEXPIRE_TIME\\n\" +\n                        \")\\n\" +\n                        \"VALUES (\\n\" +\n                        \"\\t?, ?, ?, ?, ?,\\n\" +\n                        \"\\t?, ?, ?, ?, ?,\\n\" +\n                        \"\\t?\\n\" +\n                        \")\",\n                stmt.toString());\n        SQLParseAssertUtil.assertParseSql(sql, DbType.dm);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"MERGE INTO sys_user_online a using (select count(1) co from sys_user_online \" +\n                \"where sessionid = ?) b on (b.co <> 0) when matched then update set login_name = ?, dept_name = ?, ipaddr = ?, login_location = ?, browser = ?, os = ?, status = ?, start_timestamp = ?, last_access_time = ?, expire_time = ? where sessionid = ? when not matched then insert(SESSIONID, LOGIN_NAME, DEPT_NAME, IPADDR,LOGIN_LOCATION, BROWSER, OS, STATUS, START_TIMESTAMP, LAST_ACCESS_TIME, EXPIRE_TIME) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\";\n//\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.dm);\n        SQLMergeStatement stmt = (SQLMergeStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"MERGE INTO sys_user_online a\\n\" +\n                        \"USING (\\n\" +\n                        \"\\tSELECT count(1) AS co\\n\" +\n                        \"\\tFROM sys_user_online\\n\" +\n                        \"\\tWHERE sessionid = ?\\n\" +\n                        \") b ON (b.co <> 0)\\n\" +\n                        \"WHEN MATCHED THEN UPDATE\\n\" +\n                        \"SET login_name = ?,\\n\" +\n                        \"\\tdept_name = ?,\\n\" +\n                        \"\\tipaddr = ?,\\n\" +\n                        \"\\tlogin_location = ?,\\n\" +\n                        \"\\tbrowser = ?,\\n\" +\n                        \"\\tos = ?,\\n\" +\n                        \"\\tstatus = ?,\\n\" +\n                        \"\\tstart_timestamp = ?,\\n\" +\n                        \"\\tlast_access_time = ?,\\n\" +\n                        \"\\texpire_time = ?\\n\" +\n                        \"WHERE sessionid = ?\\n\" +\n                        \"WHEN NOT MATCHED THEN INSERT (\\n\" +\n                        \"\\tSESSIONID, LOGIN_NAME, DEPT_NAME, IPADDR, LOGIN_LOCATION,\\n\" +\n                        \"\\tBROWSER, OS, STATUS, START_TIMESTAMP, LAST_ACCESS_TIME,\\n\" +\n                        \"\\tEXPIRE_TIME\\n\" +\n                        \")\\n\" +\n                        \"VALUES (\\n\" +\n                        \"\\t?, ?, ?, ?, ?,\\n\" +\n                        \"\\t?, ?, ?, ?, ?,\\n\" +\n                        \"\\t?\\n\" +\n                        \")\",\n                stmt.toString());\n        SQLParseAssertUtil.assertParseSql(sql, DbType.dm);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_SchemaStatTest.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_SchemaStatTest {\n    private final DbType dbType = DbType.dm;\n\n    @Test\n    public void test_schema_stat_select() {\n        String sql = \"SELECT a.id, a.name, b.dept_name FROM employees a JOIN departments b ON a.dept_id = b.id WHERE a.status = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n        stmtList.get(0).accept(visitor);\n\n        assertEquals(2, visitor.getTables().size());\n        assertTrue(visitor.getColumns().size() > 0);\n    }\n\n    @Test\n    public void test_schema_stat_insert() {\n        String sql = \"INSERT INTO t1 (id, name) VALUES (1, 'test')\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n        stmtList.get(0).accept(visitor);\n\n        assertEquals(1, visitor.getTables().size());\n    }\n\n    @Test\n    public void test_schema_stat_merge() {\n        String sql = \"MERGE INTO t1 a USING t2 b ON (a.id = b.id) \" +\n                \"WHEN MATCHED THEN UPDATE SET a.name = b.name \" +\n                \"WHEN NOT MATCHED THEN INSERT (id, name) VALUES (b.id, b.name)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n        stmtList.get(0).accept(visitor);\n\n        assertEquals(2, visitor.getTables().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_SelectTest.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_SelectTest {\n    private final DbType dbType = DbType.dm;\n\n    @Test\n    public void test_select_basic() {\n        String sql = \"SELECT * FROM t1 WHERE id = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_join() {\n        String sql = \"SELECT a.id, b.name FROM t1 a INNER JOIN t2 b ON a.id = b.aid WHERE a.status = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_left_join() {\n        String sql = \"SELECT a.id, b.name FROM t1 a LEFT OUTER JOIN t2 b ON a.id = b.aid\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_full_join() {\n        String sql = \"SELECT a.id, b.name FROM t1 a FULL JOIN t2 b ON a.id = b.aid\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_cross_join() {\n        String sql = \"SELECT a.id, b.name FROM t1 a CROSS JOIN t2 b\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_subquery() {\n        String sql = \"SELECT * FROM (SELECT id, name FROM t1 WHERE status = 1) t WHERE t.id > 10\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_limit() {\n        String sql = \"SELECT * FROM t1 ORDER BY id LIMIT 10\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_limit_offset_comma() {\n        // DM: LIMIT <offset>, <count>\n        String sql = \"SELECT * FROM t1 ORDER BY id LIMIT 20, 10\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_limit_offset_keyword() {\n        // DM: LIMIT <count> OFFSET <offset>\n        String sql = \"SELECT * FROM t1 ORDER BY id LIMIT 10 OFFSET 20\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_offset_limit() {\n        // DM: OFFSET <offset> LIMIT <count>\n        String sql = \"SELECT * FROM t1 ORDER BY id OFFSET 20 LIMIT 10\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_top() {\n        // DM: SELECT TOP <n> ...\n        String sql = \"SELECT TOP 10 * FROM t1 ORDER BY id\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_top_percent() {\n        // DM: SELECT TOP <n> PERCENT ...\n        String sql = \"SELECT TOP 10 PERCENT * FROM t1 ORDER BY id\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_fetch_next() {\n        // DM: OFFSET ... ROWS FETCH NEXT <n> ROWS ONLY\n        String sql = \"SELECT * FROM t1 ORDER BY id OFFSET 5 FETCH NEXT 10 ROWS ONLY\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_group_by_having() {\n        String sql = \"SELECT dept_id, COUNT(*) cnt FROM employees GROUP BY dept_id HAVING COUNT(*) > 5\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_union() {\n        String sql = \"SELECT id, name FROM t1 UNION ALL SELECT id, name FROM t2\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_minus() {\n        // DM supports MINUS (Oracle compatible)\n        String sql = \"SELECT id FROM t1 MINUS SELECT id FROM t2\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_intersect() {\n        String sql = \"SELECT id FROM t1 INTERSECT SELECT id FROM t2\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_with_cte() {\n        String sql = \"WITH cte AS (SELECT id, name FROM t1 WHERE status = 1) SELECT * FROM cte WHERE id > 10\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_recursive_cte() {\n        String sql = \"WITH RECURSIVE cte(id, name, parent_id) AS (\" +\n                \"SELECT id, name, parent_id FROM dept WHERE parent_id IS NULL \" +\n                \"UNION ALL \" +\n                \"SELECT d.id, d.name, d.parent_id FROM dept d JOIN cte c ON d.parent_id = c.id\" +\n                \") SELECT * FROM cte\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_for_update() {\n        String sql = \"SELECT * FROM t1 WHERE id = 1 FOR UPDATE\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_for_update_nowait() {\n        String sql = \"SELECT * FROM t1 WHERE id = 1 FOR UPDATE NOWAIT\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_for_update_wait() {\n        // DM: FOR UPDATE WAIT N\n        String sql = \"SELECT * FROM t1 WHERE id = 1 FOR UPDATE WAIT 5\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_for_update_skip_locked() {\n        // DM: FOR UPDATE SKIP LOCKED\n        String sql = \"SELECT * FROM t1 WHERE id = 1 FOR UPDATE SKIP LOCKED\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_distinct() {\n        String sql = \"SELECT DISTINCT name FROM t1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_case_when() {\n        String sql = \"SELECT id, CASE WHEN status = 1 THEN 'active' WHEN status = 0 THEN 'inactive' ELSE 'unknown' END AS status_desc FROM t1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_window_function() {\n        String sql = \"SELECT id, name, ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rn FROM employees\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_rank_dense_rank() {\n        String sql = \"SELECT id, RANK() OVER (ORDER BY salary DESC) AS rnk, DENSE_RANK() OVER (ORDER BY salary DESC) AS drnk FROM employees\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_connect_by() {\n        // DM Oracle-compatible hierarchical query\n        String sql = \"SELECT id, name, LEVEL FROM dept START WITH parent_id IS NULL CONNECT BY PRIOR id = parent_id\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_connect_by_nocycle() {\n        String sql = \"SELECT id, name FROM dept CONNECT BY NOCYCLE PRIOR id = parent_id START WITH parent_id IS NULL\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_exists() {\n        String sql = \"SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.aid = t1.id)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_in_subquery() {\n        String sql = \"SELECT * FROM t1 WHERE id IN (SELECT aid FROM t2 WHERE status = 1)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_nvl() {\n        // DM Oracle-compatible NVL function\n        String sql = \"SELECT NVL(name, 'unknown') FROM t1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_decode() {\n        // DM Oracle-compatible DECODE function\n        String sql = \"SELECT DECODE(status, 1, 'active', 0, 'inactive', 'unknown') FROM t1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_sysdate() {\n        // DM Oracle-compatible SYSDATE\n        String sql = \"SELECT SYSDATE FROM DUAL\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_nulls_first_last() {\n        // DM: ORDER BY ... NULLS FIRST|LAST\n        String sql = \"SELECT * FROM t1 ORDER BY name ASC NULLS FIRST\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    // ========== Error case tests ==========\n\n    @Test\n    public void test_select_invalid_sql_missing_from() {\n        // Incomplete SQL should throw ParserException\n        String sql = \"SELECT FROM\";\n        assertThrows(ParserException.class, () -> SQLUtils.parseStatements(sql, dbType));\n    }\n\n    @Test\n    public void test_select_invalid_empty_select() {\n        // Empty string should throw\n        String sql = \"SELECT\";\n        assertThrows(ParserException.class, () -> SQLUtils.parseStatements(sql, dbType));\n    }\n\n    @Test\n    public void test_select_invalid_fetch_missing_rows() {\n        // FETCH NEXT 10 without ROWS ONLY should throw\n        String sql = \"SELECT * FROM t1 ORDER BY id OFFSET 5 FETCH NEXT 10\";\n        assertThrows(ParserException.class, () -> SQLUtils.parseStatements(sql, dbType));\n    }\n\n    // ========== LIMIT/OFFSET edge case tests ==========\n\n    @Test\n    public void test_select_limit_all() {\n        // DM: LIMIT ALL\n        String sql = \"SELECT * FROM t1 LIMIT ALL\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_limit_zero() {\n        String sql = \"SELECT * FROM t1 LIMIT 0\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_select_offset_rows() {\n        // DM: OFFSET n ROWS (with ROWS suffix)\n        String sql = \"SELECT * FROM t1 ORDER BY id OFFSET 10 ROWS\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_offset_row() {\n        // DM: OFFSET n ROW (singular)\n        String sql = \"SELECT * FROM t1 ORDER BY id OFFSET 1 ROW\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_limit_offset_expressions() {\n        // LIMIT/OFFSET with complex expressions\n        String sql = \"SELECT * FROM t1 ORDER BY id LIMIT 10 + 5 OFFSET 20 * 2\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_limit_offset_comma_zero() {\n        // LIMIT 0, 10 (offset=0, count=10)\n        String sql = \"SELECT * FROM t1 ORDER BY id LIMIT 0, 10\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_fetch_first() {\n        // FETCH FIRST (not NEXT)\n        String sql = \"SELECT * FROM t1 ORDER BY id FETCH FIRST 5 ROWS ONLY\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    @Test\n    public void test_select_offset_fetch_first() {\n        // OFFSET + FETCH FIRST combined\n        String sql = \"SELECT * FROM t1 ORDER BY id OFFSET 10 ROWS FETCH FIRST 5 ROWS ONLY\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n\n    // ========== FOR UPDATE OF test ==========\n\n    @Test\n    public void test_select_for_update_of() {\n        String sql = \"SELECT * FROM t1 WHERE id = 1 FOR UPDATE OF name, status\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/dm/DM_UpdateTest.java",
    "content": "package com.alibaba.druid.bvt.sql.dm;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DM_UpdateTest {\n    private final DbType dbType = DbType.dm;\n\n    @Test\n    public void test_update_basic() {\n        String sql = \"UPDATE t1 SET name = 'test', status = 1 WHERE id = 1\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_update_with_subquery() {\n        String sql = \"UPDATE t1 SET name = (SELECT name FROM t2 WHERE t2.id = t1.aid) WHERE status = 0\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n        SQLParseAssertUtil.assertParseSql(sql, dbType);\n    }\n\n    @Test\n    public void test_update_with_join() {\n        String sql = \"UPDATE t1 a SET a.name = b.name FROM t2 b WHERE a.id = b.aid\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);\n        assertEquals(1, stmtList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/doris/DorisResourceTest.java",
    "content": "package com.alibaba.druid.bvt.sql.doris;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class DorisResourceTest extends SQLResourceTest {\n    public DorisResourceTest() {\n        super(DbType.doris);\n    }\n\n    @Test\n    public void doris_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/doris/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/elastic/Elastic_StatFilter_merge_0.java",
    "content": "package com.alibaba.druid.bvt.sql.elastic;\n\nimport com.alibaba.druid.filter.stat.MergeStatFilter;\nimport com.alibaba.druid.filter.stat.StatFilter;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Elastic_StatFilter_merge_0 {\n    @Test\n    public void test_for_stat_merge() throws Exception {\n        String sql = \"/* ///9fe39e72/ */SELECT fkc1.fkc_order_id, fkc1.out_order_id, fkc1.seller_nick, fkc1.buyer_nick, fkc1.seller_id, fkc1.buyer_id, fkc1.auction_id, fkc1.auction_title, fkc1.auction_price, fkc1.buy_amount, fkc1.fkc_type, fkc1.sub_fkc_type, fkc1.fail_reason, fkc1.pay_status, fkc1.logistics_status, fkc1.out_trade_status, fkc1.snap_path, fkc1.gmt_create, fkc1.status, ifnull(fkc1.buyer_rate_status, 4) AS buyer_rate_status, ifnull(fkc1.seller_rate_status, 4) AS seller_rate_status, fkc1.auction_pict_url, fkc1.seller_memo, fkc1.buyer_memo, fkc1.seller_flag, fkc1.buyer_flag, fkc1.buyer_message_path, fkc1.refund_status, fkc1.attributes, fkc1.attributes_cc, fkc1.gmt_modified, fkc1.ip, fkc1.end_time, fkc1.pay_time, fkc1.is_main, fkc1.is_detail, fkc1.point_rate, fkc1.parent_id, fkc1.adjust_fee, fkc1.discount_fee, fkc1.refund_fee, fkc1.confirm_paid_fee, fkc1.cod_status, fkc1.trade_tag, fkc1.shop_id, fkc1.options, fkc1.ignore_sold_quantity, fkc1.from_group, fkc1.gmt_create_tc FROM (SELECT fkc_order_id FROM tc_fkc_order AS tc_fkc_order IGNORE INDEX (ind_fkc_order_status, idx_sid_bt_st_im) WHERE is_main = 1 AND (fkc_type = 2700 OR fkc_type = 200 OR fkc_type = 10000 OR fkc_type = 610 OR fkc_type = 600 OR fkc_type = 300 OR fkc_type = 100 OR fkc_type = 500 OR fkc_type = 900 OR fkc_type = 620 OR fkc_type = 630 OR fkc_type = 650 OR fkc_type = 1000 OR fkc_type = 1001 OR fkc_type = 710 OR fkc_type = 1200 OR fkc_type = 1201 OR fkc_type = 1500 OR fkc_type = 1600 OR fkc_type = 2000 OR fkc_type = 2400) AND seller_id = 2169996291 AND (sub_fkc_type = 1 OR sub_fkc_type = 901 OR sub_fkc_type = 801 OR sub_fkc_type = 701 OR sub_fkc_type = 601 OR sub_fkc_type = 2) AND status = 0 AND gmt_create >= DATE_FORMAT('2017-04-22 00:00:00', '%Y-%m-%d %T') AND gmt_create <= DATE_FORMAT('2017-05-07 23:59:59', '%Y-%m-%d %T') AND from_group = 0 ORDER BY gmt_create DESC LIMIT 900, 100) AS fkc2, tc_fkc_order AS fkc1 WHERE fkc2.fkc_order_id = 1\";\n        StatFilter filter = new MergeStatFilter();\n        filter.setDbType(JdbcConstants.ELASTIC_SEARCH);\n        String mergedSql = filter.mergeSql(sql, JdbcConstants.ELASTIC_SEARCH);\n        assertEquals(\"SELECT fkc1.fkc_order_id, fkc1.out_order_id, fkc1.seller_nick, fkc1.buyer_nick, fkc1.seller_id\\n\" +\n                \"\\t, fkc1.buyer_id, fkc1.auction_id, fkc1.auction_title, fkc1.auction_price, fkc1.buy_amount\\n\" +\n                \"\\t, fkc1.fkc_type, fkc1.sub_fkc_type, fkc1.fail_reason, fkc1.pay_status, fkc1.logistics_status\\n\" +\n                \"\\t, fkc1.out_trade_status, fkc1.snap_path, fkc1.gmt_create, fkc1.status\\n\" +\n                \"\\t, ifnull(fkc1.buyer_rate_status, ?) AS buyer_rate_status\\n\" +\n                \"\\t, ifnull(fkc1.seller_rate_status, ?) AS seller_rate_status, fkc1.auction_pict_url\\n\" +\n                \"\\t, fkc1.seller_memo, fkc1.buyer_memo, fkc1.seller_flag, fkc1.buyer_flag, fkc1.buyer_message_path\\n\" +\n                \"\\t, fkc1.refund_status, fkc1.attributes, fkc1.attributes_cc, fkc1.gmt_modified, fkc1.ip\\n\" +\n                \"\\t, fkc1.end_time, fkc1.pay_time, fkc1.is_main, fkc1.is_detail, fkc1.point_rate\\n\" +\n                \"\\t, fkc1.parent_id, fkc1.adjust_fee, fkc1.discount_fee, fkc1.refund_fee, fkc1.confirm_paid_fee\\n\" +\n                \"\\t, fkc1.cod_status, fkc1.trade_tag, fkc1.shop_id, fkc1.options, fkc1.ignore_sold_quantity\\n\" +\n                \"\\t, fkc1.from_group, fkc1.gmt_create_tc\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT fkc_order_id\\n\" +\n                \"\\tFROM tc_fkc_order tc_fkc_order IGNORE INDEX (ind_fkc_order_status, idx_sid_bt_st_im)\\n\" +\n                \"\\tWHERE is_main = ?\\n\" +\n                \"\\t\\tAND (fkc_type = ?)\\n\" +\n                \"\\t\\tAND seller_id = ?\\n\" +\n                \"\\t\\tAND (sub_fkc_type = ?)\\n\" +\n                \"\\t\\tAND status = ?\\n\" +\n                \"\\t\\tAND gmt_create >= DATE_FORMAT(?, '%Y-%m-%d %T')\\n\" +\n                \"\\t\\tAND gmt_create <= DATE_FORMAT(?, '%Y-%m-%d %T')\\n\" +\n                \"\\t\\tAND from_group = ?\\n\" +\n                \"\\tORDER BY gmt_create DESC\\n\" +\n                \"\\tLIMIT ?, ?\\n\" +\n                \") fkc2, tc_fkc_order fkc1\\n\" +\n                \"WHERE fkc2.fkc_order_id = ?\", mergedSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalAndOrTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalAndOrTest {\n    @Test\n    public void test_and() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>0 && ?>0\", 1, 0));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"2>1 && 100>10\"));\n    }\n\n    @Test\n    public void test_or() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"10>0 || 2>0\"));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"10>0 || 2<0\"));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"2>10 || 100<10\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalBetweenTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalBetweenTest {\n    @Test\n    public void test_between() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? between 1 and 3\", 0));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? between 1 and 3\", 2));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? between 1 and 3\", 4));\n    }\n\n    @Test\n    public void test_not_between() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? not between 1 and 3\", 0));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? not between 1 and 3\", 2));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? not between 1 and 3\", 4));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalCaseThen.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalCaseThen {\n    @Test\n    public void test_eval_then() throws Exception {\n        assertEquals(111, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"case ? when 0 then 111 else 222 end\", 0));\n        assertEquals(222, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"case ? when 0 then 111 else 222 end\", 1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalConcatTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalConcatTest {\n    @Test\n    public void test_concat() throws Exception {\n        assertEquals(\"abcd\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"concat(?, ?)\", \"ab\", \"cd\"));\n        assertEquals(\"abcdef\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"concat(?, ?, ?)\", \"ab\", \"cd\", \"ef\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalInTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalInTest {\n    @Test\n    public void test_in() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? IN (1, 2, 3)\", 0));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? IN (1, 2, 3)\", 1));\n    }\n\n    @Test\n    public void test_not_in() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? NOT IN (1, 2, 3)\", 0));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? NOT IN (1, 2, 3)\", 1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalIsNullTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalIsNullTest {\n    @Test\n    public void test_null() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? is null\", 0));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? is null\", (Object) null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalLikeTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalLikeTest {\n    @Test\n    public void test_like() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'a' LIKE '[a-d]'\"));\n    }\n\n    @Test\n    public void test_not_like() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'a' NOT LIKE '[a-d]'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodAbsTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodAbsTest {\n    @Test\n    public void test_abs_int() throws Exception {\n        assertEquals(12, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs(-12)\"));\n        assertEquals(12, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs(12)\"));\n    }\n\n    @Test\n    public void test_abs_long() throws Exception {\n        assertEquals(12L, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs(?)\", 12L));\n        assertEquals(12L, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs(?)\", -12L));\n    }\n\n    @Test\n    public void test_abs_decimal() throws Exception {\n        assertEquals(new BigDecimal(\"12\"), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs(?)\", new BigDecimal(\"12\")));\n        assertEquals(new BigDecimal(\"12\"), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs(?)\", new BigDecimal(\"-12\")));\n    }\n\n    @Test\n    public void test_abs_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_abs_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"abs(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodAcosTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodAcosTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(0.0D, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"acos(1)\"));\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"acos(1.001)\"));\n        assertEquals(Math.acos(0), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"acos(0)\"));\n    }\n\n    @Test\n    public void test_abs_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"acos()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_abs_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"acos(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodAsciiTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodAsciiTest {\n    @Test\n    public void test_ascii() throws Exception {\n        assertEquals(50, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ascii('2')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodAsinTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodAsinTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.asin(0.2), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"asin(0.2)\"));\n    }\n\n    @Test\n    public void test_abs_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"asin()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_abs_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"asin(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodAtan2Test.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodAtan2Test {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.atan2(-2, 2), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"atan2(-2, 2)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"atan2()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"atan2(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodAtanTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodAtanTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.atan(2), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"atan(2)\"));\n        assertEquals(Math.atan(-2), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"atan(-2)\"));\n    }\n\n    @Test\n    public void test_abs_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"atan()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_abs_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"atan(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodBinTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodBinTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(32, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"BIT_LENGTH('text')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodBitLengthTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodBitLengthTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(\"1100\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"BIN(12)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodCeilTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodCeilTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ceil(1.23)\"));\n        assertEquals(-1, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ceil(-1.23)\"));\n        assertEquals(-1, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ceiling(-1.24)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ceil()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ceil(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodCosTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodCosTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.cos(1), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"cos(1)\"));\n        assertEquals(Math.cos(1.001), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"cos(1.001)\"));\n        assertEquals(Math.cos(0), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"cos(0)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"cos()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"cos(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodInstrTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodInstrTest {\n    @Test\n    public void test_length() throws Exception {\n        assertEquals(4, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"instr('foobarbar', 'bar')\"));\n        assertEquals(0, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"instr('xbar', 'foobar')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodLeftTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodLeftTest {\n    @Test\n    public void test_ascii() throws Exception {\n        assertEquals(\"fooba\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LEFT('foobarbar', 5)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodLengthTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodLengthTest {\n    @Test\n    public void test_length() throws Exception {\n        assertEquals(4, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"length('text')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodLog10Test.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodLog10Test {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.log10(1), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log10(1)\"));\n        assertEquals(Math.log10(1.001), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log10(1.001)\"));\n        assertEquals(Math.log10(0), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log10(0)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log10()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log10(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodLogTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodLogTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.log(1), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log(1)\"));\n        assertEquals(Math.log(1.001), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log(1.001)\"));\n        assertEquals(Math.log(0), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log(0)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"log(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodModTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodModTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"MOD(29,9)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodNowTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodNowTest {\n    @Test\n    public void test_now() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"now()\") instanceof Date);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodPITest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodPITest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.PI, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"pi()\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodPowerTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodPowerTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.pow(1, 2), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"power(1, 2)\"));\n        assertEquals(Math.pow(3, 4), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"power(3, 4)\"));\n        assertEquals(Math.pow(4, 5), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"pow(4, 5)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"pow()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"pow(a,b)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodRandom.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodRandom {\n    @Test\n    public void test_reverse() throws Exception {\n        assertNotNull(SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"rand()\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodReverseTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodReverseTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(\"cba\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"REVERSE('abc')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodRightTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodRightTest {\n    @Test\n    public void test_ascii() throws Exception {\n        assertEquals(\"rbar\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"right('foobarbar', 4)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodSinTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodSinTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.sin(1), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sin(1)\"));\n        assertEquals(Math.sin(1.001), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sin(1.001)\"));\n        assertEquals(Math.sin(0), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sin(0)\"));\n        assertEquals(Math.sin(2), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sin(2)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sin()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sin(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodSqrtTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodSqrtTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.sqrt(1), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sqrt(1)\"));\n        assertEquals(Math.sqrt(1.001), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sqrt(1.001)\"));\n        assertEquals(Math.sqrt(0), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sqrt(0)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sqrt()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"sqrt(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTanTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTanTest {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(Math.tan(1), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"tan(1)\"));\n        assertEquals(Math.tan(1.001), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"tan(1.001)\"));\n        assertEquals(Math.tan(0), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"tan(0)\"));\n    }\n\n    @Test\n    public void test_error() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"tan()\", 12L);\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n\n    @Test\n    public void test_error_1() throws Exception {\n        Exception error = null;\n        try {\n            SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"tan(a)\");\n        } catch (Exception e) {\n            error = e;\n        }\n        assertNotNull(error);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_Char.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_Char {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(\"MySQL\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"CHAR(77,121,83,81,'76')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_Char_1.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_Char_1 {\n    @Test\n    public void test_reverse() throws Exception {\n        assertEquals(\"MMM\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"CHAR(77,77.3,'77.3')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_Elt.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_Elt {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"ej\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ELT(1, 'ej', 'Heja', 'hej', 'foo')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_Elt_1.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_Elt_1 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(null,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"ELT(11, 'ej', 'Heja', 'hej', 'foo')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_insert.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_insert {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"Quadratic\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"INSERT('Quadratic', -1, 4, 'What')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_insert_1.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_insert_1 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"QuWhattic\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"INSERT('Quadratic', 3, 4, 'What')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_insert_2.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_insert_2 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"QuWhat\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"INSERT('Quadratic', 3, 100, 'What')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_instr.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_instr {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(4, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"INSTR('foobarbar', 'bar')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_instr_1.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_instr_1 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(0, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"INSTR('xbar', 'foobar')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_lcase.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_lcase {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"quadratically\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LOWER('QUADRATICALLY')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_left.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_left {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"fooba\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LEFT('foobarbar', 5)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_len.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_len {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(4, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LENGTH('text')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_locate.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_locate {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(4, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LOCATE('bar', 'foobarbar')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_locate_1.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_locate_1 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(0, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LOCATE('xbar', 'foobar')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_locate_2.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_locate_2 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(7, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LOCATE('bar', 'foobarbar', 5)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_lower.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_lower {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"quadratically\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LOWER('QUADRATICALLY')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_lpad.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_lpad {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"??hi\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LPAD('hi',4,'??')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_lpad_1.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_lpad_1 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"h\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LPAD('hi',1,'??')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_ltrim.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_ltrim {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"barbar\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"LTRIM('  barbar')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_mid.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_mid {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"ratically\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"mid('Quadratically',5)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_substring.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_substring {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"barbar\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"SUBSTRING('foobarbar' FROM 4)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_substring_1.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_substring_1 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"ratica\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"SUBSTRING('Quadratically',5,6)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_substring_2.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_substring_2 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"ila\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"SUBSTRING('Sakila', -3)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_substring_3.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_substring_3 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"aki\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"SUBSTRING('Sakila', -5, 3)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTest_substring_4.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTest_substring_4 {\n    @Test\n    public void test_method() throws Exception {\n        assertEquals(\"ki\",\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"SUBSTRING('Sakila' FROM -4 FOR 2)\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalMethodTrimTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalMethodTrimTest {\n    @Test\n    public void test_trim() throws Exception {\n        assertEquals(\"bar\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"TRIM('  bar   ')\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalRlikeTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalRlikeTest {\n    @Test\n    public void test_rlike() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'a' REGEXP '^[a-d]'\"));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'a' RLIKE '^[a-d]'\"));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'1' RLIKE '^[a-d]'\"));\n    }\n\n    @Test\n    public void test_not_rlike() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'a' NOT REGEXP '^[a-d]'\"));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'a' NOT RLIKE '^[a-d]'\"));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"'1' NOT RLIKE '^[a-d]'\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalSelectTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalSelectTest {\n    @Test\n    public void test_select() throws Exception {\n        List<List<Object>> rows = new ArrayList<List<Object>>();\n        List<Object> row = new ArrayList<Object>();\n        row.add(1);\n        rows.add(row);\n        assertEquals(rows, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"SELECT 1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest {\n    @Test\n    public void testEval() throws Exception {\n        assertEquals(\"A\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?\", \"A\"));\n        assertEquals(123, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?\", 123));\n    }\n\n    @Test\n    public void testEval_1() throws Exception {\n        assertEquals(\"AB\", SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", \"A\", \"B\"));\n        assertEquals(234, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", 123, 111));\n    }\n\n    @Test\n    public void testEval_2() throws Exception {\n        assertEquals(110, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * ?\", 10, 11));\n    }\n\n    @Test\n    public void testEval_3() throws Exception {\n        assertEquals(new BigDecimal(\"110\"), SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * ?\",\n                new BigDecimal(\"10\"),\n                new BigDecimal(\"11\")));\n    }\n\n    @Test\n    public void testEval_4() throws Exception {\n        assertEquals(new BigDecimal(\"110\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * 11\", new BigDecimal(\"10\")));\n    }\n\n    @Test\n    public void testEval_5() throws Exception {\n        assertEquals(new BigDecimal(\"110.0\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * 11.0\", new BigDecimal(\"10\")));\n    }\n\n    @Test\n    public void testEval_6() throws Exception {\n        assertEquals(new BigDecimal(\"110.0\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * 11\", new BigDecimal(\"10.0\")));\n    }\n\n    @Test\n    public void testEval_7() throws Exception {\n        assertEquals(new BigDecimal(\"110.0\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * 11.0\", \"10\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_add.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_add {\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(3, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (byte) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_byte_1() throws Exception {\n        assertEquals(3, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (byte) 1, \"2\"));\n    }\n\n    @Test\n    public void test_byte_2() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (byte) 1, null));\n    }\n\n    @Test\n    public void test_byte_3() throws Exception {\n        assertEquals(3, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", \"2\", (byte) 1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_add_long.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_add_long {\n    @Test\n    public void test_add() throws Exception {\n        assertEquals(3L, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (long) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_add_1() throws Exception {\n        assertEquals(3L, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (long) 1, \"2\"));\n    }\n\n    @Test\n    public void test_add_2() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (long) 1, null));\n    }\n\n    @Test\n    public void test_add_3() throws Exception {\n        assertEquals(3L, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (byte) 2, (long) 1));\n    }\n\n    @Test\n    public void test_add_4() throws Exception {\n        assertEquals(3L, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", \"2\", (long) 1));\n    }\n\n    @Test\n    public void test_add_5() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", null, (long) 1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_add_short.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_add_short {\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(3, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (short) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_byte_1() throws Exception {\n        assertEquals(3, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (short) 1, \"2\"));\n    }\n\n    @Test\n    public void test_byte_2() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", (short) 1, null));\n    }\n\n    @Test\n    public void test_byte_3() throws Exception {\n        assertEquals(3, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? + ?\", \"2\", (short) 1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_div.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_div {\n    @Test\n    public void test_long() throws Exception {\n        assertEquals(0L, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (long) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_int() throws Exception {\n        assertEquals(0, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (int) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_short() throws Exception {\n        assertEquals(0, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (short) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(0, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (byte) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_BigInteger() throws Exception {\n        assertEquals(BigInteger.ZERO,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", BigInteger.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_BigDecimal() throws Exception {\n        assertEquals(new BigDecimal(\"0.5\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", BigDecimal.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_float() throws Exception {\n        assertEquals(0.5F, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (float) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_double() throws Exception {\n        assertEquals(0.5D, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (double) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_double_zero() throws Exception {\n        assertEquals(Double.POSITIVE_INFINITY,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (double) 1, 0));\n    }\n\n    @Test\n    public void test_double_zero_1() throws Exception {\n        assertEquals(Double.NEGATIVE_INFINITY,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (double) -1D, 0));\n    }\n\n    @Test\n    public void test_double_zero_2() throws Exception {\n        assertEquals(Double.NaN,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (double) 0D, 0));\n    }\n\n    @Test\n    public void test_double_null() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (double) 1, null));\n    }\n\n    @Test\n    public void test_double_null_1() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", null, (double) 1));\n    }\n\n    //\n    @Test\n    public void test_float_zero() throws Exception {\n        assertEquals(Float.POSITIVE_INFINITY,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (float) 1, 0));\n    }\n\n    @Test\n    public void test_float_zero_1() throws Exception {\n        assertEquals(Float.NEGATIVE_INFINITY,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (float) -1F, 0));\n    }\n\n    @Test\n    public void test_float_zero_2() throws Exception {\n        assertEquals(Float.NaN,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (float) 0F, 0));\n    }\n\n    @Test\n    public void test_float_null() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", (float) 1, null));\n    }\n\n    @Test\n    public void test_float_null_1() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?/?\", null, (float) 1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_gt.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_gt {\n    @Test\n    public void test_long() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (long) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_int() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (int) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_short() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (short) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (byte) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_BigInteger() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", BigInteger.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_BigDecimal() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", BigDecimal.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_float() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", (float) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_double() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", (double) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_String() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", \"1\", \"2\"));\n    }\n\n    @Test\n    public void test_Date() throws Exception {\n        assertEquals(false,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\",\n                        new Date(System.currentTimeMillis() - 10),\n                        new Date(System.currentTimeMillis())));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_gt_true.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_gt_true {\n    @Test\n    public void test_long() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (long) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_int() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (int) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_short() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (short) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? > ?\", (byte) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_BigInteger() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", BigInteger.TEN, (byte) 2));\n    }\n\n    @Test\n    public void test_BigDecimal() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", BigDecimal.TEN, (byte) 2));\n    }\n\n    @Test\n    public void test_float() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", (float) 3, (byte) 2));\n    }\n\n    @Test\n    public void test_double() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", (double) 3, (byte) 2));\n    }\n\n    @Test\n    public void test_String() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\", \"3\", \"2\"));\n    }\n\n    @Test\n    public void test_Date() throws Exception {\n        assertEquals(true,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?>?\",\n                        new Date(System.currentTimeMillis()),\n                        new Date(System.currentTimeMillis() - 10)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_lt.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_lt {\n    @Test\n    public void test_long() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (long) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_int() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (int) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_short() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (short) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (byte) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_BigInteger() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", BigInteger.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_BigDecimal() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", BigDecimal.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_float() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", (float) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_double() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", (double) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_String() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", \"1\", \"2\"));\n    }\n\n    @Test\n    public void test_Date() throws Exception {\n        assertEquals(true,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\",\n                        new Date(System.currentTimeMillis() - 10),\n                        new Date(System.currentTimeMillis())));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_lt_false.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_lt_false {\n    @Test\n    public void test_long() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (long) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_int() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (int) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_short() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (short) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? < ?\", (byte) 10, (byte) 2));\n    }\n\n    @Test\n    public void test_BigInteger() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", BigInteger.TEN, (byte) 2));\n    }\n\n    @Test\n    public void test_BigDecimal() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", BigDecimal.TEN, (byte) 2));\n    }\n\n    @Test\n    public void test_float() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", (float) 3, (byte) 2));\n    }\n\n    @Test\n    public void test_double() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", (double) 3, (byte) 2));\n    }\n\n    @Test\n    public void test_String() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\", \"3\", \"2\"));\n    }\n\n    @Test\n    public void test_Date() throws Exception {\n        assertEquals(false,\n                SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<?\",\n                        new Date(System.currentTimeMillis()),\n                        new Date(System.currentTimeMillis() - 10)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_lteq.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_lteq {\n    @Test\n    public void test_long() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? <= ?\", (long) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_int() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? <= ?\", (int) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_short() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? <= ?\", (short) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? <= ?\", (byte) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_BigInteger() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<=?\", BigInteger.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_BigDecimal() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<=?\", BigDecimal.ONE, (byte) 2));\n    }\n\n    @Test\n    public void test_float() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<=?\", (float) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_double() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<=?\", (double) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_String() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"?<=?\", \"1\", \"2\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/EvalTest_multi_short.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EvalTest_multi_short {\n    @Test\n    public void test_byte() throws Exception {\n        assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * ?\", (short) 1, (byte) 2));\n    }\n\n    @Test\n    public void test_byte_1() throws Exception {\n        assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * ?\", (short) 1, \"2\"));\n    }\n\n    @Test\n    public void test_byte_2() throws Exception {\n        assertEquals(null, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * ?\", (short) 1, null));\n    }\n\n    @Test\n    public void test_byte_3() throws Exception {\n        assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcConstants.MYSQL, \"? * ?\", \"2\", (short) 1));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/LikeTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LikeTest {\n    @Test\n    public void test_any_0() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcdefg\", \"%\"));\n    }\n\n    @Test\n    public void test_any_1() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcdefg\", \"%%\"));\n    }\n\n    @Test\n    public void test_any_2() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcdefg\", \"%b%\"));\n    }\n\n    @Test\n    public void test_any_3() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcdefg\", \"a%\"));\n    }\n\n    @Test\n    public void test_any_4() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcdefg\", \"%g\"));\n    }\n\n    @Test\n    public void test_single_0() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"a\", \"_\"));\n    }\n\n    @Test\n    public void test_single_1() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"ab\", \"__\"));\n    }\n\n    @Test\n    public void test_single_2() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcd\", \"a__d\"));\n    }\n\n    @Test\n    public void test_single_3() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcdf\", \"a__d_\"));\n    }\n\n    @Test\n    public void test_range_0() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"abcdf\", \"abcd[a-f]\"));\n    }\n\n    @Test\n    public void test_range_1() throws Exception {\n        assertFalse(SQLEvalVisitorUtils.like(\"abcdf\", \"abcd[a-e]\"));\n    }\n\n    @Test\n    public void test_range_2() throws Exception {\n        assertTrue(SQLEvalVisitorUtils.like(\"ab\", \"a[abf]\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/eval/SQLEvalVisitorUtilsTest.java",
    "content": "package com.alibaba.druid.bvt.sql.eval;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryExpr;\nimport com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLEvalVisitorUtilsTest {\n    @Test\n    public void test_instance() throws Exception {\n        new SQLEvalVisitorUtils();\n    }\n\n    @Test\n    public void test_evalExpr() throws Exception {\n        assertEquals(5, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", 2, 3));\n        assertEquals(6, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? * ?\", 2, 3));\n        assertEquals(-1, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", 2, 3));\n        assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? / ?\", 6, 3));\n    }\n\n    @Test\n    public void test_evalExpr_2() throws Exception {\n        assertEquals(5, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(6, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? * ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(-1, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(2, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? / ?\", Arrays.<Object>asList(6, 3)));\n    }\n\n    @Test\n    public void test_evalExpr_3() throws Exception {\n        assertEquals(5.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", \"2.0\", 3));\n        assertEquals(6.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? * ?\", \"2.0\", 3));\n        assertEquals(-1.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", \"2.0\", 3));\n        assertEquals(2.0f, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? / ?\", \"6.0\", 3));\n    }\n\n    @Test\n    public void test_add() throws Exception {\n        assertEquals(5, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(6, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(3, 3)));\n        assertEquals(7, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(4, 3)));\n    }\n\n    @Test\n    public void test_add_1() throws Exception {\n        assertEquals(5.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(2.0, 3)));\n        assertEquals(6.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(3.0, 3)));\n        assertEquals(7.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(4.0, 3)));\n    }\n\n    @Test\n    public void test_add_2() throws Exception {\n        assertEquals(5.1, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(2.1, 3)));\n        assertEquals(6.2, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(3.2, 3)));\n        assertEquals(7.3, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(4.3, 3)));\n    }\n\n    @Test\n    public void test_add_3() throws Exception {\n        assertEquals(5.1D,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(2.1D, 3)));\n        assertEquals(6.2D,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(3.2D, 3)));\n        assertEquals(7.3D,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(4.3D, 3)));\n    }\n\n    @Test\n    public void test_add_4() throws Exception {\n        assertEquals(5.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(2, 3.0)));\n        assertEquals(6.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(3, 3.0)));\n        assertEquals(7.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\", Arrays.<Object>asList(4, 3.0)));\n    }\n\n    @Test\n    public void test_add_5() throws Exception {\n        assertEquals(new BigInteger(\"5\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\",\n                        Arrays.<Object>asList(2, new BigInteger(\"3\"))));\n        assertEquals(new BigInteger(\"6\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\",\n                        Arrays.<Object>asList(3, new BigInteger(\"3\"))));\n        assertEquals(new BigInteger(\"7\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\",\n                        Arrays.<Object>asList(4, new BigInteger(\"3\"))));\n    }\n\n    @Test\n    public void test_add_6() throws Exception {\n        assertEquals(new BigDecimal(\"5\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\",\n                        Arrays.<Object>asList(2, new BigDecimal(\"3\"))));\n        assertEquals(new BigDecimal(\"6\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\",\n                        Arrays.<Object>asList(3, new BigDecimal(\"3\"))));\n        assertEquals(new BigDecimal(\"7\"),\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? + ?\",\n                        Arrays.<Object>asList(4, new BigDecimal(\"3\"))));\n    }\n\n    @Test\n    public void test_sub() throws Exception {\n        assertEquals(-1, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(3, 3)));\n        assertEquals(1, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(4, 3)));\n    }\n\n    @Test\n    public void test_sub_1() throws Exception {\n        assertEquals(-1.0,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(2.0, 3)));\n        assertEquals(0.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(3.0, 3)));\n        assertEquals(1.0, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(4.0, 3)));\n    }\n\n    @Test\n    public void test_sub_2() throws Exception {\n        assertEquals(2.1 - 3,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(2.1, 3)));\n        assertEquals(3.2 - 3,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(3.2, 3)));\n        assertEquals(4.3 - 3,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(4.3, 3)));\n    }\n\n    @Test\n    public void test_sub_3() throws Exception {\n        assertEquals(2.1D - 3,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(2.1D, 3)));\n        assertEquals(3.2D - 3,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(3.2D, 3)));\n        assertEquals(4.3D - 3,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? - ?\", Arrays.<Object>asList(4.3D, 3)));\n    }\n\n    @Test\n    public void test_lt() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? < ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? < ?\", Arrays.<Object>asList(3, 3)));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? < ?\", Arrays.<Object>asList(4, 3)));\n    }\n\n    @Test\n    public void test_lt_1() throws Exception {\n        assertEquals(true,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? < ?\", Arrays.<Object>asList(2.0, 3)));\n        assertEquals(false,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? < ?\", Arrays.<Object>asList(3.0, 3)));\n        assertEquals(false,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? < ?\", Arrays.<Object>asList(4.0, 3)));\n    }\n\n    @Test\n    public void test_ltEq() throws Exception {\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? <= ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? <= ?\", Arrays.<Object>asList(3, 3)));\n        assertEquals(false,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? <= ?\", Arrays.<Object>asList(4, 3)));\n    }\n\n    @Test\n    public void test_ltEq_1() throws Exception {\n        assertEquals(true,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? <= ?\", Arrays.<Object>asList(2.0, 3)));\n        assertEquals(true,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? <= ?\", Arrays.<Object>asList(3.0, 3)));\n        assertEquals(false,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? <= ?\", Arrays.<Object>asList(4.0, 3)));\n    }\n\n    @Test\n    public void test_gt() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? > ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? > ?\", Arrays.<Object>asList(3, 3)));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? > ?\", Arrays.<Object>asList(4, 3)));\n    }\n\n    @Test\n    public void test_gtEq() throws Exception {\n        assertEquals(false,\n                SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? >= ?\", Arrays.<Object>asList(2, 3)));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? >= ?\", Arrays.<Object>asList(3, 3)));\n        assertEquals(true, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"? >= ?\", Arrays.<Object>asList(4, 3)));\n    }\n\n    @Test\n    public void test_binary() throws Exception {\n        assertEquals(1L, SQLEvalVisitorUtils.eval(JdbcUtils.MYSQL, new SQLBinaryExpr(\"01\"), new ArrayList<Object>()));\n        assertEquals(2L, SQLEvalVisitorUtils.eval(JdbcUtils.MYSQL, new SQLBinaryExpr(\"10\"), new ArrayList<Object>()));\n        assertEquals(3L, SQLEvalVisitorUtils.eval(JdbcUtils.MYSQL, new SQLBinaryExpr(\"11\"), new ArrayList<Object>()));\n        assertEquals(4L, SQLEvalVisitorUtils.eval(JdbcUtils.MYSQL, new SQLBinaryExpr(\"100\"), new ArrayList<Object>()));\n        assertEquals(new BigInteger(\"36893488147419103231\"), SQLEvalVisitorUtils.eval(JdbcUtils.MYSQL, new SQLBinaryExpr(\"11111111111111111111111111111111111111111111111111111111111111111\"), new ArrayList<Object>()));\n    }\n\n    @Test\n    public void test_LessThanOrGreater() throws Exception {\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"1<>1\"));\n        assertEquals(false, SQLEvalVisitorUtils.evalExpr(JdbcUtils.MYSQL, \"?<>?\", Arrays.<Object>asList(1, 1)));\n    }\n\n    /**\n     * @see <a href=\"https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_lpad\">MySQL lapd</a>\n     * @throws Exception\n     */\n    @Test\n    public void test_string_lpad() throws Exception {\n        String sql = \"LPAD('hi',4,'??')\";\n        Object val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"??hi\", val);\n        sql = \"LPAD('hi',1,'??')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"h\", val);\n        sql = \"LPAD('hi',4,'abc')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"abhi\", val);\n\n        sql = \"LPAD('hi',7,'abc')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"abcabhi\", val);\n    }\n\n    /**\n     * @see <a href=\"https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_rpad\">MySQL rapd</a>\n     * @throws Exception\n     */\n    @Test\n    public void test_string_rpad() throws Exception {\n        String sql = \"RPAD('hi',5,'?')\";\n        Object val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"hi???\", val);\n\n        sql = \"RPAD('hi',1,'?')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"h\", val);\n\n        sql = \"RPAD('hi',5,'ab')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"hiaba\", val);\n\n        sql = \"RPAD('hi',7,'abc')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"hiabcab\", val);\n\n    }\n\n    /**\n     * @see <a href=\"https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_right\">MySQL right</a>\n     * @throws Exception\n     */\n    @Test\n    public void test_string_right() throws Exception {\n        String sql = \"RIGHT('foobarbar', 4)\";\n        Object val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"rbar\", val);\n        sql = \"RIGHT('ar', 4)\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"ar\", val);\n    }\n    @Test\n    public void test_string_replace() throws Exception {\n        String sql = \"replace('abcb','b','B')\";\n        Object val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"aBcB\", val);\n        sql = \"replace('abc',null,'B')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"abc\", val);\n        sql = \"replace('abc','b',null)\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"abc\", val);\n\n        sql = \"replace('abcbbccbc','bc','QWER')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"aQWERbQWERcQWER\", val);\n\n        sql = \"replace('www.mysql.com','w','Ww')\";\n        val = SQLEvalVisitorUtils.evalExpr(DbType.mysql, sql);\n        System.out.println(sql + \": \" + val);\n        assertEquals(\"WwWwWw.mysql.com\", val);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/gaussdb/GaussDbResourceTest.java",
    "content": "package com.alibaba.druid.bvt.sql.gaussdb;\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\npublic class GaussDbResourceTest extends SQLResourceTest {\n    public GaussDbResourceTest() {\n        super(DbType.gaussdb);\n    }\n    @Test\n    public void gaussdb_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/gaussdb/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2ResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.h2.parser.H2StatementParser;\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2OutputVisitor;\nimport com.alibaba.druid.sql.dialect.h2.visitor.H2SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcUtils;\nimport com.alibaba.druid.util.Utils;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2ResourceTest {\n    @Test\n    public void test_0() throws Exception {\n        exec_test(\"bvt/parser/h2-0.txt\");\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        exec_test(\"bvt/parser/h2-1.txt\");\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        exec_test(\"bvt/parser/h2-2.txt\");\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        exec_test(\"bvt/parser/h2-3.txt\");\n    }\n\n    public void exec_test(String resource) throws Exception {\n        System.out.println(resource);\n        InputStream is = null;\n\n        is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);\n        Reader reader = new InputStreamReader(is, \"UTF-8\");\n        String input = Utils.read(reader);\n        JdbcUtils.close(reader);\n        String[] items = input.split(\"---------------------------\");\n        String sql = items[0].trim();\n        String expect = items[1].trim();\n        if (expect != null) {\n            expect = expect.replaceAll(\"\\\\r\\\\n\", \"\\n\");\n        }\n\n        H2StatementParser parser = new H2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        H2SchemaStatVisitor visitor = new H2SchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(sql);\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"conditions : \" + visitor.getConditions());\n\n        System.out.println();\n        System.out.println();\n\n        if (expect != null && !expect.isEmpty()) {\n            assertEquals(expect, stmt.toString());\n        }\n    }\n\n    void mergValidate(String sql, String expect) {\n        H2StatementParser parser = new H2StatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        StringBuilder out = new StringBuilder();\n        H2OutputVisitor visitor = new H2OutputVisitor(out);\n        stmt.accept(visitor);\n\n        System.out.println(out.toString());\n\n        assertEquals(expect, out.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_AlterTableTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_AlterTableTest_0 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = //\n                \"alter table ACT_GE_BYTEARRAY add constraint ACT_FK_BYTEARR_DEPL foreign key (DEPLOYMENT_ID_) references ACT_RE_DEPLOYMENT (ID_);\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"ALTER TABLE ACT_GE_BYTEARRAY\\n\" +\n                    \"\\tADD CONSTRAINT ACT_FK_BYTEARR_DEPL FOREIGN KEY (DEPLOYMENT_ID_)\\n\" +\n                    \"\\t\\tREFERENCES ACT_RE_DEPLOYMENT (ID_);\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"ACT_GE_BYTEARRAY\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_CreateTableTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_CreateTableTest_0 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE IF NOT EXISTS `DTS_EXECUTION_COUNTER` (        `id` bigint(20) NOT NULL AUTO_INCREMENT,        `gmt_create` datetime DEFAULT NULL,        `gmt_modified` datetime DEFAULT NULL,        `job_id` bigint(20) DEFAULT NULL,        `job_instance_id` bigint(20) DEFAULT NULL,        `receive_node` varchar(255) DEFAULT NULL,        `task_name` varchar(255) DEFAULT NULL,        `total_counter` bigint(20),        `queued_counter` bigint(20),        `running_counter` bigint(20),        `success_counter` bigint(20),        `fail_counter` bigint(20),        PRIMARY KEY (`id`)        ) ; \";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"CREATE TABLE IF NOT EXISTS `DTS_EXECUTION_COUNTER` (\\n\" +\n                    \"\\t`id` bigint(20) AUTO_INCREMENT NOT NULL,\\n\" +\n                    \"\\t`gmt_create` datetime DEFAULT NULL,\\n\" +\n                    \"\\t`gmt_modified` datetime DEFAULT NULL,\\n\" +\n                    \"\\t`job_id` bigint(20) DEFAULT NULL,\\n\" +\n                    \"\\t`job_instance_id` bigint(20) DEFAULT NULL,\\n\" +\n                    \"\\t`receive_node` varchar(255) DEFAULT NULL,\\n\" +\n                    \"\\t`task_name` varchar(255) DEFAULT NULL,\\n\" +\n                    \"\\t`total_counter` bigint(20),\\n\" +\n                    \"\\t`queued_counter` bigint(20),\\n\" +\n                    \"\\t`running_counter` bigint(20),\\n\" +\n                    \"\\t`success_counter` bigint(20),\\n\" +\n                    \"\\t`fail_counter` bigint(20),\\n\" +\n                    \"\\tPRIMARY KEY (`id`)\\n\" +\n                    \");\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(12, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"DTS_EXECUTION_COUNTER\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_CreateTableTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_CreateTableTest_1 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE tutorials_tbl ( \\n\" +\n                        \"   id bigint generated by default as identity, \\n\" +\n                        \"   title VARCHAR(50) NOT NULL, \\n\" +\n                        \"   author VARCHAR(20) NOT NULL, \\n\" +\n                        \"   submission_date DATE \\n\" +\n                        \");\";\n\n        SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.h2);\n        assertEquals(\"CREATE TABLE tutorials_tbl (\\n\" +\n                \"\\tid bigint GENERATED ALWAYS AS DEFAULT AS IDENTITY,\\n\" +\n                \"\\ttitle VARCHAR(50) NOT NULL,\\n\" +\n                \"\\tauthor VARCHAR(20) NOT NULL,\\n\" +\n                \"\\tsubmission_date DATE\\n\" +\n                \");\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_CreateTriggerTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_CreateTriggerTest_0 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create trigger employee_trigger after insert,update,delete on employee for each row call \\\"test.redisson.h2cluster.trigger.ClusterTrigger\\\"\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"CREATE TRIGGER employee_trigger\\n\" +\n                    \"\\tAFTER INSERT OR DELETE OR UPDATE\\n\" +\n                    \"\\tON employee\\n\" +\n                    \"\\tFOR EACH ROW\\n\" +\n                    \"CALL \\\"test.redisson.h2cluster.trigger.ClusterTrigger\\\"()\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"employee\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_DropDatabaseTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLDropDatabaseStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_DropDatabaseTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DROP DATABASE IF EXISTS sonar\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.H2);\n        SQLDropDatabaseStatement stmt = (SQLDropDatabaseStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP DATABASE IF EXISTS sonar\", //\n                output);\n        assertTrue(stmt.isRestrict());\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_Explain_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_Explain_0 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"EXPLAIN SELECT * FROM TEST WHERE ID=1\";\n\n//        System.out.println(sql);\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.H2);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"EXPLAIN\\n\" +\n                    \"SELECT *\\n\" +\n                    \"FROM TEST\\n\" +\n                    \"WHERE ID = 1\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"TEST\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_InsertTest_0.java",
    "content": "package com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.h2.parser.H2StatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * @author machunxiao\n * @create 2018-08-02\n */\npublic class H2_InsertTest_0 {\n    @Test\n    public void test_insertSet() {\n        String sql = \"insert into tb1 set name='n1',age=12,date='1990-11-11 12:12:12'\";\n        H2StatementParser parser = new H2StatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        assertEquals(1, stmtList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_MergeTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_MergeTest_0 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"merge into person key(id) select * from person_test\";\n\n        System.out.println(sql);\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.H2);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"MERGE INTO person KEY (id)\\n\" +\n                    \"\\tSELECT *\\n\" +\n                    \"\\tFROM person_test\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"person\"));\n        assertTrue(visitor.containsTable(\"person_test\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_MergeTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_MergeTest_1 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"MERGE INTO CUSTOMER KEY (ID) VALUES (8, 'Loki', 32, 'Hyderabad', 3000);\";\n\n//        System.out.println(sql);\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.H2);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"MERGE INTO CUSTOMER KEY (ID)\\n\" +\n                    \"VALUES (8, 'Loki', 32, 'Hyderabad', 3000);\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"CUSTOMER\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_Select_0_limit.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_Select_0_limit extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"SELECT * FROM CUSTOMER LIMIT 1000;\";\n\n//        System.out.println(sql);\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.H2);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"SELECT *\\n\" +\n                    \"FROM CUSTOMER\\n\" +\n                    \"LIMIT 1000;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"CUSTOMER\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_Select_1_for_update.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_Select_1_for_update {\n    @Test\n    public void test_0() throws Exception {\n        String sql = //\n                \"SELECT * FROM QRTZ_LOCKS WHERE SCHED_NAME = 'adminQuartzScheduler' AND LOCK_NAME = ? FOR UPDATE\";\n\n//        System.out.println(sql);\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.H2);\n        stmt.accept(visitor);\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM QRTZ_LOCKS\\n\" +\n                \"WHERE SCHED_NAME = 'adminQuartzScheduler'\\n\" +\n                \"\\tAND LOCK_NAME = ?\\n\" +\n                \"FOR UPDATE\", stmt.toString());\n\n        assertEquals(\"select *\\n\" +\n                \"from QRTZ_LOCKS\\n\" +\n                \"where SCHED_NAME = 'adminQuartzScheduler'\\n\" +\n                \"\\tand LOCK_NAME = ?\\n\" +\n                \"for update\", stmt.toLowerCaseString());\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"QRTZ_LOCKS\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_Select_1_nulls_first.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.h2;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class H2_Select_1_nulls_first extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"SELECT * FROM (SELECT ID, COUNT(*) FROM TEST\\n\" +\n                        \"    GROUP BY ID UNION SELECT NULL, COUNT(*) FROM TEST)\\n\" +\n                        \"    ORDER BY 1 NULLS LAST;\";\n\n//        System.out.println(sql);\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.H2);\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(1, stmtList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.H2);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.H2);\n\n            assertEquals(\"SELECT *\\n\" +\n                    \"FROM (\\n\" +\n                    \"\\tSELECT ID, COUNT(*)\\n\" +\n                    \"\\tFROM TEST\\n\" +\n                    \"\\tGROUP BY ID\\n\" +\n                    \"\\tUNION\\n\" +\n                    \"\\tSELECT NULL, COUNT(*)\\n\" +\n                    \"\\tFROM TEST\\n\" +\n                    \")\\n\" +\n                    \"ORDER BY 1 NULLS LAST;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"TEST\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateDatabase_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateDatabase_0 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE DATABASE merge_data;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE DATABASE merge_data;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n//        assertTrue(visitor.containsTable(\"merge_data.transactions\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_0.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_0 {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"CREATE EXTERNAL TABLE students (name VARCHAR(64), age INT, gpa DECIMAL(3, 2))\\n\" +\n                \"  CLUSTERED BY (age) INTO 2 BUCKETS STORED AS ORC;\";\n        assertEquals(\"CREATE EXTERNAL TABLE students (\\n\" +\n                \"\\tname VARCHAR(64),\\n\" +\n                \"\\tage INT,\\n\" +\n                \"\\tgpa DECIMAL(3, 2)\\n\" +\n                \")\\n\" +\n                \"CLUSTERED BY (age)\\n\" +\n                \"INTO 2 BUCKETS\\n\" +\n                \"STORED AS ORC;\", SQLUtils.formatHive(sql));\n        assertEquals(\"create external table students (\\n\" +\n                \"\\tname VARCHAR(64),\\n\" +\n                \"\\tage INT,\\n\" +\n                \"\\tgpa DECIMAL(3, 2)\\n\" +\n                \")\\n\" +\n                \"clustered by (age)\\n\" +\n                \"into 2 buckets\\n\" +\n                \"stored as ORC;\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"students\", \"name\"));\n        assertTrue(visitor.containsColumn(\"students\", \"age\"));\n        assertTrue(visitor.containsColumn(\"students\", \"gpa\"));\n    }\n\n    @Test\n    public void test_create_table_without_as_1() throws Exception {\n        //https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable\n        String sql = \"CREATE TABLE new_key_value_store\\n\"\n            + \"   ROW FORMAT SERDE \\\"org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe\\\"\\n\"\n            + \"   STORED AS RCFile\\n\"\n            + \"   AS\\n\"\n            + \"SELECT (key % 1024) new_key, concat(key, value) key_value_pair\\n\"\n            + \"FROM key_value_store\\n\"\n            + \"SORT BY new_key, key_value_pair;\";\n\n        HiveStatementParser parser = new HiveStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statement = statementList.get(0);\n        System.out.println(statement);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n    }\n\n    @Test\n    public void test_create_table_without_as_2() throws Exception {\n        //https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable\n        String sql = \"CREATE TABLE new_key_value_store\\n\"\n            + \"   ROW FORMAT SERDE \\\"org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe\\\"\\n\"\n            + \"   STORED AS RCFile\\n\"\n            + \"SELECT (key % 1024) new_key, concat(key, value) key_value_pair\\n\"\n            + \"FROM key_value_store\\n\"\n            + \"SORT BY new_key, key_value_pair;\";\n\n        HiveStatementParser parser = new HiveStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statement = statementList.get(0);\n        System.out.println(statement);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_1 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table if not EXISTS sc001.test stored as parquet as\\n\" +\n                        \"select *  from sc002.test;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE IF NOT EXISTS sc001.test\\n\" +\n                    \"STORED AS parquet\\n\" +\n                    \"AS\\n\" +\n                    \"SELECT *\\n\" +\n                    \"FROM sc002.test;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"sc001.test\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_10.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_10 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE new_key_value_store\\n\" +\n                        \"   ROW FORMAT SERDE \\\"org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe\\\"\\n\" +\n                        \"   STORED AS RCFile\\n\" +\n                        \"   AS\\n\" +\n                        \"SELECT (key % 1024) new_key, concat(key, value) key_value_pair\\n\" +\n                        \"FROM key_value_store\\n\" +\n                        \"SORT BY new_key, key_value_pair;\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE new_key_value_store\\n\" +\n                    \"ROW FORMAT\\n\" +\n                    \"\\tSERDE 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe'\\n\" +\n                    \"STORED AS RCFile\\n\" +\n                    \"AS\\n\" +\n                    \"SELECT (key % 1024) AS new_key, concat(key, value) AS key_value_pair\\n\" +\n                    \"FROM key_value_store\\n\" +\n                    \"SORT BY new_key, key_value_pair;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"new_key_value_store\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_11.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_11 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE empty_key_value_store\\n\" +\n                        \"LIKE key_value_store;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE empty_key_value_store\\n\" +\n                    \"LIKE key_value_store;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"empty_key_value_store\"));\n        assertTrue(visitor.containsTable(\"key_value_store\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_12.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_12 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE page_view(viewTime INT, userid BIGINT,\\n\" +\n                        \"     page_url STRING, referrer_url STRING,\\n\" +\n                        \"     ip STRING COMMENT 'IP Address of the User')\\n\" +\n                        \" COMMENT 'This is the page view table'\\n\" +\n                        \" PARTITIONED BY(dt STRING, country STRING)\\n\" +\n                        \" CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS\\n\" +\n                        \" ROW FORMAT DELIMITED\\n\" +\n                        \"   FIELDS TERMINATED BY '\\\\001'\\n\" +\n                        \"   COLLECTION ITEMS TERMINATED BY '\\\\002'\\n\" +\n                        \"   MAP KEYS TERMINATED BY '\\\\003'\\n\" +\n                        \" STORED AS SEQUENCEFILE;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE page_view (\\n\" +\n                    \"\\tviewTime INT,\\n\" +\n                    \"\\tuserid BIGINT,\\n\" +\n                    \"\\tpage_url STRING,\\n\" +\n                    \"\\treferrer_url STRING,\\n\" +\n                    \"\\tip STRING COMMENT 'IP Address of the User'\\n\" +\n                    \")\\n\" +\n                    \"COMMENT 'This is the page view table'\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tdt STRING,\\n\" +\n                    \"\\tcountry STRING\\n\" +\n                    \")\\n\" +\n                    \"CLUSTERED BY (userid)\\n\" +\n                    \"SORTED BY (viewTime)\\n\" +\n                    \"INTO 32 BUCKETS\\n\" +\n                    \"ROW FORMAT DELIMITED\\n\" +\n                    \"\\tFIELDS TERMINATED BY '\\\\001'\\n\" +\n                    \"\\tCOLLECTION ITEMS TERMINATED BY '\\\\002'\\n\" +\n                    \"\\tMAP KEYS TERMINATED BY '\\\\003'\\n\" +\n                    \"STORED AS SEQUENCEFILE;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"page_view\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_13_skew.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_13_skew extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE list_bucket_single (key STRING, value STRING)\\n\" +\n                        \"  SKEWED BY (key) ON (1,5,6) STORED AS DIRECTORIES;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE list_bucket_single (\\n\" +\n                    \"\\tkey STRING,\\n\" +\n                    \"\\tvalue STRING\\n\" +\n                    \")\\n\" +\n                    \"SKEWED BY (key) ON (1,5,6) \" +\n                    \"STORED AS DIRECTORIES;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"list_bucket_single\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_14_skew.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_14_skew extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE list_bucket_multiple (col1 STRING, col2 int, col3 STRING)\\n\" +\n                        \"  SKEWED BY (col1, col2) ON (('s1',1), ('s3',3), ('s13',13), ('s78',78))\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE list_bucket_multiple (\\n\" +\n                    \"\\tcol1 STRING,\\n\" +\n                    \"\\tcol2 int,\\n\" +\n                    \"\\tcol3 STRING\\n\" +\n                    \")\\n\" +\n                    \"SKEWED BY (col1,col2) ON (('s1', 1),('s3', 3),('s13', 13),('s78', 78))\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"list_bucket_multiple\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_15_pk.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_15_pk extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table pk(id1 integer, id2 integer,\\n\" +\n                        \"  primary key(id1, id2) disable novalidate);\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE pk (\\n\" +\n                    \"\\tid1 integer,\\n\" +\n                    \"\\tid2 integer,\\n\" +\n                    \"\\tPRIMARY KEY (id1, id2) DISABLE NOVALIDATE\\n\" +\n                    \");\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"pk\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_16_fk.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_16_fk extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table fk(id1 integer, id2 integer,\\n\" +\n                        \"  constraint c1 foreign key(id1, id2) references pk(id2, id1) disable novalidate);\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE fk (\\n\" +\n                    \"\\tid1 integer,\\n\" +\n                    \"\\tid2 integer,\\n\" +\n                    \"\\tCONSTRAINT c1 FOREIGN KEY (id1, id2)\\n\" +\n                    \"\\t\\tREFERENCES pk (id2, id1) DISABLE NOVALIDATE\\n\" +\n                    \");\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"fk\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_17.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_17 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table dim_ad_sem_kw_intl(\\n\" +\n                        \"id bigint,\\n\" +\n                        \"iid string,\\n\" +\n                        \"url_domain string,\\n\" +\n                        \"sem_domain string,\\n\" +\n                        \"keyword string,\\n\" +\n                        \"landing_page string,\\n\" +\n                        \"campaign_type string,\\n\" +\n                        \"create_user string,\\n\" +\n                        \"gmt_created timestamp,\\n\" +\n                        \"campaign_url string,\\n\" +\n                        \"is_deleted bigint,\\n\" +\n                        \"campaign_plan string,\\n\" +\n                        \"campaign_name string\\n\" +\n                        \") partitioned by(ds string) stored as ORC;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE dim_ad_sem_kw_intl (\\n\" +\n                    \"\\tid bigint,\\n\" +\n                    \"\\tiid string,\\n\" +\n                    \"\\turl_domain string,\\n\" +\n                    \"\\tsem_domain string,\\n\" +\n                    \"\\tkeyword string,\\n\" +\n                    \"\\tlanding_page string,\\n\" +\n                    \"\\tcampaign_type string,\\n\" +\n                    \"\\tcreate_user string,\\n\" +\n                    \"\\tgmt_created timestamp,\\n\" +\n                    \"\\tcampaign_url string,\\n\" +\n                    \"\\tis_deleted bigint,\\n\" +\n                    \"\\tcampaign_plan string,\\n\" +\n                    \"\\tcampaign_name string\\n\" +\n                    \")\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tds string\\n\" +\n                    \")\\n\" +\n                    \"STORED AS ORC;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(13, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"dim_ad_sem_kw_intl\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_18.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_18 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE json_nested_test (\\n\" +\n                        \"\\tcountry string,\\n\" +\n                        \"\\tlanguages array<string>,\\n\" +\n                        \"\\treligions map<string,array<int>>)\\n\" +\n                        \"ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'\\n\" +\n                        \"STORED AS TEXTFILE;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE json_nested_test (\\n\" +\n                    \"\\tcountry string,\\n\" +\n                    \"\\tlanguages ARRAY<string>,\\n\" +\n                    \"\\treligions MAP<string, ARRAY<int>>\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT\\n\" +\n                    \"\\tSERDE 'org.openx.data.jsonserde.JsonSerDe'\\n\" +\n                    \"STORED AS TEXTFILE;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"json_nested_test\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_19.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_19 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE complex_array (\\n\" +\n                        \"\\tname string, address struct<street:string,city:string>\\n\" +\n                        \")\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE complex_array (\\n\" +\n                    \"\\tname string,\\n\" +\n                    \"\\taddress STRUCT<street:string, city:string>\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"complex_array\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_2 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE pageviews (userid VARCHAR(64), link STRING, came_from STRING)\\n\" +\n                        \"  PARTITIONED BY (datestamp STRING) CLUSTERED BY (userid) INTO 256 BUCKETS STORED AS ORC;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE pageviews (\\n\" +\n                    \"\\tuserid VARCHAR(64),\\n\" +\n                    \"\\tlink STRING,\\n\" +\n                    \"\\tcame_from STRING\\n\" +\n                    \")\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tdatestamp STRING\\n\" +\n                    \")\\n\" +\n                    \"CLUSTERED BY (userid)\\n\" +\n                    \"INTO 256 BUCKETS\\n\" +\n                    \"STORED AS ORC;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"pageviews\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_20.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_20 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE mytable (\\n\" +\n                        \"\\tmyfield string, ts string\\n\" +\n                        \") ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'\\n\" +\n                        \"WITH SERDEPROPERTIES ( \\\"mapping.ts\\\" = \\\"timestamp\\\" )\\n\" +\n                        \"STORED AS TEXTFILE;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE mytable (\\n\" +\n                    \"\\tmyfield string,\\n\" +\n                    \"\\tts string\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT\\n\" +\n                    \"\\tSERDE 'org.openx.data.jsonserde.JsonSerDe'\\n\" +\n                    \"WITH SERDEPROPERTIES (\\n\" +\n                    \"\\t\\\"mapping.ts\\\" = 'timestamp'\\n\" +\n                    \")\\n\" +\n                    \"STORED AS TEXTFILE;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"mytable\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_21.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_21 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table if not exists aliyun_cdm.test_903_table  (\\n\" +\n                        \"col1 TINYINT,col2 SMALLINT,col3 INT,col4 BIGINT,col5 BOOLEAN\\n\" +\n                        \",col6 FLOAT,col7 DOUBLE,col8 DOUBLE PRECISION,col9 STRING,col10 BINARY\\n\" +\n                        \",col11 TIMESTAMP,col12 DECIMAL,col13 DECIMAL(10,2),col13 DATE,col14 VARCHAR,col15 CHAR\\n\" +\n                        \",col16 ARRAY<STRING>,col17 MAP<STRING,INT>,col18 STRUCT<col19:STRING comment 'column19'>,col20 UNIONTYPE<STRING,INT>\\n\" +\n                        \") clustered by (PAR1,PAR2) INTO 32 BUCKETS\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE IF NOT EXISTS aliyun_cdm.test_903_table (\\n\" +\n                    \"\\tcol1 TINYINT,\\n\" +\n                    \"\\tcol2 SMALLINT,\\n\" +\n                    \"\\tcol3 INT,\\n\" +\n                    \"\\tcol4 BIGINT,\\n\" +\n                    \"\\tcol5 BOOLEAN,\\n\" +\n                    \"\\tcol6 FLOAT,\\n\" +\n                    \"\\tcol7 DOUBLE,\\n\" +\n                    \"\\tcol8 DOUBLE PRECISION,\\n\" +\n                    \"\\tcol9 STRING,\\n\" +\n                    \"\\tcol10 BINARY,\\n\" +\n                    \"\\tcol11 TIMESTAMP,\\n\" +\n                    \"\\tcol12 DECIMAL,\\n\" +\n                    \"\\tcol13 DECIMAL(10, 2),\\n\" +\n                    \"\\tcol13 DATE,\\n\" +\n                    \"\\tcol14 VARCHAR,\\n\" +\n                    \"\\tcol15 CHAR,\\n\" +\n                    \"\\tcol16 ARRAY<STRING>,\\n\" +\n                    \"\\tcol17 MAP<STRING, INT>,\\n\" +\n                    \"\\tcol18 STRUCT<col19:STRING>,\\n\" +\n                    \"\\tcol20 UNIONTYPE<STRING, INT>\\n\" +\n                    \")\\n\" +\n                    \"CLUSTERED BY (PAR1,PAR2)\\n\" +\n                    \"INTO 32 BUCKETS\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(19, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aliyun_cdm.test_903_table\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_22.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_22 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table if not exists aliyun_cdm.test_904_table  (\\n\" +\n                        \"col1 BIGINT,col2 STRING,col3 BOOLEAN,col4 DOUBLE,col5 DATETIME\" +\n                        \"\\n) skewed by (PAR1,PAR2) ON ((\\\"v1\\\",100),(\\\"v2\\\",200))\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE IF NOT EXISTS aliyun_cdm.test_904_table (\\n\" +\n                    \"\\tcol1 BIGINT,\\n\" +\n                    \"\\tcol2 STRING,\\n\" +\n                    \"\\tcol3 BOOLEAN,\\n\" +\n                    \"\\tcol4 DOUBLE,\\n\" +\n                    \"\\tcol5 DATETIME\\n\" +\n                    \")\\n\" +\n                    \"SKEWED BY (PAR1,PAR2) ON (('v1', 100),('v2', 200))\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aliyun_cdm.test_904_table\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_23_temporary.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_23_temporary extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create temporary table aliyun_cdm.test_893_table (col1 BIGINT,col2 STRING,col3 BOOLEAN,col4 DOUBLE,col5 DATETIME)\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TEMPORARY TABLE aliyun_cdm.test_893_table (\\n\" +\n                    \"\\tcol1 BIGINT,\\n\" +\n                    \"\\tcol2 STRING,\\n\" +\n                    \"\\tcol3 BOOLEAN,\\n\" +\n                    \"\\tcol4 DOUBLE,\\n\" +\n                    \"\\tcol5 DATETIME\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aliyun_cdm.test_893_table\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_24.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_24 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table aliyun_cdm.test_905_table \\n\" +\n                        \"(col1 BIGINT,col2 STRING,col3 BOOLEAN,col4 DOUBLE,col5 DATETIME) row format delimited fields terminated by \\\"\\\\\\\\001\\\"\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE aliyun_cdm.test_905_table (\\n\" +\n                    \"\\tcol1 BIGINT,\\n\" +\n                    \"\\tcol2 STRING,\\n\" +\n                    \"\\tcol3 BOOLEAN,\\n\" +\n                    \"\\tcol4 DOUBLE,\\n\" +\n                    \"\\tcol5 DATETIME\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT DELIMITED\\n\" +\n                    \"\\tFIELDS TERMINATED BY '\\\\\\\\001'\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aliyun_cdm.test_905_table\"));\n    }\n\n    public void test_1_error() throws Exception {\n        String sql = //\n                \"create table aliyun_cdm.test_905_table \\n\" +\n                        \"(col1 BIGINT,col2 STRING,col3 BOOLEAN,col4 DOUBLE,col5 DATETIME) row format delimited field terminated by \\\"\\\\\\\\001\\\"\\n\";\n\n        Exception error = null;\n        try {\n            SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        } catch (ParserException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertEquals(\"syntax error, expect FIELDS, pos 131, line 2, column 87, token IDENTIFIER field\", error.getMessage());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_25.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_25 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table aliyun_cdm.test_910_table(\\n\" +\n                        \"col1 BIGINT,col2 STRING,col3 BOOLEAN,col4 DOUBLE,col5 DATETIME,\\n\" +\n                        \"constraint c11 foreign key(col1,col2) references aliyun_cdm.test_910_table_f (col1,col2)  disable novalidate\\n\" +\n                        \")\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE aliyun_cdm.test_910_table (\\n\" +\n                    \"\\tcol1 BIGINT,\\n\" +\n                    \"\\tcol2 STRING,\\n\" +\n                    \"\\tcol3 BOOLEAN,\\n\" +\n                    \"\\tcol4 DOUBLE,\\n\" +\n                    \"\\tcol5 DATETIME,\\n\" +\n                    \"\\tCONSTRAINT c11 FOREIGN KEY (col1, col2)\\n\" +\n                    \"\\t\\tREFERENCES aliyun_cdm.test_910_table_f (col1, col2) DISABLE NOVALIDATE\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aliyun_cdm.test_910_table\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_26_struct.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_26_struct extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE IF NOT EXISTS test_910_table (col19 STRUCT < col20:STRING COMMENT 'column19' >)\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE IF NOT EXISTS test_910_table (\\n\" +\n                    \"\\tcol19 STRUCT<col20:STRING>\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"test_910_table\"));\n        assertTrue(visitor.containsColumn(\"test_910_table\", \"col19\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_27.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_27 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE EXTERNAL TABLE `customer_case.tradelist_csv`(\\n\" +\n                        \"  `t_userid` string COMMENT '??ID', \\n\" +\n                        \"  `t_dealdate` string COMMENT '????', \\n\" +\n                        \"  `t_businflag` string COMMENT '????', \\n\" +\n                        \"  `t_cdate` string COMMENT '????', \\n\" +\n                        \"  `t_date` string COMMENT '????', \\n\" +\n                        \"  `t_serialno` string COMMENT '????', \\n\" +\n                        \"  `t_agencyno` string COMMENT '?????', \\n\" +\n                        \"  `t_netno` string COMMENT '????', \\n\" +\n                        \"  `t_fundacco` string COMMENT '????', \\n\" +\n                        \"  `t_tradeacco` string COMMENT '????', \\n\" +\n                        \"  `t_fundcode` string COMMENT '????', \\n\" +\n                        \"  `t_sharetype` string COMMENT '????', \\n\" +\n                        \"  `t_confirmbalance` double COMMENT '????', \\n\" +\n                        \"  `t_tradefare` double COMMENT '???', \\n\" +\n                        \"  `t_backfare` double COMMENT '?????', \\n\" +\n                        \"  `t_otherfare1` double COMMENT '????1', \\n\" +\n                        \"  `t_remark` string COMMENT '??')\\n\" +\n                        \"ROW FORMAT DELIMITED \\n\" +\n                        \"  FIELDS TERMINATED BY ',' \\n\" +\n                        \"STORED AS INPUTFORMAT \\n\" +\n                        \"  'org.apache.hadoop.mapred.TextInputFormat' \\n\" +\n                        \"OUTPUTFORMAT \\n\" +\n                        \"  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\\n\" +\n                        \"LOCATION\\n\" +\n                        \"  'oss://acs:ram::1:role&role@oss-cn-hangzhou-for-openanalytics/datasets/basic/customer_20180526/trade'\\n\" +\n                        \"TBLPROPERTIES (\\n\" +\n                        \"  'COLUMN_STATS_ACCURATE'='false', \\n\" +\n                        \"  'numFiles'='1', \\n\" +\n                        \"  'numRows'='-1', \\n\" +\n                        \"  'rawDataSize'='-1', \\n\" +\n                        \"  'totalSize'='1870175', \\n\" +\n                        \"  'transient_lastDdlTime'='1527408051')\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE `customer_case.tradelist_csv` (\\n\" +\n                    \"\\t`t_userid` string COMMENT '??ID',\\n\" +\n                    \"\\t`t_dealdate` string COMMENT '????',\\n\" +\n                    \"\\t`t_businflag` string COMMENT '????',\\n\" +\n                    \"\\t`t_cdate` string COMMENT '????',\\n\" +\n                    \"\\t`t_date` string COMMENT '????',\\n\" +\n                    \"\\t`t_serialno` string COMMENT '????',\\n\" +\n                    \"\\t`t_agencyno` string COMMENT '?????',\\n\" +\n                    \"\\t`t_netno` string COMMENT '????',\\n\" +\n                    \"\\t`t_fundacco` string COMMENT '????',\\n\" +\n                    \"\\t`t_tradeacco` string COMMENT '????',\\n\" +\n                    \"\\t`t_fundcode` string COMMENT '????',\\n\" +\n                    \"\\t`t_sharetype` string COMMENT '????',\\n\" +\n                    \"\\t`t_confirmbalance` double COMMENT '????',\\n\" +\n                    \"\\t`t_tradefare` double COMMENT '???',\\n\" +\n                    \"\\t`t_backfare` double COMMENT '?????',\\n\" +\n                    \"\\t`t_otherfare1` double COMMENT '????1',\\n\" +\n                    \"\\t`t_remark` string COMMENT '??'\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT DELIMITED\\n\" +\n                    \"\\tFIELDS TERMINATED BY ','\\n\" +\n                    \"STORED AS\\n\" +\n                    \"\\tINPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'\\n\" +\n                    \"\\tOUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\\n\" +\n                    \"LOCATION 'oss://acs:ram::1:role&role@oss-cn-hangzhou-for-openanalytics/datasets/basic/customer_20180526/trade'\\n\" +\n                    \"TBLPROPERTIES (\\n\" +\n                    \"\\t'COLUMN_STATS_ACCURATE' = 'false',\\n\" +\n                    \"\\t'numFiles' = '1',\\n\" +\n                    \"\\t'numRows' = '-1',\\n\" +\n                    \"\\t'rawDataSize' = '-1',\\n\" +\n                    \"\\t'totalSize' = '1870175',\\n\" +\n                    \"\\t'transient_lastDdlTime' = '1527408051'\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(17, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"customer_case.tradelist_csv\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_28_struct.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_28_struct extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE EXTERNAL TABLE `json_table_1`(\\n\" +\n                        \"  `docid` string COMMENT 'from deserializer', \\n\" +\n                        \"  `user_1` struct<id:int,username:string,name:string,shippingaddress:struct<address1:string,address2:string,city:string,state:string>,orders:array<struct<itemid:int,orderdate:string>>> COMMENT 'from deserializer')\\n\" +\n                        \"ROW FORMAT SERDE \\n\" +\n                        \"  'org.apache.hive.hcatalog.data.JsonSerDe' \\n\" +\n                        \"STORED AS INPUTFORMAT \\n\" +\n                        \"  'org.apache.hadoop.mapred.TextInputFormat' \\n\" +\n                        \"OUTPUTFORMAT \\n\" +\n                        \"  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\\n\" +\n                        \"LOCATION\\n\" +\n                        \"  'oss://acs:ram::1013022312866336:role&aliyunopenanalyticsaccessingossrole@oss-cn-beijing-for-openanalytics-test/datasets/test/json/hcatalog_serde/table_1'\\n\" +\n                        \"TBLPROPERTIES (\\n\" +\n                        \"  'COLUMN_STATS_ACCURATE'='false', \\n\" +\n                        \"  'numFiles'='1', \\n\" +\n                        \"  'numRows'='-1', \\n\" +\n                        \"  'rawDataSize'='-1', \\n\" +\n                        \"  'totalSize'='347', \\n\" +\n                        \"  'transient_lastDdlTime'='1530879306')\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE `json_table_1` (\\n\" +\n                    \"\\t`docid` string COMMENT 'from deserializer',\\n\" +\n                    \"\\t`user_1` STRUCT<\\n\" +\n                    \"\\t\\tid:int,\\n\" +\n                    \"\\t\\tusername:string,\\n\" +\n                    \"\\t\\tname:string,\\n\" +\n                    \"\\t\\tshippingaddress:STRUCT<address1:string, address2:string, city:string, state:string>,\\n\" +\n                    \"\\t\\torders:ARRAY<STRUCT<itemid:int, orderdate:string>>\\n\" +\n                    \"\\t> COMMENT 'from deserializer'\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT\\n\" +\n                    \"\\tSERDE 'org.apache.hive.hcatalog.data.JsonSerDe'\\n\" +\n                    \"STORED AS\\n\" +\n                    \"\\tINPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'\\n\" +\n                    \"\\tOUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\\n\" +\n                    \"LOCATION 'oss://acs:ram::1013022312866336:role&aliyunopenanalyticsaccessingossrole@oss-cn-beijing-for-openanalytics-test/datasets/test/json/hcatalog_serde/table_1'\\n\" +\n                    \"TBLPROPERTIES (\\n\" +\n                    \"\\t'COLUMN_STATS_ACCURATE' = 'false',\\n\" +\n                    \"\\t'numFiles' = '1',\\n\" +\n                    \"\\t'numRows' = '-1',\\n\" +\n                    \"\\t'rawDataSize' = '-1',\\n\" +\n                    \"\\t'totalSize' = '347',\\n\" +\n                    \"\\t'transient_lastDdlTime' = '1530879306'\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"json_table_1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_29.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_29 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE dataphin_test (id STRING, name STRING) \\n\" +\n                        \"ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' \\n\" +\n                        \"LINES TERMINATED BY '\\\\n' STORED AS PARQUET;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE dataphin_test (\\n\" +\n                    \"\\tid STRING,\\n\" +\n                    \"\\tname STRING\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT DELIMITED\\n\" +\n                    \"\\tFIELDS TERMINATED BY ','\\n\" +\n                    \"\\tLINES TERMINATED BY '\\\\n'\\n\" +\n                    \"STORED AS PARQUET;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"dataphin_test\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_3 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE pub_ae_sess_type_dimt0_text\\n\" +\n                        \"(        \\n\" +\n                        \"        SESSION_TYPE_ID         BIGINT          COMMENT '会话类型',\\n\" +\n                        \"        DW_INS_DATE             STRING          COMMENT '数据仓库插入时间' \\n\" +\n                        \")\\n\" +\n                        \"COMMENT 'session来源类型维表'\\n\" +\n                        \"PARTITIONED BY(date STRING COMMENT '日期', pos STRING COMMENT '位置')\\n\" +\n                        \"ROW FORMAT DELIMITED FIELDS TERMINATED BY ','\\n\" +\n                        \"STORED AS SEQUENCEFILE\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE pub_ae_sess_type_dimt0_text (\\n\" +\n                    \"\\tSESSION_TYPE_ID BIGINT COMMENT '会话类型',\\n\" +\n                    \"\\tDW_INS_DATE STRING COMMENT '数据仓库插入时间'\\n\" +\n                    \")\\n\" +\n                    \"COMMENT 'session来源类型维表'\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tdate STRING COMMENT '日期',\\n\" +\n                    \"\\tpos STRING COMMENT '位置'\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT DELIMITED\\n\" +\n                    \"\\tFIELDS TERMINATED BY ','\\n\" +\n                    \"STORED AS SEQUENCEFILE\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"pub_ae_sess_type_dimt0_text\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_30.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_30 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE EXTERNAL TABLE `nation`(\\n\" +\n                        \"  `n_nationkey` int,\\n\" +\n                        \"  `n_name` string,\\n\" +\n                        \"  `n_regionkey` int,\\n\" +\n                        \"  `n_comment` string)\\n\" +\n                        \"ROW FORMAT SERDE\\n\" +\n                        \"  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'\\n\" +\n                        \"WITH SERDEPROPERTIES (\\n\" +\n                        \"  'field.delim'='|',\\n\" +\n                        \"  'serialization.format'='|')\\n\" +\n                        \"STORED AS INPUTFORMAT\\n\" +\n                        \"  'org.apache.hadoop.mapred.TextInputFormat'\\n\" +\n                        \"OUTPUTFORMAT\\n\" +\n                        \"  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\\n\" +\n                        \"LOCATION\\n\" +\n                        \"  'oss://test-bucket-julian-1/tpch_100m/nation'\\n\" +\n                        \"TBLPROPERTIES (\\n\" +\n                        \"  'COLUMN_STATS_ACCURATE'='false',\\n\" +\n                        \"  'numFiles'='1',\\n\" +\n                        \"  'numRows'='-1',\\n\" +\n                        \"  'rawDataSize'='-1',\\n\" +\n                        \"  'totalSize'='2224',\\n\" +\n                        \"  'transient_lastDdlTime'='1528440011')\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE `nation` (\\n\" +\n                    \"\\t`n_nationkey` int,\\n\" +\n                    \"\\t`n_name` string,\\n\" +\n                    \"\\t`n_regionkey` int,\\n\" +\n                    \"\\t`n_comment` string\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT\\n\" +\n                    \"\\tSERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'\\n\" +\n                    \"WITH SERDEPROPERTIES (\\n\" +\n                    \"\\t'field.delim' = '|',\\n\" +\n                    \"\\t'serialization.format' = '|'\\n\" +\n                    \")\\n\" +\n                    \"STORED AS\\n\" +\n                    \"\\tINPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'\\n\" +\n                    \"\\tOUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'\\n\" +\n                    \"LOCATION 'oss://test-bucket-julian-1/tpch_100m/nation'\\n\" +\n                    \"TBLPROPERTIES (\\n\" +\n                    \"\\t'COLUMN_STATS_ACCURATE' = 'false',\\n\" +\n                    \"\\t'numFiles' = '1',\\n\" +\n                    \"\\t'numRows' = '-1',\\n\" +\n                    \"\\t'rawDataSize' = '-1',\\n\" +\n                    \"\\t'totalSize' = '2224',\\n\" +\n                    \"\\t'transient_lastDdlTime' = '1528440011'\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"nation\"));\n    }\n\n    public void test_1() throws Exception {\n        String sql = //\n                \"CREATE EXTERNAL TABLE nation_test \"\n                        + \"(  n_nationkey INT NOT NULL COMMENT 'xxx', \"\n                        + \"n_name STRING NULL COMMENT 'yyy', \"\n                        + \"n_regionkey INT NULL COMMENT 'zzz', \"\n                        + \"n_comment STRING NULL COMMENT 'hhh',  \"\n                        + \"PRIMARY KEY (n_nationkey)) \"\n                        + \"TBLPROPERTIES ( TABLE_MAPPING = 'nation', COLUMN_MAPPING = 'n_nationkey,N_NATIONKEY; n_name,N_NAME;n_regionkey,N_REGIONKEY; n_comment,N_COMMENT; ' ) \"\n                        + \"COMMENT '萌豆'\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE nation_test (\\n\" + \"\\tn_nationkey INT NOT NULL COMMENT 'xxx',\\n\"\n                    + \"\\tn_name STRING NULL COMMENT 'yyy',\\n\" + \"\\tn_regionkey INT NULL COMMENT 'zzz',\\n\"\n                    + \"\\tn_comment STRING NULL COMMENT 'hhh',\\n\" + \"\\tPRIMARY KEY (n_nationkey)\\n\" + \")\\n\"\n                    + \"COMMENT '萌豆'\\n\" + \"TBLPROPERTIES (\\n\" + \"\\t'TABLE_MAPPING' = 'nation',\\n\"\n                    + \"\\t'COLUMN_MAPPING' = 'n_nationkey,N_NATIONKEY; n_name,N_NAME;n_regionkey,N_REGIONKEY; n_comment,N_COMMENT; '\\n\"\n                    + \")\", text);\n        }\n\n    }\n\n    public void test_2() throws Exception {\n        String sql = //\n                \"CREATE EXTERNAL TABLE `tpch_100m_text`.`nation_line_terminated` (\\n\"\n                        + \"  `n_nationkey` int,\\n\"\n                        + \"  `n_name` string,\\n\"\n                        + \"  `n_regionkey` int,\\n\"\n                        + \"  `n_comment` string\\n\"\n                        + \")\\n\"\n                        + \"ROW FORMAT DELIMITED\\n\"\n                        + \"  FIELDS TERMINATED BY '|'  \\n\"\n                        + \"    ESCAPED BY '\\\\\\\\' \\n\"\n                        + \"    LINES TERMINATED BY ';' \\n\"\n                        + \"STORED AS `TEXTFILE`\\n\"\n                        + \"LOCATION 'oss://oss-cn-beijing-for-openanalytics/datasets/tpch/0_1x/text/nation_line_terminated/'\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE `tpch_100m_text`.`nation_line_terminated` (\\n\"\n                    + \"\\t`n_nationkey` int,\\n\" + \"\\t`n_name` string,\\n\" + \"\\t`n_regionkey` int,\\n\"\n                    + \"\\t`n_comment` string\\n\" + \")\\n\" + \"ROW FORMAT DELIMITED\\n\" + \"\\tFIELDS TERMINATED BY '|'\\n\"\n                    + \"\\tESCAPED BY '\\\\\\\\'\\n\" + \"\\tLINES TERMINATED BY ';'\\n\" + \"STORED AS `TEXTFILE`\\n\"\n                    + \"LOCATION 'oss://oss-cn-beijing-for-openanalytics/datasets/tpch/0_1x/text/nation_line_terminated/'\", text);\n        }\n\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"-- 234234\\ncreate table a(id varchar)\";\n\n        SQLStatement statement = SQLUtils.parseSingleStatement(sql, DbType.hive, SQLParserFeature.KeepComments);\n        assertEquals(\"-- 234234\\n\" + \"CREATE TABLE a (\\n\" + \"\\tid varchar\\n\" + \")\",\n                SQLUtils.toSQLString(statement, JdbcConstants.HIVE));\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"alter table partition_text_nation add partition (p=101,q) location 'oss://oss-cn-beijing-for-openanalytics-test/datasets/test/test_partition/text_table/part101/';\";\n\n        SQLStatement statement = SQLUtils.parseSingleStatement(sql, DbType.hive, SQLParserFeature.KeepComments);\n        assertEquals(\"ALTER TABLE partition_text_nation\\n\"\n                        + \"\\tADD PARTITION (p = 101, q) LOCATION 'oss://oss-cn-beijing-for-openanalytics-test/datasets/test/test_partition/text_table/part101/';\",\n                SQLUtils.toSQLString(statement, JdbcConstants.HIVE));\n    }\n\n    public void test_5() throws Exception {\n        String sql = \"alter table partition_text_nation add partition (p, q=101) location 'oss://oss-cn-beijing-for-openanalytics-test/datasets/test/test_partition/text_table/part101/';\";\n\n        SQLStatement statement = SQLUtils.parseSingleStatement(sql, DbType.hive, SQLParserFeature.KeepComments);\n        assertEquals(\"ALTER TABLE partition_text_nation\\n\"\n                        + \"\\tADD PARTITION (p, q = 101) LOCATION 'oss://oss-cn-beijing-for-openanalytics-test/datasets/test/test_partition/text_table/part101/';\",\n                SQLUtils.toSQLString(statement, JdbcConstants.HIVE));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_31_mappedBy_for_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_31_mappedBy_for_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table aaaa (\\n\" +\n                        \"  id int not null MAPPED BY (name='pk',format='yyy',charset='utf8',type='string'）\\n\" +\n                        \") MAPPED by (name='AAAA')\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE TABLE aaaa (\\n\" +\n                \"\\tid int NOT NULL MAPPED BY (name = 'pk', format = 'yyy', charset = 'utf8', type = 'string')\\n\" +\n                \")\" +\n                \" MAPPED BY (name = 'AAAA')\", stmt.toString());\n\n        assertEquals(\"CREATE TABLE aaaa (\\n\" +\n                \"\\tid int NOT NULL MAPPED BY (name = 'pk', format = 'yyy', charset = 'utf8', type = 'string')\\n\" +\n                \")\" +\n                \" MAPPED BY (name = 'AAAA')\", stmt.clone().toString());\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aaaa\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_32_properties.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_32_properties extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table aaaa (\\n\" +\n                        \"  id int not null COLPROPERTIES (name='pk',format='yyy',charset='utf8',type='string'）\\n\" +\n                        \") MAPPED by (name='AAAA')\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE TABLE aaaa (\\n\" +\n                \"\\tid int NOT NULL COLPROPERTIES (name = 'pk', format = 'yyy', charset = 'utf8', type = 'string')\\n\" +\n                \") \" +\n                \"MAPPED BY (name = 'AAAA')\", stmt.toString());\n\n        assertEquals(\"CREATE TABLE aaaa (\\n\" +\n                \"\\tid int NOT NULL COLPROPERTIES (name = 'pk', format = 'yyy', charset = 'utf8', type = 'string')\\n\" +\n                \") \" +\n                \"MAPPED BY (name = 'AAAA')\", stmt.clone().toString());\n\n        assertEquals(\"create table aaaa (\\n\" +\n                \"\\tid int not null colproperties (name = 'pk', format = 'yyy', charset = 'utf8', type = 'string')\\n\" +\n                \") \" +\n                \"mapped by (name = 'AAAA')\", stmt.toLowerCaseString());\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aaaa\"));\n    }\n\n    public void test_mysql() throws Exception {\n        String sql = //\n                \"create table aaaa (\\n\" +\n                        \"  id int not null COLPROPERTIES (name='pk',format='yyy',charset='utf8',type='string'）\\n\" +\n                        \")\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE TABLE aaaa (\\n\" +\n                \"\\tid int NOT NULL COLPROPERTIES (name = 'pk', format = 'yyy', CHARACTER SET 'utf8', type = 'string')\\n\" +\n                \")\", stmt.toString());\n\n        assertEquals(\"CREATE TABLE aaaa (\\n\" +\n                \"\\tid int NOT NULL COLPROPERTIES (name = 'pk', format = 'yyy', CHARACTER SET 'utf8', type = 'string')\\n\" +\n                \")\", stmt.clone().toString());\n\n        assertEquals(\"create table aaaa (\\n\" +\n                \"\\tid int not null colproperties (name = 'pk', format = 'yyy', character set 'utf8', type = 'string')\\n\" +\n                \")\", stmt.toLowerCaseString());\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"aaaa\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_33_struct.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_33_struct extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE EXTERNAL TABLE user_snp_test_4 (\\n\" +\n                        \"variant struct<\\n\" +\n                        \"  contigName:string,\\n\" +\n                        \"  start:bigint,\\n\" +\n                        \"  end:bigint,\\n\" +\n                        \"  names:array<string>,\\n\" +\n                        \"  splitFromMultiAllelic:boolean,\\n\" +\n                        \"  referenceAllele:string,\\n\" +\n                        \"  alternateAllele:string,\\n\" +\n                        \"  quality:double,\\n\" +\n                        \"  filtersApplied:boolean,\\n\" +\n                        \"  filtersPassed:boolean,\\n\" +\n                        \"  filtersFailed:array<string>,\\n\" +\n                        \"  annotation:struct<\\n\" +\n                        \"        ancestralAllele:string,\\n\" +\n                        \"        alleleCount:int,\\n\" +\n                        \"        readDepth:int,\\n\" +\n                        \"        forwardReadDepth:int,\\n\" +\n                        \"        reverseReadDepth:int,\\n\" +\n                        \"        referenceReadDepth:int,\\n\" +\n                        \"        referenceForwardReadDepth:int,\\n\" +\n                        \"        referenceReverseReadDepth:int,\\n\" +\n                        \"        alleleFrequency:float,\\n\" +\n                        \"        cigar:string,\\n\" +\n                        \"        dbSnp:boolean,\\n\" +\n                        \"        hapMap2:boolean,\\n\" +\n                        \"        hapMap3:boolean,\\n\" +\n                        \"        validated:boolean,\\n\" +\n                        \"        thousandGenomes:boolean,\\n\" +\n                        \"        somatic:boolean,\\n\" +\n                        \"        transcriptEffects:array<struct<\\n\" +\n                        \"            alternateAllele:string,\\n\" +\n                        \"            effects:array<string>,\\n\" +\n                        \"            geneName:string,\\n\" +\n                        \"            geneId:string,\\n\" +\n                        \"            featureType:string,\\n\" +\n                        \"            featureId:string,\\n\" +\n                        \"            biotype:string,\\n\" +\n                        \"            rank:int,\\n\" +\n                        \"            total:int,\\n\" +\n                        \"            genomicHgvs:string,\\n\" +\n                        \"            transcriptHgvs:string,\\n\" +\n                        \"            proteinHgvs:string,\\n\" +\n                        \"            cdnaPosition:int,\\n\" +\n                        \"            cdnaLength:int,\\n\" +\n                        \"            cdsPosition:int,\\n\" +\n                        \"            cdsLength:int,\\n\" +\n                        \"            proteinPosition:int,\\n\" +\n                        \"            proteinLength:int,\\n\" +\n                        \"            distance:int,\\n\" +\n                        \"            messages:array<string>\\n\" +\n                        \"        >>,\\n\" +\n                        \"        attributes:map<string,string>\\n\" +\n                        \"    >\\n\" +\n                        \">, \\n\" +\n                        \"    contigName string, \\n\" +\n                        \"    start bigint, \\n\" +\n                        \"    end bigint, \\n\" +\n                        \"    variantCallingAnnotations struct<filtersApplied:boolean,filtersPassed:boolean,filtersFailed:array<string>,downsampled:boolean,baseQRankSum:float,fisherStrandBiasPValue:float,rmsMapQ:float,mapq0Reads:int,mqRankSum:float,readPositionRankSum:float,genotypePriors:array<float>,genotypePosteriors:array<float>,vqslod:float,culprit:string,attributes:map<string,string>>, \\n\" +\n                        \"    sampleId string, \\n\" +\n                        \"    sampleDescription string, \\n\" +\n                        \"    processingDescription string, \\n\" +\n                        \"    alleles array<string>, \\n\" +\n                        \"    expectedAlleleDosage float, \\n\" +\n                        \"    referenceReadDepth int, \\n\" +\n                        \"    alternateReadDepth int, \\n\" +\n                        \"    readDepth int, \\n\" +\n                        \"    minReadDepth int, \\n\" +\n                        \"    genotypeQuality int, \\n\" +\n                        \"    genotypeLikelihoods array<double>, \\n\" +\n                        \"    nonReferenceLikelihoods array<double>, \\n\" +\n                        \"    strandBiasComponents array<int>, \\n\" +\n                        \"    splitFromMultiAllelic boolean, \\n\" +\n                        \"    phased boolean, \\n\" +\n                        \"    phaseSetId int, \\n\" +\n                        \"    phaseQuality int\\n\" +\n                        \"    ) \\n\" +\n                        \"STORED AS PARQUET \\n\" +\n                        \"LOCATION 'oss://wegene-genomics-api-test/parquet_data/WGSDANAL098612/';\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE user_snp_test_4 (\\n\" +\n                    \"\\tvariant STRUCT<\\n\" +\n                    \"\\t\\tcontigName:string,\\n\" +\n                    \"\\t\\tstart:bigint,\\n\" +\n                    \"\\t\\tend:bigint,\\n\" +\n                    \"\\t\\tnames:ARRAY<string>,\\n\" +\n                    \"\\t\\tsplitFromMultiAllelic:boolean,\\n\" +\n                    \"\\t\\treferenceAllele:string,\\n\" +\n                    \"\\t\\talternateAllele:string,\\n\" +\n                    \"\\t\\tquality:double,\\n\" +\n                    \"\\t\\tfiltersApplied:boolean,\\n\" +\n                    \"\\t\\tfiltersPassed:boolean,\\n\" +\n                    \"\\t\\tfiltersFailed:ARRAY<string>,\\n\" +\n                    \"\\t\\tannotation:STRUCT<\\n\" +\n                    \"\\t\\t\\tancestralAllele:string,\\n\" +\n                    \"\\t\\t\\talleleCount:int,\\n\" +\n                    \"\\t\\t\\treadDepth:int,\\n\" +\n                    \"\\t\\t\\tforwardReadDepth:int,\\n\" +\n                    \"\\t\\t\\treverseReadDepth:int,\\n\" +\n                    \"\\t\\t\\treferenceReadDepth:int,\\n\" +\n                    \"\\t\\t\\treferenceForwardReadDepth:int,\\n\" +\n                    \"\\t\\t\\treferenceReverseReadDepth:int,\\n\" +\n                    \"\\t\\t\\talleleFrequency:float,\\n\" +\n                    \"\\t\\t\\tcigar:string,\\n\" +\n                    \"\\t\\t\\tdbSnp:boolean,\\n\" +\n                    \"\\t\\t\\thapMap2:boolean,\\n\" +\n                    \"\\t\\t\\thapMap3:boolean,\\n\" +\n                    \"\\t\\t\\tvalidated:boolean,\\n\" +\n                    \"\\t\\t\\tthousandGenomes:boolean,\\n\" +\n                    \"\\t\\t\\tsomatic:boolean,\\n\" +\n                    \"\\t\\t\\ttranscriptEffects:ARRAY<STRUCT<\\n\" +\n                    \"\\t\\t\\t\\talternateAllele:string,\\n\" +\n                    \"\\t\\t\\t\\teffects:ARRAY<string>,\\n\" +\n                    \"\\t\\t\\t\\tgeneName:string,\\n\" +\n                    \"\\t\\t\\t\\tgeneId:string,\\n\" +\n                    \"\\t\\t\\t\\tfeatureType:string,\\n\" +\n                    \"\\t\\t\\t\\tfeatureId:string,\\n\" +\n                    \"\\t\\t\\t\\tbiotype:string,\\n\" +\n                    \"\\t\\t\\t\\trank:int,\\n\" +\n                    \"\\t\\t\\t\\ttotal:int,\\n\" +\n                    \"\\t\\t\\t\\tgenomicHgvs:string,\\n\" +\n                    \"\\t\\t\\t\\ttranscriptHgvs:string,\\n\" +\n                    \"\\t\\t\\t\\tproteinHgvs:string,\\n\" +\n                    \"\\t\\t\\t\\tcdnaPosition:int,\\n\" +\n                    \"\\t\\t\\t\\tcdnaLength:int,\\n\" +\n                    \"\\t\\t\\t\\tcdsPosition:int,\\n\" +\n                    \"\\t\\t\\t\\tcdsLength:int,\\n\" +\n                    \"\\t\\t\\t\\tproteinPosition:int,\\n\" +\n                    \"\\t\\t\\t\\tproteinLength:int,\\n\" +\n                    \"\\t\\t\\t\\tdistance:int,\\n\" +\n                    \"\\t\\t\\t\\tmessages:ARRAY<string>\\n\" +\n                    \"\\t\\t\\t>>,\\n\" +\n                    \"\\t\\t\\tattributes:MAP<string, string>\\n\" +\n                    \"\\t\\t>\\n\" +\n                    \"\\t>,\\n\" +\n                    \"\\tcontigName string,\\n\" +\n                    \"\\tstart bigint,\\n\" +\n                    \"\\tend bigint,\\n\" +\n                    \"\\tvariantCallingAnnotations STRUCT<\\n\" +\n                    \"\\t\\tfiltersApplied:boolean,\\n\" +\n                    \"\\t\\tfiltersPassed:boolean,\\n\" +\n                    \"\\t\\tfiltersFailed:ARRAY<string>,\\n\" +\n                    \"\\t\\tdownsampled:boolean,\\n\" +\n                    \"\\t\\tbaseQRankSum:float,\\n\" +\n                    \"\\t\\tfisherStrandBiasPValue:float,\\n\" +\n                    \"\\t\\trmsMapQ:float,\\n\" +\n                    \"\\t\\tmapq0Reads:int,\\n\" +\n                    \"\\t\\tmqRankSum:float,\\n\" +\n                    \"\\t\\treadPositionRankSum:float,\\n\" +\n                    \"\\t\\tgenotypePriors:ARRAY<float>,\\n\" +\n                    \"\\t\\tgenotypePosteriors:ARRAY<float>,\\n\" +\n                    \"\\t\\tvqslod:float,\\n\" +\n                    \"\\t\\tculprit:string,\\n\" +\n                    \"\\t\\tattributes:MAP<string, string>\\n\" +\n                    \"\\t>,\\n\" +\n                    \"\\tsampleId string,\\n\" +\n                    \"\\tsampleDescription string,\\n\" +\n                    \"\\tprocessingDescription string,\\n\" +\n                    \"\\talleles ARRAY<string>,\\n\" +\n                    \"\\texpectedAlleleDosage float,\\n\" +\n                    \"\\treferenceReadDepth int,\\n\" +\n                    \"\\talternateReadDepth int,\\n\" +\n                    \"\\treadDepth int,\\n\" +\n                    \"\\tminReadDepth int,\\n\" +\n                    \"\\tgenotypeQuality int,\\n\" +\n                    \"\\tgenotypeLikelihoods ARRAY<double>,\\n\" +\n                    \"\\tnonReferenceLikelihoods ARRAY<double>,\\n\" +\n                    \"\\tstrandBiasComponents ARRAY<int>,\\n\" +\n                    \"\\tsplitFromMultiAllelic boolean,\\n\" +\n                    \"\\tphased boolean,\\n\" +\n                    \"\\tphaseSetId int,\\n\" +\n                    \"\\tphaseQuality int\\n\" +\n                    \")\\n\" +\n                    \"STORED AS PARQUET\\n\" +\n                    \"LOCATION 'oss://wegene-genomics-api-test/parquet_data/WGSDANAL098612/';\", text);\n        }\n        {\n            String text = SQLUtils.toSQLString(stmt.clone(), JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE user_snp_test_4 (\\n\" +\n                    \"\\tvariant STRUCT<\\n\" +\n                    \"\\t\\tcontigName:string,\\n\" +\n                    \"\\t\\tstart:bigint,\\n\" +\n                    \"\\t\\tend:bigint,\\n\" +\n                    \"\\t\\tnames:ARRAY<string>,\\n\" +\n                    \"\\t\\tsplitFromMultiAllelic:boolean,\\n\" +\n                    \"\\t\\treferenceAllele:string,\\n\" +\n                    \"\\t\\talternateAllele:string,\\n\" +\n                    \"\\t\\tquality:double,\\n\" +\n                    \"\\t\\tfiltersApplied:boolean,\\n\" +\n                    \"\\t\\tfiltersPassed:boolean,\\n\" +\n                    \"\\t\\tfiltersFailed:ARRAY<string>,\\n\" +\n                    \"\\t\\tannotation:STRUCT<\\n\" +\n                    \"\\t\\t\\tancestralAllele:string,\\n\" +\n                    \"\\t\\t\\talleleCount:int,\\n\" +\n                    \"\\t\\t\\treadDepth:int,\\n\" +\n                    \"\\t\\t\\tforwardReadDepth:int,\\n\" +\n                    \"\\t\\t\\treverseReadDepth:int,\\n\" +\n                    \"\\t\\t\\treferenceReadDepth:int,\\n\" +\n                    \"\\t\\t\\treferenceForwardReadDepth:int,\\n\" +\n                    \"\\t\\t\\treferenceReverseReadDepth:int,\\n\" +\n                    \"\\t\\t\\talleleFrequency:float,\\n\" +\n                    \"\\t\\t\\tcigar:string,\\n\" +\n                    \"\\t\\t\\tdbSnp:boolean,\\n\" +\n                    \"\\t\\t\\thapMap2:boolean,\\n\" +\n                    \"\\t\\t\\thapMap3:boolean,\\n\" +\n                    \"\\t\\t\\tvalidated:boolean,\\n\" +\n                    \"\\t\\t\\tthousandGenomes:boolean,\\n\" +\n                    \"\\t\\t\\tsomatic:boolean,\\n\" +\n                    \"\\t\\t\\ttranscriptEffects:ARRAY<STRUCT<\\n\" +\n                    \"\\t\\t\\t\\talternateAllele:string,\\n\" +\n                    \"\\t\\t\\t\\teffects:ARRAY<string>,\\n\" +\n                    \"\\t\\t\\t\\tgeneName:string,\\n\" +\n                    \"\\t\\t\\t\\tgeneId:string,\\n\" +\n                    \"\\t\\t\\t\\tfeatureType:string,\\n\" +\n                    \"\\t\\t\\t\\tfeatureId:string,\\n\" +\n                    \"\\t\\t\\t\\tbiotype:string,\\n\" +\n                    \"\\t\\t\\t\\trank:int,\\n\" +\n                    \"\\t\\t\\t\\ttotal:int,\\n\" +\n                    \"\\t\\t\\t\\tgenomicHgvs:string,\\n\" +\n                    \"\\t\\t\\t\\ttranscriptHgvs:string,\\n\" +\n                    \"\\t\\t\\t\\tproteinHgvs:string,\\n\" +\n                    \"\\t\\t\\t\\tcdnaPosition:int,\\n\" +\n                    \"\\t\\t\\t\\tcdnaLength:int,\\n\" +\n                    \"\\t\\t\\t\\tcdsPosition:int,\\n\" +\n                    \"\\t\\t\\t\\tcdsLength:int,\\n\" +\n                    \"\\t\\t\\t\\tproteinPosition:int,\\n\" +\n                    \"\\t\\t\\t\\tproteinLength:int,\\n\" +\n                    \"\\t\\t\\t\\tdistance:int,\\n\" +\n                    \"\\t\\t\\t\\tmessages:ARRAY<string>\\n\" +\n                    \"\\t\\t\\t>>,\\n\" +\n                    \"\\t\\t\\tattributes:MAP<string, string>\\n\" +\n                    \"\\t\\t>\\n\" +\n                    \"\\t>,\\n\" +\n                    \"\\tcontigName string,\\n\" +\n                    \"\\tstart bigint,\\n\" +\n                    \"\\tend bigint,\\n\" +\n                    \"\\tvariantCallingAnnotations STRUCT<\\n\" +\n                    \"\\t\\tfiltersApplied:boolean,\\n\" +\n                    \"\\t\\tfiltersPassed:boolean,\\n\" +\n                    \"\\t\\tfiltersFailed:ARRAY<string>,\\n\" +\n                    \"\\t\\tdownsampled:boolean,\\n\" +\n                    \"\\t\\tbaseQRankSum:float,\\n\" +\n                    \"\\t\\tfisherStrandBiasPValue:float,\\n\" +\n                    \"\\t\\trmsMapQ:float,\\n\" +\n                    \"\\t\\tmapq0Reads:int,\\n\" +\n                    \"\\t\\tmqRankSum:float,\\n\" +\n                    \"\\t\\treadPositionRankSum:float,\\n\" +\n                    \"\\t\\tgenotypePriors:ARRAY<float>,\\n\" +\n                    \"\\t\\tgenotypePosteriors:ARRAY<float>,\\n\" +\n                    \"\\t\\tvqslod:float,\\n\" +\n                    \"\\t\\tculprit:string,\\n\" +\n                    \"\\t\\tattributes:MAP<string, string>\\n\" +\n                    \"\\t>,\\n\" +\n                    \"\\tsampleId string,\\n\" +\n                    \"\\tsampleDescription string,\\n\" +\n                    \"\\tprocessingDescription string,\\n\" +\n                    \"\\talleles ARRAY<string>,\\n\" +\n                    \"\\texpectedAlleleDosage float,\\n\" +\n                    \"\\treferenceReadDepth int,\\n\" +\n                    \"\\talternateReadDepth int,\\n\" +\n                    \"\\treadDepth int,\\n\" +\n                    \"\\tminReadDepth int,\\n\" +\n                    \"\\tgenotypeQuality int,\\n\" +\n                    \"\\tgenotypeLikelihoods ARRAY<double>,\\n\" +\n                    \"\\tnonReferenceLikelihoods ARRAY<double>,\\n\" +\n                    \"\\tstrandBiasComponents ARRAY<int>,\\n\" +\n                    \"\\tsplitFromMultiAllelic boolean,\\n\" +\n                    \"\\tphased boolean,\\n\" +\n                    \"\\tphaseSetId int,\\n\" +\n                    \"\\tphaseQuality int\\n\" +\n                    \")\\n\" +\n                    \"STORED AS PARQUET\\n\" +\n                    \"LOCATION 'oss://wegene-genomics-api-test/parquet_data/WGSDANAL098612/';\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(22, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"user_snp_test_4\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_34.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_34 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"-- abc\\n\" +\n                \"CREATE DATABASE `ddl_json_string` WITH DBPROPERTIES (LOCATION = 'oss://oss-cn-hangzhou-for-openanalytics/datasets/tpch/1x/json_string/', catalog = 'oss');\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"-- abc\\n\" +\n                    \"CREATE DATABASE `ddl_json_string`\\n\" +\n                    \"WITH DBPROPERTIES (\\n\" +\n                    \"\\tLOCATION = 'oss://oss-cn-hangzhou-for-openanalytics/datasets/tpch/1x/json_string/',\\n\" +\n                    \"\\tcatalog = 'oss'\\n\" +\n                    \");\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n//        assertTrue(visitor.containsTable(\"customer_case.tradelist_csv\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_35_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_35_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"create table dla_table1 like dla_table2;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE dla_table1\\n\" +\n                    \"LIKE dla_table2;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n//        assertTrue(visitor.containsTable(\"customer_case.tradelist_csv\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_36_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_36_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"create table dla_table1 like dla_table2 tblproperties (\\n\" +\n                \"\\n\" +\n                \"    column_mapping = 'hello,world;james,bond;'\\n\" +\n                \"\\n\" +\n                \");\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE dla_table1\\n\" +\n                    \"LIKE dla_table2\\n\" +\n                    \"TBLPROPERTIES (\\n\" +\n                    \"\\t'column_mapping' = 'hello,world;james,bond;'\\n\" +\n                    \");\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n//        assertTrue(visitor.containsTable(\"customer_case.tradelist_csv\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_37_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_37_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"create table dla_table1 like mapping('mysql_table1');\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE dla_table1\\n\" +\n                    \"LIKE mapping('mysql_table1');\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n//        assertTrue(visitor.containsTable(\"customer_case.tradelist_csv\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_38_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_38_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"-- {\\\"n_nationkey\\\":0,\\\"n_name\\\":\\\"ALGERIA\\\",\\\"n_regionkey\\\":0,\\\"n_comment\\\":\\\" haggle. carefully final deposits detect slyly agai\\\"}\\n\\nCREATE SCHEMA ddl_json_string with DBPROPERTIES(LOCATION = 'oss://oss-cn-hangzhou-for-openanalytics/datasets/tpch/1x/json_string/' ,catalog = 'oss');\\nCREATE EXTERNAL TABLE ddl_json_string.nation_json(n_comment string, n_name string, n_nationkey int, n_regionkey int, ) STORED AS JSON LOCATION 'oss://oss-cn-hangzhou-for-openanalytics/datasets/tpch/1x/json_string/nation_json/' TBLPROPERTIES ( \\n'skip.header.line.count'='0',\\n'recursive.directories'='false');\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"-- {\\\"n_nationkey\\\":0,\\\"n_name\\\":\\\"ALGERIA\\\",\\\"n_regionkey\\\":0,\\\"n_comment\\\":\\\" haggle. carefully final deposits detect slyly agai\\\"}\\n\" +\n                \"CREATE DATABASE ddl_json_string\\n\" +\n                \"WITH DBPROPERTIES (\\n\" +\n                \"\\tLOCATION = 'oss://oss-cn-hangzhou-for-openanalytics/datasets/tpch/1x/json_string/',\\n\" +\n                \"\\tcatalog = 'oss'\\n\" +\n                \");\\n\" +\n                \"\\n\" +\n                \"CREATE EXTERNAL TABLE ddl_json_string.nation_json (\\n\" +\n                \"\\tn_comment string,\\n\" +\n                \"\\tn_name string,\\n\" +\n                \"\\tn_nationkey int,\\n\" +\n                \"\\tn_regionkey int\\n\" +\n                \")\\n\" +\n                \"STORED AS JSON\\n\" +\n                \"LOCATION 'oss://oss-cn-hangzhou-for-openanalytics/datasets/tpch/1x/json_string/nation_json/'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'skip.header.line.count' = '0',\\n\" +\n                \"\\t'recursive.directories' = 'false'\\n\" +\n                \");\", SQLUtils.toSQLString(statementList, JdbcConstants.HIVE));\n\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(2, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"-- {\\\"n_nationkey\\\":0,\\\"n_name\\\":\\\"ALGERIA\\\",\\\"n_regionkey\\\":0,\\\"n_comment\\\":\\\" haggle. carefully final deposits detect slyly agai\\\"}\\n\" +\n                    \"CREATE DATABASE ddl_json_string\\n\" +\n                    \"WITH DBPROPERTIES (\\n\" +\n                    \"\\tLOCATION = 'oss://oss-cn-hangzhou-for-openanalytics/datasets/tpch/1x/json_string/',\\n\" +\n                    \"\\tcatalog = 'oss'\\n\" +\n                    \");\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n//        assertTrue(visitor.containsTable(\"customer_case.tradelist_csv\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_39_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_39_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"--\\n-- Sample on record\\n--     {\\\"c_custkey\\\":1,\\\"c_name\\\":\\\"Customer#000000001\\\",\\\"c_address\\\":\\\"IVhzIApeRb ot,c,E\\\",\\\"c_nationkey\\\":15,\\\"c_phone\\\":\\\"25-989-741-2988\\\",\\\"c_acctbal\\\":711.56,\\\"c_mktsegment\\\":\\\"BUILDING\\\",\\\"c_comment\\\":\\\"to theeven, regular platelets. regular, ironic epitaphs nag e\\\"}\\n\\nCREATE EXTERNAL TABLE IF NOT EXISTS `mengdou_test`.`ddl_customer_json`(`c_acctbal` double, `c_address` string, `c_comment` string, `c_custkey` int, `c_mktsegment` string, `c_name` string, `c_nationkey` int, `c_phone` string, ) STORED AS JSON LOCATION 'oss://oss-cn-shanghai-for-openanalytics/datasets/tpch/0.01x/json_date/customer_json/' TBLPROPERTIES ( \\n'skip.header.line.count'='0',\\n'recursive.directories'='false');\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"--\\n\" +\n                \"-- Sample on record\\n\" +\n                \"--     {\\\"c_custkey\\\":1,\\\"c_name\\\":\\\"Customer#000000001\\\",\\\"c_address\\\":\\\"IVhzIApeRb ot,c,E\\\",\\\"c_nationkey\\\":15,\\\"c_phone\\\":\\\"25-989-741-2988\\\",\\\"c_acctbal\\\":711.56,\\\"c_mktsegment\\\":\\\"BUILDING\\\",\\\"c_comment\\\":\\\"to theeven, regular platelets. regular, ironic epitaphs nag e\\\"}\\n\" +\n                \"CREATE EXTERNAL TABLE IF NOT EXISTS `mengdou_test`.`ddl_customer_json` (\\n\" +\n                \"\\t`c_acctbal` double,\\n\" +\n                \"\\t`c_address` string,\\n\" +\n                \"\\t`c_comment` string,\\n\" +\n                \"\\t`c_custkey` int,\\n\" +\n                \"\\t`c_mktsegment` string,\\n\" +\n                \"\\t`c_name` string,\\n\" +\n                \"\\t`c_nationkey` int,\\n\" +\n                \"\\t`c_phone` string\\n\" +\n                \")\\n\" +\n                \"STORED AS JSON\\n\" +\n                \"LOCATION 'oss://oss-cn-shanghai-for-openanalytics/datasets/tpch/0.01x/json_date/customer_json/'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'skip.header.line.count' = '0',\\n\" +\n                \"\\t'recursive.directories' = 'false'\\n\" +\n                \");\", SQLUtils.toSQLString(statementList, JdbcConstants.HIVE));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_4 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE merge_data.transactions(\\n\" +\n                        \"\\tID int,\\n\" +\n                        \"\\tTranValue string,\\n\" +\n                        \"\\tlast_update_user string)\\n\" +\n                        \"PARTITIONED BY (tran_date string)\\n\" +\n                        \"CLUSTERED BY (ID) into 5 buckets \\n\" +\n                        \"STORED AS ORC TBLPROPERTIES ('transactional'='true');\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE merge_data.transactions (\\n\" +\n                    \"\\tID int,\\n\" +\n                    \"\\tTranValue string,\\n\" +\n                    \"\\tlast_update_user string\\n\" +\n                    \")\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\ttran_date string\\n\" +\n                    \")\\n\" +\n                    \"CLUSTERED BY (ID)\\n\" +\n                    \"INTO 5 BUCKETS\\n\" +\n                    \"STORED AS ORC\\n\" +\n                    \"TBLPROPERTIES (\\n\" +\n                    \"\\t'transactional' = 'true'\\n\" +\n                    \");\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"merge_data.transactions\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_40_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_40_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE EXTERNAL TABLE IF NOT EXISTS `customer_case`.`shangjian_6e958954-f2c7-11e8-94b7-0c54159e4818.json.snappy` (\\n\" +\n                \"  `batch_date` string,\\n\" +\n                \"  `data` STRUCT<`goods_name`:STRING, `thumb_url`:STRING, `country`:STRING, `is_app`:INT, `sales_tip`:STRING, `image_url`:STRING, `cnt`:INT, `goods_id`:BIGINT, `hd_thumb_url`:STRING, `is_use_promotion`:INT, `event_type`:INT, `normal_price`:INT, `market_price`:INT, `short_name`:STRING, group:STRUCT<`price`:INT, `customer_num`:INT>>,\\n\" +\n                \"  `goods_id` bigint,\\n\" +\n                \"  `gtime` bigint,\\n\" +\n                \"  `hot_tag` int,\\n\" +\n                \"  `mall_id` int,\\n\" +\n                \"  `uuid` string\\n\" +\n                \")\\n\" +\n                \"STORED AS JSON\\n\" +\n                \"LOCATION 'oss://oss-cn-hangzhou-for-openanalytics/datasets/test/customer_case/'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"  'skip.header.line.count' = '0',\\n\" +\n                \"  'recursive.directories' = 'false',\\n\" +\n                \"  'file.filter' = 'shangjian_6e958954-f2c7-11e8-94b7-0c54159e4818.json.snappy'\\n\" +\n                \");\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"CREATE EXTERNAL TABLE IF NOT EXISTS `customer_case`.`shangjian_6e958954-f2c7-11e8-94b7-0c54159e4818.json.snappy` (\\n\" +\n                \"\\t`batch_date` string,\\n\" +\n                \"\\t`data` STRUCT<\\n\" +\n                \"\\t\\t`goods_name`:STRING,\\n\" +\n                \"\\t\\t`thumb_url`:STRING,\\n\" +\n                \"\\t\\t`country`:STRING,\\n\" +\n                \"\\t\\t`is_app`:INT,\\n\" +\n                \"\\t\\t`sales_tip`:STRING,\\n\" +\n                \"\\t\\t`image_url`:STRING,\\n\" +\n                \"\\t\\t`cnt`:INT,\\n\" +\n                \"\\t\\t`goods_id`:BIGINT,\\n\" +\n                \"\\t\\t`hd_thumb_url`:STRING,\\n\" +\n                \"\\t\\t`is_use_promotion`:INT,\\n\" +\n                \"\\t\\t`event_type`:INT,\\n\" +\n                \"\\t\\t`normal_price`:INT,\\n\" +\n                \"\\t\\t`market_price`:INT,\\n\" +\n                \"\\t\\t`short_name`:STRING,\\n\" +\n                \"\\t\\tgroup:STRUCT<`price`:INT, `customer_num`:INT>\\n\" +\n                \"\\t>,\\n\" +\n                \"\\t`goods_id` bigint,\\n\" +\n                \"\\t`gtime` bigint,\\n\" +\n                \"\\t`hot_tag` int,\\n\" +\n                \"\\t`mall_id` int,\\n\" +\n                \"\\t`uuid` string\\n\" +\n                \")\\n\" +\n                \"STORED AS JSON\\n\" +\n                \"LOCATION 'oss://oss-cn-hangzhou-for-openanalytics/datasets/test/customer_case/'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'skip.header.line.count' = '0',\\n\" +\n                \"\\t'recursive.directories' = 'false',\\n\" +\n                \"\\t'file.filter' = 'shangjian_6e958954-f2c7-11e8-94b7-0c54159e4818.json.snappy'\\n\" +\n                \");\", SQLUtils.toSQLString(statementList, JdbcConstants.HIVE));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_41.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_41 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS default.create_test (id int COMMENT '学号', name string COMMENT '姓名');\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS default.create_test (\\n\" +\n                \"\\tid int COMMENT '学号',\\n\" +\n                \"\\tname string COMMENT '姓名'\\n\" +\n                \");\", SQLUtils.toSQLString(statementList, JdbcConstants.HIVE));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_42.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_42 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS default.create_test (id int COMMENT '学号', name string COMMENT '姓名')ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' WITH SERDEPROPERTIES(\\\"serialization.encoding\\\"='gbk');\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS default.create_test (\\n\" +\n                \"\\tid int COMMENT '学号',\\n\" +\n                \"\\tname string COMMENT '姓名'\\n\" +\n                \")\\n\" +\n                \"ROW FORMAT\\n\" +\n                \"\\tSERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'\\n\" +\n                \"WITH SERDEPROPERTIES (\\n\" +\n                \"\\t\\\"serialization.encoding\\\" = 'gbk'\\n\" +\n                \");\", SQLUtils.toSQLString(statementList, JdbcConstants.HIVE));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_43.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_43 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE EXTERNAL TABLE tbl2_copy  STORED AS PARQUET LOCATION 'oss://oss-cn-beijing-for-openanalytics-test-2/datasets/jinluo/tbl1_copy/' TBLPROPERTIES ('auto.create.location' = 'true')\" +\n                \" like SELECT * FROM tbl1;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"CREATE EXTERNAL TABLE tbl2_copy\\n\" +\n                \"STORED AS PARQUET\\n\" +\n                \"LOCATION 'oss://oss-cn-beijing-for-openanalytics-test-2/datasets/jinluo/tbl1_copy/'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'auto.create.location' = 'true'\\n\" +\n                \")\\n\" +\n                \"LIKE\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM tbl1;\", SQLUtils.toSQLString(statementList, JdbcConstants.HIVE));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_43_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_43_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE EXTERNAL TABLE special_char1(\\n\" +\n                \"    data_time_str string,\\n\" +\n                \"    entity_id string,\\n\" +\n                \"    thread string,\\n\" +\n                \"    logger_name string,\\n\" +\n                \"    msg string\\n\" +\n                \") ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe'\\n\" +\n                \"with serdeproperties(\\n\" +\n                \"\\\"field.delim\\\"=\\\"\\\\u2605\\\"\\n\" +\n                \")\\n\" +\n                \"STORED AS TEXTFILE\\n\" +\n                \"LOCATION 'oss://oss-cn-beijing-for-openanalytics-test/datasets/test/customer_case/fuzhike/special_char1.log'\\n\" +\n                \"TBLPROPERTIES ('textinputformat.record.delimiter'='\\\\u25bc');\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"CREATE EXTERNAL TABLE special_char1 (\\n\" +\n                \"\\tdata_time_str string,\\n\" +\n                \"\\tentity_id string,\\n\" +\n                \"\\tthread string,\\n\" +\n                \"\\tlogger_name string,\\n\" +\n                \"\\tmsg string\\n\" +\n                \")\\n\" +\n                \"ROW FORMAT\\n\" +\n                \"\\tSERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe'\\n\" +\n                \"WITH SERDEPROPERTIES (\\n\" +\n                \"\\t\\\"field.delim\\\" = '\\\\u2605'\\n\" +\n                \")\\n\" +\n                \"STORED AS TEXTFILE\\n\" +\n                \"LOCATION 'oss://oss-cn-beijing-for-openanalytics-test/datasets/test/customer_case/fuzhike/special_char1.log'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'textinputformat.record.delimiter' = '\\\\u25bc'\\n\" +\n                \");\", statementList.get(0).toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_44.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_44 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"--\\n-- Sample on record\\n\" +\n                \"--     {\\\"bid\\\":\\\"360\\\",\\\"request_id\\\":\\\"12c6b4b7c7d590fc\\\",\\\"hour\\\":\\\"2018121315\\\",\\\"time\\\":\\\"1544684400\\\",\\\"tagid\\\":\\\"2256906\\\",\\\"plan_id\\\":\\\"636102\\\",\\\"sid\\\":\\\"288\\\",\\\"creative_id\\\":\\\"198\\\",\\\"cookie_id\\\":\\\"7af422884e2fab197c9dfd068181ac0d\\\",\\\"ip\\\":\\\"117.136.89.121\\\",\\\"price\\\":\\\"0.2800\\\",\\\"bid_price\\\":\\\"0.1400\\\",\\\"user_agent\\\":\\\"Dalvik/2.1.0 (Linux; U; Android 6.0.1; OPPO A57 Build/MMB29M)\\\",\\\"refer\\\":\\\"\\\"}\\n\\n\" +\n                \"CREATE EXTERNAL TABLE IF NOT EXISTS `data2`.`table1`(`bid` int, `bid_price` double, `cookie_id` binary, `creative_id` int, `hour` bigint, `ip` string, `plan_id` bigint, `price` double, `refer` binary, `request_id` binary, `sid` int, `tagid` bigint, `time` bigint, `user_agent` string, ) STORED AS JSON LOCATION 'oss://aliyun-oa-query-results-1863300811734283-cn-hangzhou/data/json_data/' TBLPROPERTIES ( \\n'skip.header.line.count'='0',\\n'recursive.directories'='true');\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"--\\n\" +\n                \"-- Sample on record\\n\" +\n                \"--     {\\\"bid\\\":\\\"360\\\",\\\"request_id\\\":\\\"12c6b4b7c7d590fc\\\",\\\"hour\\\":\\\"2018121315\\\",\\\"time\\\":\\\"1544684400\\\",\\\"tagid\\\":\\\"2256906\\\",\\\"plan_id\\\":\\\"636102\\\",\\\"sid\\\":\\\"288\\\",\\\"creative_id\\\":\\\"198\\\",\\\"cookie_id\\\":\\\"7af422884e2fab197c9dfd068181ac0d\\\",\\\"ip\\\":\\\"117.136.89.121\\\",\\\"price\\\":\\\"0.2800\\\",\\\"bid_price\\\":\\\"0.1400\\\",\\\"user_agent\\\":\\\"Dalvik/2.1.0 (Linux; U; Android 6.0.1; OPPO A57 Build/MMB29M)\\\",\\\"refer\\\":\\\"\\\"}\\n\" +\n                \"CREATE EXTERNAL TABLE IF NOT EXISTS `data2`.`table1` (\\n\" +\n                \"\\t`bid` int,\\n\" +\n                \"\\t`bid_price` double,\\n\" +\n                \"\\t`cookie_id` binary,\\n\" +\n                \"\\t`creative_id` int,\\n\" +\n                \"\\t`hour` bigint,\\n\" +\n                \"\\t`ip` string,\\n\" +\n                \"\\t`plan_id` bigint,\\n\" +\n                \"\\t`price` double,\\n\" +\n                \"\\t`refer` binary,\\n\" +\n                \"\\t`request_id` binary,\\n\" +\n                \"\\t`sid` int,\\n\" +\n                \"\\t`tagid` bigint,\\n\" +\n                \"\\t`time` bigint,\\n\" +\n                \"\\t`user_agent` string\\n\" +\n                \")\\n\" +\n                \"STORED AS JSON\\n\" +\n                \"LOCATION 'oss://aliyun-oa-query-results-1863300811734283-cn-hangzhou/data/json_data/'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'skip.header.line.count' = '0',\\n\" +\n                \"\\t'recursive.directories' = 'true'\\n\" +\n                \");\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_45_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_45_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE EXTERNAL TABLE IF NOT EXISTS `bfbf8508d0a59644fe2003c7506f3676`.`device_group_relation` ( `device_name` VARCHAR NOT NULL COMMENT 'name,?meta device??', `gmt_create` TIMESTAMP NOT NULL COMMENT '????', `gmt_modified` TIMESTAMP NOT NULL COMMENT '????', `group_id` VARCHAR NOT NULL COMMENT 'group id', `group_relation_status` VARCHAR NOT NULL COMMENT 'inital 0, 1 isDeleted', `group_type` VARCHAR NOT NULL COMMENT 'group type, \\\"ISOLATION\\\", \\\"\\\"', `id` BIGINT NOT NULL COMMENT '??', `iot_id` VARCHAR NOT NULL COMMENT 'iot_id', `product_key` VARCHAR NOT NULL COMMENT 'product key', `tenant_id` VARCHAR NULL COMMENT 'rbac tenant_id' ) TBLPROPERTIES ( 'TABLE_MAPPING' = `device_group_relation` )\\n\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"CREATE EXTERNAL TABLE IF NOT EXISTS `bfbf8508d0a59644fe2003c7506f3676`.`device_group_relation` (\\n\" +\n                \"\\t`device_name` VARCHAR NOT NULL COMMENT 'name,?meta device??',\\n\" +\n                \"\\t`gmt_create` TIMESTAMP NOT NULL COMMENT '????',\\n\" +\n                \"\\t`gmt_modified` TIMESTAMP NOT NULL COMMENT '????',\\n\" +\n                \"\\t`group_id` VARCHAR NOT NULL COMMENT 'group id',\\n\" +\n                \"\\t`group_relation_status` VARCHAR NOT NULL COMMENT 'inital 0, 1 isDeleted',\\n\" +\n                \"\\t`group_type` VARCHAR NOT NULL COMMENT 'group type, \\\"ISOLATION\\\", \\\"\\\"',\\n\" +\n                \"\\t`id` BIGINT NOT NULL COMMENT '??',\\n\" +\n                \"\\t`iot_id` VARCHAR NOT NULL COMMENT 'iot_id',\\n\" +\n                \"\\t`product_key` VARCHAR NOT NULL COMMENT 'product key',\\n\" +\n                \"\\t`tenant_id` VARCHAR NULL COMMENT 'rbac tenant_id'\\n\" +\n                \")\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'TABLE_MAPPING' = `device_group_relation`\\n\" +\n                \")\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_46_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_46_dla extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE EXTERNAL TABLE parquet_tbl LIKE MAPPING('oss://user/etl/destination/datafile1.dat')\" +\n                \" TBLPROPERTIES('target.table.location'='oss://user/etl/destination/')\";\n        SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"CREATE EXTERNAL TABLE parquet_tbl\\n\" +\n                \"LIKE MAPPING('oss://user/etl/destination/datafile1.dat')\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'target.table.location' = 'oss://user/etl/destination/'\\n\" +\n                \")\", stmt.toString());\n\n        assertEquals(stmt.toString(), SQLUtils.parseSingleStatement(stmt.toString(), DbType.hive, SQLParserFeature.KeepComments).toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_47_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_47_dla\n        extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE external TABLE IF NOT EXISTS dwd_tfc_bas_rdnet_inter_info (\\n\" +\n                \"inter_id varchar(225) NOT NULL COMMENT ' 路口id ',\\n\" +\n                \"inter_name varchar(225) DEFAULT NULL COMMENT ' (当前版本可能有空值)路口名称,按相交道路名命名。规则：等级高的道路放前面；相同等级道路时，路口关联的有名路段放前面。交叉口命名如：长安街与西单北大街路口道路端点命名如：xxx路端点 ',\\n\" +\n                \"lng double DEFAULT NULL COMMENT ' 路口中心点经度 ',\\n\" +\n                \"lat double DEFAULT NULL COMMENT ' 路口中心点纬度 ',\\n\" +\n                \"geohash varchar(225) DEFAULT NULL COMMENT ' geohash 10位 ',\\n\" +\n                \"is_signlight bigint DEFAULT NULL COMMENT ' 是否信号灯路口,0：无交通信号灯,1：有交通信号灯 ',\\n\" +\n                \"inter_type_no bigint DEFAULT NULL COMMENT ' 1：十字形路口,2：t形路口,3：y形路口,4：环形交叉口,5：匝道、出入口,6：路段（只有两个方向的路口）,7：错位t形路口,8：斜交路口（x型路口）,9：多路路口,10：其他 ',\\n\" +\n                \"entrance_cnt bigint DEFAULT NULL COMMENT ' 进口道数量 ',\\n\" +\n                \"area_code bigint DEFAULT NULL COMMENT ' 区域编码 ',\\n\" +\n                \"area_name varchar(225) DEFAULT NULL COMMENT ' 区域名称 ',\\n\" +\n                \"is_corner bigint DEFAULT NULL COMMENT ' 是否综合路口,0不是综合路口，1综合路口，3环岛',\\n\" +\n                \"inter_flowtype_no bigint DEFAULT NULL COMMENT '1 交叉口（多进多出）,2 合流口,3 分流口',\\n\" +\n                \"data_version varchar(225) NOT NULL COMMENT ' 季度的最后一天，如20180331 ',\\n\" +\n                \"adcode varchar(225) NOT NULL COMMENT ' 所属城市代码，标准6位数字代码 ',\\n\" +\n                \"PRIMARY KEY (`inter_id`, `data_version`, `adcode`),\\n\" +\n                \"KEY `index_id` (`inter_id`)\\n\" +\n                \") ENGINE = innodb CHARSET = utf8 COMMENT '路口基本信息';\";\n        SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        assertEquals(\"CREATE EXTERNAL TABLE IF NOT EXISTS dwd_tfc_bas_rdnet_inter_info (\\n\" +\n                \"\\tinter_id varchar(225) NOT NULL COMMENT ' 路口id ',\\n\" +\n                \"\\tinter_name varchar(225) DEFAULT NULL COMMENT ' (当前版本可能有空值)路口名称,按相交道路名命名。规则：等级高的道路放前面；相同等级道路时，路口关联的有名路段放前面。交叉口命名如：长安街与西单北大街路口道路端点命名如：xxx路端点 ',\\n\" +\n                \"\\tlng double DEFAULT NULL COMMENT ' 路口中心点经度 ',\\n\" +\n                \"\\tlat double DEFAULT NULL COMMENT ' 路口中心点纬度 ',\\n\" +\n                \"\\tgeohash varchar(225) DEFAULT NULL COMMENT ' geohash 10位 ',\\n\" +\n                \"\\tis_signlight bigint DEFAULT NULL COMMENT ' 是否信号灯路口,0：无交通信号灯,1：有交通信号灯 ',\\n\" +\n                \"\\tinter_type_no bigint DEFAULT NULL COMMENT ' 1：十字形路口,2：t形路口,3：y形路口,4：环形交叉口,5：匝道、出入口,6：路段（只有两个方向的路口）,7：错位t形路口,8：斜交路口（x型路口）,9：多路路口,10：其他 ',\\n\" +\n                \"\\tentrance_cnt bigint DEFAULT NULL COMMENT ' 进口道数量 ',\\n\" +\n                \"\\tarea_code bigint DEFAULT NULL COMMENT ' 区域编码 ',\\n\" +\n                \"\\tarea_name varchar(225) DEFAULT NULL COMMENT ' 区域名称 ',\\n\" +\n                \"\\tis_corner bigint DEFAULT NULL COMMENT ' 是否综合路口,0不是综合路口，1综合路口，3环岛',\\n\" +\n                \"\\tinter_flowtype_no bigint DEFAULT NULL COMMENT '1 交叉口（多进多出）,2 合流口,3 分流口',\\n\" +\n                \"\\tdata_version varchar(225) NOT NULL COMMENT ' 季度的最后一天，如20180331 ',\\n\" +\n                \"\\tadcode varchar(225) NOT NULL COMMENT ' 所属城市代码，标准6位数字代码 ',\\n\" +\n                \"\\tPRIMARY KEY (`inter_id`, `data_version`, `adcode`),\\n\" +\n                \"\\tKEY `index_id`(`inter_id`)\\n\" +\n                \")\\n\" +\n                \"COMMENT '路口基本信息';\", stmt.toString());\n\n        assertEquals(stmt.toString(), SQLUtils.parseSingleStatement(stmt.toString(), DbType.hive, SQLParserFeature.KeepComments).toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_49_dla.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_49_dla\n        extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = \"create external  table `dla_result`.`sgm_add`\\n\" +\n                \"STORED AS parquet \\n\" +\n                \"LOCATION  \\n\" +\n                \"'oss://aliyun-oa-query-results-1408722774623865-oss-cn-zhangjiakou/DLA_Result/sgm_add/'\\n\" +\n                \"TBLPROPERTIES ('auto.create.location' = 'true') like select pure_date,(substr(regexp_extract(fld11, '\\\"sgm_add\\\":\\\"?([^\\\"}]*)', 1), 1, 10)) AS sgm_add from \\n\" +\n                \"log_push_1912 where pure_date = 20191120\";\n        SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.hive, SQLParserFeature.KeepComments);\n\n        SQLStatement clone = stmt.clone();\n\n        assertEquals(\"CREATE EXTERNAL TABLE `dla_result`.`sgm_add`\\n\" +\n                \"STORED AS parquet\\n\" +\n                \"LOCATION 'oss://aliyun-oa-query-results-1408722774623865-oss-cn-zhangjiakou/DLA_Result/sgm_add/'\\n\" +\n                \"TBLPROPERTIES (\\n\" +\n                \"\\t'auto.create.location' = 'true'\\n\" +\n                \")\\n\" +\n                \"LIKE\\n\" +\n                \"SELECT pure_date\\n\" +\n                \"\\t, (substr(regexp_extract(fld11, '\\\"sgm_add\\\":\\\"?([^\\\"}]*)', 1), 1, 10)) AS sgm_add\\n\" +\n                \"FROM log_push_1912\\n\" +\n                \"WHERE pure_date = 20191120\", clone.toString());\n\n        assertEquals(stmt.toString(), SQLUtils.parseSingleStatement(stmt.toString(), DbType.hive, SQLParserFeature.KeepComments).toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_5 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE user_info_bucketed(user_id BIGINT, firstname STRING, lastname STRING)\\n\" +\n                        \"COMMENT 'A bucketed copy of user_info'\\n\" +\n                        \"PARTITIONED BY(ds STRING)\\n\" +\n                        \"CLUSTERED BY(user_id) INTO 256 BUCKETS;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE user_info_bucketed (\\n\" +\n                    \"\\tuser_id BIGINT,\\n\" +\n                    \"\\tfirstname STRING,\\n\" +\n                    \"\\tlastname STRING\\n\" +\n                    \")\\n\" +\n                    \"COMMENT 'A bucketed copy of user_info'\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tds STRING\\n\" +\n                    \")\\n\" +\n                    \"CLUSTERED BY (user_id)\\n\" +\n                    \"INTO 256 BUCKETS;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"user_info_bucketed\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_6.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_6 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"create table table_name (\\n\" +\n                        \"  id                int,\\n\" +\n                        \"  dtDontQuery       string,\\n\" +\n                        \"  name              string\\n\" +\n                        \")\\n\" +\n                        \"partitioned by (date string)\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE table_name (\\n\" +\n                    \"\\tid int,\\n\" +\n                    \"\\tdtDontQuery string,\\n\" +\n                    \"\\tname string\\n\" +\n                    \")\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tdate string\\n\" +\n                    \")\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"table_name\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_7.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_7 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE page_view(viewTime INT, userid BIGINT,\\n\" +\n                        \"     page_url STRING, referrer_url STRING,\\n\" +\n                        \"     ip STRING COMMENT 'IP Address of the User')\\n\" +\n                        \" COMMENT 'This is the page view table'\\n\" +\n                        \" PARTITIONED BY(dt STRING, country STRING)\\n\" +\n                        \" STORED AS SEQUENCEFILE;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE page_view (\\n\" +\n                    \"\\tviewTime INT,\\n\" +\n                    \"\\tuserid BIGINT,\\n\" +\n                    \"\\tpage_url STRING,\\n\" +\n                    \"\\treferrer_url STRING,\\n\" +\n                    \"\\tip STRING COMMENT 'IP Address of the User'\\n\" +\n                    \")\\n\" +\n                    \"COMMENT 'This is the page view table'\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tdt STRING,\\n\" +\n                    \"\\tcountry STRING\\n\" +\n                    \")\\n\" +\n                    \"STORED AS SEQUENCEFILE;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"page_view\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_8.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_8 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE TABLE page_view(viewTime INT, userid BIGINT,\\n\" +\n                        \"     page_url STRING, referrer_url STRING,\\n\" +\n                        \"     ip STRING COMMENT 'IP Address of the User')\\n\" +\n                        \" COMMENT 'This is the page view table'\\n\" +\n                        \" PARTITIONED BY(dt STRING, country STRING)\\n\" +\n                        \" ROW FORMAT DELIMITED\\n\" +\n                        \"   FIELDS TERMINATED BY '\\\\001' ESCAPED BY '\\\\\\\\'\\n\" +\n                        \"STORED AS SEQUENCEFILE;\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE TABLE page_view (\\n\" +\n                    \"\\tviewTime INT,\\n\" +\n                    \"\\tuserid BIGINT,\\n\" +\n                    \"\\tpage_url STRING,\\n\" +\n                    \"\\treferrer_url STRING,\\n\" +\n                    \"\\tip STRING COMMENT 'IP Address of the User'\\n\" +\n                    \")\\n\" +\n                    \"COMMENT 'This is the page view table'\\n\" +\n                    \"PARTITIONED BY (\\n\" +\n                    \"\\tdt STRING,\\n\" +\n                    \"\\tcountry STRING\\n\" +\n                    \")\\n\" +\n                    \"ROW FORMAT DELIMITED\\n\" +\n                    \"\\tFIELDS TERMINATED BY '\\\\001'\\n\" +\n                    \"\\tESCAPED BY '\\\\\\\\'\\n\" +\n                    \"STORED AS SEQUENCEFILE;\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"page_view\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest_9.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveCreateTableTest_9 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE EXTERNAL TABLE page_view(viewTime INT, userid BIGINT,\\n\" +\n                        \"     page_url STRING, referrer_url STRING,\\n\" +\n                        \"     ip STRING COMMENT 'IP Address of the User',\\n\" +\n                        \"     country STRING COMMENT 'country of origination')\\n\" +\n                        \" COMMENT 'This is the staging page view table'\\n\" +\n                        \" ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\\\054'\\n\" +\n                        \" STORED AS TEXTFILE\\n\" +\n                        \" LOCATION '<hdfs_location>';\";\n\n        List<SQLStatement> statementList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        {\n            String text = SQLUtils.toSQLString(stmt, JdbcConstants.HIVE);\n\n            assertEquals(\"CREATE EXTERNAL TABLE page_view (\\n\" +\n                    \"\\tviewTime INT,\\n\" +\n                    \"\\tuserid BIGINT,\\n\" +\n                    \"\\tpage_url STRING,\\n\" +\n                    \"\\treferrer_url STRING,\\n\" +\n                    \"\\tip STRING COMMENT 'IP Address of the User',\\n\" +\n                    \"\\tcountry STRING COMMENT 'country of origination'\\n\" +\n                    \")\\n\" +\n                    \"COMMENT 'This is the staging page view table'\\n\" +\n                    \"ROW FORMAT DELIMITED\\n\" +\n                    \"\\tFIELDS TERMINATED BY '\\\\054'\\n\" +\n                    \"STORED AS TEXTFILE\\n\" +\n                    \"LOCATION '<hdfs_location>';\", text);\n        }\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(6, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getRelationships().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertTrue(visitor.containsTable(\"page_view\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveInsert_0.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveInsert_0 {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"INSERT INTO TABLE students\\n\" +\n                \"  VALUES ('fred flintstone', 35, 1.28), ('barney rubble', 32, 2.32);\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        assertEquals(\"INSERT INTO TABLE students\\n\" +\n                \"VALUES ('fred flintstone', 35, 1.28), ('barney rubble', 32, 2.32);\", SQLUtils.formatHive(sql));\n\n        assertEquals(\"insert into table students\\n\" +\n                \"values ('fred flintstone', 35, 1.28), ('barney rubble', 32, 2.32);\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//      System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveInsert_1.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveInsert_1 {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"FROM page_view_stg pvs\\n\" +\n                \"INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country)\\n\" +\n                \"       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip, pvs.cnt\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        assertEquals(\"FROM page_view_stg pvs\\n\" +\n                \"INSERT OVERWRITE TABLE page_view PARTITION (dt='2008-06-08', country)\\n\" +\n                \"SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, NULL\\n\" +\n                \"\\t, NULL, pvs.ip, pvs.cnt\", SQLUtils.formatHive(sql));\n\n        assertEquals(\"from page_view_stg pvs\\n\" +\n                \"insert overwrite table page_view partition (dt='2008-06-08', country)\\n\" +\n                \"select pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null\\n\" +\n                \"\\t, null, pvs.ip, pvs.cnt\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//      System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(8, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveInsert_3.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveInsert_3 {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"FROM sale_detail\\n\" +\n                \"INSERT OVERWRITE TABLE sale_detail_multi partition (sale_date='2010', region='china' )\\n\" +\n                \"SELECT shop_name, customer_id, total_price\\n\" +\n                \"INSERT OVERWRITE TABLE sale_detail_multi partition (sale_date='2010', region='china' )\\n\" +\n                \"SELECT shop_name, customer_id, total_price;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        assertEquals(\"FROM sale_detail\\n\" +\n                \"INSERT OVERWRITE TABLE sale_detail_multi PARTITION (sale_date='2010', region='china')\\n\" +\n                \"SELECT shop_name, customer_id, total_price\\n\" +\n                \"INSERT OVERWRITE TABLE sale_detail_multi PARTITION (sale_date='2010', region='china')\\n\" +\n                \"SELECT shop_name, customer_id, total_price;\", SQLUtils.formatHive(sql));\n\n        assertEquals(\"from sale_detail\\n\" +\n                \"insert overwrite table sale_detail_multi partition (sale_date='2010', region='china')\\n\" +\n                \"select shop_name, customer_id, total_price\\n\" +\n                \"insert overwrite table sale_detail_multi partition (sale_date='2010', region='china')\\n\" +\n                \"select shop_name, customer_id, total_price;\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"sale_detail_multi\", \"sale_date\"));\n        assertTrue(visitor.containsColumn(\"sale_detail_multi\", \"region\"));\n        assertTrue(visitor.containsColumn(\"sale_detail\", \"shop_name\"));\n        assertTrue(visitor.containsColumn(\"sale_detail\", \"customer_id\"));\n        assertTrue(visitor.containsColumn(\"sale_detail\", \"total_price\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveKeywordsTest.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveKeywordsTest {\n    @Test\n    public void test_keywords() {\n        DbType dbType = DbType.hive;\n        String sql = \"select 1 as TIMESTAMPLOCALTZ\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql,\n                dbType,\n                SQLParserFeature.IgnoreNameQuotes);\n        SQLStatement stmt = parser.parseStatement();\n        assertEquals(Token.EOF, parser.getLexer().token());\n        String result = SQLUtils.toSQLString(stmt, dbType, null, VisitorFeature.OutputNameQuote).trim();\n        String expectedSql = \"SELECT 1 AS `TIMESTAMPLOCALTZ`\";\n        assertEquals(expectedSql, result);\n    }\n\n    @Test\n    public void test_keywords2() {\n        DbType dbType = DbType.hive;\n        String sql = \"select date(d) from t\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql,\n                dbType,\n                SQLParserFeature.IgnoreNameQuotes);\n        SQLStatement stmt = parser.parseStatement();\n        assertEquals(Token.EOF, parser.getLexer().token());\n        String result = SQLUtils.toSQLString(stmt, dbType, null, VisitorFeature.OutputNameQuote).trim();\n        String expectedSql = \"SELECT date(d)\\n\" + \"FROM t\";\n        assertEquals(expectedSql, result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class HiveResourceTest extends SQLResourceTest {\n    public HiveResourceTest() {\n        super(DbType.hive);\n    }\n\n    @Test\n    public void hive_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/hive/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_0.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_0 {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"SELECT page_views.*\\n\" +\n                \"FROM page_views\\n\" +\n                \"WHERE page_views.date >= '2008-03-01' AND page_views.date <= '2008-03-31'\";\n        assertEquals(\"SELECT page_views.*\\n\" +\n                \"FROM page_views\\n\" +\n                \"WHERE page_views.date >= '2008-03-01'\\n\" +\n                \"\\tAND page_views.date <= '2008-03-31'\", SQLUtils.formatHive(sql));\n        assertEquals(\"select page_views.*\\n\" +\n                \"from page_views\\n\" +\n                \"where page_views.date >= '2008-03-01'\\n\" +\n                \"\\tand page_views.date <= '2008-03-31'\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//      System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"page_views\", \"date\"));\n        assertTrue(visitor.containsColumn(\"page_views\", \"*\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_13_cluster_by.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_13_cluster_by\n {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select buyer_id,seller_id ,order_id,div_pay_amt,t1.dim_seller.member_id,t1.dim_buyer.member_id from LD_aly.fct_pay_ord_cn_di t1 cluster by buyer_id,seller_id \\n\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n\n        assertEquals(\"SELECT buyer_id, seller_id, order_id, div_pay_amt, t1.dim_seller.member_id\\n\" +\n                \"\\t, t1.dim_buyer.member_id\\n\" +\n                \"FROM LD_aly.fct_pay_ord_cn_di t1\\n\" +\n                \"CLUSTER BY buyer_id, seller_id\", stmt.toString());\n\n        assertEquals(\"SELECT buyer_id, seller_id, order_id, div_pay_amt, t1.dim_seller.member_id\\n\" +\n                \"\\t, t1.dim_buyer.member_id\\n\" +\n                \"FROM LD_aly.fct_pay_ord_cn_di t1\\n\" +\n                \"CLUSTER BY buyer_id, seller_id\", SQLUtils.toSQLString(stmt));\n\n        assertEquals(1, statementList.size());\n\n        for (SQLSelectOrderByItem item : stmt.getSelect().getQueryBlock().getClusterBy()) {\n            assertFalse(item.isSortBy());\n            assertFalse(item.isDistributeBy());\n            assertTrue(item.isClusterBy());\n        }\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n        System.out.println(\"groupBy : \" + visitor.getGroupByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getGroupByColumns().size());\n\n        assertTrue(visitor.containsColumn(\"LD_aly.fct_pay_ord_cn_di\", \"buyer_id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_1_limit.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_1_limit {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"SELECT * FROM customers ORDER BY create_date LIMIT 2,5\";\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM customers\\n\" +\n                \"ORDER BY create_date\\n\" +\n                \"LIMIT 2, 5\", SQLUtils.formatHive(sql));\n        assertEquals(\"select *\\n\" +\n                \"from customers\\n\" +\n                \"order by create_date\\n\" +\n                \"limit 2, 5\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//      System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"customers\", \"create_date\"));\n        assertTrue(visitor.containsColumn(\"customers\", \"*\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_2_lateralview.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.testutil.ParserTestUtils;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_2_lateralview {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"SELECT pageid, adid\\n\" +\n                \"FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid;\";\n        assertEquals(\"SELECT pageid, adid\\n\" +\n                \"FROM pageAds\\n\" +\n                \"\\tLATERAL VIEW explode(adid_list) adTable AS adid;\", SQLUtils.formatHive(sql));\n        assertEquals(\"select pageid, adid\\n\" +\n                \"from pageAds\\n\" +\n                \"\\tlateral view explode(adid_list) adTable as adid;\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SQLStatement stmt = ParserTestUtils.parseSingleStatement(sql, JdbcConstants.HIVE);\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"pageAds\", \"adid_list\"));\n        assertTrue(visitor.containsColumn(\"pageAds\", \"pageid\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_2_true.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBooleanExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_2_true {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"SELECT * FROM customers where isvalid = true or isxx = false\";\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM customers\\n\" +\n                \"WHERE isvalid = true\\n\" +\n                \"\\tOR isxx = false\", SQLUtils.formatHive(sql));\n        assertEquals(\"select *\\n\" +\n                \"from customers\\n\" +\n                \"where isvalid = true\\n\" +\n                \"\\tor isxx = false\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//      System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"customers\", \"isvalid\"));\n        assertTrue(visitor.containsColumn(\"customers\", \"isxx\"));\n        assertTrue(visitor.containsColumn(\"customers\", \"*\"));\n\n        SQLBinaryOpExpr where = (SQLBinaryOpExpr) ((SQLSelectStatement) stmt).getSelect().getQueryBlock().getWhere();\n        SQLBinaryOpExpr left = (SQLBinaryOpExpr) where.getLeft();\n        SQLBinaryOpExpr right = (SQLBinaryOpExpr) where.getRight();\n        assertEquals(SQLBooleanExpr.class, left.getRight().getClass());\n        assertEquals(SQLBooleanExpr.class, right.getRight().getClass());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_3_array.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_3_array\n {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"select languages[0] from json_nested_test;\";\n        assertEquals(\"SELECT languages[0]\\n\" +\n                \"FROM json_nested_test;\", SQLUtils.formatHive(sql));\n        assertEquals(\"select languages[0]\\n\" +\n                \"from json_nested_test;\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"json_nested_test\", \"languages\"));\n//        assertTrue(visitor.containsColumn(\"customers\", \"isxx\"));\n//        assertTrue(visitor.containsColumn(\"customers\", \"*\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_41.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_41 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select\\n\" +\n                \"field['id'].string_type as banner_id\\n\" +\n                \",field['index'].string_type as banner_index\\n\" +\n                \",field['pageName'].string_type as pageName\\n\" +\n                \"from\\n\" +\n                \"bdm_book.midu_xcx_web_main_log\\n\" +\n                \"where day = '2019-01-09'\\n\" +\n                \"and eventid = '151'\\n\" +\n                \"and cmd in ('26002','26003')\\n\" +\n                \"group by field['id'].string_type\\n\" +\n                \",field['index'].string_type\\n\" +\n                \",field['pageName'].string_type ;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);\n\n        assertEquals(\"SELECT field['id'].string_type AS banner_id, field['index'].string_type AS banner_index, field['pageName'].string_type AS pageName\\n\" +\n                \"FROM bdm_book.midu_xcx_web_main_log\\n\" +\n                \"WHERE day = '2019-01-09'\\n\" +\n                \"\\tAND eventid = '151'\\n\" +\n                \"\\tAND cmd IN ('26002', '26003')\\n\" +\n                \"GROUP BY field['id'].string_type, field['index'].string_type, field['pageName'].string_type;\", stmt.toString());\n\n        assertEquals(\"select field['id'].string_type as banner_id, field['index'].string_type as banner_index, field['pageName'].string_type as pageName\\n\" +\n                \"from bdm_book.midu_xcx_web_main_log\\n\" +\n                \"where day = '2019-01-09'\\n\" +\n                \"\\tand eventid = '151'\\n\" +\n                \"\\tand cmd in ('26002', '26003')\\n\" +\n                \"group by field['id'].string_type, field['index'].string_type, field['pageName'].string_type;\", stmt.toLowerCaseString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n        System.out.println(\"groupBy : \" + visitor.getGroupByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(3, visitor.getConditions().size());\n        assertEquals(0, visitor.getGroupByColumns().size());\n\n//        assertTrue(visitor.containsColumn(\"source\", \"*\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_42_cte.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveInsertStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_42_cte {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"with dycg_perform_startgametaketimelog as(\\n\" +\n                \"select app_id, if(ver is null, '', ver) as ver, if(machine_name is null, '', split(machine_name, '-') [0]) as machine_dc, game_id, current_step, err_code\\n\" +\n                \"  from ods_compass.ods_10006_dycg_perform_startgametaketimelog_tbl\\n\" +\n                \" where length(app_id)> 0\\n\" +\n                \"   and dt= substring(${dt_hour}, 0, 8)\\n\" +\n                \"   and hour= substr(${dt_hour}, 9, 2)\\n\" +\n                \"   and game_type= 1)\\n\" +\n                \"insert overwrite table ads_compass.ads_dycg_perform_eventpre_reach_game_process_rate_hour partition(ds= ${dt_hour})\\n\" +\n                \"select if(app_id is not null, app_id, 'all') as app_id, if(ver is not null, ver, 'all') as dycg_ver, if(machine_dc is not null, machine_dc, 'all') as machine_dc, if(game_id is not null, game_id, 'all') as game_id, sum(CASE WHEN current_step= 6\\n\" +\n                \"    or current_step= 7 THEN 1 ELSE 0 END) as reach_game_process_cnt, sum(CASE WHEN current_step= 5\\n\" +\n                \"    or current_step= 6\\n\" +\n                \"    or current_step= 7 THEN 1 ELSE 0 END) as tot_reach_game_process_cnt, round(1-(sum(CASE WHEN current_step= 5 THEN 1 ELSE 0 END) /sum(CASE WHEN current_step= 5\\n\" +\n                \"    or current_step= 6\\n\" +\n                \"    or current_step= 7 THEN 1 ELSE 0 END)), 4) as reach_game_process_rate, from_unixtime(unix_timestamp(cast(${dt_hour} as string), 'yyyyMMddHH'), 'yyyy-MM-dd') as dt, substring(${dt_hour}, 9, 2) as `hour`\\n\" +\n                \"  from dycg_perform_startgametaketimelog\\n\" +\n                \"group by app_id, ver, machine_dc, game_id grouping sets((app_id),(app_id, ver),(app_id, ver, machine_dc),(app_id, ver, game_id),(app_id, machine_dc),(app_id, machine_dc, game_id),(app_id, game_id),(app_id, ver, machine_dc, game_id))\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        HiveInsertStatement stmt = (HiveInsertStatement) statementList.get(0);\n\n        assertEquals(\"WITH dycg_perform_startgametaketimelog AS (\\n\" +\n                \"\\t\\tSELECT app_id\\n\" +\n                \"\\t\\t\\t, if(ver IS NULL, '', ver) AS ver\\n\" +\n                \"\\t\\t\\t, if(machine_name IS NULL, '', split(machine_name, '-')[0]) AS machine_dc\\n\" +\n                \"\\t\\t\\t, game_id, current_step, err_code\\n\" +\n                \"\\t\\tFROM ods_compass.ods_10006_dycg_perform_startgametaketimelog_tbl\\n\" +\n                \"\\t\\tWHERE length(app_id) > 0\\n\" +\n                \"\\t\\t\\tAND dt = substring(${dt_hour}, 0, 8)\\n\" +\n                \"\\t\\t\\tAND hour = substr(${dt_hour}, 9, 2)\\n\" +\n                \"\\t\\t\\tAND game_type = 1\\n\" +\n                \"\\t)\\n\" +\n                \"INSERT OVERWRITE TABLE ads_compass.ads_dycg_perform_eventpre_reach_game_process_rate_hour PARTITION (ds=${dt_hour})\\n\" +\n                \"SELECT if(app_id IS NOT NULL, app_id, 'all') AS app_id\\n\" +\n                \"\\t, if(ver IS NOT NULL, ver, 'all') AS dycg_ver\\n\" +\n                \"\\t, if(machine_dc IS NOT NULL, machine_dc, 'all') AS machine_dc\\n\" +\n                \"\\t, if(game_id IS NOT NULL, game_id, 'all') AS game_id\\n\" +\n                \"\\t, sum(CASE\\n\" +\n                \"\\t\\tWHEN current_step = 6\\n\" +\n                \"\\t\\t\\tOR current_step = 7\\n\" +\n                \"\\t\\tTHEN 1\\n\" +\n                \"\\t\\tELSE 0\\n\" +\n                \"\\tEND) AS reach_game_process_cnt\\n\" +\n                \"\\t, sum(CASE\\n\" +\n                \"\\t\\tWHEN current_step = 5\\n\" +\n                \"\\t\\t\\tOR current_step = 6\\n\" +\n                \"\\t\\t\\tOR current_step = 7\\n\" +\n                \"\\t\\tTHEN 1\\n\" +\n                \"\\t\\tELSE 0\\n\" +\n                \"\\tEND) AS tot_reach_game_process_cnt\\n\" +\n                \"\\t, round(1 - (sum(CASE\\n\" +\n                \"\\t\\tWHEN current_step = 5 THEN 1\\n\" +\n                \"\\t\\tELSE 0\\n\" +\n                \"\\tEND) / sum(CASE\\n\" +\n                \"\\t\\tWHEN current_step = 5\\n\" +\n                \"\\t\\t\\tOR current_step = 6\\n\" +\n                \"\\t\\t\\tOR current_step = 7\\n\" +\n                \"\\t\\tTHEN 1\\n\" +\n                \"\\t\\tELSE 0\\n\" +\n                \"\\tEND)), 4) AS reach_game_process_rate\\n\" +\n                \"\\t, from_unixtime(unix_timestamp(CAST(${dt_hour} AS string), 'yyyyMMddHH'), 'yyyy-MM-dd') AS dt\\n\" +\n                \"\\t, substring(${dt_hour}, 9, 2) AS `hour`\\n\" +\n                \"FROM dycg_perform_startgametaketimelog\\n\" +\n                \"GROUP BY app_id, ver, machine_dc, game_id\\n\" +\n                \"\\tGROUPING SETS ((app_id), (app_id, ver), (app_id, ver, machine_dc), (app_id, ver, game_id), (app_id, machine_dc), (app_id, machine_dc, game_id), (app_id, game_id), (app_id, ver, machine_dc, game_id))\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_43_bug.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.hive.ast.HiveMultiInsertStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_43_bug {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"from (select a.ddate\\n\" +\n                \"        ,a.game_id\\n\" +\n                \"        ,a.plat_id\\n\" +\n                \"        ,a.channel_group_id\\n\" +\n                \"        ,a.channel_id\\n\" +\n                \"        ,a.zone_id\\n\" +\n                \"        ,a.player_id\\n\" +\n                \"        ,pay_amt_1d\\n\" +\n                \"        ,pay_cnt_1d\\n\" +\n                \"        ,CASE WHEN actv_day_num_td = 0 THEN 0 \\n\" +\n                \"              WHEN actv_day_num_td<=3 THEN 1\\n\" +\n                \"              WHEN actv_day_num_td<=6 THEN 2 \\n\" +\n                \"              WHEN actv_day_num_td<=13 THEN 3\\n\" +\n                \"              WHEN actv_day_num_td<=21 THEN 4\\n\" +\n                \"              WHEN actv_day_num_td<=30 THEN 5\\n\" +\n                \"              WHEN actv_day_num_td<=60 THEN 6\\n\" +\n                \"              WHEN actv_day_num_td<=90 THEN 7\\n\" +\n                \"              WHEN actv_day_num_td>90 THEN 99 \\n\" +\n                \"              ELSE NULL END AS actv_day_num_td_segment_id     \\n\" +\n                \"        ,CASE WHEN reg_day_num_td = 0 THEN 0 \\n\" +\n                \"              WHEN reg_day_num_td<=3 THEN 1\\n\" +\n                \"              WHEN reg_day_num_td<=6 THEN 2 \\n\" +\n                \"              WHEN reg_day_num_td<=13 THEN 3\\n\" +\n                \"              WHEN reg_day_num_td<=21 THEN 4\\n\" +\n                \"              WHEN reg_day_num_td<=30 THEN 5\\n\" +\n                \"              WHEN reg_day_num_td<=60 THEN 6\\n\" +\n                \"              WHEN reg_day_num_td<=90 THEN 7\\n\" +\n                \"              WHEN reg_day_num_td>90 THEN 99 \\n\" +\n                \"              ELSE NULL END AS reg_day_num_td_segment_id \\n\" +\n                \"  from   (select ddate\\n\" +\n                \"                ,game_id\\n\" +\n                \"                ,plat_id\\n\" +\n                \"                ,channel_group_id\\n\" +\n                \"                ,channel_id\\n\" +\n                \"                ,zone_id\\n\" +\n                \"                ,player_id\\n\" +\n                \"                ,pay_amt_1d\\n\" +\n                \"                ,pay_cnt_1d\\n\" +\n                \"          from   dws_game_sdk_base.dws_game_sdk_pay_user_base_d a\\n\" +\n                \"          where  a.ddate >= '20200512'\\n\" +\n                \"          and    a.ddate < '20200513'\\n\" +\n                \"          and    a.first_pay_flag = 1) a\\n\" +\n                \"  inner  join (select ddate\\n\" +\n                \"                    ,game_id\\n\" +\n                \"                    ,plat_id\\n\" +\n                \"                    ,channel_group_id\\n\" +\n                \"                    ,channel_id\\n\" +\n                \"                    ,zone_id\\n\" +\n                \"                    ,player_id\\n\" +\n                \"                    ,actv_day_num_td\\n\" +\n                \"                    ,udf.datediff(ddate, reg_date) as reg_day_num_td\\n\" +\n                \"              from   dws_game_sdk_base.dws_game_sdk_user_actv_base_d a\\n\" +\n                \"              where  a.ddate >= '20200512'\\n\" +\n                \"              and    a.ddate < '20200513') b\\n\" +\n                \"  on     (a.ddate = b.ddate and a.game_id = b.game_id and\\n\" +\n                \"         a.plat_id = b.plat_id and a.channel_group_id = b.channel_group_id and\\n\" +\n                \"         a.channel_id = b.channel_id and a.zone_id = b.zone_id and\\n\" +\n                \"         a.player_id = b.player_id) ) d \\n\" +\n                \"INSERT OVERWRITE TABLE ads_game_sdk_base.ads_rpt_game_sdk_user_segment_d PARTITION(ddate,segment_type,user_type_id)\\n\" +\n                \"SELECT  game_id\\n\" +\n                \"    ,plat_id\\n\" +\n                \"    ,channel_group_id\\n\" +\n                \"    ,channel_id\\n\" +\n                \"    ,zone_id\\n\" +\n                \"    ,actv_day_num_td_segment_id AS segment_id\\n\" +\n                \"    ,CASE    WHEN actv_day_num_td_segment_id = 0 THEN '0天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 1 THEN '1~3天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 2 THEN '4~6天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 3 THEN '7~13天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 4 THEN '14~21天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 5 THEN '21~30天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 6 THEN '30~60天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 7 THEN '60~90天'\\n\" +\n                \"             WHEN actv_day_num_td_segment_id = 99 THEN '>90天' \\n\" +\n                \"     END AS segment_name\\n\" +\n                \"    ,COUNT(1) AS segment_user_num_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_value_sum_1d\\n\" +\n                \"    ,SUM(pay_cnt_1d) AS segment_ext_int_value1_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_ext_int_value2_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_ext_int_value3_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_ext_int_value1_4d\\n\" +\n                \"    ,SUM(pay_amt_1d) AS segment_ext_int_value4_1d\\n\" +\n                \"    ,CAST(NULL AS DOUBLE) AS segment_ext_double_value2_1d\\n\" +\n                \"    ,CAST(NULL AS DOUBLE) AS segment_ext_double_value3_1d\\n\" +\n                \"    ,CAST(NULL AS DOUBLE) AS segment_ext_double_value4_1d\\n\" +\n                \"    ,ddate\\n\" +\n                \"    ,'first_pay_user_actv_day_num' AS segment_type\\n\" +\n                \"    ,3 AS user_type_id\\n\" +\n                \"WHERE   actv_day_num_td_segment_id IS NOT NULL\\n\" +\n                \"GROUP BY ddate\\n\" +\n                \"     ,game_id\\n\" +\n                \"     ,plat_id\\n\" +\n                \"     ,channel_group_id\\n\" +\n                \"     ,channel_id\\n\" +\n                \"     ,zone_id\\n\" +\n                \"     ,actv_day_num_td_segment_id\\n\" +\n                \"INSERT OVERWRITE TABLE ads_game_sdk_base.ads_rpt_game_sdk_user_segment_d PARTITION(ddate,segment_type,user_type_id)\\n\" +\n                \"SELECT  game_id\\n\" +\n                \"    ,plat_id\\n\" +\n                \"    ,channel_group_id\\n\" +\n                \"    ,channel_id\\n\" +\n                \"    ,zone_id\\n\" +\n                \"    ,reg_day_num_td_segment_id AS segment_id\\n\" +\n                \"    ,CASE    WHEN reg_day_num_td_segment_id = 0 THEN '0天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 1 THEN '1~3天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 2 THEN '4~6天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 3 THEN '7~13天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 4 THEN '14~21天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 5 THEN '21~30天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 6 THEN '30~60天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 7 THEN '60~90天'\\n\" +\n                \"             WHEN reg_day_num_td_segment_id = 99 THEN '>90天' \\n\" +\n                \"     END AS segment_name\\n\" +\n                \"    ,COUNT(1) AS segment_user_num_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_value_sum_1d\\n\" +\n                \"    ,SUM(pay_cnt_1d) AS segment_ext_int_value1_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_ext_int_value2_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_ext_int_value3_1d\\n\" +\n                \"    ,CAST(NULL AS BIGINT) AS segment_ext_int_value1_4d\\n\" +\n                \"    ,SUM(pay_amt_1d) AS segment_ext_int_value4_1d\\n\" +\n                \"    ,CAST(NULL AS DOUBLE) AS segment_ext_double_value2_1d\\n\" +\n                \"    ,CAST(NULL AS DOUBLE) AS segment_ext_double_value3_1d\\n\" +\n                \"    ,CAST(NULL AS DOUBLE) AS segment_ext_double_value4_1d\\n\" +\n                \"    ,ddate\\n\" +\n                \"    ,'first_pay_user_reg_day_num' AS segment_type\\n\" +\n                \"    ,3 AS user_type_id\\n\" +\n                \"WHERE   reg_day_num_td_segment_id IS NOT NULL\\n\" +\n                \"GROUP BY ddate\\n\" +\n                \"     ,game_id\\n\" +\n                \"     ,plat_id\\n\" +\n                \"     ,channel_group_id\\n\" +\n                \"     ,channel_id\\n\" +\n                \"     ,zone_id\\n\" +\n                \"     ,reg_day_num_td_segment_id\\n\" +\n                \";\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive);\n        HiveMultiInsertStatement stmt = (HiveMultiInsertStatement) statementList.get(0);\n\n        assertEquals(\"FROM (\\n\" +\n                \"\\tSELECT a.ddate, a.game_id, a.plat_id, a.channel_group_id, a.channel_id\\n\" +\n                \"\\t\\t, a.zone_id, a.player_id, pay_amt_1d, pay_cnt_1d\\n\" +\n                \"\\t\\t, CASE\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td = 0 THEN 0\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td <= 3 THEN 1\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td <= 6 THEN 2\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td <= 13 THEN 3\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td <= 21 THEN 4\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td <= 30 THEN 5\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td <= 60 THEN 6\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td <= 90 THEN 7\\n\" +\n                \"\\t\\t\\tWHEN actv_day_num_td > 90 THEN 99\\n\" +\n                \"\\t\\t\\tELSE NULL\\n\" +\n                \"\\t\\tEND AS actv_day_num_td_segment_id\\n\" +\n                \"\\t\\t, CASE\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td = 0 THEN 0\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td <= 3 THEN 1\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td <= 6 THEN 2\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td <= 13 THEN 3\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td <= 21 THEN 4\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td <= 30 THEN 5\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td <= 60 THEN 6\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td <= 90 THEN 7\\n\" +\n                \"\\t\\t\\tWHEN reg_day_num_td > 90 THEN 99\\n\" +\n                \"\\t\\t\\tELSE NULL\\n\" +\n                \"\\t\\tEND AS reg_day_num_td_segment_id\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT ddate, game_id, plat_id, channel_group_id, channel_id\\n\" +\n                \"\\t\\t\\t, zone_id, player_id, pay_amt_1d, pay_cnt_1d\\n\" +\n                \"\\t\\tFROM dws_game_sdk_base.dws_game_sdk_pay_user_base_d a\\n\" +\n                \"\\t\\tWHERE a.ddate >= '20200512'\\n\" +\n                \"\\t\\t\\tAND a.ddate < '20200513'\\n\" +\n                \"\\t\\t\\tAND a.first_pay_flag = 1\\n\" +\n                \"\\t) a\\n\" +\n                \"\\t\\tINNER JOIN (\\n\" +\n                \"\\t\\t\\tSELECT ddate, game_id, plat_id, channel_group_id, channel_id\\n\" +\n                \"\\t\\t\\t\\t, zone_id, player_id, actv_day_num_td\\n\" +\n                \"\\t\\t\\t\\t, udf.datediff(ddate, reg_date) AS reg_day_num_td\\n\" +\n                \"\\t\\t\\tFROM dws_game_sdk_base.dws_game_sdk_user_actv_base_d a\\n\" +\n                \"\\t\\t\\tWHERE a.ddate >= '20200512'\\n\" +\n                \"\\t\\t\\t\\tAND a.ddate < '20200513'\\n\" +\n                \"\\t\\t) b\\n\" +\n                \"\\t\\tON (a.ddate = b.ddate\\n\" +\n                \"\\t\\t\\tAND a.game_id = b.game_id\\n\" +\n                \"\\t\\t\\tAND a.plat_id = b.plat_id\\n\" +\n                \"\\t\\t\\tAND a.channel_group_id = b.channel_group_id\\n\" +\n                \"\\t\\t\\tAND a.channel_id = b.channel_id\\n\" +\n                \"\\t\\t\\tAND a.zone_id = b.zone_id\\n\" +\n                \"\\t\\t\\tAND a.player_id = b.player_id)\\n\" +\n                \") d\\n\" +\n                \"INSERT OVERWRITE TABLE ads_game_sdk_base.ads_rpt_game_sdk_user_segment_d PARTITION (ddate, segment_type, user_type_id)\\n\" +\n                \"SELECT game_id, plat_id, channel_group_id, channel_id, zone_id\\n\" +\n                \"\\t, actv_day_num_td_segment_id AS segment_id\\n\" +\n                \"\\t, CASE\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 0 THEN '0天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 1 THEN '1~3天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 2 THEN '4~6天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 3 THEN '7~13天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 4 THEN '14~21天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 5 THEN '21~30天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 6 THEN '30~60天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 7 THEN '60~90天'\\n\" +\n                \"\\t\\tWHEN actv_day_num_td_segment_id = 99 THEN '>90天'\\n\" +\n                \"\\tEND AS segment_name, COUNT(1) AS segment_user_num_1d, CAST(NULL AS BIGINT) AS segment_value_sum_1d\\n\" +\n                \"\\t, SUM(pay_cnt_1d) AS segment_ext_int_value1_1d, CAST(NULL AS BIGINT) AS segment_ext_int_value2_1d, CAST(NULL AS BIGINT) AS segment_ext_int_value3_1d\\n\" +\n                \"\\t, CAST(NULL AS BIGINT) AS segment_ext_int_value1_4d, SUM(pay_amt_1d) AS segment_ext_int_value4_1d, CAST(NULL AS DOUBLE) AS segment_ext_double_value2_1d, CAST(NULL AS DOUBLE) AS segment_ext_double_value3_1d\\n\" +\n                \"\\t, CAST(NULL AS DOUBLE) AS segment_ext_double_value4_1d, ddate\\n\" +\n                \"\\t, 'first_pay_user_actv_day_num' AS segment_type, 3 AS user_type_id\\n\" +\n                \"WHERE actv_day_num_td_segment_id IS NOT NULL\\n\" +\n                \"GROUP BY ddate, game_id, plat_id, channel_group_id, channel_id, zone_id, actv_day_num_td_segment_id\\n\" +\n                \"INSERT OVERWRITE TABLE ads_game_sdk_base.ads_rpt_game_sdk_user_segment_d PARTITION (ddate, segment_type, user_type_id)\\n\" +\n                \"SELECT game_id, plat_id, channel_group_id, channel_id, zone_id\\n\" +\n                \"\\t, reg_day_num_td_segment_id AS segment_id\\n\" +\n                \"\\t, CASE\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 0 THEN '0天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 1 THEN '1~3天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 2 THEN '4~6天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 3 THEN '7~13天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 4 THEN '14~21天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 5 THEN '21~30天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 6 THEN '30~60天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 7 THEN '60~90天'\\n\" +\n                \"\\t\\tWHEN reg_day_num_td_segment_id = 99 THEN '>90天'\\n\" +\n                \"\\tEND AS segment_name, COUNT(1) AS segment_user_num_1d, CAST(NULL AS BIGINT) AS segment_value_sum_1d\\n\" +\n                \"\\t, SUM(pay_cnt_1d) AS segment_ext_int_value1_1d, CAST(NULL AS BIGINT) AS segment_ext_int_value2_1d, CAST(NULL AS BIGINT) AS segment_ext_int_value3_1d\\n\" +\n                \"\\t, CAST(NULL AS BIGINT) AS segment_ext_int_value1_4d, SUM(pay_amt_1d) AS segment_ext_int_value4_1d, CAST(NULL AS DOUBLE) AS segment_ext_double_value2_1d, CAST(NULL AS DOUBLE) AS segment_ext_double_value3_1d\\n\" +\n                \"\\t, CAST(NULL AS DOUBLE) AS segment_ext_double_value4_1d, ddate\\n\" +\n                \"\\t, 'first_pay_user_reg_day_num' AS segment_type, 3 AS user_type_id\\n\" +\n                \"WHERE reg_day_num_td_segment_id IS NOT NULL\\n\" +\n                \"GROUP BY ddate, game_id, plat_id, channel_group_id, channel_id, zone_id, reg_day_num_td_segment_id;\", stmt.toString());\n\n//        SQLUtils.toSQLString(stmt, DbType.hive)\n        SQLParseAssertUtil.assertParseSql(sql, DbType.hive);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_44_issue_3973.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_44_issue_3973 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"WITH t AS (SELECT * FROM t1 ) INSERT OVERWRITE TABLE t2 SELECT * FROM t;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"WITH t AS (\\n\" +\n                \"\\t\\tSELECT *\\n\" +\n                \"\\t\\tFROM t1\\n\" +\n                \"\\t)\\n\" +\n                \"INSERT OVERWRITE TABLE t2\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM t;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_45_issue_3987.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_45_issue_3987 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select id,number_id,parent_id,layer_id,alias,name \\n\" +\n                \"from (select id,number_id,parent_id,layer_id,alias,name,row_number() over(distribute by number_id sort by create_time desc,id desc) rownum from hdw_ods.ods_my_coredata__dts_device_category where pdate ='') m where m.rownum = 1\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.hive);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"SELECT id, number_id, parent_id, layer_id, alias\\n\" +\n                \"\\t, name\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT id, number_id, parent_id, layer_id, alias\\n\" +\n                \"\\t\\t, name, row_number() OVER (DISTRIBUTE BY number_id SORT BY create_time DESC, id DESC) AS rownum\\n\" +\n                \"\\tFROM hdw_ods.ods_my_coredata__dts_device_category\\n\" +\n                \"\\tWHERE pdate = ''\\n\" +\n                \") m\\n\" +\n                \"WHERE m.rownum = 1\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_47.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_47 {\n    static String sql = \"with temp1 AS ( \\n\" +\n            \"    SELECT datetrunc(gmv_time,'mm') as report_month\\n\" +\n            \"    ,seller_user_id\\n\" +\n            \"    ,count(1) as 卖家订单量\\n\" +\n            \"    from du_shucang.dm_ord_sub_order a \\n\" +\n            \"    where pt = max_pt('du_shucang.dm_ord_sub_order')\\n\" +\n            \"    and pay_status = 1 \\n\" +\n            \"    group by datetrunc(gmv_time,'mm'),seller_user_id\\n\" +\n            \")\\n\" +\n            \",temp2 AS ( \\n\" +\n            \"    -- SELECT gmv_time,a.sub_order_no,a.buyer_user_id\\n\" +\n            \"    -- ,ROW_NUMBER() OVER(PARTITION BY a.buyer_user_id ORDER BY gmv_time) AS order_rank \\n\" +\n            \"    -- from du_shucang.dm_ord_sub_order a \\n\" +\n            \"    -- where pt = max_pt('du_shucang.dm_ord_sub_order')\\n\" +\n            \"    -- and pay_status = 1 \\n\" +\n            \"    SELECT user_id,first_activat_time\\n\" +\n            \"    from du_shucang.dw_usr_user_order_extend \\n\" +\n            \"    where pt = max_pt('du_shucang.dw_usr_user_order_extend')\\n\" +\n            \")\\n\" +\n            \"SELECT datetrunc(a.gmv_time,'mm') as report_month\\n\" +\n            \",'' GMV\\n\" +\n            \"    ,sum(total_amount*0.01) as 支付gmv \\n\" +\n            \"    ,sum(buyer_discount_amount*0.01) as 买家优惠金额\\n\" +\n            \"    ,sum(buyer_discount_amount*0.01)/nullif(sum(total_amount*0.01),0) as 优惠占比 \\n\" +\n            \"    ------支付gmv-----\\n\" +\n            \"    ,sum(a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01) 支付gmv不含优惠\\n\" +\n            \"    ,sum(case when c.user_id is not null  then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01 end) 支付gmv不含优惠_新用户\\n\" +\n            \"    ,sum(case when c.user_id is null then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01 end) 支付gmv不含优惠_老用户\\n\" +\n            \"        ----未交付\\n\" +\n            \"    ,sum(case when sub_order_status_desc <> '交易成功' then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01 end) as 未交付gmv不含优惠\\n\" +\n            \"    ,sum(case when c.user_id is not null and sub_order_status_desc <> '交易成功' then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01 end) as 未交付gmv不含优惠_新用户\\n\" +\n            \"    ,sum(case when c.user_id is null and sub_order_status_desc <> '交易成功' then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01 end) as 未交付gmv不含优惠_老用户\\n\" +\n            \"    ----交付\\n\" +\n            \"    ,sum(case when sub_order_status_desc = '交易成功' then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01end) as 交付gmv不含优惠\\n\" +\n            \"    ,sum(case when c.user_id is not null and sub_order_status_desc = '交易成功' then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01end) as 交付gmv不含优惠_新用户\\n\" +\n            \"    ,sum(case when c.user_id is null  and sub_order_status_desc = '交易成功' then a.total_price*0.01 + buyer_freight_amount*0.01 - buyer_discount_amount*0.01end) as 交付gmv不含优惠_老用户\\n\" +\n            \"    ----未交付\\n\" +\n            \"    ,sum(case when sub_order_status_desc <> '交易成功' then total_amount*0.01 end) as 未交付gmv\\n\" +\n            \"    ,sum(case when c.user_id is not null and sub_order_status_desc <> '交易成功' then total_amount*0.01 end) as 未交付gmv_新用户\\n\" +\n            \"    ,sum(case when c.user_id is null and sub_order_status_desc <> '交易成功' then total_amount*0.01 end) as 未交付gmv_老用户\\n\" +\n            \"    ----交付\\n\" +\n            \"    ,sum(case when sub_order_status_desc = '交易成功' then total_amount*0.01 end) as 交付gmv\\n\" +\n            \"    ,sum(case when c.user_id is not null and sub_order_status_desc = '交易成功' then total_amount*0.01 end) as 交付gmv_新用户\\n\" +\n            \"    ,sum(case when c.user_id is null and sub_order_status_desc = '交易成功' then total_amount*0.01 end) as 交付gmv_老用户\\n\" +\n            \",'' 订单量\\n\" +\n            \"    ,count(distinct a.sub_order_no) as 支付订单量\\n\" +\n            \"    ,count(distinct case when c.user_id is not null then a.sub_order_no end) as 支付订单量_新用户\\n\" +\n            \"    ,count(distinct case when c.user_id is null then a.sub_order_no end) as 支付订单量_老用户\\n\" +\n            \"\\n\" +\n            \"    ,count(distinct case when sub_order_status_desc <> '交易成功' then a.sub_order_no end) as 未交付订单量\\n\" +\n            \"    ,count(distinct case when c.user_id is not null and sub_order_status_desc <> '交易成功' then a.sub_order_no end) as 未交付订单量_新用户\\n\" +\n            \"    ,count(distinct case when c.user_id is null and sub_order_status_desc <> '交易成功' then a.sub_order_no end) as 未交付订单量_老用户\\n\" +\n            \"\\n\" +\n            \"    ,count(distinct case when sub_order_status_desc = '交易成功' then a.sub_order_no end) as 交付订单量\\n\" +\n            \"    ,count(distinct case when c.user_id is not null and sub_order_status_desc = '交易成功' then a.sub_order_no end) as 交付订单量_新用户\\n\" +\n            \"    ,count(distinct case when c.user_id is null and sub_order_status_desc = '交易成功' then a.sub_order_no end) as 交付订单量_老用户\\n\" +\n            \",'' 价单价\\n\" +\n            \"    ,sum(total_amount*0.01)/nullif(count(distinct a.sub_order_no),0) as 支付件单价\\n\" +\n            \"    ,sum(case when c.user_id is not null then total_amount*0.01 end)/nullif(count(distinct case when c.user_id is not null then a.sub_order_no end),0) as 支付件单价_新用户\\n\" +\n            \"    ,sum(case when c.user_id is null then total_amount*0.01 end)/nullif(count(distinct case when c.user_id is null then a.sub_order_no end),0) as 支付件单价_老用户\\n\" +\n            \",'' 下单人数\\n\" +\n            \"    ,count(distinct a.buyer_user_id) as 支付下单人数\\n\" +\n            \"    ,count(distinct case when c.user_id is not null then a.buyer_user_id end) as 支付下单人数_新用户\\n\" +\n            \"    ,count(distinct case when c.user_id is null then a.buyer_user_id end) as 支付下单人数_老用户\\n\" +\n            \"\\n\" +\n            \"    ,count(distinct case when sub_order_status_desc = '交易成功' then a.buyer_user_id end) as 交付下单人数\\n\" +\n            \"    ,count(distinct case when c.user_id is not null  and sub_order_status_desc = '交易成功' then a.buyer_user_id end) as 交付下单人数_新用户\\n\" +\n            \"    ,count(distinct case when c.user_id is null and sub_order_status_desc = '交易成功' then a.buyer_user_id end) as 交付下单人数_老用户\\n\" +\n            \"\\n\" +\n            \"    ,count(distinct a.sub_order_no)/nullif(count(distinct a.buyer_user_id),0) as 支付下单频次\\n\" +\n            \"    ,count(distinct case when c.user_id is not null then a.sub_order_no end)/nullif(count(distinct case when c.user_id is not null then a.buyer_user_id end),0) as 支付下单频次_新用户\\n\" +\n            \"    ,count(distinct case when c.user_id is null then a.sub_order_no end)/nullif(count(distinct case when c.user_id is null then a.buyer_user_id end),0) as 支付下单频次_老用户\\n\" +\n            \"\\n\" +\n            \"    ,count(distinct case when sub_order_status_desc = '交易成功' then a.sub_order_no end)/nullif(count(distinct case when sub_order_status_desc = '交易成功' then a.buyer_user_id end),0) as 交付下单频次\\n\" +\n            \"    ,count(distinct case when c.user_id is not null  and sub_order_status_desc = '交易成功' then a.sub_order_no end)/nullif(count(distinct case when c.user_id is not null  and sub_order_status_desc = '交易成功'then a.buyer_user_id end),0) as 交付下单频次_新用户\\n\" +\n            \"    ,count(distinct case when c.user_id is null and sub_order_status_desc = '交易成功' then a.sub_order_no end)/nullif(count(distinct case when c.user_id is null and sub_order_status_desc = '交易成功' then a.buyer_user_id end),0) as 交付下单频次_老用户\\n\" +\n            \"\\n\" +\n            \"    ,sum(total_amount*0.01)/nullif(count(distinct a.buyer_user_id),0) as ARPU\\n\" +\n            \"    ,sum(case when c.user_id is not null then total_amount*0.01 end)/nullif(count(distinct case when c.user_id is not null  then a.buyer_user_id end),0) as ARPU_新用户\\n\" +\n            \"    ,sum(case when c.user_id is null then total_amount*0.01 end)/nullif(count(distinct case when c.user_id is null then a.buyer_user_id end),0) as ARPU_老用户\\n\" +\n            \"    \\n\" +\n            \"    ,count(distinct a.seller_user_id) as 当月卖家人数\\n\" +\n            \"    ,count(distinct case when b.卖家订单量 > 50 then a.seller_user_id end) as 订单量每月50单以上卖家数\\n\" +\n            \"    ,count(distinct case when b.卖家订单量 >= 11 and b.卖家订单量 <= 50 then a.seller_user_id end) as 订单量每月11_5卖家数\\n\" +\n            \"    ,count(distinct case when b.卖家订单量 >= 6 and b.卖家订单量 <= 10 then a.seller_user_id end) as 订单量每月6_10卖家数\\n\" +\n            \"    ,count(distinct case when b.卖家订单量 >= 1 and b.卖家订单量 <= 5 then a.seller_user_id end) as 订单量每月1_5卖家数\\n\" +\n            \"    ,count(distinct case when b.卖家订单量 >= 1 and b.卖家订单量 <= 5 then a.seller_user_id end)/count(distinct a.seller_user_id) as 月1_5卖家数占比\\n\" +\n            \"\\n\" +\n            \"    ,count(distinct case when category_lv3_name = '篮球鞋' then a.sub_order_no end) as 篮球鞋支付订单量\\n\" +\n            \"    ,count(distinct case when category_lv3_name = '跑步鞋' then a.sub_order_no end) as 跑步鞋支付订单量\\n\" +\n            \"    ,count(distinct case when category_lv2_name = '休闲鞋' then a.sub_order_no end) as 休闲鞋支付订单量\\n\" +\n            \"    ,count(distinct case when category_lv1_name = '服装' then a.sub_order_no end) as 服装支付订单量\\n\" +\n            \"    ,count(distinct case when category_lv1_name <> '服装' and category_lv2_name not in ('休闲鞋') and category_lv3_name not in ('篮球鞋','跑步鞋') then a.sub_order_no end) as 其他支付订单量\\n\" +\n            \"\\n\" +\n            \"    ,count(case when category_lv3_name = '篮球鞋' then sku_id end) as 篮球鞋sku数量\\n\" +\n            \"    ,count(case when category_lv3_name = '跑步鞋' then sku_id end) as 跑步鞋sku数量\\n\" +\n            \"    ,count(case when category_lv2_name = '休闲鞋' then sku_id end) as 休闲鞋sku数量\\n\" +\n            \"    ,count(case when category_lv1_name = '服装' then sku_id end) as 服装支付sku数量\\n\" +\n            \"    ,count(case when category_lv1_name <> '服装' and category_lv2_name not in ('休闲鞋') and category_lv3_name not in ('篮球鞋','跑步鞋') then sku_id end) as 其他支付sku数量\\n\" +\n            \"\\n\" +\n            \"from du_shucang.dm_ord_sub_order a \\n\" +\n            \"left join temp2 c on a.buyer_user_id = c.user_id and datetrunc(a.gmv_time,'mm') = datetrunc(c.first_activat_time,'mm')\\n\" +\n            \"left join temp1 b on datetrunc(a.gmv_time,'mm') = b.report_month and a.seller_user_id = b.seller_user_id \\n\" +\n            \"where a.pt = max_pt('du_shucang.dm_ord_sub_order')\\n\" +\n            \"and a.pay_status = 1 and datetrunc(a.gmv_time,'dd') >= '2017-08-01 00:00:00'\\n\" +\n            \"group by datetrunc(a.gmv_time,'mm') \\n\" +\n            \";\";\n\n    @Test\n    public void test_select() throws Exception {\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n//\n//        assertEquals(1, visitor.getTables().size());\n//        assertEquals(2, visitor.getColumns().size());\n//        assertEquals(2, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_48.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectItem;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class HiveSelectTest_48 {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"SELECT account_id FROM taobao_office.cloud_yunpan WHERE dt='2021-04-12' AND target='update'\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement sqlStatement = stmtList.get(0);\n        SQLSelectStatement stmt = (SQLSelectStatement) sqlStatement;\n        List<SQLSelectItem> list = ((SQLSelectQueryBlock) stmt.getSelect().getQuery()).getSelectList();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_4_array.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_4_array\n {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"select religions['catholic'][0] from json_nested_test;\";\n        assertEquals(\"SELECT religions['catholic'][0]\\n\" +\n                \"FROM json_nested_test;\", SQLUtils.formatHive(sql));\n        assertEquals(\"select religions['catholic'][0]\\n\" +\n                \"from json_nested_test;\", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//      System.out.println(\"coditions : \" + visitor.getConditions());\n//      System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"json_nested_test\", \"religions\"));\n//        assertTrue(visitor.containsColumn(\"customers\", \"isxx\"));\n//        assertTrue(visitor.containsColumn(\"customers\", \"*\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_cluster_by.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_cluster_by\n {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT a from x cluster by a;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"SELECT a\\n\" +\n                \"FROM x\\n\" +\n                \"CLUSTER BY a;\", stmt.toString());\n\n        assertEquals(\"SELECT a\\n\" +\n                \"FROM x\\n\" +\n                \"CLUSTER BY a;\", SQLUtils.toSQLString(stmt));\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n        System.out.println(\"groupBy : \" + visitor.getGroupByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getGroupByColumns().size());\n\n        assertTrue(visitor.containsColumn(\"x\", \"a\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_distribute.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.testutil.ParserTestUtils;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveSelectTest_distribute\n {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select * from LD_aly.fct_pay_ord_cn_di t1 distribute by buyer_id sort by seller_id\";\n\n        SQLStatement stmt = ParserTestUtils.parseSingleStatement(sql, JdbcConstants.HIVE);\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM LD_aly.fct_pay_ord_cn_di t1\\n\" +\n                \"DISTRIBUTE BY buyer_id\\n\" +\n                \"SORT BY seller_id\", stmt.toString());\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM LD_aly.fct_pay_ord_cn_di t1\\n\" +\n                \"DISTRIBUTE BY buyer_id\\n\" +\n                \"SORT BY seller_id\", SQLUtils.toSQLString(stmt));\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE);\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n        System.out.println(\"groupBy : \" + visitor.getGroupByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getGroupByColumns().size());\n\n        assertTrue(visitor.containsColumn(\"LD_aly.fct_pay_ord_cn_di\", \"*\"));\n        assertTrue(visitor.containsColumn(\"LD_aly.fct_pay_ord_cn_di\", \"buyer_id\"));\n        assertTrue(visitor.containsColumn(\"LD_aly.fct_pay_ord_cn_di\", \"seller_id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSetTest_1.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author lizongbo\n */\npublic class HiveSetTest_1 {\n    static String sql1 = \"set hivevar:exp_id = 8001\\n\" +\n        \";\";\n\n    static String sql2 = \"set hivevar:exp_id = \\\"8001\\\"\\n\" +\n        \";\";\n\n    static String sql3 = \"set hivevar.exp_id = 8001\\n\" +\n        \";\";\n\n    static String sql4 = \"set hivevar.exp_id = \\\"8001\\\"\\n\" +\n        \";\";\n    @Test\n    public void test_setHiveVar1() throws Exception {\n        {\n            DbType dbType = JdbcConstants.ODPS;\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql1, dbType);\n            SQLStatement stmt = statementList.get(0);\n            //System.out.println(dbType + \"==\" + statementList);\n            assertEquals(1, statementList.size());\n            //这里会多一个换行符， SQLExprParser的第 5259行针对ODPS类型，调用的是nextTokenForSet，而不是走nextToken，不敢随便改，先这样吧\n            assertEquals(\"SET hivevar:exp_id = 8001\\n;\", stmt.toString());\n        }\n        {\n            DbType dbType = JdbcConstants.HIVE;\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql1, dbType);\n            SQLStatement stmt = statementList.get(0);\n            //System.out.println(dbType + \"==\" + statementList);\n            assertEquals(1, statementList.size());\n            assertEquals(\"SET hivevar:exp_id = 8001;\", stmt.toString());\n        }\n\n    }\n\n    @Test\n    public void test_setHiveVar2() throws Exception {\n        for (DbType dbType : new DbType[]{JdbcConstants.ODPS, JdbcConstants.HIVE}) {\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql2, dbType);\n            SQLStatement stmt = statementList.get(0);\n            //System.out.println(dbType + \"==\" + statementList);\n            assertEquals(1, statementList.size());\n            assertEquals(\"SET hivevar:exp_id = '8001';\", stmt.toString());\n\n        }\n\n    }\n\n    @Test\n    public void test_setHiveVar3() throws Exception {\n        {\n            DbType dbType = JdbcConstants.ODPS;\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql3, dbType);\n            SQLStatement stmt = statementList.get(0);\n            //System.out.println(dbType + \"==\" + statementList);\n            assertEquals(1, statementList.size());\n            //这里会多一个换行符， SQLExprParser的第 5259行针对ODPS类型，调用的是nextTokenForSet，而不是走nextToken，不敢随便改，先这样吧\n            assertEquals(\"SET hivevar.exp_id = 8001\\n;\", stmt.toString());\n        }\n        {\n            DbType dbType = JdbcConstants.HIVE;\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql3, dbType);\n            SQLStatement stmt = statementList.get(0);\n            //System.out.println(dbType + \"==\" + statementList);\n            assertEquals(1, statementList.size());\n            assertEquals(\"SET hivevar.exp_id = 8001;\", stmt.toString());\n        }\n\n    }\n\n    @Test\n    public void test_setHiveVar4() throws Exception {\n        for (DbType dbType : new DbType[]{JdbcConstants.ODPS, JdbcConstants.HIVE}) {\n            List<SQLStatement> statementList = SQLUtils.parseStatements(sql4, dbType);\n            SQLStatement stmt = statementList.get(0);\n            //System.out.println(dbType + \"==\" + statementList);\n            assertEquals(1, statementList.size());\n            assertEquals(\"SET hivevar.exp_id = '8001';\", stmt.toString());\n\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveUtilsTest.java",
    "content": "package com.alibaba.druid.bvt.sql.hive;\n\nimport com.alibaba.druid.util.HiveUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HiveUtilsTest {\n    @Test\n    public void test_for_hive() {\n        assertTrue(HiveUtils.isBuiltinDataType(\"STRING\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"VARCHAR\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"CHAR\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"DECIMAL\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"NUMERIC\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"TINYINT\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"BIGINT\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"BOOLEAN\"));\n        assertTrue(HiveUtils.isBuiltinDataType(\"INTERVAL\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/issues/Issue5430.java",
    "content": "package com.alibaba.druid.bvt.sql.hive.issues;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Name;\nimport com.alibaba.druid.support.logging.Log;\nimport com.alibaba.druid.support.logging.LogFactory;\nimport org.apache.commons.lang3.StringUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://github.com/alibaba/druid/issues/5430\">Issue 5430</a>\n * @see <a href=\"https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL\">Hive DDL</a>\n * @todo 还有4个SQL解析存在转义字符识别的问题，暂时忽略，等温少来解决识别问题吧\n */\npublic class Issue5430 {\n    private static final Log log = LogFactory.getLog(Issue5430.class);\n\n    @Test\n    public void test_createTable() throws Exception {\n        DbType dbType = DbType.hive;\n        int index = 0;\n        for (String sql : new String[]{\"Create table if not exists data01.test_20230830(a string ,b string) \"\n            + \"PARTITIONED BY (load_date date, org string) ROW FORMAT DELIMITED NULL DEFINED AS '' STORED AS ORC\",\n            \"Create table if not exists data01.test_20230830(a string ,b string) \"\n                + \"PARTITIONED BY (load_date date, org string) ROW FORMAT DELIMITED NULL DEFINED AS \\\"\\\" STORED AS ORC\",\n            \"Create table if not exists data01.test_20230830(a string ,b string) \"\n                + \"PARTITIONED BY (load_date date, org string) ROW FORMAT DELIMITED NULL DEFINED AS 'aa' STORED AS ORC\",\n            \"Create table if not exists data01.test_20230830(a string ,b string) \"\n                + \"PARTITIONED BY (load_date date, org string) ROW FORMAT DELIMITED NULL DEFINED AS \\\"aa\\\" STORED AS ORC\",\n            \"CREATE TABLE my_table(a string, b bigint)\\n\"\n                + \"ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'\\n\"\n                + \"STORED AS TEXTFILE\",\n            \"CREATE TABLE my_table(a string, b bigint)\\n\"\n                + \"ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.JsonSerDe'\\n\"\n                + \"STORED AS TEXTFILE\",\n            \"CREATE TABLE my_table(a string, b bigint) STORED AS JSONFILE\",\n            \"create table table_name (\\n\"\n                + \"  id                int,\\n\"\n                + \"  dtDontQuery       string,\\n\"\n                + \"  name              string\\n\"\n                + \")\\n\"\n                + \"partitioned by (date string)\",\n            \"CREATE TABLE page_view(viewTime INT, userid BIGINT,\\n\"\n                + \"     page_url STRING, referrer_url STRING,\\n\"\n                + \"     ip STRING COMMENT 'IP Address of the User')\\n\"\n                + \" COMMENT 'This is the page view table'\\n\"\n                + \" PARTITIONED BY(dt STRING, country STRING)\\n\"\n                + \" STORED AS SEQUENCEFILE\",\n            \"CREATE TABLE page_view(viewTime INT, userid BIGINT,\\n\"\n                + \"     page_url STRING, referrer_url STRING,\\n\"\n                + \"     ip STRING COMMENT 'IP Address of the User')\\n\"\n                + \" COMMENT 'This is the page view table'\\n\"\n                + \" PARTITIONED BY(dt STRING, country STRING)\\n\"\n                + \" ROW FORMAT DELIMITED\\n\"\n                + \"   FIELDS TERMINATED BY '\\\\001'\\n\"\n                + \"STORED AS SEQUENCEFILE\",\n            \"CREATE EXTERNAL TABLE page_view(viewTime INT, userid BIGINT,\\n\"\n                + \"     page_url STRING, referrer_url STRING,\\n\"\n                + \"     ip STRING COMMENT 'IP Address of the User',\\n\"\n                + \"     country STRING COMMENT 'country of origination')\\n\"\n                + \" COMMENT 'This is the staging page view table'\\n\"\n                + \" ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\\\054'\\n\"\n                + \" STORED AS TEXTFILE\\n\"\n                + \" LOCATION '<hdfs_location>'\",\n            \"CREATE TABLE list_bucket_single (key STRING, value STRING)\\n\"\n                + \"  SKEWED BY (key) ON (1,5,6) [STORED AS DIRECTORIES]\",\n            \"CREATE TABLE list_bucket_multiple (col1 STRING, col2 int, col3 STRING)\\n\"\n                + \"  SKEWED BY (col1, col2) ON (('s1',1), ('s3',3), ('s13',13), ('s78',78)) [STORED AS DIRECTORIES]\",\n            \"CREATE TEMPORARY TABLE list_bucket_multiple (col1 STRING, col2 int, col3 STRING)\",\n            \"CREATE TRANSACTIONAL TABLE transactional_table_test(key string, value string) PARTITIONED BY(ds string) STORED AS ORC\",\n            \"create table pk(id1 integer, id2 integer,\\n\"\n                + \"  primary key(id1, id2) disable novalidate)\",\n            \"create table fk(id1 integer, id2 integer,\\n\"\n                + \"  constraint c1 foreign key(id1, id2) references pk(id2, id1) disable novalidate)\",\n            \"create table constraints1(id1 integer UNIQUE disable novalidate, id2 integer NOT NULL,\\n\"\n                + \"  usr string DEFAULT current_user(), price double CHECK (price > 0 AND price <= 1000))\",\n            \"create table constraints2(id1 integer, id2 integer,\\n\"\n                + \"  constraint c1_unique UNIQUE(id1) disable novalidate)\",\n            \"create table constraints3(id1 integer, id2 integer,\\n\"\n                + \"  constraint c1_check CHECK(id1 + id2 > 0))\",\n            \"CREATE TABLE apachelog (\\n\"\n                + \"  host STRING,\\n\"\n                + \"  identity STRING,\\n\"\n                + \"  user STRING,\\n\"\n                + \"  time STRING,\\n\"\n                + \"  request STRING,\\n\"\n                + \"  status STRING,\\n\"\n                + \"  size STRING,\\n\"\n                + \"  referer STRING,\\n\"\n                + \"  agent STRING)\\n\"\n                + \"ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'\\n\"\n                + \"WITH SERDEPROPERTIES (\\n\"\n                + \"  \\\"input.regex\\\" = \\\"([^]*) ([^]*) ([^]*) (-|\\\\\\\\[^\\\\\\\\]*\\\\\\\\]) ([^ \\\\\\\"]*|\\\\\\\"[^\\\\\\\"]*\\\\\\\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \\\\\\\"]*|\\\\\\\".*\\\\\\\") ([^ \\\\\\\"]*|\\\\\\\".*\\\\\\\"))?\\\"\\n\"\n                + \")\\n\"\n                + \"STORED AS TEXTFILE;\",\n\n            \"CREATE TABLE my_table(a string, b string)\\n\"\n                + \"ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'\\n\"\n                + \"WITH SERDEPROPERTIES (\\n\"\n                + \"   \\\"separatorChar\\\" = \\\"\\\\t\\\",\\n\"\n                + \"   \\\"quoteChar\\\"     = \\\"'\\\",\\n\"\n                + \"   \\\"escapeChar\\\"    = \\\"\\\\\\\\\\\"\\n\"\n                + \")  \\n\"\n                + \"STORED AS TEXTFILE\",\n            \"CREATE TABLE new_key_value_store\\n\"\n                + \"   ROW FORMAT SERDE \\\"org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe\\\"\\n\"\n                + \"   STORED AS RCFile\\n\"\n                + \"   AS\\n\"\n                + \"SELECT (key % 1024) new_key, concat(key, value) key_value_pair\\n\"\n                + \"FROM key_value_store\\n\"\n                + \"SORT BY new_key, key_value_pair\",\n\n            \"CREATE TABLE page_view(viewTime INT, userid BIGINT,\\n\"\n                + \"     page_url STRING, referrer_url STRING,\\n\"\n                + \"     ip STRING COMMENT 'IP Address of the User')\\n\"\n                + \" COMMENT 'This is the page view table'\\n\"\n                + \" PARTITIONED BY(dt STRING, country STRING)\\n\"\n                + \" CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS\\n\"\n                + \" ROW FORMAT DELIMITED\\n\"\n                + \"   FIELDS TERMINATED BY '\\\\001'\\n\"\n                + \"   COLLECTION ITEMS TERMINATED BY '\\\\002'\\n\"\n                + \"   MAP KEYS TERMINATED BY '\\\\003'\\n\"\n                + \" STORED AS SEQUENCEFILE\",\n        }) {\n            index++;\n            if (index >= 21) {\n                continue;\n            }\n            String normalizeSql = normalizeSql(sql);\n            System.out.println(\"第\" + index + \"条原始的sql格式归一化===\" + normalizeSql);\n            SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n            SQLStatement statement = parser.parseStatement();\n            String newSql = statement.toString();\n            String normalizeNewSql = normalizeSql(newSql);\n            System.out.println(\"第\" + index + \"条生成的sql格式归一化===\" + normalizeNewSql);\n            assertEquals(normalizeSql.toLowerCase(), normalizeNewSql.toLowerCase());\n            if (!normalizeSql.equalsIgnoreCase(normalizeNewSql)) {\n                System.err.println(\"第\" + index + \"条是解析失败原始的sql===\" + normalizeSql);\n            }\n            //assertTrue(newSql.equalsIgnoreCase(sql));\n            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);\n            statement.accept(visitor);\n            System.out.println(\"getTables==\" + visitor.getTables());\n            Map<Name, TableStat> tableMap = visitor.getTables();\n            assertFalse(tableMap.isEmpty());\n\n        }\n    }\n\n    static String normalizeSql(String sql) {\n        sql = StringUtils.replace(sql, \" ( \", \"(\");\n        sql = StringUtils.replace(sql, \"( \", \"(\");\n        sql = StringUtils.replace(sql, \" )\", \")\");\n        sql = StringUtils.replace(sql, \"\\t\", \" \");\n        sql = StringUtils.replace(sql, \"\\n\", \" \");\n        sql = StringUtils.replace(sql, \"\\'\", \"\\\"\");\n        sql = StringUtils.replace(sql, \" ( \", \"(\");\n        sql = StringUtils.replace(sql, \" (\", \"(\");\n        sql = StringUtils.replace(sql, \"( \", \"(\");\n        sql = StringUtils.replace(sql, \" )\", \")\");\n        sql = StringUtils.replace(sql, \"( \", \"(\");\n        sql = StringUtils.replace(sql, \"  \", \" \");\n        sql = StringUtils.replace(sql, \"  \", \" \");\n        sql = StringUtils.replace(sql, \"  \", \" \");\n        sql = StringUtils.replace(sql, \"  \", \" \");\n        sql = StringUtils.replace(sql, \"( \", \"(\");\n        sql = StringUtils.replace(sql, \", \", \",\");\n        sql = StringUtils.replace(sql, \" ,\", \",\");\n        return sql;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/issues/Issue5853.java",
    "content": "package com.alibaba.druid.bvt.sql.hive.issues;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * Hive解析CREATE TABLE的问题\n *\n * @see <a href=\"https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL\">...</a>\n */\npublic class Issue5853 {\n    @Test\n    public void test_parse_create_0() {\n        for (String sql : new String[]{\n            \"CREATE TABLE page_view (\\n\"\n                + \"\\tviewTime INT,\\n\"\n                + \"\\tuserid BIGINT,\\n\"\n                + \"\\tpage_url STRING,\\n\"\n                + \"\\treferrer_url STRING,\\n\"\n                + \"\\tip STRING COMMENT 'IP Address of the User'\\n\"\n                + \")\\n\"\n                + \"COMMENT 'This is the page view table'\\n\"\n                + \"PARTITIONED BY (\\n\"\n                + \"\\tdt STRING,\\n\"\n                + \"\\tcountry STRING\\n\"\n                + \")\\n\"\n                + \"CLUSTERED BY (userid)\\n\"\n                + \"SORTED BY (viewTime)\\n\"\n                + \"INTO 32 BUCKETS\\n\"\n                + \"ROW FORMAT DELIMITED\\n\"\n                + \"\\tFIELDS TERMINATED BY '\\\\001'\\n\"\n                + \"\\tCOLLECTION ITEMS TERMINATED BY '\\\\002'\\n\"\n                + \"\\tMAP KEYS TERMINATED BY '\\\\003'\\n\"\n                + \"STORED AS SEQUENCEFILE;\",\n        }) {\n            System.out.println(\"原始的sql===\" + sql);\n            SQLStatementParser parser1 = SQLParserUtils.createSQLStatementParser(sql, DbType.hive);\n            List<SQLStatement> statementList1 = parser1.parseStatementList();\n            String sqleNew = statementList1.get(0).toString();\n            System.out.println(\"生成的sql===\" + sqleNew);\n            assertEquals(sql, sqleNew);\n            SQLStatementParser parser2 = SQLParserUtils.createSQLStatementParser(sqleNew, DbType.hive);\n            List<SQLStatement> statementList2 = parser2.parseStatementList();\n            String sqleNew2 = statementList2.get(0).toString();\n            System.out.println(\"再次解析生成的sql===\" + sqleNew2);\n            assertEquals(sqleNew, sqleNew2);\n        }\n\n    }\n\n    @Test\n    public void test_parse_create_1() {\n        for (String sql : new String[]{\n            \"CREATE TABLE db.route(\\n\"\n                + \"od_id string COMMENT 'OD',\\n\"\n                + \"data_dt string COMMENT 'data date')\\n\"\n                + \"CLUSTERED BY (\\n\"\n                + \"od_id)\\n\"\n                + \"INTO 8 BUCKETS\\n\"\n                + \"ROW FORMAT SERDE\\n\"\n                + \"'org.apache.hadoop.hive.ql.io.orc.OrcSerde'\\n\"\n                + \"STORED AS INPUTFORMAT\\n\"\n                + \"'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat'\\n\"\n                + \"OUTPUTFORMAT\\n\"\n                + \"'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat';\",\n\n        }) {\n            System.out.println(\"原始的sql===\" + sql);\n            SQLStatementParser parser1 = SQLParserUtils.createSQLStatementParser(sql, DbType.hive);\n            List<SQLStatement> statementList1 = parser1.parseStatementList();\n            String sqleNew = statementList1.get(0).toString();\n            System.out.println(\"生成的sql===\" + sqleNew);\n            SQLStatementParser parser2 = SQLParserUtils.createSQLStatementParser(sqleNew, DbType.hive);\n            List<SQLStatement> statementList2 = parser2.parseStatementList();\n            String sqleNew2 = statementList2.get(0).toString();\n            System.out.println(\"再次解析生成的sql===\" + sqleNew2);\n            assertEquals(sqleNew, sqleNew2);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/issues/Issue5901.java",
    "content": "package com.alibaba.druid.bvt.sql.hive.issues;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://github.com/alibaba/druid/issues/5901>Issue来源</a>\n */\npublic class Issue5901 {\n    @Test\n    public void test_parse_set() {\n        for (DbType dbType : new DbType[]{DbType.hive}) {\n            for (String sql : new String[]{\n                    \"SET hivevar:account_period = IF(${hivevar:now_month} >= 3 and ${hivevar:now_month} < 6, CONCAT(${hivevar:now_year}, '-03XYZ'), ${hivevar:now_year});\\n\",\n            }) {\n                SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n                List<SQLStatement> statementList = parser.parseStatementList();\n                assertEquals(1, statementList.size());\n                assertEquals(\n                        \"SET hivevar:account_period = IF(${hivevar:now_month} >= 3 AND ${hivevar:now_month} < 6, CONCAT(${hivevar:now_year}, '-03XYZ'), ${hivevar:now_year});\",\n                        statementList.get(0).toString());\n                SQLParseAssertUtil.assertParseSql(sql, dbType);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hive/issues/Issue5968.java",
    "content": "package com.alibaba.druid.bvt.sql.hive.issues;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * @author lizongbo\n * @see <a href=\"https://github.com/alibaba/druid/issues/5968\" >Issue来源</a>\n * @see <a href=\"https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL\">Hive DDL</a>\n */\npublic class Issue5968 {\n    @Test\n    public void test_parse_stored_by() {\n        for (DbType dbType : new DbType[]{DbType.hive}) {\n            for (String sql : new String[]{\n                \"CREATE TABLE IF NOT EXISTS test.tests(\\n\"\n                    + \"  id bigint COMMENT 'from deserializer',\\n \"\n                    + \"  job_group bigint COMMENT 'from deserializer',\\n\"\n                    + \"  job_id bigint COMMENT 'from deserializer',\\n\"\n                    + \"  ums_ts_ bigint COMMENT 'from deserializer')\\n\"\n                    + \" comment 'test' \\n\"\n                    + \" ROW FORMAT SERDE  \"\n                    + \" 'org.apache.paimon.hive.PaimonSerDe'\\n \"\n                    + \"  STORED BY \"\n                    + \" 'org.apache.paimon.hive.PaimonStorageHandler';\",\n            }) {\n                SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);\n                List<SQLStatement> statementList = parser.parseStatementList();\n                System.out.println(statementList);\n                assertEquals(1, statementList.size());\n                SQLParseAssertUtil.assertParseSql(sql, dbType);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hologres/HoloKeywordsTest.java",
    "content": "package com.alibaba.druid.bvt.sql.hologres;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HoloKeywordsTest {\n    @Test\n    public void test_keywords() {\n        DbType dbType = DbType.hologres;\n        String sql = \"select 1 as default\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql,\n                dbType,\n                SQLParserFeature.IgnoreNameQuotes);\n        SQLStatement stmt = parser.parseStatement();\n        assertEquals(Token.EOF, parser.getLexer().token());\n        String result = SQLUtils.toSQLString(stmt, dbType, null, VisitorFeature.OutputNameQuote).trim();\n        String expectedSql = \"SELECT 1 AS \\\"default\\\"\";\n        assertEquals(expectedSql, result);\n    }\n\n    @Test\n    public void test_keywords2() {\n        DbType dbType = DbType.hologres;\n        String sql = \"select a from default.test\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql,\n                dbType,\n                SQLParserFeature.IgnoreNameQuotes);\n        SQLStatement stmt = parser.parseStatement();\n        assertEquals(Token.EOF, parser.getLexer().token());\n        String result = SQLUtils.toSQLString(stmt, dbType, null, VisitorFeature.OutputNameQuote).trim();\n    String expectedSql = \"SELECT a\\n\" + \"FROM \\\"DEFAULT\\\".test\";\n        assertEquals(expectedSql, result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/hologres/HoloResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.hologres;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class HoloResourceTest extends SQLResourceTest {\n    public HoloResourceTest() {\n        super(DbType.hologres);\n    }\n\n    @Test\n    public void hologres_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/hologres/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/impala/ImpalaResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.impala;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class ImpalaResourceTest extends SQLResourceTest {\n    public ImpalaResourceTest() {\n        super(DbType.impala);\n    }\n\n    @Test\n    public void impala_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/impala/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/informix/InformixSelectTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.informix;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class InformixSelectTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"select skip 500 first 500 * from pub_menu \";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.INFORMIX);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"SELECT SKIP 500 FIRST 500 *\\n\" +\n                \"FROM pub_menu\", SQLUtils.toSQLString(stmt, JdbcConstants.INFORMIX));\n\n        assertEquals(\"select skip 500 first 500 *\\n\" +\n                \"from pub_menu\", SQLUtils.toSQLString(stmt, JdbcConstants.INFORMIX, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        PGSchemaStatVisitor visitor = new PGSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(1, visitor.getTables().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/lexer/LexerParameterizedTest.java",
    "content": "package com.alibaba.druid.bvt.sql.lexer;\n\nimport com.alibaba.druid.sql.parser.Lexer;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LexerParameterizedTest {\n    @Test\n    public void test_parameterized() throws Exception {\n        String sql = \"/* 0ab23d3915048393791723851d05b8/9.1.19.1.10176122173.14//8b4757d2/ */SELECT pay_order_id, total_fee, title, alipay_seller_id, alipay_buyer_id, pay_status, out_pay_id, pay_time, end_time, gmt_create, gmt_modified, coupon_fee, actual_total_fee, discount_fee, adjust_fee, closer, point_fee, real_point_fee, obtain_point, refund_fee, confirm_paid_fee, cod_fee, from_group, attributes, attribute_cc, buyer_id, seller_id FROM tc_pay_order_3134 AS tc_pay_order WHERE pay_order_id = 52708022289887078\";\n        String target = Lexer.parameterize(sql, JdbcConstants.MYSQL);\n        //assertEquals(\"SELECT pay_order_id, total_fee, title, alipay_seller_id, alipay_buyer_id, pay_status, out_pay_id, pay_time, end_time, gmt_create, gmt_modified, coupon_fee, actual_total_fee, discount_fee, adjust_fee, closer, point_fee, real_point_fee, obtain_point, refund_fee, confirm_paid_fee, cod_fee, from_group, attributes, attribute_cc, buyer_id, seller_id FROM tc_pay_order_3134 AS tc_pay_order WHERE pay_order_id=?\", target);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLDumpStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class AdsDumpTest_0 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"/*+dump-merge=true*/DUMP DATA SELECT amp.buyer_add_cart_info.buyer_id,amp.buyer_add_cart_info.pre_score,amp.buyer_add_cart_info.cart_price FROM amp.buyer_add_cart_info  JOIN amp.crm_user_base_info ON amp.crm_user_base_info.user_id = amp.buyer_add_cart_info.buyer_id where (((amp.buyer_add_cart_info.seller_id=1921906956)) AND ((amp.buyer_add_cart_info.auction_id=562769960283)) AND ((amp.buyer_add_cart_info.show_price>=13300))) LIMIT 144800 \";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLDumpStatement stmt = (SQLDumpStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"/*+dump-merge=true*/\\n\" +\n                \"DUMP DATA SELECT amp.buyer_add_cart_info.buyer_id, amp.buyer_add_cart_info.pre_score, amp.buyer_add_cart_info.cart_price\\n\" +\n                \"FROM amp.buyer_add_cart_info\\n\" +\n                \"\\tJOIN amp.crm_user_base_info ON amp.crm_user_base_info.user_id = amp.buyer_add_cart_info.buyer_id\\n\" +\n                \"WHERE ((amp.buyer_add_cart_info.seller_id = 1921906956)\\n\" +\n                \"\\tAND (amp.buyer_add_cart_info.auction_id = 562769960283)\\n\" +\n                \"\\tAND (amp.buyer_add_cart_info.show_price >= 13300))\\n\" +\n                \"LIMIT 144800\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/AntlrMySqlTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport com.alibaba.druid.wall.WallConfig;\nimport com.alibaba.druid.wall.spi.MySqlWallProvider;\nimport org.apache.commons.io.FileUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.net.URL;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class AntlrMySqlTest {\n    @Test\n    public void test_for_antlr_examples() throws Exception {\n        SchemaStatVisitor schemaStatVisitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        WallConfig config = new WallConfig();\n        config.setConditionDoubleConstAllow(true);\n        config.setConditionAndAlwayTrueAllow(true);\n        config.setSelectIntoOutfileAllow(true);\n        config.setSelectWhereAlwayTrueCheck(false); //FIXME 此处是否要禁用审核h\n        config.setSelectUnionCheck(false); //FIXME 此处是否要禁用审核\n        config.setCommentAllow(true);\n        config.setHintAllow(true);\n        MySqlWallProvider provider = new MySqlWallProvider(config);\n\n        String path = \"bvt/parser/antlr_grammers_v4_mysql/examples/\";\n        URL resource = Thread.currentThread().getContextClassLoader().getResource(path);\n        File dir = new File(resource.getFile());\n        for (File file : dir.listFiles()) {\n            System.out.println(file);\n            String sql = FileUtils.readFileToString(file);\n\n            List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n            for (SQLStatement stmt : stmtList) {\n                String stmtSql = stmt.toString();\n\n                stmt.accept(schemaStatVisitor);\n                assertTrue(provider.checkValid(stmtSql), stmtSql);\n            }\n\n            // test different style newline.\n            if (sql.indexOf(\"\\r\\n\") == -1) {\n                sql = sql.replace(\"\\n\", \"\\r\\n\");\n            } else {\n                sql = sql.replace(\"\\r\\n\", \"\\n\");\n            }\n\n            stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n            for (SQLStatement stmt : stmtList) {\n                String stmtSql = stmt.toString();\n\n                stmt.accept(schemaStatVisitor);\n                assertTrue(provider.checkValid(stmtSql));\n            }\n\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/CobarHintsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CobarHintsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"/*!cobar: select,4,ireport.dm_mdm_mem_prod_noeff_sdt0.admin_member_seq=45654723*/ \" +\n                \"select  product_id, noeff_days,total_cnt from (\" +\n                \"select   product_id,\" +\n                \"             noeff_days,\" +\n                \"             count(*) over()  as total_cnt                        \" +\n                \"       from   (                   \" +\n                \"          select   product_id,\" +\n                \"                   noeff_days               \" +\n                \"                   from ireport.dm_mdm_mem_prod_noeff_sdt0\" +\n                \"                   where admin_member_seq = 45654723\" +\n                \") b    Order by       product_id desc  ) a limit 25 offset (1-1)*20\";\n\n        String mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, JdbcUtils.POSTGRESQL);\n        assertEquals(\"SELECT product_id, noeff_days, total_cnt\\n\" +\n                \"FROM (\\n\" +\n                \"\\tSELECT product_id, noeff_days, count(*) OVER () AS total_cnt\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT product_id, noeff_days\\n\" +\n                \"\\t\\tFROM ireport.dm_mdm_mem_prod_noeff_sdt0\\n\" +\n                \"\\t\\tWHERE admin_member_seq = ?\\n\" +\n                \"\\t) b\\n\" +\n                \"\\tORDER BY product_id DESC\\n\" +\n                \") a\\n\" +\n                \"LIMIT ? OFFSET (? - ?) * ?\", mergedSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/ComparisonFunctionsAndOperatorsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ComparisonFunctionsAndOperatorsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT 1 = 0;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 = 0;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT '0' = 0;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '0' = 0;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 <=> 1, NULL <=> NULL\\n\" +\n                \"\\t, 1 <=> NULL;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT 1 = 1, NULL = NULL, 1 = NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 = 1, NULL = NULL\\n\" +\n                \"\\t, 1 = NULL;\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT '.01' <> '0.01';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '.01' <> '0.01';\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT 0.1 <= 2\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0.1 <= 2\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT 2 < 2\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 2 < 2\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT 2 >= 2\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 2 >= 2\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT 2 > 2\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 2 > 2\", text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 IS true, 0 IS false\\n\" +\n                \"\\t, NULL IS UNKNOWN\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN\\n\" +\n                \"\\t, NULL IS NOT UNKNOWN\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 IS NULL, 0 IS NULL\\n\" +\n                \"\\t, NULL IS NULL\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SELECT * FROM tbl_name WHERE auto_col IS NULL\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT *\\nFROM tbl_name\\nWHERE auto_col IS NULL\", text);\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT * FROM tbl_name WHERE date_column IS NULL\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT *\\nFROM tbl_name\\nWHERE date_column IS NULL\", text);\n    }\n\n    @Test\n    public void test_14() throws Exception {\n        String sql = \"SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 and 1\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 2 BETWEEN 1 AND 3, 2 BETWEEN 3 AND 1\", text);\n    }\n\n    @Test\n    public void test_15() throws Exception {\n        String sql = \"SELECT 1 BETWEEN 2 AND 3;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 BETWEEN 2 AND 3;\", text);\n    }\n\n    @Test\n    public void test_16() throws Exception {\n        String sql = \"SELECT COALESCE(NULL,1);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT COALESCE(NULL, 1);\", text);\n    }\n\n    @Test\n    public void test_17() throws Exception {\n        String sql = \"SELECT GREATEST(2,0);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT GREATEST(2, 0);\", text);\n    }\n\n    @Test\n    public void test_18() throws Exception {\n        String sql = \"SELECT GREATEST(34.0,3.0,5.0,767.0);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT GREATEST(34.0, 3.0, 5.0, 767.0);\", text);\n    }\n\n    @Test\n    public void test_19() throws Exception {\n        String sql = \"SELECT GREATEST('B', 'A', 'C');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT GREATEST('B', 'A', 'C');\", text);\n    }\n\n    @Test\n    public void test_20() throws Exception {\n        String sql = \"SELECT 2 IN (0,3,5,7);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 2 IN (0, 3, 5, 7);\", text);\n    }\n\n    @Test\n    public void test_21() throws Exception {\n        String sql = \"SELECT 'wefwf' IN ('wee','wefwf','weg');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'wefwf' IN ('wee', 'wefwf', 'weg');\", text);\n    }\n\n    @Test\n    public void test_22() throws Exception {\n        String sql = \"SELECT val1 FROM tbl1 WHERE val1 IN ('1','2','a');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT val1\\nFROM tbl1\\nWHERE val1 IN ('1', '2', 'a');\", text);\n    }\n\n    @Test\n    public void test_23() throws Exception {\n        String sql = \"SELECT ISNULL(1+1);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ISNULL(1 + 1);\", text);\n    }\n\n    @Test\n    public void test_24() throws Exception {\n        String sql = \"SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);\", text);\n    }\n\n    @Test\n    public void test_25() throws Exception {\n        String sql = \"SELECT LEAST(34.0,3.0,5.0,767.0);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LEAST(34.0, 3.0, 5.0, 767.0);\", text);\n    }\n\n    @Test\n    public void test_26() throws Exception {\n        String sql = \"SELECT CAST(LEAST(3600, 9223372036854775808.0) as SIGNED);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CAST(LEAST(3600, 9223372036854775808.0) AS SIGNED);\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/ControlFlowFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class ControlFlowFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CASE 1\\n\" +\n                \"\\t\\tWHEN 1 THEN 'one'\\n\" +\n                \"\\t\\tWHEN 2 THEN 'two'\\n\" +\n                \"\\t\\tELSE 'more'\\n\" +\n                \"\\tEND;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT IF(1>2,2,3);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT IF(1 > 2, 2, 3);\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT IF(1<2,'yes','no');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT IF(1 < 2, 'yes', 'no');\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT IF(STRCMP('test','test1'),'no','yes');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT IF(STRCMP('test', 'test1'), 'no', 'yes');\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT IFNULL(1,0);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT IFNULL(1, 0);\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT IFNULL(1/0,'yes');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT IFNULL(1 / 0, 'yes');\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/CreateUserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CreateUserTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n\n        assertTrue(visitor.getTables().size() == 0);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/DateAndTimeFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DateAndTimeFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT something FROM tbl_name WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= date_col\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT something\\nFROM tbl_name\\nWHERE DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date_col\",\n                text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT DAYOFMONTH('2001-11-00'), MONTH('2005-00-00')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DAYOFMONTH('2001-11-00'), MONTH('2005-00-00')\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT DAYNAME('2006-05-00')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DAYNAME('2006-05-00')\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT DAYNAME('2006-05-00')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DAYNAME('2006-05-00')\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT DATE_ADD('2008-01-02', INTERVAL 31 DAY)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATE_ADD('2008-01-02', INTERVAL 31 DAY)\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ADDDATE('2008-01-02', INTERVAL 31 DAY)\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT ADDDATE('2008-01-02', 31)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ADDDATE('2008-01-02', 31)\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002')\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT ADDTIME('01:00:00.999999', '02:00:00.999998')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ADDTIME('01:00:00.999999', '02:00:00.999998')\", text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CONVERT_TZ('2004-01-01 12:00:00', 'GMT', 'MET');\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CONVERT_TZ('2004-01-01 12:00:00', '+00:00', '+10:00');\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SELECT CURDATE();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CURDATE();\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SELECT CURDATE() + 0;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CURDATE() + 0;\", text);\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT CURTIME();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CURTIME();\", text);\n    }\n\n    @Test\n    public void test_14() throws Exception {\n        String sql = \"SELECT CURDATE() + 0;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CURDATE() + 0;\", text);\n    }\n\n    @Test\n    public void test_15() throws Exception {\n        String sql = \"SELECT DATE('2003-12-31 01:02:03');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATE('2003-12-31 01:02:03');\", text);\n    }\n\n    @Test\n    public void test_16() throws Exception {\n        String sql = \"SELECT DATEDIFF('2007-12-31 23:59:59','2007-12-30');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATEDIFF('2007-12-31 23:59:59', '2007-12-30');\", text);\n    }\n\n    @Test\n    public void test_17() throws Exception {\n        String sql = \"SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATEDIFF('2010-11-30 23:59:59', '2010-12-31');\", text);\n    }\n\n    @Test\n    public void test_18() throws Exception {\n        String sql = \"SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;\", text);\n    }\n\n    @Test\n    public void test_19() throws Exception {\n        String sql = \"SELECT INTERVAL 1 DAY + '2008-12-31';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INTERVAL 1 DAY + '2008-12-31';\", text);\n    }\n\n    @Test\n    public void test_20() throws Exception {\n        String sql = \"SELECT '2005-01-01' - INTERVAL 1 SECOND;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '2005-01-01' - INTERVAL 1 SECOND;\", text);\n    }\n\n    @Test\n    public void test_21() throws Exception {\n        String sql = \"SELECT DATE_ADD('2000-12-31 23:59:59',INTERVAL 1 SECOND);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATE_ADD('2000-12-31 23:59:59', INTERVAL 1 SECOND);\", text);\n    }\n\n    @Test\n    public void test_22() throws Exception {\n        String sql = \"SELECT DATE_ADD('2009-01-01', INTERVAL 6/4 HOUR_MINUTE);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATE_ADD('2009-01-01', INTERVAL 6 / 4 HOUR_MINUTE);\", text);\n    }\n\n    @Test\n    public void test_23() throws Exception {\n        String sql = \"SELECT DATE_ADD('2009-01-01', INTERVAL 6/4 MINUTE_SECOND);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATE_ADD('2009-01-01', INTERVAL 6 / 4 MINUTE_SECOND);\", text);\n    }\n\n    @Test\n    public void test_24() throws Exception {\n        String sql = \"SELECT INTERVAL '-1 10' DAY_HOUR;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INTERVAL '-1 10' DAY_HOUR;\", text);\n    }\n\n    @Test\n    public void test_25() throws Exception {\n        String sql = \"SELECT INTERVAL '1 1:1:1' DAY_SECOND;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INTERVAL '1 1:1:1' DAY_SECOND;\", text);\n    }\n\n    @Test\n    public void test_26() throws Exception {\n        String sql = \"SELECT INTERVAL '-1 10' DAY_HOUR;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INTERVAL '-1 10' DAY_HOUR;\", text);\n    }\n\n    @Test\n    public void test_27() throws Exception {\n        String sql = \"SELECT INTERVAL 31 DAY;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INTERVAL 31 DAY;\", text);\n    }\n\n    @Test\n    public void test_28() throws Exception {\n        String sql = \"SELECT INTERVAL '1.999999' SECOND_MICROSECOND;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INTERVAL '1.999999' SECOND_MICROSECOND;\", text);\n    }\n\n    @Test\n    public void test_29() throws Exception {\n        String sql = \"SELECT '2005-03-32' + INTERVAL 1 MONTH;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '2005-03-32' + INTERVAL 1 MONTH;\", text);\n    }\n\n    @Test\n    public void test_30() throws Exception {\n        String sql = \"SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y');\", text);\n    }\n\n    @Test\n    public void test_31() throws Exception {\n        String sql = \"SELECT EXTRACT(YEAR FROM '2009-07-02');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT EXTRACT(YEAR FROM '2009-07-02');\", text);\n    }\n\n    @Test\n    public void test_32() throws Exception {\n        String sql = \"SELECT EXTRACT(YEAR_MONTH FROM '2009-07-02 01:02:03');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT EXTRACT(YEAR_MONTH FROM '2009-07-02 01:02:03');\", text);\n    }\n\n    @Test\n    public void test_33() throws Exception {\n        String sql = \"SELECT EXTRACT(DAY_MINUTE FROM '2009-07-02 01:02:03');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT EXTRACT(DAY_MINUTE FROM '2009-07-02 01:02:03');\", text);\n    }\n\n    @Test\n    public void test_34() throws Exception {\n        String sql = \"SELECT EXTRACT(MICROSECOND FROM '2003-01-02 10:30:00.000123');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT EXTRACT(MICROSECOND FROM '2003-01-02 10:30:00.000123');\", text);\n    }\n\n    @Test\n    public void test_35() throws Exception {\n        String sql = \"SELECT FROM_UNIXTIME(1196440219);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT FROM_UNIXTIME(1196440219);\", text);\n    }\n\n    @Test\n    public void test_36() throws Exception {\n        String sql = \"SELECT FROM_UNIXTIME(1196440219) + 0;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT FROM_UNIXTIME(1196440219) + 0;\", text);\n    }\n\n    @Test\n    public void test_37() throws Exception {\n        String sql = \"SELECT HOUR('10:05:03');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT HOUR('10:05:03');\", text);\n    }\n\n    @Test\n    public void test_38() throws Exception {\n        String sql = \"SELECT NOW(), SLEEP(2), NOW();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT NOW(), SLEEP(2), NOW();\", text);\n    }\n\n    @Test\n    public void test_39() throws Exception {\n        String sql = \"SELECT SYSDATE(), SLEEP(2), SYSDATE();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SYSDATE(), SLEEP(2), SYSDATE();\", text);\n    }\n\n    @Test\n    public void test_40() throws Exception {\n        String sql = \"SELECT SUBDATE('2008-01-02', INTERVAL 31 DAY);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SUBDATE('2008-01-02', INTERVAL 31 DAY);\", text);\n    }\n\n    @Test\n    public void test_41() throws Exception {\n        String sql = \"SELECT TIME('2003-12-31 01:02:03.000123');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TIME('2003-12-31 01:02:03.000123');\", text);\n    }\n\n    @Test\n    public void test_42() throws Exception {\n        String sql = \"SELECT SECOND('10:05:03');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SECOND('10:05:03');\", text);\n    }\n\n    @Test\n    public void test_43() throws Exception {\n        String sql = \"SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TIMESTAMPADD(MINUTE, 1, '2003-01-02');\", text);\n    }\n\n    @Test\n    public void test_44() throws Exception {\n        String sql = \"SELECT TIMESTAMPADD(WEEK,1,'2003-01-02');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TIMESTAMPADD(WEEK, 1, '2003-01-02');\", text);\n    }\n\n    @Test\n    public void test_45() throws Exception {\n        String sql = \"SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TIMESTAMPDIFF(MONTH, '2003-02-01', '2003-05-01');\", text);\n    }\n\n    @Test\n    public void test_46() throws Exception {\n        String sql = \"SELECT TIMESTAMPDIFF(MINUTE,'2003-02-01','2003-05-01 12:05:55');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TIMESTAMPDIFF(MINUTE, '2003-02-01', '2003-05-01 12:05:55');\", text);\n    }\n\n    @Test\n    public void test_47() throws Exception {\n        String sql = \"SELECT TO_DAYS('2007-10-07');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TO_DAYS('2007-10-07');\", text);\n    }\n\n    @Test\n    public void test_48() throws Exception {\n        String sql = \"SELECT TO_DAYS(950501);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TO_DAYS(950501);\", text);\n    }\n\n    @Test\n    public void test_49() throws Exception {\n        String sql = \"SELECT TO_DAYS('0000-01-01');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TO_DAYS('0000-01-01');\", text);\n    }\n\n    @Test\n    public void test_50() throws Exception {\n        String sql = \"SELECT UNIX_TIMESTAMP();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT UNIX_TIMESTAMP();\", text);\n    }\n\n    @Test\n    public void test_51() throws Exception {\n        String sql = \"SELECT WEEK('2008-02-20');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT WEEK('2008-02-20');\", text);\n    }\n\n    @Test\n    public void test_52() throws Exception {\n        String sql = \"SELECT MID(YEARWEEK('2000-01-01'),5,2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT MID(YEARWEEK('2000-01-01'), 5, 2);\", text);\n    }\n\n    @Test\n    public void test_53() throws Exception {\n        String sql = \"SELECT YEARWEEK('1987-01-01');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT YEARWEEK('1987-01-01');\", text);\n    }\n\n    @Test\n    public void test_54() throws Exception {\n        String sql = \"SELECT t.c1, DATE_ADD('2008-01-02', INTERVAL +t.c1 DAY) from t\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT t.c1, DATE_ADD('2008-01-02', INTERVAL +t.c1 DAY)\\nFROM t\", text);\n    }\n\n    @Test\n    public void test_55() throws Exception {\n        String sql = \"SELECT t.c1, DATE_ADD('2008-01-02', INTERVAL -t.c1 DAY) from t\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT t.c1, DATE_ADD('2008-01-02', INTERVAL -t.c1 DAY)\\nFROM t\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/DateAndTimeValuesTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DateAndTimeValuesTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '2008-12-31 23:59:59' + INTERVAL 1 SECOND;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT '2008-02-31' + INTERVAL 0 DAY\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '2008-02-31' + INTERVAL 0 DAY\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT '2008-02-31' + INTERVAL 0 MONTH\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '2008-02-31' + INTERVAL 0 MONTH\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/DeleteSyntaxTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DeleteSyntaxTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp_column LIMIT 1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"DELETE FROM somelog\\nWHERE user = 'jcole'\\nORDER BY timestamp_column\\nLIMIT 1;\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"DELETE t1\" +\n                \"\\nFROM t1\" +\n                \"\\n\\tLEFT JOIN t2 ON t1.id = t2.id\" +\n                \"\\nWHERE t2.id IS NULL;\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"DELETE a1, a2\\nFROM t1 a1\" +\n                \"\\n\\tINNER JOIN t2 a2\" +\n                \"\\nWHERE a1.id = a2.id\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"DELETE FROM a1, a2\\n\" +\n                \"USING t1 a1\\n\" +\n                \"\\tINNER JOIN t2 a2\\n\" +\n                \"WHERE a1.id = a2.id\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete from a1, a2\\n\" +\n                \"using t1 a1\\n\" +\n                \"\\tinner join t2 a2\\n\" +\n                \"where a1.id = a2.id\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"DELETE LOW_PRIORITY QUICK IGNORE FROM T\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"DELETE LOW_PRIORITY QUICK IGNORE FROM T\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete low_priority quick ignore from T\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/DropTableTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DropTableTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DROP TABLE films, distributors;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"films\")));\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"distributors\")));\n\n        assertTrue(visitor.getTables().get(new TableStat.Name(\"films\")).getDropCount() == 1);\n        assertTrue(visitor.getTables().get(new TableStat.Name(\"distributors\")).getDropCount() == 1);\n\n        assertTrue(visitor.getColumns().isEmpty());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/DropUserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class DropUserTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DROP USER 'jeffrey'@'localhost';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n\n        assertTrue(visitor.getTables().size() == 0);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/EncryptionAndCompressionFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class EncryptionAndCompressionFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"INSERT INTO t VALUES (1,AES_ENCRYPT('text','password'))\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"INSERT INTO t\\nVALUES (1, AES_ENCRYPT('text', 'password'));\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT LENGTH(COMPRESS(REPEAT('a',1000)))\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LENGTH(COMPRESS(REPEAT('a', 1000)));\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT LENGTH(COMPRESS(REPEAT('a',16)))\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LENGTH(COMPRESS(REPEAT('a', 16)));\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT MD5('testing')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT MD5('testing');\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT SHA1('abc')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SHA1('abc');\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT SHA2('abc')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SHA2('abc');\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT PASSWORD('badpwd')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT PASSWORD('badpwd');\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        StringBuilder out = new StringBuilder();\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(new MySqlOutputVisitor(out));\n            out.append(\";\");\n        }\n\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/FullTextSearchesWithQueryExpansionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class FullTextSearchesWithQueryExpansionTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('database' IN NATURAL LANGUAGE MODE)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n\n        {\n            String text = SQLUtils.toMySqlString(stmt);\n\n            assertEquals(\"SELECT *\"\n                            + \"\\nFROM articles\"\n                            + \"\\nWHERE MATCH (title, body) AGAINST ('database' IN NATURAL LANGUAGE MODE)\",\n                    text);\n        }\n        {\n            String text = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n\n            assertEquals(\"select *\"\n                            + \"\\nfrom articles\"\n                            + \"\\nwhere match (title, body) against ('database' in natural language mode)\",\n                    text);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/HelpTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HelpTest {\n    @Test\n    public void test_help_0() throws Exception {\n        String sql = \"HELP 'contents'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"HELP 'contents'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/HexadecimalValuesTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class HexadecimalValuesTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT 0x5061756c;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0x5061756c;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT X'4D7953514C';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0x4D7953514C;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT x'4D7953514C';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0x4D7953514C;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT 0x65 USING utf8;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0x65 USING utf8;\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT 0x41, CAST(0x41 AS UNSIGNED)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0x41, CAST(0x41 AS UNSIGNED)\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT HEX('cat')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT HEX('cat')\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/IdentifierTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class IdentifierTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT t.1c FROM tab t\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT t.1c\\nFROM tab t;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT tid,seller_nick,jdp_response from 2df1479e96cb4ac8b57f2502b5425bb5\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT tid, seller_nick, jdp_response\\nFROM 2df1479e96cb4ac8b57f2502b5425bb5;\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        StringBuilder out = new StringBuilder();\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(new MySqlOutputVisitor(out));\n            out.append(\";\");\n        }\n\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/InformationFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class InformationFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT BENCHMARK(1000000,ENCODE('hello','goodbye'))\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT BENCHMARK(1000000, ENCODE('hello', 'goodbye'))\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT CHARSET('abc');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CHARSET('abc');\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT CHARSET(CONVERT('abc' USING utf8));\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CHARSET(CONVERT('abc' USING utf8));\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT CHARSET(USER());\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CHARSET(USER());\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci);\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT COLLATION('abc');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT COLLATION('abc');\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT * FROM mysql.user;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT *\\nFROM mysql.user;\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT CURRENT_USER();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CURRENT_USER();\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT DATABASE();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DATABASE();\", text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SQL_CALC_FOUND_ROWS *\\nFROM tbl_name;\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT FOUND_ROWS();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT FOUND_ROWS();\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SELECT LAST_INSERT_ID();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LAST_INSERT_ID();\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SELECT ROW_COUNT();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ROW_COUNT();\", text);\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT USER();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT USER();\", text);\n    }\n\n    @Test\n    public void test_14() throws Exception {\n        String sql = \"SELECT VERSION();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT VERSION();\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/InsertSyntaxTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class InsertSyntaxTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"INSERT INTO tbl_name () VALUES();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"INSERT INTO tbl_name\\nVALUES ();\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"INSERT INTO tbl_name (col1, col2)\\nVALUES (15, col1 * 2);\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"INSERT INTO tbl_name (col1, col2)\\nVALUES (col2 * 2, 15);\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"INSERT INTO tbl_name (a, b, c)\\nVALUES (1, 2, 3),\" +\n                \"\\n\\t(4, 5, 6),\" +\n                \"\\n\\t(7, 8, 9);\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"INSERT INTO tbl_name (a,b,c) VALUES(1,2,3,4,5,6,7,8,9);;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"INSERT INTO tbl_name (a, b, c)\" +\n                \"\\nVALUES (1, 2, 3, 4, 5\" +\n                \"\\n\\t, 6, 7, 8, 9);\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"INSERT LOW_PRIORITY DELAYED HIGH_PRIORITY IGNORE INTO tbl_name (a,b,c) VALUES(1,2,3);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"INSERT LOW_PRIORITY DELAYED HIGH_PRIORITY IGNORE INTO tbl_name (a, b, c)\\nVALUES (1, 2, 3);\",\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"insert low_priority delayed high_priority ignore into tbl_name (a, b, c)\\nvalues (1, 2, 3);\",\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"INSERT tbl_name (a,b,c) VALUES(1,2,3) ON DUPLICATE KEY UPDATE c=c+1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"INSERT INTO tbl_name (a, b, c)\" +\n                \"\\nVALUES (1, 2, 3)\" +\n                \"\\nON DUPLICATE KEY UPDATE c = c + 1;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"insert into tbl_name (a, b, c)\" +\n                \"\\nvalues (1, 2, 3)\" +\n                \"\\non duplicate key update c = c + 1;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/Kill_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Kill_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"KILL  QUERY 233\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"KILL QUERY 233;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"KILL  CONNECTION 233\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"KILL CONNECTION 233;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"KILL 233\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"KILL 233;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"KILL 233,234\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"KILL 233, 234;\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        StringBuilder out = new StringBuilder();\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(new MySqlOutputVisitor(out));\n            out.append(\";\");\n        }\n\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/LOAD_XML_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LOAD_XML_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"LOAD XML LOCAL INFILE 'person.xml' INTO TABLE person ROWS IDENTIFIED BY '<person>';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"LOAD XML LOCAL INFILE 'person.xml' INTO TABLE person ROWS IDENTIFIED BY '<person>';\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/LoadDataInFileSyntaxTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LoadDataInFileSyntaxTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test FIELDS TERMINATED BY ','  LINES STARTING BY 'xxx';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test COLUMNS TERMINATED BY ',' LINES STARTING BY 'xxx';\",\n                text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"LOAD DATA INFILE '/home/Order.txt' INTO TABLE Orders (Order_Number, Order_Date, Customer_ID);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"LOAD DATA INFILE '/home/Order.txt' INTO TABLE Orders (Order_Number, Order_Date, Customer_ID);\",\n                text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name FIELDS TERMINATED BY ',' ENCLOSED BY '\\\"' LINES TERMINATED BY '\\r\\n' IGNORE 1 LINES;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name COLUMNS TERMINATED BY ',' ENCLOSED BY '\\\"' LINES TERMINATED BY '\\r\\n' IGNORE 1 LINES;\",\n                text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/LogicalOperatorsTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LogicalOperatorsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT 10 IS TRUE;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 10 IS true;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT -10 IS TRUE;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT -10 IS true;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT 'string' IS NOT NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'string' IS NOT NULL;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT NOT 10;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT NOT 10;\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT NOT 0;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT NOT 0;\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT NOT NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT NOT NULL;\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT ! (1+1);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT !(1 + 1);\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT ! 1+1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT !1 + 1;\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT 1 && 1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1\\n\\tAND 1;\", text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT 1 AND NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1\\n\\tAND NULL;\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT 0 OR NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0\\n\\tOR NULL;\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SELECT 0 || NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0\\n\\tOR NULL;\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SELECT 0 XOR NULL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0 XOR NULL;\", text);\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT 1 XOR 1 XOR 1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 XOR 1 XOR 1;\", text);\n    }\n\n    @Test\n    public void test14() {\n        String sql = \"SELECT ~1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ~1;\", text);\n\n        sql = \"SELECT ~(1+1);\";\n\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n\n        text = output(stmtList);\n\n        assertEquals(\"SELECT ~(1 + 1);\", text);\n    }\n\n    @Test\n    public void test15() {\n        String sql = \"SELECT * FROM SUNTEST WHERE ~ID = 1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM SUNTEST\\n\" +\n                \"WHERE ~ID = 1;\", text);\n\n        sql = \"SELECT * FROM SUNTEST WHERE ~(ID = 1);\";\n\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SELECT *\\nFROM SUNTEST\\nWHERE ~(ID = 1);\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MathematicalFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MathematicalFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT ACOS(1);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ACOS(1);\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT ABS(2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ABS(2);\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT ABS(-32);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ABS(-32);\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT ACOS(1.0001);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ACOS(1.0001);\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT ACOS(0);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ACOS(0);\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT ASIN(0.2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ASIN(0.2);\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT ASIN('foo');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ASIN('foo');\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT ATAN(2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ATAN(2);\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT ATAN(-2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ATAN(-2);\", text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT ATAN(-2,2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ATAN(-2, 2);\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT ATAN2(PI(),0);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ATAN2(PI(), 0);\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SELECT CEILING(1.23);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CEILING(1.23);\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SELECT CEILING(-1.23);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CEILING(-1.23);\", text);\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT CONV('a',16,2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CONV('a', 16, 2);\", text);\n    }\n\n    @Test\n    public void test_14() throws Exception {\n        String sql = \"SELECT CONV(10+'10'+'10'+0xa,10,10);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CONV(10 + '10' + '10' + 0xa, 10, 10);\", text);\n    }\n\n    @Test\n    public void test_15() throws Exception {\n        String sql = \"SELECT COS(PI())\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT COS(PI())\", text);\n    }\n\n    @Test\n    public void test_16() throws Exception {\n        String sql = \"SELECT CRC32('MySQL')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CRC32('MySQL')\", text);\n    }\n\n    @Test\n    public void test_17() throws Exception {\n        String sql = \"SELECT DEGREES(PI())\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DEGREES(PI())\", text);\n    }\n\n    @Test\n    public void test_18() throws Exception {\n        String sql = \"SELECT DEGREES(PI() / 2)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DEGREES(PI() / 2)\", text);\n    }\n\n    @Test\n    public void test_19() throws Exception {\n        String sql = \"SELECT MOD(29,9)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT MOD(29, 9)\", text);\n    }\n\n    @Test\n    public void test_20() throws Exception {\n        String sql = \"SELECT 29 MOD 9\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 29 % 9\", text);\n    }\n\n    @Test\n    public void test_21() throws Exception {\n        String sql = \"SELECT PI()+0.000000000000000000\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT PI() + 0.000000000000000000\", text);\n    }\n\n    @Test\n    public void test_22() throws Exception {\n        String sql = \"SELECT POW(2,-2)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT POW(2, -2)\", text);\n    }\n\n    @Test\n    public void test_23() throws Exception {\n        String sql = \"SELECT RADIANS(90)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT RADIANS(90)\", text);\n    }\n\n    @Test\n    public void test_24() throws Exception {\n        String sql = \"SELECT i, RAND() FROM t\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT i, RAND()\\nFROM t\", text);\n    }\n\n    @Test\n    public void test_25() throws Exception {\n        String sql = \"SELECT * FROM tbl_name ORDER BY RAND()\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT *\\nFROM tbl_name\\nORDER BY RAND()\", text);\n    }\n\n    @Test\n    public void test_26() throws Exception {\n        String sql = \"SELECT ROUND(2.5), ROUND(25E-1)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ROUND(2.5), ROUND(25E-1)\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MiscellaneousFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MiscellaneousFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"UPDATE t\\nSET i = DEFAULT(i) + 1\\nWHERE id < 100;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT GET_LOCK('lock1',10);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT GET_LOCK('lock1', 10);\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT INET_ATON('209.207.224.40');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INET_ATON('209.207.224.40');\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT UUID();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT UUID();\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySql57Test.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySql57Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE t1 ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(255);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t1\"\n                + \"\\n\\tALGORITHM = INPLACE,\"\n                + \"\\n\\tCHANGE COLUMN c1 c1 VARCHAR(255);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t1\"\n                + \"\\n\\talgorithm = INPLACE,\"\n                + \"\\n\\tchange column c1 c1 VARCHAR(255);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlASTVisitorAdapterTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLLimit;\nimport com.alibaba.druid.sql.ast.SQLResetStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBooleanExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLIntervalExpr;\nimport com.alibaba.druid.sql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlForceIndexHint;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlIgnoreIndexHint;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;\nimport com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;\nimport com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.*;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement.TableSpaceOption;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;\nimport org.junit.jupiter.api.Test;\n\npublic class MySqlASTVisitorAdapterTest {\n    @Test\n    public void test_adapter() throws Exception {\n        MySqlASTVisitorAdapter adapter = new MySqlASTVisitorAdapter();\n        new SQLBooleanExpr().accept(adapter);\n        new SQLLimit().accept(adapter);\n        new MySqlTableIndex().accept(adapter);\n        new MySqlKey().accept(adapter);\n        new MySqlPrimaryKey().accept(adapter);\n        new SQLIntervalExpr().accept(adapter);\n        new SQLBinaryExpr().accept(adapter);\n        new MySqlPrepareStatement().accept(adapter);\n        new MySqlExecuteStatement().accept(adapter);\n        new MysqlDeallocatePrepareStatement().accept(adapter);\n        new MySqlDeleteStatement().accept(adapter);\n        new MySqlInsertStatement().accept(adapter);\n        new MySqlLoadXmlStatement().accept(adapter);\n        new SQLReplaceStatement().accept(adapter);\n        new SQLStartTransactionStatement().accept(adapter);\n        new SQLShowColumnsStatement().accept(adapter);\n        new SQLShowDatabasesStatement().accept(adapter);\n        new MySqlShowWarningsStatement().accept(adapter);\n        new MySqlShowStatusStatement().accept(adapter);\n        new CobarShowStatus().accept(adapter);\n        new MySqlKillStatement().accept(adapter);\n        new MySqlBinlogStatement().accept(adapter);\n        new SQLResetStatement().accept(adapter);\n        new UserSpecification().accept(adapter);\n        new MySqlPartitionByKey().accept(adapter);\n        new MySqlOutFileExpr().accept(adapter);\n        new MySqlUpdateStatement().accept(adapter);\n        new MySqlSetTransactionStatement().accept(adapter);\n        new MySqlShowMasterLogsStatement().accept(adapter);\n        new MySqlShowAuthorsStatement().accept(adapter);\n        new MySqlShowCollationStatement().accept(adapter);\n        new MySqlShowBinLogEventsStatement().accept(adapter);\n        new MySqlShowCharacterSetStatement().accept(adapter);\n        new MySqlShowContributorsStatement().accept(adapter);\n        new MySqlShowCreateDatabaseStatement().accept(adapter);\n        new MySqlShowCreateEventStatement().accept(adapter);\n        new MySqlShowCreateFunctionStatement().accept(adapter);\n        new MySqlShowCreateProcedureStatement().accept(adapter);\n        new SQLShowCreateTableStatement().accept(adapter);\n        new MySqlShowCreateTriggerStatement().accept(adapter);\n        new SQLShowCreateViewStatement().accept(adapter);\n        new MySqlShowEngineStatement().accept(adapter);\n        new MySqlShowEnginesStatement().accept(adapter);\n        new MySqlShowErrorsStatement().accept(adapter);\n        new MySqlShowEventsStatement().accept(adapter);\n        new MySqlShowFunctionCodeStatement().accept(adapter);\n        new MySqlShowFunctionStatusStatement().accept(adapter);\n        new MySqlShowGrantsStatement().accept(adapter);\n        new MySqlUserName().accept(adapter);\n        new SQLShowIndexesStatement().accept(adapter);\n        new MySqlShowMasterStatusStatement().accept(adapter);\n        new MySqlShowOpenTablesStatement().accept(adapter);\n        new MySqlShowBinaryLogsStatement().accept(adapter);\n        new MySqlShowPluginsStatement().accept(adapter);\n        new MySqlShowPrivilegesStatement().accept(adapter);\n        new MySqlShowProcedureCodeStatement().accept(adapter);\n        new MySqlShowProcedureStatusStatement().accept(adapter);\n        new MySqlShowProcessListStatement().accept(adapter);\n        new MySqlShowProfileStatement().accept(adapter);\n        new MySqlShowSlaveHostsStatement().accept(adapter);\n        new MySqlShowRelayLogEventsStatement().accept(adapter);\n        new MySqlShowSlaveStatusStatement().accept(adapter);\n        new MySqlShowTableStatusStatement().accept(adapter);\n        new MySqlShowTriggersStatement().accept(adapter);\n        new MySqlRenameTableStatement().accept(adapter);\n        new MySqlUseIndexHint().accept(adapter);\n        new MySqlIgnoreIndexHint().accept(adapter);\n        new MySqlLockTableStatement().accept(adapter);\n        new MySqlUnlockTablesStatement().accept(adapter);\n        new MySqlForceIndexHint().accept(adapter);\n        new MySqlAlterTableChangeColumn().accept(adapter);\n        new SQLAlterCharacter().accept(adapter);\n        new MySqlAlterTableOption().accept(adapter);\n        new MySqlCreateTableStatement().accept(adapter);\n        new MySqlCharExpr().accept(adapter);\n        new MySqlUnique().accept(adapter);\n        new MySqlAlterTableModifyColumn().accept(adapter);\n        new MySqlAlterTableDiscardTablespace().accept(adapter);\n        new MySqlAlterTableImportTablespace().accept(adapter);\n        new TableSpaceOption().accept(adapter);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAnalyzeTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAnalyzeTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"ANALYZE TABLE t1,t2\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ANALYZE TABLE t1, t2\", //\n                output);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlBeginTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlBeginTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"START TRANSACTION;\"\n                + \"\\nSELECT @A:=SUM(salary) FROM table1 WHERE type=1;\"\n                + \"\\nUPDATE table2 SET summary=@A WHERE type=1;\"\n                + \"\\nCOMMIT;\"\n                + \"\\n\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(4, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        for (SQLStatement stmt : statementList) {\n            stmt.accept(visitor);\n        }\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        {\n            String output = SQLUtils.toSQLString(statementList, JdbcConstants.MYSQL);\n            assertEquals(\"START TRANSACTION;\"\n                            + \"\\n\"\n                            + \"\\nSELECT @A := SUM(salary)\"\n                            + \"\\nFROM table1\"\n                            + \"\\nWHERE type = 1;\"\n                            + \"\\n\"\n                            + \"\\nUPDATE table2\"\n                            + \"\\nSET summary = @A\"\n                            + \"\\nWHERE type = 1;\"\n                            + \"\\n\"\n                            + \"\\nCOMMIT;\", //\n                    output);\n        }\n        {\n            String output = SQLUtils.toSQLString(statementList, JdbcConstants.MYSQL, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"start transaction;\"\n                            + \"\\n\"\n                            + \"\\nselect @A := sum(salary)\"\n                            + \"\\nfrom table1\"\n                            + \"\\nwhere type = 1;\"\n                            + \"\\n\"\n                            + \"\\nupdate table2\"\n                            + \"\\nset summary = @A\"\n                            + \"\\nwhere type = 1;\"\n                            + \"\\n\"\n                            + \"\\ncommit;\", //\n                    output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlChecksumTableTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlChecksumTableTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CHECKSUM TABLE tbl_name\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertEquals(\"CHECKSUM TABLE tbl_name\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CHECKSUM TABLE t1,t2\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        assertEquals(\"CHECKSUM TABLE t1, t2\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDeleteTest_0 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t1\", \"id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDeleteTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"DELETE FROM a1, a2\\n\" +\n                \"USING t1 a1\\n\" +\n                \"\\tINNER JOIN t2 a2\\n\" +\n                \"WHERE a1.id = a2.id;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete from a1, a2\\n\" +\n                \"using t1 a1\\n\" +\n                \"\\tinner join t2 a2\\n\" +\n                \"where a1.id = a2.id;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt.toString());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t1\", \"id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDeleteTest_2 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"DELETE t1\"\n                + \"\\nFROM t1\"\n                + \"\\n\\tLEFT JOIN t2 ON t1.id = t2.id\"\n                + \"\\nWHERE t2.id IS NULL;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete t1\"\n                + \"\\nfrom t1\"\n                + \"\\n\\tleft join t2 on t1.id = t2.id\"\n                + \"\\nwhere t2.id is null;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(3, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t1\", \"id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDeleteTest_3 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DELETE FROM t1 \"\n                + \"WHERE s11 > ANY\"//\n                + \"(SELECT COUNT(*) /* no hint */ FROM t2\"//\n                + \"  WHERE NOT EXISTS\"//\n                + \"   (SELECT * FROM t3\"//\n                + \"    WHERE ROW(5*t2.s1,77)=\"//\n                + \"     (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM\"//\n                + \"      (SELECT * FROM t5) AS t5)));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"DELETE FROM t1\\n\" +\n                \"WHERE s11 > ANY (\\n\" +\n                \"\\t\\tSELECT COUNT(*)\\n\" +\n                \"\\t\\tFROM  /* no hint */\\n\\t\\tt2\\n\" +\n                \"\\t\\tWHERE NOT EXISTS (\\n\" +\n                \"\\t\\t\\tSELECT *\\n\" +\n                \"\\t\\t\\tFROM t3\\n\" +\n                \"\\t\\t\\tWHERE ROW(5 * t2.s1, 77) = (\\n\" +\n                \"\\t\\t\\t\\tSELECT 50, 11 * s1\\n\" +\n                \"\\t\\t\\t\\tFROM t4\\n\" +\n                \"\\t\\t\\t\\tUNION\\n\" +\n                \"\\t\\t\\t\\tSELECT 50, 77\\n\" +\n                \"\\t\\t\\t\\tFROM (\\n\" +\n                \"\\t\\t\\t\\t\\tSELECT *\\n\" +\n                \"\\t\\t\\t\\t\\tFROM t5\\n\" +\n                \"\\t\\t\\t\\t) t5\\n\" +\n                \"\\t\\t\\t)\\n\" +\n                \"\\t\\t)\\n\" +\n                \"\\t);\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete from t1\\n\" +\n                \"where s11 > any (\\n\" +\n                \"\\t\\tselect count(*)\\n\" +\n                \"\\t\\tfrom  /* no hint */\\n\\t\\tt2\\n\" +\n                \"\\t\\twhere not exists (\\n\" +\n                \"\\t\\t\\tselect *\\n\" +\n                \"\\t\\t\\tfrom t3\\n\" +\n                \"\\t\\t\\twhere ROW(5 * t2.s1, 77) = (\\n\" +\n                \"\\t\\t\\t\\tselect 50, 11 * s1\\n\" +\n                \"\\t\\t\\t\\tfrom t4\\n\" +\n                \"\\t\\t\\t\\tunion\\n\" +\n                \"\\t\\t\\t\\tselect 50, 77\\n\" +\n                \"\\t\\t\\t\\tfrom (\\n\" +\n                \"\\t\\t\\t\\t\\tselect *\\n\" +\n                \"\\t\\t\\t\\t\\tfrom t5\\n\" +\n                \"\\t\\t\\t\\t) t5\\n\" +\n                \"\\t\\t\\t)\\n\" +\n                \"\\t\\t)\\n\" +\n                \"\\t);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(stmt);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(5, visitor.getTables().size());\n        assertEquals(6, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t1\", \"s11\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"s1\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"*\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t3\", \"*\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t4\", \"s1\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t5\", \"*\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_4_force_partition.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDeleteTest_4_force_partition extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DELETE force all partitions car_tt FROM runoob_tbl WHERE runoob_id=3;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"DELETE FORCE ALL PARTITIONS car_tt\\n\" +\n                \"FROM runoob_tbl\\n\" +\n                \"WHERE runoob_id = 3;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete force all partitions car_tt\\n\" +\n                \"from runoob_tbl\\n\" +\n                \"where runoob_id = 3;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt.toString());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"runoob_tbl\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"car_tt\", \"runoob_id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_5_force_partition.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDeleteTest_5_force_partition extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DELETE force partition 'pt001' car_tt FROM runoob_tbl WHERE runoob_id=3;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"DELETE FORCE PARTITION 'pt001' car_tt\\n\" +\n                \"FROM runoob_tbl\\n\" +\n                \"WHERE runoob_id = 3;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete force partition 'pt001' car_tt\\n\" +\n                \"from runoob_tbl\\n\" +\n                \"where runoob_id = 3;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt.toString());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"runoob_tbl\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"car_tt\", \"runoob_id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDeleteTest_6 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"delete a.* from teacher_1 a join teacher_2 b on a.teacher_id = b.teacher_id where a.day < b.day\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"DELETE a.*\\n\" +\n                \"FROM teacher_1 a\\n\" +\n                \"\\tJOIN teacher_2 b ON a.teacher_id = b.teacher_id\\n\" +\n                \"WHERE a.day < b.day\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"delete a.*\\n\" +\n                \"from teacher_1 a\\n\" +\n                \"\\tjoin teacher_2 b on a.teacher_id = b.teacher_id\\n\" +\n                \"where a.day < b.day\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(stmt);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(4, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"teacher_1\")));\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"teacher_2\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"teacher_1\", \"teacher_id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"teacher_1\", \"teacher_id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"teacher_2\", \"day\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"teacher_2\", \"day\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDeleteTest_7.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class MySqlDeleteTest_7 {\n    @Test\n    public void test_0() throws Exception {\n    String sql =\n        \"delete t1.* from xxx t1 join yyy t2 \\n\"\n            + \"on t1.id = t2 .id \\n\"\n            + \"where t1.c1 in ('1','2') and t2.c2 in ('1','2');\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLDeleteStatement stmt = (SQLDeleteStatement) statementList.get(0);\n        assertEquals(\"t1.*\", stmt.getTableName().toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDescTest_0 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \" Desc City\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDescribteTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \" DESCRIBE City\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        // assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"desc student sname\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getColumns().contains(new Column(\"student\", \"sname\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDumpTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"dump data into 'odps://ktv_market_analyzing/bohan_test_001/ds=20171233/seller_bucket=9727' \" +\n                \"select '6225607' as crowd_snapshot_id, a.seller_id as seller_id, a.buyer_id as buyer_id \" +\n                \"from amp.otpx_buyer_seller_relation_detail_to_garuda a \" +\n                \"join amp.otp_user_base_info b on b.user_id= a.buyer_id \" +\n                \"where(((a.seller_id= 765844183 and a.seller_zone= 765844183%20+ 1000)) and((a.last_pay_date>= 20151226 and a.last_pay_date<= 20171215)) and((a.is_market_target in('3'))))\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(6, visitor.getColumns().size());\n        assertEquals(7, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"amp.otp_user_base_info\"));\n        assertTrue(visitor.containsTable(\"amp.otpx_buyer_seller_relation_detail_to_garuda\"));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        assertTrue(visitor.containsColumn(\"amp.otp_user_base_info\", \"user_id\"));\n        assertTrue(visitor.containsColumn(\"amp.otpx_buyer_seller_relation_detail_to_garuda\", \"buyer_id\"));\n        assertTrue(visitor.containsColumn(\"amp.otpx_buyer_seller_relation_detail_to_garuda\", \"seller_id\"));\n        assertTrue(visitor.containsColumn(\"amp.otpx_buyer_seller_relation_detail_to_garuda\", \"seller_zone\"));\n        assertTrue(visitor.containsColumn(\"amp.otpx_buyer_seller_relation_detail_to_garuda\", \"is_market_target\"));\n        assertTrue(visitor.containsColumn(\"amp.otpx_buyer_seller_relation_detail_to_garuda\", \"last_pay_date\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlDumpTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"DUMP DATA OVERWRITE INTO 'odps://cod_garuda/wenyu_meta_person' select cid, cname, dept, gender, pid from wenyu_meta_person limit 10;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"wenyu_meta_person\"));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        assertTrue(visitor.containsColumn(\"wenyu_meta_person\", \"cid\"));\n        assertTrue(visitor.containsColumn(\"wenyu_meta_person\", \"cname\"));\n        assertTrue(visitor.containsColumn(\"wenyu_meta_person\", \"dept\"));\n        assertTrue(visitor.containsColumn(\"wenyu_meta_person\", \"gender\"));\n        assertTrue(visitor.containsColumn(\"wenyu_meta_person\", \"pid\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlError_test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlError_test extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"insert into userdetectitem26 (nick,volume) values(?,?) \" +\n                \"ON DUPLICATE KEY UPDATE title = ?,picURL = ?,scoreExceed = ?,score=\";\n\n        Exception error = null;\n\n        try {\n            MySqlStatementParser parser = new MySqlStatementParser(sql);\n            parser.parseStatementList();\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n        assertEquals(\"EOF, score=\", error.getMessage());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlError_test_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlError_test_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"SELECT * FROM pp_items WHERE uid= ORDER BY id DESC LIMIT ?,?\";\n        Exception error = null;\n\n        try {\n            MySqlStatementParser parser = new MySqlStatementParser(sql);\n            parser.parseStatementList();\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n//        error.printStackTrace();\n//        assertEquals(\"ERROR. token : ORDER, pos : 39\", error.getMessage());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlError_test_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\npublic class MySqlError_test_2 extends MysqlTest {\n    public void test_0() {\n        String sql = \"Describe sdb_goods free_postage\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        parser.parseStatementList();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlError_test_3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlError_test_3 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"SELECT count(*) AS num FROM sdb_products AS P\" +\n                \" LEFT JOIN sdb_goods AS G ON G.goods_id = P.goods_id\" +\n                \" LEFT JOIN sdb_goods_cat AS C ON C.cat_id = G.cat_id\" +\n                \" LEFT JOIN sdb_brand AS B ON B.brand_id = G.brand_id\" +\n                \" WHERE P.disabled = ? AND P.op_status = LIMIT ?, ?\";\n        Exception error = null;\n\n        try {\n            MySqlStatementParser parser = new MySqlStatementParser(sql);\n            parser.parseStatementList();\n        } catch (Exception e) {\n            error = e;\n        }\n\n        assertNotNull(error);\n//        error.printStackTrace();\n        String message = error.getMessage();\n        assertTrue(message.startsWith(\"not supported. \"));\n        assertTrue(message.contains(\"pos 248\"));\n        assertTrue(message.contains(\"line 1\"));\n        assertTrue(message.contains(\"column 248\"));\n        assertTrue(message.contains(\"token ?\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlExplainTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExplainStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * See https://dev.mysql.com/doc/refman/5.7/en/explain.html for test cases.\n */\npublic class MySqlExplainTest extends MysqlTest {\n    public void testExplainTable() throws Exception {\n        String sql = \" EXPLAIN City\";\n        SQLStatement statement = testParseFormat(sql);\n\n        MySqlSchemaStatVisitor stats = schemaStats(statement);\n        assertHasSeenXTables(stats, 1);\n        assertHasSeenXColumns(stats, 0);\n        assertHasSeenXConditions(stats, 0);\n        assertHasSeenTable(stats, \"City\");\n    }\n\n    public void testExplainTableWithColumn() throws Exception {\n        String sql = \" EXPLAIN City name\";\n        SQLStatement statement = testParseFormat(sql);\n\n        MySqlSchemaStatVisitor stats = schemaStats(statement);\n        assertHasSeenXTables(stats, 1);\n        assertHasSeenXColumns(stats, 1);\n        assertHasSeenXConditions(stats, 0);\n        assertHasSeenTable(stats, \"City\");\n        assertHasSeenTableColumn(stats, \"City\", \"name\");\n    }\n\n    public void testExplainTableWithWild() throws Exception {\n        String sql = \" EXPLAIN City '%ame'\";\n        SQLStatement statement = testParseFormat(sql);\n\n        MySqlSchemaStatVisitor stats = schemaStats(statement);\n        assertHasSeenXTables(stats, 1);\n        assertHasSeenXColumns(stats, 0);\n        assertHasSeenXConditions(stats, 0);\n        assertHasSeenTable(stats, \"City\");\n    }\n\n    public void testExplainExplainableStatements() throws Exception {\n        testExplainExplainableStatement(\"EXPLAIN SELECT * FROM City\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN DELETE FROM City\", \"City\", 0);\n        testExplainExplainableStatement(\"EXPLAIN INSERT INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN REPLACE INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN UPDATE City SET name = 'Beijing'\", \"City\", 1);\n    }\n\n    public void testExplainExtendedExplainableStatements() throws Exception {\n        testExplainExplainableStatement(\"EXPLAIN EXTENDED SELECT * FROM City\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN EXTENDED DELETE FROM City\", \"City\", 0);\n        testExplainExplainableStatement(\"EXPLAIN EXTENDED INSERT INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN EXTENDED REPLACE INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN EXTENDED UPDATE City SET name = 'Beijing'\", \"City\", 1);\n    }\n\n    public void testExplainPartitionsExplainableStatements() throws Exception {\n        testExplainExplainableStatement(\"EXPLAIN PARTITIONS SELECT * FROM City\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN PARTITIONS DELETE FROM City\", \"City\", 0);\n        testExplainExplainableStatement(\"EXPLAIN PARTITIONS INSERT INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN PARTITIONS REPLACE INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN PARTITIONS UPDATE City SET name = 'Beijing'\", \"City\", 1);\n    }\n\n    public void testExplainFormatTraditionalExplainableStatements() throws Exception {\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = TRADITIONAL SELECT * FROM City\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = TRADITIONAL DELETE FROM City\", \"City\", 0);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = TRADITIONAL INSERT INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = TRADITIONAL REPLACE INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = TRADITIONAL UPDATE City SET name = 'Beijing'\", \"City\", 1);\n    }\n\n    public void testExplainFormatJsonExplainableStatements() throws Exception {\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = JSON SELECT * FROM City\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = JSON DELETE FROM City\", \"City\", 0);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = JSON INSERT INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = JSON REPLACE INTO City (name) VALUES ('Beijing')\", \"City\", 1);\n        testExplainExplainableStatement(\"EXPLAIN FORMAT = JSON UPDATE City SET name = 'Beijing'\", \"City\", 1);\n    }\n\n    public void testExplainForConnections() throws Exception {\n        testExplainForConnection(\"EXPLAIN FOR CONNECTION 1\");\n        testExplainForConnection(\"EXPLAIN EXTENDED FOR CONNECTION 1\");\n        testExplainForConnection(\"EXPLAIN PARTITIONS FOR CONNECTION 1\");\n        testExplainForConnection(\"EXPLAIN FORMAT = TRADITIONAL FOR CONNECTION 1\");\n        testExplainForConnection(\"EXPLAIN FORMAT = JSON FOR CONNECTION 1\");\n    }\n\n    public void testExplainForConnection(String sql) throws Exception {\n        SQLStatement statement = testParseFormat(sql);\n\n        MySqlSchemaStatVisitor stats = schemaStats(statement);\n        assertHasSeenXTables(stats, 0);\n        assertHasSeenXColumns(stats, 0);\n        assertHasSeenXConditions(stats, 0);\n    }\n\n    private SQLStatement testParseFormat(String sql) {\n        List<SQLStatement> statements = parseList(sql);\n        assertStatements(statements);\n\n        SQLStatement statement = statements.get(0);\n        assertStatement(statement);\n\n        String output = format(statement);\n        assertSqlEquals(sql, output);\n\n        return statement;\n    }\n\n    private void testExplainExplainableStatement(String sql, String tableName, int columns) {\n        SQLStatement statement = testParseFormat(sql);\n\n        MySqlSchemaStatVisitor stats = schemaStats(statement);\n        assertHasSeenXTables(stats, 1);\n        assertHasSeenXColumns(stats, columns);\n        assertHasSeenXConditions(stats, 0);\n\n        assertHasSeenTable(stats, tableName);\n    }\n\n    private String format(SQLStatement statement) {\n        StringBuilder out = new StringBuilder();\n        MySqlOutputVisitor visitor = new MySqlOutputVisitor(out);\n        statement.accept(visitor);\n\n        return out.toString();\n    }\n\n    private MySqlSchemaStatVisitor schemaStats(SQLStatement stmt) {\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        return visitor;\n    }\n\n    private void assertSqlEquals(String sql, String output) {\n        assertEquals(sql.trim(), output.replaceAll(\"\\\\s+\", \" \"));\n    }\n\n    private void assertStatement(SQLStatement statement) {\n        assertTrue(statement instanceof MySqlExplainStatement);\n    }\n\n    private void assertStatements(List<SQLStatement> statements) {\n        assertEquals(1, statements.size());\n    }\n\n    private void assertHasSeenXTables(MySqlSchemaStatVisitor visitor, int x) {\n        assertEquals(x, visitor.getTables().size());\n    }\n\n    private void assertHasSeenXColumns(MySqlSchemaStatVisitor visitor, int x) {\n        assertEquals(x, visitor.getColumns().size());\n    }\n\n    private void assertHasSeenXConditions(MySqlSchemaStatVisitor visitor, int x) {\n        assertEquals(x, visitor.getConditions().size());\n    }\n\n    private static void assertHasSeenTable(MySqlSchemaStatVisitor visitor, String tableName) {\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(tableName)));\n    }\n\n    private static void assertHasSeenTableColumn(MySqlSchemaStatVisitor visitor, String tableName, String columnName) {\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(tableName, columnName)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlExplainTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlExplainTest_0 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"explain SELECT * FROM sonar.groups where id = 1\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"sonar.groups\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlExplainTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlExplainTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"explain extended select * from foo\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"foo\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlFormatTest {\n    @Test\n    public void test_0() throws Exception {\n        String text = \"CREATE TABLE customer (a INT, b CHAR (20), INDEX (a));\";\n        assertEquals(\"CREATE TABLE customer (\\n\" +\n                \"\\ta INT,\\n\" +\n                \"\\tb CHAR(20),\\n\" +\n                \"\\tINDEX(a)\\n\" +\n                \");\", SQLUtils.format(text, JdbcUtils.MYSQL));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlFormatTest2 {\n    @Test\n    public void test_0() throws Exception {\n        String text = \"SELECT cq.uuid FROM ce_queue cq \"\n                + \"WHERE cq.status = ? AND NOT EXISTS (SELECT ? FROM ce_queue cq2 WHERE cq.component_uuid = cq2.component_uuid AND cq2.status <> ?) \"\n                + \"ORDER BY cq.created_at ASC, cq.id ASC\";\n        assertEquals(\"SELECT cq.uuid\"\n                + \"\\nFROM ce_queue cq\"\n                + \"\\nWHERE cq.status = ?\"\n                + \"\\n\\tAND NOT EXISTS (\"\n                + \"\\n\\t\\tSELECT ?\"\n                + \"\\n\\t\\tFROM ce_queue cq2\"\n                + \"\\n\\t\\tWHERE cq.component_uuid = cq2.component_uuid\"\n                + \"\\n\\t\\t\\tAND cq2.status <> ?\"\n                + \"\\n\\t)\"\n                + \"\\nORDER BY cq.created_at ASC, cq.id ASC\", SQLUtils.format(text, JdbcUtils.MYSQL));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlFormatTest3 {\n    @Test\n    public void test_0() throws Exception {\n        String text = \"select * from db_00.t_00_00 where id > 1;\";\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM db_00.t_00_00\\n\" +\n                \"WHERE id > 1;\", SQLUtils.format(text, JdbcUtils.MYSQL));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * test java.sql.Time parameter format and Boolean parameterized\n * @author lizongbo\n */\npublic class MySqlFormatTest4 {\n    @Test\n    public void test_0() throws Exception {\n        String text = \"select * from tabletest\\n\"\n            + \"where ccc like '%tidb_txn_mode%' and open_flag = true \"\n            + \"and bbb = 1 and ddd = 4567.9888  \"\n            + \"and added_time > ? and  added_time < ?;\";\n        List<Object> parameters = new ArrayList<>();\n        java.sql.Time startTime = new java.sql.Time(System.currentTimeMillis());\n        startTime.setHours(11);\n        startTime.setMinutes(22);\n        startTime.setSeconds(33);\n        java.sql.Time endTime = new java.sql.Time(System.currentTimeMillis());\n        endTime.setHours(20);\n        endTime.setMinutes(21);\n        endTime.setSeconds(23);\n        parameters.add(startTime);\n        parameters.add(endTime);\n        String formrtedSql = SQLUtils.format(text, JdbcUtils.MYSQL, parameters);\n        System.out.println(formrtedSql);\n        String mergedSql = ParameterizedOutputVisitorUtils.parameterize(formrtedSql, JdbcUtils.MYSQL);\n        System.out.println(\"orgSql=========\" + text);\n        System.out.println(\"formrtedSql=========\" + formrtedSql);\n        System.out.println(\"mergedSql=========\" + mergedSql);\n        assertEquals(\"SELECT *\\n\"\n            + \"FROM tabletest\\n\"\n            + \"WHERE ccc LIKE '%tidb_txn_mode%'\\n\"\n            + \"\\tAND open_flag = true\\n\"\n            + \"\\tAND bbb = 1\\n\"\n            + \"\\tAND ddd = 4567.9888\\n\"\n            + \"\\tAND added_time > TIME '11:22:33'\\n\"\n            + \"\\tAND added_time < TIME '20:21:23';\", formrtedSql);\n        assertEquals(\"SELECT *\\n\"\n            + \"FROM tabletest\\n\"\n            + \"WHERE ccc LIKE ?\\n\"\n            + \"\\tAND open_flag = ?\\n\"\n            + \"\\tAND bbb = ?\\n\"\n            + \"\\tAND ddd = ?\\n\"\n            + \"\\tAND added_time > TIME ?\\n\"\n            + \"\\tAND added_time < TIME ?;\", mergedSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlHelpTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlHelpTest_0 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"HELP 'search_string'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"HELP 'search_string'\", //\n                output);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlHintStatementTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlHintStatementTest {\n    @Test\n    public void test() {\n        String sql = \"DROP TABLE IF EXISTS `item_similarity`;\"//\n                + \"\\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\"//\n                + \"\\n/*!40101 SET character_set_client = utf8 */;\"\n                + \"\\nCREATE TABLE `item_similarity` (\"//\n                + \" `id` bigint(20) unsigned NOT NULL, \"//\n                + \" `sellerId` bigint(20) DEFAULT NULL,\"//\n                + \" PRIMARY KEY (`id`)\"\n                + \" ) ENGINE=InnoDB DEFAULT CHARSET=utf8;\"//\n                + \" \\n/*!40101 SET character_set_client = @saved_cs_client */;\";\n        String rs = SQLUtils.formatMySql(sql);\n        assertEquals(\"DROP TABLE IF EXISTS `item_similarity`;\"\n                + \"\\n\"\n                + \"\\n/*!40101 SET @saved_cs_client     = @@character_set_client */;\"\n                + \"\\n\"\n                + \"\\n/*!40101 SET character_set_client = utf8 */;\"\n                + \"\\n\"\n                + \"\\nCREATE TABLE `item_similarity` (\"\n                + \"\\n\\t`id` bigint(20) UNSIGNED NOT NULL,\"\n                + \"\\n\\t`sellerId` bigint(20) DEFAULT NULL,\"\n                + \"\\n\\tPRIMARY KEY (`id`)\"\n                + \"\\n) ENGINE = InnoDB CHARSET = utf8;\"\n                + \"\\n\"\n                + \"\\n/*!40101 SET character_set_client = @saved_cs_client */;\", rs);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"update \"\n                + \"/*MS-MRCHISHUB-MH-MESSAGE-UPDATE*/\\n\"\n                + \"/*+ INDEX(mh_message primary) */ \"\n                + \"mh_message set gmt_modified = now(),status= '099' where id = 1244918;\";\n        String rs = SQLUtils.formatMySql(sql);\n        assertEquals(\"UPDATE /*MS-MRCHISHUB-MH-MESSAGE-UPDATE*/\\n\" +\n                \"/*+ INDEX(mh_message primary) */ mh_message\\n\"\n                + \"SET gmt_modified = now(), status = '099'\\n\" + \"WHERE id = 1244918;\", rs);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlLateralTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLParseAssertUtil;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class MySqlLateralTest {\n    @Test\n    public void test_lateral_comma() {\n        String sql = \"SELECT * FROM t1, LATERAL (SELECT * FROM t2 WHERE t2.id = t1.id) AS lat\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql);\n        List<SQLStatement> stmts = parser.parseStatementList();\n        assertEquals(1, stmts.size());\n\n        SQLSelectStatement stmt = (SQLSelectStatement) stmts.get(0);\n        String output = stmt.toString();\n        assertTrue(output.contains(\"LATERAL\"));\n        SQLParseAssertUtil.assertParseSql(sql, DbType.mysql);\n    }\n\n    @Test\n    public void test_lateral_join() {\n        String sql = \"SELECT * FROM t1 JOIN LATERAL (SELECT * FROM t2 WHERE t2.a = t1.a LIMIT 3) AS sub ON true\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql);\n        List<SQLStatement> stmts = parser.parseStatementList();\n        assertEquals(1, stmts.size());\n\n        SQLSelectStatement stmt = (SQLSelectStatement) stmts.get(0);\n        String output = stmt.toString();\n        assertTrue(output.contains(\"LATERAL\"));\n        SQLParseAssertUtil.assertParseSql(sql, DbType.mysql);\n    }\n\n    @Test\n    public void test_lateral_subquery() {\n        String sql = \"SELECT t1.id, lat.total FROM orders t1, LATERAL (SELECT SUM(amount) AS total FROM order_items WHERE order_id = t1.id) AS lat\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql);\n        List<SQLStatement> stmts = parser.parseStatementList();\n        assertEquals(1, stmts.size());\n\n        SQLSelectStatement stmt = (SQLSelectStatement) stmts.get(0);\n        String output = stmt.toString();\n        assertTrue(output.contains(\"LATERAL\"));\n        SQLParseAssertUtil.assertParseSql(sql, DbType.mysql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlOptimizeTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlOptimizeTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"OPTIMIZE TABLE t1,t2\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"OPTIMIZE TABLE t1, t2\", //\n                output);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlOrderingExprTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;\nimport com.alibaba.druid.sql.ast.statement.SQLSelectStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author lizongbo\n */\npublic class MySqlOrderingExprTest {\n    @Test\n    public void test_order_column_0() throws Exception {\n        String sql = \"SELECT task_id, task_name FROM table_task WHERE task_count > 20  AND (task_date = '20230306'   OR task_date = '20230307') GROUP BY task_id ASC\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        SQLSelectStatement sss = (SQLSelectStatement) stmt;\n        MySqlSelectQueryBlock sqb = (MySqlSelectQueryBlock) sss.getSelect().getQueryBlock();\n        SQLSelectGroupByClause so = sqb.getGroupBy();\n        String groupByColumnName = so.getItems().get(0).toString();\n        System.out.println(groupByColumnName);\n        assertEquals(\"task_id ASC\", groupByColumnName);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlRepCheckTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.repository.Schema;\nimport com.alibaba.druid.sql.repository.SchemaObject;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class MySqlRepCheckTest {\n    private final SchemaRepository repository = new SchemaRepository(JdbcUtils.MYSQL);\n\n    @Test\n    public void test_check() {\n        MySqlRepCheckTest testRep = new MySqlRepCheckTest();\n        String schemaName = \"test_db\";\n        testRep.repository.setDefaultSchema(schemaName);\n        testRep.repository.console(\"CREATE TABLE `test_table` (\\n\" +\n                \"  `id` int NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  `action_flag` smallint unsigned NOT NULL,\\n\" +\n                \"  CONSTRAINT `chk_1` CHECK ((`action_flag` >= 0))\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci\");\n        Map<String, String> snapshot = testRep.snapshot();\n        System.out.println(snapshot.get(schemaName));\n    }\n\n    public Map<String, String> snapshot() {\n        Map<String, String> schemaDdls = new HashMap<String, String>();\n        for (Schema schema : repository.getSchemas()) {\n            StringBuilder data = new StringBuilder(4 * 1024);\n            for (String table : schema.showTables()) {\n                SchemaObject schemaObject = schema.findTable(table);\n                schemaObject.getStatement().output(data);\n                data.append(\"; \\n\");\n            }\n            schemaDdls.put(schema.getName(), data.toString());\n        }\n\n        return schemaDdls;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlRepTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcUtils;\n\npublic class MySqlRepTest {\n    public static void main(String[] args) {\n        SchemaRepository repository = new SchemaRepository(JdbcUtils.MYSQL);\n        repository.setDefaultSchema(\"test_db\");\n        repository.console(\"CREATE TABLE `test_table` (\" +\n                \"  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,\" +\n                \"  `varchar_column` varchar(64) DEFAULT '',\" +\n                \"  PRIMARY KEY (`id`))\");\n        try {\n            repository.console(\"CREATE INDEX idx_unikey ON test_db.test_table(varchar_column)\");\n            String ddl2 = \"drop index idx_ordinary on test_table\";\n            repository.console(ddl2);\n        } catch (Throwable e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlReplaceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlReplaceTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"replace into t1 (id,name) values('1','aa'),('2','bb')\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"REPLACE INTO t1 (id, name)\\n\" +\n                \"VALUES ('1', 'aa'), ('2', 'bb')\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"replace into t1 (id, name)\\n\" +\n                \"values ('1', 'aa'), ('2', 'bb')\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"t1\"));\n\n        assertTrue(visitor.containsColumn(\"t1\", \"id\"));\n        assertTrue(visitor.containsColumn(\"t1\", \"name\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlReplaceTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlReplaceTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"REPLACE INTO `tb_001` (`gmt_create`, `theday`, `pt`, `song_id`, `song_name`, `play_num_1d`) (SELECT now(), '20170820', case a.pt\\n\" +\n                \"        when 'android' then '安卓'\\n\" +\n                \"        when 'ios' then 'ios'\\n\" +\n                \"        when 'yunos' then '云os'\\n\" +\n                \"     end AS `pt`, a.song_id, if(b.song_name is null,'新发布歌曲',b.song_name), a.play_num_1d FROM ((SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' AND `pt` IN ('android') GROUP BY `pt`, `song_id` ORDER BY `play_num_1d` DESC LIMIT 0, 100) UNION (SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' AND `pt` IN ('ios') GROUP BY `pt`, `song_id` ORDER BY `play_num_1d` DESC LIMIT 0, 100) UNION (SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' AND `pt` IN ('yunos') GROUP BY `pt`, `song_id` ORDER BY `play_num_1d` DESC LIMIT 0, 100)) AS `a` INNER JOIN (SELECT song_id, song_name FROM `tb_003` WHERE `song_name` IS NOT NULL) AS `b` ON `a`.`song_id` = `b`.`song_id`) UNION (SELECT now(), '20170820', '整体' AS `pt`, a.song_id, if(b.song_name is null,'新发布歌曲',b.song_name), a.play_num_1d FROM (SELECT song_id, play_num_1d FROM (SELECT song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' GROUP BY `song_id`) AS `tmp` ORDER BY `play_num_1d` DESC LIMIT 0, 100) AS `a` INNER JOIN (SELECT song_id, song_name FROM `tb_003` WHERE `song_name` IS NOT NULL) AS `b` ON `a`.`song_id` = `b`.`song_id`)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(\"REPLACE INTO `tb_001` (`gmt_create`, `theday`, `pt`, `song_id`, `song_name`, `play_num_1d`)\\n\" +\n                \"\\t(SELECT now(), '20170820'\\n\" +\n                \"\\t\\t, CASE a.pt\\n\" +\n                \"\\t\\t\\tWHEN 'android' THEN '安卓'\\n\" +\n                \"\\t\\t\\tWHEN 'ios' THEN 'ios'\\n\" +\n                \"\\t\\t\\tWHEN 'yunos' THEN '云os'\\n\" +\n                \"\\t\\tEND AS `pt`, a.song_id\\n\" +\n                \"\\t\\t, if(b.song_name IS NULL, '新发布歌曲', b.song_name)\\n\" +\n                \"\\t\\t, a.play_num_1d\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\t(SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d`\\n\" +\n                \"\\t\\tFROM `tb_002`\\n\" +\n                \"\\t\\tWHERE `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tAND `pt` IN ('android')\\n\" +\n                \"\\t\\tGROUP BY `pt`, `song_id`\\n\" +\n                \"\\t\\tORDER BY `play_num_1d` DESC\\n\" +\n                \"\\t\\tLIMIT 0, 100)\\n\" +\n                \"\\t\\tUNION\\n\" +\n                \"\\t\\t(SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d`\\n\" +\n                \"\\t\\tFROM `tb_002`\\n\" +\n                \"\\t\\tWHERE `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tAND `pt` IN ('ios')\\n\" +\n                \"\\t\\tGROUP BY `pt`, `song_id`\\n\" +\n                \"\\t\\tORDER BY `play_num_1d` DESC\\n\" +\n                \"\\t\\tLIMIT 0, 100)\\n\" +\n                \"\\t\\tUNION\\n\" +\n                \"\\t\\t(SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d`\\n\" +\n                \"\\t\\tFROM `tb_002`\\n\" +\n                \"\\t\\tWHERE `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tAND `pt` IN ('yunos')\\n\" +\n                \"\\t\\tGROUP BY `pt`, `song_id`\\n\" +\n                \"\\t\\tORDER BY `play_num_1d` DESC\\n\" +\n                \"\\t\\tLIMIT 0, 100)\\n\" +\n                \"\\t) `a`\\n\" +\n                \"\\t\\tINNER JOIN (\\n\" +\n                \"\\t\\t\\tSELECT song_id, song_name\\n\" +\n                \"\\t\\t\\tFROM `tb_003`\\n\" +\n                \"\\t\\t\\tWHERE `song_name` IS NOT NULL\\n\" +\n                \"\\t\\t) `b`\\n\" +\n                \"\\t\\tON `a`.`song_id` = `b`.`song_id`)\\n\" +\n                \"\\tUNION\\n\" +\n                \"\\t(SELECT now(), '20170820', '整体' AS `pt`, a.song_id\\n\" +\n                \"\\t\\t, if(b.song_name IS NULL, '新发布歌曲', b.song_name)\\n\" +\n                \"\\t\\t, a.play_num_1d\\n\" +\n                \"\\tFROM (\\n\" +\n                \"\\t\\tSELECT song_id, play_num_1d\\n\" +\n                \"\\t\\tFROM (\\n\" +\n                \"\\t\\t\\tSELECT song_id, sum(play_num_1d) AS `play_num_1d`\\n\" +\n                \"\\t\\t\\tFROM `tb_002`\\n\" +\n                \"\\t\\t\\tWHERE `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tGROUP BY `song_id`\\n\" +\n                \"\\t\\t) `tmp`\\n\" +\n                \"\\t\\tORDER BY `play_num_1d` DESC\\n\" +\n                \"\\t\\tLIMIT 0, 100\\n\" +\n                \"\\t) `a`\\n\" +\n                \"\\t\\tINNER JOIN (\\n\" +\n                \"\\t\\t\\tSELECT song_id, song_name\\n\" +\n                \"\\t\\t\\tFROM `tb_003`\\n\" +\n                \"\\t\\t\\tWHERE `song_name` IS NOT NULL\\n\" +\n                \"\\t\\t) `b`\\n\" +\n                \"\\t\\tON `a`.`song_id` = `b`.`song_id`)\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"replace into `tb_001` (`gmt_create`, `theday`, `pt`, `song_id`, `song_name`, `play_num_1d`)\\n\" +\n                \"\\t(select now(), '20170820'\\n\" +\n                \"\\t\\t, case a.pt\\n\" +\n                \"\\t\\t\\twhen 'android' then '安卓'\\n\" +\n                \"\\t\\t\\twhen 'ios' then 'ios'\\n\" +\n                \"\\t\\t\\twhen 'yunos' then '云os'\\n\" +\n                \"\\t\\tend as `pt`, a.song_id\\n\" +\n                \"\\t\\t, if(b.song_name is null, '新发布歌曲', b.song_name)\\n\" +\n                \"\\t\\t, a.play_num_1d\\n\" +\n                \"\\tfrom (\\n\" +\n                \"\\t\\t(select pt, song_id, sum(play_num_1d) as `play_num_1d`\\n\" +\n                \"\\t\\tfrom `tb_002`\\n\" +\n                \"\\t\\twhere `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tand `pt` in ('android')\\n\" +\n                \"\\t\\tgroup by `pt`, `song_id`\\n\" +\n                \"\\t\\torder by `play_num_1d` desc\\n\" +\n                \"\\t\\tlimit 0, 100)\\n\" +\n                \"\\t\\tunion\\n\" +\n                \"\\t\\t(select pt, song_id, sum(play_num_1d) as `play_num_1d`\\n\" +\n                \"\\t\\tfrom `tb_002`\\n\" +\n                \"\\t\\twhere `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tand `pt` in ('ios')\\n\" +\n                \"\\t\\tgroup by `pt`, `song_id`\\n\" +\n                \"\\t\\torder by `play_num_1d` desc\\n\" +\n                \"\\t\\tlimit 0, 100)\\n\" +\n                \"\\t\\tunion\\n\" +\n                \"\\t\\t(select pt, song_id, sum(play_num_1d) as `play_num_1d`\\n\" +\n                \"\\t\\tfrom `tb_002`\\n\" +\n                \"\\t\\twhere `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tand `pt` in ('yunos')\\n\" +\n                \"\\t\\tgroup by `pt`, `song_id`\\n\" +\n                \"\\t\\torder by `play_num_1d` desc\\n\" +\n                \"\\t\\tlimit 0, 100)\\n\" +\n                \"\\t) `a`\\n\" +\n                \"\\t\\tinner join (\\n\" +\n                \"\\t\\t\\tselect song_id, song_name\\n\" +\n                \"\\t\\t\\tfrom `tb_003`\\n\" +\n                \"\\t\\t\\twhere `song_name` is not null\\n\" +\n                \"\\t\\t) `b`\\n\" +\n                \"\\t\\ton `a`.`song_id` = `b`.`song_id`)\\n\" +\n                \"\\tunion\\n\" +\n                \"\\t(select now(), '20170820', '整体' as `pt`, a.song_id\\n\" +\n                \"\\t\\t, if(b.song_name is null, '新发布歌曲', b.song_name)\\n\" +\n                \"\\t\\t, a.play_num_1d\\n\" +\n                \"\\tfrom (\\n\" +\n                \"\\t\\tselect song_id, play_num_1d\\n\" +\n                \"\\t\\tfrom (\\n\" +\n                \"\\t\\t\\tselect song_id, sum(play_num_1d) as `play_num_1d`\\n\" +\n                \"\\t\\t\\tfrom `tb_002`\\n\" +\n                \"\\t\\t\\twhere `theday` = '20170820'\\n\" +\n                \"\\t\\t\\tgroup by `song_id`\\n\" +\n                \"\\t\\t) `tmp`\\n\" +\n                \"\\t\\torder by `play_num_1d` desc\\n\" +\n                \"\\t\\tlimit 0, 100\\n\" +\n                \"\\t) `a`\\n\" +\n                \"\\t\\tinner join (\\n\" +\n                \"\\t\\t\\tselect song_id, song_name\\n\" +\n                \"\\t\\t\\tfrom `tb_003`\\n\" +\n                \"\\t\\t\\twhere `song_name` is not null\\n\" +\n                \"\\t\\t) `b`\\n\" +\n                \"\\t\\ton `a`.`song_id` = `b`.`song_id`)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(3, visitor.getTables().size());\n        assertEquals(13, visitor.getColumns().size());\n        assertEquals(6, visitor.getConditions().size());\n\n        assertTrue(visitor.containsTable(\"tb_001\"));\n\n//        assertTrue(visitor.containsColumn(\"t1\", \"id\"));\n//        assertTrue(visitor.containsColumn(\"t1\", \"name\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlResourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.bvt.sql.SQLResourceTest;\nimport org.junit.jupiter.api.Test;\n\npublic class MySqlResourceTest extends SQLResourceTest {\n    public MySqlResourceTest() {\n        super(DbType.mysql);\n    }\n\n    @Test\n    public void mysql_parse() throws Exception {\n        fileTest(0, 999, i -> \"bvt/parser/mysql/\" + i + \".txt\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlRevokeTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlRevokeTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"REVOKE INSERT ON *.* FROM 'jeffrey'@'localhost';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        for (SQLStatement stmt : statementList) {\n            stmt.accept(visitor);\n        }\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        {\n            String output = SQLUtils.toSQLString(statementList, JdbcConstants.MYSQL);\n            assertEquals(\"REVOKE INSERT ON *.* FROM 'jeffrey'@'localhost';\", //\n                    output);\n        }\n        {\n            String output = SQLUtils.toSQLString(statementList, JdbcConstants.MYSQL, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"revoke insert on *.* from 'jeffrey'@'localhost';\", //\n                    output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSetPasswordTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlSetPasswordTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"SET PASSWORD FOR 'bob'@'%.example.org' = PASSWORD('cleartext password');\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SET PASSWORD FOR 'bob'@'%.example.org' = PASSWORD('cleartext password');\", //\n                output);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSetTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlSetTest_0 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n//        print(stmtList);\n\n        assertEquals(1, stmtList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String text = output(stmtList);\n\n        assertEquals(\"SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSetTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlSetTest_1 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SET @@session.autocommit = ON;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n//        print(stmtList);\n\n        assertEquals(1, stmtList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String text = SQLUtils.toMySqlString(stmt);\n\n        assertEquals(\"SET @@session.autocommit = ON;\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSetTest_2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlSetTest_2 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"set character set utf8, names utf8mb4;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n//        print(stmtList);\n\n        assertEquals(1, stmtList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String text = SQLUtils.toMySqlString(stmt);\n\n        assertEquals(\"SET CHARACTER SET utf8, NAMES utf8mb4;\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSetTest_3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlSetTest_3 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SET sql_mode=?,NAMES ?,CHARACTER SET utf8,CHARACTER_SET_RESULTS=utf8,COLLATION_CONNECTION=?\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n//        print(stmtList);\n\n        assertEquals(1, stmtList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String text = SQLUtils.toMySqlString(stmt);\n\n        assertEquals(\"SET sql_mode = ?, NAMES ?, CHARACTER SET utf8, CHARACTER_SET_RESULTS = utf8, COLLATION_CONNECTION = ?\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        SQLUtils.parseSingleStatement(\"set names utf8mb4\", \"mysql\");\n        SQLUtils.parseSingleStatement(\"set names utf8mb4\", (DbType) null);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlTest_Char.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * 测试char()  CHAR(N,... [USING charset_name])\n */\npublic class MySqlTest_Char extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"SELECT char(888 using utf8)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n        assertEquals(output(statementList), \"SELECT char(888 USING utf8)\");\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"SELECT char('abc8a9b10c' using utf8)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n        assertEquals(output(statementList), \"SELECT char('abc8a9b10c' USING utf8)\");\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"SELECT char(12,321,'lq9s9f','abc8a9b10c' using utf8)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n        assertEquals(output(statementList), \"SELECT char(12, 321, 'lq9s9f', 'abc8a9b10c' USING utf8)\");\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"SELECT char(12,321,'lq9s9f','abc8a9b10c')\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n        assertEquals(output(statementList), \"SELECT char(12, 321, 'lq9s9f', 'abc8a9b10c')\");\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"SELECT CHAR(77,121,83,81,'76' using utf8)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n        assertEquals(output(statementList), \"SELECT CHAR(77, 121, 83, 81, '76' USING utf8)\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlTruncateTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlTruncateTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"truncate table city_list-- test\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"TRUNCATE TABLE city_list\", //\n                    output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"truncate table city_list\", //\n                    output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlUpdateStatementLimitTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlUpdateStatementLimitTest {\n    @Test\n    public void test_limit() {\n        String sql = \"update t set name = 'x' where id < 100 limit 10\";\n        String rs = SQLUtils.formatMySql(sql);\n        assertEquals(\"UPDATE t\"\n                + \"\\nSET name = 'x'\"\n                + \"\\nWHERE id < 100\"\n                + \"\\nLIMIT 10\", rs);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlUseTest_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlUseTest_0 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"use db;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n        assertEquals(0, visitor.getOrderByColumns().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"mytable\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MysqlCheckTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;\nimport com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableAddConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableDropConstraint;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCheck;\nimport com.alibaba.druid.sql.ast.statement.SQLTableElement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MysqlAlterTableAlterCheck;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlExportParameterVisitor;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.fastjson2.JSON;\n\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MysqlCheckTest extends MysqlTest {\n    public void testEndTokenChecking() throws Exception {\n        Object[][] samples = {\n                    {\"update test_tab1 set b= 1 swhere a=1\", false, true},\n                    {\"select * from test_tab1 swhere  a=1\", false, true},\n                    {\"delete from test_tab1 \\n swhere  a=1\", false, true},\n                    {\"delete from test_tab1 where a=1\", true, true},\n                    {\"delete from test_tab1 \\n where a=1     \\n\", true, true},\n                    {\"IF age>20 THEN SET @count1=@count1+1/* a */;\\n\"\n                            + \"    ELSEIF age=20 THEN SET @count2=@count2+1;/* b */\\n\"\n                            + \"    ELSE SET @count3=@count3+1;\\n\"\n                            + \"/* c */ END IF/*d*/;\", true, false}\n                };\n\n        for (final Object[] arr : samples) {\n            String sql = (String) arr[0];\n            final boolean ok = Boolean.TRUE.equals(arr[1]);\n            final boolean hasWhere = Boolean.TRUE.equals(arr[2]);\n            try {\n                System.out.println(\"before sql:\" + sql);\n                final StringBuilder out = new StringBuilder();\n                final MySqlExportParameterVisitor visitor = new MySqlExportParameterVisitor(out);\n                visitor.setParameterizedMergeInList(true);\n                SQLStatementParser parser = new MySqlStatementParser(sql);\n                final SQLStatement parseStatement = parser.parseStatement();\n                parseStatement.accept(visitor);\n                final List<Object> plist = visitor.getParameters();\n                sql = out.toString();\n                System.out.println(\"after sql:\" + sql);\n                System.out.println(\"params: \" + plist);\n                if (hasWhere) {\n                    assertEquals(\"[1]\", JSON.toJSONString(plist));\n                    assertTrue(Pattern.compile(\"(?i)(^|\\\\s+)where(\\\\s+|$)\").matcher(sql).find());\n                }\n                if (!ok) {\n                    fail();\n                }\n            } catch (ParserException ex) {\n                if (ok) {\n                    fail();\n                } else {\n                    ex.printStackTrace();\n                }\n            }\n        }\n    }\n\n    public void test_create1() {\n        String sql = \"CREATE TABLE `t12` (\\n\" +\n                \"  `c1` int DEFAULT NULL,\\n\" +\n                \"  `c2` int DEFAULT NULL,\\n\" +\n                \"  `c3` int DEFAULT NULL,\\n\" +\n                \"  CONSTRAINT `c12_positive` CHECK ((`c2` > 0)) /*!80016 NOT ENFORCED */,\\n\" +\n                \"  CONSTRAINT `c21_nonzero` CHECK ((`c1` <> 0)),\\n\" +\n                \"  CONSTRAINT `t12_chk_1` CHECK ((`c1` <> `c2`)),\\n\" +\n                \"  CONSTRAINT `t12_chk_2` CHECK ((`c1` > 10)),\\n\" +\n                \"  CONSTRAINT `t12_chk_3` CHECK (((`c3` < 100) and (`c3` > 0))),\\n\" +\n                \"  CONSTRAINT `t12_chk_4` CHECK ((`c1` > `c3`))\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement statement = (MySqlCreateTableStatement) statementList.get(0);\n        assertEquals(9, statement.getTableElementList().size());\n        {\n            SQLTableElement element = statement.getTableElementList().get(3);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertFalse(sqlCheck.getEnforced());\n            assertEquals(\"`c12_positive`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c2` > 0)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(4);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`c21_nonzero`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` <> 0)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(5);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_1`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` <> `c2`)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(6);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_2`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` > 10)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(7);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_3`\", sqlCheck.getName().getSimpleName());\n            assertTrue(sqlCheck.getExpr() instanceof SQLBinaryOpExpr);\n            assertEquals(SQLBinaryOperator.BooleanAnd, ((SQLBinaryOpExpr) sqlCheck.getExpr()).getOperator());\n            assertEquals(\"(`c3` < 100)\", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getLeft().toString());\n            assertEquals(\"(`c3` > 0)\", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getRight().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(8);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_4`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` > `c3`)\", sqlCheck.getExpr().toString());\n        }\n    }\n\n    public void test_create2() {\n        String sql = \"CREATE TABLE `t12` (\\n\" +\n                \"\\t`c1` int DEFAULT NULL,\\n\" +\n                \"\\t`c2` int DEFAULT NULL,\\n\" +\n                \"\\t`c3` int DEFAULT NULL,\\n\" +\n                \"\\tCONSTRAINT `c12_positive` CHECK (`c2` > 0) NOT ENFORCED,\\n\" +\n                \"\\tCONSTRAINT `c21_nonzero` CHECK (`c1` <> 0),\\n\" +\n                \"\\tCONSTRAINT `t12_chk_1` CHECK (`c1` <> `c2`),\\n\" +\n                \"\\tCONSTRAINT `t12_chk_2` CHECK (`c1` > 10),\\n\" +\n                \"\\tCONSTRAINT `t12_chk_3` CHECK (`c3` < 100\\n\" +\n                \"\\t\\tAND `c3` > 0),\\n\" +\n                \"\\tCONSTRAINT `t12_chk_4` CHECK (`c1` > `c3`)\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;\\n\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement statement = (MySqlCreateTableStatement) statementList.get(0);\n        assertEquals(9, statement.getTableElementList().size());\n        {\n            SQLTableElement element = statement.getTableElementList().get(3);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertFalse(sqlCheck.getEnforced());\n            assertEquals(\"`c12_positive`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c2` > 0)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(4);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`c21_nonzero`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` <> 0)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(5);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_1`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` <> `c2`)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(6);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_2`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` > 10)\", sqlCheck.getExpr().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(7);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_3`\", sqlCheck.getName().getSimpleName());\n            assertTrue(sqlCheck.getExpr() instanceof SQLBinaryOpExpr);\n            assertEquals(SQLBinaryOperator.BooleanAnd, ((SQLBinaryOpExpr) sqlCheck.getExpr()).getOperator());\n            assertEquals(\"`c3` < 100\", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getLeft().toString());\n            assertEquals(\"`c3` > 0\", ((SQLBinaryOpExpr) sqlCheck.getExpr()).getRight().toString());\n        }\n        {\n            SQLTableElement element = statement.getTableElementList().get(8);\n            assertTrue(element instanceof SQLCheck);\n            SQLCheck sqlCheck = (SQLCheck) element;\n            assertNull(sqlCheck.getEnforced());\n            assertEquals(\"`t12_chk_4`\", sqlCheck.getName().getSimpleName());\n            assertEquals(\"(`c1` > `c3`)\", sqlCheck.getExpr().toString());\n        }\n    }\n\n    public void test_alter_add1() {\n        String sql = \"ALTER TABLE t1 ADD CONSTRAINT chk1 CHECK((a>1));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n        assertTrue(statementList.get(0) instanceof SQLAlterTableStatement);\n        SQLAlterTableStatement statement = (SQLAlterTableStatement) statementList.get(0);\n        assertEquals(1, statement.getItems().size());\n\n        assertTrue(statement.getItems().get(0) instanceof SQLAlterTableAddConstraint);\n        SQLAlterTableAddConstraint constraint = (SQLAlterTableAddConstraint) statement.getItems().get(0);\n\n        assertTrue(constraint.getConstraint() instanceof SQLCheck);\n\n        SQLCheck sqlCheck = (SQLCheck) constraint.getConstraint();\n        assertNull(sqlCheck.getEnforced());\n        assertEquals(\"chk1\", sqlCheck.getName().getSimpleName());\n        assertEquals(\"(a > 1)\", sqlCheck.getExpr().toString());\n    }\n\n    public void test_alter_add2() {\n        String sql = \"ALTER TABLE t1 ADD CONSTRAINT chk1 CHECK((a>1)) NOT ENFORCED; \";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n        assertTrue(statementList.get(0) instanceof SQLAlterTableStatement);\n        SQLAlterTableStatement statement = (SQLAlterTableStatement) statementList.get(0);\n        assertEquals(1, statement.getItems().size());\n\n        assertTrue(statement.getItems().get(0) instanceof SQLAlterTableAddConstraint);\n        SQLAlterTableAddConstraint constraint = (SQLAlterTableAddConstraint) statement.getItems().get(0);\n\n        assertTrue(constraint.getConstraint() instanceof SQLCheck);\n\n        SQLCheck sqlCheck = (SQLCheck) constraint.getConstraint();\n        assertFalse(sqlCheck.getEnforced());\n        assertEquals(\"chk1\", sqlCheck.getName().getSimpleName());\n        assertEquals(\"(a > 1)\", sqlCheck.getExpr().toString());\n    }\n\n    public void test_alter_drop() {\n        String sql = \"ALTER TABLE t1 DROP CONSTRAINT t1_check ;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        SQLAlterTableStatement statement = (SQLAlterTableStatement) statementList.get(0);\n        assertEquals(1, statement.getItems().size());\n\n        assertTrue(statement.getItems().get(0) instanceof SQLAlterTableDropConstraint);\n        SQLAlterTableDropConstraint constraint = (SQLAlterTableDropConstraint) statement.getItems().get(0);\n\n        assertEquals(\"t1_check\", constraint.getConstraintName().getSimpleName());\n    }\n\n    public void test_alter_alter1() {\n        String sql = \"alter table t1 ALTER CHECK  t1_check  ENFORCED;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        SQLAlterTableStatement statement = (SQLAlterTableStatement) statementList.get(0);\n        assertEquals(1, statement.getItems().size());\n\n        assertTrue(statement.getItems().get(0) instanceof MysqlAlterTableAlterCheck);\n        MysqlAlterTableAlterCheck constraint = (MysqlAlterTableAlterCheck) statement.getItems().get(0);\n\n        assertEquals(\"t1_check\", constraint.getName().getSimpleName());\n        assertTrue(constraint.getEnforced());\n    }\n\n    public void test_alter_alter2() {\n        String sql = \"alter table t1 ALTER CHECK  t1_check  NOT ENFORCED;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        System.out.println(stmt);\n\n        assertEquals(1, statementList.size());\n\n        SQLAlterTableStatement statement = (SQLAlterTableStatement) statementList.get(0);\n        assertEquals(1, statement.getItems().size());\n\n        assertTrue(statement.getItems().get(0) instanceof MysqlAlterTableAlterCheck);\n        MysqlAlterTableAlterCheck constraint = (MysqlAlterTableAlterCheck) statement.getItems().get(0);\n\n        assertEquals(\"t1_check\", constraint.getName().getSimpleName());\n        assertFalse(constraint.getEnforced());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/MysqlKeywordsTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\npublic class MysqlKeywordsTest {\n    @Test\n    public void test_keywords() {\n        DbType dbType = DbType.mysql;\n        String sql = \"SELECT TIMESTAMPADD(MONTH, 2, sysdate()) FROM dual\";\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql,\n                dbType,\n                SQLParserFeature.IgnoreNameQuotes);\n        SQLStatement stmt = parser.parseStatement();\n        assertEquals(Token.EOF, parser.getLexer().token());\n        String result = SQLUtils.toSQLString(stmt, dbType, null, VisitorFeature.OutputNameQuote).trim();\n        String expectedSql = \"SELECT TIMESTAMPADD(MONTH, 2, sysdate())\\n\" + \"FROM dual\";\n        assertEquals(expectedSql, result);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/NumberTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class NumberTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT -32032.6809e+10;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SELECT -32032.6809e+10;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT 294.42;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SELECT 294.42;\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/REPLACE_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class REPLACE_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"REPLACE INTO T SELECT * FROM T;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"REPLACE INTO T\\n\\tSELECT *\\n\\tFROM T;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"REPLACE DELAYED INTO `online_users` SET `session_id`='3580cc4e61117c0785372c426eddd11c', `user_id` = 'XXX', `page` = '/', `lastview` = NOW();\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"REPLACE DELAYED INTO `online_users` (`session_id`, `user_id`, `page`, `lastview`)\\nVALUES ('3580cc4e61117c0785372c426eddd11c', 'XXX', '/', NOW());\",\n                text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \" replace into t(col1,col2)values(?,?)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"REPLACE INTO t (col1, col2)\\nVALUES (?, ?)\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/RegularExpressionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class RegularExpressionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT 'Monty!' REGEXP '.*'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'Monty!' REGEXP '.*';\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT 'new*\\n*line' REGEXP 'new\\\\\\\\*.\\\\\\\\*line'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        String e = \"SELECT 'new*\\n*line' REGEXP 'new\\\\*.\\\\*line';\";\n\n        assertEquals(\"SELECT 'new*\\n*line' REGEXP 'new\\\\\\\\*.\\\\\\\\*line';\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A';\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT 'a' REGEXP '^[a-d]'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'a' REGEXP '^[a-d]';\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT 'fo\\nfo' REGEXP '^fo$'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'fo\\nfo' REGEXP '^fo$';\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT 'fofo' REGEXP '^fo'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'fofo' REGEXP '^fo';\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT '~' REGEXP '[[.tilde.]]'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '~' REGEXP '[[.tilde.]]';\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        StringBuilder out = new StringBuilder();\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(new MySqlOutputVisitor(out));\n            out.append(\";\");\n        }\n\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/Reset_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class Reset_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"binlog  'str'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"BINLOG 'str';\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        StringBuilder out = new StringBuilder();\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(new MySqlOutputVisitor(out));\n            out.append(\";\");\n        }\n\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SELECT_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SELECT_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"SELECT year, SUM(profit)\\nFROM sales\\nGROUP BY year WITH ROLLUP;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"select year, sum(profit)\\nfrom sales\\ngroup by year with rollup;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT * FROM T FOR UPDATE;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT *\\nFROM T\\nFOR UPDATE;\", text);\n    }\n\n    @Test\n    public void test_with_cube() throws Exception {\n        String sql = \"SELECT year, SUM(profit) FROM sales GROUP BY year WITH CUBE;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"SELECT year, SUM(profit)\\nFROM sales\\nGROUP BY year WITH CUBE;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"select year, sum(profit)\\nfrom sales\\ngroup by year with cube;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT * FROM T LOCK IN SHARE MODE;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT *\\nFROM T\\nLOCK IN SHARE MODE;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\\\"' LINES TERMINATED BY '\\\\n' FROM test_table;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT a, b, a + b\\nINTO OUTFILE '/tmp/result.txt' COLUMNS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\\\"' LINES TERMINATED BY '\\n'\\nFROM test_table;\",\n                text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT 1 + 1 FROM DUAL;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 + 1\\nFROM DUAL;\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT 1 + 1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 1 + 1;\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE column1 = (\\n\" +\n                \"\\tSELECT column1\\n\" +\n                \"\\tFROM t2\\n\" +\n                \");\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT column1\"\n                + \"\\nFROM t1\"\n                + \"\\nWHERE EXISTS (\"\n                + \"\\n\\tSELECT *\"\n                + \"\\n\\tFROM t2\"\n                + \"\\n);\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT DISTINCT store_type FROM stores WHERE NOT EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT DISTINCT store_type\"\n                        + \"\\nFROM stores\"\n                        + \"\\nWHERE NOT EXISTS (\"\n                        + \"\\n\\tSELECT *\"\n                        + \"\\n\\tFROM cities_stores\"\n                        + \"\\n\\tWHERE cities_stores.store_type = stores.store_type\"\n                        + \"\\n);\",\n                text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT s1 FROM t1 WHERE s1 = SOME (SELECT s1 FROM t2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT s1\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE s1 = SOME (\\n\" +\n                \"\\tSELECT s1\\n\" +\n                \"\\tFROM t2\\n\" +\n                \");\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT s1\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE s1 = ANY (\\n\" +\n                \"\\tSELECT s1\\n\" +\n                \"\\tFROM t2\\n\" +\n                \");\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT s1\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE s1 > ALL (\\n\" +\n                \"\\tSELECT s1\\n\" +\n                \"\\tFROM t2\\n\" +\n                \");\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"SELECT s1\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE s1 NOT IN (\\n\" +\n                \"\\tSELECT s1\\n\" +\n                \"\\tFROM t2\\n\" +\n                \");\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"select s1\\n\" +\n                \"from t1\\n\" +\n                \"where s1 not in (\\n\" +\n                \"\\tselect s1\\n\" +\n                \"\\tfrom t2\\n\" +\n                \");\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT s1 FROM t1 WHERE s1 IN (SELECT s1 FROM t2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"SELECT s1\\n\" +\n                \"FROM t1\\n\" +\n                \"WHERE s1 IN (\\n\" +\n                \"\\tSELECT s1\\n\" +\n                \"\\tFROM t2\\n\" +\n                \");\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"select s1\\n\" +\n                \"from t1\\n\" +\n                \"where s1 in (\\n\" +\n                \"\\tselect s1\\n\" +\n                \"\\tfrom t2\\n\" +\n                \");\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_14() throws Exception {\n        String sql = \"SELECT s1 FROM t1 WHERE s1 IN (?, ?, ?);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"SELECT s1\\nFROM t1\\nWHERE s1 IN (?, ?, ?);\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"select s1\\nfrom t1\\nwhere s1 in (?, ?, ?);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_15() throws Exception {\n        String sql = \"SELECT s1 FROM t1 WHERE s1 NOT IN (?, ?, ?);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"SELECT s1\\nFROM t1\\nWHERE s1 NOT IN (?, ?, ?);\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"select s1\\nfrom t1\\nwhere s1 not in (?, ?, ?);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_16() throws Exception {\n        // test some keywords that MySQL allows them to be taken as field alias.\n        String[] sqls = {\n                \"select a.da comment from (select a ad from a ) t\",\n                \"select orderId, orderCode from ( select  pms_order.remark comment from pms_order) t_order\",\n                \"select ada comment from (select a comment from a ) t\",\n                \"select comment from (select a comment from a ) t\",\n                \"select a TRUNCATE from  t\",\n                \"select a view from  t\",\n                \"select a SEQUENCE, (select 1) bb,(select id from tt limit 1) view from  (select a do from b) `truncate` \",\n                \"select a tablespace from  t\",\n                \"select a do from  t\",\n                \"select a any from  t limit 5\",\n                \"select a close from  t limit 5\",\n                \"select a , (select b SEQUENCE from demo limit 1) from t\",\n                \"select a enable from t\",\n                \"select a disable from t\",\n                \"select a cast from t\",\n                \"select a escape from t\",\n                \"select a minus from t\",\n                \"select a some from t\",\n                \"select a compute from t\",\n                \"select a until from t\",\n                \"select a open from t\"\n        };\n\n        String[] expectedSqls = {\n                \"SELECT a.da AS comment\\nFROM (\\n\\tSELECT a AS ad\\n\\tFROM a\\n) t\",\n                \"SELECT orderId, orderCode\\nFROM (\\n\\tSELECT pms_order.remark AS comment\\n\\tFROM pms_order\\n) t_order\",\n                \"SELECT ada AS comment\\nFROM (\\n\\tSELECT a AS comment\\n\\tFROM a\\n) t\",\n                \"SELECT comment\\nFROM (\\n\\tSELECT a AS comment\\n\\tFROM a\\n) t\",\n                \"SELECT a AS TRUNCATE\\nFROM t\",\n                \"SELECT a AS view\\nFROM t\",\n                \"SELECT a AS SEQUENCE\\n\\t, (\\n\\t\\tSELECT 1\\n\\t) AS bb\\n\\t, (\\n\\t\\tSELECT id\\n\\t\\tFROM tt\\n\\t\\tLIMIT 1\\n\\t) AS view\\nFROM (\\n\\tSELECT a AS do\\n\\tFROM b\\n) `truncate`\",\n                \"SELECT a AS tablespace\\nFROM t\",\n                \"SELECT a AS do\\nFROM t\",\n                \"SELECT a AS any\\nFROM t\\nLIMIT 5\",\n                \"SELECT a AS close\\nFROM t\\nLIMIT 5\",\n                \"SELECT a\\n\\t, (\\n\\t\\tSELECT b AS SEQUENCE\\n\\t\\tFROM demo\\n\\t\\tLIMIT 1\\n\\t)\\nFROM t\",\n                \"SELECT a AS enable\\nFROM t\",\n                \"SELECT a AS disable\\nFROM t\",\n                \"SELECT a AS cast\\nFROM t\",\n                \"SELECT a AS escape\\nFROM t\",\n                \"SELECT a AS minus\\nFROM t\",\n                \"SELECT a AS some\\nFROM t\",\n                \"SELECT a AS compute\\nFROM t\",\n                \"SELECT a AS until\\nFROM t\",\n                \"SELECT a AS open\\nFROM t\"\n        };\n\n        for (int i = 0; i < sqls.length; i++) {\n            MySqlStatementParser parser = new MySqlStatementParser(sqls[i]);\n            List<SQLStatement> parseStatementList = parser.parseStatementList();\n            assertEquals(1, parseStatementList.size());\n            assertEquals(expectedSqls[i], parseStatementList.get(0).toString());\n        }\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SHOW_COLUMNS_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SHOW_COLUMNS_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SHOW COLUMNS FROM City;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW COLUMNS FROM City;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SHOW COLUMNS FROM mytable FROM mydb;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW COLUMNS FROM mydb.mytable;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SHOW COLUMNS FROM mydb.mytable;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW COLUMNS FROM mydb.mytable;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SHOW COLUMNS FROM mytable IN mydb;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW COLUMNS FROM mydb.mytable;\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SHOW_DATABASES_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SHOW_DATABASES_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SHOW DATABASES;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SHOW DATABASES;\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SHOW_STATUS_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SHOW_STATUS_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SHOW STATUS LIKE 'Key%'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW STATUS LIKE 'Key%';\", text);\n    }\n\n    @Test\n    public void test_where() throws Exception {\n        String sql = \"SHOW STATUS WHERE X LIKE 'Key%'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW STATUS WHERE X LIKE 'Key%';\", text);\n    }\n\n    @Test\n    public void test_corba() throws Exception {\n        String sql = \"SHOW COBAR_STATUS\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW COBAR_STATUS;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SHOW GLOBAL STATUS LIKE 'Key%'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW GLOBAL STATUS LIKE 'Key%';\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SHOW SESSION STATUS LIKE 'Key%'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW SESSION STATUS LIKE 'Key%';\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SHOW SESSION STATUS\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SHOW SESSION STATUS;\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        StringBuilder out = new StringBuilder();\n\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(new MySqlOutputVisitor(out));\n            out.append(\";\");\n        }\n\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SHOW_TABLES_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SHOW_TABLES_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SHOW TABLES FROM     SUNTEST   \";\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW TABLES FROM SUNTEST\", text);\n\n        sql = \"SHOW       TABLES\";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW TABLES\", text);\n\n        sql = \"SHOW   FULL    TABLES\";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW FULL TABLES\", text);\n\n        sql = \"SHOW   FULL    TABLES    FROM    SUNTEST   \";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW FULL TABLES FROM SUNTEST\", text);\n\n        sql = \"SHOW TABLES IN SUNTEST   \";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW TABLES FROM SUNTEST\", text);\n\n        sql = \"SHOW FULL TABLES IN SUNTEST   \";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW FULL TABLES FROM SUNTEST\", text);\n\n        sql = \"SHOW FULL TABLES IN SUNTEST  LIKE '%DDD%' \";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW FULL TABLES FROM SUNTEST LIKE '%DDD%'\", text);\n\n        sql = \"SHOW FULL TABLES FROM SUNTEST  LIKE '%DDD%' \";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW FULL TABLES FROM SUNTEST LIKE '%DDD%'\", text);\n\n        sql = \"SHOW FULL TABLES IN SUNTEST  WHERE NAME =  'DDD' \";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW FULL TABLES FROM SUNTEST WHERE NAME = 'DDD'\", text);\n\n        sql = \"SHOW FULL TABLES FROM SUNTEST  WHERE NAME =  'DDD' \";\n        parser = new MySqlStatementParser(sql);\n        stmtList = parser.parseStatementList();\n        text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n        assertEquals(\"SHOW FULL TABLES FROM SUNTEST WHERE NAME = 'DDD'\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SHOW_WARNINGS_Syntax_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SHOW_WARNINGS_Syntax_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SHOW WARNINGS;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SHOW WARNINGS;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SHOW COUNT(*) WARNINGS;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SHOW COUNT(*) WARNINGS;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SHOW WARNINGS LIMIT 1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SHOW WARNINGS LIMIT 1;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SHOW WARNINGS LIMIT 10, 10;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SHOW WARNINGS LIMIT 10, 10;\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLSelectTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\npublic class SQLSelectTest {\n    @Test\n    public void test_select() throws Exception {\n        String sql = \"SELECT ALL FID FROM T1;SELECT DISTINCT FID FROM T1;SELECT DISTINCTROW FID FROM T1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        String sql = \"SELECT HIGH_PRIORITY STRAIGHT_JOIN SQL_SMALL_RESULT SQL_BIG_RESULT SQL_BUFFER_RESULT FID FROM T1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    @Test\n    public void test_select_2() throws Exception {\n        String sql = \"SELECT SQL_CACHE FID FROM T1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    @Test\n    public void test_select_3() throws Exception {\n        String sql = \"SELECT SQL_NO_CACHE FID FROM T1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    @Test\n    public void test_select_4() throws Exception {\n        String sql = \"SELECT SQL_CALC_FOUND_ROWS FID FROM T1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    @Test\n    public void test_select_5() throws Exception {\n        String sql = \"SELECT 1 + 1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    @Test\n    public void test_select_6() throws Exception {\n        String sql = \"SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    @Test\n    public void test_select_7() throws Exception {\n        String sql = \"select * from ((select * from test1) UNION (select * from test2) UNION (select * from test3)) where t1='温高铁';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        output(stmtList);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        StringBuilder out = new StringBuilder();\n        for (SQLStatement stmt : stmtList) {\n            stmt.accept(new MySqlOutputVisitor(out));\n//            System.out.println(\";\");\n//            System.out.println();\n        }\n        return out.toString();\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsAddColumnTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsAddColumnTest {\n    @Test\n    public void test_select() throws Exception {\n        assertEquals(\"SELECT id, name\"\n                + \"\\nFROM t\", SQLUtils.addSelectItem(\"select id from t\", \"name\", null, null));\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        assertEquals(\"SELECT id, name AS XX\"\n                + \"\\nFROM t\", SQLUtils.addSelectItem(\"select id from t\", \"name\", \"XX\", null));\n    }\n\n    @Test\n    public void test_select_2() throws Exception {\n        assertEquals(\"SELECT id, name AS \\\"XX W\\\"\"\n                + \"\\nFROM t\", SQLUtils.addSelectItem(\"select id from t\", \"name\", \"XX W\", null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsAddConditionTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsAddConditionTest {\n    @Test\n    public void test_select() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"select * from t\", \"id = 0\", null));\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"select * from t where id = 0\", \"name = 'aaa'\", null));\n    }\n\n    @Test\n    public void test_delete() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"delete from t\", \"id = 0\", null));\n    }\n\n    @Test\n    public void test_delete_1() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"delete from t where id = 0\", \"name = 'aaa'\", null));\n    }\n\n    @Test\n    public void test_update() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"update t set f1 = ?\", \"id = 0\", null));\n    }\n\n    @Test\n    public void test_update_1() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'bb'\", SQLUtils.addCondition(\"update t set f1 = ? where id = 0\", \"name = 'bb'\", null));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsAddConditionTest_mysql.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsAddConditionTest_mysql {\n    @Test\n    public void test_select() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"select * from t\", \"id = 0\", DbType.mysql));\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"select * from t where id = 0\", \"name = 'aaa'\", DbType.mysql));\n    }\n\n    @Test\n    public void test_delete() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"delete from t\", \"id = 0\", DbType.mysql));\n    }\n\n    @Test\n    public void test_delete_1() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"delete from t where id = 0\", \"name = 'aaa'\", DbType.mysql));\n    }\n\n    @Test\n    public void test_update() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"update t set f1 = ?\", \"id = 0\", DbType.mysql));\n    }\n\n    @Test\n    public void test_update_1() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'bb'\", SQLUtils.addCondition(\"update t set f1 = ? where id = 0\", \"name = 'bb'\", DbType.mysql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsAddConditionTest_oracle.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsAddConditionTest_oracle {\n    @Test\n    public void test_select() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"select * from t\", \"id = 0\", DbType.oracle));\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"select * from t where id = 0\", \"name = 'aaa'\", DbType.oracle));\n    }\n\n    @Test\n    public void test_delete() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"delete from t\", \"id = 0\", DbType.oracle));\n    }\n\n    @Test\n    public void test_delete_1() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"delete from t where id = 0\", \"name = 'aaa'\", DbType.oracle));\n    }\n\n    @Test\n    public void test_update() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"update t set f1 = ?\", \"id = 0\", DbType.oracle));\n    }\n\n    @Test\n    public void test_update_1() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'bb'\", SQLUtils.addCondition(\"update t set f1 = ? where id = 0\", \"name = 'bb'\", DbType.oracle));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsAddConditionTest_pg.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsAddConditionTest_pg {\n    @Test\n    public void test_select() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"select * from t\", \"id = 0\", DbType.postgresql));\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"select * from t where id = 0\", \"name = 'aaa'\", DbType.postgresql));\n    }\n\n    @Test\n    public void test_delete() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"delete from t\", \"id = 0\", DbType.postgresql));\n    }\n\n    @Test\n    public void test_delete_1() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"delete from t where id = 0\", \"name = 'aaa'\", DbType.postgresql));\n    }\n\n    @Test\n    public void test_update() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"update t set f1 = ?\", \"id = 0\", DbType.postgresql));\n    }\n\n    @Test\n    public void test_update_1() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'bb'\", SQLUtils.addCondition(\"update t set f1 = ? where id = 0\", \"name = 'bb'\", DbType.postgresql));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsAddConditionTest_sqlserver.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsAddConditionTest_sqlserver {\n    @Test\n    public void test_select() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"select * from t\", \"id = 0\", DbType.sqlserver));\n    }\n\n    @Test\n    public void test_select_1() throws Exception {\n        assertEquals(\"SELECT *\"\n                + \"\\nFROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"select * from t where id = 0\", \"name = 'aaa'\", DbType.sqlserver));\n    }\n\n    @Test\n    public void test_delete() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"delete from t\", \"id = 0\", DbType.sqlserver));\n    }\n\n    @Test\n    public void test_delete_1() throws Exception {\n        assertEquals(\"DELETE FROM t\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'aaa'\", SQLUtils.addCondition(\"delete from t where id = 0\", \"name = 'aaa'\", DbType.sqlserver));\n    }\n\n    @Test\n    public void test_update() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\", SQLUtils.addCondition(\"update t set f1 = ?\", \"id = 0\", DbType.sqlserver));\n    }\n\n    @Test\n    public void test_update_1() throws Exception {\n        assertEquals(\"UPDATE t\"//\n                + \"\\nSET f1 = ?\"\n                + \"\\nWHERE id = 0\"\n                + \"\\n\\tAND name = 'bb'\", SQLUtils.addCondition(\"update t set f1 = ? where id = 0\", \"name = 'bb'\", DbType.sqlserver));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/SQLUtilsTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class SQLUtilsTest {\n    @Test\n    public void test_format() throws Exception {\n        String formattedSql = SQLUtils.format(\"select * from t where id = ?\", JdbcConstants.MYSQL,\n                Arrays.<Object>asList(\"abc\"));\n        assertEquals(\"SELECT *\" +\n                \"\\nFROM t\" +\n                \"\\nWHERE id = 'abc'\", formattedSql);\n    }\n\n    @Test\n    public void test_format_0() throws Exception {\n        String sql = \"select \\\"%\\\"'温'\\\"%\\\" FROM dual;\";\n        String formattedSql = SQLUtils.formatMySql(sql);\n        assertEquals(\"SELECT '%温%'\\n\" +\n                \"FROM dual;\", formattedSql);\n    }\n\n    @Test\n    public void test_format_1() throws Exception {\n        String sql = \"select * from t where tname LIKE \\\"%\\\"'温'\\\"%\\\"\";\n        String formattedSql = SQLUtils.formatMySql(sql);\n        assertEquals(\"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WHERE tname LIKE '%温%'\", formattedSql);\n    }\n\n    @Test\n    public void test_format_2() throws Exception {\n        String sql = \"begin\\n\"//\n                + \" if (a=10) then\\n\" + \" null;\\n\" + \" else\\n\" + \" null;\\n\" + \" end if;\\n\" + \"end;\";\n        assertEquals(\"BEGIN\"\n                + \"\\n\\tIF (a = 10) THEN\"\n                + \"\\n\\t\\tNULL;\"\n                + \"\\n\\tELSE\"\n                + \"\\n\\t\\tNULL;\"\n                + \"\\n\\tEND IF;\"\n                + \"\\nEND;\", SQLUtils.formatOracle(sql));\n    }\n\n    @Test\n    public void test_format_3() throws Exception {\n        String sql = \"select lottery_notice_issue,lottery_notice_date,lottery_notice_result from tb_lottery_notice where lottery_type_id=8 and lottery_notice_issue<=2014066 UNION ALL SELECT NULL, NULL, NULL, NULL, NULL, NULL# and lottery_notice_issue>=2014062 order by lottery_notice_issue desc\";\n        String formattedSql = SQLUtils.formatMySql(sql);\n        String expected = \"SELECT lottery_notice_issue, lottery_notice_date, lottery_notice_result\\n\" +\n                \"FROM tb_lottery_notice\\n\" +\n                \"WHERE lottery_type_id = 8\\n\" +\n                \"\\tAND lottery_notice_issue <= 2014066\\n\" +\n                \"UNION ALL\\n\" +\n                \"SELECT NULL, NULL, NULL, NULL, NULL\\n\" +\n                \"\\t, NULL # and lottery_notice_issue>=2014062 order by lottery_notice_issue desc\";\n        assertEquals(expected, formattedSql);\n    }\n\n    @Test\n    public void testAcceptFunctionTest() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptFunction(\n                \"select count(*) from t\",\n                DbType.odps,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n\n    @Test\n    public void testAcceptFunctionTest_1() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptAggregateFunction(\n                \"select count(*) from t\",\n                DbType.odps,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n\n    @Test\n    public void testAcceptFunctionTest_pg() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptFunction(\n                \"select count(*) from t\",\n                DbType.postgresql,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n\n    @Test\n    public void testAcceptFunctionTest_pg_1() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptAggregateFunction(\n                \"select count(*) from t\",\n                DbType.postgresql,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n\n    @Test\n    public void testAcceptFunctionTest_oracle() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptFunction(\n                \"select count(*) from t\",\n                DbType.oracle,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n\n    @Test\n    public void testAcceptFunctionTest_oracle_1() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptAggregateFunction(\n                \"select count(*) from t\",\n                DbType.oracle,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n\n    @Test\n    public void testAcceptFunctionTest_ck() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptFunction(\n                \"select count(*) from t\",\n                DbType.clickhouse,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n\n    @Test\n    public void testAcceptFunctionTest_ck_1() {\n        List<SQLMethodInvokeExpr> functions = new ArrayList<>();\n        SQLUtils.acceptAggregateFunction(\n                \"select count(*) from t\",\n                DbType.clickhouse,\n                e -> functions.add(e),\n                e -> true\n        );\n        assertEquals(1, functions.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/START_TRANSACTION_Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class START_TRANSACTION_Test {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"START TRANSACTION;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"START TRANSACTION;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"START TRANSACTION WITH CONSISTENT SNAPSHOT;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"START TRANSACTION WITH CONSISTENT SNAPSHOT;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"START TRANSACTION BEGIN;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"START TRANSACTION BEGIN;\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"START TRANSACTION BEGIN WORK;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"START TRANSACTION BEGIN WORK;\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"COMMIT;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"COMMIT;\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"COMMIT WORK;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"COMMIT WORK;\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"ROLLBACK;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"ROLLBACK;\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SET autocommit=0;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SET autocommit = 0;\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/StringComparisonFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StringComparisonFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT '?' LIKE 'ae' COLLATE latin1_german2_ci;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '?' LIKE 'ae' COLLATE latin1_german2_ci;\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT '?' = 'ae' COLLATE latin1_german2_ci;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT '?' = 'ae' COLLATE latin1_german2_ci;\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT 'a' = 'a ', 'a' LIKE 'a ';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'a' = 'a ', 'a' LIKE 'a ';\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT 'David!' LIKE 'David_';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'David!' LIKE 'David_';\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT 'David!' LIKE '%D%v%';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'David!' LIKE '%D%v%';\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT 'David!' LIKE 'David\\\\_';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'David!' LIKE 'David\\\\_';\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT 'David_' LIKE 'David|_' ESCAPE '|'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'David_' LIKE 'David|_' ESCAPE '|'\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT 'abc' LIKE BINARY 'ABC'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'abc' LIKE BINARY 'ABC'\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT 10 LIKE '1%'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 10 LIKE '1%'\", text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT filename, filename LIKE '%\\\\\\\\' FROM t1\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT filename, filename LIKE '%\\\\\\\\'\\nFROM t1\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT STRCMP('text', 'text2')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT STRCMP('text', 'text2')\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SET @s1 = _latin1 'x' COLLATE latin1_general_ci;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SET @s1 = _latin1 'x' COLLATE latin1_general_ci;\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SET @s2 = _latin1 'X' COLLATE latin1_general_ci;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SET @s2 = _latin1 'X' COLLATE latin1_general_ci;\", text);\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT STRCMP(@s1, @s2), STRCMP(@s3, @s4);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT STRCMP(@s1, @s2)\\n\" +\n                \"\\t, STRCMP(@s3, @s4);\", text);\n    }\n\n    @Test\n    public void test_14() throws Exception {\n        String sql = \"SELECT STRCMP(@s1, @s3 COLLATE latin1_general_ci);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT STRCMP(@s1, @s3 COLLATE latin1_general_ci);\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/StringFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StringFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SELECT ASCII('2');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ASCII('2');\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT ASCII(2);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ASCII(2);\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT BIN(12);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT BIN(12);\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT BIT_LENGTH('text');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT BIT_LENGTH('text');\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT CHAR(77,121,83,81,'76');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CHAR(77, 121, 83, 81, '76');\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT HEX(CHAR(1,0)), HEX(CHAR(256));\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT HEX(CHAR(1, 0))\\n\" +\n                \"\\t, HEX(CHAR(256));\", text);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256));\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT HEX(CHAR(1, 0, 0))\\n\" +\n                \"\\t, HEX(CHAR(256 * 256));\", text);\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8))\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CHARSET(CHAR(0x65))\\n\" +\n                \"\\t, CHARSET(CHAR(0x65 USING utf8))\", text);\n    }\n\n    @Test\n    public void test_8() throws Exception {\n        String sql = \"SELECT CONCAT(CAST(int_col AS CHAR), char_col)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CONCAT(CAST(int_col AS CHAR), char_col)\", text);\n    }\n\n    @Test\n    public void test_9() throws Exception {\n        String sql = \"SELECT 'My' 'S' 'QL'\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 'MySQL'\", text);\n    }\n\n    @Test\n    public void test_10() throws Exception {\n        String sql = \"SELECT CONCAT_WS(',','First name','Second name','Last Name');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CONCAT_WS(',', 'First name', 'Second name', 'Last Name');\", text);\n    }\n\n    @Test\n    public void test_11() throws Exception {\n        String sql = \"SELECT CONCAT_WS(',','First name',NULL,'Last Name');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT CONCAT_WS(',', 'First name', NULL, 'Last Name');\", text);\n    }\n\n    @Test\n    public void test_12() throws Exception {\n        String sql = \"SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');\", text);\n    }\n\n    @Test\n    public void test_13() throws Exception {\n        String sql = \"SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');\", text);\n    }\n\n    @Test\n    public void test_14() throws Exception {\n        String sql = \"SELECT EXPORT_SET(5,'Y','N',',',4);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT EXPORT_SET(5, 'Y', 'N', ',', 4);\", text);\n    }\n\n    @Test\n    public void test_15() throws Exception {\n        String sql = \"SELECT EXPORT_SET(6,'1','0',',',10);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT EXPORT_SET(6, '1', '0', ',', 10);\", text);\n    }\n\n    @Test\n    public void test_16() throws Exception {\n        String sql = \"SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');\", text);\n    }\n\n    @Test\n    public void test_17() throws Exception {\n        String sql = \"SELECT FIND_IN_SET('b','a,b,c,d');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT FIND_IN_SET('b', 'a,b,c,d');\", text);\n    }\n\n    @Test\n    public void test_18() throws Exception {\n        String sql = \"SELECT FORMAT(12332.123456, 4);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT FORMAT(12332.123456, 4);\", text);\n    }\n\n    @Test\n    public void test_19() throws Exception {\n        String sql = \"SELECT 0x616263, HEX('abc'), UNHEX(HEX('abc'));\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0x616263, HEX('abc')\\n\" +\n                \"\\t, UNHEX(HEX('abc'));\", text);\n    }\n\n    @Test\n    public void test_20() throws Exception {\n        String sql = \"SELECT HEX(255), CONV(HEX(255),16,10);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT HEX(255)\\n\" +\n                \"\\t, CONV(HEX(255), 16, 10);\", text);\n    }\n\n    @Test\n    public void test_21() throws Exception {\n        String sql = \"SELECT INSERT('Quadratic', 3, 4, 'What');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INSERT('Quadratic', 3, 4, 'What');\", text);\n    }\n\n    @Test\n    public void test_22() throws Exception {\n        String sql = \"SELECT INSERT('Quadratic', -1, 4, 'What');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INSERT('Quadratic', -1, 4, 'What');\", text);\n    }\n\n    @Test\n    public void test_23() throws Exception {\n        String sql = \"SELECT INSTR('foobarbar', 'bar');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT INSTR('foobarbar', 'bar');\", text);\n    }\n\n    @Test\n    public void test_24() throws Exception {\n        String sql = \"SELECT LEFT('foobarbar', 5);\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LEFT('foobarbar', 5);\", text);\n    }\n\n    @Test\n    public void test_25() throws Exception {\n        String sql = \"SELECT LENGTH('text');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LENGTH('text');\", text);\n    }\n\n    @Test\n    public void test_26() throws Exception {\n        String sql = \"UPDATE t SET blob_col=LOAD_FILE('/tmp/picture') WHERE id=1;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"UPDATE t\\nSET blob_col = LOAD_FILE('/tmp/picture')\\nWHERE id = 1;\", text);\n    }\n\n    @Test\n    public void test_27() throws Exception {\n        String sql = \"SELECT LOCATE('bar', 'foobarbar');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LOCATE('bar', 'foobarbar');\", text);\n    }\n\n    @Test\n    public void test_28() throws Exception {\n        String sql = \"SELECT LOWER('QUADRATICALLY');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LOWER('QUADRATICALLY');\", text);\n    }\n\n    @Test\n    public void test_29() throws Exception {\n        String sql = \"SELECT LPAD('hi',4,'??');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LPAD('hi', 4, '??');\", text);\n    }\n\n    @Test\n    public void test_30() throws Exception {\n        String sql = \"SELECT LTRIM('  barbar')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT LTRIM('  barbar')\", text);\n    }\n\n    @Test\n    public void test_31() throws Exception {\n        String sql = \"SELECT MAKE_SET(1,'a','b','c')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT MAKE_SET(1, 'a', 'b', 'c')\", text);\n    }\n\n    @Test\n    public void test_32() throws Exception {\n        String sql = \"SELECT MAKE_SET(1 | 4,'hello','nice','world')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT MAKE_SET(1 | 4, 'hello', 'nice', 'world')\", text);\n    }\n\n    @Test\n    public void test_33() throws Exception {\n        String sql = \"SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT MAKE_SET(1 | 4, 'hello', 'nice', NULL, 'world')\", text);\n    }\n\n    @Test\n    public void test_34() throws Exception {\n        String sql = \"SELECT ORD('2')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ORD('2')\", text);\n    }\n\n    @Test\n    public void test_35() throws Exception {\n        String sql = \"SELECT QUOTE('Don\\\\'t!')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT QUOTE('Don''t!')\", text);\n    }\n\n    @Test\n    public void test_36() throws Exception {\n        String sql = \"SELECT REPEAT('MySQL', 3)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT REPEAT('MySQL', 3)\", text);\n    }\n\n    @Test\n    public void test_37() throws Exception {\n        String sql = \"SELECT REVERSE('abc')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT REVERSE('abc')\", text);\n    }\n\n    @Test\n    public void test_38() throws Exception {\n        String sql = \"SELECT RIGHT('foobarbar', 4)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT RIGHT('foobarbar', 4)\", text);\n    }\n\n    @Test\n    public void test_39() throws Exception {\n        String sql = \"SELECT RPAD('hi',5,'?')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT RPAD('hi', 5, '?')\", text);\n    }\n\n    @Test\n    public void test_40() throws Exception {\n        String sql = \"SELECT RTRIM('barbar   ')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT RTRIM('barbar   ')\", text);\n    }\n\n    @Test\n    public void test_41() throws Exception {\n        String sql = \"SELECT SOUNDEX('Hello')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SOUNDEX('Hello')\", text);\n    }\n\n    @Test\n    public void test_42() throws Exception {\n        String sql = \"SELECT SPACE(6)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SPACE(6)\", text);\n    }\n\n    @Test\n    public void test_43() throws Exception {\n        String sql = \"SELECT SUBSTRING('Quadratically',5)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SUBSTRING('Quadratically', 5)\", text);\n    }\n\n    @Test\n    public void test_44() throws Exception {\n        String sql = \"SELECT SUBSTRING('Sakila' FROM -4 FOR 2)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SUBSTRING('Sakila' FROM -4 FOR 2)\", text);\n    }\n\n    @Test\n    public void test_45() throws Exception {\n        String sql = \"SELECT SUBSTRING('foobarbar' FROM 4)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SUBSTRING('foobarbar' FROM 4)\", text);\n    }\n\n    @Test\n    public void test_46() throws Exception {\n        String sql = \"SELECT SUBSTRING('Quadratically',5,6)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SUBSTRING('Quadratically', 5, 6)\", text);\n    }\n\n    @Test\n    public void test_47() throws Exception {\n        String sql = \"SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2)\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2)\", text);\n    }\n\n    @Test\n    public void test_48() throws Exception {\n        String sql = \"SELECT TRIM('  bar   ')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TRIM('  bar   ')\", text);\n    }\n\n    @Test\n    public void test_49() throws Exception {\n        String sql = \"SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx')\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx')\", text);\n    }\n\n    @Test\n    public void test_50() throws Exception {\n        String sql = \"SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');\", text);\n    }\n\n    @Test\n    public void test_51() throws Exception {\n        String sql = \"SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');\", text);\n    }\n\n    @Test\n    public void test_52() throws Exception {\n        String sql = \"SELECT UNHEX('4D7953514C');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT UNHEX('4D7953514C');\", text);\n    }\n\n    @Test\n    public void test_53() throws Exception {\n        String sql = \"SELECT 0x4D7953514C;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT 0x4D7953514C;\", text);\n    }\n\n    @Test\n    public void test_54() throws Exception {\n        String sql = \"SELECT UPPER('Hej');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT UPPER('Hej');\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/StringTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class StringTest {\n    @Test\n    public void test_latin() throws Exception {\n        String sql = \"SELECT _latin1'string' COLLATE latin1_danish_ci;\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SELECT _latin1 'string' COLLATE latin1_danish_ci;\", text);\n    }\n\n    @Test\n    public void test_utf8() throws Exception {\n        String sql = \"SELECT _utf8'some text';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n\n        assertEquals(\"SELECT _utf8 'some text';\", text);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/TiDBBeginTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLBeginStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLBlockStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author lizongbo\n */\npublic class TiDBBeginTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"BEGIN ;\";\n        testSql(sql);\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"BEGIN\";\n        testSql(sql);\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"BEGIN PESSIMISTIC;\";\n        testSql(sql);\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"BEGIN PESSIMISTIC\";\n        testSql(sql);\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"BEGIN OPTIMISTIC;\";\n        testSql(sql);\n    }\n\n    public void test_5() throws Exception {\n        String sql = \"BEGIN OPTIMISTIC\";\n        testSql(sql);\n    }\n\n    public void test_6() throws Exception {\n        String sql = \"BEGIN /*T! PESSIMISTIC */\";\n        testSql(sql);\n    }\n\n    public void test_7() throws Exception {\n        String sql = \"BEGIN /*T! PESSIMISTIC */;\";\n        testSql(sql);\n    }\n\n    public void test_8() throws Exception {\n        String sql = \"BEGIN /*T! OPTIMISTIC */\";\n        testSql(sql);\n    }\n\n    public void test_9() throws Exception {\n        String sql = \"BEGIN /*T! OPTIMISTIC */;\";\n        testSql(sql);\n    }\n\n    public void test_10() throws Exception {\n        String sql = \"BEGIN\\n\"\n            + \"    INSERT INTO `table_test` (`111`);\\n\"\n            + \"    INSERT INTO `table_test` (`222`);\\n\"\n            + \"    SELECT * FROM table_test where id = 1;\\n\"\n            + \"    END\";\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.TIDB);\n        SQLStatement statement = statementList.get(0);\n        //System.out.println(statement.getClass());\n        print(statementList);\n        assertEquals(1, statementList.size());\n        assertTrue(statement instanceof SQLBlockStatement);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n        assertEquals(1, visitor.getTables().size());\n    }\n\n    void testSql(String sql) throws Exception {\n        // MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.KeepComments);\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.TIDB);\n        SQLStatement statement = statementList.get(0);\n        //System.out.println(statement.getClass());\n        print(statementList);\n        assertEquals(1, statementList.size());\n        assertTrue(statement instanceof SQLBeginStatement);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n\n        assertEquals(0, visitor.getTables().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/XMLFunctionsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class XMLFunctionsTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"SET @xml = '<a><b>X</b><b>Y</b></a>';\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SET @xml = '<a><b>X</b><b>Y</b></a>';\", text);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"SELECT @i, ExtractValue(@xml, '//b[$@i]');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT @i, ExtractValue(@xml, '//b[$@i]');\", text);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"SELECT @j, ExtractValue(@xml, '//b[$@j]');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT @j, ExtractValue(@xml, '//b[$@j]');\", text);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"SELECT @k, ExtractValue(@xml, '//b[$@k]');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT @k, ExtractValue(@xml, '//b[$@k]');\", text);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"SELECT ExtractValue('<a><b/></a>', '/a/b');\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT ExtractValue('<a><b/></a>', '/a/b');\", text);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"SELECT UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1\";\n\n        SQLStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        String text = output(stmtList);\n\n        assertEquals(\"SELECT UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1\", text);\n    }\n\n    private String output(List<SQLStatement> stmtList) {\n        return SQLUtils.toSQLString(stmtList, JdbcConstants.MYSQL);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterMaterializedViewTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alter;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterMaterializedViewTest_0 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"ENABLE QUERY REWRITE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"ENABLE QUERY REWRITE\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_0() throws Exception {\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(\n                \"ALTER MATERIALIZED VIEW myview \\n\" +\n                        \"DISABLE QUERY REWRITE\");\n\n        assertEquals(\"ALTER MATERIALIZED VIEW myview\\n\" +\n                \"DISABLE QUERY REWRITE\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_1() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW myview \\n\" +\n                \"REFRESH FAST ON DEMAND \\n\" +\n                \"DISABLE QUERY REWRITE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW myview\\n\" +\n                \"REFRESH FAST ON DEMAND\\n\" +\n                \"DISABLE QUERY REWRITE\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_2() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_3() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND \" +\n                \"START WITH '2020-08-20 14:50:00'\\n\" +\n                \"NEXT current_date() + INTERVAL 15 DAY\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"START WITH '2020-08-20 14:50:00' NEXT current_date() + INTERVAL 15 DAY\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_4() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND \" +\n                \"START WITH now()\\n\" +\n                \"NEXT DATE_ADD(now(), INTERVAL 1 MINUTE)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"START WITH now() NEXT DATE_ADD(now(), INTERVAL 1 MINUTE)\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_5() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON COMMIT\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON COMMIT\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_6() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH FAST ON COMMIT\\n\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH FAST ON COMMIT\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_7() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON OVERWRITE\\n\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER MATERIALIZED VIEW view_name\\n\" +\n                \"REFRESH COMPLETE ON OVERWRITE\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_all() {\n        ok(\"ALTER MATERIALIZED VIEW mymv \\n\" +\n                        \"REFRESH NEXT current_date() + INTERVAL 15 DAY\\n\" +\n                        \"DISABLE QUERY REWRITE;\",\n                \"ALTER MATERIALIZED VIEW mymv\\n\" +\n                        \"REFRESH NEXT current_date() + INTERVAL 15 DAY\\n\" +\n                        \"DISABLE QUERY REWRITE;\");\n\n        ok(\"ALTER MATERIALIZED VIEW mymv \\n\" +\n                        \"REFRESH FAST ON DEMAND\\n\" +\n                        \"DISABLE QUERY REWRITE;\",\n                \"ALTER MATERIALIZED VIEW mymv\\n\" +\n                        \"REFRESH FAST ON DEMAND\\n\" +\n                        \"DISABLE QUERY REWRITE;\");\n\n        ok(\"ALTER MATERIALIZED VIEW mymv \\n\" +\n                        \"REFRESH COMPLETE\\n\" +\n                        \"ENABLE QUERY REWRITE;\",\n                \"ALTER MATERIALIZED VIEW mymv\\n\" +\n                        \"REFRESH COMPLETE\\n\" +\n                        \"ENABLE QUERY REWRITE;\");\n\n        ok(\"ALTER MATERIALIZED VIEW mymv \\n\" +\n                        \"REFRESH COMPLETE ON COMMIT\\n\" +\n                        \"ENABLE QUERY REWRITE;\",\n                \"ALTER MATERIALIZED VIEW mymv\\n\" +\n                        \"REFRESH COMPLETE ON COMMIT\\n\" +\n                        \"ENABLE QUERY REWRITE;\");\n\n        ok(\"ALTER MATERIALIZED VIEW mymv \\n\" +\n                        \"REFRESH FAST ON OVERWRITE\\n\" +\n                        \"DISABLE QUERY REWRITE;\",\n                \"ALTER MATERIALIZED VIEW mymv\\n\" +\n                        \"REFRESH FAST ON OVERWRITE\\n\" +\n                        \"DISABLE QUERY REWRITE;\");\n    }\n\n    @Test\n    public void test_bad_case() {\n        String sql = \"ALTER MATERIALIZED VIEW mymv\";\n\n        failed(sql);\n        String sql2 = \"ALTER MATERIALIZED VIEW mymv refresh\";\n\n        failed(sql2);\n\n        String sql3 = \"ALTER MATERIALIZED VIEW mymv refresh start with\";\n        failed(sql3);\n\n        String sql4 = \"ALTER MATERIALIZED VIEW mymv refresh start with now () next\";\n        failed(sql4);\n\n        String sql5 = \"ALTER MATERIALIZED VIEW mymv \" +\n                \" REFRESH COMPLETE\" +\n                \" ENABLE\";\n        failed(sql5);\n\n        String sql6 = \"ALTER MATERIALIZED VIEW mymv \" +\n                \" REFRESH COMPLETE\" +\n                \" DISABLE\";\n        failed(sql6);\n\n        String sql7 = \"ALTER MATERIALIZED VIEW mymv \" +\n                \" REFRESH COMPLETE \" +\n                \"ENABLE QUERY\";\n        failed(sql7);\n    }\n\n    public void failed(String sql) {\n        try {\n            SQLUtils.parseSingleMysqlStatement(sql);\n            fail();\n        } catch (Exception e) {\n            System.out.println(e.getMessage());\n        }\n    }\n\n    public void ok(String sql, String expectedSql) {\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n        System.out.println(stmt.toString());\n        assertEquals(expectedSql, stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterSystemTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alter;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterSystemTest_0 {\n    @Test\n    public void test_alter1() {\n        String sql = \"ALTER SYSTEM SET CONFIG useAuth=true\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER SYSTEM SET CONFIG useAuth = true\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter2() {\n        String sql = \"ALTER SYSTEM SET CONFIG useAuth=true baseURL='http://test.xxx.com/ak'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER SYSTEM SET CONFIG useAuth = true baseURL = 'http://test.xxx.com/ak'\", SQLUtils.toMySqlString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableGroupTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alter;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableGroupTest_0 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter tablegroup new_ddl.ddl_test_1 k1=v1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLEGROUP new_ddl.ddl_test_1 k1 = v1\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_2() throws Exception {\n        String sql = \"alter tablegroup new_ddl.ddl_test_1 k1=123\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLEGROUP new_ddl.ddl_test_1 k1 = 123\", SQLUtils.toMySqlString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTable_refactor_test.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alter;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlAlterTable_refactor_test\n * @description 只测试parser语法解析能力，SQL语句不具备合理性\n * @Author zzy\n * @Date 2019-07-02 15:27\n */\npublic class MySqlAlterTable_refactor_test extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"alter table test001\\n\" +\n                \"add column x int first,\" +\n                \"add column (x int, x int),\" +\n                \"add index (a,b),\" +\n                \"add fulltext index (a,b),\" +\n                \"add constraint syb primary key (a),\" +\n                \"add check (1+2),\" +\n                \"algorithm = default,\" +\n                \"alter column c set default 1,\" +\n                \"change column a b int first,\" +\n                \"convert to character set utf8 collate utf8_generic_ci,\" +\n                \"disable keys,\" +\n                \"import tablespace,\" +\n                \"drop cc,\" +\n                \"drop key cc,\" +\n                \"drop primary key,\" +\n                \"drop foreign key fk,\" +\n                \"force,\" +\n                \"lock none,\" +\n                \"modify a int first,\" +\n                \"rename key a to b,\" +\n                \"rename to tb2,\" +\n                \"without validation,\" +\n                \"auto_increment 1\\n\" +\n                \"avg_row_length 1\\n\" +\n                \"default character set utf8\\n\" +\n                \"checksum 0\\n\" +\n                \"default collate utf8_unicode_ci\\n\" +\n                \"comment 'hehe'\\n\" +\n                \"compression 'LZ4'\\n\" +\n                \"connection 'conn'\\n\" +\n                \"index directory 'path'\\n\" +\n                \"delay_key_write 1\\n\" +\n                \"encryption 'N'\\n\" +\n                \"engine innodb\\n\" +\n                \"insert_method no\\n\" +\n                \"key_block_size 32\\n\" +\n                \"max_rows 999\\n\" +\n                \"min_rows 1\\n\" +\n                \"pack_keys default\\n\" +\n                \"password 'psw'\\n\" +\n                \"row_format dynamic\\n\" +\n                \"stats_auto_recalc default\\n\" +\n                \"stats_persistent default\\n\" +\n                \"stats_sample_pages 10\\n\" +\n                \"tablespace `tbs_name` storage memory\\n\" +\n                \"union (tb1,tb2,tb3)\\n\" +\n                \"auto_increment 1,\\n\" +\n                \"order by a,b,c\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tAUTO_INCREMENT = 1 AVG_ROW_LENGTH = 1 CHARACTER SET = utf8 CHECKSUM = 0 COLLATE = utf8_unicode_ci COMMENT = 'hehe' COMPRESSION = 'LZ4' CONNECTION = 'conn' COLLATE = 'path' DELAY_KEY_WRITE = 1 ENCRYPTION = 'N' ENGINE = innodb INSERT_METHOD = no KEY_BLOCK_SIZE = 32 MAX_ROWS = 999 MIN_ROWS = 1 PACK_KEYS = DEFAULT PASSWORD = 'psw' ROW_FORMAT = dynamic STATS_AUTO_RECALC = DEFAULT STATS_PERSISTENT = DEFAULT STATS_SAMPLE_PAGES = 10 TABLESPACE `tbs_name` STORAGE memory UNION = (tb1, tb2, tb3) AUTO_INCREMENT = 1,\" +\n            \"\\n\\tADD COLUMN x int FIRST,\\n\" +\n                        \"\\tADD COLUMN (x int, x int),\\n\" +\n                        \"\\tADD INDEX (a, b),\\n\" +\n                        \"\\tADD FULLTEXT INDEX (a, b),\\n\" +\n                        \"\\tADD PRIMARY KEY (a),\\n\" +\n                        \"\\tADD CHECK (1 + 2),\\n\" +\n                        \"\\tALGORITHM = default,\\n\" +\n                        \"\\tALTER COLUMN c SET DEFAULT 1,\\n\" +\n                        \"\\tCHANGE COLUMN a b int FIRST,\\n\" +\n                        \"\\tCONVERT TO CHARACTER SET utf8 COLLATE utf8_generic_ci,\\n\" +\n                        \"\\tDISABLE KEYS,\\n\" +\n                        \"\\tIMPORT TABLESPACE,\\n\" +\n                        \"\\tDROP COLUMN cc,\\n\" +\n                        \"\\tDROP KEY cc,\\n\" +\n                        \"\\tDROP PRIMARY KEY,\\n\" +\n                        \"\\tDROP FOREIGN KEY fk,\\n\" +\n                        \"\\tFORCE,\\n\" +\n                        \"\\tLOCK = none,\\n\" +\n                        \"\\tMODIFY COLUMN a int FIRST,\\n\" +\n                        \"\\tRENAME INDEX a TO b,\\n\" +\n                        \"\\tRENAME TO tb2,\\n\" +\n                        \"\\tWITHOUT VALIDATION,\\n\" +\n                        \"\\tORDER BY a, b, c\",\n                SQLUtils.toMySqlString(statementList.get(0)));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"alter table test001\\n\" +\n                \"add index i0 using hash (a,b) key_block_size 32 using btree comment 'index comment',\" +\n                \"add fulltext key ftk0 (a,b) key_block_size=16 with parser ngram comment 'fulltext comment',\" +\n                \"add spatial sp0 (a,b) key_block_size=16 comment 'spatial comment',\" +\n                \"add constraint syb0 primary key using hash (a,b,c) using btree comment 'pk comment',\" +\n                \"add constraint unique uk0 using hash (a,b) using btree comment 'uk comment',\" +\n                \"add index i1 (a,b) covering (c,d) dbpartition by hash(a) tbpartition by MM(actionDate) tbpartitions 12;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                        \"\\tADD INDEX i0 USING btree (a, b) KEY_BLOCK_SIZE = 32 COMMENT 'index comment',\\n\" +\n                        \"\\tADD FULLTEXT KEY ftk0 (a, b) KEY_BLOCK_SIZE = 16 WITH PARSER ngram COMMENT 'fulltext comment',\\n\" +\n                        \"\\tADD SPATIAL sp0 (a, b) KEY_BLOCK_SIZE = 16 COMMENT 'spatial comment',\\n\" +\n                        \"\\tADD PRIMARY KEY USING btree (a, b, c) COMMENT 'pk comment',\\n\" +\n                        \"\\tADD UNIQUE uk0 USING btree (a, b) COMMENT 'uk comment',\\n\" +\n                        \"\\tADD INDEX i1 (a, b) COVERING (c, d) DBPARTITION BY hash(a) TBPARTITION BY MM(actionDate) TBPARTITIONS 12;\",\n                SQLUtils.toMySqlString(statementList.get(0)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterUserTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alter;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterUserTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER USER 'jeffrey'@'localhost' PASSWORD EXPIRE;\", //\n                output);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"alter user IF EXISTS user1 IDENTIFIED BY 'auth_string'\";\n\n        SQLStatement statement = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"ALTER USER IF EXISTS user1 IDENTIFIED BY 'auth_string'\", statement.toString());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"alter user IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE\";\n\n        SQLStatement statement = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"ALTER USER IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE\", statement.toString());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"alter user IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE DEFAULT\";\n\n        SQLStatement statement = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"ALTER USER IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE DEFAULT\", statement.toString());\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"alter user IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE NEVER\";\n\n        SQLStatement statement = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"ALTER USER IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE NEVER\", statement.toString());\n    }\n\n    public void test_5() throws Exception {\n        String sql = \"alter user IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE INTERVAL 5 DAY\";\n\n        SQLStatement statement = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"ALTER USER IF EXISTS user1 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE INTERVAL 5 DAY\", statement.toString());\n    }\n\n    public void test_6() throws Exception {\n        String sql = \"alter user IF EXISTS user1 IDENTIFIED BY 'auth_string', user2 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE INTERVAL 5 DAY\";\n\n        SQLStatement statement = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"ALTER USER IF EXISTS user1 IDENTIFIED BY 'auth_string', user2 IDENTIFIED BY 'auth_string' PASSWORD EXPIRE INTERVAL 5 DAY\", statement.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterViewTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alter;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterViewTest_0 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter definer = 'ivan'@'%' view my_view3 as select count(*) from t3;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER DEFINER = 'ivan'@'%'\\n\" +\n                \"\\tVIEW my_view3\\n\" +\n                \"AS\\n\" +\n                \"SELECT count(*)\\n\" +\n                \"FROM t3;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"alter definer = 'ivan'@'%'\\n\" +\n                \"\\tview my_view3\\n\" +\n                \"as\\n\" +\n                \"select count(*)\\n\" +\n                \"from t3;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_0 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1`  ADD INDEX `ix` (`f2` ASC) ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tADD INDEX `ix` (`f2` ASC);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `test`.`tb1`\" +\n                \"\\n\\tadd index `ix` (`f2` asc);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        TableStat tableStat = visitor.getTableStat(\"test.tb1\");\n        assertNotNull(tableStat);\n\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_fulltext() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` alter INDEX `ix` set fulltext analyzer='sfewfw' ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\"\n                + \"\\t ALTER INDEX `ix` FULLTEXT  ANALYZER = 'sfewfw';\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_fulltext2() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` alter INDEX `ix` set fulltext index analyzer='sfewfw' ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\"\n                + \"\\t ALTER INDEX `ix` FULLTEXT INDEX ANALYZER = 'sfewfw';\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_alter_fulltext3() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` alter INDEX `ix` set fulltext QUERY analyzer='sfewfw' ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\"\n                + \"\\t ALTER INDEX `ix` FULLTEXT QUERY ANALYZER = 'sfewfw';\", SQLUtils.toMySqlString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_1 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD UNIQUE INDEX `ix2` (`fid` ASC) ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tADD UNIQUE INDEX `ix2` (`fid` ASC);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `test`.`tb1`\" +\n                \"\\n\\tadd unique index `ix2` (`fid` asc);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test.tb1\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_10.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlAlterTableAddIndex_10\n * @description 测试index, fulltext, PK, UK的index option的支持情况，包括后者index type覆盖前者\n * @Author zzy\n * @Date 2019-05-06 15:45\n */\npublic class MySqlAlterTableAddIndex_10 {\n    @Test\n    public void test_alter_table_add_index_with_options() throws Exception {\n        String sql = \"ALTER TABLE test001 ADD INDEX `i` using btree (`b`) key_block_size=32 comment 'hehe';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tADD INDEX `i` USING btree (`b`) KEY_BLOCK_SIZE = 32 COMMENT 'hehe';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test001\\n\" +\n                \"\\tadd index `i` using btree (`b`) key_block_size = 32 comment 'hehe';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test001\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_table_add_index_multi_type() throws Exception {\n        String sql = \"ALTER TABLE test001 ADD INDEX `i2` using btree (`b`) key_block_size=32 comment 'hehe' using hash;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tADD INDEX `i2` USING hash (`b`) KEY_BLOCK_SIZE = 32 COMMENT 'hehe';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test001\\n\" +\n                \"\\tadd index `i2` using hash (`b`) key_block_size = 32 comment 'hehe';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test001\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_table_add_fulltext_index_option_ngram() throws Exception {\n        String sql = \"alter table test001 add fulltext index (b) with parser ngram key_block_size=32 comment 'hehe';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tADD FULLTEXT INDEX (b) KEY_BLOCK_SIZE = 32 WITH PARSER ngram COMMENT 'hehe';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test001\\n\" +\n                \"\\tadd fulltext index (b) key_block_size = 32 with parser ngram comment 'hehe';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test001\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_table_add_constraint_primary_key_with_options() throws Exception {\n        String sql = \"alter table test001 add constraint primary key using btree (b) key_block_size=32 comment 'hehe' using btree;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tADD PRIMARY KEY USING btree (b) KEY_BLOCK_SIZE = 32 COMMENT 'hehe';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test001\\n\" +\n                \"\\tadd primary key using btree (b) key_block_size = 32 comment 'hehe';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test001\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_table_add_constraint_unique_key_with_options() throws Exception {\n        String sql = \"alter table test001 add constraint unique key `uk` using btree (b) key_block_size=32 comment 'hehe' using btree;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tADD UNIQUE KEY `uk` USING btree (b) KEY_BLOCK_SIZE = 32 COMMENT 'hehe';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test001\\n\" +\n                \"\\tadd unique key `uk` using btree (b) key_block_size = 32 comment 'hehe';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test001\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_11.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlAlterTableAddIndex_10\n * @description 测试index, fulltext, PK, UK的index option的支持情况，包括后者index type覆盖前者\n * @Author zzy\n * @Date 2019-05-06 15:45\n */\npublic class MySqlAlterTableAddIndex_11 {\n    @Test\n    public void test_alter_table_add_index_with_options() throws Exception {\n        String sql = \"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2 ADD FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tADD FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict;\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tadd fulltext index title_fulltext_idx (title) with index analyzer index_analyzer2 with query analyzer query_analyzer2 with dict user_dict;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"aliyun_poc_db.tbl_custom_analyzer2\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_table_add_index_with_options2() throws Exception {\n        String sql = \"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2 ADD FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tADD FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tadd fulltext index title_fulltext_idx (title) with index analyzer index_analyzer2\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"aliyun_poc_db.tbl_custom_analyzer2\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_table_add_index_with_options3() throws Exception {\n        String sql = \"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2 ADD FULLTEXT INDEX title_fulltext_idx (title) WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tADD FULLTEXT INDEX title_fulltext_idx (title) WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict;\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tadd fulltext index title_fulltext_idx (title) with query analyzer query_analyzer2 with dict user_dict;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"aliyun_poc_db.tbl_custom_analyzer2\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_alter_table_add_index_with_options4() throws Exception {\n        String sql = \"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2 ADD FULLTEXT INDEX title_fulltext_idx (title) WITH DICT user_dict;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tADD FULLTEXT INDEX title_fulltext_idx (title) WITH DICT user_dict;\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table aliyun_poc_db.tbl_custom_analyzer2\\n\" +\n                \"\\tadd fulltext index title_fulltext_idx (title) with dict user_dict;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"aliyun_poc_db.tbl_custom_analyzer2\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_2 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE geom ADD SPATIAL INDEX(g);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE geom\\n\" +\n                \"\\tADD SPATIAL INDEX (g);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table geom\\n\" +\n                \"\\tadd spatial index (g);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"geom\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_3 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t_order ADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) dbpartition by hash(`buyer_id`);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) DBPARTITION BY hash(`buyer_id`);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd unique global index `g_i_buyer` (`buyer_id`) covering (order_snapshot) dbpartition by hash(`buyer_id`);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_4 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t_order ADD INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) dbpartition by hash(`buyer_id`);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) DBPARTITION BY hash(`buyer_id`);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd index `g_i_buyer` (`buyer_id`) covering (order_snapshot) dbpartition by hash(`buyer_id`);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_5 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t_order ADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) dbpartition by hash(`buyer_id`) tbpartition by hash(`buyer_id`);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) DBPARTITION BY hash(`buyer_id`) TBPARTITION BY hash(`buyer_id`);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd unique global index `g_i_buyer` (`buyer_id`) covering (order_snapshot) dbpartition by hash(`buyer_id`) tbpartition by hash(`buyer_id`);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_6.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_6 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql =\n                \"ALTER TABLE t_order ADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) dbpartition by hash(`buyer_id`) tbpartition by hash(`buyer_id`) COMMENT \\\"CREATE GSI TEST\\\";\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) DBPARTITION BY hash(`buyer_id`) TBPARTITION BY hash(`buyer_id`) COMMENT 'CREATE GSI TEST';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd unique global index `g_i_buyer` (`buyer_id`) covering (order_snapshot) dbpartition by hash(`buyer_id`) tbpartition by hash(`buyer_id`) comment 'CREATE GSI TEST';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_7.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_7 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql =\n                \"ALTER TABLE t_order ADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) dbpartition by hash(`buyer_id`) tbpartition by UNI_HASH(`buyer_id`) COMMENT \\\"CREATE GSI TEST\\\";\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD UNIQUE GLOBAL INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) DBPARTITION BY hash(`buyer_id`) TBPARTITION BY UNI_HASH(`buyer_id`) COMMENT 'CREATE GSI TEST';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd unique global index `g_i_buyer` (`buyer_id`) covering (order_snapshot) dbpartition by hash(`buyer_id`) tbpartition by UNI_HASH(`buyer_id`) comment 'CREATE GSI TEST';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_8.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_8 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql =\n                \"alter table `seller_table2` rename `seller_table3` , add key `idx_create`(`gmt_create`)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `seller_table2`\\n\" +\n                \"\\tRENAME TO `seller_table3`,\\n\" +\n                \"\\tADD KEY `idx_create` (`gmt_create`)\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `seller_table2`\\n\" +\n                \"\\trename to `seller_table3`,\\n\" +\n                \"\\tadd key `idx_create` (`gmt_create`)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"seller_table2\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddIndex_9.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddIndex_9 {\n    @Test\n    public void test_0() throws Exception {\n        String sql =\n                \"ALTER TABLE t_order ADD FULLTEXT INDEX `g_i_buyer` (`buyer_id`);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD FULLTEXT INDEX `g_i_buyer` (`buyer_id`);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd fulltext index `g_i_buyer` (`buyer_id`);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql =\n                \"ALTER TABLE t_order ADD CLUSTERED INDEX `g_i_buyer` (`buyer_id`);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD CLUSTERED INDEX `g_i_buyer` (`buyer_id`);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd clustered index `g_i_buyer` (`buyer_id`);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql =\n                \"ALTER TABLE t_order ADD CLUSTERED KEY `g_i_buyer` (`buyer_id`);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t_order\\n\" +\n                \"\\tADD CLUSTERED KEY `g_i_buyer` (`buyer_id`);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t_order\\n\" +\n                \"\\tadd clustered key `g_i_buyer` (`buyer_id`);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t_order\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql =\n                \"alter table xxx add key `idx_001`(`col1`,`current_date`,`col2`)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE xxx\\n\" +\n                \"\\tADD KEY `idx_001` (`col1`, `current_date`, `col2`)\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table xxx\\n\" +\n                \"\\tadd key `idx_001` (`col1`, `current_date`, `col2`)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"xxx\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql =\n                \"alter table xxx add key `idx_001`(`col1`,`current_time`,`col2`)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE xxx\\n\" +\n                \"\\tADD KEY `idx_001` (`col1`, `current_time`, `col2`)\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table xxx\\n\" +\n                \"\\tadd key `idx_001` (`col1`, `current_time`, `col2`)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"xxx\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql =\n                \"alter table xxx add key `idx_001`(`current_timestamp`,`curdate`,`LOCALTIME`, `LOCALTIMESTAMP`)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE xxx\\n\" +\n                \"\\tADD KEY `idx_001` (`current_timestamp`, `curdate`, `LOCALTIME`, `LOCALTIMESTAMP`)\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table xxx\\n\" +\n                \"\\tadd key `idx_001` (`current_timestamp`, `curdate`, `LOCALTIME`, `LOCALTIMESTAMP`)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"xxx\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddPrimaryKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddPrimaryKey {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` CHANGE COLUMN `fid` `fid` INT(11) NOT NULL DEFAULT NULL, ADD PRIMARY KEY (`fid`) ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tCHANGE COLUMN `fid` `fid` INT(11) NOT NULL DEFAULT NULL,\\n\\t\" +\n                \"ADD PRIMARY KEY (`fid`);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `test`.`tb1`\" +\n                \"\\n\\tchange column `fid` `fid` INT(11) not null default null,\\n\\t\" +\n                \"add primary key (`fid`);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test.tb1\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddPrimaryKey_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddPrimaryKey_1 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table tabelname add constraint  mYconstraint primary key(id)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE tabelname\" +\n                \"\\n\\tADD PRIMARY KEY (id)\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table tabelname\" +\n                \"\\n\\tadd primary key (id)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"tabelname\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAddUniqueTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAddUniqueTest {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE icp.wx_msg ADD CONSTRAINT idx_msgId_msgType_event_eventKey UNIQUE (msgId, msgType, event, eventKey)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE icp.wx_msg\"\n                + \"\\n\\tADD UNIQUE idx_msgId_msgType_event_eventKey (msgId, msgType, event, eventKey)\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table icp.wx_msg\"\n                + \"\\n\\tadd unique idx_msgId_msgType_event_eventKey (msgId, msgType, event, eventKey)\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"icp.wx_msg\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAlterColumnDropDefaultTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAlterColumnDropDefaultTest {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table tabelname alter column operateVersion drop default\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE tabelname\" +\n                \"\\n\\tALTER COLUMN operateVersion DROP DEFAULT\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table tabelname\" +\n                \"\\n\\talter column operateVersion drop default\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAlterColumnSetDefaultTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAlterColumnSetDefaultTest {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table tabelname alter column operateVersion set default 0\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE tabelname\" +\n                \"\\n\\tALTER COLUMN operateVersion SET DEFAULT 0\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table tabelname\" +\n                \"\\n\\talter column operateVersion set default 0\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableAlterColumnTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableAlterColumnTest {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `cube_template` ADD `stat_report_json` VARCHAR(256) CHARSET utf8 COLLATE utf8_general_ci DEFAULT ''  NOT NULL  COMMENT '模板的统计报表json数组';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `cube_template`\\n\" +\n                \"\\tADD COLUMN `stat_report_json` VARCHAR(256) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '模板的统计报表json数组';\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `cube_template`\\n\" +\n                \"\\tadd column `stat_report_json` VARCHAR(256) character set utf8 collate utf8_general_ci not null default '' comment '模板的统计报表json数组';\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDisableKeys.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDisableKeys {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table tableName DISABLE KEYS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE tableName\" +\n                \"\\n\\tDISABLE KEYS\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table tableName\" +\n                \"\\n\\tdisable keys\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDropIndex_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDropIndex_0 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` DROP INDEX `ix` ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tDROP INDEX `ix`;\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `test`.`tb1`\" +\n                \"\\n\\tdrop index `ix`;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"test.tb1\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getDropIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDropIndex_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDropIndex_1 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` DROP INDEX `ix`, DROP INDEX `ix2` ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tDROP INDEX `ix`,\" +\n                \"\\n\\tDROP INDEX `ix2`;\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `test`.`tb1`\" +\n                \"\\n\\tdrop index `ix`,\" +\n                \"\\n\\tdrop index `ix2`;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"ALTER TABLE customer DROP INDEX account_Index, DROP INDEX index_name , ADD INDEX guid (guid) USING BTREE;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE customer\\n\" +\n                \"\\tDROP INDEX account_Index,\\n\" +\n                \"\\tDROP INDEX index_name,\\n\" +\n                \"\\tADD INDEX guid USING BTREE (guid);\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table customer\\n\" +\n                \"\\tdrop index account_Index,\\n\" +\n                \"\\tdrop index index_name,\\n\" +\n                \"\\tadd index guid using BTREE (guid);\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor v = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(v);\n        v.getFunctions();\n    }\n\n    @Test\n    public void test_overflow() throws Exception {\n        Long l = Long.MIN_VALUE;\n        System.out.println(l);\n        float v = l.floatValue();\n        System.out.println(v);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDropKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDropKey {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table t6 drop key v\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t6\" +\n                \"\\n\\tDROP KEY v\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t6\" +\n                \"\\n\\tdrop key v\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t6\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getDropIndexCount());\n    }\n\n    @Test\n    public void test_alter_2() throws Exception {\n        String sql = \"alter table t6 drop clustered key v\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE t6\\n\" +\n                \"\\tDROP CLUSTERED KEY v\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table t6\\n\" +\n                \"\\tdrop clustered key v\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        SchemaStatVisitor visitor = new SQLUtils().createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        TableStat tableStat = visitor.getTableStat(\"t6\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(0, tableStat.getDropIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDropPrimaryKey.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDropPrimaryKey {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table tableName DROP PRIMARY KEY\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE tableName\" +\n                \"\\n\\tDROP PRIMARY KEY\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table tableName\" +\n                \"\\n\\tdrop primary key\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDrop_Test.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDrop_Test {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `rules` DROP `enabled`\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `rules`\"\n                + \"\\n\\tDROP COLUMN `enabled`\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table `rules`\"\n                + \"\\n\\tdrop column `enabled`\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDrop_Test_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDrop_Test_1 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE test.student DROP Column9, DROP Column10;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test.student\\n\" +\n                \"\\tDROP COLUMN Column9,\\n\" +\n                \"\\tDROP COLUMN Column10;\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test.student\\n\" +\n                \"\\tdrop column Column9,\\n\" +\n                \"\\tdrop column Column10;\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableDrop_Test_2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableDrop_Test_2 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE test_ddl \\n\" +\n                \"DROP COLUMN display_name, \\n\" +\n                \"MODIFY COLUMN id bigint(20) UNSIGNED NOT NULL ,\\n\" +\n                \"CHANGE COLUMN content content VARCHAR(3000) CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci' NOT NULL DEFAULT '未填写' COMMENT '默认' \\n\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test_ddl\\n\" +\n                \"\\tDROP COLUMN display_name,\\n\" +\n                \"\\tMODIFY COLUMN id bigint(20) UNSIGNED NOT NULL,\\n\" +\n                \"\\tCHANGE COLUMN content content VARCHAR(3000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '未填写' COMMENT '默认'\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test_ddl\\n\" +\n                \"\\tdrop column display_name,\\n\" +\n                \"\\tmodify column id bigint(20) unsigned not null,\\n\" +\n                \"\\tchange column content content VARCHAR(3000) character set utf8mb4 collate utf8mb4_unicode_ci not null default '未填写' comment '默认'\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableEnableKeys.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableEnableKeys {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table tableName ENABLE KEYS\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE tableName\" +\n                \"\\n\\tENABLE KEYS\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table tableName\" +\n                \"\\n\\tenable keys\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest {\n    @Test\n    public void test_alter_0() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` CHANGE COLUMN `fname` `fname1` VARCHAR(45) NULL DEFAULT NULL  ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tCHANGE COLUMN `fname` `fname1` VARCHAR(45) NULL DEFAULT NULL;\", output);\n    }\n\n    @Test\n    public void test_alter_1() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` CHARACTER SET = utf8 , COLLATE = utf8_general_ci ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tCHARACTER SET = utf8 COLLATE = utf8_general_ci;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"alter table `test`.`tb1`\\n\\tcharacter set = utf8 collate = utf8_general_ci;\",\n            SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_alter_2() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD INDEX `f` (`fname` ASC) ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tADD INDEX `f` (`fname` ASC);\", output);\n    }\n\n    @Test\n    public void test_alter_3() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ENGINE = InnoDB ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tENGINE = InnoDB;\", output);\n    }\n\n    @Test\n    public void test_alter_4() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` COLLATE = utf8_general_ci , PACK_KEYS = Pack All , ENGINE = InnoDB ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tCOLLATE = utf8_general_ci PACK_KEYS = PACK ALL ENGINE = InnoDB;\", output);\n    }\n\n    @Test\n    public void test_alter_5() throws Exception {\n        String sql = \"ALTER TABLE t1 COMMENT '表的注释';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t1\\n\\tCOMMENT = '表的注释';\", output);\n    }\n\n    @Test\n    public void test_alter_6() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` DEFAULT CHARACTER SET utf8 COLLATE = utf8_general_ci ;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        System.out.println(stmt.toString());\n        //System.out.println(SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tCHARACTER SET = utf8 COLLATE = utf8_general_ci;\", SQLUtils.toMySqlString(stmt));\n        assertEquals(\"alter table `test`.`tb1`\\n\\tcharacter set = utf8 collate = utf8_general_ci;\",\n            SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n\n    @Test\n    public void test_alter_7() throws Exception {\n        for (String sql : new String[]{\n            \"ALTER TABLE \\n\"\n                + \"    `test`  CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;\",\n            \"ALTER TABLE \\n\"\n                + \"    `test`  CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_bin';\",\n            \"ALTER TABLE \\n\"\n                + \"    `test`  CHARACTER SET \\\"utf8mb4\\\" COLLATE \\\"utf8mb4_bin\\\";\",\n            \"ALTER TABLE \\n\"\n                + \"    `test`  default CHARACTER SET utf8mb4 COLLATE =utf8mb4_bin\",\n        }) {\n            System.out.println(\"原始的sql===\" + sql);\n            SQLStatementParser parser1 = SQLParserUtils.createSQLStatementParser(sql, DbType.mysql);\n            List<SQLStatement> statementList1 = parser1.parseStatementList();\n            String sqleNew = statementList1.get(0).toString();\n            System.out.println(\"生成的sql===\" + sqleNew);\n            SQLStatementParser parser2 = SQLParserUtils.createSQLStatementParser(sqleNew, DbType.mariadb);\n            List<SQLStatement> statementList2 = parser2.parseStatementList();\n            String sqleNew2 = statementList2.get(0).toString();\n            System.out.println(\"再次解析生成的sql===\" + sqleNew2);\n            assertEquals(sqleNew, sqleNew2);\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest1 {\n    @Test\n    public void test_alter_0() throws Exception {\n        String sql = \"ALTER TABLE t1 RENAME t2;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"RENAME TABLE t1 TO t2;\", output);\n    }\n\n    @Test\n    public void test_alter_1() throws Exception {\n        String sql = \"ALTER TABLE t2 ADD d TIMESTAMP;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t2\\n\\tADD COLUMN d TIMESTAMP;\", output);\n    }\n\n    @Test\n    public void test_alter_2() throws Exception {\n        String sql = \"ALTER TABLE t2 ADD INDEX (d), ADD UNIQUE (a);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t2\\n\\tADD INDEX (d),\\n\\tADD UNIQUE (a);\", output);\n    }\n\n    @Test\n    public void test_alter_3() throws Exception {\n        String sql = \"ALTER TABLE t1 RENAME TO t2;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"RENAME TABLE t1 TO t2;\", output);\n    }\n\n    @Test\n    public void test_alter_4() throws Exception {\n        String sql = \"ALTER TABLE t1 RENAME AS t2;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"RENAME TABLE t1 TO t2;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest10.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest10 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t1 CHANGE a b INTEGER;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t1\" +\n                \"\\n\\tCHANGE COLUMN a b INTEGER;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest11.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest11 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t1 MODIFY b BIGINT NOT NULL;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t1\" +\n                \"\\n\\tMODIFY COLUMN b BIGINT NOT NULL;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest12.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest12 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE tbl_name\" +\n                \"\\n\\tDROP FOREIGN KEY fk_symbol;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest13.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest13 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE tbl_name DISCARD TABLESPACE;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE tbl_name\" +\n                \"\\n\\tDISCARD TABLESPACE;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest14.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest14 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE tbl_name IMPORT TABLESPACE;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE tbl_name\" +\n                \"\\n\\tIMPORT TABLESPACE;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest15.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest15 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table st_jklsxxb disable constraint FK_ST_xxx_REFERENCE_ST_xxx\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE st_jklsxxb\" +\n                \"\\n\\tDISABLE CONSTRAINT FK_ST_xxx_REFERENCE_ST_xxx\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest16.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest16 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table st_jklsxxb enable constraint FK_ST_xxx_REFERENCE_ST_xxx\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE st_jklsxxb\" +\n                \"\\n\\tENABLE CONSTRAINT FK_ST_xxx_REFERENCE_ST_xxx\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest17.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest17 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table rms.rms_Person_Event drop foreign key FKA382487726D72F65\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE rms.rms_Person_Event\\n\" +\n                \"\\tDROP FOREIGN KEY FKA382487726D72F65\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest18.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest18 {\n    @Test\n    public void test_alter_charset() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) CHARACTER SET gbk NULL  FIRST ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tADD COLUMN `f2` VARCHAR(45) CHARACTER SET gbk NULL FIRST;\", output);\n    }\n\n    @Test\n    public void test_alter_collate() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) COLLATE utf8_bin NULL  FIRST ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tADD COLUMN `f2` VARCHAR(45) COLLATE utf8_bin NULL FIRST;\", output);\n    }\n\n    @Test\n    public void test_alter_charset_collate() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) CHARACTER SET utf8 COLLATE utf8_bin  NULL  FIRST ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tADD COLUMN `f2` VARCHAR(45) CHARACTER SET utf8 COLLATE utf8_bin NULL FIRST;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest19.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest19 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD KEY `idx_parent_id` (`parent_id`)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tADD KEY `idx_parent_id` (`parent_id`)\", output);\n    }\n\n    @Test\n    public void test_alter_add_index() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD INDEX `idx_parent_id` (`parent_id`)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tADD INDEX `idx_parent_id` (`parent_id`)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest2 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) NULL  FIRST ;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\\n\\tADD COLUMN `f2` VARCHAR(45) NULL FIRST;\", output);\n    }\n\n    @Test\n    public void test_alter_add_column() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) NULL  AFTER `fid` , ADD COLUMN `f3` VARCHAR(45) NULL  FIRST `f2`\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                \"\\n\\tADD COLUMN `f2` VARCHAR(45) NULL AFTER `fid`,\" +\n                \"\\n\\tADD COLUMN `f3` VARCHAR(45) NULL FIRST `f2`\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest20.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest20 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE score1 ADD ( test3 int(11),test4 int(11))\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        assertEquals(\"ALTER TABLE score1\"\n                + \"\\n\\tADD COLUMN (test3 int(11), test4 int(11))\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table score1\"\n                + \"\\n\\tadd column (test3 int(11), test4 int(11))\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest21.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest21 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE tbl_name\"\n                + \"\\n\\tCONVERT TO CHARACTER SET charset_name\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest22.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest22 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"alter table pj_usr_auth add constraint FK_Reference_8 foreign key (usr) references usr (usr) on delete restrict on update restrict;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE pj_usr_auth\"\n                + \"\\n\\tADD CONSTRAINT FK_Reference_8 FOREIGN KEY (usr) REFERENCES usr (usr) ON DELETE RESTRICT ON UPDATE RESTRICT;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest23.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest23 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"alter table xxxxx modify (xxx default '0');\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE xxxxx\"\n                + \"\\n\\tMODIFY COLUMN xxx DEFAULT '0';\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest24.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest24 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"alter table xxxxx modify (f0 default '0',f1 default '0');\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE xxxxx\"\n                + \"\\n\\tMODIFY COLUMN f0 DEFAULT '0',\"\n                + \"\\n\\tMODIFY COLUMN f1 DEFAULT '0';\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest25.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest25 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"alter table xxxx add over bigint unsigned comment 'xxxx';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE xxxx\"\n                + \"\\n\\tADD COLUMN over bigint UNSIGNED COMMENT 'xxxx';\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest26.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest26 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"alter table xxxx UNION = (t1, t2);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE xxxx\"\n                + \"\\n\\tUNION = (t1, t2);\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest27.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest27 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE app_key ROW_FORMAT = DEFAULT\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE app_key\" +\n                \"\\n\\tROW_FORMAT = DEFAULT\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest28.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest28 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE project_measures MODIFY COLUMN value DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_1 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_2 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_3 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_4 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_5 DECIMAL (38,20) NULL\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE project_measures\\n\" +\n                \"\\tMODIFY COLUMN value DECIMAL(38, 20) NULL,\\n\" +\n                \"\\tMODIFY COLUMN variation_value_1 DECIMAL(38, 20) NULL,\\n\" +\n                \"\\tMODIFY COLUMN variation_value_2 DECIMAL(38, 20) NULL,\\n\" +\n                \"\\tMODIFY COLUMN variation_value_3 DECIMAL(38, 20) NULL,\\n\" +\n                \"\\tMODIFY COLUMN variation_value_4 DECIMAL(38, 20) NULL,\\n\" +\n                \"\\tMODIFY COLUMN variation_value_5 DECIMAL(38, 20) NULL\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest29.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest29 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"alter TABLE project_measures\\n\" +\n                \"        DROP COLUMN diff_value_1,\\n\" +\n                \"        DROP COLUMN diff_value_2,\\n\" +\n                \"        DROP COLUMN diff_value_3,\\n\" +\n                \"        ADD COLUMN variation_value_1 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_2 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_3 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_4 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"        ADD COLUMN variation_value_5 DECIMAL(30, 20) NULL DEFAULT NULL\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE project_measures\\n\" +\n                \"\\tDROP COLUMN diff_value_1,\\n\" +\n                \"\\tDROP COLUMN diff_value_2,\\n\" +\n                \"\\tDROP COLUMN diff_value_3,\\n\" +\n                \"\\tADD COLUMN variation_value_1 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"\\tADD COLUMN variation_value_2 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"\\tADD COLUMN variation_value_3 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"\\tADD COLUMN variation_value_4 DECIMAL(30, 20) NULL DEFAULT NULL,\\n\" +\n                \"\\tADD COLUMN variation_value_5 DECIMAL(30, 20) NULL DEFAULT NULL\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest3 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE `test`.`tb1` DROP COLUMN `f3` , CHANGE COLUMN `fname` `fname` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT NULL  AFTER `fid`\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `test`.`tb1`\" +\n                        \"\\n\\tDROP COLUMN `f3`,\" +\n                        \"\\n\\tCHANGE COLUMN `fname` `fname` VARCHAR(45) CHARACTER SET latin1 NULL DEFAULT NULL AFTER `fid`\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest30.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest30 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE test_table_normal\\n\" +\n                \"ADD FOREIGN KEY (stuID)\\n\" +\n                \"REFERENCES Persons(stuID);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE test_table_normal\\n\" +\n                \"\\tADD FOREIGN KEY (stuID) REFERENCES Persons (stuID);\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest31_renameIndex.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest31_renameIndex {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE test_table_normal\\n\" +\n                \"RENAME INDEX old_index_name TO new_index_name\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE test_table_normal\\n\" +\n                \"\\tRENAME INDEX old_index_name TO new_index_name\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest32.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest32 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE src.`part_tab` DISCARD PARTITION p10 TABLESPACE\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE src.`part_tab`\\n\" +\n                \"\\tDISCARD PARTITION p10 TABLESPACE\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest33.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest33 {\n    @Test\n    public void test_exchange_0() throws Exception {\n        String sql = \"ALTER TABLE src.`part_tab` EXCHANGE PARTITION p9 WITH TABLE test_create_table without validation\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE src.`part_tab`\\n\" +\n                \"\\tEXCHANGE PARTITION p9 WITH TABLE test_create_table WITHOUT VALIDATION\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_exchange_1() throws Exception {\n        String sql = \"ALTER TABLE e EXCHANGE PARTITION p0 WITH TABLE e2 WITHOUT VALIDATION;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE e\\n\" +\n                \"\\tEXCHANGE PARTITION p0 WITH TABLE e2 WITHOUT VALIDATION;\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_exchange_2() throws Exception {\n        String sql = \"ALTER TABLE e EXCHANGE PARTITION p0 WITH TABLE e2 WITH VALIDATION;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE e\\n\" +\n                \"\\tEXCHANGE PARTITION p0 WITH TABLE e2 WITH VALIDATION;\", SQLUtils.toMySqlString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest34_renameIndex.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest34_renameIndex {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"alter table test.table rename index idx_status to idx_status_2\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE test.table\\n\" +\n                \"\\tRENAME INDEX idx_status TO idx_status_2\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest35_multi.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest35_multi {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE `datacompute`.`users_quan` \\n\" +\n                \"DROP COLUMN `address`,\\n\" +\n                \"CHANGE COLUMN `name` `username` VARCHAR(255) NULL DEFAULT 'username' ,\\n\" +\n                \"ADD COLUMN `age` VARCHAR(45) NULL DEFAULT 'age' AFTER `username`,\\n\" +\n                \"ADD UNIQUE INDEX `idx_username` (`username` ASC), RENAME TO  `datacompute`.`users_dc` ;\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `datacompute`.`users_quan`\\n\" +\n                \"\\tDROP COLUMN `address`,\\n\" +\n                \"\\tCHANGE COLUMN `name` `username` VARCHAR(255) NULL DEFAULT 'username',\\n\" +\n                \"\\tADD COLUMN `age` VARCHAR(45) NULL DEFAULT 'age' AFTER `username`,\\n\" +\n                \"\\tADD UNIQUE INDEX `idx_username` (`username` ASC),\\n\" +\n                \"\\tRENAME TO `datacompute`.`users_dc`;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest36.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest36 {\n    @Test\n    public void test_alter_add_key() throws Exception {\n        String sql = \"ALTER TABLE t1 ADD INDEX idx_order_id(first_name) USING BTREE\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t1\\n\" +\n                \"\\tADD INDEX idx_order_id USING BTREE (first_name)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest37.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest37 {\n    @Test\n    public void test_alter_modify_clustered_by() throws Exception {\n        String sql = \"alter table new_ddl.ddl_test_1 clustered by (col1, col2)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE new_ddl.ddl_test_1\\n\"\n                + \"\\tCLUSTERED BY col1, col2\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest38.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest38 {\n    @Test\n    public void test_alter_modify_clustered_by() throws Exception {\n        String sql = \"ALTER TABLE `result` ADD INDEX `index_code` (`code`) USING BTREE;\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE `result`\\n\" +\n                \"\\tADD INDEX `index_code` USING BTREE (`code`);\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest39_ann.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest39_ann {\n    @Test\n    public void test_alter_modify_clustered_by() throws Exception {\n        String sql = \"ALTER TABLE face_feature ADD ANN INDEX facefea_index2  (facefea) DistanceMeasure = DotProduct ALGORITHM = IVF;\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE face_feature\\n\" +\n                \"\\tADD ANN INDEX facefea_index2 (facefea) ALGORITHM = IVF DistanceMeasure = DotProduct;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest4 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table test   add  dspcode  char(200)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE test\" +\n                \"\\n\\tADD COLUMN dspcode char(200)\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertTrue(visitor.getColumns().contains(new Column(\"test\", \"dspcode\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest41.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest41 {\n    @Test\n    public void test_alter_1() throws Exception {\n        String sql = \"alter table test COLLATE utf8mb4_unicode_ci\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE test\\n\" +\n                \"\\tCOLLATE = utf8mb4_unicode_ci\", output);\n    }\n\n    @Test\n    public void test_alter_2() throws Exception {\n        String sql = \"alter table test storage_type = 'oss'\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE test\\n\" +\n                \"\\tSTORAGE_TYPE = 'oss'\", output);\n    }\n\n    @Test\n    public void test_alter_3() throws Exception {\n        String sql = \"alter table test storage_policy = 'hot'\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE test\\n\" +\n                \"\\tSTORAGE_POLICY = 'hot'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest42.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest42 {\n    @Test\n    public void test_alter_modify_clustered_by() throws Exception {\n        String sql = \"alter table task AUTO_INCREMENT = 20000000 COMMENT ='自增起始值'\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE task\\n\" +\n                \"\\tAUTO_INCREMENT = 20000000 COMMENT = '自增起始值'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest43.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest43 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE logical_db.logical_tb SET TBLPROPERTIES ('read_only'=1)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE logical_db.logical_tb\\n\" +\n                \"\\tSET TBLPROPERTIES ('read_only' = 1)\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"ALTER TABLE logical_db.logical_tb SET TBLPROPERTIES ('read_only'=1) ON physical_db.physical_tb\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE logical_db.logical_tb\\n\" +\n                \"\\tSET TBLPROPERTIES ('read_only' = 1) ON physical_db.physical_tb\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest44.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest44 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE logical_db.logical_tb SET TBLPROPERTIES ('read_only'=1)\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE logical_db.logical_tb\\n\" +\n                \"\\tSET TBLPROPERTIES ('read_only' = 1)\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"ALTER TABLE logical_db.logical_tb SET TBLPROPERTIES ('read_only'=1) ON physical_db.physical_tb\";\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE logical_db.logical_tb\\n\" +\n                \"\\tSET TBLPROPERTIES ('read_only' = 1) ON physical_db.physical_tb\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest45.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author shicai.xsc 2018/9/13 下午3:35\n * @desc\n * @since 5.0.0.0\n */\npublic class MySqlAlterTableTest45 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE xx\\n\" +\n                \"ADD \\n\" +\n                \"EXTPARTITION (\\n\" +\n                \"DBPARTITION xxx BY KEY('abc') TBPARTITION yyy BY KEY('abc'), \\n\" +\n                \"DBPARTITION yyy BY KEY('def') TBPARTITION yyy BY KEY('def'), \\n\" +\n                \"DBPARTITION yyy BY KEY('gpk')\\n\" +\n                \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = stmt.toString();\n        assertEquals(\"ALTER TABLE xx\\n\\t\" +\n                \"ADD \\n\\t\" +\n                \"EXTPARTITION (\\n\\t\" +\n                \"\\tDBPARTITION xxx BY KEY('abc') TBPARTITION yyy BY KEY('abc'), \\n\\t\" +\n                \"\\tDBPARTITION yyy BY KEY('def') TBPARTITION yyy BY KEY('def'), \\n\\t\" +\n                \"\\tDBPARTITION yyy BY KEY('gpk')\\n\\t\" +\n                \")\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"ALTER TABLE xx\\n\" +\n                \"DROP \\n\" +\n                \"EXTPARTITION (\\n\" +\n                \"DBPARTITION xxx BY KEY('abc') TBPARTITION yyy BY KEY('abc'), \\n\" +\n                \"DBPARTITION yyy BY KEY('def') TBPARTITION yyy BY KEY('def'), \\n\" +\n                \"DBPARTITION yyy BY KEY('gpk')\\n\" +\n                \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = stmt.toString();\n        assertEquals(\"ALTER TABLE xx\\n\\t\" +\n                \"DROP \\n\\t\" +\n                \"EXTPARTITION (\\n\\t\" +\n                \"\\tDBPARTITION xxx BY KEY('abc') TBPARTITION yyy BY KEY('abc'), \\n\\t\" +\n                \"\\tDBPARTITION yyy BY KEY('def') TBPARTITION yyy BY KEY('def'), \\n\\t\" +\n                \"\\tDBPARTITION yyy BY KEY('gpk')\\n\\t\" +\n                \")\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest46_add_column.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author shicai.xsc 2018/9/13 下午3:35\n * @desc\n * @since 5.0.0.0\n */\npublic class MySqlAlterTableTest46_add_column {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE test_pk ADD COLUMN remark2 varchar(255) DEFAULT NULL , ALGORITHM=inplace,LOCK=NONE\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        assertEquals(\"ALTER TABLE test_pk\\n\" +\n                \"\\tADD COLUMN remark2 varchar(255) DEFAULT NULL,\\n\" +\n                \"\\tALGORITHM = inplace,\\n\" +\n                \"\\tLOCK = NONE\", stmt.toString());\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"ALTER TABLE test_pk modify COLUMN remark2 varchar(32) DEFAULT NULL , ALGORITHM=copy,LOCK=SHARED\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        assertEquals(\"ALTER TABLE test_pk\\n\" +\n                \"\\tMODIFY COLUMN remark2 varchar(32) DEFAULT NULL,\\n\" +\n                \"\\tALGORITHM = copy,\\n\" +\n                \"\\tLOCK = SHARED\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest47.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author shicai.xsc 2018/9/13 下午3:35\n * @desc\n * @since 5.0.0.0\n */\npublic class MySqlAlterTableTest47 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE aaaaa SET RULE.BROADCAST=TRUE\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = stmt.toString();\n        assertEquals(\"ALTER TABLE aaaaa\\n\" +\n                \"\\tSET TBLPROPERTIES (RULE.BROADCAST = true)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest48.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author shicai.xsc 2018/9/13 下午3:35\n * @desc\n * @since 5.0.0.0\n */\npublic class MySqlAlterTableTest48 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE `aop_sample_pool`\\n\" +\n                \"  ADD COLUMN `properties` json NULL COMMENT '样本属性',\\n\" +\n                \"  ADD COLUMN `type` int unsigned NULL DEFAULT 1 COMMENT '1: aop样本 2:odps样本 3:swift样本',\\n\" +\n                \"  ADD COLUMN `odps_project` varchar(200) GENERATED ALWAYS AS (properties->'$.odpsProject') VIRTUAL NULL COMMENT 'odps project',\\n\" +\n                \"  ADD COLUMN `odps_table` varchar(200) GENERATED ALWAYS AS (properties->'$.odpsTable') VIRTUAL NULL COMMENT 'odps表名',\\n\" +\n                \"  ADD KEY `idx_type` (`type`),\\n\" +\n                \"  ADD KEY `idx_type_name` (`type`,`name`),\\n\" +\n                \"  ADD KEY `idx_owner` (`owner`),\\n\" +\n                \"  ADD KEY `idx_odps_project` (`odps_project`(20)),\\n\" +\n                \"  ADD KEY `idx_odps_table` (`odps_table`(20));\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = stmt.toString();\n        assertEquals(\"ALTER TABLE `aop_sample_pool`\\n\" +\n                \"\\tADD COLUMN `properties` json NULL COMMENT '样本属性',\\n\" +\n                \"\\tADD COLUMN `type` int UNSIGNED NULL DEFAULT 1 COMMENT '1: aop样本 2:odps样本 3:swift样本',\\n\" +\n                \"\\tADD COLUMN `odps_project` varchar(200) GENERATED ALWAYS AS (properties -> '$.odpsProject') VIRTUAL NULL COMMENT 'odps project',\\n\" +\n                \"\\tADD COLUMN `odps_table` varchar(200) GENERATED ALWAYS AS (properties -> '$.odpsTable') VIRTUAL NULL COMMENT 'odps表名',\\n\" +\n                \"\\tADD KEY `idx_type` (`type`),\\n\" +\n                \"\\tADD KEY `idx_type_name` (`type`, `name`),\\n\" +\n                \"\\tADD KEY `idx_owner` (`owner`),\\n\" +\n                \"\\tADD KEY `idx_odps_project` (`odps_project`(20)),\\n\" +\n                \"\\tADD KEY `idx_odps_table` (`odps_table`(20));\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest49.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author shicai.xsc 2018/9/13 下午3:35\n * @desc\n * @since 5.0.0.0\n */\npublic class MySqlAlterTableTest49 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"alter table a add column auto_id int not null auto_increment by group primary key;\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = stmt.toString();\n        assertEquals(\"ALTER TABLE a\\n\" +\n                \"\\tADD COLUMN auto_id int NOT NULL PRIMARY KEY AUTO_INCREMENT BY GROUP;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest5 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE table_name   change COLUMN column_name column_newname char(50)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE table_name\" +\n                \"\\n\\tCHANGE COLUMN column_name column_newname char(50)\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertTrue(visitor.getColumns().contains(new Column(\"table_name\", \"column_name\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest50.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author shicai.xsc 2018/9/13 下午3:35\n * @desc\n * @since 5.0.0.0\n */\npublic class MySqlAlterTableTest50 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"alter table ren_test ALGORITHM=INPLACE,LOCK=NONE,add index idx_name (name) ;\";\n\n        List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        assertEquals(1, stmtList.size());\n        SQLStatement stmt = stmtList.get(0);\n        String output = stmt.toString();\n//        assertEquals(\"ALTER TABLE ren_test\\n\" +\n//                \"\\tALGORITHM = INPLACE,\\n\" +\n//                \"\\tADD INDEX idx_name (name)\\n\" +\n//                \"\\tLOCK = NONE;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest51_table_options.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest51_table_options {\n    @Test\n    public void test_0_options_no_comma_no_eq() {\n        String sql = \"alter table test001\\n\" +\n                \"auto_increment 1\\n\" +\n                \"avg_row_length 1\\n\" +\n                \"default character set utf8\\n\" +\n                \"checksum 0\\n\" +\n                \"default collate utf8_unicode_ci\\n\" +\n                \"comment 'hehe'\\n\" +\n                \"compression 'LZ4'\\n\" +\n                \"connection 'conn'\\n\" +\n                \"index directory 'path'\\n\" +\n                \"delay_key_write 1\\n\" +\n                \"encryption 'N'\\n\" +\n                \"engine innodb\\n\" +\n                \"insert_method no\\n\" +\n                \"key_block_size 32\\n\" +\n                \"max_rows 999\\n\" +\n                \"min_rows 1\\n\" +\n                \"pack_keys default\\n\" +\n                \"password 'psw'\\n\" +\n                \"row_format dynamic\\n\" +\n                \"stats_auto_recalc default\\n\" +\n                \"stats_persistent default\\n\" +\n                \"stats_sample_pages 10\\n\" +\n                \"tablespace `tbs_name` storage memory\\n\" +\n                \"union (tb1,tb2,tb3)\\n\" +\n                \"auto_increment 1\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tAUTO_INCREMENT = 1 AVG_ROW_LENGTH = 1 CHARACTER SET = utf8 CHECKSUM = 0 COLLATE = utf8_unicode_ci COMMENT = 'hehe' COMPRESSION = 'LZ4' CONNECTION = 'conn' COLLATE = 'path' DELAY_KEY_WRITE = 1 ENCRYPTION = 'N' ENGINE = innodb INSERT_METHOD = no KEY_BLOCK_SIZE = 32 MAX_ROWS = 999 MIN_ROWS = 1 PACK_KEYS = DEFAULT PASSWORD = 'psw' ROW_FORMAT = dynamic STATS_AUTO_RECALC = DEFAULT STATS_PERSISTENT = DEFAULT STATS_SAMPLE_PAGES = 10 TABLESPACE `tbs_name` STORAGE memory UNION = (tb1, tb2, tb3) AUTO_INCREMENT = 1\", SQLUtils.toMySqlString(stmt));\n    }\n\n    @Test\n    public void test_0_options_comma_eq() {\n        String sql = \"alter table test001\\n\" +\n                \"auto_increment = 2,\\n\" +\n                \"avg_row_length = 2,\\n\" +\n                \"character set = utf8,\\n\" +\n                \"checksum = 1,\\n\" +\n                \"collate = utf8_unicode_ci,\\n\" +\n                \"comment = 'hehe',\\n\" +\n                \"compression = 'NONE',\\n\" +\n                \"connection = 'conn',\\n\" +\n                \"data directory = 'path',\\n\" +\n                \"delay_key_write = 0,\\n\" +\n                \"encryption = 'Y',\\n\" +\n                \"engine = innodb,\\n\" +\n                \"insert_method = first,\\n\" +\n                \"key_block_size = 64,\\n\" +\n                \"max_rows = 999,\\n\" +\n                \"min_rows = 1,\\n\" +\n                \"pack_keys = 0,\\n\" +\n                \"password = 'psw',\\n\" +\n                \"row_format = fixed,\\n\" +\n                \"stats_auto_recalc = 1,\\n\" +\n                \"stats_persistent = 0,\\n\" +\n                \"stats_sample_pages = 2,\\n\" +\n                \"tablespace `tbs_name`\\n\" +\n                \"union = (tb1,tb2,tb3);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tAUTO_INCREMENT = 2 AVG_ROW_LENGTH = 2 CHARACTER SET = utf8 CHECKSUM = 1 COLLATE = utf8_unicode_ci COMMENT = 'hehe' COMPRESSION = 'NONE' CONNECTION = 'conn' COLLATE = 'path' DELAY_KEY_WRITE = 0 ENCRYPTION = 'Y' ENGINE = innodb INSERT_METHOD = first KEY_BLOCK_SIZE = 64 MAX_ROWS = 999 MIN_ROWS = 1 PACK_KEYS = 0 PASSWORD = 'psw' ROW_FORMAT = fixed STATS_AUTO_RECALC = 1 STATS_PERSISTENT = 0 STATS_SAMPLE_PAGES = 2 TABLESPACE `tbs_name` UNION = (tb1, tb2, tb3);\", SQLUtils.toMySqlString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest52_primary_prefix_key.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlAlterTableTest52_primary_prefix_key\n * @description\n * @Author zzy\n * @Date 2019-05-15 14:37\n */\npublic class MySqlAlterTableTest52_primary_prefix_key {\n    @Test\n    public void test_0() {\n        String sql = \"alter table test001 add primary key (b (4) asc, c (8) desc);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        assertEquals(\"ALTER TABLE test001\\n\" +\n                \"\\tADD PRIMARY KEY (b(4) ASC, c(8) DESC);\", SQLUtils.toMySqlString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest53.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author shicai.xsc 2018/9/13 下午3:35\n * @desc\n * @since 5.0.0.0\n */\npublic class MySqlAlterTableTest53 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"ALTER TABLE t_str_spare  CONVERT TO CHARACTER SET UTF8 COLLATE utf8_bin\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        String formatSql = SQLUtils.toSQLString(stmt);\n        assertEquals(\"ALTER TABLE t_str_spare\\n\" +\n                \"\\tCONVERT TO CHARACTER SET UTF8 COLLATE utf8_bin\", formatSql);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest54.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.ParserException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest54 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"alter table event_log storage_policy = 'HOT'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) parser.parseStatementList().get(0);\n        assertEquals(1, stmt.getTableOptions().size());\n        String formatSql = SQLUtils.toSQLString(stmt);\n        assertEquals(\"ALTER TABLE event_log\\n\" +\n                \"\\tSTORAGE_POLICY = 'HOT'\", formatSql);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"alter table event_log storage_policy = 'COLD'\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        String formatSql = SQLUtils.toSQLString(stmt);\n        assertEquals(\"ALTER TABLE event_log\\n\" +\n                \"\\tSTORAGE_POLICY = 'COLD'\", formatSql);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"alter table event_log storage_policy = 'MIXED' hot_partition_count = 10;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) parser.parseStatementList().get(0);\n        assertEquals(2, stmt.getTableOptions().size());\n        String formatSql = SQLUtils.toSQLString(stmt);\n        assertEquals(\"ALTER TABLE event_log\\n\" +\n                \"\\tSTORAGE_POLICY = 'MIXED' HOT_PARTITION_COUNT = 10;\", formatSql);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"alter table event_log hot_partition_count = 10;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLAlterTableStatement stmt = (SQLAlterTableStatement) parser.parseStatementList().get(0);\n        assertEquals(1, stmt.getTableOptions().size());\n        String formatSql = SQLUtils.toSQLString(stmt);\n        assertEquals(\"ALTER TABLE event_log\\n\" +\n                \"\\tHOT_PARTITION_COUNT = 10;\", formatSql);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"alter table event_log hot_partition_count = 'abc';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        try {\n            SQLStatement stmt = parser.parseStatementList().get(0);\n            fail();\n        } catch (ParserException e) {\n            //do nothing\n        }\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"alter table event_log hot_partition_count = '10';\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        try {\n            SQLStatement stmt = parser.parseStatementList().get(0);\n            fail();\n        } catch (ParserException e) {\n            //do nothing\n        }\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"alter table event_log storage_policy = HOT\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        try {\n            SQLAlterTableStatement stmt = (SQLAlterTableStatement) parser.parseStatementList().get(0);\n            fail();\n        } catch (Exception e) {\n        }\n    }\n\n    @Test\n    public void test_7() throws Exception {\n        String sql = \"alter table event_log storage_policy = COLD\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        try {\n            SQLAlterTableStatement stmt = (SQLAlterTableStatement) parser.parseStatementList().get(0);\n            fail();\n        } catch (Exception e) {\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest6.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest6 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table tableName DROP FOREIGN KEY fk_symbol\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE tableName\" +\n                \"\\n\\tDROP FOREIGN KEY fk_symbol\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest7.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest7 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t1 ENGINE = InnoDB;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t1\" +\n                \"\\n\\tENGINE = InnoDB;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest8.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest8 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t2 AUTO_INCREMENT = 3\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t2\" +\n                \"\\n\\tAUTO_INCREMENT = 3\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest9.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest9 {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE t2\" +\n                \"\\n\\tDROP COLUMN c,\" +\n                \"\\n\\tDROP COLUMN d;\", output);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest_40_change.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableRenameColumn;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableChangeColumn;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest_40_change {\n    @Test\n    public void test_alter_constraint() throws Exception {\n        String sql = \"alter table sdfwef change column a c int\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE sdfwef\\n\" +\n                \"\\tCHANGE COLUMN a c int\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table sdfwef\\n\" +\n                \"\\tchange column a c int\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(\n                isRenameColumn((SQLAlterTableStatement) stmt)\n        );\n    }\n\n    public boolean isRenameColumn(SQLAlterTableStatement stmt) {\n        for (SQLAlterTableItem item : stmt.getItems()) {\n            if (item instanceof MySqlAlterTableChangeColumn) {\n                MySqlAlterTableChangeColumn changeColumn = (MySqlAlterTableChangeColumn) item;\n                SQLIdentifierExpr columnName = (SQLIdentifierExpr) changeColumn.getColumnName();\n                String newColumnName = changeColumn.getNewColumnDefinition().getColumnName();\n                if (!columnName.nameEquals(newColumnName)) {\n                    return true;\n                }\n            }\n\n            if (item instanceof SQLAlterTableRenameColumn) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest_addFk.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest_addFk {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"alter table Test2 add index FK4CF5DC0F5DD7C31 (test1_name), \" +\n                \"add constraint FK4CF5DC0F5DD7C31 foreign key (test1_name) references Test1 (name)\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE Test2\" +\n                        \"\\n\\tADD INDEX FK4CF5DC0F5DD7C31 (test1_name),\" +\n                        \"\\n\\tADD CONSTRAINT FK4CF5DC0F5DD7C31 FOREIGN KEY (test1_name) REFERENCES Test1 (name)\",\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table Test2\" +\n                        \"\\n\\tadd index FK4CF5DC0F5DD7C31 (test1_name),\" +\n                        \"\\n\\tadd constraint FK4CF5DC0F5DD7C31 foreign key (test1_name) references Test1 (name)\",\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n\n        TableStat tableStat = visitor.getTableStat(\"Test2\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest_addPk.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.Token;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest_addPk {\n    @Test\n    public void test_alter_first() throws Exception {\n        String sql = \"ALTER TABLE test.table ADD PRIMARY KEY test_pk(id);\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE test.table\\n\" +\n                        \"\\tADD PRIMARY KEY (id);\",\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table test.table\\n\" +\n                        \"\\tadd primary key (id);\",\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n\n        TableStat tableStat = visitor.getTableStat(\"test.table\");\n        assertNotNull(tableStat);\n        assertEquals(1, tableStat.getAlterCount());\n        assertEquals(1, tableStat.getCreateIndexCount());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest_ads.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLExpr;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLAlterDatabaseStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterDatabaseSetOption;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest_ads {\n    @Test\n    public void test_alter_1() throws Exception {\n        String sql = \"ALTER TABLE grant_db.grant_table ADD INDEX user_id_index HashMap (grant_c1)\\n\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE grant_db.grant_table\\n\" + \"\\tADD INDEX user_id_index HASHMAP (grant_c1)\", output);\n    }\n\n    @Test\n    public void test_alter_2() throws Exception {\n        String sql = \"ALTER TABLE grant_db.grant_table  clustered by()\\n\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE grant_db.grant_table\\n\" + \"\\tCLUSTERED BY ()\", output);\n    }\n\n    @Test\n    public void test_alter_3() throws Exception {\n        String sql = \"ALTER TABLE grant_db.grant_table  subpartition_available_partition_num=10\\n\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE grant_db.grant_table\\n\" + \"\\tSUBPARTITION_AVAILABLE_PARTITION_NUM = 10\", output);\n    }\n\n    @Test\n    public void test_alter_4() throws Exception {\n        String sql = \"ALTER TABLEGROUP grant_db.group1  minRedundancy=10 k2=v2 executeTimeout=2000\\n\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLEGROUP grant_db.group1 minRedundancy = 10 k2 = v2 executeTimeout = 2000\", output);\n    }\n\n    @Test\n    public void test_alter_5() throws Exception {\n        String sql = \"ALTER TABLE schema1.table1 ADD COLUMN col1 varchar default '10' not null primary key\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE schema1.table1\\n\" + \"\\tADD COLUMN col1 varchar NOT NULL PRIMARY KEY DEFAULT '10'\", output);\n    }\n\n    @Test\n    public void test_alter_6() throws Exception {\n        String sql = \"alter database test_db set ecu_count=2\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER DATABASE test_db SET ecu_count = 2\", output);\n    }\n\n    @Test\n    public void test_alter_7() throws Exception {\n        String sql = \"ALTER TABLE grant_db.grant_table ADD INDEX user_id_index HashMap (grant_c1)\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE grant_db.grant_table\\n\" + \"\\tADD INDEX user_id_index HASHMAP (grant_c1)\", output);\n    }\n\n    @Test\n    public void test_alter_8() throws Exception {\n        String sql = \"ALTER TABLE grant_db.grant_table ADD column col2 varchar default '10' not null primary key\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER TABLE grant_db.grant_table\\n\"\n                + \"\\tADD COLUMN col2 varchar NOT NULL PRIMARY KEY DEFAULT '10'\", output);\n    }\n\n    @Test\n    public void test_alter_9() throws Exception {\n        String sql = \"alter database test_db set ecu_count=2\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER DATABASE test_db SET ecu_count = 2\", output);\n    }\n\n    @Test\n    public void test_alter_10() throws Exception {\n        String sql = \"alter database ads_cd_pre2 set resource_type='ecu' ecu_type=c8 ecu_count=2 modify_resource_type=true\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER DATABASE ads_cd_pre2 SET resource_type = 'ecu', ecu_type = c8, ecu_count = 2, modify_resource_type = true\", output);\n\n        SQLExpr modify_resource_type = ((MySqlAlterDatabaseSetOption) ((SQLAlterDatabaseStatement) stmt).getItem()).getOption(\n                \"modify_resource_type\");\n\n        assertEquals(\"true\", modify_resource_type.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/alterTable/MySqlAlterTableTest_drop_constraint.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.alterTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.Token;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlAlterTableTest_drop_constraint {\n    @Test\n    public void test_alter_constraint() throws Exception {\n        String sql = \"alter table TUSER drop constraint UK_084c17821a8f47e8b31fbb126b6\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatementList().get(0);\n        parser.match(Token.EOF);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(\"ALTER TABLE TUSER\" +\n                \"\\n\\tDROP CONSTRAINT UK_084c17821a8f47e8b31fbb126b6\", SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"alter table TUSER\" +\n                \"\\n\\tdrop constraint UK_084c17821a8f47e8b31fbb126b6\", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest0 extends MysqlTest {\n    public void test_types() throws Exception {\n        String sql = //\n                \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"  default_col varchar,\\n\" +\n                        \"  PRIMARY KEY(id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH (id)\\n\" +\n                        \"REFRESH FAST ON DEMAND\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS SELECT id FROM base;\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"\\tdefault_col varchar,\\n\" +\n                        \"\\tPRIMARY KEY (id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH(id)\\n\" +\n                        \"REFRESH FAST ON DEMAND\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT id\\n\" +\n                        \"FROM base;\",\n                SQLUtils.toSQLString(stmt, DbType.mysql, null, VisitorFeature.OutputDistributedLiteralInCreateTableStmt));\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"base\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest1 extends MysqlTest {\n    public void test_types() throws Exception {\n        String sql = //\n                \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"  PRIMARY KEY(id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH (id)\\n\" +\n                        \"REFRESH COMPLETE ON DEMAND\\n\" +\n                        \"START WITH now()\\n\" +\n                        \"NEXT DATE_ADD(now(), INTERVAL 1 MINUTE)\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS SELECT id FROM base;\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"\\tPRIMARY KEY (id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH(id)\\n\" +\n                        \"REFRESH COMPLETE ON DEMAND\\n\" +\n                        \"START WITH now() NEXT DATE_ADD(now(), INTERVAL 1 MINUTE)\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT id\\n\" +\n                        \"FROM base;\",\n                SQLUtils.toSQLString(stmt, DbType.mysql, null, VisitorFeature.OutputDistributedLiteralInCreateTableStmt));\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"base\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest2 extends MysqlTest {\n    public void test_types() throws Exception {\n        String sql = //\n                \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS SELECT id FROM base;\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE MATERIALIZED VIEW mymv\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT id\\n\" +\n                        \"FROM base;\",\n                SQLUtils.toSQLString(stmt, DbType.mysql));\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"base\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest3 extends MysqlTest {\n    public void test_types() throws Exception {\n        String sql = //\n                \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                        \"REFRESH COMPLETE\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS SELECT id FROM base;\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE MATERIALIZED VIEW mymv\\n\" +\n                        \"REFRESH COMPLETE\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT id\\n\" +\n                        \"FROM base;\",\n                SQLUtils.toSQLString(stmt, DbType.mysql));\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"base\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest4 extends MysqlTest {\n    public void test_types() throws Exception {\n        String sql = //\n                \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"  PRIMARY KEY(id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH (id)\\n\" +\n                        \"REFRESH COMPLETE ON DEMAND\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS SELECT id FROM base;\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"\\tPRIMARY KEY (id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH(id)\\n\" +\n                        \"REFRESH COMPLETE ON DEMAND\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT id\\n\" +\n                        \"FROM base;\",\n                SQLUtils.toSQLString(stmt, DbType.mysql, null, VisitorFeature.OutputDistributedLiteralInCreateTableStmt));\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"base\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest5 extends MysqlTest {\n    public void test_types() throws Exception {\n        String sql = //\n                \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"  PRIMARY KEY(id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH (id)\\n\" +\n                        \"REFRESH COMPLETE ON DEMAND\\n\" +\n                        \"START WITH '2020-08-20 14:50:00'\\n\" +\n                        \"NEXT current_date() + INTERVAL 15 DAY\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS SELECT id FROM base;\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"\\tPRIMARY KEY (id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY HASH(id)\\n\" +\n                        \"REFRESH COMPLETE ON DEMAND\\n\" +\n                        \"START WITH '2020-08-20 14:50:00' NEXT current_date() + INTERVAL 15 DAY\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT id\\n\" +\n                        \"FROM base;\",\n                SQLUtils.toSQLString(stmt, DbType.mysql, null, VisitorFeature.OutputDistributedLiteralInCreateTableStmt));\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"base\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest6.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest6 extends MysqlTest {\n    public void test1() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\\n\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(id)\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test2() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"START WITH now()\\n\" +\n                \"NEXT DATE_ADD(now(), INTERVAL 1 MINUTE)\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(id)\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"START WITH now() NEXT DATE_ADD(now(), INTERVAL 1 MINUTE)\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test3() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"AS\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test4() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  default_col varcahr,\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \"REFRESH FAST ON DEMAND\\n\" +\n                \"DISABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"\\tdefault_col varcahr,\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(id)\\n\" +\n                \"REFRESH FAST ON DEMAND\\n\" +\n                \"DISABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test5() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"REFRESH COMPLETE\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"REFRESH COMPLETE\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test6() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test7() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  default_col varcahr,\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \"ENABLE QUERY REWRITE AS SELECT * FROM base;\\n\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"\\tdefault_col varcahr,\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(id)\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test8() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"REFRESH ON DEMAND\\n\" +\n                \"DISABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"REFRESH ON DEMAND\\n\" +\n                \"DISABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT id\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test9() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW myview \" +\n                \" REFRESH NEXT now() + interval 1 day \" +\n                \" AS SELECT now() as t\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW myview\\n\" +\n                \"REFRESH NEXT now() + INTERVAL 1 DAY\\n\" +\n                \"AS\\n\" +\n                \"SELECT now() AS t\");\n    }\n\n    public void test10() throws Exception {\n        String sql = \"ALTER MATERIALIZED VIEW myview \" +\n                \" REFRESH NEXT now() + interval 1 day \";\n\n        ok(sql, \"ALTER MATERIALIZED VIEW myview\\n\" +\n                \"REFRESH NEXT now() + INTERVAL 1 DAY\");\n    }\n\n    public void test11() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW myview \" +\n                \" REFRESH FAST ON COMMIT \" +\n                \" DISABLE QUERY REWRITE \" +\n                \" AS SELECT * FROM base\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW myview\\n\" +\n                \"REFRESH FAST ON COMMIT\\n\" +\n                \"DISABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM base\");\n    }\n\n    public void test12() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW myview \" +\n                \" REFRESH COMPLETE ON OVERWRITE \" +\n                \" ENABLE QUERY REWRITE \" +\n                \" AS SELECT * FROM base\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW myview\\n\" +\n                \"REFRESH COMPLETE ON OVERWRITE\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM base\");\n    }\n\n    public void ok(String sql, String expectedSql) {\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(expectedSql, stmt.toString(VisitorFeature.OutputDistributedLiteralInCreateTableStmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest7.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest7 extends MysqlTest {\n    public void test1() throws Exception {\n        String sql = \"create materialized view `a` (\\n\" +\n                \"    `__adb_auto_id__` bigint AUTO_INCREMENT,\\n\" +\n                \"    `id` int comment 'id',\\n\" +\n                \"    `name` varchar(10),\\n\" +\n                \"    `value` double,\\n\" +\n                \"    index index_id(`name` ASC, `value` ASC),\\n\" +\n                \"    primary key (`__adb_auto_id__`)\\n\" +\n                \") DISTRIBUTED BY HASH(`__adb_auto_id__`)\\n\" +\n                \"comment 'materialized view a'\\n\" +\n                \"as select * from base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW `a` (\\n\" +\n                \"\\t`__adb_auto_id__` bigint AUTO_INCREMENT,\\n\" +\n                \"\\t`id` int COMMENT 'id',\\n\" +\n                \"\\t`name` varchar(10),\\n\" +\n                \"\\t`value` double,\\n\" +\n                \"\\tINDEX index_id(`name` ASC, `value` ASC),\\n\" +\n                \"\\tPRIMARY KEY (`__adb_auto_id__`)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(`__adb_auto_id__`)\\n\" +\n                \"COMMENT 'materialized view a'\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test2() throws Exception {\n        String sql = \"create materialized view `b` (\\n\" +\n                \"    `id` int comment 'id',\\n\" +\n                \"    `name` varchar(10) primary key\\n\" +\n                \") \\n\" +\n                \"DISTRIBUTED BY BROADCAST\\n\" +\n                \"INDEX_ALL = 'Y'\\n\" +\n                \"comment 'materialized view b'\\n\" +\n                \"as select * from base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW `b` (\\n\" +\n                \"\\t`id` int COMMENT 'id',\\n\" +\n                \"\\t`name` varchar(10) PRIMARY KEY\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY BROADCAST  INDEX_ALL = 'Y'\\n\" +\n                \"COMMENT 'materialized view b'\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test3() throws Exception {\n        String sql = \"create materialized view c (\\n\" +\n                \"    key index_id(id) comment 'id',\\n\" +\n                \"    name varchar(10),\\n\" +\n                \"    value double,\\n\" +\n                \"    clustered key idex(name, value),\\n\" +\n                \"    primary key(id)\\n\" +\n                \") \\n\" +\n                \"DISTRIBUTED by hash(id)\\n\" +\n                \"partition by value(date_format(dat, \\\"%Y%m%d\\\")) LIFECYCLE 30\\n\" +\n                \"comment 'materialized view c'\\n\" +\n                \"as select * from base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW c (\\n\" +\n                \"\\tKEY index_id (id) COMMENT 'id',\\n\" +\n                \"\\tname varchar(10),\\n\" +\n                \"\\tvalue double,\\n\" +\n                \"\\tCLUSTERED KEY idex (name, value),\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(id)\\n\" +\n                \"COMMENT 'materialized view c'\\n\" +\n                \"PARTITION BY VALUE (date_format(dat, '%Y%m%d'))\\n\" +\n                \"LIFECYCLE 30\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test4() throws Exception {\n        String sql = \"create materialized view d (\\n\" +\n                \"    id bigint(20) not null comment 'id',\\n\" +\n                \"    name varchar(10)\\n\" +\n                \") \\n\" +\n                \"ENGINE = 'CSTORE'\\n\" +\n                \"INDEX_ALL = 'Y'\\n\" +\n                \"DISTRIBUTED BY HASH(`ID`)\\n\" +\n                \"partition by value(name) LIFECYCLE 15\\n\" +\n                \"COMMENT 'materialized view d'\\n\" +\n                \"as select * from base;\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW d (\\n\" +\n                \"\\tid bigint(20) NOT NULL COMMENT 'id',\\n\" +\n                \"\\tname varchar(10)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(`ID`) ENGINE = 'CSTORE' INDEX_ALL = 'Y'\\n\" +\n                \"COMMENT 'materialized view d'\\n\" +\n                \"PARTITION BY VALUE (name)\\n\" +\n                \"LIFECYCLE 15\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM base;\");\n    }\n\n    public void test5() throws Exception {\n        String sql = \"Create Materialized View `mview_0` (\\n\" +\n                \" `a` int,\\n\" +\n                \" `b` double,\\n\" +\n                \" `c` float,\\n\" +\n                \" `d` int,\\n\" +\n                \" `e` double,\\n\" +\n                \" `f` float,\\n\" +\n                \" primary key (`a`)\\n\" +\n                \") DISTRIBUTED BY HASH(`a`) INDEX_ALL='Y'\\n\" +\n                \" REFRESH COMPLETE ON DEMAND\\n\" +\n                \" START WITH '2020-09-02 16:06:05'\\n\" +\n                \" NEXT adddatedatetime(now(), INTERVAL  '10' MINUTE)\\n\" +\n                \" DISABLE QUERY REWRITE\\n\" +\n                \"AS SELECT *\\n\" +\n                \"FROM\\n\" +\n                \"  `base0`\\n\" +\n                \", `base1`\\n\" +\n                \"WHERE ((`a` = `d`) AND (`c` <> `F`))\";\n\n        ok(sql, \"CREATE MATERIALIZED VIEW `mview_0` (\\n\" +\n                \"\\t`a` int,\\n\" +\n                \"\\t`b` double,\\n\" +\n                \"\\t`c` float,\\n\" +\n                \"\\t`d` int,\\n\" +\n                \"\\t`e` double,\\n\" +\n                \"\\t`f` float,\\n\" +\n                \"\\tPRIMARY KEY (`a`)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH(`a`) INDEX_ALL = 'Y'\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"START WITH '2020-09-02 16:06:05' NEXT adddatedatetime(now(), INTERVAL '10' MINUTE)\\n\" +\n                \"DISABLE QUERY REWRITE\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM `base0`, `base1`\\n\" +\n                \"WHERE ((`a` = `d`)\\n\" +\n                \"\\tAND (`c` <> `F`))\");\n    }\n\n    public void ok(String sql, String expectedSql) {\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(expectedSql, stmt.toString(VisitorFeature.OutputDistributedLiteralInCreateTableStmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest8_distributed_by_with_duplicate.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest8_distributed_by_with_duplicate extends MysqlTest {\n    public void test_types() throws Exception {\n        String sql = //\n                \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"  default_col varchar,\\n\" +\n                        \"  PRIMARY KEY(id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY DUPLICATE (id)\\n\" +\n                        \"REFRESH FAST ON DEMAND\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS SELECT id FROM base;\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                        \"\\tdefault_col varchar,\\n\" +\n                        \"\\tPRIMARY KEY (id)\\n\" +\n                        \")\\n\" +\n                        \"DISTRIBUTED BY DUPLICATE(id)\\n\" +\n                        \"REFRESH FAST ON DEMAND\\n\" +\n                        \"ENABLE QUERY REWRITE\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT id\\n\" +\n                        \"FROM base;\",\n                SQLUtils.toSQLString(stmt, DbType.mysql, null, VisitorFeature.OutputDistributedLiteralInCreateTableStmt));\n\n        OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n\n        assertEquals(1, visitor.getColumns().size());\n\n        assertTrue(visitor.getColumns().contains(new TableStat.Column(\"base\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySQLCreateMaterializedViewTest_fail.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySQLCreateMaterializedViewTest_fail extends OracleTest {\n    public void test1() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS SELECT \\n\";\n\n        failed(sql);\n    }\n\n    public void test2() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \"REFRESH COMPLETE ON DEMAND\\n\" +\n                \"START WITH now()\\n\" +\n                \"NEXT DATE_ADD(now(), INTERVAL 1 MINUTE)\\n\" +\n                \"ENABLE \\n\" +\n                \"AS SELECT id FROM base;\";\n\n        failed(sql);\n    }\n\n    public void test3() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"\";\n\n        failed(sql);\n    }\n\n    public void test4() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  default_col varcahr,\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \"REFRESH \\n\" +\n                \"DISABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        failed(sql);\n    }\n\n    public void test5() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"REFRESH \\n\" +\n                \"ENABLE QUERY REWRITE\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        failed(sql);\n    }\n\n    public void test6() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"ENABLE QUERY\\n\" +\n                \"AS SELECT id FROM base;\";\n\n        failed(sql);\n    }\n\n    public void test7() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv (\\n\" +\n                \"  default_col varcahr,\\n\" +\n                \"  PRIMARY KEY(id)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTED BY HASH (id)\\n\" +\n                \" QUERY REWRITE AS SELECT * FROM base;\\n\";\n\n        failed(sql);\n    }\n\n    public void test8() throws Exception {\n        String sql = \"CREATE MATERIALIZED VIEW mymv\\n\" +\n                \"REFRESH ON DEMAND\\n\" +\n                \"DISABLE \\n\" +\n                \"AS SELECT id FROM base;\";\n\n        failed(sql);\n    }\n\n    public void failed(String sql) {\n        try {\n            SQLUtils.parseSingleMysqlStatement(sql);\n            fail();\n        } catch (Exception e) {\n            System.out.println(e.getMessage());\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateAddLogFileGroupTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateAddLogFileGroupTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE LOGFILE GROUP lg1 ADD UNDOFILE 'undo.dat' INITIAL_SIZE = 10M ENGINE = InnoDB;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE LOGFILE GROUP lg1 ADD UNDOFILE 'undo.dat' INITIAL_SIZE 10M ENGINE InnoDB;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create database if not exists a\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE IF NOT EXISTS a\", output);\n    }\n\n    // for ads\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"create database test_cascade for 'ALIYUN$test@aliyun.com' options(resourceType=ecu ecu_type=c1 ecu_count=2)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE test_cascade FOR 'ALIYUN$test@aliyun.com' OPTIONS (ecu_type=c1 ecu_count=2 resourceType=ecu )\", output);\n    }\n\n    // for ads\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"CREATE EXTERNAL TABLE IF NOT EXISTS ots_0.ots_table_0 (pk VARCHAR, a BIGINT, b BIGINT) \"\n                + \"STORED BY 'OTS' WITH (column_mapping = 'pk:pk,a:col1,b:col2', serializer = 'default') \"\n                + \"COMMENT 'test_ots_table_0'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE EXTERNAL TABLE IF NOT EXISTS ots_0.ots_table_0 (\\n\"\n                + \"\\tpk VARCHAR,\\n\"\n                + \"\\ta BIGINT,\\n\"\n                + \"\\tb BIGINT\\n\"\n                + \") COMMENT 'test_ots_table_0'\\n\"\n                + \" STORED BY 'OTS'\\n\"\n                + \" WITH (column_mapping = 'pk:pk,a:col1,b:col2', serializer = 'default')\", output);\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = \"create database /*!32312 if  not  exists */ test4 /*!40100 default  character  set  utf8 */;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE IF NOT EXISTS test4 CHARACTER SET utf8;\", output);\n    }\n\n    @Test\n    public void test_5() throws Exception {\n        String sql = \"create database /*!32312 if  not  exists */ test5 /*!40100 default  character  set  utf8  collate  utf8_general_ci */;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE IF NOT EXISTS test5 CHARACTER SET utf8 COLLATE utf8_general_ci;\", output);\n    }\n\n    @Test\n    public void test_6() throws Exception {\n        String sql = \"create database /*!32312 if  not  exists */ test6 /*!40100 collate  utf8_general_ci  character  set  utf8  */;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE IF NOT EXISTS test6 CHARACTER SET utf8 COLLATE utf8_general_ci;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest2 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE DATABASE testRep CHARACTER SET utf8 COLLATE utf8_general_ci\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE testRep CHARACTER SET utf8 COLLATE utf8_general_ci\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest3 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create database user default charset=utf8 default collate=utf8_general_ci;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE user CHARACTER SET utf8 COLLATE utf8_general_ci;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest4 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create database super default character set utf8 collate = utf8_bin character set utf8 collate utf8_bin;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE super CHARACTER SET utf8 COLLATE utf8_bin;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest5 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE SCHEMA IF NOT EXISTS schema_name with (property_name = 'expression')\\n\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE IF NOT EXISTS schema_name\\n\" +\n                \"WITH (\\n\" +\n                \"\\tproperty_name = 'expression'\\n\" +\n                \")\", output);\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE SCHEMA IF NOT EXISTS `schema_name` with (property_name = 'expression')\\n\";\n\n        SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.mysql, SQLParserFeature.IgnoreNameQuotes);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE IF NOT EXISTS schema_name\\n\" +\n                \"WITH (\\n\" +\n                \"\\tproperty_name = 'expression'\\n\" +\n                \")\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest6_drds.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest6_drds extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE DATABASE d2 DEFAULT CHARACTER SET = gbk PASSWORD = 'd2_pwd' \\n\" +\n                \"STORED AS d1;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE d2 CHARACTER SET gbk\\n\" +\n                \"STORED AS d1;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest7_drds.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest7_drds extends MysqlTest {\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"CREATE DATABASE d1 DEFAULT CHARACTER SET = utf8mb4 PASSWORD = 'd1_pwd' \\n\" +\n                \"STORED IN d1 ON\\n\" +\n                \"    (IP = '127.0.0.1', PORT = 3306, USER = 'root', PASSWORD = '123456');\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE d1 CHARACTER SET utf8mb4\\n\" +\n                \"STORED IN d1 ON (IP = '127.0.0.1', PORT = 3306, USER = 'root', PASSWORD = '123456');\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest8_drds.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest8_drds extends MysqlTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE DATABASE IF NOT EXISTS d1 DEFAULT CHARACTER SET = utf8mb4 \\n\" +\n                \"  PASSWORD = 'd1_pwd' STORED BY \\n\" +\n                \"    (IP = '127.0.0.1', PORT = 3306, USER = 'root', PASSWORD = '123456'),\\n\" +\n                \"    (IP = '127.0.0.1', PORT = 3307, USER = 'root', PASSWORD = '123456');\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DATABASE IF NOT EXISTS d1 CHARACTER SET utf8mb4\\n\" +\n                \"STORED BY (IP = '127.0.0.1', PORT = 3306, USER = 'root', PASSWORD = '123456'),\\n\" +\n                \"\\t(IP = '127.0.0.1', PORT = 3307, USER = 'root', PASSWORD = '123456');\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateDatabaseTest9_issue_3975.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateDatabaseTest9_issue_3975\n        extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create database user default charset=utf8 collate=utf8_general_ci;\";\n\n        SQLCreateDatabaseStatement stmt = (SQLCreateDatabaseStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE DATABASE user CHARACTER SET utf8 COLLATE utf8_general_ci;\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create database user COLLATE=utf8_bin default CHARSET=utf8\";\n\n        SQLCreateDatabaseStatement stmt = (SQLCreateDatabaseStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE DATABASE user CHARACTER SET utf8 COLLATE utf8_bin\", stmt.toString());\n    }\n\n    public void test_craeteTable() throws Exception {\n        String sql = \"create table test_option(a int) COLLATE=utf8_bin default CHARSET=utf8; \";\n\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE TABLE test_option (\\n\" +\n                \"\\ta int\\n\" +\n                \") COLLATE = utf8_bin CHARSET = utf8;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateEventTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateEventTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create definer = current_user event if not exists someevent on schedule at current_timestamp + interval 30 minute\\n\" +\n                \"on completion preserve do begin insert into test.t1 values (33), (111);select * from test.t1; end; -- //\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DEFINER = current_user EVENT IF NOT EXISTS someevent ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 30 MINUTE\\n\" +\n                \"DO\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tINSERT INTO test.t1\\n\" +\n                \"\\tVALUES (33),\\n\" +\n                \"\\t\\t(111);\\n\" +\n                \"\\tSELECT *\\n\" +\n                \"\\tFROM test.t1;\\n\" +\n                \"END;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateEventTest1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateEventTest1 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create definer = 'ivan'@'%' event testevent1 on schedule every 1 hour ends '2016-11-05 23:59:00'\\n\" +\n                \"do begin select * from test.t2; end; -- //\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE DEFINER = 'ivan'@'%' EVENT testevent1 ON SCHEDULE EVERY 1 HOUR ENDS '2016-11-05 23:59:00'\\n\" +\n                \"DO\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tSELECT *\\n\" +\n                \"\\tFROM test.t2;\\n\" +\n                \"END;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateExternalCatalogTest1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateExternalCatalogTest1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE EXTERNAL CATALOG IF NOT EXISTS kafka_1 PROPERTIES (\"\n                + \"'connector.name'='kafka' \" + \"'kafka.table-names'='table1,table2' \"\n                + \"'kafka.nodes'='1.1.1.1:10000,1.1.1.2:10000') COMMENT 'this is a kafka connector test.'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE EXTERNAL CATALOG IF NOT EXISTS kafka_1 PROPERTIES (\\n\"\n                + \"'connector.name'='kafka'\\n\"\n                + \"'kafka.nodes'='1.1.1.1:10000,1.1.1.2:10000'\\n\"\n                + \"'kafka.table-names'='table1,table2')\\n\"\n                + \"COMMENT 'this is a kafka connector test.'\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE EXTERNAL CATALOG user_db.mysql_1 PROPERTIES (\"\n                + \"'connector.name'='mysql' \"\n                + \"'connection-url'='jdbc:mysql://1.1.1.1:3306' \"\n                + \"'connection-user'=\\\"x'!xx\\\" \"\n                + \"'connection-password'=\\\"x'xx\\\")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE EXTERNAL CATALOG user_db.mysql_1 PROPERTIES (\\n\"\n                + \"'connector.name'='mysql'\\n\"\n                + \"'connection-url'='jdbc:mysql://1.1.1.1:3306'\\n\"\n                + \"'connection-user'=\\\"x'!xx\\\"\\n\"\n                + \"'connection-password'=\\\"x'xx\\\")\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateExternalCatalogTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateExternalCatalogTest2 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE EXTERNAL CATALOG shanghao_test.oss_catalog_0\\n\" +\n                \"PROPERTIES\\n\" +\n                \"(\\n\" +\n                \"  connector.name='oss'\\n\" +\n                \"  'connection-url'='http://oss-cn-hangzhou-zmf.aliyuncs.com'\\n\" +\n                \"  'bucket-name'='oss_test'\\n\" +\n                \"  'connection-user' = 'access_id'\\n\" +\n                \"  'connection-password' = 'access_key'\\n\" +\n                \" )\\n\" +\n                \"COMMENT 'This is a sample to create an oss connector catalog';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE EXTERNAL CATALOG shanghao_test.oss_catalog_0 PROPERTIES (\\n\" +\n                \"connector.name='oss'\\n\" +\n                \"'bucket-name'='oss_test'\\n\" +\n                \"'connection-url'='http://oss-cn-hangzhou-zmf.aliyuncs.com'\\n\" +\n                \"'connection-user'='access_id'\\n\" +\n                \"'connection-password'='access_key')\\n\" +\n                \"COMMENT 'This is a sample to create an oss connector catalog';\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateFullTextAnalyzerTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateFullTextAnalyzerTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create fulltext ANALYZER test1 (\"\n                + \"'tokenizer' = 'dictionary-name',\"\n                + \"\\\"charfilter\\\" = ['name1','name2'],\"\n                + \"'tokenfilter'=['name1', 'name2']\"\n                + \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT ANALYZER test1(\\n\"\n                + \"\\\"TOKENIZER\\\" = dictionary-name,\\n\"\n                + \"\\\"CHARFILTER\\\" = [\\\"name1\\\", \\\"name2\\\"],\\n\"\n                + \"\\\"TOKENFILTER\\\" = [\\\"name1\\\", \\\"name2\\\"]\\n\" + \")\", output);\n    }\n\n    @Test\n    public void test_create() throws Exception {\n        String sql = \"create fulltext ANALYZER test1 (\"\n                + \"\\\"tokenizer\\\" = \\\"dictionary-name\\\",\"\n                + \"\\\"charfilter\\\" = [\\\"name1\\\",\\\"name2\\\"],\"\n                + \"\\\"tokenfilter\\\"=[\\\"name1\\\",\\\"name2\\\"]\"\n                + \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT ANALYZER test1(\\n\"\n                + \"\\\"TOKENIZER\\\" = dictionary-name,\\n\"\n                + \"\\\"CHARFILTER\\\" = [\\\"name1\\\", \\\"name2\\\"],\\n\"\n                + \"\\\"TOKENFILTER\\\" = [\\\"name1\\\", \\\"name2\\\"]\\n\"\n                + \")\", output);\n    }\n\n    @Test\n    public void test_create2() throws Exception {\n        String sql = \"create fulltext analyzer test_analyzer ( \\\"charfilter\\\"=[\\\"test_stconv\\\"],   \\\"tokenizer\\\"= \\\"test_alinlp\\\", \\\"tokenfilter\\\"=[\\\"test_pinyin\\\"] );\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT ANALYZER test_analyzer(\\n\"\n                + \"\\\"TOKENIZER\\\" = test_alinlp,\\n\"\n                + \"\\\"CHARFILTER\\\" = [\\\"test_stconv\\\"],\\n\"\n                + \"\\\"TOKENFILTER\\\" = [\\\"test_pinyin\\\"]\\n\"\n                + \");\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"show fulltext analyzers\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW FULLTEXT ANALYZERS\", output);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"show create fulltext analyzer test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW CREATE FULLTEXT ANALYZER test1\", output);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"alter fulltext analyzer test1 set k = 'a';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER FULLTEXT ANALYZER test1 SET k = 'a';\", output);\n    }\n\n    @Test\n    public void test_drop() throws Exception {\n        String sql = \"drop fulltext analyzer test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP FULLTEXT ANALYZER test1\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateFullTextCharFilterTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateFullTextCharFilterTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create fulltext charfilter test1 (\"\n                + \"'type' = 'typename',\"\n                + \"'key'='name',\"\n                + \"'key2'='name2'\"\n                + \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT CHARFILTER test1(\\n\" + \"\\\"type\\\" = 'typename',\\n\"\n                + \"'key' = 'name','key2' = 'name2'\\n\" + \")\", output);\n    }\n\n    @Test\n    public void test_crate() throws Exception {\n        String sql = \"create fulltext charfilter test1 (\"\n                + \"\\\"type\\\" = \\\"typename\\\",\"\n                + \"\\\"key\\\"=\\\"name\\\"\"\n                + \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT CHARFILTER test1(\\n\"\n                + \"\\\"type\\\" = 'typename',\\n\"\n                + \"'key' = 'name'\\n\"\n                + \")\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"show fulltext charfilters\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW FULLTEXT CHARFILTERS\", output);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"show create fulltext charfilter test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW CREATE FULLTEXT CHARFILTER test1\", output);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"alter fulltext charfilter test1 set k = 'a';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER FULLTEXT CHARFILTER test1 SET k = 'a';\", output);\n    }\n\n    @Test\n    public void test_drop() throws Exception {\n        String sql = \"drop fulltext charfilter test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP FULLTEXT CHARFILTER test1\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateFullTextDictTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateFullTextDictTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create fulltext dictionary test1 (\"\n                + \" word varchar comment 'comment1' \"\n                + \") comment 'comment1'\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT DICTIONARY test1(\\n\"\n                + \"word varchar COMMENT 'comment1'\\n\"\n                + \")\\n\" +\n                \"COMMENT 'comment1'\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"show fulltext dictionaries\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW FULLTEXT DICTIONARIES\", output);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"show fulltext dictionaries\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW FULLTEXT DICTIONARIES\", output);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"drop fulltext dictionary dic_name\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP FULLTEXT DICTIONARY dic_name\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateFullTextTokenFilterTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateFullTextTokenFilterTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create fulltext tokenfilter test1 (\"\n                + \"'type' = 'typename',\"\n                + \"'key'='name'\"\n                + \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT TOKENFILTER test1(\\n\"\n                + \"\\\"type\\\" = 'typename',\\n\"\n                + \"'key' = 'name'\\n\"\n                + \")\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"show fulltext tokenfilters\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW FULLTEXT TOKENFILTERS\", output);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"show create fulltext tokenfilter test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW CREATE FULLTEXT TOKENFILTER test1\", output);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"alter fulltext tokenfilter test1 set k = 'a';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER FULLTEXT TOKENFILTER test1 SET k = 'a';\", output);\n    }\n\n    @Test\n    public void test_drop() throws Exception {\n        String sql = \"drop fulltext tokenfilter test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP FULLTEXT TOKENFILTER test1\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateFullTextTokenizeTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateFullTextTokenizeTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create fulltext tokenizer test1 (\"\n                + \"'type' = 'typename',\"\n                + \"'user_defined_dict' = 'dictionary-name',\"\n                + \"'key'='name'\"\n                + \")\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT TOKENIZER test1(\\n\"\n                + \"\\\"type\\\" = 'typename',\\n\"\n                + \"\\\"user_defined_dict\\\" = 'dictionary-name',\\n\"\n                + \"'key' = 'name'\\n\"\n                + \")\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"show fulltext tokenfilters\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW FULLTEXT TOKENFILTERS\", output);\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"show create fulltext tokenfilter test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"SHOW CREATE FULLTEXT TOKENFILTER test1\", output);\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"alter fulltext tokenfilter test1 set k = 'a';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER FULLTEXT TOKENFILTER test1 SET k = 'a';\", output);\n    }\n\n    @Test\n    public void test_drop() throws Exception {\n        String sql = \"drop fulltext tokenfilter test1\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP FULLTEXT TOKENFILTER test1\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateFunctionTest_1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateFunctionTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"sql : \\n\" +\n                \"     create function `test1`.`proc1`(`a` enum('1','2') charset utf8)\\n\" +\n                \"               returns int(10)\\n\" +\n                \"               DETERMINISTIC \\n\" +\n                \"     BEGIN\\n\" +\n                \"              return 0;\\n\" +\n                \"     END \";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"CREATE FUNCTION `test1`.`proc1` (\\n\" +\n                \"\\t`a` enum('1', '2') CHARACTER SET utf8\\n\" +\n                \")\\n\" +\n                \"RETURNS int(10) DETERMINISTIC\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tRETURN 0;\\n\" +\n                \"END\", SQLUtils.toMySqlString(stmt));\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndex2Test.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndex2Test extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create index index1 on t1(col1) comment 'test index' comment 'some test' using btree;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE INDEX index1 ON t1 (col1) USING BTREE COMMENT 'some test';\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndexTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create index index1 on t1(col1) comment 'test index' comment 'some test' using btree;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE INDEX index1 ON t1 (col1) USING BTREE COMMENT 'some test';\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndexTest_1 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE SPATIAL INDEX g ON geom (g);\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE SPATIAL INDEX g ON geom (g);\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_10_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author chenmo.cm\n * @date 2018/12/12 10:01 AM\n */\npublic class MySqlCreateIndexTest_10_drds extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \\n\"\n                + \"dbpartition by hash(`seller_id`) \\n\" +\n                \"tbpartition by hash(`seller_id`) \\n\" +\n                \"tbpartitions 3;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3;\", output);\n    }\n\n    @Test\n    public void test_two() throws Exception {\n        String sql = \"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3 \"\n                + \"COMMENT 'CREATE GSI TEST';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3 \"\n                + \"COMMENT 'CREATE GSI TEST';\", output);\n    }\n\n    @Test\n    public void test_three() throws Exception {\n        String sql = \"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3 \"\n                + \"USING BTREE KEY_BLOCK_SIZE=20 COMMENT 'CREATE GSI TEST' ALGORITHM=DEFAULT LOCK=DEFAULT;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3 USING BTREE KEY_BLOCK_SIZE = 20 COMMENT 'CREATE GSI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT;\",\n                output);\n    }\n\n    @Test\n    public void test_one_1() throws Exception {\n        String sql = \"CREATE GLOBAL UNIQUE INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \\n\"\n                + \"dbpartition by hash(`seller_id`) \\n\" +\n                \"tbpartition by hash(`seller_id`) \\n\" +\n                \"tbpartitions 3;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3;\", output);\n    }\n\n    @Test\n    public void test_two_1() throws Exception {\n        String sql = \"CREATE GLOBAL UNIQUE INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3 \"\n                + \"COMMENT 'CREATE GSI TEST';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3 \"\n                + \"COMMENT 'CREATE GSI TEST';\", output);\n    }\n\n    @Test\n    public void test_three_1() throws Exception {\n        String sql = \"CREATE GLOBAL UNIQUE INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3 \"\n                + \"USING BTREE KEY_BLOCK_SIZE=20 COMMENT 'CREATE GSI TEST' ALGORITHM=DEFAULT LOCK=DEFAULT;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3 USING BTREE KEY_BLOCK_SIZE = 20 COMMENT 'CREATE GSI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT;\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_11_adb.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author chenmo.cm\n * @date 2018/12/12 10:01 AM\n */\npublic class MySqlCreateIndexTest_11_adb extends MysqlTest {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE FULLTEXT INDEX `g_i_seller` ON t_order (`seller_id`)\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE FULLTEXT INDEX `g_i_seller` ON t_order (`seller_id`)\", output);\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"CREATE CLUSTERED INDEX `g_i_seller` ON t_order (`seller_id`)\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE CLUSTERED INDEX `g_i_seller` ON t_order (`seller_id`)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_2_ann.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndexTest_2_ann extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE ANN INDEX facefea_index3 ON face_feature (facefea) DistanceMeasure = DotProduct ALGORITHM = IVF;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE ANN INDEX facefea_index3 ON face_feature (facefea) ALGORITHM = IVF DistanceMeasure = DotProduct;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndexTest_3 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create unique index index_1_id USING btree on index_1 (id) KEY_BLOCK_SIZE=10 comment '分表index'\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE UNIQUE INDEX index_1_id ON index_1 (id) USING BTREE KEY_BLOCK_SIZE = 10 COMMENT '分表index'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndexTest_4 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE INDEX idx_t_uid on stu_score (uid) COMMENT '' ALGORITHM DEFAULT LOCK DEFAULT\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE INDEX idx_t_uid ON stu_score (uid) COMMENT '' ALGORITHM = DEFAULT LOCK = DEFAULT\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndexTest_5 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE app_info (id bigint(20) NOT NULL, app_name varchar(255) NOT NULL ,PRIMARY KEY (id),INDEX idx USING BTREE (app_name) comment '') \";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE app_info (\\n\" +\n                \"\\tid bigint(20) NOT NULL,\\n\" +\n                \"\\tapp_name varchar(255) NOT NULL,\\n\" +\n                \"\\tPRIMARY KEY (id),\\n\" +\n                \"\\tINDEX idx USING BTREE(app_name) COMMENT ''\\n\" +\n                \")\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_6.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateIndexTest_6 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) dbpartition by hash(`seller_id`);\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) DBPARTITION BY hash(`seller_id`);\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_7_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author chenmo.cm\n * @date 2018/12/12 10:01 AM\n */\npublic class MySqlCreateIndexTest_7_drds extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                        + \"DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3;\",\n                output);\n    }\n\n    @Test\n    public void test_two() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3 \"\n                + \"COMMENT 'CREATE GSI TEST';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                        + \"DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3 \"\n                        + \"COMMENT 'CREATE GSI TEST';\",\n                output);\n    }\n\n    @Test\n    public void test_three() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3 \"\n                + \"USING BTREE KEY_BLOCK_SIZE=20 COMMENT 'CREATE GSI TEST' ALGORITHM=DEFAULT LOCK=DEFAULT;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3 USING BTREE KEY_BLOCK_SIZE = 20 COMMENT 'CREATE GSI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT;\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_8_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author chenmo.cm\n * @date 2018/12/12 2:03 PM\n */\npublic class MySqlCreateIndexTest_8_drds extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"DBPARTITION BY HASH(seller_id) TBPARTITION BY UNI_HASH(seller_id) TBPARTITIONS 12;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) DBPARTITION BY HASH(seller_id) TBPARTITION BY UNI_HASH(seller_id) TBPARTITIONS 12;\", output);\n    }\n\n    @Test\n    public void test_two() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"DBPARTITION BY HASH(SELLER_ID) TBPARTITION BY uni_hash(SELLER_ID) TBPARTITIONS 12 \"\n                + \"COMMENT 'CREATE GSI TEST';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) DBPARTITION BY HASH(SELLER_ID) TBPARTITION BY uni_hash(SELLER_ID) TBPARTITIONS 12 COMMENT 'CREATE GSI TEST';\", output);\n    }\n\n    @Test\n    public void test_three() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) \"\n                + \"DBPARTITION BY HASH(SELLER_ID) TBPARTITION BY UNI_HASH(SELLER_ID) TBPARTITIONS 12 \"\n                + \"USING BTREE KEY_BLOCK_SIZE=20 COMMENT 'CREATE GSI TEST' ALGORITHM=DEFAULT LOCK=DEFAULT;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`seller_id`) COVERING (order_snapshot) DBPARTITION BY HASH(SELLER_ID) TBPARTITION BY UNI_HASH(SELLER_ID) TBPARTITIONS 12 USING BTREE KEY_BLOCK_SIZE = 20 COMMENT 'CREATE GSI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT;\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateIndexTest_9_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author chenmo.cm\n * @date 2018/12/12 2:23 PM\n */\npublic class MySqlCreateIndexTest_9_drds extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`create_time`) COVERING (order_snapshot) \"\n                + \"dbpartition BY YYYYMM_NOLOOP (create_time) tbpartition BY YYYYMM_NOLOOP (create_time) \"\n                + \"STARTWITH 20160108 ENDWITH 20170108;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`create_time`) COVERING (order_snapshot) DBPARTITION BY YYYYMM_NOLOOP(create_time) TBPARTITION BY YYYYMM_NOLOOP(create_time) BETWEEN 20160108 AND 20170108;\", output);\n    }\n\n    @Test\n    public void test_two() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`create_time`) COVERING (order_snapshot) \"\n                + \"dbpartition BY YYYYMM_NOLOOP (create_time) tbpartition BY YYYYMM_NOLOOP (create_time) \"\n                + \"STARTWITH 20160108 ENDWITH 20170108 \" + \"COMMENT 'CREATE GSI TEST';\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`create_time`) COVERING (order_snapshot) DBPARTITION BY YYYYMM_NOLOOP(create_time) TBPARTITION BY YYYYMM_NOLOOP(create_time) BETWEEN 20160108 AND 20170108 COMMENT 'CREATE GSI TEST';\", output);\n    }\n\n    @Test\n    public void test_three() throws Exception {\n        String sql = \"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`create_time`) COVERING (order_snapshot) \"\n                + \"dbpartition BY YYYYMM_NOLOOP (create_time) tbpartition BY YYYYMM_NOLOOP (create_time) \"\n                + \"STARTWITH 20160108 ENDWITH 20170108 \"\n                + \"USING BTREE KEY_BLOCK_SIZE=20 COMMENT 'CREATE GSI TEST' ALGORITHM=DEFAULT LOCK=DEFAULT;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE GLOBAL INDEX `g_i_seller` ON t_order (`create_time`) COVERING (order_snapshot) DBPARTITION BY YYYYMM_NOLOOP(create_time) TBPARTITION BY YYYYMM_NOLOOP(create_time) BETWEEN 20160108 AND 20170108 USING BTREE KEY_BLOCK_SIZE = 20 COMMENT 'CREATE GSI TEST' ALGORITHM = DEFAULT LOCK = DEFAULT;\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateOutlineTest_0.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateOutlineTest_0 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"create outline t2 on select ? to select /*+TDDL:slave()*/ * from ms10 where c1=?;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE OUTLINE t2 ON SELECT ? TO SELECT /*+TDDL:slave()*/ *\\n\" +\n                        \"FROM ms10\\n\" +\n                        \"WHERE c1 = ?;\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create outline t2 on select ? to select /*+TDDL:slave()*/ *\\n\" +\n                        \"from ms10\\n\" +\n                        \"where c1 = ?;\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"ms10\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"ms10\", \"c1\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"ms10\", \"*\")));\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"*\")));\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"l_suppkey\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" select id into x,y,z from test;\" +\n                \" insert into test values(id,age);\" +\n                \" while x do\" +\n                \" insert into test values(id,age);\" +\n                \" end while;\" +\n                \" if x then\" +\n                \" insert into test values(id,age);\" +\n                \" insert into test values(id,age);\" +\n                \" else if y then\" +\n                \" insert into test values(id,age);\" +\n                \" while x do\" +\n                \" insert into test values(id,age);\" +\n                \" end while;\" +\n                \" else\" +\n                \" insert into test values(id,age);\" +\n                \" end if;\" +\n                \" case x\" +\n                \" when x>10 then\" +\n                \" insert into test values(id,age);\" +\n                \" insert into test values(id,age);\" +\n                \" when x>20 then\" +\n                \" insert into test values(id,age);\" +\n                \" insert into test values(id,age);\" +\n                \" else\" +\n                \" insert into test values(id,age);\" +\n                \" end case;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author zz email:455910092@qq.com\n * @version V1.0\n * @Description: begin-end within begin-end\n * @date 2015-9-14\n */\npublic class MySqlCreateProcedureTest1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" begin\" +\n                \" insert into test values(id,age);\" +\n                \" end\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest10.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest10 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE PROCEDURE p2(p INT) SET @x = p ;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest11.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest11 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE PROCEDURE curdemo()\\n\" +\n                \"BEGIN\\n\" +\n                \"  DECLARE done INT DEFAULT FALSE;\\n\" +\n                \"  DECLARE a CHAR(16);\\n\" +\n                \"  DECLARE b, c INT;\\n\" +\n                \"  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;\\n\" +\n                \"  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;\\n\" +\n                \"  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\\n\" +\n                \"\\n\" +\n                \"  OPEN cur1;\\n\" +\n                \"  OPEN cur2;\\n\" +\n                \"\\n\" +\n                \"  read_loop: LOOP\\n\" +\n                \"    FETCH cur1 INTO a, b;\\n\" +\n                \"    FETCH cur2 INTO c;\\n\" +\n                \"    IF done THEN\\n\" +\n                \"      LEAVE read_loop;\\n\" +\n                \"    END IF;\\n\" +\n                \"    IF b < c THEN\\n\" +\n                \"      INSERT INTO test.t3 VALUES (a,b);\\n\" +\n                \"    ELSE\\n\" +\n                \"      INSERT INTO test.t3 VALUES (a,c);\\n\" +\n                \"    END IF;\\n\" +\n                \"  END LOOP;\\n\" +\n                \"\\n\" +\n                \"  CLOSE cur1;\\n\" +\n                \"  CLOSE cur2;\\n\" +\n                \"END;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        // assertEquals(1, statementList.size());\n\n        System.out.println(SQLUtils.toMySqlString(stmt));\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(3, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest12.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest12 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE PROCEDURE find_parts (\\n\" +\n                \"\\tseed INT\\n\" +\n                \")\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tDROP TABLE IF EXISTS _result;\\n\" +\n                \"\\tCREATE TEMPORARY TABLE _result (\\n\" +\n                \"\\t\\tnode INT PRIMARY KEY\\n\" +\n                \"\\t);\\n\" +\n                \"\\tINSERT INTO _result\\n\" +\n                \"\\tVALUES (seed);\\n\" +\n                \"\\tDROP TABLE IF EXISTS _tmp;\\n\" +\n                \"\\tCREATE TEMPORARY TABLE _tmp LIKE _result;\\n\" +\n                \"\\tREPEAT \\n\" +\n                \"\\t\\tTRUNCATE TABLE _tmp;\\n\" +\n                \"\\t\\tINSERT INTO _tmp\\n\" +\n                \"\\t\\tSELECT child AS node\\n\" +\n                \"\\t\\tFROM _result\\n\" +\n                \"\\t\\t\\tJOIN nodes ON node = parent;\\n\" +\n                \"\\t\\tINSERT IGNORE INTO _result\\n\" +\n                \"\\t\\tSELECT node\\n\" +\n                \"\\t\\tFROM _tmp;\\n\" +\n                \"\\tUNTIL ROW_COUNT() = 0\\n\" +\n                \"\\tEND REPEAT;\\n\" +\n                \"\\tDROP TABLE _tmp;\\n\" +\n                \"\\tSELECT *\\n\" +\n                \"\\tFROM _result;\\n\" +\n                \"END;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        // assertEquals(1, statementList.size());\n\n        System.out.println(SQLUtils.toMySqlString(stmt));\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(3, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"_result\", \"*\"));\n        assertTrue(visitor.containsColumn(\"_result\", \"node\"));\n        assertTrue(visitor.containsColumn(\"nodes\", \"parent\"));\n        assertTrue(visitor.containsColumn(\"nodes\", \"child\"));\n        assertTrue(visitor.containsColumn(\"_tmp\", \"node\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest13.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest13 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create procedure foo(param1 int unsigned) contains sql begin select param1; end\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"CREATE PROCEDURE foo (\\n\" +\n                \"\\tparam1 int UNSIGNED\\n\" +\n                \")\\n\" +\n                \"CONTAINS SQL\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tSELECT param1;\\n\" +\n                \"END\", SQLUtils.toMySqlString(stmt));\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest14.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest14 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count()\\n\" +\n                \"SQL SECURITY INVOKER\\n\" +\n                \"BEGIN\\n\" +\n                \"  SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;\\n\" +\n                \"END;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"CREATE PROCEDURE account_count ()\\n\" +\n                \"SQL SECURITY INVOKER\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tSELECT 'Number of accounts:', COUNT(*)\\n\" +\n                \"\\tFROM mysql.user;\\n\" +\n                \"END;\", SQLUtils.toMySqlString(stmt));\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.containsColumn(\"mysql.user\", \"*\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest15.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateFunctionStatement;\nimport com.alibaba.druid.sql.parser.SQLParserUtils;\nimport com.alibaba.druid.sql.parser.SQLStatementParser;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest15 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"     create function `test1`.`proc1`(`a` enum('1','2') charset utf8)\\n\" +\n                \"               returns int(10)\\n\" +\n                \"               DETERMINISTIC \\n\" +\n                \"     BEGIN\\n\" +\n                \"              return 0;\\n\" +\n                \"     END \";\n\n        SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL, false);\n        SQLCreateFunctionStatement stmt = parser.parseCreateFunction();\n        assertEquals(1, stmt.getParameters().size());\n\n        assertEquals(\"CREATE FUNCTION `test1`.`proc1` (\\n\" +\n                \"\\t`a` enum('1', '2') CHARACTER SET utf8\\n\" +\n                \")\\n\" +\n                \"RETURNS int(10) DETERMINISTIC\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tRETURN 0;\\n\" +\n                \"END\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest16.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateProcedureTest16 extends MysqlTest {\n    public void test_0() {\n        String sql = \"CREATE PROCEDURE drop_tab_index (IN db varchar(50),IN tb_name varchar(512),IN idx_type varchar(50),IN idx_name varchar(512))\\n\" +\n                \"BEGIN\\n\" +\n                \"    CASE\\n\" +\n                \"        WHEN idx_type='PRIMARY' OR idx_type='primary' THEN\\n\" +\n                \"            IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA=db AND table_name=tb_name AND INDEX_NAME='PRIMARY') THEN\\n\" +\n                \"                SET @alter_sql=concat(\\\"ALTER TABLE \\\",db,\\\".\\\",tb_name,\\\" DROP PRIMARY KEY\\\");\\n\" +\n                \"                prepare stmt from @alter_sql;\\n\" +\n                \"                execute stmt;\\n\" +\n                \"                SELECT @alter_sql;\\n\" +\n                \"            END IF;\\n\" +\n                \"        WHEN idx_type='UNIQUE' OR idx_type='unique' THEN\\n\" +\n                \"            IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA=db AND table_name=tb_name AND INDEX_NAME=idx_name) THEN\\n\" +\n                \"                SET @alter_sql=concat(\\\"ALTER TABLE \\\",db,\\\".\\\",tb_name,\\\" DROP KEY \\\",idx_name);\\n\" +\n                \"                prepare stmt from @alter_sql;\\n\" +\n                \"                execute stmt;\\n\" +\n                \"                SELECT @alter_sql;\\n\" +\n                \"            END IF;\\n\" +\n                \"        WHEN idx_type='SECONDARY' OR idx_type='secondary' THEN\\n\" +\n                \"            IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA=db AND table_name=tb_name AND INDEX_NAME=idx_name) THEN\\n\" +\n                \"                SET @alter_sql=concat(\\\"ALTER TABLE \\\",db,\\\".\\\",tb_name,\\\" DROP KEY \\\",idx_name);\\n\" +\n                \"                prepare stmt from @alter_sql;\\n\" +\n                \"                execute stmt;\\n\" +\n                \"                SELECT @alter_sql;\\n\" +\n                \"            END IF;\\n\" +\n                \"    END CASE;\\n\" +\n                \"END;;\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseStatement();\n        System.out.println(SQLUtils.toMySqlString(stmt));\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n        assertEquals(3, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author zz email:455910092@qq.com\n * @version V1.0\n * @Description: procedure begin-end, loop, while use label\n * @date 2015-9-14\n */\npublic class MySqlCreateProcedureTest2 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" lable_1: while x do\" +\n                \" insert into test values(id,age);\" +\n                \" end while lable_1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" lable_1: begin\" +\n                \" insert into test values(id,age);\" +\n                \" end lable_1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" lable_1: loop\" +\n                \" insert into test values(id,age);\" +\n                \" end loop lable_1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest3.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author zz email:455910092@qq.com\n * @version V1.0\n * @Description: procedure begin-end, loop, while use label\n * @date 2015-9-14\n */\npublic class MySqlCreateProcedureTest3 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" lable_1: while x do\" +\n                \" insert into test values(id,age);\" +\n                \" leave lable_1;\" +\n                \" end while lable_1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" lable_1: begin\" +\n                \" insert into test values(id,age);\" +\n                \" leave lable_1;\" +\n                \" end lable_1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" lable_1: loop\" +\n                \" insert into test values(id,age);\" +\n                \" leave lable_1;\" +\n                \" end loop lable_1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest4.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author zz email:455910092@qq.com\n * @version V1.0\n * @Description: procedure begin-end, loop, while use label\n * @date 2015-9-14\n */\npublic class MySqlCreateProcedureTest4 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" repeat\" +\n                \" insert into test values(id,age);\" +\n                \" until x>10\" +\n                \" end repeat;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare x,y,z int;\" +\n                \" lable_1: repeat\" +\n                \" insert into test values(id,age);\" +\n                \" until x>10\" +\n                \" end repeat lable_1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest5.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Description: procedure begin-end, loop, while use label\n * author zz email:455910092@qq.com\n * date 2015-9-14\n * version V1.0\n */\npublic class MySqlCreateProcedureTest5 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare c1 cursor for select id,age from test;\" +\n                \" open c1;\" +\n                \" fetch c1 into x;\" +\n                \" close c1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n        // assertTrue(visitor.containsColumn(\"test\", \"age\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest6.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author zz email:455910092@qq.com\n * @version V1.0\n * @Description: create procedure parameter type support\n * @date 2015-9-14\n */\npublic class MySqlCreateProcedureTest6 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" insert into test values(id,age);\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create or replace procedure sp_name(in level int,in age int)\" +\n                \" begin\" +\n                \" insert into test values(id,age);\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"create or replace procedure sp_name(out level int,out age int)\" +\n                \" begin\" +\n                \" insert into test values(id,age);\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"create or replace procedure sp_name(inout level int,inout age int)\" +\n                \" begin\" +\n                \" insert into test values(id,age);\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest7.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author zz email:455910092@qq.com\n * @version V1.0\n * @Description: create procedure parameter type support\n * @date 2015-9-14\n */\npublic class MySqlCreateProcedureTest7 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE DEFINER=test@% PROCEDURE test11111()\"\n                + \"\\nBEGIN\"\n                + \"\\ndeclare v_a date default '2007-4-10';\"\n                + \"\\ndeclare v_b date default '2007-4-11';\"\n                + \"\\ndeclare v_c datetime default '2004-4-9 0:0:0';\"\n                + \"\\nEND\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE PROCEDURE test11111 ()\"\n                + \"\\nBEGIN\"\n                + \"\\n\\tDECLARE v_a date DEFAULT '2007-4-10';\"\n                + \"\\n\\tDECLARE v_b date DEFAULT '2007-4-11';\"\n                + \"\\n\\tDECLARE v_c datetime DEFAULT '2004-4-9 0:0:0';\"\n                + \"\\nEND\", output);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest8.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author zhujun [455910092@qq.com]\n * @version V1.0\n * @Description: begin-end within begin-end\n * @date 2016-4-14\n */\npublic class MySqlCreateProcedureTest8 extends MysqlTest {\n    /**\n     * DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement handler_type: CONTINUE | EXIT condition_value: SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_code\n     *\n     * @throws Exception\n     */\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure test_cursor (in param int(10),out result varchar(90))  \"\n                + \" begin\"\n                + \" declare name varchar(20);\"\n                + \" declare pass varchar(20);\"\n                + \" declare done int;\"\n                + \" declare cur_test CURSOR for select user_name,user_pass from test;\"\n                + \" declare continue handler FOR SQLSTATE '02000' SET done = 1;\"\n                + \" if param then\"\n                + \"     select concat_ws(',',user_name,user_pass) into result from test.users where id=param;\"\n                + \" else\"\n                + \"     open cur_test;\"\n                + \"     repeat\"\n                + \"     fetch cur_test into name, pass;\"\n                + \"     select concat_ws(',',result,name,pass) into result;\"\n                + \"     until done end repeat;\"\n                + \"     close cur_test;\"\n                + \" end if;\"\n                + \" end;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(SQLUtils.toSQLString(stmt, JdbcConstants.MYSQL));\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt);\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare continue handler FOR SQLSTATE '02000' SET done = 1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare continue handler FOR SQLEXCEPTION,SQLWARNING SET done = 1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare continue handler FOR 1002 SET done = 1;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare continue handler FOR SQLWARNING begin set done = 1; end\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_5() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare continue handler FOR SQLWARNING begin set done = 1; end;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateProcedureTest9.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Description: 测试异常声明\n * author zhujun [455910092@qq.com]\n * date 2016-4-17\n * version V1.0\n */\npublic class MySqlCreateProcedureTest9 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare test1 CONDITION FOR SQLSTATE '02000';\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"create or replace procedure sp_name(level int,age int)\" +\n                \" begin\" +\n                \" declare condition_name CONDITION FOR 1002;\" +\n                \" end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        // System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"create or replace procedure test_cursor (in param int(10),out result varchar(90))  \"\n                + \" begin\"\n                + \" declare name varchar(20);\"\n                + \" declare pass varchar(20);\"\n                + \" declare done int;\"\n                + \" declare cur_test CURSOR for select user_name,user_pass from test;\"\n                + \" declare condition_name CONDITION FOR 1002;\"\n                + \" declare continue handler FOR condition_name SET done = 1;\"\n                + \" if param then\"\n                + \"     select concat_ws(',',user_name,user_pass) into result from test.users where id=param;\"\n                + \" else\"\n                + \"     open cur_test;\"\n                + \"     repeat\"\n                + \"     fetch cur_test into name, pass;\"\n                + \"     select concat_ws(',',result,name,pass) into result;\"\n                + \"     until done end repeat;\"\n                + \"     close cur_test;\"\n                + \" end if;\"\n                + \" end;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        System.out.println(SQLUtils.toSQLString(statementList, JdbcConstants.MYSQL));\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateResourceGroupTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateResourceGroupTest\n        extends MysqlTest {\n    @Test\n    public void test_create() throws Exception {\n        String sql = \"CREATE RESOURCE GROUP sql_thread TYPE = USER VCPU = 1,3 THREAD_PRIORITY = -20\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE RESOURCE GROUP sql_thread THREAD_PRIORITY = -20 VCPU = 1,3 TYPE = USER\", output);\n    }\n\n    @Test\n    public void test_create2() throws Exception {\n        String sql = \"CREATE RESOURCE GROUP sql_thread TYPE = USER VCPU = 1,3 THREAD_PRIORITY = -20 disable\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE RESOURCE GROUP sql_thread THREAD_PRIORITY = -20 VCPU = 1,3 TYPE = USER DISABLE\", output);\n    }\n\n    @Test\n    public void test_create3() throws Exception {\n        String sql = \"CREATE RESOURCE GROUP group_name\\n\" +\n                \"    QUERY_EXECUTION_TYPE = USER\" +\n                \" ACU = 3 \" +\n                \" ENABLE\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE RESOURCE GROUP group_name QUERY_EXECUTION_TYPE = USER ACU = 3 ENABLE\", output);\n    }\n\n    @Test\n    public void test_create4() throws Exception {\n        String sql = \"CREATE RESOURCE GROUP group_name\\n\" +\n                \" ENABLE\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE RESOURCE GROUP group_name ENABLE\", output);\n    }\n\n    @Test\n    public void test_alter() throws Exception {\n        String sql = \"ALTER RESOURCE GROUP sql_thread TYPE = USER VCPU = 1,3 THREAD_PRIORITY = -20\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER RESOURCE GROUP sql_thread THREAD_PRIORITY = -20 VCPU = 1,3 TYPE = USER\", output);\n    }\n\n    @Test\n    public void test_alter2() throws Exception {\n        String sql = \"ALTER RESOURCE GROUP group_name\\n\" +\n                \"    QUERY_EXECUTION_TYPE = USER\" +\n                \" ACU = 3 \" +\n                \" ENABLE\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER RESOURCE GROUP group_name QUERY_EXECUTION_TYPE = USER ACU = 3 ENABLE\", output);\n    }\n\n    @Test\n    public void test_alter4() throws Exception {\n        String sql = \"ALTER RESOURCE GROUP group_name\\n\" +\n                \" ENABLE\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER RESOURCE GROUP group_name ENABLE\", output);\n    }\n\n    @Test\n    public void test_drop() throws Exception {\n        String sql = \"DROP RESOURCE GROUP sql_thread;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP RESOURCE GROUP sql_thread;\", output);\n    }\n\n    @Test\n    public void test_list() throws Exception {\n        String sql = \"LIST RESOURCE GROUP;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"LIST RESOURCE GROUP;\", output);\n    }\n\n    @Test\n    public void test_list2() throws Exception {\n        String sql = \"LIST RESOURCE GROUP\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"LIST RESOURCE GROUP\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateResourceGroupTest_hive.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateResourceGroupTest_hive\n        extends MysqlTest {\n    @Test\n    public void test_create() throws Exception {\n        String sql = \"CREATE RESOURCE GROUP sql_thread TYPE = USER VCPU = 1,3 THREAD_PRIORITY = -20\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE RESOURCE GROUP sql_thread THREAD_PRIORITY = -20 VCPU = 1,3 TYPE = USER\", output);\n    }\n\n    @Test\n    public void test_alter() throws Exception {\n        String sql = \"ALTER RESOURCE GROUP sql_thread TYPE = USER VCPU = 1,3 THREAD_PRIORITY = -20\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"ALTER RESOURCE GROUP sql_thread THREAD_PRIORITY = -20 VCPU = 1,3 TYPE = USER\", output);\n    }\n\n    @Test\n    public void test_drop() throws Exception {\n        String sql = \"DROP RESOURCE GROUP sql_thread;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.HIVE);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"DROP RESOURCE GROUP sql_thread;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateSequenceTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateSequenceTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE SEQUENCE seq1;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE SEQUENCE seq1;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateSequenceTest1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateSequenceTest1 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE SEQUENCE customers_seq\" +\n                        \" START WITH     1000\" +\n                        \" INCREMENT BY   1\" +\n                        \" NOCACHE\" +\n                        \" NOCYCLE;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE SEQUENCE customers_seq START WITH 1000 INCREMENT BY 1 NOCYCLE NOCACHE;\", stmt.toString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n\n    public void test_1() throws Exception {\n        String sql = //\n                \"CREATE SIMPLE SEQUENCE customers_seq\" +\n                        \" WITH CACHE;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE SIMPLE SEQUENCE customers_seq CACHE;\", stmt.toString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateSequenceTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.OracleTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateSequenceTest2 extends OracleTest {\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE GROUP SEQUENCE seq1;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE GROUP SEQUENCE seq1;\", stmt.toString());\n        assertEquals(\"create group sequence seq1;\", stmt.toLowerCaseString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n\n    public void test_1() throws Exception {\n        String sql = //\n                \"CREATE SIMPLE SEQUENCE seq1;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE SIMPLE SEQUENCE seq1;\", stmt.toString());\n        assertEquals(\"create simple sequence seq1;\", stmt.toLowerCaseString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateSequenceTest3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateSequenceTest3 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = //\n                \"CREATE GROUP SEQUENCE seq1 START WITH 123 UNIT COUNT 1 INDEX 0\";\n        System.out.println(sql);\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n        System.out.println(stmt.toString());\n        stmt = SQLUtils.parseStatements(stmt.toString(), DbType.mysql).get(0);\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE GROUP SEQUENCE seq1 START WITH 123 UNIT COUNT 1 INDEX 0\", stmt.toString());\n        assertEquals(\"create group sequence seq1 start with 123 unit count 1 index 0\", stmt.toLowerCaseString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = //\n                \"CREATE SIMPLE WITH CACHE SEQUENCE seq1 START WITH 123\";\n        System.out.println(sql);\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n        System.out.println(stmt.toString());\n        stmt = SQLUtils.parseStatements(stmt.toString(), DbType.mysql).get(0);\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE SIMPLE WITH CACHE SEQUENCE seq1 START WITH 123\", stmt.toString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = //\n                \"RENAME SEQUENCE seq3 to seq4\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n        System.out.println(stmt.toString());\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"RENAME SEQUENCE seq3 TO seq4\", stmt.toString());\n        assertEquals(\"rename sequence seq3 to seq4\", stmt.toLowerCaseString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = //\n                \"CREATE GROUP SEQUENCE seq1 START WITH 123 unit count 10 index 1 step 10\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE GROUP SEQUENCE seq1 START WITH 123 UNIT COUNT 10 INDEX 1 STEP 10\", stmt.toString());\n    }\n\n    @Test\n    public void test_4() throws Exception {\n        String sql = //\n                \"CREATE TIME SEQUENCE seq1\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.mysql);\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"relationships : \" + visitor.getRelationships());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n\n        // assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"cdc.en_complaint_ipr_stat_fdt0\")));\n\n        assertEquals(0, visitor.getColumns().size());\n\n        assertEquals(\"CREATE TIME SEQUENCE seq1\", stmt.toString());\n        assertEquals(\"create time sequence seq1\", stmt.toLowerCaseString());\n\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"*\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"YEAR\")));\n        // assertTrue(visitor.getColumns().contains(new TableStat.Column(\"pivot_table\", \"order_mode\")));\n    }\n\n    public static void main(String[] args) {\n        System.out.println(buildTableNameForXDriver(\"a.b\"));\n    }\n\n    private static String buildTableNameForXDriver(String t) {\n        try {\n            if (t.contains(\"\\\\.\")) {\n                final String[] split = t.split(\"\\\\.\");\n                return new String(\"`\" + split[0] + \"`.`\" + t + \"`\");\n            } else {\n                return new String(\"`\" + t + \"`\");\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateServerTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateServerTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"-- Create server\\n\" +\n                \"-- http://dev.mysql.com/doc/refman/5.6/en/create-server.html\\n\" +\n                \"CREATE SERVER s\\n\" +\n                \"FOREIGN DATA WRAPPER mysql\\n\" +\n                \"OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test');\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE SERVER s FOREIGN DATA WRAPPER mysql OPTIONS(HOST '192.168.1.106', DATABASE 'test', USER 'Remote');\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTableSpaceTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableSpaceTest extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create tablespace tblsp1 add datafile 'tblsp_work1' use logfile group lg_1 initial_size = 4G engine MYISAM;\";\n\n        List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, JdbcConstants.MYSQL);\n\n        SQLStatement stmt = stmtList.get(0);\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLESPACE tblsp1 ADD DATAFILE 'tblsp_work1' FILE_BLOCK_SIZE = lg_1 INITIAL_SIZE = 4G ENGINE MYISAM;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTableUnitTest.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.statement.SQLAssignItem;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableUnitTest\n * @description\n * @Author zzy\n * @Date 2019-05-31 17:39\n */\npublic class MySqlCreateTableUnitTest extends MysqlTest {\n    public void test_0_table_options() throws Exception {\n        String sql = \"auto_increment 1\\n\" +\n                \"avg_row_length 1\\n\" +\n                \"default character set utf8\\n\" +\n                \"checksum 0\\n\" +\n                \"default collate utf8_unicode_ci\\n\" +\n                \"comment 'hehe'\\n\" +\n                \"compression 'LZ4'\\n\" +\n                \"connection 'conn'\\n\" +\n                \"index directory 'path'\\n\" +\n                \"delay_key_write 1\\n\" +\n                \"encryption 'N'\\n\" +\n                \"engine innodb\\n\" +\n                \"insert_method no\\n\" +\n                \"key_block_size 32\\n\" +\n                \"max_rows 999\\n\" +\n                \"min_rows 1\\n\" +\n                \"pack_keys default\\n\" +\n                \"password 'psw'\\n\" +\n                \"row_format dynamic\\n\" +\n                \"stats_auto_recalc default\\n\" +\n                \"stats_persistent default\\n\" +\n                \"stats_sample_pages 10\\n\" +\n                \"tablespace `tbs_name` storage memory\\n\" +\n                \"union (tb1,tb2,tb3)\\n\" +\n                \"auto_increment 1\";\n        MySqlExprParser parser = new MySqlExprParser(sql);\n\n        List<SQLAssignItem> list = new ArrayList<SQLAssignItem>();\n        assertTrue(parser.parseTableOptions(list, null));\n\n        StringBuilder strBuilder = new StringBuilder();\n        MySqlOutputVisitor visitor = new MySqlOutputVisitor(strBuilder);\n        for (SQLAssignItem item : list) {\n            visitor.visit(item);\n            visitor.println();\n        }\n        System.out.println(strBuilder.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_like_test.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLExprTableSource;\nimport com.alibaba.druid.sql.ast.statement.SQLTableLike;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTable_like_test extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE like_test (LIKE t1)\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        SQLExprTableSource like = stmt.getLike();\n        assertTrue(stmt.getTableElementList().size() == 1);\n        assertTrue(like == null);\n        assertTrue(stmt.getTableElementList().get(0) instanceof SQLTableLike);\n        assertEquals(\"CREATE TABLE like_test (\\n\" +\n                \"\\tLIKE t1\\n\" +\n                \")\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE like_test (`LIKE` t1)\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertTrue(stmt.getLike() == null);\n\n        assertEquals(\"CREATE TABLE like_test (\\n\" +\n                \"\\t`LIKE` t1\\n\" +\n                \")\", stmt.toString());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"CREATE TABLE like_test LIKE t1\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertTrue(stmt.getLike() != null);\n\n        assertEquals(\"CREATE TABLE like_test LIKE t1\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_refactor_test.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTable_refactor_test\n * @description 只测试parser语法解析能力，SQL语句不具备合理性\n * @Author zzy\n * @Date 2019-07-02 15:18\n */\npublic class MySqlCreateTable_refactor_test extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table test001\\n\" +\n                \"(\" +\n                \"a varchar(10),\" +\n                \"b varchar(10),\" +\n                \"index c using btree (a(4) desc) comment 'hehe' key_block_size 4,\" +\n                \"fulltext d (b) with parser ngram,\" +\n                \"constraint symb primary key (a),\" +\n                \"constraint symb unique key e (b),\" +\n                \"constraint symb foreign key (b) references tb (a)\" +\n                \")\" +\n                \"auto_increment 1\\n\" +\n                \"avg_row_length 1\\n\" +\n                \"default character set utf8\\n\" +\n                \"checksum 0\\n\" +\n                \"default collate utf8_unicode_ci\\n\" +\n                \"comment 'hehe'\\n\" +\n                \"compression 'LZ4'\\n\" +\n                \"connection 'conn'\\n\" +\n                \"index directory 'path'\\n\" +\n                \"delay_key_write 1\\n\" +\n                \"encryption 'N'\\n\" +\n                \"engine innodb\\n\" +\n                \"insert_method no\\n\" +\n                \"key_block_size 32\\n\" +\n                \"max_rows 999\\n\" +\n                \"min_rows 1\\n\" +\n                \"pack_keys default\\n\" +\n                \"password 'psw'\\n\" +\n                \"row_format dynamic\\n\" +\n                \"stats_auto_recalc default\\n\" +\n                \"stats_persistent default\\n\" +\n                \"stats_sample_pages 10\\n\" +\n                \"tablespace `tbs_name` storage memory\\n\" +\n                \"union (tb1,tb2,tb3)\\n\" +\n                \"auto_increment 1,\\n\" +\n                \"dbpartition by hash(a) tbpartition by hash(b) tbpartitions 4 partition by hash(b)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE test001 (\\n\" +\n                        \"\\ta varchar(10),\\n\" +\n                        \"\\tb varchar(10),\\n\" +\n                        \"\\tINDEX c USING btree(a(4) DESC) KEY_BLOCK_SIZE = 4 COMMENT 'hehe',\\n\" +\n                        \"\\tFULLTEXT INDEX d(b) WITH PARSER ngram,\\n\" +\n                        \"\\tPRIMARY KEY (a),\\n\" +\n                        \"\\tUNIQUE KEY e (b),\\n\" +\n                        \"\\tCONSTRAINT symb FOREIGN KEY (b) REFERENCES tb (a)\\n\" +\n                        \") AUTO_INCREMENT = 1 AVG_ROW_LENGTH = 1 CHARACTER SET = utf8 CHECKSUM = 0 COLLATE = utf8_unicode_ci COMPRESSION = 'LZ4' CONNECTION = 'conn' INDEX DIRECTORY = 'path' DELAY_KEY_WRITE = 1 ENCRYPTION = 'N' ENGINE = innodb INSERT_METHOD = no KEY_BLOCK_SIZE = 32 MAX_ROWS = 999 MIN_ROWS = 1 PACK_KEYS = DEFAULT PASSWORD = 'psw' ROW_FORMAT = dynamic STATS_AUTO_RECALC = DEFAULT STATS_PERSISTENT = DEFAULT STATS_SAMPLE_PAGES = 10 TABLESPACE `tbs_name` STORAGE memory UNION = (tb1, tb2, tb3) AUTO_INCREMENT = 1 COMMENT 'hehe'\\n\" +\n                        \"PARTITION BY HASH (b)\\n\" +\n                        \"DBPARTITION BY hash(a)\\n\" +\n                        \"TBPARTITION BY hash(b) TBPARTITIONS 4\",\n                SQLUtils.toMySqlString(statementList.get(0)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_showColumns_repository_test.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTable_showColumns_repository_test extends MysqlTest {\n    private SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n\n    public void test_0() throws Exception {\n        repository.console(\"use sc00;\");\n\n        String sql = \"CREATE TABLE `test1` (\\n\" +\n                \"  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"  `c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"  `c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"  `c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"  `c_int` int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"  `c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"  `c_decimal` decimal(10,3) DEFAULT NULL COMMENT 'decimal',\\n\" +\n                \"  `c_date` date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"  `c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"  `c_timestamp` timestamp NULL DEFAULT NULL COMMENT 'timestamp'  ON UPDATE CURRENT_TIMESTAMP ,\\n\" +\n                \"  `c_time` time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"  `c_char` char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"  `c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"  `c_blob` blob COMMENT 'blob',\\n\" +\n                \"  `c_text` text COMMENT 'text',\\n\" +\n                \"  `c_mediumtext` mediumtext COMMENT 'mediumtext',\\n\" +\n                \"  `c_longblob` longblob COMMENT 'longblob',\\n\" +\n                \"  PRIMARY KEY (`id`,`c_tinyint`),\\n\" +\n                \"  UNIQUE KEY `uk_a` (`c_varchar`,`c_mediumint`),\\n\" +\n                \"  KEY `k_c` (`c_tinyint`,`c_int`),\\n\" +\n                \"  KEY `k_d` (`c_char`,`c_bigint`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=1769503 DEFAULT CHARSET=utf8mb4 COMMENT='10000000'\";\n\n        repository.console(sql);\n\n        MySqlCreateTableStatement createTableStmt = (MySqlCreateTableStatement) repository.findTable(\"test1\").getStatement();\n        assertEquals(21, createTableStmt.getTableElementList().size());\n\n        //StringBuilder buf = new StringBuilder();\n        //createTableStmt.showCoumns(buf);\n\n        assertEquals(\"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type          | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| id           | bigint(20)    | NO   | PRI | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)    | YES  | PRI | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)   | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9)  | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)       | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)    | YES  |     | NULL                |                             |\\n\" +\n                \"| c_decimal    | decimal(10,3) | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date          | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime      | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp     | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)      | YES  | MUL | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)   | YES  | MUL | hello               |                             |\\n\" +\n                \"| c_blob       | blob          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext    | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob      | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\", repository.console(\"show columns from test1\"));\n\n        repository.console(\"alter table test1 drop column c_decimal;\");\n        assertEquals(20, createTableStmt.getTableElementList().size());\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| id           | bigint(20)   | NO   | PRI | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  | PRI | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)     | YES  | MUL | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  | MUL | hello               |                             |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\", repository.console(\"show columns from test1\"));\n\n        repository.console(\"alter table test1 add column c_decimal decimal(10,3) DEFAULT NULL COMMENT 'decimal';\");\n        assertEquals(21, createTableStmt.getTableElementList().size());\n\n        assertEquals(\"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type          | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| id           | bigint(20)    | NO   | PRI | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)    | YES  | PRI | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)   | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9)  | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)       | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)    | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date          | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime      | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp     | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)      | YES  | MUL | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)   | YES  | MUL | hello               |                             |\\n\" +\n                \"| c_blob       | blob          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext    | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob      | YES  |     | NULL                |                             |\\n\" +\n                \"| c_decimal    | decimal(10,3) | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\", repository.console(\"show columns from test1\"));\n\n        repository.console(\"ALTER TABLE test1 CHANGE COLUMN c_decimal c_decimal_1 INT(11) NOT NULL DEFAULT NULL FIRST id;\");\n        assertEquals(21, createTableStmt.getTableElementList().size());\n        //String sql = \"ALTER TABLE `test`.`tb1` CHANGE COLUMN `fid` `fid` INT(11) NOT NULL DEFAULT NULL, ADD PRIMARY KEY (`fid`) ;\";\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                \"| id           | bigint(20)   | NO   | PRI | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  | PRI | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)     | YES  | MUL | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  | MUL | hello               |                             |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\", repository.console(\"show columns from test1\"));\n\n        repository.console(\"ALTER TABLE test1 DROP PRIMARY KEY;\");\n        assertEquals(20, createTableStmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tUNIQUE KEY uk_a (c_varchar, c_mediumint),\\n\" +\n                        \"\\tKEY k_c (c_tinyint, c_int),\\n\" +\n                        \"\\tKEY k_d (c_char, c_bigint)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\")\n        );\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                \"| id           | bigint(20)   | NO   |     | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  | MUL | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)     | YES  | MUL | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  | MUL | hello               |                             |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\", repository.console(\"show columns from test1\"));\n\n        repository.console(\"ALTER TABLE test1 DROP INDEX k_d;\");\n        assertEquals(19, createTableStmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tUNIQUE KEY uk_a (c_varchar, c_mediumint),\\n\" +\n                        \"\\tKEY k_c (c_tinyint, c_int)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\")\n        );\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                \"| id           | bigint(20)   | NO   |     | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  | MUL | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)     | YES  |     | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  | MUL | hello               |                             |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\", repository.console(\"show columns from test1\"));\n\n        repository.console(\"ALTER TABLE test1 DROP INDEX uk_a;\");\n        assertEquals(18, createTableStmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                \"\\tc_text text COMMENT 'text',\\n\" +\n                \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                \"\\tKEY k_c (c_tinyint, c_int)\\n\" +\n                \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\")\n        );\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                \"| id           | bigint(20)   | NO   |     | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  | MUL | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)     | YES  |     | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  |     | hello               |                             |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\", repository.console(\"show columns from test1\"));\n\n        repository.console(\"CREATE TABLE test2 like test1\");\n\n        assertEquals(\"CREATE TABLE test2 (\\n\" +\n                \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                \"\\tc_text text COMMENT 'text',\\n\" +\n                \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                \"\\tKEY k_c (c_tinyint, c_int)\\n\" +\n                \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\", repository.console(\"show create table test2\"));\n\n        repository.console(\"CREATE TABLE test3 as select * from test2\");\n        assertEquals(\"CREATE TABLE test3 (\\n\" +\n                \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                \"\\tid bigint(20) NOT NULL COMMENT 'id',\\n\" +\n                \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"\\tc_timestamp timestamp NULL DEFAULT NULL COMMENT 'timestamp',\\n\" +\n                \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                \"\\tc_text text COMMENT 'text',\\n\" +\n                \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                \"\\tc_longblob longblob COMMENT 'longblob'\\n\" +\n                \")\", repository.console(\"show create table test3\"));\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-------+\\n\" +\n                \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |       |\\n\" +\n                \"| id           | bigint(20)   | NO   |     | NULL                |       |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  |     | 1                   |       |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |       |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |       |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |       |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |       |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |       |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |       |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                |       |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |       |\\n\" +\n                \"| c_char       | char(10)     | YES  |     | NULL                |       |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  |     | hello               |       |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |       |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |       |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |       |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-------+\\n\", repository.console(\"show columns from test3\"));\n\n        repository.console(\"alter TABLE test3 add UNIQUE(c_tinyint)\");\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-------+\\n\" +\n                \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |       |\\n\" +\n                \"| id           | bigint(20)   | NO   |     | NULL                |       |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  | UNI | 1                   |       |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |       |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |       |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |       |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |       |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |       |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |       |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                |       |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |       |\\n\" +\n                \"| c_char       | char(10)     | YES  |     | NULL                |       |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  |     | hello               |       |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |       |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |       |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |       |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-------+\\n\", repository.console(\"show columns from test3\"));\n\n        repository.console(\"alter TABLE test3 add PRIMARY KEY(id)\");\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-------+\\n\" +\n                \"| Field        | Type         | Null | Key | Default             | Extra |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-------+\\n\" +\n                \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |       |\\n\" +\n                \"| id           | bigint(20)   | NO   | PRI | NULL                |       |\\n\" +\n                \"| c_tinyint    | tinyint(4)   | YES  | UNI | 1                   |       |\\n\" +\n                \"| c_smallint   | smallint(6)  | YES  |     | 0                   |       |\\n\" +\n                \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |       |\\n\" +\n                \"| c_int        | int(11)      | YES  |     | NULL                |       |\\n\" +\n                \"| c_bigint     | bigint(20)   | YES  |     | NULL                |       |\\n\" +\n                \"| c_date       | date         | YES  |     | 0000-00-00          |       |\\n\" +\n                \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |       |\\n\" +\n                \"| c_timestamp  | timestamp    | YES  |     | NULL                |       |\\n\" +\n                \"| c_time       | time         | YES  |     | NULL                |       |\\n\" +\n                \"| c_char       | char(10)     | YES  |     | NULL                |       |\\n\" +\n                \"| c_varchar    | varchar(10)  | YES  |     | hello               |       |\\n\" +\n                \"| c_blob       | blob         | YES  |     | NULL                |       |\\n\" +\n                \"| c_text       | text         | YES  |     | NULL                |       |\\n\" +\n                \"| c_mediumtext | mediumtext   | YES  |     | NULL                |       |\\n\" +\n                \"| c_longblob   | longblob     | YES  |     | NULL                |       |\\n\" +\n                \"+--------------+--------------+------+-----+---------------------+-------+\\n\", repository.console(\"show columns from test3\"));\n\n        repository.console(\"CREATE TABLE test4 as select a.* from test2 a\");\n        assertEquals(\"CREATE TABLE test4 (\\n\" +\n                \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                \"\\tid bigint(20) NOT NULL COMMENT 'id',\\n\" +\n                \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"\\tc_timestamp timestamp NULL DEFAULT NULL COMMENT 'timestamp',\\n\" +\n                \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                \"\\tc_text text COMMENT 'text',\\n\" +\n                \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                \"\\tc_longblob longblob COMMENT 'longblob'\\n\" +\n                \")\", repository.console(\"show create table test4\"));\n\n        repository.console(\"CREATE TABLE test5 as select a.* from test2 a union all select * from test3\");\n        assertEquals(\"CREATE TABLE test5 (\\n\" +\n                \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                \"\\tid bigint(20) NOT NULL COMMENT 'id',\\n\" +\n                \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"\\tc_timestamp timestamp NULL DEFAULT NULL COMMENT 'timestamp',\\n\" +\n                \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                \"\\tc_text text COMMENT 'text',\\n\" +\n                \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                \"\\tc_longblob longblob COMMENT 'longblob'\\n\" +\n                \")\", repository.console(\"show create table test5\"));\n\n        repository.console(\"CREATE TABLE sc01.test6 as select a.id, c_tinyint, 'a' f3, 3 f4 from test2 a\");\n        assertEquals(\"CREATE TABLE test6 (\\n\" +\n                \"\\tid bigint(20) NOT NULL COMMENT 'id',\\n\" +\n                \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\tf3 char,\\n\" +\n                \"\\tf4 bigint\\n\" +\n                \")\", repository.console(\"show create table sc01.test6\"));\n\n        assertEquals(\"test1\\n\" +\n                \"test2\\n\" +\n                \"test3\\n\" +\n                \"test4\\n\" +\n                \"test5\\n\", repository.console(\"show tables\"));\n\n        assertEquals(\"test1\\n\" +\n                \"test2\\n\" +\n                \"test3\\n\" +\n                \"test4\\n\" +\n                \"test5\\n\", repository.console(\"show tables\"));\n\n        assertEquals(\"test6\\n\", repository.console(\"show tables from sc01\"));\n\n        repository.console(\"DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `sc01`.`test6`;\");\n\n        assertEquals(\"\\n\", repository.console(\"show tables from sc01\"));\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_tinyint, c_int)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\")\n        );\n\n        repository.console(\" alter table test1 change c_tinyint c_tinyint_x tinyint(4) DEFAULT '1' COMMENT 'tinyint x' first;\");\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_tinyint_x tinyint(4) DEFAULT '1' COMMENT 'tinyint x',\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_tinyint_x, c_int)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\" alter table test1 drop c_tinyint_x\");\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\" alter table test1 add index name_idx(c_char,c_date);\");\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tINDEX name_idx(c_char, c_date)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                        \"| id           | bigint(20)   | NO   |     | NULL                | auto_increment              |\\n\" +\n                        \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                        \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_int        | int(11)      | YES  | MUL | NULL                |                             |\\n\" +\n                        \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                        \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                        \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                        \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_char       | char(10)     | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_varchar    | varchar(10)  | YES  |     | hello               |                             |\\n\" +\n                        \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\",\n                repository.console(\"show columns from test1\"));\n\n        repository.console(\" drop index name_idx on test1\");\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\"alter table test1 modify c_char char(32) after id\");\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_char char(32),\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                        \"| id           | bigint(20)   | NO   |     | NULL                | auto_increment              |\\n\" +\n                        \"| c_char       | char(32)     | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                        \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_int        | int(11)      | YES  | MUL | NULL                |                             |\\n\" +\n                        \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                        \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                        \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                        \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_varchar    | varchar(10)  | YES  |     | hello               |                             |\\n\" +\n                        \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\",\n                repository.console(\"show columns from test1\"));\n\n        repository.console(\"alter table test1 add CONSTRAINT unique name4_idx(id); \");\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                        \"| id           | bigint(20)   | NO   | UNI | NULL                | auto_increment              |\\n\" +\n                        \"| c_char       | char(32)     | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                        \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_int        | int(11)      | YES  | MUL | NULL                |                             |\\n\" +\n                        \"| c_bigint     | bigint(20)   | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                        \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                        \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                        \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_varchar    | varchar(10)  | YES  |     | hello               |                             |\\n\" +\n                        \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\",\n                repository.console(\"show columns from test1\"));\n\n        repository.console(\"alter table test1 add FULLTEXT name4_idx_c_longblob(c_longblob); \");\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_char char(32),\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tUNIQUE name4_idx (id),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\"alter table test1 add key name5_idx(c_bigint); \");\n\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_char char(32),\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tUNIQUE name4_idx (id),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob),\\n\" +\n                        \"\\tKEY name5_idx (c_bigint)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\"alter table test1 drop index name4_idx\");\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_char char(32),\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob),\\n\" +\n                        \"\\tKEY name5_idx (c_bigint)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\"alter table test1 add primary key name5_pk(c_bigint); \");\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_char char(32),\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob),\\n\" +\n                        \"\\tKEY name5_idx (c_bigint),\\n\" +\n                        \"\\tPRIMARY KEY (c_bigint)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\"alter table test1 drop primary key;\");\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_char char(32),\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob),\\n\" +\n                        \"\\tKEY name5_idx (c_bigint)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\"GRANT ALL PRIVILEGES ON *.* TO 'idbtmp_1208408_9'@'%' IDENTIFIED BY PASSWORD '*5E8A11FF574FCBC6440EB285D490AEE96B16E250' WITH GRANT OPTION\");\n\n        repository.console(\"alter table test1 add unique key name_idx_23 (c_char(10))\");\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_char char(32),\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob),\\n\" +\n                        \"\\tKEY name5_idx (c_bigint),\\n\" +\n                        \"\\tUNIQUE KEY name_idx_23 (c_char(10))\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        assertEquals(\"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| Field        | Type         | Null | Key | Default             | Extra                       |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\" +\n                        \"| c_decimal_1  | INT(11)      | NO   |     | NULL                |                             |\\n\" +\n                        \"| id           | bigint(20)   | NO   |     | NULL                | auto_increment              |\\n\" +\n                        \"| c_char       | char(32)     | YES  | UNI | NULL                |                             |\\n\" +\n                        \"| c_smallint   | smallint(6)  | YES  |     | 0                   |                             |\\n\" +\n                        \"| c_mediumint  | mediumint(9) | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_int        | int(11)      | YES  | MUL | NULL                |                             |\\n\" +\n                        \"| c_bigint     | bigint(20)   | YES  | MUL | NULL                |                             |\\n\" +\n                        \"| c_date       | date         | YES  |     | 0000-00-00          |                             |\\n\" +\n                        \"| c_datetime   | datetime     | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                        \"| c_timestamp  | timestamp    | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                        \"| c_time       | time         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_varchar    | varchar(10)  | YES  |     | hello               |                             |\\n\" +\n                        \"| c_blob       | blob         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_text       | text         | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_mediumtext | mediumtext   | YES  |     | NULL                |                             |\\n\" +\n                        \"| c_longblob   | longblob     | YES  |     | NULL                |                             |\\n\" +\n                        \"+--------------+--------------+------+-----+---------------------+-----------------------------+\\n\",\n                repository.console(\"show columns from test1\"));\n\n        repository.console(\"alter table test1 drop c_char;\");\n        assertEquals(\"CREATE TABLE test1 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob),\\n\" +\n                        \"\\tKEY name5_idx (c_bigint)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1\"));\n\n        repository.console(\"rename table test1 to test1_xx\");\n\n        assertEquals(\"ERROR 1146 (42S02): Table 'test1' doesn't exist\\n\",\n                repository.console(\"show create table test1\"));\n\n        assertEquals(\"ERROR 1146 (42S02): Table 'test1' doesn't exist\\n\",\n                repository.console(\"show columns from test1\"));\n\n        assertEquals(\"CREATE TABLE test1_xx (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob',\\n\" +\n                        \"\\tKEY k_c (c_int),\\n\" +\n                        \"\\tFULLTEXT INDEX name4_idx_c_longblob(c_longblob),\\n\" +\n                        \"\\tKEY name5_idx (c_bigint)\\n\" +\n                        \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 COMMENT '10000000'\",\n                repository.console(\"show create table test1_xx\"));\n\n        assertEquals(\"CREATE TABLE test5 (\\n\" +\n                        \"\\tc_decimal_1 INT(11) NOT NULL DEFAULT NULL,\\n\" +\n                        \"\\tid bigint(20) NOT NULL COMMENT 'id',\\n\" +\n                        \"\\tc_tinyint tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                        \"\\tc_smallint smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                        \"\\tc_mediumint mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                        \"\\tc_int int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                        \"\\tc_bigint bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                        \"\\tc_date date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                        \"\\tc_datetime datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                        \"\\tc_timestamp timestamp NULL DEFAULT NULL COMMENT 'timestamp',\\n\" +\n                        \"\\tc_time time DEFAULT NULL COMMENT 'time',\\n\" +\n                        \"\\tc_char char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                        \"\\tc_varchar varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                        \"\\tc_blob blob COMMENT 'blob',\\n\" +\n                        \"\\tc_text text COMMENT 'text',\\n\" +\n                        \"\\tc_mediumtext mediumtext COMMENT 'mediumtext',\\n\" +\n                        \"\\tc_longblob longblob COMMENT 'longblob'\\n\" +\n                        \")\",\n                repository.console(\"show create table test5\"));\n\n        repository.console(\"create table test5(fid bigint)\");\n        assertEquals(\"CREATE TABLE test5 (\\n\" +\n                        \"\\tfid bigint\\n\" +\n                        \")\",\n                repository.console(\"show create table test5\"));\n\n        repository.console(\"CREATE TABLE tddl5_00.ljh_test1(be_id VARCHAR(20) NOT NULL DEFAULT ''  COMMENT '企业标识')ENGINE = InnoDB, CHARACTER SET = utf8, COMMENT = '应用层-汇总销售及销售毛利表'\");\n\n        assertEquals(\"+-------+-------------+------+-----+---------+-------+\\n\" +\n                        \"| Field | Type        | Null | Key | Default | Extra |\\n\" +\n                        \"+-------+-------------+------+-----+---------+-------+\\n\" +\n                        \"| be_id | VARCHAR(20) | NO   |     | ''      |       |\\n\" +\n                        \"+-------+-------------+------+-----+---------+-------+\\n\",\n                repository.console(\"show columns from tddl5_00.ljh_test1\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_showColumns_test.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTable_showColumns_test extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `test1` (\\n\" +\n                \"  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"  `c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"  `c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"  `c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"  `c_int` int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"  `c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"  `c_decimal` decimal(10,3) DEFAULT NULL COMMENT 'decimal',\\n\" +\n                \"  `c_date` date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"  `c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"  `c_timestamp` timestamp NULL DEFAULT NULL COMMENT 'timestamp'  ON UPDATE CURRENT_TIMESTAMP ,\\n\" +\n                \"  `c_time` time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"  `c_char` char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"  `c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"  `c_blob` blob COMMENT 'blob',\\n\" +\n                \"  `c_text` text COMMENT 'text',\\n\" +\n                \"  `c_mediumtext` mediumtext COMMENT 'mediumtext',\\n\" +\n                \"  `c_longblob` longblob COMMENT 'longblob',\\n\" +\n                \"  PRIMARY KEY (`id`,`c_tinyint`),\\n\" +\n                \"  UNIQUE KEY `uk_a` (`c_varchar`,`c_mediumint`),\\n\" +\n                \"  KEY `k_c` (`c_tinyint`,`c_int`),\\n\" +\n                \"  KEY `k_d` (`c_char`,`c_bigint`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=1769503 DEFAULT CHARSET=utf8mb4 COMMENT='10000000'\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        StringBuilder buf = new StringBuilder();\n        stmt.showColumns(buf);\n\n        assertEquals(\"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| Field        | Type          | Null | Key | Default             | Extra                       |\\n\" +\n                \"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\" +\n                \"| id           | bigint(20)    | NO   | PRI | NULL                | auto_increment              |\\n\" +\n                \"| c_tinyint    | tinyint(4)    | YES  | PRI | 1                   |                             |\\n\" +\n                \"| c_smallint   | smallint(6)   | YES  |     | 0                   |                             |\\n\" +\n                \"| c_mediumint  | mediumint(9)  | YES  |     | NULL                |                             |\\n\" +\n                \"| c_int        | int(11)       | YES  |     | NULL                |                             |\\n\" +\n                \"| c_bigint     | bigint(20)    | YES  |     | NULL                |                             |\\n\" +\n                \"| c_decimal    | decimal(10,3) | YES  |     | NULL                |                             |\\n\" +\n                \"| c_date       | date          | YES  |     | 0000-00-00          |                             |\\n\" +\n                \"| c_datetime   | datetime      | YES  |     | 0000-00-00 00:00:00 |                             |\\n\" +\n                \"| c_timestamp  | timestamp     | YES  |     | NULL                | on update CURRENT_TIMESTAMP |\\n\" +\n                \"| c_time       | time          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_char       | char(10)      | YES  | MUL | NULL                |                             |\\n\" +\n                \"| c_varchar    | varchar(10)   | YES  | MUL | hello               |                             |\\n\" +\n                \"| c_blob       | blob          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_text       | text          | YES  |     | NULL                |                             |\\n\" +\n                \"| c_mediumtext | mediumtext    | YES  |     | NULL                |                             |\\n\" +\n                \"| c_longblob   | longblob      | YES  |     | NULL                |                             |\\n\" +\n                \"+--------------+---------------+------+-----+---------------------+-----------------------------+\\n\", buf.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_showColumns_test_2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.repository.SchemaObject;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTable_showColumns_test_2 extends MysqlTest {\n    public void test_0() throws Exception {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n\n        String sql = \"create table yushitai_test.card_record ( id bigint auto_increment) auto_increment=256 \"\n                + \"; alter table yushitai_test.card_record add column customization_id bigint unsigned NOT NULL COMMENT 'TEST' ;\"\n                + \"; alter table yushitai_test.card_record add column customization_id bigint unsigned NOT NULL COMMENT 'TEST' ;\";\n        repository.console(sql);\n\n        repository.setDefaultSchema(\"yushitai_test\");\n        SchemaObject table = repository.findTable(\"card_record\");\n        assertEquals(\"CREATE TABLE card_record (\\n\" +\n                \"\\tid bigint AUTO_INCREMENT,\\n\" +\n                \"\\tcustomization_id bigint UNSIGNED NOT NULL COMMENT 'TEST'\\n\" +\n                \") AUTO_INCREMENT = 256;\", table.getStatement().toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_showColumns_test_3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.repository.SchemaObject;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTable_showColumns_test_3 extends MysqlTest {\n    public void test_0() throws Exception {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n\n        String sql = \"create table yushitai_test.card_record ( id bigint auto_increment) auto_increment=256 \"\n                + \"alter table yushitai_test.card_record add index index_name(name) ;\"\n                + \"alter table yushitai_test.card_record add index index_name(name) ;\"\n                + \"alter table yushitai_test.card_record add Constraint pk_id PRIMARY KEY (id);\"\n                + \"alter table yushitai_test.card_record add Constraint pk_id PRIMARY KEY (id);\";\n        repository.console(sql);\n\n        repository.setDefaultSchema(\"yushitai_test\");\n        SchemaObject table = repository.findTable(\"card_record\");\n        assertEquals(\"CREATE TABLE card_record (\\n\" +\n                \"\\tid bigint AUTO_INCREMENT,\\n\" +\n                \"\\tINDEX index_name(name),\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \") AUTO_INCREMENT = 256\", table.getStatement().toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_showColumns_test_4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTable_showColumns_test_4 extends MysqlTest {\n    public void test_0() throws Exception {\n        SchemaRepository repository = new SchemaRepository(JdbcConstants.MYSQL);\n        String sql = \"create table tmp_eric (pk int key, ia int unique);\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE TABLE tmp_eric (\\n\" +\n                \"\\tpk int PRIMARY KEY,\\n\" +\n                \"\\tia int UNIQUE\\n\" +\n                \");\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTable_storage_type_test.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTable_storage_type_test extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `test1` (\\n\" +\n                \"  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"  `c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"  `c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"  `c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"  `c_int` int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"  `c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"  `c_decimal` decimal(10,3) DEFAULT NULL COMMENT 'decimal',\\n\" +\n                \"  `c_date` date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"  `c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"  `c_timestamp` timestamp NULL DEFAULT NULL COMMENT 'timestamp'  ON UPDATE CURRENT_TIMESTAMP ,\\n\" +\n                \"  `c_time` time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"  `c_char` char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"  `c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"  `c_blob` blob COMMENT 'blob',\\n\" +\n                \"  `c_text` text COMMENT 'text',\\n\" +\n                \"  `c_mediumtext` mediumtext COMMENT 'mediumtext',\\n\" +\n                \"  `c_longblob` longblob COMMENT 'longblob',\\n\" +\n                \"  PRIMARY KEY (`id`,`c_tinyint`),\\n\" +\n                \"  UNIQUE KEY `uk_a` (`c_varchar`,`c_mediumint`),\\n\" +\n                \"  KEY `k_c` (`c_tinyint`,`c_int`),\\n\" +\n                \"  KEY `k_d` (`c_char`,`c_bigint`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=1769503 DEFAULT CHARSET=utf8mb4 COMMENT='10000000' storage_type = 'oss'\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(\"CREATE TABLE `test1` (\\n\" +\n                \"\\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"\\t`c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"\\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"\\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"\\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"\\t`c_decimal` decimal(10, 3) DEFAULT NULL COMMENT 'decimal',\\n\" +\n                \"\\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"\\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"\\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                \"\\t`c_time` time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"\\t`c_char` char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"\\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"\\t`c_blob` blob COMMENT 'blob',\\n\" +\n                \"\\t`c_text` text COMMENT 'text',\\n\" +\n                \"\\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\\n\" +\n                \"\\t`c_longblob` longblob COMMENT 'longblob',\\n\" +\n                \"\\tPRIMARY KEY (`id`, `c_tinyint`),\\n\" +\n                \"\\tUNIQUE KEY `uk_a` (`c_varchar`, `c_mediumint`),\\n\" +\n                \"\\tKEY `k_c` (`c_tinyint`, `c_int`),\\n\" +\n                \"\\tKEY `k_d` (`c_char`, `c_bigint`)\\n\" +\n                \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 STORAGE_TYPE = 'oss' COMMENT '10000000'\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE `test1` (\\n\" +\n                \"  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"  `c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"  `c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"  `c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"  `c_int` int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"  `c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"  `c_decimal` decimal(10,3) DEFAULT NULL COMMENT 'decimal',\\n\" +\n                \"  `c_date` date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"  `c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"  `c_timestamp` timestamp NULL DEFAULT NULL COMMENT 'timestamp'  ON UPDATE CURRENT_TIMESTAMP ,\\n\" +\n                \"  `c_time` time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"  `c_char` char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"  `c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"  `c_blob` blob COMMENT 'blob',\\n\" +\n                \"  `c_text` text COMMENT 'text',\\n\" +\n                \"  `c_mediumtext` mediumtext COMMENT 'mediumtext',\\n\" +\n                \"  `c_longblob` longblob COMMENT 'longblob',\\n\" +\n                \"  PRIMARY KEY (`id`,`c_tinyint`),\\n\" +\n                \"  UNIQUE KEY `uk_a` (`c_varchar`,`c_mediumint`),\\n\" +\n                \"  KEY `k_c` (`c_tinyint`,`c_int`),\\n\" +\n                \"  KEY `k_d` (`c_char`,`c_bigint`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=1769503 DEFAULT CHARSET=utf8mb4 COMMENT='10000000' storage_policy = 'hot'\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);\n\n        assertEquals(1, statementList.size());\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(\"CREATE TABLE `test1` (\\n\" +\n                \"\\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"\\t`c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"\\t`c_smallint` smallint(6) DEFAULT 0 COMMENT 'smallint',\\n\" +\n                \"\\t`c_mediumint` mediumint(9) DEFAULT NULL COMMENT 'mediumint',\\n\" +\n                \"\\t`c_int` int(11) DEFAULT NULL COMMENT 'int',\\n\" +\n                \"\\t`c_bigint` bigint(20) DEFAULT NULL COMMENT 'bigint',\\n\" +\n                \"\\t`c_decimal` decimal(10, 3) DEFAULT NULL COMMENT 'decimal',\\n\" +\n                \"\\t`c_date` date DEFAULT '0000-00-00' COMMENT 'date',\\n\" +\n                \"\\t`c_datetime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT 'datetime',\\n\" +\n                \"\\t`c_timestamp` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'timestamp',\\n\" +\n                \"\\t`c_time` time DEFAULT NULL COMMENT 'time',\\n\" +\n                \"\\t`c_char` char(10) DEFAULT NULL COMMENT 'char',\\n\" +\n                \"\\t`c_varchar` varchar(10) DEFAULT 'hello' COMMENT 'varchar',\\n\" +\n                \"\\t`c_blob` blob COMMENT 'blob',\\n\" +\n                \"\\t`c_text` text COMMENT 'text',\\n\" +\n                \"\\t`c_mediumtext` mediumtext COMMENT 'mediumtext',\\n\" +\n                \"\\t`c_longblob` longblob COMMENT 'longblob',\\n\" +\n                \"\\tPRIMARY KEY (`id`, `c_tinyint`),\\n\" +\n                \"\\tUNIQUE KEY `uk_a` (`c_varchar`, `c_mediumint`),\\n\" +\n                \"\\tKEY `k_c` (`c_tinyint`, `c_int`),\\n\" +\n                \"\\tKEY `k_d` (`c_char`, `c_bigint`)\\n\" +\n                \") ENGINE = InnoDB AUTO_INCREMENT = 1769503 CHARSET = utf8mb4 STORAGE_POLICY = 'hot' COMMENT '10000000'\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTriggerTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTriggerTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TRIGGER ins_sum BEFORE INSERT ON account FOR EACH ROW SET @sum = @sum + NEW.amount;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TRIGGER testref BEFORE INSERT ON test1\" + \" FOR EACH ROW\" + \" BEGIN\"\n                + \" INSERT INTO test2 SET a2 = NEW.a1;\" + \" DELETE FROM test3 WHERE a3 = NEW.a1;\"\n                + \" UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;\" + \" END;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTriggerTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTriggerTest2 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create trigger employee_trigger after insert,update,delete on employee for each row call \\\"test.redisson.h2cluster.trigger.ClusterTrigger\\\"\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TRIGGER testref BEFORE INSERT ON test1\" + \" FOR EACH ROW\" + \" BEGIN\"\n                + \" INSERT INTO test2 SET a2 = NEW.a1;\" + \" DELETE FROM test3 WHERE a3 = NEW.a1;\"\n                + \" UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;\" + \" END;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTriggerTest3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTriggerTest3 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"-- Create trigger 1\\n\" +\n                \"-- delimiter //\\n\" +\n                \"create trigger trg_my1 before delete on test.t1 for each row begin insert into log_table values (\\\"delete row from test.t1\\\"); insert into t4 values (old.col1, old.col1 + 5, old.col1 + 7); end; -- //-- delimiter ;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE TRIGGER trg_my1\\n\" +\n                \"\\tBEFORE DELETE\\n\" +\n                \"\\tON test.t1\\n\" +\n                \"\\tFOR EACH ROW\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tINSERT INTO log_table\\n\" +\n                \"\\tVALUES ('delete row from test.t1');\\n\" +\n                \"\\tINSERT INTO t4\\n\" +\n                \"\\tVALUES (old.col1, old.col1 + 5, old.col1 + 7);\\n\" +\n                \"END;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTriggerTest4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTriggerTest4 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create definer = current_user() trigger trg_my2 after insert on test.t2 for each row insert into log_table values (concat(\\\"inserted into table test.t2 values: (1c, _) = (\\\", cast(NEW.col1 as char(100)), \\\", \\\", convertToSqlNode(new.`_`, char(100)), \\\")\\\"));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE TRIGGER trg_my2\\n\" +\n                \"\\tAFTER INSERT\\n\" +\n                \"\\tON test.t2\\n\" +\n                \"\\tFOR EACH ROW\\n\" +\n                \"INSERT INTO log_table\\n\" +\n                \"VALUES (concat('inserted into table test.t2 values: (1c, _) = (', CAST(NEW.col1 AS char(100)), ', ', convertToSqlNode(new.`_`, char(100)), ')'));\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateTriggerTest5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTriggerTest5 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \" CREATE DEFINER=`test_app`@`%` TRIGGER `trg_xxx_update` AFTER UPDATE ON `txxx` FOR EACH ROW begin\"\n                + \"\\ninsert into record_history_log (object, identity, action) values('txxx', new.object_id, 'UPDATE');\"\n                + \"\\ninsert into record_history_log_sim (object, identity, action) values('txxx', new.object_id, 'UPDATE');end\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> stmtList = parser.parseStatementList();\n//        print(statementList);\n\n        assertEquals(1, stmtList.size());\n\n        SQLStatement stmt = stmtList.get(0);\n\n        assertEquals(\"CREATE TRIGGER `trg_xxx_update`\\n\" +\n                \"\\tAFTER UPDATE\\n\" +\n                \"\\tON `txxx`\\n\" +\n                \"\\tFOR EACH ROW\\n\" +\n                \"BEGIN\\n\" +\n                \"\\tINSERT INTO record_history_log (object, identity, action)\\n\" +\n                \"\\tVALUES ('txxx', new.object_id, 'UPDATE');\\n\" +\n                \"\\tINSERT INTO record_history_log_sim (object, identity, action)\\n\" +\n                \"\\tVALUES ('txxx', new.object_id, 'UPDATE');\\n\" +\n                \"END\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateUserTest_1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateUserTest_1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE USER 'jeffrey'@'localhost';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'jeffrey'@'localhost';\", //\n                SQLUtils.toMySqlString(stmt));\n        assertEquals(\"create user 'jeffrey'@'localhost';\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateUserTest_2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateUserTest_2 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';\", //\n                SQLUtils.toMySqlString(stmt));\n        assertEquals(\"create user 'jeffrey'@'localhost' identified by 'mypass';\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateUserTest_3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateUserTest_3 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE USER 'jeffrey'@'localhost'\"\n                + \" IDENTIFIED BY PASSWORD '*90E462C37378CED12064BB3388827D2BA3A9B689';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY PASSWORD '*90E462C37378CED12064BB3388827D2BA3A9B689';\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create user 'jeffrey'@'localhost' identified by password '*90E462C37378CED12064BB3388827D2BA3A9B689';\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateUserTest_4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateUserTest_4 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE USER 'jeffrey'@'localhost'\"\n                + \" IDENTIFIED WITH my_auth_plugin;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'jeffrey'@'localhost' IDENTIFIED WITH my_auth_plugin;\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create user 'jeffrey'@'localhost' identified with my_auth_plugin;\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateUserTest_5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateUserTest_5 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create user 'user5301new'@'%' IDENTIFIED BY '123456'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'user5301new'@'%' IDENTIFIED BY '123456'\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create user 'user5301new'@'%' identified by '123456'\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateUserTest_6.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateUserTest_6 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';\";\n\n        MySqlCreateUserStatement stmt = (MySqlCreateUserStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';\", //\n                SQLUtils.toMySqlString(stmt));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE USER jeffrey@'localhost' IDENTIFIED BY 'password';\";\n\n        MySqlCreateUserStatement stmt = (MySqlCreateUserStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';\", //\n                SQLUtils.toMySqlString(stmt));\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"CREATE USER 'jeffrey'@localhost IDENTIFIED BY 'password';\";\n\n        MySqlCreateUserStatement stmt = (MySqlCreateUserStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';\", //\n                SQLUtils.toMySqlString(stmt));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateUserTest_7.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateUserTest_7\n * @description\n * @Author zzy\n * @Date 2019-05-22 09:43\n */\npublic class MySqlCreateUserTest_7 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE USER 'seomdbyu'@'%'\\n\" +\n                \"IDENTIFIED BY PASSWORD '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'seomdbyu'@'%' IDENTIFIED BY PASSWORD '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create user 'seomdbyu'@'%' identified by password '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE USER 'seomdbyu'@'%'\\n\" +\n                \"IDENTIFIED WITH 'mysql_native_password' AS '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'seomdbyu'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create user 'seomdbyu'@'%' identified with 'mysql_native_password' as '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"CREATE USER 'seomdbyu'@'%'\\n\" +\n                \"IDENTIFIED WITH 'mysql_native_password' BY '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE USER 'seomdbyu'@'%' IDENTIFIED WITH 'mysql_native_password' BY '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create user 'seomdbyu'@'%' identified with 'mysql_native_password' by '*E31E2E4B771597DE2FDECB4E0EC00BE9E87D39D2'\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateViewTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE OR REPLACE VIEW view_name AS\\n\" +\n                \"SELECT fname\\n\" +\n                \"FROM table_name\\n\" +\n                \"WHERE fid = ?\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"table_name\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"table_name\", \"fid\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"table_name\", \"fname\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateViewTest1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW view_audit_enroll AS \" +\n                \"SELECT a.enroll_id AS 'enrollId', case when ((SELECT audit FROM actvty_audit WHERE enroll_id = a.enroll_id AND rankjurisdiction = 1) > 0) then \\\"县站已审核\\\" else NULL end AS 'countyAudit', case when ((SELECT audit FROM actvty_audit WHERE enroll_id = a.enroll_id AND rankjurisdiction = 2) > 0) then \\\"市馆已审核\\\" else NULL end AS 'cityAudit', case when ((SELECT audit FROM actvty_audit WHERE enroll_id = a.enroll_id AND rankjurisdiction = 3) > 0) then \\\"省馆已审核\\\" else NULL end AS 'provinceAudit' FROM actvty_audit a GROUP BY a.enroll_id\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE ALGORITHM = UNDEFINED\\n\" +\n                        \"\\tDEFINER = 'root'@'localhost'\\n\" +\n                        \"\\tSQL SECURITY DEFINER\\n\" +\n                        \"\\tVIEW view_audit_enroll\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT a.enroll_id AS \\\"enrollId\\\"\\n\" +\n                        \"\\t, CASE\\n\" +\n                        \"\\t\\tWHEN ((\\n\" +\n                        \"\\t\\t\\t\\tSELECT audit\\n\" +\n                        \"\\t\\t\\t\\tFROM actvty_audit\\n\" +\n                        \"\\t\\t\\t\\tWHERE enroll_id = a.enroll_id\\n\" +\n                        \"\\t\\t\\t\\t\\tAND rankjurisdiction = 1\\n\" +\n                        \"\\t\\t\\t) > 0)\\n\" +\n                        \"\\t\\tTHEN '县站已审核'\\n\" +\n                        \"\\t\\tELSE NULL\\n\" +\n                        \"\\tEND AS \\\"countyAudit\\\"\\n\" +\n                        \"\\t, CASE\\n\" +\n                        \"\\t\\tWHEN ((\\n\" +\n                        \"\\t\\t\\t\\tSELECT audit\\n\" +\n                        \"\\t\\t\\t\\tFROM actvty_audit\\n\" +\n                        \"\\t\\t\\t\\tWHERE enroll_id = a.enroll_id\\n\" +\n                        \"\\t\\t\\t\\t\\tAND rankjurisdiction = 2\\n\" +\n                        \"\\t\\t\\t) > 0)\\n\" +\n                        \"\\t\\tTHEN '市馆已审核'\\n\" +\n                        \"\\t\\tELSE NULL\\n\" +\n                        \"\\tEND AS \\\"cityAudit\\\"\\n\" +\n                        \"\\t, CASE\\n\" +\n                        \"\\t\\tWHEN ((\\n\" +\n                        \"\\t\\t\\t\\tSELECT audit\\n\" +\n                        \"\\t\\t\\t\\tFROM actvty_audit\\n\" +\n                        \"\\t\\t\\t\\tWHERE enroll_id = a.enroll_id\\n\" +\n                        \"\\t\\t\\t\\t\\tAND rankjurisdiction = 3\\n\" +\n                        \"\\t\\t\\t) > 0)\\n\" +\n                        \"\\t\\tTHEN '省馆已审核'\\n\" +\n                        \"\\t\\tELSE NULL\\n\" +\n                        \"\\tEND AS \\\"provinceAudit\\\"\\n\" +\n                        \"FROM actvty_audit a\\n\" +\n                        \"GROUP BY a.enroll_id\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create algorithm = UNDEFINED\\n\" +\n                        \"\\tdefiner = 'root'@'localhost'\\n\" +\n                        \"\\tsql security DEFINER\\n\" +\n                        \"\\tview view_audit_enroll\\n\" +\n                        \"as\\n\" +\n                        \"select a.enroll_id as \\\"enrollId\\\"\\n\" +\n                        \"\\t, case\\n\" +\n                        \"\\t\\twhen ((\\n\" +\n                        \"\\t\\t\\t\\tselect audit\\n\" +\n                        \"\\t\\t\\t\\tfrom actvty_audit\\n\" +\n                        \"\\t\\t\\t\\twhere enroll_id = a.enroll_id\\n\" +\n                        \"\\t\\t\\t\\t\\tand rankjurisdiction = 1\\n\" +\n                        \"\\t\\t\\t) > 0)\\n\" +\n                        \"\\t\\tthen '县站已审核'\\n\" +\n                        \"\\t\\telse null\\n\" +\n                        \"\\tend as \\\"countyAudit\\\"\\n\" +\n                        \"\\t, case\\n\" +\n                        \"\\t\\twhen ((\\n\" +\n                        \"\\t\\t\\t\\tselect audit\\n\" +\n                        \"\\t\\t\\t\\tfrom actvty_audit\\n\" +\n                        \"\\t\\t\\t\\twhere enroll_id = a.enroll_id\\n\" +\n                        \"\\t\\t\\t\\t\\tand rankjurisdiction = 2\\n\" +\n                        \"\\t\\t\\t) > 0)\\n\" +\n                        \"\\t\\tthen '市馆已审核'\\n\" +\n                        \"\\t\\telse null\\n\" +\n                        \"\\tend as \\\"cityAudit\\\"\\n\" +\n                        \"\\t, case\\n\" +\n                        \"\\t\\twhen ((\\n\" +\n                        \"\\t\\t\\t\\tselect audit\\n\" +\n                        \"\\t\\t\\t\\tfrom actvty_audit\\n\" +\n                        \"\\t\\t\\t\\twhere enroll_id = a.enroll_id\\n\" +\n                        \"\\t\\t\\t\\t\\tand rankjurisdiction = 3\\n\" +\n                        \"\\t\\t\\t) > 0)\\n\" +\n                        \"\\t\\tthen '省馆已审核'\\n\" +\n                        \"\\t\\telse null\\n\" +\n                        \"\\tend as \\\"provinceAudit\\\"\\n\" +\n                        \"from actvty_audit a\\n\" +\n                        \"group by a.enroll_id\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"actvty_audit\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"actvty_audit\", \"audit\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"actvty_audit\", \"enroll_id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateViewTest2 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create view revenue0 as \\n\" +\n                \"select l_suppkey as supplier_no, sum(l_extendedprice * (1 - l_discount)) as total_revenue \\n\" +\n                \"from lineitem \\n\" +\n                \"where l_shipdate >= date '1993-01-01' and l_shipdate < date '1993-01-01' + interval '3' month \\n\" +\n                \"group by l_suppkey\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE VIEW revenue0\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT l_suppkey AS supplier_no, sum(l_extendedprice * (1 - l_discount)) AS total_revenue\\n\" +\n                        \"FROM lineitem\\n\" +\n                        \"WHERE l_shipdate >= DATE '1993-01-01'\\n\" +\n                        \"\\tAND l_shipdate < DATE '1993-01-01' + INTERVAL '3' MONTH\\n\" +\n                        \"GROUP BY l_suppkey\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create view revenue0\\n\" +\n                        \"as\\n\" +\n                        \"select l_suppkey as supplier_no, sum(l_extendedprice * (1 - l_discount)) as total_revenue\\n\" +\n                        \"from lineitem\\n\" +\n                        \"where l_shipdate >= date '1993-01-01'\\n\" +\n                        \"\\tand l_shipdate < date '1993-01-01' + interval '3' month\\n\" +\n                        \"group by l_suppkey\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(2, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lineitem\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"lineitem\", \"l_shipdate\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"lineitem\", \"l_suppkey\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateViewTest3 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create algorithm = merge view my_view2(col1, col2) as select * from t2 with check option;\\n\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE ALGORITHM = merge\\n\" +\n                        \"\\tVIEW my_view2 (\\n\" +\n                        \"\\tcol1, \\n\" +\n                        \"\\tcol2\\n\" +\n                        \")\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT *\\n\" +\n                        \"FROM t2\\n\" +\n                        \"WITH CHECK OPTION;\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create algorithm = merge\\n\" +\n                        \"\\tview my_view2 (\\n\" +\n                        \"\\tcol1, \\n\" +\n                        \"\\tcol2\\n\" +\n                        \")\\n\" +\n                        \"as\\n\" +\n                        \"select *\\n\" +\n                        \"from t2\\n\" +\n                        \"with check option;\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"*\")));\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"l_suppkey\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateViewTest4 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create or replace definer = 'ivan'@'%' view my_view3 as select count(*) from t3;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE OR REPLACE DEFINER = 'ivan'@'%'\\n\" +\n                        \"\\tVIEW my_view3\\n\" +\n                        \"AS\\n\" +\n                        \"SELECT count(*)\\n\" +\n                        \"FROM t3;\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create or replace definer = 'ivan'@'%'\\n\" +\n                        \"\\tview my_view3\\n\" +\n                        \"as\\n\" +\n                        \"select count(*)\\n\" +\n                        \"from t3;\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t3\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t3\", \"*\")));\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"l_suppkey\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create/MySqlCreateViewTest5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateViewTest5 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"create or replace definer = current_user sql security invoker view my_view4(c1, 1c, _, c1_2) \\n\" +\n            \"\\tas select * from  (t1 as tt1, t2 as tt2) inner join t1 on t1.col1 = tt1.col1;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE OR REPLACE DEFINER = current_user\\n\" +\n                \"\\tSQL SECURITY invoker\\n\" +\n                \"\\tVIEW my_view4 (\\n\" +\n                \"\\tc1, \\n\" +\n                \"\\t1c, \\n\" +\n                \"\\t_, \\n\" +\n                \"\\tc1_2\\n\" +\n                \")\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM (t1 tt1, t2 tt2)\\n\" +\n                \"\\tINNER JOIN t1 ON t1.col1 = tt1.col1;\", //\n            SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create or replace definer = current_user\\n\" +\n                \"\\tsql security invoker\\n\" +\n                \"\\tview my_view4 (\\n\" +\n                \"\\tc1, \\n\" +\n                \"\\t1c, \\n\" +\n                \"\\t_, \\n\" +\n                \"\\tc1_2\\n\" +\n                \")\\n\" +\n                \"as\\n\" +\n                \"select *\\n\" +\n                \"from (t1 tt1, t2 tt2)\\n\" +\n                \"\\tinner join t1 on t1.col1 = tt1.col1;\", //\n            SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t1\", \"col1\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t1\", \"*\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"*\")));\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"l_suppkey\")));\n    }\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"CREATE ALGORITHM=UNDEFINED \" +\n            \"DEFINER=`root`@`%` \" +\n            \"SQL SECURITY DEFINER VIEW `test_view` AS \\n\" +\n            \"select  `t1`.`US_USERID` AS `US_USERID`,  `t1`.`US_USERNAME` AS `US_USERNAME` from `test_userinfo` `t1`\";\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE ALGORITHM = UNDEFINED\\n\"\n                + \"\\tDEFINER = '`root`'@'`%`'\\n\"\n                + \"\\tSQL SECURITY DEFINER\\n\"\n                + \"\\tVIEW `test_view`\\n\"\n                + \"AS\\n\"\n                + \"SELECT `t1`.`US_USERID` AS `US_USERID`, `t1`.`US_USERNAME` AS `US_USERNAME`\\n\"\n                + \"FROM `test_userinfo` `t1`\", //\n            SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create algorithm = UNDEFINED\\n\"\n                + \"\\tdefiner = '`root`'@'`%`'\\n\"\n                + \"\\tsql security DEFINER\\n\"\n                + \"\\tview `test_view`\\n\"\n                + \"as\\n\"\n                + \"select `t1`.`US_USERID` as `US_USERID`, `t1`.`US_USERNAME` as `US_USERNAME`\\n\"\n                + \"from `test_userinfo` `t1`\", //\n            SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test_userinfo\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"test_userinfo\", \"US_USERID\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"test_userinfo\", \"US_USERNAME\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCeateTableTest34.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * Created by wenshao on 16/8/5.\n */\npublic class MySqlCeateTableTest34 {\n    @Test\n    public void test_for_parse() throws Exception {\n        String sql = \"CREATE TABLE \\\"item_extra\\\" (\\n\" +\n                \"  \\\"id\\\" int(10) unsigned NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  \\\"item_id\\\" int(10) unsigned NOT NULL DEFAULT '0' COMMENT '商品id',\\n\" +\n                \"  \\\"type\\\" tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '扩展属性类型，0：虚拟商品',\\n\" +\n                \"  \\\"attr_key\\\" varchar(50) NOT NULL COMMENT '扩展属性key',\\n\" +\n                \"  \\\"attr_value\\\" varchar(500) NOT NULL COMMENT '扩展属性value',\\n\" +\n                \"  PRIMARY KEY (\\'id\\'),\\n\" +\n                \"  KEY \\\"idx_item_type_kv\\\" (\\\"item_id\\\",\\\"type\\\",\\\"attr_key\\\",\\\"attr_value\\\"(191))\\n\" +\n                \")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"item_extra\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE \\\"item_extra\\\" (\\n\" +\n                \"\\t\\\"id\\\" int(10) UNSIGNED NOT NULL AUTO_INCREMENT,\\n\" +\n                \"\\t\\\"item_id\\\" int(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '商品id',\\n\" +\n                \"\\t\\\"type\\\" tinyint(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT '扩展属性类型，0：虚拟商品',\\n\" +\n                \"\\t\\\"attr_key\\\" varchar(50) NOT NULL COMMENT '扩展属性key',\\n\" +\n                \"\\t\\\"attr_value\\\" varchar(500) NOT NULL COMMENT '扩展属性value',\\n\" +\n                \"\\tPRIMARY KEY (\\'id\\'),\\n\" +\n                \"\\tKEY \\\"idx_item_type_kv\\\" (\\\"item_id\\\", \\\"type\\\", \\\"attr_key\\\", \\\"attr_value\\\"(191))\\n\" +\n                \")\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statement = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"mytable\", \"last_name\")));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE `ins_ebay_auth` (\"\n                + \" `auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"\n                + \" `usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"\n                + \" `status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"\n                + \" `ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"\n                + \" `ebay_name` varchar(50) COLLATE utf8_bin NOT NULL COMMENT 'eBay唯一名',\"\n                + \" `create_time` datetime NOT NULL COMMENT '授权时间', \"\n                + \" `invalid_time` datetime NOT NULL COMMENT '授权失效时间',\"\n                + \" PRIMARY KEY (`auth_id`)\"\n                + \" ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statement = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"create table t2 as select * from t1\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statement = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n    }\n\n    public void test_create_table_without_as_1() throws Exception {\n        //https://dev.mysql.com/doc/refman/8.0/en/create-table-select.html\n        String sql = \"CREATE TABLE bar (m INT) SELECT n FROM foo\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statement = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n    }\n    public void test_create_table_without_as_2() throws Exception {\n        //https://dev.mysql.com/doc/refman/8.0/en/create-table-select.html\n        String sql = \"create table t2 select * from t1 where id > 10\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statement = statementList.get(0);\n        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statement.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        System.out.println(\"coditions : \" + visitor.getConditions());\n        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest1.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest1 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  ENGINE = MEMORY;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"lookup\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest10.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest10 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table TACCOUNT (\" +\n                \"        ID varchar(36) not null,\" +\n                \"        ACCOUNT varchar(100) not null,\" +\n                \"        account_money double precision,\" +\n                \"        NAME varchar(100) not null,\" +\n                \"        TYPE integer,\" +\n                \"        primary key (ID)\" +\n                \"    )\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"TACCOUNT\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"TACCOUNT\", \"ID\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"TACCOUNT\", \"ACCOUNT\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"TACCOUNT\", \"account_money\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"TACCOUNT\", \"NAME\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"TACCOUNT\", \"TYPE\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest100.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest100 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS ttable\\n\" +\n                \"(\\n\" +\n                \"`id` BIGINT(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"`queue_id` varchar(20) NOT NULL DEFAULT '-1',\\n\" +\n                \"`status` TINYINT(4) NOT NULL DEFAULT '1',\\n\" +\n                \"`geometry` geometry not null,\\n\" +\n                \"CONSTRAINT PRIMARY KEY (`id`),\\n\" +\n                \"CONSTRAINT UNIQUE KEY `uk_queue_id` USING BTREE (`queue_id`) KEY_BLOCK_SIZE=10,\\n\" +\n                \"FULLTEXT KEY `ft_status` (`queue_id`),\\n\" +\n                \"spatial index `spatial` (`geometry`),\\n\" +\n                \"CONSTRAINT FOREIGN KEY `fk_test`(`queue_id`) REFERENCES `test`(`id`)\\n\" +\n                \") ENGINE=INNODB\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(9, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS ttable (\\n\" +\n                \"\\t`id` BIGINT(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"\\t`queue_id` varchar(20) NOT NULL DEFAULT '-1',\\n\" +\n                \"\\t`status` TINYINT(4) NOT NULL DEFAULT '1',\\n\" +\n                \"\\t`geometry` geometry NOT NULL,\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tUNIQUE KEY `uk_queue_id` USING BTREE (`queue_id`) KEY_BLOCK_SIZE = 10,\\n\" +\n                \"\\tFULLTEXT KEY `ft_status` (`queue_id`),\\n\" +\n                \"\\tSPATIAL INDEX `spatial`(`geometry`),\\n\" +\n                \"\\tCONSTRAINT FOREIGN KEY `fk_test` (`queue_id`) REFERENCES `test` (`id`)\\n\" +\n                \") ENGINE = INNODB\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest101_geometry.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest101_geometry extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE geom (g GEOMETRY NOT NULL);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(1, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE geom (\\n\" +\n                \"\\tg GEOMETRY NOT NULL\\n\" +\n                \");\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest102.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest102 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `xktv_perf_6519` (\\n\" +\n                \"  `kd` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\\n\" +\n                \"  `gmt_create` datetime NOT NULL COMMENT '创建时间',\\n\" +\n                \"  `time` datetime NOT NULL COMMENT '统计的时间',\\n\" +\n                \"  `scope` int(11) NOT NULL COMMENT '时间粒度',\\n\" +\n                \"  `knstance_id` varchar(128) DEFAULT NULL COMMENT '实例id',\\n\" +\n                \"  `kp` varchar(16) NOT NULL COMMENT 'ip',\\n\" +\n                \"  `port` int(11) NOT NULL COMMENT 'port',\\n\" +\n                \"  `db` varchar(42) NOT NULL COMMENT 'db',\\n\" +\n                \"  `hashcode` varchar(32) NOT NULL COMMENT 'hashcode',\\n\" +\n                \"  `sql_type` varchar(6) NOT NULL COMMENT 'sql_type',\\n\" +\n                \"  `logical_table` varchar(128) DEFAULT NULL COMMENT '逻辑表名',\\n\" +\n                \"  `physical_table` varchar(128) DEFAULT NULL COMMENT '物理表名',\\n\" +\n                \"  `request_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT '执行次数',\\n\" +\n                \"  `rows_examined` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rows_examined',\\n\" +\n                \"  `rows_sent` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rows_sent',\\n\" +\n                \"  `rows_affected` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rows_affected',\\n\" +\n                \"  `knnodb_pages_read` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'innodb_pages_read',\\n\" +\n                \"  `knnodb_pages_io_read` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'innodb_pages_io_read',\\n\" +\n                \"  `rt_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_count',\\n\" +\n                \"  `query_time` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'query_time',\\n\" +\n                \"  `wait_time` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'wait_time',\\n\" +\n                \"  `lock_time` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'lock_time',\\n\" +\n                \"  `rt_1ms_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_1ms_count',\\n\" +\n                \"  `rt_2ms_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_2ms_count',\\n\" +\n                \"  `rt_3ms_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_3ms_count',\\n\" +\n                \"  `rt_10ms_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_10ms_count',\\n\" +\n                \"  `rt_100ms_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_100ms_count',\\n\" +\n                \"  `rt_1s_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_1s_count',\\n\" +\n                \"  `rt_gt1s_count` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'rt_gt1s_count',\\n\" +\n                \"  `avg_90_rt` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'avg_90_rt',\\n\" +\n                \"  `avg_95_rt` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'avg_95_rt',\\n\" +\n                \"  `avg_99_rt` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'avg_99_rt',\\n\" +\n                \"  `avg_rt` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'avg_rt',\\n\" +\n                \"  `val_ext_c0` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c0',\\n\" +\n                \"  `val_ext_c1` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c1',\\n\" +\n                \"  `val_ext_c2` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c2',\\n\" +\n                \"  `val_ext_c3` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c3',\\n\" +\n                \"  `val_ext_c4` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c4',\\n\" +\n                \"  `val_ext_c5` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c5',\\n\" +\n                \"  `val_ext_c6` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c6',\\n\" +\n                \"  `val_ext_c7` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c7',\\n\" +\n                \"  `val_ext_c8` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c8',\\n\" +\n                \"  `val_ext_c9` decimal(42,20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c9',\\n\" +\n                \"  `str_ext_c0` varchar(128) DEFAULT NULL COMMENT 'str_ext_c0',\\n\" +\n                \"  `str_ext_c1` varchar(128) DEFAULT NULL COMMENT 'str_ext_c1',\\n\" +\n                \"  `str_ext_c2` varchar(128) DEFAULT NULL COMMENT 'str_ext_c2',\\n\" +\n                \"  `str_ext_c3` varchar(128) DEFAULT NULL COMMENT 'str_ext_c3',\\n\" +\n                \"  `str_ext_c4` varchar(128) DEFAULT NULL COMMENT 'str_ext_c4',\\n\" +\n                \"  `str_ext_c5` varchar(128) DEFAULT NULL COMMENT 'str_ext_c5',\\n\" +\n                \"  `str_ext_c6` varchar(128) DEFAULT NULL COMMENT 'str_ext_c6',\\n\" +\n                \"  `str_ext_c7` varchar(128) DEFAULT NULL COMMENT 'str_ext_c7',\\n\" +\n                \"  `str_ext_c8` varchar(128) DEFAULT NULL COMMENT 'str_ext_c8',\\n\" +\n                \"  `str_ext_c9` varchar(128) DEFAULT NULL COMMENT 'str_ext_c9',\\n\" +\n                \"  `str_ext_c10` varchar(128) DEFAULT NULL COMMENT 'str_ext_c10',\\n\" +\n                \"  `str_ext_c11` varchar(128) DEFAULT NULL COMMENT 'str_ext_c11',\\n\" +\n                \"  `str_ext_c12` varchar(128) DEFAULT NULL COMMENT 'str_ext_c12',\\n\" +\n                \"  `str_ext_c13` varchar(128) DEFAULT NULL COMMENT 'str_ext_c13',\\n\" +\n                \"  `str_ext_c14` varchar(128) DEFAULT NULL COMMENT 'str_ext_c14',\\n\" +\n                \"  PRIMARY KEY (`kd`) COMMENT 'index_key_ins_perf_6519',\\n\" +\n                \"  KEY `kdx_time` (`time`) COMMENT 'index_perf_time_6519',\\n\" +\n                \"  KEY `kdx_instance_time` (`kp`,`port`,`scope`,`time`) COMMENT 'index_ins_perf_inst_time_6519',\\n\" +\n                \"  KEY `kdx_instance_hash` (`kp`,`port`,`hashcode`,`scope`,`time`) COMMENT 'index_ins_perf_hash_6519',\\n\" +\n                \"  KEY `kdx_instance_all_dim` (`kp`,`port`,`db`,`logical_table`,`physical_table`,`sql_type`,`hashcode`,`scope`,`time`) COMMENT 'index_ins_perf_all_6519'\\n\" +\n                \") ENGINE=XENGINE AUTO_INCREMENT=339181584 DEFAULT CHARSET=utf8mb4 COMMENT='sql_ins_perf'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(63, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE `xktv_perf_6519` (\\n\" +\n                \"\\t`kd` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',\\n\" +\n                \"\\t`gmt_create` datetime NOT NULL COMMENT '创建时间',\\n\" +\n                \"\\t`time` datetime NOT NULL COMMENT '统计的时间',\\n\" +\n                \"\\t`scope` int(11) NOT NULL COMMENT '时间粒度',\\n\" +\n                \"\\t`knstance_id` varchar(128) DEFAULT NULL COMMENT '实例id',\\n\" +\n                \"\\t`kp` varchar(16) NOT NULL COMMENT 'ip',\\n\" +\n                \"\\t`port` int(11) NOT NULL COMMENT 'port',\\n\" +\n                \"\\t`db` varchar(42) NOT NULL COMMENT 'db',\\n\" +\n                \"\\t`hashcode` varchar(32) NOT NULL COMMENT 'hashcode',\\n\" +\n                \"\\t`sql_type` varchar(6) NOT NULL COMMENT 'sql_type',\\n\" +\n                \"\\t`logical_table` varchar(128) DEFAULT NULL COMMENT '逻辑表名',\\n\" +\n                \"\\t`physical_table` varchar(128) DEFAULT NULL COMMENT '物理表名',\\n\" +\n                \"\\t`request_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT '执行次数',\\n\" +\n                \"\\t`rows_examined` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rows_examined',\\n\" +\n                \"\\t`rows_sent` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rows_sent',\\n\" +\n                \"\\t`rows_affected` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rows_affected',\\n\" +\n                \"\\t`knnodb_pages_read` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'innodb_pages_read',\\n\" +\n                \"\\t`knnodb_pages_io_read` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'innodb_pages_io_read',\\n\" +\n                \"\\t`rt_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_count',\\n\" +\n                \"\\t`query_time` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'query_time',\\n\" +\n                \"\\t`wait_time` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'wait_time',\\n\" +\n                \"\\t`lock_time` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'lock_time',\\n\" +\n                \"\\t`rt_1ms_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_1ms_count',\\n\" +\n                \"\\t`rt_2ms_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_2ms_count',\\n\" +\n                \"\\t`rt_3ms_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_3ms_count',\\n\" +\n                \"\\t`rt_10ms_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_10ms_count',\\n\" +\n                \"\\t`rt_100ms_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_100ms_count',\\n\" +\n                \"\\t`rt_1s_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_1s_count',\\n\" +\n                \"\\t`rt_gt1s_count` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'rt_gt1s_count',\\n\" +\n                \"\\t`avg_90_rt` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'avg_90_rt',\\n\" +\n                \"\\t`avg_95_rt` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'avg_95_rt',\\n\" +\n                \"\\t`avg_99_rt` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'avg_99_rt',\\n\" +\n                \"\\t`avg_rt` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'avg_rt',\\n\" +\n                \"\\t`val_ext_c0` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c0',\\n\" +\n                \"\\t`val_ext_c1` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c1',\\n\" +\n                \"\\t`val_ext_c2` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c2',\\n\" +\n                \"\\t`val_ext_c3` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c3',\\n\" +\n                \"\\t`val_ext_c4` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c4',\\n\" +\n                \"\\t`val_ext_c5` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c5',\\n\" +\n                \"\\t`val_ext_c6` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c6',\\n\" +\n                \"\\t`val_ext_c7` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c7',\\n\" +\n                \"\\t`val_ext_c8` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c8',\\n\" +\n                \"\\t`val_ext_c9` decimal(42, 20) DEFAULT '0.00000000000000000000' COMMENT 'val_ext_c9',\\n\" +\n                \"\\t`str_ext_c0` varchar(128) DEFAULT NULL COMMENT 'str_ext_c0',\\n\" +\n                \"\\t`str_ext_c1` varchar(128) DEFAULT NULL COMMENT 'str_ext_c1',\\n\" +\n                \"\\t`str_ext_c2` varchar(128) DEFAULT NULL COMMENT 'str_ext_c2',\\n\" +\n                \"\\t`str_ext_c3` varchar(128) DEFAULT NULL COMMENT 'str_ext_c3',\\n\" +\n                \"\\t`str_ext_c4` varchar(128) DEFAULT NULL COMMENT 'str_ext_c4',\\n\" +\n                \"\\t`str_ext_c5` varchar(128) DEFAULT NULL COMMENT 'str_ext_c5',\\n\" +\n                \"\\t`str_ext_c6` varchar(128) DEFAULT NULL COMMENT 'str_ext_c6',\\n\" +\n                \"\\t`str_ext_c7` varchar(128) DEFAULT NULL COMMENT 'str_ext_c7',\\n\" +\n                \"\\t`str_ext_c8` varchar(128) DEFAULT NULL COMMENT 'str_ext_c8',\\n\" +\n                \"\\t`str_ext_c9` varchar(128) DEFAULT NULL COMMENT 'str_ext_c9',\\n\" +\n                \"\\t`str_ext_c10` varchar(128) DEFAULT NULL COMMENT 'str_ext_c10',\\n\" +\n                \"\\t`str_ext_c11` varchar(128) DEFAULT NULL COMMENT 'str_ext_c11',\\n\" +\n                \"\\t`str_ext_c12` varchar(128) DEFAULT NULL COMMENT 'str_ext_c12',\\n\" +\n                \"\\t`str_ext_c13` varchar(128) DEFAULT NULL COMMENT 'str_ext_c13',\\n\" +\n                \"\\t`str_ext_c14` varchar(128) DEFAULT NULL COMMENT 'str_ext_c14',\\n\" +\n                \"\\tPRIMARY KEY (`kd`) COMMENT 'index_key_ins_perf_6519',\\n\" +\n                \"\\tKEY `kdx_time` (`time`) COMMENT 'index_perf_time_6519',\\n\" +\n                \"\\tKEY `kdx_instance_time` (`kp`, `port`, `scope`, `time`) COMMENT 'index_ins_perf_inst_time_6519',\\n\" +\n                \"\\tKEY `kdx_instance_hash` (`kp`, `port`, `hashcode`, `scope`, `time`) COMMENT 'index_ins_perf_hash_6519',\\n\" +\n                \"\\tKEY `kdx_instance_all_dim` (`kp`, `port`, `db`, `logical_table`, `physical_table`, `sql_type`, `hashcode`, `scope`, `time`) COMMENT 'index_ins_perf_all_6519'\\n\" +\n                \") ENGINE = XENGINE AUTO_INCREMENT = 339181584 CHARSET = utf8mb4 COMMENT 'sql_ins_perf'\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest103.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest103 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `procs_priv` (\\n\" +\n                \"  `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"  `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"  `User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"  `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '',\\n\" +\n                \"  `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL,\\n\" +\n                \"  `Grantor` char(93) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"  `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '',\\n\" +\n                \"  `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                \"  PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`),\\n\" +\n                \"  KEY `Grantor` (`Grantor`)\\n\" +\n                \") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(10, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE `procs_priv` (\\n\" +\n                \"\\t`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Routine_type` enum('FUNCTION', 'PROCEDURE') COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\t`Grantor` char(93) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Proc_priv` set('Execute', 'Alter Routine', 'Grant') CHARACTER SET utf8 NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                \"\\tPRIMARY KEY (`Host`, `Db`, `User`, `Routine_name`, `Routine_type`),\\n\" +\n                \"\\tKEY `Grantor` (`Grantor`)\\n\" +\n                \") ENGINE = MyISAM CHARSET = utf8 COLLATE = utf8_bin COMMENT 'Procedure privileges'\", stmt.toString());\n\n        assertEquals(\"CREATE TABLE `procs_priv` (\\n\" +\n                \"\\t`Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`User` char(32) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Routine_type` enum('FUNCTION', 'PROCEDURE') COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\t`Grantor` char(93) COLLATE utf8_bin NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Proc_priv` set('Execute', 'Alter Routine', 'Grant') CHARACTER SET utf8 NOT NULL DEFAULT '',\\n\" +\n                \"\\t`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                \"\\tPRIMARY KEY (`Host`, `Db`, `User`, `Routine_name`, `Routine_type`),\\n\" +\n                \"\\tKEY `Grantor` (`Grantor`)\\n\" +\n                \") ENGINE = MyISAM CHARSET = utf8 COLLATE = utf8_bin COMMENT 'Procedure privileges'\", stmt.clone().toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest104.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest104 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE db1.table_0 (\\n\" +\n                \"  column_0 VARCHAR NOT NULL DEFAULT default_varchar COMMENT '',\\n\" +\n                \"  column_1 BIGINT COMMENT 'BIGINT_comment',\\n\" +\n                \"  column_2 DOUBLE NOT NULL DEFAULT default_double COMMENT '',\\n\" +\n                \"  column_3 VARCHAR delimiter \\\",\\\" COMMENT ''\\n\" +\n                \")\\n\" +\n                \"PARTITION BY KEY (column_0) PARTITION NUM 0\\n\" +\n                \"TABLEGROUP gg\\n\" +\n                \"OPTIONS (UPDATETYPE='realtime')\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(4, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE db1.table_0 (\\n\"\n                + \"\\tcolumn_0 VARCHAR NOT NULL DEFAULT default_varchar COMMENT '',\\n\"\n                + \"\\tcolumn_1 BIGINT COMMENT 'BIGINT_comment',\\n\"\n                + \"\\tcolumn_2 DOUBLE NOT NULL DEFAULT default_double COMMENT '',\\n\"\n                + \"\\tcolumn_3 VARCHAR DELIMITER ',' COMMENT ''\\n\"\n                + \")\\n\"\n                + \"OPTIONS (UPDATETYPE = 'realtime')\\n\"\n                + \"PARTITION BY KEY (column_0) PARTITION NUM 0\\n\"\n                + \"TABLEGROUP gg\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest105.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest105 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE DIMENSION TABLE tpch_junlan.nation (\\n\" +\n                \"  n_nationkey int NOT NULL COMMENT '',\\n\" +\n                \"  n_name varchar NOT NULL COMMENT '',\\n\" +\n                \"  n_regionkey int NOT NULL COMMENT '',\\n\" +\n                \"  n_comment varchar COMMENT '',\\n\" +\n                \"  PRIMARY KEY (N_NATIONKEY)\\n\" +\n                \")\\n\" +\n                \"OPTIONS (UPDATETYPE='realtime')\\n\" +\n                \"COMMENT ''\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(5, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE DIMENSION TABLE tpch_junlan.nation (\\n\"\n                + \"\\tn_nationkey int NOT NULL COMMENT '',\\n\"\n                + \"\\tn_name varchar NOT NULL COMMENT '',\\n\"\n                + \"\\tn_regionkey int NOT NULL COMMENT '',\\n\"\n                + \"\\tn_comment varchar COMMENT '',\\n\"\n                + \"\\tPRIMARY KEY (N_NATIONKEY)\\n\"\n                + \")\\n\"\n                + \"OPTIONS (UPDATETYPE = 'realtime') COMMENT ''\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest106.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest106 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `procs_priv` (\\n\" +\n                \"  `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL,\\n\" +\n                \"  PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`),\\n\" +\n                \"  KEY `Grantor` (`Grantor`)\\n\" +\n                \") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(3, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE `procs_priv` (\\n\" +\n                \"\\t`Routine_type` enum('FUNCTION', 'PROCEDURE') COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\tPRIMARY KEY (`Host`, `Db`, `User`, `Routine_name`, `Routine_type`),\\n\" +\n                \"\\tKEY `Grantor` (`Grantor`)\\n\" +\n                \") ENGINE = MyISAM CHARSET = utf8 COLLATE = utf8_bin COMMENT 'Procedure privileges'\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest107.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest107 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE \\n\" +\n                \"aliolap152578dbopt.aliolap152578dbopt_tbl1 (\\n\" +\n                \"col_id_int int NOT NULL , \\n\" +\n                \"col2_tinyint tinyint , \\n\" +\n                \"col3_boolean boolean , \\n\" +\n                \"col4_smallint smallint , \\n\" +\n                \"col5_int int , \\n\" +\n                \"col6_bigint bigint , \\n\" +\n                \"col7_float float , \\n\" +\n                \"col8_double double , \\n\" +\n                \"col9_date date , \\n\" +\n                \"col10_time time , \\n\" +\n                \"col11_timestamp timestamp , \\n\" +\n                \"col12_varchar varchar(1000) , \\n\" +\n                \"col13_multivalue multivalue  delimiter ',' , \\n\" +\n                \"primary key (col_id_int,col6_bigint)\\n\" +\n                \") \\n\" +\n                \"PARTITION BY HASH KEY(col_id_int) PARTITION NUM 100\\n\" +\n                \"SUBPARTITION BY LIST(col6_bigint BIGINT)\\n\" +\n                \"SUBPARTITION OPTIONS(available_Partition_Num=100)\\n\" +\n                \"TABLEGROUP aliolap152578dbopt_tg1\\n\" +\n                \"OPTIONS(UPDATETYPE='realtime')\\n\" +\n                \";\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(14, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE aliolap152578dbopt.aliolap152578dbopt_tbl1 (\\n\"\n                + \"\\tcol_id_int int NOT NULL,\\n\"\n                + \"\\tcol2_tinyint tinyint,\\n\" + \"\\tcol3_boolean boolean,\\n\"\n                + \"\\tcol4_smallint smallint,\\n\"\n                + \"\\tcol5_int int,\\n\" + \"\\tcol6_bigint bigint,\\n\"\n                + \"\\tcol7_float float,\\n\"\n                + \"\\tcol8_double double,\\n\" + \"\\tcol9_date date,\\n\"\n                + \"\\tcol10_time time,\\n\"\n                + \"\\tcol11_timestamp timestamp,\\n\" + \"\\tcol12_varchar varchar(1000),\\n\"\n                + \"\\tcol13_multivalue multivalue DELIMITER ',',\\n\"\n                + \"\\tPRIMARY KEY (col_id_int, col6_bigint)\\n\"\n                + \")\\n\"\n                + \"OPTIONS (UPDATETYPE = 'realtime')\\n\"\n                + \"PARTITION BY HASH KEY(col_id_int) PARTITION NUM 100\\n\"\n                + \"SUBPARTITION BY LIST (col6_bigint BIGINT)\\n\"\n                + \"SUBPARTITION OPTIONS (available_Partition_Num = 100)\\n\"\n                + \"TABLEGROUP aliolap152578dbopt_tg1;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest108_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest108_drds extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table ARCHIVE_ERR_RECORD\\n\" +\n                \"(\\n\" +\n                \"SUBS_ORDER_ID numeric(18,0) not null comment '订单编号',\\n\" +\n                \"ERR_MSG text comment '失败的消息结构',\\n\" +\n                \"ERR_REASON varchar(255) comment '失败原因',\\n\" +\n                \"PART_ID integer not null comment '分区标识（取订单编号中的月份）'\\n\" +\n                \")\\n\" +\n                \"DBPARTITION BY HASH(SUBS_ORDER_ID)\\n\" +\n                \"TBPARTITION BY UNI_HASH(PART_ID) TBPARTITIONS 12;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ALIYUN_DRDS);\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(4, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE ARCHIVE_ERR_RECORD (\\n\" +\n                \"\\tSUBS_ORDER_ID numeric(18, 0) NOT NULL COMMENT '订单编号',\\n\" +\n                \"\\tERR_MSG text COMMENT '失败的消息结构',\\n\" +\n                \"\\tERR_REASON varchar(255) COMMENT '失败原因',\\n\" +\n                \"\\tPART_ID integer NOT NULL COMMENT '分区标识（取订单编号中的月份）'\\n\" +\n                \")\\n\" +\n                \"DBPARTITION BY HASH(SUBS_ORDER_ID)\\n\" +\n                \"TBPARTITION BY UNI_HASH(PART_ID) TBPARTITIONS 12;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest108_error.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.parser.ParserException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest108_error extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table t (\\n\" +\n                \"f0 int,\\n\" +\n                \"delete int\" +\n                \");\";\n\n        Exception error = null;\n        try {\n            SQLUtils.parseStatements(sql, DbType.mysql);\n        } catch (ParserException ex) {\n            error = ex;\n        }\n        assertNotNull(error);\n        assertEquals(\"illegal name, pos 31, line 3, column 1, token DELETE\", error.getMessage());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest11.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest11 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `tmall_campaign` (\" +\n                \"`id` int(11) NOT NULL AUTO_INCREMENT,\" +\n                \"`campaign_name` varchar(200) NOT NULL COMMENT '活动名称',\" +\n                \"`create_date` datetime DEFAULT NULL COMMENT '活动创建时间',\" +\n                \"`delete_flag` int(11) DEFAULT '0' COMMENT '活动删除标识',\" +\n                \"PRIMARY KEY (`id`)\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=gbk;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"tmall_campaign\")));\n\n        assertTrue(visitor.containsColumn(\"tmall_campaign\", \"id\"));\n        assertTrue(visitor.containsColumn(\"tmall_campaign\", \"campaign_name\"));\n        assertTrue(visitor.containsColumn(\"tmall_campaign\", \"create_date\"));\n        assertTrue(visitor.containsColumn(\"tmall_campaign\", \"delete_flag\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest110_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest110_drds extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table a (id int(10)) dbpartition by hash(id) dbpartitionS 2 tbpartition by hash(id) tbpartitions 2 \";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(1, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE a (\\n\" +\n                \"\\tid int(10)\\n\" +\n                \")\\n\" +\n                \"DBPARTITION BY hash(id) DBPARTITIONS 2\\n\" +\n                \"TBPARTITION BY hash(id) TBPARTITIONS 2\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest111_ann.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest111_ann extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table t1 (\\n\" +\n                \"fid bigint, \\n\" +\n                \"feature array<float> ANNINDEX (type='FAST_INDEX,FLAT', distance='DotProduct', rttype='FLAT')\" +\n                \")\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ALIYUN_DRDS);\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(2, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE t1 (\\n\" +\n                \"\\tfid bigint,\\n\" +\n                \"\\tfeature ARRAY<float> ANNINDX (type = 'FLAT,FLAT_INDEX', DISTANCE = 'DotProduct', RTTYPE = 'FLAT')\\n\" +\n                \")\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.sql.Types;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest112 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE opening_lines ( \" +\n                \"id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY\" +\n                \", opening_line TEXT(500)\" +\n                \", author VARCHAR(200)\" +\n                \", title VARCHAR(200)\" +\n                \", FULLTEXT idx (opening_line) \" +\n                \") ENGINE=InnoDB;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(5, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE opening_lines (\\n\" +\n                \"\\tid INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,\\n\" +\n                \"\\topening_line TEXT(500),\\n\" +\n                \"\\tauthor VARCHAR(200),\\n\" +\n                \"\\ttitle VARCHAR(200),\\n\" +\n                \"\\tFULLTEXT INDEX idx(opening_line)\\n\" +\n                \") ENGINE = InnoDB;\", stmt.toString());\n\n        SchemaStatVisitor v = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(v);\n\n        assertEquals(4, v.getColumns().size());\n        SQLColumnDefinition column = stmt.findColumn(\"id\");\n        assertNotNull(column);\n        assertEquals(2, column.getConstraints().size());\n        assertTrue(column.isPrimaryKey());\n        assertEquals(Types.INTEGER, column.jdbcType());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest113_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest113_drds extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table if not exists test_table(\\n\" +\n                \"  id INT,name VARCHAR(30) DEFAULT NULL,\\n\" +\n                \"  create_time DATETIME DEFAULT NULL\\n\" +\n                \")ENGINE = InnoDB DEFAULT CHARSET = utf8 \\n\" +\n                \"dbpartition BY YYYYMM_NOLOOP (create_time) \\n\" +\n                \"tbpartition BY YYYYMM_NOLOOP (create_time) \\n\" +\n                \"  STARTWITH 20160108 ENDWITH 20170108;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(3, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS test_table (\\n\" +\n                \"\\tid INT,\\n\" +\n                \"\\tname VARCHAR(30) DEFAULT NULL,\\n\" +\n                \"\\tcreate_time DATETIME DEFAULT NULL\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8\\n\" +\n                \"DBPARTITION BY YYYYMM_NOLOOP(create_time)\\n\" +\n                \"TBPARTITION BY YYYYMM_NOLOOP(create_time) BETWEEN 20160108 AND 20170108;\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create table if not exists test_table(\\n\" +\n                \"  id INT,name VARCHAR(30) DEFAULT NULL,\\n\" +\n                \"  create_time DATETIME DEFAULT NULL\\n\" +\n                \")ENGINE = InnoDB DEFAULT CHARSET = utf8 \\n\" +\n                \"dbpartition BY YYYYMM_NOLOOP (create_time) \\n\" +\n                \"tbpartition BY YYYYMM_NOLOOP (create_time) \\n\" +\n                \"  BETWEEN 20160108 AND 20170108;\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(3, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS test_table (\\n\" +\n                \"\\tid INT,\\n\" +\n                \"\\tname VARCHAR(30) DEFAULT NULL,\\n\" +\n                \"\\tcreate_time DATETIME DEFAULT NULL\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8\\n\" +\n                \"DBPARTITION BY YYYYMM_NOLOOP(create_time)\\n\" +\n                \"TBPARTITION BY YYYYMM_NOLOOP(create_time) BETWEEN 20160108 AND 20170108;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest114.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.sql.Types;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest114 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE best_sign_cont_task ( \\n\" +\n                \"  sys_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL COMMENT '系统时间' \\n\" +\n                \") ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT '上上签合同创建任务记录'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(1, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE best_sign_cont_task (\\n\" +\n                \"\\tsys_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '系统时间'\\n\" +\n                \") ENGINE = INNODB CHARSET = utf8 COMMENT '上上签合同创建任务记录'\", stmt.toString());\n\n        SchemaStatVisitor v = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(v);\n\n        assertEquals(1, v.getColumns().size());\n        SQLColumnDefinition column = stmt.findColumn(\"sys_time\");\n        assertNotNull(column);\n        assertEquals(1, column.getConstraints().size());\n        assertFalse(column.isPrimaryKey());\n        assertEquals(Types.TIMESTAMP, column.jdbcType());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest115.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.repository.SchemaRepository;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.sql.Types;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest115 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `schema`.`Employee` (\\n\" +\n                \"   id int(10),\\n\" +\n                \"   `Employee_id` VARCHAR(45) NOT NULL ,\\n\" +\n                \"   `Name` VARCHAR(255) NULL ,\\n\" +\n                \"   `idAddresses` VARCHAR(45) NULL ,\\n\" +\n                \"   PRIMARY KEY (`Employee_id`) ,\\n\" +\n                \"   INDEX `employee_id` USING BTREE (id(5)),\\n\" +\n                \"   CONSTRAINT `fkEmployee_Addresses`\\n\" +\n                \"   FOREIGN KEY `fkEmployee_Addresses` (`idAddresses`)\\n\" +\n                \"   REFERENCES `schema`.`Addresses` (`idAddresses`)\\n\" +\n                \"   ON DELETE NO ACTION\\n\" +\n                \"   ON UPDATE NO ACTION\\n\" +\n                \" ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(7, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `schema`.`Employee` (\\n\" +\n                \"\\tid int(10),\\n\" +\n                \"\\t`Employee_id` VARCHAR(45) NOT NULL,\\n\" +\n                \"\\t`Name` VARCHAR(255) NULL,\\n\" +\n                \"\\t`idAddresses` VARCHAR(45) NULL,\\n\" +\n                \"\\tPRIMARY KEY (`Employee_id`),\\n\" +\n                \"\\tINDEX `employee_id` USING BTREE(id(5)),\\n\" +\n                \"\\tCONSTRAINT `fkEmployee_Addresses` FOREIGN KEY `fkEmployee_Addresses` (`idAddresses`) REFERENCES `schema`.`Addresses` (`idAddresses`) ON DELETE NO ACTION ON UPDATE NO ACTION\\n\" +\n                \") ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.toString());\n\n        SchemaStatVisitor v = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(v);\n\n        assertEquals(5, v.getColumns().size());\n        SQLColumnDefinition column = stmt.findColumn(\"Employee_id\");\n        assertNotNull(column);\n        assertEquals(1, column.getConstraints().size());\n        assertTrue(column.isPrimaryKey());\n        assertEquals(Types.VARCHAR, column.jdbcType());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `schema`.`Employee` (\\n\" +\n                \"\\tid int(10),\\n\" +\n                \"\\t`Employee_id` VARCHAR(45) NOT NULL,\\n\" +\n                \"\\t`Name` VARCHAR(255) NULL,\\n\" +\n                \"\\t`idAddresses` VARCHAR(45) NULL,\\n\" +\n                \"\\tPRIMARY KEY (`Employee_id`),\\n\" +\n                \"\\tINDEX `employee_id` USING BTREE(id(5)),\\n\" +\n                \"\\tFOREIGN KEY `fkEmployee_Addresses` (`idAddresses`) REFERENCES `schema`.`Addresses` (`idAddresses`) ON DELETE NO ACTION ON UPDATE NO ACTION\\n\" +\n                \") ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.clone().toString());\n\n        SchemaRepository repository = new SchemaRepository(DbType.mysql);\n        repository.acceptDDL(sql);\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"\\tid int(10),\\n\" +\n                \"\\t`Employee_id` VARCHAR(45) NOT NULL,\\n\" +\n                \"\\t`Name` VARCHAR(255) NULL,\\n\" +\n                \"\\t`idAddresses` VARCHAR(45) NULL,\\n\" +\n                \"\\tPRIMARY KEY (`Employee_id`),\\n\" +\n                \"\\tINDEX `employee_id` USING BTREE(id(5)),\\n\" +\n                \"\\tFOREIGN KEY `fkEmployee_Addresses` (`idAddresses`) REFERENCES `schema`.`Addresses` (`idAddresses`) ON DELETE NO ACTION ON UPDATE NO ACTION\\n\" +\n                \") ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", repository\n                .findTable(\"Employee\")\n                .getStatement()\n                .toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest116.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest116 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"   id int(10)\" +\n                \" ) broadcast ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"\\tid int(10)\\n\" +\n                \") BROADCAST ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE `t1` (\\n\" +\n                \"  `id` int NOT NULL,\\n\" +\n                \"  `e_id` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"  `m_id` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"  `m_id1` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"  `m_id2` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"  `name` varchar(256) COLLATE utf8_bin DEFAULT NULL,\\n\" +\n                \"  `addr` varchar(45) COLLATE utf8_bin DEFAULT NULL,\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `index_e_id` (`e_id`),\\n\" +\n                \"  index `index_m_id` (`m_id`),\\n\" +\n                \"  KEY `index_m1_id` (m_id1(10)),\\n\" +\n                \"  index `index_m2_id` (m_id2(30))\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `t1` (\\n\" +\n                \"\\t`id` int NOT NULL,\\n\" +\n                \"\\t`e_id` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\t`m_id` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\t`m_id1` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\t`m_id2` varchar(45) COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\t`name` varchar(256) COLLATE utf8_bin DEFAULT NULL,\\n\" +\n                \"\\t`addr` varchar(45) COLLATE utf8_bin DEFAULT NULL,\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tKEY `index_e_id` (`e_id`),\\n\" +\n                \"\\tINDEX `index_m_id`(`m_id`),\\n\" +\n                \"\\tKEY `index_m1_id` (m_id1(10)),\\n\" +\n                \"\\tINDEX `index_m2_id`(m_id2(30))\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8 COLLATE = utf8_bin\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest117.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest117 extends MysqlTest {\n    public void test() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `Employee` (id int(10) auto_increment\" +\n                \" ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"\\tid int(10) AUTO_INCREMENT\\n\" +\n                \") ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.toString());\n    }\n\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `Employee` (id int(10) auto_increment by GROUP\" +\n                \" ) auto_increment=12313 ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"\\tid int(10) AUTO_INCREMENT BY GROUP\\n\" +\n                \") AUTO_INCREMENT = 12313 ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `Employee` (id int(10) auto_increment by simple\" +\n                \" ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"\\tid int(10) AUTO_INCREMENT BY SIMPLE\\n\" +\n                \") ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.toString());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `Employee` (id int(10) auto_increment by simple with cache\" +\n                \" ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"\\tid int(10) AUTO_INCREMENT BY SIMPLE WITH CACHE\\n\" +\n                \") ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.toString());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `Employee` (id int(10) auto_increment by time\" +\n                \" ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS `Employee` (\\n\" +\n                \"\\tid int(10) AUTO_INCREMENT BY TIME\\n\" +\n                \") ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest118.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest118 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE sal_emp (\\n\" +\n                \"    name            int,\\n\" +\n                \"    pay_by_quarter  int[],\\n\" +\n                \"    schedule        long[256]\\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE sal_emp (\\n\" +\n                \"\\tname int,\\n\" +\n                \"\\tpay_by_quarter int[],\\n\" +\n                \"\\tschedule long[256]\\n\" +\n                \");\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE sal_emp (\\n\" +\n                \"    name            int,\\n\" +\n                \"    pay_by_quarter  array<int>,\\n\" +\n                \"    schedule        array<long>(256)\\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE sal_emp (\\n\" +\n                \"\\tname int,\\n\" +\n                \"\\tpay_by_quarter ARRAY<int>,\\n\" +\n                \"\\tschedule ARRAY<long>(256)\\n\" +\n                \");\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest119_ann.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest119_ann extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE face_feature (\\n\" +\n                \"  id varchar COMMENT 'id',\\n\" +\n                \"  facefea array<short>(256) COMMENT 'feature',\\n\" +\n                \"  ANN INDEX facefea_index1 (facefea) DistanceMeasure = DotProduct ALGORITHM = IVF\\n\" +\n                \"  PRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY (id) PARTITION NUM 8\\n\" +\n                \"TABLEGROUP vector_demo_group\\n\" +\n                \"OPTIONS (UPDATETYPE='batch')\\n\" +\n                \"COMMENT '';\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ALIYUN_DRDS);\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(4, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE face_feature (\\n\" +\n                \"\\tid varchar COMMENT 'id',\\n\" +\n                \"\\tfacefea ARRAY<short>(256) COMMENT 'feature',\\n\" +\n                \"\\tINDEX facefea_index1 ANN(facefea) ALGORITHM = IVF DistanceMeasure = DotProduct,\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"OPTIONS (UPDATETYPE = 'batch') COMMENT ''\\n\" +\n                \"PARTITION BY HASH KEY(id) PARTITION NUM 8\\n\" +\n                \"TABLEGROUP vector_demo_group;\", stmt.toString());\n\n        MySqlTableIndex idx = (MySqlTableIndex) stmt.findIndex(\"facefea\");\n        assertNotNull(idx);\n\n        assertEquals(\"DotProduct\", idx.getDistanceMeasure());\n        assertEquals(\"IVF\", idx.getAlgorithm());\n        assertEquals(\"ANN\", idx.getIndexType());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest12.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest12 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE 'test' ('blob_col' BLOB, INDEX(blob_col(10)));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"blob_col\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest120.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest120 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE sal_emp (\\n\" +\n                \"    name            int auto_increment unit count 2 index 1 step 0,\\n\" +\n                \"    pay_by_quarter  int[],\\n\" +\n                \"    schedule        long[256]\\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE sal_emp (\\n\" +\n                \"\\tname int AUTO_INCREMENT UNIT COUNT 2 INDEX 1 STEP 0,\\n\" +\n                \"\\tpay_by_quarter int[],\\n\" +\n                \"\\tschedule long[256]\\n\" +\n                \");\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE sal_emp (\\n\" +\n                \"\\tname int PRIMARY KEY AUTO_INCREMENT UNIT COUNT 666 INDEX 8 STEP 11110,\\n\" +\n                \"\\tpay_by_quarter ARRAY<int>,\\n\" +\n                \"\\tschedule ARRAY<long>(256)\\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE sal_emp (\\n\" +\n                \"\\tname int PRIMARY KEY AUTO_INCREMENT UNIT COUNT 666 INDEX 8 STEP 11110,\\n\" +\n                \"\\tpay_by_quarter ARRAY<int>,\\n\" +\n                \"\\tschedule ARRAY<long>(256)\\n\" +\n                \");\", stmt.toString());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"CREATE TABLE sal_emp (\\n\" +\n                \"\\tname int AUTO_INCREMENT UNIT COUNT 666 INDEX 8 STEP 11110,\\n\" +\n                \"\\tpay_by_quarter ARRAY<int>,\\n\" +\n                \"\\tschedule ARRAY<long>(256),\\n\" +\n                \"primary key (name)\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE sal_emp (\\n\" +\n                \"\\tname int AUTO_INCREMENT UNIT COUNT 666 INDEX 8 STEP 11110,\\n\" +\n                \"\\tpay_by_quarter ARRAY<int>,\\n\" +\n                \"\\tschedule ARRAY<long>(256),\\n\" +\n                \"\\tPRIMARY KEY (name)\\n\" +\n                \");\", stmt.toString());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"CREATE TABLE `sch1`.`sal_emp` (\\n\" +\n                \"\\tname int AUTO_INCREMENT UNIT COUNT 666 INDEX 8 STEP 11110,\\n\" +\n                \"\\tpay_by_quarter ARRAY<int>,\\n\" +\n                \"\\tschedule ARRAY<long>(256),\\n\" +\n                \"primary key (name)\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.IgnoreNameQuotes);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE sch1.sal_emp (\\n\" +\n                \"\\tname int AUTO_INCREMENT UNIT COUNT 666 INDEX 8 STEP 11110,\\n\" +\n                \"\\tpay_by_quarter ARRAY<int>,\\n\" +\n                \"\\tschedule ARRAY<long>(256),\\n\" +\n                \"\\tPRIMARY KEY (name)\\n\" +\n                \");\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest121_fulltext.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.sql.Types;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest121_fulltext extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS ddd ( pk int NOT NULL PRIMARY KEY AUTO_INCREMENT\" +\n                \", tint tinyint(10) UNSIGNED ZEROFILL, sint smallint DEFAULT 1000, mint mediumint UNIQUE, bint bigint(20) COMMENT 'bigint'\" +\n                \", rint real(10, 2) REFERENCES tt1 (rint) MATCH FULL ON DELETE RESTRICT, dble double(10, 2) REFERENCES tt1 (dble) MATCH PARTIAL ON DELETE CASCADE\" +\n                \", fl float(10, 2) REFERENCES tt1 (fl) MATCH SIMPLE ON DELETE SET NULL, dc decimal(10, 2) REFERENCES tt1 (dc) MATCH SIMPLE ON UPDATE NO ACTION\" +\n                \", num numeric(10, 2), dt date NULL, ti time, tis timestamp, dti datetime\" +\n                \", vc varchar(100) BINARY , vc2 varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, tb tinyblob, bl blob, mb mediumblob\" +\n                \", lb longblob, tt tinytext, mt mediumtext, lt longtext, en enum('1', '2'), st set('5', '6'), id1 int, id2 int, id3 varchar(100)\" +\n                \", vc1 varchar(100), vc3 varchar(100), INDEX idx1 USING hash(id1), KEY idx2 USING hash (id2), FULLTEXT key idx4(id3(20))\" +\n                \", CONSTRAINT c1 UNIQUE c1 USING btree (vc1(20)) ) ENGINE = InnoDB AUTO_INCREMENT = 2 AVG_ROW_LENGTH = 100 CHARACTER SET = utf8 COLLATE utf8_bin CHECKSUM = 0 COMMENT 'abcd'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        assertEquals(34, stmt.getTableElementList().size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS ddd (\\n\" +\n                \"\\tpk int NOT NULL PRIMARY KEY AUTO_INCREMENT,\\n\" +\n                \"\\ttint tinyint(10) UNSIGNED ZEROFILL,\\n\" +\n                \"\\tsint smallint DEFAULT 1000,\\n\" +\n                \"\\tmint mediumint UNIQUE,\\n\" +\n                \"\\tbint bigint(20) COMMENT 'bigint',\\n\" +\n                \"\\trint real(10, 2) REFERENCES tt1 (rint) MATCH FULL ON DELETE RESTRICT,\\n\" +\n                \"\\tdble double(10, 2) REFERENCES tt1 (dble) MATCH PARTIAL ON DELETE CASCADE,\\n\" +\n                \"\\tfl float(10, 2) REFERENCES tt1 (fl) MATCH SIMPLE ON DELETE SET NULL,\\n\" +\n                \"\\tdc decimal(10, 2) REFERENCES tt1 (dc) MATCH SIMPLE ON UPDATE NO ACTION,\\n\" +\n                \"\\tnum numeric(10, 2),\\n\" +\n                \"\\tdt date NULL,\\n\" +\n                \"\\tti time,\\n\" +\n                \"\\ttis timestamp,\\n\" +\n                \"\\tdti datetime,\\n\" +\n                \"\\tvc varchar(100) BINARY ,\\n\" +\n                \"\\tvc2 varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,\\n\" +\n                \"\\ttb tinyblob,\\n\" +\n                \"\\tbl blob,\\n\" +\n                \"\\tmb mediumblob,\\n\" +\n                \"\\tlb longblob,\\n\" +\n                \"\\ttt tinytext,\\n\" +\n                \"\\tmt mediumtext,\\n\" +\n                \"\\tlt longtext,\\n\" +\n                \"\\ten enum('1', '2'),\\n\" +\n                \"\\tst set('5', '6'),\\n\" +\n                \"\\tid1 int,\\n\" +\n                \"\\tid2 int,\\n\" +\n                \"\\tid3 varchar(100),\\n\" +\n                \"\\tvc1 varchar(100),\\n\" +\n                \"\\tvc3 varchar(100),\\n\" +\n                \"\\tINDEX idx1 USING hash(id1),\\n\" +\n                \"\\tKEY idx2 USING hash (id2),\\n\" +\n                \"\\tFULLTEXT KEY idx4 (id3(20)),\\n\" +\n                \"\\tUNIQUE c1 USING btree (vc1(20))\\n\" +\n                \") ENGINE = InnoDB AUTO_INCREMENT = 2 AVG_ROW_LENGTH = 100 CHARACTER SET = utf8 COLLATE = utf8_bin CHECKSUM = 0 COMMENT 'abcd'\", stmt.toString());\n\n        assertEquals(\"create table if not exists ddd (\\n\" +\n                \"\\tpk int not null primary key auto_increment,\\n\" +\n                \"\\ttint tinyint(10) unsigned zerofill,\\n\" +\n                \"\\tsint smallint default 1000,\\n\" +\n                \"\\tmint mediumint unique,\\n\" +\n                \"\\tbint bigint(20) comment 'bigint',\\n\" +\n                \"\\trint real(10, 2) references tt1 (rint) match full on delete restrict,\\n\" +\n                \"\\tdble double(10, 2) references tt1 (dble) match partial on delete cascade,\\n\" +\n                \"\\tfl float(10, 2) references tt1 (fl) match simple on delete set null,\\n\" +\n                \"\\tdc decimal(10, 2) references tt1 (dc) match simple on update no action,\\n\" +\n                \"\\tnum numeric(10, 2),\\n\" +\n                \"\\tdt date null,\\n\" +\n                \"\\tti time,\\n\" +\n                \"\\ttis timestamp,\\n\" +\n                \"\\tdti datetime,\\n\" +\n                \"\\tvc varchar(100) binary ,\\n\" +\n                \"\\tvc2 varchar(100) character set utf8 collate utf8_bin not null,\\n\" +\n                \"\\ttb tinyblob,\\n\" +\n                \"\\tbl blob,\\n\" +\n                \"\\tmb mediumblob,\\n\" +\n                \"\\tlb longblob,\\n\" +\n                \"\\ttt tinytext,\\n\" +\n                \"\\tmt mediumtext,\\n\" +\n                \"\\tlt longtext,\\n\" +\n                \"\\ten enum('1', '2'),\\n\" +\n                \"\\tst set('5', '6'),\\n\" +\n                \"\\tid1 int,\\n\" +\n                \"\\tid2 int,\\n\" +\n                \"\\tid3 varchar(100),\\n\" +\n                \"\\tvc1 varchar(100),\\n\" +\n                \"\\tvc3 varchar(100),\\n\" +\n                \"\\tindex idx1 using hash(id1),\\n\" +\n                \"\\tkey idx2 using hash (id2),\\n\" +\n                \"\\tfulltext key idx4 (id3(20)),\\n\" +\n                \"\\tunique c1 using btree (vc1(20))\\n\" +\n                \") engine = InnoDB auto_increment = 2 avg_row_length = 100 character set = utf8 collate = utf8_bin checksum = 0 comment 'abcd'\", stmt.toLowerCaseString());\n\n        SchemaStatVisitor v = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(v);\n\n        assertEquals(30, v.getColumns().size());\n        SQLColumnDefinition column = stmt.findColumn(\"bint\");\n        assertNotNull(column);\n        assertEquals(0, column.getConstraints().size());\n        assertFalse(column.isPrimaryKey());\n        assertEquals(Types.BIGINT, column.jdbcType());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest122_ads.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest122_ads extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE cache_table_1 OPTIONS(cache=true) AS /*+ engine=MPP */ SELECT * FROM test_realtime1 LIMIT 200;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE cache_table_1\\n\" +\n                \"OPTIONS (cache = true)\\n\" +\n                \"AS\\n\" +\n                \"/*+ engine=MPP */\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM test_realtime1\\n\" +\n                \"LIMIT 200;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest125_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest125_drds extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE t_order (\\n\" +\n                \"  `id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  `order_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `buyer_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `seller_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `order_snapshot` longtext DEFAULT NULL,\\n\" +\n                \"  `order_detail` longtext DEFAULT NULL,\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `l_i_order` (`order_id`),\\n\" +\n                \"  GLOBAL INDEX `g_i_seller` (`seller_id`) dbpartition by hash(`seller_id`),\\n\" +\n                \"  UNIQUE GLOBAL `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) dbpartition by hash(`buyer_id`)\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`order_id`);\";\n//        System.out.println(sql);\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE t_order (\\n\" +\n                \"\\t`id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"\\t`order_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"\\t`buyer_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"\\t`seller_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"\\t`order_snapshot` longtext DEFAULT NULL,\\n\" +\n                \"\\t`order_detail` longtext DEFAULT NULL,\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tKEY `l_i_order` (`order_id`),\\n\" +\n                \"\\tGLOBAL INDEX `g_i_seller`(`seller_id`) DBPARTITION BY hash(`seller_id`),\\n\" +\n                \"\\tUNIQUE GLOBAL `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) DBPARTITION BY hash(`buyer_id`)\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8\\n\" +\n                \"DBPARTITION BY hash(`order_id`);\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE t_order (\\n\" +\n                \"  `id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  `order_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `buyer_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `seller_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `order_snapshot` longtext DEFAULT NULL,\\n\" +\n                \"  `order_detail` longtext DEFAULT NULL,\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `l_i_order` (`order_id`),\\n\" +\n                \"  GLOBAL INDEX `g_i_seller` (`seller_id`) covering(`order_snapshot`) dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`order_id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE t_order (\\n\"\n                + \"\\t`id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\"\n                + \"\\t`order_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"\\t`buyer_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"\\t`seller_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"\\t`order_snapshot` longtext DEFAULT NULL,\\n\"\n                + \"\\t`order_detail` longtext DEFAULT NULL,\\n\"\n                + \"\\tPRIMARY KEY (`id`),\\n\"\n                + \"\\tKEY `l_i_order` (`order_id`),\\n\"\n                + \"\\tGLOBAL INDEX `g_i_seller`(`seller_id`) COVERING (`order_snapshot`) DBPARTITION BY hash(`seller_id`) TBPARTITION BY hash\"\n                + \"(`seller_id`) TBPARTITIONS 3\\n\"\n                + \") ENGINE = InnoDB CHARSET = utf8\\n\"\n                + \"DBPARTITION BY hash(`order_id`);\", stmt.toString());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"CREATE TABLE t_order (\\n\" +\n                \"  `id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  `order_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `buyer_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `seller_id` varchar(20) DEFAULT NULL,\\n\" +\n                \"  `order_snapshot` longtext DEFAULT NULL,\\n\" +\n                \"  `order_detail` longtext DEFAULT NULL,\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `l_i_order` (`order_id`),\\n\" +\n                \"  UNIQUE GLOBAL INDEX `g_i_seller` (`seller_id`) covering (order_snapshot) dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`order_id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE t_order (\\n\"\n                + \"\\t`id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\"\n                + \"\\t`order_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"\\t`buyer_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"\\t`seller_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"\\t`order_snapshot` longtext DEFAULT NULL,\\n\"\n                + \"\\t`order_detail` longtext DEFAULT NULL,\\n\"\n                + \"\\tPRIMARY KEY (`id`),\\n\"\n                + \"\\tKEY `l_i_order` (`order_id`),\\n\"\n                + \"\\tUNIQUE GLOBAL INDEX `g_i_seller` (`seller_id`) COVERING (order_snapshot) DBPARTITION BY hash(`seller_id`)\"\n                + \" TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3\\n\"\n                + \") ENGINE = InnoDB CHARSET = utf8\\n\"\n                + \"DBPARTITION BY hash(`order_id`);\", stmt.toString());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"CREATE TABLE t_order (\\n\" + \"  `id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\"\n                + \"  `order_id` varchar(20) DEFAULT NULL,\\n\" + \"  `buyer_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"  `seller_id` varchar(20) DEFAULT NULL,\\n\" + \"  `order_snapshot` longtext DEFAULT NULL,\\n\"\n                + \"  `order_detail` longtext DEFAULT NULL,\\n\" + \"  PRIMARY KEY (`id`),\\n\"\n                + \"  KEY `l_i_order` (`order_id`),\\n\"\n                + \"  UNIQUE GLOBAL `g_i_seller` (`seller_id`) covering (order_snapshot) \"\n                + \"DBPARTITION BY HASH(SELLER_ID) TBPARTITION BY UNI_HASH(SELLER_ID) TBPARTITIONS 12\"\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`order_id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE t_order (\\n\" + \"\\t`id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\"\n                        + \"\\t`order_id` varchar(20) DEFAULT NULL,\\n\" + \"\\t`buyer_id` varchar(20) DEFAULT NULL,\\n\"\n                        + \"\\t`seller_id` varchar(20) DEFAULT NULL,\\n\" + \"\\t`order_snapshot` longtext DEFAULT NULL,\\n\"\n                        + \"\\t`order_detail` longtext DEFAULT NULL,\\n\" + \"\\tPRIMARY KEY (`id`),\\n\"\n                        + \"\\tKEY `l_i_order` (`order_id`),\\n\"\n                        + \"\\tUNIQUE GLOBAL `g_i_seller` (`seller_id`) COVERING (order_snapshot) \"\n                        + \"DBPARTITION BY HASH(SELLER_ID) TBPARTITION BY UNI_HASH(SELLER_ID) TBPARTITIONS 12\\n\"\n                        + \") ENGINE = InnoDB CHARSET = utf8\\n\" + \"DBPARTITION BY hash(`order_id`);\",\n                stmt.toString());\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"CREATE TABLE t_order (\\n\"\n                + \"  `id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\"\n                + \"  `order_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"  `buyer_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"  `seller_id` varchar(20) DEFAULT NULL,\\n\"\n                + \"  `order_snapshot` longtext DEFAULT NULL,\\n\"\n                + \"  `order_detail` longtext DEFAULT NULL,\\n\"\n                + \"  PRIMARY KEY (`id`),\\n\"\n                + \"  KEY `l_i_order` (`order_id`),\\n\"\n                + \"  UNIQUE GLOBAL `g_i_seller` (`seller_id`) covering (order_snapshot) dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`) tbpartitions 3 COMMENT \\\"CREATE GSI TEST\\\"\\n\"\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`order_id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE t_order (\\n\"\n                        + \"\\t`id` bigint(11) NOT NULL AUTO_INCREMENT,\\n\"\n                        + \"\\t`order_id` varchar(20) DEFAULT NULL,\\n\"\n                        + \"\\t`buyer_id` varchar(20) DEFAULT NULL,\\n\"\n                        + \"\\t`seller_id` varchar(20) DEFAULT NULL,\\n\"\n                        + \"\\t`order_snapshot` longtext DEFAULT NULL,\\n\"\n                        + \"\\t`order_detail` longtext DEFAULT NULL,\\n\"\n                        + \"\\tPRIMARY KEY (`id`),\\n\"\n                        + \"\\tKEY `l_i_order` (`order_id`),\\n\"\n                        + \"\\tUNIQUE GLOBAL `g_i_seller` (`seller_id`) COVERING (order_snapshot) DBPARTITION BY hash(`seller_id`)\"\n                        + \" TBPARTITION BY hash(`seller_id`) TBPARTITIONS 3 COMMENT 'CREATE GSI TEST'\\n\"\n                        + \") ENGINE = InnoDB CHARSET = utf8\\n\" + \"DBPARTITION BY hash(`order_id`);\",\n                stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest126.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest126 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE tablename1 (\\n\"\n                + \"      id INT,\\n\"\n                + \"      title clob,\\n\"\n                + \"      body clob,\\n\"\n                + \"      comment clob,\\n\"\n                + \"      author clob,\\n\"\n                + \"      FULLTEXT INDEX f_idx1(title) WITH INDEX ANALYZER 'analyzer_name1' WITH QUERY ANALYZER 'analyzer_name2',\\n\"\n                + \"      FULLTEXT INDEX f_idx2(body) WITH ANALYZER 'analyzer_name3',    \"\n                + \"      FULLTEXT INDEX f_idx3(comment) WITH INDEX ANALYZER 'analyzer_name4',  \"\n                + \"      FULLTEXT INDEX f_idx4(author)  WITH QUERY ANALYZER 'analyzer_name5',\"\n                + \"      FULLTEXT INDEX f_idx5(author)\\n\"\n                + \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE tablename1 (\\n\" + \"\\tid INT,\\n\" + \"\\ttitle clob,\\n\" + \"\\tbody clob,\\n\"\n                + \"\\tcomment clob,\\n\" + \"\\tauthor clob,\\n\"\n                + \"\\tFULLTEXT INDEX f_idx1(title) WITH INDEX ANALYZER 'analyzer_name1' WITH QUERY ANALYZER 'analyzer_name2',\\n\"\n                + \"\\tFULLTEXT INDEX f_idx2(body) WITH ANALYZER 'analyzer_name3',\\n\"\n                + \"\\tFULLTEXT INDEX f_idx3(comment) WITH INDEX ANALYZER 'analyzer_name4',\\n\"\n                + \"\\tFULLTEXT INDEX f_idx4(author) WITH QUERY ANALYZER 'analyzer_name5',\\n\"\n                + \"\\tFULLTEXT INDEX f_idx5(author)\\n\" + \");\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest126_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest126_drds extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE xx\\n\" +\n                \"DBPARTITION BY hash(name1) TBPARTITION BY hash(name2) TBPARTITIONS 4\\n\" +\n                \"EXTPARTITION (\\n\" +\n                \"    DBPARTITION xxx BY KEY('abc') TBPARTITION yyy BY KEY('abc'),\\n\" +\n                \"    DBPARTITION yyy BY KEY('def') TBPARTITION yyy BY KEY('def'),\\n\" +\n                \"    DBPARTITION yyy BY KEY('gpk')\\n\" +\n                \")\";\n//        System.out.println(sql);\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE xx\\n\" +\n                \"DBPARTITION BY hash(name1)\\n\" +\n                \"TBPARTITION BY hash(name2) TBPARTITIONS 4\\n\" +\n                \"EXTPARTITION (\\n\" +\n                \"\\tDBPARTITION xxx BY KEY('abc') TBPARTITION yyy BY KEY('abc'), \\n\" +\n                \"\\tDBPARTITION yyy BY KEY('def') TBPARTITION yyy BY KEY('def'), \\n\" +\n                \"\\tDBPARTITION yyy BY KEY('gpk')\\n\" +\n                \")\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest127_ads_ann.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest127_ads_ann extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE adl_new_retail.adl_sec_verify_face ( \\n\" +\n                \"   id varchar NOT NULL COMMENT '', \\n\" +\n                \"   xid varchar NOT NULL COMMENT ''\\n, \" +\n                \"   card_no varchar COMMENT '', \\n\" +\n                \"   face_oss varchar COMMENT '', idpc float COMMENT '', fidpc float COMMENT '', face_feature float[256] NOT NULL COMMENT '', \\n\" +\n                \"gender smallint COMMENT '', age smallint COMMENT '', \\n\" +\n                \"ANN INDEX feature_idx0 (face_feature) DistanceMeasure=DotProduct Algorithm=FAST_INDEX, PRIMARY KEY (id,xid) \\n\" +\n                \") PARTITION BY HASH (ComSubStr (xid, face_oss)) PARTITION NUM 16 TABLEGROUP deepvision OPTIONS (UPDATETYPE='realtime') COMMENT 'verify photos';\";\n//        System.out.println(sql);\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE adl_new_retail.adl_sec_verify_face (\\n\" +\n                \"\\tid varchar NOT NULL COMMENT '',\\n\" +\n                \"\\txid varchar NOT NULL COMMENT '',\\n\" +\n                \"\\tcard_no varchar COMMENT '',\\n\" +\n                \"\\tface_oss varchar COMMENT '',\\n\" +\n                \"\\tidpc float COMMENT '',\\n\" +\n                \"\\tfidpc float COMMENT '',\\n\" +\n                \"\\tface_feature float[256] NOT NULL COMMENT '',\\n\" +\n                \"\\tgender smallint COMMENT '',\\n\" +\n                \"\\tage smallint COMMENT '',\\n\" +\n                \"\\tINDEX feature_idx0 ANN(face_feature) ALGORITHM = FAST_INDEX DistanceMeasure = DotProduct,\\n\" +\n                \"\\tPRIMARY KEY (id, xid)\\n\" +\n                \")\\n\" +\n                \"OPTIONS (UPDATETYPE = 'realtime') COMMENT 'verify photos'\\n\" +\n                \"PARTITION BY HASH (ComSubStr(xid, face_oss)) PARTITION NUM 16\\n\" +\n                \"TABLEGROUP deepvision;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest128_quote.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest128_quote extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE \\\"linxi_test\\\".\\\"linxi_subpart11\\\" (\\n\" +\n                \"  \\\"id\\\"       BIGINT  NOT NULL\\n\" +\n                \"  COMMENT '',\\n\" +\n                \"  \\\"int_test\\\" BIGINT  NOT NULL\\n\" +\n                \"  COMMENT '',\\n\" +\n                \"  v_test     VARCHAR NOT NULL\\n\" +\n                \"  COMMENT '',\\n\" +\n                \"  PRIMARY KEY (\\'id\\', int_test, subcol)\\n\" +\n                \") PARTITION BY HASH KEY (\\\"id\\\"\\n\" +\n                \") PARTITION NUM 10 SUBPARTITION BY LIST (\\\"subcol\\\" BIGINT\\n\" +\n                \") SUBPARTITION OPTIONS (available_Partition_Num=100\\n\" +\n                \") TABLEGROUP group2 OPTIONS (UPDATETYPE='realtime'\\n\" +\n                \") COMMENT ''\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE \\\"linxi_test\\\".\\\"linxi_subpart11\\\" (\\n\" +\n                \"\\t\\\"id\\\" BIGINT NOT NULL COMMENT '',\\n\" +\n                \"\\t\\\"int_test\\\" BIGINT NOT NULL COMMENT '',\\n\" +\n                \"\\tv_test VARCHAR NOT NULL COMMENT '',\\n\" +\n                \"\\tPRIMARY KEY (\\'id\\', int_test, subcol)\\n\" +\n                \")\\n\" +\n                \"OPTIONS (UPDATETYPE = 'realtime') COMMENT ''\\n\" +\n                \"PARTITION BY HASH KEY('id') PARTITION NUM 10\\n\" +\n                \"SUBPARTITION BY LIST (\\\"subcol\\\" BIGINT)\\n\" +\n                \"SUBPARTITION OPTIONS (available_Partition_Num = 100)\\n\" +\n                \"TABLEGROUP group2\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest129_ads.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest129_ads extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE cache_table_1 OPTIONS(cache=true) AS /*+ engine=MPP */ SELECT * FROM test_realtime1 LIMIT 200;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE cache_table_1\\n\" +\n                \"OPTIONS (cache = true)\\n\" +\n                \"AS\\n\" +\n                \"/*+ engine=MPP */\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM test_realtime1\\n\" +\n                \"LIMIT 200;\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE employees (\\n\" +\n                \"    id INT NOT NULL,\\n\" +\n                \"    fname VARCHAR(30),\\n\" +\n                \"    lname VARCHAR(30),\\n\" +\n                \"    hired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"    separated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"    job_code INT,\\n\" +\n                \"    store_id INT\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY (id)\\n\" +\n                \"tablegroup group0;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE employees (\\n\" +\n                \"\\tid INT NOT NULL,\\n\" +\n                \"\\tfname VARCHAR(30),\\n\" +\n                \"\\tlname VARCHAR(30),\\n\" +\n                \"\\thired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"\\tseparated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"\\tjob_code INT,\\n\" +\n                \"\\tstore_id INT\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY(id)\\n\" +\n                \"TABLEGROUP group0;\", stmt.toString());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"CREATE TABLE employees (\\n\" +\n                \"    id INT NOT NULL,\\n\" +\n                \"    fname VARCHAR(30),\\n\" +\n                \"    lname VARCHAR(30),\\n\" +\n                \"    hired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"    separated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"    job_code INT,\\n\" +\n                \"    store_id INT,\\n\" +\n                \"    primary key(id)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY (id)\\n\" +\n                \"SUBPARTITION BY RANGE (YEAR(separated)) \\n\" +\n                \"(\\n\" +\n                \"    PARTITION p0 VALUES LESS THAN (1991),\\n\" +\n                \"    PARTITION p1 VALUES LESS THAN (1996),\\n\" +\n                \"    PARTITION p2 VALUES LESS THAN (2001),\\n\" +\n                \"    PARTITION p3 VALUES LESS THAN MAXVALUE\\n\" +\n                \")\\n\" +\n                \"tablegroup group0;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE employees (\\n\" +\n                \"\\tid INT NOT NULL,\\n\" +\n                \"\\tfname VARCHAR(30),\\n\" +\n                \"\\tlname VARCHAR(30),\\n\" +\n                \"\\thired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"\\tseparated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"\\tjob_code INT,\\n\" +\n                \"\\tstore_id INT,\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY(id)\\n\" +\n                \"SUBPARTITION BY RANGE  (\\n\" +\n                \"\\tPARTITION p0 VALUES LESS THAN (1991),\\n\" +\n                \"\\tPARTITION p1 VALUES LESS THAN (1996),\\n\" +\n                \"\\tPARTITION p2 VALUES LESS THAN (2001),\\n\" +\n                \"\\tPARTITION p3 VALUES LESS THAN MAXVALUE\\n\" +\n                \")\\n\" +\n                \"TABLEGROUP group0;\", stmt.toString());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"CREATE TABLE employees (\\n\" +\n                \"    id INT NOT NULL,\\n\" +\n                \"    fname VARCHAR(30),\\n\" +\n                \"    lname VARCHAR(30),\\n\" +\n                \"    hired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"    separated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"    job_code INT,\\n\" +\n                \"    store_id INT,\\n\" +\n                \"    primary key(id)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY (id)\\n\" +\n                \"SUBPARTITION BY LIST(store_id) (\\n\" +\n                \"    PARTITION pNorth VALUES IN (3,5,6,9,17),\\n\" +\n                \"    PARTITION pEast VALUES IN (1,2,10,11,19,20),\\n\" +\n                \"    PARTITION pWest VALUES IN (4,12,13,14,18),\\n\" +\n                \"    PARTITION pCentral VALUES IN (7,8,15,16)\\n\" +\n                \")\\n\" +\n                \"tablegroup group0;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE employees (\\n\" +\n                \"\\tid INT NOT NULL,\\n\" +\n                \"\\tfname VARCHAR(30),\\n\" +\n                \"\\tlname VARCHAR(30),\\n\" +\n                \"\\thired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"\\tseparated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"\\tjob_code INT,\\n\" +\n                \"\\tstore_id INT,\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY(id)\\n\" +\n                \"SUBPARTITION BY LIST (store_id)  (\\n\" +\n                \"\\tPARTITION pNorth VALUES IN (3, 5, 6, 9, 17),\\n\" +\n                \"\\tPARTITION pEast VALUES IN (1, 2, 10, 11, 19, 20),\\n\" +\n                \"\\tPARTITION pWest VALUES IN (4, 12, 13, 14, 18),\\n\" +\n                \"\\tPARTITION pCentral VALUES IN (7, 8, 15, 16)\\n\" +\n                \")\\n\" +\n                \"TABLEGROUP group0;\", stmt.toString());\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"CREATE TABLE employees (\\n\" +\n                \"    id INT NOT NULL,\\n\" +\n                \"    fname VARCHAR(30),\\n\" +\n                \"    lname VARCHAR(30),\\n\" +\n                \"    hired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"    separated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"    job_code INT,\\n\" +\n                \"    store_id INT,\\n\" +\n                \"    close INT,\\n\" +\n                \"    primary key(id)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY (id)\\n\" +\n                \"SUBPARTITION BY LIST (store_id) (\\n\" +\n                \"    SUBPARTITION pNorth VALUES IN (3,5,6,9,17),\\n\" +\n                \"    SUBPARTITION pEast VALUES IN (1,2,10,11,19,20),\\n\" +\n                \"    SUBPARTITION pWest VALUES IN (4,12,13,14,18),\\n\" +\n                \"    SUBPARTITION pCentral VALUES IN (7,8,15,16)\\n\" +\n                \")\\n\" +\n                \"tablegroup group0;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE employees (\\n\" +\n                \"\\tid INT NOT NULL,\\n\" +\n                \"\\tfname VARCHAR(30),\\n\" +\n                \"\\tlname VARCHAR(30),\\n\" +\n                \"\\thired DATE NOT NULL DEFAULT '1970-01-01',\\n\" +\n                \"\\tseparated DATE NOT NULL DEFAULT '9999-12-31',\\n\" +\n                \"\\tjob_code INT,\\n\" +\n                \"\\tstore_id INT,\\n\" +\n                \"\\tclose INT,\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY(id)\\n\" +\n                \"SUBPARTITION BY LIST (store_id)  (\\n\" +\n                \"\\tPARTITION pNorth VALUES IN (3, 5, 6, 9, 17),\\n\" +\n                \"\\tPARTITION pEast VALUES IN (1, 2, 10, 11, 19, 20),\\n\" +\n                \"\\tPARTITION pWest VALUES IN (4, 12, 13, 14, 18),\\n\" +\n                \"\\tPARTITION pCentral VALUES IN (7, 8, 15, 16)\\n\" +\n                \")\\n\" +\n                \"TABLEGROUP group0;\", stmt.toString());\n    }\n\n    public void test_create_table_as() {\n        String sql = \"CREATE TABLE triangle (\\n\" +\n                \"  sidea DOUBLE,\\n\" +\n                \"  sideb DOUBLE,\\n\" +\n                \"  sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))\\n\" +\n                \");\";\n\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE TABLE triangle (\\n\" +\n                \"\\tsidea DOUBLE,\\n\" +\n                \"\\tsideb DOUBLE,\\n\" +\n                \"\\tsidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))\\n\" +\n                \");\", stmt.toString());\n    }\n\n    public void test_create_table_new() {\n        String sql = \"select label from t\";\n\n        SQLStatement statement = SQLUtils.parseSingleMysqlStatement(sql);\n\n        System.out.println(statement.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest13.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest13 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `xx_video` (\" +\n                \"`id` int(11) NOT NULL AUTO_INCREMENT,\" +\n                \"`video_url` varchar(500) DEFAULT NULL,\" +\n                \"`video_title` varchar(200) DEFAULT NULL,\" +\n                \"`video_des` varchar(500) DEFAULT NULL,\" +\n                \"`video_type` varchar(11) NOT NULL,\" +\n                \"`delete_flag` int(11) DEFAULT '0',\" +\n                \"`create_date` datetime DEFAULT NULL,\" +\n                \"`last_update` datetime DEFAULT NULL,\" +\n                \"PRIMARY KEY (`id`)\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=gbk;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(8, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"xx_video\")));\n\n        assertTrue(visitor.containsColumn(\"xx_video\", \"id\"));\n        assertTrue(visitor.containsColumn(\"xx_video\", \"video_url\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest130_ads.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest130_ads extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS hm_crm.crm_wdk_hm_store_poi_di\\n\" +\n                \"(\\n\" +\n                \"    shop_id    BIGINT COMMENT '店铺id',\\n\" +\n                \"    poi_type   BIGINT COMMENT '0：家 1： 工作',\\n\" +\n                \"    poi        VARCHAR COMMENT 'poi信息',\\n\" +\n                \"    user_count BIGINT COMMENT '用户量'\\n\" +\n                \")\\n\" +\n                \"PARTITION BY HASH KEY (shop_id) PARTITION NUM 250\\n\" +\n                \"SUBPARTITION BY LIST KEY (biz_date long)\\n\" +\n                \"SUBPARTITION OPTIONS (available_partition_num = 1)\\n\" +\n                \"TABLEGROUP crm_platform_filter\\n\" +\n                \"OPTIONS (UPDATETYPE='batch')\\n\" +\n                \"COMMENT '店铺poi数据'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS hm_crm.crm_wdk_hm_store_poi_di (\\n\" +\n                \"\\tshop_id BIGINT COMMENT '店铺id',\\n\" +\n                \"\\tpoi_type BIGINT COMMENT '0：家 1： 工作',\\n\" +\n                \"\\tpoi VARCHAR COMMENT 'poi信息',\\n\" +\n                \"\\tuser_count BIGINT COMMENT '用户量'\\n\" +\n                \")\\n\" +\n                \"OPTIONS (UPDATETYPE = 'batch') COMMENT '店铺poi数据'\\n\" +\n                \"PARTITION BY HASH KEY(shop_id) PARTITION NUM 250\\n\" +\n                \"SUBPARTITION BY LIST KEY (biz_date) \\n\" +\n                \"SUBPARTITION OPTIONS (available_partition_num = 1)\\n\" +\n                \"TABLEGROUP crm_platform_filter\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest131_drds.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest131_drds extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE shard_hot_test_table (\\n\" +\n                \" id int(11) NOT NULL AUTO_INCREMENT BY GROUP,\\n\" +\n                \" name varchar(30) DEFAULT NULL,\\n\" +\n                \" gmt_create datetime(3) DEFAULT NULL, PRIMARY KEY (id), KEY auto_shard_key_name (name) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(name) dbpartitions 8 tbpartition by hash(name) tbpartitions 64 extpartition( dbpartition HOT_TEST_ERROR_TIPS_1544416881653EDSX_Z4MU_0000_HOT by key('aaa') tbpartition shard_hot_test_table_aaa_table by key('aaa'), dbpartition HOT_TEST_ERROR_TIPS_1544416881653EDSX_Z4MU_0001_HOT by key('bbb')\\n\" +\n                \" tbpartition shard_hot_test_table_bbb_table by key('bbb') )\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE shard_hot_test_table (\\n\" +\n                \"\\tid int(11) NOT NULL AUTO_INCREMENT BY GROUP,\\n\" +\n                \"\\tname varchar(30) DEFAULT NULL,\\n\" +\n                \"\\tgmt_create datetime(3) DEFAULT NULL,\\n\" +\n                \"\\tPRIMARY KEY (id),\\n\" +\n                \"\\tKEY auto_shard_key_name USING BTREE (name)\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8\\n\" +\n                \"DBPARTITION BY hash(name) DBPARTITIONS 8\\n\" +\n                \"TBPARTITION BY hash(name) TBPARTITIONS 64\\n\" +\n                \"EXTPARTITION (\\n\" +\n                \"\\tDBPARTITION HOT_TEST_ERROR_TIPS_1544416881653EDSX_Z4MU_0000_HOT BY key('aaa') TBPARTITION shard_hot_test_table_aaa_table BY key('aaa'), \\n\" +\n                \"\\tDBPARTITION HOT_TEST_ERROR_TIPS_1544416881653EDSX_Z4MU_0001_HOT BY key('bbb') TBPARTITION shard_hot_test_table_bbb_table BY key('bbb')\\n\" +\n                \")\", stmt.toString());\n\n        SQLColumnDefinition id = stmt.getColumn(\"ID\");\n        assertNotNull(id);\n        assertTrue(id.isPrimaryKey());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest132_drds_primaryKey.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest132_drds_primaryKey extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table gxw_test_87 (id int, name varchar(20),  primary key(id, name)) dbpartition by hash(id);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE gxw_test_87 (\\n\" +\n                \"\\tid int,\\n\" +\n                \"\\tname varchar(20),\\n\" +\n                \"\\tPRIMARY KEY (id, name)\\n\" +\n                \")\\n\" +\n                \"DBPARTITION BY hash(id);\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest133_drds_gsi.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.apache.commons.lang3.StringUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest133_drds_gsi extends MysqlTest {\n    // Constraint XXX may not show in parsed sql, so removed it.\n    private static final String CREATE_TABLE_BASE = \"CREATE TABLE IF NOT EXISTS `full_type_table` (\\n\"\n            + \"\\tpk INT NOT NULL PRIMARY KEY AUTO_INCREMENT,\\n\"\n            + \"\\tid1 INT,\\n\" + \"\\tid2 INT,\\n\"\n            + \"\\tid3 VARCHAR(100),\\n\" + \"\\tvc1 VARCHAR(100),\\n\"\n            + \"\\tvc3 VARCHAR(100),\\n\"\n            + \"\\tINDEX idx1 USING HASH(id1),\\n\"\n            + \"\\tKEY idx2 USING HASH (id2),\\n\"\n            + \"\\tFULLTEXT KEY idx4 (id3(20)),\\n\"\n            + \"\\tUNIQUE idx3 USING BTREE (vc1(20))\";\n    private static final String CREATE_TABLE_TAIL = \"\\n) ENGINE = INNODB AUTO_INCREMENT = 2 AVG_ROW_LENGTH = 100 \"\n            + \"CHARACTER SET = utf8 COLLATE = utf8_bin CHECKSUM = 0 COMMENT 'abcd'\\n\"\n            + \"DBPARTITION BY HASH(id1);\";\n\n    private static final String FULL_TYPE_TABLE = CREATE_TABLE_BASE + CREATE_TABLE_TAIL;\n\n    private static final List<String> GSI_DEFINITIONS = new ArrayList<String>();\n\n    private static final List<String> GSI_DEF_HEAD = new ArrayList<String>();\n    private static final List<String> GSI_DEF_COLUMN_DB = new ArrayList<String>();\n    private static final List<String> GSI_DEF_COLUMN_TB = new ArrayList<String>();\n    private static final List<String> GSI_DEF_SHARDING_DB = new ArrayList<String>();\n    private static final List<String> GSI_DEF_SHARDING_TB = new ArrayList<String>();\n    private static final List<String> GSI_DEF_INDEX_OPTION = new ArrayList<String>();\n\n    static {\n        GSI_DEF_HEAD.add(\"GLOBAL INDEX\");\n        GSI_DEF_HEAD.add(\"UNIQUE GLOBAL\");\n        // GSI_DEF_HEAD.add(\"GLOBAL UNIQUE INDEX\");\n\n        GSI_DEF_COLUMN_DB.add(\"gsi_id2(id2)\");\n        GSI_DEF_COLUMN_DB.add(\"gsi_id2(id2) COVERING (vc1)\");\n        GSI_DEF_COLUMN_DB.add(\"gsi_id2(id2) COVERING (vc1, vc2)\");\n\n        GSI_DEF_COLUMN_TB.add(\"gsi_id2(id2, id3)\");\n        GSI_DEF_COLUMN_TB.add(\"gsi_id2(id2, id3) COVERING (vc1)\");\n        GSI_DEF_COLUMN_TB.add(\"gsi_id2(id2, id3) COVERING (vc1, vc2)\");\n        GSI_DEF_COLUMN_TB.add(\"gsi_id2 USING HASH(id2, id3) COVERING (vc1, vc2)\");\n\n        GSI_DEF_SHARDING_DB.add(\"DBPARTITION BY HASH(id2)\");\n        GSI_DEF_SHARDING_DB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY HASH(id2) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_DB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY MM(id2) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_DB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY DD(id2) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_DB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY WEEK(id2) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_DB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY MMDD(id2) TBPARTITIONS 3\");\n\n        GSI_DEF_SHARDING_TB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY HASH(id3) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_TB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY MM(id3) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_TB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY DD(id3) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_TB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY WEEK(id3) TBPARTITIONS 3\");\n        GSI_DEF_SHARDING_TB.add(\"DBPARTITION BY HASH(id2) TBPARTITION BY MMDD(id3) TBPARTITIONS 3\");\n\n        GSI_DEF_INDEX_OPTION.add(\"\");\n        GSI_DEF_INDEX_OPTION.add(\"COMMENT 'gsi test'\");\n\n        for (String head : GSI_DEF_HEAD) {\n            for (String option : GSI_DEF_INDEX_OPTION) {\n                for (String column : GSI_DEF_COLUMN_DB) {\n                    buildGsiDef(head, option, column, GSI_DEF_SHARDING_DB);\n                }\n\n                for (String column : GSI_DEF_COLUMN_TB) {\n                    buildGsiDef(head, option, column, GSI_DEF_SHARDING_TB);\n                }\n            }\n        }\n    }\n\n    private static void buildGsiDef(String head, String option, String column, List<String> gsiDefShardingDb) {\n        for (String sharding : gsiDefShardingDb) {\n            GSI_DEFINITIONS.add(\"\\t\" + head + \" \" + column + \" \" + sharding + (StringUtils.isBlank(option) ? \"\" : \" \")\n                    + option);\n        }\n    }\n\n    private static void checkExplain(final String sql) {\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n        String a = StringUtils.replace(sql, \" \", \"\");\n        String b = StringUtils.replace(stmt.toString(), \" \", \"\");\n        assertEquals(a, b);\n    }\n\n    @Test\n    public void test() {\n        List<Throwable> errors = new ArrayList<Throwable>();\n        List<String> errorGsiDefs = new ArrayList<String>();\n        for (String gsiDef : GSI_DEFINITIONS) {\n            final StringBuilder sqlBuilder = new StringBuilder(CREATE_TABLE_BASE);\n\n            sqlBuilder.append(\",\\n\").append(gsiDef);\n\n            sqlBuilder.append(CREATE_TABLE_TAIL);\n            try {\n                checkExplain(sqlBuilder.toString());\n            } catch (Throwable e) {\n                // System.out.println(e.getMessage());\n                System.out.println(sqlBuilder.toString());\n                e.printStackTrace();\n                errors.add(e);\n                errorGsiDefs.add(gsiDef);\n            }\n        }\n\n        if (errors.size() > 0) {\n            for (String e : errorGsiDefs) {\n                System.out.println(e);\n            }\n            fail(errors.size() + \" out of \" + GSI_DEFINITIONS.size() + \" CREATE TABLE statement failed\");\n        } else {\n            System.out.println(GSI_DEFINITIONS.size() + \" CREATE TABLE statement success!\");\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest134.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest134 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table xuhan3(\\n\" +\n                \"id int not null AUTO_INCREMENT primary key, \\n\" +\n                \"name char(40), SimpleDate date, \\n\" +\n                \"SimpleDate_dayofweek tinyint(4) GENERATED ALWAYS AS (dayofweek(SimpleDate)) VIRTUAL, \\n\" +\n                \"KEY SimpleDate_dayofweek (SimpleDate_dayofweek));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE xuhan3 (\\n\" +\n                \"\\tid int NOT NULL PRIMARY KEY AUTO_INCREMENT,\\n\" +\n                \"\\tname char(40),\\n\" +\n                \"\\tSimpleDate date,\\n\" +\n                \"\\tSimpleDate_dayofweek tinyint(4) GENERATED ALWAYS AS (dayofweek(SimpleDate)) VIRTUAL,\\n\" +\n                \"\\tKEY SimpleDate_dayofweek (SimpleDate_dayofweek)\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table xuhan3 (\\n\" +\n                \"\\tid int not null primary key auto_increment,\\n\" +\n                \"\\tname char(40),\\n\" +\n                \"\\tSimpleDate date,\\n\" +\n                \"\\tSimpleDate_dayofweek tinyint(4) generated always as (dayofweek(SimpleDate)) virtual,\\n\" +\n                \"\\tkey SimpleDate_dayofweek (SimpleDate_dayofweek)\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest135.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @author Dagon0577\n * @date 2020/5/14 10:51\n */\npublic class MySqlCreateTableTest135 {\n    @Test\n    public void test_0() throws Exception {\n        String sql =\n                \"create table MQ_TOPIC_RECORD(\\n\"\n                        + \"   TOPIC_ID             bigint(11) not null,\\n\"\n                        + \"   BROKENNAME           national VARCHAR(50),\\n\"\n                        + \"   BROKENNAME2           national CHAR(50)\\n\" + \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE MQ_TOPIC_RECORD (\\n\" +\n                \"\\tTOPIC_ID bigint(11) NOT NULL,\\n\" +\n                \"\\tBROKENNAME national VARCHAR(50),\\n\" +\n                \"\\tBROKENNAME2 national CHAR(50)\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table MQ_TOPIC_RECORD (\\n\" +\n                \"\\tTOPIC_ID bigint(11) not null,\\n\" +\n                \"\\tBROKENNAME national VARCHAR(50),\\n\" +\n                \"\\tBROKENNAME2 national CHAR(50)\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest135_isString.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest135_isString extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table t(\\n\" +\n                \"f1 varchar(50), \\n\" +\n                \"f2 string, \\n\" +\n                \"f3 clob, \\n\" +\n                \"f4 nclob, \\n\" +\n                \"f5 nvarchar(50), \\n\" +\n                \"f6 text \\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        for (SQLColumnDefinition item : stmt.getColumnDefinitions()) {\n            assertTrue(item.getDataType().isString());\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest136.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest136 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `c1` (\\n\" +\n                \"        `id` bigint NOT NULL AUTO_INCREMENT,\\n\" +\n                \"        `d` int DEFAULT 1,\\n\" +\n                \"        `b` varchar(100) DEFAULT '123',\\n\" +\n                \"        PRIMARY KEY (`id`),\\n\" +\n                \"    key idxa2(`d`,`b`) comment '2'\\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `c1` (\\n\" +\n                \"\\t`id` bigint NOT NULL AUTO_INCREMENT,\\n\" +\n                \"\\t`d` int DEFAULT 1,\\n\" +\n                \"\\t`b` varchar(100) DEFAULT '123',\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tKEY idxa2 (`d`, `b`) COMMENT '2'\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table `c1` (\\n\" +\n                \"\\t`id` bigint not null auto_increment,\\n\" +\n                \"\\t`d` int default 1,\\n\" +\n                \"\\t`b` varchar(100) default '123',\\n\" +\n                \"\\tprimary key (`id`),\\n\" +\n                \"\\tkey idxa2 (`d`, `b`) comment '2'\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest137.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLCommentHint;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest137 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `c1` (\\n\" +\n                \"        order bigint);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `c1` (\\n\" +\n                \"\\torder bigint\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table `c1` (\\n\" +\n                \"\\torder bigint\\n\" +\n                \");\", stmt.toLowerCaseString());\n\n        SQLUtils.parseSingleMysqlStatement(\"insert into w (order) values (1)\");\n        SQLUtils.parseSingleMysqlStatement(\"select order from w1 where order = 1\");\n    }\n\n    public void test_1() throws Exception {\n        SQLUtils.parseSingleMysqlStatement(\"create table order (fid bigint)\");\n        SQLUtils.parseSingleMysqlStatement(\"insert into order (f1) values (1)\");\n        SQLStatement stmt = SQLUtils.parseSingleMysqlStatement(\"/*+engine=mpp*/select f1 from pt_dc.order where f1 = 1\");\n        List<SQLCommentHint> hints = stmt.getHeadHintsDirect();\n        System.out.println(hints);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest138.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest138 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `t_push_branch3` (\\n\" +\n                \"  `id` varchar(50) NOT NULL COMMENT '主键id',\\n\" +\n                \"  `waybill_no` varchar(50) DEFAULT NULL COMMENT '运单号',\\n\" +\n                \"  `bill_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '开单时间',\\n\" +\n                \"  `create_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',\\n\" +\n                \"  PRIMARY KEY (`id`,`create_time`),\\n\" +\n                \"  KEY `index_waybill_no` (`waybill_no`),\\n\" +\n                \"  KEY `index_create_time` (`create_time`)\\n\" +\n                \") ENGINE=InnoDB COMMENT='网点剔除表'\\n\" +\n                \"PARTITION BY RANGE  COLUMNS(create_time)\\n\" +\n                \"(PARTITION P201812 VALUES LESS THAN ('2019-01-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201901 VALUES LESS THAN ('2019-02-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201902 VALUES LESS THAN ('2019-03-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201903 VALUES LESS THAN ('2019-04-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201904 VALUES LESS THAN ('2019-05-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201905 VALUES LESS THAN ('2019-06-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201906 VALUES LESS THAN ('2019-07-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201907 VALUES LESS THAN ('2019-08-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201908 VALUES LESS THAN ('2019-09-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201909 VALUES LESS THAN ('2019-10-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201910 VALUES LESS THAN ('2019-11-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201911 VALUES LESS THAN ('2019-12-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION P201912 VALUES LESS THAN ('2020-01-01') ENGINE = InnoDB,\\n\" +\n                \" PARTITION PMAX VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `t_push_branch3` (\\n\" +\n                \"\\t`id` varchar(50) NOT NULL COMMENT '主键id',\\n\" +\n                \"\\t`waybill_no` varchar(50) DEFAULT NULL COMMENT '运单号',\\n\" +\n                \"\\t`bill_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '开单时间',\\n\" +\n                \"\\t`create_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',\\n\" +\n                \"\\tPRIMARY KEY (`id`, `create_time`),\\n\" +\n                \"\\tKEY `index_waybill_no` (`waybill_no`),\\n\" +\n                \"\\tKEY `index_create_time` (`create_time`)\\n\" +\n                \") ENGINE = InnoDB COMMENT '网点剔除表'\\n\" +\n                \"PARTITION BY RANGE COLUMNS (create_time) (\\n\" +\n                \"\\tPARTITION P201812 VALUES LESS THAN ('2019-01-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201901 VALUES LESS THAN ('2019-02-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201902 VALUES LESS THAN ('2019-03-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201903 VALUES LESS THAN ('2019-04-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201904 VALUES LESS THAN ('2019-05-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201905 VALUES LESS THAN ('2019-06-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201906 VALUES LESS THAN ('2019-07-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201907 VALUES LESS THAN ('2019-08-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201908 VALUES LESS THAN ('2019-09-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201909 VALUES LESS THAN ('2019-10-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201910 VALUES LESS THAN ('2019-11-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201911 VALUES LESS THAN ('2019-12-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION P201912 VALUES LESS THAN ('2020-01-01')\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB,\\n\" +\n                \"\\tPARTITION PMAX VALUES LESS THAN MAXVALUE\\n\" +\n                \"\\t\\tSTORAGE ENGINE InnoDB\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table `t_push_branch3` (\\n\" +\n                \"\\t`id` varchar(50) not null comment '主键id',\\n\" +\n                \"\\t`waybill_no` varchar(50) default null comment '运单号',\\n\" +\n                \"\\t`bill_time` datetime default null on update current_timestamp comment '开单时间',\\n\" +\n                \"\\t`create_time` datetime not null on update current_timestamp comment '创建时间',\\n\" +\n                \"\\tprimary key (`id`, `create_time`),\\n\" +\n                \"\\tkey `index_waybill_no` (`waybill_no`),\\n\" +\n                \"\\tkey `index_create_time` (`create_time`)\\n\" +\n                \") engine = InnoDB comment '网点剔除表'\\n\" +\n                \"partition by range columns (create_time) (\\n\" +\n                \"\\tpartition P201812 values less than ('2019-01-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201901 values less than ('2019-02-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201902 values less than ('2019-03-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201903 values less than ('2019-04-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201904 values less than ('2019-05-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201905 values less than ('2019-06-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201906 values less than ('2019-07-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201907 values less than ('2019-08-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201908 values less than ('2019-09-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201909 values less than ('2019-10-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201910 values less than ('2019-11-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201911 values less than ('2019-12-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition P201912 values less than ('2020-01-01')\\n\" +\n                \"\\t\\tstorage engine InnoDB,\\n\" +\n                \"\\tpartition PMAX values less than maxvalue\\n\" +\n                \"\\t\\tstorage engine InnoDB\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest139.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest139 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \" CREATE TABLE IF NOT EXISTS simiao_alter_partition2 (id int, id2 int, name varchar(30), time timestamp NOT NULL, PRIMARY KEY (id, time), KEY idx_id_time USING BTREE (id, time)) PARTITION BY RANGE (UNIX_TIMESTAMP(time))( PARTITION p0 VALUES LESS THAN (UNIX_TIMESTAMP('2013-01-01 00:00:00')), PARTITION p1 VALUES LESS THAN (UNIX_TIMESTAMP('2013-02-01 00:00:00')), PARTITION p2 VALUES LESS THAN (UNIX_TIMESTAMP('2013-03-01 00:00:00')), PARTITION p3 VALUES LESS THAN (UNIX_TIMESTAMP('2013-04-01 00:00:00')), PARTITION p4 VALUES LESS THAN (UNIX_TIMESTAMP('2013-05-01 00:00:00')), PARTITION p5 VALUES LESS THAN (UNIX_TIMESTAMP('2013-06-01 00:00:00')), PARTITION p6 VALUES LESS THAN (UNIX_TIMESTAMP('2013-07-01 00:00:00')), PARTITION p7 VALUES LESS THAN (UNIX_TIMESTAMP('2013-08-01 00:00:00')), PARTITION p8 VALUES LESS THAN (UNIX_TIMESTAMP('2013-09-01 00:00:00')), PARTITION p10 VALUES LESS THAN (UNIX_TIMESTAMP('2013-10-01 00:00:00')), PARTITION p11 VALUES LESS THAN (UNIX_TIMESTAMP('2013-11-01 00:00:00')), PARTITION p12 VALUES LESS THAN (UNIX_TIMESTAMP('2013-12-01 00:00:00')), PARTITION p13 VALUES LESS THAN (MAXVALUE) ) dbpartition by hash(id) dbpartitions 4;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE IF NOT EXISTS simiao_alter_partition2 (\\n\" +\n                \"\\tid int,\\n\" +\n                \"\\tid2 int,\\n\" +\n                \"\\tname varchar(30),\\n\" +\n                \"\\ttime timestamp NOT NULL,\\n\" +\n                \"\\tPRIMARY KEY (id, time),\\n\" +\n                \"\\tKEY idx_id_time USING BTREE (id, time)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY RANGE (UNIX_TIMESTAMP(time)) (\\n\" +\n                \"\\tPARTITION p0 VALUES LESS THAN (UNIX_TIMESTAMP('2013-01-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p1 VALUES LESS THAN (UNIX_TIMESTAMP('2013-02-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p2 VALUES LESS THAN (UNIX_TIMESTAMP('2013-03-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p3 VALUES LESS THAN (UNIX_TIMESTAMP('2013-04-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p4 VALUES LESS THAN (UNIX_TIMESTAMP('2013-05-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p5 VALUES LESS THAN (UNIX_TIMESTAMP('2013-06-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p6 VALUES LESS THAN (UNIX_TIMESTAMP('2013-07-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p7 VALUES LESS THAN (UNIX_TIMESTAMP('2013-08-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p8 VALUES LESS THAN (UNIX_TIMESTAMP('2013-09-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p10 VALUES LESS THAN (UNIX_TIMESTAMP('2013-10-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p11 VALUES LESS THAN (UNIX_TIMESTAMP('2013-11-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p12 VALUES LESS THAN (UNIX_TIMESTAMP('2013-12-01 00:00:00')),\\n\" +\n                \"\\tPARTITION p13 VALUES LESS THAN MAXVALUE\\n\" +\n                \")\\n\" +\n                \"DBPARTITION BY hash(id) DBPARTITIONS 4;\", stmt.toString());\n\n        assertEquals(\"create table if not exists simiao_alter_partition2 (\\n\" +\n                \"\\tid int,\\n\" +\n                \"\\tid2 int,\\n\" +\n                \"\\tname varchar(30),\\n\" +\n                \"\\ttime timestamp not null,\\n\" +\n                \"\\tprimary key (id, time),\\n\" +\n                \"\\tkey idx_id_time using BTREE (id, time)\\n\" +\n                \")\\n\" +\n                \"partition by range (UNIX_TIMESTAMP(time)) (\\n\" +\n                \"\\tpartition p0 values less than (UNIX_TIMESTAMP('2013-01-01 00:00:00')),\\n\" +\n                \"\\tpartition p1 values less than (UNIX_TIMESTAMP('2013-02-01 00:00:00')),\\n\" +\n                \"\\tpartition p2 values less than (UNIX_TIMESTAMP('2013-03-01 00:00:00')),\\n\" +\n                \"\\tpartition p3 values less than (UNIX_TIMESTAMP('2013-04-01 00:00:00')),\\n\" +\n                \"\\tpartition p4 values less than (UNIX_TIMESTAMP('2013-05-01 00:00:00')),\\n\" +\n                \"\\tpartition p5 values less than (UNIX_TIMESTAMP('2013-06-01 00:00:00')),\\n\" +\n                \"\\tpartition p6 values less than (UNIX_TIMESTAMP('2013-07-01 00:00:00')),\\n\" +\n                \"\\tpartition p7 values less than (UNIX_TIMESTAMP('2013-08-01 00:00:00')),\\n\" +\n                \"\\tpartition p8 values less than (UNIX_TIMESTAMP('2013-09-01 00:00:00')),\\n\" +\n                \"\\tpartition p10 values less than (UNIX_TIMESTAMP('2013-10-01 00:00:00')),\\n\" +\n                \"\\tpartition p11 values less than (UNIX_TIMESTAMP('2013-11-01 00:00:00')),\\n\" +\n                \"\\tpartition p12 values less than (UNIX_TIMESTAMP('2013-12-01 00:00:00')),\\n\" +\n                \"\\tpartition p13 values less than maxvalue\\n\" +\n                \")\\n\" +\n                \"dbpartition by hash(id) dbpartitions 4;\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest14.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest14 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \" CREATE TABLE `OptionList` ( \" +\n                \"`ID` int(11) NOT NULL AUTO_INCREMENT, \" +\n                \"`OptionID` int(11) DEFAULT NULL COMMENT '选项ID', \" +\n                \"`QuizID` int(11) DEFAULT NULL COMMENT '竞猜题目ID', \" +\n                \"`OptionName` varchar(500) DEFAULT NULL COMMENT '选项名称', \" +\n                \"`OptionCount` int(11) DEFAULT NULL COMMENT '选择的人数', \" +\n                \"PRIMARY KEY (`ID`), KEY `quizId` (`QuizID`) USING BTREE, \" +\n                \"KEY `optionId` (`OptionID`) USING BTREE\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=gbk COMMENT=''\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"CREATE TABLE `OptionList` (\"\n                        + \"\\n\\t`ID` int(11) NOT NULL AUTO_INCREMENT,\"\n                        + \"\\n\\t`OptionID` int(11) DEFAULT NULL COMMENT '选项ID',\"\n                        + \"\\n\\t`QuizID` int(11) DEFAULT NULL COMMENT '竞猜题目ID',\"\n                        + \"\\n\\t`OptionName` varchar(500) DEFAULT NULL COMMENT '选项名称',\"\n                        + \"\\n\\t`OptionCount` int(11) DEFAULT NULL COMMENT '选择的人数',\"\n                        + \"\\n\\tPRIMARY KEY (`ID`),\"\n                        + \"\\n\\tKEY `quizId` USING BTREE (`QuizID`),\"\n                        + \"\\n\\tKEY `optionId` USING BTREE (`OptionID`)\"\n                        + \"\\n) ENGINE = InnoDB CHARSET = gbk COMMENT ''\", //\n                SQLUtils.toMySqlString(stmt));\n        assertEquals(\"create table `OptionList` (\"\n                        + \"\\n\\t`ID` int(11) not null auto_increment,\"\n                        + \"\\n\\t`OptionID` int(11) default null comment '选项ID',\"\n                        + \"\\n\\t`QuizID` int(11) default null comment '竞猜题目ID',\"\n                        + \"\\n\\t`OptionName` varchar(500) default null comment '选项名称',\"\n                        + \"\\n\\t`OptionCount` int(11) default null comment '选择的人数',\"\n                        + \"\\n\\tprimary key (`ID`),\"\n                        + \"\\n\\tkey `quizId` using BTREE (`QuizID`),\"\n                        + \"\\n\\tkey `optionId` using BTREE (`OptionID`)\"\n                        + \"\\n) engine = InnoDB charset = gbk comment ''\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"OptionList\")));\n\n        assertTrue(visitor.containsColumn(\"OptionList\", \"ID\"));\n        assertTrue(visitor.containsColumn(\"OptionList\", \"OptionCount\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest140.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest140 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE foo AS SELECT * FROM t WITH NO DATA\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE foo\\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM t\\n\" +\n                \"WITH NO DATA\", stmt.toString());\n\n        assertEquals(\"create table foo\\n\" +\n                \"as\\n\" +\n                \"select *\\n\" +\n                \"from t\\n\" +\n                \"with no data\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest141.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest141 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE sbtest1 (\\n\" +\n                \"id INTEGER UNSIGNED NOT NULL ,\\n\" +\n                \"k INTEGER UNSIGNED DEFAULT '0' NOT NULL,\\n\" +\n                \"c CHAR(120) DEFAULT '' NOT NULL,\\n\" +\n                \"pad CHAR(60) DEFAULT '' NOT NULL,\\n\" +\n                \"KEY xid (id)\\n\" +\n                \") /*! ENGINE = innodb MAX_ROWS = 1000000 */  dbpartition by hash(id) tbpartition by hash(id) tbpartitions 2\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE sbtest1 (\\n\" +\n                \"\\tid INTEGER UNSIGNED NOT NULL,\\n\" +\n                \"\\tk INTEGER UNSIGNED NOT NULL DEFAULT '0',\\n\" +\n                \"\\tc CHAR(120) NOT NULL DEFAULT '',\\n\" +\n                \"\\tpad CHAR(60) NOT NULL DEFAULT '',\\n\" +\n                \"\\tKEY xid (id)\\n\" +\n                \")\\n\" +\n                \"DBPARTITION BY hash(id)\\n\" +\n                \"TBPARTITION BY hash(id) TBPARTITIONS 2\", stmt.toString());\n\n        assertEquals(\"create table sbtest1 (\\n\" +\n                \"\\tid INTEGER unsigned not null,\\n\" +\n                \"\\tk INTEGER unsigned not null default '0',\\n\" +\n                \"\\tc CHAR(120) not null default '',\\n\" +\n                \"\\tpad CHAR(60) not null default '',\\n\" +\n                \"\\tkey xid (id)\\n\" +\n                \")\\n\" +\n                \"dbpartition by hash(id)\\n\" +\n                \"tbpartition by hash(id) tbpartitions 2\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest142.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest142 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `think_member_discount` (\\n\" +\n                \" `id`  bigint , \\n\" +\n                \" `uid`  bigint , \\n\" +\n                \" `config_id`  int(10) , \\n\" +\n                \" `cou_validity_time`  bigint(20) , \\n\" +\n                \" `order_id`  int(10) , \\n\" +\n                \" `config_order_type`  int(3) , \\n\" +\n                \" `use_order_type`  int(3) , \\n\" +\n                \" `platform`  int(5) , \\n\" +\n                \" `condition`  int(10) , \\n\" +\n                \" `consequence`  int(10) , \\n\" +\n                \" `is_use`  tinyint(3) , \\n\" +\n                \" `create_time`  bigint(20) , \\n\" +\n                \" `update_time`  bigint(20) , \\n\" +\n                \" `status`  tinyint(3) , \\n\" +\n                \" `unlock_time`  bigint , \\n\" +\n                \" `type`  smallint \\n\" +\n                \", primary key (id) )  PARTITION BY hash key(id)\\n\" +\n                \" PARTITION NUM 128\\n\" +\n                \" TABLEGROUP mkzhan options (updateType='realtime') \";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `think_member_discount` (\\n\" +\n                \"\\t`id` bigint,\\n\" +\n                \"\\t`uid` bigint,\\n\" +\n                \"\\t`config_id` int(10),\\n\" +\n                \"\\t`cou_validity_time` bigint(20),\\n\" +\n                \"\\t`order_id` int(10),\\n\" +\n                \"\\t`config_order_type` int(3),\\n\" +\n                \"\\t`use_order_type` int(3),\\n\" +\n                \"\\t`platform` int(5),\\n\" +\n                \"\\t`condition` int(10),\\n\" +\n                \"\\t`consequence` int(10),\\n\" +\n                \"\\t`is_use` tinyint(3),\\n\" +\n                \"\\t`create_time` bigint(20),\\n\" +\n                \"\\t`update_time` bigint(20),\\n\" +\n                \"\\t`status` tinyint(3),\\n\" +\n                \"\\t`unlock_time` bigint,\\n\" +\n                \"\\t`type` smallint,\\n\" +\n                \"\\tPRIMARY KEY (id)\\n\" +\n                \")\\n\" +\n                \"OPTIONS (updateType = 'realtime')\\n\" +\n                \"PARTITION BY HASH KEY(id) PARTITION NUM 128\\n\" +\n                \"TABLEGROUP mkzhan\", stmt.toString());\n\n        assertEquals(\"create table `think_member_discount` (\\n\" +\n                \"\\t`id` bigint,\\n\" +\n                \"\\t`uid` bigint,\\n\" +\n                \"\\t`config_id` int(10),\\n\" +\n                \"\\t`cou_validity_time` bigint(20),\\n\" +\n                \"\\t`order_id` int(10),\\n\" +\n                \"\\t`config_order_type` int(3),\\n\" +\n                \"\\t`use_order_type` int(3),\\n\" +\n                \"\\t`platform` int(5),\\n\" +\n                \"\\t`condition` int(10),\\n\" +\n                \"\\t`consequence` int(10),\\n\" +\n                \"\\t`is_use` tinyint(3),\\n\" +\n                \"\\t`create_time` bigint(20),\\n\" +\n                \"\\t`update_time` bigint(20),\\n\" +\n                \"\\t`status` tinyint(3),\\n\" +\n                \"\\t`unlock_time` bigint,\\n\" +\n                \"\\t`type` smallint,\\n\" +\n                \"\\tprimary key (id)\\n\" +\n                \")\\n\" +\n                \"options (updateType = 'realtime')\\n\" +\n                \"partition by hash key(id) partition num 128\\n\" +\n                \"tablegroup mkzhan\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest143_position.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest143_position\n * @description\n * @Author zzy\n * @Date 2019-05-09 10:45\n */\npublic class MySqlCreateTableTest143_position extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `resume_position_portrait` (\\n\" +\n                \"  `resume_id` varchar(36) NOT NULL,\\n\" +\n                \"  `method` varchar(50) NOT NULL,\\n\" +\n                \"  `position` varchar(256) NOT NULL,\\n\" +\n                \"  `position_level1` longtext,\\n\" +\n                \"  `position_level2` longtext,\\n\" +\n                \"  `probability` float NOT NULL,\\n\" +\n                \"  `success` bit(1) NOT NULL,\\n\" +\n                \"  `updated` datetime(6) NOT NULL,\\n\" +\n                \"  `created` datetime DEFAULT NULL,\\n\" +\n                \"  PRIMARY KEY (`resume_id`),\\n\" +\n                \"  INDEX `IX_resume_position_portrait_probability` (`probability`) USING BTREE,\\n\" +\n                \"  KEY `IX_resume_position_portrait_method` (`method`) USING BTREE,\\n\" +\n                \"  KEY `IX_resume_position_portrait_method_probability` (`method`,`probability`) USING BTREE,\\n\" +\n                \"  KEY `IX_resume_position_portrait_position_probability` (`position`(191),`probability`) USING BTREE,\\n\" +\n                \"  KEY `ix_probability_method` (`probability`,`method`)\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 dbpartition by hash(`resume_id`) tbpartition by hash(`resume_id`) tbpartitions 4\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `resume_position_portrait` (\\n\" +\n                \"\\t`resume_id` varchar(36) NOT NULL,\\n\" +\n                \"\\t`method` varchar(50) NOT NULL,\\n\" +\n                \"\\t`position` varchar(256) NOT NULL,\\n\" +\n                \"\\t`position_level1` longtext,\\n\" +\n                \"\\t`position_level2` longtext,\\n\" +\n                \"\\t`probability` float NOT NULL,\\n\" +\n                \"\\t`success` bit(1) NOT NULL,\\n\" +\n                \"\\t`updated` datetime(6) NOT NULL,\\n\" +\n                \"\\t`created` datetime DEFAULT NULL,\\n\" +\n                \"\\tPRIMARY KEY (`resume_id`),\\n\" +\n                \"\\tINDEX `IX_resume_position_portrait_probability` USING BTREE(`probability`),\\n\" +\n                \"\\tKEY `IX_resume_position_portrait_method` USING BTREE (`method`),\\n\" +\n                \"\\tKEY `IX_resume_position_portrait_method_probability` USING BTREE (`method`, `probability`),\\n\" +\n                \"\\tKEY `IX_resume_position_portrait_position_probability` USING BTREE (`position`(191), `probability`),\\n\" +\n                \"\\tKEY `ix_probability_method` (`probability`, `method`)\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8mb4\\n\" +\n                \"DBPARTITION BY hash(`resume_id`)\\n\" +\n                \"TBPARTITION BY hash(`resume_id`) TBPARTITIONS 4\", stmt.toString());\n\n        assertEquals(\"create table `resume_position_portrait` (\\n\" +\n                \"\\t`resume_id` varchar(36) not null,\\n\" +\n                \"\\t`method` varchar(50) not null,\\n\" +\n                \"\\t`position` varchar(256) not null,\\n\" +\n                \"\\t`position_level1` longtext,\\n\" +\n                \"\\t`position_level2` longtext,\\n\" +\n                \"\\t`probability` float not null,\\n\" +\n                \"\\t`success` bit(1) not null,\\n\" +\n                \"\\t`updated` datetime(6) not null,\\n\" +\n                \"\\t`created` datetime default null,\\n\" +\n                \"\\tprimary key (`resume_id`),\\n\" +\n                \"\\tindex `IX_resume_position_portrait_probability` using BTREE(`probability`),\\n\" +\n                \"\\tkey `IX_resume_position_portrait_method` using BTREE (`method`),\\n\" +\n                \"\\tkey `IX_resume_position_portrait_method_probability` using BTREE (`method`, `probability`),\\n\" +\n                \"\\tkey `IX_resume_position_portrait_position_probability` using BTREE (`position`(191), `probability`),\\n\" +\n                \"\\tkey `ix_probability_method` (`probability`, `method`)\\n\" +\n                \") engine = InnoDB charset = utf8mb4\\n\" +\n                \"dbpartition by hash(`resume_id`)\\n\" +\n                \"tbpartition by hash(`resume_id`) tbpartitions 4\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest144_three_backtick.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest144_three_backtick\n * @description\n * @Author zzy\n * @Date 2019-05-09 14:51\n */\npublic class MySqlCreateTableTest144_three_backtick extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `dbn_product_album_info` (\\n\" +\n                \"  `id` bigint(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  `position` int(11) DEFAULT '9999',\\n\" +\n                \"  `album_id` bigint(20) DEFAULT NULL,\\n\" +\n                \"  `product_id` bigint(20) DEFAULT NULL,\\n\" +\n                \"  `goods_id` bigint(20) DEFAULT NULL,\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `FKDECFEBDE7B82325` (`product_id`),\\n\" +\n                \"  KEY `FKDECFEBD949942C0` (`album_id`),\\n\" +\n                \"  KEY ```album_id``` (`album_id`) USING BTREE,\\n\" +\n                \"  CONSTRAINT `FKDECFEBD949942C0` FOREIGN KEY (`album_id`) REFERENCES `dbn_product_album` (`id`),\\n\" +\n                \"  CONSTRAINT `FKDECFEBDE7B82325` FOREIGN KEY (`product_id`) REFERENCES `dbn_products` (`id`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=317607 DEFAULT CHARSET=utf8 COLLATE=utf8_bin\\n\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `dbn_product_album_info` (\\n\" +\n                \"\\t`id` bigint(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"\\t`position` int(11) DEFAULT '9999',\\n\" +\n                \"\\t`album_id` bigint(20) DEFAULT NULL,\\n\" +\n                \"\\t`product_id` bigint(20) DEFAULT NULL,\\n\" +\n                \"\\t`goods_id` bigint(20) DEFAULT NULL,\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tKEY `FKDECFEBDE7B82325` (`product_id`),\\n\" +\n                \"\\tKEY `FKDECFEBD949942C0` (`album_id`),\\n\" +\n                \"\\tKEY ```album_id``` USING BTREE (`album_id`),\\n\" +\n                \"\\tCONSTRAINT `FKDECFEBD949942C0` FOREIGN KEY (`album_id`) REFERENCES `dbn_product_album` (`id`),\\n\" +\n                \"\\tCONSTRAINT `FKDECFEBDE7B82325` FOREIGN KEY (`product_id`) REFERENCES `dbn_products` (`id`)\\n\" +\n                \") ENGINE = InnoDB AUTO_INCREMENT = 317607 CHARSET = utf8 COLLATE = utf8_bin\", stmt.toString());\n\n        assertEquals(\"create table `dbn_product_album_info` (\\n\" +\n                \"\\t`id` bigint(20) not null auto_increment,\\n\" +\n                \"\\t`position` int(11) default '9999',\\n\" +\n                \"\\t`album_id` bigint(20) default null,\\n\" +\n                \"\\t`product_id` bigint(20) default null,\\n\" +\n                \"\\t`goods_id` bigint(20) default null,\\n\" +\n                \"\\tprimary key (`id`),\\n\" +\n                \"\\tkey `FKDECFEBDE7B82325` (`product_id`),\\n\" +\n                \"\\tkey `FKDECFEBD949942C0` (`album_id`),\\n\" +\n                \"\\tkey ```album_id``` using BTREE (`album_id`),\\n\" +\n                \"\\tconstraint `FKDECFEBD949942C0` foreign key (`album_id`) references `dbn_product_album` (`id`),\\n\" +\n                \"\\tconstraint `FKDECFEBDE7B82325` foreign key (`product_id`) references `dbn_products` (`id`)\\n\" +\n                \") engine = InnoDB auto_increment = 317607 charset = utf8 collate = utf8_bin\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest145_tail_hint.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest145_tail_hint\n * @description\n * @Author zzy\n * @Date 2019-05-09 20:08\n */\npublic class MySqlCreateTableTest145_tail_hint extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `log_fake` (\\n\" +\n                \"  `id` varchar(37) NOT NULL COMMENT 'uuid',\\n\" +\n                \"  `merchant_id` varchar(37) DEFAULT NULL COMMENT '商户id',\\n\" +\n                \"  `type` int(11) NOT NULL COMMENT 'type字段决定payload如何解析',\\n\" +\n                \"  `payload` blob COMMENT 'payload存放以JSON格式编码的系统事件，例如订单成功支付。',\\n\" +\n                \"  `processed` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否已经处理（下游业务逻辑完成运算并更新数据或者同步到持久化的队列）',\\n\" +\n                \"  `partition` int(10) unsigned NOT NULL COMMENT '分区ID(0-999)。多线程方式处理日志记录的时候，防止同一条记录被重复处理。',\\n\" +\n                \"  `action_id` varchar(37) DEFAULT NULL COMMENT '外部业务id 比如提现记录id',\\n\" +\n                \"  `ctime` bigint(20) DEFAULT NULL,\\n\" +\n                \"  `mtime` bigint(20) DEFAULT NULL,\\n\" +\n                \"  `version` bigint(20) unsigned NOT NULL,\\n\" +\n                \"  `deleted` tinyint(1) NOT NULL DEFAULT '0',\\n\" +\n                \"  KEY `id` (`id`),\\n\" +\n                \"  KEY `log_processed` (`processed`),\\n\" +\n                \"  KEY `log_ctime` (`ctime`),\\n\" +\n                \"  KEY `log_merchant_id_ctime` (`merchant_id`,`ctime`),\\n\" +\n                \"  KEY `log_action_id` (`action_id`)\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='日志记录用于驱动下游逻辑（余额更新）和外部系统的数据同步（积分）。'\\n\" +\n                \"/*!50100 PARTITION BY RANGE (`ctime`)\\n\" +\n                \"(PARTITION p201804 VALUES LESS THAN (1525104000000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201805 VALUES LESS THAN (1527782400000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201806 VALUES LESS THAN (1530374400000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201807 VALUES LESS THAN (1533052800000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201808 VALUES LESS THAN (1535731200000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201809 VALUES LESS THAN (1538323200000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201810 VALUES LESS THAN (1541001600000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201811 VALUES LESS THAN (1543593600000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201812 VALUES LESS THAN (1546272000000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */ dbpartition by hash(`merchant_id`)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `log_fake` (\\n\" +\n                \"\\t`id` varchar(37) NOT NULL COMMENT 'uuid',\\n\" +\n                \"\\t`merchant_id` varchar(37) DEFAULT NULL COMMENT '商户id',\\n\" +\n                \"\\t`type` int(11) NOT NULL COMMENT 'type字段决定payload如何解析',\\n\" +\n                \"\\t`payload` blob COMMENT 'payload存放以JSON格式编码的系统事件，例如订单成功支付。',\\n\" +\n                \"\\t`processed` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' COMMENT '是否已经处理（下游业务逻辑完成运算并更新数据或者同步到持久化的队列）',\\n\" +\n                \"\\t`partition` int(10) UNSIGNED NOT NULL COMMENT '分区ID(0-999)。多线程方式处理日志记录的时候，防止同一条记录被重复处理。',\\n\" +\n                \"\\t`action_id` varchar(37) DEFAULT NULL COMMENT '外部业务id 比如提现记录id',\\n\" +\n                \"\\t`ctime` bigint(20) DEFAULT NULL,\\n\" +\n                \"\\t`mtime` bigint(20) DEFAULT NULL,\\n\" +\n                \"\\t`version` bigint(20) UNSIGNED NOT NULL,\\n\" +\n                \"\\t`deleted` tinyint(1) NOT NULL DEFAULT '0',\\n\" +\n                \"\\tKEY `id` (`id`),\\n\" +\n                \"\\tKEY `log_processed` (`processed`),\\n\" +\n                \"\\tKEY `log_ctime` (`ctime`),\\n\" +\n                \"\\tKEY `log_merchant_id_ctime` (`merchant_id`, `ctime`),\\n\" +\n                \"\\tKEY `log_action_id` (`action_id`)\\n\" +\n                \") ENGINE = InnoDB CHARSET = utf8 COMMENT '日志记录用于驱动下游逻辑（余额更新）和外部系统的数据同步（积分）。'\\n\" +\n                \"DBPARTITION BY hash(`merchant_id`) /*!50100 PARTITION BY RANGE (`ctime`)\\n\" +\n                \"(PARTITION p201804 VALUES LESS THAN (1525104000000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201805 VALUES LESS THAN (1527782400000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201806 VALUES LESS THAN (1530374400000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201807 VALUES LESS THAN (1533052800000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201808 VALUES LESS THAN (1535731200000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201809 VALUES LESS THAN (1538323200000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201810 VALUES LESS THAN (1541001600000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201811 VALUES LESS THAN (1543593600000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201812 VALUES LESS THAN (1546272000000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */\", stmt.toString());\n\n        assertEquals(\"create table `log_fake` (\\n\" +\n                \"\\t`id` varchar(37) not null comment 'uuid',\\n\" +\n                \"\\t`merchant_id` varchar(37) default null comment '商户id',\\n\" +\n                \"\\t`type` int(11) not null comment 'type字段决定payload如何解析',\\n\" +\n                \"\\t`payload` blob comment 'payload存放以JSON格式编码的系统事件，例如订单成功支付。',\\n\" +\n                \"\\t`processed` tinyint(1) unsigned not null default '0' comment '是否已经处理（下游业务逻辑完成运算并更新数据或者同步到持久化的队列）',\\n\" +\n                \"\\t`partition` int(10) unsigned not null comment '分区ID(0-999)。多线程方式处理日志记录的时候，防止同一条记录被重复处理。',\\n\" +\n                \"\\t`action_id` varchar(37) default null comment '外部业务id 比如提现记录id',\\n\" +\n                \"\\t`ctime` bigint(20) default null,\\n\" +\n                \"\\t`mtime` bigint(20) default null,\\n\" +\n                \"\\t`version` bigint(20) unsigned not null,\\n\" +\n                \"\\t`deleted` tinyint(1) not null default '0',\\n\" +\n                \"\\tkey `id` (`id`),\\n\" +\n                \"\\tkey `log_processed` (`processed`),\\n\" +\n                \"\\tkey `log_ctime` (`ctime`),\\n\" +\n                \"\\tkey `log_merchant_id_ctime` (`merchant_id`, `ctime`),\\n\" +\n                \"\\tkey `log_action_id` (`action_id`)\\n\" +\n                \") engine = InnoDB charset = utf8 comment '日志记录用于驱动下游逻辑（余额更新）和外部系统的数据同步（积分）。'\\n\" +\n                \"dbpartition by hash(`merchant_id`) /*!50100 PARTITION BY RANGE (`ctime`)\\n\" +\n                \"(PARTITION p201804 VALUES LESS THAN (1525104000000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201805 VALUES LESS THAN (1527782400000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201806 VALUES LESS THAN (1530374400000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201807 VALUES LESS THAN (1533052800000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201808 VALUES LESS THAN (1535731200000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201809 VALUES LESS THAN (1538323200000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201810 VALUES LESS THAN (1541001600000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201811 VALUES LESS THAN (1543593600000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION p201812 VALUES LESS THAN (1546272000000) ENGINE = InnoDB,\\n\" +\n                \" PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest146_col_def.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest146_col_def\n * @description column_definition:\n * data_type [NOT NULL | NULL] [DEFAULT default_value]\n * [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY]\n * [COMMENT 'string']\n * [COLLATE collation_name]\n * [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}]\n * [STORAGE {DISK|MEMORY}]\n * [reference_definition]\n * | data_type\n * [COLLATE collation_name]\n * [GENERATED ALWAYS] AS (expr)\n * [VIRTUAL | STORED] [NOT NULL | NULL]\n * [UNIQUE [KEY]] [[PRIMARY] KEY]\n * [COMMENT 'string']\n * [reference_definition]\n * @Author zzy\n * @Date 2019-05-14 10:14\n */\npublic class MySqlCreateTableTest146_col_def {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"create table tb_dxdd (\" +\n                \"`a` varchar(10) not null default 'val' comment 'hehe' collate utf8_unicode_ci column_format default storage disk references tb_ref (a) match full on delete cascade on update cascade\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        /*\n        assertEquals(\"CREATE TABLE tb_dxdd (\\n\" +\n                \"\\t`a` varchar(10) NOT NULL DEFAULT 'val' COMMENT 'hehe' COLLATE utf8_unicode_ci COLUMN_FORMAT DEFAULT STORAGE disk REFERENCES tb_ref (a) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table tb_dxdd (\\n\" +\n                \"\\t`a` varchar(10) not null default 'val' comment 'hehe' collate utf8_unicode_ci column_format default storage disk references tb_ref (a) match full on delete cascade on update cascade\\n\" +\n                \");\", stmt.toLowerCaseString());\n        */\n        // Output order bad.\n        assertEquals(\"CREATE TABLE tb_dxdd (\\n\" +\n                \"\\t`a` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'val' STORAGE disk COLUMN_FORMAT DEFAULT COMMENT 'hehe' REFERENCES tb_ref (a) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table tb_dxdd (\\n\" +\n                \"\\t`a` varchar(10) collate utf8_unicode_ci not null default 'val' storage disk column_format default comment 'hehe' references tb_ref (a) match full on delete cascade on update cascade\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"create table tb_xx (a int generated always as (1) virtual not null comment 'xxx');\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE tb_xx (\\n\" +\n                \"\\ta int GENERATED ALWAYS AS (1) VIRTUAL NOT NULL COMMENT 'xxx'\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table tb_xx (\\n\" +\n                \"\\ta int generated always as (1) virtual not null comment 'xxx'\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"create table tb_ssx (a varchar(10) collate utf8_general_ci as ('val') stored not null primary key comment 'hh' references tb_ref (a));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        /*\n        assertEquals(\"CREATE TABLE tb_ssx (\\n\" +\n                \"\\ta varchar(10) COLLATE utf8_general_ci AS ('val') SORTED NOT NULL PRIMARY KEY COMMENT 'hh' REFERENCES tb_ref (a)\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table tb_ssx (\\n\" +\n                \"\\ta varchar(10) collate utf8_general_ci as ('val') sorted not null primary key comment 'hh' references tb_ref (a)\\n\" +\n                \");\", stmt.toLowerCaseString());\n        */\n        // Output order bad.\n        assertEquals(\"CREATE TABLE tb_ssx (\\n\" +\n                \"\\ta varchar(10) COLLATE utf8_general_ci NOT NULL PRIMARY KEY COMMENT 'hh' AS ('val') STORED REFERENCES tb_ref (a)\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table tb_ssx (\\n\" +\n                \"\\ta varchar(10) collate utf8_general_ci not null primary key comment 'hh' as ('val') stored references tb_ref (a)\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest147_fulltext.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest147_fulltext\n * @description | {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (key_part,...)\n * [index_option] ...\n * [INDEX|KEY] [index_name]都可以省略\n * @Author zzy\n * @Date 2019-05-14 16:19\n */\npublic class MySqlCreateTableTest147_fulltext {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"create table tt (b varchar(128), fulltext (b));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE tt (\\n\" +\n                \"\\tb varchar(128),\\n\" +\n                \"\\tFULLTEXT INDEX(b)\\n\" +\n                \");\", stmt.toString());\n\n        assertEquals(\"create table tt (\\n\" +\n                \"\\tb varchar(128),\\n\" +\n                \"\\tfulltext index(b)\\n\" +\n                \");\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest147_fulltext2.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest147_fulltext2 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE aliyun_poc_db.tbl_custom_analyzer2 (\\n\" +\n                \"  `id` int COMMENT '',\\n\" +\n                \"  `title` varchar COMMENT '',\\n\" +\n                \"  FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict,\\n\" +\n                \"  PRIMARY KEY (`id`)\\n\" +\n                \")DISTRIBUTED BY HASH(`id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE aliyun_poc_db.tbl_custom_analyzer2 (\\n\" +\n                \"\\t`id` int COMMENT '',\\n\" +\n                \"\\t`title` varchar COMMENT '',\\n\" +\n                \"\\tFULLTEXT INDEX title_fulltext_idx(title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict,\\n\" +\n                \"\\tPRIMARY KEY (`id`)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTE BY HASH(`id`);\", stmt.toString());\n\n        assertEquals(\"create table aliyun_poc_db.tbl_custom_analyzer2 (\\n\" +\n                \"\\t`id` int comment '',\\n\" +\n                \"\\t`title` varchar comment '',\\n\" +\n                \"\\tfulltext index title_fulltext_idx(title) with index analyzer index_analyzer2 with query analyzer query_analyzer2 with dict user_dict,\\n\" +\n                \"\\tprimary key (`id`)\\n\" +\n                \")\\n\" +\n                \"distribute by hash(`id`);\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest147_fulltext3.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest147_fulltext3 {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"  `id` int COMMENT '',   \\n\" +\n                \"  `title` varchar COMMENT '', \\n\" +\n                \"  FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict, \\n\" +\n                \"  PRIMARY KEY (`id`) )\\n\" +\n                \"  DISTRIBUTED BY HASH(`id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"\\t`id` int COMMENT '',\\n\" +\n                \"\\t`title` varchar COMMENT '',\\n\" +\n                \"\\tFULLTEXT INDEX title_fulltext_idx(title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict,\\n\" +\n                \"\\tPRIMARY KEY (`id`)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTE BY HASH(`id`);\", stmt.toString());\n    }\n\n    @Test\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"  `id` int COMMENT '',   \\n\" +\n                \"  `title` varchar COMMENT '', \\n\" +\n                \"  FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2 WITH DICT user_dict, \\n\" +\n                \"  PRIMARY KEY (`id`) )\\n\" +\n                \"  DISTRIBUTED BY HASH(`id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt.toString());\n        assertEquals(\"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"\\t`id` int COMMENT '',\\n\" +\n                \"\\t`title` varchar COMMENT '',\\n\" +\n                \"\\tFULLTEXT INDEX title_fulltext_idx(title) WITH INDEX ANALYZER index_analyzer2 WITH DICT user_dict,\\n\" +\n                \"\\tPRIMARY KEY (`id`)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTE BY HASH(`id`);\", stmt.toString());\n    }\n\n    @Test\n    public void test_2() throws Exception {\n        String sql = \"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"  `id` int COMMENT '',   \\n\" +\n                \"  `title` varchar COMMENT '', \\n\" +\n                \"  FULLTEXT INDEX title_fulltext_idx (title) WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict, \\n\" +\n                \"  PRIMARY KEY (`id`) )\\n\" +\n                \"  DISTRIBUTED BY HASH(`id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt.toString());\n        assertEquals(\"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"\\t`id` int COMMENT '',\\n\" +\n                \"\\t`title` varchar COMMENT '',\\n\" +\n                \"\\tFULLTEXT INDEX title_fulltext_idx(title) WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict,\\n\" +\n                \"\\tPRIMARY KEY (`id`)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTE BY HASH(`id`);\", stmt.toString());\n    }\n\n    @Test\n    public void test_3() throws Exception {\n        String sql = \"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"  `id` int COMMENT '',   \\n\" +\n                \"  `title` varchar COMMENT '', \\n\" +\n                \"  FULLTEXT INDEX title_fulltext_idx (title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict, \\n\" +\n                \"  PRIMARY KEY (`id`) )\\n\" +\n                \"  DISTRIBUTED BY HASH(`id`);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        System.out.println(stmt.toString());\n        assertEquals(\"CREATE TABLE tbl_custom_analyzer2 (\\n\" +\n                \"\\t`id` int COMMENT '',\\n\" +\n                \"\\t`title` varchar COMMENT '',\\n\" +\n                \"\\tFULLTEXT INDEX title_fulltext_idx(title) WITH INDEX ANALYZER index_analyzer2 WITH QUERY ANALYZER query_analyzer2 WITH DICT user_dict,\\n\" +\n                \"\\tPRIMARY KEY (`id`)\\n\" +\n                \")\\n\" +\n                \"DISTRIBUTE BY HASH(`id`);\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest148_national_char.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest148_national_char\n * @description [NATIONAL] CHAR[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]\n * [NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name]\n * @Author zzy\n * @Date 2019-05-14 17:25\n */\npublic class MySqlCreateTableTest148_national_char {\n    @Test\n    public void test_0() throws Exception {\n        String sql = \"create temporary table if not exists `tb_kxipe` (\\n\" +\n                \"\\t col_vttevt national char(128),\\n\" +\n                \"\\t col_wqq national varchar(128)\\n\" +\n                \") comment 'comment' \";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TEMPORARY TABLE IF NOT EXISTS `tb_kxipe` (\\n\" +\n                \"\\tcol_vttevt national char(128),\\n\" +\n                \"\\tcol_wqq national varchar(128)\\n\" +\n                \") COMMENT 'comment'\", stmt.toString());\n\n        assertEquals(\"create temporary table if not exists `tb_kxipe` (\\n\" +\n                \"\\tcol_vttevt national char(128),\\n\" +\n                \"\\tcol_wqq national varchar(128)\\n\" +\n                \") comment 'comment'\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest149_collate_before_generated.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest149_collate_before_generated\n * @description | data_type\n * [COLLATE collation_name]\n * [GENERATED ALWAYS] AS (expr)\n * [VIRTUAL | STORED] [NOT NULL | NULL]\n * [UNIQUE [KEY]] [[PRIMARY] KEY]\n * [COMMENT 'string']\n * [reference_definition]\n * @Author zzy\n * @Date 2019-05-14 17:41\n */\npublic class MySqlCreateTableTest149_collate_before_generated {\n    @Test\n    public void test_0() {\n        String sql = \"create temporary table `tb_dhma` (col_oxqagw int collate utf8_unicode_ci generated always as ( 1+2 ))\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TEMPORARY TABLE `tb_dhma` (\\n\" +\n                \"\\tcol_oxqagw int GENERATED ALWAYS AS (1 + 2) COLLATE utf8_unicode_ci\\n\" +\n                \")\", stmt.toString());\n\n        assertEquals(\"create temporary table `tb_dhma` (\\n\" +\n                \"\\tcol_oxqagw int generated always as (1 + 2) collate utf8_unicode_ci\\n\" +\n                \")\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest15.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest15 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `xxx` (\" +\n                \"                `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\" +\n                \"                `create_date` datetime DEFAULT NULL,\" +\n                \"                `update_date` datetime DEFAULT NULL,\" +\n                \"                `product_id` int(11) NOT NULL COMMENT '产品ID',\" +\n                \"                `memeber_id` int(11) NOT NULL COMMENT '用户ID',\" +\n                \"                `name` varchar(50) DEFAULT NULL COMMENT '姓名',\" +\n                \"                `address` varchar(500) DEFAULT NULL COMMENT '地址',\" +\n                \"                `mobile` varchar(50) DEFAULT NULL COMMENT '手机',\" +\n                \"                `amount` int(11) DEFAULT NULL COMMENT '兑换数量',\" +\n                \"                PRIMARY KEY (`id`)\" +\n                \"              ) ENGINE=InnoDB DEFAULT CHARSET=gbk;\" +\n                \"\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(9, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"xxx\")));\n\n        assertTrue(visitor.containsColumn(\"xxx\", \"id\"));\n        assertTrue(visitor.containsColumn(\"xxx\", \"amount\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest150_eunm_set_with_charset.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest150_eunm_set_with_charset\n * @description\n * @Author zzy\n * @Date 2019-05-15 10:30\n */\npublic class MySqlCreateTableTest150_eunm_set_with_charset {\n    @Test\n    public void test_0() {\n        String sql = \"create temporary table `tb_xx` (\\n\" +\n                \"`col_ttuap` enum('value1','value2') character set utf8  collate utf8_unicode_ci generated always as ( 1+2 ) virtual unique comment 'comment' references tb_fn ( `col_qzqnqrrfyv` ) match partial\\n\" +\n                \") min_rows = 1 , checksum = 1 , compression 'NONE'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TEMPORARY TABLE `tb_xx` (\\n\" +\n                \"\\t`col_ttuap` enum('value1', 'value2') CHARACTER SET utf8 COLLATE utf8_unicode_ci GENERATED ALWAYS AS (1 + 2) VIRTUAL UNIQUE COMMENT 'comment' REFERENCES tb_fn (`col_qzqnqrrfyv`) MATCH PARTIAL\\n\" +\n                \") MIN_ROWS = 1 CHECKSUM = 1 COMPRESSION = 'NONE'\", stmt.toString());\n\n        assertEquals(\"create temporary table `tb_xx` (\\n\" +\n                \"\\t`col_ttuap` enum('value1', 'value2') character set utf8 collate utf8_unicode_ci generated always as (1 + 2) virtual unique comment 'comment' references tb_fn (`col_qzqnqrrfyv`) match partial\\n\" +\n                \") min_rows = 1 checksum = 1 compression = 'NONE'\", stmt.toLowerCaseString());\n    }\n\n    @Test\n    public void test_1() {\n        String sql = \"create temporary table `tb_xx` (\\n\" +\n                \"\\t`col_ttuap` enum('value1', 'value2') character set utf8 collate utf8_unicode_ci generated always as (1 + 2) virtual unique comment 'comment' references tb_fn (`col_qzqnqrrfyv`) match partial\\n\" +\n                \") min_rows = 1 checksum = 1 compression = 'NONE'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TEMPORARY TABLE `tb_xx` (\\n\" +\n                \"\\t`col_ttuap` enum('value1', 'value2') CHARACTER SET utf8 COLLATE utf8_unicode_ci GENERATED ALWAYS AS (1 + 2) VIRTUAL UNIQUE COMMENT 'comment' REFERENCES tb_fn (`col_qzqnqrrfyv`) MATCH PARTIAL\\n\" +\n                \") MIN_ROWS = 1 CHECKSUM = 1 COMPRESSION = 'NONE'\", stmt.toString());\n\n        assertEquals(\"create temporary table `tb_xx` (\\n\" +\n                \"\\t`col_ttuap` enum('value1', 'value2') character set utf8 collate utf8_unicode_ci generated always as (1 + 2) virtual unique comment 'comment' references tb_fn (`col_qzqnqrrfyv`) match partial\\n\" +\n                \") min_rows = 1 checksum = 1 compression = 'NONE'\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest151_double_precision.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest151_double_precision\n * @description\n * @Author zzy\n * @Date 2019-05-15 14:07\n */\npublic class MySqlCreateTableTest151_double_precision {\n    @Test\n    public void test_0() {\n        String sql = \"create temporary table tb_etaqf (\\n\" +\n                \"\\t `col_mcdw` double precision(10,2)\\n\" +\n                \")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TEMPORARY TABLE tb_etaqf (\\n\" +\n                \"\\t`col_mcdw` double precision(10, 2)\\n\" +\n                \")\", stmt.toString());\n\n        assertEquals(\"create temporary table tb_etaqf (\\n\" +\n                \"\\t`col_mcdw` double precision(10, 2)\\n\" +\n                \")\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest152_table_options.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest152_table_options\n * @description table_option:\n * AUTO_INCREMENT [=] value\n * | AVG_ROW_LENGTH [=] value\n * | [DEFAULT] CHARACTER SET [=] charset_name\n * | CHECKSUM [=] {0 | 1}\n * | [DEFAULT] COLLATE [=] collation_name\n * | COMMENT [=] 'string'\n * | COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'}\n * | CONNECTION [=] 'connect_string'\n * | {DATA|INDEX} DIRECTORY [=] 'absolute path to directory'\n * | DELAY_KEY_WRITE [=] {0 | 1}\n * | ENCRYPTION [=] {'Y' | 'N'}\n * | ENGINE [=] engine_name\n * | INSERT_METHOD [=] { NO | FIRST | LAST }\n * | KEY_BLOCK_SIZE [=] value\n * | MAX_ROWS [=] value\n * | MIN_ROWS [=] value\n * | PACK_KEYS [=] {0 | 1 | DEFAULT}\n * | PASSWORD [=] 'string'\n * | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}\n * | STATS_AUTO_RECALC [=] {DEFAULT|0|1}\n * | STATS_PERSISTENT [=] {DEFAULT|0|1}\n * | STATS_SAMPLE_PAGES [=] value\n * | TABLESPACE tablespace_name [STORAGE {DISK|MEMORY}]\n * | UNION [=] (tbl_name[,tbl_name]...)\n * @Author zzy\n * @Date 2019-05-15 16:26\n */\npublic class MySqlCreateTableTest152_table_options {\n    @Test\n    public void test_no_comma_no_eq() {\n        String sql = \"create table tb (a int)\" +\n                \"auto_increment 1\\n\" +\n                \"avg_row_length 1\\n\" +\n                \"default character set utf8\\n\" +\n                \"checksum 0\\n\" +\n                \"default collate utf8_unicode_ci\\n\" +\n                \"comment 'hehe'\\n\" +\n                \"compression 'LZ4'\\n\" +\n                \"connection 'conn'\\n\" +\n                \"index directory 'path'\\n\" +\n                \"delay_key_write 1\\n\" +\n                \"encryption 'N'\\n\" +\n                \"engine innodb\\n\" +\n                \"insert_method no\\n\" +\n                \"key_block_size 32\\n\" +\n                \"max_rows 999\\n\" +\n                \"min_rows 1\\n\" +\n                \"pack_keys default\\n\" +\n                \"password 'psw'\\n\" +\n                \"row_format dynamic\\n\" +\n                \"stats_auto_recalc default\\n\" +\n                \"stats_persistent default\\n\" +\n                \"stats_sample_pages 10\\n\" +\n                \"tablespace `tbs_name` storage memory\\n\" +\n                \"union (tb1,tb2,tb3)\\n\" +\n                \"auto_increment 1\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE tb (\\n\" +\n                \"\\ta int\\n\" +\n                \") AUTO_INCREMENT = 1 AVG_ROW_LENGTH = 1 CHARACTER SET = utf8 CHECKSUM = 0 COLLATE = utf8_unicode_ci COMPRESSION = 'LZ4' CONNECTION = 'conn' INDEX DIRECTORY = 'path' DELAY_KEY_WRITE = 1 ENCRYPTION = 'N' ENGINE = innodb INSERT_METHOD = no KEY_BLOCK_SIZE = 32 MAX_ROWS = 999 MIN_ROWS = 1 PACK_KEYS = DEFAULT PASSWORD = 'psw' ROW_FORMAT = dynamic STATS_AUTO_RECALC = DEFAULT STATS_PERSISTENT = DEFAULT STATS_SAMPLE_PAGES = 10 TABLESPACE `tbs_name` STORAGE memory UNION = (tb1, tb2, tb3) AUTO_INCREMENT = 1 COMMENT 'hehe'\", stmt.toString());\n\n        assertEquals(\"create table tb (\\n\" +\n                \"\\ta int\\n\" +\n                \") auto_increment = 1 avg_row_length = 1 character set = utf8 checksum = 0 collate = utf8_unicode_ci compression = 'LZ4' connection = 'conn' index directory = 'path' delay_key_write = 1 encryption = 'N' engine = innodb insert_method = no key_block_size = 32 max_rows = 999 min_rows = 1 pack_keys = default password = 'psw' row_format = dynamic stats_auto_recalc = default stats_persistent = default stats_sample_pages = 10 tablespace `tbs_name` storage memory union = (tb1, tb2, tb3) auto_increment = 1 comment 'hehe'\", stmt.toLowerCaseString());\n    }\n\n    @Test\n    public void test_options_comma_eq() {\n        String sql = \"create table tb (a int)\" +\n                \"auto_increment = 2,\\n\" +\n                \"avg_row_length = 2,\\n\" +\n                \"character set = utf8,\\n\" +\n                \"checksum = 1,\\n\" +\n                \"collate = utf8_unicode_ci,\\n\" +\n                \"comment = 'hehe',\\n\" +\n                \"compression = 'NONE',\\n\" +\n                \"connection = 'conn',\\n\" +\n                \"data directory = 'path',\\n\" +\n                \"delay_key_write = 0,\\n\" +\n                \"encryption = 'Y',\\n\" +\n                \"engine = innodb,\\n\" +\n                \"insert_method = first,\\n\" +\n                \"key_block_size = 64,\\n\" +\n                \"max_rows = 999,\\n\" +\n                \"min_rows = 1,\\n\" +\n                \"pack_keys = 0,\\n\" +\n                \"password = 'psw',\\n\" +\n                \"row_format = fixed,\\n\" +\n                \"stats_auto_recalc = 1,\\n\" +\n                \"stats_persistent = 0,\\n\" +\n                \"stats_sample_pages = 2,\\n\" +\n                \"tablespace `tbs_name`\\n\" +\n                \"union = (tb1,tb2,tb3);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE tb (\\n\" +\n                \"\\ta int\\n\" +\n                \") AUTO_INCREMENT = 2 AVG_ROW_LENGTH = 2 CHARACTER SET = utf8 CHECKSUM = 1 COLLATE = utf8_unicode_ci COMPRESSION = 'NONE' CONNECTION = 'conn' DATA DIRECTORY = 'path' DELAY_KEY_WRITE = 0 ENCRYPTION = 'Y' ENGINE = innodb INSERT_METHOD = first KEY_BLOCK_SIZE = 64 MAX_ROWS = 999 MIN_ROWS = 1 PACK_KEYS = 0 PASSWORD = 'psw' ROW_FORMAT = fixed STATS_AUTO_RECALC = 1 STATS_PERSISTENT = 0 STATS_SAMPLE_PAGES = 2 TABLESPACE `tbs_name` UNION = (tb1, tb2, tb3) COMMENT 'hehe';\", stmt.toString());\n\n        assertEquals(\"create table tb (\\n\" +\n                \"\\ta int\\n\" +\n                \") auto_increment = 2 avg_row_length = 2 character set = utf8 checksum = 1 collate = utf8_unicode_ci compression = 'NONE' connection = 'conn' data directory = 'path' delay_key_write = 0 encryption = 'Y' engine = innodb insert_method = first key_block_size = 64 max_rows = 999 min_rows = 1 pack_keys = 0 password = 'psw' row_format = fixed stats_auto_recalc = 1 stats_persistent = 0 stats_sample_pages = 2 tablespace `tbs_name` union = (tb1, tb2, tb3) comment 'hehe';\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest153_collate.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest153_collate extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `t_file` (\\n\" +\n                \"`id` BIGINT(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"`account_id` VARCHAR(32) NULL DEFAULT '0' COMMENT '账户id' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`bussiness_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '业务id' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`target_id` VARCHAR(48) NULL DEFAULT '0' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`file_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '文件id' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`cloud_id` INT(11) NOT NULL DEFAULT '0' COMMENT '三方云id',\\n\" +\n                \"`src_file_id` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT '源文件id' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`file_name` VARCHAR(128) NOT NULL DEFAULT '0' COMMENT '文件名称' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`etag` VARCHAR(256) NULL DEFAULT '0' COMMENT '文件hash' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`object_name` VARCHAR(512) NOT NULL DEFAULT '0' COMMENT '云objectName' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`file_type` VARCHAR(20) NOT NULL DEFAULT '0' COMMENT '文件类型' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`access_mode` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '0-私有，1-公有',\\n\" +\n                \"`file_size` BIGINT(20) NULL DEFAULT '0' COMMENT '文件大小字节数',\\n\" +\n                \"`meta` TEXT NULL COMMENT '文件meta信息' COLLATE 'utf8mb4_bin',\\n\" +\n                \"`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\\n\" +\n                \"`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                \"PRIMARY KEY (`id`),\\n\" +\n                \"UNIQUE INDEX `file_id` (`file_id`),\\n\" +\n                \"INDEX `account_id` (`account_id`),\\n\" +\n                \"INDEX `src_file_id` (`src_file_id`, `bussiness_id`),\\n\" +\n                \"INDEX `target_id` (`target_id`)\\n\" +\n                \")\\n\" +\n                \"COLLATE='utf8mb4_bin'\\n\" +\n                \"ENGINE=InnoDB\\n\" +\n                \"dbpartition by hash(`src_file_id`) tbpartition by hash(`src_file_id`) tbpartitions 2\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `t_file` (\\n\" +\n                \"\\t`id` BIGINT(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"\\t`account_id` VARCHAR(32) COLLATE 'utf8mb4_bin' NULL DEFAULT '0' COMMENT '账户id',\\n\" +\n                \"\\t`bussiness_id` VARCHAR(32) COLLATE 'utf8mb4_bin' NOT NULL DEFAULT '0' COMMENT '业务id',\\n\" +\n                \"\\t`target_id` VARCHAR(48) COLLATE 'utf8mb4_bin' NULL DEFAULT '0',\\n\" +\n                \"\\t`file_id` VARCHAR(32) COLLATE 'utf8mb4_bin' NOT NULL DEFAULT '0' COMMENT '文件id',\\n\" +\n                \"\\t`cloud_id` INT(11) NOT NULL DEFAULT '0' COMMENT '三方云id',\\n\" +\n                \"\\t`src_file_id` VARCHAR(32) COLLATE 'utf8mb4_bin' NOT NULL DEFAULT '0' COMMENT '源文件id',\\n\" +\n                \"\\t`file_name` VARCHAR(128) COLLATE 'utf8mb4_bin' NOT NULL DEFAULT '0' COMMENT '文件名称',\\n\" +\n                \"\\t`etag` VARCHAR(256) COLLATE 'utf8mb4_bin' NULL DEFAULT '0' COMMENT '文件hash',\\n\" +\n                \"\\t`object_name` VARCHAR(512) COLLATE 'utf8mb4_bin' NOT NULL DEFAULT '0' COMMENT '云objectName',\\n\" +\n                \"\\t`file_type` VARCHAR(20) COLLATE 'utf8mb4_bin' NOT NULL DEFAULT '0' COMMENT '文件类型',\\n\" +\n                \"\\t`access_mode` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '0-私有，1-公有',\\n\" +\n                \"\\t`file_size` BIGINT(20) NULL DEFAULT '0' COMMENT '文件大小字节数',\\n\" +\n                \"\\t`meta` TEXT COLLATE 'utf8mb4_bin' NULL COMMENT '文件meta信息',\\n\" +\n                \"\\t`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\\n\" +\n                \"\\t`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tUNIQUE INDEX `file_id` (`file_id`),\\n\" +\n                \"\\tINDEX `account_id`(`account_id`),\\n\" +\n                \"\\tINDEX `src_file_id`(`src_file_id`, `bussiness_id`),\\n\" +\n                \"\\tINDEX `target_id`(`target_id`)\\n\" +\n                \") COLLATE = 'utf8mb4_bin' ENGINE = InnoDB\\n\" +\n                \"DBPARTITION BY hash(`src_file_id`)\\n\" +\n                \"TBPARTITION BY hash(`src_file_id`) TBPARTITIONS 2\", stmt.toString());\n\n        assertEquals(\"create table `t_file` (\\n\" +\n                \"\\t`id` BIGINT(20) not null auto_increment,\\n\" +\n                \"\\t`account_id` VARCHAR(32) collate 'utf8mb4_bin' null default '0' comment '账户id',\\n\" +\n                \"\\t`bussiness_id` VARCHAR(32) collate 'utf8mb4_bin' not null default '0' comment '业务id',\\n\" +\n                \"\\t`target_id` VARCHAR(48) collate 'utf8mb4_bin' null default '0',\\n\" +\n                \"\\t`file_id` VARCHAR(32) collate 'utf8mb4_bin' not null default '0' comment '文件id',\\n\" +\n                \"\\t`cloud_id` INT(11) not null default '0' comment '三方云id',\\n\" +\n                \"\\t`src_file_id` VARCHAR(32) collate 'utf8mb4_bin' not null default '0' comment '源文件id',\\n\" +\n                \"\\t`file_name` VARCHAR(128) collate 'utf8mb4_bin' not null default '0' comment '文件名称',\\n\" +\n                \"\\t`etag` VARCHAR(256) collate 'utf8mb4_bin' null default '0' comment '文件hash',\\n\" +\n                \"\\t`object_name` VARCHAR(512) collate 'utf8mb4_bin' not null default '0' comment '云objectName',\\n\" +\n                \"\\t`file_type` VARCHAR(20) collate 'utf8mb4_bin' not null default '0' comment '文件类型',\\n\" +\n                \"\\t`access_mode` TINYINT(4) not null default '0' comment '0-私有，1-公有',\\n\" +\n                \"\\t`file_size` BIGINT(20) null default '0' comment '文件大小字节数',\\n\" +\n                \"\\t`meta` TEXT collate 'utf8mb4_bin' null comment '文件meta信息',\\n\" +\n                \"\\t`create_time` DATETIME not null default current_timestamp,\\n\" +\n                \"\\t`update_time` DATETIME not null default current_timestamp on update current_timestamp,\\n\" +\n                \"\\tprimary key (`id`),\\n\" +\n                \"\\tunique index `file_id` (`file_id`),\\n\" +\n                \"\\tindex `account_id`(`account_id`),\\n\" +\n                \"\\tindex `src_file_id`(`src_file_id`, `bussiness_id`),\\n\" +\n                \"\\tindex `target_id`(`target_id`)\\n\" +\n                \") collate = 'utf8mb4_bin' engine = InnoDB\\n\" +\n                \"dbpartition by hash(`src_file_id`)\\n\" +\n                \"tbpartition by hash(`src_file_id`) tbpartitions 2\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest154_hint.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest154_hint\n        extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `ngram_2_t1_1` (\\n\" +\n                \"  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  `title` varchar(200) DEFAULT NULL,\\n\" +\n                \"  `content` text,\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  FULLTEXT KEY `ft_content` (`content`) /*!50100 WITH PARSER `ngram` */ ,\\n\" +\n                \"  FULLTEXT KEY `ft_title` (`title`) /*!50100 WITH PARSER `ngram` */\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=gb2312\\n\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        assertEquals(\"CREATE TABLE `ngram_2_t1_1` (\\n\" +\n                \"\\t`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,\\n\" +\n                \"\\t`title` varchar(200) DEFAULT NULL,\\n\" +\n                \"\\t`content` text,\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tFULLTEXT KEY `ft_content` (`content`),\\n\" +\n                \"\\tFULLTEXT KEY `ft_title` (`title`)\\n\" +\n                \") ENGINE = InnoDB AUTO_INCREMENT = 3 CHARSET = gb2312\", stmt.toString());\n\n        assertEquals(\"create table `ngram_2_t1_1` (\\n\" +\n                \"\\t`id` int(10) unsigned not null auto_increment,\\n\" +\n                \"\\t`title` varchar(200) default null,\\n\" +\n                \"\\t`content` text,\\n\" +\n                \"\\tprimary key (`id`),\\n\" +\n                \"\\tfulltext key `ft_content` (`content`),\\n\" +\n                \"\\tfulltext key `ft_title` (`title`)\\n\" +\n                \") engine = InnoDB auto_increment = 3 charset = gb2312\", stmt.toLowerCaseString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest155.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest155\n        extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table pk(id int primary key , name varchar)\";\n\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertTrue(stmt.isPrimaryColumn(\"id\"));\n        assertTrue(stmt.isPrimaryColumn(\"`id`\"));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"create table pk(id int, name varchar, primary key(id, name))\";\n\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertTrue(stmt.isPrimaryColumn(\"id\"));\n        assertTrue(stmt.isPrimaryColumn(\"`id`\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest156_ob.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest156_ob\n        extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table `ar_ranking_001_t` (\\n\" +\n                \"  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\\n\" +\n                \"  `user_id` varchar(32) NOT NULL COMMENT '用户ID',\\n\" +\n                \"  `scene_code` varchar(64) NOT NULL COMMENT '业务场景码',\\n\" +\n                \"  `record_type` varchar(16) NOT NULL COMMENT '记录类型 分数/等级',\\n\" +\n                \"  `record_value` int(11) NOT NULL COMMENT '记录值',\\n\" +\n                \"  `record_date` varchar(8) NOT NULL COMMENT '记录日期',\\n\" +\n                \"  `gmt_create` datetime NOT NULL COMMENT '创建时间',\\n\" +\n                \"  `gmt_modified` datetime NOT NULL COMMENT '修改时间',\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `idx_ranking` (`user_id`, `scene_code`, `record_type`, `record_date`) BLOCK_SIZE 16384\\n\" +\n                \") AUTO_INCREMENT = 1000001 DEFAULT CHARSET = utf8mb4 \\n\" +\n                \"COMPRESSION = 'lz4_1.0' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 10 COMMENT = 'ar平台数据排行榜';\\n\";\n\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE TABLE `ar_ranking_001_t` (\\n\" +\n                \"\\t`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',\\n\" +\n                \"\\t`user_id` varchar(32) NOT NULL COMMENT '用户ID',\\n\" +\n                \"\\t`scene_code` varchar(64) NOT NULL COMMENT '业务场景码',\\n\" +\n                \"\\t`record_type` varchar(16) NOT NULL COMMENT '记录类型 分数/等级',\\n\" +\n                \"\\t`record_value` int(11) NOT NULL COMMENT '记录值',\\n\" +\n                \"\\t`record_date` varchar(8) NOT NULL COMMENT '记录日期',\\n\" +\n                \"\\t`gmt_create` datetime NOT NULL COMMENT '创建时间',\\n\" +\n                \"\\t`gmt_modified` datetime NOT NULL COMMENT '修改时间',\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tKEY `idx_ranking` (`user_id`, `scene_code`, `record_type`, `record_date`) KEY_BLOCK_SIZE = 16384\\n\" +\n                \") AUTO_INCREMENT = 1000001 CHARSET = utf8mb4 COMPRESSION = 'lz4_1.0' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = false TABLET_SIZE = 134217728 PCTFREE = 10 COMMENT 'ar平台数据排行榜';\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest157_shadow.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * @version 1.0\n * @ClassName MySqlCreateTableTest157_shadow\n * @description\n * @Author zzy\n * @Date 2019/10/8 19:25\n */\npublic class MySqlCreateTableTest157_shadow extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create shadow table `ar_ranking_001_t` (\\n\" +\n                \"  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\\n\" +\n                \"  `user_id` varchar(32) NOT NULL COMMENT '用户ID',\\n\" +\n                \"  `scene_code` varchar(64) NOT NULL COMMENT '业务场景码',\\n\" +\n                \"  `record_type` varchar(16) NOT NULL COMMENT '记录类型 分数/等级',\\n\" +\n                \"  `record_value` int(11) NOT NULL COMMENT '记录值',\\n\" +\n                \"  `record_date` varchar(8) NOT NULL COMMENT '记录日期',\\n\" +\n                \"  `gmt_create` datetime NOT NULL COMMENT '创建时间',\\n\" +\n                \"  `gmt_modified` datetime NOT NULL COMMENT '修改时间',\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `idx_ranking` (`user_id`, `scene_code`, `record_type`, `record_date`) BLOCK_SIZE 16384\\n\" +\n                \") AUTO_INCREMENT = 1000001 DEFAULT CHARSET = utf8mb4;\\n\";\n\n        SQLCreateTableStatement stmt = (SQLCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE SHADOW TABLE `ar_ranking_001_t` (\\n\" +\n                \"\\t`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',\\n\" +\n                \"\\t`user_id` varchar(32) NOT NULL COMMENT '用户ID',\\n\" +\n                \"\\t`scene_code` varchar(64) NOT NULL COMMENT '业务场景码',\\n\" +\n                \"\\t`record_type` varchar(16) NOT NULL COMMENT '记录类型 分数/等级',\\n\" +\n                \"\\t`record_value` int(11) NOT NULL COMMENT '记录值',\\n\" +\n                \"\\t`record_date` varchar(8) NOT NULL COMMENT '记录日期',\\n\" +\n                \"\\t`gmt_create` datetime NOT NULL COMMENT '创建时间',\\n\" +\n                \"\\t`gmt_modified` datetime NOT NULL COMMENT '修改时间',\\n\" +\n                \"\\tPRIMARY KEY (`id`),\\n\" +\n                \"\\tKEY `idx_ranking` (`user_id`, `scene_code`, `record_type`, `record_date`) KEY_BLOCK_SIZE = 16384\\n\" +\n                \") AUTO_INCREMENT = 1000001 CHARSET = utf8mb4;\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest158_asselect.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest158_asselect extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table tmp_eric (pk int key, ia int unique) replace as select * from t;\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE TABLE tmp_eric (\\n\" +\n                \"\\tpk int PRIMARY KEY,\\n\" +\n                \"\\tia int UNIQUE\\n\" +\n                \")\\n\" +\n                \"REPLACE \\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM t;\", stmt.toString());\n    }\n\n    public void test_2() throws Exception {\n        String sql = \"create table tmp_eric (pk int key, ia int unique) ignore as select * from t;\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE TABLE tmp_eric (\\n\" +\n                \"\\tpk int PRIMARY KEY,\\n\" +\n                \"\\tia int UNIQUE\\n\" +\n                \")\\n\" +\n                \"IGNORE \\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM t;\", stmt.toString());\n    }\n\n    public void test_3() throws Exception {\n        String sql = \"create table tmp_eric (pk int key, ia int unique) replace ignore as select * from t;\";\n\n        try {\n            MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n            fail();\n        } catch (Exception e) {\n        }\n    }\n\n    public void test_4() throws Exception {\n        String sql = \"CREATE TABLE `D` (\\n\"\n                + \" `id` bigint(20) NOT NULL comment 'xxx' AUTO_INCREMENT,\\n\"\n                + \" `c1` tinyint(1) DEFAULT NULL,\\n\"\n                + \" `c2` tinyint(4) DEFAULT NULL,\\n\"\n                + \" PRIMARY KEY (`id`)\\n\"\n                + \") replace as select * from a\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE TABLE `D` (\\n\" +\n                \"\\t`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'xxx',\\n\" +\n                \"\\t`c1` tinyint(1) DEFAULT NULL,\\n\" +\n                \"\\t`c2` tinyint(4) DEFAULT NULL,\\n\" +\n                \"\\tPRIMARY KEY (`id`)\\n\" +\n                \")\\n\" +\n                \"REPLACE \\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM a\", stmt.toString());\n    }\n\n    public void test_5() throws Exception {\n        String sql = \"CREATE TABLE artists_and_works\\n\" +\n                \"  SELECT artist.name, COUNT(work.artist_id) AS number_of_works\\n\" +\n                \"  FROM artist LEFT JOIN work ON artist.id = work.artist_id\\n\" +\n                \"  GROUP BY artist.id;\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE TABLE artists_and_works\\n\" +\n                \"AS\\n\" +\n                \"SELECT artist.name, COUNT(work.artist_id) AS number_of_works\\n\" +\n                \"FROM artist\\n\" +\n                \"\\tLEFT JOIN work ON artist.id = work.artist_id\\n\" +\n                \"GROUP BY artist.id;\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"Create Table `aftersale_item_s3combine_1000` (\\n\" +\n                \" `order_status` varchar,\\n\" +\n                \" `is_cod` int,\\n\" +\n                \" `so_id` varchar,\\n\" +\n                \" `type` varchar,\\n\" +\n                \" `created` timestamp,\\n\" +\n                \" `creator_name` varchar,\\n\" +\n                \" `modifier_name` varchar,\\n\" +\n                \" `status` varchar,\\n\" +\n                \" `remark` varchar,\\n\" +\n                \" `question_type` varchar,\\n\" +\n                \" `refund` decimal(16, 4),\\n\" +\n                \" `payment` decimal(16, 4),\\n\" +\n                \" `shop_buyer_id` varchar,\\n\" +\n                \" `shop_id` int,\\n\" +\n                \" `logistics_company` varchar,\\n\" +\n                \" `l_id` varchar,\\n\" +\n                \" `good_status` varchar,\\n\" +\n                \" `order_type` varchar,\\n\" +\n                \" `drp_co_id` int,\\n\" +\n                \" `wms_co_id` int,\\n\" +\n                \" `tag` int,\\n\" +\n                \" `confirm_date` timestamp,\\n\" +\n                \" `asi_id` bigint,\\n\" +\n                \" `as_id` bigint,\\n\" +\n                \" `o_id` bigint,\\n\" +\n                \" `co_id` int,\\n\" +\n                \" `sku_id` varchar,\\n\" +\n                \" `outer_oi_id` varchar,\\n\" +\n                \" `sku_type` varchar,\\n\" +\n                \" `db_name` varchar,\\n\" +\n                \" `table_name` varchar,\\n\" +\n                \" `db_id` int,\\n\" +\n                \" `tb_id` int,\\n\" +\n                \" `cost_price` decimal(12, 4),\\n\" +\n                \" `base_amount` decimal(16, 4),\\n\" +\n                \" `bf_amount` decimal(16, 4),\\n\" +\n                \" `return_amount` decimal(16, 4),\\n\" +\n                \" `bf_qty` int,\\n\" +\n                \" `return_qty` int,\\n\" +\n                \" `base_qty` int,\\n\" +\n                \" `r_qty` int,\\n\" +\n                \" `src_combine_sku_id` varchar,\\n\" +\n                \" `item_type` varchar,\\n\" +\n                \" `return_amount_share` decimal(16, 4),\\n\" +\n                \" `bf_amount_share` decimal(16, 4),\\n\" +\n                \" `asid_rownumber` int,\\n\" +\n                \" `bf_asid_rownumber` int,\\n\" +\n                \" `sku_flag` int,\\n\" +\n                \" `sku_row_number` int,\\n\" +\n                \" `combinesku_row_number` int,\\n\" +\n                \" `buyer_message` varchar,\\n\" +\n                \" `order_remark` varchar,\\n\" +\n                \" `sent_flag` int,\\n\" +\n                \" `order_date` timestamp,\\n\" +\n                \" `pay_date` timestamp,\\n\" +\n                \" `send_date` timestamp,\\n\" +\n                \" `merge_so_id` varchar,\\n\" +\n                \" `receiver_state` varchar,\\n\" +\n                \" `receiver_city` varchar,\\n\" +\n                \" `receiver_district` varchar,\\n\" +\n                \" `receiver_name` varchar,\\n\" +\n                \" `order_from` varchar,\\n\" +\n                \" `presend_status` varchar,\\n\" +\n                \" `is_jst` int,\\n\" +\n                \" `seller_flag` int,\\n\" +\n                \" `shop_site` varchar,\\n\" +\n                \" `shop_buyer_id_en` varchar,\\n\" +\n                \" `receiver_name_en` varchar,\\n\" +\n                \" `dw_created` timestamp,\\n\" +\n                \" `properties_value` varchar,\\n\" +\n                \" `order_labels` varchar,\\n\" +\n                \" `order_l_id` varchar,\\n\" +\n                \" `outer_as_id` varchar,\\n\" +\n                \" `is_gift` int,\\n\" +\n                \" `end_time` timestamp,\\n\" +\n                \" `shop_sku_id` varchar,\\n\" +\n                \" `freight` decimal(16, 4),\\n\" +\n                \" `shop_i_id` varchar,\\n\" +\n                \" `as_item_so_id` varchar,\\n\" +\n                \" `entity_sku_flag` int,\\n\" +\n                \" `entity_combinesku_id` varchar,\\n\" +\n                \" `cdc_ts` timestamp,\\n\" +\n                \" `del_flag` int,\\n\" +\n                \" `sku_flag_new` int,\\n\" +\n                \" `drp_co_id_from` int,\\n\" +\n                \" `drp_co_id_to` int,\\n\" +\n                \" `supplier_name` varchar,\\n\" +\n                \" `wh_id` int,\\n\" +\n                \" `warehouse` varchar,\\n\" +\n                \" `combine_sku_id` varchar,\\n\" +\n                \" `creator` bigint,\\n\" +\n                \" `des` varchar,\\n\" +\n                \" `skuid_row_number` int,\\n\" +\n                \" `order_creator_name` varchar,\\n\" +\n                \" `order_creator` bigint,\\n\" +\n                \" primary key (co_id,o_id,as_id,asi_id,sku_id,sku_flag,entity_combinesku_id)\\n\" +\n                \") DISTRIBUTE BY HASH(`o_id`) INDEX_ALL='Y' COMMENT='comments' replace as select * from t;\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n        assertEquals(\"CREATE TABLE `aftersale_item_s3combine_1000` (\\n\" +\n                \"\\t`order_status` varchar,\\n\" +\n                \"\\t`is_cod` int,\\n\" +\n                \"\\t`so_id` varchar,\\n\" +\n                \"\\t`type` varchar,\\n\" +\n                \"\\t`created` timestamp,\\n\" +\n                \"\\t`creator_name` varchar,\\n\" +\n                \"\\t`modifier_name` varchar,\\n\" +\n                \"\\t`status` varchar,\\n\" +\n                \"\\t`remark` varchar,\\n\" +\n                \"\\t`question_type` varchar,\\n\" +\n                \"\\t`refund` decimal(16, 4),\\n\" +\n                \"\\t`payment` decimal(16, 4),\\n\" +\n                \"\\t`shop_buyer_id` varchar,\\n\" +\n                \"\\t`shop_id` int,\\n\" +\n                \"\\t`logistics_company` varchar,\\n\" +\n                \"\\t`l_id` varchar,\\n\" +\n                \"\\t`good_status` varchar,\\n\" +\n                \"\\t`order_type` varchar,\\n\" +\n                \"\\t`drp_co_id` int,\\n\" +\n                \"\\t`wms_co_id` int,\\n\" +\n                \"\\t`tag` int,\\n\" +\n                \"\\t`confirm_date` timestamp,\\n\" +\n                \"\\t`asi_id` bigint,\\n\" +\n                \"\\t`as_id` bigint,\\n\" +\n                \"\\t`o_id` bigint,\\n\" +\n                \"\\t`co_id` int,\\n\" +\n                \"\\t`sku_id` varchar,\\n\" +\n                \"\\t`outer_oi_id` varchar,\\n\" +\n                \"\\t`sku_type` varchar,\\n\" +\n                \"\\t`db_name` varchar,\\n\" +\n                \"\\t`table_name` varchar,\\n\" +\n                \"\\t`db_id` int,\\n\" +\n                \"\\t`tb_id` int,\\n\" +\n                \"\\t`cost_price` decimal(12, 4),\\n\" +\n                \"\\t`base_amount` decimal(16, 4),\\n\" +\n                \"\\t`bf_amount` decimal(16, 4),\\n\" +\n                \"\\t`return_amount` decimal(16, 4),\\n\" +\n                \"\\t`bf_qty` int,\\n\" +\n                \"\\t`return_qty` int,\\n\" +\n                \"\\t`base_qty` int,\\n\" +\n                \"\\t`r_qty` int,\\n\" +\n                \"\\t`src_combine_sku_id` varchar,\\n\" +\n                \"\\t`item_type` varchar,\\n\" +\n                \"\\t`return_amount_share` decimal(16, 4),\\n\" +\n                \"\\t`bf_amount_share` decimal(16, 4),\\n\" +\n                \"\\t`asid_rownumber` int,\\n\" +\n                \"\\t`bf_asid_rownumber` int,\\n\" +\n                \"\\t`sku_flag` int,\\n\" +\n                \"\\t`sku_row_number` int,\\n\" +\n                \"\\t`combinesku_row_number` int,\\n\" +\n                \"\\t`buyer_message` varchar,\\n\" +\n                \"\\t`order_remark` varchar,\\n\" +\n                \"\\t`sent_flag` int,\\n\" +\n                \"\\t`order_date` timestamp,\\n\" +\n                \"\\t`pay_date` timestamp,\\n\" +\n                \"\\t`send_date` timestamp,\\n\" +\n                \"\\t`merge_so_id` varchar,\\n\" +\n                \"\\t`receiver_state` varchar,\\n\" +\n                \"\\t`receiver_city` varchar,\\n\" +\n                \"\\t`receiver_district` varchar,\\n\" +\n                \"\\t`receiver_name` varchar,\\n\" +\n                \"\\t`order_from` varchar,\\n\" +\n                \"\\t`presend_status` varchar,\\n\" +\n                \"\\t`is_jst` int,\\n\" +\n                \"\\t`seller_flag` int,\\n\" +\n                \"\\t`shop_site` varchar,\\n\" +\n                \"\\t`shop_buyer_id_en` varchar,\\n\" +\n                \"\\t`receiver_name_en` varchar,\\n\" +\n                \"\\t`dw_created` timestamp,\\n\" +\n                \"\\t`properties_value` varchar,\\n\" +\n                \"\\t`order_labels` varchar,\\n\" +\n                \"\\t`order_l_id` varchar,\\n\" +\n                \"\\t`outer_as_id` varchar,\\n\" +\n                \"\\t`is_gift` int,\\n\" +\n                \"\\t`end_time` timestamp,\\n\" +\n                \"\\t`shop_sku_id` varchar,\\n\" +\n                \"\\t`freight` decimal(16, 4),\\n\" +\n                \"\\t`shop_i_id` varchar,\\n\" +\n                \"\\t`as_item_so_id` varchar,\\n\" +\n                \"\\t`entity_sku_flag` int,\\n\" +\n                \"\\t`entity_combinesku_id` varchar,\\n\" +\n                \"\\t`cdc_ts` timestamp,\\n\" +\n                \"\\t`del_flag` int,\\n\" +\n                \"\\t`sku_flag_new` int,\\n\" +\n                \"\\t`drp_co_id_from` int,\\n\" +\n                \"\\t`drp_co_id_to` int,\\n\" +\n                \"\\t`supplier_name` varchar,\\n\" +\n                \"\\t`wh_id` int,\\n\" +\n                \"\\t`warehouse` varchar,\\n\" +\n                \"\\t`combine_sku_id` varchar,\\n\" +\n                \"\\t`creator` bigint,\\n\" +\n                \"\\t`des` varchar,\\n\" +\n                \"\\t`skuid_row_number` int,\\n\" +\n                \"\\t`order_creator_name` varchar,\\n\" +\n                \"\\t`order_creator` bigint,\\n\" +\n                \"\\tPRIMARY KEY (co_id, o_id, as_id, asi_id, sku_id, sku_flag, entity_combinesku_id)\\n\" +\n                \") INDEX_ALL = 'Y' COMMENT 'comments'\\n\" +\n                \"DISTRIBUTE BY HASH(`o_id`)\\n\" +\n                \"REPLACE \\n\" +\n                \"AS\\n\" +\n                \"SELECT *\\n\" +\n                \"FROM t;\", stmt.toString());\n    }\n\n    @Test\n    public void test_6() {\n        SQLUtils.parseSingleMysqlStatement(\"CREATE TABLE `aftersale_item_s3combine_1000` (\\n\" +\n                \"\\t`order_status` varchar,\\n\" +\n                \"\\t`is_cod` int,\\n\" +\n                \"\\t`so_id` varchar,\\n\" +\n                \"\\t`type` varchar,\\n\" +\n                \"\\t`created` timestamp,\\n\" +\n                \"\\t`creator_name` varchar,\\n\" +\n                \"\\t`modifier_name` varchar,\\n\" +\n                \"\\t`status` varchar,\\n\" +\n                \"\\t`remark` varchar,\\n\" +\n                \"\\t`question_type` varchar,\\n\" +\n                \"\\t`refund` decimal(16, 4),\\n\" +\n                \"\\t`payment` decimal(16, 4),\\n\" +\n                \"\\t`shop_buyer_id` varchar,\\n\" +\n                \"\\t`shop_id` int,\\n\" +\n                \"\\t`logistics_company` varchar,\\n\" +\n                \"\\t`l_id` varchar,\\n\" +\n                \"\\t`good_status` varchar,\\n\" +\n                \"\\t`order_type` varchar,\\n\" +\n                \"\\t`drp_co_id` int,\\n\" +\n                \"\\t`wms_co_id` int,\\n\" +\n                \"\\t`tag` int,\\n\" +\n                \"\\t`confirm_date` timestamp,\\n\" +\n                \"\\t`asi_id` bigint,\\n\" +\n                \"\\t`as_id` bigint,\\n\" +\n                \"\\t`o_id` bigint,\\n\" +\n                \"\\t`co_id` int,\\n\" +\n                \"\\t`sku_id` varchar,\\n\" +\n                \"\\t`outer_oi_id` varchar,\\n\" +\n                \"\\t`sku_type` varchar,\\n\" +\n                \"\\t`db_name` varchar,\\n\" +\n                \"\\t`table_name` varchar,\\n\" +\n                \"\\t`db_id` int,\\n\" +\n                \"\\t`tb_id` int,\\n\" +\n                \"\\t`cost_price` decimal(12, 4),\\n\" +\n                \"\\t`base_amount` decimal(16, 4),\\n\" +\n                \"\\t`bf_amount` decimal(16, 4),\\n\" +\n                \"\\t`return_amount` decimal(16, 4),\\n\" +\n                \"\\t`bf_qty` int,\\n\" +\n                \"\\t`return_qty` int,\\n\" +\n                \"\\t`base_qty` int,\\n\" +\n                \"\\t`r_qty` int,\\n\" +\n                \"\\t`src_combine_sku_id` varchar,\\n\" +\n                \"\\t`item_type` varchar,\\n\" +\n                \"\\t`return_amount_share` decimal(16, 4),\\n\" +\n                \"\\t`bf_amount_share` decimal(16, 4),\\n\" +\n                \"\\t`asid_rownumber` int,\\n\" +\n                \"\\t`bf_asid_rownumber` int,\\n\" +\n                \"\\t`sku_flag` int,\\n\" +\n                \"\\t`sku_row_number` int,\\n\" +\n                \"\\t`combinesku_row_number` int,\\n\" +\n                \"\\t`buyer_message` varchar,\\n\" +\n                \"\\t`order_remark` varchar,\\n\" +\n                \"\\t`sent_flag` int,\\n\" +\n                \"\\t`order_date` timestamp,\\n\" +\n                \"\\t`pay_date` timestamp,\\n\" +\n                \"\\t`send_date` timestamp,\\n\" +\n                \"\\t`merge_so_id` varchar,\\n\" +\n                \"\\t`receiver_state` varchar,\\n\" +\n                \"\\t`receiver_city` varchar,\\n\" +\n                \"\\t`receiver_district` varchar,\\n\" +\n                \"\\t`receiver_name` varchar,\\n\" +\n                \"\\t`order_from` varchar,\\n\" +\n                \"\\t`presend_status` varchar,\\n\" +\n                \"\\t`is_jst` int,\\n\" +\n                \"\\t`seller_flag` int,\\n\" +\n                \"\\t`shop_site` varchar,\\n\" +\n                \"\\t`shop_buyer_id_en` varchar,\\n\" +\n                \"\\t`receiver_name_en` varchar,\\n\" +\n                \"\\t`dw_created` timestamp,\\n\" +\n                \"\\t`properties_value` varchar,\\n\" +\n                \"\\t`order_labels` varchar,\\n\" +\n                \"\\t`order_l_id` varchar,\\n\" +\n                \"\\t`outer_as_id` varchar,\\n\" +\n                \"\\t`is_gift` int,\\n\" +\n                \"\\t`end_time` timestamp,\\n\" +\n                \"\\t`shop_sku_id` varchar,\\n\" +\n                \"\\t`freight` decimal(16, 4),\\n\" +\n                \"\\t`shop_i_id` varchar,\\n\" +\n                \"\\t`as_item_so_id` varchar,\\n\" +\n                \"\\t`entity_sku_flag` int,\\n\" +\n                \"\\t`entity_combinesku_id` varchar,\\n\" +\n                \"\\t`cdc_ts` timestamp,\\n\" +\n                \"\\t`del_flag` int,\\n\" +\n                \"\\t`sku_flag_new` int,\\n\" +\n                \"\\t`drp_co_id_from` int,\\n\" +\n                \"\\t`drp_co_id_to` int,\\n\" +\n                \"\\t`supplier_name` varchar,\\n\" +\n                \"\\t`wh_id` int,\\n\" +\n                \"\\t`warehouse` varchar,\\n\" +\n                \"\\t`combine_sku_id` varchar,\\n\" +\n                \"\\t`creator` bigint,\\n\" +\n                \"\\t`des` varchar,\\n\" +\n                \"\\t`skuid_row_number` int,\\n\" +\n                \"\\t`order_creator_name` varchar,\\n\" +\n                \"\\t`order_creator` bigint,\\n\" +\n                \"\\tPRIMARY KEY (co_id, o_id, as_id, asi_id, sku_id, sku_flag, entity_combinesku_id)\\n\" +\n                \") INDEX_ALL = 'Y' COMMENT 'a'\\n\" +\n                \"DISTRIBUTE BY HASH(`o_id`)\");\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest159.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest159\n        extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `articles` (\\n\" +\n                \"  `article_id` bigint NOT NULL AUTO_INCREMENT COMMENT '文章id',\\n\" +\n                \"  `type` tinyint(1) NOT NULL COMMENT '文章类型',\\n\" +\n                \"  `cate` tinyint(1) DEFAULT '0' COMMENT '分类',\\n\" +\n                \"  `carousel` tinyint(1) DEFAULT '0' COMMENT '轮播',\\n\" +\n                \"  `author_id` bigint NOT NULL COMMENT '小编',\\n\" +\n                \"  `teacher_id` int DEFAULT NULL COMMENT '课程讲师',\\n\" +\n                \"  `is_fee` tinyint(1) DEFAULT NULL COMMENT '付费文章',\\n\" +\n                \"  `title` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文章标题',\\n\" +\n                \"  `name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '大咖名字',\\n\" +\n                \"  `sub_title` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '副标题',\\n\" +\n                \"  `summary` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文章简介',\\n\" +\n                \"  `tags` json DEFAULT NULL COMMENT '标签',\\n\" +\n                \"  `seo` json DEFAULT NULL COMMENT 'seo关键词',\\n\" +\n                \"  `published_at` datetime NOT NULL COMMENT '发布时间',\\n\" +\n                \"  `cover` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '封面图',\\n\" +\n                \"  `carousel_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '轮播图片',\\n\" +\n                \"  `act_time` datetime DEFAULT NULL COMMENT '活动时间',\\n\" +\n                \"  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '活动地点',\\n\" +\n                \"  `body` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文章内容',\\n\" +\n                \"  `suppliers` json DEFAULT NULL COMMENT '关联服务商',\\n\" +\n                \"  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\\n\" +\n                \"  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',\\n\" +\n                \"  PRIMARY KEY (`article_id`),\\n\" +\n                \"  KEY `articles_type` (`type`),\\n\" +\n                \"  KEY `articles_cate` (`cate`),\\n\" +\n                \"  KEY `articles_carousel` (`carousel`),\\n\" +\n                \"  KEY `articles_teacher_id` (`teacher_id`),\\n\" +\n                \"  KEY `articles_author_id` (`author_id`),\\n\" +\n                \"  KEY `articles_published_at` (`published_at`),\\n\" +\n                \"  KEY `articles_title` (`title`),\\n\" +\n                \"  KEY `articles_tags` ((cast(json_extract(`tags`,_utf8mb4'$[*]') as char(40) array)))\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=1054 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文章'\";\n\n//        SQLCreateTableStatement stmt = (SQLCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n//\n//        assertTrue(stmt.isPrimaryColumn(\"id\"));\n//        assertTrue(stmt.isPrimaryColumn(\"`id`\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest16.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest16 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `xxx` (\" +\n                \"                `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\" +\n                \"                `create_date` datetime DEFAULT NULL,\" +\n                \"                `update_date` datetime DEFAULT NULL,\" +\n                \"                `product_id` int(11) NOT NULL COMMENT '产品ID',\" +\n                \"                `memeber_id` int(11) NOT NULL COMMENT '用户ID',\" +\n                \"                `name` varchar(50) DEFAULT NULL COMMENT '姓名',\" +\n                \"                `address` varchar(500) DEFAULT NULL COMMENT '地址',\" +\n                \"                `mobile` varchar(50) DEFAULT NULL COMMENT '手机',\" +\n                \"                `amount` int(11) DEFAULT NULL COMMENT '兑换数量',\" +\n                \"                PRIMARY KEY (`id`)\" +\n                \"              ) ENGINE=InnoDB DEFAULT CHARSET=gbk;\" +\n                \"\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(9, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"xxx\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"xxx\", \"id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"xxx\", \"amount\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest160.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.statement.SQLTableLike;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest160 extends MysqlTest {\n    public void test_0() throws Exception {\n        //for ADB\n        String sql = \"CREATE TABLE IF NOT EXISTS bar (LIKE a INCLUDING PROPERTIES)\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertTrue(stmt.getTableElementList().get(0) instanceof SQLTableLike);\n        assertEquals(\"CREATE TABLE IF NOT EXISTS bar (\\n\" +\n                \"\\tLIKE a INCLUDING PROPERTIES\\n\" +\n                \")\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        //for ADB\n        String sql = \"CREATE TABLE IF NOT EXISTS bar2 (c TIMESTAMP, LIKE bar, d DATE)\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertTrue(stmt.getTableElementList().get(1) instanceof SQLTableLike);\n        assertEquals(\"CREATE TABLE IF NOT EXISTS bar2 (\\n\" +\n                \"\\tc TIMESTAMP,\\n\" +\n                \"\\tLIKE bar,\\n\" +\n                \"\\td DATE\\n\" +\n                \")\", stmt.toString());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest161_storage_policy.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.parser.ParserException;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest161_storage_policy extends MysqlTest {\n    public void test_0() throws Exception {\n        //for ADB\n        String sql = \"create table event_log(log_id bigint, log_time datetime)\\n\" +\n                \"distribute by hash(log_id)\\n\" +\n                \"partition by value(date_format('%Y%m%d')) lifecycle 180\\n\" +\n                \"storage_policy = 'HOT'\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE TABLE event_log (\\n\" +\n                \"\\tlog_id bigint,\\n\" +\n                \"\\tlog_time datetime\\n\" +\n                \") STORAGE_POLICY = 'HOT'\\n\" +\n                \"DISTRIBUTE BY HASH(log_id)\\n\" +\n                \"PARTITION BY VALUE (date_format('%Y%m%d'))\\n\" +\n                \"LIFECYCLE 180\", stmt.toString());\n    }\n\n    public void test_1() throws Exception {\n        //for ADB\n        String sql = \"create table event_log(log_id bigint, log_time datetime)\\n\" +\n                \"distribute by hash(log_id)\\n\" +\n                \"partition by value(date_format('%Y%m%d')) lifecycle 180\\n\" +\n                \"storage_policy = 'COLD';\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE TABLE event_log (\\n\" +\n                \"\\tlog_id bigint,\\n\" +\n                \"\\tlog_time datetime\\n\" +\n                \") STORAGE_POLICY = 'COLD'\\n\" +\n                \"DISTRIBUTE BY HASH(log_id)\\n\" +\n                \"PARTITION BY VALUE (date_format('%Y%m%d'))\\n\" +\n                \"LIFECYCLE 180;\", stmt.toString());\n    }\n\n    public void test_2() throws Exception {\n        //for ADB\n        String sql = \"create table event_log(log_id bigint, log_time datetime)\\n\" +\n                \"distribute by hash(log_id)\\n\" +\n                \"partition by value(date_format('%Y%m%d')) lifecycle 180\\n\" +\n                \"storage_policy = 'MIXED' hot_partition_count = 10;\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(\"CREATE TABLE event_log (\\n\" +\n                \"\\tlog_id bigint,\\n\" +\n                \"\\tlog_time datetime\\n\" +\n                \") STORAGE_POLICY = 'MIXED' HOT_PARTITION_COUNT = 10\\n\" +\n                \"DISTRIBUTE BY HASH(log_id)\\n\" +\n                \"PARTITION BY VALUE (date_format('%Y%m%d'))\\n\" +\n                \"LIFECYCLE 180;\", stmt.toString());\n    }\n\n    public void test_3() throws Exception {\n        //for ADB\n        String sql = \"create table event_log(log_id bigint, log_time datetime)\\n\" +\n                \"distribute by hash(log_id)\\n\" +\n                \"partition by value(date_format('%Y%m%d')) lifecycle 180\\n\" +\n                \"storage_policy = 'MIXED' hot_partition_count = 0.1;\";\n\n        try {\n            SQLUtils.parseSingleMysqlStatement(sql);\n            fail();\n        } catch (ParserException e) {\n        }\n\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest162_distributed_by_with_duplicate.java",
    "content": "package com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.DbType;\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.visitor.VisitorFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest162_distributed_by_with_duplicate extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `test_user` ( `id` int(11) NOT NULL AUTO_INCREMENT ) DISTRIBUTE BY DUPLICATE(g1,g2);\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(sql, SQLUtils.toSQLString(stmt, DbType.mysql, new SQLUtils.FormatOption(VisitorFeature.OutputUCase)));\n    }\n\n    public void test_1() throws Exception {\n        String sql = \"CREATE TABLE `test_user` ( `id` int(11) NOT NULL AUTO_INCREMENT ) DISTRIBUTED BY DUPLICATE(g1,g2);\";\n\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(sql);\n\n        assertEquals(sql, SQLUtils.toSQLString(stmt, DbType.mysql, new SQLUtils.FormatOption(\n                VisitorFeature.OutputDistributedLiteralInCreateTableStmt, VisitorFeature.OutputUCase)));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest17.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest17 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE t1 (\" +\n                \"  ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t1\", \"ts\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest18.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest18 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE IF NOT EXISTS `t_awards` (\" +\n                \"  `id` int(11) NOT NULL AUTO_INCREMENT,\" +\n                \"  `seller_id` int(11) NOT NULL,\" +\n                \"  `shop_id` int(11) DEFAULT NULL,\" +\n                \"  `mode` int(4) NOT NULL,\" +\n                \"  `draw_rate_1` int(11) NOT NULL,\" +\n                \"  `draw_rate_2` int(11) NOT NULL,\" +\n                \"  `amount` int(11) NOT NULL,\" +\n                \"  `position_code` int(11) NOT NULL,\" +\n                \"  `f_denomination` int(11) DEFAULT NULL,\" +\n                \"  `f_description` text,\" +\n                \"  `f_url` text,\" +\n                \"  `f_type` int(4) DEFAULT NULL,\" +\n                \"  PRIMARY KEY (`id`),\" +\n                \"  UNIQUE KEY `id` (`id`)\" +\n                \") ENGINE=InnoDB  DEFAULT CHARSET=gbk\" +\n                \";\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n        // print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n        // System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n        // System.out.println(\"coditions : \" + visitor.getConditions());\n        // System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(12, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(\n                new TableStat.Name(\"t_awards\")));\n\n        assertTrue(visitor.containsColumn(\"t_awards\", \"f_type\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest19.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest19 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE new_tbl LIKE orig_tbl;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(\"CREATE TABLE new_tbl LIKE orig_tbl;\", //\n                SQLUtils.toMySqlString(stmt));\n        assertEquals(\"create table new_tbl like orig_tbl;\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"new_tbl\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest2.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest2 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"test\", \"blob_col\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest20.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest20 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE new_tbl (LIKE orig_tbl);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"new_tbl\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest21.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest21 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE new_tbl (LIKE orig_tbl);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(0, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"new_tbl\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest22.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest22 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE t1 (\" +\n                \"c1 INT STORAGE DISK,\" +\n                \"c2 INT STORAGE MEMORY \" +\n                \") TABLESPACE ts_1 ENGINE NDB;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE t1 (\" +\n                \"\\n\\tc1 INT STORAGE DISK,\" +\n                \"\\n\\tc2 INT STORAGE MEMORY\" +\n                \"\\n) TABLESPACE ts_1 ENGINE = NDB;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest23.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest23 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  ENGINE = MEMORY;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) ENGINE = MEMORY;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest24.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest24 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  AVG_ROW_LENGTH = 1024;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) AVG_ROW_LENGTH = 1024;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest25.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest25 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  AVG_ROW_LENGTH 1024;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) AVG_ROW_LENGTH = 1024;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest26.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest26 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  MAX_ROWS 1024;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) MAX_ROWS = 1024;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest27.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest27 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  MAX_ROWS = 1024;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) MAX_ROWS = 1024;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest28.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest28 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  MIN_ROWS = 1024;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) MIN_ROWS = 1024;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest29.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest29 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE user\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  MIN_ROWS 1024;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"user\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE user (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) MIN_ROWS = 1024;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest3.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest3 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)    PARTITION BY KEY(col3)    PARTITIONS 4;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"tk\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"tk\", \"col1\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"tk\", \"col2\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"tk\", \"col3\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest30.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest30 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  DELAY_KEY_WRITE 0;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) DELAY_KEY_WRITE = 0;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest31.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest31 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  DELAY_KEY_WRITE = 1;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) DELAY_KEY_WRITE = 1;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest32.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest32 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  DATA DIRECTORY = 'aaa';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) DATA DIRECTORY = 'aaa';\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest33.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest33 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  CONNECTION = 'aaa';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) CONNECTION = 'aaa';\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest34.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest34 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  CHECKSUM = 1;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) CHECKSUM = 1;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest35.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest35 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  AUTO_INCREMENT = 1;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) AUTO_INCREMENT = 1;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest36.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest36 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  STATS_AUTO_RECALC = 1;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) STATS_AUTO_RECALC = 1;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest37.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest37 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  STATS_AUTO_RECALC DEFAULT;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) STATS_AUTO_RECALC = DEFAULT;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest38.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest38 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  STATS_PERSISTENT DEFAULT;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) STATS_PERSISTENT = DEFAULT;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest39.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest39 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  STATS_PERSISTENT 1;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) STATS_PERSISTENT = 1;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest4.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest4 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"create table t_temp_11593685fc3244cf81468209484078a0 (\" +\n                \"id int not null auto_increment, \" +\n                \"score float not null, \" +\n                \"student bigint not null, \" +\n                \"primary key(id),\" +\n                \"key score(score), \" +\n                \"key student(student))\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement statemen = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        statemen.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t_temp_11593685fc3244cf81468209484078a0\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"t_temp_11593685fc3244cf81468209484078a0\", \"id\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t_temp_11593685fc3244cf81468209484078a0\", \"score\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"t_temp_11593685fc3244cf81468209484078a0\", \"student\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest40.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest40 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE t1 (col1 INT, col2 CHAR(5))\" +\n                \" PARTITION BY HASH(col1);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t1\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE t1 (\" +\n                \"\\n\\tcol1 INT,\" +\n                \"\\n\\tcol2 CHAR(5)\" +\n                \"\\n)\"\n                + \"\\nPARTITION BY HASH (col1);\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest41.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest41 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)\" +\n                \"    PARTITION BY LINEAR KEY(col3)\" +\n                \"    PARTITIONS 5;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"tk\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE tk (\" +\n                \"\\n\\tcol1 INT,\" +\n                \"\\n\\tcol2 CHAR(5),\" +\n                \"\\n\\tcol3 DATE\" +\n                \"\\n)\"\n                + \"\\nPARTITION BY LINEAR KEY (col3) PARTITIONS 5;\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest42.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest42 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE rc (\" +\n                \"    a INT NOT NULL, \" +\n                \"    b INT NOT NULL\" +\n                \")\" +\n                \"PARTITION BY RANGE COLUMNS(a,b) (\" +\n                \"    PARTITION p0 VALUES LESS THAN (10,5),\" +\n                \"    PARTITION p1 VALUES LESS THAN (20,10),\" +\n                \"    PARTITION p2 VALUES LESS THAN (MAXVALUE,15),\" +\n                \"    PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE)\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"rc\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE rc (\\n\" +\n                \"\\ta INT NOT NULL,\\n\" +\n                \"\\tb INT NOT NULL\\n\" +\n                \")\\n\" +\n                \"PARTITION BY RANGE COLUMNS (a, b) (\\n\" +\n                \"\\tPARTITION p0 VALUES LESS THAN (10, 5),\\n\" +\n                \"\\tPARTITION p1 VALUES LESS THAN (20, 10),\\n\" +\n                \"\\tPARTITION p2 VALUES LESS THAN (MAXVALUE, 15),\\n\" +\n                \"\\tPARTITION p3 VALUES LESS THAN (MAXVALUE, MAXVALUE)\\n\" +\n                \");\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest43.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest43 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE client_firms (\" +\n                \"    id   INT,\" +\n                \"    name VARCHAR(35)\" +\n                \")\" +\n                \"PARTITION BY LIST (id) (\" +\n                \"    PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),\" +\n                \"    PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),\" +\n                \"    PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),\" +\n                \"    PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"client_firms\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE client_firms (\\n\" +\n                \"\\tid INT,\\n\" +\n                \"\\tname VARCHAR(35)\\n\" +\n                \")\\n\" +\n                \"PARTITION BY LIST (id) (\\n\" +\n                \"\\tPARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),\\n\" +\n                \"\\tPARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),\\n\" +\n                \"\\tPARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),\\n\" +\n                \"\\tPARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)\\n\" +\n                \");\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest44.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest44 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lc (\" +\n                \"    a INT NULL, \" +\n                \"    b INT NULL\" +\n                \")\" +\n                \"PARTITION BY LIST COLUMNS(a,b) (\" +\n                \"    PARTITION p0 VALUES IN( (0,0), (NULL,NULL) ),\" +\n                \"    PARTITION p1 VALUES IN( (0,1), (0,2), (0,3), (1,1), (1,2) ),\" +\n                \"    PARTITION p2 VALUES IN( (1,0), (2,0), (2,1), (3,0), (3,1) ),\" +\n                \"    PARTITION p3 VALUES IN( (1,3), (2,2), (2,3), (3,2), (3,3) )\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lc\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lc (\\n\" +\n                \"\\ta INT NULL,\\n\" +\n                \"\\tb INT NULL\\n\" +\n                \")\\n\" +\n                \"PARTITION BY LIST COLUMNS (a, b) (\\n\" +\n                \"\\tPARTITION p0 VALUES IN ((0, 0), (NULL, NULL)),\\n\" +\n                \"\\tPARTITION p1 VALUES IN ((0, 1), (0, 2), (0, 3), (1, 1), (1, 2)),\\n\" +\n                \"\\tPARTITION p2 VALUES IN ((1, 0), (2, 0), (2, 1), (3, 0), (3, 1)),\\n\" +\n                \"\\tPARTITION p3 VALUES IN ((1, 3), (2, 2), (2, 3), (3, 2), (3, 3))\\n\" +\n                \");\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest45.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest45 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE th (id INT, name VARCHAR(30), adate DATE)\" +\n                \"PARTITION BY LIST(YEAR(adate))\" +\n                \"(\" +\n                \"  PARTITION p1999 VALUES IN (1995, 1999, 2003)\" +\n                \"    DATA DIRECTORY = '/var/appdata/95/data'\" +\n                \"    INDEX DIRECTORY = '/var/appdata/95/idx',\" +\n                \"  PARTITION p2000 VALUES IN (1996, 2000, 2004)\" +\n                \"    DATA DIRECTORY = '/var/appdata/96/data'\" +\n                \"    INDEX DIRECTORY = '/var/appdata/96/idx',\" +\n                \"  PARTITION p2001 VALUES IN (1997, 2001, 2005)\" +\n                \"    DATA DIRECTORY = '/var/appdata/97/data'\" +\n                \"    INDEX DIRECTORY = '/var/appdata/97/idx',\" +\n                \"  PARTITION p2002 VALUES IN (1998, 2002, 2006)\" +\n                \"    DATA DIRECTORY = '/var/appdata/98/data'\" +\n                \"    INDEX DIRECTORY = '/var/appdata/98/idx'\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        SQLStatement stmt = statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"th\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE th (\\n\" +\n                \"\\tid INT,\\n\" +\n                \"\\tname VARCHAR(30),\\n\" +\n                \"\\tadate DATE\\n\" +\n                \")\\n\" +\n                \"PARTITION BY LIST (YEAR(adate)) (\\n\" +\n                \"\\tPARTITION p1999 VALUES IN (1995, 1999, 2003)\\n\" +\n                \"\\t\\tDATA DIRECTORY '/var/appdata/95/data'\\n\" +\n                \"\\t\\tINDEX DIRECTORY '/var/appdata/95/idx',\\n\" +\n                \"\\tPARTITION p2000 VALUES IN (1996, 2000, 2004)\\n\" +\n                \"\\t\\tDATA DIRECTORY '/var/appdata/96/data'\\n\" +\n                \"\\t\\tINDEX DIRECTORY '/var/appdata/96/idx',\\n\" +\n                \"\\tPARTITION p2001 VALUES IN (1997, 2001, 2005)\\n\" +\n                \"\\t\\tDATA DIRECTORY '/var/appdata/97/data'\\n\" +\n                \"\\t\\tINDEX DIRECTORY '/var/appdata/97/idx',\\n\" +\n                \"\\tPARTITION p2002 VALUES IN (1998, 2002, 2006)\\n\" +\n                \"\\t\\tDATA DIRECTORY '/var/appdata/98/data'\\n\" +\n                \"\\t\\tINDEX DIRECTORY '/var/appdata/98/idx'\\n\" +\n                \");\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest46.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest46 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE lookup\" +\n                \"  (id INT, INDEX USING BTREE (id))\" +\n                \"  STATS_PERSISTENT 1;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"lookup\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE lookup (\" +\n                \"\\n\\tid INT,\" +\n                \"\\n\\tINDEX USING BTREE(id)\" +\n                \"\\n) STATS_PERSISTENT = 1\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest47.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest47 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE issuestatus (\"//\n                + \"ID VARCHAR(60) NOT NULL, \"\n                + \"SEQUENCE DECIMAL(18,0), \"\n                + \"pname VARCHAR(60), \"\n                + \"DESCRIPTION TEXT, \"\n                + \"ICONURL VARCHAR(255), \"\n                + \"CONSTRAINT PK_issuestatus PRIMARY KEY (ID))\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"issuestatus\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE issuestatus (\"//\n                + \"\\n\\tID VARCHAR(60) NOT NULL,\"//\n                + \"\\n\\tSEQUENCE DECIMAL(18, 0),\"//\n                + \"\\n\\tpname VARCHAR(60),\"//\n                + \"\\n\\tDESCRIPTION TEXT,\"//\n                + \"\\n\\tICONURL VARCHAR(255),\"//\n                + \"\\n\\tPRIMARY KEY (ID)\"//\n                + \"\\n)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest48.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest48 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE AO_E8B6CC_REPO_TO_CHANGESET (\"\n                + \"    CHANGESET_ID INTEGER,\"//\n                + \"    ID INTEGER AUTO_INCREMENT NOT NULL,\"//\n                + \"    REPOSITORY_ID INTEGER,\"//\n                + \"    CONSTRAINT fk_ao_e8b6cc_repo_to_changeset_repository_id FOREIGN KEY (REPOSITORY_ID) REFERENCES AO_E8B6CC_REPOSITORY_MAPPING(ID),\"//\n                + \"    CONSTRAINT fk_ao_e8b6cc_repo_to_changeset_changeset_id FOREIGN KEY (CHANGESET_ID) REFERENCES AO_E8B6CC_CHANGESET_MAPPING(ID),\"//\n                + \"    PRIMARY KEY(ID)\"//\n                + \") ENGINE=InnoDB\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        System.out.println(stmt);\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(3, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"AO_E8B6CC_REPO_TO_CHANGESET\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE AO_E8B6CC_REPO_TO_CHANGESET (\"//\n                        + \"\\n\\tCHANGESET_ID INTEGER,\"//\n                        + \"\\n\\tID INTEGER NOT NULL AUTO_INCREMENT,\"//\n                        + \"\\n\\tREPOSITORY_ID INTEGER,\"//\n                        + \"\\n\\tCONSTRAINT fk_ao_e8b6cc_repo_to_changeset_repository_id FOREIGN KEY (REPOSITORY_ID) REFERENCES AO_E8B6CC_REPOSITORY_MAPPING (ID),\"//\n                        + \"\\n\\tCONSTRAINT fk_ao_e8b6cc_repo_to_changeset_changeset_id FOREIGN KEY (CHANGESET_ID) REFERENCES AO_E8B6CC_CHANGESET_MAPPING (ID),\"//\n                        + \"\\n\\tPRIMARY KEY (ID)\"//\n                        + \"\\n) ENGINE = InnoDB\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest49.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest49 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"    create table tauth (\"\n                + \"        cid varchar(36) not null unique,\"//\n                + \"        cdesc varchar(200),\"//\n                + \"        cname varchar(100) not null,\"//\n                + \"        cseq decimal(22,0),\"//\n                + \"        curl varchar(200),\"//\n                + \"        cpid varchar(36),\"//\n                + \"        primary key (cid)\"//\n                + \"    )\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(6, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"tauth\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE tauth (\"\n                        + \"\\n\\tcid varchar(36) NOT NULL UNIQUE,\"//\n                        + \"\\n\\tcdesc varchar(200),\"//\n                        + \"\\n\\tcname varchar(100) NOT NULL,\"//\n                        + \"\\n\\tcseq decimal(22, 0),\"//\n                        + \"\\n\\tcurl varchar(200),\"//\n                        + \"\\n\\tcpid varchar(36),\"//\n                        + \"\\n\\tPRIMARY KEY (cid)\"//\n                        + \"\\n)\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest5.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest5 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `test` (\" +\n                \"  `id` bigint(20) NOT NULL AUTO_INCREMENT,\" +\n                \"  `dspcode` char(200) DEFAULT NULL,\" +\n                \"  PRIMARY KEY (`id`),\" +\n                \"  KEY `index_name` (`dspcode`)\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        assertEquals(\"utf8\", stmt.getOption(\"CHARSET\").toString());\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        assertTrue(visitor.containsColumn(\"test\", \"id\"));\n        assertTrue(visitor.containsColumn(\"test\", \"dspcode\"));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest50.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest50 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE  TABLE `test`.`a` (\"\n                + \"  `ida` INT NOT NULL COMMENT 'aaa' ,\"//\n                + \"  PRIMARY KEY (`ida`) )\"//\n                + \" COMMENT = 'bb';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test.a\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE `test`.`a` (\"\n                        + \"\\n\\t`ida` INT NOT NULL COMMENT 'aaa',\"//\n                        + \"\\n\\tPRIMARY KEY (`ida`)\"//\n                        + \"\\n) COMMENT 'bb'\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest51.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest51 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `test` (\"\n                + \"`Id` int(11) NOT NULL,\"\n                + \"`text` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL\"//\n                + \") ENGINE=InnoDB DEFAULT CHARSET=gbk\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(2, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"test\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n//        System.out.println(output);\n        assertEquals(\"CREATE TABLE `test` (\"\n                        + \"\\n\\t`Id` int(11) NOT NULL,\"//\n                        + \"\\n\\t`text` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL\"//\n                        + \"\\n) ENGINE = InnoDB CHARSET = gbk\",\n                output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest52.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest52 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"//\n                + \"`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"`ebay_name` varchar(50)  NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\" + \"PRIMARY KEY (`auth_id`)\"//\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"ins_ebay_auth\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"\\n\\t`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"\n                + \"\\n\\t`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"\\n\\t`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"\\n\\t`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"\\n\\t`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"\\n\\t`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"\\n\\t`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\"//\n                + \"\\n\\tPRIMARY KEY (`auth_id`)\"\n                + \"\\n) ENGINE = InnoDB CHARSET = utf8 COLLATE = utf8_bin COMMENT 'INS_EBAY_AUTH'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest53.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest53 extends MysqlTest {\n    @Test\n    public void test_primary_key_using_btree() throws Exception {\n        String sql = \"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"//\n                + \"`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"`ebay_name` varchar(50)  NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\" + \"PRIMARY KEY USING BTREE (`auth_id`)\"//\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"ins_ebay_auth\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"\\n\\t`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"\n                + \"\\n\\t`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"\\n\\t`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"\\n\\t`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"\\n\\t`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"\\n\\t`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"\\n\\t`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\"//\n                + \"\\n\\tPRIMARY KEY USING BTREE (`auth_id`)\"\n                + \"\\n) ENGINE = InnoDB CHARSET = utf8 COLLATE = utf8_bin COMMENT 'INS_EBAY_AUTH'\", output);\n    }\n\n    @Test\n    public void test_index_using_btree() throws Exception {\n        String sql = \"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"//\n                + \"`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"`ebay_name` varchar(50)  NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\" + \"PRIMARY KEY USING BTREE (`auth_id`), INDEX `ind_usr_id` USING BTREE(`usr_id`)\"//\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"ins_ebay_auth\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"\\n\\t`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"\n                + \"\\n\\t`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"\\n\\t`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"\\n\\t`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"\\n\\t`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"\\n\\t`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"\\n\\t`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\"//\n                + \"\\n\\tPRIMARY KEY USING BTREE (`auth_id`),\"\n                + \"\\n\\tINDEX `ind_usr_id` USING BTREE(`usr_id`)\"\n                + \"\\n) ENGINE = InnoDB CHARSET = utf8 COLLATE = utf8_bin COMMENT 'INS_EBAY_AUTH'\", output);\n    }\n\n    @Test\n    public void test_key_using_btree() throws Exception {\n        String sql = \"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"//\n                + \"`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"`ebay_name` varchar(50)  NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\" + \"PRIMARY KEY USING BTREE (`auth_id`), KEY `ind_usr_id` USING BTREE (`usr_id`)\"//\n                + \") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(7, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"ins_ebay_auth\")));\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE `ins_ebay_auth` (\"//\n                + \"\\n\\t`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',\"\n                + \"\\n\\t`usr_id` int(10) NOT NULL COMMENT '外键，用户表',\"//\n                + \"\\n\\t`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',\"//\n                + \"\\n\\t`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',\"//\n                + \"\\n\\t`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名',\"//\n                + \"\\n\\t`create_time` datetime NOT NULL COMMENT '授权时间',\"//\n                + \"\\n\\t`invalid_time` datetime NOT NULL COMMENT '授权失效时间',\"//\n                + \"\\n\\tPRIMARY KEY USING BTREE (`auth_id`),\"\n                + \"\\n\\tKEY `ind_usr_id` USING BTREE (`usr_id`)\"\n                + \"\\n) ENGINE = InnoDB CHARSET = utf8 COLLATE = utf8_bin COMMENT 'INS_EBAY_AUTH'\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest54.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest54 extends MysqlTest {\n    @Test\n    public void test_UNSIGNED_ZEROFILL() throws Exception {\n        String sql = \"CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, day INT(2) UNSIGNED ZEROFILL);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(3, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE t1 (\" + \"\\n\\tyear YEAR(4),\" + \"\\n\\tmonth INT(2) UNSIGNED ZEROFILL,\"\n                + \"\\n\\tday INT(2) UNSIGNED ZEROFILL\" + \"\\n)\", output);\n    }\n\n    @Test\n    public void test_FOREIGN_KEY() throws Exception {\n        String sql = \"CREATE TABLE `t_activity_node` (\"\n                + \"\\n`id` bigint(20) NOT NULL,\"\n                + \"\\n`sellerId` bigint(20) DEFAULT NULL,\"\n                + \"\\n`canvas_id` bigint(20) NOT NULL COMMENT '画布ID',\"\n                + \"\\n`view_node_id` bigint(20) NOT NULL COMMENT '对应显示的节点id',\"\n                + \"\\n`activity_type` int(11) NOT NULL COMMENT '活动类型',\"\n                + \"\\n`node_type` int(11) NOT NULL COMMENT '节点类型',\"\n                + \"\\n`node_title` varchar(200) NOT NULL COMMENT '节点标题',\"\n                + \"\\n`status` int(11) NOT NULL DEFAULT '0' COMMENT '页面的显示状态',\"\n                + \"\\n`update_status` int(11) DEFAULT NULL COMMENT '节点创建后的修改状态',\"\n                + \"\\n`execute_status` int(11) DEFAULT NULL COMMENT '节点当前的执行状态',\"\n                + \"\\n`start_time` datetime DEFAULT NULL COMMENT '该节点活动的开始时间',\"\n                + \"\\n`end_time` datetime DEFAULT NULL COMMENT '该节点活动的结束时间',\"\n                + \"\\n`activity_start_time` datetime DEFAULT NULL COMMENT '营销活动的开始时间',\"\n                + \"\\n`activity_end_time` datetime DEFAULT NULL COMMENT '营销活动的结束时间',\"\n                + \"\\n`report_start_time` datetime DEFAULT NULL COMMENT '该节点活动效果报告的开始时间',\"\n                + \"\\n`report_end_time` datetime DEFAULT NULL COMMENT '该节点活动效果报告的结束时间',\"\n                + \"\\n`cron_rule` varchar(100) DEFAULT NULL COMMENT '周期性营销的时间表达式',\"\n                + \"\\n`split_rule` varchar(1000) DEFAULT NULL COMMENT '节点拆分规则',\"\n                + \"\\n`search_json` varchar(5000) DEFAULT NULL COMMENT '索引查找的条件字符串',\"\n                + \"\\n`filter_json` varchar(1000) DEFAULT NULL COMMENT '各种过滤条件的设置',\"\n                + \"\\n`buyer_count` int(11) DEFAULT NULL COMMENT '营销的会员数量',\"\n                + \"\\n`gmt_modified` datetime NOT NULL COMMENT '活动最后修改时间',\"\n                + \"\\n`gmt_create` datetime NOT NULL COMMENT '活动创建时间',\"\n                + \"\\nPRIMARY KEY (`id`),\"\n                + \"\\nKEY `canvas_id` (`canvas_id`),\"\n                + \"\\nKEY `sid_ty_time` (`sellerId`,`node_type`,`start_time`),\"\n                + \"\\nCONSTRAINT `t_activity_node_ibfk_1` FOREIGN KEY (`canvas_id`) REFERENCES `t_activity_canvas` (`id`) ON DELETE CASCADE\"\n                + \"\\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(24, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `t_activity_node` (\"\n                    + \"\\n\\t`id` bigint(20) NOT NULL,\"\n                    + \"\\n\\t`sellerId` bigint(20) DEFAULT NULL,\"\n                    + \"\\n\\t`canvas_id` bigint(20) NOT NULL COMMENT '画布ID',\"\n                    + \"\\n\\t`view_node_id` bigint(20) NOT NULL COMMENT '对应显示的节点id',\"\n                    + \"\\n\\t`activity_type` int(11) NOT NULL COMMENT '活动类型',\"\n                    + \"\\n\\t`node_type` int(11) NOT NULL COMMENT '节点类型',\"\n                    + \"\\n\\t`node_title` varchar(200) NOT NULL COMMENT '节点标题',\"\n                    + \"\\n\\t`status` int(11) NOT NULL DEFAULT '0' COMMENT '页面的显示状态',\"\n                    + \"\\n\\t`update_status` int(11) DEFAULT NULL COMMENT '节点创建后的修改状态',\"\n                    + \"\\n\\t`execute_status` int(11) DEFAULT NULL COMMENT '节点当前的执行状态',\"\n                    + \"\\n\\t`start_time` datetime DEFAULT NULL COMMENT '该节点活动的开始时间',\"\n                    + \"\\n\\t`end_time` datetime DEFAULT NULL COMMENT '该节点活动的结束时间',\"\n                    + \"\\n\\t`activity_start_time` datetime DEFAULT NULL COMMENT '营销活动的开始时间',\"\n                    + \"\\n\\t`activity_end_time` datetime DEFAULT NULL COMMENT '营销活动的结束时间',\"\n                    + \"\\n\\t`report_start_time` datetime DEFAULT NULL COMMENT '该节点活动效果报告的开始时间',\"\n                    + \"\\n\\t`report_end_time` datetime DEFAULT NULL COMMENT '该节点活动效果报告的结束时间',\"\n                    + \"\\n\\t`cron_rule` varchar(100) DEFAULT NULL COMMENT '周期性营销的时间表达式',\"\n                    + \"\\n\\t`split_rule` varchar(1000) DEFAULT NULL COMMENT '节点拆分规则',\"\n                    + \"\\n\\t`search_json` varchar(5000) DEFAULT NULL COMMENT '索引查找的条件字符串',\"\n                    + \"\\n\\t`filter_json` varchar(1000) DEFAULT NULL COMMENT '各种过滤条件的设置',\"\n                    + \"\\n\\t`buyer_count` int(11) DEFAULT NULL COMMENT '营销的会员数量',\"\n                    + \"\\n\\t`gmt_modified` datetime NOT NULL COMMENT '活动最后修改时间',\"\n                    + \"\\n\\t`gmt_create` datetime NOT NULL COMMENT '活动创建时间',\"\n                    + \"\\n\\tPRIMARY KEY (`id`),\"\n                    + \"\\n\\tKEY `canvas_id` (`canvas_id`),\"\n                    + \"\\n\\tKEY `sid_ty_time` (`sellerId`, `node_type`, `start_time`),\"\n                    + \"\\n\\tCONSTRAINT `t_activity_node_ibfk_1` FOREIGN KEY (`canvas_id`) REFERENCES `t_activity_canvas` (`id`) ON DELETE CASCADE\"\n                    + \"\\n) ENGINE = InnoDB CHARSET = utf8\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `t_activity_node` (\"\n                    + \"\\n\\t`id` bigint(20) not null,\"\n                    + \"\\n\\t`sellerId` bigint(20) default null,\"\n                    + \"\\n\\t`canvas_id` bigint(20) not null comment '画布ID',\"\n                    + \"\\n\\t`view_node_id` bigint(20) not null comment '对应显示的节点id',\"\n                    + \"\\n\\t`activity_type` int(11) not null comment '活动类型',\"\n                    + \"\\n\\t`node_type` int(11) not null comment '节点类型',\"\n                    + \"\\n\\t`node_title` varchar(200) not null comment '节点标题',\"\n                    + \"\\n\\t`status` int(11) not null default '0' comment '页面的显示状态',\"\n                    + \"\\n\\t`update_status` int(11) default null comment '节点创建后的修改状态',\"\n                    + \"\\n\\t`execute_status` int(11) default null comment '节点当前的执行状态',\"\n                    + \"\\n\\t`start_time` datetime default null comment '该节点活动的开始时间',\"\n                    + \"\\n\\t`end_time` datetime default null comment '该节点活动的结束时间',\"\n                    + \"\\n\\t`activity_start_time` datetime default null comment '营销活动的开始时间',\"\n                    + \"\\n\\t`activity_end_time` datetime default null comment '营销活动的结束时间',\"\n                    + \"\\n\\t`report_start_time` datetime default null comment '该节点活动效果报告的开始时间',\"\n                    + \"\\n\\t`report_end_time` datetime default null comment '该节点活动效果报告的结束时间',\"\n                    + \"\\n\\t`cron_rule` varchar(100) default null comment '周期性营销的时间表达式',\"\n                    + \"\\n\\t`split_rule` varchar(1000) default null comment '节点拆分规则',\"\n                    + \"\\n\\t`search_json` varchar(5000) default null comment '索引查找的条件字符串',\"\n                    + \"\\n\\t`filter_json` varchar(1000) default null comment '各种过滤条件的设置',\"\n                    + \"\\n\\t`buyer_count` int(11) default null comment '营销的会员数量',\"\n                    + \"\\n\\t`gmt_modified` datetime not null comment '活动最后修改时间',\"\n                    + \"\\n\\t`gmt_create` datetime not null comment '活动创建时间',\"\n                    + \"\\n\\tprimary key (`id`),\"\n                    + \"\\n\\tkey `canvas_id` (`canvas_id`),\"\n                    + \"\\n\\tkey `sid_ty_time` (`sellerId`, `node_type`, `start_time`),\"\n                    + \"\\n\\tconstraint `t_activity_node_ibfk_1` foreign key (`canvas_id`) references `t_activity_canvas` (`id`) on delete cascade\"\n                    + \"\\n) engine = InnoDB charset = utf8\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest55.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest55 extends MysqlTest {\n    @Test\n    public void test_union() throws Exception {\n        String sql = \"CREATE TABLE tableA (datasn varchar(100) NOT NULL,PRIMARY KEY(datasn)) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 UNION=(tableB)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE tableA (\"\n                + \"\\n\\tdatasn varchar(100) NOT NULL,\"\n                + \"\\n\\tPRIMARY KEY (datasn)\"\n                + \"\\n) ENGINE = MRG_MyISAM CHARSET = utf8 UNION = (tableB)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest56.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest56 extends MysqlTest {\n    @Test\n    public void test_union() throws Exception {\n        String sql = \"CREATE TABLE tableA (datasn varchar(100) NOT NULL,PRIMARY KEY(datasn)) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 UNION=(tableB,tableC)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(3, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE tableA (\"\n                    + \"\\n\\tdatasn varchar(100) NOT NULL,\"\n                    + \"\\n\\tPRIMARY KEY (datasn)\"\n                    + \"\\n) ENGINE = MRG_MyISAM CHARSET = utf8 UNION = (tableB, tableC)\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table tableA (\"\n                    + \"\\n\\tdatasn varchar(100) not null,\"\n                    + \"\\n\\tprimary key (datasn)\"\n                    + \"\\n) engine = MRG_MyISAM charset = utf8 union = (tableB, tableC)\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest57.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest57 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `t_cpi_driskconfig_bak` (\" + \"`Sequence` bigint(20) NOT NULL AUTO_INCREMENT,\"\n                + \"`comcode` varchar(20) binary NOT NULL,\" + \"`riskcode` varchar(10) binary NOT NULL,\"\n                + \"`configcodehead` varchar(30) binary NOT NULL,\" + \"`configcodebody` varchar(100) binary,\"\n                + \"`configvalue` varchar(200) binary ,\" + \"`inputdate` datetime NOT NULL,\"\n                + \"`validstatus` char(1) NOT NULL,\" + \"`remark` varchar(3000),\" + \"`flag` varchar(10) ,\"\n                + \"PRIMARY KEY (`Sequence`)\" + \") ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(10, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE `t_cpi_driskconfig_bak` (\" + \"\\n\\t`Sequence` bigint(20) NOT NULL AUTO_INCREMENT,\"\n                + \"\\n\\t`comcode` varchar(20) BINARY  NOT NULL,\" + \"\\n\\t`riskcode` varchar(10) BINARY  NOT NULL,\"\n                + \"\\n\\t`configcodehead` varchar(30) BINARY  NOT NULL,\" + \"\\n\\t`configcodebody` varchar(100) BINARY ,\"\n                + \"\\n\\t`configvalue` varchar(200) BINARY ,\" + \"\\n\\t`inputdate` datetime NOT NULL,\"\n                + \"\\n\\t`validstatus` char(1) NOT NULL,\" + \"\\n\\t`remark` varchar(3000),\" + \"\\n\\t`flag` varchar(10),\"\n                + \"\\n\\tPRIMARY KEY (`Sequence`)\" + \"\\n) ENGINE = InnoDB AUTO_INCREMENT = 49 CHARSET = utf8\", output);\n    }\n\n    @Test\n    public void test_two() throws Exception {\n        String sql = \"CREATE TABLE `t_cpi_driskconfig_bak` (\" + \"`Sequence` bigint(20) NOT NULL AUTO_INCREMENT,\"\n                + \"`comcode` binary(20) NOT NULL,\" + \"`riskcode` varchar(10) binary NOT NULL,\"\n                + \"`configcodehead` varchar(30) binary NOT NULL,\" + \"`configcodebody` varchar(100) binary,\"\n                + \"`configvalue` varchar(200) binary ,\" + \"`inputdate` datetime NOT NULL,\"\n                + \"`validstatus` char(1) NOT NULL,\" + \"`remark` varchar(3000),\" + \"`flag` varchar(10) ,\"\n                + \"PRIMARY KEY (`Sequence`)\" + \") ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(10, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE `t_cpi_driskconfig_bak` (\" + \"\\n\\t`Sequence` bigint(20) NOT NULL AUTO_INCREMENT,\"\n                + \"\\n\\t`comcode` binary(20) NOT NULL,\" + \"\\n\\t`riskcode` varchar(10) BINARY  NOT NULL,\"\n                + \"\\n\\t`configcodehead` varchar(30) BINARY  NOT NULL,\" + \"\\n\\t`configcodebody` varchar(100) BINARY ,\"\n                + \"\\n\\t`configvalue` varchar(200) BINARY ,\" + \"\\n\\t`inputdate` datetime NOT NULL,\"\n                + \"\\n\\t`validstatus` char(1) NOT NULL,\" + \"\\n\\t`remark` varchar(3000),\" + \"\\n\\t`flag` varchar(10),\"\n                + \"\\n\\tPRIMARY KEY (`Sequence`)\" + \"\\n) ENGINE = InnoDB AUTO_INCREMENT = 49 CHARSET = utf8\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest58.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest58 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `appservice_account` (\" + \"`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\"\n                + \"`password` varchar(128) NOT NULL,\" + \"`last_login` datetime NOT NULL,\"\n                + \"`username` varchar(40) NOT NULL UNIQUE,\" + \"`date_of_birth` date NOT NULL,\"\n                + \"`head` varchar(100) NOT NULL,\" + \"`headThumb` varchar(100) NOT NULL,\"\n                + \"`name` varchar(50) NOT NULL,\" + \"`gender` integer,\" + \"`uploadVideoCount` integer NOT NULL,\"\n                + \"`fansCount` integer NOT NULL,\" + \"`balance` numeric(19, 2) NOT NULL,\"\n                + \"`brick` integer NOT NULL,\" + \"`reward` integer NOT NULL,\" + \"`token` varchar(500) NOT NULL,\"\n                + \"`weiboUserid` varchar(50) NOT NULL,\" + \"`weiboAccesstoken` varchar(500) NOT NULL,\"\n                + \"`qqUserid` varchar(50) NOT NULL,\" + \"`qqAccesstoken` varchar(500) NOT NULL,\"\n                + \"`wechatUserid` varchar(50) NOT NULL,\" + \"`wechatAccesstoken` varchar(500) NOT NULL,\"\n                + \"`is_active` bool NOT NULL,\" + \"`is_admin` bool NOT NULL\" + \")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `appservice_account` (\" +\n                    \"\\n\\t`id` integer NOT NULL PRIMARY KEY AUTO_INCREMENT,\" +\n                    \"\\n\\t`password` varchar(128) NOT NULL,\" +\n                    \"\\n\\t`last_login` datetime NOT NULL,\" +\n                    \"\\n\\t`username` varchar(40) NOT NULL UNIQUE,\" +\n                    \"\\n\\t`date_of_birth` date NOT NULL,\" +\n                    \"\\n\\t`head` varchar(100) NOT NULL,\" +\n                    \"\\n\\t`headThumb` varchar(100) NOT NULL,\" +\n                    \"\\n\\t`name` varchar(50) NOT NULL,\" +\n                    \"\\n\\t`gender` integer,\" +\n                    \"\\n\\t`uploadVideoCount` integer NOT NULL,\" +\n                    \"\\n\\t`fansCount` integer NOT NULL,\" +\n                    \"\\n\\t`balance` numeric(19, 2) NOT NULL,\" +\n                    \"\\n\\t`brick` integer NOT NULL,\" +\n                    \"\\n\\t`reward` integer NOT NULL,\" +\n                    \"\\n\\t`token` varchar(500) NOT NULL,\" +\n                    \"\\n\\t`weiboUserid` varchar(50) NOT NULL,\" +\n                    \"\\n\\t`weiboAccesstoken` varchar(500) NOT NULL,\" +\n                    \"\\n\\t`qqUserid` varchar(50) NOT NULL,\" +\n                    \"\\n\\t`qqAccesstoken` varchar(500) NOT NULL,\" +\n                    \"\\n\\t`wechatUserid` varchar(50) NOT NULL,\" +\n                    \"\\n\\t`wechatAccesstoken` varchar(500) NOT NULL,\" +\n                    \"\\n\\t`is_active` bool NOT NULL,\" +\n                    \"\\n\\t`is_admin` bool NOT NULL\" +\n                    \"\\n)\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `appservice_account` (\" +\n                    \"\\n\\t`id` integer not null primary key auto_increment,\" +\n                    \"\\n\\t`password` varchar(128) not null,\" +\n                    \"\\n\\t`last_login` datetime not null,\" +\n                    \"\\n\\t`username` varchar(40) not null unique,\" +\n                    \"\\n\\t`date_of_birth` date not null,\" +\n                    \"\\n\\t`head` varchar(100) not null,\" +\n                    \"\\n\\t`headThumb` varchar(100) not null,\" +\n                    \"\\n\\t`name` varchar(50) not null,\" +\n                    \"\\n\\t`gender` integer,\" +\n                    \"\\n\\t`uploadVideoCount` integer not null,\" +\n                    \"\\n\\t`fansCount` integer not null,\" +\n                    \"\\n\\t`balance` numeric(19, 2) not null,\" +\n                    \"\\n\\t`brick` integer not null,\" +\n                    \"\\n\\t`reward` integer not null,\" +\n                    \"\\n\\t`token` varchar(500) not null,\" +\n                    \"\\n\\t`weiboUserid` varchar(50) not null,\" +\n                    \"\\n\\t`weiboAccesstoken` varchar(500) not null,\" +\n                    \"\\n\\t`qqUserid` varchar(50) not null,\" +\n                    \"\\n\\t`qqAccesstoken` varchar(500) not null,\" +\n                    \"\\n\\t`wechatUserid` varchar(50) not null,\" +\n                    \"\\n\\t`wechatAccesstoken` varchar(500) not null,\" +\n                    \"\\n\\t`is_active` bool not null,\" +\n                    \"\\n\\t`is_admin` bool not null\" +\n                    \"\\n)\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest59.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest59 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table t3 (a long, b long byte);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        String output = SQLUtils.toMySqlString(stmt);\n        assertEquals(\"CREATE TABLE t3 (\"\n                + \"\\n\\ta long,\"\n                + \"\\n\\tb long byte\"\n                + \"\\n)\", output);\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest6.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest6 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE Persons\\n\" +\n                \"(\\n\" +\n                \"Id_P int NOT NULL,\\n\" +\n                \"LastName varchar(255) NOT NULL,\\n\" +\n                \"FirstName varchar(255),\\n\" +\n                \"Address varchar(255),\\n\" +\n                \"City varchar(255),\\n\" +\n                \"UNIQUE (Id_P)\\n\" +\n                \")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"Persons\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"Persons\", \"Id_P\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"Persons\", \"LastName\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest60.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest60 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table t10 (pk int auto_increment primary key,f1 varchar(65500) charset latin1);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t10 (\\n\" +\n                    \"\\tpk int PRIMARY KEY AUTO_INCREMENT,\\n\" +\n                    \"\\tf1 varchar(65500) CHARACTER SET latin1\\n\" +\n                    \")\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t10 (\\n\" +\n                    \"\\tpk int primary key auto_increment,\\n\" +\n                    \"\\tf1 varchar(65500) character set latin1\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest61.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest61 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table t (pk int auto_increment primary key,a timestamp null default current_timestamp on update current_timestamp, b timestamp null)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t (\"\n                    + \"\\n\\tpk int PRIMARY KEY AUTO_INCREMENT,\"\n                    + \"\\n\\ta timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\"\n                    + \"\\n\\tb timestamp NULL\"\n                    + \"\\n)\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t (\"\n                    + \"\\n\\tpk int primary key auto_increment,\"\n                    + \"\\n\\ta timestamp null default current_timestamp on update current_timestamp,\"\n                    + \"\\n\\tb timestamp null\"\n                    + \"\\n)\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest62.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest62 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table a ( b varchar(15) CHARACTER SET latin1 DEFAULT NULL)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE a (\"\n                    + \"\\n\\tb varchar(15) CHARACTER SET latin1 DEFAULT NULL\"\n                    + \"\\n)\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table a (\"\n                    + \"\\n\\tb varchar(15) character set latin1 default null\"\n                    + \"\\n)\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest63.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest63 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE t (pk int auto_increment primary key, a TIMESTAMP, KEY ( a DESC ) );\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t (\"\n                    + \"\\n\\tpk int PRIMARY KEY AUTO_INCREMENT,\"\n                    + \"\\n\\ta TIMESTAMP,\"\n                    + \"\\n\\tKEY (a DESC)\"\n                    + \"\\n)\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t (\"\n                    + \"\\n\\tpk int primary key auto_increment,\"\n                    + \"\\n\\ta TIMESTAMP,\"\n                    + \"\\n\\tkey (a desc)\"\n                    + \"\\n)\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest64.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest64 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table t (c char(10) ,unique key a using hash (c(1))) charset = utf8mb4 engine=heap;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t (\"\n                    + \"\\n\\tc char(10),\"\n                    + \"\\n\\tUNIQUE KEY a USING hash (c(1))\"\n                    + \"\\n) CHARSET = utf8mb4 ENGINE = heap\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t (\"\n                    + \"\\n\\tc char(10),\"\n                    + \"\\n\\tunique key a using hash (c(1))\"\n                    + \"\\n) charset = utf8mb4 engine = heap\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest65.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest65 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table t (c char(10) ,unique key a using btree (c(1))) charset = utf8mb4 engine=heap;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t (\"\n                    + \"\\n\\tc char(10),\"\n                    + \"\\n\\tUNIQUE KEY a USING btree (c(1))\"\n                    + \"\\n) CHARSET = utf8mb4 ENGINE = heap\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t (\"\n                    + \"\\n\\tc char(10),\"\n                    + \"\\n\\tunique key a using btree (c(1))\"\n                    + \"\\n) charset = utf8mb4 engine = heap\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest66.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest66 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table hp_db.g20_relationship_communication_daily(                   \"\n                + \" a_iden_string    varchar,\"\n                + \" b_iden_string    varchar,\"\n                + \" counter          bigint,\"\n                + \" durationtime     bigint\"\n                + \") \"\n                + \"\\nPARTITION BY HASH KEY(a_iden_string) PARTITION NUM 100\"\n                + \"\\nSUBPARTITION BY LIST(bdt bigint)\"\n                + \"\\nSUBPARTITION OPTIONS(available_Partition_Num=90)\"\n                + \"\\nTABLEGROUP g20_test_group;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE hp_db.g20_relationship_communication_daily (\"\n                    + \"\\n\\ta_iden_string varchar,\"\n                    + \"\\n\\tb_iden_string varchar,\"\n                    + \"\\n\\tcounter bigint,\"\n                    + \"\\n\\tdurationtime bigint\"\n                    + \"\\n)\"\n                    + \"\\nPARTITION BY HASH KEY(a_iden_string) PARTITION NUM 100\"\n                    + \"\\nSUBPARTITION BY LIST (bdt bigint)\"\n                    + \"\\nSUBPARTITION OPTIONS (available_Partition_Num = 90)\"\n                    + \"\\nTABLEGROUP g20_test_group\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table hp_db.g20_relationship_communication_daily (\"\n                    + \"\\n\\ta_iden_string varchar,\"\n                    + \"\\n\\tb_iden_string varchar,\"\n                    + \"\\n\\tcounter bigint,\"\n                    + \"\\n\\tdurationtime bigint\"\n                    + \"\\n)\"\n                    + \"\\npartition by hash key(a_iden_string) partition num 100\"\n                    + \"\\nsubpartition by list (bdt bigint)\"\n                    + \"\\nsubpartition options (available_Partition_Num = 90)\"\n                    + \"\\ntablegroup g20_test_group\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest67.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest67 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE t1 ( a INT NOT NULL, PRIMARY KEY (a))\"\n                + \" ENGINE=InnoDB TABLESPACE ts1                            \"\n                + \" PARTITION BY RANGE (a) PARTITIONS 3 (\"\n                + \" PARTITION P1 VALUES LESS THAN (2),\"\n                + \" PARTITION P2 VALUES LESS THAN (4) TABLESPACE ts2,\"\n                + \" PARTITION P3 VALUES LESS THAN (6) TABLESPACE ts3);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t1 (\\n\" +\n                    \"\\ta INT NOT NULL,\\n\" +\n                    \"\\tPRIMARY KEY (a)\\n\" +\n                    \") ENGINE = InnoDB TABLESPACE ts1\\n\" +\n                    \"PARTITION BY RANGE COLUMNS (a) PARTITIONS 3 (\\n\" +\n                    \"\\tPARTITION P1 VALUES LESS THAN (2),\\n\" +\n                    \"\\tPARTITION P2 VALUES LESS THAN (4)\\n\" +\n                    \"\\t\\tTABLESPACE ts2,\\n\" +\n                    \"\\tPARTITION P3 VALUES LESS THAN (6)\\n\" +\n                    \"\\t\\tTABLESPACE ts3\\n\" +\n                    \")\", output);\n        }\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t1 (\\n\" +\n                    \"\\ta INT not null,\\n\" +\n                    \"\\tprimary key (a)\\n\" +\n                    \") engine = InnoDB tablespace ts1\\n\" +\n                    \"partition by range columns (a) partitions 3 (\\n\" +\n                    \"\\tpartition P1 values less than (2),\\n\" +\n                    \"\\tpartition P2 values less than (4)\\n\" +\n                    \"\\t\\ttablespace ts2,\\n\" +\n                    \"\\tpartition P3 values less than (6)\\n\" +\n                    \"\\t\\ttablespace ts3\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest68.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest68 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE t1 (\"\n                + \"\\n\\tyear_col  INT,\"\n                + \"\\n\\tsome_data INT\"\n                + \"\\n)\"\n                + \"\\nPARTITION BY RANGE (year_col) (\"\n                + \"    PARTITION p0 VALUES LESS THAN (1991),\"\n                + \"    PARTITION p1 VALUES LESS THAN (1995),\"\n                + \"    PARTITION p2 VALUES LESS THAN (1999),\"\n                + \"    PARTITION p3 VALUES LESS THAN (2002),\"\n                + \"    PARTITION p4 VALUES LESS THAN (2006),\"\n                + \"    PARTITION p5 VALUES LESS THAN MAXVALUE\"\n                + \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t1 (\"\n                    + \"\\n\\tyear_col INT,\"\n                    + \"\\n\\tsome_data INT\"\n                    + \"\\n)\"\n                    + \"\\nPARTITION BY RANGE COLUMNS (year_col) (\"\n                    + \"\\n\\tPARTITION p0 VALUES LESS THAN (1991),\"\n                    + \"\\n\\tPARTITION p1 VALUES LESS THAN (1995),\"\n                    + \"\\n\\tPARTITION p2 VALUES LESS THAN (1999),\"\n                    + \"\\n\\tPARTITION p3 VALUES LESS THAN (2002),\"\n                    + \"\\n\\tPARTITION p4 VALUES LESS THAN (2006),\"\n                    + \"\\n\\tPARTITION p5 VALUES LESS THAN MAXVALUE\"\n                    + \"\\n)\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t1 (\"\n                    + \"\\n\\tyear_col INT,\"\n                    + \"\\n\\tsome_data INT\"\n                    + \"\\n)\"\n                    + \"\\npartition by range columns (year_col) (\"\n                    + \"\\n\\tpartition p0 values less than (1991),\"\n                    + \"\\n\\tpartition p1 values less than (1995),\"\n                    + \"\\n\\tpartition p2 values less than (1999),\"\n                    + \"\\n\\tpartition p3 values less than (2002),\"\n                    + \"\\n\\tpartition p4 values less than (2006),\"\n                    + \"\\n\\tpartition p5 values less than maxvalue\"\n                    + \"\\n)\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest69.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest69 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE t1 (\"\n                + \"  s1 INT,\"\n                + \"  s2 INT AS (EXP(s1)) STORED\"\n                + \")\"\n                + \"PARTITION BY LIST (s2) (\"\n                + \"  PARTITION p1 VALUES IN (1)\"\n                + \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t1 (\\n\" +\n                    \"\\ts1 INT,\\n\" +\n                    \"\\ts2 INT AS (EXP(s1)) STORED\\n\" +\n                    \")\\n\" +\n                    \"PARTITION BY LIST (s2) (\\n\" +\n                    \"\\tPARTITION p1 VALUES IN (1)\\n\" +\n                    \")\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t1 (\\n\" +\n                    \"\\ts1 INT,\\n\" +\n                    \"\\ts2 INT as (EXP(s1)) stored\\n\" +\n                    \")\\n\" +\n                    \"partition by list (s2) (\\n\" +\n                    \"\\tpartition p1 values in (1)\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest7.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest7 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE Orders\\n\" +\n                \"(\\n\" +\n                \"O_Id int NOT NULL,\\n\" +\n                \"OrderNo int NOT NULL,\\n\" +\n                \"Id_P int,\\n\" +\n                \"PRIMARY KEY (O_Id),\\n\" +\n                \"FOREIGN KEY (Id_P) REFERENCES Persons(Id_P)\\n\" +\n                \")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(2, visitor.getTables().size());\n        assertEquals(4, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"Orders\")));\n\n        assertTrue(visitor.containsColumn(\"Orders\", \"O_Id\"));\n        assertTrue(visitor.containsColumn(\"Orders\", \"OrderNo\"));\n        assertTrue(visitor.containsColumn(\"Orders\", \"Id_P\"));\n\n        SQLColumnDefinition column = stmt.findColumn(\"O_id\");\n        assertNotNull(column);\n        assertEquals(1, column.getConstraints().size());\n        assertTrue(column.isPrimaryKey());\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest70.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest70 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `app_customer_license` (\"\n                + \"  `id`  bigint(20) NOT NULL AUTO_INCREMENT ,\"\n                + \"  `created_by`  varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,\"\n                + \"  `created_date`  datetime NOT NULL ,\"\n                + \"  `last_modified_by`  varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,\"\n                + \"  `last_modified_date`  datetime NULL DEFAULT NULL ,\"\n                + \"  `version`  bigint(20) NOT NULL ,\"\n                + \"  `device_id`  varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,\"\n                + \"  `customer_info`  bigint(20) NULL DEFAULT NULL ,\"\n                + \"  PRIMARY KEY (`id`),\"\n                + \"  FOREIGN KEY (`customer_info`) REFERENCES `app_customer_info` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,\"\n                + \"  INDEX `fk_app_customer_info_id` (`customer_info`) USING BTREE,\"\n                + \"  UNIQUE `idx_app_customer_license_deviceId` (`device_id`) USING BTREE\"\n                + \")\"\n                + \"ENGINE=InnoDB \"\n                + \"DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci \"\n                + \"AUTO_INCREMENT=1 \"\n                + \"ROW_FORMAT=DYNAMIC \"\n                + \";;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"app_customer_license\", \"version\");\n        assertNotNull(column);\n        assertEquals(\"bigint\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `app_customer_license` (\"\n                    + \"\\n\\t`id` bigint(20) NOT NULL AUTO_INCREMENT,\"\n                    + \"\\n\\t`created_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\"\n                    + \"\\n\\t`created_date` datetime NOT NULL,\"\n                    + \"\\n\\t`last_modified_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\"\n                    + \"\\n\\t`last_modified_date` datetime NULL DEFAULT NULL,\"\n                    + \"\\n\\t`version` bigint(20) NOT NULL,\"\n                    + \"\\n\\t`device_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\"\n                    + \"\\n\\t`customer_info` bigint(20) NULL DEFAULT NULL,\"\n                    + \"\\n\\tPRIMARY KEY (`id`),\"\n                    + \"\\n\\tFOREIGN KEY (`customer_info`) REFERENCES `app_customer_info` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,\"\n                    + \"\\n\\tINDEX `fk_app_customer_info_id` USING BTREE(`customer_info`),\"\n                    + \"\\n\\tUNIQUE `idx_app_customer_license_deviceId` USING BTREE (`device_id`)\"\n                    + \"\\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci AUTO_INCREMENT = 1 ROW_FORMAT = DYNAMIC\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `app_customer_license` (\"\n                    + \"\\n\\t`id` bigint(20) not null auto_increment,\"\n                    + \"\\n\\t`created_by` varchar(50) character set utf8 collate utf8_general_ci not null,\"\n                    + \"\\n\\t`created_date` datetime not null,\"\n                    + \"\\n\\t`last_modified_by` varchar(50) character set utf8 collate utf8_general_ci null default null,\"\n                    + \"\\n\\t`last_modified_date` datetime null default null,\"\n                    + \"\\n\\t`version` bigint(20) not null,\"\n                    + \"\\n\\t`device_id` varchar(20) character set utf8 collate utf8_general_ci not null,\"\n                    + \"\\n\\t`customer_info` bigint(20) null default null,\"\n                    + \"\\n\\tprimary key (`id`),\"\n                    + \"\\n\\tforeign key (`customer_info`) references `app_customer_info` (`id`) on delete restrict on update restrict,\"\n                    + \"\\n\\tindex `fk_app_customer_info_id` using BTREE(`customer_info`),\"\n                    + \"\\n\\tunique `idx_app_customer_license_deviceId` using BTREE (`device_id`)\"\n                    + \"\\n) engine = InnoDB character set = utf8 collate = utf8_general_ci auto_increment = 1 row_format = DYNAMIC\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest73.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest73 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE total (\"\n                + \"    id INT NOT NULL AUTO_INCREMENT,\"\n                + \"    message CHAR(20), INDEX(a))\"\n                + \"    ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"total\", \"id\");\n        assertNotNull(column);\n        assertEquals(\"INT\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE total (\"\n                    + \"\\n\\tid INT NOT NULL AUTO_INCREMENT,\"\n                    + \"\\n\\tmessage CHAR(20),\"\n                    + \"\\n\\tINDEX(a)\"\n                    + \"\\n) ENGINE = MERGE UNION = (t1, t2) INSERT_METHOD = LAST\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table total (\"\n                    + \"\\n\\tid INT not null auto_increment,\"\n                    + \"\\n\\tmessage CHAR(20),\"\n                    + \"\\n\\tindex(a)\"\n                    + \"\\n) engine = MERGE union = (t1, t2) insert_method = LAST\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest74.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest74 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"create table test.simple_test (\\n\" +\n                \"col_key bigint(20) not null auto_increment,\\n\" +\n                \"col1 varchar(45) null,\\n\" +\n                \"col2 tinyint(4) null,\\n\" +\n                \"col3 datetime null,\\n\" +\n                \"col4 timestamp null default current_timestamp on update current_timestamp,\\n\" +\n                \"primary key (col_key),\\n\" +\n                \"unique index v1_unique (col_key asc))\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"test.simple_test\", \"col_key\");\n        assertNotNull(column);\n        assertEquals(\"bigint\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE test.simple_test (\\n\" +\n                    \"\\tcol_key bigint(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                    \"\\tcol1 varchar(45) NULL,\\n\" +\n                    \"\\tcol2 tinyint(4) NULL,\\n\" +\n                    \"\\tcol3 datetime NULL,\\n\" +\n                    \"\\tcol4 timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                    \"\\tPRIMARY KEY (col_key),\\n\" +\n                    \"\\tUNIQUE INDEX v1_unique (col_key ASC)\\n\" +\n                    \")\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table test.simple_test (\\n\" +\n                    \"\\tcol_key bigint(20) not null auto_increment,\\n\" +\n                    \"\\tcol1 varchar(45) null,\\n\" +\n                    \"\\tcol2 tinyint(4) null,\\n\" +\n                    \"\\tcol3 datetime null,\\n\" +\n                    \"\\tcol4 timestamp null default current_timestamp on update current_timestamp,\\n\" +\n                    \"\\tprimary key (col_key),\\n\" +\n                    \"\\tunique index v1_unique (col_key asc)\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest75.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest75 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `sys_msg_entry_0320` (\\n\" +\n                \"  `provider_dsp_name` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息提供者的显示名，提供给一些需要统一发送名称的系统消息',\\n\" +\n                \"  `template_data` varchar(2048) NOT NULL /*!50616 COLUMN_FORMAT COMPRESSED */ COMMENT '模板渲染时使用的数据,key-value对',\\n\" +\n                \"  `template_merge_data` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '对于需要合并的消息，被合并的参数放在此处理',\\n\" +\n                \"  `expiration_date` datetime NOT NULL COMMENT '失效日期，精度到天,查询和任务处理时使用',\\n\" +\n                \"  `merge_key` varchar(128) DEFAULT NULL COMMENT '消息合并主键，合并成功的消息，不参与计数',\\n\" +\n                \"  `out_id` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '外部关联源的id',\\n\" +\n                \"  `number_expiration_date` datetime DEFAULT NULL COMMENT '计数过期时间',\\n\" +\n                \"  `hidden` int(11) DEFAULT '0' COMMENT '标记是否在吊顶展示，1表示隐藏，0表示展示',\\n\" +\n                \"  `popup` tinyint(3) unsigned DEFAULT '0' COMMENT '表示消息提醒方式:0-数字提醒，1-layer，2-popup',\\n\" +\n                \"  `tag_id` bigint(20) unsigned DEFAULT NULL COMMENT 'TAG标志',\\n\" +\n                \"  `attribute` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息的一些属性',\\n\" +\n                \"  `original_msg_ids` varchar(1024) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '原始消息ID，多个id用半角逗号隔开',\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `idx_expiration_date` (`expiration_date`),\\n\" +\n                \"  KEY `k_rid_hidd_cid` (`receiver_id`,`hidden`,`cat_id`,`expiration_date`),\\n\" +\n                \"  KEY `k_rid_aid_tid` (`receiver_id`,`app_id`,`type_id`,`expiration_date`),\\n\" +\n                \"  KEY `k_rid_stat_popup` (`receiver_id`,`status`,`popup`,`expiration_date`),\\n\" +\n                \"  KEY `k_tid` (`tag_id`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=167279613030 DEFAULT CHARSET=gbk COMMENT='消息实体表'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"sys_msg_entry_0320\", \"provider_dsp_name\");\n        assertNotNull(column);\n        assertEquals(\"varchar\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `sys_msg_entry_0320` (\\n\" +\n                    \"\\t`provider_dsp_name` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息提供者的显示名，提供给一些需要统一发送名称的系统消息',\\n\" +\n                    \"\\t`template_data` varchar(2048) NOT NULL /*!50616 COLUMN_FORMAT COMPRESSED */ COMMENT '模板渲染时使用的数据,key-value对',\\n\" +\n                    \"\\t`template_merge_data` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '对于需要合并的消息，被合并的参数放在此处理',\\n\" +\n                    \"\\t`expiration_date` datetime NOT NULL COMMENT '失效日期，精度到天,查询和任务处理时使用',\\n\" +\n                    \"\\t`merge_key` varchar(128) DEFAULT NULL COMMENT '消息合并主键，合并成功的消息，不参与计数',\\n\" +\n                    \"\\t`out_id` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '外部关联源的id',\\n\" +\n                    \"\\t`number_expiration_date` datetime DEFAULT NULL COMMENT '计数过期时间',\\n\" +\n                    \"\\t`hidden` int(11) DEFAULT '0' COMMENT '标记是否在吊顶展示，1表示隐藏，0表示展示',\\n\" +\n                    \"\\t`popup` tinyint(3) UNSIGNED DEFAULT '0' COMMENT '表示消息提醒方式:0-数字提醒，1-layer，2-popup',\\n\" +\n                    \"\\t`tag_id` bigint(20) UNSIGNED DEFAULT NULL COMMENT 'TAG标志',\\n\" +\n                    \"\\t`attribute` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息的一些属性',\\n\" +\n                    \"\\t`original_msg_ids` varchar(1024) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '原始消息ID，多个id用半角逗号隔开',\\n\" +\n                    \"\\tPRIMARY KEY (`id`),\\n\" +\n                    \"\\tKEY `idx_expiration_date` (`expiration_date`),\\n\" +\n                    \"\\tKEY `k_rid_hidd_cid` (`receiver_id`, `hidden`, `cat_id`, `expiration_date`),\\n\" +\n                    \"\\tKEY `k_rid_aid_tid` (`receiver_id`, `app_id`, `type_id`, `expiration_date`),\\n\" +\n                    \"\\tKEY `k_rid_stat_popup` (`receiver_id`, `status`, `popup`, `expiration_date`),\\n\" +\n                    \"\\tKEY `k_tid` (`tag_id`)\\n\" +\n                    \") ENGINE = InnoDB AUTO_INCREMENT = 167279613030 CHARSET = gbk COMMENT '消息实体表'\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `sys_msg_entry_0320` (\\n\" +\n                    \"\\t`provider_dsp_name` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '消息提供者的显示名，提供给一些需要统一发送名称的系统消息',\\n\" +\n                    \"\\t`template_data` varchar(2048) not null /*!50616 COLUMN_FORMAT COMPRESSED */ comment '模板渲染时使用的数据,key-value对',\\n\" +\n                    \"\\t`template_merge_data` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '对于需要合并的消息，被合并的参数放在此处理',\\n\" +\n                    \"\\t`expiration_date` datetime not null comment '失效日期，精度到天,查询和任务处理时使用',\\n\" +\n                    \"\\t`merge_key` varchar(128) default null comment '消息合并主键，合并成功的消息，不参与计数',\\n\" +\n                    \"\\t`out_id` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '外部关联源的id',\\n\" +\n                    \"\\t`number_expiration_date` datetime default null comment '计数过期时间',\\n\" +\n                    \"\\t`hidden` int(11) default '0' comment '标记是否在吊顶展示，1表示隐藏，0表示展示',\\n\" +\n                    \"\\t`popup` tinyint(3) unsigned default '0' comment '表示消息提醒方式:0-数字提醒，1-layer，2-popup',\\n\" +\n                    \"\\t`tag_id` bigint(20) unsigned default null comment 'TAG标志',\\n\" +\n                    \"\\t`attribute` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '消息的一些属性',\\n\" +\n                    \"\\t`original_msg_ids` varchar(1024) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '原始消息ID，多个id用半角逗号隔开',\\n\" +\n                    \"\\tprimary key (`id`),\\n\" +\n                    \"\\tkey `idx_expiration_date` (`expiration_date`),\\n\" +\n                    \"\\tkey `k_rid_hidd_cid` (`receiver_id`, `hidden`, `cat_id`, `expiration_date`),\\n\" +\n                    \"\\tkey `k_rid_aid_tid` (`receiver_id`, `app_id`, `type_id`, `expiration_date`),\\n\" +\n                    \"\\tkey `k_rid_stat_popup` (`receiver_id`, `status`, `popup`, `expiration_date`),\\n\" +\n                    \"\\tkey `k_tid` (`tag_id`)\\n\" +\n                    \") engine = InnoDB auto_increment = 167279613030 charset = gbk comment '消息实体表'\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest76.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest76 extends MysqlTest {\n    @Test\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `sys_msg_entry_0320` (\\n\" +\n                \"  `provider_dsp_name` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息提供者的显示名，提供给一些需要统一发送名称的系统消息',\\n\" +\n                \"  `template_data` varchar(2048) NOT NULL /*!50616 COLUMN_FORMAT COMPRESSED */ COMMENT '模板渲染时使用的数据,key-value对',\\n\" +\n                \"  `template_merge_data` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '对于需要合并的消息，被合并的参数放在此处理',\\n\" +\n                \"  `expiration_date` datetime NOT NULL COMMENT '失效日期，精度到天,查询和任务处理时使用',\\n\" +\n                \"  `merge_key` varchar(128) DEFAULT NULL COMMENT '消息合并主键，合并成功的消息，不参与计数',\\n\" +\n                \"  `out_id` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '外部关联源的id',\\n\" +\n                \"  `number_expiration_date` datetime DEFAULT NULL COMMENT '计数过期时间',\\n\" +\n                \"  `hidden` int(11) DEFAULT '0' COMMENT '标记是否在吊顶展示，1表示隐藏，0表示展示',\\n\" +\n                \"  `popup` tinyint(3) unsigned DEFAULT '0' COMMENT '表示消息提醒方式:0-数字提醒，1-layer，2-popup',\\n\" +\n                \"  `tag_id` bigint(20) unsigned DEFAULT NULL COMMENT 'TAG标志',\\n\" +\n                \"  `attribute` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息的一些属性',\\n\" +\n                \"  `original_msg_ids` varchar(1024) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '原始消息ID，多个id用半角逗号隔开',\\n\" +\n                \"  PRIMARY KEY (`id`),\\n\" +\n                \"  KEY `idx_expiration_date` (`expiration_date`),\\n\" +\n                \"  KEY `k_rid_hidd_cid` (`receiver_id`,`hidden`,`cat_id`,`expiration_date`),\\n\" +\n                \"  KEY `k_rid_aid_tid` (`receiver_id`,`app_id`,`type_id`,`expiration_date`),\\n\" +\n                \"  KEY `k_rid_stat_popup` (`receiver_id`,`status`,`popup`,`expiration_date`),\\n\" +\n                \"  KEY `k_tid` (`tag_id`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=167279613030 DEFAULT CHARSET=gbk COMMENT='消息实体表'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"sys_msg_entry_0320\", \"provider_dsp_name\");\n        assertNotNull(column);\n        assertEquals(\"varchar\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `sys_msg_entry_0320` (\\n\" +\n                    \"\\t`provider_dsp_name` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息提供者的显示名，提供给一些需要统一发送名称的系统消息',\\n\" +\n                    \"\\t`template_data` varchar(2048) NOT NULL /*!50616 COLUMN_FORMAT COMPRESSED */ COMMENT '模板渲染时使用的数据,key-value对',\\n\" +\n                    \"\\t`template_merge_data` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '对于需要合并的消息，被合并的参数放在此处理',\\n\" +\n                    \"\\t`expiration_date` datetime NOT NULL COMMENT '失效日期，精度到天,查询和任务处理时使用',\\n\" +\n                    \"\\t`merge_key` varchar(128) DEFAULT NULL COMMENT '消息合并主键，合并成功的消息，不参与计数',\\n\" +\n                    \"\\t`out_id` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '外部关联源的id',\\n\" +\n                    \"\\t`number_expiration_date` datetime DEFAULT NULL COMMENT '计数过期时间',\\n\" +\n                    \"\\t`hidden` int(11) DEFAULT '0' COMMENT '标记是否在吊顶展示，1表示隐藏，0表示展示',\\n\" +\n                    \"\\t`popup` tinyint(3) UNSIGNED DEFAULT '0' COMMENT '表示消息提醒方式:0-数字提醒，1-layer，2-popup',\\n\" +\n                    \"\\t`tag_id` bigint(20) UNSIGNED DEFAULT NULL COMMENT 'TAG标志',\\n\" +\n                    \"\\t`attribute` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '消息的一些属性',\\n\" +\n                    \"\\t`original_msg_ids` varchar(1024) /*!50616 COLUMN_FORMAT COMPRESSED */ DEFAULT NULL COMMENT '原始消息ID，多个id用半角逗号隔开',\\n\" +\n                    \"\\tPRIMARY KEY (`id`),\\n\" +\n                    \"\\tKEY `idx_expiration_date` (`expiration_date`),\\n\" +\n                    \"\\tKEY `k_rid_hidd_cid` (`receiver_id`, `hidden`, `cat_id`, `expiration_date`),\\n\" +\n                    \"\\tKEY `k_rid_aid_tid` (`receiver_id`, `app_id`, `type_id`, `expiration_date`),\\n\" +\n                    \"\\tKEY `k_rid_stat_popup` (`receiver_id`, `status`, `popup`, `expiration_date`),\\n\" +\n                    \"\\tKEY `k_tid` (`tag_id`)\\n\" +\n                    \") ENGINE = InnoDB AUTO_INCREMENT = 167279613030 CHARSET = gbk COMMENT '消息实体表'\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `sys_msg_entry_0320` (\\n\" +\n                    \"\\t`provider_dsp_name` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '消息提供者的显示名，提供给一些需要统一发送名称的系统消息',\\n\" +\n                    \"\\t`template_data` varchar(2048) not null /*!50616 COLUMN_FORMAT COMPRESSED */ comment '模板渲染时使用的数据,key-value对',\\n\" +\n                    \"\\t`template_merge_data` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '对于需要合并的消息，被合并的参数放在此处理',\\n\" +\n                    \"\\t`expiration_date` datetime not null comment '失效日期，精度到天,查询和任务处理时使用',\\n\" +\n                    \"\\t`merge_key` varchar(128) default null comment '消息合并主键，合并成功的消息，不参与计数',\\n\" +\n                    \"\\t`out_id` varchar(256) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '外部关联源的id',\\n\" +\n                    \"\\t`number_expiration_date` datetime default null comment '计数过期时间',\\n\" +\n                    \"\\t`hidden` int(11) default '0' comment '标记是否在吊顶展示，1表示隐藏，0表示展示',\\n\" +\n                    \"\\t`popup` tinyint(3) unsigned default '0' comment '表示消息提醒方式:0-数字提醒，1-layer，2-popup',\\n\" +\n                    \"\\t`tag_id` bigint(20) unsigned default null comment 'TAG标志',\\n\" +\n                    \"\\t`attribute` varchar(512) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '消息的一些属性',\\n\" +\n                    \"\\t`original_msg_ids` varchar(1024) /*!50616 COLUMN_FORMAT COMPRESSED */ default null comment '原始消息ID，多个id用半角逗号隔开',\\n\" +\n                    \"\\tprimary key (`id`),\\n\" +\n                    \"\\tkey `idx_expiration_date` (`expiration_date`),\\n\" +\n                    \"\\tkey `k_rid_hidd_cid` (`receiver_id`, `hidden`, `cat_id`, `expiration_date`),\\n\" +\n                    \"\\tkey `k_rid_aid_tid` (`receiver_id`, `app_id`, `type_id`, `expiration_date`),\\n\" +\n                    \"\\tkey `k_rid_stat_popup` (`receiver_id`, `status`, `popup`, `expiration_date`),\\n\" +\n                    \"\\tkey `k_tid` (`tag_id`)\\n\" +\n                    \") engine = InnoDB auto_increment = 167279613030 charset = gbk comment '消息实体表'\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest77.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest77 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"-- table-name-bean-name:some --\\n\" +\n                \"CREATE TABLE `some_table` (\\n\" +\n                \"  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键'\\n\" +\n                \")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"some_table\", \"id\");\n        assertNotNull(column);\n        assertEquals(\"bigint\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"-- table-name-bean-name:some --\\n\" +\n                    \"CREATE TABLE `some_table` (\\n\" +\n                    \"\\t`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键'\\n\" +\n                    \")\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"-- table-name-bean-name:some --\\n\" +\n                    \"create table `some_table` (\\n\" +\n                    \"\\t`id` bigint(20) unsigned not null auto_increment comment '主键'\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest78_json.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest78_json extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE t1 (jdoc JSON);\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"t1\", \"jdoc\");\n        assertNotNull(column);\n        assertEquals(\"JSON\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t1 (\\n\" +\n                    \"\\tjdoc JSON\\n\" +\n                    \")\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t1 (\\n\" +\n                    \"\\tjdoc JSON\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest79_collate.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest79_collate extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE tb_custom_vip_show_message (custom_vip_show_message_seq INT(11) NOT NULL AUTO_INCREMENT,show_channel_type TINYINT(4) NOT NULL COMMENT '通道类型',PRIMARY KEY (custom_vip_show_message_seq))COMMENT='自定VIP显示表' COLLATE='utf8_general_ci' ENGINE=InnoDB;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n        assertNotNull(column);\n        assertEquals(\"INT\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE tb_custom_vip_show_message (\\n\" +\n                    \"\\tcustom_vip_show_message_seq INT(11) NOT NULL AUTO_INCREMENT,\\n\" +\n                    \"\\tshow_channel_type TINYINT(4) NOT NULL COMMENT '通道类型',\\n\" +\n                    \"\\tPRIMARY KEY (custom_vip_show_message_seq)\\n\" +\n                    \") ENGINE = InnoDB COMMENT '自定VIP显示表' COLLATE utf8_general_ci\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table tb_custom_vip_show_message (\\n\" +\n                    \"\\tcustom_vip_show_message_seq INT(11) not null auto_increment,\\n\" +\n                    \"\\tshow_channel_type TINYINT(4) not null comment '通道类型',\\n\" +\n                    \"\\tprimary key (custom_vip_show_message_seq)\\n\" +\n                    \") engine = InnoDB comment '自定VIP显示表' collate utf8_general_ci\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest8.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.stat.TableStat;\nimport com.alibaba.druid.stat.TableStat.Column;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest8 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE TABLE Persons\\n\" +\n                \"(\\n\" +\n                \"Id_P int NOT NULL,\\n\" +\n                \"LastName varchar(255) NOT NULL,\\n\" +\n                \"FirstName varchar(255),\\n\" +\n                \"Address varchar(255),\\n\" +\n                \"City varchar(255),\\n\" +\n                \"CHECK (Id_P>0)\\n\" +\n                \")\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        List<SQLStatement> statementList = parser.parseStatementList();\n        MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0);\n//        print(statementList);\n\n        assertEquals(1, statementList.size());\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(1, visitor.getTables().size());\n        assertEquals(5, visitor.getColumns().size());\n        assertEquals(1, visitor.getConditions().size());\n\n        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"Persons\")));\n\n        assertTrue(visitor.getColumns().contains(new Column(\"Persons\", \"Id_P\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"Persons\", \"LastName\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"Persons\", \"FirstName\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"Persons\", \"Address\")));\n        assertTrue(visitor.getColumns().contains(new Column(\"Persons\", \"City\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest80.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest80 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"create table tb1(select * from tb2)\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n//        assertNotNull(column);\n//        assertEquals(\"INT\", column.getDataType());\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE tb1\\n\" +\n                    \"AS\\n\" +\n                    \"SELECT *\\n\" +\n                    \"FROM tb2\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table tb1\\n\" +\n                    \"as\\n\" +\n                    \"select *\\n\" +\n                    \"from tb2\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest81.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest81 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `admin` (\\n\" +\n                \"  `id` char(20) NOT NULL,\\n\" +\n                \"  `username` varchar(16) NOT NULL COMMENT '用户名',\\n\" +\n                \"  `password` varchar(32) NOT NULL COMMENT '密码',\\n\" +\n                \"  `permission` varchar(255) NOT NULL DEFAULT '' COMMENT '权限',\\n\" +\n                \"  PRIMARY KEY (`id`) USING BTREE\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='管理员';\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n//        assertNotNull(column);\n//        assertEquals(\"INT\", column.getDataType());\n        System.out.println(stmt);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `admin` (\\n\" +\n                    \"\\t`id` char(20) NOT NULL,\\n\" +\n                    \"\\t`username` varchar(16) NOT NULL COMMENT '用户名',\\n\" +\n                    \"\\t`password` varchar(32) NOT NULL COMMENT '密码',\\n\" +\n                    \"\\t`permission` varchar(255) NOT NULL DEFAULT '' COMMENT '权限',\\n\" +\n                    \"\\tPRIMARY KEY USING BTREE (`id`)\\n\" +\n                    \") ENGINE = InnoDB CHARSET = utf8 COMMENT '管理员'\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `admin` (\\n\" +\n                    \"\\t`id` char(20) not null,\\n\" +\n                    \"\\t`username` varchar(16) not null comment '用户名',\\n\" +\n                    \"\\t`password` varchar(32) not null comment '密码',\\n\" +\n                    \"\\t`permission` varchar(255) not null default '' comment '权限',\\n\" +\n                    \"\\tprimary key using BTREE (`id`)\\n\" +\n                    \") engine = InnoDB charset = utf8 comment '管理员'\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest82.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest82 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE t1 (\\n\" +\n                \"  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                \"  dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n//        assertNotNull(column);\n//        assertEquals(\"INT\", column.getDataType());\n        System.out.println(stmt);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t1 (\\n\" +\n                    \"\\tts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\\n\" +\n                    \"\\tdt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\\n\" +\n                    \")\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t1 (\\n\" +\n                    \"\\tts TIMESTAMP default current_timestamp on update current_timestamp,\\n\" +\n                    \"\\tdt DATETIME default current_timestamp on update current_timestamp\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest83.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest83 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE t1 (\\n\" +\n                \"  ts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,     -- default 0\\n\" +\n                \"  ts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL\\n\" +\n                \");\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.KeepComments);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n//        assertNotNull(column);\n//        assertEquals(\"INT\", column.getDataType());\n        System.out.println(stmt);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE t1 (\\n\" +\n                    \"\\tts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- default 0\\n\" +\n                    \"\\tts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL\\n\" +\n                    \")\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table t1 (\\n\" +\n                    \"\\tts1 TIMESTAMP on update current_timestamp, -- default 0\\n\" +\n                    \"\\tts2 TIMESTAMP null on update current_timestamp -- default NULL\\n\" +\n                    \")\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest85.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest85 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"create table `some table $$`(id int auto_increment key, class varchar(10), data binary) engine=MYISAM;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.KeepComments);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n//        assertNotNull(column);\n//        assertEquals(\"INT\", column.getDataType());\n        System.out.println(stmt);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `some table $$` (\\n\" +\n                    \"\\tid int PRIMARY KEY AUTO_INCREMENT,\\n\" +\n                    \"\\tclass varchar(10),\\n\" +\n                    \"\\tdata binary\\n\" +\n                    \") ENGINE = MYISAM\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `some table $$` (\\n\" +\n                    \"\\tid int primary key auto_increment,\\n\" +\n                    \"\\tclass varchar(10),\\n\" +\n                    \"\\tdata binary\\n\" +\n                    \") engine = MYISAM\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest86.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest86 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"create table child_table(id int unsigned auto_increment primary key, id_parent int references parent_table(id) match full on update cascade on delete set null) engine=InnoDB;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.KeepComments);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n//        assertNotNull(column);\n//        assertEquals(\"INT\", column.getDataType());\n        System.out.println(stmt);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE child_table (\\n\" +\n                    \"\\tid int UNSIGNED PRIMARY KEY AUTO_INCREMENT,\\n\" +\n                    \"\\tid_parent int REFERENCES parent_table (id) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE\\n\" +\n                    \") ENGINE = InnoDB\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table child_table (\\n\" +\n                    \"\\tid int unsigned primary key auto_increment,\\n\" +\n                    \"\\tid_parent int references parent_table (id) match full on delete set null on update cascade\\n\" +\n                    \") engine = InnoDB\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest87.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest87 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `test_4` (\\n\" +\n                \"  `id` bigint(20) zerofill   unsigNed NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                \"  `c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                \"  PRIMARY KEY (`id`)\\n\" +\n                \") ENGINE=InnoDB AUTO_INCREMENT=1769531 DEFAULT CHARSET=utf8mb4 COMMENT='10000000'\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.KeepComments);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n//\n//        Column column = visitor.getColumn(\"tb_custom_vip_show_message\", \"custom_vip_show_message_seq\");\n//        assertNotNull(column);\n//        assertEquals(\"INT\", column.getDataType());\n        System.out.println(stmt);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `test_4` (\\n\" +\n                    \"\\t`id` bigint(20) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT COMMENT 'id',\\n\" +\n                    \"\\t`c_tinyint` tinyint(4) DEFAULT '1' COMMENT 'tinyint',\\n\" +\n                    \"\\tPRIMARY KEY (`id`)\\n\" +\n                    \") ENGINE = InnoDB AUTO_INCREMENT = 1769531 CHARSET = utf8mb4 COMMENT '10000000'\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `test_4` (\\n\" +\n                    \"\\t`id` bigint(20) unsigned zerofill not null auto_increment comment 'id',\\n\" +\n                    \"\\t`c_tinyint` tinyint(4) default '1' comment 'tinyint',\\n\" +\n                    \"\\tprimary key (`id`)\\n\" +\n                    \") engine = InnoDB auto_increment = 1769531 charset = utf8mb4 comment '10000000'\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest88.java",
    "content": "/*\n * Copyright 1999-2017 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.createTable;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;\nimport com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;\nimport com.alibaba.druid.sql.parser.SQLParserFeature;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySqlCreateTableTest88 extends MysqlTest {\n    public void test_one() throws Exception {\n        String sql = \"CREATE TABLE `t_share_like_info` (\\n\" +\n                \"  `id` bigint(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                \"  `share_id` bigint(20) NOT NULL,\\n\" +\n                \"  `user_name` bigint(20) NOT NULL,\\n\" +\n                \"  PRIMARY KEY (`id`)\\n\" +\n                \") ENGINE=InnoDB DEFAULT CHARSET=utf8;\";\n\n        MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.KeepComments);\n        SQLStatement stmt = parser.parseCreateTable();\n\n        MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();\n        stmt.accept(visitor);\n\n        visitor.containsTable(\"t_share_like_info\");\n//        System.out.println(\"Tables : \" + visitor.getTables());\n        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        System.out.println(stmt);\n\n        {\n            String output = SQLUtils.toMySqlString(stmt);\n            assertEquals(\"CREATE TABLE `t_share_like_info` (\\n\" +\n                    \"\\t`id` bigint(20) NOT NULL AUTO_INCREMENT,\\n\" +\n                    \"\\t`share_id` bigint(20) NOT NULL,\\n\" +\n                    \"\\t`user_name` bigint(20) NOT NULL,\\n\" +\n                    \"\\tPRIMARY KEY (`id`)\\n\" +\n                    \") ENGINE = InnoDB CHARSET = utf8\", output);\n        }\n\n        {\n            String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);\n            assertEquals(\"create table `t_share_like_info` (\\n\" +\n                    \"\\t`id` bigint(20) not null auto_increment,\\n\" +\n                    \"\\t`share_id` bigint(20) not null,\\n\" +\n                    \"\\t`user_name` bigint(20) not null,\\n\" +\n                    \"\\tprimary key (`id`)\\n\" +\n                    \") engine = InnoDB charset = utf8\", output);\n        }\n    }\n}\n"
  },
  {
    "path": "core/src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_0.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.alibaba.druid.bvt.sql.mysql.create_function;\n\nimport com.alibaba.druid.sql.MysqlTest;\nimport com.alibaba.druid.sql.SQLUtils;\nimport com.alibaba.druid.sql.ast.SQLStatement;\nimport com.alibaba.druid.sql.visitor.SchemaStatVisitor;\nimport com.alibaba.druid.util.JdbcConstants;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class MySql_Create_Function_0 extends MysqlTest {\n    public void test_0() throws Exception {\n        String sql = \"CREATE FUNCTION hello (s CHAR(20))\\n\" +\n                \" RETURNS CHAR(50) DETERMINISTIC\\n\" +\n                \" RETURN CONCAT('Hello, ',s,'!');\";\n\n        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);\n        SQLStatement stmt = statementList.get(0);\n\n        assertEquals(1, statementList.size());\n\n        SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);\n        stmt.accept(visitor);\n\n        assertEquals(\"CREATE FUNCTION hello (\\n\" +\n                        \"\\ts CHAR(20)\\n\" +\n                        \")\\n\" +\n                        \"RETURNS CHAR(50) DETERMINISTIC\\n\" +\n                        \"RETURN CONCAT('Hello, ', s, '!');\", //\n                SQLUtils.toMySqlString(stmt));\n\n        assertEquals(\"create function hello (\\n\" +\n                        \"\\ts CHAR(20)\\n\" +\n                        \")\\n\" +\n                        \"returns CHAR(50) deterministic\\n\" +\n                        \"return CONCAT('Hello, ', s, '!');\", //\n                SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));\n\n//        System.out.println(\"Tables : \" + visitor.getTables());\n//        System.out.println(\"fields : \" + visitor.getColumns());\n//        System.out.println(\"coditions : \" + visitor.getConditions());\n//        System.out.println(\"orderBy : \" + visitor.getOrderByColumns());\n\n        assertEquals(0, visitor.getTables().size());\n        assertEquals(1, visitor.getColumns().size());\n        assertEquals(0, visitor.getConditions().size());\n\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"City\")));\n//        assertTrue(visitor.getTables().containsKey(new TableStat.Name(\"t2\")));\n\n//        assertTrue(visitor.getColumns().contains(new Column(\"t2\", \"id\")));\n    }\n}\n"
  },
  {
    "path": "core/src/test/resources/benchmark/sql/oracle-0.txt",
    "content": ""
  }
]